From e58455ae6ff6ca787af9ae39728b506b068168d6 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 14 Nov 2018 19:31:34 +0000 Subject: [PATCH 001/115] Adds savedata to the Research folder for testing. Fresh account with a single character. --- Research/clean_save/account.dat | 1 + .../clean_save/heroes/58cbabd8758b0055.dat | 1 + Research/clean_save/prefs.dat | 121 ++++++++++++++++++ Research/clean_save/profile.dat | 1 + 4 files changed, 124 insertions(+) create mode 100755 Research/clean_save/account.dat create mode 100755 Research/clean_save/heroes/58cbabd8758b0055.dat create mode 100755 Research/clean_save/prefs.dat create mode 100755 Research/clean_save/profile.dat diff --git a/Research/clean_save/account.dat b/Research/clean_save/account.dat new file mode 100755 index 0000000..390a121 --- /dev/null +++ b/Research/clean_save/account.dat @@ -0,0 +1 @@ +M<PJ>.Jh>6jg/)8=U),]̸KLl]͘IeWřʶUk¶GlIl]NQM]NQMWEQMWE[UWd[UWd[UWd[GWF|FEO{YYRRsssQƾ옙 X̹f3~3~9~9t9t9tޞ9tތ9N3֏+I2pekk8hDkk8hDa`8hDa`8b\aA8b\aA3b\aA3bNaclcD%_cE% \ No newline at end of file diff --git a/Research/clean_save/heroes/58cbabd8758b0055.dat b/Research/clean_save/heroes/58cbabd8758b0055.dat new file mode 100755 index 0000000..6fc05a0 --- /dev/null +++ b/Research/clean_save/heroes/58cbabd8758b0055.dat @@ -0,0 +1 @@ +)<7% Date: Fri, 16 Nov 2018 10:18:18 +0000 Subject: [PATCH 002/115] Implements save manager to handle Save Data. Implements all currencies. Adds subparser for currencies. --- D3Edit.py | 178 ++++++----------------------------- save_manager/__init__.py | 68 +++++++++++++ save_manager/save_handler.py | 103 ++++++++++++++++++++ settings.json | 12 +++ settings.py | 28 ++++++ 5 files changed, 238 insertions(+), 151 deletions(-) create mode 100644 save_manager/__init__.py create mode 100644 save_manager/save_handler.py create mode 100644 settings.json create mode 100644 settings.py diff --git a/D3Edit.py b/D3Edit.py index a5893f7..56fb296 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -1,162 +1,38 @@ #!/usr/bin/env python3 -from json import load -from sys import getsizeof -from struct import pack, unpack +import save_manager from argparse import ArgumentParser -from os.path import isfile, isdir, join -from binascii import hexlify as _hexlify +from settings import CURRENCY_LIST -# pip3 install protobuf -import Hero_pb2 -import Account_pb2 - -BYTE_MAX_VALUE = 255 -XOR_KEY = 0x305F92D82EC9A01B - -GBIDS_FILE = "gbids.json" -SLOTS_FILE = "slots.json" -AFFIXES_FILE = "affixes.json" -CURRENCY_FILE = "currencies.json" - -HERO_DIR = "heroes" -ASSET_DIR = "assets" - -def hexlify(b: (bytes, bytearray)) -> (bytes, bytearray): - """ - bytes -> hex - :param b: the bytes you want to convert to hex - :return: the hex string representation of the specified bytes - """ - return _hexlify(b).decode("utf8") - -def truncate(num: int, boundary: int, signed: bool, endian: str = "little") -> int: - """ - Truncate an int to a given byte boundary - :param num: the number to truncate - :param margin: the byte boundary - :param signed: whether or not the int is signed - :param endian: the integer's endianness - :return: the truncated integer - """ - return int.from_bytes(num.to_bytes(getsizeof(num), endian, signed=signed)[:boundary], endian, signed=signed) - -def decrypt_save(data: (bytes, bytearray)) -> (bytes, bytearray): - """ - Decrypt a save file - :param data: the save data to decrypt - :return: the decrypted save data - """ - global XOR_KEY - - if isinstance(data, bytes): - data = bytearray(data) - - num = XOR_KEY - for i in range(len(data)): - data[i] ^= (num & BYTE_MAX_VALUE) - num = truncate((((num ^ data[i]) << 56) | num >> 8), 8, False) - - return bytes(data) - -def encrypt_save(data: (bytes, bytearray)) -> (bytes, bytearray): - """ - Encrypt a save file - :param data: the save data to encrypt - :return: the encrypted save data - """ - global XOR_KEY - - if isinstance(data, bytes): - data = bytearray(data) - - num1 = XOR_KEY - for i in range(len(data)): - num2 = data[i] - data[i] ^= (num1 & BYTE_MAX_VALUE) - num1 = truncate(((num1 ^ num2) << 56) | num1 >> 8, 8, False) - - return bytes(data) if __name__ == "__main__": # parse arguments parser = ArgumentParser(description="A script to encrypt/decrypt and modify Diablo III saves") parser.add_argument("-i", "--in-file", type=str, required=True, help="The save file you want to work with") - parser.add_argument("-o", "--out-file", type=str, help="The save file you want to output to") - mod_group = parser.add_argument_group("modifications") - mod_group.add_argument("--gold", type=int, help="The amount of gold you want your characters to have") + parser.add_argument("-o", "--out-file", type=str, default='account_modified.dat', help="The save file you want to output to") + modifications_subparser = parser.add_subparsers(title='Modifications') + currency_parser = modifications_subparser.add_parser(name='currency', help="Command to modify currency amounts.") + arg_currencies = {} + for id, currency in CURRENCY_LIST.items(): + curr_currency = currency.lower().replace(' ', '-') + currency_parser.add_argument('--{0}'.format(curr_currency), type=int, + help="Set amount of {0} to the specified amount".format(curr_currency)) args = parser.parse_args() - # make sure the input file exists - assert isfile(args.in_file), "input file doesn't exist" - - # make sure assets exist - assert isfile(join(ASSET_DIR, GBIDS_FILE)), "%s doesn't exist" % (GBIDS_FILE) - assert isfile(join(ASSET_DIR, AFFIXES_FILE)), "%s doesn't exist" % (AFFIXES_FILE) - assert isfile(join(ASSET_DIR, CURRENCY_FILE)), "%s doesn't exist" % (CURRENCY_FILE) - - # load assets - with open(join(ASSET_DIR, GBIDS_FILE), "r") as f: - gbid_list = load(f) - with open(join(ASSET_DIR, AFFIXES_FILE), "r") as f: - affix_list = load(f) - with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: - currency_list = load(f) - with open(join(ASSET_DIR, SLOTS_FILE), "r") as f: - slot_list = load(f) - - # account - # decrypt - with open(args.in_file, "rb") as f: - account_enc = f.read() - account_dec = decrypt_save(account_enc) - - # parse - asd = Account_pb2.SavedDefinition() - asd.ParseFromString(account_dec) - for partition in asd.partitions: - currencies = partition.currency_data.currency - for currency in currencies: - if str(currency.id) in currency_list: - print("%s: %s" % (currency_list[str(currency.id)], currency.count)) - else: - print("Unknown currency ID: %s" % (currency.id)) - # modify account here - if args.gold: - for i in range(len(asd.partitions)): - #for j in range(len(asd.partitions[i].currency_data.currency)): - # asd.partitions[j].currency_data.currency[j].id - if len(asd.partitions[i].currency_data.currency) > 0: - asd.partitions[i].currency_data.currency[0].count = args.gold - print("Set slot %s gold to %s" % (i, args.gold)) - # end account modifications - account_mod_dec = asd.SerializeToString() - account_mod_enc = encrypt_save(account_mod_dec) - # output the modified account - if args.out_file: - with open(args.out_file, "wb") as f: - f.write(account_mod_enc) - # end account output - - # hero ID is in big endian for god knows why (maybe PS3 and Xbox 360 releases?) - last_hero_save = hexlify(pack(">Q", asd.digest.last_played_hero_id.id_low)) - - if isdir(join("saves", "Modded", HERO_DIR)): - last_hero_save_path = join("saves", "Modded", HERO_DIR, last_hero_save + ".dat") - if isfile(last_hero_save_path): - with open(last_hero_save_path, "rb") as f: - hero_enc = f.read() - hero_dec = decrypt_save(hero_enc) - hsd = Hero_pb2.SavedDefinition() - hsd.ParseFromString(hero_dec) - #print(hsd.items.items) - for single in hsd.items.items: - for affix in single.generator.base_affixes: - if str(affix) in affix_list: - print(affix_list[str(affix)]) - else: - print("Unknown Affix: %s" % (affix)) - # modify hero here - hero_mod_dec = hsd.SerializeToString() - hero_mod_enc = encrypt_save(hero_mod_dec) - # output the modified hero \ No newline at end of file + # instance account object + account = save_manager.SaveData(args.in_file, args.out_file) + # modify save file here + account_currencies = account.currency_names + for id, currency in CURRENCY_LIST.items(): + amount = None + curr_currency = currency.lower().replace(' ', '-') + try: + amount = getattr(args, curr_currency) + except AttributeError: + pass + if amount: + account.set_currency(id, amount) + + + # This should be the only write we do, a final commit_all_changes(). + account.commit_all_changes() diff --git a/save_manager/__init__.py b/save_manager/__init__.py new file mode 100644 index 0000000..a0f3781 --- /dev/null +++ b/save_manager/__init__.py @@ -0,0 +1,68 @@ +import Account_pb2 + +from save_manager import save_handler +from settings import CURRENCY_LIST +from struct import pack + + +class SaveData(object): + def __init__(self, account_file, output_file): + self.account_file = account_file + self.output_file = output_file + self.account_file = account_file + # load encrypted save data + self.account_enc = save_handler.load_encrypted_file(self.account_file) + self.account_dec = save_handler.decrypt_save(self.account_enc) + # load saved definition + self.asd = Account_pb2.SavedDefinition() + # parse decrypted save definitions TODO: Should this be done here? + self.asd.ParseFromString(self.account_dec) + # load currency information + self.currency_names = self.load_currencies() + self.last_played_hero_id = save_handler.hexlify(pack(">Q", self.asd.digest.last_played_hero_id.id_low)) + # load last played hero + self.heroes = {} + self.heroes[self.last_played_hero_id] = save_handler.load_hero(self.last_played_hero_id) + + def load_currencies(self): + """ + Loads currencies from the account file. + """ + currency_names = {} + for partition in self.asd.partitions: + currencies = partition.currency_data.currency + for currency in currencies: + currency_id = str(currency.id) + if currency_id in CURRENCY_LIST: + currency_name = CURRENCY_LIST[currency_id] + currency_names[currency_name.lower().replace(' ', '-')] = currency_id + print("Loaded %s: %s" % (currency_name, currency.count)) + else: + print("Unknown currency ID: %s" % currency.id) + return currency_names + + def set_currency(self, currency_id, amount): + """ + + :param currency_id: int() id of the currency to modify + :param amount: int() amount to set the currency to + :return: + """ + currency_id = int(currency_id) + if currency_id in list(self.currency_names.values()): + for i in range(len(self.asd.partitions)): + if len(self.asd.partitions[i].currency_data.currency) > 0: + current_currency = self.asd.partitions[i].currency_data.currency[currency_id] + current_currency.count = amount + print("Set currency {0} to {1}".format(self.currency_names[str(currency_id)], current_currency.count)) + else: + print("Currency not found on the account, this normally means you need to play and collect some currency first.") + + def commit_all_changes(self): + # TODO: perhaps automatically backup account.dat + # serialize and encrypt account file + account_mod_dec = self.asd.SerializeToString() + account_mod_enc = save_handler.encrypt_save(account_mod_dec) + # commit account file to storage only if it changed + if self.output_file and (account_mod_enc != self.account_enc): + save_handler.commit_to_file(account_mod_enc, self.output_file) \ No newline at end of file diff --git a/save_manager/save_handler.py b/save_manager/save_handler.py new file mode 100644 index 0000000..e485550 --- /dev/null +++ b/save_manager/save_handler.py @@ -0,0 +1,103 @@ +import Hero_pb2 +from os.path import isfile, isdir, join +from settings import HERO_DIR, AFFIX_LIST +from sys import getsizeof +from binascii import hexlify as _hexlify + +XOR_KEY = 0x305F92D82EC9A01B +BYTE_MAX_VALUE = 255 + + +def truncate(num: int, boundary: int, signed: bool, endian: str = "little") -> int: + """ + Truncate an int to a given byte boundary + :param num: the number to truncate + :param boundary: the byte boundary + :param signed: whether or not the int is signed + :param endian: the integer's endianness + :return: the truncated integer + """ + return int.from_bytes(num.to_bytes(getsizeof(num), endian, signed=signed)[:boundary], endian, signed=signed) + + +def decrypt_save(data: (bytes, bytearray)) -> (bytes, bytearray): + """ + Decrypt a save file + :param data: the save data to decrypt + :return: the decrypted save data + """ + + global XOR_KEY + + if isinstance(data, bytes): + data = bytearray(data) + + num = XOR_KEY + for i in range(len(data)): + data[i] ^= (num & BYTE_MAX_VALUE) + num = truncate((((num ^ data[i]) << 56) | num >> 8), 8, False) + + return bytes(data) + + +def encrypt_save(data: (bytes, bytearray)) -> (bytes, bytearray): + """ + Encrypt a save file + :param data: the save data to encrypt + :return: the encrypted save data + """ + global XOR_KEY + + if isinstance(data, bytes): + data = bytearray(data) + + num1 = XOR_KEY + for i in range(len(data)): + num2 = data[i] + data[i] ^= (num1 & BYTE_MAX_VALUE) + num1 = truncate(((num1 ^ num2) << 56) | num1 >> 8, 8, False) + + return bytes(data) + + +def hexlify(b: (bytes, bytearray)) -> (bytes, bytearray): + """ + bytes -> hex + :param b: the bytes you want to convert to hex + :return: the hex string representation of the specified bytes + """ + return _hexlify(b).decode("utf8") + + +def load_encrypted_file(encrypted_file): + # TODO: Unify account and hero loading + assert isfile(encrypted_file), "File {} doesn't exit".format(encrypted_file) + with open(encrypted_file, 'rb') as f: + file_enc = f.read() + return file_enc + + +def load_hero(hero_id): + # hero ID is in big endian for god knows why (maybe PS3 and Xbox 360 releases?) + if isdir(join("saves", "Modded", HERO_DIR)): + last_hero_save_path = join("saves", "Modded", HERO_DIR, hero_id + ".dat") + if isfile(last_hero_save_path): + with open(last_hero_save_path, "rb") as f: + hero_enc = f.read() + hero_dec = decrypt_save(hero_enc) + return hero_dec +""" +# print(hsd.items.items) +for single in hsd.items.items: + for affix in single.generator.base_affixes: + if str(affix) in AFFIX_LIST: + print(AFFIX_LIST[str(affix)]) + else: + print("Unknown Affix: %s" % (affix)) +""" + + +def commit_to_file(data, target): + with open(target, "wb") as f: + f.write(data) + return "Changed written to {}".format(target) \ No newline at end of file diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..c5278d6 --- /dev/null +++ b/settings.json @@ -0,0 +1,12 @@ +{ + "directories": { + "HERO_DIR": "heroes", + "ASSET_DIR": "assets" + }, + "files":{ + "GBIDS_FILE": "gbids.json", + "SLOTS_FILE": "slots.json", + "AFFIXES_FILE": "affixes.json", + "CURRENCY_FILE": "currencies.json" + } +} \ No newline at end of file diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..3626a9b --- /dev/null +++ b/settings.py @@ -0,0 +1,28 @@ +from json import load +from os.path import isfile, join + +# load settings +with open('settings.json') as f: + settings = load(f) + +# apply settings +ASSET_DIR = settings['directories']['ASSET_DIR'] +HERO_DIR = settings['directories']['HERO_DIR'] +GBIDS_FILE = settings['files']['GBIDS_FILE'] +AFFIXES_FILE = settings['files']['AFFIXES_FILE'] +CURRENCY_FILE = settings['files']['CURRENCY_FILE'] +SLOTS_FILE = settings['files']['SLOTS_FILE'] + +# make sure assets exist +assert isfile(join(ASSET_DIR, GBIDS_FILE)), "%s doesn't exist" % GBIDS_FILE +assert isfile(join(ASSET_DIR, AFFIXES_FILE)), "%s doesn't exist" % AFFIXES_FILE +assert isfile(join(ASSET_DIR, CURRENCY_FILE)), "%s doesn't exist" % CURRENCY_FILE +# load assets +with open(join(ASSET_DIR, GBIDS_FILE), "r") as f: + GBID_LIST = load(f) +with open(join(ASSET_DIR, AFFIXES_FILE), "r") as f: + AFFIX_LIST = load(f) +with open(join(ASSET_DIR, SLOTS_FILE), "r") as f: + SLOT_LIST = load(f) +with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: + CURRENCY_LIST = load(f) \ No newline at end of file From 2356aaf61b6e8402791fab0be891c1155e967ffc Mon Sep 17 00:00:00 2001 From: unixtreme Date: Sat, 17 Nov 2018 12:54:29 +0000 Subject: [PATCH 003/115] Resolves conflict with upstream. --- D3Edit.py | 43 +++++++++++++++++++++++----------------- assets/currencies.json | 42 +++++++++++++++++++-------------------- save_manager/__init__.py | 9 +++++---- settings.py | 2 +- 4 files changed, 52 insertions(+), 44 deletions(-) diff --git a/D3Edit.py b/D3Edit.py index 56fb296..115c22c 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -2,36 +2,43 @@ import save_manager from argparse import ArgumentParser -from settings import CURRENCY_LIST +from settings import currency_list if __name__ == "__main__": # parse arguments parser = ArgumentParser(description="A script to encrypt/decrypt and modify Diablo III saves") parser.add_argument("-i", "--in-file", type=str, required=True, help="The save file you want to work with") - parser.add_argument("-o", "--out-file", type=str, default='account_modified.dat', help="The save file you want to output to") - modifications_subparser = parser.add_subparsers(title='Modifications') - currency_parser = modifications_subparser.add_parser(name='currency', help="Command to modify currency amounts.") - arg_currencies = {} - for id, currency in CURRENCY_LIST.items(): + parser.add_argument("-o", "--out-file", type=str, default='account_modified.dat', + help="The save file you want to output to") + mod_group = parser.add_argument_group("modifications") + mod_group.add_argument('--all-currencies', type=int, + help="Set all currencies to this amount (overrides other changes)") + # modifications_subparser = parser.add_subparsers(title='Modifications') + # currency_parser = modifications_subparser.add_parser(name='currency', help="Command to modify currency amounts.") + for id, currency in currency_list.items(): curr_currency = currency.lower().replace(' ', '-') - currency_parser.add_argument('--{0}'.format(curr_currency), type=int, - help="Set amount of {0} to the specified amount".format(curr_currency)) + mod_group.add_argument('--{0}'.format(curr_currency), type=int, + help="Set amount of {0} to the specified amount".format(curr_currency)) + # currency_parser.add_argument('--{0}'.format(curr_currency), type=int, args = parser.parse_args() # instance account object account = save_manager.SaveData(args.in_file, args.out_file) # modify save file here - account_currencies = account.currency_names - for id, currency in CURRENCY_LIST.items(): - amount = None - curr_currency = currency.lower().replace(' ', '-') - try: - amount = getattr(args, curr_currency) - except AttributeError: - pass - if amount: - account.set_currency(id, amount) + if args.all_currencies: + for id in currency_list.keys(): + account.set_currency(id, args.all_currencies) + else: + for id, currency in currency_list.items(): + amount = None + curr_currency = currency.lower().replace(' ', '-') + try: + amount = getattr(args, curr_currency) + except AttributeError: + pass + if amount: + account.set_currency(id, amount) # This should be the only write we do, a final commit_all_changes(). diff --git a/assets/currencies.json b/assets/currencies.json index dd546be..1752e30 100644 --- a/assets/currencies.json +++ b/assets/currencies.json @@ -1,21 +1,21 @@ -[ - "Gold", - "Blood Shards", - "Reusable Parts", - "Arcane Dust", - "Veiled Crystals", - "Death's Breath", - "Forgotten Souls", - "Khanduran Runes", - "Caldeum Nightshade", - "Arreat War Tapestries", - "Corrupted Angel Flesh", - "Westmarch Holy Water", - "Hearts of Fright", - "Vials of Putridness", - "Idols of Terror", - "Leoric's Regrets", - "Vengeful Eyes", - "Writhing Spines", - "Devil's Fangs" -] \ No newline at end of file +{ + "0": "Gold", + "1": "Blood Shards", + "3": "Reusable Parts", + "4": "Arcane Dust", + "5": "Veiled Crystal", + "6": "Deaths Breath", + "7": "Forgotten Soul", + "8": "Khanduran Rune", + "9": "Caldeum Nightshade", + "10": "Arreat War Tapestry", + "11": "Corrupted Angel Flesh", + "12": "Westmarch Holy Water", + "13": "Demon Organ Diablo", + "14": "Demon Organ Ghom", + "15": "Demon Organ Siege Breaker", + "16": "Demon Organ Skeleton King", + "17": "Demon Organ Eye", + "18": "Demon Organ Spine Cord", + "19": "Demon Organ Tooth" +} \ No newline at end of file diff --git a/save_manager/__init__.py b/save_manager/__init__.py index a0f3781..0840d61 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -1,7 +1,7 @@ import Account_pb2 from save_manager import save_handler -from settings import CURRENCY_LIST +from settings import currency_list from struct import pack @@ -33,8 +33,8 @@ def load_currencies(self): currencies = partition.currency_data.currency for currency in currencies: currency_id = str(currency.id) - if currency_id in CURRENCY_LIST: - currency_name = CURRENCY_LIST[currency_id] + if currency_id in currency_list: + currency_name = currency_list[currency_id] currency_names[currency_name.lower().replace(' ', '-')] = currency_id print("Loaded %s: %s" % (currency_name, currency.count)) else: @@ -56,7 +56,8 @@ def set_currency(self, currency_id, amount): current_currency.count = amount print("Set currency {0} to {1}".format(self.currency_names[str(currency_id)], current_currency.count)) else: - print("Currency not found on the account, this normally means you need to play and collect some currency first.") + print("Currency {0} found on the account, this normally means you need to play and collect some currency " + "first.".format(currency_id)) def commit_all_changes(self): # TODO: perhaps automatically backup account.dat diff --git a/settings.py b/settings.py index 3626a9b..a0f16bd 100644 --- a/settings.py +++ b/settings.py @@ -25,4 +25,4 @@ with open(join(ASSET_DIR, SLOTS_FILE), "r") as f: SLOT_LIST = load(f) with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: - CURRENCY_LIST = load(f) \ No newline at end of file + currency_list = load(f) \ No newline at end of file From 78b9aac82d0ac66d1858120cf09d906ef5d59a3e Mon Sep 17 00:00:00 2001 From: unixtreme Date: Sat, 17 Nov 2018 10:08:04 +0000 Subject: [PATCH 004/115] Adds basic framework for GUI feature and GUI branch. --- D3Edit.py | 9 ++++ gui/__init__.py | 93 ++++++++++++++++++++++++++++++++++++ gui/account_frame.py | 82 +++++++++++++++++++++++++++++++ requirements.txt | 2 + save_manager/__init__.py | 2 +- save_manager/save_handler.py | 2 +- 6 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 gui/__init__.py create mode 100644 gui/account_frame.py create mode 100644 requirements.txt diff --git a/D3Edit.py b/D3Edit.py index 115c22c..f77824f 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +import gui import save_manager +import sys from argparse import ArgumentParser from settings import currency_list @@ -11,6 +13,7 @@ parser.add_argument("-i", "--in-file", type=str, required=True, help="The save file you want to work with") parser.add_argument("-o", "--out-file", type=str, default='account_modified.dat', help="The save file you want to output to") + parser.add_argument("-g", "--gui", default=False, action='store_true', help="Launch GUI instead of CLI") mod_group = parser.add_argument_group("modifications") mod_group.add_argument('--all-currencies', type=int, help="Set all currencies to this amount (overrides other changes)") @@ -23,6 +26,12 @@ # currency_parser.add_argument('--{0}'.format(curr_currency), type=int, args = parser.parse_args() + # TESTING GUI + if args.gui: + gui.start() + sys.exit(0) + else: + assert args.in_file, "Must specify a file when running in CLI mode." # instance account object account = save_manager.SaveData(args.in_file, args.out_file) # modify save file here diff --git a/gui/__init__.py b/gui/__init__.py new file mode 100644 index 0000000..b3894d7 --- /dev/null +++ b/gui/__init__.py @@ -0,0 +1,93 @@ +import wx +import save_manager +from gui import account_frame + +def start(): + # When this module is run (not imported) then create the app, the + # frame, show it, and start the event loop. + app = wx.App() + frm = Welcome(None, title='D3Edit') + frm.Show() + app.MainLoop() + + +class Welcome(wx.Frame): + def __init__(self, *args, **kwargs): + # ensure the parent's __init__ is called + super(Welcome, self).__init__(*args, **kwargs) + # create a panel in the frame + pnl = wx.Panel(self) + window_size = wx.Size(800, 600) + self.SetInitialSize(size=window_size) + + # and put some text with a larger bold font on it + st = wx.StaticText(pnl, label="Import an account.dat file to get started!", pos=(25,25)) + font = st.GetFont() + font.PointSize += 10 + font = font.Bold() + st.SetFont(font) + + # create a menu bar + self.makeMenuBar() + + # and a status bar + self.CreateStatusBar() + self.SetStatusText("Import an account.dat file to get started!") + + def makeMenuBar(self): + """ + A menu bar is composed of menus, which are composed of menu items. + This method builds a set of menus and binds handlers to be called + when the menu item is selected. + """ + + # Make a file menu with Hello and Exit items + fileMenu = wx.Menu() + # The "\t..." syntax defines an accelerator key that also triggers + # the same event + openitem = fileMenu.Append(-1, "&Open\tCtrl-O", + "Select account.dat file to import") + fileMenu.AppendSeparator() + # When using a stock ID we don't need to specify the menu item's + # label + exititem = fileMenu.Append(wx.ID_EXIT) + + # Make the menu bar and add the two menus to it. The '&' defines + # that the next letter is the "mnemonic" for the menu item. On the + # platforms that support it those letters are underlined and can be + # triggered from the keyboard. + menuBar = wx.MenuBar() + menuBar.Append(fileMenu, "&File") + + # Give the menu bar to the frame + self.SetMenuBar(menuBar) + + # Finally, associate a handler function with the EVT_MENU event for + # each of the menu items. That means that when that menu item is + # activated then the associated handler function will be called. + self.Bind(wx.EVT_MENU, self.onopen, openitem) + self.Bind(wx.EVT_MENU, self.OnExit, exititem) + + + def OnExit(self, event): + """Close the frame, terminating the application.""" + self.Close(True) + + def doondatfile(self, file): + self.account = save_manager.SaveData(file) + account_frame.Account() + + + def onopen(self, event): + with wx.FileDialog(self, "Open .dat file", wildcard=".dat files (*.dat)|*.dat", + style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: + + if fileDialog.ShowModal() == wx.ID_CANCEL: + return # the user changed their mind + + # Proceed loading the file chosen by the user + pathname = fileDialog.GetPath() + try: + self.doondatfile(pathname) + except IOError: + wx.LogError("Cannot open file '%s'." % pathname) \ No newline at end of file diff --git a/gui/account_frame.py b/gui/account_frame.py new file mode 100644 index 0000000..e46ef17 --- /dev/null +++ b/gui/account_frame.py @@ -0,0 +1,82 @@ +import wx + + +class Account(wx.Frame): + def __init__(self, *args, **kwargs): + super(Account, self).__init__(*args, **kwargs) + # create a panel in the frame + pnl = wx.Panel(self) + window_size = wx.Size(800, 600) + self.SetInitialSize(size=window_size) + + # and put some text with a larger bold font on it + st = wx.StaticText(pnl, label="started!", pos=(25,25)) + font = st.GetFont() + font.PointSize += 10 + font = font.Bold() + st.SetFont(font) + + # create a menu bar + self.makeMenuBar() + + # and a status bar + self.CreateStatusBar() + self.SetStatusText("Import an account.dat file to get started!") + + # define default content status + self.accountnotsaved = False + + def makeMenuBar(self): + """ + A menu bar is composed of menus, which are composed of menu items. + This method builds a set of menus and binds handlers to be called + when the menu item is selected. + """ + + # Make a file menu with Hello and Exit items + fileMenu = wx.Menu() + # The "\t..." syntax defines an accelerator key that also triggers + # the same event + openitem = fileMenu.Append(-1, "&Save\tCtrl-S", + "Save account.dat") + fileMenu.AppendSeparator() + # When using a stock ID we don't need to specify the menu item's + # label + exititem = fileMenu.Append(wx.ID_EXIT) + + # Make the menu bar and add the two menus to it. The '&' defines + # that the next letter is the "mnemonic" for the menu item. On the + # platforms that support it those letters are underlined and can be + # triggered from the keyboard. + menuBar = wx.MenuBar() + menuBar.Append(fileMenu, "&File") + + # Give the menu bar to the frame + self.SetMenuBar(menuBar) + + # Finally, associate a handler function with the EVT_MENU event for + # each of the menu items. That means that when that menu item is + # activated then the associated handler function will be called. + self.Bind(wx.EVT_MENU, self.onsave, openitem) + self.Bind(wx.EVT_MENU, self.OnExit, exititem) + + def onsave(self, event): + + if self.accountnotsaved: + if wx.MessageBox("Current content has not been saved! Proceed?", "Please confirm", + wx.ICON_QUESTION | wx.YES_NO, self) == wx.NO: + return + + # otherwise ask the user what new file to open + with wx.FileDialog(self, "Open .dat file", wildcard=".dat files (*.dat)|*.dat", + style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: + + if fileDialog.ShowModal() == wx.ID_CANCEL: + return # the user changed their mind + + # Proceed loading the file chosen by the user + pathname = fileDialog.GetPath() + try: + self.doondatfile(pathname) + except IOError: + wx.LogError("Cannot open file '%s'." % pathname) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fd986d9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +wxpython +protobuf diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 0840d61..ef4cc73 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -6,7 +6,7 @@ class SaveData(object): - def __init__(self, account_file, output_file): + def __init__(self, account_file, output_file=None): self.account_file = account_file self.output_file = output_file self.account_file = account_file diff --git a/save_manager/save_handler.py b/save_manager/save_handler.py index e485550..7d79f0d 100644 --- a/save_manager/save_handler.py +++ b/save_manager/save_handler.py @@ -71,7 +71,7 @@ def hexlify(b: (bytes, bytearray)) -> (bytes, bytearray): def load_encrypted_file(encrypted_file): # TODO: Unify account and hero loading - assert isfile(encrypted_file), "File {} doesn't exit".format(encrypted_file) + assert isfile(encrypted_file), "File {} doesn't exist".format(encrypted_file) with open(encrypted_file, 'rb') as f: file_enc = f.read() return file_enc From a51a2096c9119416063ceac8f256c9afbd04e5c4 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Sun, 18 Nov 2018 19:04:47 +0000 Subject: [PATCH 005/115] Resolves bug with hero importing. --- D3Edit.py | 3 +-- save_manager/__init__.py | 22 +++++++++++++++++----- save_manager/save_handler.py | 1 - 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/D3Edit.py b/D3Edit.py index f77824f..c0daed6 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -10,7 +10,7 @@ if __name__ == "__main__": # parse arguments parser = ArgumentParser(description="A script to encrypt/decrypt and modify Diablo III saves") - parser.add_argument("-i", "--in-file", type=str, required=True, help="The save file you want to work with") + parser.add_argument("-i", "--in-file", type=str, required=False, help="The save file you want to work with") parser.add_argument("-o", "--out-file", type=str, default='account_modified.dat', help="The save file you want to output to") parser.add_argument("-g", "--gui", default=False, action='store_true', help="Launch GUI instead of CLI") @@ -49,6 +49,5 @@ if amount: account.set_currency(id, amount) - # This should be the only write we do, a final commit_all_changes(). account.commit_all_changes() diff --git a/save_manager/__init__.py b/save_manager/__init__.py index ef4cc73..caa9ce3 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -1,5 +1,8 @@ import Account_pb2 +import Hero_pb2 +import glob +from os.path import dirname, basename from save_manager import save_handler from settings import currency_list from struct import pack @@ -8,6 +11,8 @@ class SaveData(object): def __init__(self, account_file, output_file=None): self.account_file = account_file + self.save_folder = dirname(self.account_file) + self.hero_files = glob.glob('{}/heroes/*.dat'.format(self.save_folder)) self.output_file = output_file self.account_file = account_file # load encrypted save data @@ -22,7 +27,13 @@ def __init__(self, account_file, output_file=None): self.last_played_hero_id = save_handler.hexlify(pack(">Q", self.asd.digest.last_played_hero_id.id_low)) # load last played hero self.heroes = {} - self.heroes[self.last_played_hero_id] = save_handler.load_hero(self.last_played_hero_id) + self.hsd = Hero_pb2.SavedDefinition() + for hero_path in self.hero_files: + hero_id = basename(hero_path) + if self.last_played_hero_id in hero_id: + enc_hero = save_handler.load_encrypted_file(hero_path) + dec_hero = save_handler.decrypt_save(enc_hero) + self.heroes[hero_id] = self.hsd.ParseFromString(dec_hero) def load_currencies(self): """ @@ -36,7 +47,7 @@ def load_currencies(self): if currency_id in currency_list: currency_name = currency_list[currency_id] currency_names[currency_name.lower().replace(' ', '-')] = currency_id - print("Loaded %s: %s" % (currency_name, currency.count)) + # print("Loaded %s: %s" % (currency_name, currency.count)) else: print("Unknown currency ID: %s" % currency.id) return currency_names @@ -49,14 +60,15 @@ def set_currency(self, currency_id, amount): :return: """ currency_id = int(currency_id) - if currency_id in list(self.currency_names.values()): + if str(currency_id) in list(self.currency_names.values()): for i in range(len(self.asd.partitions)): if len(self.asd.partitions[i].currency_data.currency) > 0: current_currency = self.asd.partitions[i].currency_data.currency[currency_id] current_currency.count = amount - print("Set currency {0} to {1}".format(self.currency_names[str(currency_id)], current_currency.count)) + print("Set currency {0} to {1}".format( + currency_list[str(currency_id)], current_currency.count, currency_id)) else: - print("Currency {0} found on the account, this normally means you need to play and collect some currency " + print("Currency {0} not found on the account, this normally means you need to play and collect some currency " "first.".format(currency_id)) def commit_all_changes(self): diff --git a/save_manager/save_handler.py b/save_manager/save_handler.py index 7d79f0d..eb9b1eb 100644 --- a/save_manager/save_handler.py +++ b/save_manager/save_handler.py @@ -78,7 +78,6 @@ def load_encrypted_file(encrypted_file): def load_hero(hero_id): - # hero ID is in big endian for god knows why (maybe PS3 and Xbox 360 releases?) if isdir(join("saves", "Modded", HERO_DIR)): last_hero_save_path = join("saves", "Modded", HERO_DIR, hero_id + ".dat") if isfile(last_hero_save_path): From 65b1748d8711ca02e244d806a84e48a3a665204f Mon Sep 17 00:00:00 2001 From: unixtreme Date: Sun, 18 Nov 2018 19:07:32 +0000 Subject: [PATCH 006/115] Resolves bug with hero importing. --- save_manager/__init__.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 0840d61..caa9ce3 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -1,13 +1,18 @@ import Account_pb2 +import Hero_pb2 +import glob +from os.path import dirname, basename from save_manager import save_handler from settings import currency_list from struct import pack class SaveData(object): - def __init__(self, account_file, output_file): + def __init__(self, account_file, output_file=None): self.account_file = account_file + self.save_folder = dirname(self.account_file) + self.hero_files = glob.glob('{}/heroes/*.dat'.format(self.save_folder)) self.output_file = output_file self.account_file = account_file # load encrypted save data @@ -22,7 +27,13 @@ def __init__(self, account_file, output_file): self.last_played_hero_id = save_handler.hexlify(pack(">Q", self.asd.digest.last_played_hero_id.id_low)) # load last played hero self.heroes = {} - self.heroes[self.last_played_hero_id] = save_handler.load_hero(self.last_played_hero_id) + self.hsd = Hero_pb2.SavedDefinition() + for hero_path in self.hero_files: + hero_id = basename(hero_path) + if self.last_played_hero_id in hero_id: + enc_hero = save_handler.load_encrypted_file(hero_path) + dec_hero = save_handler.decrypt_save(enc_hero) + self.heroes[hero_id] = self.hsd.ParseFromString(dec_hero) def load_currencies(self): """ @@ -36,7 +47,7 @@ def load_currencies(self): if currency_id in currency_list: currency_name = currency_list[currency_id] currency_names[currency_name.lower().replace(' ', '-')] = currency_id - print("Loaded %s: %s" % (currency_name, currency.count)) + # print("Loaded %s: %s" % (currency_name, currency.count)) else: print("Unknown currency ID: %s" % currency.id) return currency_names @@ -49,14 +60,15 @@ def set_currency(self, currency_id, amount): :return: """ currency_id = int(currency_id) - if currency_id in list(self.currency_names.values()): + if str(currency_id) in list(self.currency_names.values()): for i in range(len(self.asd.partitions)): if len(self.asd.partitions[i].currency_data.currency) > 0: current_currency = self.asd.partitions[i].currency_data.currency[currency_id] current_currency.count = amount - print("Set currency {0} to {1}".format(self.currency_names[str(currency_id)], current_currency.count)) + print("Set currency {0} to {1}".format( + currency_list[str(currency_id)], current_currency.count, currency_id)) else: - print("Currency {0} found on the account, this normally means you need to play and collect some currency " + print("Currency {0} not found on the account, this normally means you need to play and collect some currency " "first.".format(currency_id)) def commit_all_changes(self): From 1cbe7082ed6eb77ad43f2d8c32155e94238e853f Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 19 Nov 2018 13:03:42 +0000 Subject: [PATCH 007/115] Initial GUI commit. Loads currency information and displays it on basic view. --- D3Edit.py | 19 +++-- gui/__init__.py | 162 +++++++++++++++++---------------------- save_manager/__init__.py | 5 ++ 3 files changed, 85 insertions(+), 101 deletions(-) diff --git a/D3Edit.py b/D3Edit.py index c0daed6..404ad2c 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 -import gui import save_manager -import sys +import gui from argparse import ArgumentParser from settings import currency_list @@ -10,10 +9,10 @@ if __name__ == "__main__": # parse arguments parser = ArgumentParser(description="A script to encrypt/decrypt and modify Diablo III saves") - parser.add_argument("-i", "--in-file", type=str, required=False, help="The save file you want to work with") + parser.add_argument("-i", "--in-file", type=str, help="The save file you want to work with") parser.add_argument("-o", "--out-file", type=str, default='account_modified.dat', help="The save file you want to output to") - parser.add_argument("-g", "--gui", default=False, action='store_true', help="Launch GUI instead of CLI") + parser.add_argument("-c", "--cli", action='store_true', default=False, help="Run in CLI mode instead of GUI.") mod_group = parser.add_argument_group("modifications") mod_group.add_argument('--all-currencies', type=int, help="Set all currencies to this amount (overrides other changes)") @@ -26,12 +25,11 @@ # currency_parser.add_argument('--{0}'.format(curr_currency), type=int, args = parser.parse_args() - # TESTING GUI - if args.gui: - gui.start() - sys.exit(0) - else: - assert args.in_file, "Must specify a file when running in CLI mode." + # Initialize GUI + if not args.cli: + instanced_gui = gui.D3Edit() + instanced_gui.start() + # instance account object account = save_manager.SaveData(args.in_file, args.out_file) # modify save file here @@ -49,5 +47,6 @@ if amount: account.set_currency(id, amount) + # This should be the only write we do, a final commit_all_changes(). account.commit_all_changes() diff --git a/gui/__init__.py b/gui/__init__.py index b3894d7..dd6bf6f 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -1,93 +1,73 @@ -import wx import save_manager -from gui import account_frame - -def start(): - # When this module is run (not imported) then create the app, the - # frame, show it, and start the event loop. - app = wx.App() - frm = Welcome(None, title='D3Edit') - frm.Show() - app.MainLoop() - - -class Welcome(wx.Frame): - def __init__(self, *args, **kwargs): - # ensure the parent's __init__ is called - super(Welcome, self).__init__(*args, **kwargs) - # create a panel in the frame - pnl = wx.Panel(self) - window_size = wx.Size(800, 600) - self.SetInitialSize(size=window_size) - - # and put some text with a larger bold font on it - st = wx.StaticText(pnl, label="Import an account.dat file to get started!", pos=(25,25)) - font = st.GetFont() - font.PointSize += 10 - font = font.Bold() - st.SetFont(font) - - # create a menu bar - self.makeMenuBar() - - # and a status bar - self.CreateStatusBar() - self.SetStatusText("Import an account.dat file to get started!") - - def makeMenuBar(self): - """ - A menu bar is composed of menus, which are composed of menu items. - This method builds a set of menus and binds handlers to be called - when the menu item is selected. - """ - - # Make a file menu with Hello and Exit items - fileMenu = wx.Menu() - # The "\t..." syntax defines an accelerator key that also triggers - # the same event - openitem = fileMenu.Append(-1, "&Open\tCtrl-O", - "Select account.dat file to import") - fileMenu.AppendSeparator() - # When using a stock ID we don't need to specify the menu item's - # label - exititem = fileMenu.Append(wx.ID_EXIT) - - # Make the menu bar and add the two menus to it. The '&' defines - # that the next letter is the "mnemonic" for the menu item. On the - # platforms that support it those letters are underlined and can be - # triggered from the keyboard. - menuBar = wx.MenuBar() - menuBar.Append(fileMenu, "&File") - - # Give the menu bar to the frame - self.SetMenuBar(menuBar) - - # Finally, associate a handler function with the EVT_MENU event for - # each of the menu items. That means that when that menu item is - # activated then the associated handler function will be called. - self.Bind(wx.EVT_MENU, self.onopen, openitem) - self.Bind(wx.EVT_MENU, self.OnExit, exititem) - - - def OnExit(self, event): - """Close the frame, terminating the application.""" - self.Close(True) - - def doondatfile(self, file): +import sys +import tkinter as tk +from settings import currency_list +from tkinter import filedialog +from tkinter import ttk + + +class D3Edit(object): + def __init__(self): + self.current_file = None + self.main_window = tk.Tk() + self.main_window.title("D3Edit") + self.drawn_elements = [] + self.draw_first_view() + + def draw_first_view(self): + self.first_label = ttk.Label(self.main_window, text="Account not loaded, please load an account file to begin.") + self.first_label.grid(column=0, row=0) + self.drawn_elements.append(self.first_label) + self.open_button = ttk.Button(self.main_window, text="Open File", command=self.openfile) + self.open_button.grid(column=0, row=1) + self.drawn_elements.append(self.open_button) + + def destroy_loaded_view(self): + while len(self.drawn_elements): + item = self.drawn_elements.pop() + item.destroy() + + def openfile(self): + selected_file = filedialog.askopenfilename(initialdir=".", title="Select account.dat file") + if selected_file: + if self.current_file: + self.previous_file = self.current_file + self.current_file = selected_file + self.first_label.configure(text=self.current_file) + self.loadaccount(self.current_file) + + def loadaccount(self, file): self.account = save_manager.SaveData(file) - account_frame.Account() - - - def onopen(self, event): - with wx.FileDialog(self, "Open .dat file", wildcard=".dat files (*.dat)|*.dat", - style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: - - if fileDialog.ShowModal() == wx.ID_CANCEL: - return # the user changed their mind - - # Proceed loading the file chosen by the user - pathname = fileDialog.GetPath() - try: - self.doondatfile(pathname) - except IOError: - wx.LogError("Cannot open file '%s'." % pathname) \ No newline at end of file + self.destroy_loaded_view() + self.draw_account_view() + + def draw_account_view(self): + self.account_header = ttk.Label(text=self.current_file).grid(column=0, row=0) + self.drawn_elements.append(self.account_header) + self.currency_button = ttk.Button(self.main_window, text="Currencies").grid(column=0, row=1) + self.drawn_elements.append(self.currency_button) + self.sccurrencies = self.account.asd.partitions[0].currency_data.currency + self.currtitles = {} + self.currvalues = {} + self.currvalentry = {} + startcol = 0 + startrow = 2 + print(currency_list) + for currency in self.sccurrencies: + currid = str(currency.id) + self.currvalues[currid] = tk.StringVar(value=currency.count) + self.currtitles[currid] = ttk.Label(self.main_window, text=currency_list[currid])\ + .grid(column=startcol, row=startrow, sticky='W') + self.currvalentry[currid] = ttk.Entry( + self.main_window, textvariable=self.currvalues[currid])\ + .grid(column=(startcol + 1), row=startrow, sticky='W') + startrow = startrow + 1 + self.drawn_elements.append(self.currtitles) + self.drawn_elements.append(self.currvalentry) + + def start(self): + self.main_window.mainloop() + self.stop_gui() + + def stop_gui(self): + sys.exit(0) diff --git a/save_manager/__init__.py b/save_manager/__init__.py index caa9ce3..7df442a 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -34,6 +34,11 @@ def __init__(self, account_file, output_file=None): enc_hero = save_handler.load_encrypted_file(hero_path) dec_hero = save_handler.decrypt_save(enc_hero) self.heroes[hero_id] = self.hsd.ParseFromString(dec_hero) + else: + self.heroes[hero_id] = Hero_pb2.SavedDefinition() + enc_hero = save_handler.load_encrypted_file(hero_path) + dec_hero = save_handler.decrypt_save(enc_hero) + self.heroes[hero_id].ParseFromString(dec_hero) def load_currencies(self): """ From 29098381ebe78cc76dbbf1360b7900c0f9ff9ca2 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 19 Nov 2018 15:33:47 +0000 Subject: [PATCH 008/115] Implements basic GUI for materials. Loosely tested. --- gui/__init__.py | 48 +++++++++++------------ gui/account_frame.py | 82 ---------------------------------------- save_manager/__init__.py | 4 +- 3 files changed, 27 insertions(+), 107 deletions(-) delete mode 100644 gui/account_frame.py diff --git a/gui/__init__.py b/gui/__init__.py index dd6bf6f..76ca803 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -11,21 +11,20 @@ def __init__(self): self.current_file = None self.main_window = tk.Tk() self.main_window.title("D3Edit") - self.drawn_elements = [] - self.draw_first_view() + self.draw_welcome() - def draw_first_view(self): - self.first_label = ttk.Label(self.main_window, text="Account not loaded, please load an account file to begin.") + def draw_welcome(self, message=None): + if not message: + message = "Account not loaded, please load an account file to begin." + self.first_label = ttk.Label(self.main_window, text=message) self.first_label.grid(column=0, row=0) - self.drawn_elements.append(self.first_label) self.open_button = ttk.Button(self.main_window, text="Open File", command=self.openfile) self.open_button.grid(column=0, row=1) - self.drawn_elements.append(self.open_button) def destroy_loaded_view(self): - while len(self.drawn_elements): - item = self.drawn_elements.pop() - item.destroy() + self.main_window.destroy() + self.main_window = tk.Tk() + self.main_window.title("D3Edit") def openfile(self): selected_file = filedialog.askopenfilename(initialdir=".", title="Select account.dat file") @@ -38,32 +37,33 @@ def openfile(self): def loadaccount(self, file): self.account = save_manager.SaveData(file) + self.account.output_file = file self.destroy_loaded_view() self.draw_account_view() + def savecurrencies(self): + for currency in self.account.asd.partitions[0].currency_data.currency: + amount = getattr(self.scvalues[str(currency.id)], 'get') + currency.count = int(amount()) + self.account.commit_all_changes() + self.destroy_loaded_view() + self.draw_welcome("Account data saved.") + def draw_account_view(self): self.account_header = ttk.Label(text=self.current_file).grid(column=0, row=0) - self.drawn_elements.append(self.account_header) - self.currency_button = ttk.Button(self.main_window, text="Currencies").grid(column=0, row=1) - self.drawn_elements.append(self.currency_button) + self.currency_button = ttk.Button(self.main_window, text="Save Softcore Currencies", + command=self.savecurrencies).grid(column=0, row=1) self.sccurrencies = self.account.asd.partitions[0].currency_data.currency - self.currtitles = {} - self.currvalues = {} - self.currvalentry = {} + self.scvalues = {} startcol = 0 startrow = 2 - print(currency_list) for currency in self.sccurrencies: currid = str(currency.id) - self.currvalues[currid] = tk.StringVar(value=currency.count) - self.currtitles[currid] = ttk.Label(self.main_window, text=currency_list[currid])\ - .grid(column=startcol, row=startrow, sticky='W') - self.currvalentry[currid] = ttk.Entry( - self.main_window, textvariable=self.currvalues[currid])\ - .grid(column=(startcol + 1), row=startrow, sticky='W') + self.scvalues[currid] = tk.StringVar(value=currency.count) + ttk.Label(self.main_window, text=currency_list[currid]).grid(column=startcol, row=startrow, sticky='W') + ttk.Entry(self.main_window, textvariable=self.scvalues[currid])\ + .grid(column=startcol, row=startrow, sticky='E') startrow = startrow + 1 - self.drawn_elements.append(self.currtitles) - self.drawn_elements.append(self.currvalentry) def start(self): self.main_window.mainloop() diff --git a/gui/account_frame.py b/gui/account_frame.py deleted file mode 100644 index e46ef17..0000000 --- a/gui/account_frame.py +++ /dev/null @@ -1,82 +0,0 @@ -import wx - - -class Account(wx.Frame): - def __init__(self, *args, **kwargs): - super(Account, self).__init__(*args, **kwargs) - # create a panel in the frame - pnl = wx.Panel(self) - window_size = wx.Size(800, 600) - self.SetInitialSize(size=window_size) - - # and put some text with a larger bold font on it - st = wx.StaticText(pnl, label="started!", pos=(25,25)) - font = st.GetFont() - font.PointSize += 10 - font = font.Bold() - st.SetFont(font) - - # create a menu bar - self.makeMenuBar() - - # and a status bar - self.CreateStatusBar() - self.SetStatusText("Import an account.dat file to get started!") - - # define default content status - self.accountnotsaved = False - - def makeMenuBar(self): - """ - A menu bar is composed of menus, which are composed of menu items. - This method builds a set of menus and binds handlers to be called - when the menu item is selected. - """ - - # Make a file menu with Hello and Exit items - fileMenu = wx.Menu() - # The "\t..." syntax defines an accelerator key that also triggers - # the same event - openitem = fileMenu.Append(-1, "&Save\tCtrl-S", - "Save account.dat") - fileMenu.AppendSeparator() - # When using a stock ID we don't need to specify the menu item's - # label - exititem = fileMenu.Append(wx.ID_EXIT) - - # Make the menu bar and add the two menus to it. The '&' defines - # that the next letter is the "mnemonic" for the menu item. On the - # platforms that support it those letters are underlined and can be - # triggered from the keyboard. - menuBar = wx.MenuBar() - menuBar.Append(fileMenu, "&File") - - # Give the menu bar to the frame - self.SetMenuBar(menuBar) - - # Finally, associate a handler function with the EVT_MENU event for - # each of the menu items. That means that when that menu item is - # activated then the associated handler function will be called. - self.Bind(wx.EVT_MENU, self.onsave, openitem) - self.Bind(wx.EVT_MENU, self.OnExit, exititem) - - def onsave(self, event): - - if self.accountnotsaved: - if wx.MessageBox("Current content has not been saved! Proceed?", "Please confirm", - wx.ICON_QUESTION | wx.YES_NO, self) == wx.NO: - return - - # otherwise ask the user what new file to open - with wx.FileDialog(self, "Open .dat file", wildcard=".dat files (*.dat)|*.dat", - style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: - - if fileDialog.ShowModal() == wx.ID_CANCEL: - return # the user changed their mind - - # Proceed loading the file chosen by the user - pathname = fileDialog.GetPath() - try: - self.doondatfile(pathname) - except IOError: - wx.LogError("Cannot open file '%s'." % pathname) \ No newline at end of file diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 7df442a..51b59bb 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -76,9 +76,11 @@ def set_currency(self, currency_id, amount): print("Currency {0} not found on the account, this normally means you need to play and collect some currency " "first.".format(currency_id)) - def commit_all_changes(self): + def commit_all_changes(self, target_file=None): # TODO: perhaps automatically backup account.dat # serialize and encrypt account file + if target_file: + self.output_file = target_file account_mod_dec = self.asd.SerializeToString() account_mod_enc = save_handler.encrypt_save(account_mod_dec) # commit account file to storage only if it changed From f0eb60216c38363e1daf9b273d5e5fb0a886d47a Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 19 Nov 2018 15:43:52 +0000 Subject: [PATCH 009/115] Adds error message if protobuf is missing. --- gui/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gui/__init__.py b/gui/__init__.py index 76ca803..0e0b1ee 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -8,10 +8,16 @@ class D3Edit(object): def __init__(self): + message = None self.current_file = None self.main_window = tk.Tk() self.main_window.title("D3Edit") - self.draw_welcome() + try: + from google import protobuf + del protobuf + except: + message = "Could not import protobuff, please install the protobuf python package." + self.draw_welcome(message) def draw_welcome(self, message=None): if not message: From 0a72a181f8b57338cacd547229df2d4cf3004df1 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Tue, 20 Nov 2018 07:31:37 +0000 Subject: [PATCH 010/115] Implements GUI for HC materials --- gui/__init__.py | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index 0e0b1ee..3415921 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -10,8 +10,7 @@ class D3Edit(object): def __init__(self): message = None self.current_file = None - self.main_window = tk.Tk() - self.main_window.title("D3Edit") + self.setupframe() try: from google import protobuf del protobuf @@ -19,18 +18,24 @@ def __init__(self): message = "Could not import protobuff, please install the protobuf python package." self.draw_welcome(message) + def setupframe(self): + self.main_window = tk.Tk() + self.main_window.title("D3Edit") + self.style = ttk.Style(self.main_window) + self.style.theme_use('default') + self.style.configure("TLabel", foreground="black", background="white") + def draw_welcome(self, message=None): if not message: message = "Account not loaded, please load an account file to begin." - self.first_label = ttk.Label(self.main_window, text=message) + self.first_label = ttk.Label(self.main_window, text=message, style="TLabel") self.first_label.grid(column=0, row=0) self.open_button = ttk.Button(self.main_window, text="Open File", command=self.openfile) self.open_button.grid(column=0, row=1) def destroy_loaded_view(self): self.main_window.destroy() - self.main_window = tk.Tk() - self.main_window.title("D3Edit") + self.setupframe() def openfile(self): selected_file = filedialog.askopenfilename(initialdir=".", title="Select account.dat file") @@ -51,18 +56,25 @@ def savecurrencies(self): for currency in self.account.asd.partitions[0].currency_data.currency: amount = getattr(self.scvalues[str(currency.id)], 'get') currency.count = int(amount()) + for currency in self.account.asd.partitions[1].currency_data.currency: + amount = getattr(self.hcvalues[str(currency.id)], 'get') + currency.count = int(amount()) self.account.commit_all_changes() self.destroy_loaded_view() self.draw_welcome("Account data saved.") def draw_account_view(self): - self.account_header = ttk.Label(text=self.current_file).grid(column=0, row=0) - self.currency_button = ttk.Button(self.main_window, text="Save Softcore Currencies", - command=self.savecurrencies).grid(column=0, row=1) + self.account_header = ttk.Label(text=self.current_file, style="TLabel").grid(column=0, row=0) + self.currency_button = ttk.Button(self.main_window, text="Save all currency changes", + command=self.savecurrencies).grid(column=0, row=1, sticky='E', padx=30) self.sccurrencies = self.account.asd.partitions[0].currency_data.currency + self.hccurrencies = self.account.asd.partitions[1].currency_data.currency self.scvalues = {} + self.hcvalues = {} startcol = 0 - startrow = 2 + startrow = 3 + ttk.Label(self.main_window, text="Softcore").grid(column=0, row=2, sticky='E', padx=128) + ttk.Label(self.main_window, text="Hardcore").grid(column=1, row=2, sticky='W') for currency in self.sccurrencies: currid = str(currency.id) self.scvalues[currid] = tk.StringVar(value=currency.count) @@ -70,7 +82,15 @@ def draw_account_view(self): ttk.Entry(self.main_window, textvariable=self.scvalues[currid])\ .grid(column=startcol, row=startrow, sticky='E') startrow = startrow + 1 - + startcol = 1 + startrow = 3 + for currency in self.hccurrencies: + currid = str(currency.id) + self.hcvalues[currid] = tk.StringVar(value=currency.count) + ttk.Label(self.main_window, text=currency_list[currid]).grid(column=startcol, row=startrow, sticky='W') + ttk.Entry(self.main_window, textvariable=self.hcvalues[currid])\ + .grid(column=startcol, row=startrow, sticky='E') + startrow = startrow + 1 def start(self): self.main_window.mainloop() self.stop_gui() From a7faebdaf1d196baba2c72e07b0a6b762e372c8c Mon Sep 17 00:00:00 2001 From: unixtreme Date: Tue, 20 Nov 2018 07:58:25 +0000 Subject: [PATCH 011/115] Implements paragon levels on GUI for HC and SC --- gui/__init__.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index 3415921..ebde230 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -65,8 +65,6 @@ def savecurrencies(self): def draw_account_view(self): self.account_header = ttk.Label(text=self.current_file, style="TLabel").grid(column=0, row=0) - self.currency_button = ttk.Button(self.main_window, text="Save all currency changes", - command=self.savecurrencies).grid(column=0, row=1, sticky='E', padx=30) self.sccurrencies = self.account.asd.partitions[0].currency_data.currency self.hccurrencies = self.account.asd.partitions[1].currency_data.currency self.scvalues = {} @@ -75,22 +73,31 @@ def draw_account_view(self): startrow = 3 ttk.Label(self.main_window, text="Softcore").grid(column=0, row=2, sticky='E', padx=128) ttk.Label(self.main_window, text="Hardcore").grid(column=1, row=2, sticky='W') + self.scparagon = self.account.asd.partitions[0].alt_level + self.scvalues['plvl'] = tk.StringVar(value=self.scparagon) + self.hcparagon = self.account.asd.partitions[1].alt_level + self.hcvalues['plvl'] = tk.StringVar(value=self.hcparagon) + ttk.Label(self.main_window, text="Paragon Level").grid(column=startcol, row=startrow, sticky='W') + ttk.Entry(self.main_window, textvariable=self.scvalues['plvl']).grid(column=startcol, row=startrow, sticky='E') for currency in self.sccurrencies: + startrow = startrow + 1 currid = str(currency.id) self.scvalues[currid] = tk.StringVar(value=currency.count) ttk.Label(self.main_window, text=currency_list[currid]).grid(column=startcol, row=startrow, sticky='W') ttk.Entry(self.main_window, textvariable=self.scvalues[currid])\ .grid(column=startcol, row=startrow, sticky='E') - startrow = startrow + 1 startcol = 1 startrow = 3 + ttk.Entry(self.main_window, textvariable=self.hcvalues['plvl']).grid(column=startcol, row=startrow, sticky='W') for currency in self.hccurrencies: + startrow = startrow + 1 currid = str(currency.id) self.hcvalues[currid] = tk.StringVar(value=currency.count) ttk.Label(self.main_window, text=currency_list[currid]).grid(column=startcol, row=startrow, sticky='W') ttk.Entry(self.main_window, textvariable=self.hcvalues[currid])\ .grid(column=startcol, row=startrow, sticky='E') - startrow = startrow + 1 + ttk.Button(self.main_window, text="Save all changes", + command=self.savecurrencies).grid(column=0, row=99, sticky='E', padx=40) def start(self): self.main_window.mainloop() self.stop_gui() From d2abf4f33dd6aa18c5e79b00f1cc37be01d61f51 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Tue, 20 Nov 2018 09:09:40 +0000 Subject: [PATCH 012/115] General style changes for PEP8 compliance. --- gui/__init__.py | 33 ++++++++++++++++++++------------- requirements.txt | 1 - 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index ebde230..e14e187 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -9,13 +9,24 @@ class D3Edit(object): def __init__(self): message = None - self.current_file = None - self.setupframe() try: from google import protobuf del protobuf - except: + except ImportError: + protobuf = None message = "Could not import protobuff, please install the protobuf python package." + self.current_file = None + self.scvalues = {} + self.hcvalues = {} + self.sccurrencies = None + self.hccurrencies = None + self.scparagon = None + self.hcparagon = None + self.main_window = None + self.style = None + self.account = None + self.previous_file = None + self.setupframe() self.draw_welcome(message) def setupframe(self): @@ -28,10 +39,10 @@ def setupframe(self): def draw_welcome(self, message=None): if not message: message = "Account not loaded, please load an account file to begin." - self.first_label = ttk.Label(self.main_window, text=message, style="TLabel") - self.first_label.grid(column=0, row=0) - self.open_button = ttk.Button(self.main_window, text="Open File", command=self.openfile) - self.open_button.grid(column=0, row=1) + message_label = ttk.Label(self.main_window, text=message, style="TLabel") + message_label.grid(column=0, row=0) + open_file = ttk.Button(self.main_window, text="Open File", command=self.openfile) + open_file.grid(column=0, row=1) def destroy_loaded_view(self): self.main_window.destroy() @@ -64,11 +75,9 @@ def savecurrencies(self): self.draw_welcome("Account data saved.") def draw_account_view(self): - self.account_header = ttk.Label(text=self.current_file, style="TLabel").grid(column=0, row=0) + ttk.Label(text=self.current_file, style="TLabel").grid(column=0, row=0) self.sccurrencies = self.account.asd.partitions[0].currency_data.currency self.hccurrencies = self.account.asd.partitions[1].currency_data.currency - self.scvalues = {} - self.hcvalues = {} startcol = 0 startrow = 3 ttk.Label(self.main_window, text="Softcore").grid(column=0, row=2, sticky='E', padx=128) @@ -98,9 +107,7 @@ def draw_account_view(self): .grid(column=startcol, row=startrow, sticky='E') ttk.Button(self.main_window, text="Save all changes", command=self.savecurrencies).grid(column=0, row=99, sticky='E', padx=40) + def start(self): self.main_window.mainloop() - self.stop_gui() - - def stop_gui(self): sys.exit(0) diff --git a/requirements.txt b/requirements.txt index fd986d9..b0c79cc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ -wxpython protobuf From b981f4a687698f9dfdf5646c388b14578258fa6c Mon Sep 17 00:00:00 2001 From: unixtreme Date: Tue, 20 Nov 2018 09:17:43 +0000 Subject: [PATCH 013/115] FIX: Actually save changes to Paragon level. --- gui/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index e14e187..4c3a797 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -54,7 +54,6 @@ def openfile(self): if self.current_file: self.previous_file = self.current_file self.current_file = selected_file - self.first_label.configure(text=self.current_file) self.loadaccount(self.current_file) def loadaccount(self, file): @@ -63,18 +62,24 @@ def loadaccount(self, file): self.destroy_loaded_view() self.draw_account_view() - def savecurrencies(self): + def savechanges(self): for currency in self.account.asd.partitions[0].currency_data.currency: amount = getattr(self.scvalues[str(currency.id)], 'get') currency.count = int(amount()) for currency in self.account.asd.partitions[1].currency_data.currency: amount = getattr(self.hcvalues[str(currency.id)], 'get') currency.count = int(amount()) + scplvl = getattr(self.scvalues['plvl'], 'get') + hcplvl = getattr(self.hcvalues['plvl'], 'get') + self.account.asd.partitions[0].alt_level = int(scplvl()) + self.account.asd.partitions[1].alt_level = int(hcplvl()) self.account.commit_all_changes() self.destroy_loaded_view() self.draw_welcome("Account data saved.") def draw_account_view(self): + message_label = ttk.Label(self.main_window, text=self.current_file, style="TLabel") + message_label.grid(column=0, row=0) ttk.Label(text=self.current_file, style="TLabel").grid(column=0, row=0) self.sccurrencies = self.account.asd.partitions[0].currency_data.currency self.hccurrencies = self.account.asd.partitions[1].currency_data.currency @@ -106,7 +111,7 @@ def draw_account_view(self): ttk.Entry(self.main_window, textvariable=self.hcvalues[currid])\ .grid(column=startcol, row=startrow, sticky='E') ttk.Button(self.main_window, text="Save all changes", - command=self.savecurrencies).grid(column=0, row=99, sticky='E', padx=40) + command=self.savechanges).grid(column=0, row=99, sticky='E', padx=40) def start(self): self.main_window.mainloop() From a7bf872c3e07f2a3810a15329f1079441c7ff532 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Tue, 20 Nov 2018 10:14:44 +0000 Subject: [PATCH 014/115] Remember window location, set starting window size. --- gui/__init__.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index 4c3a797..aaa5674 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -26,12 +26,16 @@ def __init__(self): self.style = None self.account = None self.previous_file = None + self.wcoords = None self.setupframe() self.draw_welcome(message) def setupframe(self): self.main_window = tk.Tk() self.main_window.title("D3Edit") + self.main_window.minsize(600, 450) + if self.wcoords: + self.main_window.geometry("+{0}+{1}".format(self.wcoords[0], self.wcoords[1])) self.style = ttk.Style(self.main_window) self.style.theme_use('default') self.style.configure("TLabel", foreground="black", background="white") @@ -40,11 +44,13 @@ def draw_welcome(self, message=None): if not message: message = "Account not loaded, please load an account file to begin." message_label = ttk.Label(self.main_window, text=message, style="TLabel") - message_label.grid(column=0, row=0) + message_label.grid(column=0, row=0, sticky='NEW') + message_label.configure(anchor='center') open_file = ttk.Button(self.main_window, text="Open File", command=self.openfile) - open_file.grid(column=0, row=1) + open_file.place(rely=0.5, relx=0.5, anchor='center') def destroy_loaded_view(self): + self.wcoords = (self.main_window.winfo_x(), self.main_window.winfo_y()) self.main_window.destroy() self.setupframe() From 324ce842a8ee627d3c8768df37fc37ef4f12fe47 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Tue, 20 Nov 2018 13:00:29 +0000 Subject: [PATCH 015/115] Creating tabs for account and so on. Tabs defined on sepparate file. --- gui/__init__.py | 52 ++++++++----------------------------------------- gui/tabs.py | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 44 deletions(-) create mode 100644 gui/tabs.py diff --git a/gui/__init__.py b/gui/__init__.py index aaa5674..2248ff0 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -1,6 +1,7 @@ import save_manager import sys import tkinter as tk +from gui import tabs from settings import currency_list from tkinter import filedialog from tkinter import ttk @@ -16,12 +17,6 @@ def __init__(self): protobuf = None message = "Could not import protobuff, please install the protobuf python package." self.current_file = None - self.scvalues = {} - self.hcvalues = {} - self.sccurrencies = None - self.hccurrencies = None - self.scparagon = None - self.hcparagon = None self.main_window = None self.style = None self.account = None @@ -39,6 +34,7 @@ def setupframe(self): self.style = ttk.Style(self.main_window) self.style.theme_use('default') self.style.configure("TLabel", foreground="black", background="white") + self.style.configure("TNotebook", background="white") def draw_welcome(self, message=None): if not message: @@ -70,13 +66,13 @@ def loadaccount(self, file): def savechanges(self): for currency in self.account.asd.partitions[0].currency_data.currency: - amount = getattr(self.scvalues[str(currency.id)], 'get') + amount = getattr(self.tabs.scvalues[str(currency.id)], 'get') currency.count = int(amount()) for currency in self.account.asd.partitions[1].currency_data.currency: - amount = getattr(self.hcvalues[str(currency.id)], 'get') + amount = getattr(self.tabs.hcvalues[str(currency.id)], 'get') currency.count = int(amount()) - scplvl = getattr(self.scvalues['plvl'], 'get') - hcplvl = getattr(self.hcvalues['plvl'], 'get') + scplvl = getattr(self.tabs.scvalues['plvl'], 'get') + hcplvl = getattr(self.tabs.hcvalues['plvl'], 'get') self.account.asd.partitions[0].alt_level = int(scplvl()) self.account.asd.partitions[1].alt_level = int(hcplvl()) self.account.commit_all_changes() @@ -84,40 +80,8 @@ def savechanges(self): self.draw_welcome("Account data saved.") def draw_account_view(self): - message_label = ttk.Label(self.main_window, text=self.current_file, style="TLabel") - message_label.grid(column=0, row=0) - ttk.Label(text=self.current_file, style="TLabel").grid(column=0, row=0) - self.sccurrencies = self.account.asd.partitions[0].currency_data.currency - self.hccurrencies = self.account.asd.partitions[1].currency_data.currency - startcol = 0 - startrow = 3 - ttk.Label(self.main_window, text="Softcore").grid(column=0, row=2, sticky='E', padx=128) - ttk.Label(self.main_window, text="Hardcore").grid(column=1, row=2, sticky='W') - self.scparagon = self.account.asd.partitions[0].alt_level - self.scvalues['plvl'] = tk.StringVar(value=self.scparagon) - self.hcparagon = self.account.asd.partitions[1].alt_level - self.hcvalues['plvl'] = tk.StringVar(value=self.hcparagon) - ttk.Label(self.main_window, text="Paragon Level").grid(column=startcol, row=startrow, sticky='W') - ttk.Entry(self.main_window, textvariable=self.scvalues['plvl']).grid(column=startcol, row=startrow, sticky='E') - for currency in self.sccurrencies: - startrow = startrow + 1 - currid = str(currency.id) - self.scvalues[currid] = tk.StringVar(value=currency.count) - ttk.Label(self.main_window, text=currency_list[currid]).grid(column=startcol, row=startrow, sticky='W') - ttk.Entry(self.main_window, textvariable=self.scvalues[currid])\ - .grid(column=startcol, row=startrow, sticky='E') - startcol = 1 - startrow = 3 - ttk.Entry(self.main_window, textvariable=self.hcvalues['plvl']).grid(column=startcol, row=startrow, sticky='W') - for currency in self.hccurrencies: - startrow = startrow + 1 - currid = str(currency.id) - self.hcvalues[currid] = tk.StringVar(value=currency.count) - ttk.Label(self.main_window, text=currency_list[currid]).grid(column=startcol, row=startrow, sticky='W') - ttk.Entry(self.main_window, textvariable=self.hcvalues[currid])\ - .grid(column=startcol, row=startrow, sticky='E') - ttk.Button(self.main_window, text="Save all changes", - command=self.savechanges).grid(column=0, row=99, sticky='E', padx=40) + self.tabs = tabs.Notebook(self.main_window, account=self.account.asd) + ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) def start(self): self.main_window.mainloop() diff --git a/gui/tabs.py b/gui/tabs.py new file mode 100644 index 0000000..bfa8a8e --- /dev/null +++ b/gui/tabs.py @@ -0,0 +1,46 @@ +import tkinter as tk +from tkinter import ttk +from settings import currency_list + + +class Notebook(ttk.Notebook): + def __init__(self, parent, account): + self.account = account + self.tabs = ttk.Notebook(parent) + self.account_tab = ttk.Frame(self.tabs, style="TNotebook") + self.hero_tab = ttk.Frame(self.tabs, style="TNotebook") + self.tabs.add(self.account_tab, text="Account") + self.tabs.pack(expan=1, fill="both") + # dictionary holding textvariables for Entry fields + self.scvalues = {} + self.hcvalues = {} + self.configure_account_tab() + self.populate_sc_data() + self.populate_hc_data() + + def configure_account_tab(self): + ttk.Label(self.account_tab, text="Softcore").grid(column=1, row=0, sticky='E', padx=128) + ttk.Label(self.account_tab, text="Hardcore").grid(column=2, row=0, sticky='W') + ttk.Label(self.account_tab, text="Paragon Level").grid(column=0, row=1, sticky='W') + for id, currency in currency_list.items(): + ttk.Label(self.account_tab, text=currency).grid(column=0, row=(int(id) + 5), sticky='W') + + def populate_sc_data(self): + self.scvalues['plvl'] = tk.StringVar(value=self.account.partitions[0].alt_level) + ttk.Entry(self.account_tab, textvariable=self.scvalues['plvl']).grid(column=1, row=1, sticky='E') + sccurrency = self.account.partitions[0].currency_data.currency + for currency in sccurrency: + id = currency.id + idstr = str(currency.id) + self.scvalues[idstr] = tk.StringVar(value=currency.count) + ttk.Entry(self.account_tab, textvariable=self.scvalues[idstr]).grid(column=1, row=(id + 5), sticky='E') + + def populate_hc_data(self): + self.hcvalues['plvl'] = tk.StringVar(value=self.account.partitions[1].alt_level) + ttk.Entry(self.account_tab, textvariable=self.hcvalues['plvl']).grid(column=2, row=1, sticky='E') + hccurrency = self.account.partitions[1].currency_data.currency + for currency in hccurrency: + id = currency.id + idstr = str(currency.id) + self.hcvalues[idstr] = tk.StringVar(value=currency.count) + ttk.Entry(self.account_tab, textvariable=self.hcvalues[idstr]).grid(column=2, row=(id + 5), sticky='E') From 12315aa6498994e5e529c1309fb31a172926cde5 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 12:06:00 +0000 Subject: [PATCH 016/115] Populates hero tab with currently loaded heroes. Default hero is last_played_hero_id. --- gui/__init__.py | 3 +-- gui/tabs.py | 21 +++++++++++++++++---- save_manager/__init__.py | 17 +++++++---------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index 2248ff0..bde4e7e 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -2,7 +2,6 @@ import sys import tkinter as tk from gui import tabs -from settings import currency_list from tkinter import filedialog from tkinter import ttk @@ -80,7 +79,7 @@ def savechanges(self): self.draw_welcome("Account data saved.") def draw_account_view(self): - self.tabs = tabs.Notebook(self.main_window, account=self.account.asd) + self.tabs = tabs.Notebook(self.main_window, account=self.account) ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) def start(self): diff --git a/gui/tabs.py b/gui/tabs.py index bfa8a8e..68ac603 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -10,11 +10,14 @@ def __init__(self, parent, account): self.account_tab = ttk.Frame(self.tabs, style="TNotebook") self.hero_tab = ttk.Frame(self.tabs, style="TNotebook") self.tabs.add(self.account_tab, text="Account") + self.tabs.add(self.hero_tab, text="Heroes") self.tabs.pack(expan=1, fill="both") # dictionary holding textvariables for Entry fields self.scvalues = {} self.hcvalues = {} + self.active_hero = None self.configure_account_tab() + self.configure_hero_tab() self.populate_sc_data() self.populate_hc_data() @@ -26,9 +29,9 @@ def configure_account_tab(self): ttk.Label(self.account_tab, text=currency).grid(column=0, row=(int(id) + 5), sticky='W') def populate_sc_data(self): - self.scvalues['plvl'] = tk.StringVar(value=self.account.partitions[0].alt_level) + self.scvalues['plvl'] = tk.StringVar(value=self.account.asd.partitions[0].alt_level) ttk.Entry(self.account_tab, textvariable=self.scvalues['plvl']).grid(column=1, row=1, sticky='E') - sccurrency = self.account.partitions[0].currency_data.currency + sccurrency = self.account.asd.partitions[0].currency_data.currency for currency in sccurrency: id = currency.id idstr = str(currency.id) @@ -36,11 +39,21 @@ def populate_sc_data(self): ttk.Entry(self.account_tab, textvariable=self.scvalues[idstr]).grid(column=1, row=(id + 5), sticky='E') def populate_hc_data(self): - self.hcvalues['plvl'] = tk.StringVar(value=self.account.partitions[1].alt_level) + self.hcvalues['plvl'] = tk.StringVar(value=self.account.asd.partitions[1].alt_level) ttk.Entry(self.account_tab, textvariable=self.hcvalues['plvl']).grid(column=2, row=1, sticky='E') - hccurrency = self.account.partitions[1].currency_data.currency + hccurrency = self.account.asd.partitions[1].currency_data.currency for currency in hccurrency: id = currency.id idstr = str(currency.id) self.hcvalues[idstr] = tk.StringVar(value=currency.count) ttk.Entry(self.account_tab, textvariable=self.hcvalues[idstr]).grid(column=2, row=(id + 5), sticky='E') + + def configure_hero_tab(self): + heroes = ['{1} - {0}'.format(h, d.digest.hero_name) for h, d in self.account.heroes.items()] + for hero in heroes: + if hero.endswith(self.account.last_played_hero_id): + self.active_hero = tk.StringVar(value=hero) + else: + self.active_hero = tk.StringVar(value=hero[0]) + c = ttk.Combobox(self.hero_tab, textvariable=self.active_hero, values=heroes, state='readonly') + c.pack() diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 51b59bb..2aa4737 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -29,16 +29,13 @@ def __init__(self, account_file, output_file=None): self.heroes = {} self.hsd = Hero_pb2.SavedDefinition() for hero_path in self.hero_files: - hero_id = basename(hero_path) - if self.last_played_hero_id in hero_id: - enc_hero = save_handler.load_encrypted_file(hero_path) - dec_hero = save_handler.decrypt_save(enc_hero) - self.heroes[hero_id] = self.hsd.ParseFromString(dec_hero) - else: - self.heroes[hero_id] = Hero_pb2.SavedDefinition() - enc_hero = save_handler.load_encrypted_file(hero_path) - dec_hero = save_handler.decrypt_save(enc_hero) - self.heroes[hero_id].ParseFromString(dec_hero) + hero_id = basename(hero_path.replace('.dat', '')) + self.heroes[hero_id] = Hero_pb2.SavedDefinition() + enc_hero = save_handler.load_encrypted_file(hero_path) + dec_hero = save_handler.decrypt_save(enc_hero) + self.heroes[hero_id].ParseFromString(dec_hero) + if isinstance(self.heroes[hero_id], int): + del self.heroes[hero_id] def load_currencies(self): """ From b5ebfc9e242a02a46c67c2154ddb0bb3b6ed3ba5 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 13:23:08 +0000 Subject: [PATCH 017/115] Adds some information into the hero frames of the hero_tab. Editing not supported at the moment. --- gui/tabs.py | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/gui/tabs.py b/gui/tabs.py index 68ac603..0f89a7d 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -16,6 +16,10 @@ def __init__(self, parent, account): self.scvalues = {} self.hcvalues = {} self.active_hero = None + self.active_hero_data = {} + self.active_hero_frame = tk.Frame(self.hero_tab) + self.active_hero_frame.grid(column=0, row=1) + self.heroframes = None self.configure_account_tab() self.configure_hero_tab() self.populate_sc_data() @@ -48,12 +52,38 @@ def populate_hc_data(self): self.hcvalues[idstr] = tk.StringVar(value=currency.count) ttk.Entry(self.account_tab, textvariable=self.hcvalues[idstr]).grid(column=2, row=(id + 5), sticky='E') + def generate_hero_frame(self, event=None): + if event: + self.active_hero_frame.destroy() + self.active_hero_frame = tk.Frame(self.hero_tab) + self.active_hero_frame.grid(column=0, row=1) + c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero, values=self.heroes, state='readonly') + c.grid(column=1, row=0) + c.bind("<>", self.generate_hero_frame) + active_hid = self.active_hero.get().split(" - ")[1] + current_hero_data = self.account.heroes[active_hid] + self.active_hero_data['name'] = tk.StringVar(value=current_hero_data.digest.hero_name) + self.active_hero_data['level'] = tk.StringVar(value=current_hero_data.digest.level) + self.active_hero_data['rift'] = tk.StringVar(value=current_hero_data.digest.highest_solo_rift_completed) + hnamelabel = ttk.Label(self.active_hero_frame, text="Name") + hnameentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['name']) + hlevellabel = ttk.Label(self.active_hero_frame, text="Level") + hlevelentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['level']) + hriftlabel = ttk.Label(self.active_hero_frame, text="Highest Solo Rift") + hriftentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['rift']) + hnamelabel.grid(column=0, row=1, sticky='W') + hnameentry.grid(column=1, row=1, sticky='W') + hlevellabel.grid(column=0, row=2, sticky='W') + hlevelentry.grid(column=1, row=2, sticky='W') + hriftlabel.grid(column=0, row=3, sticky='W') + hriftentry.grid(column=1, row=3, sticky='W') + self.active_hero_frame.grid(column=0, row=0, sticky='NEWS') + def configure_hero_tab(self): - heroes = ['{1} - {0}'.format(h, d.digest.hero_name) for h, d in self.account.heroes.items()] - for hero in heroes: + self.heroes = ['{1} - {0}'.format(h, d.digest.hero_name) for h, d in self.account.heroes.items()] + for hero in self.heroes: if hero.endswith(self.account.last_played_hero_id): self.active_hero = tk.StringVar(value=hero) else: self.active_hero = tk.StringVar(value=hero[0]) - c = ttk.Combobox(self.hero_tab, textvariable=self.active_hero, values=heroes, state='readonly') - c.pack() + self.generate_hero_frame() From bb4f222302327cb4299bc2e997e77978903cd5f9 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 13:34:47 +0000 Subject: [PATCH 018/115] Adds Stash tab. --- gui/tabs.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gui/tabs.py b/gui/tabs.py index 0f89a7d..d7c62fb 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -9,8 +9,10 @@ def __init__(self, parent, account): self.tabs = ttk.Notebook(parent) self.account_tab = ttk.Frame(self.tabs, style="TNotebook") self.hero_tab = ttk.Frame(self.tabs, style="TNotebook") + self.stash_tab = ttk.Frame(self.tabs, style="TNotebook") self.tabs.add(self.account_tab, text="Account") self.tabs.add(self.hero_tab, text="Heroes") + self.tabs.add(self.stash_tab, text="Stash") self.tabs.pack(expan=1, fill="both") # dictionary holding textvariables for Entry fields self.scvalues = {} @@ -18,10 +20,12 @@ def __init__(self, parent, account): self.active_hero = None self.active_hero_data = {} self.active_hero_frame = tk.Frame(self.hero_tab) - self.active_hero_frame.grid(column=0, row=1) self.heroframes = None + self.active_stash_frame = tk.Frame(self.stash_tab) + self.active_stash = None self.configure_account_tab() self.configure_hero_tab() + self.configure_stash_tab() self.populate_sc_data() self.populate_hc_data() @@ -87,3 +91,13 @@ def configure_hero_tab(self): else: self.active_hero = tk.StringVar(value=hero[0]) self.generate_hero_frame() + + def configure_stash_tab(self, event=None): + if event: + self.active_stash_frame.destroy() + self.active_stash_frame = tk.Frame(self.stash_tab) + self.active_stash_frame.grid(column=0, row=1) + c = ttk.Combobox(self.active_stash_frame, textvariable=self.active_stash, values=['SC', 'HC'], state='readonly') + c.grid(column=1, row=0) + c.bind("<>", self.configure_stash_tab) + self.active_stash_frame.grid(column=0, row=0, sticky='NEWS') From 72cfc53a834e3e5a9925ea886270977e24787eac Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 15:11:58 +0000 Subject: [PATCH 019/115] Allows to save Hero changes. --- D3Edit.py | 2 +- gui/__init__.py | 21 ++++++++++++++++----- gui/tabs.py | 38 ++++++++++++++++---------------------- save_manager/__init__.py | 13 +++++++++++-- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/D3Edit.py b/D3Edit.py index 404ad2c..63f03e1 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -49,4 +49,4 @@ # This should be the only write we do, a final commit_all_changes(). - account.commit_all_changes() + account.commit_account_changes() diff --git a/gui/__init__.py b/gui/__init__.py index bde4e7e..dd67e95 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -21,6 +21,7 @@ def __init__(self): self.account = None self.previous_file = None self.wcoords = None + self.tabs = None self.setupframe() self.draw_welcome(message) @@ -61,7 +62,11 @@ def loadaccount(self, file): self.account = save_manager.SaveData(file) self.account.output_file = file self.destroy_loaded_view() - self.draw_account_view() + self.tabs = tabs.Notebook(self.main_window, account=self.account) + if self.account.heroes: + self.tabs.configure_hero_tab() + ttk.Button(self.tabs.hero_tab, text="Save Hero", command=self.savehero).grid(column=1, row=99) + ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) def savechanges(self): for currency in self.account.asd.partitions[0].currency_data.currency: @@ -74,13 +79,19 @@ def savechanges(self): hcplvl = getattr(self.tabs.hcvalues['plvl'], 'get') self.account.asd.partitions[0].alt_level = int(scplvl()) self.account.asd.partitions[1].alt_level = int(hcplvl()) - self.account.commit_all_changes() + self.account.commit_account_changes() self.destroy_loaded_view() self.draw_welcome("Account data saved.") - def draw_account_view(self): - self.tabs = tabs.Notebook(self.main_window, account=self.account) - ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) + def savehero(self): + hid = self.tabs.active_hid + name = getattr(self.tabs.active_hero_data['Name'], 'get') + level = getattr(self.tabs.active_hero_data['Level'], 'get') + rift = getattr(self.tabs.active_hero_data['Highest Solo Rift'], 'get') + self.account.heroes[hid].digest.hero_name = name() + self.account.heroes[hid].digest.level = int(level()) + self.account.heroes[hid].digest.highest_solo_rift_completed = int(rift()) + self.account.commit_hero_changes(hid) def start(self): self.main_window.mainloop() diff --git a/gui/tabs.py b/gui/tabs.py index d7c62fb..9b2990b 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -17,14 +17,14 @@ def __init__(self, parent, account): # dictionary holding textvariables for Entry fields self.scvalues = {} self.hcvalues = {} - self.active_hero = None + self.active_hid = None + self.active_hero_name = None self.active_hero_data = {} self.active_hero_frame = tk.Frame(self.hero_tab) self.heroframes = None self.active_stash_frame = tk.Frame(self.stash_tab) self.active_stash = None self.configure_account_tab() - self.configure_hero_tab() self.configure_stash_tab() self.populate_sc_data() self.populate_hc_data() @@ -61,35 +61,29 @@ def generate_hero_frame(self, event=None): self.active_hero_frame.destroy() self.active_hero_frame = tk.Frame(self.hero_tab) self.active_hero_frame.grid(column=0, row=1) - c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero, values=self.heroes, state='readonly') + c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero_name, values=self.heroes, state='readonly') c.grid(column=1, row=0) c.bind("<>", self.generate_hero_frame) - active_hid = self.active_hero.get().split(" - ")[1] - current_hero_data = self.account.heroes[active_hid] - self.active_hero_data['name'] = tk.StringVar(value=current_hero_data.digest.hero_name) - self.active_hero_data['level'] = tk.StringVar(value=current_hero_data.digest.level) - self.active_hero_data['rift'] = tk.StringVar(value=current_hero_data.digest.highest_solo_rift_completed) - hnamelabel = ttk.Label(self.active_hero_frame, text="Name") - hnameentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['name']) - hlevellabel = ttk.Label(self.active_hero_frame, text="Level") - hlevelentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['level']) - hriftlabel = ttk.Label(self.active_hero_frame, text="Highest Solo Rift") - hriftentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['rift']) - hnamelabel.grid(column=0, row=1, sticky='W') - hnameentry.grid(column=1, row=1, sticky='W') - hlevellabel.grid(column=0, row=2, sticky='W') - hlevelentry.grid(column=1, row=2, sticky='W') - hriftlabel.grid(column=0, row=3, sticky='W') - hriftentry.grid(column=1, row=3, sticky='W') + self.active_hid = self.active_hero_name.get().split(" - ")[1] + current_hero_data = self.account.heroes[self.active_hid] + self.active_hero_data['Name'] = tk.StringVar(value=current_hero_data.digest.hero_name) + self.active_hero_data['Level'] = tk.StringVar(value=current_hero_data.digest.level) + self.active_hero_data['Highest Solo Rift'] = tk.StringVar( + value=current_hero_data.digest.highest_solo_rift_completed) + row = 1 + for key, value in self.active_hero_data.items(): + ttk.Label(self.active_hero_frame, text=key).grid(column=0, row=row, sticky='W') + ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data[key]).grid(column=1, row=row) + row = row + 1 self.active_hero_frame.grid(column=0, row=0, sticky='NEWS') def configure_hero_tab(self): self.heroes = ['{1} - {0}'.format(h, d.digest.hero_name) for h, d in self.account.heroes.items()] for hero in self.heroes: if hero.endswith(self.account.last_played_hero_id): - self.active_hero = tk.StringVar(value=hero) + self.active_hero_name = tk.StringVar(value=hero) else: - self.active_hero = tk.StringVar(value=hero[0]) + self.active_hero_name = tk.StringVar(value=hero[0]) self.generate_hero_frame() def configure_stash_tab(self, event=None): diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 2aa4737..8256461 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -73,7 +73,7 @@ def set_currency(self, currency_id, amount): print("Currency {0} not found on the account, this normally means you need to play and collect some currency " "first.".format(currency_id)) - def commit_all_changes(self, target_file=None): + def commit_account_changes(self, target_file=None): # TODO: perhaps automatically backup account.dat # serialize and encrypt account file if target_file: @@ -82,4 +82,13 @@ def commit_all_changes(self, target_file=None): account_mod_enc = save_handler.encrypt_save(account_mod_dec) # commit account file to storage only if it changed if self.output_file and (account_mod_enc != self.account_enc): - save_handler.commit_to_file(account_mod_enc, self.output_file) \ No newline at end of file + save_handler.commit_to_file(account_mod_enc, self.output_file) + + def commit_hero_changes(self, hid): + if hid.startswith('modded_'): + target_file = "{0}/heroes/{1}.dat".format(self.save_folder, hid) + else: + target_file = "{0}/heroes/modded_{1}.dat".format(self.save_folder, hid) + hero_mod_dec = self.heroes[hid].SerializeToString() + hero_mod_enc = save_handler.encrypt_save(hero_mod_dec) + save_handler.commit_to_file(hero_mod_enc, target_file) \ No newline at end of file From c3af8c8584dc1cdb3607f2b43c4bb21921f5b447 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 15:11:58 +0000 Subject: [PATCH 020/115] Allows to save Hero changes. --- D3Edit.py | 2 +- gui/__init__.py | 22 +++++++++++++++----- gui/tabs.py | 44 ++++++++++++++++++++-------------------- save_manager/__init__.py | 15 ++++++++++++-- 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/D3Edit.py b/D3Edit.py index 404ad2c..63f03e1 100644 --- a/D3Edit.py +++ b/D3Edit.py @@ -49,4 +49,4 @@ # This should be the only write we do, a final commit_all_changes(). - account.commit_all_changes() + account.commit_account_changes() diff --git a/gui/__init__.py b/gui/__init__.py index bde4e7e..a480cca 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -21,6 +21,7 @@ def __init__(self): self.account = None self.previous_file = None self.wcoords = None + self.tabs = None self.setupframe() self.draw_welcome(message) @@ -61,7 +62,11 @@ def loadaccount(self, file): self.account = save_manager.SaveData(file) self.account.output_file = file self.destroy_loaded_view() - self.draw_account_view() + self.tabs = tabs.Notebook(self.main_window, account=self.account) + if self.account.heroes: + self.tabs.configure_hero_tab() + ttk.Button(self.tabs.active_hero_frame, text="Save Hero", command=self.savehero).grid(column=1, row=99) + ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) def savechanges(self): for currency in self.account.asd.partitions[0].currency_data.currency: @@ -74,13 +79,20 @@ def savechanges(self): hcplvl = getattr(self.tabs.hcvalues['plvl'], 'get') self.account.asd.partitions[0].alt_level = int(scplvl()) self.account.asd.partitions[1].alt_level = int(hcplvl()) - self.account.commit_all_changes() + self.account.commit_account_changes() self.destroy_loaded_view() self.draw_welcome("Account data saved.") - def draw_account_view(self): - self.tabs = tabs.Notebook(self.main_window, account=self.account) - ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) + def savehero(self): + hid = self.tabs.active_hid + name = getattr(self.tabs.active_hero_data['Name'], 'get') + level = getattr(self.tabs.active_hero_data['Level'], 'get') + rift = getattr(self.tabs.active_hero_data['Highest Solo Rift'], 'get') + self.account.heroes[hid].digest.hero_name = name() + self.account.heroes[hid].digest.level = int(level()) + self.account.heroes[hid].digest.highest_solo_rift_completed = int(rift()) + saved = self.account.commit_hero_changes(hid) + self.tabs.hero_tab_message("Hero saved as: {}".format(saved.split('/')[-1])) def start(self): self.main_window.mainloop() diff --git a/gui/tabs.py b/gui/tabs.py index d7c62fb..d785325 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -17,14 +17,14 @@ def __init__(self, parent, account): # dictionary holding textvariables for Entry fields self.scvalues = {} self.hcvalues = {} - self.active_hero = None + self.active_hid = None + self.active_hero_name = None self.active_hero_data = {} self.active_hero_frame = tk.Frame(self.hero_tab) self.heroframes = None self.active_stash_frame = tk.Frame(self.stash_tab) self.active_stash = None self.configure_account_tab() - self.configure_hero_tab() self.configure_stash_tab() self.populate_sc_data() self.populate_hc_data() @@ -61,37 +61,37 @@ def generate_hero_frame(self, event=None): self.active_hero_frame.destroy() self.active_hero_frame = tk.Frame(self.hero_tab) self.active_hero_frame.grid(column=0, row=1) - c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero, values=self.heroes, state='readonly') + c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero_name, values=self.heroes, state='readonly') c.grid(column=1, row=0) c.bind("<>", self.generate_hero_frame) - active_hid = self.active_hero.get().split(" - ")[1] - current_hero_data = self.account.heroes[active_hid] - self.active_hero_data['name'] = tk.StringVar(value=current_hero_data.digest.hero_name) - self.active_hero_data['level'] = tk.StringVar(value=current_hero_data.digest.level) - self.active_hero_data['rift'] = tk.StringVar(value=current_hero_data.digest.highest_solo_rift_completed) - hnamelabel = ttk.Label(self.active_hero_frame, text="Name") - hnameentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['name']) - hlevellabel = ttk.Label(self.active_hero_frame, text="Level") - hlevelentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['level']) - hriftlabel = ttk.Label(self.active_hero_frame, text="Highest Solo Rift") - hriftentry = ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data['rift']) - hnamelabel.grid(column=0, row=1, sticky='W') - hnameentry.grid(column=1, row=1, sticky='W') - hlevellabel.grid(column=0, row=2, sticky='W') - hlevelentry.grid(column=1, row=2, sticky='W') - hriftlabel.grid(column=0, row=3, sticky='W') - hriftentry.grid(column=1, row=3, sticky='W') + self.active_hid = self.active_hero_name.get().split(" - ")[1] + current_hero_data = self.account.heroes[self.active_hid] + self.active_hero_data['Name'] = tk.StringVar(value=current_hero_data.digest.hero_name) + self.active_hero_data['Level'] = tk.StringVar(value=current_hero_data.digest.level) + self.active_hero_data['Highest Solo Rift'] = tk.StringVar( + value=current_hero_data.digest.highest_solo_rift_completed) + row = 1 + for key, value in self.active_hero_data.items(): + ttk.Label(self.active_hero_frame, text=key).grid(column=0, row=row, sticky='W') + ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data[key]).grid(column=1, row=row) + row = row + 1 + self.active_hero_frame.rowconfigure(98, weight=1) + self.active_hero_frame.rowconfigure(99, weight=1) + self.active_hero_frame.columnconfigure(1, weight=0) self.active_hero_frame.grid(column=0, row=0, sticky='NEWS') def configure_hero_tab(self): self.heroes = ['{1} - {0}'.format(h, d.digest.hero_name) for h, d in self.account.heroes.items()] for hero in self.heroes: if hero.endswith(self.account.last_played_hero_id): - self.active_hero = tk.StringVar(value=hero) + self.active_hero_name = tk.StringVar(value=hero) else: - self.active_hero = tk.StringVar(value=hero[0]) + self.active_hero_name = tk.StringVar(value=hero[0]) self.generate_hero_frame() + def hero_tab_message(self, message): + ttk.Label(self.active_hero_frame, text=message).grid(column=1, row=98) + def configure_stash_tab(self, event=None): if event: self.active_stash_frame.destroy() diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 2aa4737..a986a00 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -73,7 +73,7 @@ def set_currency(self, currency_id, amount): print("Currency {0} not found on the account, this normally means you need to play and collect some currency " "first.".format(currency_id)) - def commit_all_changes(self, target_file=None): + def commit_account_changes(self, target_file=None): # TODO: perhaps automatically backup account.dat # serialize and encrypt account file if target_file: @@ -82,4 +82,15 @@ def commit_all_changes(self, target_file=None): account_mod_enc = save_handler.encrypt_save(account_mod_dec) # commit account file to storage only if it changed if self.output_file and (account_mod_enc != self.account_enc): - save_handler.commit_to_file(account_mod_enc, self.output_file) \ No newline at end of file + save_handler.commit_to_file(account_mod_enc, self.output_file) + + def commit_hero_changes(self, hid): + if hid.startswith('modded_'): + target_file = "{0}/heroes/{1}.dat".format(self.save_folder, hid) + else: + target_file = "{0}/heroes/modded_{1}.dat".format(self.save_folder, hid) + hero_mod_dec = self.heroes[hid].SerializeToString() + hero_mod_enc = save_handler.encrypt_save(hero_mod_dec) + save_handler.commit_to_file(hero_mod_enc, target_file) + + return target_file From cd80b4ec3d522aae90734ab457dc3de8e5515f7f Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 15:29:21 +0000 Subject: [PATCH 021/115] Dummy commit for stash manager --- stash_manager/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 stash_manager/__init__.py diff --git a/stash_manager/__init__.py b/stash_manager/__init__.py new file mode 100644 index 0000000..e69de29 From bef7292c162393d5e086ca1cafcff16e1f2425aa Mon Sep 17 00:00:00 2001 From: unixtreme Date: Wed, 21 Nov 2018 16:34:20 +0000 Subject: [PATCH 022/115] Fix: Save Hero button disappearing after changing hero. --- gui/__init__.py | 2 +- gui/tabs.py | 4 +++- save_manager/__init__.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index a480cca..b034807 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -65,7 +65,7 @@ def loadaccount(self, file): self.tabs = tabs.Notebook(self.main_window, account=self.account) if self.account.heroes: self.tabs.configure_hero_tab() - ttk.Button(self.tabs.active_hero_frame, text="Save Hero", command=self.savehero).grid(column=1, row=99) + ttk.Button(self.tabs.hero_tab, text="Save Hero", command=self.savehero).grid(column=1, row=99) ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) def savechanges(self): diff --git a/gui/tabs.py b/gui/tabs.py index d785325..68c6131 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -17,6 +17,7 @@ def __init__(self, parent, account): # dictionary holding textvariables for Entry fields self.scvalues = {} self.hcvalues = {} + self.heroes = None self.active_hid = None self.active_hero_name = None self.active_hero_data = {} @@ -61,7 +62,8 @@ def generate_hero_frame(self, event=None): self.active_hero_frame.destroy() self.active_hero_frame = tk.Frame(self.hero_tab) self.active_hero_frame.grid(column=0, row=1) - c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero_name, values=self.heroes, state='readonly') + c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero_name, + values=self.heroes, state='readonly') c.grid(column=1, row=0) c.bind("<>", self.generate_hero_frame) self.active_hid = self.active_hero_name.get().split(" - ")[1] diff --git a/save_manager/__init__.py b/save_manager/__init__.py index a986a00..1f02a7c 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -70,8 +70,8 @@ def set_currency(self, currency_id, amount): print("Set currency {0} to {1}".format( currency_list[str(currency_id)], current_currency.count, currency_id)) else: - print("Currency {0} not found on the account, this normally means you need to play and collect some currency " - "first.".format(currency_id)) + print("Currency {0} not found on the account, this normally means you need to play and collect " + "some currency first.".format(currency_id)) def commit_account_changes(self, target_file=None): # TODO: perhaps automatically backup account.dat From 5f809eaa6dd04bd8d85db176845aafe4736da89f Mon Sep 17 00:00:00 2001 From: unixtreme Date: Thu, 22 Nov 2018 11:42:56 +0000 Subject: [PATCH 023/115] Fix: Paragon level should now take effect. --- gui/__init__.py | 8 ++++++-- save_manager/__init__.py | 12 ++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index b034807..4e6a855 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -76,9 +76,13 @@ def savechanges(self): amount = getattr(self.tabs.hcvalues[str(currency.id)], 'get') currency.count = int(amount()) scplvl = getattr(self.tabs.scvalues['plvl'], 'get') + scplvl = int(scplvl()) hcplvl = getattr(self.tabs.hcvalues['plvl'], 'get') - self.account.asd.partitions[0].alt_level = int(scplvl()) - self.account.asd.partitions[1].alt_level = int(hcplvl()) + hcplvl = int(hcplvl()) + self.account.set_attribute(0, (-4093, scplvl)) + self.account.set_attribute(1, (-4093, hcplvl)) + self.account.asd.partitions[0].alt_level = scplvl + self.account.asd.partitions[1].alt_level = hcplvl self.account.commit_account_changes() self.destroy_loaded_view() self.draw_welcome("Account data saved.") diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 1f02a7c..34d6073 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -73,6 +73,18 @@ def set_currency(self, currency_id, amount): print("Currency {0} not found on the account, this normally means you need to play and collect " "some currency first.".format(currency_id)) + def set_attribute(self, partition: int, contents: tuple): + attributes = self.asd.partitions[partition].saved_attributes.attributes + keyfound = False + for attribute in attributes: + if attribute.key == contents[0]: + keyfound = True + attribute.value = contents[1] + if not keyfound: + added_attribute = attributes.add() + added_attribute.key = contents[0] + added_attribute.value = contents[1] + def commit_account_changes(self, target_file=None): # TODO: perhaps automatically backup account.dat # serialize and encrypt account file From 13ec77cdef11c81b77f51080f1bfe2ea9e8d31ae Mon Sep 17 00:00:00 2001 From: unixtreme Date: Thu, 22 Nov 2018 16:22:32 +0000 Subject: [PATCH 024/115] Basic inventory read only view. --- gui/__init__.py | 15 +++---- gui/tabs.py | 107 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 91 insertions(+), 31 deletions(-) diff --git a/gui/__init__.py b/gui/__init__.py index 4e6a855..b11308d 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -25,12 +25,12 @@ def __init__(self): self.setupframe() self.draw_welcome(message) - def setupframe(self): + def setupframe(self, wcoords=None): self.main_window = tk.Tk() self.main_window.title("D3Edit") self.main_window.minsize(600, 450) - if self.wcoords: - self.main_window.geometry("+{0}+{1}".format(self.wcoords[0], self.wcoords[1])) + if wcoords: + self.main_window.geometry("+{0}+{1}".format(wcoords[0], wcoords[1])) self.style = ttk.Style(self.main_window) self.style.theme_use('default') self.style.configure("TLabel", foreground="black", background="white") @@ -46,9 +46,9 @@ def draw_welcome(self, message=None): open_file.place(rely=0.5, relx=0.5, anchor='center') def destroy_loaded_view(self): - self.wcoords = (self.main_window.winfo_x(), self.main_window.winfo_y()) + wcoords = (self.main_window.winfo_x(), self.main_window.winfo_y()) self.main_window.destroy() - self.setupframe() + self.setupframe(wcoords) def openfile(self): selected_file = filedialog.askopenfilename(initialdir=".", title="Select account.dat file") @@ -65,8 +65,9 @@ def loadaccount(self, file): self.tabs = tabs.Notebook(self.main_window, account=self.account) if self.account.heroes: self.tabs.configure_hero_tab() - ttk.Button(self.tabs.hero_tab, text="Save Hero", command=self.savehero).grid(column=1, row=99) - ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges).grid(column=1, row=99) + ttk.Button(self.tabs.hero_tab, text="Save Hero", command=self.savehero).grid(column=0, row=99) + s = ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges) + s.grid(column=1, row=99) def savechanges(self): for currency in self.account.asd.partitions[0].currency_data.currency: diff --git a/gui/tabs.py b/gui/tabs.py index 68c6131..0e1ba7a 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -7,9 +7,9 @@ class Notebook(ttk.Notebook): def __init__(self, parent, account): self.account = account self.tabs = ttk.Notebook(parent) - self.account_tab = ttk.Frame(self.tabs, style="TNotebook") - self.hero_tab = ttk.Frame(self.tabs, style="TNotebook") - self.stash_tab = ttk.Frame(self.tabs, style="TNotebook") + self.account_tab = ttk.Frame(self.tabs, style="TNotebook", borderwidth=0) + self.hero_tab = ttk.Frame(self.tabs, style="TNotebook", borderwidth=0) + self.stash_tab = ttk.Frame(self.tabs, style="TNotebook", borderwidth=0) self.tabs.add(self.account_tab, text="Account") self.tabs.add(self.hero_tab, text="Heroes") self.tabs.add(self.stash_tab, text="Stash") @@ -19,14 +19,17 @@ def __init__(self, parent, account): self.hcvalues = {} self.heroes = None self.active_hid = None - self.active_hero_name = None + self.active_hero_name = "No - Hero" self.active_hero_data = {} - self.active_hero_frame = tk.Frame(self.hero_tab) + self.active_hero_frame = ttk.Frame(self.hero_tab, style="TNotebook", borderwidth=0) self.heroframes = None - self.active_stash_frame = tk.Frame(self.stash_tab) - self.active_stash = None + self.active_stash_frame = None + self.active_stash = tk.StringVar(value='SC') + self.stash_data = None + self.item_list_frame = None + self.item_frame = None self.configure_account_tab() - self.configure_stash_tab() + self.configure_stash_frame() self.populate_sc_data() self.populate_hc_data() @@ -57,15 +60,15 @@ def populate_hc_data(self): self.hcvalues[idstr] = tk.StringVar(value=currency.count) ttk.Entry(self.account_tab, textvariable=self.hcvalues[idstr]).grid(column=2, row=(id + 5), sticky='E') - def generate_hero_frame(self, event=None): + def load_hero_frame(self, event=None): if event: self.active_hero_frame.destroy() - self.active_hero_frame = tk.Frame(self.hero_tab) + self.active_hero_frame = ttk.Frame(self.hero_tab, style="TNotebook", borderwidth=0) self.active_hero_frame.grid(column=0, row=1) c = ttk.Combobox(self.active_hero_frame, textvariable=self.active_hero_name, values=self.heroes, state='readonly') c.grid(column=1, row=0) - c.bind("<>", self.generate_hero_frame) + c.bind("<>", self.load_hero_frame) self.active_hid = self.active_hero_name.get().split(" - ")[1] current_hero_data = self.account.heroes[self.active_hid] self.active_hero_data['Name'] = tk.StringVar(value=current_hero_data.digest.hero_name) @@ -77,10 +80,7 @@ def generate_hero_frame(self, event=None): ttk.Label(self.active_hero_frame, text=key).grid(column=0, row=row, sticky='W') ttk.Entry(self.active_hero_frame, textvariable=self.active_hero_data[key]).grid(column=1, row=row) row = row + 1 - self.active_hero_frame.rowconfigure(98, weight=1) - self.active_hero_frame.rowconfigure(99, weight=1) - self.active_hero_frame.columnconfigure(1, weight=0) - self.active_hero_frame.grid(column=0, row=0, sticky='NEWS') + self.active_hero_frame.grid(column=0, row=0) def configure_hero_tab(self): self.heroes = ['{1} - {0}'.format(h, d.digest.hero_name) for h, d in self.account.heroes.items()] @@ -88,18 +88,77 @@ def configure_hero_tab(self): if hero.endswith(self.account.last_played_hero_id): self.active_hero_name = tk.StringVar(value=hero) else: - self.active_hero_name = tk.StringVar(value=hero[0]) - self.generate_hero_frame() + self.active_hero_name = tk.StringVar(value=self.heroes[0]) + self.load_hero_frame() def hero_tab_message(self, message): ttk.Label(self.active_hero_frame, text=message).grid(column=1, row=98) - def configure_stash_tab(self, event=None): - if event: + def configure_stash_frame(self, event=None): + if self.active_stash_frame: self.active_stash_frame.destroy() - self.active_stash_frame = tk.Frame(self.stash_tab) - self.active_stash_frame.grid(column=0, row=1) + self.active_stash_frame = ttk.Frame(self.stash_tab, style="TNotebook", borderwidth=0) + self.active_stash_frame.grid(column=0, row=0) c = ttk.Combobox(self.active_stash_frame, textvariable=self.active_stash, values=['SC', 'HC'], state='readonly') - c.grid(column=1, row=0) - c.bind("<>", self.configure_stash_tab) - self.active_stash_frame.grid(column=0, row=0, sticky='NEWS') + c.grid(column=0, row=0, sticky='NW', columnspan=2) + c.bind("<>", self.configure_stash_frame) + if self.active_stash.get() == 'SC': + try: + self.stash_data = self.account.asd.partitions[0].items.ListFields()[0][1] + except IndexError: + self.stash_data = None + elif self.active_stash.get() == 'HC': + try: + self.stash_data = self.account.asd.partitions[1].items.ListFields()[0][1] + except IndexError: + self.stash_data = None + else: + assert "incorrect stash selected, stash has to be either SC or HC." + if self.stash_data: + self.load_item_list_frame(self.stash_data, self.active_stash_frame) + + def load_item_list_frame(self, itemlist, parent): + if self.item_list_frame: + self.item_list_frame.destroy() + self.item_list_frame = ttk.Frame(parent, style="TNotebook", borderwidth=0) + self.item_list_frame.grid(column=0, row=1, sticky='NESW') + ttk.Label(self.item_list_frame, text="Item List:").grid(column=0, row=1, sticky='W') + scrollbar = ScrollbarItems(itemlist, parent=self.item_list_frame) + scrollbar.grid(column=0, row=2) + scrollbar.listbox.bind('', lambda x: self.loaditemfromsb(itemlist, scrollbar, self.item_list_frame)) + + def loaditemfromsb(self, itemlist, scrollbar, parent): + index = scrollbar.listbox.curselection()[0] + item = scrollbar.indexmap[index] + print(item) + self.load_item_frame(item, parent) + + def load_item_frame(self, item, parent): + if self.item_frame: + self.item_frame.destroy() + self.item_frame = ttk.Frame(parent, style="TNotebook", borderwidth=0) + self.item_frame.grid(row=2, column=1, sticky='NES') + ttk.Label(self.item_frame, text=item).grid(sticky='NES') + + +class ScrollbarItems(ttk.Frame): + def __init__(self, options, parent=None): + ttk.Frame.__init__(self, parent) + self.indexmap = {} + self.parent = parent + self.makewidgets(options) + + def makewidgets(self, options): + sb = tk.Scrollbar(self) + listing = tk.Listbox(self, relief='sunken') + sb.config(command=listing.yview) + listing.config(yscrollcommand=sb.set, height=35) + sb.grid(row=0, column=1, sticky='ns') + listing.grid(row=0, column=0, sticky='ns') + curr_index = 0 + for item in options: + sq_index = item.square_index + listing.insert(curr_index, sq_index) + self.indexmap[curr_index] = item + curr_index = curr_index + 1 + self.listbox = listing From f14391377d9a6e0a023afd9ad59cba4020a82f3c Mon Sep 17 00:00:00 2001 From: unixtreme Date: Thu, 22 Nov 2018 18:21:12 +0000 Subject: [PATCH 025/115] Translates some item name labels. --- Research/clean_save/account.dat | Bin 383 -> 402 bytes gui/tabs.py | 12 +++++++++--- settings.py | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Research/clean_save/account.dat b/Research/clean_save/account.dat index 390a1215fe3c1b74b5dd9dd38bfae20a575d059e..75cc704270f1a98e4d53e0d14644d45ddfafb611 100755 GIT binary patch delta 339 zcmey*G>LhFNBxOI+uXYs<(xTr-E&7tY~87YdSxs2#Ke3$t(v!DE{qNfe|4G#$OqFY zi(A9WfP66h;DAg@6Oa$4r-y|+Xs9^Wd^|4n(}bdf-N(FF@#gnl?mM?>s%-xH*DXg^ zO|^m1sY^b$JXtlh-UiHAFi$156(|6vfA;@buph_=(`Kp5f1dxtw68FC>FZLnD&roVCDt#!StL$FAqB)A504|>(9CD&2J_ss5b42 zGoSLicQ<`9zg4qne0%o;MkoJGX5j?#!StV}50dWy`CvMeU+~WnARkPBO8%F*RN&K@ S>cqZ{lKXW}GAHtFkOTns2d6#& delta 320 zcmbQl{GVxpNBzA++uSEF$~klYy629ZSidhu=DruvO+|IS?-gd?wrw=CQ>5k^Y}oe^IO#BR$}OnJT> z$OqFU|L0k51oFZ3yf^zx?g9B=y2o Date: Fri, 23 Nov 2018 11:59:18 +0000 Subject: [PATCH 026/115] Basic item and affix decoding --- gui/tabs.py | 47 ++++++++++++++++++------------------ save_manager/save_handler.py | 3 +-- settings.py | 2 +- stash_manager/__init__.py | 0 4 files changed, 25 insertions(+), 27 deletions(-) delete mode 100644 stash_manager/__init__.py diff --git a/gui/tabs.py b/gui/tabs.py index 74bcc96..da5d418 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -1,5 +1,6 @@ import tkinter as tk from tkinter import ttk +from save_manager import item_handler from settings import currency_list from settings import gbid_list @@ -124,47 +125,45 @@ def load_item_list_frame(self, itemlist, parent): self.item_list_frame = ttk.Frame(parent, style="TNotebook", borderwidth=0) self.item_list_frame.grid(column=0, row=1, sticky='NESW') ttk.Label(self.item_list_frame, text="Item List:").grid(column=0, row=1, sticky='W') - scrollbar = ScrollbarItems(itemlist, parent=self.item_list_frame) + self.decodeditems = item_handler.decode_itemlist(itemlist) + scrollbar = ScrollbarItems(self.decodeditems, parent=self.item_list_frame) scrollbar.grid(column=0, row=2) - scrollbar.listbox.bind('', lambda x: self.loaditemfromsb(itemlist, scrollbar, self.item_list_frame)) + scrollbar.listbox.bind('', lambda x: self.load_item_frame(scrollbar, self.item_list_frame)) - def loaditemfromsb(self, itemlist, scrollbar, parent): - index = scrollbar.listbox.curselection()[0] - item = scrollbar.indexmap[index] - self.load_item_frame(item, parent) - - def load_item_frame(self, item, parent): + def load_item_frame(self, scrollbar, parent): if self.item_frame: self.item_frame.destroy() + index = scrollbar.listbox.curselection()[0] + entry = scrollbar.indexmap[index] self.item_frame = ttk.Frame(parent, style="TNotebook", borderwidth=0) self.item_frame.grid(row=2, column=1, sticky='NES') - ttk.Label(self.item_frame, text=item).grid(sticky='NES') + # INSIDE ABOVE FRAME + row = 0 + ttk.Label(self.item_frame, text=entry['name']).grid(row=row, sticky='NWS') + for affix in entry['affixes']: + row = row + 1 + ttk.Label(self.item_frame, text=affix['effect']).grid(row=row, sticky='NES') class ScrollbarItems(ttk.Frame): - def __init__(self, options, parent=None): + def __init__(self, items, parent=None): ttk.Frame.__init__(self, parent) - self.indexmap = {} + self.indexmap = [] self.parent = parent - self.makewidgets(options) + self.makewidgets(items) - def makewidgets(self, options): + def makewidgets(self, items): sb = tk.Scrollbar(self) listing = tk.Listbox(self, relief='sunken') sb.config(command=listing.yview) listing.config(yscrollcommand=sb.set, height=35) sb.grid(row=0, column=1, sticky='ns') listing.grid(row=0, column=0, sticky='ns') - curr_index = 0 - for item in options: - gbid = str(item.generator.gb_handle.gbid) - if gbid in gbid_list: - label = gbid_list[gbid]['name'] - if ':' in label: - label = label.split(':')[1] - else: - label = item.square_index + for item in items: + curr_index = len(self.indexmap) + label = item['name'] + if not isinstance(label, str): + label = label['name'] listing.insert(curr_index, label) - self.indexmap[curr_index] = item - curr_index = curr_index + 1 + self.indexmap.append(item) self.listbox = listing diff --git a/save_manager/save_handler.py b/save_manager/save_handler.py index eb9b1eb..2f82fc9 100644 --- a/save_manager/save_handler.py +++ b/save_manager/save_handler.py @@ -1,6 +1,5 @@ -import Hero_pb2 from os.path import isfile, isdir, join -from settings import HERO_DIR, AFFIX_LIST +from settings import HERO_DIR from sys import getsizeof from binascii import hexlify as _hexlify diff --git a/settings.py b/settings.py index 34bd674..9edde05 100644 --- a/settings.py +++ b/settings.py @@ -21,7 +21,7 @@ with open(join(ASSET_DIR, GBIDS_FILE), "r") as f: gbid_list = load(f) with open(join(ASSET_DIR, AFFIXES_FILE), "r") as f: - AFFIX_LIST = load(f) + affixes_list = load(f) with open(join(ASSET_DIR, SLOTS_FILE), "r") as f: SLOT_LIST = load(f) with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: diff --git a/stash_manager/__init__.py b/stash_manager/__init__.py deleted file mode 100644 index e69de29..0000000 From db3385095e35daf67b1633ce2fc577151e5351c9 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Fri, 23 Nov 2018 12:15:37 +0000 Subject: [PATCH 027/115] Basic item and affix decoding --- save_manager/item_handler.py | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 save_manager/item_handler.py diff --git a/save_manager/item_handler.py b/save_manager/item_handler.py new file mode 100644 index 0000000..f2a120b --- /dev/null +++ b/save_manager/item_handler.py @@ -0,0 +1,41 @@ +from settings import gbid_list +from settings import affixes_list + + +def gbid_to_str(gbid): + try: + gbid_return = gbid_list[str(gbid)] + except KeyError: + gbid_return = 'Unknown Item' + return gbid_return + + +def affix_to_str(affix): + try: + affix_return = affixes_list[str(affix)] + except KeyError: + affix_return = {'effect': 'Unknown Affix'} + return affix_return + + +def decode_single_item(item): + decoded_item = {} + gbid = str(item.generator.gb_handle.gbid) + decoded_gbid = gbid_to_str(gbid) + if isinstance(decoded_gbid, dict): + decoded_item['name'] = decoded_gbid['name'] + decoded_item['category'] = decoded_gbid['category'] + else: + decoded_item['name'] = decoded_gbid + decoded_item['category'] = 'Unknown Category' + decoded_item['affixes'] = [affix_to_str(affix) for affix in item.generator.base_affixes] + decoded_item['item'] = item + return decoded_item + + +def decode_itemlist(itemlist): + item_out = [] + for item in itemlist: + item_out.append(decode_single_item(item)) + + return item_out From 9aa8e8a5c347deed85e32bdbaf3926be152be3bd Mon Sep 17 00:00:00 2001 From: unixtreme Date: Fri, 23 Nov 2018 14:35:00 +0000 Subject: [PATCH 028/115] Adds Hero inventory listing. Includes categorised gbid_list for future use for item edition. --- assets/gbids_categorised.json | 1 + assets/itemquality.json | 15 +++++++++++++++ gui/__init__.py | 1 + gui/tabs.py | 13 +++++++------ settings.json | 3 ++- settings.py | 8 +++++++- 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 assets/gbids_categorised.json create mode 100644 assets/itemquality.json diff --git a/assets/gbids_categorised.json b/assets/gbids_categorised.json new file mode 100644 index 0000000..53cf1a7 --- /dev/null +++ b/assets/gbids_categorised.json @@ -0,0 +1 @@ +{"None": {}, "Amulets": {"1682228618": {"name": "02: Amulet", "category": "Amulets", "platform": "Console"}, "1682228619": {"name": "03: Amulet", "category": "Amulets", "platform": "Console"}, "1682228620": {"name": "04: Amulet", "category": "Amulets", "platform": "Console"}, "1682228621": {"name": "05: Amulet", "category": "Amulets", "platform": "Console"}, "1682228622": {"name": "06: Amulet", "category": "Amulets", "platform": "Console"}, "1682228623": {"name": "07: Amulet", "category": "Amulets", "platform": "Console"}, "1682228624": {"name": "08: Amulet", "category": "Amulets", "platform": "Console"}, "1682228625": {"name": "09: Amulet", "category": "Amulets", "platform": "Console"}, "1682228649": {"name": "10: Amulet", "category": "Amulets", "platform": "Console"}, "1682228650": {"name": "11: Amulet", "category": "Amulets", "platform": "Console"}, "1682228651": {"name": "12: Amulet", "category": "Amulets", "platform": "Console"}, "1682228652": {"name": "13: Amulet", "category": "Amulets", "platform": "Console"}, "1682228653": {"name": "14: Amulet", "category": "Amulets", "platform": "Console"}, "1682228654": {"name": "15: Amulet", "category": "Amulets", "platform": "Console"}, "1682228655": {"name": "16: Amulet", "category": "Amulets", "platform": "Console"}, "1682228656": {"name": "17: Amulet", "category": "Amulets", "platform": "Console"}, "-1335710051": {"name": "Art Test Amulet 1", "category": "Amulets", "platform": "Console"}, "-1335710050": {"name": "Art Test Amulet 2", "category": "Amulets", "platform": "Console"}, "-1335710049": {"name": "Art Test Amulet 3", "category": "Amulets", "platform": "Console"}, "-1335710048": {"name": "Art Test Amulet 4", "category": "Amulets", "platform": "Console"}, "-1335710047": {"name": "Art Test Amulet 5", "category": "Amulets", "platform": "Console"}, "1566332280": {"name": "Legendary: Ancestors' Grace", "category": "Amulets", "platform": "Console"}, "1566368217": {"name": "Legendary: Countess Julia's Cameo", "category": "Amulets", "platform": "Console"}, "1566511965": {"name": "Legendary: Dovu Energy Trap", "category": "Amulets", "platform": "Console"}, "1200923753": {"name": "Legendary: Drake's Amulet (PS3 Promo)", "category": "Amulets", "platform": "Console"}, "1528454682": {"name": "Legendary: Eye of Etlich", "category": "Amulets", "platform": "Console"}, "-1100680346": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "-1100677902": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "412126098": {"name": "Legendary: Eye of Etlich (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566440091": {"name": "Legendary: Golden Gorget of Leoric", "category": "Amulets", "platform": "Console"}, "1566583839": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "737941201": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "1566296343": {"name": "Legendary: Haunt of Vaxo", "category": "Amulets", "platform": "Console"}, "761548935": {"name": "Legendary: Hellfire Amulet (Patch 1.2.0)", "category": "Amulets", "platform": "Console"}, "1528418745": {"name": "Legendary: Holy Beacon", "category": "Amulets", "platform": "Console"}, "-1101866267": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "-1101863823": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "412126097": {"name": "Legendary: Holy Beacon (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196887": {"name": "Legendary: Kymbo's Gold", "category": "Amulets", "platform": "Console"}, "-1142187581": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "-1142185137": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "412126063": {"name": "Legendary: Kymbo's Gold (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196623": {"name": "Legendary: Kymbo's Gold (Patch 2.1.0)", "category": "Amulets", "platform": "Console"}, "1528490619": {"name": "Legendary: Mara's Kaleidoscope", "category": "Amulets", "platform": "Console"}, "-1099494425": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "-1099491981": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "412126099": {"name": "Legendary: Mara's Kaleidoscope (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527232824": {"name": "Legendary: Moonlight Ward", "category": "Amulets", "platform": "Console"}, "-1141001660": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "-1140999216": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "412126064": {"name": "Legendary: Moonlight Ward (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527304698": {"name": "Legendary: Ouroboros", "category": "Amulets", "platform": "Console"}, "-1138629818": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "-1138627374": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "412126066": {"name": "Legendary: Ouroboros (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566476028": {"name": "Legendary: Overwhelming Desire", "category": "Amulets", "platform": "Console"}, "1566547902": {"name": "Legendary: Rakoff's Glass of Life", "category": "Amulets", "platform": "Console"}, "1527448446": {"name": "Legendary: Rondal's Locket", "category": "Amulets", "platform": "Console"}, "-1133886134": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1133883690": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126070": {"name": "Legendary: Rondal's Locket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528310934": {"name": "Legendary: Squirt's Necklace", "category": "Amulets", "platform": "Console"}, "-1105424030": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "-1105421586": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "412126094": {"name": "Legendary: Squirt's Necklace (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528382808": {"name": "Legendary: Talisman of Aranoch", "category": "Amulets", "platform": "Console"}, "-1103052188": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "-1103049744": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "412126096": {"name": "Legendary: Talisman of Aranoch (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566404154": {"name": "Legendary: The Ess of Johan", "category": "Amulets", "platform": "Console"}, "1527160950": {"name": "Legendary: The Flavor of Time", "category": "Amulets", "platform": "Console"}, "-1143373502": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "-1143371058": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "412126062": {"name": "Legendary: The Flavor of Time (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528346871": {"name": "Legendary: The Murlocket", "category": "Amulets", "platform": "Console"}, "-1104238109": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1104235665": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126095": {"name": "Legendary: The Murlocket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527340635": {"name": "Legendary: The Star of Azkaranth", "category": "Amulets", "platform": "Console"}, "-1137443897": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "-1137441453": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "412126067": {"name": "Legendary: The Star of Azkaranth (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527268761": {"name": "Legendary: Xephirian Amulet", "category": "Amulets", "platform": "Console"}, "-1139815739": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "-1139813295": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "412126065": {"name": "Legendary: Xephirian Amulet (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "714520304": {"name": "PvP: Art of War 3v3", "category": "Amulets", "platform": "Console"}, "1685772266": {"name": "PvP: Art of War All", "category": "Amulets", "platform": "Console"}, "1685772538": {"name": "PvP: Art of War Attack", "category": "Amulets", "platform": "Console"}, "1685775296": {"name": "PvP: Art of War Defense", "category": "Amulets", "platform": "Console"}, "-203544613": {"name": "PvP: Art of War Precision", "category": "Amulets", "platform": "Console"}, "1685795044": {"name": "PvP: Art of War Vitality", "category": "Amulets", "platform": "Console"}, "-203302615": {"name": "PvP: Art of War Willpower", "category": "Amulets", "platform": "Console"}, "1803178445": {"name": "PvP: Born for War All", "category": "Amulets", "platform": "Console"}, "1803178717": {"name": "PvP: Born for War Attack", "category": "Amulets", "platform": "Console"}, "1803181475": {"name": "PvP: Born for War Defense", "category": "Amulets", "platform": "Console"}, "-624108002": {"name": "PvP: Born for War Precision", "category": "Amulets", "platform": "Console"}, "1803201223": {"name": "PvP: Born for War Vitality", "category": "Amulets", "platform": "Console"}, "1528526556": {"name": "Set: Blackthorne's Duncraig Cross", "category": "Amulets", "platform": "Console"}, "-1098308504": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "-1098306060": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "412126100": {"name": "Set: Blackthorne's Medal (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "412126069": {"name": "Set: Spirit of Adventure (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "-1544505070": {"name": "Set: Sunwuko's Shines", "category": "Amulets", "platform": "Console"}, "412126068": {"name": "Set: Tal Rasha's Adjudication (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527376572": {"name": "Set: Tal Rasha's Allegiance", "category": "Amulets", "platform": "Console"}, "-1136257976": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "-1136255532": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "1527412509": {"name": "Set: The Traveler's Pledge", "category": "Amulets", "platform": "Console"}, "-1135072055": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-1135069611": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-795161790": {"name": "legendary: Moonlight Ward (Patch 2.2.0)", "category": "Amulets", "platform": "Console"}}, "Axes, One-Handed": {"1661412390": {"name": "01: Hand Axe (DPS 3.3-4.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412391": {"name": "02: Broad Axe (DPS 7.2-9.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412392": {"name": "03: Double Axe (DPS 12.4-14.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412393": {"name": "04: Heavy Axe (DPS 17.6-19.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412394": {"name": "05: Battle Axe (DPS 21.5-23.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412395": {"name": "06: Marauder Axe (DPS 26.7-28.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412396": {"name": "07: Soldier Axe (DPS 31.2-33.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413479": {"name": "08: Hatchet (DPS 36.4-38.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413480": {"name": "09: Ono (DPS 46.2-48.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413481": {"name": "10: Bullova (DPS 57.2-59.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413482": {"name": "11: Adze (DPS 69.6-73.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413483": {"name": "12: Chopper (DPS 86.5-90.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413484": {"name": "13: Toporok (DPS 101.4-105.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413485": {"name": "14: Masakari (DPS 118.3-122.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414568": {"name": "15: Tomahawk (DPS 129.4-135.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414569": {"name": "16: Crescent Axe (DPS 144.3-150.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414570": {"name": "17: Arreat Axe (DPS 160.6-166.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414571": {"name": "18: Balestarius (DPS 177.5-185.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414572": {"name": "19: Skartaran Axe (DPS 206.7-214.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414573": {"name": "20: Galraki (DPS 238.6-246.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414574": {"name": "21: Arch Axe (DPS 275.6-285.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415657": {"name": "22: Executioner's Axe (DPS 371.8-379.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415658": {"name": "23: Dire Axe (DPS 461.5-469.3)", "category": "Axes, One-Handed", "platform": "Console"}, "-657929333": {"name": "Art Test Axe One-Handed 1", "category": "Axes, One-Handed", "platform": "Console"}, "-657929332": {"name": "Art Test Axe One-Handed 2", "category": "Axes, One-Handed", "platform": "Console"}, "-657929331": {"name": "Art Test Axe One-Handed 3", "category": "Axes, One-Handed", "platform": "Console"}, "-657929330": {"name": "Art Test Axe One-Handed 4", "category": "Axes, One-Handed", "platform": "Console"}, "-657929329": {"name": "Art Test Axe One-Handed 5", "category": "Axes, One-Handed", "platform": "Console"}, "824126149": {"name": "Legendary: Aidan's Revenge", "category": "Axes, One-Handed", "platform": "Console"}, "824162086": {"name": "Legendary: Fenris Tooth", "category": "Axes, One-Handed", "platform": "Console"}, "784990756": {"name": "Legendary: Flesh Tearer", "category": "Axes, One-Handed", "platform": "Console"}, "134813872": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "134816316": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046948": {"name": "Legendary: Flesh Tearer (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785062630": {"name": "Legendary: Genzaniku", "category": "Axes, One-Handed", "platform": "Console"}, "137185714": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "137188158": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046946": {"name": "Legendary: Genzaniku (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "824198023": {"name": "Legendary: Hack", "category": "Axes, One-Handed", "platform": "Console"}, "785134504": {"name": "Legendary: Sky Splitter", "category": "Axes, One-Handed", "platform": "Console"}, "139557556": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "139560000": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046944": {"name": "Legendary: Sky Splitter (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785206378": {"name": "Legendary: The Burning Axe of Sankis", "category": "Axes, One-Handed", "platform": "Console"}, "141929398": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "141931842": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046942": {"name": "Legendary: The Burning Axe of Sankis (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785170441": {"name": "Legendary: The Butcher's Sickle", "category": "Axes, One-Handed", "platform": "Console"}, "140743477": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "140745921": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046943": {"name": "Legendary: The Butcher's Sickle (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138371635": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138374079": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046945": {"name": "Legendary: The Wedge (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785098567": {"name": "Legendary: Utar's Roar", "category": "Axes, One-Handed", "platform": "Console"}, "786248551": {"name": "Set: Hallowed Breach", "category": "Axes, One-Handed", "platform": "Console"}, "-219046913": {"name": "Set: Hallowed Divide (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176321107": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176323551": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785134241": {"name": "legendary: Sky Spliiter (Patch 2.2.0)", "category": "Axes, One-Handed", "platform": "Console"}}, "Axes, Two-Handed": {"1700547784": {"name": "02: War Axe (DPS 16.0-17.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547785": {"name": "03: Tabarzin (DPS 22.5-24.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547786": {"name": "04: Military Axe (DPS 31.5-33.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547787": {"name": "05: Great Axe (DPS 42.5-44.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548872": {"name": "06: Timber Axe (DPS 56.5-59.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548873": {"name": "07: Francisca (DPS 73.5-76.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548874": {"name": "08: Fang Axe (DPS 94.0-98.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548875": {"name": "09: Parashu (DPS 119.0-125.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548876": {"name": "10: Labrys (DPS 170.0-177.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549961": {"name": "11: Fell Axe (DPS 230.5-241.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549962": {"name": "12: Valaska (DPS 313.0-325.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549963": {"name": "13: Ripper Axe (DPS 400.0-412.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549964": {"name": "14: Sagaris (DPS 474.5-486.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549965": {"name": "15: Decapitator (DPS 560.0-572.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551050": {"name": "16: Dread Axe (DPS 698.0-711.2)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551051": {"name": "17: Flesh Render (DPS 948.2-961.4)", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893396": {"name": "Art Test Axe Two-Handed 1", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893395": {"name": "Art Test Axe Two-Handed 2", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893394": {"name": "Art Test Axe Two-Handed 3", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893393": {"name": "Art Test Axe Two-Handed 4", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893392": {"name": "Art Test Axe Two-Handed 5", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516456824": {"name": "Legendary: Burst of Wrath", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555664091": {"name": "Legendary: Butcher's Carver", "category": "Axes, Two-Handed", "platform": "Console"}, "202615249": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "202617693": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911555": {"name": "Legendary: Butcher's Carver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554514107": {"name": "Legendary: Cinder Switch", "category": "Axes, Two-Handed", "platform": "Console"}, "240564721": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "240567165": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911523": {"name": "Legendary: Fire Brand (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554478170": {"name": "Legendary: Messerschmidt's Reaver", "category": "Axes, Two-Handed", "platform": "Console"}, "241750642": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "241753086": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911522": {"name": "Legendary: Messerschmidt's Reaver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516420887": {"name": "Legendary: Saint of Slaughter", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555376595": {"name": "Legendary: Skorn", "category": "Axes, Two-Handed", "platform": "Console"}, "212102617": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "212105061": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911547": {"name": "Legendary: Skorn (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516492761": {"name": "Legendary: Sungjae's Fury", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555592217": {"name": "Legendary: The Executioner", "category": "Axes, Two-Handed", "platform": "Console"}, "204987091": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "204989535": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911553": {"name": "Legendary: The Executioner (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516528698": {"name": "Legendary: The Marauder", "category": "Axes, Two-Handed", "platform": "Console"}, "120887006": {"name": "PvP: Heroic Reaper", "category": "Axes, Two-Handed", "platform": "Console"}, "120887005": {"name": "PvP: Mighty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "120887004": {"name": "PvP: Trusty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}}, "Belts": {"-733831368": {"name": "02: Hide Belt (AR 24-28)", "category": "Belts", "platform": "Console"}, "-733831367": {"name": "03: Leather Belt (AR 14-16)", "category": "Belts", "platform": "Console"}, "-733831366": {"name": "04: Cord (AR 44-53)", "category": "Belts", "platform": "Console"}, "-733831365": {"name": "05: Binding Rope (AR 54-67)", "category": "Belts", "platform": "Console"}, "-733831364": {"name": "06: Chain Belt (AR 34-43)", "category": "Belts", "platform": "Console"}, "-733830280": {"name": "07: Silk Sash (AR 68-87)", "category": "Belts", "platform": "Console"}, "-733830279": {"name": "08: Waistwrap (AR 88-107)", "category": "Belts", "platform": "Console"}, "-733830278": {"name": "09: Strand (AR 108-127)", "category": "Belts", "platform": "Console"}, "-733830277": {"name": "10: Cupola (AR 128-149)", "category": "Belts", "platform": "Console"}, "-733830276": {"name": "11: Cinch (AR 150-164)", "category": "Belts", "platform": "Console"}, "-733829191": {"name": "12: Grasp (AR 165-179)", "category": "Belts", "platform": "Console"}, "-733829190": {"name": "13: Sheath (AR 180-189)", "category": "Belts", "platform": "Console"}, "-733829189": {"name": "14: Cincture (AR 190-214)", "category": "Belts", "platform": "Console"}, "-733829188": {"name": "15: Girdle (AR 215-239)", "category": "Belts", "platform": "Console"}, "-733829187": {"name": "16: Heaven Strand (AR 240-264)", "category": "Belts", "platform": "Console"}, "-733829186": {"name": "17: High Scabbard (AR 265-314)", "category": "Belts", "platform": "Console"}, "-733829185": {"name": "18: War Belt (AR 315-439)", "category": "Belts", "platform": "Console"}, "-733829184": {"name": "19: Archon Sash (AR 440-506)", "category": "Belts", "platform": "Console"}, "1187629340": {"name": "Art Test Belt 1", "category": "Belts", "platform": "Console"}, "1187629341": {"name": "Art Test Belt 2", "category": "Belts", "platform": "Console"}, "1187629342": {"name": "Art Test Belt 3", "category": "Belts", "platform": "Console"}, "1187629343": {"name": "Art Test Belt 4", "category": "Belts", "platform": "Console"}, "1187629344": {"name": "Art Test Belt 5", "category": "Belts", "platform": "Console"}, "949342869": {"name": "Belt Of The Trove (Patch 2.1.2)", "category": "Belts", "platform": "Console"}, "1770820311": {"name": "Legendary: Angel Hair Braid", "category": "Belts", "platform": "Console"}, "-1692549181": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-1692546737": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-660622993": {"name": "Legendary: Angel Hair Braid (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770820047": {"name": "Legendary: Angel Hair Braid (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1809991641": {"name": "Legendary: Cord of the Sherma", "category": "Belts", "platform": "Console"}, "1770856248": {"name": "Legendary: Fleeting Strap", "category": "Belts", "platform": "Console"}, "1771898421": {"name": "Legendary: Goldwrap", "category": "Belts", "platform": "Console"}, "-1656971551": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1656969107": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622963": {"name": "Legendary: Goldwrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810027578": {"name": "Legendary: Harrington Waistguard", "category": "Belts", "platform": "Console"}, "1770892185": {"name": "Legendary: Hellcat Waistguard", "category": "Belts", "platform": "Console"}, "-1690177339": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-1690174895": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-660622991": {"name": "Legendary: Hellcat Waistguard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810099452": {"name": "Legendary: Hwoj Wrap", "category": "Belts", "platform": "Console"}, "1809955704": {"name": "Legendary: Insatiable Belt", "category": "Belts", "platform": "Console"}, "1810063515": {"name": "Legendary: Jang's Envelopment", "category": "Belts", "platform": "Console"}, "-1691363260": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1691360816": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622992": {"name": "Legendary: Quick Draw Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809883830": {"name": "Legendary: Razor Strop", "category": "Belts", "platform": "Console"}, "1770748437": {"name": "Legendary: Saffron Wrap", "category": "Belts", "platform": "Console"}, "-1694921023": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1694918579": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622995": {"name": "Legendary: Saffron Wrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809919767": {"name": "Legendary: Sash of Knives", "category": "Belts", "platform": "Console"}, "1809919503": {"name": "Legendary: Sash of Knives (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1810135389": {"name": "Legendary: Sebor's Nightmare", "category": "Belts", "platform": "Console"}, "1770999996": {"name": "Legendary: String of Ears", "category": "Belts", "platform": "Console"}, "-1686619576": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-1686617132": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-660622988": {"name": "Legendary: String of Ears (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1771035933": {"name": "Legendary: The Witching Hour", "category": "Belts", "platform": "Console"}, "-1685433655": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-1685431211": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-660622987": {"name": "Legendary: The Witching Hour (Old-Legacy)", "category": "Belts", "platform": "Console"}, "924103246": {"name": "Legendary: Thundergod's Vigor", "category": "Belts", "platform": "Console"}, "1770784374": {"name": "Legendary: Vigilante Belt", "category": "Belts", "platform": "Console"}, "-1693735102": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1693732658": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622994": {"name": "Legendary: Vigilante Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1772078106": {"name": "Set: Blackthorne's Notched Belt", "category": "Belts", "platform": "Console"}, "-1651041946": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1651039502": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622958": {"name": "Set: Blackthorne's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-660622961": {"name": "Set: Captain Crimson's Brace (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1654599709": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "-1654597265": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "1771970295": {"name": "Set: Captain Crimson's Silk Girdle", "category": "Belts", "platform": "Console"}, "-660622959": {"name": "Set: Demon's Binding (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1652227867": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "-1652225423": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "1772042169": {"name": "Set: Demon's Restraint", "category": "Belts", "platform": "Console"}, "1772006232": {"name": "Set: Guardian's Case", "category": "Belts", "platform": "Console"}, "-660622960": {"name": "Set: Guardian's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1653413788": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-1653411344": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-660622989": {"name": "Set: Inna's Blessing (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770964059": {"name": "Set: Inna's Favor", "category": "Belts", "platform": "Console"}, "-1687805497": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-1687803053": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-885483983": {"name": "Set: Krelm's Buff Belt", "category": "Belts", "platform": "Console"}, "1770928122": {"name": "Set: Tal Rasha's Brace", "category": "Belts", "platform": "Console"}, "-1688991418": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-1688988974": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-660622990": {"name": "Set: Tal Rasha's Finespun Cloth (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1069972162": {"name": "legendary: Belessed of Haull (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972159": {"name": "legendary: Belt of Transcendence (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972158": {"name": "legendary: Crashing Rain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972160": {"name": "legendary: Haunting Girdle (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972161": {"name": "legendary: Omnislash (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972163": {"name": "legendary: Omryn's Chain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809919504": {"name": "legendary: Sash of Knives (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1810135126": {"name": "legendary: Sebor's Nightmare (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809991378": {"name": "legendary: Sherma of Corrosion (Patch 2.2.0)", "category": "Belts", "platform": "Console"}}, "Boots": {"2140880152": {"name": "02: Boots (AR 16-18)", "category": "Boots", "platform": "Console"}, "2140880153": {"name": "03: Heavy Boots (AR 30-35)", "category": "Boots", "platform": "Console"}, "2140880154": {"name": "04: Chain Boots (AR 44-57)", "category": "Boots", "platform": "Console"}, "2140880155": {"name": "05: Sabatons (AR 58-66)", "category": "Boots", "platform": "Console"}, "2140880156": {"name": "06: Greaves (AR 67-82)", "category": "Boots", "platform": "Console"}, "2140881240": {"name": "07: Silk Shoes (AR 54-106)", "category": "Boots", "platform": "Console"}, "2140881241": {"name": "08: Brogans (AR 107-129)", "category": "Boots", "platform": "Console"}, "2140881242": {"name": "09: Treads (AR 130-152)", "category": "Boots", "platform": "Console"}, "2140881243": {"name": "10: Heavy Sabatons (AR 154-174)", "category": "Boots", "platform": "Console"}, "2140881244": {"name": "11: Battle Greaves (AR 175-192)", "category": "Boots", "platform": "Console"}, "2140882329": {"name": "12: Balor Treads (AR 192-209)", "category": "Boots", "platform": "Console"}, "2140882330": {"name": "13: Astral Greaves (AR 210-221)", "category": "Boots", "platform": "Console"}, "2140882331": {"name": "14: Warlord Boots (AR 221-249)", "category": "Boots", "platform": "Console"}, "2140882332": {"name": "15: Doom Treads (AR 250-278)", "category": "Boots", "platform": "Console"}, "2140882333": {"name": "16: Sovereign Greaves (AR 280-308)", "category": "Boots", "platform": "Console"}, "2140882334": {"name": "17: Archon Greaves (AR 309-366)", "category": "Boots", "platform": "Console"}, "2140882335": {"name": "18: Rakkisgard Greaves (AR 367-512)", "category": "Boots", "platform": "Console"}, "2140882336": {"name": "19: Ascended Greaves (AR 513-590)", "category": "Boots", "platform": "Console"}, "931997596": {"name": "Art Test Boots 1", "category": "Boots", "platform": "Console"}, "931997597": {"name": "Art Test Boots 2", "category": "Boots", "platform": "Console"}, "931997598": {"name": "Art Test Boots 3", "category": "Boots", "platform": "Console"}, "931997599": {"name": "Art Test Boots 4", "category": "Boots", "platform": "Console"}, "931997600": {"name": "Art Test Boots 5", "category": "Boots", "platform": "Console"}, "691149644": {"name": "Art_Test_Boots_10 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997601": {"name": "Art_Test_Boots_6 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997602": {"name": "Art_Test_Boots_7 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997603": {"name": "Art_Test_Boots_8 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997604": {"name": "Art_Test_Boots_9 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940245561": {"name": "Legendary: Board Walkers", "category": "Boots", "platform": "Console"}, "1940101813": {"name": "Legendary: Boj Anglers", "category": "Boots", "platform": "Console"}, "-401226911": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "-401224467": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "261789197": {"name": "Legendary: Boj Anglers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979273143": {"name": "Legendary: Boots of Disregard", "category": "Boots", "platform": "Console"}, "1290781938": {"name": "Legendary: Conqueror's Sabatons (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1940317435": {"name": "Legendary: Fire Walkers", "category": "Boots", "platform": "Console"}, "-394111385": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "-394108941": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "261789203": {"name": "Legendary: Fire Walkers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-639326280": {"name": "Legendary: Footfalls of the Forbidden Lands", "category": "Boots", "platform": "Console"}, "1940353372": {"name": "Legendary: Ice Climbers", "category": "Boots", "platform": "Console"}, "-392925464": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "-392923020": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "261789204": {"name": "Legendary: Ice Climbers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979309080": {"name": "Legendary: Illusory Boots", "category": "Boots", "platform": "Console"}, "1979345017": {"name": "Legendary: Irontoe Mudsputters", "category": "Boots", "platform": "Console"}, "-396483227": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "-396480783": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "261789201": {"name": "Legendary: Lost Boys (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1940389309": {"name": "Legendary: Lut Socks", "category": "Boots", "platform": "Console"}, "-391739543": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "-391737099": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "261789205": {"name": "Legendary: Lut Socks (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941251797": {"name": "Legendary: The Crudest Boots", "category": "Boots", "platform": "Console"}, "-363277439": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "-363274995": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "261789229": {"name": "Legendary: The Crudest Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-2143372979": {"name": "Legendary: The Crudest Boots (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1941395545": {"name": "Set: Asheara's Finders", "category": "Boots", "platform": "Console"}, "261789233": {"name": "Set: Asheara's Lock (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-358533755": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "-358531311": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "261789238": {"name": "Set: Blackthorne's Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941575230": {"name": "Set: Blackthorne's Spurs", "category": "Boots", "platform": "Console"}, "-352604150": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-352601706": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-357347834": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "-357345390": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "261789234": {"name": "Set: Cain's Slippers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941431482": {"name": "Set: Cain's Travelers", "category": "Boots", "platform": "Console"}, "261789236": {"name": "Set: Captain Crimson's Deck Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941503356": {"name": "Set: Captain Crimson's Waders", "category": "Boots", "platform": "Console"}, "-354975992": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-354973548": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-801833428": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801653481": {"name": "Set: Eight-Demon Boots", "category": "Boots", "platform": "Console"}, "-801725355": {"name": "Set: Firebird's Tarsi", "category": "Boots", "platform": "Console"}, "-801833429": {"name": "Set: Hell Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800539434": {"name": "Set: Helltooth Greaves", "category": "Boots", "platform": "Console"}, "261789231": {"name": "Set: Immortal King's Pillar (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941323671": {"name": "Set: Immortal King's Stride", "category": "Boots", "platform": "Console"}, "-360905597": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "-360903153": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "1097296767": {"name": "Set: Inna's Sandals (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801617544": {"name": "Set: Jade Harvester's Swiftness", "category": "Boots", "platform": "Console"}, "-801689418": {"name": "Set: Marauder's Treads", "category": "Boots", "platform": "Console"}, "-801905302": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1941287734": {"name": "Set: Natalya's Bloody Footprints", "category": "Boots", "platform": "Console"}, "-362091518": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "-362089074": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "261789230": {"name": "Set: Natalya's Soul (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1097296766": {"name": "Set: Nilfur's Boast (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801761292": {"name": "Set: Raekor's Striders", "category": "Boots", "platform": "Console"}, "-801905304": {"name": "Set: Roland's Stride (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "-801905303": {"name": "Set: Sabaton of the Wastes (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800755056": {"name": "Set: Sabatons of Akkhan", "category": "Boots", "platform": "Console"}, "-353790071": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "-353787627": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "1941539293": {"name": "Set: Sage's Passage", "category": "Boots", "platform": "Console"}, "261789237": {"name": "Set: Sage's Seekers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-1957807619": {"name": "Set: Striders of Destiny (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800611308": {"name": "Set: The Shadow's Heels", "category": "Boots", "platform": "Console"}, "-800647245": {"name": "Set: Vyr's Swaggering Stance", "category": "Boots", "platform": "Console"}, "-801869365": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "261789232": {"name": "Set: Zunimassa's Journey (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941359608": {"name": "Set: Zunimassa's Trail", "category": "Boots", "platform": "Console"}, "-359719676": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "-359717232": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "1979344754": {"name": "legendary: Boots_104_p2 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940317172": {"name": "legendary: Fire Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800575371": {"name": "legendary: Seismic Treads", "category": "Boots", "platform": "Console"}, "-700134034": {"name": "legendary: Seismic Treads (Patch 2.2.0)", "category": "Boots", "platform": "Console"}}, "Bows": {"-2091504071": {"name": "02: Warden Bow (DPS 14.7-16.8)", "category": "Bows", "platform": "Console"}, "-2091504070": {"name": "03: Long Bow (DPS 20.3-22.4)", "category": "Bows", "platform": "Console"}, "-2091504069": {"name": "04: Recurve Bow (DPS 27.7-30.8)", "category": "Bows", "platform": "Console"}, "-2091504068": {"name": "05: Hunting Bow (DPS 34.3-36.4)", "category": "Bows", "platform": "Console"}, "-2091504067": {"name": "06: Battle Bow (DPS 41.3-43.4)", "category": "Bows", "platform": "Console"}, "-2091502983": {"name": "07: Siege Bow (DPS 44.1-46.2)", "category": "Bows", "platform": "Console"}, "-2091502982": {"name": "08: Maruki (DPS 55.3-57.4)", "category": "Bows", "platform": "Console"}, "-2091502981": {"name": "09: Yumi (DPS 64.4-66.5)", "category": "Bows", "platform": "Console"}, "-2091502980": {"name": "10: Composite Bow (DPS 749.9-77.0)", "category": "Bows", "platform": "Console"}, "-2091502979": {"name": "11: Daikyu (DPS 91.0-93.1)", "category": "Bows", "platform": "Console"}, "-2091502978": {"name": "12: Hankyu (DPS 107.1-109.2)", "category": "Bows", "platform": "Console"}, "-2091501894": {"name": "13: Higoyumi (DPS 140.7-142.8)", "category": "Bows", "platform": "Console"}, "-2091501893": {"name": "14: Ranger Bow (DPS 172.2-174.3)", "category": "Bows", "platform": "Console"}, "-2091501892": {"name": "15: Longshot Bow (DPS 207.2-211.4)", "category": "Bows", "platform": "Console"}, "-2091501891": {"name": "16: Sniper Bow (DPS 275.1-279.3)", "category": "Bows", "platform": "Console"}, "-2091501890": {"name": "17: Phantom Bow (DPS 322.0-326.2)", "category": "Bows", "platform": "Console"}, "-2091501889": {"name": "18: Revenant Bow (DPS 376.6-380.8)", "category": "Bows", "platform": "Console"}, "-2091500805": {"name": "19: Twinbow (DPS 513.1-517.3)", "category": "Bows", "platform": "Console"}, "-2091500804": {"name": "20: Doubleshot (DPS 670.6-674.8)", "category": "Bows", "platform": "Console"}, "687111997": {"name": "Art Test Bow 1", "category": "Bows", "platform": "Console"}, "687111998": {"name": "Art Test Bow 2", "category": "Bows", "platform": "Console"}, "687111999": {"name": "Art Test Bow 3", "category": "Bows", "platform": "Console"}, "687112000": {"name": "Art Test Bow 4", "category": "Bows", "platform": "Console"}, "687112001": {"name": "Art Test Bow 5", "category": "Bows", "platform": "Console"}, "1999703162": {"name": "Legendary: Amazonian Arch", "category": "Bows", "platform": "Console"}, "1142135055": {"name": "Legendary: Bow of the Lost Warlord (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1961789627": {"name": "Legendary: Cluckeye", "category": "Bows", "platform": "Console"}, "314470951": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "314473395": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "513724883": {"name": "Legendary: Cluckeye (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459958": {"name": "Legendary: Etrayu", "category": "Bows", "platform": "Console"}, "270591874": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "270594318": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "513724846": {"name": "Legendary: Etrayu (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459694": {"name": "Legendary: Etrayu (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1999595351": {"name": "Legendary: Kridershot", "category": "Bows", "platform": "Console"}, "1999667225": {"name": "Legendary: Leonine Bow of Hashir", "category": "Bows", "platform": "Console"}, "277707400": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "277709844": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "513724852": {"name": "Legendary: Longshot (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1999631288": {"name": "Legendary: Odyssey's End", "category": "Bows", "platform": "Console"}, "1961609942": {"name": "Legendary: Sydyru Crust", "category": "Bows", "platform": "Console"}, "1960711517": {"name": "Legendary: The Raven's Wing", "category": "Bows", "platform": "Console"}, "278893321": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "278895765": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "513724853": {"name": "Legendary: The Raven's Wing (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960675580": {"name": "Legendary: Unbound Bolt", "category": "Bows", "platform": "Console"}, "1960603706": {"name": "Legendary: Uskang", "category": "Bows", "platform": "Console"}, "275335558": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "275338002": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "513724850": {"name": "Legendary: Uskang (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960603442": {"name": "Legendary: Uskang (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "308541346": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "308543790": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "513724878": {"name": "Legendary: Venomhusk (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960747454": {"name": "Legendary: Windforce", "category": "Bows", "platform": "Console"}, "280079242": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "280081686": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "513724854": {"name": "Legendary: Windforce (Old-Legacy)", "category": "Bows", "platform": "Console"}}, "Bracers": {"-875944877": {"name": "02: Leather Cuffs (AR 16-19)", "category": "Bracers", "platform": "Console"}, "-875944876": {"name": "03: Bindings (AR 25-32)", "category": "Bracers", "platform": "Console"}, "-875944875": {"name": "04: Vambraces (AR 33-40)", "category": "Bracers", "platform": "Console"}, "-875944874": {"name": "05: Bracelets (AR 41-48)", "category": "Bracers", "platform": "Console"}, "-875943789": {"name": "067: Wristwraps (AR 63-75)", "category": "Bracers", "platform": "Console"}, "-875944873": {"name": "06: Mail Bands (AR 50-62)", "category": "Bracers", "platform": "Console"}, "-875943788": {"name": "08: Wristbands (AR 76-88)", "category": "Bracers", "platform": "Console"}, "-875943787": {"name": "09: Stabilizers (AR 90-102)", "category": "Bracers", "platform": "Console"}, "-875943786": {"name": "10: Wristguards (AR 103-124)", "category": "Bracers", "platform": "Console"}, "-875943785": {"name": "11: Wristplates (AR 125-137)", "category": "Bracers", "platform": "Console"}, "-875942700": {"name": "12: Armwraps (AR 137-149)", "category": "Bracers", "platform": "Console"}, "-875942699": {"name": "13: Armbands (AR 150-157)", "category": "Bracers", "platform": "Console"}, "-875942698": {"name": "14: Warbands (AR 158-178)", "category": "Bracers", "platform": "Console"}, "-875942697": {"name": "15: Armguards (AR 179-199)", "category": "Bracers", "platform": "Console"}, "-875942696": {"name": "16: Armplates (AR 200-220)", "category": "Bracers", "platform": "Console"}, "-875942695": {"name": "17: Razorspikes (AR 220-261)", "category": "Bracers", "platform": "Console"}, "-875942694": {"name": "18: Rakkisgard Bracelets (AR 262-365)", "category": "Bracers", "platform": "Console"}, "-875942693": {"name": "19: Ascended Bracers (AR 366-421)", "category": "Bracers", "platform": "Console"}, "-297950812": {"name": "Art Test Bracer 1", "category": "Bracers", "platform": "Console"}, "-297950811": {"name": "Art Test Bracer 2", "category": "Bracers", "platform": "Console"}, "-297950810": {"name": "Art Test Bracer 3", "category": "Bracers", "platform": "Console"}, "-297950809": {"name": "Art Test Bracer 4", "category": "Bracers", "platform": "Console"}, "-297950808": {"name": "Art Test Bracer 5", "category": "Bracers", "platform": "Console"}, "1861699995": {"name": "Grundo Gear (Patch 2.1.2)", "category": "Bracers", "platform": "Console"}, "962282719": {"name": "Legendary: Ancient Parthan Defenders", "category": "Bracers", "platform": "Console"}, "962462404": {"name": "Legendary: Custerian Wristguards", "category": "Bracers", "platform": "Console"}, "923291074": {"name": "Legendary: Gungdo Gear", "category": "Bracers", "platform": "Console"}, "403757070": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "403759514": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "955538490": {"name": "Legendary: Gungdo Gear (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923111389": {"name": "Legendary: Kethryes' Splint", "category": "Bracers", "platform": "Console"}, "923255137": {"name": "Legendary: Lacuni Prowlers", "category": "Bracers", "platform": "Console"}, "402571149": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "402573593": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538489": {"name": "Legendary: Lacuni Prowlers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962498341": {"name": "Legendary: Lucky Bowman's Armscales", "category": "Bracers", "platform": "Console"}, "962426467": {"name": "Legendary: Nemesis Bracers", "category": "Bracers", "platform": "Console"}, "923147326": {"name": "Legendary: Promise of Glory", "category": "Bracers", "platform": "Console"}, "399013386": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "399015830": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "955538486": {"name": "Legendary: Promise of Glory (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962318656": {"name": "Legendary: Reaper's Wraps", "category": "Bracers", "platform": "Console"}, "962390530": {"name": "Legendary: Sanguinary Vambraces", "category": "Bracers", "platform": "Console"}, "923183263": {"name": "Legendary: Slave Bonds", "category": "Bracers", "platform": "Console"}, "400199307": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "400201751": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "955538487": {"name": "Legendary: Slave Bonds (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923219200": {"name": "Legendary: Steady Strikers", "category": "Bracers", "platform": "Console"}, "401385228": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "401387672": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538488": {"name": "Legendary: Steady Strikers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923327011": {"name": "Legendary: Strongarm Bracers", "category": "Bracers", "platform": "Console"}, "404942991": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "404945435": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538491": {"name": "Legendary: Strongarm Bracers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962354593": {"name": "Legendary: Trag'Oul Coils", "category": "Bracers", "platform": "Console"}, "962246782": {"name": "Legendary: Warzechian Armguards", "category": "Bracers", "platform": "Console"}, "397827465": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "397829909": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "955538485": {"name": "Legendary: Wondrous Deflectors (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "955538493": {"name": "Set: Aughild's Demands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923398885": {"name": "Set: Aughild's Search", "category": "Bracers", "platform": "Console"}, "407314833": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "407317277": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "924297310": {"name": "Set: Demon's Animus", "category": "Bracers", "platform": "Console"}, "955538518": {"name": "Set: Demon's Manacles (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "436962858": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "436965302": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "924261373": {"name": "Set: Guardian's Aversion", "category": "Bracers", "platform": "Console"}, "955538517": {"name": "Set: Guardian's Bands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "435776937": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "435779381": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "1784952569": {"name": "Set: Krelm's Buff Bracers", "category": "Bracers", "platform": "Console"}, "1786138490": {"name": "Set: Shackles of the Invoker", "category": "Bracers", "platform": "Console"}, "1861701111": {"name": "legendary: Drakon's Lesson (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861699992": {"name": "legendary: Mortick's Brace (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861701087": {"name": "legendary: Spirit Guards (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}}, "Ceremonial Knives": {"-635269583": {"name": "01: Stone Knife (DPS 11.2-12.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269582": {"name": "02: Kris Blade (DPS 14.7-16.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269581": {"name": "03: Jagged Edge (DPS 21.0-23.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269580": {"name": "04: Flint Knife (DPS 30.8-32.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268494": {"name": "05: Sacrifice Blade (DPS 39.2-41.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268493": {"name": "06: Flayer (DPS 48.3-50.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268492": {"name": "07: Bone Saw (DPS 62.3-64.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268491": {"name": "08: Beast Tusk (DPS 84.0-86.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267405": {"name": "09: Scalping Razor (DPS 112.7-114.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267404": {"name": "10: Obsidian Edge (DPS 137.2-139.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267403": {"name": "11: Skin Cutter (DPS 165.2-169.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267402": {"name": "12: Exquisite Knife (DPS 190.4-194.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267401": {"name": "13: Flesh Ripper (DPS 219.1-223.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267400": {"name": "14: Veil Piercer (DPS 251.3-257.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266316": {"name": "15: Odsidian Skiver (DPS 336.7-340.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266315": {"name": "16: Tecpat1 (DPS 410.2-414.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-97045282": {"name": "Art Test CeremonialDagger 1", "category": "Ceremonial Knives", "platform": "Console"}, "-97045281": {"name": "Art Test CeremonialDagger 2", "category": "Ceremonial Knives", "platform": "Console"}, "-97045280": {"name": "Art Test CeremonialDagger 3", "category": "Ceremonial Knives", "platform": "Console"}, "-97045279": {"name": "Art Test CeremonialDagger 4", "category": "Ceremonial Knives", "platform": "Console"}, "-97045278": {"name": "Art Test CeremonialDagger 5", "category": "Ceremonial Knives", "platform": "Console"}, "1784443031": {"name": "Legendary: Anessazi Edge", "category": "Ceremonial Knives", "platform": "Console"}, "-1242999421": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1242996977": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684207": {"name": "Legendary: Anessazi Edge (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784514905": {"name": "Legendary: Deadly Rebirth", "category": "Ceremonial Knives", "platform": "Console"}, "1784694590": {"name": "Legendary: Last Breath", "category": "Ceremonial Knives", "platform": "Console"}, "-1234697974": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1234695530": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684214": {"name": "Legendary: Last Breath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784622716": {"name": "Legendary: Living Umbral Oath", "category": "Ceremonial Knives", "platform": "Console"}, "-1240627579": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1240625135": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684209": {"name": "Legendary: Moon Slayer (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1823614361": {"name": "Legendary: Rhen'ho Flayer", "category": "Ceremonial Knives", "platform": "Console"}, "916911834": {"name": "Legendary: Sacred Harvester (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "595814643": {"name": "Legendary: Sacrificer", "category": "Ceremonial Knives", "platform": "Console"}, "1823578424": {"name": "Legendary: Starmetal Kukri", "category": "Ceremonial Knives", "platform": "Console"}, "916911835": {"name": "Legendary: The Dagger of Darts (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "1784478968": {"name": "Legendary: The Gidbinn", "category": "Ceremonial Knives", "platform": "Console"}, "-1241813500": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1241811056": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684208": {"name": "Legendary: The Gidbinn (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784550842": {"name": "Legendary: The Spider Queen's Grasp", "category": "Ceremonial Knives", "platform": "Console"}, "-1237069816": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1237067372": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684212": {"name": "Legendary: Umbral Oath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239441658": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239439214": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684210": {"name": "Legendary: Ziggurat Tooth (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684240": {"name": "Set: Hallowed Sacrifice (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203864028": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203861584": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1785628952": {"name": "Set: Hallowed Sufferance", "category": "Ceremonial Knives", "platform": "Console"}, "1784730527": {"name": "Set: Manajuma's Carving Knife", "category": "Ceremonial Knives", "platform": "Console"}, "-1233512053": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1233509609": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684215": {"name": "Set: Manajuma's Ritual Cutter (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}}, "Chest": {"258855260": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783385": {"name": "Set: Cuirass of the Wastes (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819322": {"name": "Set: Harness of Truth (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783386": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "259969569": {"name": "Set: Sunwuko's Soul (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819323": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}}, "Chest Armor": {"1612257705": {"name": "02: Leather Doublet (AR 18-21)", "category": "Chest Armor", "platform": "Console"}, "1612257706": {"name": "03: Brigandine Coat (AR 33-38)", "category": "Chest Armor", "platform": "Console"}, "1612257707": {"name": "04: Chain Mail (AR 51-68)", "category": "Chest Armor", "platform": "Console"}, "1612257708": {"name": "05: Splint Cuirass (AR 69-86)", "category": "Chest Armor", "platform": "Console"}, "1612257709": {"name": "06: Plate Mail (AR 87-107)", "category": "Chest Armor", "platform": "Console"}, "1612258793": {"name": "07: Stygian Harness (AR 108-137)", "category": "Chest Armor", "platform": "Console"}, "1612258794": {"name": "08: Etched Jacket (AR 138-167)", "category": "Chest Armor", "platform": "Console"}, "1612258795": {"name": "09: Jazeraint Mail (AR 168-197)", "category": "Chest Armor", "platform": "Console"}, "1612258796": {"name": "10: Battle Armor (AR 198-224)", "category": "Chest Armor", "platform": "Console"}, "1612258797": {"name": "11: Boneweave Hauberk (AR 225-247)", "category": "Chest Armor", "platform": "Console"}, "1612259882": {"name": "12: Balor Armor (AR 247-269)", "category": "Chest Armor", "platform": "Console"}, "1612259883": {"name": "13: Astral Mail (AR 270-284)", "category": "Chest Armor", "platform": "Console"}, "1612259884": {"name": "14: Warlord Plate (AR 285-322)", "category": "Chest Armor", "platform": "Console"}, "1612259885": {"name": "15: Doom Armor (AR 322-359)", "category": "Chest Armor", "platform": "Console"}, "1612259886": {"name": "16: Sovereign Mail (AR 360-397)", "category": "Chest Armor", "platform": "Console"}, "1612259887": {"name": "17: Archon Armor (AR 397-471)", "category": "Chest Armor", "platform": "Console"}, "1612259888": {"name": "18: Rakkisgard Armor (AR 472-659)", "category": "Chest Armor", "platform": "Console"}, "1612259889": {"name": "19: Ascended Armor (AR 660-759)", "category": "Chest Armor", "platform": "Console"}, "1937623756": {"name": "Art Test Chest 1", "category": "Chest Armor", "platform": "Console"}, "1937623757": {"name": "Art Test Chest 2", "category": "Chest Armor", "platform": "Console"}, "1937623758": {"name": "Art Test Chest 3", "category": "Chest Armor", "platform": "Console"}, "1937623759": {"name": "Art Test Chest 4", "category": "Chest Armor", "platform": "Console"}, "1937623760": {"name": "Art Test Chest 5", "category": "Chest Armor", "platform": "Console"}, "1316774087": {"name": "Legendary: Aquila Cuirass", "category": "Chest Armor", "platform": "Console"}, "503794611": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "503797055": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016991": {"name": "Legendary: Aquila Cuirass (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354723559": {"name": "Legendary: Armor of the Kind Regent", "category": "Chest Armor", "platform": "Console"}, "1316702213": {"name": "Legendary: Chaingmail", "category": "Chest Armor", "platform": "Console"}, "501422769": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "501425213": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016989": {"name": "Legendary: Chaingmail (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1315731914": {"name": "Legendary: Cindercoat", "category": "Chest Armor", "platform": "Console"}, "469402902": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "469405346": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016962": {"name": "Legendary: Cindercoat (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "883162595": {"name": "Legendary: Conqueror's Cuirass (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "1315552229": {"name": "Legendary: Goldskin", "category": "Chest Armor", "platform": "Console"}, "463473297": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "463475741": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016957": {"name": "Legendary: Goldskin (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316989709": {"name": "Legendary: Heart of Iron", "category": "Chest Armor", "platform": "Console"}, "510910137": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "510912581": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016997": {"name": "Legendary: Heart of Iron (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1821181577": {"name": "Legendary: Heart of the Titans", "category": "Chest Armor", "platform": "Console"}, "1317025646": {"name": "Legendary: Mantle of the Rydraelm", "category": "Chest Armor", "platform": "Console"}, "512096058": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "512098502": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016998": {"name": "Legendary: Robes of the Rydraelm (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354687622": {"name": "Legendary: Shi Mizu's Haori", "category": "Chest Armor", "platform": "Console"}, "1315588166": {"name": "Legendary: Tyrael's Might", "category": "Chest Armor", "platform": "Console"}, "464659218": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "464661662": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016958": {"name": "Legendary: Tyrael's Might (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "547673688": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "547676132": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318103756": {"name": "Set: Aughild's Rule", "category": "Chest Armor", "platform": "Console"}, "172017028": {"name": "Set: Aughild's Vestments (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1262779559": {"name": "Set: Blackthorne's Jacket (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "-115330289": {"name": "Set: Blackthorne's Surcoat", "category": "Chest Armor", "platform": "Console"}, "488990459": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "488992903": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172017027": {"name": "Set: Born's Carapace (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318067819": {"name": "Set: Born's Frozen Soul", "category": "Chest Armor", "platform": "Console"}, "546487767": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "546490211": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259933632": {"name": "Set: Breastplate of Akkhan", "category": "Chest Armor", "platform": "Console"}, "172017029": {"name": "Set: Demon's Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "548859609": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "548862053": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318139693": {"name": "Set: Demon's Marrow", "category": "Chest Armor", "platform": "Console"}, "258963333": {"name": "Set: Firebird's Breast", "category": "Chest Armor", "platform": "Console"}, "259035207": {"name": "Set: Heart of the Crashing Wave", "category": "Chest Armor", "platform": "Console"}, "260149254": {"name": "Set: Helltooth Tunic", "category": "Chest Armor", "platform": "Console"}, "1316810024": {"name": "Set: Immortal King's Eternal Reign", "category": "Chest Armor", "platform": "Console"}, "504980532": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "504982976": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016992": {"name": "Set: Immortal King's Soul Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016994": {"name": "Set: Inna's Refuge (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316881898": {"name": "Set: Inna's Vast Expanse", "category": "Chest Armor", "platform": "Console"}, "507352374": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "507354818": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259071144": {"name": "Set: Jade Harvester's Peace", "category": "Chest Armor", "platform": "Console"}, "258999270": {"name": "Set: Marauder's Carapace", "category": "Chest Armor", "platform": "Console"}, "258927396": {"name": "Set: Raekor's Heart", "category": "Chest Armor", "platform": "Console"}, "258783384": {"name": "Set: Roland's Bearing (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "172016993": {"name": "Set: Tal Rasha's Guardianship (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316845961": {"name": "Set: Tal Rasha's Relentless Pursuit", "category": "Chest Armor", "platform": "Console"}, "506166453": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "506168897": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "260077380": {"name": "Set: The Shadow's Bane", "category": "Chest Armor", "platform": "Console"}, "260041443": {"name": "Set: Vyr's Astonishing Aura", "category": "Chest Armor", "platform": "Console"}, "1316917835": {"name": "Set: Zunimassa's Marrow", "category": "Chest Armor", "platform": "Console"}, "508538295": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "508540739": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016995": {"name": "Set: Zunimassa's Vessel (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}}, "Chests": {"1937623762": {"name": "Art_Test_Chest_7 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623763": {"name": "Art_Test_Chest_8 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623764": {"name": "Art_Test_Chest_9 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}}, "Cloaks": {"40855419": {"name": "02: Shroud (AR 36-41)", "category": "Cloaks", "platform": "Console"}, "40855420": {"name": "03: Cape (AR 60-69)", "category": "Cloaks", "platform": "Console"}, "40855421": {"name": "04: Tabard (AR 84-113)", "category": "Cloaks", "platform": "Console"}, "40856507": {"name": "05: Wrap (AR 114-149)", "category": "Cloaks", "platform": "Console"}, "40856508": {"name": "06: Lurker Shroud (AR 150-185)", "category": "Cloaks", "platform": "Console"}, "40856509": {"name": "07: Talma (AR 186-232)", "category": "Cloaks", "platform": "Console"}, "40856510": {"name": "08: Cardinal (AR 232-254)", "category": "Cloaks", "platform": "Console"}, "40857596": {"name": "09: Veteran Cloak (AR 255-284)", "category": "Cloaks", "platform": "Console"}, "40857597": {"name": "10: Death Shroud (AR 385-322)", "category": "Cloaks", "platform": "Console"}, "40857598": {"name": "11: Stalker Cape (AR 322-359)", "category": "Cloaks", "platform": "Console"}, "40857599": {"name": "12: Dread Cloak (AR 360-472)", "category": "Cloaks", "platform": "Console"}, "40857600": {"name": "13: Rakkisgard Cloak (AR 472-659)", "category": "Cloaks", "platform": "Console"}, "40857601": {"name": "14: Ascended Cloak (AR 660-759)", "category": "Cloaks", "platform": "Console"}, "2105367871": {"name": "Art Test Cloak 1", "category": "Cloaks", "platform": "Console"}, "2105367872": {"name": "Art Test Cloak 2", "category": "Cloaks", "platform": "Console"}, "2105367873": {"name": "Art Test Cloak 3", "category": "Cloaks", "platform": "Console"}, "2105367874": {"name": "Art Test Cloak 4", "category": "Cloaks", "platform": "Console"}, "2105367875": {"name": "Art Test Cloak 5", "category": "Cloaks", "platform": "Console"}, "221665681": {"name": "Legendary Cloak 002 p1", "category": "Cloaks", "platform": "Console"}, "221773756": {"name": "Legendary: Beckon Sail", "category": "Cloaks", "platform": "Console"}, "-1271477944": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1271475500": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235532": {"name": "Legendary: Beckon Sail (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260765401": {"name": "Legendary: Blackfeather", "category": "Cloaks", "platform": "Console"}, "221630008": {"name": "Legendary: Cape of the Dark Night", "category": "Cloaks", "platform": "Console"}, "-1276221628": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1276219184": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235536": {"name": "Legendary: Cape of the Dark Night (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260801338": {"name": "Legendary: Cloak of Deception", "category": "Cloaks", "platform": "Console"}, "221665945": {"name": "Legendary: The Cloak of the Garwulf", "category": "Cloaks", "platform": "Console"}, "-1275035707": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1275033263": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235535": {"name": "Legendary: The Inquisitor (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "221809693": {"name": "Set: Natalya's Embrace", "category": "Cloaks", "platform": "Console"}, "-1270292023": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1270289579": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235531": {"name": "Set: Natalya's Shadow (Old-Legacy)", "category": "Cloaks", "platform": "Console"}}, "Consumables": {"-1691237125": {"name": "Blood Shard", "category": "Consumables", "platform": "Console"}, "-2018707791": {"name": "Bottomless Potion Of Fear (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-2018707790": {"name": "Bottomless Potion of Amplification (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707793": {"name": "Bottomless Potion of Kulle Aid", "category": "Consumables", "platform": "Console"}, "-2018707794": {"name": "Bottomless Potion of Mutilation", "category": "Consumables", "platform": "Console"}, "-2018707796": {"name": "Bottomless Potion of Regeneration", "category": "Consumables", "platform": "Console"}, "-2018707792": {"name": "Bottomless Potion of Rejuvenation", "category": "Consumables", "platform": "Console"}, "510979313": {"name": "Bottomless Potion of Rejuvenation (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707797": {"name": "Bottomless Potion of the Diamond", "category": "Consumables", "platform": "Console"}, "-2018707795": {"name": "Bottomless Potion of the Leech", "category": "Consumables", "platform": "Console"}, "-2018707798": {"name": "Bottomless Potion of the Tower", "category": "Consumables", "platform": "Console"}, "727989467": {"name": "Bottomless Regular Health Potion (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618072": {"name": "Consumable_Potion_Bloodshard_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "736462346": {"name": "Consumable_Potion_Bloodshard_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618138": {"name": "Consumable_Potion_Bloodshard_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618270": {"name": "Consumable_Potion_Bloodshard_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764252": {"name": "Consumable_Potion_Gold_Find_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-418681010": {"name": "Consumable_Potion_Gold_Find_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764318": {"name": "Consumable_Potion_Gold_Find_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764450": {"name": "Consumable_Potion_Gold_Find_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167362": {"name": "Consumable_Potion_XP_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1032379504": {"name": "Consumable_Potion_XP_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167296": {"name": "Consumable_Potion_XP_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167164": {"name": "Consumable_Potion_XP_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2142362846": {"name": "Health Potion", "category": "Consumables", "platform": "Console"}, "-650776931": {"name": "Infernal Machine", "category": "Consumables", "platform": "Console"}, "1054965529": {"name": "Infernal Machine of Bones", "category": "Consumables", "platform": "Console"}, "1458185494": {"name": "Infernal Machine of Evil", "category": "Consumables", "platform": "Console"}, "-1506243402": {"name": "Infernal Machine of Gluttony", "category": "Consumables", "platform": "Console"}, "-1672611564": {"name": "Infernal Machine of War", "category": "Consumables", "platform": "Console"}, "-1055802742": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1927699898": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-1990624170": {"name": "PowerGlobe", "category": "Consumables", "platform": "Console"}, "-1407876474": {"name": "PowerGlobe NoFlippy", "category": "Consumables", "platform": "Console"}, "1604670149": {"name": "PowerGlobe v2 x1", "category": "Consumables", "platform": "Console"}, "1554449877": {"name": "PowerGlobe v2 x1 NoFlippy", "category": "Consumables", "platform": "Console"}, "-767886865": {"name": "PvP_HealingDude", "category": "Consumables", "platform": "Console"}, "1844495708": {"name": "Ramaladni's Gift", "category": "Consumables", "platform": "Console"}, "-2108322324": {"name": "Ramaladni's Gift (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-1629755675": {"name": "Rare Gift (RoS)", "category": "Consumables", "platform": "Console"}, "750709043": {"name": "ShrineGlobe Blessed", "category": "Consumables", "platform": "Console"}, "-783958152": {"name": "ShrineGlobe Enlightened", "category": "Consumables", "platform": "Console"}, "1754475188": {"name": "ShrineGlobe Fortune", "category": "Consumables", "platform": "Console"}, "1126841672": {"name": "ShrineGlobe Frenzied", "category": "Consumables", "platform": "Console"}, "-1436918535": {"name": "Steak10", "category": "Consumables", "platform": "Console"}, "-1436918530": {"name": "Steak15", "category": "Consumables", "platform": "Console"}, "-1436918502": {"name": "Steak20", "category": "Consumables", "platform": "Console"}, "-1436918497": {"name": "Steak25", "category": "Consumables", "platform": "Console"}, "-1436918469": {"name": "Steak30", "category": "Consumables", "platform": "Console"}, "-1436918464": {"name": "Steak35", "category": "Consumables", "platform": "Console"}, "-1436918436": {"name": "Steak40", "category": "Consumables", "platform": "Console"}, "346908589": {"name": "Steak5", "category": "Consumables", "platform": "Console"}, "450956006": {"name": "p1 tiered rifts Orb", "category": "Consumables", "platform": "Console"}}, "Cosmetics": {"703352254": {"name": "Art_Test_Pet_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352255": {"name": "Art_Test_Pet_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352256": {"name": "Art_Test_Pet_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352257": {"name": "Art_Test_Pet_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352258": {"name": "Art_Test_Pet_5 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352259": {"name": "Art_Test_Pet_6 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555709": {"name": "Art_Test_Wings_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555710": {"name": "Art_Test_Wings_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555711": {"name": "Art_Test_Wings_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555712": {"name": "Art_Test_Wings_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1736870778": {"name": "Blade Wings", "category": "Cosmetics", "platform": "Console"}, "2015178386": {"name": "Blade Wings (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508877": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508876": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "988742338": {"name": "Cosmetic_Pet_FallenHound_Skeletal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508875": {"name": "Cosmetic_Pet_teddyBear_04 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1464439640": {"name": "Cosmetic_Wings_Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834901": {"name": "Cosmetic_Wings_bat_02 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834902": {"name": "Cosmetic_Wings_bat_03 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1424453175": {"name": "Crimson Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "1464422100": {"name": "Demon Soaring (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208405024": {"name": "Eldritch Embrace (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1081301157": {"name": "Eternal Flame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1030142027": {"name": "Eternal Light (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1815774861": {"name": "Fingers of Terror (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380235": {"name": "Frame: Angelic (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264991": {"name": "Frame: Base Frame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380233": {"name": "Frame: Bone (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380234": {"name": "Frame: Deathshead (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380230": {"name": "Frame: Molton (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264990": {"name": "Frame: Paragon 1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764818": {"name": "Frame: Paragon 10 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114304450": {"name": "Frame: Paragon 100 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764851": {"name": "Frame: Paragon 20 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114305539": {"name": "Frame: Paragon 200 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764884": {"name": "Frame: Paragon 30 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764917": {"name": "Frame: Paragon 40 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114307717": {"name": "Frame: Paragon 400 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764950": {"name": "Frame: Paragon 50 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114308806": {"name": "Frame: Paragon 500 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764983": {"name": "Frame: Paragon 60 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114309895": {"name": "Frame: Paragon 600 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765016": {"name": "Frame: Paragon 70 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114310984": {"name": "Frame: Paragon 700 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765049": {"name": "Frame: Paragon 80 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114312073": {"name": "Frame: Paragon 800 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765082": {"name": "Frame: Paragon 90 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114306628": {"name": "Frame: Paraogn 300 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380199": {"name": "Frame: Season 3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380228": {"name": "Frame: Staind Glass Azure (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380202": {"name": "Frame: Staind Glass Orange (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380201": {"name": "Frame: Staind Glass Purple (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380227": {"name": "Frame: Staind Glass Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380229": {"name": "Frame: Staind Glass Teal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380203": {"name": "Frame: Staind Glass Yellow (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380231": {"name": "Frame: Steadfast (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380198": {"name": "Frame: Storm (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380232": {"name": "Frame: Thorns (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380200": {"name": "Frame: Whimseyshire (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "211305012": {"name": "Harbringer of Destruction (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "262300867": {"name": "Heaven't Might (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-922089455": {"name": "Knights of Westmarch (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1412314502": {"name": "Liber Canis Mortui", "category": "Cosmetics", "platform": "Console"}, "-1527508878": {"name": "Mr Bear (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208454467": {"name": "Pieces of Hatred (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "517654224": {"name": "Probe (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "291388174": {"name": "Spike (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1647814559": {"name": "Ten Pounder (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1454306710": {"name": "The Light of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-2072242152": {"name": "The Pillars of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-937743655": {"name": "Warlords Of Draenor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-762694428": {"name": "Warsong Pennant", "category": "Cosmetics", "platform": "Console"}, "-1364948604": {"name": "Wings of Valor", "category": "Cosmetics", "platform": "Console"}, "1464422747": {"name": "Wings of Valor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}}, "Crafting Components": {"-784029520": {"name": "Angelic Shard", "category": "Crafting Components", "platform": "Console"}, "-1585802162": {"name": "Arcane Dust", "category": "Crafting Components", "platform": "Console"}, "2048505008": {"name": "Behistun Rune", "category": "Crafting Components", "platform": "Console"}, "-1993550104": {"name": "Black Mushroom", "category": "Crafting Components", "platform": "Console"}, "1864276820": {"name": "Bloody Pincer", "category": "Crafting Components", "platform": "Console"}, "-875022940": {"name": "Born's Key", "category": "Crafting Components", "platform": "Console"}, "-229384987": {"name": "Captured Nightmare", "category": "Crafting Components", "platform": "Console"}, "1016443205": {"name": "Captured Soul", "category": "Crafting Components", "platform": "Console"}, "903645542": {"name": "Cartographer's Toolkit", "category": "Crafting Components", "platform": "Console"}, "2064572165": {"name": "Common Debris", "category": "Crafting Components", "platform": "Console"}, "-821947350": {"name": "Cultist Blood", "category": "Crafting Components", "platform": "Console"}, "2087837753": {"name": "Death's Breath", "category": "Crafting Components", "platform": "Console"}, "2000469169": {"name": "Defiled Doll", "category": "Crafting Components", "platform": "Console"}, "-1761931437": {"name": "Demon Skin", "category": "Crafting Components", "platform": "Console"}, "-152489231": {"name": "Demonic Essence", "category": "Crafting Components", "platform": "Console"}, "-645052297": {"name": "Devil's Fang", "category": "Crafting Components", "platform": "Console"}, "437938885": {"name": "Element of Celerity", "category": "Crafting Components", "platform": "Console"}, "2064572134": {"name": "Encrusted Hoof (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-1725926578": {"name": "Essence of the Twin Seas", "category": "Crafting Components", "platform": "Console"}, "-1506992994": {"name": "Eternal Power Capsule", "category": "Crafting Components", "platform": "Console"}, "2064572166": {"name": "Exquisite Essence", "category": "Crafting Components", "platform": "Console"}, "1726149320": {"name": "Eyes of the Dead", "category": "Crafting Components", "platform": "Console"}, "2064572068": {"name": "Fallen Tooth (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "2064572168": {"name": "Fiery Brimstone", "category": "Crafting Components", "platform": "Console"}, "2073430088": {"name": "Forgotten Soul", "category": "Crafting Components", "platform": "Console"}, "937036308": {"name": "Frozen Blood", "category": "Crafting Components", "platform": "Console"}, "-799974399": {"name": "Gibbering Gemstone", "category": "Crafting Components", "platform": "Console"}, "-1299206911": {"name": "Glowing Ore", "category": "Crafting Components", "platform": "Console"}, "-730966965": {"name": "Griswold's Scribblings", "category": "Crafting Components", "platform": "Console"}, "-958180196": {"name": "Heart of Evil", "category": "Crafting Components", "platform": "Console"}, "460247356": {"name": "Hilt of the Silver Wolf", "category": "Crafting Components", "platform": "Console"}, "314328565": {"name": "Human Cartilage", "category": "Crafting Components", "platform": "Console"}, "-1624623846": {"name": "Idol of Terror", "category": "Crafting Components", "platform": "Console"}, "2064572167": {"name": "Iridescent Tear", "category": "Crafting Components", "platform": "Console"}, "-661382443": {"name": "Iron Wolves Doctrine", "category": "Crafting Components", "platform": "Console"}, "1102953247": {"name": "Leoric's Regret", "category": "Crafting Components", "platform": "Console"}, "-629520052": {"name": "Leoric's Shinbone", "category": "Crafting Components", "platform": "Console"}, "725082635": {"name": "Liquid Rainbow", "category": "Crafting Components", "platform": "Console"}, "-1402576366": {"name": "Living Flame", "category": "Crafting Components", "platform": "Console"}, "2064572101": {"name": "Lizard Eye (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "291872615": {"name": "Lyekurn's Diary", "category": "Crafting Components", "platform": "Console"}, "1835813454": {"name": "Maghda's Tormented Soul", "category": "Crafting Components", "platform": "Console"}, "-1018735616": {"name": "Mystical Source", "category": "Crafting Components", "platform": "Console"}, "-1020906970": {"name": "Page of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-667291726": {"name": "Page of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "526997101": {"name": "Phial of Weakness", "category": "Crafting Components", "platform": "Console"}, "778194127": {"name": "Quaking Vial", "category": "Crafting Components", "platform": "Console"}, "1114256397": {"name": "Reaper's Fear", "category": "Crafting Components", "platform": "Console"}, "-363607620": {"name": "Reusable Parts", "category": "Crafting Components", "platform": "Console"}, "280425627": {"name": "Rydraelm Tome", "category": "Crafting Components", "platform": "Console"}, "-830982818": {"name": "Shard of Entsteig Plate", "category": "Crafting Components", "platform": "Console"}, "-1176010511": {"name": "Shattered Core", "category": "Crafting Components", "platform": "Console"}, "2064572100": {"name": "Shimmering Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2114382103": {"name": "Shimmering Quill", "category": "Crafting Components", "platform": "Console"}, "-248569447": {"name": "Shuddering Demon Bone", "category": "Crafting Components", "platform": "Console"}, "-1810945531": {"name": "Skelon's Dice", "category": "Crafting Components", "platform": "Console"}, "-997569662": {"name": "Skull of Raylend", "category": "Crafting Components", "platform": "Console"}, "2064572067": {"name": "Subtle Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2113447741": {"name": "Sydyru Bone", "category": "Crafting Components", "platform": "Console"}, "-1253986069": {"name": "Symbol of the Guardian Brotherhood", "category": "Crafting Components", "platform": "Console"}, "494826242": {"name": "Tome of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-722757874": {"name": "Tome of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-970366835": {"name": "Tome of Secrets (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-443730551": {"name": "Torn Soul", "category": "Crafting Components", "platform": "Console"}, "1075049130": {"name": "Urn of Quickening", "category": "Crafting Components", "platform": "Console"}, "-605947593": {"name": "Veiled Crystal", "category": "Crafting Components", "platform": "Console"}, "1998976972": {"name": "Vengeful Eye", "category": "Crafting Components", "platform": "Console"}, "2029265596": {"name": "Vial of Putridness", "category": "Crafting Components", "platform": "Console"}, "1016299457": {"name": "White Oak Splinter", "category": "Crafting Components", "platform": "Console"}, "-799868536": {"name": "Wirt's Bell", "category": "Crafting Components", "platform": "Console"}, "2064572133": {"name": "Wishful Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "1098021531": {"name": "Wooden Stake", "category": "Crafting Components", "platform": "Console"}, "2103664575": {"name": "Woven Plate", "category": "Crafting Components", "platform": "Console"}, "-1824155952": {"name": "Writhing Spine", "category": "Crafting Components", "platform": "Console"}, "-747908647": {"name": "px_HoradricReagent_01 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908646": {"name": "px_HoradricReagent_02 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908645": {"name": "px_HoradricReagent_03 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908644": {"name": "px_HoradricReagent_04 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908643": {"name": "px_HoradricReagent_05 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}}, "Crafting Plans, Jeweler": {"429567911": {"name": "Design: Flawless Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521994629": {"name": "Design: Flawless Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147380749": {"name": "Design: Flawless Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872863289": {"name": "Design: Flawless Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171649812": {"name": "Design: Flawless Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521743063": {"name": "Design: Flawless Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147129183": {"name": "Design: Flawless Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872611723": {"name": "Design: Flawless Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1540480229": {"name": "Design: Hellfire Amulet (Patch 1.2.0)", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-384404829": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1792019289": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171541998": {"name": "Design: Marquise Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521850877": {"name": "Design: Marquise Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147236997": {"name": "Design: Marquise Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872719537": {"name": "Design: Marquise Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171613874": {"name": "Design: Perfect Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521779001": {"name": "Design: Perfect Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147165121": {"name": "Design: Perfect Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872647661": {"name": "Design: Perfect Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171577936": {"name": "Design: Radiant Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521814939": {"name": "Design: Radiant Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147201059": {"name": "Design: Radiant Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872683599": {"name": "Design: Radiant Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171434184": {"name": "Design: Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429531973": {"name": "Design: Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521958691": {"name": "Design: Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147344811": {"name": "Design: Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872827351": {"name": "Design: Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}}, "Crafting Plans, Smith": {"-1427518108": {"name": "Legendary Plan: Archfiend Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1046516600": {"name": "Legendary Plan: Atrophy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1423568820": {"name": "Legendary Plan: Bitterness", "category": "Crafting Plans, Smith", "platform": "Console"}, "-380290097": {"name": "Legendary Plan: Black Bone Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1418151206": {"name": "Legendary Plan: Blitzbolter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-912856835": {"name": "Legendary Plan: Blood-Magic Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2000896011": {"name": "Legendary Plan: Blood-Magic Edge", "category": "Crafting Plans, Smith", "platform": "Console"}, "867919825": {"name": "Legendary Plan: Board Walkers", "category": "Crafting Plans, Smith", "platform": "Console"}, "-412066328": {"name": "Legendary Plan: Cataclysm", "category": "Crafting Plans, Smith", "platform": "Console"}, "1713442269": {"name": "Legendary Plan: Cinder Switch", "category": "Crafting Plans, Smith", "platform": "Console"}, "612002290": {"name": "Legendary Plan: Corruption", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1413614420": {"name": "Legendary Plan: Cosmic Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "421386501": {"name": "Legendary Plan: Deadeye", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1911170977": {"name": "Legendary Plan: Demon Claw", "category": "Crafting Plans, Smith", "platform": "Console"}, "999120591": {"name": "Legendary Plan: Demon Hand", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1426610660": {"name": "Legendary Plan: Devastator", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1326018783": {"name": "Legendary Plan: Earthshatter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1003069110": {"name": "Legendary Plan: Fire Brand", "category": "Crafting Plans, Smith", "platform": "Console"}, "957458384": {"name": "Legendary Plan: Fleeting Strap", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1639510640": {"name": "Legendary Plan: Gehennas", "category": "Crafting Plans, Smith", "platform": "Console"}, "780377031": {"name": "Legendary Plan: Golden Scourge", "category": "Crafting Plans, Smith", "platform": "Console"}, "412214125": {"name": "Legendary Plan: Harvest Moon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-501637898": {"name": "Legendary Plan: Hellish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-846348803": {"name": "Legendary Plan: Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "253048194": {"name": "Legendary Plan: Infernal Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-103899531": {"name": "Legendary Plan: Kethryes' Splint", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904674800": {"name": "Legendary Plan: Lai Yui's Persuader", "category": "Crafting Plans, Smith", "platform": "Console"}, "-168948640": {"name": "Legendary Plan: Lai Yui's Taiji", "category": "Crafting Plans, Smith", "platform": "Console"}, "1029528340": {"name": "Legendary Plan: Living Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "-405238050": {"name": "Legendary Plan: Longshot", "category": "Crafting Plans, Smith", "platform": "Console"}, "269805368": {"name": "Legendary Plan: Lost Boys", "category": "Crafting Plans, Smith", "platform": "Console"}, "244699910": {"name": "Legendary Plan: Mantle of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "2012779291": {"name": "Legendary Plan: Mark of The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "1744959696": {"name": "Legendary Plan: Night's Reaping", "category": "Crafting Plans, Smith", "platform": "Console"}, "645585264": {"name": "Legendary Plan: Nightmarish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2142082753": {"name": "Legendary Plan: Pendergrasps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-451796586": {"name": "Legendary Plan: Penders Purchase", "category": "Crafting Plans, Smith", "platform": "Console"}, "-216958038": {"name": "Legendary Plan: Piro Marella", "category": "Crafting Plans, Smith", "platform": "Console"}, "1162824884": {"name": "Legendary Plan: Quick Draw Belt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-64692264": {"name": "Legendary Plan: Reaper's Wraps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1654685887": {"name": "Legendary Plan: Robes of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904818548": {"name": "Legendary Plan: Rozpedin's Force", "category": "Crafting Plans, Smith", "platform": "Console"}, "1548578205": {"name": "Legendary Plan: Rozpedin's Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1861702115": {"name": "Legendary Plan: Ruinstoke", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2122397885": {"name": "Legendary Plan: Seven Sins", "category": "Crafting Plans, Smith", "platform": "Console"}, "1071490652": {"name": "Legendary Plan: Singularity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1846671248": {"name": "Legendary Plan: Skelon's Deceit", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1774978628": {"name": "Legendary Plan: Spite", "category": "Crafting Plans, Smith", "platform": "Console"}, "1806898802": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1463195022": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-402133524": {"name": "Legendary Plan: Starspine", "category": "Crafting Plans, Smith", "platform": "Console"}, "527593978": {"name": "Legendary Plan: Sunder", "category": "Crafting Plans, Smith", "platform": "Console"}, "2067112046": {"name": "Legendary Plan: Sydyru Crust", "category": "Crafting Plans, Smith", "platform": "Console"}, "1121389360": {"name": "Legendary Plan: The Helm of Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "-478050163": {"name": "Legendary Plan: The Helm of Rule", "category": "Crafting Plans, Smith", "platform": "Console"}, "186340431": {"name": "Legendary Plan: The Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "274154411": {"name": "Legendary Plan: The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "-242397939": {"name": "Legendary Plan: The Wedge", "category": "Crafting Plans, Smith", "platform": "Console"}, "-647199777": {"name": "Legendary Plan: Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "2066177684": {"name": "Legendary Plan: Unbound Bolt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1895316276": {"name": "Legendary Plan: Unending War", "category": "Crafting Plans, Smith", "platform": "Console"}, "-241912353": {"name": "Legendary Plan: Utar's Roar", "category": "Crafting Plans, Smith", "platform": "Console"}, "-446889189": {"name": "Legendary Plan: Venomhusk", "category": "Crafting Plans, Smith", "platform": "Console"}, "-30314682": {"name": "Legendary Plan: Wall of Bone", "category": "Crafting Plans, Smith", "platform": "Console"}, "-864620096": {"name": "Legendary Plan: Wall of Man", "category": "Crafting Plans, Smith", "platform": "Console"}, "-594473293": {"name": "Legendary Plan: War of the Dead", "category": "Crafting Plans, Smith", "platform": "Console"}, "1027888204": {"name": "Legendary Plan: Wondrous Deflectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110595705": {"name": "Rare Plan: Amulet of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110601443": {"name": "Rare Plan: Amulet of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110612529": {"name": "Rare Plan: Amulet of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110615435": {"name": "Rare Plan: Amulet of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069218648": {"name": "Rare Plan: Archon Armor of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069212910": {"name": "Rare Plan: Archon Armor of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069201824": {"name": "Rare Plan: Archon Armor of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069198918": {"name": "Rare Plan: Archon Armor of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427345983": {"name": "Rare Plan: Archon Gauntlets of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427340245": {"name": "Rare Plan: Archon Gauntlets of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427329159": {"name": "Rare Plan: Archon Gauntlets of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427326253": {"name": "Rare Plan: Archon Gauntlets of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194993962": {"name": "Rare Plan: Archon Spaulders of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194999700": {"name": "Rare Plan: Archon Spaulders of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195010786": {"name": "Rare Plan: Archon Spaulders of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195013692": {"name": "Rare Plan: Archon Spaulders of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666895": {"name": "Rare Plan: Exalted Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006109": {"name": "Rare Plan: Exalted Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232950": {"name": "Rare Plan: Exalted Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008978": {"name": "Rare Plan: Exalted Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049108": {"name": "Rare Plan: Exalted Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150314": {"name": "Rare Plan: Exalted Fine Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666894": {"name": "Rare Plan: Exalted Fine Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006108": {"name": "Rare Plan: Exalted Fine Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232949": {"name": "Rare Plan: Exalted Fine Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008977": {"name": "Rare Plan: Exalted Fine Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049107": {"name": "Rare Plan: Exalted Fine Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445431": {"name": "Rare Plan: Exalted Fine Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898771": {"name": "Rare Plan: Exalted Fine Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669101": {"name": "Rare Plan: Exalted Fine Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978459": {"name": "Rare Plan: Exalted Fine Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927530": {"name": "Rare Plan: Exalted Fine Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852815": {"name": "Rare Plan: Exalted Fine Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340209": {"name": "Rare Plan: Exalted Fine Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820187": {"name": "Rare Plan: Exalted Fine Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806016": {"name": "Rare Plan: Exalted Fine Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305005": {"name": "Rare Plan: Exalted Fine Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242821": {"name": "Rare Plan: Exalted Fine Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302887": {"name": "Rare Plan: Exalted Fine Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895417": {"name": "Rare Plan: Exalted Fine Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084692": {"name": "Rare Plan: Exalted Fine Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047028": {"name": "Rare Plan: Exalted Fine Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766203": {"name": "Rare Plan: Exalted Fine Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600122": {"name": "Rare Plan: Exalted Fine Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691115": {"name": "Rare Plan: Exalted Fine Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695962": {"name": "Rare Plan: Exalted Fine Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502140": {"name": "Rare Plan: Exalted Fine Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137849": {"name": "Rare Plan: Exalted Fine Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631474": {"name": "Rare Plan: Exalted Fine Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237753": {"name": "Rare Plan: Exalted Fine Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445432": {"name": "Rare Plan: Exalted Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898770": {"name": "Rare Plan: Exalted Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669102": {"name": "Rare Plan: Exalted Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-93021373": {"name": "Rare Plan: Exalted Grand Archmage Headpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150313": {"name": "Rare Plan: Exalted Grand Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666893": {"name": "Rare Plan: Exalted Grand Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006107": {"name": "Rare Plan: Exalted Grand Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232948": {"name": "Rare Plan: Exalted Grand Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008976": {"name": "Rare Plan: Exalted Grand Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049106": {"name": "Rare Plan: Exalted Grand Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445430": {"name": "Rare Plan: Exalted Grand Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898772": {"name": "Rare Plan: Exalted Grand Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "972140825": {"name": "Rare Plan: Exalted Grand Ghost Sight", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669100": {"name": "Rare Plan: Exalted Grand Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978460": {"name": "Rare Plan: Exalted Grand Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "531375006": {"name": "Rare Plan: Exalted Grand Heavy Baldric", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927531": {"name": "Rare Plan: Exalted Grand Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1162323497": {"name": "Rare Plan: Exalted Grand Manitou Mask", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852814": {"name": "Rare Plan: Exalted Grand Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340210": {"name": "Rare Plan: Exalted Grand Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820186": {"name": "Rare Plan: Exalted Grand Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806017": {"name": "Rare Plan: Exalted Grand Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305006": {"name": "Rare Plan: Exalted Grand Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242822": {"name": "Rare Plan: Exalted Grand Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302888": {"name": "Rare Plan: Exalted Grand Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895418": {"name": "Rare Plan: Exalted Grand Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084693": {"name": "Rare Plan: Exalted Grand Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047027": {"name": "Rare Plan: Exalted Grand Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766204": {"name": "Rare Plan: Exalted Grand Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600123": {"name": "Rare Plan: Exalted Grand Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691116": {"name": "Rare Plan: Exalted Grand Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695963": {"name": "Rare Plan: Exalted Grand Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502139": {"name": "Rare Plan: Exalted Grand Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "1784279615": {"name": "Rare Plan: Exalted Grand Stalker Cape", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137848": {"name": "Rare Plan: Exalted Grand Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631475": {"name": "Rare Plan: Exalted Grand Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237752": {"name": "Rare Plan: Exalted Grand Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927529": {"name": "Rare Plan: Exalted Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852816": {"name": "Rare Plan: Exalted Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340208": {"name": "Rare Plan: Exalted Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820188": {"name": "Rare Plan: Exalted Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806015": {"name": "Rare Plan: Exalted Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305004": {"name": "Rare Plan: Exalted Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242820": {"name": "Rare Plan: Exalted Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302886": {"name": "Rare Plan: Exalted Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895416": {"name": "Rare Plan: Exalted Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084691": {"name": "Rare Plan: Exalted Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047029": {"name": "Rare Plan: Exalted Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600121": {"name": "Rare Plan: Exalted Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691114": {"name": "Rare Plan: Exalted Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137850": {"name": "Rare Plan: Exalted Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631473": {"name": "Rare Plan: Exalted Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237754": {"name": "Rare Plan: Exalted Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656027917": {"name": "Rare Plan: Razorspikes of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656022179": {"name": "Rare Plan: Razorspikes of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656011093": {"name": "Rare Plan: Razorspikes of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656008187": {"name": "Rare Plan: Razorspikes of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1846613104": {"name": "Set Plan: Asheara's Uniform", "category": "Crafting Plans, Smith", "platform": "Console"}, "1930988128": {"name": "Set Plan: Asheara's Vestments", "category": "Crafting Plans, Smith", "platform": "Console"}, "1761387753": {"name": "Set Plan: Aughild's Authority", "category": "Crafting Plans, Smith", "platform": "Console"}, "-522988374": {"name": "Set Plan: Aughild's Victory", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1294645649": {"name": "Set Plan: Born's Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833297": {"name": "Set Plan: Born's Defiance", "category": "Crafting Plans, Smith", "platform": "Console"}, "1416190745": {"name": "Set Plan: Cain's Destiny", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833298": {"name": "Set Plan: Cain's Fate", "category": "Crafting Plans, Smith", "platform": "Console"}, "179824936": {"name": "Set Plan: Captain Crimson's Finery", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1405796903": {"name": "Set Plan: Captain Crimson's Trimmings", "category": "Crafting Plans, Smith", "platform": "Console"}, "2113413150": {"name": "Set Plan: Demon's Hide", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968554": {"name": "Set Plan: Demon's Skin", "category": "Crafting Plans, Smith", "platform": "Console"}, "331434522": {"name": "Set Plan: Griswold's Masterpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-410837290": {"name": "Set Plan: Griswold's Perfection", "category": "Crafting Plans, Smith", "platform": "Console"}, "1023052626": {"name": "Set Plan: Guardian's Contingency", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1605103146": {"name": "Set Plan: Guardian's Jeopardy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968552": {"name": "Set Plan: Hallowed Defenders", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1135146597": {"name": "Set Plan: Hallowed Protectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "1831860075": {"name": "Set Plan: Sage's Journey", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968553": {"name": "Set Plan: Sage's Plight", "category": "Crafting Plans, Smith", "platform": "Console"}}, "Crafting Plans, Transmog": {"1549850923": {"name": "Arma Mortis", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850925": {"name": "Guardian Facade", "category": "Crafting Plans, Transmog", "platform": "Console"}, "-1723454145": {"name": "Legends of the Conqueror Volume 1 (Patch 2.1.0)", "category": "Crafting Plans, Transmog", "platform": "Console"}}, "Crossbows": {"181031811": {"name": "02: Crossbow (DPS 12.7-14.3)", "category": "Crossbows", "platform": "Console"}, "181031812": {"name": "03: Heavy Crossbow (DPS 17.6-19.3)", "category": "Crossbows", "platform": "Console"}, "181031813": {"name": "04: Arbalest (DPS 22.6-24.2)", "category": "Crossbows", "platform": "Console"}, "181031814": {"name": "05: Lian Nu (DPS 27.5-29.2)", "category": "Crossbows", "platform": "Console"}, "181031815": {"name": "06: War Crossbow (DPS 32.5-34.1)", "category": "Crossbows", "platform": "Console"}, "181031816": {"name": "07: Porcupine (DPS 37.4-39.1)", "category": "Crossbows", "platform": "Console"}, "181032899": {"name": "08: Siege Crossbow (DPS 53.9-57.2)", "category": "Crossbows", "platform": "Console"}, "181032900": {"name": "09: Quarrelbow (DPS 57.2-60.5)", "category": "Crossbows", "platform": "Console"}, "181032901": {"name": "10: Heavy Siege Crossbow (DPS 64.9-68.2)", "category": "Crossbows", "platform": "Console"}, "181032902": {"name": "11: Slingbow (DPS 76.5-81.4)", "category": "Crossbows", "platform": "Console"}, "181032903": {"name": "12: Chokonu (DPS 102.9-109.5)", "category": "Crossbows", "platform": "Console"}, "181032904": {"name": "13: War Caster (DPS 122.1-130.4)", "category": "Crossbows", "platform": "Console"}, "181032905": {"name": "14: Scorpion (DPS 165.6-175.5)", "category": "Crossbows", "platform": "Console"}, "181033988": {"name": "15: Windlass (DPS 179.3-189.2)", "category": "Crossbows", "platform": "Console"}, "181033989": {"name": "16: Cranequin (DPS 194.2-204.1)", "category": "Crossbows", "platform": "Console"}, "181033990": {"name": "17: Dread Crossbow (DPS 225.0-236.5)", "category": "Crossbows", "platform": "Console"}, "181033991": {"name": "18: Nayin (DPS 281.1-294.3)", "category": "Crossbows", "platform": "Console"}, "181033992": {"name": "19: Stonebow (DPS 358.1-371.3)", "category": "Crossbows", "platform": "Console"}, "181033993": {"name": "20: Doomcaster (DPS 424.1-437.3)", "category": "Crossbows", "platform": "Console"}, "181033994": {"name": "21: Hellion Crossbow (DPS 501.1-514.3)", "category": "Crossbows", "platform": "Console"}, "181035077": {"name": "22: Rampart Bow (DPS 698.0-711.2)", "category": "Crossbows", "platform": "Console"}, "181035078": {"name": "23: Oxybeles (DPS 948.2-961.4)", "category": "Crossbows", "platform": "Console"}, "2045161301": {"name": "Art Test Crossbow 1", "category": "Crossbows", "platform": "Console"}, "2045161302": {"name": "Art Test Crossbow 2", "category": "Crossbows", "platform": "Console"}, "2045161303": {"name": "Art Test Crossbow 3", "category": "Crossbows", "platform": "Console"}, "2045161304": {"name": "Art Test Crossbow 4", "category": "Crossbows", "platform": "Console"}, "2045161305": {"name": "Art Test Crossbow 5", "category": "Crossbows", "platform": "Console"}, "-174075631": {"name": "Legendary: Arcane Barb", "category": "Crossbows", "platform": "Console"}, "-174003757": {"name": "Legendary: Bakkan Caster", "category": "Crossbows", "platform": "Console"}, "-1447231541": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1447233985": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779307": {"name": "Legendary: Bakkan Caster (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172997521": {"name": "Legendary: Buriza-Do Kyanon", "category": "Crossbows", "platform": "Console"}, "-1414028197": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1414025753": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779335": {"name": "Legendary: Buriza-Do Kyanon (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135048049": {"name": "Legendary: Chanon Bolter", "category": "Crossbows", "platform": "Console"}, "-174183442": {"name": "Legendary: Demon Machine", "category": "Crossbows", "platform": "Console"}, "-1453163590": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1453161146": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779302": {"name": "Legendary: Demon Machine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174147505": {"name": "Legendary: Hellrack", "category": "Crossbows", "platform": "Console"}, "-1451977669": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1451975225": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779303": {"name": "Legendary: Hellrack (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174111568": {"name": "Legendary: Manticore", "category": "Crossbows", "platform": "Console"}, "-1450791748": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1450789304": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779304": {"name": "Legendary: Manticore (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172961584": {"name": "Legendary: Pus Spitter", "category": "Crossbows", "platform": "Console"}, "-1412842276": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1412839832": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779336": {"name": "Legendary: Pus Spitter (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449605827": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449603383": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779305": {"name": "Legendary: Starspine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135012112": {"name": "Legendary: Wojahnni Assaulter", "category": "Crossbows", "platform": "Console"}, "376423602": {"name": "P2 Crossbow norm Legendary 01", "category": "Crossbows", "platform": "Console"}, "376423603": {"name": "P2 Crossbow norm Legendary 02", "category": "Crossbows", "platform": "Console"}, "762151703": {"name": "PvP: Heavy Crossbow", "category": "Crossbows", "platform": "Console"}, "762151705": {"name": "PvP: Heroic Crossbow", "category": "Crossbows", "platform": "Console"}, "762151704": {"name": "PvP: Mighty Crossbow", "category": "Crossbows", "platform": "Console"}}, "Crusader Shields": {"-118254878": {"name": "01: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254877": {"name": "02: Sacred Scutum (AR 54-62)", "category": "Crusader Shields", "platform": "Console"}, "-118254876": {"name": "03: Royal Shield (AR 99-114)", "category": "Crusader Shields", "platform": "Console"}, "-118254875": {"name": "04: Heraldic Heater (AR 144-188)", "category": "Crusader Shields", "platform": "Console"}, "-118254874": {"name": "05: Embossed Shield (AR 189-224)", "category": "Crusader Shields", "platform": "Console"}, "-118254873": {"name": "06: Protector Shield (AR 225-251)", "category": "Crusader Shields", "platform": "Console"}, "-118254872": {"name": "07: Crown Shield (AR 252-287)", "category": "Crusader Shields", "platform": "Console"}, "-118253789": {"name": "08: Gilded Shield (AR 288-359)", "category": "Crusader Shields", "platform": "Console"}, "-118253788": {"name": "09: Wall Shield (AR 360-431)", "category": "Crusader Shields", "platform": "Console"}, "-118253787": {"name": "10: Zakara Heater (AR 432-503)", "category": "Crusader Shields", "platform": "Console"}, "-118253786": {"name": "11: Blazoned Shield (AR 504-575)", "category": "Crusader Shields", "platform": "Console"}, "-118253785": {"name": "12: Chased Shield (AR 576-652)", "category": "Crusader Shields", "platform": "Console"}, "-118253784": {"name": "13: Conquest Shield (AR 652-696)", "category": "Crusader Shields", "platform": "Console"}, "-118253783": {"name": "14: Imperial Kite (AR 697-741)", "category": "Crusader Shields", "platform": "Console"}, "-118252700": {"name": "15: Righteous Defender (AR 742-786)", "category": "Crusader Shields", "platform": "Console"}, "-118252699": {"name": "16: Enduring Guardian (AR 787-831)", "category": "Crusader Shields", "platform": "Console"}, "-118252698": {"name": "17: Zealous Protector (AR 832-854)", "category": "Crusader Shields", "platform": "Console"}, "-118252697": {"name": "18: Raptor Shield (AR 855-967)", "category": "Crusader Shields", "platform": "Console"}, "-118252696": {"name": "19: Adamantine Blason (AR 967-1112)", "category": "Crusader Shields", "platform": "Console"}, "-118252695": {"name": "20: Heavy Shield (AR 1417-1979)", "category": "Crusader Shields", "platform": "Console"}, "-118252694": {"name": "21: Stalwart Guardian (AR 1980-2277)", "category": "Crusader Shields", "platform": "Console"}, "795980376": {"name": "Art Test CruShield 1", "category": "Crusader Shields", "platform": "Console"}, "795980377": {"name": "Art Test CruShield 2", "category": "Crusader Shields", "platform": "Console"}, "795980378": {"name": "Art Test CruShield 3", "category": "Crusader Shields", "platform": "Console"}, "795980379": {"name": "Art Test CruShield 4", "category": "Crusader Shields", "platform": "Console"}, "795980380": {"name": "Art Test CruShield 5", "category": "Crusader Shields", "platform": "Console"}, "820607285": {"name": "Legendary: Akarat's Awakening", "category": "Crusader Shields", "platform": "Console"}, "1983862516": {"name": "Legendary: Frydehr's Wrath (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "820571348": {"name": "Legendary: Hallowed Bulwark", "category": "Crusader Shields", "platform": "Console"}, "820643222": {"name": "Legendary: Hellskull", "category": "Crusader Shields", "platform": "Console"}, "820535411": {"name": "Legendary: Jekangbord", "category": "Crusader Shields", "platform": "Console"}, "820499474": {"name": "Legendary: Piro Marella", "category": "Crusader Shields", "platform": "Console"}, "820751033": {"name": "Legendary: Salvation", "category": "Crusader Shields", "platform": "Console"}, "820679159": {"name": "Legendary: Sublime Conviction", "category": "Crusader Shields", "platform": "Console"}, "820715096": {"name": "Legendary: The Final Witness", "category": "Crusader Shields", "platform": "Console"}, "1983862517": {"name": "Legendary: Unrelenting Phalanx (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}}, "Daggers": {"-1303415301": {"name": "02: Shiv (DPS 9.0-11.3)", "category": "Daggers", "platform": "Console"}, "-1303415300": {"name": "03: Short Dagger (DPS 15.0-17.3)", "category": "Daggers", "platform": "Console"}, "-1303415299": {"name": "04: Dagger (DPS 20.3-22.5)", "category": "Daggers", "platform": "Console"}, "-1303415298": {"name": "05: Poignard (DPS 23.3-25.5)", "category": "Daggers", "platform": "Console"}, "-1303415297": {"name": "06: Stiletto (DPS 27.0-29.3)", "category": "Daggers", "platform": "Console"}, "-1303415296": {"name": "07: Skiver (DPS 30.0-23.3)", "category": "Daggers", "platform": "Console"}, "-1303414213": {"name": "08: Jagged Dagger (DPS 38.3-40.5)", "category": "Daggers", "platform": "Console"}, "-1303414212": {"name": "09: Kindjal (DPS 44.3-46.5)", "category": "Daggers", "platform": "Console"}, "-1303414211": {"name": "10: Pugio (DPS 50.3-52.5)", "category": "Daggers", "platform": "Console"}, "-1303414210": {"name": "11: Rondel (DPS 57.0-59.3)", "category": "Daggers", "platform": "Console"}, "-1303414209": {"name": "12: Scramasax (DPS 66.0-68.3)", "category": "Daggers", "platform": "Console"}, "-1303414208": {"name": "13: Main Gauche (DPS 77.3-79.5)", "category": "Daggers", "platform": "Console"}, "-1303414207": {"name": "14: Spine (DPS 92.3-94.5)", "category": "Daggers", "platform": "Console"}, "-1303413124": {"name": "15: Kukri (DPS 101.3-103.5)", "category": "Daggers", "platform": "Console"}, "-1303413123": {"name": "16: Pavade (DPS 108.0-112.5)", "category": "Daggers", "platform": "Console"}, "-1303413122": {"name": "17: Cinquedea (DPS 117.8-122.3)", "category": "Daggers", "platform": "Console"}, "-1303413121": {"name": "18: Skain (DPS 129.0-133.5)", "category": "Daggers", "platform": "Console"}, "-1303413120": {"name": "19: Basilard (DPS 156.0-160.5)", "category": "Daggers", "platform": "Console"}, "-1303413119": {"name": "20: Piercer (DPS 177.8-182.3)", "category": "Daggers", "platform": "Console"}, "-1303413118": {"name": "21: Darkblade (DPS 202.5-209.3)", "category": "Daggers", "platform": "Console"}, "-1303412035": {"name": "22: Kingsport Blade (DPS 270.0-274.5)", "category": "Daggers", "platform": "Console"}, "-1303412034": {"name": "23: Punyal (DPS 321.0-325.5)", "category": "Daggers", "platform": "Console"}, "-1200973729": {"name": "Art Test Dagger 1", "category": "Daggers", "platform": "Console"}, "-1200973728": {"name": "Art Test Dagger 2", "category": "Daggers", "platform": "Console"}, "-1200973727": {"name": "Art Test Dagger 3", "category": "Daggers", "platform": "Console"}, "-1200973726": {"name": "Art Test Dagger 4", "category": "Daggers", "platform": "Console"}, "-1200973725": {"name": "Art Test Dagger 5", "category": "Daggers", "platform": "Console"}, "-2073514231": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "-2073511787": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092661": {"name": "Legendary: Blood-Magic Blade (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973885091": {"name": "Legendary: Blood-Magic Edge", "category": "Daggers", "platform": "Console"}, "-934857509": {"name": "Legendary: Envious Blade", "category": "Daggers", "platform": "Console"}, "-934929383": {"name": "Legendary: Gull Dagger", "category": "Daggers", "platform": "Console"}, "-974028839": {"name": "Legendary: Kill", "category": "Daggers", "platform": "Console"}, "-2078257915": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "-2078255471": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092657": {"name": "Legendary: Kill (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973849154": {"name": "Legendary: Pig Sticker", "category": "Daggers", "platform": "Console"}, "-2072328310": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "-2072325866": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092662": {"name": "Legendary: Pig Sticker (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934893446": {"name": "Legendary: Prowl's Dastardly Shiv", "category": "Daggers", "platform": "Console"}, "-973992902": {"name": "Legendary: The Barber", "category": "Daggers", "platform": "Console"}, "-2077071994": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "-2077069550": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092658": {"name": "Legendary: The Barber (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973813217": {"name": "Legendary: The Clipper", "category": "Daggers", "platform": "Console"}, "-2071142389": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "-2071139945": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092663": {"name": "Legendary: The Clipper (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-838272988": {"name": "Legendary: The Horadric Hamburger", "category": "Daggers", "platform": "Console"}, "-1893282128": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1893279684": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1817947684": {"name": "Legendary: The Horadric Hamburger (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-972914792": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-65175862": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-2041494364": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "-2041491920": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092688": {"name": "Legendary: Wizardspike (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934821572": {"name": "Set: Eun-jang-do (Patch 2.2.0)", "category": "Daggers", "platform": "Console"}}, "Daibos": {"1771748852": {"name": "02: Spade (DPS 21.5-23.1)", "category": "Daibos", "platform": "Console"}, "1771748853": {"name": "03: Eiku (DPS 27.5-29.2)", "category": "Daibos", "platform": "Console"}, "1771748854": {"name": "04: Taiji (DPS 41.8-43.5)", "category": "Daibos", "platform": "Console"}, "1771749940": {"name": "05: Jodo Staff (DPS 51.2-52.8)", "category": "Daibos", "platform": "Console"}, "1771749941": {"name": "06: Sibat (DPS 67.1-70.4)", "category": "Daibos", "platform": "Console"}, "1771749942": {"name": "07: Trost (DPS 97.9-101.2)", "category": "Daibos", "platform": "Console"}, "1771749943": {"name": "08: Svardstav (DPS 145.2-150.2)", "category": "Daibos", "platform": "Console"}, "1771751029": {"name": "09: Lathi (DPS 176.6-183.2)", "category": "Daibos", "platform": "Console"}, "1771751030": {"name": "10: Silambam (DPS 220.6-228.8)", "category": "Daibos", "platform": "Console"}, "1771751031": {"name": "11: Drevko (DPS 274.5-284.4)", "category": "Daibos", "platform": "Console"}, "1771751032": {"name": "12: Grand Taiji (DPS 374.6-386.1)", "category": "Daibos", "platform": "Console"}, "1771751033": {"name": "13: Zhezl (DPS 442.2-455.4)", "category": "Daibos", "platform": "Console"}, "1771751034": {"name": "14: Guru Staff (DPS 522.0-535.2)", "category": "Daibos", "platform": "Console"}, "1771752118": {"name": "15: Iron Judgement (DPS 684.3-696.3)", "category": "Daibos", "platform": "Console"}, "1771752119": {"name": "16: Whirlwind Staff (DPS 925.8-937.8)", "category": "Daibos", "platform": "Console"}, "446400306": {"name": "Legendary: Balance", "category": "Daibos", "platform": "Console"}, "1846230910": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "1846233354": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857814": {"name": "Legendary: Balance (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446651865": {"name": "Legendary: Flying Dragon", "category": "Daibos", "platform": "Console"}, "1854532357": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "1854534801": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857807": {"name": "Legendary: Flying Dragon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446436243": {"name": "Legendary: Incense Torch of the Grand Temple", "category": "Daibos", "platform": "Console"}, "1847416831": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "1847419275": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857813": {"name": "Legendary: Incense Torch of the Grand Temple (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446615928": {"name": "Legendary: Lai Yui's Persuader", "category": "Daibos", "platform": "Console"}, "1853346436": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "1853348880": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857808": {"name": "Legendary: Lai Yui's Taiji (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446472180": {"name": "Legendary: Rozpedin's Force", "category": "Daibos", "platform": "Console"}, "1848602752": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "1848605196": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857812": {"name": "Legendary: Rozpedin's Staff (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485499762": {"name": "Legendary: Staff of Kyro", "category": "Daibos", "platform": "Console"}, "1849788673": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "1849791117": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857811": {"name": "Legendary: The Clouds and the Moon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446508117": {"name": "Legendary: The Flow of Eternity", "category": "Daibos", "platform": "Console"}, "446579991": {"name": "Legendary: The Paddle", "category": "Daibos", "platform": "Console"}, "1852160515": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "1852162959": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857809": {"name": "Legendary: The Paddle (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485535699": {"name": "Legendary: Warstaff of General Quang", "category": "Daibos", "platform": "Console"}, "-326857815": {"name": "Set: Inna's Justice (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446364369": {"name": "Set: Inna's Reach", "category": "Daibos", "platform": "Console"}, "1845044989": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "1845047433": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}}, "Debug": {"201941397": {"name": "Debug Axe 002", "category": "Debug", "platform": "Console"}, "1162537406": {"name": "Debug Bow 001", "category": "Debug", "platform": "Console"}, "-1837157688": {"name": "Debug CrossBow 001", "category": "Debug", "platform": "Console"}, "110611392": {"name": "Debug Dagger 001", "category": "Debug", "platform": "Console"}, "-257486314": {"name": "Debug FistWeapon 001", "category": "Debug", "platform": "Console"}, "-1314119444": {"name": "Debug Mace 001", "category": "Debug", "platform": "Console"}, "-1314119443": {"name": "Debug Mace 002", "category": "Debug", "platform": "Console"}, "-1919522874": {"name": "Debug Polearm 001", "category": "Debug", "platform": "Console"}, "201837585": {"name": "Debug Spear 001", "category": "Debug", "platform": "Console"}, "-1812541014": {"name": "Debug Staff 001", "category": "Debug", "platform": "Console"}, "97851424": {"name": "Debug Wand 001", "category": "Debug", "platform": "Console"}, "109003955": {"name": "Professional Russian's 100 DPS 1H Axe", "category": "Debug", "platform": "Console"}, "1012655083": {"name": "Professional Russian's 100 DPS 1H Mace", "category": "Debug", "platform": "Console"}, "198260772": {"name": "Professional Russian's 100 DPS 1H Sword", "category": "Debug", "platform": "Console"}, "109003988": {"name": "Professional Russian's 100 DPS 2H Axe", "category": "Debug", "platform": "Console"}, "1012655116": {"name": "Professional Russian's 100 DPS 2H Mace", "category": "Debug", "platform": "Console"}, "198260805": {"name": "Professional Russian's 100 DPS 2H Sword", "category": "Debug", "platform": "Console"}, "1565754085": {"name": "Professional Russian's 100 DPS Bow", "category": "Debug", "platform": "Console"}, "1144284824": {"name": "Professional Russian's 100 DPS Crossbow Pistol", "category": "Debug", "platform": "Console"}, "199216263": {"name": "Professional Russian's 100 DPS Dagger", "category": "Debug", "platform": "Console"}, "131016487": {"name": "Professional Russian's 100 DPS Wand", "category": "Debug", "platform": "Console"}, "-268664650": {"name": "Professional Russian's Blind Proc Bow", "category": "Debug", "platform": "Console"}, "-497584419": {"name": "Professional Russian's Blind Proc Sword", "category": "Debug", "platform": "Console"}, "-1692695305": {"name": "Professional Russian's Bow", "category": "Debug", "platform": "Console"}, "-1353182983": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-1489225678": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-422042656": {"name": "Professional Russian's Chill Proc Sword", "category": "Debug", "platform": "Console"}, "860521450": {"name": "Professional Russian's Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-708154023": {"name": "Professional Russian's Dagger", "category": "Debug", "platform": "Console"}, "-813820178": {"name": "Professional Russian's Fast Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-1759844230": {"name": "Professional Russian's Fast Sword", "category": "Debug", "platform": "Console"}, "-1433265027": {"name": "Professional Russian's Fast Wand", "category": "Debug", "platform": "Console"}, "1812597803": {"name": "Professional Russian's Fear Proc Bow", "category": "Debug", "platform": "Console"}, "-1745505390": {"name": "Professional Russian's Fear Proc Sword", "category": "Debug", "platform": "Console"}, "-2004205682": {"name": "Professional Russian's Freeze Proc Bow", "category": "Debug", "platform": "Console"}, "-716158027": {"name": "Professional Russian's Freeze Proc Sword", "category": "Debug", "platform": "Console"}, "-1049148770": {"name": "Professional Russian's Immobilize Proc Bow", "category": "Debug", "platform": "Console"}, "1369510420": {"name": "Professional Russian's Knockback Proc Bow", "category": "Debug", "platform": "Console"}, "1063638971": {"name": "Professional Russian's Knockback Proc Sword", "category": "Debug", "platform": "Console"}, "-798366331": {"name": "Professional Russian's One-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206717": {"name": "Professional Russian's One-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502602": {"name": "Professional Russian's One-Handed Sword", "category": "Debug", "platform": "Console"}, "-395086843": {"name": "Professional Russian's Slow Crossbow Pistol", "category": "Debug", "platform": "Console"}, "1751317849": {"name": "Professional Russian's Slow Proc Sword", "category": "Debug", "platform": "Console"}, "-1341110895": {"name": "Professional Russian's Slow Sword", "category": "Debug", "platform": "Console"}, "-1899067884": {"name": "Professional Russian's Slow Wand", "category": "Debug", "platform": "Console"}, "476722551": {"name": "Professional Russian's Stun Proc Bow", "category": "Debug", "platform": "Console"}, "-41266491": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-519741474": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-798366298": {"name": "Professional Russian's Two-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206750": {"name": "Professional Russian's Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502569": {"name": "Professional Russian's Two-Handed Sword", "category": "Debug", "platform": "Console"}, "-23630983": {"name": "Professional Russian's Wand", "category": "Debug", "platform": "Console"}, "-908294397": {"name": "Shadowclone Ceremonial Knife (Hell)", "category": "Debug", "platform": "Console"}, "2012151919": {"name": "Shadowclone Ceremonial Knife (Inferno)", "category": "Debug", "platform": "Console"}, "754127773": {"name": "Shadowclone Ceremonial Knife (Nightmare)", "category": "Debug", "platform": "Console"}, "-1043228665": {"name": "Shadowclone Ceremonial Knife (Normal)", "category": "Debug", "platform": "Console"}, "-1067377991": {"name": "Shadowclone Crusader Shield", "category": "Debug", "platform": "Console"}, "413641572": {"name": "Shadowclone Daibo (Hell)", "category": "Debug", "platform": "Console"}, "1791808816": {"name": "Shadowclone Daibo (Inferno)", "category": "Debug", "platform": "Console"}, "1318657182": {"name": "Shadowclone Daibo (Nightmare)", "category": "Debug", "platform": "Console"}, "-269002584": {"name": "Shadowclone Daibo (Normal)", "category": "Debug", "platform": "Console"}, "-909812331": {"name": "Shadowclone Hand Crossbow (Hell)", "category": "Debug", "platform": "Console"}, "-998234687": {"name": "Shadowclone Hand Crossbow (Inferno)", "category": "Debug", "platform": "Console"}, "-496839313": {"name": "Shadowclone Hand Crossbow (Nightmare)", "category": "Debug", "platform": "Console"}, "1598708505": {"name": "Shadowclone Hand Crossbow (Normal)", "category": "Debug", "platform": "Console"}, "-1831368437": {"name": "Shadowclone Mojo", "category": "Debug", "platform": "Console"}, "-989882433": {"name": "Shadowclone One-Handed Flail", "category": "Debug", "platform": "Console"}, "318426510": {"name": "Shadowclone Staff (Hell)", "category": "Debug", "platform": "Console"}, "-1157906662": {"name": "Shadowclone Staff (Inferno)", "category": "Debug", "platform": "Console"}, "1714039048": {"name": "Shadowclone Staff (Nightmare)", "category": "Debug", "platform": "Console"}, "-878989998": {"name": "Shadowclone Staff (Normal)", "category": "Debug", "platform": "Console"}, "1875985680": {"name": "Shadowclone Two-Handed Mighty Weapon (Hell)", "category": "Debug", "platform": "Console"}, "832184156": {"name": "Shadowclone Two-Handed Mighty Weapon (Inferno)", "category": "Debug", "platform": "Console"}, "-35544630": {"name": "Shadowclone Two-Handed Mighty Weapon (Nightmare)", "category": "Debug", "platform": "Console"}, "-1209135788": {"name": "Shadowclone Two-Handed Mighty Weapon (Normal)", "category": "Debug", "platform": "Console"}, "2099757732": {"name": "ThorTest Bow", "category": "Debug", "platform": "Console"}, "-163370651": {"name": "ThorTest Ceremonial Dagger", "category": "Debug", "platform": "Console"}, "1291822630": {"name": "ThorTest CombatStaff", "category": "Debug", "platform": "Console"}, "-1647832978": {"name": "ThorTest Crossbow", "category": "Debug", "platform": "Console"}, "774399974": {"name": "ThorTest Dagger", "category": "Debug", "platform": "Console"}, "726818364": {"name": "ThorTest FistWeapon", "category": "Debug", "platform": "Console"}, "454120887": {"name": "ThorTest Hand Crossbow", "category": "Debug", "platform": "Console"}, "572923409": {"name": "ThorTest Mojo", "category": "Debug", "platform": "Console"}, "684187666": {"name": "ThorTest One-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118934": {"name": "ThorTest One-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530416": {"name": "ThorTest One-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903165": {"name": "ThorTest One-Handed Sword", "category": "Debug", "platform": "Console"}, "2099771967": {"name": "ThorTest Orb", "category": "Debug", "platform": "Console"}, "-1343109204": {"name": "ThorTest Polearm", "category": "Debug", "platform": "Console"}, "1306966712": {"name": "ThorTest Quiver", "category": "Debug", "platform": "Console"}, "1369802229": {"name": "ThorTest Shield", "category": "Debug", "platform": "Console"}, "1733748983": {"name": "ThorTest Spear", "category": "Debug", "platform": "Console"}, "1733888528": {"name": "ThorTest Staff", "category": "Debug", "platform": "Console"}, "684187699": {"name": "ThorTest Two-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118901": {"name": "ThorTest Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530383": {"name": "ThorTest Two-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903132": {"name": "ThorTest Two-Handed Sword", "category": "Debug", "platform": "Console"}, "573267654": {"name": "ThorTest Wand", "category": "Debug", "platform": "Console"}}, "Dyes": {"-575184703": {"name": "All-Soap's Miraculous Dye Remover", "category": "Dyes", "platform": "Console"}, "-234196827": {"name": "Aquatic Dye", "category": "Dyes", "platform": "Console"}, "-234196822": {"name": "Autumn Dye", "category": "Dyes", "platform": "Console"}, "1866876233": {"name": "Bottled Cloud", "category": "Dyes", "platform": "Console"}, "1866876234": {"name": "Bottled Smoke", "category": "Dyes", "platform": "Console"}, "-234196826": {"name": "Cardinal Dye", "category": "Dyes", "platform": "Console"}, "-234196823": {"name": "Desert Dye", "category": "Dyes", "platform": "Console"}, "-234196795": {"name": "Elegant Dye", "category": "Dyes", "platform": "Console"}, "-234196794": {"name": "Forester's Dye", "category": "Dyes", "platform": "Console"}, "-234196792": {"name": "Golden Dye", "category": "Dyes", "platform": "Console"}, "-234196790": {"name": "Infernal Dye", "category": "Dyes", "platform": "Console"}, "-234196798": {"name": "Lovely Dye", "category": "Dyes", "platform": "Console"}, "-234196793": {"name": "Mariner's Dye", "category": "Dyes", "platform": "Console"}, "-234196789": {"name": "Purity Dye", "category": "Dyes", "platform": "Console"}, "-234196825": {"name": "Ranger's Dye", "category": "Dyes", "platform": "Console"}, "-234196791": {"name": "Royal Dye", "category": "Dyes", "platform": "Console"}, "-234196796": {"name": "Spring Dye", "category": "Dyes", "platform": "Console"}, "-234196797": {"name": "Summer Dye", "category": "Dyes", "platform": "Console"}, "-234196830": {"name": "Tanner's Dye", "category": "Dyes", "platform": "Console"}, "-2000448920": {"name": "Vanishing Dye", "category": "Dyes", "platform": "Console"}, "-234196828": {"name": "Winter Dye", "category": "Dyes", "platform": "Console"}}, "Enchantress Focuses": {"761436847": {"name": "02: Eye", "category": "Enchantress Focuses", "platform": "Console"}, "761437935": {"name": "03: Scrying Glass", "category": "Enchantress Focuses", "platform": "Console"}, "761437936": {"name": "04: Blink", "category": "Enchantress Focuses", "platform": "Console"}, "761437937": {"name": "05: Crucible", "category": "Enchantress Focuses", "platform": "Console"}, "761437938": {"name": "06: Root", "category": "Enchantress Focuses", "platform": "Console"}, "761439024": {"name": "07: Eternity Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761439025": {"name": "08: Oculus", "category": "Enchantress Focuses", "platform": "Console"}, "761439026": {"name": "09: Cauldron", "category": "Enchantress Focuses", "platform": "Console"}, "761439027": {"name": "10: Herb", "category": "Enchantress Focuses", "platform": "Console"}, "761439028": {"name": "11: Anamorphosis", "category": "Enchantress Focuses", "platform": "Console"}, "761439029": {"name": "12: Augur", "category": "Enchantress Focuses", "platform": "Console"}, "-450681607": {"name": "Legendary: Hand of the Prophet", "category": "Enchantress Focuses", "platform": "Console"}, "-450681608": {"name": "Legendary: Smoking Thurible", "category": "Enchantress Focuses", "platform": "Console"}, "-450681606": {"name": "Legendary: Vadim's Surge", "category": "Enchantress Focuses", "platform": "Console"}}, "Fist Weapons": {"1236604968": {"name": "01: Knuckles (DPS 7.0-8.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604969": {"name": "02: Spikes (DPS 15.4-17.5)", "category": "Fist Weapons", "platform": "Console"}, "1236604970": {"name": "03: Talon (DPS 20.3-22.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604971": {"name": "04: Shuko (DPS 29.4-31.5)", "category": "Fist Weapons", "platform": "Console"}, "1236606057": {"name": "05: Breaker (DPS 38.5-40.6)", "category": "Fist Weapons", "platform": "Console"}, "1236606058": {"name": "06: Iron Fist (DPS 46.2-48.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606059": {"name": "07: Claw (DPS 60.2-62.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606060": {"name": "08: Kastet (DPS 81.2-83.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607146": {"name": "09: Grappler (DPS 106.4-110.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607147": {"name": "10: Hammer Hand (DPS 130.2-134.4)", "category": "Fist Weapons", "platform": "Console"}, "1236607148": {"name": "11: Demon Fang (DPS 156.8-163.1)", "category": "Fist Weapons", "platform": "Console"}, "1236607149": {"name": "12: Pulverizer (DPS 181.3-187.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607150": {"name": "13: Golden Talon (DPS 210.0-216.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607151": {"name": "14: Heaven Hand (DPS 242.2-248.5)", "category": "Fist Weapons", "platform": "Console"}, "1236608235": {"name": "15: Spiked Fist (DPS 322.0-328.3)", "category": "Fist Weapons", "platform": "Console"}, "1236608236": {"name": "16: Suwaiya (DPS 392.0-398.3)", "category": "Fist Weapons", "platform": "Console"}, "1349166155": {"name": "Art Test Fist 1", "category": "Fist Weapons", "platform": "Console"}, "1349166156": {"name": "Art Test Fist 2", "category": "Fist Weapons", "platform": "Console"}, "1349166157": {"name": "Art Test Fist 3", "category": "Fist Weapons", "platform": "Console"}, "1349166158": {"name": "Art Test Fist 4", "category": "Fist Weapons", "platform": "Console"}, "1349166159": {"name": "Art Test Fist 5", "category": "Fist Weapons", "platform": "Console"}, "-1097629365": {"name": "Legendary: Crystal Fist", "category": "Fist Weapons", "platform": "Console"}, "-1862107977": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1862105533": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690589": {"name": "Legendary: Crystal Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "2032005920": {"name": "Legendary: Deathreach", "category": "Fist Weapons", "platform": "Console"}, "-1097773113": {"name": "Legendary: Demon Claw", "category": "Fist Weapons", "platform": "Console"}, "-1866851661": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1866849217": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690593": {"name": "Legendary: Demon Hand (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058709594": {"name": "Legendary: Falcon Strike", "category": "Fist Weapons", "platform": "Console"}, "537275943": {"name": "Legendary: Fist Weapon of the Shattered Hand (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097665302": {"name": "Legendary: Fleshrake", "category": "Fist Weapons", "platform": "Console"}, "-1863293898": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1863291454": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690590": {"name": "Legendary: Fleshrake (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058745531": {"name": "Legendary: Jawbreaker", "category": "Fist Weapons", "platform": "Console"}, "-1097737176": {"name": "Legendary: Logan's Claw", "category": "Fist Weapons", "platform": "Console"}, "-1865665740": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1865663296": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690592": {"name": "Legendary: Logan's Claw (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097809050": {"name": "Legendary: Rabid Strike", "category": "Fist Weapons", "platform": "Console"}, "-1868037582": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1868035138": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690594": {"name": "Legendary: Rabid Strike (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096623129": {"name": "Legendary: Scarbringer", "category": "Fist Weapons", "platform": "Console"}, "-1828902189": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1828899745": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690561": {"name": "Legendary: Scarbringer (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096659066": {"name": "Legendary: Sledge Fist", "category": "Fist Weapons", "platform": "Console"}, "-1830088110": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1830085666": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690562": {"name": "Legendary: Sledge Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097593428": {"name": "Legendary: The Fist of Az'Turrasq", "category": "Fist Weapons", "platform": "Console"}, "-1860922056": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1860919612": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690588": {"name": "Legendary: The Fist of Az'Turrasq (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132078": {"name": "Legendary: Vengeful Wind (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097701239": {"name": "Legendary: Won Khim Lau", "category": "Fist Weapons", "platform": "Console"}, "-1864479819": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1864477375": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690591": {"name": "Legendary: Won Khim Lau (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132079": {"name": "P1 fistWeapon norm Legendary 01", "category": "Fist Weapons", "platform": "Console"}, "-1826530347": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1826527903": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096551255": {"name": "Set: Hallowed Hold", "category": "Fist Weapons", "platform": "Console"}, "-840690559": {"name": "Set: Hallowed Touch (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690563": {"name": "Set: Shenlong's Crashing Tide (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690564": {"name": "Set: Shenlong's Endless Wave (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096695003": {"name": "Set: Shenlong's Fist of Legend", "category": "Fist Weapons", "platform": "Console"}, "-1831274031": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1831271587": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096730940": {"name": "Set: Shenlong's Relentless Assault", "category": "Fist Weapons", "platform": "Console"}, "-1832459952": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1832457508": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}}, "Flails, One-Handed": {"-912456880": {"name": "01: Spiked Flail (DPS 7.7-9.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456879": {"name": "02: Iron Whip (DPS 13.3-15.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456878": {"name": "03: Barbed Flail (DPS 18.9-21.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456877": {"name": "04: Thresher (DPS 25.2-27.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456876": {"name": "05: Flail (DPS 30.8-32.9)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455791": {"name": "06: Ball and Chain (DPS 35.0-37.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455790": {"name": "07: Chain Mace (DPS 43.4-45.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455789": {"name": "08: Shredder (DPS 53.2-55.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455788": {"name": "09: Imposing Flail (DPS 71.4-73.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455787": {"name": "10: Royal Guardian (DPS 105.0-109.2)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454702": {"name": "11: Painbringer (DPS 119.0-125.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454701": {"name": "12: Knout (DPS 139.3-145.6)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454700": {"name": "13: Wicked Flail (DPS 177.1-183.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454699": {"name": "14: Giant's Flail (DPS 312.9-321.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454698": {"name": "15: Grandfather's Flail (DPS 382.9-391.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955915": {"name": "Art Test Flails One-Handed 1", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955914": {"name": "Art Test Flails One-Handed 2", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955913": {"name": "Art Test Flails One-Handed 3", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955912": {"name": "Art Test Flails One-Handed 4", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955911": {"name": "Art Test Flails One-Handed 5", "category": "Flails, One-Handed", "platform": "Console"}, "-1791015660": {"name": "Legendary: Darklight", "category": "Flails, One-Handed", "platform": "Console"}, "-1791195345": {"name": "Legendary: Golden Scourge", "category": "Flails, One-Handed", "platform": "Console"}, "-1791051597": {"name": "Legendary: Gyrfalcon's Foote", "category": "Flails, One-Handed", "platform": "Console"}, "-1790979723": {"name": "Legendary: Inviolable Faith", "category": "Flails, One-Handed", "platform": "Console"}, "-1791159408": {"name": "Legendary: Justinian's Mercy", "category": "Flails, One-Handed", "platform": "Console"}, "-1791087534": {"name": "Legendary: Kassar's Retribution", "category": "Flails, One-Handed", "platform": "Console"}, "1226090826": {"name": "Legendary: Mortal Coil", "category": "Flails, One-Handed", "platform": "Console"}, "-1791123471": {"name": "Legendary: Swiftmount", "category": "Flails, One-Handed", "platform": "Console"}, "1784501906": {"name": "P1 Flails1H norm Legendary 01", "category": "Flails, One-Handed", "platform": "Console"}}, "Flails, Two-Handed": {"-873321486": {"name": "02: Battle Flail (DPS 15.0-16.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321485": {"name": "03: Grand Thresher (DPS 22.4-24.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321484": {"name": "04: Two-Handed Flail (DPS 29.3-31.1)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321483": {"name": "05: Castigator (DPS 37.4-40.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320398": {"name": "06: Pyeongon (DPS 51.8-55.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320397": {"name": "07: Chigiriki (DPS 65.0-70.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320396": {"name": "08: Threshal (DPS 81.7-86.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320395": {"name": "09: Grand Flail (DPS 102.9-109.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320394": {"name": "10: Angelic Flail (DPS 146.1-154.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319309": {"name": "11: Campaigner's Grand Flail (DPS 194.4-206.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319308": {"name": "12: Bludgeoning Grand Flail (DPS 261.6-275.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319307": {"name": "13: Painbringer Grand Flail (DPS 333.5-347.3)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319306": {"name": "14: Baroque Grand Flail (DPS 648.0-661.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319305": {"name": "15: Angelic Grand Flail (DPS 878.0-891.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919978": {"name": "Art Test Flails Two-Handed 1", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919977": {"name": "Art Test Flails Two-Handed 2", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919976": {"name": "Art Test Flails Two-Handed 3", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919975": {"name": "Art Test Flails Two-Handed 4", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919974": {"name": "Art Test Flails Two-Handed 5", "category": "Flails, Two-Handed", "platform": "Console"}, "163153041": {"name": "Legendary: Baleful Remnant", "category": "Flails, Two-Handed", "platform": "Console"}, "163188978": {"name": "Legendary: Fate of the Fell", "category": "Flails, Two-Handed", "platform": "Console"}, "163224915": {"name": "Legendary: Golden Flense", "category": "Flails, Two-Handed", "platform": "Console"}, "163117104": {"name": "Legendary: The Mortal Drama", "category": "Flails, Two-Handed", "platform": "Console"}, "1784501907": {"name": "P1 Flails1H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712685": {"name": "P1 Flails2H norm Legendary 01", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712684": {"name": "P1 Flails2H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-1026738420": {"name": "legendary: Golden Flense (Patch 2.2.0)", "category": "Flails, Two-Handed", "platform": "Console"}}, "Gems": {"-1411866896": {"name": "Amethyst 02: Flawed Amethyst", "category": "Gems", "platform": "Console"}, "-1411866895": {"name": "Amethyst 03: Amethyst", "category": "Gems", "platform": "Console"}, "-1411866894": {"name": "Amethyst 04: Flawless Amethyst", "category": "Gems", "platform": "Console"}, "-1411866893": {"name": "Amethyst 05: Perfect Amethyst", "category": "Gems", "platform": "Console"}, "-1411866892": {"name": "Amethyst 06: Radiant Amethyst", "category": "Gems", "platform": "Console"}, "-1411866891": {"name": "Amethyst 07: Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866890": {"name": "Amethyst 08: Flawless Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866889": {"name": "Amethyst 09: Perfect Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866865": {"name": "Amethyst 10: Radiant Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866864": {"name": "Amethyst 11: Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866863": {"name": "Amethyst 12: Flawless Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866862": {"name": "Amethyst 13: Perfect Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866861": {"name": "Amethyst 14: Radiant Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866860": {"name": "Amethyst 15: Marquise Amethyst", "category": "Gems", "platform": "Console"}, "-1411866859": {"name": "Amethyst 16: Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866858": {"name": "Amethyst 17: Flawless Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866857": {"name": "Amethyst 18: Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1411866856": {"name": "Amethyst 19: Flawless Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1315690660": {"name": "Diamond 01: Chipped Diamond", "category": "Gems", "platform": "Console"}, "-1315690659": {"name": "Diamond 02: Flawed Diamond", "category": "Gems", "platform": "Console"}, "-1315690658": {"name": "Diamond 03: Diamond", "category": "Gems", "platform": "Console"}, "-1315690657": {"name": "Diamond 04: Flawless Diamond", "category": "Gems", "platform": "Console"}, "-1315690656": {"name": "Diamond 05: Perfect Diamond", "category": "Gems", "platform": "Console"}, "-1315690655": {"name": "Diamond 06: Radiant Diamond", "category": "Gems", "platform": "Console"}, "-1315690654": {"name": "Diamond 07: Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690653": {"name": "Diamond 08: Flawless Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690652": {"name": "Diamond 09: Perfect Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690628": {"name": "Diamond 10: Radiant Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690627": {"name": "Diamond 11: Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690626": {"name": "Diamond 12: Flawless Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690625": {"name": "Diamond 13: Perfect Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690624": {"name": "Diamond 14: Radiant Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690623": {"name": "Diamond 15: Marquise Diamond", "category": "Gems", "platform": "Console"}, "-1315690622": {"name": "Diamond 16: Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690621": {"name": "Diamond 17: Flawless Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690620": {"name": "Diamond 18: Royal Diamond", "category": "Gems", "platform": "Console"}, "-1315690619": {"name": "Diamond 19: Flawless Royal Diamond", "category": "Gems", "platform": "Console"}, "-1733388806": {"name": "Emerald 01: Chipped Emerald", "category": "Gems", "platform": "Console"}, "-1733388805": {"name": "Emerald 02: Flawed Emerald", "category": "Gems", "platform": "Console"}, "-1733388804": {"name": "Emerald 03: Emerald", "category": "Gems", "platform": "Console"}, "-1733388803": {"name": "Emerald 04: Flawless Emerald", "category": "Gems", "platform": "Console"}, "-1733388802": {"name": "Emerald 05: Perfect Emerald", "category": "Gems", "platform": "Console"}, "-1733388801": {"name": "Emerald 06: Radiant Emerald", "category": "Gems", "platform": "Console"}, "-1733388800": {"name": "Emerald 07: Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388799": {"name": "Emerald 08: Flawless Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388798": {"name": "Emerald 09: Perfect Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388774": {"name": "Emerald 10: Radiant Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388773": {"name": "Emerald 11: Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388772": {"name": "Emerald 12: Flawless Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388771": {"name": "Emerald 13: Perfect Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388770": {"name": "Emerald 14: Radiant Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388769": {"name": "Emerald 15: Marquise Emerald", "category": "Gems", "platform": "Console"}, "-1733388768": {"name": "Emerald 16: Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388767": {"name": "Emerald 17: Flawless Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388766": {"name": "Emerald 18: Royal Emerald", "category": "Gems", "platform": "Console"}, "-1733388765": {"name": "Emerald 19: Flawless Royal Emerald", "category": "Gems", "platform": "Console"}, "-1046455929": {"name": "Legendary: Bane of the Powerful (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046419992": {"name": "Legendary: Bane of the Trapped (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045162197": {"name": "Legendary: Boon of the Hoarder (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045305945": {"name": "Legendary: Enforcer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045090323": {"name": "Legendary: Esoteric Alteration (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1044084087": {"name": "Legendary: Gem Of X NYI (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046312181": {"name": "Legendary: Gem of Efficacious Toxin (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046384055": {"name": "Legendary: Gem of Reduced Level Requirement (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046204370": {"name": "Legendary: Gogok of Swiftness (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046168433": {"name": "Legendary: Invigorating Gemstone (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046240307": {"name": "Legendary: Mirinae, Teardrop of the Starweaver (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045054386": {"name": "Legendary: Molten Wildebeest's Gizzard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045270008": {"name": "Legendary: Moratorium (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044982512": {"name": "Legendary: Mutilation Guard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046276244": {"name": "Legendary: Pain Enhancer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044120024": {"name": "Legendary: Shen's Delight (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045198134": {"name": "Legendary: Simplicity's Strength (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045018449": {"name": "Legendary: Stone Of Heresy (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045126260": {"name": "Legendary: Taeguk (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046348118": {"name": "Legendary: Wreath of Lightning (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045234071": {"name": "Legendary: Zei's Stone of Vengeance (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "1603007810": {"name": "Ruby 01: Chipped Ruby", "category": "Gems", "platform": "Console"}, "1603007811": {"name": "Ruby 02: Flawed Ruby", "category": "Gems", "platform": "Console"}, "1603007812": {"name": "Ruby 03: Ruby", "category": "Gems", "platform": "Console"}, "1603007813": {"name": "Ruby 04: Flawless Ruby", "category": "Gems", "platform": "Console"}, "1603007814": {"name": "Ruby 05: Perfect Ruby", "category": "Gems", "platform": "Console"}, "1603007815": {"name": "Ruby 06: Radiant Ruby", "category": "Gems", "platform": "Console"}, "1603007816": {"name": "Ruby 07: Square Ruby", "category": "Gems", "platform": "Console"}, "1603007817": {"name": "Ruby 08: Flawless Square Ruby", "category": "Gems", "platform": "Console"}, "1603007818": {"name": "Ruby 09: Perfect Square Ruby", "category": "Gems", "platform": "Console"}, "1603007842": {"name": "Ruby 10: Radiant Square Ruby", "category": "Gems", "platform": "Console"}, "1603007843": {"name": "Ruby 11: Star Ruby", "category": "Gems", "platform": "Console"}, "1603007844": {"name": "Ruby 12: Flawless Star Ruby", "category": "Gems", "platform": "Console"}, "1603007845": {"name": "Ruby 13: Perfect Star Ruby", "category": "Gems", "platform": "Console"}, "1603007846": {"name": "Ruby 14: Radiant Star Ruby", "category": "Gems", "platform": "Console"}, "1603007847": {"name": "Ruby 15: Marquise Ruby", "category": "Gems", "platform": "Console"}, "1603007848": {"name": "Ruby 16: Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007849": {"name": "Ruby 17: Flawless Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007850": {"name": "Ruby 18: Royal Ruby", "category": "Gems", "platform": "Console"}, "1603007851": {"name": "Ruby 19: Flawless Royal Ruby", "category": "Gems", "platform": "Console"}, "2058771886": {"name": "Topaz 01: Chipped Topaz", "category": "Gems", "platform": "Console"}, "2058771887": {"name": "Topaz 02: Flawed Topaz", "category": "Gems", "platform": "Console"}, "2058771888": {"name": "Topaz 03: Topaz", "category": "Gems", "platform": "Console"}, "2058771889": {"name": "Topaz 04: Flawless Topaz", "category": "Gems", "platform": "Console"}, "2058771890": {"name": "Topaz 05: Perfect Topaz", "category": "Gems", "platform": "Console"}, "2058771891": {"name": "Topaz 06: Radiant Topaz", "category": "Gems", "platform": "Console"}, "2058771892": {"name": "Topaz 07: Square Topaz", "category": "Gems", "platform": "Console"}, "2058771893": {"name": "Topaz 08: Flawless Square Topaz", "category": "Gems", "platform": "Console"}, "2058771894": {"name": "Topaz 09: Perfect Square Topaz", "category": "Gems", "platform": "Console"}, "2058771918": {"name": "Topaz 10: Radiant Square Topaz", "category": "Gems", "platform": "Console"}, "2058771919": {"name": "Topaz 11: Star Topaz", "category": "Gems", "platform": "Console"}, "2058771920": {"name": "Topaz 12: Flawless Star Topaz", "category": "Gems", "platform": "Console"}, "2058771921": {"name": "Topaz 13: Perfect Star Topaz", "category": "Gems", "platform": "Console"}, "2058771922": {"name": "Topaz 14: Radiant Star Topaz", "category": "Gems", "platform": "Console"}, "2058771923": {"name": "Topaz 15: Marquise Topaz", "category": "Gems", "platform": "Console"}, "2058771924": {"name": "Topaz 16: Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771925": {"name": "Topaz 17: Flawless Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771926": {"name": "Topaz 18: Royal Topaz", "category": "Gems", "platform": "Console"}, "2058771927": {"name": "Topaz 19: Flawless Royal Topaz", "category": "Gems", "platform": "Console"}}, "Gloves": {"-1533914303": {"name": "02: Leather Gloves (AR 14-16)", "category": "Gloves", "platform": "Console"}, "-1533914302": {"name": "03: Hide Gloves (AR 28-32)", "category": "Gloves", "platform": "Console"}, "-1533914301": {"name": "04: Chain Gloves (AR 42-55)", "category": "Gloves", "platform": "Console"}, "-1533914300": {"name": "05: Gauntlets (AR 56-69)", "category": "Gloves", "platform": "Console"}, "-1533914299": {"name": "06: Plated Gauntlets (AR 70-88)", "category": "Gloves", "platform": "Console"}, "-1533913215": {"name": "07: Grips (AR 88-106)", "category": "Gloves", "platform": "Console"}, "-1533913214": {"name": "08: Etched Gloves (AR 107-125)", "category": "Gloves", "platform": "Console"}, "-1533913213": {"name": "09: Vambraces (AR 126-144)", "category": "Gloves", "platform": "Console"}, "-1533913212": {"name": "10: Battle Gauntlets (AR 144-173)", "category": "Gloves", "platform": "Console"}, "-1533913211": {"name": "11: Boneweave Gauntlets (AR 175-192)", "category": "Gloves", "platform": "Console"}, "-1533912126": {"name": "12: Balor Fists (AR 192-209)", "category": "Gloves", "platform": "Console"}, "-1533912125": {"name": "13: Manifers (AR 210-221)", "category": "Gloves", "platform": "Console"}, "-1533912124": {"name": "14: Warlord Gauntlets (AR 221-249)", "category": "Gloves", "platform": "Console"}, "-1533912123": {"name": "15: Stranglers (AR 250-278)", "category": "Gloves", "platform": "Console"}, "-1533912122": {"name": "16: Sovereign Vambraces (AR 280-308)", "category": "Gloves", "platform": "Console"}, "-1533912121": {"name": "17: Archon Gauntlets (AR 309-366)", "category": "Gloves", "platform": "Console"}, "-1533912120": {"name": "18: Rakkisgard Gauntlets (AR 367-512)", "category": "Gloves", "platform": "Console"}, "-1533912119": {"name": "19: Ascended Gauntlets (AR 513-590)", "category": "Gloves", "platform": "Console"}, "-542544859": {"name": "Art Test Gloves 1", "category": "Gloves", "platform": "Console"}, "-542544858": {"name": "Art Test Gloves 2", "category": "Gloves", "platform": "Console"}, "-542544857": {"name": "Art Test Gloves 3", "category": "Gloves", "platform": "Console"}, "-542544856": {"name": "Art Test Gloves 4", "category": "Gloves", "platform": "Console"}, "-542544855": {"name": "Art Test Gloves 5", "category": "Gloves", "platform": "Console"}, "-724111115": {"name": "Art_Test_Gloves_10 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-724111114": {"name": "Art_Test_Gloves_11 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544854": {"name": "Art_Test_Gloves_6 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544853": {"name": "Art_Test_Gloves_7 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544852": {"name": "Art_Test_Gloves_8 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544851": {"name": "Art_Test_Gloves_9 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "509897201": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "742334711": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "614385664": {"name": "Legendary: Alabaster Gloves", "category": "Gloves", "platform": "Console"}, "-935578501": {"name": "Legendary: Conqueror's Gauntlets (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "575250271": {"name": "Legendary: Frostburn", "category": "Gloves", "platform": "Console"}, "1803312459": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1803314903": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593655": {"name": "Legendary: Frostburn Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576400255": {"name": "Legendary: Gladiator Gauntlets", "category": "Gloves", "platform": "Console"}, "1841261931": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1841264375": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593687": {"name": "Legendary: Gladiator Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "614421601": {"name": "Legendary: Gloves of Worship", "category": "Gloves", "platform": "Console"}, "204261921": {"name": "Legendary: Grips of Perilous Ascent", "category": "Gloves", "platform": "Console"}, "576508066": {"name": "Legendary: Magefist", "category": "Gloves", "platform": "Console"}, "1844819694": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "1844822138": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "880593690": {"name": "Legendary: Magefist (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1802126538": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "1802128982": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "880593654": {"name": "Legendary: Pendergrasps (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575214334": {"name": "Legendary: Penders Purchase", "category": "Gloves", "platform": "Console"}, "614349727": {"name": "Legendary: St. Archew's Gage", "category": "Gloves", "platform": "Console"}, "575429956": {"name": "Legendary: Stone Gauntlets", "category": "Gloves", "platform": "Console"}, "1809242064": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1809244508": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593660": {"name": "Legendary: Stone Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575286208": {"name": "Legendary: Tasker and Theo", "category": "Gloves", "platform": "Console"}, "1804498380": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "1804500824": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "880593656": {"name": "Legendary: Tasker and Theo (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "880593662": {"name": "Set: Asheara's Clasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1811613906": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "1811616350": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "575501830": {"name": "Set: Asheara's Ward", "category": "Gloves", "platform": "Console"}, "1846005615": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "1846008059": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "576544003": {"name": "Set: Cain's Scrivener", "category": "Gloves", "platform": "Console"}, "880593691": {"name": "Set: Cain's Warmers (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "2058321365": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058321364": {"name": "Set: Fiendish Grips (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058285427": {"name": "Set: Fierce Gauntlets (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058429438": {"name": "Set: Firebird's Talons", "category": "Gloves", "platform": "Console"}, "2058501312": {"name": "Set: Fists of Thunder", "category": "Gloves", "platform": "Console"}, "2058249490": {"name": "Set: Gauntlet of the Wastes (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059399737": {"name": "Set: Gauntlets of Akkhan", "category": "Gloves", "platform": "Console"}, "2059615359": {"name": "Set: Helltooth Gauntlets", "category": "Gloves", "platform": "Console"}, "880593661": {"name": "Set: Immortal King's Forge (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575465893": {"name": "Set: Immortal King's Irons", "category": "Gloves", "platform": "Console"}, "1810427985": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "1810430429": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "-206156950": {"name": "Set: Inna's Hold (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058537249": {"name": "Set: Jade Harvester's Mercy", "category": "Gloves", "platform": "Console"}, "2058465375": {"name": "Set: Marauder's Gloves", "category": "Gloves", "platform": "Console"}, "2058249491": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156953": {"name": "Set: Natalya's Touch (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059471611": {"name": "Set: Pride of the Invoker", "category": "Gloves", "platform": "Console"}, "2059579422": {"name": "Set: Pull of the Earth", "category": "Gloves", "platform": "Console"}, "2058393501": {"name": "Set: Raekor's Wraps", "category": "Gloves", "platform": "Console"}, "2058249489": {"name": "Set: Roland's Grasp (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "1848377457": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "1848379901": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "880593693": {"name": "Set: Sage's Grasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576615877": {"name": "Set: Sage's Purchase", "category": "Gloves", "platform": "Console"}, "2059435674": {"name": "Set: Sunwuko's Paws", "category": "Gloves", "platform": "Console"}, "-206156952": {"name": "Set: Tal Rasha's Grasp (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059543485": {"name": "Set: The Shadow's Grasp", "category": "Gloves", "platform": "Console"}, "2059507548": {"name": "Set: Vyr's Grasping Gauntlets", "category": "Gloves", "platform": "Console"}, "2058285428": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156951": {"name": "Set: Zunimassa's Finger Wraps (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "614349464": {"name": "legendary: St. Archew's Gage (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}}, "Hand Crossbows": {"-363391669": {"name": "01: Simple Hand Crossbow (DPS 12.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363391668": {"name": "02: Light Hand Crossbow (DPS 11.2-13.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363391667": {"name": "03: Stake Thrower (DPS 12.8-15.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391666": {"name": "04: Hand Crossbow (DPS 16.0-18.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391665": {"name": "05: Slinglock (DPS 20.8-23.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391664": {"name": "06: Quillshot (DPS 24.0-26.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391663": {"name": "07: Nail Spitter (DPS 28.0-30.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391662": {"name": "08: Heavy Stake Thrower (DPS 32.8-35.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390580": {"name": "09: Sling Pistol (DPS 38.4-40.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363390579": {"name": "10: Crosslock (DPS 44.0-46.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390578": {"name": "11: Siege Lock (DPS 48.8-51.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390577": {"name": "12: Arcus (DPS 60.0-62.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390576": {"name": "13: Cranequin (DPS 65.6-68.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390575": {"name": "14: Spine Thrower (DPS 76.8-79.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390574": {"name": "15: Heavy Arcus (DPS 85.6-88.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390573": {"name": "16: Bolt Rack (DPS 98.4-100.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389491": {"name": "17: Runic Sling Pistol (DPS 113.6-116.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389490": {"name": "18: Splinter Shot (DPS 127.2-129.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389489": {"name": "19: Windlash (DPS 139.2-141.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389488": {"name": "20: Blade Spitter (DPS 154.4-156.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389487": {"name": "21: Heavy Cranequin (DPS 170.4-172.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389486": {"name": "22: Runic Arcus (DPS 196.8-199.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363389485": {"name": "23: Impellor (DPS 225.6-228.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389484": {"name": "24: Exorcist (DPS 258.4-263.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388402": {"name": "25: Lionblade Bow (DPS 516.8-519.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388401": {"name": "26: Penetrator (DPS 672.0-674.4)", "category": "Hand Crossbows", "platform": "Console"}, "1203045553": {"name": "Art Test Hand Crossbow 2", "category": "Hand Crossbows", "platform": "Console"}, "1203045554": {"name": "Art Test Hand Crossbow 3", "category": "Hand Crossbows", "platform": "Console"}, "1203045555": {"name": "Art Test Hand Crossbow 4", "category": "Hand Crossbows", "platform": "Console"}, "1203045556": {"name": "Art Test Hand Crossbow 5", "category": "Hand Crossbows", "platform": "Console"}, "1203045552": {"name": "Art Test HandCrossbow 1", "category": "Hand Crossbows", "platform": "Console"}, "-1153493044": {"name": "Legendary: Balefire Caster", "category": "Hand Crossbows", "platform": "Console"}, "589357912": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "589360356": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789444": {"name": "Legendary: Balefire Caster (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153493308": {"name": "Legendary: Balefire Caster (Patch 2.1.0)", "category": "Hand Crossbows", "platform": "Console"}, "-1153421170": {"name": "Legendary: Blitzbolter", "category": "Hand Crossbows", "platform": "Console"}, "-1152378997": {"name": "Legendary: Calamity", "category": "Hand Crossbows", "platform": "Console"}, "626121463": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "626123907": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789475": {"name": "Legendary: Calamity (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153385233": {"name": "Legendary: Dawn", "category": "Hand Crossbows", "platform": "Console"}, "592915675": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "592918119": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789447": {"name": "Legendary: Dawn (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591729754": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591732198": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789446": {"name": "Legendary: Deadeye (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114429525": {"name": "Legendary: Helltrapper", "category": "Hand Crossbows", "platform": "Console"}, "-1153457107": {"name": "Legendary: Izzuccob", "category": "Hand Crossbows", "platform": "Console"}, "590543833": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "590546277": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789445": {"name": "Legendary: Izzuccob (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114465462": {"name": "Legendary: K'mar Tenclip", "category": "Hand Crossbows", "platform": "Console"}, "-44923323": {"name": "Legendary: Quietus", "category": "Hand Crossbows", "platform": "Console"}, "-1266666515": {"name": "P2 Hand Crossbow norm Legendary 01", "category": "Hand Crossbows", "platform": "Console"}, "-1266666514": {"name": "P2 Hand Crossbow norm Legendary 02", "category": "Hand Crossbows", "platform": "Console"}, "-1266666513": {"name": "P2 Hand Crossbow norm Legendary 03", "category": "Hand Crossbows", "platform": "Console"}, "515789442": {"name": "Set: Danetta's Fury (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789441": {"name": "Set: Danetta's Rage (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153564918": {"name": "Set: Danetta's Revenge", "category": "Hand Crossbows", "platform": "Console"}, "586986070": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "586988514": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153600855": {"name": "Set: Danetta's Spite", "category": "Hand Crossbows", "platform": "Console"}, "585800149": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "585802593": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789479": {"name": "Set: Hallowed Avenger (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1152235249": {"name": "Set: Hallowed Condemnation", "category": "Hand Crossbows", "platform": "Console"}, "630865147": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "630867591": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789443": {"name": "Set: Natalya's Redemption (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153528981": {"name": "Set: Natalya's Slayer", "category": "Hand Crossbows", "platform": "Console"}, "588171991": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "588174435": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}}, "Helms": {"1565454584": {"name": "03: Coif (AR 36-41)", "category": "Helms", "platform": "Console"}, "1565454585": {"name": "04: Arming Cap (AR 54-71)", "category": "Helms", "platform": "Console"}, "1565454586": {"name": "05: Helmet (AR 72-89)", "category": "Helms", "platform": "Console"}, "1565454587": {"name": "06: Plated Helm (AR 90-113)", "category": "Helms", "platform": "Console"}, "1565455671": {"name": "07: Crown (AR 114-137)", "category": "Helms", "platform": "Console"}, "1565455672": {"name": "08: Basinet (AR 138-161)", "category": "Helms", "platform": "Console"}, "1565455673": {"name": "09: Klappvisier (AR 162-185)", "category": "Helms", "platform": "Console"}, "1565455674": {"name": "10: Casque (AR 186-224)", "category": "Helms", "platform": "Console"}, "1565455675": {"name": "11: Great Helm (AR 225-247)", "category": "Helms", "platform": "Console"}, "1565456760": {"name": "12: Hounskull (AR 247-269)", "category": "Helms", "platform": "Console"}, "1565456761": {"name": "13: Stechhelm (AR 270-284)", "category": "Helms", "platform": "Console"}, "1565456762": {"name": "14: Zischagge (AR 285-322)", "category": "Helms", "platform": "Console"}, "1565456763": {"name": "15: Hellscape Mask (AR 322-359)", "category": "Helms", "platform": "Console"}, "1565456764": {"name": "16: Sovereign Helm (AR 360-397)", "category": "Helms", "platform": "Console"}, "1565456765": {"name": "17: Archon Crown (AR 397-471)", "category": "Helms", "platform": "Console"}, "1565456766": {"name": "18: Rakkisgard Helm (AR 472-659)", "category": "Helms", "platform": "Console"}, "1565456767": {"name": "19: Ascended Crown (AR 660-759)", "category": "Helms", "platform": "Console"}, "1422434075": {"name": "Art Test Helm 1", "category": "Helms", "platform": "Console"}, "1422434076": {"name": "Art Test Helm 2", "category": "Helms", "platform": "Console"}, "1422434077": {"name": "Art Test Helm 3", "category": "Helms", "platform": "Console"}, "1422434078": {"name": "Art Test Helm 4", "category": "Helms", "platform": "Console"}, "1422434079": {"name": "Art Test Helm 5", "category": "Helms", "platform": "Console"}, "-304315733": {"name": "Art_Test_Helm_10 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315732": {"name": "Art_Test_Helm_11 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315731": {"name": "Art_Test_Helm_12 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434080": {"name": "Art_Test_Helm_6 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434081": {"name": "Art_Test_Helm_7 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434082": {"name": "Art_Test_Helm_8 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434083": {"name": "Art_Test_Helm_9 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233654": {"name": "Legendary: Andariel's Visage", "category": "Helms", "platform": "Console"}, "-1855268606": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "-1855266162": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "1638662958": {"name": "Legendary: Andariel's Visage (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334377402": {"name": "Legendary: Blind Faith", "category": "Helms", "platform": "Console"}, "-1850524922": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "-1850522478": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "1638662962": {"name": "Legendary: Blind Faith (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334161780": {"name": "Legendary: Broken Crown", "category": "Helms", "platform": "Console"}, "-1857640448": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1857638004": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662956": {"name": "Legendary: Broken Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1046338483": {"name": "Legendary: Broken Crown (Patch 2.1.2)", "category": "Helms", "platform": "Console"}, "1239902833": {"name": "Legendary: Conqueror's Shako (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "974143057": {"name": "Legendary: Death Mask", "category": "Helms", "platform": "Console"}, "373333110": {"name": "Legendary: Deathseer's Cowl", "category": "Helms", "platform": "Console"}, "-1854082685": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "-1854080241": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "1638662959": {"name": "Legendary: Giant Skull (Old-Legacy)", "category": "Helms", "platform": "Console"}, "1571690839": {"name": "Legendary: Guardian Facade", "category": "Helms", "platform": "Console"}, "974107120": {"name": "Legendary: Hallowed Helm", "category": "Helms", "platform": "Console"}, "-843818268": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "-1425221075": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "334197717": {"name": "Legendary: Leoric's Crown", "category": "Helms", "platform": "Console"}, "-1856454527": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1856452083": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662957": {"name": "Legendary: Leoric's Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334197453": {"name": "Legendary: Leoric's Crown (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "334341465": {"name": "Legendary: Mempo of Twilight", "category": "Helms", "platform": "Console"}, "-1851710843": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "-1851708399": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "1638662961": {"name": "Legendary: Mempo of Twilight (Old-Legacy)", "category": "Helms", "platform": "Console"}, "373369047": {"name": "Legendary: Pride's Fall", "category": "Helms", "platform": "Console"}, "334269591": {"name": "Legendary: Skull of Resonance", "category": "Helms", "platform": "Console"}, "-1818505055": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "-1818502611": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "1638662989": {"name": "Legendary: The Helm of Command (Old-Legacy)", "category": "Helms", "platform": "Console"}, "335347701": {"name": "Legendary: The Helm of Rule", "category": "Helms", "platform": "Console"}, "-1993242998": {"name": "Set: Accursed Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662992": {"name": "Set: Aughild's Brow (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1814947292": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "-1814944848": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "335455512": {"name": "Set: Aughild's Spike", "category": "Helms", "platform": "Console"}, "335383638": {"name": "Set: Cain's Insight", "category": "Helms", "platform": "Console"}, "1638662990": {"name": "Set: Cain's Laurel (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1817319134": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1817316690": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1992092751": {"name": "Set: Crown of the Invoker", "category": "Helms", "platform": "Console"}, "-1993242997": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1991984940": {"name": "Set: Eyes of the Earth", "category": "Helms", "platform": "Console"}, "-1993134924": {"name": "Set: Firebird's Plume", "category": "Helms", "platform": "Console"}, "-1813761371": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "-1813758927": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "335491449": {"name": "Set: Guardian's Gaze", "category": "Helms", "platform": "Console"}, "1638662993": {"name": "Set: Guardian's Watch (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1992164625": {"name": "Set: Helm of Akkhan", "category": "Helms", "platform": "Console"}, "-1993314872": {"name": "Set: Helm of the Wastes (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334413339": {"name": "Set: Immortal King's Triumph", "category": "Helms", "platform": "Console"}, "-1849339001": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "-1849336557": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "1638662963": {"name": "Set: Immortal King's Will (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993027113": {"name": "Set: Jade Harvester's Wisdom", "category": "Helms", "platform": "Console"}, "-1993098987": {"name": "Set: Marauder's Visage", "category": "Helms", "platform": "Console"}, "-1991949003": {"name": "Set: Mask of Jeram", "category": "Helms", "platform": "Console"}, "-1993063050": {"name": "Set: Mask of the Searing Sky", "category": "Helms", "platform": "Console"}, "-1993314871": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662964": {"name": "Set: Natalya's Gaze (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334449276": {"name": "Set: Natalya's Sight", "category": "Helms", "platform": "Console"}, "-1848153080": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1848150636": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1993170861": {"name": "Set: Raekor's Will", "category": "Helms", "platform": "Console"}, "-1993314873": {"name": "Set: Roland's Visage (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "335527386": {"name": "Set: Sage's Apogee", "category": "Helms", "platform": "Console"}, "-1812575450": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "-1812573006": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "1638662994": {"name": "Set: Sage's Stones (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278935": {"name": "Set: Shrouded Mask (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1992128688": {"name": "Set: Sunwuko's Crown", "category": "Helms", "platform": "Console"}, "335311764": {"name": "Set: Tal Rasha's Guise of Wisdom", "category": "Helms", "platform": "Console"}, "-1819690976": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "-1819688532": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "1638662988": {"name": "Set: Tal Rasha's Horadric Crest (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278934": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233391": {"name": "legendary: Andariel's Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-36755477": {"name": "legendary: Helm of the Hierarch (Patch 2.2.0)", "category": "Helms", "platform": "Console"}}, "Horadric Cache": {"739397179": {"name": "Act 1, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1369696819": {"name": "Act 1, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1369696818": {"name": "Act 1, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1369696817": {"name": "Act 1, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1369696816": {"name": "Act 1, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1369696815": {"name": "Act 1, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654861": {"name": "Act 2", "category": "Horadric Cache", "platform": "Console"}, "408167196": {"name": "Act 2, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "584615630": {"name": "Act 2, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "584615631": {"name": "Act 2, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "584615632": {"name": "Act 2, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "584615633": {"name": "Act 2, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "584615634": {"name": "Act 2, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654860": {"name": "Act 3", "category": "Horadric Cache", "platform": "Console"}, "76937213": {"name": "Act 3, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1756039217": {"name": "Act 3, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1756039216": {"name": "Act 3, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1756039215": {"name": "Act 3, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1756039214": {"name": "Act 3, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1756039213": {"name": "Act 3, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654859": {"name": "Act 4", "category": "Horadric Cache", "platform": "Console"}, "-254292770": {"name": "Act 4, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "198273232": {"name": "Act 4, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "198273233": {"name": "Act 4, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "198273234": {"name": "Act 4, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "198273235": {"name": "Act 4, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "198273236": {"name": "Act 4, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654858": {"name": "Act 5", "category": "Horadric Cache", "platform": "Console"}, "-585522753": {"name": "Act 5, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-2142381615": {"name": "Act 5, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-2142381614": {"name": "Act 5, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-2142381613": {"name": "Act 5, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-2142381612": {"name": "Act 5, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-2142381611": {"name": "Act 5, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "1574352095": {"name": "Bonus Act", "category": "Horadric Cache", "platform": "Console"}, "1749838250": {"name": "Greater Horadric Cache", "category": "Horadric Cache", "platform": "Console"}, "1802516147": {"name": "Greater Horadric Cache Torment", "category": "Horadric Cache", "platform": "Console"}, "-1262930872": {"name": "Horadric Cache Bonus Act Torment", "category": "Horadric Cache", "platform": "Console"}}, "Junk": {"-326449293": {"name": "Arcane Globe", "category": "Junk", "platform": "Console"}, "393991529": {"name": "Art_Test_Pennant_1 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991530": {"name": "Art_Test_Pennant_2 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991531": {"name": "Art_Test_Pennant_3 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991532": {"name": "Art_Test_Pennant_4 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991533": {"name": "Art_Test_Pennant_5 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991534": {"name": "Art_Test_Pennant_6 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991535": {"name": "Art_Test_Pennant_7 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991536": {"name": "Art_Test_Pennant_8 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-215839115": {"name": "Blizzcon Artifact", "category": "Junk", "platform": "Console"}, "-1812121245": {"name": "Cauldron of Jordan", "category": "Junk", "platform": "Console"}, "-125073416": {"name": "Charm", "category": "Junk", "platform": "Console"}, "-125073414": {"name": "Crafter Skillup Page", "category": "Junk", "platform": "Console"}, "-1739891535": {"name": "CupCake05", "category": "Junk", "platform": "Console"}, "-1581845891": {"name": "CupCake10", "category": "Junk", "platform": "Console"}, "-1581845886": {"name": "CupCake15", "category": "Junk", "platform": "Console"}, "-1581845858": {"name": "CupCake20", "category": "Junk", "platform": "Console"}, "-1581845853": {"name": "CupCake25", "category": "Junk", "platform": "Console"}, "-1581845825": {"name": "CupCake30", "category": "Junk", "platform": "Console"}, "-1581845820": {"name": "CupCake35", "category": "Junk", "platform": "Console"}, "-1581845792": {"name": "CupCake40", "category": "Junk", "platform": "Console"}, "1402040296": {"name": "Damaged Chestpiece", "category": "Junk", "platform": "Console"}, "-904648741": {"name": "Debug Transmog Plan", "category": "Junk", "platform": "Console"}, "-808688257": {"name": "Event MapVendor Egg", "category": "Junk", "platform": "Console"}, "-2126877461": {"name": "Example Book", "category": "Junk", "platform": "Console"}, "126259831": {"name": "Gold1", "category": "Junk", "platform": "Console"}, "126259832": {"name": "Gold2", "category": "Junk", "platform": "Console"}, "126259833": {"name": "Gold3", "category": "Junk", "platform": "Console"}, "126259834": {"name": "Gold4", "category": "Junk", "platform": "Console"}, "126259835": {"name": "Gold5", "category": "Junk", "platform": "Console"}, "-1165367015": {"name": "Greater Health Potion", "category": "Junk", "platform": "Console"}, "-1916071921": {"name": "Health Potion", "category": "Junk", "platform": "Console"}, "2022931376": {"name": "HealthGlobe01", "category": "Junk", "platform": "Console"}, "2022931377": {"name": "HealthGlobe02", "category": "Junk", "platform": "Console"}, "2022931378": {"name": "HealthGlobe03", "category": "Junk", "platform": "Console"}, "2022931379": {"name": "HealthGlobe04", "category": "Junk", "platform": "Console"}, "2022931380": {"name": "HealthGlobe05", "category": "Junk", "platform": "Console"}, "2022931381": {"name": "HealthGlobe06", "category": "Junk", "platform": "Console"}, "2022931382": {"name": "HealthGlobe07", "category": "Junk", "platform": "Console"}, "2022931383": {"name": "HealthGlobe08", "category": "Junk", "platform": "Console"}, "2022931384": {"name": "HealthGlobe09", "category": "Junk", "platform": "Console"}, "-1962741280": {"name": "HealthGlobe10", "category": "Junk", "platform": "Console"}, "-345952752": {"name": "HealthGlobe100", "category": "Junk", "platform": "Console"}, "-1962741275": {"name": "HealthGlobe15", "category": "Junk", "platform": "Console"}, "-1962741247": {"name": "HealthGlobe20", "category": "Junk", "platform": "Console"}, "-1962741242": {"name": "HealthGlobe25", "category": "Junk", "platform": "Console"}, "-1962741214": {"name": "HealthGlobe30", "category": "Junk", "platform": "Console"}, "-1962741209": {"name": "HealthGlobe35", "category": "Junk", "platform": "Console"}, "-1962741181": {"name": "HealthGlobe40", "category": "Junk", "platform": "Console"}, "-1962741176": {"name": "HealthGlobe45", "category": "Junk", "platform": "Console"}, "-1962741148": {"name": "HealthGlobe50", "category": "Junk", "platform": "Console"}, "-1962741143": {"name": "HealthGlobe55", "category": "Junk", "platform": "Console"}, "-1962741115": {"name": "HealthGlobe60", "category": "Junk", "platform": "Console"}, "-1962741110": {"name": "HealthGlobe65", "category": "Junk", "platform": "Console"}, "-1962741082": {"name": "HealthGlobe70", "category": "Junk", "platform": "Console"}, "-1962741077": {"name": "HealthGlobe75", "category": "Junk", "platform": "Console"}, "-1962741049": {"name": "HealthGlobe80", "category": "Junk", "platform": "Console"}, "-1962741044": {"name": "HealthGlobe85", "category": "Junk", "platform": "Console"}, "-1962741016": {"name": "HealthGlobe90", "category": "Junk", "platform": "Console"}, "-1962741011": {"name": "HealthGlobe95", "category": "Junk", "platform": "Console"}, "-1703070487": {"name": "Heroic Health Potion", "category": "Junk", "platform": "Console"}, "-125073411": {"name": "Junkorama", "category": "Junk", "platform": "Console"}, "-1546488739": {"name": "Lesser Health Potion", "category": "Junk", "platform": "Console"}, "1646125768": {"name": "Major Health Potion", "category": "Junk", "platform": "Console"}, "1646417620": {"name": "Minor Health Potion", "category": "Junk", "platform": "Console"}, "522407589": {"name": "Monk Staff Pvp 001", "category": "Junk", "platform": "Console"}, "522407590": {"name": "Monk Staff Pvp 002", "category": "Junk", "platform": "Console"}, "522407591": {"name": "Monk Staff Pvp 003", "category": "Junk", "platform": "Console"}, "-1483610851": {"name": "Mythic Health Potion", "category": "Junk", "platform": "Console"}, "-125073413": {"name": "OH NOES! JUNK!", "category": "Junk", "platform": "Console"}, "-1596706792": {"name": "Orn Bag 01", "category": "Junk", "platform": "Console"}, "885847747": {"name": "Orn BlizzconPrize", "category": "Junk", "platform": "Console"}, "-125073415": {"name": "Page of Fate", "category": "Junk", "platform": "Console"}, "197999857": {"name": "Page of Useless Scribbling", "category": "Junk", "platform": "Console"}, "1249260787": {"name": "PageOfFateA", "category": "Junk", "platform": "Console"}, "-910124122": {"name": "Power Potion", "category": "Junk", "platform": "Console"}, "1921622363": {"name": "Power-Up Attack Speed", "category": "Junk", "platform": "Console"}, "-859355014": {"name": "Power-Up Cooldown Reset", "category": "Junk", "platform": "Console"}, "11858385": {"name": "Power-Up Damage", "category": "Junk", "platform": "Console"}, "455273651": {"name": "Power-Up Invulnerability", "category": "Junk", "platform": "Console"}, "-977399097": {"name": "Power-Up Stealth", "category": "Junk", "platform": "Console"}, "-1504368109": {"name": "Resplendent Health Potion", "category": "Junk", "platform": "Console"}, "1652778256": {"name": "Runic Health Potion", "category": "Junk", "platform": "Console"}, "-1277860767": {"name": "Sacred Health Potion", "category": "Junk", "platform": "Console"}, "704159709": {"name": "Scholarly Writings", "category": "Junk", "platform": "Console"}, "197999858": {"name": "ScrapPaper 02", "category": "Junk", "platform": "Console"}, "197999859": {"name": "ScrapPaper 03", "category": "Junk", "platform": "Console"}, "197999860": {"name": "ScrapPaper 04", "category": "Junk", "platform": "Console"}, "1462277166": {"name": "Scroll", "category": "Junk", "platform": "Console"}, "146554345": {"name": "Set 001 GiyuasFang", "category": "Junk", "platform": "Console"}, "1653966238": {"name": "Super Health Potion", "category": "Junk", "platform": "Console"}, "1626390053": {"name": "Talisman", "category": "Junk", "platform": "Console"}, "761573026": {"name": "The Black Rock Ledger, Page 15", "category": "Junk", "platform": "Console"}, "761573027": {"name": "The Black Rock Ledger, Page 16", "category": "Junk", "platform": "Console"}, "761573028": {"name": "The Black Rock Ledger, Page 23", "category": "Junk", "platform": "Console"}, "761573024": {"name": "The Black Rock Ledger, Page 4", "category": "Junk", "platform": "Console"}, "761573029": {"name": "The Black Rock Ledger, Page 42", "category": "Junk", "platform": "Console"}, "761573025": {"name": "The Black Rock Ledger, Page 8", "category": "Junk", "platform": "Console"}, "-2007738575": {"name": "Town Portal Stone 2", "category": "Junk", "platform": "Console"}, "-125073412": {"name": "Trunk Junk", "category": "Junk", "platform": "Console"}, "177825848": {"name": "cos_pennant_01 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825849": {"name": "cos_pennant_02 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825850": {"name": "cos_pennant_03 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825851": {"name": "cos_pennant_04 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825852": {"name": "cos_pennant_05 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-1562301750": {"name": "cos_pennant_p2_Anniversary (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "127020830": {"name": "cos_pennant_p2_Heroes (Patch 2.2.0)", "category": "Junk", "platform": "Console"}}, "Keys": {"-1088058180": {"name": "Key of Destruction", "category": "Keys", "platform": "Console"}, "113551449": {"name": "Key of Evil", "category": "Keys", "platform": "Console"}, "-1207737543": {"name": "Key of Gluttony", "category": "Keys", "platform": "Console"}, "1064300938": {"name": "Key of Hate", "category": "Keys", "platform": "Console"}, "-143133978": {"name": "Key of Terror", "category": "Keys", "platform": "Console"}, "2050794135": {"name": "Key of War", "category": "Keys", "platform": "Console"}}, "Keystones": {"1955086538": {"name": "Greater Rift Keystone Rank 02 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086539": {"name": "Greater Rift Keystone Rank 03 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086540": {"name": "Greater Rift Keystone Rank 04 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086541": {"name": "Greater Rift Keystone Rank 05 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086542": {"name": "Greater Rift Keystone Rank 06 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086543": {"name": "Greater Rift Keystone Rank 07 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086544": {"name": "Greater Rift Keystone Rank 08 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086545": {"name": "Greater Rift Keystone Rank 09 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346329": {"name": "Greater Rift Keystone Rank 10 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1214538391": {"name": "Greater Rift Keystone Rank 100 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346330": {"name": "Greater Rift Keystone Rank 11 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346331": {"name": "Greater Rift Keystone Rank 12 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346332": {"name": "Greater Rift Keystone Rank 13 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346333": {"name": "Greater Rift Keystone Rank 14 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346334": {"name": "Greater Rift Keystone Rank 15 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346335": {"name": "Greater Rift Keystone Rank 16 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346336": {"name": "Greater Rift Keystone Rank 17 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346337": {"name": "Greater Rift Keystone Rank 18 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346338": {"name": "Greater Rift Keystone Rank 19 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346362": {"name": "Greater Rift Keystone Rank 20 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346363": {"name": "Greater Rift Keystone Rank 21 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346364": {"name": "Greater Rift Keystone Rank 22 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346365": {"name": "Greater Rift Keystone Rank 23 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346366": {"name": "Greater Rift Keystone Rank 24 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346367": {"name": "Greater Rift Keystone Rank 25 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346368": {"name": "Greater Rift Keystone Rank 26 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346369": {"name": "Greater Rift Keystone Rank 27 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346370": {"name": "Greater Rift Keystone Rank 28 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346371": {"name": "Greater Rift Keystone Rank 29 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346395": {"name": "Greater Rift Keystone Rank 30 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346396": {"name": "Greater Rift Keystone Rank 31 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346397": {"name": "Greater Rift Keystone Rank 32 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346398": {"name": "Greater Rift Keystone Rank 33 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346399": {"name": "Greater Rift Keystone Rank 34 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346400": {"name": "Greater Rift Keystone Rank 35 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346401": {"name": "Greater Rift Keystone Rank 36 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346402": {"name": "Greater Rift Keystone Rank 37 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346403": {"name": "Greater Rift Keystone Rank 38 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346404": {"name": "Greater Rift Keystone Rank 39 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346428": {"name": "Greater Rift Keystone Rank 40 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346429": {"name": "Greater Rift Keystone Rank 41 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346430": {"name": "Greater Rift Keystone Rank 42 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346431": {"name": "Greater Rift Keystone Rank 43 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346432": {"name": "Greater Rift Keystone Rank 44 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346433": {"name": "Greater Rift Keystone Rank 45 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346434": {"name": "Greater Rift Keystone Rank 46 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346435": {"name": "Greater Rift Keystone Rank 47 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346436": {"name": "Greater Rift Keystone Rank 48 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346437": {"name": "Greater Rift Keystone Rank 49 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346461": {"name": "Greater Rift Keystone Rank 50 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346462": {"name": "Greater Rift Keystone Rank 51 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346463": {"name": "Greater Rift Keystone Rank 52 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346464": {"name": "Greater Rift Keystone Rank 53 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346465": {"name": "Greater Rift Keystone Rank 54 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346466": {"name": "Greater Rift Keystone Rank 55 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346467": {"name": "Greater Rift Keystone Rank 56 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346468": {"name": "Greater Rift Keystone Rank 57 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346469": {"name": "Greater Rift Keystone Rank 58 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346470": {"name": "Greater Rift Keystone Rank 59 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346494": {"name": "Greater Rift Keystone Rank 60 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346495": {"name": "Greater Rift Keystone Rank 61 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346496": {"name": "Greater Rift Keystone Rank 62 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346497": {"name": "Greater Rift Keystone Rank 63 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346498": {"name": "Greater Rift Keystone Rank 64 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346499": {"name": "Greater Rift Keystone Rank 65 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346500": {"name": "Greater Rift Keystone Rank 66 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346501": {"name": "Greater Rift Keystone Rank 67 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346502": {"name": "Greater Rift Keystone Rank 68 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346503": {"name": "Greater Rift Keystone Rank 69 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346527": {"name": "Greater Rift Keystone Rank 70 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346528": {"name": "Greater Rift Keystone Rank 71 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346529": {"name": "Greater Rift Keystone Rank 72 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346530": {"name": "Greater Rift Keystone Rank 73 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346531": {"name": "Greater Rift Keystone Rank 74 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346532": {"name": "Greater Rift Keystone Rank 75 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346533": {"name": "Greater Rift Keystone Rank 76 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346534": {"name": "Greater Rift Keystone Rank 77 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346535": {"name": "Greater Rift Keystone Rank 78 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346536": {"name": "Greater Rift Keystone Rank 79 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346560": {"name": "Greater Rift Keystone Rank 80 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346561": {"name": "Greater Rift Keystone Rank 81 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346562": {"name": "Greater Rift Keystone Rank 82 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346563": {"name": "Greater Rift Keystone Rank 83 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346564": {"name": "Greater Rift Keystone Rank 84 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346565": {"name": "Greater Rift Keystone Rank 85 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346566": {"name": "Greater Rift Keystone Rank 86 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346567": {"name": "Greater Rift Keystone Rank 87 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346568": {"name": "Greater Rift Keystone Rank 88 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346569": {"name": "Greater Rift Keystone Rank 89 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346593": {"name": "Greater Rift Keystone Rank 90 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346594": {"name": "Greater Rift Keystone Rank 91 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346595": {"name": "Greater Rift Keystone Rank 92 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346596": {"name": "Greater Rift Keystone Rank 93 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346597": {"name": "Greater Rift Keystone Rank 94 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346598": {"name": "Greater Rift Keystone Rank 95 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346599": {"name": "Greater Rift Keystone Rank 96 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346600": {"name": "Greater Rift Keystone Rank 97 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346601": {"name": "Greater Rift Keystone Rank 98 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346602": {"name": "Greater Rift Keystone Rank 99 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086536": {"name": "Keystone of Trials (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1698136228": {"name": "Rift Keys", "category": "Keystones", "platform": "Console"}}, "Lore": {"-1194932976": {"name": "A2 Oasis KamyrsOrdersTwo", "category": "Lore", "platform": "Console"}, "192275875": {"name": "A2 TemplarBackstory 3 Landus's Diary", "category": "Lore", "platform": "Console"}, "-1883980626": {"name": "A3 Battlefields Supply WagonDiaries", "category": "Lore", "platform": "Console"}, "1740306889": {"name": "A4 Hub OldCouple 1", "category": "Lore", "platform": "Console"}, "-1764974213": {"name": "Adria ZoltunKulle2", "category": "Lore", "platform": "Console"}, "103300821": {"name": "Adria: Adria's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-776544373": {"name": "Adria: Adria's Journal, Part 2", "category": "Lore", "platform": "Console"}, "133385135": {"name": "Adria: Adria's Journal, Part 3", "category": "Lore", "platform": "Console"}, "133390039": {"name": "Adria: Adria's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1890330185": {"name": "Adria: Adria's Journal, Part 5", "category": "Lore", "platform": "Console"}, "127066864": {"name": "Adria: Adria's Journal, Part 6", "category": "Lore", "platform": "Console"}, "733368986": {"name": "Adria: Adria's Journal, Part 7", "category": "Lore", "platform": "Console"}, "100959118": {"name": "Adria: Adria's Journal, Part 8", "category": "Lore", "platform": "Console"}, "133600747": {"name": "Adria: Adria's Journal, Part 9", "category": "Lore", "platform": "Console"}, "133313247": {"name": "Adria: Adria's Note", "category": "Lore", "platform": "Console"}, "954251807": {"name": "Adria: Adria's Purpose", "category": "Lore", "platform": "Console"}, "900358318": {"name": "AdventureMode: A New Era", "category": "Lore", "platform": "Console"}, "-282286736": {"name": "AdventureMode: An Eternity of Agony", "category": "Lore", "platform": "Console"}, "1375431349": {"name": "AdventureMode: Impossibilities", "category": "Lore", "platform": "Console"}, "-1315225766": {"name": "AdventureMode: The Nephalem", "category": "Lore", "platform": "Console"}, "501220619": {"name": "AngirisCouncil: The Angiris Council", "category": "Lore", "platform": "Console"}, "-1383924340": {"name": "AngirisCouncil: The Archangel Auriel", "category": "Lore", "platform": "Console"}, "260686328": {"name": "AngirisCouncil: The Archangel Imperius", "category": "Lore", "platform": "Console"}, "397935128": {"name": "AngirisCouncil: The Archangel Itherael", "category": "Lore", "platform": "Console"}, "478898578": {"name": "AngirisCouncil: The Archangel Malthael", "category": "Lore", "platform": "Console"}, "-635616901": {"name": "AngirisCouncil: The Archangel Tyrael", "category": "Lore", "platform": "Console"}, "-164029999": {"name": "Aqueducts: The Desert Aqueducts, Part 1", "category": "Lore", "platform": "Console"}, "-164029998": {"name": "Aqueducts: The Desert Aqueducts, Part 2", "category": "Lore", "platform": "Console"}, "-714930281": {"name": "Armorer: Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "-1385743634": {"name": "Azmodan: Orders from Azmodan, Part 1", "category": "Lore", "platform": "Console"}, "-1385743633": {"name": "Azmodan: Orders from Azmodan, Part 2", "category": "Lore", "platform": "Console"}, "-1385743632": {"name": "Azmodan: Orders from Azmodan, Part 3", "category": "Lore", "platform": "Console"}, "-1385743631": {"name": "Azmodan: Orders from Azmodan, Part 4", "category": "Lore", "platform": "Console"}, "-1385743630": {"name": "Azmodan: Orders from Azmodan, Part 5", "category": "Lore", "platform": "Console"}, "-1385743629": {"name": "Azmodan: Orders from Azmodan, Part 6", "category": "Lore", "platform": "Console"}, "-1312231117": {"name": "Belial: Deceivers' Orders, Part 1", "category": "Lore", "platform": "Console"}, "-1346161479": {"name": "Belial: Deceivers' Orders, Part 2", "category": "Lore", "platform": "Console"}, "-661262942": {"name": "Belial: Deceivers' Orders, Part 3", "category": "Lore", "platform": "Console"}, "-978510227": {"name": "Belial: Guard's Orders", "category": "Lore", "platform": "Console"}, "1488385291": {"name": "Belial: Missive to Maghda, Part 1", "category": "Lore", "platform": "Console"}, "1488385292": {"name": "Belial: Missive to Maghda, Part 2", "category": "Lore", "platform": "Console"}, "10458238": {"name": "Belial: Proclamation from the Imperial Guard", "category": "Lore", "platform": "Console"}, "621163016": {"name": "Bestiary: Anarch", "category": "Lore", "platform": "Console"}, "515122494": {"name": "Bestiary: Armored Destroyer", "category": "Lore", "platform": "Console"}, "-1478953705": {"name": "Bestiary: Barbed Lurker", "category": "Lore", "platform": "Console"}, "1467646658": {"name": "Bestiary: Beast", "category": "Lore", "platform": "Console"}, "231471423": {"name": "Bestiary: Bile Crawler", "category": "Lore", "platform": "Console"}, "1675636673": {"name": "Bestiary: Blood Clan Khazra", "category": "Lore", "platform": "Console"}, "1675805102": {"name": "Bestiary: Blood Hawk", "category": "Lore", "platform": "Console"}, "2132231168": {"name": "Bestiary: Bogan Trapper", "category": "Lore", "platform": "Console"}, "661688183": {"name": "Bestiary: Boggit", "category": "Lore", "platform": "Console"}, "-1697636392": {"name": "Bestiary: Carrion Bat", "category": "Lore", "platform": "Console"}, "-186990405": {"name": "Bestiary: Carrion Nest", "category": "Lore", "platform": "Console"}, "1864365917": {"name": "Bestiary: Colossal Golgor", "category": "Lore", "platform": "Console"}, "-899331059": {"name": "Bestiary: Corpse Raiser", "category": "Lore", "platform": "Console"}, "-563018536": {"name": "Bestiary: Dark Berserker", "category": "Lore", "platform": "Console"}, "-1824883589": {"name": "Bestiary: Dark Cultist", "category": "Lore", "platform": "Console"}, "1971053797": {"name": "Bestiary: Dark Vessel", "category": "Lore", "platform": "Console"}, "-985860913": {"name": "Bestiary: Death Maiden", "category": "Lore", "platform": "Console"}, "610441837": {"name": "Bestiary: Deceivers", "category": "Lore", "platform": "Console"}, "-1937284463": {"name": "Bestiary: Demon Trooper", "category": "Lore", "platform": "Console"}, "478100232": {"name": "Bestiary: Demonic Hell Bearer", "category": "Lore", "platform": "Console"}, "-140849528": {"name": "Bestiary: Demonic Hellflyer", "category": "Lore", "platform": "Console"}, "2144349771": {"name": "Bestiary: Demonic Tremor", "category": "Lore", "platform": "Console"}, "1641498900": {"name": "Bestiary: Dune Dervish", "category": "Lore", "platform": "Console"}, "1184767076": {"name": "Bestiary: Dune Thresher", "category": "Lore", "platform": "Console"}, "-525114375": {"name": "Bestiary: Dust Imp", "category": "Lore", "platform": "Console"}, "-1086668012": {"name": "Bestiary: Electric Eel", "category": "Lore", "platform": "Console"}, "90729293": {"name": "Bestiary: Enraged Phantasm", "category": "Lore", "platform": "Console"}, "-1878606908": {"name": "Bestiary: Enslaved Nightmare", "category": "Lore", "platform": "Console"}, "789563798": {"name": "Bestiary: Exarch", "category": "Lore", "platform": "Console"}, "-1299022938": {"name": "Bestiary: Executioner", "category": "Lore", "platform": "Console"}, "1389417324": {"name": "Bestiary: Exorcist", "category": "Lore", "platform": "Console"}, "163638005": {"name": "Bestiary: Fallen Grunt", "category": "Lore", "platform": "Console"}, "84174677": {"name": "Bestiary: Fallen Lunatic", "category": "Lore", "platform": "Console"}, "1562132029": {"name": "Bestiary: Fallen Shaman", "category": "Lore", "platform": "Console"}, "-990665261": {"name": "Bestiary: Flesh Gorger", "category": "Lore", "platform": "Console"}, "-944408897": {"name": "Bestiary: Flesh Hurler", "category": "Lore", "platform": "Console"}, "-529946523": {"name": "Bestiary: Flesh Shaman", "category": "Lore", "platform": "Console"}, "1473699320": {"name": "Bestiary: Ghost", "category": "Lore", "platform": "Console"}, "1473699378": {"name": "Bestiary: Ghoul", "category": "Lore", "platform": "Console"}, "1067328402": {"name": "Bestiary: Grotesque", "category": "Lore", "platform": "Console"}, "-288964962": {"name": "Bestiary: Hellion", "category": "Lore", "platform": "Console"}, "-675600988": {"name": "Bestiary: Herald of Pestilence", "category": "Lore", "platform": "Console"}, "-1778975775": {"name": "Bestiary: Hound Pack Leader", "category": "Lore", "platform": "Console"}, "-1864253371": {"name": "Bestiary: Hulking Phasebeast", "category": "Lore", "platform": "Console"}, "1270376265": {"name": "Bestiary: Imp", "category": "Lore", "platform": "Console"}, "1543483412": {"name": "Bestiary: Khazra", "category": "Lore", "platform": "Console"}, "1080209708": {"name": "Bestiary: Khazra Shaman", "category": "Lore", "platform": "Console"}, "1574383663": {"name": "Bestiary: Lacuni", "category": "Lore", "platform": "Console"}, "1277879248": {"name": "Bestiary: Maggot Brood", "category": "Lore", "platform": "Console"}, "-1289421300": {"name": "Bestiary: Primordial Scavenger", "category": "Lore", "platform": "Console"}, "-683087584": {"name": "Bestiary: Quill Fiend", "category": "Lore", "platform": "Console"}, "2123300624": {"name": "Bestiary: Revenant Soldier", "category": "Lore", "platform": "Console"}, "2139220569": {"name": "Bestiary: Risen Dead", "category": "Lore", "platform": "Console"}, "-286364985": {"name": "Bestiary: Rockworm", "category": "Lore", "platform": "Console"}, "507308136": {"name": "Bestiary: Sand Dweller", "category": "Lore", "platform": "Console"}, "-1096104684": {"name": "Bestiary: Sand Wasp", "category": "Lore", "platform": "Console"}, "1312554887": {"name": "Bestiary: Scarab", "category": "Lore", "platform": "Console"}, "-1399846223": {"name": "Bestiary: Scavenger", "category": "Lore", "platform": "Console"}, "2067382477": {"name": "Bestiary: Scavenging Tunneler", "category": "Lore", "platform": "Console"}, "-458569087": {"name": "Bestiary: Scouring Charger", "category": "Lore", "platform": "Console"}, "-1529207830": {"name": "Bestiary: Shadow Vermin", "category": "Lore", "platform": "Console"}, "-1715924548": {"name": "Bestiary: Shadow of Death", "category": "Lore", "platform": "Console"}, "1905172061": {"name": "Bestiary: Shrieking Terror", "category": "Lore", "platform": "Console"}, "56567324": {"name": "Bestiary: Siegebreaker Assault Beast", "category": "Lore", "platform": "Console"}, "-387707041": {"name": "Bestiary: Skeletal Beast", "category": "Lore", "platform": "Console"}, "494193920": {"name": "Bestiary: Skeletal Crawler", "category": "Lore", "platform": "Console"}, "-313234093": {"name": "Bestiary: Skeletal Guardian", "category": "Lore", "platform": "Console"}, "-1409684360": {"name": "Bestiary: Skeleton", "category": "Lore", "platform": "Console"}, "1170383240": {"name": "Bestiary: Soul Ripper", "category": "Lore", "platform": "Console"}, "1866317050": {"name": "Bestiary: Spider", "category": "Lore", "platform": "Console"}, "564441124": {"name": "Bestiary: Spiderling", "category": "Lore", "platform": "Console"}, "-330757856": {"name": "Bestiary: Stinging Swarm", "category": "Lore", "platform": "Console"}, "-458677543": {"name": "Bestiary: Subjugator", "category": "Lore", "platform": "Console"}, "-1468295040": {"name": "Bestiary: Succubus", "category": "Lore", "platform": "Console"}, "-513840200": {"name": "Bestiary: Summoned Archer", "category": "Lore", "platform": "Console"}, "166255055": {"name": "Bestiary: Summoned Shield Guard", "category": "Lore", "platform": "Console"}, "1887856949": {"name": "Bestiary: Summoned Soldier", "category": "Lore", "platform": "Console"}, "920539156": {"name": "Bestiary: Summoner of the Dead", "category": "Lore", "platform": "Console"}, "166186064": {"name": "Bestiary: Terror Demon", "category": "Lore", "platform": "Console"}, "-1551452867": {"name": "Bestiary: The Accursed", "category": "Lore", "platform": "Console"}, "1613832402": {"name": "Bestiary: The Mallet Lords", "category": "Lore", "platform": "Console"}, "1481069442": {"name": "Bestiary: The Morlu", "category": "Lore", "platform": "Console"}, "1727215776": {"name": "Bestiary: The Oppressors", "category": "Lore", "platform": "Console"}, "-1569107231": {"name": "Bestiary: Tormented Stinger", "category": "Lore", "platform": "Console"}, "692217017": {"name": "Bestiary: Treasure Goblin", "category": "Lore", "platform": "Console"}, "1112087602": {"name": "Bestiary: Tusked Bogan", "category": "Lore", "platform": "Console"}, "1695981553": {"name": "Bestiary: Unburied", "category": "Lore", "platform": "Console"}, "181747316": {"name": "Bestiary: Vicious Hound", "category": "Lore", "platform": "Console"}, "191466402": {"name": "Bestiary: Vile Bat", "category": "Lore", "platform": "Console"}, "1295465786": {"name": "Bestiary: Warscarred Marauder", "category": "Lore", "platform": "Console"}, "-1568007631": {"name": "Bestiary: Warscarred Ravager", "category": "Lore", "platform": "Console"}, "1809929374": {"name": "Bestiary: Winged Assassin", "category": "Lore", "platform": "Console"}, "-1414985342": {"name": "Bestiary: Winged Talus", "category": "Lore", "platform": "Console"}, "1562746110": {"name": "Bestiary: Withermoth", "category": "Lore", "platform": "Console"}, "1892963547": {"name": "Bestiary: Wood Wraith", "category": "Lore", "platform": "Console"}, "1470131000": {"name": "Bestiary: Wretched Mother", "category": "Lore", "platform": "Console"}, "2033922302": {"name": "Butcher: Butcher", "category": "Lore", "platform": "Console"}, "3246582303": {"name": "Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "4058000945": {"name": "Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "554362535": {"name": "Cain: Deckard Cain's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1114094521": {"name": "Cain: Deckard Cain's Journal, Part 2", "category": "Lore", "platform": "Console"}, "828022511": {"name": "Caldeum: An Abridged History of Caldeum, Part 1", "category": "Lore", "platform": "Console"}, "828022512": {"name": "Caldeum: An Abridged History of Caldeum, Part 2", "category": "Lore", "platform": "Console"}, "828022513": {"name": "Caldeum: An Abridged History of Caldeum, Part 3", "category": "Lore", "platform": "Console"}, "828022514": {"name": "Caldeum: An Abridged History of Caldeum, Part 4", "category": "Lore", "platform": "Console"}, "828022515": {"name": "Caldeum: An Abridged History of Caldeum, Part 5", "category": "Lore", "platform": "Console"}, "828022516": {"name": "Caldeum: An Abridged History of Caldeum, Part 6", "category": "Lore", "platform": "Console"}, "344927641": {"name": "CaliphateSardar: The Musings of Caliphate Sardar", "category": "Lore", "platform": "Console"}, "-1106917318": {"name": "CampCultist: The Feared Hero", "category": "Lore", "platform": "Console"}, "-668215174": {"name": "CellarMadman: The Ravings of a Deranged Mind", "category": "Lore", "platform": "Console"}, "-1518383148": {"name": "CemeteryCrypts: Gravedigger's Log", "category": "Lore", "platform": "Console"}, "-727194820": {"name": "Challenge: Nephalem Rifts", "category": "Lore", "platform": "Console"}, "2125283571": {"name": "Crusader: The Crusaders, Part 1", "category": "Lore", "platform": "Console"}, "2125283572": {"name": "Crusader: The Crusaders, Part 2", "category": "Lore", "platform": "Console"}, "2125283573": {"name": "Crusader: The Crusaders, Part 3", "category": "Lore", "platform": "Console"}, "2125283574": {"name": "Crusader: The Crusaders, Part 4", "category": "Lore", "platform": "Console"}, "2125283575": {"name": "Crusader: The Crusaders, Part 5", "category": "Lore", "platform": "Console"}, "2125283576": {"name": "Crusader: The Crusaders, Part 6", "category": "Lore", "platform": "Console"}, "2125283577": {"name": "Crusader: The Crusaders, Part 7", "category": "Lore", "platform": "Console"}, "2125283578": {"name": "Crusader: The Crusaders, Part 8", "category": "Lore", "platform": "Console"}, "2125283579": {"name": "Crusader: The Crusaders, Part 9", "category": "Lore", "platform": "Console"}, "-186854830": {"name": "CultCrown: Cultist Orders", "category": "Lore", "platform": "Console"}, "4108112466": {"name": "Cultist Orders", "category": "Lore", "platform": "Console"}, "504852499": {"name": "CurioVendor: Adenah's Jottings", "category": "Lore", "platform": "Console"}, "-1717171528": {"name": "Cydaea: Cydaea, the Maiden of Lust", "category": "Lore", "platform": "Console"}, "1958060101": {"name": "DahlgurOasis: The Dahlgur Oasis", "category": "Lore", "platform": "Console"}, "-1010870335": {"name": "DarkZealot: Report from Wortham", "category": "Lore", "platform": "Console"}, "-819413474": {"name": "Deserter: Deserter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-819413473": {"name": "Deserter: Deserter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-819413472": {"name": "Deserter: Deserter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-819413471": {"name": "Deserter: Deserter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-819413470": {"name": "Deserter: Deserter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "1121720780": {"name": "DesolateSands: On the Desolate Sands, Part 1", "category": "Lore", "platform": "Console"}, "1121720781": {"name": "DesolateSands: On the Desolate Sands, Part 2", "category": "Lore", "platform": "Console"}, "1121720782": {"name": "DesolateSands: On the Desolate Sands, Part 3", "category": "Lore", "platform": "Console"}, "2388677118": {"name": "Despina's Journal", "category": "Lore", "platform": "Console"}, "1244727565": {"name": "DevilsHand: Implements of the Dark Coven", "category": "Lore", "platform": "Console"}, "1244727564": {"name": "DevilsHand: The Black King's Reign", "category": "Lore", "platform": "Console"}, "1244727563": {"name": "DevilsHand: The Covenant's Search", "category": "Lore", "platform": "Console"}, "172363859": {"name": "DoomedWoman: The Horrible Secret", "category": "Lore", "platform": "Console"}, "-1577589110": {"name": "Enchantress: Eirena's Journal", "category": "Lore", "platform": "Console"}, "2168089835": {"name": "Example Book", "category": "Lore", "platform": "Console"}, "1850500833": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 1", "category": "Lore", "platform": "Console"}, "1850500834": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 2", "category": "Lore", "platform": "Console"}, "1850500835": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 3", "category": "Lore", "platform": "Console"}, "1850500836": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 4", "category": "Lore", "platform": "Console"}, "1850500837": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 5", "category": "Lore", "platform": "Console"}, "1814333430": {"name": "FieldsofMisery: Tristram Fields", "category": "Lore", "platform": "Console"}, "-821793924": {"name": "Ghom: Ghom, the Lord of Gluttony", "category": "Lore", "platform": "Console"}, "-681952308": {"name": "GluttonysLog: Ghom's Log", "category": "Lore", "platform": "Console"}, "1895762819": {"name": "GoatmenHunter: Khazra Heads Wanted", "category": "Lore", "platform": "Console"}, "1895762820": {"name": "GoatmenHunter: Researching the Khazra", "category": "Lore", "platform": "Console"}, "1895762821": {"name": "GoatmenHunter: The Khazra Massacre", "category": "Lore", "platform": "Console"}, "-1085616825": {"name": "Halls_of_Agony: Command from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "-1085616824": {"name": "Halls_of_Agony: Reply from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "721065374": {"name": "HangingTree: The Hanging Tree", "category": "Lore", "platform": "Console"}, "4006002334": {"name": "Hellion", "category": "Lore", "platform": "Console"}, "1555542539": {"name": "Hermit_Caves: Hermit's Ravings", "category": "Lore", "platform": "Console"}, "-578368437": {"name": "HexMaze: Melaina's Memory", "category": "Lore", "platform": "Console"}, "-578368438": {"name": "HexMaze: Raissa's Memory", "category": "Lore", "platform": "Console"}, "-578368439": {"name": "HexMaze: Sibyl's Thoughts", "category": "Lore", "platform": "Console"}, "2145056291": {"name": "Highlands: The Highlands", "category": "Lore", "platform": "Console"}, "174686246": {"name": "HuntersJournal: Hunter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "174686247": {"name": "HuntersJournal: Hunter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "174686248": {"name": "HuntersJournal: Hunter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "174686249": {"name": "HuntersJournal: Hunter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "174686250": {"name": "HuntersJournal: Hunter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "174686251": {"name": "HuntersJournal: Hunter's Journal, Part 6", "category": "Lore", "platform": "Console"}, "-799754755": {"name": "Inarius: The Creation of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "-799754754": {"name": "Inarius: The Creation of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "-799754753": {"name": "Inarius: The Creation of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "-799754752": {"name": "Inarius: The Creation of Sanctuary, Part 4", "category": "Lore", "platform": "Console"}, "194883964": {"name": "Inarius: The Testament of Inarius, Part 1", "category": "Lore", "platform": "Console"}, "194883965": {"name": "Inarius: The Testament of Inarius, Part 2", "category": "Lore", "platform": "Console"}, "194883966": {"name": "Inarius: The Testament of Inarius, Part 3", "category": "Lore", "platform": "Console"}, "194883967": {"name": "Inarius: The Testament of Inarius, Part 4", "category": "Lore", "platform": "Console"}, "194883968": {"name": "Inarius: The Testament of Inarius, Part 5", "category": "Lore", "platform": "Console"}, "194883969": {"name": "Inarius: The Testament of Inarius, Part 6", "category": "Lore", "platform": "Console"}, "194883970": {"name": "Inarius: The Testament of Inarius, Part 7", "category": "Lore", "platform": "Console"}, "-1346370762": {"name": "Izual: Izual's Descent", "category": "Lore", "platform": "Console"}, "28868489": {"name": "Jeweler: Journal of Covetous Shen", "category": "Lore", "platform": "Console"}, "1221720352": {"name": "Jeweler: The Legend of Zei the Trickster", "category": "Lore", "platform": "Console"}, "-329801970": {"name": "Kala: Kala's Poem", "category": "Lore", "platform": "Console"}, "-355886665": {"name": "KeepHistory: The History of Bastion's Keep", "category": "Lore", "platform": "Console"}, "815737414": {"name": "KhanDakab: Last Will of Khan Dakab", "category": "Lore", "platform": "Console"}, "378673143": {"name": "KidVendor: Larra's Diary", "category": "Lore", "platform": "Console"}, "-1755180605": {"name": "Kingsport: Kingsport Bill", "category": "Lore", "platform": "Console"}, "-1156197446": {"name": "Kulle: Kulle's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1156197445": {"name": "Kulle: Kulle's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1156197444": {"name": "Kulle: Kulle's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-1156197443": {"name": "Kulle: Kulle's Journal, Part 4", "category": "Lore", "platform": "Console"}, "2698411174": {"name": "Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "3758420764": {"name": "Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "3768800974": {"name": "Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "3768800975": {"name": "Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "3768800976": {"name": "Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "3768800977": {"name": "Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "-1596556122": {"name": "Lachdanan: Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "-536546532": {"name": "Lachdanan: Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "-526166322": {"name": "Lachdanan: Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "-526166321": {"name": "Lachdanan: Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "-526166320": {"name": "Lachdanan: Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "-526166319": {"name": "Lachdanan: Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "1554177638": {"name": "LastAncient: The Last of the Ancients", "category": "Lore", "platform": "Console"}, "1905436671": {"name": "Lazarus: A Page from Lazarus's Grimoire", "category": "Lore", "platform": "Console"}, "3272862989": {"name": "Leah's Journal, Part 1", "category": "Lore", "platform": "Console"}, "3272868741": {"name": "Leah's Journal, Part 2", "category": "Lore", "platform": "Console"}, "3625638211": {"name": "Leah's Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922967": {"name": "Leah: Leah's Caldeum Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922968": {"name": "Leah: Leah's Caldeum Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922969": {"name": "Leah: Leah's Caldeum Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922970": {"name": "Leah: Leah's Caldeum Journal, Part 4", "category": "Lore", "platform": "Console"}, "891922971": {"name": "Leah: Leah's Caldeum Journal, Part 5", "category": "Lore", "platform": "Console"}, "891922972": {"name": "Leah: Leah's Keep Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922973": {"name": "Leah: Leah's Keep Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922974": {"name": "Leah: Leah's Keep Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922975": {"name": "Leah: Leah's Keep Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1022104307": {"name": "Leah: Leah's Tristram Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1022098555": {"name": "Leah: Leah's Tristram Journal, Part 2", "category": "Lore", "platform": "Console"}, "-669329085": {"name": "Leah: Leah's Tristram Journal, Part 3", "category": "Lore", "platform": "Console"}, "629974535": {"name": "Leah: Leah's Tristram Journal, Part 4", "category": "Lore", "platform": "Console"}, "629968021": {"name": "Leah: Leah's Tristram Journal, Part 5", "category": "Lore", "platform": "Console"}, "-1022100097": {"name": "Leah: Leah's Tristram Journal, Part 6", "category": "Lore", "platform": "Console"}, "-670618452": {"name": "Leah: Leah's Tristram Journal, Part 7", "category": "Lore", "platform": "Console"}, "2951326394": {"name": "Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1091428479": {"name": "Leoric: A Prisoner's Journal", "category": "Lore", "platform": "Console"}, "-1343640902": {"name": "Leoric: Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1561062717": {"name": "Leoric: Leoric's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1561062718": {"name": "Leoric: Leoric's Journal, Part 2", "category": "Lore", "platform": "Console"}, "1561062719": {"name": "Leoric: Leoric's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561062720": {"name": "Leoric: Leoric's Journal, Part 4", "category": "Lore", "platform": "Console"}, "1561062721": {"name": "Leoric: Leoric's Journal, Part 5", "category": "Lore", "platform": "Console"}, "342313869": {"name": "Leoric: Leoric's Relic", "category": "Lore", "platform": "Console"}, "164674838": {"name": "Leoric: The Death of King Leoric", "category": "Lore", "platform": "Console"}, "82422929": {"name": "Leoric: Torn Letter", "category": "Lore", "platform": "Console"}, "82422930": {"name": "Leoric: Torn Letter's Response", "category": "Lore", "platform": "Console"}, "1354656263": {"name": "Lilith: The Writings of Lilith, Part 1", "category": "Lore", "platform": "Console"}, "1354656264": {"name": "Lilith: The Writings of Lilith, Part 2", "category": "Lore", "platform": "Console"}, "1354656265": {"name": "Lilith: The Writings of Lilith, Part 3", "category": "Lore", "platform": "Console"}, "1354656266": {"name": "Lilith: The Writings of Lilith, Part 4", "category": "Lore", "platform": "Console"}, "2145180345": {"name": "LordofFools: Lord Kertis's Journal", "category": "Lore", "platform": "Console"}, "704654350": {"name": "LordsofHell: Andariel, the Maiden of Anguish", "category": "Lore", "platform": "Console"}, "-408914888": {"name": "LordsofHell: Azmodan, the Lord of Sin", "category": "Lore", "platform": "Console"}, "-1390665602": {"name": "LordsofHell: Baal, the Lord of Destruction", "category": "Lore", "platform": "Console"}, "1693753943": {"name": "LordsofHell: Belial, the Lord of Lies", "category": "Lore", "platform": "Console"}, "1776365849": {"name": "LordsofHell: Diablo, the Lord of Terror", "category": "Lore", "platform": "Console"}, "1791215219": {"name": "LordsofHell: Duriel, the Lord of Pain", "category": "Lore", "platform": "Console"}, "-1530801161": {"name": "LordsofHell: Mephisto, the Lord of Hatred", "category": "Lore", "platform": "Console"}, "1361465018": {"name": "LordsofHell: The Seven Lords of Hell", "category": "Lore", "platform": "Console"}, "1775133212": {"name": "Lore CainLetter", "category": "Lore", "platform": "Console"}, "1615247495": {"name": "Lore Catacombs NephDefenseSystem", "category": "Lore", "platform": "Console"}, "-1084060684": {"name": "Lore Festering CryptOfTheAncients", "category": "Lore", "platform": "Console"}, "108864625": {"name": "Lore Festering DrownedTemple", "category": "Lore", "platform": "Console"}, "-740914034": {"name": "Lore Festering WarriorsRest", "category": "Lore", "platform": "Console"}, "2011207568": {"name": "Lore X1 Bog Ideation AdriaSpikeChest", "category": "Lore", "platform": "Console"}, "216459655": {"name": "Lore X1 Graveyard Azthar", "category": "Lore", "platform": "Console"}, "-827657709": {"name": "Lore X1 Westm Legendary Drop", "category": "Lore", "platform": "Console"}, "-1004685329": {"name": "Lore x1 MysticIntro1", "category": "Lore", "platform": "Console"}, "-1004685328": {"name": "Lore x1 MysticIntro2", "category": "Lore", "platform": "Console"}, "-2124310248": {"name": "Lore_p2_DateDungeon_CovenPlans (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "-1307619936": {"name": "Lore_p2_ScoundrelEvent02_SimonNote (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "1390356236": {"name": "LostAngel: The Lost Warrior", "category": "Lore", "platform": "Console"}, "1487246296": {"name": "LoveLetter: A Love Letter", "category": "Lore", "platform": "Console"}, "-184131088": {"name": "MaghdaManor: Orders from Maghda", "category": "Lore", "platform": "Console"}, "18980873": {"name": "Malthael: The Path of Wisdom, Part 1", "category": "Lore", "platform": "Console"}, "18980874": {"name": "Malthael: The Path of Wisdom, Part 2", "category": "Lore", "platform": "Console"}, "18980875": {"name": "Malthael: The Path of Wisdom, Part 3", "category": "Lore", "platform": "Console"}, "18980876": {"name": "Malthael: The Path of Wisdom, Part 4", "category": "Lore", "platform": "Console"}, "18980877": {"name": "Malthael: The Path of Wisdom, Part 5", "category": "Lore", "platform": "Console"}, "18980878": {"name": "Malthael: The Path of Wisdom, Part 6", "category": "Lore", "platform": "Console"}, "3897062066": {"name": "Mira's Letter to Haedrig", "category": "Lore", "platform": "Console"}, "-768304375": {"name": "MisguidedFarmer: Farmer's Journal", "category": "Lore", "platform": "Console"}, "-1595216991": {"name": "Morgan: Morgan's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1595216990": {"name": "Morgan: Morgan's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1595216989": {"name": "Morgan: Morgan's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561999134": {"name": "Necromancer: Necromancer's Log", "category": "Lore", "platform": "Console"}, "1036599468": {"name": "Nephalem: The Destiny of the Nephalem, Part 1", "category": "Lore", "platform": "Console"}, "1036599469": {"name": "Nephalem: The Destiny of the Nephalem, Part 2", "category": "Lore", "platform": "Console"}, "1036599470": {"name": "Nephalem: The Destiny of the Nephalem, Part 3", "category": "Lore", "platform": "Console"}, "85406869": {"name": "Nephalem: The Drowned Temple", "category": "Lore", "platform": "Console"}, "1604771305": {"name": "Nephalem: The Last Stand of the Ancients", "category": "Lore", "platform": "Console"}, "1071008887": {"name": "Nephalem: The Nephalem Tome", "category": "Lore", "platform": "Console"}, "220221847": {"name": "Nephalem: Tomb Robber's Journal", "category": "Lore", "platform": "Console"}, "429729842": {"name": "Nephalem: Warrior's Rest", "category": "Lore", "platform": "Console"}, "-1608490938": {"name": "NephalemMiser: Miser's Will", "category": "Lore", "platform": "Console"}, "775555921": {"name": "NewTristram: New Tristram", "category": "Lore", "platform": "Console"}, "-1083079452": {"name": "Note: Secret Note", "category": "Lore", "platform": "Console"}, "1316599940": {"name": "Oasis: A Love Letter", "category": "Lore", "platform": "Console"}, "1676339915": {"name": "OasisCellars: The Imperial Guard's Orders", "category": "Lore", "platform": "Console"}, "-1048384993": {"name": "OldTristram: Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "-236966351": {"name": "OldTristram: Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1906290178": {"name": "OldTristram: Despina's Journal", "category": "Lore", "platform": "Console"}, "829218340": {"name": "OldTristram: Gillian's Diary, Part 1", "category": "Lore", "platform": "Console"}, "1594401494": {"name": "OldTristram: Gillian's Diary, Part 2", "category": "Lore", "platform": "Console"}, "316278028": {"name": "OldTristram: Lost Journal", "category": "Lore", "platform": "Console"}, "316278029": {"name": "OldTristram: Old Diary", "category": "Lore", "platform": "Console"}, "316278027": {"name": "OldTristram: Old Tristram Journal", "category": "Lore", "platform": "Console"}, "-700459563": {"name": "OldTristram: Traveler's Journal", "category": "Lore", "platform": "Console"}, "-289611678": {"name": "OldTristram: Villager's Journal", "category": "Lore", "platform": "Console"}, "1708077021": {"name": "OldTristram: Warriv's Journal", "category": "Lore", "platform": "Console"}, "-561113926": {"name": "OneLastEntry: Crumbling Journal", "category": "Lore", "platform": "Console"}, "-216253271": {"name": "PandExt: Legend of the Great Weapon", "category": "Lore", "platform": "Console"}, "551638722": {"name": "PandExt: Malthael's Plan", "category": "Lore", "platform": "Console"}, "-420053241": {"name": "Pandemonium: The History of Pandemonium, Part 1", "category": "Lore", "platform": "Console"}, "-420053240": {"name": "Pandemonium: The History of Pandemonium, Part 2", "category": "Lore", "platform": "Console"}, "-420053239": {"name": "Pandemonium: The History of Pandemonium, Part 3", "category": "Lore", "platform": "Console"}, "-420053238": {"name": "Pandemonium: The History of Pandemonium, Part 4", "category": "Lore", "platform": "Console"}, "-1604058933": {"name": "Poltahr: Poltahr's Notes", "category": "Lore", "platform": "Console"}, "-1861918345": {"name": "PortalRoulette: Lyndo's Journal", "category": "Lore", "platform": "Console"}, "613068827": {"name": "Priest: Priest's Contemplations, Part 1", "category": "Lore", "platform": "Console"}, "613068826": {"name": "Priest: Priest's Contemplations, Part 2", "category": "Lore", "platform": "Console"}, "1320763167": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "1320763168": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "1320763169": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "1758275411": {"name": "PromisesOfFezuul: The Promises of Fezuul al-Kazarr", "category": "Lore", "platform": "Console"}, "-139516026": {"name": "ProudWife: Bloodstained Letter", "category": "Lore", "platform": "Console"}, "3611879712": {"name": "Quill Fiend", "category": "Lore", "platform": "Console"}, "1276294793": {"name": "Rakanoth: Rakanoth, the Lord of Despair", "category": "Lore", "platform": "Console"}, "-1106592288": {"name": "Rakkis: Rakkis's Orders", "category": "Lore", "platform": "Console"}, "-1074332472": {"name": "RakkisHistory: The Testament of Rakkis, Part 1", "category": "Lore", "platform": "Console"}, "-1074332471": {"name": "RakkisHistory: The Testament of Rakkis, Part 2", "category": "Lore", "platform": "Console"}, "-1074332470": {"name": "RakkisHistory: The Testament of Rakkis, Part 3", "category": "Lore", "platform": "Console"}, "-1074332469": {"name": "RakkisHistory: The Testament of Rakkis, Part 4", "category": "Lore", "platform": "Console"}, "-1074332468": {"name": "RakkisHistory: The Testament of Rakkis, Part 5", "category": "Lore", "platform": "Console"}, "-1074332467": {"name": "RakkisHistory: The Testament of Rakkis, Part 6", "category": "Lore", "platform": "Console"}, "-1074332466": {"name": "RakkisHistory: The Testament of Rakkis, Part 7", "category": "Lore", "platform": "Console"}, "-1074332465": {"name": "RakkisHistory: The Testament of Rakkis, Part 8", "category": "Lore", "platform": "Console"}, "-1074332464": {"name": "RakkisHistory: The Testament of Rakkis, Part 9", "category": "Lore", "platform": "Console"}, "1960749072": {"name": "Realmwalker: The Realmwalker", "category": "Lore", "platform": "Console"}, "3580037015": {"name": "Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "2895121073": {"name": "Scavenger", "category": "Lore", "platform": "Console"}, "-561655662": {"name": "Scoundrel: Scoundrel's Journal", "category": "Lore", "platform": "Console"}, "648677458": {"name": "Siege: Missive from Imperius", "category": "Lore", "platform": "Console"}, "-1327438701": {"name": "Siege: Siege Runes", "category": "Lore", "platform": "Console"}, "1667935935": {"name": "SkeletonKing: The Skeleton King", "category": "Lore", "platform": "Console"}, "-21507498": {"name": "SpiderQueen: The Spider Queen", "category": "Lore", "platform": "Console"}, "1881837798": {"name": "Templar: Bloodied Parchment", "category": "Lore", "platform": "Console"}, "1881837797": {"name": "Templar: Bloodied Scraps", "category": "Lore", "platform": "Console"}, "1792637338": {"name": "TemplarMaester: Grand Maester's Journal", "category": "Lore", "platform": "Console"}, "1776052671": {"name": "TemplarMaester: The Maester's Proclamation", "category": "Lore", "platform": "Console"}, "464105835": {"name": "Tinker: Wandering Tinker's Diary", "category": "Lore", "platform": "Console"}, "3594507733": {"name": "Traveler's Journal", "category": "Lore", "platform": "Console"}, "732715821": {"name": "UriktheSeer: Notes of Urik the Seer, Part 1", "category": "Lore", "platform": "Console"}, "732715822": {"name": "UriktheSeer: Notes of Urik the Seer, Part 2", "category": "Lore", "platform": "Console"}, "732715823": {"name": "UriktheSeer: Notes of Urik the Seer, Part 3", "category": "Lore", "platform": "Console"}, "-645692806": {"name": "Urzael: Urzael's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-645692805": {"name": "Urzael: Urzael's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-645692804": {"name": "Urzael: Urzael's Journal, Part 3", "category": "Lore", "platform": "Console"}, "4005355618": {"name": "Villager's Journal", "category": "Lore", "platform": "Console"}, "-1451420418": {"name": "WaterPuzzle: The Chamber of Faces", "category": "Lore", "platform": "Console"}, "1223177093": {"name": "Westm: It's a Trap", "category": "Lore", "platform": "Console"}, "831394876": {"name": "Westm: The Cult Shall Rise Again", "category": "Lore", "platform": "Console"}, "913430382": {"name": "Westm: The King's Journal, Part 1", "category": "Lore", "platform": "Console"}, "913430383": {"name": "Westm: The King's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1218326648": {"name": "Westm: The King's Note to Lord Wynton", "category": "Lore", "platform": "Console"}, "1526997743": {"name": "Westm: The Plague Tunnels", "category": "Lore", "platform": "Console"}, "-1469466389": {"name": "Westm: The Souls of Westmarch", "category": "Lore", "platform": "Console"}, "-916745255": {"name": "Westmarch: The History of Westmarch, Part 1", "category": "Lore", "platform": "Console"}, "-916745254": {"name": "Westmarch: The History of Westmarch, Part 2", "category": "Lore", "platform": "Console"}, "-916745253": {"name": "Westmarch: The History of Westmarch, Part 3", "category": "Lore", "platform": "Console"}, "-916745252": {"name": "Westmarch: The History of Westmarch, Part 4", "category": "Lore", "platform": "Console"}, "-916745251": {"name": "Westmarch: The History of Westmarch, Part 5", "category": "Lore", "platform": "Console"}, "-916745250": {"name": "Westmarch: The History of Westmarch, Part 6", "category": "Lore", "platform": "Console"}, "-916745249": {"name": "Westmarch: The History of Westmarch, Part 7", "category": "Lore", "platform": "Console"}, "-223645750": {"name": "X1 Lore Besitary RevenantShieldGuard", "category": "Lore", "platform": "Console"}, "1571805338": {"name": "X1 Lore Bestiary GhastlySeraph", "category": "Lore", "platform": "Console"}, "1836003891": {"name": "X1 Lore Bestiary RevenantArcher", "category": "Lore", "platform": "Console"}, "-1635681275": {"name": "x1 Bog Lore AdriaBetrayal", "category": "Lore", "platform": "Console"}, "-8314071": {"name": "x1 Bog Lore AdriaEmptiness", "category": "Lore", "platform": "Console"}, "1923206206": {"name": "x1 Bog Lore AdriaLosingControl", "category": "Lore", "platform": "Console"}, "2045759001": {"name": "x1 Bog Lore AdriaNewHost", "category": "Lore", "platform": "Console"}, "118984382": {"name": "x1 Bog Lore AdriaPower", "category": "Lore", "platform": "Console"}, "-134175942": {"name": "x1 Bog Lore AdriaVoices", "category": "Lore", "platform": "Console"}, "-1074332440": {"name": "x1 Bog Lore RakkisHistory10", "category": "Lore", "platform": "Console"}}, "Maces, One-Handed": {"-1656026177": {"name": "02: Cudgel (DPS 9.6-11.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026176": {"name": "03: Morning Star (DPS 15.0-16.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026175": {"name": "04: Mace (DPS 18.6-20.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026174": {"name": "05: Flanged Mace (DPS 23.4-25.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026173": {"name": "06: Hammer (DPS 28.2-30.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026172": {"name": "07: War Gavel (DPS 33.6-35.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025089": {"name": "08: Bludgeon (DPS 43.8-45.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025088": {"name": "09: Spiked Baton (DPS 52.2-54.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025087": {"name": "10: War Mace (DPS 62.4-64.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025086": {"name": "11: Gada (DPS 73.2-75.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025085": {"name": "12: Pernach (DPS 85.2-88.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025084": {"name": "13: Heavy Hammer (DPS 102.0-105.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025083": {"name": "14: War Hammer (DPS 124.8-128.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656024000": {"name": "15: Skull Crusher (DPS 138.0-143.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023999": {"name": "16: Truncheon (DPS 155.4-160.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023998": {"name": "17: Death Mace (DPS 174.0-179.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023997": {"name": "18: Tripyor (DPS 192.6-199.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023996": {"name": "19: Goedendag (DPS 237.0-244.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023995": {"name": "20: Crag Hammer (DPS 273.6-282.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023994": {"name": "21: Demolisher (DPS 318.0-327.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022911": {"name": "22: Brutalizer (DPS 429.6-436.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022910": {"name": "23: Skullsplitter (DPS 540.6-547.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099965": {"name": "Art Test Mace One-Handed 1", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099964": {"name": "Art Test Mace One-Handed 2", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099963": {"name": "Art Test Mace One-Handed 3", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099962": {"name": "Art Test Mace One-Handed 4", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099961": {"name": "Art Test Mace One-Handed 5", "category": "Maces, One-Handed", "platform": "Console"}, "-1473010435": {"name": "Legendary: Deadeye's Mace (Patch 2.1.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894988668": {"name": "Legendary: Devastator", "category": "Maces, One-Handed", "platform": "Console"}, "1889806096": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1889808540": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325116": {"name": "Legendary: Earthshatter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895276164": {"name": "Legendary: Echoing Fury", "category": "Maces, One-Handed", "platform": "Console"}, "1880318728": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1880321172": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325108": {"name": "Legendary: Echoing Fury (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856068897": {"name": "Legendary: Jace's Hammer of Vigilance", "category": "Maces, One-Handed", "platform": "Console"}, "-1856140771": {"name": "Legendary: Mad Monarch's Scepter", "category": "Maces, One-Handed", "platform": "Console"}, "-1895024605": {"name": "Legendary: Nailbiter", "category": "Maces, One-Handed", "platform": "Console"}, "1888620175": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1888622619": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325115": {"name": "Legendary: Nailbiter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895204290": {"name": "Legendary: Neanderthal", "category": "Maces, One-Handed", "platform": "Console"}, "1882690570": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1882693014": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325110": {"name": "Legendary: Neanderthal (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895132416": {"name": "Legendary: Nutcracker", "category": "Maces, One-Handed", "platform": "Console"}, "1885062412": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1885064856": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325112": {"name": "Legendary: Nutcracker (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895240227": {"name": "Legendary: Odyn Son", "category": "Maces, One-Handed", "platform": "Console"}, "1881504649": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1881507093": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325109": {"name": "Legendary: Odyn Son (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856104834": {"name": "Legendary: Solanium", "category": "Maces, One-Handed", "platform": "Console"}, "-1894090243": {"name": "Legendary: Sun Keeper", "category": "Maces, One-Handed", "platform": "Console"}, "1919454121": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1919456565": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325141": {"name": "Legendary: Sun Keeper (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895060542": {"name": "Legendary: Telranden's Hand", "category": "Maces, One-Handed", "platform": "Console"}, "1887434254": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1887436698": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325114": {"name": "Legendary: Telranden's Hand (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894126180": {"name": "Legendary: Wirt's Original Leg", "category": "Maces, One-Handed", "platform": "Console"}, "1918268200": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1918270644": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325140": {"name": "Legendary: Wirt's Original Leg (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}}, "Maces, Two-Handed": {"-1616890784": {"name": "02: Two-Handed Mace (DPS 20.3-21.6)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890783": {"name": "03: Two-Handed Hammer (DPS 24.8-26.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890782": {"name": "04: Maul (DPS 31.5-32.9)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890781": {"name": "05: Mallet (DPS 37.8-40.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890780": {"name": "06: Great Hammer (DPS 45.5-48.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889696": {"name": "07: Dire Club (DPS 55.8-58.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889695": {"name": "08: Dire Mace (DPS 66.6-70.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889694": {"name": "09: Sledge Hammer (DPS 81.9-86.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889693": {"name": "10: Great Maul (DPS 98.6-104.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889692": {"name": "11: War Mallet (DPS 117.9-124.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889691": {"name": "12: Rock Breaker (DPS 144.5-151.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888607": {"name": "13: Wrecker (DPS 196.7-206.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888606": {"name": "14: Dread Mace (DPS 249.3-260.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888605": {"name": "15: War Sledge (DPS 315.9-326.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888604": {"name": "16: War Maul (DPS 437.9-448.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888603": {"name": "17: Slag Hammer (DPS 518.4-529.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888602": {"name": "18: Doom Hammer (DPS 613.4-624.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887518": {"name": "19: Royal Mace (DPS 774.0-786.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887517": {"name": "20: Persuader (DPS 1058.5-1070.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064028": {"name": "Art Test Mace Two-Handed 1", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064027": {"name": "Art Test Mace Two-Handed 2", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064026": {"name": "Art Test Mace Two-Handed 3", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064025": {"name": "Art Test Mace Two-Handed 4", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064024": {"name": "Art Test Mace Two-Handed 5", "category": "Maces, Two-Handed", "platform": "Console"}, "59108159": {"name": "Legendary: Arthef's Spark of Life", "category": "Maces, Two-Handed", "platform": "Console"}, "1950491947": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1950494391": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460503": {"name": "Legendary: Boneshatter (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954049710": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954052154": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460506": {"name": "Legendary: Cataclysm (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59036285": {"name": "Legendary: Crushbane", "category": "Maces, Two-Handed", "platform": "Console"}, "1948120105": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1948122549": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460501": {"name": "Legendary: Crushbane (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323781": {"name": "Legendary: Schaefer's Hammer", "category": "Maces, Two-Handed", "platform": "Console"}, "1957607473": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1957609917": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460509": {"name": "Legendary: Schaefer's Hammer (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60186269": {"name": "Legendary: Skywarden", "category": "Maces, Two-Handed", "platform": "Console"}, "1986069577": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1986072021": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460533": {"name": "Legendary: Skywarden (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59072222": {"name": "Legendary: Sledge of Athskeleng", "category": "Maces, Two-Handed", "platform": "Console"}, "1949306026": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1949308470": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460502": {"name": "Legendary: Sledge of Athskeleng (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "98279489": {"name": "Legendary: Soulsmasher", "category": "Maces, Two-Handed", "platform": "Console"}, "59215970": {"name": "Legendary: Sunder", "category": "Maces, Two-Handed", "platform": "Console"}, "98243552": {"name": "Legendary: The Furnace", "category": "Maces, Two-Handed", "platform": "Console"}, "60258143": {"name": "Legendary: Wrath of the Bone King", "category": "Maces, Two-Handed", "platform": "Console"}, "1988441419": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1988443863": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460535": {"name": "Legendary: Wrath of the Bone King (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60257879": {"name": "Legendary: Wrath of the Bone King (Patch 2.1.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323518": {"name": "legendary: Schaefer's Hammer (Patch 2.2.0)", "category": "Maces, Two-Handed", "platform": "Console"}}, "Mighty Belts": {"2112155407": {"name": "02: Harness (AR 32-37)", "category": "Mighty Belts", "platform": "Console"}, "2112155408": {"name": "03: Braid (AR 53-61)", "category": "Mighty Belts", "platform": "Console"}, "2112155409": {"name": "04: Grand Belt (AR 74-100)", "category": "Mighty Belts", "platform": "Console"}, "2112156495": {"name": "05: Baldric (AR 101-132)", "category": "Mighty Belts", "platform": "Console"}, "2112156496": {"name": "06: Blade Harness (AR 133-164)", "category": "Mighty Belts", "platform": "Console"}, "2112156497": {"name": "07: Iron Braid (AR 165-205)", "category": "Mighty Belts", "platform": "Console"}, "2112156498": {"name": "08: Steel Chain (AR 206-225)", "category": "Mighty Belts", "platform": "Console"}, "2112157584": {"name": "09: Lock (AR 226-252)", "category": "Mighty Belts", "platform": "Console"}, "2112157585": {"name": "10: Bronze Links (AR 253-285)", "category": "Mighty Belts", "platform": "Console"}, "2112157586": {"name": "11: Heavy Baldric (AR 286-318)", "category": "Mighty Belts", "platform": "Console"}, "2112157587": {"name": "12: Grand Chain (AR 320-419)", "category": "Mighty Belts", "platform": "Console"}, "2112157588": {"name": "13: Platinum Lock (AR 420-586)", "category": "Mighty Belts", "platform": "Console"}, "2112157589": {"name": "14: Mighty Scourge (AR 586-674)", "category": "Mighty Belts", "platform": "Console"}, "325816755": {"name": "Art Test BarbBelt 1", "category": "Mighty Belts", "platform": "Console"}, "325816756": {"name": "Art Test BarbBelt 2", "category": "Mighty Belts", "platform": "Console"}, "325816757": {"name": "Art Test BarbBelt 3", "category": "Mighty Belts", "platform": "Console"}, "325816758": {"name": "Art Test BarbBelt 4", "category": "Mighty Belts", "platform": "Console"}, "325816759": {"name": "Art Test BarbBelt 5", "category": "Mighty Belts", "platform": "Console"}, "924282931": {"name": "Legendary: Ageless Might", "category": "Mighty Belts", "platform": "Console"}, "436488351": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "436490795": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630773": {"name": "Legendary: Ageless Might (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963274576": {"name": "Legendary: Ancients' Discontent", "category": "Mighty Belts", "platform": "Console"}, "963166765": {"name": "Legendary: Chilanik's Chain", "category": "Mighty Belts", "platform": "Console"}, "924031372": {"name": "Legendary: Dread Iron", "category": "Mighty Belts", "platform": "Console"}, "428186904": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "428189348": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630780": {"name": "Legendary: Dread Iron (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924139183": {"name": "Legendary: Girdle of Giants", "category": "Mighty Belts", "platform": "Console"}, "431744667": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "431747111": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630777": {"name": "Legendary: Girdle of Giants (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924246994": {"name": "Legendary: Kotuur's Brace", "category": "Mighty Belts", "platform": "Console"}, "435302430": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "435304874": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630774": {"name": "Legendary: Kotuur's Brace (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924175120": {"name": "Legendary: Lamentation", "category": "Mighty Belts", "platform": "Console"}, "432930588": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "432933032": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630776": {"name": "Legendary: Lamentation (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924174856": {"name": "Legendary: Lamentation (Patch 2.1.0)", "category": "Mighty Belts", "platform": "Console"}, "924067309": {"name": "Legendary: Pride of Cassius", "category": "Mighty Belts", "platform": "Console"}, "429372825": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "429375269": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630779": {"name": "Legendary: Pride of Cassius (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963310513": {"name": "Legendary: Promise of the Doomed Forebearer", "category": "Mighty Belts", "platform": "Console"}, "924211057": {"name": "Legendary: The Undisputed Champion", "category": "Mighty Belts", "platform": "Console"}, "434116509": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "434118953": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630775": {"name": "Legendary: The Undisputed Champion (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737386": {"name": "Legendary: The Undisputed Champion (Patch 2.1.2)", "category": "Mighty Belts", "platform": "Console"}, "430558746": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "430561190": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630778": {"name": "Legendary: Thunder God's Vigor (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963238639": {"name": "Legendary: Wodir Harness", "category": "Mighty Belts", "platform": "Console"}, "963202702": {"name": "Legendary: x1_BarbBelt_norm_unique_11", "category": "Mighty Belts", "platform": "Console"}, "-1303630772": {"name": "Set: Immortal King's Detail (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924318868": {"name": "Set: Immortal King's Tribal Binding", "category": "Mighty Belts", "platform": "Console"}, "437674272": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "437676716": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737381": {"name": "legendary: Dread Iron (Patch 2.2.0)", "category": "Mighty Belts", "platform": "Console"}}, "Mighty Weapons, One-Handed": {"290066502": {"name": "02: Carver (DPS 14.3-16.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066503": {"name": "03: Maw Axe (DPS 21.5-23.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066504": {"name": "04: War Blade (DPS 31.2-33.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067590": {"name": "05: Scythe (DPS 36.4-38.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067591": {"name": "06: Machete (DPS 54.6-56.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067592": {"name": "07: Gutwrench (DPS 82.6-86.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067593": {"name": "08: Rage Blade (DPS 118.3-122.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068679": {"name": "09: Reaper (DPS 153.4-159.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068680": {"name": "10: Chopsword (DPS 206.7-214.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068681": {"name": "11: Massacre Axe (DPS 238.6-246.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068682": {"name": "12: Slayer (DPS 277.6-285.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069768": {"name": "13: Caldean Sword (DPS 371.8-379.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069769": {"name": "14: Limb Cleaver (DPS 461.5-469.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026495": {"name": "Art Test Mighty One-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026496": {"name": "Art Test Mighty One-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026497": {"name": "Art Test Mighty One-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026498": {"name": "Art Test Mighty One-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026499": {"name": "Art Test Mighty One-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062432": {"name": "Art Test Mighty Two-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062433": {"name": "Art Test Mighty Two-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062434": {"name": "Art Test Mighty Two-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062435": {"name": "Art Test Mighty Two-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062436": {"name": "Art Test Mighty Two-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511328230": {"name": "Legendary: Ambo's Pride", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665698662": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665701106": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986962": {"name": "Legendary: Ambo's Pride (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512406340": {"name": "Legendary: Blade of the Warlord", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630121032": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630123476": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986932": {"name": "Legendary: Blade of the Warlord (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473342821": {"name": "Legendary: Dishonored Legacy", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512370403": {"name": "Legendary: Fjord Cutter", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631306953": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631309397": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986933": {"name": "Legendary: Fjord Cutter (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625377348": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625379792": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986928": {"name": "Legendary: Harvest Moon (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473414695": {"name": "Legendary: Hellion Scale", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512550088": {"name": "Legendary: Night's Reaping", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473306884": {"name": "Legendary: Oathkeeper", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473378758": {"name": "Legendary: Remorseless", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986960": {"name": "Set: Bul-Kathos's Sacred Charge (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511400104": {"name": "Set: Bul-Kathos's Solemn Vow", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663326820": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663329264": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986961": {"name": "Set: Bul-Kathos's Tribal Guardian (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511364167": {"name": "Set: Bul-Kathos's Warrior Blood", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664512741": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664515185": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986965": {"name": "Set: Hallowed Destroyer (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511220419": {"name": "Set: Hallowed Nemesis", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669258869": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669256425": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}}, "Mighty Weapons, Two-Handed": {"329201895": {"name": "02: Giant Sword (DPS 18.0-19.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201896": {"name": "03: Giant Hammer (DPS 25.5-27.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201897": {"name": "04: Giant Axe (DPS 36.0-37.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202983": {"name": "05: Redwood War Club (DPS 60.6-63.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202984": {"name": "06: Colossus Sword (DPS 81.5-86.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202985": {"name": "07: Crusher (DPS 110.5-116.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202986": {"name": "08: Colossus Axe (DPS 169.0-176.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204072": {"name": "09: Battersmash (DPS 248.5-257.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204073": {"name": "10: Titan Sword (DPS 397.5-408.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204074": {"name": "11: Behemoth (DPS 469.0-481.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204075": {"name": "12: Titan Axe (DPS 555.0-567.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205161": {"name": "13: Hassan Chopper (DPS 691.9-703.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205162": {"name": "14: Steppes Smasher (DPS 940.0-951.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441870172": {"name": "Legendary: Bastion's Revered", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696736488": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696738932": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122324": {"name": "Legendary: Bastion's Revered (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441869908": {"name": "Legendary: Bastion's Revered (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441942046": {"name": "Legendary: Fury of the Vanished Peak", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699108330": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699110774": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122326": {"name": "Legendary: Fury of the Vanished Peak (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-96858155": {"name": "Legendary: Grim Reaper", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "480897754": {"name": "Legendary: Madawc's Sorrow", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-389442788": {"name": "Legendary: The Blackrock Destroyer (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441762361": {"name": "Legendary: The Gavel of Judgment", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693178725": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693181169": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122321": {"name": "Legendary: The Gavel of Judgment (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733500039": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733502483": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122355": {"name": "Legendary: Unending War (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442984219": {"name": "Legendary: War of the Dead", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442912345": {"name": "Set: Immortal King's Boulder Breaker", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731128197": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731130641": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122353": {"name": "Set: Immortal King's Stone Crusher (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}}, "Mightys, Two-Handed": {}, "Mojos": {"-136816474": {"name": "02: Shrunken Head (+(2-3)-(3-5) DMG)", "category": "Mojos", "platform": "Console"}, "-136816473": {"name": "03: Caged Horror (+(3-5)-(4-8) DMG)", "category": "Mojos", "platform": "Console"}, "-136816472": {"name": "04: Viper (+(3-6)-(4-10) DMG)", "category": "Mojos", "platform": "Console"}, "-136815386": {"name": "05: Gris-Gris Moppet (+(4-8)-(5-13) DMG)", "category": "Mojos", "platform": "Console"}, "-136815385": {"name": "06: Tzantza (+(6-11)-(7-19) DMG)", "category": "Mojos", "platform": "Console"}, "-136815384": {"name": "07: Living Tentacle (+(8-16)-(9-29) DMG)", "category": "Mojos", "platform": "Console"}, "-136815383": {"name": "08: Copperhead (+(13-26)-(14-45) DMG)", "category": "Mojos", "platform": "Console"}, "-136814297": {"name": "09: Wicker Man (+(17-39)-(18-114) DMG)", "category": "Mojos", "platform": "Console"}, "-136814296": {"name": "10: Muttering Head (+(19-58)-(20-213) DMG)", "category": "Mojos", "platform": "Console"}, "-136814295": {"name": "11: Unspeakable Thing (+(24-72)-(25-265) DMG)", "category": "Mojos", "platform": "Console"}, "-136814294": {"name": "12: Kurastian Asp (+(28-110)-(29-405) DMG)", "category": "Mojos", "platform": "Console"}, "-136814293": {"name": "13: Skull Talisman (+(126-158)-(127-190) DMG)", "category": "Mojos", "platform": "Console"}, "-136814292": {"name": "14: Thing That Should Not Be (+(262-328)-(263-394) DMG)", "category": "Mojos", "platform": "Console"}, "1629900554": {"name": "Art Test Mojo 1", "category": "Mojos", "platform": "Console"}, "1629900555": {"name": "Art Test Mojo 2", "category": "Mojos", "platform": "Console"}, "1629900556": {"name": "Art Test Mojo 3", "category": "Mojos", "platform": "Console"}, "1629900557": {"name": "Art Test Mojo 4", "category": "Mojos", "platform": "Console"}, "1629900558": {"name": "Art Test Mojo 5", "category": "Mojos", "platform": "Console"}, "-1667471440": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-1667468996": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608100": {"name": "Legendary: Bitterness (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961544827": {"name": "Legendary: Gazing Demise", "category": "Mojos", "platform": "Console"}, "-1666285519": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-1666283075": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608099": {"name": "Legendary: Gazing Demise (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961508890": {"name": "Legendary: Homunculus", "category": "Mojos", "platform": "Console"}, "-1665099598": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-1665097154": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608098": {"name": "Legendary: Homunculus (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922445371": {"name": "Legendary: Shukrani's Triumph", "category": "Mojos", "platform": "Console"}, "-922409434": {"name": "Legendary: Sorrowful Countenance", "category": "Mojos", "platform": "Console"}, "-961580764": {"name": "Legendary: Spite", "category": "Mojos", "platform": "Console"}, "-961329205": {"name": "Legendary: Thing of the Deep", "category": "Mojos", "platform": "Console"}, "-1659169993": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-1659167549": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608093": {"name": "Legendary: Thing of the Deep (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961365142": {"name": "Legendary: Uhkapian Serpent", "category": "Mojos", "platform": "Console"}, "-1660355914": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-1660353470": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608094": {"name": "Legendary: Uhkapian Serpent (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922373497": {"name": "Legendary: Vile Hive", "category": "Mojos", "platform": "Console"}, "1413644935": {"name": "P2 mojo norm Legendary 01", "category": "Mojos", "platform": "Console"}, "1413644936": {"name": "P2 mojo norm Legendary 02", "category": "Mojos", "platform": "Console"}, "1413644937": {"name": "P2 mojo norm Legendary 03", "category": "Mojos", "platform": "Console"}, "-960466717": {"name": "Set: Manajuma's Gory Fetch", "category": "Mojos", "platform": "Console"}, "-1630707889": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-1630705445": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608069": {"name": "Set: Manajuma's Ritual Prize (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-63608068": {"name": "Set: Zunimassa's Ferocity (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-960430780": {"name": "Set: Zunimassa's String of Skulls", "category": "Mojos", "platform": "Console"}, "-1629521968": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-1629519524": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-961509153": {"name": "legendary: Homunculus (Patch 2.2.0)", "category": "Mojos", "platform": "Console"}}, "NPC Items": {"1372800103": {"name": "A Summoner's Journal", "category": "NPC Items", "platform": "Console"}, "1366034119": {"name": "A2C2EmptyCage", "category": "NPC Items", "platform": "Console"}, "-894018760": {"name": "A2C2HusamHead", "category": "NPC Items", "platform": "Console"}, "1506900471": {"name": "A2C2NecromancerCrystal", "category": "NPC Items", "platform": "Console"}, "-1176971336": {"name": "A2C2OreBag", "category": "NPC Items", "platform": "Console"}, "-701130141": {"name": "A2C2RygnarIdol", "category": "NPC Items", "platform": "Console"}, "-1969048485": {"name": "A2C2SharkHide", "category": "NPC Items", "platform": "Console"}, "524402999": {"name": "A2C2SharkNecklace", "category": "NPC Items", "platform": "Console"}, "297778632": {"name": "A2C2WantedPoster", "category": "NPC Items", "platform": "Console"}, "1135854513": {"name": "A2C2WantedPosterGood", "category": "NPC Items", "platform": "Console"}, "-284487217": {"name": "ActIQ2 RatMageSkull", "category": "NPC Items", "platform": "Console"}, "956379400": {"name": "Ahren's Hammer", "category": "NPC Items", "platform": "Console"}, "893398919": {"name": "AlbrechtsRemains", "category": "NPC Items", "platform": "Console"}, "-1240838296": {"name": "Ancient Medallion", "category": "NPC Items", "platform": "Console"}, "1475923527": {"name": "Ancient Tome Page", "category": "NPC Items", "platform": "Console"}, "-831189640": {"name": "Angelic Seal", "category": "NPC Items", "platform": "Console"}, "-885657485": {"name": "Antique Box", "category": "NPC Items", "platform": "Console"}, "-309356827": {"name": "Aqueduct Key", "category": "NPC Items", "platform": "Console"}, "493907862": {"name": "Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "-470655325": {"name": "Beacon of Honor", "category": "NPC Items", "platform": "Console"}, "-470655324": {"name": "Beacon of Light", "category": "NPC Items", "platform": "Console"}, "-246893943": {"name": "Black Soulstone", "category": "NPC Items", "platform": "Console"}, "504121446": {"name": "Blackened Journal", "category": "NPC Items", "platform": "Console"}, "1818884426": {"name": "Blacksmith's Tome", "category": "NPC Items", "platform": "Console"}, "263122102": {"name": "Bogus Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "944034263": {"name": "Broken Crown", "category": "NPC Items", "platform": "Console"}, "-63906132": {"name": "Broken Doll", "category": "NPC Items", "platform": "Console"}, "1201838506": {"name": "Calldown Grenade", "category": "NPC Items", "platform": "Console"}, "-1797642504": {"name": "Caravan Inventory List", "category": "NPC Items", "platform": "Console"}, "-110888638": {"name": "Chain Key", "category": "NPC Items", "platform": "Console"}, "1061128541": {"name": "Cloud Fire", "category": "NPC Items", "platform": "Console"}, "-565248060": {"name": "Cultist Cellar Key", "category": "NPC Items", "platform": "Console"}, "-613437014": {"name": "DevilsHand: Aidan's Memento", "category": "NPC Items", "platform": "Console"}, "-613616703": {"name": "DevilsHand: Broken Oath", "category": "NPC Items", "platform": "Console"}, "-613437017": {"name": "DevilsHand: Cain's Memento", "category": "NPC Items", "platform": "Console"}, "-613544825": {"name": "DevilsHand: Dark Coven Familiar", "category": "NPC Items", "platform": "Console"}, "-613544828": {"name": "DevilsHand: Dark Coven Insignia", "category": "NPC Items", "platform": "Console"}, "-613544826": {"name": "DevilsHand: Dark Coven Jar of Reagents", "category": "NPC Items", "platform": "Console"}, "-613544829": {"name": "DevilsHand: Dark Coven Scroll of Illusions", "category": "NPC Items", "platform": "Console"}, "-613544827": {"name": "DevilsHand: Dark Coven Torturing Device", "category": "NPC Items", "platform": "Console"}, "-613437012": {"name": "DevilsHand: Gideon's Memento", "category": "NPC Items", "platform": "Console"}, "-613508887": {"name": "DevilsHand: Icon of Envy", "category": "NPC Items", "platform": "Console"}, "-613508886": {"name": "DevilsHand: Icon of Gluttony", "category": "NPC Items", "platform": "Console"}, "-613508891": {"name": "DevilsHand: Icon of Greed", "category": "NPC Items", "platform": "Console"}, "-613508888": {"name": "DevilsHand: Icon of Lust", "category": "NPC Items", "platform": "Console"}, "-613508889": {"name": "DevilsHand: Icon of Pride", "category": "NPC Items", "platform": "Console"}, "-613508890": {"name": "DevilsHand: Icon of Sloth", "category": "NPC Items", "platform": "Console"}, "-613508892": {"name": "DevilsHand: Icon of Wrath", "category": "NPC Items", "platform": "Console"}, "-613437016": {"name": "DevilsHand: Leah's Memento", "category": "NPC Items", "platform": "Console"}, "-613616702": {"name": "DevilsHand: Love's Oath", "category": "NPC Items", "platform": "Console"}, "-613437013": {"name": "DevilsHand: Ogden's Memento", "category": "NPC Items", "platform": "Console"}, "-613616701": {"name": "DevilsHand: Selfless Oath", "category": "NPC Items", "platform": "Console"}, "-613580763": {"name": "DevilsHand: The Black King's Bloodied Gauntlet", "category": "NPC Items", "platform": "Console"}, "-613580762": {"name": "DevilsHand: The Black King's Journal", "category": "NPC Items", "platform": "Console"}, "-613580765": {"name": "DevilsHand: The Black King's Skull", "category": "NPC Items", "platform": "Console"}, "-613580764": {"name": "DevilsHand: The Black King's Tainted Elixir", "category": "NPC Items", "platform": "Console"}, "-613580766": {"name": "DevilsHand: The Black King's Trophy", "category": "NPC Items", "platform": "Console"}, "-613437018": {"name": "DevilsHand: Warriv's Memento", "category": "NPC Items", "platform": "Console"}, "-613437015": {"name": "DevilsHand: Wirt's Memento", "category": "NPC Items", "platform": "Console"}, "-473140170": {"name": "Event: Alchemist Concoction", "category": "NPC Items", "platform": "Console"}, "452865871": {"name": "Event: Aperture Key", "category": "NPC Items", "platform": "Console"}, "-1312544703": {"name": "Event: Battle Elixir", "category": "NPC Items", "platform": "Console"}, "66225719": {"name": "Event: Battlefield Reports", "category": "NPC Items", "platform": "Console"}, "-1961273523": {"name": "Event: Bones of the Matriarch1", "category": "NPC Items", "platform": "Console"}, "-1961273522": {"name": "Event: Bones of the Matriarch2", "category": "NPC Items", "platform": "Console"}, "-1961273521": {"name": "Event: Bones of the Matriarch3", "category": "NPC Items", "platform": "Console"}, "1197498604": {"name": "Event: Dusty Old Tome", "category": "NPC Items", "platform": "Console"}, "463155324": {"name": "Event: Forboding Tome", "category": "NPC Items", "platform": "Console"}, "-934435532": {"name": "Event: Jeweled Scabbard", "category": "NPC Items", "platform": "Console"}, "1465477567": {"name": "Event: Medical Supplies", "category": "NPC Items", "platform": "Console"}, "-694090266": {"name": "Event: Officer's Orders", "category": "NPC Items", "platform": "Console"}, "-2013751652": {"name": "Event: Templar Object 1", "category": "NPC Items", "platform": "Console"}, "-1003233507": {"name": "Event: The Matriarch's Skeleton", "category": "NPC Items", "platform": "Console"}, "899528155": {"name": "FacePuzzleSmallKey", "category": "NPC Items", "platform": "Console"}, "-1986712818": {"name": "Fuad's Journal", "category": "NPC Items", "platform": "Console"}, "1331402556": {"name": "Greater Shard", "category": "NPC Items", "platform": "Console"}, "301784336": {"name": "Heretic Text", "category": "NPC Items", "platform": "Console"}, "-705827599": {"name": "HunterJournal", "category": "NPC Items", "platform": "Console"}, "1742022798": {"name": "Iron Wolf Captain's Journal", "category": "NPC Items", "platform": "Console"}, "680369210": {"name": "Jail Gate Key", "category": "NPC Items", "platform": "Console"}, "-78029774": {"name": "Jelisa's Wedding Ring", "category": "NPC Items", "platform": "Console"}, "1018820302": {"name": "Jeweler's Crucible", "category": "NPC Items", "platform": "Console"}, "872964849": {"name": "Journal of Hansan Haile, Captain", "category": "NPC Items", "platform": "Console"}, "1264544813": {"name": "Khan's Tomb Key", "category": "NPC Items", "platform": "Console"}, "-1071052922": {"name": "Kulle's Blood", "category": "NPC Items", "platform": "Console"}, "-1341834848": {"name": "Kulle's Body", "category": "NPC Items", "platform": "Console"}, "-1341834849": {"name": "Kulle's Heart", "category": "NPC Items", "platform": "Console"}, "425198027": {"name": "Larus's Log", "category": "NPC Items", "platform": "Console"}, "1790135009": {"name": "Mausoleum Key", "category": "NPC Items", "platform": "Console"}, "-397905230": {"name": "Mira's Letter to Haedrig", "category": "NPC Items", "platform": "Console"}, "-1140969500": {"name": "Mysterious Box", "category": "NPC Items", "platform": "Console"}, "1816611999": {"name": "Mystery Amulet", "category": "NPC Items", "platform": "Console"}, "-1493063970": {"name": "Mystery Belt", "category": "NPC Items", "platform": "Console"}, "-2026108002": {"name": "Mystery Boots", "category": "NPC Items", "platform": "Console"}, "1281756953": {"name": "Mystery Bracers", "category": "NPC Items", "platform": "Console"}, "-594428401": {"name": "Mystery Chest Armor", "category": "NPC Items", "platform": "Console"}, "2050033703": {"name": "Mystery Gloves", "category": "NPC Items", "platform": "Console"}, "-1492848355": {"name": "Mystery Helm", "category": "NPC Items", "platform": "Console"}, "-1492657844": {"name": "Mystery Mojo", "category": "NPC Items", "platform": "Console"}, "215071258": {"name": "Mystery Orb", "category": "NPC Items", "platform": "Console"}, "-2010009315": {"name": "Mystery Pants", "category": "NPC Items", "platform": "Console"}, "-1843121997": {"name": "Mystery Quiver", "category": "NPC Items", "platform": "Console"}, "-1492484569": {"name": "Mystery Ring", "category": "NPC Items", "platform": "Console"}, "-1780286480": {"name": "Mystery Shield", "category": "NPC Items", "platform": "Console"}, "-537237168": {"name": "Mystery Shoulders", "category": "NPC Items", "platform": "Console"}, "-767866790": {"name": "Mystery Weapon, One-Handed", "category": "NPC Items", "platform": "Console"}, "-1099096773": {"name": "Mystery Weapon, Two-Handed", "category": "NPC Items", "platform": "Console"}, "-1352920439": {"name": "Nephalem Cube", "category": "NPC Items", "platform": "Console"}, "1774254059": {"name": "Nephalem Shard", "category": "NPC Items", "platform": "Console"}, "-1224842764": {"name": "Note from Maghda", "category": "NPC Items", "platform": "Console"}, "1524078078": {"name": "Old Tristram Key", "category": "NPC Items", "platform": "Console"}, "1524684909": {"name": "Orn VaseB caOut Props", "category": "NPC Items", "platform": "Console"}, "1472347958": {"name": "Orn a2dun Zolt Centerpiece A", "category": "NPC Items", "platform": "Console"}, "1354327297": {"name": "Orn caOut Cauldron", "category": "NPC Items", "platform": "Console"}, "-330317735": {"name": "Orn caOut CrateA", "category": "NPC Items", "platform": "Console"}, "1360506355": {"name": "Orn caOut VendorStandB", "category": "NPC Items", "platform": "Console"}, "1823013658": {"name": "Orn trDun Cath Candlestand", "category": "NPC Items", "platform": "Console"}, "-479501418": {"name": "Orn trDun Cath LibraryTable", "category": "NPC Items", "platform": "Console"}, "582933236": {"name": "Orn trDun Gargoyle 01", "category": "NPC Items", "platform": "Console"}, "684496620": {"name": "Orn trDun Incense Burner", "category": "NPC Items", "platform": "Console"}, "1432424645": {"name": "Orn trDun Weaponrack", "category": "NPC Items", "platform": "Console"}, "-1232771108": {"name": "Primordial Key", "category": "NPC Items", "platform": "Console"}, "-1661570587": {"name": "Queen Asylla's Journal", "category": "NPC Items", "platform": "Console"}, "1490502399": {"name": "Release Lever", "category": "NPC Items", "platform": "Console"}, "-1106160196": {"name": "Relic of Purification", "category": "NPC Items", "platform": "Console"}, "1259412129": {"name": "ReligiousArtifact", "category": "NPC Items", "platform": "Console"}, "-255366628": {"name": "Resonating Crystal", "category": "NPC Items", "platform": "Console"}, "468192851": {"name": "Scroll of Companion", "category": "NPC Items", "platform": "Console"}, "-96106000": {"name": "Scroll of Mysteries", "category": "NPC Items", "platform": "Console"}, "1310326700": {"name": "Shamanic Khazra Staff", "category": "NPC Items", "platform": "Console"}, "140227858": {"name": "Shard", "category": "NPC Items", "platform": "Console"}, "-1223968557": {"name": "Shard of Resurrection", "category": "NPC Items", "platform": "Console"}, "-1703187309": {"name": "Shen's Loot", "category": "NPC Items", "platform": "Console"}, "753721399": {"name": "Skeleton King's Crown", "category": "NPC Items", "platform": "Console"}, "-1874288726": {"name": "Spider Queen Venom", "category": "NPC Items", "platform": "Console"}, "437383090": {"name": "Sword Blade", "category": "NPC Items", "platform": "Console"}, "-1027737429": {"name": "Sword Hilt", "category": "NPC Items", "platform": "Console"}, "457400460": {"name": "Sword Piece", "category": "NPC Items", "platform": "Console"}, "1360078715": {"name": "SwordOfJustice", "category": "NPC Items", "platform": "Console"}, "1163171450": {"name": "The Cultist's Head", "category": "NPC Items", "platform": "Console"}, "-718773999": {"name": "Three Broken Gems", "category": "NPC Items", "platform": "Console"}, "-797314365": {"name": "Town Portal Stone", "category": "NPC Items", "platform": "Console"}, "-608122705": {"name": "Treasure Hunter's Note", "category": "NPC Items", "platform": "Console"}, "1111843456": {"name": "Triune Smith's Tools", "category": "NPC Items", "platform": "Console"}, "-1062930416": {"name": "Vasily's Angelic Idol", "category": "NPC Items", "platform": "Console"}, "-290192033": {"name": "WestM_Food", "category": "NPC Items", "platform": "Console"}, "437221476": {"name": "ZakarumTotem", "category": "NPC Items", "platform": "Console"}, "-1464111916": {"name": "Zoltun Kulle Blood Vial", "category": "NPC Items", "platform": "Console"}, "609972295": {"name": "Zoltun Kulle's Blue Eye", "category": "NPC Items", "platform": "Console"}, "-1341834850": {"name": "Zoltun Kulle's Body", "category": "NPC Items", "platform": "Console"}, "395877111": {"name": "Zoltun Kulle's Completed Head", "category": "NPC Items", "platform": "Console"}, "-1345664746": {"name": "Zoltun Kulle's Head", "category": "NPC Items", "platform": "Console"}, "-674931800": {"name": "Zoltun Kulle's One Eyed Head", "category": "NPC Items", "platform": "Console"}, "-1345750695": {"name": "Zoltun Kulle's Red Eye", "category": "NPC Items", "platform": "Console"}, "892508204": {"name": "Zoltun Kulle's Rotting Head", "category": "NPC Items", "platform": "Console"}, "414825604": {"name": "Zoltun Kulle's Tome of the Nephalem", "category": "NPC Items", "platform": "Console"}, "-649774063": {"name": "px_DevilsHand_TestGlobe (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "87458782": {"name": "px_DevilsHand_TestGlobe_Dropped (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}}, "Paints": {"-590920596": {"name": "Art_Test_Pants_11 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920595": {"name": "Art_Test_Pants_12 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920594": {"name": "Art_Test_Pants_13 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920593": {"name": "Art_Test_Pants_14 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598560": {"name": "Art_Test_Pants_6 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598561": {"name": "Art_Test_Pants_7 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598562": {"name": "Art_Test_Pants_8 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598563": {"name": "Art_Test_Pants_9 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}}, "Pants": {"-1512732137": {"name": "02: Leather Pants (AR 18-21)", "category": "Pants", "platform": "Console"}, "-1512732136": {"name": "03: Hide Breeches (AR 33-38)", "category": "Pants", "platform": "Console"}, "-1512732135": {"name": "04: Chain Leggings (AR 48-62)", "category": "Pants", "platform": "Console"}, "-1512732134": {"name": "05: Faulds (AR 63-77)", "category": "Pants", "platform": "Console"}, "-1512732133": {"name": "06: Plate Leggings (AR 78-101)", "category": "Pants", "platform": "Console"}, "-1512731049": {"name": "07: Legwraps (AR 102-131)", "category": "Pants", "platform": "Console"}, "-1512731048": {"name": "08: Etched Pants (AR 132-161)", "category": "Pants", "platform": "Console"}, "-1512731047": {"name": "09: Chausses (AR 162-191)", "category": "Pants", "platform": "Console"}, "-1512731046": {"name": "10: Tassets (AR 192-224)", "category": "Pants", "platform": "Console"}, "-1512731045": {"name": "11: Boneweave Faulds (AR 225-247)", "category": "Pants", "platform": "Console"}, "-1512729960": {"name": "12: Leg Guards (AR 27-269)", "category": "Pants", "platform": "Console"}, "-1512729959": {"name": "13: Poleyns (AR 270-284)", "category": "Pants", "platform": "Console"}, "-1512729958": {"name": "14: Warlord Leg Plates (AR 285-322)", "category": "Pants", "platform": "Console"}, "-1512729957": {"name": "15: Schynbalds (AR 322-359)", "category": "Pants", "platform": "Console"}, "-1512729956": {"name": "16: Sovereign Tassets (AR 360-397)", "category": "Pants", "platform": "Console"}, "-1512729955": {"name": "17: Archon Faulds (AR 397-471)", "category": "Pants", "platform": "Console"}, "-1512729954": {"name": "18: Rakkisgard Leg Plates (AR 472-659)", "category": "Pants", "platform": "Console"}, "-1512729953": {"name": "19: Ascended Faulds (AR 660-759)", "category": "Pants", "platform": "Console"}, "1283598555": {"name": "Art Test Pants 1", "category": "Pants", "platform": "Console"}, "1283598556": {"name": "Art Test Pants 2", "category": "Pants", "platform": "Console"}, "1283598557": {"name": "Art Test Pants 3", "category": "Pants", "platform": "Console"}, "1283598558": {"name": "Art Test Pants 4", "category": "Pants", "platform": "Console"}, "1283598559": {"name": "Art Test Pants 5", "category": "Pants", "platform": "Console"}, "-586378095": {"name": "Legendary: Conqueror's Legguards (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "-735317930": {"name": "Legendary: Death's Bargain", "category": "Pants", "platform": "Console"}, "-774309575": {"name": "Legendary: Depth Diggers", "category": "Pants", "platform": "Console"}, "217510501": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "217512945": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "903144209": {"name": "Legendary: Depth Diggers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774309839": {"name": "Legendary: Depth Diggers (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "216324580": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "216327024": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "903144208": {"name": "Legendary: Gehennas (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774453323": {"name": "Legendary: Hammer Jammers", "category": "Pants", "platform": "Console"}, "212766817": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "212769261": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "903144205": {"name": "Legendary: Hammer Jammers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-735353867": {"name": "Legendary: Hexing Pants of Mr. Yan", "category": "Pants", "platform": "Console"}, "-305758345": {"name": "Legendary: Legs of the Sealed Valley", "category": "Pants", "platform": "Console"}, "-774273638": {"name": "Legendary: Pox Faulds", "category": "Pants", "platform": "Console"}, "218696422": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "218698866": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "903144210": {"name": "Legendary: Pox Faulds (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774345512": {"name": "Legendary: Skelon's Deceit", "category": "Pants", "platform": "Console"}, "-774489260": {"name": "Legendary: Swamp Land Waders", "category": "Pants", "platform": "Console"}, "211580896": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "211583340": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "903144204": {"name": "Legendary: Swamp Land Waders (Old-Legacy)", "category": "Pants", "platform": "Console"}, "903144212": {"name": "Set: Asheara's Cradle (Old-Legacy)", "category": "Pants", "platform": "Console"}, "221068264": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "221070708": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "-774201764": {"name": "Set: Asheara's Pace", "category": "Pants", "platform": "Console"}, "903144239": {"name": "Set: Blackthorne's Breeches (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773231465": {"name": "Set: Blackthorne's Jousting Mail", "category": "Pants", "platform": "Console"}, "253088131": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "253090575": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "-773339276": {"name": "Set: Cain's Habit", "category": "Pants", "platform": "Console"}, "903144236": {"name": "Set: Cain's Raiment (Old-Legacy)", "category": "Pants", "platform": "Console"}, "249530368": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "249532812": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "251902210": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "251904654": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "903144238": {"name": "Set: Captain Crimson's Codpiece (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773267402": {"name": "Set: Captain Crimson's Thrust", "category": "Pants", "platform": "Console"}, "825937515": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827015887": {"name": "Set: Cuisses of Akkhan", "category": "Pants", "platform": "Console"}, "903144240": {"name": "Set: Demon's Flesh (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773195528": {"name": "Set: Demon's Plate", "category": "Pants", "platform": "Console"}, "254274052": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "254276496": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "826045588": {"name": "Set: Firebird's Down", "category": "Pants", "platform": "Console"}, "827231509": {"name": "Set: Helltooth Leg Guards", "category": "Pants", "platform": "Console"}, "-184773474": {"name": "Set: Immortal King's Stature (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "903144211": {"name": "Set: Inna's Glory (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774237701": {"name": "Set: Inna's Temperance", "category": "Pants", "platform": "Console"}, "219882343": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "219884787": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "826153399": {"name": "Set: Jade Harvester's Courage", "category": "Pants", "platform": "Console"}, "825901577": {"name": "Set: Leg Guards of Mystery (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826081525": {"name": "Set: Marauder's Encasement", "category": "Pants", "platform": "Console"}, "825865641": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773475": {"name": "Set: Natalya's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826009651": {"name": "Set: Raekor's Breeches", "category": "Pants", "platform": "Console"}, "825865639": {"name": "Set: Roland's Determination (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "826117462": {"name": "Set: Scales of the Dancing Serpent", "category": "Pants", "platform": "Console"}, "827051824": {"name": "Set: Sunwuko's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773473": {"name": "Set: Tal Rasha's Stride (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "825865640": {"name": "Set: Tasset of the Wastes (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827159635": {"name": "Set: The Shadow's Coil", "category": "Pants", "platform": "Console"}, "825937514": {"name": "Set: Unholy Plates (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827123698": {"name": "Set: Vyr's Fantastic Finery", "category": "Pants", "platform": "Console"}, "827195572": {"name": "Set: Weight of the Earth", "category": "Pants", "platform": "Console"}, "825901578": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773472": {"name": "Set: Zunimassa's Cloth (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-774273901": {"name": "legendary: Pox Faulds (Patch 2.2.0)", "category": "Pants", "platform": "Console"}}, "Polearms": {"-1337763519": {"name": "02: Pike (DPS 15.2-16.6)", "category": "Polearms", "platform": "Console"}, "-1337763518": {"name": "03: Guisarme (DPS 20.4-21.9)", "category": "Polearms", "platform": "Console"}, "-1337763517": {"name": "04: Hache (DPS 24.7-26.1)", "category": "Polearms", "platform": "Console"}, "-1337763516": {"name": "05: Glaive (DPS 31.8-33.3)", "category": "Polearms", "platform": "Console"}, "-1337763515": {"name": "06: Pole Axe (DPS 38.0-40.9)", "category": "Polearms", "platform": "Console"}, "-1337763514": {"name": "07: Halberd (DPS 41.3-44.2)", "category": "Polearms", "platform": "Console"}, "-1337763513": {"name": "08: Lance (DPS 50.8-53.7)", "category": "Polearms", "platform": "Console"}, "-1337762431": {"name": "09: Voulge (DPS 58.0-60.8)", "category": "Polearms", "platform": "Console"}, "-1337762430": {"name": "10: Naginata (DPS 70.3-74.6)", "category": "Polearms", "platform": "Console"}, "-1337762429": {"name": "11: Croc (DPS 79.8-84.1)", "category": "Polearms", "platform": "Console"}, "-1337762428": {"name": "12: Battle Hache (DPS 91.7-96.0)", "category": "Polearms", "platform": "Console"}, "-1337762427": {"name": "13: Bisento (DPS 101.7-107.4)", "category": "Polearms", "platform": "Console"}, "-1337762426": {"name": "14: Great Pole Axe (DPS 116.4-122.1)", "category": "Polearms", "platform": "Console"}, "-1337762425": {"name": "15: Battle Halberd (DPS 131.1-138.2)", "category": "Polearms", "platform": "Console"}, "-1337762424": {"name": "16: Partizan (DPS 156.3-163.4)", "category": "Polearms", "platform": "Console"}, "-1337761342": {"name": "17: Lochaber Axe (DPS 191.9-200.5)", "category": "Polearms", "platform": "Console"}, "-1337761341": {"name": "18: Fauchard (DPS 223.3-233.2)", "category": "Polearms", "platform": "Console"}, "-1337761340": {"name": "19: Skewer (DPS 260.8-272.2)", "category": "Polearms", "platform": "Console"}, "-1337761339": {"name": "20: War Crest (DPS 305.0-316.4)", "category": "Polearms", "platform": "Console"}, "-1337761338": {"name": "21: Kwan Dao (DPS 355.8-367.2)", "category": "Polearms", "platform": "Console"}, "-1337761337": {"name": "22: War Thresher (DPS 421.3-432.7)", "category": "Polearms", "platform": "Console"}, "-1337761336": {"name": "23: Grand Halberd (DPS 499.2-510.6)", "category": "Polearms", "platform": "Console"}, "-1337761335": {"name": "24: Dread Lance (DPS 590.0-601.4)", "category": "Polearms", "platform": "Console"}, "-1337760253": {"name": "25: Trident (DPS 739.7-752.3)", "category": "Polearms", "platform": "Console"}, "-1337760252": {"name": "26: Trishula (DPS 1009.1-1021.7)", "category": "Polearms", "platform": "Console"}, "-1558359355": {"name": "Art Test Polearm 1", "category": "Polearms", "platform": "Console"}, "-1558359354": {"name": "Art Test Polearm 2", "category": "Polearms", "platform": "Console"}, "-1558359353": {"name": "Art Test Polearm 3", "category": "Polearms", "platform": "Console"}, "-1558359352": {"name": "Art Test Polearm 4", "category": "Polearms", "platform": "Console"}, "-1558359351": {"name": "Art Test Polearm 5", "category": "Polearms", "platform": "Console"}, "-1948909473": {"name": "Legendary: Bovine Bardiche", "category": "Polearms", "platform": "Console"}, "-1948873536": {"name": "Legendary: Foushee Voulge", "category": "Polearms", "platform": "Console"}, "-1987972992": {"name": "Legendary: Heart Slaughter", "category": "Polearms", "platform": "Console"}, "-1178676596": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "-1178674152": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587768": {"name": "Legendary: Heart Slaughter (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987973256": {"name": "Legendary: Heart Slaughter (Patch 2.1.0)", "category": "Polearms", "platform": "Console"}, "-1988008929": {"name": "Legendary: Pledge of Caldeum", "category": "Polearms", "platform": "Console"}, "-1179862517": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "-1179860073": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587767": {"name": "Legendary: Pledge of Caldeum (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987937055": {"name": "Legendary: Standoff", "category": "Polearms", "platform": "Console"}, "-1177490675": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "-1177488231": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587769": {"name": "Legendary: Standoff (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1988044866": {"name": "Legendary: Vigilance", "category": "Polearms", "platform": "Console"}, "-1181048438": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "-1181045994": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587766": {"name": "Legendary: Vigilance (Old-Legacy)", "category": "Polearms", "platform": "Console"}}, "Quivers": {"1539236301": {"name": "02: Canvas Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236302": {"name": "03: Leather Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236303": {"name": "04: Hunting Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236304": {"name": "05: Assassin Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539237389": {"name": "06: Heavy Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237390": {"name": "07: Barbed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237391": {"name": "08: Hallowed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237392": {"name": "09: Stalker Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237393": {"name": "10: Razorspine Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238478": {"name": "11: Deadeye Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238479": {"name": "12: Bonetooth Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238480": {"name": "13: Consecrated Quiver (ASI 13.0%)", "category": "Quivers", "platform": "Console"}, "1539238481": {"name": "14: Runic Quiver (ASI 14.0%)", "category": "Quivers", "platform": "Console"}, "1539238482": {"name": "15: Sanctified Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238483": {"name": "16: Rakkisgard Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238484": {"name": "17: Ascended Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "-1056381007": {"name": "Art Test Quiver 1", "category": "Quivers", "platform": "Console"}, "-1056381006": {"name": "Art Test Quiver 2", "category": "Quivers", "platform": "Console"}, "-1056381005": {"name": "Art Test Quiver 3", "category": "Quivers", "platform": "Console"}, "-1056381004": {"name": "Art Test Quiver 4", "category": "Quivers", "platform": "Console"}, "-1056381003": {"name": "Art Test Quiver 5", "category": "Quivers", "platform": "Console"}, "-400507188": {"name": "Legendary: Archfiend Arrows", "category": "Quivers", "platform": "Console"}, "-331912616": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-331910172": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223036": {"name": "Legendary: Black Bone Arrows (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361407732": {"name": "Legendary: Bombadier's Rucksack", "category": "Quivers", "platform": "Console"}, "-400363440": {"name": "Legendary: Dead Man's Legacy", "category": "Quivers", "platform": "Console"}, "-327168932": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-327166488": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223032": {"name": "Legendary: Dead Man's Legacy (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361371795": {"name": "Legendary: Emimei's Duffel", "category": "Quivers", "platform": "Console"}, "-400399377": {"name": "Legendary: Fletcher's Pride", "category": "Quivers", "platform": "Console"}, "-328354853": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-328352409": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223033": {"name": "Legendary: Fletcher's Pride (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400579062": {"name": "Legendary: Flint Ripper Arrowheads", "category": "Quivers", "platform": "Console"}, "-334284458": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-334282014": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223038": {"name": "Legendary: Flint Ripper Arrowheads (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400471251": {"name": "Legendary: Holy Point Shot", "category": "Quivers", "platform": "Console"}, "-330726695": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-330724251": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223035": {"name": "Legendary: Holy Point Shot (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361335858": {"name": "Legendary: Hunter's Longbox", "category": "Quivers", "platform": "Console"}, "-400579326": {"name": "Legendary: Meticulous Bolts (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-400435314": {"name": "Legendary: Silver Star Piercers", "category": "Quivers", "platform": "Console"}, "-329540774": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-329538330": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223034": {"name": "Legendary: Silver Star Piercers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400543125": {"name": "Legendary: Sin Seekers", "category": "Quivers", "platform": "Console"}, "-333098537": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-333096093": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223037": {"name": "Legendary: Sin Seekers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400435578": {"name": "Legendary: Spines of Seething Hatred (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-361443669": {"name": "Legendary: The Ninth Cirri Satchel", "category": "Quivers", "platform": "Console"}, "564938473": {"name": "legendary: Dead Man's Legacy (Patch 2.2.0)", "category": "Quivers", "platform": "Console"}}, "Rings": {"1146967281": {"name": "02: Ring", "category": "Rings", "platform": "Console"}, "1146967282": {"name": "03: Ring", "category": "Rings", "platform": "Console"}, "1146967283": {"name": "04: Ring", "category": "Rings", "platform": "Console"}, "1146967284": {"name": "05: Ring", "category": "Rings", "platform": "Console"}, "1146967285": {"name": "06: Ring", "category": "Rings", "platform": "Console"}, "1146967286": {"name": "07: Ring", "category": "Rings", "platform": "Console"}, "1146967287": {"name": "08: Ring", "category": "Rings", "platform": "Console"}, "1146967288": {"name": "09: Ring", "category": "Rings", "platform": "Console"}, "1146967312": {"name": "10: Ring", "category": "Rings", "platform": "Console"}, "1146967313": {"name": "11: Ring", "category": "Rings", "platform": "Console"}, "1146967314": {"name": "12: Ring", "category": "Rings", "platform": "Console"}, "1146967315": {"name": "13: Ring", "category": "Rings", "platform": "Console"}, "1146967316": {"name": "14: Ring", "category": "Rings", "platform": "Console"}, "1146967317": {"name": "15: Ring", "category": "Rings", "platform": "Console"}, "1146967318": {"name": "16: Ring", "category": "Rings", "platform": "Console"}, "1146967319": {"name": "17: Ring", "category": "Rings", "platform": "Console"}, "1146967320": {"name": "18: Ring", "category": "Rings", "platform": "Console"}, "1146967321": {"name": "19: Ring", "category": "Rings", "platform": "Console"}, "1146967345": {"name": "20: Ring", "category": "Rings", "platform": "Console"}, "1146967346": {"name": "21: Ring", "category": "Rings", "platform": "Console"}, "1146967347": {"name": "22: Ring", "category": "Rings", "platform": "Console"}, "1146967348": {"name": "23: Ring", "category": "Rings", "platform": "Console"}, "1146967349": {"name": "24: Ring", "category": "Rings", "platform": "Console"}, "1146967350": {"name": "25: Ring", "category": "Rings", "platform": "Console"}, "1818597029": {"name": "Art Test Ring 1", "category": "Rings", "platform": "Console"}, "1818597030": {"name": "Art Test Ring 2", "category": "Rings", "platform": "Console"}, "1818597031": {"name": "Art Test Ring 3", "category": "Rings", "platform": "Console"}, "1818597032": {"name": "Art Test Ring 4", "category": "Rings", "platform": "Console"}, "1818597033": {"name": "Art Test Ring 5", "category": "Rings", "platform": "Console"}, "-1149557626": {"name": "Legendary: Avarice Band", "category": "Rings", "platform": "Console"}, "-1188944578": {"name": "Legendary: Band of Hollow Whispers", "category": "Rings", "platform": "Console"}, "-580542710": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-580540266": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-731577034": {"name": "Legendary: Band of Hollow Whispers (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188657082": {"name": "Legendary: Band of Untold Secrets", "category": "Rings", "platform": "Console"}, "-571055342": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-571052898": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-731577026": {"name": "Legendary: Band of Untold Secrets (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149629500": {"name": "Legendary: Band of the Rue Chambers", "category": "Rings", "platform": "Console"}, "-1188764893": {"name": "Legendary: Broken Promises", "category": "Rings", "platform": "Console"}, "-574613105": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-574610661": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-731577029": {"name": "Legendary: Broken Promises (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186608673": {"name": "Legendary: Bul-Kathos's Wedding Band", "category": "Rings", "platform": "Console"}, "-503457845": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-503455401": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-731576969": {"name": "Legendary: Bul-Kathos's Wedding Band (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188728956": {"name": "Legendary: Eternal Union", "category": "Rings", "platform": "Console"}, "-573427184": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-573424740": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-731577028": {"name": "Legendary: Eternal Union (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188729220": {"name": "Legendary: Eternal Union (Patch 2.1.0)", "category": "Rings", "platform": "Console"}, "-1149665437": {"name": "Legendary: Gamuel's Deceit", "category": "Rings", "platform": "Console"}, "425752007": {"name": "Legendary: Halo Of Arlyse (Patch 2.1.2)", "category": "Rings", "platform": "Console"}, "-1186464925": {"name": "Legendary: Hellfire Ring", "category": "Rings", "platform": "Console"}, "-498714161": {"name": "Legendary: Hellfire Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-578170868": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-578168424": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-731577032": {"name": "Legendary: Hierophant's Seal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188693019": {"name": "Legendary: Justice Lantern", "category": "Rings", "platform": "Console"}, "-572241263": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-572238819": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-731577027": {"name": "Legendary: Justice Lantern (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188872704": {"name": "Legendary: Krede's Flame", "category": "Rings", "platform": "Console"}, "1963121073": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-159638916": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-1188908641": {"name": "Legendary: Leoric's Signet", "category": "Rings", "platform": "Console"}, "-579356789": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-579354345": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-731577033": {"name": "Legendary: Leoric's Signet (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186572736": {"name": "Legendary: Manald Heal", "category": "Rings", "platform": "Console"}, "-502271924": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-502269480": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-731576968": {"name": "Legendary: Manald Heal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187507098": {"name": "Legendary: Nagelring", "category": "Rings", "platform": "Console"}, "-533105870": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-533103426": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576994": {"name": "Legendary: Nagelring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186500862": {"name": "Legendary: Obsidian Ring of the Zodiac", "category": "Rings", "platform": "Console"}, "-499900082": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-499897638": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-731576966": {"name": "Legendary: Obsidian Ring of the Zodiac (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187543035": {"name": "Legendary: Oculus Ring", "category": "Rings", "platform": "Console"}, "-534291791": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-534289347": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576995": {"name": "Legendary: Oculus Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149521689": {"name": "Legendary: Pandemonium Loop", "category": "Rings", "platform": "Console"}, "-1188836767": {"name": "Legendary: Puzzle Ring", "category": "Rings", "platform": "Console"}, "-576984947": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-576982503": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577031": {"name": "Legendary: Puzzle Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149701374": {"name": "Legendary: Rechel's Ring of Larceny", "category": "Rings", "platform": "Console"}, "-1149593563": {"name": "Legendary: Ring of Royal Grandeur", "category": "Rings", "platform": "Console"}, "-1149737311": {"name": "Legendary: Rogar's Huge Stone", "category": "Rings", "platform": "Console"}, "-611901958": {"name": "Legendary: Signet Ring of the Blizzard", "category": "Rings", "platform": "Console"}, "-1186536799": {"name": "Legendary: Skull Grasp", "category": "Rings", "platform": "Console"}, "-501086003": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-501083559": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-731576967": {"name": "Legendary: Skull Grasp (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188800830": {"name": "Legendary: Stolen Ring", "category": "Rings", "platform": "Console"}, "-575799026": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-575796582": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577030": {"name": "Legendary: Stolen Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187471161": {"name": "Legendary: Stone of Jordan", "category": "Rings", "platform": "Console"}, "-531919949": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-531917505": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-731576993": {"name": "Legendary: Stone of Jordan (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149809185": {"name": "Legendary: The Tall Man's Finger", "category": "Rings", "platform": "Console"}, "-1187794594": {"name": "Legendary: Unity", "category": "Rings", "platform": "Console"}, "-542593238": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-542590794": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-731577002": {"name": "Legendary: Unity (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149773248": {"name": "Legendary: Wyrdward", "category": "Rings", "platform": "Console"}, "-1585363882": {"name": "P1_Ring_001 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363881": {"name": "P1_Ring_002 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363880": {"name": "P1_Ring_003 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363879": {"name": "P1_Ring_004 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "2082266421": {"name": "PvP: Echo Band All", "category": "Rings", "platform": "Console"}, "2082266693": {"name": "PvP: Echo Band Attack", "category": "Rings", "platform": "Console"}, "2082269451": {"name": "PvP: Echo Band Defense", "category": "Rings", "platform": "Console"}, "-4139386": {"name": "PvP: Echo Band Precision", "category": "Rings", "platform": "Console"}, "2082289199": {"name": "PvP: Echo Band Vitality", "category": "Rings", "platform": "Console"}, "-3897388": {"name": "PvP: Echo Band Willpower", "category": "Rings", "platform": "Console"}, "-2095294696": {"name": "PvP: Sherman Signet All", "category": "Rings", "platform": "Console"}, "-2095294424": {"name": "PvP: Sherman Signet Attack", "category": "Rings", "platform": "Console"}, "-2095291666": {"name": "PvP: Sherman Signet Defense", "category": "Rings", "platform": "Console"}, "-424702775": {"name": "PvP: Sherman Signet Precision", "category": "Rings", "platform": "Console"}, "-2095271918": {"name": "PvP: Sherman Signet Vitality", "category": "Rings", "platform": "Console"}, "-731576997": {"name": "Set: Band of Fallen Heroes (Old-Legacy)", "category": "Rings", "platform": "Console"}, "1978116233": {"name": "Set: Focus", "category": "Rings", "platform": "Console"}, "-1187614909": {"name": "Set: Litany of the Undaunted", "category": "Rings", "platform": "Console"}, "-536663633": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-536661189": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-731577001": {"name": "Set: Natalya's Mark (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187758657": {"name": "Set: Natalya's Reflection", "category": "Rings", "platform": "Console"}, "-541407317": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "-541404873": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "1978152170": {"name": "Set: Restraint", "category": "Rings", "platform": "Console"}, "-731576998": {"name": "Set: Screaming Chain (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187686783": {"name": "Set: The Compass Rose", "category": "Rings", "platform": "Console"}, "-539035475": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-539033031": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-1187650846": {"name": "Set: The Wailing Host", "category": "Rings", "platform": "Console"}, "-537849554": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-537847110": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-731576999": {"name": "Set: Wanderlust (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-731577000": {"name": "Set: Zunimassa's Plague (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187722720": {"name": "Set: Zunimassa's Pox", "category": "Rings", "platform": "Console"}, "-540221396": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "-540218952": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "417069417": {"name": "legendary: Arcstone (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1188765156": {"name": "legendary: Broken Promises (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069418": {"name": "legendary: Convention Of Elements (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187507361": {"name": "legendary: Nagelring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187543298": {"name": "legendary: Oculus Ring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149521952": {"name": "legendary: Pandemonium Loop (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1186501125": {"name": "legendary: Ring of the Zodiac (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069415": {"name": "legendary: Skull Grasp (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069416": {"name": "legendary: The Short Man's Finger (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149773511": {"name": "legendary: Wyrdward (Patch 2.2.0)", "category": "Rings", "platform": "Console"}}, "Scoundrel Tokens": {"-229902048": {"name": "02: Glass Blade", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900960": {"name": "03: Loaded Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900959": {"name": "04: Crystal Edge", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900958": {"name": "05: Clasp", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900957": {"name": "06: Sand Pouch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899871": {"name": "07: Bone Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899870": {"name": "08: Diamond Razor", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899869": {"name": "09: Brooch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899868": {"name": "10: Dust Satchel", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899867": {"name": "11: Hazard", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899866": {"name": "12: Stinger", "category": "Scoundrel Tokens", "platform": "Console"}, "978821514": {"name": "Legendary: Ribald Etchings", "category": "Scoundrel Tokens", "platform": "Console"}, "978821513": {"name": "Legendary: Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "978821515": {"name": "Legendary: Slipka's Letter Opener", "category": "Scoundrel Tokens", "platform": "Console"}, "-978821513": {"name": "Legendary:Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}}, "Shields": {"1815806857": {"name": "01: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806858": {"name": "02: Targe Shield (AR 48-55)", "category": "Shields", "platform": "Console"}, "1815806859": {"name": "03: Heater Shield (AR 88-101)", "category": "Shields", "platform": "Console"}, "1815806860": {"name": "04: Kite Shield (AR 128-167)", "category": "Shields", "platform": "Console"}, "1815806861": {"name": "05: Large Shield (AR 168-199)", "category": "Shields", "platform": "Console"}, "1815806862": {"name": "06: Gothic Shield (AR 200-223)", "category": "Shields", "platform": "Console"}, "1815806863": {"name": "07: Tower Shield (AR 224-255)", "category": "Shields", "platform": "Console"}, "1815807946": {"name": "08: Pelta (AR 256-319)", "category": "Shields", "platform": "Console"}, "1815807947": {"name": "09: Rondache (AR 320-383)", "category": "Shields", "platform": "Console"}, "1815807948": {"name": "10: Knight Shield (AR 384-447)", "category": "Shields", "platform": "Console"}, "1815807949": {"name": "11: Ironwood Shield (AR 448-511)", "category": "Shields", "platform": "Console"}, "1815807950": {"name": "12: Pavise (AR 512-579)", "category": "Shields", "platform": "Console"}, "1815807951": {"name": "13: Bone Shield (AR 580-619)", "category": "Shields", "platform": "Console"}, "1815807952": {"name": "14: Savior (AR 620-659)", "category": "Shields", "platform": "Console"}, "1815809035": {"name": "15: Aspis (AR 660-699)", "category": "Shields", "platform": "Console"}, "1815809036": {"name": "16: Hoplon (AR 700-739)", "category": "Shields", "platform": "Console"}, "1815809037": {"name": "17: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "-335464095": {"name": "17b: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "1815809038": {"name": "18: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "-334278174": {"name": "18b: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "1815809039": {"name": "19: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "-333092253": {"name": "19b: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "1815809040": {"name": "20: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "-331906332": {"name": "20b: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "1815809041": {"name": "21: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "-330720411": {"name": "21b: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "1815809042": {"name": "22: Rakkisgard Shield (AR 1260-1759)", "category": "Shields", "platform": "Console"}, "1815809043": {"name": "23: Ascended Shield (AR 1760-2024)", "category": "Shields", "platform": "Console"}, "-1347979730": {"name": "Art Test Shield 1", "category": "Shields", "platform": "Console"}, "-1347979729": {"name": "Art Test Shield 2", "category": "Shields", "platform": "Console"}, "-1347979728": {"name": "Art Test Shield 3", "category": "Shields", "platform": "Console"}, "-1347979727": {"name": "Art Test Shield 4", "category": "Shields", "platform": "Console"}, "-1347979726": {"name": "Art Test Shield 5", "category": "Shields", "platform": "Console"}, "200412170": {"name": "Legendary: Amazonian Parma", "category": "Shields", "platform": "Console"}, "200519981": {"name": "Legendary: Beastguard", "category": "Shields", "platform": "Console"}, "1028274966": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "1028277410": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "-64652478": {"name": "Legendary: Centurion (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200555918": {"name": "Legendary: Coven's Criterion", "category": "Shields", "platform": "Console"}, "200340296": {"name": "Legendary: Defender of Westmarch", "category": "Shields", "platform": "Console"}, "161420525": {"name": "Legendary: Denial", "category": "Shields", "platform": "Console"}, "1031832729": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "1031835173": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "-64652475": {"name": "Legendary: Denial (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200376233": {"name": "Legendary: Eberli Charo", "category": "Shields", "platform": "Console"}, "161312714": {"name": "Legendary: Freeze of Deflection", "category": "Shields", "platform": "Console"}, "161240840": {"name": "Legendary: Ivory Tower", "category": "Shields", "platform": "Console"}, "1025903124": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "1025905568": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "-64652480": {"name": "Legendary: Ivory Tower (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161456462": {"name": "Legendary: Lidless Wall", "category": "Shields", "platform": "Console"}, "1033018650": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "1033021094": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "-64652474": {"name": "Legendary: Lidless Wall (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161492399": {"name": "Legendary: Stormshield", "category": "Shields", "platform": "Console"}, "1034204571": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "1034207015": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "-64652473": {"name": "Legendary: Stormshield (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200448107": {"name": "Legendary: Vo'Toyias Spiker", "category": "Shields", "platform": "Console"}, "1063852596": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "1063855040": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "-64652448": {"name": "Legendary: Wall of Bone (Old-Legacy)", "category": "Shields", "platform": "Console"}, "162390824": {"name": "Legendary: Wall of Man", "category": "Shields", "platform": "Console"}, "200484044": {"name": "Legendary: Wretchskin", "category": "Shields", "platform": "Console"}, "162426761": {"name": "Set: Hallowed Barricade", "category": "Shields", "platform": "Console"}, "-64652447": {"name": "Set: Hallowed Barrier (Old-Legacy)", "category": "Shields", "platform": "Console"}, "1065038517": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "1065040961": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "200340033": {"name": "legendary: Defender Of Westmarch (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509030": {"name": "legendary: Denial (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509025": {"name": "legendary: Ivory Tower (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "-519190663": {"name": "legendary: Stormshield (Patch 2.2.0)", "category": "Shields", "platform": "Console"}}, "Shoulders": {"365490251": {"name": "03: Shoulder Guards (AR 48-58)", "category": "Shoulders", "platform": "Console"}, "365490252": {"name": "04: Amice (AR 58-68)", "category": "Shoulders", "platform": "Console"}, "365490253": {"name": "05: Spaulders (AR 69-79)", "category": "Shoulders", "platform": "Console"}, "365490254": {"name": "06: Shoulder Plates (AR 80-100)", "category": "Shoulders", "platform": "Console"}, "365491338": {"name": "07: Etched Mantle (AR 101-121)", "category": "Shoulders", "platform": "Console"}, "365491339": {"name": "08: Ailettes (AR 122-142)", "category": "Shoulders", "platform": "Console"}, "365491340": {"name": "09: Pauldrons (AR 144-164)", "category": "Shoulders", "platform": "Console"}, "365491341": {"name": "10: Sode (AR 165-199)", "category": "Shoulders", "platform": "Console"}, "365491342": {"name": "11: Epaulets (AR 200-219)", "category": "Shoulders", "platform": "Console"}, "365492427": {"name": "12: Balor Pauldrons (AR 220-239)", "category": "Shoulders", "platform": "Console"}, "365492428": {"name": "13: Espaliers (AR 240-252)", "category": "Shoulders", "platform": "Console"}, "365492429": {"name": "14: Warlord Spaulders (AR 253-285)", "category": "Shoulders", "platform": "Console"}, "365492430": {"name": "15: Doom Pauldrons (AR 286-318)", "category": "Shoulders", "platform": "Console"}, "365492431": {"name": "16: Pallium (AR 320-352)", "category": "Shoulders", "platform": "Console"}, "365492432": {"name": "17: Archon Spaulders (AR 353-419)", "category": "Shoulders", "platform": "Console"}, "365492433": {"name": "18: Rakkisgard Pauldrons (AR 420-586)", "category": "Shoulders", "platform": "Console"}, "365492434": {"name": "19: Ascended Pauldrons (AR 586-674)", "category": "Shoulders", "platform": "Console"}, "-1869550021": {"name": "Art Test Shoulder 1", "category": "Shoulders", "platform": "Console"}, "-1869550020": {"name": "Art Test Shoulder 2", "category": "Shoulders", "platform": "Console"}, "-1869550019": {"name": "Art Test Shoulder 3", "category": "Shoulders", "platform": "Console"}, "-1869550018": {"name": "Art Test Shoulder 4", "category": "Shoulders", "platform": "Console"}, "-1869550017": {"name": "Art Test Shoulder 5", "category": "Shoulders", "platform": "Console"}, "-1565608501": {"name": "Art_Test_Shoulder_10 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608500": {"name": "Art_Test_Shoulder_11 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608499": {"name": "Art_Test_Shoulder_12 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550016": {"name": "Art_Test_Shoulder_6 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550015": {"name": "Art_Test_Shoulder_7 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550014": {"name": "Art_Test_Shoulder_8 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550013": {"name": "Art_Test_Shoulder_9 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-248496224": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "-248493780": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734028": {"name": "Legendary: Barter Town Pads (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "2112365407": {"name": "Legendary: Burdens of the Brave Survivor", "category": "Shoulders", "platform": "Console"}, "1902294393": {"name": "Legendary: Conqueror's Pauldrons (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1959570086": {"name": "Legendary: Corruption", "category": "Shoulders", "platform": "Console"}, "-1959749771": {"name": "Legendary: Death Watch Mantle", "category": "Shoulders", "platform": "Console"}, "-247310303": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "-247307859": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734029": {"name": "Legendary: Death Watch Mantle (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959785708": {"name": "Legendary: Homing Pads", "category": "Shoulders", "platform": "Console"}, "507255184": {"name": "Legendary: Infernal Pauldrons", "category": "Shoulders", "platform": "Console"}, "-1920578441": {"name": "Legendary: Pauldrons of the Skeleton King", "category": "Shoulders", "platform": "Console"}, "-1920650315": {"name": "Legendary: Profane Pauldrons", "category": "Shoulders", "platform": "Console"}, "-241380698": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "-241378254": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734034": {"name": "Legendary: Seven Sins (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1920614378": {"name": "Legendary: Spaulders of Zakara", "category": "Shoulders", "platform": "Console"}, "1277749690": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-419021771": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-1959713834": {"name": "Legendary: Vile Ward", "category": "Shoulders", "platform": "Console"}, "-246124382": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "-246121938": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734030": {"name": "Legendary: Vile Ward (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959714098": {"name": "Legendary: Vile Ward (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1958384165": {"name": "Set: Asheara's Custodian", "category": "Shoulders", "platform": "Console"}, "-202245305": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "-202242861": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734067": {"name": "Set: Asheara's Vigilance (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959534149": {"name": "Set: Aughild's Power", "category": "Shoulders", "platform": "Console"}, "-240194777": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "-240192333": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734035": {"name": "Set: Aughild's Triumph (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-242566619": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "-242564175": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734033": {"name": "Set: Born's Pauldrons (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959606023": {"name": "Set: Born's Privilege", "category": "Shoulders", "platform": "Console"}, "-1980689583": {"name": "Set: Burden of the Invoker", "category": "Shoulders", "platform": "Console"}, "-1981839829": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875767": {"name": "Set: Dashing Pauldrons of Despair (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959498212": {"name": "Set: Demon's Aileron", "category": "Shoulders", "platform": "Console"}, "-239008856": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "-239006412": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734036": {"name": "Set: Demon's Wings (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1981731756": {"name": "Set: Firebird's Pinions", "category": "Shoulders", "platform": "Console"}, "-1980545835": {"name": "Set: Helltooth Mantle", "category": "Shoulders", "platform": "Console"}, "-1981623945": {"name": "Set: Jade Harvester's Joy", "category": "Shoulders", "platform": "Console"}, "-1981659882": {"name": "Set: Mantle of the Upside-Down Sinners", "category": "Shoulders", "platform": "Console"}, "-1981695819": {"name": "Set: Marauder's Spines", "category": "Shoulders", "platform": "Console"}, "-1981911703": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1980761457": {"name": "Set: Pauldrons of Akkhan", "category": "Shoulders", "platform": "Console"}, "-1981911704": {"name": "Set: Pauldrons of the Wastes (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981767693": {"name": "Set: Raekor's Burden", "category": "Shoulders", "platform": "Console"}, "-1981911705": {"name": "Set: Roland's Mantle (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1980581772": {"name": "Set: Spires of the Earth", "category": "Shoulders", "platform": "Console"}, "-1980725520": {"name": "Set: Sunwuko's Balance", "category": "Shoulders", "platform": "Console"}, "-1981839830": {"name": "Set: Unsanctified Shoulders (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875766": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959750034": {"name": "legendary: Death Watch Mantle (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1449741837": {"name": "legendary: Pauldrons of the Hierarch (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}}, "Sources": {"1905179476": {"name": "02: Spellbook (+(2-3)-(3-5) DMG)", "category": "Sources", "platform": "Console"}, "1905179477": {"name": "03: Smoked Spheres (+(3-5)-(4-8) DMG)", "category": "Sources", "platform": "Console"}, "1905179478": {"name": "04: Cursed Skull (+(3-6)-(4-10) DMG)", "category": "Sources", "platform": "Console"}, "1905180564": {"name": "05: Sanctuary Globe (+(4-8)-(5-13) DMG)", "category": "Sources", "platform": "Console"}, "1905180565": {"name": "06: Fiendish Folio (+(6-11)-(7-19) DMG)", "category": "Sources", "platform": "Console"}, "1905180566": {"name": "07: Triad (+(8-16)-(9-29) DMG)", "category": "Sources", "platform": "Console"}, "1905180567": {"name": "08: Screaming Skull (+(13-26)-(14-45) DMG)", "category": "Sources", "platform": "Console"}, "1905181653": {"name": "09: Power Sphere (+(17-39)-(18-114) DMG)", "category": "Sources", "platform": "Console"}, "1905181654": {"name": "10: Codex (+(19-58)-(20-213) DMG)", "category": "Sources", "platform": "Console"}, "1905181655": {"name": "11: Orbit Stones (+(24-72)-(25-265) DMG)", "category": "Sources", "platform": "Console"}, "1905181656": {"name": "12: Demi Lich (+(28-110)-(29-405) DMG)", "category": "Sources", "platform": "Console"}, "1905181657": {"name": "13: Puzzle Box (+(126-158)-(127-190) DMG)", "category": "Sources", "platform": "Console"}, "1905181658": {"name": "14: Moschen Spheres (+(262-328)-(263-394) DMG)", "category": "Sources", "platform": "Console"}, "702613912": {"name": "Art Test Orb 1", "category": "Sources", "platform": "Console"}, "702613913": {"name": "Art Test Orb 2", "category": "Sources", "platform": "Console"}, "702613914": {"name": "Art Test Orb 3", "category": "Sources", "platform": "Console"}, "702613915": {"name": "Art Test Orb 4", "category": "Sources", "platform": "Console"}, "702613916": {"name": "Art Test Orb 5", "category": "Sources", "platform": "Console"}, "-1519116524": {"name": "Legendary: Cosmic Strand", "category": "Sources", "platform": "Console"}, "2028438506": {"name": "Legendary: Gul'dan's Secret (Patch 2.1.0)", "category": "Sources", "platform": "Console"}, "-1934140787": {"name": "Legendary: Heart of Darkness", "category": "Sources", "platform": "Console"}, "-1480017068": {"name": "Legendary: Light of Grace", "category": "Sources", "platform": "Console"}, "-1480088942": {"name": "Legendary: Mirrorball", "category": "Sources", "platform": "Console"}, "-1480053005": {"name": "Legendary: Myken's Ball of Hate", "category": "Sources", "platform": "Console"}, "1408684960": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "1408687404": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "215441100": {"name": "Legendary: Singularity (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519224335": {"name": "Legendary: The Oculus", "category": "Sources", "platform": "Console"}, "1405127197": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "1405129641": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "215441097": {"name": "Legendary: The Oculus (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519152461": {"name": "Legendary: Triumvirate", "category": "Sources", "platform": "Console"}, "1407499039": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "1407501483": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "215441099": {"name": "Legendary: Triumvirate (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519080587": {"name": "Legendary: Winter Flurry", "category": "Sources", "platform": "Console"}, "1409870881": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "1409873325": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "215441101": {"name": "Legendary: Winter Flurry (Old-Legacy)", "category": "Sources", "platform": "Console"}, "215441130": {"name": "Set: Chantodo's Elemental Seal (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518038414": {"name": "Set: Chantodo's Force", "category": "Sources", "platform": "Console"}, "1444262590": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "1444265034": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "-777123311": {"name": "Set: Firebird's Eye", "category": "Sources", "platform": "Console"}, "215441131": {"name": "Set: Tal Rasha's Lidless Eye (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518002477": {"name": "Set: Tal Rasha's Unwavering Glare", "category": "Sources", "platform": "Console"}, "1445448511": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1445450955": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1175281612": {"name": "legendary: Triumvirate (Patch 2.2.0)", "category": "Sources", "platform": "Console"}}, "Spears": {"-101312756": {"name": "02: Fuscina (DPS 12.6-14.4)", "category": "Spears", "platform": "Console"}, "-101312755": {"name": "03: Spear (DPS 18.6-20.4)", "category": "Spears", "platform": "Console"}, "-101312754": {"name": "04: Hasta (DPS 24.6-26.4)", "category": "Spears", "platform": "Console"}, "-101312753": {"name": "05: Pilum (DPS 32.4-34.2)", "category": "Spears", "platform": "Console"}, "-101311668": {"name": "06: Angon (DPS 38.4-40.2)", "category": "Spears", "platform": "Console"}, "-101311667": {"name": "07: Assegai (DPS 48.6-50.4)", "category": "Spears", "platform": "Console"}, "-101311666": {"name": "08: War Spear (DPS 60.6-62.4)", "category": "Spears", "platform": "Console"}, "-101311665": {"name": "09: Spontoon (DPS 84.6-88.2)", "category": "Spears", "platform": "Console"}, "-101311664": {"name": "10: Yari (DPS 127.8-133.2)", "category": "Spears", "platform": "Console"}, "-101310579": {"name": "11: Harpoon (DPS 151.8-157.2)", "category": "Spears", "platform": "Console"}, "-101310578": {"name": "12: Impaler (DPS 178.2-185.4)", "category": "Spears", "platform": "Console"}, "-101310577": {"name": "13: Qiang (DPS 230.4-239.4)", "category": "Spears", "platform": "Console"}, "-101310576": {"name": "14: Vel (DPS 268.2-277.2)", "category": "Spears", "platform": "Console"}, "-101310575": {"name": "15: Centurion Spear (DPS 311.4-320.4)", "category": "Spears", "platform": "Console"}, "-101309490": {"name": "16: Honed Spear (DPS 419.4-428.4)", "category": "Spears", "platform": "Console"}, "-101309489": {"name": "17: Disemboweler (DPS 527.4-536.4)", "category": "Spears", "platform": "Console"}, "1438708880": {"name": "Art Test Spear 1", "category": "Spears", "platform": "Console"}, "1438708881": {"name": "Art Test Spear 2", "category": "Spears", "platform": "Console"}, "1438708882": {"name": "Art Test Spear 3", "category": "Spears", "platform": "Console"}, "1438708883": {"name": "Art Test Spear 4", "category": "Spears", "platform": "Console"}, "1438708884": {"name": "Art Test Spear 5", "category": "Spears", "platform": "Console"}, "-2120824630": {"name": "Legendary: Akanesh, the Herald of Righteousness", "category": "Spears", "platform": "Console"}, "2135007273": {"name": "Legendary: Arreat's Law", "category": "Spears", "platform": "Console"}, "1735685973": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "1735688417": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403711": {"name": "Legendary: Arreat's Law (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135079147": {"name": "Legendary: Empyrean Messenger", "category": "Spears", "platform": "Console"}, "1738057815": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "1738060259": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403709": {"name": "Legendary: Empyrean Messenger (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135115084": {"name": "Legendary: Scrimshaw", "category": "Spears", "platform": "Console"}, "1739243736": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "1739246180": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403708": {"name": "Legendary: Scrimshaw (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-2120788693": {"name": "Legendary: Steffon's Heavy Lance", "category": "Spears", "platform": "Console"}, "2135043210": {"name": "Legendary: The Three Hundredth Spear", "category": "Spears", "platform": "Console"}, "1736871894": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "1736874338": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403710": {"name": "Legendary: The Three Hundredth Spear (Old-Legacy)", "category": "Spears", "platform": "Console"}}, "Spirit Stones": {"-242895467": {"name": "02: Thought Mirror (AR 36-41)", "category": "Spirit Stones", "platform": "Console"}, "-242895466": {"name": "03: Third Eye (AR 60-69)", "category": "Spirit Stones", "platform": "Console"}, "-242895465": {"name": "04: Onyx Cluster (AR 84-113)", "category": "Spirit Stones", "platform": "Console"}, "-242894379": {"name": "05: Sunstone (AR 114-149)", "category": "Spirit Stones", "platform": "Console"}, "-242894378": {"name": "06: Prism (AR 150-185)", "category": "Spirit Stones", "platform": "Console"}, "-242894377": {"name": "07: Seer Shard (AR 186-232)", "category": "Spirit Stones", "platform": "Console"}, "-242894376": {"name": "08: Igneous Studs (AR 232-254)", "category": "Spirit Stones", "platform": "Console"}, "-242893290": {"name": "09: Solarius (AR 255-284)", "category": "Spirit Stones", "platform": "Console"}, "-242893289": {"name": "10: Meditator (AR 285-322)", "category": "Spirit Stones", "platform": "Console"}, "-242893288": {"name": "11: Ghost Sight (AR 322-359)", "category": "Spirit Stones", "platform": "Console"}, "-242893287": {"name": "12: Star Crown (AR 360-472)", "category": "Spirit Stones", "platform": "Console"}, "-242893286": {"name": "13: Insight Stone (AR 472-659)", "category": "Spirit Stones", "platform": "Console"}, "-242893285": {"name": "14: Ascended Stone (AR 660-759)", "category": "Spirit Stones", "platform": "Console"}, "113759385": {"name": "Art Test SpiritStone 1", "category": "Spirit Stones", "platform": "Console"}, "113759386": {"name": "Art Test SpiritStone 2", "category": "Spirit Stones", "platform": "Console"}, "113759387": {"name": "Art Test SpiritStone 3", "category": "Spirit Stones", "platform": "Console"}, "113759388": {"name": "Art Test SpiritStone 4", "category": "Spirit Stones", "platform": "Console"}, "113759389": {"name": "Art Test SpiritStone 5", "category": "Spirit Stones", "platform": "Console"}, "635580050": {"name": "Legendary: Bezoar Stone", "category": "Spirit Stones", "platform": "Console"}, "-500772130": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-500769686": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225226": {"name": "Legendary: Bezoar Stone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635651924": {"name": "Legendary: Erlang Shen", "category": "Spirit Stones", "platform": "Console"}, "-498400288": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-498397844": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225228": {"name": "Legendary: Erlang Shen (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674787317": {"name": "Legendary: Eye of Peshkov", "category": "Spirit Stones", "platform": "Console"}, "635687861": {"name": "Legendary: Gyana Na Kashu", "category": "Spirit Stones", "platform": "Console"}, "-497214367": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-497211923": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225229": {"name": "Legendary: Gyana Na Kashu (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674751380": {"name": "Legendary: Kekegi's Unbreakable Spirit", "category": "Spirit Stones", "platform": "Console"}, "635831609": {"name": "Legendary: Madstone", "category": "Spirit Stones", "platform": "Console"}, "-492470683": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-492468239": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225233": {"name": "Legendary: Madstone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1935108657": {"name": "Legendary: Madstone (Patch 2.1.0)", "category": "Spirit Stones", "platform": "Console"}, "635723798": {"name": "Legendary: See No Evil", "category": "Spirit Stones", "platform": "Console"}, "-496028446": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-496026002": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225230": {"name": "Legendary: See No Evil (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635759735": {"name": "Legendary: The Eye of the Storm", "category": "Spirit Stones", "platform": "Console"}, "-494842525": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-494840081": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225231": {"name": "Legendary: The Eye of the Storm (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674715443": {"name": "Legendary: The Laws of Seph", "category": "Spirit Stones", "platform": "Console"}, "635615987": {"name": "Legendary: The Mind's Eye", "category": "Spirit Stones", "platform": "Console"}, "-499586209": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-499583765": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225227": {"name": "Legendary: The Mind's Eye (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635795672": {"name": "Legendary: Tzo Krin's Gaze", "category": "Spirit Stones", "platform": "Console"}, "-493656604": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-493654160": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225232": {"name": "Legendary: Tzo Krin's Gaze (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635867546": {"name": "Set: Inna's Radiance", "category": "Spirit Stones", "platform": "Console"}, "-491284762": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-491282318": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225234": {"name": "Set: Inna's Splendor (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}}, "Staves": {"-2115691355": {"name": "02: Long Staff (DPS 17.0-18.5)", "category": "Staves", "platform": "Console"}, "-2115691354": {"name": "03: Yew Staff (DPS 22.0-23.5)", "category": "Staves", "platform": "Console"}, "-2115691353": {"name": "04: Gnarled Staff (DPS 27.0-28.5)", "category": "Staves", "platform": "Console"}, "-2115691352": {"name": "05: Bone Staff (DPS 33.0-34.5)", "category": "Staves", "platform": "Console"}, "-2115691351": {"name": "06: Battle Staff (DPS 40.5-42.0)", "category": "Staves", "platform": "Console"}, "-2115691350": {"name": "07: War Staff (DPS 50.5-53.5)", "category": "Staves", "platform": "Console"}, "-2115690267": {"name": "08: Mentor Staff (DPS 66.5-69.5)", "category": "Staves", "platform": "Console"}, "-2115690266": {"name": "09: Obsidian Staff (DPS 75.5-78.5)", "category": "Staves", "platform": "Console"}, "-2115690265": {"name": "10: Petrified Staff (DPS 90.0-94.5)", "category": "Staves", "platform": "Console"}, "-2115690264": {"name": "11: Elder Staff (DPS 101.5-106.0)", "category": "Staves", "platform": "Console"}, "-2115690263": {"name": "12: Shamanic Staff (DPS 121.0-127.0)", "category": "Staves", "platform": "Console"}, "-2115690262": {"name": "13: High Priest Staff (DPS 138.5-144.5)", "category": "Staves", "platform": "Console"}, "-2115690261": {"name": "14: Arcane Staff (DPS 174.5-182.0)", "category": "Staves", "platform": "Console"}, "-2115689178": {"name": "15: Hyperion Staff (DPS 204.5-212.0)", "category": "Staves", "platform": "Console"}, "-2115689177": {"name": "16: Stygian Staff (DPS 237.0-246.0)", "category": "Staves", "platform": "Console"}, "-2115689176": {"name": "17: Primordial Staff (DPS 275.5-286.0)", "category": "Staves", "platform": "Console"}, "-2115689175": {"name": "18: Archaic Staff (DPS 320.0-332.0)", "category": "Staves", "platform": "Console"}, "-2115689174": {"name": "19: Conquest Staff (DPS 409.0-421.0)", "category": "Staves", "platform": "Console"}, "-2115689173": {"name": "20: Mythical Staff (DPS 484.0-496.0)", "category": "Staves", "platform": "Console"}, "-2115689172": {"name": "21: Sovereign Staff (DPS 572.5-584.5)", "category": "Staves", "platform": "Console"}, "-2115688089": {"name": "22: Caduceus Staff (DPS 712.3-725.5)", "category": "Staves", "platform": "Console"}, "-2115688088": {"name": "23: Kerykeion (DPS 968.0-981.2)", "category": "Staves", "platform": "Console"}, "-1849507048": {"name": "Art Test CombatStaff Two-Handed 1", "category": "Staves", "platform": "Console"}, "-1849507047": {"name": "Art Test CombatStaff Two-Handed 2", "category": "Staves", "platform": "Console"}, "-1849507046": {"name": "Art Test CombatStaff Two-Handed 3", "category": "Staves", "platform": "Console"}, "-1849507045": {"name": "Art Test CombatStaff Two-Handed 4", "category": "Staves", "platform": "Console"}, "-1849507044": {"name": "Art Test CombatStaff Two-Handed 5", "category": "Staves", "platform": "Console"}, "1590673385": {"name": "Art Test Staff 1", "category": "Staves", "platform": "Console"}, "1590673386": {"name": "Art Test Staff 2", "category": "Staves", "platform": "Console"}, "1590673387": {"name": "Art Test Staff 3", "category": "Staves", "platform": "Console"}, "1590673388": {"name": "Art Test Staff 4", "category": "Staves", "platform": "Console"}, "1590673389": {"name": "Art Test Staff 5", "category": "Staves", "platform": "Console"}, "2065442005": {"name": "Crafted: Elderwood Staff", "category": "Staves", "platform": "Console"}, "-1170762813": {"name": "Legendary: Ahavarion, Spear of Lycander", "category": "Staves", "platform": "Console"}, "-1209646647": {"name": "Legendary: Autumn's Call", "category": "Staves", "platform": "Console"}, "-1263710987": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "-1263708543": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "300184993": {"name": "Legendary: Autumn's Call (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-306066026": {"name": "Legendary: Hellish Staff of Herding", "category": "Staves", "platform": "Console"}, "1952916002": {"name": "Legendary: Infernal Staff of Herding", "category": "Staves", "platform": "Console"}, "-1209718521": {"name": "Legendary: Maloth's Focus", "category": "Staves", "platform": "Console"}, "-1266082829": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "-1266080385": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "300184991": {"name": "Legendary: Maloth's Focus (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209862269": {"name": "Legendary: Mark of The Magi", "category": "Staves", "platform": "Console"}, "-1409366405": {"name": "Legendary: Ner'zhul's Staff of Shadowmoon (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "670723600": {"name": "Legendary: Nightmarish Staff of Herding", "category": "Staves", "platform": "Console"}, "-1077364974": {"name": "Legendary: Staff of Herding", "category": "Staves", "platform": "Console"}, "-1170655002": {"name": "Legendary: SuWong Diviner", "category": "Staves", "platform": "Console"}, "-1209898206": {"name": "Legendary: The Broken Staff", "category": "Staves", "platform": "Console"}, "-1272012434": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "-1272009990": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "300184986": {"name": "Legendary: The Broken Staff (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610710": {"name": "Legendary: The Grand Vizier", "category": "Staves", "platform": "Console"}, "-1262525066": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "-1262522622": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "300184994": {"name": "Legendary: The Grand Vizier (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610974": {"name": "Legendary: The Grand Vizier (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "-1270826513": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "-1270824069": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "300184987": {"name": "Legendary: The Magi (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170690939": {"name": "Legendary: The Smoldering Core", "category": "Staves", "platform": "Console"}, "-1209682584": {"name": "Legendary: The Tormentor", "category": "Staves", "platform": "Console"}, "-1264896908": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "-1264894464": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "300184992": {"name": "Legendary: The Tormentor (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170726876": {"name": "Legendary: Valthek's Rebuke", "category": "Staves", "platform": "Console"}, "-1209826332": {"name": "Legendary: Wormwood", "category": "Staves", "platform": "Console"}, "-1269640592": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "-1269638148": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "300184988": {"name": "Legendary: Wormwood (Old-Legacy)", "category": "Staves", "platform": "Console"}, "1889450717": {"name": "Legendary: Wormwood (Patch 2.1.2)", "category": "Staves", "platform": "Console"}, "-1953260964": {"name": "P2 combatStaff norm Legendary 01", "category": "Staves", "platform": "Console"}, "397178771": {"name": "PvP: Heroic Staff", "category": "Staves", "platform": "Console"}, "397178770": {"name": "PvP: Mighty Staff", "category": "Staves", "platform": "Console"}, "397178769": {"name": "PvP: Staff", "category": "Staves", "platform": "Console"}}, "Swords, One-Handed": {"-270938920": {"name": "02: Sabre (DPS 8.4-10.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938919": {"name": "03: Broadsword (DPS 11.2-13.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938918": {"name": "04: Longsword (DPS 16.1-18.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938917": {"name": "05: Falchion (DPS 20.3-22.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938916": {"name": "06: Scimitar (DPS 24.5-26.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938915": {"name": "07: War Sword (DPS 28.0-30.1)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938914": {"name": "08: Bastard Sword (DPS 32.2-34.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937832": {"name": "09: Gladius (DPS 39.2-41.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937831": {"name": "10: Cutlass (DPS 44.1-46.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937830": {"name": "11: Battle Sword (DPS 48.3-50.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937829": {"name": "12: Knight Sword (DPS 53.2-55.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937828": {"name": "13: Dao (DPS 62.3-64.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937827": {"name": "14: Shamshir (DPS 73.5-75.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937826": {"name": "15: Raid Sword (DPS 81.2-83.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937825": {"name": "16: Ancient Sword (DPS 93.1-95.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936743": {"name": "17: Spatha (DPS 100.1-104.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936742": {"name": "18: Pirate Sword (DPS 112.0-116.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936741": {"name": "19: Strong Sword (DPS 123.2-127.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936740": {"name": "20: King Blade (DPS 137.2-141.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936739": {"name": "21: Tulwar (DPS 151.2-155.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936738": {"name": "22: Saif (DPS 181.3-187.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936737": {"name": "23: Conquest Sword (DPS 210.0-216.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936736": {"name": "24: Rune Sword (DPS 242.2-248.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935654": {"name": "25: Champion Sword (DPS 322.0-328.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935653": {"name": "26: Tsunami Blade (DPS 392.0-398.3)", "category": "Swords, One-Handed", "platform": "Console"}, "1775003964": {"name": "Art Test Sword One-Handed 1", "category": "Swords, One-Handed", "platform": "Console"}, "1775003965": {"name": "Art Test Sword One-Handed 2", "category": "Swords, One-Handed", "platform": "Console"}, "1775003966": {"name": "Art Test Sword One-Handed 3", "category": "Swords, One-Handed", "platform": "Console"}, "1775003967": {"name": "Art Test Sword One-Handed 4", "category": "Swords, One-Handed", "platform": "Console"}, "1775003968": {"name": "Art Test Sword One-Handed 5", "category": "Swords, One-Handed", "platform": "Console"}, "560809999": {"name": "Crafted: Blacksteel Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1351405527": {"name": "Legendary: Amberwing", "category": "Swords, One-Handed", "platform": "Console"}, "1312306071": {"name": "Legendary: Azurewrath", "category": "Swords, One-Handed", "platform": "Console"}, "356350083": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "356352527": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242223": {"name": "Legendary: Azurewrath (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351441464": {"name": "Legendary: Deathwish", "category": "Swords, One-Handed", "platform": "Console"}, "1312270134": {"name": "Legendary: Devil Tongue", "category": "Swords, One-Handed", "platform": "Console"}, "355164162": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "355166606": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242222": {"name": "Legendary: Devil Tongue (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312377945": {"name": "Legendary: Doombringer", "category": "Swords, One-Handed", "platform": "Console"}, "358721925": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "358724369": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242225": {"name": "Legendary: Doombringer (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350255543": {"name": "Legendary: Exarian", "category": "Swords, One-Handed", "platform": "Console"}, "1350327417": {"name": "Legendary: Fulminator", "category": "Swords, One-Handed", "platform": "Console"}, "1350399291": {"name": "Legendary: Ghoul King's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "1350291480": {"name": "Legendary: Gift of Silaria", "category": "Swords, One-Handed", "platform": "Console"}, "1350363354": {"name": "Legendary: God Butcher", "category": "Swords, One-Handed", "platform": "Console"}, "364651530": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "364653974": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242230": {"name": "Legendary: Griswold's Masterpiece (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312557630": {"name": "Legendary: Griswold's Perfection", "category": "Swords, One-Handed", "platform": "Console"}, "1311084213": {"name": "Legendary: Griswold's Worn Edge", "category": "Swords, One-Handed", "platform": "Console"}, "316028769": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "316031213": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242189": {"name": "Legendary: Griswold's Worn Edge (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350471165": {"name": "Legendary: Incinerator", "category": "Swords, One-Handed", "platform": "Console"}, "229247441": {"name": "Legendary: Lifebane", "category": "Swords, One-Handed", "platform": "Console"}, "1312485756": {"name": "Legendary: Monster Hunter", "category": "Swords, One-Handed", "platform": "Console"}, "362279688": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "362282132": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242228": {"name": "Legendary: Monster Hunter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350435228": {"name": "Legendary: Nazim's Greatness", "category": "Swords, One-Handed", "platform": "Console"}, "1312234197": {"name": "Legendary: Rakanishu's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "353978241": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "353980685": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242221": {"name": "Legendary: Rakanishu's Blade (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351369590": {"name": "Legendary: Rancor", "category": "Swords, One-Handed", "platform": "Console"}, "1350507102": {"name": "Legendary: Rimeheart", "category": "Swords, One-Handed", "platform": "Console"}, "1311299835": {"name": "Legendary: Sever", "category": "Swords, One-Handed", "platform": "Console"}, "323144295": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "323146739": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242195": {"name": "Legendary: Sever (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "229283378": {"name": "Legendary: Shard of Hate", "category": "Swords, One-Handed", "platform": "Console"}, "1311192024": {"name": "Legendary: Skycutter", "category": "Swords, One-Handed", "platform": "Console"}, "319586532": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "319588976": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242192": {"name": "Legendary: Skycutter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1313456055": {"name": "Legendary: Spectrum", "category": "Swords, One-Handed", "platform": "Console"}, "394299555": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "394301999": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242255": {"name": "Legendary: Spectrum (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1311156087": {"name": "Legendary: The Ancient Bonesaber of Zumakalis", "category": "Swords, One-Handed", "platform": "Console"}, "318400611": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "318403055": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242191": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350219606": {"name": "Legendary: Thunderfury, Blessed Blade of the Windseeker", "category": "Swords, One-Handed", "platform": "Console"}, "1311120150": {"name": "Legendary: Wildwood", "category": "Swords, One-Handed", "platform": "Console"}, "317214690": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "317217134": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242190": {"name": "Legendary: Wildwood (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487634": {"name": "PvP: Heroic Bastard Sword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487635": {"name": "PvP: Mighty Longsword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487636": {"name": "PvP: Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1312521693": {"name": "Set: Born's Furious Wrath", "category": "Swords, One-Handed", "platform": "Console"}, "363465609": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "363468053": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242229": {"name": "Set: Born's Seething Rage (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1394445518": {"name": "Set: Little Rogue", "category": "Swords, One-Handed", "platform": "Console"}, "-1394481455": {"name": "Set: The Slanderer", "category": "Swords, One-Handed", "platform": "Console"}, "-2025765397": {"name": "Sword Of Justice Tyrael", "category": "Swords, One-Handed", "platform": "Console"}, "1351477401": {"name": "legendary: In-geom (Patch 2.2.0)", "category": "Swords, One-Handed", "platform": "Console"}}, "Swords, Two-Handed": {"-231803527": {"name": "02: Flamberge (DPS 16.0-17.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803526": {"name": "03: Dervish (DPS 22.6-24.2)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803525": {"name": "04: Executioner Sword (DPS 28.1-29.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803524": {"name": "05: Nodachi (DPS 35.2-36.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803523": {"name": "06: Claymore (DPS 41.8-43.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802439": {"name": "07: Great Sword (DPS 52.8-54.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802438": {"name": "08: Reaver (DPS 62.2-65.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802437": {"name": "09: Kilij (DPS 74.8-78.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802436": {"name": "10: Mameluke (DPS 89.7-93.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802435": {"name": "11: Nagamaki (DPS 106.2-111.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802434": {"name": "12: Grand Sword (DPS 126.5-133.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801350": {"name": "13: Highland Sword (DPS 171.6-179.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801349": {"name": "14: Brimstone Sword (DPS 215.6-223.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801348": {"name": "15: Yatagan (DPS 269.0-278.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801347": {"name": "16: Colossus Blade (DPS 367.4-379.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801346": {"name": "17: Oni Blade (DPS 433.4-446.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801345": {"name": "18: Warlord Sword (DPS 511.5-524.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800261": {"name": "19: Gothic Blade (DPS 670.5-682.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800260": {"name": "20: Kingslayer (DPS 907.4-919.4)", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039901": {"name": "Art Test Sword Two-Handed 1", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039902": {"name": "Art Test Sword Two-Handed 2", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039903": {"name": "Art Test Sword Two-Handed 3", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039904": {"name": "Art Test Sword Two-Handed 4", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039905": {"name": "Art Test Sword Two-Handed 5", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028384713": {"name": "Legendary: Blackguard", "category": "Swords, Two-Handed", "platform": "Console"}, "422965539": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "422967983": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377615": {"name": "Legendary: Blackguard (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029355012": {"name": "Legendary: Blade of Prophecy", "category": "Swords, Two-Handed", "platform": "Console"}, "390945672": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "390948116": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377588": {"name": "Legendary: Blade of Prophecy (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "1516448771": {"name": "Legendary: Blade of the Ancients", "category": "Swords, Two-Handed", "platform": "Console"}, "-990363367": {"name": "Legendary: Blood Brother", "category": "Swords, Two-Handed", "platform": "Console"}, "-990399304": {"name": "Legendary: Cam's Rebuttal", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028348776": {"name": "Legendary: Faithful Memory", "category": "Swords, Two-Handed", "platform": "Console"}, "424151460": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "424153904": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377616": {"name": "Legendary: Faithful Memory (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028420650": {"name": "Legendary: Maximus", "category": "Swords, Two-Handed", "platform": "Console"}, "421779618": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "421782062": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377614": {"name": "Legendary: Maximus (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029462823": {"name": "Legendary: Scourge", "category": "Swords, Two-Handed", "platform": "Console"}, "387387909": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "387390353": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377585": {"name": "Legendary: Scourge (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028276902": {"name": "Legendary: Splintered Oar", "category": "Swords, Two-Handed", "platform": "Console"}, "426523302": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "426525746": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377618": {"name": "Legendary: Splintered Oar (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990435241": {"name": "Legendary: Stalgard's Decimator", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029570634": {"name": "Legendary: The Grandfather", "category": "Swords, Two-Handed", "platform": "Console"}, "383830146": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "383832590": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377582": {"name": "Legendary: The Grandfather (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029319075": {"name": "Legendary: The Sultan of Blinding Sand", "category": "Swords, Two-Handed", "platform": "Console"}, "392131593": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "392134037": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377589": {"name": "Legendary: The Sultan of Blinding Sand (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029534697": {"name": "Legendary: The Zweihander", "category": "Swords, Two-Handed", "platform": "Console"}, "385016067": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "385018511": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377583": {"name": "Legendary: The Zweihander (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029498760": {"name": "Legendary: Warmonger", "category": "Swords, Two-Handed", "platform": "Console"}, "386201988": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "386204432": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377584": {"name": "Legendary: Warmonger (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1271367654": {"name": "legendary: Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990291493": {"name": "legendary: Ch'il-chi-do (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990327430": {"name": "legendary: Corrupted Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}}, "Templar Relics": {"1147339622": {"name": "02: Spear Fragment", "category": "Templar Relics", "platform": "Console"}, "1147340710": {"name": "03: Sacred Text", "category": "Templar Relics", "platform": "Console"}, "1147340711": {"name": "04: Blade Shard", "category": "Templar Relics", "platform": "Console"}, "1147340712": {"name": "05: Martyr Tears", "category": "Templar Relics", "platform": "Console"}, "1147340713": {"name": "06: Chalice", "category": "Templar Relics", "platform": "Console"}, "1147341799": {"name": "07: Libram Spiritus", "category": "Templar Relics", "platform": "Console"}, "1147341800": {"name": "08: Blade Remnant", "category": "Templar Relics", "platform": "Console"}, "1147341801": {"name": "09: Saint Tears", "category": "Templar Relics", "platform": "Console"}, "1147341802": {"name": "10: Grail", "category": "Templar Relics", "platform": "Console"}, "1147341803": {"name": "11: Codex", "category": "Templar Relics", "platform": "Console"}, "1147341804": {"name": "12: Broken Foible", "category": "Templar Relics", "platform": "Console"}, "-765770609": {"name": "Legendary: Enchanting Favor", "category": "Templar Relics", "platform": "Console"}, "-765770607": {"name": "Legendary: Hillenbrand's Training Sword", "category": "Templar Relics", "platform": "Console"}, "-765770608": {"name": "Legendary: Relic of Akarat", "category": "Templar Relics", "platform": "Console"}}, "Test": {"-1438295707": {"name": "Don's Sword of Testing", "category": "Test", "platform": "Console"}, "-1585353949": {"name": "P1 Test Ring 941 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353948": {"name": "P1 Test Ring 942 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353947": {"name": "P1 Test Ring 943 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353946": {"name": "P1 Test Ring 944 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388889": {"name": "P2 TEST RING 021 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388890": {"name": "P2 TEST RING 022 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388891": {"name": "P2 TEST RING 023 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388892": {"name": "P2 TEST RING 024 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388893": {"name": "P2 TEST RING 025 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388894": {"name": "P2 TEST RING 026 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388895": {"name": "P2 TEST RING 027 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388896": {"name": "P2 TEST RING 028 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388897": {"name": "P2 TEST RING 029 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388921": {"name": "P2 TEST RING 030 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388922": {"name": "P2 TEST RING 031 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388923": {"name": "P2 TEST RING 032 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388924": {"name": "P2 TEST RING 033 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388925": {"name": "P2 TEST RING 034 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388926": {"name": "P2 TEST RING 035 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388927": {"name": "P2 TEST RING 036 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388928": {"name": "P2 TEST RING 037 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388929": {"name": "P2 TEST RING 038 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388930": {"name": "P2 TEST RING 039 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388954": {"name": "P2 TEST RING 040 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388955": {"name": "P2 TEST RING 041 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388956": {"name": "P2 TEST RING 042 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388957": {"name": "P2 TEST RING 043 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388958": {"name": "P2 TEST RING 044 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388959": {"name": "P2 TEST RING 045 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388960": {"name": "P2 TEST RING 046 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388961": {"name": "P2 TEST RING 047 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388962": {"name": "P2 TEST RING 048 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388963": {"name": "P2 TEST RING 049 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388987": {"name": "P2 TEST RING 050 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388824": {"name": "P2 Test Ring 002 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388825": {"name": "P2 Test Ring 003 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388826": {"name": "P2 Test Ring 004 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388827": {"name": "P2 Test Ring 005 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388828": {"name": "P2 Test Ring 006 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388829": {"name": "P2 Test Ring 007 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388830": {"name": "P2 Test Ring 008 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388831": {"name": "P2 Test Ring 009 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388855": {"name": "P2 Test Ring 010 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388856": {"name": "P2 Test Ring 011 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388857": {"name": "P2 Test Ring 012 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388858": {"name": "P2 Test Ring 013 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388859": {"name": "P2 Test Ring 014 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388860": {"name": "P2 Test Ring 015 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388861": {"name": "P2 Test Ring 016 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388862": {"name": "P2 Test Ring 017 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388863": {"name": "P2 Test Ring 018 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388864": {"name": "P2 Test Ring 019 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388888": {"name": "P2 Test Ring 020 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "1608362283": {"name": "P2_WizardSet_Scroll_Test (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388823": {"name": "Test Ring 001 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "708102766": {"name": "Test Ring 1000", "category": "Test", "platform": "Console"}, "-993303550": {"name": "Test Ring 500", "category": "Test", "platform": "Console"}, "-993267613": {"name": "Test Ring 501", "category": "Test", "platform": "Console"}, "-993231676": {"name": "Test Ring 502", "category": "Test", "platform": "Console"}, "-993195739": {"name": "Test Ring 503", "category": "Test", "platform": "Console"}, "-993159802": {"name": "Test Ring 504", "category": "Test", "platform": "Console"}, "-993123865": {"name": "Test Ring 505", "category": "Test", "platform": "Console"}, "-993087928": {"name": "Test Ring 506", "category": "Test", "platform": "Console"}, "-993051991": {"name": "Test Ring 507", "category": "Test", "platform": "Console"}, "-993016054": {"name": "Test Ring 508", "category": "Test", "platform": "Console"}, "-992980117": {"name": "Test Ring 509", "category": "Test", "platform": "Console"}, "-992117629": {"name": "Test Ring 510", "category": "Test", "platform": "Console"}, "-992081692": {"name": "Test Ring 511", "category": "Test", "platform": "Console"}, "-992045755": {"name": "Test Ring 512", "category": "Test", "platform": "Console"}, "-992009818": {"name": "Test Ring 513", "category": "Test", "platform": "Console"}, "-991973881": {"name": "Test Ring 514", "category": "Test", "platform": "Console"}, "-991937944": {"name": "Test Ring 515", "category": "Test", "platform": "Console"}, "-991902007": {"name": "Test Ring 516", "category": "Test", "platform": "Console"}, "-991866070": {"name": "Test Ring 517", "category": "Test", "platform": "Console"}, "-991830133": {"name": "Test Ring 518", "category": "Test", "platform": "Console"}, "-991794196": {"name": "Test Ring 519", "category": "Test", "platform": "Console"}, "-990931708": {"name": "Test Ring 520", "category": "Test", "platform": "Console"}, "-990895771": {"name": "Test Ring 521", "category": "Test", "platform": "Console"}, "-990859834": {"name": "Test Ring 522", "category": "Test", "platform": "Console"}, "-990823897": {"name": "Test Ring 523", "category": "Test", "platform": "Console"}, "-990787960": {"name": "Test Ring 524", "category": "Test", "platform": "Console"}, "-990752023": {"name": "Test Ring 525", "category": "Test", "platform": "Console"}, "-990716086": {"name": "Test Ring 526", "category": "Test", "platform": "Console"}, "-990680149": {"name": "Test Ring 527", "category": "Test", "platform": "Console"}, "-990644212": {"name": "Test Ring 528", "category": "Test", "platform": "Console"}, "-990608275": {"name": "Test Ring 529", "category": "Test", "platform": "Console"}, "-989745787": {"name": "Test Ring 530", "category": "Test", "platform": "Console"}, "-989709850": {"name": "Test Ring 531", "category": "Test", "platform": "Console"}, "-989673913": {"name": "Test Ring 532", "category": "Test", "platform": "Console"}, "-989637976": {"name": "Test Ring 533", "category": "Test", "platform": "Console"}, "-989602039": {"name": "Test Ring 534", "category": "Test", "platform": "Console"}, "-989566102": {"name": "Test Ring 535", "category": "Test", "platform": "Console"}, "-989530165": {"name": "Test Ring 536", "category": "Test", "platform": "Console"}, "-989494228": {"name": "Test Ring 537", "category": "Test", "platform": "Console"}, "-989458291": {"name": "Test Ring 538", "category": "Test", "platform": "Console"}, "-989422354": {"name": "Test Ring 539", "category": "Test", "platform": "Console"}, "-988559866": {"name": "Test Ring 540", "category": "Test", "platform": "Console"}, "-988523929": {"name": "Test Ring 541", "category": "Test", "platform": "Console"}, "-988487992": {"name": "Test Ring 542", "category": "Test", "platform": "Console"}, "-988452055": {"name": "Test Ring 543", "category": "Test", "platform": "Console"}, "-988416118": {"name": "Test Ring 544", "category": "Test", "platform": "Console"}, "-988380181": {"name": "Test Ring 545", "category": "Test", "platform": "Console"}, "-988344244": {"name": "Test Ring 546", "category": "Test", "platform": "Console"}, "-988308307": {"name": "Test Ring 547", "category": "Test", "platform": "Console"}, "-988272370": {"name": "Test Ring 548", "category": "Test", "platform": "Console"}, "-988236433": {"name": "Test Ring 549", "category": "Test", "platform": "Console"}, "-987373945": {"name": "Test Ring 550", "category": "Test", "platform": "Console"}, "-987338008": {"name": "Test Ring 551", "category": "Test", "platform": "Console"}, "-987302071": {"name": "Test Ring 552", "category": "Test", "platform": "Console"}, "-987266134": {"name": "Test Ring 553", "category": "Test", "platform": "Console"}, "-987230197": {"name": "Test Ring 554", "category": "Test", "platform": "Console"}, "-987194260": {"name": "Test Ring 555", "category": "Test", "platform": "Console"}, "-987158323": {"name": "Test Ring 556", "category": "Test", "platform": "Console"}, "-987122386": {"name": "Test Ring 557", "category": "Test", "platform": "Console"}, "-987086449": {"name": "Test Ring 558", "category": "Test", "platform": "Console"}, "-987050512": {"name": "Test Ring 559", "category": "Test", "platform": "Console"}, "-986188024": {"name": "Test Ring 560", "category": "Test", "platform": "Console"}, "-986152087": {"name": "Test Ring 561", "category": "Test", "platform": "Console"}, "-986116150": {"name": "Test Ring 562", "category": "Test", "platform": "Console"}, "-986080213": {"name": "Test Ring 563", "category": "Test", "platform": "Console"}, "-986044276": {"name": "Test Ring 564", "category": "Test", "platform": "Console"}, "-986008339": {"name": "Test Ring 565", "category": "Test", "platform": "Console"}, "-985972402": {"name": "Test Ring 566", "category": "Test", "platform": "Console"}, "-985936465": {"name": "Test Ring 567", "category": "Test", "platform": "Console"}, "-985900528": {"name": "Test Ring 568", "category": "Test", "platform": "Console"}, "-985864591": {"name": "Test Ring 569", "category": "Test", "platform": "Console"}, "-985002103": {"name": "Test Ring 570", "category": "Test", "platform": "Console"}, "-984966166": {"name": "Test Ring 571", "category": "Test", "platform": "Console"}, "-984930229": {"name": "Test Ring 572", "category": "Test", "platform": "Console"}, "-984894292": {"name": "Test Ring 573", "category": "Test", "platform": "Console"}, "-984858355": {"name": "Test Ring 574", "category": "Test", "platform": "Console"}, "-984822418": {"name": "Test Ring 575", "category": "Test", "platform": "Console"}, "-984786481": {"name": "Test Ring 576", "category": "Test", "platform": "Console"}, "-984750544": {"name": "Test Ring 577", "category": "Test", "platform": "Console"}, "-984714607": {"name": "Test Ring 578", "category": "Test", "platform": "Console"}, "-984678670": {"name": "Test Ring 579", "category": "Test", "platform": "Console"}, "-983816182": {"name": "Test Ring 580", "category": "Test", "platform": "Console"}, "-983780245": {"name": "Test Ring 581", "category": "Test", "platform": "Console"}, "-983744308": {"name": "Test Ring 582", "category": "Test", "platform": "Console"}, "-983708371": {"name": "Test Ring 583", "category": "Test", "platform": "Console"}, "-983672434": {"name": "Test Ring 584", "category": "Test", "platform": "Console"}, "-983636497": {"name": "Test Ring 585", "category": "Test", "platform": "Console"}, "-983600560": {"name": "Test Ring 586", "category": "Test", "platform": "Console"}, "-983564623": {"name": "Test Ring 587", "category": "Test", "platform": "Console"}, "-983528686": {"name": "Test Ring 588", "category": "Test", "platform": "Console"}, "-983492749": {"name": "Test Ring 589", "category": "Test", "platform": "Console"}, "-982630261": {"name": "Test Ring 590", "category": "Test", "platform": "Console"}, "-982594324": {"name": "Test Ring 591", "category": "Test", "platform": "Console"}, "-982558387": {"name": "Test Ring 592", "category": "Test", "platform": "Console"}, "-982522450": {"name": "Test Ring 593", "category": "Test", "platform": "Console"}, "-982486513": {"name": "Test Ring 594", "category": "Test", "platform": "Console"}, "-982450576": {"name": "Test Ring 595", "category": "Test", "platform": "Console"}, "-982414639": {"name": "Test Ring 596", "category": "Test", "platform": "Console"}, "-982378702": {"name": "Test Ring 597", "category": "Test", "platform": "Console"}, "-982342765": {"name": "Test Ring 598", "category": "Test", "platform": "Console"}, "-982306828": {"name": "Test Ring 599", "category": "Test", "platform": "Console"}, "-954168157": {"name": "Test Ring 600", "category": "Test", "platform": "Console"}, "-954132220": {"name": "Test Ring 601", "category": "Test", "platform": "Console"}, "-954096283": {"name": "Test Ring 602", "category": "Test", "platform": "Console"}, "-954060346": {"name": "Test Ring 603", "category": "Test", "platform": "Console"}, "-954024409": {"name": "Test Ring 604", "category": "Test", "platform": "Console"}, "-953988472": {"name": "Test Ring 605", "category": "Test", "platform": "Console"}, "-953952535": {"name": "Test Ring 606", "category": "Test", "platform": "Console"}, "-953916598": {"name": "Test Ring 607", "category": "Test", "platform": "Console"}, "-953880661": {"name": "Test Ring 608", "category": "Test", "platform": "Console"}, "-953844724": {"name": "Test Ring 609", "category": "Test", "platform": "Console"}, "-952982236": {"name": "Test Ring 610", "category": "Test", "platform": "Console"}, "-952946299": {"name": "Test Ring 611", "category": "Test", "platform": "Console"}, "-952910362": {"name": "Test Ring 612", "category": "Test", "platform": "Console"}, "-952874425": {"name": "Test Ring 613", "category": "Test", "platform": "Console"}, "-952838488": {"name": "Test Ring 614", "category": "Test", "platform": "Console"}, "-952802551": {"name": "Test Ring 615", "category": "Test", "platform": "Console"}, "-952766614": {"name": "Test Ring 616", "category": "Test", "platform": "Console"}, "-952730677": {"name": "Test Ring 617", "category": "Test", "platform": "Console"}, "-952694740": {"name": "Test Ring 618", "category": "Test", "platform": "Console"}, "-952658803": {"name": "Test Ring 619", "category": "Test", "platform": "Console"}, "-951796315": {"name": "Test Ring 620", "category": "Test", "platform": "Console"}, "-951760378": {"name": "Test Ring 621", "category": "Test", "platform": "Console"}, "-951724441": {"name": "Test Ring 622", "category": "Test", "platform": "Console"}, "-951688504": {"name": "Test Ring 623", "category": "Test", "platform": "Console"}, "-951652567": {"name": "Test Ring 624", "category": "Test", "platform": "Console"}, "-951616630": {"name": "Test Ring 625", "category": "Test", "platform": "Console"}, "-951580693": {"name": "Test Ring 626", "category": "Test", "platform": "Console"}, "-951544756": {"name": "Test Ring 627", "category": "Test", "platform": "Console"}, "-951508819": {"name": "Test Ring 628", "category": "Test", "platform": "Console"}, "-951472882": {"name": "Test Ring 629", "category": "Test", "platform": "Console"}, "-950610394": {"name": "Test Ring 630", "category": "Test", "platform": "Console"}, "-950574457": {"name": "Test Ring 631", "category": "Test", "platform": "Console"}, "-950538520": {"name": "Test Ring 632", "category": "Test", "platform": "Console"}, "-950502583": {"name": "Test Ring 633", "category": "Test", "platform": "Console"}, "-950466646": {"name": "Test Ring 634", "category": "Test", "platform": "Console"}, "-950430709": {"name": "Test Ring 635", "category": "Test", "platform": "Console"}, "-950394772": {"name": "Test Ring 636", "category": "Test", "platform": "Console"}, "-950358835": {"name": "Test Ring 637", "category": "Test", "platform": "Console"}, "-950322898": {"name": "Test Ring 638", "category": "Test", "platform": "Console"}, "-950286961": {"name": "Test Ring 639", "category": "Test", "platform": "Console"}, "-949424473": {"name": "Test Ring 640", "category": "Test", "platform": "Console"}, "-949388536": {"name": "Test Ring 641", "category": "Test", "platform": "Console"}, "-949352599": {"name": "Test Ring 642", "category": "Test", "platform": "Console"}, "-949316662": {"name": "Test Ring 643", "category": "Test", "platform": "Console"}, "-949280725": {"name": "Test Ring 644", "category": "Test", "platform": "Console"}, "-949244788": {"name": "Test Ring 645", "category": "Test", "platform": "Console"}, "-949208851": {"name": "Test Ring 646", "category": "Test", "platform": "Console"}, "-949172914": {"name": "Test Ring 647", "category": "Test", "platform": "Console"}, "-949136977": {"name": "Test Ring 648", "category": "Test", "platform": "Console"}, "-949101040": {"name": "Test Ring 649", "category": "Test", "platform": "Console"}, "-948238552": {"name": "Test Ring 650", "category": "Test", "platform": "Console"}, "-948202615": {"name": "Test Ring 651", "category": "Test", "platform": "Console"}, "-948166678": {"name": "Test Ring 652", "category": "Test", "platform": "Console"}, "-948130741": {"name": "Test Ring 653", "category": "Test", "platform": "Console"}, "-948094804": {"name": "Test Ring 654", "category": "Test", "platform": "Console"}, "-948058867": {"name": "Test Ring 655", "category": "Test", "platform": "Console"}, "-948022930": {"name": "Test Ring 656", "category": "Test", "platform": "Console"}, "-947986993": {"name": "Test Ring 657", "category": "Test", "platform": "Console"}, "-947951056": {"name": "Test Ring 658", "category": "Test", "platform": "Console"}, "-947915119": {"name": "Test Ring 659", "category": "Test", "platform": "Console"}, "-947052631": {"name": "Test Ring 660", "category": "Test", "platform": "Console"}, "-947016694": {"name": "Test Ring 661", "category": "Test", "platform": "Console"}, "-946980757": {"name": "Test Ring 662", "category": "Test", "platform": "Console"}, "-946944820": {"name": "Test Ring 663", "category": "Test", "platform": "Console"}, "-946908883": {"name": "Test Ring 664", "category": "Test", "platform": "Console"}, "-946872946": {"name": "Test Ring 665", "category": "Test", "platform": "Console"}, "-946837009": {"name": "Test Ring 666", "category": "Test", "platform": "Console"}, "-946801072": {"name": "Test Ring 667", "category": "Test", "platform": "Console"}, "-946765135": {"name": "Test Ring 668", "category": "Test", "platform": "Console"}, "-946729198": {"name": "Test Ring 669", "category": "Test", "platform": "Console"}, "-945866710": {"name": "Test Ring 670", "category": "Test", "platform": "Console"}, "-945830773": {"name": "Test Ring 671", "category": "Test", "platform": "Console"}, "-945794836": {"name": "Test Ring 672", "category": "Test", "platform": "Console"}, "-945758899": {"name": "Test Ring 673", "category": "Test", "platform": "Console"}, "-945722962": {"name": "Test Ring 674", "category": "Test", "platform": "Console"}, "-945687025": {"name": "Test Ring 675", "category": "Test", "platform": "Console"}, "-945651088": {"name": "Test Ring 676", "category": "Test", "platform": "Console"}, "-945615151": {"name": "Test Ring 677", "category": "Test", "platform": "Console"}, "-945579214": {"name": "Test Ring 678", "category": "Test", "platform": "Console"}, "-945543277": {"name": "Test Ring 679", "category": "Test", "platform": "Console"}, "-944680789": {"name": "Test Ring 680", "category": "Test", "platform": "Console"}, "-944644852": {"name": "Test Ring 681", "category": "Test", "platform": "Console"}, "-944608915": {"name": "Test Ring 682", "category": "Test", "platform": "Console"}, "-944572978": {"name": "Test Ring 683", "category": "Test", "platform": "Console"}, "-944537041": {"name": "Test Ring 684", "category": "Test", "platform": "Console"}, "-944501104": {"name": "Test Ring 685", "category": "Test", "platform": "Console"}, "-944465167": {"name": "Test Ring 686", "category": "Test", "platform": "Console"}, "-944429230": {"name": "Test Ring 687", "category": "Test", "platform": "Console"}, "-944393293": {"name": "Test Ring 688", "category": "Test", "platform": "Console"}, "-944357356": {"name": "Test Ring 689", "category": "Test", "platform": "Console"}, "-943494868": {"name": "Test Ring 690", "category": "Test", "platform": "Console"}, "-943458931": {"name": "Test Ring 691", "category": "Test", "platform": "Console"}, "-943422994": {"name": "Test Ring 692", "category": "Test", "platform": "Console"}, "-943387057": {"name": "Test Ring 693", "category": "Test", "platform": "Console"}, "-943351120": {"name": "Test Ring 694", "category": "Test", "platform": "Console"}, "-943315183": {"name": "Test Ring 695", "category": "Test", "platform": "Console"}, "-943279246": {"name": "Test Ring 696", "category": "Test", "platform": "Console"}, "-943243309": {"name": "Test Ring 697", "category": "Test", "platform": "Console"}, "-943207372": {"name": "Test Ring 698", "category": "Test", "platform": "Console"}, "-943171435": {"name": "Test Ring 699", "category": "Test", "platform": "Console"}, "-915032764": {"name": "Test Ring 700", "category": "Test", "platform": "Console"}, "-914996827": {"name": "Test Ring 701", "category": "Test", "platform": "Console"}, "-914960890": {"name": "Test Ring 702", "category": "Test", "platform": "Console"}, "-914924953": {"name": "Test Ring 703", "category": "Test", "platform": "Console"}, "-914889016": {"name": "Test Ring 704", "category": "Test", "platform": "Console"}, "-914853079": {"name": "Test Ring 705", "category": "Test", "platform": "Console"}, "-914817142": {"name": "Test Ring 706", "category": "Test", "platform": "Console"}, "-914781205": {"name": "Test Ring 707", "category": "Test", "platform": "Console"}, "-914745268": {"name": "Test Ring 708", "category": "Test", "platform": "Console"}, "-914709331": {"name": "Test Ring 709", "category": "Test", "platform": "Console"}, "-913846843": {"name": "Test Ring 710", "category": "Test", "platform": "Console"}, "-913810906": {"name": "Test Ring 711", "category": "Test", "platform": "Console"}, "-913774969": {"name": "Test Ring 712", "category": "Test", "platform": "Console"}, "-913739032": {"name": "Test Ring 713", "category": "Test", "platform": "Console"}, "-913703095": {"name": "Test Ring 714", "category": "Test", "platform": "Console"}, "-913667158": {"name": "Test Ring 715", "category": "Test", "platform": "Console"}, "-913631221": {"name": "Test Ring 716", "category": "Test", "platform": "Console"}, "-913595284": {"name": "Test Ring 717", "category": "Test", "platform": "Console"}, "-913559347": {"name": "Test Ring 718", "category": "Test", "platform": "Console"}, "-913523410": {"name": "Test Ring 719", "category": "Test", "platform": "Console"}, "-912660922": {"name": "Test Ring 720", "category": "Test", "platform": "Console"}, "-912624985": {"name": "Test Ring 721", "category": "Test", "platform": "Console"}, "-912589048": {"name": "Test Ring 722", "category": "Test", "platform": "Console"}, "-912553111": {"name": "Test Ring 723", "category": "Test", "platform": "Console"}, "-912517174": {"name": "Test Ring 724", "category": "Test", "platform": "Console"}, "-912481237": {"name": "Test Ring 725", "category": "Test", "platform": "Console"}, "-912445300": {"name": "Test Ring 726", "category": "Test", "platform": "Console"}, "-912409363": {"name": "Test Ring 727", "category": "Test", "platform": "Console"}, "-912373426": {"name": "Test Ring 728", "category": "Test", "platform": "Console"}, "-912337489": {"name": "Test Ring 729", "category": "Test", "platform": "Console"}, "-911475001": {"name": "Test Ring 730", "category": "Test", "platform": "Console"}, "-911439064": {"name": "Test Ring 731", "category": "Test", "platform": "Console"}, "-911403127": {"name": "Test Ring 732", "category": "Test", "platform": "Console"}, "-911367190": {"name": "Test Ring 733", "category": "Test", "platform": "Console"}, "-911331253": {"name": "Test Ring 734", "category": "Test", "platform": "Console"}, "-911295316": {"name": "Test Ring 735", "category": "Test", "platform": "Console"}, "-911259379": {"name": "Test Ring 736", "category": "Test", "platform": "Console"}, "-911223442": {"name": "Test Ring 737", "category": "Test", "platform": "Console"}, "-911187505": {"name": "Test Ring 738", "category": "Test", "platform": "Console"}, "-911151568": {"name": "Test Ring 739", "category": "Test", "platform": "Console"}, "-910289080": {"name": "Test Ring 740", "category": "Test", "platform": "Console"}, "-910253143": {"name": "Test Ring 741", "category": "Test", "platform": "Console"}, "-910217206": {"name": "Test Ring 742", "category": "Test", "platform": "Console"}, "-910181269": {"name": "Test Ring 743", "category": "Test", "platform": "Console"}, "-910145332": {"name": "Test Ring 744", "category": "Test", "platform": "Console"}, "-910109395": {"name": "Test Ring 745", "category": "Test", "platform": "Console"}, "-910073458": {"name": "Test Ring 746", "category": "Test", "platform": "Console"}, "-910037521": {"name": "Test Ring 747", "category": "Test", "platform": "Console"}, "-910001584": {"name": "Test Ring 748", "category": "Test", "platform": "Console"}, "-909965647": {"name": "Test Ring 749", "category": "Test", "platform": "Console"}, "-909103159": {"name": "Test Ring 750", "category": "Test", "platform": "Console"}, "-909067222": {"name": "Test Ring 751", "category": "Test", "platform": "Console"}, "-909031285": {"name": "Test Ring 752", "category": "Test", "platform": "Console"}, "-908995348": {"name": "Test Ring 753", "category": "Test", "platform": "Console"}, "-908959411": {"name": "Test Ring 754", "category": "Test", "platform": "Console"}, "-908923474": {"name": "Test Ring 755", "category": "Test", "platform": "Console"}, "-908887537": {"name": "Test Ring 756", "category": "Test", "platform": "Console"}, "-908851600": {"name": "Test Ring 757", "category": "Test", "platform": "Console"}, "-908815663": {"name": "Test Ring 758", "category": "Test", "platform": "Console"}, "-908779726": {"name": "Test Ring 759", "category": "Test", "platform": "Console"}, "-907917238": {"name": "Test Ring 760", "category": "Test", "platform": "Console"}, "-907881301": {"name": "Test Ring 761", "category": "Test", "platform": "Console"}, "-907845364": {"name": "Test Ring 762", "category": "Test", "platform": "Console"}, "-907809427": {"name": "Test Ring 763", "category": "Test", "platform": "Console"}, "-907773490": {"name": "Test Ring 764", "category": "Test", "platform": "Console"}, "-907737553": {"name": "Test Ring 765", "category": "Test", "platform": "Console"}, "-907701616": {"name": "Test Ring 766", "category": "Test", "platform": "Console"}, "-907665679": {"name": "Test Ring 767", "category": "Test", "platform": "Console"}, "-907629742": {"name": "Test Ring 768", "category": "Test", "platform": "Console"}, "-907593805": {"name": "Test Ring 769", "category": "Test", "platform": "Console"}, "-906731317": {"name": "Test Ring 770", "category": "Test", "platform": "Console"}, "-906695380": {"name": "Test Ring 771", "category": "Test", "platform": "Console"}, "-906659443": {"name": "Test Ring 772", "category": "Test", "platform": "Console"}, "-906623506": {"name": "Test Ring 773", "category": "Test", "platform": "Console"}, "-906587569": {"name": "Test Ring 774", "category": "Test", "platform": "Console"}, "-906551632": {"name": "Test Ring 775", "category": "Test", "platform": "Console"}, "-906515695": {"name": "Test Ring 776", "category": "Test", "platform": "Console"}, "-906479758": {"name": "Test Ring 777", "category": "Test", "platform": "Console"}, "-906443821": {"name": "Test Ring 778", "category": "Test", "platform": "Console"}, "-906407884": {"name": "Test Ring 779", "category": "Test", "platform": "Console"}, "-905545396": {"name": "Test Ring 780", "category": "Test", "platform": "Console"}, "-905509459": {"name": "Test Ring 781", "category": "Test", "platform": "Console"}, "-905473522": {"name": "Test Ring 782", "category": "Test", "platform": "Console"}, "-905437585": {"name": "Test Ring 783", "category": "Test", "platform": "Console"}, "-905401648": {"name": "Test Ring 784", "category": "Test", "platform": "Console"}, "-905365711": {"name": "Test Ring 785", "category": "Test", "platform": "Console"}, "-905329774": {"name": "Test Ring 786", "category": "Test", "platform": "Console"}, "-905293837": {"name": "Test Ring 787", "category": "Test", "platform": "Console"}, "-905257900": {"name": "Test Ring 788", "category": "Test", "platform": "Console"}, "-905221963": {"name": "Test Ring 789", "category": "Test", "platform": "Console"}, "-904359475": {"name": "Test Ring 790", "category": "Test", "platform": "Console"}, "-904323538": {"name": "Test Ring 791", "category": "Test", "platform": "Console"}, "-904287601": {"name": "Test Ring 792", "category": "Test", "platform": "Console"}, "-904251664": {"name": "Test Ring 793", "category": "Test", "platform": "Console"}, "-904215727": {"name": "Test Ring 794", "category": "Test", "platform": "Console"}, "-904179790": {"name": "Test Ring 795", "category": "Test", "platform": "Console"}, "-904143853": {"name": "Test Ring 796", "category": "Test", "platform": "Console"}, "-904107916": {"name": "Test Ring 797", "category": "Test", "platform": "Console"}, "-904071979": {"name": "Test Ring 798", "category": "Test", "platform": "Console"}, "-904036042": {"name": "Test Ring 799", "category": "Test", "platform": "Console"}, "-875897371": {"name": "Test Ring 800", "category": "Test", "platform": "Console"}, "-875861434": {"name": "Test Ring 801", "category": "Test", "platform": "Console"}, "-875825497": {"name": "Test Ring 802", "category": "Test", "platform": "Console"}, "-875789560": {"name": "Test Ring 803", "category": "Test", "platform": "Console"}, "-875753623": {"name": "Test Ring 804", "category": "Test", "platform": "Console"}, "-875717686": {"name": "Test Ring 805", "category": "Test", "platform": "Console"}, "-875681749": {"name": "Test Ring 806", "category": "Test", "platform": "Console"}, "-875645812": {"name": "Test Ring 807", "category": "Test", "platform": "Console"}, "-875609875": {"name": "Test Ring 808", "category": "Test", "platform": "Console"}, "-875573938": {"name": "Test Ring 809", "category": "Test", "platform": "Console"}, "-874711450": {"name": "Test Ring 810", "category": "Test", "platform": "Console"}, "-874675513": {"name": "Test Ring 811", "category": "Test", "platform": "Console"}, "-874639576": {"name": "Test Ring 812", "category": "Test", "platform": "Console"}, "-874603639": {"name": "Test Ring 813", "category": "Test", "platform": "Console"}, "-874567702": {"name": "Test Ring 814", "category": "Test", "platform": "Console"}, "-874531765": {"name": "Test Ring 815", "category": "Test", "platform": "Console"}, "-874495828": {"name": "Test Ring 816", "category": "Test", "platform": "Console"}, "-874459891": {"name": "Test Ring 817", "category": "Test", "platform": "Console"}, "-874423954": {"name": "Test Ring 818", "category": "Test", "platform": "Console"}, "-874388017": {"name": "Test Ring 819", "category": "Test", "platform": "Console"}, "-873525529": {"name": "Test Ring 820", "category": "Test", "platform": "Console"}, "-873489592": {"name": "Test Ring 821", "category": "Test", "platform": "Console"}, "-873453655": {"name": "Test Ring 822", "category": "Test", "platform": "Console"}, "-873417718": {"name": "Test Ring 823", "category": "Test", "platform": "Console"}, "-873381781": {"name": "Test Ring 824", "category": "Test", "platform": "Console"}, "-873345844": {"name": "Test Ring 825", "category": "Test", "platform": "Console"}, "-873309907": {"name": "Test Ring 826", "category": "Test", "platform": "Console"}, "-873273970": {"name": "Test Ring 827", "category": "Test", "platform": "Console"}, "-873238033": {"name": "Test Ring 828", "category": "Test", "platform": "Console"}, "-873202096": {"name": "Test Ring 829", "category": "Test", "platform": "Console"}, "-872339608": {"name": "Test Ring 830", "category": "Test", "platform": "Console"}, "-872303671": {"name": "Test Ring 831", "category": "Test", "platform": "Console"}, "-872267734": {"name": "Test Ring 832", "category": "Test", "platform": "Console"}, "-872231797": {"name": "Test Ring 833", "category": "Test", "platform": "Console"}, "-872195860": {"name": "Test Ring 834", "category": "Test", "platform": "Console"}, "-872159923": {"name": "Test Ring 835", "category": "Test", "platform": "Console"}, "-872123986": {"name": "Test Ring 836", "category": "Test", "platform": "Console"}, "-872088049": {"name": "Test Ring 837", "category": "Test", "platform": "Console"}, "-872052112": {"name": "Test Ring 838", "category": "Test", "platform": "Console"}, "-872016175": {"name": "Test Ring 839", "category": "Test", "platform": "Console"}, "-871153687": {"name": "Test Ring 840", "category": "Test", "platform": "Console"}, "-871117750": {"name": "Test Ring 841", "category": "Test", "platform": "Console"}, "-871081813": {"name": "Test Ring 842", "category": "Test", "platform": "Console"}, "-871045876": {"name": "Test Ring 843", "category": "Test", "platform": "Console"}, "-871009939": {"name": "Test Ring 844", "category": "Test", "platform": "Console"}, "-870974002": {"name": "Test Ring 845", "category": "Test", "platform": "Console"}, "-870938065": {"name": "Test Ring 846", "category": "Test", "platform": "Console"}, "-870902128": {"name": "Test Ring 847", "category": "Test", "platform": "Console"}, "-870866191": {"name": "Test Ring 848", "category": "Test", "platform": "Console"}, "-870830254": {"name": "Test Ring 849", "category": "Test", "platform": "Console"}, "-869967766": {"name": "Test Ring 850", "category": "Test", "platform": "Console"}, "-869931829": {"name": "Test Ring 851", "category": "Test", "platform": "Console"}, "-869895892": {"name": "Test Ring 852", "category": "Test", "platform": "Console"}, "-869859955": {"name": "Test Ring 853", "category": "Test", "platform": "Console"}, "-869824018": {"name": "Test Ring 854", "category": "Test", "platform": "Console"}, "-869788081": {"name": "Test Ring 855", "category": "Test", "platform": "Console"}, "-869752144": {"name": "Test Ring 856", "category": "Test", "platform": "Console"}, "-869716207": {"name": "Test Ring 857", "category": "Test", "platform": "Console"}, "-869680270": {"name": "Test Ring 858", "category": "Test", "platform": "Console"}, "-869644333": {"name": "Test Ring 859", "category": "Test", "platform": "Console"}, "-868781845": {"name": "Test Ring 860", "category": "Test", "platform": "Console"}, "-868745908": {"name": "Test Ring 861", "category": "Test", "platform": "Console"}, "-868709971": {"name": "Test Ring 862", "category": "Test", "platform": "Console"}, "-868674034": {"name": "Test Ring 863", "category": "Test", "platform": "Console"}, "-868638097": {"name": "Test Ring 864", "category": "Test", "platform": "Console"}, "-868602160": {"name": "Test Ring 865", "category": "Test", "platform": "Console"}, "-868566223": {"name": "Test Ring 866", "category": "Test", "platform": "Console"}, "-868530286": {"name": "Test Ring 867", "category": "Test", "platform": "Console"}, "-868494349": {"name": "Test Ring 868", "category": "Test", "platform": "Console"}, "-868458412": {"name": "Test Ring 869", "category": "Test", "platform": "Console"}, "-867595924": {"name": "Test Ring 870", "category": "Test", "platform": "Console"}, "-867559987": {"name": "Test Ring 871", "category": "Test", "platform": "Console"}, "-867524050": {"name": "Test Ring 872", "category": "Test", "platform": "Console"}, "-867488113": {"name": "Test Ring 873", "category": "Test", "platform": "Console"}, "-867452176": {"name": "Test Ring 874", "category": "Test", "platform": "Console"}, "-867416239": {"name": "Test Ring 875", "category": "Test", "platform": "Console"}, "-867380302": {"name": "Test Ring 876", "category": "Test", "platform": "Console"}, "-867344365": {"name": "Test Ring 877", "category": "Test", "platform": "Console"}, "-867308428": {"name": "Test Ring 878", "category": "Test", "platform": "Console"}, "-867272491": {"name": "Test Ring 879", "category": "Test", "platform": "Console"}, "-866410003": {"name": "Test Ring 880", "category": "Test", "platform": "Console"}, "-866374066": {"name": "Test Ring 881", "category": "Test", "platform": "Console"}, "-866338129": {"name": "Test Ring 882", "category": "Test", "platform": "Console"}, "-866302192": {"name": "Test Ring 883", "category": "Test", "platform": "Console"}, "-866266255": {"name": "Test Ring 884", "category": "Test", "platform": "Console"}, "-866230318": {"name": "Test Ring 885", "category": "Test", "platform": "Console"}, "-866194381": {"name": "Test Ring 886", "category": "Test", "platform": "Console"}, "-866158444": {"name": "Test Ring 887", "category": "Test", "platform": "Console"}, "-866122507": {"name": "Test Ring 888", "category": "Test", "platform": "Console"}, "-866086570": {"name": "Test Ring 889", "category": "Test", "platform": "Console"}, "-865224082": {"name": "Test Ring 890", "category": "Test", "platform": "Console"}, "-865188145": {"name": "Test Ring 891", "category": "Test", "platform": "Console"}, "-865152208": {"name": "Test Ring 892", "category": "Test", "platform": "Console"}, "-865116271": {"name": "Test Ring 893", "category": "Test", "platform": "Console"}, "-865080334": {"name": "Test Ring 894", "category": "Test", "platform": "Console"}, "-865044397": {"name": "Test Ring 895", "category": "Test", "platform": "Console"}, "-865008460": {"name": "Test Ring 896", "category": "Test", "platform": "Console"}, "-864972523": {"name": "Test Ring 897", "category": "Test", "platform": "Console"}, "-864936586": {"name": "Test Ring 898", "category": "Test", "platform": "Console"}, "-864900649": {"name": "Test Ring 899", "category": "Test", "platform": "Console"}, "-836761978": {"name": "Test Ring 900", "category": "Test", "platform": "Console"}, "-836726041": {"name": "Test Ring 901", "category": "Test", "platform": "Console"}, "-836690104": {"name": "Test Ring 902", "category": "Test", "platform": "Console"}, "-836654167": {"name": "Test Ring 903", "category": "Test", "platform": "Console"}, "-836618230": {"name": "Test Ring 904", "category": "Test", "platform": "Console"}, "-836582293": {"name": "Test Ring 905", "category": "Test", "platform": "Console"}, "-836546356": {"name": "Test Ring 906", "category": "Test", "platform": "Console"}, "-836510419": {"name": "Test Ring 907", "category": "Test", "platform": "Console"}, "-836474482": {"name": "Test Ring 908", "category": "Test", "platform": "Console"}, "-836438545": {"name": "Test Ring 909", "category": "Test", "platform": "Console"}, "-835576057": {"name": "Test Ring 910", "category": "Test", "platform": "Console"}, "-835540120": {"name": "Test Ring 911", "category": "Test", "platform": "Console"}, "-835504183": {"name": "Test Ring 912", "category": "Test", "platform": "Console"}, "-835468246": {"name": "Test Ring 913", "category": "Test", "platform": "Console"}, "-835432309": {"name": "Test Ring 914", "category": "Test", "platform": "Console"}, "-835396372": {"name": "Test Ring 915", "category": "Test", "platform": "Console"}, "-835360435": {"name": "Test Ring 916", "category": "Test", "platform": "Console"}, "-835324498": {"name": "Test Ring 917", "category": "Test", "platform": "Console"}, "-835288561": {"name": "Test Ring 918", "category": "Test", "platform": "Console"}, "-835252624": {"name": "Test Ring 919", "category": "Test", "platform": "Console"}, "-834390136": {"name": "Test Ring 920", "category": "Test", "platform": "Console"}, "-834354199": {"name": "Test Ring 921", "category": "Test", "platform": "Console"}, "-834318262": {"name": "Test Ring 922", "category": "Test", "platform": "Console"}, "-834282325": {"name": "Test Ring 923", "category": "Test", "platform": "Console"}, "-834246388": {"name": "Test Ring 924", "category": "Test", "platform": "Console"}, "-834210451": {"name": "Test Ring 925", "category": "Test", "platform": "Console"}, "-834174514": {"name": "Test Ring 926", "category": "Test", "platform": "Console"}, "-834138577": {"name": "Test Ring 927", "category": "Test", "platform": "Console"}, "-834102640": {"name": "Test Ring 928", "category": "Test", "platform": "Console"}, "-834066703": {"name": "Test Ring 929", "category": "Test", "platform": "Console"}, "-833204215": {"name": "Test Ring 930", "category": "Test", "platform": "Console"}, "-833168278": {"name": "Test Ring 931", "category": "Test", "platform": "Console"}, "-833132341": {"name": "Test Ring 932", "category": "Test", "platform": "Console"}, "-833096404": {"name": "Test Ring 933", "category": "Test", "platform": "Console"}, "-833060467": {"name": "Test Ring 934", "category": "Test", "platform": "Console"}, "-833024530": {"name": "Test Ring 935", "category": "Test", "platform": "Console"}, "-832988593": {"name": "Test Ring 936", "category": "Test", "platform": "Console"}, "-832952656": {"name": "Test Ring 937", "category": "Test", "platform": "Console"}, "-832916719": {"name": "Test Ring 938", "category": "Test", "platform": "Console"}, "-832880782": {"name": "Test Ring 939", "category": "Test", "platform": "Console"}, "-832018294": {"name": "Test Ring 940", "category": "Test", "platform": "Console"}, "-831982357": {"name": "Test Ring 941", "category": "Test", "platform": "Console"}, "-831946420": {"name": "Test Ring 942", "category": "Test", "platform": "Console"}, "-831910483": {"name": "Test Ring 943", "category": "Test", "platform": "Console"}, "-831874546": {"name": "Test Ring 944", "category": "Test", "platform": "Console"}, "-831838609": {"name": "Test Ring 945", "category": "Test", "platform": "Console"}, "-831802672": {"name": "Test Ring 946", "category": "Test", "platform": "Console"}, "-831766735": {"name": "Test Ring 947", "category": "Test", "platform": "Console"}, "-831730798": {"name": "Test Ring 948", "category": "Test", "platform": "Console"}, "-831694861": {"name": "Test Ring 949", "category": "Test", "platform": "Console"}, "-830832373": {"name": "Test Ring 950", "category": "Test", "platform": "Console"}, "-830796436": {"name": "Test Ring 951", "category": "Test", "platform": "Console"}, "-830760499": {"name": "Test Ring 952", "category": "Test", "platform": "Console"}, "-830724562": {"name": "Test Ring 953", "category": "Test", "platform": "Console"}, "-830688625": {"name": "Test Ring 954", "category": "Test", "platform": "Console"}, "-830652688": {"name": "Test Ring 955", "category": "Test", "platform": "Console"}, "-830616751": {"name": "Test Ring 956", "category": "Test", "platform": "Console"}, "-830580814": {"name": "Test Ring 957", "category": "Test", "platform": "Console"}, "-830544877": {"name": "Test Ring 958", "category": "Test", "platform": "Console"}, "-830508940": {"name": "Test Ring 959", "category": "Test", "platform": "Console"}, "-829646452": {"name": "Test Ring 960", "category": "Test", "platform": "Console"}, "-829610515": {"name": "Test Ring 961", "category": "Test", "platform": "Console"}, "-829574578": {"name": "Test Ring 962", "category": "Test", "platform": "Console"}, "-829538641": {"name": "Test Ring 963", "category": "Test", "platform": "Console"}, "-829502704": {"name": "Test Ring 964", "category": "Test", "platform": "Console"}, "-829466767": {"name": "Test Ring 965", "category": "Test", "platform": "Console"}, "-829430830": {"name": "Test Ring 966", "category": "Test", "platform": "Console"}, "-829394893": {"name": "Test Ring 967", "category": "Test", "platform": "Console"}, "-829358956": {"name": "Test Ring 968", "category": "Test", "platform": "Console"}, "-829323019": {"name": "Test Ring 969", "category": "Test", "platform": "Console"}, "-828460531": {"name": "Test Ring 970", "category": "Test", "platform": "Console"}, "-828424594": {"name": "Test Ring 971", "category": "Test", "platform": "Console"}, "-828388657": {"name": "Test Ring 972", "category": "Test", "platform": "Console"}, "-828352720": {"name": "Test Ring 973", "category": "Test", "platform": "Console"}, "-828316783": {"name": "Test Ring 974", "category": "Test", "platform": "Console"}, "-828280846": {"name": "Test Ring 975", "category": "Test", "platform": "Console"}, "-828244909": {"name": "Test Ring 976", "category": "Test", "platform": "Console"}, "-828208972": {"name": "Test Ring 977", "category": "Test", "platform": "Console"}, "-828173035": {"name": "Test Ring 978", "category": "Test", "platform": "Console"}, "-828137098": {"name": "Test Ring 979", "category": "Test", "platform": "Console"}, "-827274610": {"name": "Test Ring 980", "category": "Test", "platform": "Console"}, "-827238673": {"name": "Test Ring 981", "category": "Test", "platform": "Console"}, "-827202736": {"name": "Test Ring 982", "category": "Test", "platform": "Console"}, "-827166799": {"name": "Test Ring 983", "category": "Test", "platform": "Console"}, "-827130862": {"name": "Test Ring 984", "category": "Test", "platform": "Console"}, "-827094925": {"name": "Test Ring 985", "category": "Test", "platform": "Console"}, "-827058988": {"name": "Test Ring 986", "category": "Test", "platform": "Console"}, "-827023051": {"name": "Test Ring 987", "category": "Test", "platform": "Console"}, "-826987114": {"name": "Test Ring 988", "category": "Test", "platform": "Console"}, "-826951177": {"name": "Test Ring 989", "category": "Test", "platform": "Console"}, "-826088689": {"name": "Test Ring 990", "category": "Test", "platform": "Console"}, "-826052752": {"name": "Test Ring 991", "category": "Test", "platform": "Console"}, "-826016815": {"name": "Test Ring 992", "category": "Test", "platform": "Console"}, "-825980878": {"name": "Test Ring 993", "category": "Test", "platform": "Console"}, "-825944941": {"name": "Test Ring 994", "category": "Test", "platform": "Console"}, "-825909004": {"name": "Test Ring 995", "category": "Test", "platform": "Console"}, "-825873067": {"name": "Test Ring 996", "category": "Test", "platform": "Console"}, "-825837130": {"name": "Test Ring 997", "category": "Test", "platform": "Console"}, "-825801193": {"name": "Test Ring 998", "category": "Test", "platform": "Console"}, "-825765256": {"name": "Test Ring 999", "category": "Test", "platform": "Console"}}, "Voodoo Masks": {"620034067": {"name": "02: Shaman Mask (AR 36-41)", "category": "Voodoo Masks", "platform": "Console"}, "620034068": {"name": "03: Chieftain Mask (AR 60-69)", "category": "Voodoo Masks", "platform": "Console"}, "620034069": {"name": "04: Spirit Mask (AR 84-113)", "category": "Voodoo Masks", "platform": "Console"}, "620035155": {"name": "05: Woodwraith Bark (AR 114-149)", "category": "Voodoo Masks", "platform": "Console"}, "620035156": {"name": "06: Burial Mask (AR 150-185)", "category": "Voodoo Masks", "platform": "Console"}, "620035157": {"name": "07: Naga Mask (AR 186-232)", "category": "Voodoo Masks", "platform": "Console"}, "620035158": {"name": "08: Umbra Mask (AR 232-254)", "category": "Voodoo Masks", "platform": "Console"}, "620036244": {"name": "09: Screaming Mask (AR 255-322)", "category": "Voodoo Masks", "platform": "Console"}, "620036245": {"name": "10: Underworld Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036246": {"name": "11: Manitou Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036247": {"name": "12: Deva (AR 360-472)", "category": "Voodoo Masks", "platform": "Console"}, "620036248": {"name": "13: Tribal Mask (AR 472-659)", "category": "Voodoo Masks", "platform": "Console"}, "620036249": {"name": "14: Ascended Mask (AR 660-759)", "category": "Voodoo Masks", "platform": "Console"}, "-1716736265": {"name": "Art Test VoodooMask 1", "category": "Voodoo Masks", "platform": "Console"}, "-1716736264": {"name": "Art Test VoodooMask 2", "category": "Voodoo Masks", "platform": "Console"}, "-1716736263": {"name": "Art Test VoodooMask 3", "category": "Voodoo Masks", "platform": "Console"}, "-1716736262": {"name": "Art Test VoodooMask 4", "category": "Voodoo Masks", "platform": "Console"}, "-1716736261": {"name": "Art Test VoodooMask 5", "category": "Voodoo Masks", "platform": "Console"}, "-801205711": {"name": "Legendary: Carnevil", "category": "Voodoo Masks", "platform": "Console"}, "-801169774": {"name": "Legendary: Mask of Jeram", "category": "Voodoo Masks", "platform": "Console"}, "-840197356": {"name": "Legendary: Quetzalcoatl", "category": "Voodoo Masks", "platform": "Console"}, "-1956786272": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1956783828": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555852": {"name": "Legendary: Quetzalcoatl (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840161419": {"name": "Legendary: Split Tusk", "category": "Voodoo Masks", "platform": "Console"}, "-1955600351": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1955597907": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555853": {"name": "Legendary: Split Tusk (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840305167": {"name": "Legendary: The Grin Reaper", "category": "Voodoo Masks", "platform": "Console"}, "-1960344035": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1960341591": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555849": {"name": "Legendary: The Grin Reaper (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840341104": {"name": "Legendary: Tiklandian Visage", "category": "Voodoo Masks", "platform": "Console"}, "-1961529956": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1961527512": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555848": {"name": "Legendary: Tiklandian Visage (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840089545": {"name": "Legendary: Visage of Giyua", "category": "Voodoo Masks", "platform": "Console"}, "-1953228509": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1953226065": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555855": {"name": "Legendary: Visage of Giyua (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555854": {"name": "Set: Zunimassa's Attunement (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840125482": {"name": "Set: Zunimassa's Vision", "category": "Voodoo Masks", "platform": "Console"}, "-1954414430": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1954411986": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}}, "Wands": {"88665050": {"name": "01: Lesser Wand (DPS 9.8-11.2)", "category": "Wands", "platform": "Console"}, "88665051": {"name": "02: Oak Wand (DPS 11.2-13.3)", "category": "Wands", "platform": "Console"}, "88665052": {"name": "03: Wand (DPS 14.7-16.8)", "category": "Wands", "platform": "Console"}, "88665053": {"name": "04: Steel Wand (DPS 17.5-19.6)", "category": "Wands", "platform": "Console"}, "88665054": {"name": "05: Mentor Wand (DPS 21.7-23.8)", "category": "Wands", "platform": "Console"}, "88665055": {"name": "06: Enchanter Wand (DPS 25.2-27.3)", "category": "Wands", "platform": "Console"}, "88665056": {"name": "07: Grim Wand (DPS 29.4-31.5)", "category": "Wands", "platform": "Console"}, "88666139": {"name": "08: Petrified Wand (DPS 41.3-43.4)", "category": "Wands", "platform": "Console"}, "88666140": {"name": "09: Duelist Wand (DPS 47.6-49.7)", "category": "Wands", "platform": "Console"}, "88666141": {"name": "10: Jade Wand (DPS 55.3-57.4)", "category": "Wands", "platform": "Console"}, "88666142": {"name": "11: Battle Wand (DPS 65.1-67.2)", "category": "Wands", "platform": "Console"}, "88666143": {"name": "12: Divination Wand (DPS 75.6-77.7)", "category": "Wands", "platform": "Console"}, "88666144": {"name": "13: Sorcery Wand (DPS 89.6-93.8)", "category": "Wands", "platform": "Console"}, "88666145": {"name": "14: Silversteel Wand (DPS 105.0-109.2)", "category": "Wands", "platform": "Console"}, "88667228": {"name": "15: Greater Wand (DPS 115.5-119.7)", "category": "Wands", "platform": "Console"}, "88667229": {"name": "16: Guardian (DPS 127.4-131.6)", "category": "Wands", "platform": "Console"}, "88667230": {"name": "17: Magus Wand (DPS 139.3-145.6)", "category": "Wands", "platform": "Console"}, "88667231": {"name": "18: Spellbinder (DPS 153.3-159.6)", "category": "Wands", "platform": "Console"}, "88667232": {"name": "19: Archmage Wand (DPS 177.1-183.4)", "category": "Wands", "platform": "Console"}, "88667233": {"name": "20: Strike Wand (DPS 203.0-211.4)", "category": "Wands", "platform": "Console"}, "88667234": {"name": "21: Desolator Wand (DPS 235.2-243.6)", "category": "Wands", "platform": "Console"}, "88668317": {"name": "22: Demon's Head Wand (DPS 315.0-321.3)", "category": "Wands", "platform": "Console"}, "88668318": {"name": "23: Diabolic Wand (DPS 385.0-391.3)", "category": "Wands", "platform": "Console"}, "2004783359": {"name": "Art Test Wand 1", "category": "Wands", "platform": "Console"}, "2004783360": {"name": "Art Test Wand 2", "category": "Wands", "platform": "Console"}, "2004783361": {"name": "Art Test Wand 3", "category": "Wands", "platform": "Console"}, "2004783362": {"name": "Art Test Wand 4", "category": "Wands", "platform": "Console"}, "2004783363": {"name": "Art Test Wand 5", "category": "Wands", "platform": "Console"}, "456527018": {"name": "Crafted: Elderwood Wand", "category": "Wands", "platform": "Console"}, "-1415147493": {"name": "Legendary: Aether Walker (Patch 2.1.0)", "category": "Wands", "platform": "Console"}, "1859914464": {"name": "Legendary: Atrophy", "category": "Wands", "platform": "Console"}, "1859806653": {"name": "Legendary: Blackhand Key", "category": "Wands", "platform": "Console"}, "1244000105": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "1244002549": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "161873429": {"name": "Legendary: Blackhand Key (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860776952": {"name": "Legendary: Fragment of Destiny", "category": "Wands", "platform": "Console"}, "1276019972": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "1276022416": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "161873456": {"name": "Legendary: Fragment of Destiny (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859662905": {"name": "Legendary: Gesture of Orpheus", "category": "Wands", "platform": "Console"}, "1239256421": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "1239258865": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "161873425": {"name": "Legendary: Gesture of Orpheus (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1247557868": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "1247560312": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "161873432": {"name": "Legendary: Ruinstoke (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898798298": {"name": "Legendary: Serpent's Sparker", "category": "Wands", "platform": "Console"}, "1860884763": {"name": "Legendary: Slorak's Madness", "category": "Wands", "platform": "Console"}, "1279577735": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "1279580179": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "161873459": {"name": "Legendary: Slorak's Madness (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859698842": {"name": "Legendary: Starfire", "category": "Wands", "platform": "Console"}, "1240442342": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "1240444786": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "161873426": {"name": "Legendary: Starfire (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898762361": {"name": "Legendary: Wand of Woh", "category": "Wands", "platform": "Console"}, "-1415147492": {"name": "P1 Wand norm Legendary 02", "category": "Wands", "platform": "Console"}, "161873458": {"name": "Set: Chantodo's Sacred Protector (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860848826": {"name": "Set: Chantodo's Will", "category": "Wands", "platform": "Console"}, "1278391814": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1278394258": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1861064448": {"name": "Set: Hallowed Baton", "category": "Wands", "platform": "Console"}, "161873464": {"name": "Set: Hallowed Rod (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1285507340": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1285509784": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1771839282": {"name": "legendary: Gesture Of Orpheus (Patch 2.2.0)", "category": "Wands", "platform": "Console"}}, "Wizard Hats": {"1755621631": {"name": "02: Journey Mask (AR 36-41)", "category": "Wizard Hats", "platform": "Console"}, "1755621632": {"name": "03: Scholarly Fez (AR 60-69)", "category": "Wizard Hats", "platform": "Console"}, "1755621633": {"name": "04: Charlatan Cap (AR 84-113)", "category": "Wizard Hats", "platform": "Console"}, "1755622719": {"name": "05: Conjurer Shade (AR 114-149)", "category": "Wizard Hats", "platform": "Console"}, "1755622720": {"name": "06: Mystic Shade (AR 150-185)", "category": "Wizard Hats", "platform": "Console"}, "1755622721": {"name": "07: Mentor Cap (AR 186-232)", "category": "Wizard Hats", "platform": "Console"}, "1755622722": {"name": "08: Traveler Hat (AR 232-254)", "category": "Wizard Hats", "platform": "Console"}, "1755623808": {"name": "09: Sage Hat (AR 255-284)", "category": "Wizard Hats", "platform": "Console"}, "1755623809": {"name": "10: Sinister Mask (AR 285-322)", "category": "Wizard Hats", "platform": "Console"}, "1755623810": {"name": "11: Archmage Headpiece (AR 322-359)", "category": "Wizard Hats", "platform": "Console"}, "1755623811": {"name": "12: Elder Hat (AR 360-472)", "category": "Wizard Hats", "platform": "Console"}, "1755623812": {"name": "13: Vizier Hat (AR 472-659)", "category": "Wizard Hats", "platform": "Console"}, "1755623813": {"name": "14: Ascended Headpiece (AR 660-759)", "category": "Wizard Hats", "platform": "Console"}, "376117315": {"name": "Art Test WizardHat 1", "category": "Wizard Hats", "platform": "Console"}, "376117316": {"name": "Art Test WizardHat 2", "category": "Wizard Hats", "platform": "Console"}, "376117317": {"name": "Art Test WizardHat 3", "category": "Wizard Hats", "platform": "Console"}, "376117318": {"name": "Art Test WizardHat 4", "category": "Wizard Hats", "platform": "Console"}, "376117319": {"name": "Art Test WizardHat 5", "category": "Wizard Hats", "platform": "Console"}, "414491869": {"name": "Legendary: Archmage's Vicalyke", "category": "Wizard Hats", "platform": "Console"}, "375356476": {"name": "Legendary: Dark Mage's Shade", "category": "Wizard Hats", "platform": "Console"}, "-498215480": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-498213036": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827188": {"name": "Legendary: Dark Mage's Shade (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414599680": {"name": "Legendary: Mask of Lies", "category": "Wizard Hats", "platform": "Console"}, "375464287": {"name": "Legendary: Storm Crow", "category": "Wizard Hats", "platform": "Console"}, "-494657717": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-494655273": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827191": {"name": "Legendary: Storm Crow (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414563743": {"name": "Legendary: The Magistrate", "category": "Wizard Hats", "platform": "Console"}, "375428350": {"name": "Legendary: The Swami", "category": "Wizard Hats", "platform": "Console"}, "-495843638": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-495841194": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827190": {"name": "Legendary: The Swami (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-936099818": {"name": "Legendary: The Swami (Patch 2.1.0)", "category": "Wizard Hats", "platform": "Console"}, "414527806": {"name": "Legendary: Velvet Camaral", "category": "Wizard Hats", "platform": "Console"}}} \ No newline at end of file diff --git a/assets/itemquality.json b/assets/itemquality.json new file mode 100644 index 0000000..111846a --- /dev/null +++ b/assets/itemquality.json @@ -0,0 +1,15 @@ +{ + "Invalid": "-1", + "Inferior": "0", + "Normal": "1", + "Superior": "2", + "Magic1": "3", + "Magic2": "4", + "Magic3": "5", + "Rare4": "6", + "Rare5": "7", + "Rare6": "8", + "Legendary": "9", + "Special": "10", + "Set": "1" +} \ No newline at end of file diff --git a/gui/__init__.py b/gui/__init__.py index b11308d..0632e85 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -68,6 +68,7 @@ def loadaccount(self, file): ttk.Button(self.tabs.hero_tab, text="Save Hero", command=self.savehero).grid(column=0, row=99) s = ttk.Button(self.tabs.account_tab, text="Save all changes", command=self.savechanges) s.grid(column=1, row=99) + self.tabs.configure_stash_frame() def savechanges(self): for currency in self.account.asd.partitions[0].currency_data.currency: diff --git a/gui/tabs.py b/gui/tabs.py index da5d418..2fc57ea 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -2,7 +2,6 @@ from tkinter import ttk from save_manager import item_handler from settings import currency_list -from settings import gbid_list class Notebook(ttk.Notebook): @@ -31,7 +30,6 @@ def __init__(self, parent, account): self.item_list_frame = None self.item_frame = None self.configure_account_tab() - self.configure_stash_frame() self.populate_sc_data() self.populate_hc_data() @@ -101,21 +99,23 @@ def configure_stash_frame(self, event=None): self.active_stash_frame.destroy() self.active_stash_frame = ttk.Frame(self.stash_tab, style="TNotebook", borderwidth=0) self.active_stash_frame.grid(column=0, row=0) - c = ttk.Combobox(self.active_stash_frame, textvariable=self.active_stash, values=['SC', 'HC'], state='readonly') + stashvalues = ['SC', 'HC'] + self.heroes + c = ttk.Combobox(self.active_stash_frame, textvariable=self.active_stash, values=stashvalues, state='readonly') c.grid(column=0, row=0, sticky='NW', columnspan=2) c.bind("<>", self.configure_stash_frame) if self.active_stash.get() == 'SC': try: - self.stash_data = self.account.asd.partitions[0].items.ListFields()[0][1] + self.stash_data = self.account.asd.partitions[0].items.items except IndexError: self.stash_data = None elif self.active_stash.get() == 'HC': try: - self.stash_data = self.account.asd.partitions[1].items.ListFields()[0][1] + self.stash_data = self.account.asd.partitions[1].items.items except IndexError: self.stash_data = None else: - assert "incorrect stash selected, stash has to be either SC or HC." + hero_id = self.active_stash.get().split(' - ')[1] + self.stash_data = self.account.heroes[hero_id].items.items if self.stash_data: self.load_item_list_frame(self.stash_data, self.active_stash_frame) @@ -125,6 +125,7 @@ def load_item_list_frame(self, itemlist, parent): self.item_list_frame = ttk.Frame(parent, style="TNotebook", borderwidth=0) self.item_list_frame.grid(column=0, row=1, sticky='NESW') ttk.Label(self.item_list_frame, text="Item List:").grid(column=0, row=1, sticky='W') + parent.columnconfigure(1, weight=1) self.decodeditems = item_handler.decode_itemlist(itemlist) scrollbar = ScrollbarItems(self.decodeditems, parent=self.item_list_frame) scrollbar.grid(column=0, row=2) diff --git a/settings.json b/settings.json index c5278d6..1e6bc45 100644 --- a/settings.json +++ b/settings.json @@ -7,6 +7,7 @@ "GBIDS_FILE": "gbids.json", "SLOTS_FILE": "slots.json", "AFFIXES_FILE": "affixes.json", - "CURRENCY_FILE": "currencies.json" + "CURRENCY_FILE": "currencies.json", + "GBID_CAT_FILE": "gbids_categorised.json" } } \ No newline at end of file diff --git a/settings.py b/settings.py index 9edde05..d884d70 100644 --- a/settings.py +++ b/settings.py @@ -9,6 +9,7 @@ ASSET_DIR = settings['directories']['ASSET_DIR'] HERO_DIR = settings['directories']['HERO_DIR'] GBIDS_FILE = settings['files']['GBIDS_FILE'] +GBID_CAT_FILE = settings['files']['GBID_CAT_FILE'] AFFIXES_FILE = settings['files']['AFFIXES_FILE'] CURRENCY_FILE = settings['files']['CURRENCY_FILE'] SLOTS_FILE = settings['files']['SLOTS_FILE'] @@ -17,6 +18,9 @@ assert isfile(join(ASSET_DIR, GBIDS_FILE)), "%s doesn't exist" % GBIDS_FILE assert isfile(join(ASSET_DIR, AFFIXES_FILE)), "%s doesn't exist" % AFFIXES_FILE assert isfile(join(ASSET_DIR, CURRENCY_FILE)), "%s doesn't exist" % CURRENCY_FILE +assert isfile(join(ASSET_DIR, SLOTS_FILE)), "%s doesn't exist" % SLOTS_FILE +assert isfile(join(ASSET_DIR, GBID_CAT_FILE)), "%s doesn't exist" % GBID_CAT_FILE + # load assets with open(join(ASSET_DIR, GBIDS_FILE), "r") as f: gbid_list = load(f) @@ -25,4 +29,6 @@ with open(join(ASSET_DIR, SLOTS_FILE), "r") as f: SLOT_LIST = load(f) with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: - currency_list = load(f) \ No newline at end of file + currency_list = load(f) +with open(join(ASSET_DIR, GBID_CAT_FILE, "r")) as f: + gbid_cat = load(f) From 2faaa826e95d1ffe18f7e808977c9fb2ace7c694 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Fri, 23 Nov 2018 14:38:05 +0000 Subject: [PATCH 029/115] Hero item decoding (for now on stash tab) --- gui/tabs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/tabs.py b/gui/tabs.py index 2fc57ea..5c75398 100644 --- a/gui/tabs.py +++ b/gui/tabs.py @@ -13,7 +13,7 @@ def __init__(self, parent, account): self.stash_tab = ttk.Frame(self.tabs, style="TNotebook", borderwidth=0) self.tabs.add(self.account_tab, text="Account") self.tabs.add(self.hero_tab, text="Heroes") - self.tabs.add(self.stash_tab, text="Stash") + self.tabs.add(self.stash_tab, text="Stash and Inventories") self.tabs.pack(expan=1, fill="both") # dictionary holding textvariables for Entry fields self.scvalues = {} From bd93984d50b063dcec8d7a599ebda258a34eccee Mon Sep 17 00:00:00 2001 From: unixtreme Date: Fri, 23 Nov 2018 15:23:15 +0000 Subject: [PATCH 030/115] fix to silly missing parenthesis. --- assets/{gbids_categorised.json => gbidscategorised.json} | 0 settings.json | 2 +- settings.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename assets/{gbids_categorised.json => gbidscategorised.json} (100%) diff --git a/assets/gbids_categorised.json b/assets/gbidscategorised.json similarity index 100% rename from assets/gbids_categorised.json rename to assets/gbidscategorised.json diff --git a/settings.json b/settings.json index 1e6bc45..ac91699 100644 --- a/settings.json +++ b/settings.json @@ -8,6 +8,6 @@ "SLOTS_FILE": "slots.json", "AFFIXES_FILE": "affixes.json", "CURRENCY_FILE": "currencies.json", - "GBID_CAT_FILE": "gbids_categorised.json" + "GBID_CAT_FILE": "gbidscategorised.json" } } \ No newline at end of file diff --git a/settings.py b/settings.py index d884d70..f1c3dbc 100644 --- a/settings.py +++ b/settings.py @@ -30,5 +30,5 @@ SLOT_LIST = load(f) with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: currency_list = load(f) -with open(join(ASSET_DIR, GBID_CAT_FILE, "r")) as f: +with open(join(ASSET_DIR, GBID_CAT_FILE), "r") as f: gbid_cat = load(f) From dd841c012291e6bcc42f23fa2a77e356d5693a91 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 26 Nov 2018 10:01:59 +0000 Subject: [PATCH 031/115] Adds GR keystone to gbids --- assets/gbids.json | 2 +- assets/gbidscategorised.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/gbids.json b/assets/gbids.json index 9561199..2b284f9 100644 --- a/assets/gbids.json +++ b/assets/gbids.json @@ -1 +1 @@ -{"0": {"name": "None", "category": "None", "platform": "Console"}, "1682228617": {"name": "01: Amulet", "category": "Amulets", "platform": "Console"}, "1682228618": {"name": "02: Amulet", "category": "Amulets", "platform": "Console"}, "1682228619": {"name": "03: Amulet", "category": "Amulets", "platform": "Console"}, "1682228620": {"name": "04: Amulet", "category": "Amulets", "platform": "Console"}, "1682228621": {"name": "05: Amulet", "category": "Amulets", "platform": "Console"}, "1682228622": {"name": "06: Amulet", "category": "Amulets", "platform": "Console"}, "1682228623": {"name": "07: Amulet", "category": "Amulets", "platform": "Console"}, "1682228624": {"name": "08: Amulet", "category": "Amulets", "platform": "Console"}, "1682228625": {"name": "09: Amulet", "category": "Amulets", "platform": "Console"}, "1682228649": {"name": "10: Amulet", "category": "Amulets", "platform": "Console"}, "1682228650": {"name": "11: Amulet", "category": "Amulets", "platform": "Console"}, "1682228651": {"name": "12: Amulet", "category": "Amulets", "platform": "Console"}, "1682228652": {"name": "13: Amulet", "category": "Amulets", "platform": "Console"}, "1682228653": {"name": "14: Amulet", "category": "Amulets", "platform": "Console"}, "1682228654": {"name": "15: Amulet", "category": "Amulets", "platform": "Console"}, "1682228655": {"name": "16: Amulet", "category": "Amulets", "platform": "Console"}, "1682228656": {"name": "17: Amulet", "category": "Amulets", "platform": "Console"}, "-1335710051": {"name": "Art Test Amulet 1", "category": "Amulets", "platform": "Console"}, "-1335710050": {"name": "Art Test Amulet 2", "category": "Amulets", "platform": "Console"}, "-1335710049": {"name": "Art Test Amulet 3", "category": "Amulets", "platform": "Console"}, "-1335710048": {"name": "Art Test Amulet 4", "category": "Amulets", "platform": "Console"}, "-1335710047": {"name": "Art Test Amulet 5", "category": "Amulets", "platform": "Console"}, "1566332280": {"name": "Legendary: Ancestors' Grace", "category": "Amulets", "platform": "Console"}, "1566368217": {"name": "Legendary: Countess Julia's Cameo", "category": "Amulets", "platform": "Console"}, "1566511965": {"name": "Legendary: Dovu Energy Trap", "category": "Amulets", "platform": "Console"}, "1200923753": {"name": "Legendary: Drake's Amulet (PS3 Promo)", "category": "Amulets", "platform": "Console"}, "1528454682": {"name": "Legendary: Eye of Etlich", "category": "Amulets", "platform": "Console"}, "-1100680346": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "-1100677902": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "412126098": {"name": "Legendary: Eye of Etlich (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566440091": {"name": "Legendary: Golden Gorget of Leoric", "category": "Amulets", "platform": "Console"}, "1566583839": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "737941201": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "1566296343": {"name": "Legendary: Haunt of Vaxo", "category": "Amulets", "platform": "Console"}, "761548935": {"name": "Legendary: Hellfire Amulet (Patch 1.2.0)", "category": "Amulets", "platform": "Console"}, "1528418745": {"name": "Legendary: Holy Beacon", "category": "Amulets", "platform": "Console"}, "-1101866267": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "-1101863823": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "412126097": {"name": "Legendary: Holy Beacon (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196887": {"name": "Legendary: Kymbo's Gold", "category": "Amulets", "platform": "Console"}, "-1142187581": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "-1142185137": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "412126063": {"name": "Legendary: Kymbo's Gold (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196623": {"name": "Legendary: Kymbo's Gold (Patch 2.1.0)", "category": "Amulets", "platform": "Console"}, "1528490619": {"name": "Legendary: Mara's Kaleidoscope", "category": "Amulets", "platform": "Console"}, "-1099494425": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "-1099491981": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "412126099": {"name": "Legendary: Mara's Kaleidoscope (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527232824": {"name": "Legendary: Moonlight Ward", "category": "Amulets", "platform": "Console"}, "-1141001660": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "-1140999216": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "412126064": {"name": "Legendary: Moonlight Ward (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527304698": {"name": "Legendary: Ouroboros", "category": "Amulets", "platform": "Console"}, "-1138629818": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "-1138627374": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "412126066": {"name": "Legendary: Ouroboros (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566476028": {"name": "Legendary: Overwhelming Desire", "category": "Amulets", "platform": "Console"}, "1566547902": {"name": "Legendary: Rakoff's Glass of Life", "category": "Amulets", "platform": "Console"}, "1527448446": {"name": "Legendary: Rondal's Locket", "category": "Amulets", "platform": "Console"}, "-1133886134": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1133883690": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126070": {"name": "Legendary: Rondal's Locket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528310934": {"name": "Legendary: Squirt's Necklace", "category": "Amulets", "platform": "Console"}, "-1105424030": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "-1105421586": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "412126094": {"name": "Legendary: Squirt's Necklace (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528382808": {"name": "Legendary: Talisman of Aranoch", "category": "Amulets", "platform": "Console"}, "-1103052188": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "-1103049744": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "412126096": {"name": "Legendary: Talisman of Aranoch (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566404154": {"name": "Legendary: The Ess of Johan", "category": "Amulets", "platform": "Console"}, "1527160950": {"name": "Legendary: The Flavor of Time", "category": "Amulets", "platform": "Console"}, "-1143373502": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "-1143371058": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "412126062": {"name": "Legendary: The Flavor of Time (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528346871": {"name": "Legendary: The Murlocket", "category": "Amulets", "platform": "Console"}, "-1104238109": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1104235665": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126095": {"name": "Legendary: The Murlocket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527340635": {"name": "Legendary: The Star of Azkaranth", "category": "Amulets", "platform": "Console"}, "-1137443897": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "-1137441453": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "412126067": {"name": "Legendary: The Star of Azkaranth (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527268761": {"name": "Legendary: Xephirian Amulet", "category": "Amulets", "platform": "Console"}, "-1139815739": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "-1139813295": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "412126065": {"name": "Legendary: Xephirian Amulet (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "714520304": {"name": "PvP: Art of War 3v3", "category": "Amulets", "platform": "Console"}, "1685772266": {"name": "PvP: Art of War All", "category": "Amulets", "platform": "Console"}, "1685772538": {"name": "PvP: Art of War Attack", "category": "Amulets", "platform": "Console"}, "1685775296": {"name": "PvP: Art of War Defense", "category": "Amulets", "platform": "Console"}, "-203544613": {"name": "PvP: Art of War Precision", "category": "Amulets", "platform": "Console"}, "1685795044": {"name": "PvP: Art of War Vitality", "category": "Amulets", "platform": "Console"}, "-203302615": {"name": "PvP: Art of War Willpower", "category": "Amulets", "platform": "Console"}, "1803178445": {"name": "PvP: Born for War All", "category": "Amulets", "platform": "Console"}, "1803178717": {"name": "PvP: Born for War Attack", "category": "Amulets", "platform": "Console"}, "1803181475": {"name": "PvP: Born for War Defense", "category": "Amulets", "platform": "Console"}, "-624108002": {"name": "PvP: Born for War Precision", "category": "Amulets", "platform": "Console"}, "1803201223": {"name": "PvP: Born for War Vitality", "category": "Amulets", "platform": "Console"}, "1528526556": {"name": "Set: Blackthorne's Duncraig Cross", "category": "Amulets", "platform": "Console"}, "-1098308504": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "-1098306060": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "412126100": {"name": "Set: Blackthorne's Medal (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "412126069": {"name": "Set: Spirit of Adventure (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "-1544505070": {"name": "Set: Sunwuko's Shines", "category": "Amulets", "platform": "Console"}, "412126068": {"name": "Set: Tal Rasha's Adjudication (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527376572": {"name": "Set: Tal Rasha's Allegiance", "category": "Amulets", "platform": "Console"}, "-1136257976": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "-1136255532": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "1527412509": {"name": "Set: The Traveler's Pledge", "category": "Amulets", "platform": "Console"}, "-1135072055": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-1135069611": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-795161790": {"name": "legendary: Moonlight Ward (Patch 2.2.0)", "category": "Amulets", "platform": "Console"}, "1661412389": {"name": "00: Weathered Hand Axe (DPS 3.0)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412390": {"name": "01: Hand Axe (DPS 3.3-4.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412391": {"name": "02: Broad Axe (DPS 7.2-9.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412392": {"name": "03: Double Axe (DPS 12.4-14.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412393": {"name": "04: Heavy Axe (DPS 17.6-19.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412394": {"name": "05: Battle Axe (DPS 21.5-23.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412395": {"name": "06: Marauder Axe (DPS 26.7-28.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412396": {"name": "07: Soldier Axe (DPS 31.2-33.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413479": {"name": "08: Hatchet (DPS 36.4-38.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413480": {"name": "09: Ono (DPS 46.2-48.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413481": {"name": "10: Bullova (DPS 57.2-59.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413482": {"name": "11: Adze (DPS 69.6-73.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413483": {"name": "12: Chopper (DPS 86.5-90.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413484": {"name": "13: Toporok (DPS 101.4-105.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413485": {"name": "14: Masakari (DPS 118.3-122.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414568": {"name": "15: Tomahawk (DPS 129.4-135.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414569": {"name": "16: Crescent Axe (DPS 144.3-150.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414570": {"name": "17: Arreat Axe (DPS 160.6-166.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414571": {"name": "18: Balestarius (DPS 177.5-185.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414572": {"name": "19: Skartaran Axe (DPS 206.7-214.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414573": {"name": "20: Galraki (DPS 238.6-246.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414574": {"name": "21: Arch Axe (DPS 275.6-285.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415657": {"name": "22: Executioner's Axe (DPS 371.8-379.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415658": {"name": "23: Dire Axe (DPS 461.5-469.3)", "category": "Axes, One-Handed", "platform": "Console"}, "-657929333": {"name": "Art Test Axe One-Handed 1", "category": "Axes, One-Handed", "platform": "Console"}, "-657929332": {"name": "Art Test Axe One-Handed 2", "category": "Axes, One-Handed", "platform": "Console"}, "-657929331": {"name": "Art Test Axe One-Handed 3", "category": "Axes, One-Handed", "platform": "Console"}, "-657929330": {"name": "Art Test Axe One-Handed 4", "category": "Axes, One-Handed", "platform": "Console"}, "-657929329": {"name": "Art Test Axe One-Handed 5", "category": "Axes, One-Handed", "platform": "Console"}, "824126149": {"name": "Legendary: Aidan's Revenge", "category": "Axes, One-Handed", "platform": "Console"}, "824162086": {"name": "Legendary: Fenris Tooth", "category": "Axes, One-Handed", "platform": "Console"}, "784990756": {"name": "Legendary: Flesh Tearer", "category": "Axes, One-Handed", "platform": "Console"}, "134813872": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "134816316": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046948": {"name": "Legendary: Flesh Tearer (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785062630": {"name": "Legendary: Genzaniku", "category": "Axes, One-Handed", "platform": "Console"}, "137185714": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "137188158": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046946": {"name": "Legendary: Genzaniku (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "824198023": {"name": "Legendary: Hack", "category": "Axes, One-Handed", "platform": "Console"}, "785134504": {"name": "Legendary: Sky Splitter", "category": "Axes, One-Handed", "platform": "Console"}, "139557556": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "139560000": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046944": {"name": "Legendary: Sky Splitter (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785206378": {"name": "Legendary: The Burning Axe of Sankis", "category": "Axes, One-Handed", "platform": "Console"}, "141929398": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "141931842": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046942": {"name": "Legendary: The Burning Axe of Sankis (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785170441": {"name": "Legendary: The Butcher's Sickle", "category": "Axes, One-Handed", "platform": "Console"}, "140743477": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "140745921": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046943": {"name": "Legendary: The Butcher's Sickle (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138371635": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138374079": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046945": {"name": "Legendary: The Wedge (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785098567": {"name": "Legendary: Utar's Roar", "category": "Axes, One-Handed", "platform": "Console"}, "786248551": {"name": "Set: Hallowed Breach", "category": "Axes, One-Handed", "platform": "Console"}, "-219046913": {"name": "Set: Hallowed Divide (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176321107": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176323551": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785134241": {"name": "legendary: Sky Spliiter (Patch 2.2.0)", "category": "Axes, One-Handed", "platform": "Console"}, "1700547783": {"name": "01: Lumber Axe (DPS 10.0-11.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547784": {"name": "02: War Axe (DPS 16.0-17.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547785": {"name": "03: Tabarzin (DPS 22.5-24.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547786": {"name": "04: Military Axe (DPS 31.5-33.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547787": {"name": "05: Great Axe (DPS 42.5-44.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548872": {"name": "06: Timber Axe (DPS 56.5-59.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548873": {"name": "07: Francisca (DPS 73.5-76.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548874": {"name": "08: Fang Axe (DPS 94.0-98.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548875": {"name": "09: Parashu (DPS 119.0-125.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548876": {"name": "10: Labrys (DPS 170.0-177.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549961": {"name": "11: Fell Axe (DPS 230.5-241.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549962": {"name": "12: Valaska (DPS 313.0-325.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549963": {"name": "13: Ripper Axe (DPS 400.0-412.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549964": {"name": "14: Sagaris (DPS 474.5-486.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549965": {"name": "15: Decapitator (DPS 560.0-572.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551050": {"name": "16: Dread Axe (DPS 698.0-711.2)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551051": {"name": "17: Flesh Render (DPS 948.2-961.4)", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893396": {"name": "Art Test Axe Two-Handed 1", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893395": {"name": "Art Test Axe Two-Handed 2", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893394": {"name": "Art Test Axe Two-Handed 3", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893393": {"name": "Art Test Axe Two-Handed 4", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893392": {"name": "Art Test Axe Two-Handed 5", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516456824": {"name": "Legendary: Burst of Wrath", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555664091": {"name": "Legendary: Butcher's Carver", "category": "Axes, Two-Handed", "platform": "Console"}, "202615249": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "202617693": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911555": {"name": "Legendary: Butcher's Carver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554514107": {"name": "Legendary: Cinder Switch", "category": "Axes, Two-Handed", "platform": "Console"}, "240564721": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "240567165": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911523": {"name": "Legendary: Fire Brand (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554478170": {"name": "Legendary: Messerschmidt's Reaver", "category": "Axes, Two-Handed", "platform": "Console"}, "241750642": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "241753086": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911522": {"name": "Legendary: Messerschmidt's Reaver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516420887": {"name": "Legendary: Saint of Slaughter", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555376595": {"name": "Legendary: Skorn", "category": "Axes, Two-Handed", "platform": "Console"}, "212102617": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "212105061": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911547": {"name": "Legendary: Skorn (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516492761": {"name": "Legendary: Sungjae's Fury", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555592217": {"name": "Legendary: The Executioner", "category": "Axes, Two-Handed", "platform": "Console"}, "204987091": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "204989535": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911553": {"name": "Legendary: The Executioner (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516528698": {"name": "Legendary: The Marauder", "category": "Axes, Two-Handed", "platform": "Console"}, "120887006": {"name": "PvP: Heroic Reaper", "category": "Axes, Two-Handed", "platform": "Console"}, "120887005": {"name": "PvP: Mighty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "120887004": {"name": "PvP: Trusty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "-733831369": {"name": "01: Sash (AR 6-7)", "category": "Belts", "platform": "Console"}, "-733831368": {"name": "02: Hide Belt (AR 24-28)", "category": "Belts", "platform": "Console"}, "-733831367": {"name": "03: Leather Belt (AR 14-16)", "category": "Belts", "platform": "Console"}, "-733831366": {"name": "04: Cord (AR 44-53)", "category": "Belts", "platform": "Console"}, "-733831365": {"name": "05: Binding Rope (AR 54-67)", "category": "Belts", "platform": "Console"}, "-733831364": {"name": "06: Chain Belt (AR 34-43)", "category": "Belts", "platform": "Console"}, "-733830280": {"name": "07: Silk Sash (AR 68-87)", "category": "Belts", "platform": "Console"}, "-733830279": {"name": "08: Waistwrap (AR 88-107)", "category": "Belts", "platform": "Console"}, "-733830278": {"name": "09: Strand (AR 108-127)", "category": "Belts", "platform": "Console"}, "-733830277": {"name": "10: Cupola (AR 128-149)", "category": "Belts", "platform": "Console"}, "-733830276": {"name": "11: Cinch (AR 150-164)", "category": "Belts", "platform": "Console"}, "-733829191": {"name": "12: Grasp (AR 165-179)", "category": "Belts", "platform": "Console"}, "-733829190": {"name": "13: Sheath (AR 180-189)", "category": "Belts", "platform": "Console"}, "-733829189": {"name": "14: Cincture (AR 190-214)", "category": "Belts", "platform": "Console"}, "-733829188": {"name": "15: Girdle (AR 215-239)", "category": "Belts", "platform": "Console"}, "-733829187": {"name": "16: Heaven Strand (AR 240-264)", "category": "Belts", "platform": "Console"}, "-733829186": {"name": "17: High Scabbard (AR 265-314)", "category": "Belts", "platform": "Console"}, "-733829185": {"name": "18: War Belt (AR 315-439)", "category": "Belts", "platform": "Console"}, "-733829184": {"name": "19: Archon Sash (AR 440-506)", "category": "Belts", "platform": "Console"}, "1187629340": {"name": "Art Test Belt 1", "category": "Belts", "platform": "Console"}, "1187629341": {"name": "Art Test Belt 2", "category": "Belts", "platform": "Console"}, "1187629342": {"name": "Art Test Belt 3", "category": "Belts", "platform": "Console"}, "1187629343": {"name": "Art Test Belt 4", "category": "Belts", "platform": "Console"}, "1187629344": {"name": "Art Test Belt 5", "category": "Belts", "platform": "Console"}, "949342869": {"name": "Belt Of The Trove (Patch 2.1.2)", "category": "Belts", "platform": "Console"}, "1770820311": {"name": "Legendary: Angel Hair Braid", "category": "Belts", "platform": "Console"}, "-1692549181": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-1692546737": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-660622993": {"name": "Legendary: Angel Hair Braid (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770820047": {"name": "Legendary: Angel Hair Braid (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1809991641": {"name": "Legendary: Cord of the Sherma", "category": "Belts", "platform": "Console"}, "1770856248": {"name": "Legendary: Fleeting Strap", "category": "Belts", "platform": "Console"}, "1771898421": {"name": "Legendary: Goldwrap", "category": "Belts", "platform": "Console"}, "-1656971551": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1656969107": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622963": {"name": "Legendary: Goldwrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810027578": {"name": "Legendary: Harrington Waistguard", "category": "Belts", "platform": "Console"}, "1770892185": {"name": "Legendary: Hellcat Waistguard", "category": "Belts", "platform": "Console"}, "-1690177339": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-1690174895": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-660622991": {"name": "Legendary: Hellcat Waistguard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810099452": {"name": "Legendary: Hwoj Wrap", "category": "Belts", "platform": "Console"}, "1809955704": {"name": "Legendary: Insatiable Belt", "category": "Belts", "platform": "Console"}, "1810063515": {"name": "Legendary: Jang's Envelopment", "category": "Belts", "platform": "Console"}, "-1691363260": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1691360816": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622992": {"name": "Legendary: Quick Draw Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809883830": {"name": "Legendary: Razor Strop", "category": "Belts", "platform": "Console"}, "1770748437": {"name": "Legendary: Saffron Wrap", "category": "Belts", "platform": "Console"}, "-1694921023": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1694918579": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622995": {"name": "Legendary: Saffron Wrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809919767": {"name": "Legendary: Sash of Knives", "category": "Belts", "platform": "Console"}, "1809919503": {"name": "Legendary: Sash of Knives (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1810135389": {"name": "Legendary: Sebor's Nightmare", "category": "Belts", "platform": "Console"}, "1770999996": {"name": "Legendary: String of Ears", "category": "Belts", "platform": "Console"}, "-1686619576": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-1686617132": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-660622988": {"name": "Legendary: String of Ears (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1771035933": {"name": "Legendary: The Witching Hour", "category": "Belts", "platform": "Console"}, "-1685433655": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-1685431211": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-660622987": {"name": "Legendary: The Witching Hour (Old-Legacy)", "category": "Belts", "platform": "Console"}, "924103246": {"name": "Legendary: Thundergod's Vigor", "category": "Belts", "platform": "Console"}, "1770784374": {"name": "Legendary: Vigilante Belt", "category": "Belts", "platform": "Console"}, "-1693735102": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1693732658": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622994": {"name": "Legendary: Vigilante Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1772078106": {"name": "Set: Blackthorne's Notched Belt", "category": "Belts", "platform": "Console"}, "-1651041946": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1651039502": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622958": {"name": "Set: Blackthorne's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-660622961": {"name": "Set: Captain Crimson's Brace (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1654599709": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "-1654597265": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "1771970295": {"name": "Set: Captain Crimson's Silk Girdle", "category": "Belts", "platform": "Console"}, "-660622959": {"name": "Set: Demon's Binding (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1652227867": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "-1652225423": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "1772042169": {"name": "Set: Demon's Restraint", "category": "Belts", "platform": "Console"}, "1772006232": {"name": "Set: Guardian's Case", "category": "Belts", "platform": "Console"}, "-660622960": {"name": "Set: Guardian's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1653413788": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-1653411344": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-660622989": {"name": "Set: Inna's Blessing (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770964059": {"name": "Set: Inna's Favor", "category": "Belts", "platform": "Console"}, "-1687805497": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-1687803053": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-885483983": {"name": "Set: Krelm's Buff Belt", "category": "Belts", "platform": "Console"}, "1770928122": {"name": "Set: Tal Rasha's Brace", "category": "Belts", "platform": "Console"}, "-1688991418": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-1688988974": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-660622990": {"name": "Set: Tal Rasha's Finespun Cloth (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1069972162": {"name": "legendary: Belessed of Haull (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972159": {"name": "legendary: Belt of Transcendence (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972158": {"name": "legendary: Crashing Rain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972160": {"name": "legendary: Haunting Girdle (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972161": {"name": "legendary: Omnislash (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972163": {"name": "legendary: Omryn's Chain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809919504": {"name": "legendary: Sash of Knives (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1810135126": {"name": "legendary: Sebor's Nightmare (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809991378": {"name": "legendary: Sherma of Corrosion (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "2140880151": {"name": "01: Shoes (AR 7-8)", "category": "Boots", "platform": "Console"}, "2140880152": {"name": "02: Boots (AR 16-18)", "category": "Boots", "platform": "Console"}, "2140880153": {"name": "03: Heavy Boots (AR 30-35)", "category": "Boots", "platform": "Console"}, "2140880154": {"name": "04: Chain Boots (AR 44-57)", "category": "Boots", "platform": "Console"}, "2140880155": {"name": "05: Sabatons (AR 58-66)", "category": "Boots", "platform": "Console"}, "2140880156": {"name": "06: Greaves (AR 67-82)", "category": "Boots", "platform": "Console"}, "2140881240": {"name": "07: Silk Shoes (AR 54-106)", "category": "Boots", "platform": "Console"}, "2140881241": {"name": "08: Brogans (AR 107-129)", "category": "Boots", "platform": "Console"}, "2140881242": {"name": "09: Treads (AR 130-152)", "category": "Boots", "platform": "Console"}, "2140881243": {"name": "10: Heavy Sabatons (AR 154-174)", "category": "Boots", "platform": "Console"}, "2140881244": {"name": "11: Battle Greaves (AR 175-192)", "category": "Boots", "platform": "Console"}, "2140882329": {"name": "12: Balor Treads (AR 192-209)", "category": "Boots", "platform": "Console"}, "2140882330": {"name": "13: Astral Greaves (AR 210-221)", "category": "Boots", "platform": "Console"}, "2140882331": {"name": "14: Warlord Boots (AR 221-249)", "category": "Boots", "platform": "Console"}, "2140882332": {"name": "15: Doom Treads (AR 250-278)", "category": "Boots", "platform": "Console"}, "2140882333": {"name": "16: Sovereign Greaves (AR 280-308)", "category": "Boots", "platform": "Console"}, "2140882334": {"name": "17: Archon Greaves (AR 309-366)", "category": "Boots", "platform": "Console"}, "2140882335": {"name": "18: Rakkisgard Greaves (AR 367-512)", "category": "Boots", "platform": "Console"}, "2140882336": {"name": "19: Ascended Greaves (AR 513-590)", "category": "Boots", "platform": "Console"}, "931997596": {"name": "Art Test Boots 1", "category": "Boots", "platform": "Console"}, "931997597": {"name": "Art Test Boots 2", "category": "Boots", "platform": "Console"}, "931997598": {"name": "Art Test Boots 3", "category": "Boots", "platform": "Console"}, "931997599": {"name": "Art Test Boots 4", "category": "Boots", "platform": "Console"}, "931997600": {"name": "Art Test Boots 5", "category": "Boots", "platform": "Console"}, "691149644": {"name": "Art_Test_Boots_10 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997601": {"name": "Art_Test_Boots_6 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997602": {"name": "Art_Test_Boots_7 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997603": {"name": "Art_Test_Boots_8 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997604": {"name": "Art_Test_Boots_9 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940245561": {"name": "Legendary: Board Walkers", "category": "Boots", "platform": "Console"}, "1940101813": {"name": "Legendary: Boj Anglers", "category": "Boots", "platform": "Console"}, "-401226911": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "-401224467": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "261789197": {"name": "Legendary: Boj Anglers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979273143": {"name": "Legendary: Boots of Disregard", "category": "Boots", "platform": "Console"}, "1290781938": {"name": "Legendary: Conqueror's Sabatons (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1940317435": {"name": "Legendary: Fire Walkers", "category": "Boots", "platform": "Console"}, "-394111385": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "-394108941": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "261789203": {"name": "Legendary: Fire Walkers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-639326280": {"name": "Legendary: Footfalls of the Forbidden Lands", "category": "Boots", "platform": "Console"}, "1940353372": {"name": "Legendary: Ice Climbers", "category": "Boots", "platform": "Console"}, "-392925464": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "-392923020": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "261789204": {"name": "Legendary: Ice Climbers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979309080": {"name": "Legendary: Illusory Boots", "category": "Boots", "platform": "Console"}, "1979345017": {"name": "Legendary: Irontoe Mudsputters", "category": "Boots", "platform": "Console"}, "-396483227": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "-396480783": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "261789201": {"name": "Legendary: Lost Boys (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1940389309": {"name": "Legendary: Lut Socks", "category": "Boots", "platform": "Console"}, "-391739543": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "-391737099": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "261789205": {"name": "Legendary: Lut Socks (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941251797": {"name": "Legendary: The Crudest Boots", "category": "Boots", "platform": "Console"}, "-363277439": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "-363274995": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "261789229": {"name": "Legendary: The Crudest Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-2143372979": {"name": "Legendary: The Crudest Boots (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1941395545": {"name": "Set: Asheara's Finders", "category": "Boots", "platform": "Console"}, "261789233": {"name": "Set: Asheara's Lock (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-358533755": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "-358531311": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "261789238": {"name": "Set: Blackthorne's Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941575230": {"name": "Set: Blackthorne's Spurs", "category": "Boots", "platform": "Console"}, "-352604150": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-352601706": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-357347834": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "-357345390": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "261789234": {"name": "Set: Cain's Slippers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941431482": {"name": "Set: Cain's Travelers", "category": "Boots", "platform": "Console"}, "261789236": {"name": "Set: Captain Crimson's Deck Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941503356": {"name": "Set: Captain Crimson's Waders", "category": "Boots", "platform": "Console"}, "-354975992": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-354973548": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-801833428": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801653481": {"name": "Set: Eight-Demon Boots", "category": "Boots", "platform": "Console"}, "-801725355": {"name": "Set: Firebird's Tarsi", "category": "Boots", "platform": "Console"}, "-801833429": {"name": "Set: Hell Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800539434": {"name": "Set: Helltooth Greaves", "category": "Boots", "platform": "Console"}, "261789231": {"name": "Set: Immortal King's Pillar (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941323671": {"name": "Set: Immortal King's Stride", "category": "Boots", "platform": "Console"}, "-360905597": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "-360903153": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "1097296767": {"name": "Set: Inna's Sandals (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801617544": {"name": "Set: Jade Harvester's Swiftness", "category": "Boots", "platform": "Console"}, "-801689418": {"name": "Set: Marauder's Treads", "category": "Boots", "platform": "Console"}, "-801905302": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1941287734": {"name": "Set: Natalya's Bloody Footprints", "category": "Boots", "platform": "Console"}, "-362091518": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "-362089074": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "261789230": {"name": "Set: Natalya's Soul (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1097296766": {"name": "Set: Nilfur's Boast (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801761292": {"name": "Set: Raekor's Striders", "category": "Boots", "platform": "Console"}, "-801905304": {"name": "Set: Roland's Stride (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "-801905303": {"name": "Set: Sabaton of the Wastes (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800755056": {"name": "Set: Sabatons of Akkhan", "category": "Boots", "platform": "Console"}, "-353790071": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "-353787627": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "1941539293": {"name": "Set: Sage's Passage", "category": "Boots", "platform": "Console"}, "261789237": {"name": "Set: Sage's Seekers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-1957807619": {"name": "Set: Striders of Destiny (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800611308": {"name": "Set: The Shadow's Heels", "category": "Boots", "platform": "Console"}, "-800647245": {"name": "Set: Vyr's Swaggering Stance", "category": "Boots", "platform": "Console"}, "-801869365": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "261789232": {"name": "Set: Zunimassa's Journey (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941359608": {"name": "Set: Zunimassa's Trail", "category": "Boots", "platform": "Console"}, "-359719676": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "-359717232": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "1979344754": {"name": "legendary: Boots_104_p2 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940317172": {"name": "legendary: Fire Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800575371": {"name": "legendary: Seismic Treads", "category": "Boots", "platform": "Console"}, "-700134034": {"name": "legendary: Seismic Treads (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-2091504072": {"name": "01: Short Bow (DPS 6.3-7.7)", "category": "Bows", "platform": "Console"}, "-2091504071": {"name": "02: Warden Bow (DPS 14.7-16.8)", "category": "Bows", "platform": "Console"}, "-2091504070": {"name": "03: Long Bow (DPS 20.3-22.4)", "category": "Bows", "platform": "Console"}, "-2091504069": {"name": "04: Recurve Bow (DPS 27.7-30.8)", "category": "Bows", "platform": "Console"}, "-2091504068": {"name": "05: Hunting Bow (DPS 34.3-36.4)", "category": "Bows", "platform": "Console"}, "-2091504067": {"name": "06: Battle Bow (DPS 41.3-43.4)", "category": "Bows", "platform": "Console"}, "-2091502983": {"name": "07: Siege Bow (DPS 44.1-46.2)", "category": "Bows", "platform": "Console"}, "-2091502982": {"name": "08: Maruki (DPS 55.3-57.4)", "category": "Bows", "platform": "Console"}, "-2091502981": {"name": "09: Yumi (DPS 64.4-66.5)", "category": "Bows", "platform": "Console"}, "-2091502980": {"name": "10: Composite Bow (DPS 749.9-77.0)", "category": "Bows", "platform": "Console"}, "-2091502979": {"name": "11: Daikyu (DPS 91.0-93.1)", "category": "Bows", "platform": "Console"}, "-2091502978": {"name": "12: Hankyu (DPS 107.1-109.2)", "category": "Bows", "platform": "Console"}, "-2091501894": {"name": "13: Higoyumi (DPS 140.7-142.8)", "category": "Bows", "platform": "Console"}, "-2091501893": {"name": "14: Ranger Bow (DPS 172.2-174.3)", "category": "Bows", "platform": "Console"}, "-2091501892": {"name": "15: Longshot Bow (DPS 207.2-211.4)", "category": "Bows", "platform": "Console"}, "-2091501891": {"name": "16: Sniper Bow (DPS 275.1-279.3)", "category": "Bows", "platform": "Console"}, "-2091501890": {"name": "17: Phantom Bow (DPS 322.0-326.2)", "category": "Bows", "platform": "Console"}, "-2091501889": {"name": "18: Revenant Bow (DPS 376.6-380.8)", "category": "Bows", "platform": "Console"}, "-2091500805": {"name": "19: Twinbow (DPS 513.1-517.3)", "category": "Bows", "platform": "Console"}, "-2091500804": {"name": "20: Doubleshot (DPS 670.6-674.8)", "category": "Bows", "platform": "Console"}, "687111997": {"name": "Art Test Bow 1", "category": "Bows", "platform": "Console"}, "687111998": {"name": "Art Test Bow 2", "category": "Bows", "platform": "Console"}, "687111999": {"name": "Art Test Bow 3", "category": "Bows", "platform": "Console"}, "687112000": {"name": "Art Test Bow 4", "category": "Bows", "platform": "Console"}, "687112001": {"name": "Art Test Bow 5", "category": "Bows", "platform": "Console"}, "1999703162": {"name": "Legendary: Amazonian Arch", "category": "Bows", "platform": "Console"}, "1142135055": {"name": "Legendary: Bow of the Lost Warlord (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1961789627": {"name": "Legendary: Cluckeye", "category": "Bows", "platform": "Console"}, "314470951": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "314473395": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "513724883": {"name": "Legendary: Cluckeye (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459958": {"name": "Legendary: Etrayu", "category": "Bows", "platform": "Console"}, "270591874": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "270594318": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "513724846": {"name": "Legendary: Etrayu (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459694": {"name": "Legendary: Etrayu (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1999595351": {"name": "Legendary: Kridershot", "category": "Bows", "platform": "Console"}, "1999667225": {"name": "Legendary: Leonine Bow of Hashir", "category": "Bows", "platform": "Console"}, "277707400": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "277709844": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "513724852": {"name": "Legendary: Longshot (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1999631288": {"name": "Legendary: Odyssey's End", "category": "Bows", "platform": "Console"}, "1961609942": {"name": "Legendary: Sydyru Crust", "category": "Bows", "platform": "Console"}, "1960711517": {"name": "Legendary: The Raven's Wing", "category": "Bows", "platform": "Console"}, "278893321": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "278895765": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "513724853": {"name": "Legendary: The Raven's Wing (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960675580": {"name": "Legendary: Unbound Bolt", "category": "Bows", "platform": "Console"}, "1960603706": {"name": "Legendary: Uskang", "category": "Bows", "platform": "Console"}, "275335558": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "275338002": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "513724850": {"name": "Legendary: Uskang (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960603442": {"name": "Legendary: Uskang (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "308541346": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "308543790": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "513724878": {"name": "Legendary: Venomhusk (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960747454": {"name": "Legendary: Windforce", "category": "Bows", "platform": "Console"}, "280079242": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "280081686": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "513724854": {"name": "Legendary: Windforce (Old-Legacy)", "category": "Bows", "platform": "Console"}, "-875944878": {"name": "01: Bracers (AR 8-9)", "category": "Bracers", "platform": "Console"}, "-875944877": {"name": "02: Leather Cuffs (AR 16-19)", "category": "Bracers", "platform": "Console"}, "-875944876": {"name": "03: Bindings (AR 25-32)", "category": "Bracers", "platform": "Console"}, "-875944875": {"name": "04: Vambraces (AR 33-40)", "category": "Bracers", "platform": "Console"}, "-875944874": {"name": "05: Bracelets (AR 41-48)", "category": "Bracers", "platform": "Console"}, "-875943789": {"name": "067: Wristwraps (AR 63-75)", "category": "Bracers", "platform": "Console"}, "-875944873": {"name": "06: Mail Bands (AR 50-62)", "category": "Bracers", "platform": "Console"}, "-875943788": {"name": "08: Wristbands (AR 76-88)", "category": "Bracers", "platform": "Console"}, "-875943787": {"name": "09: Stabilizers (AR 90-102)", "category": "Bracers", "platform": "Console"}, "-875943786": {"name": "10: Wristguards (AR 103-124)", "category": "Bracers", "platform": "Console"}, "-875943785": {"name": "11: Wristplates (AR 125-137)", "category": "Bracers", "platform": "Console"}, "-875942700": {"name": "12: Armwraps (AR 137-149)", "category": "Bracers", "platform": "Console"}, "-875942699": {"name": "13: Armbands (AR 150-157)", "category": "Bracers", "platform": "Console"}, "-875942698": {"name": "14: Warbands (AR 158-178)", "category": "Bracers", "platform": "Console"}, "-875942697": {"name": "15: Armguards (AR 179-199)", "category": "Bracers", "platform": "Console"}, "-875942696": {"name": "16: Armplates (AR 200-220)", "category": "Bracers", "platform": "Console"}, "-875942695": {"name": "17: Razorspikes (AR 220-261)", "category": "Bracers", "platform": "Console"}, "-875942694": {"name": "18: Rakkisgard Bracelets (AR 262-365)", "category": "Bracers", "platform": "Console"}, "-875942693": {"name": "19: Ascended Bracers (AR 366-421)", "category": "Bracers", "platform": "Console"}, "-297950812": {"name": "Art Test Bracer 1", "category": "Bracers", "platform": "Console"}, "-297950811": {"name": "Art Test Bracer 2", "category": "Bracers", "platform": "Console"}, "-297950810": {"name": "Art Test Bracer 3", "category": "Bracers", "platform": "Console"}, "-297950809": {"name": "Art Test Bracer 4", "category": "Bracers", "platform": "Console"}, "-297950808": {"name": "Art Test Bracer 5", "category": "Bracers", "platform": "Console"}, "1861699995": {"name": "Grundo Gear (Patch 2.1.2)", "category": "Bracers", "platform": "Console"}, "962282719": {"name": "Legendary: Ancient Parthan Defenders", "category": "Bracers", "platform": "Console"}, "962462404": {"name": "Legendary: Custerian Wristguards", "category": "Bracers", "platform": "Console"}, "923291074": {"name": "Legendary: Gungdo Gear", "category": "Bracers", "platform": "Console"}, "403757070": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "403759514": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "955538490": {"name": "Legendary: Gungdo Gear (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923111389": {"name": "Legendary: Kethryes' Splint", "category": "Bracers", "platform": "Console"}, "923255137": {"name": "Legendary: Lacuni Prowlers", "category": "Bracers", "platform": "Console"}, "402571149": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "402573593": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538489": {"name": "Legendary: Lacuni Prowlers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962498341": {"name": "Legendary: Lucky Bowman's Armscales", "category": "Bracers", "platform": "Console"}, "962426467": {"name": "Legendary: Nemesis Bracers", "category": "Bracers", "platform": "Console"}, "923147326": {"name": "Legendary: Promise of Glory", "category": "Bracers", "platform": "Console"}, "399013386": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "399015830": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "955538486": {"name": "Legendary: Promise of Glory (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962318656": {"name": "Legendary: Reaper's Wraps", "category": "Bracers", "platform": "Console"}, "962390530": {"name": "Legendary: Sanguinary Vambraces", "category": "Bracers", "platform": "Console"}, "923183263": {"name": "Legendary: Slave Bonds", "category": "Bracers", "platform": "Console"}, "400199307": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "400201751": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "955538487": {"name": "Legendary: Slave Bonds (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923219200": {"name": "Legendary: Steady Strikers", "category": "Bracers", "platform": "Console"}, "401385228": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "401387672": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538488": {"name": "Legendary: Steady Strikers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923327011": {"name": "Legendary: Strongarm Bracers", "category": "Bracers", "platform": "Console"}, "404942991": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "404945435": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538491": {"name": "Legendary: Strongarm Bracers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962354593": {"name": "Legendary: Trag'Oul Coils", "category": "Bracers", "platform": "Console"}, "962246782": {"name": "Legendary: Warzechian Armguards", "category": "Bracers", "platform": "Console"}, "397827465": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "397829909": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "955538485": {"name": "Legendary: Wondrous Deflectors (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "955538493": {"name": "Set: Aughild's Demands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923398885": {"name": "Set: Aughild's Search", "category": "Bracers", "platform": "Console"}, "407314833": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "407317277": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "924297310": {"name": "Set: Demon's Animus", "category": "Bracers", "platform": "Console"}, "955538518": {"name": "Set: Demon's Manacles (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "436962858": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "436965302": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "924261373": {"name": "Set: Guardian's Aversion", "category": "Bracers", "platform": "Console"}, "955538517": {"name": "Set: Guardian's Bands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "435776937": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "435779381": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "1784952569": {"name": "Set: Krelm's Buff Bracers", "category": "Bracers", "platform": "Console"}, "1786138490": {"name": "Set: Shackles of the Invoker", "category": "Bracers", "platform": "Console"}, "1861701111": {"name": "legendary: Drakon's Lesson (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861699992": {"name": "legendary: Mortick's Brace (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861701087": {"name": "legendary: Spirit Guards (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "-635269584": {"name": "00: Simple Knife (DPS 3.0)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269583": {"name": "01: Stone Knife (DPS 11.2-12.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269582": {"name": "02: Kris Blade (DPS 14.7-16.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269581": {"name": "03: Jagged Edge (DPS 21.0-23.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269580": {"name": "04: Flint Knife (DPS 30.8-32.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268494": {"name": "05: Sacrifice Blade (DPS 39.2-41.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268493": {"name": "06: Flayer (DPS 48.3-50.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268492": {"name": "07: Bone Saw (DPS 62.3-64.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268491": {"name": "08: Beast Tusk (DPS 84.0-86.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267405": {"name": "09: Scalping Razor (DPS 112.7-114.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267404": {"name": "10: Obsidian Edge (DPS 137.2-139.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267403": {"name": "11: Skin Cutter (DPS 165.2-169.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267402": {"name": "12: Exquisite Knife (DPS 190.4-194.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267401": {"name": "13: Flesh Ripper (DPS 219.1-223.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267400": {"name": "14: Veil Piercer (DPS 251.3-257.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266316": {"name": "15: Odsidian Skiver (DPS 336.7-340.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266315": {"name": "16: Tecpat1 (DPS 410.2-414.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-97045282": {"name": "Art Test CeremonialDagger 1", "category": "Ceremonial Knives", "platform": "Console"}, "-97045281": {"name": "Art Test CeremonialDagger 2", "category": "Ceremonial Knives", "platform": "Console"}, "-97045280": {"name": "Art Test CeremonialDagger 3", "category": "Ceremonial Knives", "platform": "Console"}, "-97045279": {"name": "Art Test CeremonialDagger 4", "category": "Ceremonial Knives", "platform": "Console"}, "-97045278": {"name": "Art Test CeremonialDagger 5", "category": "Ceremonial Knives", "platform": "Console"}, "1784443031": {"name": "Legendary: Anessazi Edge", "category": "Ceremonial Knives", "platform": "Console"}, "-1242999421": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1242996977": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684207": {"name": "Legendary: Anessazi Edge (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784514905": {"name": "Legendary: Deadly Rebirth", "category": "Ceremonial Knives", "platform": "Console"}, "1784694590": {"name": "Legendary: Last Breath", "category": "Ceremonial Knives", "platform": "Console"}, "-1234697974": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1234695530": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684214": {"name": "Legendary: Last Breath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784622716": {"name": "Legendary: Living Umbral Oath", "category": "Ceremonial Knives", "platform": "Console"}, "-1240627579": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1240625135": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684209": {"name": "Legendary: Moon Slayer (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1823614361": {"name": "Legendary: Rhen'ho Flayer", "category": "Ceremonial Knives", "platform": "Console"}, "916911834": {"name": "Legendary: Sacred Harvester (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "595814643": {"name": "Legendary: Sacrificer", "category": "Ceremonial Knives", "platform": "Console"}, "1823578424": {"name": "Legendary: Starmetal Kukri", "category": "Ceremonial Knives", "platform": "Console"}, "916911835": {"name": "Legendary: The Dagger of Darts (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "1784478968": {"name": "Legendary: The Gidbinn", "category": "Ceremonial Knives", "platform": "Console"}, "-1241813500": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1241811056": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684208": {"name": "Legendary: The Gidbinn (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784550842": {"name": "Legendary: The Spider Queen's Grasp", "category": "Ceremonial Knives", "platform": "Console"}, "-1237069816": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1237067372": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684212": {"name": "Legendary: Umbral Oath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239441658": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239439214": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684210": {"name": "Legendary: Ziggurat Tooth (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684240": {"name": "Set: Hallowed Sacrifice (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203864028": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203861584": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1785628952": {"name": "Set: Hallowed Sufferance", "category": "Ceremonial Knives", "platform": "Console"}, "1784730527": {"name": "Set: Manajuma's Carving Knife", "category": "Ceremonial Knives", "platform": "Console"}, "-1233512053": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1233509609": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684215": {"name": "Set: Manajuma's Ritual Cutter (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "258855259": {"name": "Set: Cage of the Hellborn (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258855260": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783385": {"name": "Set: Cuirass of the Wastes (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819322": {"name": "Set: Harness of Truth (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783386": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "259969569": {"name": "Set: Sunwuko's Soul (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819323": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "1612257704": {"name": "01: Cloth Tunic (AR 3)", "category": "Chest Armor", "platform": "Console"}, "1612257705": {"name": "02: Leather Doublet (AR 18-21)", "category": "Chest Armor", "platform": "Console"}, "1612257706": {"name": "03: Brigandine Coat (AR 33-38)", "category": "Chest Armor", "platform": "Console"}, "1612257707": {"name": "04: Chain Mail (AR 51-68)", "category": "Chest Armor", "platform": "Console"}, "1612257708": {"name": "05: Splint Cuirass (AR 69-86)", "category": "Chest Armor", "platform": "Console"}, "1612257709": {"name": "06: Plate Mail (AR 87-107)", "category": "Chest Armor", "platform": "Console"}, "1612258793": {"name": "07: Stygian Harness (AR 108-137)", "category": "Chest Armor", "platform": "Console"}, "1612258794": {"name": "08: Etched Jacket (AR 138-167)", "category": "Chest Armor", "platform": "Console"}, "1612258795": {"name": "09: Jazeraint Mail (AR 168-197)", "category": "Chest Armor", "platform": "Console"}, "1612258796": {"name": "10: Battle Armor (AR 198-224)", "category": "Chest Armor", "platform": "Console"}, "1612258797": {"name": "11: Boneweave Hauberk (AR 225-247)", "category": "Chest Armor", "platform": "Console"}, "1612259882": {"name": "12: Balor Armor (AR 247-269)", "category": "Chest Armor", "platform": "Console"}, "1612259883": {"name": "13: Astral Mail (AR 270-284)", "category": "Chest Armor", "platform": "Console"}, "1612259884": {"name": "14: Warlord Plate (AR 285-322)", "category": "Chest Armor", "platform": "Console"}, "1612259885": {"name": "15: Doom Armor (AR 322-359)", "category": "Chest Armor", "platform": "Console"}, "1612259886": {"name": "16: Sovereign Mail (AR 360-397)", "category": "Chest Armor", "platform": "Console"}, "1612259887": {"name": "17: Archon Armor (AR 397-471)", "category": "Chest Armor", "platform": "Console"}, "1612259888": {"name": "18: Rakkisgard Armor (AR 472-659)", "category": "Chest Armor", "platform": "Console"}, "1612259889": {"name": "19: Ascended Armor (AR 660-759)", "category": "Chest Armor", "platform": "Console"}, "1937623756": {"name": "Art Test Chest 1", "category": "Chest Armor", "platform": "Console"}, "1937623757": {"name": "Art Test Chest 2", "category": "Chest Armor", "platform": "Console"}, "1937623758": {"name": "Art Test Chest 3", "category": "Chest Armor", "platform": "Console"}, "1937623759": {"name": "Art Test Chest 4", "category": "Chest Armor", "platform": "Console"}, "1937623760": {"name": "Art Test Chest 5", "category": "Chest Armor", "platform": "Console"}, "1316774087": {"name": "Legendary: Aquila Cuirass", "category": "Chest Armor", "platform": "Console"}, "503794611": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "503797055": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016991": {"name": "Legendary: Aquila Cuirass (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354723559": {"name": "Legendary: Armor of the Kind Regent", "category": "Chest Armor", "platform": "Console"}, "1316702213": {"name": "Legendary: Chaingmail", "category": "Chest Armor", "platform": "Console"}, "501422769": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "501425213": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016989": {"name": "Legendary: Chaingmail (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1315731914": {"name": "Legendary: Cindercoat", "category": "Chest Armor", "platform": "Console"}, "469402902": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "469405346": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016962": {"name": "Legendary: Cindercoat (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "883162595": {"name": "Legendary: Conqueror's Cuirass (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "1315552229": {"name": "Legendary: Goldskin", "category": "Chest Armor", "platform": "Console"}, "463473297": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "463475741": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016957": {"name": "Legendary: Goldskin (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316989709": {"name": "Legendary: Heart of Iron", "category": "Chest Armor", "platform": "Console"}, "510910137": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "510912581": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016997": {"name": "Legendary: Heart of Iron (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1821181577": {"name": "Legendary: Heart of the Titans", "category": "Chest Armor", "platform": "Console"}, "1317025646": {"name": "Legendary: Mantle of the Rydraelm", "category": "Chest Armor", "platform": "Console"}, "512096058": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "512098502": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016998": {"name": "Legendary: Robes of the Rydraelm (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354687622": {"name": "Legendary: Shi Mizu's Haori", "category": "Chest Armor", "platform": "Console"}, "1315588166": {"name": "Legendary: Tyrael's Might", "category": "Chest Armor", "platform": "Console"}, "464659218": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "464661662": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016958": {"name": "Legendary: Tyrael's Might (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "547673688": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "547676132": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318103756": {"name": "Set: Aughild's Rule", "category": "Chest Armor", "platform": "Console"}, "172017028": {"name": "Set: Aughild's Vestments (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1262779559": {"name": "Set: Blackthorne's Jacket (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "-115330289": {"name": "Set: Blackthorne's Surcoat", "category": "Chest Armor", "platform": "Console"}, "488990459": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "488992903": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172017027": {"name": "Set: Born's Carapace (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318067819": {"name": "Set: Born's Frozen Soul", "category": "Chest Armor", "platform": "Console"}, "546487767": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "546490211": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259933632": {"name": "Set: Breastplate of Akkhan", "category": "Chest Armor", "platform": "Console"}, "172017029": {"name": "Set: Demon's Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "548859609": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "548862053": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318139693": {"name": "Set: Demon's Marrow", "category": "Chest Armor", "platform": "Console"}, "258963333": {"name": "Set: Firebird's Breast", "category": "Chest Armor", "platform": "Console"}, "259035207": {"name": "Set: Heart of the Crashing Wave", "category": "Chest Armor", "platform": "Console"}, "260149254": {"name": "Set: Helltooth Tunic", "category": "Chest Armor", "platform": "Console"}, "1316810024": {"name": "Set: Immortal King's Eternal Reign", "category": "Chest Armor", "platform": "Console"}, "504980532": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "504982976": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016992": {"name": "Set: Immortal King's Soul Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016994": {"name": "Set: Inna's Refuge (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316881898": {"name": "Set: Inna's Vast Expanse", "category": "Chest Armor", "platform": "Console"}, "507352374": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "507354818": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259071144": {"name": "Set: Jade Harvester's Peace", "category": "Chest Armor", "platform": "Console"}, "258999270": {"name": "Set: Marauder's Carapace", "category": "Chest Armor", "platform": "Console"}, "258927396": {"name": "Set: Raekor's Heart", "category": "Chest Armor", "platform": "Console"}, "258783384": {"name": "Set: Roland's Bearing (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "172016993": {"name": "Set: Tal Rasha's Guardianship (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316845961": {"name": "Set: Tal Rasha's Relentless Pursuit", "category": "Chest Armor", "platform": "Console"}, "506166453": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "506168897": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "260077380": {"name": "Set: The Shadow's Bane", "category": "Chest Armor", "platform": "Console"}, "260041443": {"name": "Set: Vyr's Astonishing Aura", "category": "Chest Armor", "platform": "Console"}, "1316917835": {"name": "Set: Zunimassa's Marrow", "category": "Chest Armor", "platform": "Console"}, "508538295": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "508540739": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016995": {"name": "Set: Zunimassa's Vessel (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1937623761": {"name": "Art_Test_Chest_6 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623762": {"name": "Art_Test_Chest_7 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623763": {"name": "Art_Test_Chest_8 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623764": {"name": "Art_Test_Chest_9 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "40855418": {"name": "01: Hunter Cloak (AR 30-35)", "category": "Cloaks", "platform": "Console"}, "40855419": {"name": "02: Shroud (AR 36-41)", "category": "Cloaks", "platform": "Console"}, "40855420": {"name": "03: Cape (AR 60-69)", "category": "Cloaks", "platform": "Console"}, "40855421": {"name": "04: Tabard (AR 84-113)", "category": "Cloaks", "platform": "Console"}, "40856507": {"name": "05: Wrap (AR 114-149)", "category": "Cloaks", "platform": "Console"}, "40856508": {"name": "06: Lurker Shroud (AR 150-185)", "category": "Cloaks", "platform": "Console"}, "40856509": {"name": "07: Talma (AR 186-232)", "category": "Cloaks", "platform": "Console"}, "40856510": {"name": "08: Cardinal (AR 232-254)", "category": "Cloaks", "platform": "Console"}, "40857596": {"name": "09: Veteran Cloak (AR 255-284)", "category": "Cloaks", "platform": "Console"}, "40857597": {"name": "10: Death Shroud (AR 385-322)", "category": "Cloaks", "platform": "Console"}, "40857598": {"name": "11: Stalker Cape (AR 322-359)", "category": "Cloaks", "platform": "Console"}, "40857599": {"name": "12: Dread Cloak (AR 360-472)", "category": "Cloaks", "platform": "Console"}, "40857600": {"name": "13: Rakkisgard Cloak (AR 472-659)", "category": "Cloaks", "platform": "Console"}, "40857601": {"name": "14: Ascended Cloak (AR 660-759)", "category": "Cloaks", "platform": "Console"}, "2105367871": {"name": "Art Test Cloak 1", "category": "Cloaks", "platform": "Console"}, "2105367872": {"name": "Art Test Cloak 2", "category": "Cloaks", "platform": "Console"}, "2105367873": {"name": "Art Test Cloak 3", "category": "Cloaks", "platform": "Console"}, "2105367874": {"name": "Art Test Cloak 4", "category": "Cloaks", "platform": "Console"}, "2105367875": {"name": "Art Test Cloak 5", "category": "Cloaks", "platform": "Console"}, "221665681": {"name": "Legendary Cloak 002 p1", "category": "Cloaks", "platform": "Console"}, "221773756": {"name": "Legendary: Beckon Sail", "category": "Cloaks", "platform": "Console"}, "-1271477944": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1271475500": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235532": {"name": "Legendary: Beckon Sail (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260765401": {"name": "Legendary: Blackfeather", "category": "Cloaks", "platform": "Console"}, "221630008": {"name": "Legendary: Cape of the Dark Night", "category": "Cloaks", "platform": "Console"}, "-1276221628": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1276219184": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235536": {"name": "Legendary: Cape of the Dark Night (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260801338": {"name": "Legendary: Cloak of Deception", "category": "Cloaks", "platform": "Console"}, "221665945": {"name": "Legendary: The Cloak of the Garwulf", "category": "Cloaks", "platform": "Console"}, "-1275035707": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1275033263": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235535": {"name": "Legendary: The Inquisitor (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "221809693": {"name": "Set: Natalya's Embrace", "category": "Cloaks", "platform": "Console"}, "-1270292023": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1270289579": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235531": {"name": "Set: Natalya's Shadow (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "1401594517": {"name": "A Gift", "category": "Consumables", "platform": "Console"}, "-1691237125": {"name": "Blood Shard", "category": "Consumables", "platform": "Console"}, "-2018707791": {"name": "Bottomless Potion Of Fear (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-2018707790": {"name": "Bottomless Potion of Amplification (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707793": {"name": "Bottomless Potion of Kulle Aid", "category": "Consumables", "platform": "Console"}, "-2018707794": {"name": "Bottomless Potion of Mutilation", "category": "Consumables", "platform": "Console"}, "-2018707796": {"name": "Bottomless Potion of Regeneration", "category": "Consumables", "platform": "Console"}, "-2018707792": {"name": "Bottomless Potion of Rejuvenation", "category": "Consumables", "platform": "Console"}, "510979313": {"name": "Bottomless Potion of Rejuvenation (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707797": {"name": "Bottomless Potion of the Diamond", "category": "Consumables", "platform": "Console"}, "-2018707795": {"name": "Bottomless Potion of the Leech", "category": "Consumables", "platform": "Console"}, "-2018707798": {"name": "Bottomless Potion of the Tower", "category": "Consumables", "platform": "Console"}, "727989467": {"name": "Bottomless Regular Health Potion (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618072": {"name": "Consumable_Potion_Bloodshard_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "736462346": {"name": "Consumable_Potion_Bloodshard_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618138": {"name": "Consumable_Potion_Bloodshard_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618270": {"name": "Consumable_Potion_Bloodshard_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764252": {"name": "Consumable_Potion_Gold_Find_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-418681010": {"name": "Consumable_Potion_Gold_Find_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764318": {"name": "Consumable_Potion_Gold_Find_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764450": {"name": "Consumable_Potion_Gold_Find_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167362": {"name": "Consumable_Potion_XP_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1032379504": {"name": "Consumable_Potion_XP_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167296": {"name": "Consumable_Potion_XP_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167164": {"name": "Consumable_Potion_XP_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2142362846": {"name": "Health Potion", "category": "Consumables", "platform": "Console"}, "-650776931": {"name": "Infernal Machine", "category": "Consumables", "platform": "Console"}, "1054965529": {"name": "Infernal Machine of Bones", "category": "Consumables", "platform": "Console"}, "1458185494": {"name": "Infernal Machine of Evil", "category": "Consumables", "platform": "Console"}, "-1506243402": {"name": "Infernal Machine of Gluttony", "category": "Consumables", "platform": "Console"}, "-1672611564": {"name": "Infernal Machine of War", "category": "Consumables", "platform": "Console"}, "-1055802742": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1927699898": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-1990624170": {"name": "PowerGlobe", "category": "Consumables", "platform": "Console"}, "-1407876474": {"name": "PowerGlobe NoFlippy", "category": "Consumables", "platform": "Console"}, "1604670149": {"name": "PowerGlobe v2 x1", "category": "Consumables", "platform": "Console"}, "1554449877": {"name": "PowerGlobe v2 x1 NoFlippy", "category": "Consumables", "platform": "Console"}, "-767886865": {"name": "PvP_HealingDude", "category": "Consumables", "platform": "Console"}, "1844495708": {"name": "Ramaladni's Gift", "category": "Consumables", "platform": "Console"}, "-2108322324": {"name": "Ramaladni's Gift (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-1629755675": {"name": "Rare Gift (RoS)", "category": "Consumables", "platform": "Console"}, "750709043": {"name": "ShrineGlobe Blessed", "category": "Consumables", "platform": "Console"}, "-783958152": {"name": "ShrineGlobe Enlightened", "category": "Consumables", "platform": "Console"}, "1754475188": {"name": "ShrineGlobe Fortune", "category": "Consumables", "platform": "Console"}, "1126841672": {"name": "ShrineGlobe Frenzied", "category": "Consumables", "platform": "Console"}, "-1436918535": {"name": "Steak10", "category": "Consumables", "platform": "Console"}, "-1436918530": {"name": "Steak15", "category": "Consumables", "platform": "Console"}, "-1436918502": {"name": "Steak20", "category": "Consumables", "platform": "Console"}, "-1436918497": {"name": "Steak25", "category": "Consumables", "platform": "Console"}, "-1436918469": {"name": "Steak30", "category": "Consumables", "platform": "Console"}, "-1436918464": {"name": "Steak35", "category": "Consumables", "platform": "Console"}, "-1436918436": {"name": "Steak40", "category": "Consumables", "platform": "Console"}, "346908589": {"name": "Steak5", "category": "Consumables", "platform": "Console"}, "450956006": {"name": "p1 tiered rifts Orb", "category": "Consumables", "platform": "Console"}, "237118774": {"name": "Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "703352254": {"name": "Art_Test_Pet_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352255": {"name": "Art_Test_Pet_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352256": {"name": "Art_Test_Pet_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352257": {"name": "Art_Test_Pet_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352258": {"name": "Art_Test_Pet_5 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352259": {"name": "Art_Test_Pet_6 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555709": {"name": "Art_Test_Wings_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555710": {"name": "Art_Test_Wings_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555711": {"name": "Art_Test_Wings_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555712": {"name": "Art_Test_Wings_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1736870778": {"name": "Blade Wings", "category": "Cosmetics", "platform": "Console"}, "2015178386": {"name": "Blade Wings (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508877": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508876": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "988742338": {"name": "Cosmetic_Pet_FallenHound_Skeletal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508875": {"name": "Cosmetic_Pet_teddyBear_04 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1464439640": {"name": "Cosmetic_Wings_Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834901": {"name": "Cosmetic_Wings_bat_02 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834902": {"name": "Cosmetic_Wings_bat_03 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1424453175": {"name": "Crimson Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "1464422100": {"name": "Demon Soaring (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208405024": {"name": "Eldritch Embrace (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1081301157": {"name": "Eternal Flame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1030142027": {"name": "Eternal Light (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1815774861": {"name": "Fingers of Terror (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380235": {"name": "Frame: Angelic (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264991": {"name": "Frame: Base Frame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380233": {"name": "Frame: Bone (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380234": {"name": "Frame: Deathshead (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380230": {"name": "Frame: Molton (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264990": {"name": "Frame: Paragon 1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764818": {"name": "Frame: Paragon 10 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114304450": {"name": "Frame: Paragon 100 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764851": {"name": "Frame: Paragon 20 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114305539": {"name": "Frame: Paragon 200 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764884": {"name": "Frame: Paragon 30 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764917": {"name": "Frame: Paragon 40 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114307717": {"name": "Frame: Paragon 400 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764950": {"name": "Frame: Paragon 50 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114308806": {"name": "Frame: Paragon 500 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764983": {"name": "Frame: Paragon 60 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114309895": {"name": "Frame: Paragon 600 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765016": {"name": "Frame: Paragon 70 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114310984": {"name": "Frame: Paragon 700 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765049": {"name": "Frame: Paragon 80 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114312073": {"name": "Frame: Paragon 800 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765082": {"name": "Frame: Paragon 90 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114306628": {"name": "Frame: Paraogn 300 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380199": {"name": "Frame: Season 3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380228": {"name": "Frame: Staind Glass Azure (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380202": {"name": "Frame: Staind Glass Orange (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380201": {"name": "Frame: Staind Glass Purple (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380227": {"name": "Frame: Staind Glass Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380229": {"name": "Frame: Staind Glass Teal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380203": {"name": "Frame: Staind Glass Yellow (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380231": {"name": "Frame: Steadfast (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380198": {"name": "Frame: Storm (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380232": {"name": "Frame: Thorns (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380200": {"name": "Frame: Whimseyshire (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "211305012": {"name": "Harbringer of Destruction (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "262300867": {"name": "Heaven't Might (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-922089455": {"name": "Knights of Westmarch (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1412314502": {"name": "Liber Canis Mortui", "category": "Cosmetics", "platform": "Console"}, "-1527508878": {"name": "Mr Bear (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208454467": {"name": "Pieces of Hatred (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "517654224": {"name": "Probe (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "291388174": {"name": "Spike (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1647814559": {"name": "Ten Pounder (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1454306710": {"name": "The Light of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-2072242152": {"name": "The Pillars of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-937743655": {"name": "Warlords Of Draenor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-762694428": {"name": "Warsong Pennant", "category": "Cosmetics", "platform": "Console"}, "-1364948604": {"name": "Wings of Valor", "category": "Cosmetics", "platform": "Console"}, "1464422747": {"name": "Wings of Valor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "727152075": {"name": "Adventurer's Journal", "category": "Crafting Components", "platform": "Console"}, "-784029520": {"name": "Angelic Shard", "category": "Crafting Components", "platform": "Console"}, "-1585802162": {"name": "Arcane Dust", "category": "Crafting Components", "platform": "Console"}, "2048505008": {"name": "Behistun Rune", "category": "Crafting Components", "platform": "Console"}, "-1993550104": {"name": "Black Mushroom", "category": "Crafting Components", "platform": "Console"}, "1864276820": {"name": "Bloody Pincer", "category": "Crafting Components", "platform": "Console"}, "-875022940": {"name": "Born's Key", "category": "Crafting Components", "platform": "Console"}, "-229384987": {"name": "Captured Nightmare", "category": "Crafting Components", "platform": "Console"}, "1016443205": {"name": "Captured Soul", "category": "Crafting Components", "platform": "Console"}, "903645542": {"name": "Cartographer's Toolkit", "category": "Crafting Components", "platform": "Console"}, "2064572165": {"name": "Common Debris", "category": "Crafting Components", "platform": "Console"}, "-821947350": {"name": "Cultist Blood", "category": "Crafting Components", "platform": "Console"}, "2087837753": {"name": "Death's Breath", "category": "Crafting Components", "platform": "Console"}, "2000469169": {"name": "Defiled Doll", "category": "Crafting Components", "platform": "Console"}, "-1761931437": {"name": "Demon Skin", "category": "Crafting Components", "platform": "Console"}, "-152489231": {"name": "Demonic Essence", "category": "Crafting Components", "platform": "Console"}, "-645052297": {"name": "Devil's Fang", "category": "Crafting Components", "platform": "Console"}, "437938885": {"name": "Element of Celerity", "category": "Crafting Components", "platform": "Console"}, "2064572134": {"name": "Encrusted Hoof (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-1725926578": {"name": "Essence of the Twin Seas", "category": "Crafting Components", "platform": "Console"}, "-1506992994": {"name": "Eternal Power Capsule", "category": "Crafting Components", "platform": "Console"}, "2064572166": {"name": "Exquisite Essence", "category": "Crafting Components", "platform": "Console"}, "1726149320": {"name": "Eyes of the Dead", "category": "Crafting Components", "platform": "Console"}, "2064572068": {"name": "Fallen Tooth (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "2064572168": {"name": "Fiery Brimstone", "category": "Crafting Components", "platform": "Console"}, "2073430088": {"name": "Forgotten Soul", "category": "Crafting Components", "platform": "Console"}, "937036308": {"name": "Frozen Blood", "category": "Crafting Components", "platform": "Console"}, "-799974399": {"name": "Gibbering Gemstone", "category": "Crafting Components", "platform": "Console"}, "-1299206911": {"name": "Glowing Ore", "category": "Crafting Components", "platform": "Console"}, "-730966965": {"name": "Griswold's Scribblings", "category": "Crafting Components", "platform": "Console"}, "-958180196": {"name": "Heart of Evil", "category": "Crafting Components", "platform": "Console"}, "460247356": {"name": "Hilt of the Silver Wolf", "category": "Crafting Components", "platform": "Console"}, "314328565": {"name": "Human Cartilage", "category": "Crafting Components", "platform": "Console"}, "-1624623846": {"name": "Idol of Terror", "category": "Crafting Components", "platform": "Console"}, "2064572167": {"name": "Iridescent Tear", "category": "Crafting Components", "platform": "Console"}, "-661382443": {"name": "Iron Wolves Doctrine", "category": "Crafting Components", "platform": "Console"}, "1102953247": {"name": "Leoric's Regret", "category": "Crafting Components", "platform": "Console"}, "-629520052": {"name": "Leoric's Shinbone", "category": "Crafting Components", "platform": "Console"}, "725082635": {"name": "Liquid Rainbow", "category": "Crafting Components", "platform": "Console"}, "-1402576366": {"name": "Living Flame", "category": "Crafting Components", "platform": "Console"}, "2064572101": {"name": "Lizard Eye (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "291872615": {"name": "Lyekurn's Diary", "category": "Crafting Components", "platform": "Console"}, "1835813454": {"name": "Maghda's Tormented Soul", "category": "Crafting Components", "platform": "Console"}, "-1018735616": {"name": "Mystical Source", "category": "Crafting Components", "platform": "Console"}, "-1020906970": {"name": "Page of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-667291726": {"name": "Page of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "526997101": {"name": "Phial of Weakness", "category": "Crafting Components", "platform": "Console"}, "778194127": {"name": "Quaking Vial", "category": "Crafting Components", "platform": "Console"}, "1114256397": {"name": "Reaper's Fear", "category": "Crafting Components", "platform": "Console"}, "-363607620": {"name": "Reusable Parts", "category": "Crafting Components", "platform": "Console"}, "280425627": {"name": "Rydraelm Tome", "category": "Crafting Components", "platform": "Console"}, "-830982818": {"name": "Shard of Entsteig Plate", "category": "Crafting Components", "platform": "Console"}, "-1176010511": {"name": "Shattered Core", "category": "Crafting Components", "platform": "Console"}, "2064572100": {"name": "Shimmering Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2114382103": {"name": "Shimmering Quill", "category": "Crafting Components", "platform": "Console"}, "-248569447": {"name": "Shuddering Demon Bone", "category": "Crafting Components", "platform": "Console"}, "-1810945531": {"name": "Skelon's Dice", "category": "Crafting Components", "platform": "Console"}, "-997569662": {"name": "Skull of Raylend", "category": "Crafting Components", "platform": "Console"}, "2064572067": {"name": "Subtle Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2113447741": {"name": "Sydyru Bone", "category": "Crafting Components", "platform": "Console"}, "-1253986069": {"name": "Symbol of the Guardian Brotherhood", "category": "Crafting Components", "platform": "Console"}, "494826242": {"name": "Tome of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-722757874": {"name": "Tome of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-970366835": {"name": "Tome of Secrets (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-443730551": {"name": "Torn Soul", "category": "Crafting Components", "platform": "Console"}, "1075049130": {"name": "Urn of Quickening", "category": "Crafting Components", "platform": "Console"}, "-605947593": {"name": "Veiled Crystal", "category": "Crafting Components", "platform": "Console"}, "1998976972": {"name": "Vengeful Eye", "category": "Crafting Components", "platform": "Console"}, "2029265596": {"name": "Vial of Putridness", "category": "Crafting Components", "platform": "Console"}, "1016299457": {"name": "White Oak Splinter", "category": "Crafting Components", "platform": "Console"}, "-799868536": {"name": "Wirt's Bell", "category": "Crafting Components", "platform": "Console"}, "2064572133": {"name": "Wishful Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "1098021531": {"name": "Wooden Stake", "category": "Crafting Components", "platform": "Console"}, "2103664575": {"name": "Woven Plate", "category": "Crafting Components", "platform": "Console"}, "-1824155952": {"name": "Writhing Spine", "category": "Crafting Components", "platform": "Console"}, "-747908647": {"name": "px_HoradricReagent_01 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908646": {"name": "px_HoradricReagent_02 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908645": {"name": "px_HoradricReagent_03 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908644": {"name": "px_HoradricReagent_04 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908643": {"name": "px_HoradricReagent_05 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-1171398246": {"name": "Design: Flawless Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429567911": {"name": "Design: Flawless Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521994629": {"name": "Design: Flawless Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147380749": {"name": "Design: Flawless Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872863289": {"name": "Design: Flawless Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171649812": {"name": "Design: Flawless Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521743063": {"name": "Design: Flawless Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147129183": {"name": "Design: Flawless Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872611723": {"name": "Design: Flawless Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1540480229": {"name": "Design: Hellfire Amulet (Patch 1.2.0)", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-384404829": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1792019289": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171541998": {"name": "Design: Marquise Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521850877": {"name": "Design: Marquise Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147236997": {"name": "Design: Marquise Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872719537": {"name": "Design: Marquise Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171613874": {"name": "Design: Perfect Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521779001": {"name": "Design: Perfect Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147165121": {"name": "Design: Perfect Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872647661": {"name": "Design: Perfect Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171577936": {"name": "Design: Radiant Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521814939": {"name": "Design: Radiant Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147201059": {"name": "Design: Radiant Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872683599": {"name": "Design: Radiant Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171434184": {"name": "Design: Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429531973": {"name": "Design: Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521958691": {"name": "Design: Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147344811": {"name": "Design: Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872827351": {"name": "Design: Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-987473495": {"name": "Legendary Plan: Arcane Barb", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427518108": {"name": "Legendary Plan: Archfiend Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1046516600": {"name": "Legendary Plan: Atrophy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1423568820": {"name": "Legendary Plan: Bitterness", "category": "Crafting Plans, Smith", "platform": "Console"}, "-380290097": {"name": "Legendary Plan: Black Bone Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1418151206": {"name": "Legendary Plan: Blitzbolter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-912856835": {"name": "Legendary Plan: Blood-Magic Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2000896011": {"name": "Legendary Plan: Blood-Magic Edge", "category": "Crafting Plans, Smith", "platform": "Console"}, "867919825": {"name": "Legendary Plan: Board Walkers", "category": "Crafting Plans, Smith", "platform": "Console"}, "-412066328": {"name": "Legendary Plan: Cataclysm", "category": "Crafting Plans, Smith", "platform": "Console"}, "1713442269": {"name": "Legendary Plan: Cinder Switch", "category": "Crafting Plans, Smith", "platform": "Console"}, "612002290": {"name": "Legendary Plan: Corruption", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1413614420": {"name": "Legendary Plan: Cosmic Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "421386501": {"name": "Legendary Plan: Deadeye", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1911170977": {"name": "Legendary Plan: Demon Claw", "category": "Crafting Plans, Smith", "platform": "Console"}, "999120591": {"name": "Legendary Plan: Demon Hand", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1426610660": {"name": "Legendary Plan: Devastator", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1326018783": {"name": "Legendary Plan: Earthshatter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1003069110": {"name": "Legendary Plan: Fire Brand", "category": "Crafting Plans, Smith", "platform": "Console"}, "957458384": {"name": "Legendary Plan: Fleeting Strap", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1639510640": {"name": "Legendary Plan: Gehennas", "category": "Crafting Plans, Smith", "platform": "Console"}, "780377031": {"name": "Legendary Plan: Golden Scourge", "category": "Crafting Plans, Smith", "platform": "Console"}, "412214125": {"name": "Legendary Plan: Harvest Moon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-501637898": {"name": "Legendary Plan: Hellish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-846348803": {"name": "Legendary Plan: Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "253048194": {"name": "Legendary Plan: Infernal Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-103899531": {"name": "Legendary Plan: Kethryes' Splint", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904674800": {"name": "Legendary Plan: Lai Yui's Persuader", "category": "Crafting Plans, Smith", "platform": "Console"}, "-168948640": {"name": "Legendary Plan: Lai Yui's Taiji", "category": "Crafting Plans, Smith", "platform": "Console"}, "1029528340": {"name": "Legendary Plan: Living Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "-405238050": {"name": "Legendary Plan: Longshot", "category": "Crafting Plans, Smith", "platform": "Console"}, "269805368": {"name": "Legendary Plan: Lost Boys", "category": "Crafting Plans, Smith", "platform": "Console"}, "244699910": {"name": "Legendary Plan: Mantle of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "2012779291": {"name": "Legendary Plan: Mark of The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "1744959696": {"name": "Legendary Plan: Night's Reaping", "category": "Crafting Plans, Smith", "platform": "Console"}, "645585264": {"name": "Legendary Plan: Nightmarish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2142082753": {"name": "Legendary Plan: Pendergrasps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-451796586": {"name": "Legendary Plan: Penders Purchase", "category": "Crafting Plans, Smith", "platform": "Console"}, "-216958038": {"name": "Legendary Plan: Piro Marella", "category": "Crafting Plans, Smith", "platform": "Console"}, "1162824884": {"name": "Legendary Plan: Quick Draw Belt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-64692264": {"name": "Legendary Plan: Reaper's Wraps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1654685887": {"name": "Legendary Plan: Robes of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904818548": {"name": "Legendary Plan: Rozpedin's Force", "category": "Crafting Plans, Smith", "platform": "Console"}, "1548578205": {"name": "Legendary Plan: Rozpedin's Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1861702115": {"name": "Legendary Plan: Ruinstoke", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2122397885": {"name": "Legendary Plan: Seven Sins", "category": "Crafting Plans, Smith", "platform": "Console"}, "1071490652": {"name": "Legendary Plan: Singularity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1846671248": {"name": "Legendary Plan: Skelon's Deceit", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1774978628": {"name": "Legendary Plan: Spite", "category": "Crafting Plans, Smith", "platform": "Console"}, "1806898802": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1463195022": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-402133524": {"name": "Legendary Plan: Starspine", "category": "Crafting Plans, Smith", "platform": "Console"}, "527593978": {"name": "Legendary Plan: Sunder", "category": "Crafting Plans, Smith", "platform": "Console"}, "2067112046": {"name": "Legendary Plan: Sydyru Crust", "category": "Crafting Plans, Smith", "platform": "Console"}, "1121389360": {"name": "Legendary Plan: The Helm of Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "-478050163": {"name": "Legendary Plan: The Helm of Rule", "category": "Crafting Plans, Smith", "platform": "Console"}, "186340431": {"name": "Legendary Plan: The Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "274154411": {"name": "Legendary Plan: The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "-242397939": {"name": "Legendary Plan: The Wedge", "category": "Crafting Plans, Smith", "platform": "Console"}, "-647199777": {"name": "Legendary Plan: Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "2066177684": {"name": "Legendary Plan: Unbound Bolt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1895316276": {"name": "Legendary Plan: Unending War", "category": "Crafting Plans, Smith", "platform": "Console"}, "-241912353": {"name": "Legendary Plan: Utar's Roar", "category": "Crafting Plans, Smith", "platform": "Console"}, "-446889189": {"name": "Legendary Plan: Venomhusk", "category": "Crafting Plans, Smith", "platform": "Console"}, "-30314682": {"name": "Legendary Plan: Wall of Bone", "category": "Crafting Plans, Smith", "platform": "Console"}, "-864620096": {"name": "Legendary Plan: Wall of Man", "category": "Crafting Plans, Smith", "platform": "Console"}, "-594473293": {"name": "Legendary Plan: War of the Dead", "category": "Crafting Plans, Smith", "platform": "Console"}, "1027888204": {"name": "Legendary Plan: Wondrous Deflectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110595705": {"name": "Rare Plan: Amulet of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110601443": {"name": "Rare Plan: Amulet of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110612529": {"name": "Rare Plan: Amulet of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110615435": {"name": "Rare Plan: Amulet of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069218648": {"name": "Rare Plan: Archon Armor of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069212910": {"name": "Rare Plan: Archon Armor of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069201824": {"name": "Rare Plan: Archon Armor of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069198918": {"name": "Rare Plan: Archon Armor of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427345983": {"name": "Rare Plan: Archon Gauntlets of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427340245": {"name": "Rare Plan: Archon Gauntlets of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427329159": {"name": "Rare Plan: Archon Gauntlets of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427326253": {"name": "Rare Plan: Archon Gauntlets of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194993962": {"name": "Rare Plan: Archon Spaulders of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194999700": {"name": "Rare Plan: Archon Spaulders of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195010786": {"name": "Rare Plan: Archon Spaulders of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195013692": {"name": "Rare Plan: Archon Spaulders of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666895": {"name": "Rare Plan: Exalted Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006109": {"name": "Rare Plan: Exalted Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232950": {"name": "Rare Plan: Exalted Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008978": {"name": "Rare Plan: Exalted Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049108": {"name": "Rare Plan: Exalted Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150314": {"name": "Rare Plan: Exalted Fine Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666894": {"name": "Rare Plan: Exalted Fine Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006108": {"name": "Rare Plan: Exalted Fine Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232949": {"name": "Rare Plan: Exalted Fine Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008977": {"name": "Rare Plan: Exalted Fine Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049107": {"name": "Rare Plan: Exalted Fine Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445431": {"name": "Rare Plan: Exalted Fine Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898771": {"name": "Rare Plan: Exalted Fine Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669101": {"name": "Rare Plan: Exalted Fine Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978459": {"name": "Rare Plan: Exalted Fine Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927530": {"name": "Rare Plan: Exalted Fine Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852815": {"name": "Rare Plan: Exalted Fine Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340209": {"name": "Rare Plan: Exalted Fine Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820187": {"name": "Rare Plan: Exalted Fine Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806016": {"name": "Rare Plan: Exalted Fine Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305005": {"name": "Rare Plan: Exalted Fine Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242821": {"name": "Rare Plan: Exalted Fine Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302887": {"name": "Rare Plan: Exalted Fine Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895417": {"name": "Rare Plan: Exalted Fine Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084692": {"name": "Rare Plan: Exalted Fine Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047028": {"name": "Rare Plan: Exalted Fine Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766203": {"name": "Rare Plan: Exalted Fine Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600122": {"name": "Rare Plan: Exalted Fine Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691115": {"name": "Rare Plan: Exalted Fine Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695962": {"name": "Rare Plan: Exalted Fine Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502140": {"name": "Rare Plan: Exalted Fine Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137849": {"name": "Rare Plan: Exalted Fine Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631474": {"name": "Rare Plan: Exalted Fine Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237753": {"name": "Rare Plan: Exalted Fine Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445432": {"name": "Rare Plan: Exalted Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898770": {"name": "Rare Plan: Exalted Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669102": {"name": "Rare Plan: Exalted Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-93021373": {"name": "Rare Plan: Exalted Grand Archmage Headpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150313": {"name": "Rare Plan: Exalted Grand Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666893": {"name": "Rare Plan: Exalted Grand Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006107": {"name": "Rare Plan: Exalted Grand Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232948": {"name": "Rare Plan: Exalted Grand Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008976": {"name": "Rare Plan: Exalted Grand Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049106": {"name": "Rare Plan: Exalted Grand Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445430": {"name": "Rare Plan: Exalted Grand Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898772": {"name": "Rare Plan: Exalted Grand Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "972140825": {"name": "Rare Plan: Exalted Grand Ghost Sight", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669100": {"name": "Rare Plan: Exalted Grand Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978460": {"name": "Rare Plan: Exalted Grand Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "531375006": {"name": "Rare Plan: Exalted Grand Heavy Baldric", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927531": {"name": "Rare Plan: Exalted Grand Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1162323497": {"name": "Rare Plan: Exalted Grand Manitou Mask", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852814": {"name": "Rare Plan: Exalted Grand Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340210": {"name": "Rare Plan: Exalted Grand Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820186": {"name": "Rare Plan: Exalted Grand Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806017": {"name": "Rare Plan: Exalted Grand Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305006": {"name": "Rare Plan: Exalted Grand Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242822": {"name": "Rare Plan: Exalted Grand Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302888": {"name": "Rare Plan: Exalted Grand Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895418": {"name": "Rare Plan: Exalted Grand Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084693": {"name": "Rare Plan: Exalted Grand Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047027": {"name": "Rare Plan: Exalted Grand Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766204": {"name": "Rare Plan: Exalted Grand Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600123": {"name": "Rare Plan: Exalted Grand Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691116": {"name": "Rare Plan: Exalted Grand Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695963": {"name": "Rare Plan: Exalted Grand Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502139": {"name": "Rare Plan: Exalted Grand Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "1784279615": {"name": "Rare Plan: Exalted Grand Stalker Cape", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137848": {"name": "Rare Plan: Exalted Grand Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631475": {"name": "Rare Plan: Exalted Grand Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237752": {"name": "Rare Plan: Exalted Grand Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927529": {"name": "Rare Plan: Exalted Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852816": {"name": "Rare Plan: Exalted Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340208": {"name": "Rare Plan: Exalted Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820188": {"name": "Rare Plan: Exalted Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806015": {"name": "Rare Plan: Exalted Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305004": {"name": "Rare Plan: Exalted Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242820": {"name": "Rare Plan: Exalted Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302886": {"name": "Rare Plan: Exalted Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895416": {"name": "Rare Plan: Exalted Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084691": {"name": "Rare Plan: Exalted Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047029": {"name": "Rare Plan: Exalted Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600121": {"name": "Rare Plan: Exalted Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691114": {"name": "Rare Plan: Exalted Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137850": {"name": "Rare Plan: Exalted Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631473": {"name": "Rare Plan: Exalted Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237754": {"name": "Rare Plan: Exalted Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656027917": {"name": "Rare Plan: Razorspikes of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656022179": {"name": "Rare Plan: Razorspikes of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656011093": {"name": "Rare Plan: Razorspikes of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656008187": {"name": "Rare Plan: Razorspikes of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1846613104": {"name": "Set Plan: Asheara's Uniform", "category": "Crafting Plans, Smith", "platform": "Console"}, "1930988128": {"name": "Set Plan: Asheara's Vestments", "category": "Crafting Plans, Smith", "platform": "Console"}, "1761387753": {"name": "Set Plan: Aughild's Authority", "category": "Crafting Plans, Smith", "platform": "Console"}, "-522988374": {"name": "Set Plan: Aughild's Victory", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1294645649": {"name": "Set Plan: Born's Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833297": {"name": "Set Plan: Born's Defiance", "category": "Crafting Plans, Smith", "platform": "Console"}, "1416190745": {"name": "Set Plan: Cain's Destiny", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833298": {"name": "Set Plan: Cain's Fate", "category": "Crafting Plans, Smith", "platform": "Console"}, "179824936": {"name": "Set Plan: Captain Crimson's Finery", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1405796903": {"name": "Set Plan: Captain Crimson's Trimmings", "category": "Crafting Plans, Smith", "platform": "Console"}, "2113413150": {"name": "Set Plan: Demon's Hide", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968554": {"name": "Set Plan: Demon's Skin", "category": "Crafting Plans, Smith", "platform": "Console"}, "331434522": {"name": "Set Plan: Griswold's Masterpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-410837290": {"name": "Set Plan: Griswold's Perfection", "category": "Crafting Plans, Smith", "platform": "Console"}, "1023052626": {"name": "Set Plan: Guardian's Contingency", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1605103146": {"name": "Set Plan: Guardian's Jeopardy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968552": {"name": "Set Plan: Hallowed Defenders", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1135146597": {"name": "Set Plan: Hallowed Protectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "1831860075": {"name": "Set Plan: Sage's Journey", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968553": {"name": "Set Plan: Sage's Plight", "category": "Crafting Plans, Smith", "platform": "Console"}, "1549850924": {"name": "Arma Haereticorum", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850923": {"name": "Arma Mortis", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850925": {"name": "Guardian Facade", "category": "Crafting Plans, Transmog", "platform": "Console"}, "-1723454145": {"name": "Legends of the Conqueror Volume 1 (Patch 2.1.0)", "category": "Crafting Plans, Transmog", "platform": "Console"}, "181031810": {"name": "01: Light Crossbow (DPS 9.4-10.5)", "category": "Crossbows", "platform": "Console"}, "181031811": {"name": "02: Crossbow (DPS 12.7-14.3)", "category": "Crossbows", "platform": "Console"}, "181031812": {"name": "03: Heavy Crossbow (DPS 17.6-19.3)", "category": "Crossbows", "platform": "Console"}, "181031813": {"name": "04: Arbalest (DPS 22.6-24.2)", "category": "Crossbows", "platform": "Console"}, "181031814": {"name": "05: Lian Nu (DPS 27.5-29.2)", "category": "Crossbows", "platform": "Console"}, "181031815": {"name": "06: War Crossbow (DPS 32.5-34.1)", "category": "Crossbows", "platform": "Console"}, "181031816": {"name": "07: Porcupine (DPS 37.4-39.1)", "category": "Crossbows", "platform": "Console"}, "181032899": {"name": "08: Siege Crossbow (DPS 53.9-57.2)", "category": "Crossbows", "platform": "Console"}, "181032900": {"name": "09: Quarrelbow (DPS 57.2-60.5)", "category": "Crossbows", "platform": "Console"}, "181032901": {"name": "10: Heavy Siege Crossbow (DPS 64.9-68.2)", "category": "Crossbows", "platform": "Console"}, "181032902": {"name": "11: Slingbow (DPS 76.5-81.4)", "category": "Crossbows", "platform": "Console"}, "181032903": {"name": "12: Chokonu (DPS 102.9-109.5)", "category": "Crossbows", "platform": "Console"}, "181032904": {"name": "13: War Caster (DPS 122.1-130.4)", "category": "Crossbows", "platform": "Console"}, "181032905": {"name": "14: Scorpion (DPS 165.6-175.5)", "category": "Crossbows", "platform": "Console"}, "181033988": {"name": "15: Windlass (DPS 179.3-189.2)", "category": "Crossbows", "platform": "Console"}, "181033989": {"name": "16: Cranequin (DPS 194.2-204.1)", "category": "Crossbows", "platform": "Console"}, "181033990": {"name": "17: Dread Crossbow (DPS 225.0-236.5)", "category": "Crossbows", "platform": "Console"}, "181033991": {"name": "18: Nayin (DPS 281.1-294.3)", "category": "Crossbows", "platform": "Console"}, "181033992": {"name": "19: Stonebow (DPS 358.1-371.3)", "category": "Crossbows", "platform": "Console"}, "181033993": {"name": "20: Doomcaster (DPS 424.1-437.3)", "category": "Crossbows", "platform": "Console"}, "181033994": {"name": "21: Hellion Crossbow (DPS 501.1-514.3)", "category": "Crossbows", "platform": "Console"}, "181035077": {"name": "22: Rampart Bow (DPS 698.0-711.2)", "category": "Crossbows", "platform": "Console"}, "181035078": {"name": "23: Oxybeles (DPS 948.2-961.4)", "category": "Crossbows", "platform": "Console"}, "2045161301": {"name": "Art Test Crossbow 1", "category": "Crossbows", "platform": "Console"}, "2045161302": {"name": "Art Test Crossbow 2", "category": "Crossbows", "platform": "Console"}, "2045161303": {"name": "Art Test Crossbow 3", "category": "Crossbows", "platform": "Console"}, "2045161304": {"name": "Art Test Crossbow 4", "category": "Crossbows", "platform": "Console"}, "2045161305": {"name": "Art Test Crossbow 5", "category": "Crossbows", "platform": "Console"}, "-174075631": {"name": "Legendary: Arcane Barb", "category": "Crossbows", "platform": "Console"}, "-174003757": {"name": "Legendary: Bakkan Caster", "category": "Crossbows", "platform": "Console"}, "-1447231541": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1447233985": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779307": {"name": "Legendary: Bakkan Caster (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172997521": {"name": "Legendary: Buriza-Do Kyanon", "category": "Crossbows", "platform": "Console"}, "-1414028197": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1414025753": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779335": {"name": "Legendary: Buriza-Do Kyanon (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135048049": {"name": "Legendary: Chanon Bolter", "category": "Crossbows", "platform": "Console"}, "-174183442": {"name": "Legendary: Demon Machine", "category": "Crossbows", "platform": "Console"}, "-1453163590": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1453161146": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779302": {"name": "Legendary: Demon Machine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174147505": {"name": "Legendary: Hellrack", "category": "Crossbows", "platform": "Console"}, "-1451977669": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1451975225": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779303": {"name": "Legendary: Hellrack (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174111568": {"name": "Legendary: Manticore", "category": "Crossbows", "platform": "Console"}, "-1450791748": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1450789304": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779304": {"name": "Legendary: Manticore (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172961584": {"name": "Legendary: Pus Spitter", "category": "Crossbows", "platform": "Console"}, "-1412842276": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1412839832": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779336": {"name": "Legendary: Pus Spitter (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449605827": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449603383": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779305": {"name": "Legendary: Starspine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135012112": {"name": "Legendary: Wojahnni Assaulter", "category": "Crossbows", "platform": "Console"}, "376423602": {"name": "P2 Crossbow norm Legendary 01", "category": "Crossbows", "platform": "Console"}, "376423603": {"name": "P2 Crossbow norm Legendary 02", "category": "Crossbows", "platform": "Console"}, "762151703": {"name": "PvP: Heavy Crossbow", "category": "Crossbows", "platform": "Console"}, "762151705": {"name": "PvP: Heroic Crossbow", "category": "Crossbows", "platform": "Console"}, "762151704": {"name": "PvP: Mighty Crossbow", "category": "Crossbows", "platform": "Console"}, "-118254879": {"name": "00: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254878": {"name": "01: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254877": {"name": "02: Sacred Scutum (AR 54-62)", "category": "Crusader Shields", "platform": "Console"}, "-118254876": {"name": "03: Royal Shield (AR 99-114)", "category": "Crusader Shields", "platform": "Console"}, "-118254875": {"name": "04: Heraldic Heater (AR 144-188)", "category": "Crusader Shields", "platform": "Console"}, "-118254874": {"name": "05: Embossed Shield (AR 189-224)", "category": "Crusader Shields", "platform": "Console"}, "-118254873": {"name": "06: Protector Shield (AR 225-251)", "category": "Crusader Shields", "platform": "Console"}, "-118254872": {"name": "07: Crown Shield (AR 252-287)", "category": "Crusader Shields", "platform": "Console"}, "-118253789": {"name": "08: Gilded Shield (AR 288-359)", "category": "Crusader Shields", "platform": "Console"}, "-118253788": {"name": "09: Wall Shield (AR 360-431)", "category": "Crusader Shields", "platform": "Console"}, "-118253787": {"name": "10: Zakara Heater (AR 432-503)", "category": "Crusader Shields", "platform": "Console"}, "-118253786": {"name": "11: Blazoned Shield (AR 504-575)", "category": "Crusader Shields", "platform": "Console"}, "-118253785": {"name": "12: Chased Shield (AR 576-652)", "category": "Crusader Shields", "platform": "Console"}, "-118253784": {"name": "13: Conquest Shield (AR 652-696)", "category": "Crusader Shields", "platform": "Console"}, "-118253783": {"name": "14: Imperial Kite (AR 697-741)", "category": "Crusader Shields", "platform": "Console"}, "-118252700": {"name": "15: Righteous Defender (AR 742-786)", "category": "Crusader Shields", "platform": "Console"}, "-118252699": {"name": "16: Enduring Guardian (AR 787-831)", "category": "Crusader Shields", "platform": "Console"}, "-118252698": {"name": "17: Zealous Protector (AR 832-854)", "category": "Crusader Shields", "platform": "Console"}, "-118252697": {"name": "18: Raptor Shield (AR 855-967)", "category": "Crusader Shields", "platform": "Console"}, "-118252696": {"name": "19: Adamantine Blason (AR 967-1112)", "category": "Crusader Shields", "platform": "Console"}, "-118252695": {"name": "20: Heavy Shield (AR 1417-1979)", "category": "Crusader Shields", "platform": "Console"}, "-118252694": {"name": "21: Stalwart Guardian (AR 1980-2277)", "category": "Crusader Shields", "platform": "Console"}, "795980376": {"name": "Art Test CruShield 1", "category": "Crusader Shields", "platform": "Console"}, "795980377": {"name": "Art Test CruShield 2", "category": "Crusader Shields", "platform": "Console"}, "795980378": {"name": "Art Test CruShield 3", "category": "Crusader Shields", "platform": "Console"}, "795980379": {"name": "Art Test CruShield 4", "category": "Crusader Shields", "platform": "Console"}, "795980380": {"name": "Art Test CruShield 5", "category": "Crusader Shields", "platform": "Console"}, "820607285": {"name": "Legendary: Akarat's Awakening", "category": "Crusader Shields", "platform": "Console"}, "1983862516": {"name": "Legendary: Frydehr's Wrath (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "820571348": {"name": "Legendary: Hallowed Bulwark", "category": "Crusader Shields", "platform": "Console"}, "820643222": {"name": "Legendary: Hellskull", "category": "Crusader Shields", "platform": "Console"}, "820535411": {"name": "Legendary: Jekangbord", "category": "Crusader Shields", "platform": "Console"}, "820499474": {"name": "Legendary: Piro Marella", "category": "Crusader Shields", "platform": "Console"}, "820751033": {"name": "Legendary: Salvation", "category": "Crusader Shields", "platform": "Console"}, "820679159": {"name": "Legendary: Sublime Conviction", "category": "Crusader Shields", "platform": "Console"}, "820715096": {"name": "Legendary: The Final Witness", "category": "Crusader Shields", "platform": "Console"}, "1983862517": {"name": "Legendary: Unrelenting Phalanx (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "-1303415302": {"name": "01: Simple Dagger (DPS 6.0-7.5)", "category": "Daggers", "platform": "Console"}, "-1303415301": {"name": "02: Shiv (DPS 9.0-11.3)", "category": "Daggers", "platform": "Console"}, "-1303415300": {"name": "03: Short Dagger (DPS 15.0-17.3)", "category": "Daggers", "platform": "Console"}, "-1303415299": {"name": "04: Dagger (DPS 20.3-22.5)", "category": "Daggers", "platform": "Console"}, "-1303415298": {"name": "05: Poignard (DPS 23.3-25.5)", "category": "Daggers", "platform": "Console"}, "-1303415297": {"name": "06: Stiletto (DPS 27.0-29.3)", "category": "Daggers", "platform": "Console"}, "-1303415296": {"name": "07: Skiver (DPS 30.0-23.3)", "category": "Daggers", "platform": "Console"}, "-1303414213": {"name": "08: Jagged Dagger (DPS 38.3-40.5)", "category": "Daggers", "platform": "Console"}, "-1303414212": {"name": "09: Kindjal (DPS 44.3-46.5)", "category": "Daggers", "platform": "Console"}, "-1303414211": {"name": "10: Pugio (DPS 50.3-52.5)", "category": "Daggers", "platform": "Console"}, "-1303414210": {"name": "11: Rondel (DPS 57.0-59.3)", "category": "Daggers", "platform": "Console"}, "-1303414209": {"name": "12: Scramasax (DPS 66.0-68.3)", "category": "Daggers", "platform": "Console"}, "-1303414208": {"name": "13: Main Gauche (DPS 77.3-79.5)", "category": "Daggers", "platform": "Console"}, "-1303414207": {"name": "14: Spine (DPS 92.3-94.5)", "category": "Daggers", "platform": "Console"}, "-1303413124": {"name": "15: Kukri (DPS 101.3-103.5)", "category": "Daggers", "platform": "Console"}, "-1303413123": {"name": "16: Pavade (DPS 108.0-112.5)", "category": "Daggers", "platform": "Console"}, "-1303413122": {"name": "17: Cinquedea (DPS 117.8-122.3)", "category": "Daggers", "platform": "Console"}, "-1303413121": {"name": "18: Skain (DPS 129.0-133.5)", "category": "Daggers", "platform": "Console"}, "-1303413120": {"name": "19: Basilard (DPS 156.0-160.5)", "category": "Daggers", "platform": "Console"}, "-1303413119": {"name": "20: Piercer (DPS 177.8-182.3)", "category": "Daggers", "platform": "Console"}, "-1303413118": {"name": "21: Darkblade (DPS 202.5-209.3)", "category": "Daggers", "platform": "Console"}, "-1303412035": {"name": "22: Kingsport Blade (DPS 270.0-274.5)", "category": "Daggers", "platform": "Console"}, "-1303412034": {"name": "23: Punyal (DPS 321.0-325.5)", "category": "Daggers", "platform": "Console"}, "-1200973729": {"name": "Art Test Dagger 1", "category": "Daggers", "platform": "Console"}, "-1200973728": {"name": "Art Test Dagger 2", "category": "Daggers", "platform": "Console"}, "-1200973727": {"name": "Art Test Dagger 3", "category": "Daggers", "platform": "Console"}, "-1200973726": {"name": "Art Test Dagger 4", "category": "Daggers", "platform": "Console"}, "-1200973725": {"name": "Art Test Dagger 5", "category": "Daggers", "platform": "Console"}, "-2073514231": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "-2073511787": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092661": {"name": "Legendary: Blood-Magic Blade (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973885091": {"name": "Legendary: Blood-Magic Edge", "category": "Daggers", "platform": "Console"}, "-934857509": {"name": "Legendary: Envious Blade", "category": "Daggers", "platform": "Console"}, "-934929383": {"name": "Legendary: Gull Dagger", "category": "Daggers", "platform": "Console"}, "-974028839": {"name": "Legendary: Kill", "category": "Daggers", "platform": "Console"}, "-2078257915": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "-2078255471": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092657": {"name": "Legendary: Kill (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973849154": {"name": "Legendary: Pig Sticker", "category": "Daggers", "platform": "Console"}, "-2072328310": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "-2072325866": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092662": {"name": "Legendary: Pig Sticker (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934893446": {"name": "Legendary: Prowl's Dastardly Shiv", "category": "Daggers", "platform": "Console"}, "-973992902": {"name": "Legendary: The Barber", "category": "Daggers", "platform": "Console"}, "-2077071994": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "-2077069550": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092658": {"name": "Legendary: The Barber (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973813217": {"name": "Legendary: The Clipper", "category": "Daggers", "platform": "Console"}, "-2071142389": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "-2071139945": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092663": {"name": "Legendary: The Clipper (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-838272988": {"name": "Legendary: The Horadric Hamburger", "category": "Daggers", "platform": "Console"}, "-1893282128": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1893279684": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1817947684": {"name": "Legendary: The Horadric Hamburger (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-972914792": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-65175862": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-2041494364": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "-2041491920": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092688": {"name": "Legendary: Wizardspike (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934821572": {"name": "Set: Eun-jang-do (Patch 2.2.0)", "category": "Daggers", "platform": "Console"}, "1771748851": {"name": "01: Wooden Bo (DPS 17.1-18.2)", "category": "Daibos", "platform": "Console"}, "1771748852": {"name": "02: Spade (DPS 21.5-23.1)", "category": "Daibos", "platform": "Console"}, "1771748853": {"name": "03: Eiku (DPS 27.5-29.2)", "category": "Daibos", "platform": "Console"}, "1771748854": {"name": "04: Taiji (DPS 41.8-43.5)", "category": "Daibos", "platform": "Console"}, "1771749940": {"name": "05: Jodo Staff (DPS 51.2-52.8)", "category": "Daibos", "platform": "Console"}, "1771749941": {"name": "06: Sibat (DPS 67.1-70.4)", "category": "Daibos", "platform": "Console"}, "1771749942": {"name": "07: Trost (DPS 97.9-101.2)", "category": "Daibos", "platform": "Console"}, "1771749943": {"name": "08: Svardstav (DPS 145.2-150.2)", "category": "Daibos", "platform": "Console"}, "1771751029": {"name": "09: Lathi (DPS 176.6-183.2)", "category": "Daibos", "platform": "Console"}, "1771751030": {"name": "10: Silambam (DPS 220.6-228.8)", "category": "Daibos", "platform": "Console"}, "1771751031": {"name": "11: Drevko (DPS 274.5-284.4)", "category": "Daibos", "platform": "Console"}, "1771751032": {"name": "12: Grand Taiji (DPS 374.6-386.1)", "category": "Daibos", "platform": "Console"}, "1771751033": {"name": "13: Zhezl (DPS 442.2-455.4)", "category": "Daibos", "platform": "Console"}, "1771751034": {"name": "14: Guru Staff (DPS 522.0-535.2)", "category": "Daibos", "platform": "Console"}, "1771752118": {"name": "15: Iron Judgement (DPS 684.3-696.3)", "category": "Daibos", "platform": "Console"}, "1771752119": {"name": "16: Whirlwind Staff (DPS 925.8-937.8)", "category": "Daibos", "platform": "Console"}, "446400306": {"name": "Legendary: Balance", "category": "Daibos", "platform": "Console"}, "1846230910": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "1846233354": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857814": {"name": "Legendary: Balance (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446651865": {"name": "Legendary: Flying Dragon", "category": "Daibos", "platform": "Console"}, "1854532357": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "1854534801": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857807": {"name": "Legendary: Flying Dragon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446436243": {"name": "Legendary: Incense Torch of the Grand Temple", "category": "Daibos", "platform": "Console"}, "1847416831": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "1847419275": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857813": {"name": "Legendary: Incense Torch of the Grand Temple (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446615928": {"name": "Legendary: Lai Yui's Persuader", "category": "Daibos", "platform": "Console"}, "1853346436": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "1853348880": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857808": {"name": "Legendary: Lai Yui's Taiji (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446472180": {"name": "Legendary: Rozpedin's Force", "category": "Daibos", "platform": "Console"}, "1848602752": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "1848605196": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857812": {"name": "Legendary: Rozpedin's Staff (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485499762": {"name": "Legendary: Staff of Kyro", "category": "Daibos", "platform": "Console"}, "1849788673": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "1849791117": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857811": {"name": "Legendary: The Clouds and the Moon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446508117": {"name": "Legendary: The Flow of Eternity", "category": "Daibos", "platform": "Console"}, "446579991": {"name": "Legendary: The Paddle", "category": "Daibos", "platform": "Console"}, "1852160515": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "1852162959": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857809": {"name": "Legendary: The Paddle (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485535699": {"name": "Legendary: Warstaff of General Quang", "category": "Daibos", "platform": "Console"}, "-326857815": {"name": "Set: Inna's Justice (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446364369": {"name": "Set: Inna's Reach", "category": "Daibos", "platform": "Console"}, "1845044989": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "1845047433": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "201941396": {"name": "Debug Axe 001", "category": "Debug", "platform": "Console"}, "201941397": {"name": "Debug Axe 002", "category": "Debug", "platform": "Console"}, "1162537406": {"name": "Debug Bow 001", "category": "Debug", "platform": "Console"}, "-1837157688": {"name": "Debug CrossBow 001", "category": "Debug", "platform": "Console"}, "110611392": {"name": "Debug Dagger 001", "category": "Debug", "platform": "Console"}, "-257486314": {"name": "Debug FistWeapon 001", "category": "Debug", "platform": "Console"}, "-1314119444": {"name": "Debug Mace 001", "category": "Debug", "platform": "Console"}, "-1314119443": {"name": "Debug Mace 002", "category": "Debug", "platform": "Console"}, "-1919522874": {"name": "Debug Polearm 001", "category": "Debug", "platform": "Console"}, "201837585": {"name": "Debug Spear 001", "category": "Debug", "platform": "Console"}, "-1812541014": {"name": "Debug Staff 001", "category": "Debug", "platform": "Console"}, "97851424": {"name": "Debug Wand 001", "category": "Debug", "platform": "Console"}, "109003955": {"name": "Professional Russian's 100 DPS 1H Axe", "category": "Debug", "platform": "Console"}, "1012655083": {"name": "Professional Russian's 100 DPS 1H Mace", "category": "Debug", "platform": "Console"}, "198260772": {"name": "Professional Russian's 100 DPS 1H Sword", "category": "Debug", "platform": "Console"}, "109003988": {"name": "Professional Russian's 100 DPS 2H Axe", "category": "Debug", "platform": "Console"}, "1012655116": {"name": "Professional Russian's 100 DPS 2H Mace", "category": "Debug", "platform": "Console"}, "198260805": {"name": "Professional Russian's 100 DPS 2H Sword", "category": "Debug", "platform": "Console"}, "1565754085": {"name": "Professional Russian's 100 DPS Bow", "category": "Debug", "platform": "Console"}, "1144284824": {"name": "Professional Russian's 100 DPS Crossbow Pistol", "category": "Debug", "platform": "Console"}, "199216263": {"name": "Professional Russian's 100 DPS Dagger", "category": "Debug", "platform": "Console"}, "131016487": {"name": "Professional Russian's 100 DPS Wand", "category": "Debug", "platform": "Console"}, "-268664650": {"name": "Professional Russian's Blind Proc Bow", "category": "Debug", "platform": "Console"}, "-497584419": {"name": "Professional Russian's Blind Proc Sword", "category": "Debug", "platform": "Console"}, "-1692695305": {"name": "Professional Russian's Bow", "category": "Debug", "platform": "Console"}, "-1353182983": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-1489225678": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-422042656": {"name": "Professional Russian's Chill Proc Sword", "category": "Debug", "platform": "Console"}, "860521450": {"name": "Professional Russian's Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-708154023": {"name": "Professional Russian's Dagger", "category": "Debug", "platform": "Console"}, "-813820178": {"name": "Professional Russian's Fast Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-1759844230": {"name": "Professional Russian's Fast Sword", "category": "Debug", "platform": "Console"}, "-1433265027": {"name": "Professional Russian's Fast Wand", "category": "Debug", "platform": "Console"}, "1812597803": {"name": "Professional Russian's Fear Proc Bow", "category": "Debug", "platform": "Console"}, "-1745505390": {"name": "Professional Russian's Fear Proc Sword", "category": "Debug", "platform": "Console"}, "-2004205682": {"name": "Professional Russian's Freeze Proc Bow", "category": "Debug", "platform": "Console"}, "-716158027": {"name": "Professional Russian's Freeze Proc Sword", "category": "Debug", "platform": "Console"}, "-1049148770": {"name": "Professional Russian's Immobilize Proc Bow", "category": "Debug", "platform": "Console"}, "1369510420": {"name": "Professional Russian's Knockback Proc Bow", "category": "Debug", "platform": "Console"}, "1063638971": {"name": "Professional Russian's Knockback Proc Sword", "category": "Debug", "platform": "Console"}, "-798366331": {"name": "Professional Russian's One-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206717": {"name": "Professional Russian's One-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502602": {"name": "Professional Russian's One-Handed Sword", "category": "Debug", "platform": "Console"}, "-395086843": {"name": "Professional Russian's Slow Crossbow Pistol", "category": "Debug", "platform": "Console"}, "1751317849": {"name": "Professional Russian's Slow Proc Sword", "category": "Debug", "platform": "Console"}, "-1341110895": {"name": "Professional Russian's Slow Sword", "category": "Debug", "platform": "Console"}, "-1899067884": {"name": "Professional Russian's Slow Wand", "category": "Debug", "platform": "Console"}, "476722551": {"name": "Professional Russian's Stun Proc Bow", "category": "Debug", "platform": "Console"}, "-41266491": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-519741474": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-798366298": {"name": "Professional Russian's Two-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206750": {"name": "Professional Russian's Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502569": {"name": "Professional Russian's Two-Handed Sword", "category": "Debug", "platform": "Console"}, "-23630983": {"name": "Professional Russian's Wand", "category": "Debug", "platform": "Console"}, "-908294397": {"name": "Shadowclone Ceremonial Knife (Hell)", "category": "Debug", "platform": "Console"}, "2012151919": {"name": "Shadowclone Ceremonial Knife (Inferno)", "category": "Debug", "platform": "Console"}, "754127773": {"name": "Shadowclone Ceremonial Knife (Nightmare)", "category": "Debug", "platform": "Console"}, "-1043228665": {"name": "Shadowclone Ceremonial Knife (Normal)", "category": "Debug", "platform": "Console"}, "-1067377991": {"name": "Shadowclone Crusader Shield", "category": "Debug", "platform": "Console"}, "413641572": {"name": "Shadowclone Daibo (Hell)", "category": "Debug", "platform": "Console"}, "1791808816": {"name": "Shadowclone Daibo (Inferno)", "category": "Debug", "platform": "Console"}, "1318657182": {"name": "Shadowclone Daibo (Nightmare)", "category": "Debug", "platform": "Console"}, "-269002584": {"name": "Shadowclone Daibo (Normal)", "category": "Debug", "platform": "Console"}, "-909812331": {"name": "Shadowclone Hand Crossbow (Hell)", "category": "Debug", "platform": "Console"}, "-998234687": {"name": "Shadowclone Hand Crossbow (Inferno)", "category": "Debug", "platform": "Console"}, "-496839313": {"name": "Shadowclone Hand Crossbow (Nightmare)", "category": "Debug", "platform": "Console"}, "1598708505": {"name": "Shadowclone Hand Crossbow (Normal)", "category": "Debug", "platform": "Console"}, "-1831368437": {"name": "Shadowclone Mojo", "category": "Debug", "platform": "Console"}, "-989882433": {"name": "Shadowclone One-Handed Flail", "category": "Debug", "platform": "Console"}, "318426510": {"name": "Shadowclone Staff (Hell)", "category": "Debug", "platform": "Console"}, "-1157906662": {"name": "Shadowclone Staff (Inferno)", "category": "Debug", "platform": "Console"}, "1714039048": {"name": "Shadowclone Staff (Nightmare)", "category": "Debug", "platform": "Console"}, "-878989998": {"name": "Shadowclone Staff (Normal)", "category": "Debug", "platform": "Console"}, "1875985680": {"name": "Shadowclone Two-Handed Mighty Weapon (Hell)", "category": "Debug", "platform": "Console"}, "832184156": {"name": "Shadowclone Two-Handed Mighty Weapon (Inferno)", "category": "Debug", "platform": "Console"}, "-35544630": {"name": "Shadowclone Two-Handed Mighty Weapon (Nightmare)", "category": "Debug", "platform": "Console"}, "-1209135788": {"name": "Shadowclone Two-Handed Mighty Weapon (Normal)", "category": "Debug", "platform": "Console"}, "2099757732": {"name": "ThorTest Bow", "category": "Debug", "platform": "Console"}, "-163370651": {"name": "ThorTest Ceremonial Dagger", "category": "Debug", "platform": "Console"}, "1291822630": {"name": "ThorTest CombatStaff", "category": "Debug", "platform": "Console"}, "-1647832978": {"name": "ThorTest Crossbow", "category": "Debug", "platform": "Console"}, "774399974": {"name": "ThorTest Dagger", "category": "Debug", "platform": "Console"}, "726818364": {"name": "ThorTest FistWeapon", "category": "Debug", "platform": "Console"}, "454120887": {"name": "ThorTest Hand Crossbow", "category": "Debug", "platform": "Console"}, "572923409": {"name": "ThorTest Mojo", "category": "Debug", "platform": "Console"}, "684187666": {"name": "ThorTest One-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118934": {"name": "ThorTest One-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530416": {"name": "ThorTest One-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903165": {"name": "ThorTest One-Handed Sword", "category": "Debug", "platform": "Console"}, "2099771967": {"name": "ThorTest Orb", "category": "Debug", "platform": "Console"}, "-1343109204": {"name": "ThorTest Polearm", "category": "Debug", "platform": "Console"}, "1306966712": {"name": "ThorTest Quiver", "category": "Debug", "platform": "Console"}, "1369802229": {"name": "ThorTest Shield", "category": "Debug", "platform": "Console"}, "1733748983": {"name": "ThorTest Spear", "category": "Debug", "platform": "Console"}, "1733888528": {"name": "ThorTest Staff", "category": "Debug", "platform": "Console"}, "684187699": {"name": "ThorTest Two-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118901": {"name": "ThorTest Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530383": {"name": "ThorTest Two-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903132": {"name": "ThorTest Two-Handed Sword", "category": "Debug", "platform": "Console"}, "573267654": {"name": "ThorTest Wand", "category": "Debug", "platform": "Console"}, "-234196765": {"name": "Abyssal Dye", "category": "Dyes", "platform": "Console"}, "-575184703": {"name": "All-Soap's Miraculous Dye Remover", "category": "Dyes", "platform": "Console"}, "-234196827": {"name": "Aquatic Dye", "category": "Dyes", "platform": "Console"}, "-234196822": {"name": "Autumn Dye", "category": "Dyes", "platform": "Console"}, "1866876233": {"name": "Bottled Cloud", "category": "Dyes", "platform": "Console"}, "1866876234": {"name": "Bottled Smoke", "category": "Dyes", "platform": "Console"}, "-234196826": {"name": "Cardinal Dye", "category": "Dyes", "platform": "Console"}, "-234196823": {"name": "Desert Dye", "category": "Dyes", "platform": "Console"}, "-234196795": {"name": "Elegant Dye", "category": "Dyes", "platform": "Console"}, "-234196794": {"name": "Forester's Dye", "category": "Dyes", "platform": "Console"}, "-234196792": {"name": "Golden Dye", "category": "Dyes", "platform": "Console"}, "-234196790": {"name": "Infernal Dye", "category": "Dyes", "platform": "Console"}, "-234196798": {"name": "Lovely Dye", "category": "Dyes", "platform": "Console"}, "-234196793": {"name": "Mariner's Dye", "category": "Dyes", "platform": "Console"}, "-234196789": {"name": "Purity Dye", "category": "Dyes", "platform": "Console"}, "-234196825": {"name": "Ranger's Dye", "category": "Dyes", "platform": "Console"}, "-234196791": {"name": "Royal Dye", "category": "Dyes", "platform": "Console"}, "-234196796": {"name": "Spring Dye", "category": "Dyes", "platform": "Console"}, "-234196797": {"name": "Summer Dye", "category": "Dyes", "platform": "Console"}, "-234196830": {"name": "Tanner's Dye", "category": "Dyes", "platform": "Console"}, "-2000448920": {"name": "Vanishing Dye", "category": "Dyes", "platform": "Console"}, "-234196828": {"name": "Winter Dye", "category": "Dyes", "platform": "Console"}, "761436846": {"name": "01: Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761436847": {"name": "02: Eye", "category": "Enchantress Focuses", "platform": "Console"}, "761437935": {"name": "03: Scrying Glass", "category": "Enchantress Focuses", "platform": "Console"}, "761437936": {"name": "04: Blink", "category": "Enchantress Focuses", "platform": "Console"}, "761437937": {"name": "05: Crucible", "category": "Enchantress Focuses", "platform": "Console"}, "761437938": {"name": "06: Root", "category": "Enchantress Focuses", "platform": "Console"}, "761439024": {"name": "07: Eternity Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761439025": {"name": "08: Oculus", "category": "Enchantress Focuses", "platform": "Console"}, "761439026": {"name": "09: Cauldron", "category": "Enchantress Focuses", "platform": "Console"}, "761439027": {"name": "10: Herb", "category": "Enchantress Focuses", "platform": "Console"}, "761439028": {"name": "11: Anamorphosis", "category": "Enchantress Focuses", "platform": "Console"}, "761439029": {"name": "12: Augur", "category": "Enchantress Focuses", "platform": "Console"}, "-450681607": {"name": "Legendary: Hand of the Prophet", "category": "Enchantress Focuses", "platform": "Console"}, "-450681608": {"name": "Legendary: Smoking Thurible", "category": "Enchantress Focuses", "platform": "Console"}, "-450681606": {"name": "Legendary: Vadim's Surge", "category": "Enchantress Focuses", "platform": "Console"}, "1236604967": {"name": "00: Worn Knuckles (DPS 3.0)", "category": "Fist Weapons", "platform": "Console"}, "1236604968": {"name": "01: Knuckles (DPS 7.0-8.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604969": {"name": "02: Spikes (DPS 15.4-17.5)", "category": "Fist Weapons", "platform": "Console"}, "1236604970": {"name": "03: Talon (DPS 20.3-22.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604971": {"name": "04: Shuko (DPS 29.4-31.5)", "category": "Fist Weapons", "platform": "Console"}, "1236606057": {"name": "05: Breaker (DPS 38.5-40.6)", "category": "Fist Weapons", "platform": "Console"}, "1236606058": {"name": "06: Iron Fist (DPS 46.2-48.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606059": {"name": "07: Claw (DPS 60.2-62.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606060": {"name": "08: Kastet (DPS 81.2-83.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607146": {"name": "09: Grappler (DPS 106.4-110.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607147": {"name": "10: Hammer Hand (DPS 130.2-134.4)", "category": "Fist Weapons", "platform": "Console"}, "1236607148": {"name": "11: Demon Fang (DPS 156.8-163.1)", "category": "Fist Weapons", "platform": "Console"}, "1236607149": {"name": "12: Pulverizer (DPS 181.3-187.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607150": {"name": "13: Golden Talon (DPS 210.0-216.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607151": {"name": "14: Heaven Hand (DPS 242.2-248.5)", "category": "Fist Weapons", "platform": "Console"}, "1236608235": {"name": "15: Spiked Fist (DPS 322.0-328.3)", "category": "Fist Weapons", "platform": "Console"}, "1236608236": {"name": "16: Suwaiya (DPS 392.0-398.3)", "category": "Fist Weapons", "platform": "Console"}, "1349166155": {"name": "Art Test Fist 1", "category": "Fist Weapons", "platform": "Console"}, "1349166156": {"name": "Art Test Fist 2", "category": "Fist Weapons", "platform": "Console"}, "1349166157": {"name": "Art Test Fist 3", "category": "Fist Weapons", "platform": "Console"}, "1349166158": {"name": "Art Test Fist 4", "category": "Fist Weapons", "platform": "Console"}, "1349166159": {"name": "Art Test Fist 5", "category": "Fist Weapons", "platform": "Console"}, "-1097629365": {"name": "Legendary: Crystal Fist", "category": "Fist Weapons", "platform": "Console"}, "-1862107977": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1862105533": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690589": {"name": "Legendary: Crystal Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "2032005920": {"name": "Legendary: Deathreach", "category": "Fist Weapons", "platform": "Console"}, "-1097773113": {"name": "Legendary: Demon Claw", "category": "Fist Weapons", "platform": "Console"}, "-1866851661": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1866849217": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690593": {"name": "Legendary: Demon Hand (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058709594": {"name": "Legendary: Falcon Strike", "category": "Fist Weapons", "platform": "Console"}, "537275943": {"name": "Legendary: Fist Weapon of the Shattered Hand (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097665302": {"name": "Legendary: Fleshrake", "category": "Fist Weapons", "platform": "Console"}, "-1863293898": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1863291454": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690590": {"name": "Legendary: Fleshrake (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058745531": {"name": "Legendary: Jawbreaker", "category": "Fist Weapons", "platform": "Console"}, "-1097737176": {"name": "Legendary: Logan's Claw", "category": "Fist Weapons", "platform": "Console"}, "-1865665740": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1865663296": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690592": {"name": "Legendary: Logan's Claw (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097809050": {"name": "Legendary: Rabid Strike", "category": "Fist Weapons", "platform": "Console"}, "-1868037582": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1868035138": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690594": {"name": "Legendary: Rabid Strike (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096623129": {"name": "Legendary: Scarbringer", "category": "Fist Weapons", "platform": "Console"}, "-1828902189": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1828899745": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690561": {"name": "Legendary: Scarbringer (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096659066": {"name": "Legendary: Sledge Fist", "category": "Fist Weapons", "platform": "Console"}, "-1830088110": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1830085666": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690562": {"name": "Legendary: Sledge Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097593428": {"name": "Legendary: The Fist of Az'Turrasq", "category": "Fist Weapons", "platform": "Console"}, "-1860922056": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1860919612": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690588": {"name": "Legendary: The Fist of Az'Turrasq (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132078": {"name": "Legendary: Vengeful Wind (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097701239": {"name": "Legendary: Won Khim Lau", "category": "Fist Weapons", "platform": "Console"}, "-1864479819": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1864477375": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690591": {"name": "Legendary: Won Khim Lau (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132079": {"name": "P1 fistWeapon norm Legendary 01", "category": "Fist Weapons", "platform": "Console"}, "-1826530347": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1826527903": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096551255": {"name": "Set: Hallowed Hold", "category": "Fist Weapons", "platform": "Console"}, "-840690559": {"name": "Set: Hallowed Touch (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690563": {"name": "Set: Shenlong's Crashing Tide (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690564": {"name": "Set: Shenlong's Endless Wave (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096695003": {"name": "Set: Shenlong's Fist of Legend", "category": "Fist Weapons", "platform": "Console"}, "-1831274031": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1831271587": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096730940": {"name": "Set: Shenlong's Relentless Assault", "category": "Fist Weapons", "platform": "Console"}, "-1832459952": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1832457508": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-912456881": {"name": "00: Rusty Flail (DPS 3.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456880": {"name": "01: Spiked Flail (DPS 7.7-9.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456879": {"name": "02: Iron Whip (DPS 13.3-15.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456878": {"name": "03: Barbed Flail (DPS 18.9-21.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456877": {"name": "04: Thresher (DPS 25.2-27.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456876": {"name": "05: Flail (DPS 30.8-32.9)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455791": {"name": "06: Ball and Chain (DPS 35.0-37.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455790": {"name": "07: Chain Mace (DPS 43.4-45.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455789": {"name": "08: Shredder (DPS 53.2-55.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455788": {"name": "09: Imposing Flail (DPS 71.4-73.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455787": {"name": "10: Royal Guardian (DPS 105.0-109.2)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454702": {"name": "11: Painbringer (DPS 119.0-125.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454701": {"name": "12: Knout (DPS 139.3-145.6)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454700": {"name": "13: Wicked Flail (DPS 177.1-183.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454699": {"name": "14: Giant's Flail (DPS 312.9-321.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454698": {"name": "15: Grandfather's Flail (DPS 382.9-391.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955915": {"name": "Art Test Flails One-Handed 1", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955914": {"name": "Art Test Flails One-Handed 2", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955913": {"name": "Art Test Flails One-Handed 3", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955912": {"name": "Art Test Flails One-Handed 4", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955911": {"name": "Art Test Flails One-Handed 5", "category": "Flails, One-Handed", "platform": "Console"}, "-1791015660": {"name": "Legendary: Darklight", "category": "Flails, One-Handed", "platform": "Console"}, "-1791195345": {"name": "Legendary: Golden Scourge", "category": "Flails, One-Handed", "platform": "Console"}, "-1791051597": {"name": "Legendary: Gyrfalcon's Foote", "category": "Flails, One-Handed", "platform": "Console"}, "-1790979723": {"name": "Legendary: Inviolable Faith", "category": "Flails, One-Handed", "platform": "Console"}, "-1791159408": {"name": "Legendary: Justinian's Mercy", "category": "Flails, One-Handed", "platform": "Console"}, "-1791087534": {"name": "Legendary: Kassar's Retribution", "category": "Flails, One-Handed", "platform": "Console"}, "1226090826": {"name": "Legendary: Mortal Coil", "category": "Flails, One-Handed", "platform": "Console"}, "-1791123471": {"name": "Legendary: Swiftmount", "category": "Flails, One-Handed", "platform": "Console"}, "1784501906": {"name": "P1 Flails1H norm Legendary 01", "category": "Flails, One-Handed", "platform": "Console"}, "-873321487": {"name": "01: Chang Xiao Bang (DPS 9.2-10.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321486": {"name": "02: Battle Flail (DPS 15.0-16.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321485": {"name": "03: Grand Thresher (DPS 22.4-24.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321484": {"name": "04: Two-Handed Flail (DPS 29.3-31.1)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321483": {"name": "05: Castigator (DPS 37.4-40.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320398": {"name": "06: Pyeongon (DPS 51.8-55.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320397": {"name": "07: Chigiriki (DPS 65.0-70.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320396": {"name": "08: Threshal (DPS 81.7-86.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320395": {"name": "09: Grand Flail (DPS 102.9-109.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320394": {"name": "10: Angelic Flail (DPS 146.1-154.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319309": {"name": "11: Campaigner's Grand Flail (DPS 194.4-206.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319308": {"name": "12: Bludgeoning Grand Flail (DPS 261.6-275.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319307": {"name": "13: Painbringer Grand Flail (DPS 333.5-347.3)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319306": {"name": "14: Baroque Grand Flail (DPS 648.0-661.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319305": {"name": "15: Angelic Grand Flail (DPS 878.0-891.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919978": {"name": "Art Test Flails Two-Handed 1", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919977": {"name": "Art Test Flails Two-Handed 2", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919976": {"name": "Art Test Flails Two-Handed 3", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919975": {"name": "Art Test Flails Two-Handed 4", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919974": {"name": "Art Test Flails Two-Handed 5", "category": "Flails, Two-Handed", "platform": "Console"}, "163153041": {"name": "Legendary: Baleful Remnant", "category": "Flails, Two-Handed", "platform": "Console"}, "163188978": {"name": "Legendary: Fate of the Fell", "category": "Flails, Two-Handed", "platform": "Console"}, "163224915": {"name": "Legendary: Golden Flense", "category": "Flails, Two-Handed", "platform": "Console"}, "163117104": {"name": "Legendary: The Mortal Drama", "category": "Flails, Two-Handed", "platform": "Console"}, "1784501907": {"name": "P1 Flails1H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712685": {"name": "P1 Flails2H norm Legendary 01", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712684": {"name": "P1 Flails2H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-1026738420": {"name": "legendary: Golden Flense (Patch 2.2.0)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1411866897": {"name": "Amethyst 01: Chipped Amethyst", "category": "Gems", "platform": "Console"}, "-1411866896": {"name": "Amethyst 02: Flawed Amethyst", "category": "Gems", "platform": "Console"}, "-1411866895": {"name": "Amethyst 03: Amethyst", "category": "Gems", "platform": "Console"}, "-1411866894": {"name": "Amethyst 04: Flawless Amethyst", "category": "Gems", "platform": "Console"}, "-1411866893": {"name": "Amethyst 05: Perfect Amethyst", "category": "Gems", "platform": "Console"}, "-1411866892": {"name": "Amethyst 06: Radiant Amethyst", "category": "Gems", "platform": "Console"}, "-1411866891": {"name": "Amethyst 07: Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866890": {"name": "Amethyst 08: Flawless Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866889": {"name": "Amethyst 09: Perfect Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866865": {"name": "Amethyst 10: Radiant Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866864": {"name": "Amethyst 11: Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866863": {"name": "Amethyst 12: Flawless Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866862": {"name": "Amethyst 13: Perfect Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866861": {"name": "Amethyst 14: Radiant Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866860": {"name": "Amethyst 15: Marquise Amethyst", "category": "Gems", "platform": "Console"}, "-1411866859": {"name": "Amethyst 16: Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866858": {"name": "Amethyst 17: Flawless Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866857": {"name": "Amethyst 18: Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1411866856": {"name": "Amethyst 19: Flawless Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1315690660": {"name": "Diamond 01: Chipped Diamond", "category": "Gems", "platform": "Console"}, "-1315690659": {"name": "Diamond 02: Flawed Diamond", "category": "Gems", "platform": "Console"}, "-1315690658": {"name": "Diamond 03: Diamond", "category": "Gems", "platform": "Console"}, "-1315690657": {"name": "Diamond 04: Flawless Diamond", "category": "Gems", "platform": "Console"}, "-1315690656": {"name": "Diamond 05: Perfect Diamond", "category": "Gems", "platform": "Console"}, "-1315690655": {"name": "Diamond 06: Radiant Diamond", "category": "Gems", "platform": "Console"}, "-1315690654": {"name": "Diamond 07: Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690653": {"name": "Diamond 08: Flawless Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690652": {"name": "Diamond 09: Perfect Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690628": {"name": "Diamond 10: Radiant Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690627": {"name": "Diamond 11: Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690626": {"name": "Diamond 12: Flawless Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690625": {"name": "Diamond 13: Perfect Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690624": {"name": "Diamond 14: Radiant Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690623": {"name": "Diamond 15: Marquise Diamond", "category": "Gems", "platform": "Console"}, "-1315690622": {"name": "Diamond 16: Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690621": {"name": "Diamond 17: Flawless Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690620": {"name": "Diamond 18: Royal Diamond", "category": "Gems", "platform": "Console"}, "-1315690619": {"name": "Diamond 19: Flawless Royal Diamond", "category": "Gems", "platform": "Console"}, "-1733388806": {"name": "Emerald 01: Chipped Emerald", "category": "Gems", "platform": "Console"}, "-1733388805": {"name": "Emerald 02: Flawed Emerald", "category": "Gems", "platform": "Console"}, "-1733388804": {"name": "Emerald 03: Emerald", "category": "Gems", "platform": "Console"}, "-1733388803": {"name": "Emerald 04: Flawless Emerald", "category": "Gems", "platform": "Console"}, "-1733388802": {"name": "Emerald 05: Perfect Emerald", "category": "Gems", "platform": "Console"}, "-1733388801": {"name": "Emerald 06: Radiant Emerald", "category": "Gems", "platform": "Console"}, "-1733388800": {"name": "Emerald 07: Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388799": {"name": "Emerald 08: Flawless Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388798": {"name": "Emerald 09: Perfect Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388774": {"name": "Emerald 10: Radiant Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388773": {"name": "Emerald 11: Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388772": {"name": "Emerald 12: Flawless Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388771": {"name": "Emerald 13: Perfect Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388770": {"name": "Emerald 14: Radiant Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388769": {"name": "Emerald 15: Marquise Emerald", "category": "Gems", "platform": "Console"}, "-1733388768": {"name": "Emerald 16: Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388767": {"name": "Emerald 17: Flawless Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388766": {"name": "Emerald 18: Royal Emerald", "category": "Gems", "platform": "Console"}, "-1733388765": {"name": "Emerald 19: Flawless Royal Emerald", "category": "Gems", "platform": "Console"}, "-1046455929": {"name": "Legendary: Bane of the Powerful (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046419992": {"name": "Legendary: Bane of the Trapped (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045162197": {"name": "Legendary: Boon of the Hoarder (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045305945": {"name": "Legendary: Enforcer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045090323": {"name": "Legendary: Esoteric Alteration (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1044084087": {"name": "Legendary: Gem Of X NYI (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046312181": {"name": "Legendary: Gem of Efficacious Toxin (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046384055": {"name": "Legendary: Gem of Reduced Level Requirement (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046204370": {"name": "Legendary: Gogok of Swiftness (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046168433": {"name": "Legendary: Invigorating Gemstone (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046240307": {"name": "Legendary: Mirinae, Teardrop of the Starweaver (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045054386": {"name": "Legendary: Molten Wildebeest's Gizzard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045270008": {"name": "Legendary: Moratorium (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044982512": {"name": "Legendary: Mutilation Guard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046276244": {"name": "Legendary: Pain Enhancer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044120024": {"name": "Legendary: Shen's Delight (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045198134": {"name": "Legendary: Simplicity's Strength (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045018449": {"name": "Legendary: Stone Of Heresy (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045126260": {"name": "Legendary: Taeguk (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046348118": {"name": "Legendary: Wreath of Lightning (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045234071": {"name": "Legendary: Zei's Stone of Vengeance (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "1603007810": {"name": "Ruby 01: Chipped Ruby", "category": "Gems", "platform": "Console"}, "1603007811": {"name": "Ruby 02: Flawed Ruby", "category": "Gems", "platform": "Console"}, "1603007812": {"name": "Ruby 03: Ruby", "category": "Gems", "platform": "Console"}, "1603007813": {"name": "Ruby 04: Flawless Ruby", "category": "Gems", "platform": "Console"}, "1603007814": {"name": "Ruby 05: Perfect Ruby", "category": "Gems", "platform": "Console"}, "1603007815": {"name": "Ruby 06: Radiant Ruby", "category": "Gems", "platform": "Console"}, "1603007816": {"name": "Ruby 07: Square Ruby", "category": "Gems", "platform": "Console"}, "1603007817": {"name": "Ruby 08: Flawless Square Ruby", "category": "Gems", "platform": "Console"}, "1603007818": {"name": "Ruby 09: Perfect Square Ruby", "category": "Gems", "platform": "Console"}, "1603007842": {"name": "Ruby 10: Radiant Square Ruby", "category": "Gems", "platform": "Console"}, "1603007843": {"name": "Ruby 11: Star Ruby", "category": "Gems", "platform": "Console"}, "1603007844": {"name": "Ruby 12: Flawless Star Ruby", "category": "Gems", "platform": "Console"}, "1603007845": {"name": "Ruby 13: Perfect Star Ruby", "category": "Gems", "platform": "Console"}, "1603007846": {"name": "Ruby 14: Radiant Star Ruby", "category": "Gems", "platform": "Console"}, "1603007847": {"name": "Ruby 15: Marquise Ruby", "category": "Gems", "platform": "Console"}, "1603007848": {"name": "Ruby 16: Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007849": {"name": "Ruby 17: Flawless Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007850": {"name": "Ruby 18: Royal Ruby", "category": "Gems", "platform": "Console"}, "1603007851": {"name": "Ruby 19: Flawless Royal Ruby", "category": "Gems", "platform": "Console"}, "2058771886": {"name": "Topaz 01: Chipped Topaz", "category": "Gems", "platform": "Console"}, "2058771887": {"name": "Topaz 02: Flawed Topaz", "category": "Gems", "platform": "Console"}, "2058771888": {"name": "Topaz 03: Topaz", "category": "Gems", "platform": "Console"}, "2058771889": {"name": "Topaz 04: Flawless Topaz", "category": "Gems", "platform": "Console"}, "2058771890": {"name": "Topaz 05: Perfect Topaz", "category": "Gems", "platform": "Console"}, "2058771891": {"name": "Topaz 06: Radiant Topaz", "category": "Gems", "platform": "Console"}, "2058771892": {"name": "Topaz 07: Square Topaz", "category": "Gems", "platform": "Console"}, "2058771893": {"name": "Topaz 08: Flawless Square Topaz", "category": "Gems", "platform": "Console"}, "2058771894": {"name": "Topaz 09: Perfect Square Topaz", "category": "Gems", "platform": "Console"}, "2058771918": {"name": "Topaz 10: Radiant Square Topaz", "category": "Gems", "platform": "Console"}, "2058771919": {"name": "Topaz 11: Star Topaz", "category": "Gems", "platform": "Console"}, "2058771920": {"name": "Topaz 12: Flawless Star Topaz", "category": "Gems", "platform": "Console"}, "2058771921": {"name": "Topaz 13: Perfect Star Topaz", "category": "Gems", "platform": "Console"}, "2058771922": {"name": "Topaz 14: Radiant Star Topaz", "category": "Gems", "platform": "Console"}, "2058771923": {"name": "Topaz 15: Marquise Topaz", "category": "Gems", "platform": "Console"}, "2058771924": {"name": "Topaz 16: Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771925": {"name": "Topaz 17: Flawless Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771926": {"name": "Topaz 18: Royal Topaz", "category": "Gems", "platform": "Console"}, "2058771927": {"name": "Topaz 19: Flawless Royal Topaz", "category": "Gems", "platform": "Console"}, "-1533914304": {"name": "01: Gloves (AR 4-5)", "category": "Gloves", "platform": "Console"}, "-1533914303": {"name": "02: Leather Gloves (AR 14-16)", "category": "Gloves", "platform": "Console"}, "-1533914302": {"name": "03: Hide Gloves (AR 28-32)", "category": "Gloves", "platform": "Console"}, "-1533914301": {"name": "04: Chain Gloves (AR 42-55)", "category": "Gloves", "platform": "Console"}, "-1533914300": {"name": "05: Gauntlets (AR 56-69)", "category": "Gloves", "platform": "Console"}, "-1533914299": {"name": "06: Plated Gauntlets (AR 70-88)", "category": "Gloves", "platform": "Console"}, "-1533913215": {"name": "07: Grips (AR 88-106)", "category": "Gloves", "platform": "Console"}, "-1533913214": {"name": "08: Etched Gloves (AR 107-125)", "category": "Gloves", "platform": "Console"}, "-1533913213": {"name": "09: Vambraces (AR 126-144)", "category": "Gloves", "platform": "Console"}, "-1533913212": {"name": "10: Battle Gauntlets (AR 144-173)", "category": "Gloves", "platform": "Console"}, "-1533913211": {"name": "11: Boneweave Gauntlets (AR 175-192)", "category": "Gloves", "platform": "Console"}, "-1533912126": {"name": "12: Balor Fists (AR 192-209)", "category": "Gloves", "platform": "Console"}, "-1533912125": {"name": "13: Manifers (AR 210-221)", "category": "Gloves", "platform": "Console"}, "-1533912124": {"name": "14: Warlord Gauntlets (AR 221-249)", "category": "Gloves", "platform": "Console"}, "-1533912123": {"name": "15: Stranglers (AR 250-278)", "category": "Gloves", "platform": "Console"}, "-1533912122": {"name": "16: Sovereign Vambraces (AR 280-308)", "category": "Gloves", "platform": "Console"}, "-1533912121": {"name": "17: Archon Gauntlets (AR 309-366)", "category": "Gloves", "platform": "Console"}, "-1533912120": {"name": "18: Rakkisgard Gauntlets (AR 367-512)", "category": "Gloves", "platform": "Console"}, "-1533912119": {"name": "19: Ascended Gauntlets (AR 513-590)", "category": "Gloves", "platform": "Console"}, "-542544859": {"name": "Art Test Gloves 1", "category": "Gloves", "platform": "Console"}, "-542544858": {"name": "Art Test Gloves 2", "category": "Gloves", "platform": "Console"}, "-542544857": {"name": "Art Test Gloves 3", "category": "Gloves", "platform": "Console"}, "-542544856": {"name": "Art Test Gloves 4", "category": "Gloves", "platform": "Console"}, "-542544855": {"name": "Art Test Gloves 5", "category": "Gloves", "platform": "Console"}, "-724111115": {"name": "Art_Test_Gloves_10 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-724111114": {"name": "Art_Test_Gloves_11 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544854": {"name": "Art_Test_Gloves_6 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544853": {"name": "Art_Test_Gloves_7 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544852": {"name": "Art_Test_Gloves_8 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544851": {"name": "Art_Test_Gloves_9 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "509897201": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "742334711": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "614385664": {"name": "Legendary: Alabaster Gloves", "category": "Gloves", "platform": "Console"}, "-935578501": {"name": "Legendary: Conqueror's Gauntlets (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "575250271": {"name": "Legendary: Frostburn", "category": "Gloves", "platform": "Console"}, "1803312459": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1803314903": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593655": {"name": "Legendary: Frostburn Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576400255": {"name": "Legendary: Gladiator Gauntlets", "category": "Gloves", "platform": "Console"}, "1841261931": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1841264375": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593687": {"name": "Legendary: Gladiator Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "614421601": {"name": "Legendary: Gloves of Worship", "category": "Gloves", "platform": "Console"}, "204261921": {"name": "Legendary: Grips of Perilous Ascent", "category": "Gloves", "platform": "Console"}, "576508066": {"name": "Legendary: Magefist", "category": "Gloves", "platform": "Console"}, "1844819694": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "1844822138": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "880593690": {"name": "Legendary: Magefist (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1802126538": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "1802128982": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "880593654": {"name": "Legendary: Pendergrasps (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575214334": {"name": "Legendary: Penders Purchase", "category": "Gloves", "platform": "Console"}, "614349727": {"name": "Legendary: St. Archew's Gage", "category": "Gloves", "platform": "Console"}, "575429956": {"name": "Legendary: Stone Gauntlets", "category": "Gloves", "platform": "Console"}, "1809242064": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1809244508": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593660": {"name": "Legendary: Stone Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575286208": {"name": "Legendary: Tasker and Theo", "category": "Gloves", "platform": "Console"}, "1804498380": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "1804500824": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "880593656": {"name": "Legendary: Tasker and Theo (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "880593662": {"name": "Set: Asheara's Clasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1811613906": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "1811616350": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "575501830": {"name": "Set: Asheara's Ward", "category": "Gloves", "platform": "Console"}, "1846005615": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "1846008059": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "576544003": {"name": "Set: Cain's Scrivener", "category": "Gloves", "platform": "Console"}, "880593691": {"name": "Set: Cain's Warmers (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "2058321365": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058321364": {"name": "Set: Fiendish Grips (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058285427": {"name": "Set: Fierce Gauntlets (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058429438": {"name": "Set: Firebird's Talons", "category": "Gloves", "platform": "Console"}, "2058501312": {"name": "Set: Fists of Thunder", "category": "Gloves", "platform": "Console"}, "2058249490": {"name": "Set: Gauntlet of the Wastes (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059399737": {"name": "Set: Gauntlets of Akkhan", "category": "Gloves", "platform": "Console"}, "2059615359": {"name": "Set: Helltooth Gauntlets", "category": "Gloves", "platform": "Console"}, "880593661": {"name": "Set: Immortal King's Forge (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575465893": {"name": "Set: Immortal King's Irons", "category": "Gloves", "platform": "Console"}, "1810427985": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "1810430429": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "-206156950": {"name": "Set: Inna's Hold (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058537249": {"name": "Set: Jade Harvester's Mercy", "category": "Gloves", "platform": "Console"}, "2058465375": {"name": "Set: Marauder's Gloves", "category": "Gloves", "platform": "Console"}, "2058249491": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156953": {"name": "Set: Natalya's Touch (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059471611": {"name": "Set: Pride of the Invoker", "category": "Gloves", "platform": "Console"}, "2059579422": {"name": "Set: Pull of the Earth", "category": "Gloves", "platform": "Console"}, "2058393501": {"name": "Set: Raekor's Wraps", "category": "Gloves", "platform": "Console"}, "2058249489": {"name": "Set: Roland's Grasp (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "1848377457": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "1848379901": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "880593693": {"name": "Set: Sage's Grasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576615877": {"name": "Set: Sage's Purchase", "category": "Gloves", "platform": "Console"}, "2059435674": {"name": "Set: Sunwuko's Paws", "category": "Gloves", "platform": "Console"}, "-206156952": {"name": "Set: Tal Rasha's Grasp (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059543485": {"name": "Set: The Shadow's Grasp", "category": "Gloves", "platform": "Console"}, "2059507548": {"name": "Set: Vyr's Grasping Gauntlets", "category": "Gloves", "platform": "Console"}, "2058285428": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156951": {"name": "Set: Zunimassa's Finger Wraps (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "614349464": {"name": "legendary: St. Archew's Gage (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-363391670": {"name": "00: Initiate's Hand Crossbow (DPS 3.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363391669": {"name": "01: Simple Hand Crossbow (DPS 12.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363391668": {"name": "02: Light Hand Crossbow (DPS 11.2-13.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363391667": {"name": "03: Stake Thrower (DPS 12.8-15.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391666": {"name": "04: Hand Crossbow (DPS 16.0-18.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391665": {"name": "05: Slinglock (DPS 20.8-23.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391664": {"name": "06: Quillshot (DPS 24.0-26.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391663": {"name": "07: Nail Spitter (DPS 28.0-30.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391662": {"name": "08: Heavy Stake Thrower (DPS 32.8-35.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390580": {"name": "09: Sling Pistol (DPS 38.4-40.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363390579": {"name": "10: Crosslock (DPS 44.0-46.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390578": {"name": "11: Siege Lock (DPS 48.8-51.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390577": {"name": "12: Arcus (DPS 60.0-62.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390576": {"name": "13: Cranequin (DPS 65.6-68.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390575": {"name": "14: Spine Thrower (DPS 76.8-79.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390574": {"name": "15: Heavy Arcus (DPS 85.6-88.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390573": {"name": "16: Bolt Rack (DPS 98.4-100.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389491": {"name": "17: Runic Sling Pistol (DPS 113.6-116.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389490": {"name": "18: Splinter Shot (DPS 127.2-129.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389489": {"name": "19: Windlash (DPS 139.2-141.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389488": {"name": "20: Blade Spitter (DPS 154.4-156.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389487": {"name": "21: Heavy Cranequin (DPS 170.4-172.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389486": {"name": "22: Runic Arcus (DPS 196.8-199.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363389485": {"name": "23: Impellor (DPS 225.6-228.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389484": {"name": "24: Exorcist (DPS 258.4-263.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388402": {"name": "25: Lionblade Bow (DPS 516.8-519.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388401": {"name": "26: Penetrator (DPS 672.0-674.4)", "category": "Hand Crossbows", "platform": "Console"}, "1203045553": {"name": "Art Test Hand Crossbow 2", "category": "Hand Crossbows", "platform": "Console"}, "1203045554": {"name": "Art Test Hand Crossbow 3", "category": "Hand Crossbows", "platform": "Console"}, "1203045555": {"name": "Art Test Hand Crossbow 4", "category": "Hand Crossbows", "platform": "Console"}, "1203045556": {"name": "Art Test Hand Crossbow 5", "category": "Hand Crossbows", "platform": "Console"}, "1203045552": {"name": "Art Test HandCrossbow 1", "category": "Hand Crossbows", "platform": "Console"}, "-1153493044": {"name": "Legendary: Balefire Caster", "category": "Hand Crossbows", "platform": "Console"}, "589357912": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "589360356": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789444": {"name": "Legendary: Balefire Caster (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153493308": {"name": "Legendary: Balefire Caster (Patch 2.1.0)", "category": "Hand Crossbows", "platform": "Console"}, "-1153421170": {"name": "Legendary: Blitzbolter", "category": "Hand Crossbows", "platform": "Console"}, "-1152378997": {"name": "Legendary: Calamity", "category": "Hand Crossbows", "platform": "Console"}, "626121463": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "626123907": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789475": {"name": "Legendary: Calamity (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153385233": {"name": "Legendary: Dawn", "category": "Hand Crossbows", "platform": "Console"}, "592915675": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "592918119": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789447": {"name": "Legendary: Dawn (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591729754": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591732198": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789446": {"name": "Legendary: Deadeye (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114429525": {"name": "Legendary: Helltrapper", "category": "Hand Crossbows", "platform": "Console"}, "-1153457107": {"name": "Legendary: Izzuccob", "category": "Hand Crossbows", "platform": "Console"}, "590543833": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "590546277": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789445": {"name": "Legendary: Izzuccob (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114465462": {"name": "Legendary: K'mar Tenclip", "category": "Hand Crossbows", "platform": "Console"}, "-44923323": {"name": "Legendary: Quietus", "category": "Hand Crossbows", "platform": "Console"}, "-1266666515": {"name": "P2 Hand Crossbow norm Legendary 01", "category": "Hand Crossbows", "platform": "Console"}, "-1266666514": {"name": "P2 Hand Crossbow norm Legendary 02", "category": "Hand Crossbows", "platform": "Console"}, "-1266666513": {"name": "P2 Hand Crossbow norm Legendary 03", "category": "Hand Crossbows", "platform": "Console"}, "515789442": {"name": "Set: Danetta's Fury (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789441": {"name": "Set: Danetta's Rage (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153564918": {"name": "Set: Danetta's Revenge", "category": "Hand Crossbows", "platform": "Console"}, "586986070": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "586988514": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153600855": {"name": "Set: Danetta's Spite", "category": "Hand Crossbows", "platform": "Console"}, "585800149": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "585802593": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789479": {"name": "Set: Hallowed Avenger (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1152235249": {"name": "Set: Hallowed Condemnation", "category": "Hand Crossbows", "platform": "Console"}, "630865147": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "630867591": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789443": {"name": "Set: Natalya's Redemption (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153528981": {"name": "Set: Natalya's Slayer", "category": "Hand Crossbows", "platform": "Console"}, "588171991": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "588174435": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "1565454583": {"name": "02: Leather Hood (AR 21-24)", "category": "Helms", "platform": "Console"}, "1565454584": {"name": "03: Coif (AR 36-41)", "category": "Helms", "platform": "Console"}, "1565454585": {"name": "04: Arming Cap (AR 54-71)", "category": "Helms", "platform": "Console"}, "1565454586": {"name": "05: Helmet (AR 72-89)", "category": "Helms", "platform": "Console"}, "1565454587": {"name": "06: Plated Helm (AR 90-113)", "category": "Helms", "platform": "Console"}, "1565455671": {"name": "07: Crown (AR 114-137)", "category": "Helms", "platform": "Console"}, "1565455672": {"name": "08: Basinet (AR 138-161)", "category": "Helms", "platform": "Console"}, "1565455673": {"name": "09: Klappvisier (AR 162-185)", "category": "Helms", "platform": "Console"}, "1565455674": {"name": "10: Casque (AR 186-224)", "category": "Helms", "platform": "Console"}, "1565455675": {"name": "11: Great Helm (AR 225-247)", "category": "Helms", "platform": "Console"}, "1565456760": {"name": "12: Hounskull (AR 247-269)", "category": "Helms", "platform": "Console"}, "1565456761": {"name": "13: Stechhelm (AR 270-284)", "category": "Helms", "platform": "Console"}, "1565456762": {"name": "14: Zischagge (AR 285-322)", "category": "Helms", "platform": "Console"}, "1565456763": {"name": "15: Hellscape Mask (AR 322-359)", "category": "Helms", "platform": "Console"}, "1565456764": {"name": "16: Sovereign Helm (AR 360-397)", "category": "Helms", "platform": "Console"}, "1565456765": {"name": "17: Archon Crown (AR 397-471)", "category": "Helms", "platform": "Console"}, "1565456766": {"name": "18: Rakkisgard Helm (AR 472-659)", "category": "Helms", "platform": "Console"}, "1565456767": {"name": "19: Ascended Crown (AR 660-759)", "category": "Helms", "platform": "Console"}, "1422434075": {"name": "Art Test Helm 1", "category": "Helms", "platform": "Console"}, "1422434076": {"name": "Art Test Helm 2", "category": "Helms", "platform": "Console"}, "1422434077": {"name": "Art Test Helm 3", "category": "Helms", "platform": "Console"}, "1422434078": {"name": "Art Test Helm 4", "category": "Helms", "platform": "Console"}, "1422434079": {"name": "Art Test Helm 5", "category": "Helms", "platform": "Console"}, "-304315733": {"name": "Art_Test_Helm_10 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315732": {"name": "Art_Test_Helm_11 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315731": {"name": "Art_Test_Helm_12 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434080": {"name": "Art_Test_Helm_6 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434081": {"name": "Art_Test_Helm_7 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434082": {"name": "Art_Test_Helm_8 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434083": {"name": "Art_Test_Helm_9 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233654": {"name": "Legendary: Andariel's Visage", "category": "Helms", "platform": "Console"}, "-1855268606": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "-1855266162": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "1638662958": {"name": "Legendary: Andariel's Visage (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334377402": {"name": "Legendary: Blind Faith", "category": "Helms", "platform": "Console"}, "-1850524922": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "-1850522478": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "1638662962": {"name": "Legendary: Blind Faith (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334161780": {"name": "Legendary: Broken Crown", "category": "Helms", "platform": "Console"}, "-1857640448": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1857638004": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662956": {"name": "Legendary: Broken Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1046338483": {"name": "Legendary: Broken Crown (Patch 2.1.2)", "category": "Helms", "platform": "Console"}, "1239902833": {"name": "Legendary: Conqueror's Shako (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "974143057": {"name": "Legendary: Death Mask", "category": "Helms", "platform": "Console"}, "373333110": {"name": "Legendary: Deathseer's Cowl", "category": "Helms", "platform": "Console"}, "-1854082685": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "-1854080241": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "1638662959": {"name": "Legendary: Giant Skull (Old-Legacy)", "category": "Helms", "platform": "Console"}, "1571690839": {"name": "Legendary: Guardian Facade", "category": "Helms", "platform": "Console"}, "974107120": {"name": "Legendary: Hallowed Helm", "category": "Helms", "platform": "Console"}, "-843818268": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "-1425221075": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "334197717": {"name": "Legendary: Leoric's Crown", "category": "Helms", "platform": "Console"}, "-1856454527": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1856452083": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662957": {"name": "Legendary: Leoric's Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334197453": {"name": "Legendary: Leoric's Crown (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "334341465": {"name": "Legendary: Mempo of Twilight", "category": "Helms", "platform": "Console"}, "-1851710843": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "-1851708399": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "1638662961": {"name": "Legendary: Mempo of Twilight (Old-Legacy)", "category": "Helms", "platform": "Console"}, "373369047": {"name": "Legendary: Pride's Fall", "category": "Helms", "platform": "Console"}, "334269591": {"name": "Legendary: Skull of Resonance", "category": "Helms", "platform": "Console"}, "-1818505055": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "-1818502611": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "1638662989": {"name": "Legendary: The Helm of Command (Old-Legacy)", "category": "Helms", "platform": "Console"}, "335347701": {"name": "Legendary: The Helm of Rule", "category": "Helms", "platform": "Console"}, "-1993242998": {"name": "Set: Accursed Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662992": {"name": "Set: Aughild's Brow (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1814947292": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "-1814944848": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "335455512": {"name": "Set: Aughild's Spike", "category": "Helms", "platform": "Console"}, "335383638": {"name": "Set: Cain's Insight", "category": "Helms", "platform": "Console"}, "1638662990": {"name": "Set: Cain's Laurel (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1817319134": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1817316690": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1992092751": {"name": "Set: Crown of the Invoker", "category": "Helms", "platform": "Console"}, "-1993242997": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1991984940": {"name": "Set: Eyes of the Earth", "category": "Helms", "platform": "Console"}, "-1993134924": {"name": "Set: Firebird's Plume", "category": "Helms", "platform": "Console"}, "-1813761371": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "-1813758927": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "335491449": {"name": "Set: Guardian's Gaze", "category": "Helms", "platform": "Console"}, "1638662993": {"name": "Set: Guardian's Watch (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1992164625": {"name": "Set: Helm of Akkhan", "category": "Helms", "platform": "Console"}, "-1993314872": {"name": "Set: Helm of the Wastes (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334413339": {"name": "Set: Immortal King's Triumph", "category": "Helms", "platform": "Console"}, "-1849339001": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "-1849336557": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "1638662963": {"name": "Set: Immortal King's Will (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993027113": {"name": "Set: Jade Harvester's Wisdom", "category": "Helms", "platform": "Console"}, "-1993098987": {"name": "Set: Marauder's Visage", "category": "Helms", "platform": "Console"}, "-1991949003": {"name": "Set: Mask of Jeram", "category": "Helms", "platform": "Console"}, "-1993063050": {"name": "Set: Mask of the Searing Sky", "category": "Helms", "platform": "Console"}, "-1993314871": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662964": {"name": "Set: Natalya's Gaze (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334449276": {"name": "Set: Natalya's Sight", "category": "Helms", "platform": "Console"}, "-1848153080": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1848150636": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1993170861": {"name": "Set: Raekor's Will", "category": "Helms", "platform": "Console"}, "-1993314873": {"name": "Set: Roland's Visage (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "335527386": {"name": "Set: Sage's Apogee", "category": "Helms", "platform": "Console"}, "-1812575450": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "-1812573006": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "1638662994": {"name": "Set: Sage's Stones (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278935": {"name": "Set: Shrouded Mask (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1992128688": {"name": "Set: Sunwuko's Crown", "category": "Helms", "platform": "Console"}, "335311764": {"name": "Set: Tal Rasha's Guise of Wisdom", "category": "Helms", "platform": "Console"}, "-1819690976": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "-1819688532": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "1638662988": {"name": "Set: Tal Rasha's Horadric Crest (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278934": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233391": {"name": "legendary: Andariel's Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-36755477": {"name": "legendary: Helm of the Hierarch (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1575654862": {"name": "Act 1", "category": "Horadric Cache", "platform": "Console"}, "739397179": {"name": "Act 1, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1369696819": {"name": "Act 1, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1369696818": {"name": "Act 1, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1369696817": {"name": "Act 1, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1369696816": {"name": "Act 1, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1369696815": {"name": "Act 1, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654861": {"name": "Act 2", "category": "Horadric Cache", "platform": "Console"}, "408167196": {"name": "Act 2, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "584615630": {"name": "Act 2, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "584615631": {"name": "Act 2, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "584615632": {"name": "Act 2, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "584615633": {"name": "Act 2, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "584615634": {"name": "Act 2, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654860": {"name": "Act 3", "category": "Horadric Cache", "platform": "Console"}, "76937213": {"name": "Act 3, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1756039217": {"name": "Act 3, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1756039216": {"name": "Act 3, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1756039215": {"name": "Act 3, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1756039214": {"name": "Act 3, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1756039213": {"name": "Act 3, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654859": {"name": "Act 4", "category": "Horadric Cache", "platform": "Console"}, "-254292770": {"name": "Act 4, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "198273232": {"name": "Act 4, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "198273233": {"name": "Act 4, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "198273234": {"name": "Act 4, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "198273235": {"name": "Act 4, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "198273236": {"name": "Act 4, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654858": {"name": "Act 5", "category": "Horadric Cache", "platform": "Console"}, "-585522753": {"name": "Act 5, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-2142381615": {"name": "Act 5, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-2142381614": {"name": "Act 5, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-2142381613": {"name": "Act 5, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-2142381612": {"name": "Act 5, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-2142381611": {"name": "Act 5, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "1574352095": {"name": "Bonus Act", "category": "Horadric Cache", "platform": "Console"}, "1749838250": {"name": "Greater Horadric Cache", "category": "Horadric Cache", "platform": "Console"}, "1802516147": {"name": "Greater Horadric Cache Torment", "category": "Horadric Cache", "platform": "Console"}, "-1262930872": {"name": "Horadric Cache Bonus Act Torment", "category": "Horadric Cache", "platform": "Console"}, "867759243": {"name": "A2 MapVendor DungeonMap", "category": "Junk", "platform": "Console"}, "-326449293": {"name": "Arcane Globe", "category": "Junk", "platform": "Console"}, "393991529": {"name": "Art_Test_Pennant_1 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991530": {"name": "Art_Test_Pennant_2 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991531": {"name": "Art_Test_Pennant_3 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991532": {"name": "Art_Test_Pennant_4 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991533": {"name": "Art_Test_Pennant_5 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991534": {"name": "Art_Test_Pennant_6 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991535": {"name": "Art_Test_Pennant_7 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991536": {"name": "Art_Test_Pennant_8 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-215839115": {"name": "Blizzcon Artifact", "category": "Junk", "platform": "Console"}, "-1812121245": {"name": "Cauldron of Jordan", "category": "Junk", "platform": "Console"}, "-125073416": {"name": "Charm", "category": "Junk", "platform": "Console"}, "-125073414": {"name": "Crafter Skillup Page", "category": "Junk", "platform": "Console"}, "-1739891535": {"name": "CupCake05", "category": "Junk", "platform": "Console"}, "-1581845891": {"name": "CupCake10", "category": "Junk", "platform": "Console"}, "-1581845886": {"name": "CupCake15", "category": "Junk", "platform": "Console"}, "-1581845858": {"name": "CupCake20", "category": "Junk", "platform": "Console"}, "-1581845853": {"name": "CupCake25", "category": "Junk", "platform": "Console"}, "-1581845825": {"name": "CupCake30", "category": "Junk", "platform": "Console"}, "-1581845820": {"name": "CupCake35", "category": "Junk", "platform": "Console"}, "-1581845792": {"name": "CupCake40", "category": "Junk", "platform": "Console"}, "1402040296": {"name": "Damaged Chestpiece", "category": "Junk", "platform": "Console"}, "-904648741": {"name": "Debug Transmog Plan", "category": "Junk", "platform": "Console"}, "-808688257": {"name": "Event MapVendor Egg", "category": "Junk", "platform": "Console"}, "-2126877461": {"name": "Example Book", "category": "Junk", "platform": "Console"}, "126259831": {"name": "Gold1", "category": "Junk", "platform": "Console"}, "126259832": {"name": "Gold2", "category": "Junk", "platform": "Console"}, "126259833": {"name": "Gold3", "category": "Junk", "platform": "Console"}, "126259834": {"name": "Gold4", "category": "Junk", "platform": "Console"}, "126259835": {"name": "Gold5", "category": "Junk", "platform": "Console"}, "-1165367015": {"name": "Greater Health Potion", "category": "Junk", "platform": "Console"}, "-1916071921": {"name": "Health Potion", "category": "Junk", "platform": "Console"}, "2022931376": {"name": "HealthGlobe01", "category": "Junk", "platform": "Console"}, "2022931377": {"name": "HealthGlobe02", "category": "Junk", "platform": "Console"}, "2022931378": {"name": "HealthGlobe03", "category": "Junk", "platform": "Console"}, "2022931379": {"name": "HealthGlobe04", "category": "Junk", "platform": "Console"}, "2022931380": {"name": "HealthGlobe05", "category": "Junk", "platform": "Console"}, "2022931381": {"name": "HealthGlobe06", "category": "Junk", "platform": "Console"}, "2022931382": {"name": "HealthGlobe07", "category": "Junk", "platform": "Console"}, "2022931383": {"name": "HealthGlobe08", "category": "Junk", "platform": "Console"}, "2022931384": {"name": "HealthGlobe09", "category": "Junk", "platform": "Console"}, "-1962741280": {"name": "HealthGlobe10", "category": "Junk", "platform": "Console"}, "-345952752": {"name": "HealthGlobe100", "category": "Junk", "platform": "Console"}, "-1962741275": {"name": "HealthGlobe15", "category": "Junk", "platform": "Console"}, "-1962741247": {"name": "HealthGlobe20", "category": "Junk", "platform": "Console"}, "-1962741242": {"name": "HealthGlobe25", "category": "Junk", "platform": "Console"}, "-1962741214": {"name": "HealthGlobe30", "category": "Junk", "platform": "Console"}, "-1962741209": {"name": "HealthGlobe35", "category": "Junk", "platform": "Console"}, "-1962741181": {"name": "HealthGlobe40", "category": "Junk", "platform": "Console"}, "-1962741176": {"name": "HealthGlobe45", "category": "Junk", "platform": "Console"}, "-1962741148": {"name": "HealthGlobe50", "category": "Junk", "platform": "Console"}, "-1962741143": {"name": "HealthGlobe55", "category": "Junk", "platform": "Console"}, "-1962741115": {"name": "HealthGlobe60", "category": "Junk", "platform": "Console"}, "-1962741110": {"name": "HealthGlobe65", "category": "Junk", "platform": "Console"}, "-1962741082": {"name": "HealthGlobe70", "category": "Junk", "platform": "Console"}, "-1962741077": {"name": "HealthGlobe75", "category": "Junk", "platform": "Console"}, "-1962741049": {"name": "HealthGlobe80", "category": "Junk", "platform": "Console"}, "-1962741044": {"name": "HealthGlobe85", "category": "Junk", "platform": "Console"}, "-1962741016": {"name": "HealthGlobe90", "category": "Junk", "platform": "Console"}, "-1962741011": {"name": "HealthGlobe95", "category": "Junk", "platform": "Console"}, "-1703070487": {"name": "Heroic Health Potion", "category": "Junk", "platform": "Console"}, "-125073411": {"name": "Junkorama", "category": "Junk", "platform": "Console"}, "-1546488739": {"name": "Lesser Health Potion", "category": "Junk", "platform": "Console"}, "1646125768": {"name": "Major Health Potion", "category": "Junk", "platform": "Console"}, "1646417620": {"name": "Minor Health Potion", "category": "Junk", "platform": "Console"}, "522407589": {"name": "Monk Staff Pvp 001", "category": "Junk", "platform": "Console"}, "522407590": {"name": "Monk Staff Pvp 002", "category": "Junk", "platform": "Console"}, "522407591": {"name": "Monk Staff Pvp 003", "category": "Junk", "platform": "Console"}, "-1483610851": {"name": "Mythic Health Potion", "category": "Junk", "platform": "Console"}, "-125073413": {"name": "OH NOES! JUNK!", "category": "Junk", "platform": "Console"}, "-1596706792": {"name": "Orn Bag 01", "category": "Junk", "platform": "Console"}, "885847747": {"name": "Orn BlizzconPrize", "category": "Junk", "platform": "Console"}, "-125073415": {"name": "Page of Fate", "category": "Junk", "platform": "Console"}, "197999857": {"name": "Page of Useless Scribbling", "category": "Junk", "platform": "Console"}, "1249260787": {"name": "PageOfFateA", "category": "Junk", "platform": "Console"}, "-910124122": {"name": "Power Potion", "category": "Junk", "platform": "Console"}, "1921622363": {"name": "Power-Up Attack Speed", "category": "Junk", "platform": "Console"}, "-859355014": {"name": "Power-Up Cooldown Reset", "category": "Junk", "platform": "Console"}, "11858385": {"name": "Power-Up Damage", "category": "Junk", "platform": "Console"}, "455273651": {"name": "Power-Up Invulnerability", "category": "Junk", "platform": "Console"}, "-977399097": {"name": "Power-Up Stealth", "category": "Junk", "platform": "Console"}, "-1504368109": {"name": "Resplendent Health Potion", "category": "Junk", "platform": "Console"}, "1652778256": {"name": "Runic Health Potion", "category": "Junk", "platform": "Console"}, "-1277860767": {"name": "Sacred Health Potion", "category": "Junk", "platform": "Console"}, "704159709": {"name": "Scholarly Writings", "category": "Junk", "platform": "Console"}, "197999858": {"name": "ScrapPaper 02", "category": "Junk", "platform": "Console"}, "197999859": {"name": "ScrapPaper 03", "category": "Junk", "platform": "Console"}, "197999860": {"name": "ScrapPaper 04", "category": "Junk", "platform": "Console"}, "1462277166": {"name": "Scroll", "category": "Junk", "platform": "Console"}, "146554345": {"name": "Set 001 GiyuasFang", "category": "Junk", "platform": "Console"}, "1653966238": {"name": "Super Health Potion", "category": "Junk", "platform": "Console"}, "1626390053": {"name": "Talisman", "category": "Junk", "platform": "Console"}, "761573026": {"name": "The Black Rock Ledger, Page 15", "category": "Junk", "platform": "Console"}, "761573027": {"name": "The Black Rock Ledger, Page 16", "category": "Junk", "platform": "Console"}, "761573028": {"name": "The Black Rock Ledger, Page 23", "category": "Junk", "platform": "Console"}, "761573024": {"name": "The Black Rock Ledger, Page 4", "category": "Junk", "platform": "Console"}, "761573029": {"name": "The Black Rock Ledger, Page 42", "category": "Junk", "platform": "Console"}, "761573025": {"name": "The Black Rock Ledger, Page 8", "category": "Junk", "platform": "Console"}, "-2007738575": {"name": "Town Portal Stone 2", "category": "Junk", "platform": "Console"}, "-125073412": {"name": "Trunk Junk", "category": "Junk", "platform": "Console"}, "177825848": {"name": "cos_pennant_01 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825849": {"name": "cos_pennant_02 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825850": {"name": "cos_pennant_03 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825851": {"name": "cos_pennant_04 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825852": {"name": "cos_pennant_05 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-1562301750": {"name": "cos_pennant_p2_Anniversary (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "127020830": {"name": "cos_pennant_p2_Heroes (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "483403932": {"name": "Key of Bones", "category": "Keys", "platform": "Console"}, "-1088058180": {"name": "Key of Destruction", "category": "Keys", "platform": "Console"}, "113551449": {"name": "Key of Evil", "category": "Keys", "platform": "Console"}, "-1207737543": {"name": "Key of Gluttony", "category": "Keys", "platform": "Console"}, "1064300938": {"name": "Key of Hate", "category": "Keys", "platform": "Console"}, "-143133978": {"name": "Key of Terror", "category": "Keys", "platform": "Console"}, "2050794135": {"name": "Key of War", "category": "Keys", "platform": "Console"}, "1955086537": {"name": "Greater Rift Keystone Rank 01 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086538": {"name": "Greater Rift Keystone Rank 02 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086539": {"name": "Greater Rift Keystone Rank 03 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086540": {"name": "Greater Rift Keystone Rank 04 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086541": {"name": "Greater Rift Keystone Rank 05 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086542": {"name": "Greater Rift Keystone Rank 06 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086543": {"name": "Greater Rift Keystone Rank 07 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086544": {"name": "Greater Rift Keystone Rank 08 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086545": {"name": "Greater Rift Keystone Rank 09 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346329": {"name": "Greater Rift Keystone Rank 10 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1214538391": {"name": "Greater Rift Keystone Rank 100 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346330": {"name": "Greater Rift Keystone Rank 11 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346331": {"name": "Greater Rift Keystone Rank 12 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346332": {"name": "Greater Rift Keystone Rank 13 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346333": {"name": "Greater Rift Keystone Rank 14 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346334": {"name": "Greater Rift Keystone Rank 15 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346335": {"name": "Greater Rift Keystone Rank 16 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346336": {"name": "Greater Rift Keystone Rank 17 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346337": {"name": "Greater Rift Keystone Rank 18 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346338": {"name": "Greater Rift Keystone Rank 19 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346362": {"name": "Greater Rift Keystone Rank 20 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346363": {"name": "Greater Rift Keystone Rank 21 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346364": {"name": "Greater Rift Keystone Rank 22 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346365": {"name": "Greater Rift Keystone Rank 23 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346366": {"name": "Greater Rift Keystone Rank 24 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346367": {"name": "Greater Rift Keystone Rank 25 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346368": {"name": "Greater Rift Keystone Rank 26 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346369": {"name": "Greater Rift Keystone Rank 27 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346370": {"name": "Greater Rift Keystone Rank 28 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346371": {"name": "Greater Rift Keystone Rank 29 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346395": {"name": "Greater Rift Keystone Rank 30 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346396": {"name": "Greater Rift Keystone Rank 31 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346397": {"name": "Greater Rift Keystone Rank 32 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346398": {"name": "Greater Rift Keystone Rank 33 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346399": {"name": "Greater Rift Keystone Rank 34 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346400": {"name": "Greater Rift Keystone Rank 35 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346401": {"name": "Greater Rift Keystone Rank 36 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346402": {"name": "Greater Rift Keystone Rank 37 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346403": {"name": "Greater Rift Keystone Rank 38 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346404": {"name": "Greater Rift Keystone Rank 39 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346428": {"name": "Greater Rift Keystone Rank 40 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346429": {"name": "Greater Rift Keystone Rank 41 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346430": {"name": "Greater Rift Keystone Rank 42 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346431": {"name": "Greater Rift Keystone Rank 43 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346432": {"name": "Greater Rift Keystone Rank 44 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346433": {"name": "Greater Rift Keystone Rank 45 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346434": {"name": "Greater Rift Keystone Rank 46 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346435": {"name": "Greater Rift Keystone Rank 47 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346436": {"name": "Greater Rift Keystone Rank 48 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346437": {"name": "Greater Rift Keystone Rank 49 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346461": {"name": "Greater Rift Keystone Rank 50 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346462": {"name": "Greater Rift Keystone Rank 51 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346463": {"name": "Greater Rift Keystone Rank 52 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346464": {"name": "Greater Rift Keystone Rank 53 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346465": {"name": "Greater Rift Keystone Rank 54 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346466": {"name": "Greater Rift Keystone Rank 55 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346467": {"name": "Greater Rift Keystone Rank 56 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346468": {"name": "Greater Rift Keystone Rank 57 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346469": {"name": "Greater Rift Keystone Rank 58 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346470": {"name": "Greater Rift Keystone Rank 59 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346494": {"name": "Greater Rift Keystone Rank 60 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346495": {"name": "Greater Rift Keystone Rank 61 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346496": {"name": "Greater Rift Keystone Rank 62 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346497": {"name": "Greater Rift Keystone Rank 63 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346498": {"name": "Greater Rift Keystone Rank 64 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346499": {"name": "Greater Rift Keystone Rank 65 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346500": {"name": "Greater Rift Keystone Rank 66 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346501": {"name": "Greater Rift Keystone Rank 67 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346502": {"name": "Greater Rift Keystone Rank 68 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346503": {"name": "Greater Rift Keystone Rank 69 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346527": {"name": "Greater Rift Keystone Rank 70 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346528": {"name": "Greater Rift Keystone Rank 71 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346529": {"name": "Greater Rift Keystone Rank 72 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346530": {"name": "Greater Rift Keystone Rank 73 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346531": {"name": "Greater Rift Keystone Rank 74 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346532": {"name": "Greater Rift Keystone Rank 75 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346533": {"name": "Greater Rift Keystone Rank 76 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346534": {"name": "Greater Rift Keystone Rank 77 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346535": {"name": "Greater Rift Keystone Rank 78 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346536": {"name": "Greater Rift Keystone Rank 79 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346560": {"name": "Greater Rift Keystone Rank 80 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346561": {"name": "Greater Rift Keystone Rank 81 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346562": {"name": "Greater Rift Keystone Rank 82 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346563": {"name": "Greater Rift Keystone Rank 83 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346564": {"name": "Greater Rift Keystone Rank 84 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346565": {"name": "Greater Rift Keystone Rank 85 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346566": {"name": "Greater Rift Keystone Rank 86 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346567": {"name": "Greater Rift Keystone Rank 87 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346568": {"name": "Greater Rift Keystone Rank 88 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346569": {"name": "Greater Rift Keystone Rank 89 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346593": {"name": "Greater Rift Keystone Rank 90 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346594": {"name": "Greater Rift Keystone Rank 91 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346595": {"name": "Greater Rift Keystone Rank 92 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346596": {"name": "Greater Rift Keystone Rank 93 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346597": {"name": "Greater Rift Keystone Rank 94 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346598": {"name": "Greater Rift Keystone Rank 95 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346599": {"name": "Greater Rift Keystone Rank 96 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346600": {"name": "Greater Rift Keystone Rank 97 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346601": {"name": "Greater Rift Keystone Rank 98 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346602": {"name": "Greater Rift Keystone Rank 99 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086536": {"name": "Keystone of Trials (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1698136228": {"name": "Rift Keys", "category": "Keystones", "platform": "Console"}, "925362070": {"name": "A2 Oasis KamyrsOrders", "category": "Lore", "platform": "Console"}, "-1194932976": {"name": "A2 Oasis KamyrsOrdersTwo", "category": "Lore", "platform": "Console"}, "192275875": {"name": "A2 TemplarBackstory 3 Landus's Diary", "category": "Lore", "platform": "Console"}, "-1883980626": {"name": "A3 Battlefields Supply WagonDiaries", "category": "Lore", "platform": "Console"}, "1740306889": {"name": "A4 Hub OldCouple 1", "category": "Lore", "platform": "Console"}, "-1764974213": {"name": "Adria ZoltunKulle2", "category": "Lore", "platform": "Console"}, "103300821": {"name": "Adria: Adria's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-776544373": {"name": "Adria: Adria's Journal, Part 2", "category": "Lore", "platform": "Console"}, "133385135": {"name": "Adria: Adria's Journal, Part 3", "category": "Lore", "platform": "Console"}, "133390039": {"name": "Adria: Adria's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1890330185": {"name": "Adria: Adria's Journal, Part 5", "category": "Lore", "platform": "Console"}, "127066864": {"name": "Adria: Adria's Journal, Part 6", "category": "Lore", "platform": "Console"}, "733368986": {"name": "Adria: Adria's Journal, Part 7", "category": "Lore", "platform": "Console"}, "100959118": {"name": "Adria: Adria's Journal, Part 8", "category": "Lore", "platform": "Console"}, "133600747": {"name": "Adria: Adria's Journal, Part 9", "category": "Lore", "platform": "Console"}, "133313247": {"name": "Adria: Adria's Note", "category": "Lore", "platform": "Console"}, "954251807": {"name": "Adria: Adria's Purpose", "category": "Lore", "platform": "Console"}, "900358318": {"name": "AdventureMode: A New Era", "category": "Lore", "platform": "Console"}, "-282286736": {"name": "AdventureMode: An Eternity of Agony", "category": "Lore", "platform": "Console"}, "1375431349": {"name": "AdventureMode: Impossibilities", "category": "Lore", "platform": "Console"}, "-1315225766": {"name": "AdventureMode: The Nephalem", "category": "Lore", "platform": "Console"}, "501220619": {"name": "AngirisCouncil: The Angiris Council", "category": "Lore", "platform": "Console"}, "-1383924340": {"name": "AngirisCouncil: The Archangel Auriel", "category": "Lore", "platform": "Console"}, "260686328": {"name": "AngirisCouncil: The Archangel Imperius", "category": "Lore", "platform": "Console"}, "397935128": {"name": "AngirisCouncil: The Archangel Itherael", "category": "Lore", "platform": "Console"}, "478898578": {"name": "AngirisCouncil: The Archangel Malthael", "category": "Lore", "platform": "Console"}, "-635616901": {"name": "AngirisCouncil: The Archangel Tyrael", "category": "Lore", "platform": "Console"}, "-164029999": {"name": "Aqueducts: The Desert Aqueducts, Part 1", "category": "Lore", "platform": "Console"}, "-164029998": {"name": "Aqueducts: The Desert Aqueducts, Part 2", "category": "Lore", "platform": "Console"}, "-714930281": {"name": "Armorer: Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "-1385743634": {"name": "Azmodan: Orders from Azmodan, Part 1", "category": "Lore", "platform": "Console"}, "-1385743633": {"name": "Azmodan: Orders from Azmodan, Part 2", "category": "Lore", "platform": "Console"}, "-1385743632": {"name": "Azmodan: Orders from Azmodan, Part 3", "category": "Lore", "platform": "Console"}, "-1385743631": {"name": "Azmodan: Orders from Azmodan, Part 4", "category": "Lore", "platform": "Console"}, "-1385743630": {"name": "Azmodan: Orders from Azmodan, Part 5", "category": "Lore", "platform": "Console"}, "-1385743629": {"name": "Azmodan: Orders from Azmodan, Part 6", "category": "Lore", "platform": "Console"}, "-1312231117": {"name": "Belial: Deceivers' Orders, Part 1", "category": "Lore", "platform": "Console"}, "-1346161479": {"name": "Belial: Deceivers' Orders, Part 2", "category": "Lore", "platform": "Console"}, "-661262942": {"name": "Belial: Deceivers' Orders, Part 3", "category": "Lore", "platform": "Console"}, "-978510227": {"name": "Belial: Guard's Orders", "category": "Lore", "platform": "Console"}, "1488385291": {"name": "Belial: Missive to Maghda, Part 1", "category": "Lore", "platform": "Console"}, "1488385292": {"name": "Belial: Missive to Maghda, Part 2", "category": "Lore", "platform": "Console"}, "10458238": {"name": "Belial: Proclamation from the Imperial Guard", "category": "Lore", "platform": "Console"}, "621163016": {"name": "Bestiary: Anarch", "category": "Lore", "platform": "Console"}, "515122494": {"name": "Bestiary: Armored Destroyer", "category": "Lore", "platform": "Console"}, "-1478953705": {"name": "Bestiary: Barbed Lurker", "category": "Lore", "platform": "Console"}, "1467646658": {"name": "Bestiary: Beast", "category": "Lore", "platform": "Console"}, "231471423": {"name": "Bestiary: Bile Crawler", "category": "Lore", "platform": "Console"}, "1675636673": {"name": "Bestiary: Blood Clan Khazra", "category": "Lore", "platform": "Console"}, "1675805102": {"name": "Bestiary: Blood Hawk", "category": "Lore", "platform": "Console"}, "2132231168": {"name": "Bestiary: Bogan Trapper", "category": "Lore", "platform": "Console"}, "661688183": {"name": "Bestiary: Boggit", "category": "Lore", "platform": "Console"}, "-1697636392": {"name": "Bestiary: Carrion Bat", "category": "Lore", "platform": "Console"}, "-186990405": {"name": "Bestiary: Carrion Nest", "category": "Lore", "platform": "Console"}, "1864365917": {"name": "Bestiary: Colossal Golgor", "category": "Lore", "platform": "Console"}, "-899331059": {"name": "Bestiary: Corpse Raiser", "category": "Lore", "platform": "Console"}, "-563018536": {"name": "Bestiary: Dark Berserker", "category": "Lore", "platform": "Console"}, "-1824883589": {"name": "Bestiary: Dark Cultist", "category": "Lore", "platform": "Console"}, "1971053797": {"name": "Bestiary: Dark Vessel", "category": "Lore", "platform": "Console"}, "-985860913": {"name": "Bestiary: Death Maiden", "category": "Lore", "platform": "Console"}, "610441837": {"name": "Bestiary: Deceivers", "category": "Lore", "platform": "Console"}, "-1937284463": {"name": "Bestiary: Demon Trooper", "category": "Lore", "platform": "Console"}, "478100232": {"name": "Bestiary: Demonic Hell Bearer", "category": "Lore", "platform": "Console"}, "-140849528": {"name": "Bestiary: Demonic Hellflyer", "category": "Lore", "platform": "Console"}, "2144349771": {"name": "Bestiary: Demonic Tremor", "category": "Lore", "platform": "Console"}, "1641498900": {"name": "Bestiary: Dune Dervish", "category": "Lore", "platform": "Console"}, "1184767076": {"name": "Bestiary: Dune Thresher", "category": "Lore", "platform": "Console"}, "-525114375": {"name": "Bestiary: Dust Imp", "category": "Lore", "platform": "Console"}, "-1086668012": {"name": "Bestiary: Electric Eel", "category": "Lore", "platform": "Console"}, "90729293": {"name": "Bestiary: Enraged Phantasm", "category": "Lore", "platform": "Console"}, "-1878606908": {"name": "Bestiary: Enslaved Nightmare", "category": "Lore", "platform": "Console"}, "789563798": {"name": "Bestiary: Exarch", "category": "Lore", "platform": "Console"}, "-1299022938": {"name": "Bestiary: Executioner", "category": "Lore", "platform": "Console"}, "1389417324": {"name": "Bestiary: Exorcist", "category": "Lore", "platform": "Console"}, "163638005": {"name": "Bestiary: Fallen Grunt", "category": "Lore", "platform": "Console"}, "84174677": {"name": "Bestiary: Fallen Lunatic", "category": "Lore", "platform": "Console"}, "1562132029": {"name": "Bestiary: Fallen Shaman", "category": "Lore", "platform": "Console"}, "-990665261": {"name": "Bestiary: Flesh Gorger", "category": "Lore", "platform": "Console"}, "-944408897": {"name": "Bestiary: Flesh Hurler", "category": "Lore", "platform": "Console"}, "-529946523": {"name": "Bestiary: Flesh Shaman", "category": "Lore", "platform": "Console"}, "1473699320": {"name": "Bestiary: Ghost", "category": "Lore", "platform": "Console"}, "1473699378": {"name": "Bestiary: Ghoul", "category": "Lore", "platform": "Console"}, "1067328402": {"name": "Bestiary: Grotesque", "category": "Lore", "platform": "Console"}, "-288964962": {"name": "Bestiary: Hellion", "category": "Lore", "platform": "Console"}, "-675600988": {"name": "Bestiary: Herald of Pestilence", "category": "Lore", "platform": "Console"}, "-1778975775": {"name": "Bestiary: Hound Pack Leader", "category": "Lore", "platform": "Console"}, "-1864253371": {"name": "Bestiary: Hulking Phasebeast", "category": "Lore", "platform": "Console"}, "1270376265": {"name": "Bestiary: Imp", "category": "Lore", "platform": "Console"}, "1543483412": {"name": "Bestiary: Khazra", "category": "Lore", "platform": "Console"}, "1080209708": {"name": "Bestiary: Khazra Shaman", "category": "Lore", "platform": "Console"}, "1574383663": {"name": "Bestiary: Lacuni", "category": "Lore", "platform": "Console"}, "1277879248": {"name": "Bestiary: Maggot Brood", "category": "Lore", "platform": "Console"}, "-1289421300": {"name": "Bestiary: Primordial Scavenger", "category": "Lore", "platform": "Console"}, "-683087584": {"name": "Bestiary: Quill Fiend", "category": "Lore", "platform": "Console"}, "2123300624": {"name": "Bestiary: Revenant Soldier", "category": "Lore", "platform": "Console"}, "2139220569": {"name": "Bestiary: Risen Dead", "category": "Lore", "platform": "Console"}, "-286364985": {"name": "Bestiary: Rockworm", "category": "Lore", "platform": "Console"}, "507308136": {"name": "Bestiary: Sand Dweller", "category": "Lore", "platform": "Console"}, "-1096104684": {"name": "Bestiary: Sand Wasp", "category": "Lore", "platform": "Console"}, "1312554887": {"name": "Bestiary: Scarab", "category": "Lore", "platform": "Console"}, "-1399846223": {"name": "Bestiary: Scavenger", "category": "Lore", "platform": "Console"}, "2067382477": {"name": "Bestiary: Scavenging Tunneler", "category": "Lore", "platform": "Console"}, "-458569087": {"name": "Bestiary: Scouring Charger", "category": "Lore", "platform": "Console"}, "-1529207830": {"name": "Bestiary: Shadow Vermin", "category": "Lore", "platform": "Console"}, "-1715924548": {"name": "Bestiary: Shadow of Death", "category": "Lore", "platform": "Console"}, "1905172061": {"name": "Bestiary: Shrieking Terror", "category": "Lore", "platform": "Console"}, "56567324": {"name": "Bestiary: Siegebreaker Assault Beast", "category": "Lore", "platform": "Console"}, "-387707041": {"name": "Bestiary: Skeletal Beast", "category": "Lore", "platform": "Console"}, "494193920": {"name": "Bestiary: Skeletal Crawler", "category": "Lore", "platform": "Console"}, "-313234093": {"name": "Bestiary: Skeletal Guardian", "category": "Lore", "platform": "Console"}, "-1409684360": {"name": "Bestiary: Skeleton", "category": "Lore", "platform": "Console"}, "1170383240": {"name": "Bestiary: Soul Ripper", "category": "Lore", "platform": "Console"}, "1866317050": {"name": "Bestiary: Spider", "category": "Lore", "platform": "Console"}, "564441124": {"name": "Bestiary: Spiderling", "category": "Lore", "platform": "Console"}, "-330757856": {"name": "Bestiary: Stinging Swarm", "category": "Lore", "platform": "Console"}, "-458677543": {"name": "Bestiary: Subjugator", "category": "Lore", "platform": "Console"}, "-1468295040": {"name": "Bestiary: Succubus", "category": "Lore", "platform": "Console"}, "-513840200": {"name": "Bestiary: Summoned Archer", "category": "Lore", "platform": "Console"}, "166255055": {"name": "Bestiary: Summoned Shield Guard", "category": "Lore", "platform": "Console"}, "1887856949": {"name": "Bestiary: Summoned Soldier", "category": "Lore", "platform": "Console"}, "920539156": {"name": "Bestiary: Summoner of the Dead", "category": "Lore", "platform": "Console"}, "166186064": {"name": "Bestiary: Terror Demon", "category": "Lore", "platform": "Console"}, "-1551452867": {"name": "Bestiary: The Accursed", "category": "Lore", "platform": "Console"}, "1613832402": {"name": "Bestiary: The Mallet Lords", "category": "Lore", "platform": "Console"}, "1481069442": {"name": "Bestiary: The Morlu", "category": "Lore", "platform": "Console"}, "1727215776": {"name": "Bestiary: The Oppressors", "category": "Lore", "platform": "Console"}, "-1569107231": {"name": "Bestiary: Tormented Stinger", "category": "Lore", "platform": "Console"}, "692217017": {"name": "Bestiary: Treasure Goblin", "category": "Lore", "platform": "Console"}, "1112087602": {"name": "Bestiary: Tusked Bogan", "category": "Lore", "platform": "Console"}, "1695981553": {"name": "Bestiary: Unburied", "category": "Lore", "platform": "Console"}, "181747316": {"name": "Bestiary: Vicious Hound", "category": "Lore", "platform": "Console"}, "191466402": {"name": "Bestiary: Vile Bat", "category": "Lore", "platform": "Console"}, "1295465786": {"name": "Bestiary: Warscarred Marauder", "category": "Lore", "platform": "Console"}, "-1568007631": {"name": "Bestiary: Warscarred Ravager", "category": "Lore", "platform": "Console"}, "1809929374": {"name": "Bestiary: Winged Assassin", "category": "Lore", "platform": "Console"}, "-1414985342": {"name": "Bestiary: Winged Talus", "category": "Lore", "platform": "Console"}, "1562746110": {"name": "Bestiary: Withermoth", "category": "Lore", "platform": "Console"}, "1892963547": {"name": "Bestiary: Wood Wraith", "category": "Lore", "platform": "Console"}, "1470131000": {"name": "Bestiary: Wretched Mother", "category": "Lore", "platform": "Console"}, "2033922302": {"name": "Butcher: Butcher", "category": "Lore", "platform": "Console"}, "3246582303": {"name": "Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "4058000945": {"name": "Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "554362535": {"name": "Cain: Deckard Cain's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1114094521": {"name": "Cain: Deckard Cain's Journal, Part 2", "category": "Lore", "platform": "Console"}, "828022511": {"name": "Caldeum: An Abridged History of Caldeum, Part 1", "category": "Lore", "platform": "Console"}, "828022512": {"name": "Caldeum: An Abridged History of Caldeum, Part 2", "category": "Lore", "platform": "Console"}, "828022513": {"name": "Caldeum: An Abridged History of Caldeum, Part 3", "category": "Lore", "platform": "Console"}, "828022514": {"name": "Caldeum: An Abridged History of Caldeum, Part 4", "category": "Lore", "platform": "Console"}, "828022515": {"name": "Caldeum: An Abridged History of Caldeum, Part 5", "category": "Lore", "platform": "Console"}, "828022516": {"name": "Caldeum: An Abridged History of Caldeum, Part 6", "category": "Lore", "platform": "Console"}, "344927641": {"name": "CaliphateSardar: The Musings of Caliphate Sardar", "category": "Lore", "platform": "Console"}, "-1106917318": {"name": "CampCultist: The Feared Hero", "category": "Lore", "platform": "Console"}, "-668215174": {"name": "CellarMadman: The Ravings of a Deranged Mind", "category": "Lore", "platform": "Console"}, "-1518383148": {"name": "CemeteryCrypts: Gravedigger's Log", "category": "Lore", "platform": "Console"}, "-727194820": {"name": "Challenge: Nephalem Rifts", "category": "Lore", "platform": "Console"}, "2125283571": {"name": "Crusader: The Crusaders, Part 1", "category": "Lore", "platform": "Console"}, "2125283572": {"name": "Crusader: The Crusaders, Part 2", "category": "Lore", "platform": "Console"}, "2125283573": {"name": "Crusader: The Crusaders, Part 3", "category": "Lore", "platform": "Console"}, "2125283574": {"name": "Crusader: The Crusaders, Part 4", "category": "Lore", "platform": "Console"}, "2125283575": {"name": "Crusader: The Crusaders, Part 5", "category": "Lore", "platform": "Console"}, "2125283576": {"name": "Crusader: The Crusaders, Part 6", "category": "Lore", "platform": "Console"}, "2125283577": {"name": "Crusader: The Crusaders, Part 7", "category": "Lore", "platform": "Console"}, "2125283578": {"name": "Crusader: The Crusaders, Part 8", "category": "Lore", "platform": "Console"}, "2125283579": {"name": "Crusader: The Crusaders, Part 9", "category": "Lore", "platform": "Console"}, "-186854830": {"name": "CultCrown: Cultist Orders", "category": "Lore", "platform": "Console"}, "4108112466": {"name": "Cultist Orders", "category": "Lore", "platform": "Console"}, "504852499": {"name": "CurioVendor: Adenah's Jottings", "category": "Lore", "platform": "Console"}, "-1717171528": {"name": "Cydaea: Cydaea, the Maiden of Lust", "category": "Lore", "platform": "Console"}, "1958060101": {"name": "DahlgurOasis: The Dahlgur Oasis", "category": "Lore", "platform": "Console"}, "-1010870335": {"name": "DarkZealot: Report from Wortham", "category": "Lore", "platform": "Console"}, "-819413474": {"name": "Deserter: Deserter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-819413473": {"name": "Deserter: Deserter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-819413472": {"name": "Deserter: Deserter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-819413471": {"name": "Deserter: Deserter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-819413470": {"name": "Deserter: Deserter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "1121720780": {"name": "DesolateSands: On the Desolate Sands, Part 1", "category": "Lore", "platform": "Console"}, "1121720781": {"name": "DesolateSands: On the Desolate Sands, Part 2", "category": "Lore", "platform": "Console"}, "1121720782": {"name": "DesolateSands: On the Desolate Sands, Part 3", "category": "Lore", "platform": "Console"}, "2388677118": {"name": "Despina's Journal", "category": "Lore", "platform": "Console"}, "1244727565": {"name": "DevilsHand: Implements of the Dark Coven", "category": "Lore", "platform": "Console"}, "1244727564": {"name": "DevilsHand: The Black King's Reign", "category": "Lore", "platform": "Console"}, "1244727563": {"name": "DevilsHand: The Covenant's Search", "category": "Lore", "platform": "Console"}, "172363859": {"name": "DoomedWoman: The Horrible Secret", "category": "Lore", "platform": "Console"}, "-1577589110": {"name": "Enchantress: Eirena's Journal", "category": "Lore", "platform": "Console"}, "2168089835": {"name": "Example Book", "category": "Lore", "platform": "Console"}, "1850500833": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 1", "category": "Lore", "platform": "Console"}, "1850500834": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 2", "category": "Lore", "platform": "Console"}, "1850500835": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 3", "category": "Lore", "platform": "Console"}, "1850500836": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 4", "category": "Lore", "platform": "Console"}, "1850500837": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 5", "category": "Lore", "platform": "Console"}, "1814333430": {"name": "FieldsofMisery: Tristram Fields", "category": "Lore", "platform": "Console"}, "-821793924": {"name": "Ghom: Ghom, the Lord of Gluttony", "category": "Lore", "platform": "Console"}, "-681952308": {"name": "GluttonysLog: Ghom's Log", "category": "Lore", "platform": "Console"}, "1895762819": {"name": "GoatmenHunter: Khazra Heads Wanted", "category": "Lore", "platform": "Console"}, "1895762820": {"name": "GoatmenHunter: Researching the Khazra", "category": "Lore", "platform": "Console"}, "1895762821": {"name": "GoatmenHunter: The Khazra Massacre", "category": "Lore", "platform": "Console"}, "-1085616825": {"name": "Halls_of_Agony: Command from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "-1085616824": {"name": "Halls_of_Agony: Reply from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "721065374": {"name": "HangingTree: The Hanging Tree", "category": "Lore", "platform": "Console"}, "4006002334": {"name": "Hellion", "category": "Lore", "platform": "Console"}, "1555542539": {"name": "Hermit_Caves: Hermit's Ravings", "category": "Lore", "platform": "Console"}, "-578368437": {"name": "HexMaze: Melaina's Memory", "category": "Lore", "platform": "Console"}, "-578368438": {"name": "HexMaze: Raissa's Memory", "category": "Lore", "platform": "Console"}, "-578368439": {"name": "HexMaze: Sibyl's Thoughts", "category": "Lore", "platform": "Console"}, "2145056291": {"name": "Highlands: The Highlands", "category": "Lore", "platform": "Console"}, "174686246": {"name": "HuntersJournal: Hunter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "174686247": {"name": "HuntersJournal: Hunter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "174686248": {"name": "HuntersJournal: Hunter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "174686249": {"name": "HuntersJournal: Hunter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "174686250": {"name": "HuntersJournal: Hunter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "174686251": {"name": "HuntersJournal: Hunter's Journal, Part 6", "category": "Lore", "platform": "Console"}, "-799754755": {"name": "Inarius: The Creation of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "-799754754": {"name": "Inarius: The Creation of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "-799754753": {"name": "Inarius: The Creation of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "-799754752": {"name": "Inarius: The Creation of Sanctuary, Part 4", "category": "Lore", "platform": "Console"}, "194883964": {"name": "Inarius: The Testament of Inarius, Part 1", "category": "Lore", "platform": "Console"}, "194883965": {"name": "Inarius: The Testament of Inarius, Part 2", "category": "Lore", "platform": "Console"}, "194883966": {"name": "Inarius: The Testament of Inarius, Part 3", "category": "Lore", "platform": "Console"}, "194883967": {"name": "Inarius: The Testament of Inarius, Part 4", "category": "Lore", "platform": "Console"}, "194883968": {"name": "Inarius: The Testament of Inarius, Part 5", "category": "Lore", "platform": "Console"}, "194883969": {"name": "Inarius: The Testament of Inarius, Part 6", "category": "Lore", "platform": "Console"}, "194883970": {"name": "Inarius: The Testament of Inarius, Part 7", "category": "Lore", "platform": "Console"}, "-1346370762": {"name": "Izual: Izual's Descent", "category": "Lore", "platform": "Console"}, "28868489": {"name": "Jeweler: Journal of Covetous Shen", "category": "Lore", "platform": "Console"}, "1221720352": {"name": "Jeweler: The Legend of Zei the Trickster", "category": "Lore", "platform": "Console"}, "-329801970": {"name": "Kala: Kala's Poem", "category": "Lore", "platform": "Console"}, "-355886665": {"name": "KeepHistory: The History of Bastion's Keep", "category": "Lore", "platform": "Console"}, "815737414": {"name": "KhanDakab: Last Will of Khan Dakab", "category": "Lore", "platform": "Console"}, "378673143": {"name": "KidVendor: Larra's Diary", "category": "Lore", "platform": "Console"}, "-1755180605": {"name": "Kingsport: Kingsport Bill", "category": "Lore", "platform": "Console"}, "-1156197446": {"name": "Kulle: Kulle's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1156197445": {"name": "Kulle: Kulle's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1156197444": {"name": "Kulle: Kulle's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-1156197443": {"name": "Kulle: Kulle's Journal, Part 4", "category": "Lore", "platform": "Console"}, "2698411174": {"name": "Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "3758420764": {"name": "Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "3768800974": {"name": "Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "3768800975": {"name": "Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "3768800976": {"name": "Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "3768800977": {"name": "Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "-1596556122": {"name": "Lachdanan: Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "-536546532": {"name": "Lachdanan: Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "-526166322": {"name": "Lachdanan: Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "-526166321": {"name": "Lachdanan: Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "-526166320": {"name": "Lachdanan: Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "-526166319": {"name": "Lachdanan: Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "1554177638": {"name": "LastAncient: The Last of the Ancients", "category": "Lore", "platform": "Console"}, "1905436671": {"name": "Lazarus: A Page from Lazarus's Grimoire", "category": "Lore", "platform": "Console"}, "3272862989": {"name": "Leah's Journal, Part 1", "category": "Lore", "platform": "Console"}, "3272868741": {"name": "Leah's Journal, Part 2", "category": "Lore", "platform": "Console"}, "3625638211": {"name": "Leah's Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922967": {"name": "Leah: Leah's Caldeum Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922968": {"name": "Leah: Leah's Caldeum Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922969": {"name": "Leah: Leah's Caldeum Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922970": {"name": "Leah: Leah's Caldeum Journal, Part 4", "category": "Lore", "platform": "Console"}, "891922971": {"name": "Leah: Leah's Caldeum Journal, Part 5", "category": "Lore", "platform": "Console"}, "891922972": {"name": "Leah: Leah's Keep Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922973": {"name": "Leah: Leah's Keep Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922974": {"name": "Leah: Leah's Keep Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922975": {"name": "Leah: Leah's Keep Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1022104307": {"name": "Leah: Leah's Tristram Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1022098555": {"name": "Leah: Leah's Tristram Journal, Part 2", "category": "Lore", "platform": "Console"}, "-669329085": {"name": "Leah: Leah's Tristram Journal, Part 3", "category": "Lore", "platform": "Console"}, "629974535": {"name": "Leah: Leah's Tristram Journal, Part 4", "category": "Lore", "platform": "Console"}, "629968021": {"name": "Leah: Leah's Tristram Journal, Part 5", "category": "Lore", "platform": "Console"}, "-1022100097": {"name": "Leah: Leah's Tristram Journal, Part 6", "category": "Lore", "platform": "Console"}, "-670618452": {"name": "Leah: Leah's Tristram Journal, Part 7", "category": "Lore", "platform": "Console"}, "2951326394": {"name": "Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1091428479": {"name": "Leoric: A Prisoner's Journal", "category": "Lore", "platform": "Console"}, "-1343640902": {"name": "Leoric: Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1561062717": {"name": "Leoric: Leoric's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1561062718": {"name": "Leoric: Leoric's Journal, Part 2", "category": "Lore", "platform": "Console"}, "1561062719": {"name": "Leoric: Leoric's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561062720": {"name": "Leoric: Leoric's Journal, Part 4", "category": "Lore", "platform": "Console"}, "1561062721": {"name": "Leoric: Leoric's Journal, Part 5", "category": "Lore", "platform": "Console"}, "342313869": {"name": "Leoric: Leoric's Relic", "category": "Lore", "platform": "Console"}, "164674838": {"name": "Leoric: The Death of King Leoric", "category": "Lore", "platform": "Console"}, "82422929": {"name": "Leoric: Torn Letter", "category": "Lore", "platform": "Console"}, "82422930": {"name": "Leoric: Torn Letter's Response", "category": "Lore", "platform": "Console"}, "1354656263": {"name": "Lilith: The Writings of Lilith, Part 1", "category": "Lore", "platform": "Console"}, "1354656264": {"name": "Lilith: The Writings of Lilith, Part 2", "category": "Lore", "platform": "Console"}, "1354656265": {"name": "Lilith: The Writings of Lilith, Part 3", "category": "Lore", "platform": "Console"}, "1354656266": {"name": "Lilith: The Writings of Lilith, Part 4", "category": "Lore", "platform": "Console"}, "2145180345": {"name": "LordofFools: Lord Kertis's Journal", "category": "Lore", "platform": "Console"}, "704654350": {"name": "LordsofHell: Andariel, the Maiden of Anguish", "category": "Lore", "platform": "Console"}, "-408914888": {"name": "LordsofHell: Azmodan, the Lord of Sin", "category": "Lore", "platform": "Console"}, "-1390665602": {"name": "LordsofHell: Baal, the Lord of Destruction", "category": "Lore", "platform": "Console"}, "1693753943": {"name": "LordsofHell: Belial, the Lord of Lies", "category": "Lore", "platform": "Console"}, "1776365849": {"name": "LordsofHell: Diablo, the Lord of Terror", "category": "Lore", "platform": "Console"}, "1791215219": {"name": "LordsofHell: Duriel, the Lord of Pain", "category": "Lore", "platform": "Console"}, "-1530801161": {"name": "LordsofHell: Mephisto, the Lord of Hatred", "category": "Lore", "platform": "Console"}, "1361465018": {"name": "LordsofHell: The Seven Lords of Hell", "category": "Lore", "platform": "Console"}, "1775133212": {"name": "Lore CainLetter", "category": "Lore", "platform": "Console"}, "1615247495": {"name": "Lore Catacombs NephDefenseSystem", "category": "Lore", "platform": "Console"}, "-1084060684": {"name": "Lore Festering CryptOfTheAncients", "category": "Lore", "platform": "Console"}, "108864625": {"name": "Lore Festering DrownedTemple", "category": "Lore", "platform": "Console"}, "-740914034": {"name": "Lore Festering WarriorsRest", "category": "Lore", "platform": "Console"}, "2011207568": {"name": "Lore X1 Bog Ideation AdriaSpikeChest", "category": "Lore", "platform": "Console"}, "216459655": {"name": "Lore X1 Graveyard Azthar", "category": "Lore", "platform": "Console"}, "-827657709": {"name": "Lore X1 Westm Legendary Drop", "category": "Lore", "platform": "Console"}, "-1004685329": {"name": "Lore x1 MysticIntro1", "category": "Lore", "platform": "Console"}, "-1004685328": {"name": "Lore x1 MysticIntro2", "category": "Lore", "platform": "Console"}, "-2124310248": {"name": "Lore_p2_DateDungeon_CovenPlans (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "-1307619936": {"name": "Lore_p2_ScoundrelEvent02_SimonNote (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "1390356236": {"name": "LostAngel: The Lost Warrior", "category": "Lore", "platform": "Console"}, "1487246296": {"name": "LoveLetter: A Love Letter", "category": "Lore", "platform": "Console"}, "-184131088": {"name": "MaghdaManor: Orders from Maghda", "category": "Lore", "platform": "Console"}, "18980873": {"name": "Malthael: The Path of Wisdom, Part 1", "category": "Lore", "platform": "Console"}, "18980874": {"name": "Malthael: The Path of Wisdom, Part 2", "category": "Lore", "platform": "Console"}, "18980875": {"name": "Malthael: The Path of Wisdom, Part 3", "category": "Lore", "platform": "Console"}, "18980876": {"name": "Malthael: The Path of Wisdom, Part 4", "category": "Lore", "platform": "Console"}, "18980877": {"name": "Malthael: The Path of Wisdom, Part 5", "category": "Lore", "platform": "Console"}, "18980878": {"name": "Malthael: The Path of Wisdom, Part 6", "category": "Lore", "platform": "Console"}, "3897062066": {"name": "Mira's Letter to Haedrig", "category": "Lore", "platform": "Console"}, "-768304375": {"name": "MisguidedFarmer: Farmer's Journal", "category": "Lore", "platform": "Console"}, "-1595216991": {"name": "Morgan: Morgan's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1595216990": {"name": "Morgan: Morgan's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1595216989": {"name": "Morgan: Morgan's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561999134": {"name": "Necromancer: Necromancer's Log", "category": "Lore", "platform": "Console"}, "1036599468": {"name": "Nephalem: The Destiny of the Nephalem, Part 1", "category": "Lore", "platform": "Console"}, "1036599469": {"name": "Nephalem: The Destiny of the Nephalem, Part 2", "category": "Lore", "platform": "Console"}, "1036599470": {"name": "Nephalem: The Destiny of the Nephalem, Part 3", "category": "Lore", "platform": "Console"}, "85406869": {"name": "Nephalem: The Drowned Temple", "category": "Lore", "platform": "Console"}, "1604771305": {"name": "Nephalem: The Last Stand of the Ancients", "category": "Lore", "platform": "Console"}, "1071008887": {"name": "Nephalem: The Nephalem Tome", "category": "Lore", "platform": "Console"}, "220221847": {"name": "Nephalem: Tomb Robber's Journal", "category": "Lore", "platform": "Console"}, "429729842": {"name": "Nephalem: Warrior's Rest", "category": "Lore", "platform": "Console"}, "-1608490938": {"name": "NephalemMiser: Miser's Will", "category": "Lore", "platform": "Console"}, "775555921": {"name": "NewTristram: New Tristram", "category": "Lore", "platform": "Console"}, "-1083079452": {"name": "Note: Secret Note", "category": "Lore", "platform": "Console"}, "1316599940": {"name": "Oasis: A Love Letter", "category": "Lore", "platform": "Console"}, "1676339915": {"name": "OasisCellars: The Imperial Guard's Orders", "category": "Lore", "platform": "Console"}, "-1048384993": {"name": "OldTristram: Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "-236966351": {"name": "OldTristram: Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1906290178": {"name": "OldTristram: Despina's Journal", "category": "Lore", "platform": "Console"}, "829218340": {"name": "OldTristram: Gillian's Diary, Part 1", "category": "Lore", "platform": "Console"}, "1594401494": {"name": "OldTristram: Gillian's Diary, Part 2", "category": "Lore", "platform": "Console"}, "316278028": {"name": "OldTristram: Lost Journal", "category": "Lore", "platform": "Console"}, "316278029": {"name": "OldTristram: Old Diary", "category": "Lore", "platform": "Console"}, "316278027": {"name": "OldTristram: Old Tristram Journal", "category": "Lore", "platform": "Console"}, "-700459563": {"name": "OldTristram: Traveler's Journal", "category": "Lore", "platform": "Console"}, "-289611678": {"name": "OldTristram: Villager's Journal", "category": "Lore", "platform": "Console"}, "1708077021": {"name": "OldTristram: Warriv's Journal", "category": "Lore", "platform": "Console"}, "-561113926": {"name": "OneLastEntry: Crumbling Journal", "category": "Lore", "platform": "Console"}, "-216253271": {"name": "PandExt: Legend of the Great Weapon", "category": "Lore", "platform": "Console"}, "551638722": {"name": "PandExt: Malthael's Plan", "category": "Lore", "platform": "Console"}, "-420053241": {"name": "Pandemonium: The History of Pandemonium, Part 1", "category": "Lore", "platform": "Console"}, "-420053240": {"name": "Pandemonium: The History of Pandemonium, Part 2", "category": "Lore", "platform": "Console"}, "-420053239": {"name": "Pandemonium: The History of Pandemonium, Part 3", "category": "Lore", "platform": "Console"}, "-420053238": {"name": "Pandemonium: The History of Pandemonium, Part 4", "category": "Lore", "platform": "Console"}, "-1604058933": {"name": "Poltahr: Poltahr's Notes", "category": "Lore", "platform": "Console"}, "-1861918345": {"name": "PortalRoulette: Lyndo's Journal", "category": "Lore", "platform": "Console"}, "613068827": {"name": "Priest: Priest's Contemplations, Part 1", "category": "Lore", "platform": "Console"}, "613068826": {"name": "Priest: Priest's Contemplations, Part 2", "category": "Lore", "platform": "Console"}, "1320763167": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "1320763168": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "1320763169": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "1758275411": {"name": "PromisesOfFezuul: The Promises of Fezuul al-Kazarr", "category": "Lore", "platform": "Console"}, "-139516026": {"name": "ProudWife: Bloodstained Letter", "category": "Lore", "platform": "Console"}, "3611879712": {"name": "Quill Fiend", "category": "Lore", "platform": "Console"}, "1276294793": {"name": "Rakanoth: Rakanoth, the Lord of Despair", "category": "Lore", "platform": "Console"}, "-1106592288": {"name": "Rakkis: Rakkis's Orders", "category": "Lore", "platform": "Console"}, "-1074332472": {"name": "RakkisHistory: The Testament of Rakkis, Part 1", "category": "Lore", "platform": "Console"}, "-1074332471": {"name": "RakkisHistory: The Testament of Rakkis, Part 2", "category": "Lore", "platform": "Console"}, "-1074332470": {"name": "RakkisHistory: The Testament of Rakkis, Part 3", "category": "Lore", "platform": "Console"}, "-1074332469": {"name": "RakkisHistory: The Testament of Rakkis, Part 4", "category": "Lore", "platform": "Console"}, "-1074332468": {"name": "RakkisHistory: The Testament of Rakkis, Part 5", "category": "Lore", "platform": "Console"}, "-1074332467": {"name": "RakkisHistory: The Testament of Rakkis, Part 6", "category": "Lore", "platform": "Console"}, "-1074332466": {"name": "RakkisHistory: The Testament of Rakkis, Part 7", "category": "Lore", "platform": "Console"}, "-1074332465": {"name": "RakkisHistory: The Testament of Rakkis, Part 8", "category": "Lore", "platform": "Console"}, "-1074332464": {"name": "RakkisHistory: The Testament of Rakkis, Part 9", "category": "Lore", "platform": "Console"}, "1960749072": {"name": "Realmwalker: The Realmwalker", "category": "Lore", "platform": "Console"}, "3580037015": {"name": "Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "2895121073": {"name": "Scavenger", "category": "Lore", "platform": "Console"}, "-561655662": {"name": "Scoundrel: Scoundrel's Journal", "category": "Lore", "platform": "Console"}, "648677458": {"name": "Siege: Missive from Imperius", "category": "Lore", "platform": "Console"}, "-1327438701": {"name": "Siege: Siege Runes", "category": "Lore", "platform": "Console"}, "1667935935": {"name": "SkeletonKing: The Skeleton King", "category": "Lore", "platform": "Console"}, "-21507498": {"name": "SpiderQueen: The Spider Queen", "category": "Lore", "platform": "Console"}, "1881837798": {"name": "Templar: Bloodied Parchment", "category": "Lore", "platform": "Console"}, "1881837797": {"name": "Templar: Bloodied Scraps", "category": "Lore", "platform": "Console"}, "1792637338": {"name": "TemplarMaester: Grand Maester's Journal", "category": "Lore", "platform": "Console"}, "1776052671": {"name": "TemplarMaester: The Maester's Proclamation", "category": "Lore", "platform": "Console"}, "464105835": {"name": "Tinker: Wandering Tinker's Diary", "category": "Lore", "platform": "Console"}, "3594507733": {"name": "Traveler's Journal", "category": "Lore", "platform": "Console"}, "732715821": {"name": "UriktheSeer: Notes of Urik the Seer, Part 1", "category": "Lore", "platform": "Console"}, "732715822": {"name": "UriktheSeer: Notes of Urik the Seer, Part 2", "category": "Lore", "platform": "Console"}, "732715823": {"name": "UriktheSeer: Notes of Urik the Seer, Part 3", "category": "Lore", "platform": "Console"}, "-645692806": {"name": "Urzael: Urzael's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-645692805": {"name": "Urzael: Urzael's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-645692804": {"name": "Urzael: Urzael's Journal, Part 3", "category": "Lore", "platform": "Console"}, "4005355618": {"name": "Villager's Journal", "category": "Lore", "platform": "Console"}, "-1451420418": {"name": "WaterPuzzle: The Chamber of Faces", "category": "Lore", "platform": "Console"}, "1223177093": {"name": "Westm: It's a Trap", "category": "Lore", "platform": "Console"}, "831394876": {"name": "Westm: The Cult Shall Rise Again", "category": "Lore", "platform": "Console"}, "913430382": {"name": "Westm: The King's Journal, Part 1", "category": "Lore", "platform": "Console"}, "913430383": {"name": "Westm: The King's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1218326648": {"name": "Westm: The King's Note to Lord Wynton", "category": "Lore", "platform": "Console"}, "1526997743": {"name": "Westm: The Plague Tunnels", "category": "Lore", "platform": "Console"}, "-1469466389": {"name": "Westm: The Souls of Westmarch", "category": "Lore", "platform": "Console"}, "-916745255": {"name": "Westmarch: The History of Westmarch, Part 1", "category": "Lore", "platform": "Console"}, "-916745254": {"name": "Westmarch: The History of Westmarch, Part 2", "category": "Lore", "platform": "Console"}, "-916745253": {"name": "Westmarch: The History of Westmarch, Part 3", "category": "Lore", "platform": "Console"}, "-916745252": {"name": "Westmarch: The History of Westmarch, Part 4", "category": "Lore", "platform": "Console"}, "-916745251": {"name": "Westmarch: The History of Westmarch, Part 5", "category": "Lore", "platform": "Console"}, "-916745250": {"name": "Westmarch: The History of Westmarch, Part 6", "category": "Lore", "platform": "Console"}, "-916745249": {"name": "Westmarch: The History of Westmarch, Part 7", "category": "Lore", "platform": "Console"}, "-223645750": {"name": "X1 Lore Besitary RevenantShieldGuard", "category": "Lore", "platform": "Console"}, "1571805338": {"name": "X1 Lore Bestiary GhastlySeraph", "category": "Lore", "platform": "Console"}, "1836003891": {"name": "X1 Lore Bestiary RevenantArcher", "category": "Lore", "platform": "Console"}, "-1635681275": {"name": "x1 Bog Lore AdriaBetrayal", "category": "Lore", "platform": "Console"}, "-8314071": {"name": "x1 Bog Lore AdriaEmptiness", "category": "Lore", "platform": "Console"}, "1923206206": {"name": "x1 Bog Lore AdriaLosingControl", "category": "Lore", "platform": "Console"}, "2045759001": {"name": "x1 Bog Lore AdriaNewHost", "category": "Lore", "platform": "Console"}, "118984382": {"name": "x1 Bog Lore AdriaPower", "category": "Lore", "platform": "Console"}, "-134175942": {"name": "x1 Bog Lore AdriaVoices", "category": "Lore", "platform": "Console"}, "-1074332440": {"name": "x1 Bog Lore RakkisHistory10", "category": "Lore", "platform": "Console"}, "-1656026178": {"name": "01: Club (DPS 5.4-6.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026177": {"name": "02: Cudgel (DPS 9.6-11.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026176": {"name": "03: Morning Star (DPS 15.0-16.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026175": {"name": "04: Mace (DPS 18.6-20.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026174": {"name": "05: Flanged Mace (DPS 23.4-25.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026173": {"name": "06: Hammer (DPS 28.2-30.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026172": {"name": "07: War Gavel (DPS 33.6-35.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025089": {"name": "08: Bludgeon (DPS 43.8-45.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025088": {"name": "09: Spiked Baton (DPS 52.2-54.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025087": {"name": "10: War Mace (DPS 62.4-64.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025086": {"name": "11: Gada (DPS 73.2-75.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025085": {"name": "12: Pernach (DPS 85.2-88.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025084": {"name": "13: Heavy Hammer (DPS 102.0-105.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025083": {"name": "14: War Hammer (DPS 124.8-128.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656024000": {"name": "15: Skull Crusher (DPS 138.0-143.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023999": {"name": "16: Truncheon (DPS 155.4-160.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023998": {"name": "17: Death Mace (DPS 174.0-179.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023997": {"name": "18: Tripyor (DPS 192.6-199.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023996": {"name": "19: Goedendag (DPS 237.0-244.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023995": {"name": "20: Crag Hammer (DPS 273.6-282.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023994": {"name": "21: Demolisher (DPS 318.0-327.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022911": {"name": "22: Brutalizer (DPS 429.6-436.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022910": {"name": "23: Skullsplitter (DPS 540.6-547.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099965": {"name": "Art Test Mace One-Handed 1", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099964": {"name": "Art Test Mace One-Handed 2", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099963": {"name": "Art Test Mace One-Handed 3", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099962": {"name": "Art Test Mace One-Handed 4", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099961": {"name": "Art Test Mace One-Handed 5", "category": "Maces, One-Handed", "platform": "Console"}, "-1473010435": {"name": "Legendary: Deadeye's Mace (Patch 2.1.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894988668": {"name": "Legendary: Devastator", "category": "Maces, One-Handed", "platform": "Console"}, "1889806096": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1889808540": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325116": {"name": "Legendary: Earthshatter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895276164": {"name": "Legendary: Echoing Fury", "category": "Maces, One-Handed", "platform": "Console"}, "1880318728": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1880321172": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325108": {"name": "Legendary: Echoing Fury (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856068897": {"name": "Legendary: Jace's Hammer of Vigilance", "category": "Maces, One-Handed", "platform": "Console"}, "-1856140771": {"name": "Legendary: Mad Monarch's Scepter", "category": "Maces, One-Handed", "platform": "Console"}, "-1895024605": {"name": "Legendary: Nailbiter", "category": "Maces, One-Handed", "platform": "Console"}, "1888620175": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1888622619": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325115": {"name": "Legendary: Nailbiter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895204290": {"name": "Legendary: Neanderthal", "category": "Maces, One-Handed", "platform": "Console"}, "1882690570": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1882693014": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325110": {"name": "Legendary: Neanderthal (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895132416": {"name": "Legendary: Nutcracker", "category": "Maces, One-Handed", "platform": "Console"}, "1885062412": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1885064856": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325112": {"name": "Legendary: Nutcracker (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895240227": {"name": "Legendary: Odyn Son", "category": "Maces, One-Handed", "platform": "Console"}, "1881504649": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1881507093": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325109": {"name": "Legendary: Odyn Son (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856104834": {"name": "Legendary: Solanium", "category": "Maces, One-Handed", "platform": "Console"}, "-1894090243": {"name": "Legendary: Sun Keeper", "category": "Maces, One-Handed", "platform": "Console"}, "1919454121": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1919456565": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325141": {"name": "Legendary: Sun Keeper (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895060542": {"name": "Legendary: Telranden's Hand", "category": "Maces, One-Handed", "platform": "Console"}, "1887434254": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1887436698": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325114": {"name": "Legendary: Telranden's Hand (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894126180": {"name": "Legendary: Wirt's Original Leg", "category": "Maces, One-Handed", "platform": "Console"}, "1918268200": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1918270644": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325140": {"name": "Legendary: Wirt's Original Leg (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1616890785": {"name": "01: Two-Handed Club (DPS 15.8-16.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890784": {"name": "02: Two-Handed Mace (DPS 20.3-21.6)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890783": {"name": "03: Two-Handed Hammer (DPS 24.8-26.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890782": {"name": "04: Maul (DPS 31.5-32.9)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890781": {"name": "05: Mallet (DPS 37.8-40.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890780": {"name": "06: Great Hammer (DPS 45.5-48.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889696": {"name": "07: Dire Club (DPS 55.8-58.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889695": {"name": "08: Dire Mace (DPS 66.6-70.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889694": {"name": "09: Sledge Hammer (DPS 81.9-86.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889693": {"name": "10: Great Maul (DPS 98.6-104.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889692": {"name": "11: War Mallet (DPS 117.9-124.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889691": {"name": "12: Rock Breaker (DPS 144.5-151.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888607": {"name": "13: Wrecker (DPS 196.7-206.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888606": {"name": "14: Dread Mace (DPS 249.3-260.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888605": {"name": "15: War Sledge (DPS 315.9-326.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888604": {"name": "16: War Maul (DPS 437.9-448.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888603": {"name": "17: Slag Hammer (DPS 518.4-529.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888602": {"name": "18: Doom Hammer (DPS 613.4-624.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887518": {"name": "19: Royal Mace (DPS 774.0-786.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887517": {"name": "20: Persuader (DPS 1058.5-1070.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064028": {"name": "Art Test Mace Two-Handed 1", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064027": {"name": "Art Test Mace Two-Handed 2", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064026": {"name": "Art Test Mace Two-Handed 3", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064025": {"name": "Art Test Mace Two-Handed 4", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064024": {"name": "Art Test Mace Two-Handed 5", "category": "Maces, Two-Handed", "platform": "Console"}, "59108159": {"name": "Legendary: Arthef's Spark of Life", "category": "Maces, Two-Handed", "platform": "Console"}, "1950491947": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1950494391": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460503": {"name": "Legendary: Boneshatter (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954049710": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954052154": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460506": {"name": "Legendary: Cataclysm (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59036285": {"name": "Legendary: Crushbane", "category": "Maces, Two-Handed", "platform": "Console"}, "1948120105": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1948122549": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460501": {"name": "Legendary: Crushbane (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323781": {"name": "Legendary: Schaefer's Hammer", "category": "Maces, Two-Handed", "platform": "Console"}, "1957607473": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1957609917": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460509": {"name": "Legendary: Schaefer's Hammer (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60186269": {"name": "Legendary: Skywarden", "category": "Maces, Two-Handed", "platform": "Console"}, "1986069577": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1986072021": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460533": {"name": "Legendary: Skywarden (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59072222": {"name": "Legendary: Sledge of Athskeleng", "category": "Maces, Two-Handed", "platform": "Console"}, "1949306026": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1949308470": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460502": {"name": "Legendary: Sledge of Athskeleng (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "98279489": {"name": "Legendary: Soulsmasher", "category": "Maces, Two-Handed", "platform": "Console"}, "59215970": {"name": "Legendary: Sunder", "category": "Maces, Two-Handed", "platform": "Console"}, "98243552": {"name": "Legendary: The Furnace", "category": "Maces, Two-Handed", "platform": "Console"}, "60258143": {"name": "Legendary: Wrath of the Bone King", "category": "Maces, Two-Handed", "platform": "Console"}, "1988441419": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1988443863": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460535": {"name": "Legendary: Wrath of the Bone King (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60257879": {"name": "Legendary: Wrath of the Bone King (Patch 2.1.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323518": {"name": "legendary: Schaefer's Hammer (Patch 2.2.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "2112155406": {"name": "01: Warrior Belt (AR 26-30)", "category": "Mighty Belts", "platform": "Console"}, "2112155407": {"name": "02: Harness (AR 32-37)", "category": "Mighty Belts", "platform": "Console"}, "2112155408": {"name": "03: Braid (AR 53-61)", "category": "Mighty Belts", "platform": "Console"}, "2112155409": {"name": "04: Grand Belt (AR 74-100)", "category": "Mighty Belts", "platform": "Console"}, "2112156495": {"name": "05: Baldric (AR 101-132)", "category": "Mighty Belts", "platform": "Console"}, "2112156496": {"name": "06: Blade Harness (AR 133-164)", "category": "Mighty Belts", "platform": "Console"}, "2112156497": {"name": "07: Iron Braid (AR 165-205)", "category": "Mighty Belts", "platform": "Console"}, "2112156498": {"name": "08: Steel Chain (AR 206-225)", "category": "Mighty Belts", "platform": "Console"}, "2112157584": {"name": "09: Lock (AR 226-252)", "category": "Mighty Belts", "platform": "Console"}, "2112157585": {"name": "10: Bronze Links (AR 253-285)", "category": "Mighty Belts", "platform": "Console"}, "2112157586": {"name": "11: Heavy Baldric (AR 286-318)", "category": "Mighty Belts", "platform": "Console"}, "2112157587": {"name": "12: Grand Chain (AR 320-419)", "category": "Mighty Belts", "platform": "Console"}, "2112157588": {"name": "13: Platinum Lock (AR 420-586)", "category": "Mighty Belts", "platform": "Console"}, "2112157589": {"name": "14: Mighty Scourge (AR 586-674)", "category": "Mighty Belts", "platform": "Console"}, "325816755": {"name": "Art Test BarbBelt 1", "category": "Mighty Belts", "platform": "Console"}, "325816756": {"name": "Art Test BarbBelt 2", "category": "Mighty Belts", "platform": "Console"}, "325816757": {"name": "Art Test BarbBelt 3", "category": "Mighty Belts", "platform": "Console"}, "325816758": {"name": "Art Test BarbBelt 4", "category": "Mighty Belts", "platform": "Console"}, "325816759": {"name": "Art Test BarbBelt 5", "category": "Mighty Belts", "platform": "Console"}, "924282931": {"name": "Legendary: Ageless Might", "category": "Mighty Belts", "platform": "Console"}, "436488351": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "436490795": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630773": {"name": "Legendary: Ageless Might (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963274576": {"name": "Legendary: Ancients' Discontent", "category": "Mighty Belts", "platform": "Console"}, "963166765": {"name": "Legendary: Chilanik's Chain", "category": "Mighty Belts", "platform": "Console"}, "924031372": {"name": "Legendary: Dread Iron", "category": "Mighty Belts", "platform": "Console"}, "428186904": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "428189348": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630780": {"name": "Legendary: Dread Iron (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924139183": {"name": "Legendary: Girdle of Giants", "category": "Mighty Belts", "platform": "Console"}, "431744667": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "431747111": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630777": {"name": "Legendary: Girdle of Giants (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924246994": {"name": "Legendary: Kotuur's Brace", "category": "Mighty Belts", "platform": "Console"}, "435302430": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "435304874": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630774": {"name": "Legendary: Kotuur's Brace (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924175120": {"name": "Legendary: Lamentation", "category": "Mighty Belts", "platform": "Console"}, "432930588": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "432933032": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630776": {"name": "Legendary: Lamentation (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924174856": {"name": "Legendary: Lamentation (Patch 2.1.0)", "category": "Mighty Belts", "platform": "Console"}, "924067309": {"name": "Legendary: Pride of Cassius", "category": "Mighty Belts", "platform": "Console"}, "429372825": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "429375269": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630779": {"name": "Legendary: Pride of Cassius (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963310513": {"name": "Legendary: Promise of the Doomed Forebearer", "category": "Mighty Belts", "platform": "Console"}, "924211057": {"name": "Legendary: The Undisputed Champion", "category": "Mighty Belts", "platform": "Console"}, "434116509": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "434118953": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630775": {"name": "Legendary: The Undisputed Champion (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737386": {"name": "Legendary: The Undisputed Champion (Patch 2.1.2)", "category": "Mighty Belts", "platform": "Console"}, "430558746": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "430561190": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630778": {"name": "Legendary: Thunder God's Vigor (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963238639": {"name": "Legendary: Wodir Harness", "category": "Mighty Belts", "platform": "Console"}, "963202702": {"name": "Legendary: x1_BarbBelt_norm_unique_11", "category": "Mighty Belts", "platform": "Console"}, "-1303630772": {"name": "Set: Immortal King's Detail (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924318868": {"name": "Set: Immortal King's Tribal Binding", "category": "Mighty Belts", "platform": "Console"}, "437674272": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "437676716": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737381": {"name": "legendary: Dread Iron (Patch 2.2.0)", "category": "Mighty Belts", "platform": "Console"}, "290066501": {"name": "01: Sickle (DPS 11.1-12.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066502": {"name": "02: Carver (DPS 14.3-16.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066503": {"name": "03: Maw Axe (DPS 21.5-23.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066504": {"name": "04: War Blade (DPS 31.2-33.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067590": {"name": "05: Scythe (DPS 36.4-38.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067591": {"name": "06: Machete (DPS 54.6-56.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067592": {"name": "07: Gutwrench (DPS 82.6-86.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067593": {"name": "08: Rage Blade (DPS 118.3-122.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068679": {"name": "09: Reaper (DPS 153.4-159.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068680": {"name": "10: Chopsword (DPS 206.7-214.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068681": {"name": "11: Massacre Axe (DPS 238.6-246.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068682": {"name": "12: Slayer (DPS 277.6-285.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069768": {"name": "13: Caldean Sword (DPS 371.8-379.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069769": {"name": "14: Limb Cleaver (DPS 461.5-469.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026495": {"name": "Art Test Mighty One-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026496": {"name": "Art Test Mighty One-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026497": {"name": "Art Test Mighty One-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026498": {"name": "Art Test Mighty One-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026499": {"name": "Art Test Mighty One-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062432": {"name": "Art Test Mighty Two-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062433": {"name": "Art Test Mighty Two-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062434": {"name": "Art Test Mighty Two-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062435": {"name": "Art Test Mighty Two-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062436": {"name": "Art Test Mighty Two-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511328230": {"name": "Legendary: Ambo's Pride", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665698662": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665701106": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986962": {"name": "Legendary: Ambo's Pride (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512406340": {"name": "Legendary: Blade of the Warlord", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630121032": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630123476": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986932": {"name": "Legendary: Blade of the Warlord (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473342821": {"name": "Legendary: Dishonored Legacy", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512370403": {"name": "Legendary: Fjord Cutter", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631306953": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631309397": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986933": {"name": "Legendary: Fjord Cutter (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625377348": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625379792": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986928": {"name": "Legendary: Harvest Moon (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473414695": {"name": "Legendary: Hellion Scale", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512550088": {"name": "Legendary: Night's Reaping", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473306884": {"name": "Legendary: Oathkeeper", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473378758": {"name": "Legendary: Remorseless", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986960": {"name": "Set: Bul-Kathos's Sacred Charge (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511400104": {"name": "Set: Bul-Kathos's Solemn Vow", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663326820": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663329264": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986961": {"name": "Set: Bul-Kathos's Tribal Guardian (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511364167": {"name": "Set: Bul-Kathos's Warrior Blood", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664512741": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664515185": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986965": {"name": "Set: Hallowed Destroyer (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511220419": {"name": "Set: Hallowed Nemesis", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669258869": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669256425": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "329201894": {"name": "01: Petrified Trunk (DPS 15.5-16.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201895": {"name": "02: Giant Sword (DPS 18.0-19.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201896": {"name": "03: Giant Hammer (DPS 25.5-27.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201897": {"name": "04: Giant Axe (DPS 36.0-37.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202983": {"name": "05: Redwood War Club (DPS 60.6-63.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202984": {"name": "06: Colossus Sword (DPS 81.5-86.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202985": {"name": "07: Crusher (DPS 110.5-116.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202986": {"name": "08: Colossus Axe (DPS 169.0-176.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204072": {"name": "09: Battersmash (DPS 248.5-257.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204073": {"name": "10: Titan Sword (DPS 397.5-408.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204074": {"name": "11: Behemoth (DPS 469.0-481.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204075": {"name": "12: Titan Axe (DPS 555.0-567.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205161": {"name": "13: Hassan Chopper (DPS 691.9-703.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205162": {"name": "14: Steppes Smasher (DPS 940.0-951.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441870172": {"name": "Legendary: Bastion's Revered", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696736488": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696738932": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122324": {"name": "Legendary: Bastion's Revered (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441869908": {"name": "Legendary: Bastion's Revered (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441942046": {"name": "Legendary: Fury of the Vanished Peak", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699108330": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699110774": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122326": {"name": "Legendary: Fury of the Vanished Peak (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-96858155": {"name": "Legendary: Grim Reaper", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "480897754": {"name": "Legendary: Madawc's Sorrow", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-389442788": {"name": "Legendary: The Blackrock Destroyer (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441762361": {"name": "Legendary: The Gavel of Judgment", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693178725": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693181169": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122321": {"name": "Legendary: The Gavel of Judgment (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733500039": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733502483": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122355": {"name": "Legendary: Unending War (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442984219": {"name": "Legendary: War of the Dead", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442912345": {"name": "Set: Immortal King's Boulder Breaker", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731128197": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731130641": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122353": {"name": "Set: Immortal King's Stone Crusher (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "2125089234": {"name": "legendary: The Gavel Of Judgement (Patch 2.2.0)", "category": "Mightys, Two-Handed", "platform": "Console"}, "-136816475": {"name": "01: Wanga Doll (+1-2 DMG)", "category": "Mojos", "platform": "Console"}, "-136816474": {"name": "02: Shrunken Head (+(2-3)-(3-5) DMG)", "category": "Mojos", "platform": "Console"}, "-136816473": {"name": "03: Caged Horror (+(3-5)-(4-8) DMG)", "category": "Mojos", "platform": "Console"}, "-136816472": {"name": "04: Viper (+(3-6)-(4-10) DMG)", "category": "Mojos", "platform": "Console"}, "-136815386": {"name": "05: Gris-Gris Moppet (+(4-8)-(5-13) DMG)", "category": "Mojos", "platform": "Console"}, "-136815385": {"name": "06: Tzantza (+(6-11)-(7-19) DMG)", "category": "Mojos", "platform": "Console"}, "-136815384": {"name": "07: Living Tentacle (+(8-16)-(9-29) DMG)", "category": "Mojos", "platform": "Console"}, "-136815383": {"name": "08: Copperhead (+(13-26)-(14-45) DMG)", "category": "Mojos", "platform": "Console"}, "-136814297": {"name": "09: Wicker Man (+(17-39)-(18-114) DMG)", "category": "Mojos", "platform": "Console"}, "-136814296": {"name": "10: Muttering Head (+(19-58)-(20-213) DMG)", "category": "Mojos", "platform": "Console"}, "-136814295": {"name": "11: Unspeakable Thing (+(24-72)-(25-265) DMG)", "category": "Mojos", "platform": "Console"}, "-136814294": {"name": "12: Kurastian Asp (+(28-110)-(29-405) DMG)", "category": "Mojos", "platform": "Console"}, "-136814293": {"name": "13: Skull Talisman (+(126-158)-(127-190) DMG)", "category": "Mojos", "platform": "Console"}, "-136814292": {"name": "14: Thing That Should Not Be (+(262-328)-(263-394) DMG)", "category": "Mojos", "platform": "Console"}, "1629900554": {"name": "Art Test Mojo 1", "category": "Mojos", "platform": "Console"}, "1629900555": {"name": "Art Test Mojo 2", "category": "Mojos", "platform": "Console"}, "1629900556": {"name": "Art Test Mojo 3", "category": "Mojos", "platform": "Console"}, "1629900557": {"name": "Art Test Mojo 4", "category": "Mojos", "platform": "Console"}, "1629900558": {"name": "Art Test Mojo 5", "category": "Mojos", "platform": "Console"}, "-1667471440": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-1667468996": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608100": {"name": "Legendary: Bitterness (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961544827": {"name": "Legendary: Gazing Demise", "category": "Mojos", "platform": "Console"}, "-1666285519": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-1666283075": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608099": {"name": "Legendary: Gazing Demise (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961508890": {"name": "Legendary: Homunculus", "category": "Mojos", "platform": "Console"}, "-1665099598": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-1665097154": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608098": {"name": "Legendary: Homunculus (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922445371": {"name": "Legendary: Shukrani's Triumph", "category": "Mojos", "platform": "Console"}, "-922409434": {"name": "Legendary: Sorrowful Countenance", "category": "Mojos", "platform": "Console"}, "-961580764": {"name": "Legendary: Spite", "category": "Mojos", "platform": "Console"}, "-961329205": {"name": "Legendary: Thing of the Deep", "category": "Mojos", "platform": "Console"}, "-1659169993": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-1659167549": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608093": {"name": "Legendary: Thing of the Deep (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961365142": {"name": "Legendary: Uhkapian Serpent", "category": "Mojos", "platform": "Console"}, "-1660355914": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-1660353470": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608094": {"name": "Legendary: Uhkapian Serpent (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922373497": {"name": "Legendary: Vile Hive", "category": "Mojos", "platform": "Console"}, "1413644935": {"name": "P2 mojo norm Legendary 01", "category": "Mojos", "platform": "Console"}, "1413644936": {"name": "P2 mojo norm Legendary 02", "category": "Mojos", "platform": "Console"}, "1413644937": {"name": "P2 mojo norm Legendary 03", "category": "Mojos", "platform": "Console"}, "-960466717": {"name": "Set: Manajuma's Gory Fetch", "category": "Mojos", "platform": "Console"}, "-1630707889": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-1630705445": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608069": {"name": "Set: Manajuma's Ritual Prize (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-63608068": {"name": "Set: Zunimassa's Ferocity (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-960430780": {"name": "Set: Zunimassa's String of Skulls", "category": "Mojos", "platform": "Console"}, "-1629521968": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-1629519524": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-961509153": {"name": "legendary: Homunculus (Patch 2.2.0)", "category": "Mojos", "platform": "Console"}, "-734094289": {"name": "A Servant's Journal", "category": "NPC Items", "platform": "Console"}, "1372800103": {"name": "A Summoner's Journal", "category": "NPC Items", "platform": "Console"}, "1366034119": {"name": "A2C2EmptyCage", "category": "NPC Items", "platform": "Console"}, "-894018760": {"name": "A2C2HusamHead", "category": "NPC Items", "platform": "Console"}, "1506900471": {"name": "A2C2NecromancerCrystal", "category": "NPC Items", "platform": "Console"}, "-1176971336": {"name": "A2C2OreBag", "category": "NPC Items", "platform": "Console"}, "-701130141": {"name": "A2C2RygnarIdol", "category": "NPC Items", "platform": "Console"}, "-1969048485": {"name": "A2C2SharkHide", "category": "NPC Items", "platform": "Console"}, "524402999": {"name": "A2C2SharkNecklace", "category": "NPC Items", "platform": "Console"}, "297778632": {"name": "A2C2WantedPoster", "category": "NPC Items", "platform": "Console"}, "1135854513": {"name": "A2C2WantedPosterGood", "category": "NPC Items", "platform": "Console"}, "-284487217": {"name": "ActIQ2 RatMageSkull", "category": "NPC Items", "platform": "Console"}, "956379400": {"name": "Ahren's Hammer", "category": "NPC Items", "platform": "Console"}, "893398919": {"name": "AlbrechtsRemains", "category": "NPC Items", "platform": "Console"}, "-1240838296": {"name": "Ancient Medallion", "category": "NPC Items", "platform": "Console"}, "1475923527": {"name": "Ancient Tome Page", "category": "NPC Items", "platform": "Console"}, "-831189640": {"name": "Angelic Seal", "category": "NPC Items", "platform": "Console"}, "-885657485": {"name": "Antique Box", "category": "NPC Items", "platform": "Console"}, "-309356827": {"name": "Aqueduct Key", "category": "NPC Items", "platform": "Console"}, "493907862": {"name": "Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "-470655325": {"name": "Beacon of Honor", "category": "NPC Items", "platform": "Console"}, "-470655324": {"name": "Beacon of Light", "category": "NPC Items", "platform": "Console"}, "-246893943": {"name": "Black Soulstone", "category": "NPC Items", "platform": "Console"}, "504121446": {"name": "Blackened Journal", "category": "NPC Items", "platform": "Console"}, "1818884426": {"name": "Blacksmith's Tome", "category": "NPC Items", "platform": "Console"}, "263122102": {"name": "Bogus Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "944034263": {"name": "Broken Crown", "category": "NPC Items", "platform": "Console"}, "-63906132": {"name": "Broken Doll", "category": "NPC Items", "platform": "Console"}, "1201838506": {"name": "Calldown Grenade", "category": "NPC Items", "platform": "Console"}, "-1797642504": {"name": "Caravan Inventory List", "category": "NPC Items", "platform": "Console"}, "-110888638": {"name": "Chain Key", "category": "NPC Items", "platform": "Console"}, "1061128541": {"name": "Cloud Fire", "category": "NPC Items", "platform": "Console"}, "-565248060": {"name": "Cultist Cellar Key", "category": "NPC Items", "platform": "Console"}, "-613437014": {"name": "DevilsHand: Aidan's Memento", "category": "NPC Items", "platform": "Console"}, "-613616703": {"name": "DevilsHand: Broken Oath", "category": "NPC Items", "platform": "Console"}, "-613437017": {"name": "DevilsHand: Cain's Memento", "category": "NPC Items", "platform": "Console"}, "-613544825": {"name": "DevilsHand: Dark Coven Familiar", "category": "NPC Items", "platform": "Console"}, "-613544828": {"name": "DevilsHand: Dark Coven Insignia", "category": "NPC Items", "platform": "Console"}, "-613544826": {"name": "DevilsHand: Dark Coven Jar of Reagents", "category": "NPC Items", "platform": "Console"}, "-613544829": {"name": "DevilsHand: Dark Coven Scroll of Illusions", "category": "NPC Items", "platform": "Console"}, "-613544827": {"name": "DevilsHand: Dark Coven Torturing Device", "category": "NPC Items", "platform": "Console"}, "-613437012": {"name": "DevilsHand: Gideon's Memento", "category": "NPC Items", "platform": "Console"}, "-613508887": {"name": "DevilsHand: Icon of Envy", "category": "NPC Items", "platform": "Console"}, "-613508886": {"name": "DevilsHand: Icon of Gluttony", "category": "NPC Items", "platform": "Console"}, "-613508891": {"name": "DevilsHand: Icon of Greed", "category": "NPC Items", "platform": "Console"}, "-613508888": {"name": "DevilsHand: Icon of Lust", "category": "NPC Items", "platform": "Console"}, "-613508889": {"name": "DevilsHand: Icon of Pride", "category": "NPC Items", "platform": "Console"}, "-613508890": {"name": "DevilsHand: Icon of Sloth", "category": "NPC Items", "platform": "Console"}, "-613508892": {"name": "DevilsHand: Icon of Wrath", "category": "NPC Items", "platform": "Console"}, "-613437016": {"name": "DevilsHand: Leah's Memento", "category": "NPC Items", "platform": "Console"}, "-613616702": {"name": "DevilsHand: Love's Oath", "category": "NPC Items", "platform": "Console"}, "-613437013": {"name": "DevilsHand: Ogden's Memento", "category": "NPC Items", "platform": "Console"}, "-613616701": {"name": "DevilsHand: Selfless Oath", "category": "NPC Items", "platform": "Console"}, "-613580763": {"name": "DevilsHand: The Black King's Bloodied Gauntlet", "category": "NPC Items", "platform": "Console"}, "-613580762": {"name": "DevilsHand: The Black King's Journal", "category": "NPC Items", "platform": "Console"}, "-613580765": {"name": "DevilsHand: The Black King's Skull", "category": "NPC Items", "platform": "Console"}, "-613580764": {"name": "DevilsHand: The Black King's Tainted Elixir", "category": "NPC Items", "platform": "Console"}, "-613580766": {"name": "DevilsHand: The Black King's Trophy", "category": "NPC Items", "platform": "Console"}, "-613437018": {"name": "DevilsHand: Warriv's Memento", "category": "NPC Items", "platform": "Console"}, "-613437015": {"name": "DevilsHand: Wirt's Memento", "category": "NPC Items", "platform": "Console"}, "-473140170": {"name": "Event: Alchemist Concoction", "category": "NPC Items", "platform": "Console"}, "452865871": {"name": "Event: Aperture Key", "category": "NPC Items", "platform": "Console"}, "-1312544703": {"name": "Event: Battle Elixir", "category": "NPC Items", "platform": "Console"}, "66225719": {"name": "Event: Battlefield Reports", "category": "NPC Items", "platform": "Console"}, "-1961273523": {"name": "Event: Bones of the Matriarch1", "category": "NPC Items", "platform": "Console"}, "-1961273522": {"name": "Event: Bones of the Matriarch2", "category": "NPC Items", "platform": "Console"}, "-1961273521": {"name": "Event: Bones of the Matriarch3", "category": "NPC Items", "platform": "Console"}, "1197498604": {"name": "Event: Dusty Old Tome", "category": "NPC Items", "platform": "Console"}, "463155324": {"name": "Event: Forboding Tome", "category": "NPC Items", "platform": "Console"}, "-934435532": {"name": "Event: Jeweled Scabbard", "category": "NPC Items", "platform": "Console"}, "1465477567": {"name": "Event: Medical Supplies", "category": "NPC Items", "platform": "Console"}, "-694090266": {"name": "Event: Officer's Orders", "category": "NPC Items", "platform": "Console"}, "-2013751652": {"name": "Event: Templar Object 1", "category": "NPC Items", "platform": "Console"}, "-1003233507": {"name": "Event: The Matriarch's Skeleton", "category": "NPC Items", "platform": "Console"}, "899528155": {"name": "FacePuzzleSmallKey", "category": "NPC Items", "platform": "Console"}, "-1986712818": {"name": "Fuad's Journal", "category": "NPC Items", "platform": "Console"}, "1331402556": {"name": "Greater Shard", "category": "NPC Items", "platform": "Console"}, "301784336": {"name": "Heretic Text", "category": "NPC Items", "platform": "Console"}, "-705827599": {"name": "HunterJournal", "category": "NPC Items", "platform": "Console"}, "1742022798": {"name": "Iron Wolf Captain's Journal", "category": "NPC Items", "platform": "Console"}, "680369210": {"name": "Jail Gate Key", "category": "NPC Items", "platform": "Console"}, "-78029774": {"name": "Jelisa's Wedding Ring", "category": "NPC Items", "platform": "Console"}, "1018820302": {"name": "Jeweler's Crucible", "category": "NPC Items", "platform": "Console"}, "872964849": {"name": "Journal of Hansan Haile, Captain", "category": "NPC Items", "platform": "Console"}, "1264544813": {"name": "Khan's Tomb Key", "category": "NPC Items", "platform": "Console"}, "-1071052922": {"name": "Kulle's Blood", "category": "NPC Items", "platform": "Console"}, "-1341834848": {"name": "Kulle's Body", "category": "NPC Items", "platform": "Console"}, "-1341834849": {"name": "Kulle's Heart", "category": "NPC Items", "platform": "Console"}, "425198027": {"name": "Larus's Log", "category": "NPC Items", "platform": "Console"}, "1790135009": {"name": "Mausoleum Key", "category": "NPC Items", "platform": "Console"}, "-397905230": {"name": "Mira's Letter to Haedrig", "category": "NPC Items", "platform": "Console"}, "-1140969500": {"name": "Mysterious Box", "category": "NPC Items", "platform": "Console"}, "1816611999": {"name": "Mystery Amulet", "category": "NPC Items", "platform": "Console"}, "-1493063970": {"name": "Mystery Belt", "category": "NPC Items", "platform": "Console"}, "-2026108002": {"name": "Mystery Boots", "category": "NPC Items", "platform": "Console"}, "1281756953": {"name": "Mystery Bracers", "category": "NPC Items", "platform": "Console"}, "-594428401": {"name": "Mystery Chest Armor", "category": "NPC Items", "platform": "Console"}, "2050033703": {"name": "Mystery Gloves", "category": "NPC Items", "platform": "Console"}, "-1492848355": {"name": "Mystery Helm", "category": "NPC Items", "platform": "Console"}, "-1492657844": {"name": "Mystery Mojo", "category": "NPC Items", "platform": "Console"}, "215071258": {"name": "Mystery Orb", "category": "NPC Items", "platform": "Console"}, "-2010009315": {"name": "Mystery Pants", "category": "NPC Items", "platform": "Console"}, "-1843121997": {"name": "Mystery Quiver", "category": "NPC Items", "platform": "Console"}, "-1492484569": {"name": "Mystery Ring", "category": "NPC Items", "platform": "Console"}, "-1780286480": {"name": "Mystery Shield", "category": "NPC Items", "platform": "Console"}, "-537237168": {"name": "Mystery Shoulders", "category": "NPC Items", "platform": "Console"}, "-767866790": {"name": "Mystery Weapon, One-Handed", "category": "NPC Items", "platform": "Console"}, "-1099096773": {"name": "Mystery Weapon, Two-Handed", "category": "NPC Items", "platform": "Console"}, "-1352920439": {"name": "Nephalem Cube", "category": "NPC Items", "platform": "Console"}, "1774254059": {"name": "Nephalem Shard", "category": "NPC Items", "platform": "Console"}, "-1224842764": {"name": "Note from Maghda", "category": "NPC Items", "platform": "Console"}, "1524078078": {"name": "Old Tristram Key", "category": "NPC Items", "platform": "Console"}, "1524684909": {"name": "Orn VaseB caOut Props", "category": "NPC Items", "platform": "Console"}, "1472347958": {"name": "Orn a2dun Zolt Centerpiece A", "category": "NPC Items", "platform": "Console"}, "1354327297": {"name": "Orn caOut Cauldron", "category": "NPC Items", "platform": "Console"}, "-330317735": {"name": "Orn caOut CrateA", "category": "NPC Items", "platform": "Console"}, "1360506355": {"name": "Orn caOut VendorStandB", "category": "NPC Items", "platform": "Console"}, "1823013658": {"name": "Orn trDun Cath Candlestand", "category": "NPC Items", "platform": "Console"}, "-479501418": {"name": "Orn trDun Cath LibraryTable", "category": "NPC Items", "platform": "Console"}, "582933236": {"name": "Orn trDun Gargoyle 01", "category": "NPC Items", "platform": "Console"}, "684496620": {"name": "Orn trDun Incense Burner", "category": "NPC Items", "platform": "Console"}, "1432424645": {"name": "Orn trDun Weaponrack", "category": "NPC Items", "platform": "Console"}, "-1232771108": {"name": "Primordial Key", "category": "NPC Items", "platform": "Console"}, "-1661570587": {"name": "Queen Asylla's Journal", "category": "NPC Items", "platform": "Console"}, "1490502399": {"name": "Release Lever", "category": "NPC Items", "platform": "Console"}, "-1106160196": {"name": "Relic of Purification", "category": "NPC Items", "platform": "Console"}, "1259412129": {"name": "ReligiousArtifact", "category": "NPC Items", "platform": "Console"}, "-255366628": {"name": "Resonating Crystal", "category": "NPC Items", "platform": "Console"}, "468192851": {"name": "Scroll of Companion", "category": "NPC Items", "platform": "Console"}, "-96106000": {"name": "Scroll of Mysteries", "category": "NPC Items", "platform": "Console"}, "1310326700": {"name": "Shamanic Khazra Staff", "category": "NPC Items", "platform": "Console"}, "140227858": {"name": "Shard", "category": "NPC Items", "platform": "Console"}, "-1223968557": {"name": "Shard of Resurrection", "category": "NPC Items", "platform": "Console"}, "-1703187309": {"name": "Shen's Loot", "category": "NPC Items", "platform": "Console"}, "753721399": {"name": "Skeleton King's Crown", "category": "NPC Items", "platform": "Console"}, "-1874288726": {"name": "Spider Queen Venom", "category": "NPC Items", "platform": "Console"}, "437383090": {"name": "Sword Blade", "category": "NPC Items", "platform": "Console"}, "-1027737429": {"name": "Sword Hilt", "category": "NPC Items", "platform": "Console"}, "457400460": {"name": "Sword Piece", "category": "NPC Items", "platform": "Console"}, "1360078715": {"name": "SwordOfJustice", "category": "NPC Items", "platform": "Console"}, "1163171450": {"name": "The Cultist's Head", "category": "NPC Items", "platform": "Console"}, "-718773999": {"name": "Three Broken Gems", "category": "NPC Items", "platform": "Console"}, "-797314365": {"name": "Town Portal Stone", "category": "NPC Items", "platform": "Console"}, "-608122705": {"name": "Treasure Hunter's Note", "category": "NPC Items", "platform": "Console"}, "1111843456": {"name": "Triune Smith's Tools", "category": "NPC Items", "platform": "Console"}, "-1062930416": {"name": "Vasily's Angelic Idol", "category": "NPC Items", "platform": "Console"}, "-290192033": {"name": "WestM_Food", "category": "NPC Items", "platform": "Console"}, "437221476": {"name": "ZakarumTotem", "category": "NPC Items", "platform": "Console"}, "-1464111916": {"name": "Zoltun Kulle Blood Vial", "category": "NPC Items", "platform": "Console"}, "609972295": {"name": "Zoltun Kulle's Blue Eye", "category": "NPC Items", "platform": "Console"}, "-1341834850": {"name": "Zoltun Kulle's Body", "category": "NPC Items", "platform": "Console"}, "395877111": {"name": "Zoltun Kulle's Completed Head", "category": "NPC Items", "platform": "Console"}, "-1345664746": {"name": "Zoltun Kulle's Head", "category": "NPC Items", "platform": "Console"}, "-674931800": {"name": "Zoltun Kulle's One Eyed Head", "category": "NPC Items", "platform": "Console"}, "-1345750695": {"name": "Zoltun Kulle's Red Eye", "category": "NPC Items", "platform": "Console"}, "892508204": {"name": "Zoltun Kulle's Rotting Head", "category": "NPC Items", "platform": "Console"}, "414825604": {"name": "Zoltun Kulle's Tome of the Nephalem", "category": "NPC Items", "platform": "Console"}, "-649774063": {"name": "px_DevilsHand_TestGlobe (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "87458782": {"name": "px_DevilsHand_TestGlobe_Dropped (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "-590920597": {"name": "Art_Test_Pants_10 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920596": {"name": "Art_Test_Pants_11 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920595": {"name": "Art_Test_Pants_12 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920594": {"name": "Art_Test_Pants_13 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920593": {"name": "Art_Test_Pants_14 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598560": {"name": "Art_Test_Pants_6 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598561": {"name": "Art_Test_Pants_7 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598562": {"name": "Art_Test_Pants_8 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598563": {"name": "Art_Test_Pants_9 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-1512732138": {"name": "01: Cloth Pants (AR 6-7)", "category": "Pants", "platform": "Console"}, "-1512732137": {"name": "02: Leather Pants (AR 18-21)", "category": "Pants", "platform": "Console"}, "-1512732136": {"name": "03: Hide Breeches (AR 33-38)", "category": "Pants", "platform": "Console"}, "-1512732135": {"name": "04: Chain Leggings (AR 48-62)", "category": "Pants", "platform": "Console"}, "-1512732134": {"name": "05: Faulds (AR 63-77)", "category": "Pants", "platform": "Console"}, "-1512732133": {"name": "06: Plate Leggings (AR 78-101)", "category": "Pants", "platform": "Console"}, "-1512731049": {"name": "07: Legwraps (AR 102-131)", "category": "Pants", "platform": "Console"}, "-1512731048": {"name": "08: Etched Pants (AR 132-161)", "category": "Pants", "platform": "Console"}, "-1512731047": {"name": "09: Chausses (AR 162-191)", "category": "Pants", "platform": "Console"}, "-1512731046": {"name": "10: Tassets (AR 192-224)", "category": "Pants", "platform": "Console"}, "-1512731045": {"name": "11: Boneweave Faulds (AR 225-247)", "category": "Pants", "platform": "Console"}, "-1512729960": {"name": "12: Leg Guards (AR 27-269)", "category": "Pants", "platform": "Console"}, "-1512729959": {"name": "13: Poleyns (AR 270-284)", "category": "Pants", "platform": "Console"}, "-1512729958": {"name": "14: Warlord Leg Plates (AR 285-322)", "category": "Pants", "platform": "Console"}, "-1512729957": {"name": "15: Schynbalds (AR 322-359)", "category": "Pants", "platform": "Console"}, "-1512729956": {"name": "16: Sovereign Tassets (AR 360-397)", "category": "Pants", "platform": "Console"}, "-1512729955": {"name": "17: Archon Faulds (AR 397-471)", "category": "Pants", "platform": "Console"}, "-1512729954": {"name": "18: Rakkisgard Leg Plates (AR 472-659)", "category": "Pants", "platform": "Console"}, "-1512729953": {"name": "19: Ascended Faulds (AR 660-759)", "category": "Pants", "platform": "Console"}, "1283598555": {"name": "Art Test Pants 1", "category": "Pants", "platform": "Console"}, "1283598556": {"name": "Art Test Pants 2", "category": "Pants", "platform": "Console"}, "1283598557": {"name": "Art Test Pants 3", "category": "Pants", "platform": "Console"}, "1283598558": {"name": "Art Test Pants 4", "category": "Pants", "platform": "Console"}, "1283598559": {"name": "Art Test Pants 5", "category": "Pants", "platform": "Console"}, "-586378095": {"name": "Legendary: Conqueror's Legguards (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "-735317930": {"name": "Legendary: Death's Bargain", "category": "Pants", "platform": "Console"}, "-774309575": {"name": "Legendary: Depth Diggers", "category": "Pants", "platform": "Console"}, "217510501": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "217512945": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "903144209": {"name": "Legendary: Depth Diggers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774309839": {"name": "Legendary: Depth Diggers (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "216324580": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "216327024": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "903144208": {"name": "Legendary: Gehennas (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774453323": {"name": "Legendary: Hammer Jammers", "category": "Pants", "platform": "Console"}, "212766817": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "212769261": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "903144205": {"name": "Legendary: Hammer Jammers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-735353867": {"name": "Legendary: Hexing Pants of Mr. Yan", "category": "Pants", "platform": "Console"}, "-305758345": {"name": "Legendary: Legs of the Sealed Valley", "category": "Pants", "platform": "Console"}, "-774273638": {"name": "Legendary: Pox Faulds", "category": "Pants", "platform": "Console"}, "218696422": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "218698866": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "903144210": {"name": "Legendary: Pox Faulds (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774345512": {"name": "Legendary: Skelon's Deceit", "category": "Pants", "platform": "Console"}, "-774489260": {"name": "Legendary: Swamp Land Waders", "category": "Pants", "platform": "Console"}, "211580896": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "211583340": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "903144204": {"name": "Legendary: Swamp Land Waders (Old-Legacy)", "category": "Pants", "platform": "Console"}, "903144212": {"name": "Set: Asheara's Cradle (Old-Legacy)", "category": "Pants", "platform": "Console"}, "221068264": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "221070708": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "-774201764": {"name": "Set: Asheara's Pace", "category": "Pants", "platform": "Console"}, "903144239": {"name": "Set: Blackthorne's Breeches (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773231465": {"name": "Set: Blackthorne's Jousting Mail", "category": "Pants", "platform": "Console"}, "253088131": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "253090575": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "-773339276": {"name": "Set: Cain's Habit", "category": "Pants", "platform": "Console"}, "903144236": {"name": "Set: Cain's Raiment (Old-Legacy)", "category": "Pants", "platform": "Console"}, "249530368": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "249532812": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "251902210": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "251904654": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "903144238": {"name": "Set: Captain Crimson's Codpiece (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773267402": {"name": "Set: Captain Crimson's Thrust", "category": "Pants", "platform": "Console"}, "825937515": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827015887": {"name": "Set: Cuisses of Akkhan", "category": "Pants", "platform": "Console"}, "903144240": {"name": "Set: Demon's Flesh (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773195528": {"name": "Set: Demon's Plate", "category": "Pants", "platform": "Console"}, "254274052": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "254276496": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "826045588": {"name": "Set: Firebird's Down", "category": "Pants", "platform": "Console"}, "827231509": {"name": "Set: Helltooth Leg Guards", "category": "Pants", "platform": "Console"}, "-184773474": {"name": "Set: Immortal King's Stature (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "903144211": {"name": "Set: Inna's Glory (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774237701": {"name": "Set: Inna's Temperance", "category": "Pants", "platform": "Console"}, "219882343": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "219884787": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "826153399": {"name": "Set: Jade Harvester's Courage", "category": "Pants", "platform": "Console"}, "825901577": {"name": "Set: Leg Guards of Mystery (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826081525": {"name": "Set: Marauder's Encasement", "category": "Pants", "platform": "Console"}, "825865641": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773475": {"name": "Set: Natalya's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826009651": {"name": "Set: Raekor's Breeches", "category": "Pants", "platform": "Console"}, "825865639": {"name": "Set: Roland's Determination (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "826117462": {"name": "Set: Scales of the Dancing Serpent", "category": "Pants", "platform": "Console"}, "827051824": {"name": "Set: Sunwuko's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773473": {"name": "Set: Tal Rasha's Stride (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "825865640": {"name": "Set: Tasset of the Wastes (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827159635": {"name": "Set: The Shadow's Coil", "category": "Pants", "platform": "Console"}, "825937514": {"name": "Set: Unholy Plates (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827123698": {"name": "Set: Vyr's Fantastic Finery", "category": "Pants", "platform": "Console"}, "827195572": {"name": "Set: Weight of the Earth", "category": "Pants", "platform": "Console"}, "825901578": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773472": {"name": "Set: Zunimassa's Cloth (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-774273901": {"name": "legendary: Pox Faulds (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-1337763520": {"name": "01: Bardiche (DPS 11.4-12.4)", "category": "Polearms", "platform": "Console"}, "-1337763519": {"name": "02: Pike (DPS 15.2-16.6)", "category": "Polearms", "platform": "Console"}, "-1337763518": {"name": "03: Guisarme (DPS 20.4-21.9)", "category": "Polearms", "platform": "Console"}, "-1337763517": {"name": "04: Hache (DPS 24.7-26.1)", "category": "Polearms", "platform": "Console"}, "-1337763516": {"name": "05: Glaive (DPS 31.8-33.3)", "category": "Polearms", "platform": "Console"}, "-1337763515": {"name": "06: Pole Axe (DPS 38.0-40.9)", "category": "Polearms", "platform": "Console"}, "-1337763514": {"name": "07: Halberd (DPS 41.3-44.2)", "category": "Polearms", "platform": "Console"}, "-1337763513": {"name": "08: Lance (DPS 50.8-53.7)", "category": "Polearms", "platform": "Console"}, "-1337762431": {"name": "09: Voulge (DPS 58.0-60.8)", "category": "Polearms", "platform": "Console"}, "-1337762430": {"name": "10: Naginata (DPS 70.3-74.6)", "category": "Polearms", "platform": "Console"}, "-1337762429": {"name": "11: Croc (DPS 79.8-84.1)", "category": "Polearms", "platform": "Console"}, "-1337762428": {"name": "12: Battle Hache (DPS 91.7-96.0)", "category": "Polearms", "platform": "Console"}, "-1337762427": {"name": "13: Bisento (DPS 101.7-107.4)", "category": "Polearms", "platform": "Console"}, "-1337762426": {"name": "14: Great Pole Axe (DPS 116.4-122.1)", "category": "Polearms", "platform": "Console"}, "-1337762425": {"name": "15: Battle Halberd (DPS 131.1-138.2)", "category": "Polearms", "platform": "Console"}, "-1337762424": {"name": "16: Partizan (DPS 156.3-163.4)", "category": "Polearms", "platform": "Console"}, "-1337761342": {"name": "17: Lochaber Axe (DPS 191.9-200.5)", "category": "Polearms", "platform": "Console"}, "-1337761341": {"name": "18: Fauchard (DPS 223.3-233.2)", "category": "Polearms", "platform": "Console"}, "-1337761340": {"name": "19: Skewer (DPS 260.8-272.2)", "category": "Polearms", "platform": "Console"}, "-1337761339": {"name": "20: War Crest (DPS 305.0-316.4)", "category": "Polearms", "platform": "Console"}, "-1337761338": {"name": "21: Kwan Dao (DPS 355.8-367.2)", "category": "Polearms", "platform": "Console"}, "-1337761337": {"name": "22: War Thresher (DPS 421.3-432.7)", "category": "Polearms", "platform": "Console"}, "-1337761336": {"name": "23: Grand Halberd (DPS 499.2-510.6)", "category": "Polearms", "platform": "Console"}, "-1337761335": {"name": "24: Dread Lance (DPS 590.0-601.4)", "category": "Polearms", "platform": "Console"}, "-1337760253": {"name": "25: Trident (DPS 739.7-752.3)", "category": "Polearms", "platform": "Console"}, "-1337760252": {"name": "26: Trishula (DPS 1009.1-1021.7)", "category": "Polearms", "platform": "Console"}, "-1558359355": {"name": "Art Test Polearm 1", "category": "Polearms", "platform": "Console"}, "-1558359354": {"name": "Art Test Polearm 2", "category": "Polearms", "platform": "Console"}, "-1558359353": {"name": "Art Test Polearm 3", "category": "Polearms", "platform": "Console"}, "-1558359352": {"name": "Art Test Polearm 4", "category": "Polearms", "platform": "Console"}, "-1558359351": {"name": "Art Test Polearm 5", "category": "Polearms", "platform": "Console"}, "-1948909473": {"name": "Legendary: Bovine Bardiche", "category": "Polearms", "platform": "Console"}, "-1948873536": {"name": "Legendary: Foushee Voulge", "category": "Polearms", "platform": "Console"}, "-1987972992": {"name": "Legendary: Heart Slaughter", "category": "Polearms", "platform": "Console"}, "-1178676596": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "-1178674152": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587768": {"name": "Legendary: Heart Slaughter (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987973256": {"name": "Legendary: Heart Slaughter (Patch 2.1.0)", "category": "Polearms", "platform": "Console"}, "-1988008929": {"name": "Legendary: Pledge of Caldeum", "category": "Polearms", "platform": "Console"}, "-1179862517": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "-1179860073": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587767": {"name": "Legendary: Pledge of Caldeum (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987937055": {"name": "Legendary: Standoff", "category": "Polearms", "platform": "Console"}, "-1177490675": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "-1177488231": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587769": {"name": "Legendary: Standoff (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1988044866": {"name": "Legendary: Vigilance", "category": "Polearms", "platform": "Console"}, "-1181048438": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "-1181045994": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587766": {"name": "Legendary: Vigilance (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "1539236300": {"name": "01: Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236301": {"name": "02: Canvas Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236302": {"name": "03: Leather Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236303": {"name": "04: Hunting Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236304": {"name": "05: Assassin Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539237389": {"name": "06: Heavy Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237390": {"name": "07: Barbed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237391": {"name": "08: Hallowed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237392": {"name": "09: Stalker Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237393": {"name": "10: Razorspine Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238478": {"name": "11: Deadeye Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238479": {"name": "12: Bonetooth Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238480": {"name": "13: Consecrated Quiver (ASI 13.0%)", "category": "Quivers", "platform": "Console"}, "1539238481": {"name": "14: Runic Quiver (ASI 14.0%)", "category": "Quivers", "platform": "Console"}, "1539238482": {"name": "15: Sanctified Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238483": {"name": "16: Rakkisgard Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238484": {"name": "17: Ascended Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "-1056381007": {"name": "Art Test Quiver 1", "category": "Quivers", "platform": "Console"}, "-1056381006": {"name": "Art Test Quiver 2", "category": "Quivers", "platform": "Console"}, "-1056381005": {"name": "Art Test Quiver 3", "category": "Quivers", "platform": "Console"}, "-1056381004": {"name": "Art Test Quiver 4", "category": "Quivers", "platform": "Console"}, "-1056381003": {"name": "Art Test Quiver 5", "category": "Quivers", "platform": "Console"}, "-400507188": {"name": "Legendary: Archfiend Arrows", "category": "Quivers", "platform": "Console"}, "-331912616": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-331910172": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223036": {"name": "Legendary: Black Bone Arrows (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361407732": {"name": "Legendary: Bombadier's Rucksack", "category": "Quivers", "platform": "Console"}, "-400363440": {"name": "Legendary: Dead Man's Legacy", "category": "Quivers", "platform": "Console"}, "-327168932": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-327166488": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223032": {"name": "Legendary: Dead Man's Legacy (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361371795": {"name": "Legendary: Emimei's Duffel", "category": "Quivers", "platform": "Console"}, "-400399377": {"name": "Legendary: Fletcher's Pride", "category": "Quivers", "platform": "Console"}, "-328354853": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-328352409": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223033": {"name": "Legendary: Fletcher's Pride (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400579062": {"name": "Legendary: Flint Ripper Arrowheads", "category": "Quivers", "platform": "Console"}, "-334284458": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-334282014": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223038": {"name": "Legendary: Flint Ripper Arrowheads (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400471251": {"name": "Legendary: Holy Point Shot", "category": "Quivers", "platform": "Console"}, "-330726695": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-330724251": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223035": {"name": "Legendary: Holy Point Shot (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361335858": {"name": "Legendary: Hunter's Longbox", "category": "Quivers", "platform": "Console"}, "-400579326": {"name": "Legendary: Meticulous Bolts (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-400435314": {"name": "Legendary: Silver Star Piercers", "category": "Quivers", "platform": "Console"}, "-329540774": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-329538330": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223034": {"name": "Legendary: Silver Star Piercers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400543125": {"name": "Legendary: Sin Seekers", "category": "Quivers", "platform": "Console"}, "-333098537": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-333096093": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223037": {"name": "Legendary: Sin Seekers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400435578": {"name": "Legendary: Spines of Seething Hatred (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-361443669": {"name": "Legendary: The Ninth Cirri Satchel", "category": "Quivers", "platform": "Console"}, "564938473": {"name": "legendary: Dead Man's Legacy (Patch 2.2.0)", "category": "Quivers", "platform": "Console"}, "1146967280": {"name": "01: Ring", "category": "Rings", "platform": "Console"}, "1146967281": {"name": "02: Ring", "category": "Rings", "platform": "Console"}, "1146967282": {"name": "03: Ring", "category": "Rings", "platform": "Console"}, "1146967283": {"name": "04: Ring", "category": "Rings", "platform": "Console"}, "1146967284": {"name": "05: Ring", "category": "Rings", "platform": "Console"}, "1146967285": {"name": "06: Ring", "category": "Rings", "platform": "Console"}, "1146967286": {"name": "07: Ring", "category": "Rings", "platform": "Console"}, "1146967287": {"name": "08: Ring", "category": "Rings", "platform": "Console"}, "1146967288": {"name": "09: Ring", "category": "Rings", "platform": "Console"}, "1146967312": {"name": "10: Ring", "category": "Rings", "platform": "Console"}, "1146967313": {"name": "11: Ring", "category": "Rings", "platform": "Console"}, "1146967314": {"name": "12: Ring", "category": "Rings", "platform": "Console"}, "1146967315": {"name": "13: Ring", "category": "Rings", "platform": "Console"}, "1146967316": {"name": "14: Ring", "category": "Rings", "platform": "Console"}, "1146967317": {"name": "15: Ring", "category": "Rings", "platform": "Console"}, "1146967318": {"name": "16: Ring", "category": "Rings", "platform": "Console"}, "1146967319": {"name": "17: Ring", "category": "Rings", "platform": "Console"}, "1146967320": {"name": "18: Ring", "category": "Rings", "platform": "Console"}, "1146967321": {"name": "19: Ring", "category": "Rings", "platform": "Console"}, "1146967345": {"name": "20: Ring", "category": "Rings", "platform": "Console"}, "1146967346": {"name": "21: Ring", "category": "Rings", "platform": "Console"}, "1146967347": {"name": "22: Ring", "category": "Rings", "platform": "Console"}, "1146967348": {"name": "23: Ring", "category": "Rings", "platform": "Console"}, "1146967349": {"name": "24: Ring", "category": "Rings", "platform": "Console"}, "1146967350": {"name": "25: Ring", "category": "Rings", "platform": "Console"}, "1818597029": {"name": "Art Test Ring 1", "category": "Rings", "platform": "Console"}, "1818597030": {"name": "Art Test Ring 2", "category": "Rings", "platform": "Console"}, "1818597031": {"name": "Art Test Ring 3", "category": "Rings", "platform": "Console"}, "1818597032": {"name": "Art Test Ring 4", "category": "Rings", "platform": "Console"}, "1818597033": {"name": "Art Test Ring 5", "category": "Rings", "platform": "Console"}, "-1149557626": {"name": "Legendary: Avarice Band", "category": "Rings", "platform": "Console"}, "-1188944578": {"name": "Legendary: Band of Hollow Whispers", "category": "Rings", "platform": "Console"}, "-580542710": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-580540266": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-731577034": {"name": "Legendary: Band of Hollow Whispers (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188657082": {"name": "Legendary: Band of Untold Secrets", "category": "Rings", "platform": "Console"}, "-571055342": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-571052898": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-731577026": {"name": "Legendary: Band of Untold Secrets (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149629500": {"name": "Legendary: Band of the Rue Chambers", "category": "Rings", "platform": "Console"}, "-1188764893": {"name": "Legendary: Broken Promises", "category": "Rings", "platform": "Console"}, "-574613105": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-574610661": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-731577029": {"name": "Legendary: Broken Promises (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186608673": {"name": "Legendary: Bul-Kathos's Wedding Band", "category": "Rings", "platform": "Console"}, "-503457845": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-503455401": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-731576969": {"name": "Legendary: Bul-Kathos's Wedding Band (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188728956": {"name": "Legendary: Eternal Union", "category": "Rings", "platform": "Console"}, "-573427184": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-573424740": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-731577028": {"name": "Legendary: Eternal Union (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188729220": {"name": "Legendary: Eternal Union (Patch 2.1.0)", "category": "Rings", "platform": "Console"}, "-1149665437": {"name": "Legendary: Gamuel's Deceit", "category": "Rings", "platform": "Console"}, "425752007": {"name": "Legendary: Halo Of Arlyse (Patch 2.1.2)", "category": "Rings", "platform": "Console"}, "-1186464925": {"name": "Legendary: Hellfire Ring", "category": "Rings", "platform": "Console"}, "-498714161": {"name": "Legendary: Hellfire Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-578170868": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-578168424": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-731577032": {"name": "Legendary: Hierophant's Seal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188693019": {"name": "Legendary: Justice Lantern", "category": "Rings", "platform": "Console"}, "-572241263": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-572238819": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-731577027": {"name": "Legendary: Justice Lantern (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188872704": {"name": "Legendary: Krede's Flame", "category": "Rings", "platform": "Console"}, "1963121073": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-159638916": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-1188908641": {"name": "Legendary: Leoric's Signet", "category": "Rings", "platform": "Console"}, "-579356789": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-579354345": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-731577033": {"name": "Legendary: Leoric's Signet (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186572736": {"name": "Legendary: Manald Heal", "category": "Rings", "platform": "Console"}, "-502271924": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-502269480": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-731576968": {"name": "Legendary: Manald Heal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187507098": {"name": "Legendary: Nagelring", "category": "Rings", "platform": "Console"}, "-533105870": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-533103426": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576994": {"name": "Legendary: Nagelring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186500862": {"name": "Legendary: Obsidian Ring of the Zodiac", "category": "Rings", "platform": "Console"}, "-499900082": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-499897638": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-731576966": {"name": "Legendary: Obsidian Ring of the Zodiac (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187543035": {"name": "Legendary: Oculus Ring", "category": "Rings", "platform": "Console"}, "-534291791": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-534289347": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576995": {"name": "Legendary: Oculus Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149521689": {"name": "Legendary: Pandemonium Loop", "category": "Rings", "platform": "Console"}, "-1188836767": {"name": "Legendary: Puzzle Ring", "category": "Rings", "platform": "Console"}, "-576984947": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-576982503": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577031": {"name": "Legendary: Puzzle Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149701374": {"name": "Legendary: Rechel's Ring of Larceny", "category": "Rings", "platform": "Console"}, "-1149593563": {"name": "Legendary: Ring of Royal Grandeur", "category": "Rings", "platform": "Console"}, "-1149737311": {"name": "Legendary: Rogar's Huge Stone", "category": "Rings", "platform": "Console"}, "-611901958": {"name": "Legendary: Signet Ring of the Blizzard", "category": "Rings", "platform": "Console"}, "-1186536799": {"name": "Legendary: Skull Grasp", "category": "Rings", "platform": "Console"}, "-501086003": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-501083559": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-731576967": {"name": "Legendary: Skull Grasp (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188800830": {"name": "Legendary: Stolen Ring", "category": "Rings", "platform": "Console"}, "-575799026": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-575796582": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577030": {"name": "Legendary: Stolen Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187471161": {"name": "Legendary: Stone of Jordan", "category": "Rings", "platform": "Console"}, "-531919949": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-531917505": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-731576993": {"name": "Legendary: Stone of Jordan (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149809185": {"name": "Legendary: The Tall Man's Finger", "category": "Rings", "platform": "Console"}, "-1187794594": {"name": "Legendary: Unity", "category": "Rings", "platform": "Console"}, "-542593238": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-542590794": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-731577002": {"name": "Legendary: Unity (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149773248": {"name": "Legendary: Wyrdward", "category": "Rings", "platform": "Console"}, "-1585363882": {"name": "P1_Ring_001 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363881": {"name": "P1_Ring_002 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363880": {"name": "P1_Ring_003 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363879": {"name": "P1_Ring_004 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "2082266421": {"name": "PvP: Echo Band All", "category": "Rings", "platform": "Console"}, "2082266693": {"name": "PvP: Echo Band Attack", "category": "Rings", "platform": "Console"}, "2082269451": {"name": "PvP: Echo Band Defense", "category": "Rings", "platform": "Console"}, "-4139386": {"name": "PvP: Echo Band Precision", "category": "Rings", "platform": "Console"}, "2082289199": {"name": "PvP: Echo Band Vitality", "category": "Rings", "platform": "Console"}, "-3897388": {"name": "PvP: Echo Band Willpower", "category": "Rings", "platform": "Console"}, "-2095294696": {"name": "PvP: Sherman Signet All", "category": "Rings", "platform": "Console"}, "-2095294424": {"name": "PvP: Sherman Signet Attack", "category": "Rings", "platform": "Console"}, "-2095291666": {"name": "PvP: Sherman Signet Defense", "category": "Rings", "platform": "Console"}, "-424702775": {"name": "PvP: Sherman Signet Precision", "category": "Rings", "platform": "Console"}, "-2095271918": {"name": "PvP: Sherman Signet Vitality", "category": "Rings", "platform": "Console"}, "-731576997": {"name": "Set: Band of Fallen Heroes (Old-Legacy)", "category": "Rings", "platform": "Console"}, "1978116233": {"name": "Set: Focus", "category": "Rings", "platform": "Console"}, "-1187614909": {"name": "Set: Litany of the Undaunted", "category": "Rings", "platform": "Console"}, "-536663633": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-536661189": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-731577001": {"name": "Set: Natalya's Mark (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187758657": {"name": "Set: Natalya's Reflection", "category": "Rings", "platform": "Console"}, "-541407317": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "-541404873": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "1978152170": {"name": "Set: Restraint", "category": "Rings", "platform": "Console"}, "-731576998": {"name": "Set: Screaming Chain (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187686783": {"name": "Set: The Compass Rose", "category": "Rings", "platform": "Console"}, "-539035475": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-539033031": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-1187650846": {"name": "Set: The Wailing Host", "category": "Rings", "platform": "Console"}, "-537849554": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-537847110": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-731576999": {"name": "Set: Wanderlust (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-731577000": {"name": "Set: Zunimassa's Plague (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187722720": {"name": "Set: Zunimassa's Pox", "category": "Rings", "platform": "Console"}, "-540221396": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "-540218952": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "417069417": {"name": "legendary: Arcstone (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1188765156": {"name": "legendary: Broken Promises (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069418": {"name": "legendary: Convention Of Elements (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187507361": {"name": "legendary: Nagelring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187543298": {"name": "legendary: Oculus Ring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149521952": {"name": "legendary: Pandemonium Loop (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1186501125": {"name": "legendary: Ring of the Zodiac (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069415": {"name": "legendary: Skull Grasp (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069416": {"name": "legendary: The Short Man's Finger (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149773511": {"name": "legendary: Wyrdward (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-229902049": {"name": "01: Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229902048": {"name": "02: Glass Blade", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900960": {"name": "03: Loaded Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900959": {"name": "04: Crystal Edge", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900958": {"name": "05: Clasp", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900957": {"name": "06: Sand Pouch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899871": {"name": "07: Bone Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899870": {"name": "08: Diamond Razor", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899869": {"name": "09: Brooch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899868": {"name": "10: Dust Satchel", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899867": {"name": "11: Hazard", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899866": {"name": "12: Stinger", "category": "Scoundrel Tokens", "platform": "Console"}, "978821514": {"name": "Legendary: Ribald Etchings", "category": "Scoundrel Tokens", "platform": "Console"}, "978821513": {"name": "Legendary: Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "978821515": {"name": "Legendary: Slipka's Letter Opener", "category": "Scoundrel Tokens", "platform": "Console"}, "-978821513": {"name": "Legendary:Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "1815806856": {"name": "00: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806857": {"name": "01: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806858": {"name": "02: Targe Shield (AR 48-55)", "category": "Shields", "platform": "Console"}, "1815806859": {"name": "03: Heater Shield (AR 88-101)", "category": "Shields", "platform": "Console"}, "1815806860": {"name": "04: Kite Shield (AR 128-167)", "category": "Shields", "platform": "Console"}, "1815806861": {"name": "05: Large Shield (AR 168-199)", "category": "Shields", "platform": "Console"}, "1815806862": {"name": "06: Gothic Shield (AR 200-223)", "category": "Shields", "platform": "Console"}, "1815806863": {"name": "07: Tower Shield (AR 224-255)", "category": "Shields", "platform": "Console"}, "1815807946": {"name": "08: Pelta (AR 256-319)", "category": "Shields", "platform": "Console"}, "1815807947": {"name": "09: Rondache (AR 320-383)", "category": "Shields", "platform": "Console"}, "1815807948": {"name": "10: Knight Shield (AR 384-447)", "category": "Shields", "platform": "Console"}, "1815807949": {"name": "11: Ironwood Shield (AR 448-511)", "category": "Shields", "platform": "Console"}, "1815807950": {"name": "12: Pavise (AR 512-579)", "category": "Shields", "platform": "Console"}, "1815807951": {"name": "13: Bone Shield (AR 580-619)", "category": "Shields", "platform": "Console"}, "1815807952": {"name": "14: Savior (AR 620-659)", "category": "Shields", "platform": "Console"}, "1815809035": {"name": "15: Aspis (AR 660-699)", "category": "Shields", "platform": "Console"}, "1815809036": {"name": "16: Hoplon (AR 700-739)", "category": "Shields", "platform": "Console"}, "1815809037": {"name": "17: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "-335464095": {"name": "17b: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "1815809038": {"name": "18: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "-334278174": {"name": "18b: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "1815809039": {"name": "19: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "-333092253": {"name": "19b: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "1815809040": {"name": "20: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "-331906332": {"name": "20b: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "1815809041": {"name": "21: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "-330720411": {"name": "21b: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "1815809042": {"name": "22: Rakkisgard Shield (AR 1260-1759)", "category": "Shields", "platform": "Console"}, "1815809043": {"name": "23: Ascended Shield (AR 1760-2024)", "category": "Shields", "platform": "Console"}, "-1347979730": {"name": "Art Test Shield 1", "category": "Shields", "platform": "Console"}, "-1347979729": {"name": "Art Test Shield 2", "category": "Shields", "platform": "Console"}, "-1347979728": {"name": "Art Test Shield 3", "category": "Shields", "platform": "Console"}, "-1347979727": {"name": "Art Test Shield 4", "category": "Shields", "platform": "Console"}, "-1347979726": {"name": "Art Test Shield 5", "category": "Shields", "platform": "Console"}, "200412170": {"name": "Legendary: Amazonian Parma", "category": "Shields", "platform": "Console"}, "200519981": {"name": "Legendary: Beastguard", "category": "Shields", "platform": "Console"}, "1028274966": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "1028277410": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "-64652478": {"name": "Legendary: Centurion (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200555918": {"name": "Legendary: Coven's Criterion", "category": "Shields", "platform": "Console"}, "200340296": {"name": "Legendary: Defender of Westmarch", "category": "Shields", "platform": "Console"}, "161420525": {"name": "Legendary: Denial", "category": "Shields", "platform": "Console"}, "1031832729": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "1031835173": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "-64652475": {"name": "Legendary: Denial (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200376233": {"name": "Legendary: Eberli Charo", "category": "Shields", "platform": "Console"}, "161312714": {"name": "Legendary: Freeze of Deflection", "category": "Shields", "platform": "Console"}, "161240840": {"name": "Legendary: Ivory Tower", "category": "Shields", "platform": "Console"}, "1025903124": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "1025905568": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "-64652480": {"name": "Legendary: Ivory Tower (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161456462": {"name": "Legendary: Lidless Wall", "category": "Shields", "platform": "Console"}, "1033018650": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "1033021094": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "-64652474": {"name": "Legendary: Lidless Wall (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161492399": {"name": "Legendary: Stormshield", "category": "Shields", "platform": "Console"}, "1034204571": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "1034207015": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "-64652473": {"name": "Legendary: Stormshield (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200448107": {"name": "Legendary: Vo'Toyias Spiker", "category": "Shields", "platform": "Console"}, "1063852596": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "1063855040": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "-64652448": {"name": "Legendary: Wall of Bone (Old-Legacy)", "category": "Shields", "platform": "Console"}, "162390824": {"name": "Legendary: Wall of Man", "category": "Shields", "platform": "Console"}, "200484044": {"name": "Legendary: Wretchskin", "category": "Shields", "platform": "Console"}, "162426761": {"name": "Set: Hallowed Barricade", "category": "Shields", "platform": "Console"}, "-64652447": {"name": "Set: Hallowed Barrier (Old-Legacy)", "category": "Shields", "platform": "Console"}, "1065038517": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "1065040961": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "200340033": {"name": "legendary: Defender Of Westmarch (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509030": {"name": "legendary: Denial (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509025": {"name": "legendary: Ivory Tower (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "-519190663": {"name": "legendary: Stormshield (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "365490250": {"name": "02: Leather Mantle (AR 34-46)", "category": "Shoulders", "platform": "Console"}, "365490251": {"name": "03: Shoulder Guards (AR 48-58)", "category": "Shoulders", "platform": "Console"}, "365490252": {"name": "04: Amice (AR 58-68)", "category": "Shoulders", "platform": "Console"}, "365490253": {"name": "05: Spaulders (AR 69-79)", "category": "Shoulders", "platform": "Console"}, "365490254": {"name": "06: Shoulder Plates (AR 80-100)", "category": "Shoulders", "platform": "Console"}, "365491338": {"name": "07: Etched Mantle (AR 101-121)", "category": "Shoulders", "platform": "Console"}, "365491339": {"name": "08: Ailettes (AR 122-142)", "category": "Shoulders", "platform": "Console"}, "365491340": {"name": "09: Pauldrons (AR 144-164)", "category": "Shoulders", "platform": "Console"}, "365491341": {"name": "10: Sode (AR 165-199)", "category": "Shoulders", "platform": "Console"}, "365491342": {"name": "11: Epaulets (AR 200-219)", "category": "Shoulders", "platform": "Console"}, "365492427": {"name": "12: Balor Pauldrons (AR 220-239)", "category": "Shoulders", "platform": "Console"}, "365492428": {"name": "13: Espaliers (AR 240-252)", "category": "Shoulders", "platform": "Console"}, "365492429": {"name": "14: Warlord Spaulders (AR 253-285)", "category": "Shoulders", "platform": "Console"}, "365492430": {"name": "15: Doom Pauldrons (AR 286-318)", "category": "Shoulders", "platform": "Console"}, "365492431": {"name": "16: Pallium (AR 320-352)", "category": "Shoulders", "platform": "Console"}, "365492432": {"name": "17: Archon Spaulders (AR 353-419)", "category": "Shoulders", "platform": "Console"}, "365492433": {"name": "18: Rakkisgard Pauldrons (AR 420-586)", "category": "Shoulders", "platform": "Console"}, "365492434": {"name": "19: Ascended Pauldrons (AR 586-674)", "category": "Shoulders", "platform": "Console"}, "-1869550021": {"name": "Art Test Shoulder 1", "category": "Shoulders", "platform": "Console"}, "-1869550020": {"name": "Art Test Shoulder 2", "category": "Shoulders", "platform": "Console"}, "-1869550019": {"name": "Art Test Shoulder 3", "category": "Shoulders", "platform": "Console"}, "-1869550018": {"name": "Art Test Shoulder 4", "category": "Shoulders", "platform": "Console"}, "-1869550017": {"name": "Art Test Shoulder 5", "category": "Shoulders", "platform": "Console"}, "-1565608501": {"name": "Art_Test_Shoulder_10 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608500": {"name": "Art_Test_Shoulder_11 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608499": {"name": "Art_Test_Shoulder_12 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550016": {"name": "Art_Test_Shoulder_6 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550015": {"name": "Art_Test_Shoulder_7 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550014": {"name": "Art_Test_Shoulder_8 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550013": {"name": "Art_Test_Shoulder_9 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-248496224": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "-248493780": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734028": {"name": "Legendary: Barter Town Pads (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "2112365407": {"name": "Legendary: Burdens of the Brave Survivor", "category": "Shoulders", "platform": "Console"}, "1902294393": {"name": "Legendary: Conqueror's Pauldrons (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1959570086": {"name": "Legendary: Corruption", "category": "Shoulders", "platform": "Console"}, "-1959749771": {"name": "Legendary: Death Watch Mantle", "category": "Shoulders", "platform": "Console"}, "-247310303": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "-247307859": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734029": {"name": "Legendary: Death Watch Mantle (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959785708": {"name": "Legendary: Homing Pads", "category": "Shoulders", "platform": "Console"}, "507255184": {"name": "Legendary: Infernal Pauldrons", "category": "Shoulders", "platform": "Console"}, "-1920578441": {"name": "Legendary: Pauldrons of the Skeleton King", "category": "Shoulders", "platform": "Console"}, "-1920650315": {"name": "Legendary: Profane Pauldrons", "category": "Shoulders", "platform": "Console"}, "-241380698": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "-241378254": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734034": {"name": "Legendary: Seven Sins (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1920614378": {"name": "Legendary: Spaulders of Zakara", "category": "Shoulders", "platform": "Console"}, "1277749690": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-419021771": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-1959713834": {"name": "Legendary: Vile Ward", "category": "Shoulders", "platform": "Console"}, "-246124382": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "-246121938": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734030": {"name": "Legendary: Vile Ward (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959714098": {"name": "Legendary: Vile Ward (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1958384165": {"name": "Set: Asheara's Custodian", "category": "Shoulders", "platform": "Console"}, "-202245305": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "-202242861": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734067": {"name": "Set: Asheara's Vigilance (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959534149": {"name": "Set: Aughild's Power", "category": "Shoulders", "platform": "Console"}, "-240194777": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "-240192333": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734035": {"name": "Set: Aughild's Triumph (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-242566619": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "-242564175": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734033": {"name": "Set: Born's Pauldrons (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959606023": {"name": "Set: Born's Privilege", "category": "Shoulders", "platform": "Console"}, "-1980689583": {"name": "Set: Burden of the Invoker", "category": "Shoulders", "platform": "Console"}, "-1981839829": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875767": {"name": "Set: Dashing Pauldrons of Despair (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959498212": {"name": "Set: Demon's Aileron", "category": "Shoulders", "platform": "Console"}, "-239008856": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "-239006412": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734036": {"name": "Set: Demon's Wings (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1981731756": {"name": "Set: Firebird's Pinions", "category": "Shoulders", "platform": "Console"}, "-1980545835": {"name": "Set: Helltooth Mantle", "category": "Shoulders", "platform": "Console"}, "-1981623945": {"name": "Set: Jade Harvester's Joy", "category": "Shoulders", "platform": "Console"}, "-1981659882": {"name": "Set: Mantle of the Upside-Down Sinners", "category": "Shoulders", "platform": "Console"}, "-1981695819": {"name": "Set: Marauder's Spines", "category": "Shoulders", "platform": "Console"}, "-1981911703": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1980761457": {"name": "Set: Pauldrons of Akkhan", "category": "Shoulders", "platform": "Console"}, "-1981911704": {"name": "Set: Pauldrons of the Wastes (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981767693": {"name": "Set: Raekor's Burden", "category": "Shoulders", "platform": "Console"}, "-1981911705": {"name": "Set: Roland's Mantle (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1980581772": {"name": "Set: Spires of the Earth", "category": "Shoulders", "platform": "Console"}, "-1980725520": {"name": "Set: Sunwuko's Balance", "category": "Shoulders", "platform": "Console"}, "-1981839830": {"name": "Set: Unsanctified Shoulders (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875766": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959750034": {"name": "legendary: Death Watch Mantle (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1449741837": {"name": "legendary: Pauldrons of the Hierarch (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "1905179475": {"name": "01: Eagle Orb (+1-2 DMG)", "category": "Sources", "platform": "Console"}, "1905179476": {"name": "02: Spellbook (+(2-3)-(3-5) DMG)", "category": "Sources", "platform": "Console"}, "1905179477": {"name": "03: Smoked Spheres (+(3-5)-(4-8) DMG)", "category": "Sources", "platform": "Console"}, "1905179478": {"name": "04: Cursed Skull (+(3-6)-(4-10) DMG)", "category": "Sources", "platform": "Console"}, "1905180564": {"name": "05: Sanctuary Globe (+(4-8)-(5-13) DMG)", "category": "Sources", "platform": "Console"}, "1905180565": {"name": "06: Fiendish Folio (+(6-11)-(7-19) DMG)", "category": "Sources", "platform": "Console"}, "1905180566": {"name": "07: Triad (+(8-16)-(9-29) DMG)", "category": "Sources", "platform": "Console"}, "1905180567": {"name": "08: Screaming Skull (+(13-26)-(14-45) DMG)", "category": "Sources", "platform": "Console"}, "1905181653": {"name": "09: Power Sphere (+(17-39)-(18-114) DMG)", "category": "Sources", "platform": "Console"}, "1905181654": {"name": "10: Codex (+(19-58)-(20-213) DMG)", "category": "Sources", "platform": "Console"}, "1905181655": {"name": "11: Orbit Stones (+(24-72)-(25-265) DMG)", "category": "Sources", "platform": "Console"}, "1905181656": {"name": "12: Demi Lich (+(28-110)-(29-405) DMG)", "category": "Sources", "platform": "Console"}, "1905181657": {"name": "13: Puzzle Box (+(126-158)-(127-190) DMG)", "category": "Sources", "platform": "Console"}, "1905181658": {"name": "14: Moschen Spheres (+(262-328)-(263-394) DMG)", "category": "Sources", "platform": "Console"}, "702613912": {"name": "Art Test Orb 1", "category": "Sources", "platform": "Console"}, "702613913": {"name": "Art Test Orb 2", "category": "Sources", "platform": "Console"}, "702613914": {"name": "Art Test Orb 3", "category": "Sources", "platform": "Console"}, "702613915": {"name": "Art Test Orb 4", "category": "Sources", "platform": "Console"}, "702613916": {"name": "Art Test Orb 5", "category": "Sources", "platform": "Console"}, "-1519116524": {"name": "Legendary: Cosmic Strand", "category": "Sources", "platform": "Console"}, "2028438506": {"name": "Legendary: Gul'dan's Secret (Patch 2.1.0)", "category": "Sources", "platform": "Console"}, "-1934140787": {"name": "Legendary: Heart of Darkness", "category": "Sources", "platform": "Console"}, "-1480017068": {"name": "Legendary: Light of Grace", "category": "Sources", "platform": "Console"}, "-1480088942": {"name": "Legendary: Mirrorball", "category": "Sources", "platform": "Console"}, "-1480053005": {"name": "Legendary: Myken's Ball of Hate", "category": "Sources", "platform": "Console"}, "1408684960": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "1408687404": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "215441100": {"name": "Legendary: Singularity (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519224335": {"name": "Legendary: The Oculus", "category": "Sources", "platform": "Console"}, "1405127197": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "1405129641": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "215441097": {"name": "Legendary: The Oculus (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519152461": {"name": "Legendary: Triumvirate", "category": "Sources", "platform": "Console"}, "1407499039": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "1407501483": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "215441099": {"name": "Legendary: Triumvirate (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519080587": {"name": "Legendary: Winter Flurry", "category": "Sources", "platform": "Console"}, "1409870881": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "1409873325": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "215441101": {"name": "Legendary: Winter Flurry (Old-Legacy)", "category": "Sources", "platform": "Console"}, "215441130": {"name": "Set: Chantodo's Elemental Seal (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518038414": {"name": "Set: Chantodo's Force", "category": "Sources", "platform": "Console"}, "1444262590": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "1444265034": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "-777123311": {"name": "Set: Firebird's Eye", "category": "Sources", "platform": "Console"}, "215441131": {"name": "Set: Tal Rasha's Lidless Eye (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518002477": {"name": "Set: Tal Rasha's Unwavering Glare", "category": "Sources", "platform": "Console"}, "1445448511": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1445450955": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1175281612": {"name": "legendary: Triumvirate (Patch 2.2.0)", "category": "Sources", "platform": "Console"}, "-101312757": {"name": "01: Javelin (DPS 7.2-8.4)", "category": "Spears", "platform": "Console"}, "-101312756": {"name": "02: Fuscina (DPS 12.6-14.4)", "category": "Spears", "platform": "Console"}, "-101312755": {"name": "03: Spear (DPS 18.6-20.4)", "category": "Spears", "platform": "Console"}, "-101312754": {"name": "04: Hasta (DPS 24.6-26.4)", "category": "Spears", "platform": "Console"}, "-101312753": {"name": "05: Pilum (DPS 32.4-34.2)", "category": "Spears", "platform": "Console"}, "-101311668": {"name": "06: Angon (DPS 38.4-40.2)", "category": "Spears", "platform": "Console"}, "-101311667": {"name": "07: Assegai (DPS 48.6-50.4)", "category": "Spears", "platform": "Console"}, "-101311666": {"name": "08: War Spear (DPS 60.6-62.4)", "category": "Spears", "platform": "Console"}, "-101311665": {"name": "09: Spontoon (DPS 84.6-88.2)", "category": "Spears", "platform": "Console"}, "-101311664": {"name": "10: Yari (DPS 127.8-133.2)", "category": "Spears", "platform": "Console"}, "-101310579": {"name": "11: Harpoon (DPS 151.8-157.2)", "category": "Spears", "platform": "Console"}, "-101310578": {"name": "12: Impaler (DPS 178.2-185.4)", "category": "Spears", "platform": "Console"}, "-101310577": {"name": "13: Qiang (DPS 230.4-239.4)", "category": "Spears", "platform": "Console"}, "-101310576": {"name": "14: Vel (DPS 268.2-277.2)", "category": "Spears", "platform": "Console"}, "-101310575": {"name": "15: Centurion Spear (DPS 311.4-320.4)", "category": "Spears", "platform": "Console"}, "-101309490": {"name": "16: Honed Spear (DPS 419.4-428.4)", "category": "Spears", "platform": "Console"}, "-101309489": {"name": "17: Disemboweler (DPS 527.4-536.4)", "category": "Spears", "platform": "Console"}, "1438708880": {"name": "Art Test Spear 1", "category": "Spears", "platform": "Console"}, "1438708881": {"name": "Art Test Spear 2", "category": "Spears", "platform": "Console"}, "1438708882": {"name": "Art Test Spear 3", "category": "Spears", "platform": "Console"}, "1438708883": {"name": "Art Test Spear 4", "category": "Spears", "platform": "Console"}, "1438708884": {"name": "Art Test Spear 5", "category": "Spears", "platform": "Console"}, "-2120824630": {"name": "Legendary: Akanesh, the Herald of Righteousness", "category": "Spears", "platform": "Console"}, "2135007273": {"name": "Legendary: Arreat's Law", "category": "Spears", "platform": "Console"}, "1735685973": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "1735688417": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403711": {"name": "Legendary: Arreat's Law (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135079147": {"name": "Legendary: Empyrean Messenger", "category": "Spears", "platform": "Console"}, "1738057815": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "1738060259": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403709": {"name": "Legendary: Empyrean Messenger (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135115084": {"name": "Legendary: Scrimshaw", "category": "Spears", "platform": "Console"}, "1739243736": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "1739246180": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403708": {"name": "Legendary: Scrimshaw (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-2120788693": {"name": "Legendary: Steffon's Heavy Lance", "category": "Spears", "platform": "Console"}, "2135043210": {"name": "Legendary: The Three Hundredth Spear", "category": "Spears", "platform": "Console"}, "1736871894": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "1736874338": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403710": {"name": "Legendary: The Three Hundredth Spear (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-242895468": {"name": "01: Glass Star (AR 30-35)", "category": "Spirit Stones", "platform": "Console"}, "-242895467": {"name": "02: Thought Mirror (AR 36-41)", "category": "Spirit Stones", "platform": "Console"}, "-242895466": {"name": "03: Third Eye (AR 60-69)", "category": "Spirit Stones", "platform": "Console"}, "-242895465": {"name": "04: Onyx Cluster (AR 84-113)", "category": "Spirit Stones", "platform": "Console"}, "-242894379": {"name": "05: Sunstone (AR 114-149)", "category": "Spirit Stones", "platform": "Console"}, "-242894378": {"name": "06: Prism (AR 150-185)", "category": "Spirit Stones", "platform": "Console"}, "-242894377": {"name": "07: Seer Shard (AR 186-232)", "category": "Spirit Stones", "platform": "Console"}, "-242894376": {"name": "08: Igneous Studs (AR 232-254)", "category": "Spirit Stones", "platform": "Console"}, "-242893290": {"name": "09: Solarius (AR 255-284)", "category": "Spirit Stones", "platform": "Console"}, "-242893289": {"name": "10: Meditator (AR 285-322)", "category": "Spirit Stones", "platform": "Console"}, "-242893288": {"name": "11: Ghost Sight (AR 322-359)", "category": "Spirit Stones", "platform": "Console"}, "-242893287": {"name": "12: Star Crown (AR 360-472)", "category": "Spirit Stones", "platform": "Console"}, "-242893286": {"name": "13: Insight Stone (AR 472-659)", "category": "Spirit Stones", "platform": "Console"}, "-242893285": {"name": "14: Ascended Stone (AR 660-759)", "category": "Spirit Stones", "platform": "Console"}, "113759385": {"name": "Art Test SpiritStone 1", "category": "Spirit Stones", "platform": "Console"}, "113759386": {"name": "Art Test SpiritStone 2", "category": "Spirit Stones", "platform": "Console"}, "113759387": {"name": "Art Test SpiritStone 3", "category": "Spirit Stones", "platform": "Console"}, "113759388": {"name": "Art Test SpiritStone 4", "category": "Spirit Stones", "platform": "Console"}, "113759389": {"name": "Art Test SpiritStone 5", "category": "Spirit Stones", "platform": "Console"}, "635580050": {"name": "Legendary: Bezoar Stone", "category": "Spirit Stones", "platform": "Console"}, "-500772130": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-500769686": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225226": {"name": "Legendary: Bezoar Stone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635651924": {"name": "Legendary: Erlang Shen", "category": "Spirit Stones", "platform": "Console"}, "-498400288": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-498397844": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225228": {"name": "Legendary: Erlang Shen (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674787317": {"name": "Legendary: Eye of Peshkov", "category": "Spirit Stones", "platform": "Console"}, "635687861": {"name": "Legendary: Gyana Na Kashu", "category": "Spirit Stones", "platform": "Console"}, "-497214367": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-497211923": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225229": {"name": "Legendary: Gyana Na Kashu (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674751380": {"name": "Legendary: Kekegi's Unbreakable Spirit", "category": "Spirit Stones", "platform": "Console"}, "635831609": {"name": "Legendary: Madstone", "category": "Spirit Stones", "platform": "Console"}, "-492470683": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-492468239": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225233": {"name": "Legendary: Madstone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1935108657": {"name": "Legendary: Madstone (Patch 2.1.0)", "category": "Spirit Stones", "platform": "Console"}, "635723798": {"name": "Legendary: See No Evil", "category": "Spirit Stones", "platform": "Console"}, "-496028446": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-496026002": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225230": {"name": "Legendary: See No Evil (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635759735": {"name": "Legendary: The Eye of the Storm", "category": "Spirit Stones", "platform": "Console"}, "-494842525": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-494840081": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225231": {"name": "Legendary: The Eye of the Storm (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674715443": {"name": "Legendary: The Laws of Seph", "category": "Spirit Stones", "platform": "Console"}, "635615987": {"name": "Legendary: The Mind's Eye", "category": "Spirit Stones", "platform": "Console"}, "-499586209": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-499583765": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225227": {"name": "Legendary: The Mind's Eye (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635795672": {"name": "Legendary: Tzo Krin's Gaze", "category": "Spirit Stones", "platform": "Console"}, "-493656604": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-493654160": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225232": {"name": "Legendary: Tzo Krin's Gaze (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635867546": {"name": "Set: Inna's Radiance", "category": "Spirit Stones", "platform": "Console"}, "-491284762": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-491282318": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225234": {"name": "Set: Inna's Splendor (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-2115691356": {"name": "01: Short Staff (DPS 12.5-13.5)", "category": "Staves", "platform": "Console"}, "-2115691355": {"name": "02: Long Staff (DPS 17.0-18.5)", "category": "Staves", "platform": "Console"}, "-2115691354": {"name": "03: Yew Staff (DPS 22.0-23.5)", "category": "Staves", "platform": "Console"}, "-2115691353": {"name": "04: Gnarled Staff (DPS 27.0-28.5)", "category": "Staves", "platform": "Console"}, "-2115691352": {"name": "05: Bone Staff (DPS 33.0-34.5)", "category": "Staves", "platform": "Console"}, "-2115691351": {"name": "06: Battle Staff (DPS 40.5-42.0)", "category": "Staves", "platform": "Console"}, "-2115691350": {"name": "07: War Staff (DPS 50.5-53.5)", "category": "Staves", "platform": "Console"}, "-2115690267": {"name": "08: Mentor Staff (DPS 66.5-69.5)", "category": "Staves", "platform": "Console"}, "-2115690266": {"name": "09: Obsidian Staff (DPS 75.5-78.5)", "category": "Staves", "platform": "Console"}, "-2115690265": {"name": "10: Petrified Staff (DPS 90.0-94.5)", "category": "Staves", "platform": "Console"}, "-2115690264": {"name": "11: Elder Staff (DPS 101.5-106.0)", "category": "Staves", "platform": "Console"}, "-2115690263": {"name": "12: Shamanic Staff (DPS 121.0-127.0)", "category": "Staves", "platform": "Console"}, "-2115690262": {"name": "13: High Priest Staff (DPS 138.5-144.5)", "category": "Staves", "platform": "Console"}, "-2115690261": {"name": "14: Arcane Staff (DPS 174.5-182.0)", "category": "Staves", "platform": "Console"}, "-2115689178": {"name": "15: Hyperion Staff (DPS 204.5-212.0)", "category": "Staves", "platform": "Console"}, "-2115689177": {"name": "16: Stygian Staff (DPS 237.0-246.0)", "category": "Staves", "platform": "Console"}, "-2115689176": {"name": "17: Primordial Staff (DPS 275.5-286.0)", "category": "Staves", "platform": "Console"}, "-2115689175": {"name": "18: Archaic Staff (DPS 320.0-332.0)", "category": "Staves", "platform": "Console"}, "-2115689174": {"name": "19: Conquest Staff (DPS 409.0-421.0)", "category": "Staves", "platform": "Console"}, "-2115689173": {"name": "20: Mythical Staff (DPS 484.0-496.0)", "category": "Staves", "platform": "Console"}, "-2115689172": {"name": "21: Sovereign Staff (DPS 572.5-584.5)", "category": "Staves", "platform": "Console"}, "-2115688089": {"name": "22: Caduceus Staff (DPS 712.3-725.5)", "category": "Staves", "platform": "Console"}, "-2115688088": {"name": "23: Kerykeion (DPS 968.0-981.2)", "category": "Staves", "platform": "Console"}, "-1849507048": {"name": "Art Test CombatStaff Two-Handed 1", "category": "Staves", "platform": "Console"}, "-1849507047": {"name": "Art Test CombatStaff Two-Handed 2", "category": "Staves", "platform": "Console"}, "-1849507046": {"name": "Art Test CombatStaff Two-Handed 3", "category": "Staves", "platform": "Console"}, "-1849507045": {"name": "Art Test CombatStaff Two-Handed 4", "category": "Staves", "platform": "Console"}, "-1849507044": {"name": "Art Test CombatStaff Two-Handed 5", "category": "Staves", "platform": "Console"}, "1590673385": {"name": "Art Test Staff 1", "category": "Staves", "platform": "Console"}, "1590673386": {"name": "Art Test Staff 2", "category": "Staves", "platform": "Console"}, "1590673387": {"name": "Art Test Staff 3", "category": "Staves", "platform": "Console"}, "1590673388": {"name": "Art Test Staff 4", "category": "Staves", "platform": "Console"}, "1590673389": {"name": "Art Test Staff 5", "category": "Staves", "platform": "Console"}, "2065442005": {"name": "Crafted: Elderwood Staff", "category": "Staves", "platform": "Console"}, "-1170762813": {"name": "Legendary: Ahavarion, Spear of Lycander", "category": "Staves", "platform": "Console"}, "-1209646647": {"name": "Legendary: Autumn's Call", "category": "Staves", "platform": "Console"}, "-1263710987": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "-1263708543": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "300184993": {"name": "Legendary: Autumn's Call (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-306066026": {"name": "Legendary: Hellish Staff of Herding", "category": "Staves", "platform": "Console"}, "1952916002": {"name": "Legendary: Infernal Staff of Herding", "category": "Staves", "platform": "Console"}, "-1209718521": {"name": "Legendary: Maloth's Focus", "category": "Staves", "platform": "Console"}, "-1266082829": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "-1266080385": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "300184991": {"name": "Legendary: Maloth's Focus (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209862269": {"name": "Legendary: Mark of The Magi", "category": "Staves", "platform": "Console"}, "-1409366405": {"name": "Legendary: Ner'zhul's Staff of Shadowmoon (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "670723600": {"name": "Legendary: Nightmarish Staff of Herding", "category": "Staves", "platform": "Console"}, "-1077364974": {"name": "Legendary: Staff of Herding", "category": "Staves", "platform": "Console"}, "-1170655002": {"name": "Legendary: SuWong Diviner", "category": "Staves", "platform": "Console"}, "-1209898206": {"name": "Legendary: The Broken Staff", "category": "Staves", "platform": "Console"}, "-1272012434": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "-1272009990": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "300184986": {"name": "Legendary: The Broken Staff (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610710": {"name": "Legendary: The Grand Vizier", "category": "Staves", "platform": "Console"}, "-1262525066": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "-1262522622": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "300184994": {"name": "Legendary: The Grand Vizier (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610974": {"name": "Legendary: The Grand Vizier (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "-1270826513": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "-1270824069": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "300184987": {"name": "Legendary: The Magi (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170690939": {"name": "Legendary: The Smoldering Core", "category": "Staves", "platform": "Console"}, "-1209682584": {"name": "Legendary: The Tormentor", "category": "Staves", "platform": "Console"}, "-1264896908": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "-1264894464": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "300184992": {"name": "Legendary: The Tormentor (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170726876": {"name": "Legendary: Valthek's Rebuke", "category": "Staves", "platform": "Console"}, "-1209826332": {"name": "Legendary: Wormwood", "category": "Staves", "platform": "Console"}, "-1269640592": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "-1269638148": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "300184988": {"name": "Legendary: Wormwood (Old-Legacy)", "category": "Staves", "platform": "Console"}, "1889450717": {"name": "Legendary: Wormwood (Patch 2.1.2)", "category": "Staves", "platform": "Console"}, "-1953260964": {"name": "P2 combatStaff norm Legendary 01", "category": "Staves", "platform": "Console"}, "397178771": {"name": "PvP: Heroic Staff", "category": "Staves", "platform": "Console"}, "397178770": {"name": "PvP: Mighty Staff", "category": "Staves", "platform": "Console"}, "397178769": {"name": "PvP: Staff", "category": "Staves", "platform": "Console"}, "-270938921": {"name": "01: Short Sword (DPS 4.2-5.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938920": {"name": "02: Sabre (DPS 8.4-10.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938919": {"name": "03: Broadsword (DPS 11.2-13.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938918": {"name": "04: Longsword (DPS 16.1-18.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938917": {"name": "05: Falchion (DPS 20.3-22.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938916": {"name": "06: Scimitar (DPS 24.5-26.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938915": {"name": "07: War Sword (DPS 28.0-30.1)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938914": {"name": "08: Bastard Sword (DPS 32.2-34.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937832": {"name": "09: Gladius (DPS 39.2-41.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937831": {"name": "10: Cutlass (DPS 44.1-46.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937830": {"name": "11: Battle Sword (DPS 48.3-50.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937829": {"name": "12: Knight Sword (DPS 53.2-55.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937828": {"name": "13: Dao (DPS 62.3-64.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937827": {"name": "14: Shamshir (DPS 73.5-75.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937826": {"name": "15: Raid Sword (DPS 81.2-83.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937825": {"name": "16: Ancient Sword (DPS 93.1-95.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936743": {"name": "17: Spatha (DPS 100.1-104.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936742": {"name": "18: Pirate Sword (DPS 112.0-116.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936741": {"name": "19: Strong Sword (DPS 123.2-127.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936740": {"name": "20: King Blade (DPS 137.2-141.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936739": {"name": "21: Tulwar (DPS 151.2-155.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936738": {"name": "22: Saif (DPS 181.3-187.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936737": {"name": "23: Conquest Sword (DPS 210.0-216.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936736": {"name": "24: Rune Sword (DPS 242.2-248.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935654": {"name": "25: Champion Sword (DPS 322.0-328.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935653": {"name": "26: Tsunami Blade (DPS 392.0-398.3)", "category": "Swords, One-Handed", "platform": "Console"}, "1775003964": {"name": "Art Test Sword One-Handed 1", "category": "Swords, One-Handed", "platform": "Console"}, "1775003965": {"name": "Art Test Sword One-Handed 2", "category": "Swords, One-Handed", "platform": "Console"}, "1775003966": {"name": "Art Test Sword One-Handed 3", "category": "Swords, One-Handed", "platform": "Console"}, "1775003967": {"name": "Art Test Sword One-Handed 4", "category": "Swords, One-Handed", "platform": "Console"}, "1775003968": {"name": "Art Test Sword One-Handed 5", "category": "Swords, One-Handed", "platform": "Console"}, "560809999": {"name": "Crafted: Blacksteel Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1351405527": {"name": "Legendary: Amberwing", "category": "Swords, One-Handed", "platform": "Console"}, "1312306071": {"name": "Legendary: Azurewrath", "category": "Swords, One-Handed", "platform": "Console"}, "356350083": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "356352527": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242223": {"name": "Legendary: Azurewrath (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351441464": {"name": "Legendary: Deathwish", "category": "Swords, One-Handed", "platform": "Console"}, "1312270134": {"name": "Legendary: Devil Tongue", "category": "Swords, One-Handed", "platform": "Console"}, "355164162": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "355166606": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242222": {"name": "Legendary: Devil Tongue (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312377945": {"name": "Legendary: Doombringer", "category": "Swords, One-Handed", "platform": "Console"}, "358721925": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "358724369": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242225": {"name": "Legendary: Doombringer (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350255543": {"name": "Legendary: Exarian", "category": "Swords, One-Handed", "platform": "Console"}, "1350327417": {"name": "Legendary: Fulminator", "category": "Swords, One-Handed", "platform": "Console"}, "1350399291": {"name": "Legendary: Ghoul King's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "1350291480": {"name": "Legendary: Gift of Silaria", "category": "Swords, One-Handed", "platform": "Console"}, "1350363354": {"name": "Legendary: God Butcher", "category": "Swords, One-Handed", "platform": "Console"}, "364651530": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "364653974": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242230": {"name": "Legendary: Griswold's Masterpiece (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312557630": {"name": "Legendary: Griswold's Perfection", "category": "Swords, One-Handed", "platform": "Console"}, "1311084213": {"name": "Legendary: Griswold's Worn Edge", "category": "Swords, One-Handed", "platform": "Console"}, "316028769": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "316031213": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242189": {"name": "Legendary: Griswold's Worn Edge (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350471165": {"name": "Legendary: Incinerator", "category": "Swords, One-Handed", "platform": "Console"}, "229247441": {"name": "Legendary: Lifebane", "category": "Swords, One-Handed", "platform": "Console"}, "1312485756": {"name": "Legendary: Monster Hunter", "category": "Swords, One-Handed", "platform": "Console"}, "362279688": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "362282132": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242228": {"name": "Legendary: Monster Hunter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350435228": {"name": "Legendary: Nazim's Greatness", "category": "Swords, One-Handed", "platform": "Console"}, "1312234197": {"name": "Legendary: Rakanishu's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "353978241": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "353980685": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242221": {"name": "Legendary: Rakanishu's Blade (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351369590": {"name": "Legendary: Rancor", "category": "Swords, One-Handed", "platform": "Console"}, "1350507102": {"name": "Legendary: Rimeheart", "category": "Swords, One-Handed", "platform": "Console"}, "1311299835": {"name": "Legendary: Sever", "category": "Swords, One-Handed", "platform": "Console"}, "323144295": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "323146739": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242195": {"name": "Legendary: Sever (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "229283378": {"name": "Legendary: Shard of Hate", "category": "Swords, One-Handed", "platform": "Console"}, "1311192024": {"name": "Legendary: Skycutter", "category": "Swords, One-Handed", "platform": "Console"}, "319586532": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "319588976": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242192": {"name": "Legendary: Skycutter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1313456055": {"name": "Legendary: Spectrum", "category": "Swords, One-Handed", "platform": "Console"}, "394299555": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "394301999": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242255": {"name": "Legendary: Spectrum (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1311156087": {"name": "Legendary: The Ancient Bonesaber of Zumakalis", "category": "Swords, One-Handed", "platform": "Console"}, "318400611": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "318403055": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242191": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350219606": {"name": "Legendary: Thunderfury, Blessed Blade of the Windseeker", "category": "Swords, One-Handed", "platform": "Console"}, "1311120150": {"name": "Legendary: Wildwood", "category": "Swords, One-Handed", "platform": "Console"}, "317214690": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "317217134": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242190": {"name": "Legendary: Wildwood (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487634": {"name": "PvP: Heroic Bastard Sword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487635": {"name": "PvP: Mighty Longsword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487636": {"name": "PvP: Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1312521693": {"name": "Set: Born's Furious Wrath", "category": "Swords, One-Handed", "platform": "Console"}, "363465609": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "363468053": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242229": {"name": "Set: Born's Seething Rage (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1394445518": {"name": "Set: Little Rogue", "category": "Swords, One-Handed", "platform": "Console"}, "-1394481455": {"name": "Set: The Slanderer", "category": "Swords, One-Handed", "platform": "Console"}, "-2025765397": {"name": "Sword Of Justice Tyrael", "category": "Swords, One-Handed", "platform": "Console"}, "1351477401": {"name": "legendary: In-geom (Patch 2.2.0)", "category": "Swords, One-Handed", "platform": "Console"}, "-231803528": {"name": "01: Two-Handed Sword (DPS 11.0-12.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803527": {"name": "02: Flamberge (DPS 16.0-17.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803526": {"name": "03: Dervish (DPS 22.6-24.2)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803525": {"name": "04: Executioner Sword (DPS 28.1-29.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803524": {"name": "05: Nodachi (DPS 35.2-36.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803523": {"name": "06: Claymore (DPS 41.8-43.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802439": {"name": "07: Great Sword (DPS 52.8-54.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802438": {"name": "08: Reaver (DPS 62.2-65.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802437": {"name": "09: Kilij (DPS 74.8-78.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802436": {"name": "10: Mameluke (DPS 89.7-93.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802435": {"name": "11: Nagamaki (DPS 106.2-111.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802434": {"name": "12: Grand Sword (DPS 126.5-133.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801350": {"name": "13: Highland Sword (DPS 171.6-179.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801349": {"name": "14: Brimstone Sword (DPS 215.6-223.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801348": {"name": "15: Yatagan (DPS 269.0-278.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801347": {"name": "16: Colossus Blade (DPS 367.4-379.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801346": {"name": "17: Oni Blade (DPS 433.4-446.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801345": {"name": "18: Warlord Sword (DPS 511.5-524.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800261": {"name": "19: Gothic Blade (DPS 670.5-682.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800260": {"name": "20: Kingslayer (DPS 907.4-919.4)", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039901": {"name": "Art Test Sword Two-Handed 1", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039902": {"name": "Art Test Sword Two-Handed 2", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039903": {"name": "Art Test Sword Two-Handed 3", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039904": {"name": "Art Test Sword Two-Handed 4", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039905": {"name": "Art Test Sword Two-Handed 5", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028384713": {"name": "Legendary: Blackguard", "category": "Swords, Two-Handed", "platform": "Console"}, "422965539": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "422967983": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377615": {"name": "Legendary: Blackguard (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029355012": {"name": "Legendary: Blade of Prophecy", "category": "Swords, Two-Handed", "platform": "Console"}, "390945672": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "390948116": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377588": {"name": "Legendary: Blade of Prophecy (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "1516448771": {"name": "Legendary: Blade of the Ancients", "category": "Swords, Two-Handed", "platform": "Console"}, "-990363367": {"name": "Legendary: Blood Brother", "category": "Swords, Two-Handed", "platform": "Console"}, "-990399304": {"name": "Legendary: Cam's Rebuttal", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028348776": {"name": "Legendary: Faithful Memory", "category": "Swords, Two-Handed", "platform": "Console"}, "424151460": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "424153904": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377616": {"name": "Legendary: Faithful Memory (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028420650": {"name": "Legendary: Maximus", "category": "Swords, Two-Handed", "platform": "Console"}, "421779618": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "421782062": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377614": {"name": "Legendary: Maximus (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029462823": {"name": "Legendary: Scourge", "category": "Swords, Two-Handed", "platform": "Console"}, "387387909": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "387390353": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377585": {"name": "Legendary: Scourge (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028276902": {"name": "Legendary: Splintered Oar", "category": "Swords, Two-Handed", "platform": "Console"}, "426523302": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "426525746": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377618": {"name": "Legendary: Splintered Oar (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990435241": {"name": "Legendary: Stalgard's Decimator", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029570634": {"name": "Legendary: The Grandfather", "category": "Swords, Two-Handed", "platform": "Console"}, "383830146": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "383832590": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377582": {"name": "Legendary: The Grandfather (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029319075": {"name": "Legendary: The Sultan of Blinding Sand", "category": "Swords, Two-Handed", "platform": "Console"}, "392131593": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "392134037": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377589": {"name": "Legendary: The Sultan of Blinding Sand (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029534697": {"name": "Legendary: The Zweihander", "category": "Swords, Two-Handed", "platform": "Console"}, "385016067": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "385018511": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377583": {"name": "Legendary: The Zweihander (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029498760": {"name": "Legendary: Warmonger", "category": "Swords, Two-Handed", "platform": "Console"}, "386201988": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "386204432": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377584": {"name": "Legendary: Warmonger (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1271367654": {"name": "legendary: Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990291493": {"name": "legendary: Ch'il-chi-do (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990327430": {"name": "legendary: Corrupted Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "1147339621": {"name": "01: Holy Tome", "category": "Templar Relics", "platform": "Console"}, "1147339622": {"name": "02: Spear Fragment", "category": "Templar Relics", "platform": "Console"}, "1147340710": {"name": "03: Sacred Text", "category": "Templar Relics", "platform": "Console"}, "1147340711": {"name": "04: Blade Shard", "category": "Templar Relics", "platform": "Console"}, "1147340712": {"name": "05: Martyr Tears", "category": "Templar Relics", "platform": "Console"}, "1147340713": {"name": "06: Chalice", "category": "Templar Relics", "platform": "Console"}, "1147341799": {"name": "07: Libram Spiritus", "category": "Templar Relics", "platform": "Console"}, "1147341800": {"name": "08: Blade Remnant", "category": "Templar Relics", "platform": "Console"}, "1147341801": {"name": "09: Saint Tears", "category": "Templar Relics", "platform": "Console"}, "1147341802": {"name": "10: Grail", "category": "Templar Relics", "platform": "Console"}, "1147341803": {"name": "11: Codex", "category": "Templar Relics", "platform": "Console"}, "1147341804": {"name": "12: Broken Foible", "category": "Templar Relics", "platform": "Console"}, "-765770609": {"name": "Legendary: Enchanting Favor", "category": "Templar Relics", "platform": "Console"}, "-765770607": {"name": "Legendary: Hillenbrand's Training Sword", "category": "Templar Relics", "platform": "Console"}, "-765770608": {"name": "Legendary: Relic of Akarat", "category": "Templar Relics", "platform": "Console"}, "-1438295706": {"name": "Don's 2H Sword of Testing", "category": "Test", "platform": "Console"}, "-1438295707": {"name": "Don's Sword of Testing", "category": "Test", "platform": "Console"}, "-1585353949": {"name": "P1 Test Ring 941 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353948": {"name": "P1 Test Ring 942 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353947": {"name": "P1 Test Ring 943 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353946": {"name": "P1 Test Ring 944 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388889": {"name": "P2 TEST RING 021 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388890": {"name": "P2 TEST RING 022 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388891": {"name": "P2 TEST RING 023 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388892": {"name": "P2 TEST RING 024 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388893": {"name": "P2 TEST RING 025 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388894": {"name": "P2 TEST RING 026 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388895": {"name": "P2 TEST RING 027 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388896": {"name": "P2 TEST RING 028 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388897": {"name": "P2 TEST RING 029 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388921": {"name": "P2 TEST RING 030 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388922": {"name": "P2 TEST RING 031 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388923": {"name": "P2 TEST RING 032 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388924": {"name": "P2 TEST RING 033 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388925": {"name": "P2 TEST RING 034 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388926": {"name": "P2 TEST RING 035 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388927": {"name": "P2 TEST RING 036 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388928": {"name": "P2 TEST RING 037 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388929": {"name": "P2 TEST RING 038 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388930": {"name": "P2 TEST RING 039 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388954": {"name": "P2 TEST RING 040 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388955": {"name": "P2 TEST RING 041 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388956": {"name": "P2 TEST RING 042 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388957": {"name": "P2 TEST RING 043 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388958": {"name": "P2 TEST RING 044 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388959": {"name": "P2 TEST RING 045 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388960": {"name": "P2 TEST RING 046 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388961": {"name": "P2 TEST RING 047 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388962": {"name": "P2 TEST RING 048 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388963": {"name": "P2 TEST RING 049 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388987": {"name": "P2 TEST RING 050 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388824": {"name": "P2 Test Ring 002 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388825": {"name": "P2 Test Ring 003 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388826": {"name": "P2 Test Ring 004 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388827": {"name": "P2 Test Ring 005 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388828": {"name": "P2 Test Ring 006 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388829": {"name": "P2 Test Ring 007 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388830": {"name": "P2 Test Ring 008 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388831": {"name": "P2 Test Ring 009 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388855": {"name": "P2 Test Ring 010 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388856": {"name": "P2 Test Ring 011 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388857": {"name": "P2 Test Ring 012 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388858": {"name": "P2 Test Ring 013 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388859": {"name": "P2 Test Ring 014 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388860": {"name": "P2 Test Ring 015 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388861": {"name": "P2 Test Ring 016 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388862": {"name": "P2 Test Ring 017 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388863": {"name": "P2 Test Ring 018 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388864": {"name": "P2 Test Ring 019 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388888": {"name": "P2 Test Ring 020 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "1608362283": {"name": "P2_WizardSet_Scroll_Test (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388823": {"name": "Test Ring 001 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "708102766": {"name": "Test Ring 1000", "category": "Test", "platform": "Console"}, "-993303550": {"name": "Test Ring 500", "category": "Test", "platform": "Console"}, "-993267613": {"name": "Test Ring 501", "category": "Test", "platform": "Console"}, "-993231676": {"name": "Test Ring 502", "category": "Test", "platform": "Console"}, "-993195739": {"name": "Test Ring 503", "category": "Test", "platform": "Console"}, "-993159802": {"name": "Test Ring 504", "category": "Test", "platform": "Console"}, "-993123865": {"name": "Test Ring 505", "category": "Test", "platform": "Console"}, "-993087928": {"name": "Test Ring 506", "category": "Test", "platform": "Console"}, "-993051991": {"name": "Test Ring 507", "category": "Test", "platform": "Console"}, "-993016054": {"name": "Test Ring 508", "category": "Test", "platform": "Console"}, "-992980117": {"name": "Test Ring 509", "category": "Test", "platform": "Console"}, "-992117629": {"name": "Test Ring 510", "category": "Test", "platform": "Console"}, "-992081692": {"name": "Test Ring 511", "category": "Test", "platform": "Console"}, "-992045755": {"name": "Test Ring 512", "category": "Test", "platform": "Console"}, "-992009818": {"name": "Test Ring 513", "category": "Test", "platform": "Console"}, "-991973881": {"name": "Test Ring 514", "category": "Test", "platform": "Console"}, "-991937944": {"name": "Test Ring 515", "category": "Test", "platform": "Console"}, "-991902007": {"name": "Test Ring 516", "category": "Test", "platform": "Console"}, "-991866070": {"name": "Test Ring 517", "category": "Test", "platform": "Console"}, "-991830133": {"name": "Test Ring 518", "category": "Test", "platform": "Console"}, "-991794196": {"name": "Test Ring 519", "category": "Test", "platform": "Console"}, "-990931708": {"name": "Test Ring 520", "category": "Test", "platform": "Console"}, "-990895771": {"name": "Test Ring 521", "category": "Test", "platform": "Console"}, "-990859834": {"name": "Test Ring 522", "category": "Test", "platform": "Console"}, "-990823897": {"name": "Test Ring 523", "category": "Test", "platform": "Console"}, "-990787960": {"name": "Test Ring 524", "category": "Test", "platform": "Console"}, "-990752023": {"name": "Test Ring 525", "category": "Test", "platform": "Console"}, "-990716086": {"name": "Test Ring 526", "category": "Test", "platform": "Console"}, "-990680149": {"name": "Test Ring 527", "category": "Test", "platform": "Console"}, "-990644212": {"name": "Test Ring 528", "category": "Test", "platform": "Console"}, "-990608275": {"name": "Test Ring 529", "category": "Test", "platform": "Console"}, "-989745787": {"name": "Test Ring 530", "category": "Test", "platform": "Console"}, "-989709850": {"name": "Test Ring 531", "category": "Test", "platform": "Console"}, "-989673913": {"name": "Test Ring 532", "category": "Test", "platform": "Console"}, "-989637976": {"name": "Test Ring 533", "category": "Test", "platform": "Console"}, "-989602039": {"name": "Test Ring 534", "category": "Test", "platform": "Console"}, "-989566102": {"name": "Test Ring 535", "category": "Test", "platform": "Console"}, "-989530165": {"name": "Test Ring 536", "category": "Test", "platform": "Console"}, "-989494228": {"name": "Test Ring 537", "category": "Test", "platform": "Console"}, "-989458291": {"name": "Test Ring 538", "category": "Test", "platform": "Console"}, "-989422354": {"name": "Test Ring 539", "category": "Test", "platform": "Console"}, "-988559866": {"name": "Test Ring 540", "category": "Test", "platform": "Console"}, "-988523929": {"name": "Test Ring 541", "category": "Test", "platform": "Console"}, "-988487992": {"name": "Test Ring 542", "category": "Test", "platform": "Console"}, "-988452055": {"name": "Test Ring 543", "category": "Test", "platform": "Console"}, "-988416118": {"name": "Test Ring 544", "category": "Test", "platform": "Console"}, "-988380181": {"name": "Test Ring 545", "category": "Test", "platform": "Console"}, "-988344244": {"name": "Test Ring 546", "category": "Test", "platform": "Console"}, "-988308307": {"name": "Test Ring 547", "category": "Test", "platform": "Console"}, "-988272370": {"name": "Test Ring 548", "category": "Test", "platform": "Console"}, "-988236433": {"name": "Test Ring 549", "category": "Test", "platform": "Console"}, "-987373945": {"name": "Test Ring 550", "category": "Test", "platform": "Console"}, "-987338008": {"name": "Test Ring 551", "category": "Test", "platform": "Console"}, "-987302071": {"name": "Test Ring 552", "category": "Test", "platform": "Console"}, "-987266134": {"name": "Test Ring 553", "category": "Test", "platform": "Console"}, "-987230197": {"name": "Test Ring 554", "category": "Test", "platform": "Console"}, "-987194260": {"name": "Test Ring 555", "category": "Test", "platform": "Console"}, "-987158323": {"name": "Test Ring 556", "category": "Test", "platform": "Console"}, "-987122386": {"name": "Test Ring 557", "category": "Test", "platform": "Console"}, "-987086449": {"name": "Test Ring 558", "category": "Test", "platform": "Console"}, "-987050512": {"name": "Test Ring 559", "category": "Test", "platform": "Console"}, "-986188024": {"name": "Test Ring 560", "category": "Test", "platform": "Console"}, "-986152087": {"name": "Test Ring 561", "category": "Test", "platform": "Console"}, "-986116150": {"name": "Test Ring 562", "category": "Test", "platform": "Console"}, "-986080213": {"name": "Test Ring 563", "category": "Test", "platform": "Console"}, "-986044276": {"name": "Test Ring 564", "category": "Test", "platform": "Console"}, "-986008339": {"name": "Test Ring 565", "category": "Test", "platform": "Console"}, "-985972402": {"name": "Test Ring 566", "category": "Test", "platform": "Console"}, "-985936465": {"name": "Test Ring 567", "category": "Test", "platform": "Console"}, "-985900528": {"name": "Test Ring 568", "category": "Test", "platform": "Console"}, "-985864591": {"name": "Test Ring 569", "category": "Test", "platform": "Console"}, "-985002103": {"name": "Test Ring 570", "category": "Test", "platform": "Console"}, "-984966166": {"name": "Test Ring 571", "category": "Test", "platform": "Console"}, "-984930229": {"name": "Test Ring 572", "category": "Test", "platform": "Console"}, "-984894292": {"name": "Test Ring 573", "category": "Test", "platform": "Console"}, "-984858355": {"name": "Test Ring 574", "category": "Test", "platform": "Console"}, "-984822418": {"name": "Test Ring 575", "category": "Test", "platform": "Console"}, "-984786481": {"name": "Test Ring 576", "category": "Test", "platform": "Console"}, "-984750544": {"name": "Test Ring 577", "category": "Test", "platform": "Console"}, "-984714607": {"name": "Test Ring 578", "category": "Test", "platform": "Console"}, "-984678670": {"name": "Test Ring 579", "category": "Test", "platform": "Console"}, "-983816182": {"name": "Test Ring 580", "category": "Test", "platform": "Console"}, "-983780245": {"name": "Test Ring 581", "category": "Test", "platform": "Console"}, "-983744308": {"name": "Test Ring 582", "category": "Test", "platform": "Console"}, "-983708371": {"name": "Test Ring 583", "category": "Test", "platform": "Console"}, "-983672434": {"name": "Test Ring 584", "category": "Test", "platform": "Console"}, "-983636497": {"name": "Test Ring 585", "category": "Test", "platform": "Console"}, "-983600560": {"name": "Test Ring 586", "category": "Test", "platform": "Console"}, "-983564623": {"name": "Test Ring 587", "category": "Test", "platform": "Console"}, "-983528686": {"name": "Test Ring 588", "category": "Test", "platform": "Console"}, "-983492749": {"name": "Test Ring 589", "category": "Test", "platform": "Console"}, "-982630261": {"name": "Test Ring 590", "category": "Test", "platform": "Console"}, "-982594324": {"name": "Test Ring 591", "category": "Test", "platform": "Console"}, "-982558387": {"name": "Test Ring 592", "category": "Test", "platform": "Console"}, "-982522450": {"name": "Test Ring 593", "category": "Test", "platform": "Console"}, "-982486513": {"name": "Test Ring 594", "category": "Test", "platform": "Console"}, "-982450576": {"name": "Test Ring 595", "category": "Test", "platform": "Console"}, "-982414639": {"name": "Test Ring 596", "category": "Test", "platform": "Console"}, "-982378702": {"name": "Test Ring 597", "category": "Test", "platform": "Console"}, "-982342765": {"name": "Test Ring 598", "category": "Test", "platform": "Console"}, "-982306828": {"name": "Test Ring 599", "category": "Test", "platform": "Console"}, "-954168157": {"name": "Test Ring 600", "category": "Test", "platform": "Console"}, "-954132220": {"name": "Test Ring 601", "category": "Test", "platform": "Console"}, "-954096283": {"name": "Test Ring 602", "category": "Test", "platform": "Console"}, "-954060346": {"name": "Test Ring 603", "category": "Test", "platform": "Console"}, "-954024409": {"name": "Test Ring 604", "category": "Test", "platform": "Console"}, "-953988472": {"name": "Test Ring 605", "category": "Test", "platform": "Console"}, "-953952535": {"name": "Test Ring 606", "category": "Test", "platform": "Console"}, "-953916598": {"name": "Test Ring 607", "category": "Test", "platform": "Console"}, "-953880661": {"name": "Test Ring 608", "category": "Test", "platform": "Console"}, "-953844724": {"name": "Test Ring 609", "category": "Test", "platform": "Console"}, "-952982236": {"name": "Test Ring 610", "category": "Test", "platform": "Console"}, "-952946299": {"name": "Test Ring 611", "category": "Test", "platform": "Console"}, "-952910362": {"name": "Test Ring 612", "category": "Test", "platform": "Console"}, "-952874425": {"name": "Test Ring 613", "category": "Test", "platform": "Console"}, "-952838488": {"name": "Test Ring 614", "category": "Test", "platform": "Console"}, "-952802551": {"name": "Test Ring 615", "category": "Test", "platform": "Console"}, "-952766614": {"name": "Test Ring 616", "category": "Test", "platform": "Console"}, "-952730677": {"name": "Test Ring 617", "category": "Test", "platform": "Console"}, "-952694740": {"name": "Test Ring 618", "category": "Test", "platform": "Console"}, "-952658803": {"name": "Test Ring 619", "category": "Test", "platform": "Console"}, "-951796315": {"name": "Test Ring 620", "category": "Test", "platform": "Console"}, "-951760378": {"name": "Test Ring 621", "category": "Test", "platform": "Console"}, "-951724441": {"name": "Test Ring 622", "category": "Test", "platform": "Console"}, "-951688504": {"name": "Test Ring 623", "category": "Test", "platform": "Console"}, "-951652567": {"name": "Test Ring 624", "category": "Test", "platform": "Console"}, "-951616630": {"name": "Test Ring 625", "category": "Test", "platform": "Console"}, "-951580693": {"name": "Test Ring 626", "category": "Test", "platform": "Console"}, "-951544756": {"name": "Test Ring 627", "category": "Test", "platform": "Console"}, "-951508819": {"name": "Test Ring 628", "category": "Test", "platform": "Console"}, "-951472882": {"name": "Test Ring 629", "category": "Test", "platform": "Console"}, "-950610394": {"name": "Test Ring 630", "category": "Test", "platform": "Console"}, "-950574457": {"name": "Test Ring 631", "category": "Test", "platform": "Console"}, "-950538520": {"name": "Test Ring 632", "category": "Test", "platform": "Console"}, "-950502583": {"name": "Test Ring 633", "category": "Test", "platform": "Console"}, "-950466646": {"name": "Test Ring 634", "category": "Test", "platform": "Console"}, "-950430709": {"name": "Test Ring 635", "category": "Test", "platform": "Console"}, "-950394772": {"name": "Test Ring 636", "category": "Test", "platform": "Console"}, "-950358835": {"name": "Test Ring 637", "category": "Test", "platform": "Console"}, "-950322898": {"name": "Test Ring 638", "category": "Test", "platform": "Console"}, "-950286961": {"name": "Test Ring 639", "category": "Test", "platform": "Console"}, "-949424473": {"name": "Test Ring 640", "category": "Test", "platform": "Console"}, "-949388536": {"name": "Test Ring 641", "category": "Test", "platform": "Console"}, "-949352599": {"name": "Test Ring 642", "category": "Test", "platform": "Console"}, "-949316662": {"name": "Test Ring 643", "category": "Test", "platform": "Console"}, "-949280725": {"name": "Test Ring 644", "category": "Test", "platform": "Console"}, "-949244788": {"name": "Test Ring 645", "category": "Test", "platform": "Console"}, "-949208851": {"name": "Test Ring 646", "category": "Test", "platform": "Console"}, "-949172914": {"name": "Test Ring 647", "category": "Test", "platform": "Console"}, "-949136977": {"name": "Test Ring 648", "category": "Test", "platform": "Console"}, "-949101040": {"name": "Test Ring 649", "category": "Test", "platform": "Console"}, "-948238552": {"name": "Test Ring 650", "category": "Test", "platform": "Console"}, "-948202615": {"name": "Test Ring 651", "category": "Test", "platform": "Console"}, "-948166678": {"name": "Test Ring 652", "category": "Test", "platform": "Console"}, "-948130741": {"name": "Test Ring 653", "category": "Test", "platform": "Console"}, "-948094804": {"name": "Test Ring 654", "category": "Test", "platform": "Console"}, "-948058867": {"name": "Test Ring 655", "category": "Test", "platform": "Console"}, "-948022930": {"name": "Test Ring 656", "category": "Test", "platform": "Console"}, "-947986993": {"name": "Test Ring 657", "category": "Test", "platform": "Console"}, "-947951056": {"name": "Test Ring 658", "category": "Test", "platform": "Console"}, "-947915119": {"name": "Test Ring 659", "category": "Test", "platform": "Console"}, "-947052631": {"name": "Test Ring 660", "category": "Test", "platform": "Console"}, "-947016694": {"name": "Test Ring 661", "category": "Test", "platform": "Console"}, "-946980757": {"name": "Test Ring 662", "category": "Test", "platform": "Console"}, "-946944820": {"name": "Test Ring 663", "category": "Test", "platform": "Console"}, "-946908883": {"name": "Test Ring 664", "category": "Test", "platform": "Console"}, "-946872946": {"name": "Test Ring 665", "category": "Test", "platform": "Console"}, "-946837009": {"name": "Test Ring 666", "category": "Test", "platform": "Console"}, "-946801072": {"name": "Test Ring 667", "category": "Test", "platform": "Console"}, "-946765135": {"name": "Test Ring 668", "category": "Test", "platform": "Console"}, "-946729198": {"name": "Test Ring 669", "category": "Test", "platform": "Console"}, "-945866710": {"name": "Test Ring 670", "category": "Test", "platform": "Console"}, "-945830773": {"name": "Test Ring 671", "category": "Test", "platform": "Console"}, "-945794836": {"name": "Test Ring 672", "category": "Test", "platform": "Console"}, "-945758899": {"name": "Test Ring 673", "category": "Test", "platform": "Console"}, "-945722962": {"name": "Test Ring 674", "category": "Test", "platform": "Console"}, "-945687025": {"name": "Test Ring 675", "category": "Test", "platform": "Console"}, "-945651088": {"name": "Test Ring 676", "category": "Test", "platform": "Console"}, "-945615151": {"name": "Test Ring 677", "category": "Test", "platform": "Console"}, "-945579214": {"name": "Test Ring 678", "category": "Test", "platform": "Console"}, "-945543277": {"name": "Test Ring 679", "category": "Test", "platform": "Console"}, "-944680789": {"name": "Test Ring 680", "category": "Test", "platform": "Console"}, "-944644852": {"name": "Test Ring 681", "category": "Test", "platform": "Console"}, "-944608915": {"name": "Test Ring 682", "category": "Test", "platform": "Console"}, "-944572978": {"name": "Test Ring 683", "category": "Test", "platform": "Console"}, "-944537041": {"name": "Test Ring 684", "category": "Test", "platform": "Console"}, "-944501104": {"name": "Test Ring 685", "category": "Test", "platform": "Console"}, "-944465167": {"name": "Test Ring 686", "category": "Test", "platform": "Console"}, "-944429230": {"name": "Test Ring 687", "category": "Test", "platform": "Console"}, "-944393293": {"name": "Test Ring 688", "category": "Test", "platform": "Console"}, "-944357356": {"name": "Test Ring 689", "category": "Test", "platform": "Console"}, "-943494868": {"name": "Test Ring 690", "category": "Test", "platform": "Console"}, "-943458931": {"name": "Test Ring 691", "category": "Test", "platform": "Console"}, "-943422994": {"name": "Test Ring 692", "category": "Test", "platform": "Console"}, "-943387057": {"name": "Test Ring 693", "category": "Test", "platform": "Console"}, "-943351120": {"name": "Test Ring 694", "category": "Test", "platform": "Console"}, "-943315183": {"name": "Test Ring 695", "category": "Test", "platform": "Console"}, "-943279246": {"name": "Test Ring 696", "category": "Test", "platform": "Console"}, "-943243309": {"name": "Test Ring 697", "category": "Test", "platform": "Console"}, "-943207372": {"name": "Test Ring 698", "category": "Test", "platform": "Console"}, "-943171435": {"name": "Test Ring 699", "category": "Test", "platform": "Console"}, "-915032764": {"name": "Test Ring 700", "category": "Test", "platform": "Console"}, "-914996827": {"name": "Test Ring 701", "category": "Test", "platform": "Console"}, "-914960890": {"name": "Test Ring 702", "category": "Test", "platform": "Console"}, "-914924953": {"name": "Test Ring 703", "category": "Test", "platform": "Console"}, "-914889016": {"name": "Test Ring 704", "category": "Test", "platform": "Console"}, "-914853079": {"name": "Test Ring 705", "category": "Test", "platform": "Console"}, "-914817142": {"name": "Test Ring 706", "category": "Test", "platform": "Console"}, "-914781205": {"name": "Test Ring 707", "category": "Test", "platform": "Console"}, "-914745268": {"name": "Test Ring 708", "category": "Test", "platform": "Console"}, "-914709331": {"name": "Test Ring 709", "category": "Test", "platform": "Console"}, "-913846843": {"name": "Test Ring 710", "category": "Test", "platform": "Console"}, "-913810906": {"name": "Test Ring 711", "category": "Test", "platform": "Console"}, "-913774969": {"name": "Test Ring 712", "category": "Test", "platform": "Console"}, "-913739032": {"name": "Test Ring 713", "category": "Test", "platform": "Console"}, "-913703095": {"name": "Test Ring 714", "category": "Test", "platform": "Console"}, "-913667158": {"name": "Test Ring 715", "category": "Test", "platform": "Console"}, "-913631221": {"name": "Test Ring 716", "category": "Test", "platform": "Console"}, "-913595284": {"name": "Test Ring 717", "category": "Test", "platform": "Console"}, "-913559347": {"name": "Test Ring 718", "category": "Test", "platform": "Console"}, "-913523410": {"name": "Test Ring 719", "category": "Test", "platform": "Console"}, "-912660922": {"name": "Test Ring 720", "category": "Test", "platform": "Console"}, "-912624985": {"name": "Test Ring 721", "category": "Test", "platform": "Console"}, "-912589048": {"name": "Test Ring 722", "category": "Test", "platform": "Console"}, "-912553111": {"name": "Test Ring 723", "category": "Test", "platform": "Console"}, "-912517174": {"name": "Test Ring 724", "category": "Test", "platform": "Console"}, "-912481237": {"name": "Test Ring 725", "category": "Test", "platform": "Console"}, "-912445300": {"name": "Test Ring 726", "category": "Test", "platform": "Console"}, "-912409363": {"name": "Test Ring 727", "category": "Test", "platform": "Console"}, "-912373426": {"name": "Test Ring 728", "category": "Test", "platform": "Console"}, "-912337489": {"name": "Test Ring 729", "category": "Test", "platform": "Console"}, "-911475001": {"name": "Test Ring 730", "category": "Test", "platform": "Console"}, "-911439064": {"name": "Test Ring 731", "category": "Test", "platform": "Console"}, "-911403127": {"name": "Test Ring 732", "category": "Test", "platform": "Console"}, "-911367190": {"name": "Test Ring 733", "category": "Test", "platform": "Console"}, "-911331253": {"name": "Test Ring 734", "category": "Test", "platform": "Console"}, "-911295316": {"name": "Test Ring 735", "category": "Test", "platform": "Console"}, "-911259379": {"name": "Test Ring 736", "category": "Test", "platform": "Console"}, "-911223442": {"name": "Test Ring 737", "category": "Test", "platform": "Console"}, "-911187505": {"name": "Test Ring 738", "category": "Test", "platform": "Console"}, "-911151568": {"name": "Test Ring 739", "category": "Test", "platform": "Console"}, "-910289080": {"name": "Test Ring 740", "category": "Test", "platform": "Console"}, "-910253143": {"name": "Test Ring 741", "category": "Test", "platform": "Console"}, "-910217206": {"name": "Test Ring 742", "category": "Test", "platform": "Console"}, "-910181269": {"name": "Test Ring 743", "category": "Test", "platform": "Console"}, "-910145332": {"name": "Test Ring 744", "category": "Test", "platform": "Console"}, "-910109395": {"name": "Test Ring 745", "category": "Test", "platform": "Console"}, "-910073458": {"name": "Test Ring 746", "category": "Test", "platform": "Console"}, "-910037521": {"name": "Test Ring 747", "category": "Test", "platform": "Console"}, "-910001584": {"name": "Test Ring 748", "category": "Test", "platform": "Console"}, "-909965647": {"name": "Test Ring 749", "category": "Test", "platform": "Console"}, "-909103159": {"name": "Test Ring 750", "category": "Test", "platform": "Console"}, "-909067222": {"name": "Test Ring 751", "category": "Test", "platform": "Console"}, "-909031285": {"name": "Test Ring 752", "category": "Test", "platform": "Console"}, "-908995348": {"name": "Test Ring 753", "category": "Test", "platform": "Console"}, "-908959411": {"name": "Test Ring 754", "category": "Test", "platform": "Console"}, "-908923474": {"name": "Test Ring 755", "category": "Test", "platform": "Console"}, "-908887537": {"name": "Test Ring 756", "category": "Test", "platform": "Console"}, "-908851600": {"name": "Test Ring 757", "category": "Test", "platform": "Console"}, "-908815663": {"name": "Test Ring 758", "category": "Test", "platform": "Console"}, "-908779726": {"name": "Test Ring 759", "category": "Test", "platform": "Console"}, "-907917238": {"name": "Test Ring 760", "category": "Test", "platform": "Console"}, "-907881301": {"name": "Test Ring 761", "category": "Test", "platform": "Console"}, "-907845364": {"name": "Test Ring 762", "category": "Test", "platform": "Console"}, "-907809427": {"name": "Test Ring 763", "category": "Test", "platform": "Console"}, "-907773490": {"name": "Test Ring 764", "category": "Test", "platform": "Console"}, "-907737553": {"name": "Test Ring 765", "category": "Test", "platform": "Console"}, "-907701616": {"name": "Test Ring 766", "category": "Test", "platform": "Console"}, "-907665679": {"name": "Test Ring 767", "category": "Test", "platform": "Console"}, "-907629742": {"name": "Test Ring 768", "category": "Test", "platform": "Console"}, "-907593805": {"name": "Test Ring 769", "category": "Test", "platform": "Console"}, "-906731317": {"name": "Test Ring 770", "category": "Test", "platform": "Console"}, "-906695380": {"name": "Test Ring 771", "category": "Test", "platform": "Console"}, "-906659443": {"name": "Test Ring 772", "category": "Test", "platform": "Console"}, "-906623506": {"name": "Test Ring 773", "category": "Test", "platform": "Console"}, "-906587569": {"name": "Test Ring 774", "category": "Test", "platform": "Console"}, "-906551632": {"name": "Test Ring 775", "category": "Test", "platform": "Console"}, "-906515695": {"name": "Test Ring 776", "category": "Test", "platform": "Console"}, "-906479758": {"name": "Test Ring 777", "category": "Test", "platform": "Console"}, "-906443821": {"name": "Test Ring 778", "category": "Test", "platform": "Console"}, "-906407884": {"name": "Test Ring 779", "category": "Test", "platform": "Console"}, "-905545396": {"name": "Test Ring 780", "category": "Test", "platform": "Console"}, "-905509459": {"name": "Test Ring 781", "category": "Test", "platform": "Console"}, "-905473522": {"name": "Test Ring 782", "category": "Test", "platform": "Console"}, "-905437585": {"name": "Test Ring 783", "category": "Test", "platform": "Console"}, "-905401648": {"name": "Test Ring 784", "category": "Test", "platform": "Console"}, "-905365711": {"name": "Test Ring 785", "category": "Test", "platform": "Console"}, "-905329774": {"name": "Test Ring 786", "category": "Test", "platform": "Console"}, "-905293837": {"name": "Test Ring 787", "category": "Test", "platform": "Console"}, "-905257900": {"name": "Test Ring 788", "category": "Test", "platform": "Console"}, "-905221963": {"name": "Test Ring 789", "category": "Test", "platform": "Console"}, "-904359475": {"name": "Test Ring 790", "category": "Test", "platform": "Console"}, "-904323538": {"name": "Test Ring 791", "category": "Test", "platform": "Console"}, "-904287601": {"name": "Test Ring 792", "category": "Test", "platform": "Console"}, "-904251664": {"name": "Test Ring 793", "category": "Test", "platform": "Console"}, "-904215727": {"name": "Test Ring 794", "category": "Test", "platform": "Console"}, "-904179790": {"name": "Test Ring 795", "category": "Test", "platform": "Console"}, "-904143853": {"name": "Test Ring 796", "category": "Test", "platform": "Console"}, "-904107916": {"name": "Test Ring 797", "category": "Test", "platform": "Console"}, "-904071979": {"name": "Test Ring 798", "category": "Test", "platform": "Console"}, "-904036042": {"name": "Test Ring 799", "category": "Test", "platform": "Console"}, "-875897371": {"name": "Test Ring 800", "category": "Test", "platform": "Console"}, "-875861434": {"name": "Test Ring 801", "category": "Test", "platform": "Console"}, "-875825497": {"name": "Test Ring 802", "category": "Test", "platform": "Console"}, "-875789560": {"name": "Test Ring 803", "category": "Test", "platform": "Console"}, "-875753623": {"name": "Test Ring 804", "category": "Test", "platform": "Console"}, "-875717686": {"name": "Test Ring 805", "category": "Test", "platform": "Console"}, "-875681749": {"name": "Test Ring 806", "category": "Test", "platform": "Console"}, "-875645812": {"name": "Test Ring 807", "category": "Test", "platform": "Console"}, "-875609875": {"name": "Test Ring 808", "category": "Test", "platform": "Console"}, "-875573938": {"name": "Test Ring 809", "category": "Test", "platform": "Console"}, "-874711450": {"name": "Test Ring 810", "category": "Test", "platform": "Console"}, "-874675513": {"name": "Test Ring 811", "category": "Test", "platform": "Console"}, "-874639576": {"name": "Test Ring 812", "category": "Test", "platform": "Console"}, "-874603639": {"name": "Test Ring 813", "category": "Test", "platform": "Console"}, "-874567702": {"name": "Test Ring 814", "category": "Test", "platform": "Console"}, "-874531765": {"name": "Test Ring 815", "category": "Test", "platform": "Console"}, "-874495828": {"name": "Test Ring 816", "category": "Test", "platform": "Console"}, "-874459891": {"name": "Test Ring 817", "category": "Test", "platform": "Console"}, "-874423954": {"name": "Test Ring 818", "category": "Test", "platform": "Console"}, "-874388017": {"name": "Test Ring 819", "category": "Test", "platform": "Console"}, "-873525529": {"name": "Test Ring 820", "category": "Test", "platform": "Console"}, "-873489592": {"name": "Test Ring 821", "category": "Test", "platform": "Console"}, "-873453655": {"name": "Test Ring 822", "category": "Test", "platform": "Console"}, "-873417718": {"name": "Test Ring 823", "category": "Test", "platform": "Console"}, "-873381781": {"name": "Test Ring 824", "category": "Test", "platform": "Console"}, "-873345844": {"name": "Test Ring 825", "category": "Test", "platform": "Console"}, "-873309907": {"name": "Test Ring 826", "category": "Test", "platform": "Console"}, "-873273970": {"name": "Test Ring 827", "category": "Test", "platform": "Console"}, "-873238033": {"name": "Test Ring 828", "category": "Test", "platform": "Console"}, "-873202096": {"name": "Test Ring 829", "category": "Test", "platform": "Console"}, "-872339608": {"name": "Test Ring 830", "category": "Test", "platform": "Console"}, "-872303671": {"name": "Test Ring 831", "category": "Test", "platform": "Console"}, "-872267734": {"name": "Test Ring 832", "category": "Test", "platform": "Console"}, "-872231797": {"name": "Test Ring 833", "category": "Test", "platform": "Console"}, "-872195860": {"name": "Test Ring 834", "category": "Test", "platform": "Console"}, "-872159923": {"name": "Test Ring 835", "category": "Test", "platform": "Console"}, "-872123986": {"name": "Test Ring 836", "category": "Test", "platform": "Console"}, "-872088049": {"name": "Test Ring 837", "category": "Test", "platform": "Console"}, "-872052112": {"name": "Test Ring 838", "category": "Test", "platform": "Console"}, "-872016175": {"name": "Test Ring 839", "category": "Test", "platform": "Console"}, "-871153687": {"name": "Test Ring 840", "category": "Test", "platform": "Console"}, "-871117750": {"name": "Test Ring 841", "category": "Test", "platform": "Console"}, "-871081813": {"name": "Test Ring 842", "category": "Test", "platform": "Console"}, "-871045876": {"name": "Test Ring 843", "category": "Test", "platform": "Console"}, "-871009939": {"name": "Test Ring 844", "category": "Test", "platform": "Console"}, "-870974002": {"name": "Test Ring 845", "category": "Test", "platform": "Console"}, "-870938065": {"name": "Test Ring 846", "category": "Test", "platform": "Console"}, "-870902128": {"name": "Test Ring 847", "category": "Test", "platform": "Console"}, "-870866191": {"name": "Test Ring 848", "category": "Test", "platform": "Console"}, "-870830254": {"name": "Test Ring 849", "category": "Test", "platform": "Console"}, "-869967766": {"name": "Test Ring 850", "category": "Test", "platform": "Console"}, "-869931829": {"name": "Test Ring 851", "category": "Test", "platform": "Console"}, "-869895892": {"name": "Test Ring 852", "category": "Test", "platform": "Console"}, "-869859955": {"name": "Test Ring 853", "category": "Test", "platform": "Console"}, "-869824018": {"name": "Test Ring 854", "category": "Test", "platform": "Console"}, "-869788081": {"name": "Test Ring 855", "category": "Test", "platform": "Console"}, "-869752144": {"name": "Test Ring 856", "category": "Test", "platform": "Console"}, "-869716207": {"name": "Test Ring 857", "category": "Test", "platform": "Console"}, "-869680270": {"name": "Test Ring 858", "category": "Test", "platform": "Console"}, "-869644333": {"name": "Test Ring 859", "category": "Test", "platform": "Console"}, "-868781845": {"name": "Test Ring 860", "category": "Test", "platform": "Console"}, "-868745908": {"name": "Test Ring 861", "category": "Test", "platform": "Console"}, "-868709971": {"name": "Test Ring 862", "category": "Test", "platform": "Console"}, "-868674034": {"name": "Test Ring 863", "category": "Test", "platform": "Console"}, "-868638097": {"name": "Test Ring 864", "category": "Test", "platform": "Console"}, "-868602160": {"name": "Test Ring 865", "category": "Test", "platform": "Console"}, "-868566223": {"name": "Test Ring 866", "category": "Test", "platform": "Console"}, "-868530286": {"name": "Test Ring 867", "category": "Test", "platform": "Console"}, "-868494349": {"name": "Test Ring 868", "category": "Test", "platform": "Console"}, "-868458412": {"name": "Test Ring 869", "category": "Test", "platform": "Console"}, "-867595924": {"name": "Test Ring 870", "category": "Test", "platform": "Console"}, "-867559987": {"name": "Test Ring 871", "category": "Test", "platform": "Console"}, "-867524050": {"name": "Test Ring 872", "category": "Test", "platform": "Console"}, "-867488113": {"name": "Test Ring 873", "category": "Test", "platform": "Console"}, "-867452176": {"name": "Test Ring 874", "category": "Test", "platform": "Console"}, "-867416239": {"name": "Test Ring 875", "category": "Test", "platform": "Console"}, "-867380302": {"name": "Test Ring 876", "category": "Test", "platform": "Console"}, "-867344365": {"name": "Test Ring 877", "category": "Test", "platform": "Console"}, "-867308428": {"name": "Test Ring 878", "category": "Test", "platform": "Console"}, "-867272491": {"name": "Test Ring 879", "category": "Test", "platform": "Console"}, "-866410003": {"name": "Test Ring 880", "category": "Test", "platform": "Console"}, "-866374066": {"name": "Test Ring 881", "category": "Test", "platform": "Console"}, "-866338129": {"name": "Test Ring 882", "category": "Test", "platform": "Console"}, "-866302192": {"name": "Test Ring 883", "category": "Test", "platform": "Console"}, "-866266255": {"name": "Test Ring 884", "category": "Test", "platform": "Console"}, "-866230318": {"name": "Test Ring 885", "category": "Test", "platform": "Console"}, "-866194381": {"name": "Test Ring 886", "category": "Test", "platform": "Console"}, "-866158444": {"name": "Test Ring 887", "category": "Test", "platform": "Console"}, "-866122507": {"name": "Test Ring 888", "category": "Test", "platform": "Console"}, "-866086570": {"name": "Test Ring 889", "category": "Test", "platform": "Console"}, "-865224082": {"name": "Test Ring 890", "category": "Test", "platform": "Console"}, "-865188145": {"name": "Test Ring 891", "category": "Test", "platform": "Console"}, "-865152208": {"name": "Test Ring 892", "category": "Test", "platform": "Console"}, "-865116271": {"name": "Test Ring 893", "category": "Test", "platform": "Console"}, "-865080334": {"name": "Test Ring 894", "category": "Test", "platform": "Console"}, "-865044397": {"name": "Test Ring 895", "category": "Test", "platform": "Console"}, "-865008460": {"name": "Test Ring 896", "category": "Test", "platform": "Console"}, "-864972523": {"name": "Test Ring 897", "category": "Test", "platform": "Console"}, "-864936586": {"name": "Test Ring 898", "category": "Test", "platform": "Console"}, "-864900649": {"name": "Test Ring 899", "category": "Test", "platform": "Console"}, "-836761978": {"name": "Test Ring 900", "category": "Test", "platform": "Console"}, "-836726041": {"name": "Test Ring 901", "category": "Test", "platform": "Console"}, "-836690104": {"name": "Test Ring 902", "category": "Test", "platform": "Console"}, "-836654167": {"name": "Test Ring 903", "category": "Test", "platform": "Console"}, "-836618230": {"name": "Test Ring 904", "category": "Test", "platform": "Console"}, "-836582293": {"name": "Test Ring 905", "category": "Test", "platform": "Console"}, "-836546356": {"name": "Test Ring 906", "category": "Test", "platform": "Console"}, "-836510419": {"name": "Test Ring 907", "category": "Test", "platform": "Console"}, "-836474482": {"name": "Test Ring 908", "category": "Test", "platform": "Console"}, "-836438545": {"name": "Test Ring 909", "category": "Test", "platform": "Console"}, "-835576057": {"name": "Test Ring 910", "category": "Test", "platform": "Console"}, "-835540120": {"name": "Test Ring 911", "category": "Test", "platform": "Console"}, "-835504183": {"name": "Test Ring 912", "category": "Test", "platform": "Console"}, "-835468246": {"name": "Test Ring 913", "category": "Test", "platform": "Console"}, "-835432309": {"name": "Test Ring 914", "category": "Test", "platform": "Console"}, "-835396372": {"name": "Test Ring 915", "category": "Test", "platform": "Console"}, "-835360435": {"name": "Test Ring 916", "category": "Test", "platform": "Console"}, "-835324498": {"name": "Test Ring 917", "category": "Test", "platform": "Console"}, "-835288561": {"name": "Test Ring 918", "category": "Test", "platform": "Console"}, "-835252624": {"name": "Test Ring 919", "category": "Test", "platform": "Console"}, "-834390136": {"name": "Test Ring 920", "category": "Test", "platform": "Console"}, "-834354199": {"name": "Test Ring 921", "category": "Test", "platform": "Console"}, "-834318262": {"name": "Test Ring 922", "category": "Test", "platform": "Console"}, "-834282325": {"name": "Test Ring 923", "category": "Test", "platform": "Console"}, "-834246388": {"name": "Test Ring 924", "category": "Test", "platform": "Console"}, "-834210451": {"name": "Test Ring 925", "category": "Test", "platform": "Console"}, "-834174514": {"name": "Test Ring 926", "category": "Test", "platform": "Console"}, "-834138577": {"name": "Test Ring 927", "category": "Test", "platform": "Console"}, "-834102640": {"name": "Test Ring 928", "category": "Test", "platform": "Console"}, "-834066703": {"name": "Test Ring 929", "category": "Test", "platform": "Console"}, "-833204215": {"name": "Test Ring 930", "category": "Test", "platform": "Console"}, "-833168278": {"name": "Test Ring 931", "category": "Test", "platform": "Console"}, "-833132341": {"name": "Test Ring 932", "category": "Test", "platform": "Console"}, "-833096404": {"name": "Test Ring 933", "category": "Test", "platform": "Console"}, "-833060467": {"name": "Test Ring 934", "category": "Test", "platform": "Console"}, "-833024530": {"name": "Test Ring 935", "category": "Test", "platform": "Console"}, "-832988593": {"name": "Test Ring 936", "category": "Test", "platform": "Console"}, "-832952656": {"name": "Test Ring 937", "category": "Test", "platform": "Console"}, "-832916719": {"name": "Test Ring 938", "category": "Test", "platform": "Console"}, "-832880782": {"name": "Test Ring 939", "category": "Test", "platform": "Console"}, "-832018294": {"name": "Test Ring 940", "category": "Test", "platform": "Console"}, "-831982357": {"name": "Test Ring 941", "category": "Test", "platform": "Console"}, "-831946420": {"name": "Test Ring 942", "category": "Test", "platform": "Console"}, "-831910483": {"name": "Test Ring 943", "category": "Test", "platform": "Console"}, "-831874546": {"name": "Test Ring 944", "category": "Test", "platform": "Console"}, "-831838609": {"name": "Test Ring 945", "category": "Test", "platform": "Console"}, "-831802672": {"name": "Test Ring 946", "category": "Test", "platform": "Console"}, "-831766735": {"name": "Test Ring 947", "category": "Test", "platform": "Console"}, "-831730798": {"name": "Test Ring 948", "category": "Test", "platform": "Console"}, "-831694861": {"name": "Test Ring 949", "category": "Test", "platform": "Console"}, "-830832373": {"name": "Test Ring 950", "category": "Test", "platform": "Console"}, "-830796436": {"name": "Test Ring 951", "category": "Test", "platform": "Console"}, "-830760499": {"name": "Test Ring 952", "category": "Test", "platform": "Console"}, "-830724562": {"name": "Test Ring 953", "category": "Test", "platform": "Console"}, "-830688625": {"name": "Test Ring 954", "category": "Test", "platform": "Console"}, "-830652688": {"name": "Test Ring 955", "category": "Test", "platform": "Console"}, "-830616751": {"name": "Test Ring 956", "category": "Test", "platform": "Console"}, "-830580814": {"name": "Test Ring 957", "category": "Test", "platform": "Console"}, "-830544877": {"name": "Test Ring 958", "category": "Test", "platform": "Console"}, "-830508940": {"name": "Test Ring 959", "category": "Test", "platform": "Console"}, "-829646452": {"name": "Test Ring 960", "category": "Test", "platform": "Console"}, "-829610515": {"name": "Test Ring 961", "category": "Test", "platform": "Console"}, "-829574578": {"name": "Test Ring 962", "category": "Test", "platform": "Console"}, "-829538641": {"name": "Test Ring 963", "category": "Test", "platform": "Console"}, "-829502704": {"name": "Test Ring 964", "category": "Test", "platform": "Console"}, "-829466767": {"name": "Test Ring 965", "category": "Test", "platform": "Console"}, "-829430830": {"name": "Test Ring 966", "category": "Test", "platform": "Console"}, "-829394893": {"name": "Test Ring 967", "category": "Test", "platform": "Console"}, "-829358956": {"name": "Test Ring 968", "category": "Test", "platform": "Console"}, "-829323019": {"name": "Test Ring 969", "category": "Test", "platform": "Console"}, "-828460531": {"name": "Test Ring 970", "category": "Test", "platform": "Console"}, "-828424594": {"name": "Test Ring 971", "category": "Test", "platform": "Console"}, "-828388657": {"name": "Test Ring 972", "category": "Test", "platform": "Console"}, "-828352720": {"name": "Test Ring 973", "category": "Test", "platform": "Console"}, "-828316783": {"name": "Test Ring 974", "category": "Test", "platform": "Console"}, "-828280846": {"name": "Test Ring 975", "category": "Test", "platform": "Console"}, "-828244909": {"name": "Test Ring 976", "category": "Test", "platform": "Console"}, "-828208972": {"name": "Test Ring 977", "category": "Test", "platform": "Console"}, "-828173035": {"name": "Test Ring 978", "category": "Test", "platform": "Console"}, "-828137098": {"name": "Test Ring 979", "category": "Test", "platform": "Console"}, "-827274610": {"name": "Test Ring 980", "category": "Test", "platform": "Console"}, "-827238673": {"name": "Test Ring 981", "category": "Test", "platform": "Console"}, "-827202736": {"name": "Test Ring 982", "category": "Test", "platform": "Console"}, "-827166799": {"name": "Test Ring 983", "category": "Test", "platform": "Console"}, "-827130862": {"name": "Test Ring 984", "category": "Test", "platform": "Console"}, "-827094925": {"name": "Test Ring 985", "category": "Test", "platform": "Console"}, "-827058988": {"name": "Test Ring 986", "category": "Test", "platform": "Console"}, "-827023051": {"name": "Test Ring 987", "category": "Test", "platform": "Console"}, "-826987114": {"name": "Test Ring 988", "category": "Test", "platform": "Console"}, "-826951177": {"name": "Test Ring 989", "category": "Test", "platform": "Console"}, "-826088689": {"name": "Test Ring 990", "category": "Test", "platform": "Console"}, "-826052752": {"name": "Test Ring 991", "category": "Test", "platform": "Console"}, "-826016815": {"name": "Test Ring 992", "category": "Test", "platform": "Console"}, "-825980878": {"name": "Test Ring 993", "category": "Test", "platform": "Console"}, "-825944941": {"name": "Test Ring 994", "category": "Test", "platform": "Console"}, "-825909004": {"name": "Test Ring 995", "category": "Test", "platform": "Console"}, "-825873067": {"name": "Test Ring 996", "category": "Test", "platform": "Console"}, "-825837130": {"name": "Test Ring 997", "category": "Test", "platform": "Console"}, "-825801193": {"name": "Test Ring 998", "category": "Test", "platform": "Console"}, "-825765256": {"name": "Test Ring 999", "category": "Test", "platform": "Console"}, "620034066": {"name": "01: Tribal Mask (AR 30-35)", "category": "Voodoo Masks", "platform": "Console"}, "620034067": {"name": "02: Shaman Mask (AR 36-41)", "category": "Voodoo Masks", "platform": "Console"}, "620034068": {"name": "03: Chieftain Mask (AR 60-69)", "category": "Voodoo Masks", "platform": "Console"}, "620034069": {"name": "04: Spirit Mask (AR 84-113)", "category": "Voodoo Masks", "platform": "Console"}, "620035155": {"name": "05: Woodwraith Bark (AR 114-149)", "category": "Voodoo Masks", "platform": "Console"}, "620035156": {"name": "06: Burial Mask (AR 150-185)", "category": "Voodoo Masks", "platform": "Console"}, "620035157": {"name": "07: Naga Mask (AR 186-232)", "category": "Voodoo Masks", "platform": "Console"}, "620035158": {"name": "08: Umbra Mask (AR 232-254)", "category": "Voodoo Masks", "platform": "Console"}, "620036244": {"name": "09: Screaming Mask (AR 255-322)", "category": "Voodoo Masks", "platform": "Console"}, "620036245": {"name": "10: Underworld Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036246": {"name": "11: Manitou Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036247": {"name": "12: Deva (AR 360-472)", "category": "Voodoo Masks", "platform": "Console"}, "620036248": {"name": "13: Tribal Mask (AR 472-659)", "category": "Voodoo Masks", "platform": "Console"}, "620036249": {"name": "14: Ascended Mask (AR 660-759)", "category": "Voodoo Masks", "platform": "Console"}, "-1716736265": {"name": "Art Test VoodooMask 1", "category": "Voodoo Masks", "platform": "Console"}, "-1716736264": {"name": "Art Test VoodooMask 2", "category": "Voodoo Masks", "platform": "Console"}, "-1716736263": {"name": "Art Test VoodooMask 3", "category": "Voodoo Masks", "platform": "Console"}, "-1716736262": {"name": "Art Test VoodooMask 4", "category": "Voodoo Masks", "platform": "Console"}, "-1716736261": {"name": "Art Test VoodooMask 5", "category": "Voodoo Masks", "platform": "Console"}, "-801205711": {"name": "Legendary: Carnevil", "category": "Voodoo Masks", "platform": "Console"}, "-801169774": {"name": "Legendary: Mask of Jeram", "category": "Voodoo Masks", "platform": "Console"}, "-840197356": {"name": "Legendary: Quetzalcoatl", "category": "Voodoo Masks", "platform": "Console"}, "-1956786272": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1956783828": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555852": {"name": "Legendary: Quetzalcoatl (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840161419": {"name": "Legendary: Split Tusk", "category": "Voodoo Masks", "platform": "Console"}, "-1955600351": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1955597907": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555853": {"name": "Legendary: Split Tusk (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840305167": {"name": "Legendary: The Grin Reaper", "category": "Voodoo Masks", "platform": "Console"}, "-1960344035": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1960341591": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555849": {"name": "Legendary: The Grin Reaper (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840341104": {"name": "Legendary: Tiklandian Visage", "category": "Voodoo Masks", "platform": "Console"}, "-1961529956": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1961527512": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555848": {"name": "Legendary: Tiklandian Visage (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840089545": {"name": "Legendary: Visage of Giyua", "category": "Voodoo Masks", "platform": "Console"}, "-1953228509": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1953226065": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555855": {"name": "Legendary: Visage of Giyua (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555854": {"name": "Set: Zunimassa's Attunement (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840125482": {"name": "Set: Zunimassa's Vision", "category": "Voodoo Masks", "platform": "Console"}, "-1954414430": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1954411986": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "88665049": {"name": "00: Apprentice's Wand (DPS 3.0)", "category": "Wands", "platform": "Console"}, "88665050": {"name": "01: Lesser Wand (DPS 9.8-11.2)", "category": "Wands", "platform": "Console"}, "88665051": {"name": "02: Oak Wand (DPS 11.2-13.3)", "category": "Wands", "platform": "Console"}, "88665052": {"name": "03: Wand (DPS 14.7-16.8)", "category": "Wands", "platform": "Console"}, "88665053": {"name": "04: Steel Wand (DPS 17.5-19.6)", "category": "Wands", "platform": "Console"}, "88665054": {"name": "05: Mentor Wand (DPS 21.7-23.8)", "category": "Wands", "platform": "Console"}, "88665055": {"name": "06: Enchanter Wand (DPS 25.2-27.3)", "category": "Wands", "platform": "Console"}, "88665056": {"name": "07: Grim Wand (DPS 29.4-31.5)", "category": "Wands", "platform": "Console"}, "88666139": {"name": "08: Petrified Wand (DPS 41.3-43.4)", "category": "Wands", "platform": "Console"}, "88666140": {"name": "09: Duelist Wand (DPS 47.6-49.7)", "category": "Wands", "platform": "Console"}, "88666141": {"name": "10: Jade Wand (DPS 55.3-57.4)", "category": "Wands", "platform": "Console"}, "88666142": {"name": "11: Battle Wand (DPS 65.1-67.2)", "category": "Wands", "platform": "Console"}, "88666143": {"name": "12: Divination Wand (DPS 75.6-77.7)", "category": "Wands", "platform": "Console"}, "88666144": {"name": "13: Sorcery Wand (DPS 89.6-93.8)", "category": "Wands", "platform": "Console"}, "88666145": {"name": "14: Silversteel Wand (DPS 105.0-109.2)", "category": "Wands", "platform": "Console"}, "88667228": {"name": "15: Greater Wand (DPS 115.5-119.7)", "category": "Wands", "platform": "Console"}, "88667229": {"name": "16: Guardian (DPS 127.4-131.6)", "category": "Wands", "platform": "Console"}, "88667230": {"name": "17: Magus Wand (DPS 139.3-145.6)", "category": "Wands", "platform": "Console"}, "88667231": {"name": "18: Spellbinder (DPS 153.3-159.6)", "category": "Wands", "platform": "Console"}, "88667232": {"name": "19: Archmage Wand (DPS 177.1-183.4)", "category": "Wands", "platform": "Console"}, "88667233": {"name": "20: Strike Wand (DPS 203.0-211.4)", "category": "Wands", "platform": "Console"}, "88667234": {"name": "21: Desolator Wand (DPS 235.2-243.6)", "category": "Wands", "platform": "Console"}, "88668317": {"name": "22: Demon's Head Wand (DPS 315.0-321.3)", "category": "Wands", "platform": "Console"}, "88668318": {"name": "23: Diabolic Wand (DPS 385.0-391.3)", "category": "Wands", "platform": "Console"}, "2004783359": {"name": "Art Test Wand 1", "category": "Wands", "platform": "Console"}, "2004783360": {"name": "Art Test Wand 2", "category": "Wands", "platform": "Console"}, "2004783361": {"name": "Art Test Wand 3", "category": "Wands", "platform": "Console"}, "2004783362": {"name": "Art Test Wand 4", "category": "Wands", "platform": "Console"}, "2004783363": {"name": "Art Test Wand 5", "category": "Wands", "platform": "Console"}, "456527018": {"name": "Crafted: Elderwood Wand", "category": "Wands", "platform": "Console"}, "-1415147493": {"name": "Legendary: Aether Walker (Patch 2.1.0)", "category": "Wands", "platform": "Console"}, "1859914464": {"name": "Legendary: Atrophy", "category": "Wands", "platform": "Console"}, "1859806653": {"name": "Legendary: Blackhand Key", "category": "Wands", "platform": "Console"}, "1244000105": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "1244002549": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "161873429": {"name": "Legendary: Blackhand Key (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860776952": {"name": "Legendary: Fragment of Destiny", "category": "Wands", "platform": "Console"}, "1276019972": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "1276022416": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "161873456": {"name": "Legendary: Fragment of Destiny (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859662905": {"name": "Legendary: Gesture of Orpheus", "category": "Wands", "platform": "Console"}, "1239256421": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "1239258865": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "161873425": {"name": "Legendary: Gesture of Orpheus (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1247557868": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "1247560312": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "161873432": {"name": "Legendary: Ruinstoke (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898798298": {"name": "Legendary: Serpent's Sparker", "category": "Wands", "platform": "Console"}, "1860884763": {"name": "Legendary: Slorak's Madness", "category": "Wands", "platform": "Console"}, "1279577735": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "1279580179": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "161873459": {"name": "Legendary: Slorak's Madness (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859698842": {"name": "Legendary: Starfire", "category": "Wands", "platform": "Console"}, "1240442342": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "1240444786": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "161873426": {"name": "Legendary: Starfire (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898762361": {"name": "Legendary: Wand of Woh", "category": "Wands", "platform": "Console"}, "-1415147492": {"name": "P1 Wand norm Legendary 02", "category": "Wands", "platform": "Console"}, "161873458": {"name": "Set: Chantodo's Sacred Protector (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860848826": {"name": "Set: Chantodo's Will", "category": "Wands", "platform": "Console"}, "1278391814": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1278394258": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1861064448": {"name": "Set: Hallowed Baton", "category": "Wands", "platform": "Console"}, "161873464": {"name": "Set: Hallowed Rod (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1285507340": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1285509784": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1771839282": {"name": "legendary: Gesture Of Orpheus (Patch 2.2.0)", "category": "Wands", "platform": "Console"}, "1755621630": {"name": "01: Wanderer Hat (AR 30-35)", "category": "Wizard Hats", "platform": "Console"}, "1755621631": {"name": "02: Journey Mask (AR 36-41)", "category": "Wizard Hats", "platform": "Console"}, "1755621632": {"name": "03: Scholarly Fez (AR 60-69)", "category": "Wizard Hats", "platform": "Console"}, "1755621633": {"name": "04: Charlatan Cap (AR 84-113)", "category": "Wizard Hats", "platform": "Console"}, "1755622719": {"name": "05: Conjurer Shade (AR 114-149)", "category": "Wizard Hats", "platform": "Console"}, "1755622720": {"name": "06: Mystic Shade (AR 150-185)", "category": "Wizard Hats", "platform": "Console"}, "1755622721": {"name": "07: Mentor Cap (AR 186-232)", "category": "Wizard Hats", "platform": "Console"}, "1755622722": {"name": "08: Traveler Hat (AR 232-254)", "category": "Wizard Hats", "platform": "Console"}, "1755623808": {"name": "09: Sage Hat (AR 255-284)", "category": "Wizard Hats", "platform": "Console"}, "1755623809": {"name": "10: Sinister Mask (AR 285-322)", "category": "Wizard Hats", "platform": "Console"}, "1755623810": {"name": "11: Archmage Headpiece (AR 322-359)", "category": "Wizard Hats", "platform": "Console"}, "1755623811": {"name": "12: Elder Hat (AR 360-472)", "category": "Wizard Hats", "platform": "Console"}, "1755623812": {"name": "13: Vizier Hat (AR 472-659)", "category": "Wizard Hats", "platform": "Console"}, "1755623813": {"name": "14: Ascended Headpiece (AR 660-759)", "category": "Wizard Hats", "platform": "Console"}, "376117315": {"name": "Art Test WizardHat 1", "category": "Wizard Hats", "platform": "Console"}, "376117316": {"name": "Art Test WizardHat 2", "category": "Wizard Hats", "platform": "Console"}, "376117317": {"name": "Art Test WizardHat 3", "category": "Wizard Hats", "platform": "Console"}, "376117318": {"name": "Art Test WizardHat 4", "category": "Wizard Hats", "platform": "Console"}, "376117319": {"name": "Art Test WizardHat 5", "category": "Wizard Hats", "platform": "Console"}, "414491869": {"name": "Legendary: Archmage's Vicalyke", "category": "Wizard Hats", "platform": "Console"}, "375356476": {"name": "Legendary: Dark Mage's Shade", "category": "Wizard Hats", "platform": "Console"}, "-498215480": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-498213036": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827188": {"name": "Legendary: Dark Mage's Shade (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414599680": {"name": "Legendary: Mask of Lies", "category": "Wizard Hats", "platform": "Console"}, "375464287": {"name": "Legendary: Storm Crow", "category": "Wizard Hats", "platform": "Console"}, "-494657717": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-494655273": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827191": {"name": "Legendary: Storm Crow (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414563743": {"name": "Legendary: The Magistrate", "category": "Wizard Hats", "platform": "Console"}, "375428350": {"name": "Legendary: The Swami", "category": "Wizard Hats", "platform": "Console"}, "-495843638": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-495841194": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827190": {"name": "Legendary: The Swami (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-936099818": {"name": "Legendary: The Swami (Patch 2.1.0)", "category": "Wizard Hats", "platform": "Console"}, "414527806": {"name": "Legendary: Velvet Camaral", "category": "Wizard Hats", "platform": "Console"}} \ No newline at end of file +{"0": {"name": "None", "category": "None", "platform": "Console"}, "1682228617": {"name": "01: Amulet", "category": "Amulets", "platform": "Console"}, "1682228618": {"name": "02: Amulet", "category": "Amulets", "platform": "Console"}, "1682228619": {"name": "03: Amulet", "category": "Amulets", "platform": "Console"}, "1682228620": {"name": "04: Amulet", "category": "Amulets", "platform": "Console"}, "1682228621": {"name": "05: Amulet", "category": "Amulets", "platform": "Console"}, "1682228622": {"name": "06: Amulet", "category": "Amulets", "platform": "Console"}, "1682228623": {"name": "07: Amulet", "category": "Amulets", "platform": "Console"}, "1682228624": {"name": "08: Amulet", "category": "Amulets", "platform": "Console"}, "1682228625": {"name": "09: Amulet", "category": "Amulets", "platform": "Console"}, "1682228649": {"name": "10: Amulet", "category": "Amulets", "platform": "Console"}, "1682228650": {"name": "11: Amulet", "category": "Amulets", "platform": "Console"}, "1682228651": {"name": "12: Amulet", "category": "Amulets", "platform": "Console"}, "1682228652": {"name": "13: Amulet", "category": "Amulets", "platform": "Console"}, "1682228653": {"name": "14: Amulet", "category": "Amulets", "platform": "Console"}, "1682228654": {"name": "15: Amulet", "category": "Amulets", "platform": "Console"}, "1682228655": {"name": "16: Amulet", "category": "Amulets", "platform": "Console"}, "1682228656": {"name": "17: Amulet", "category": "Amulets", "platform": "Console"}, "-1335710051": {"name": "Art Test Amulet 1", "category": "Amulets", "platform": "Console"}, "-1335710050": {"name": "Art Test Amulet 2", "category": "Amulets", "platform": "Console"}, "-1335710049": {"name": "Art Test Amulet 3", "category": "Amulets", "platform": "Console"}, "-1335710048": {"name": "Art Test Amulet 4", "category": "Amulets", "platform": "Console"}, "-1335710047": {"name": "Art Test Amulet 5", "category": "Amulets", "platform": "Console"}, "1566332280": {"name": "Legendary: Ancestors' Grace", "category": "Amulets", "platform": "Console"}, "1566368217": {"name": "Legendary: Countess Julia's Cameo", "category": "Amulets", "platform": "Console"}, "1566511965": {"name": "Legendary: Dovu Energy Trap", "category": "Amulets", "platform": "Console"}, "1200923753": {"name": "Legendary: Drake's Amulet (PS3 Promo)", "category": "Amulets", "platform": "Console"}, "1528454682": {"name": "Legendary: Eye of Etlich", "category": "Amulets", "platform": "Console"}, "-1100680346": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "-1100677902": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "412126098": {"name": "Legendary: Eye of Etlich (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566440091": {"name": "Legendary: Golden Gorget of Leoric", "category": "Amulets", "platform": "Console"}, "1566583839": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "737941201": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "1566296343": {"name": "Legendary: Haunt of Vaxo", "category": "Amulets", "platform": "Console"}, "761548935": {"name": "Legendary: Hellfire Amulet (Patch 1.2.0)", "category": "Amulets", "platform": "Console"}, "1528418745": {"name": "Legendary: Holy Beacon", "category": "Amulets", "platform": "Console"}, "-1101866267": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "-1101863823": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "412126097": {"name": "Legendary: Holy Beacon (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196887": {"name": "Legendary: Kymbo's Gold", "category": "Amulets", "platform": "Console"}, "-1142187581": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "-1142185137": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "412126063": {"name": "Legendary: Kymbo's Gold (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196623": {"name": "Legendary: Kymbo's Gold (Patch 2.1.0)", "category": "Amulets", "platform": "Console"}, "1528490619": {"name": "Legendary: Mara's Kaleidoscope", "category": "Amulets", "platform": "Console"}, "-1099494425": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "-1099491981": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "412126099": {"name": "Legendary: Mara's Kaleidoscope (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527232824": {"name": "Legendary: Moonlight Ward", "category": "Amulets", "platform": "Console"}, "-1141001660": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "-1140999216": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "412126064": {"name": "Legendary: Moonlight Ward (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527304698": {"name": "Legendary: Ouroboros", "category": "Amulets", "platform": "Console"}, "-1138629818": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "-1138627374": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "412126066": {"name": "Legendary: Ouroboros (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566476028": {"name": "Legendary: Overwhelming Desire", "category": "Amulets", "platform": "Console"}, "1566547902": {"name": "Legendary: Rakoff's Glass of Life", "category": "Amulets", "platform": "Console"}, "1527448446": {"name": "Legendary: Rondal's Locket", "category": "Amulets", "platform": "Console"}, "-1133886134": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1133883690": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126070": {"name": "Legendary: Rondal's Locket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528310934": {"name": "Legendary: Squirt's Necklace", "category": "Amulets", "platform": "Console"}, "-1105424030": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "-1105421586": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "412126094": {"name": "Legendary: Squirt's Necklace (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528382808": {"name": "Legendary: Talisman of Aranoch", "category": "Amulets", "platform": "Console"}, "-1103052188": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "-1103049744": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "412126096": {"name": "Legendary: Talisman of Aranoch (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566404154": {"name": "Legendary: The Ess of Johan", "category": "Amulets", "platform": "Console"}, "1527160950": {"name": "Legendary: The Flavor of Time", "category": "Amulets", "platform": "Console"}, "-1143373502": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "-1143371058": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "412126062": {"name": "Legendary: The Flavor of Time (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528346871": {"name": "Legendary: The Murlocket", "category": "Amulets", "platform": "Console"}, "-1104238109": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1104235665": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126095": {"name": "Legendary: The Murlocket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527340635": {"name": "Legendary: The Star of Azkaranth", "category": "Amulets", "platform": "Console"}, "-1137443897": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "-1137441453": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "412126067": {"name": "Legendary: The Star of Azkaranth (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527268761": {"name": "Legendary: Xephirian Amulet", "category": "Amulets", "platform": "Console"}, "-1139815739": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "-1139813295": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "412126065": {"name": "Legendary: Xephirian Amulet (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "714520304": {"name": "PvP: Art of War 3v3", "category": "Amulets", "platform": "Console"}, "1685772266": {"name": "PvP: Art of War All", "category": "Amulets", "platform": "Console"}, "1685772538": {"name": "PvP: Art of War Attack", "category": "Amulets", "platform": "Console"}, "1685775296": {"name": "PvP: Art of War Defense", "category": "Amulets", "platform": "Console"}, "-203544613": {"name": "PvP: Art of War Precision", "category": "Amulets", "platform": "Console"}, "1685795044": {"name": "PvP: Art of War Vitality", "category": "Amulets", "platform": "Console"}, "-203302615": {"name": "PvP: Art of War Willpower", "category": "Amulets", "platform": "Console"}, "1803178445": {"name": "PvP: Born for War All", "category": "Amulets", "platform": "Console"}, "1803178717": {"name": "PvP: Born for War Attack", "category": "Amulets", "platform": "Console"}, "1803181475": {"name": "PvP: Born for War Defense", "category": "Amulets", "platform": "Console"}, "-624108002": {"name": "PvP: Born for War Precision", "category": "Amulets", "platform": "Console"}, "1803201223": {"name": "PvP: Born for War Vitality", "category": "Amulets", "platform": "Console"}, "1528526556": {"name": "Set: Blackthorne's Duncraig Cross", "category": "Amulets", "platform": "Console"}, "-1098308504": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "-1098306060": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "412126100": {"name": "Set: Blackthorne's Medal (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "412126069": {"name": "Set: Spirit of Adventure (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "-1544505070": {"name": "Set: Sunwuko's Shines", "category": "Amulets", "platform": "Console"}, "412126068": {"name": "Set: Tal Rasha's Adjudication (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527376572": {"name": "Set: Tal Rasha's Allegiance", "category": "Amulets", "platform": "Console"}, "-1136257976": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "-1136255532": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "1527412509": {"name": "Set: The Traveler's Pledge", "category": "Amulets", "platform": "Console"}, "-1135072055": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-1135069611": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-795161790": {"name": "legendary: Moonlight Ward (Patch 2.2.0)", "category": "Amulets", "platform": "Console"}, "1661412389": {"name": "00: Weathered Hand Axe (DPS 3.0)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412390": {"name": "01: Hand Axe (DPS 3.3-4.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412391": {"name": "02: Broad Axe (DPS 7.2-9.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412392": {"name": "03: Double Axe (DPS 12.4-14.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412393": {"name": "04: Heavy Axe (DPS 17.6-19.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412394": {"name": "05: Battle Axe (DPS 21.5-23.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412395": {"name": "06: Marauder Axe (DPS 26.7-28.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412396": {"name": "07: Soldier Axe (DPS 31.2-33.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413479": {"name": "08: Hatchet (DPS 36.4-38.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413480": {"name": "09: Ono (DPS 46.2-48.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413481": {"name": "10: Bullova (DPS 57.2-59.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413482": {"name": "11: Adze (DPS 69.6-73.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413483": {"name": "12: Chopper (DPS 86.5-90.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413484": {"name": "13: Toporok (DPS 101.4-105.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413485": {"name": "14: Masakari (DPS 118.3-122.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414568": {"name": "15: Tomahawk (DPS 129.4-135.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414569": {"name": "16: Crescent Axe (DPS 144.3-150.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414570": {"name": "17: Arreat Axe (DPS 160.6-166.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414571": {"name": "18: Balestarius (DPS 177.5-185.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414572": {"name": "19: Skartaran Axe (DPS 206.7-214.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414573": {"name": "20: Galraki (DPS 238.6-246.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414574": {"name": "21: Arch Axe (DPS 275.6-285.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415657": {"name": "22: Executioner's Axe (DPS 371.8-379.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415658": {"name": "23: Dire Axe (DPS 461.5-469.3)", "category": "Axes, One-Handed", "platform": "Console"}, "-657929333": {"name": "Art Test Axe One-Handed 1", "category": "Axes, One-Handed", "platform": "Console"}, "-657929332": {"name": "Art Test Axe One-Handed 2", "category": "Axes, One-Handed", "platform": "Console"}, "-657929331": {"name": "Art Test Axe One-Handed 3", "category": "Axes, One-Handed", "platform": "Console"}, "-657929330": {"name": "Art Test Axe One-Handed 4", "category": "Axes, One-Handed", "platform": "Console"}, "-657929329": {"name": "Art Test Axe One-Handed 5", "category": "Axes, One-Handed", "platform": "Console"}, "824126149": {"name": "Legendary: Aidan's Revenge", "category": "Axes, One-Handed", "platform": "Console"}, "824162086": {"name": "Legendary: Fenris Tooth", "category": "Axes, One-Handed", "platform": "Console"}, "784990756": {"name": "Legendary: Flesh Tearer", "category": "Axes, One-Handed", "platform": "Console"}, "134813872": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "134816316": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046948": {"name": "Legendary: Flesh Tearer (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785062630": {"name": "Legendary: Genzaniku", "category": "Axes, One-Handed", "platform": "Console"}, "137185714": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "137188158": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046946": {"name": "Legendary: Genzaniku (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "824198023": {"name": "Legendary: Hack", "category": "Axes, One-Handed", "platform": "Console"}, "785134504": {"name": "Legendary: Sky Splitter", "category": "Axes, One-Handed", "platform": "Console"}, "139557556": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "139560000": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046944": {"name": "Legendary: Sky Splitter (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785206378": {"name": "Legendary: The Burning Axe of Sankis", "category": "Axes, One-Handed", "platform": "Console"}, "141929398": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "141931842": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046942": {"name": "Legendary: The Burning Axe of Sankis (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785170441": {"name": "Legendary: The Butcher's Sickle", "category": "Axes, One-Handed", "platform": "Console"}, "140743477": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "140745921": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046943": {"name": "Legendary: The Butcher's Sickle (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138371635": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138374079": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046945": {"name": "Legendary: The Wedge (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785098567": {"name": "Legendary: Utar's Roar", "category": "Axes, One-Handed", "platform": "Console"}, "786248551": {"name": "Set: Hallowed Breach", "category": "Axes, One-Handed", "platform": "Console"}, "-219046913": {"name": "Set: Hallowed Divide (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176321107": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176323551": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785134241": {"name": "legendary: Sky Spliiter (Patch 2.2.0)", "category": "Axes, One-Handed", "platform": "Console"}, "1700547783": {"name": "01: Lumber Axe (DPS 10.0-11.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547784": {"name": "02: War Axe (DPS 16.0-17.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547785": {"name": "03: Tabarzin (DPS 22.5-24.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547786": {"name": "04: Military Axe (DPS 31.5-33.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547787": {"name": "05: Great Axe (DPS 42.5-44.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548872": {"name": "06: Timber Axe (DPS 56.5-59.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548873": {"name": "07: Francisca (DPS 73.5-76.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548874": {"name": "08: Fang Axe (DPS 94.0-98.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548875": {"name": "09: Parashu (DPS 119.0-125.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548876": {"name": "10: Labrys (DPS 170.0-177.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549961": {"name": "11: Fell Axe (DPS 230.5-241.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549962": {"name": "12: Valaska (DPS 313.0-325.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549963": {"name": "13: Ripper Axe (DPS 400.0-412.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549964": {"name": "14: Sagaris (DPS 474.5-486.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549965": {"name": "15: Decapitator (DPS 560.0-572.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551050": {"name": "16: Dread Axe (DPS 698.0-711.2)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551051": {"name": "17: Flesh Render (DPS 948.2-961.4)", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893396": {"name": "Art Test Axe Two-Handed 1", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893395": {"name": "Art Test Axe Two-Handed 2", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893394": {"name": "Art Test Axe Two-Handed 3", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893393": {"name": "Art Test Axe Two-Handed 4", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893392": {"name": "Art Test Axe Two-Handed 5", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516456824": {"name": "Legendary: Burst of Wrath", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555664091": {"name": "Legendary: Butcher's Carver", "category": "Axes, Two-Handed", "platform": "Console"}, "202615249": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "202617693": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911555": {"name": "Legendary: Butcher's Carver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554514107": {"name": "Legendary: Cinder Switch", "category": "Axes, Two-Handed", "platform": "Console"}, "240564721": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "240567165": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911523": {"name": "Legendary: Fire Brand (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554478170": {"name": "Legendary: Messerschmidt's Reaver", "category": "Axes, Two-Handed", "platform": "Console"}, "241750642": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "241753086": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911522": {"name": "Legendary: Messerschmidt's Reaver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516420887": {"name": "Legendary: Saint of Slaughter", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555376595": {"name": "Legendary: Skorn", "category": "Axes, Two-Handed", "platform": "Console"}, "212102617": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "212105061": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911547": {"name": "Legendary: Skorn (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516492761": {"name": "Legendary: Sungjae's Fury", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555592217": {"name": "Legendary: The Executioner", "category": "Axes, Two-Handed", "platform": "Console"}, "204987091": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "204989535": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911553": {"name": "Legendary: The Executioner (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516528698": {"name": "Legendary: The Marauder", "category": "Axes, Two-Handed", "platform": "Console"}, "120887006": {"name": "PvP: Heroic Reaper", "category": "Axes, Two-Handed", "platform": "Console"}, "120887005": {"name": "PvP: Mighty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "120887004": {"name": "PvP: Trusty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "-733831369": {"name": "01: Sash (AR 6-7)", "category": "Belts", "platform": "Console"}, "-733831368": {"name": "02: Hide Belt (AR 24-28)", "category": "Belts", "platform": "Console"}, "-733831367": {"name": "03: Leather Belt (AR 14-16)", "category": "Belts", "platform": "Console"}, "-733831366": {"name": "04: Cord (AR 44-53)", "category": "Belts", "platform": "Console"}, "-733831365": {"name": "05: Binding Rope (AR 54-67)", "category": "Belts", "platform": "Console"}, "-733831364": {"name": "06: Chain Belt (AR 34-43)", "category": "Belts", "platform": "Console"}, "-733830280": {"name": "07: Silk Sash (AR 68-87)", "category": "Belts", "platform": "Console"}, "-733830279": {"name": "08: Waistwrap (AR 88-107)", "category": "Belts", "platform": "Console"}, "-733830278": {"name": "09: Strand (AR 108-127)", "category": "Belts", "platform": "Console"}, "-733830277": {"name": "10: Cupola (AR 128-149)", "category": "Belts", "platform": "Console"}, "-733830276": {"name": "11: Cinch (AR 150-164)", "category": "Belts", "platform": "Console"}, "-733829191": {"name": "12: Grasp (AR 165-179)", "category": "Belts", "platform": "Console"}, "-733829190": {"name": "13: Sheath (AR 180-189)", "category": "Belts", "platform": "Console"}, "-733829189": {"name": "14: Cincture (AR 190-214)", "category": "Belts", "platform": "Console"}, "-733829188": {"name": "15: Girdle (AR 215-239)", "category": "Belts", "platform": "Console"}, "-733829187": {"name": "16: Heaven Strand (AR 240-264)", "category": "Belts", "platform": "Console"}, "-733829186": {"name": "17: High Scabbard (AR 265-314)", "category": "Belts", "platform": "Console"}, "-733829185": {"name": "18: War Belt (AR 315-439)", "category": "Belts", "platform": "Console"}, "-733829184": {"name": "19: Archon Sash (AR 440-506)", "category": "Belts", "platform": "Console"}, "1187629340": {"name": "Art Test Belt 1", "category": "Belts", "platform": "Console"}, "1187629341": {"name": "Art Test Belt 2", "category": "Belts", "platform": "Console"}, "1187629342": {"name": "Art Test Belt 3", "category": "Belts", "platform": "Console"}, "1187629343": {"name": "Art Test Belt 4", "category": "Belts", "platform": "Console"}, "1187629344": {"name": "Art Test Belt 5", "category": "Belts", "platform": "Console"}, "949342869": {"name": "Belt Of The Trove (Patch 2.1.2)", "category": "Belts", "platform": "Console"}, "1770820311": {"name": "Legendary: Angel Hair Braid", "category": "Belts", "platform": "Console"}, "-1692549181": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-1692546737": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-660622993": {"name": "Legendary: Angel Hair Braid (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770820047": {"name": "Legendary: Angel Hair Braid (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1809991641": {"name": "Legendary: Cord of the Sherma", "category": "Belts", "platform": "Console"}, "1770856248": {"name": "Legendary: Fleeting Strap", "category": "Belts", "platform": "Console"}, "1771898421": {"name": "Legendary: Goldwrap", "category": "Belts", "platform": "Console"}, "-1656971551": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1656969107": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622963": {"name": "Legendary: Goldwrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810027578": {"name": "Legendary: Harrington Waistguard", "category": "Belts", "platform": "Console"}, "1770892185": {"name": "Legendary: Hellcat Waistguard", "category": "Belts", "platform": "Console"}, "-1690177339": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-1690174895": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-660622991": {"name": "Legendary: Hellcat Waistguard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810099452": {"name": "Legendary: Hwoj Wrap", "category": "Belts", "platform": "Console"}, "1809955704": {"name": "Legendary: Insatiable Belt", "category": "Belts", "platform": "Console"}, "1810063515": {"name": "Legendary: Jang's Envelopment", "category": "Belts", "platform": "Console"}, "-1691363260": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1691360816": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622992": {"name": "Legendary: Quick Draw Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809883830": {"name": "Legendary: Razor Strop", "category": "Belts", "platform": "Console"}, "1770748437": {"name": "Legendary: Saffron Wrap", "category": "Belts", "platform": "Console"}, "-1694921023": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1694918579": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622995": {"name": "Legendary: Saffron Wrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809919767": {"name": "Legendary: Sash of Knives", "category": "Belts", "platform": "Console"}, "1809919503": {"name": "Legendary: Sash of Knives (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1810135389": {"name": "Legendary: Sebor's Nightmare", "category": "Belts", "platform": "Console"}, "1770999996": {"name": "Legendary: String of Ears", "category": "Belts", "platform": "Console"}, "-1686619576": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-1686617132": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-660622988": {"name": "Legendary: String of Ears (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1771035933": {"name": "Legendary: The Witching Hour", "category": "Belts", "platform": "Console"}, "-1685433655": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-1685431211": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-660622987": {"name": "Legendary: The Witching Hour (Old-Legacy)", "category": "Belts", "platform": "Console"}, "924103246": {"name": "Legendary: Thundergod's Vigor", "category": "Belts", "platform": "Console"}, "1770784374": {"name": "Legendary: Vigilante Belt", "category": "Belts", "platform": "Console"}, "-1693735102": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1693732658": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622994": {"name": "Legendary: Vigilante Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1772078106": {"name": "Set: Blackthorne's Notched Belt", "category": "Belts", "platform": "Console"}, "-1651041946": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1651039502": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622958": {"name": "Set: Blackthorne's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-660622961": {"name": "Set: Captain Crimson's Brace (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1654599709": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "-1654597265": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "1771970295": {"name": "Set: Captain Crimson's Silk Girdle", "category": "Belts", "platform": "Console"}, "-660622959": {"name": "Set: Demon's Binding (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1652227867": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "-1652225423": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "1772042169": {"name": "Set: Demon's Restraint", "category": "Belts", "platform": "Console"}, "1772006232": {"name": "Set: Guardian's Case", "category": "Belts", "platform": "Console"}, "-660622960": {"name": "Set: Guardian's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1653413788": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-1653411344": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-660622989": {"name": "Set: Inna's Blessing (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770964059": {"name": "Set: Inna's Favor", "category": "Belts", "platform": "Console"}, "-1687805497": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-1687803053": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-885483983": {"name": "Set: Krelm's Buff Belt", "category": "Belts", "platform": "Console"}, "1770928122": {"name": "Set: Tal Rasha's Brace", "category": "Belts", "platform": "Console"}, "-1688991418": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-1688988974": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-660622990": {"name": "Set: Tal Rasha's Finespun Cloth (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1069972162": {"name": "legendary: Belessed of Haull (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972159": {"name": "legendary: Belt of Transcendence (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972158": {"name": "legendary: Crashing Rain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972160": {"name": "legendary: Haunting Girdle (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972161": {"name": "legendary: Omnislash (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972163": {"name": "legendary: Omryn's Chain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809919504": {"name": "legendary: Sash of Knives (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1810135126": {"name": "legendary: Sebor's Nightmare (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809991378": {"name": "legendary: Sherma of Corrosion (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "2140880151": {"name": "01: Shoes (AR 7-8)", "category": "Boots", "platform": "Console"}, "2140880152": {"name": "02: Boots (AR 16-18)", "category": "Boots", "platform": "Console"}, "2140880153": {"name": "03: Heavy Boots (AR 30-35)", "category": "Boots", "platform": "Console"}, "2140880154": {"name": "04: Chain Boots (AR 44-57)", "category": "Boots", "platform": "Console"}, "2140880155": {"name": "05: Sabatons (AR 58-66)", "category": "Boots", "platform": "Console"}, "2140880156": {"name": "06: Greaves (AR 67-82)", "category": "Boots", "platform": "Console"}, "2140881240": {"name": "07: Silk Shoes (AR 54-106)", "category": "Boots", "platform": "Console"}, "2140881241": {"name": "08: Brogans (AR 107-129)", "category": "Boots", "platform": "Console"}, "2140881242": {"name": "09: Treads (AR 130-152)", "category": "Boots", "platform": "Console"}, "2140881243": {"name": "10: Heavy Sabatons (AR 154-174)", "category": "Boots", "platform": "Console"}, "2140881244": {"name": "11: Battle Greaves (AR 175-192)", "category": "Boots", "platform": "Console"}, "2140882329": {"name": "12: Balor Treads (AR 192-209)", "category": "Boots", "platform": "Console"}, "2140882330": {"name": "13: Astral Greaves (AR 210-221)", "category": "Boots", "platform": "Console"}, "2140882331": {"name": "14: Warlord Boots (AR 221-249)", "category": "Boots", "platform": "Console"}, "2140882332": {"name": "15: Doom Treads (AR 250-278)", "category": "Boots", "platform": "Console"}, "2140882333": {"name": "16: Sovereign Greaves (AR 280-308)", "category": "Boots", "platform": "Console"}, "2140882334": {"name": "17: Archon Greaves (AR 309-366)", "category": "Boots", "platform": "Console"}, "2140882335": {"name": "18: Rakkisgard Greaves (AR 367-512)", "category": "Boots", "platform": "Console"}, "2140882336": {"name": "19: Ascended Greaves (AR 513-590)", "category": "Boots", "platform": "Console"}, "931997596": {"name": "Art Test Boots 1", "category": "Boots", "platform": "Console"}, "931997597": {"name": "Art Test Boots 2", "category": "Boots", "platform": "Console"}, "931997598": {"name": "Art Test Boots 3", "category": "Boots", "platform": "Console"}, "931997599": {"name": "Art Test Boots 4", "category": "Boots", "platform": "Console"}, "931997600": {"name": "Art Test Boots 5", "category": "Boots", "platform": "Console"}, "691149644": {"name": "Art_Test_Boots_10 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997601": {"name": "Art_Test_Boots_6 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997602": {"name": "Art_Test_Boots_7 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997603": {"name": "Art_Test_Boots_8 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997604": {"name": "Art_Test_Boots_9 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940245561": {"name": "Legendary: Board Walkers", "category": "Boots", "platform": "Console"}, "1940101813": {"name": "Legendary: Boj Anglers", "category": "Boots", "platform": "Console"}, "-401226911": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "-401224467": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "261789197": {"name": "Legendary: Boj Anglers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979273143": {"name": "Legendary: Boots of Disregard", "category": "Boots", "platform": "Console"}, "1290781938": {"name": "Legendary: Conqueror's Sabatons (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1940317435": {"name": "Legendary: Fire Walkers", "category": "Boots", "platform": "Console"}, "-394111385": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "-394108941": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "261789203": {"name": "Legendary: Fire Walkers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-639326280": {"name": "Legendary: Footfalls of the Forbidden Lands", "category": "Boots", "platform": "Console"}, "1940353372": {"name": "Legendary: Ice Climbers", "category": "Boots", "platform": "Console"}, "-392925464": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "-392923020": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "261789204": {"name": "Legendary: Ice Climbers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979309080": {"name": "Legendary: Illusory Boots", "category": "Boots", "platform": "Console"}, "1979345017": {"name": "Legendary: Irontoe Mudsputters", "category": "Boots", "platform": "Console"}, "-396483227": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "-396480783": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "261789201": {"name": "Legendary: Lost Boys (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1940389309": {"name": "Legendary: Lut Socks", "category": "Boots", "platform": "Console"}, "-391739543": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "-391737099": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "261789205": {"name": "Legendary: Lut Socks (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941251797": {"name": "Legendary: The Crudest Boots", "category": "Boots", "platform": "Console"}, "-363277439": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "-363274995": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "261789229": {"name": "Legendary: The Crudest Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-2143372979": {"name": "Legendary: The Crudest Boots (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1941395545": {"name": "Set: Asheara's Finders", "category": "Boots", "platform": "Console"}, "261789233": {"name": "Set: Asheara's Lock (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-358533755": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "-358531311": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "261789238": {"name": "Set: Blackthorne's Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941575230": {"name": "Set: Blackthorne's Spurs", "category": "Boots", "platform": "Console"}, "-352604150": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-352601706": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-357347834": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "-357345390": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "261789234": {"name": "Set: Cain's Slippers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941431482": {"name": "Set: Cain's Travelers", "category": "Boots", "platform": "Console"}, "261789236": {"name": "Set: Captain Crimson's Deck Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941503356": {"name": "Set: Captain Crimson's Waders", "category": "Boots", "platform": "Console"}, "-354975992": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-354973548": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-801833428": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801653481": {"name": "Set: Eight-Demon Boots", "category": "Boots", "platform": "Console"}, "-801725355": {"name": "Set: Firebird's Tarsi", "category": "Boots", "platform": "Console"}, "-801833429": {"name": "Set: Hell Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800539434": {"name": "Set: Helltooth Greaves", "category": "Boots", "platform": "Console"}, "261789231": {"name": "Set: Immortal King's Pillar (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941323671": {"name": "Set: Immortal King's Stride", "category": "Boots", "platform": "Console"}, "-360905597": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "-360903153": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "1097296767": {"name": "Set: Inna's Sandals (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801617544": {"name": "Set: Jade Harvester's Swiftness", "category": "Boots", "platform": "Console"}, "-801689418": {"name": "Set: Marauder's Treads", "category": "Boots", "platform": "Console"}, "-801905302": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1941287734": {"name": "Set: Natalya's Bloody Footprints", "category": "Boots", "platform": "Console"}, "-362091518": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "-362089074": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "261789230": {"name": "Set: Natalya's Soul (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1097296766": {"name": "Set: Nilfur's Boast (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801761292": {"name": "Set: Raekor's Striders", "category": "Boots", "platform": "Console"}, "-801905304": {"name": "Set: Roland's Stride (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "-801905303": {"name": "Set: Sabaton of the Wastes (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800755056": {"name": "Set: Sabatons of Akkhan", "category": "Boots", "platform": "Console"}, "-353790071": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "-353787627": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "1941539293": {"name": "Set: Sage's Passage", "category": "Boots", "platform": "Console"}, "261789237": {"name": "Set: Sage's Seekers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-1957807619": {"name": "Set: Striders of Destiny (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800611308": {"name": "Set: The Shadow's Heels", "category": "Boots", "platform": "Console"}, "-800647245": {"name": "Set: Vyr's Swaggering Stance", "category": "Boots", "platform": "Console"}, "-801869365": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "261789232": {"name": "Set: Zunimassa's Journey (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941359608": {"name": "Set: Zunimassa's Trail", "category": "Boots", "platform": "Console"}, "-359719676": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "-359717232": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "1979344754": {"name": "legendary: Boots_104_p2 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940317172": {"name": "legendary: Fire Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800575371": {"name": "legendary: Seismic Treads", "category": "Boots", "platform": "Console"}, "-700134034": {"name": "legendary: Seismic Treads (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-2091504072": {"name": "01: Short Bow (DPS 6.3-7.7)", "category": "Bows", "platform": "Console"}, "-2091504071": {"name": "02: Warden Bow (DPS 14.7-16.8)", "category": "Bows", "platform": "Console"}, "-2091504070": {"name": "03: Long Bow (DPS 20.3-22.4)", "category": "Bows", "platform": "Console"}, "-2091504069": {"name": "04: Recurve Bow (DPS 27.7-30.8)", "category": "Bows", "platform": "Console"}, "-2091504068": {"name": "05: Hunting Bow (DPS 34.3-36.4)", "category": "Bows", "platform": "Console"}, "-2091504067": {"name": "06: Battle Bow (DPS 41.3-43.4)", "category": "Bows", "platform": "Console"}, "-2091502983": {"name": "07: Siege Bow (DPS 44.1-46.2)", "category": "Bows", "platform": "Console"}, "-2091502982": {"name": "08: Maruki (DPS 55.3-57.4)", "category": "Bows", "platform": "Console"}, "-2091502981": {"name": "09: Yumi (DPS 64.4-66.5)", "category": "Bows", "platform": "Console"}, "-2091502980": {"name": "10: Composite Bow (DPS 749.9-77.0)", "category": "Bows", "platform": "Console"}, "-2091502979": {"name": "11: Daikyu (DPS 91.0-93.1)", "category": "Bows", "platform": "Console"}, "-2091502978": {"name": "12: Hankyu (DPS 107.1-109.2)", "category": "Bows", "platform": "Console"}, "-2091501894": {"name": "13: Higoyumi (DPS 140.7-142.8)", "category": "Bows", "platform": "Console"}, "-2091501893": {"name": "14: Ranger Bow (DPS 172.2-174.3)", "category": "Bows", "platform": "Console"}, "-2091501892": {"name": "15: Longshot Bow (DPS 207.2-211.4)", "category": "Bows", "platform": "Console"}, "-2091501891": {"name": "16: Sniper Bow (DPS 275.1-279.3)", "category": "Bows", "platform": "Console"}, "-2091501890": {"name": "17: Phantom Bow (DPS 322.0-326.2)", "category": "Bows", "platform": "Console"}, "-2091501889": {"name": "18: Revenant Bow (DPS 376.6-380.8)", "category": "Bows", "platform": "Console"}, "-2091500805": {"name": "19: Twinbow (DPS 513.1-517.3)", "category": "Bows", "platform": "Console"}, "-2091500804": {"name": "20: Doubleshot (DPS 670.6-674.8)", "category": "Bows", "platform": "Console"}, "687111997": {"name": "Art Test Bow 1", "category": "Bows", "platform": "Console"}, "687111998": {"name": "Art Test Bow 2", "category": "Bows", "platform": "Console"}, "687111999": {"name": "Art Test Bow 3", "category": "Bows", "platform": "Console"}, "687112000": {"name": "Art Test Bow 4", "category": "Bows", "platform": "Console"}, "687112001": {"name": "Art Test Bow 5", "category": "Bows", "platform": "Console"}, "1999703162": {"name": "Legendary: Amazonian Arch", "category": "Bows", "platform": "Console"}, "1142135055": {"name": "Legendary: Bow of the Lost Warlord (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1961789627": {"name": "Legendary: Cluckeye", "category": "Bows", "platform": "Console"}, "314470951": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "314473395": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "513724883": {"name": "Legendary: Cluckeye (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459958": {"name": "Legendary: Etrayu", "category": "Bows", "platform": "Console"}, "270591874": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "270594318": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "513724846": {"name": "Legendary: Etrayu (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459694": {"name": "Legendary: Etrayu (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1999595351": {"name": "Legendary: Kridershot", "category": "Bows", "platform": "Console"}, "1999667225": {"name": "Legendary: Leonine Bow of Hashir", "category": "Bows", "platform": "Console"}, "277707400": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "277709844": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "513724852": {"name": "Legendary: Longshot (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1999631288": {"name": "Legendary: Odyssey's End", "category": "Bows", "platform": "Console"}, "1961609942": {"name": "Legendary: Sydyru Crust", "category": "Bows", "platform": "Console"}, "1960711517": {"name": "Legendary: The Raven's Wing", "category": "Bows", "platform": "Console"}, "278893321": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "278895765": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "513724853": {"name": "Legendary: The Raven's Wing (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960675580": {"name": "Legendary: Unbound Bolt", "category": "Bows", "platform": "Console"}, "1960603706": {"name": "Legendary: Uskang", "category": "Bows", "platform": "Console"}, "275335558": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "275338002": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "513724850": {"name": "Legendary: Uskang (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960603442": {"name": "Legendary: Uskang (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "308541346": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "308543790": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "513724878": {"name": "Legendary: Venomhusk (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960747454": {"name": "Legendary: Windforce", "category": "Bows", "platform": "Console"}, "280079242": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "280081686": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "513724854": {"name": "Legendary: Windforce (Old-Legacy)", "category": "Bows", "platform": "Console"}, "-875944878": {"name": "01: Bracers (AR 8-9)", "category": "Bracers", "platform": "Console"}, "-875944877": {"name": "02: Leather Cuffs (AR 16-19)", "category": "Bracers", "platform": "Console"}, "-875944876": {"name": "03: Bindings (AR 25-32)", "category": "Bracers", "platform": "Console"}, "-875944875": {"name": "04: Vambraces (AR 33-40)", "category": "Bracers", "platform": "Console"}, "-875944874": {"name": "05: Bracelets (AR 41-48)", "category": "Bracers", "platform": "Console"}, "-875943789": {"name": "067: Wristwraps (AR 63-75)", "category": "Bracers", "platform": "Console"}, "-875944873": {"name": "06: Mail Bands (AR 50-62)", "category": "Bracers", "platform": "Console"}, "-875943788": {"name": "08: Wristbands (AR 76-88)", "category": "Bracers", "platform": "Console"}, "-875943787": {"name": "09: Stabilizers (AR 90-102)", "category": "Bracers", "platform": "Console"}, "-875943786": {"name": "10: Wristguards (AR 103-124)", "category": "Bracers", "platform": "Console"}, "-875943785": {"name": "11: Wristplates (AR 125-137)", "category": "Bracers", "platform": "Console"}, "-875942700": {"name": "12: Armwraps (AR 137-149)", "category": "Bracers", "platform": "Console"}, "-875942699": {"name": "13: Armbands (AR 150-157)", "category": "Bracers", "platform": "Console"}, "-875942698": {"name": "14: Warbands (AR 158-178)", "category": "Bracers", "platform": "Console"}, "-875942697": {"name": "15: Armguards (AR 179-199)", "category": "Bracers", "platform": "Console"}, "-875942696": {"name": "16: Armplates (AR 200-220)", "category": "Bracers", "platform": "Console"}, "-875942695": {"name": "17: Razorspikes (AR 220-261)", "category": "Bracers", "platform": "Console"}, "-875942694": {"name": "18: Rakkisgard Bracelets (AR 262-365)", "category": "Bracers", "platform": "Console"}, "-875942693": {"name": "19: Ascended Bracers (AR 366-421)", "category": "Bracers", "platform": "Console"}, "-297950812": {"name": "Art Test Bracer 1", "category": "Bracers", "platform": "Console"}, "-297950811": {"name": "Art Test Bracer 2", "category": "Bracers", "platform": "Console"}, "-297950810": {"name": "Art Test Bracer 3", "category": "Bracers", "platform": "Console"}, "-297950809": {"name": "Art Test Bracer 4", "category": "Bracers", "platform": "Console"}, "-297950808": {"name": "Art Test Bracer 5", "category": "Bracers", "platform": "Console"}, "1861699995": {"name": "Grundo Gear (Patch 2.1.2)", "category": "Bracers", "platform": "Console"}, "962282719": {"name": "Legendary: Ancient Parthan Defenders", "category": "Bracers", "platform": "Console"}, "962462404": {"name": "Legendary: Custerian Wristguards", "category": "Bracers", "platform": "Console"}, "923291074": {"name": "Legendary: Gungdo Gear", "category": "Bracers", "platform": "Console"}, "403757070": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "403759514": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "955538490": {"name": "Legendary: Gungdo Gear (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923111389": {"name": "Legendary: Kethryes' Splint", "category": "Bracers", "platform": "Console"}, "923255137": {"name": "Legendary: Lacuni Prowlers", "category": "Bracers", "platform": "Console"}, "402571149": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "402573593": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538489": {"name": "Legendary: Lacuni Prowlers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962498341": {"name": "Legendary: Lucky Bowman's Armscales", "category": "Bracers", "platform": "Console"}, "962426467": {"name": "Legendary: Nemesis Bracers", "category": "Bracers", "platform": "Console"}, "923147326": {"name": "Legendary: Promise of Glory", "category": "Bracers", "platform": "Console"}, "399013386": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "399015830": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "955538486": {"name": "Legendary: Promise of Glory (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962318656": {"name": "Legendary: Reaper's Wraps", "category": "Bracers", "platform": "Console"}, "962390530": {"name": "Legendary: Sanguinary Vambraces", "category": "Bracers", "platform": "Console"}, "923183263": {"name": "Legendary: Slave Bonds", "category": "Bracers", "platform": "Console"}, "400199307": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "400201751": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "955538487": {"name": "Legendary: Slave Bonds (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923219200": {"name": "Legendary: Steady Strikers", "category": "Bracers", "platform": "Console"}, "401385228": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "401387672": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538488": {"name": "Legendary: Steady Strikers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923327011": {"name": "Legendary: Strongarm Bracers", "category": "Bracers", "platform": "Console"}, "404942991": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "404945435": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538491": {"name": "Legendary: Strongarm Bracers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962354593": {"name": "Legendary: Trag'Oul Coils", "category": "Bracers", "platform": "Console"}, "962246782": {"name": "Legendary: Warzechian Armguards", "category": "Bracers", "platform": "Console"}, "397827465": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "397829909": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "955538485": {"name": "Legendary: Wondrous Deflectors (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "955538493": {"name": "Set: Aughild's Demands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923398885": {"name": "Set: Aughild's Search", "category": "Bracers", "platform": "Console"}, "407314833": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "407317277": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "924297310": {"name": "Set: Demon's Animus", "category": "Bracers", "platform": "Console"}, "955538518": {"name": "Set: Demon's Manacles (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "436962858": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "436965302": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "924261373": {"name": "Set: Guardian's Aversion", "category": "Bracers", "platform": "Console"}, "955538517": {"name": "Set: Guardian's Bands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "435776937": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "435779381": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "1784952569": {"name": "Set: Krelm's Buff Bracers", "category": "Bracers", "platform": "Console"}, "1786138490": {"name": "Set: Shackles of the Invoker", "category": "Bracers", "platform": "Console"}, "1861701111": {"name": "legendary: Drakon's Lesson (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861699992": {"name": "legendary: Mortick's Brace (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861701087": {"name": "legendary: Spirit Guards (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "-635269584": {"name": "00: Simple Knife (DPS 3.0)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269583": {"name": "01: Stone Knife (DPS 11.2-12.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269582": {"name": "02: Kris Blade (DPS 14.7-16.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269581": {"name": "03: Jagged Edge (DPS 21.0-23.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269580": {"name": "04: Flint Knife (DPS 30.8-32.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268494": {"name": "05: Sacrifice Blade (DPS 39.2-41.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268493": {"name": "06: Flayer (DPS 48.3-50.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268492": {"name": "07: Bone Saw (DPS 62.3-64.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268491": {"name": "08: Beast Tusk (DPS 84.0-86.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267405": {"name": "09: Scalping Razor (DPS 112.7-114.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267404": {"name": "10: Obsidian Edge (DPS 137.2-139.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267403": {"name": "11: Skin Cutter (DPS 165.2-169.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267402": {"name": "12: Exquisite Knife (DPS 190.4-194.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267401": {"name": "13: Flesh Ripper (DPS 219.1-223.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267400": {"name": "14: Veil Piercer (DPS 251.3-257.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266316": {"name": "15: Odsidian Skiver (DPS 336.7-340.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266315": {"name": "16: Tecpat1 (DPS 410.2-414.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-97045282": {"name": "Art Test CeremonialDagger 1", "category": "Ceremonial Knives", "platform": "Console"}, "-97045281": {"name": "Art Test CeremonialDagger 2", "category": "Ceremonial Knives", "platform": "Console"}, "-97045280": {"name": "Art Test CeremonialDagger 3", "category": "Ceremonial Knives", "platform": "Console"}, "-97045279": {"name": "Art Test CeremonialDagger 4", "category": "Ceremonial Knives", "platform": "Console"}, "-97045278": {"name": "Art Test CeremonialDagger 5", "category": "Ceremonial Knives", "platform": "Console"}, "1784443031": {"name": "Legendary: Anessazi Edge", "category": "Ceremonial Knives", "platform": "Console"}, "-1242999421": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1242996977": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684207": {"name": "Legendary: Anessazi Edge (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784514905": {"name": "Legendary: Deadly Rebirth", "category": "Ceremonial Knives", "platform": "Console"}, "1784694590": {"name": "Legendary: Last Breath", "category": "Ceremonial Knives", "platform": "Console"}, "-1234697974": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1234695530": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684214": {"name": "Legendary: Last Breath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784622716": {"name": "Legendary: Living Umbral Oath", "category": "Ceremonial Knives", "platform": "Console"}, "-1240627579": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1240625135": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684209": {"name": "Legendary: Moon Slayer (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1823614361": {"name": "Legendary: Rhen'ho Flayer", "category": "Ceremonial Knives", "platform": "Console"}, "916911834": {"name": "Legendary: Sacred Harvester (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "595814643": {"name": "Legendary: Sacrificer", "category": "Ceremonial Knives", "platform": "Console"}, "1823578424": {"name": "Legendary: Starmetal Kukri", "category": "Ceremonial Knives", "platform": "Console"}, "916911835": {"name": "Legendary: The Dagger of Darts (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "1784478968": {"name": "Legendary: The Gidbinn", "category": "Ceremonial Knives", "platform": "Console"}, "-1241813500": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1241811056": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684208": {"name": "Legendary: The Gidbinn (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784550842": {"name": "Legendary: The Spider Queen's Grasp", "category": "Ceremonial Knives", "platform": "Console"}, "-1237069816": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1237067372": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684212": {"name": "Legendary: Umbral Oath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239441658": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239439214": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684210": {"name": "Legendary: Ziggurat Tooth (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684240": {"name": "Set: Hallowed Sacrifice (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203864028": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203861584": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1785628952": {"name": "Set: Hallowed Sufferance", "category": "Ceremonial Knives", "platform": "Console"}, "1784730527": {"name": "Set: Manajuma's Carving Knife", "category": "Ceremonial Knives", "platform": "Console"}, "-1233512053": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1233509609": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684215": {"name": "Set: Manajuma's Ritual Cutter (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "258855259": {"name": "Set: Cage of the Hellborn (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258855260": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783385": {"name": "Set: Cuirass of the Wastes (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819322": {"name": "Set: Harness of Truth (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783386": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "259969569": {"name": "Set: Sunwuko's Soul (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819323": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "1612257704": {"name": "01: Cloth Tunic (AR 3)", "category": "Chest Armor", "platform": "Console"}, "1612257705": {"name": "02: Leather Doublet (AR 18-21)", "category": "Chest Armor", "platform": "Console"}, "1612257706": {"name": "03: Brigandine Coat (AR 33-38)", "category": "Chest Armor", "platform": "Console"}, "1612257707": {"name": "04: Chain Mail (AR 51-68)", "category": "Chest Armor", "platform": "Console"}, "1612257708": {"name": "05: Splint Cuirass (AR 69-86)", "category": "Chest Armor", "platform": "Console"}, "1612257709": {"name": "06: Plate Mail (AR 87-107)", "category": "Chest Armor", "platform": "Console"}, "1612258793": {"name": "07: Stygian Harness (AR 108-137)", "category": "Chest Armor", "platform": "Console"}, "1612258794": {"name": "08: Etched Jacket (AR 138-167)", "category": "Chest Armor", "platform": "Console"}, "1612258795": {"name": "09: Jazeraint Mail (AR 168-197)", "category": "Chest Armor", "platform": "Console"}, "1612258796": {"name": "10: Battle Armor (AR 198-224)", "category": "Chest Armor", "platform": "Console"}, "1612258797": {"name": "11: Boneweave Hauberk (AR 225-247)", "category": "Chest Armor", "platform": "Console"}, "1612259882": {"name": "12: Balor Armor (AR 247-269)", "category": "Chest Armor", "platform": "Console"}, "1612259883": {"name": "13: Astral Mail (AR 270-284)", "category": "Chest Armor", "platform": "Console"}, "1612259884": {"name": "14: Warlord Plate (AR 285-322)", "category": "Chest Armor", "platform": "Console"}, "1612259885": {"name": "15: Doom Armor (AR 322-359)", "category": "Chest Armor", "platform": "Console"}, "1612259886": {"name": "16: Sovereign Mail (AR 360-397)", "category": "Chest Armor", "platform": "Console"}, "1612259887": {"name": "17: Archon Armor (AR 397-471)", "category": "Chest Armor", "platform": "Console"}, "1612259888": {"name": "18: Rakkisgard Armor (AR 472-659)", "category": "Chest Armor", "platform": "Console"}, "1612259889": {"name": "19: Ascended Armor (AR 660-759)", "category": "Chest Armor", "platform": "Console"}, "1937623756": {"name": "Art Test Chest 1", "category": "Chest Armor", "platform": "Console"}, "1937623757": {"name": "Art Test Chest 2", "category": "Chest Armor", "platform": "Console"}, "1937623758": {"name": "Art Test Chest 3", "category": "Chest Armor", "platform": "Console"}, "1937623759": {"name": "Art Test Chest 4", "category": "Chest Armor", "platform": "Console"}, "1937623760": {"name": "Art Test Chest 5", "category": "Chest Armor", "platform": "Console"}, "1316774087": {"name": "Legendary: Aquila Cuirass", "category": "Chest Armor", "platform": "Console"}, "503794611": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "503797055": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016991": {"name": "Legendary: Aquila Cuirass (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354723559": {"name": "Legendary: Armor of the Kind Regent", "category": "Chest Armor", "platform": "Console"}, "1316702213": {"name": "Legendary: Chaingmail", "category": "Chest Armor", "platform": "Console"}, "501422769": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "501425213": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016989": {"name": "Legendary: Chaingmail (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1315731914": {"name": "Legendary: Cindercoat", "category": "Chest Armor", "platform": "Console"}, "469402902": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "469405346": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016962": {"name": "Legendary: Cindercoat (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "883162595": {"name": "Legendary: Conqueror's Cuirass (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "1315552229": {"name": "Legendary: Goldskin", "category": "Chest Armor", "platform": "Console"}, "463473297": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "463475741": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016957": {"name": "Legendary: Goldskin (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316989709": {"name": "Legendary: Heart of Iron", "category": "Chest Armor", "platform": "Console"}, "510910137": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "510912581": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016997": {"name": "Legendary: Heart of Iron (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1821181577": {"name": "Legendary: Heart of the Titans", "category": "Chest Armor", "platform": "Console"}, "1317025646": {"name": "Legendary: Mantle of the Rydraelm", "category": "Chest Armor", "platform": "Console"}, "512096058": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "512098502": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016998": {"name": "Legendary: Robes of the Rydraelm (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354687622": {"name": "Legendary: Shi Mizu's Haori", "category": "Chest Armor", "platform": "Console"}, "1315588166": {"name": "Legendary: Tyrael's Might", "category": "Chest Armor", "platform": "Console"}, "464659218": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "464661662": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016958": {"name": "Legendary: Tyrael's Might (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "547673688": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "547676132": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318103756": {"name": "Set: Aughild's Rule", "category": "Chest Armor", "platform": "Console"}, "172017028": {"name": "Set: Aughild's Vestments (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1262779559": {"name": "Set: Blackthorne's Jacket (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "-115330289": {"name": "Set: Blackthorne's Surcoat", "category": "Chest Armor", "platform": "Console"}, "488990459": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "488992903": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172017027": {"name": "Set: Born's Carapace (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318067819": {"name": "Set: Born's Frozen Soul", "category": "Chest Armor", "platform": "Console"}, "546487767": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "546490211": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259933632": {"name": "Set: Breastplate of Akkhan", "category": "Chest Armor", "platform": "Console"}, "172017029": {"name": "Set: Demon's Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "548859609": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "548862053": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318139693": {"name": "Set: Demon's Marrow", "category": "Chest Armor", "platform": "Console"}, "258963333": {"name": "Set: Firebird's Breast", "category": "Chest Armor", "platform": "Console"}, "259035207": {"name": "Set: Heart of the Crashing Wave", "category": "Chest Armor", "platform": "Console"}, "260149254": {"name": "Set: Helltooth Tunic", "category": "Chest Armor", "platform": "Console"}, "1316810024": {"name": "Set: Immortal King's Eternal Reign", "category": "Chest Armor", "platform": "Console"}, "504980532": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "504982976": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016992": {"name": "Set: Immortal King's Soul Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016994": {"name": "Set: Inna's Refuge (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316881898": {"name": "Set: Inna's Vast Expanse", "category": "Chest Armor", "platform": "Console"}, "507352374": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "507354818": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259071144": {"name": "Set: Jade Harvester's Peace", "category": "Chest Armor", "platform": "Console"}, "258999270": {"name": "Set: Marauder's Carapace", "category": "Chest Armor", "platform": "Console"}, "258927396": {"name": "Set: Raekor's Heart", "category": "Chest Armor", "platform": "Console"}, "258783384": {"name": "Set: Roland's Bearing (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "172016993": {"name": "Set: Tal Rasha's Guardianship (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316845961": {"name": "Set: Tal Rasha's Relentless Pursuit", "category": "Chest Armor", "platform": "Console"}, "506166453": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "506168897": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "260077380": {"name": "Set: The Shadow's Bane", "category": "Chest Armor", "platform": "Console"}, "260041443": {"name": "Set: Vyr's Astonishing Aura", "category": "Chest Armor", "platform": "Console"}, "1316917835": {"name": "Set: Zunimassa's Marrow", "category": "Chest Armor", "platform": "Console"}, "508538295": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "508540739": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016995": {"name": "Set: Zunimassa's Vessel (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1937623761": {"name": "Art_Test_Chest_6 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623762": {"name": "Art_Test_Chest_7 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623763": {"name": "Art_Test_Chest_8 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623764": {"name": "Art_Test_Chest_9 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "40855418": {"name": "01: Hunter Cloak (AR 30-35)", "category": "Cloaks", "platform": "Console"}, "40855419": {"name": "02: Shroud (AR 36-41)", "category": "Cloaks", "platform": "Console"}, "40855420": {"name": "03: Cape (AR 60-69)", "category": "Cloaks", "platform": "Console"}, "40855421": {"name": "04: Tabard (AR 84-113)", "category": "Cloaks", "platform": "Console"}, "40856507": {"name": "05: Wrap (AR 114-149)", "category": "Cloaks", "platform": "Console"}, "40856508": {"name": "06: Lurker Shroud (AR 150-185)", "category": "Cloaks", "platform": "Console"}, "40856509": {"name": "07: Talma (AR 186-232)", "category": "Cloaks", "platform": "Console"}, "40856510": {"name": "08: Cardinal (AR 232-254)", "category": "Cloaks", "platform": "Console"}, "40857596": {"name": "09: Veteran Cloak (AR 255-284)", "category": "Cloaks", "platform": "Console"}, "40857597": {"name": "10: Death Shroud (AR 385-322)", "category": "Cloaks", "platform": "Console"}, "40857598": {"name": "11: Stalker Cape (AR 322-359)", "category": "Cloaks", "platform": "Console"}, "40857599": {"name": "12: Dread Cloak (AR 360-472)", "category": "Cloaks", "platform": "Console"}, "40857600": {"name": "13: Rakkisgard Cloak (AR 472-659)", "category": "Cloaks", "platform": "Console"}, "40857601": {"name": "14: Ascended Cloak (AR 660-759)", "category": "Cloaks", "platform": "Console"}, "2105367871": {"name": "Art Test Cloak 1", "category": "Cloaks", "platform": "Console"}, "2105367872": {"name": "Art Test Cloak 2", "category": "Cloaks", "platform": "Console"}, "2105367873": {"name": "Art Test Cloak 3", "category": "Cloaks", "platform": "Console"}, "2105367874": {"name": "Art Test Cloak 4", "category": "Cloaks", "platform": "Console"}, "2105367875": {"name": "Art Test Cloak 5", "category": "Cloaks", "platform": "Console"}, "221665681": {"name": "Legendary Cloak 002 p1", "category": "Cloaks", "platform": "Console"}, "221773756": {"name": "Legendary: Beckon Sail", "category": "Cloaks", "platform": "Console"}, "-1271477944": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1271475500": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235532": {"name": "Legendary: Beckon Sail (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260765401": {"name": "Legendary: Blackfeather", "category": "Cloaks", "platform": "Console"}, "221630008": {"name": "Legendary: Cape of the Dark Night", "category": "Cloaks", "platform": "Console"}, "-1276221628": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1276219184": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235536": {"name": "Legendary: Cape of the Dark Night (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260801338": {"name": "Legendary: Cloak of Deception", "category": "Cloaks", "platform": "Console"}, "221665945": {"name": "Legendary: The Cloak of the Garwulf", "category": "Cloaks", "platform": "Console"}, "-1275035707": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1275033263": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235535": {"name": "Legendary: The Inquisitor (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "221809693": {"name": "Set: Natalya's Embrace", "category": "Cloaks", "platform": "Console"}, "-1270292023": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1270289579": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235531": {"name": "Set: Natalya's Shadow (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "1401594517": {"name": "A Gift", "category": "Consumables", "platform": "Console"}, "-1691237125": {"name": "Blood Shard", "category": "Consumables", "platform": "Console"}, "-2018707791": {"name": "Bottomless Potion Of Fear (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-2018707790": {"name": "Bottomless Potion of Amplification (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707793": {"name": "Bottomless Potion of Kulle Aid", "category": "Consumables", "platform": "Console"}, "-2018707794": {"name": "Bottomless Potion of Mutilation", "category": "Consumables", "platform": "Console"}, "-2018707796": {"name": "Bottomless Potion of Regeneration", "category": "Consumables", "platform": "Console"}, "-2018707792": {"name": "Bottomless Potion of Rejuvenation", "category": "Consumables", "platform": "Console"}, "510979313": {"name": "Bottomless Potion of Rejuvenation (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707797": {"name": "Bottomless Potion of the Diamond", "category": "Consumables", "platform": "Console"}, "-2018707795": {"name": "Bottomless Potion of the Leech", "category": "Consumables", "platform": "Console"}, "-2018707798": {"name": "Bottomless Potion of the Tower", "category": "Consumables", "platform": "Console"}, "727989467": {"name": "Bottomless Regular Health Potion (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618072": {"name": "Consumable_Potion_Bloodshard_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "736462346": {"name": "Consumable_Potion_Bloodshard_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618138": {"name": "Consumable_Potion_Bloodshard_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618270": {"name": "Consumable_Potion_Bloodshard_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764252": {"name": "Consumable_Potion_Gold_Find_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-418681010": {"name": "Consumable_Potion_Gold_Find_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764318": {"name": "Consumable_Potion_Gold_Find_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764450": {"name": "Consumable_Potion_Gold_Find_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167362": {"name": "Consumable_Potion_XP_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1032379504": {"name": "Consumable_Potion_XP_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167296": {"name": "Consumable_Potion_XP_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167164": {"name": "Consumable_Potion_XP_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2142362846": {"name": "Health Potion", "category": "Consumables", "platform": "Console"}, "-650776931": {"name": "Infernal Machine", "category": "Consumables", "platform": "Console"}, "1054965529": {"name": "Infernal Machine of Bones", "category": "Consumables", "platform": "Console"}, "1458185494": {"name": "Infernal Machine of Evil", "category": "Consumables", "platform": "Console"}, "-1506243402": {"name": "Infernal Machine of Gluttony", "category": "Consumables", "platform": "Console"}, "-1672611564": {"name": "Infernal Machine of War", "category": "Consumables", "platform": "Console"}, "-1055802742": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1927699898": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-1990624170": {"name": "PowerGlobe", "category": "Consumables", "platform": "Console"}, "-1407876474": {"name": "PowerGlobe NoFlippy", "category": "Consumables", "platform": "Console"}, "1604670149": {"name": "PowerGlobe v2 x1", "category": "Consumables", "platform": "Console"}, "1554449877": {"name": "PowerGlobe v2 x1 NoFlippy", "category": "Consumables", "platform": "Console"}, "-767886865": {"name": "PvP_HealingDude", "category": "Consumables", "platform": "Console"}, "1844495708": {"name": "Ramaladni's Gift", "category": "Consumables", "platform": "Console"}, "-2108322324": {"name": "Ramaladni's Gift (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-1629755675": {"name": "Rare Gift (RoS)", "category": "Consumables", "platform": "Console"}, "750709043": {"name": "ShrineGlobe Blessed", "category": "Consumables", "platform": "Console"}, "-783958152": {"name": "ShrineGlobe Enlightened", "category": "Consumables", "platform": "Console"}, "1754475188": {"name": "ShrineGlobe Fortune", "category": "Consumables", "platform": "Console"}, "1126841672": {"name": "ShrineGlobe Frenzied", "category": "Consumables", "platform": "Console"}, "-1436918535": {"name": "Steak10", "category": "Consumables", "platform": "Console"}, "-1436918530": {"name": "Steak15", "category": "Consumables", "platform": "Console"}, "-1436918502": {"name": "Steak20", "category": "Consumables", "platform": "Console"}, "-1436918497": {"name": "Steak25", "category": "Consumables", "platform": "Console"}, "-1436918469": {"name": "Steak30", "category": "Consumables", "platform": "Console"}, "-1436918464": {"name": "Steak35", "category": "Consumables", "platform": "Console"}, "-1436918436": {"name": "Steak40", "category": "Consumables", "platform": "Console"}, "346908589": {"name": "Steak5", "category": "Consumables", "platform": "Console"}, "450956006": {"name": "p1 tiered rifts Orb", "category": "Consumables", "platform": "Console"}, "237118774": {"name": "Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "703352254": {"name": "Art_Test_Pet_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352255": {"name": "Art_Test_Pet_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352256": {"name": "Art_Test_Pet_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352257": {"name": "Art_Test_Pet_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352258": {"name": "Art_Test_Pet_5 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352259": {"name": "Art_Test_Pet_6 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555709": {"name": "Art_Test_Wings_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555710": {"name": "Art_Test_Wings_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555711": {"name": "Art_Test_Wings_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555712": {"name": "Art_Test_Wings_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1736870778": {"name": "Blade Wings", "category": "Cosmetics", "platform": "Console"}, "2015178386": {"name": "Blade Wings (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508877": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508876": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "988742338": {"name": "Cosmetic_Pet_FallenHound_Skeletal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508875": {"name": "Cosmetic_Pet_teddyBear_04 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1464439640": {"name": "Cosmetic_Wings_Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834901": {"name": "Cosmetic_Wings_bat_02 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834902": {"name": "Cosmetic_Wings_bat_03 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1424453175": {"name": "Crimson Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "1464422100": {"name": "Demon Soaring (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208405024": {"name": "Eldritch Embrace (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1081301157": {"name": "Eternal Flame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1030142027": {"name": "Eternal Light (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1815774861": {"name": "Fingers of Terror (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380235": {"name": "Frame: Angelic (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264991": {"name": "Frame: Base Frame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380233": {"name": "Frame: Bone (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380234": {"name": "Frame: Deathshead (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380230": {"name": "Frame: Molton (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264990": {"name": "Frame: Paragon 1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764818": {"name": "Frame: Paragon 10 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114304450": {"name": "Frame: Paragon 100 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764851": {"name": "Frame: Paragon 20 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114305539": {"name": "Frame: Paragon 200 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764884": {"name": "Frame: Paragon 30 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764917": {"name": "Frame: Paragon 40 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114307717": {"name": "Frame: Paragon 400 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764950": {"name": "Frame: Paragon 50 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114308806": {"name": "Frame: Paragon 500 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764983": {"name": "Frame: Paragon 60 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114309895": {"name": "Frame: Paragon 600 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765016": {"name": "Frame: Paragon 70 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114310984": {"name": "Frame: Paragon 700 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765049": {"name": "Frame: Paragon 80 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114312073": {"name": "Frame: Paragon 800 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765082": {"name": "Frame: Paragon 90 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114306628": {"name": "Frame: Paraogn 300 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380199": {"name": "Frame: Season 3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380228": {"name": "Frame: Staind Glass Azure (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380202": {"name": "Frame: Staind Glass Orange (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380201": {"name": "Frame: Staind Glass Purple (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380227": {"name": "Frame: Staind Glass Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380229": {"name": "Frame: Staind Glass Teal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380203": {"name": "Frame: Staind Glass Yellow (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380231": {"name": "Frame: Steadfast (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380198": {"name": "Frame: Storm (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380232": {"name": "Frame: Thorns (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380200": {"name": "Frame: Whimseyshire (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "211305012": {"name": "Harbringer of Destruction (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "262300867": {"name": "Heaven't Might (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-922089455": {"name": "Knights of Westmarch (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1412314502": {"name": "Liber Canis Mortui", "category": "Cosmetics", "platform": "Console"}, "-1527508878": {"name": "Mr Bear (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208454467": {"name": "Pieces of Hatred (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "517654224": {"name": "Probe (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "291388174": {"name": "Spike (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1647814559": {"name": "Ten Pounder (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1454306710": {"name": "The Light of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-2072242152": {"name": "The Pillars of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-937743655": {"name": "Warlords Of Draenor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-762694428": {"name": "Warsong Pennant", "category": "Cosmetics", "platform": "Console"}, "-1364948604": {"name": "Wings of Valor", "category": "Cosmetics", "platform": "Console"}, "1464422747": {"name": "Wings of Valor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "727152075": {"name": "Adventurer's Journal", "category": "Crafting Components", "platform": "Console"}, "-784029520": {"name": "Angelic Shard", "category": "Crafting Components", "platform": "Console"}, "-1585802162": {"name": "Arcane Dust", "category": "Crafting Components", "platform": "Console"}, "2048505008": {"name": "Behistun Rune", "category": "Crafting Components", "platform": "Console"}, "-1993550104": {"name": "Black Mushroom", "category": "Crafting Components", "platform": "Console"}, "1864276820": {"name": "Bloody Pincer", "category": "Crafting Components", "platform": "Console"}, "-875022940": {"name": "Born's Key", "category": "Crafting Components", "platform": "Console"}, "-229384987": {"name": "Captured Nightmare", "category": "Crafting Components", "platform": "Console"}, "1016443205": {"name": "Captured Soul", "category": "Crafting Components", "platform": "Console"}, "903645542": {"name": "Cartographer's Toolkit", "category": "Crafting Components", "platform": "Console"}, "2064572165": {"name": "Common Debris", "category": "Crafting Components", "platform": "Console"}, "-821947350": {"name": "Cultist Blood", "category": "Crafting Components", "platform": "Console"}, "2087837753": {"name": "Death's Breath", "category": "Crafting Components", "platform": "Console"}, "2000469169": {"name": "Defiled Doll", "category": "Crafting Components", "platform": "Console"}, "-1761931437": {"name": "Demon Skin", "category": "Crafting Components", "platform": "Console"}, "-152489231": {"name": "Demonic Essence", "category": "Crafting Components", "platform": "Console"}, "-645052297": {"name": "Devil's Fang", "category": "Crafting Components", "platform": "Console"}, "437938885": {"name": "Element of Celerity", "category": "Crafting Components", "platform": "Console"}, "2064572134": {"name": "Encrusted Hoof (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-1725926578": {"name": "Essence of the Twin Seas", "category": "Crafting Components", "platform": "Console"}, "-1506992994": {"name": "Eternal Power Capsule", "category": "Crafting Components", "platform": "Console"}, "2064572166": {"name": "Exquisite Essence", "category": "Crafting Components", "platform": "Console"}, "1726149320": {"name": "Eyes of the Dead", "category": "Crafting Components", "platform": "Console"}, "2064572068": {"name": "Fallen Tooth (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "2064572168": {"name": "Fiery Brimstone", "category": "Crafting Components", "platform": "Console"}, "2073430088": {"name": "Forgotten Soul", "category": "Crafting Components", "platform": "Console"}, "937036308": {"name": "Frozen Blood", "category": "Crafting Components", "platform": "Console"}, "-799974399": {"name": "Gibbering Gemstone", "category": "Crafting Components", "platform": "Console"}, "-1299206911": {"name": "Glowing Ore", "category": "Crafting Components", "platform": "Console"}, "-730966965": {"name": "Griswold's Scribblings", "category": "Crafting Components", "platform": "Console"}, "-958180196": {"name": "Heart of Evil", "category": "Crafting Components", "platform": "Console"}, "460247356": {"name": "Hilt of the Silver Wolf", "category": "Crafting Components", "platform": "Console"}, "314328565": {"name": "Human Cartilage", "category": "Crafting Components", "platform": "Console"}, "-1624623846": {"name": "Idol of Terror", "category": "Crafting Components", "platform": "Console"}, "2064572167": {"name": "Iridescent Tear", "category": "Crafting Components", "platform": "Console"}, "-661382443": {"name": "Iron Wolves Doctrine", "category": "Crafting Components", "platform": "Console"}, "1102953247": {"name": "Leoric's Regret", "category": "Crafting Components", "platform": "Console"}, "-629520052": {"name": "Leoric's Shinbone", "category": "Crafting Components", "platform": "Console"}, "725082635": {"name": "Liquid Rainbow", "category": "Crafting Components", "platform": "Console"}, "-1402576366": {"name": "Living Flame", "category": "Crafting Components", "platform": "Console"}, "2064572101": {"name": "Lizard Eye (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "291872615": {"name": "Lyekurn's Diary", "category": "Crafting Components", "platform": "Console"}, "1835813454": {"name": "Maghda's Tormented Soul", "category": "Crafting Components", "platform": "Console"}, "-1018735616": {"name": "Mystical Source", "category": "Crafting Components", "platform": "Console"}, "-1020906970": {"name": "Page of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-667291726": {"name": "Page of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "526997101": {"name": "Phial of Weakness", "category": "Crafting Components", "platform": "Console"}, "778194127": {"name": "Quaking Vial", "category": "Crafting Components", "platform": "Console"}, "1114256397": {"name": "Reaper's Fear", "category": "Crafting Components", "platform": "Console"}, "-363607620": {"name": "Reusable Parts", "category": "Crafting Components", "platform": "Console"}, "280425627": {"name": "Rydraelm Tome", "category": "Crafting Components", "platform": "Console"}, "-830982818": {"name": "Shard of Entsteig Plate", "category": "Crafting Components", "platform": "Console"}, "-1176010511": {"name": "Shattered Core", "category": "Crafting Components", "platform": "Console"}, "2064572100": {"name": "Shimmering Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2114382103": {"name": "Shimmering Quill", "category": "Crafting Components", "platform": "Console"}, "-248569447": {"name": "Shuddering Demon Bone", "category": "Crafting Components", "platform": "Console"}, "-1810945531": {"name": "Skelon's Dice", "category": "Crafting Components", "platform": "Console"}, "-997569662": {"name": "Skull of Raylend", "category": "Crafting Components", "platform": "Console"}, "2064572067": {"name": "Subtle Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2113447741": {"name": "Sydyru Bone", "category": "Crafting Components", "platform": "Console"}, "-1253986069": {"name": "Symbol of the Guardian Brotherhood", "category": "Crafting Components", "platform": "Console"}, "494826242": {"name": "Tome of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-722757874": {"name": "Tome of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-970366835": {"name": "Tome of Secrets (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-443730551": {"name": "Torn Soul", "category": "Crafting Components", "platform": "Console"}, "1075049130": {"name": "Urn of Quickening", "category": "Crafting Components", "platform": "Console"}, "-605947593": {"name": "Veiled Crystal", "category": "Crafting Components", "platform": "Console"}, "1998976972": {"name": "Vengeful Eye", "category": "Crafting Components", "platform": "Console"}, "2029265596": {"name": "Vial of Putridness", "category": "Crafting Components", "platform": "Console"}, "1016299457": {"name": "White Oak Splinter", "category": "Crafting Components", "platform": "Console"}, "-799868536": {"name": "Wirt's Bell", "category": "Crafting Components", "platform": "Console"}, "2064572133": {"name": "Wishful Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "1098021531": {"name": "Wooden Stake", "category": "Crafting Components", "platform": "Console"}, "2103664575": {"name": "Woven Plate", "category": "Crafting Components", "platform": "Console"}, "-1824155952": {"name": "Writhing Spine", "category": "Crafting Components", "platform": "Console"}, "-747908647": {"name": "px_HoradricReagent_01 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908646": {"name": "px_HoradricReagent_02 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908645": {"name": "px_HoradricReagent_03 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908644": {"name": "px_HoradricReagent_04 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908643": {"name": "px_HoradricReagent_05 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-1171398246": {"name": "Design: Flawless Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429567911": {"name": "Design: Flawless Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521994629": {"name": "Design: Flawless Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147380749": {"name": "Design: Flawless Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872863289": {"name": "Design: Flawless Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171649812": {"name": "Design: Flawless Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521743063": {"name": "Design: Flawless Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147129183": {"name": "Design: Flawless Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872611723": {"name": "Design: Flawless Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1540480229": {"name": "Design: Hellfire Amulet (Patch 1.2.0)", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-384404829": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1792019289": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171541998": {"name": "Design: Marquise Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521850877": {"name": "Design: Marquise Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147236997": {"name": "Design: Marquise Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872719537": {"name": "Design: Marquise Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171613874": {"name": "Design: Perfect Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521779001": {"name": "Design: Perfect Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147165121": {"name": "Design: Perfect Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872647661": {"name": "Design: Perfect Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171577936": {"name": "Design: Radiant Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521814939": {"name": "Design: Radiant Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147201059": {"name": "Design: Radiant Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872683599": {"name": "Design: Radiant Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171434184": {"name": "Design: Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429531973": {"name": "Design: Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521958691": {"name": "Design: Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147344811": {"name": "Design: Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872827351": {"name": "Design: Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-987473495": {"name": "Legendary Plan: Arcane Barb", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427518108": {"name": "Legendary Plan: Archfiend Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1046516600": {"name": "Legendary Plan: Atrophy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1423568820": {"name": "Legendary Plan: Bitterness", "category": "Crafting Plans, Smith", "platform": "Console"}, "-380290097": {"name": "Legendary Plan: Black Bone Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1418151206": {"name": "Legendary Plan: Blitzbolter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-912856835": {"name": "Legendary Plan: Blood-Magic Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2000896011": {"name": "Legendary Plan: Blood-Magic Edge", "category": "Crafting Plans, Smith", "platform": "Console"}, "867919825": {"name": "Legendary Plan: Board Walkers", "category": "Crafting Plans, Smith", "platform": "Console"}, "-412066328": {"name": "Legendary Plan: Cataclysm", "category": "Crafting Plans, Smith", "platform": "Console"}, "1713442269": {"name": "Legendary Plan: Cinder Switch", "category": "Crafting Plans, Smith", "platform": "Console"}, "612002290": {"name": "Legendary Plan: Corruption", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1413614420": {"name": "Legendary Plan: Cosmic Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "421386501": {"name": "Legendary Plan: Deadeye", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1911170977": {"name": "Legendary Plan: Demon Claw", "category": "Crafting Plans, Smith", "platform": "Console"}, "999120591": {"name": "Legendary Plan: Demon Hand", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1426610660": {"name": "Legendary Plan: Devastator", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1326018783": {"name": "Legendary Plan: Earthshatter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1003069110": {"name": "Legendary Plan: Fire Brand", "category": "Crafting Plans, Smith", "platform": "Console"}, "957458384": {"name": "Legendary Plan: Fleeting Strap", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1639510640": {"name": "Legendary Plan: Gehennas", "category": "Crafting Plans, Smith", "platform": "Console"}, "780377031": {"name": "Legendary Plan: Golden Scourge", "category": "Crafting Plans, Smith", "platform": "Console"}, "412214125": {"name": "Legendary Plan: Harvest Moon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-501637898": {"name": "Legendary Plan: Hellish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-846348803": {"name": "Legendary Plan: Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "253048194": {"name": "Legendary Plan: Infernal Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-103899531": {"name": "Legendary Plan: Kethryes' Splint", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904674800": {"name": "Legendary Plan: Lai Yui's Persuader", "category": "Crafting Plans, Smith", "platform": "Console"}, "-168948640": {"name": "Legendary Plan: Lai Yui's Taiji", "category": "Crafting Plans, Smith", "platform": "Console"}, "1029528340": {"name": "Legendary Plan: Living Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "-405238050": {"name": "Legendary Plan: Longshot", "category": "Crafting Plans, Smith", "platform": "Console"}, "269805368": {"name": "Legendary Plan: Lost Boys", "category": "Crafting Plans, Smith", "platform": "Console"}, "244699910": {"name": "Legendary Plan: Mantle of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "2012779291": {"name": "Legendary Plan: Mark of The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "1744959696": {"name": "Legendary Plan: Night's Reaping", "category": "Crafting Plans, Smith", "platform": "Console"}, "645585264": {"name": "Legendary Plan: Nightmarish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2142082753": {"name": "Legendary Plan: Pendergrasps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-451796586": {"name": "Legendary Plan: Penders Purchase", "category": "Crafting Plans, Smith", "platform": "Console"}, "-216958038": {"name": "Legendary Plan: Piro Marella", "category": "Crafting Plans, Smith", "platform": "Console"}, "1162824884": {"name": "Legendary Plan: Quick Draw Belt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-64692264": {"name": "Legendary Plan: Reaper's Wraps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1654685887": {"name": "Legendary Plan: Robes of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904818548": {"name": "Legendary Plan: Rozpedin's Force", "category": "Crafting Plans, Smith", "platform": "Console"}, "1548578205": {"name": "Legendary Plan: Rozpedin's Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1861702115": {"name": "Legendary Plan: Ruinstoke", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2122397885": {"name": "Legendary Plan: Seven Sins", "category": "Crafting Plans, Smith", "platform": "Console"}, "1071490652": {"name": "Legendary Plan: Singularity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1846671248": {"name": "Legendary Plan: Skelon's Deceit", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1774978628": {"name": "Legendary Plan: Spite", "category": "Crafting Plans, Smith", "platform": "Console"}, "1806898802": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1463195022": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-402133524": {"name": "Legendary Plan: Starspine", "category": "Crafting Plans, Smith", "platform": "Console"}, "527593978": {"name": "Legendary Plan: Sunder", "category": "Crafting Plans, Smith", "platform": "Console"}, "2067112046": {"name": "Legendary Plan: Sydyru Crust", "category": "Crafting Plans, Smith", "platform": "Console"}, "1121389360": {"name": "Legendary Plan: The Helm of Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "-478050163": {"name": "Legendary Plan: The Helm of Rule", "category": "Crafting Plans, Smith", "platform": "Console"}, "186340431": {"name": "Legendary Plan: The Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "274154411": {"name": "Legendary Plan: The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "-242397939": {"name": "Legendary Plan: The Wedge", "category": "Crafting Plans, Smith", "platform": "Console"}, "-647199777": {"name": "Legendary Plan: Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "2066177684": {"name": "Legendary Plan: Unbound Bolt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1895316276": {"name": "Legendary Plan: Unending War", "category": "Crafting Plans, Smith", "platform": "Console"}, "-241912353": {"name": "Legendary Plan: Utar's Roar", "category": "Crafting Plans, Smith", "platform": "Console"}, "-446889189": {"name": "Legendary Plan: Venomhusk", "category": "Crafting Plans, Smith", "platform": "Console"}, "-30314682": {"name": "Legendary Plan: Wall of Bone", "category": "Crafting Plans, Smith", "platform": "Console"}, "-864620096": {"name": "Legendary Plan: Wall of Man", "category": "Crafting Plans, Smith", "platform": "Console"}, "-594473293": {"name": "Legendary Plan: War of the Dead", "category": "Crafting Plans, Smith", "platform": "Console"}, "1027888204": {"name": "Legendary Plan: Wondrous Deflectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110595705": {"name": "Rare Plan: Amulet of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110601443": {"name": "Rare Plan: Amulet of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110612529": {"name": "Rare Plan: Amulet of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110615435": {"name": "Rare Plan: Amulet of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069218648": {"name": "Rare Plan: Archon Armor of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069212910": {"name": "Rare Plan: Archon Armor of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069201824": {"name": "Rare Plan: Archon Armor of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069198918": {"name": "Rare Plan: Archon Armor of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427345983": {"name": "Rare Plan: Archon Gauntlets of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427340245": {"name": "Rare Plan: Archon Gauntlets of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427329159": {"name": "Rare Plan: Archon Gauntlets of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427326253": {"name": "Rare Plan: Archon Gauntlets of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194993962": {"name": "Rare Plan: Archon Spaulders of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194999700": {"name": "Rare Plan: Archon Spaulders of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195010786": {"name": "Rare Plan: Archon Spaulders of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195013692": {"name": "Rare Plan: Archon Spaulders of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666895": {"name": "Rare Plan: Exalted Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006109": {"name": "Rare Plan: Exalted Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232950": {"name": "Rare Plan: Exalted Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008978": {"name": "Rare Plan: Exalted Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049108": {"name": "Rare Plan: Exalted Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150314": {"name": "Rare Plan: Exalted Fine Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666894": {"name": "Rare Plan: Exalted Fine Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006108": {"name": "Rare Plan: Exalted Fine Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232949": {"name": "Rare Plan: Exalted Fine Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008977": {"name": "Rare Plan: Exalted Fine Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049107": {"name": "Rare Plan: Exalted Fine Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445431": {"name": "Rare Plan: Exalted Fine Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898771": {"name": "Rare Plan: Exalted Fine Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669101": {"name": "Rare Plan: Exalted Fine Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978459": {"name": "Rare Plan: Exalted Fine Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927530": {"name": "Rare Plan: Exalted Fine Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852815": {"name": "Rare Plan: Exalted Fine Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340209": {"name": "Rare Plan: Exalted Fine Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820187": {"name": "Rare Plan: Exalted Fine Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806016": {"name": "Rare Plan: Exalted Fine Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305005": {"name": "Rare Plan: Exalted Fine Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242821": {"name": "Rare Plan: Exalted Fine Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302887": {"name": "Rare Plan: Exalted Fine Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895417": {"name": "Rare Plan: Exalted Fine Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084692": {"name": "Rare Plan: Exalted Fine Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047028": {"name": "Rare Plan: Exalted Fine Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766203": {"name": "Rare Plan: Exalted Fine Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600122": {"name": "Rare Plan: Exalted Fine Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691115": {"name": "Rare Plan: Exalted Fine Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695962": {"name": "Rare Plan: Exalted Fine Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502140": {"name": "Rare Plan: Exalted Fine Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137849": {"name": "Rare Plan: Exalted Fine Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631474": {"name": "Rare Plan: Exalted Fine Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237753": {"name": "Rare Plan: Exalted Fine Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445432": {"name": "Rare Plan: Exalted Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898770": {"name": "Rare Plan: Exalted Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669102": {"name": "Rare Plan: Exalted Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-93021373": {"name": "Rare Plan: Exalted Grand Archmage Headpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150313": {"name": "Rare Plan: Exalted Grand Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666893": {"name": "Rare Plan: Exalted Grand Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006107": {"name": "Rare Plan: Exalted Grand Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232948": {"name": "Rare Plan: Exalted Grand Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008976": {"name": "Rare Plan: Exalted Grand Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049106": {"name": "Rare Plan: Exalted Grand Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445430": {"name": "Rare Plan: Exalted Grand Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898772": {"name": "Rare Plan: Exalted Grand Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "972140825": {"name": "Rare Plan: Exalted Grand Ghost Sight", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669100": {"name": "Rare Plan: Exalted Grand Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978460": {"name": "Rare Plan: Exalted Grand Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "531375006": {"name": "Rare Plan: Exalted Grand Heavy Baldric", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927531": {"name": "Rare Plan: Exalted Grand Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1162323497": {"name": "Rare Plan: Exalted Grand Manitou Mask", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852814": {"name": "Rare Plan: Exalted Grand Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340210": {"name": "Rare Plan: Exalted Grand Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820186": {"name": "Rare Plan: Exalted Grand Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806017": {"name": "Rare Plan: Exalted Grand Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305006": {"name": "Rare Plan: Exalted Grand Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242822": {"name": "Rare Plan: Exalted Grand Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302888": {"name": "Rare Plan: Exalted Grand Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895418": {"name": "Rare Plan: Exalted Grand Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084693": {"name": "Rare Plan: Exalted Grand Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047027": {"name": "Rare Plan: Exalted Grand Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766204": {"name": "Rare Plan: Exalted Grand Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600123": {"name": "Rare Plan: Exalted Grand Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691116": {"name": "Rare Plan: Exalted Grand Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695963": {"name": "Rare Plan: Exalted Grand Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502139": {"name": "Rare Plan: Exalted Grand Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "1784279615": {"name": "Rare Plan: Exalted Grand Stalker Cape", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137848": {"name": "Rare Plan: Exalted Grand Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631475": {"name": "Rare Plan: Exalted Grand Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237752": {"name": "Rare Plan: Exalted Grand Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927529": {"name": "Rare Plan: Exalted Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852816": {"name": "Rare Plan: Exalted Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340208": {"name": "Rare Plan: Exalted Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820188": {"name": "Rare Plan: Exalted Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806015": {"name": "Rare Plan: Exalted Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305004": {"name": "Rare Plan: Exalted Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242820": {"name": "Rare Plan: Exalted Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302886": {"name": "Rare Plan: Exalted Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895416": {"name": "Rare Plan: Exalted Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084691": {"name": "Rare Plan: Exalted Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047029": {"name": "Rare Plan: Exalted Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600121": {"name": "Rare Plan: Exalted Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691114": {"name": "Rare Plan: Exalted Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137850": {"name": "Rare Plan: Exalted Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631473": {"name": "Rare Plan: Exalted Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237754": {"name": "Rare Plan: Exalted Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656027917": {"name": "Rare Plan: Razorspikes of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656022179": {"name": "Rare Plan: Razorspikes of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656011093": {"name": "Rare Plan: Razorspikes of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656008187": {"name": "Rare Plan: Razorspikes of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1846613104": {"name": "Set Plan: Asheara's Uniform", "category": "Crafting Plans, Smith", "platform": "Console"}, "1930988128": {"name": "Set Plan: Asheara's Vestments", "category": "Crafting Plans, Smith", "platform": "Console"}, "1761387753": {"name": "Set Plan: Aughild's Authority", "category": "Crafting Plans, Smith", "platform": "Console"}, "-522988374": {"name": "Set Plan: Aughild's Victory", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1294645649": {"name": "Set Plan: Born's Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833297": {"name": "Set Plan: Born's Defiance", "category": "Crafting Plans, Smith", "platform": "Console"}, "1416190745": {"name": "Set Plan: Cain's Destiny", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833298": {"name": "Set Plan: Cain's Fate", "category": "Crafting Plans, Smith", "platform": "Console"}, "179824936": {"name": "Set Plan: Captain Crimson's Finery", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1405796903": {"name": "Set Plan: Captain Crimson's Trimmings", "category": "Crafting Plans, Smith", "platform": "Console"}, "2113413150": {"name": "Set Plan: Demon's Hide", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968554": {"name": "Set Plan: Demon's Skin", "category": "Crafting Plans, Smith", "platform": "Console"}, "331434522": {"name": "Set Plan: Griswold's Masterpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-410837290": {"name": "Set Plan: Griswold's Perfection", "category": "Crafting Plans, Smith", "platform": "Console"}, "1023052626": {"name": "Set Plan: Guardian's Contingency", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1605103146": {"name": "Set Plan: Guardian's Jeopardy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968552": {"name": "Set Plan: Hallowed Defenders", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1135146597": {"name": "Set Plan: Hallowed Protectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "1831860075": {"name": "Set Plan: Sage's Journey", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968553": {"name": "Set Plan: Sage's Plight", "category": "Crafting Plans, Smith", "platform": "Console"}, "1549850924": {"name": "Arma Haereticorum", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850923": {"name": "Arma Mortis", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850925": {"name": "Guardian Facade", "category": "Crafting Plans, Transmog", "platform": "Console"}, "-1723454145": {"name": "Legends of the Conqueror Volume 1 (Patch 2.1.0)", "category": "Crafting Plans, Transmog", "platform": "Console"}, "181031810": {"name": "01: Light Crossbow (DPS 9.4-10.5)", "category": "Crossbows", "platform": "Console"}, "181031811": {"name": "02: Crossbow (DPS 12.7-14.3)", "category": "Crossbows", "platform": "Console"}, "181031812": {"name": "03: Heavy Crossbow (DPS 17.6-19.3)", "category": "Crossbows", "platform": "Console"}, "181031813": {"name": "04: Arbalest (DPS 22.6-24.2)", "category": "Crossbows", "platform": "Console"}, "181031814": {"name": "05: Lian Nu (DPS 27.5-29.2)", "category": "Crossbows", "platform": "Console"}, "181031815": {"name": "06: War Crossbow (DPS 32.5-34.1)", "category": "Crossbows", "platform": "Console"}, "181031816": {"name": "07: Porcupine (DPS 37.4-39.1)", "category": "Crossbows", "platform": "Console"}, "181032899": {"name": "08: Siege Crossbow (DPS 53.9-57.2)", "category": "Crossbows", "platform": "Console"}, "181032900": {"name": "09: Quarrelbow (DPS 57.2-60.5)", "category": "Crossbows", "platform": "Console"}, "181032901": {"name": "10: Heavy Siege Crossbow (DPS 64.9-68.2)", "category": "Crossbows", "platform": "Console"}, "181032902": {"name": "11: Slingbow (DPS 76.5-81.4)", "category": "Crossbows", "platform": "Console"}, "181032903": {"name": "12: Chokonu (DPS 102.9-109.5)", "category": "Crossbows", "platform": "Console"}, "181032904": {"name": "13: War Caster (DPS 122.1-130.4)", "category": "Crossbows", "platform": "Console"}, "181032905": {"name": "14: Scorpion (DPS 165.6-175.5)", "category": "Crossbows", "platform": "Console"}, "181033988": {"name": "15: Windlass (DPS 179.3-189.2)", "category": "Crossbows", "platform": "Console"}, "181033989": {"name": "16: Cranequin (DPS 194.2-204.1)", "category": "Crossbows", "platform": "Console"}, "181033990": {"name": "17: Dread Crossbow (DPS 225.0-236.5)", "category": "Crossbows", "platform": "Console"}, "181033991": {"name": "18: Nayin (DPS 281.1-294.3)", "category": "Crossbows", "platform": "Console"}, "181033992": {"name": "19: Stonebow (DPS 358.1-371.3)", "category": "Crossbows", "platform": "Console"}, "181033993": {"name": "20: Doomcaster (DPS 424.1-437.3)", "category": "Crossbows", "platform": "Console"}, "181033994": {"name": "21: Hellion Crossbow (DPS 501.1-514.3)", "category": "Crossbows", "platform": "Console"}, "181035077": {"name": "22: Rampart Bow (DPS 698.0-711.2)", "category": "Crossbows", "platform": "Console"}, "181035078": {"name": "23: Oxybeles (DPS 948.2-961.4)", "category": "Crossbows", "platform": "Console"}, "2045161301": {"name": "Art Test Crossbow 1", "category": "Crossbows", "platform": "Console"}, "2045161302": {"name": "Art Test Crossbow 2", "category": "Crossbows", "platform": "Console"}, "2045161303": {"name": "Art Test Crossbow 3", "category": "Crossbows", "platform": "Console"}, "2045161304": {"name": "Art Test Crossbow 4", "category": "Crossbows", "platform": "Console"}, "2045161305": {"name": "Art Test Crossbow 5", "category": "Crossbows", "platform": "Console"}, "-174075631": {"name": "Legendary: Arcane Barb", "category": "Crossbows", "platform": "Console"}, "-174003757": {"name": "Legendary: Bakkan Caster", "category": "Crossbows", "platform": "Console"}, "-1447231541": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1447233985": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779307": {"name": "Legendary: Bakkan Caster (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172997521": {"name": "Legendary: Buriza-Do Kyanon", "category": "Crossbows", "platform": "Console"}, "-1414028197": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1414025753": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779335": {"name": "Legendary: Buriza-Do Kyanon (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135048049": {"name": "Legendary: Chanon Bolter", "category": "Crossbows", "platform": "Console"}, "-174183442": {"name": "Legendary: Demon Machine", "category": "Crossbows", "platform": "Console"}, "-1453163590": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1453161146": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779302": {"name": "Legendary: Demon Machine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174147505": {"name": "Legendary: Hellrack", "category": "Crossbows", "platform": "Console"}, "-1451977669": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1451975225": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779303": {"name": "Legendary: Hellrack (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174111568": {"name": "Legendary: Manticore", "category": "Crossbows", "platform": "Console"}, "-1450791748": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1450789304": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779304": {"name": "Legendary: Manticore (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172961584": {"name": "Legendary: Pus Spitter", "category": "Crossbows", "platform": "Console"}, "-1412842276": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1412839832": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779336": {"name": "Legendary: Pus Spitter (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449605827": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449603383": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779305": {"name": "Legendary: Starspine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135012112": {"name": "Legendary: Wojahnni Assaulter", "category": "Crossbows", "platform": "Console"}, "376423602": {"name": "P2 Crossbow norm Legendary 01", "category": "Crossbows", "platform": "Console"}, "376423603": {"name": "P2 Crossbow norm Legendary 02", "category": "Crossbows", "platform": "Console"}, "762151703": {"name": "PvP: Heavy Crossbow", "category": "Crossbows", "platform": "Console"}, "762151705": {"name": "PvP: Heroic Crossbow", "category": "Crossbows", "platform": "Console"}, "762151704": {"name": "PvP: Mighty Crossbow", "category": "Crossbows", "platform": "Console"}, "-118254879": {"name": "00: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254878": {"name": "01: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254877": {"name": "02: Sacred Scutum (AR 54-62)", "category": "Crusader Shields", "platform": "Console"}, "-118254876": {"name": "03: Royal Shield (AR 99-114)", "category": "Crusader Shields", "platform": "Console"}, "-118254875": {"name": "04: Heraldic Heater (AR 144-188)", "category": "Crusader Shields", "platform": "Console"}, "-118254874": {"name": "05: Embossed Shield (AR 189-224)", "category": "Crusader Shields", "platform": "Console"}, "-118254873": {"name": "06: Protector Shield (AR 225-251)", "category": "Crusader Shields", "platform": "Console"}, "-118254872": {"name": "07: Crown Shield (AR 252-287)", "category": "Crusader Shields", "platform": "Console"}, "-118253789": {"name": "08: Gilded Shield (AR 288-359)", "category": "Crusader Shields", "platform": "Console"}, "-118253788": {"name": "09: Wall Shield (AR 360-431)", "category": "Crusader Shields", "platform": "Console"}, "-118253787": {"name": "10: Zakara Heater (AR 432-503)", "category": "Crusader Shields", "platform": "Console"}, "-118253786": {"name": "11: Blazoned Shield (AR 504-575)", "category": "Crusader Shields", "platform": "Console"}, "-118253785": {"name": "12: Chased Shield (AR 576-652)", "category": "Crusader Shields", "platform": "Console"}, "-118253784": {"name": "13: Conquest Shield (AR 652-696)", "category": "Crusader Shields", "platform": "Console"}, "-118253783": {"name": "14: Imperial Kite (AR 697-741)", "category": "Crusader Shields", "platform": "Console"}, "-118252700": {"name": "15: Righteous Defender (AR 742-786)", "category": "Crusader Shields", "platform": "Console"}, "-118252699": {"name": "16: Enduring Guardian (AR 787-831)", "category": "Crusader Shields", "platform": "Console"}, "-118252698": {"name": "17: Zealous Protector (AR 832-854)", "category": "Crusader Shields", "platform": "Console"}, "-118252697": {"name": "18: Raptor Shield (AR 855-967)", "category": "Crusader Shields", "platform": "Console"}, "-118252696": {"name": "19: Adamantine Blason (AR 967-1112)", "category": "Crusader Shields", "platform": "Console"}, "-118252695": {"name": "20: Heavy Shield (AR 1417-1979)", "category": "Crusader Shields", "platform": "Console"}, "-118252694": {"name": "21: Stalwart Guardian (AR 1980-2277)", "category": "Crusader Shields", "platform": "Console"}, "795980376": {"name": "Art Test CruShield 1", "category": "Crusader Shields", "platform": "Console"}, "795980377": {"name": "Art Test CruShield 2", "category": "Crusader Shields", "platform": "Console"}, "795980378": {"name": "Art Test CruShield 3", "category": "Crusader Shields", "platform": "Console"}, "795980379": {"name": "Art Test CruShield 4", "category": "Crusader Shields", "platform": "Console"}, "795980380": {"name": "Art Test CruShield 5", "category": "Crusader Shields", "platform": "Console"}, "820607285": {"name": "Legendary: Akarat's Awakening", "category": "Crusader Shields", "platform": "Console"}, "1983862516": {"name": "Legendary: Frydehr's Wrath (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "820571348": {"name": "Legendary: Hallowed Bulwark", "category": "Crusader Shields", "platform": "Console"}, "820643222": {"name": "Legendary: Hellskull", "category": "Crusader Shields", "platform": "Console"}, "820535411": {"name": "Legendary: Jekangbord", "category": "Crusader Shields", "platform": "Console"}, "820499474": {"name": "Legendary: Piro Marella", "category": "Crusader Shields", "platform": "Console"}, "820751033": {"name": "Legendary: Salvation", "category": "Crusader Shields", "platform": "Console"}, "820679159": {"name": "Legendary: Sublime Conviction", "category": "Crusader Shields", "platform": "Console"}, "820715096": {"name": "Legendary: The Final Witness", "category": "Crusader Shields", "platform": "Console"}, "1983862517": {"name": "Legendary: Unrelenting Phalanx (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "-1303415302": {"name": "01: Simple Dagger (DPS 6.0-7.5)", "category": "Daggers", "platform": "Console"}, "-1303415301": {"name": "02: Shiv (DPS 9.0-11.3)", "category": "Daggers", "platform": "Console"}, "-1303415300": {"name": "03: Short Dagger (DPS 15.0-17.3)", "category": "Daggers", "platform": "Console"}, "-1303415299": {"name": "04: Dagger (DPS 20.3-22.5)", "category": "Daggers", "platform": "Console"}, "-1303415298": {"name": "05: Poignard (DPS 23.3-25.5)", "category": "Daggers", "platform": "Console"}, "-1303415297": {"name": "06: Stiletto (DPS 27.0-29.3)", "category": "Daggers", "platform": "Console"}, "-1303415296": {"name": "07: Skiver (DPS 30.0-23.3)", "category": "Daggers", "platform": "Console"}, "-1303414213": {"name": "08: Jagged Dagger (DPS 38.3-40.5)", "category": "Daggers", "platform": "Console"}, "-1303414212": {"name": "09: Kindjal (DPS 44.3-46.5)", "category": "Daggers", "platform": "Console"}, "-1303414211": {"name": "10: Pugio (DPS 50.3-52.5)", "category": "Daggers", "platform": "Console"}, "-1303414210": {"name": "11: Rondel (DPS 57.0-59.3)", "category": "Daggers", "platform": "Console"}, "-1303414209": {"name": "12: Scramasax (DPS 66.0-68.3)", "category": "Daggers", "platform": "Console"}, "-1303414208": {"name": "13: Main Gauche (DPS 77.3-79.5)", "category": "Daggers", "platform": "Console"}, "-1303414207": {"name": "14: Spine (DPS 92.3-94.5)", "category": "Daggers", "platform": "Console"}, "-1303413124": {"name": "15: Kukri (DPS 101.3-103.5)", "category": "Daggers", "platform": "Console"}, "-1303413123": {"name": "16: Pavade (DPS 108.0-112.5)", "category": "Daggers", "platform": "Console"}, "-1303413122": {"name": "17: Cinquedea (DPS 117.8-122.3)", "category": "Daggers", "platform": "Console"}, "-1303413121": {"name": "18: Skain (DPS 129.0-133.5)", "category": "Daggers", "platform": "Console"}, "-1303413120": {"name": "19: Basilard (DPS 156.0-160.5)", "category": "Daggers", "platform": "Console"}, "-1303413119": {"name": "20: Piercer (DPS 177.8-182.3)", "category": "Daggers", "platform": "Console"}, "-1303413118": {"name": "21: Darkblade (DPS 202.5-209.3)", "category": "Daggers", "platform": "Console"}, "-1303412035": {"name": "22: Kingsport Blade (DPS 270.0-274.5)", "category": "Daggers", "platform": "Console"}, "-1303412034": {"name": "23: Punyal (DPS 321.0-325.5)", "category": "Daggers", "platform": "Console"}, "-1200973729": {"name": "Art Test Dagger 1", "category": "Daggers", "platform": "Console"}, "-1200973728": {"name": "Art Test Dagger 2", "category": "Daggers", "platform": "Console"}, "-1200973727": {"name": "Art Test Dagger 3", "category": "Daggers", "platform": "Console"}, "-1200973726": {"name": "Art Test Dagger 4", "category": "Daggers", "platform": "Console"}, "-1200973725": {"name": "Art Test Dagger 5", "category": "Daggers", "platform": "Console"}, "-2073514231": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "-2073511787": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092661": {"name": "Legendary: Blood-Magic Blade (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973885091": {"name": "Legendary: Blood-Magic Edge", "category": "Daggers", "platform": "Console"}, "-934857509": {"name": "Legendary: Envious Blade", "category": "Daggers", "platform": "Console"}, "-934929383": {"name": "Legendary: Gull Dagger", "category": "Daggers", "platform": "Console"}, "-974028839": {"name": "Legendary: Kill", "category": "Daggers", "platform": "Console"}, "-2078257915": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "-2078255471": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092657": {"name": "Legendary: Kill (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973849154": {"name": "Legendary: Pig Sticker", "category": "Daggers", "platform": "Console"}, "-2072328310": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "-2072325866": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092662": {"name": "Legendary: Pig Sticker (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934893446": {"name": "Legendary: Prowl's Dastardly Shiv", "category": "Daggers", "platform": "Console"}, "-973992902": {"name": "Legendary: The Barber", "category": "Daggers", "platform": "Console"}, "-2077071994": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "-2077069550": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092658": {"name": "Legendary: The Barber (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973813217": {"name": "Legendary: The Clipper", "category": "Daggers", "platform": "Console"}, "-2071142389": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "-2071139945": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092663": {"name": "Legendary: The Clipper (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-838272988": {"name": "Legendary: The Horadric Hamburger", "category": "Daggers", "platform": "Console"}, "-1893282128": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1893279684": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1817947684": {"name": "Legendary: The Horadric Hamburger (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-972914792": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-65175862": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-2041494364": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "-2041491920": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092688": {"name": "Legendary: Wizardspike (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934821572": {"name": "Set: Eun-jang-do (Patch 2.2.0)", "category": "Daggers", "platform": "Console"}, "1771748851": {"name": "01: Wooden Bo (DPS 17.1-18.2)", "category": "Daibos", "platform": "Console"}, "1771748852": {"name": "02: Spade (DPS 21.5-23.1)", "category": "Daibos", "platform": "Console"}, "1771748853": {"name": "03: Eiku (DPS 27.5-29.2)", "category": "Daibos", "platform": "Console"}, "1771748854": {"name": "04: Taiji (DPS 41.8-43.5)", "category": "Daibos", "platform": "Console"}, "1771749940": {"name": "05: Jodo Staff (DPS 51.2-52.8)", "category": "Daibos", "platform": "Console"}, "1771749941": {"name": "06: Sibat (DPS 67.1-70.4)", "category": "Daibos", "platform": "Console"}, "1771749942": {"name": "07: Trost (DPS 97.9-101.2)", "category": "Daibos", "platform": "Console"}, "1771749943": {"name": "08: Svardstav (DPS 145.2-150.2)", "category": "Daibos", "platform": "Console"}, "1771751029": {"name": "09: Lathi (DPS 176.6-183.2)", "category": "Daibos", "platform": "Console"}, "1771751030": {"name": "10: Silambam (DPS 220.6-228.8)", "category": "Daibos", "platform": "Console"}, "1771751031": {"name": "11: Drevko (DPS 274.5-284.4)", "category": "Daibos", "platform": "Console"}, "1771751032": {"name": "12: Grand Taiji (DPS 374.6-386.1)", "category": "Daibos", "platform": "Console"}, "1771751033": {"name": "13: Zhezl (DPS 442.2-455.4)", "category": "Daibos", "platform": "Console"}, "1771751034": {"name": "14: Guru Staff (DPS 522.0-535.2)", "category": "Daibos", "platform": "Console"}, "1771752118": {"name": "15: Iron Judgement (DPS 684.3-696.3)", "category": "Daibos", "platform": "Console"}, "1771752119": {"name": "16: Whirlwind Staff (DPS 925.8-937.8)", "category": "Daibos", "platform": "Console"}, "446400306": {"name": "Legendary: Balance", "category": "Daibos", "platform": "Console"}, "1846230910": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "1846233354": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857814": {"name": "Legendary: Balance (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446651865": {"name": "Legendary: Flying Dragon", "category": "Daibos", "platform": "Console"}, "1854532357": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "1854534801": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857807": {"name": "Legendary: Flying Dragon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446436243": {"name": "Legendary: Incense Torch of the Grand Temple", "category": "Daibos", "platform": "Console"}, "1847416831": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "1847419275": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857813": {"name": "Legendary: Incense Torch of the Grand Temple (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446615928": {"name": "Legendary: Lai Yui's Persuader", "category": "Daibos", "platform": "Console"}, "1853346436": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "1853348880": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857808": {"name": "Legendary: Lai Yui's Taiji (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446472180": {"name": "Legendary: Rozpedin's Force", "category": "Daibos", "platform": "Console"}, "1848602752": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "1848605196": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857812": {"name": "Legendary: Rozpedin's Staff (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485499762": {"name": "Legendary: Staff of Kyro", "category": "Daibos", "platform": "Console"}, "1849788673": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "1849791117": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857811": {"name": "Legendary: The Clouds and the Moon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446508117": {"name": "Legendary: The Flow of Eternity", "category": "Daibos", "platform": "Console"}, "446579991": {"name": "Legendary: The Paddle", "category": "Daibos", "platform": "Console"}, "1852160515": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "1852162959": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857809": {"name": "Legendary: The Paddle (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485535699": {"name": "Legendary: Warstaff of General Quang", "category": "Daibos", "platform": "Console"}, "-326857815": {"name": "Set: Inna's Justice (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446364369": {"name": "Set: Inna's Reach", "category": "Daibos", "platform": "Console"}, "1845044989": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "1845047433": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "201941396": {"name": "Debug Axe 001", "category": "Debug", "platform": "Console"}, "201941397": {"name": "Debug Axe 002", "category": "Debug", "platform": "Console"}, "1162537406": {"name": "Debug Bow 001", "category": "Debug", "platform": "Console"}, "-1837157688": {"name": "Debug CrossBow 001", "category": "Debug", "platform": "Console"}, "110611392": {"name": "Debug Dagger 001", "category": "Debug", "platform": "Console"}, "-257486314": {"name": "Debug FistWeapon 001", "category": "Debug", "platform": "Console"}, "-1314119444": {"name": "Debug Mace 001", "category": "Debug", "platform": "Console"}, "-1314119443": {"name": "Debug Mace 002", "category": "Debug", "platform": "Console"}, "-1919522874": {"name": "Debug Polearm 001", "category": "Debug", "platform": "Console"}, "201837585": {"name": "Debug Spear 001", "category": "Debug", "platform": "Console"}, "-1812541014": {"name": "Debug Staff 001", "category": "Debug", "platform": "Console"}, "97851424": {"name": "Debug Wand 001", "category": "Debug", "platform": "Console"}, "109003955": {"name": "Professional Russian's 100 DPS 1H Axe", "category": "Debug", "platform": "Console"}, "1012655083": {"name": "Professional Russian's 100 DPS 1H Mace", "category": "Debug", "platform": "Console"}, "198260772": {"name": "Professional Russian's 100 DPS 1H Sword", "category": "Debug", "platform": "Console"}, "109003988": {"name": "Professional Russian's 100 DPS 2H Axe", "category": "Debug", "platform": "Console"}, "1012655116": {"name": "Professional Russian's 100 DPS 2H Mace", "category": "Debug", "platform": "Console"}, "198260805": {"name": "Professional Russian's 100 DPS 2H Sword", "category": "Debug", "platform": "Console"}, "1565754085": {"name": "Professional Russian's 100 DPS Bow", "category": "Debug", "platform": "Console"}, "1144284824": {"name": "Professional Russian's 100 DPS Crossbow Pistol", "category": "Debug", "platform": "Console"}, "199216263": {"name": "Professional Russian's 100 DPS Dagger", "category": "Debug", "platform": "Console"}, "131016487": {"name": "Professional Russian's 100 DPS Wand", "category": "Debug", "platform": "Console"}, "-268664650": {"name": "Professional Russian's Blind Proc Bow", "category": "Debug", "platform": "Console"}, "-497584419": {"name": "Professional Russian's Blind Proc Sword", "category": "Debug", "platform": "Console"}, "-1692695305": {"name": "Professional Russian's Bow", "category": "Debug", "platform": "Console"}, "-1353182983": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-1489225678": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-422042656": {"name": "Professional Russian's Chill Proc Sword", "category": "Debug", "platform": "Console"}, "860521450": {"name": "Professional Russian's Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-708154023": {"name": "Professional Russian's Dagger", "category": "Debug", "platform": "Console"}, "-813820178": {"name": "Professional Russian's Fast Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-1759844230": {"name": "Professional Russian's Fast Sword", "category": "Debug", "platform": "Console"}, "-1433265027": {"name": "Professional Russian's Fast Wand", "category": "Debug", "platform": "Console"}, "1812597803": {"name": "Professional Russian's Fear Proc Bow", "category": "Debug", "platform": "Console"}, "-1745505390": {"name": "Professional Russian's Fear Proc Sword", "category": "Debug", "platform": "Console"}, "-2004205682": {"name": "Professional Russian's Freeze Proc Bow", "category": "Debug", "platform": "Console"}, "-716158027": {"name": "Professional Russian's Freeze Proc Sword", "category": "Debug", "platform": "Console"}, "-1049148770": {"name": "Professional Russian's Immobilize Proc Bow", "category": "Debug", "platform": "Console"}, "1369510420": {"name": "Professional Russian's Knockback Proc Bow", "category": "Debug", "platform": "Console"}, "1063638971": {"name": "Professional Russian's Knockback Proc Sword", "category": "Debug", "platform": "Console"}, "-798366331": {"name": "Professional Russian's One-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206717": {"name": "Professional Russian's One-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502602": {"name": "Professional Russian's One-Handed Sword", "category": "Debug", "platform": "Console"}, "-395086843": {"name": "Professional Russian's Slow Crossbow Pistol", "category": "Debug", "platform": "Console"}, "1751317849": {"name": "Professional Russian's Slow Proc Sword", "category": "Debug", "platform": "Console"}, "-1341110895": {"name": "Professional Russian's Slow Sword", "category": "Debug", "platform": "Console"}, "-1899067884": {"name": "Professional Russian's Slow Wand", "category": "Debug", "platform": "Console"}, "476722551": {"name": "Professional Russian's Stun Proc Bow", "category": "Debug", "platform": "Console"}, "-41266491": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-519741474": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-798366298": {"name": "Professional Russian's Two-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206750": {"name": "Professional Russian's Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502569": {"name": "Professional Russian's Two-Handed Sword", "category": "Debug", "platform": "Console"}, "-23630983": {"name": "Professional Russian's Wand", "category": "Debug", "platform": "Console"}, "-908294397": {"name": "Shadowclone Ceremonial Knife (Hell)", "category": "Debug", "platform": "Console"}, "2012151919": {"name": "Shadowclone Ceremonial Knife (Inferno)", "category": "Debug", "platform": "Console"}, "754127773": {"name": "Shadowclone Ceremonial Knife (Nightmare)", "category": "Debug", "platform": "Console"}, "-1043228665": {"name": "Shadowclone Ceremonial Knife (Normal)", "category": "Debug", "platform": "Console"}, "-1067377991": {"name": "Shadowclone Crusader Shield", "category": "Debug", "platform": "Console"}, "413641572": {"name": "Shadowclone Daibo (Hell)", "category": "Debug", "platform": "Console"}, "1791808816": {"name": "Shadowclone Daibo (Inferno)", "category": "Debug", "platform": "Console"}, "1318657182": {"name": "Shadowclone Daibo (Nightmare)", "category": "Debug", "platform": "Console"}, "-269002584": {"name": "Shadowclone Daibo (Normal)", "category": "Debug", "platform": "Console"}, "-909812331": {"name": "Shadowclone Hand Crossbow (Hell)", "category": "Debug", "platform": "Console"}, "-998234687": {"name": "Shadowclone Hand Crossbow (Inferno)", "category": "Debug", "platform": "Console"}, "-496839313": {"name": "Shadowclone Hand Crossbow (Nightmare)", "category": "Debug", "platform": "Console"}, "1598708505": {"name": "Shadowclone Hand Crossbow (Normal)", "category": "Debug", "platform": "Console"}, "-1831368437": {"name": "Shadowclone Mojo", "category": "Debug", "platform": "Console"}, "-989882433": {"name": "Shadowclone One-Handed Flail", "category": "Debug", "platform": "Console"}, "318426510": {"name": "Shadowclone Staff (Hell)", "category": "Debug", "platform": "Console"}, "-1157906662": {"name": "Shadowclone Staff (Inferno)", "category": "Debug", "platform": "Console"}, "1714039048": {"name": "Shadowclone Staff (Nightmare)", "category": "Debug", "platform": "Console"}, "-878989998": {"name": "Shadowclone Staff (Normal)", "category": "Debug", "platform": "Console"}, "1875985680": {"name": "Shadowclone Two-Handed Mighty Weapon (Hell)", "category": "Debug", "platform": "Console"}, "832184156": {"name": "Shadowclone Two-Handed Mighty Weapon (Inferno)", "category": "Debug", "platform": "Console"}, "-35544630": {"name": "Shadowclone Two-Handed Mighty Weapon (Nightmare)", "category": "Debug", "platform": "Console"}, "-1209135788": {"name": "Shadowclone Two-Handed Mighty Weapon (Normal)", "category": "Debug", "platform": "Console"}, "2099757732": {"name": "ThorTest Bow", "category": "Debug", "platform": "Console"}, "-163370651": {"name": "ThorTest Ceremonial Dagger", "category": "Debug", "platform": "Console"}, "1291822630": {"name": "ThorTest CombatStaff", "category": "Debug", "platform": "Console"}, "-1647832978": {"name": "ThorTest Crossbow", "category": "Debug", "platform": "Console"}, "774399974": {"name": "ThorTest Dagger", "category": "Debug", "platform": "Console"}, "726818364": {"name": "ThorTest FistWeapon", "category": "Debug", "platform": "Console"}, "454120887": {"name": "ThorTest Hand Crossbow", "category": "Debug", "platform": "Console"}, "572923409": {"name": "ThorTest Mojo", "category": "Debug", "platform": "Console"}, "684187666": {"name": "ThorTest One-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118934": {"name": "ThorTest One-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530416": {"name": "ThorTest One-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903165": {"name": "ThorTest One-Handed Sword", "category": "Debug", "platform": "Console"}, "2099771967": {"name": "ThorTest Orb", "category": "Debug", "platform": "Console"}, "-1343109204": {"name": "ThorTest Polearm", "category": "Debug", "platform": "Console"}, "1306966712": {"name": "ThorTest Quiver", "category": "Debug", "platform": "Console"}, "1369802229": {"name": "ThorTest Shield", "category": "Debug", "platform": "Console"}, "1733748983": {"name": "ThorTest Spear", "category": "Debug", "platform": "Console"}, "1733888528": {"name": "ThorTest Staff", "category": "Debug", "platform": "Console"}, "684187699": {"name": "ThorTest Two-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118901": {"name": "ThorTest Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530383": {"name": "ThorTest Two-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903132": {"name": "ThorTest Two-Handed Sword", "category": "Debug", "platform": "Console"}, "573267654": {"name": "ThorTest Wand", "category": "Debug", "platform": "Console"}, "-234196765": {"name": "Abyssal Dye", "category": "Dyes", "platform": "Console"}, "-575184703": {"name": "All-Soap's Miraculous Dye Remover", "category": "Dyes", "platform": "Console"}, "-234196827": {"name": "Aquatic Dye", "category": "Dyes", "platform": "Console"}, "-234196822": {"name": "Autumn Dye", "category": "Dyes", "platform": "Console"}, "1866876233": {"name": "Bottled Cloud", "category": "Dyes", "platform": "Console"}, "1866876234": {"name": "Bottled Smoke", "category": "Dyes", "platform": "Console"}, "-234196826": {"name": "Cardinal Dye", "category": "Dyes", "platform": "Console"}, "-234196823": {"name": "Desert Dye", "category": "Dyes", "platform": "Console"}, "-234196795": {"name": "Elegant Dye", "category": "Dyes", "platform": "Console"}, "-234196794": {"name": "Forester's Dye", "category": "Dyes", "platform": "Console"}, "-234196792": {"name": "Golden Dye", "category": "Dyes", "platform": "Console"}, "-234196790": {"name": "Infernal Dye", "category": "Dyes", "platform": "Console"}, "-234196798": {"name": "Lovely Dye", "category": "Dyes", "platform": "Console"}, "-234196793": {"name": "Mariner's Dye", "category": "Dyes", "platform": "Console"}, "-234196789": {"name": "Purity Dye", "category": "Dyes", "platform": "Console"}, "-234196825": {"name": "Ranger's Dye", "category": "Dyes", "platform": "Console"}, "-234196791": {"name": "Royal Dye", "category": "Dyes", "platform": "Console"}, "-234196796": {"name": "Spring Dye", "category": "Dyes", "platform": "Console"}, "-234196797": {"name": "Summer Dye", "category": "Dyes", "platform": "Console"}, "-234196830": {"name": "Tanner's Dye", "category": "Dyes", "platform": "Console"}, "-2000448920": {"name": "Vanishing Dye", "category": "Dyes", "platform": "Console"}, "-234196828": {"name": "Winter Dye", "category": "Dyes", "platform": "Console"}, "761436846": {"name": "01: Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761436847": {"name": "02: Eye", "category": "Enchantress Focuses", "platform": "Console"}, "761437935": {"name": "03: Scrying Glass", "category": "Enchantress Focuses", "platform": "Console"}, "761437936": {"name": "04: Blink", "category": "Enchantress Focuses", "platform": "Console"}, "761437937": {"name": "05: Crucible", "category": "Enchantress Focuses", "platform": "Console"}, "761437938": {"name": "06: Root", "category": "Enchantress Focuses", "platform": "Console"}, "761439024": {"name": "07: Eternity Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761439025": {"name": "08: Oculus", "category": "Enchantress Focuses", "platform": "Console"}, "761439026": {"name": "09: Cauldron", "category": "Enchantress Focuses", "platform": "Console"}, "761439027": {"name": "10: Herb", "category": "Enchantress Focuses", "platform": "Console"}, "761439028": {"name": "11: Anamorphosis", "category": "Enchantress Focuses", "platform": "Console"}, "761439029": {"name": "12: Augur", "category": "Enchantress Focuses", "platform": "Console"}, "-450681607": {"name": "Legendary: Hand of the Prophet", "category": "Enchantress Focuses", "platform": "Console"}, "-450681608": {"name": "Legendary: Smoking Thurible", "category": "Enchantress Focuses", "platform": "Console"}, "-450681606": {"name": "Legendary: Vadim's Surge", "category": "Enchantress Focuses", "platform": "Console"}, "1236604967": {"name": "00: Worn Knuckles (DPS 3.0)", "category": "Fist Weapons", "platform": "Console"}, "1236604968": {"name": "01: Knuckles (DPS 7.0-8.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604969": {"name": "02: Spikes (DPS 15.4-17.5)", "category": "Fist Weapons", "platform": "Console"}, "1236604970": {"name": "03: Talon (DPS 20.3-22.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604971": {"name": "04: Shuko (DPS 29.4-31.5)", "category": "Fist Weapons", "platform": "Console"}, "1236606057": {"name": "05: Breaker (DPS 38.5-40.6)", "category": "Fist Weapons", "platform": "Console"}, "1236606058": {"name": "06: Iron Fist (DPS 46.2-48.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606059": {"name": "07: Claw (DPS 60.2-62.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606060": {"name": "08: Kastet (DPS 81.2-83.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607146": {"name": "09: Grappler (DPS 106.4-110.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607147": {"name": "10: Hammer Hand (DPS 130.2-134.4)", "category": "Fist Weapons", "platform": "Console"}, "1236607148": {"name": "11: Demon Fang (DPS 156.8-163.1)", "category": "Fist Weapons", "platform": "Console"}, "1236607149": {"name": "12: Pulverizer (DPS 181.3-187.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607150": {"name": "13: Golden Talon (DPS 210.0-216.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607151": {"name": "14: Heaven Hand (DPS 242.2-248.5)", "category": "Fist Weapons", "platform": "Console"}, "1236608235": {"name": "15: Spiked Fist (DPS 322.0-328.3)", "category": "Fist Weapons", "platform": "Console"}, "1236608236": {"name": "16: Suwaiya (DPS 392.0-398.3)", "category": "Fist Weapons", "platform": "Console"}, "1349166155": {"name": "Art Test Fist 1", "category": "Fist Weapons", "platform": "Console"}, "1349166156": {"name": "Art Test Fist 2", "category": "Fist Weapons", "platform": "Console"}, "1349166157": {"name": "Art Test Fist 3", "category": "Fist Weapons", "platform": "Console"}, "1349166158": {"name": "Art Test Fist 4", "category": "Fist Weapons", "platform": "Console"}, "1349166159": {"name": "Art Test Fist 5", "category": "Fist Weapons", "platform": "Console"}, "-1097629365": {"name": "Legendary: Crystal Fist", "category": "Fist Weapons", "platform": "Console"}, "-1862107977": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1862105533": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690589": {"name": "Legendary: Crystal Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "2032005920": {"name": "Legendary: Deathreach", "category": "Fist Weapons", "platform": "Console"}, "-1097773113": {"name": "Legendary: Demon Claw", "category": "Fist Weapons", "platform": "Console"}, "-1866851661": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1866849217": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690593": {"name": "Legendary: Demon Hand (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058709594": {"name": "Legendary: Falcon Strike", "category": "Fist Weapons", "platform": "Console"}, "537275943": {"name": "Legendary: Fist Weapon of the Shattered Hand (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097665302": {"name": "Legendary: Fleshrake", "category": "Fist Weapons", "platform": "Console"}, "-1863293898": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1863291454": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690590": {"name": "Legendary: Fleshrake (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058745531": {"name": "Legendary: Jawbreaker", "category": "Fist Weapons", "platform": "Console"}, "-1097737176": {"name": "Legendary: Logan's Claw", "category": "Fist Weapons", "platform": "Console"}, "-1865665740": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1865663296": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690592": {"name": "Legendary: Logan's Claw (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097809050": {"name": "Legendary: Rabid Strike", "category": "Fist Weapons", "platform": "Console"}, "-1868037582": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1868035138": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690594": {"name": "Legendary: Rabid Strike (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096623129": {"name": "Legendary: Scarbringer", "category": "Fist Weapons", "platform": "Console"}, "-1828902189": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1828899745": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690561": {"name": "Legendary: Scarbringer (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096659066": {"name": "Legendary: Sledge Fist", "category": "Fist Weapons", "platform": "Console"}, "-1830088110": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1830085666": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690562": {"name": "Legendary: Sledge Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097593428": {"name": "Legendary: The Fist of Az'Turrasq", "category": "Fist Weapons", "platform": "Console"}, "-1860922056": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1860919612": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690588": {"name": "Legendary: The Fist of Az'Turrasq (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132078": {"name": "Legendary: Vengeful Wind (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097701239": {"name": "Legendary: Won Khim Lau", "category": "Fist Weapons", "platform": "Console"}, "-1864479819": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1864477375": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690591": {"name": "Legendary: Won Khim Lau (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132079": {"name": "P1 fistWeapon norm Legendary 01", "category": "Fist Weapons", "platform": "Console"}, "-1826530347": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1826527903": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096551255": {"name": "Set: Hallowed Hold", "category": "Fist Weapons", "platform": "Console"}, "-840690559": {"name": "Set: Hallowed Touch (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690563": {"name": "Set: Shenlong's Crashing Tide (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690564": {"name": "Set: Shenlong's Endless Wave (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096695003": {"name": "Set: Shenlong's Fist of Legend", "category": "Fist Weapons", "platform": "Console"}, "-1831274031": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1831271587": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096730940": {"name": "Set: Shenlong's Relentless Assault", "category": "Fist Weapons", "platform": "Console"}, "-1832459952": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1832457508": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-912456881": {"name": "00: Rusty Flail (DPS 3.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456880": {"name": "01: Spiked Flail (DPS 7.7-9.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456879": {"name": "02: Iron Whip (DPS 13.3-15.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456878": {"name": "03: Barbed Flail (DPS 18.9-21.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456877": {"name": "04: Thresher (DPS 25.2-27.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456876": {"name": "05: Flail (DPS 30.8-32.9)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455791": {"name": "06: Ball and Chain (DPS 35.0-37.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455790": {"name": "07: Chain Mace (DPS 43.4-45.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455789": {"name": "08: Shredder (DPS 53.2-55.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455788": {"name": "09: Imposing Flail (DPS 71.4-73.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455787": {"name": "10: Royal Guardian (DPS 105.0-109.2)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454702": {"name": "11: Painbringer (DPS 119.0-125.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454701": {"name": "12: Knout (DPS 139.3-145.6)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454700": {"name": "13: Wicked Flail (DPS 177.1-183.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454699": {"name": "14: Giant's Flail (DPS 312.9-321.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454698": {"name": "15: Grandfather's Flail (DPS 382.9-391.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955915": {"name": "Art Test Flails One-Handed 1", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955914": {"name": "Art Test Flails One-Handed 2", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955913": {"name": "Art Test Flails One-Handed 3", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955912": {"name": "Art Test Flails One-Handed 4", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955911": {"name": "Art Test Flails One-Handed 5", "category": "Flails, One-Handed", "platform": "Console"}, "-1791015660": {"name": "Legendary: Darklight", "category": "Flails, One-Handed", "platform": "Console"}, "-1791195345": {"name": "Legendary: Golden Scourge", "category": "Flails, One-Handed", "platform": "Console"}, "-1791051597": {"name": "Legendary: Gyrfalcon's Foote", "category": "Flails, One-Handed", "platform": "Console"}, "-1790979723": {"name": "Legendary: Inviolable Faith", "category": "Flails, One-Handed", "platform": "Console"}, "-1791159408": {"name": "Legendary: Justinian's Mercy", "category": "Flails, One-Handed", "platform": "Console"}, "-1791087534": {"name": "Legendary: Kassar's Retribution", "category": "Flails, One-Handed", "platform": "Console"}, "1226090826": {"name": "Legendary: Mortal Coil", "category": "Flails, One-Handed", "platform": "Console"}, "-1791123471": {"name": "Legendary: Swiftmount", "category": "Flails, One-Handed", "platform": "Console"}, "1784501906": {"name": "P1 Flails1H norm Legendary 01", "category": "Flails, One-Handed", "platform": "Console"}, "-873321487": {"name": "01: Chang Xiao Bang (DPS 9.2-10.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321486": {"name": "02: Battle Flail (DPS 15.0-16.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321485": {"name": "03: Grand Thresher (DPS 22.4-24.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321484": {"name": "04: Two-Handed Flail (DPS 29.3-31.1)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321483": {"name": "05: Castigator (DPS 37.4-40.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320398": {"name": "06: Pyeongon (DPS 51.8-55.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320397": {"name": "07: Chigiriki (DPS 65.0-70.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320396": {"name": "08: Threshal (DPS 81.7-86.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320395": {"name": "09: Grand Flail (DPS 102.9-109.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320394": {"name": "10: Angelic Flail (DPS 146.1-154.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319309": {"name": "11: Campaigner's Grand Flail (DPS 194.4-206.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319308": {"name": "12: Bludgeoning Grand Flail (DPS 261.6-275.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319307": {"name": "13: Painbringer Grand Flail (DPS 333.5-347.3)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319306": {"name": "14: Baroque Grand Flail (DPS 648.0-661.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319305": {"name": "15: Angelic Grand Flail (DPS 878.0-891.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919978": {"name": "Art Test Flails Two-Handed 1", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919977": {"name": "Art Test Flails Two-Handed 2", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919976": {"name": "Art Test Flails Two-Handed 3", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919975": {"name": "Art Test Flails Two-Handed 4", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919974": {"name": "Art Test Flails Two-Handed 5", "category": "Flails, Two-Handed", "platform": "Console"}, "163153041": {"name": "Legendary: Baleful Remnant", "category": "Flails, Two-Handed", "platform": "Console"}, "163188978": {"name": "Legendary: Fate of the Fell", "category": "Flails, Two-Handed", "platform": "Console"}, "163224915": {"name": "Legendary: Golden Flense", "category": "Flails, Two-Handed", "platform": "Console"}, "163117104": {"name": "Legendary: The Mortal Drama", "category": "Flails, Two-Handed", "platform": "Console"}, "1784501907": {"name": "P1 Flails1H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712685": {"name": "P1 Flails2H norm Legendary 01", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712684": {"name": "P1 Flails2H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-1026738420": {"name": "legendary: Golden Flense (Patch 2.2.0)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1411866897": {"name": "Amethyst 01: Chipped Amethyst", "category": "Gems", "platform": "Console"}, "-1411866896": {"name": "Amethyst 02: Flawed Amethyst", "category": "Gems", "platform": "Console"}, "-1411866895": {"name": "Amethyst 03: Amethyst", "category": "Gems", "platform": "Console"}, "-1411866894": {"name": "Amethyst 04: Flawless Amethyst", "category": "Gems", "platform": "Console"}, "-1411866893": {"name": "Amethyst 05: Perfect Amethyst", "category": "Gems", "platform": "Console"}, "-1411866892": {"name": "Amethyst 06: Radiant Amethyst", "category": "Gems", "platform": "Console"}, "-1411866891": {"name": "Amethyst 07: Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866890": {"name": "Amethyst 08: Flawless Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866889": {"name": "Amethyst 09: Perfect Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866865": {"name": "Amethyst 10: Radiant Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866864": {"name": "Amethyst 11: Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866863": {"name": "Amethyst 12: Flawless Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866862": {"name": "Amethyst 13: Perfect Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866861": {"name": "Amethyst 14: Radiant Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866860": {"name": "Amethyst 15: Marquise Amethyst", "category": "Gems", "platform": "Console"}, "-1411866859": {"name": "Amethyst 16: Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866858": {"name": "Amethyst 17: Flawless Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866857": {"name": "Amethyst 18: Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1411866856": {"name": "Amethyst 19: Flawless Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1315690660": {"name": "Diamond 01: Chipped Diamond", "category": "Gems", "platform": "Console"}, "-1315690659": {"name": "Diamond 02: Flawed Diamond", "category": "Gems", "platform": "Console"}, "-1315690658": {"name": "Diamond 03: Diamond", "category": "Gems", "platform": "Console"}, "-1315690657": {"name": "Diamond 04: Flawless Diamond", "category": "Gems", "platform": "Console"}, "-1315690656": {"name": "Diamond 05: Perfect Diamond", "category": "Gems", "platform": "Console"}, "-1315690655": {"name": "Diamond 06: Radiant Diamond", "category": "Gems", "platform": "Console"}, "-1315690654": {"name": "Diamond 07: Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690653": {"name": "Diamond 08: Flawless Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690652": {"name": "Diamond 09: Perfect Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690628": {"name": "Diamond 10: Radiant Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690627": {"name": "Diamond 11: Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690626": {"name": "Diamond 12: Flawless Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690625": {"name": "Diamond 13: Perfect Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690624": {"name": "Diamond 14: Radiant Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690623": {"name": "Diamond 15: Marquise Diamond", "category": "Gems", "platform": "Console"}, "-1315690622": {"name": "Diamond 16: Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690621": {"name": "Diamond 17: Flawless Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690620": {"name": "Diamond 18: Royal Diamond", "category": "Gems", "platform": "Console"}, "-1315690619": {"name": "Diamond 19: Flawless Royal Diamond", "category": "Gems", "platform": "Console"}, "-1733388806": {"name": "Emerald 01: Chipped Emerald", "category": "Gems", "platform": "Console"}, "-1733388805": {"name": "Emerald 02: Flawed Emerald", "category": "Gems", "platform": "Console"}, "-1733388804": {"name": "Emerald 03: Emerald", "category": "Gems", "platform": "Console"}, "-1733388803": {"name": "Emerald 04: Flawless Emerald", "category": "Gems", "platform": "Console"}, "-1733388802": {"name": "Emerald 05: Perfect Emerald", "category": "Gems", "platform": "Console"}, "-1733388801": {"name": "Emerald 06: Radiant Emerald", "category": "Gems", "platform": "Console"}, "-1733388800": {"name": "Emerald 07: Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388799": {"name": "Emerald 08: Flawless Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388798": {"name": "Emerald 09: Perfect Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388774": {"name": "Emerald 10: Radiant Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388773": {"name": "Emerald 11: Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388772": {"name": "Emerald 12: Flawless Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388771": {"name": "Emerald 13: Perfect Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388770": {"name": "Emerald 14: Radiant Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388769": {"name": "Emerald 15: Marquise Emerald", "category": "Gems", "platform": "Console"}, "-1733388768": {"name": "Emerald 16: Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388767": {"name": "Emerald 17: Flawless Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388766": {"name": "Emerald 18: Royal Emerald", "category": "Gems", "platform": "Console"}, "-1733388765": {"name": "Emerald 19: Flawless Royal Emerald", "category": "Gems", "platform": "Console"}, "-1046455929": {"name": "Legendary: Bane of the Powerful (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046419992": {"name": "Legendary: Bane of the Trapped (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045162197": {"name": "Legendary: Boon of the Hoarder (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045305945": {"name": "Legendary: Enforcer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045090323": {"name": "Legendary: Esoteric Alteration (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1044084087": {"name": "Legendary: Gem Of X NYI (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046312181": {"name": "Legendary: Gem of Efficacious Toxin (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046384055": {"name": "Legendary: Gem of Reduced Level Requirement (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046204370": {"name": "Legendary: Gogok of Swiftness (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046168433": {"name": "Legendary: Invigorating Gemstone (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046240307": {"name": "Legendary: Mirinae, Teardrop of the Starweaver (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045054386": {"name": "Legendary: Molten Wildebeest's Gizzard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045270008": {"name": "Legendary: Moratorium (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044982512": {"name": "Legendary: Mutilation Guard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046276244": {"name": "Legendary: Pain Enhancer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044120024": {"name": "Legendary: Shen's Delight (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045198134": {"name": "Legendary: Simplicity's Strength (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045018449": {"name": "Legendary: Stone Of Heresy (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045126260": {"name": "Legendary: Taeguk (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046348118": {"name": "Legendary: Wreath of Lightning (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045234071": {"name": "Legendary: Zei's Stone of Vengeance (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "1603007810": {"name": "Ruby 01: Chipped Ruby", "category": "Gems", "platform": "Console"}, "1603007811": {"name": "Ruby 02: Flawed Ruby", "category": "Gems", "platform": "Console"}, "1603007812": {"name": "Ruby 03: Ruby", "category": "Gems", "platform": "Console"}, "1603007813": {"name": "Ruby 04: Flawless Ruby", "category": "Gems", "platform": "Console"}, "1603007814": {"name": "Ruby 05: Perfect Ruby", "category": "Gems", "platform": "Console"}, "1603007815": {"name": "Ruby 06: Radiant Ruby", "category": "Gems", "platform": "Console"}, "1603007816": {"name": "Ruby 07: Square Ruby", "category": "Gems", "platform": "Console"}, "1603007817": {"name": "Ruby 08: Flawless Square Ruby", "category": "Gems", "platform": "Console"}, "1603007818": {"name": "Ruby 09: Perfect Square Ruby", "category": "Gems", "platform": "Console"}, "1603007842": {"name": "Ruby 10: Radiant Square Ruby", "category": "Gems", "platform": "Console"}, "1603007843": {"name": "Ruby 11: Star Ruby", "category": "Gems", "platform": "Console"}, "1603007844": {"name": "Ruby 12: Flawless Star Ruby", "category": "Gems", "platform": "Console"}, "1603007845": {"name": "Ruby 13: Perfect Star Ruby", "category": "Gems", "platform": "Console"}, "1603007846": {"name": "Ruby 14: Radiant Star Ruby", "category": "Gems", "platform": "Console"}, "1603007847": {"name": "Ruby 15: Marquise Ruby", "category": "Gems", "platform": "Console"}, "1603007848": {"name": "Ruby 16: Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007849": {"name": "Ruby 17: Flawless Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007850": {"name": "Ruby 18: Royal Ruby", "category": "Gems", "platform": "Console"}, "1603007851": {"name": "Ruby 19: Flawless Royal Ruby", "category": "Gems", "platform": "Console"}, "2058771886": {"name": "Topaz 01: Chipped Topaz", "category": "Gems", "platform": "Console"}, "2058771887": {"name": "Topaz 02: Flawed Topaz", "category": "Gems", "platform": "Console"}, "2058771888": {"name": "Topaz 03: Topaz", "category": "Gems", "platform": "Console"}, "2058771889": {"name": "Topaz 04: Flawless Topaz", "category": "Gems", "platform": "Console"}, "2058771890": {"name": "Topaz 05: Perfect Topaz", "category": "Gems", "platform": "Console"}, "2058771891": {"name": "Topaz 06: Radiant Topaz", "category": "Gems", "platform": "Console"}, "2058771892": {"name": "Topaz 07: Square Topaz", "category": "Gems", "platform": "Console"}, "2058771893": {"name": "Topaz 08: Flawless Square Topaz", "category": "Gems", "platform": "Console"}, "2058771894": {"name": "Topaz 09: Perfect Square Topaz", "category": "Gems", "platform": "Console"}, "2058771918": {"name": "Topaz 10: Radiant Square Topaz", "category": "Gems", "platform": "Console"}, "2058771919": {"name": "Topaz 11: Star Topaz", "category": "Gems", "platform": "Console"}, "2058771920": {"name": "Topaz 12: Flawless Star Topaz", "category": "Gems", "platform": "Console"}, "2058771921": {"name": "Topaz 13: Perfect Star Topaz", "category": "Gems", "platform": "Console"}, "2058771922": {"name": "Topaz 14: Radiant Star Topaz", "category": "Gems", "platform": "Console"}, "2058771923": {"name": "Topaz 15: Marquise Topaz", "category": "Gems", "platform": "Console"}, "2058771924": {"name": "Topaz 16: Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771925": {"name": "Topaz 17: Flawless Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771926": {"name": "Topaz 18: Royal Topaz", "category": "Gems", "platform": "Console"}, "2058771927": {"name": "Topaz 19: Flawless Royal Topaz", "category": "Gems", "platform": "Console"}, "-1533914304": {"name": "01: Gloves (AR 4-5)", "category": "Gloves", "platform": "Console"}, "-1533914303": {"name": "02: Leather Gloves (AR 14-16)", "category": "Gloves", "platform": "Console"}, "-1533914302": {"name": "03: Hide Gloves (AR 28-32)", "category": "Gloves", "platform": "Console"}, "-1533914301": {"name": "04: Chain Gloves (AR 42-55)", "category": "Gloves", "platform": "Console"}, "-1533914300": {"name": "05: Gauntlets (AR 56-69)", "category": "Gloves", "platform": "Console"}, "-1533914299": {"name": "06: Plated Gauntlets (AR 70-88)", "category": "Gloves", "platform": "Console"}, "-1533913215": {"name": "07: Grips (AR 88-106)", "category": "Gloves", "platform": "Console"}, "-1533913214": {"name": "08: Etched Gloves (AR 107-125)", "category": "Gloves", "platform": "Console"}, "-1533913213": {"name": "09: Vambraces (AR 126-144)", "category": "Gloves", "platform": "Console"}, "-1533913212": {"name": "10: Battle Gauntlets (AR 144-173)", "category": "Gloves", "platform": "Console"}, "-1533913211": {"name": "11: Boneweave Gauntlets (AR 175-192)", "category": "Gloves", "platform": "Console"}, "-1533912126": {"name": "12: Balor Fists (AR 192-209)", "category": "Gloves", "platform": "Console"}, "-1533912125": {"name": "13: Manifers (AR 210-221)", "category": "Gloves", "platform": "Console"}, "-1533912124": {"name": "14: Warlord Gauntlets (AR 221-249)", "category": "Gloves", "platform": "Console"}, "-1533912123": {"name": "15: Stranglers (AR 250-278)", "category": "Gloves", "platform": "Console"}, "-1533912122": {"name": "16: Sovereign Vambraces (AR 280-308)", "category": "Gloves", "platform": "Console"}, "-1533912121": {"name": "17: Archon Gauntlets (AR 309-366)", "category": "Gloves", "platform": "Console"}, "-1533912120": {"name": "18: Rakkisgard Gauntlets (AR 367-512)", "category": "Gloves", "platform": "Console"}, "-1533912119": {"name": "19: Ascended Gauntlets (AR 513-590)", "category": "Gloves", "platform": "Console"}, "-542544859": {"name": "Art Test Gloves 1", "category": "Gloves", "platform": "Console"}, "-542544858": {"name": "Art Test Gloves 2", "category": "Gloves", "platform": "Console"}, "-542544857": {"name": "Art Test Gloves 3", "category": "Gloves", "platform": "Console"}, "-542544856": {"name": "Art Test Gloves 4", "category": "Gloves", "platform": "Console"}, "-542544855": {"name": "Art Test Gloves 5", "category": "Gloves", "platform": "Console"}, "-724111115": {"name": "Art_Test_Gloves_10 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-724111114": {"name": "Art_Test_Gloves_11 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544854": {"name": "Art_Test_Gloves_6 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544853": {"name": "Art_Test_Gloves_7 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544852": {"name": "Art_Test_Gloves_8 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544851": {"name": "Art_Test_Gloves_9 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "509897201": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "742334711": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "614385664": {"name": "Legendary: Alabaster Gloves", "category": "Gloves", "platform": "Console"}, "-935578501": {"name": "Legendary: Conqueror's Gauntlets (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "575250271": {"name": "Legendary: Frostburn", "category": "Gloves", "platform": "Console"}, "1803312459": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1803314903": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593655": {"name": "Legendary: Frostburn Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576400255": {"name": "Legendary: Gladiator Gauntlets", "category": "Gloves", "platform": "Console"}, "1841261931": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1841264375": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593687": {"name": "Legendary: Gladiator Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "614421601": {"name": "Legendary: Gloves of Worship", "category": "Gloves", "platform": "Console"}, "204261921": {"name": "Legendary: Grips of Perilous Ascent", "category": "Gloves", "platform": "Console"}, "576508066": {"name": "Legendary: Magefist", "category": "Gloves", "platform": "Console"}, "1844819694": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "1844822138": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "880593690": {"name": "Legendary: Magefist (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1802126538": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "1802128982": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "880593654": {"name": "Legendary: Pendergrasps (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575214334": {"name": "Legendary: Penders Purchase", "category": "Gloves", "platform": "Console"}, "614349727": {"name": "Legendary: St. Archew's Gage", "category": "Gloves", "platform": "Console"}, "575429956": {"name": "Legendary: Stone Gauntlets", "category": "Gloves", "platform": "Console"}, "1809242064": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1809244508": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593660": {"name": "Legendary: Stone Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575286208": {"name": "Legendary: Tasker and Theo", "category": "Gloves", "platform": "Console"}, "1804498380": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "1804500824": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "880593656": {"name": "Legendary: Tasker and Theo (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "880593662": {"name": "Set: Asheara's Clasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1811613906": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "1811616350": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "575501830": {"name": "Set: Asheara's Ward", "category": "Gloves", "platform": "Console"}, "1846005615": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "1846008059": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "576544003": {"name": "Set: Cain's Scrivener", "category": "Gloves", "platform": "Console"}, "880593691": {"name": "Set: Cain's Warmers (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "2058321365": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058321364": {"name": "Set: Fiendish Grips (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058285427": {"name": "Set: Fierce Gauntlets (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058429438": {"name": "Set: Firebird's Talons", "category": "Gloves", "platform": "Console"}, "2058501312": {"name": "Set: Fists of Thunder", "category": "Gloves", "platform": "Console"}, "2058249490": {"name": "Set: Gauntlet of the Wastes (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059399737": {"name": "Set: Gauntlets of Akkhan", "category": "Gloves", "platform": "Console"}, "2059615359": {"name": "Set: Helltooth Gauntlets", "category": "Gloves", "platform": "Console"}, "880593661": {"name": "Set: Immortal King's Forge (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575465893": {"name": "Set: Immortal King's Irons", "category": "Gloves", "platform": "Console"}, "1810427985": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "1810430429": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "-206156950": {"name": "Set: Inna's Hold (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058537249": {"name": "Set: Jade Harvester's Mercy", "category": "Gloves", "platform": "Console"}, "2058465375": {"name": "Set: Marauder's Gloves", "category": "Gloves", "platform": "Console"}, "2058249491": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156953": {"name": "Set: Natalya's Touch (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059471611": {"name": "Set: Pride of the Invoker", "category": "Gloves", "platform": "Console"}, "2059579422": {"name": "Set: Pull of the Earth", "category": "Gloves", "platform": "Console"}, "2058393501": {"name": "Set: Raekor's Wraps", "category": "Gloves", "platform": "Console"}, "2058249489": {"name": "Set: Roland's Grasp (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "1848377457": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "1848379901": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "880593693": {"name": "Set: Sage's Grasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576615877": {"name": "Set: Sage's Purchase", "category": "Gloves", "platform": "Console"}, "2059435674": {"name": "Set: Sunwuko's Paws", "category": "Gloves", "platform": "Console"}, "-206156952": {"name": "Set: Tal Rasha's Grasp (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059543485": {"name": "Set: The Shadow's Grasp", "category": "Gloves", "platform": "Console"}, "2059507548": {"name": "Set: Vyr's Grasping Gauntlets", "category": "Gloves", "platform": "Console"}, "2058285428": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156951": {"name": "Set: Zunimassa's Finger Wraps (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "614349464": {"name": "legendary: St. Archew's Gage (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-363391670": {"name": "00: Initiate's Hand Crossbow (DPS 3.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363391669": {"name": "01: Simple Hand Crossbow (DPS 12.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363391668": {"name": "02: Light Hand Crossbow (DPS 11.2-13.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363391667": {"name": "03: Stake Thrower (DPS 12.8-15.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391666": {"name": "04: Hand Crossbow (DPS 16.0-18.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391665": {"name": "05: Slinglock (DPS 20.8-23.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391664": {"name": "06: Quillshot (DPS 24.0-26.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391663": {"name": "07: Nail Spitter (DPS 28.0-30.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391662": {"name": "08: Heavy Stake Thrower (DPS 32.8-35.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390580": {"name": "09: Sling Pistol (DPS 38.4-40.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363390579": {"name": "10: Crosslock (DPS 44.0-46.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390578": {"name": "11: Siege Lock (DPS 48.8-51.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390577": {"name": "12: Arcus (DPS 60.0-62.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390576": {"name": "13: Cranequin (DPS 65.6-68.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390575": {"name": "14: Spine Thrower (DPS 76.8-79.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390574": {"name": "15: Heavy Arcus (DPS 85.6-88.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390573": {"name": "16: Bolt Rack (DPS 98.4-100.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389491": {"name": "17: Runic Sling Pistol (DPS 113.6-116.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389490": {"name": "18: Splinter Shot (DPS 127.2-129.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389489": {"name": "19: Windlash (DPS 139.2-141.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389488": {"name": "20: Blade Spitter (DPS 154.4-156.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389487": {"name": "21: Heavy Cranequin (DPS 170.4-172.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389486": {"name": "22: Runic Arcus (DPS 196.8-199.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363389485": {"name": "23: Impellor (DPS 225.6-228.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389484": {"name": "24: Exorcist (DPS 258.4-263.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388402": {"name": "25: Lionblade Bow (DPS 516.8-519.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388401": {"name": "26: Penetrator (DPS 672.0-674.4)", "category": "Hand Crossbows", "platform": "Console"}, "1203045553": {"name": "Art Test Hand Crossbow 2", "category": "Hand Crossbows", "platform": "Console"}, "1203045554": {"name": "Art Test Hand Crossbow 3", "category": "Hand Crossbows", "platform": "Console"}, "1203045555": {"name": "Art Test Hand Crossbow 4", "category": "Hand Crossbows", "platform": "Console"}, "1203045556": {"name": "Art Test Hand Crossbow 5", "category": "Hand Crossbows", "platform": "Console"}, "1203045552": {"name": "Art Test HandCrossbow 1", "category": "Hand Crossbows", "platform": "Console"}, "-1153493044": {"name": "Legendary: Balefire Caster", "category": "Hand Crossbows", "platform": "Console"}, "589357912": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "589360356": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789444": {"name": "Legendary: Balefire Caster (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153493308": {"name": "Legendary: Balefire Caster (Patch 2.1.0)", "category": "Hand Crossbows", "platform": "Console"}, "-1153421170": {"name": "Legendary: Blitzbolter", "category": "Hand Crossbows", "platform": "Console"}, "-1152378997": {"name": "Legendary: Calamity", "category": "Hand Crossbows", "platform": "Console"}, "626121463": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "626123907": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789475": {"name": "Legendary: Calamity (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153385233": {"name": "Legendary: Dawn", "category": "Hand Crossbows", "platform": "Console"}, "592915675": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "592918119": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789447": {"name": "Legendary: Dawn (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591729754": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591732198": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789446": {"name": "Legendary: Deadeye (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114429525": {"name": "Legendary: Helltrapper", "category": "Hand Crossbows", "platform": "Console"}, "-1153457107": {"name": "Legendary: Izzuccob", "category": "Hand Crossbows", "platform": "Console"}, "590543833": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "590546277": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789445": {"name": "Legendary: Izzuccob (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114465462": {"name": "Legendary: K'mar Tenclip", "category": "Hand Crossbows", "platform": "Console"}, "-44923323": {"name": "Legendary: Quietus", "category": "Hand Crossbows", "platform": "Console"}, "-1266666515": {"name": "P2 Hand Crossbow norm Legendary 01", "category": "Hand Crossbows", "platform": "Console"}, "-1266666514": {"name": "P2 Hand Crossbow norm Legendary 02", "category": "Hand Crossbows", "platform": "Console"}, "-1266666513": {"name": "P2 Hand Crossbow norm Legendary 03", "category": "Hand Crossbows", "platform": "Console"}, "515789442": {"name": "Set: Danetta's Fury (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789441": {"name": "Set: Danetta's Rage (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153564918": {"name": "Set: Danetta's Revenge", "category": "Hand Crossbows", "platform": "Console"}, "586986070": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "586988514": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153600855": {"name": "Set: Danetta's Spite", "category": "Hand Crossbows", "platform": "Console"}, "585800149": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "585802593": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789479": {"name": "Set: Hallowed Avenger (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1152235249": {"name": "Set: Hallowed Condemnation", "category": "Hand Crossbows", "platform": "Console"}, "630865147": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "630867591": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789443": {"name": "Set: Natalya's Redemption (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153528981": {"name": "Set: Natalya's Slayer", "category": "Hand Crossbows", "platform": "Console"}, "588171991": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "588174435": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "1565454583": {"name": "02: Leather Hood (AR 21-24)", "category": "Helms", "platform": "Console"}, "1565454584": {"name": "03: Coif (AR 36-41)", "category": "Helms", "platform": "Console"}, "1565454585": {"name": "04: Arming Cap (AR 54-71)", "category": "Helms", "platform": "Console"}, "1565454586": {"name": "05: Helmet (AR 72-89)", "category": "Helms", "platform": "Console"}, "1565454587": {"name": "06: Plated Helm (AR 90-113)", "category": "Helms", "platform": "Console"}, "1565455671": {"name": "07: Crown (AR 114-137)", "category": "Helms", "platform": "Console"}, "1565455672": {"name": "08: Basinet (AR 138-161)", "category": "Helms", "platform": "Console"}, "1565455673": {"name": "09: Klappvisier (AR 162-185)", "category": "Helms", "platform": "Console"}, "1565455674": {"name": "10: Casque (AR 186-224)", "category": "Helms", "platform": "Console"}, "1565455675": {"name": "11: Great Helm (AR 225-247)", "category": "Helms", "platform": "Console"}, "1565456760": {"name": "12: Hounskull (AR 247-269)", "category": "Helms", "platform": "Console"}, "1565456761": {"name": "13: Stechhelm (AR 270-284)", "category": "Helms", "platform": "Console"}, "1565456762": {"name": "14: Zischagge (AR 285-322)", "category": "Helms", "platform": "Console"}, "1565456763": {"name": "15: Hellscape Mask (AR 322-359)", "category": "Helms", "platform": "Console"}, "1565456764": {"name": "16: Sovereign Helm (AR 360-397)", "category": "Helms", "platform": "Console"}, "1565456765": {"name": "17: Archon Crown (AR 397-471)", "category": "Helms", "platform": "Console"}, "1565456766": {"name": "18: Rakkisgard Helm (AR 472-659)", "category": "Helms", "platform": "Console"}, "1565456767": {"name": "19: Ascended Crown (AR 660-759)", "category": "Helms", "platform": "Console"}, "1422434075": {"name": "Art Test Helm 1", "category": "Helms", "platform": "Console"}, "1422434076": {"name": "Art Test Helm 2", "category": "Helms", "platform": "Console"}, "1422434077": {"name": "Art Test Helm 3", "category": "Helms", "platform": "Console"}, "1422434078": {"name": "Art Test Helm 4", "category": "Helms", "platform": "Console"}, "1422434079": {"name": "Art Test Helm 5", "category": "Helms", "platform": "Console"}, "-304315733": {"name": "Art_Test_Helm_10 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315732": {"name": "Art_Test_Helm_11 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315731": {"name": "Art_Test_Helm_12 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434080": {"name": "Art_Test_Helm_6 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434081": {"name": "Art_Test_Helm_7 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434082": {"name": "Art_Test_Helm_8 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434083": {"name": "Art_Test_Helm_9 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233654": {"name": "Legendary: Andariel's Visage", "category": "Helms", "platform": "Console"}, "-1855268606": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "-1855266162": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "1638662958": {"name": "Legendary: Andariel's Visage (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334377402": {"name": "Legendary: Blind Faith", "category": "Helms", "platform": "Console"}, "-1850524922": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "-1850522478": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "1638662962": {"name": "Legendary: Blind Faith (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334161780": {"name": "Legendary: Broken Crown", "category": "Helms", "platform": "Console"}, "-1857640448": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1857638004": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662956": {"name": "Legendary: Broken Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1046338483": {"name": "Legendary: Broken Crown (Patch 2.1.2)", "category": "Helms", "platform": "Console"}, "1239902833": {"name": "Legendary: Conqueror's Shako (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "974143057": {"name": "Legendary: Death Mask", "category": "Helms", "platform": "Console"}, "373333110": {"name": "Legendary: Deathseer's Cowl", "category": "Helms", "platform": "Console"}, "-1854082685": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "-1854080241": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "1638662959": {"name": "Legendary: Giant Skull (Old-Legacy)", "category": "Helms", "platform": "Console"}, "1571690839": {"name": "Legendary: Guardian Facade", "category": "Helms", "platform": "Console"}, "974107120": {"name": "Legendary: Hallowed Helm", "category": "Helms", "platform": "Console"}, "-843818268": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "-1425221075": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "334197717": {"name": "Legendary: Leoric's Crown", "category": "Helms", "platform": "Console"}, "-1856454527": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1856452083": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662957": {"name": "Legendary: Leoric's Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334197453": {"name": "Legendary: Leoric's Crown (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "334341465": {"name": "Legendary: Mempo of Twilight", "category": "Helms", "platform": "Console"}, "-1851710843": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "-1851708399": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "1638662961": {"name": "Legendary: Mempo of Twilight (Old-Legacy)", "category": "Helms", "platform": "Console"}, "373369047": {"name": "Legendary: Pride's Fall", "category": "Helms", "platform": "Console"}, "334269591": {"name": "Legendary: Skull of Resonance", "category": "Helms", "platform": "Console"}, "-1818505055": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "-1818502611": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "1638662989": {"name": "Legendary: The Helm of Command (Old-Legacy)", "category": "Helms", "platform": "Console"}, "335347701": {"name": "Legendary: The Helm of Rule", "category": "Helms", "platform": "Console"}, "-1993242998": {"name": "Set: Accursed Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662992": {"name": "Set: Aughild's Brow (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1814947292": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "-1814944848": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "335455512": {"name": "Set: Aughild's Spike", "category": "Helms", "platform": "Console"}, "335383638": {"name": "Set: Cain's Insight", "category": "Helms", "platform": "Console"}, "1638662990": {"name": "Set: Cain's Laurel (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1817319134": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1817316690": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1992092751": {"name": "Set: Crown of the Invoker", "category": "Helms", "platform": "Console"}, "-1993242997": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1991984940": {"name": "Set: Eyes of the Earth", "category": "Helms", "platform": "Console"}, "-1993134924": {"name": "Set: Firebird's Plume", "category": "Helms", "platform": "Console"}, "-1813761371": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "-1813758927": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "335491449": {"name": "Set: Guardian's Gaze", "category": "Helms", "platform": "Console"}, "1638662993": {"name": "Set: Guardian's Watch (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1992164625": {"name": "Set: Helm of Akkhan", "category": "Helms", "platform": "Console"}, "-1993314872": {"name": "Set: Helm of the Wastes (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334413339": {"name": "Set: Immortal King's Triumph", "category": "Helms", "platform": "Console"}, "-1849339001": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "-1849336557": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "1638662963": {"name": "Set: Immortal King's Will (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993027113": {"name": "Set: Jade Harvester's Wisdom", "category": "Helms", "platform": "Console"}, "-1993098987": {"name": "Set: Marauder's Visage", "category": "Helms", "platform": "Console"}, "-1991949003": {"name": "Set: Mask of Jeram", "category": "Helms", "platform": "Console"}, "-1993063050": {"name": "Set: Mask of the Searing Sky", "category": "Helms", "platform": "Console"}, "-1993314871": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662964": {"name": "Set: Natalya's Gaze (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334449276": {"name": "Set: Natalya's Sight", "category": "Helms", "platform": "Console"}, "-1848153080": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1848150636": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1993170861": {"name": "Set: Raekor's Will", "category": "Helms", "platform": "Console"}, "-1993314873": {"name": "Set: Roland's Visage (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "335527386": {"name": "Set: Sage's Apogee", "category": "Helms", "platform": "Console"}, "-1812575450": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "-1812573006": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "1638662994": {"name": "Set: Sage's Stones (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278935": {"name": "Set: Shrouded Mask (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1992128688": {"name": "Set: Sunwuko's Crown", "category": "Helms", "platform": "Console"}, "335311764": {"name": "Set: Tal Rasha's Guise of Wisdom", "category": "Helms", "platform": "Console"}, "-1819690976": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "-1819688532": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "1638662988": {"name": "Set: Tal Rasha's Horadric Crest (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278934": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233391": {"name": "legendary: Andariel's Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-36755477": {"name": "legendary: Helm of the Hierarch (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1575654862": {"name": "Act 1", "category": "Horadric Cache", "platform": "Console"}, "739397179": {"name": "Act 1, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1369696819": {"name": "Act 1, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1369696818": {"name": "Act 1, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1369696817": {"name": "Act 1, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1369696816": {"name": "Act 1, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1369696815": {"name": "Act 1, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654861": {"name": "Act 2", "category": "Horadric Cache", "platform": "Console"}, "408167196": {"name": "Act 2, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "584615630": {"name": "Act 2, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "584615631": {"name": "Act 2, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "584615632": {"name": "Act 2, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "584615633": {"name": "Act 2, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "584615634": {"name": "Act 2, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654860": {"name": "Act 3", "category": "Horadric Cache", "platform": "Console"}, "76937213": {"name": "Act 3, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1756039217": {"name": "Act 3, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1756039216": {"name": "Act 3, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1756039215": {"name": "Act 3, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1756039214": {"name": "Act 3, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1756039213": {"name": "Act 3, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654859": {"name": "Act 4", "category": "Horadric Cache", "platform": "Console"}, "-254292770": {"name": "Act 4, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "198273232": {"name": "Act 4, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "198273233": {"name": "Act 4, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "198273234": {"name": "Act 4, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "198273235": {"name": "Act 4, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "198273236": {"name": "Act 4, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654858": {"name": "Act 5", "category": "Horadric Cache", "platform": "Console"}, "-585522753": {"name": "Act 5, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-2142381615": {"name": "Act 5, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-2142381614": {"name": "Act 5, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-2142381613": {"name": "Act 5, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-2142381612": {"name": "Act 5, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-2142381611": {"name": "Act 5, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "1574352095": {"name": "Bonus Act", "category": "Horadric Cache", "platform": "Console"}, "1749838250": {"name": "Greater Horadric Cache", "category": "Horadric Cache", "platform": "Console"}, "1802516147": {"name": "Greater Horadric Cache Torment", "category": "Horadric Cache", "platform": "Console"}, "-1262930872": {"name": "Horadric Cache Bonus Act Torment", "category": "Horadric Cache", "platform": "Console"}, "867759243": {"name": "A2 MapVendor DungeonMap", "category": "Junk", "platform": "Console"}, "-326449293": {"name": "Arcane Globe", "category": "Junk", "platform": "Console"}, "393991529": {"name": "Art_Test_Pennant_1 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991530": {"name": "Art_Test_Pennant_2 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991531": {"name": "Art_Test_Pennant_3 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991532": {"name": "Art_Test_Pennant_4 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991533": {"name": "Art_Test_Pennant_5 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991534": {"name": "Art_Test_Pennant_6 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991535": {"name": "Art_Test_Pennant_7 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991536": {"name": "Art_Test_Pennant_8 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-215839115": {"name": "Blizzcon Artifact", "category": "Junk", "platform": "Console"}, "-1812121245": {"name": "Cauldron of Jordan", "category": "Junk", "platform": "Console"}, "-125073416": {"name": "Charm", "category": "Junk", "platform": "Console"}, "-125073414": {"name": "Crafter Skillup Page", "category": "Junk", "platform": "Console"}, "-1739891535": {"name": "CupCake05", "category": "Junk", "platform": "Console"}, "-1581845891": {"name": "CupCake10", "category": "Junk", "platform": "Console"}, "-1581845886": {"name": "CupCake15", "category": "Junk", "platform": "Console"}, "-1581845858": {"name": "CupCake20", "category": "Junk", "platform": "Console"}, "-1581845853": {"name": "CupCake25", "category": "Junk", "platform": "Console"}, "-1581845825": {"name": "CupCake30", "category": "Junk", "platform": "Console"}, "-1581845820": {"name": "CupCake35", "category": "Junk", "platform": "Console"}, "-1581845792": {"name": "CupCake40", "category": "Junk", "platform": "Console"}, "1402040296": {"name": "Damaged Chestpiece", "category": "Junk", "platform": "Console"}, "-904648741": {"name": "Debug Transmog Plan", "category": "Junk", "platform": "Console"}, "-808688257": {"name": "Event MapVendor Egg", "category": "Junk", "platform": "Console"}, "-2126877461": {"name": "Example Book", "category": "Junk", "platform": "Console"}, "126259831": {"name": "Gold1", "category": "Junk", "platform": "Console"}, "126259832": {"name": "Gold2", "category": "Junk", "platform": "Console"}, "126259833": {"name": "Gold3", "category": "Junk", "platform": "Console"}, "126259834": {"name": "Gold4", "category": "Junk", "platform": "Console"}, "126259835": {"name": "Gold5", "category": "Junk", "platform": "Console"}, "-1165367015": {"name": "Greater Health Potion", "category": "Junk", "platform": "Console"}, "-1916071921": {"name": "Health Potion", "category": "Junk", "platform": "Console"}, "2022931376": {"name": "HealthGlobe01", "category": "Junk", "platform": "Console"}, "2022931377": {"name": "HealthGlobe02", "category": "Junk", "platform": "Console"}, "2022931378": {"name": "HealthGlobe03", "category": "Junk", "platform": "Console"}, "2022931379": {"name": "HealthGlobe04", "category": "Junk", "platform": "Console"}, "2022931380": {"name": "HealthGlobe05", "category": "Junk", "platform": "Console"}, "2022931381": {"name": "HealthGlobe06", "category": "Junk", "platform": "Console"}, "2022931382": {"name": "HealthGlobe07", "category": "Junk", "platform": "Console"}, "2022931383": {"name": "HealthGlobe08", "category": "Junk", "platform": "Console"}, "2022931384": {"name": "HealthGlobe09", "category": "Junk", "platform": "Console"}, "-1962741280": {"name": "HealthGlobe10", "category": "Junk", "platform": "Console"}, "-345952752": {"name": "HealthGlobe100", "category": "Junk", "platform": "Console"}, "-1962741275": {"name": "HealthGlobe15", "category": "Junk", "platform": "Console"}, "-1962741247": {"name": "HealthGlobe20", "category": "Junk", "platform": "Console"}, "-1962741242": {"name": "HealthGlobe25", "category": "Junk", "platform": "Console"}, "-1962741214": {"name": "HealthGlobe30", "category": "Junk", "platform": "Console"}, "-1962741209": {"name": "HealthGlobe35", "category": "Junk", "platform": "Console"}, "-1962741181": {"name": "HealthGlobe40", "category": "Junk", "platform": "Console"}, "-1962741176": {"name": "HealthGlobe45", "category": "Junk", "platform": "Console"}, "-1962741148": {"name": "HealthGlobe50", "category": "Junk", "platform": "Console"}, "-1962741143": {"name": "HealthGlobe55", "category": "Junk", "platform": "Console"}, "-1962741115": {"name": "HealthGlobe60", "category": "Junk", "platform": "Console"}, "-1962741110": {"name": "HealthGlobe65", "category": "Junk", "platform": "Console"}, "-1962741082": {"name": "HealthGlobe70", "category": "Junk", "platform": "Console"}, "-1962741077": {"name": "HealthGlobe75", "category": "Junk", "platform": "Console"}, "-1962741049": {"name": "HealthGlobe80", "category": "Junk", "platform": "Console"}, "-1962741044": {"name": "HealthGlobe85", "category": "Junk", "platform": "Console"}, "-1962741016": {"name": "HealthGlobe90", "category": "Junk", "platform": "Console"}, "-1962741011": {"name": "HealthGlobe95", "category": "Junk", "platform": "Console"}, "-1703070487": {"name": "Heroic Health Potion", "category": "Junk", "platform": "Console"}, "-125073411": {"name": "Junkorama", "category": "Junk", "platform": "Console"}, "-1546488739": {"name": "Lesser Health Potion", "category": "Junk", "platform": "Console"}, "1646125768": {"name": "Major Health Potion", "category": "Junk", "platform": "Console"}, "1646417620": {"name": "Minor Health Potion", "category": "Junk", "platform": "Console"}, "522407589": {"name": "Monk Staff Pvp 001", "category": "Junk", "platform": "Console"}, "522407590": {"name": "Monk Staff Pvp 002", "category": "Junk", "platform": "Console"}, "522407591": {"name": "Monk Staff Pvp 003", "category": "Junk", "platform": "Console"}, "-1483610851": {"name": "Mythic Health Potion", "category": "Junk", "platform": "Console"}, "-125073413": {"name": "OH NOES! JUNK!", "category": "Junk", "platform": "Console"}, "-1596706792": {"name": "Orn Bag 01", "category": "Junk", "platform": "Console"}, "885847747": {"name": "Orn BlizzconPrize", "category": "Junk", "platform": "Console"}, "-125073415": {"name": "Page of Fate", "category": "Junk", "platform": "Console"}, "197999857": {"name": "Page of Useless Scribbling", "category": "Junk", "platform": "Console"}, "1249260787": {"name": "PageOfFateA", "category": "Junk", "platform": "Console"}, "-910124122": {"name": "Power Potion", "category": "Junk", "platform": "Console"}, "1921622363": {"name": "Power-Up Attack Speed", "category": "Junk", "platform": "Console"}, "-859355014": {"name": "Power-Up Cooldown Reset", "category": "Junk", "platform": "Console"}, "11858385": {"name": "Power-Up Damage", "category": "Junk", "platform": "Console"}, "455273651": {"name": "Power-Up Invulnerability", "category": "Junk", "platform": "Console"}, "-977399097": {"name": "Power-Up Stealth", "category": "Junk", "platform": "Console"}, "-1504368109": {"name": "Resplendent Health Potion", "category": "Junk", "platform": "Console"}, "1652778256": {"name": "Runic Health Potion", "category": "Junk", "platform": "Console"}, "-1277860767": {"name": "Sacred Health Potion", "category": "Junk", "platform": "Console"}, "704159709": {"name": "Scholarly Writings", "category": "Junk", "platform": "Console"}, "197999858": {"name": "ScrapPaper 02", "category": "Junk", "platform": "Console"}, "197999859": {"name": "ScrapPaper 03", "category": "Junk", "platform": "Console"}, "197999860": {"name": "ScrapPaper 04", "category": "Junk", "platform": "Console"}, "1462277166": {"name": "Scroll", "category": "Junk", "platform": "Console"}, "146554345": {"name": "Set 001 GiyuasFang", "category": "Junk", "platform": "Console"}, "1653966238": {"name": "Super Health Potion", "category": "Junk", "platform": "Console"}, "1626390053": {"name": "Talisman", "category": "Junk", "platform": "Console"}, "761573026": {"name": "The Black Rock Ledger, Page 15", "category": "Junk", "platform": "Console"}, "761573027": {"name": "The Black Rock Ledger, Page 16", "category": "Junk", "platform": "Console"}, "761573028": {"name": "The Black Rock Ledger, Page 23", "category": "Junk", "platform": "Console"}, "761573024": {"name": "The Black Rock Ledger, Page 4", "category": "Junk", "platform": "Console"}, "761573029": {"name": "The Black Rock Ledger, Page 42", "category": "Junk", "platform": "Console"}, "761573025": {"name": "The Black Rock Ledger, Page 8", "category": "Junk", "platform": "Console"}, "-2007738575": {"name": "Town Portal Stone 2", "category": "Junk", "platform": "Console"}, "-125073412": {"name": "Trunk Junk", "category": "Junk", "platform": "Console"}, "177825848": {"name": "cos_pennant_01 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825849": {"name": "cos_pennant_02 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825850": {"name": "cos_pennant_03 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825851": {"name": "cos_pennant_04 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825852": {"name": "cos_pennant_05 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-1562301750": {"name": "cos_pennant_p2_Anniversary (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "127020830": {"name": "cos_pennant_p2_Heroes (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "483403932": {"name": "Key of Bones", "category": "Keys", "platform": "Console"}, "-1088058180": {"name": "Key of Destruction", "category": "Keys", "platform": "Console"}, "113551449": {"name": "Key of Evil", "category": "Keys", "platform": "Console"}, "-1207737543": {"name": "Key of Gluttony", "category": "Keys", "platform": "Console"}, "1064300938": {"name": "Key of Hate", "category": "Keys", "platform": "Console"}, "-143133978": {"name": "Key of Terror", "category": "Keys", "platform": "Console"}, "2050794135": {"name": "Key of War", "category": "Keys", "platform": "Console"}, "1955086537": {"name": "Greater Rift Keystone Rank 01 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086538": {"name": "Greater Rift Keystone Rank 02 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086539": {"name": "Greater Rift Keystone Rank 03 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086540": {"name": "Greater Rift Keystone Rank 04 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086541": {"name": "Greater Rift Keystone Rank 05 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086542": {"name": "Greater Rift Keystone Rank 06 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086543": {"name": "Greater Rift Keystone Rank 07 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086544": {"name": "Greater Rift Keystone Rank 08 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086545": {"name": "Greater Rift Keystone Rank 09 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346329": {"name": "Greater Rift Keystone Rank 10 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1214538391": {"name": "Greater Rift Keystone Rank 100 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346330": {"name": "Greater Rift Keystone Rank 11 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346331": {"name": "Greater Rift Keystone Rank 12 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346332": {"name": "Greater Rift Keystone Rank 13 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346333": {"name": "Greater Rift Keystone Rank 14 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346334": {"name": "Greater Rift Keystone Rank 15 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346335": {"name": "Greater Rift Keystone Rank 16 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346336": {"name": "Greater Rift Keystone Rank 17 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346337": {"name": "Greater Rift Keystone Rank 18 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346338": {"name": "Greater Rift Keystone Rank 19 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346362": {"name": "Greater Rift Keystone Rank 20 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346363": {"name": "Greater Rift Keystone Rank 21 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346364": {"name": "Greater Rift Keystone Rank 22 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346365": {"name": "Greater Rift Keystone Rank 23 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346366": {"name": "Greater Rift Keystone Rank 24 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346367": {"name": "Greater Rift Keystone Rank 25 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346368": {"name": "Greater Rift Keystone Rank 26 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346369": {"name": "Greater Rift Keystone Rank 27 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346370": {"name": "Greater Rift Keystone Rank 28 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346371": {"name": "Greater Rift Keystone Rank 29 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346395": {"name": "Greater Rift Keystone Rank 30 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346396": {"name": "Greater Rift Keystone Rank 31 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346397": {"name": "Greater Rift Keystone Rank 32 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346398": {"name": "Greater Rift Keystone Rank 33 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346399": {"name": "Greater Rift Keystone Rank 34 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346400": {"name": "Greater Rift Keystone Rank 35 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346401": {"name": "Greater Rift Keystone Rank 36 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346402": {"name": "Greater Rift Keystone Rank 37 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346403": {"name": "Greater Rift Keystone Rank 38 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346404": {"name": "Greater Rift Keystone Rank 39 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346428": {"name": "Greater Rift Keystone Rank 40 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346429": {"name": "Greater Rift Keystone Rank 41 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346430": {"name": "Greater Rift Keystone Rank 42 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346431": {"name": "Greater Rift Keystone Rank 43 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346432": {"name": "Greater Rift Keystone Rank 44 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346433": {"name": "Greater Rift Keystone Rank 45 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346434": {"name": "Greater Rift Keystone Rank 46 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346435": {"name": "Greater Rift Keystone Rank 47 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346436": {"name": "Greater Rift Keystone Rank 48 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346437": {"name": "Greater Rift Keystone Rank 49 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346461": {"name": "Greater Rift Keystone Rank 50 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346462": {"name": "Greater Rift Keystone Rank 51 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346463": {"name": "Greater Rift Keystone Rank 52 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346464": {"name": "Greater Rift Keystone Rank 53 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346465": {"name": "Greater Rift Keystone Rank 54 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346466": {"name": "Greater Rift Keystone Rank 55 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346467": {"name": "Greater Rift Keystone Rank 56 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346468": {"name": "Greater Rift Keystone Rank 57 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346469": {"name": "Greater Rift Keystone Rank 58 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346470": {"name": "Greater Rift Keystone Rank 59 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346494": {"name": "Greater Rift Keystone Rank 60 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346495": {"name": "Greater Rift Keystone Rank 61 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346496": {"name": "Greater Rift Keystone Rank 62 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346497": {"name": "Greater Rift Keystone Rank 63 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346498": {"name": "Greater Rift Keystone Rank 64 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346499": {"name": "Greater Rift Keystone Rank 65 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346500": {"name": "Greater Rift Keystone Rank 66 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346501": {"name": "Greater Rift Keystone Rank 67 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346502": {"name": "Greater Rift Keystone Rank 68 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346503": {"name": "Greater Rift Keystone Rank 69 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346527": {"name": "Greater Rift Keystone Rank 70 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346528": {"name": "Greater Rift Keystone Rank 71 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346529": {"name": "Greater Rift Keystone Rank 72 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346530": {"name": "Greater Rift Keystone Rank 73 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346531": {"name": "Greater Rift Keystone Rank 74 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346532": {"name": "Greater Rift Keystone Rank 75 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346533": {"name": "Greater Rift Keystone Rank 76 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346534": {"name": "Greater Rift Keystone Rank 77 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346535": {"name": "Greater Rift Keystone Rank 78 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346536": {"name": "Greater Rift Keystone Rank 79 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346560": {"name": "Greater Rift Keystone Rank 80 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346561": {"name": "Greater Rift Keystone Rank 81 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346562": {"name": "Greater Rift Keystone Rank 82 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346563": {"name": "Greater Rift Keystone Rank 83 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346564": {"name": "Greater Rift Keystone Rank 84 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346565": {"name": "Greater Rift Keystone Rank 85 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346566": {"name": "Greater Rift Keystone Rank 86 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346567": {"name": "Greater Rift Keystone Rank 87 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346568": {"name": "Greater Rift Keystone Rank 88 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346569": {"name": "Greater Rift Keystone Rank 89 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346593": {"name": "Greater Rift Keystone Rank 90 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346594": {"name": "Greater Rift Keystone Rank 91 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346595": {"name": "Greater Rift Keystone Rank 92 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346596": {"name": "Greater Rift Keystone Rank 93 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346597": {"name": "Greater Rift Keystone Rank 94 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346598": {"name": "Greater Rift Keystone Rank 95 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346599": {"name": "Greater Rift Keystone Rank 96 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346600": {"name": "Greater Rift Keystone Rank 97 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346601": {"name": "Greater Rift Keystone Rank 98 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346602": {"name": "Greater Rift Keystone Rank 99 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086536": {"name": "Keystone of Trials (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1698136228": {"name": "Rift Keys", "category": "Keystones", "platform": "Console"}, "925362070": {"name": "A2 Oasis KamyrsOrders", "category": "Lore", "platform": "Console"}, "-1194932976": {"name": "A2 Oasis KamyrsOrdersTwo", "category": "Lore", "platform": "Console"}, "192275875": {"name": "A2 TemplarBackstory 3 Landus's Diary", "category": "Lore", "platform": "Console"}, "-1883980626": {"name": "A3 Battlefields Supply WagonDiaries", "category": "Lore", "platform": "Console"}, "1740306889": {"name": "A4 Hub OldCouple 1", "category": "Lore", "platform": "Console"}, "-1764974213": {"name": "Adria ZoltunKulle2", "category": "Lore", "platform": "Console"}, "103300821": {"name": "Adria: Adria's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-776544373": {"name": "Adria: Adria's Journal, Part 2", "category": "Lore", "platform": "Console"}, "133385135": {"name": "Adria: Adria's Journal, Part 3", "category": "Lore", "platform": "Console"}, "133390039": {"name": "Adria: Adria's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1890330185": {"name": "Adria: Adria's Journal, Part 5", "category": "Lore", "platform": "Console"}, "127066864": {"name": "Adria: Adria's Journal, Part 6", "category": "Lore", "platform": "Console"}, "733368986": {"name": "Adria: Adria's Journal, Part 7", "category": "Lore", "platform": "Console"}, "100959118": {"name": "Adria: Adria's Journal, Part 8", "category": "Lore", "platform": "Console"}, "133600747": {"name": "Adria: Adria's Journal, Part 9", "category": "Lore", "platform": "Console"}, "133313247": {"name": "Adria: Adria's Note", "category": "Lore", "platform": "Console"}, "954251807": {"name": "Adria: Adria's Purpose", "category": "Lore", "platform": "Console"}, "900358318": {"name": "AdventureMode: A New Era", "category": "Lore", "platform": "Console"}, "-282286736": {"name": "AdventureMode: An Eternity of Agony", "category": "Lore", "platform": "Console"}, "1375431349": {"name": "AdventureMode: Impossibilities", "category": "Lore", "platform": "Console"}, "-1315225766": {"name": "AdventureMode: The Nephalem", "category": "Lore", "platform": "Console"}, "501220619": {"name": "AngirisCouncil: The Angiris Council", "category": "Lore", "platform": "Console"}, "-1383924340": {"name": "AngirisCouncil: The Archangel Auriel", "category": "Lore", "platform": "Console"}, "260686328": {"name": "AngirisCouncil: The Archangel Imperius", "category": "Lore", "platform": "Console"}, "397935128": {"name": "AngirisCouncil: The Archangel Itherael", "category": "Lore", "platform": "Console"}, "478898578": {"name": "AngirisCouncil: The Archangel Malthael", "category": "Lore", "platform": "Console"}, "-635616901": {"name": "AngirisCouncil: The Archangel Tyrael", "category": "Lore", "platform": "Console"}, "-164029999": {"name": "Aqueducts: The Desert Aqueducts, Part 1", "category": "Lore", "platform": "Console"}, "-164029998": {"name": "Aqueducts: The Desert Aqueducts, Part 2", "category": "Lore", "platform": "Console"}, "-714930281": {"name": "Armorer: Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "-1385743634": {"name": "Azmodan: Orders from Azmodan, Part 1", "category": "Lore", "platform": "Console"}, "-1385743633": {"name": "Azmodan: Orders from Azmodan, Part 2", "category": "Lore", "platform": "Console"}, "-1385743632": {"name": "Azmodan: Orders from Azmodan, Part 3", "category": "Lore", "platform": "Console"}, "-1385743631": {"name": "Azmodan: Orders from Azmodan, Part 4", "category": "Lore", "platform": "Console"}, "-1385743630": {"name": "Azmodan: Orders from Azmodan, Part 5", "category": "Lore", "platform": "Console"}, "-1385743629": {"name": "Azmodan: Orders from Azmodan, Part 6", "category": "Lore", "platform": "Console"}, "-1312231117": {"name": "Belial: Deceivers' Orders, Part 1", "category": "Lore", "platform": "Console"}, "-1346161479": {"name": "Belial: Deceivers' Orders, Part 2", "category": "Lore", "platform": "Console"}, "-661262942": {"name": "Belial: Deceivers' Orders, Part 3", "category": "Lore", "platform": "Console"}, "-978510227": {"name": "Belial: Guard's Orders", "category": "Lore", "platform": "Console"}, "1488385291": {"name": "Belial: Missive to Maghda, Part 1", "category": "Lore", "platform": "Console"}, "1488385292": {"name": "Belial: Missive to Maghda, Part 2", "category": "Lore", "platform": "Console"}, "10458238": {"name": "Belial: Proclamation from the Imperial Guard", "category": "Lore", "platform": "Console"}, "621163016": {"name": "Bestiary: Anarch", "category": "Lore", "platform": "Console"}, "515122494": {"name": "Bestiary: Armored Destroyer", "category": "Lore", "platform": "Console"}, "-1478953705": {"name": "Bestiary: Barbed Lurker", "category": "Lore", "platform": "Console"}, "1467646658": {"name": "Bestiary: Beast", "category": "Lore", "platform": "Console"}, "231471423": {"name": "Bestiary: Bile Crawler", "category": "Lore", "platform": "Console"}, "1675636673": {"name": "Bestiary: Blood Clan Khazra", "category": "Lore", "platform": "Console"}, "1675805102": {"name": "Bestiary: Blood Hawk", "category": "Lore", "platform": "Console"}, "2132231168": {"name": "Bestiary: Bogan Trapper", "category": "Lore", "platform": "Console"}, "661688183": {"name": "Bestiary: Boggit", "category": "Lore", "platform": "Console"}, "-1697636392": {"name": "Bestiary: Carrion Bat", "category": "Lore", "platform": "Console"}, "-186990405": {"name": "Bestiary: Carrion Nest", "category": "Lore", "platform": "Console"}, "1864365917": {"name": "Bestiary: Colossal Golgor", "category": "Lore", "platform": "Console"}, "-899331059": {"name": "Bestiary: Corpse Raiser", "category": "Lore", "platform": "Console"}, "-563018536": {"name": "Bestiary: Dark Berserker", "category": "Lore", "platform": "Console"}, "-1824883589": {"name": "Bestiary: Dark Cultist", "category": "Lore", "platform": "Console"}, "1971053797": {"name": "Bestiary: Dark Vessel", "category": "Lore", "platform": "Console"}, "-985860913": {"name": "Bestiary: Death Maiden", "category": "Lore", "platform": "Console"}, "610441837": {"name": "Bestiary: Deceivers", "category": "Lore", "platform": "Console"}, "-1937284463": {"name": "Bestiary: Demon Trooper", "category": "Lore", "platform": "Console"}, "478100232": {"name": "Bestiary: Demonic Hell Bearer", "category": "Lore", "platform": "Console"}, "-140849528": {"name": "Bestiary: Demonic Hellflyer", "category": "Lore", "platform": "Console"}, "2144349771": {"name": "Bestiary: Demonic Tremor", "category": "Lore", "platform": "Console"}, "1641498900": {"name": "Bestiary: Dune Dervish", "category": "Lore", "platform": "Console"}, "1184767076": {"name": "Bestiary: Dune Thresher", "category": "Lore", "platform": "Console"}, "-525114375": {"name": "Bestiary: Dust Imp", "category": "Lore", "platform": "Console"}, "-1086668012": {"name": "Bestiary: Electric Eel", "category": "Lore", "platform": "Console"}, "90729293": {"name": "Bestiary: Enraged Phantasm", "category": "Lore", "platform": "Console"}, "-1878606908": {"name": "Bestiary: Enslaved Nightmare", "category": "Lore", "platform": "Console"}, "789563798": {"name": "Bestiary: Exarch", "category": "Lore", "platform": "Console"}, "-1299022938": {"name": "Bestiary: Executioner", "category": "Lore", "platform": "Console"}, "1389417324": {"name": "Bestiary: Exorcist", "category": "Lore", "platform": "Console"}, "163638005": {"name": "Bestiary: Fallen Grunt", "category": "Lore", "platform": "Console"}, "84174677": {"name": "Bestiary: Fallen Lunatic", "category": "Lore", "platform": "Console"}, "1562132029": {"name": "Bestiary: Fallen Shaman", "category": "Lore", "platform": "Console"}, "-990665261": {"name": "Bestiary: Flesh Gorger", "category": "Lore", "platform": "Console"}, "-944408897": {"name": "Bestiary: Flesh Hurler", "category": "Lore", "platform": "Console"}, "-529946523": {"name": "Bestiary: Flesh Shaman", "category": "Lore", "platform": "Console"}, "1473699320": {"name": "Bestiary: Ghost", "category": "Lore", "platform": "Console"}, "1473699378": {"name": "Bestiary: Ghoul", "category": "Lore", "platform": "Console"}, "1067328402": {"name": "Bestiary: Grotesque", "category": "Lore", "platform": "Console"}, "-288964962": {"name": "Bestiary: Hellion", "category": "Lore", "platform": "Console"}, "-675600988": {"name": "Bestiary: Herald of Pestilence", "category": "Lore", "platform": "Console"}, "-1778975775": {"name": "Bestiary: Hound Pack Leader", "category": "Lore", "platform": "Console"}, "-1864253371": {"name": "Bestiary: Hulking Phasebeast", "category": "Lore", "platform": "Console"}, "1270376265": {"name": "Bestiary: Imp", "category": "Lore", "platform": "Console"}, "1543483412": {"name": "Bestiary: Khazra", "category": "Lore", "platform": "Console"}, "1080209708": {"name": "Bestiary: Khazra Shaman", "category": "Lore", "platform": "Console"}, "1574383663": {"name": "Bestiary: Lacuni", "category": "Lore", "platform": "Console"}, "1277879248": {"name": "Bestiary: Maggot Brood", "category": "Lore", "platform": "Console"}, "-1289421300": {"name": "Bestiary: Primordial Scavenger", "category": "Lore", "platform": "Console"}, "-683087584": {"name": "Bestiary: Quill Fiend", "category": "Lore", "platform": "Console"}, "2123300624": {"name": "Bestiary: Revenant Soldier", "category": "Lore", "platform": "Console"}, "2139220569": {"name": "Bestiary: Risen Dead", "category": "Lore", "platform": "Console"}, "-286364985": {"name": "Bestiary: Rockworm", "category": "Lore", "platform": "Console"}, "507308136": {"name": "Bestiary: Sand Dweller", "category": "Lore", "platform": "Console"}, "-1096104684": {"name": "Bestiary: Sand Wasp", "category": "Lore", "platform": "Console"}, "1312554887": {"name": "Bestiary: Scarab", "category": "Lore", "platform": "Console"}, "-1399846223": {"name": "Bestiary: Scavenger", "category": "Lore", "platform": "Console"}, "2067382477": {"name": "Bestiary: Scavenging Tunneler", "category": "Lore", "platform": "Console"}, "-458569087": {"name": "Bestiary: Scouring Charger", "category": "Lore", "platform": "Console"}, "-1529207830": {"name": "Bestiary: Shadow Vermin", "category": "Lore", "platform": "Console"}, "-1715924548": {"name": "Bestiary: Shadow of Death", "category": "Lore", "platform": "Console"}, "1905172061": {"name": "Bestiary: Shrieking Terror", "category": "Lore", "platform": "Console"}, "56567324": {"name": "Bestiary: Siegebreaker Assault Beast", "category": "Lore", "platform": "Console"}, "-387707041": {"name": "Bestiary: Skeletal Beast", "category": "Lore", "platform": "Console"}, "494193920": {"name": "Bestiary: Skeletal Crawler", "category": "Lore", "platform": "Console"}, "-313234093": {"name": "Bestiary: Skeletal Guardian", "category": "Lore", "platform": "Console"}, "-1409684360": {"name": "Bestiary: Skeleton", "category": "Lore", "platform": "Console"}, "1170383240": {"name": "Bestiary: Soul Ripper", "category": "Lore", "platform": "Console"}, "1866317050": {"name": "Bestiary: Spider", "category": "Lore", "platform": "Console"}, "564441124": {"name": "Bestiary: Spiderling", "category": "Lore", "platform": "Console"}, "-330757856": {"name": "Bestiary: Stinging Swarm", "category": "Lore", "platform": "Console"}, "-458677543": {"name": "Bestiary: Subjugator", "category": "Lore", "platform": "Console"}, "-1468295040": {"name": "Bestiary: Succubus", "category": "Lore", "platform": "Console"}, "-513840200": {"name": "Bestiary: Summoned Archer", "category": "Lore", "platform": "Console"}, "166255055": {"name": "Bestiary: Summoned Shield Guard", "category": "Lore", "platform": "Console"}, "1887856949": {"name": "Bestiary: Summoned Soldier", "category": "Lore", "platform": "Console"}, "920539156": {"name": "Bestiary: Summoner of the Dead", "category": "Lore", "platform": "Console"}, "166186064": {"name": "Bestiary: Terror Demon", "category": "Lore", "platform": "Console"}, "-1551452867": {"name": "Bestiary: The Accursed", "category": "Lore", "platform": "Console"}, "1613832402": {"name": "Bestiary: The Mallet Lords", "category": "Lore", "platform": "Console"}, "1481069442": {"name": "Bestiary: The Morlu", "category": "Lore", "platform": "Console"}, "1727215776": {"name": "Bestiary: The Oppressors", "category": "Lore", "platform": "Console"}, "-1569107231": {"name": "Bestiary: Tormented Stinger", "category": "Lore", "platform": "Console"}, "692217017": {"name": "Bestiary: Treasure Goblin", "category": "Lore", "platform": "Console"}, "1112087602": {"name": "Bestiary: Tusked Bogan", "category": "Lore", "platform": "Console"}, "1695981553": {"name": "Bestiary: Unburied", "category": "Lore", "platform": "Console"}, "181747316": {"name": "Bestiary: Vicious Hound", "category": "Lore", "platform": "Console"}, "191466402": {"name": "Bestiary: Vile Bat", "category": "Lore", "platform": "Console"}, "1295465786": {"name": "Bestiary: Warscarred Marauder", "category": "Lore", "platform": "Console"}, "-1568007631": {"name": "Bestiary: Warscarred Ravager", "category": "Lore", "platform": "Console"}, "1809929374": {"name": "Bestiary: Winged Assassin", "category": "Lore", "platform": "Console"}, "-1414985342": {"name": "Bestiary: Winged Talus", "category": "Lore", "platform": "Console"}, "1562746110": {"name": "Bestiary: Withermoth", "category": "Lore", "platform": "Console"}, "1892963547": {"name": "Bestiary: Wood Wraith", "category": "Lore", "platform": "Console"}, "1470131000": {"name": "Bestiary: Wretched Mother", "category": "Lore", "platform": "Console"}, "2033922302": {"name": "Butcher: Butcher", "category": "Lore", "platform": "Console"}, "3246582303": {"name": "Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "4058000945": {"name": "Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "554362535": {"name": "Cain: Deckard Cain's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1114094521": {"name": "Cain: Deckard Cain's Journal, Part 2", "category": "Lore", "platform": "Console"}, "828022511": {"name": "Caldeum: An Abridged History of Caldeum, Part 1", "category": "Lore", "platform": "Console"}, "828022512": {"name": "Caldeum: An Abridged History of Caldeum, Part 2", "category": "Lore", "platform": "Console"}, "828022513": {"name": "Caldeum: An Abridged History of Caldeum, Part 3", "category": "Lore", "platform": "Console"}, "828022514": {"name": "Caldeum: An Abridged History of Caldeum, Part 4", "category": "Lore", "platform": "Console"}, "828022515": {"name": "Caldeum: An Abridged History of Caldeum, Part 5", "category": "Lore", "platform": "Console"}, "828022516": {"name": "Caldeum: An Abridged History of Caldeum, Part 6", "category": "Lore", "platform": "Console"}, "344927641": {"name": "CaliphateSardar: The Musings of Caliphate Sardar", "category": "Lore", "platform": "Console"}, "-1106917318": {"name": "CampCultist: The Feared Hero", "category": "Lore", "platform": "Console"}, "-668215174": {"name": "CellarMadman: The Ravings of a Deranged Mind", "category": "Lore", "platform": "Console"}, "-1518383148": {"name": "CemeteryCrypts: Gravedigger's Log", "category": "Lore", "platform": "Console"}, "-727194820": {"name": "Challenge: Nephalem Rifts", "category": "Lore", "platform": "Console"}, "2125283571": {"name": "Crusader: The Crusaders, Part 1", "category": "Lore", "platform": "Console"}, "2125283572": {"name": "Crusader: The Crusaders, Part 2", "category": "Lore", "platform": "Console"}, "2125283573": {"name": "Crusader: The Crusaders, Part 3", "category": "Lore", "platform": "Console"}, "2125283574": {"name": "Crusader: The Crusaders, Part 4", "category": "Lore", "platform": "Console"}, "2125283575": {"name": "Crusader: The Crusaders, Part 5", "category": "Lore", "platform": "Console"}, "2125283576": {"name": "Crusader: The Crusaders, Part 6", "category": "Lore", "platform": "Console"}, "2125283577": {"name": "Crusader: The Crusaders, Part 7", "category": "Lore", "platform": "Console"}, "2125283578": {"name": "Crusader: The Crusaders, Part 8", "category": "Lore", "platform": "Console"}, "2125283579": {"name": "Crusader: The Crusaders, Part 9", "category": "Lore", "platform": "Console"}, "-186854830": {"name": "CultCrown: Cultist Orders", "category": "Lore", "platform": "Console"}, "4108112466": {"name": "Cultist Orders", "category": "Lore", "platform": "Console"}, "504852499": {"name": "CurioVendor: Adenah's Jottings", "category": "Lore", "platform": "Console"}, "-1717171528": {"name": "Cydaea: Cydaea, the Maiden of Lust", "category": "Lore", "platform": "Console"}, "1958060101": {"name": "DahlgurOasis: The Dahlgur Oasis", "category": "Lore", "platform": "Console"}, "-1010870335": {"name": "DarkZealot: Report from Wortham", "category": "Lore", "platform": "Console"}, "-819413474": {"name": "Deserter: Deserter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-819413473": {"name": "Deserter: Deserter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-819413472": {"name": "Deserter: Deserter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-819413471": {"name": "Deserter: Deserter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-819413470": {"name": "Deserter: Deserter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "1121720780": {"name": "DesolateSands: On the Desolate Sands, Part 1", "category": "Lore", "platform": "Console"}, "1121720781": {"name": "DesolateSands: On the Desolate Sands, Part 2", "category": "Lore", "platform": "Console"}, "1121720782": {"name": "DesolateSands: On the Desolate Sands, Part 3", "category": "Lore", "platform": "Console"}, "2388677118": {"name": "Despina's Journal", "category": "Lore", "platform": "Console"}, "1244727565": {"name": "DevilsHand: Implements of the Dark Coven", "category": "Lore", "platform": "Console"}, "1244727564": {"name": "DevilsHand: The Black King's Reign", "category": "Lore", "platform": "Console"}, "1244727563": {"name": "DevilsHand: The Covenant's Search", "category": "Lore", "platform": "Console"}, "172363859": {"name": "DoomedWoman: The Horrible Secret", "category": "Lore", "platform": "Console"}, "-1577589110": {"name": "Enchantress: Eirena's Journal", "category": "Lore", "platform": "Console"}, "2168089835": {"name": "Example Book", "category": "Lore", "platform": "Console"}, "1850500833": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 1", "category": "Lore", "platform": "Console"}, "1850500834": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 2", "category": "Lore", "platform": "Console"}, "1850500835": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 3", "category": "Lore", "platform": "Console"}, "1850500836": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 4", "category": "Lore", "platform": "Console"}, "1850500837": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 5", "category": "Lore", "platform": "Console"}, "1814333430": {"name": "FieldsofMisery: Tristram Fields", "category": "Lore", "platform": "Console"}, "-821793924": {"name": "Ghom: Ghom, the Lord of Gluttony", "category": "Lore", "platform": "Console"}, "-681952308": {"name": "GluttonysLog: Ghom's Log", "category": "Lore", "platform": "Console"}, "1895762819": {"name": "GoatmenHunter: Khazra Heads Wanted", "category": "Lore", "platform": "Console"}, "1895762820": {"name": "GoatmenHunter: Researching the Khazra", "category": "Lore", "platform": "Console"}, "1895762821": {"name": "GoatmenHunter: The Khazra Massacre", "category": "Lore", "platform": "Console"}, "-1085616825": {"name": "Halls_of_Agony: Command from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "-1085616824": {"name": "Halls_of_Agony: Reply from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "721065374": {"name": "HangingTree: The Hanging Tree", "category": "Lore", "platform": "Console"}, "4006002334": {"name": "Hellion", "category": "Lore", "platform": "Console"}, "1555542539": {"name": "Hermit_Caves: Hermit's Ravings", "category": "Lore", "platform": "Console"}, "-578368437": {"name": "HexMaze: Melaina's Memory", "category": "Lore", "platform": "Console"}, "-578368438": {"name": "HexMaze: Raissa's Memory", "category": "Lore", "platform": "Console"}, "-578368439": {"name": "HexMaze: Sibyl's Thoughts", "category": "Lore", "platform": "Console"}, "2145056291": {"name": "Highlands: The Highlands", "category": "Lore", "platform": "Console"}, "174686246": {"name": "HuntersJournal: Hunter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "174686247": {"name": "HuntersJournal: Hunter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "174686248": {"name": "HuntersJournal: Hunter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "174686249": {"name": "HuntersJournal: Hunter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "174686250": {"name": "HuntersJournal: Hunter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "174686251": {"name": "HuntersJournal: Hunter's Journal, Part 6", "category": "Lore", "platform": "Console"}, "-799754755": {"name": "Inarius: The Creation of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "-799754754": {"name": "Inarius: The Creation of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "-799754753": {"name": "Inarius: The Creation of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "-799754752": {"name": "Inarius: The Creation of Sanctuary, Part 4", "category": "Lore", "platform": "Console"}, "194883964": {"name": "Inarius: The Testament of Inarius, Part 1", "category": "Lore", "platform": "Console"}, "194883965": {"name": "Inarius: The Testament of Inarius, Part 2", "category": "Lore", "platform": "Console"}, "194883966": {"name": "Inarius: The Testament of Inarius, Part 3", "category": "Lore", "platform": "Console"}, "194883967": {"name": "Inarius: The Testament of Inarius, Part 4", "category": "Lore", "platform": "Console"}, "194883968": {"name": "Inarius: The Testament of Inarius, Part 5", "category": "Lore", "platform": "Console"}, "194883969": {"name": "Inarius: The Testament of Inarius, Part 6", "category": "Lore", "platform": "Console"}, "194883970": {"name": "Inarius: The Testament of Inarius, Part 7", "category": "Lore", "platform": "Console"}, "-1346370762": {"name": "Izual: Izual's Descent", "category": "Lore", "platform": "Console"}, "28868489": {"name": "Jeweler: Journal of Covetous Shen", "category": "Lore", "platform": "Console"}, "1221720352": {"name": "Jeweler: The Legend of Zei the Trickster", "category": "Lore", "platform": "Console"}, "-329801970": {"name": "Kala: Kala's Poem", "category": "Lore", "platform": "Console"}, "-355886665": {"name": "KeepHistory: The History of Bastion's Keep", "category": "Lore", "platform": "Console"}, "815737414": {"name": "KhanDakab: Last Will of Khan Dakab", "category": "Lore", "platform": "Console"}, "378673143": {"name": "KidVendor: Larra's Diary", "category": "Lore", "platform": "Console"}, "-1755180605": {"name": "Kingsport: Kingsport Bill", "category": "Lore", "platform": "Console"}, "-1156197446": {"name": "Kulle: Kulle's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1156197445": {"name": "Kulle: Kulle's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1156197444": {"name": "Kulle: Kulle's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-1156197443": {"name": "Kulle: Kulle's Journal, Part 4", "category": "Lore", "platform": "Console"}, "2698411174": {"name": "Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "3758420764": {"name": "Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "3768800974": {"name": "Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "3768800975": {"name": "Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "3768800976": {"name": "Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "3768800977": {"name": "Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "-1596556122": {"name": "Lachdanan: Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "-536546532": {"name": "Lachdanan: Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "-526166322": {"name": "Lachdanan: Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "-526166321": {"name": "Lachdanan: Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "-526166320": {"name": "Lachdanan: Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "-526166319": {"name": "Lachdanan: Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "1554177638": {"name": "LastAncient: The Last of the Ancients", "category": "Lore", "platform": "Console"}, "1905436671": {"name": "Lazarus: A Page from Lazarus's Grimoire", "category": "Lore", "platform": "Console"}, "3272862989": {"name": "Leah's Journal, Part 1", "category": "Lore", "platform": "Console"}, "3272868741": {"name": "Leah's Journal, Part 2", "category": "Lore", "platform": "Console"}, "3625638211": {"name": "Leah's Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922967": {"name": "Leah: Leah's Caldeum Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922968": {"name": "Leah: Leah's Caldeum Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922969": {"name": "Leah: Leah's Caldeum Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922970": {"name": "Leah: Leah's Caldeum Journal, Part 4", "category": "Lore", "platform": "Console"}, "891922971": {"name": "Leah: Leah's Caldeum Journal, Part 5", "category": "Lore", "platform": "Console"}, "891922972": {"name": "Leah: Leah's Keep Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922973": {"name": "Leah: Leah's Keep Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922974": {"name": "Leah: Leah's Keep Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922975": {"name": "Leah: Leah's Keep Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1022104307": {"name": "Leah: Leah's Tristram Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1022098555": {"name": "Leah: Leah's Tristram Journal, Part 2", "category": "Lore", "platform": "Console"}, "-669329085": {"name": "Leah: Leah's Tristram Journal, Part 3", "category": "Lore", "platform": "Console"}, "629974535": {"name": "Leah: Leah's Tristram Journal, Part 4", "category": "Lore", "platform": "Console"}, "629968021": {"name": "Leah: Leah's Tristram Journal, Part 5", "category": "Lore", "platform": "Console"}, "-1022100097": {"name": "Leah: Leah's Tristram Journal, Part 6", "category": "Lore", "platform": "Console"}, "-670618452": {"name": "Leah: Leah's Tristram Journal, Part 7", "category": "Lore", "platform": "Console"}, "2951326394": {"name": "Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1091428479": {"name": "Leoric: A Prisoner's Journal", "category": "Lore", "platform": "Console"}, "-1343640902": {"name": "Leoric: Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1561062717": {"name": "Leoric: Leoric's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1561062718": {"name": "Leoric: Leoric's Journal, Part 2", "category": "Lore", "platform": "Console"}, "1561062719": {"name": "Leoric: Leoric's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561062720": {"name": "Leoric: Leoric's Journal, Part 4", "category": "Lore", "platform": "Console"}, "1561062721": {"name": "Leoric: Leoric's Journal, Part 5", "category": "Lore", "platform": "Console"}, "342313869": {"name": "Leoric: Leoric's Relic", "category": "Lore", "platform": "Console"}, "164674838": {"name": "Leoric: The Death of King Leoric", "category": "Lore", "platform": "Console"}, "82422929": {"name": "Leoric: Torn Letter", "category": "Lore", "platform": "Console"}, "82422930": {"name": "Leoric: Torn Letter's Response", "category": "Lore", "platform": "Console"}, "1354656263": {"name": "Lilith: The Writings of Lilith, Part 1", "category": "Lore", "platform": "Console"}, "1354656264": {"name": "Lilith: The Writings of Lilith, Part 2", "category": "Lore", "platform": "Console"}, "1354656265": {"name": "Lilith: The Writings of Lilith, Part 3", "category": "Lore", "platform": "Console"}, "1354656266": {"name": "Lilith: The Writings of Lilith, Part 4", "category": "Lore", "platform": "Console"}, "2145180345": {"name": "LordofFools: Lord Kertis's Journal", "category": "Lore", "platform": "Console"}, "704654350": {"name": "LordsofHell: Andariel, the Maiden of Anguish", "category": "Lore", "platform": "Console"}, "-408914888": {"name": "LordsofHell: Azmodan, the Lord of Sin", "category": "Lore", "platform": "Console"}, "-1390665602": {"name": "LordsofHell: Baal, the Lord of Destruction", "category": "Lore", "platform": "Console"}, "1693753943": {"name": "LordsofHell: Belial, the Lord of Lies", "category": "Lore", "platform": "Console"}, "1776365849": {"name": "LordsofHell: Diablo, the Lord of Terror", "category": "Lore", "platform": "Console"}, "1791215219": {"name": "LordsofHell: Duriel, the Lord of Pain", "category": "Lore", "platform": "Console"}, "-1530801161": {"name": "LordsofHell: Mephisto, the Lord of Hatred", "category": "Lore", "platform": "Console"}, "1361465018": {"name": "LordsofHell: The Seven Lords of Hell", "category": "Lore", "platform": "Console"}, "1775133212": {"name": "Lore CainLetter", "category": "Lore", "platform": "Console"}, "1615247495": {"name": "Lore Catacombs NephDefenseSystem", "category": "Lore", "platform": "Console"}, "-1084060684": {"name": "Lore Festering CryptOfTheAncients", "category": "Lore", "platform": "Console"}, "108864625": {"name": "Lore Festering DrownedTemple", "category": "Lore", "platform": "Console"}, "-740914034": {"name": "Lore Festering WarriorsRest", "category": "Lore", "platform": "Console"}, "2011207568": {"name": "Lore X1 Bog Ideation AdriaSpikeChest", "category": "Lore", "platform": "Console"}, "216459655": {"name": "Lore X1 Graveyard Azthar", "category": "Lore", "platform": "Console"}, "-827657709": {"name": "Lore X1 Westm Legendary Drop", "category": "Lore", "platform": "Console"}, "-1004685329": {"name": "Lore x1 MysticIntro1", "category": "Lore", "platform": "Console"}, "-1004685328": {"name": "Lore x1 MysticIntro2", "category": "Lore", "platform": "Console"}, "-2124310248": {"name": "Lore_p2_DateDungeon_CovenPlans (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "-1307619936": {"name": "Lore_p2_ScoundrelEvent02_SimonNote (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "1390356236": {"name": "LostAngel: The Lost Warrior", "category": "Lore", "platform": "Console"}, "1487246296": {"name": "LoveLetter: A Love Letter", "category": "Lore", "platform": "Console"}, "-184131088": {"name": "MaghdaManor: Orders from Maghda", "category": "Lore", "platform": "Console"}, "18980873": {"name": "Malthael: The Path of Wisdom, Part 1", "category": "Lore", "platform": "Console"}, "18980874": {"name": "Malthael: The Path of Wisdom, Part 2", "category": "Lore", "platform": "Console"}, "18980875": {"name": "Malthael: The Path of Wisdom, Part 3", "category": "Lore", "platform": "Console"}, "18980876": {"name": "Malthael: The Path of Wisdom, Part 4", "category": "Lore", "platform": "Console"}, "18980877": {"name": "Malthael: The Path of Wisdom, Part 5", "category": "Lore", "platform": "Console"}, "18980878": {"name": "Malthael: The Path of Wisdom, Part 6", "category": "Lore", "platform": "Console"}, "3897062066": {"name": "Mira's Letter to Haedrig", "category": "Lore", "platform": "Console"}, "-768304375": {"name": "MisguidedFarmer: Farmer's Journal", "category": "Lore", "platform": "Console"}, "-1595216991": {"name": "Morgan: Morgan's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1595216990": {"name": "Morgan: Morgan's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1595216989": {"name": "Morgan: Morgan's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561999134": {"name": "Necromancer: Necromancer's Log", "category": "Lore", "platform": "Console"}, "1036599468": {"name": "Nephalem: The Destiny of the Nephalem, Part 1", "category": "Lore", "platform": "Console"}, "1036599469": {"name": "Nephalem: The Destiny of the Nephalem, Part 2", "category": "Lore", "platform": "Console"}, "1036599470": {"name": "Nephalem: The Destiny of the Nephalem, Part 3", "category": "Lore", "platform": "Console"}, "85406869": {"name": "Nephalem: The Drowned Temple", "category": "Lore", "platform": "Console"}, "1604771305": {"name": "Nephalem: The Last Stand of the Ancients", "category": "Lore", "platform": "Console"}, "1071008887": {"name": "Nephalem: The Nephalem Tome", "category": "Lore", "platform": "Console"}, "220221847": {"name": "Nephalem: Tomb Robber's Journal", "category": "Lore", "platform": "Console"}, "429729842": {"name": "Nephalem: Warrior's Rest", "category": "Lore", "platform": "Console"}, "-1608490938": {"name": "NephalemMiser: Miser's Will", "category": "Lore", "platform": "Console"}, "775555921": {"name": "NewTristram: New Tristram", "category": "Lore", "platform": "Console"}, "-1083079452": {"name": "Note: Secret Note", "category": "Lore", "platform": "Console"}, "1316599940": {"name": "Oasis: A Love Letter", "category": "Lore", "platform": "Console"}, "1676339915": {"name": "OasisCellars: The Imperial Guard's Orders", "category": "Lore", "platform": "Console"}, "-1048384993": {"name": "OldTristram: Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "-236966351": {"name": "OldTristram: Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1906290178": {"name": "OldTristram: Despina's Journal", "category": "Lore", "platform": "Console"}, "829218340": {"name": "OldTristram: Gillian's Diary, Part 1", "category": "Lore", "platform": "Console"}, "1594401494": {"name": "OldTristram: Gillian's Diary, Part 2", "category": "Lore", "platform": "Console"}, "316278028": {"name": "OldTristram: Lost Journal", "category": "Lore", "platform": "Console"}, "316278029": {"name": "OldTristram: Old Diary", "category": "Lore", "platform": "Console"}, "316278027": {"name": "OldTristram: Old Tristram Journal", "category": "Lore", "platform": "Console"}, "-700459563": {"name": "OldTristram: Traveler's Journal", "category": "Lore", "platform": "Console"}, "-289611678": {"name": "OldTristram: Villager's Journal", "category": "Lore", "platform": "Console"}, "1708077021": {"name": "OldTristram: Warriv's Journal", "category": "Lore", "platform": "Console"}, "-561113926": {"name": "OneLastEntry: Crumbling Journal", "category": "Lore", "platform": "Console"}, "-216253271": {"name": "PandExt: Legend of the Great Weapon", "category": "Lore", "platform": "Console"}, "551638722": {"name": "PandExt: Malthael's Plan", "category": "Lore", "platform": "Console"}, "-420053241": {"name": "Pandemonium: The History of Pandemonium, Part 1", "category": "Lore", "platform": "Console"}, "-420053240": {"name": "Pandemonium: The History of Pandemonium, Part 2", "category": "Lore", "platform": "Console"}, "-420053239": {"name": "Pandemonium: The History of Pandemonium, Part 3", "category": "Lore", "platform": "Console"}, "-420053238": {"name": "Pandemonium: The History of Pandemonium, Part 4", "category": "Lore", "platform": "Console"}, "-1604058933": {"name": "Poltahr: Poltahr's Notes", "category": "Lore", "platform": "Console"}, "-1861918345": {"name": "PortalRoulette: Lyndo's Journal", "category": "Lore", "platform": "Console"}, "613068827": {"name": "Priest: Priest's Contemplations, Part 1", "category": "Lore", "platform": "Console"}, "613068826": {"name": "Priest: Priest's Contemplations, Part 2", "category": "Lore", "platform": "Console"}, "1320763167": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "1320763168": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "1320763169": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "1758275411": {"name": "PromisesOfFezuul: The Promises of Fezuul al-Kazarr", "category": "Lore", "platform": "Console"}, "-139516026": {"name": "ProudWife: Bloodstained Letter", "category": "Lore", "platform": "Console"}, "3611879712": {"name": "Quill Fiend", "category": "Lore", "platform": "Console"}, "1276294793": {"name": "Rakanoth: Rakanoth, the Lord of Despair", "category": "Lore", "platform": "Console"}, "-1106592288": {"name": "Rakkis: Rakkis's Orders", "category": "Lore", "platform": "Console"}, "-1074332472": {"name": "RakkisHistory: The Testament of Rakkis, Part 1", "category": "Lore", "platform": "Console"}, "-1074332471": {"name": "RakkisHistory: The Testament of Rakkis, Part 2", "category": "Lore", "platform": "Console"}, "-1074332470": {"name": "RakkisHistory: The Testament of Rakkis, Part 3", "category": "Lore", "platform": "Console"}, "-1074332469": {"name": "RakkisHistory: The Testament of Rakkis, Part 4", "category": "Lore", "platform": "Console"}, "-1074332468": {"name": "RakkisHistory: The Testament of Rakkis, Part 5", "category": "Lore", "platform": "Console"}, "-1074332467": {"name": "RakkisHistory: The Testament of Rakkis, Part 6", "category": "Lore", "platform": "Console"}, "-1074332466": {"name": "RakkisHistory: The Testament of Rakkis, Part 7", "category": "Lore", "platform": "Console"}, "-1074332465": {"name": "RakkisHistory: The Testament of Rakkis, Part 8", "category": "Lore", "platform": "Console"}, "-1074332464": {"name": "RakkisHistory: The Testament of Rakkis, Part 9", "category": "Lore", "platform": "Console"}, "1960749072": {"name": "Realmwalker: The Realmwalker", "category": "Lore", "platform": "Console"}, "3580037015": {"name": "Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "2895121073": {"name": "Scavenger", "category": "Lore", "platform": "Console"}, "-561655662": {"name": "Scoundrel: Scoundrel's Journal", "category": "Lore", "platform": "Console"}, "648677458": {"name": "Siege: Missive from Imperius", "category": "Lore", "platform": "Console"}, "-1327438701": {"name": "Siege: Siege Runes", "category": "Lore", "platform": "Console"}, "1667935935": {"name": "SkeletonKing: The Skeleton King", "category": "Lore", "platform": "Console"}, "-21507498": {"name": "SpiderQueen: The Spider Queen", "category": "Lore", "platform": "Console"}, "1881837798": {"name": "Templar: Bloodied Parchment", "category": "Lore", "platform": "Console"}, "1881837797": {"name": "Templar: Bloodied Scraps", "category": "Lore", "platform": "Console"}, "1792637338": {"name": "TemplarMaester: Grand Maester's Journal", "category": "Lore", "platform": "Console"}, "1776052671": {"name": "TemplarMaester: The Maester's Proclamation", "category": "Lore", "platform": "Console"}, "464105835": {"name": "Tinker: Wandering Tinker's Diary", "category": "Lore", "platform": "Console"}, "3594507733": {"name": "Traveler's Journal", "category": "Lore", "platform": "Console"}, "732715821": {"name": "UriktheSeer: Notes of Urik the Seer, Part 1", "category": "Lore", "platform": "Console"}, "732715822": {"name": "UriktheSeer: Notes of Urik the Seer, Part 2", "category": "Lore", "platform": "Console"}, "732715823": {"name": "UriktheSeer: Notes of Urik the Seer, Part 3", "category": "Lore", "platform": "Console"}, "-645692806": {"name": "Urzael: Urzael's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-645692805": {"name": "Urzael: Urzael's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-645692804": {"name": "Urzael: Urzael's Journal, Part 3", "category": "Lore", "platform": "Console"}, "4005355618": {"name": "Villager's Journal", "category": "Lore", "platform": "Console"}, "-1451420418": {"name": "WaterPuzzle: The Chamber of Faces", "category": "Lore", "platform": "Console"}, "1223177093": {"name": "Westm: It's a Trap", "category": "Lore", "platform": "Console"}, "831394876": {"name": "Westm: The Cult Shall Rise Again", "category": "Lore", "platform": "Console"}, "913430382": {"name": "Westm: The King's Journal, Part 1", "category": "Lore", "platform": "Console"}, "913430383": {"name": "Westm: The King's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1218326648": {"name": "Westm: The King's Note to Lord Wynton", "category": "Lore", "platform": "Console"}, "1526997743": {"name": "Westm: The Plague Tunnels", "category": "Lore", "platform": "Console"}, "-1469466389": {"name": "Westm: The Souls of Westmarch", "category": "Lore", "platform": "Console"}, "-916745255": {"name": "Westmarch: The History of Westmarch, Part 1", "category": "Lore", "platform": "Console"}, "-916745254": {"name": "Westmarch: The History of Westmarch, Part 2", "category": "Lore", "platform": "Console"}, "-916745253": {"name": "Westmarch: The History of Westmarch, Part 3", "category": "Lore", "platform": "Console"}, "-916745252": {"name": "Westmarch: The History of Westmarch, Part 4", "category": "Lore", "platform": "Console"}, "-916745251": {"name": "Westmarch: The History of Westmarch, Part 5", "category": "Lore", "platform": "Console"}, "-916745250": {"name": "Westmarch: The History of Westmarch, Part 6", "category": "Lore", "platform": "Console"}, "-916745249": {"name": "Westmarch: The History of Westmarch, Part 7", "category": "Lore", "platform": "Console"}, "-223645750": {"name": "X1 Lore Besitary RevenantShieldGuard", "category": "Lore", "platform": "Console"}, "1571805338": {"name": "X1 Lore Bestiary GhastlySeraph", "category": "Lore", "platform": "Console"}, "1836003891": {"name": "X1 Lore Bestiary RevenantArcher", "category": "Lore", "platform": "Console"}, "-1635681275": {"name": "x1 Bog Lore AdriaBetrayal", "category": "Lore", "platform": "Console"}, "-8314071": {"name": "x1 Bog Lore AdriaEmptiness", "category": "Lore", "platform": "Console"}, "1923206206": {"name": "x1 Bog Lore AdriaLosingControl", "category": "Lore", "platform": "Console"}, "2045759001": {"name": "x1 Bog Lore AdriaNewHost", "category": "Lore", "platform": "Console"}, "118984382": {"name": "x1 Bog Lore AdriaPower", "category": "Lore", "platform": "Console"}, "-134175942": {"name": "x1 Bog Lore AdriaVoices", "category": "Lore", "platform": "Console"}, "-1074332440": {"name": "x1 Bog Lore RakkisHistory10", "category": "Lore", "platform": "Console"}, "-1656026178": {"name": "01: Club (DPS 5.4-6.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026177": {"name": "02: Cudgel (DPS 9.6-11.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026176": {"name": "03: Morning Star (DPS 15.0-16.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026175": {"name": "04: Mace (DPS 18.6-20.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026174": {"name": "05: Flanged Mace (DPS 23.4-25.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026173": {"name": "06: Hammer (DPS 28.2-30.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026172": {"name": "07: War Gavel (DPS 33.6-35.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025089": {"name": "08: Bludgeon (DPS 43.8-45.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025088": {"name": "09: Spiked Baton (DPS 52.2-54.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025087": {"name": "10: War Mace (DPS 62.4-64.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025086": {"name": "11: Gada (DPS 73.2-75.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025085": {"name": "12: Pernach (DPS 85.2-88.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025084": {"name": "13: Heavy Hammer (DPS 102.0-105.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025083": {"name": "14: War Hammer (DPS 124.8-128.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656024000": {"name": "15: Skull Crusher (DPS 138.0-143.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023999": {"name": "16: Truncheon (DPS 155.4-160.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023998": {"name": "17: Death Mace (DPS 174.0-179.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023997": {"name": "18: Tripyor (DPS 192.6-199.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023996": {"name": "19: Goedendag (DPS 237.0-244.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023995": {"name": "20: Crag Hammer (DPS 273.6-282.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023994": {"name": "21: Demolisher (DPS 318.0-327.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022911": {"name": "22: Brutalizer (DPS 429.6-436.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022910": {"name": "23: Skullsplitter (DPS 540.6-547.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099965": {"name": "Art Test Mace One-Handed 1", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099964": {"name": "Art Test Mace One-Handed 2", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099963": {"name": "Art Test Mace One-Handed 3", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099962": {"name": "Art Test Mace One-Handed 4", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099961": {"name": "Art Test Mace One-Handed 5", "category": "Maces, One-Handed", "platform": "Console"}, "-1473010435": {"name": "Legendary: Deadeye's Mace (Patch 2.1.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894988668": {"name": "Legendary: Devastator", "category": "Maces, One-Handed", "platform": "Console"}, "1889806096": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1889808540": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325116": {"name": "Legendary: Earthshatter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895276164": {"name": "Legendary: Echoing Fury", "category": "Maces, One-Handed", "platform": "Console"}, "1880318728": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1880321172": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325108": {"name": "Legendary: Echoing Fury (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856068897": {"name": "Legendary: Jace's Hammer of Vigilance", "category": "Maces, One-Handed", "platform": "Console"}, "-1856140771": {"name": "Legendary: Mad Monarch's Scepter", "category": "Maces, One-Handed", "platform": "Console"}, "-1895024605": {"name": "Legendary: Nailbiter", "category": "Maces, One-Handed", "platform": "Console"}, "1888620175": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1888622619": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325115": {"name": "Legendary: Nailbiter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895204290": {"name": "Legendary: Neanderthal", "category": "Maces, One-Handed", "platform": "Console"}, "1882690570": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1882693014": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325110": {"name": "Legendary: Neanderthal (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895132416": {"name": "Legendary: Nutcracker", "category": "Maces, One-Handed", "platform": "Console"}, "1885062412": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1885064856": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325112": {"name": "Legendary: Nutcracker (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895240227": {"name": "Legendary: Odyn Son", "category": "Maces, One-Handed", "platform": "Console"}, "1881504649": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1881507093": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325109": {"name": "Legendary: Odyn Son (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856104834": {"name": "Legendary: Solanium", "category": "Maces, One-Handed", "platform": "Console"}, "-1894090243": {"name": "Legendary: Sun Keeper", "category": "Maces, One-Handed", "platform": "Console"}, "1919454121": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1919456565": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325141": {"name": "Legendary: Sun Keeper (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895060542": {"name": "Legendary: Telranden's Hand", "category": "Maces, One-Handed", "platform": "Console"}, "1887434254": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1887436698": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325114": {"name": "Legendary: Telranden's Hand (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894126180": {"name": "Legendary: Wirt's Original Leg", "category": "Maces, One-Handed", "platform": "Console"}, "1918268200": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1918270644": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325140": {"name": "Legendary: Wirt's Original Leg (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1616890785": {"name": "01: Two-Handed Club (DPS 15.8-16.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890784": {"name": "02: Two-Handed Mace (DPS 20.3-21.6)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890783": {"name": "03: Two-Handed Hammer (DPS 24.8-26.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890782": {"name": "04: Maul (DPS 31.5-32.9)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890781": {"name": "05: Mallet (DPS 37.8-40.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890780": {"name": "06: Great Hammer (DPS 45.5-48.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889696": {"name": "07: Dire Club (DPS 55.8-58.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889695": {"name": "08: Dire Mace (DPS 66.6-70.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889694": {"name": "09: Sledge Hammer (DPS 81.9-86.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889693": {"name": "10: Great Maul (DPS 98.6-104.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889692": {"name": "11: War Mallet (DPS 117.9-124.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889691": {"name": "12: Rock Breaker (DPS 144.5-151.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888607": {"name": "13: Wrecker (DPS 196.7-206.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888606": {"name": "14: Dread Mace (DPS 249.3-260.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888605": {"name": "15: War Sledge (DPS 315.9-326.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888604": {"name": "16: War Maul (DPS 437.9-448.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888603": {"name": "17: Slag Hammer (DPS 518.4-529.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888602": {"name": "18: Doom Hammer (DPS 613.4-624.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887518": {"name": "19: Royal Mace (DPS 774.0-786.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887517": {"name": "20: Persuader (DPS 1058.5-1070.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064028": {"name": "Art Test Mace Two-Handed 1", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064027": {"name": "Art Test Mace Two-Handed 2", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064026": {"name": "Art Test Mace Two-Handed 3", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064025": {"name": "Art Test Mace Two-Handed 4", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064024": {"name": "Art Test Mace Two-Handed 5", "category": "Maces, Two-Handed", "platform": "Console"}, "59108159": {"name": "Legendary: Arthef's Spark of Life", "category": "Maces, Two-Handed", "platform": "Console"}, "1950491947": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1950494391": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460503": {"name": "Legendary: Boneshatter (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954049710": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954052154": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460506": {"name": "Legendary: Cataclysm (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59036285": {"name": "Legendary: Crushbane", "category": "Maces, Two-Handed", "platform": "Console"}, "1948120105": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1948122549": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460501": {"name": "Legendary: Crushbane (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323781": {"name": "Legendary: Schaefer's Hammer", "category": "Maces, Two-Handed", "platform": "Console"}, "1957607473": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1957609917": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460509": {"name": "Legendary: Schaefer's Hammer (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60186269": {"name": "Legendary: Skywarden", "category": "Maces, Two-Handed", "platform": "Console"}, "1986069577": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1986072021": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460533": {"name": "Legendary: Skywarden (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59072222": {"name": "Legendary: Sledge of Athskeleng", "category": "Maces, Two-Handed", "platform": "Console"}, "1949306026": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1949308470": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460502": {"name": "Legendary: Sledge of Athskeleng (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "98279489": {"name": "Legendary: Soulsmasher", "category": "Maces, Two-Handed", "platform": "Console"}, "59215970": {"name": "Legendary: Sunder", "category": "Maces, Two-Handed", "platform": "Console"}, "98243552": {"name": "Legendary: The Furnace", "category": "Maces, Two-Handed", "platform": "Console"}, "60258143": {"name": "Legendary: Wrath of the Bone King", "category": "Maces, Two-Handed", "platform": "Console"}, "1988441419": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1988443863": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460535": {"name": "Legendary: Wrath of the Bone King (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60257879": {"name": "Legendary: Wrath of the Bone King (Patch 2.1.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323518": {"name": "legendary: Schaefer's Hammer (Patch 2.2.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "2112155406": {"name": "01: Warrior Belt (AR 26-30)", "category": "Mighty Belts", "platform": "Console"}, "2112155407": {"name": "02: Harness (AR 32-37)", "category": "Mighty Belts", "platform": "Console"}, "2112155408": {"name": "03: Braid (AR 53-61)", "category": "Mighty Belts", "platform": "Console"}, "2112155409": {"name": "04: Grand Belt (AR 74-100)", "category": "Mighty Belts", "platform": "Console"}, "2112156495": {"name": "05: Baldric (AR 101-132)", "category": "Mighty Belts", "platform": "Console"}, "2112156496": {"name": "06: Blade Harness (AR 133-164)", "category": "Mighty Belts", "platform": "Console"}, "2112156497": {"name": "07: Iron Braid (AR 165-205)", "category": "Mighty Belts", "platform": "Console"}, "2112156498": {"name": "08: Steel Chain (AR 206-225)", "category": "Mighty Belts", "platform": "Console"}, "2112157584": {"name": "09: Lock (AR 226-252)", "category": "Mighty Belts", "platform": "Console"}, "2112157585": {"name": "10: Bronze Links (AR 253-285)", "category": "Mighty Belts", "platform": "Console"}, "2112157586": {"name": "11: Heavy Baldric (AR 286-318)", "category": "Mighty Belts", "platform": "Console"}, "2112157587": {"name": "12: Grand Chain (AR 320-419)", "category": "Mighty Belts", "platform": "Console"}, "2112157588": {"name": "13: Platinum Lock (AR 420-586)", "category": "Mighty Belts", "platform": "Console"}, "2112157589": {"name": "14: Mighty Scourge (AR 586-674)", "category": "Mighty Belts", "platform": "Console"}, "325816755": {"name": "Art Test BarbBelt 1", "category": "Mighty Belts", "platform": "Console"}, "325816756": {"name": "Art Test BarbBelt 2", "category": "Mighty Belts", "platform": "Console"}, "325816757": {"name": "Art Test BarbBelt 3", "category": "Mighty Belts", "platform": "Console"}, "325816758": {"name": "Art Test BarbBelt 4", "category": "Mighty Belts", "platform": "Console"}, "325816759": {"name": "Art Test BarbBelt 5", "category": "Mighty Belts", "platform": "Console"}, "924282931": {"name": "Legendary: Ageless Might", "category": "Mighty Belts", "platform": "Console"}, "436488351": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "436490795": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630773": {"name": "Legendary: Ageless Might (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963274576": {"name": "Legendary: Ancients' Discontent", "category": "Mighty Belts", "platform": "Console"}, "963166765": {"name": "Legendary: Chilanik's Chain", "category": "Mighty Belts", "platform": "Console"}, "924031372": {"name": "Legendary: Dread Iron", "category": "Mighty Belts", "platform": "Console"}, "428186904": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "428189348": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630780": {"name": "Legendary: Dread Iron (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924139183": {"name": "Legendary: Girdle of Giants", "category": "Mighty Belts", "platform": "Console"}, "431744667": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "431747111": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630777": {"name": "Legendary: Girdle of Giants (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924246994": {"name": "Legendary: Kotuur's Brace", "category": "Mighty Belts", "platform": "Console"}, "435302430": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "435304874": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630774": {"name": "Legendary: Kotuur's Brace (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924175120": {"name": "Legendary: Lamentation", "category": "Mighty Belts", "platform": "Console"}, "432930588": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "432933032": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630776": {"name": "Legendary: Lamentation (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924174856": {"name": "Legendary: Lamentation (Patch 2.1.0)", "category": "Mighty Belts", "platform": "Console"}, "924067309": {"name": "Legendary: Pride of Cassius", "category": "Mighty Belts", "platform": "Console"}, "429372825": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "429375269": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630779": {"name": "Legendary: Pride of Cassius (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963310513": {"name": "Legendary: Promise of the Doomed Forebearer", "category": "Mighty Belts", "platform": "Console"}, "924211057": {"name": "Legendary: The Undisputed Champion", "category": "Mighty Belts", "platform": "Console"}, "434116509": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "434118953": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630775": {"name": "Legendary: The Undisputed Champion (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737386": {"name": "Legendary: The Undisputed Champion (Patch 2.1.2)", "category": "Mighty Belts", "platform": "Console"}, "430558746": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "430561190": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630778": {"name": "Legendary: Thunder God's Vigor (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963238639": {"name": "Legendary: Wodir Harness", "category": "Mighty Belts", "platform": "Console"}, "963202702": {"name": "Legendary: x1_BarbBelt_norm_unique_11", "category": "Mighty Belts", "platform": "Console"}, "-1303630772": {"name": "Set: Immortal King's Detail (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924318868": {"name": "Set: Immortal King's Tribal Binding", "category": "Mighty Belts", "platform": "Console"}, "437674272": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "437676716": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737381": {"name": "legendary: Dread Iron (Patch 2.2.0)", "category": "Mighty Belts", "platform": "Console"}, "290066501": {"name": "01: Sickle (DPS 11.1-12.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066502": {"name": "02: Carver (DPS 14.3-16.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066503": {"name": "03: Maw Axe (DPS 21.5-23.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066504": {"name": "04: War Blade (DPS 31.2-33.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067590": {"name": "05: Scythe (DPS 36.4-38.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067591": {"name": "06: Machete (DPS 54.6-56.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067592": {"name": "07: Gutwrench (DPS 82.6-86.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067593": {"name": "08: Rage Blade (DPS 118.3-122.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068679": {"name": "09: Reaper (DPS 153.4-159.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068680": {"name": "10: Chopsword (DPS 206.7-214.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068681": {"name": "11: Massacre Axe (DPS 238.6-246.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068682": {"name": "12: Slayer (DPS 277.6-285.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069768": {"name": "13: Caldean Sword (DPS 371.8-379.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069769": {"name": "14: Limb Cleaver (DPS 461.5-469.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026495": {"name": "Art Test Mighty One-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026496": {"name": "Art Test Mighty One-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026497": {"name": "Art Test Mighty One-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026498": {"name": "Art Test Mighty One-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026499": {"name": "Art Test Mighty One-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062432": {"name": "Art Test Mighty Two-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062433": {"name": "Art Test Mighty Two-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062434": {"name": "Art Test Mighty Two-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062435": {"name": "Art Test Mighty Two-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062436": {"name": "Art Test Mighty Two-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511328230": {"name": "Legendary: Ambo's Pride", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665698662": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665701106": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986962": {"name": "Legendary: Ambo's Pride (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512406340": {"name": "Legendary: Blade of the Warlord", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630121032": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630123476": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986932": {"name": "Legendary: Blade of the Warlord (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473342821": {"name": "Legendary: Dishonored Legacy", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512370403": {"name": "Legendary: Fjord Cutter", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631306953": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631309397": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986933": {"name": "Legendary: Fjord Cutter (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625377348": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625379792": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986928": {"name": "Legendary: Harvest Moon (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473414695": {"name": "Legendary: Hellion Scale", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512550088": {"name": "Legendary: Night's Reaping", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473306884": {"name": "Legendary: Oathkeeper", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473378758": {"name": "Legendary: Remorseless", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986960": {"name": "Set: Bul-Kathos's Sacred Charge (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511400104": {"name": "Set: Bul-Kathos's Solemn Vow", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663326820": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663329264": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986961": {"name": "Set: Bul-Kathos's Tribal Guardian (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511364167": {"name": "Set: Bul-Kathos's Warrior Blood", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664512741": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664515185": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986965": {"name": "Set: Hallowed Destroyer (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511220419": {"name": "Set: Hallowed Nemesis", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669258869": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669256425": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "329201894": {"name": "01: Petrified Trunk (DPS 15.5-16.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201895": {"name": "02: Giant Sword (DPS 18.0-19.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201896": {"name": "03: Giant Hammer (DPS 25.5-27.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201897": {"name": "04: Giant Axe (DPS 36.0-37.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202983": {"name": "05: Redwood War Club (DPS 60.6-63.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202984": {"name": "06: Colossus Sword (DPS 81.5-86.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202985": {"name": "07: Crusher (DPS 110.5-116.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202986": {"name": "08: Colossus Axe (DPS 169.0-176.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204072": {"name": "09: Battersmash (DPS 248.5-257.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204073": {"name": "10: Titan Sword (DPS 397.5-408.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204074": {"name": "11: Behemoth (DPS 469.0-481.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204075": {"name": "12: Titan Axe (DPS 555.0-567.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205161": {"name": "13: Hassan Chopper (DPS 691.9-703.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205162": {"name": "14: Steppes Smasher (DPS 940.0-951.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441870172": {"name": "Legendary: Bastion's Revered", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696736488": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696738932": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122324": {"name": "Legendary: Bastion's Revered (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441869908": {"name": "Legendary: Bastion's Revered (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441942046": {"name": "Legendary: Fury of the Vanished Peak", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699108330": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699110774": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122326": {"name": "Legendary: Fury of the Vanished Peak (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-96858155": {"name": "Legendary: Grim Reaper", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "480897754": {"name": "Legendary: Madawc's Sorrow", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-389442788": {"name": "Legendary: The Blackrock Destroyer (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441762361": {"name": "Legendary: The Gavel of Judgment", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693178725": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693181169": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122321": {"name": "Legendary: The Gavel of Judgment (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733500039": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733502483": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122355": {"name": "Legendary: Unending War (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442984219": {"name": "Legendary: War of the Dead", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442912345": {"name": "Set: Immortal King's Boulder Breaker", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731128197": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731130641": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122353": {"name": "Set: Immortal King's Stone Crusher (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "2125089234": {"name": "legendary: The Gavel Of Judgement (Patch 2.2.0)", "category": "Mightys, Two-Handed", "platform": "Console"}, "-136816475": {"name": "01: Wanga Doll (+1-2 DMG)", "category": "Mojos", "platform": "Console"}, "-136816474": {"name": "02: Shrunken Head (+(2-3)-(3-5) DMG)", "category": "Mojos", "platform": "Console"}, "-136816473": {"name": "03: Caged Horror (+(3-5)-(4-8) DMG)", "category": "Mojos", "platform": "Console"}, "-136816472": {"name": "04: Viper (+(3-6)-(4-10) DMG)", "category": "Mojos", "platform": "Console"}, "-136815386": {"name": "05: Gris-Gris Moppet (+(4-8)-(5-13) DMG)", "category": "Mojos", "platform": "Console"}, "-136815385": {"name": "06: Tzantza (+(6-11)-(7-19) DMG)", "category": "Mojos", "platform": "Console"}, "-136815384": {"name": "07: Living Tentacle (+(8-16)-(9-29) DMG)", "category": "Mojos", "platform": "Console"}, "-136815383": {"name": "08: Copperhead (+(13-26)-(14-45) DMG)", "category": "Mojos", "platform": "Console"}, "-136814297": {"name": "09: Wicker Man (+(17-39)-(18-114) DMG)", "category": "Mojos", "platform": "Console"}, "-136814296": {"name": "10: Muttering Head (+(19-58)-(20-213) DMG)", "category": "Mojos", "platform": "Console"}, "-136814295": {"name": "11: Unspeakable Thing (+(24-72)-(25-265) DMG)", "category": "Mojos", "platform": "Console"}, "-136814294": {"name": "12: Kurastian Asp (+(28-110)-(29-405) DMG)", "category": "Mojos", "platform": "Console"}, "-136814293": {"name": "13: Skull Talisman (+(126-158)-(127-190) DMG)", "category": "Mojos", "platform": "Console"}, "-136814292": {"name": "14: Thing That Should Not Be (+(262-328)-(263-394) DMG)", "category": "Mojos", "platform": "Console"}, "1629900554": {"name": "Art Test Mojo 1", "category": "Mojos", "platform": "Console"}, "1629900555": {"name": "Art Test Mojo 2", "category": "Mojos", "platform": "Console"}, "1629900556": {"name": "Art Test Mojo 3", "category": "Mojos", "platform": "Console"}, "1629900557": {"name": "Art Test Mojo 4", "category": "Mojos", "platform": "Console"}, "1629900558": {"name": "Art Test Mojo 5", "category": "Mojos", "platform": "Console"}, "-1667471440": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-1667468996": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608100": {"name": "Legendary: Bitterness (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961544827": {"name": "Legendary: Gazing Demise", "category": "Mojos", "platform": "Console"}, "-1666285519": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-1666283075": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608099": {"name": "Legendary: Gazing Demise (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961508890": {"name": "Legendary: Homunculus", "category": "Mojos", "platform": "Console"}, "-1665099598": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-1665097154": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608098": {"name": "Legendary: Homunculus (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922445371": {"name": "Legendary: Shukrani's Triumph", "category": "Mojos", "platform": "Console"}, "-922409434": {"name": "Legendary: Sorrowful Countenance", "category": "Mojos", "platform": "Console"}, "-961580764": {"name": "Legendary: Spite", "category": "Mojos", "platform": "Console"}, "-961329205": {"name": "Legendary: Thing of the Deep", "category": "Mojos", "platform": "Console"}, "-1659169993": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-1659167549": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608093": {"name": "Legendary: Thing of the Deep (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961365142": {"name": "Legendary: Uhkapian Serpent", "category": "Mojos", "platform": "Console"}, "-1660355914": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-1660353470": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608094": {"name": "Legendary: Uhkapian Serpent (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922373497": {"name": "Legendary: Vile Hive", "category": "Mojos", "platform": "Console"}, "1413644935": {"name": "P2 mojo norm Legendary 01", "category": "Mojos", "platform": "Console"}, "1413644936": {"name": "P2 mojo norm Legendary 02", "category": "Mojos", "platform": "Console"}, "1413644937": {"name": "P2 mojo norm Legendary 03", "category": "Mojos", "platform": "Console"}, "-960466717": {"name": "Set: Manajuma's Gory Fetch", "category": "Mojos", "platform": "Console"}, "-1630707889": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-1630705445": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608069": {"name": "Set: Manajuma's Ritual Prize (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-63608068": {"name": "Set: Zunimassa's Ferocity (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-960430780": {"name": "Set: Zunimassa's String of Skulls", "category": "Mojos", "platform": "Console"}, "-1629521968": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-1629519524": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-961509153": {"name": "legendary: Homunculus (Patch 2.2.0)", "category": "Mojos", "platform": "Console"}, "-734094289": {"name": "A Servant's Journal", "category": "NPC Items", "platform": "Console"}, "1372800103": {"name": "A Summoner's Journal", "category": "NPC Items", "platform": "Console"}, "1366034119": {"name": "A2C2EmptyCage", "category": "NPC Items", "platform": "Console"}, "-894018760": {"name": "A2C2HusamHead", "category": "NPC Items", "platform": "Console"}, "1506900471": {"name": "A2C2NecromancerCrystal", "category": "NPC Items", "platform": "Console"}, "-1176971336": {"name": "A2C2OreBag", "category": "NPC Items", "platform": "Console"}, "-701130141": {"name": "A2C2RygnarIdol", "category": "NPC Items", "platform": "Console"}, "-1969048485": {"name": "A2C2SharkHide", "category": "NPC Items", "platform": "Console"}, "524402999": {"name": "A2C2SharkNecklace", "category": "NPC Items", "platform": "Console"}, "297778632": {"name": "A2C2WantedPoster", "category": "NPC Items", "platform": "Console"}, "1135854513": {"name": "A2C2WantedPosterGood", "category": "NPC Items", "platform": "Console"}, "-284487217": {"name": "ActIQ2 RatMageSkull", "category": "NPC Items", "platform": "Console"}, "956379400": {"name": "Ahren's Hammer", "category": "NPC Items", "platform": "Console"}, "893398919": {"name": "AlbrechtsRemains", "category": "NPC Items", "platform": "Console"}, "-1240838296": {"name": "Ancient Medallion", "category": "NPC Items", "platform": "Console"}, "1475923527": {"name": "Ancient Tome Page", "category": "NPC Items", "platform": "Console"}, "-831189640": {"name": "Angelic Seal", "category": "NPC Items", "platform": "Console"}, "-885657485": {"name": "Antique Box", "category": "NPC Items", "platform": "Console"}, "-309356827": {"name": "Aqueduct Key", "category": "NPC Items", "platform": "Console"}, "493907862": {"name": "Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "-470655325": {"name": "Beacon of Honor", "category": "NPC Items", "platform": "Console"}, "-470655324": {"name": "Beacon of Light", "category": "NPC Items", "platform": "Console"}, "-246893943": {"name": "Black Soulstone", "category": "NPC Items", "platform": "Console"}, "504121446": {"name": "Blackened Journal", "category": "NPC Items", "platform": "Console"}, "1818884426": {"name": "Blacksmith's Tome", "category": "NPC Items", "platform": "Console"}, "263122102": {"name": "Bogus Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "944034263": {"name": "Broken Crown", "category": "NPC Items", "platform": "Console"}, "-63906132": {"name": "Broken Doll", "category": "NPC Items", "platform": "Console"}, "1201838506": {"name": "Calldown Grenade", "category": "NPC Items", "platform": "Console"}, "-1797642504": {"name": "Caravan Inventory List", "category": "NPC Items", "platform": "Console"}, "-110888638": {"name": "Chain Key", "category": "NPC Items", "platform": "Console"}, "1061128541": {"name": "Cloud Fire", "category": "NPC Items", "platform": "Console"}, "-565248060": {"name": "Cultist Cellar Key", "category": "NPC Items", "platform": "Console"}, "-613437014": {"name": "DevilsHand: Aidan's Memento", "category": "NPC Items", "platform": "Console"}, "-613616703": {"name": "DevilsHand: Broken Oath", "category": "NPC Items", "platform": "Console"}, "-613437017": {"name": "DevilsHand: Cain's Memento", "category": "NPC Items", "platform": "Console"}, "-613544825": {"name": "DevilsHand: Dark Coven Familiar", "category": "NPC Items", "platform": "Console"}, "-613544828": {"name": "DevilsHand: Dark Coven Insignia", "category": "NPC Items", "platform": "Console"}, "-613544826": {"name": "DevilsHand: Dark Coven Jar of Reagents", "category": "NPC Items", "platform": "Console"}, "-613544829": {"name": "DevilsHand: Dark Coven Scroll of Illusions", "category": "NPC Items", "platform": "Console"}, "-613544827": {"name": "DevilsHand: Dark Coven Torturing Device", "category": "NPC Items", "platform": "Console"}, "-613437012": {"name": "DevilsHand: Gideon's Memento", "category": "NPC Items", "platform": "Console"}, "-613508887": {"name": "DevilsHand: Icon of Envy", "category": "NPC Items", "platform": "Console"}, "-613508886": {"name": "DevilsHand: Icon of Gluttony", "category": "NPC Items", "platform": "Console"}, "-613508891": {"name": "DevilsHand: Icon of Greed", "category": "NPC Items", "platform": "Console"}, "-613508888": {"name": "DevilsHand: Icon of Lust", "category": "NPC Items", "platform": "Console"}, "-613508889": {"name": "DevilsHand: Icon of Pride", "category": "NPC Items", "platform": "Console"}, "-613508890": {"name": "DevilsHand: Icon of Sloth", "category": "NPC Items", "platform": "Console"}, "-613508892": {"name": "DevilsHand: Icon of Wrath", "category": "NPC Items", "platform": "Console"}, "-613437016": {"name": "DevilsHand: Leah's Memento", "category": "NPC Items", "platform": "Console"}, "-613616702": {"name": "DevilsHand: Love's Oath", "category": "NPC Items", "platform": "Console"}, "-613437013": {"name": "DevilsHand: Ogden's Memento", "category": "NPC Items", "platform": "Console"}, "-613616701": {"name": "DevilsHand: Selfless Oath", "category": "NPC Items", "platform": "Console"}, "-613580763": {"name": "DevilsHand: The Black King's Bloodied Gauntlet", "category": "NPC Items", "platform": "Console"}, "-613580762": {"name": "DevilsHand: The Black King's Journal", "category": "NPC Items", "platform": "Console"}, "-613580765": {"name": "DevilsHand: The Black King's Skull", "category": "NPC Items", "platform": "Console"}, "-613580764": {"name": "DevilsHand: The Black King's Tainted Elixir", "category": "NPC Items", "platform": "Console"}, "-613580766": {"name": "DevilsHand: The Black King's Trophy", "category": "NPC Items", "platform": "Console"}, "-613437018": {"name": "DevilsHand: Warriv's Memento", "category": "NPC Items", "platform": "Console"}, "-613437015": {"name": "DevilsHand: Wirt's Memento", "category": "NPC Items", "platform": "Console"}, "-473140170": {"name": "Event: Alchemist Concoction", "category": "NPC Items", "platform": "Console"}, "452865871": {"name": "Event: Aperture Key", "category": "NPC Items", "platform": "Console"}, "-1312544703": {"name": "Event: Battle Elixir", "category": "NPC Items", "platform": "Console"}, "66225719": {"name": "Event: Battlefield Reports", "category": "NPC Items", "platform": "Console"}, "-1961273523": {"name": "Event: Bones of the Matriarch1", "category": "NPC Items", "platform": "Console"}, "-1961273522": {"name": "Event: Bones of the Matriarch2", "category": "NPC Items", "platform": "Console"}, "-1961273521": {"name": "Event: Bones of the Matriarch3", "category": "NPC Items", "platform": "Console"}, "1197498604": {"name": "Event: Dusty Old Tome", "category": "NPC Items", "platform": "Console"}, "463155324": {"name": "Event: Forboding Tome", "category": "NPC Items", "platform": "Console"}, "-934435532": {"name": "Event: Jeweled Scabbard", "category": "NPC Items", "platform": "Console"}, "1465477567": {"name": "Event: Medical Supplies", "category": "NPC Items", "platform": "Console"}, "-694090266": {"name": "Event: Officer's Orders", "category": "NPC Items", "platform": "Console"}, "-2013751652": {"name": "Event: Templar Object 1", "category": "NPC Items", "platform": "Console"}, "-1003233507": {"name": "Event: The Matriarch's Skeleton", "category": "NPC Items", "platform": "Console"}, "899528155": {"name": "FacePuzzleSmallKey", "category": "NPC Items", "platform": "Console"}, "-1986712818": {"name": "Fuad's Journal", "category": "NPC Items", "platform": "Console"}, "1331402556": {"name": "Greater Shard", "category": "NPC Items", "platform": "Console"}, "301784336": {"name": "Heretic Text", "category": "NPC Items", "platform": "Console"}, "-705827599": {"name": "HunterJournal", "category": "NPC Items", "platform": "Console"}, "1742022798": {"name": "Iron Wolf Captain's Journal", "category": "NPC Items", "platform": "Console"}, "680369210": {"name": "Jail Gate Key", "category": "NPC Items", "platform": "Console"}, "-78029774": {"name": "Jelisa's Wedding Ring", "category": "NPC Items", "platform": "Console"}, "1018820302": {"name": "Jeweler's Crucible", "category": "NPC Items", "platform": "Console"}, "872964849": {"name": "Journal of Hansan Haile, Captain", "category": "NPC Items", "platform": "Console"}, "1264544813": {"name": "Khan's Tomb Key", "category": "NPC Items", "platform": "Console"}, "-1071052922": {"name": "Kulle's Blood", "category": "NPC Items", "platform": "Console"}, "-1341834848": {"name": "Kulle's Body", "category": "NPC Items", "platform": "Console"}, "-1341834849": {"name": "Kulle's Heart", "category": "NPC Items", "platform": "Console"}, "425198027": {"name": "Larus's Log", "category": "NPC Items", "platform": "Console"}, "1790135009": {"name": "Mausoleum Key", "category": "NPC Items", "platform": "Console"}, "-397905230": {"name": "Mira's Letter to Haedrig", "category": "NPC Items", "platform": "Console"}, "-1140969500": {"name": "Mysterious Box", "category": "NPC Items", "platform": "Console"}, "1816611999": {"name": "Mystery Amulet", "category": "NPC Items", "platform": "Console"}, "-1493063970": {"name": "Mystery Belt", "category": "NPC Items", "platform": "Console"}, "-2026108002": {"name": "Mystery Boots", "category": "NPC Items", "platform": "Console"}, "1281756953": {"name": "Mystery Bracers", "category": "NPC Items", "platform": "Console"}, "-594428401": {"name": "Mystery Chest Armor", "category": "NPC Items", "platform": "Console"}, "2050033703": {"name": "Mystery Gloves", "category": "NPC Items", "platform": "Console"}, "-1492848355": {"name": "Mystery Helm", "category": "NPC Items", "platform": "Console"}, "-1492657844": {"name": "Mystery Mojo", "category": "NPC Items", "platform": "Console"}, "215071258": {"name": "Mystery Orb", "category": "NPC Items", "platform": "Console"}, "-2010009315": {"name": "Mystery Pants", "category": "NPC Items", "platform": "Console"}, "-1843121997": {"name": "Mystery Quiver", "category": "NPC Items", "platform": "Console"}, "-1492484569": {"name": "Mystery Ring", "category": "NPC Items", "platform": "Console"}, "-1780286480": {"name": "Mystery Shield", "category": "NPC Items", "platform": "Console"}, "-537237168": {"name": "Mystery Shoulders", "category": "NPC Items", "platform": "Console"}, "-767866790": {"name": "Mystery Weapon, One-Handed", "category": "NPC Items", "platform": "Console"}, "-1099096773": {"name": "Mystery Weapon, Two-Handed", "category": "NPC Items", "platform": "Console"}, "-1352920439": {"name": "Nephalem Cube", "category": "NPC Items", "platform": "Console"}, "1774254059": {"name": "Nephalem Shard", "category": "NPC Items", "platform": "Console"}, "-1224842764": {"name": "Note from Maghda", "category": "NPC Items", "platform": "Console"}, "1524078078": {"name": "Old Tristram Key", "category": "NPC Items", "platform": "Console"}, "1524684909": {"name": "Orn VaseB caOut Props", "category": "NPC Items", "platform": "Console"}, "1472347958": {"name": "Orn a2dun Zolt Centerpiece A", "category": "NPC Items", "platform": "Console"}, "1354327297": {"name": "Orn caOut Cauldron", "category": "NPC Items", "platform": "Console"}, "-330317735": {"name": "Orn caOut CrateA", "category": "NPC Items", "platform": "Console"}, "1360506355": {"name": "Orn caOut VendorStandB", "category": "NPC Items", "platform": "Console"}, "1823013658": {"name": "Orn trDun Cath Candlestand", "category": "NPC Items", "platform": "Console"}, "-479501418": {"name": "Orn trDun Cath LibraryTable", "category": "NPC Items", "platform": "Console"}, "582933236": {"name": "Orn trDun Gargoyle 01", "category": "NPC Items", "platform": "Console"}, "684496620": {"name": "Orn trDun Incense Burner", "category": "NPC Items", "platform": "Console"}, "1432424645": {"name": "Orn trDun Weaponrack", "category": "NPC Items", "platform": "Console"}, "-1232771108": {"name": "Primordial Key", "category": "NPC Items", "platform": "Console"}, "-1661570587": {"name": "Queen Asylla's Journal", "category": "NPC Items", "platform": "Console"}, "1490502399": {"name": "Release Lever", "category": "NPC Items", "platform": "Console"}, "-1106160196": {"name": "Relic of Purification", "category": "NPC Items", "platform": "Console"}, "1259412129": {"name": "ReligiousArtifact", "category": "NPC Items", "platform": "Console"}, "-255366628": {"name": "Resonating Crystal", "category": "NPC Items", "platform": "Console"}, "468192851": {"name": "Scroll of Companion", "category": "NPC Items", "platform": "Console"}, "-96106000": {"name": "Scroll of Mysteries", "category": "NPC Items", "platform": "Console"}, "1310326700": {"name": "Shamanic Khazra Staff", "category": "NPC Items", "platform": "Console"}, "140227858": {"name": "Shard", "category": "NPC Items", "platform": "Console"}, "-1223968557": {"name": "Shard of Resurrection", "category": "NPC Items", "platform": "Console"}, "-1703187309": {"name": "Shen's Loot", "category": "NPC Items", "platform": "Console"}, "753721399": {"name": "Skeleton King's Crown", "category": "NPC Items", "platform": "Console"}, "-1874288726": {"name": "Spider Queen Venom", "category": "NPC Items", "platform": "Console"}, "437383090": {"name": "Sword Blade", "category": "NPC Items", "platform": "Console"}, "-1027737429": {"name": "Sword Hilt", "category": "NPC Items", "platform": "Console"}, "457400460": {"name": "Sword Piece", "category": "NPC Items", "platform": "Console"}, "1360078715": {"name": "SwordOfJustice", "category": "NPC Items", "platform": "Console"}, "1163171450": {"name": "The Cultist's Head", "category": "NPC Items", "platform": "Console"}, "-718773999": {"name": "Three Broken Gems", "category": "NPC Items", "platform": "Console"}, "-797314365": {"name": "Town Portal Stone", "category": "NPC Items", "platform": "Console"}, "-608122705": {"name": "Treasure Hunter's Note", "category": "NPC Items", "platform": "Console"}, "1111843456": {"name": "Triune Smith's Tools", "category": "NPC Items", "platform": "Console"}, "-1062930416": {"name": "Vasily's Angelic Idol", "category": "NPC Items", "platform": "Console"}, "-290192033": {"name": "WestM_Food", "category": "NPC Items", "platform": "Console"}, "437221476": {"name": "ZakarumTotem", "category": "NPC Items", "platform": "Console"}, "-1464111916": {"name": "Zoltun Kulle Blood Vial", "category": "NPC Items", "platform": "Console"}, "609972295": {"name": "Zoltun Kulle's Blue Eye", "category": "NPC Items", "platform": "Console"}, "-1341834850": {"name": "Zoltun Kulle's Body", "category": "NPC Items", "platform": "Console"}, "395877111": {"name": "Zoltun Kulle's Completed Head", "category": "NPC Items", "platform": "Console"}, "-1345664746": {"name": "Zoltun Kulle's Head", "category": "NPC Items", "platform": "Console"}, "-674931800": {"name": "Zoltun Kulle's One Eyed Head", "category": "NPC Items", "platform": "Console"}, "-1345750695": {"name": "Zoltun Kulle's Red Eye", "category": "NPC Items", "platform": "Console"}, "892508204": {"name": "Zoltun Kulle's Rotting Head", "category": "NPC Items", "platform": "Console"}, "414825604": {"name": "Zoltun Kulle's Tome of the Nephalem", "category": "NPC Items", "platform": "Console"}, "-649774063": {"name": "px_DevilsHand_TestGlobe (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "87458782": {"name": "px_DevilsHand_TestGlobe_Dropped (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "-590920597": {"name": "Art_Test_Pants_10 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920596": {"name": "Art_Test_Pants_11 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920595": {"name": "Art_Test_Pants_12 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920594": {"name": "Art_Test_Pants_13 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920593": {"name": "Art_Test_Pants_14 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598560": {"name": "Art_Test_Pants_6 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598561": {"name": "Art_Test_Pants_7 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598562": {"name": "Art_Test_Pants_8 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598563": {"name": "Art_Test_Pants_9 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-1512732138": {"name": "01: Cloth Pants (AR 6-7)", "category": "Pants", "platform": "Console"}, "-1512732137": {"name": "02: Leather Pants (AR 18-21)", "category": "Pants", "platform": "Console"}, "-1512732136": {"name": "03: Hide Breeches (AR 33-38)", "category": "Pants", "platform": "Console"}, "-1512732135": {"name": "04: Chain Leggings (AR 48-62)", "category": "Pants", "platform": "Console"}, "-1512732134": {"name": "05: Faulds (AR 63-77)", "category": "Pants", "platform": "Console"}, "-1512732133": {"name": "06: Plate Leggings (AR 78-101)", "category": "Pants", "platform": "Console"}, "-1512731049": {"name": "07: Legwraps (AR 102-131)", "category": "Pants", "platform": "Console"}, "-1512731048": {"name": "08: Etched Pants (AR 132-161)", "category": "Pants", "platform": "Console"}, "-1512731047": {"name": "09: Chausses (AR 162-191)", "category": "Pants", "platform": "Console"}, "-1512731046": {"name": "10: Tassets (AR 192-224)", "category": "Pants", "platform": "Console"}, "-1512731045": {"name": "11: Boneweave Faulds (AR 225-247)", "category": "Pants", "platform": "Console"}, "-1512729960": {"name": "12: Leg Guards (AR 27-269)", "category": "Pants", "platform": "Console"}, "-1512729959": {"name": "13: Poleyns (AR 270-284)", "category": "Pants", "platform": "Console"}, "-1512729958": {"name": "14: Warlord Leg Plates (AR 285-322)", "category": "Pants", "platform": "Console"}, "-1512729957": {"name": "15: Schynbalds (AR 322-359)", "category": "Pants", "platform": "Console"}, "-1512729956": {"name": "16: Sovereign Tassets (AR 360-397)", "category": "Pants", "platform": "Console"}, "-1512729955": {"name": "17: Archon Faulds (AR 397-471)", "category": "Pants", "platform": "Console"}, "-1512729954": {"name": "18: Rakkisgard Leg Plates (AR 472-659)", "category": "Pants", "platform": "Console"}, "-1512729953": {"name": "19: Ascended Faulds (AR 660-759)", "category": "Pants", "platform": "Console"}, "1283598555": {"name": "Art Test Pants 1", "category": "Pants", "platform": "Console"}, "1283598556": {"name": "Art Test Pants 2", "category": "Pants", "platform": "Console"}, "1283598557": {"name": "Art Test Pants 3", "category": "Pants", "platform": "Console"}, "1283598558": {"name": "Art Test Pants 4", "category": "Pants", "platform": "Console"}, "1283598559": {"name": "Art Test Pants 5", "category": "Pants", "platform": "Console"}, "-586378095": {"name": "Legendary: Conqueror's Legguards (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "-735317930": {"name": "Legendary: Death's Bargain", "category": "Pants", "platform": "Console"}, "-774309575": {"name": "Legendary: Depth Diggers", "category": "Pants", "platform": "Console"}, "217510501": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "217512945": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "903144209": {"name": "Legendary: Depth Diggers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774309839": {"name": "Legendary: Depth Diggers (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "216324580": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "216327024": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "903144208": {"name": "Legendary: Gehennas (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774453323": {"name": "Legendary: Hammer Jammers", "category": "Pants", "platform": "Console"}, "212766817": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "212769261": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "903144205": {"name": "Legendary: Hammer Jammers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-735353867": {"name": "Legendary: Hexing Pants of Mr. Yan", "category": "Pants", "platform": "Console"}, "-305758345": {"name": "Legendary: Legs of the Sealed Valley", "category": "Pants", "platform": "Console"}, "-774273638": {"name": "Legendary: Pox Faulds", "category": "Pants", "platform": "Console"}, "218696422": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "218698866": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "903144210": {"name": "Legendary: Pox Faulds (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774345512": {"name": "Legendary: Skelon's Deceit", "category": "Pants", "platform": "Console"}, "-774489260": {"name": "Legendary: Swamp Land Waders", "category": "Pants", "platform": "Console"}, "211580896": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "211583340": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "903144204": {"name": "Legendary: Swamp Land Waders (Old-Legacy)", "category": "Pants", "platform": "Console"}, "903144212": {"name": "Set: Asheara's Cradle (Old-Legacy)", "category": "Pants", "platform": "Console"}, "221068264": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "221070708": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "-774201764": {"name": "Set: Asheara's Pace", "category": "Pants", "platform": "Console"}, "903144239": {"name": "Set: Blackthorne's Breeches (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773231465": {"name": "Set: Blackthorne's Jousting Mail", "category": "Pants", "platform": "Console"}, "253088131": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "253090575": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "-773339276": {"name": "Set: Cain's Habit", "category": "Pants", "platform": "Console"}, "903144236": {"name": "Set: Cain's Raiment (Old-Legacy)", "category": "Pants", "platform": "Console"}, "249530368": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "249532812": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "251902210": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "251904654": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "903144238": {"name": "Set: Captain Crimson's Codpiece (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773267402": {"name": "Set: Captain Crimson's Thrust", "category": "Pants", "platform": "Console"}, "825937515": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827015887": {"name": "Set: Cuisses of Akkhan", "category": "Pants", "platform": "Console"}, "903144240": {"name": "Set: Demon's Flesh (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773195528": {"name": "Set: Demon's Plate", "category": "Pants", "platform": "Console"}, "254274052": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "254276496": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "826045588": {"name": "Set: Firebird's Down", "category": "Pants", "platform": "Console"}, "827231509": {"name": "Set: Helltooth Leg Guards", "category": "Pants", "platform": "Console"}, "-184773474": {"name": "Set: Immortal King's Stature (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "903144211": {"name": "Set: Inna's Glory (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774237701": {"name": "Set: Inna's Temperance", "category": "Pants", "platform": "Console"}, "219882343": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "219884787": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "826153399": {"name": "Set: Jade Harvester's Courage", "category": "Pants", "platform": "Console"}, "825901577": {"name": "Set: Leg Guards of Mystery (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826081525": {"name": "Set: Marauder's Encasement", "category": "Pants", "platform": "Console"}, "825865641": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773475": {"name": "Set: Natalya's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826009651": {"name": "Set: Raekor's Breeches", "category": "Pants", "platform": "Console"}, "825865639": {"name": "Set: Roland's Determination (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "826117462": {"name": "Set: Scales of the Dancing Serpent", "category": "Pants", "platform": "Console"}, "827051824": {"name": "Set: Sunwuko's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773473": {"name": "Set: Tal Rasha's Stride (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "825865640": {"name": "Set: Tasset of the Wastes (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827159635": {"name": "Set: The Shadow's Coil", "category": "Pants", "platform": "Console"}, "825937514": {"name": "Set: Unholy Plates (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827123698": {"name": "Set: Vyr's Fantastic Finery", "category": "Pants", "platform": "Console"}, "827195572": {"name": "Set: Weight of the Earth", "category": "Pants", "platform": "Console"}, "825901578": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773472": {"name": "Set: Zunimassa's Cloth (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-774273901": {"name": "legendary: Pox Faulds (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-1337763520": {"name": "01: Bardiche (DPS 11.4-12.4)", "category": "Polearms", "platform": "Console"}, "-1337763519": {"name": "02: Pike (DPS 15.2-16.6)", "category": "Polearms", "platform": "Console"}, "-1337763518": {"name": "03: Guisarme (DPS 20.4-21.9)", "category": "Polearms", "platform": "Console"}, "-1337763517": {"name": "04: Hache (DPS 24.7-26.1)", "category": "Polearms", "platform": "Console"}, "-1337763516": {"name": "05: Glaive (DPS 31.8-33.3)", "category": "Polearms", "platform": "Console"}, "-1337763515": {"name": "06: Pole Axe (DPS 38.0-40.9)", "category": "Polearms", "platform": "Console"}, "-1337763514": {"name": "07: Halberd (DPS 41.3-44.2)", "category": "Polearms", "platform": "Console"}, "-1337763513": {"name": "08: Lance (DPS 50.8-53.7)", "category": "Polearms", "platform": "Console"}, "-1337762431": {"name": "09: Voulge (DPS 58.0-60.8)", "category": "Polearms", "platform": "Console"}, "-1337762430": {"name": "10: Naginata (DPS 70.3-74.6)", "category": "Polearms", "platform": "Console"}, "-1337762429": {"name": "11: Croc (DPS 79.8-84.1)", "category": "Polearms", "platform": "Console"}, "-1337762428": {"name": "12: Battle Hache (DPS 91.7-96.0)", "category": "Polearms", "platform": "Console"}, "-1337762427": {"name": "13: Bisento (DPS 101.7-107.4)", "category": "Polearms", "platform": "Console"}, "-1337762426": {"name": "14: Great Pole Axe (DPS 116.4-122.1)", "category": "Polearms", "platform": "Console"}, "-1337762425": {"name": "15: Battle Halberd (DPS 131.1-138.2)", "category": "Polearms", "platform": "Console"}, "-1337762424": {"name": "16: Partizan (DPS 156.3-163.4)", "category": "Polearms", "platform": "Console"}, "-1337761342": {"name": "17: Lochaber Axe (DPS 191.9-200.5)", "category": "Polearms", "platform": "Console"}, "-1337761341": {"name": "18: Fauchard (DPS 223.3-233.2)", "category": "Polearms", "platform": "Console"}, "-1337761340": {"name": "19: Skewer (DPS 260.8-272.2)", "category": "Polearms", "platform": "Console"}, "-1337761339": {"name": "20: War Crest (DPS 305.0-316.4)", "category": "Polearms", "platform": "Console"}, "-1337761338": {"name": "21: Kwan Dao (DPS 355.8-367.2)", "category": "Polearms", "platform": "Console"}, "-1337761337": {"name": "22: War Thresher (DPS 421.3-432.7)", "category": "Polearms", "platform": "Console"}, "-1337761336": {"name": "23: Grand Halberd (DPS 499.2-510.6)", "category": "Polearms", "platform": "Console"}, "-1337761335": {"name": "24: Dread Lance (DPS 590.0-601.4)", "category": "Polearms", "platform": "Console"}, "-1337760253": {"name": "25: Trident (DPS 739.7-752.3)", "category": "Polearms", "platform": "Console"}, "-1337760252": {"name": "26: Trishula (DPS 1009.1-1021.7)", "category": "Polearms", "platform": "Console"}, "-1558359355": {"name": "Art Test Polearm 1", "category": "Polearms", "platform": "Console"}, "-1558359354": {"name": "Art Test Polearm 2", "category": "Polearms", "platform": "Console"}, "-1558359353": {"name": "Art Test Polearm 3", "category": "Polearms", "platform": "Console"}, "-1558359352": {"name": "Art Test Polearm 4", "category": "Polearms", "platform": "Console"}, "-1558359351": {"name": "Art Test Polearm 5", "category": "Polearms", "platform": "Console"}, "-1948909473": {"name": "Legendary: Bovine Bardiche", "category": "Polearms", "platform": "Console"}, "-1948873536": {"name": "Legendary: Foushee Voulge", "category": "Polearms", "platform": "Console"}, "-1987972992": {"name": "Legendary: Heart Slaughter", "category": "Polearms", "platform": "Console"}, "-1178676596": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "-1178674152": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587768": {"name": "Legendary: Heart Slaughter (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987973256": {"name": "Legendary: Heart Slaughter (Patch 2.1.0)", "category": "Polearms", "platform": "Console"}, "-1988008929": {"name": "Legendary: Pledge of Caldeum", "category": "Polearms", "platform": "Console"}, "-1179862517": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "-1179860073": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587767": {"name": "Legendary: Pledge of Caldeum (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987937055": {"name": "Legendary: Standoff", "category": "Polearms", "platform": "Console"}, "-1177490675": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "-1177488231": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587769": {"name": "Legendary: Standoff (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1988044866": {"name": "Legendary: Vigilance", "category": "Polearms", "platform": "Console"}, "-1181048438": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "-1181045994": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587766": {"name": "Legendary: Vigilance (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "1539236300": {"name": "01: Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236301": {"name": "02: Canvas Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236302": {"name": "03: Leather Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236303": {"name": "04: Hunting Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236304": {"name": "05: Assassin Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539237389": {"name": "06: Heavy Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237390": {"name": "07: Barbed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237391": {"name": "08: Hallowed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237392": {"name": "09: Stalker Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237393": {"name": "10: Razorspine Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238478": {"name": "11: Deadeye Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238479": {"name": "12: Bonetooth Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238480": {"name": "13: Consecrated Quiver (ASI 13.0%)", "category": "Quivers", "platform": "Console"}, "1539238481": {"name": "14: Runic Quiver (ASI 14.0%)", "category": "Quivers", "platform": "Console"}, "1539238482": {"name": "15: Sanctified Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238483": {"name": "16: Rakkisgard Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238484": {"name": "17: Ascended Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "-1056381007": {"name": "Art Test Quiver 1", "category": "Quivers", "platform": "Console"}, "-1056381006": {"name": "Art Test Quiver 2", "category": "Quivers", "platform": "Console"}, "-1056381005": {"name": "Art Test Quiver 3", "category": "Quivers", "platform": "Console"}, "-1056381004": {"name": "Art Test Quiver 4", "category": "Quivers", "platform": "Console"}, "-1056381003": {"name": "Art Test Quiver 5", "category": "Quivers", "platform": "Console"}, "-400507188": {"name": "Legendary: Archfiend Arrows", "category": "Quivers", "platform": "Console"}, "-331912616": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-331910172": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223036": {"name": "Legendary: Black Bone Arrows (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361407732": {"name": "Legendary: Bombadier's Rucksack", "category": "Quivers", "platform": "Console"}, "-400363440": {"name": "Legendary: Dead Man's Legacy", "category": "Quivers", "platform": "Console"}, "-327168932": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-327166488": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223032": {"name": "Legendary: Dead Man's Legacy (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361371795": {"name": "Legendary: Emimei's Duffel", "category": "Quivers", "platform": "Console"}, "-400399377": {"name": "Legendary: Fletcher's Pride", "category": "Quivers", "platform": "Console"}, "-328354853": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-328352409": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223033": {"name": "Legendary: Fletcher's Pride (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400579062": {"name": "Legendary: Flint Ripper Arrowheads", "category": "Quivers", "platform": "Console"}, "-334284458": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-334282014": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223038": {"name": "Legendary: Flint Ripper Arrowheads (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400471251": {"name": "Legendary: Holy Point Shot", "category": "Quivers", "platform": "Console"}, "-330726695": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-330724251": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223035": {"name": "Legendary: Holy Point Shot (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361335858": {"name": "Legendary: Hunter's Longbox", "category": "Quivers", "platform": "Console"}, "-400579326": {"name": "Legendary: Meticulous Bolts (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-400435314": {"name": "Legendary: Silver Star Piercers", "category": "Quivers", "platform": "Console"}, "-329540774": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-329538330": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223034": {"name": "Legendary: Silver Star Piercers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400543125": {"name": "Legendary: Sin Seekers", "category": "Quivers", "platform": "Console"}, "-333098537": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-333096093": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223037": {"name": "Legendary: Sin Seekers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400435578": {"name": "Legendary: Spines of Seething Hatred (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-361443669": {"name": "Legendary: The Ninth Cirri Satchel", "category": "Quivers", "platform": "Console"}, "564938473": {"name": "legendary: Dead Man's Legacy (Patch 2.2.0)", "category": "Quivers", "platform": "Console"}, "1146967280": {"name": "01: Ring", "category": "Rings", "platform": "Console"}, "1146967281": {"name": "02: Ring", "category": "Rings", "platform": "Console"}, "1146967282": {"name": "03: Ring", "category": "Rings", "platform": "Console"}, "1146967283": {"name": "04: Ring", "category": "Rings", "platform": "Console"}, "1146967284": {"name": "05: Ring", "category": "Rings", "platform": "Console"}, "1146967285": {"name": "06: Ring", "category": "Rings", "platform": "Console"}, "1146967286": {"name": "07: Ring", "category": "Rings", "platform": "Console"}, "1146967287": {"name": "08: Ring", "category": "Rings", "platform": "Console"}, "1146967288": {"name": "09: Ring", "category": "Rings", "platform": "Console"}, "1146967312": {"name": "10: Ring", "category": "Rings", "platform": "Console"}, "1146967313": {"name": "11: Ring", "category": "Rings", "platform": "Console"}, "1146967314": {"name": "12: Ring", "category": "Rings", "platform": "Console"}, "1146967315": {"name": "13: Ring", "category": "Rings", "platform": "Console"}, "1146967316": {"name": "14: Ring", "category": "Rings", "platform": "Console"}, "1146967317": {"name": "15: Ring", "category": "Rings", "platform": "Console"}, "1146967318": {"name": "16: Ring", "category": "Rings", "platform": "Console"}, "1146967319": {"name": "17: Ring", "category": "Rings", "platform": "Console"}, "1146967320": {"name": "18: Ring", "category": "Rings", "platform": "Console"}, "1146967321": {"name": "19: Ring", "category": "Rings", "platform": "Console"}, "1146967345": {"name": "20: Ring", "category": "Rings", "platform": "Console"}, "1146967346": {"name": "21: Ring", "category": "Rings", "platform": "Console"}, "1146967347": {"name": "22: Ring", "category": "Rings", "platform": "Console"}, "1146967348": {"name": "23: Ring", "category": "Rings", "platform": "Console"}, "1146967349": {"name": "24: Ring", "category": "Rings", "platform": "Console"}, "1146967350": {"name": "25: Ring", "category": "Rings", "platform": "Console"}, "1818597029": {"name": "Art Test Ring 1", "category": "Rings", "platform": "Console"}, "1818597030": {"name": "Art Test Ring 2", "category": "Rings", "platform": "Console"}, "1818597031": {"name": "Art Test Ring 3", "category": "Rings", "platform": "Console"}, "1818597032": {"name": "Art Test Ring 4", "category": "Rings", "platform": "Console"}, "1818597033": {"name": "Art Test Ring 5", "category": "Rings", "platform": "Console"}, "-1149557626": {"name": "Legendary: Avarice Band", "category": "Rings", "platform": "Console"}, "-1188944578": {"name": "Legendary: Band of Hollow Whispers", "category": "Rings", "platform": "Console"}, "-580542710": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-580540266": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-731577034": {"name": "Legendary: Band of Hollow Whispers (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188657082": {"name": "Legendary: Band of Untold Secrets", "category": "Rings", "platform": "Console"}, "-571055342": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-571052898": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-731577026": {"name": "Legendary: Band of Untold Secrets (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149629500": {"name": "Legendary: Band of the Rue Chambers", "category": "Rings", "platform": "Console"}, "-1188764893": {"name": "Legendary: Broken Promises", "category": "Rings", "platform": "Console"}, "-574613105": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-574610661": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-731577029": {"name": "Legendary: Broken Promises (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186608673": {"name": "Legendary: Bul-Kathos's Wedding Band", "category": "Rings", "platform": "Console"}, "-503457845": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-503455401": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-731576969": {"name": "Legendary: Bul-Kathos's Wedding Band (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188728956": {"name": "Legendary: Eternal Union", "category": "Rings", "platform": "Console"}, "-573427184": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-573424740": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-731577028": {"name": "Legendary: Eternal Union (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188729220": {"name": "Legendary: Eternal Union (Patch 2.1.0)", "category": "Rings", "platform": "Console"}, "-1149665437": {"name": "Legendary: Gamuel's Deceit", "category": "Rings", "platform": "Console"}, "425752007": {"name": "Legendary: Halo Of Arlyse (Patch 2.1.2)", "category": "Rings", "platform": "Console"}, "-1186464925": {"name": "Legendary: Hellfire Ring", "category": "Rings", "platform": "Console"}, "-498714161": {"name": "Legendary: Hellfire Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-578170868": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-578168424": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-731577032": {"name": "Legendary: Hierophant's Seal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188693019": {"name": "Legendary: Justice Lantern", "category": "Rings", "platform": "Console"}, "-572241263": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-572238819": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-731577027": {"name": "Legendary: Justice Lantern (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188872704": {"name": "Legendary: Krede's Flame", "category": "Rings", "platform": "Console"}, "1963121073": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-159638916": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-1188908641": {"name": "Legendary: Leoric's Signet", "category": "Rings", "platform": "Console"}, "-579356789": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-579354345": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-731577033": {"name": "Legendary: Leoric's Signet (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186572736": {"name": "Legendary: Manald Heal", "category": "Rings", "platform": "Console"}, "-502271924": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-502269480": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-731576968": {"name": "Legendary: Manald Heal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187507098": {"name": "Legendary: Nagelring", "category": "Rings", "platform": "Console"}, "-533105870": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-533103426": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576994": {"name": "Legendary: Nagelring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186500862": {"name": "Legendary: Obsidian Ring of the Zodiac", "category": "Rings", "platform": "Console"}, "-499900082": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-499897638": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-731576966": {"name": "Legendary: Obsidian Ring of the Zodiac (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187543035": {"name": "Legendary: Oculus Ring", "category": "Rings", "platform": "Console"}, "-534291791": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-534289347": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576995": {"name": "Legendary: Oculus Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149521689": {"name": "Legendary: Pandemonium Loop", "category": "Rings", "platform": "Console"}, "-1188836767": {"name": "Legendary: Puzzle Ring", "category": "Rings", "platform": "Console"}, "-576984947": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-576982503": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577031": {"name": "Legendary: Puzzle Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149701374": {"name": "Legendary: Rechel's Ring of Larceny", "category": "Rings", "platform": "Console"}, "-1149593563": {"name": "Legendary: Ring of Royal Grandeur", "category": "Rings", "platform": "Console"}, "-1149737311": {"name": "Legendary: Rogar's Huge Stone", "category": "Rings", "platform": "Console"}, "-611901958": {"name": "Legendary: Signet Ring of the Blizzard", "category": "Rings", "platform": "Console"}, "-1186536799": {"name": "Legendary: Skull Grasp", "category": "Rings", "platform": "Console"}, "-501086003": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-501083559": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-731576967": {"name": "Legendary: Skull Grasp (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188800830": {"name": "Legendary: Stolen Ring", "category": "Rings", "platform": "Console"}, "-575799026": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-575796582": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577030": {"name": "Legendary: Stolen Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187471161": {"name": "Legendary: Stone of Jordan", "category": "Rings", "platform": "Console"}, "-531919949": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-531917505": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-731576993": {"name": "Legendary: Stone of Jordan (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149809185": {"name": "Legendary: The Tall Man's Finger", "category": "Rings", "platform": "Console"}, "-1187794594": {"name": "Legendary: Unity", "category": "Rings", "platform": "Console"}, "-542593238": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-542590794": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-731577002": {"name": "Legendary: Unity (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149773248": {"name": "Legendary: Wyrdward", "category": "Rings", "platform": "Console"}, "-1585363882": {"name": "P1_Ring_001 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363881": {"name": "P1_Ring_002 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363880": {"name": "P1_Ring_003 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363879": {"name": "P1_Ring_004 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "2082266421": {"name": "PvP: Echo Band All", "category": "Rings", "platform": "Console"}, "2082266693": {"name": "PvP: Echo Band Attack", "category": "Rings", "platform": "Console"}, "2082269451": {"name": "PvP: Echo Band Defense", "category": "Rings", "platform": "Console"}, "-4139386": {"name": "PvP: Echo Band Precision", "category": "Rings", "platform": "Console"}, "2082289199": {"name": "PvP: Echo Band Vitality", "category": "Rings", "platform": "Console"}, "-3897388": {"name": "PvP: Echo Band Willpower", "category": "Rings", "platform": "Console"}, "-2095294696": {"name": "PvP: Sherman Signet All", "category": "Rings", "platform": "Console"}, "-2095294424": {"name": "PvP: Sherman Signet Attack", "category": "Rings", "platform": "Console"}, "-2095291666": {"name": "PvP: Sherman Signet Defense", "category": "Rings", "platform": "Console"}, "-424702775": {"name": "PvP: Sherman Signet Precision", "category": "Rings", "platform": "Console"}, "-2095271918": {"name": "PvP: Sherman Signet Vitality", "category": "Rings", "platform": "Console"}, "-731576997": {"name": "Set: Band of Fallen Heroes (Old-Legacy)", "category": "Rings", "platform": "Console"}, "1978116233": {"name": "Set: Focus", "category": "Rings", "platform": "Console"}, "-1187614909": {"name": "Set: Litany of the Undaunted", "category": "Rings", "platform": "Console"}, "-536663633": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-536661189": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-731577001": {"name": "Set: Natalya's Mark (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187758657": {"name": "Set: Natalya's Reflection", "category": "Rings", "platform": "Console"}, "-541407317": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "-541404873": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "1978152170": {"name": "Set: Restraint", "category": "Rings", "platform": "Console"}, "-731576998": {"name": "Set: Screaming Chain (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187686783": {"name": "Set: The Compass Rose", "category": "Rings", "platform": "Console"}, "-539035475": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-539033031": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-1187650846": {"name": "Set: The Wailing Host", "category": "Rings", "platform": "Console"}, "-537849554": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-537847110": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-731576999": {"name": "Set: Wanderlust (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-731577000": {"name": "Set: Zunimassa's Plague (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187722720": {"name": "Set: Zunimassa's Pox", "category": "Rings", "platform": "Console"}, "-540221396": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "-540218952": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "417069417": {"name": "legendary: Arcstone (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1188765156": {"name": "legendary: Broken Promises (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069418": {"name": "legendary: Convention Of Elements (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187507361": {"name": "legendary: Nagelring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187543298": {"name": "legendary: Oculus Ring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149521952": {"name": "legendary: Pandemonium Loop (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1186501125": {"name": "legendary: Ring of the Zodiac (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069415": {"name": "legendary: Skull Grasp (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069416": {"name": "legendary: The Short Man's Finger (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149773511": {"name": "legendary: Wyrdward (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-229902049": {"name": "01: Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229902048": {"name": "02: Glass Blade", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900960": {"name": "03: Loaded Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900959": {"name": "04: Crystal Edge", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900958": {"name": "05: Clasp", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900957": {"name": "06: Sand Pouch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899871": {"name": "07: Bone Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899870": {"name": "08: Diamond Razor", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899869": {"name": "09: Brooch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899868": {"name": "10: Dust Satchel", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899867": {"name": "11: Hazard", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899866": {"name": "12: Stinger", "category": "Scoundrel Tokens", "platform": "Console"}, "978821514": {"name": "Legendary: Ribald Etchings", "category": "Scoundrel Tokens", "platform": "Console"}, "978821513": {"name": "Legendary: Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "978821515": {"name": "Legendary: Slipka's Letter Opener", "category": "Scoundrel Tokens", "platform": "Console"}, "-978821513": {"name": "Legendary:Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "1815806856": {"name": "00: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806857": {"name": "01: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806858": {"name": "02: Targe Shield (AR 48-55)", "category": "Shields", "platform": "Console"}, "1815806859": {"name": "03: Heater Shield (AR 88-101)", "category": "Shields", "platform": "Console"}, "1815806860": {"name": "04: Kite Shield (AR 128-167)", "category": "Shields", "platform": "Console"}, "1815806861": {"name": "05: Large Shield (AR 168-199)", "category": "Shields", "platform": "Console"}, "1815806862": {"name": "06: Gothic Shield (AR 200-223)", "category": "Shields", "platform": "Console"}, "1815806863": {"name": "07: Tower Shield (AR 224-255)", "category": "Shields", "platform": "Console"}, "1815807946": {"name": "08: Pelta (AR 256-319)", "category": "Shields", "platform": "Console"}, "1815807947": {"name": "09: Rondache (AR 320-383)", "category": "Shields", "platform": "Console"}, "1815807948": {"name": "10: Knight Shield (AR 384-447)", "category": "Shields", "platform": "Console"}, "1815807949": {"name": "11: Ironwood Shield (AR 448-511)", "category": "Shields", "platform": "Console"}, "1815807950": {"name": "12: Pavise (AR 512-579)", "category": "Shields", "platform": "Console"}, "1815807951": {"name": "13: Bone Shield (AR 580-619)", "category": "Shields", "platform": "Console"}, "1815807952": {"name": "14: Savior (AR 620-659)", "category": "Shields", "platform": "Console"}, "1815809035": {"name": "15: Aspis (AR 660-699)", "category": "Shields", "platform": "Console"}, "1815809036": {"name": "16: Hoplon (AR 700-739)", "category": "Shields", "platform": "Console"}, "1815809037": {"name": "17: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "-335464095": {"name": "17b: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "1815809038": {"name": "18: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "-334278174": {"name": "18b: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "1815809039": {"name": "19: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "-333092253": {"name": "19b: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "1815809040": {"name": "20: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "-331906332": {"name": "20b: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "1815809041": {"name": "21: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "-330720411": {"name": "21b: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "1815809042": {"name": "22: Rakkisgard Shield (AR 1260-1759)", "category": "Shields", "platform": "Console"}, "1815809043": {"name": "23: Ascended Shield (AR 1760-2024)", "category": "Shields", "platform": "Console"}, "-1347979730": {"name": "Art Test Shield 1", "category": "Shields", "platform": "Console"}, "-1347979729": {"name": "Art Test Shield 2", "category": "Shields", "platform": "Console"}, "-1347979728": {"name": "Art Test Shield 3", "category": "Shields", "platform": "Console"}, "-1347979727": {"name": "Art Test Shield 4", "category": "Shields", "platform": "Console"}, "-1347979726": {"name": "Art Test Shield 5", "category": "Shields", "platform": "Console"}, "200412170": {"name": "Legendary: Amazonian Parma", "category": "Shields", "platform": "Console"}, "200519981": {"name": "Legendary: Beastguard", "category": "Shields", "platform": "Console"}, "1028274966": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "1028277410": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "-64652478": {"name": "Legendary: Centurion (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200555918": {"name": "Legendary: Coven's Criterion", "category": "Shields", "platform": "Console"}, "200340296": {"name": "Legendary: Defender of Westmarch", "category": "Shields", "platform": "Console"}, "161420525": {"name": "Legendary: Denial", "category": "Shields", "platform": "Console"}, "1031832729": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "1031835173": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "-64652475": {"name": "Legendary: Denial (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200376233": {"name": "Legendary: Eberli Charo", "category": "Shields", "platform": "Console"}, "161312714": {"name": "Legendary: Freeze of Deflection", "category": "Shields", "platform": "Console"}, "161240840": {"name": "Legendary: Ivory Tower", "category": "Shields", "platform": "Console"}, "1025903124": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "1025905568": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "-64652480": {"name": "Legendary: Ivory Tower (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161456462": {"name": "Legendary: Lidless Wall", "category": "Shields", "platform": "Console"}, "1033018650": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "1033021094": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "-64652474": {"name": "Legendary: Lidless Wall (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161492399": {"name": "Legendary: Stormshield", "category": "Shields", "platform": "Console"}, "1034204571": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "1034207015": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "-64652473": {"name": "Legendary: Stormshield (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200448107": {"name": "Legendary: Vo'Toyias Spiker", "category": "Shields", "platform": "Console"}, "1063852596": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "1063855040": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "-64652448": {"name": "Legendary: Wall of Bone (Old-Legacy)", "category": "Shields", "platform": "Console"}, "162390824": {"name": "Legendary: Wall of Man", "category": "Shields", "platform": "Console"}, "200484044": {"name": "Legendary: Wretchskin", "category": "Shields", "platform": "Console"}, "162426761": {"name": "Set: Hallowed Barricade", "category": "Shields", "platform": "Console"}, "-64652447": {"name": "Set: Hallowed Barrier (Old-Legacy)", "category": "Shields", "platform": "Console"}, "1065038517": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "1065040961": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "200340033": {"name": "legendary: Defender Of Westmarch (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509030": {"name": "legendary: Denial (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509025": {"name": "legendary: Ivory Tower (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "-519190663": {"name": "legendary: Stormshield (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "365490250": {"name": "02: Leather Mantle (AR 34-46)", "category": "Shoulders", "platform": "Console"}, "365490251": {"name": "03: Shoulder Guards (AR 48-58)", "category": "Shoulders", "platform": "Console"}, "365490252": {"name": "04: Amice (AR 58-68)", "category": "Shoulders", "platform": "Console"}, "365490253": {"name": "05: Spaulders (AR 69-79)", "category": "Shoulders", "platform": "Console"}, "365490254": {"name": "06: Shoulder Plates (AR 80-100)", "category": "Shoulders", "platform": "Console"}, "365491338": {"name": "07: Etched Mantle (AR 101-121)", "category": "Shoulders", "platform": "Console"}, "365491339": {"name": "08: Ailettes (AR 122-142)", "category": "Shoulders", "platform": "Console"}, "365491340": {"name": "09: Pauldrons (AR 144-164)", "category": "Shoulders", "platform": "Console"}, "365491341": {"name": "10: Sode (AR 165-199)", "category": "Shoulders", "platform": "Console"}, "365491342": {"name": "11: Epaulets (AR 200-219)", "category": "Shoulders", "platform": "Console"}, "365492427": {"name": "12: Balor Pauldrons (AR 220-239)", "category": "Shoulders", "platform": "Console"}, "365492428": {"name": "13: Espaliers (AR 240-252)", "category": "Shoulders", "platform": "Console"}, "365492429": {"name": "14: Warlord Spaulders (AR 253-285)", "category": "Shoulders", "platform": "Console"}, "365492430": {"name": "15: Doom Pauldrons (AR 286-318)", "category": "Shoulders", "platform": "Console"}, "365492431": {"name": "16: Pallium (AR 320-352)", "category": "Shoulders", "platform": "Console"}, "365492432": {"name": "17: Archon Spaulders (AR 353-419)", "category": "Shoulders", "platform": "Console"}, "365492433": {"name": "18: Rakkisgard Pauldrons (AR 420-586)", "category": "Shoulders", "platform": "Console"}, "365492434": {"name": "19: Ascended Pauldrons (AR 586-674)", "category": "Shoulders", "platform": "Console"}, "-1869550021": {"name": "Art Test Shoulder 1", "category": "Shoulders", "platform": "Console"}, "-1869550020": {"name": "Art Test Shoulder 2", "category": "Shoulders", "platform": "Console"}, "-1869550019": {"name": "Art Test Shoulder 3", "category": "Shoulders", "platform": "Console"}, "-1869550018": {"name": "Art Test Shoulder 4", "category": "Shoulders", "platform": "Console"}, "-1869550017": {"name": "Art Test Shoulder 5", "category": "Shoulders", "platform": "Console"}, "-1565608501": {"name": "Art_Test_Shoulder_10 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608500": {"name": "Art_Test_Shoulder_11 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608499": {"name": "Art_Test_Shoulder_12 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550016": {"name": "Art_Test_Shoulder_6 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550015": {"name": "Art_Test_Shoulder_7 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550014": {"name": "Art_Test_Shoulder_8 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550013": {"name": "Art_Test_Shoulder_9 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-248496224": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "-248493780": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734028": {"name": "Legendary: Barter Town Pads (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "2112365407": {"name": "Legendary: Burdens of the Brave Survivor", "category": "Shoulders", "platform": "Console"}, "1902294393": {"name": "Legendary: Conqueror's Pauldrons (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1959570086": {"name": "Legendary: Corruption", "category": "Shoulders", "platform": "Console"}, "-1959749771": {"name": "Legendary: Death Watch Mantle", "category": "Shoulders", "platform": "Console"}, "-247310303": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "-247307859": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734029": {"name": "Legendary: Death Watch Mantle (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959785708": {"name": "Legendary: Homing Pads", "category": "Shoulders", "platform": "Console"}, "507255184": {"name": "Legendary: Infernal Pauldrons", "category": "Shoulders", "platform": "Console"}, "-1920578441": {"name": "Legendary: Pauldrons of the Skeleton King", "category": "Shoulders", "platform": "Console"}, "-1920650315": {"name": "Legendary: Profane Pauldrons", "category": "Shoulders", "platform": "Console"}, "-241380698": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "-241378254": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734034": {"name": "Legendary: Seven Sins (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1920614378": {"name": "Legendary: Spaulders of Zakara", "category": "Shoulders", "platform": "Console"}, "1277749690": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-419021771": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-1959713834": {"name": "Legendary: Vile Ward", "category": "Shoulders", "platform": "Console"}, "-246124382": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "-246121938": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734030": {"name": "Legendary: Vile Ward (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959714098": {"name": "Legendary: Vile Ward (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1958384165": {"name": "Set: Asheara's Custodian", "category": "Shoulders", "platform": "Console"}, "-202245305": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "-202242861": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734067": {"name": "Set: Asheara's Vigilance (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959534149": {"name": "Set: Aughild's Power", "category": "Shoulders", "platform": "Console"}, "-240194777": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "-240192333": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734035": {"name": "Set: Aughild's Triumph (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-242566619": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "-242564175": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734033": {"name": "Set: Born's Pauldrons (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959606023": {"name": "Set: Born's Privilege", "category": "Shoulders", "platform": "Console"}, "-1980689583": {"name": "Set: Burden of the Invoker", "category": "Shoulders", "platform": "Console"}, "-1981839829": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875767": {"name": "Set: Dashing Pauldrons of Despair (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959498212": {"name": "Set: Demon's Aileron", "category": "Shoulders", "platform": "Console"}, "-239008856": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "-239006412": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734036": {"name": "Set: Demon's Wings (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1981731756": {"name": "Set: Firebird's Pinions", "category": "Shoulders", "platform": "Console"}, "-1980545835": {"name": "Set: Helltooth Mantle", "category": "Shoulders", "platform": "Console"}, "-1981623945": {"name": "Set: Jade Harvester's Joy", "category": "Shoulders", "platform": "Console"}, "-1981659882": {"name": "Set: Mantle of the Upside-Down Sinners", "category": "Shoulders", "platform": "Console"}, "-1981695819": {"name": "Set: Marauder's Spines", "category": "Shoulders", "platform": "Console"}, "-1981911703": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1980761457": {"name": "Set: Pauldrons of Akkhan", "category": "Shoulders", "platform": "Console"}, "-1981911704": {"name": "Set: Pauldrons of the Wastes (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981767693": {"name": "Set: Raekor's Burden", "category": "Shoulders", "platform": "Console"}, "-1981911705": {"name": "Set: Roland's Mantle (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1980581772": {"name": "Set: Spires of the Earth", "category": "Shoulders", "platform": "Console"}, "-1980725520": {"name": "Set: Sunwuko's Balance", "category": "Shoulders", "platform": "Console"}, "-1981839830": {"name": "Set: Unsanctified Shoulders (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875766": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959750034": {"name": "legendary: Death Watch Mantle (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1449741837": {"name": "legendary: Pauldrons of the Hierarch (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "1905179475": {"name": "01: Eagle Orb (+1-2 DMG)", "category": "Sources", "platform": "Console"}, "1905179476": {"name": "02: Spellbook (+(2-3)-(3-5) DMG)", "category": "Sources", "platform": "Console"}, "1905179477": {"name": "03: Smoked Spheres (+(3-5)-(4-8) DMG)", "category": "Sources", "platform": "Console"}, "1905179478": {"name": "04: Cursed Skull (+(3-6)-(4-10) DMG)", "category": "Sources", "platform": "Console"}, "1905180564": {"name": "05: Sanctuary Globe (+(4-8)-(5-13) DMG)", "category": "Sources", "platform": "Console"}, "1905180565": {"name": "06: Fiendish Folio (+(6-11)-(7-19) DMG)", "category": "Sources", "platform": "Console"}, "1905180566": {"name": "07: Triad (+(8-16)-(9-29) DMG)", "category": "Sources", "platform": "Console"}, "1905180567": {"name": "08: Screaming Skull (+(13-26)-(14-45) DMG)", "category": "Sources", "platform": "Console"}, "1905181653": {"name": "09: Power Sphere (+(17-39)-(18-114) DMG)", "category": "Sources", "platform": "Console"}, "1905181654": {"name": "10: Codex (+(19-58)-(20-213) DMG)", "category": "Sources", "platform": "Console"}, "1905181655": {"name": "11: Orbit Stones (+(24-72)-(25-265) DMG)", "category": "Sources", "platform": "Console"}, "1905181656": {"name": "12: Demi Lich (+(28-110)-(29-405) DMG)", "category": "Sources", "platform": "Console"}, "1905181657": {"name": "13: Puzzle Box (+(126-158)-(127-190) DMG)", "category": "Sources", "platform": "Console"}, "1905181658": {"name": "14: Moschen Spheres (+(262-328)-(263-394) DMG)", "category": "Sources", "platform": "Console"}, "702613912": {"name": "Art Test Orb 1", "category": "Sources", "platform": "Console"}, "702613913": {"name": "Art Test Orb 2", "category": "Sources", "platform": "Console"}, "702613914": {"name": "Art Test Orb 3", "category": "Sources", "platform": "Console"}, "702613915": {"name": "Art Test Orb 4", "category": "Sources", "platform": "Console"}, "702613916": {"name": "Art Test Orb 5", "category": "Sources", "platform": "Console"}, "-1519116524": {"name": "Legendary: Cosmic Strand", "category": "Sources", "platform": "Console"}, "2028438506": {"name": "Legendary: Gul'dan's Secret (Patch 2.1.0)", "category": "Sources", "platform": "Console"}, "-1934140787": {"name": "Legendary: Heart of Darkness", "category": "Sources", "platform": "Console"}, "-1480017068": {"name": "Legendary: Light of Grace", "category": "Sources", "platform": "Console"}, "-1480088942": {"name": "Legendary: Mirrorball", "category": "Sources", "platform": "Console"}, "-1480053005": {"name": "Legendary: Myken's Ball of Hate", "category": "Sources", "platform": "Console"}, "1408684960": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "1408687404": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "215441100": {"name": "Legendary: Singularity (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519224335": {"name": "Legendary: The Oculus", "category": "Sources", "platform": "Console"}, "1405127197": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "1405129641": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "215441097": {"name": "Legendary: The Oculus (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519152461": {"name": "Legendary: Triumvirate", "category": "Sources", "platform": "Console"}, "1407499039": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "1407501483": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "215441099": {"name": "Legendary: Triumvirate (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519080587": {"name": "Legendary: Winter Flurry", "category": "Sources", "platform": "Console"}, "1409870881": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "1409873325": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "215441101": {"name": "Legendary: Winter Flurry (Old-Legacy)", "category": "Sources", "platform": "Console"}, "215441130": {"name": "Set: Chantodo's Elemental Seal (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518038414": {"name": "Set: Chantodo's Force", "category": "Sources", "platform": "Console"}, "1444262590": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "1444265034": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "-777123311": {"name": "Set: Firebird's Eye", "category": "Sources", "platform": "Console"}, "215441131": {"name": "Set: Tal Rasha's Lidless Eye (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518002477": {"name": "Set: Tal Rasha's Unwavering Glare", "category": "Sources", "platform": "Console"}, "1445448511": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1445450955": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1175281612": {"name": "legendary: Triumvirate (Patch 2.2.0)", "category": "Sources", "platform": "Console"}, "-101312757": {"name": "01: Javelin (DPS 7.2-8.4)", "category": "Spears", "platform": "Console"}, "-101312756": {"name": "02: Fuscina (DPS 12.6-14.4)", "category": "Spears", "platform": "Console"}, "-101312755": {"name": "03: Spear (DPS 18.6-20.4)", "category": "Spears", "platform": "Console"}, "-101312754": {"name": "04: Hasta (DPS 24.6-26.4)", "category": "Spears", "platform": "Console"}, "-101312753": {"name": "05: Pilum (DPS 32.4-34.2)", "category": "Spears", "platform": "Console"}, "-101311668": {"name": "06: Angon (DPS 38.4-40.2)", "category": "Spears", "platform": "Console"}, "-101311667": {"name": "07: Assegai (DPS 48.6-50.4)", "category": "Spears", "platform": "Console"}, "-101311666": {"name": "08: War Spear (DPS 60.6-62.4)", "category": "Spears", "platform": "Console"}, "-101311665": {"name": "09: Spontoon (DPS 84.6-88.2)", "category": "Spears", "platform": "Console"}, "-101311664": {"name": "10: Yari (DPS 127.8-133.2)", "category": "Spears", "platform": "Console"}, "-101310579": {"name": "11: Harpoon (DPS 151.8-157.2)", "category": "Spears", "platform": "Console"}, "-101310578": {"name": "12: Impaler (DPS 178.2-185.4)", "category": "Spears", "platform": "Console"}, "-101310577": {"name": "13: Qiang (DPS 230.4-239.4)", "category": "Spears", "platform": "Console"}, "-101310576": {"name": "14: Vel (DPS 268.2-277.2)", "category": "Spears", "platform": "Console"}, "-101310575": {"name": "15: Centurion Spear (DPS 311.4-320.4)", "category": "Spears", "platform": "Console"}, "-101309490": {"name": "16: Honed Spear (DPS 419.4-428.4)", "category": "Spears", "platform": "Console"}, "-101309489": {"name": "17: Disemboweler (DPS 527.4-536.4)", "category": "Spears", "platform": "Console"}, "1438708880": {"name": "Art Test Spear 1", "category": "Spears", "platform": "Console"}, "1438708881": {"name": "Art Test Spear 2", "category": "Spears", "platform": "Console"}, "1438708882": {"name": "Art Test Spear 3", "category": "Spears", "platform": "Console"}, "1438708883": {"name": "Art Test Spear 4", "category": "Spears", "platform": "Console"}, "1438708884": {"name": "Art Test Spear 5", "category": "Spears", "platform": "Console"}, "-2120824630": {"name": "Legendary: Akanesh, the Herald of Righteousness", "category": "Spears", "platform": "Console"}, "2135007273": {"name": "Legendary: Arreat's Law", "category": "Spears", "platform": "Console"}, "1735685973": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "1735688417": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403711": {"name": "Legendary: Arreat's Law (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135079147": {"name": "Legendary: Empyrean Messenger", "category": "Spears", "platform": "Console"}, "1738057815": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "1738060259": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403709": {"name": "Legendary: Empyrean Messenger (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135115084": {"name": "Legendary: Scrimshaw", "category": "Spears", "platform": "Console"}, "1739243736": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "1739246180": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403708": {"name": "Legendary: Scrimshaw (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-2120788693": {"name": "Legendary: Steffon's Heavy Lance", "category": "Spears", "platform": "Console"}, "2135043210": {"name": "Legendary: The Three Hundredth Spear", "category": "Spears", "platform": "Console"}, "1736871894": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "1736874338": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403710": {"name": "Legendary: The Three Hundredth Spear (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-242895468": {"name": "01: Glass Star (AR 30-35)", "category": "Spirit Stones", "platform": "Console"}, "-242895467": {"name": "02: Thought Mirror (AR 36-41)", "category": "Spirit Stones", "platform": "Console"}, "-242895466": {"name": "03: Third Eye (AR 60-69)", "category": "Spirit Stones", "platform": "Console"}, "-242895465": {"name": "04: Onyx Cluster (AR 84-113)", "category": "Spirit Stones", "platform": "Console"}, "-242894379": {"name": "05: Sunstone (AR 114-149)", "category": "Spirit Stones", "platform": "Console"}, "-242894378": {"name": "06: Prism (AR 150-185)", "category": "Spirit Stones", "platform": "Console"}, "-242894377": {"name": "07: Seer Shard (AR 186-232)", "category": "Spirit Stones", "platform": "Console"}, "-242894376": {"name": "08: Igneous Studs (AR 232-254)", "category": "Spirit Stones", "platform": "Console"}, "-242893290": {"name": "09: Solarius (AR 255-284)", "category": "Spirit Stones", "platform": "Console"}, "-242893289": {"name": "10: Meditator (AR 285-322)", "category": "Spirit Stones", "platform": "Console"}, "-242893288": {"name": "11: Ghost Sight (AR 322-359)", "category": "Spirit Stones", "platform": "Console"}, "-242893287": {"name": "12: Star Crown (AR 360-472)", "category": "Spirit Stones", "platform": "Console"}, "-242893286": {"name": "13: Insight Stone (AR 472-659)", "category": "Spirit Stones", "platform": "Console"}, "-242893285": {"name": "14: Ascended Stone (AR 660-759)", "category": "Spirit Stones", "platform": "Console"}, "113759385": {"name": "Art Test SpiritStone 1", "category": "Spirit Stones", "platform": "Console"}, "113759386": {"name": "Art Test SpiritStone 2", "category": "Spirit Stones", "platform": "Console"}, "113759387": {"name": "Art Test SpiritStone 3", "category": "Spirit Stones", "platform": "Console"}, "113759388": {"name": "Art Test SpiritStone 4", "category": "Spirit Stones", "platform": "Console"}, "113759389": {"name": "Art Test SpiritStone 5", "category": "Spirit Stones", "platform": "Console"}, "635580050": {"name": "Legendary: Bezoar Stone", "category": "Spirit Stones", "platform": "Console"}, "-500772130": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-500769686": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225226": {"name": "Legendary: Bezoar Stone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635651924": {"name": "Legendary: Erlang Shen", "category": "Spirit Stones", "platform": "Console"}, "-498400288": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-498397844": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225228": {"name": "Legendary: Erlang Shen (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674787317": {"name": "Legendary: Eye of Peshkov", "category": "Spirit Stones", "platform": "Console"}, "635687861": {"name": "Legendary: Gyana Na Kashu", "category": "Spirit Stones", "platform": "Console"}, "-497214367": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-497211923": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225229": {"name": "Legendary: Gyana Na Kashu (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674751380": {"name": "Legendary: Kekegi's Unbreakable Spirit", "category": "Spirit Stones", "platform": "Console"}, "635831609": {"name": "Legendary: Madstone", "category": "Spirit Stones", "platform": "Console"}, "-492470683": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-492468239": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225233": {"name": "Legendary: Madstone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1935108657": {"name": "Legendary: Madstone (Patch 2.1.0)", "category": "Spirit Stones", "platform": "Console"}, "635723798": {"name": "Legendary: See No Evil", "category": "Spirit Stones", "platform": "Console"}, "-496028446": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-496026002": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225230": {"name": "Legendary: See No Evil (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635759735": {"name": "Legendary: The Eye of the Storm", "category": "Spirit Stones", "platform": "Console"}, "-494842525": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-494840081": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225231": {"name": "Legendary: The Eye of the Storm (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674715443": {"name": "Legendary: The Laws of Seph", "category": "Spirit Stones", "platform": "Console"}, "635615987": {"name": "Legendary: The Mind's Eye", "category": "Spirit Stones", "platform": "Console"}, "-499586209": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-499583765": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225227": {"name": "Legendary: The Mind's Eye (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635795672": {"name": "Legendary: Tzo Krin's Gaze", "category": "Spirit Stones", "platform": "Console"}, "-493656604": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-493654160": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225232": {"name": "Legendary: Tzo Krin's Gaze (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635867546": {"name": "Set: Inna's Radiance", "category": "Spirit Stones", "platform": "Console"}, "-491284762": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-491282318": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225234": {"name": "Set: Inna's Splendor (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-2115691356": {"name": "01: Short Staff (DPS 12.5-13.5)", "category": "Staves", "platform": "Console"}, "-2115691355": {"name": "02: Long Staff (DPS 17.0-18.5)", "category": "Staves", "platform": "Console"}, "-2115691354": {"name": "03: Yew Staff (DPS 22.0-23.5)", "category": "Staves", "platform": "Console"}, "-2115691353": {"name": "04: Gnarled Staff (DPS 27.0-28.5)", "category": "Staves", "platform": "Console"}, "-2115691352": {"name": "05: Bone Staff (DPS 33.0-34.5)", "category": "Staves", "platform": "Console"}, "-2115691351": {"name": "06: Battle Staff (DPS 40.5-42.0)", "category": "Staves", "platform": "Console"}, "-2115691350": {"name": "07: War Staff (DPS 50.5-53.5)", "category": "Staves", "platform": "Console"}, "-2115690267": {"name": "08: Mentor Staff (DPS 66.5-69.5)", "category": "Staves", "platform": "Console"}, "-2115690266": {"name": "09: Obsidian Staff (DPS 75.5-78.5)", "category": "Staves", "platform": "Console"}, "-2115690265": {"name": "10: Petrified Staff (DPS 90.0-94.5)", "category": "Staves", "platform": "Console"}, "-2115690264": {"name": "11: Elder Staff (DPS 101.5-106.0)", "category": "Staves", "platform": "Console"}, "-2115690263": {"name": "12: Shamanic Staff (DPS 121.0-127.0)", "category": "Staves", "platform": "Console"}, "-2115690262": {"name": "13: High Priest Staff (DPS 138.5-144.5)", "category": "Staves", "platform": "Console"}, "-2115690261": {"name": "14: Arcane Staff (DPS 174.5-182.0)", "category": "Staves", "platform": "Console"}, "-2115689178": {"name": "15: Hyperion Staff (DPS 204.5-212.0)", "category": "Staves", "platform": "Console"}, "-2115689177": {"name": "16: Stygian Staff (DPS 237.0-246.0)", "category": "Staves", "platform": "Console"}, "-2115689176": {"name": "17: Primordial Staff (DPS 275.5-286.0)", "category": "Staves", "platform": "Console"}, "-2115689175": {"name": "18: Archaic Staff (DPS 320.0-332.0)", "category": "Staves", "platform": "Console"}, "-2115689174": {"name": "19: Conquest Staff (DPS 409.0-421.0)", "category": "Staves", "platform": "Console"}, "-2115689173": {"name": "20: Mythical Staff (DPS 484.0-496.0)", "category": "Staves", "platform": "Console"}, "-2115689172": {"name": "21: Sovereign Staff (DPS 572.5-584.5)", "category": "Staves", "platform": "Console"}, "-2115688089": {"name": "22: Caduceus Staff (DPS 712.3-725.5)", "category": "Staves", "platform": "Console"}, "-2115688088": {"name": "23: Kerykeion (DPS 968.0-981.2)", "category": "Staves", "platform": "Console"}, "-1849507048": {"name": "Art Test CombatStaff Two-Handed 1", "category": "Staves", "platform": "Console"}, "-1849507047": {"name": "Art Test CombatStaff Two-Handed 2", "category": "Staves", "platform": "Console"}, "-1849507046": {"name": "Art Test CombatStaff Two-Handed 3", "category": "Staves", "platform": "Console"}, "-1849507045": {"name": "Art Test CombatStaff Two-Handed 4", "category": "Staves", "platform": "Console"}, "-1849507044": {"name": "Art Test CombatStaff Two-Handed 5", "category": "Staves", "platform": "Console"}, "1590673385": {"name": "Art Test Staff 1", "category": "Staves", "platform": "Console"}, "1590673386": {"name": "Art Test Staff 2", "category": "Staves", "platform": "Console"}, "1590673387": {"name": "Art Test Staff 3", "category": "Staves", "platform": "Console"}, "1590673388": {"name": "Art Test Staff 4", "category": "Staves", "platform": "Console"}, "1590673389": {"name": "Art Test Staff 5", "category": "Staves", "platform": "Console"}, "2065442005": {"name": "Crafted: Elderwood Staff", "category": "Staves", "platform": "Console"}, "-1170762813": {"name": "Legendary: Ahavarion, Spear of Lycander", "category": "Staves", "platform": "Console"}, "-1209646647": {"name": "Legendary: Autumn's Call", "category": "Staves", "platform": "Console"}, "-1263710987": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "-1263708543": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "300184993": {"name": "Legendary: Autumn's Call (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-306066026": {"name": "Legendary: Hellish Staff of Herding", "category": "Staves", "platform": "Console"}, "1952916002": {"name": "Legendary: Infernal Staff of Herding", "category": "Staves", "platform": "Console"}, "-1209718521": {"name": "Legendary: Maloth's Focus", "category": "Staves", "platform": "Console"}, "-1266082829": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "-1266080385": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "300184991": {"name": "Legendary: Maloth's Focus (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209862269": {"name": "Legendary: Mark of The Magi", "category": "Staves", "platform": "Console"}, "-1409366405": {"name": "Legendary: Ner'zhul's Staff of Shadowmoon (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "670723600": {"name": "Legendary: Nightmarish Staff of Herding", "category": "Staves", "platform": "Console"}, "-1077364974": {"name": "Legendary: Staff of Herding", "category": "Staves", "platform": "Console"}, "-1170655002": {"name": "Legendary: SuWong Diviner", "category": "Staves", "platform": "Console"}, "-1209898206": {"name": "Legendary: The Broken Staff", "category": "Staves", "platform": "Console"}, "-1272012434": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "-1272009990": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "300184986": {"name": "Legendary: The Broken Staff (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610710": {"name": "Legendary: The Grand Vizier", "category": "Staves", "platform": "Console"}, "-1262525066": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "-1262522622": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "300184994": {"name": "Legendary: The Grand Vizier (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1459729466": {"name": "Greater Rift Keystone", "category": "Comsumables", "platform": "Console"},"-1209610974": {"name": "Legendary: The Grand Vizier (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "-1270826513": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "-1270824069": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "300184987": {"name": "Legendary: The Magi (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170690939": {"name": "Legendary: The Smoldering Core", "category": "Staves", "platform": "Console"}, "-1209682584": {"name": "Legendary: The Tormentor", "category": "Staves", "platform": "Console"}, "-1264896908": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "-1264894464": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "300184992": {"name": "Legendary: The Tormentor (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170726876": {"name": "Legendary: Valthek's Rebuke", "category": "Staves", "platform": "Console"}, "-1209826332": {"name": "Legendary: Wormwood", "category": "Staves", "platform": "Console"}, "-1269640592": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "-1269638148": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "300184988": {"name": "Legendary: Wormwood (Old-Legacy)", "category": "Staves", "platform": "Console"}, "1889450717": {"name": "Legendary: Wormwood (Patch 2.1.2)", "category": "Staves", "platform": "Console"}, "-1953260964": {"name": "P2 combatStaff norm Legendary 01", "category": "Staves", "platform": "Console"}, "397178771": {"name": "PvP: Heroic Staff", "category": "Staves", "platform": "Console"}, "397178770": {"name": "PvP: Mighty Staff", "category": "Staves", "platform": "Console"}, "397178769": {"name": "PvP: Staff", "category": "Staves", "platform": "Console"}, "-270938921": {"name": "01: Short Sword (DPS 4.2-5.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938920": {"name": "02: Sabre (DPS 8.4-10.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938919": {"name": "03: Broadsword (DPS 11.2-13.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938918": {"name": "04: Longsword (DPS 16.1-18.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938917": {"name": "05: Falchion (DPS 20.3-22.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938916": {"name": "06: Scimitar (DPS 24.5-26.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938915": {"name": "07: War Sword (DPS 28.0-30.1)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938914": {"name": "08: Bastard Sword (DPS 32.2-34.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937832": {"name": "09: Gladius (DPS 39.2-41.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937831": {"name": "10: Cutlass (DPS 44.1-46.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937830": {"name": "11: Battle Sword (DPS 48.3-50.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937829": {"name": "12: Knight Sword (DPS 53.2-55.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937828": {"name": "13: Dao (DPS 62.3-64.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937827": {"name": "14: Shamshir (DPS 73.5-75.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937826": {"name": "15: Raid Sword (DPS 81.2-83.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937825": {"name": "16: Ancient Sword (DPS 93.1-95.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936743": {"name": "17: Spatha (DPS 100.1-104.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936742": {"name": "18: Pirate Sword (DPS 112.0-116.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936741": {"name": "19: Strong Sword (DPS 123.2-127.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936740": {"name": "20: King Blade (DPS 137.2-141.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936739": {"name": "21: Tulwar (DPS 151.2-155.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936738": {"name": "22: Saif (DPS 181.3-187.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936737": {"name": "23: Conquest Sword (DPS 210.0-216.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936736": {"name": "24: Rune Sword (DPS 242.2-248.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935654": {"name": "25: Champion Sword (DPS 322.0-328.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935653": {"name": "26: Tsunami Blade (DPS 392.0-398.3)", "category": "Swords, One-Handed", "platform": "Console"}, "1775003964": {"name": "Art Test Sword One-Handed 1", "category": "Swords, One-Handed", "platform": "Console"}, "1775003965": {"name": "Art Test Sword One-Handed 2", "category": "Swords, One-Handed", "platform": "Console"}, "1775003966": {"name": "Art Test Sword One-Handed 3", "category": "Swords, One-Handed", "platform": "Console"}, "1775003967": {"name": "Art Test Sword One-Handed 4", "category": "Swords, One-Handed", "platform": "Console"}, "1775003968": {"name": "Art Test Sword One-Handed 5", "category": "Swords, One-Handed", "platform": "Console"}, "560809999": {"name": "Crafted: Blacksteel Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1351405527": {"name": "Legendary: Amberwing", "category": "Swords, One-Handed", "platform": "Console"}, "1312306071": {"name": "Legendary: Azurewrath", "category": "Swords, One-Handed", "platform": "Console"}, "356350083": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "356352527": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242223": {"name": "Legendary: Azurewrath (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351441464": {"name": "Legendary: Deathwish", "category": "Swords, One-Handed", "platform": "Console"}, "1312270134": {"name": "Legendary: Devil Tongue", "category": "Swords, One-Handed", "platform": "Console"}, "355164162": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "355166606": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242222": {"name": "Legendary: Devil Tongue (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312377945": {"name": "Legendary: Doombringer", "category": "Swords, One-Handed", "platform": "Console"}, "358721925": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "358724369": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242225": {"name": "Legendary: Doombringer (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350255543": {"name": "Legendary: Exarian", "category": "Swords, One-Handed", "platform": "Console"}, "1350327417": {"name": "Legendary: Fulminator", "category": "Swords, One-Handed", "platform": "Console"}, "1350399291": {"name": "Legendary: Ghoul King's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "1350291480": {"name": "Legendary: Gift of Silaria", "category": "Swords, One-Handed", "platform": "Console"}, "1350363354": {"name": "Legendary: God Butcher", "category": "Swords, One-Handed", "platform": "Console"}, "364651530": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "364653974": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242230": {"name": "Legendary: Griswold's Masterpiece (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312557630": {"name": "Legendary: Griswold's Perfection", "category": "Swords, One-Handed", "platform": "Console"}, "1311084213": {"name": "Legendary: Griswold's Worn Edge", "category": "Swords, One-Handed", "platform": "Console"}, "316028769": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "316031213": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242189": {"name": "Legendary: Griswold's Worn Edge (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350471165": {"name": "Legendary: Incinerator", "category": "Swords, One-Handed", "platform": "Console"}, "229247441": {"name": "Legendary: Lifebane", "category": "Swords, One-Handed", "platform": "Console"}, "1312485756": {"name": "Legendary: Monster Hunter", "category": "Swords, One-Handed", "platform": "Console"}, "362279688": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "362282132": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242228": {"name": "Legendary: Monster Hunter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350435228": {"name": "Legendary: Nazim's Greatness", "category": "Swords, One-Handed", "platform": "Console"}, "1312234197": {"name": "Legendary: Rakanishu's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "353978241": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "353980685": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242221": {"name": "Legendary: Rakanishu's Blade (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351369590": {"name": "Legendary: Rancor", "category": "Swords, One-Handed", "platform": "Console"}, "1350507102": {"name": "Legendary: Rimeheart", "category": "Swords, One-Handed", "platform": "Console"}, "1311299835": {"name": "Legendary: Sever", "category": "Swords, One-Handed", "platform": "Console"}, "323144295": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "323146739": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242195": {"name": "Legendary: Sever (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "229283378": {"name": "Legendary: Shard of Hate", "category": "Swords, One-Handed", "platform": "Console"}, "1311192024": {"name": "Legendary: Skycutter", "category": "Swords, One-Handed", "platform": "Console"}, "319586532": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "319588976": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242192": {"name": "Legendary: Skycutter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1313456055": {"name": "Legendary: Spectrum", "category": "Swords, One-Handed", "platform": "Console"}, "394299555": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "394301999": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242255": {"name": "Legendary: Spectrum (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1311156087": {"name": "Legendary: The Ancient Bonesaber of Zumakalis", "category": "Swords, One-Handed", "platform": "Console"}, "318400611": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "318403055": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242191": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350219606": {"name": "Legendary: Thunderfury, Blessed Blade of the Windseeker", "category": "Swords, One-Handed", "platform": "Console"}, "1311120150": {"name": "Legendary: Wildwood", "category": "Swords, One-Handed", "platform": "Console"}, "317214690": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "317217134": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242190": {"name": "Legendary: Wildwood (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487634": {"name": "PvP: Heroic Bastard Sword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487635": {"name": "PvP: Mighty Longsword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487636": {"name": "PvP: Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1312521693": {"name": "Set: Born's Furious Wrath", "category": "Swords, One-Handed", "platform": "Console"}, "363465609": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "363468053": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242229": {"name": "Set: Born's Seething Rage (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1394445518": {"name": "Set: Little Rogue", "category": "Swords, One-Handed", "platform": "Console"}, "-1394481455": {"name": "Set: The Slanderer", "category": "Swords, One-Handed", "platform": "Console"}, "-2025765397": {"name": "Sword Of Justice Tyrael", "category": "Swords, One-Handed", "platform": "Console"}, "1351477401": {"name": "legendary: In-geom (Patch 2.2.0)", "category": "Swords, One-Handed", "platform": "Console"}, "-231803528": {"name": "01: Two-Handed Sword (DPS 11.0-12.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803527": {"name": "02: Flamberge (DPS 16.0-17.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803526": {"name": "03: Dervish (DPS 22.6-24.2)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803525": {"name": "04: Executioner Sword (DPS 28.1-29.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803524": {"name": "05: Nodachi (DPS 35.2-36.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803523": {"name": "06: Claymore (DPS 41.8-43.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802439": {"name": "07: Great Sword (DPS 52.8-54.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802438": {"name": "08: Reaver (DPS 62.2-65.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802437": {"name": "09: Kilij (DPS 74.8-78.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802436": {"name": "10: Mameluke (DPS 89.7-93.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802435": {"name": "11: Nagamaki (DPS 106.2-111.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802434": {"name": "12: Grand Sword (DPS 126.5-133.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801350": {"name": "13: Highland Sword (DPS 171.6-179.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801349": {"name": "14: Brimstone Sword (DPS 215.6-223.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801348": {"name": "15: Yatagan (DPS 269.0-278.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801347": {"name": "16: Colossus Blade (DPS 367.4-379.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801346": {"name": "17: Oni Blade (DPS 433.4-446.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801345": {"name": "18: Warlord Sword (DPS 511.5-524.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800261": {"name": "19: Gothic Blade (DPS 670.5-682.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800260": {"name": "20: Kingslayer (DPS 907.4-919.4)", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039901": {"name": "Art Test Sword Two-Handed 1", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039902": {"name": "Art Test Sword Two-Handed 2", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039903": {"name": "Art Test Sword Two-Handed 3", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039904": {"name": "Art Test Sword Two-Handed 4", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039905": {"name": "Art Test Sword Two-Handed 5", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028384713": {"name": "Legendary: Blackguard", "category": "Swords, Two-Handed", "platform": "Console"}, "422965539": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "422967983": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377615": {"name": "Legendary: Blackguard (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029355012": {"name": "Legendary: Blade of Prophecy", "category": "Swords, Two-Handed", "platform": "Console"}, "390945672": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "390948116": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377588": {"name": "Legendary: Blade of Prophecy (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "1516448771": {"name": "Legendary: Blade of the Ancients", "category": "Swords, Two-Handed", "platform": "Console"}, "-990363367": {"name": "Legendary: Blood Brother", "category": "Swords, Two-Handed", "platform": "Console"}, "-990399304": {"name": "Legendary: Cam's Rebuttal", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028348776": {"name": "Legendary: Faithful Memory", "category": "Swords, Two-Handed", "platform": "Console"}, "424151460": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "424153904": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377616": {"name": "Legendary: Faithful Memory (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028420650": {"name": "Legendary: Maximus", "category": "Swords, Two-Handed", "platform": "Console"}, "421779618": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "421782062": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377614": {"name": "Legendary: Maximus (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029462823": {"name": "Legendary: Scourge", "category": "Swords, Two-Handed", "platform": "Console"}, "387387909": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "387390353": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377585": {"name": "Legendary: Scourge (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028276902": {"name": "Legendary: Splintered Oar", "category": "Swords, Two-Handed", "platform": "Console"}, "426523302": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "426525746": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377618": {"name": "Legendary: Splintered Oar (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990435241": {"name": "Legendary: Stalgard's Decimator", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029570634": {"name": "Legendary: The Grandfather", "category": "Swords, Two-Handed", "platform": "Console"}, "383830146": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "383832590": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377582": {"name": "Legendary: The Grandfather (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029319075": {"name": "Legendary: The Sultan of Blinding Sand", "category": "Swords, Two-Handed", "platform": "Console"}, "392131593": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "392134037": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377589": {"name": "Legendary: The Sultan of Blinding Sand (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029534697": {"name": "Legendary: The Zweihander", "category": "Swords, Two-Handed", "platform": "Console"}, "385016067": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "385018511": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377583": {"name": "Legendary: The Zweihander (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029498760": {"name": "Legendary: Warmonger", "category": "Swords, Two-Handed", "platform": "Console"}, "386201988": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "386204432": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377584": {"name": "Legendary: Warmonger (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1271367654": {"name": "legendary: Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990291493": {"name": "legendary: Ch'il-chi-do (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990327430": {"name": "legendary: Corrupted Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "1147339621": {"name": "01: Holy Tome", "category": "Templar Relics", "platform": "Console"}, "1147339622": {"name": "02: Spear Fragment", "category": "Templar Relics", "platform": "Console"}, "1147340710": {"name": "03: Sacred Text", "category": "Templar Relics", "platform": "Console"}, "1147340711": {"name": "04: Blade Shard", "category": "Templar Relics", "platform": "Console"}, "1147340712": {"name": "05: Martyr Tears", "category": "Templar Relics", "platform": "Console"}, "1147340713": {"name": "06: Chalice", "category": "Templar Relics", "platform": "Console"}, "1147341799": {"name": "07: Libram Spiritus", "category": "Templar Relics", "platform": "Console"}, "1147341800": {"name": "08: Blade Remnant", "category": "Templar Relics", "platform": "Console"}, "1147341801": {"name": "09: Saint Tears", "category": "Templar Relics", "platform": "Console"}, "1147341802": {"name": "10: Grail", "category": "Templar Relics", "platform": "Console"}, "1147341803": {"name": "11: Codex", "category": "Templar Relics", "platform": "Console"}, "1147341804": {"name": "12: Broken Foible", "category": "Templar Relics", "platform": "Console"}, "-765770609": {"name": "Legendary: Enchanting Favor", "category": "Templar Relics", "platform": "Console"}, "-765770607": {"name": "Legendary: Hillenbrand's Training Sword", "category": "Templar Relics", "platform": "Console"}, "-765770608": {"name": "Legendary: Relic of Akarat", "category": "Templar Relics", "platform": "Console"}, "-1438295706": {"name": "Don's 2H Sword of Testing", "category": "Test", "platform": "Console"}, "-1438295707": {"name": "Don's Sword of Testing", "category": "Test", "platform": "Console"}, "-1585353949": {"name": "P1 Test Ring 941 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353948": {"name": "P1 Test Ring 942 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353947": {"name": "P1 Test Ring 943 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353946": {"name": "P1 Test Ring 944 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388889": {"name": "P2 TEST RING 021 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388890": {"name": "P2 TEST RING 022 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388891": {"name": "P2 TEST RING 023 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388892": {"name": "P2 TEST RING 024 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388893": {"name": "P2 TEST RING 025 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388894": {"name": "P2 TEST RING 026 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388895": {"name": "P2 TEST RING 027 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388896": {"name": "P2 TEST RING 028 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388897": {"name": "P2 TEST RING 029 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388921": {"name": "P2 TEST RING 030 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388922": {"name": "P2 TEST RING 031 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388923": {"name": "P2 TEST RING 032 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388924": {"name": "P2 TEST RING 033 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388925": {"name": "P2 TEST RING 034 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388926": {"name": "P2 TEST RING 035 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388927": {"name": "P2 TEST RING 036 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388928": {"name": "P2 TEST RING 037 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388929": {"name": "P2 TEST RING 038 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388930": {"name": "P2 TEST RING 039 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388954": {"name": "P2 TEST RING 040 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388955": {"name": "P2 TEST RING 041 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388956": {"name": "P2 TEST RING 042 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388957": {"name": "P2 TEST RING 043 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388958": {"name": "P2 TEST RING 044 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388959": {"name": "P2 TEST RING 045 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388960": {"name": "P2 TEST RING 046 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388961": {"name": "P2 TEST RING 047 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388962": {"name": "P2 TEST RING 048 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388963": {"name": "P2 TEST RING 049 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388987": {"name": "P2 TEST RING 050 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388824": {"name": "P2 Test Ring 002 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388825": {"name": "P2 Test Ring 003 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388826": {"name": "P2 Test Ring 004 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388827": {"name": "P2 Test Ring 005 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388828": {"name": "P2 Test Ring 006 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388829": {"name": "P2 Test Ring 007 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388830": {"name": "P2 Test Ring 008 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388831": {"name": "P2 Test Ring 009 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388855": {"name": "P2 Test Ring 010 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388856": {"name": "P2 Test Ring 011 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388857": {"name": "P2 Test Ring 012 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388858": {"name": "P2 Test Ring 013 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388859": {"name": "P2 Test Ring 014 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388860": {"name": "P2 Test Ring 015 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388861": {"name": "P2 Test Ring 016 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388862": {"name": "P2 Test Ring 017 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388863": {"name": "P2 Test Ring 018 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388864": {"name": "P2 Test Ring 019 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388888": {"name": "P2 Test Ring 020 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "1608362283": {"name": "P2_WizardSet_Scroll_Test (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388823": {"name": "Test Ring 001 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "708102766": {"name": "Test Ring 1000", "category": "Test", "platform": "Console"}, "-993303550": {"name": "Test Ring 500", "category": "Test", "platform": "Console"}, "-993267613": {"name": "Test Ring 501", "category": "Test", "platform": "Console"}, "-993231676": {"name": "Test Ring 502", "category": "Test", "platform": "Console"}, "-993195739": {"name": "Test Ring 503", "category": "Test", "platform": "Console"}, "-993159802": {"name": "Test Ring 504", "category": "Test", "platform": "Console"}, "-993123865": {"name": "Test Ring 505", "category": "Test", "platform": "Console"}, "-993087928": {"name": "Test Ring 506", "category": "Test", "platform": "Console"}, "-993051991": {"name": "Test Ring 507", "category": "Test", "platform": "Console"}, "-993016054": {"name": "Test Ring 508", "category": "Test", "platform": "Console"}, "-992980117": {"name": "Test Ring 509", "category": "Test", "platform": "Console"}, "-992117629": {"name": "Test Ring 510", "category": "Test", "platform": "Console"}, "-992081692": {"name": "Test Ring 511", "category": "Test", "platform": "Console"}, "-992045755": {"name": "Test Ring 512", "category": "Test", "platform": "Console"}, "-992009818": {"name": "Test Ring 513", "category": "Test", "platform": "Console"}, "-991973881": {"name": "Test Ring 514", "category": "Test", "platform": "Console"}, "-991937944": {"name": "Test Ring 515", "category": "Test", "platform": "Console"}, "-991902007": {"name": "Test Ring 516", "category": "Test", "platform": "Console"}, "-991866070": {"name": "Test Ring 517", "category": "Test", "platform": "Console"}, "-991830133": {"name": "Test Ring 518", "category": "Test", "platform": "Console"}, "-991794196": {"name": "Test Ring 519", "category": "Test", "platform": "Console"}, "-990931708": {"name": "Test Ring 520", "category": "Test", "platform": "Console"}, "-990895771": {"name": "Test Ring 521", "category": "Test", "platform": "Console"}, "-990859834": {"name": "Test Ring 522", "category": "Test", "platform": "Console"}, "-990823897": {"name": "Test Ring 523", "category": "Test", "platform": "Console"}, "-990787960": {"name": "Test Ring 524", "category": "Test", "platform": "Console"}, "-990752023": {"name": "Test Ring 525", "category": "Test", "platform": "Console"}, "-990716086": {"name": "Test Ring 526", "category": "Test", "platform": "Console"}, "-990680149": {"name": "Test Ring 527", "category": "Test", "platform": "Console"}, "-990644212": {"name": "Test Ring 528", "category": "Test", "platform": "Console"}, "-990608275": {"name": "Test Ring 529", "category": "Test", "platform": "Console"}, "-989745787": {"name": "Test Ring 530", "category": "Test", "platform": "Console"}, "-989709850": {"name": "Test Ring 531", "category": "Test", "platform": "Console"}, "-989673913": {"name": "Test Ring 532", "category": "Test", "platform": "Console"}, "-989637976": {"name": "Test Ring 533", "category": "Test", "platform": "Console"}, "-989602039": {"name": "Test Ring 534", "category": "Test", "platform": "Console"}, "-989566102": {"name": "Test Ring 535", "category": "Test", "platform": "Console"}, "-989530165": {"name": "Test Ring 536", "category": "Test", "platform": "Console"}, "-989494228": {"name": "Test Ring 537", "category": "Test", "platform": "Console"}, "-989458291": {"name": "Test Ring 538", "category": "Test", "platform": "Console"}, "-989422354": {"name": "Test Ring 539", "category": "Test", "platform": "Console"}, "-988559866": {"name": "Test Ring 540", "category": "Test", "platform": "Console"}, "-988523929": {"name": "Test Ring 541", "category": "Test", "platform": "Console"}, "-988487992": {"name": "Test Ring 542", "category": "Test", "platform": "Console"}, "-988452055": {"name": "Test Ring 543", "category": "Test", "platform": "Console"}, "-988416118": {"name": "Test Ring 544", "category": "Test", "platform": "Console"}, "-988380181": {"name": "Test Ring 545", "category": "Test", "platform": "Console"}, "-988344244": {"name": "Test Ring 546", "category": "Test", "platform": "Console"}, "-988308307": {"name": "Test Ring 547", "category": "Test", "platform": "Console"}, "-988272370": {"name": "Test Ring 548", "category": "Test", "platform": "Console"}, "-988236433": {"name": "Test Ring 549", "category": "Test", "platform": "Console"}, "-987373945": {"name": "Test Ring 550", "category": "Test", "platform": "Console"}, "-987338008": {"name": "Test Ring 551", "category": "Test", "platform": "Console"}, "-987302071": {"name": "Test Ring 552", "category": "Test", "platform": "Console"}, "-987266134": {"name": "Test Ring 553", "category": "Test", "platform": "Console"}, "-987230197": {"name": "Test Ring 554", "category": "Test", "platform": "Console"}, "-987194260": {"name": "Test Ring 555", "category": "Test", "platform": "Console"}, "-987158323": {"name": "Test Ring 556", "category": "Test", "platform": "Console"}, "-987122386": {"name": "Test Ring 557", "category": "Test", "platform": "Console"}, "-987086449": {"name": "Test Ring 558", "category": "Test", "platform": "Console"}, "-987050512": {"name": "Test Ring 559", "category": "Test", "platform": "Console"}, "-986188024": {"name": "Test Ring 560", "category": "Test", "platform": "Console"}, "-986152087": {"name": "Test Ring 561", "category": "Test", "platform": "Console"}, "-986116150": {"name": "Test Ring 562", "category": "Test", "platform": "Console"}, "-986080213": {"name": "Test Ring 563", "category": "Test", "platform": "Console"}, "-986044276": {"name": "Test Ring 564", "category": "Test", "platform": "Console"}, "-986008339": {"name": "Test Ring 565", "category": "Test", "platform": "Console"}, "-985972402": {"name": "Test Ring 566", "category": "Test", "platform": "Console"}, "-985936465": {"name": "Test Ring 567", "category": "Test", "platform": "Console"}, "-985900528": {"name": "Test Ring 568", "category": "Test", "platform": "Console"}, "-985864591": {"name": "Test Ring 569", "category": "Test", "platform": "Console"}, "-985002103": {"name": "Test Ring 570", "category": "Test", "platform": "Console"}, "-984966166": {"name": "Test Ring 571", "category": "Test", "platform": "Console"}, "-984930229": {"name": "Test Ring 572", "category": "Test", "platform": "Console"}, "-984894292": {"name": "Test Ring 573", "category": "Test", "platform": "Console"}, "-984858355": {"name": "Test Ring 574", "category": "Test", "platform": "Console"}, "-984822418": {"name": "Test Ring 575", "category": "Test", "platform": "Console"}, "-984786481": {"name": "Test Ring 576", "category": "Test", "platform": "Console"}, "-984750544": {"name": "Test Ring 577", "category": "Test", "platform": "Console"}, "-984714607": {"name": "Test Ring 578", "category": "Test", "platform": "Console"}, "-984678670": {"name": "Test Ring 579", "category": "Test", "platform": "Console"}, "-983816182": {"name": "Test Ring 580", "category": "Test", "platform": "Console"}, "-983780245": {"name": "Test Ring 581", "category": "Test", "platform": "Console"}, "-983744308": {"name": "Test Ring 582", "category": "Test", "platform": "Console"}, "-983708371": {"name": "Test Ring 583", "category": "Test", "platform": "Console"}, "-983672434": {"name": "Test Ring 584", "category": "Test", "platform": "Console"}, "-983636497": {"name": "Test Ring 585", "category": "Test", "platform": "Console"}, "-983600560": {"name": "Test Ring 586", "category": "Test", "platform": "Console"}, "-983564623": {"name": "Test Ring 587", "category": "Test", "platform": "Console"}, "-983528686": {"name": "Test Ring 588", "category": "Test", "platform": "Console"}, "-983492749": {"name": "Test Ring 589", "category": "Test", "platform": "Console"}, "-982630261": {"name": "Test Ring 590", "category": "Test", "platform": "Console"}, "-982594324": {"name": "Test Ring 591", "category": "Test", "platform": "Console"}, "-982558387": {"name": "Test Ring 592", "category": "Test", "platform": "Console"}, "-982522450": {"name": "Test Ring 593", "category": "Test", "platform": "Console"}, "-982486513": {"name": "Test Ring 594", "category": "Test", "platform": "Console"}, "-982450576": {"name": "Test Ring 595", "category": "Test", "platform": "Console"}, "-982414639": {"name": "Test Ring 596", "category": "Test", "platform": "Console"}, "-982378702": {"name": "Test Ring 597", "category": "Test", "platform": "Console"}, "-982342765": {"name": "Test Ring 598", "category": "Test", "platform": "Console"}, "-982306828": {"name": "Test Ring 599", "category": "Test", "platform": "Console"}, "-954168157": {"name": "Test Ring 600", "category": "Test", "platform": "Console"}, "-954132220": {"name": "Test Ring 601", "category": "Test", "platform": "Console"}, "-954096283": {"name": "Test Ring 602", "category": "Test", "platform": "Console"}, "-954060346": {"name": "Test Ring 603", "category": "Test", "platform": "Console"}, "-954024409": {"name": "Test Ring 604", "category": "Test", "platform": "Console"}, "-953988472": {"name": "Test Ring 605", "category": "Test", "platform": "Console"}, "-953952535": {"name": "Test Ring 606", "category": "Test", "platform": "Console"}, "-953916598": {"name": "Test Ring 607", "category": "Test", "platform": "Console"}, "-953880661": {"name": "Test Ring 608", "category": "Test", "platform": "Console"}, "-953844724": {"name": "Test Ring 609", "category": "Test", "platform": "Console"}, "-952982236": {"name": "Test Ring 610", "category": "Test", "platform": "Console"}, "-952946299": {"name": "Test Ring 611", "category": "Test", "platform": "Console"}, "-952910362": {"name": "Test Ring 612", "category": "Test", "platform": "Console"}, "-952874425": {"name": "Test Ring 613", "category": "Test", "platform": "Console"}, "-952838488": {"name": "Test Ring 614", "category": "Test", "platform": "Console"}, "-952802551": {"name": "Test Ring 615", "category": "Test", "platform": "Console"}, "-952766614": {"name": "Test Ring 616", "category": "Test", "platform": "Console"}, "-952730677": {"name": "Test Ring 617", "category": "Test", "platform": "Console"}, "-952694740": {"name": "Test Ring 618", "category": "Test", "platform": "Console"}, "-952658803": {"name": "Test Ring 619", "category": "Test", "platform": "Console"}, "-951796315": {"name": "Test Ring 620", "category": "Test", "platform": "Console"}, "-951760378": {"name": "Test Ring 621", "category": "Test", "platform": "Console"}, "-951724441": {"name": "Test Ring 622", "category": "Test", "platform": "Console"}, "-951688504": {"name": "Test Ring 623", "category": "Test", "platform": "Console"}, "-951652567": {"name": "Test Ring 624", "category": "Test", "platform": "Console"}, "-951616630": {"name": "Test Ring 625", "category": "Test", "platform": "Console"}, "-951580693": {"name": "Test Ring 626", "category": "Test", "platform": "Console"}, "-951544756": {"name": "Test Ring 627", "category": "Test", "platform": "Console"}, "-951508819": {"name": "Test Ring 628", "category": "Test", "platform": "Console"}, "-951472882": {"name": "Test Ring 629", "category": "Test", "platform": "Console"}, "-950610394": {"name": "Test Ring 630", "category": "Test", "platform": "Console"}, "-950574457": {"name": "Test Ring 631", "category": "Test", "platform": "Console"}, "-950538520": {"name": "Test Ring 632", "category": "Test", "platform": "Console"}, "-950502583": {"name": "Test Ring 633", "category": "Test", "platform": "Console"}, "-950466646": {"name": "Test Ring 634", "category": "Test", "platform": "Console"}, "-950430709": {"name": "Test Ring 635", "category": "Test", "platform": "Console"}, "-950394772": {"name": "Test Ring 636", "category": "Test", "platform": "Console"}, "-950358835": {"name": "Test Ring 637", "category": "Test", "platform": "Console"}, "-950322898": {"name": "Test Ring 638", "category": "Test", "platform": "Console"}, "-950286961": {"name": "Test Ring 639", "category": "Test", "platform": "Console"}, "-949424473": {"name": "Test Ring 640", "category": "Test", "platform": "Console"}, "-949388536": {"name": "Test Ring 641", "category": "Test", "platform": "Console"}, "-949352599": {"name": "Test Ring 642", "category": "Test", "platform": "Console"}, "-949316662": {"name": "Test Ring 643", "category": "Test", "platform": "Console"}, "-949280725": {"name": "Test Ring 644", "category": "Test", "platform": "Console"}, "-949244788": {"name": "Test Ring 645", "category": "Test", "platform": "Console"}, "-949208851": {"name": "Test Ring 646", "category": "Test", "platform": "Console"}, "-949172914": {"name": "Test Ring 647", "category": "Test", "platform": "Console"}, "-949136977": {"name": "Test Ring 648", "category": "Test", "platform": "Console"}, "-949101040": {"name": "Test Ring 649", "category": "Test", "platform": "Console"}, "-948238552": {"name": "Test Ring 650", "category": "Test", "platform": "Console"}, "-948202615": {"name": "Test Ring 651", "category": "Test", "platform": "Console"}, "-948166678": {"name": "Test Ring 652", "category": "Test", "platform": "Console"}, "-948130741": {"name": "Test Ring 653", "category": "Test", "platform": "Console"}, "-948094804": {"name": "Test Ring 654", "category": "Test", "platform": "Console"}, "-948058867": {"name": "Test Ring 655", "category": "Test", "platform": "Console"}, "-948022930": {"name": "Test Ring 656", "category": "Test", "platform": "Console"}, "-947986993": {"name": "Test Ring 657", "category": "Test", "platform": "Console"}, "-947951056": {"name": "Test Ring 658", "category": "Test", "platform": "Console"}, "-947915119": {"name": "Test Ring 659", "category": "Test", "platform": "Console"}, "-947052631": {"name": "Test Ring 660", "category": "Test", "platform": "Console"}, "-947016694": {"name": "Test Ring 661", "category": "Test", "platform": "Console"}, "-946980757": {"name": "Test Ring 662", "category": "Test", "platform": "Console"}, "-946944820": {"name": "Test Ring 663", "category": "Test", "platform": "Console"}, "-946908883": {"name": "Test Ring 664", "category": "Test", "platform": "Console"}, "-946872946": {"name": "Test Ring 665", "category": "Test", "platform": "Console"}, "-946837009": {"name": "Test Ring 666", "category": "Test", "platform": "Console"}, "-946801072": {"name": "Test Ring 667", "category": "Test", "platform": "Console"}, "-946765135": {"name": "Test Ring 668", "category": "Test", "platform": "Console"}, "-946729198": {"name": "Test Ring 669", "category": "Test", "platform": "Console"}, "-945866710": {"name": "Test Ring 670", "category": "Test", "platform": "Console"}, "-945830773": {"name": "Test Ring 671", "category": "Test", "platform": "Console"}, "-945794836": {"name": "Test Ring 672", "category": "Test", "platform": "Console"}, "-945758899": {"name": "Test Ring 673", "category": "Test", "platform": "Console"}, "-945722962": {"name": "Test Ring 674", "category": "Test", "platform": "Console"}, "-945687025": {"name": "Test Ring 675", "category": "Test", "platform": "Console"}, "-945651088": {"name": "Test Ring 676", "category": "Test", "platform": "Console"}, "-945615151": {"name": "Test Ring 677", "category": "Test", "platform": "Console"}, "-945579214": {"name": "Test Ring 678", "category": "Test", "platform": "Console"}, "-945543277": {"name": "Test Ring 679", "category": "Test", "platform": "Console"}, "-944680789": {"name": "Test Ring 680", "category": "Test", "platform": "Console"}, "-944644852": {"name": "Test Ring 681", "category": "Test", "platform": "Console"}, "-944608915": {"name": "Test Ring 682", "category": "Test", "platform": "Console"}, "-944572978": {"name": "Test Ring 683", "category": "Test", "platform": "Console"}, "-944537041": {"name": "Test Ring 684", "category": "Test", "platform": "Console"}, "-944501104": {"name": "Test Ring 685", "category": "Test", "platform": "Console"}, "-944465167": {"name": "Test Ring 686", "category": "Test", "platform": "Console"}, "-944429230": {"name": "Test Ring 687", "category": "Test", "platform": "Console"}, "-944393293": {"name": "Test Ring 688", "category": "Test", "platform": "Console"}, "-944357356": {"name": "Test Ring 689", "category": "Test", "platform": "Console"}, "-943494868": {"name": "Test Ring 690", "category": "Test", "platform": "Console"}, "-943458931": {"name": "Test Ring 691", "category": "Test", "platform": "Console"}, "-943422994": {"name": "Test Ring 692", "category": "Test", "platform": "Console"}, "-943387057": {"name": "Test Ring 693", "category": "Test", "platform": "Console"}, "-943351120": {"name": "Test Ring 694", "category": "Test", "platform": "Console"}, "-943315183": {"name": "Test Ring 695", "category": "Test", "platform": "Console"}, "-943279246": {"name": "Test Ring 696", "category": "Test", "platform": "Console"}, "-943243309": {"name": "Test Ring 697", "category": "Test", "platform": "Console"}, "-943207372": {"name": "Test Ring 698", "category": "Test", "platform": "Console"}, "-943171435": {"name": "Test Ring 699", "category": "Test", "platform": "Console"}, "-915032764": {"name": "Test Ring 700", "category": "Test", "platform": "Console"}, "-914996827": {"name": "Test Ring 701", "category": "Test", "platform": "Console"}, "-914960890": {"name": "Test Ring 702", "category": "Test", "platform": "Console"}, "-914924953": {"name": "Test Ring 703", "category": "Test", "platform": "Console"}, "-914889016": {"name": "Test Ring 704", "category": "Test", "platform": "Console"}, "-914853079": {"name": "Test Ring 705", "category": "Test", "platform": "Console"}, "-914817142": {"name": "Test Ring 706", "category": "Test", "platform": "Console"}, "-914781205": {"name": "Test Ring 707", "category": "Test", "platform": "Console"}, "-914745268": {"name": "Test Ring 708", "category": "Test", "platform": "Console"}, "-914709331": {"name": "Test Ring 709", "category": "Test", "platform": "Console"}, "-913846843": {"name": "Test Ring 710", "category": "Test", "platform": "Console"}, "-913810906": {"name": "Test Ring 711", "category": "Test", "platform": "Console"}, "-913774969": {"name": "Test Ring 712", "category": "Test", "platform": "Console"}, "-913739032": {"name": "Test Ring 713", "category": "Test", "platform": "Console"}, "-913703095": {"name": "Test Ring 714", "category": "Test", "platform": "Console"}, "-913667158": {"name": "Test Ring 715", "category": "Test", "platform": "Console"}, "-913631221": {"name": "Test Ring 716", "category": "Test", "platform": "Console"}, "-913595284": {"name": "Test Ring 717", "category": "Test", "platform": "Console"}, "-913559347": {"name": "Test Ring 718", "category": "Test", "platform": "Console"}, "-913523410": {"name": "Test Ring 719", "category": "Test", "platform": "Console"}, "-912660922": {"name": "Test Ring 720", "category": "Test", "platform": "Console"}, "-912624985": {"name": "Test Ring 721", "category": "Test", "platform": "Console"}, "-912589048": {"name": "Test Ring 722", "category": "Test", "platform": "Console"}, "-912553111": {"name": "Test Ring 723", "category": "Test", "platform": "Console"}, "-912517174": {"name": "Test Ring 724", "category": "Test", "platform": "Console"}, "-912481237": {"name": "Test Ring 725", "category": "Test", "platform": "Console"}, "-912445300": {"name": "Test Ring 726", "category": "Test", "platform": "Console"}, "-912409363": {"name": "Test Ring 727", "category": "Test", "platform": "Console"}, "-912373426": {"name": "Test Ring 728", "category": "Test", "platform": "Console"}, "-912337489": {"name": "Test Ring 729", "category": "Test", "platform": "Console"}, "-911475001": {"name": "Test Ring 730", "category": "Test", "platform": "Console"}, "-911439064": {"name": "Test Ring 731", "category": "Test", "platform": "Console"}, "-911403127": {"name": "Test Ring 732", "category": "Test", "platform": "Console"}, "-911367190": {"name": "Test Ring 733", "category": "Test", "platform": "Console"}, "-911331253": {"name": "Test Ring 734", "category": "Test", "platform": "Console"}, "-911295316": {"name": "Test Ring 735", "category": "Test", "platform": "Console"}, "-911259379": {"name": "Test Ring 736", "category": "Test", "platform": "Console"}, "-911223442": {"name": "Test Ring 737", "category": "Test", "platform": "Console"}, "-911187505": {"name": "Test Ring 738", "category": "Test", "platform": "Console"}, "-911151568": {"name": "Test Ring 739", "category": "Test", "platform": "Console"}, "-910289080": {"name": "Test Ring 740", "category": "Test", "platform": "Console"}, "-910253143": {"name": "Test Ring 741", "category": "Test", "platform": "Console"}, "-910217206": {"name": "Test Ring 742", "category": "Test", "platform": "Console"}, "-910181269": {"name": "Test Ring 743", "category": "Test", "platform": "Console"}, "-910145332": {"name": "Test Ring 744", "category": "Test", "platform": "Console"}, "-910109395": {"name": "Test Ring 745", "category": "Test", "platform": "Console"}, "-910073458": {"name": "Test Ring 746", "category": "Test", "platform": "Console"}, "-910037521": {"name": "Test Ring 747", "category": "Test", "platform": "Console"}, "-910001584": {"name": "Test Ring 748", "category": "Test", "platform": "Console"}, "-909965647": {"name": "Test Ring 749", "category": "Test", "platform": "Console"}, "-909103159": {"name": "Test Ring 750", "category": "Test", "platform": "Console"}, "-909067222": {"name": "Test Ring 751", "category": "Test", "platform": "Console"}, "-909031285": {"name": "Test Ring 752", "category": "Test", "platform": "Console"}, "-908995348": {"name": "Test Ring 753", "category": "Test", "platform": "Console"}, "-908959411": {"name": "Test Ring 754", "category": "Test", "platform": "Console"}, "-908923474": {"name": "Test Ring 755", "category": "Test", "platform": "Console"}, "-908887537": {"name": "Test Ring 756", "category": "Test", "platform": "Console"}, "-908851600": {"name": "Test Ring 757", "category": "Test", "platform": "Console"}, "-908815663": {"name": "Test Ring 758", "category": "Test", "platform": "Console"}, "-908779726": {"name": "Test Ring 759", "category": "Test", "platform": "Console"}, "-907917238": {"name": "Test Ring 760", "category": "Test", "platform": "Console"}, "-907881301": {"name": "Test Ring 761", "category": "Test", "platform": "Console"}, "-907845364": {"name": "Test Ring 762", "category": "Test", "platform": "Console"}, "-907809427": {"name": "Test Ring 763", "category": "Test", "platform": "Console"}, "-907773490": {"name": "Test Ring 764", "category": "Test", "platform": "Console"}, "-907737553": {"name": "Test Ring 765", "category": "Test", "platform": "Console"}, "-907701616": {"name": "Test Ring 766", "category": "Test", "platform": "Console"}, "-907665679": {"name": "Test Ring 767", "category": "Test", "platform": "Console"}, "-907629742": {"name": "Test Ring 768", "category": "Test", "platform": "Console"}, "-907593805": {"name": "Test Ring 769", "category": "Test", "platform": "Console"}, "-906731317": {"name": "Test Ring 770", "category": "Test", "platform": "Console"}, "-906695380": {"name": "Test Ring 771", "category": "Test", "platform": "Console"}, "-906659443": {"name": "Test Ring 772", "category": "Test", "platform": "Console"}, "-906623506": {"name": "Test Ring 773", "category": "Test", "platform": "Console"}, "-906587569": {"name": "Test Ring 774", "category": "Test", "platform": "Console"}, "-906551632": {"name": "Test Ring 775", "category": "Test", "platform": "Console"}, "-906515695": {"name": "Test Ring 776", "category": "Test", "platform": "Console"}, "-906479758": {"name": "Test Ring 777", "category": "Test", "platform": "Console"}, "-906443821": {"name": "Test Ring 778", "category": "Test", "platform": "Console"}, "-906407884": {"name": "Test Ring 779", "category": "Test", "platform": "Console"}, "-905545396": {"name": "Test Ring 780", "category": "Test", "platform": "Console"}, "-905509459": {"name": "Test Ring 781", "category": "Test", "platform": "Console"}, "-905473522": {"name": "Test Ring 782", "category": "Test", "platform": "Console"}, "-905437585": {"name": "Test Ring 783", "category": "Test", "platform": "Console"}, "-905401648": {"name": "Test Ring 784", "category": "Test", "platform": "Console"}, "-905365711": {"name": "Test Ring 785", "category": "Test", "platform": "Console"}, "-905329774": {"name": "Test Ring 786", "category": "Test", "platform": "Console"}, "-905293837": {"name": "Test Ring 787", "category": "Test", "platform": "Console"}, "-905257900": {"name": "Test Ring 788", "category": "Test", "platform": "Console"}, "-905221963": {"name": "Test Ring 789", "category": "Test", "platform": "Console"}, "-904359475": {"name": "Test Ring 790", "category": "Test", "platform": "Console"}, "-904323538": {"name": "Test Ring 791", "category": "Test", "platform": "Console"}, "-904287601": {"name": "Test Ring 792", "category": "Test", "platform": "Console"}, "-904251664": {"name": "Test Ring 793", "category": "Test", "platform": "Console"}, "-904215727": {"name": "Test Ring 794", "category": "Test", "platform": "Console"}, "-904179790": {"name": "Test Ring 795", "category": "Test", "platform": "Console"}, "-904143853": {"name": "Test Ring 796", "category": "Test", "platform": "Console"}, "-904107916": {"name": "Test Ring 797", "category": "Test", "platform": "Console"}, "-904071979": {"name": "Test Ring 798", "category": "Test", "platform": "Console"}, "-904036042": {"name": "Test Ring 799", "category": "Test", "platform": "Console"}, "-875897371": {"name": "Test Ring 800", "category": "Test", "platform": "Console"}, "-875861434": {"name": "Test Ring 801", "category": "Test", "platform": "Console"}, "-875825497": {"name": "Test Ring 802", "category": "Test", "platform": "Console"}, "-875789560": {"name": "Test Ring 803", "category": "Test", "platform": "Console"}, "-875753623": {"name": "Test Ring 804", "category": "Test", "platform": "Console"}, "-875717686": {"name": "Test Ring 805", "category": "Test", "platform": "Console"}, "-875681749": {"name": "Test Ring 806", "category": "Test", "platform": "Console"}, "-875645812": {"name": "Test Ring 807", "category": "Test", "platform": "Console"}, "-875609875": {"name": "Test Ring 808", "category": "Test", "platform": "Console"}, "-875573938": {"name": "Test Ring 809", "category": "Test", "platform": "Console"}, "-874711450": {"name": "Test Ring 810", "category": "Test", "platform": "Console"}, "-874675513": {"name": "Test Ring 811", "category": "Test", "platform": "Console"}, "-874639576": {"name": "Test Ring 812", "category": "Test", "platform": "Console"}, "-874603639": {"name": "Test Ring 813", "category": "Test", "platform": "Console"}, "-874567702": {"name": "Test Ring 814", "category": "Test", "platform": "Console"}, "-874531765": {"name": "Test Ring 815", "category": "Test", "platform": "Console"}, "-874495828": {"name": "Test Ring 816", "category": "Test", "platform": "Console"}, "-874459891": {"name": "Test Ring 817", "category": "Test", "platform": "Console"}, "-874423954": {"name": "Test Ring 818", "category": "Test", "platform": "Console"}, "-874388017": {"name": "Test Ring 819", "category": "Test", "platform": "Console"}, "-873525529": {"name": "Test Ring 820", "category": "Test", "platform": "Console"}, "-873489592": {"name": "Test Ring 821", "category": "Test", "platform": "Console"}, "-873453655": {"name": "Test Ring 822", "category": "Test", "platform": "Console"}, "-873417718": {"name": "Test Ring 823", "category": "Test", "platform": "Console"}, "-873381781": {"name": "Test Ring 824", "category": "Test", "platform": "Console"}, "-873345844": {"name": "Test Ring 825", "category": "Test", "platform": "Console"}, "-873309907": {"name": "Test Ring 826", "category": "Test", "platform": "Console"}, "-873273970": {"name": "Test Ring 827", "category": "Test", "platform": "Console"}, "-873238033": {"name": "Test Ring 828", "category": "Test", "platform": "Console"}, "-873202096": {"name": "Test Ring 829", "category": "Test", "platform": "Console"}, "-872339608": {"name": "Test Ring 830", "category": "Test", "platform": "Console"}, "-872303671": {"name": "Test Ring 831", "category": "Test", "platform": "Console"}, "-872267734": {"name": "Test Ring 832", "category": "Test", "platform": "Console"}, "-872231797": {"name": "Test Ring 833", "category": "Test", "platform": "Console"}, "-872195860": {"name": "Test Ring 834", "category": "Test", "platform": "Console"}, "-872159923": {"name": "Test Ring 835", "category": "Test", "platform": "Console"}, "-872123986": {"name": "Test Ring 836", "category": "Test", "platform": "Console"}, "-872088049": {"name": "Test Ring 837", "category": "Test", "platform": "Console"}, "-872052112": {"name": "Test Ring 838", "category": "Test", "platform": "Console"}, "-872016175": {"name": "Test Ring 839", "category": "Test", "platform": "Console"}, "-871153687": {"name": "Test Ring 840", "category": "Test", "platform": "Console"}, "-871117750": {"name": "Test Ring 841", "category": "Test", "platform": "Console"}, "-871081813": {"name": "Test Ring 842", "category": "Test", "platform": "Console"}, "-871045876": {"name": "Test Ring 843", "category": "Test", "platform": "Console"}, "-871009939": {"name": "Test Ring 844", "category": "Test", "platform": "Console"}, "-870974002": {"name": "Test Ring 845", "category": "Test", "platform": "Console"}, "-870938065": {"name": "Test Ring 846", "category": "Test", "platform": "Console"}, "-870902128": {"name": "Test Ring 847", "category": "Test", "platform": "Console"}, "-870866191": {"name": "Test Ring 848", "category": "Test", "platform": "Console"}, "-870830254": {"name": "Test Ring 849", "category": "Test", "platform": "Console"}, "-869967766": {"name": "Test Ring 850", "category": "Test", "platform": "Console"}, "-869931829": {"name": "Test Ring 851", "category": "Test", "platform": "Console"}, "-869895892": {"name": "Test Ring 852", "category": "Test", "platform": "Console"}, "-869859955": {"name": "Test Ring 853", "category": "Test", "platform": "Console"}, "-869824018": {"name": "Test Ring 854", "category": "Test", "platform": "Console"}, "-869788081": {"name": "Test Ring 855", "category": "Test", "platform": "Console"}, "-869752144": {"name": "Test Ring 856", "category": "Test", "platform": "Console"}, "-869716207": {"name": "Test Ring 857", "category": "Test", "platform": "Console"}, "-869680270": {"name": "Test Ring 858", "category": "Test", "platform": "Console"}, "-869644333": {"name": "Test Ring 859", "category": "Test", "platform": "Console"}, "-868781845": {"name": "Test Ring 860", "category": "Test", "platform": "Console"}, "-868745908": {"name": "Test Ring 861", "category": "Test", "platform": "Console"}, "-868709971": {"name": "Test Ring 862", "category": "Test", "platform": "Console"}, "-868674034": {"name": "Test Ring 863", "category": "Test", "platform": "Console"}, "-868638097": {"name": "Test Ring 864", "category": "Test", "platform": "Console"}, "-868602160": {"name": "Test Ring 865", "category": "Test", "platform": "Console"}, "-868566223": {"name": "Test Ring 866", "category": "Test", "platform": "Console"}, "-868530286": {"name": "Test Ring 867", "category": "Test", "platform": "Console"}, "-868494349": {"name": "Test Ring 868", "category": "Test", "platform": "Console"}, "-868458412": {"name": "Test Ring 869", "category": "Test", "platform": "Console"}, "-867595924": {"name": "Test Ring 870", "category": "Test", "platform": "Console"}, "-867559987": {"name": "Test Ring 871", "category": "Test", "platform": "Console"}, "-867524050": {"name": "Test Ring 872", "category": "Test", "platform": "Console"}, "-867488113": {"name": "Test Ring 873", "category": "Test", "platform": "Console"}, "-867452176": {"name": "Test Ring 874", "category": "Test", "platform": "Console"}, "-867416239": {"name": "Test Ring 875", "category": "Test", "platform": "Console"}, "-867380302": {"name": "Test Ring 876", "category": "Test", "platform": "Console"}, "-867344365": {"name": "Test Ring 877", "category": "Test", "platform": "Console"}, "-867308428": {"name": "Test Ring 878", "category": "Test", "platform": "Console"}, "-867272491": {"name": "Test Ring 879", "category": "Test", "platform": "Console"}, "-866410003": {"name": "Test Ring 880", "category": "Test", "platform": "Console"}, "-866374066": {"name": "Test Ring 881", "category": "Test", "platform": "Console"}, "-866338129": {"name": "Test Ring 882", "category": "Test", "platform": "Console"}, "-866302192": {"name": "Test Ring 883", "category": "Test", "platform": "Console"}, "-866266255": {"name": "Test Ring 884", "category": "Test", "platform": "Console"}, "-866230318": {"name": "Test Ring 885", "category": "Test", "platform": "Console"}, "-866194381": {"name": "Test Ring 886", "category": "Test", "platform": "Console"}, "-866158444": {"name": "Test Ring 887", "category": "Test", "platform": "Console"}, "-866122507": {"name": "Test Ring 888", "category": "Test", "platform": "Console"}, "-866086570": {"name": "Test Ring 889", "category": "Test", "platform": "Console"}, "-865224082": {"name": "Test Ring 890", "category": "Test", "platform": "Console"}, "-865188145": {"name": "Test Ring 891", "category": "Test", "platform": "Console"}, "-865152208": {"name": "Test Ring 892", "category": "Test", "platform": "Console"}, "-865116271": {"name": "Test Ring 893", "category": "Test", "platform": "Console"}, "-865080334": {"name": "Test Ring 894", "category": "Test", "platform": "Console"}, "-865044397": {"name": "Test Ring 895", "category": "Test", "platform": "Console"}, "-865008460": {"name": "Test Ring 896", "category": "Test", "platform": "Console"}, "-864972523": {"name": "Test Ring 897", "category": "Test", "platform": "Console"}, "-864936586": {"name": "Test Ring 898", "category": "Test", "platform": "Console"}, "-864900649": {"name": "Test Ring 899", "category": "Test", "platform": "Console"}, "-836761978": {"name": "Test Ring 900", "category": "Test", "platform": "Console"}, "-836726041": {"name": "Test Ring 901", "category": "Test", "platform": "Console"}, "-836690104": {"name": "Test Ring 902", "category": "Test", "platform": "Console"}, "-836654167": {"name": "Test Ring 903", "category": "Test", "platform": "Console"}, "-836618230": {"name": "Test Ring 904", "category": "Test", "platform": "Console"}, "-836582293": {"name": "Test Ring 905", "category": "Test", "platform": "Console"}, "-836546356": {"name": "Test Ring 906", "category": "Test", "platform": "Console"}, "-836510419": {"name": "Test Ring 907", "category": "Test", "platform": "Console"}, "-836474482": {"name": "Test Ring 908", "category": "Test", "platform": "Console"}, "-836438545": {"name": "Test Ring 909", "category": "Test", "platform": "Console"}, "-835576057": {"name": "Test Ring 910", "category": "Test", "platform": "Console"}, "-835540120": {"name": "Test Ring 911", "category": "Test", "platform": "Console"}, "-835504183": {"name": "Test Ring 912", "category": "Test", "platform": "Console"}, "-835468246": {"name": "Test Ring 913", "category": "Test", "platform": "Console"}, "-835432309": {"name": "Test Ring 914", "category": "Test", "platform": "Console"}, "-835396372": {"name": "Test Ring 915", "category": "Test", "platform": "Console"}, "-835360435": {"name": "Test Ring 916", "category": "Test", "platform": "Console"}, "-835324498": {"name": "Test Ring 917", "category": "Test", "platform": "Console"}, "-835288561": {"name": "Test Ring 918", "category": "Test", "platform": "Console"}, "-835252624": {"name": "Test Ring 919", "category": "Test", "platform": "Console"}, "-834390136": {"name": "Test Ring 920", "category": "Test", "platform": "Console"}, "-834354199": {"name": "Test Ring 921", "category": "Test", "platform": "Console"}, "-834318262": {"name": "Test Ring 922", "category": "Test", "platform": "Console"}, "-834282325": {"name": "Test Ring 923", "category": "Test", "platform": "Console"}, "-834246388": {"name": "Test Ring 924", "category": "Test", "platform": "Console"}, "-834210451": {"name": "Test Ring 925", "category": "Test", "platform": "Console"}, "-834174514": {"name": "Test Ring 926", "category": "Test", "platform": "Console"}, "-834138577": {"name": "Test Ring 927", "category": "Test", "platform": "Console"}, "-834102640": {"name": "Test Ring 928", "category": "Test", "platform": "Console"}, "-834066703": {"name": "Test Ring 929", "category": "Test", "platform": "Console"}, "-833204215": {"name": "Test Ring 930", "category": "Test", "platform": "Console"}, "-833168278": {"name": "Test Ring 931", "category": "Test", "platform": "Console"}, "-833132341": {"name": "Test Ring 932", "category": "Test", "platform": "Console"}, "-833096404": {"name": "Test Ring 933", "category": "Test", "platform": "Console"}, "-833060467": {"name": "Test Ring 934", "category": "Test", "platform": "Console"}, "-833024530": {"name": "Test Ring 935", "category": "Test", "platform": "Console"}, "-832988593": {"name": "Test Ring 936", "category": "Test", "platform": "Console"}, "-832952656": {"name": "Test Ring 937", "category": "Test", "platform": "Console"}, "-832916719": {"name": "Test Ring 938", "category": "Test", "platform": "Console"}, "-832880782": {"name": "Test Ring 939", "category": "Test", "platform": "Console"}, "-832018294": {"name": "Test Ring 940", "category": "Test", "platform": "Console"}, "-831982357": {"name": "Test Ring 941", "category": "Test", "platform": "Console"}, "-831946420": {"name": "Test Ring 942", "category": "Test", "platform": "Console"}, "-831910483": {"name": "Test Ring 943", "category": "Test", "platform": "Console"}, "-831874546": {"name": "Test Ring 944", "category": "Test", "platform": "Console"}, "-831838609": {"name": "Test Ring 945", "category": "Test", "platform": "Console"}, "-831802672": {"name": "Test Ring 946", "category": "Test", "platform": "Console"}, "-831766735": {"name": "Test Ring 947", "category": "Test", "platform": "Console"}, "-831730798": {"name": "Test Ring 948", "category": "Test", "platform": "Console"}, "-831694861": {"name": "Test Ring 949", "category": "Test", "platform": "Console"}, "-830832373": {"name": "Test Ring 950", "category": "Test", "platform": "Console"}, "-830796436": {"name": "Test Ring 951", "category": "Test", "platform": "Console"}, "-830760499": {"name": "Test Ring 952", "category": "Test", "platform": "Console"}, "-830724562": {"name": "Test Ring 953", "category": "Test", "platform": "Console"}, "-830688625": {"name": "Test Ring 954", "category": "Test", "platform": "Console"}, "-830652688": {"name": "Test Ring 955", "category": "Test", "platform": "Console"}, "-830616751": {"name": "Test Ring 956", "category": "Test", "platform": "Console"}, "-830580814": {"name": "Test Ring 957", "category": "Test", "platform": "Console"}, "-830544877": {"name": "Test Ring 958", "category": "Test", "platform": "Console"}, "-830508940": {"name": "Test Ring 959", "category": "Test", "platform": "Console"}, "-829646452": {"name": "Test Ring 960", "category": "Test", "platform": "Console"}, "-829610515": {"name": "Test Ring 961", "category": "Test", "platform": "Console"}, "-829574578": {"name": "Test Ring 962", "category": "Test", "platform": "Console"}, "-829538641": {"name": "Test Ring 963", "category": "Test", "platform": "Console"}, "-829502704": {"name": "Test Ring 964", "category": "Test", "platform": "Console"}, "-829466767": {"name": "Test Ring 965", "category": "Test", "platform": "Console"}, "-829430830": {"name": "Test Ring 966", "category": "Test", "platform": "Console"}, "-829394893": {"name": "Test Ring 967", "category": "Test", "platform": "Console"}, "-829358956": {"name": "Test Ring 968", "category": "Test", "platform": "Console"}, "-829323019": {"name": "Test Ring 969", "category": "Test", "platform": "Console"}, "-828460531": {"name": "Test Ring 970", "category": "Test", "platform": "Console"}, "-828424594": {"name": "Test Ring 971", "category": "Test", "platform": "Console"}, "-828388657": {"name": "Test Ring 972", "category": "Test", "platform": "Console"}, "-828352720": {"name": "Test Ring 973", "category": "Test", "platform": "Console"}, "-828316783": {"name": "Test Ring 974", "category": "Test", "platform": "Console"}, "-828280846": {"name": "Test Ring 975", "category": "Test", "platform": "Console"}, "-828244909": {"name": "Test Ring 976", "category": "Test", "platform": "Console"}, "-828208972": {"name": "Test Ring 977", "category": "Test", "platform": "Console"}, "-828173035": {"name": "Test Ring 978", "category": "Test", "platform": "Console"}, "-828137098": {"name": "Test Ring 979", "category": "Test", "platform": "Console"}, "-827274610": {"name": "Test Ring 980", "category": "Test", "platform": "Console"}, "-827238673": {"name": "Test Ring 981", "category": "Test", "platform": "Console"}, "-827202736": {"name": "Test Ring 982", "category": "Test", "platform": "Console"}, "-827166799": {"name": "Test Ring 983", "category": "Test", "platform": "Console"}, "-827130862": {"name": "Test Ring 984", "category": "Test", "platform": "Console"}, "-827094925": {"name": "Test Ring 985", "category": "Test", "platform": "Console"}, "-827058988": {"name": "Test Ring 986", "category": "Test", "platform": "Console"}, "-827023051": {"name": "Test Ring 987", "category": "Test", "platform": "Console"}, "-826987114": {"name": "Test Ring 988", "category": "Test", "platform": "Console"}, "-826951177": {"name": "Test Ring 989", "category": "Test", "platform": "Console"}, "-826088689": {"name": "Test Ring 990", "category": "Test", "platform": "Console"}, "-826052752": {"name": "Test Ring 991", "category": "Test", "platform": "Console"}, "-826016815": {"name": "Test Ring 992", "category": "Test", "platform": "Console"}, "-825980878": {"name": "Test Ring 993", "category": "Test", "platform": "Console"}, "-825944941": {"name": "Test Ring 994", "category": "Test", "platform": "Console"}, "-825909004": {"name": "Test Ring 995", "category": "Test", "platform": "Console"}, "-825873067": {"name": "Test Ring 996", "category": "Test", "platform": "Console"}, "-825837130": {"name": "Test Ring 997", "category": "Test", "platform": "Console"}, "-825801193": {"name": "Test Ring 998", "category": "Test", "platform": "Console"}, "-825765256": {"name": "Test Ring 999", "category": "Test", "platform": "Console"}, "620034066": {"name": "01: Tribal Mask (AR 30-35)", "category": "Voodoo Masks", "platform": "Console"}, "620034067": {"name": "02: Shaman Mask (AR 36-41)", "category": "Voodoo Masks", "platform": "Console"}, "620034068": {"name": "03: Chieftain Mask (AR 60-69)", "category": "Voodoo Masks", "platform": "Console"}, "620034069": {"name": "04: Spirit Mask (AR 84-113)", "category": "Voodoo Masks", "platform": "Console"}, "620035155": {"name": "05: Woodwraith Bark (AR 114-149)", "category": "Voodoo Masks", "platform": "Console"}, "620035156": {"name": "06: Burial Mask (AR 150-185)", "category": "Voodoo Masks", "platform": "Console"}, "620035157": {"name": "07: Naga Mask (AR 186-232)", "category": "Voodoo Masks", "platform": "Console"}, "620035158": {"name": "08: Umbra Mask (AR 232-254)", "category": "Voodoo Masks", "platform": "Console"}, "620036244": {"name": "09: Screaming Mask (AR 255-322)", "category": "Voodoo Masks", "platform": "Console"}, "620036245": {"name": "10: Underworld Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036246": {"name": "11: Manitou Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036247": {"name": "12: Deva (AR 360-472)", "category": "Voodoo Masks", "platform": "Console"}, "620036248": {"name": "13: Tribal Mask (AR 472-659)", "category": "Voodoo Masks", "platform": "Console"}, "620036249": {"name": "14: Ascended Mask (AR 660-759)", "category": "Voodoo Masks", "platform": "Console"}, "-1716736265": {"name": "Art Test VoodooMask 1", "category": "Voodoo Masks", "platform": "Console"}, "-1716736264": {"name": "Art Test VoodooMask 2", "category": "Voodoo Masks", "platform": "Console"}, "-1716736263": {"name": "Art Test VoodooMask 3", "category": "Voodoo Masks", "platform": "Console"}, "-1716736262": {"name": "Art Test VoodooMask 4", "category": "Voodoo Masks", "platform": "Console"}, "-1716736261": {"name": "Art Test VoodooMask 5", "category": "Voodoo Masks", "platform": "Console"}, "-801205711": {"name": "Legendary: Carnevil", "category": "Voodoo Masks", "platform": "Console"}, "-801169774": {"name": "Legendary: Mask of Jeram", "category": "Voodoo Masks", "platform": "Console"}, "-840197356": {"name": "Legendary: Quetzalcoatl", "category": "Voodoo Masks", "platform": "Console"}, "-1956786272": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1956783828": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555852": {"name": "Legendary: Quetzalcoatl (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840161419": {"name": "Legendary: Split Tusk", "category": "Voodoo Masks", "platform": "Console"}, "-1955600351": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1955597907": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555853": {"name": "Legendary: Split Tusk (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840305167": {"name": "Legendary: The Grin Reaper", "category": "Voodoo Masks", "platform": "Console"}, "-1960344035": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1960341591": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555849": {"name": "Legendary: The Grin Reaper (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840341104": {"name": "Legendary: Tiklandian Visage", "category": "Voodoo Masks", "platform": "Console"}, "-1961529956": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1961527512": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555848": {"name": "Legendary: Tiklandian Visage (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840089545": {"name": "Legendary: Visage of Giyua", "category": "Voodoo Masks", "platform": "Console"}, "-1953228509": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1953226065": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555855": {"name": "Legendary: Visage of Giyua (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555854": {"name": "Set: Zunimassa's Attunement (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840125482": {"name": "Set: Zunimassa's Vision", "category": "Voodoo Masks", "platform": "Console"}, "-1954414430": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1954411986": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "88665049": {"name": "00: Apprentice's Wand (DPS 3.0)", "category": "Wands", "platform": "Console"}, "88665050": {"name": "01: Lesser Wand (DPS 9.8-11.2)", "category": "Wands", "platform": "Console"}, "88665051": {"name": "02: Oak Wand (DPS 11.2-13.3)", "category": "Wands", "platform": "Console"}, "88665052": {"name": "03: Wand (DPS 14.7-16.8)", "category": "Wands", "platform": "Console"}, "88665053": {"name": "04: Steel Wand (DPS 17.5-19.6)", "category": "Wands", "platform": "Console"}, "88665054": {"name": "05: Mentor Wand (DPS 21.7-23.8)", "category": "Wands", "platform": "Console"}, "88665055": {"name": "06: Enchanter Wand (DPS 25.2-27.3)", "category": "Wands", "platform": "Console"}, "88665056": {"name": "07: Grim Wand (DPS 29.4-31.5)", "category": "Wands", "platform": "Console"}, "88666139": {"name": "08: Petrified Wand (DPS 41.3-43.4)", "category": "Wands", "platform": "Console"}, "88666140": {"name": "09: Duelist Wand (DPS 47.6-49.7)", "category": "Wands", "platform": "Console"}, "88666141": {"name": "10: Jade Wand (DPS 55.3-57.4)", "category": "Wands", "platform": "Console"}, "88666142": {"name": "11: Battle Wand (DPS 65.1-67.2)", "category": "Wands", "platform": "Console"}, "88666143": {"name": "12: Divination Wand (DPS 75.6-77.7)", "category": "Wands", "platform": "Console"}, "88666144": {"name": "13: Sorcery Wand (DPS 89.6-93.8)", "category": "Wands", "platform": "Console"}, "88666145": {"name": "14: Silversteel Wand (DPS 105.0-109.2)", "category": "Wands", "platform": "Console"}, "88667228": {"name": "15: Greater Wand (DPS 115.5-119.7)", "category": "Wands", "platform": "Console"}, "88667229": {"name": "16: Guardian (DPS 127.4-131.6)", "category": "Wands", "platform": "Console"}, "88667230": {"name": "17: Magus Wand (DPS 139.3-145.6)", "category": "Wands", "platform": "Console"}, "88667231": {"name": "18: Spellbinder (DPS 153.3-159.6)", "category": "Wands", "platform": "Console"}, "88667232": {"name": "19: Archmage Wand (DPS 177.1-183.4)", "category": "Wands", "platform": "Console"}, "88667233": {"name": "20: Strike Wand (DPS 203.0-211.4)", "category": "Wands", "platform": "Console"}, "88667234": {"name": "21: Desolator Wand (DPS 235.2-243.6)", "category": "Wands", "platform": "Console"}, "88668317": {"name": "22: Demon's Head Wand (DPS 315.0-321.3)", "category": "Wands", "platform": "Console"}, "88668318": {"name": "23: Diabolic Wand (DPS 385.0-391.3)", "category": "Wands", "platform": "Console"}, "2004783359": {"name": "Art Test Wand 1", "category": "Wands", "platform": "Console"}, "2004783360": {"name": "Art Test Wand 2", "category": "Wands", "platform": "Console"}, "2004783361": {"name": "Art Test Wand 3", "category": "Wands", "platform": "Console"}, "2004783362": {"name": "Art Test Wand 4", "category": "Wands", "platform": "Console"}, "2004783363": {"name": "Art Test Wand 5", "category": "Wands", "platform": "Console"}, "456527018": {"name": "Crafted: Elderwood Wand", "category": "Wands", "platform": "Console"}, "-1415147493": {"name": "Legendary: Aether Walker (Patch 2.1.0)", "category": "Wands", "platform": "Console"}, "1859914464": {"name": "Legendary: Atrophy", "category": "Wands", "platform": "Console"}, "1859806653": {"name": "Legendary: Blackhand Key", "category": "Wands", "platform": "Console"}, "1244000105": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "1244002549": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "161873429": {"name": "Legendary: Blackhand Key (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860776952": {"name": "Legendary: Fragment of Destiny", "category": "Wands", "platform": "Console"}, "1276019972": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "1276022416": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "161873456": {"name": "Legendary: Fragment of Destiny (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859662905": {"name": "Legendary: Gesture of Orpheus", "category": "Wands", "platform": "Console"}, "1239256421": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "1239258865": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "161873425": {"name": "Legendary: Gesture of Orpheus (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1247557868": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "1247560312": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "161873432": {"name": "Legendary: Ruinstoke (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898798298": {"name": "Legendary: Serpent's Sparker", "category": "Wands", "platform": "Console"}, "1860884763": {"name": "Legendary: Slorak's Madness", "category": "Wands", "platform": "Console"}, "1279577735": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "1279580179": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "161873459": {"name": "Legendary: Slorak's Madness (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859698842": {"name": "Legendary: Starfire", "category": "Wands", "platform": "Console"}, "1240442342": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "1240444786": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "161873426": {"name": "Legendary: Starfire (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898762361": {"name": "Legendary: Wand of Woh", "category": "Wands", "platform": "Console"}, "-1415147492": {"name": "P1 Wand norm Legendary 02", "category": "Wands", "platform": "Console"}, "161873458": {"name": "Set: Chantodo's Sacred Protector (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860848826": {"name": "Set: Chantodo's Will", "category": "Wands", "platform": "Console"}, "1278391814": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1278394258": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1861064448": {"name": "Set: Hallowed Baton", "category": "Wands", "platform": "Console"}, "161873464": {"name": "Set: Hallowed Rod (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1285507340": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1285509784": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1771839282": {"name": "legendary: Gesture Of Orpheus (Patch 2.2.0)", "category": "Wands", "platform": "Console"}, "1755621630": {"name": "01: Wanderer Hat (AR 30-35)", "category": "Wizard Hats", "platform": "Console"}, "1755621631": {"name": "02: Journey Mask (AR 36-41)", "category": "Wizard Hats", "platform": "Console"}, "1755621632": {"name": "03: Scholarly Fez (AR 60-69)", "category": "Wizard Hats", "platform": "Console"}, "1755621633": {"name": "04: Charlatan Cap (AR 84-113)", "category": "Wizard Hats", "platform": "Console"}, "1755622719": {"name": "05: Conjurer Shade (AR 114-149)", "category": "Wizard Hats", "platform": "Console"}, "1755622720": {"name": "06: Mystic Shade (AR 150-185)", "category": "Wizard Hats", "platform": "Console"}, "1755622721": {"name": "07: Mentor Cap (AR 186-232)", "category": "Wizard Hats", "platform": "Console"}, "1755622722": {"name": "08: Traveler Hat (AR 232-254)", "category": "Wizard Hats", "platform": "Console"}, "1755623808": {"name": "09: Sage Hat (AR 255-284)", "category": "Wizard Hats", "platform": "Console"}, "1755623809": {"name": "10: Sinister Mask (AR 285-322)", "category": "Wizard Hats", "platform": "Console"}, "1755623810": {"name": "11: Archmage Headpiece (AR 322-359)", "category": "Wizard Hats", "platform": "Console"}, "1755623811": {"name": "12: Elder Hat (AR 360-472)", "category": "Wizard Hats", "platform": "Console"}, "1755623812": {"name": "13: Vizier Hat (AR 472-659)", "category": "Wizard Hats", "platform": "Console"}, "1755623813": {"name": "14: Ascended Headpiece (AR 660-759)", "category": "Wizard Hats", "platform": "Console"}, "376117315": {"name": "Art Test WizardHat 1", "category": "Wizard Hats", "platform": "Console"}, "376117316": {"name": "Art Test WizardHat 2", "category": "Wizard Hats", "platform": "Console"}, "376117317": {"name": "Art Test WizardHat 3", "category": "Wizard Hats", "platform": "Console"}, "376117318": {"name": "Art Test WizardHat 4", "category": "Wizard Hats", "platform": "Console"}, "376117319": {"name": "Art Test WizardHat 5", "category": "Wizard Hats", "platform": "Console"}, "414491869": {"name": "Legendary: Archmage's Vicalyke", "category": "Wizard Hats", "platform": "Console"}, "375356476": {"name": "Legendary: Dark Mage's Shade", "category": "Wizard Hats", "platform": "Console"}, "-498215480": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-498213036": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827188": {"name": "Legendary: Dark Mage's Shade (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414599680": {"name": "Legendary: Mask of Lies", "category": "Wizard Hats", "platform": "Console"}, "375464287": {"name": "Legendary: Storm Crow", "category": "Wizard Hats", "platform": "Console"}, "-494657717": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-494655273": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827191": {"name": "Legendary: Storm Crow (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414563743": {"name": "Legendary: The Magistrate", "category": "Wizard Hats", "platform": "Console"}, "375428350": {"name": "Legendary: The Swami", "category": "Wizard Hats", "platform": "Console"}, "-495843638": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-495841194": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827190": {"name": "Legendary: The Swami (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-936099818": {"name": "Legendary: The Swami (Patch 2.1.0)", "category": "Wizard Hats", "platform": "Console"}, "414527806": {"name": "Legendary: Velvet Camaral", "category": "Wizard Hats", "platform": "Console"}} \ No newline at end of file diff --git a/assets/gbidscategorised.json b/assets/gbidscategorised.json index 53cf1a7..fecafe0 100644 --- a/assets/gbidscategorised.json +++ b/assets/gbidscategorised.json @@ -1 +1 @@ -{"None": {}, "Amulets": {"1682228618": {"name": "02: Amulet", "category": "Amulets", "platform": "Console"}, "1682228619": {"name": "03: Amulet", "category": "Amulets", "platform": "Console"}, "1682228620": {"name": "04: Amulet", "category": "Amulets", "platform": "Console"}, "1682228621": {"name": "05: Amulet", "category": "Amulets", "platform": "Console"}, "1682228622": {"name": "06: Amulet", "category": "Amulets", "platform": "Console"}, "1682228623": {"name": "07: Amulet", "category": "Amulets", "platform": "Console"}, "1682228624": {"name": "08: Amulet", "category": "Amulets", "platform": "Console"}, "1682228625": {"name": "09: Amulet", "category": "Amulets", "platform": "Console"}, "1682228649": {"name": "10: Amulet", "category": "Amulets", "platform": "Console"}, "1682228650": {"name": "11: Amulet", "category": "Amulets", "platform": "Console"}, "1682228651": {"name": "12: Amulet", "category": "Amulets", "platform": "Console"}, "1682228652": {"name": "13: Amulet", "category": "Amulets", "platform": "Console"}, "1682228653": {"name": "14: Amulet", "category": "Amulets", "platform": "Console"}, "1682228654": {"name": "15: Amulet", "category": "Amulets", "platform": "Console"}, "1682228655": {"name": "16: Amulet", "category": "Amulets", "platform": "Console"}, "1682228656": {"name": "17: Amulet", "category": "Amulets", "platform": "Console"}, "-1335710051": {"name": "Art Test Amulet 1", "category": "Amulets", "platform": "Console"}, "-1335710050": {"name": "Art Test Amulet 2", "category": "Amulets", "platform": "Console"}, "-1335710049": {"name": "Art Test Amulet 3", "category": "Amulets", "platform": "Console"}, "-1335710048": {"name": "Art Test Amulet 4", "category": "Amulets", "platform": "Console"}, "-1335710047": {"name": "Art Test Amulet 5", "category": "Amulets", "platform": "Console"}, "1566332280": {"name": "Legendary: Ancestors' Grace", "category": "Amulets", "platform": "Console"}, "1566368217": {"name": "Legendary: Countess Julia's Cameo", "category": "Amulets", "platform": "Console"}, "1566511965": {"name": "Legendary: Dovu Energy Trap", "category": "Amulets", "platform": "Console"}, "1200923753": {"name": "Legendary: Drake's Amulet (PS3 Promo)", "category": "Amulets", "platform": "Console"}, "1528454682": {"name": "Legendary: Eye of Etlich", "category": "Amulets", "platform": "Console"}, "-1100680346": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "-1100677902": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "412126098": {"name": "Legendary: Eye of Etlich (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566440091": {"name": "Legendary: Golden Gorget of Leoric", "category": "Amulets", "platform": "Console"}, "1566583839": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "737941201": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "1566296343": {"name": "Legendary: Haunt of Vaxo", "category": "Amulets", "platform": "Console"}, "761548935": {"name": "Legendary: Hellfire Amulet (Patch 1.2.0)", "category": "Amulets", "platform": "Console"}, "1528418745": {"name": "Legendary: Holy Beacon", "category": "Amulets", "platform": "Console"}, "-1101866267": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "-1101863823": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "412126097": {"name": "Legendary: Holy Beacon (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196887": {"name": "Legendary: Kymbo's Gold", "category": "Amulets", "platform": "Console"}, "-1142187581": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "-1142185137": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "412126063": {"name": "Legendary: Kymbo's Gold (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196623": {"name": "Legendary: Kymbo's Gold (Patch 2.1.0)", "category": "Amulets", "platform": "Console"}, "1528490619": {"name": "Legendary: Mara's Kaleidoscope", "category": "Amulets", "platform": "Console"}, "-1099494425": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "-1099491981": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "412126099": {"name": "Legendary: Mara's Kaleidoscope (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527232824": {"name": "Legendary: Moonlight Ward", "category": "Amulets", "platform": "Console"}, "-1141001660": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "-1140999216": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "412126064": {"name": "Legendary: Moonlight Ward (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527304698": {"name": "Legendary: Ouroboros", "category": "Amulets", "platform": "Console"}, "-1138629818": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "-1138627374": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "412126066": {"name": "Legendary: Ouroboros (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566476028": {"name": "Legendary: Overwhelming Desire", "category": "Amulets", "platform": "Console"}, "1566547902": {"name": "Legendary: Rakoff's Glass of Life", "category": "Amulets", "platform": "Console"}, "1527448446": {"name": "Legendary: Rondal's Locket", "category": "Amulets", "platform": "Console"}, "-1133886134": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1133883690": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126070": {"name": "Legendary: Rondal's Locket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528310934": {"name": "Legendary: Squirt's Necklace", "category": "Amulets", "platform": "Console"}, "-1105424030": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "-1105421586": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "412126094": {"name": "Legendary: Squirt's Necklace (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528382808": {"name": "Legendary: Talisman of Aranoch", "category": "Amulets", "platform": "Console"}, "-1103052188": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "-1103049744": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "412126096": {"name": "Legendary: Talisman of Aranoch (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566404154": {"name": "Legendary: The Ess of Johan", "category": "Amulets", "platform": "Console"}, "1527160950": {"name": "Legendary: The Flavor of Time", "category": "Amulets", "platform": "Console"}, "-1143373502": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "-1143371058": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "412126062": {"name": "Legendary: The Flavor of Time (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528346871": {"name": "Legendary: The Murlocket", "category": "Amulets", "platform": "Console"}, "-1104238109": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1104235665": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126095": {"name": "Legendary: The Murlocket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527340635": {"name": "Legendary: The Star of Azkaranth", "category": "Amulets", "platform": "Console"}, "-1137443897": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "-1137441453": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "412126067": {"name": "Legendary: The Star of Azkaranth (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527268761": {"name": "Legendary: Xephirian Amulet", "category": "Amulets", "platform": "Console"}, "-1139815739": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "-1139813295": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "412126065": {"name": "Legendary: Xephirian Amulet (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "714520304": {"name": "PvP: Art of War 3v3", "category": "Amulets", "platform": "Console"}, "1685772266": {"name": "PvP: Art of War All", "category": "Amulets", "platform": "Console"}, "1685772538": {"name": "PvP: Art of War Attack", "category": "Amulets", "platform": "Console"}, "1685775296": {"name": "PvP: Art of War Defense", "category": "Amulets", "platform": "Console"}, "-203544613": {"name": "PvP: Art of War Precision", "category": "Amulets", "platform": "Console"}, "1685795044": {"name": "PvP: Art of War Vitality", "category": "Amulets", "platform": "Console"}, "-203302615": {"name": "PvP: Art of War Willpower", "category": "Amulets", "platform": "Console"}, "1803178445": {"name": "PvP: Born for War All", "category": "Amulets", "platform": "Console"}, "1803178717": {"name": "PvP: Born for War Attack", "category": "Amulets", "platform": "Console"}, "1803181475": {"name": "PvP: Born for War Defense", "category": "Amulets", "platform": "Console"}, "-624108002": {"name": "PvP: Born for War Precision", "category": "Amulets", "platform": "Console"}, "1803201223": {"name": "PvP: Born for War Vitality", "category": "Amulets", "platform": "Console"}, "1528526556": {"name": "Set: Blackthorne's Duncraig Cross", "category": "Amulets", "platform": "Console"}, "-1098308504": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "-1098306060": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "412126100": {"name": "Set: Blackthorne's Medal (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "412126069": {"name": "Set: Spirit of Adventure (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "-1544505070": {"name": "Set: Sunwuko's Shines", "category": "Amulets", "platform": "Console"}, "412126068": {"name": "Set: Tal Rasha's Adjudication (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527376572": {"name": "Set: Tal Rasha's Allegiance", "category": "Amulets", "platform": "Console"}, "-1136257976": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "-1136255532": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "1527412509": {"name": "Set: The Traveler's Pledge", "category": "Amulets", "platform": "Console"}, "-1135072055": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-1135069611": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-795161790": {"name": "legendary: Moonlight Ward (Patch 2.2.0)", "category": "Amulets", "platform": "Console"}}, "Axes, One-Handed": {"1661412390": {"name": "01: Hand Axe (DPS 3.3-4.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412391": {"name": "02: Broad Axe (DPS 7.2-9.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412392": {"name": "03: Double Axe (DPS 12.4-14.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412393": {"name": "04: Heavy Axe (DPS 17.6-19.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412394": {"name": "05: Battle Axe (DPS 21.5-23.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412395": {"name": "06: Marauder Axe (DPS 26.7-28.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412396": {"name": "07: Soldier Axe (DPS 31.2-33.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413479": {"name": "08: Hatchet (DPS 36.4-38.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413480": {"name": "09: Ono (DPS 46.2-48.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413481": {"name": "10: Bullova (DPS 57.2-59.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413482": {"name": "11: Adze (DPS 69.6-73.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413483": {"name": "12: Chopper (DPS 86.5-90.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413484": {"name": "13: Toporok (DPS 101.4-105.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413485": {"name": "14: Masakari (DPS 118.3-122.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414568": {"name": "15: Tomahawk (DPS 129.4-135.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414569": {"name": "16: Crescent Axe (DPS 144.3-150.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414570": {"name": "17: Arreat Axe (DPS 160.6-166.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414571": {"name": "18: Balestarius (DPS 177.5-185.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414572": {"name": "19: Skartaran Axe (DPS 206.7-214.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414573": {"name": "20: Galraki (DPS 238.6-246.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414574": {"name": "21: Arch Axe (DPS 275.6-285.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415657": {"name": "22: Executioner's Axe (DPS 371.8-379.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415658": {"name": "23: Dire Axe (DPS 461.5-469.3)", "category": "Axes, One-Handed", "platform": "Console"}, "-657929333": {"name": "Art Test Axe One-Handed 1", "category": "Axes, One-Handed", "platform": "Console"}, "-657929332": {"name": "Art Test Axe One-Handed 2", "category": "Axes, One-Handed", "platform": "Console"}, "-657929331": {"name": "Art Test Axe One-Handed 3", "category": "Axes, One-Handed", "platform": "Console"}, "-657929330": {"name": "Art Test Axe One-Handed 4", "category": "Axes, One-Handed", "platform": "Console"}, "-657929329": {"name": "Art Test Axe One-Handed 5", "category": "Axes, One-Handed", "platform": "Console"}, "824126149": {"name": "Legendary: Aidan's Revenge", "category": "Axes, One-Handed", "platform": "Console"}, "824162086": {"name": "Legendary: Fenris Tooth", "category": "Axes, One-Handed", "platform": "Console"}, "784990756": {"name": "Legendary: Flesh Tearer", "category": "Axes, One-Handed", "platform": "Console"}, "134813872": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "134816316": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046948": {"name": "Legendary: Flesh Tearer (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785062630": {"name": "Legendary: Genzaniku", "category": "Axes, One-Handed", "platform": "Console"}, "137185714": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "137188158": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046946": {"name": "Legendary: Genzaniku (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "824198023": {"name": "Legendary: Hack", "category": "Axes, One-Handed", "platform": "Console"}, "785134504": {"name": "Legendary: Sky Splitter", "category": "Axes, One-Handed", "platform": "Console"}, "139557556": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "139560000": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046944": {"name": "Legendary: Sky Splitter (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785206378": {"name": "Legendary: The Burning Axe of Sankis", "category": "Axes, One-Handed", "platform": "Console"}, "141929398": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "141931842": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046942": {"name": "Legendary: The Burning Axe of Sankis (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785170441": {"name": "Legendary: The Butcher's Sickle", "category": "Axes, One-Handed", "platform": "Console"}, "140743477": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "140745921": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046943": {"name": "Legendary: The Butcher's Sickle (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138371635": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138374079": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046945": {"name": "Legendary: The Wedge (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785098567": {"name": "Legendary: Utar's Roar", "category": "Axes, One-Handed", "platform": "Console"}, "786248551": {"name": "Set: Hallowed Breach", "category": "Axes, One-Handed", "platform": "Console"}, "-219046913": {"name": "Set: Hallowed Divide (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176321107": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176323551": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785134241": {"name": "legendary: Sky Spliiter (Patch 2.2.0)", "category": "Axes, One-Handed", "platform": "Console"}}, "Axes, Two-Handed": {"1700547784": {"name": "02: War Axe (DPS 16.0-17.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547785": {"name": "03: Tabarzin (DPS 22.5-24.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547786": {"name": "04: Military Axe (DPS 31.5-33.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547787": {"name": "05: Great Axe (DPS 42.5-44.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548872": {"name": "06: Timber Axe (DPS 56.5-59.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548873": {"name": "07: Francisca (DPS 73.5-76.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548874": {"name": "08: Fang Axe (DPS 94.0-98.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548875": {"name": "09: Parashu (DPS 119.0-125.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548876": {"name": "10: Labrys (DPS 170.0-177.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549961": {"name": "11: Fell Axe (DPS 230.5-241.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549962": {"name": "12: Valaska (DPS 313.0-325.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549963": {"name": "13: Ripper Axe (DPS 400.0-412.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549964": {"name": "14: Sagaris (DPS 474.5-486.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549965": {"name": "15: Decapitator (DPS 560.0-572.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551050": {"name": "16: Dread Axe (DPS 698.0-711.2)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551051": {"name": "17: Flesh Render (DPS 948.2-961.4)", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893396": {"name": "Art Test Axe Two-Handed 1", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893395": {"name": "Art Test Axe Two-Handed 2", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893394": {"name": "Art Test Axe Two-Handed 3", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893393": {"name": "Art Test Axe Two-Handed 4", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893392": {"name": "Art Test Axe Two-Handed 5", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516456824": {"name": "Legendary: Burst of Wrath", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555664091": {"name": "Legendary: Butcher's Carver", "category": "Axes, Two-Handed", "platform": "Console"}, "202615249": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "202617693": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911555": {"name": "Legendary: Butcher's Carver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554514107": {"name": "Legendary: Cinder Switch", "category": "Axes, Two-Handed", "platform": "Console"}, "240564721": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "240567165": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911523": {"name": "Legendary: Fire Brand (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554478170": {"name": "Legendary: Messerschmidt's Reaver", "category": "Axes, Two-Handed", "platform": "Console"}, "241750642": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "241753086": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911522": {"name": "Legendary: Messerschmidt's Reaver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516420887": {"name": "Legendary: Saint of Slaughter", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555376595": {"name": "Legendary: Skorn", "category": "Axes, Two-Handed", "platform": "Console"}, "212102617": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "212105061": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911547": {"name": "Legendary: Skorn (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516492761": {"name": "Legendary: Sungjae's Fury", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555592217": {"name": "Legendary: The Executioner", "category": "Axes, Two-Handed", "platform": "Console"}, "204987091": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "204989535": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911553": {"name": "Legendary: The Executioner (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516528698": {"name": "Legendary: The Marauder", "category": "Axes, Two-Handed", "platform": "Console"}, "120887006": {"name": "PvP: Heroic Reaper", "category": "Axes, Two-Handed", "platform": "Console"}, "120887005": {"name": "PvP: Mighty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "120887004": {"name": "PvP: Trusty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}}, "Belts": {"-733831368": {"name": "02: Hide Belt (AR 24-28)", "category": "Belts", "platform": "Console"}, "-733831367": {"name": "03: Leather Belt (AR 14-16)", "category": "Belts", "platform": "Console"}, "-733831366": {"name": "04: Cord (AR 44-53)", "category": "Belts", "platform": "Console"}, "-733831365": {"name": "05: Binding Rope (AR 54-67)", "category": "Belts", "platform": "Console"}, "-733831364": {"name": "06: Chain Belt (AR 34-43)", "category": "Belts", "platform": "Console"}, "-733830280": {"name": "07: Silk Sash (AR 68-87)", "category": "Belts", "platform": "Console"}, "-733830279": {"name": "08: Waistwrap (AR 88-107)", "category": "Belts", "platform": "Console"}, "-733830278": {"name": "09: Strand (AR 108-127)", "category": "Belts", "platform": "Console"}, "-733830277": {"name": "10: Cupola (AR 128-149)", "category": "Belts", "platform": "Console"}, "-733830276": {"name": "11: Cinch (AR 150-164)", "category": "Belts", "platform": "Console"}, "-733829191": {"name": "12: Grasp (AR 165-179)", "category": "Belts", "platform": "Console"}, "-733829190": {"name": "13: Sheath (AR 180-189)", "category": "Belts", "platform": "Console"}, "-733829189": {"name": "14: Cincture (AR 190-214)", "category": "Belts", "platform": "Console"}, "-733829188": {"name": "15: Girdle (AR 215-239)", "category": "Belts", "platform": "Console"}, "-733829187": {"name": "16: Heaven Strand (AR 240-264)", "category": "Belts", "platform": "Console"}, "-733829186": {"name": "17: High Scabbard (AR 265-314)", "category": "Belts", "platform": "Console"}, "-733829185": {"name": "18: War Belt (AR 315-439)", "category": "Belts", "platform": "Console"}, "-733829184": {"name": "19: Archon Sash (AR 440-506)", "category": "Belts", "platform": "Console"}, "1187629340": {"name": "Art Test Belt 1", "category": "Belts", "platform": "Console"}, "1187629341": {"name": "Art Test Belt 2", "category": "Belts", "platform": "Console"}, "1187629342": {"name": "Art Test Belt 3", "category": "Belts", "platform": "Console"}, "1187629343": {"name": "Art Test Belt 4", "category": "Belts", "platform": "Console"}, "1187629344": {"name": "Art Test Belt 5", "category": "Belts", "platform": "Console"}, "949342869": {"name": "Belt Of The Trove (Patch 2.1.2)", "category": "Belts", "platform": "Console"}, "1770820311": {"name": "Legendary: Angel Hair Braid", "category": "Belts", "platform": "Console"}, "-1692549181": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-1692546737": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-660622993": {"name": "Legendary: Angel Hair Braid (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770820047": {"name": "Legendary: Angel Hair Braid (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1809991641": {"name": "Legendary: Cord of the Sherma", "category": "Belts", "platform": "Console"}, "1770856248": {"name": "Legendary: Fleeting Strap", "category": "Belts", "platform": "Console"}, "1771898421": {"name": "Legendary: Goldwrap", "category": "Belts", "platform": "Console"}, "-1656971551": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1656969107": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622963": {"name": "Legendary: Goldwrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810027578": {"name": "Legendary: Harrington Waistguard", "category": "Belts", "platform": "Console"}, "1770892185": {"name": "Legendary: Hellcat Waistguard", "category": "Belts", "platform": "Console"}, "-1690177339": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-1690174895": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-660622991": {"name": "Legendary: Hellcat Waistguard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810099452": {"name": "Legendary: Hwoj Wrap", "category": "Belts", "platform": "Console"}, "1809955704": {"name": "Legendary: Insatiable Belt", "category": "Belts", "platform": "Console"}, "1810063515": {"name": "Legendary: Jang's Envelopment", "category": "Belts", "platform": "Console"}, "-1691363260": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1691360816": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622992": {"name": "Legendary: Quick Draw Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809883830": {"name": "Legendary: Razor Strop", "category": "Belts", "platform": "Console"}, "1770748437": {"name": "Legendary: Saffron Wrap", "category": "Belts", "platform": "Console"}, "-1694921023": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1694918579": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622995": {"name": "Legendary: Saffron Wrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809919767": {"name": "Legendary: Sash of Knives", "category": "Belts", "platform": "Console"}, "1809919503": {"name": "Legendary: Sash of Knives (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1810135389": {"name": "Legendary: Sebor's Nightmare", "category": "Belts", "platform": "Console"}, "1770999996": {"name": "Legendary: String of Ears", "category": "Belts", "platform": "Console"}, "-1686619576": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-1686617132": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-660622988": {"name": "Legendary: String of Ears (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1771035933": {"name": "Legendary: The Witching Hour", "category": "Belts", "platform": "Console"}, "-1685433655": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-1685431211": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-660622987": {"name": "Legendary: The Witching Hour (Old-Legacy)", "category": "Belts", "platform": "Console"}, "924103246": {"name": "Legendary: Thundergod's Vigor", "category": "Belts", "platform": "Console"}, "1770784374": {"name": "Legendary: Vigilante Belt", "category": "Belts", "platform": "Console"}, "-1693735102": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1693732658": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622994": {"name": "Legendary: Vigilante Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1772078106": {"name": "Set: Blackthorne's Notched Belt", "category": "Belts", "platform": "Console"}, "-1651041946": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1651039502": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622958": {"name": "Set: Blackthorne's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-660622961": {"name": "Set: Captain Crimson's Brace (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1654599709": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "-1654597265": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "1771970295": {"name": "Set: Captain Crimson's Silk Girdle", "category": "Belts", "platform": "Console"}, "-660622959": {"name": "Set: Demon's Binding (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1652227867": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "-1652225423": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "1772042169": {"name": "Set: Demon's Restraint", "category": "Belts", "platform": "Console"}, "1772006232": {"name": "Set: Guardian's Case", "category": "Belts", "platform": "Console"}, "-660622960": {"name": "Set: Guardian's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1653413788": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-1653411344": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-660622989": {"name": "Set: Inna's Blessing (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770964059": {"name": "Set: Inna's Favor", "category": "Belts", "platform": "Console"}, "-1687805497": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-1687803053": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-885483983": {"name": "Set: Krelm's Buff Belt", "category": "Belts", "platform": "Console"}, "1770928122": {"name": "Set: Tal Rasha's Brace", "category": "Belts", "platform": "Console"}, "-1688991418": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-1688988974": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-660622990": {"name": "Set: Tal Rasha's Finespun Cloth (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1069972162": {"name": "legendary: Belessed of Haull (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972159": {"name": "legendary: Belt of Transcendence (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972158": {"name": "legendary: Crashing Rain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972160": {"name": "legendary: Haunting Girdle (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972161": {"name": "legendary: Omnislash (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972163": {"name": "legendary: Omryn's Chain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809919504": {"name": "legendary: Sash of Knives (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1810135126": {"name": "legendary: Sebor's Nightmare (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809991378": {"name": "legendary: Sherma of Corrosion (Patch 2.2.0)", "category": "Belts", "platform": "Console"}}, "Boots": {"2140880152": {"name": "02: Boots (AR 16-18)", "category": "Boots", "platform": "Console"}, "2140880153": {"name": "03: Heavy Boots (AR 30-35)", "category": "Boots", "platform": "Console"}, "2140880154": {"name": "04: Chain Boots (AR 44-57)", "category": "Boots", "platform": "Console"}, "2140880155": {"name": "05: Sabatons (AR 58-66)", "category": "Boots", "platform": "Console"}, "2140880156": {"name": "06: Greaves (AR 67-82)", "category": "Boots", "platform": "Console"}, "2140881240": {"name": "07: Silk Shoes (AR 54-106)", "category": "Boots", "platform": "Console"}, "2140881241": {"name": "08: Brogans (AR 107-129)", "category": "Boots", "platform": "Console"}, "2140881242": {"name": "09: Treads (AR 130-152)", "category": "Boots", "platform": "Console"}, "2140881243": {"name": "10: Heavy Sabatons (AR 154-174)", "category": "Boots", "platform": "Console"}, "2140881244": {"name": "11: Battle Greaves (AR 175-192)", "category": "Boots", "platform": "Console"}, "2140882329": {"name": "12: Balor Treads (AR 192-209)", "category": "Boots", "platform": "Console"}, "2140882330": {"name": "13: Astral Greaves (AR 210-221)", "category": "Boots", "platform": "Console"}, "2140882331": {"name": "14: Warlord Boots (AR 221-249)", "category": "Boots", "platform": "Console"}, "2140882332": {"name": "15: Doom Treads (AR 250-278)", "category": "Boots", "platform": "Console"}, "2140882333": {"name": "16: Sovereign Greaves (AR 280-308)", "category": "Boots", "platform": "Console"}, "2140882334": {"name": "17: Archon Greaves (AR 309-366)", "category": "Boots", "platform": "Console"}, "2140882335": {"name": "18: Rakkisgard Greaves (AR 367-512)", "category": "Boots", "platform": "Console"}, "2140882336": {"name": "19: Ascended Greaves (AR 513-590)", "category": "Boots", "platform": "Console"}, "931997596": {"name": "Art Test Boots 1", "category": "Boots", "platform": "Console"}, "931997597": {"name": "Art Test Boots 2", "category": "Boots", "platform": "Console"}, "931997598": {"name": "Art Test Boots 3", "category": "Boots", "platform": "Console"}, "931997599": {"name": "Art Test Boots 4", "category": "Boots", "platform": "Console"}, "931997600": {"name": "Art Test Boots 5", "category": "Boots", "platform": "Console"}, "691149644": {"name": "Art_Test_Boots_10 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997601": {"name": "Art_Test_Boots_6 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997602": {"name": "Art_Test_Boots_7 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997603": {"name": "Art_Test_Boots_8 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997604": {"name": "Art_Test_Boots_9 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940245561": {"name": "Legendary: Board Walkers", "category": "Boots", "platform": "Console"}, "1940101813": {"name": "Legendary: Boj Anglers", "category": "Boots", "platform": "Console"}, "-401226911": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "-401224467": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "261789197": {"name": "Legendary: Boj Anglers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979273143": {"name": "Legendary: Boots of Disregard", "category": "Boots", "platform": "Console"}, "1290781938": {"name": "Legendary: Conqueror's Sabatons (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1940317435": {"name": "Legendary: Fire Walkers", "category": "Boots", "platform": "Console"}, "-394111385": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "-394108941": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "261789203": {"name": "Legendary: Fire Walkers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-639326280": {"name": "Legendary: Footfalls of the Forbidden Lands", "category": "Boots", "platform": "Console"}, "1940353372": {"name": "Legendary: Ice Climbers", "category": "Boots", "platform": "Console"}, "-392925464": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "-392923020": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "261789204": {"name": "Legendary: Ice Climbers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979309080": {"name": "Legendary: Illusory Boots", "category": "Boots", "platform": "Console"}, "1979345017": {"name": "Legendary: Irontoe Mudsputters", "category": "Boots", "platform": "Console"}, "-396483227": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "-396480783": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "261789201": {"name": "Legendary: Lost Boys (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1940389309": {"name": "Legendary: Lut Socks", "category": "Boots", "platform": "Console"}, "-391739543": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "-391737099": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "261789205": {"name": "Legendary: Lut Socks (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941251797": {"name": "Legendary: The Crudest Boots", "category": "Boots", "platform": "Console"}, "-363277439": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "-363274995": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "261789229": {"name": "Legendary: The Crudest Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-2143372979": {"name": "Legendary: The Crudest Boots (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1941395545": {"name": "Set: Asheara's Finders", "category": "Boots", "platform": "Console"}, "261789233": {"name": "Set: Asheara's Lock (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-358533755": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "-358531311": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "261789238": {"name": "Set: Blackthorne's Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941575230": {"name": "Set: Blackthorne's Spurs", "category": "Boots", "platform": "Console"}, "-352604150": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-352601706": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-357347834": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "-357345390": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "261789234": {"name": "Set: Cain's Slippers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941431482": {"name": "Set: Cain's Travelers", "category": "Boots", "platform": "Console"}, "261789236": {"name": "Set: Captain Crimson's Deck Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941503356": {"name": "Set: Captain Crimson's Waders", "category": "Boots", "platform": "Console"}, "-354975992": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-354973548": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-801833428": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801653481": {"name": "Set: Eight-Demon Boots", "category": "Boots", "platform": "Console"}, "-801725355": {"name": "Set: Firebird's Tarsi", "category": "Boots", "platform": "Console"}, "-801833429": {"name": "Set: Hell Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800539434": {"name": "Set: Helltooth Greaves", "category": "Boots", "platform": "Console"}, "261789231": {"name": "Set: Immortal King's Pillar (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941323671": {"name": "Set: Immortal King's Stride", "category": "Boots", "platform": "Console"}, "-360905597": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "-360903153": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "1097296767": {"name": "Set: Inna's Sandals (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801617544": {"name": "Set: Jade Harvester's Swiftness", "category": "Boots", "platform": "Console"}, "-801689418": {"name": "Set: Marauder's Treads", "category": "Boots", "platform": "Console"}, "-801905302": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1941287734": {"name": "Set: Natalya's Bloody Footprints", "category": "Boots", "platform": "Console"}, "-362091518": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "-362089074": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "261789230": {"name": "Set: Natalya's Soul (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1097296766": {"name": "Set: Nilfur's Boast (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801761292": {"name": "Set: Raekor's Striders", "category": "Boots", "platform": "Console"}, "-801905304": {"name": "Set: Roland's Stride (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "-801905303": {"name": "Set: Sabaton of the Wastes (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800755056": {"name": "Set: Sabatons of Akkhan", "category": "Boots", "platform": "Console"}, "-353790071": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "-353787627": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "1941539293": {"name": "Set: Sage's Passage", "category": "Boots", "platform": "Console"}, "261789237": {"name": "Set: Sage's Seekers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-1957807619": {"name": "Set: Striders of Destiny (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800611308": {"name": "Set: The Shadow's Heels", "category": "Boots", "platform": "Console"}, "-800647245": {"name": "Set: Vyr's Swaggering Stance", "category": "Boots", "platform": "Console"}, "-801869365": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "261789232": {"name": "Set: Zunimassa's Journey (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941359608": {"name": "Set: Zunimassa's Trail", "category": "Boots", "platform": "Console"}, "-359719676": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "-359717232": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "1979344754": {"name": "legendary: Boots_104_p2 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940317172": {"name": "legendary: Fire Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800575371": {"name": "legendary: Seismic Treads", "category": "Boots", "platform": "Console"}, "-700134034": {"name": "legendary: Seismic Treads (Patch 2.2.0)", "category": "Boots", "platform": "Console"}}, "Bows": {"-2091504071": {"name": "02: Warden Bow (DPS 14.7-16.8)", "category": "Bows", "platform": "Console"}, "-2091504070": {"name": "03: Long Bow (DPS 20.3-22.4)", "category": "Bows", "platform": "Console"}, "-2091504069": {"name": "04: Recurve Bow (DPS 27.7-30.8)", "category": "Bows", "platform": "Console"}, "-2091504068": {"name": "05: Hunting Bow (DPS 34.3-36.4)", "category": "Bows", "platform": "Console"}, "-2091504067": {"name": "06: Battle Bow (DPS 41.3-43.4)", "category": "Bows", "platform": "Console"}, "-2091502983": {"name": "07: Siege Bow (DPS 44.1-46.2)", "category": "Bows", "platform": "Console"}, "-2091502982": {"name": "08: Maruki (DPS 55.3-57.4)", "category": "Bows", "platform": "Console"}, "-2091502981": {"name": "09: Yumi (DPS 64.4-66.5)", "category": "Bows", "platform": "Console"}, "-2091502980": {"name": "10: Composite Bow (DPS 749.9-77.0)", "category": "Bows", "platform": "Console"}, "-2091502979": {"name": "11: Daikyu (DPS 91.0-93.1)", "category": "Bows", "platform": "Console"}, "-2091502978": {"name": "12: Hankyu (DPS 107.1-109.2)", "category": "Bows", "platform": "Console"}, "-2091501894": {"name": "13: Higoyumi (DPS 140.7-142.8)", "category": "Bows", "platform": "Console"}, "-2091501893": {"name": "14: Ranger Bow (DPS 172.2-174.3)", "category": "Bows", "platform": "Console"}, "-2091501892": {"name": "15: Longshot Bow (DPS 207.2-211.4)", "category": "Bows", "platform": "Console"}, "-2091501891": {"name": "16: Sniper Bow (DPS 275.1-279.3)", "category": "Bows", "platform": "Console"}, "-2091501890": {"name": "17: Phantom Bow (DPS 322.0-326.2)", "category": "Bows", "platform": "Console"}, "-2091501889": {"name": "18: Revenant Bow (DPS 376.6-380.8)", "category": "Bows", "platform": "Console"}, "-2091500805": {"name": "19: Twinbow (DPS 513.1-517.3)", "category": "Bows", "platform": "Console"}, "-2091500804": {"name": "20: Doubleshot (DPS 670.6-674.8)", "category": "Bows", "platform": "Console"}, "687111997": {"name": "Art Test Bow 1", "category": "Bows", "platform": "Console"}, "687111998": {"name": "Art Test Bow 2", "category": "Bows", "platform": "Console"}, "687111999": {"name": "Art Test Bow 3", "category": "Bows", "platform": "Console"}, "687112000": {"name": "Art Test Bow 4", "category": "Bows", "platform": "Console"}, "687112001": {"name": "Art Test Bow 5", "category": "Bows", "platform": "Console"}, "1999703162": {"name": "Legendary: Amazonian Arch", "category": "Bows", "platform": "Console"}, "1142135055": {"name": "Legendary: Bow of the Lost Warlord (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1961789627": {"name": "Legendary: Cluckeye", "category": "Bows", "platform": "Console"}, "314470951": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "314473395": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "513724883": {"name": "Legendary: Cluckeye (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459958": {"name": "Legendary: Etrayu", "category": "Bows", "platform": "Console"}, "270591874": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "270594318": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "513724846": {"name": "Legendary: Etrayu (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459694": {"name": "Legendary: Etrayu (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1999595351": {"name": "Legendary: Kridershot", "category": "Bows", "platform": "Console"}, "1999667225": {"name": "Legendary: Leonine Bow of Hashir", "category": "Bows", "platform": "Console"}, "277707400": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "277709844": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "513724852": {"name": "Legendary: Longshot (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1999631288": {"name": "Legendary: Odyssey's End", "category": "Bows", "platform": "Console"}, "1961609942": {"name": "Legendary: Sydyru Crust", "category": "Bows", "platform": "Console"}, "1960711517": {"name": "Legendary: The Raven's Wing", "category": "Bows", "platform": "Console"}, "278893321": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "278895765": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "513724853": {"name": "Legendary: The Raven's Wing (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960675580": {"name": "Legendary: Unbound Bolt", "category": "Bows", "platform": "Console"}, "1960603706": {"name": "Legendary: Uskang", "category": "Bows", "platform": "Console"}, "275335558": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "275338002": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "513724850": {"name": "Legendary: Uskang (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960603442": {"name": "Legendary: Uskang (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "308541346": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "308543790": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "513724878": {"name": "Legendary: Venomhusk (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960747454": {"name": "Legendary: Windforce", "category": "Bows", "platform": "Console"}, "280079242": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "280081686": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "513724854": {"name": "Legendary: Windforce (Old-Legacy)", "category": "Bows", "platform": "Console"}}, "Bracers": {"-875944877": {"name": "02: Leather Cuffs (AR 16-19)", "category": "Bracers", "platform": "Console"}, "-875944876": {"name": "03: Bindings (AR 25-32)", "category": "Bracers", "platform": "Console"}, "-875944875": {"name": "04: Vambraces (AR 33-40)", "category": "Bracers", "platform": "Console"}, "-875944874": {"name": "05: Bracelets (AR 41-48)", "category": "Bracers", "platform": "Console"}, "-875943789": {"name": "067: Wristwraps (AR 63-75)", "category": "Bracers", "platform": "Console"}, "-875944873": {"name": "06: Mail Bands (AR 50-62)", "category": "Bracers", "platform": "Console"}, "-875943788": {"name": "08: Wristbands (AR 76-88)", "category": "Bracers", "platform": "Console"}, "-875943787": {"name": "09: Stabilizers (AR 90-102)", "category": "Bracers", "platform": "Console"}, "-875943786": {"name": "10: Wristguards (AR 103-124)", "category": "Bracers", "platform": "Console"}, "-875943785": {"name": "11: Wristplates (AR 125-137)", "category": "Bracers", "platform": "Console"}, "-875942700": {"name": "12: Armwraps (AR 137-149)", "category": "Bracers", "platform": "Console"}, "-875942699": {"name": "13: Armbands (AR 150-157)", "category": "Bracers", "platform": "Console"}, "-875942698": {"name": "14: Warbands (AR 158-178)", "category": "Bracers", "platform": "Console"}, "-875942697": {"name": "15: Armguards (AR 179-199)", "category": "Bracers", "platform": "Console"}, "-875942696": {"name": "16: Armplates (AR 200-220)", "category": "Bracers", "platform": "Console"}, "-875942695": {"name": "17: Razorspikes (AR 220-261)", "category": "Bracers", "platform": "Console"}, "-875942694": {"name": "18: Rakkisgard Bracelets (AR 262-365)", "category": "Bracers", "platform": "Console"}, "-875942693": {"name": "19: Ascended Bracers (AR 366-421)", "category": "Bracers", "platform": "Console"}, "-297950812": {"name": "Art Test Bracer 1", "category": "Bracers", "platform": "Console"}, "-297950811": {"name": "Art Test Bracer 2", "category": "Bracers", "platform": "Console"}, "-297950810": {"name": "Art Test Bracer 3", "category": "Bracers", "platform": "Console"}, "-297950809": {"name": "Art Test Bracer 4", "category": "Bracers", "platform": "Console"}, "-297950808": {"name": "Art Test Bracer 5", "category": "Bracers", "platform": "Console"}, "1861699995": {"name": "Grundo Gear (Patch 2.1.2)", "category": "Bracers", "platform": "Console"}, "962282719": {"name": "Legendary: Ancient Parthan Defenders", "category": "Bracers", "platform": "Console"}, "962462404": {"name": "Legendary: Custerian Wristguards", "category": "Bracers", "platform": "Console"}, "923291074": {"name": "Legendary: Gungdo Gear", "category": "Bracers", "platform": "Console"}, "403757070": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "403759514": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "955538490": {"name": "Legendary: Gungdo Gear (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923111389": {"name": "Legendary: Kethryes' Splint", "category": "Bracers", "platform": "Console"}, "923255137": {"name": "Legendary: Lacuni Prowlers", "category": "Bracers", "platform": "Console"}, "402571149": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "402573593": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538489": {"name": "Legendary: Lacuni Prowlers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962498341": {"name": "Legendary: Lucky Bowman's Armscales", "category": "Bracers", "platform": "Console"}, "962426467": {"name": "Legendary: Nemesis Bracers", "category": "Bracers", "platform": "Console"}, "923147326": {"name": "Legendary: Promise of Glory", "category": "Bracers", "platform": "Console"}, "399013386": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "399015830": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "955538486": {"name": "Legendary: Promise of Glory (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962318656": {"name": "Legendary: Reaper's Wraps", "category": "Bracers", "platform": "Console"}, "962390530": {"name": "Legendary: Sanguinary Vambraces", "category": "Bracers", "platform": "Console"}, "923183263": {"name": "Legendary: Slave Bonds", "category": "Bracers", "platform": "Console"}, "400199307": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "400201751": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "955538487": {"name": "Legendary: Slave Bonds (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923219200": {"name": "Legendary: Steady Strikers", "category": "Bracers", "platform": "Console"}, "401385228": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "401387672": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538488": {"name": "Legendary: Steady Strikers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923327011": {"name": "Legendary: Strongarm Bracers", "category": "Bracers", "platform": "Console"}, "404942991": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "404945435": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538491": {"name": "Legendary: Strongarm Bracers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962354593": {"name": "Legendary: Trag'Oul Coils", "category": "Bracers", "platform": "Console"}, "962246782": {"name": "Legendary: Warzechian Armguards", "category": "Bracers", "platform": "Console"}, "397827465": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "397829909": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "955538485": {"name": "Legendary: Wondrous Deflectors (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "955538493": {"name": "Set: Aughild's Demands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923398885": {"name": "Set: Aughild's Search", "category": "Bracers", "platform": "Console"}, "407314833": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "407317277": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "924297310": {"name": "Set: Demon's Animus", "category": "Bracers", "platform": "Console"}, "955538518": {"name": "Set: Demon's Manacles (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "436962858": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "436965302": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "924261373": {"name": "Set: Guardian's Aversion", "category": "Bracers", "platform": "Console"}, "955538517": {"name": "Set: Guardian's Bands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "435776937": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "435779381": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "1784952569": {"name": "Set: Krelm's Buff Bracers", "category": "Bracers", "platform": "Console"}, "1786138490": {"name": "Set: Shackles of the Invoker", "category": "Bracers", "platform": "Console"}, "1861701111": {"name": "legendary: Drakon's Lesson (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861699992": {"name": "legendary: Mortick's Brace (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861701087": {"name": "legendary: Spirit Guards (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}}, "Ceremonial Knives": {"-635269583": {"name": "01: Stone Knife (DPS 11.2-12.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269582": {"name": "02: Kris Blade (DPS 14.7-16.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269581": {"name": "03: Jagged Edge (DPS 21.0-23.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269580": {"name": "04: Flint Knife (DPS 30.8-32.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268494": {"name": "05: Sacrifice Blade (DPS 39.2-41.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268493": {"name": "06: Flayer (DPS 48.3-50.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268492": {"name": "07: Bone Saw (DPS 62.3-64.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268491": {"name": "08: Beast Tusk (DPS 84.0-86.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267405": {"name": "09: Scalping Razor (DPS 112.7-114.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267404": {"name": "10: Obsidian Edge (DPS 137.2-139.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267403": {"name": "11: Skin Cutter (DPS 165.2-169.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267402": {"name": "12: Exquisite Knife (DPS 190.4-194.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267401": {"name": "13: Flesh Ripper (DPS 219.1-223.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267400": {"name": "14: Veil Piercer (DPS 251.3-257.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266316": {"name": "15: Odsidian Skiver (DPS 336.7-340.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266315": {"name": "16: Tecpat1 (DPS 410.2-414.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-97045282": {"name": "Art Test CeremonialDagger 1", "category": "Ceremonial Knives", "platform": "Console"}, "-97045281": {"name": "Art Test CeremonialDagger 2", "category": "Ceremonial Knives", "platform": "Console"}, "-97045280": {"name": "Art Test CeremonialDagger 3", "category": "Ceremonial Knives", "platform": "Console"}, "-97045279": {"name": "Art Test CeremonialDagger 4", "category": "Ceremonial Knives", "platform": "Console"}, "-97045278": {"name": "Art Test CeremonialDagger 5", "category": "Ceremonial Knives", "platform": "Console"}, "1784443031": {"name": "Legendary: Anessazi Edge", "category": "Ceremonial Knives", "platform": "Console"}, "-1242999421": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1242996977": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684207": {"name": "Legendary: Anessazi Edge (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784514905": {"name": "Legendary: Deadly Rebirth", "category": "Ceremonial Knives", "platform": "Console"}, "1784694590": {"name": "Legendary: Last Breath", "category": "Ceremonial Knives", "platform": "Console"}, "-1234697974": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1234695530": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684214": {"name": "Legendary: Last Breath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784622716": {"name": "Legendary: Living Umbral Oath", "category": "Ceremonial Knives", "platform": "Console"}, "-1240627579": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1240625135": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684209": {"name": "Legendary: Moon Slayer (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1823614361": {"name": "Legendary: Rhen'ho Flayer", "category": "Ceremonial Knives", "platform": "Console"}, "916911834": {"name": "Legendary: Sacred Harvester (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "595814643": {"name": "Legendary: Sacrificer", "category": "Ceremonial Knives", "platform": "Console"}, "1823578424": {"name": "Legendary: Starmetal Kukri", "category": "Ceremonial Knives", "platform": "Console"}, "916911835": {"name": "Legendary: The Dagger of Darts (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "1784478968": {"name": "Legendary: The Gidbinn", "category": "Ceremonial Knives", "platform": "Console"}, "-1241813500": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1241811056": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684208": {"name": "Legendary: The Gidbinn (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784550842": {"name": "Legendary: The Spider Queen's Grasp", "category": "Ceremonial Knives", "platform": "Console"}, "-1237069816": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1237067372": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684212": {"name": "Legendary: Umbral Oath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239441658": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239439214": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684210": {"name": "Legendary: Ziggurat Tooth (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684240": {"name": "Set: Hallowed Sacrifice (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203864028": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203861584": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1785628952": {"name": "Set: Hallowed Sufferance", "category": "Ceremonial Knives", "platform": "Console"}, "1784730527": {"name": "Set: Manajuma's Carving Knife", "category": "Ceremonial Knives", "platform": "Console"}, "-1233512053": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1233509609": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684215": {"name": "Set: Manajuma's Ritual Cutter (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}}, "Chest": {"258855260": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783385": {"name": "Set: Cuirass of the Wastes (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819322": {"name": "Set: Harness of Truth (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783386": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "259969569": {"name": "Set: Sunwuko's Soul (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819323": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}}, "Chest Armor": {"1612257705": {"name": "02: Leather Doublet (AR 18-21)", "category": "Chest Armor", "platform": "Console"}, "1612257706": {"name": "03: Brigandine Coat (AR 33-38)", "category": "Chest Armor", "platform": "Console"}, "1612257707": {"name": "04: Chain Mail (AR 51-68)", "category": "Chest Armor", "platform": "Console"}, "1612257708": {"name": "05: Splint Cuirass (AR 69-86)", "category": "Chest Armor", "platform": "Console"}, "1612257709": {"name": "06: Plate Mail (AR 87-107)", "category": "Chest Armor", "platform": "Console"}, "1612258793": {"name": "07: Stygian Harness (AR 108-137)", "category": "Chest Armor", "platform": "Console"}, "1612258794": {"name": "08: Etched Jacket (AR 138-167)", "category": "Chest Armor", "platform": "Console"}, "1612258795": {"name": "09: Jazeraint Mail (AR 168-197)", "category": "Chest Armor", "platform": "Console"}, "1612258796": {"name": "10: Battle Armor (AR 198-224)", "category": "Chest Armor", "platform": "Console"}, "1612258797": {"name": "11: Boneweave Hauberk (AR 225-247)", "category": "Chest Armor", "platform": "Console"}, "1612259882": {"name": "12: Balor Armor (AR 247-269)", "category": "Chest Armor", "platform": "Console"}, "1612259883": {"name": "13: Astral Mail (AR 270-284)", "category": "Chest Armor", "platform": "Console"}, "1612259884": {"name": "14: Warlord Plate (AR 285-322)", "category": "Chest Armor", "platform": "Console"}, "1612259885": {"name": "15: Doom Armor (AR 322-359)", "category": "Chest Armor", "platform": "Console"}, "1612259886": {"name": "16: Sovereign Mail (AR 360-397)", "category": "Chest Armor", "platform": "Console"}, "1612259887": {"name": "17: Archon Armor (AR 397-471)", "category": "Chest Armor", "platform": "Console"}, "1612259888": {"name": "18: Rakkisgard Armor (AR 472-659)", "category": "Chest Armor", "platform": "Console"}, "1612259889": {"name": "19: Ascended Armor (AR 660-759)", "category": "Chest Armor", "platform": "Console"}, "1937623756": {"name": "Art Test Chest 1", "category": "Chest Armor", "platform": "Console"}, "1937623757": {"name": "Art Test Chest 2", "category": "Chest Armor", "platform": "Console"}, "1937623758": {"name": "Art Test Chest 3", "category": "Chest Armor", "platform": "Console"}, "1937623759": {"name": "Art Test Chest 4", "category": "Chest Armor", "platform": "Console"}, "1937623760": {"name": "Art Test Chest 5", "category": "Chest Armor", "platform": "Console"}, "1316774087": {"name": "Legendary: Aquila Cuirass", "category": "Chest Armor", "platform": "Console"}, "503794611": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "503797055": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016991": {"name": "Legendary: Aquila Cuirass (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354723559": {"name": "Legendary: Armor of the Kind Regent", "category": "Chest Armor", "platform": "Console"}, "1316702213": {"name": "Legendary: Chaingmail", "category": "Chest Armor", "platform": "Console"}, "501422769": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "501425213": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016989": {"name": "Legendary: Chaingmail (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1315731914": {"name": "Legendary: Cindercoat", "category": "Chest Armor", "platform": "Console"}, "469402902": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "469405346": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016962": {"name": "Legendary: Cindercoat (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "883162595": {"name": "Legendary: Conqueror's Cuirass (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "1315552229": {"name": "Legendary: Goldskin", "category": "Chest Armor", "platform": "Console"}, "463473297": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "463475741": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016957": {"name": "Legendary: Goldskin (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316989709": {"name": "Legendary: Heart of Iron", "category": "Chest Armor", "platform": "Console"}, "510910137": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "510912581": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016997": {"name": "Legendary: Heart of Iron (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1821181577": {"name": "Legendary: Heart of the Titans", "category": "Chest Armor", "platform": "Console"}, "1317025646": {"name": "Legendary: Mantle of the Rydraelm", "category": "Chest Armor", "platform": "Console"}, "512096058": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "512098502": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016998": {"name": "Legendary: Robes of the Rydraelm (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354687622": {"name": "Legendary: Shi Mizu's Haori", "category": "Chest Armor", "platform": "Console"}, "1315588166": {"name": "Legendary: Tyrael's Might", "category": "Chest Armor", "platform": "Console"}, "464659218": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "464661662": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016958": {"name": "Legendary: Tyrael's Might (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "547673688": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "547676132": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318103756": {"name": "Set: Aughild's Rule", "category": "Chest Armor", "platform": "Console"}, "172017028": {"name": "Set: Aughild's Vestments (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1262779559": {"name": "Set: Blackthorne's Jacket (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "-115330289": {"name": "Set: Blackthorne's Surcoat", "category": "Chest Armor", "platform": "Console"}, "488990459": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "488992903": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172017027": {"name": "Set: Born's Carapace (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318067819": {"name": "Set: Born's Frozen Soul", "category": "Chest Armor", "platform": "Console"}, "546487767": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "546490211": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259933632": {"name": "Set: Breastplate of Akkhan", "category": "Chest Armor", "platform": "Console"}, "172017029": {"name": "Set: Demon's Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "548859609": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "548862053": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318139693": {"name": "Set: Demon's Marrow", "category": "Chest Armor", "platform": "Console"}, "258963333": {"name": "Set: Firebird's Breast", "category": "Chest Armor", "platform": "Console"}, "259035207": {"name": "Set: Heart of the Crashing Wave", "category": "Chest Armor", "platform": "Console"}, "260149254": {"name": "Set: Helltooth Tunic", "category": "Chest Armor", "platform": "Console"}, "1316810024": {"name": "Set: Immortal King's Eternal Reign", "category": "Chest Armor", "platform": "Console"}, "504980532": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "504982976": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016992": {"name": "Set: Immortal King's Soul Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016994": {"name": "Set: Inna's Refuge (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316881898": {"name": "Set: Inna's Vast Expanse", "category": "Chest Armor", "platform": "Console"}, "507352374": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "507354818": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259071144": {"name": "Set: Jade Harvester's Peace", "category": "Chest Armor", "platform": "Console"}, "258999270": {"name": "Set: Marauder's Carapace", "category": "Chest Armor", "platform": "Console"}, "258927396": {"name": "Set: Raekor's Heart", "category": "Chest Armor", "platform": "Console"}, "258783384": {"name": "Set: Roland's Bearing (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "172016993": {"name": "Set: Tal Rasha's Guardianship (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316845961": {"name": "Set: Tal Rasha's Relentless Pursuit", "category": "Chest Armor", "platform": "Console"}, "506166453": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "506168897": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "260077380": {"name": "Set: The Shadow's Bane", "category": "Chest Armor", "platform": "Console"}, "260041443": {"name": "Set: Vyr's Astonishing Aura", "category": "Chest Armor", "platform": "Console"}, "1316917835": {"name": "Set: Zunimassa's Marrow", "category": "Chest Armor", "platform": "Console"}, "508538295": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "508540739": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016995": {"name": "Set: Zunimassa's Vessel (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}}, "Chests": {"1937623762": {"name": "Art_Test_Chest_7 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623763": {"name": "Art_Test_Chest_8 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623764": {"name": "Art_Test_Chest_9 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}}, "Cloaks": {"40855419": {"name": "02: Shroud (AR 36-41)", "category": "Cloaks", "platform": "Console"}, "40855420": {"name": "03: Cape (AR 60-69)", "category": "Cloaks", "platform": "Console"}, "40855421": {"name": "04: Tabard (AR 84-113)", "category": "Cloaks", "platform": "Console"}, "40856507": {"name": "05: Wrap (AR 114-149)", "category": "Cloaks", "platform": "Console"}, "40856508": {"name": "06: Lurker Shroud (AR 150-185)", "category": "Cloaks", "platform": "Console"}, "40856509": {"name": "07: Talma (AR 186-232)", "category": "Cloaks", "platform": "Console"}, "40856510": {"name": "08: Cardinal (AR 232-254)", "category": "Cloaks", "platform": "Console"}, "40857596": {"name": "09: Veteran Cloak (AR 255-284)", "category": "Cloaks", "platform": "Console"}, "40857597": {"name": "10: Death Shroud (AR 385-322)", "category": "Cloaks", "platform": "Console"}, "40857598": {"name": "11: Stalker Cape (AR 322-359)", "category": "Cloaks", "platform": "Console"}, "40857599": {"name": "12: Dread Cloak (AR 360-472)", "category": "Cloaks", "platform": "Console"}, "40857600": {"name": "13: Rakkisgard Cloak (AR 472-659)", "category": "Cloaks", "platform": "Console"}, "40857601": {"name": "14: Ascended Cloak (AR 660-759)", "category": "Cloaks", "platform": "Console"}, "2105367871": {"name": "Art Test Cloak 1", "category": "Cloaks", "platform": "Console"}, "2105367872": {"name": "Art Test Cloak 2", "category": "Cloaks", "platform": "Console"}, "2105367873": {"name": "Art Test Cloak 3", "category": "Cloaks", "platform": "Console"}, "2105367874": {"name": "Art Test Cloak 4", "category": "Cloaks", "platform": "Console"}, "2105367875": {"name": "Art Test Cloak 5", "category": "Cloaks", "platform": "Console"}, "221665681": {"name": "Legendary Cloak 002 p1", "category": "Cloaks", "platform": "Console"}, "221773756": {"name": "Legendary: Beckon Sail", "category": "Cloaks", "platform": "Console"}, "-1271477944": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1271475500": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235532": {"name": "Legendary: Beckon Sail (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260765401": {"name": "Legendary: Blackfeather", "category": "Cloaks", "platform": "Console"}, "221630008": {"name": "Legendary: Cape of the Dark Night", "category": "Cloaks", "platform": "Console"}, "-1276221628": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1276219184": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235536": {"name": "Legendary: Cape of the Dark Night (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260801338": {"name": "Legendary: Cloak of Deception", "category": "Cloaks", "platform": "Console"}, "221665945": {"name": "Legendary: The Cloak of the Garwulf", "category": "Cloaks", "platform": "Console"}, "-1275035707": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1275033263": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235535": {"name": "Legendary: The Inquisitor (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "221809693": {"name": "Set: Natalya's Embrace", "category": "Cloaks", "platform": "Console"}, "-1270292023": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1270289579": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235531": {"name": "Set: Natalya's Shadow (Old-Legacy)", "category": "Cloaks", "platform": "Console"}}, "Consumables": {"-1691237125": {"name": "Blood Shard", "category": "Consumables", "platform": "Console"}, "-2018707791": {"name": "Bottomless Potion Of Fear (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-2018707790": {"name": "Bottomless Potion of Amplification (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707793": {"name": "Bottomless Potion of Kulle Aid", "category": "Consumables", "platform": "Console"}, "-2018707794": {"name": "Bottomless Potion of Mutilation", "category": "Consumables", "platform": "Console"}, "-2018707796": {"name": "Bottomless Potion of Regeneration", "category": "Consumables", "platform": "Console"}, "-2018707792": {"name": "Bottomless Potion of Rejuvenation", "category": "Consumables", "platform": "Console"}, "510979313": {"name": "Bottomless Potion of Rejuvenation (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707797": {"name": "Bottomless Potion of the Diamond", "category": "Consumables", "platform": "Console"}, "-2018707795": {"name": "Bottomless Potion of the Leech", "category": "Consumables", "platform": "Console"}, "-2018707798": {"name": "Bottomless Potion of the Tower", "category": "Consumables", "platform": "Console"}, "727989467": {"name": "Bottomless Regular Health Potion (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618072": {"name": "Consumable_Potion_Bloodshard_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "736462346": {"name": "Consumable_Potion_Bloodshard_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618138": {"name": "Consumable_Potion_Bloodshard_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618270": {"name": "Consumable_Potion_Bloodshard_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764252": {"name": "Consumable_Potion_Gold_Find_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-418681010": {"name": "Consumable_Potion_Gold_Find_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764318": {"name": "Consumable_Potion_Gold_Find_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764450": {"name": "Consumable_Potion_Gold_Find_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167362": {"name": "Consumable_Potion_XP_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1032379504": {"name": "Consumable_Potion_XP_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167296": {"name": "Consumable_Potion_XP_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167164": {"name": "Consumable_Potion_XP_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2142362846": {"name": "Health Potion", "category": "Consumables", "platform": "Console"}, "-650776931": {"name": "Infernal Machine", "category": "Consumables", "platform": "Console"}, "1054965529": {"name": "Infernal Machine of Bones", "category": "Consumables", "platform": "Console"}, "1458185494": {"name": "Infernal Machine of Evil", "category": "Consumables", "platform": "Console"}, "-1506243402": {"name": "Infernal Machine of Gluttony", "category": "Consumables", "platform": "Console"}, "-1672611564": {"name": "Infernal Machine of War", "category": "Consumables", "platform": "Console"}, "-1055802742": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1927699898": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-1990624170": {"name": "PowerGlobe", "category": "Consumables", "platform": "Console"}, "-1407876474": {"name": "PowerGlobe NoFlippy", "category": "Consumables", "platform": "Console"}, "1604670149": {"name": "PowerGlobe v2 x1", "category": "Consumables", "platform": "Console"}, "1554449877": {"name": "PowerGlobe v2 x1 NoFlippy", "category": "Consumables", "platform": "Console"}, "-767886865": {"name": "PvP_HealingDude", "category": "Consumables", "platform": "Console"}, "1844495708": {"name": "Ramaladni's Gift", "category": "Consumables", "platform": "Console"}, "-2108322324": {"name": "Ramaladni's Gift (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-1629755675": {"name": "Rare Gift (RoS)", "category": "Consumables", "platform": "Console"}, "750709043": {"name": "ShrineGlobe Blessed", "category": "Consumables", "platform": "Console"}, "-783958152": {"name": "ShrineGlobe Enlightened", "category": "Consumables", "platform": "Console"}, "1754475188": {"name": "ShrineGlobe Fortune", "category": "Consumables", "platform": "Console"}, "1126841672": {"name": "ShrineGlobe Frenzied", "category": "Consumables", "platform": "Console"}, "-1436918535": {"name": "Steak10", "category": "Consumables", "platform": "Console"}, "-1436918530": {"name": "Steak15", "category": "Consumables", "platform": "Console"}, "-1436918502": {"name": "Steak20", "category": "Consumables", "platform": "Console"}, "-1436918497": {"name": "Steak25", "category": "Consumables", "platform": "Console"}, "-1436918469": {"name": "Steak30", "category": "Consumables", "platform": "Console"}, "-1436918464": {"name": "Steak35", "category": "Consumables", "platform": "Console"}, "-1436918436": {"name": "Steak40", "category": "Consumables", "platform": "Console"}, "346908589": {"name": "Steak5", "category": "Consumables", "platform": "Console"}, "450956006": {"name": "p1 tiered rifts Orb", "category": "Consumables", "platform": "Console"}}, "Cosmetics": {"703352254": {"name": "Art_Test_Pet_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352255": {"name": "Art_Test_Pet_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352256": {"name": "Art_Test_Pet_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352257": {"name": "Art_Test_Pet_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352258": {"name": "Art_Test_Pet_5 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352259": {"name": "Art_Test_Pet_6 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555709": {"name": "Art_Test_Wings_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555710": {"name": "Art_Test_Wings_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555711": {"name": "Art_Test_Wings_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555712": {"name": "Art_Test_Wings_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1736870778": {"name": "Blade Wings", "category": "Cosmetics", "platform": "Console"}, "2015178386": {"name": "Blade Wings (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508877": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508876": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "988742338": {"name": "Cosmetic_Pet_FallenHound_Skeletal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508875": {"name": "Cosmetic_Pet_teddyBear_04 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1464439640": {"name": "Cosmetic_Wings_Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834901": {"name": "Cosmetic_Wings_bat_02 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834902": {"name": "Cosmetic_Wings_bat_03 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1424453175": {"name": "Crimson Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "1464422100": {"name": "Demon Soaring (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208405024": {"name": "Eldritch Embrace (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1081301157": {"name": "Eternal Flame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1030142027": {"name": "Eternal Light (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1815774861": {"name": "Fingers of Terror (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380235": {"name": "Frame: Angelic (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264991": {"name": "Frame: Base Frame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380233": {"name": "Frame: Bone (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380234": {"name": "Frame: Deathshead (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380230": {"name": "Frame: Molton (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264990": {"name": "Frame: Paragon 1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764818": {"name": "Frame: Paragon 10 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114304450": {"name": "Frame: Paragon 100 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764851": {"name": "Frame: Paragon 20 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114305539": {"name": "Frame: Paragon 200 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764884": {"name": "Frame: Paragon 30 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764917": {"name": "Frame: Paragon 40 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114307717": {"name": "Frame: Paragon 400 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764950": {"name": "Frame: Paragon 50 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114308806": {"name": "Frame: Paragon 500 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764983": {"name": "Frame: Paragon 60 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114309895": {"name": "Frame: Paragon 600 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765016": {"name": "Frame: Paragon 70 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114310984": {"name": "Frame: Paragon 700 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765049": {"name": "Frame: Paragon 80 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114312073": {"name": "Frame: Paragon 800 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765082": {"name": "Frame: Paragon 90 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114306628": {"name": "Frame: Paraogn 300 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380199": {"name": "Frame: Season 3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380228": {"name": "Frame: Staind Glass Azure (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380202": {"name": "Frame: Staind Glass Orange (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380201": {"name": "Frame: Staind Glass Purple (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380227": {"name": "Frame: Staind Glass Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380229": {"name": "Frame: Staind Glass Teal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380203": {"name": "Frame: Staind Glass Yellow (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380231": {"name": "Frame: Steadfast (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380198": {"name": "Frame: Storm (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380232": {"name": "Frame: Thorns (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380200": {"name": "Frame: Whimseyshire (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "211305012": {"name": "Harbringer of Destruction (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "262300867": {"name": "Heaven't Might (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-922089455": {"name": "Knights of Westmarch (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1412314502": {"name": "Liber Canis Mortui", "category": "Cosmetics", "platform": "Console"}, "-1527508878": {"name": "Mr Bear (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208454467": {"name": "Pieces of Hatred (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "517654224": {"name": "Probe (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "291388174": {"name": "Spike (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1647814559": {"name": "Ten Pounder (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1454306710": {"name": "The Light of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-2072242152": {"name": "The Pillars of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-937743655": {"name": "Warlords Of Draenor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-762694428": {"name": "Warsong Pennant", "category": "Cosmetics", "platform": "Console"}, "-1364948604": {"name": "Wings of Valor", "category": "Cosmetics", "platform": "Console"}, "1464422747": {"name": "Wings of Valor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}}, "Crafting Components": {"-784029520": {"name": "Angelic Shard", "category": "Crafting Components", "platform": "Console"}, "-1585802162": {"name": "Arcane Dust", "category": "Crafting Components", "platform": "Console"}, "2048505008": {"name": "Behistun Rune", "category": "Crafting Components", "platform": "Console"}, "-1993550104": {"name": "Black Mushroom", "category": "Crafting Components", "platform": "Console"}, "1864276820": {"name": "Bloody Pincer", "category": "Crafting Components", "platform": "Console"}, "-875022940": {"name": "Born's Key", "category": "Crafting Components", "platform": "Console"}, "-229384987": {"name": "Captured Nightmare", "category": "Crafting Components", "platform": "Console"}, "1016443205": {"name": "Captured Soul", "category": "Crafting Components", "platform": "Console"}, "903645542": {"name": "Cartographer's Toolkit", "category": "Crafting Components", "platform": "Console"}, "2064572165": {"name": "Common Debris", "category": "Crafting Components", "platform": "Console"}, "-821947350": {"name": "Cultist Blood", "category": "Crafting Components", "platform": "Console"}, "2087837753": {"name": "Death's Breath", "category": "Crafting Components", "platform": "Console"}, "2000469169": {"name": "Defiled Doll", "category": "Crafting Components", "platform": "Console"}, "-1761931437": {"name": "Demon Skin", "category": "Crafting Components", "platform": "Console"}, "-152489231": {"name": "Demonic Essence", "category": "Crafting Components", "platform": "Console"}, "-645052297": {"name": "Devil's Fang", "category": "Crafting Components", "platform": "Console"}, "437938885": {"name": "Element of Celerity", "category": "Crafting Components", "platform": "Console"}, "2064572134": {"name": "Encrusted Hoof (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-1725926578": {"name": "Essence of the Twin Seas", "category": "Crafting Components", "platform": "Console"}, "-1506992994": {"name": "Eternal Power Capsule", "category": "Crafting Components", "platform": "Console"}, "2064572166": {"name": "Exquisite Essence", "category": "Crafting Components", "platform": "Console"}, "1726149320": {"name": "Eyes of the Dead", "category": "Crafting Components", "platform": "Console"}, "2064572068": {"name": "Fallen Tooth (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "2064572168": {"name": "Fiery Brimstone", "category": "Crafting Components", "platform": "Console"}, "2073430088": {"name": "Forgotten Soul", "category": "Crafting Components", "platform": "Console"}, "937036308": {"name": "Frozen Blood", "category": "Crafting Components", "platform": "Console"}, "-799974399": {"name": "Gibbering Gemstone", "category": "Crafting Components", "platform": "Console"}, "-1299206911": {"name": "Glowing Ore", "category": "Crafting Components", "platform": "Console"}, "-730966965": {"name": "Griswold's Scribblings", "category": "Crafting Components", "platform": "Console"}, "-958180196": {"name": "Heart of Evil", "category": "Crafting Components", "platform": "Console"}, "460247356": {"name": "Hilt of the Silver Wolf", "category": "Crafting Components", "platform": "Console"}, "314328565": {"name": "Human Cartilage", "category": "Crafting Components", "platform": "Console"}, "-1624623846": {"name": "Idol of Terror", "category": "Crafting Components", "platform": "Console"}, "2064572167": {"name": "Iridescent Tear", "category": "Crafting Components", "platform": "Console"}, "-661382443": {"name": "Iron Wolves Doctrine", "category": "Crafting Components", "platform": "Console"}, "1102953247": {"name": "Leoric's Regret", "category": "Crafting Components", "platform": "Console"}, "-629520052": {"name": "Leoric's Shinbone", "category": "Crafting Components", "platform": "Console"}, "725082635": {"name": "Liquid Rainbow", "category": "Crafting Components", "platform": "Console"}, "-1402576366": {"name": "Living Flame", "category": "Crafting Components", "platform": "Console"}, "2064572101": {"name": "Lizard Eye (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "291872615": {"name": "Lyekurn's Diary", "category": "Crafting Components", "platform": "Console"}, "1835813454": {"name": "Maghda's Tormented Soul", "category": "Crafting Components", "platform": "Console"}, "-1018735616": {"name": "Mystical Source", "category": "Crafting Components", "platform": "Console"}, "-1020906970": {"name": "Page of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-667291726": {"name": "Page of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "526997101": {"name": "Phial of Weakness", "category": "Crafting Components", "platform": "Console"}, "778194127": {"name": "Quaking Vial", "category": "Crafting Components", "platform": "Console"}, "1114256397": {"name": "Reaper's Fear", "category": "Crafting Components", "platform": "Console"}, "-363607620": {"name": "Reusable Parts", "category": "Crafting Components", "platform": "Console"}, "280425627": {"name": "Rydraelm Tome", "category": "Crafting Components", "platform": "Console"}, "-830982818": {"name": "Shard of Entsteig Plate", "category": "Crafting Components", "platform": "Console"}, "-1176010511": {"name": "Shattered Core", "category": "Crafting Components", "platform": "Console"}, "2064572100": {"name": "Shimmering Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2114382103": {"name": "Shimmering Quill", "category": "Crafting Components", "platform": "Console"}, "-248569447": {"name": "Shuddering Demon Bone", "category": "Crafting Components", "platform": "Console"}, "-1810945531": {"name": "Skelon's Dice", "category": "Crafting Components", "platform": "Console"}, "-997569662": {"name": "Skull of Raylend", "category": "Crafting Components", "platform": "Console"}, "2064572067": {"name": "Subtle Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2113447741": {"name": "Sydyru Bone", "category": "Crafting Components", "platform": "Console"}, "-1253986069": {"name": "Symbol of the Guardian Brotherhood", "category": "Crafting Components", "platform": "Console"}, "494826242": {"name": "Tome of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-722757874": {"name": "Tome of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-970366835": {"name": "Tome of Secrets (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-443730551": {"name": "Torn Soul", "category": "Crafting Components", "platform": "Console"}, "1075049130": {"name": "Urn of Quickening", "category": "Crafting Components", "platform": "Console"}, "-605947593": {"name": "Veiled Crystal", "category": "Crafting Components", "platform": "Console"}, "1998976972": {"name": "Vengeful Eye", "category": "Crafting Components", "platform": "Console"}, "2029265596": {"name": "Vial of Putridness", "category": "Crafting Components", "platform": "Console"}, "1016299457": {"name": "White Oak Splinter", "category": "Crafting Components", "platform": "Console"}, "-799868536": {"name": "Wirt's Bell", "category": "Crafting Components", "platform": "Console"}, "2064572133": {"name": "Wishful Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "1098021531": {"name": "Wooden Stake", "category": "Crafting Components", "platform": "Console"}, "2103664575": {"name": "Woven Plate", "category": "Crafting Components", "platform": "Console"}, "-1824155952": {"name": "Writhing Spine", "category": "Crafting Components", "platform": "Console"}, "-747908647": {"name": "px_HoradricReagent_01 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908646": {"name": "px_HoradricReagent_02 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908645": {"name": "px_HoradricReagent_03 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908644": {"name": "px_HoradricReagent_04 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908643": {"name": "px_HoradricReagent_05 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}}, "Crafting Plans, Jeweler": {"429567911": {"name": "Design: Flawless Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521994629": {"name": "Design: Flawless Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147380749": {"name": "Design: Flawless Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872863289": {"name": "Design: Flawless Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171649812": {"name": "Design: Flawless Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521743063": {"name": "Design: Flawless Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147129183": {"name": "Design: Flawless Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872611723": {"name": "Design: Flawless Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1540480229": {"name": "Design: Hellfire Amulet (Patch 1.2.0)", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-384404829": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1792019289": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171541998": {"name": "Design: Marquise Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521850877": {"name": "Design: Marquise Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147236997": {"name": "Design: Marquise Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872719537": {"name": "Design: Marquise Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171613874": {"name": "Design: Perfect Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521779001": {"name": "Design: Perfect Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147165121": {"name": "Design: Perfect Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872647661": {"name": "Design: Perfect Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171577936": {"name": "Design: Radiant Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521814939": {"name": "Design: Radiant Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147201059": {"name": "Design: Radiant Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872683599": {"name": "Design: Radiant Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171434184": {"name": "Design: Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429531973": {"name": "Design: Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521958691": {"name": "Design: Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147344811": {"name": "Design: Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872827351": {"name": "Design: Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}}, "Crafting Plans, Smith": {"-1427518108": {"name": "Legendary Plan: Archfiend Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1046516600": {"name": "Legendary Plan: Atrophy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1423568820": {"name": "Legendary Plan: Bitterness", "category": "Crafting Plans, Smith", "platform": "Console"}, "-380290097": {"name": "Legendary Plan: Black Bone Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1418151206": {"name": "Legendary Plan: Blitzbolter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-912856835": {"name": "Legendary Plan: Blood-Magic Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2000896011": {"name": "Legendary Plan: Blood-Magic Edge", "category": "Crafting Plans, Smith", "platform": "Console"}, "867919825": {"name": "Legendary Plan: Board Walkers", "category": "Crafting Plans, Smith", "platform": "Console"}, "-412066328": {"name": "Legendary Plan: Cataclysm", "category": "Crafting Plans, Smith", "platform": "Console"}, "1713442269": {"name": "Legendary Plan: Cinder Switch", "category": "Crafting Plans, Smith", "platform": "Console"}, "612002290": {"name": "Legendary Plan: Corruption", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1413614420": {"name": "Legendary Plan: Cosmic Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "421386501": {"name": "Legendary Plan: Deadeye", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1911170977": {"name": "Legendary Plan: Demon Claw", "category": "Crafting Plans, Smith", "platform": "Console"}, "999120591": {"name": "Legendary Plan: Demon Hand", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1426610660": {"name": "Legendary Plan: Devastator", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1326018783": {"name": "Legendary Plan: Earthshatter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1003069110": {"name": "Legendary Plan: Fire Brand", "category": "Crafting Plans, Smith", "platform": "Console"}, "957458384": {"name": "Legendary Plan: Fleeting Strap", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1639510640": {"name": "Legendary Plan: Gehennas", "category": "Crafting Plans, Smith", "platform": "Console"}, "780377031": {"name": "Legendary Plan: Golden Scourge", "category": "Crafting Plans, Smith", "platform": "Console"}, "412214125": {"name": "Legendary Plan: Harvest Moon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-501637898": {"name": "Legendary Plan: Hellish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-846348803": {"name": "Legendary Plan: Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "253048194": {"name": "Legendary Plan: Infernal Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-103899531": {"name": "Legendary Plan: Kethryes' Splint", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904674800": {"name": "Legendary Plan: Lai Yui's Persuader", "category": "Crafting Plans, Smith", "platform": "Console"}, "-168948640": {"name": "Legendary Plan: Lai Yui's Taiji", "category": "Crafting Plans, Smith", "platform": "Console"}, "1029528340": {"name": "Legendary Plan: Living Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "-405238050": {"name": "Legendary Plan: Longshot", "category": "Crafting Plans, Smith", "platform": "Console"}, "269805368": {"name": "Legendary Plan: Lost Boys", "category": "Crafting Plans, Smith", "platform": "Console"}, "244699910": {"name": "Legendary Plan: Mantle of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "2012779291": {"name": "Legendary Plan: Mark of The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "1744959696": {"name": "Legendary Plan: Night's Reaping", "category": "Crafting Plans, Smith", "platform": "Console"}, "645585264": {"name": "Legendary Plan: Nightmarish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2142082753": {"name": "Legendary Plan: Pendergrasps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-451796586": {"name": "Legendary Plan: Penders Purchase", "category": "Crafting Plans, Smith", "platform": "Console"}, "-216958038": {"name": "Legendary Plan: Piro Marella", "category": "Crafting Plans, Smith", "platform": "Console"}, "1162824884": {"name": "Legendary Plan: Quick Draw Belt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-64692264": {"name": "Legendary Plan: Reaper's Wraps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1654685887": {"name": "Legendary Plan: Robes of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904818548": {"name": "Legendary Plan: Rozpedin's Force", "category": "Crafting Plans, Smith", "platform": "Console"}, "1548578205": {"name": "Legendary Plan: Rozpedin's Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1861702115": {"name": "Legendary Plan: Ruinstoke", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2122397885": {"name": "Legendary Plan: Seven Sins", "category": "Crafting Plans, Smith", "platform": "Console"}, "1071490652": {"name": "Legendary Plan: Singularity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1846671248": {"name": "Legendary Plan: Skelon's Deceit", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1774978628": {"name": "Legendary Plan: Spite", "category": "Crafting Plans, Smith", "platform": "Console"}, "1806898802": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1463195022": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-402133524": {"name": "Legendary Plan: Starspine", "category": "Crafting Plans, Smith", "platform": "Console"}, "527593978": {"name": "Legendary Plan: Sunder", "category": "Crafting Plans, Smith", "platform": "Console"}, "2067112046": {"name": "Legendary Plan: Sydyru Crust", "category": "Crafting Plans, Smith", "platform": "Console"}, "1121389360": {"name": "Legendary Plan: The Helm of Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "-478050163": {"name": "Legendary Plan: The Helm of Rule", "category": "Crafting Plans, Smith", "platform": "Console"}, "186340431": {"name": "Legendary Plan: The Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "274154411": {"name": "Legendary Plan: The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "-242397939": {"name": "Legendary Plan: The Wedge", "category": "Crafting Plans, Smith", "platform": "Console"}, "-647199777": {"name": "Legendary Plan: Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "2066177684": {"name": "Legendary Plan: Unbound Bolt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1895316276": {"name": "Legendary Plan: Unending War", "category": "Crafting Plans, Smith", "platform": "Console"}, "-241912353": {"name": "Legendary Plan: Utar's Roar", "category": "Crafting Plans, Smith", "platform": "Console"}, "-446889189": {"name": "Legendary Plan: Venomhusk", "category": "Crafting Plans, Smith", "platform": "Console"}, "-30314682": {"name": "Legendary Plan: Wall of Bone", "category": "Crafting Plans, Smith", "platform": "Console"}, "-864620096": {"name": "Legendary Plan: Wall of Man", "category": "Crafting Plans, Smith", "platform": "Console"}, "-594473293": {"name": "Legendary Plan: War of the Dead", "category": "Crafting Plans, Smith", "platform": "Console"}, "1027888204": {"name": "Legendary Plan: Wondrous Deflectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110595705": {"name": "Rare Plan: Amulet of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110601443": {"name": "Rare Plan: Amulet of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110612529": {"name": "Rare Plan: Amulet of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110615435": {"name": "Rare Plan: Amulet of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069218648": {"name": "Rare Plan: Archon Armor of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069212910": {"name": "Rare Plan: Archon Armor of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069201824": {"name": "Rare Plan: Archon Armor of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069198918": {"name": "Rare Plan: Archon Armor of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427345983": {"name": "Rare Plan: Archon Gauntlets of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427340245": {"name": "Rare Plan: Archon Gauntlets of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427329159": {"name": "Rare Plan: Archon Gauntlets of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427326253": {"name": "Rare Plan: Archon Gauntlets of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194993962": {"name": "Rare Plan: Archon Spaulders of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194999700": {"name": "Rare Plan: Archon Spaulders of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195010786": {"name": "Rare Plan: Archon Spaulders of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195013692": {"name": "Rare Plan: Archon Spaulders of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666895": {"name": "Rare Plan: Exalted Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006109": {"name": "Rare Plan: Exalted Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232950": {"name": "Rare Plan: Exalted Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008978": {"name": "Rare Plan: Exalted Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049108": {"name": "Rare Plan: Exalted Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150314": {"name": "Rare Plan: Exalted Fine Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666894": {"name": "Rare Plan: Exalted Fine Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006108": {"name": "Rare Plan: Exalted Fine Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232949": {"name": "Rare Plan: Exalted Fine Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008977": {"name": "Rare Plan: Exalted Fine Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049107": {"name": "Rare Plan: Exalted Fine Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445431": {"name": "Rare Plan: Exalted Fine Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898771": {"name": "Rare Plan: Exalted Fine Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669101": {"name": "Rare Plan: Exalted Fine Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978459": {"name": "Rare Plan: Exalted Fine Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927530": {"name": "Rare Plan: Exalted Fine Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852815": {"name": "Rare Plan: Exalted Fine Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340209": {"name": "Rare Plan: Exalted Fine Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820187": {"name": "Rare Plan: Exalted Fine Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806016": {"name": "Rare Plan: Exalted Fine Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305005": {"name": "Rare Plan: Exalted Fine Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242821": {"name": "Rare Plan: Exalted Fine Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302887": {"name": "Rare Plan: Exalted Fine Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895417": {"name": "Rare Plan: Exalted Fine Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084692": {"name": "Rare Plan: Exalted Fine Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047028": {"name": "Rare Plan: Exalted Fine Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766203": {"name": "Rare Plan: Exalted Fine Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600122": {"name": "Rare Plan: Exalted Fine Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691115": {"name": "Rare Plan: Exalted Fine Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695962": {"name": "Rare Plan: Exalted Fine Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502140": {"name": "Rare Plan: Exalted Fine Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137849": {"name": "Rare Plan: Exalted Fine Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631474": {"name": "Rare Plan: Exalted Fine Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237753": {"name": "Rare Plan: Exalted Fine Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445432": {"name": "Rare Plan: Exalted Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898770": {"name": "Rare Plan: Exalted Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669102": {"name": "Rare Plan: Exalted Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-93021373": {"name": "Rare Plan: Exalted Grand Archmage Headpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150313": {"name": "Rare Plan: Exalted Grand Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666893": {"name": "Rare Plan: Exalted Grand Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006107": {"name": "Rare Plan: Exalted Grand Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232948": {"name": "Rare Plan: Exalted Grand Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008976": {"name": "Rare Plan: Exalted Grand Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049106": {"name": "Rare Plan: Exalted Grand Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445430": {"name": "Rare Plan: Exalted Grand Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898772": {"name": "Rare Plan: Exalted Grand Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "972140825": {"name": "Rare Plan: Exalted Grand Ghost Sight", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669100": {"name": "Rare Plan: Exalted Grand Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978460": {"name": "Rare Plan: Exalted Grand Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "531375006": {"name": "Rare Plan: Exalted Grand Heavy Baldric", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927531": {"name": "Rare Plan: Exalted Grand Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1162323497": {"name": "Rare Plan: Exalted Grand Manitou Mask", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852814": {"name": "Rare Plan: Exalted Grand Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340210": {"name": "Rare Plan: Exalted Grand Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820186": {"name": "Rare Plan: Exalted Grand Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806017": {"name": "Rare Plan: Exalted Grand Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305006": {"name": "Rare Plan: Exalted Grand Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242822": {"name": "Rare Plan: Exalted Grand Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302888": {"name": "Rare Plan: Exalted Grand Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895418": {"name": "Rare Plan: Exalted Grand Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084693": {"name": "Rare Plan: Exalted Grand Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047027": {"name": "Rare Plan: Exalted Grand Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766204": {"name": "Rare Plan: Exalted Grand Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600123": {"name": "Rare Plan: Exalted Grand Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691116": {"name": "Rare Plan: Exalted Grand Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695963": {"name": "Rare Plan: Exalted Grand Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502139": {"name": "Rare Plan: Exalted Grand Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "1784279615": {"name": "Rare Plan: Exalted Grand Stalker Cape", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137848": {"name": "Rare Plan: Exalted Grand Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631475": {"name": "Rare Plan: Exalted Grand Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237752": {"name": "Rare Plan: Exalted Grand Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927529": {"name": "Rare Plan: Exalted Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852816": {"name": "Rare Plan: Exalted Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340208": {"name": "Rare Plan: Exalted Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820188": {"name": "Rare Plan: Exalted Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806015": {"name": "Rare Plan: Exalted Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305004": {"name": "Rare Plan: Exalted Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242820": {"name": "Rare Plan: Exalted Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302886": {"name": "Rare Plan: Exalted Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895416": {"name": "Rare Plan: Exalted Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084691": {"name": "Rare Plan: Exalted Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047029": {"name": "Rare Plan: Exalted Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600121": {"name": "Rare Plan: Exalted Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691114": {"name": "Rare Plan: Exalted Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137850": {"name": "Rare Plan: Exalted Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631473": {"name": "Rare Plan: Exalted Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237754": {"name": "Rare Plan: Exalted Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656027917": {"name": "Rare Plan: Razorspikes of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656022179": {"name": "Rare Plan: Razorspikes of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656011093": {"name": "Rare Plan: Razorspikes of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656008187": {"name": "Rare Plan: Razorspikes of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1846613104": {"name": "Set Plan: Asheara's Uniform", "category": "Crafting Plans, Smith", "platform": "Console"}, "1930988128": {"name": "Set Plan: Asheara's Vestments", "category": "Crafting Plans, Smith", "platform": "Console"}, "1761387753": {"name": "Set Plan: Aughild's Authority", "category": "Crafting Plans, Smith", "platform": "Console"}, "-522988374": {"name": "Set Plan: Aughild's Victory", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1294645649": {"name": "Set Plan: Born's Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833297": {"name": "Set Plan: Born's Defiance", "category": "Crafting Plans, Smith", "platform": "Console"}, "1416190745": {"name": "Set Plan: Cain's Destiny", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833298": {"name": "Set Plan: Cain's Fate", "category": "Crafting Plans, Smith", "platform": "Console"}, "179824936": {"name": "Set Plan: Captain Crimson's Finery", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1405796903": {"name": "Set Plan: Captain Crimson's Trimmings", "category": "Crafting Plans, Smith", "platform": "Console"}, "2113413150": {"name": "Set Plan: Demon's Hide", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968554": {"name": "Set Plan: Demon's Skin", "category": "Crafting Plans, Smith", "platform": "Console"}, "331434522": {"name": "Set Plan: Griswold's Masterpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-410837290": {"name": "Set Plan: Griswold's Perfection", "category": "Crafting Plans, Smith", "platform": "Console"}, "1023052626": {"name": "Set Plan: Guardian's Contingency", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1605103146": {"name": "Set Plan: Guardian's Jeopardy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968552": {"name": "Set Plan: Hallowed Defenders", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1135146597": {"name": "Set Plan: Hallowed Protectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "1831860075": {"name": "Set Plan: Sage's Journey", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968553": {"name": "Set Plan: Sage's Plight", "category": "Crafting Plans, Smith", "platform": "Console"}}, "Crafting Plans, Transmog": {"1549850923": {"name": "Arma Mortis", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850925": {"name": "Guardian Facade", "category": "Crafting Plans, Transmog", "platform": "Console"}, "-1723454145": {"name": "Legends of the Conqueror Volume 1 (Patch 2.1.0)", "category": "Crafting Plans, Transmog", "platform": "Console"}}, "Crossbows": {"181031811": {"name": "02: Crossbow (DPS 12.7-14.3)", "category": "Crossbows", "platform": "Console"}, "181031812": {"name": "03: Heavy Crossbow (DPS 17.6-19.3)", "category": "Crossbows", "platform": "Console"}, "181031813": {"name": "04: Arbalest (DPS 22.6-24.2)", "category": "Crossbows", "platform": "Console"}, "181031814": {"name": "05: Lian Nu (DPS 27.5-29.2)", "category": "Crossbows", "platform": "Console"}, "181031815": {"name": "06: War Crossbow (DPS 32.5-34.1)", "category": "Crossbows", "platform": "Console"}, "181031816": {"name": "07: Porcupine (DPS 37.4-39.1)", "category": "Crossbows", "platform": "Console"}, "181032899": {"name": "08: Siege Crossbow (DPS 53.9-57.2)", "category": "Crossbows", "platform": "Console"}, "181032900": {"name": "09: Quarrelbow (DPS 57.2-60.5)", "category": "Crossbows", "platform": "Console"}, "181032901": {"name": "10: Heavy Siege Crossbow (DPS 64.9-68.2)", "category": "Crossbows", "platform": "Console"}, "181032902": {"name": "11: Slingbow (DPS 76.5-81.4)", "category": "Crossbows", "platform": "Console"}, "181032903": {"name": "12: Chokonu (DPS 102.9-109.5)", "category": "Crossbows", "platform": "Console"}, "181032904": {"name": "13: War Caster (DPS 122.1-130.4)", "category": "Crossbows", "platform": "Console"}, "181032905": {"name": "14: Scorpion (DPS 165.6-175.5)", "category": "Crossbows", "platform": "Console"}, "181033988": {"name": "15: Windlass (DPS 179.3-189.2)", "category": "Crossbows", "platform": "Console"}, "181033989": {"name": "16: Cranequin (DPS 194.2-204.1)", "category": "Crossbows", "platform": "Console"}, "181033990": {"name": "17: Dread Crossbow (DPS 225.0-236.5)", "category": "Crossbows", "platform": "Console"}, "181033991": {"name": "18: Nayin (DPS 281.1-294.3)", "category": "Crossbows", "platform": "Console"}, "181033992": {"name": "19: Stonebow (DPS 358.1-371.3)", "category": "Crossbows", "platform": "Console"}, "181033993": {"name": "20: Doomcaster (DPS 424.1-437.3)", "category": "Crossbows", "platform": "Console"}, "181033994": {"name": "21: Hellion Crossbow (DPS 501.1-514.3)", "category": "Crossbows", "platform": "Console"}, "181035077": {"name": "22: Rampart Bow (DPS 698.0-711.2)", "category": "Crossbows", "platform": "Console"}, "181035078": {"name": "23: Oxybeles (DPS 948.2-961.4)", "category": "Crossbows", "platform": "Console"}, "2045161301": {"name": "Art Test Crossbow 1", "category": "Crossbows", "platform": "Console"}, "2045161302": {"name": "Art Test Crossbow 2", "category": "Crossbows", "platform": "Console"}, "2045161303": {"name": "Art Test Crossbow 3", "category": "Crossbows", "platform": "Console"}, "2045161304": {"name": "Art Test Crossbow 4", "category": "Crossbows", "platform": "Console"}, "2045161305": {"name": "Art Test Crossbow 5", "category": "Crossbows", "platform": "Console"}, "-174075631": {"name": "Legendary: Arcane Barb", "category": "Crossbows", "platform": "Console"}, "-174003757": {"name": "Legendary: Bakkan Caster", "category": "Crossbows", "platform": "Console"}, "-1447231541": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1447233985": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779307": {"name": "Legendary: Bakkan Caster (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172997521": {"name": "Legendary: Buriza-Do Kyanon", "category": "Crossbows", "platform": "Console"}, "-1414028197": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1414025753": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779335": {"name": "Legendary: Buriza-Do Kyanon (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135048049": {"name": "Legendary: Chanon Bolter", "category": "Crossbows", "platform": "Console"}, "-174183442": {"name": "Legendary: Demon Machine", "category": "Crossbows", "platform": "Console"}, "-1453163590": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1453161146": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779302": {"name": "Legendary: Demon Machine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174147505": {"name": "Legendary: Hellrack", "category": "Crossbows", "platform": "Console"}, "-1451977669": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1451975225": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779303": {"name": "Legendary: Hellrack (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174111568": {"name": "Legendary: Manticore", "category": "Crossbows", "platform": "Console"}, "-1450791748": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1450789304": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779304": {"name": "Legendary: Manticore (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172961584": {"name": "Legendary: Pus Spitter", "category": "Crossbows", "platform": "Console"}, "-1412842276": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1412839832": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779336": {"name": "Legendary: Pus Spitter (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449605827": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449603383": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779305": {"name": "Legendary: Starspine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135012112": {"name": "Legendary: Wojahnni Assaulter", "category": "Crossbows", "platform": "Console"}, "376423602": {"name": "P2 Crossbow norm Legendary 01", "category": "Crossbows", "platform": "Console"}, "376423603": {"name": "P2 Crossbow norm Legendary 02", "category": "Crossbows", "platform": "Console"}, "762151703": {"name": "PvP: Heavy Crossbow", "category": "Crossbows", "platform": "Console"}, "762151705": {"name": "PvP: Heroic Crossbow", "category": "Crossbows", "platform": "Console"}, "762151704": {"name": "PvP: Mighty Crossbow", "category": "Crossbows", "platform": "Console"}}, "Crusader Shields": {"-118254878": {"name": "01: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254877": {"name": "02: Sacred Scutum (AR 54-62)", "category": "Crusader Shields", "platform": "Console"}, "-118254876": {"name": "03: Royal Shield (AR 99-114)", "category": "Crusader Shields", "platform": "Console"}, "-118254875": {"name": "04: Heraldic Heater (AR 144-188)", "category": "Crusader Shields", "platform": "Console"}, "-118254874": {"name": "05: Embossed Shield (AR 189-224)", "category": "Crusader Shields", "platform": "Console"}, "-118254873": {"name": "06: Protector Shield (AR 225-251)", "category": "Crusader Shields", "platform": "Console"}, "-118254872": {"name": "07: Crown Shield (AR 252-287)", "category": "Crusader Shields", "platform": "Console"}, "-118253789": {"name": "08: Gilded Shield (AR 288-359)", "category": "Crusader Shields", "platform": "Console"}, "-118253788": {"name": "09: Wall Shield (AR 360-431)", "category": "Crusader Shields", "platform": "Console"}, "-118253787": {"name": "10: Zakara Heater (AR 432-503)", "category": "Crusader Shields", "platform": "Console"}, "-118253786": {"name": "11: Blazoned Shield (AR 504-575)", "category": "Crusader Shields", "platform": "Console"}, "-118253785": {"name": "12: Chased Shield (AR 576-652)", "category": "Crusader Shields", "platform": "Console"}, "-118253784": {"name": "13: Conquest Shield (AR 652-696)", "category": "Crusader Shields", "platform": "Console"}, "-118253783": {"name": "14: Imperial Kite (AR 697-741)", "category": "Crusader Shields", "platform": "Console"}, "-118252700": {"name": "15: Righteous Defender (AR 742-786)", "category": "Crusader Shields", "platform": "Console"}, "-118252699": {"name": "16: Enduring Guardian (AR 787-831)", "category": "Crusader Shields", "platform": "Console"}, "-118252698": {"name": "17: Zealous Protector (AR 832-854)", "category": "Crusader Shields", "platform": "Console"}, "-118252697": {"name": "18: Raptor Shield (AR 855-967)", "category": "Crusader Shields", "platform": "Console"}, "-118252696": {"name": "19: Adamantine Blason (AR 967-1112)", "category": "Crusader Shields", "platform": "Console"}, "-118252695": {"name": "20: Heavy Shield (AR 1417-1979)", "category": "Crusader Shields", "platform": "Console"}, "-118252694": {"name": "21: Stalwart Guardian (AR 1980-2277)", "category": "Crusader Shields", "platform": "Console"}, "795980376": {"name": "Art Test CruShield 1", "category": "Crusader Shields", "platform": "Console"}, "795980377": {"name": "Art Test CruShield 2", "category": "Crusader Shields", "platform": "Console"}, "795980378": {"name": "Art Test CruShield 3", "category": "Crusader Shields", "platform": "Console"}, "795980379": {"name": "Art Test CruShield 4", "category": "Crusader Shields", "platform": "Console"}, "795980380": {"name": "Art Test CruShield 5", "category": "Crusader Shields", "platform": "Console"}, "820607285": {"name": "Legendary: Akarat's Awakening", "category": "Crusader Shields", "platform": "Console"}, "1983862516": {"name": "Legendary: Frydehr's Wrath (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "820571348": {"name": "Legendary: Hallowed Bulwark", "category": "Crusader Shields", "platform": "Console"}, "820643222": {"name": "Legendary: Hellskull", "category": "Crusader Shields", "platform": "Console"}, "820535411": {"name": "Legendary: Jekangbord", "category": "Crusader Shields", "platform": "Console"}, "820499474": {"name": "Legendary: Piro Marella", "category": "Crusader Shields", "platform": "Console"}, "820751033": {"name": "Legendary: Salvation", "category": "Crusader Shields", "platform": "Console"}, "820679159": {"name": "Legendary: Sublime Conviction", "category": "Crusader Shields", "platform": "Console"}, "820715096": {"name": "Legendary: The Final Witness", "category": "Crusader Shields", "platform": "Console"}, "1983862517": {"name": "Legendary: Unrelenting Phalanx (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}}, "Daggers": {"-1303415301": {"name": "02: Shiv (DPS 9.0-11.3)", "category": "Daggers", "platform": "Console"}, "-1303415300": {"name": "03: Short Dagger (DPS 15.0-17.3)", "category": "Daggers", "platform": "Console"}, "-1303415299": {"name": "04: Dagger (DPS 20.3-22.5)", "category": "Daggers", "platform": "Console"}, "-1303415298": {"name": "05: Poignard (DPS 23.3-25.5)", "category": "Daggers", "platform": "Console"}, "-1303415297": {"name": "06: Stiletto (DPS 27.0-29.3)", "category": "Daggers", "platform": "Console"}, "-1303415296": {"name": "07: Skiver (DPS 30.0-23.3)", "category": "Daggers", "platform": "Console"}, "-1303414213": {"name": "08: Jagged Dagger (DPS 38.3-40.5)", "category": "Daggers", "platform": "Console"}, "-1303414212": {"name": "09: Kindjal (DPS 44.3-46.5)", "category": "Daggers", "platform": "Console"}, "-1303414211": {"name": "10: Pugio (DPS 50.3-52.5)", "category": "Daggers", "platform": "Console"}, "-1303414210": {"name": "11: Rondel (DPS 57.0-59.3)", "category": "Daggers", "platform": "Console"}, "-1303414209": {"name": "12: Scramasax (DPS 66.0-68.3)", "category": "Daggers", "platform": "Console"}, "-1303414208": {"name": "13: Main Gauche (DPS 77.3-79.5)", "category": "Daggers", "platform": "Console"}, "-1303414207": {"name": "14: Spine (DPS 92.3-94.5)", "category": "Daggers", "platform": "Console"}, "-1303413124": {"name": "15: Kukri (DPS 101.3-103.5)", "category": "Daggers", "platform": "Console"}, "-1303413123": {"name": "16: Pavade (DPS 108.0-112.5)", "category": "Daggers", "platform": "Console"}, "-1303413122": {"name": "17: Cinquedea (DPS 117.8-122.3)", "category": "Daggers", "platform": "Console"}, "-1303413121": {"name": "18: Skain (DPS 129.0-133.5)", "category": "Daggers", "platform": "Console"}, "-1303413120": {"name": "19: Basilard (DPS 156.0-160.5)", "category": "Daggers", "platform": "Console"}, "-1303413119": {"name": "20: Piercer (DPS 177.8-182.3)", "category": "Daggers", "platform": "Console"}, "-1303413118": {"name": "21: Darkblade (DPS 202.5-209.3)", "category": "Daggers", "platform": "Console"}, "-1303412035": {"name": "22: Kingsport Blade (DPS 270.0-274.5)", "category": "Daggers", "platform": "Console"}, "-1303412034": {"name": "23: Punyal (DPS 321.0-325.5)", "category": "Daggers", "platform": "Console"}, "-1200973729": {"name": "Art Test Dagger 1", "category": "Daggers", "platform": "Console"}, "-1200973728": {"name": "Art Test Dagger 2", "category": "Daggers", "platform": "Console"}, "-1200973727": {"name": "Art Test Dagger 3", "category": "Daggers", "platform": "Console"}, "-1200973726": {"name": "Art Test Dagger 4", "category": "Daggers", "platform": "Console"}, "-1200973725": {"name": "Art Test Dagger 5", "category": "Daggers", "platform": "Console"}, "-2073514231": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "-2073511787": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092661": {"name": "Legendary: Blood-Magic Blade (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973885091": {"name": "Legendary: Blood-Magic Edge", "category": "Daggers", "platform": "Console"}, "-934857509": {"name": "Legendary: Envious Blade", "category": "Daggers", "platform": "Console"}, "-934929383": {"name": "Legendary: Gull Dagger", "category": "Daggers", "platform": "Console"}, "-974028839": {"name": "Legendary: Kill", "category": "Daggers", "platform": "Console"}, "-2078257915": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "-2078255471": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092657": {"name": "Legendary: Kill (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973849154": {"name": "Legendary: Pig Sticker", "category": "Daggers", "platform": "Console"}, "-2072328310": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "-2072325866": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092662": {"name": "Legendary: Pig Sticker (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934893446": {"name": "Legendary: Prowl's Dastardly Shiv", "category": "Daggers", "platform": "Console"}, "-973992902": {"name": "Legendary: The Barber", "category": "Daggers", "platform": "Console"}, "-2077071994": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "-2077069550": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092658": {"name": "Legendary: The Barber (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973813217": {"name": "Legendary: The Clipper", "category": "Daggers", "platform": "Console"}, "-2071142389": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "-2071139945": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092663": {"name": "Legendary: The Clipper (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-838272988": {"name": "Legendary: The Horadric Hamburger", "category": "Daggers", "platform": "Console"}, "-1893282128": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1893279684": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1817947684": {"name": "Legendary: The Horadric Hamburger (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-972914792": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-65175862": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-2041494364": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "-2041491920": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092688": {"name": "Legendary: Wizardspike (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934821572": {"name": "Set: Eun-jang-do (Patch 2.2.0)", "category": "Daggers", "platform": "Console"}}, "Daibos": {"1771748852": {"name": "02: Spade (DPS 21.5-23.1)", "category": "Daibos", "platform": "Console"}, "1771748853": {"name": "03: Eiku (DPS 27.5-29.2)", "category": "Daibos", "platform": "Console"}, "1771748854": {"name": "04: Taiji (DPS 41.8-43.5)", "category": "Daibos", "platform": "Console"}, "1771749940": {"name": "05: Jodo Staff (DPS 51.2-52.8)", "category": "Daibos", "platform": "Console"}, "1771749941": {"name": "06: Sibat (DPS 67.1-70.4)", "category": "Daibos", "platform": "Console"}, "1771749942": {"name": "07: Trost (DPS 97.9-101.2)", "category": "Daibos", "platform": "Console"}, "1771749943": {"name": "08: Svardstav (DPS 145.2-150.2)", "category": "Daibos", "platform": "Console"}, "1771751029": {"name": "09: Lathi (DPS 176.6-183.2)", "category": "Daibos", "platform": "Console"}, "1771751030": {"name": "10: Silambam (DPS 220.6-228.8)", "category": "Daibos", "platform": "Console"}, "1771751031": {"name": "11: Drevko (DPS 274.5-284.4)", "category": "Daibos", "platform": "Console"}, "1771751032": {"name": "12: Grand Taiji (DPS 374.6-386.1)", "category": "Daibos", "platform": "Console"}, "1771751033": {"name": "13: Zhezl (DPS 442.2-455.4)", "category": "Daibos", "platform": "Console"}, "1771751034": {"name": "14: Guru Staff (DPS 522.0-535.2)", "category": "Daibos", "platform": "Console"}, "1771752118": {"name": "15: Iron Judgement (DPS 684.3-696.3)", "category": "Daibos", "platform": "Console"}, "1771752119": {"name": "16: Whirlwind Staff (DPS 925.8-937.8)", "category": "Daibos", "platform": "Console"}, "446400306": {"name": "Legendary: Balance", "category": "Daibos", "platform": "Console"}, "1846230910": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "1846233354": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857814": {"name": "Legendary: Balance (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446651865": {"name": "Legendary: Flying Dragon", "category": "Daibos", "platform": "Console"}, "1854532357": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "1854534801": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857807": {"name": "Legendary: Flying Dragon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446436243": {"name": "Legendary: Incense Torch of the Grand Temple", "category": "Daibos", "platform": "Console"}, "1847416831": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "1847419275": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857813": {"name": "Legendary: Incense Torch of the Grand Temple (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446615928": {"name": "Legendary: Lai Yui's Persuader", "category": "Daibos", "platform": "Console"}, "1853346436": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "1853348880": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857808": {"name": "Legendary: Lai Yui's Taiji (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446472180": {"name": "Legendary: Rozpedin's Force", "category": "Daibos", "platform": "Console"}, "1848602752": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "1848605196": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857812": {"name": "Legendary: Rozpedin's Staff (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485499762": {"name": "Legendary: Staff of Kyro", "category": "Daibos", "platform": "Console"}, "1849788673": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "1849791117": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857811": {"name": "Legendary: The Clouds and the Moon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446508117": {"name": "Legendary: The Flow of Eternity", "category": "Daibos", "platform": "Console"}, "446579991": {"name": "Legendary: The Paddle", "category": "Daibos", "platform": "Console"}, "1852160515": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "1852162959": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857809": {"name": "Legendary: The Paddle (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485535699": {"name": "Legendary: Warstaff of General Quang", "category": "Daibos", "platform": "Console"}, "-326857815": {"name": "Set: Inna's Justice (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446364369": {"name": "Set: Inna's Reach", "category": "Daibos", "platform": "Console"}, "1845044989": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "1845047433": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}}, "Debug": {"201941397": {"name": "Debug Axe 002", "category": "Debug", "platform": "Console"}, "1162537406": {"name": "Debug Bow 001", "category": "Debug", "platform": "Console"}, "-1837157688": {"name": "Debug CrossBow 001", "category": "Debug", "platform": "Console"}, "110611392": {"name": "Debug Dagger 001", "category": "Debug", "platform": "Console"}, "-257486314": {"name": "Debug FistWeapon 001", "category": "Debug", "platform": "Console"}, "-1314119444": {"name": "Debug Mace 001", "category": "Debug", "platform": "Console"}, "-1314119443": {"name": "Debug Mace 002", "category": "Debug", "platform": "Console"}, "-1919522874": {"name": "Debug Polearm 001", "category": "Debug", "platform": "Console"}, "201837585": {"name": "Debug Spear 001", "category": "Debug", "platform": "Console"}, "-1812541014": {"name": "Debug Staff 001", "category": "Debug", "platform": "Console"}, "97851424": {"name": "Debug Wand 001", "category": "Debug", "platform": "Console"}, "109003955": {"name": "Professional Russian's 100 DPS 1H Axe", "category": "Debug", "platform": "Console"}, "1012655083": {"name": "Professional Russian's 100 DPS 1H Mace", "category": "Debug", "platform": "Console"}, "198260772": {"name": "Professional Russian's 100 DPS 1H Sword", "category": "Debug", "platform": "Console"}, "109003988": {"name": "Professional Russian's 100 DPS 2H Axe", "category": "Debug", "platform": "Console"}, "1012655116": {"name": "Professional Russian's 100 DPS 2H Mace", "category": "Debug", "platform": "Console"}, "198260805": {"name": "Professional Russian's 100 DPS 2H Sword", "category": "Debug", "platform": "Console"}, "1565754085": {"name": "Professional Russian's 100 DPS Bow", "category": "Debug", "platform": "Console"}, "1144284824": {"name": "Professional Russian's 100 DPS Crossbow Pistol", "category": "Debug", "platform": "Console"}, "199216263": {"name": "Professional Russian's 100 DPS Dagger", "category": "Debug", "platform": "Console"}, "131016487": {"name": "Professional Russian's 100 DPS Wand", "category": "Debug", "platform": "Console"}, "-268664650": {"name": "Professional Russian's Blind Proc Bow", "category": "Debug", "platform": "Console"}, "-497584419": {"name": "Professional Russian's Blind Proc Sword", "category": "Debug", "platform": "Console"}, "-1692695305": {"name": "Professional Russian's Bow", "category": "Debug", "platform": "Console"}, "-1353182983": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-1489225678": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-422042656": {"name": "Professional Russian's Chill Proc Sword", "category": "Debug", "platform": "Console"}, "860521450": {"name": "Professional Russian's Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-708154023": {"name": "Professional Russian's Dagger", "category": "Debug", "platform": "Console"}, "-813820178": {"name": "Professional Russian's Fast Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-1759844230": {"name": "Professional Russian's Fast Sword", "category": "Debug", "platform": "Console"}, "-1433265027": {"name": "Professional Russian's Fast Wand", "category": "Debug", "platform": "Console"}, "1812597803": {"name": "Professional Russian's Fear Proc Bow", "category": "Debug", "platform": "Console"}, "-1745505390": {"name": "Professional Russian's Fear Proc Sword", "category": "Debug", "platform": "Console"}, "-2004205682": {"name": "Professional Russian's Freeze Proc Bow", "category": "Debug", "platform": "Console"}, "-716158027": {"name": "Professional Russian's Freeze Proc Sword", "category": "Debug", "platform": "Console"}, "-1049148770": {"name": "Professional Russian's Immobilize Proc Bow", "category": "Debug", "platform": "Console"}, "1369510420": {"name": "Professional Russian's Knockback Proc Bow", "category": "Debug", "platform": "Console"}, "1063638971": {"name": "Professional Russian's Knockback Proc Sword", "category": "Debug", "platform": "Console"}, "-798366331": {"name": "Professional Russian's One-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206717": {"name": "Professional Russian's One-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502602": {"name": "Professional Russian's One-Handed Sword", "category": "Debug", "platform": "Console"}, "-395086843": {"name": "Professional Russian's Slow Crossbow Pistol", "category": "Debug", "platform": "Console"}, "1751317849": {"name": "Professional Russian's Slow Proc Sword", "category": "Debug", "platform": "Console"}, "-1341110895": {"name": "Professional Russian's Slow Sword", "category": "Debug", "platform": "Console"}, "-1899067884": {"name": "Professional Russian's Slow Wand", "category": "Debug", "platform": "Console"}, "476722551": {"name": "Professional Russian's Stun Proc Bow", "category": "Debug", "platform": "Console"}, "-41266491": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-519741474": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-798366298": {"name": "Professional Russian's Two-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206750": {"name": "Professional Russian's Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502569": {"name": "Professional Russian's Two-Handed Sword", "category": "Debug", "platform": "Console"}, "-23630983": {"name": "Professional Russian's Wand", "category": "Debug", "platform": "Console"}, "-908294397": {"name": "Shadowclone Ceremonial Knife (Hell)", "category": "Debug", "platform": "Console"}, "2012151919": {"name": "Shadowclone Ceremonial Knife (Inferno)", "category": "Debug", "platform": "Console"}, "754127773": {"name": "Shadowclone Ceremonial Knife (Nightmare)", "category": "Debug", "platform": "Console"}, "-1043228665": {"name": "Shadowclone Ceremonial Knife (Normal)", "category": "Debug", "platform": "Console"}, "-1067377991": {"name": "Shadowclone Crusader Shield", "category": "Debug", "platform": "Console"}, "413641572": {"name": "Shadowclone Daibo (Hell)", "category": "Debug", "platform": "Console"}, "1791808816": {"name": "Shadowclone Daibo (Inferno)", "category": "Debug", "platform": "Console"}, "1318657182": {"name": "Shadowclone Daibo (Nightmare)", "category": "Debug", "platform": "Console"}, "-269002584": {"name": "Shadowclone Daibo (Normal)", "category": "Debug", "platform": "Console"}, "-909812331": {"name": "Shadowclone Hand Crossbow (Hell)", "category": "Debug", "platform": "Console"}, "-998234687": {"name": "Shadowclone Hand Crossbow (Inferno)", "category": "Debug", "platform": "Console"}, "-496839313": {"name": "Shadowclone Hand Crossbow (Nightmare)", "category": "Debug", "platform": "Console"}, "1598708505": {"name": "Shadowclone Hand Crossbow (Normal)", "category": "Debug", "platform": "Console"}, "-1831368437": {"name": "Shadowclone Mojo", "category": "Debug", "platform": "Console"}, "-989882433": {"name": "Shadowclone One-Handed Flail", "category": "Debug", "platform": "Console"}, "318426510": {"name": "Shadowclone Staff (Hell)", "category": "Debug", "platform": "Console"}, "-1157906662": {"name": "Shadowclone Staff (Inferno)", "category": "Debug", "platform": "Console"}, "1714039048": {"name": "Shadowclone Staff (Nightmare)", "category": "Debug", "platform": "Console"}, "-878989998": {"name": "Shadowclone Staff (Normal)", "category": "Debug", "platform": "Console"}, "1875985680": {"name": "Shadowclone Two-Handed Mighty Weapon (Hell)", "category": "Debug", "platform": "Console"}, "832184156": {"name": "Shadowclone Two-Handed Mighty Weapon (Inferno)", "category": "Debug", "platform": "Console"}, "-35544630": {"name": "Shadowclone Two-Handed Mighty Weapon (Nightmare)", "category": "Debug", "platform": "Console"}, "-1209135788": {"name": "Shadowclone Two-Handed Mighty Weapon (Normal)", "category": "Debug", "platform": "Console"}, "2099757732": {"name": "ThorTest Bow", "category": "Debug", "platform": "Console"}, "-163370651": {"name": "ThorTest Ceremonial Dagger", "category": "Debug", "platform": "Console"}, "1291822630": {"name": "ThorTest CombatStaff", "category": "Debug", "platform": "Console"}, "-1647832978": {"name": "ThorTest Crossbow", "category": "Debug", "platform": "Console"}, "774399974": {"name": "ThorTest Dagger", "category": "Debug", "platform": "Console"}, "726818364": {"name": "ThorTest FistWeapon", "category": "Debug", "platform": "Console"}, "454120887": {"name": "ThorTest Hand Crossbow", "category": "Debug", "platform": "Console"}, "572923409": {"name": "ThorTest Mojo", "category": "Debug", "platform": "Console"}, "684187666": {"name": "ThorTest One-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118934": {"name": "ThorTest One-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530416": {"name": "ThorTest One-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903165": {"name": "ThorTest One-Handed Sword", "category": "Debug", "platform": "Console"}, "2099771967": {"name": "ThorTest Orb", "category": "Debug", "platform": "Console"}, "-1343109204": {"name": "ThorTest Polearm", "category": "Debug", "platform": "Console"}, "1306966712": {"name": "ThorTest Quiver", "category": "Debug", "platform": "Console"}, "1369802229": {"name": "ThorTest Shield", "category": "Debug", "platform": "Console"}, "1733748983": {"name": "ThorTest Spear", "category": "Debug", "platform": "Console"}, "1733888528": {"name": "ThorTest Staff", "category": "Debug", "platform": "Console"}, "684187699": {"name": "ThorTest Two-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118901": {"name": "ThorTest Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530383": {"name": "ThorTest Two-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903132": {"name": "ThorTest Two-Handed Sword", "category": "Debug", "platform": "Console"}, "573267654": {"name": "ThorTest Wand", "category": "Debug", "platform": "Console"}}, "Dyes": {"-575184703": {"name": "All-Soap's Miraculous Dye Remover", "category": "Dyes", "platform": "Console"}, "-234196827": {"name": "Aquatic Dye", "category": "Dyes", "platform": "Console"}, "-234196822": {"name": "Autumn Dye", "category": "Dyes", "platform": "Console"}, "1866876233": {"name": "Bottled Cloud", "category": "Dyes", "platform": "Console"}, "1866876234": {"name": "Bottled Smoke", "category": "Dyes", "platform": "Console"}, "-234196826": {"name": "Cardinal Dye", "category": "Dyes", "platform": "Console"}, "-234196823": {"name": "Desert Dye", "category": "Dyes", "platform": "Console"}, "-234196795": {"name": "Elegant Dye", "category": "Dyes", "platform": "Console"}, "-234196794": {"name": "Forester's Dye", "category": "Dyes", "platform": "Console"}, "-234196792": {"name": "Golden Dye", "category": "Dyes", "platform": "Console"}, "-234196790": {"name": "Infernal Dye", "category": "Dyes", "platform": "Console"}, "-234196798": {"name": "Lovely Dye", "category": "Dyes", "platform": "Console"}, "-234196793": {"name": "Mariner's Dye", "category": "Dyes", "platform": "Console"}, "-234196789": {"name": "Purity Dye", "category": "Dyes", "platform": "Console"}, "-234196825": {"name": "Ranger's Dye", "category": "Dyes", "platform": "Console"}, "-234196791": {"name": "Royal Dye", "category": "Dyes", "platform": "Console"}, "-234196796": {"name": "Spring Dye", "category": "Dyes", "platform": "Console"}, "-234196797": {"name": "Summer Dye", "category": "Dyes", "platform": "Console"}, "-234196830": {"name": "Tanner's Dye", "category": "Dyes", "platform": "Console"}, "-2000448920": {"name": "Vanishing Dye", "category": "Dyes", "platform": "Console"}, "-234196828": {"name": "Winter Dye", "category": "Dyes", "platform": "Console"}}, "Enchantress Focuses": {"761436847": {"name": "02: Eye", "category": "Enchantress Focuses", "platform": "Console"}, "761437935": {"name": "03: Scrying Glass", "category": "Enchantress Focuses", "platform": "Console"}, "761437936": {"name": "04: Blink", "category": "Enchantress Focuses", "platform": "Console"}, "761437937": {"name": "05: Crucible", "category": "Enchantress Focuses", "platform": "Console"}, "761437938": {"name": "06: Root", "category": "Enchantress Focuses", "platform": "Console"}, "761439024": {"name": "07: Eternity Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761439025": {"name": "08: Oculus", "category": "Enchantress Focuses", "platform": "Console"}, "761439026": {"name": "09: Cauldron", "category": "Enchantress Focuses", "platform": "Console"}, "761439027": {"name": "10: Herb", "category": "Enchantress Focuses", "platform": "Console"}, "761439028": {"name": "11: Anamorphosis", "category": "Enchantress Focuses", "platform": "Console"}, "761439029": {"name": "12: Augur", "category": "Enchantress Focuses", "platform": "Console"}, "-450681607": {"name": "Legendary: Hand of the Prophet", "category": "Enchantress Focuses", "platform": "Console"}, "-450681608": {"name": "Legendary: Smoking Thurible", "category": "Enchantress Focuses", "platform": "Console"}, "-450681606": {"name": "Legendary: Vadim's Surge", "category": "Enchantress Focuses", "platform": "Console"}}, "Fist Weapons": {"1236604968": {"name": "01: Knuckles (DPS 7.0-8.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604969": {"name": "02: Spikes (DPS 15.4-17.5)", "category": "Fist Weapons", "platform": "Console"}, "1236604970": {"name": "03: Talon (DPS 20.3-22.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604971": {"name": "04: Shuko (DPS 29.4-31.5)", "category": "Fist Weapons", "platform": "Console"}, "1236606057": {"name": "05: Breaker (DPS 38.5-40.6)", "category": "Fist Weapons", "platform": "Console"}, "1236606058": {"name": "06: Iron Fist (DPS 46.2-48.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606059": {"name": "07: Claw (DPS 60.2-62.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606060": {"name": "08: Kastet (DPS 81.2-83.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607146": {"name": "09: Grappler (DPS 106.4-110.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607147": {"name": "10: Hammer Hand (DPS 130.2-134.4)", "category": "Fist Weapons", "platform": "Console"}, "1236607148": {"name": "11: Demon Fang (DPS 156.8-163.1)", "category": "Fist Weapons", "platform": "Console"}, "1236607149": {"name": "12: Pulverizer (DPS 181.3-187.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607150": {"name": "13: Golden Talon (DPS 210.0-216.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607151": {"name": "14: Heaven Hand (DPS 242.2-248.5)", "category": "Fist Weapons", "platform": "Console"}, "1236608235": {"name": "15: Spiked Fist (DPS 322.0-328.3)", "category": "Fist Weapons", "platform": "Console"}, "1236608236": {"name": "16: Suwaiya (DPS 392.0-398.3)", "category": "Fist Weapons", "platform": "Console"}, "1349166155": {"name": "Art Test Fist 1", "category": "Fist Weapons", "platform": "Console"}, "1349166156": {"name": "Art Test Fist 2", "category": "Fist Weapons", "platform": "Console"}, "1349166157": {"name": "Art Test Fist 3", "category": "Fist Weapons", "platform": "Console"}, "1349166158": {"name": "Art Test Fist 4", "category": "Fist Weapons", "platform": "Console"}, "1349166159": {"name": "Art Test Fist 5", "category": "Fist Weapons", "platform": "Console"}, "-1097629365": {"name": "Legendary: Crystal Fist", "category": "Fist Weapons", "platform": "Console"}, "-1862107977": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1862105533": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690589": {"name": "Legendary: Crystal Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "2032005920": {"name": "Legendary: Deathreach", "category": "Fist Weapons", "platform": "Console"}, "-1097773113": {"name": "Legendary: Demon Claw", "category": "Fist Weapons", "platform": "Console"}, "-1866851661": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1866849217": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690593": {"name": "Legendary: Demon Hand (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058709594": {"name": "Legendary: Falcon Strike", "category": "Fist Weapons", "platform": "Console"}, "537275943": {"name": "Legendary: Fist Weapon of the Shattered Hand (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097665302": {"name": "Legendary: Fleshrake", "category": "Fist Weapons", "platform": "Console"}, "-1863293898": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1863291454": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690590": {"name": "Legendary: Fleshrake (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058745531": {"name": "Legendary: Jawbreaker", "category": "Fist Weapons", "platform": "Console"}, "-1097737176": {"name": "Legendary: Logan's Claw", "category": "Fist Weapons", "platform": "Console"}, "-1865665740": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1865663296": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690592": {"name": "Legendary: Logan's Claw (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097809050": {"name": "Legendary: Rabid Strike", "category": "Fist Weapons", "platform": "Console"}, "-1868037582": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1868035138": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690594": {"name": "Legendary: Rabid Strike (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096623129": {"name": "Legendary: Scarbringer", "category": "Fist Weapons", "platform": "Console"}, "-1828902189": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1828899745": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690561": {"name": "Legendary: Scarbringer (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096659066": {"name": "Legendary: Sledge Fist", "category": "Fist Weapons", "platform": "Console"}, "-1830088110": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1830085666": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690562": {"name": "Legendary: Sledge Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097593428": {"name": "Legendary: The Fist of Az'Turrasq", "category": "Fist Weapons", "platform": "Console"}, "-1860922056": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1860919612": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690588": {"name": "Legendary: The Fist of Az'Turrasq (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132078": {"name": "Legendary: Vengeful Wind (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097701239": {"name": "Legendary: Won Khim Lau", "category": "Fist Weapons", "platform": "Console"}, "-1864479819": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1864477375": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690591": {"name": "Legendary: Won Khim Lau (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132079": {"name": "P1 fistWeapon norm Legendary 01", "category": "Fist Weapons", "platform": "Console"}, "-1826530347": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1826527903": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096551255": {"name": "Set: Hallowed Hold", "category": "Fist Weapons", "platform": "Console"}, "-840690559": {"name": "Set: Hallowed Touch (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690563": {"name": "Set: Shenlong's Crashing Tide (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690564": {"name": "Set: Shenlong's Endless Wave (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096695003": {"name": "Set: Shenlong's Fist of Legend", "category": "Fist Weapons", "platform": "Console"}, "-1831274031": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1831271587": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096730940": {"name": "Set: Shenlong's Relentless Assault", "category": "Fist Weapons", "platform": "Console"}, "-1832459952": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1832457508": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}}, "Flails, One-Handed": {"-912456880": {"name": "01: Spiked Flail (DPS 7.7-9.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456879": {"name": "02: Iron Whip (DPS 13.3-15.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456878": {"name": "03: Barbed Flail (DPS 18.9-21.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456877": {"name": "04: Thresher (DPS 25.2-27.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456876": {"name": "05: Flail (DPS 30.8-32.9)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455791": {"name": "06: Ball and Chain (DPS 35.0-37.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455790": {"name": "07: Chain Mace (DPS 43.4-45.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455789": {"name": "08: Shredder (DPS 53.2-55.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455788": {"name": "09: Imposing Flail (DPS 71.4-73.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455787": {"name": "10: Royal Guardian (DPS 105.0-109.2)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454702": {"name": "11: Painbringer (DPS 119.0-125.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454701": {"name": "12: Knout (DPS 139.3-145.6)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454700": {"name": "13: Wicked Flail (DPS 177.1-183.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454699": {"name": "14: Giant's Flail (DPS 312.9-321.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454698": {"name": "15: Grandfather's Flail (DPS 382.9-391.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955915": {"name": "Art Test Flails One-Handed 1", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955914": {"name": "Art Test Flails One-Handed 2", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955913": {"name": "Art Test Flails One-Handed 3", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955912": {"name": "Art Test Flails One-Handed 4", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955911": {"name": "Art Test Flails One-Handed 5", "category": "Flails, One-Handed", "platform": "Console"}, "-1791015660": {"name": "Legendary: Darklight", "category": "Flails, One-Handed", "platform": "Console"}, "-1791195345": {"name": "Legendary: Golden Scourge", "category": "Flails, One-Handed", "platform": "Console"}, "-1791051597": {"name": "Legendary: Gyrfalcon's Foote", "category": "Flails, One-Handed", "platform": "Console"}, "-1790979723": {"name": "Legendary: Inviolable Faith", "category": "Flails, One-Handed", "platform": "Console"}, "-1791159408": {"name": "Legendary: Justinian's Mercy", "category": "Flails, One-Handed", "platform": "Console"}, "-1791087534": {"name": "Legendary: Kassar's Retribution", "category": "Flails, One-Handed", "platform": "Console"}, "1226090826": {"name": "Legendary: Mortal Coil", "category": "Flails, One-Handed", "platform": "Console"}, "-1791123471": {"name": "Legendary: Swiftmount", "category": "Flails, One-Handed", "platform": "Console"}, "1784501906": {"name": "P1 Flails1H norm Legendary 01", "category": "Flails, One-Handed", "platform": "Console"}}, "Flails, Two-Handed": {"-873321486": {"name": "02: Battle Flail (DPS 15.0-16.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321485": {"name": "03: Grand Thresher (DPS 22.4-24.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321484": {"name": "04: Two-Handed Flail (DPS 29.3-31.1)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321483": {"name": "05: Castigator (DPS 37.4-40.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320398": {"name": "06: Pyeongon (DPS 51.8-55.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320397": {"name": "07: Chigiriki (DPS 65.0-70.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320396": {"name": "08: Threshal (DPS 81.7-86.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320395": {"name": "09: Grand Flail (DPS 102.9-109.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320394": {"name": "10: Angelic Flail (DPS 146.1-154.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319309": {"name": "11: Campaigner's Grand Flail (DPS 194.4-206.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319308": {"name": "12: Bludgeoning Grand Flail (DPS 261.6-275.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319307": {"name": "13: Painbringer Grand Flail (DPS 333.5-347.3)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319306": {"name": "14: Baroque Grand Flail (DPS 648.0-661.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319305": {"name": "15: Angelic Grand Flail (DPS 878.0-891.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919978": {"name": "Art Test Flails Two-Handed 1", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919977": {"name": "Art Test Flails Two-Handed 2", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919976": {"name": "Art Test Flails Two-Handed 3", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919975": {"name": "Art Test Flails Two-Handed 4", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919974": {"name": "Art Test Flails Two-Handed 5", "category": "Flails, Two-Handed", "platform": "Console"}, "163153041": {"name": "Legendary: Baleful Remnant", "category": "Flails, Two-Handed", "platform": "Console"}, "163188978": {"name": "Legendary: Fate of the Fell", "category": "Flails, Two-Handed", "platform": "Console"}, "163224915": {"name": "Legendary: Golden Flense", "category": "Flails, Two-Handed", "platform": "Console"}, "163117104": {"name": "Legendary: The Mortal Drama", "category": "Flails, Two-Handed", "platform": "Console"}, "1784501907": {"name": "P1 Flails1H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712685": {"name": "P1 Flails2H norm Legendary 01", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712684": {"name": "P1 Flails2H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-1026738420": {"name": "legendary: Golden Flense (Patch 2.2.0)", "category": "Flails, Two-Handed", "platform": "Console"}}, "Gems": {"-1411866896": {"name": "Amethyst 02: Flawed Amethyst", "category": "Gems", "platform": "Console"}, "-1411866895": {"name": "Amethyst 03: Amethyst", "category": "Gems", "platform": "Console"}, "-1411866894": {"name": "Amethyst 04: Flawless Amethyst", "category": "Gems", "platform": "Console"}, "-1411866893": {"name": "Amethyst 05: Perfect Amethyst", "category": "Gems", "platform": "Console"}, "-1411866892": {"name": "Amethyst 06: Radiant Amethyst", "category": "Gems", "platform": "Console"}, "-1411866891": {"name": "Amethyst 07: Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866890": {"name": "Amethyst 08: Flawless Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866889": {"name": "Amethyst 09: Perfect Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866865": {"name": "Amethyst 10: Radiant Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866864": {"name": "Amethyst 11: Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866863": {"name": "Amethyst 12: Flawless Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866862": {"name": "Amethyst 13: Perfect Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866861": {"name": "Amethyst 14: Radiant Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866860": {"name": "Amethyst 15: Marquise Amethyst", "category": "Gems", "platform": "Console"}, "-1411866859": {"name": "Amethyst 16: Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866858": {"name": "Amethyst 17: Flawless Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866857": {"name": "Amethyst 18: Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1411866856": {"name": "Amethyst 19: Flawless Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1315690660": {"name": "Diamond 01: Chipped Diamond", "category": "Gems", "platform": "Console"}, "-1315690659": {"name": "Diamond 02: Flawed Diamond", "category": "Gems", "platform": "Console"}, "-1315690658": {"name": "Diamond 03: Diamond", "category": "Gems", "platform": "Console"}, "-1315690657": {"name": "Diamond 04: Flawless Diamond", "category": "Gems", "platform": "Console"}, "-1315690656": {"name": "Diamond 05: Perfect Diamond", "category": "Gems", "platform": "Console"}, "-1315690655": {"name": "Diamond 06: Radiant Diamond", "category": "Gems", "platform": "Console"}, "-1315690654": {"name": "Diamond 07: Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690653": {"name": "Diamond 08: Flawless Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690652": {"name": "Diamond 09: Perfect Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690628": {"name": "Diamond 10: Radiant Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690627": {"name": "Diamond 11: Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690626": {"name": "Diamond 12: Flawless Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690625": {"name": "Diamond 13: Perfect Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690624": {"name": "Diamond 14: Radiant Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690623": {"name": "Diamond 15: Marquise Diamond", "category": "Gems", "platform": "Console"}, "-1315690622": {"name": "Diamond 16: Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690621": {"name": "Diamond 17: Flawless Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690620": {"name": "Diamond 18: Royal Diamond", "category": "Gems", "platform": "Console"}, "-1315690619": {"name": "Diamond 19: Flawless Royal Diamond", "category": "Gems", "platform": "Console"}, "-1733388806": {"name": "Emerald 01: Chipped Emerald", "category": "Gems", "platform": "Console"}, "-1733388805": {"name": "Emerald 02: Flawed Emerald", "category": "Gems", "platform": "Console"}, "-1733388804": {"name": "Emerald 03: Emerald", "category": "Gems", "platform": "Console"}, "-1733388803": {"name": "Emerald 04: Flawless Emerald", "category": "Gems", "platform": "Console"}, "-1733388802": {"name": "Emerald 05: Perfect Emerald", "category": "Gems", "platform": "Console"}, "-1733388801": {"name": "Emerald 06: Radiant Emerald", "category": "Gems", "platform": "Console"}, "-1733388800": {"name": "Emerald 07: Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388799": {"name": "Emerald 08: Flawless Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388798": {"name": "Emerald 09: Perfect Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388774": {"name": "Emerald 10: Radiant Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388773": {"name": "Emerald 11: Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388772": {"name": "Emerald 12: Flawless Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388771": {"name": "Emerald 13: Perfect Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388770": {"name": "Emerald 14: Radiant Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388769": {"name": "Emerald 15: Marquise Emerald", "category": "Gems", "platform": "Console"}, "-1733388768": {"name": "Emerald 16: Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388767": {"name": "Emerald 17: Flawless Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388766": {"name": "Emerald 18: Royal Emerald", "category": "Gems", "platform": "Console"}, "-1733388765": {"name": "Emerald 19: Flawless Royal Emerald", "category": "Gems", "platform": "Console"}, "-1046455929": {"name": "Legendary: Bane of the Powerful (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046419992": {"name": "Legendary: Bane of the Trapped (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045162197": {"name": "Legendary: Boon of the Hoarder (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045305945": {"name": "Legendary: Enforcer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045090323": {"name": "Legendary: Esoteric Alteration (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1044084087": {"name": "Legendary: Gem Of X NYI (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046312181": {"name": "Legendary: Gem of Efficacious Toxin (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046384055": {"name": "Legendary: Gem of Reduced Level Requirement (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046204370": {"name": "Legendary: Gogok of Swiftness (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046168433": {"name": "Legendary: Invigorating Gemstone (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046240307": {"name": "Legendary: Mirinae, Teardrop of the Starweaver (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045054386": {"name": "Legendary: Molten Wildebeest's Gizzard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045270008": {"name": "Legendary: Moratorium (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044982512": {"name": "Legendary: Mutilation Guard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046276244": {"name": "Legendary: Pain Enhancer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044120024": {"name": "Legendary: Shen's Delight (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045198134": {"name": "Legendary: Simplicity's Strength (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045018449": {"name": "Legendary: Stone Of Heresy (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045126260": {"name": "Legendary: Taeguk (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046348118": {"name": "Legendary: Wreath of Lightning (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045234071": {"name": "Legendary: Zei's Stone of Vengeance (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "1603007810": {"name": "Ruby 01: Chipped Ruby", "category": "Gems", "platform": "Console"}, "1603007811": {"name": "Ruby 02: Flawed Ruby", "category": "Gems", "platform": "Console"}, "1603007812": {"name": "Ruby 03: Ruby", "category": "Gems", "platform": "Console"}, "1603007813": {"name": "Ruby 04: Flawless Ruby", "category": "Gems", "platform": "Console"}, "1603007814": {"name": "Ruby 05: Perfect Ruby", "category": "Gems", "platform": "Console"}, "1603007815": {"name": "Ruby 06: Radiant Ruby", "category": "Gems", "platform": "Console"}, "1603007816": {"name": "Ruby 07: Square Ruby", "category": "Gems", "platform": "Console"}, "1603007817": {"name": "Ruby 08: Flawless Square Ruby", "category": "Gems", "platform": "Console"}, "1603007818": {"name": "Ruby 09: Perfect Square Ruby", "category": "Gems", "platform": "Console"}, "1603007842": {"name": "Ruby 10: Radiant Square Ruby", "category": "Gems", "platform": "Console"}, "1603007843": {"name": "Ruby 11: Star Ruby", "category": "Gems", "platform": "Console"}, "1603007844": {"name": "Ruby 12: Flawless Star Ruby", "category": "Gems", "platform": "Console"}, "1603007845": {"name": "Ruby 13: Perfect Star Ruby", "category": "Gems", "platform": "Console"}, "1603007846": {"name": "Ruby 14: Radiant Star Ruby", "category": "Gems", "platform": "Console"}, "1603007847": {"name": "Ruby 15: Marquise Ruby", "category": "Gems", "platform": "Console"}, "1603007848": {"name": "Ruby 16: Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007849": {"name": "Ruby 17: Flawless Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007850": {"name": "Ruby 18: Royal Ruby", "category": "Gems", "platform": "Console"}, "1603007851": {"name": "Ruby 19: Flawless Royal Ruby", "category": "Gems", "platform": "Console"}, "2058771886": {"name": "Topaz 01: Chipped Topaz", "category": "Gems", "platform": "Console"}, "2058771887": {"name": "Topaz 02: Flawed Topaz", "category": "Gems", "platform": "Console"}, "2058771888": {"name": "Topaz 03: Topaz", "category": "Gems", "platform": "Console"}, "2058771889": {"name": "Topaz 04: Flawless Topaz", "category": "Gems", "platform": "Console"}, "2058771890": {"name": "Topaz 05: Perfect Topaz", "category": "Gems", "platform": "Console"}, "2058771891": {"name": "Topaz 06: Radiant Topaz", "category": "Gems", "platform": "Console"}, "2058771892": {"name": "Topaz 07: Square Topaz", "category": "Gems", "platform": "Console"}, "2058771893": {"name": "Topaz 08: Flawless Square Topaz", "category": "Gems", "platform": "Console"}, "2058771894": {"name": "Topaz 09: Perfect Square Topaz", "category": "Gems", "platform": "Console"}, "2058771918": {"name": "Topaz 10: Radiant Square Topaz", "category": "Gems", "platform": "Console"}, "2058771919": {"name": "Topaz 11: Star Topaz", "category": "Gems", "platform": "Console"}, "2058771920": {"name": "Topaz 12: Flawless Star Topaz", "category": "Gems", "platform": "Console"}, "2058771921": {"name": "Topaz 13: Perfect Star Topaz", "category": "Gems", "platform": "Console"}, "2058771922": {"name": "Topaz 14: Radiant Star Topaz", "category": "Gems", "platform": "Console"}, "2058771923": {"name": "Topaz 15: Marquise Topaz", "category": "Gems", "platform": "Console"}, "2058771924": {"name": "Topaz 16: Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771925": {"name": "Topaz 17: Flawless Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771926": {"name": "Topaz 18: Royal Topaz", "category": "Gems", "platform": "Console"}, "2058771927": {"name": "Topaz 19: Flawless Royal Topaz", "category": "Gems", "platform": "Console"}}, "Gloves": {"-1533914303": {"name": "02: Leather Gloves (AR 14-16)", "category": "Gloves", "platform": "Console"}, "-1533914302": {"name": "03: Hide Gloves (AR 28-32)", "category": "Gloves", "platform": "Console"}, "-1533914301": {"name": "04: Chain Gloves (AR 42-55)", "category": "Gloves", "platform": "Console"}, "-1533914300": {"name": "05: Gauntlets (AR 56-69)", "category": "Gloves", "platform": "Console"}, "-1533914299": {"name": "06: Plated Gauntlets (AR 70-88)", "category": "Gloves", "platform": "Console"}, "-1533913215": {"name": "07: Grips (AR 88-106)", "category": "Gloves", "platform": "Console"}, "-1533913214": {"name": "08: Etched Gloves (AR 107-125)", "category": "Gloves", "platform": "Console"}, "-1533913213": {"name": "09: Vambraces (AR 126-144)", "category": "Gloves", "platform": "Console"}, "-1533913212": {"name": "10: Battle Gauntlets (AR 144-173)", "category": "Gloves", "platform": "Console"}, "-1533913211": {"name": "11: Boneweave Gauntlets (AR 175-192)", "category": "Gloves", "platform": "Console"}, "-1533912126": {"name": "12: Balor Fists (AR 192-209)", "category": "Gloves", "platform": "Console"}, "-1533912125": {"name": "13: Manifers (AR 210-221)", "category": "Gloves", "platform": "Console"}, "-1533912124": {"name": "14: Warlord Gauntlets (AR 221-249)", "category": "Gloves", "platform": "Console"}, "-1533912123": {"name": "15: Stranglers (AR 250-278)", "category": "Gloves", "platform": "Console"}, "-1533912122": {"name": "16: Sovereign Vambraces (AR 280-308)", "category": "Gloves", "platform": "Console"}, "-1533912121": {"name": "17: Archon Gauntlets (AR 309-366)", "category": "Gloves", "platform": "Console"}, "-1533912120": {"name": "18: Rakkisgard Gauntlets (AR 367-512)", "category": "Gloves", "platform": "Console"}, "-1533912119": {"name": "19: Ascended Gauntlets (AR 513-590)", "category": "Gloves", "platform": "Console"}, "-542544859": {"name": "Art Test Gloves 1", "category": "Gloves", "platform": "Console"}, "-542544858": {"name": "Art Test Gloves 2", "category": "Gloves", "platform": "Console"}, "-542544857": {"name": "Art Test Gloves 3", "category": "Gloves", "platform": "Console"}, "-542544856": {"name": "Art Test Gloves 4", "category": "Gloves", "platform": "Console"}, "-542544855": {"name": "Art Test Gloves 5", "category": "Gloves", "platform": "Console"}, "-724111115": {"name": "Art_Test_Gloves_10 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-724111114": {"name": "Art_Test_Gloves_11 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544854": {"name": "Art_Test_Gloves_6 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544853": {"name": "Art_Test_Gloves_7 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544852": {"name": "Art_Test_Gloves_8 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544851": {"name": "Art_Test_Gloves_9 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "509897201": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "742334711": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "614385664": {"name": "Legendary: Alabaster Gloves", "category": "Gloves", "platform": "Console"}, "-935578501": {"name": "Legendary: Conqueror's Gauntlets (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "575250271": {"name": "Legendary: Frostburn", "category": "Gloves", "platform": "Console"}, "1803312459": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1803314903": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593655": {"name": "Legendary: Frostburn Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576400255": {"name": "Legendary: Gladiator Gauntlets", "category": "Gloves", "platform": "Console"}, "1841261931": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1841264375": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593687": {"name": "Legendary: Gladiator Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "614421601": {"name": "Legendary: Gloves of Worship", "category": "Gloves", "platform": "Console"}, "204261921": {"name": "Legendary: Grips of Perilous Ascent", "category": "Gloves", "platform": "Console"}, "576508066": {"name": "Legendary: Magefist", "category": "Gloves", "platform": "Console"}, "1844819694": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "1844822138": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "880593690": {"name": "Legendary: Magefist (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1802126538": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "1802128982": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "880593654": {"name": "Legendary: Pendergrasps (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575214334": {"name": "Legendary: Penders Purchase", "category": "Gloves", "platform": "Console"}, "614349727": {"name": "Legendary: St. Archew's Gage", "category": "Gloves", "platform": "Console"}, "575429956": {"name": "Legendary: Stone Gauntlets", "category": "Gloves", "platform": "Console"}, "1809242064": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1809244508": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593660": {"name": "Legendary: Stone Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575286208": {"name": "Legendary: Tasker and Theo", "category": "Gloves", "platform": "Console"}, "1804498380": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "1804500824": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "880593656": {"name": "Legendary: Tasker and Theo (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "880593662": {"name": "Set: Asheara's Clasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1811613906": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "1811616350": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "575501830": {"name": "Set: Asheara's Ward", "category": "Gloves", "platform": "Console"}, "1846005615": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "1846008059": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "576544003": {"name": "Set: Cain's Scrivener", "category": "Gloves", "platform": "Console"}, "880593691": {"name": "Set: Cain's Warmers (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "2058321365": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058321364": {"name": "Set: Fiendish Grips (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058285427": {"name": "Set: Fierce Gauntlets (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058429438": {"name": "Set: Firebird's Talons", "category": "Gloves", "platform": "Console"}, "2058501312": {"name": "Set: Fists of Thunder", "category": "Gloves", "platform": "Console"}, "2058249490": {"name": "Set: Gauntlet of the Wastes (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059399737": {"name": "Set: Gauntlets of Akkhan", "category": "Gloves", "platform": "Console"}, "2059615359": {"name": "Set: Helltooth Gauntlets", "category": "Gloves", "platform": "Console"}, "880593661": {"name": "Set: Immortal King's Forge (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575465893": {"name": "Set: Immortal King's Irons", "category": "Gloves", "platform": "Console"}, "1810427985": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "1810430429": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "-206156950": {"name": "Set: Inna's Hold (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058537249": {"name": "Set: Jade Harvester's Mercy", "category": "Gloves", "platform": "Console"}, "2058465375": {"name": "Set: Marauder's Gloves", "category": "Gloves", "platform": "Console"}, "2058249491": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156953": {"name": "Set: Natalya's Touch (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059471611": {"name": "Set: Pride of the Invoker", "category": "Gloves", "platform": "Console"}, "2059579422": {"name": "Set: Pull of the Earth", "category": "Gloves", "platform": "Console"}, "2058393501": {"name": "Set: Raekor's Wraps", "category": "Gloves", "platform": "Console"}, "2058249489": {"name": "Set: Roland's Grasp (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "1848377457": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "1848379901": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "880593693": {"name": "Set: Sage's Grasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576615877": {"name": "Set: Sage's Purchase", "category": "Gloves", "platform": "Console"}, "2059435674": {"name": "Set: Sunwuko's Paws", "category": "Gloves", "platform": "Console"}, "-206156952": {"name": "Set: Tal Rasha's Grasp (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059543485": {"name": "Set: The Shadow's Grasp", "category": "Gloves", "platform": "Console"}, "2059507548": {"name": "Set: Vyr's Grasping Gauntlets", "category": "Gloves", "platform": "Console"}, "2058285428": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156951": {"name": "Set: Zunimassa's Finger Wraps (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "614349464": {"name": "legendary: St. Archew's Gage (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}}, "Hand Crossbows": {"-363391669": {"name": "01: Simple Hand Crossbow (DPS 12.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363391668": {"name": "02: Light Hand Crossbow (DPS 11.2-13.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363391667": {"name": "03: Stake Thrower (DPS 12.8-15.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391666": {"name": "04: Hand Crossbow (DPS 16.0-18.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391665": {"name": "05: Slinglock (DPS 20.8-23.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391664": {"name": "06: Quillshot (DPS 24.0-26.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391663": {"name": "07: Nail Spitter (DPS 28.0-30.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391662": {"name": "08: Heavy Stake Thrower (DPS 32.8-35.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390580": {"name": "09: Sling Pistol (DPS 38.4-40.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363390579": {"name": "10: Crosslock (DPS 44.0-46.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390578": {"name": "11: Siege Lock (DPS 48.8-51.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390577": {"name": "12: Arcus (DPS 60.0-62.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390576": {"name": "13: Cranequin (DPS 65.6-68.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390575": {"name": "14: Spine Thrower (DPS 76.8-79.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390574": {"name": "15: Heavy Arcus (DPS 85.6-88.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390573": {"name": "16: Bolt Rack (DPS 98.4-100.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389491": {"name": "17: Runic Sling Pistol (DPS 113.6-116.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389490": {"name": "18: Splinter Shot (DPS 127.2-129.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389489": {"name": "19: Windlash (DPS 139.2-141.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389488": {"name": "20: Blade Spitter (DPS 154.4-156.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389487": {"name": "21: Heavy Cranequin (DPS 170.4-172.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389486": {"name": "22: Runic Arcus (DPS 196.8-199.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363389485": {"name": "23: Impellor (DPS 225.6-228.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389484": {"name": "24: Exorcist (DPS 258.4-263.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388402": {"name": "25: Lionblade Bow (DPS 516.8-519.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388401": {"name": "26: Penetrator (DPS 672.0-674.4)", "category": "Hand Crossbows", "platform": "Console"}, "1203045553": {"name": "Art Test Hand Crossbow 2", "category": "Hand Crossbows", "platform": "Console"}, "1203045554": {"name": "Art Test Hand Crossbow 3", "category": "Hand Crossbows", "platform": "Console"}, "1203045555": {"name": "Art Test Hand Crossbow 4", "category": "Hand Crossbows", "platform": "Console"}, "1203045556": {"name": "Art Test Hand Crossbow 5", "category": "Hand Crossbows", "platform": "Console"}, "1203045552": {"name": "Art Test HandCrossbow 1", "category": "Hand Crossbows", "platform": "Console"}, "-1153493044": {"name": "Legendary: Balefire Caster", "category": "Hand Crossbows", "platform": "Console"}, "589357912": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "589360356": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789444": {"name": "Legendary: Balefire Caster (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153493308": {"name": "Legendary: Balefire Caster (Patch 2.1.0)", "category": "Hand Crossbows", "platform": "Console"}, "-1153421170": {"name": "Legendary: Blitzbolter", "category": "Hand Crossbows", "platform": "Console"}, "-1152378997": {"name": "Legendary: Calamity", "category": "Hand Crossbows", "platform": "Console"}, "626121463": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "626123907": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789475": {"name": "Legendary: Calamity (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153385233": {"name": "Legendary: Dawn", "category": "Hand Crossbows", "platform": "Console"}, "592915675": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "592918119": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789447": {"name": "Legendary: Dawn (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591729754": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591732198": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789446": {"name": "Legendary: Deadeye (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114429525": {"name": "Legendary: Helltrapper", "category": "Hand Crossbows", "platform": "Console"}, "-1153457107": {"name": "Legendary: Izzuccob", "category": "Hand Crossbows", "platform": "Console"}, "590543833": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "590546277": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789445": {"name": "Legendary: Izzuccob (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114465462": {"name": "Legendary: K'mar Tenclip", "category": "Hand Crossbows", "platform": "Console"}, "-44923323": {"name": "Legendary: Quietus", "category": "Hand Crossbows", "platform": "Console"}, "-1266666515": {"name": "P2 Hand Crossbow norm Legendary 01", "category": "Hand Crossbows", "platform": "Console"}, "-1266666514": {"name": "P2 Hand Crossbow norm Legendary 02", "category": "Hand Crossbows", "platform": "Console"}, "-1266666513": {"name": "P2 Hand Crossbow norm Legendary 03", "category": "Hand Crossbows", "platform": "Console"}, "515789442": {"name": "Set: Danetta's Fury (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789441": {"name": "Set: Danetta's Rage (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153564918": {"name": "Set: Danetta's Revenge", "category": "Hand Crossbows", "platform": "Console"}, "586986070": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "586988514": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153600855": {"name": "Set: Danetta's Spite", "category": "Hand Crossbows", "platform": "Console"}, "585800149": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "585802593": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789479": {"name": "Set: Hallowed Avenger (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1152235249": {"name": "Set: Hallowed Condemnation", "category": "Hand Crossbows", "platform": "Console"}, "630865147": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "630867591": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789443": {"name": "Set: Natalya's Redemption (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153528981": {"name": "Set: Natalya's Slayer", "category": "Hand Crossbows", "platform": "Console"}, "588171991": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "588174435": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}}, "Helms": {"1565454584": {"name": "03: Coif (AR 36-41)", "category": "Helms", "platform": "Console"}, "1565454585": {"name": "04: Arming Cap (AR 54-71)", "category": "Helms", "platform": "Console"}, "1565454586": {"name": "05: Helmet (AR 72-89)", "category": "Helms", "platform": "Console"}, "1565454587": {"name": "06: Plated Helm (AR 90-113)", "category": "Helms", "platform": "Console"}, "1565455671": {"name": "07: Crown (AR 114-137)", "category": "Helms", "platform": "Console"}, "1565455672": {"name": "08: Basinet (AR 138-161)", "category": "Helms", "platform": "Console"}, "1565455673": {"name": "09: Klappvisier (AR 162-185)", "category": "Helms", "platform": "Console"}, "1565455674": {"name": "10: Casque (AR 186-224)", "category": "Helms", "platform": "Console"}, "1565455675": {"name": "11: Great Helm (AR 225-247)", "category": "Helms", "platform": "Console"}, "1565456760": {"name": "12: Hounskull (AR 247-269)", "category": "Helms", "platform": "Console"}, "1565456761": {"name": "13: Stechhelm (AR 270-284)", "category": "Helms", "platform": "Console"}, "1565456762": {"name": "14: Zischagge (AR 285-322)", "category": "Helms", "platform": "Console"}, "1565456763": {"name": "15: Hellscape Mask (AR 322-359)", "category": "Helms", "platform": "Console"}, "1565456764": {"name": "16: Sovereign Helm (AR 360-397)", "category": "Helms", "platform": "Console"}, "1565456765": {"name": "17: Archon Crown (AR 397-471)", "category": "Helms", "platform": "Console"}, "1565456766": {"name": "18: Rakkisgard Helm (AR 472-659)", "category": "Helms", "platform": "Console"}, "1565456767": {"name": "19: Ascended Crown (AR 660-759)", "category": "Helms", "platform": "Console"}, "1422434075": {"name": "Art Test Helm 1", "category": "Helms", "platform": "Console"}, "1422434076": {"name": "Art Test Helm 2", "category": "Helms", "platform": "Console"}, "1422434077": {"name": "Art Test Helm 3", "category": "Helms", "platform": "Console"}, "1422434078": {"name": "Art Test Helm 4", "category": "Helms", "platform": "Console"}, "1422434079": {"name": "Art Test Helm 5", "category": "Helms", "platform": "Console"}, "-304315733": {"name": "Art_Test_Helm_10 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315732": {"name": "Art_Test_Helm_11 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315731": {"name": "Art_Test_Helm_12 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434080": {"name": "Art_Test_Helm_6 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434081": {"name": "Art_Test_Helm_7 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434082": {"name": "Art_Test_Helm_8 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434083": {"name": "Art_Test_Helm_9 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233654": {"name": "Legendary: Andariel's Visage", "category": "Helms", "platform": "Console"}, "-1855268606": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "-1855266162": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "1638662958": {"name": "Legendary: Andariel's Visage (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334377402": {"name": "Legendary: Blind Faith", "category": "Helms", "platform": "Console"}, "-1850524922": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "-1850522478": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "1638662962": {"name": "Legendary: Blind Faith (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334161780": {"name": "Legendary: Broken Crown", "category": "Helms", "platform": "Console"}, "-1857640448": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1857638004": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662956": {"name": "Legendary: Broken Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1046338483": {"name": "Legendary: Broken Crown (Patch 2.1.2)", "category": "Helms", "platform": "Console"}, "1239902833": {"name": "Legendary: Conqueror's Shako (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "974143057": {"name": "Legendary: Death Mask", "category": "Helms", "platform": "Console"}, "373333110": {"name": "Legendary: Deathseer's Cowl", "category": "Helms", "platform": "Console"}, "-1854082685": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "-1854080241": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "1638662959": {"name": "Legendary: Giant Skull (Old-Legacy)", "category": "Helms", "platform": "Console"}, "1571690839": {"name": "Legendary: Guardian Facade", "category": "Helms", "platform": "Console"}, "974107120": {"name": "Legendary: Hallowed Helm", "category": "Helms", "platform": "Console"}, "-843818268": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "-1425221075": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "334197717": {"name": "Legendary: Leoric's Crown", "category": "Helms", "platform": "Console"}, "-1856454527": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1856452083": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662957": {"name": "Legendary: Leoric's Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334197453": {"name": "Legendary: Leoric's Crown (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "334341465": {"name": "Legendary: Mempo of Twilight", "category": "Helms", "platform": "Console"}, "-1851710843": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "-1851708399": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "1638662961": {"name": "Legendary: Mempo of Twilight (Old-Legacy)", "category": "Helms", "platform": "Console"}, "373369047": {"name": "Legendary: Pride's Fall", "category": "Helms", "platform": "Console"}, "334269591": {"name": "Legendary: Skull of Resonance", "category": "Helms", "platform": "Console"}, "-1818505055": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "-1818502611": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "1638662989": {"name": "Legendary: The Helm of Command (Old-Legacy)", "category": "Helms", "platform": "Console"}, "335347701": {"name": "Legendary: The Helm of Rule", "category": "Helms", "platform": "Console"}, "-1993242998": {"name": "Set: Accursed Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662992": {"name": "Set: Aughild's Brow (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1814947292": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "-1814944848": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "335455512": {"name": "Set: Aughild's Spike", "category": "Helms", "platform": "Console"}, "335383638": {"name": "Set: Cain's Insight", "category": "Helms", "platform": "Console"}, "1638662990": {"name": "Set: Cain's Laurel (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1817319134": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1817316690": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1992092751": {"name": "Set: Crown of the Invoker", "category": "Helms", "platform": "Console"}, "-1993242997": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1991984940": {"name": "Set: Eyes of the Earth", "category": "Helms", "platform": "Console"}, "-1993134924": {"name": "Set: Firebird's Plume", "category": "Helms", "platform": "Console"}, "-1813761371": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "-1813758927": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "335491449": {"name": "Set: Guardian's Gaze", "category": "Helms", "platform": "Console"}, "1638662993": {"name": "Set: Guardian's Watch (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1992164625": {"name": "Set: Helm of Akkhan", "category": "Helms", "platform": "Console"}, "-1993314872": {"name": "Set: Helm of the Wastes (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334413339": {"name": "Set: Immortal King's Triumph", "category": "Helms", "platform": "Console"}, "-1849339001": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "-1849336557": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "1638662963": {"name": "Set: Immortal King's Will (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993027113": {"name": "Set: Jade Harvester's Wisdom", "category": "Helms", "platform": "Console"}, "-1993098987": {"name": "Set: Marauder's Visage", "category": "Helms", "platform": "Console"}, "-1991949003": {"name": "Set: Mask of Jeram", "category": "Helms", "platform": "Console"}, "-1993063050": {"name": "Set: Mask of the Searing Sky", "category": "Helms", "platform": "Console"}, "-1993314871": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662964": {"name": "Set: Natalya's Gaze (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334449276": {"name": "Set: Natalya's Sight", "category": "Helms", "platform": "Console"}, "-1848153080": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1848150636": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1993170861": {"name": "Set: Raekor's Will", "category": "Helms", "platform": "Console"}, "-1993314873": {"name": "Set: Roland's Visage (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "335527386": {"name": "Set: Sage's Apogee", "category": "Helms", "platform": "Console"}, "-1812575450": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "-1812573006": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "1638662994": {"name": "Set: Sage's Stones (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278935": {"name": "Set: Shrouded Mask (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1992128688": {"name": "Set: Sunwuko's Crown", "category": "Helms", "platform": "Console"}, "335311764": {"name": "Set: Tal Rasha's Guise of Wisdom", "category": "Helms", "platform": "Console"}, "-1819690976": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "-1819688532": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "1638662988": {"name": "Set: Tal Rasha's Horadric Crest (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278934": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233391": {"name": "legendary: Andariel's Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-36755477": {"name": "legendary: Helm of the Hierarch (Patch 2.2.0)", "category": "Helms", "platform": "Console"}}, "Horadric Cache": {"739397179": {"name": "Act 1, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1369696819": {"name": "Act 1, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1369696818": {"name": "Act 1, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1369696817": {"name": "Act 1, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1369696816": {"name": "Act 1, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1369696815": {"name": "Act 1, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654861": {"name": "Act 2", "category": "Horadric Cache", "platform": "Console"}, "408167196": {"name": "Act 2, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "584615630": {"name": "Act 2, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "584615631": {"name": "Act 2, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "584615632": {"name": "Act 2, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "584615633": {"name": "Act 2, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "584615634": {"name": "Act 2, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654860": {"name": "Act 3", "category": "Horadric Cache", "platform": "Console"}, "76937213": {"name": "Act 3, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1756039217": {"name": "Act 3, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1756039216": {"name": "Act 3, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1756039215": {"name": "Act 3, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1756039214": {"name": "Act 3, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1756039213": {"name": "Act 3, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654859": {"name": "Act 4", "category": "Horadric Cache", "platform": "Console"}, "-254292770": {"name": "Act 4, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "198273232": {"name": "Act 4, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "198273233": {"name": "Act 4, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "198273234": {"name": "Act 4, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "198273235": {"name": "Act 4, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "198273236": {"name": "Act 4, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654858": {"name": "Act 5", "category": "Horadric Cache", "platform": "Console"}, "-585522753": {"name": "Act 5, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-2142381615": {"name": "Act 5, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-2142381614": {"name": "Act 5, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-2142381613": {"name": "Act 5, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-2142381612": {"name": "Act 5, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-2142381611": {"name": "Act 5, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "1574352095": {"name": "Bonus Act", "category": "Horadric Cache", "platform": "Console"}, "1749838250": {"name": "Greater Horadric Cache", "category": "Horadric Cache", "platform": "Console"}, "1802516147": {"name": "Greater Horadric Cache Torment", "category": "Horadric Cache", "platform": "Console"}, "-1262930872": {"name": "Horadric Cache Bonus Act Torment", "category": "Horadric Cache", "platform": "Console"}}, "Junk": {"-326449293": {"name": "Arcane Globe", "category": "Junk", "platform": "Console"}, "393991529": {"name": "Art_Test_Pennant_1 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991530": {"name": "Art_Test_Pennant_2 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991531": {"name": "Art_Test_Pennant_3 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991532": {"name": "Art_Test_Pennant_4 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991533": {"name": "Art_Test_Pennant_5 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991534": {"name": "Art_Test_Pennant_6 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991535": {"name": "Art_Test_Pennant_7 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991536": {"name": "Art_Test_Pennant_8 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-215839115": {"name": "Blizzcon Artifact", "category": "Junk", "platform": "Console"}, "-1812121245": {"name": "Cauldron of Jordan", "category": "Junk", "platform": "Console"}, "-125073416": {"name": "Charm", "category": "Junk", "platform": "Console"}, "-125073414": {"name": "Crafter Skillup Page", "category": "Junk", "platform": "Console"}, "-1739891535": {"name": "CupCake05", "category": "Junk", "platform": "Console"}, "-1581845891": {"name": "CupCake10", "category": "Junk", "platform": "Console"}, "-1581845886": {"name": "CupCake15", "category": "Junk", "platform": "Console"}, "-1581845858": {"name": "CupCake20", "category": "Junk", "platform": "Console"}, "-1581845853": {"name": "CupCake25", "category": "Junk", "platform": "Console"}, "-1581845825": {"name": "CupCake30", "category": "Junk", "platform": "Console"}, "-1581845820": {"name": "CupCake35", "category": "Junk", "platform": "Console"}, "-1581845792": {"name": "CupCake40", "category": "Junk", "platform": "Console"}, "1402040296": {"name": "Damaged Chestpiece", "category": "Junk", "platform": "Console"}, "-904648741": {"name": "Debug Transmog Plan", "category": "Junk", "platform": "Console"}, "-808688257": {"name": "Event MapVendor Egg", "category": "Junk", "platform": "Console"}, "-2126877461": {"name": "Example Book", "category": "Junk", "platform": "Console"}, "126259831": {"name": "Gold1", "category": "Junk", "platform": "Console"}, "126259832": {"name": "Gold2", "category": "Junk", "platform": "Console"}, "126259833": {"name": "Gold3", "category": "Junk", "platform": "Console"}, "126259834": {"name": "Gold4", "category": "Junk", "platform": "Console"}, "126259835": {"name": "Gold5", "category": "Junk", "platform": "Console"}, "-1165367015": {"name": "Greater Health Potion", "category": "Junk", "platform": "Console"}, "-1916071921": {"name": "Health Potion", "category": "Junk", "platform": "Console"}, "2022931376": {"name": "HealthGlobe01", "category": "Junk", "platform": "Console"}, "2022931377": {"name": "HealthGlobe02", "category": "Junk", "platform": "Console"}, "2022931378": {"name": "HealthGlobe03", "category": "Junk", "platform": "Console"}, "2022931379": {"name": "HealthGlobe04", "category": "Junk", "platform": "Console"}, "2022931380": {"name": "HealthGlobe05", "category": "Junk", "platform": "Console"}, "2022931381": {"name": "HealthGlobe06", "category": "Junk", "platform": "Console"}, "2022931382": {"name": "HealthGlobe07", "category": "Junk", "platform": "Console"}, "2022931383": {"name": "HealthGlobe08", "category": "Junk", "platform": "Console"}, "2022931384": {"name": "HealthGlobe09", "category": "Junk", "platform": "Console"}, "-1962741280": {"name": "HealthGlobe10", "category": "Junk", "platform": "Console"}, "-345952752": {"name": "HealthGlobe100", "category": "Junk", "platform": "Console"}, "-1962741275": {"name": "HealthGlobe15", "category": "Junk", "platform": "Console"}, "-1962741247": {"name": "HealthGlobe20", "category": "Junk", "platform": "Console"}, "-1962741242": {"name": "HealthGlobe25", "category": "Junk", "platform": "Console"}, "-1962741214": {"name": "HealthGlobe30", "category": "Junk", "platform": "Console"}, "-1962741209": {"name": "HealthGlobe35", "category": "Junk", "platform": "Console"}, "-1962741181": {"name": "HealthGlobe40", "category": "Junk", "platform": "Console"}, "-1962741176": {"name": "HealthGlobe45", "category": "Junk", "platform": "Console"}, "-1962741148": {"name": "HealthGlobe50", "category": "Junk", "platform": "Console"}, "-1962741143": {"name": "HealthGlobe55", "category": "Junk", "platform": "Console"}, "-1962741115": {"name": "HealthGlobe60", "category": "Junk", "platform": "Console"}, "-1962741110": {"name": "HealthGlobe65", "category": "Junk", "platform": "Console"}, "-1962741082": {"name": "HealthGlobe70", "category": "Junk", "platform": "Console"}, "-1962741077": {"name": "HealthGlobe75", "category": "Junk", "platform": "Console"}, "-1962741049": {"name": "HealthGlobe80", "category": "Junk", "platform": "Console"}, "-1962741044": {"name": "HealthGlobe85", "category": "Junk", "platform": "Console"}, "-1962741016": {"name": "HealthGlobe90", "category": "Junk", "platform": "Console"}, "-1962741011": {"name": "HealthGlobe95", "category": "Junk", "platform": "Console"}, "-1703070487": {"name": "Heroic Health Potion", "category": "Junk", "platform": "Console"}, "-125073411": {"name": "Junkorama", "category": "Junk", "platform": "Console"}, "-1546488739": {"name": "Lesser Health Potion", "category": "Junk", "platform": "Console"}, "1646125768": {"name": "Major Health Potion", "category": "Junk", "platform": "Console"}, "1646417620": {"name": "Minor Health Potion", "category": "Junk", "platform": "Console"}, "522407589": {"name": "Monk Staff Pvp 001", "category": "Junk", "platform": "Console"}, "522407590": {"name": "Monk Staff Pvp 002", "category": "Junk", "platform": "Console"}, "522407591": {"name": "Monk Staff Pvp 003", "category": "Junk", "platform": "Console"}, "-1483610851": {"name": "Mythic Health Potion", "category": "Junk", "platform": "Console"}, "-125073413": {"name": "OH NOES! JUNK!", "category": "Junk", "platform": "Console"}, "-1596706792": {"name": "Orn Bag 01", "category": "Junk", "platform": "Console"}, "885847747": {"name": "Orn BlizzconPrize", "category": "Junk", "platform": "Console"}, "-125073415": {"name": "Page of Fate", "category": "Junk", "platform": "Console"}, "197999857": {"name": "Page of Useless Scribbling", "category": "Junk", "platform": "Console"}, "1249260787": {"name": "PageOfFateA", "category": "Junk", "platform": "Console"}, "-910124122": {"name": "Power Potion", "category": "Junk", "platform": "Console"}, "1921622363": {"name": "Power-Up Attack Speed", "category": "Junk", "platform": "Console"}, "-859355014": {"name": "Power-Up Cooldown Reset", "category": "Junk", "platform": "Console"}, "11858385": {"name": "Power-Up Damage", "category": "Junk", "platform": "Console"}, "455273651": {"name": "Power-Up Invulnerability", "category": "Junk", "platform": "Console"}, "-977399097": {"name": "Power-Up Stealth", "category": "Junk", "platform": "Console"}, "-1504368109": {"name": "Resplendent Health Potion", "category": "Junk", "platform": "Console"}, "1652778256": {"name": "Runic Health Potion", "category": "Junk", "platform": "Console"}, "-1277860767": {"name": "Sacred Health Potion", "category": "Junk", "platform": "Console"}, "704159709": {"name": "Scholarly Writings", "category": "Junk", "platform": "Console"}, "197999858": {"name": "ScrapPaper 02", "category": "Junk", "platform": "Console"}, "197999859": {"name": "ScrapPaper 03", "category": "Junk", "platform": "Console"}, "197999860": {"name": "ScrapPaper 04", "category": "Junk", "platform": "Console"}, "1462277166": {"name": "Scroll", "category": "Junk", "platform": "Console"}, "146554345": {"name": "Set 001 GiyuasFang", "category": "Junk", "platform": "Console"}, "1653966238": {"name": "Super Health Potion", "category": "Junk", "platform": "Console"}, "1626390053": {"name": "Talisman", "category": "Junk", "platform": "Console"}, "761573026": {"name": "The Black Rock Ledger, Page 15", "category": "Junk", "platform": "Console"}, "761573027": {"name": "The Black Rock Ledger, Page 16", "category": "Junk", "platform": "Console"}, "761573028": {"name": "The Black Rock Ledger, Page 23", "category": "Junk", "platform": "Console"}, "761573024": {"name": "The Black Rock Ledger, Page 4", "category": "Junk", "platform": "Console"}, "761573029": {"name": "The Black Rock Ledger, Page 42", "category": "Junk", "platform": "Console"}, "761573025": {"name": "The Black Rock Ledger, Page 8", "category": "Junk", "platform": "Console"}, "-2007738575": {"name": "Town Portal Stone 2", "category": "Junk", "platform": "Console"}, "-125073412": {"name": "Trunk Junk", "category": "Junk", "platform": "Console"}, "177825848": {"name": "cos_pennant_01 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825849": {"name": "cos_pennant_02 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825850": {"name": "cos_pennant_03 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825851": {"name": "cos_pennant_04 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825852": {"name": "cos_pennant_05 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-1562301750": {"name": "cos_pennant_p2_Anniversary (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "127020830": {"name": "cos_pennant_p2_Heroes (Patch 2.2.0)", "category": "Junk", "platform": "Console"}}, "Keys": {"-1088058180": {"name": "Key of Destruction", "category": "Keys", "platform": "Console"}, "113551449": {"name": "Key of Evil", "category": "Keys", "platform": "Console"}, "-1207737543": {"name": "Key of Gluttony", "category": "Keys", "platform": "Console"}, "1064300938": {"name": "Key of Hate", "category": "Keys", "platform": "Console"}, "-143133978": {"name": "Key of Terror", "category": "Keys", "platform": "Console"}, "2050794135": {"name": "Key of War", "category": "Keys", "platform": "Console"}}, "Keystones": {"1955086538": {"name": "Greater Rift Keystone Rank 02 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086539": {"name": "Greater Rift Keystone Rank 03 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086540": {"name": "Greater Rift Keystone Rank 04 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086541": {"name": "Greater Rift Keystone Rank 05 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086542": {"name": "Greater Rift Keystone Rank 06 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086543": {"name": "Greater Rift Keystone Rank 07 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086544": {"name": "Greater Rift Keystone Rank 08 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086545": {"name": "Greater Rift Keystone Rank 09 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346329": {"name": "Greater Rift Keystone Rank 10 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1214538391": {"name": "Greater Rift Keystone Rank 100 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346330": {"name": "Greater Rift Keystone Rank 11 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346331": {"name": "Greater Rift Keystone Rank 12 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346332": {"name": "Greater Rift Keystone Rank 13 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346333": {"name": "Greater Rift Keystone Rank 14 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346334": {"name": "Greater Rift Keystone Rank 15 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346335": {"name": "Greater Rift Keystone Rank 16 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346336": {"name": "Greater Rift Keystone Rank 17 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346337": {"name": "Greater Rift Keystone Rank 18 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346338": {"name": "Greater Rift Keystone Rank 19 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346362": {"name": "Greater Rift Keystone Rank 20 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346363": {"name": "Greater Rift Keystone Rank 21 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346364": {"name": "Greater Rift Keystone Rank 22 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346365": {"name": "Greater Rift Keystone Rank 23 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346366": {"name": "Greater Rift Keystone Rank 24 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346367": {"name": "Greater Rift Keystone Rank 25 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346368": {"name": "Greater Rift Keystone Rank 26 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346369": {"name": "Greater Rift Keystone Rank 27 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346370": {"name": "Greater Rift Keystone Rank 28 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346371": {"name": "Greater Rift Keystone Rank 29 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346395": {"name": "Greater Rift Keystone Rank 30 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346396": {"name": "Greater Rift Keystone Rank 31 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346397": {"name": "Greater Rift Keystone Rank 32 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346398": {"name": "Greater Rift Keystone Rank 33 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346399": {"name": "Greater Rift Keystone Rank 34 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346400": {"name": "Greater Rift Keystone Rank 35 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346401": {"name": "Greater Rift Keystone Rank 36 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346402": {"name": "Greater Rift Keystone Rank 37 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346403": {"name": "Greater Rift Keystone Rank 38 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346404": {"name": "Greater Rift Keystone Rank 39 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346428": {"name": "Greater Rift Keystone Rank 40 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346429": {"name": "Greater Rift Keystone Rank 41 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346430": {"name": "Greater Rift Keystone Rank 42 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346431": {"name": "Greater Rift Keystone Rank 43 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346432": {"name": "Greater Rift Keystone Rank 44 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346433": {"name": "Greater Rift Keystone Rank 45 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346434": {"name": "Greater Rift Keystone Rank 46 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346435": {"name": "Greater Rift Keystone Rank 47 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346436": {"name": "Greater Rift Keystone Rank 48 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346437": {"name": "Greater Rift Keystone Rank 49 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346461": {"name": "Greater Rift Keystone Rank 50 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346462": {"name": "Greater Rift Keystone Rank 51 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346463": {"name": "Greater Rift Keystone Rank 52 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346464": {"name": "Greater Rift Keystone Rank 53 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346465": {"name": "Greater Rift Keystone Rank 54 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346466": {"name": "Greater Rift Keystone Rank 55 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346467": {"name": "Greater Rift Keystone Rank 56 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346468": {"name": "Greater Rift Keystone Rank 57 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346469": {"name": "Greater Rift Keystone Rank 58 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346470": {"name": "Greater Rift Keystone Rank 59 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346494": {"name": "Greater Rift Keystone Rank 60 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346495": {"name": "Greater Rift Keystone Rank 61 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346496": {"name": "Greater Rift Keystone Rank 62 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346497": {"name": "Greater Rift Keystone Rank 63 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346498": {"name": "Greater Rift Keystone Rank 64 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346499": {"name": "Greater Rift Keystone Rank 65 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346500": {"name": "Greater Rift Keystone Rank 66 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346501": {"name": "Greater Rift Keystone Rank 67 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346502": {"name": "Greater Rift Keystone Rank 68 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346503": {"name": "Greater Rift Keystone Rank 69 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346527": {"name": "Greater Rift Keystone Rank 70 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346528": {"name": "Greater Rift Keystone Rank 71 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346529": {"name": "Greater Rift Keystone Rank 72 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346530": {"name": "Greater Rift Keystone Rank 73 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346531": {"name": "Greater Rift Keystone Rank 74 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346532": {"name": "Greater Rift Keystone Rank 75 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346533": {"name": "Greater Rift Keystone Rank 76 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346534": {"name": "Greater Rift Keystone Rank 77 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346535": {"name": "Greater Rift Keystone Rank 78 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346536": {"name": "Greater Rift Keystone Rank 79 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346560": {"name": "Greater Rift Keystone Rank 80 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346561": {"name": "Greater Rift Keystone Rank 81 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346562": {"name": "Greater Rift Keystone Rank 82 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346563": {"name": "Greater Rift Keystone Rank 83 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346564": {"name": "Greater Rift Keystone Rank 84 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346565": {"name": "Greater Rift Keystone Rank 85 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346566": {"name": "Greater Rift Keystone Rank 86 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346567": {"name": "Greater Rift Keystone Rank 87 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346568": {"name": "Greater Rift Keystone Rank 88 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346569": {"name": "Greater Rift Keystone Rank 89 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346593": {"name": "Greater Rift Keystone Rank 90 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346594": {"name": "Greater Rift Keystone Rank 91 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346595": {"name": "Greater Rift Keystone Rank 92 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346596": {"name": "Greater Rift Keystone Rank 93 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346597": {"name": "Greater Rift Keystone Rank 94 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346598": {"name": "Greater Rift Keystone Rank 95 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346599": {"name": "Greater Rift Keystone Rank 96 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346600": {"name": "Greater Rift Keystone Rank 97 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346601": {"name": "Greater Rift Keystone Rank 98 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346602": {"name": "Greater Rift Keystone Rank 99 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086536": {"name": "Keystone of Trials (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1698136228": {"name": "Rift Keys", "category": "Keystones", "platform": "Console"}}, "Lore": {"-1194932976": {"name": "A2 Oasis KamyrsOrdersTwo", "category": "Lore", "platform": "Console"}, "192275875": {"name": "A2 TemplarBackstory 3 Landus's Diary", "category": "Lore", "platform": "Console"}, "-1883980626": {"name": "A3 Battlefields Supply WagonDiaries", "category": "Lore", "platform": "Console"}, "1740306889": {"name": "A4 Hub OldCouple 1", "category": "Lore", "platform": "Console"}, "-1764974213": {"name": "Adria ZoltunKulle2", "category": "Lore", "platform": "Console"}, "103300821": {"name": "Adria: Adria's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-776544373": {"name": "Adria: Adria's Journal, Part 2", "category": "Lore", "platform": "Console"}, "133385135": {"name": "Adria: Adria's Journal, Part 3", "category": "Lore", "platform": "Console"}, "133390039": {"name": "Adria: Adria's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1890330185": {"name": "Adria: Adria's Journal, Part 5", "category": "Lore", "platform": "Console"}, "127066864": {"name": "Adria: Adria's Journal, Part 6", "category": "Lore", "platform": "Console"}, "733368986": {"name": "Adria: Adria's Journal, Part 7", "category": "Lore", "platform": "Console"}, "100959118": {"name": "Adria: Adria's Journal, Part 8", "category": "Lore", "platform": "Console"}, "133600747": {"name": "Adria: Adria's Journal, Part 9", "category": "Lore", "platform": "Console"}, "133313247": {"name": "Adria: Adria's Note", "category": "Lore", "platform": "Console"}, "954251807": {"name": "Adria: Adria's Purpose", "category": "Lore", "platform": "Console"}, "900358318": {"name": "AdventureMode: A New Era", "category": "Lore", "platform": "Console"}, "-282286736": {"name": "AdventureMode: An Eternity of Agony", "category": "Lore", "platform": "Console"}, "1375431349": {"name": "AdventureMode: Impossibilities", "category": "Lore", "platform": "Console"}, "-1315225766": {"name": "AdventureMode: The Nephalem", "category": "Lore", "platform": "Console"}, "501220619": {"name": "AngirisCouncil: The Angiris Council", "category": "Lore", "platform": "Console"}, "-1383924340": {"name": "AngirisCouncil: The Archangel Auriel", "category": "Lore", "platform": "Console"}, "260686328": {"name": "AngirisCouncil: The Archangel Imperius", "category": "Lore", "platform": "Console"}, "397935128": {"name": "AngirisCouncil: The Archangel Itherael", "category": "Lore", "platform": "Console"}, "478898578": {"name": "AngirisCouncil: The Archangel Malthael", "category": "Lore", "platform": "Console"}, "-635616901": {"name": "AngirisCouncil: The Archangel Tyrael", "category": "Lore", "platform": "Console"}, "-164029999": {"name": "Aqueducts: The Desert Aqueducts, Part 1", "category": "Lore", "platform": "Console"}, "-164029998": {"name": "Aqueducts: The Desert Aqueducts, Part 2", "category": "Lore", "platform": "Console"}, "-714930281": {"name": "Armorer: Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "-1385743634": {"name": "Azmodan: Orders from Azmodan, Part 1", "category": "Lore", "platform": "Console"}, "-1385743633": {"name": "Azmodan: Orders from Azmodan, Part 2", "category": "Lore", "platform": "Console"}, "-1385743632": {"name": "Azmodan: Orders from Azmodan, Part 3", "category": "Lore", "platform": "Console"}, "-1385743631": {"name": "Azmodan: Orders from Azmodan, Part 4", "category": "Lore", "platform": "Console"}, "-1385743630": {"name": "Azmodan: Orders from Azmodan, Part 5", "category": "Lore", "platform": "Console"}, "-1385743629": {"name": "Azmodan: Orders from Azmodan, Part 6", "category": "Lore", "platform": "Console"}, "-1312231117": {"name": "Belial: Deceivers' Orders, Part 1", "category": "Lore", "platform": "Console"}, "-1346161479": {"name": "Belial: Deceivers' Orders, Part 2", "category": "Lore", "platform": "Console"}, "-661262942": {"name": "Belial: Deceivers' Orders, Part 3", "category": "Lore", "platform": "Console"}, "-978510227": {"name": "Belial: Guard's Orders", "category": "Lore", "platform": "Console"}, "1488385291": {"name": "Belial: Missive to Maghda, Part 1", "category": "Lore", "platform": "Console"}, "1488385292": {"name": "Belial: Missive to Maghda, Part 2", "category": "Lore", "platform": "Console"}, "10458238": {"name": "Belial: Proclamation from the Imperial Guard", "category": "Lore", "platform": "Console"}, "621163016": {"name": "Bestiary: Anarch", "category": "Lore", "platform": "Console"}, "515122494": {"name": "Bestiary: Armored Destroyer", "category": "Lore", "platform": "Console"}, "-1478953705": {"name": "Bestiary: Barbed Lurker", "category": "Lore", "platform": "Console"}, "1467646658": {"name": "Bestiary: Beast", "category": "Lore", "platform": "Console"}, "231471423": {"name": "Bestiary: Bile Crawler", "category": "Lore", "platform": "Console"}, "1675636673": {"name": "Bestiary: Blood Clan Khazra", "category": "Lore", "platform": "Console"}, "1675805102": {"name": "Bestiary: Blood Hawk", "category": "Lore", "platform": "Console"}, "2132231168": {"name": "Bestiary: Bogan Trapper", "category": "Lore", "platform": "Console"}, "661688183": {"name": "Bestiary: Boggit", "category": "Lore", "platform": "Console"}, "-1697636392": {"name": "Bestiary: Carrion Bat", "category": "Lore", "platform": "Console"}, "-186990405": {"name": "Bestiary: Carrion Nest", "category": "Lore", "platform": "Console"}, "1864365917": {"name": "Bestiary: Colossal Golgor", "category": "Lore", "platform": "Console"}, "-899331059": {"name": "Bestiary: Corpse Raiser", "category": "Lore", "platform": "Console"}, "-563018536": {"name": "Bestiary: Dark Berserker", "category": "Lore", "platform": "Console"}, "-1824883589": {"name": "Bestiary: Dark Cultist", "category": "Lore", "platform": "Console"}, "1971053797": {"name": "Bestiary: Dark Vessel", "category": "Lore", "platform": "Console"}, "-985860913": {"name": "Bestiary: Death Maiden", "category": "Lore", "platform": "Console"}, "610441837": {"name": "Bestiary: Deceivers", "category": "Lore", "platform": "Console"}, "-1937284463": {"name": "Bestiary: Demon Trooper", "category": "Lore", "platform": "Console"}, "478100232": {"name": "Bestiary: Demonic Hell Bearer", "category": "Lore", "platform": "Console"}, "-140849528": {"name": "Bestiary: Demonic Hellflyer", "category": "Lore", "platform": "Console"}, "2144349771": {"name": "Bestiary: Demonic Tremor", "category": "Lore", "platform": "Console"}, "1641498900": {"name": "Bestiary: Dune Dervish", "category": "Lore", "platform": "Console"}, "1184767076": {"name": "Bestiary: Dune Thresher", "category": "Lore", "platform": "Console"}, "-525114375": {"name": "Bestiary: Dust Imp", "category": "Lore", "platform": "Console"}, "-1086668012": {"name": "Bestiary: Electric Eel", "category": "Lore", "platform": "Console"}, "90729293": {"name": "Bestiary: Enraged Phantasm", "category": "Lore", "platform": "Console"}, "-1878606908": {"name": "Bestiary: Enslaved Nightmare", "category": "Lore", "platform": "Console"}, "789563798": {"name": "Bestiary: Exarch", "category": "Lore", "platform": "Console"}, "-1299022938": {"name": "Bestiary: Executioner", "category": "Lore", "platform": "Console"}, "1389417324": {"name": "Bestiary: Exorcist", "category": "Lore", "platform": "Console"}, "163638005": {"name": "Bestiary: Fallen Grunt", "category": "Lore", "platform": "Console"}, "84174677": {"name": "Bestiary: Fallen Lunatic", "category": "Lore", "platform": "Console"}, "1562132029": {"name": "Bestiary: Fallen Shaman", "category": "Lore", "platform": "Console"}, "-990665261": {"name": "Bestiary: Flesh Gorger", "category": "Lore", "platform": "Console"}, "-944408897": {"name": "Bestiary: Flesh Hurler", "category": "Lore", "platform": "Console"}, "-529946523": {"name": "Bestiary: Flesh Shaman", "category": "Lore", "platform": "Console"}, "1473699320": {"name": "Bestiary: Ghost", "category": "Lore", "platform": "Console"}, "1473699378": {"name": "Bestiary: Ghoul", "category": "Lore", "platform": "Console"}, "1067328402": {"name": "Bestiary: Grotesque", "category": "Lore", "platform": "Console"}, "-288964962": {"name": "Bestiary: Hellion", "category": "Lore", "platform": "Console"}, "-675600988": {"name": "Bestiary: Herald of Pestilence", "category": "Lore", "platform": "Console"}, "-1778975775": {"name": "Bestiary: Hound Pack Leader", "category": "Lore", "platform": "Console"}, "-1864253371": {"name": "Bestiary: Hulking Phasebeast", "category": "Lore", "platform": "Console"}, "1270376265": {"name": "Bestiary: Imp", "category": "Lore", "platform": "Console"}, "1543483412": {"name": "Bestiary: Khazra", "category": "Lore", "platform": "Console"}, "1080209708": {"name": "Bestiary: Khazra Shaman", "category": "Lore", "platform": "Console"}, "1574383663": {"name": "Bestiary: Lacuni", "category": "Lore", "platform": "Console"}, "1277879248": {"name": "Bestiary: Maggot Brood", "category": "Lore", "platform": "Console"}, "-1289421300": {"name": "Bestiary: Primordial Scavenger", "category": "Lore", "platform": "Console"}, "-683087584": {"name": "Bestiary: Quill Fiend", "category": "Lore", "platform": "Console"}, "2123300624": {"name": "Bestiary: Revenant Soldier", "category": "Lore", "platform": "Console"}, "2139220569": {"name": "Bestiary: Risen Dead", "category": "Lore", "platform": "Console"}, "-286364985": {"name": "Bestiary: Rockworm", "category": "Lore", "platform": "Console"}, "507308136": {"name": "Bestiary: Sand Dweller", "category": "Lore", "platform": "Console"}, "-1096104684": {"name": "Bestiary: Sand Wasp", "category": "Lore", "platform": "Console"}, "1312554887": {"name": "Bestiary: Scarab", "category": "Lore", "platform": "Console"}, "-1399846223": {"name": "Bestiary: Scavenger", "category": "Lore", "platform": "Console"}, "2067382477": {"name": "Bestiary: Scavenging Tunneler", "category": "Lore", "platform": "Console"}, "-458569087": {"name": "Bestiary: Scouring Charger", "category": "Lore", "platform": "Console"}, "-1529207830": {"name": "Bestiary: Shadow Vermin", "category": "Lore", "platform": "Console"}, "-1715924548": {"name": "Bestiary: Shadow of Death", "category": "Lore", "platform": "Console"}, "1905172061": {"name": "Bestiary: Shrieking Terror", "category": "Lore", "platform": "Console"}, "56567324": {"name": "Bestiary: Siegebreaker Assault Beast", "category": "Lore", "platform": "Console"}, "-387707041": {"name": "Bestiary: Skeletal Beast", "category": "Lore", "platform": "Console"}, "494193920": {"name": "Bestiary: Skeletal Crawler", "category": "Lore", "platform": "Console"}, "-313234093": {"name": "Bestiary: Skeletal Guardian", "category": "Lore", "platform": "Console"}, "-1409684360": {"name": "Bestiary: Skeleton", "category": "Lore", "platform": "Console"}, "1170383240": {"name": "Bestiary: Soul Ripper", "category": "Lore", "platform": "Console"}, "1866317050": {"name": "Bestiary: Spider", "category": "Lore", "platform": "Console"}, "564441124": {"name": "Bestiary: Spiderling", "category": "Lore", "platform": "Console"}, "-330757856": {"name": "Bestiary: Stinging Swarm", "category": "Lore", "platform": "Console"}, "-458677543": {"name": "Bestiary: Subjugator", "category": "Lore", "platform": "Console"}, "-1468295040": {"name": "Bestiary: Succubus", "category": "Lore", "platform": "Console"}, "-513840200": {"name": "Bestiary: Summoned Archer", "category": "Lore", "platform": "Console"}, "166255055": {"name": "Bestiary: Summoned Shield Guard", "category": "Lore", "platform": "Console"}, "1887856949": {"name": "Bestiary: Summoned Soldier", "category": "Lore", "platform": "Console"}, "920539156": {"name": "Bestiary: Summoner of the Dead", "category": "Lore", "platform": "Console"}, "166186064": {"name": "Bestiary: Terror Demon", "category": "Lore", "platform": "Console"}, "-1551452867": {"name": "Bestiary: The Accursed", "category": "Lore", "platform": "Console"}, "1613832402": {"name": "Bestiary: The Mallet Lords", "category": "Lore", "platform": "Console"}, "1481069442": {"name": "Bestiary: The Morlu", "category": "Lore", "platform": "Console"}, "1727215776": {"name": "Bestiary: The Oppressors", "category": "Lore", "platform": "Console"}, "-1569107231": {"name": "Bestiary: Tormented Stinger", "category": "Lore", "platform": "Console"}, "692217017": {"name": "Bestiary: Treasure Goblin", "category": "Lore", "platform": "Console"}, "1112087602": {"name": "Bestiary: Tusked Bogan", "category": "Lore", "platform": "Console"}, "1695981553": {"name": "Bestiary: Unburied", "category": "Lore", "platform": "Console"}, "181747316": {"name": "Bestiary: Vicious Hound", "category": "Lore", "platform": "Console"}, "191466402": {"name": "Bestiary: Vile Bat", "category": "Lore", "platform": "Console"}, "1295465786": {"name": "Bestiary: Warscarred Marauder", "category": "Lore", "platform": "Console"}, "-1568007631": {"name": "Bestiary: Warscarred Ravager", "category": "Lore", "platform": "Console"}, "1809929374": {"name": "Bestiary: Winged Assassin", "category": "Lore", "platform": "Console"}, "-1414985342": {"name": "Bestiary: Winged Talus", "category": "Lore", "platform": "Console"}, "1562746110": {"name": "Bestiary: Withermoth", "category": "Lore", "platform": "Console"}, "1892963547": {"name": "Bestiary: Wood Wraith", "category": "Lore", "platform": "Console"}, "1470131000": {"name": "Bestiary: Wretched Mother", "category": "Lore", "platform": "Console"}, "2033922302": {"name": "Butcher: Butcher", "category": "Lore", "platform": "Console"}, "3246582303": {"name": "Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "4058000945": {"name": "Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "554362535": {"name": "Cain: Deckard Cain's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1114094521": {"name": "Cain: Deckard Cain's Journal, Part 2", "category": "Lore", "platform": "Console"}, "828022511": {"name": "Caldeum: An Abridged History of Caldeum, Part 1", "category": "Lore", "platform": "Console"}, "828022512": {"name": "Caldeum: An Abridged History of Caldeum, Part 2", "category": "Lore", "platform": "Console"}, "828022513": {"name": "Caldeum: An Abridged History of Caldeum, Part 3", "category": "Lore", "platform": "Console"}, "828022514": {"name": "Caldeum: An Abridged History of Caldeum, Part 4", "category": "Lore", "platform": "Console"}, "828022515": {"name": "Caldeum: An Abridged History of Caldeum, Part 5", "category": "Lore", "platform": "Console"}, "828022516": {"name": "Caldeum: An Abridged History of Caldeum, Part 6", "category": "Lore", "platform": "Console"}, "344927641": {"name": "CaliphateSardar: The Musings of Caliphate Sardar", "category": "Lore", "platform": "Console"}, "-1106917318": {"name": "CampCultist: The Feared Hero", "category": "Lore", "platform": "Console"}, "-668215174": {"name": "CellarMadman: The Ravings of a Deranged Mind", "category": "Lore", "platform": "Console"}, "-1518383148": {"name": "CemeteryCrypts: Gravedigger's Log", "category": "Lore", "platform": "Console"}, "-727194820": {"name": "Challenge: Nephalem Rifts", "category": "Lore", "platform": "Console"}, "2125283571": {"name": "Crusader: The Crusaders, Part 1", "category": "Lore", "platform": "Console"}, "2125283572": {"name": "Crusader: The Crusaders, Part 2", "category": "Lore", "platform": "Console"}, "2125283573": {"name": "Crusader: The Crusaders, Part 3", "category": "Lore", "platform": "Console"}, "2125283574": {"name": "Crusader: The Crusaders, Part 4", "category": "Lore", "platform": "Console"}, "2125283575": {"name": "Crusader: The Crusaders, Part 5", "category": "Lore", "platform": "Console"}, "2125283576": {"name": "Crusader: The Crusaders, Part 6", "category": "Lore", "platform": "Console"}, "2125283577": {"name": "Crusader: The Crusaders, Part 7", "category": "Lore", "platform": "Console"}, "2125283578": {"name": "Crusader: The Crusaders, Part 8", "category": "Lore", "platform": "Console"}, "2125283579": {"name": "Crusader: The Crusaders, Part 9", "category": "Lore", "platform": "Console"}, "-186854830": {"name": "CultCrown: Cultist Orders", "category": "Lore", "platform": "Console"}, "4108112466": {"name": "Cultist Orders", "category": "Lore", "platform": "Console"}, "504852499": {"name": "CurioVendor: Adenah's Jottings", "category": "Lore", "platform": "Console"}, "-1717171528": {"name": "Cydaea: Cydaea, the Maiden of Lust", "category": "Lore", "platform": "Console"}, "1958060101": {"name": "DahlgurOasis: The Dahlgur Oasis", "category": "Lore", "platform": "Console"}, "-1010870335": {"name": "DarkZealot: Report from Wortham", "category": "Lore", "platform": "Console"}, "-819413474": {"name": "Deserter: Deserter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-819413473": {"name": "Deserter: Deserter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-819413472": {"name": "Deserter: Deserter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-819413471": {"name": "Deserter: Deserter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-819413470": {"name": "Deserter: Deserter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "1121720780": {"name": "DesolateSands: On the Desolate Sands, Part 1", "category": "Lore", "platform": "Console"}, "1121720781": {"name": "DesolateSands: On the Desolate Sands, Part 2", "category": "Lore", "platform": "Console"}, "1121720782": {"name": "DesolateSands: On the Desolate Sands, Part 3", "category": "Lore", "platform": "Console"}, "2388677118": {"name": "Despina's Journal", "category": "Lore", "platform": "Console"}, "1244727565": {"name": "DevilsHand: Implements of the Dark Coven", "category": "Lore", "platform": "Console"}, "1244727564": {"name": "DevilsHand: The Black King's Reign", "category": "Lore", "platform": "Console"}, "1244727563": {"name": "DevilsHand: The Covenant's Search", "category": "Lore", "platform": "Console"}, "172363859": {"name": "DoomedWoman: The Horrible Secret", "category": "Lore", "platform": "Console"}, "-1577589110": {"name": "Enchantress: Eirena's Journal", "category": "Lore", "platform": "Console"}, "2168089835": {"name": "Example Book", "category": "Lore", "platform": "Console"}, "1850500833": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 1", "category": "Lore", "platform": "Console"}, "1850500834": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 2", "category": "Lore", "platform": "Console"}, "1850500835": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 3", "category": "Lore", "platform": "Console"}, "1850500836": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 4", "category": "Lore", "platform": "Console"}, "1850500837": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 5", "category": "Lore", "platform": "Console"}, "1814333430": {"name": "FieldsofMisery: Tristram Fields", "category": "Lore", "platform": "Console"}, "-821793924": {"name": "Ghom: Ghom, the Lord of Gluttony", "category": "Lore", "platform": "Console"}, "-681952308": {"name": "GluttonysLog: Ghom's Log", "category": "Lore", "platform": "Console"}, "1895762819": {"name": "GoatmenHunter: Khazra Heads Wanted", "category": "Lore", "platform": "Console"}, "1895762820": {"name": "GoatmenHunter: Researching the Khazra", "category": "Lore", "platform": "Console"}, "1895762821": {"name": "GoatmenHunter: The Khazra Massacre", "category": "Lore", "platform": "Console"}, "-1085616825": {"name": "Halls_of_Agony: Command from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "-1085616824": {"name": "Halls_of_Agony: Reply from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "721065374": {"name": "HangingTree: The Hanging Tree", "category": "Lore", "platform": "Console"}, "4006002334": {"name": "Hellion", "category": "Lore", "platform": "Console"}, "1555542539": {"name": "Hermit_Caves: Hermit's Ravings", "category": "Lore", "platform": "Console"}, "-578368437": {"name": "HexMaze: Melaina's Memory", "category": "Lore", "platform": "Console"}, "-578368438": {"name": "HexMaze: Raissa's Memory", "category": "Lore", "platform": "Console"}, "-578368439": {"name": "HexMaze: Sibyl's Thoughts", "category": "Lore", "platform": "Console"}, "2145056291": {"name": "Highlands: The Highlands", "category": "Lore", "platform": "Console"}, "174686246": {"name": "HuntersJournal: Hunter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "174686247": {"name": "HuntersJournal: Hunter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "174686248": {"name": "HuntersJournal: Hunter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "174686249": {"name": "HuntersJournal: Hunter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "174686250": {"name": "HuntersJournal: Hunter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "174686251": {"name": "HuntersJournal: Hunter's Journal, Part 6", "category": "Lore", "platform": "Console"}, "-799754755": {"name": "Inarius: The Creation of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "-799754754": {"name": "Inarius: The Creation of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "-799754753": {"name": "Inarius: The Creation of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "-799754752": {"name": "Inarius: The Creation of Sanctuary, Part 4", "category": "Lore", "platform": "Console"}, "194883964": {"name": "Inarius: The Testament of Inarius, Part 1", "category": "Lore", "platform": "Console"}, "194883965": {"name": "Inarius: The Testament of Inarius, Part 2", "category": "Lore", "platform": "Console"}, "194883966": {"name": "Inarius: The Testament of Inarius, Part 3", "category": "Lore", "platform": "Console"}, "194883967": {"name": "Inarius: The Testament of Inarius, Part 4", "category": "Lore", "platform": "Console"}, "194883968": {"name": "Inarius: The Testament of Inarius, Part 5", "category": "Lore", "platform": "Console"}, "194883969": {"name": "Inarius: The Testament of Inarius, Part 6", "category": "Lore", "platform": "Console"}, "194883970": {"name": "Inarius: The Testament of Inarius, Part 7", "category": "Lore", "platform": "Console"}, "-1346370762": {"name": "Izual: Izual's Descent", "category": "Lore", "platform": "Console"}, "28868489": {"name": "Jeweler: Journal of Covetous Shen", "category": "Lore", "platform": "Console"}, "1221720352": {"name": "Jeweler: The Legend of Zei the Trickster", "category": "Lore", "platform": "Console"}, "-329801970": {"name": "Kala: Kala's Poem", "category": "Lore", "platform": "Console"}, "-355886665": {"name": "KeepHistory: The History of Bastion's Keep", "category": "Lore", "platform": "Console"}, "815737414": {"name": "KhanDakab: Last Will of Khan Dakab", "category": "Lore", "platform": "Console"}, "378673143": {"name": "KidVendor: Larra's Diary", "category": "Lore", "platform": "Console"}, "-1755180605": {"name": "Kingsport: Kingsport Bill", "category": "Lore", "platform": "Console"}, "-1156197446": {"name": "Kulle: Kulle's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1156197445": {"name": "Kulle: Kulle's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1156197444": {"name": "Kulle: Kulle's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-1156197443": {"name": "Kulle: Kulle's Journal, Part 4", "category": "Lore", "platform": "Console"}, "2698411174": {"name": "Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "3758420764": {"name": "Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "3768800974": {"name": "Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "3768800975": {"name": "Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "3768800976": {"name": "Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "3768800977": {"name": "Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "-1596556122": {"name": "Lachdanan: Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "-536546532": {"name": "Lachdanan: Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "-526166322": {"name": "Lachdanan: Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "-526166321": {"name": "Lachdanan: Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "-526166320": {"name": "Lachdanan: Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "-526166319": {"name": "Lachdanan: Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "1554177638": {"name": "LastAncient: The Last of the Ancients", "category": "Lore", "platform": "Console"}, "1905436671": {"name": "Lazarus: A Page from Lazarus's Grimoire", "category": "Lore", "platform": "Console"}, "3272862989": {"name": "Leah's Journal, Part 1", "category": "Lore", "platform": "Console"}, "3272868741": {"name": "Leah's Journal, Part 2", "category": "Lore", "platform": "Console"}, "3625638211": {"name": "Leah's Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922967": {"name": "Leah: Leah's Caldeum Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922968": {"name": "Leah: Leah's Caldeum Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922969": {"name": "Leah: Leah's Caldeum Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922970": {"name": "Leah: Leah's Caldeum Journal, Part 4", "category": "Lore", "platform": "Console"}, "891922971": {"name": "Leah: Leah's Caldeum Journal, Part 5", "category": "Lore", "platform": "Console"}, "891922972": {"name": "Leah: Leah's Keep Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922973": {"name": "Leah: Leah's Keep Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922974": {"name": "Leah: Leah's Keep Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922975": {"name": "Leah: Leah's Keep Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1022104307": {"name": "Leah: Leah's Tristram Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1022098555": {"name": "Leah: Leah's Tristram Journal, Part 2", "category": "Lore", "platform": "Console"}, "-669329085": {"name": "Leah: Leah's Tristram Journal, Part 3", "category": "Lore", "platform": "Console"}, "629974535": {"name": "Leah: Leah's Tristram Journal, Part 4", "category": "Lore", "platform": "Console"}, "629968021": {"name": "Leah: Leah's Tristram Journal, Part 5", "category": "Lore", "platform": "Console"}, "-1022100097": {"name": "Leah: Leah's Tristram Journal, Part 6", "category": "Lore", "platform": "Console"}, "-670618452": {"name": "Leah: Leah's Tristram Journal, Part 7", "category": "Lore", "platform": "Console"}, "2951326394": {"name": "Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1091428479": {"name": "Leoric: A Prisoner's Journal", "category": "Lore", "platform": "Console"}, "-1343640902": {"name": "Leoric: Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1561062717": {"name": "Leoric: Leoric's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1561062718": {"name": "Leoric: Leoric's Journal, Part 2", "category": "Lore", "platform": "Console"}, "1561062719": {"name": "Leoric: Leoric's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561062720": {"name": "Leoric: Leoric's Journal, Part 4", "category": "Lore", "platform": "Console"}, "1561062721": {"name": "Leoric: Leoric's Journal, Part 5", "category": "Lore", "platform": "Console"}, "342313869": {"name": "Leoric: Leoric's Relic", "category": "Lore", "platform": "Console"}, "164674838": {"name": "Leoric: The Death of King Leoric", "category": "Lore", "platform": "Console"}, "82422929": {"name": "Leoric: Torn Letter", "category": "Lore", "platform": "Console"}, "82422930": {"name": "Leoric: Torn Letter's Response", "category": "Lore", "platform": "Console"}, "1354656263": {"name": "Lilith: The Writings of Lilith, Part 1", "category": "Lore", "platform": "Console"}, "1354656264": {"name": "Lilith: The Writings of Lilith, Part 2", "category": "Lore", "platform": "Console"}, "1354656265": {"name": "Lilith: The Writings of Lilith, Part 3", "category": "Lore", "platform": "Console"}, "1354656266": {"name": "Lilith: The Writings of Lilith, Part 4", "category": "Lore", "platform": "Console"}, "2145180345": {"name": "LordofFools: Lord Kertis's Journal", "category": "Lore", "platform": "Console"}, "704654350": {"name": "LordsofHell: Andariel, the Maiden of Anguish", "category": "Lore", "platform": "Console"}, "-408914888": {"name": "LordsofHell: Azmodan, the Lord of Sin", "category": "Lore", "platform": "Console"}, "-1390665602": {"name": "LordsofHell: Baal, the Lord of Destruction", "category": "Lore", "platform": "Console"}, "1693753943": {"name": "LordsofHell: Belial, the Lord of Lies", "category": "Lore", "platform": "Console"}, "1776365849": {"name": "LordsofHell: Diablo, the Lord of Terror", "category": "Lore", "platform": "Console"}, "1791215219": {"name": "LordsofHell: Duriel, the Lord of Pain", "category": "Lore", "platform": "Console"}, "-1530801161": {"name": "LordsofHell: Mephisto, the Lord of Hatred", "category": "Lore", "platform": "Console"}, "1361465018": {"name": "LordsofHell: The Seven Lords of Hell", "category": "Lore", "platform": "Console"}, "1775133212": {"name": "Lore CainLetter", "category": "Lore", "platform": "Console"}, "1615247495": {"name": "Lore Catacombs NephDefenseSystem", "category": "Lore", "platform": "Console"}, "-1084060684": {"name": "Lore Festering CryptOfTheAncients", "category": "Lore", "platform": "Console"}, "108864625": {"name": "Lore Festering DrownedTemple", "category": "Lore", "platform": "Console"}, "-740914034": {"name": "Lore Festering WarriorsRest", "category": "Lore", "platform": "Console"}, "2011207568": {"name": "Lore X1 Bog Ideation AdriaSpikeChest", "category": "Lore", "platform": "Console"}, "216459655": {"name": "Lore X1 Graveyard Azthar", "category": "Lore", "platform": "Console"}, "-827657709": {"name": "Lore X1 Westm Legendary Drop", "category": "Lore", "platform": "Console"}, "-1004685329": {"name": "Lore x1 MysticIntro1", "category": "Lore", "platform": "Console"}, "-1004685328": {"name": "Lore x1 MysticIntro2", "category": "Lore", "platform": "Console"}, "-2124310248": {"name": "Lore_p2_DateDungeon_CovenPlans (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "-1307619936": {"name": "Lore_p2_ScoundrelEvent02_SimonNote (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "1390356236": {"name": "LostAngel: The Lost Warrior", "category": "Lore", "platform": "Console"}, "1487246296": {"name": "LoveLetter: A Love Letter", "category": "Lore", "platform": "Console"}, "-184131088": {"name": "MaghdaManor: Orders from Maghda", "category": "Lore", "platform": "Console"}, "18980873": {"name": "Malthael: The Path of Wisdom, Part 1", "category": "Lore", "platform": "Console"}, "18980874": {"name": "Malthael: The Path of Wisdom, Part 2", "category": "Lore", "platform": "Console"}, "18980875": {"name": "Malthael: The Path of Wisdom, Part 3", "category": "Lore", "platform": "Console"}, "18980876": {"name": "Malthael: The Path of Wisdom, Part 4", "category": "Lore", "platform": "Console"}, "18980877": {"name": "Malthael: The Path of Wisdom, Part 5", "category": "Lore", "platform": "Console"}, "18980878": {"name": "Malthael: The Path of Wisdom, Part 6", "category": "Lore", "platform": "Console"}, "3897062066": {"name": "Mira's Letter to Haedrig", "category": "Lore", "platform": "Console"}, "-768304375": {"name": "MisguidedFarmer: Farmer's Journal", "category": "Lore", "platform": "Console"}, "-1595216991": {"name": "Morgan: Morgan's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1595216990": {"name": "Morgan: Morgan's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1595216989": {"name": "Morgan: Morgan's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561999134": {"name": "Necromancer: Necromancer's Log", "category": "Lore", "platform": "Console"}, "1036599468": {"name": "Nephalem: The Destiny of the Nephalem, Part 1", "category": "Lore", "platform": "Console"}, "1036599469": {"name": "Nephalem: The Destiny of the Nephalem, Part 2", "category": "Lore", "platform": "Console"}, "1036599470": {"name": "Nephalem: The Destiny of the Nephalem, Part 3", "category": "Lore", "platform": "Console"}, "85406869": {"name": "Nephalem: The Drowned Temple", "category": "Lore", "platform": "Console"}, "1604771305": {"name": "Nephalem: The Last Stand of the Ancients", "category": "Lore", "platform": "Console"}, "1071008887": {"name": "Nephalem: The Nephalem Tome", "category": "Lore", "platform": "Console"}, "220221847": {"name": "Nephalem: Tomb Robber's Journal", "category": "Lore", "platform": "Console"}, "429729842": {"name": "Nephalem: Warrior's Rest", "category": "Lore", "platform": "Console"}, "-1608490938": {"name": "NephalemMiser: Miser's Will", "category": "Lore", "platform": "Console"}, "775555921": {"name": "NewTristram: New Tristram", "category": "Lore", "platform": "Console"}, "-1083079452": {"name": "Note: Secret Note", "category": "Lore", "platform": "Console"}, "1316599940": {"name": "Oasis: A Love Letter", "category": "Lore", "platform": "Console"}, "1676339915": {"name": "OasisCellars: The Imperial Guard's Orders", "category": "Lore", "platform": "Console"}, "-1048384993": {"name": "OldTristram: Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "-236966351": {"name": "OldTristram: Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1906290178": {"name": "OldTristram: Despina's Journal", "category": "Lore", "platform": "Console"}, "829218340": {"name": "OldTristram: Gillian's Diary, Part 1", "category": "Lore", "platform": "Console"}, "1594401494": {"name": "OldTristram: Gillian's Diary, Part 2", "category": "Lore", "platform": "Console"}, "316278028": {"name": "OldTristram: Lost Journal", "category": "Lore", "platform": "Console"}, "316278029": {"name": "OldTristram: Old Diary", "category": "Lore", "platform": "Console"}, "316278027": {"name": "OldTristram: Old Tristram Journal", "category": "Lore", "platform": "Console"}, "-700459563": {"name": "OldTristram: Traveler's Journal", "category": "Lore", "platform": "Console"}, "-289611678": {"name": "OldTristram: Villager's Journal", "category": "Lore", "platform": "Console"}, "1708077021": {"name": "OldTristram: Warriv's Journal", "category": "Lore", "platform": "Console"}, "-561113926": {"name": "OneLastEntry: Crumbling Journal", "category": "Lore", "platform": "Console"}, "-216253271": {"name": "PandExt: Legend of the Great Weapon", "category": "Lore", "platform": "Console"}, "551638722": {"name": "PandExt: Malthael's Plan", "category": "Lore", "platform": "Console"}, "-420053241": {"name": "Pandemonium: The History of Pandemonium, Part 1", "category": "Lore", "platform": "Console"}, "-420053240": {"name": "Pandemonium: The History of Pandemonium, Part 2", "category": "Lore", "platform": "Console"}, "-420053239": {"name": "Pandemonium: The History of Pandemonium, Part 3", "category": "Lore", "platform": "Console"}, "-420053238": {"name": "Pandemonium: The History of Pandemonium, Part 4", "category": "Lore", "platform": "Console"}, "-1604058933": {"name": "Poltahr: Poltahr's Notes", "category": "Lore", "platform": "Console"}, "-1861918345": {"name": "PortalRoulette: Lyndo's Journal", "category": "Lore", "platform": "Console"}, "613068827": {"name": "Priest: Priest's Contemplations, Part 1", "category": "Lore", "platform": "Console"}, "613068826": {"name": "Priest: Priest's Contemplations, Part 2", "category": "Lore", "platform": "Console"}, "1320763167": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "1320763168": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "1320763169": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "1758275411": {"name": "PromisesOfFezuul: The Promises of Fezuul al-Kazarr", "category": "Lore", "platform": "Console"}, "-139516026": {"name": "ProudWife: Bloodstained Letter", "category": "Lore", "platform": "Console"}, "3611879712": {"name": "Quill Fiend", "category": "Lore", "platform": "Console"}, "1276294793": {"name": "Rakanoth: Rakanoth, the Lord of Despair", "category": "Lore", "platform": "Console"}, "-1106592288": {"name": "Rakkis: Rakkis's Orders", "category": "Lore", "platform": "Console"}, "-1074332472": {"name": "RakkisHistory: The Testament of Rakkis, Part 1", "category": "Lore", "platform": "Console"}, "-1074332471": {"name": "RakkisHistory: The Testament of Rakkis, Part 2", "category": "Lore", "platform": "Console"}, "-1074332470": {"name": "RakkisHistory: The Testament of Rakkis, Part 3", "category": "Lore", "platform": "Console"}, "-1074332469": {"name": "RakkisHistory: The Testament of Rakkis, Part 4", "category": "Lore", "platform": "Console"}, "-1074332468": {"name": "RakkisHistory: The Testament of Rakkis, Part 5", "category": "Lore", "platform": "Console"}, "-1074332467": {"name": "RakkisHistory: The Testament of Rakkis, Part 6", "category": "Lore", "platform": "Console"}, "-1074332466": {"name": "RakkisHistory: The Testament of Rakkis, Part 7", "category": "Lore", "platform": "Console"}, "-1074332465": {"name": "RakkisHistory: The Testament of Rakkis, Part 8", "category": "Lore", "platform": "Console"}, "-1074332464": {"name": "RakkisHistory: The Testament of Rakkis, Part 9", "category": "Lore", "platform": "Console"}, "1960749072": {"name": "Realmwalker: The Realmwalker", "category": "Lore", "platform": "Console"}, "3580037015": {"name": "Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "2895121073": {"name": "Scavenger", "category": "Lore", "platform": "Console"}, "-561655662": {"name": "Scoundrel: Scoundrel's Journal", "category": "Lore", "platform": "Console"}, "648677458": {"name": "Siege: Missive from Imperius", "category": "Lore", "platform": "Console"}, "-1327438701": {"name": "Siege: Siege Runes", "category": "Lore", "platform": "Console"}, "1667935935": {"name": "SkeletonKing: The Skeleton King", "category": "Lore", "platform": "Console"}, "-21507498": {"name": "SpiderQueen: The Spider Queen", "category": "Lore", "platform": "Console"}, "1881837798": {"name": "Templar: Bloodied Parchment", "category": "Lore", "platform": "Console"}, "1881837797": {"name": "Templar: Bloodied Scraps", "category": "Lore", "platform": "Console"}, "1792637338": {"name": "TemplarMaester: Grand Maester's Journal", "category": "Lore", "platform": "Console"}, "1776052671": {"name": "TemplarMaester: The Maester's Proclamation", "category": "Lore", "platform": "Console"}, "464105835": {"name": "Tinker: Wandering Tinker's Diary", "category": "Lore", "platform": "Console"}, "3594507733": {"name": "Traveler's Journal", "category": "Lore", "platform": "Console"}, "732715821": {"name": "UriktheSeer: Notes of Urik the Seer, Part 1", "category": "Lore", "platform": "Console"}, "732715822": {"name": "UriktheSeer: Notes of Urik the Seer, Part 2", "category": "Lore", "platform": "Console"}, "732715823": {"name": "UriktheSeer: Notes of Urik the Seer, Part 3", "category": "Lore", "platform": "Console"}, "-645692806": {"name": "Urzael: Urzael's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-645692805": {"name": "Urzael: Urzael's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-645692804": {"name": "Urzael: Urzael's Journal, Part 3", "category": "Lore", "platform": "Console"}, "4005355618": {"name": "Villager's Journal", "category": "Lore", "platform": "Console"}, "-1451420418": {"name": "WaterPuzzle: The Chamber of Faces", "category": "Lore", "platform": "Console"}, "1223177093": {"name": "Westm: It's a Trap", "category": "Lore", "platform": "Console"}, "831394876": {"name": "Westm: The Cult Shall Rise Again", "category": "Lore", "platform": "Console"}, "913430382": {"name": "Westm: The King's Journal, Part 1", "category": "Lore", "platform": "Console"}, "913430383": {"name": "Westm: The King's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1218326648": {"name": "Westm: The King's Note to Lord Wynton", "category": "Lore", "platform": "Console"}, "1526997743": {"name": "Westm: The Plague Tunnels", "category": "Lore", "platform": "Console"}, "-1469466389": {"name": "Westm: The Souls of Westmarch", "category": "Lore", "platform": "Console"}, "-916745255": {"name": "Westmarch: The History of Westmarch, Part 1", "category": "Lore", "platform": "Console"}, "-916745254": {"name": "Westmarch: The History of Westmarch, Part 2", "category": "Lore", "platform": "Console"}, "-916745253": {"name": "Westmarch: The History of Westmarch, Part 3", "category": "Lore", "platform": "Console"}, "-916745252": {"name": "Westmarch: The History of Westmarch, Part 4", "category": "Lore", "platform": "Console"}, "-916745251": {"name": "Westmarch: The History of Westmarch, Part 5", "category": "Lore", "platform": "Console"}, "-916745250": {"name": "Westmarch: The History of Westmarch, Part 6", "category": "Lore", "platform": "Console"}, "-916745249": {"name": "Westmarch: The History of Westmarch, Part 7", "category": "Lore", "platform": "Console"}, "-223645750": {"name": "X1 Lore Besitary RevenantShieldGuard", "category": "Lore", "platform": "Console"}, "1571805338": {"name": "X1 Lore Bestiary GhastlySeraph", "category": "Lore", "platform": "Console"}, "1836003891": {"name": "X1 Lore Bestiary RevenantArcher", "category": "Lore", "platform": "Console"}, "-1635681275": {"name": "x1 Bog Lore AdriaBetrayal", "category": "Lore", "platform": "Console"}, "-8314071": {"name": "x1 Bog Lore AdriaEmptiness", "category": "Lore", "platform": "Console"}, "1923206206": {"name": "x1 Bog Lore AdriaLosingControl", "category": "Lore", "platform": "Console"}, "2045759001": {"name": "x1 Bog Lore AdriaNewHost", "category": "Lore", "platform": "Console"}, "118984382": {"name": "x1 Bog Lore AdriaPower", "category": "Lore", "platform": "Console"}, "-134175942": {"name": "x1 Bog Lore AdriaVoices", "category": "Lore", "platform": "Console"}, "-1074332440": {"name": "x1 Bog Lore RakkisHistory10", "category": "Lore", "platform": "Console"}}, "Maces, One-Handed": {"-1656026177": {"name": "02: Cudgel (DPS 9.6-11.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026176": {"name": "03: Morning Star (DPS 15.0-16.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026175": {"name": "04: Mace (DPS 18.6-20.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026174": {"name": "05: Flanged Mace (DPS 23.4-25.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026173": {"name": "06: Hammer (DPS 28.2-30.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026172": {"name": "07: War Gavel (DPS 33.6-35.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025089": {"name": "08: Bludgeon (DPS 43.8-45.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025088": {"name": "09: Spiked Baton (DPS 52.2-54.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025087": {"name": "10: War Mace (DPS 62.4-64.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025086": {"name": "11: Gada (DPS 73.2-75.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025085": {"name": "12: Pernach (DPS 85.2-88.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025084": {"name": "13: Heavy Hammer (DPS 102.0-105.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025083": {"name": "14: War Hammer (DPS 124.8-128.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656024000": {"name": "15: Skull Crusher (DPS 138.0-143.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023999": {"name": "16: Truncheon (DPS 155.4-160.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023998": {"name": "17: Death Mace (DPS 174.0-179.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023997": {"name": "18: Tripyor (DPS 192.6-199.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023996": {"name": "19: Goedendag (DPS 237.0-244.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023995": {"name": "20: Crag Hammer (DPS 273.6-282.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023994": {"name": "21: Demolisher (DPS 318.0-327.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022911": {"name": "22: Brutalizer (DPS 429.6-436.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022910": {"name": "23: Skullsplitter (DPS 540.6-547.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099965": {"name": "Art Test Mace One-Handed 1", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099964": {"name": "Art Test Mace One-Handed 2", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099963": {"name": "Art Test Mace One-Handed 3", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099962": {"name": "Art Test Mace One-Handed 4", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099961": {"name": "Art Test Mace One-Handed 5", "category": "Maces, One-Handed", "platform": "Console"}, "-1473010435": {"name": "Legendary: Deadeye's Mace (Patch 2.1.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894988668": {"name": "Legendary: Devastator", "category": "Maces, One-Handed", "platform": "Console"}, "1889806096": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1889808540": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325116": {"name": "Legendary: Earthshatter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895276164": {"name": "Legendary: Echoing Fury", "category": "Maces, One-Handed", "platform": "Console"}, "1880318728": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1880321172": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325108": {"name": "Legendary: Echoing Fury (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856068897": {"name": "Legendary: Jace's Hammer of Vigilance", "category": "Maces, One-Handed", "platform": "Console"}, "-1856140771": {"name": "Legendary: Mad Monarch's Scepter", "category": "Maces, One-Handed", "platform": "Console"}, "-1895024605": {"name": "Legendary: Nailbiter", "category": "Maces, One-Handed", "platform": "Console"}, "1888620175": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1888622619": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325115": {"name": "Legendary: Nailbiter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895204290": {"name": "Legendary: Neanderthal", "category": "Maces, One-Handed", "platform": "Console"}, "1882690570": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1882693014": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325110": {"name": "Legendary: Neanderthal (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895132416": {"name": "Legendary: Nutcracker", "category": "Maces, One-Handed", "platform": "Console"}, "1885062412": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1885064856": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325112": {"name": "Legendary: Nutcracker (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895240227": {"name": "Legendary: Odyn Son", "category": "Maces, One-Handed", "platform": "Console"}, "1881504649": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1881507093": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325109": {"name": "Legendary: Odyn Son (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856104834": {"name": "Legendary: Solanium", "category": "Maces, One-Handed", "platform": "Console"}, "-1894090243": {"name": "Legendary: Sun Keeper", "category": "Maces, One-Handed", "platform": "Console"}, "1919454121": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1919456565": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325141": {"name": "Legendary: Sun Keeper (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895060542": {"name": "Legendary: Telranden's Hand", "category": "Maces, One-Handed", "platform": "Console"}, "1887434254": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1887436698": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325114": {"name": "Legendary: Telranden's Hand (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894126180": {"name": "Legendary: Wirt's Original Leg", "category": "Maces, One-Handed", "platform": "Console"}, "1918268200": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1918270644": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325140": {"name": "Legendary: Wirt's Original Leg (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}}, "Maces, Two-Handed": {"-1616890784": {"name": "02: Two-Handed Mace (DPS 20.3-21.6)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890783": {"name": "03: Two-Handed Hammer (DPS 24.8-26.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890782": {"name": "04: Maul (DPS 31.5-32.9)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890781": {"name": "05: Mallet (DPS 37.8-40.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890780": {"name": "06: Great Hammer (DPS 45.5-48.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889696": {"name": "07: Dire Club (DPS 55.8-58.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889695": {"name": "08: Dire Mace (DPS 66.6-70.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889694": {"name": "09: Sledge Hammer (DPS 81.9-86.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889693": {"name": "10: Great Maul (DPS 98.6-104.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889692": {"name": "11: War Mallet (DPS 117.9-124.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889691": {"name": "12: Rock Breaker (DPS 144.5-151.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888607": {"name": "13: Wrecker (DPS 196.7-206.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888606": {"name": "14: Dread Mace (DPS 249.3-260.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888605": {"name": "15: War Sledge (DPS 315.9-326.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888604": {"name": "16: War Maul (DPS 437.9-448.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888603": {"name": "17: Slag Hammer (DPS 518.4-529.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888602": {"name": "18: Doom Hammer (DPS 613.4-624.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887518": {"name": "19: Royal Mace (DPS 774.0-786.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887517": {"name": "20: Persuader (DPS 1058.5-1070.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064028": {"name": "Art Test Mace Two-Handed 1", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064027": {"name": "Art Test Mace Two-Handed 2", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064026": {"name": "Art Test Mace Two-Handed 3", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064025": {"name": "Art Test Mace Two-Handed 4", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064024": {"name": "Art Test Mace Two-Handed 5", "category": "Maces, Two-Handed", "platform": "Console"}, "59108159": {"name": "Legendary: Arthef's Spark of Life", "category": "Maces, Two-Handed", "platform": "Console"}, "1950491947": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1950494391": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460503": {"name": "Legendary: Boneshatter (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954049710": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954052154": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460506": {"name": "Legendary: Cataclysm (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59036285": {"name": "Legendary: Crushbane", "category": "Maces, Two-Handed", "platform": "Console"}, "1948120105": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1948122549": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460501": {"name": "Legendary: Crushbane (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323781": {"name": "Legendary: Schaefer's Hammer", "category": "Maces, Two-Handed", "platform": "Console"}, "1957607473": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1957609917": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460509": {"name": "Legendary: Schaefer's Hammer (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60186269": {"name": "Legendary: Skywarden", "category": "Maces, Two-Handed", "platform": "Console"}, "1986069577": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1986072021": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460533": {"name": "Legendary: Skywarden (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59072222": {"name": "Legendary: Sledge of Athskeleng", "category": "Maces, Two-Handed", "platform": "Console"}, "1949306026": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1949308470": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460502": {"name": "Legendary: Sledge of Athskeleng (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "98279489": {"name": "Legendary: Soulsmasher", "category": "Maces, Two-Handed", "platform": "Console"}, "59215970": {"name": "Legendary: Sunder", "category": "Maces, Two-Handed", "platform": "Console"}, "98243552": {"name": "Legendary: The Furnace", "category": "Maces, Two-Handed", "platform": "Console"}, "60258143": {"name": "Legendary: Wrath of the Bone King", "category": "Maces, Two-Handed", "platform": "Console"}, "1988441419": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1988443863": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460535": {"name": "Legendary: Wrath of the Bone King (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60257879": {"name": "Legendary: Wrath of the Bone King (Patch 2.1.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323518": {"name": "legendary: Schaefer's Hammer (Patch 2.2.0)", "category": "Maces, Two-Handed", "platform": "Console"}}, "Mighty Belts": {"2112155407": {"name": "02: Harness (AR 32-37)", "category": "Mighty Belts", "platform": "Console"}, "2112155408": {"name": "03: Braid (AR 53-61)", "category": "Mighty Belts", "platform": "Console"}, "2112155409": {"name": "04: Grand Belt (AR 74-100)", "category": "Mighty Belts", "platform": "Console"}, "2112156495": {"name": "05: Baldric (AR 101-132)", "category": "Mighty Belts", "platform": "Console"}, "2112156496": {"name": "06: Blade Harness (AR 133-164)", "category": "Mighty Belts", "platform": "Console"}, "2112156497": {"name": "07: Iron Braid (AR 165-205)", "category": "Mighty Belts", "platform": "Console"}, "2112156498": {"name": "08: Steel Chain (AR 206-225)", "category": "Mighty Belts", "platform": "Console"}, "2112157584": {"name": "09: Lock (AR 226-252)", "category": "Mighty Belts", "platform": "Console"}, "2112157585": {"name": "10: Bronze Links (AR 253-285)", "category": "Mighty Belts", "platform": "Console"}, "2112157586": {"name": "11: Heavy Baldric (AR 286-318)", "category": "Mighty Belts", "platform": "Console"}, "2112157587": {"name": "12: Grand Chain (AR 320-419)", "category": "Mighty Belts", "platform": "Console"}, "2112157588": {"name": "13: Platinum Lock (AR 420-586)", "category": "Mighty Belts", "platform": "Console"}, "2112157589": {"name": "14: Mighty Scourge (AR 586-674)", "category": "Mighty Belts", "platform": "Console"}, "325816755": {"name": "Art Test BarbBelt 1", "category": "Mighty Belts", "platform": "Console"}, "325816756": {"name": "Art Test BarbBelt 2", "category": "Mighty Belts", "platform": "Console"}, "325816757": {"name": "Art Test BarbBelt 3", "category": "Mighty Belts", "platform": "Console"}, "325816758": {"name": "Art Test BarbBelt 4", "category": "Mighty Belts", "platform": "Console"}, "325816759": {"name": "Art Test BarbBelt 5", "category": "Mighty Belts", "platform": "Console"}, "924282931": {"name": "Legendary: Ageless Might", "category": "Mighty Belts", "platform": "Console"}, "436488351": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "436490795": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630773": {"name": "Legendary: Ageless Might (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963274576": {"name": "Legendary: Ancients' Discontent", "category": "Mighty Belts", "platform": "Console"}, "963166765": {"name": "Legendary: Chilanik's Chain", "category": "Mighty Belts", "platform": "Console"}, "924031372": {"name": "Legendary: Dread Iron", "category": "Mighty Belts", "platform": "Console"}, "428186904": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "428189348": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630780": {"name": "Legendary: Dread Iron (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924139183": {"name": "Legendary: Girdle of Giants", "category": "Mighty Belts", "platform": "Console"}, "431744667": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "431747111": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630777": {"name": "Legendary: Girdle of Giants (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924246994": {"name": "Legendary: Kotuur's Brace", "category": "Mighty Belts", "platform": "Console"}, "435302430": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "435304874": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630774": {"name": "Legendary: Kotuur's Brace (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924175120": {"name": "Legendary: Lamentation", "category": "Mighty Belts", "platform": "Console"}, "432930588": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "432933032": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630776": {"name": "Legendary: Lamentation (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924174856": {"name": "Legendary: Lamentation (Patch 2.1.0)", "category": "Mighty Belts", "platform": "Console"}, "924067309": {"name": "Legendary: Pride of Cassius", "category": "Mighty Belts", "platform": "Console"}, "429372825": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "429375269": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630779": {"name": "Legendary: Pride of Cassius (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963310513": {"name": "Legendary: Promise of the Doomed Forebearer", "category": "Mighty Belts", "platform": "Console"}, "924211057": {"name": "Legendary: The Undisputed Champion", "category": "Mighty Belts", "platform": "Console"}, "434116509": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "434118953": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630775": {"name": "Legendary: The Undisputed Champion (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737386": {"name": "Legendary: The Undisputed Champion (Patch 2.1.2)", "category": "Mighty Belts", "platform": "Console"}, "430558746": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "430561190": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630778": {"name": "Legendary: Thunder God's Vigor (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963238639": {"name": "Legendary: Wodir Harness", "category": "Mighty Belts", "platform": "Console"}, "963202702": {"name": "Legendary: x1_BarbBelt_norm_unique_11", "category": "Mighty Belts", "platform": "Console"}, "-1303630772": {"name": "Set: Immortal King's Detail (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924318868": {"name": "Set: Immortal King's Tribal Binding", "category": "Mighty Belts", "platform": "Console"}, "437674272": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "437676716": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737381": {"name": "legendary: Dread Iron (Patch 2.2.0)", "category": "Mighty Belts", "platform": "Console"}}, "Mighty Weapons, One-Handed": {"290066502": {"name": "02: Carver (DPS 14.3-16.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066503": {"name": "03: Maw Axe (DPS 21.5-23.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066504": {"name": "04: War Blade (DPS 31.2-33.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067590": {"name": "05: Scythe (DPS 36.4-38.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067591": {"name": "06: Machete (DPS 54.6-56.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067592": {"name": "07: Gutwrench (DPS 82.6-86.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067593": {"name": "08: Rage Blade (DPS 118.3-122.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068679": {"name": "09: Reaper (DPS 153.4-159.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068680": {"name": "10: Chopsword (DPS 206.7-214.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068681": {"name": "11: Massacre Axe (DPS 238.6-246.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068682": {"name": "12: Slayer (DPS 277.6-285.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069768": {"name": "13: Caldean Sword (DPS 371.8-379.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069769": {"name": "14: Limb Cleaver (DPS 461.5-469.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026495": {"name": "Art Test Mighty One-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026496": {"name": "Art Test Mighty One-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026497": {"name": "Art Test Mighty One-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026498": {"name": "Art Test Mighty One-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026499": {"name": "Art Test Mighty One-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062432": {"name": "Art Test Mighty Two-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062433": {"name": "Art Test Mighty Two-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062434": {"name": "Art Test Mighty Two-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062435": {"name": "Art Test Mighty Two-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062436": {"name": "Art Test Mighty Two-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511328230": {"name": "Legendary: Ambo's Pride", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665698662": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665701106": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986962": {"name": "Legendary: Ambo's Pride (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512406340": {"name": "Legendary: Blade of the Warlord", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630121032": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630123476": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986932": {"name": "Legendary: Blade of the Warlord (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473342821": {"name": "Legendary: Dishonored Legacy", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512370403": {"name": "Legendary: Fjord Cutter", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631306953": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631309397": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986933": {"name": "Legendary: Fjord Cutter (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625377348": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625379792": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986928": {"name": "Legendary: Harvest Moon (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473414695": {"name": "Legendary: Hellion Scale", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512550088": {"name": "Legendary: Night's Reaping", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473306884": {"name": "Legendary: Oathkeeper", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473378758": {"name": "Legendary: Remorseless", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986960": {"name": "Set: Bul-Kathos's Sacred Charge (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511400104": {"name": "Set: Bul-Kathos's Solemn Vow", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663326820": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663329264": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986961": {"name": "Set: Bul-Kathos's Tribal Guardian (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511364167": {"name": "Set: Bul-Kathos's Warrior Blood", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664512741": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664515185": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986965": {"name": "Set: Hallowed Destroyer (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511220419": {"name": "Set: Hallowed Nemesis", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669258869": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669256425": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}}, "Mighty Weapons, Two-Handed": {"329201895": {"name": "02: Giant Sword (DPS 18.0-19.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201896": {"name": "03: Giant Hammer (DPS 25.5-27.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201897": {"name": "04: Giant Axe (DPS 36.0-37.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202983": {"name": "05: Redwood War Club (DPS 60.6-63.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202984": {"name": "06: Colossus Sword (DPS 81.5-86.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202985": {"name": "07: Crusher (DPS 110.5-116.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202986": {"name": "08: Colossus Axe (DPS 169.0-176.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204072": {"name": "09: Battersmash (DPS 248.5-257.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204073": {"name": "10: Titan Sword (DPS 397.5-408.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204074": {"name": "11: Behemoth (DPS 469.0-481.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204075": {"name": "12: Titan Axe (DPS 555.0-567.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205161": {"name": "13: Hassan Chopper (DPS 691.9-703.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205162": {"name": "14: Steppes Smasher (DPS 940.0-951.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441870172": {"name": "Legendary: Bastion's Revered", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696736488": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696738932": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122324": {"name": "Legendary: Bastion's Revered (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441869908": {"name": "Legendary: Bastion's Revered (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441942046": {"name": "Legendary: Fury of the Vanished Peak", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699108330": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699110774": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122326": {"name": "Legendary: Fury of the Vanished Peak (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-96858155": {"name": "Legendary: Grim Reaper", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "480897754": {"name": "Legendary: Madawc's Sorrow", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-389442788": {"name": "Legendary: The Blackrock Destroyer (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441762361": {"name": "Legendary: The Gavel of Judgment", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693178725": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693181169": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122321": {"name": "Legendary: The Gavel of Judgment (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733500039": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733502483": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122355": {"name": "Legendary: Unending War (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442984219": {"name": "Legendary: War of the Dead", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442912345": {"name": "Set: Immortal King's Boulder Breaker", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731128197": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731130641": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122353": {"name": "Set: Immortal King's Stone Crusher (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}}, "Mightys, Two-Handed": {}, "Mojos": {"-136816474": {"name": "02: Shrunken Head (+(2-3)-(3-5) DMG)", "category": "Mojos", "platform": "Console"}, "-136816473": {"name": "03: Caged Horror (+(3-5)-(4-8) DMG)", "category": "Mojos", "platform": "Console"}, "-136816472": {"name": "04: Viper (+(3-6)-(4-10) DMG)", "category": "Mojos", "platform": "Console"}, "-136815386": {"name": "05: Gris-Gris Moppet (+(4-8)-(5-13) DMG)", "category": "Mojos", "platform": "Console"}, "-136815385": {"name": "06: Tzantza (+(6-11)-(7-19) DMG)", "category": "Mojos", "platform": "Console"}, "-136815384": {"name": "07: Living Tentacle (+(8-16)-(9-29) DMG)", "category": "Mojos", "platform": "Console"}, "-136815383": {"name": "08: Copperhead (+(13-26)-(14-45) DMG)", "category": "Mojos", "platform": "Console"}, "-136814297": {"name": "09: Wicker Man (+(17-39)-(18-114) DMG)", "category": "Mojos", "platform": "Console"}, "-136814296": {"name": "10: Muttering Head (+(19-58)-(20-213) DMG)", "category": "Mojos", "platform": "Console"}, "-136814295": {"name": "11: Unspeakable Thing (+(24-72)-(25-265) DMG)", "category": "Mojos", "platform": "Console"}, "-136814294": {"name": "12: Kurastian Asp (+(28-110)-(29-405) DMG)", "category": "Mojos", "platform": "Console"}, "-136814293": {"name": "13: Skull Talisman (+(126-158)-(127-190) DMG)", "category": "Mojos", "platform": "Console"}, "-136814292": {"name": "14: Thing That Should Not Be (+(262-328)-(263-394) DMG)", "category": "Mojos", "platform": "Console"}, "1629900554": {"name": "Art Test Mojo 1", "category": "Mojos", "platform": "Console"}, "1629900555": {"name": "Art Test Mojo 2", "category": "Mojos", "platform": "Console"}, "1629900556": {"name": "Art Test Mojo 3", "category": "Mojos", "platform": "Console"}, "1629900557": {"name": "Art Test Mojo 4", "category": "Mojos", "platform": "Console"}, "1629900558": {"name": "Art Test Mojo 5", "category": "Mojos", "platform": "Console"}, "-1667471440": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-1667468996": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608100": {"name": "Legendary: Bitterness (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961544827": {"name": "Legendary: Gazing Demise", "category": "Mojos", "platform": "Console"}, "-1666285519": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-1666283075": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608099": {"name": "Legendary: Gazing Demise (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961508890": {"name": "Legendary: Homunculus", "category": "Mojos", "platform": "Console"}, "-1665099598": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-1665097154": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608098": {"name": "Legendary: Homunculus (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922445371": {"name": "Legendary: Shukrani's Triumph", "category": "Mojos", "platform": "Console"}, "-922409434": {"name": "Legendary: Sorrowful Countenance", "category": "Mojos", "platform": "Console"}, "-961580764": {"name": "Legendary: Spite", "category": "Mojos", "platform": "Console"}, "-961329205": {"name": "Legendary: Thing of the Deep", "category": "Mojos", "platform": "Console"}, "-1659169993": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-1659167549": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608093": {"name": "Legendary: Thing of the Deep (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961365142": {"name": "Legendary: Uhkapian Serpent", "category": "Mojos", "platform": "Console"}, "-1660355914": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-1660353470": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608094": {"name": "Legendary: Uhkapian Serpent (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922373497": {"name": "Legendary: Vile Hive", "category": "Mojos", "platform": "Console"}, "1413644935": {"name": "P2 mojo norm Legendary 01", "category": "Mojos", "platform": "Console"}, "1413644936": {"name": "P2 mojo norm Legendary 02", "category": "Mojos", "platform": "Console"}, "1413644937": {"name": "P2 mojo norm Legendary 03", "category": "Mojos", "platform": "Console"}, "-960466717": {"name": "Set: Manajuma's Gory Fetch", "category": "Mojos", "platform": "Console"}, "-1630707889": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-1630705445": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608069": {"name": "Set: Manajuma's Ritual Prize (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-63608068": {"name": "Set: Zunimassa's Ferocity (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-960430780": {"name": "Set: Zunimassa's String of Skulls", "category": "Mojos", "platform": "Console"}, "-1629521968": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-1629519524": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-961509153": {"name": "legendary: Homunculus (Patch 2.2.0)", "category": "Mojos", "platform": "Console"}}, "NPC Items": {"1372800103": {"name": "A Summoner's Journal", "category": "NPC Items", "platform": "Console"}, "1366034119": {"name": "A2C2EmptyCage", "category": "NPC Items", "platform": "Console"}, "-894018760": {"name": "A2C2HusamHead", "category": "NPC Items", "platform": "Console"}, "1506900471": {"name": "A2C2NecromancerCrystal", "category": "NPC Items", "platform": "Console"}, "-1176971336": {"name": "A2C2OreBag", "category": "NPC Items", "platform": "Console"}, "-701130141": {"name": "A2C2RygnarIdol", "category": "NPC Items", "platform": "Console"}, "-1969048485": {"name": "A2C2SharkHide", "category": "NPC Items", "platform": "Console"}, "524402999": {"name": "A2C2SharkNecklace", "category": "NPC Items", "platform": "Console"}, "297778632": {"name": "A2C2WantedPoster", "category": "NPC Items", "platform": "Console"}, "1135854513": {"name": "A2C2WantedPosterGood", "category": "NPC Items", "platform": "Console"}, "-284487217": {"name": "ActIQ2 RatMageSkull", "category": "NPC Items", "platform": "Console"}, "956379400": {"name": "Ahren's Hammer", "category": "NPC Items", "platform": "Console"}, "893398919": {"name": "AlbrechtsRemains", "category": "NPC Items", "platform": "Console"}, "-1240838296": {"name": "Ancient Medallion", "category": "NPC Items", "platform": "Console"}, "1475923527": {"name": "Ancient Tome Page", "category": "NPC Items", "platform": "Console"}, "-831189640": {"name": "Angelic Seal", "category": "NPC Items", "platform": "Console"}, "-885657485": {"name": "Antique Box", "category": "NPC Items", "platform": "Console"}, "-309356827": {"name": "Aqueduct Key", "category": "NPC Items", "platform": "Console"}, "493907862": {"name": "Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "-470655325": {"name": "Beacon of Honor", "category": "NPC Items", "platform": "Console"}, "-470655324": {"name": "Beacon of Light", "category": "NPC Items", "platform": "Console"}, "-246893943": {"name": "Black Soulstone", "category": "NPC Items", "platform": "Console"}, "504121446": {"name": "Blackened Journal", "category": "NPC Items", "platform": "Console"}, "1818884426": {"name": "Blacksmith's Tome", "category": "NPC Items", "platform": "Console"}, "263122102": {"name": "Bogus Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "944034263": {"name": "Broken Crown", "category": "NPC Items", "platform": "Console"}, "-63906132": {"name": "Broken Doll", "category": "NPC Items", "platform": "Console"}, "1201838506": {"name": "Calldown Grenade", "category": "NPC Items", "platform": "Console"}, "-1797642504": {"name": "Caravan Inventory List", "category": "NPC Items", "platform": "Console"}, "-110888638": {"name": "Chain Key", "category": "NPC Items", "platform": "Console"}, "1061128541": {"name": "Cloud Fire", "category": "NPC Items", "platform": "Console"}, "-565248060": {"name": "Cultist Cellar Key", "category": "NPC Items", "platform": "Console"}, "-613437014": {"name": "DevilsHand: Aidan's Memento", "category": "NPC Items", "platform": "Console"}, "-613616703": {"name": "DevilsHand: Broken Oath", "category": "NPC Items", "platform": "Console"}, "-613437017": {"name": "DevilsHand: Cain's Memento", "category": "NPC Items", "platform": "Console"}, "-613544825": {"name": "DevilsHand: Dark Coven Familiar", "category": "NPC Items", "platform": "Console"}, "-613544828": {"name": "DevilsHand: Dark Coven Insignia", "category": "NPC Items", "platform": "Console"}, "-613544826": {"name": "DevilsHand: Dark Coven Jar of Reagents", "category": "NPC Items", "platform": "Console"}, "-613544829": {"name": "DevilsHand: Dark Coven Scroll of Illusions", "category": "NPC Items", "platform": "Console"}, "-613544827": {"name": "DevilsHand: Dark Coven Torturing Device", "category": "NPC Items", "platform": "Console"}, "-613437012": {"name": "DevilsHand: Gideon's Memento", "category": "NPC Items", "platform": "Console"}, "-613508887": {"name": "DevilsHand: Icon of Envy", "category": "NPC Items", "platform": "Console"}, "-613508886": {"name": "DevilsHand: Icon of Gluttony", "category": "NPC Items", "platform": "Console"}, "-613508891": {"name": "DevilsHand: Icon of Greed", "category": "NPC Items", "platform": "Console"}, "-613508888": {"name": "DevilsHand: Icon of Lust", "category": "NPC Items", "platform": "Console"}, "-613508889": {"name": "DevilsHand: Icon of Pride", "category": "NPC Items", "platform": "Console"}, "-613508890": {"name": "DevilsHand: Icon of Sloth", "category": "NPC Items", "platform": "Console"}, "-613508892": {"name": "DevilsHand: Icon of Wrath", "category": "NPC Items", "platform": "Console"}, "-613437016": {"name": "DevilsHand: Leah's Memento", "category": "NPC Items", "platform": "Console"}, "-613616702": {"name": "DevilsHand: Love's Oath", "category": "NPC Items", "platform": "Console"}, "-613437013": {"name": "DevilsHand: Ogden's Memento", "category": "NPC Items", "platform": "Console"}, "-613616701": {"name": "DevilsHand: Selfless Oath", "category": "NPC Items", "platform": "Console"}, "-613580763": {"name": "DevilsHand: The Black King's Bloodied Gauntlet", "category": "NPC Items", "platform": "Console"}, "-613580762": {"name": "DevilsHand: The Black King's Journal", "category": "NPC Items", "platform": "Console"}, "-613580765": {"name": "DevilsHand: The Black King's Skull", "category": "NPC Items", "platform": "Console"}, "-613580764": {"name": "DevilsHand: The Black King's Tainted Elixir", "category": "NPC Items", "platform": "Console"}, "-613580766": {"name": "DevilsHand: The Black King's Trophy", "category": "NPC Items", "platform": "Console"}, "-613437018": {"name": "DevilsHand: Warriv's Memento", "category": "NPC Items", "platform": "Console"}, "-613437015": {"name": "DevilsHand: Wirt's Memento", "category": "NPC Items", "platform": "Console"}, "-473140170": {"name": "Event: Alchemist Concoction", "category": "NPC Items", "platform": "Console"}, "452865871": {"name": "Event: Aperture Key", "category": "NPC Items", "platform": "Console"}, "-1312544703": {"name": "Event: Battle Elixir", "category": "NPC Items", "platform": "Console"}, "66225719": {"name": "Event: Battlefield Reports", "category": "NPC Items", "platform": "Console"}, "-1961273523": {"name": "Event: Bones of the Matriarch1", "category": "NPC Items", "platform": "Console"}, "-1961273522": {"name": "Event: Bones of the Matriarch2", "category": "NPC Items", "platform": "Console"}, "-1961273521": {"name": "Event: Bones of the Matriarch3", "category": "NPC Items", "platform": "Console"}, "1197498604": {"name": "Event: Dusty Old Tome", "category": "NPC Items", "platform": "Console"}, "463155324": {"name": "Event: Forboding Tome", "category": "NPC Items", "platform": "Console"}, "-934435532": {"name": "Event: Jeweled Scabbard", "category": "NPC Items", "platform": "Console"}, "1465477567": {"name": "Event: Medical Supplies", "category": "NPC Items", "platform": "Console"}, "-694090266": {"name": "Event: Officer's Orders", "category": "NPC Items", "platform": "Console"}, "-2013751652": {"name": "Event: Templar Object 1", "category": "NPC Items", "platform": "Console"}, "-1003233507": {"name": "Event: The Matriarch's Skeleton", "category": "NPC Items", "platform": "Console"}, "899528155": {"name": "FacePuzzleSmallKey", "category": "NPC Items", "platform": "Console"}, "-1986712818": {"name": "Fuad's Journal", "category": "NPC Items", "platform": "Console"}, "1331402556": {"name": "Greater Shard", "category": "NPC Items", "platform": "Console"}, "301784336": {"name": "Heretic Text", "category": "NPC Items", "platform": "Console"}, "-705827599": {"name": "HunterJournal", "category": "NPC Items", "platform": "Console"}, "1742022798": {"name": "Iron Wolf Captain's Journal", "category": "NPC Items", "platform": "Console"}, "680369210": {"name": "Jail Gate Key", "category": "NPC Items", "platform": "Console"}, "-78029774": {"name": "Jelisa's Wedding Ring", "category": "NPC Items", "platform": "Console"}, "1018820302": {"name": "Jeweler's Crucible", "category": "NPC Items", "platform": "Console"}, "872964849": {"name": "Journal of Hansan Haile, Captain", "category": "NPC Items", "platform": "Console"}, "1264544813": {"name": "Khan's Tomb Key", "category": "NPC Items", "platform": "Console"}, "-1071052922": {"name": "Kulle's Blood", "category": "NPC Items", "platform": "Console"}, "-1341834848": {"name": "Kulle's Body", "category": "NPC Items", "platform": "Console"}, "-1341834849": {"name": "Kulle's Heart", "category": "NPC Items", "platform": "Console"}, "425198027": {"name": "Larus's Log", "category": "NPC Items", "platform": "Console"}, "1790135009": {"name": "Mausoleum Key", "category": "NPC Items", "platform": "Console"}, "-397905230": {"name": "Mira's Letter to Haedrig", "category": "NPC Items", "platform": "Console"}, "-1140969500": {"name": "Mysterious Box", "category": "NPC Items", "platform": "Console"}, "1816611999": {"name": "Mystery Amulet", "category": "NPC Items", "platform": "Console"}, "-1493063970": {"name": "Mystery Belt", "category": "NPC Items", "platform": "Console"}, "-2026108002": {"name": "Mystery Boots", "category": "NPC Items", "platform": "Console"}, "1281756953": {"name": "Mystery Bracers", "category": "NPC Items", "platform": "Console"}, "-594428401": {"name": "Mystery Chest Armor", "category": "NPC Items", "platform": "Console"}, "2050033703": {"name": "Mystery Gloves", "category": "NPC Items", "platform": "Console"}, "-1492848355": {"name": "Mystery Helm", "category": "NPC Items", "platform": "Console"}, "-1492657844": {"name": "Mystery Mojo", "category": "NPC Items", "platform": "Console"}, "215071258": {"name": "Mystery Orb", "category": "NPC Items", "platform": "Console"}, "-2010009315": {"name": "Mystery Pants", "category": "NPC Items", "platform": "Console"}, "-1843121997": {"name": "Mystery Quiver", "category": "NPC Items", "platform": "Console"}, "-1492484569": {"name": "Mystery Ring", "category": "NPC Items", "platform": "Console"}, "-1780286480": {"name": "Mystery Shield", "category": "NPC Items", "platform": "Console"}, "-537237168": {"name": "Mystery Shoulders", "category": "NPC Items", "platform": "Console"}, "-767866790": {"name": "Mystery Weapon, One-Handed", "category": "NPC Items", "platform": "Console"}, "-1099096773": {"name": "Mystery Weapon, Two-Handed", "category": "NPC Items", "platform": "Console"}, "-1352920439": {"name": "Nephalem Cube", "category": "NPC Items", "platform": "Console"}, "1774254059": {"name": "Nephalem Shard", "category": "NPC Items", "platform": "Console"}, "-1224842764": {"name": "Note from Maghda", "category": "NPC Items", "platform": "Console"}, "1524078078": {"name": "Old Tristram Key", "category": "NPC Items", "platform": "Console"}, "1524684909": {"name": "Orn VaseB caOut Props", "category": "NPC Items", "platform": "Console"}, "1472347958": {"name": "Orn a2dun Zolt Centerpiece A", "category": "NPC Items", "platform": "Console"}, "1354327297": {"name": "Orn caOut Cauldron", "category": "NPC Items", "platform": "Console"}, "-330317735": {"name": "Orn caOut CrateA", "category": "NPC Items", "platform": "Console"}, "1360506355": {"name": "Orn caOut VendorStandB", "category": "NPC Items", "platform": "Console"}, "1823013658": {"name": "Orn trDun Cath Candlestand", "category": "NPC Items", "platform": "Console"}, "-479501418": {"name": "Orn trDun Cath LibraryTable", "category": "NPC Items", "platform": "Console"}, "582933236": {"name": "Orn trDun Gargoyle 01", "category": "NPC Items", "platform": "Console"}, "684496620": {"name": "Orn trDun Incense Burner", "category": "NPC Items", "platform": "Console"}, "1432424645": {"name": "Orn trDun Weaponrack", "category": "NPC Items", "platform": "Console"}, "-1232771108": {"name": "Primordial Key", "category": "NPC Items", "platform": "Console"}, "-1661570587": {"name": "Queen Asylla's Journal", "category": "NPC Items", "platform": "Console"}, "1490502399": {"name": "Release Lever", "category": "NPC Items", "platform": "Console"}, "-1106160196": {"name": "Relic of Purification", "category": "NPC Items", "platform": "Console"}, "1259412129": {"name": "ReligiousArtifact", "category": "NPC Items", "platform": "Console"}, "-255366628": {"name": "Resonating Crystal", "category": "NPC Items", "platform": "Console"}, "468192851": {"name": "Scroll of Companion", "category": "NPC Items", "platform": "Console"}, "-96106000": {"name": "Scroll of Mysteries", "category": "NPC Items", "platform": "Console"}, "1310326700": {"name": "Shamanic Khazra Staff", "category": "NPC Items", "platform": "Console"}, "140227858": {"name": "Shard", "category": "NPC Items", "platform": "Console"}, "-1223968557": {"name": "Shard of Resurrection", "category": "NPC Items", "platform": "Console"}, "-1703187309": {"name": "Shen's Loot", "category": "NPC Items", "platform": "Console"}, "753721399": {"name": "Skeleton King's Crown", "category": "NPC Items", "platform": "Console"}, "-1874288726": {"name": "Spider Queen Venom", "category": "NPC Items", "platform": "Console"}, "437383090": {"name": "Sword Blade", "category": "NPC Items", "platform": "Console"}, "-1027737429": {"name": "Sword Hilt", "category": "NPC Items", "platform": "Console"}, "457400460": {"name": "Sword Piece", "category": "NPC Items", "platform": "Console"}, "1360078715": {"name": "SwordOfJustice", "category": "NPC Items", "platform": "Console"}, "1163171450": {"name": "The Cultist's Head", "category": "NPC Items", "platform": "Console"}, "-718773999": {"name": "Three Broken Gems", "category": "NPC Items", "platform": "Console"}, "-797314365": {"name": "Town Portal Stone", "category": "NPC Items", "platform": "Console"}, "-608122705": {"name": "Treasure Hunter's Note", "category": "NPC Items", "platform": "Console"}, "1111843456": {"name": "Triune Smith's Tools", "category": "NPC Items", "platform": "Console"}, "-1062930416": {"name": "Vasily's Angelic Idol", "category": "NPC Items", "platform": "Console"}, "-290192033": {"name": "WestM_Food", "category": "NPC Items", "platform": "Console"}, "437221476": {"name": "ZakarumTotem", "category": "NPC Items", "platform": "Console"}, "-1464111916": {"name": "Zoltun Kulle Blood Vial", "category": "NPC Items", "platform": "Console"}, "609972295": {"name": "Zoltun Kulle's Blue Eye", "category": "NPC Items", "platform": "Console"}, "-1341834850": {"name": "Zoltun Kulle's Body", "category": "NPC Items", "platform": "Console"}, "395877111": {"name": "Zoltun Kulle's Completed Head", "category": "NPC Items", "platform": "Console"}, "-1345664746": {"name": "Zoltun Kulle's Head", "category": "NPC Items", "platform": "Console"}, "-674931800": {"name": "Zoltun Kulle's One Eyed Head", "category": "NPC Items", "platform": "Console"}, "-1345750695": {"name": "Zoltun Kulle's Red Eye", "category": "NPC Items", "platform": "Console"}, "892508204": {"name": "Zoltun Kulle's Rotting Head", "category": "NPC Items", "platform": "Console"}, "414825604": {"name": "Zoltun Kulle's Tome of the Nephalem", "category": "NPC Items", "platform": "Console"}, "-649774063": {"name": "px_DevilsHand_TestGlobe (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "87458782": {"name": "px_DevilsHand_TestGlobe_Dropped (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}}, "Paints": {"-590920596": {"name": "Art_Test_Pants_11 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920595": {"name": "Art_Test_Pants_12 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920594": {"name": "Art_Test_Pants_13 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920593": {"name": "Art_Test_Pants_14 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598560": {"name": "Art_Test_Pants_6 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598561": {"name": "Art_Test_Pants_7 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598562": {"name": "Art_Test_Pants_8 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598563": {"name": "Art_Test_Pants_9 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}}, "Pants": {"-1512732137": {"name": "02: Leather Pants (AR 18-21)", "category": "Pants", "platform": "Console"}, "-1512732136": {"name": "03: Hide Breeches (AR 33-38)", "category": "Pants", "platform": "Console"}, "-1512732135": {"name": "04: Chain Leggings (AR 48-62)", "category": "Pants", "platform": "Console"}, "-1512732134": {"name": "05: Faulds (AR 63-77)", "category": "Pants", "platform": "Console"}, "-1512732133": {"name": "06: Plate Leggings (AR 78-101)", "category": "Pants", "platform": "Console"}, "-1512731049": {"name": "07: Legwraps (AR 102-131)", "category": "Pants", "platform": "Console"}, "-1512731048": {"name": "08: Etched Pants (AR 132-161)", "category": "Pants", "platform": "Console"}, "-1512731047": {"name": "09: Chausses (AR 162-191)", "category": "Pants", "platform": "Console"}, "-1512731046": {"name": "10: Tassets (AR 192-224)", "category": "Pants", "platform": "Console"}, "-1512731045": {"name": "11: Boneweave Faulds (AR 225-247)", "category": "Pants", "platform": "Console"}, "-1512729960": {"name": "12: Leg Guards (AR 27-269)", "category": "Pants", "platform": "Console"}, "-1512729959": {"name": "13: Poleyns (AR 270-284)", "category": "Pants", "platform": "Console"}, "-1512729958": {"name": "14: Warlord Leg Plates (AR 285-322)", "category": "Pants", "platform": "Console"}, "-1512729957": {"name": "15: Schynbalds (AR 322-359)", "category": "Pants", "platform": "Console"}, "-1512729956": {"name": "16: Sovereign Tassets (AR 360-397)", "category": "Pants", "platform": "Console"}, "-1512729955": {"name": "17: Archon Faulds (AR 397-471)", "category": "Pants", "platform": "Console"}, "-1512729954": {"name": "18: Rakkisgard Leg Plates (AR 472-659)", "category": "Pants", "platform": "Console"}, "-1512729953": {"name": "19: Ascended Faulds (AR 660-759)", "category": "Pants", "platform": "Console"}, "1283598555": {"name": "Art Test Pants 1", "category": "Pants", "platform": "Console"}, "1283598556": {"name": "Art Test Pants 2", "category": "Pants", "platform": "Console"}, "1283598557": {"name": "Art Test Pants 3", "category": "Pants", "platform": "Console"}, "1283598558": {"name": "Art Test Pants 4", "category": "Pants", "platform": "Console"}, "1283598559": {"name": "Art Test Pants 5", "category": "Pants", "platform": "Console"}, "-586378095": {"name": "Legendary: Conqueror's Legguards (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "-735317930": {"name": "Legendary: Death's Bargain", "category": "Pants", "platform": "Console"}, "-774309575": {"name": "Legendary: Depth Diggers", "category": "Pants", "platform": "Console"}, "217510501": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "217512945": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "903144209": {"name": "Legendary: Depth Diggers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774309839": {"name": "Legendary: Depth Diggers (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "216324580": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "216327024": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "903144208": {"name": "Legendary: Gehennas (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774453323": {"name": "Legendary: Hammer Jammers", "category": "Pants", "platform": "Console"}, "212766817": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "212769261": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "903144205": {"name": "Legendary: Hammer Jammers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-735353867": {"name": "Legendary: Hexing Pants of Mr. Yan", "category": "Pants", "platform": "Console"}, "-305758345": {"name": "Legendary: Legs of the Sealed Valley", "category": "Pants", "platform": "Console"}, "-774273638": {"name": "Legendary: Pox Faulds", "category": "Pants", "platform": "Console"}, "218696422": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "218698866": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "903144210": {"name": "Legendary: Pox Faulds (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774345512": {"name": "Legendary: Skelon's Deceit", "category": "Pants", "platform": "Console"}, "-774489260": {"name": "Legendary: Swamp Land Waders", "category": "Pants", "platform": "Console"}, "211580896": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "211583340": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "903144204": {"name": "Legendary: Swamp Land Waders (Old-Legacy)", "category": "Pants", "platform": "Console"}, "903144212": {"name": "Set: Asheara's Cradle (Old-Legacy)", "category": "Pants", "platform": "Console"}, "221068264": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "221070708": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "-774201764": {"name": "Set: Asheara's Pace", "category": "Pants", "platform": "Console"}, "903144239": {"name": "Set: Blackthorne's Breeches (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773231465": {"name": "Set: Blackthorne's Jousting Mail", "category": "Pants", "platform": "Console"}, "253088131": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "253090575": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "-773339276": {"name": "Set: Cain's Habit", "category": "Pants", "platform": "Console"}, "903144236": {"name": "Set: Cain's Raiment (Old-Legacy)", "category": "Pants", "platform": "Console"}, "249530368": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "249532812": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "251902210": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "251904654": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "903144238": {"name": "Set: Captain Crimson's Codpiece (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773267402": {"name": "Set: Captain Crimson's Thrust", "category": "Pants", "platform": "Console"}, "825937515": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827015887": {"name": "Set: Cuisses of Akkhan", "category": "Pants", "platform": "Console"}, "903144240": {"name": "Set: Demon's Flesh (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773195528": {"name": "Set: Demon's Plate", "category": "Pants", "platform": "Console"}, "254274052": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "254276496": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "826045588": {"name": "Set: Firebird's Down", "category": "Pants", "platform": "Console"}, "827231509": {"name": "Set: Helltooth Leg Guards", "category": "Pants", "platform": "Console"}, "-184773474": {"name": "Set: Immortal King's Stature (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "903144211": {"name": "Set: Inna's Glory (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774237701": {"name": "Set: Inna's Temperance", "category": "Pants", "platform": "Console"}, "219882343": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "219884787": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "826153399": {"name": "Set: Jade Harvester's Courage", "category": "Pants", "platform": "Console"}, "825901577": {"name": "Set: Leg Guards of Mystery (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826081525": {"name": "Set: Marauder's Encasement", "category": "Pants", "platform": "Console"}, "825865641": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773475": {"name": "Set: Natalya's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826009651": {"name": "Set: Raekor's Breeches", "category": "Pants", "platform": "Console"}, "825865639": {"name": "Set: Roland's Determination (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "826117462": {"name": "Set: Scales of the Dancing Serpent", "category": "Pants", "platform": "Console"}, "827051824": {"name": "Set: Sunwuko's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773473": {"name": "Set: Tal Rasha's Stride (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "825865640": {"name": "Set: Tasset of the Wastes (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827159635": {"name": "Set: The Shadow's Coil", "category": "Pants", "platform": "Console"}, "825937514": {"name": "Set: Unholy Plates (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827123698": {"name": "Set: Vyr's Fantastic Finery", "category": "Pants", "platform": "Console"}, "827195572": {"name": "Set: Weight of the Earth", "category": "Pants", "platform": "Console"}, "825901578": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773472": {"name": "Set: Zunimassa's Cloth (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-774273901": {"name": "legendary: Pox Faulds (Patch 2.2.0)", "category": "Pants", "platform": "Console"}}, "Polearms": {"-1337763519": {"name": "02: Pike (DPS 15.2-16.6)", "category": "Polearms", "platform": "Console"}, "-1337763518": {"name": "03: Guisarme (DPS 20.4-21.9)", "category": "Polearms", "platform": "Console"}, "-1337763517": {"name": "04: Hache (DPS 24.7-26.1)", "category": "Polearms", "platform": "Console"}, "-1337763516": {"name": "05: Glaive (DPS 31.8-33.3)", "category": "Polearms", "platform": "Console"}, "-1337763515": {"name": "06: Pole Axe (DPS 38.0-40.9)", "category": "Polearms", "platform": "Console"}, "-1337763514": {"name": "07: Halberd (DPS 41.3-44.2)", "category": "Polearms", "platform": "Console"}, "-1337763513": {"name": "08: Lance (DPS 50.8-53.7)", "category": "Polearms", "platform": "Console"}, "-1337762431": {"name": "09: Voulge (DPS 58.0-60.8)", "category": "Polearms", "platform": "Console"}, "-1337762430": {"name": "10: Naginata (DPS 70.3-74.6)", "category": "Polearms", "platform": "Console"}, "-1337762429": {"name": "11: Croc (DPS 79.8-84.1)", "category": "Polearms", "platform": "Console"}, "-1337762428": {"name": "12: Battle Hache (DPS 91.7-96.0)", "category": "Polearms", "platform": "Console"}, "-1337762427": {"name": "13: Bisento (DPS 101.7-107.4)", "category": "Polearms", "platform": "Console"}, "-1337762426": {"name": "14: Great Pole Axe (DPS 116.4-122.1)", "category": "Polearms", "platform": "Console"}, "-1337762425": {"name": "15: Battle Halberd (DPS 131.1-138.2)", "category": "Polearms", "platform": "Console"}, "-1337762424": {"name": "16: Partizan (DPS 156.3-163.4)", "category": "Polearms", "platform": "Console"}, "-1337761342": {"name": "17: Lochaber Axe (DPS 191.9-200.5)", "category": "Polearms", "platform": "Console"}, "-1337761341": {"name": "18: Fauchard (DPS 223.3-233.2)", "category": "Polearms", "platform": "Console"}, "-1337761340": {"name": "19: Skewer (DPS 260.8-272.2)", "category": "Polearms", "platform": "Console"}, "-1337761339": {"name": "20: War Crest (DPS 305.0-316.4)", "category": "Polearms", "platform": "Console"}, "-1337761338": {"name": "21: Kwan Dao (DPS 355.8-367.2)", "category": "Polearms", "platform": "Console"}, "-1337761337": {"name": "22: War Thresher (DPS 421.3-432.7)", "category": "Polearms", "platform": "Console"}, "-1337761336": {"name": "23: Grand Halberd (DPS 499.2-510.6)", "category": "Polearms", "platform": "Console"}, "-1337761335": {"name": "24: Dread Lance (DPS 590.0-601.4)", "category": "Polearms", "platform": "Console"}, "-1337760253": {"name": "25: Trident (DPS 739.7-752.3)", "category": "Polearms", "platform": "Console"}, "-1337760252": {"name": "26: Trishula (DPS 1009.1-1021.7)", "category": "Polearms", "platform": "Console"}, "-1558359355": {"name": "Art Test Polearm 1", "category": "Polearms", "platform": "Console"}, "-1558359354": {"name": "Art Test Polearm 2", "category": "Polearms", "platform": "Console"}, "-1558359353": {"name": "Art Test Polearm 3", "category": "Polearms", "platform": "Console"}, "-1558359352": {"name": "Art Test Polearm 4", "category": "Polearms", "platform": "Console"}, "-1558359351": {"name": "Art Test Polearm 5", "category": "Polearms", "platform": "Console"}, "-1948909473": {"name": "Legendary: Bovine Bardiche", "category": "Polearms", "platform": "Console"}, "-1948873536": {"name": "Legendary: Foushee Voulge", "category": "Polearms", "platform": "Console"}, "-1987972992": {"name": "Legendary: Heart Slaughter", "category": "Polearms", "platform": "Console"}, "-1178676596": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "-1178674152": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587768": {"name": "Legendary: Heart Slaughter (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987973256": {"name": "Legendary: Heart Slaughter (Patch 2.1.0)", "category": "Polearms", "platform": "Console"}, "-1988008929": {"name": "Legendary: Pledge of Caldeum", "category": "Polearms", "platform": "Console"}, "-1179862517": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "-1179860073": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587767": {"name": "Legendary: Pledge of Caldeum (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987937055": {"name": "Legendary: Standoff", "category": "Polearms", "platform": "Console"}, "-1177490675": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "-1177488231": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587769": {"name": "Legendary: Standoff (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1988044866": {"name": "Legendary: Vigilance", "category": "Polearms", "platform": "Console"}, "-1181048438": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "-1181045994": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587766": {"name": "Legendary: Vigilance (Old-Legacy)", "category": "Polearms", "platform": "Console"}}, "Quivers": {"1539236301": {"name": "02: Canvas Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236302": {"name": "03: Leather Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236303": {"name": "04: Hunting Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236304": {"name": "05: Assassin Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539237389": {"name": "06: Heavy Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237390": {"name": "07: Barbed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237391": {"name": "08: Hallowed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237392": {"name": "09: Stalker Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237393": {"name": "10: Razorspine Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238478": {"name": "11: Deadeye Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238479": {"name": "12: Bonetooth Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238480": {"name": "13: Consecrated Quiver (ASI 13.0%)", "category": "Quivers", "platform": "Console"}, "1539238481": {"name": "14: Runic Quiver (ASI 14.0%)", "category": "Quivers", "platform": "Console"}, "1539238482": {"name": "15: Sanctified Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238483": {"name": "16: Rakkisgard Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238484": {"name": "17: Ascended Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "-1056381007": {"name": "Art Test Quiver 1", "category": "Quivers", "platform": "Console"}, "-1056381006": {"name": "Art Test Quiver 2", "category": "Quivers", "platform": "Console"}, "-1056381005": {"name": "Art Test Quiver 3", "category": "Quivers", "platform": "Console"}, "-1056381004": {"name": "Art Test Quiver 4", "category": "Quivers", "platform": "Console"}, "-1056381003": {"name": "Art Test Quiver 5", "category": "Quivers", "platform": "Console"}, "-400507188": {"name": "Legendary: Archfiend Arrows", "category": "Quivers", "platform": "Console"}, "-331912616": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-331910172": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223036": {"name": "Legendary: Black Bone Arrows (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361407732": {"name": "Legendary: Bombadier's Rucksack", "category": "Quivers", "platform": "Console"}, "-400363440": {"name": "Legendary: Dead Man's Legacy", "category": "Quivers", "platform": "Console"}, "-327168932": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-327166488": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223032": {"name": "Legendary: Dead Man's Legacy (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361371795": {"name": "Legendary: Emimei's Duffel", "category": "Quivers", "platform": "Console"}, "-400399377": {"name": "Legendary: Fletcher's Pride", "category": "Quivers", "platform": "Console"}, "-328354853": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-328352409": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223033": {"name": "Legendary: Fletcher's Pride (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400579062": {"name": "Legendary: Flint Ripper Arrowheads", "category": "Quivers", "platform": "Console"}, "-334284458": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-334282014": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223038": {"name": "Legendary: Flint Ripper Arrowheads (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400471251": {"name": "Legendary: Holy Point Shot", "category": "Quivers", "platform": "Console"}, "-330726695": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-330724251": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223035": {"name": "Legendary: Holy Point Shot (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361335858": {"name": "Legendary: Hunter's Longbox", "category": "Quivers", "platform": "Console"}, "-400579326": {"name": "Legendary: Meticulous Bolts (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-400435314": {"name": "Legendary: Silver Star Piercers", "category": "Quivers", "platform": "Console"}, "-329540774": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-329538330": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223034": {"name": "Legendary: Silver Star Piercers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400543125": {"name": "Legendary: Sin Seekers", "category": "Quivers", "platform": "Console"}, "-333098537": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-333096093": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223037": {"name": "Legendary: Sin Seekers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400435578": {"name": "Legendary: Spines of Seething Hatred (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-361443669": {"name": "Legendary: The Ninth Cirri Satchel", "category": "Quivers", "platform": "Console"}, "564938473": {"name": "legendary: Dead Man's Legacy (Patch 2.2.0)", "category": "Quivers", "platform": "Console"}}, "Rings": {"1146967281": {"name": "02: Ring", "category": "Rings", "platform": "Console"}, "1146967282": {"name": "03: Ring", "category": "Rings", "platform": "Console"}, "1146967283": {"name": "04: Ring", "category": "Rings", "platform": "Console"}, "1146967284": {"name": "05: Ring", "category": "Rings", "platform": "Console"}, "1146967285": {"name": "06: Ring", "category": "Rings", "platform": "Console"}, "1146967286": {"name": "07: Ring", "category": "Rings", "platform": "Console"}, "1146967287": {"name": "08: Ring", "category": "Rings", "platform": "Console"}, "1146967288": {"name": "09: Ring", "category": "Rings", "platform": "Console"}, "1146967312": {"name": "10: Ring", "category": "Rings", "platform": "Console"}, "1146967313": {"name": "11: Ring", "category": "Rings", "platform": "Console"}, "1146967314": {"name": "12: Ring", "category": "Rings", "platform": "Console"}, "1146967315": {"name": "13: Ring", "category": "Rings", "platform": "Console"}, "1146967316": {"name": "14: Ring", "category": "Rings", "platform": "Console"}, "1146967317": {"name": "15: Ring", "category": "Rings", "platform": "Console"}, "1146967318": {"name": "16: Ring", "category": "Rings", "platform": "Console"}, "1146967319": {"name": "17: Ring", "category": "Rings", "platform": "Console"}, "1146967320": {"name": "18: Ring", "category": "Rings", "platform": "Console"}, "1146967321": {"name": "19: Ring", "category": "Rings", "platform": "Console"}, "1146967345": {"name": "20: Ring", "category": "Rings", "platform": "Console"}, "1146967346": {"name": "21: Ring", "category": "Rings", "platform": "Console"}, "1146967347": {"name": "22: Ring", "category": "Rings", "platform": "Console"}, "1146967348": {"name": "23: Ring", "category": "Rings", "platform": "Console"}, "1146967349": {"name": "24: Ring", "category": "Rings", "platform": "Console"}, "1146967350": {"name": "25: Ring", "category": "Rings", "platform": "Console"}, "1818597029": {"name": "Art Test Ring 1", "category": "Rings", "platform": "Console"}, "1818597030": {"name": "Art Test Ring 2", "category": "Rings", "platform": "Console"}, "1818597031": {"name": "Art Test Ring 3", "category": "Rings", "platform": "Console"}, "1818597032": {"name": "Art Test Ring 4", "category": "Rings", "platform": "Console"}, "1818597033": {"name": "Art Test Ring 5", "category": "Rings", "platform": "Console"}, "-1149557626": {"name": "Legendary: Avarice Band", "category": "Rings", "platform": "Console"}, "-1188944578": {"name": "Legendary: Band of Hollow Whispers", "category": "Rings", "platform": "Console"}, "-580542710": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-580540266": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-731577034": {"name": "Legendary: Band of Hollow Whispers (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188657082": {"name": "Legendary: Band of Untold Secrets", "category": "Rings", "platform": "Console"}, "-571055342": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-571052898": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-731577026": {"name": "Legendary: Band of Untold Secrets (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149629500": {"name": "Legendary: Band of the Rue Chambers", "category": "Rings", "platform": "Console"}, "-1188764893": {"name": "Legendary: Broken Promises", "category": "Rings", "platform": "Console"}, "-574613105": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-574610661": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-731577029": {"name": "Legendary: Broken Promises (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186608673": {"name": "Legendary: Bul-Kathos's Wedding Band", "category": "Rings", "platform": "Console"}, "-503457845": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-503455401": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-731576969": {"name": "Legendary: Bul-Kathos's Wedding Band (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188728956": {"name": "Legendary: Eternal Union", "category": "Rings", "platform": "Console"}, "-573427184": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-573424740": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-731577028": {"name": "Legendary: Eternal Union (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188729220": {"name": "Legendary: Eternal Union (Patch 2.1.0)", "category": "Rings", "platform": "Console"}, "-1149665437": {"name": "Legendary: Gamuel's Deceit", "category": "Rings", "platform": "Console"}, "425752007": {"name": "Legendary: Halo Of Arlyse (Patch 2.1.2)", "category": "Rings", "platform": "Console"}, "-1186464925": {"name": "Legendary: Hellfire Ring", "category": "Rings", "platform": "Console"}, "-498714161": {"name": "Legendary: Hellfire Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-578170868": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-578168424": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-731577032": {"name": "Legendary: Hierophant's Seal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188693019": {"name": "Legendary: Justice Lantern", "category": "Rings", "platform": "Console"}, "-572241263": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-572238819": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-731577027": {"name": "Legendary: Justice Lantern (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188872704": {"name": "Legendary: Krede's Flame", "category": "Rings", "platform": "Console"}, "1963121073": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-159638916": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-1188908641": {"name": "Legendary: Leoric's Signet", "category": "Rings", "platform": "Console"}, "-579356789": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-579354345": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-731577033": {"name": "Legendary: Leoric's Signet (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186572736": {"name": "Legendary: Manald Heal", "category": "Rings", "platform": "Console"}, "-502271924": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-502269480": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-731576968": {"name": "Legendary: Manald Heal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187507098": {"name": "Legendary: Nagelring", "category": "Rings", "platform": "Console"}, "-533105870": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-533103426": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576994": {"name": "Legendary: Nagelring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186500862": {"name": "Legendary: Obsidian Ring of the Zodiac", "category": "Rings", "platform": "Console"}, "-499900082": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-499897638": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-731576966": {"name": "Legendary: Obsidian Ring of the Zodiac (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187543035": {"name": "Legendary: Oculus Ring", "category": "Rings", "platform": "Console"}, "-534291791": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-534289347": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576995": {"name": "Legendary: Oculus Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149521689": {"name": "Legendary: Pandemonium Loop", "category": "Rings", "platform": "Console"}, "-1188836767": {"name": "Legendary: Puzzle Ring", "category": "Rings", "platform": "Console"}, "-576984947": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-576982503": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577031": {"name": "Legendary: Puzzle Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149701374": {"name": "Legendary: Rechel's Ring of Larceny", "category": "Rings", "platform": "Console"}, "-1149593563": {"name": "Legendary: Ring of Royal Grandeur", "category": "Rings", "platform": "Console"}, "-1149737311": {"name": "Legendary: Rogar's Huge Stone", "category": "Rings", "platform": "Console"}, "-611901958": {"name": "Legendary: Signet Ring of the Blizzard", "category": "Rings", "platform": "Console"}, "-1186536799": {"name": "Legendary: Skull Grasp", "category": "Rings", "platform": "Console"}, "-501086003": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-501083559": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-731576967": {"name": "Legendary: Skull Grasp (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188800830": {"name": "Legendary: Stolen Ring", "category": "Rings", "platform": "Console"}, "-575799026": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-575796582": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577030": {"name": "Legendary: Stolen Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187471161": {"name": "Legendary: Stone of Jordan", "category": "Rings", "platform": "Console"}, "-531919949": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-531917505": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-731576993": {"name": "Legendary: Stone of Jordan (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149809185": {"name": "Legendary: The Tall Man's Finger", "category": "Rings", "platform": "Console"}, "-1187794594": {"name": "Legendary: Unity", "category": "Rings", "platform": "Console"}, "-542593238": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-542590794": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-731577002": {"name": "Legendary: Unity (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149773248": {"name": "Legendary: Wyrdward", "category": "Rings", "platform": "Console"}, "-1585363882": {"name": "P1_Ring_001 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363881": {"name": "P1_Ring_002 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363880": {"name": "P1_Ring_003 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363879": {"name": "P1_Ring_004 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "2082266421": {"name": "PvP: Echo Band All", "category": "Rings", "platform": "Console"}, "2082266693": {"name": "PvP: Echo Band Attack", "category": "Rings", "platform": "Console"}, "2082269451": {"name": "PvP: Echo Band Defense", "category": "Rings", "platform": "Console"}, "-4139386": {"name": "PvP: Echo Band Precision", "category": "Rings", "platform": "Console"}, "2082289199": {"name": "PvP: Echo Band Vitality", "category": "Rings", "platform": "Console"}, "-3897388": {"name": "PvP: Echo Band Willpower", "category": "Rings", "platform": "Console"}, "-2095294696": {"name": "PvP: Sherman Signet All", "category": "Rings", "platform": "Console"}, "-2095294424": {"name": "PvP: Sherman Signet Attack", "category": "Rings", "platform": "Console"}, "-2095291666": {"name": "PvP: Sherman Signet Defense", "category": "Rings", "platform": "Console"}, "-424702775": {"name": "PvP: Sherman Signet Precision", "category": "Rings", "platform": "Console"}, "-2095271918": {"name": "PvP: Sherman Signet Vitality", "category": "Rings", "platform": "Console"}, "-731576997": {"name": "Set: Band of Fallen Heroes (Old-Legacy)", "category": "Rings", "platform": "Console"}, "1978116233": {"name": "Set: Focus", "category": "Rings", "platform": "Console"}, "-1187614909": {"name": "Set: Litany of the Undaunted", "category": "Rings", "platform": "Console"}, "-536663633": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-536661189": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-731577001": {"name": "Set: Natalya's Mark (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187758657": {"name": "Set: Natalya's Reflection", "category": "Rings", "platform": "Console"}, "-541407317": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "-541404873": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "1978152170": {"name": "Set: Restraint", "category": "Rings", "platform": "Console"}, "-731576998": {"name": "Set: Screaming Chain (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187686783": {"name": "Set: The Compass Rose", "category": "Rings", "platform": "Console"}, "-539035475": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-539033031": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-1187650846": {"name": "Set: The Wailing Host", "category": "Rings", "platform": "Console"}, "-537849554": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-537847110": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-731576999": {"name": "Set: Wanderlust (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-731577000": {"name": "Set: Zunimassa's Plague (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187722720": {"name": "Set: Zunimassa's Pox", "category": "Rings", "platform": "Console"}, "-540221396": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "-540218952": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "417069417": {"name": "legendary: Arcstone (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1188765156": {"name": "legendary: Broken Promises (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069418": {"name": "legendary: Convention Of Elements (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187507361": {"name": "legendary: Nagelring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187543298": {"name": "legendary: Oculus Ring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149521952": {"name": "legendary: Pandemonium Loop (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1186501125": {"name": "legendary: Ring of the Zodiac (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069415": {"name": "legendary: Skull Grasp (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069416": {"name": "legendary: The Short Man's Finger (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149773511": {"name": "legendary: Wyrdward (Patch 2.2.0)", "category": "Rings", "platform": "Console"}}, "Scoundrel Tokens": {"-229902048": {"name": "02: Glass Blade", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900960": {"name": "03: Loaded Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900959": {"name": "04: Crystal Edge", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900958": {"name": "05: Clasp", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900957": {"name": "06: Sand Pouch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899871": {"name": "07: Bone Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899870": {"name": "08: Diamond Razor", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899869": {"name": "09: Brooch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899868": {"name": "10: Dust Satchel", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899867": {"name": "11: Hazard", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899866": {"name": "12: Stinger", "category": "Scoundrel Tokens", "platform": "Console"}, "978821514": {"name": "Legendary: Ribald Etchings", "category": "Scoundrel Tokens", "platform": "Console"}, "978821513": {"name": "Legendary: Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "978821515": {"name": "Legendary: Slipka's Letter Opener", "category": "Scoundrel Tokens", "platform": "Console"}, "-978821513": {"name": "Legendary:Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}}, "Shields": {"1815806857": {"name": "01: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806858": {"name": "02: Targe Shield (AR 48-55)", "category": "Shields", "platform": "Console"}, "1815806859": {"name": "03: Heater Shield (AR 88-101)", "category": "Shields", "platform": "Console"}, "1815806860": {"name": "04: Kite Shield (AR 128-167)", "category": "Shields", "platform": "Console"}, "1815806861": {"name": "05: Large Shield (AR 168-199)", "category": "Shields", "platform": "Console"}, "1815806862": {"name": "06: Gothic Shield (AR 200-223)", "category": "Shields", "platform": "Console"}, "1815806863": {"name": "07: Tower Shield (AR 224-255)", "category": "Shields", "platform": "Console"}, "1815807946": {"name": "08: Pelta (AR 256-319)", "category": "Shields", "platform": "Console"}, "1815807947": {"name": "09: Rondache (AR 320-383)", "category": "Shields", "platform": "Console"}, "1815807948": {"name": "10: Knight Shield (AR 384-447)", "category": "Shields", "platform": "Console"}, "1815807949": {"name": "11: Ironwood Shield (AR 448-511)", "category": "Shields", "platform": "Console"}, "1815807950": {"name": "12: Pavise (AR 512-579)", "category": "Shields", "platform": "Console"}, "1815807951": {"name": "13: Bone Shield (AR 580-619)", "category": "Shields", "platform": "Console"}, "1815807952": {"name": "14: Savior (AR 620-659)", "category": "Shields", "platform": "Console"}, "1815809035": {"name": "15: Aspis (AR 660-699)", "category": "Shields", "platform": "Console"}, "1815809036": {"name": "16: Hoplon (AR 700-739)", "category": "Shields", "platform": "Console"}, "1815809037": {"name": "17: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "-335464095": {"name": "17b: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "1815809038": {"name": "18: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "-334278174": {"name": "18b: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "1815809039": {"name": "19: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "-333092253": {"name": "19b: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "1815809040": {"name": "20: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "-331906332": {"name": "20b: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "1815809041": {"name": "21: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "-330720411": {"name": "21b: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "1815809042": {"name": "22: Rakkisgard Shield (AR 1260-1759)", "category": "Shields", "platform": "Console"}, "1815809043": {"name": "23: Ascended Shield (AR 1760-2024)", "category": "Shields", "platform": "Console"}, "-1347979730": {"name": "Art Test Shield 1", "category": "Shields", "platform": "Console"}, "-1347979729": {"name": "Art Test Shield 2", "category": "Shields", "platform": "Console"}, "-1347979728": {"name": "Art Test Shield 3", "category": "Shields", "platform": "Console"}, "-1347979727": {"name": "Art Test Shield 4", "category": "Shields", "platform": "Console"}, "-1347979726": {"name": "Art Test Shield 5", "category": "Shields", "platform": "Console"}, "200412170": {"name": "Legendary: Amazonian Parma", "category": "Shields", "platform": "Console"}, "200519981": {"name": "Legendary: Beastguard", "category": "Shields", "platform": "Console"}, "1028274966": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "1028277410": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "-64652478": {"name": "Legendary: Centurion (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200555918": {"name": "Legendary: Coven's Criterion", "category": "Shields", "platform": "Console"}, "200340296": {"name": "Legendary: Defender of Westmarch", "category": "Shields", "platform": "Console"}, "161420525": {"name": "Legendary: Denial", "category": "Shields", "platform": "Console"}, "1031832729": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "1031835173": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "-64652475": {"name": "Legendary: Denial (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200376233": {"name": "Legendary: Eberli Charo", "category": "Shields", "platform": "Console"}, "161312714": {"name": "Legendary: Freeze of Deflection", "category": "Shields", "platform": "Console"}, "161240840": {"name": "Legendary: Ivory Tower", "category": "Shields", "platform": "Console"}, "1025903124": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "1025905568": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "-64652480": {"name": "Legendary: Ivory Tower (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161456462": {"name": "Legendary: Lidless Wall", "category": "Shields", "platform": "Console"}, "1033018650": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "1033021094": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "-64652474": {"name": "Legendary: Lidless Wall (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161492399": {"name": "Legendary: Stormshield", "category": "Shields", "platform": "Console"}, "1034204571": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "1034207015": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "-64652473": {"name": "Legendary: Stormshield (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200448107": {"name": "Legendary: Vo'Toyias Spiker", "category": "Shields", "platform": "Console"}, "1063852596": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "1063855040": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "-64652448": {"name": "Legendary: Wall of Bone (Old-Legacy)", "category": "Shields", "platform": "Console"}, "162390824": {"name": "Legendary: Wall of Man", "category": "Shields", "platform": "Console"}, "200484044": {"name": "Legendary: Wretchskin", "category": "Shields", "platform": "Console"}, "162426761": {"name": "Set: Hallowed Barricade", "category": "Shields", "platform": "Console"}, "-64652447": {"name": "Set: Hallowed Barrier (Old-Legacy)", "category": "Shields", "platform": "Console"}, "1065038517": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "1065040961": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "200340033": {"name": "legendary: Defender Of Westmarch (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509030": {"name": "legendary: Denial (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509025": {"name": "legendary: Ivory Tower (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "-519190663": {"name": "legendary: Stormshield (Patch 2.2.0)", "category": "Shields", "platform": "Console"}}, "Shoulders": {"365490251": {"name": "03: Shoulder Guards (AR 48-58)", "category": "Shoulders", "platform": "Console"}, "365490252": {"name": "04: Amice (AR 58-68)", "category": "Shoulders", "platform": "Console"}, "365490253": {"name": "05: Spaulders (AR 69-79)", "category": "Shoulders", "platform": "Console"}, "365490254": {"name": "06: Shoulder Plates (AR 80-100)", "category": "Shoulders", "platform": "Console"}, "365491338": {"name": "07: Etched Mantle (AR 101-121)", "category": "Shoulders", "platform": "Console"}, "365491339": {"name": "08: Ailettes (AR 122-142)", "category": "Shoulders", "platform": "Console"}, "365491340": {"name": "09: Pauldrons (AR 144-164)", "category": "Shoulders", "platform": "Console"}, "365491341": {"name": "10: Sode (AR 165-199)", "category": "Shoulders", "platform": "Console"}, "365491342": {"name": "11: Epaulets (AR 200-219)", "category": "Shoulders", "platform": "Console"}, "365492427": {"name": "12: Balor Pauldrons (AR 220-239)", "category": "Shoulders", "platform": "Console"}, "365492428": {"name": "13: Espaliers (AR 240-252)", "category": "Shoulders", "platform": "Console"}, "365492429": {"name": "14: Warlord Spaulders (AR 253-285)", "category": "Shoulders", "platform": "Console"}, "365492430": {"name": "15: Doom Pauldrons (AR 286-318)", "category": "Shoulders", "platform": "Console"}, "365492431": {"name": "16: Pallium (AR 320-352)", "category": "Shoulders", "platform": "Console"}, "365492432": {"name": "17: Archon Spaulders (AR 353-419)", "category": "Shoulders", "platform": "Console"}, "365492433": {"name": "18: Rakkisgard Pauldrons (AR 420-586)", "category": "Shoulders", "platform": "Console"}, "365492434": {"name": "19: Ascended Pauldrons (AR 586-674)", "category": "Shoulders", "platform": "Console"}, "-1869550021": {"name": "Art Test Shoulder 1", "category": "Shoulders", "platform": "Console"}, "-1869550020": {"name": "Art Test Shoulder 2", "category": "Shoulders", "platform": "Console"}, "-1869550019": {"name": "Art Test Shoulder 3", "category": "Shoulders", "platform": "Console"}, "-1869550018": {"name": "Art Test Shoulder 4", "category": "Shoulders", "platform": "Console"}, "-1869550017": {"name": "Art Test Shoulder 5", "category": "Shoulders", "platform": "Console"}, "-1565608501": {"name": "Art_Test_Shoulder_10 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608500": {"name": "Art_Test_Shoulder_11 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608499": {"name": "Art_Test_Shoulder_12 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550016": {"name": "Art_Test_Shoulder_6 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550015": {"name": "Art_Test_Shoulder_7 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550014": {"name": "Art_Test_Shoulder_8 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550013": {"name": "Art_Test_Shoulder_9 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-248496224": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "-248493780": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734028": {"name": "Legendary: Barter Town Pads (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "2112365407": {"name": "Legendary: Burdens of the Brave Survivor", "category": "Shoulders", "platform": "Console"}, "1902294393": {"name": "Legendary: Conqueror's Pauldrons (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1959570086": {"name": "Legendary: Corruption", "category": "Shoulders", "platform": "Console"}, "-1959749771": {"name": "Legendary: Death Watch Mantle", "category": "Shoulders", "platform": "Console"}, "-247310303": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "-247307859": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734029": {"name": "Legendary: Death Watch Mantle (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959785708": {"name": "Legendary: Homing Pads", "category": "Shoulders", "platform": "Console"}, "507255184": {"name": "Legendary: Infernal Pauldrons", "category": "Shoulders", "platform": "Console"}, "-1920578441": {"name": "Legendary: Pauldrons of the Skeleton King", "category": "Shoulders", "platform": "Console"}, "-1920650315": {"name": "Legendary: Profane Pauldrons", "category": "Shoulders", "platform": "Console"}, "-241380698": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "-241378254": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734034": {"name": "Legendary: Seven Sins (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1920614378": {"name": "Legendary: Spaulders of Zakara", "category": "Shoulders", "platform": "Console"}, "1277749690": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-419021771": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-1959713834": {"name": "Legendary: Vile Ward", "category": "Shoulders", "platform": "Console"}, "-246124382": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "-246121938": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734030": {"name": "Legendary: Vile Ward (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959714098": {"name": "Legendary: Vile Ward (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1958384165": {"name": "Set: Asheara's Custodian", "category": "Shoulders", "platform": "Console"}, "-202245305": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "-202242861": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734067": {"name": "Set: Asheara's Vigilance (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959534149": {"name": "Set: Aughild's Power", "category": "Shoulders", "platform": "Console"}, "-240194777": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "-240192333": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734035": {"name": "Set: Aughild's Triumph (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-242566619": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "-242564175": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734033": {"name": "Set: Born's Pauldrons (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959606023": {"name": "Set: Born's Privilege", "category": "Shoulders", "platform": "Console"}, "-1980689583": {"name": "Set: Burden of the Invoker", "category": "Shoulders", "platform": "Console"}, "-1981839829": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875767": {"name": "Set: Dashing Pauldrons of Despair (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959498212": {"name": "Set: Demon's Aileron", "category": "Shoulders", "platform": "Console"}, "-239008856": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "-239006412": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734036": {"name": "Set: Demon's Wings (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1981731756": {"name": "Set: Firebird's Pinions", "category": "Shoulders", "platform": "Console"}, "-1980545835": {"name": "Set: Helltooth Mantle", "category": "Shoulders", "platform": "Console"}, "-1981623945": {"name": "Set: Jade Harvester's Joy", "category": "Shoulders", "platform": "Console"}, "-1981659882": {"name": "Set: Mantle of the Upside-Down Sinners", "category": "Shoulders", "platform": "Console"}, "-1981695819": {"name": "Set: Marauder's Spines", "category": "Shoulders", "platform": "Console"}, "-1981911703": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1980761457": {"name": "Set: Pauldrons of Akkhan", "category": "Shoulders", "platform": "Console"}, "-1981911704": {"name": "Set: Pauldrons of the Wastes (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981767693": {"name": "Set: Raekor's Burden", "category": "Shoulders", "platform": "Console"}, "-1981911705": {"name": "Set: Roland's Mantle (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1980581772": {"name": "Set: Spires of the Earth", "category": "Shoulders", "platform": "Console"}, "-1980725520": {"name": "Set: Sunwuko's Balance", "category": "Shoulders", "platform": "Console"}, "-1981839830": {"name": "Set: Unsanctified Shoulders (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875766": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959750034": {"name": "legendary: Death Watch Mantle (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1449741837": {"name": "legendary: Pauldrons of the Hierarch (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}}, "Sources": {"1905179476": {"name": "02: Spellbook (+(2-3)-(3-5) DMG)", "category": "Sources", "platform": "Console"}, "1905179477": {"name": "03: Smoked Spheres (+(3-5)-(4-8) DMG)", "category": "Sources", "platform": "Console"}, "1905179478": {"name": "04: Cursed Skull (+(3-6)-(4-10) DMG)", "category": "Sources", "platform": "Console"}, "1905180564": {"name": "05: Sanctuary Globe (+(4-8)-(5-13) DMG)", "category": "Sources", "platform": "Console"}, "1905180565": {"name": "06: Fiendish Folio (+(6-11)-(7-19) DMG)", "category": "Sources", "platform": "Console"}, "1905180566": {"name": "07: Triad (+(8-16)-(9-29) DMG)", "category": "Sources", "platform": "Console"}, "1905180567": {"name": "08: Screaming Skull (+(13-26)-(14-45) DMG)", "category": "Sources", "platform": "Console"}, "1905181653": {"name": "09: Power Sphere (+(17-39)-(18-114) DMG)", "category": "Sources", "platform": "Console"}, "1905181654": {"name": "10: Codex (+(19-58)-(20-213) DMG)", "category": "Sources", "platform": "Console"}, "1905181655": {"name": "11: Orbit Stones (+(24-72)-(25-265) DMG)", "category": "Sources", "platform": "Console"}, "1905181656": {"name": "12: Demi Lich (+(28-110)-(29-405) DMG)", "category": "Sources", "platform": "Console"}, "1905181657": {"name": "13: Puzzle Box (+(126-158)-(127-190) DMG)", "category": "Sources", "platform": "Console"}, "1905181658": {"name": "14: Moschen Spheres (+(262-328)-(263-394) DMG)", "category": "Sources", "platform": "Console"}, "702613912": {"name": "Art Test Orb 1", "category": "Sources", "platform": "Console"}, "702613913": {"name": "Art Test Orb 2", "category": "Sources", "platform": "Console"}, "702613914": {"name": "Art Test Orb 3", "category": "Sources", "platform": "Console"}, "702613915": {"name": "Art Test Orb 4", "category": "Sources", "platform": "Console"}, "702613916": {"name": "Art Test Orb 5", "category": "Sources", "platform": "Console"}, "-1519116524": {"name": "Legendary: Cosmic Strand", "category": "Sources", "platform": "Console"}, "2028438506": {"name": "Legendary: Gul'dan's Secret (Patch 2.1.0)", "category": "Sources", "platform": "Console"}, "-1934140787": {"name": "Legendary: Heart of Darkness", "category": "Sources", "platform": "Console"}, "-1480017068": {"name": "Legendary: Light of Grace", "category": "Sources", "platform": "Console"}, "-1480088942": {"name": "Legendary: Mirrorball", "category": "Sources", "platform": "Console"}, "-1480053005": {"name": "Legendary: Myken's Ball of Hate", "category": "Sources", "platform": "Console"}, "1408684960": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "1408687404": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "215441100": {"name": "Legendary: Singularity (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519224335": {"name": "Legendary: The Oculus", "category": "Sources", "platform": "Console"}, "1405127197": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "1405129641": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "215441097": {"name": "Legendary: The Oculus (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519152461": {"name": "Legendary: Triumvirate", "category": "Sources", "platform": "Console"}, "1407499039": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "1407501483": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "215441099": {"name": "Legendary: Triumvirate (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519080587": {"name": "Legendary: Winter Flurry", "category": "Sources", "platform": "Console"}, "1409870881": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "1409873325": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "215441101": {"name": "Legendary: Winter Flurry (Old-Legacy)", "category": "Sources", "platform": "Console"}, "215441130": {"name": "Set: Chantodo's Elemental Seal (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518038414": {"name": "Set: Chantodo's Force", "category": "Sources", "platform": "Console"}, "1444262590": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "1444265034": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "-777123311": {"name": "Set: Firebird's Eye", "category": "Sources", "platform": "Console"}, "215441131": {"name": "Set: Tal Rasha's Lidless Eye (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518002477": {"name": "Set: Tal Rasha's Unwavering Glare", "category": "Sources", "platform": "Console"}, "1445448511": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1445450955": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1175281612": {"name": "legendary: Triumvirate (Patch 2.2.0)", "category": "Sources", "platform": "Console"}}, "Spears": {"-101312756": {"name": "02: Fuscina (DPS 12.6-14.4)", "category": "Spears", "platform": "Console"}, "-101312755": {"name": "03: Spear (DPS 18.6-20.4)", "category": "Spears", "platform": "Console"}, "-101312754": {"name": "04: Hasta (DPS 24.6-26.4)", "category": "Spears", "platform": "Console"}, "-101312753": {"name": "05: Pilum (DPS 32.4-34.2)", "category": "Spears", "platform": "Console"}, "-101311668": {"name": "06: Angon (DPS 38.4-40.2)", "category": "Spears", "platform": "Console"}, "-101311667": {"name": "07: Assegai (DPS 48.6-50.4)", "category": "Spears", "platform": "Console"}, "-101311666": {"name": "08: War Spear (DPS 60.6-62.4)", "category": "Spears", "platform": "Console"}, "-101311665": {"name": "09: Spontoon (DPS 84.6-88.2)", "category": "Spears", "platform": "Console"}, "-101311664": {"name": "10: Yari (DPS 127.8-133.2)", "category": "Spears", "platform": "Console"}, "-101310579": {"name": "11: Harpoon (DPS 151.8-157.2)", "category": "Spears", "platform": "Console"}, "-101310578": {"name": "12: Impaler (DPS 178.2-185.4)", "category": "Spears", "platform": "Console"}, "-101310577": {"name": "13: Qiang (DPS 230.4-239.4)", "category": "Spears", "platform": "Console"}, "-101310576": {"name": "14: Vel (DPS 268.2-277.2)", "category": "Spears", "platform": "Console"}, "-101310575": {"name": "15: Centurion Spear (DPS 311.4-320.4)", "category": "Spears", "platform": "Console"}, "-101309490": {"name": "16: Honed Spear (DPS 419.4-428.4)", "category": "Spears", "platform": "Console"}, "-101309489": {"name": "17: Disemboweler (DPS 527.4-536.4)", "category": "Spears", "platform": "Console"}, "1438708880": {"name": "Art Test Spear 1", "category": "Spears", "platform": "Console"}, "1438708881": {"name": "Art Test Spear 2", "category": "Spears", "platform": "Console"}, "1438708882": {"name": "Art Test Spear 3", "category": "Spears", "platform": "Console"}, "1438708883": {"name": "Art Test Spear 4", "category": "Spears", "platform": "Console"}, "1438708884": {"name": "Art Test Spear 5", "category": "Spears", "platform": "Console"}, "-2120824630": {"name": "Legendary: Akanesh, the Herald of Righteousness", "category": "Spears", "platform": "Console"}, "2135007273": {"name": "Legendary: Arreat's Law", "category": "Spears", "platform": "Console"}, "1735685973": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "1735688417": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403711": {"name": "Legendary: Arreat's Law (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135079147": {"name": "Legendary: Empyrean Messenger", "category": "Spears", "platform": "Console"}, "1738057815": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "1738060259": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403709": {"name": "Legendary: Empyrean Messenger (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135115084": {"name": "Legendary: Scrimshaw", "category": "Spears", "platform": "Console"}, "1739243736": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "1739246180": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403708": {"name": "Legendary: Scrimshaw (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-2120788693": {"name": "Legendary: Steffon's Heavy Lance", "category": "Spears", "platform": "Console"}, "2135043210": {"name": "Legendary: The Three Hundredth Spear", "category": "Spears", "platform": "Console"}, "1736871894": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "1736874338": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403710": {"name": "Legendary: The Three Hundredth Spear (Old-Legacy)", "category": "Spears", "platform": "Console"}}, "Spirit Stones": {"-242895467": {"name": "02: Thought Mirror (AR 36-41)", "category": "Spirit Stones", "platform": "Console"}, "-242895466": {"name": "03: Third Eye (AR 60-69)", "category": "Spirit Stones", "platform": "Console"}, "-242895465": {"name": "04: Onyx Cluster (AR 84-113)", "category": "Spirit Stones", "platform": "Console"}, "-242894379": {"name": "05: Sunstone (AR 114-149)", "category": "Spirit Stones", "platform": "Console"}, "-242894378": {"name": "06: Prism (AR 150-185)", "category": "Spirit Stones", "platform": "Console"}, "-242894377": {"name": "07: Seer Shard (AR 186-232)", "category": "Spirit Stones", "platform": "Console"}, "-242894376": {"name": "08: Igneous Studs (AR 232-254)", "category": "Spirit Stones", "platform": "Console"}, "-242893290": {"name": "09: Solarius (AR 255-284)", "category": "Spirit Stones", "platform": "Console"}, "-242893289": {"name": "10: Meditator (AR 285-322)", "category": "Spirit Stones", "platform": "Console"}, "-242893288": {"name": "11: Ghost Sight (AR 322-359)", "category": "Spirit Stones", "platform": "Console"}, "-242893287": {"name": "12: Star Crown (AR 360-472)", "category": "Spirit Stones", "platform": "Console"}, "-242893286": {"name": "13: Insight Stone (AR 472-659)", "category": "Spirit Stones", "platform": "Console"}, "-242893285": {"name": "14: Ascended Stone (AR 660-759)", "category": "Spirit Stones", "platform": "Console"}, "113759385": {"name": "Art Test SpiritStone 1", "category": "Spirit Stones", "platform": "Console"}, "113759386": {"name": "Art Test SpiritStone 2", "category": "Spirit Stones", "platform": "Console"}, "113759387": {"name": "Art Test SpiritStone 3", "category": "Spirit Stones", "platform": "Console"}, "113759388": {"name": "Art Test SpiritStone 4", "category": "Spirit Stones", "platform": "Console"}, "113759389": {"name": "Art Test SpiritStone 5", "category": "Spirit Stones", "platform": "Console"}, "635580050": {"name": "Legendary: Bezoar Stone", "category": "Spirit Stones", "platform": "Console"}, "-500772130": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-500769686": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225226": {"name": "Legendary: Bezoar Stone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635651924": {"name": "Legendary: Erlang Shen", "category": "Spirit Stones", "platform": "Console"}, "-498400288": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-498397844": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225228": {"name": "Legendary: Erlang Shen (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674787317": {"name": "Legendary: Eye of Peshkov", "category": "Spirit Stones", "platform": "Console"}, "635687861": {"name": "Legendary: Gyana Na Kashu", "category": "Spirit Stones", "platform": "Console"}, "-497214367": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-497211923": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225229": {"name": "Legendary: Gyana Na Kashu (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674751380": {"name": "Legendary: Kekegi's Unbreakable Spirit", "category": "Spirit Stones", "platform": "Console"}, "635831609": {"name": "Legendary: Madstone", "category": "Spirit Stones", "platform": "Console"}, "-492470683": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-492468239": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225233": {"name": "Legendary: Madstone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1935108657": {"name": "Legendary: Madstone (Patch 2.1.0)", "category": "Spirit Stones", "platform": "Console"}, "635723798": {"name": "Legendary: See No Evil", "category": "Spirit Stones", "platform": "Console"}, "-496028446": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-496026002": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225230": {"name": "Legendary: See No Evil (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635759735": {"name": "Legendary: The Eye of the Storm", "category": "Spirit Stones", "platform": "Console"}, "-494842525": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-494840081": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225231": {"name": "Legendary: The Eye of the Storm (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674715443": {"name": "Legendary: The Laws of Seph", "category": "Spirit Stones", "platform": "Console"}, "635615987": {"name": "Legendary: The Mind's Eye", "category": "Spirit Stones", "platform": "Console"}, "-499586209": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-499583765": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225227": {"name": "Legendary: The Mind's Eye (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635795672": {"name": "Legendary: Tzo Krin's Gaze", "category": "Spirit Stones", "platform": "Console"}, "-493656604": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-493654160": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225232": {"name": "Legendary: Tzo Krin's Gaze (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635867546": {"name": "Set: Inna's Radiance", "category": "Spirit Stones", "platform": "Console"}, "-491284762": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-491282318": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225234": {"name": "Set: Inna's Splendor (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}}, "Staves": {"-2115691355": {"name": "02: Long Staff (DPS 17.0-18.5)", "category": "Staves", "platform": "Console"}, "-2115691354": {"name": "03: Yew Staff (DPS 22.0-23.5)", "category": "Staves", "platform": "Console"}, "-2115691353": {"name": "04: Gnarled Staff (DPS 27.0-28.5)", "category": "Staves", "platform": "Console"}, "-2115691352": {"name": "05: Bone Staff (DPS 33.0-34.5)", "category": "Staves", "platform": "Console"}, "-2115691351": {"name": "06: Battle Staff (DPS 40.5-42.0)", "category": "Staves", "platform": "Console"}, "-2115691350": {"name": "07: War Staff (DPS 50.5-53.5)", "category": "Staves", "platform": "Console"}, "-2115690267": {"name": "08: Mentor Staff (DPS 66.5-69.5)", "category": "Staves", "platform": "Console"}, "-2115690266": {"name": "09: Obsidian Staff (DPS 75.5-78.5)", "category": "Staves", "platform": "Console"}, "-2115690265": {"name": "10: Petrified Staff (DPS 90.0-94.5)", "category": "Staves", "platform": "Console"}, "-2115690264": {"name": "11: Elder Staff (DPS 101.5-106.0)", "category": "Staves", "platform": "Console"}, "-2115690263": {"name": "12: Shamanic Staff (DPS 121.0-127.0)", "category": "Staves", "platform": "Console"}, "-2115690262": {"name": "13: High Priest Staff (DPS 138.5-144.5)", "category": "Staves", "platform": "Console"}, "-2115690261": {"name": "14: Arcane Staff (DPS 174.5-182.0)", "category": "Staves", "platform": "Console"}, "-2115689178": {"name": "15: Hyperion Staff (DPS 204.5-212.0)", "category": "Staves", "platform": "Console"}, "-2115689177": {"name": "16: Stygian Staff (DPS 237.0-246.0)", "category": "Staves", "platform": "Console"}, "-2115689176": {"name": "17: Primordial Staff (DPS 275.5-286.0)", "category": "Staves", "platform": "Console"}, "-2115689175": {"name": "18: Archaic Staff (DPS 320.0-332.0)", "category": "Staves", "platform": "Console"}, "-2115689174": {"name": "19: Conquest Staff (DPS 409.0-421.0)", "category": "Staves", "platform": "Console"}, "-2115689173": {"name": "20: Mythical Staff (DPS 484.0-496.0)", "category": "Staves", "platform": "Console"}, "-2115689172": {"name": "21: Sovereign Staff (DPS 572.5-584.5)", "category": "Staves", "platform": "Console"}, "-2115688089": {"name": "22: Caduceus Staff (DPS 712.3-725.5)", "category": "Staves", "platform": "Console"}, "-2115688088": {"name": "23: Kerykeion (DPS 968.0-981.2)", "category": "Staves", "platform": "Console"}, "-1849507048": {"name": "Art Test CombatStaff Two-Handed 1", "category": "Staves", "platform": "Console"}, "-1849507047": {"name": "Art Test CombatStaff Two-Handed 2", "category": "Staves", "platform": "Console"}, "-1849507046": {"name": "Art Test CombatStaff Two-Handed 3", "category": "Staves", "platform": "Console"}, "-1849507045": {"name": "Art Test CombatStaff Two-Handed 4", "category": "Staves", "platform": "Console"}, "-1849507044": {"name": "Art Test CombatStaff Two-Handed 5", "category": "Staves", "platform": "Console"}, "1590673385": {"name": "Art Test Staff 1", "category": "Staves", "platform": "Console"}, "1590673386": {"name": "Art Test Staff 2", "category": "Staves", "platform": "Console"}, "1590673387": {"name": "Art Test Staff 3", "category": "Staves", "platform": "Console"}, "1590673388": {"name": "Art Test Staff 4", "category": "Staves", "platform": "Console"}, "1590673389": {"name": "Art Test Staff 5", "category": "Staves", "platform": "Console"}, "2065442005": {"name": "Crafted: Elderwood Staff", "category": "Staves", "platform": "Console"}, "-1170762813": {"name": "Legendary: Ahavarion, Spear of Lycander", "category": "Staves", "platform": "Console"}, "-1209646647": {"name": "Legendary: Autumn's Call", "category": "Staves", "platform": "Console"}, "-1263710987": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "-1263708543": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "300184993": {"name": "Legendary: Autumn's Call (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-306066026": {"name": "Legendary: Hellish Staff of Herding", "category": "Staves", "platform": "Console"}, "1952916002": {"name": "Legendary: Infernal Staff of Herding", "category": "Staves", "platform": "Console"}, "-1209718521": {"name": "Legendary: Maloth's Focus", "category": "Staves", "platform": "Console"}, "-1266082829": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "-1266080385": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "300184991": {"name": "Legendary: Maloth's Focus (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209862269": {"name": "Legendary: Mark of The Magi", "category": "Staves", "platform": "Console"}, "-1409366405": {"name": "Legendary: Ner'zhul's Staff of Shadowmoon (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "670723600": {"name": "Legendary: Nightmarish Staff of Herding", "category": "Staves", "platform": "Console"}, "-1077364974": {"name": "Legendary: Staff of Herding", "category": "Staves", "platform": "Console"}, "-1170655002": {"name": "Legendary: SuWong Diviner", "category": "Staves", "platform": "Console"}, "-1209898206": {"name": "Legendary: The Broken Staff", "category": "Staves", "platform": "Console"}, "-1272012434": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "-1272009990": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "300184986": {"name": "Legendary: The Broken Staff (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610710": {"name": "Legendary: The Grand Vizier", "category": "Staves", "platform": "Console"}, "-1262525066": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "-1262522622": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "300184994": {"name": "Legendary: The Grand Vizier (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610974": {"name": "Legendary: The Grand Vizier (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "-1270826513": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "-1270824069": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "300184987": {"name": "Legendary: The Magi (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170690939": {"name": "Legendary: The Smoldering Core", "category": "Staves", "platform": "Console"}, "-1209682584": {"name": "Legendary: The Tormentor", "category": "Staves", "platform": "Console"}, "-1264896908": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "-1264894464": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "300184992": {"name": "Legendary: The Tormentor (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170726876": {"name": "Legendary: Valthek's Rebuke", "category": "Staves", "platform": "Console"}, "-1209826332": {"name": "Legendary: Wormwood", "category": "Staves", "platform": "Console"}, "-1269640592": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "-1269638148": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "300184988": {"name": "Legendary: Wormwood (Old-Legacy)", "category": "Staves", "platform": "Console"}, "1889450717": {"name": "Legendary: Wormwood (Patch 2.1.2)", "category": "Staves", "platform": "Console"}, "-1953260964": {"name": "P2 combatStaff norm Legendary 01", "category": "Staves", "platform": "Console"}, "397178771": {"name": "PvP: Heroic Staff", "category": "Staves", "platform": "Console"}, "397178770": {"name": "PvP: Mighty Staff", "category": "Staves", "platform": "Console"}, "397178769": {"name": "PvP: Staff", "category": "Staves", "platform": "Console"}}, "Swords, One-Handed": {"-270938920": {"name": "02: Sabre (DPS 8.4-10.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938919": {"name": "03: Broadsword (DPS 11.2-13.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938918": {"name": "04: Longsword (DPS 16.1-18.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938917": {"name": "05: Falchion (DPS 20.3-22.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938916": {"name": "06: Scimitar (DPS 24.5-26.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938915": {"name": "07: War Sword (DPS 28.0-30.1)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938914": {"name": "08: Bastard Sword (DPS 32.2-34.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937832": {"name": "09: Gladius (DPS 39.2-41.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937831": {"name": "10: Cutlass (DPS 44.1-46.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937830": {"name": "11: Battle Sword (DPS 48.3-50.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937829": {"name": "12: Knight Sword (DPS 53.2-55.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937828": {"name": "13: Dao (DPS 62.3-64.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937827": {"name": "14: Shamshir (DPS 73.5-75.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937826": {"name": "15: Raid Sword (DPS 81.2-83.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937825": {"name": "16: Ancient Sword (DPS 93.1-95.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936743": {"name": "17: Spatha (DPS 100.1-104.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936742": {"name": "18: Pirate Sword (DPS 112.0-116.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936741": {"name": "19: Strong Sword (DPS 123.2-127.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936740": {"name": "20: King Blade (DPS 137.2-141.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936739": {"name": "21: Tulwar (DPS 151.2-155.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936738": {"name": "22: Saif (DPS 181.3-187.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936737": {"name": "23: Conquest Sword (DPS 210.0-216.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936736": {"name": "24: Rune Sword (DPS 242.2-248.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935654": {"name": "25: Champion Sword (DPS 322.0-328.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935653": {"name": "26: Tsunami Blade (DPS 392.0-398.3)", "category": "Swords, One-Handed", "platform": "Console"}, "1775003964": {"name": "Art Test Sword One-Handed 1", "category": "Swords, One-Handed", "platform": "Console"}, "1775003965": {"name": "Art Test Sword One-Handed 2", "category": "Swords, One-Handed", "platform": "Console"}, "1775003966": {"name": "Art Test Sword One-Handed 3", "category": "Swords, One-Handed", "platform": "Console"}, "1775003967": {"name": "Art Test Sword One-Handed 4", "category": "Swords, One-Handed", "platform": "Console"}, "1775003968": {"name": "Art Test Sword One-Handed 5", "category": "Swords, One-Handed", "platform": "Console"}, "560809999": {"name": "Crafted: Blacksteel Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1351405527": {"name": "Legendary: Amberwing", "category": "Swords, One-Handed", "platform": "Console"}, "1312306071": {"name": "Legendary: Azurewrath", "category": "Swords, One-Handed", "platform": "Console"}, "356350083": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "356352527": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242223": {"name": "Legendary: Azurewrath (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351441464": {"name": "Legendary: Deathwish", "category": "Swords, One-Handed", "platform": "Console"}, "1312270134": {"name": "Legendary: Devil Tongue", "category": "Swords, One-Handed", "platform": "Console"}, "355164162": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "355166606": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242222": {"name": "Legendary: Devil Tongue (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312377945": {"name": "Legendary: Doombringer", "category": "Swords, One-Handed", "platform": "Console"}, "358721925": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "358724369": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242225": {"name": "Legendary: Doombringer (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350255543": {"name": "Legendary: Exarian", "category": "Swords, One-Handed", "platform": "Console"}, "1350327417": {"name": "Legendary: Fulminator", "category": "Swords, One-Handed", "platform": "Console"}, "1350399291": {"name": "Legendary: Ghoul King's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "1350291480": {"name": "Legendary: Gift of Silaria", "category": "Swords, One-Handed", "platform": "Console"}, "1350363354": {"name": "Legendary: God Butcher", "category": "Swords, One-Handed", "platform": "Console"}, "364651530": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "364653974": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242230": {"name": "Legendary: Griswold's Masterpiece (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312557630": {"name": "Legendary: Griswold's Perfection", "category": "Swords, One-Handed", "platform": "Console"}, "1311084213": {"name": "Legendary: Griswold's Worn Edge", "category": "Swords, One-Handed", "platform": "Console"}, "316028769": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "316031213": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242189": {"name": "Legendary: Griswold's Worn Edge (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350471165": {"name": "Legendary: Incinerator", "category": "Swords, One-Handed", "platform": "Console"}, "229247441": {"name": "Legendary: Lifebane", "category": "Swords, One-Handed", "platform": "Console"}, "1312485756": {"name": "Legendary: Monster Hunter", "category": "Swords, One-Handed", "platform": "Console"}, "362279688": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "362282132": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242228": {"name": "Legendary: Monster Hunter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350435228": {"name": "Legendary: Nazim's Greatness", "category": "Swords, One-Handed", "platform": "Console"}, "1312234197": {"name": "Legendary: Rakanishu's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "353978241": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "353980685": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242221": {"name": "Legendary: Rakanishu's Blade (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351369590": {"name": "Legendary: Rancor", "category": "Swords, One-Handed", "platform": "Console"}, "1350507102": {"name": "Legendary: Rimeheart", "category": "Swords, One-Handed", "platform": "Console"}, "1311299835": {"name": "Legendary: Sever", "category": "Swords, One-Handed", "platform": "Console"}, "323144295": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "323146739": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242195": {"name": "Legendary: Sever (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "229283378": {"name": "Legendary: Shard of Hate", "category": "Swords, One-Handed", "platform": "Console"}, "1311192024": {"name": "Legendary: Skycutter", "category": "Swords, One-Handed", "platform": "Console"}, "319586532": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "319588976": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242192": {"name": "Legendary: Skycutter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1313456055": {"name": "Legendary: Spectrum", "category": "Swords, One-Handed", "platform": "Console"}, "394299555": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "394301999": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242255": {"name": "Legendary: Spectrum (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1311156087": {"name": "Legendary: The Ancient Bonesaber of Zumakalis", "category": "Swords, One-Handed", "platform": "Console"}, "318400611": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "318403055": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242191": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350219606": {"name": "Legendary: Thunderfury, Blessed Blade of the Windseeker", "category": "Swords, One-Handed", "platform": "Console"}, "1311120150": {"name": "Legendary: Wildwood", "category": "Swords, One-Handed", "platform": "Console"}, "317214690": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "317217134": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242190": {"name": "Legendary: Wildwood (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487634": {"name": "PvP: Heroic Bastard Sword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487635": {"name": "PvP: Mighty Longsword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487636": {"name": "PvP: Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1312521693": {"name": "Set: Born's Furious Wrath", "category": "Swords, One-Handed", "platform": "Console"}, "363465609": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "363468053": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242229": {"name": "Set: Born's Seething Rage (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1394445518": {"name": "Set: Little Rogue", "category": "Swords, One-Handed", "platform": "Console"}, "-1394481455": {"name": "Set: The Slanderer", "category": "Swords, One-Handed", "platform": "Console"}, "-2025765397": {"name": "Sword Of Justice Tyrael", "category": "Swords, One-Handed", "platform": "Console"}, "1351477401": {"name": "legendary: In-geom (Patch 2.2.0)", "category": "Swords, One-Handed", "platform": "Console"}}, "Swords, Two-Handed": {"-231803527": {"name": "02: Flamberge (DPS 16.0-17.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803526": {"name": "03: Dervish (DPS 22.6-24.2)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803525": {"name": "04: Executioner Sword (DPS 28.1-29.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803524": {"name": "05: Nodachi (DPS 35.2-36.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803523": {"name": "06: Claymore (DPS 41.8-43.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802439": {"name": "07: Great Sword (DPS 52.8-54.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802438": {"name": "08: Reaver (DPS 62.2-65.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802437": {"name": "09: Kilij (DPS 74.8-78.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802436": {"name": "10: Mameluke (DPS 89.7-93.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802435": {"name": "11: Nagamaki (DPS 106.2-111.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802434": {"name": "12: Grand Sword (DPS 126.5-133.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801350": {"name": "13: Highland Sword (DPS 171.6-179.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801349": {"name": "14: Brimstone Sword (DPS 215.6-223.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801348": {"name": "15: Yatagan (DPS 269.0-278.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801347": {"name": "16: Colossus Blade (DPS 367.4-379.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801346": {"name": "17: Oni Blade (DPS 433.4-446.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801345": {"name": "18: Warlord Sword (DPS 511.5-524.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800261": {"name": "19: Gothic Blade (DPS 670.5-682.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800260": {"name": "20: Kingslayer (DPS 907.4-919.4)", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039901": {"name": "Art Test Sword Two-Handed 1", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039902": {"name": "Art Test Sword Two-Handed 2", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039903": {"name": "Art Test Sword Two-Handed 3", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039904": {"name": "Art Test Sword Two-Handed 4", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039905": {"name": "Art Test Sword Two-Handed 5", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028384713": {"name": "Legendary: Blackguard", "category": "Swords, Two-Handed", "platform": "Console"}, "422965539": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "422967983": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377615": {"name": "Legendary: Blackguard (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029355012": {"name": "Legendary: Blade of Prophecy", "category": "Swords, Two-Handed", "platform": "Console"}, "390945672": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "390948116": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377588": {"name": "Legendary: Blade of Prophecy (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "1516448771": {"name": "Legendary: Blade of the Ancients", "category": "Swords, Two-Handed", "platform": "Console"}, "-990363367": {"name": "Legendary: Blood Brother", "category": "Swords, Two-Handed", "platform": "Console"}, "-990399304": {"name": "Legendary: Cam's Rebuttal", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028348776": {"name": "Legendary: Faithful Memory", "category": "Swords, Two-Handed", "platform": "Console"}, "424151460": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "424153904": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377616": {"name": "Legendary: Faithful Memory (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028420650": {"name": "Legendary: Maximus", "category": "Swords, Two-Handed", "platform": "Console"}, "421779618": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "421782062": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377614": {"name": "Legendary: Maximus (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029462823": {"name": "Legendary: Scourge", "category": "Swords, Two-Handed", "platform": "Console"}, "387387909": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "387390353": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377585": {"name": "Legendary: Scourge (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028276902": {"name": "Legendary: Splintered Oar", "category": "Swords, Two-Handed", "platform": "Console"}, "426523302": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "426525746": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377618": {"name": "Legendary: Splintered Oar (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990435241": {"name": "Legendary: Stalgard's Decimator", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029570634": {"name": "Legendary: The Grandfather", "category": "Swords, Two-Handed", "platform": "Console"}, "383830146": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "383832590": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377582": {"name": "Legendary: The Grandfather (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029319075": {"name": "Legendary: The Sultan of Blinding Sand", "category": "Swords, Two-Handed", "platform": "Console"}, "392131593": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "392134037": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377589": {"name": "Legendary: The Sultan of Blinding Sand (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029534697": {"name": "Legendary: The Zweihander", "category": "Swords, Two-Handed", "platform": "Console"}, "385016067": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "385018511": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377583": {"name": "Legendary: The Zweihander (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029498760": {"name": "Legendary: Warmonger", "category": "Swords, Two-Handed", "platform": "Console"}, "386201988": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "386204432": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377584": {"name": "Legendary: Warmonger (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1271367654": {"name": "legendary: Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990291493": {"name": "legendary: Ch'il-chi-do (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990327430": {"name": "legendary: Corrupted Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}}, "Templar Relics": {"1147339622": {"name": "02: Spear Fragment", "category": "Templar Relics", "platform": "Console"}, "1147340710": {"name": "03: Sacred Text", "category": "Templar Relics", "platform": "Console"}, "1147340711": {"name": "04: Blade Shard", "category": "Templar Relics", "platform": "Console"}, "1147340712": {"name": "05: Martyr Tears", "category": "Templar Relics", "platform": "Console"}, "1147340713": {"name": "06: Chalice", "category": "Templar Relics", "platform": "Console"}, "1147341799": {"name": "07: Libram Spiritus", "category": "Templar Relics", "platform": "Console"}, "1147341800": {"name": "08: Blade Remnant", "category": "Templar Relics", "platform": "Console"}, "1147341801": {"name": "09: Saint Tears", "category": "Templar Relics", "platform": "Console"}, "1147341802": {"name": "10: Grail", "category": "Templar Relics", "platform": "Console"}, "1147341803": {"name": "11: Codex", "category": "Templar Relics", "platform": "Console"}, "1147341804": {"name": "12: Broken Foible", "category": "Templar Relics", "platform": "Console"}, "-765770609": {"name": "Legendary: Enchanting Favor", "category": "Templar Relics", "platform": "Console"}, "-765770607": {"name": "Legendary: Hillenbrand's Training Sword", "category": "Templar Relics", "platform": "Console"}, "-765770608": {"name": "Legendary: Relic of Akarat", "category": "Templar Relics", "platform": "Console"}}, "Test": {"-1438295707": {"name": "Don's Sword of Testing", "category": "Test", "platform": "Console"}, "-1585353949": {"name": "P1 Test Ring 941 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353948": {"name": "P1 Test Ring 942 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353947": {"name": "P1 Test Ring 943 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353946": {"name": "P1 Test Ring 944 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388889": {"name": "P2 TEST RING 021 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388890": {"name": "P2 TEST RING 022 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388891": {"name": "P2 TEST RING 023 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388892": {"name": "P2 TEST RING 024 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388893": {"name": "P2 TEST RING 025 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388894": {"name": "P2 TEST RING 026 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388895": {"name": "P2 TEST RING 027 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388896": {"name": "P2 TEST RING 028 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388897": {"name": "P2 TEST RING 029 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388921": {"name": "P2 TEST RING 030 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388922": {"name": "P2 TEST RING 031 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388923": {"name": "P2 TEST RING 032 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388924": {"name": "P2 TEST RING 033 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388925": {"name": "P2 TEST RING 034 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388926": {"name": "P2 TEST RING 035 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388927": {"name": "P2 TEST RING 036 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388928": {"name": "P2 TEST RING 037 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388929": {"name": "P2 TEST RING 038 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388930": {"name": "P2 TEST RING 039 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388954": {"name": "P2 TEST RING 040 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388955": {"name": "P2 TEST RING 041 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388956": {"name": "P2 TEST RING 042 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388957": {"name": "P2 TEST RING 043 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388958": {"name": "P2 TEST RING 044 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388959": {"name": "P2 TEST RING 045 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388960": {"name": "P2 TEST RING 046 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388961": {"name": "P2 TEST RING 047 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388962": {"name": "P2 TEST RING 048 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388963": {"name": "P2 TEST RING 049 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388987": {"name": "P2 TEST RING 050 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388824": {"name": "P2 Test Ring 002 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388825": {"name": "P2 Test Ring 003 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388826": {"name": "P2 Test Ring 004 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388827": {"name": "P2 Test Ring 005 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388828": {"name": "P2 Test Ring 006 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388829": {"name": "P2 Test Ring 007 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388830": {"name": "P2 Test Ring 008 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388831": {"name": "P2 Test Ring 009 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388855": {"name": "P2 Test Ring 010 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388856": {"name": "P2 Test Ring 011 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388857": {"name": "P2 Test Ring 012 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388858": {"name": "P2 Test Ring 013 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388859": {"name": "P2 Test Ring 014 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388860": {"name": "P2 Test Ring 015 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388861": {"name": "P2 Test Ring 016 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388862": {"name": "P2 Test Ring 017 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388863": {"name": "P2 Test Ring 018 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388864": {"name": "P2 Test Ring 019 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388888": {"name": "P2 Test Ring 020 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "1608362283": {"name": "P2_WizardSet_Scroll_Test (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388823": {"name": "Test Ring 001 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "708102766": {"name": "Test Ring 1000", "category": "Test", "platform": "Console"}, "-993303550": {"name": "Test Ring 500", "category": "Test", "platform": "Console"}, "-993267613": {"name": "Test Ring 501", "category": "Test", "platform": "Console"}, "-993231676": {"name": "Test Ring 502", "category": "Test", "platform": "Console"}, "-993195739": {"name": "Test Ring 503", "category": "Test", "platform": "Console"}, "-993159802": {"name": "Test Ring 504", "category": "Test", "platform": "Console"}, "-993123865": {"name": "Test Ring 505", "category": "Test", "platform": "Console"}, "-993087928": {"name": "Test Ring 506", "category": "Test", "platform": "Console"}, "-993051991": {"name": "Test Ring 507", "category": "Test", "platform": "Console"}, "-993016054": {"name": "Test Ring 508", "category": "Test", "platform": "Console"}, "-992980117": {"name": "Test Ring 509", "category": "Test", "platform": "Console"}, "-992117629": {"name": "Test Ring 510", "category": "Test", "platform": "Console"}, "-992081692": {"name": "Test Ring 511", "category": "Test", "platform": "Console"}, "-992045755": {"name": "Test Ring 512", "category": "Test", "platform": "Console"}, "-992009818": {"name": "Test Ring 513", "category": "Test", "platform": "Console"}, "-991973881": {"name": "Test Ring 514", "category": "Test", "platform": "Console"}, "-991937944": {"name": "Test Ring 515", "category": "Test", "platform": "Console"}, "-991902007": {"name": "Test Ring 516", "category": "Test", "platform": "Console"}, "-991866070": {"name": "Test Ring 517", "category": "Test", "platform": "Console"}, "-991830133": {"name": "Test Ring 518", "category": "Test", "platform": "Console"}, "-991794196": {"name": "Test Ring 519", "category": "Test", "platform": "Console"}, "-990931708": {"name": "Test Ring 520", "category": "Test", "platform": "Console"}, "-990895771": {"name": "Test Ring 521", "category": "Test", "platform": "Console"}, "-990859834": {"name": "Test Ring 522", "category": "Test", "platform": "Console"}, "-990823897": {"name": "Test Ring 523", "category": "Test", "platform": "Console"}, "-990787960": {"name": "Test Ring 524", "category": "Test", "platform": "Console"}, "-990752023": {"name": "Test Ring 525", "category": "Test", "platform": "Console"}, "-990716086": {"name": "Test Ring 526", "category": "Test", "platform": "Console"}, "-990680149": {"name": "Test Ring 527", "category": "Test", "platform": "Console"}, "-990644212": {"name": "Test Ring 528", "category": "Test", "platform": "Console"}, "-990608275": {"name": "Test Ring 529", "category": "Test", "platform": "Console"}, "-989745787": {"name": "Test Ring 530", "category": "Test", "platform": "Console"}, "-989709850": {"name": "Test Ring 531", "category": "Test", "platform": "Console"}, "-989673913": {"name": "Test Ring 532", "category": "Test", "platform": "Console"}, "-989637976": {"name": "Test Ring 533", "category": "Test", "platform": "Console"}, "-989602039": {"name": "Test Ring 534", "category": "Test", "platform": "Console"}, "-989566102": {"name": "Test Ring 535", "category": "Test", "platform": "Console"}, "-989530165": {"name": "Test Ring 536", "category": "Test", "platform": "Console"}, "-989494228": {"name": "Test Ring 537", "category": "Test", "platform": "Console"}, "-989458291": {"name": "Test Ring 538", "category": "Test", "platform": "Console"}, "-989422354": {"name": "Test Ring 539", "category": "Test", "platform": "Console"}, "-988559866": {"name": "Test Ring 540", "category": "Test", "platform": "Console"}, "-988523929": {"name": "Test Ring 541", "category": "Test", "platform": "Console"}, "-988487992": {"name": "Test Ring 542", "category": "Test", "platform": "Console"}, "-988452055": {"name": "Test Ring 543", "category": "Test", "platform": "Console"}, "-988416118": {"name": "Test Ring 544", "category": "Test", "platform": "Console"}, "-988380181": {"name": "Test Ring 545", "category": "Test", "platform": "Console"}, "-988344244": {"name": "Test Ring 546", "category": "Test", "platform": "Console"}, "-988308307": {"name": "Test Ring 547", "category": "Test", "platform": "Console"}, "-988272370": {"name": "Test Ring 548", "category": "Test", "platform": "Console"}, "-988236433": {"name": "Test Ring 549", "category": "Test", "platform": "Console"}, "-987373945": {"name": "Test Ring 550", "category": "Test", "platform": "Console"}, "-987338008": {"name": "Test Ring 551", "category": "Test", "platform": "Console"}, "-987302071": {"name": "Test Ring 552", "category": "Test", "platform": "Console"}, "-987266134": {"name": "Test Ring 553", "category": "Test", "platform": "Console"}, "-987230197": {"name": "Test Ring 554", "category": "Test", "platform": "Console"}, "-987194260": {"name": "Test Ring 555", "category": "Test", "platform": "Console"}, "-987158323": {"name": "Test Ring 556", "category": "Test", "platform": "Console"}, "-987122386": {"name": "Test Ring 557", "category": "Test", "platform": "Console"}, "-987086449": {"name": "Test Ring 558", "category": "Test", "platform": "Console"}, "-987050512": {"name": "Test Ring 559", "category": "Test", "platform": "Console"}, "-986188024": {"name": "Test Ring 560", "category": "Test", "platform": "Console"}, "-986152087": {"name": "Test Ring 561", "category": "Test", "platform": "Console"}, "-986116150": {"name": "Test Ring 562", "category": "Test", "platform": "Console"}, "-986080213": {"name": "Test Ring 563", "category": "Test", "platform": "Console"}, "-986044276": {"name": "Test Ring 564", "category": "Test", "platform": "Console"}, "-986008339": {"name": "Test Ring 565", "category": "Test", "platform": "Console"}, "-985972402": {"name": "Test Ring 566", "category": "Test", "platform": "Console"}, "-985936465": {"name": "Test Ring 567", "category": "Test", "platform": "Console"}, "-985900528": {"name": "Test Ring 568", "category": "Test", "platform": "Console"}, "-985864591": {"name": "Test Ring 569", "category": "Test", "platform": "Console"}, "-985002103": {"name": "Test Ring 570", "category": "Test", "platform": "Console"}, "-984966166": {"name": "Test Ring 571", "category": "Test", "platform": "Console"}, "-984930229": {"name": "Test Ring 572", "category": "Test", "platform": "Console"}, "-984894292": {"name": "Test Ring 573", "category": "Test", "platform": "Console"}, "-984858355": {"name": "Test Ring 574", "category": "Test", "platform": "Console"}, "-984822418": {"name": "Test Ring 575", "category": "Test", "platform": "Console"}, "-984786481": {"name": "Test Ring 576", "category": "Test", "platform": "Console"}, "-984750544": {"name": "Test Ring 577", "category": "Test", "platform": "Console"}, "-984714607": {"name": "Test Ring 578", "category": "Test", "platform": "Console"}, "-984678670": {"name": "Test Ring 579", "category": "Test", "platform": "Console"}, "-983816182": {"name": "Test Ring 580", "category": "Test", "platform": "Console"}, "-983780245": {"name": "Test Ring 581", "category": "Test", "platform": "Console"}, "-983744308": {"name": "Test Ring 582", "category": "Test", "platform": "Console"}, "-983708371": {"name": "Test Ring 583", "category": "Test", "platform": "Console"}, "-983672434": {"name": "Test Ring 584", "category": "Test", "platform": "Console"}, "-983636497": {"name": "Test Ring 585", "category": "Test", "platform": "Console"}, "-983600560": {"name": "Test Ring 586", "category": "Test", "platform": "Console"}, "-983564623": {"name": "Test Ring 587", "category": "Test", "platform": "Console"}, "-983528686": {"name": "Test Ring 588", "category": "Test", "platform": "Console"}, "-983492749": {"name": "Test Ring 589", "category": "Test", "platform": "Console"}, "-982630261": {"name": "Test Ring 590", "category": "Test", "platform": "Console"}, "-982594324": {"name": "Test Ring 591", "category": "Test", "platform": "Console"}, "-982558387": {"name": "Test Ring 592", "category": "Test", "platform": "Console"}, "-982522450": {"name": "Test Ring 593", "category": "Test", "platform": "Console"}, "-982486513": {"name": "Test Ring 594", "category": "Test", "platform": "Console"}, "-982450576": {"name": "Test Ring 595", "category": "Test", "platform": "Console"}, "-982414639": {"name": "Test Ring 596", "category": "Test", "platform": "Console"}, "-982378702": {"name": "Test Ring 597", "category": "Test", "platform": "Console"}, "-982342765": {"name": "Test Ring 598", "category": "Test", "platform": "Console"}, "-982306828": {"name": "Test Ring 599", "category": "Test", "platform": "Console"}, "-954168157": {"name": "Test Ring 600", "category": "Test", "platform": "Console"}, "-954132220": {"name": "Test Ring 601", "category": "Test", "platform": "Console"}, "-954096283": {"name": "Test Ring 602", "category": "Test", "platform": "Console"}, "-954060346": {"name": "Test Ring 603", "category": "Test", "platform": "Console"}, "-954024409": {"name": "Test Ring 604", "category": "Test", "platform": "Console"}, "-953988472": {"name": "Test Ring 605", "category": "Test", "platform": "Console"}, "-953952535": {"name": "Test Ring 606", "category": "Test", "platform": "Console"}, "-953916598": {"name": "Test Ring 607", "category": "Test", "platform": "Console"}, "-953880661": {"name": "Test Ring 608", "category": "Test", "platform": "Console"}, "-953844724": {"name": "Test Ring 609", "category": "Test", "platform": "Console"}, "-952982236": {"name": "Test Ring 610", "category": "Test", "platform": "Console"}, "-952946299": {"name": "Test Ring 611", "category": "Test", "platform": "Console"}, "-952910362": {"name": "Test Ring 612", "category": "Test", "platform": "Console"}, "-952874425": {"name": "Test Ring 613", "category": "Test", "platform": "Console"}, "-952838488": {"name": "Test Ring 614", "category": "Test", "platform": "Console"}, "-952802551": {"name": "Test Ring 615", "category": "Test", "platform": "Console"}, "-952766614": {"name": "Test Ring 616", "category": "Test", "platform": "Console"}, "-952730677": {"name": "Test Ring 617", "category": "Test", "platform": "Console"}, "-952694740": {"name": "Test Ring 618", "category": "Test", "platform": "Console"}, "-952658803": {"name": "Test Ring 619", "category": "Test", "platform": "Console"}, "-951796315": {"name": "Test Ring 620", "category": "Test", "platform": "Console"}, "-951760378": {"name": "Test Ring 621", "category": "Test", "platform": "Console"}, "-951724441": {"name": "Test Ring 622", "category": "Test", "platform": "Console"}, "-951688504": {"name": "Test Ring 623", "category": "Test", "platform": "Console"}, "-951652567": {"name": "Test Ring 624", "category": "Test", "platform": "Console"}, "-951616630": {"name": "Test Ring 625", "category": "Test", "platform": "Console"}, "-951580693": {"name": "Test Ring 626", "category": "Test", "platform": "Console"}, "-951544756": {"name": "Test Ring 627", "category": "Test", "platform": "Console"}, "-951508819": {"name": "Test Ring 628", "category": "Test", "platform": "Console"}, "-951472882": {"name": "Test Ring 629", "category": "Test", "platform": "Console"}, "-950610394": {"name": "Test Ring 630", "category": "Test", "platform": "Console"}, "-950574457": {"name": "Test Ring 631", "category": "Test", "platform": "Console"}, "-950538520": {"name": "Test Ring 632", "category": "Test", "platform": "Console"}, "-950502583": {"name": "Test Ring 633", "category": "Test", "platform": "Console"}, "-950466646": {"name": "Test Ring 634", "category": "Test", "platform": "Console"}, "-950430709": {"name": "Test Ring 635", "category": "Test", "platform": "Console"}, "-950394772": {"name": "Test Ring 636", "category": "Test", "platform": "Console"}, "-950358835": {"name": "Test Ring 637", "category": "Test", "platform": "Console"}, "-950322898": {"name": "Test Ring 638", "category": "Test", "platform": "Console"}, "-950286961": {"name": "Test Ring 639", "category": "Test", "platform": "Console"}, "-949424473": {"name": "Test Ring 640", "category": "Test", "platform": "Console"}, "-949388536": {"name": "Test Ring 641", "category": "Test", "platform": "Console"}, "-949352599": {"name": "Test Ring 642", "category": "Test", "platform": "Console"}, "-949316662": {"name": "Test Ring 643", "category": "Test", "platform": "Console"}, "-949280725": {"name": "Test Ring 644", "category": "Test", "platform": "Console"}, "-949244788": {"name": "Test Ring 645", "category": "Test", "platform": "Console"}, "-949208851": {"name": "Test Ring 646", "category": "Test", "platform": "Console"}, "-949172914": {"name": "Test Ring 647", "category": "Test", "platform": "Console"}, "-949136977": {"name": "Test Ring 648", "category": "Test", "platform": "Console"}, "-949101040": {"name": "Test Ring 649", "category": "Test", "platform": "Console"}, "-948238552": {"name": "Test Ring 650", "category": "Test", "platform": "Console"}, "-948202615": {"name": "Test Ring 651", "category": "Test", "platform": "Console"}, "-948166678": {"name": "Test Ring 652", "category": "Test", "platform": "Console"}, "-948130741": {"name": "Test Ring 653", "category": "Test", "platform": "Console"}, "-948094804": {"name": "Test Ring 654", "category": "Test", "platform": "Console"}, "-948058867": {"name": "Test Ring 655", "category": "Test", "platform": "Console"}, "-948022930": {"name": "Test Ring 656", "category": "Test", "platform": "Console"}, "-947986993": {"name": "Test Ring 657", "category": "Test", "platform": "Console"}, "-947951056": {"name": "Test Ring 658", "category": "Test", "platform": "Console"}, "-947915119": {"name": "Test Ring 659", "category": "Test", "platform": "Console"}, "-947052631": {"name": "Test Ring 660", "category": "Test", "platform": "Console"}, "-947016694": {"name": "Test Ring 661", "category": "Test", "platform": "Console"}, "-946980757": {"name": "Test Ring 662", "category": "Test", "platform": "Console"}, "-946944820": {"name": "Test Ring 663", "category": "Test", "platform": "Console"}, "-946908883": {"name": "Test Ring 664", "category": "Test", "platform": "Console"}, "-946872946": {"name": "Test Ring 665", "category": "Test", "platform": "Console"}, "-946837009": {"name": "Test Ring 666", "category": "Test", "platform": "Console"}, "-946801072": {"name": "Test Ring 667", "category": "Test", "platform": "Console"}, "-946765135": {"name": "Test Ring 668", "category": "Test", "platform": "Console"}, "-946729198": {"name": "Test Ring 669", "category": "Test", "platform": "Console"}, "-945866710": {"name": "Test Ring 670", "category": "Test", "platform": "Console"}, "-945830773": {"name": "Test Ring 671", "category": "Test", "platform": "Console"}, "-945794836": {"name": "Test Ring 672", "category": "Test", "platform": "Console"}, "-945758899": {"name": "Test Ring 673", "category": "Test", "platform": "Console"}, "-945722962": {"name": "Test Ring 674", "category": "Test", "platform": "Console"}, "-945687025": {"name": "Test Ring 675", "category": "Test", "platform": "Console"}, "-945651088": {"name": "Test Ring 676", "category": "Test", "platform": "Console"}, "-945615151": {"name": "Test Ring 677", "category": "Test", "platform": "Console"}, "-945579214": {"name": "Test Ring 678", "category": "Test", "platform": "Console"}, "-945543277": {"name": "Test Ring 679", "category": "Test", "platform": "Console"}, "-944680789": {"name": "Test Ring 680", "category": "Test", "platform": "Console"}, "-944644852": {"name": "Test Ring 681", "category": "Test", "platform": "Console"}, "-944608915": {"name": "Test Ring 682", "category": "Test", "platform": "Console"}, "-944572978": {"name": "Test Ring 683", "category": "Test", "platform": "Console"}, "-944537041": {"name": "Test Ring 684", "category": "Test", "platform": "Console"}, "-944501104": {"name": "Test Ring 685", "category": "Test", "platform": "Console"}, "-944465167": {"name": "Test Ring 686", "category": "Test", "platform": "Console"}, "-944429230": {"name": "Test Ring 687", "category": "Test", "platform": "Console"}, "-944393293": {"name": "Test Ring 688", "category": "Test", "platform": "Console"}, "-944357356": {"name": "Test Ring 689", "category": "Test", "platform": "Console"}, "-943494868": {"name": "Test Ring 690", "category": "Test", "platform": "Console"}, "-943458931": {"name": "Test Ring 691", "category": "Test", "platform": "Console"}, "-943422994": {"name": "Test Ring 692", "category": "Test", "platform": "Console"}, "-943387057": {"name": "Test Ring 693", "category": "Test", "platform": "Console"}, "-943351120": {"name": "Test Ring 694", "category": "Test", "platform": "Console"}, "-943315183": {"name": "Test Ring 695", "category": "Test", "platform": "Console"}, "-943279246": {"name": "Test Ring 696", "category": "Test", "platform": "Console"}, "-943243309": {"name": "Test Ring 697", "category": "Test", "platform": "Console"}, "-943207372": {"name": "Test Ring 698", "category": "Test", "platform": "Console"}, "-943171435": {"name": "Test Ring 699", "category": "Test", "platform": "Console"}, "-915032764": {"name": "Test Ring 700", "category": "Test", "platform": "Console"}, "-914996827": {"name": "Test Ring 701", "category": "Test", "platform": "Console"}, "-914960890": {"name": "Test Ring 702", "category": "Test", "platform": "Console"}, "-914924953": {"name": "Test Ring 703", "category": "Test", "platform": "Console"}, "-914889016": {"name": "Test Ring 704", "category": "Test", "platform": "Console"}, "-914853079": {"name": "Test Ring 705", "category": "Test", "platform": "Console"}, "-914817142": {"name": "Test Ring 706", "category": "Test", "platform": "Console"}, "-914781205": {"name": "Test Ring 707", "category": "Test", "platform": "Console"}, "-914745268": {"name": "Test Ring 708", "category": "Test", "platform": "Console"}, "-914709331": {"name": "Test Ring 709", "category": "Test", "platform": "Console"}, "-913846843": {"name": "Test Ring 710", "category": "Test", "platform": "Console"}, "-913810906": {"name": "Test Ring 711", "category": "Test", "platform": "Console"}, "-913774969": {"name": "Test Ring 712", "category": "Test", "platform": "Console"}, "-913739032": {"name": "Test Ring 713", "category": "Test", "platform": "Console"}, "-913703095": {"name": "Test Ring 714", "category": "Test", "platform": "Console"}, "-913667158": {"name": "Test Ring 715", "category": "Test", "platform": "Console"}, "-913631221": {"name": "Test Ring 716", "category": "Test", "platform": "Console"}, "-913595284": {"name": "Test Ring 717", "category": "Test", "platform": "Console"}, "-913559347": {"name": "Test Ring 718", "category": "Test", "platform": "Console"}, "-913523410": {"name": "Test Ring 719", "category": "Test", "platform": "Console"}, "-912660922": {"name": "Test Ring 720", "category": "Test", "platform": "Console"}, "-912624985": {"name": "Test Ring 721", "category": "Test", "platform": "Console"}, "-912589048": {"name": "Test Ring 722", "category": "Test", "platform": "Console"}, "-912553111": {"name": "Test Ring 723", "category": "Test", "platform": "Console"}, "-912517174": {"name": "Test Ring 724", "category": "Test", "platform": "Console"}, "-912481237": {"name": "Test Ring 725", "category": "Test", "platform": "Console"}, "-912445300": {"name": "Test Ring 726", "category": "Test", "platform": "Console"}, "-912409363": {"name": "Test Ring 727", "category": "Test", "platform": "Console"}, "-912373426": {"name": "Test Ring 728", "category": "Test", "platform": "Console"}, "-912337489": {"name": "Test Ring 729", "category": "Test", "platform": "Console"}, "-911475001": {"name": "Test Ring 730", "category": "Test", "platform": "Console"}, "-911439064": {"name": "Test Ring 731", "category": "Test", "platform": "Console"}, "-911403127": {"name": "Test Ring 732", "category": "Test", "platform": "Console"}, "-911367190": {"name": "Test Ring 733", "category": "Test", "platform": "Console"}, "-911331253": {"name": "Test Ring 734", "category": "Test", "platform": "Console"}, "-911295316": {"name": "Test Ring 735", "category": "Test", "platform": "Console"}, "-911259379": {"name": "Test Ring 736", "category": "Test", "platform": "Console"}, "-911223442": {"name": "Test Ring 737", "category": "Test", "platform": "Console"}, "-911187505": {"name": "Test Ring 738", "category": "Test", "platform": "Console"}, "-911151568": {"name": "Test Ring 739", "category": "Test", "platform": "Console"}, "-910289080": {"name": "Test Ring 740", "category": "Test", "platform": "Console"}, "-910253143": {"name": "Test Ring 741", "category": "Test", "platform": "Console"}, "-910217206": {"name": "Test Ring 742", "category": "Test", "platform": "Console"}, "-910181269": {"name": "Test Ring 743", "category": "Test", "platform": "Console"}, "-910145332": {"name": "Test Ring 744", "category": "Test", "platform": "Console"}, "-910109395": {"name": "Test Ring 745", "category": "Test", "platform": "Console"}, "-910073458": {"name": "Test Ring 746", "category": "Test", "platform": "Console"}, "-910037521": {"name": "Test Ring 747", "category": "Test", "platform": "Console"}, "-910001584": {"name": "Test Ring 748", "category": "Test", "platform": "Console"}, "-909965647": {"name": "Test Ring 749", "category": "Test", "platform": "Console"}, "-909103159": {"name": "Test Ring 750", "category": "Test", "platform": "Console"}, "-909067222": {"name": "Test Ring 751", "category": "Test", "platform": "Console"}, "-909031285": {"name": "Test Ring 752", "category": "Test", "platform": "Console"}, "-908995348": {"name": "Test Ring 753", "category": "Test", "platform": "Console"}, "-908959411": {"name": "Test Ring 754", "category": "Test", "platform": "Console"}, "-908923474": {"name": "Test Ring 755", "category": "Test", "platform": "Console"}, "-908887537": {"name": "Test Ring 756", "category": "Test", "platform": "Console"}, "-908851600": {"name": "Test Ring 757", "category": "Test", "platform": "Console"}, "-908815663": {"name": "Test Ring 758", "category": "Test", "platform": "Console"}, "-908779726": {"name": "Test Ring 759", "category": "Test", "platform": "Console"}, "-907917238": {"name": "Test Ring 760", "category": "Test", "platform": "Console"}, "-907881301": {"name": "Test Ring 761", "category": "Test", "platform": "Console"}, "-907845364": {"name": "Test Ring 762", "category": "Test", "platform": "Console"}, "-907809427": {"name": "Test Ring 763", "category": "Test", "platform": "Console"}, "-907773490": {"name": "Test Ring 764", "category": "Test", "platform": "Console"}, "-907737553": {"name": "Test Ring 765", "category": "Test", "platform": "Console"}, "-907701616": {"name": "Test Ring 766", "category": "Test", "platform": "Console"}, "-907665679": {"name": "Test Ring 767", "category": "Test", "platform": "Console"}, "-907629742": {"name": "Test Ring 768", "category": "Test", "platform": "Console"}, "-907593805": {"name": "Test Ring 769", "category": "Test", "platform": "Console"}, "-906731317": {"name": "Test Ring 770", "category": "Test", "platform": "Console"}, "-906695380": {"name": "Test Ring 771", "category": "Test", "platform": "Console"}, "-906659443": {"name": "Test Ring 772", "category": "Test", "platform": "Console"}, "-906623506": {"name": "Test Ring 773", "category": "Test", "platform": "Console"}, "-906587569": {"name": "Test Ring 774", "category": "Test", "platform": "Console"}, "-906551632": {"name": "Test Ring 775", "category": "Test", "platform": "Console"}, "-906515695": {"name": "Test Ring 776", "category": "Test", "platform": "Console"}, "-906479758": {"name": "Test Ring 777", "category": "Test", "platform": "Console"}, "-906443821": {"name": "Test Ring 778", "category": "Test", "platform": "Console"}, "-906407884": {"name": "Test Ring 779", "category": "Test", "platform": "Console"}, "-905545396": {"name": "Test Ring 780", "category": "Test", "platform": "Console"}, "-905509459": {"name": "Test Ring 781", "category": "Test", "platform": "Console"}, "-905473522": {"name": "Test Ring 782", "category": "Test", "platform": "Console"}, "-905437585": {"name": "Test Ring 783", "category": "Test", "platform": "Console"}, "-905401648": {"name": "Test Ring 784", "category": "Test", "platform": "Console"}, "-905365711": {"name": "Test Ring 785", "category": "Test", "platform": "Console"}, "-905329774": {"name": "Test Ring 786", "category": "Test", "platform": "Console"}, "-905293837": {"name": "Test Ring 787", "category": "Test", "platform": "Console"}, "-905257900": {"name": "Test Ring 788", "category": "Test", "platform": "Console"}, "-905221963": {"name": "Test Ring 789", "category": "Test", "platform": "Console"}, "-904359475": {"name": "Test Ring 790", "category": "Test", "platform": "Console"}, "-904323538": {"name": "Test Ring 791", "category": "Test", "platform": "Console"}, "-904287601": {"name": "Test Ring 792", "category": "Test", "platform": "Console"}, "-904251664": {"name": "Test Ring 793", "category": "Test", "platform": "Console"}, "-904215727": {"name": "Test Ring 794", "category": "Test", "platform": "Console"}, "-904179790": {"name": "Test Ring 795", "category": "Test", "platform": "Console"}, "-904143853": {"name": "Test Ring 796", "category": "Test", "platform": "Console"}, "-904107916": {"name": "Test Ring 797", "category": "Test", "platform": "Console"}, "-904071979": {"name": "Test Ring 798", "category": "Test", "platform": "Console"}, "-904036042": {"name": "Test Ring 799", "category": "Test", "platform": "Console"}, "-875897371": {"name": "Test Ring 800", "category": "Test", "platform": "Console"}, "-875861434": {"name": "Test Ring 801", "category": "Test", "platform": "Console"}, "-875825497": {"name": "Test Ring 802", "category": "Test", "platform": "Console"}, "-875789560": {"name": "Test Ring 803", "category": "Test", "platform": "Console"}, "-875753623": {"name": "Test Ring 804", "category": "Test", "platform": "Console"}, "-875717686": {"name": "Test Ring 805", "category": "Test", "platform": "Console"}, "-875681749": {"name": "Test Ring 806", "category": "Test", "platform": "Console"}, "-875645812": {"name": "Test Ring 807", "category": "Test", "platform": "Console"}, "-875609875": {"name": "Test Ring 808", "category": "Test", "platform": "Console"}, "-875573938": {"name": "Test Ring 809", "category": "Test", "platform": "Console"}, "-874711450": {"name": "Test Ring 810", "category": "Test", "platform": "Console"}, "-874675513": {"name": "Test Ring 811", "category": "Test", "platform": "Console"}, "-874639576": {"name": "Test Ring 812", "category": "Test", "platform": "Console"}, "-874603639": {"name": "Test Ring 813", "category": "Test", "platform": "Console"}, "-874567702": {"name": "Test Ring 814", "category": "Test", "platform": "Console"}, "-874531765": {"name": "Test Ring 815", "category": "Test", "platform": "Console"}, "-874495828": {"name": "Test Ring 816", "category": "Test", "platform": "Console"}, "-874459891": {"name": "Test Ring 817", "category": "Test", "platform": "Console"}, "-874423954": {"name": "Test Ring 818", "category": "Test", "platform": "Console"}, "-874388017": {"name": "Test Ring 819", "category": "Test", "platform": "Console"}, "-873525529": {"name": "Test Ring 820", "category": "Test", "platform": "Console"}, "-873489592": {"name": "Test Ring 821", "category": "Test", "platform": "Console"}, "-873453655": {"name": "Test Ring 822", "category": "Test", "platform": "Console"}, "-873417718": {"name": "Test Ring 823", "category": "Test", "platform": "Console"}, "-873381781": {"name": "Test Ring 824", "category": "Test", "platform": "Console"}, "-873345844": {"name": "Test Ring 825", "category": "Test", "platform": "Console"}, "-873309907": {"name": "Test Ring 826", "category": "Test", "platform": "Console"}, "-873273970": {"name": "Test Ring 827", "category": "Test", "platform": "Console"}, "-873238033": {"name": "Test Ring 828", "category": "Test", "platform": "Console"}, "-873202096": {"name": "Test Ring 829", "category": "Test", "platform": "Console"}, "-872339608": {"name": "Test Ring 830", "category": "Test", "platform": "Console"}, "-872303671": {"name": "Test Ring 831", "category": "Test", "platform": "Console"}, "-872267734": {"name": "Test Ring 832", "category": "Test", "platform": "Console"}, "-872231797": {"name": "Test Ring 833", "category": "Test", "platform": "Console"}, "-872195860": {"name": "Test Ring 834", "category": "Test", "platform": "Console"}, "-872159923": {"name": "Test Ring 835", "category": "Test", "platform": "Console"}, "-872123986": {"name": "Test Ring 836", "category": "Test", "platform": "Console"}, "-872088049": {"name": "Test Ring 837", "category": "Test", "platform": "Console"}, "-872052112": {"name": "Test Ring 838", "category": "Test", "platform": "Console"}, "-872016175": {"name": "Test Ring 839", "category": "Test", "platform": "Console"}, "-871153687": {"name": "Test Ring 840", "category": "Test", "platform": "Console"}, "-871117750": {"name": "Test Ring 841", "category": "Test", "platform": "Console"}, "-871081813": {"name": "Test Ring 842", "category": "Test", "platform": "Console"}, "-871045876": {"name": "Test Ring 843", "category": "Test", "platform": "Console"}, "-871009939": {"name": "Test Ring 844", "category": "Test", "platform": "Console"}, "-870974002": {"name": "Test Ring 845", "category": "Test", "platform": "Console"}, "-870938065": {"name": "Test Ring 846", "category": "Test", "platform": "Console"}, "-870902128": {"name": "Test Ring 847", "category": "Test", "platform": "Console"}, "-870866191": {"name": "Test Ring 848", "category": "Test", "platform": "Console"}, "-870830254": {"name": "Test Ring 849", "category": "Test", "platform": "Console"}, "-869967766": {"name": "Test Ring 850", "category": "Test", "platform": "Console"}, "-869931829": {"name": "Test Ring 851", "category": "Test", "platform": "Console"}, "-869895892": {"name": "Test Ring 852", "category": "Test", "platform": "Console"}, "-869859955": {"name": "Test Ring 853", "category": "Test", "platform": "Console"}, "-869824018": {"name": "Test Ring 854", "category": "Test", "platform": "Console"}, "-869788081": {"name": "Test Ring 855", "category": "Test", "platform": "Console"}, "-869752144": {"name": "Test Ring 856", "category": "Test", "platform": "Console"}, "-869716207": {"name": "Test Ring 857", "category": "Test", "platform": "Console"}, "-869680270": {"name": "Test Ring 858", "category": "Test", "platform": "Console"}, "-869644333": {"name": "Test Ring 859", "category": "Test", "platform": "Console"}, "-868781845": {"name": "Test Ring 860", "category": "Test", "platform": "Console"}, "-868745908": {"name": "Test Ring 861", "category": "Test", "platform": "Console"}, "-868709971": {"name": "Test Ring 862", "category": "Test", "platform": "Console"}, "-868674034": {"name": "Test Ring 863", "category": "Test", "platform": "Console"}, "-868638097": {"name": "Test Ring 864", "category": "Test", "platform": "Console"}, "-868602160": {"name": "Test Ring 865", "category": "Test", "platform": "Console"}, "-868566223": {"name": "Test Ring 866", "category": "Test", "platform": "Console"}, "-868530286": {"name": "Test Ring 867", "category": "Test", "platform": "Console"}, "-868494349": {"name": "Test Ring 868", "category": "Test", "platform": "Console"}, "-868458412": {"name": "Test Ring 869", "category": "Test", "platform": "Console"}, "-867595924": {"name": "Test Ring 870", "category": "Test", "platform": "Console"}, "-867559987": {"name": "Test Ring 871", "category": "Test", "platform": "Console"}, "-867524050": {"name": "Test Ring 872", "category": "Test", "platform": "Console"}, "-867488113": {"name": "Test Ring 873", "category": "Test", "platform": "Console"}, "-867452176": {"name": "Test Ring 874", "category": "Test", "platform": "Console"}, "-867416239": {"name": "Test Ring 875", "category": "Test", "platform": "Console"}, "-867380302": {"name": "Test Ring 876", "category": "Test", "platform": "Console"}, "-867344365": {"name": "Test Ring 877", "category": "Test", "platform": "Console"}, "-867308428": {"name": "Test Ring 878", "category": "Test", "platform": "Console"}, "-867272491": {"name": "Test Ring 879", "category": "Test", "platform": "Console"}, "-866410003": {"name": "Test Ring 880", "category": "Test", "platform": "Console"}, "-866374066": {"name": "Test Ring 881", "category": "Test", "platform": "Console"}, "-866338129": {"name": "Test Ring 882", "category": "Test", "platform": "Console"}, "-866302192": {"name": "Test Ring 883", "category": "Test", "platform": "Console"}, "-866266255": {"name": "Test Ring 884", "category": "Test", "platform": "Console"}, "-866230318": {"name": "Test Ring 885", "category": "Test", "platform": "Console"}, "-866194381": {"name": "Test Ring 886", "category": "Test", "platform": "Console"}, "-866158444": {"name": "Test Ring 887", "category": "Test", "platform": "Console"}, "-866122507": {"name": "Test Ring 888", "category": "Test", "platform": "Console"}, "-866086570": {"name": "Test Ring 889", "category": "Test", "platform": "Console"}, "-865224082": {"name": "Test Ring 890", "category": "Test", "platform": "Console"}, "-865188145": {"name": "Test Ring 891", "category": "Test", "platform": "Console"}, "-865152208": {"name": "Test Ring 892", "category": "Test", "platform": "Console"}, "-865116271": {"name": "Test Ring 893", "category": "Test", "platform": "Console"}, "-865080334": {"name": "Test Ring 894", "category": "Test", "platform": "Console"}, "-865044397": {"name": "Test Ring 895", "category": "Test", "platform": "Console"}, "-865008460": {"name": "Test Ring 896", "category": "Test", "platform": "Console"}, "-864972523": {"name": "Test Ring 897", "category": "Test", "platform": "Console"}, "-864936586": {"name": "Test Ring 898", "category": "Test", "platform": "Console"}, "-864900649": {"name": "Test Ring 899", "category": "Test", "platform": "Console"}, "-836761978": {"name": "Test Ring 900", "category": "Test", "platform": "Console"}, "-836726041": {"name": "Test Ring 901", "category": "Test", "platform": "Console"}, "-836690104": {"name": "Test Ring 902", "category": "Test", "platform": "Console"}, "-836654167": {"name": "Test Ring 903", "category": "Test", "platform": "Console"}, "-836618230": {"name": "Test Ring 904", "category": "Test", "platform": "Console"}, "-836582293": {"name": "Test Ring 905", "category": "Test", "platform": "Console"}, "-836546356": {"name": "Test Ring 906", "category": "Test", "platform": "Console"}, "-836510419": {"name": "Test Ring 907", "category": "Test", "platform": "Console"}, "-836474482": {"name": "Test Ring 908", "category": "Test", "platform": "Console"}, "-836438545": {"name": "Test Ring 909", "category": "Test", "platform": "Console"}, "-835576057": {"name": "Test Ring 910", "category": "Test", "platform": "Console"}, "-835540120": {"name": "Test Ring 911", "category": "Test", "platform": "Console"}, "-835504183": {"name": "Test Ring 912", "category": "Test", "platform": "Console"}, "-835468246": {"name": "Test Ring 913", "category": "Test", "platform": "Console"}, "-835432309": {"name": "Test Ring 914", "category": "Test", "platform": "Console"}, "-835396372": {"name": "Test Ring 915", "category": "Test", "platform": "Console"}, "-835360435": {"name": "Test Ring 916", "category": "Test", "platform": "Console"}, "-835324498": {"name": "Test Ring 917", "category": "Test", "platform": "Console"}, "-835288561": {"name": "Test Ring 918", "category": "Test", "platform": "Console"}, "-835252624": {"name": "Test Ring 919", "category": "Test", "platform": "Console"}, "-834390136": {"name": "Test Ring 920", "category": "Test", "platform": "Console"}, "-834354199": {"name": "Test Ring 921", "category": "Test", "platform": "Console"}, "-834318262": {"name": "Test Ring 922", "category": "Test", "platform": "Console"}, "-834282325": {"name": "Test Ring 923", "category": "Test", "platform": "Console"}, "-834246388": {"name": "Test Ring 924", "category": "Test", "platform": "Console"}, "-834210451": {"name": "Test Ring 925", "category": "Test", "platform": "Console"}, "-834174514": {"name": "Test Ring 926", "category": "Test", "platform": "Console"}, "-834138577": {"name": "Test Ring 927", "category": "Test", "platform": "Console"}, "-834102640": {"name": "Test Ring 928", "category": "Test", "platform": "Console"}, "-834066703": {"name": "Test Ring 929", "category": "Test", "platform": "Console"}, "-833204215": {"name": "Test Ring 930", "category": "Test", "platform": "Console"}, "-833168278": {"name": "Test Ring 931", "category": "Test", "platform": "Console"}, "-833132341": {"name": "Test Ring 932", "category": "Test", "platform": "Console"}, "-833096404": {"name": "Test Ring 933", "category": "Test", "platform": "Console"}, "-833060467": {"name": "Test Ring 934", "category": "Test", "platform": "Console"}, "-833024530": {"name": "Test Ring 935", "category": "Test", "platform": "Console"}, "-832988593": {"name": "Test Ring 936", "category": "Test", "platform": "Console"}, "-832952656": {"name": "Test Ring 937", "category": "Test", "platform": "Console"}, "-832916719": {"name": "Test Ring 938", "category": "Test", "platform": "Console"}, "-832880782": {"name": "Test Ring 939", "category": "Test", "platform": "Console"}, "-832018294": {"name": "Test Ring 940", "category": "Test", "platform": "Console"}, "-831982357": {"name": "Test Ring 941", "category": "Test", "platform": "Console"}, "-831946420": {"name": "Test Ring 942", "category": "Test", "platform": "Console"}, "-831910483": {"name": "Test Ring 943", "category": "Test", "platform": "Console"}, "-831874546": {"name": "Test Ring 944", "category": "Test", "platform": "Console"}, "-831838609": {"name": "Test Ring 945", "category": "Test", "platform": "Console"}, "-831802672": {"name": "Test Ring 946", "category": "Test", "platform": "Console"}, "-831766735": {"name": "Test Ring 947", "category": "Test", "platform": "Console"}, "-831730798": {"name": "Test Ring 948", "category": "Test", "platform": "Console"}, "-831694861": {"name": "Test Ring 949", "category": "Test", "platform": "Console"}, "-830832373": {"name": "Test Ring 950", "category": "Test", "platform": "Console"}, "-830796436": {"name": "Test Ring 951", "category": "Test", "platform": "Console"}, "-830760499": {"name": "Test Ring 952", "category": "Test", "platform": "Console"}, "-830724562": {"name": "Test Ring 953", "category": "Test", "platform": "Console"}, "-830688625": {"name": "Test Ring 954", "category": "Test", "platform": "Console"}, "-830652688": {"name": "Test Ring 955", "category": "Test", "platform": "Console"}, "-830616751": {"name": "Test Ring 956", "category": "Test", "platform": "Console"}, "-830580814": {"name": "Test Ring 957", "category": "Test", "platform": "Console"}, "-830544877": {"name": "Test Ring 958", "category": "Test", "platform": "Console"}, "-830508940": {"name": "Test Ring 959", "category": "Test", "platform": "Console"}, "-829646452": {"name": "Test Ring 960", "category": "Test", "platform": "Console"}, "-829610515": {"name": "Test Ring 961", "category": "Test", "platform": "Console"}, "-829574578": {"name": "Test Ring 962", "category": "Test", "platform": "Console"}, "-829538641": {"name": "Test Ring 963", "category": "Test", "platform": "Console"}, "-829502704": {"name": "Test Ring 964", "category": "Test", "platform": "Console"}, "-829466767": {"name": "Test Ring 965", "category": "Test", "platform": "Console"}, "-829430830": {"name": "Test Ring 966", "category": "Test", "platform": "Console"}, "-829394893": {"name": "Test Ring 967", "category": "Test", "platform": "Console"}, "-829358956": {"name": "Test Ring 968", "category": "Test", "platform": "Console"}, "-829323019": {"name": "Test Ring 969", "category": "Test", "platform": "Console"}, "-828460531": {"name": "Test Ring 970", "category": "Test", "platform": "Console"}, "-828424594": {"name": "Test Ring 971", "category": "Test", "platform": "Console"}, "-828388657": {"name": "Test Ring 972", "category": "Test", "platform": "Console"}, "-828352720": {"name": "Test Ring 973", "category": "Test", "platform": "Console"}, "-828316783": {"name": "Test Ring 974", "category": "Test", "platform": "Console"}, "-828280846": {"name": "Test Ring 975", "category": "Test", "platform": "Console"}, "-828244909": {"name": "Test Ring 976", "category": "Test", "platform": "Console"}, "-828208972": {"name": "Test Ring 977", "category": "Test", "platform": "Console"}, "-828173035": {"name": "Test Ring 978", "category": "Test", "platform": "Console"}, "-828137098": {"name": "Test Ring 979", "category": "Test", "platform": "Console"}, "-827274610": {"name": "Test Ring 980", "category": "Test", "platform": "Console"}, "-827238673": {"name": "Test Ring 981", "category": "Test", "platform": "Console"}, "-827202736": {"name": "Test Ring 982", "category": "Test", "platform": "Console"}, "-827166799": {"name": "Test Ring 983", "category": "Test", "platform": "Console"}, "-827130862": {"name": "Test Ring 984", "category": "Test", "platform": "Console"}, "-827094925": {"name": "Test Ring 985", "category": "Test", "platform": "Console"}, "-827058988": {"name": "Test Ring 986", "category": "Test", "platform": "Console"}, "-827023051": {"name": "Test Ring 987", "category": "Test", "platform": "Console"}, "-826987114": {"name": "Test Ring 988", "category": "Test", "platform": "Console"}, "-826951177": {"name": "Test Ring 989", "category": "Test", "platform": "Console"}, "-826088689": {"name": "Test Ring 990", "category": "Test", "platform": "Console"}, "-826052752": {"name": "Test Ring 991", "category": "Test", "platform": "Console"}, "-826016815": {"name": "Test Ring 992", "category": "Test", "platform": "Console"}, "-825980878": {"name": "Test Ring 993", "category": "Test", "platform": "Console"}, "-825944941": {"name": "Test Ring 994", "category": "Test", "platform": "Console"}, "-825909004": {"name": "Test Ring 995", "category": "Test", "platform": "Console"}, "-825873067": {"name": "Test Ring 996", "category": "Test", "platform": "Console"}, "-825837130": {"name": "Test Ring 997", "category": "Test", "platform": "Console"}, "-825801193": {"name": "Test Ring 998", "category": "Test", "platform": "Console"}, "-825765256": {"name": "Test Ring 999", "category": "Test", "platform": "Console"}}, "Voodoo Masks": {"620034067": {"name": "02: Shaman Mask (AR 36-41)", "category": "Voodoo Masks", "platform": "Console"}, "620034068": {"name": "03: Chieftain Mask (AR 60-69)", "category": "Voodoo Masks", "platform": "Console"}, "620034069": {"name": "04: Spirit Mask (AR 84-113)", "category": "Voodoo Masks", "platform": "Console"}, "620035155": {"name": "05: Woodwraith Bark (AR 114-149)", "category": "Voodoo Masks", "platform": "Console"}, "620035156": {"name": "06: Burial Mask (AR 150-185)", "category": "Voodoo Masks", "platform": "Console"}, "620035157": {"name": "07: Naga Mask (AR 186-232)", "category": "Voodoo Masks", "platform": "Console"}, "620035158": {"name": "08: Umbra Mask (AR 232-254)", "category": "Voodoo Masks", "platform": "Console"}, "620036244": {"name": "09: Screaming Mask (AR 255-322)", "category": "Voodoo Masks", "platform": "Console"}, "620036245": {"name": "10: Underworld Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036246": {"name": "11: Manitou Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036247": {"name": "12: Deva (AR 360-472)", "category": "Voodoo Masks", "platform": "Console"}, "620036248": {"name": "13: Tribal Mask (AR 472-659)", "category": "Voodoo Masks", "platform": "Console"}, "620036249": {"name": "14: Ascended Mask (AR 660-759)", "category": "Voodoo Masks", "platform": "Console"}, "-1716736265": {"name": "Art Test VoodooMask 1", "category": "Voodoo Masks", "platform": "Console"}, "-1716736264": {"name": "Art Test VoodooMask 2", "category": "Voodoo Masks", "platform": "Console"}, "-1716736263": {"name": "Art Test VoodooMask 3", "category": "Voodoo Masks", "platform": "Console"}, "-1716736262": {"name": "Art Test VoodooMask 4", "category": "Voodoo Masks", "platform": "Console"}, "-1716736261": {"name": "Art Test VoodooMask 5", "category": "Voodoo Masks", "platform": "Console"}, "-801205711": {"name": "Legendary: Carnevil", "category": "Voodoo Masks", "platform": "Console"}, "-801169774": {"name": "Legendary: Mask of Jeram", "category": "Voodoo Masks", "platform": "Console"}, "-840197356": {"name": "Legendary: Quetzalcoatl", "category": "Voodoo Masks", "platform": "Console"}, "-1956786272": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1956783828": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555852": {"name": "Legendary: Quetzalcoatl (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840161419": {"name": "Legendary: Split Tusk", "category": "Voodoo Masks", "platform": "Console"}, "-1955600351": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1955597907": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555853": {"name": "Legendary: Split Tusk (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840305167": {"name": "Legendary: The Grin Reaper", "category": "Voodoo Masks", "platform": "Console"}, "-1960344035": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1960341591": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555849": {"name": "Legendary: The Grin Reaper (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840341104": {"name": "Legendary: Tiklandian Visage", "category": "Voodoo Masks", "platform": "Console"}, "-1961529956": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1961527512": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555848": {"name": "Legendary: Tiklandian Visage (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840089545": {"name": "Legendary: Visage of Giyua", "category": "Voodoo Masks", "platform": "Console"}, "-1953228509": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1953226065": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555855": {"name": "Legendary: Visage of Giyua (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555854": {"name": "Set: Zunimassa's Attunement (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840125482": {"name": "Set: Zunimassa's Vision", "category": "Voodoo Masks", "platform": "Console"}, "-1954414430": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1954411986": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}}, "Wands": {"88665050": {"name": "01: Lesser Wand (DPS 9.8-11.2)", "category": "Wands", "platform": "Console"}, "88665051": {"name": "02: Oak Wand (DPS 11.2-13.3)", "category": "Wands", "platform": "Console"}, "88665052": {"name": "03: Wand (DPS 14.7-16.8)", "category": "Wands", "platform": "Console"}, "88665053": {"name": "04: Steel Wand (DPS 17.5-19.6)", "category": "Wands", "platform": "Console"}, "88665054": {"name": "05: Mentor Wand (DPS 21.7-23.8)", "category": "Wands", "platform": "Console"}, "88665055": {"name": "06: Enchanter Wand (DPS 25.2-27.3)", "category": "Wands", "platform": "Console"}, "88665056": {"name": "07: Grim Wand (DPS 29.4-31.5)", "category": "Wands", "platform": "Console"}, "88666139": {"name": "08: Petrified Wand (DPS 41.3-43.4)", "category": "Wands", "platform": "Console"}, "88666140": {"name": "09: Duelist Wand (DPS 47.6-49.7)", "category": "Wands", "platform": "Console"}, "88666141": {"name": "10: Jade Wand (DPS 55.3-57.4)", "category": "Wands", "platform": "Console"}, "88666142": {"name": "11: Battle Wand (DPS 65.1-67.2)", "category": "Wands", "platform": "Console"}, "88666143": {"name": "12: Divination Wand (DPS 75.6-77.7)", "category": "Wands", "platform": "Console"}, "88666144": {"name": "13: Sorcery Wand (DPS 89.6-93.8)", "category": "Wands", "platform": "Console"}, "88666145": {"name": "14: Silversteel Wand (DPS 105.0-109.2)", "category": "Wands", "platform": "Console"}, "88667228": {"name": "15: Greater Wand (DPS 115.5-119.7)", "category": "Wands", "platform": "Console"}, "88667229": {"name": "16: Guardian (DPS 127.4-131.6)", "category": "Wands", "platform": "Console"}, "88667230": {"name": "17: Magus Wand (DPS 139.3-145.6)", "category": "Wands", "platform": "Console"}, "88667231": {"name": "18: Spellbinder (DPS 153.3-159.6)", "category": "Wands", "platform": "Console"}, "88667232": {"name": "19: Archmage Wand (DPS 177.1-183.4)", "category": "Wands", "platform": "Console"}, "88667233": {"name": "20: Strike Wand (DPS 203.0-211.4)", "category": "Wands", "platform": "Console"}, "88667234": {"name": "21: Desolator Wand (DPS 235.2-243.6)", "category": "Wands", "platform": "Console"}, "88668317": {"name": "22: Demon's Head Wand (DPS 315.0-321.3)", "category": "Wands", "platform": "Console"}, "88668318": {"name": "23: Diabolic Wand (DPS 385.0-391.3)", "category": "Wands", "platform": "Console"}, "2004783359": {"name": "Art Test Wand 1", "category": "Wands", "platform": "Console"}, "2004783360": {"name": "Art Test Wand 2", "category": "Wands", "platform": "Console"}, "2004783361": {"name": "Art Test Wand 3", "category": "Wands", "platform": "Console"}, "2004783362": {"name": "Art Test Wand 4", "category": "Wands", "platform": "Console"}, "2004783363": {"name": "Art Test Wand 5", "category": "Wands", "platform": "Console"}, "456527018": {"name": "Crafted: Elderwood Wand", "category": "Wands", "platform": "Console"}, "-1415147493": {"name": "Legendary: Aether Walker (Patch 2.1.0)", "category": "Wands", "platform": "Console"}, "1859914464": {"name": "Legendary: Atrophy", "category": "Wands", "platform": "Console"}, "1859806653": {"name": "Legendary: Blackhand Key", "category": "Wands", "platform": "Console"}, "1244000105": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "1244002549": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "161873429": {"name": "Legendary: Blackhand Key (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860776952": {"name": "Legendary: Fragment of Destiny", "category": "Wands", "platform": "Console"}, "1276019972": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "1276022416": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "161873456": {"name": "Legendary: Fragment of Destiny (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859662905": {"name": "Legendary: Gesture of Orpheus", "category": "Wands", "platform": "Console"}, "1239256421": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "1239258865": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "161873425": {"name": "Legendary: Gesture of Orpheus (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1247557868": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "1247560312": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "161873432": {"name": "Legendary: Ruinstoke (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898798298": {"name": "Legendary: Serpent's Sparker", "category": "Wands", "platform": "Console"}, "1860884763": {"name": "Legendary: Slorak's Madness", "category": "Wands", "platform": "Console"}, "1279577735": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "1279580179": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "161873459": {"name": "Legendary: Slorak's Madness (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859698842": {"name": "Legendary: Starfire", "category": "Wands", "platform": "Console"}, "1240442342": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "1240444786": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "161873426": {"name": "Legendary: Starfire (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898762361": {"name": "Legendary: Wand of Woh", "category": "Wands", "platform": "Console"}, "-1415147492": {"name": "P1 Wand norm Legendary 02", "category": "Wands", "platform": "Console"}, "161873458": {"name": "Set: Chantodo's Sacred Protector (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860848826": {"name": "Set: Chantodo's Will", "category": "Wands", "platform": "Console"}, "1278391814": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1278394258": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1861064448": {"name": "Set: Hallowed Baton", "category": "Wands", "platform": "Console"}, "161873464": {"name": "Set: Hallowed Rod (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1285507340": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1285509784": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1771839282": {"name": "legendary: Gesture Of Orpheus (Patch 2.2.0)", "category": "Wands", "platform": "Console"}}, "Wizard Hats": {"1755621631": {"name": "02: Journey Mask (AR 36-41)", "category": "Wizard Hats", "platform": "Console"}, "1755621632": {"name": "03: Scholarly Fez (AR 60-69)", "category": "Wizard Hats", "platform": "Console"}, "1755621633": {"name": "04: Charlatan Cap (AR 84-113)", "category": "Wizard Hats", "platform": "Console"}, "1755622719": {"name": "05: Conjurer Shade (AR 114-149)", "category": "Wizard Hats", "platform": "Console"}, "1755622720": {"name": "06: Mystic Shade (AR 150-185)", "category": "Wizard Hats", "platform": "Console"}, "1755622721": {"name": "07: Mentor Cap (AR 186-232)", "category": "Wizard Hats", "platform": "Console"}, "1755622722": {"name": "08: Traveler Hat (AR 232-254)", "category": "Wizard Hats", "platform": "Console"}, "1755623808": {"name": "09: Sage Hat (AR 255-284)", "category": "Wizard Hats", "platform": "Console"}, "1755623809": {"name": "10: Sinister Mask (AR 285-322)", "category": "Wizard Hats", "platform": "Console"}, "1755623810": {"name": "11: Archmage Headpiece (AR 322-359)", "category": "Wizard Hats", "platform": "Console"}, "1755623811": {"name": "12: Elder Hat (AR 360-472)", "category": "Wizard Hats", "platform": "Console"}, "1755623812": {"name": "13: Vizier Hat (AR 472-659)", "category": "Wizard Hats", "platform": "Console"}, "1755623813": {"name": "14: Ascended Headpiece (AR 660-759)", "category": "Wizard Hats", "platform": "Console"}, "376117315": {"name": "Art Test WizardHat 1", "category": "Wizard Hats", "platform": "Console"}, "376117316": {"name": "Art Test WizardHat 2", "category": "Wizard Hats", "platform": "Console"}, "376117317": {"name": "Art Test WizardHat 3", "category": "Wizard Hats", "platform": "Console"}, "376117318": {"name": "Art Test WizardHat 4", "category": "Wizard Hats", "platform": "Console"}, "376117319": {"name": "Art Test WizardHat 5", "category": "Wizard Hats", "platform": "Console"}, "414491869": {"name": "Legendary: Archmage's Vicalyke", "category": "Wizard Hats", "platform": "Console"}, "375356476": {"name": "Legendary: Dark Mage's Shade", "category": "Wizard Hats", "platform": "Console"}, "-498215480": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-498213036": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827188": {"name": "Legendary: Dark Mage's Shade (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414599680": {"name": "Legendary: Mask of Lies", "category": "Wizard Hats", "platform": "Console"}, "375464287": {"name": "Legendary: Storm Crow", "category": "Wizard Hats", "platform": "Console"}, "-494657717": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-494655273": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827191": {"name": "Legendary: Storm Crow (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414563743": {"name": "Legendary: The Magistrate", "category": "Wizard Hats", "platform": "Console"}, "375428350": {"name": "Legendary: The Swami", "category": "Wizard Hats", "platform": "Console"}, "-495843638": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-495841194": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827190": {"name": "Legendary: The Swami (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-936099818": {"name": "Legendary: The Swami (Patch 2.1.0)", "category": "Wizard Hats", "platform": "Console"}, "414527806": {"name": "Legendary: Velvet Camaral", "category": "Wizard Hats", "platform": "Console"}}} \ No newline at end of file +{"None": {}, "Amulets": {"1682228618": {"name": "02: Amulet", "category": "Amulets", "platform": "Console"}, "1682228619": {"name": "03: Amulet", "category": "Amulets", "platform": "Console"}, "1682228620": {"name": "04: Amulet", "category": "Amulets", "platform": "Console"}, "1682228621": {"name": "05: Amulet", "category": "Amulets", "platform": "Console"}, "1682228622": {"name": "06: Amulet", "category": "Amulets", "platform": "Console"}, "1682228623": {"name": "07: Amulet", "category": "Amulets", "platform": "Console"}, "1682228624": {"name": "08: Amulet", "category": "Amulets", "platform": "Console"}, "1682228625": {"name": "09: Amulet", "category": "Amulets", "platform": "Console"}, "1682228649": {"name": "10: Amulet", "category": "Amulets", "platform": "Console"}, "1682228650": {"name": "11: Amulet", "category": "Amulets", "platform": "Console"}, "1682228651": {"name": "12: Amulet", "category": "Amulets", "platform": "Console"}, "1682228652": {"name": "13: Amulet", "category": "Amulets", "platform": "Console"}, "1682228653": {"name": "14: Amulet", "category": "Amulets", "platform": "Console"}, "1682228654": {"name": "15: Amulet", "category": "Amulets", "platform": "Console"}, "1682228655": {"name": "16: Amulet", "category": "Amulets", "platform": "Console"}, "1682228656": {"name": "17: Amulet", "category": "Amulets", "platform": "Console"}, "-1335710051": {"name": "Art Test Amulet 1", "category": "Amulets", "platform": "Console"}, "-1335710050": {"name": "Art Test Amulet 2", "category": "Amulets", "platform": "Console"}, "-1335710049": {"name": "Art Test Amulet 3", "category": "Amulets", "platform": "Console"}, "-1335710048": {"name": "Art Test Amulet 4", "category": "Amulets", "platform": "Console"}, "-1335710047": {"name": "Art Test Amulet 5", "category": "Amulets", "platform": "Console"}, "1566332280": {"name": "Legendary: Ancestors' Grace", "category": "Amulets", "platform": "Console"}, "1566368217": {"name": "Legendary: Countess Julia's Cameo", "category": "Amulets", "platform": "Console"}, "1566511965": {"name": "Legendary: Dovu Energy Trap", "category": "Amulets", "platform": "Console"}, "1200923753": {"name": "Legendary: Drake's Amulet (PS3 Promo)", "category": "Amulets", "platform": "Console"}, "1528454682": {"name": "Legendary: Eye of Etlich", "category": "Amulets", "platform": "Console"}, "-1100680346": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "-1100677902": {"name": "Legendary: Eye of Etlich (Legacy)", "category": "Amulets", "platform": "Console"}, "412126098": {"name": "Legendary: Eye of Etlich (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566440091": {"name": "Legendary: Golden Gorget of Leoric", "category": "Amulets", "platform": "Console"}, "1566583839": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "737941201": {"name": "Legendary: Halcyon's Ascent", "category": "Amulets", "platform": "Console"}, "1566296343": {"name": "Legendary: Haunt of Vaxo", "category": "Amulets", "platform": "Console"}, "761548935": {"name": "Legendary: Hellfire Amulet (Patch 1.2.0)", "category": "Amulets", "platform": "Console"}, "1528418745": {"name": "Legendary: Holy Beacon", "category": "Amulets", "platform": "Console"}, "-1101866267": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "-1101863823": {"name": "Legendary: Holy Beacon (Legacy)", "category": "Amulets", "platform": "Console"}, "412126097": {"name": "Legendary: Holy Beacon (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196887": {"name": "Legendary: Kymbo's Gold", "category": "Amulets", "platform": "Console"}, "-1142187581": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "-1142185137": {"name": "Legendary: Kymbo's Gold (Legacy)", "category": "Amulets", "platform": "Console"}, "412126063": {"name": "Legendary: Kymbo's Gold (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527196623": {"name": "Legendary: Kymbo's Gold (Patch 2.1.0)", "category": "Amulets", "platform": "Console"}, "1528490619": {"name": "Legendary: Mara's Kaleidoscope", "category": "Amulets", "platform": "Console"}, "-1099494425": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "-1099491981": {"name": "Legendary: Mara's Kaleidoscope (Legacy)", "category": "Amulets", "platform": "Console"}, "412126099": {"name": "Legendary: Mara's Kaleidoscope (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527232824": {"name": "Legendary: Moonlight Ward", "category": "Amulets", "platform": "Console"}, "-1141001660": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "-1140999216": {"name": "Legendary: Moonlight Ward (Legacy)", "category": "Amulets", "platform": "Console"}, "412126064": {"name": "Legendary: Moonlight Ward (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527304698": {"name": "Legendary: Ouroboros", "category": "Amulets", "platform": "Console"}, "-1138629818": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "-1138627374": {"name": "Legendary: Ouroboros (Legacy)", "category": "Amulets", "platform": "Console"}, "412126066": {"name": "Legendary: Ouroboros (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566476028": {"name": "Legendary: Overwhelming Desire", "category": "Amulets", "platform": "Console"}, "1566547902": {"name": "Legendary: Rakoff's Glass of Life", "category": "Amulets", "platform": "Console"}, "1527448446": {"name": "Legendary: Rondal's Locket", "category": "Amulets", "platform": "Console"}, "-1133886134": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1133883690": {"name": "Legendary: Rondal's Locket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126070": {"name": "Legendary: Rondal's Locket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528310934": {"name": "Legendary: Squirt's Necklace", "category": "Amulets", "platform": "Console"}, "-1105424030": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "-1105421586": {"name": "Legendary: Squirt's Necklace (Legacy)", "category": "Amulets", "platform": "Console"}, "412126094": {"name": "Legendary: Squirt's Necklace (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528382808": {"name": "Legendary: Talisman of Aranoch", "category": "Amulets", "platform": "Console"}, "-1103052188": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "-1103049744": {"name": "Legendary: Talisman of Aranoch (Legacy)", "category": "Amulets", "platform": "Console"}, "412126096": {"name": "Legendary: Talisman of Aranoch (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1566404154": {"name": "Legendary: The Ess of Johan", "category": "Amulets", "platform": "Console"}, "1527160950": {"name": "Legendary: The Flavor of Time", "category": "Amulets", "platform": "Console"}, "-1143373502": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "-1143371058": {"name": "Legendary: The Flavor of Time (Legacy)", "category": "Amulets", "platform": "Console"}, "412126062": {"name": "Legendary: The Flavor of Time (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1528346871": {"name": "Legendary: The Murlocket", "category": "Amulets", "platform": "Console"}, "-1104238109": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "-1104235665": {"name": "Legendary: The Murlocket (Legacy)", "category": "Amulets", "platform": "Console"}, "412126095": {"name": "Legendary: The Murlocket (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527340635": {"name": "Legendary: The Star of Azkaranth", "category": "Amulets", "platform": "Console"}, "-1137443897": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "-1137441453": {"name": "Legendary: The Star of Azkaranth (Legacy)", "category": "Amulets", "platform": "Console"}, "412126067": {"name": "Legendary: The Star of Azkaranth (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527268761": {"name": "Legendary: Xephirian Amulet", "category": "Amulets", "platform": "Console"}, "-1139815739": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "-1139813295": {"name": "Legendary: Xephirian Amulet (Legacy)", "category": "Amulets", "platform": "Console"}, "412126065": {"name": "Legendary: Xephirian Amulet (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "714520304": {"name": "PvP: Art of War 3v3", "category": "Amulets", "platform": "Console"}, "1685772266": {"name": "PvP: Art of War All", "category": "Amulets", "platform": "Console"}, "1685772538": {"name": "PvP: Art of War Attack", "category": "Amulets", "platform": "Console"}, "1685775296": {"name": "PvP: Art of War Defense", "category": "Amulets", "platform": "Console"}, "-203544613": {"name": "PvP: Art of War Precision", "category": "Amulets", "platform": "Console"}, "1685795044": {"name": "PvP: Art of War Vitality", "category": "Amulets", "platform": "Console"}, "-203302615": {"name": "PvP: Art of War Willpower", "category": "Amulets", "platform": "Console"}, "1803178445": {"name": "PvP: Born for War All", "category": "Amulets", "platform": "Console"}, "1803178717": {"name": "PvP: Born for War Attack", "category": "Amulets", "platform": "Console"}, "1803181475": {"name": "PvP: Born for War Defense", "category": "Amulets", "platform": "Console"}, "-624108002": {"name": "PvP: Born for War Precision", "category": "Amulets", "platform": "Console"}, "1803201223": {"name": "PvP: Born for War Vitality", "category": "Amulets", "platform": "Console"}, "1528526556": {"name": "Set: Blackthorne's Duncraig Cross", "category": "Amulets", "platform": "Console"}, "-1098308504": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "-1098306060": {"name": "Set: Blackthorne's Duncraig Cross (Legacy)", "category": "Amulets", "platform": "Console"}, "412126100": {"name": "Set: Blackthorne's Medal (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "412126069": {"name": "Set: Spirit of Adventure (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "-1544505070": {"name": "Set: Sunwuko's Shines", "category": "Amulets", "platform": "Console"}, "412126068": {"name": "Set: Tal Rasha's Adjudication (Old-Legacy)", "category": "Amulets", "platform": "Console"}, "1527376572": {"name": "Set: Tal Rasha's Allegiance", "category": "Amulets", "platform": "Console"}, "-1136257976": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "-1136255532": {"name": "Set: Tal Rasha's Allegiance (Legacy)", "category": "Amulets", "platform": "Console"}, "1527412509": {"name": "Set: The Traveler's Pledge", "category": "Amulets", "platform": "Console"}, "-1135072055": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-1135069611": {"name": "Set: The Traveler's Pledge (Legacy)", "category": "Amulets", "platform": "Console"}, "-795161790": {"name": "legendary: Moonlight Ward (Patch 2.2.0)", "category": "Amulets", "platform": "Console"}}, "Axes, One-Handed": {"1661412390": {"name": "01: Hand Axe (DPS 3.3-4.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412391": {"name": "02: Broad Axe (DPS 7.2-9.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412392": {"name": "03: Double Axe (DPS 12.4-14.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412393": {"name": "04: Heavy Axe (DPS 17.6-19.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412394": {"name": "05: Battle Axe (DPS 21.5-23.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412395": {"name": "06: Marauder Axe (DPS 26.7-28.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661412396": {"name": "07: Soldier Axe (DPS 31.2-33.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413479": {"name": "08: Hatchet (DPS 36.4-38.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413480": {"name": "09: Ono (DPS 46.2-48.1)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413481": {"name": "10: Bullova (DPS 57.2-59.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413482": {"name": "11: Adze (DPS 69.6-73.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413483": {"name": "12: Chopper (DPS 86.5-90.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413484": {"name": "13: Toporok (DPS 101.4-105.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661413485": {"name": "14: Masakari (DPS 118.3-122.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414568": {"name": "15: Tomahawk (DPS 129.4-135.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414569": {"name": "16: Crescent Axe (DPS 144.3-150.2)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414570": {"name": "17: Arreat Axe (DPS 160.6-166.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414571": {"name": "18: Balestarius (DPS 177.5-185.3)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414572": {"name": "19: Skartaran Axe (DPS 206.7-214.5)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414573": {"name": "20: Galraki (DPS 238.6-246.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661414574": {"name": "21: Arch Axe (DPS 275.6-285.4)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415657": {"name": "22: Executioner's Axe (DPS 371.8-379.6)", "category": "Axes, One-Handed", "platform": "Console"}, "1661415658": {"name": "23: Dire Axe (DPS 461.5-469.3)", "category": "Axes, One-Handed", "platform": "Console"}, "-657929333": {"name": "Art Test Axe One-Handed 1", "category": "Axes, One-Handed", "platform": "Console"}, "-657929332": {"name": "Art Test Axe One-Handed 2", "category": "Axes, One-Handed", "platform": "Console"}, "-657929331": {"name": "Art Test Axe One-Handed 3", "category": "Axes, One-Handed", "platform": "Console"}, "-657929330": {"name": "Art Test Axe One-Handed 4", "category": "Axes, One-Handed", "platform": "Console"}, "-657929329": {"name": "Art Test Axe One-Handed 5", "category": "Axes, One-Handed", "platform": "Console"}, "824126149": {"name": "Legendary: Aidan's Revenge", "category": "Axes, One-Handed", "platform": "Console"}, "824162086": {"name": "Legendary: Fenris Tooth", "category": "Axes, One-Handed", "platform": "Console"}, "784990756": {"name": "Legendary: Flesh Tearer", "category": "Axes, One-Handed", "platform": "Console"}, "134813872": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "134816316": {"name": "Legendary: Flesh Tearer (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046948": {"name": "Legendary: Flesh Tearer (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785062630": {"name": "Legendary: Genzaniku", "category": "Axes, One-Handed", "platform": "Console"}, "137185714": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "137188158": {"name": "Legendary: Genzaniku (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046946": {"name": "Legendary: Genzaniku (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "824198023": {"name": "Legendary: Hack", "category": "Axes, One-Handed", "platform": "Console"}, "785134504": {"name": "Legendary: Sky Splitter", "category": "Axes, One-Handed", "platform": "Console"}, "139557556": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "139560000": {"name": "Legendary: Sky Splitter (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046944": {"name": "Legendary: Sky Splitter (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785206378": {"name": "Legendary: The Burning Axe of Sankis", "category": "Axes, One-Handed", "platform": "Console"}, "141929398": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "141931842": {"name": "Legendary: The Burning Axe of Sankis (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046942": {"name": "Legendary: The Burning Axe of Sankis (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785170441": {"name": "Legendary: The Butcher's Sickle", "category": "Axes, One-Handed", "platform": "Console"}, "140743477": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "140745921": {"name": "Legendary: The Butcher's Sickle (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046943": {"name": "Legendary: The Butcher's Sickle (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138371635": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "138374079": {"name": "Legendary: The Wedge (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "-219046945": {"name": "Legendary: The Wedge (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785098567": {"name": "Legendary: Utar's Roar", "category": "Axes, One-Handed", "platform": "Console"}, "786248551": {"name": "Set: Hallowed Breach", "category": "Axes, One-Handed", "platform": "Console"}, "-219046913": {"name": "Set: Hallowed Divide (Old-Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176321107": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "176323551": {"name": "Set: Hallowed Storm (Legacy)", "category": "Axes, One-Handed", "platform": "Console"}, "785134241": {"name": "legendary: Sky Spliiter (Patch 2.2.0)", "category": "Axes, One-Handed", "platform": "Console"}}, "Axes, Two-Handed": {"1700547784": {"name": "02: War Axe (DPS 16.0-17.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547785": {"name": "03: Tabarzin (DPS 22.5-24.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547786": {"name": "04: Military Axe (DPS 31.5-33.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700547787": {"name": "05: Great Axe (DPS 42.5-44.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548872": {"name": "06: Timber Axe (DPS 56.5-59.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548873": {"name": "07: Francisca (DPS 73.5-76.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548874": {"name": "08: Fang Axe (DPS 94.0-98.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548875": {"name": "09: Parashu (DPS 119.0-125.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700548876": {"name": "10: Labrys (DPS 170.0-177.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549961": {"name": "11: Fell Axe (DPS 230.5-241.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549962": {"name": "12: Valaska (DPS 313.0-325.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549963": {"name": "13: Ripper Axe (DPS 400.0-412.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549964": {"name": "14: Sagaris (DPS 474.5-486.5)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700549965": {"name": "15: Decapitator (DPS 560.0-572.0)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551050": {"name": "16: Dread Axe (DPS 698.0-711.2)", "category": "Axes, Two-Handed", "platform": "Console"}, "1700551051": {"name": "17: Flesh Render (DPS 948.2-961.4)", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893396": {"name": "Art Test Axe Two-Handed 1", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893395": {"name": "Art Test Axe Two-Handed 2", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893394": {"name": "Art Test Axe Two-Handed 3", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893393": {"name": "Art Test Axe Two-Handed 4", "category": "Axes, Two-Handed", "platform": "Console"}, "-657893392": {"name": "Art Test Axe Two-Handed 5", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516456824": {"name": "Legendary: Burst of Wrath", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555664091": {"name": "Legendary: Butcher's Carver", "category": "Axes, Two-Handed", "platform": "Console"}, "202615249": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "202617693": {"name": "Legendary: Butcher's Carver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911555": {"name": "Legendary: Butcher's Carver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554514107": {"name": "Legendary: Cinder Switch", "category": "Axes, Two-Handed", "platform": "Console"}, "240564721": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "240567165": {"name": "Legendary: Fire Brand (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911523": {"name": "Legendary: Fire Brand (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1554478170": {"name": "Legendary: Messerschmidt's Reaver", "category": "Axes, Two-Handed", "platform": "Console"}, "241750642": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "241753086": {"name": "Legendary: Messerschmidt's Reaver (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911522": {"name": "Legendary: Messerschmidt's Reaver (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516420887": {"name": "Legendary: Saint of Slaughter", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555376595": {"name": "Legendary: Skorn", "category": "Axes, Two-Handed", "platform": "Console"}, "212102617": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "212105061": {"name": "Legendary: Skorn (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911547": {"name": "Legendary: Skorn (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516492761": {"name": "Legendary: Sungjae's Fury", "category": "Axes, Two-Handed", "platform": "Console"}, "-1555592217": {"name": "Legendary: The Executioner", "category": "Axes, Two-Handed", "platform": "Console"}, "204987091": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "204989535": {"name": "Legendary: The Executioner (Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-179911553": {"name": "Legendary: The Executioner (Old-Legacy)", "category": "Axes, Two-Handed", "platform": "Console"}, "-1516528698": {"name": "Legendary: The Marauder", "category": "Axes, Two-Handed", "platform": "Console"}, "120887006": {"name": "PvP: Heroic Reaper", "category": "Axes, Two-Handed", "platform": "Console"}, "120887005": {"name": "PvP: Mighty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}, "120887004": {"name": "PvP: Trusty Battleaxe", "category": "Axes, Two-Handed", "platform": "Console"}}, "Belts": {"-733831368": {"name": "02: Hide Belt (AR 24-28)", "category": "Belts", "platform": "Console"}, "-733831367": {"name": "03: Leather Belt (AR 14-16)", "category": "Belts", "platform": "Console"}, "-733831366": {"name": "04: Cord (AR 44-53)", "category": "Belts", "platform": "Console"}, "-733831365": {"name": "05: Binding Rope (AR 54-67)", "category": "Belts", "platform": "Console"}, "-733831364": {"name": "06: Chain Belt (AR 34-43)", "category": "Belts", "platform": "Console"}, "-733830280": {"name": "07: Silk Sash (AR 68-87)", "category": "Belts", "platform": "Console"}, "-733830279": {"name": "08: Waistwrap (AR 88-107)", "category": "Belts", "platform": "Console"}, "-733830278": {"name": "09: Strand (AR 108-127)", "category": "Belts", "platform": "Console"}, "-733830277": {"name": "10: Cupola (AR 128-149)", "category": "Belts", "platform": "Console"}, "-733830276": {"name": "11: Cinch (AR 150-164)", "category": "Belts", "platform": "Console"}, "-733829191": {"name": "12: Grasp (AR 165-179)", "category": "Belts", "platform": "Console"}, "-733829190": {"name": "13: Sheath (AR 180-189)", "category": "Belts", "platform": "Console"}, "-733829189": {"name": "14: Cincture (AR 190-214)", "category": "Belts", "platform": "Console"}, "-733829188": {"name": "15: Girdle (AR 215-239)", "category": "Belts", "platform": "Console"}, "-733829187": {"name": "16: Heaven Strand (AR 240-264)", "category": "Belts", "platform": "Console"}, "-733829186": {"name": "17: High Scabbard (AR 265-314)", "category": "Belts", "platform": "Console"}, "-733829185": {"name": "18: War Belt (AR 315-439)", "category": "Belts", "platform": "Console"}, "-733829184": {"name": "19: Archon Sash (AR 440-506)", "category": "Belts", "platform": "Console"}, "1187629340": {"name": "Art Test Belt 1", "category": "Belts", "platform": "Console"}, "1187629341": {"name": "Art Test Belt 2", "category": "Belts", "platform": "Console"}, "1187629342": {"name": "Art Test Belt 3", "category": "Belts", "platform": "Console"}, "1187629343": {"name": "Art Test Belt 4", "category": "Belts", "platform": "Console"}, "1187629344": {"name": "Art Test Belt 5", "category": "Belts", "platform": "Console"}, "949342869": {"name": "Belt Of The Trove (Patch 2.1.2)", "category": "Belts", "platform": "Console"}, "1770820311": {"name": "Legendary: Angel Hair Braid", "category": "Belts", "platform": "Console"}, "-1692549181": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-1692546737": {"name": "Legendary: Angel Hair Braid (Legacy)", "category": "Belts", "platform": "Console"}, "-660622993": {"name": "Legendary: Angel Hair Braid (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770820047": {"name": "Legendary: Angel Hair Braid (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1809991641": {"name": "Legendary: Cord of the Sherma", "category": "Belts", "platform": "Console"}, "1770856248": {"name": "Legendary: Fleeting Strap", "category": "Belts", "platform": "Console"}, "1771898421": {"name": "Legendary: Goldwrap", "category": "Belts", "platform": "Console"}, "-1656971551": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1656969107": {"name": "Legendary: Goldwrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622963": {"name": "Legendary: Goldwrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810027578": {"name": "Legendary: Harrington Waistguard", "category": "Belts", "platform": "Console"}, "1770892185": {"name": "Legendary: Hellcat Waistguard", "category": "Belts", "platform": "Console"}, "-1690177339": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-1690174895": {"name": "Legendary: Hellcat Waistguard (Legacy)", "category": "Belts", "platform": "Console"}, "-660622991": {"name": "Legendary: Hellcat Waistguard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1810099452": {"name": "Legendary: Hwoj Wrap", "category": "Belts", "platform": "Console"}, "1809955704": {"name": "Legendary: Insatiable Belt", "category": "Belts", "platform": "Console"}, "1810063515": {"name": "Legendary: Jang's Envelopment", "category": "Belts", "platform": "Console"}, "-1691363260": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1691360816": {"name": "Legendary: Quick Draw Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622992": {"name": "Legendary: Quick Draw Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809883830": {"name": "Legendary: Razor Strop", "category": "Belts", "platform": "Console"}, "1770748437": {"name": "Legendary: Saffron Wrap", "category": "Belts", "platform": "Console"}, "-1694921023": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-1694918579": {"name": "Legendary: Saffron Wrap (Legacy)", "category": "Belts", "platform": "Console"}, "-660622995": {"name": "Legendary: Saffron Wrap (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1809919767": {"name": "Legendary: Sash of Knives", "category": "Belts", "platform": "Console"}, "1809919503": {"name": "Legendary: Sash of Knives (Patch 2.1.0)", "category": "Belts", "platform": "Console"}, "1810135389": {"name": "Legendary: Sebor's Nightmare", "category": "Belts", "platform": "Console"}, "1770999996": {"name": "Legendary: String of Ears", "category": "Belts", "platform": "Console"}, "-1686619576": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-1686617132": {"name": "Legendary: String of Ears (Legacy)", "category": "Belts", "platform": "Console"}, "-660622988": {"name": "Legendary: String of Ears (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1771035933": {"name": "Legendary: The Witching Hour", "category": "Belts", "platform": "Console"}, "-1685433655": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-1685431211": {"name": "Legendary: The Witching Hour (Legacy)", "category": "Belts", "platform": "Console"}, "-660622987": {"name": "Legendary: The Witching Hour (Old-Legacy)", "category": "Belts", "platform": "Console"}, "924103246": {"name": "Legendary: Thundergod's Vigor", "category": "Belts", "platform": "Console"}, "1770784374": {"name": "Legendary: Vigilante Belt", "category": "Belts", "platform": "Console"}, "-1693735102": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1693732658": {"name": "Legendary: Vigilante Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622994": {"name": "Legendary: Vigilante Belt (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1772078106": {"name": "Set: Blackthorne's Notched Belt", "category": "Belts", "platform": "Console"}, "-1651041946": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-1651039502": {"name": "Set: Blackthorne's Notched Belt (Legacy)", "category": "Belts", "platform": "Console"}, "-660622958": {"name": "Set: Blackthorne's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-660622961": {"name": "Set: Captain Crimson's Brace (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1654599709": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "-1654597265": {"name": "Set: Captain Crimson's Satin Sash (Legacy)", "category": "Belts", "platform": "Console"}, "1771970295": {"name": "Set: Captain Crimson's Silk Girdle", "category": "Belts", "platform": "Console"}, "-660622959": {"name": "Set: Demon's Binding (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1652227867": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "-1652225423": {"name": "Set: Demon's Lock (Legacy)", "category": "Belts", "platform": "Console"}, "1772042169": {"name": "Set: Demon's Restraint", "category": "Belts", "platform": "Console"}, "1772006232": {"name": "Set: Guardian's Case", "category": "Belts", "platform": "Console"}, "-660622960": {"name": "Set: Guardian's Scabbard (Old-Legacy)", "category": "Belts", "platform": "Console"}, "-1653413788": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-1653411344": {"name": "Set: Guardian's Sheath (Legacy)", "category": "Belts", "platform": "Console"}, "-660622989": {"name": "Set: Inna's Blessing (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1770964059": {"name": "Set: Inna's Favor", "category": "Belts", "platform": "Console"}, "-1687805497": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-1687803053": {"name": "Set: Inna's Favor (Legacy)", "category": "Belts", "platform": "Console"}, "-885483983": {"name": "Set: Krelm's Buff Belt", "category": "Belts", "platform": "Console"}, "1770928122": {"name": "Set: Tal Rasha's Brace", "category": "Belts", "platform": "Console"}, "-1688991418": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-1688988974": {"name": "Set: Tal Rasha's Brace (Legacy)", "category": "Belts", "platform": "Console"}, "-660622990": {"name": "Set: Tal Rasha's Finespun Cloth (Old-Legacy)", "category": "Belts", "platform": "Console"}, "1069972162": {"name": "legendary: Belessed of Haull (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972159": {"name": "legendary: Belt of Transcendence (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972158": {"name": "legendary: Crashing Rain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972160": {"name": "legendary: Haunting Girdle (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972161": {"name": "legendary: Omnislash (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1069972163": {"name": "legendary: Omryn's Chain (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809919504": {"name": "legendary: Sash of Knives (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1810135126": {"name": "legendary: Sebor's Nightmare (Patch 2.2.0)", "category": "Belts", "platform": "Console"}, "1809991378": {"name": "legendary: Sherma of Corrosion (Patch 2.2.0)", "category": "Belts", "platform": "Console"}}, "Boots": {"2140880152": {"name": "02: Boots (AR 16-18)", "category": "Boots", "platform": "Console"}, "2140880153": {"name": "03: Heavy Boots (AR 30-35)", "category": "Boots", "platform": "Console"}, "2140880154": {"name": "04: Chain Boots (AR 44-57)", "category": "Boots", "platform": "Console"}, "2140880155": {"name": "05: Sabatons (AR 58-66)", "category": "Boots", "platform": "Console"}, "2140880156": {"name": "06: Greaves (AR 67-82)", "category": "Boots", "platform": "Console"}, "2140881240": {"name": "07: Silk Shoes (AR 54-106)", "category": "Boots", "platform": "Console"}, "2140881241": {"name": "08: Brogans (AR 107-129)", "category": "Boots", "platform": "Console"}, "2140881242": {"name": "09: Treads (AR 130-152)", "category": "Boots", "platform": "Console"}, "2140881243": {"name": "10: Heavy Sabatons (AR 154-174)", "category": "Boots", "platform": "Console"}, "2140881244": {"name": "11: Battle Greaves (AR 175-192)", "category": "Boots", "platform": "Console"}, "2140882329": {"name": "12: Balor Treads (AR 192-209)", "category": "Boots", "platform": "Console"}, "2140882330": {"name": "13: Astral Greaves (AR 210-221)", "category": "Boots", "platform": "Console"}, "2140882331": {"name": "14: Warlord Boots (AR 221-249)", "category": "Boots", "platform": "Console"}, "2140882332": {"name": "15: Doom Treads (AR 250-278)", "category": "Boots", "platform": "Console"}, "2140882333": {"name": "16: Sovereign Greaves (AR 280-308)", "category": "Boots", "platform": "Console"}, "2140882334": {"name": "17: Archon Greaves (AR 309-366)", "category": "Boots", "platform": "Console"}, "2140882335": {"name": "18: Rakkisgard Greaves (AR 367-512)", "category": "Boots", "platform": "Console"}, "2140882336": {"name": "19: Ascended Greaves (AR 513-590)", "category": "Boots", "platform": "Console"}, "931997596": {"name": "Art Test Boots 1", "category": "Boots", "platform": "Console"}, "931997597": {"name": "Art Test Boots 2", "category": "Boots", "platform": "Console"}, "931997598": {"name": "Art Test Boots 3", "category": "Boots", "platform": "Console"}, "931997599": {"name": "Art Test Boots 4", "category": "Boots", "platform": "Console"}, "931997600": {"name": "Art Test Boots 5", "category": "Boots", "platform": "Console"}, "691149644": {"name": "Art_Test_Boots_10 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997601": {"name": "Art_Test_Boots_6 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997602": {"name": "Art_Test_Boots_7 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997603": {"name": "Art_Test_Boots_8 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "931997604": {"name": "Art_Test_Boots_9 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940245561": {"name": "Legendary: Board Walkers", "category": "Boots", "platform": "Console"}, "1940101813": {"name": "Legendary: Boj Anglers", "category": "Boots", "platform": "Console"}, "-401226911": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "-401224467": {"name": "Legendary: Boj Anglers (Legacy)", "category": "Boots", "platform": "Console"}, "261789197": {"name": "Legendary: Boj Anglers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979273143": {"name": "Legendary: Boots of Disregard", "category": "Boots", "platform": "Console"}, "1290781938": {"name": "Legendary: Conqueror's Sabatons (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1940317435": {"name": "Legendary: Fire Walkers", "category": "Boots", "platform": "Console"}, "-394111385": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "-394108941": {"name": "Legendary: Fire Walkers (Legacy)", "category": "Boots", "platform": "Console"}, "261789203": {"name": "Legendary: Fire Walkers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-639326280": {"name": "Legendary: Footfalls of the Forbidden Lands", "category": "Boots", "platform": "Console"}, "1940353372": {"name": "Legendary: Ice Climbers", "category": "Boots", "platform": "Console"}, "-392925464": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "-392923020": {"name": "Legendary: Ice Climbers (Legacy)", "category": "Boots", "platform": "Console"}, "261789204": {"name": "Legendary: Ice Climbers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1979309080": {"name": "Legendary: Illusory Boots", "category": "Boots", "platform": "Console"}, "1979345017": {"name": "Legendary: Irontoe Mudsputters", "category": "Boots", "platform": "Console"}, "-396483227": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "-396480783": {"name": "Legendary: Lost Boys (Legacy)", "category": "Boots", "platform": "Console"}, "261789201": {"name": "Legendary: Lost Boys (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1940389309": {"name": "Legendary: Lut Socks", "category": "Boots", "platform": "Console"}, "-391739543": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "-391737099": {"name": "Legendary: Lut Socks (Legacy)", "category": "Boots", "platform": "Console"}, "261789205": {"name": "Legendary: Lut Socks (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941251797": {"name": "Legendary: The Crudest Boots", "category": "Boots", "platform": "Console"}, "-363277439": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "-363274995": {"name": "Legendary: The Crudest Boots (Legacy)", "category": "Boots", "platform": "Console"}, "261789229": {"name": "Legendary: The Crudest Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-2143372979": {"name": "Legendary: The Crudest Boots (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "1941395545": {"name": "Set: Asheara's Finders", "category": "Boots", "platform": "Console"}, "261789233": {"name": "Set: Asheara's Lock (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-358533755": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "-358531311": {"name": "Set: Asheara's Tracks (Legacy)", "category": "Boots", "platform": "Console"}, "261789238": {"name": "Set: Blackthorne's Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941575230": {"name": "Set: Blackthorne's Spurs", "category": "Boots", "platform": "Console"}, "-352604150": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-352601706": {"name": "Set: Blackthorne's Spurs (Legacy)", "category": "Boots", "platform": "Console"}, "-357347834": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "-357345390": {"name": "Set: Cain's Sandals (Legacy)", "category": "Boots", "platform": "Console"}, "261789234": {"name": "Set: Cain's Slippers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941431482": {"name": "Set: Cain's Travelers", "category": "Boots", "platform": "Console"}, "261789236": {"name": "Set: Captain Crimson's Deck Boots (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941503356": {"name": "Set: Captain Crimson's Waders", "category": "Boots", "platform": "Console"}, "-354975992": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-354973548": {"name": "Set: Captain Crimson's Whalers (Legacy)", "category": "Boots", "platform": "Console"}, "-801833428": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801653481": {"name": "Set: Eight-Demon Boots", "category": "Boots", "platform": "Console"}, "-801725355": {"name": "Set: Firebird's Tarsi", "category": "Boots", "platform": "Console"}, "-801833429": {"name": "Set: Hell Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800539434": {"name": "Set: Helltooth Greaves", "category": "Boots", "platform": "Console"}, "261789231": {"name": "Set: Immortal King's Pillar (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941323671": {"name": "Set: Immortal King's Stride", "category": "Boots", "platform": "Console"}, "-360905597": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "-360903153": {"name": "Set: Immortal King's Stride (Legacy)", "category": "Boots", "platform": "Console"}, "1097296767": {"name": "Set: Inna's Sandals (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801617544": {"name": "Set: Jade Harvester's Swiftness", "category": "Boots", "platform": "Console"}, "-801689418": {"name": "Set: Marauder's Treads", "category": "Boots", "platform": "Console"}, "-801905302": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1941287734": {"name": "Set: Natalya's Bloody Footprints", "category": "Boots", "platform": "Console"}, "-362091518": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "-362089074": {"name": "Set: Natalya's Bloody Footprints (Legacy)", "category": "Boots", "platform": "Console"}, "261789230": {"name": "Set: Natalya's Soul (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1097296766": {"name": "Set: Nilfur's Boast (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-801761292": {"name": "Set: Raekor's Striders", "category": "Boots", "platform": "Console"}, "-801905304": {"name": "Set: Roland's Stride (Patch 2.1.0)", "category": "Boots", "platform": "Console"}, "-801905303": {"name": "Set: Sabaton of the Wastes (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800755056": {"name": "Set: Sabatons of Akkhan", "category": "Boots", "platform": "Console"}, "-353790071": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "-353787627": {"name": "Set: Sage's Journey (Legacy)", "category": "Boots", "platform": "Console"}, "1941539293": {"name": "Set: Sage's Passage", "category": "Boots", "platform": "Console"}, "261789237": {"name": "Set: Sage's Seekers (Old-Legacy)", "category": "Boots", "platform": "Console"}, "-1957807619": {"name": "Set: Striders of Destiny (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800611308": {"name": "Set: The Shadow's Heels", "category": "Boots", "platform": "Console"}, "-800647245": {"name": "Set: Vyr's Swaggering Stance", "category": "Boots", "platform": "Console"}, "-801869365": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "261789232": {"name": "Set: Zunimassa's Journey (Old-Legacy)", "category": "Boots", "platform": "Console"}, "1941359608": {"name": "Set: Zunimassa's Trail", "category": "Boots", "platform": "Console"}, "-359719676": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "-359717232": {"name": "Set: Zunimassa's Trail (Legacy)", "category": "Boots", "platform": "Console"}, "1979344754": {"name": "legendary: Boots_104_p2 (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "1940317172": {"name": "legendary: Fire Walkers (Patch 2.2.0)", "category": "Boots", "platform": "Console"}, "-800575371": {"name": "legendary: Seismic Treads", "category": "Boots", "platform": "Console"}, "-700134034": {"name": "legendary: Seismic Treads (Patch 2.2.0)", "category": "Boots", "platform": "Console"}}, "Bows": {"-2091504071": {"name": "02: Warden Bow (DPS 14.7-16.8)", "category": "Bows", "platform": "Console"}, "-2091504070": {"name": "03: Long Bow (DPS 20.3-22.4)", "category": "Bows", "platform": "Console"}, "-2091504069": {"name": "04: Recurve Bow (DPS 27.7-30.8)", "category": "Bows", "platform": "Console"}, "-2091504068": {"name": "05: Hunting Bow (DPS 34.3-36.4)", "category": "Bows", "platform": "Console"}, "-2091504067": {"name": "06: Battle Bow (DPS 41.3-43.4)", "category": "Bows", "platform": "Console"}, "-2091502983": {"name": "07: Siege Bow (DPS 44.1-46.2)", "category": "Bows", "platform": "Console"}, "-2091502982": {"name": "08: Maruki (DPS 55.3-57.4)", "category": "Bows", "platform": "Console"}, "-2091502981": {"name": "09: Yumi (DPS 64.4-66.5)", "category": "Bows", "platform": "Console"}, "-2091502980": {"name": "10: Composite Bow (DPS 749.9-77.0)", "category": "Bows", "platform": "Console"}, "-2091502979": {"name": "11: Daikyu (DPS 91.0-93.1)", "category": "Bows", "platform": "Console"}, "-2091502978": {"name": "12: Hankyu (DPS 107.1-109.2)", "category": "Bows", "platform": "Console"}, "-2091501894": {"name": "13: Higoyumi (DPS 140.7-142.8)", "category": "Bows", "platform": "Console"}, "-2091501893": {"name": "14: Ranger Bow (DPS 172.2-174.3)", "category": "Bows", "platform": "Console"}, "-2091501892": {"name": "15: Longshot Bow (DPS 207.2-211.4)", "category": "Bows", "platform": "Console"}, "-2091501891": {"name": "16: Sniper Bow (DPS 275.1-279.3)", "category": "Bows", "platform": "Console"}, "-2091501890": {"name": "17: Phantom Bow (DPS 322.0-326.2)", "category": "Bows", "platform": "Console"}, "-2091501889": {"name": "18: Revenant Bow (DPS 376.6-380.8)", "category": "Bows", "platform": "Console"}, "-2091500805": {"name": "19: Twinbow (DPS 513.1-517.3)", "category": "Bows", "platform": "Console"}, "-2091500804": {"name": "20: Doubleshot (DPS 670.6-674.8)", "category": "Bows", "platform": "Console"}, "687111997": {"name": "Art Test Bow 1", "category": "Bows", "platform": "Console"}, "687111998": {"name": "Art Test Bow 2", "category": "Bows", "platform": "Console"}, "687111999": {"name": "Art Test Bow 3", "category": "Bows", "platform": "Console"}, "687112000": {"name": "Art Test Bow 4", "category": "Bows", "platform": "Console"}, "687112001": {"name": "Art Test Bow 5", "category": "Bows", "platform": "Console"}, "1999703162": {"name": "Legendary: Amazonian Arch", "category": "Bows", "platform": "Console"}, "1142135055": {"name": "Legendary: Bow of the Lost Warlord (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1961789627": {"name": "Legendary: Cluckeye", "category": "Bows", "platform": "Console"}, "314470951": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "314473395": {"name": "Legendary: Cluckeye (Legacy)", "category": "Bows", "platform": "Console"}, "513724883": {"name": "Legendary: Cluckeye (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459958": {"name": "Legendary: Etrayu", "category": "Bows", "platform": "Console"}, "270591874": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "270594318": {"name": "Legendary: Etrayu (Legacy)", "category": "Bows", "platform": "Console"}, "513724846": {"name": "Legendary: Etrayu (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960459694": {"name": "Legendary: Etrayu (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "1999595351": {"name": "Legendary: Kridershot", "category": "Bows", "platform": "Console"}, "1999667225": {"name": "Legendary: Leonine Bow of Hashir", "category": "Bows", "platform": "Console"}, "277707400": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "277709844": {"name": "Legendary: Longshot (Legacy)", "category": "Bows", "platform": "Console"}, "513724852": {"name": "Legendary: Longshot (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1999631288": {"name": "Legendary: Odyssey's End", "category": "Bows", "platform": "Console"}, "1961609942": {"name": "Legendary: Sydyru Crust", "category": "Bows", "platform": "Console"}, "1960711517": {"name": "Legendary: The Raven's Wing", "category": "Bows", "platform": "Console"}, "278893321": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "278895765": {"name": "Legendary: The Raven's Wing (Legacy)", "category": "Bows", "platform": "Console"}, "513724853": {"name": "Legendary: The Raven's Wing (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960675580": {"name": "Legendary: Unbound Bolt", "category": "Bows", "platform": "Console"}, "1960603706": {"name": "Legendary: Uskang", "category": "Bows", "platform": "Console"}, "275335558": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "275338002": {"name": "Legendary: Uskang (Legacy)", "category": "Bows", "platform": "Console"}, "513724850": {"name": "Legendary: Uskang (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960603442": {"name": "Legendary: Uskang (Patch 2.1.0)", "category": "Bows", "platform": "Console"}, "308541346": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "308543790": {"name": "Legendary: Venomhusk (Legacy)", "category": "Bows", "platform": "Console"}, "513724878": {"name": "Legendary: Venomhusk (Old-Legacy)", "category": "Bows", "platform": "Console"}, "1960747454": {"name": "Legendary: Windforce", "category": "Bows", "platform": "Console"}, "280079242": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "280081686": {"name": "Legendary: Windforce (Legacy)", "category": "Bows", "platform": "Console"}, "513724854": {"name": "Legendary: Windforce (Old-Legacy)", "category": "Bows", "platform": "Console"}}, "Bracers": {"-875944877": {"name": "02: Leather Cuffs (AR 16-19)", "category": "Bracers", "platform": "Console"}, "-875944876": {"name": "03: Bindings (AR 25-32)", "category": "Bracers", "platform": "Console"}, "-875944875": {"name": "04: Vambraces (AR 33-40)", "category": "Bracers", "platform": "Console"}, "-875944874": {"name": "05: Bracelets (AR 41-48)", "category": "Bracers", "platform": "Console"}, "-875943789": {"name": "067: Wristwraps (AR 63-75)", "category": "Bracers", "platform": "Console"}, "-875944873": {"name": "06: Mail Bands (AR 50-62)", "category": "Bracers", "platform": "Console"}, "-875943788": {"name": "08: Wristbands (AR 76-88)", "category": "Bracers", "platform": "Console"}, "-875943787": {"name": "09: Stabilizers (AR 90-102)", "category": "Bracers", "platform": "Console"}, "-875943786": {"name": "10: Wristguards (AR 103-124)", "category": "Bracers", "platform": "Console"}, "-875943785": {"name": "11: Wristplates (AR 125-137)", "category": "Bracers", "platform": "Console"}, "-875942700": {"name": "12: Armwraps (AR 137-149)", "category": "Bracers", "platform": "Console"}, "-875942699": {"name": "13: Armbands (AR 150-157)", "category": "Bracers", "platform": "Console"}, "-875942698": {"name": "14: Warbands (AR 158-178)", "category": "Bracers", "platform": "Console"}, "-875942697": {"name": "15: Armguards (AR 179-199)", "category": "Bracers", "platform": "Console"}, "-875942696": {"name": "16: Armplates (AR 200-220)", "category": "Bracers", "platform": "Console"}, "-875942695": {"name": "17: Razorspikes (AR 220-261)", "category": "Bracers", "platform": "Console"}, "-875942694": {"name": "18: Rakkisgard Bracelets (AR 262-365)", "category": "Bracers", "platform": "Console"}, "-875942693": {"name": "19: Ascended Bracers (AR 366-421)", "category": "Bracers", "platform": "Console"}, "-297950812": {"name": "Art Test Bracer 1", "category": "Bracers", "platform": "Console"}, "-297950811": {"name": "Art Test Bracer 2", "category": "Bracers", "platform": "Console"}, "-297950810": {"name": "Art Test Bracer 3", "category": "Bracers", "platform": "Console"}, "-297950809": {"name": "Art Test Bracer 4", "category": "Bracers", "platform": "Console"}, "-297950808": {"name": "Art Test Bracer 5", "category": "Bracers", "platform": "Console"}, "1861699995": {"name": "Grundo Gear (Patch 2.1.2)", "category": "Bracers", "platform": "Console"}, "962282719": {"name": "Legendary: Ancient Parthan Defenders", "category": "Bracers", "platform": "Console"}, "962462404": {"name": "Legendary: Custerian Wristguards", "category": "Bracers", "platform": "Console"}, "923291074": {"name": "Legendary: Gungdo Gear", "category": "Bracers", "platform": "Console"}, "403757070": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "403759514": {"name": "Legendary: Gungdo Gear (Legacy)", "category": "Bracers", "platform": "Console"}, "955538490": {"name": "Legendary: Gungdo Gear (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923111389": {"name": "Legendary: Kethryes' Splint", "category": "Bracers", "platform": "Console"}, "923255137": {"name": "Legendary: Lacuni Prowlers", "category": "Bracers", "platform": "Console"}, "402571149": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "402573593": {"name": "Legendary: Lacuni Prowlers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538489": {"name": "Legendary: Lacuni Prowlers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962498341": {"name": "Legendary: Lucky Bowman's Armscales", "category": "Bracers", "platform": "Console"}, "962426467": {"name": "Legendary: Nemesis Bracers", "category": "Bracers", "platform": "Console"}, "923147326": {"name": "Legendary: Promise of Glory", "category": "Bracers", "platform": "Console"}, "399013386": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "399015830": {"name": "Legendary: Promise of Glory (Legacy)", "category": "Bracers", "platform": "Console"}, "955538486": {"name": "Legendary: Promise of Glory (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962318656": {"name": "Legendary: Reaper's Wraps", "category": "Bracers", "platform": "Console"}, "962390530": {"name": "Legendary: Sanguinary Vambraces", "category": "Bracers", "platform": "Console"}, "923183263": {"name": "Legendary: Slave Bonds", "category": "Bracers", "platform": "Console"}, "400199307": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "400201751": {"name": "Legendary: Slave Bonds (Legacy)", "category": "Bracers", "platform": "Console"}, "955538487": {"name": "Legendary: Slave Bonds (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923219200": {"name": "Legendary: Steady Strikers", "category": "Bracers", "platform": "Console"}, "401385228": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "401387672": {"name": "Legendary: Steady Strikers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538488": {"name": "Legendary: Steady Strikers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923327011": {"name": "Legendary: Strongarm Bracers", "category": "Bracers", "platform": "Console"}, "404942991": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "404945435": {"name": "Legendary: Strongarm Bracers (Legacy)", "category": "Bracers", "platform": "Console"}, "955538491": {"name": "Legendary: Strongarm Bracers (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "962354593": {"name": "Legendary: Trag'Oul Coils", "category": "Bracers", "platform": "Console"}, "962246782": {"name": "Legendary: Warzechian Armguards", "category": "Bracers", "platform": "Console"}, "397827465": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "397829909": {"name": "Legendary: Wondrous Deflectors (Legacy)", "category": "Bracers", "platform": "Console"}, "955538485": {"name": "Legendary: Wondrous Deflectors (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "955538493": {"name": "Set: Aughild's Demands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "923398885": {"name": "Set: Aughild's Search", "category": "Bracers", "platform": "Console"}, "407314833": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "407317277": {"name": "Set: Aughild's Ultimatum (Legacy)", "category": "Bracers", "platform": "Console"}, "924297310": {"name": "Set: Demon's Animus", "category": "Bracers", "platform": "Console"}, "955538518": {"name": "Set: Demon's Manacles (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "436962858": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "436965302": {"name": "Set: Demon's Revenge (Legacy)", "category": "Bracers", "platform": "Console"}, "924261373": {"name": "Set: Guardian's Aversion", "category": "Bracers", "platform": "Console"}, "955538517": {"name": "Set: Guardian's Bands (Old-Legacy)", "category": "Bracers", "platform": "Console"}, "435776937": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "435779381": {"name": "Set: Guardian's Deflector (Legacy)", "category": "Bracers", "platform": "Console"}, "1784952569": {"name": "Set: Krelm's Buff Bracers", "category": "Bracers", "platform": "Console"}, "1786138490": {"name": "Set: Shackles of the Invoker", "category": "Bracers", "platform": "Console"}, "1861701111": {"name": "legendary: Drakon's Lesson (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861699992": {"name": "legendary: Mortick's Brace (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}, "1861701087": {"name": "legendary: Spirit Guards (Patch 2.2.0)", "category": "Bracers", "platform": "Console"}}, "Ceremonial Knives": {"-635269583": {"name": "01: Stone Knife (DPS 11.2-12.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269582": {"name": "02: Kris Blade (DPS 14.7-16.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269581": {"name": "03: Jagged Edge (DPS 21.0-23.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635269580": {"name": "04: Flint Knife (DPS 30.8-32.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268494": {"name": "05: Sacrifice Blade (DPS 39.2-41.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268493": {"name": "06: Flayer (DPS 48.3-50.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268492": {"name": "07: Bone Saw (DPS 62.3-64.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635268491": {"name": "08: Beast Tusk (DPS 84.0-86.1)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267405": {"name": "09: Scalping Razor (DPS 112.7-114.8)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267404": {"name": "10: Obsidian Edge (DPS 137.2-139.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267403": {"name": "11: Skin Cutter (DPS 165.2-169.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267402": {"name": "12: Exquisite Knife (DPS 190.4-194.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267401": {"name": "13: Flesh Ripper (DPS 219.1-223.3)", "category": "Ceremonial Knives", "platform": "Console"}, "-635267400": {"name": "14: Veil Piercer (DPS 251.3-257.6)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266316": {"name": "15: Odsidian Skiver (DPS 336.7-340.9)", "category": "Ceremonial Knives", "platform": "Console"}, "-635266315": {"name": "16: Tecpat1 (DPS 410.2-414.4)", "category": "Ceremonial Knives", "platform": "Console"}, "-97045282": {"name": "Art Test CeremonialDagger 1", "category": "Ceremonial Knives", "platform": "Console"}, "-97045281": {"name": "Art Test CeremonialDagger 2", "category": "Ceremonial Knives", "platform": "Console"}, "-97045280": {"name": "Art Test CeremonialDagger 3", "category": "Ceremonial Knives", "platform": "Console"}, "-97045279": {"name": "Art Test CeremonialDagger 4", "category": "Ceremonial Knives", "platform": "Console"}, "-97045278": {"name": "Art Test CeremonialDagger 5", "category": "Ceremonial Knives", "platform": "Console"}, "1784443031": {"name": "Legendary: Anessazi Edge", "category": "Ceremonial Knives", "platform": "Console"}, "-1242999421": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1242996977": {"name": "Legendary: Anessazi Edge (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684207": {"name": "Legendary: Anessazi Edge (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784514905": {"name": "Legendary: Deadly Rebirth", "category": "Ceremonial Knives", "platform": "Console"}, "1784694590": {"name": "Legendary: Last Breath", "category": "Ceremonial Knives", "platform": "Console"}, "-1234697974": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1234695530": {"name": "Legendary: Last Breath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684214": {"name": "Legendary: Last Breath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784622716": {"name": "Legendary: Living Umbral Oath", "category": "Ceremonial Knives", "platform": "Console"}, "-1240627579": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1240625135": {"name": "Legendary: Moon Slayer (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684209": {"name": "Legendary: Moon Slayer (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1823614361": {"name": "Legendary: Rhen'ho Flayer", "category": "Ceremonial Knives", "platform": "Console"}, "916911834": {"name": "Legendary: Sacred Harvester (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "595814643": {"name": "Legendary: Sacrificer", "category": "Ceremonial Knives", "platform": "Console"}, "1823578424": {"name": "Legendary: Starmetal Kukri", "category": "Ceremonial Knives", "platform": "Console"}, "916911835": {"name": "Legendary: The Dagger of Darts (Patch 2.1.0)", "category": "Ceremonial Knives", "platform": "Console"}, "1784478968": {"name": "Legendary: The Gidbinn", "category": "Ceremonial Knives", "platform": "Console"}, "-1241813500": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1241811056": {"name": "Legendary: The Gidbinn (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684208": {"name": "Legendary: The Gidbinn (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1784550842": {"name": "Legendary: The Spider Queen's Grasp", "category": "Ceremonial Knives", "platform": "Console"}, "-1237069816": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1237067372": {"name": "Legendary: Umbral Oath (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684212": {"name": "Legendary: Umbral Oath (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239441658": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1239439214": {"name": "Legendary: Ziggurat Tooth (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684210": {"name": "Legendary: Ziggurat Tooth (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684240": {"name": "Set: Hallowed Sacrifice (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203864028": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1203861584": {"name": "Set: Hallowed Salvation (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "1785628952": {"name": "Set: Hallowed Sufferance", "category": "Ceremonial Knives", "platform": "Console"}, "1784730527": {"name": "Set: Manajuma's Carving Knife", "category": "Ceremonial Knives", "platform": "Console"}, "-1233512053": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "-1233509609": {"name": "Set: Manajuma's Carving Knife (Legacy)", "category": "Ceremonial Knives", "platform": "Console"}, "394684215": {"name": "Set: Manajuma's Ritual Cutter (Old-Legacy)", "category": "Ceremonial Knives", "platform": "Console"}}, "Chest": {"258855260": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783385": {"name": "Set: Cuirass of the Wastes (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819322": {"name": "Set: Harness of Truth (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258783386": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "259969569": {"name": "Set: Sunwuko's Soul (Patch 2.2.0)", "category": "Chest", "platform": "Console"}, "258819323": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Chest", "platform": "Console"}}, "Chest Armor": {"1612257705": {"name": "02: Leather Doublet (AR 18-21)", "category": "Chest Armor", "platform": "Console"}, "1612257706": {"name": "03: Brigandine Coat (AR 33-38)", "category": "Chest Armor", "platform": "Console"}, "1612257707": {"name": "04: Chain Mail (AR 51-68)", "category": "Chest Armor", "platform": "Console"}, "1612257708": {"name": "05: Splint Cuirass (AR 69-86)", "category": "Chest Armor", "platform": "Console"}, "1612257709": {"name": "06: Plate Mail (AR 87-107)", "category": "Chest Armor", "platform": "Console"}, "1612258793": {"name": "07: Stygian Harness (AR 108-137)", "category": "Chest Armor", "platform": "Console"}, "1612258794": {"name": "08: Etched Jacket (AR 138-167)", "category": "Chest Armor", "platform": "Console"}, "1612258795": {"name": "09: Jazeraint Mail (AR 168-197)", "category": "Chest Armor", "platform": "Console"}, "1612258796": {"name": "10: Battle Armor (AR 198-224)", "category": "Chest Armor", "platform": "Console"}, "1612258797": {"name": "11: Boneweave Hauberk (AR 225-247)", "category": "Chest Armor", "platform": "Console"}, "1612259882": {"name": "12: Balor Armor (AR 247-269)", "category": "Chest Armor", "platform": "Console"}, "1612259883": {"name": "13: Astral Mail (AR 270-284)", "category": "Chest Armor", "platform": "Console"}, "1612259884": {"name": "14: Warlord Plate (AR 285-322)", "category": "Chest Armor", "platform": "Console"}, "1612259885": {"name": "15: Doom Armor (AR 322-359)", "category": "Chest Armor", "platform": "Console"}, "1612259886": {"name": "16: Sovereign Mail (AR 360-397)", "category": "Chest Armor", "platform": "Console"}, "1612259887": {"name": "17: Archon Armor (AR 397-471)", "category": "Chest Armor", "platform": "Console"}, "1612259888": {"name": "18: Rakkisgard Armor (AR 472-659)", "category": "Chest Armor", "platform": "Console"}, "1612259889": {"name": "19: Ascended Armor (AR 660-759)", "category": "Chest Armor", "platform": "Console"}, "1937623756": {"name": "Art Test Chest 1", "category": "Chest Armor", "platform": "Console"}, "1937623757": {"name": "Art Test Chest 2", "category": "Chest Armor", "platform": "Console"}, "1937623758": {"name": "Art Test Chest 3", "category": "Chest Armor", "platform": "Console"}, "1937623759": {"name": "Art Test Chest 4", "category": "Chest Armor", "platform": "Console"}, "1937623760": {"name": "Art Test Chest 5", "category": "Chest Armor", "platform": "Console"}, "1316774087": {"name": "Legendary: Aquila Cuirass", "category": "Chest Armor", "platform": "Console"}, "503794611": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "503797055": {"name": "Legendary: Aquila Cuirass (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016991": {"name": "Legendary: Aquila Cuirass (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354723559": {"name": "Legendary: Armor of the Kind Regent", "category": "Chest Armor", "platform": "Console"}, "1316702213": {"name": "Legendary: Chaingmail", "category": "Chest Armor", "platform": "Console"}, "501422769": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "501425213": {"name": "Legendary: Chaingmail (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016989": {"name": "Legendary: Chaingmail (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1315731914": {"name": "Legendary: Cindercoat", "category": "Chest Armor", "platform": "Console"}, "469402902": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "469405346": {"name": "Legendary: Cindercoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016962": {"name": "Legendary: Cindercoat (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "883162595": {"name": "Legendary: Conqueror's Cuirass (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "1315552229": {"name": "Legendary: Goldskin", "category": "Chest Armor", "platform": "Console"}, "463473297": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "463475741": {"name": "Legendary: Goldskin (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016957": {"name": "Legendary: Goldskin (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316989709": {"name": "Legendary: Heart of Iron", "category": "Chest Armor", "platform": "Console"}, "510910137": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "510912581": {"name": "Legendary: Heart of Iron (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016997": {"name": "Legendary: Heart of Iron (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1821181577": {"name": "Legendary: Heart of the Titans", "category": "Chest Armor", "platform": "Console"}, "1317025646": {"name": "Legendary: Mantle of the Rydraelm", "category": "Chest Armor", "platform": "Console"}, "512096058": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "512098502": {"name": "Legendary: Robes of the Rydraelm (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016998": {"name": "Legendary: Robes of the Rydraelm (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1354687622": {"name": "Legendary: Shi Mizu's Haori", "category": "Chest Armor", "platform": "Console"}, "1315588166": {"name": "Legendary: Tyrael's Might", "category": "Chest Armor", "platform": "Console"}, "464659218": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "464661662": {"name": "Legendary: Tyrael's Might (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016958": {"name": "Legendary: Tyrael's Might (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "547673688": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "547676132": {"name": "Set: Aughild's Dominion (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318103756": {"name": "Set: Aughild's Rule", "category": "Chest Armor", "platform": "Console"}, "172017028": {"name": "Set: Aughild's Vestments (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1262779559": {"name": "Set: Blackthorne's Jacket (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "-115330289": {"name": "Set: Blackthorne's Surcoat", "category": "Chest Armor", "platform": "Console"}, "488990459": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "488992903": {"name": "Set: Blackthorne's Surcoat (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172017027": {"name": "Set: Born's Carapace (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318067819": {"name": "Set: Born's Frozen Soul", "category": "Chest Armor", "platform": "Console"}, "546487767": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "546490211": {"name": "Set: Born's Heart of Steel (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259933632": {"name": "Set: Breastplate of Akkhan", "category": "Chest Armor", "platform": "Console"}, "172017029": {"name": "Set: Demon's Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "548859609": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "548862053": {"name": "Set: Demon's Heart (Legacy)", "category": "Chest Armor", "platform": "Console"}, "1318139693": {"name": "Set: Demon's Marrow", "category": "Chest Armor", "platform": "Console"}, "258963333": {"name": "Set: Firebird's Breast", "category": "Chest Armor", "platform": "Console"}, "259035207": {"name": "Set: Heart of the Crashing Wave", "category": "Chest Armor", "platform": "Console"}, "260149254": {"name": "Set: Helltooth Tunic", "category": "Chest Armor", "platform": "Console"}, "1316810024": {"name": "Set: Immortal King's Eternal Reign", "category": "Chest Armor", "platform": "Console"}, "504980532": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "504982976": {"name": "Set: Immortal King's Eternal Reign (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016992": {"name": "Set: Immortal King's Soul Cage (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016994": {"name": "Set: Inna's Refuge (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316881898": {"name": "Set: Inna's Vast Expanse", "category": "Chest Armor", "platform": "Console"}, "507352374": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "507354818": {"name": "Set: Inna's Vast Expanse (Legacy)", "category": "Chest Armor", "platform": "Console"}, "259071144": {"name": "Set: Jade Harvester's Peace", "category": "Chest Armor", "platform": "Console"}, "258999270": {"name": "Set: Marauder's Carapace", "category": "Chest Armor", "platform": "Console"}, "258927396": {"name": "Set: Raekor's Heart", "category": "Chest Armor", "platform": "Console"}, "258783384": {"name": "Set: Roland's Bearing (Patch 2.1.0)", "category": "Chest Armor", "platform": "Console"}, "172016993": {"name": "Set: Tal Rasha's Guardianship (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}, "1316845961": {"name": "Set: Tal Rasha's Relentless Pursuit", "category": "Chest Armor", "platform": "Console"}, "506166453": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "506168897": {"name": "Set: Tal Rasha's Relentless Pursuit (Legacy)", "category": "Chest Armor", "platform": "Console"}, "260077380": {"name": "Set: The Shadow's Bane", "category": "Chest Armor", "platform": "Console"}, "260041443": {"name": "Set: Vyr's Astonishing Aura", "category": "Chest Armor", "platform": "Console"}, "1316917835": {"name": "Set: Zunimassa's Marrow", "category": "Chest Armor", "platform": "Console"}, "508538295": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "508540739": {"name": "Set: Zunimassa's Marrow (Legacy)", "category": "Chest Armor", "platform": "Console"}, "172016995": {"name": "Set: Zunimassa's Vessel (Old-Legacy)", "category": "Chest Armor", "platform": "Console"}}, "Chests": {"1937623762": {"name": "Art_Test_Chest_7 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623763": {"name": "Art_Test_Chest_8 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}, "1937623764": {"name": "Art_Test_Chest_9 (Patch 2.2.0)", "category": "Chests", "platform": "Console"}}, "Cloaks": {"40855419": {"name": "02: Shroud (AR 36-41)", "category": "Cloaks", "platform": "Console"}, "40855420": {"name": "03: Cape (AR 60-69)", "category": "Cloaks", "platform": "Console"}, "40855421": {"name": "04: Tabard (AR 84-113)", "category": "Cloaks", "platform": "Console"}, "40856507": {"name": "05: Wrap (AR 114-149)", "category": "Cloaks", "platform": "Console"}, "40856508": {"name": "06: Lurker Shroud (AR 150-185)", "category": "Cloaks", "platform": "Console"}, "40856509": {"name": "07: Talma (AR 186-232)", "category": "Cloaks", "platform": "Console"}, "40856510": {"name": "08: Cardinal (AR 232-254)", "category": "Cloaks", "platform": "Console"}, "40857596": {"name": "09: Veteran Cloak (AR 255-284)", "category": "Cloaks", "platform": "Console"}, "40857597": {"name": "10: Death Shroud (AR 385-322)", "category": "Cloaks", "platform": "Console"}, "40857598": {"name": "11: Stalker Cape (AR 322-359)", "category": "Cloaks", "platform": "Console"}, "40857599": {"name": "12: Dread Cloak (AR 360-472)", "category": "Cloaks", "platform": "Console"}, "40857600": {"name": "13: Rakkisgard Cloak (AR 472-659)", "category": "Cloaks", "platform": "Console"}, "40857601": {"name": "14: Ascended Cloak (AR 660-759)", "category": "Cloaks", "platform": "Console"}, "2105367871": {"name": "Art Test Cloak 1", "category": "Cloaks", "platform": "Console"}, "2105367872": {"name": "Art Test Cloak 2", "category": "Cloaks", "platform": "Console"}, "2105367873": {"name": "Art Test Cloak 3", "category": "Cloaks", "platform": "Console"}, "2105367874": {"name": "Art Test Cloak 4", "category": "Cloaks", "platform": "Console"}, "2105367875": {"name": "Art Test Cloak 5", "category": "Cloaks", "platform": "Console"}, "221665681": {"name": "Legendary Cloak 002 p1", "category": "Cloaks", "platform": "Console"}, "221773756": {"name": "Legendary: Beckon Sail", "category": "Cloaks", "platform": "Console"}, "-1271477944": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1271475500": {"name": "Legendary: Beckon Sail (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235532": {"name": "Legendary: Beckon Sail (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260765401": {"name": "Legendary: Blackfeather", "category": "Cloaks", "platform": "Console"}, "221630008": {"name": "Legendary: Cape of the Dark Night", "category": "Cloaks", "platform": "Console"}, "-1276221628": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1276219184": {"name": "Legendary: Cape of the Dark Night (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235536": {"name": "Legendary: Cape of the Dark Night (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "260801338": {"name": "Legendary: Cloak of Deception", "category": "Cloaks", "platform": "Console"}, "221665945": {"name": "Legendary: The Cloak of the Garwulf", "category": "Cloaks", "platform": "Console"}, "-1275035707": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1275033263": {"name": "Legendary: The Inquisitor (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235535": {"name": "Legendary: The Inquisitor (Old-Legacy)", "category": "Cloaks", "platform": "Console"}, "221809693": {"name": "Set: Natalya's Embrace", "category": "Cloaks", "platform": "Console"}, "-1270292023": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1270289579": {"name": "Set: Natalya's Embrace (Legacy)", "category": "Cloaks", "platform": "Console"}, "-1838235531": {"name": "Set: Natalya's Shadow (Old-Legacy)", "category": "Cloaks", "platform": "Console"}}, "Consumables": {"-1459729466": {"name": "Greater Rift Keystone", "category": "Comsumables", "platform": "Console"}, "-1691237125": {"name": "Blood Shard", "category": "Consumables", "platform": "Console"}, "-2018707791": {"name": "Bottomless Potion Of Fear (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-2018707790": {"name": "Bottomless Potion of Amplification (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707793": {"name": "Bottomless Potion of Kulle Aid", "category": "Consumables", "platform": "Console"}, "-2018707794": {"name": "Bottomless Potion of Mutilation", "category": "Consumables", "platform": "Console"}, "-2018707796": {"name": "Bottomless Potion of Regeneration", "category": "Consumables", "platform": "Console"}, "-2018707792": {"name": "Bottomless Potion of Rejuvenation", "category": "Consumables", "platform": "Console"}, "510979313": {"name": "Bottomless Potion of Rejuvenation (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2018707797": {"name": "Bottomless Potion of the Diamond", "category": "Consumables", "platform": "Console"}, "-2018707795": {"name": "Bottomless Potion of the Leech", "category": "Consumables", "platform": "Console"}, "-2018707798": {"name": "Bottomless Potion of the Tower", "category": "Consumables", "platform": "Console"}, "727989467": {"name": "Bottomless Regular Health Potion (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618072": {"name": "Consumable_Potion_Bloodshard_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "736462346": {"name": "Consumable_Potion_Bloodshard_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618138": {"name": "Consumable_Potion_Bloodshard_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "282618270": {"name": "Consumable_Potion_Bloodshard_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764252": {"name": "Consumable_Potion_Gold_Find_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-418681010": {"name": "Consumable_Potion_Gold_Find_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764318": {"name": "Consumable_Potion_Gold_Find_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "377764450": {"name": "Consumable_Potion_Gold_Find_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167362": {"name": "Consumable_Potion_XP_Buff_1D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1032379504": {"name": "Consumable_Potion_XP_Buff_30D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167296": {"name": "Consumable_Potion_XP_Buff_3D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-359167164": {"name": "Consumable_Potion_XP_Buff_7D (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-2142362846": {"name": "Health Potion", "category": "Consumables", "platform": "Console"}, "-650776931": {"name": "Infernal Machine", "category": "Consumables", "platform": "Console"}, "1054965529": {"name": "Infernal Machine of Bones", "category": "Consumables", "platform": "Console"}, "1458185494": {"name": "Infernal Machine of Evil", "category": "Consumables", "platform": "Console"}, "-1506243402": {"name": "Infernal Machine of Gluttony", "category": "Consumables", "platform": "Console"}, "-1672611564": {"name": "Infernal Machine of War", "category": "Consumables", "platform": "Console"}, "-1055802742": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "1927699898": {"name": "Platinum (Patch 2.2.0)", "category": "Consumables", "platform": "Console"}, "-1990624170": {"name": "PowerGlobe", "category": "Consumables", "platform": "Console"}, "-1407876474": {"name": "PowerGlobe NoFlippy", "category": "Consumables", "platform": "Console"}, "1604670149": {"name": "PowerGlobe v2 x1", "category": "Consumables", "platform": "Console"}, "1554449877": {"name": "PowerGlobe v2 x1 NoFlippy", "category": "Consumables", "platform": "Console"}, "-767886865": {"name": "PvP_HealingDude", "category": "Consumables", "platform": "Console"}, "1844495708": {"name": "Ramaladni's Gift", "category": "Consumables", "platform": "Console"}, "-2108322324": {"name": "Ramaladni's Gift (Patch 2.1.0)", "category": "Consumables", "platform": "Console"}, "-1629755675": {"name": "Rare Gift (RoS)", "category": "Consumables", "platform": "Console"}, "750709043": {"name": "ShrineGlobe Blessed", "category": "Consumables", "platform": "Console"}, "-783958152": {"name": "ShrineGlobe Enlightened", "category": "Consumables", "platform": "Console"}, "1754475188": {"name": "ShrineGlobe Fortune", "category": "Consumables", "platform": "Console"}, "1126841672": {"name": "ShrineGlobe Frenzied", "category": "Consumables", "platform": "Console"}, "-1436918535": {"name": "Steak10", "category": "Consumables", "platform": "Console"}, "-1436918530": {"name": "Steak15", "category": "Consumables", "platform": "Console"}, "-1436918502": {"name": "Steak20", "category": "Consumables", "platform": "Console"}, "-1436918497": {"name": "Steak25", "category": "Consumables", "platform": "Console"}, "-1436918469": {"name": "Steak30", "category": "Consumables", "platform": "Console"}, "-1436918464": {"name": "Steak35", "category": "Consumables", "platform": "Console"}, "-1436918436": {"name": "Steak40", "category": "Consumables", "platform": "Console"}, "346908589": {"name": "Steak5", "category": "Consumables", "platform": "Console"}, "450956006": {"name": "p1 tiered rifts Orb", "category": "Consumables", "platform": "Console"}}, "Cosmetics": {"703352254": {"name": "Art_Test_Pet_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352255": {"name": "Art_Test_Pet_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352256": {"name": "Art_Test_Pet_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352257": {"name": "Art_Test_Pet_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352258": {"name": "Art_Test_Pet_5 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "703352259": {"name": "Art_Test_Pet_6 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555709": {"name": "Art_Test_Wings_1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555710": {"name": "Art_Test_Wings_2 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555711": {"name": "Art_Test_Wings_3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "2046555712": {"name": "Art_Test_Wings_4 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1736870778": {"name": "Blade Wings", "category": "Cosmetics", "platform": "Console"}, "2015178386": {"name": "Blade Wings (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508877": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508876": {"name": "Blank Consumable (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "988742338": {"name": "Cosmetic_Pet_FallenHound_Skeletal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1527508875": {"name": "Cosmetic_Pet_teddyBear_04 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1464439640": {"name": "Cosmetic_Wings_Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834901": {"name": "Cosmetic_Wings_bat_02 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "702834902": {"name": "Cosmetic_Wings_bat_03 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1424453175": {"name": "Crimson Angelic Wings", "category": "Cosmetics", "platform": "Console"}, "1464422100": {"name": "Demon Soaring (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208405024": {"name": "Eldritch Embrace (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1081301157": {"name": "Eternal Flame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "1030142027": {"name": "Eternal Light (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1815774861": {"name": "Fingers of Terror (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380235": {"name": "Frame: Angelic (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264991": {"name": "Frame: Base Frame (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380233": {"name": "Frame: Bone (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380234": {"name": "Frame: Deathshead (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380230": {"name": "Frame: Molton (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1944264990": {"name": "Frame: Paragon 1 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764818": {"name": "Frame: Paragon 10 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114304450": {"name": "Frame: Paragon 100 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764851": {"name": "Frame: Paragon 20 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114305539": {"name": "Frame: Paragon 200 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764884": {"name": "Frame: Paragon 30 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764917": {"name": "Frame: Paragon 40 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114307717": {"name": "Frame: Paragon 400 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764950": {"name": "Frame: Paragon 50 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114308806": {"name": "Frame: Paragon 500 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263764983": {"name": "Frame: Paragon 60 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114309895": {"name": "Frame: Paragon 600 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765016": {"name": "Frame: Paragon 70 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114310984": {"name": "Frame: Paragon 700 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765049": {"name": "Frame: Paragon 80 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114312073": {"name": "Frame: Paragon 800 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "263765082": {"name": "Frame: Paragon 90 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "114306628": {"name": "Frame: Paraogn 300 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380199": {"name": "Frame: Season 3 (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380228": {"name": "Frame: Staind Glass Azure (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380202": {"name": "Frame: Staind Glass Orange (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380201": {"name": "Frame: Staind Glass Purple (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380227": {"name": "Frame: Staind Glass Red (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380229": {"name": "Frame: Staind Glass Teal (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380203": {"name": "Frame: Staind Glass Yellow (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380231": {"name": "Frame: Steadfast (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380198": {"name": "Frame: Storm (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380232": {"name": "Frame: Thorns (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1863380200": {"name": "Frame: Whimseyshire (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "211305012": {"name": "Harbringer of Destruction (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "262300867": {"name": "Heaven't Might (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-922089455": {"name": "Knights of Westmarch (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1412314502": {"name": "Liber Canis Mortui", "category": "Cosmetics", "platform": "Console"}, "-1527508878": {"name": "Mr Bear (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "208454467": {"name": "Pieces of Hatred (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "517654224": {"name": "Probe (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "291388174": {"name": "Spike (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1647814559": {"name": "Ten Pounder (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-1454306710": {"name": "The Light of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-2072242152": {"name": "The Pillars of Heaven (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-937743655": {"name": "Warlords Of Draenor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}, "-762694428": {"name": "Warsong Pennant", "category": "Cosmetics", "platform": "Console"}, "-1364948604": {"name": "Wings of Valor", "category": "Cosmetics", "platform": "Console"}, "1464422747": {"name": "Wings of Valor (Patch 2.2.0)", "category": "Cosmetics", "platform": "Console"}}, "Crafting Components": {"-784029520": {"name": "Angelic Shard", "category": "Crafting Components", "platform": "Console"}, "-1585802162": {"name": "Arcane Dust", "category": "Crafting Components", "platform": "Console"}, "2048505008": {"name": "Behistun Rune", "category": "Crafting Components", "platform": "Console"}, "-1993550104": {"name": "Black Mushroom", "category": "Crafting Components", "platform": "Console"}, "1864276820": {"name": "Bloody Pincer", "category": "Crafting Components", "platform": "Console"}, "-875022940": {"name": "Born's Key", "category": "Crafting Components", "platform": "Console"}, "-229384987": {"name": "Captured Nightmare", "category": "Crafting Components", "platform": "Console"}, "1016443205": {"name": "Captured Soul", "category": "Crafting Components", "platform": "Console"}, "903645542": {"name": "Cartographer's Toolkit", "category": "Crafting Components", "platform": "Console"}, "2064572165": {"name": "Common Debris", "category": "Crafting Components", "platform": "Console"}, "-821947350": {"name": "Cultist Blood", "category": "Crafting Components", "platform": "Console"}, "2087837753": {"name": "Death's Breath", "category": "Crafting Components", "platform": "Console"}, "2000469169": {"name": "Defiled Doll", "category": "Crafting Components", "platform": "Console"}, "-1761931437": {"name": "Demon Skin", "category": "Crafting Components", "platform": "Console"}, "-152489231": {"name": "Demonic Essence", "category": "Crafting Components", "platform": "Console"}, "-645052297": {"name": "Devil's Fang", "category": "Crafting Components", "platform": "Console"}, "437938885": {"name": "Element of Celerity", "category": "Crafting Components", "platform": "Console"}, "2064572134": {"name": "Encrusted Hoof (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-1725926578": {"name": "Essence of the Twin Seas", "category": "Crafting Components", "platform": "Console"}, "-1506992994": {"name": "Eternal Power Capsule", "category": "Crafting Components", "platform": "Console"}, "2064572166": {"name": "Exquisite Essence", "category": "Crafting Components", "platform": "Console"}, "1726149320": {"name": "Eyes of the Dead", "category": "Crafting Components", "platform": "Console"}, "2064572068": {"name": "Fallen Tooth (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "2064572168": {"name": "Fiery Brimstone", "category": "Crafting Components", "platform": "Console"}, "2073430088": {"name": "Forgotten Soul", "category": "Crafting Components", "platform": "Console"}, "937036308": {"name": "Frozen Blood", "category": "Crafting Components", "platform": "Console"}, "-799974399": {"name": "Gibbering Gemstone", "category": "Crafting Components", "platform": "Console"}, "-1299206911": {"name": "Glowing Ore", "category": "Crafting Components", "platform": "Console"}, "-730966965": {"name": "Griswold's Scribblings", "category": "Crafting Components", "platform": "Console"}, "-958180196": {"name": "Heart of Evil", "category": "Crafting Components", "platform": "Console"}, "460247356": {"name": "Hilt of the Silver Wolf", "category": "Crafting Components", "platform": "Console"}, "314328565": {"name": "Human Cartilage", "category": "Crafting Components", "platform": "Console"}, "-1624623846": {"name": "Idol of Terror", "category": "Crafting Components", "platform": "Console"}, "2064572167": {"name": "Iridescent Tear", "category": "Crafting Components", "platform": "Console"}, "-661382443": {"name": "Iron Wolves Doctrine", "category": "Crafting Components", "platform": "Console"}, "1102953247": {"name": "Leoric's Regret", "category": "Crafting Components", "platform": "Console"}, "-629520052": {"name": "Leoric's Shinbone", "category": "Crafting Components", "platform": "Console"}, "725082635": {"name": "Liquid Rainbow", "category": "Crafting Components", "platform": "Console"}, "-1402576366": {"name": "Living Flame", "category": "Crafting Components", "platform": "Console"}, "2064572101": {"name": "Lizard Eye (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "291872615": {"name": "Lyekurn's Diary", "category": "Crafting Components", "platform": "Console"}, "1835813454": {"name": "Maghda's Tormented Soul", "category": "Crafting Components", "platform": "Console"}, "-1018735616": {"name": "Mystical Source", "category": "Crafting Components", "platform": "Console"}, "-1020906970": {"name": "Page of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-667291726": {"name": "Page of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "526997101": {"name": "Phial of Weakness", "category": "Crafting Components", "platform": "Console"}, "778194127": {"name": "Quaking Vial", "category": "Crafting Components", "platform": "Console"}, "1114256397": {"name": "Reaper's Fear", "category": "Crafting Components", "platform": "Console"}, "-363607620": {"name": "Reusable Parts", "category": "Crafting Components", "platform": "Console"}, "280425627": {"name": "Rydraelm Tome", "category": "Crafting Components", "platform": "Console"}, "-830982818": {"name": "Shard of Entsteig Plate", "category": "Crafting Components", "platform": "Console"}, "-1176010511": {"name": "Shattered Core", "category": "Crafting Components", "platform": "Console"}, "2064572100": {"name": "Shimmering Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2114382103": {"name": "Shimmering Quill", "category": "Crafting Components", "platform": "Console"}, "-248569447": {"name": "Shuddering Demon Bone", "category": "Crafting Components", "platform": "Console"}, "-1810945531": {"name": "Skelon's Dice", "category": "Crafting Components", "platform": "Console"}, "-997569662": {"name": "Skull of Raylend", "category": "Crafting Components", "platform": "Console"}, "2064572067": {"name": "Subtle Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-2113447741": {"name": "Sydyru Bone", "category": "Crafting Components", "platform": "Console"}, "-1253986069": {"name": "Symbol of the Guardian Brotherhood", "category": "Crafting Components", "platform": "Console"}, "494826242": {"name": "Tome of Blacksmithing (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-722757874": {"name": "Tome of Jewelcrafting (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-970366835": {"name": "Tome of Secrets (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "-443730551": {"name": "Torn Soul", "category": "Crafting Components", "platform": "Console"}, "1075049130": {"name": "Urn of Quickening", "category": "Crafting Components", "platform": "Console"}, "-605947593": {"name": "Veiled Crystal", "category": "Crafting Components", "platform": "Console"}, "1998976972": {"name": "Vengeful Eye", "category": "Crafting Components", "platform": "Console"}, "2029265596": {"name": "Vial of Putridness", "category": "Crafting Components", "platform": "Console"}, "1016299457": {"name": "White Oak Splinter", "category": "Crafting Components", "platform": "Console"}, "-799868536": {"name": "Wirt's Bell", "category": "Crafting Components", "platform": "Console"}, "2064572133": {"name": "Wishful Essence (Vanilla)", "category": "Crafting Components", "platform": "Console"}, "1098021531": {"name": "Wooden Stake", "category": "Crafting Components", "platform": "Console"}, "2103664575": {"name": "Woven Plate", "category": "Crafting Components", "platform": "Console"}, "-1824155952": {"name": "Writhing Spine", "category": "Crafting Components", "platform": "Console"}, "-747908647": {"name": "px_HoradricReagent_01 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908646": {"name": "px_HoradricReagent_02 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908645": {"name": "px_HoradricReagent_03 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908644": {"name": "px_HoradricReagent_04 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}, "-747908643": {"name": "px_HoradricReagent_05 (Patch 2.2.0)", "category": "Crafting Components", "platform": "Console"}}, "Crafting Plans, Jeweler": {"429567911": {"name": "Design: Flawless Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521994629": {"name": "Design: Flawless Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147380749": {"name": "Design: Flawless Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872863289": {"name": "Design: Flawless Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171649812": {"name": "Design: Flawless Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521743063": {"name": "Design: Flawless Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147129183": {"name": "Design: Flawless Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872611723": {"name": "Design: Flawless Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1540480229": {"name": "Design: Hellfire Amulet (Patch 1.2.0)", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-384404829": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1792019289": {"name": "Design: Hellfire Ring", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171541998": {"name": "Design: Marquise Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521850877": {"name": "Design: Marquise Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147236997": {"name": "Design: Marquise Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872719537": {"name": "Design: Marquise Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171613874": {"name": "Design: Perfect Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521779001": {"name": "Design: Perfect Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147165121": {"name": "Design: Perfect Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872647661": {"name": "Design: Perfect Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171577936": {"name": "Design: Radiant Star Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521814939": {"name": "Design: Radiant Star Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147201059": {"name": "Design: Radiant Star Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872683599": {"name": "Design: Radiant Star Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "-1171434184": {"name": "Design: Royal Amethyst", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "429531973": {"name": "Design: Royal Diamond", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "521958691": {"name": "Design: Royal Emerald", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "2147344811": {"name": "Design: Royal Ruby", "category": "Crafting Plans, Jeweler", "platform": "Console"}, "872827351": {"name": "Design: Royal Topaz", "category": "Crafting Plans, Jeweler", "platform": "Console"}}, "Crafting Plans, Smith": {"-1427518108": {"name": "Legendary Plan: Archfiend Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1046516600": {"name": "Legendary Plan: Atrophy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1423568820": {"name": "Legendary Plan: Bitterness", "category": "Crafting Plans, Smith", "platform": "Console"}, "-380290097": {"name": "Legendary Plan: Black Bone Arrows", "category": "Crafting Plans, Smith", "platform": "Console"}, "1418151206": {"name": "Legendary Plan: Blitzbolter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-912856835": {"name": "Legendary Plan: Blood-Magic Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2000896011": {"name": "Legendary Plan: Blood-Magic Edge", "category": "Crafting Plans, Smith", "platform": "Console"}, "867919825": {"name": "Legendary Plan: Board Walkers", "category": "Crafting Plans, Smith", "platform": "Console"}, "-412066328": {"name": "Legendary Plan: Cataclysm", "category": "Crafting Plans, Smith", "platform": "Console"}, "1713442269": {"name": "Legendary Plan: Cinder Switch", "category": "Crafting Plans, Smith", "platform": "Console"}, "612002290": {"name": "Legendary Plan: Corruption", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1413614420": {"name": "Legendary Plan: Cosmic Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "421386501": {"name": "Legendary Plan: Deadeye", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1911170977": {"name": "Legendary Plan: Demon Claw", "category": "Crafting Plans, Smith", "platform": "Console"}, "999120591": {"name": "Legendary Plan: Demon Hand", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1426610660": {"name": "Legendary Plan: Devastator", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1326018783": {"name": "Legendary Plan: Earthshatter", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1003069110": {"name": "Legendary Plan: Fire Brand", "category": "Crafting Plans, Smith", "platform": "Console"}, "957458384": {"name": "Legendary Plan: Fleeting Strap", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1639510640": {"name": "Legendary Plan: Gehennas", "category": "Crafting Plans, Smith", "platform": "Console"}, "780377031": {"name": "Legendary Plan: Golden Scourge", "category": "Crafting Plans, Smith", "platform": "Console"}, "412214125": {"name": "Legendary Plan: Harvest Moon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-501637898": {"name": "Legendary Plan: Hellish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-846348803": {"name": "Legendary Plan: Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "253048194": {"name": "Legendary Plan: Infernal Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-103899531": {"name": "Legendary Plan: Kethryes' Splint", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904674800": {"name": "Legendary Plan: Lai Yui's Persuader", "category": "Crafting Plans, Smith", "platform": "Console"}, "-168948640": {"name": "Legendary Plan: Lai Yui's Taiji", "category": "Crafting Plans, Smith", "platform": "Console"}, "1029528340": {"name": "Legendary Plan: Living Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "-405238050": {"name": "Legendary Plan: Longshot", "category": "Crafting Plans, Smith", "platform": "Console"}, "269805368": {"name": "Legendary Plan: Lost Boys", "category": "Crafting Plans, Smith", "platform": "Console"}, "244699910": {"name": "Legendary Plan: Mantle of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "2012779291": {"name": "Legendary Plan: Mark of The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "1744959696": {"name": "Legendary Plan: Night's Reaping", "category": "Crafting Plans, Smith", "platform": "Console"}, "645585264": {"name": "Legendary Plan: Nightmarish Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2142082753": {"name": "Legendary Plan: Pendergrasps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-451796586": {"name": "Legendary Plan: Penders Purchase", "category": "Crafting Plans, Smith", "platform": "Console"}, "-216958038": {"name": "Legendary Plan: Piro Marella", "category": "Crafting Plans, Smith", "platform": "Console"}, "1162824884": {"name": "Legendary Plan: Quick Draw Belt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-64692264": {"name": "Legendary Plan: Reaper's Wraps", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1654685887": {"name": "Legendary Plan: Robes of the Rydraelm", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1904818548": {"name": "Legendary Plan: Rozpedin's Force", "category": "Crafting Plans, Smith", "platform": "Console"}, "1548578205": {"name": "Legendary Plan: Rozpedin's Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1861702115": {"name": "Legendary Plan: Ruinstoke", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2122397885": {"name": "Legendary Plan: Seven Sins", "category": "Crafting Plans, Smith", "platform": "Console"}, "1071490652": {"name": "Legendary Plan: Singularity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1846671248": {"name": "Legendary Plan: Skelon's Deceit", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1774978628": {"name": "Legendary Plan: Spite", "category": "Crafting Plans, Smith", "platform": "Console"}, "1806898802": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1463195022": {"name": "Legendary Plan: Staff of Herding", "category": "Crafting Plans, Smith", "platform": "Console"}, "-402133524": {"name": "Legendary Plan: Starspine", "category": "Crafting Plans, Smith", "platform": "Console"}, "527593978": {"name": "Legendary Plan: Sunder", "category": "Crafting Plans, Smith", "platform": "Console"}, "2067112046": {"name": "Legendary Plan: Sydyru Crust", "category": "Crafting Plans, Smith", "platform": "Console"}, "1121389360": {"name": "Legendary Plan: The Helm of Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "-478050163": {"name": "Legendary Plan: The Helm of Rule", "category": "Crafting Plans, Smith", "platform": "Console"}, "186340431": {"name": "Legendary Plan: The Infernal Machine", "category": "Crafting Plans, Smith", "platform": "Console"}, "274154411": {"name": "Legendary Plan: The Magi", "category": "Crafting Plans, Smith", "platform": "Console"}, "-242397939": {"name": "Legendary Plan: The Wedge", "category": "Crafting Plans, Smith", "platform": "Console"}, "-647199777": {"name": "Legendary Plan: Umbral Oath", "category": "Crafting Plans, Smith", "platform": "Console"}, "2066177684": {"name": "Legendary Plan: Unbound Bolt", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1895316276": {"name": "Legendary Plan: Unending War", "category": "Crafting Plans, Smith", "platform": "Console"}, "-241912353": {"name": "Legendary Plan: Utar's Roar", "category": "Crafting Plans, Smith", "platform": "Console"}, "-446889189": {"name": "Legendary Plan: Venomhusk", "category": "Crafting Plans, Smith", "platform": "Console"}, "-30314682": {"name": "Legendary Plan: Wall of Bone", "category": "Crafting Plans, Smith", "platform": "Console"}, "-864620096": {"name": "Legendary Plan: Wall of Man", "category": "Crafting Plans, Smith", "platform": "Console"}, "-594473293": {"name": "Legendary Plan: War of the Dead", "category": "Crafting Plans, Smith", "platform": "Console"}, "1027888204": {"name": "Legendary Plan: Wondrous Deflectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110595705": {"name": "Rare Plan: Amulet of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110601443": {"name": "Rare Plan: Amulet of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110612529": {"name": "Rare Plan: Amulet of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "2110615435": {"name": "Rare Plan: Amulet of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069218648": {"name": "Rare Plan: Archon Armor of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069212910": {"name": "Rare Plan: Archon Armor of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069201824": {"name": "Rare Plan: Archon Armor of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1069198918": {"name": "Rare Plan: Archon Armor of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427345983": {"name": "Rare Plan: Archon Gauntlets of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427340245": {"name": "Rare Plan: Archon Gauntlets of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427329159": {"name": "Rare Plan: Archon Gauntlets of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1427326253": {"name": "Rare Plan: Archon Gauntlets of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194993962": {"name": "Rare Plan: Archon Spaulders of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "1194999700": {"name": "Rare Plan: Archon Spaulders of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195010786": {"name": "Rare Plan: Archon Spaulders of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "1195013692": {"name": "Rare Plan: Archon Spaulders of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666895": {"name": "Rare Plan: Exalted Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006109": {"name": "Rare Plan: Exalted Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232950": {"name": "Rare Plan: Exalted Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008978": {"name": "Rare Plan: Exalted Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049108": {"name": "Rare Plan: Exalted Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150314": {"name": "Rare Plan: Exalted Fine Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666894": {"name": "Rare Plan: Exalted Fine Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006108": {"name": "Rare Plan: Exalted Fine Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232949": {"name": "Rare Plan: Exalted Fine Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008977": {"name": "Rare Plan: Exalted Fine Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049107": {"name": "Rare Plan: Exalted Fine Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445431": {"name": "Rare Plan: Exalted Fine Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898771": {"name": "Rare Plan: Exalted Fine Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669101": {"name": "Rare Plan: Exalted Fine Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978459": {"name": "Rare Plan: Exalted Fine Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927530": {"name": "Rare Plan: Exalted Fine Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852815": {"name": "Rare Plan: Exalted Fine Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340209": {"name": "Rare Plan: Exalted Fine Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820187": {"name": "Rare Plan: Exalted Fine Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806016": {"name": "Rare Plan: Exalted Fine Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305005": {"name": "Rare Plan: Exalted Fine Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242821": {"name": "Rare Plan: Exalted Fine Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302887": {"name": "Rare Plan: Exalted Fine Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895417": {"name": "Rare Plan: Exalted Fine Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084692": {"name": "Rare Plan: Exalted Fine Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047028": {"name": "Rare Plan: Exalted Fine Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766203": {"name": "Rare Plan: Exalted Fine Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600122": {"name": "Rare Plan: Exalted Fine Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691115": {"name": "Rare Plan: Exalted Fine Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695962": {"name": "Rare Plan: Exalted Fine Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502140": {"name": "Rare Plan: Exalted Fine Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137849": {"name": "Rare Plan: Exalted Fine Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631474": {"name": "Rare Plan: Exalted Fine Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237753": {"name": "Rare Plan: Exalted Fine Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445432": {"name": "Rare Plan: Exalted Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898770": {"name": "Rare Plan: Exalted Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669102": {"name": "Rare Plan: Exalted Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "-93021373": {"name": "Rare Plan: Exalted Grand Archmage Headpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1051150313": {"name": "Rare Plan: Exalted Grand Armplates", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1660666893": {"name": "Rare Plan: Exalted Grand Behemoth", "category": "Crafting Plans, Smith", "platform": "Console"}, "-638006107": {"name": "Rare Plan: Exalted Grand Conquest Sword", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1690232948": {"name": "Rare Plan: Exalted Grand Crag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "-364008976": {"name": "Rare Plan: Exalted Grand Doomcaster", "category": "Crafting Plans, Smith", "platform": "Console"}, "-2015049106": {"name": "Rare Plan: Exalted Grand Dread Shield", "category": "Crafting Plans, Smith", "platform": "Console"}, "-576445430": {"name": "Rare Plan: Exalted Grand Flesh Ripper", "category": "Crafting Plans, Smith", "platform": "Console"}, "1108898772": {"name": "Rare Plan: Exalted Grand Galraki", "category": "Crafting Plans, Smith", "platform": "Console"}, "972140825": {"name": "Rare Plan: Exalted Grand Ghost Sight", "category": "Crafting Plans, Smith", "platform": "Console"}, "-275669100": {"name": "Rare Plan: Exalted Grand Golden Talon", "category": "Crafting Plans, Smith", "platform": "Console"}, "2129978460": {"name": "Rare Plan: Exalted Grand Heaven Strand", "category": "Crafting Plans, Smith", "platform": "Console"}, "531375006": {"name": "Rare Plan: Exalted Grand Heavy Baldric", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927531": {"name": "Rare Plan: Exalted Grand Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1162323497": {"name": "Rare Plan: Exalted Grand Manitou Mask", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852814": {"name": "Rare Plan: Exalted Grand Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340210": {"name": "Rare Plan: Exalted Grand Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820186": {"name": "Rare Plan: Exalted Grand Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806017": {"name": "Rare Plan: Exalted Grand Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305006": {"name": "Rare Plan: Exalted Grand Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242822": {"name": "Rare Plan: Exalted Grand Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302888": {"name": "Rare Plan: Exalted Grand Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895418": {"name": "Rare Plan: Exalted Grand Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084693": {"name": "Rare Plan: Exalted Grand Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047027": {"name": "Rare Plan: Exalted Grand Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1717766204": {"name": "Rare Plan: Exalted Grand Sovereign Greaves", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600123": {"name": "Rare Plan: Exalted Grand Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691116": {"name": "Rare Plan: Exalted Grand Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "435695963": {"name": "Rare Plan: Exalted Grand Sovereign Tassets", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1205502139": {"name": "Rare Plan: Exalted Grand Sovereign Vambraces", "category": "Crafting Plans, Smith", "platform": "Console"}, "1784279615": {"name": "Rare Plan: Exalted Grand Stalker Cape", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137848": {"name": "Rare Plan: Exalted Grand Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631475": {"name": "Rare Plan: Exalted Grand Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237752": {"name": "Rare Plan: Exalted Grand Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "364927529": {"name": "Rare Plan: Exalted Impellor", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1661852816": {"name": "Rare Plan: Exalted Massacre Axe", "category": "Crafting Plans, Smith", "platform": "Console"}, "82340208": {"name": "Rare Plan: Exalted Mythical Staff", "category": "Crafting Plans, Smith", "platform": "Console"}, "-636820188": {"name": "Rare Plan: Exalted Oni Blade", "category": "Crafting Plans, Smith", "platform": "Console"}, "1134806015": {"name": "Rare Plan: Exalted Orbit Stones", "category": "Crafting Plans, Smith", "platform": "Console"}, "255305004": {"name": "Rare Plan: Exalted Pallium", "category": "Crafting Plans, Smith", "platform": "Console"}, "623242820": {"name": "Rare Plan: Exalted Phantom Bow", "category": "Crafting Plans, Smith", "platform": "Console"}, "368302886": {"name": "Rare Plan: Exalted Piercer", "category": "Crafting Plans, Smith", "platform": "Console"}, "844895416": {"name": "Rare Plan: Exalted Runic Quiver", "category": "Crafting Plans, Smith", "platform": "Console"}, "1110084691": {"name": "Rare Plan: Exalted Sagaris", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1689047029": {"name": "Rare Plan: Exalted Slag Hammer", "category": "Crafting Plans, Smith", "platform": "Console"}, "1288600121": {"name": "Rare Plan: Exalted Sovereign Helm", "category": "Crafting Plans, Smith", "platform": "Console"}, "543691114": {"name": "Rare Plan: Exalted Sovereign Mail", "category": "Crafting Plans, Smith", "platform": "Console"}, "-115137850": {"name": "Rare Plan: Exalted Strike Wand", "category": "Crafting Plans, Smith", "platform": "Console"}, "398631473": {"name": "Rare Plan: Exalted Unspeakable Thing", "category": "Crafting Plans, Smith", "platform": "Console"}, "-807237754": {"name": "Rare Plan: Exalted Zhezl", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656027917": {"name": "Rare Plan: Razorspikes of Dexterity", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656022179": {"name": "Rare Plan: Razorspikes of Intelligence", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656011093": {"name": "Rare Plan: Razorspikes of Strength", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1656008187": {"name": "Rare Plan: Razorspikes of Vitality", "category": "Crafting Plans, Smith", "platform": "Console"}, "1846613104": {"name": "Set Plan: Asheara's Uniform", "category": "Crafting Plans, Smith", "platform": "Console"}, "1930988128": {"name": "Set Plan: Asheara's Vestments", "category": "Crafting Plans, Smith", "platform": "Console"}, "1761387753": {"name": "Set Plan: Aughild's Authority", "category": "Crafting Plans, Smith", "platform": "Console"}, "-522988374": {"name": "Set Plan: Aughild's Victory", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1294645649": {"name": "Set Plan: Born's Command", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833297": {"name": "Set Plan: Born's Defiance", "category": "Crafting Plans, Smith", "platform": "Console"}, "1416190745": {"name": "Set Plan: Cain's Destiny", "category": "Crafting Plans, Smith", "platform": "Console"}, "769833298": {"name": "Set Plan: Cain's Fate", "category": "Crafting Plans, Smith", "platform": "Console"}, "179824936": {"name": "Set Plan: Captain Crimson's Finery", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1405796903": {"name": "Set Plan: Captain Crimson's Trimmings", "category": "Crafting Plans, Smith", "platform": "Console"}, "2113413150": {"name": "Set Plan: Demon's Hide", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968554": {"name": "Set Plan: Demon's Skin", "category": "Crafting Plans, Smith", "platform": "Console"}, "331434522": {"name": "Set Plan: Griswold's Masterpiece", "category": "Crafting Plans, Smith", "platform": "Console"}, "-410837290": {"name": "Set Plan: Griswold's Perfection", "category": "Crafting Plans, Smith", "platform": "Console"}, "1023052626": {"name": "Set Plan: Guardian's Contingency", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1605103146": {"name": "Set Plan: Guardian's Jeopardy", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968552": {"name": "Set Plan: Hallowed Defenders", "category": "Crafting Plans, Smith", "platform": "Console"}, "-1135146597": {"name": "Set Plan: Hallowed Protectors", "category": "Crafting Plans, Smith", "platform": "Console"}, "1831860075": {"name": "Set Plan: Sage's Journey", "category": "Crafting Plans, Smith", "platform": "Console"}, "-893968553": {"name": "Set Plan: Sage's Plight", "category": "Crafting Plans, Smith", "platform": "Console"}}, "Crafting Plans, Transmog": {"1549850923": {"name": "Arma Mortis", "category": "Crafting Plans, Transmog", "platform": "Console"}, "1549850925": {"name": "Guardian Facade", "category": "Crafting Plans, Transmog", "platform": "Console"}, "-1723454145": {"name": "Legends of the Conqueror Volume 1 (Patch 2.1.0)", "category": "Crafting Plans, Transmog", "platform": "Console"}}, "Crossbows": {"181031811": {"name": "02: Crossbow (DPS 12.7-14.3)", "category": "Crossbows", "platform": "Console"}, "181031812": {"name": "03: Heavy Crossbow (DPS 17.6-19.3)", "category": "Crossbows", "platform": "Console"}, "181031813": {"name": "04: Arbalest (DPS 22.6-24.2)", "category": "Crossbows", "platform": "Console"}, "181031814": {"name": "05: Lian Nu (DPS 27.5-29.2)", "category": "Crossbows", "platform": "Console"}, "181031815": {"name": "06: War Crossbow (DPS 32.5-34.1)", "category": "Crossbows", "platform": "Console"}, "181031816": {"name": "07: Porcupine (DPS 37.4-39.1)", "category": "Crossbows", "platform": "Console"}, "181032899": {"name": "08: Siege Crossbow (DPS 53.9-57.2)", "category": "Crossbows", "platform": "Console"}, "181032900": {"name": "09: Quarrelbow (DPS 57.2-60.5)", "category": "Crossbows", "platform": "Console"}, "181032901": {"name": "10: Heavy Siege Crossbow (DPS 64.9-68.2)", "category": "Crossbows", "platform": "Console"}, "181032902": {"name": "11: Slingbow (DPS 76.5-81.4)", "category": "Crossbows", "platform": "Console"}, "181032903": {"name": "12: Chokonu (DPS 102.9-109.5)", "category": "Crossbows", "platform": "Console"}, "181032904": {"name": "13: War Caster (DPS 122.1-130.4)", "category": "Crossbows", "platform": "Console"}, "181032905": {"name": "14: Scorpion (DPS 165.6-175.5)", "category": "Crossbows", "platform": "Console"}, "181033988": {"name": "15: Windlass (DPS 179.3-189.2)", "category": "Crossbows", "platform": "Console"}, "181033989": {"name": "16: Cranequin (DPS 194.2-204.1)", "category": "Crossbows", "platform": "Console"}, "181033990": {"name": "17: Dread Crossbow (DPS 225.0-236.5)", "category": "Crossbows", "platform": "Console"}, "181033991": {"name": "18: Nayin (DPS 281.1-294.3)", "category": "Crossbows", "platform": "Console"}, "181033992": {"name": "19: Stonebow (DPS 358.1-371.3)", "category": "Crossbows", "platform": "Console"}, "181033993": {"name": "20: Doomcaster (DPS 424.1-437.3)", "category": "Crossbows", "platform": "Console"}, "181033994": {"name": "21: Hellion Crossbow (DPS 501.1-514.3)", "category": "Crossbows", "platform": "Console"}, "181035077": {"name": "22: Rampart Bow (DPS 698.0-711.2)", "category": "Crossbows", "platform": "Console"}, "181035078": {"name": "23: Oxybeles (DPS 948.2-961.4)", "category": "Crossbows", "platform": "Console"}, "2045161301": {"name": "Art Test Crossbow 1", "category": "Crossbows", "platform": "Console"}, "2045161302": {"name": "Art Test Crossbow 2", "category": "Crossbows", "platform": "Console"}, "2045161303": {"name": "Art Test Crossbow 3", "category": "Crossbows", "platform": "Console"}, "2045161304": {"name": "Art Test Crossbow 4", "category": "Crossbows", "platform": "Console"}, "2045161305": {"name": "Art Test Crossbow 5", "category": "Crossbows", "platform": "Console"}, "-174075631": {"name": "Legendary: Arcane Barb", "category": "Crossbows", "platform": "Console"}, "-174003757": {"name": "Legendary: Bakkan Caster", "category": "Crossbows", "platform": "Console"}, "-1447231541": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1447233985": {"name": "Legendary: Bakkan Caster (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779307": {"name": "Legendary: Bakkan Caster (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172997521": {"name": "Legendary: Buriza-Do Kyanon", "category": "Crossbows", "platform": "Console"}, "-1414028197": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1414025753": {"name": "Legendary: Buriza-Do Kyanon (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779335": {"name": "Legendary: Buriza-Do Kyanon (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135048049": {"name": "Legendary: Chanon Bolter", "category": "Crossbows", "platform": "Console"}, "-174183442": {"name": "Legendary: Demon Machine", "category": "Crossbows", "platform": "Console"}, "-1453163590": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1453161146": {"name": "Legendary: Demon Machine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779302": {"name": "Legendary: Demon Machine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174147505": {"name": "Legendary: Hellrack", "category": "Crossbows", "platform": "Console"}, "-1451977669": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1451975225": {"name": "Legendary: Hellrack (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779303": {"name": "Legendary: Hellrack (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-174111568": {"name": "Legendary: Manticore", "category": "Crossbows", "platform": "Console"}, "-1450791748": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1450789304": {"name": "Legendary: Manticore (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779304": {"name": "Legendary: Manticore (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-172961584": {"name": "Legendary: Pus Spitter", "category": "Crossbows", "platform": "Console"}, "-1412842276": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1412839832": {"name": "Legendary: Pus Spitter (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779336": {"name": "Legendary: Pus Spitter (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449605827": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "-1449603383": {"name": "Legendary: Starspine (Legacy)", "category": "Crossbows", "platform": "Console"}, "1183779305": {"name": "Legendary: Starspine (Old-Legacy)", "category": "Crossbows", "platform": "Console"}, "-135012112": {"name": "Legendary: Wojahnni Assaulter", "category": "Crossbows", "platform": "Console"}, "376423602": {"name": "P2 Crossbow norm Legendary 01", "category": "Crossbows", "platform": "Console"}, "376423603": {"name": "P2 Crossbow norm Legendary 02", "category": "Crossbows", "platform": "Console"}, "762151703": {"name": "PvP: Heavy Crossbow", "category": "Crossbows", "platform": "Console"}, "762151705": {"name": "PvP: Heroic Crossbow", "category": "Crossbows", "platform": "Console"}, "762151704": {"name": "PvP: Mighty Crossbow", "category": "Crossbows", "platform": "Console"}}, "Crusader Shields": {"-118254878": {"name": "01: Crusader Shield (AR 9-10)", "category": "Crusader Shields", "platform": "Console"}, "-118254877": {"name": "02: Sacred Scutum (AR 54-62)", "category": "Crusader Shields", "platform": "Console"}, "-118254876": {"name": "03: Royal Shield (AR 99-114)", "category": "Crusader Shields", "platform": "Console"}, "-118254875": {"name": "04: Heraldic Heater (AR 144-188)", "category": "Crusader Shields", "platform": "Console"}, "-118254874": {"name": "05: Embossed Shield (AR 189-224)", "category": "Crusader Shields", "platform": "Console"}, "-118254873": {"name": "06: Protector Shield (AR 225-251)", "category": "Crusader Shields", "platform": "Console"}, "-118254872": {"name": "07: Crown Shield (AR 252-287)", "category": "Crusader Shields", "platform": "Console"}, "-118253789": {"name": "08: Gilded Shield (AR 288-359)", "category": "Crusader Shields", "platform": "Console"}, "-118253788": {"name": "09: Wall Shield (AR 360-431)", "category": "Crusader Shields", "platform": "Console"}, "-118253787": {"name": "10: Zakara Heater (AR 432-503)", "category": "Crusader Shields", "platform": "Console"}, "-118253786": {"name": "11: Blazoned Shield (AR 504-575)", "category": "Crusader Shields", "platform": "Console"}, "-118253785": {"name": "12: Chased Shield (AR 576-652)", "category": "Crusader Shields", "platform": "Console"}, "-118253784": {"name": "13: Conquest Shield (AR 652-696)", "category": "Crusader Shields", "platform": "Console"}, "-118253783": {"name": "14: Imperial Kite (AR 697-741)", "category": "Crusader Shields", "platform": "Console"}, "-118252700": {"name": "15: Righteous Defender (AR 742-786)", "category": "Crusader Shields", "platform": "Console"}, "-118252699": {"name": "16: Enduring Guardian (AR 787-831)", "category": "Crusader Shields", "platform": "Console"}, "-118252698": {"name": "17: Zealous Protector (AR 832-854)", "category": "Crusader Shields", "platform": "Console"}, "-118252697": {"name": "18: Raptor Shield (AR 855-967)", "category": "Crusader Shields", "platform": "Console"}, "-118252696": {"name": "19: Adamantine Blason (AR 967-1112)", "category": "Crusader Shields", "platform": "Console"}, "-118252695": {"name": "20: Heavy Shield (AR 1417-1979)", "category": "Crusader Shields", "platform": "Console"}, "-118252694": {"name": "21: Stalwart Guardian (AR 1980-2277)", "category": "Crusader Shields", "platform": "Console"}, "795980376": {"name": "Art Test CruShield 1", "category": "Crusader Shields", "platform": "Console"}, "795980377": {"name": "Art Test CruShield 2", "category": "Crusader Shields", "platform": "Console"}, "795980378": {"name": "Art Test CruShield 3", "category": "Crusader Shields", "platform": "Console"}, "795980379": {"name": "Art Test CruShield 4", "category": "Crusader Shields", "platform": "Console"}, "795980380": {"name": "Art Test CruShield 5", "category": "Crusader Shields", "platform": "Console"}, "820607285": {"name": "Legendary: Akarat's Awakening", "category": "Crusader Shields", "platform": "Console"}, "1983862516": {"name": "Legendary: Frydehr's Wrath (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}, "820571348": {"name": "Legendary: Hallowed Bulwark", "category": "Crusader Shields", "platform": "Console"}, "820643222": {"name": "Legendary: Hellskull", "category": "Crusader Shields", "platform": "Console"}, "820535411": {"name": "Legendary: Jekangbord", "category": "Crusader Shields", "platform": "Console"}, "820499474": {"name": "Legendary: Piro Marella", "category": "Crusader Shields", "platform": "Console"}, "820751033": {"name": "Legendary: Salvation", "category": "Crusader Shields", "platform": "Console"}, "820679159": {"name": "Legendary: Sublime Conviction", "category": "Crusader Shields", "platform": "Console"}, "820715096": {"name": "Legendary: The Final Witness", "category": "Crusader Shields", "platform": "Console"}, "1983862517": {"name": "Legendary: Unrelenting Phalanx (Patch 2.1.0)", "category": "Crusader Shields", "platform": "Console"}}, "Daggers": {"-1303415301": {"name": "02: Shiv (DPS 9.0-11.3)", "category": "Daggers", "platform": "Console"}, "-1303415300": {"name": "03: Short Dagger (DPS 15.0-17.3)", "category": "Daggers", "platform": "Console"}, "-1303415299": {"name": "04: Dagger (DPS 20.3-22.5)", "category": "Daggers", "platform": "Console"}, "-1303415298": {"name": "05: Poignard (DPS 23.3-25.5)", "category": "Daggers", "platform": "Console"}, "-1303415297": {"name": "06: Stiletto (DPS 27.0-29.3)", "category": "Daggers", "platform": "Console"}, "-1303415296": {"name": "07: Skiver (DPS 30.0-23.3)", "category": "Daggers", "platform": "Console"}, "-1303414213": {"name": "08: Jagged Dagger (DPS 38.3-40.5)", "category": "Daggers", "platform": "Console"}, "-1303414212": {"name": "09: Kindjal (DPS 44.3-46.5)", "category": "Daggers", "platform": "Console"}, "-1303414211": {"name": "10: Pugio (DPS 50.3-52.5)", "category": "Daggers", "platform": "Console"}, "-1303414210": {"name": "11: Rondel (DPS 57.0-59.3)", "category": "Daggers", "platform": "Console"}, "-1303414209": {"name": "12: Scramasax (DPS 66.0-68.3)", "category": "Daggers", "platform": "Console"}, "-1303414208": {"name": "13: Main Gauche (DPS 77.3-79.5)", "category": "Daggers", "platform": "Console"}, "-1303414207": {"name": "14: Spine (DPS 92.3-94.5)", "category": "Daggers", "platform": "Console"}, "-1303413124": {"name": "15: Kukri (DPS 101.3-103.5)", "category": "Daggers", "platform": "Console"}, "-1303413123": {"name": "16: Pavade (DPS 108.0-112.5)", "category": "Daggers", "platform": "Console"}, "-1303413122": {"name": "17: Cinquedea (DPS 117.8-122.3)", "category": "Daggers", "platform": "Console"}, "-1303413121": {"name": "18: Skain (DPS 129.0-133.5)", "category": "Daggers", "platform": "Console"}, "-1303413120": {"name": "19: Basilard (DPS 156.0-160.5)", "category": "Daggers", "platform": "Console"}, "-1303413119": {"name": "20: Piercer (DPS 177.8-182.3)", "category": "Daggers", "platform": "Console"}, "-1303413118": {"name": "21: Darkblade (DPS 202.5-209.3)", "category": "Daggers", "platform": "Console"}, "-1303412035": {"name": "22: Kingsport Blade (DPS 270.0-274.5)", "category": "Daggers", "platform": "Console"}, "-1303412034": {"name": "23: Punyal (DPS 321.0-325.5)", "category": "Daggers", "platform": "Console"}, "-1200973729": {"name": "Art Test Dagger 1", "category": "Daggers", "platform": "Console"}, "-1200973728": {"name": "Art Test Dagger 2", "category": "Daggers", "platform": "Console"}, "-1200973727": {"name": "Art Test Dagger 3", "category": "Daggers", "platform": "Console"}, "-1200973726": {"name": "Art Test Dagger 4", "category": "Daggers", "platform": "Console"}, "-1200973725": {"name": "Art Test Dagger 5", "category": "Daggers", "platform": "Console"}, "-2073514231": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "-2073511787": {"name": "Legendary: Blood-Magic Blade (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092661": {"name": "Legendary: Blood-Magic Blade (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973885091": {"name": "Legendary: Blood-Magic Edge", "category": "Daggers", "platform": "Console"}, "-934857509": {"name": "Legendary: Envious Blade", "category": "Daggers", "platform": "Console"}, "-934929383": {"name": "Legendary: Gull Dagger", "category": "Daggers", "platform": "Console"}, "-974028839": {"name": "Legendary: Kill", "category": "Daggers", "platform": "Console"}, "-2078257915": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "-2078255471": {"name": "Legendary: Kill (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092657": {"name": "Legendary: Kill (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973849154": {"name": "Legendary: Pig Sticker", "category": "Daggers", "platform": "Console"}, "-2072328310": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "-2072325866": {"name": "Legendary: Pig Sticker (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092662": {"name": "Legendary: Pig Sticker (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934893446": {"name": "Legendary: Prowl's Dastardly Shiv", "category": "Daggers", "platform": "Console"}, "-973992902": {"name": "Legendary: The Barber", "category": "Daggers", "platform": "Console"}, "-2077071994": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "-2077069550": {"name": "Legendary: The Barber (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092658": {"name": "Legendary: The Barber (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-973813217": {"name": "Legendary: The Clipper", "category": "Daggers", "platform": "Console"}, "-2071142389": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "-2071139945": {"name": "Legendary: The Clipper (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092663": {"name": "Legendary: The Clipper (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-838272988": {"name": "Legendary: The Horadric Hamburger", "category": "Daggers", "platform": "Console"}, "-1893282128": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1893279684": {"name": "Legendary: The Horadric Hamburger (Legacy)", "category": "Daggers", "platform": "Console"}, "-1817947684": {"name": "Legendary: The Horadric Hamburger (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-972914792": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-65175862": {"name": "Legendary: Wizardspike", "category": "Daggers", "platform": "Console"}, "-2041494364": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "-2041491920": {"name": "Legendary: Wizardspike (Legacy)", "category": "Daggers", "platform": "Console"}, "1111092688": {"name": "Legendary: Wizardspike (Old-Legacy)", "category": "Daggers", "platform": "Console"}, "-934821572": {"name": "Set: Eun-jang-do (Patch 2.2.0)", "category": "Daggers", "platform": "Console"}}, "Daibos": {"1771748852": {"name": "02: Spade (DPS 21.5-23.1)", "category": "Daibos", "platform": "Console"}, "1771748853": {"name": "03: Eiku (DPS 27.5-29.2)", "category": "Daibos", "platform": "Console"}, "1771748854": {"name": "04: Taiji (DPS 41.8-43.5)", "category": "Daibos", "platform": "Console"}, "1771749940": {"name": "05: Jodo Staff (DPS 51.2-52.8)", "category": "Daibos", "platform": "Console"}, "1771749941": {"name": "06: Sibat (DPS 67.1-70.4)", "category": "Daibos", "platform": "Console"}, "1771749942": {"name": "07: Trost (DPS 97.9-101.2)", "category": "Daibos", "platform": "Console"}, "1771749943": {"name": "08: Svardstav (DPS 145.2-150.2)", "category": "Daibos", "platform": "Console"}, "1771751029": {"name": "09: Lathi (DPS 176.6-183.2)", "category": "Daibos", "platform": "Console"}, "1771751030": {"name": "10: Silambam (DPS 220.6-228.8)", "category": "Daibos", "platform": "Console"}, "1771751031": {"name": "11: Drevko (DPS 274.5-284.4)", "category": "Daibos", "platform": "Console"}, "1771751032": {"name": "12: Grand Taiji (DPS 374.6-386.1)", "category": "Daibos", "platform": "Console"}, "1771751033": {"name": "13: Zhezl (DPS 442.2-455.4)", "category": "Daibos", "platform": "Console"}, "1771751034": {"name": "14: Guru Staff (DPS 522.0-535.2)", "category": "Daibos", "platform": "Console"}, "1771752118": {"name": "15: Iron Judgement (DPS 684.3-696.3)", "category": "Daibos", "platform": "Console"}, "1771752119": {"name": "16: Whirlwind Staff (DPS 925.8-937.8)", "category": "Daibos", "platform": "Console"}, "446400306": {"name": "Legendary: Balance", "category": "Daibos", "platform": "Console"}, "1846230910": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "1846233354": {"name": "Legendary: Balance (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857814": {"name": "Legendary: Balance (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446651865": {"name": "Legendary: Flying Dragon", "category": "Daibos", "platform": "Console"}, "1854532357": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "1854534801": {"name": "Legendary: Flying Dragon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857807": {"name": "Legendary: Flying Dragon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446436243": {"name": "Legendary: Incense Torch of the Grand Temple", "category": "Daibos", "platform": "Console"}, "1847416831": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "1847419275": {"name": "Legendary: Incense Torch of the Grand Temple (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857813": {"name": "Legendary: Incense Torch of the Grand Temple (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446615928": {"name": "Legendary: Lai Yui's Persuader", "category": "Daibos", "platform": "Console"}, "1853346436": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "1853348880": {"name": "Legendary: Lai Yui's Taiji (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857808": {"name": "Legendary: Lai Yui's Taiji (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446472180": {"name": "Legendary: Rozpedin's Force", "category": "Daibos", "platform": "Console"}, "1848602752": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "1848605196": {"name": "Legendary: Rozpedin's Staff (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857812": {"name": "Legendary: Rozpedin's Staff (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485499762": {"name": "Legendary: Staff of Kyro", "category": "Daibos", "platform": "Console"}, "1849788673": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "1849791117": {"name": "Legendary: The Clouds and the Moon (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857811": {"name": "Legendary: The Clouds and the Moon (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446508117": {"name": "Legendary: The Flow of Eternity", "category": "Daibos", "platform": "Console"}, "446579991": {"name": "Legendary: The Paddle", "category": "Daibos", "platform": "Console"}, "1852160515": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "1852162959": {"name": "Legendary: The Paddle (Legacy)", "category": "Daibos", "platform": "Console"}, "-326857809": {"name": "Legendary: The Paddle (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "485535699": {"name": "Legendary: Warstaff of General Quang", "category": "Daibos", "platform": "Console"}, "-326857815": {"name": "Set: Inna's Justice (Old-Legacy)", "category": "Daibos", "platform": "Console"}, "446364369": {"name": "Set: Inna's Reach", "category": "Daibos", "platform": "Console"}, "1845044989": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}, "1845047433": {"name": "Set: Inna's Reach (Legacy)", "category": "Daibos", "platform": "Console"}}, "Debug": {"201941397": {"name": "Debug Axe 002", "category": "Debug", "platform": "Console"}, "1162537406": {"name": "Debug Bow 001", "category": "Debug", "platform": "Console"}, "-1837157688": {"name": "Debug CrossBow 001", "category": "Debug", "platform": "Console"}, "110611392": {"name": "Debug Dagger 001", "category": "Debug", "platform": "Console"}, "-257486314": {"name": "Debug FistWeapon 001", "category": "Debug", "platform": "Console"}, "-1314119444": {"name": "Debug Mace 001", "category": "Debug", "platform": "Console"}, "-1314119443": {"name": "Debug Mace 002", "category": "Debug", "platform": "Console"}, "-1919522874": {"name": "Debug Polearm 001", "category": "Debug", "platform": "Console"}, "201837585": {"name": "Debug Spear 001", "category": "Debug", "platform": "Console"}, "-1812541014": {"name": "Debug Staff 001", "category": "Debug", "platform": "Console"}, "97851424": {"name": "Debug Wand 001", "category": "Debug", "platform": "Console"}, "109003955": {"name": "Professional Russian's 100 DPS 1H Axe", "category": "Debug", "platform": "Console"}, "1012655083": {"name": "Professional Russian's 100 DPS 1H Mace", "category": "Debug", "platform": "Console"}, "198260772": {"name": "Professional Russian's 100 DPS 1H Sword", "category": "Debug", "platform": "Console"}, "109003988": {"name": "Professional Russian's 100 DPS 2H Axe", "category": "Debug", "platform": "Console"}, "1012655116": {"name": "Professional Russian's 100 DPS 2H Mace", "category": "Debug", "platform": "Console"}, "198260805": {"name": "Professional Russian's 100 DPS 2H Sword", "category": "Debug", "platform": "Console"}, "1565754085": {"name": "Professional Russian's 100 DPS Bow", "category": "Debug", "platform": "Console"}, "1144284824": {"name": "Professional Russian's 100 DPS Crossbow Pistol", "category": "Debug", "platform": "Console"}, "199216263": {"name": "Professional Russian's 100 DPS Dagger", "category": "Debug", "platform": "Console"}, "131016487": {"name": "Professional Russian's 100 DPS Wand", "category": "Debug", "platform": "Console"}, "-268664650": {"name": "Professional Russian's Blind Proc Bow", "category": "Debug", "platform": "Console"}, "-497584419": {"name": "Professional Russian's Blind Proc Sword", "category": "Debug", "platform": "Console"}, "-1692695305": {"name": "Professional Russian's Bow", "category": "Debug", "platform": "Console"}, "-1353182983": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-1489225678": {"name": "Professional Russian's Chill Proc Bow", "category": "Debug", "platform": "Console"}, "-422042656": {"name": "Professional Russian's Chill Proc Sword", "category": "Debug", "platform": "Console"}, "860521450": {"name": "Professional Russian's Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-708154023": {"name": "Professional Russian's Dagger", "category": "Debug", "platform": "Console"}, "-813820178": {"name": "Professional Russian's Fast Crossbow Pistol", "category": "Debug", "platform": "Console"}, "-1759844230": {"name": "Professional Russian's Fast Sword", "category": "Debug", "platform": "Console"}, "-1433265027": {"name": "Professional Russian's Fast Wand", "category": "Debug", "platform": "Console"}, "1812597803": {"name": "Professional Russian's Fear Proc Bow", "category": "Debug", "platform": "Console"}, "-1745505390": {"name": "Professional Russian's Fear Proc Sword", "category": "Debug", "platform": "Console"}, "-2004205682": {"name": "Professional Russian's Freeze Proc Bow", "category": "Debug", "platform": "Console"}, "-716158027": {"name": "Professional Russian's Freeze Proc Sword", "category": "Debug", "platform": "Console"}, "-1049148770": {"name": "Professional Russian's Immobilize Proc Bow", "category": "Debug", "platform": "Console"}, "1369510420": {"name": "Professional Russian's Knockback Proc Bow", "category": "Debug", "platform": "Console"}, "1063638971": {"name": "Professional Russian's Knockback Proc Sword", "category": "Debug", "platform": "Console"}, "-798366331": {"name": "Professional Russian's One-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206717": {"name": "Professional Russian's One-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502602": {"name": "Professional Russian's One-Handed Sword", "category": "Debug", "platform": "Console"}, "-395086843": {"name": "Professional Russian's Slow Crossbow Pistol", "category": "Debug", "platform": "Console"}, "1751317849": {"name": "Professional Russian's Slow Proc Sword", "category": "Debug", "platform": "Console"}, "-1341110895": {"name": "Professional Russian's Slow Sword", "category": "Debug", "platform": "Console"}, "-1899067884": {"name": "Professional Russian's Slow Wand", "category": "Debug", "platform": "Console"}, "476722551": {"name": "Professional Russian's Stun Proc Bow", "category": "Debug", "platform": "Console"}, "-41266491": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-519741474": {"name": "Professional Russian's Stun Proc Sword", "category": "Debug", "platform": "Console"}, "-798366298": {"name": "Professional Russian's Two-Handed Axe", "category": "Debug", "platform": "Console"}, "1134206750": {"name": "Professional Russian's Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-85502569": {"name": "Professional Russian's Two-Handed Sword", "category": "Debug", "platform": "Console"}, "-23630983": {"name": "Professional Russian's Wand", "category": "Debug", "platform": "Console"}, "-908294397": {"name": "Shadowclone Ceremonial Knife (Hell)", "category": "Debug", "platform": "Console"}, "2012151919": {"name": "Shadowclone Ceremonial Knife (Inferno)", "category": "Debug", "platform": "Console"}, "754127773": {"name": "Shadowclone Ceremonial Knife (Nightmare)", "category": "Debug", "platform": "Console"}, "-1043228665": {"name": "Shadowclone Ceremonial Knife (Normal)", "category": "Debug", "platform": "Console"}, "-1067377991": {"name": "Shadowclone Crusader Shield", "category": "Debug", "platform": "Console"}, "413641572": {"name": "Shadowclone Daibo (Hell)", "category": "Debug", "platform": "Console"}, "1791808816": {"name": "Shadowclone Daibo (Inferno)", "category": "Debug", "platform": "Console"}, "1318657182": {"name": "Shadowclone Daibo (Nightmare)", "category": "Debug", "platform": "Console"}, "-269002584": {"name": "Shadowclone Daibo (Normal)", "category": "Debug", "platform": "Console"}, "-909812331": {"name": "Shadowclone Hand Crossbow (Hell)", "category": "Debug", "platform": "Console"}, "-998234687": {"name": "Shadowclone Hand Crossbow (Inferno)", "category": "Debug", "platform": "Console"}, "-496839313": {"name": "Shadowclone Hand Crossbow (Nightmare)", "category": "Debug", "platform": "Console"}, "1598708505": {"name": "Shadowclone Hand Crossbow (Normal)", "category": "Debug", "platform": "Console"}, "-1831368437": {"name": "Shadowclone Mojo", "category": "Debug", "platform": "Console"}, "-989882433": {"name": "Shadowclone One-Handed Flail", "category": "Debug", "platform": "Console"}, "318426510": {"name": "Shadowclone Staff (Hell)", "category": "Debug", "platform": "Console"}, "-1157906662": {"name": "Shadowclone Staff (Inferno)", "category": "Debug", "platform": "Console"}, "1714039048": {"name": "Shadowclone Staff (Nightmare)", "category": "Debug", "platform": "Console"}, "-878989998": {"name": "Shadowclone Staff (Normal)", "category": "Debug", "platform": "Console"}, "1875985680": {"name": "Shadowclone Two-Handed Mighty Weapon (Hell)", "category": "Debug", "platform": "Console"}, "832184156": {"name": "Shadowclone Two-Handed Mighty Weapon (Inferno)", "category": "Debug", "platform": "Console"}, "-35544630": {"name": "Shadowclone Two-Handed Mighty Weapon (Nightmare)", "category": "Debug", "platform": "Console"}, "-1209135788": {"name": "Shadowclone Two-Handed Mighty Weapon (Normal)", "category": "Debug", "platform": "Console"}, "2099757732": {"name": "ThorTest Bow", "category": "Debug", "platform": "Console"}, "-163370651": {"name": "ThorTest Ceremonial Dagger", "category": "Debug", "platform": "Console"}, "1291822630": {"name": "ThorTest CombatStaff", "category": "Debug", "platform": "Console"}, "-1647832978": {"name": "ThorTest Crossbow", "category": "Debug", "platform": "Console"}, "774399974": {"name": "ThorTest Dagger", "category": "Debug", "platform": "Console"}, "726818364": {"name": "ThorTest FistWeapon", "category": "Debug", "platform": "Console"}, "454120887": {"name": "ThorTest Hand Crossbow", "category": "Debug", "platform": "Console"}, "572923409": {"name": "ThorTest Mojo", "category": "Debug", "platform": "Console"}, "684187666": {"name": "ThorTest One-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118934": {"name": "ThorTest One-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530416": {"name": "ThorTest One-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903165": {"name": "ThorTest One-Handed Sword", "category": "Debug", "platform": "Console"}, "2099771967": {"name": "ThorTest Orb", "category": "Debug", "platform": "Console"}, "-1343109204": {"name": "ThorTest Polearm", "category": "Debug", "platform": "Console"}, "1306966712": {"name": "ThorTest Quiver", "category": "Debug", "platform": "Console"}, "1369802229": {"name": "ThorTest Shield", "category": "Debug", "platform": "Console"}, "1733748983": {"name": "ThorTest Spear", "category": "Debug", "platform": "Console"}, "1733888528": {"name": "ThorTest Staff", "category": "Debug", "platform": "Console"}, "684187699": {"name": "ThorTest Two-Handed Axe", "category": "Debug", "platform": "Console"}, "-1481118901": {"name": "ThorTest Two-Handed Mace", "category": "Debug", "platform": "Console"}, "-969530383": {"name": "ThorTest Two-Handed Mighty Weapon", "category": "Debug", "platform": "Console"}, "-491903132": {"name": "ThorTest Two-Handed Sword", "category": "Debug", "platform": "Console"}, "573267654": {"name": "ThorTest Wand", "category": "Debug", "platform": "Console"}}, "Dyes": {"-575184703": {"name": "All-Soap's Miraculous Dye Remover", "category": "Dyes", "platform": "Console"}, "-234196827": {"name": "Aquatic Dye", "category": "Dyes", "platform": "Console"}, "-234196822": {"name": "Autumn Dye", "category": "Dyes", "platform": "Console"}, "1866876233": {"name": "Bottled Cloud", "category": "Dyes", "platform": "Console"}, "1866876234": {"name": "Bottled Smoke", "category": "Dyes", "platform": "Console"}, "-234196826": {"name": "Cardinal Dye", "category": "Dyes", "platform": "Console"}, "-234196823": {"name": "Desert Dye", "category": "Dyes", "platform": "Console"}, "-234196795": {"name": "Elegant Dye", "category": "Dyes", "platform": "Console"}, "-234196794": {"name": "Forester's Dye", "category": "Dyes", "platform": "Console"}, "-234196792": {"name": "Golden Dye", "category": "Dyes", "platform": "Console"}, "-234196790": {"name": "Infernal Dye", "category": "Dyes", "platform": "Console"}, "-234196798": {"name": "Lovely Dye", "category": "Dyes", "platform": "Console"}, "-234196793": {"name": "Mariner's Dye", "category": "Dyes", "platform": "Console"}, "-234196789": {"name": "Purity Dye", "category": "Dyes", "platform": "Console"}, "-234196825": {"name": "Ranger's Dye", "category": "Dyes", "platform": "Console"}, "-234196791": {"name": "Royal Dye", "category": "Dyes", "platform": "Console"}, "-234196796": {"name": "Spring Dye", "category": "Dyes", "platform": "Console"}, "-234196797": {"name": "Summer Dye", "category": "Dyes", "platform": "Console"}, "-234196830": {"name": "Tanner's Dye", "category": "Dyes", "platform": "Console"}, "-2000448920": {"name": "Vanishing Dye", "category": "Dyes", "platform": "Console"}, "-234196828": {"name": "Winter Dye", "category": "Dyes", "platform": "Console"}}, "Enchantress Focuses": {"761436847": {"name": "02: Eye", "category": "Enchantress Focuses", "platform": "Console"}, "761437935": {"name": "03: Scrying Glass", "category": "Enchantress Focuses", "platform": "Console"}, "761437936": {"name": "04: Blink", "category": "Enchantress Focuses", "platform": "Console"}, "761437937": {"name": "05: Crucible", "category": "Enchantress Focuses", "platform": "Console"}, "761437938": {"name": "06: Root", "category": "Enchantress Focuses", "platform": "Console"}, "761439024": {"name": "07: Eternity Mirror", "category": "Enchantress Focuses", "platform": "Console"}, "761439025": {"name": "08: Oculus", "category": "Enchantress Focuses", "platform": "Console"}, "761439026": {"name": "09: Cauldron", "category": "Enchantress Focuses", "platform": "Console"}, "761439027": {"name": "10: Herb", "category": "Enchantress Focuses", "platform": "Console"}, "761439028": {"name": "11: Anamorphosis", "category": "Enchantress Focuses", "platform": "Console"}, "761439029": {"name": "12: Augur", "category": "Enchantress Focuses", "platform": "Console"}, "-450681607": {"name": "Legendary: Hand of the Prophet", "category": "Enchantress Focuses", "platform": "Console"}, "-450681608": {"name": "Legendary: Smoking Thurible", "category": "Enchantress Focuses", "platform": "Console"}, "-450681606": {"name": "Legendary: Vadim's Surge", "category": "Enchantress Focuses", "platform": "Console"}}, "Fist Weapons": {"1236604968": {"name": "01: Knuckles (DPS 7.0-8.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604969": {"name": "02: Spikes (DPS 15.4-17.5)", "category": "Fist Weapons", "platform": "Console"}, "1236604970": {"name": "03: Talon (DPS 20.3-22.4)", "category": "Fist Weapons", "platform": "Console"}, "1236604971": {"name": "04: Shuko (DPS 29.4-31.5)", "category": "Fist Weapons", "platform": "Console"}, "1236606057": {"name": "05: Breaker (DPS 38.5-40.6)", "category": "Fist Weapons", "platform": "Console"}, "1236606058": {"name": "06: Iron Fist (DPS 46.2-48.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606059": {"name": "07: Claw (DPS 60.2-62.3)", "category": "Fist Weapons", "platform": "Console"}, "1236606060": {"name": "08: Kastet (DPS 81.2-83.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607146": {"name": "09: Grappler (DPS 106.4-110.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607147": {"name": "10: Hammer Hand (DPS 130.2-134.4)", "category": "Fist Weapons", "platform": "Console"}, "1236607148": {"name": "11: Demon Fang (DPS 156.8-163.1)", "category": "Fist Weapons", "platform": "Console"}, "1236607149": {"name": "12: Pulverizer (DPS 181.3-187.6)", "category": "Fist Weapons", "platform": "Console"}, "1236607150": {"name": "13: Golden Talon (DPS 210.0-216.3)", "category": "Fist Weapons", "platform": "Console"}, "1236607151": {"name": "14: Heaven Hand (DPS 242.2-248.5)", "category": "Fist Weapons", "platform": "Console"}, "1236608235": {"name": "15: Spiked Fist (DPS 322.0-328.3)", "category": "Fist Weapons", "platform": "Console"}, "1236608236": {"name": "16: Suwaiya (DPS 392.0-398.3)", "category": "Fist Weapons", "platform": "Console"}, "1349166155": {"name": "Art Test Fist 1", "category": "Fist Weapons", "platform": "Console"}, "1349166156": {"name": "Art Test Fist 2", "category": "Fist Weapons", "platform": "Console"}, "1349166157": {"name": "Art Test Fist 3", "category": "Fist Weapons", "platform": "Console"}, "1349166158": {"name": "Art Test Fist 4", "category": "Fist Weapons", "platform": "Console"}, "1349166159": {"name": "Art Test Fist 5", "category": "Fist Weapons", "platform": "Console"}, "-1097629365": {"name": "Legendary: Crystal Fist", "category": "Fist Weapons", "platform": "Console"}, "-1862107977": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1862105533": {"name": "Legendary: Crystal Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690589": {"name": "Legendary: Crystal Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "2032005920": {"name": "Legendary: Deathreach", "category": "Fist Weapons", "platform": "Console"}, "-1097773113": {"name": "Legendary: Demon Claw", "category": "Fist Weapons", "platform": "Console"}, "-1866851661": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1866849217": {"name": "Legendary: Demon Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690593": {"name": "Legendary: Demon Hand (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058709594": {"name": "Legendary: Falcon Strike", "category": "Fist Weapons", "platform": "Console"}, "537275943": {"name": "Legendary: Fist Weapon of the Shattered Hand (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097665302": {"name": "Legendary: Fleshrake", "category": "Fist Weapons", "platform": "Console"}, "-1863293898": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1863291454": {"name": "Legendary: Fleshrake (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690590": {"name": "Legendary: Fleshrake (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1058745531": {"name": "Legendary: Jawbreaker", "category": "Fist Weapons", "platform": "Console"}, "-1097737176": {"name": "Legendary: Logan's Claw", "category": "Fist Weapons", "platform": "Console"}, "-1865665740": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1865663296": {"name": "Legendary: Logan's Claw (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690592": {"name": "Legendary: Logan's Claw (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097809050": {"name": "Legendary: Rabid Strike", "category": "Fist Weapons", "platform": "Console"}, "-1868037582": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1868035138": {"name": "Legendary: Rabid Strike (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690594": {"name": "Legendary: Rabid Strike (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096623129": {"name": "Legendary: Scarbringer", "category": "Fist Weapons", "platform": "Console"}, "-1828902189": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1828899745": {"name": "Legendary: Scarbringer (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690561": {"name": "Legendary: Scarbringer (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096659066": {"name": "Legendary: Sledge Fist", "category": "Fist Weapons", "platform": "Console"}, "-1830088110": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1830085666": {"name": "Legendary: Sledge Fist (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690562": {"name": "Legendary: Sledge Fist (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1097593428": {"name": "Legendary: The Fist of Az'Turrasq", "category": "Fist Weapons", "platform": "Console"}, "-1860922056": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1860919612": {"name": "Legendary: The Fist of Az'Turrasq (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690588": {"name": "Legendary: The Fist of Az'Turrasq (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132078": {"name": "Legendary: Vengeful Wind (Patch 2.1.0)", "category": "Fist Weapons", "platform": "Console"}, "-1097701239": {"name": "Legendary: Won Khim Lau", "category": "Fist Weapons", "platform": "Console"}, "-1864479819": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1864477375": {"name": "Legendary: Won Khim Lau (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690591": {"name": "Legendary: Won Khim Lau (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-233132079": {"name": "P1 fistWeapon norm Legendary 01", "category": "Fist Weapons", "platform": "Console"}, "-1826530347": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1826527903": {"name": "Set: Hallowed Hand (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096551255": {"name": "Set: Hallowed Hold", "category": "Fist Weapons", "platform": "Console"}, "-840690559": {"name": "Set: Hallowed Touch (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690563": {"name": "Set: Shenlong's Crashing Tide (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-840690564": {"name": "Set: Shenlong's Endless Wave (Old-Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096695003": {"name": "Set: Shenlong's Fist of Legend", "category": "Fist Weapons", "platform": "Console"}, "-1831274031": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1831271587": {"name": "Set: Shenlong's Fist of Legend (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1096730940": {"name": "Set: Shenlong's Relentless Assault", "category": "Fist Weapons", "platform": "Console"}, "-1832459952": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}, "-1832457508": {"name": "Set: Shenlong's Relentless Assault (Legacy)", "category": "Fist Weapons", "platform": "Console"}}, "Flails, One-Handed": {"-912456880": {"name": "01: Spiked Flail (DPS 7.7-9.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456879": {"name": "02: Iron Whip (DPS 13.3-15.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456878": {"name": "03: Barbed Flail (DPS 18.9-21.0)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456877": {"name": "04: Thresher (DPS 25.2-27.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912456876": {"name": "05: Flail (DPS 30.8-32.9)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455791": {"name": "06: Ball and Chain (DPS 35.0-37.1)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455790": {"name": "07: Chain Mace (DPS 43.4-45.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455789": {"name": "08: Shredder (DPS 53.2-55.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455788": {"name": "09: Imposing Flail (DPS 71.4-73.5)", "category": "Flails, One-Handed", "platform": "Console"}, "-912455787": {"name": "10: Royal Guardian (DPS 105.0-109.2)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454702": {"name": "11: Painbringer (DPS 119.0-125.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454701": {"name": "12: Knout (DPS 139.3-145.6)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454700": {"name": "13: Wicked Flail (DPS 177.1-183.4)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454699": {"name": "14: Giant's Flail (DPS 312.9-321.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-912454698": {"name": "15: Grandfather's Flail (DPS 382.9-391.3)", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955915": {"name": "Art Test Flails One-Handed 1", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955914": {"name": "Art Test Flails One-Handed 2", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955913": {"name": "Art Test Flails One-Handed 3", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955912": {"name": "Art Test Flails One-Handed 4", "category": "Flails, One-Handed", "platform": "Console"}, "-1506955911": {"name": "Art Test Flails One-Handed 5", "category": "Flails, One-Handed", "platform": "Console"}, "-1791015660": {"name": "Legendary: Darklight", "category": "Flails, One-Handed", "platform": "Console"}, "-1791195345": {"name": "Legendary: Golden Scourge", "category": "Flails, One-Handed", "platform": "Console"}, "-1791051597": {"name": "Legendary: Gyrfalcon's Foote", "category": "Flails, One-Handed", "platform": "Console"}, "-1790979723": {"name": "Legendary: Inviolable Faith", "category": "Flails, One-Handed", "platform": "Console"}, "-1791159408": {"name": "Legendary: Justinian's Mercy", "category": "Flails, One-Handed", "platform": "Console"}, "-1791087534": {"name": "Legendary: Kassar's Retribution", "category": "Flails, One-Handed", "platform": "Console"}, "1226090826": {"name": "Legendary: Mortal Coil", "category": "Flails, One-Handed", "platform": "Console"}, "-1791123471": {"name": "Legendary: Swiftmount", "category": "Flails, One-Handed", "platform": "Console"}, "1784501906": {"name": "P1 Flails1H norm Legendary 01", "category": "Flails, One-Handed", "platform": "Console"}}, "Flails, Two-Handed": {"-873321486": {"name": "02: Battle Flail (DPS 15.0-16.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321485": {"name": "03: Grand Thresher (DPS 22.4-24.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321484": {"name": "04: Two-Handed Flail (DPS 29.3-31.1)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873321483": {"name": "05: Castigator (DPS 37.4-40.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320398": {"name": "06: Pyeongon (DPS 51.8-55.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320397": {"name": "07: Chigiriki (DPS 65.0-70.2)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320396": {"name": "08: Threshal (DPS 81.7-86.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320395": {"name": "09: Grand Flail (DPS 102.9-109.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873320394": {"name": "10: Angelic Flail (DPS 146.1-154.7)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319309": {"name": "11: Campaigner's Grand Flail (DPS 194.4-206.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319308": {"name": "12: Bludgeoning Grand Flail (DPS 261.6-275.4)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319307": {"name": "13: Painbringer Grand Flail (DPS 333.5-347.3)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319306": {"name": "14: Baroque Grand Flail (DPS 648.0-661.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-873319305": {"name": "15: Angelic Grand Flail (DPS 878.0-891.8)", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919978": {"name": "Art Test Flails Two-Handed 1", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919977": {"name": "Art Test Flails Two-Handed 2", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919976": {"name": "Art Test Flails Two-Handed 3", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919975": {"name": "Art Test Flails Two-Handed 4", "category": "Flails, Two-Handed", "platform": "Console"}, "-1506919974": {"name": "Art Test Flails Two-Handed 5", "category": "Flails, Two-Handed", "platform": "Console"}, "163153041": {"name": "Legendary: Baleful Remnant", "category": "Flails, Two-Handed", "platform": "Console"}, "163188978": {"name": "Legendary: Fate of the Fell", "category": "Flails, Two-Handed", "platform": "Console"}, "163224915": {"name": "Legendary: Golden Flense", "category": "Flails, Two-Handed", "platform": "Console"}, "163117104": {"name": "Legendary: The Mortal Drama", "category": "Flails, Two-Handed", "platform": "Console"}, "1784501907": {"name": "P1 Flails1H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712685": {"name": "P1 Flails2H norm Legendary 01", "category": "Flails, Two-Handed", "platform": "Console"}, "-46712684": {"name": "P1 Flails2H norm Legendary 02", "category": "Flails, Two-Handed", "platform": "Console"}, "-1026738420": {"name": "legendary: Golden Flense (Patch 2.2.0)", "category": "Flails, Two-Handed", "platform": "Console"}}, "Gems": {"-1411866896": {"name": "Amethyst 02: Flawed Amethyst", "category": "Gems", "platform": "Console"}, "-1411866895": {"name": "Amethyst 03: Amethyst", "category": "Gems", "platform": "Console"}, "-1411866894": {"name": "Amethyst 04: Flawless Amethyst", "category": "Gems", "platform": "Console"}, "-1411866893": {"name": "Amethyst 05: Perfect Amethyst", "category": "Gems", "platform": "Console"}, "-1411866892": {"name": "Amethyst 06: Radiant Amethyst", "category": "Gems", "platform": "Console"}, "-1411866891": {"name": "Amethyst 07: Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866890": {"name": "Amethyst 08: Flawless Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866889": {"name": "Amethyst 09: Perfect Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866865": {"name": "Amethyst 10: Radiant Square Amethyst", "category": "Gems", "platform": "Console"}, "-1411866864": {"name": "Amethyst 11: Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866863": {"name": "Amethyst 12: Flawless Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866862": {"name": "Amethyst 13: Perfect Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866861": {"name": "Amethyst 14: Radiant Star Amethyst", "category": "Gems", "platform": "Console"}, "-1411866860": {"name": "Amethyst 15: Marquise Amethyst", "category": "Gems", "platform": "Console"}, "-1411866859": {"name": "Amethyst 16: Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866858": {"name": "Amethyst 17: Flawless Imperial Amethyst", "category": "Gems", "platform": "Console"}, "-1411866857": {"name": "Amethyst 18: Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1411866856": {"name": "Amethyst 19: Flawless Royal Amethyst", "category": "Gems", "platform": "Console"}, "-1315690660": {"name": "Diamond 01: Chipped Diamond", "category": "Gems", "platform": "Console"}, "-1315690659": {"name": "Diamond 02: Flawed Diamond", "category": "Gems", "platform": "Console"}, "-1315690658": {"name": "Diamond 03: Diamond", "category": "Gems", "platform": "Console"}, "-1315690657": {"name": "Diamond 04: Flawless Diamond", "category": "Gems", "platform": "Console"}, "-1315690656": {"name": "Diamond 05: Perfect Diamond", "category": "Gems", "platform": "Console"}, "-1315690655": {"name": "Diamond 06: Radiant Diamond", "category": "Gems", "platform": "Console"}, "-1315690654": {"name": "Diamond 07: Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690653": {"name": "Diamond 08: Flawless Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690652": {"name": "Diamond 09: Perfect Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690628": {"name": "Diamond 10: Radiant Square Diamond", "category": "Gems", "platform": "Console"}, "-1315690627": {"name": "Diamond 11: Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690626": {"name": "Diamond 12: Flawless Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690625": {"name": "Diamond 13: Perfect Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690624": {"name": "Diamond 14: Radiant Star Diamond", "category": "Gems", "platform": "Console"}, "-1315690623": {"name": "Diamond 15: Marquise Diamond", "category": "Gems", "platform": "Console"}, "-1315690622": {"name": "Diamond 16: Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690621": {"name": "Diamond 17: Flawless Imperial Diamond", "category": "Gems", "platform": "Console"}, "-1315690620": {"name": "Diamond 18: Royal Diamond", "category": "Gems", "platform": "Console"}, "-1315690619": {"name": "Diamond 19: Flawless Royal Diamond", "category": "Gems", "platform": "Console"}, "-1733388806": {"name": "Emerald 01: Chipped Emerald", "category": "Gems", "platform": "Console"}, "-1733388805": {"name": "Emerald 02: Flawed Emerald", "category": "Gems", "platform": "Console"}, "-1733388804": {"name": "Emerald 03: Emerald", "category": "Gems", "platform": "Console"}, "-1733388803": {"name": "Emerald 04: Flawless Emerald", "category": "Gems", "platform": "Console"}, "-1733388802": {"name": "Emerald 05: Perfect Emerald", "category": "Gems", "platform": "Console"}, "-1733388801": {"name": "Emerald 06: Radiant Emerald", "category": "Gems", "platform": "Console"}, "-1733388800": {"name": "Emerald 07: Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388799": {"name": "Emerald 08: Flawless Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388798": {"name": "Emerald 09: Perfect Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388774": {"name": "Emerald 10: Radiant Square Emerald", "category": "Gems", "platform": "Console"}, "-1733388773": {"name": "Emerald 11: Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388772": {"name": "Emerald 12: Flawless Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388771": {"name": "Emerald 13: Perfect Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388770": {"name": "Emerald 14: Radiant Star Emerald", "category": "Gems", "platform": "Console"}, "-1733388769": {"name": "Emerald 15: Marquise Emerald", "category": "Gems", "platform": "Console"}, "-1733388768": {"name": "Emerald 16: Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388767": {"name": "Emerald 17: Flawless Imperial Emerald", "category": "Gems", "platform": "Console"}, "-1733388766": {"name": "Emerald 18: Royal Emerald", "category": "Gems", "platform": "Console"}, "-1733388765": {"name": "Emerald 19: Flawless Royal Emerald", "category": "Gems", "platform": "Console"}, "-1046455929": {"name": "Legendary: Bane of the Powerful (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046419992": {"name": "Legendary: Bane of the Trapped (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045162197": {"name": "Legendary: Boon of the Hoarder (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045305945": {"name": "Legendary: Enforcer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045090323": {"name": "Legendary: Esoteric Alteration (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1044084087": {"name": "Legendary: Gem Of X NYI (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046312181": {"name": "Legendary: Gem of Efficacious Toxin (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046384055": {"name": "Legendary: Gem of Reduced Level Requirement (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046204370": {"name": "Legendary: Gogok of Swiftness (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046168433": {"name": "Legendary: Invigorating Gemstone (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046240307": {"name": "Legendary: Mirinae, Teardrop of the Starweaver (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045054386": {"name": "Legendary: Molten Wildebeest's Gizzard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045270008": {"name": "Legendary: Moratorium (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044982512": {"name": "Legendary: Mutilation Guard (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1046276244": {"name": "Legendary: Pain Enhancer (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1044120024": {"name": "Legendary: Shen's Delight (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045198134": {"name": "Legendary: Simplicity's Strength (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045018449": {"name": "Legendary: Stone Of Heresy (Patch 2.1.2)", "category": "Gems", "platform": "Console"}, "-1045126260": {"name": "Legendary: Taeguk (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1046348118": {"name": "Legendary: Wreath of Lightning (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "-1045234071": {"name": "Legendary: Zei's Stone of Vengeance (Patch 2.1.0)", "category": "Gems", "platform": "Console"}, "1603007810": {"name": "Ruby 01: Chipped Ruby", "category": "Gems", "platform": "Console"}, "1603007811": {"name": "Ruby 02: Flawed Ruby", "category": "Gems", "platform": "Console"}, "1603007812": {"name": "Ruby 03: Ruby", "category": "Gems", "platform": "Console"}, "1603007813": {"name": "Ruby 04: Flawless Ruby", "category": "Gems", "platform": "Console"}, "1603007814": {"name": "Ruby 05: Perfect Ruby", "category": "Gems", "platform": "Console"}, "1603007815": {"name": "Ruby 06: Radiant Ruby", "category": "Gems", "platform": "Console"}, "1603007816": {"name": "Ruby 07: Square Ruby", "category": "Gems", "platform": "Console"}, "1603007817": {"name": "Ruby 08: Flawless Square Ruby", "category": "Gems", "platform": "Console"}, "1603007818": {"name": "Ruby 09: Perfect Square Ruby", "category": "Gems", "platform": "Console"}, "1603007842": {"name": "Ruby 10: Radiant Square Ruby", "category": "Gems", "platform": "Console"}, "1603007843": {"name": "Ruby 11: Star Ruby", "category": "Gems", "platform": "Console"}, "1603007844": {"name": "Ruby 12: Flawless Star Ruby", "category": "Gems", "platform": "Console"}, "1603007845": {"name": "Ruby 13: Perfect Star Ruby", "category": "Gems", "platform": "Console"}, "1603007846": {"name": "Ruby 14: Radiant Star Ruby", "category": "Gems", "platform": "Console"}, "1603007847": {"name": "Ruby 15: Marquise Ruby", "category": "Gems", "platform": "Console"}, "1603007848": {"name": "Ruby 16: Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007849": {"name": "Ruby 17: Flawless Imperial Ruby", "category": "Gems", "platform": "Console"}, "1603007850": {"name": "Ruby 18: Royal Ruby", "category": "Gems", "platform": "Console"}, "1603007851": {"name": "Ruby 19: Flawless Royal Ruby", "category": "Gems", "platform": "Console"}, "2058771886": {"name": "Topaz 01: Chipped Topaz", "category": "Gems", "platform": "Console"}, "2058771887": {"name": "Topaz 02: Flawed Topaz", "category": "Gems", "platform": "Console"}, "2058771888": {"name": "Topaz 03: Topaz", "category": "Gems", "platform": "Console"}, "2058771889": {"name": "Topaz 04: Flawless Topaz", "category": "Gems", "platform": "Console"}, "2058771890": {"name": "Topaz 05: Perfect Topaz", "category": "Gems", "platform": "Console"}, "2058771891": {"name": "Topaz 06: Radiant Topaz", "category": "Gems", "platform": "Console"}, "2058771892": {"name": "Topaz 07: Square Topaz", "category": "Gems", "platform": "Console"}, "2058771893": {"name": "Topaz 08: Flawless Square Topaz", "category": "Gems", "platform": "Console"}, "2058771894": {"name": "Topaz 09: Perfect Square Topaz", "category": "Gems", "platform": "Console"}, "2058771918": {"name": "Topaz 10: Radiant Square Topaz", "category": "Gems", "platform": "Console"}, "2058771919": {"name": "Topaz 11: Star Topaz", "category": "Gems", "platform": "Console"}, "2058771920": {"name": "Topaz 12: Flawless Star Topaz", "category": "Gems", "platform": "Console"}, "2058771921": {"name": "Topaz 13: Perfect Star Topaz", "category": "Gems", "platform": "Console"}, "2058771922": {"name": "Topaz 14: Radiant Star Topaz", "category": "Gems", "platform": "Console"}, "2058771923": {"name": "Topaz 15: Marquise Topaz", "category": "Gems", "platform": "Console"}, "2058771924": {"name": "Topaz 16: Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771925": {"name": "Topaz 17: Flawless Imperial Topaz", "category": "Gems", "platform": "Console"}, "2058771926": {"name": "Topaz 18: Royal Topaz", "category": "Gems", "platform": "Console"}, "2058771927": {"name": "Topaz 19: Flawless Royal Topaz", "category": "Gems", "platform": "Console"}}, "Gloves": {"-1533914303": {"name": "02: Leather Gloves (AR 14-16)", "category": "Gloves", "platform": "Console"}, "-1533914302": {"name": "03: Hide Gloves (AR 28-32)", "category": "Gloves", "platform": "Console"}, "-1533914301": {"name": "04: Chain Gloves (AR 42-55)", "category": "Gloves", "platform": "Console"}, "-1533914300": {"name": "05: Gauntlets (AR 56-69)", "category": "Gloves", "platform": "Console"}, "-1533914299": {"name": "06: Plated Gauntlets (AR 70-88)", "category": "Gloves", "platform": "Console"}, "-1533913215": {"name": "07: Grips (AR 88-106)", "category": "Gloves", "platform": "Console"}, "-1533913214": {"name": "08: Etched Gloves (AR 107-125)", "category": "Gloves", "platform": "Console"}, "-1533913213": {"name": "09: Vambraces (AR 126-144)", "category": "Gloves", "platform": "Console"}, "-1533913212": {"name": "10: Battle Gauntlets (AR 144-173)", "category": "Gloves", "platform": "Console"}, "-1533913211": {"name": "11: Boneweave Gauntlets (AR 175-192)", "category": "Gloves", "platform": "Console"}, "-1533912126": {"name": "12: Balor Fists (AR 192-209)", "category": "Gloves", "platform": "Console"}, "-1533912125": {"name": "13: Manifers (AR 210-221)", "category": "Gloves", "platform": "Console"}, "-1533912124": {"name": "14: Warlord Gauntlets (AR 221-249)", "category": "Gloves", "platform": "Console"}, "-1533912123": {"name": "15: Stranglers (AR 250-278)", "category": "Gloves", "platform": "Console"}, "-1533912122": {"name": "16: Sovereign Vambraces (AR 280-308)", "category": "Gloves", "platform": "Console"}, "-1533912121": {"name": "17: Archon Gauntlets (AR 309-366)", "category": "Gloves", "platform": "Console"}, "-1533912120": {"name": "18: Rakkisgard Gauntlets (AR 367-512)", "category": "Gloves", "platform": "Console"}, "-1533912119": {"name": "19: Ascended Gauntlets (AR 513-590)", "category": "Gloves", "platform": "Console"}, "-542544859": {"name": "Art Test Gloves 1", "category": "Gloves", "platform": "Console"}, "-542544858": {"name": "Art Test Gloves 2", "category": "Gloves", "platform": "Console"}, "-542544857": {"name": "Art Test Gloves 3", "category": "Gloves", "platform": "Console"}, "-542544856": {"name": "Art Test Gloves 4", "category": "Gloves", "platform": "Console"}, "-542544855": {"name": "Art Test Gloves 5", "category": "Gloves", "platform": "Console"}, "-724111115": {"name": "Art_Test_Gloves_10 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-724111114": {"name": "Art_Test_Gloves_11 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544854": {"name": "Art_Test_Gloves_6 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544853": {"name": "Art_Test_Gloves_7 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544852": {"name": "Art_Test_Gloves_8 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-542544851": {"name": "Art_Test_Gloves_9 (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "509897201": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "742334711": {"name": "Legendary: Leoric's Gauntlets (PS3 Promo)", "category": "Gloves", "platform": "Console"}, "614385664": {"name": "Legendary: Alabaster Gloves", "category": "Gloves", "platform": "Console"}, "-935578501": {"name": "Legendary: Conqueror's Gauntlets (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "575250271": {"name": "Legendary: Frostburn", "category": "Gloves", "platform": "Console"}, "1803312459": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1803314903": {"name": "Legendary: Frostburn Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593655": {"name": "Legendary: Frostburn Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576400255": {"name": "Legendary: Gladiator Gauntlets", "category": "Gloves", "platform": "Console"}, "1841261931": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1841264375": {"name": "Legendary: Gladiator Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593687": {"name": "Legendary: Gladiator Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "614421601": {"name": "Legendary: Gloves of Worship", "category": "Gloves", "platform": "Console"}, "204261921": {"name": "Legendary: Grips of Perilous Ascent", "category": "Gloves", "platform": "Console"}, "576508066": {"name": "Legendary: Magefist", "category": "Gloves", "platform": "Console"}, "1844819694": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "1844822138": {"name": "Legendary: Magefist (Legacy)", "category": "Gloves", "platform": "Console"}, "880593690": {"name": "Legendary: Magefist (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1802126538": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "1802128982": {"name": "Legendary: Pendergrasps (Legacy)", "category": "Gloves", "platform": "Console"}, "880593654": {"name": "Legendary: Pendergrasps (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575214334": {"name": "Legendary: Penders Purchase", "category": "Gloves", "platform": "Console"}, "614349727": {"name": "Legendary: St. Archew's Gage", "category": "Gloves", "platform": "Console"}, "575429956": {"name": "Legendary: Stone Gauntlets", "category": "Gloves", "platform": "Console"}, "1809242064": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "1809244508": {"name": "Legendary: Stone Gauntlets (Legacy)", "category": "Gloves", "platform": "Console"}, "880593660": {"name": "Legendary: Stone Gauntlets (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575286208": {"name": "Legendary: Tasker and Theo", "category": "Gloves", "platform": "Console"}, "1804498380": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "1804500824": {"name": "Legendary: Tasker and Theo (Legacy)", "category": "Gloves", "platform": "Console"}, "880593656": {"name": "Legendary: Tasker and Theo (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "880593662": {"name": "Set: Asheara's Clasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "1811613906": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "1811616350": {"name": "Set: Asheara's Iron Fist (Legacy)", "category": "Gloves", "platform": "Console"}, "575501830": {"name": "Set: Asheara's Ward", "category": "Gloves", "platform": "Console"}, "1846005615": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "1846008059": {"name": "Set: Cain's Scribe (Legacy)", "category": "Gloves", "platform": "Console"}, "576544003": {"name": "Set: Cain's Scrivener", "category": "Gloves", "platform": "Console"}, "880593691": {"name": "Set: Cain's Warmers (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "2058321365": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058321364": {"name": "Set: Fiendish Grips (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058285427": {"name": "Set: Fierce Gauntlets (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058429438": {"name": "Set: Firebird's Talons", "category": "Gloves", "platform": "Console"}, "2058501312": {"name": "Set: Fists of Thunder", "category": "Gloves", "platform": "Console"}, "2058249490": {"name": "Set: Gauntlet of the Wastes (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059399737": {"name": "Set: Gauntlets of Akkhan", "category": "Gloves", "platform": "Console"}, "2059615359": {"name": "Set: Helltooth Gauntlets", "category": "Gloves", "platform": "Console"}, "880593661": {"name": "Set: Immortal King's Forge (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "575465893": {"name": "Set: Immortal King's Irons", "category": "Gloves", "platform": "Console"}, "1810427985": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "1810430429": {"name": "Set: Immortal King's Irons (Legacy)", "category": "Gloves", "platform": "Console"}, "-206156950": {"name": "Set: Inna's Hold (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2058537249": {"name": "Set: Jade Harvester's Mercy", "category": "Gloves", "platform": "Console"}, "2058465375": {"name": "Set: Marauder's Gloves", "category": "Gloves", "platform": "Console"}, "2058249491": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156953": {"name": "Set: Natalya's Touch (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059471611": {"name": "Set: Pride of the Invoker", "category": "Gloves", "platform": "Console"}, "2059579422": {"name": "Set: Pull of the Earth", "category": "Gloves", "platform": "Console"}, "2058393501": {"name": "Set: Raekor's Wraps", "category": "Gloves", "platform": "Console"}, "2058249489": {"name": "Set: Roland's Grasp (Patch 2.1.0)", "category": "Gloves", "platform": "Console"}, "1848377457": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "1848379901": {"name": "Set: Sage's Gesture (Legacy)", "category": "Gloves", "platform": "Console"}, "880593693": {"name": "Set: Sage's Grasp (Old-Legacy)", "category": "Gloves", "platform": "Console"}, "576615877": {"name": "Set: Sage's Purchase", "category": "Gloves", "platform": "Console"}, "2059435674": {"name": "Set: Sunwuko's Paws", "category": "Gloves", "platform": "Console"}, "-206156952": {"name": "Set: Tal Rasha's Grasp (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "2059543485": {"name": "Set: The Shadow's Grasp", "category": "Gloves", "platform": "Console"}, "2059507548": {"name": "Set: Vyr's Grasping Gauntlets", "category": "Gloves", "platform": "Console"}, "2058285428": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "-206156951": {"name": "Set: Zunimassa's Finger Wraps (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}, "614349464": {"name": "legendary: St. Archew's Gage (Patch 2.2.0)", "category": "Gloves", "platform": "Console"}}, "Hand Crossbows": {"-363391669": {"name": "01: Simple Hand Crossbow (DPS 12.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363391668": {"name": "02: Light Hand Crossbow (DPS 11.2-13.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363391667": {"name": "03: Stake Thrower (DPS 12.8-15.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391666": {"name": "04: Hand Crossbow (DPS 16.0-18.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391665": {"name": "05: Slinglock (DPS 20.8-23.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363391664": {"name": "06: Quillshot (DPS 24.0-26.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391663": {"name": "07: Nail Spitter (DPS 28.0-30.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363391662": {"name": "08: Heavy Stake Thrower (DPS 32.8-35.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390580": {"name": "09: Sling Pistol (DPS 38.4-40.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363390579": {"name": "10: Crosslock (DPS 44.0-46.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390578": {"name": "11: Siege Lock (DPS 48.8-51.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390577": {"name": "12: Arcus (DPS 60.0-62.4)", "category": "Hand Crossbows", "platform": "Console"}, "-363390576": {"name": "13: Cranequin (DPS 65.6-68.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390575": {"name": "14: Spine Thrower (DPS 76.8-79.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363390574": {"name": "15: Heavy Arcus (DPS 85.6-88.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363390573": {"name": "16: Bolt Rack (DPS 98.4-100.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389491": {"name": "17: Runic Sling Pistol (DPS 113.6-116.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389490": {"name": "18: Splinter Shot (DPS 127.2-129.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389489": {"name": "19: Windlash (DPS 139.2-141.6)", "category": "Hand Crossbows", "platform": "Console"}, "-363389488": {"name": "20: Blade Spitter (DPS 154.4-156.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389487": {"name": "21: Heavy Cranequin (DPS 170.4-172.8)", "category": "Hand Crossbows", "platform": "Console"}, "-363389486": {"name": "22: Runic Arcus (DPS 196.8-199.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363389485": {"name": "23: Impellor (DPS 225.6-228.0)", "category": "Hand Crossbows", "platform": "Console"}, "-363389484": {"name": "24: Exorcist (DPS 258.4-263.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388402": {"name": "25: Lionblade Bow (DPS 516.8-519.2)", "category": "Hand Crossbows", "platform": "Console"}, "-363388401": {"name": "26: Penetrator (DPS 672.0-674.4)", "category": "Hand Crossbows", "platform": "Console"}, "1203045553": {"name": "Art Test Hand Crossbow 2", "category": "Hand Crossbows", "platform": "Console"}, "1203045554": {"name": "Art Test Hand Crossbow 3", "category": "Hand Crossbows", "platform": "Console"}, "1203045555": {"name": "Art Test Hand Crossbow 4", "category": "Hand Crossbows", "platform": "Console"}, "1203045556": {"name": "Art Test Hand Crossbow 5", "category": "Hand Crossbows", "platform": "Console"}, "1203045552": {"name": "Art Test HandCrossbow 1", "category": "Hand Crossbows", "platform": "Console"}, "-1153493044": {"name": "Legendary: Balefire Caster", "category": "Hand Crossbows", "platform": "Console"}, "589357912": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "589360356": {"name": "Legendary: Balefire Caster (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789444": {"name": "Legendary: Balefire Caster (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153493308": {"name": "Legendary: Balefire Caster (Patch 2.1.0)", "category": "Hand Crossbows", "platform": "Console"}, "-1153421170": {"name": "Legendary: Blitzbolter", "category": "Hand Crossbows", "platform": "Console"}, "-1152378997": {"name": "Legendary: Calamity", "category": "Hand Crossbows", "platform": "Console"}, "626121463": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "626123907": {"name": "Legendary: Calamity (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789475": {"name": "Legendary: Calamity (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153385233": {"name": "Legendary: Dawn", "category": "Hand Crossbows", "platform": "Console"}, "592915675": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "592918119": {"name": "Legendary: Dawn (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789447": {"name": "Legendary: Dawn (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591729754": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "591732198": {"name": "Legendary: Deadeye (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789446": {"name": "Legendary: Deadeye (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114429525": {"name": "Legendary: Helltrapper", "category": "Hand Crossbows", "platform": "Console"}, "-1153457107": {"name": "Legendary: Izzuccob", "category": "Hand Crossbows", "platform": "Console"}, "590543833": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "590546277": {"name": "Legendary: Izzuccob (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789445": {"name": "Legendary: Izzuccob (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1114465462": {"name": "Legendary: K'mar Tenclip", "category": "Hand Crossbows", "platform": "Console"}, "-44923323": {"name": "Legendary: Quietus", "category": "Hand Crossbows", "platform": "Console"}, "-1266666515": {"name": "P2 Hand Crossbow norm Legendary 01", "category": "Hand Crossbows", "platform": "Console"}, "-1266666514": {"name": "P2 Hand Crossbow norm Legendary 02", "category": "Hand Crossbows", "platform": "Console"}, "-1266666513": {"name": "P2 Hand Crossbow norm Legendary 03", "category": "Hand Crossbows", "platform": "Console"}, "515789442": {"name": "Set: Danetta's Fury (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789441": {"name": "Set: Danetta's Rage (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153564918": {"name": "Set: Danetta's Revenge", "category": "Hand Crossbows", "platform": "Console"}, "586986070": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "586988514": {"name": "Set: Danetta's Revenge (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153600855": {"name": "Set: Danetta's Spite", "category": "Hand Crossbows", "platform": "Console"}, "585800149": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "585802593": {"name": "Set: Danetta's Spite (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789479": {"name": "Set: Hallowed Avenger (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1152235249": {"name": "Set: Hallowed Condemnation", "category": "Hand Crossbows", "platform": "Console"}, "630865147": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "630867591": {"name": "Set: Hallowed Judgment (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "515789443": {"name": "Set: Natalya's Redemption (Old-Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "-1153528981": {"name": "Set: Natalya's Slayer", "category": "Hand Crossbows", "platform": "Console"}, "588171991": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}, "588174435": {"name": "Set: Natalya's Slayer (Legacy)", "category": "Hand Crossbows", "platform": "Console"}}, "Helms": {"1565454584": {"name": "03: Coif (AR 36-41)", "category": "Helms", "platform": "Console"}, "1565454585": {"name": "04: Arming Cap (AR 54-71)", "category": "Helms", "platform": "Console"}, "1565454586": {"name": "05: Helmet (AR 72-89)", "category": "Helms", "platform": "Console"}, "1565454587": {"name": "06: Plated Helm (AR 90-113)", "category": "Helms", "platform": "Console"}, "1565455671": {"name": "07: Crown (AR 114-137)", "category": "Helms", "platform": "Console"}, "1565455672": {"name": "08: Basinet (AR 138-161)", "category": "Helms", "platform": "Console"}, "1565455673": {"name": "09: Klappvisier (AR 162-185)", "category": "Helms", "platform": "Console"}, "1565455674": {"name": "10: Casque (AR 186-224)", "category": "Helms", "platform": "Console"}, "1565455675": {"name": "11: Great Helm (AR 225-247)", "category": "Helms", "platform": "Console"}, "1565456760": {"name": "12: Hounskull (AR 247-269)", "category": "Helms", "platform": "Console"}, "1565456761": {"name": "13: Stechhelm (AR 270-284)", "category": "Helms", "platform": "Console"}, "1565456762": {"name": "14: Zischagge (AR 285-322)", "category": "Helms", "platform": "Console"}, "1565456763": {"name": "15: Hellscape Mask (AR 322-359)", "category": "Helms", "platform": "Console"}, "1565456764": {"name": "16: Sovereign Helm (AR 360-397)", "category": "Helms", "platform": "Console"}, "1565456765": {"name": "17: Archon Crown (AR 397-471)", "category": "Helms", "platform": "Console"}, "1565456766": {"name": "18: Rakkisgard Helm (AR 472-659)", "category": "Helms", "platform": "Console"}, "1565456767": {"name": "19: Ascended Crown (AR 660-759)", "category": "Helms", "platform": "Console"}, "1422434075": {"name": "Art Test Helm 1", "category": "Helms", "platform": "Console"}, "1422434076": {"name": "Art Test Helm 2", "category": "Helms", "platform": "Console"}, "1422434077": {"name": "Art Test Helm 3", "category": "Helms", "platform": "Console"}, "1422434078": {"name": "Art Test Helm 4", "category": "Helms", "platform": "Console"}, "1422434079": {"name": "Art Test Helm 5", "category": "Helms", "platform": "Console"}, "-304315733": {"name": "Art_Test_Helm_10 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315732": {"name": "Art_Test_Helm_11 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-304315731": {"name": "Art_Test_Helm_12 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434080": {"name": "Art_Test_Helm_6 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434081": {"name": "Art_Test_Helm_7 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434082": {"name": "Art_Test_Helm_8 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1422434083": {"name": "Art_Test_Helm_9 (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233654": {"name": "Legendary: Andariel's Visage", "category": "Helms", "platform": "Console"}, "-1855268606": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "-1855266162": {"name": "Legendary: Andariel's Visage (Legacy)", "category": "Helms", "platform": "Console"}, "1638662958": {"name": "Legendary: Andariel's Visage (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334377402": {"name": "Legendary: Blind Faith", "category": "Helms", "platform": "Console"}, "-1850524922": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "-1850522478": {"name": "Legendary: Blind Faith (Legacy)", "category": "Helms", "platform": "Console"}, "1638662962": {"name": "Legendary: Blind Faith (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334161780": {"name": "Legendary: Broken Crown", "category": "Helms", "platform": "Console"}, "-1857640448": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1857638004": {"name": "Legendary: Broken Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662956": {"name": "Legendary: Broken Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1046338483": {"name": "Legendary: Broken Crown (Patch 2.1.2)", "category": "Helms", "platform": "Console"}, "1239902833": {"name": "Legendary: Conqueror's Shako (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "974143057": {"name": "Legendary: Death Mask", "category": "Helms", "platform": "Console"}, "373333110": {"name": "Legendary: Deathseer's Cowl", "category": "Helms", "platform": "Console"}, "-1854082685": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "-1854080241": {"name": "Legendary: Giant Skull (Legacy)", "category": "Helms", "platform": "Console"}, "1638662959": {"name": "Legendary: Giant Skull (Old-Legacy)", "category": "Helms", "platform": "Console"}, "1571690839": {"name": "Legendary: Guardian Facade", "category": "Helms", "platform": "Console"}, "974107120": {"name": "Legendary: Hallowed Helm", "category": "Helms", "platform": "Console"}, "-843818268": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "-1425221075": {"name": "Legendary: Infernal Helm", "category": "Helms", "platform": "Console"}, "334197717": {"name": "Legendary: Leoric's Crown", "category": "Helms", "platform": "Console"}, "-1856454527": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "-1856452083": {"name": "Legendary: Leoric's Crown (Legacy)", "category": "Helms", "platform": "Console"}, "1638662957": {"name": "Legendary: Leoric's Crown (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334197453": {"name": "Legendary: Leoric's Crown (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "334341465": {"name": "Legendary: Mempo of Twilight", "category": "Helms", "platform": "Console"}, "-1851710843": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "-1851708399": {"name": "Legendary: Mempo of Twilight (Legacy)", "category": "Helms", "platform": "Console"}, "1638662961": {"name": "Legendary: Mempo of Twilight (Old-Legacy)", "category": "Helms", "platform": "Console"}, "373369047": {"name": "Legendary: Pride's Fall", "category": "Helms", "platform": "Console"}, "334269591": {"name": "Legendary: Skull of Resonance", "category": "Helms", "platform": "Console"}, "-1818505055": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "-1818502611": {"name": "Legendary: The Helm of Command (Legacy)", "category": "Helms", "platform": "Console"}, "1638662989": {"name": "Legendary: The Helm of Command (Old-Legacy)", "category": "Helms", "platform": "Console"}, "335347701": {"name": "Legendary: The Helm of Rule", "category": "Helms", "platform": "Console"}, "-1993242998": {"name": "Set: Accursed Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662992": {"name": "Set: Aughild's Brow (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1814947292": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "-1814944848": {"name": "Set: Aughild's Peak (Legacy)", "category": "Helms", "platform": "Console"}, "335455512": {"name": "Set: Aughild's Spike", "category": "Helms", "platform": "Console"}, "335383638": {"name": "Set: Cain's Insight", "category": "Helms", "platform": "Console"}, "1638662990": {"name": "Set: Cain's Laurel (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1817319134": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1817316690": {"name": "Set: Cain's Memory (Legacy)", "category": "Helms", "platform": "Console"}, "-1992092751": {"name": "Set: Crown of the Invoker", "category": "Helms", "platform": "Console"}, "-1993242997": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1991984940": {"name": "Set: Eyes of the Earth", "category": "Helms", "platform": "Console"}, "-1993134924": {"name": "Set: Firebird's Plume", "category": "Helms", "platform": "Console"}, "-1813761371": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "-1813758927": {"name": "Set: Guardian's Foresight (Legacy)", "category": "Helms", "platform": "Console"}, "335491449": {"name": "Set: Guardian's Gaze", "category": "Helms", "platform": "Console"}, "1638662993": {"name": "Set: Guardian's Watch (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1992164625": {"name": "Set: Helm of Akkhan", "category": "Helms", "platform": "Console"}, "-1993314872": {"name": "Set: Helm of the Wastes (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334413339": {"name": "Set: Immortal King's Triumph", "category": "Helms", "platform": "Console"}, "-1849339001": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "-1849336557": {"name": "Set: Immortal King's Triumph (Legacy)", "category": "Helms", "platform": "Console"}, "1638662963": {"name": "Set: Immortal King's Will (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993027113": {"name": "Set: Jade Harvester's Wisdom", "category": "Helms", "platform": "Console"}, "-1993098987": {"name": "Set: Marauder's Visage", "category": "Helms", "platform": "Console"}, "-1991949003": {"name": "Set: Mask of Jeram", "category": "Helms", "platform": "Console"}, "-1993063050": {"name": "Set: Mask of the Searing Sky", "category": "Helms", "platform": "Console"}, "-1993314871": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "1638662964": {"name": "Set: Natalya's Gaze (Old-Legacy)", "category": "Helms", "platform": "Console"}, "334449276": {"name": "Set: Natalya's Sight", "category": "Helms", "platform": "Console"}, "-1848153080": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1848150636": {"name": "Set: Natalya's Sight (Legacy)", "category": "Helms", "platform": "Console"}, "-1993170861": {"name": "Set: Raekor's Will", "category": "Helms", "platform": "Console"}, "-1993314873": {"name": "Set: Roland's Visage (Patch 2.1.0)", "category": "Helms", "platform": "Console"}, "335527386": {"name": "Set: Sage's Apogee", "category": "Helms", "platform": "Console"}, "-1812575450": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "-1812573006": {"name": "Set: Sage's Orbit (Legacy)", "category": "Helms", "platform": "Console"}, "1638662994": {"name": "Set: Sage's Stones (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278935": {"name": "Set: Shrouded Mask (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-1992128688": {"name": "Set: Sunwuko's Crown", "category": "Helms", "platform": "Console"}, "335311764": {"name": "Set: Tal Rasha's Guise of Wisdom", "category": "Helms", "platform": "Console"}, "-1819690976": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "-1819688532": {"name": "Set: Tal Rasha's Guise of Wisdom (Legacy)", "category": "Helms", "platform": "Console"}, "1638662988": {"name": "Set: Tal Rasha's Horadric Crest (Old-Legacy)", "category": "Helms", "platform": "Console"}, "-1993278934": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "334233391": {"name": "legendary: Andariel's Visage (Patch 2.2.0)", "category": "Helms", "platform": "Console"}, "-36755477": {"name": "legendary: Helm of the Hierarch (Patch 2.2.0)", "category": "Helms", "platform": "Console"}}, "Horadric Cache": {"739397179": {"name": "Act 1, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1369696819": {"name": "Act 1, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1369696818": {"name": "Act 1, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1369696817": {"name": "Act 1, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1369696816": {"name": "Act 1, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1369696815": {"name": "Act 1, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654861": {"name": "Act 2", "category": "Horadric Cache", "platform": "Console"}, "408167196": {"name": "Act 2, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "584615630": {"name": "Act 2, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "584615631": {"name": "Act 2, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "584615632": {"name": "Act 2, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "584615633": {"name": "Act 2, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "584615634": {"name": "Act 2, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654860": {"name": "Act 3", "category": "Horadric Cache", "platform": "Console"}, "76937213": {"name": "Act 3, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-1756039217": {"name": "Act 3, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-1756039216": {"name": "Act 3, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-1756039215": {"name": "Act 3, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-1756039214": {"name": "Act 3, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-1756039213": {"name": "Act 3, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654859": {"name": "Act 4", "category": "Horadric Cache", "platform": "Console"}, "-254292770": {"name": "Act 4, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "198273232": {"name": "Act 4, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "198273233": {"name": "Act 4, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "198273234": {"name": "Act 4, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "198273235": {"name": "Act 4, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "198273236": {"name": "Act 4, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "-1575654858": {"name": "Act 5", "category": "Horadric Cache", "platform": "Console"}, "-585522753": {"name": "Act 5, Torment 1", "category": "Horadric Cache", "platform": "Console"}, "-2142381615": {"name": "Act 5, Torment 2", "category": "Horadric Cache", "platform": "Console"}, "-2142381614": {"name": "Act 5, Torment 3", "category": "Horadric Cache", "platform": "Console"}, "-2142381613": {"name": "Act 5, Torment 4", "category": "Horadric Cache", "platform": "Console"}, "-2142381612": {"name": "Act 5, Torment 5", "category": "Horadric Cache", "platform": "Console"}, "-2142381611": {"name": "Act 5, Torment 6", "category": "Horadric Cache", "platform": "Console"}, "1574352095": {"name": "Bonus Act", "category": "Horadric Cache", "platform": "Console"}, "1749838250": {"name": "Greater Horadric Cache", "category": "Horadric Cache", "platform": "Console"}, "1802516147": {"name": "Greater Horadric Cache Torment", "category": "Horadric Cache", "platform": "Console"}, "-1262930872": {"name": "Horadric Cache Bonus Act Torment", "category": "Horadric Cache", "platform": "Console"}}, "Junk": {"-326449293": {"name": "Arcane Globe", "category": "Junk", "platform": "Console"}, "393991529": {"name": "Art_Test_Pennant_1 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991530": {"name": "Art_Test_Pennant_2 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991531": {"name": "Art_Test_Pennant_3 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991532": {"name": "Art_Test_Pennant_4 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991533": {"name": "Art_Test_Pennant_5 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991534": {"name": "Art_Test_Pennant_6 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991535": {"name": "Art_Test_Pennant_7 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "393991536": {"name": "Art_Test_Pennant_8 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-215839115": {"name": "Blizzcon Artifact", "category": "Junk", "platform": "Console"}, "-1812121245": {"name": "Cauldron of Jordan", "category": "Junk", "platform": "Console"}, "-125073416": {"name": "Charm", "category": "Junk", "platform": "Console"}, "-125073414": {"name": "Crafter Skillup Page", "category": "Junk", "platform": "Console"}, "-1739891535": {"name": "CupCake05", "category": "Junk", "platform": "Console"}, "-1581845891": {"name": "CupCake10", "category": "Junk", "platform": "Console"}, "-1581845886": {"name": "CupCake15", "category": "Junk", "platform": "Console"}, "-1581845858": {"name": "CupCake20", "category": "Junk", "platform": "Console"}, "-1581845853": {"name": "CupCake25", "category": "Junk", "platform": "Console"}, "-1581845825": {"name": "CupCake30", "category": "Junk", "platform": "Console"}, "-1581845820": {"name": "CupCake35", "category": "Junk", "platform": "Console"}, "-1581845792": {"name": "CupCake40", "category": "Junk", "platform": "Console"}, "1402040296": {"name": "Damaged Chestpiece", "category": "Junk", "platform": "Console"}, "-904648741": {"name": "Debug Transmog Plan", "category": "Junk", "platform": "Console"}, "-808688257": {"name": "Event MapVendor Egg", "category": "Junk", "platform": "Console"}, "-2126877461": {"name": "Example Book", "category": "Junk", "platform": "Console"}, "126259831": {"name": "Gold1", "category": "Junk", "platform": "Console"}, "126259832": {"name": "Gold2", "category": "Junk", "platform": "Console"}, "126259833": {"name": "Gold3", "category": "Junk", "platform": "Console"}, "126259834": {"name": "Gold4", "category": "Junk", "platform": "Console"}, "126259835": {"name": "Gold5", "category": "Junk", "platform": "Console"}, "-1165367015": {"name": "Greater Health Potion", "category": "Junk", "platform": "Console"}, "-1916071921": {"name": "Health Potion", "category": "Junk", "platform": "Console"}, "2022931376": {"name": "HealthGlobe01", "category": "Junk", "platform": "Console"}, "2022931377": {"name": "HealthGlobe02", "category": "Junk", "platform": "Console"}, "2022931378": {"name": "HealthGlobe03", "category": "Junk", "platform": "Console"}, "2022931379": {"name": "HealthGlobe04", "category": "Junk", "platform": "Console"}, "2022931380": {"name": "HealthGlobe05", "category": "Junk", "platform": "Console"}, "2022931381": {"name": "HealthGlobe06", "category": "Junk", "platform": "Console"}, "2022931382": {"name": "HealthGlobe07", "category": "Junk", "platform": "Console"}, "2022931383": {"name": "HealthGlobe08", "category": "Junk", "platform": "Console"}, "2022931384": {"name": "HealthGlobe09", "category": "Junk", "platform": "Console"}, "-1962741280": {"name": "HealthGlobe10", "category": "Junk", "platform": "Console"}, "-345952752": {"name": "HealthGlobe100", "category": "Junk", "platform": "Console"}, "-1962741275": {"name": "HealthGlobe15", "category": "Junk", "platform": "Console"}, "-1962741247": {"name": "HealthGlobe20", "category": "Junk", "platform": "Console"}, "-1962741242": {"name": "HealthGlobe25", "category": "Junk", "platform": "Console"}, "-1962741214": {"name": "HealthGlobe30", "category": "Junk", "platform": "Console"}, "-1962741209": {"name": "HealthGlobe35", "category": "Junk", "platform": "Console"}, "-1962741181": {"name": "HealthGlobe40", "category": "Junk", "platform": "Console"}, "-1962741176": {"name": "HealthGlobe45", "category": "Junk", "platform": "Console"}, "-1962741148": {"name": "HealthGlobe50", "category": "Junk", "platform": "Console"}, "-1962741143": {"name": "HealthGlobe55", "category": "Junk", "platform": "Console"}, "-1962741115": {"name": "HealthGlobe60", "category": "Junk", "platform": "Console"}, "-1962741110": {"name": "HealthGlobe65", "category": "Junk", "platform": "Console"}, "-1962741082": {"name": "HealthGlobe70", "category": "Junk", "platform": "Console"}, "-1962741077": {"name": "HealthGlobe75", "category": "Junk", "platform": "Console"}, "-1962741049": {"name": "HealthGlobe80", "category": "Junk", "platform": "Console"}, "-1962741044": {"name": "HealthGlobe85", "category": "Junk", "platform": "Console"}, "-1962741016": {"name": "HealthGlobe90", "category": "Junk", "platform": "Console"}, "-1962741011": {"name": "HealthGlobe95", "category": "Junk", "platform": "Console"}, "-1703070487": {"name": "Heroic Health Potion", "category": "Junk", "platform": "Console"}, "-125073411": {"name": "Junkorama", "category": "Junk", "platform": "Console"}, "-1546488739": {"name": "Lesser Health Potion", "category": "Junk", "platform": "Console"}, "1646125768": {"name": "Major Health Potion", "category": "Junk", "platform": "Console"}, "1646417620": {"name": "Minor Health Potion", "category": "Junk", "platform": "Console"}, "522407589": {"name": "Monk Staff Pvp 001", "category": "Junk", "platform": "Console"}, "522407590": {"name": "Monk Staff Pvp 002", "category": "Junk", "platform": "Console"}, "522407591": {"name": "Monk Staff Pvp 003", "category": "Junk", "platform": "Console"}, "-1483610851": {"name": "Mythic Health Potion", "category": "Junk", "platform": "Console"}, "-125073413": {"name": "OH NOES! JUNK!", "category": "Junk", "platform": "Console"}, "-1596706792": {"name": "Orn Bag 01", "category": "Junk", "platform": "Console"}, "885847747": {"name": "Orn BlizzconPrize", "category": "Junk", "platform": "Console"}, "-125073415": {"name": "Page of Fate", "category": "Junk", "platform": "Console"}, "197999857": {"name": "Page of Useless Scribbling", "category": "Junk", "platform": "Console"}, "1249260787": {"name": "PageOfFateA", "category": "Junk", "platform": "Console"}, "-910124122": {"name": "Power Potion", "category": "Junk", "platform": "Console"}, "1921622363": {"name": "Power-Up Attack Speed", "category": "Junk", "platform": "Console"}, "-859355014": {"name": "Power-Up Cooldown Reset", "category": "Junk", "platform": "Console"}, "11858385": {"name": "Power-Up Damage", "category": "Junk", "platform": "Console"}, "455273651": {"name": "Power-Up Invulnerability", "category": "Junk", "platform": "Console"}, "-977399097": {"name": "Power-Up Stealth", "category": "Junk", "platform": "Console"}, "-1504368109": {"name": "Resplendent Health Potion", "category": "Junk", "platform": "Console"}, "1652778256": {"name": "Runic Health Potion", "category": "Junk", "platform": "Console"}, "-1277860767": {"name": "Sacred Health Potion", "category": "Junk", "platform": "Console"}, "704159709": {"name": "Scholarly Writings", "category": "Junk", "platform": "Console"}, "197999858": {"name": "ScrapPaper 02", "category": "Junk", "platform": "Console"}, "197999859": {"name": "ScrapPaper 03", "category": "Junk", "platform": "Console"}, "197999860": {"name": "ScrapPaper 04", "category": "Junk", "platform": "Console"}, "1462277166": {"name": "Scroll", "category": "Junk", "platform": "Console"}, "146554345": {"name": "Set 001 GiyuasFang", "category": "Junk", "platform": "Console"}, "1653966238": {"name": "Super Health Potion", "category": "Junk", "platform": "Console"}, "1626390053": {"name": "Talisman", "category": "Junk", "platform": "Console"}, "761573026": {"name": "The Black Rock Ledger, Page 15", "category": "Junk", "platform": "Console"}, "761573027": {"name": "The Black Rock Ledger, Page 16", "category": "Junk", "platform": "Console"}, "761573028": {"name": "The Black Rock Ledger, Page 23", "category": "Junk", "platform": "Console"}, "761573024": {"name": "The Black Rock Ledger, Page 4", "category": "Junk", "platform": "Console"}, "761573029": {"name": "The Black Rock Ledger, Page 42", "category": "Junk", "platform": "Console"}, "761573025": {"name": "The Black Rock Ledger, Page 8", "category": "Junk", "platform": "Console"}, "-2007738575": {"name": "Town Portal Stone 2", "category": "Junk", "platform": "Console"}, "-125073412": {"name": "Trunk Junk", "category": "Junk", "platform": "Console"}, "177825848": {"name": "cos_pennant_01 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825849": {"name": "cos_pennant_02 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825850": {"name": "cos_pennant_03 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825851": {"name": "cos_pennant_04 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "177825852": {"name": "cos_pennant_05 (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "-1562301750": {"name": "cos_pennant_p2_Anniversary (Patch 2.2.0)", "category": "Junk", "platform": "Console"}, "127020830": {"name": "cos_pennant_p2_Heroes (Patch 2.2.0)", "category": "Junk", "platform": "Console"}}, "Keys": {"-1088058180": {"name": "Key of Destruction", "category": "Keys", "platform": "Console"}, "113551449": {"name": "Key of Evil", "category": "Keys", "platform": "Console"}, "-1207737543": {"name": "Key of Gluttony", "category": "Keys", "platform": "Console"}, "1064300938": {"name": "Key of Hate", "category": "Keys", "platform": "Console"}, "-143133978": {"name": "Key of Terror", "category": "Keys", "platform": "Console"}, "2050794135": {"name": "Key of War", "category": "Keys", "platform": "Console"}}, "Keystones": {"1955086538": {"name": "Greater Rift Keystone Rank 02 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086539": {"name": "Greater Rift Keystone Rank 03 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086540": {"name": "Greater Rift Keystone Rank 04 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086541": {"name": "Greater Rift Keystone Rank 05 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086542": {"name": "Greater Rift Keystone Rank 06 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086543": {"name": "Greater Rift Keystone Rank 07 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086544": {"name": "Greater Rift Keystone Rank 08 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086545": {"name": "Greater Rift Keystone Rank 09 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346329": {"name": "Greater Rift Keystone Rank 10 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1214538391": {"name": "Greater Rift Keystone Rank 100 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346330": {"name": "Greater Rift Keystone Rank 11 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346331": {"name": "Greater Rift Keystone Rank 12 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346332": {"name": "Greater Rift Keystone Rank 13 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346333": {"name": "Greater Rift Keystone Rank 14 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346334": {"name": "Greater Rift Keystone Rank 15 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346335": {"name": "Greater Rift Keystone Rank 16 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346336": {"name": "Greater Rift Keystone Rank 17 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346337": {"name": "Greater Rift Keystone Rank 18 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346338": {"name": "Greater Rift Keystone Rank 19 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346362": {"name": "Greater Rift Keystone Rank 20 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346363": {"name": "Greater Rift Keystone Rank 21 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346364": {"name": "Greater Rift Keystone Rank 22 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346365": {"name": "Greater Rift Keystone Rank 23 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346366": {"name": "Greater Rift Keystone Rank 24 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346367": {"name": "Greater Rift Keystone Rank 25 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346368": {"name": "Greater Rift Keystone Rank 26 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346369": {"name": "Greater Rift Keystone Rank 27 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346370": {"name": "Greater Rift Keystone Rank 28 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346371": {"name": "Greater Rift Keystone Rank 29 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346395": {"name": "Greater Rift Keystone Rank 30 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346396": {"name": "Greater Rift Keystone Rank 31 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346397": {"name": "Greater Rift Keystone Rank 32 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346398": {"name": "Greater Rift Keystone Rank 33 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346399": {"name": "Greater Rift Keystone Rank 34 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346400": {"name": "Greater Rift Keystone Rank 35 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346401": {"name": "Greater Rift Keystone Rank 36 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346402": {"name": "Greater Rift Keystone Rank 37 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346403": {"name": "Greater Rift Keystone Rank 38 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346404": {"name": "Greater Rift Keystone Rank 39 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346428": {"name": "Greater Rift Keystone Rank 40 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346429": {"name": "Greater Rift Keystone Rank 41 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346430": {"name": "Greater Rift Keystone Rank 42 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346431": {"name": "Greater Rift Keystone Rank 43 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346432": {"name": "Greater Rift Keystone Rank 44 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346433": {"name": "Greater Rift Keystone Rank 45 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346434": {"name": "Greater Rift Keystone Rank 46 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346435": {"name": "Greater Rift Keystone Rank 47 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346436": {"name": "Greater Rift Keystone Rank 48 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346437": {"name": "Greater Rift Keystone Rank 49 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346461": {"name": "Greater Rift Keystone Rank 50 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346462": {"name": "Greater Rift Keystone Rank 51 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346463": {"name": "Greater Rift Keystone Rank 52 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346464": {"name": "Greater Rift Keystone Rank 53 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346465": {"name": "Greater Rift Keystone Rank 54 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346466": {"name": "Greater Rift Keystone Rank 55 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346467": {"name": "Greater Rift Keystone Rank 56 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346468": {"name": "Greater Rift Keystone Rank 57 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346469": {"name": "Greater Rift Keystone Rank 58 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346470": {"name": "Greater Rift Keystone Rank 59 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346494": {"name": "Greater Rift Keystone Rank 60 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346495": {"name": "Greater Rift Keystone Rank 61 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346496": {"name": "Greater Rift Keystone Rank 62 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346497": {"name": "Greater Rift Keystone Rank 63 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346498": {"name": "Greater Rift Keystone Rank 64 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346499": {"name": "Greater Rift Keystone Rank 65 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346500": {"name": "Greater Rift Keystone Rank 66 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346501": {"name": "Greater Rift Keystone Rank 67 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346502": {"name": "Greater Rift Keystone Rank 68 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346503": {"name": "Greater Rift Keystone Rank 69 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346527": {"name": "Greater Rift Keystone Rank 70 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346528": {"name": "Greater Rift Keystone Rank 71 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346529": {"name": "Greater Rift Keystone Rank 72 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346530": {"name": "Greater Rift Keystone Rank 73 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346531": {"name": "Greater Rift Keystone Rank 74 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346532": {"name": "Greater Rift Keystone Rank 75 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346533": {"name": "Greater Rift Keystone Rank 76 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346534": {"name": "Greater Rift Keystone Rank 77 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346535": {"name": "Greater Rift Keystone Rank 78 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346536": {"name": "Greater Rift Keystone Rank 79 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346560": {"name": "Greater Rift Keystone Rank 80 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346561": {"name": "Greater Rift Keystone Rank 81 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346562": {"name": "Greater Rift Keystone Rank 82 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346563": {"name": "Greater Rift Keystone Rank 83 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346564": {"name": "Greater Rift Keystone Rank 84 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346565": {"name": "Greater Rift Keystone Rank 85 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346566": {"name": "Greater Rift Keystone Rank 86 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346567": {"name": "Greater Rift Keystone Rank 87 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346568": {"name": "Greater Rift Keystone Rank 88 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346569": {"name": "Greater Rift Keystone Rank 89 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346593": {"name": "Greater Rift Keystone Rank 90 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346594": {"name": "Greater Rift Keystone Rank 91 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346595": {"name": "Greater Rift Keystone Rank 92 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346596": {"name": "Greater Rift Keystone Rank 93 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346597": {"name": "Greater Rift Keystone Rank 94 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346598": {"name": "Greater Rift Keystone Rank 95 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346599": {"name": "Greater Rift Keystone Rank 96 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346600": {"name": "Greater Rift Keystone Rank 97 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346601": {"name": "Greater Rift Keystone Rank 98 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "93346602": {"name": "Greater Rift Keystone Rank 99 (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "1955086536": {"name": "Keystone of Trials (Patch 2.1.0)", "category": "Keystones", "platform": "Console"}, "-1698136228": {"name": "Rift Keys", "category": "Keystones", "platform": "Console"}}, "Lore": {"-1194932976": {"name": "A2 Oasis KamyrsOrdersTwo", "category": "Lore", "platform": "Console"}, "192275875": {"name": "A2 TemplarBackstory 3 Landus's Diary", "category": "Lore", "platform": "Console"}, "-1883980626": {"name": "A3 Battlefields Supply WagonDiaries", "category": "Lore", "platform": "Console"}, "1740306889": {"name": "A4 Hub OldCouple 1", "category": "Lore", "platform": "Console"}, "-1764974213": {"name": "Adria ZoltunKulle2", "category": "Lore", "platform": "Console"}, "103300821": {"name": "Adria: Adria's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-776544373": {"name": "Adria: Adria's Journal, Part 2", "category": "Lore", "platform": "Console"}, "133385135": {"name": "Adria: Adria's Journal, Part 3", "category": "Lore", "platform": "Console"}, "133390039": {"name": "Adria: Adria's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1890330185": {"name": "Adria: Adria's Journal, Part 5", "category": "Lore", "platform": "Console"}, "127066864": {"name": "Adria: Adria's Journal, Part 6", "category": "Lore", "platform": "Console"}, "733368986": {"name": "Adria: Adria's Journal, Part 7", "category": "Lore", "platform": "Console"}, "100959118": {"name": "Adria: Adria's Journal, Part 8", "category": "Lore", "platform": "Console"}, "133600747": {"name": "Adria: Adria's Journal, Part 9", "category": "Lore", "platform": "Console"}, "133313247": {"name": "Adria: Adria's Note", "category": "Lore", "platform": "Console"}, "954251807": {"name": "Adria: Adria's Purpose", "category": "Lore", "platform": "Console"}, "900358318": {"name": "AdventureMode: A New Era", "category": "Lore", "platform": "Console"}, "-282286736": {"name": "AdventureMode: An Eternity of Agony", "category": "Lore", "platform": "Console"}, "1375431349": {"name": "AdventureMode: Impossibilities", "category": "Lore", "platform": "Console"}, "-1315225766": {"name": "AdventureMode: The Nephalem", "category": "Lore", "platform": "Console"}, "501220619": {"name": "AngirisCouncil: The Angiris Council", "category": "Lore", "platform": "Console"}, "-1383924340": {"name": "AngirisCouncil: The Archangel Auriel", "category": "Lore", "platform": "Console"}, "260686328": {"name": "AngirisCouncil: The Archangel Imperius", "category": "Lore", "platform": "Console"}, "397935128": {"name": "AngirisCouncil: The Archangel Itherael", "category": "Lore", "platform": "Console"}, "478898578": {"name": "AngirisCouncil: The Archangel Malthael", "category": "Lore", "platform": "Console"}, "-635616901": {"name": "AngirisCouncil: The Archangel Tyrael", "category": "Lore", "platform": "Console"}, "-164029999": {"name": "Aqueducts: The Desert Aqueducts, Part 1", "category": "Lore", "platform": "Console"}, "-164029998": {"name": "Aqueducts: The Desert Aqueducts, Part 2", "category": "Lore", "platform": "Console"}, "-714930281": {"name": "Armorer: Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "-1385743634": {"name": "Azmodan: Orders from Azmodan, Part 1", "category": "Lore", "platform": "Console"}, "-1385743633": {"name": "Azmodan: Orders from Azmodan, Part 2", "category": "Lore", "platform": "Console"}, "-1385743632": {"name": "Azmodan: Orders from Azmodan, Part 3", "category": "Lore", "platform": "Console"}, "-1385743631": {"name": "Azmodan: Orders from Azmodan, Part 4", "category": "Lore", "platform": "Console"}, "-1385743630": {"name": "Azmodan: Orders from Azmodan, Part 5", "category": "Lore", "platform": "Console"}, "-1385743629": {"name": "Azmodan: Orders from Azmodan, Part 6", "category": "Lore", "platform": "Console"}, "-1312231117": {"name": "Belial: Deceivers' Orders, Part 1", "category": "Lore", "platform": "Console"}, "-1346161479": {"name": "Belial: Deceivers' Orders, Part 2", "category": "Lore", "platform": "Console"}, "-661262942": {"name": "Belial: Deceivers' Orders, Part 3", "category": "Lore", "platform": "Console"}, "-978510227": {"name": "Belial: Guard's Orders", "category": "Lore", "platform": "Console"}, "1488385291": {"name": "Belial: Missive to Maghda, Part 1", "category": "Lore", "platform": "Console"}, "1488385292": {"name": "Belial: Missive to Maghda, Part 2", "category": "Lore", "platform": "Console"}, "10458238": {"name": "Belial: Proclamation from the Imperial Guard", "category": "Lore", "platform": "Console"}, "621163016": {"name": "Bestiary: Anarch", "category": "Lore", "platform": "Console"}, "515122494": {"name": "Bestiary: Armored Destroyer", "category": "Lore", "platform": "Console"}, "-1478953705": {"name": "Bestiary: Barbed Lurker", "category": "Lore", "platform": "Console"}, "1467646658": {"name": "Bestiary: Beast", "category": "Lore", "platform": "Console"}, "231471423": {"name": "Bestiary: Bile Crawler", "category": "Lore", "platform": "Console"}, "1675636673": {"name": "Bestiary: Blood Clan Khazra", "category": "Lore", "platform": "Console"}, "1675805102": {"name": "Bestiary: Blood Hawk", "category": "Lore", "platform": "Console"}, "2132231168": {"name": "Bestiary: Bogan Trapper", "category": "Lore", "platform": "Console"}, "661688183": {"name": "Bestiary: Boggit", "category": "Lore", "platform": "Console"}, "-1697636392": {"name": "Bestiary: Carrion Bat", "category": "Lore", "platform": "Console"}, "-186990405": {"name": "Bestiary: Carrion Nest", "category": "Lore", "platform": "Console"}, "1864365917": {"name": "Bestiary: Colossal Golgor", "category": "Lore", "platform": "Console"}, "-899331059": {"name": "Bestiary: Corpse Raiser", "category": "Lore", "platform": "Console"}, "-563018536": {"name": "Bestiary: Dark Berserker", "category": "Lore", "platform": "Console"}, "-1824883589": {"name": "Bestiary: Dark Cultist", "category": "Lore", "platform": "Console"}, "1971053797": {"name": "Bestiary: Dark Vessel", "category": "Lore", "platform": "Console"}, "-985860913": {"name": "Bestiary: Death Maiden", "category": "Lore", "platform": "Console"}, "610441837": {"name": "Bestiary: Deceivers", "category": "Lore", "platform": "Console"}, "-1937284463": {"name": "Bestiary: Demon Trooper", "category": "Lore", "platform": "Console"}, "478100232": {"name": "Bestiary: Demonic Hell Bearer", "category": "Lore", "platform": "Console"}, "-140849528": {"name": "Bestiary: Demonic Hellflyer", "category": "Lore", "platform": "Console"}, "2144349771": {"name": "Bestiary: Demonic Tremor", "category": "Lore", "platform": "Console"}, "1641498900": {"name": "Bestiary: Dune Dervish", "category": "Lore", "platform": "Console"}, "1184767076": {"name": "Bestiary: Dune Thresher", "category": "Lore", "platform": "Console"}, "-525114375": {"name": "Bestiary: Dust Imp", "category": "Lore", "platform": "Console"}, "-1086668012": {"name": "Bestiary: Electric Eel", "category": "Lore", "platform": "Console"}, "90729293": {"name": "Bestiary: Enraged Phantasm", "category": "Lore", "platform": "Console"}, "-1878606908": {"name": "Bestiary: Enslaved Nightmare", "category": "Lore", "platform": "Console"}, "789563798": {"name": "Bestiary: Exarch", "category": "Lore", "platform": "Console"}, "-1299022938": {"name": "Bestiary: Executioner", "category": "Lore", "platform": "Console"}, "1389417324": {"name": "Bestiary: Exorcist", "category": "Lore", "platform": "Console"}, "163638005": {"name": "Bestiary: Fallen Grunt", "category": "Lore", "platform": "Console"}, "84174677": {"name": "Bestiary: Fallen Lunatic", "category": "Lore", "platform": "Console"}, "1562132029": {"name": "Bestiary: Fallen Shaman", "category": "Lore", "platform": "Console"}, "-990665261": {"name": "Bestiary: Flesh Gorger", "category": "Lore", "platform": "Console"}, "-944408897": {"name": "Bestiary: Flesh Hurler", "category": "Lore", "platform": "Console"}, "-529946523": {"name": "Bestiary: Flesh Shaman", "category": "Lore", "platform": "Console"}, "1473699320": {"name": "Bestiary: Ghost", "category": "Lore", "platform": "Console"}, "1473699378": {"name": "Bestiary: Ghoul", "category": "Lore", "platform": "Console"}, "1067328402": {"name": "Bestiary: Grotesque", "category": "Lore", "platform": "Console"}, "-288964962": {"name": "Bestiary: Hellion", "category": "Lore", "platform": "Console"}, "-675600988": {"name": "Bestiary: Herald of Pestilence", "category": "Lore", "platform": "Console"}, "-1778975775": {"name": "Bestiary: Hound Pack Leader", "category": "Lore", "platform": "Console"}, "-1864253371": {"name": "Bestiary: Hulking Phasebeast", "category": "Lore", "platform": "Console"}, "1270376265": {"name": "Bestiary: Imp", "category": "Lore", "platform": "Console"}, "1543483412": {"name": "Bestiary: Khazra", "category": "Lore", "platform": "Console"}, "1080209708": {"name": "Bestiary: Khazra Shaman", "category": "Lore", "platform": "Console"}, "1574383663": {"name": "Bestiary: Lacuni", "category": "Lore", "platform": "Console"}, "1277879248": {"name": "Bestiary: Maggot Brood", "category": "Lore", "platform": "Console"}, "-1289421300": {"name": "Bestiary: Primordial Scavenger", "category": "Lore", "platform": "Console"}, "-683087584": {"name": "Bestiary: Quill Fiend", "category": "Lore", "platform": "Console"}, "2123300624": {"name": "Bestiary: Revenant Soldier", "category": "Lore", "platform": "Console"}, "2139220569": {"name": "Bestiary: Risen Dead", "category": "Lore", "platform": "Console"}, "-286364985": {"name": "Bestiary: Rockworm", "category": "Lore", "platform": "Console"}, "507308136": {"name": "Bestiary: Sand Dweller", "category": "Lore", "platform": "Console"}, "-1096104684": {"name": "Bestiary: Sand Wasp", "category": "Lore", "platform": "Console"}, "1312554887": {"name": "Bestiary: Scarab", "category": "Lore", "platform": "Console"}, "-1399846223": {"name": "Bestiary: Scavenger", "category": "Lore", "platform": "Console"}, "2067382477": {"name": "Bestiary: Scavenging Tunneler", "category": "Lore", "platform": "Console"}, "-458569087": {"name": "Bestiary: Scouring Charger", "category": "Lore", "platform": "Console"}, "-1529207830": {"name": "Bestiary: Shadow Vermin", "category": "Lore", "platform": "Console"}, "-1715924548": {"name": "Bestiary: Shadow of Death", "category": "Lore", "platform": "Console"}, "1905172061": {"name": "Bestiary: Shrieking Terror", "category": "Lore", "platform": "Console"}, "56567324": {"name": "Bestiary: Siegebreaker Assault Beast", "category": "Lore", "platform": "Console"}, "-387707041": {"name": "Bestiary: Skeletal Beast", "category": "Lore", "platform": "Console"}, "494193920": {"name": "Bestiary: Skeletal Crawler", "category": "Lore", "platform": "Console"}, "-313234093": {"name": "Bestiary: Skeletal Guardian", "category": "Lore", "platform": "Console"}, "-1409684360": {"name": "Bestiary: Skeleton", "category": "Lore", "platform": "Console"}, "1170383240": {"name": "Bestiary: Soul Ripper", "category": "Lore", "platform": "Console"}, "1866317050": {"name": "Bestiary: Spider", "category": "Lore", "platform": "Console"}, "564441124": {"name": "Bestiary: Spiderling", "category": "Lore", "platform": "Console"}, "-330757856": {"name": "Bestiary: Stinging Swarm", "category": "Lore", "platform": "Console"}, "-458677543": {"name": "Bestiary: Subjugator", "category": "Lore", "platform": "Console"}, "-1468295040": {"name": "Bestiary: Succubus", "category": "Lore", "platform": "Console"}, "-513840200": {"name": "Bestiary: Summoned Archer", "category": "Lore", "platform": "Console"}, "166255055": {"name": "Bestiary: Summoned Shield Guard", "category": "Lore", "platform": "Console"}, "1887856949": {"name": "Bestiary: Summoned Soldier", "category": "Lore", "platform": "Console"}, "920539156": {"name": "Bestiary: Summoner of the Dead", "category": "Lore", "platform": "Console"}, "166186064": {"name": "Bestiary: Terror Demon", "category": "Lore", "platform": "Console"}, "-1551452867": {"name": "Bestiary: The Accursed", "category": "Lore", "platform": "Console"}, "1613832402": {"name": "Bestiary: The Mallet Lords", "category": "Lore", "platform": "Console"}, "1481069442": {"name": "Bestiary: The Morlu", "category": "Lore", "platform": "Console"}, "1727215776": {"name": "Bestiary: The Oppressors", "category": "Lore", "platform": "Console"}, "-1569107231": {"name": "Bestiary: Tormented Stinger", "category": "Lore", "platform": "Console"}, "692217017": {"name": "Bestiary: Treasure Goblin", "category": "Lore", "platform": "Console"}, "1112087602": {"name": "Bestiary: Tusked Bogan", "category": "Lore", "platform": "Console"}, "1695981553": {"name": "Bestiary: Unburied", "category": "Lore", "platform": "Console"}, "181747316": {"name": "Bestiary: Vicious Hound", "category": "Lore", "platform": "Console"}, "191466402": {"name": "Bestiary: Vile Bat", "category": "Lore", "platform": "Console"}, "1295465786": {"name": "Bestiary: Warscarred Marauder", "category": "Lore", "platform": "Console"}, "-1568007631": {"name": "Bestiary: Warscarred Ravager", "category": "Lore", "platform": "Console"}, "1809929374": {"name": "Bestiary: Winged Assassin", "category": "Lore", "platform": "Console"}, "-1414985342": {"name": "Bestiary: Winged Talus", "category": "Lore", "platform": "Console"}, "1562746110": {"name": "Bestiary: Withermoth", "category": "Lore", "platform": "Console"}, "1892963547": {"name": "Bestiary: Wood Wraith", "category": "Lore", "platform": "Console"}, "1470131000": {"name": "Bestiary: Wretched Mother", "category": "Lore", "platform": "Console"}, "2033922302": {"name": "Butcher: Butcher", "category": "Lore", "platform": "Console"}, "3246582303": {"name": "Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "4058000945": {"name": "Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "554362535": {"name": "Cain: Deckard Cain's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1114094521": {"name": "Cain: Deckard Cain's Journal, Part 2", "category": "Lore", "platform": "Console"}, "828022511": {"name": "Caldeum: An Abridged History of Caldeum, Part 1", "category": "Lore", "platform": "Console"}, "828022512": {"name": "Caldeum: An Abridged History of Caldeum, Part 2", "category": "Lore", "platform": "Console"}, "828022513": {"name": "Caldeum: An Abridged History of Caldeum, Part 3", "category": "Lore", "platform": "Console"}, "828022514": {"name": "Caldeum: An Abridged History of Caldeum, Part 4", "category": "Lore", "platform": "Console"}, "828022515": {"name": "Caldeum: An Abridged History of Caldeum, Part 5", "category": "Lore", "platform": "Console"}, "828022516": {"name": "Caldeum: An Abridged History of Caldeum, Part 6", "category": "Lore", "platform": "Console"}, "344927641": {"name": "CaliphateSardar: The Musings of Caliphate Sardar", "category": "Lore", "platform": "Console"}, "-1106917318": {"name": "CampCultist: The Feared Hero", "category": "Lore", "platform": "Console"}, "-668215174": {"name": "CellarMadman: The Ravings of a Deranged Mind", "category": "Lore", "platform": "Console"}, "-1518383148": {"name": "CemeteryCrypts: Gravedigger's Log", "category": "Lore", "platform": "Console"}, "-727194820": {"name": "Challenge: Nephalem Rifts", "category": "Lore", "platform": "Console"}, "2125283571": {"name": "Crusader: The Crusaders, Part 1", "category": "Lore", "platform": "Console"}, "2125283572": {"name": "Crusader: The Crusaders, Part 2", "category": "Lore", "platform": "Console"}, "2125283573": {"name": "Crusader: The Crusaders, Part 3", "category": "Lore", "platform": "Console"}, "2125283574": {"name": "Crusader: The Crusaders, Part 4", "category": "Lore", "platform": "Console"}, "2125283575": {"name": "Crusader: The Crusaders, Part 5", "category": "Lore", "platform": "Console"}, "2125283576": {"name": "Crusader: The Crusaders, Part 6", "category": "Lore", "platform": "Console"}, "2125283577": {"name": "Crusader: The Crusaders, Part 7", "category": "Lore", "platform": "Console"}, "2125283578": {"name": "Crusader: The Crusaders, Part 8", "category": "Lore", "platform": "Console"}, "2125283579": {"name": "Crusader: The Crusaders, Part 9", "category": "Lore", "platform": "Console"}, "-186854830": {"name": "CultCrown: Cultist Orders", "category": "Lore", "platform": "Console"}, "4108112466": {"name": "Cultist Orders", "category": "Lore", "platform": "Console"}, "504852499": {"name": "CurioVendor: Adenah's Jottings", "category": "Lore", "platform": "Console"}, "-1717171528": {"name": "Cydaea: Cydaea, the Maiden of Lust", "category": "Lore", "platform": "Console"}, "1958060101": {"name": "DahlgurOasis: The Dahlgur Oasis", "category": "Lore", "platform": "Console"}, "-1010870335": {"name": "DarkZealot: Report from Wortham", "category": "Lore", "platform": "Console"}, "-819413474": {"name": "Deserter: Deserter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-819413473": {"name": "Deserter: Deserter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-819413472": {"name": "Deserter: Deserter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-819413471": {"name": "Deserter: Deserter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "-819413470": {"name": "Deserter: Deserter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "1121720780": {"name": "DesolateSands: On the Desolate Sands, Part 1", "category": "Lore", "platform": "Console"}, "1121720781": {"name": "DesolateSands: On the Desolate Sands, Part 2", "category": "Lore", "platform": "Console"}, "1121720782": {"name": "DesolateSands: On the Desolate Sands, Part 3", "category": "Lore", "platform": "Console"}, "2388677118": {"name": "Despina's Journal", "category": "Lore", "platform": "Console"}, "1244727565": {"name": "DevilsHand: Implements of the Dark Coven", "category": "Lore", "platform": "Console"}, "1244727564": {"name": "DevilsHand: The Black King's Reign", "category": "Lore", "platform": "Console"}, "1244727563": {"name": "DevilsHand: The Covenant's Search", "category": "Lore", "platform": "Console"}, "172363859": {"name": "DoomedWoman: The Horrible Secret", "category": "Lore", "platform": "Console"}, "-1577589110": {"name": "Enchantress: Eirena's Journal", "category": "Lore", "platform": "Console"}, "2168089835": {"name": "Example Book", "category": "Lore", "platform": "Console"}, "1850500833": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 1", "category": "Lore", "platform": "Console"}, "1850500834": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 2", "category": "Lore", "platform": "Console"}, "1850500835": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 3", "category": "Lore", "platform": "Console"}, "1850500836": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 4", "category": "Lore", "platform": "Console"}, "1850500837": {"name": "FalloftheBarbs: Fall of the Barbarians, Part 5", "category": "Lore", "platform": "Console"}, "1814333430": {"name": "FieldsofMisery: Tristram Fields", "category": "Lore", "platform": "Console"}, "-821793924": {"name": "Ghom: Ghom, the Lord of Gluttony", "category": "Lore", "platform": "Console"}, "-681952308": {"name": "GluttonysLog: Ghom's Log", "category": "Lore", "platform": "Console"}, "1895762819": {"name": "GoatmenHunter: Khazra Heads Wanted", "category": "Lore", "platform": "Console"}, "1895762820": {"name": "GoatmenHunter: Researching the Khazra", "category": "Lore", "platform": "Console"}, "1895762821": {"name": "GoatmenHunter: The Khazra Massacre", "category": "Lore", "platform": "Console"}, "-1085616825": {"name": "Halls_of_Agony: Command from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "-1085616824": {"name": "Halls_of_Agony: Reply from Cultist Grand Inquisitor", "category": "Lore", "platform": "Console"}, "721065374": {"name": "HangingTree: The Hanging Tree", "category": "Lore", "platform": "Console"}, "4006002334": {"name": "Hellion", "category": "Lore", "platform": "Console"}, "1555542539": {"name": "Hermit_Caves: Hermit's Ravings", "category": "Lore", "platform": "Console"}, "-578368437": {"name": "HexMaze: Melaina's Memory", "category": "Lore", "platform": "Console"}, "-578368438": {"name": "HexMaze: Raissa's Memory", "category": "Lore", "platform": "Console"}, "-578368439": {"name": "HexMaze: Sibyl's Thoughts", "category": "Lore", "platform": "Console"}, "2145056291": {"name": "Highlands: The Highlands", "category": "Lore", "platform": "Console"}, "174686246": {"name": "HuntersJournal: Hunter's Journal, Part 1", "category": "Lore", "platform": "Console"}, "174686247": {"name": "HuntersJournal: Hunter's Journal, Part 2", "category": "Lore", "platform": "Console"}, "174686248": {"name": "HuntersJournal: Hunter's Journal, Part 3", "category": "Lore", "platform": "Console"}, "174686249": {"name": "HuntersJournal: Hunter's Journal, Part 4", "category": "Lore", "platform": "Console"}, "174686250": {"name": "HuntersJournal: Hunter's Journal, Part 5", "category": "Lore", "platform": "Console"}, "174686251": {"name": "HuntersJournal: Hunter's Journal, Part 6", "category": "Lore", "platform": "Console"}, "-799754755": {"name": "Inarius: The Creation of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "-799754754": {"name": "Inarius: The Creation of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "-799754753": {"name": "Inarius: The Creation of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "-799754752": {"name": "Inarius: The Creation of Sanctuary, Part 4", "category": "Lore", "platform": "Console"}, "194883964": {"name": "Inarius: The Testament of Inarius, Part 1", "category": "Lore", "platform": "Console"}, "194883965": {"name": "Inarius: The Testament of Inarius, Part 2", "category": "Lore", "platform": "Console"}, "194883966": {"name": "Inarius: The Testament of Inarius, Part 3", "category": "Lore", "platform": "Console"}, "194883967": {"name": "Inarius: The Testament of Inarius, Part 4", "category": "Lore", "platform": "Console"}, "194883968": {"name": "Inarius: The Testament of Inarius, Part 5", "category": "Lore", "platform": "Console"}, "194883969": {"name": "Inarius: The Testament of Inarius, Part 6", "category": "Lore", "platform": "Console"}, "194883970": {"name": "Inarius: The Testament of Inarius, Part 7", "category": "Lore", "platform": "Console"}, "-1346370762": {"name": "Izual: Izual's Descent", "category": "Lore", "platform": "Console"}, "28868489": {"name": "Jeweler: Journal of Covetous Shen", "category": "Lore", "platform": "Console"}, "1221720352": {"name": "Jeweler: The Legend of Zei the Trickster", "category": "Lore", "platform": "Console"}, "-329801970": {"name": "Kala: Kala's Poem", "category": "Lore", "platform": "Console"}, "-355886665": {"name": "KeepHistory: The History of Bastion's Keep", "category": "Lore", "platform": "Console"}, "815737414": {"name": "KhanDakab: Last Will of Khan Dakab", "category": "Lore", "platform": "Console"}, "378673143": {"name": "KidVendor: Larra's Diary", "category": "Lore", "platform": "Console"}, "-1755180605": {"name": "Kingsport: Kingsport Bill", "category": "Lore", "platform": "Console"}, "-1156197446": {"name": "Kulle: Kulle's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1156197445": {"name": "Kulle: Kulle's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1156197444": {"name": "Kulle: Kulle's Journal, Part 3", "category": "Lore", "platform": "Console"}, "-1156197443": {"name": "Kulle: Kulle's Journal, Part 4", "category": "Lore", "platform": "Console"}, "2698411174": {"name": "Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "3758420764": {"name": "Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "3768800974": {"name": "Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "3768800975": {"name": "Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "3768800976": {"name": "Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "3768800977": {"name": "Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "-1596556122": {"name": "Lachdanan: Lachdanan's Final Scroll", "category": "Lore", "platform": "Console"}, "-536546532": {"name": "Lachdanan: Lachdanan's Scroll, Part 1", "category": "Lore", "platform": "Console"}, "-526166322": {"name": "Lachdanan: Lachdanan's Scroll, Part 2", "category": "Lore", "platform": "Console"}, "-526166321": {"name": "Lachdanan: Lachdanan's Scroll, Part 3", "category": "Lore", "platform": "Console"}, "-526166320": {"name": "Lachdanan: Lachdanan's Scroll, Part 4", "category": "Lore", "platform": "Console"}, "-526166319": {"name": "Lachdanan: Lachdanan's Scroll, Part 5", "category": "Lore", "platform": "Console"}, "1554177638": {"name": "LastAncient: The Last of the Ancients", "category": "Lore", "platform": "Console"}, "1905436671": {"name": "Lazarus: A Page from Lazarus's Grimoire", "category": "Lore", "platform": "Console"}, "3272862989": {"name": "Leah's Journal, Part 1", "category": "Lore", "platform": "Console"}, "3272868741": {"name": "Leah's Journal, Part 2", "category": "Lore", "platform": "Console"}, "3625638211": {"name": "Leah's Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922967": {"name": "Leah: Leah's Caldeum Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922968": {"name": "Leah: Leah's Caldeum Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922969": {"name": "Leah: Leah's Caldeum Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922970": {"name": "Leah: Leah's Caldeum Journal, Part 4", "category": "Lore", "platform": "Console"}, "891922971": {"name": "Leah: Leah's Caldeum Journal, Part 5", "category": "Lore", "platform": "Console"}, "891922972": {"name": "Leah: Leah's Keep Journal, Part 1", "category": "Lore", "platform": "Console"}, "891922973": {"name": "Leah: Leah's Keep Journal, Part 2", "category": "Lore", "platform": "Console"}, "891922974": {"name": "Leah: Leah's Keep Journal, Part 3", "category": "Lore", "platform": "Console"}, "891922975": {"name": "Leah: Leah's Keep Journal, Part 4", "category": "Lore", "platform": "Console"}, "-1022104307": {"name": "Leah: Leah's Tristram Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1022098555": {"name": "Leah: Leah's Tristram Journal, Part 2", "category": "Lore", "platform": "Console"}, "-669329085": {"name": "Leah: Leah's Tristram Journal, Part 3", "category": "Lore", "platform": "Console"}, "629974535": {"name": "Leah: Leah's Tristram Journal, Part 4", "category": "Lore", "platform": "Console"}, "629968021": {"name": "Leah: Leah's Tristram Journal, Part 5", "category": "Lore", "platform": "Console"}, "-1022100097": {"name": "Leah: Leah's Tristram Journal, Part 6", "category": "Lore", "platform": "Console"}, "-670618452": {"name": "Leah: Leah's Tristram Journal, Part 7", "category": "Lore", "platform": "Console"}, "2951326394": {"name": "Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1091428479": {"name": "Leoric: A Prisoner's Journal", "category": "Lore", "platform": "Console"}, "-1343640902": {"name": "Leoric: Leoric's Crown Note", "category": "Lore", "platform": "Console"}, "1561062717": {"name": "Leoric: Leoric's Journal, Part 1", "category": "Lore", "platform": "Console"}, "1561062718": {"name": "Leoric: Leoric's Journal, Part 2", "category": "Lore", "platform": "Console"}, "1561062719": {"name": "Leoric: Leoric's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561062720": {"name": "Leoric: Leoric's Journal, Part 4", "category": "Lore", "platform": "Console"}, "1561062721": {"name": "Leoric: Leoric's Journal, Part 5", "category": "Lore", "platform": "Console"}, "342313869": {"name": "Leoric: Leoric's Relic", "category": "Lore", "platform": "Console"}, "164674838": {"name": "Leoric: The Death of King Leoric", "category": "Lore", "platform": "Console"}, "82422929": {"name": "Leoric: Torn Letter", "category": "Lore", "platform": "Console"}, "82422930": {"name": "Leoric: Torn Letter's Response", "category": "Lore", "platform": "Console"}, "1354656263": {"name": "Lilith: The Writings of Lilith, Part 1", "category": "Lore", "platform": "Console"}, "1354656264": {"name": "Lilith: The Writings of Lilith, Part 2", "category": "Lore", "platform": "Console"}, "1354656265": {"name": "Lilith: The Writings of Lilith, Part 3", "category": "Lore", "platform": "Console"}, "1354656266": {"name": "Lilith: The Writings of Lilith, Part 4", "category": "Lore", "platform": "Console"}, "2145180345": {"name": "LordofFools: Lord Kertis's Journal", "category": "Lore", "platform": "Console"}, "704654350": {"name": "LordsofHell: Andariel, the Maiden of Anguish", "category": "Lore", "platform": "Console"}, "-408914888": {"name": "LordsofHell: Azmodan, the Lord of Sin", "category": "Lore", "platform": "Console"}, "-1390665602": {"name": "LordsofHell: Baal, the Lord of Destruction", "category": "Lore", "platform": "Console"}, "1693753943": {"name": "LordsofHell: Belial, the Lord of Lies", "category": "Lore", "platform": "Console"}, "1776365849": {"name": "LordsofHell: Diablo, the Lord of Terror", "category": "Lore", "platform": "Console"}, "1791215219": {"name": "LordsofHell: Duriel, the Lord of Pain", "category": "Lore", "platform": "Console"}, "-1530801161": {"name": "LordsofHell: Mephisto, the Lord of Hatred", "category": "Lore", "platform": "Console"}, "1361465018": {"name": "LordsofHell: The Seven Lords of Hell", "category": "Lore", "platform": "Console"}, "1775133212": {"name": "Lore CainLetter", "category": "Lore", "platform": "Console"}, "1615247495": {"name": "Lore Catacombs NephDefenseSystem", "category": "Lore", "platform": "Console"}, "-1084060684": {"name": "Lore Festering CryptOfTheAncients", "category": "Lore", "platform": "Console"}, "108864625": {"name": "Lore Festering DrownedTemple", "category": "Lore", "platform": "Console"}, "-740914034": {"name": "Lore Festering WarriorsRest", "category": "Lore", "platform": "Console"}, "2011207568": {"name": "Lore X1 Bog Ideation AdriaSpikeChest", "category": "Lore", "platform": "Console"}, "216459655": {"name": "Lore X1 Graveyard Azthar", "category": "Lore", "platform": "Console"}, "-827657709": {"name": "Lore X1 Westm Legendary Drop", "category": "Lore", "platform": "Console"}, "-1004685329": {"name": "Lore x1 MysticIntro1", "category": "Lore", "platform": "Console"}, "-1004685328": {"name": "Lore x1 MysticIntro2", "category": "Lore", "platform": "Console"}, "-2124310248": {"name": "Lore_p2_DateDungeon_CovenPlans (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "-1307619936": {"name": "Lore_p2_ScoundrelEvent02_SimonNote (Patch 2.2.0)", "category": "Lore", "platform": "Console"}, "1390356236": {"name": "LostAngel: The Lost Warrior", "category": "Lore", "platform": "Console"}, "1487246296": {"name": "LoveLetter: A Love Letter", "category": "Lore", "platform": "Console"}, "-184131088": {"name": "MaghdaManor: Orders from Maghda", "category": "Lore", "platform": "Console"}, "18980873": {"name": "Malthael: The Path of Wisdom, Part 1", "category": "Lore", "platform": "Console"}, "18980874": {"name": "Malthael: The Path of Wisdom, Part 2", "category": "Lore", "platform": "Console"}, "18980875": {"name": "Malthael: The Path of Wisdom, Part 3", "category": "Lore", "platform": "Console"}, "18980876": {"name": "Malthael: The Path of Wisdom, Part 4", "category": "Lore", "platform": "Console"}, "18980877": {"name": "Malthael: The Path of Wisdom, Part 5", "category": "Lore", "platform": "Console"}, "18980878": {"name": "Malthael: The Path of Wisdom, Part 6", "category": "Lore", "platform": "Console"}, "3897062066": {"name": "Mira's Letter to Haedrig", "category": "Lore", "platform": "Console"}, "-768304375": {"name": "MisguidedFarmer: Farmer's Journal", "category": "Lore", "platform": "Console"}, "-1595216991": {"name": "Morgan: Morgan's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-1595216990": {"name": "Morgan: Morgan's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1595216989": {"name": "Morgan: Morgan's Journal, Part 3", "category": "Lore", "platform": "Console"}, "1561999134": {"name": "Necromancer: Necromancer's Log", "category": "Lore", "platform": "Console"}, "1036599468": {"name": "Nephalem: The Destiny of the Nephalem, Part 1", "category": "Lore", "platform": "Console"}, "1036599469": {"name": "Nephalem: The Destiny of the Nephalem, Part 2", "category": "Lore", "platform": "Console"}, "1036599470": {"name": "Nephalem: The Destiny of the Nephalem, Part 3", "category": "Lore", "platform": "Console"}, "85406869": {"name": "Nephalem: The Drowned Temple", "category": "Lore", "platform": "Console"}, "1604771305": {"name": "Nephalem: The Last Stand of the Ancients", "category": "Lore", "platform": "Console"}, "1071008887": {"name": "Nephalem: The Nephalem Tome", "category": "Lore", "platform": "Console"}, "220221847": {"name": "Nephalem: Tomb Robber's Journal", "category": "Lore", "platform": "Console"}, "429729842": {"name": "Nephalem: Warrior's Rest", "category": "Lore", "platform": "Console"}, "-1608490938": {"name": "NephalemMiser: Miser's Will", "category": "Lore", "platform": "Console"}, "775555921": {"name": "NewTristram: New Tristram", "category": "Lore", "platform": "Console"}, "-1083079452": {"name": "Note: Secret Note", "category": "Lore", "platform": "Console"}, "1316599940": {"name": "Oasis: A Love Letter", "category": "Lore", "platform": "Console"}, "1676339915": {"name": "OasisCellars: The Imperial Guard's Orders", "category": "Lore", "platform": "Console"}, "-1048384993": {"name": "OldTristram: Cain's Old Journal, Part 1", "category": "Lore", "platform": "Console"}, "-236966351": {"name": "OldTristram: Cain's Old Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1906290178": {"name": "OldTristram: Despina's Journal", "category": "Lore", "platform": "Console"}, "829218340": {"name": "OldTristram: Gillian's Diary, Part 1", "category": "Lore", "platform": "Console"}, "1594401494": {"name": "OldTristram: Gillian's Diary, Part 2", "category": "Lore", "platform": "Console"}, "316278028": {"name": "OldTristram: Lost Journal", "category": "Lore", "platform": "Console"}, "316278029": {"name": "OldTristram: Old Diary", "category": "Lore", "platform": "Console"}, "316278027": {"name": "OldTristram: Old Tristram Journal", "category": "Lore", "platform": "Console"}, "-700459563": {"name": "OldTristram: Traveler's Journal", "category": "Lore", "platform": "Console"}, "-289611678": {"name": "OldTristram: Villager's Journal", "category": "Lore", "platform": "Console"}, "1708077021": {"name": "OldTristram: Warriv's Journal", "category": "Lore", "platform": "Console"}, "-561113926": {"name": "OneLastEntry: Crumbling Journal", "category": "Lore", "platform": "Console"}, "-216253271": {"name": "PandExt: Legend of the Great Weapon", "category": "Lore", "platform": "Console"}, "551638722": {"name": "PandExt: Malthael's Plan", "category": "Lore", "platform": "Console"}, "-420053241": {"name": "Pandemonium: The History of Pandemonium, Part 1", "category": "Lore", "platform": "Console"}, "-420053240": {"name": "Pandemonium: The History of Pandemonium, Part 2", "category": "Lore", "platform": "Console"}, "-420053239": {"name": "Pandemonium: The History of Pandemonium, Part 3", "category": "Lore", "platform": "Console"}, "-420053238": {"name": "Pandemonium: The History of Pandemonium, Part 4", "category": "Lore", "platform": "Console"}, "-1604058933": {"name": "Poltahr: Poltahr's Notes", "category": "Lore", "platform": "Console"}, "-1861918345": {"name": "PortalRoulette: Lyndo's Journal", "category": "Lore", "platform": "Console"}, "613068827": {"name": "Priest: Priest's Contemplations, Part 1", "category": "Lore", "platform": "Console"}, "613068826": {"name": "Priest: Priest's Contemplations, Part 2", "category": "Lore", "platform": "Console"}, "1320763167": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 1", "category": "Lore", "platform": "Console"}, "1320763168": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 2", "category": "Lore", "platform": "Console"}, "1320763169": {"name": "PrimeDiscovery: The Discovery of Sanctuary, Part 3", "category": "Lore", "platform": "Console"}, "1758275411": {"name": "PromisesOfFezuul: The Promises of Fezuul al-Kazarr", "category": "Lore", "platform": "Console"}, "-139516026": {"name": "ProudWife: Bloodstained Letter", "category": "Lore", "platform": "Console"}, "3611879712": {"name": "Quill Fiend", "category": "Lore", "platform": "Console"}, "1276294793": {"name": "Rakanoth: Rakanoth, the Lord of Despair", "category": "Lore", "platform": "Console"}, "-1106592288": {"name": "Rakkis: Rakkis's Orders", "category": "Lore", "platform": "Console"}, "-1074332472": {"name": "RakkisHistory: The Testament of Rakkis, Part 1", "category": "Lore", "platform": "Console"}, "-1074332471": {"name": "RakkisHistory: The Testament of Rakkis, Part 2", "category": "Lore", "platform": "Console"}, "-1074332470": {"name": "RakkisHistory: The Testament of Rakkis, Part 3", "category": "Lore", "platform": "Console"}, "-1074332469": {"name": "RakkisHistory: The Testament of Rakkis, Part 4", "category": "Lore", "platform": "Console"}, "-1074332468": {"name": "RakkisHistory: The Testament of Rakkis, Part 5", "category": "Lore", "platform": "Console"}, "-1074332467": {"name": "RakkisHistory: The Testament of Rakkis, Part 6", "category": "Lore", "platform": "Console"}, "-1074332466": {"name": "RakkisHistory: The Testament of Rakkis, Part 7", "category": "Lore", "platform": "Console"}, "-1074332465": {"name": "RakkisHistory: The Testament of Rakkis, Part 8", "category": "Lore", "platform": "Console"}, "-1074332464": {"name": "RakkisHistory: The Testament of Rakkis, Part 9", "category": "Lore", "platform": "Console"}, "1960749072": {"name": "Realmwalker: The Realmwalker", "category": "Lore", "platform": "Console"}, "3580037015": {"name": "Scabbard of Talic the Defender", "category": "Lore", "platform": "Console"}, "2895121073": {"name": "Scavenger", "category": "Lore", "platform": "Console"}, "-561655662": {"name": "Scoundrel: Scoundrel's Journal", "category": "Lore", "platform": "Console"}, "648677458": {"name": "Siege: Missive from Imperius", "category": "Lore", "platform": "Console"}, "-1327438701": {"name": "Siege: Siege Runes", "category": "Lore", "platform": "Console"}, "1667935935": {"name": "SkeletonKing: The Skeleton King", "category": "Lore", "platform": "Console"}, "-21507498": {"name": "SpiderQueen: The Spider Queen", "category": "Lore", "platform": "Console"}, "1881837798": {"name": "Templar: Bloodied Parchment", "category": "Lore", "platform": "Console"}, "1881837797": {"name": "Templar: Bloodied Scraps", "category": "Lore", "platform": "Console"}, "1792637338": {"name": "TemplarMaester: Grand Maester's Journal", "category": "Lore", "platform": "Console"}, "1776052671": {"name": "TemplarMaester: The Maester's Proclamation", "category": "Lore", "platform": "Console"}, "464105835": {"name": "Tinker: Wandering Tinker's Diary", "category": "Lore", "platform": "Console"}, "3594507733": {"name": "Traveler's Journal", "category": "Lore", "platform": "Console"}, "732715821": {"name": "UriktheSeer: Notes of Urik the Seer, Part 1", "category": "Lore", "platform": "Console"}, "732715822": {"name": "UriktheSeer: Notes of Urik the Seer, Part 2", "category": "Lore", "platform": "Console"}, "732715823": {"name": "UriktheSeer: Notes of Urik the Seer, Part 3", "category": "Lore", "platform": "Console"}, "-645692806": {"name": "Urzael: Urzael's Journal, Part 1", "category": "Lore", "platform": "Console"}, "-645692805": {"name": "Urzael: Urzael's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-645692804": {"name": "Urzael: Urzael's Journal, Part 3", "category": "Lore", "platform": "Console"}, "4005355618": {"name": "Villager's Journal", "category": "Lore", "platform": "Console"}, "-1451420418": {"name": "WaterPuzzle: The Chamber of Faces", "category": "Lore", "platform": "Console"}, "1223177093": {"name": "Westm: It's a Trap", "category": "Lore", "platform": "Console"}, "831394876": {"name": "Westm: The Cult Shall Rise Again", "category": "Lore", "platform": "Console"}, "913430382": {"name": "Westm: The King's Journal, Part 1", "category": "Lore", "platform": "Console"}, "913430383": {"name": "Westm: The King's Journal, Part 2", "category": "Lore", "platform": "Console"}, "-1218326648": {"name": "Westm: The King's Note to Lord Wynton", "category": "Lore", "platform": "Console"}, "1526997743": {"name": "Westm: The Plague Tunnels", "category": "Lore", "platform": "Console"}, "-1469466389": {"name": "Westm: The Souls of Westmarch", "category": "Lore", "platform": "Console"}, "-916745255": {"name": "Westmarch: The History of Westmarch, Part 1", "category": "Lore", "platform": "Console"}, "-916745254": {"name": "Westmarch: The History of Westmarch, Part 2", "category": "Lore", "platform": "Console"}, "-916745253": {"name": "Westmarch: The History of Westmarch, Part 3", "category": "Lore", "platform": "Console"}, "-916745252": {"name": "Westmarch: The History of Westmarch, Part 4", "category": "Lore", "platform": "Console"}, "-916745251": {"name": "Westmarch: The History of Westmarch, Part 5", "category": "Lore", "platform": "Console"}, "-916745250": {"name": "Westmarch: The History of Westmarch, Part 6", "category": "Lore", "platform": "Console"}, "-916745249": {"name": "Westmarch: The History of Westmarch, Part 7", "category": "Lore", "platform": "Console"}, "-223645750": {"name": "X1 Lore Besitary RevenantShieldGuard", "category": "Lore", "platform": "Console"}, "1571805338": {"name": "X1 Lore Bestiary GhastlySeraph", "category": "Lore", "platform": "Console"}, "1836003891": {"name": "X1 Lore Bestiary RevenantArcher", "category": "Lore", "platform": "Console"}, "-1635681275": {"name": "x1 Bog Lore AdriaBetrayal", "category": "Lore", "platform": "Console"}, "-8314071": {"name": "x1 Bog Lore AdriaEmptiness", "category": "Lore", "platform": "Console"}, "1923206206": {"name": "x1 Bog Lore AdriaLosingControl", "category": "Lore", "platform": "Console"}, "2045759001": {"name": "x1 Bog Lore AdriaNewHost", "category": "Lore", "platform": "Console"}, "118984382": {"name": "x1 Bog Lore AdriaPower", "category": "Lore", "platform": "Console"}, "-134175942": {"name": "x1 Bog Lore AdriaVoices", "category": "Lore", "platform": "Console"}, "-1074332440": {"name": "x1 Bog Lore RakkisHistory10", "category": "Lore", "platform": "Console"}}, "Maces, One-Handed": {"-1656026177": {"name": "02: Cudgel (DPS 9.6-11.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026176": {"name": "03: Morning Star (DPS 15.0-16.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026175": {"name": "04: Mace (DPS 18.6-20.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026174": {"name": "05: Flanged Mace (DPS 23.4-25.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026173": {"name": "06: Hammer (DPS 28.2-30.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656026172": {"name": "07: War Gavel (DPS 33.6-35.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025089": {"name": "08: Bludgeon (DPS 43.8-45.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025088": {"name": "09: Spiked Baton (DPS 52.2-54.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025087": {"name": "10: War Mace (DPS 62.4-64.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025086": {"name": "11: Gada (DPS 73.2-75.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025085": {"name": "12: Pernach (DPS 85.2-88.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025084": {"name": "13: Heavy Hammer (DPS 102.0-105.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656025083": {"name": "14: War Hammer (DPS 124.8-128.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656024000": {"name": "15: Skull Crusher (DPS 138.0-143.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023999": {"name": "16: Truncheon (DPS 155.4-160.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023998": {"name": "17: Death Mace (DPS 174.0-179.4)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023997": {"name": "18: Tripyor (DPS 192.6-199.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023996": {"name": "19: Goedendag (DPS 237.0-244.2)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023995": {"name": "20: Crag Hammer (DPS 273.6-282.6)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656023994": {"name": "21: Demolisher (DPS 318.0-327.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022911": {"name": "22: Brutalizer (DPS 429.6-436.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1656022910": {"name": "23: Skullsplitter (DPS 540.6-547.8)", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099965": {"name": "Art Test Mace One-Handed 1", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099964": {"name": "Art Test Mace One-Handed 2", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099963": {"name": "Art Test Mace One-Handed 3", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099962": {"name": "Art Test Mace One-Handed 4", "category": "Maces, One-Handed", "platform": "Console"}, "-1527099961": {"name": "Art Test Mace One-Handed 5", "category": "Maces, One-Handed", "platform": "Console"}, "-1473010435": {"name": "Legendary: Deadeye's Mace (Patch 2.1.0)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894988668": {"name": "Legendary: Devastator", "category": "Maces, One-Handed", "platform": "Console"}, "1889806096": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1889808540": {"name": "Legendary: Earthshatter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325116": {"name": "Legendary: Earthshatter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895276164": {"name": "Legendary: Echoing Fury", "category": "Maces, One-Handed", "platform": "Console"}, "1880318728": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1880321172": {"name": "Legendary: Echoing Fury (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325108": {"name": "Legendary: Echoing Fury (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856068897": {"name": "Legendary: Jace's Hammer of Vigilance", "category": "Maces, One-Handed", "platform": "Console"}, "-1856140771": {"name": "Legendary: Mad Monarch's Scepter", "category": "Maces, One-Handed", "platform": "Console"}, "-1895024605": {"name": "Legendary: Nailbiter", "category": "Maces, One-Handed", "platform": "Console"}, "1888620175": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1888622619": {"name": "Legendary: Nailbiter (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325115": {"name": "Legendary: Nailbiter (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895204290": {"name": "Legendary: Neanderthal", "category": "Maces, One-Handed", "platform": "Console"}, "1882690570": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1882693014": {"name": "Legendary: Neanderthal (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325110": {"name": "Legendary: Neanderthal (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895132416": {"name": "Legendary: Nutcracker", "category": "Maces, One-Handed", "platform": "Console"}, "1885062412": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1885064856": {"name": "Legendary: Nutcracker (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325112": {"name": "Legendary: Nutcracker (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895240227": {"name": "Legendary: Odyn Son", "category": "Maces, One-Handed", "platform": "Console"}, "1881504649": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1881507093": {"name": "Legendary: Odyn Son (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325109": {"name": "Legendary: Odyn Son (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1856104834": {"name": "Legendary: Solanium", "category": "Maces, One-Handed", "platform": "Console"}, "-1894090243": {"name": "Legendary: Sun Keeper", "category": "Maces, One-Handed", "platform": "Console"}, "1919454121": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1919456565": {"name": "Legendary: Sun Keeper (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325141": {"name": "Legendary: Sun Keeper (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1895060542": {"name": "Legendary: Telranden's Hand", "category": "Maces, One-Handed", "platform": "Console"}, "1887434254": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1887436698": {"name": "Legendary: Telranden's Hand (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325114": {"name": "Legendary: Telranden's Hand (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "-1894126180": {"name": "Legendary: Wirt's Original Leg", "category": "Maces, One-Handed", "platform": "Console"}, "1918268200": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "1918270644": {"name": "Legendary: Wirt's Original Leg (Legacy)", "category": "Maces, One-Handed", "platform": "Console"}, "713325140": {"name": "Legendary: Wirt's Original Leg (Old-Legacy)", "category": "Maces, One-Handed", "platform": "Console"}}, "Maces, Two-Handed": {"-1616890784": {"name": "02: Two-Handed Mace (DPS 20.3-21.6)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890783": {"name": "03: Two-Handed Hammer (DPS 24.8-26.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890782": {"name": "04: Maul (DPS 31.5-32.9)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890781": {"name": "05: Mallet (DPS 37.8-40.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616890780": {"name": "06: Great Hammer (DPS 45.5-48.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889696": {"name": "07: Dire Club (DPS 55.8-58.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889695": {"name": "08: Dire Mace (DPS 66.6-70.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889694": {"name": "09: Sledge Hammer (DPS 81.9-86.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889693": {"name": "10: Great Maul (DPS 98.6-104.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889692": {"name": "11: War Mallet (DPS 117.9-124.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616889691": {"name": "12: Rock Breaker (DPS 144.5-151.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888607": {"name": "13: Wrecker (DPS 196.7-206.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888606": {"name": "14: Dread Mace (DPS 249.3-260.1)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888605": {"name": "15: War Sledge (DPS 315.9-326.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888604": {"name": "16: War Maul (DPS 437.9-448.7)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888603": {"name": "17: Slag Hammer (DPS 518.4-529.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616888602": {"name": "18: Doom Hammer (DPS 613.4-624.2)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887518": {"name": "19: Royal Mace (DPS 774.0-786.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1616887517": {"name": "20: Persuader (DPS 1058.5-1070.5)", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064028": {"name": "Art Test Mace Two-Handed 1", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064027": {"name": "Art Test Mace Two-Handed 2", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064026": {"name": "Art Test Mace Two-Handed 3", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064025": {"name": "Art Test Mace Two-Handed 4", "category": "Maces, Two-Handed", "platform": "Console"}, "-1527064024": {"name": "Art Test Mace Two-Handed 5", "category": "Maces, Two-Handed", "platform": "Console"}, "59108159": {"name": "Legendary: Arthef's Spark of Life", "category": "Maces, Two-Handed", "platform": "Console"}, "1950491947": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1950494391": {"name": "Legendary: Boneshatter (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460503": {"name": "Legendary: Boneshatter (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954049710": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1954052154": {"name": "Legendary: Cataclysm (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460506": {"name": "Legendary: Cataclysm (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59036285": {"name": "Legendary: Crushbane", "category": "Maces, Two-Handed", "platform": "Console"}, "1948120105": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1948122549": {"name": "Legendary: Crushbane (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460501": {"name": "Legendary: Crushbane (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323781": {"name": "Legendary: Schaefer's Hammer", "category": "Maces, Two-Handed", "platform": "Console"}, "1957607473": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1957609917": {"name": "Legendary: Schaefer's Hammer (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460509": {"name": "Legendary: Schaefer's Hammer (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60186269": {"name": "Legendary: Skywarden", "category": "Maces, Two-Handed", "platform": "Console"}, "1986069577": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1986072021": {"name": "Legendary: Skywarden (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460533": {"name": "Legendary: Skywarden (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "59072222": {"name": "Legendary: Sledge of Athskeleng", "category": "Maces, Two-Handed", "platform": "Console"}, "1949306026": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1949308470": {"name": "Legendary: Sledge of Athskeleng (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460502": {"name": "Legendary: Sledge of Athskeleng (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "98279489": {"name": "Legendary: Soulsmasher", "category": "Maces, Two-Handed", "platform": "Console"}, "59215970": {"name": "Legendary: Sunder", "category": "Maces, Two-Handed", "platform": "Console"}, "98243552": {"name": "Legendary: The Furnace", "category": "Maces, Two-Handed", "platform": "Console"}, "60258143": {"name": "Legendary: Wrath of the Bone King", "category": "Maces, Two-Handed", "platform": "Console"}, "1988441419": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "1988443863": {"name": "Legendary: Wrath of the Bone King (Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "752460535": {"name": "Legendary: Wrath of the Bone King (Old-Legacy)", "category": "Maces, Two-Handed", "platform": "Console"}, "60257879": {"name": "Legendary: Wrath of the Bone King (Patch 2.1.0)", "category": "Maces, Two-Handed", "platform": "Console"}, "59323518": {"name": "legendary: Schaefer's Hammer (Patch 2.2.0)", "category": "Maces, Two-Handed", "platform": "Console"}}, "Mighty Belts": {"2112155407": {"name": "02: Harness (AR 32-37)", "category": "Mighty Belts", "platform": "Console"}, "2112155408": {"name": "03: Braid (AR 53-61)", "category": "Mighty Belts", "platform": "Console"}, "2112155409": {"name": "04: Grand Belt (AR 74-100)", "category": "Mighty Belts", "platform": "Console"}, "2112156495": {"name": "05: Baldric (AR 101-132)", "category": "Mighty Belts", "platform": "Console"}, "2112156496": {"name": "06: Blade Harness (AR 133-164)", "category": "Mighty Belts", "platform": "Console"}, "2112156497": {"name": "07: Iron Braid (AR 165-205)", "category": "Mighty Belts", "platform": "Console"}, "2112156498": {"name": "08: Steel Chain (AR 206-225)", "category": "Mighty Belts", "platform": "Console"}, "2112157584": {"name": "09: Lock (AR 226-252)", "category": "Mighty Belts", "platform": "Console"}, "2112157585": {"name": "10: Bronze Links (AR 253-285)", "category": "Mighty Belts", "platform": "Console"}, "2112157586": {"name": "11: Heavy Baldric (AR 286-318)", "category": "Mighty Belts", "platform": "Console"}, "2112157587": {"name": "12: Grand Chain (AR 320-419)", "category": "Mighty Belts", "platform": "Console"}, "2112157588": {"name": "13: Platinum Lock (AR 420-586)", "category": "Mighty Belts", "platform": "Console"}, "2112157589": {"name": "14: Mighty Scourge (AR 586-674)", "category": "Mighty Belts", "platform": "Console"}, "325816755": {"name": "Art Test BarbBelt 1", "category": "Mighty Belts", "platform": "Console"}, "325816756": {"name": "Art Test BarbBelt 2", "category": "Mighty Belts", "platform": "Console"}, "325816757": {"name": "Art Test BarbBelt 3", "category": "Mighty Belts", "platform": "Console"}, "325816758": {"name": "Art Test BarbBelt 4", "category": "Mighty Belts", "platform": "Console"}, "325816759": {"name": "Art Test BarbBelt 5", "category": "Mighty Belts", "platform": "Console"}, "924282931": {"name": "Legendary: Ageless Might", "category": "Mighty Belts", "platform": "Console"}, "436488351": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "436490795": {"name": "Legendary: Ageless Might (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630773": {"name": "Legendary: Ageless Might (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963274576": {"name": "Legendary: Ancients' Discontent", "category": "Mighty Belts", "platform": "Console"}, "963166765": {"name": "Legendary: Chilanik's Chain", "category": "Mighty Belts", "platform": "Console"}, "924031372": {"name": "Legendary: Dread Iron", "category": "Mighty Belts", "platform": "Console"}, "428186904": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "428189348": {"name": "Legendary: Dread Iron (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630780": {"name": "Legendary: Dread Iron (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924139183": {"name": "Legendary: Girdle of Giants", "category": "Mighty Belts", "platform": "Console"}, "431744667": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "431747111": {"name": "Legendary: Girdle of Giants (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630777": {"name": "Legendary: Girdle of Giants (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924246994": {"name": "Legendary: Kotuur's Brace", "category": "Mighty Belts", "platform": "Console"}, "435302430": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "435304874": {"name": "Legendary: Kotuur's Brace (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630774": {"name": "Legendary: Kotuur's Brace (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924175120": {"name": "Legendary: Lamentation", "category": "Mighty Belts", "platform": "Console"}, "432930588": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "432933032": {"name": "Legendary: Lamentation (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630776": {"name": "Legendary: Lamentation (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924174856": {"name": "Legendary: Lamentation (Patch 2.1.0)", "category": "Mighty Belts", "platform": "Console"}, "924067309": {"name": "Legendary: Pride of Cassius", "category": "Mighty Belts", "platform": "Console"}, "429372825": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "429375269": {"name": "Legendary: Pride of Cassius (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630779": {"name": "Legendary: Pride of Cassius (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963310513": {"name": "Legendary: Promise of the Doomed Forebearer", "category": "Mighty Belts", "platform": "Console"}, "924211057": {"name": "Legendary: The Undisputed Champion", "category": "Mighty Belts", "platform": "Console"}, "434116509": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "434118953": {"name": "Legendary: The Undisputed Champion (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630775": {"name": "Legendary: The Undisputed Champion (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737386": {"name": "Legendary: The Undisputed Champion (Patch 2.1.2)", "category": "Mighty Belts", "platform": "Console"}, "430558746": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "430561190": {"name": "Legendary: Thunder God's Vigor (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "-1303630778": {"name": "Legendary: Thunder God's Vigor (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "963238639": {"name": "Legendary: Wodir Harness", "category": "Mighty Belts", "platform": "Console"}, "963202702": {"name": "Legendary: x1_BarbBelt_norm_unique_11", "category": "Mighty Belts", "platform": "Console"}, "-1303630772": {"name": "Set: Immortal King's Detail (Old-Legacy)", "category": "Mighty Belts", "platform": "Console"}, "924318868": {"name": "Set: Immortal King's Tribal Binding", "category": "Mighty Belts", "platform": "Console"}, "437674272": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "437676716": {"name": "Set: Immortal King's Tribal Binding (Legacy)", "category": "Mighty Belts", "platform": "Console"}, "1958737381": {"name": "legendary: Dread Iron (Patch 2.2.0)", "category": "Mighty Belts", "platform": "Console"}}, "Mighty Weapons, One-Handed": {"290066502": {"name": "02: Carver (DPS 14.3-16.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066503": {"name": "03: Maw Axe (DPS 21.5-23.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290066504": {"name": "04: War Blade (DPS 31.2-33.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067590": {"name": "05: Scythe (DPS 36.4-38.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067591": {"name": "06: Machete (DPS 54.6-56.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067592": {"name": "07: Gutwrench (DPS 82.6-86.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290067593": {"name": "08: Rage Blade (DPS 118.3-122.2)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068679": {"name": "09: Reaper (DPS 153.4-159.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068680": {"name": "10: Chopsword (DPS 206.7-214.5)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068681": {"name": "11: Massacre Axe (DPS 238.6-246.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290068682": {"name": "12: Slayer (DPS 277.6-285.4)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069768": {"name": "13: Caldean Sword (DPS 371.8-379.6)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "290069769": {"name": "14: Limb Cleaver (DPS 461.5-469.3)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026495": {"name": "Art Test Mighty One-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026496": {"name": "Art Test Mighty One-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026497": {"name": "Art Test Mighty One-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026498": {"name": "Art Test Mighty One-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073026499": {"name": "Art Test Mighty One-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062432": {"name": "Art Test Mighty Two-Handed 1", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062433": {"name": "Art Test Mighty Two-Handed 2", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062434": {"name": "Art Test Mighty Two-Handed 3", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062435": {"name": "Art Test Mighty Two-Handed 4", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "2073062436": {"name": "Art Test Mighty Two-Handed 5", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511328230": {"name": "Legendary: Ambo's Pride", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665698662": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1665701106": {"name": "Legendary: Ambo's Pride (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986962": {"name": "Legendary: Ambo's Pride (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512406340": {"name": "Legendary: Blade of the Warlord", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630121032": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1630123476": {"name": "Legendary: Blade of the Warlord (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986932": {"name": "Legendary: Blade of the Warlord (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473342821": {"name": "Legendary: Dishonored Legacy", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512370403": {"name": "Legendary: Fjord Cutter", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631306953": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1631309397": {"name": "Legendary: Fjord Cutter (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986933": {"name": "Legendary: Fjord Cutter (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625377348": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1625379792": {"name": "Legendary: Harvest Moon (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986928": {"name": "Legendary: Harvest Moon (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473414695": {"name": "Legendary: Hellion Scale", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1512550088": {"name": "Legendary: Night's Reaping", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473306884": {"name": "Legendary: Oathkeeper", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1473378758": {"name": "Legendary: Remorseless", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986960": {"name": "Set: Bul-Kathos's Sacred Charge (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511400104": {"name": "Set: Bul-Kathos's Solemn Vow", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663326820": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1663329264": {"name": "Set: Bul-Kathos's Solemn Vow (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986961": {"name": "Set: Bul-Kathos's Tribal Guardian (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511364167": {"name": "Set: Bul-Kathos's Warrior Blood", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664512741": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1664515185": {"name": "Set: Bul-Kathos's Warrior Blood (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1801986965": {"name": "Set: Hallowed Destroyer (Old-Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "-1511220419": {"name": "Set: Hallowed Nemesis", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669258869": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}, "1669256425": {"name": "Set: Hallowed Reckoning (Legacy)", "category": "Mighty Weapons, One-Handed", "platform": "Console"}}, "Mighty Weapons, Two-Handed": {"329201895": {"name": "02: Giant Sword (DPS 18.0-19.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201896": {"name": "03: Giant Hammer (DPS 25.5-27.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329201897": {"name": "04: Giant Axe (DPS 36.0-37.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202983": {"name": "05: Redwood War Club (DPS 60.6-63.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202984": {"name": "06: Colossus Sword (DPS 81.5-86.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202985": {"name": "07: Crusher (DPS 110.5-116.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329202986": {"name": "08: Colossus Axe (DPS 169.0-176.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204072": {"name": "09: Battersmash (DPS 248.5-257.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204073": {"name": "10: Titan Sword (DPS 397.5-408.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204074": {"name": "11: Behemoth (DPS 469.0-481.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329204075": {"name": "12: Titan Axe (DPS 555.0-567.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205161": {"name": "13: Hassan Chopper (DPS 691.9-703.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "329205162": {"name": "14: Steppes Smasher (DPS 940.0-951.5)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441870172": {"name": "Legendary: Bastion's Revered", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696736488": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1696738932": {"name": "Legendary: Bastion's Revered (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122324": {"name": "Legendary: Bastion's Revered (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441869908": {"name": "Legendary: Bastion's Revered (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441942046": {"name": "Legendary: Fury of the Vanished Peak", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699108330": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1699110774": {"name": "Legendary: Fury of the Vanished Peak (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122326": {"name": "Legendary: Fury of the Vanished Peak (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-96858155": {"name": "Legendary: Grim Reaper", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "480897754": {"name": "Legendary: Madawc's Sorrow", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "-389442788": {"name": "Legendary: The Blackrock Destroyer (Patch 2.1.0)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "441762361": {"name": "Legendary: The Gavel of Judgment", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693178725": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1693181169": {"name": "Legendary: The Gavel of Judgment (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122321": {"name": "Legendary: The Gavel of Judgment (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733500039": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1733502483": {"name": "Legendary: Unending War (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122355": {"name": "Legendary: Unending War (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442984219": {"name": "Legendary: War of the Dead", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "442912345": {"name": "Set: Immortal King's Boulder Breaker", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731128197": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1731130641": {"name": "Set: Immortal King's Boulder Breaker (Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}, "1841122353": {"name": "Set: Immortal King's Stone Crusher (Old-Legacy)", "category": "Mighty Weapons, Two-Handed", "platform": "Console"}}, "Mightys, Two-Handed": {}, "Mojos": {"-136816474": {"name": "02: Shrunken Head (+(2-3)-(3-5) DMG)", "category": "Mojos", "platform": "Console"}, "-136816473": {"name": "03: Caged Horror (+(3-5)-(4-8) DMG)", "category": "Mojos", "platform": "Console"}, "-136816472": {"name": "04: Viper (+(3-6)-(4-10) DMG)", "category": "Mojos", "platform": "Console"}, "-136815386": {"name": "05: Gris-Gris Moppet (+(4-8)-(5-13) DMG)", "category": "Mojos", "platform": "Console"}, "-136815385": {"name": "06: Tzantza (+(6-11)-(7-19) DMG)", "category": "Mojos", "platform": "Console"}, "-136815384": {"name": "07: Living Tentacle (+(8-16)-(9-29) DMG)", "category": "Mojos", "platform": "Console"}, "-136815383": {"name": "08: Copperhead (+(13-26)-(14-45) DMG)", "category": "Mojos", "platform": "Console"}, "-136814297": {"name": "09: Wicker Man (+(17-39)-(18-114) DMG)", "category": "Mojos", "platform": "Console"}, "-136814296": {"name": "10: Muttering Head (+(19-58)-(20-213) DMG)", "category": "Mojos", "platform": "Console"}, "-136814295": {"name": "11: Unspeakable Thing (+(24-72)-(25-265) DMG)", "category": "Mojos", "platform": "Console"}, "-136814294": {"name": "12: Kurastian Asp (+(28-110)-(29-405) DMG)", "category": "Mojos", "platform": "Console"}, "-136814293": {"name": "13: Skull Talisman (+(126-158)-(127-190) DMG)", "category": "Mojos", "platform": "Console"}, "-136814292": {"name": "14: Thing That Should Not Be (+(262-328)-(263-394) DMG)", "category": "Mojos", "platform": "Console"}, "1629900554": {"name": "Art Test Mojo 1", "category": "Mojos", "platform": "Console"}, "1629900555": {"name": "Art Test Mojo 2", "category": "Mojos", "platform": "Console"}, "1629900556": {"name": "Art Test Mojo 3", "category": "Mojos", "platform": "Console"}, "1629900557": {"name": "Art Test Mojo 4", "category": "Mojos", "platform": "Console"}, "1629900558": {"name": "Art Test Mojo 5", "category": "Mojos", "platform": "Console"}, "-1667471440": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-1667468996": {"name": "Legendary: Bitterness (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608100": {"name": "Legendary: Bitterness (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961544827": {"name": "Legendary: Gazing Demise", "category": "Mojos", "platform": "Console"}, "-1666285519": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-1666283075": {"name": "Legendary: Gazing Demise (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608099": {"name": "Legendary: Gazing Demise (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961508890": {"name": "Legendary: Homunculus", "category": "Mojos", "platform": "Console"}, "-1665099598": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-1665097154": {"name": "Legendary: Homunculus (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608098": {"name": "Legendary: Homunculus (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922445371": {"name": "Legendary: Shukrani's Triumph", "category": "Mojos", "platform": "Console"}, "-922409434": {"name": "Legendary: Sorrowful Countenance", "category": "Mojos", "platform": "Console"}, "-961580764": {"name": "Legendary: Spite", "category": "Mojos", "platform": "Console"}, "-961329205": {"name": "Legendary: Thing of the Deep", "category": "Mojos", "platform": "Console"}, "-1659169993": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-1659167549": {"name": "Legendary: Thing of the Deep (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608093": {"name": "Legendary: Thing of the Deep (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-961365142": {"name": "Legendary: Uhkapian Serpent", "category": "Mojos", "platform": "Console"}, "-1660355914": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-1660353470": {"name": "Legendary: Uhkapian Serpent (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608094": {"name": "Legendary: Uhkapian Serpent (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-922373497": {"name": "Legendary: Vile Hive", "category": "Mojos", "platform": "Console"}, "1413644935": {"name": "P2 mojo norm Legendary 01", "category": "Mojos", "platform": "Console"}, "1413644936": {"name": "P2 mojo norm Legendary 02", "category": "Mojos", "platform": "Console"}, "1413644937": {"name": "P2 mojo norm Legendary 03", "category": "Mojos", "platform": "Console"}, "-960466717": {"name": "Set: Manajuma's Gory Fetch", "category": "Mojos", "platform": "Console"}, "-1630707889": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-1630705445": {"name": "Set: Manajuma's Gory Fetch (Legacy)", "category": "Mojos", "platform": "Console"}, "-63608069": {"name": "Set: Manajuma's Ritual Prize (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-63608068": {"name": "Set: Zunimassa's Ferocity (Old-Legacy)", "category": "Mojos", "platform": "Console"}, "-960430780": {"name": "Set: Zunimassa's String of Skulls", "category": "Mojos", "platform": "Console"}, "-1629521968": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-1629519524": {"name": "Set: Zunimassa's String of Skulls (Legacy)", "category": "Mojos", "platform": "Console"}, "-961509153": {"name": "legendary: Homunculus (Patch 2.2.0)", "category": "Mojos", "platform": "Console"}}, "NPC Items": {"1372800103": {"name": "A Summoner's Journal", "category": "NPC Items", "platform": "Console"}, "1366034119": {"name": "A2C2EmptyCage", "category": "NPC Items", "platform": "Console"}, "-894018760": {"name": "A2C2HusamHead", "category": "NPC Items", "platform": "Console"}, "1506900471": {"name": "A2C2NecromancerCrystal", "category": "NPC Items", "platform": "Console"}, "-1176971336": {"name": "A2C2OreBag", "category": "NPC Items", "platform": "Console"}, "-701130141": {"name": "A2C2RygnarIdol", "category": "NPC Items", "platform": "Console"}, "-1969048485": {"name": "A2C2SharkHide", "category": "NPC Items", "platform": "Console"}, "524402999": {"name": "A2C2SharkNecklace", "category": "NPC Items", "platform": "Console"}, "297778632": {"name": "A2C2WantedPoster", "category": "NPC Items", "platform": "Console"}, "1135854513": {"name": "A2C2WantedPosterGood", "category": "NPC Items", "platform": "Console"}, "-284487217": {"name": "ActIQ2 RatMageSkull", "category": "NPC Items", "platform": "Console"}, "956379400": {"name": "Ahren's Hammer", "category": "NPC Items", "platform": "Console"}, "893398919": {"name": "AlbrechtsRemains", "category": "NPC Items", "platform": "Console"}, "-1240838296": {"name": "Ancient Medallion", "category": "NPC Items", "platform": "Console"}, "1475923527": {"name": "Ancient Tome Page", "category": "NPC Items", "platform": "Console"}, "-831189640": {"name": "Angelic Seal", "category": "NPC Items", "platform": "Console"}, "-885657485": {"name": "Antique Box", "category": "NPC Items", "platform": "Console"}, "-309356827": {"name": "Aqueduct Key", "category": "NPC Items", "platform": "Console"}, "493907862": {"name": "Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "-470655325": {"name": "Beacon of Honor", "category": "NPC Items", "platform": "Console"}, "-470655324": {"name": "Beacon of Light", "category": "NPC Items", "platform": "Console"}, "-246893943": {"name": "Black Soulstone", "category": "NPC Items", "platform": "Console"}, "504121446": {"name": "Blackened Journal", "category": "NPC Items", "platform": "Console"}, "1818884426": {"name": "Blacksmith's Tome", "category": "NPC Items", "platform": "Console"}, "263122102": {"name": "Bogus Arcana Obscurum", "category": "NPC Items", "platform": "Console"}, "944034263": {"name": "Broken Crown", "category": "NPC Items", "platform": "Console"}, "-63906132": {"name": "Broken Doll", "category": "NPC Items", "platform": "Console"}, "1201838506": {"name": "Calldown Grenade", "category": "NPC Items", "platform": "Console"}, "-1797642504": {"name": "Caravan Inventory List", "category": "NPC Items", "platform": "Console"}, "-110888638": {"name": "Chain Key", "category": "NPC Items", "platform": "Console"}, "1061128541": {"name": "Cloud Fire", "category": "NPC Items", "platform": "Console"}, "-565248060": {"name": "Cultist Cellar Key", "category": "NPC Items", "platform": "Console"}, "-613437014": {"name": "DevilsHand: Aidan's Memento", "category": "NPC Items", "platform": "Console"}, "-613616703": {"name": "DevilsHand: Broken Oath", "category": "NPC Items", "platform": "Console"}, "-613437017": {"name": "DevilsHand: Cain's Memento", "category": "NPC Items", "platform": "Console"}, "-613544825": {"name": "DevilsHand: Dark Coven Familiar", "category": "NPC Items", "platform": "Console"}, "-613544828": {"name": "DevilsHand: Dark Coven Insignia", "category": "NPC Items", "platform": "Console"}, "-613544826": {"name": "DevilsHand: Dark Coven Jar of Reagents", "category": "NPC Items", "platform": "Console"}, "-613544829": {"name": "DevilsHand: Dark Coven Scroll of Illusions", "category": "NPC Items", "platform": "Console"}, "-613544827": {"name": "DevilsHand: Dark Coven Torturing Device", "category": "NPC Items", "platform": "Console"}, "-613437012": {"name": "DevilsHand: Gideon's Memento", "category": "NPC Items", "platform": "Console"}, "-613508887": {"name": "DevilsHand: Icon of Envy", "category": "NPC Items", "platform": "Console"}, "-613508886": {"name": "DevilsHand: Icon of Gluttony", "category": "NPC Items", "platform": "Console"}, "-613508891": {"name": "DevilsHand: Icon of Greed", "category": "NPC Items", "platform": "Console"}, "-613508888": {"name": "DevilsHand: Icon of Lust", "category": "NPC Items", "platform": "Console"}, "-613508889": {"name": "DevilsHand: Icon of Pride", "category": "NPC Items", "platform": "Console"}, "-613508890": {"name": "DevilsHand: Icon of Sloth", "category": "NPC Items", "platform": "Console"}, "-613508892": {"name": "DevilsHand: Icon of Wrath", "category": "NPC Items", "platform": "Console"}, "-613437016": {"name": "DevilsHand: Leah's Memento", "category": "NPC Items", "platform": "Console"}, "-613616702": {"name": "DevilsHand: Love's Oath", "category": "NPC Items", "platform": "Console"}, "-613437013": {"name": "DevilsHand: Ogden's Memento", "category": "NPC Items", "platform": "Console"}, "-613616701": {"name": "DevilsHand: Selfless Oath", "category": "NPC Items", "platform": "Console"}, "-613580763": {"name": "DevilsHand: The Black King's Bloodied Gauntlet", "category": "NPC Items", "platform": "Console"}, "-613580762": {"name": "DevilsHand: The Black King's Journal", "category": "NPC Items", "platform": "Console"}, "-613580765": {"name": "DevilsHand: The Black King's Skull", "category": "NPC Items", "platform": "Console"}, "-613580764": {"name": "DevilsHand: The Black King's Tainted Elixir", "category": "NPC Items", "platform": "Console"}, "-613580766": {"name": "DevilsHand: The Black King's Trophy", "category": "NPC Items", "platform": "Console"}, "-613437018": {"name": "DevilsHand: Warriv's Memento", "category": "NPC Items", "platform": "Console"}, "-613437015": {"name": "DevilsHand: Wirt's Memento", "category": "NPC Items", "platform": "Console"}, "-473140170": {"name": "Event: Alchemist Concoction", "category": "NPC Items", "platform": "Console"}, "452865871": {"name": "Event: Aperture Key", "category": "NPC Items", "platform": "Console"}, "-1312544703": {"name": "Event: Battle Elixir", "category": "NPC Items", "platform": "Console"}, "66225719": {"name": "Event: Battlefield Reports", "category": "NPC Items", "platform": "Console"}, "-1961273523": {"name": "Event: Bones of the Matriarch1", "category": "NPC Items", "platform": "Console"}, "-1961273522": {"name": "Event: Bones of the Matriarch2", "category": "NPC Items", "platform": "Console"}, "-1961273521": {"name": "Event: Bones of the Matriarch3", "category": "NPC Items", "platform": "Console"}, "1197498604": {"name": "Event: Dusty Old Tome", "category": "NPC Items", "platform": "Console"}, "463155324": {"name": "Event: Forboding Tome", "category": "NPC Items", "platform": "Console"}, "-934435532": {"name": "Event: Jeweled Scabbard", "category": "NPC Items", "platform": "Console"}, "1465477567": {"name": "Event: Medical Supplies", "category": "NPC Items", "platform": "Console"}, "-694090266": {"name": "Event: Officer's Orders", "category": "NPC Items", "platform": "Console"}, "-2013751652": {"name": "Event: Templar Object 1", "category": "NPC Items", "platform": "Console"}, "-1003233507": {"name": "Event: The Matriarch's Skeleton", "category": "NPC Items", "platform": "Console"}, "899528155": {"name": "FacePuzzleSmallKey", "category": "NPC Items", "platform": "Console"}, "-1986712818": {"name": "Fuad's Journal", "category": "NPC Items", "platform": "Console"}, "1331402556": {"name": "Greater Shard", "category": "NPC Items", "platform": "Console"}, "301784336": {"name": "Heretic Text", "category": "NPC Items", "platform": "Console"}, "-705827599": {"name": "HunterJournal", "category": "NPC Items", "platform": "Console"}, "1742022798": {"name": "Iron Wolf Captain's Journal", "category": "NPC Items", "platform": "Console"}, "680369210": {"name": "Jail Gate Key", "category": "NPC Items", "platform": "Console"}, "-78029774": {"name": "Jelisa's Wedding Ring", "category": "NPC Items", "platform": "Console"}, "1018820302": {"name": "Jeweler's Crucible", "category": "NPC Items", "platform": "Console"}, "872964849": {"name": "Journal of Hansan Haile, Captain", "category": "NPC Items", "platform": "Console"}, "1264544813": {"name": "Khan's Tomb Key", "category": "NPC Items", "platform": "Console"}, "-1071052922": {"name": "Kulle's Blood", "category": "NPC Items", "platform": "Console"}, "-1341834848": {"name": "Kulle's Body", "category": "NPC Items", "platform": "Console"}, "-1341834849": {"name": "Kulle's Heart", "category": "NPC Items", "platform": "Console"}, "425198027": {"name": "Larus's Log", "category": "NPC Items", "platform": "Console"}, "1790135009": {"name": "Mausoleum Key", "category": "NPC Items", "platform": "Console"}, "-397905230": {"name": "Mira's Letter to Haedrig", "category": "NPC Items", "platform": "Console"}, "-1140969500": {"name": "Mysterious Box", "category": "NPC Items", "platform": "Console"}, "1816611999": {"name": "Mystery Amulet", "category": "NPC Items", "platform": "Console"}, "-1493063970": {"name": "Mystery Belt", "category": "NPC Items", "platform": "Console"}, "-2026108002": {"name": "Mystery Boots", "category": "NPC Items", "platform": "Console"}, "1281756953": {"name": "Mystery Bracers", "category": "NPC Items", "platform": "Console"}, "-594428401": {"name": "Mystery Chest Armor", "category": "NPC Items", "platform": "Console"}, "2050033703": {"name": "Mystery Gloves", "category": "NPC Items", "platform": "Console"}, "-1492848355": {"name": "Mystery Helm", "category": "NPC Items", "platform": "Console"}, "-1492657844": {"name": "Mystery Mojo", "category": "NPC Items", "platform": "Console"}, "215071258": {"name": "Mystery Orb", "category": "NPC Items", "platform": "Console"}, "-2010009315": {"name": "Mystery Pants", "category": "NPC Items", "platform": "Console"}, "-1843121997": {"name": "Mystery Quiver", "category": "NPC Items", "platform": "Console"}, "-1492484569": {"name": "Mystery Ring", "category": "NPC Items", "platform": "Console"}, "-1780286480": {"name": "Mystery Shield", "category": "NPC Items", "platform": "Console"}, "-537237168": {"name": "Mystery Shoulders", "category": "NPC Items", "platform": "Console"}, "-767866790": {"name": "Mystery Weapon, One-Handed", "category": "NPC Items", "platform": "Console"}, "-1099096773": {"name": "Mystery Weapon, Two-Handed", "category": "NPC Items", "platform": "Console"}, "-1352920439": {"name": "Nephalem Cube", "category": "NPC Items", "platform": "Console"}, "1774254059": {"name": "Nephalem Shard", "category": "NPC Items", "platform": "Console"}, "-1224842764": {"name": "Note from Maghda", "category": "NPC Items", "platform": "Console"}, "1524078078": {"name": "Old Tristram Key", "category": "NPC Items", "platform": "Console"}, "1524684909": {"name": "Orn VaseB caOut Props", "category": "NPC Items", "platform": "Console"}, "1472347958": {"name": "Orn a2dun Zolt Centerpiece A", "category": "NPC Items", "platform": "Console"}, "1354327297": {"name": "Orn caOut Cauldron", "category": "NPC Items", "platform": "Console"}, "-330317735": {"name": "Orn caOut CrateA", "category": "NPC Items", "platform": "Console"}, "1360506355": {"name": "Orn caOut VendorStandB", "category": "NPC Items", "platform": "Console"}, "1823013658": {"name": "Orn trDun Cath Candlestand", "category": "NPC Items", "platform": "Console"}, "-479501418": {"name": "Orn trDun Cath LibraryTable", "category": "NPC Items", "platform": "Console"}, "582933236": {"name": "Orn trDun Gargoyle 01", "category": "NPC Items", "platform": "Console"}, "684496620": {"name": "Orn trDun Incense Burner", "category": "NPC Items", "platform": "Console"}, "1432424645": {"name": "Orn trDun Weaponrack", "category": "NPC Items", "platform": "Console"}, "-1232771108": {"name": "Primordial Key", "category": "NPC Items", "platform": "Console"}, "-1661570587": {"name": "Queen Asylla's Journal", "category": "NPC Items", "platform": "Console"}, "1490502399": {"name": "Release Lever", "category": "NPC Items", "platform": "Console"}, "-1106160196": {"name": "Relic of Purification", "category": "NPC Items", "platform": "Console"}, "1259412129": {"name": "ReligiousArtifact", "category": "NPC Items", "platform": "Console"}, "-255366628": {"name": "Resonating Crystal", "category": "NPC Items", "platform": "Console"}, "468192851": {"name": "Scroll of Companion", "category": "NPC Items", "platform": "Console"}, "-96106000": {"name": "Scroll of Mysteries", "category": "NPC Items", "platform": "Console"}, "1310326700": {"name": "Shamanic Khazra Staff", "category": "NPC Items", "platform": "Console"}, "140227858": {"name": "Shard", "category": "NPC Items", "platform": "Console"}, "-1223968557": {"name": "Shard of Resurrection", "category": "NPC Items", "platform": "Console"}, "-1703187309": {"name": "Shen's Loot", "category": "NPC Items", "platform": "Console"}, "753721399": {"name": "Skeleton King's Crown", "category": "NPC Items", "platform": "Console"}, "-1874288726": {"name": "Spider Queen Venom", "category": "NPC Items", "platform": "Console"}, "437383090": {"name": "Sword Blade", "category": "NPC Items", "platform": "Console"}, "-1027737429": {"name": "Sword Hilt", "category": "NPC Items", "platform": "Console"}, "457400460": {"name": "Sword Piece", "category": "NPC Items", "platform": "Console"}, "1360078715": {"name": "SwordOfJustice", "category": "NPC Items", "platform": "Console"}, "1163171450": {"name": "The Cultist's Head", "category": "NPC Items", "platform": "Console"}, "-718773999": {"name": "Three Broken Gems", "category": "NPC Items", "platform": "Console"}, "-797314365": {"name": "Town Portal Stone", "category": "NPC Items", "platform": "Console"}, "-608122705": {"name": "Treasure Hunter's Note", "category": "NPC Items", "platform": "Console"}, "1111843456": {"name": "Triune Smith's Tools", "category": "NPC Items", "platform": "Console"}, "-1062930416": {"name": "Vasily's Angelic Idol", "category": "NPC Items", "platform": "Console"}, "-290192033": {"name": "WestM_Food", "category": "NPC Items", "platform": "Console"}, "437221476": {"name": "ZakarumTotem", "category": "NPC Items", "platform": "Console"}, "-1464111916": {"name": "Zoltun Kulle Blood Vial", "category": "NPC Items", "platform": "Console"}, "609972295": {"name": "Zoltun Kulle's Blue Eye", "category": "NPC Items", "platform": "Console"}, "-1341834850": {"name": "Zoltun Kulle's Body", "category": "NPC Items", "platform": "Console"}, "395877111": {"name": "Zoltun Kulle's Completed Head", "category": "NPC Items", "platform": "Console"}, "-1345664746": {"name": "Zoltun Kulle's Head", "category": "NPC Items", "platform": "Console"}, "-674931800": {"name": "Zoltun Kulle's One Eyed Head", "category": "NPC Items", "platform": "Console"}, "-1345750695": {"name": "Zoltun Kulle's Red Eye", "category": "NPC Items", "platform": "Console"}, "892508204": {"name": "Zoltun Kulle's Rotting Head", "category": "NPC Items", "platform": "Console"}, "414825604": {"name": "Zoltun Kulle's Tome of the Nephalem", "category": "NPC Items", "platform": "Console"}, "-649774063": {"name": "px_DevilsHand_TestGlobe (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}, "87458782": {"name": "px_DevilsHand_TestGlobe_Dropped (Patch 2.2.0)", "category": "NPC Items", "platform": "Console"}}, "Paints": {"-590920596": {"name": "Art_Test_Pants_11 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920595": {"name": "Art_Test_Pants_12 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920594": {"name": "Art_Test_Pants_13 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "-590920593": {"name": "Art_Test_Pants_14 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598560": {"name": "Art_Test_Pants_6 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598561": {"name": "Art_Test_Pants_7 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598562": {"name": "Art_Test_Pants_8 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}, "1283598563": {"name": "Art_Test_Pants_9 (Patch 2.2.0)", "category": "Paints", "platform": "Console"}}, "Pants": {"-1512732137": {"name": "02: Leather Pants (AR 18-21)", "category": "Pants", "platform": "Console"}, "-1512732136": {"name": "03: Hide Breeches (AR 33-38)", "category": "Pants", "platform": "Console"}, "-1512732135": {"name": "04: Chain Leggings (AR 48-62)", "category": "Pants", "platform": "Console"}, "-1512732134": {"name": "05: Faulds (AR 63-77)", "category": "Pants", "platform": "Console"}, "-1512732133": {"name": "06: Plate Leggings (AR 78-101)", "category": "Pants", "platform": "Console"}, "-1512731049": {"name": "07: Legwraps (AR 102-131)", "category": "Pants", "platform": "Console"}, "-1512731048": {"name": "08: Etched Pants (AR 132-161)", "category": "Pants", "platform": "Console"}, "-1512731047": {"name": "09: Chausses (AR 162-191)", "category": "Pants", "platform": "Console"}, "-1512731046": {"name": "10: Tassets (AR 192-224)", "category": "Pants", "platform": "Console"}, "-1512731045": {"name": "11: Boneweave Faulds (AR 225-247)", "category": "Pants", "platform": "Console"}, "-1512729960": {"name": "12: Leg Guards (AR 27-269)", "category": "Pants", "platform": "Console"}, "-1512729959": {"name": "13: Poleyns (AR 270-284)", "category": "Pants", "platform": "Console"}, "-1512729958": {"name": "14: Warlord Leg Plates (AR 285-322)", "category": "Pants", "platform": "Console"}, "-1512729957": {"name": "15: Schynbalds (AR 322-359)", "category": "Pants", "platform": "Console"}, "-1512729956": {"name": "16: Sovereign Tassets (AR 360-397)", "category": "Pants", "platform": "Console"}, "-1512729955": {"name": "17: Archon Faulds (AR 397-471)", "category": "Pants", "platform": "Console"}, "-1512729954": {"name": "18: Rakkisgard Leg Plates (AR 472-659)", "category": "Pants", "platform": "Console"}, "-1512729953": {"name": "19: Ascended Faulds (AR 660-759)", "category": "Pants", "platform": "Console"}, "1283598555": {"name": "Art Test Pants 1", "category": "Pants", "platform": "Console"}, "1283598556": {"name": "Art Test Pants 2", "category": "Pants", "platform": "Console"}, "1283598557": {"name": "Art Test Pants 3", "category": "Pants", "platform": "Console"}, "1283598558": {"name": "Art Test Pants 4", "category": "Pants", "platform": "Console"}, "1283598559": {"name": "Art Test Pants 5", "category": "Pants", "platform": "Console"}, "-586378095": {"name": "Legendary: Conqueror's Legguards (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "-735317930": {"name": "Legendary: Death's Bargain", "category": "Pants", "platform": "Console"}, "-774309575": {"name": "Legendary: Depth Diggers", "category": "Pants", "platform": "Console"}, "217510501": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "217512945": {"name": "Legendary: Depth Diggers (Legacy)", "category": "Pants", "platform": "Console"}, "903144209": {"name": "Legendary: Depth Diggers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774309839": {"name": "Legendary: Depth Diggers (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "216324580": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "216327024": {"name": "Legendary: Gehennas (Legacy)", "category": "Pants", "platform": "Console"}, "903144208": {"name": "Legendary: Gehennas (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774453323": {"name": "Legendary: Hammer Jammers", "category": "Pants", "platform": "Console"}, "212766817": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "212769261": {"name": "Legendary: Hammer Jammers (Legacy)", "category": "Pants", "platform": "Console"}, "903144205": {"name": "Legendary: Hammer Jammers (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-735353867": {"name": "Legendary: Hexing Pants of Mr. Yan", "category": "Pants", "platform": "Console"}, "-305758345": {"name": "Legendary: Legs of the Sealed Valley", "category": "Pants", "platform": "Console"}, "-774273638": {"name": "Legendary: Pox Faulds", "category": "Pants", "platform": "Console"}, "218696422": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "218698866": {"name": "Legendary: Pox Faulds (Legacy)", "category": "Pants", "platform": "Console"}, "903144210": {"name": "Legendary: Pox Faulds (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774345512": {"name": "Legendary: Skelon's Deceit", "category": "Pants", "platform": "Console"}, "-774489260": {"name": "Legendary: Swamp Land Waders", "category": "Pants", "platform": "Console"}, "211580896": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "211583340": {"name": "Legendary: Swamp Land Waders (Legacy)", "category": "Pants", "platform": "Console"}, "903144204": {"name": "Legendary: Swamp Land Waders (Old-Legacy)", "category": "Pants", "platform": "Console"}, "903144212": {"name": "Set: Asheara's Cradle (Old-Legacy)", "category": "Pants", "platform": "Console"}, "221068264": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "221070708": {"name": "Set: Asheara's Gait (Legacy)", "category": "Pants", "platform": "Console"}, "-774201764": {"name": "Set: Asheara's Pace", "category": "Pants", "platform": "Console"}, "903144239": {"name": "Set: Blackthorne's Breeches (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773231465": {"name": "Set: Blackthorne's Jousting Mail", "category": "Pants", "platform": "Console"}, "253088131": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "253090575": {"name": "Set: Blackthorne's Jousting Mail (Legacy)", "category": "Pants", "platform": "Console"}, "-773339276": {"name": "Set: Cain's Habit", "category": "Pants", "platform": "Console"}, "903144236": {"name": "Set: Cain's Raiment (Old-Legacy)", "category": "Pants", "platform": "Console"}, "249530368": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "249532812": {"name": "Set: Cain's Robes (Legacy)", "category": "Pants", "platform": "Console"}, "251902210": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "251904654": {"name": "Set: Captain Crimson's Bowsprit (Legacy)", "category": "Pants", "platform": "Console"}, "903144238": {"name": "Set: Captain Crimson's Codpiece (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773267402": {"name": "Set: Captain Crimson's Thrust", "category": "Pants", "platform": "Console"}, "825937515": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827015887": {"name": "Set: Cuisses of Akkhan", "category": "Pants", "platform": "Console"}, "903144240": {"name": "Set: Demon's Flesh (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-773195528": {"name": "Set: Demon's Plate", "category": "Pants", "platform": "Console"}, "254274052": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "254276496": {"name": "Set: Demon's Scale (Legacy)", "category": "Pants", "platform": "Console"}, "826045588": {"name": "Set: Firebird's Down", "category": "Pants", "platform": "Console"}, "827231509": {"name": "Set: Helltooth Leg Guards", "category": "Pants", "platform": "Console"}, "-184773474": {"name": "Set: Immortal King's Stature (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "903144211": {"name": "Set: Inna's Glory (Old-Legacy)", "category": "Pants", "platform": "Console"}, "-774237701": {"name": "Set: Inna's Temperance", "category": "Pants", "platform": "Console"}, "219882343": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "219884787": {"name": "Set: Inna's Temperance (Legacy)", "category": "Pants", "platform": "Console"}, "826153399": {"name": "Set: Jade Harvester's Courage", "category": "Pants", "platform": "Console"}, "825901577": {"name": "Set: Leg Guards of Mystery (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826081525": {"name": "Set: Marauder's Encasement", "category": "Pants", "platform": "Console"}, "825865641": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773475": {"name": "Set: Natalya's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "826009651": {"name": "Set: Raekor's Breeches", "category": "Pants", "platform": "Console"}, "825865639": {"name": "Set: Roland's Determination (Patch 2.1.0)", "category": "Pants", "platform": "Console"}, "826117462": {"name": "Set: Scales of the Dancing Serpent", "category": "Pants", "platform": "Console"}, "827051824": {"name": "Set: Sunwuko's Leggings (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773473": {"name": "Set: Tal Rasha's Stride (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "825865640": {"name": "Set: Tasset of the Wastes (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827159635": {"name": "Set: The Shadow's Coil", "category": "Pants", "platform": "Console"}, "825937514": {"name": "Set: Unholy Plates (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "827123698": {"name": "Set: Vyr's Fantastic Finery", "category": "Pants", "platform": "Console"}, "827195572": {"name": "Set: Weight of the Earth", "category": "Pants", "platform": "Console"}, "825901578": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-184773472": {"name": "Set: Zunimassa's Cloth (Patch 2.2.0)", "category": "Pants", "platform": "Console"}, "-774273901": {"name": "legendary: Pox Faulds (Patch 2.2.0)", "category": "Pants", "platform": "Console"}}, "Polearms": {"-1337763519": {"name": "02: Pike (DPS 15.2-16.6)", "category": "Polearms", "platform": "Console"}, "-1337763518": {"name": "03: Guisarme (DPS 20.4-21.9)", "category": "Polearms", "platform": "Console"}, "-1337763517": {"name": "04: Hache (DPS 24.7-26.1)", "category": "Polearms", "platform": "Console"}, "-1337763516": {"name": "05: Glaive (DPS 31.8-33.3)", "category": "Polearms", "platform": "Console"}, "-1337763515": {"name": "06: Pole Axe (DPS 38.0-40.9)", "category": "Polearms", "platform": "Console"}, "-1337763514": {"name": "07: Halberd (DPS 41.3-44.2)", "category": "Polearms", "platform": "Console"}, "-1337763513": {"name": "08: Lance (DPS 50.8-53.7)", "category": "Polearms", "platform": "Console"}, "-1337762431": {"name": "09: Voulge (DPS 58.0-60.8)", "category": "Polearms", "platform": "Console"}, "-1337762430": {"name": "10: Naginata (DPS 70.3-74.6)", "category": "Polearms", "platform": "Console"}, "-1337762429": {"name": "11: Croc (DPS 79.8-84.1)", "category": "Polearms", "platform": "Console"}, "-1337762428": {"name": "12: Battle Hache (DPS 91.7-96.0)", "category": "Polearms", "platform": "Console"}, "-1337762427": {"name": "13: Bisento (DPS 101.7-107.4)", "category": "Polearms", "platform": "Console"}, "-1337762426": {"name": "14: Great Pole Axe (DPS 116.4-122.1)", "category": "Polearms", "platform": "Console"}, "-1337762425": {"name": "15: Battle Halberd (DPS 131.1-138.2)", "category": "Polearms", "platform": "Console"}, "-1337762424": {"name": "16: Partizan (DPS 156.3-163.4)", "category": "Polearms", "platform": "Console"}, "-1337761342": {"name": "17: Lochaber Axe (DPS 191.9-200.5)", "category": "Polearms", "platform": "Console"}, "-1337761341": {"name": "18: Fauchard (DPS 223.3-233.2)", "category": "Polearms", "platform": "Console"}, "-1337761340": {"name": "19: Skewer (DPS 260.8-272.2)", "category": "Polearms", "platform": "Console"}, "-1337761339": {"name": "20: War Crest (DPS 305.0-316.4)", "category": "Polearms", "platform": "Console"}, "-1337761338": {"name": "21: Kwan Dao (DPS 355.8-367.2)", "category": "Polearms", "platform": "Console"}, "-1337761337": {"name": "22: War Thresher (DPS 421.3-432.7)", "category": "Polearms", "platform": "Console"}, "-1337761336": {"name": "23: Grand Halberd (DPS 499.2-510.6)", "category": "Polearms", "platform": "Console"}, "-1337761335": {"name": "24: Dread Lance (DPS 590.0-601.4)", "category": "Polearms", "platform": "Console"}, "-1337760253": {"name": "25: Trident (DPS 739.7-752.3)", "category": "Polearms", "platform": "Console"}, "-1337760252": {"name": "26: Trishula (DPS 1009.1-1021.7)", "category": "Polearms", "platform": "Console"}, "-1558359355": {"name": "Art Test Polearm 1", "category": "Polearms", "platform": "Console"}, "-1558359354": {"name": "Art Test Polearm 2", "category": "Polearms", "platform": "Console"}, "-1558359353": {"name": "Art Test Polearm 3", "category": "Polearms", "platform": "Console"}, "-1558359352": {"name": "Art Test Polearm 4", "category": "Polearms", "platform": "Console"}, "-1558359351": {"name": "Art Test Polearm 5", "category": "Polearms", "platform": "Console"}, "-1948909473": {"name": "Legendary: Bovine Bardiche", "category": "Polearms", "platform": "Console"}, "-1948873536": {"name": "Legendary: Foushee Voulge", "category": "Polearms", "platform": "Console"}, "-1987972992": {"name": "Legendary: Heart Slaughter", "category": "Polearms", "platform": "Console"}, "-1178676596": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "-1178674152": {"name": "Legendary: Heart Slaughter (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587768": {"name": "Legendary: Heart Slaughter (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987973256": {"name": "Legendary: Heart Slaughter (Patch 2.1.0)", "category": "Polearms", "platform": "Console"}, "-1988008929": {"name": "Legendary: Pledge of Caldeum", "category": "Polearms", "platform": "Console"}, "-1179862517": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "-1179860073": {"name": "Legendary: Pledge of Caldeum (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587767": {"name": "Legendary: Pledge of Caldeum (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1987937055": {"name": "Legendary: Standoff", "category": "Polearms", "platform": "Console"}, "-1177490675": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "-1177488231": {"name": "Legendary: Standoff (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587769": {"name": "Legendary: Standoff (Old-Legacy)", "category": "Polearms", "platform": "Console"}, "-1988044866": {"name": "Legendary: Vigilance", "category": "Polearms", "platform": "Console"}, "-1181048438": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "-1181045994": {"name": "Legendary: Vigilance (Legacy)", "category": "Polearms", "platform": "Console"}, "1031587766": {"name": "Legendary: Vigilance (Old-Legacy)", "category": "Polearms", "platform": "Console"}}, "Quivers": {"1539236301": {"name": "02: Canvas Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236302": {"name": "03: Leather Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236303": {"name": "04: Hunting Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539236304": {"name": "05: Assassin Quiver (ASI 10.0%)", "category": "Quivers", "platform": "Console"}, "1539237389": {"name": "06: Heavy Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237390": {"name": "07: Barbed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237391": {"name": "08: Hallowed Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237392": {"name": "09: Stalker Quiver (ASI 11.0%)", "category": "Quivers", "platform": "Console"}, "1539237393": {"name": "10: Razorspine Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238478": {"name": "11: Deadeye Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238479": {"name": "12: Bonetooth Quiver (ASI 12.0%)", "category": "Quivers", "platform": "Console"}, "1539238480": {"name": "13: Consecrated Quiver (ASI 13.0%)", "category": "Quivers", "platform": "Console"}, "1539238481": {"name": "14: Runic Quiver (ASI 14.0%)", "category": "Quivers", "platform": "Console"}, "1539238482": {"name": "15: Sanctified Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238483": {"name": "16: Rakkisgard Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "1539238484": {"name": "17: Ascended Quiver (ASI 15.0%)", "category": "Quivers", "platform": "Console"}, "-1056381007": {"name": "Art Test Quiver 1", "category": "Quivers", "platform": "Console"}, "-1056381006": {"name": "Art Test Quiver 2", "category": "Quivers", "platform": "Console"}, "-1056381005": {"name": "Art Test Quiver 3", "category": "Quivers", "platform": "Console"}, "-1056381004": {"name": "Art Test Quiver 4", "category": "Quivers", "platform": "Console"}, "-1056381003": {"name": "Art Test Quiver 5", "category": "Quivers", "platform": "Console"}, "-400507188": {"name": "Legendary: Archfiend Arrows", "category": "Quivers", "platform": "Console"}, "-331912616": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-331910172": {"name": "Legendary: Black Bone Arrows (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223036": {"name": "Legendary: Black Bone Arrows (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361407732": {"name": "Legendary: Bombadier's Rucksack", "category": "Quivers", "platform": "Console"}, "-400363440": {"name": "Legendary: Dead Man's Legacy", "category": "Quivers", "platform": "Console"}, "-327168932": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-327166488": {"name": "Legendary: Dead Man's Legacy (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223032": {"name": "Legendary: Dead Man's Legacy (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361371795": {"name": "Legendary: Emimei's Duffel", "category": "Quivers", "platform": "Console"}, "-400399377": {"name": "Legendary: Fletcher's Pride", "category": "Quivers", "platform": "Console"}, "-328354853": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-328352409": {"name": "Legendary: Fletcher's Pride (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223033": {"name": "Legendary: Fletcher's Pride (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400579062": {"name": "Legendary: Flint Ripper Arrowheads", "category": "Quivers", "platform": "Console"}, "-334284458": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-334282014": {"name": "Legendary: Flint Ripper Arrowheads (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223038": {"name": "Legendary: Flint Ripper Arrowheads (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400471251": {"name": "Legendary: Holy Point Shot", "category": "Quivers", "platform": "Console"}, "-330726695": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-330724251": {"name": "Legendary: Holy Point Shot (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223035": {"name": "Legendary: Holy Point Shot (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-361335858": {"name": "Legendary: Hunter's Longbox", "category": "Quivers", "platform": "Console"}, "-400579326": {"name": "Legendary: Meticulous Bolts (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-400435314": {"name": "Legendary: Silver Star Piercers", "category": "Quivers", "platform": "Console"}, "-329540774": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-329538330": {"name": "Legendary: Silver Star Piercers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223034": {"name": "Legendary: Silver Star Piercers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400543125": {"name": "Legendary: Sin Seekers", "category": "Quivers", "platform": "Console"}, "-333098537": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-333096093": {"name": "Legendary: Sin Seekers (Legacy)", "category": "Quivers", "platform": "Console"}, "-341223037": {"name": "Legendary: Sin Seekers (Old-Legacy)", "category": "Quivers", "platform": "Console"}, "-400435578": {"name": "Legendary: Spines of Seething Hatred (Patch 2.1.0)", "category": "Quivers", "platform": "Console"}, "-361443669": {"name": "Legendary: The Ninth Cirri Satchel", "category": "Quivers", "platform": "Console"}, "564938473": {"name": "legendary: Dead Man's Legacy (Patch 2.2.0)", "category": "Quivers", "platform": "Console"}}, "Rings": {"1146967281": {"name": "02: Ring", "category": "Rings", "platform": "Console"}, "1146967282": {"name": "03: Ring", "category": "Rings", "platform": "Console"}, "1146967283": {"name": "04: Ring", "category": "Rings", "platform": "Console"}, "1146967284": {"name": "05: Ring", "category": "Rings", "platform": "Console"}, "1146967285": {"name": "06: Ring", "category": "Rings", "platform": "Console"}, "1146967286": {"name": "07: Ring", "category": "Rings", "platform": "Console"}, "1146967287": {"name": "08: Ring", "category": "Rings", "platform": "Console"}, "1146967288": {"name": "09: Ring", "category": "Rings", "platform": "Console"}, "1146967312": {"name": "10: Ring", "category": "Rings", "platform": "Console"}, "1146967313": {"name": "11: Ring", "category": "Rings", "platform": "Console"}, "1146967314": {"name": "12: Ring", "category": "Rings", "platform": "Console"}, "1146967315": {"name": "13: Ring", "category": "Rings", "platform": "Console"}, "1146967316": {"name": "14: Ring", "category": "Rings", "platform": "Console"}, "1146967317": {"name": "15: Ring", "category": "Rings", "platform": "Console"}, "1146967318": {"name": "16: Ring", "category": "Rings", "platform": "Console"}, "1146967319": {"name": "17: Ring", "category": "Rings", "platform": "Console"}, "1146967320": {"name": "18: Ring", "category": "Rings", "platform": "Console"}, "1146967321": {"name": "19: Ring", "category": "Rings", "platform": "Console"}, "1146967345": {"name": "20: Ring", "category": "Rings", "platform": "Console"}, "1146967346": {"name": "21: Ring", "category": "Rings", "platform": "Console"}, "1146967347": {"name": "22: Ring", "category": "Rings", "platform": "Console"}, "1146967348": {"name": "23: Ring", "category": "Rings", "platform": "Console"}, "1146967349": {"name": "24: Ring", "category": "Rings", "platform": "Console"}, "1146967350": {"name": "25: Ring", "category": "Rings", "platform": "Console"}, "1818597029": {"name": "Art Test Ring 1", "category": "Rings", "platform": "Console"}, "1818597030": {"name": "Art Test Ring 2", "category": "Rings", "platform": "Console"}, "1818597031": {"name": "Art Test Ring 3", "category": "Rings", "platform": "Console"}, "1818597032": {"name": "Art Test Ring 4", "category": "Rings", "platform": "Console"}, "1818597033": {"name": "Art Test Ring 5", "category": "Rings", "platform": "Console"}, "-1149557626": {"name": "Legendary: Avarice Band", "category": "Rings", "platform": "Console"}, "-1188944578": {"name": "Legendary: Band of Hollow Whispers", "category": "Rings", "platform": "Console"}, "-580542710": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-580540266": {"name": "Legendary: Band of Hollow Whispers (Legacy)", "category": "Rings", "platform": "Console"}, "-731577034": {"name": "Legendary: Band of Hollow Whispers (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188657082": {"name": "Legendary: Band of Untold Secrets", "category": "Rings", "platform": "Console"}, "-571055342": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-571052898": {"name": "Legendary: Band of Untold Secrets (Legacy)", "category": "Rings", "platform": "Console"}, "-731577026": {"name": "Legendary: Band of Untold Secrets (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149629500": {"name": "Legendary: Band of the Rue Chambers", "category": "Rings", "platform": "Console"}, "-1188764893": {"name": "Legendary: Broken Promises", "category": "Rings", "platform": "Console"}, "-574613105": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-574610661": {"name": "Legendary: Broken Promises (Legacy)", "category": "Rings", "platform": "Console"}, "-731577029": {"name": "Legendary: Broken Promises (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186608673": {"name": "Legendary: Bul-Kathos's Wedding Band", "category": "Rings", "platform": "Console"}, "-503457845": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-503455401": {"name": "Legendary: Bul-Kathos's Wedding Band (Legacy)", "category": "Rings", "platform": "Console"}, "-731576969": {"name": "Legendary: Bul-Kathos's Wedding Band (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188728956": {"name": "Legendary: Eternal Union", "category": "Rings", "platform": "Console"}, "-573427184": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-573424740": {"name": "Legendary: Eternal Union (Legacy)", "category": "Rings", "platform": "Console"}, "-731577028": {"name": "Legendary: Eternal Union (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188729220": {"name": "Legendary: Eternal Union (Patch 2.1.0)", "category": "Rings", "platform": "Console"}, "-1149665437": {"name": "Legendary: Gamuel's Deceit", "category": "Rings", "platform": "Console"}, "425752007": {"name": "Legendary: Halo Of Arlyse (Patch 2.1.2)", "category": "Rings", "platform": "Console"}, "-1186464925": {"name": "Legendary: Hellfire Ring", "category": "Rings", "platform": "Console"}, "-498714161": {"name": "Legendary: Hellfire Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-578170868": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-578168424": {"name": "Legendary: Hierophant's Seal (Legacy)", "category": "Rings", "platform": "Console"}, "-731577032": {"name": "Legendary: Hierophant's Seal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188693019": {"name": "Legendary: Justice Lantern", "category": "Rings", "platform": "Console"}, "-572241263": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-572238819": {"name": "Legendary: Justice Lantern (Legacy)", "category": "Rings", "platform": "Console"}, "-731577027": {"name": "Legendary: Justice Lantern (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188872704": {"name": "Legendary: Krede's Flame", "category": "Rings", "platform": "Console"}, "1963121073": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-159638916": {"name": "Legendary: Leah's Ring (PS3 Promo)", "category": "Rings", "platform": "Console"}, "-1188908641": {"name": "Legendary: Leoric's Signet", "category": "Rings", "platform": "Console"}, "-579356789": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-579354345": {"name": "Legendary: Leoric's Signet (Legacy)", "category": "Rings", "platform": "Console"}, "-731577033": {"name": "Legendary: Leoric's Signet (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186572736": {"name": "Legendary: Manald Heal", "category": "Rings", "platform": "Console"}, "-502271924": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-502269480": {"name": "Legendary: Manald Heal (Legacy)", "category": "Rings", "platform": "Console"}, "-731576968": {"name": "Legendary: Manald Heal (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187507098": {"name": "Legendary: Nagelring", "category": "Rings", "platform": "Console"}, "-533105870": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-533103426": {"name": "Legendary: Nagelring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576994": {"name": "Legendary: Nagelring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1186500862": {"name": "Legendary: Obsidian Ring of the Zodiac", "category": "Rings", "platform": "Console"}, "-499900082": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-499897638": {"name": "Legendary: Obsidian Ring of the Zodiac (Legacy)", "category": "Rings", "platform": "Console"}, "-731576966": {"name": "Legendary: Obsidian Ring of the Zodiac (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187543035": {"name": "Legendary: Oculus Ring", "category": "Rings", "platform": "Console"}, "-534291791": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-534289347": {"name": "Legendary: Oculus Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731576995": {"name": "Legendary: Oculus Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149521689": {"name": "Legendary: Pandemonium Loop", "category": "Rings", "platform": "Console"}, "-1188836767": {"name": "Legendary: Puzzle Ring", "category": "Rings", "platform": "Console"}, "-576984947": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-576982503": {"name": "Legendary: Puzzle Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577031": {"name": "Legendary: Puzzle Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149701374": {"name": "Legendary: Rechel's Ring of Larceny", "category": "Rings", "platform": "Console"}, "-1149593563": {"name": "Legendary: Ring of Royal Grandeur", "category": "Rings", "platform": "Console"}, "-1149737311": {"name": "Legendary: Rogar's Huge Stone", "category": "Rings", "platform": "Console"}, "-611901958": {"name": "Legendary: Signet Ring of the Blizzard", "category": "Rings", "platform": "Console"}, "-1186536799": {"name": "Legendary: Skull Grasp", "category": "Rings", "platform": "Console"}, "-501086003": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-501083559": {"name": "Legendary: Skull Grasp (Legacy)", "category": "Rings", "platform": "Console"}, "-731576967": {"name": "Legendary: Skull Grasp (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1188800830": {"name": "Legendary: Stolen Ring", "category": "Rings", "platform": "Console"}, "-575799026": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-575796582": {"name": "Legendary: Stolen Ring (Legacy)", "category": "Rings", "platform": "Console"}, "-731577030": {"name": "Legendary: Stolen Ring (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187471161": {"name": "Legendary: Stone of Jordan", "category": "Rings", "platform": "Console"}, "-531919949": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-531917505": {"name": "Legendary: Stone of Jordan (Legacy)", "category": "Rings", "platform": "Console"}, "-731576993": {"name": "Legendary: Stone of Jordan (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149809185": {"name": "Legendary: The Tall Man's Finger", "category": "Rings", "platform": "Console"}, "-1187794594": {"name": "Legendary: Unity", "category": "Rings", "platform": "Console"}, "-542593238": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-542590794": {"name": "Legendary: Unity (Legacy)", "category": "Rings", "platform": "Console"}, "-731577002": {"name": "Legendary: Unity (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1149773248": {"name": "Legendary: Wyrdward", "category": "Rings", "platform": "Console"}, "-1585363882": {"name": "P1_Ring_001 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363881": {"name": "P1_Ring_002 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363880": {"name": "P1_Ring_003 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1585363879": {"name": "P1_Ring_004 (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "2082266421": {"name": "PvP: Echo Band All", "category": "Rings", "platform": "Console"}, "2082266693": {"name": "PvP: Echo Band Attack", "category": "Rings", "platform": "Console"}, "2082269451": {"name": "PvP: Echo Band Defense", "category": "Rings", "platform": "Console"}, "-4139386": {"name": "PvP: Echo Band Precision", "category": "Rings", "platform": "Console"}, "2082289199": {"name": "PvP: Echo Band Vitality", "category": "Rings", "platform": "Console"}, "-3897388": {"name": "PvP: Echo Band Willpower", "category": "Rings", "platform": "Console"}, "-2095294696": {"name": "PvP: Sherman Signet All", "category": "Rings", "platform": "Console"}, "-2095294424": {"name": "PvP: Sherman Signet Attack", "category": "Rings", "platform": "Console"}, "-2095291666": {"name": "PvP: Sherman Signet Defense", "category": "Rings", "platform": "Console"}, "-424702775": {"name": "PvP: Sherman Signet Precision", "category": "Rings", "platform": "Console"}, "-2095271918": {"name": "PvP: Sherman Signet Vitality", "category": "Rings", "platform": "Console"}, "-731576997": {"name": "Set: Band of Fallen Heroes (Old-Legacy)", "category": "Rings", "platform": "Console"}, "1978116233": {"name": "Set: Focus", "category": "Rings", "platform": "Console"}, "-1187614909": {"name": "Set: Litany of the Undaunted", "category": "Rings", "platform": "Console"}, "-536663633": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-536661189": {"name": "Set: Litany of the Undaunted (Legacy)", "category": "Rings", "platform": "Console"}, "-731577001": {"name": "Set: Natalya's Mark (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187758657": {"name": "Set: Natalya's Reflection", "category": "Rings", "platform": "Console"}, "-541407317": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "-541404873": {"name": "Set: Natalya's Reflection (Legacy)", "category": "Rings", "platform": "Console"}, "1978152170": {"name": "Set: Restraint", "category": "Rings", "platform": "Console"}, "-731576998": {"name": "Set: Screaming Chain (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187686783": {"name": "Set: The Compass Rose", "category": "Rings", "platform": "Console"}, "-539035475": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-539033031": {"name": "Set: The Compass Rose (Legacy)", "category": "Rings", "platform": "Console"}, "-1187650846": {"name": "Set: The Wailing Host", "category": "Rings", "platform": "Console"}, "-537849554": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-537847110": {"name": "Set: The Wailing Host (Legacy)", "category": "Rings", "platform": "Console"}, "-731576999": {"name": "Set: Wanderlust (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-731577000": {"name": "Set: Zunimassa's Plague (Old-Legacy)", "category": "Rings", "platform": "Console"}, "-1187722720": {"name": "Set: Zunimassa's Pox", "category": "Rings", "platform": "Console"}, "-540221396": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "-540218952": {"name": "Set: Zunimassa's Pox (Legacy)", "category": "Rings", "platform": "Console"}, "417069417": {"name": "legendary: Arcstone (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1188765156": {"name": "legendary: Broken Promises (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069418": {"name": "legendary: Convention Of Elements (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187507361": {"name": "legendary: Nagelring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1187543298": {"name": "legendary: Oculus Ring (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149521952": {"name": "legendary: Pandemonium Loop (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1186501125": {"name": "legendary: Ring of the Zodiac (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069415": {"name": "legendary: Skull Grasp (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "417069416": {"name": "legendary: The Short Man's Finger (Patch 2.2.0)", "category": "Rings", "platform": "Console"}, "-1149773511": {"name": "legendary: Wyrdward (Patch 2.2.0)", "category": "Rings", "platform": "Console"}}, "Scoundrel Tokens": {"-229902048": {"name": "02: Glass Blade", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900960": {"name": "03: Loaded Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900959": {"name": "04: Crystal Edge", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900958": {"name": "05: Clasp", "category": "Scoundrel Tokens", "platform": "Console"}, "-229900957": {"name": "06: Sand Pouch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899871": {"name": "07: Bone Dice", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899870": {"name": "08: Diamond Razor", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899869": {"name": "09: Brooch", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899868": {"name": "10: Dust Satchel", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899867": {"name": "11: Hazard", "category": "Scoundrel Tokens", "platform": "Console"}, "-229899866": {"name": "12: Stinger", "category": "Scoundrel Tokens", "platform": "Console"}, "978821514": {"name": "Legendary: Ribald Etchings", "category": "Scoundrel Tokens", "platform": "Console"}, "978821513": {"name": "Legendary: Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}, "978821515": {"name": "Legendary: Slipka's Letter Opener", "category": "Scoundrel Tokens", "platform": "Console"}, "-978821513": {"name": "Legendary:Skeleton Key", "category": "Scoundrel Tokens", "platform": "Console"}}, "Shields": {"1815806857": {"name": "01: Buckler (AR 8-9)", "category": "Shields", "platform": "Console"}, "1815806858": {"name": "02: Targe Shield (AR 48-55)", "category": "Shields", "platform": "Console"}, "1815806859": {"name": "03: Heater Shield (AR 88-101)", "category": "Shields", "platform": "Console"}, "1815806860": {"name": "04: Kite Shield (AR 128-167)", "category": "Shields", "platform": "Console"}, "1815806861": {"name": "05: Large Shield (AR 168-199)", "category": "Shields", "platform": "Console"}, "1815806862": {"name": "06: Gothic Shield (AR 200-223)", "category": "Shields", "platform": "Console"}, "1815806863": {"name": "07: Tower Shield (AR 224-255)", "category": "Shields", "platform": "Console"}, "1815807946": {"name": "08: Pelta (AR 256-319)", "category": "Shields", "platform": "Console"}, "1815807947": {"name": "09: Rondache (AR 320-383)", "category": "Shields", "platform": "Console"}, "1815807948": {"name": "10: Knight Shield (AR 384-447)", "category": "Shields", "platform": "Console"}, "1815807949": {"name": "11: Ironwood Shield (AR 448-511)", "category": "Shields", "platform": "Console"}, "1815807950": {"name": "12: Pavise (AR 512-579)", "category": "Shields", "platform": "Console"}, "1815807951": {"name": "13: Bone Shield (AR 580-619)", "category": "Shields", "platform": "Console"}, "1815807952": {"name": "14: Savior (AR 620-659)", "category": "Shields", "platform": "Console"}, "1815809035": {"name": "15: Aspis (AR 660-699)", "category": "Shields", "platform": "Console"}, "1815809036": {"name": "16: Hoplon (AR 700-739)", "category": "Shields", "platform": "Console"}, "1815809037": {"name": "17: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "-335464095": {"name": "17b: Defender (AR 740-759)", "category": "Shields", "platform": "Console"}, "1815809038": {"name": "18: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "-334278174": {"name": "18b: Scutum (AR 760-859)", "category": "Shields", "platform": "Console"}, "1815809039": {"name": "19: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "-333092253": {"name": "19b: Aegis (AR 860-959)", "category": "Shields", "platform": "Console"}, "1815809040": {"name": "20: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "-331906332": {"name": "20b: Dread Shield (AR 960-1059)", "category": "Shields", "platform": "Console"}, "1815809041": {"name": "21: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "-330720411": {"name": "21b: Sacred Shield (AR 1060-1219)", "category": "Shields", "platform": "Console"}, "1815809042": {"name": "22: Rakkisgard Shield (AR 1260-1759)", "category": "Shields", "platform": "Console"}, "1815809043": {"name": "23: Ascended Shield (AR 1760-2024)", "category": "Shields", "platform": "Console"}, "-1347979730": {"name": "Art Test Shield 1", "category": "Shields", "platform": "Console"}, "-1347979729": {"name": "Art Test Shield 2", "category": "Shields", "platform": "Console"}, "-1347979728": {"name": "Art Test Shield 3", "category": "Shields", "platform": "Console"}, "-1347979727": {"name": "Art Test Shield 4", "category": "Shields", "platform": "Console"}, "-1347979726": {"name": "Art Test Shield 5", "category": "Shields", "platform": "Console"}, "200412170": {"name": "Legendary: Amazonian Parma", "category": "Shields", "platform": "Console"}, "200519981": {"name": "Legendary: Beastguard", "category": "Shields", "platform": "Console"}, "1028274966": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "1028277410": {"name": "Legendary: Centurion (Legacy)", "category": "Shields", "platform": "Console"}, "-64652478": {"name": "Legendary: Centurion (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200555918": {"name": "Legendary: Coven's Criterion", "category": "Shields", "platform": "Console"}, "200340296": {"name": "Legendary: Defender of Westmarch", "category": "Shields", "platform": "Console"}, "161420525": {"name": "Legendary: Denial", "category": "Shields", "platform": "Console"}, "1031832729": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "1031835173": {"name": "Legendary: Denial (Legacy)", "category": "Shields", "platform": "Console"}, "-64652475": {"name": "Legendary: Denial (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200376233": {"name": "Legendary: Eberli Charo", "category": "Shields", "platform": "Console"}, "161312714": {"name": "Legendary: Freeze of Deflection", "category": "Shields", "platform": "Console"}, "161240840": {"name": "Legendary: Ivory Tower", "category": "Shields", "platform": "Console"}, "1025903124": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "1025905568": {"name": "Legendary: Ivory Tower (Legacy)", "category": "Shields", "platform": "Console"}, "-64652480": {"name": "Legendary: Ivory Tower (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161456462": {"name": "Legendary: Lidless Wall", "category": "Shields", "platform": "Console"}, "1033018650": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "1033021094": {"name": "Legendary: Lidless Wall (Legacy)", "category": "Shields", "platform": "Console"}, "-64652474": {"name": "Legendary: Lidless Wall (Old-Legacy)", "category": "Shields", "platform": "Console"}, "161492399": {"name": "Legendary: Stormshield", "category": "Shields", "platform": "Console"}, "1034204571": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "1034207015": {"name": "Legendary: Stormshield (Legacy)", "category": "Shields", "platform": "Console"}, "-64652473": {"name": "Legendary: Stormshield (Old-Legacy)", "category": "Shields", "platform": "Console"}, "200448107": {"name": "Legendary: Vo'Toyias Spiker", "category": "Shields", "platform": "Console"}, "1063852596": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "1063855040": {"name": "Legendary: Wall of Bone (Legacy)", "category": "Shields", "platform": "Console"}, "-64652448": {"name": "Legendary: Wall of Bone (Old-Legacy)", "category": "Shields", "platform": "Console"}, "162390824": {"name": "Legendary: Wall of Man", "category": "Shields", "platform": "Console"}, "200484044": {"name": "Legendary: Wretchskin", "category": "Shields", "platform": "Console"}, "162426761": {"name": "Set: Hallowed Barricade", "category": "Shields", "platform": "Console"}, "-64652447": {"name": "Set: Hallowed Barrier (Old-Legacy)", "category": "Shields", "platform": "Console"}, "1065038517": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "1065040961": {"name": "Set: Hallowed Defender (Legacy)", "category": "Shields", "platform": "Console"}, "200340033": {"name": "legendary: Defender Of Westmarch (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509030": {"name": "legendary: Denial (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "841509025": {"name": "legendary: Ivory Tower (Patch 2.2.0)", "category": "Shields", "platform": "Console"}, "-519190663": {"name": "legendary: Stormshield (Patch 2.2.0)", "category": "Shields", "platform": "Console"}}, "Shoulders": {"365490251": {"name": "03: Shoulder Guards (AR 48-58)", "category": "Shoulders", "platform": "Console"}, "365490252": {"name": "04: Amice (AR 58-68)", "category": "Shoulders", "platform": "Console"}, "365490253": {"name": "05: Spaulders (AR 69-79)", "category": "Shoulders", "platform": "Console"}, "365490254": {"name": "06: Shoulder Plates (AR 80-100)", "category": "Shoulders", "platform": "Console"}, "365491338": {"name": "07: Etched Mantle (AR 101-121)", "category": "Shoulders", "platform": "Console"}, "365491339": {"name": "08: Ailettes (AR 122-142)", "category": "Shoulders", "platform": "Console"}, "365491340": {"name": "09: Pauldrons (AR 144-164)", "category": "Shoulders", "platform": "Console"}, "365491341": {"name": "10: Sode (AR 165-199)", "category": "Shoulders", "platform": "Console"}, "365491342": {"name": "11: Epaulets (AR 200-219)", "category": "Shoulders", "platform": "Console"}, "365492427": {"name": "12: Balor Pauldrons (AR 220-239)", "category": "Shoulders", "platform": "Console"}, "365492428": {"name": "13: Espaliers (AR 240-252)", "category": "Shoulders", "platform": "Console"}, "365492429": {"name": "14: Warlord Spaulders (AR 253-285)", "category": "Shoulders", "platform": "Console"}, "365492430": {"name": "15: Doom Pauldrons (AR 286-318)", "category": "Shoulders", "platform": "Console"}, "365492431": {"name": "16: Pallium (AR 320-352)", "category": "Shoulders", "platform": "Console"}, "365492432": {"name": "17: Archon Spaulders (AR 353-419)", "category": "Shoulders", "platform": "Console"}, "365492433": {"name": "18: Rakkisgard Pauldrons (AR 420-586)", "category": "Shoulders", "platform": "Console"}, "365492434": {"name": "19: Ascended Pauldrons (AR 586-674)", "category": "Shoulders", "platform": "Console"}, "-1869550021": {"name": "Art Test Shoulder 1", "category": "Shoulders", "platform": "Console"}, "-1869550020": {"name": "Art Test Shoulder 2", "category": "Shoulders", "platform": "Console"}, "-1869550019": {"name": "Art Test Shoulder 3", "category": "Shoulders", "platform": "Console"}, "-1869550018": {"name": "Art Test Shoulder 4", "category": "Shoulders", "platform": "Console"}, "-1869550017": {"name": "Art Test Shoulder 5", "category": "Shoulders", "platform": "Console"}, "-1565608501": {"name": "Art_Test_Shoulder_10 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608500": {"name": "Art_Test_Shoulder_11 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1565608499": {"name": "Art_Test_Shoulder_12 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550016": {"name": "Art_Test_Shoulder_6 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550015": {"name": "Art_Test_Shoulder_7 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550014": {"name": "Art_Test_Shoulder_8 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1869550013": {"name": "Art_Test_Shoulder_9 (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-248496224": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "-248493780": {"name": "Legendary: Barter Town Pads (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734028": {"name": "Legendary: Barter Town Pads (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "2112365407": {"name": "Legendary: Burdens of the Brave Survivor", "category": "Shoulders", "platform": "Console"}, "1902294393": {"name": "Legendary: Conqueror's Pauldrons (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1959570086": {"name": "Legendary: Corruption", "category": "Shoulders", "platform": "Console"}, "-1959749771": {"name": "Legendary: Death Watch Mantle", "category": "Shoulders", "platform": "Console"}, "-247310303": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "-247307859": {"name": "Legendary: Death Watch Mantle (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734029": {"name": "Legendary: Death Watch Mantle (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959785708": {"name": "Legendary: Homing Pads", "category": "Shoulders", "platform": "Console"}, "507255184": {"name": "Legendary: Infernal Pauldrons", "category": "Shoulders", "platform": "Console"}, "-1920578441": {"name": "Legendary: Pauldrons of the Skeleton King", "category": "Shoulders", "platform": "Console"}, "-1920650315": {"name": "Legendary: Profane Pauldrons", "category": "Shoulders", "platform": "Console"}, "-241380698": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "-241378254": {"name": "Legendary: Seven Sins (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734034": {"name": "Legendary: Seven Sins (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1920614378": {"name": "Legendary: Spaulders of Zakara", "category": "Shoulders", "platform": "Console"}, "1277749690": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-419021771": {"name": "Legendary: The Hero's Journey (PS3 Promo)", "category": "Shoulders", "platform": "Console"}, "-1959713834": {"name": "Legendary: Vile Ward", "category": "Shoulders", "platform": "Console"}, "-246124382": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "-246121938": {"name": "Legendary: Vile Ward (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734030": {"name": "Legendary: Vile Ward (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959714098": {"name": "Legendary: Vile Ward (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1958384165": {"name": "Set: Asheara's Custodian", "category": "Shoulders", "platform": "Console"}, "-202245305": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "-202242861": {"name": "Set: Asheara's Guard (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734067": {"name": "Set: Asheara's Vigilance (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959534149": {"name": "Set: Aughild's Power", "category": "Shoulders", "platform": "Console"}, "-240194777": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "-240192333": {"name": "Set: Aughild's Reign (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734035": {"name": "Set: Aughild's Triumph (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-242566619": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "-242564175": {"name": "Set: Born's Impunity (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734033": {"name": "Set: Born's Pauldrons (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1959606023": {"name": "Set: Born's Privilege", "category": "Shoulders", "platform": "Console"}, "-1980689583": {"name": "Set: Burden of the Invoker", "category": "Shoulders", "platform": "Console"}, "-1981839829": {"name": "Set: Crusader Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875767": {"name": "Set: Dashing Pauldrons of Despair (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959498212": {"name": "Set: Demon's Aileron", "category": "Shoulders", "platform": "Console"}, "-239008856": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "-239006412": {"name": "Set: Demon's Flight (Legacy)", "category": "Shoulders", "platform": "Console"}, "238734036": {"name": "Set: Demon's Wings (Old-Legacy)", "category": "Shoulders", "platform": "Console"}, "-1981731756": {"name": "Set: Firebird's Pinions", "category": "Shoulders", "platform": "Console"}, "-1980545835": {"name": "Set: Helltooth Mantle", "category": "Shoulders", "platform": "Console"}, "-1981623945": {"name": "Set: Jade Harvester's Joy", "category": "Shoulders", "platform": "Console"}, "-1981659882": {"name": "Set: Mantle of the Upside-Down Sinners", "category": "Shoulders", "platform": "Console"}, "-1981695819": {"name": "Set: Marauder's Spines", "category": "Shoulders", "platform": "Console"}, "-1981911703": {"name": "Set: Monk Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1980761457": {"name": "Set: Pauldrons of Akkhan", "category": "Shoulders", "platform": "Console"}, "-1981911704": {"name": "Set: Pauldrons of the Wastes (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981767693": {"name": "Set: Raekor's Burden", "category": "Shoulders", "platform": "Console"}, "-1981911705": {"name": "Set: Roland's Mantle (Patch 2.1.0)", "category": "Shoulders", "platform": "Console"}, "-1980581772": {"name": "Set: Spires of the Earth", "category": "Shoulders", "platform": "Console"}, "-1980725520": {"name": "Set: Sunwuko's Balance", "category": "Shoulders", "platform": "Console"}, "-1981839830": {"name": "Set: Unsanctified Shoulders (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1981875766": {"name": "Set: Witch Doctor Set (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1959750034": {"name": "legendary: Death Watch Mantle (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}, "-1449741837": {"name": "legendary: Pauldrons of the Hierarch (Patch 2.2.0)", "category": "Shoulders", "platform": "Console"}}, "Sources": {"1905179476": {"name": "02: Spellbook (+(2-3)-(3-5) DMG)", "category": "Sources", "platform": "Console"}, "1905179477": {"name": "03: Smoked Spheres (+(3-5)-(4-8) DMG)", "category": "Sources", "platform": "Console"}, "1905179478": {"name": "04: Cursed Skull (+(3-6)-(4-10) DMG)", "category": "Sources", "platform": "Console"}, "1905180564": {"name": "05: Sanctuary Globe (+(4-8)-(5-13) DMG)", "category": "Sources", "platform": "Console"}, "1905180565": {"name": "06: Fiendish Folio (+(6-11)-(7-19) DMG)", "category": "Sources", "platform": "Console"}, "1905180566": {"name": "07: Triad (+(8-16)-(9-29) DMG)", "category": "Sources", "platform": "Console"}, "1905180567": {"name": "08: Screaming Skull (+(13-26)-(14-45) DMG)", "category": "Sources", "platform": "Console"}, "1905181653": {"name": "09: Power Sphere (+(17-39)-(18-114) DMG)", "category": "Sources", "platform": "Console"}, "1905181654": {"name": "10: Codex (+(19-58)-(20-213) DMG)", "category": "Sources", "platform": "Console"}, "1905181655": {"name": "11: Orbit Stones (+(24-72)-(25-265) DMG)", "category": "Sources", "platform": "Console"}, "1905181656": {"name": "12: Demi Lich (+(28-110)-(29-405) DMG)", "category": "Sources", "platform": "Console"}, "1905181657": {"name": "13: Puzzle Box (+(126-158)-(127-190) DMG)", "category": "Sources", "platform": "Console"}, "1905181658": {"name": "14: Moschen Spheres (+(262-328)-(263-394) DMG)", "category": "Sources", "platform": "Console"}, "702613912": {"name": "Art Test Orb 1", "category": "Sources", "platform": "Console"}, "702613913": {"name": "Art Test Orb 2", "category": "Sources", "platform": "Console"}, "702613914": {"name": "Art Test Orb 3", "category": "Sources", "platform": "Console"}, "702613915": {"name": "Art Test Orb 4", "category": "Sources", "platform": "Console"}, "702613916": {"name": "Art Test Orb 5", "category": "Sources", "platform": "Console"}, "-1519116524": {"name": "Legendary: Cosmic Strand", "category": "Sources", "platform": "Console"}, "2028438506": {"name": "Legendary: Gul'dan's Secret (Patch 2.1.0)", "category": "Sources", "platform": "Console"}, "-1934140787": {"name": "Legendary: Heart of Darkness", "category": "Sources", "platform": "Console"}, "-1480017068": {"name": "Legendary: Light of Grace", "category": "Sources", "platform": "Console"}, "-1480088942": {"name": "Legendary: Mirrorball", "category": "Sources", "platform": "Console"}, "-1480053005": {"name": "Legendary: Myken's Ball of Hate", "category": "Sources", "platform": "Console"}, "1408684960": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "1408687404": {"name": "Legendary: Singularity (Legacy)", "category": "Sources", "platform": "Console"}, "215441100": {"name": "Legendary: Singularity (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519224335": {"name": "Legendary: The Oculus", "category": "Sources", "platform": "Console"}, "1405127197": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "1405129641": {"name": "Legendary: The Oculus (Legacy)", "category": "Sources", "platform": "Console"}, "215441097": {"name": "Legendary: The Oculus (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519152461": {"name": "Legendary: Triumvirate", "category": "Sources", "platform": "Console"}, "1407499039": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "1407501483": {"name": "Legendary: Triumvirate (Legacy)", "category": "Sources", "platform": "Console"}, "215441099": {"name": "Legendary: Triumvirate (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1519080587": {"name": "Legendary: Winter Flurry", "category": "Sources", "platform": "Console"}, "1409870881": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "1409873325": {"name": "Legendary: Winter Flurry (Legacy)", "category": "Sources", "platform": "Console"}, "215441101": {"name": "Legendary: Winter Flurry (Old-Legacy)", "category": "Sources", "platform": "Console"}, "215441130": {"name": "Set: Chantodo's Elemental Seal (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518038414": {"name": "Set: Chantodo's Force", "category": "Sources", "platform": "Console"}, "1444262590": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "1444265034": {"name": "Set: Chantodo's Force (Legacy)", "category": "Sources", "platform": "Console"}, "-777123311": {"name": "Set: Firebird's Eye", "category": "Sources", "platform": "Console"}, "215441131": {"name": "Set: Tal Rasha's Lidless Eye (Old-Legacy)", "category": "Sources", "platform": "Console"}, "-1518002477": {"name": "Set: Tal Rasha's Unwavering Glare", "category": "Sources", "platform": "Console"}, "1445448511": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1445450955": {"name": "Set: Tal Rasha's Unwavering Glare (Legacy)", "category": "Sources", "platform": "Console"}, "1175281612": {"name": "legendary: Triumvirate (Patch 2.2.0)", "category": "Sources", "platform": "Console"}}, "Spears": {"-101312756": {"name": "02: Fuscina (DPS 12.6-14.4)", "category": "Spears", "platform": "Console"}, "-101312755": {"name": "03: Spear (DPS 18.6-20.4)", "category": "Spears", "platform": "Console"}, "-101312754": {"name": "04: Hasta (DPS 24.6-26.4)", "category": "Spears", "platform": "Console"}, "-101312753": {"name": "05: Pilum (DPS 32.4-34.2)", "category": "Spears", "platform": "Console"}, "-101311668": {"name": "06: Angon (DPS 38.4-40.2)", "category": "Spears", "platform": "Console"}, "-101311667": {"name": "07: Assegai (DPS 48.6-50.4)", "category": "Spears", "platform": "Console"}, "-101311666": {"name": "08: War Spear (DPS 60.6-62.4)", "category": "Spears", "platform": "Console"}, "-101311665": {"name": "09: Spontoon (DPS 84.6-88.2)", "category": "Spears", "platform": "Console"}, "-101311664": {"name": "10: Yari (DPS 127.8-133.2)", "category": "Spears", "platform": "Console"}, "-101310579": {"name": "11: Harpoon (DPS 151.8-157.2)", "category": "Spears", "platform": "Console"}, "-101310578": {"name": "12: Impaler (DPS 178.2-185.4)", "category": "Spears", "platform": "Console"}, "-101310577": {"name": "13: Qiang (DPS 230.4-239.4)", "category": "Spears", "platform": "Console"}, "-101310576": {"name": "14: Vel (DPS 268.2-277.2)", "category": "Spears", "platform": "Console"}, "-101310575": {"name": "15: Centurion Spear (DPS 311.4-320.4)", "category": "Spears", "platform": "Console"}, "-101309490": {"name": "16: Honed Spear (DPS 419.4-428.4)", "category": "Spears", "platform": "Console"}, "-101309489": {"name": "17: Disemboweler (DPS 527.4-536.4)", "category": "Spears", "platform": "Console"}, "1438708880": {"name": "Art Test Spear 1", "category": "Spears", "platform": "Console"}, "1438708881": {"name": "Art Test Spear 2", "category": "Spears", "platform": "Console"}, "1438708882": {"name": "Art Test Spear 3", "category": "Spears", "platform": "Console"}, "1438708883": {"name": "Art Test Spear 4", "category": "Spears", "platform": "Console"}, "1438708884": {"name": "Art Test Spear 5", "category": "Spears", "platform": "Console"}, "-2120824630": {"name": "Legendary: Akanesh, the Herald of Righteousness", "category": "Spears", "platform": "Console"}, "2135007273": {"name": "Legendary: Arreat's Law", "category": "Spears", "platform": "Console"}, "1735685973": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "1735688417": {"name": "Legendary: Arreat's Law (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403711": {"name": "Legendary: Arreat's Law (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135079147": {"name": "Legendary: Empyrean Messenger", "category": "Spears", "platform": "Console"}, "1738057815": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "1738060259": {"name": "Legendary: Empyrean Messenger (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403709": {"name": "Legendary: Empyrean Messenger (Old-Legacy)", "category": "Spears", "platform": "Console"}, "2135115084": {"name": "Legendary: Scrimshaw", "category": "Spears", "platform": "Console"}, "1739243736": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "1739246180": {"name": "Legendary: Scrimshaw (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403708": {"name": "Legendary: Scrimshaw (Old-Legacy)", "category": "Spears", "platform": "Console"}, "-2120788693": {"name": "Legendary: Steffon's Heavy Lance", "category": "Spears", "platform": "Console"}, "2135043210": {"name": "Legendary: The Three Hundredth Spear", "category": "Spears", "platform": "Console"}, "1736871894": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "1736874338": {"name": "Legendary: The Three Hundredth Spear (Legacy)", "category": "Spears", "platform": "Console"}, "-1980403710": {"name": "Legendary: The Three Hundredth Spear (Old-Legacy)", "category": "Spears", "platform": "Console"}}, "Spirit Stones": {"-242895467": {"name": "02: Thought Mirror (AR 36-41)", "category": "Spirit Stones", "platform": "Console"}, "-242895466": {"name": "03: Third Eye (AR 60-69)", "category": "Spirit Stones", "platform": "Console"}, "-242895465": {"name": "04: Onyx Cluster (AR 84-113)", "category": "Spirit Stones", "platform": "Console"}, "-242894379": {"name": "05: Sunstone (AR 114-149)", "category": "Spirit Stones", "platform": "Console"}, "-242894378": {"name": "06: Prism (AR 150-185)", "category": "Spirit Stones", "platform": "Console"}, "-242894377": {"name": "07: Seer Shard (AR 186-232)", "category": "Spirit Stones", "platform": "Console"}, "-242894376": {"name": "08: Igneous Studs (AR 232-254)", "category": "Spirit Stones", "platform": "Console"}, "-242893290": {"name": "09: Solarius (AR 255-284)", "category": "Spirit Stones", "platform": "Console"}, "-242893289": {"name": "10: Meditator (AR 285-322)", "category": "Spirit Stones", "platform": "Console"}, "-242893288": {"name": "11: Ghost Sight (AR 322-359)", "category": "Spirit Stones", "platform": "Console"}, "-242893287": {"name": "12: Star Crown (AR 360-472)", "category": "Spirit Stones", "platform": "Console"}, "-242893286": {"name": "13: Insight Stone (AR 472-659)", "category": "Spirit Stones", "platform": "Console"}, "-242893285": {"name": "14: Ascended Stone (AR 660-759)", "category": "Spirit Stones", "platform": "Console"}, "113759385": {"name": "Art Test SpiritStone 1", "category": "Spirit Stones", "platform": "Console"}, "113759386": {"name": "Art Test SpiritStone 2", "category": "Spirit Stones", "platform": "Console"}, "113759387": {"name": "Art Test SpiritStone 3", "category": "Spirit Stones", "platform": "Console"}, "113759388": {"name": "Art Test SpiritStone 4", "category": "Spirit Stones", "platform": "Console"}, "113759389": {"name": "Art Test SpiritStone 5", "category": "Spirit Stones", "platform": "Console"}, "635580050": {"name": "Legendary: Bezoar Stone", "category": "Spirit Stones", "platform": "Console"}, "-500772130": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-500769686": {"name": "Legendary: Bezoar Stone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225226": {"name": "Legendary: Bezoar Stone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635651924": {"name": "Legendary: Erlang Shen", "category": "Spirit Stones", "platform": "Console"}, "-498400288": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-498397844": {"name": "Legendary: Erlang Shen (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225228": {"name": "Legendary: Erlang Shen (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674787317": {"name": "Legendary: Eye of Peshkov", "category": "Spirit Stones", "platform": "Console"}, "635687861": {"name": "Legendary: Gyana Na Kashu", "category": "Spirit Stones", "platform": "Console"}, "-497214367": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-497211923": {"name": "Legendary: Gyana Na Kashu (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225229": {"name": "Legendary: Gyana Na Kashu (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674751380": {"name": "Legendary: Kekegi's Unbreakable Spirit", "category": "Spirit Stones", "platform": "Console"}, "635831609": {"name": "Legendary: Madstone", "category": "Spirit Stones", "platform": "Console"}, "-492470683": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-492468239": {"name": "Legendary: Madstone (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225233": {"name": "Legendary: Madstone (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1935108657": {"name": "Legendary: Madstone (Patch 2.1.0)", "category": "Spirit Stones", "platform": "Console"}, "635723798": {"name": "Legendary: See No Evil", "category": "Spirit Stones", "platform": "Console"}, "-496028446": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-496026002": {"name": "Legendary: See No Evil (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225230": {"name": "Legendary: See No Evil (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635759735": {"name": "Legendary: The Eye of the Storm", "category": "Spirit Stones", "platform": "Console"}, "-494842525": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-494840081": {"name": "Legendary: The Eye of the Storm (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225231": {"name": "Legendary: The Eye of the Storm (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "674715443": {"name": "Legendary: The Laws of Seph", "category": "Spirit Stones", "platform": "Console"}, "635615987": {"name": "Legendary: The Mind's Eye", "category": "Spirit Stones", "platform": "Console"}, "-499586209": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-499583765": {"name": "Legendary: The Mind's Eye (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225227": {"name": "Legendary: The Mind's Eye (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635795672": {"name": "Legendary: Tzo Krin's Gaze", "category": "Spirit Stones", "platform": "Console"}, "-493656604": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-493654160": {"name": "Legendary: Tzo Krin's Gaze (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225232": {"name": "Legendary: Tzo Krin's Gaze (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}, "635867546": {"name": "Set: Inna's Radiance", "category": "Spirit Stones", "platform": "Console"}, "-491284762": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "-491282318": {"name": "Set: Inna's Radiance (Legacy)", "category": "Spirit Stones", "platform": "Console"}, "1109225234": {"name": "Set: Inna's Splendor (Old-Legacy)", "category": "Spirit Stones", "platform": "Console"}}, "Staves": {"-2115691355": {"name": "02: Long Staff (DPS 17.0-18.5)", "category": "Staves", "platform": "Console"}, "-2115691354": {"name": "03: Yew Staff (DPS 22.0-23.5)", "category": "Staves", "platform": "Console"}, "-2115691353": {"name": "04: Gnarled Staff (DPS 27.0-28.5)", "category": "Staves", "platform": "Console"}, "-2115691352": {"name": "05: Bone Staff (DPS 33.0-34.5)", "category": "Staves", "platform": "Console"}, "-2115691351": {"name": "06: Battle Staff (DPS 40.5-42.0)", "category": "Staves", "platform": "Console"}, "-2115691350": {"name": "07: War Staff (DPS 50.5-53.5)", "category": "Staves", "platform": "Console"}, "-2115690267": {"name": "08: Mentor Staff (DPS 66.5-69.5)", "category": "Staves", "platform": "Console"}, "-2115690266": {"name": "09: Obsidian Staff (DPS 75.5-78.5)", "category": "Staves", "platform": "Console"}, "-2115690265": {"name": "10: Petrified Staff (DPS 90.0-94.5)", "category": "Staves", "platform": "Console"}, "-2115690264": {"name": "11: Elder Staff (DPS 101.5-106.0)", "category": "Staves", "platform": "Console"}, "-2115690263": {"name": "12: Shamanic Staff (DPS 121.0-127.0)", "category": "Staves", "platform": "Console"}, "-2115690262": {"name": "13: High Priest Staff (DPS 138.5-144.5)", "category": "Staves", "platform": "Console"}, "-2115690261": {"name": "14: Arcane Staff (DPS 174.5-182.0)", "category": "Staves", "platform": "Console"}, "-2115689178": {"name": "15: Hyperion Staff (DPS 204.5-212.0)", "category": "Staves", "platform": "Console"}, "-2115689177": {"name": "16: Stygian Staff (DPS 237.0-246.0)", "category": "Staves", "platform": "Console"}, "-2115689176": {"name": "17: Primordial Staff (DPS 275.5-286.0)", "category": "Staves", "platform": "Console"}, "-2115689175": {"name": "18: Archaic Staff (DPS 320.0-332.0)", "category": "Staves", "platform": "Console"}, "-2115689174": {"name": "19: Conquest Staff (DPS 409.0-421.0)", "category": "Staves", "platform": "Console"}, "-2115689173": {"name": "20: Mythical Staff (DPS 484.0-496.0)", "category": "Staves", "platform": "Console"}, "-2115689172": {"name": "21: Sovereign Staff (DPS 572.5-584.5)", "category": "Staves", "platform": "Console"}, "-2115688089": {"name": "22: Caduceus Staff (DPS 712.3-725.5)", "category": "Staves", "platform": "Console"}, "-2115688088": {"name": "23: Kerykeion (DPS 968.0-981.2)", "category": "Staves", "platform": "Console"}, "-1849507048": {"name": "Art Test CombatStaff Two-Handed 1", "category": "Staves", "platform": "Console"}, "-1849507047": {"name": "Art Test CombatStaff Two-Handed 2", "category": "Staves", "platform": "Console"}, "-1849507046": {"name": "Art Test CombatStaff Two-Handed 3", "category": "Staves", "platform": "Console"}, "-1849507045": {"name": "Art Test CombatStaff Two-Handed 4", "category": "Staves", "platform": "Console"}, "-1849507044": {"name": "Art Test CombatStaff Two-Handed 5", "category": "Staves", "platform": "Console"}, "1590673385": {"name": "Art Test Staff 1", "category": "Staves", "platform": "Console"}, "1590673386": {"name": "Art Test Staff 2", "category": "Staves", "platform": "Console"}, "1590673387": {"name": "Art Test Staff 3", "category": "Staves", "platform": "Console"}, "1590673388": {"name": "Art Test Staff 4", "category": "Staves", "platform": "Console"}, "1590673389": {"name": "Art Test Staff 5", "category": "Staves", "platform": "Console"}, "2065442005": {"name": "Crafted: Elderwood Staff", "category": "Staves", "platform": "Console"}, "-1170762813": {"name": "Legendary: Ahavarion, Spear of Lycander", "category": "Staves", "platform": "Console"}, "-1209646647": {"name": "Legendary: Autumn's Call", "category": "Staves", "platform": "Console"}, "-1263710987": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "-1263708543": {"name": "Legendary: Autumn's Call (Legacy)", "category": "Staves", "platform": "Console"}, "300184993": {"name": "Legendary: Autumn's Call (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-306066026": {"name": "Legendary: Hellish Staff of Herding", "category": "Staves", "platform": "Console"}, "1952916002": {"name": "Legendary: Infernal Staff of Herding", "category": "Staves", "platform": "Console"}, "-1209718521": {"name": "Legendary: Maloth's Focus", "category": "Staves", "platform": "Console"}, "-1266082829": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "-1266080385": {"name": "Legendary: Maloth's Focus (Legacy)", "category": "Staves", "platform": "Console"}, "300184991": {"name": "Legendary: Maloth's Focus (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209862269": {"name": "Legendary: Mark of The Magi", "category": "Staves", "platform": "Console"}, "-1409366405": {"name": "Legendary: Ner'zhul's Staff of Shadowmoon (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "670723600": {"name": "Legendary: Nightmarish Staff of Herding", "category": "Staves", "platform": "Console"}, "-1077364974": {"name": "Legendary: Staff of Herding", "category": "Staves", "platform": "Console"}, "-1170655002": {"name": "Legendary: SuWong Diviner", "category": "Staves", "platform": "Console"}, "-1209898206": {"name": "Legendary: The Broken Staff", "category": "Staves", "platform": "Console"}, "-1272012434": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "-1272009990": {"name": "Legendary: The Broken Staff (Legacy)", "category": "Staves", "platform": "Console"}, "300184986": {"name": "Legendary: The Broken Staff (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610710": {"name": "Legendary: The Grand Vizier", "category": "Staves", "platform": "Console"}, "-1262525066": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "-1262522622": {"name": "Legendary: The Grand Vizier (Legacy)", "category": "Staves", "platform": "Console"}, "300184994": {"name": "Legendary: The Grand Vizier (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1209610974": {"name": "Legendary: The Grand Vizier (Patch 2.1.0)", "category": "Staves", "platform": "Console"}, "-1270826513": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "-1270824069": {"name": "Legendary: The Magi (Legacy)", "category": "Staves", "platform": "Console"}, "300184987": {"name": "Legendary: The Magi (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170690939": {"name": "Legendary: The Smoldering Core", "category": "Staves", "platform": "Console"}, "-1209682584": {"name": "Legendary: The Tormentor", "category": "Staves", "platform": "Console"}, "-1264896908": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "-1264894464": {"name": "Legendary: The Tormentor (Legacy)", "category": "Staves", "platform": "Console"}, "300184992": {"name": "Legendary: The Tormentor (Old-Legacy)", "category": "Staves", "platform": "Console"}, "-1170726876": {"name": "Legendary: Valthek's Rebuke", "category": "Staves", "platform": "Console"}, "-1209826332": {"name": "Legendary: Wormwood", "category": "Staves", "platform": "Console"}, "-1269640592": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "-1269638148": {"name": "Legendary: Wormwood (Legacy)", "category": "Staves", "platform": "Console"}, "300184988": {"name": "Legendary: Wormwood (Old-Legacy)", "category": "Staves", "platform": "Console"}, "1889450717": {"name": "Legendary: Wormwood (Patch 2.1.2)", "category": "Staves", "platform": "Console"}, "-1953260964": {"name": "P2 combatStaff norm Legendary 01", "category": "Staves", "platform": "Console"}, "397178771": {"name": "PvP: Heroic Staff", "category": "Staves", "platform": "Console"}, "397178770": {"name": "PvP: Mighty Staff", "category": "Staves", "platform": "Console"}, "397178769": {"name": "PvP: Staff", "category": "Staves", "platform": "Console"}}, "Swords, One-Handed": {"-270938920": {"name": "02: Sabre (DPS 8.4-10.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938919": {"name": "03: Broadsword (DPS 11.2-13.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938918": {"name": "04: Longsword (DPS 16.1-18.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938917": {"name": "05: Falchion (DPS 20.3-22.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938916": {"name": "06: Scimitar (DPS 24.5-26.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938915": {"name": "07: War Sword (DPS 28.0-30.1)", "category": "Swords, One-Handed", "platform": "Console"}, "-270938914": {"name": "08: Bastard Sword (DPS 32.2-34.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937832": {"name": "09: Gladius (DPS 39.2-41.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937831": {"name": "10: Cutlass (DPS 44.1-46.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937830": {"name": "11: Battle Sword (DPS 48.3-50.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937829": {"name": "12: Knight Sword (DPS 53.2-55.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937828": {"name": "13: Dao (DPS 62.3-64.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937827": {"name": "14: Shamshir (DPS 73.5-75.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937826": {"name": "15: Raid Sword (DPS 81.2-83.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270937825": {"name": "16: Ancient Sword (DPS 93.1-95.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936743": {"name": "17: Spatha (DPS 100.1-104.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936742": {"name": "18: Pirate Sword (DPS 112.0-116.2)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936741": {"name": "19: Strong Sword (DPS 123.2-127.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936740": {"name": "20: King Blade (DPS 137.2-141.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936739": {"name": "21: Tulwar (DPS 151.2-155.4)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936738": {"name": "22: Saif (DPS 181.3-187.6)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936737": {"name": "23: Conquest Sword (DPS 210.0-216.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270936736": {"name": "24: Rune Sword (DPS 242.2-248.5)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935654": {"name": "25: Champion Sword (DPS 322.0-328.3)", "category": "Swords, One-Handed", "platform": "Console"}, "-270935653": {"name": "26: Tsunami Blade (DPS 392.0-398.3)", "category": "Swords, One-Handed", "platform": "Console"}, "1775003964": {"name": "Art Test Sword One-Handed 1", "category": "Swords, One-Handed", "platform": "Console"}, "1775003965": {"name": "Art Test Sword One-Handed 2", "category": "Swords, One-Handed", "platform": "Console"}, "1775003966": {"name": "Art Test Sword One-Handed 3", "category": "Swords, One-Handed", "platform": "Console"}, "1775003967": {"name": "Art Test Sword One-Handed 4", "category": "Swords, One-Handed", "platform": "Console"}, "1775003968": {"name": "Art Test Sword One-Handed 5", "category": "Swords, One-Handed", "platform": "Console"}, "560809999": {"name": "Crafted: Blacksteel Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1351405527": {"name": "Legendary: Amberwing", "category": "Swords, One-Handed", "platform": "Console"}, "1312306071": {"name": "Legendary: Azurewrath", "category": "Swords, One-Handed", "platform": "Console"}, "356350083": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "356352527": {"name": "Legendary: Azurewrath (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242223": {"name": "Legendary: Azurewrath (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351441464": {"name": "Legendary: Deathwish", "category": "Swords, One-Handed", "platform": "Console"}, "1312270134": {"name": "Legendary: Devil Tongue", "category": "Swords, One-Handed", "platform": "Console"}, "355164162": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "355166606": {"name": "Legendary: Devil Tongue (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242222": {"name": "Legendary: Devil Tongue (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312377945": {"name": "Legendary: Doombringer", "category": "Swords, One-Handed", "platform": "Console"}, "358721925": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "358724369": {"name": "Legendary: Doombringer (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242225": {"name": "Legendary: Doombringer (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350255543": {"name": "Legendary: Exarian", "category": "Swords, One-Handed", "platform": "Console"}, "1350327417": {"name": "Legendary: Fulminator", "category": "Swords, One-Handed", "platform": "Console"}, "1350399291": {"name": "Legendary: Ghoul King's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "1350291480": {"name": "Legendary: Gift of Silaria", "category": "Swords, One-Handed", "platform": "Console"}, "1350363354": {"name": "Legendary: God Butcher", "category": "Swords, One-Handed", "platform": "Console"}, "364651530": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "364653974": {"name": "Legendary: Griswold's Masterpiece (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242230": {"name": "Legendary: Griswold's Masterpiece (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1312557630": {"name": "Legendary: Griswold's Perfection", "category": "Swords, One-Handed", "platform": "Console"}, "1311084213": {"name": "Legendary: Griswold's Worn Edge", "category": "Swords, One-Handed", "platform": "Console"}, "316028769": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "316031213": {"name": "Legendary: Griswold's Worn Edge (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242189": {"name": "Legendary: Griswold's Worn Edge (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350471165": {"name": "Legendary: Incinerator", "category": "Swords, One-Handed", "platform": "Console"}, "229247441": {"name": "Legendary: Lifebane", "category": "Swords, One-Handed", "platform": "Console"}, "1312485756": {"name": "Legendary: Monster Hunter", "category": "Swords, One-Handed", "platform": "Console"}, "362279688": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "362282132": {"name": "Legendary: Monster Hunter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242228": {"name": "Legendary: Monster Hunter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350435228": {"name": "Legendary: Nazim's Greatness", "category": "Swords, One-Handed", "platform": "Console"}, "1312234197": {"name": "Legendary: Rakanishu's Blade", "category": "Swords, One-Handed", "platform": "Console"}, "353978241": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "353980685": {"name": "Legendary: Rakanishu's Blade (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242221": {"name": "Legendary: Rakanishu's Blade (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1351369590": {"name": "Legendary: Rancor", "category": "Swords, One-Handed", "platform": "Console"}, "1350507102": {"name": "Legendary: Rimeheart", "category": "Swords, One-Handed", "platform": "Console"}, "1311299835": {"name": "Legendary: Sever", "category": "Swords, One-Handed", "platform": "Console"}, "323144295": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "323146739": {"name": "Legendary: Sever (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242195": {"name": "Legendary: Sever (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "229283378": {"name": "Legendary: Shard of Hate", "category": "Swords, One-Handed", "platform": "Console"}, "1311192024": {"name": "Legendary: Skycutter", "category": "Swords, One-Handed", "platform": "Console"}, "319586532": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "319588976": {"name": "Legendary: Skycutter (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242192": {"name": "Legendary: Skycutter (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1313456055": {"name": "Legendary: Spectrum", "category": "Swords, One-Handed", "platform": "Console"}, "394299555": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "394301999": {"name": "Legendary: Spectrum (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242255": {"name": "Legendary: Spectrum (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1311156087": {"name": "Legendary: The Ancient Bonesaber of Zumakalis", "category": "Swords, One-Handed", "platform": "Console"}, "318400611": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "318403055": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242191": {"name": "Legendary: The Ancient Bonesaber of Zumakalis (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "1350219606": {"name": "Legendary: Thunderfury, Blessed Blade of the Windseeker", "category": "Swords, One-Handed", "platform": "Console"}, "1311120150": {"name": "Legendary: Wildwood", "category": "Swords, One-Handed", "platform": "Console"}, "317214690": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "317217134": {"name": "Legendary: Wildwood (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242190": {"name": "Legendary: Wildwood (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487634": {"name": "PvP: Heroic Bastard Sword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487635": {"name": "PvP: Mighty Longsword", "category": "Swords, One-Handed", "platform": "Console"}, "-1785487636": {"name": "PvP: Shortsword", "category": "Swords, One-Handed", "platform": "Console"}, "1312521693": {"name": "Set: Born's Furious Wrath", "category": "Swords, One-Handed", "platform": "Console"}, "363465609": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "363468053": {"name": "Set: Born's Searing Spite (Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "608242229": {"name": "Set: Born's Seething Rage (Old-Legacy)", "category": "Swords, One-Handed", "platform": "Console"}, "-1394445518": {"name": "Set: Little Rogue", "category": "Swords, One-Handed", "platform": "Console"}, "-1394481455": {"name": "Set: The Slanderer", "category": "Swords, One-Handed", "platform": "Console"}, "-2025765397": {"name": "Sword Of Justice Tyrael", "category": "Swords, One-Handed", "platform": "Console"}, "1351477401": {"name": "legendary: In-geom (Patch 2.2.0)", "category": "Swords, One-Handed", "platform": "Console"}}, "Swords, Two-Handed": {"-231803527": {"name": "02: Flamberge (DPS 16.0-17.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803526": {"name": "03: Dervish (DPS 22.6-24.2)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803525": {"name": "04: Executioner Sword (DPS 28.1-29.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803524": {"name": "05: Nodachi (DPS 35.2-36.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231803523": {"name": "06: Claymore (DPS 41.8-43.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802439": {"name": "07: Great Sword (DPS 52.8-54.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802438": {"name": "08: Reaver (DPS 62.2-65.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802437": {"name": "09: Kilij (DPS 74.8-78.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802436": {"name": "10: Mameluke (DPS 89.7-93.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802435": {"name": "11: Nagamaki (DPS 106.2-111.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231802434": {"name": "12: Grand Sword (DPS 126.5-133.1)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801350": {"name": "13: Highland Sword (DPS 171.6-179.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801349": {"name": "14: Brimstone Sword (DPS 215.6-223.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801348": {"name": "15: Yatagan (DPS 269.0-278.9)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801347": {"name": "16: Colossus Blade (DPS 367.4-379.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801346": {"name": "17: Oni Blade (DPS 433.4-446.6)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231801345": {"name": "18: Warlord Sword (DPS 511.5-524.7)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800261": {"name": "19: Gothic Blade (DPS 670.5-682.5)", "category": "Swords, Two-Handed", "platform": "Console"}, "-231800260": {"name": "20: Kingslayer (DPS 907.4-919.4)", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039901": {"name": "Art Test Sword Two-Handed 1", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039902": {"name": "Art Test Sword Two-Handed 2", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039903": {"name": "Art Test Sword Two-Handed 3", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039904": {"name": "Art Test Sword Two-Handed 4", "category": "Swords, Two-Handed", "platform": "Console"}, "1775039905": {"name": "Art Test Sword Two-Handed 5", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028384713": {"name": "Legendary: Blackguard", "category": "Swords, Two-Handed", "platform": "Console"}, "422965539": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "422967983": {"name": "Legendary: Blackguard (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377615": {"name": "Legendary: Blackguard (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029355012": {"name": "Legendary: Blade of Prophecy", "category": "Swords, Two-Handed", "platform": "Console"}, "390945672": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "390948116": {"name": "Legendary: Blade of Prophecy (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377588": {"name": "Legendary: Blade of Prophecy (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "1516448771": {"name": "Legendary: Blade of the Ancients", "category": "Swords, Two-Handed", "platform": "Console"}, "-990363367": {"name": "Legendary: Blood Brother", "category": "Swords, Two-Handed", "platform": "Console"}, "-990399304": {"name": "Legendary: Cam's Rebuttal", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028348776": {"name": "Legendary: Faithful Memory", "category": "Swords, Two-Handed", "platform": "Console"}, "424151460": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "424153904": {"name": "Legendary: Faithful Memory (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377616": {"name": "Legendary: Faithful Memory (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028420650": {"name": "Legendary: Maximus", "category": "Swords, Two-Handed", "platform": "Console"}, "421779618": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "421782062": {"name": "Legendary: Maximus (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377614": {"name": "Legendary: Maximus (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029462823": {"name": "Legendary: Scourge", "category": "Swords, Two-Handed", "platform": "Console"}, "387387909": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "387390353": {"name": "Legendary: Scourge (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377585": {"name": "Legendary: Scourge (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1028276902": {"name": "Legendary: Splintered Oar", "category": "Swords, Two-Handed", "platform": "Console"}, "426523302": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "426525746": {"name": "Legendary: Splintered Oar (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377618": {"name": "Legendary: Splintered Oar (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990435241": {"name": "Legendary: Stalgard's Decimator", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029570634": {"name": "Legendary: The Grandfather", "category": "Swords, Two-Handed", "platform": "Console"}, "383830146": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "383832590": {"name": "Legendary: The Grandfather (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377582": {"name": "Legendary: The Grandfather (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029319075": {"name": "Legendary: The Sultan of Blinding Sand", "category": "Swords, Two-Handed", "platform": "Console"}, "392131593": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "392134037": {"name": "Legendary: The Sultan of Blinding Sand (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377589": {"name": "Legendary: The Sultan of Blinding Sand (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029534697": {"name": "Legendary: The Zweihander", "category": "Swords, Two-Handed", "platform": "Console"}, "385016067": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "385018511": {"name": "Legendary: The Zweihander (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377583": {"name": "Legendary: The Zweihander (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1029498760": {"name": "Legendary: Warmonger", "category": "Swords, Two-Handed", "platform": "Console"}, "386201988": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "386204432": {"name": "Legendary: Warmonger (Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "647377584": {"name": "Legendary: Warmonger (Old-Legacy)", "category": "Swords, Two-Handed", "platform": "Console"}, "-1271367654": {"name": "legendary: Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990291493": {"name": "legendary: Ch'il-chi-do (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}, "-990327430": {"name": "legendary: Corrupted Ashbringer (Patch 2.2.0)", "category": "Swords, Two-Handed", "platform": "Console"}}, "Templar Relics": {"1147339622": {"name": "02: Spear Fragment", "category": "Templar Relics", "platform": "Console"}, "1147340710": {"name": "03: Sacred Text", "category": "Templar Relics", "platform": "Console"}, "1147340711": {"name": "04: Blade Shard", "category": "Templar Relics", "platform": "Console"}, "1147340712": {"name": "05: Martyr Tears", "category": "Templar Relics", "platform": "Console"}, "1147340713": {"name": "06: Chalice", "category": "Templar Relics", "platform": "Console"}, "1147341799": {"name": "07: Libram Spiritus", "category": "Templar Relics", "platform": "Console"}, "1147341800": {"name": "08: Blade Remnant", "category": "Templar Relics", "platform": "Console"}, "1147341801": {"name": "09: Saint Tears", "category": "Templar Relics", "platform": "Console"}, "1147341802": {"name": "10: Grail", "category": "Templar Relics", "platform": "Console"}, "1147341803": {"name": "11: Codex", "category": "Templar Relics", "platform": "Console"}, "1147341804": {"name": "12: Broken Foible", "category": "Templar Relics", "platform": "Console"}, "-765770609": {"name": "Legendary: Enchanting Favor", "category": "Templar Relics", "platform": "Console"}, "-765770607": {"name": "Legendary: Hillenbrand's Training Sword", "category": "Templar Relics", "platform": "Console"}, "-765770608": {"name": "Legendary: Relic of Akarat", "category": "Templar Relics", "platform": "Console"}}, "Test": {"-1438295707": {"name": "Don's Sword of Testing", "category": "Test", "platform": "Console"}, "-1585353949": {"name": "P1 Test Ring 941 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353948": {"name": "P1 Test Ring 942 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353947": {"name": "P1 Test Ring 943 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "-1585353946": {"name": "P1 Test Ring 944 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388889": {"name": "P2 TEST RING 021 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388890": {"name": "P2 TEST RING 022 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388891": {"name": "P2 TEST RING 023 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388892": {"name": "P2 TEST RING 024 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388893": {"name": "P2 TEST RING 025 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388894": {"name": "P2 TEST RING 026 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388895": {"name": "P2 TEST RING 027 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388896": {"name": "P2 TEST RING 028 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388897": {"name": "P2 TEST RING 029 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388921": {"name": "P2 TEST RING 030 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388922": {"name": "P2 TEST RING 031 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388923": {"name": "P2 TEST RING 032 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388924": {"name": "P2 TEST RING 033 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388925": {"name": "P2 TEST RING 034 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388926": {"name": "P2 TEST RING 035 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388927": {"name": "P2 TEST RING 036 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388928": {"name": "P2 TEST RING 037 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388929": {"name": "P2 TEST RING 038 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388930": {"name": "P2 TEST RING 039 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388954": {"name": "P2 TEST RING 040 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388955": {"name": "P2 TEST RING 041 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388956": {"name": "P2 TEST RING 042 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388957": {"name": "P2 TEST RING 043 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388958": {"name": "P2 TEST RING 044 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388959": {"name": "P2 TEST RING 045 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388960": {"name": "P2 TEST RING 046 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388961": {"name": "P2 TEST RING 047 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388962": {"name": "P2 TEST RING 048 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388963": {"name": "P2 TEST RING 049 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388987": {"name": "P2 TEST RING 050 (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388824": {"name": "P2 Test Ring 002 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388825": {"name": "P2 Test Ring 003 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388826": {"name": "P2 Test Ring 004 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388827": {"name": "P2 Test Ring 005 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388828": {"name": "P2 Test Ring 006 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388829": {"name": "P2 Test Ring 007 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388830": {"name": "P2 Test Ring 008 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388831": {"name": "P2 Test Ring 009 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388855": {"name": "P2 Test Ring 010 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388856": {"name": "P2 Test Ring 011 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388857": {"name": "P2 Test Ring 012 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388858": {"name": "P2 Test Ring 013 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388859": {"name": "P2 Test Ring 014 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388860": {"name": "P2 Test Ring 015 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388861": {"name": "P2 Test Ring 016 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388862": {"name": "P2 Test Ring 017 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388863": {"name": "P2 Test Ring 018 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388864": {"name": "P2 Test Ring 019 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "878388888": {"name": "P2 Test Ring 020 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "1608362283": {"name": "P2_WizardSet_Scroll_Test (Patch 2.2.0)", "category": "Test", "platform": "Console"}, "878388823": {"name": "Test Ring 001 (Patch 2.1.2)", "category": "Test", "platform": "Console"}, "708102766": {"name": "Test Ring 1000", "category": "Test", "platform": "Console"}, "-993303550": {"name": "Test Ring 500", "category": "Test", "platform": "Console"}, "-993267613": {"name": "Test Ring 501", "category": "Test", "platform": "Console"}, "-993231676": {"name": "Test Ring 502", "category": "Test", "platform": "Console"}, "-993195739": {"name": "Test Ring 503", "category": "Test", "platform": "Console"}, "-993159802": {"name": "Test Ring 504", "category": "Test", "platform": "Console"}, "-993123865": {"name": "Test Ring 505", "category": "Test", "platform": "Console"}, "-993087928": {"name": "Test Ring 506", "category": "Test", "platform": "Console"}, "-993051991": {"name": "Test Ring 507", "category": "Test", "platform": "Console"}, "-993016054": {"name": "Test Ring 508", "category": "Test", "platform": "Console"}, "-992980117": {"name": "Test Ring 509", "category": "Test", "platform": "Console"}, "-992117629": {"name": "Test Ring 510", "category": "Test", "platform": "Console"}, "-992081692": {"name": "Test Ring 511", "category": "Test", "platform": "Console"}, "-992045755": {"name": "Test Ring 512", "category": "Test", "platform": "Console"}, "-992009818": {"name": "Test Ring 513", "category": "Test", "platform": "Console"}, "-991973881": {"name": "Test Ring 514", "category": "Test", "platform": "Console"}, "-991937944": {"name": "Test Ring 515", "category": "Test", "platform": "Console"}, "-991902007": {"name": "Test Ring 516", "category": "Test", "platform": "Console"}, "-991866070": {"name": "Test Ring 517", "category": "Test", "platform": "Console"}, "-991830133": {"name": "Test Ring 518", "category": "Test", "platform": "Console"}, "-991794196": {"name": "Test Ring 519", "category": "Test", "platform": "Console"}, "-990931708": {"name": "Test Ring 520", "category": "Test", "platform": "Console"}, "-990895771": {"name": "Test Ring 521", "category": "Test", "platform": "Console"}, "-990859834": {"name": "Test Ring 522", "category": "Test", "platform": "Console"}, "-990823897": {"name": "Test Ring 523", "category": "Test", "platform": "Console"}, "-990787960": {"name": "Test Ring 524", "category": "Test", "platform": "Console"}, "-990752023": {"name": "Test Ring 525", "category": "Test", "platform": "Console"}, "-990716086": {"name": "Test Ring 526", "category": "Test", "platform": "Console"}, "-990680149": {"name": "Test Ring 527", "category": "Test", "platform": "Console"}, "-990644212": {"name": "Test Ring 528", "category": "Test", "platform": "Console"}, "-990608275": {"name": "Test Ring 529", "category": "Test", "platform": "Console"}, "-989745787": {"name": "Test Ring 530", "category": "Test", "platform": "Console"}, "-989709850": {"name": "Test Ring 531", "category": "Test", "platform": "Console"}, "-989673913": {"name": "Test Ring 532", "category": "Test", "platform": "Console"}, "-989637976": {"name": "Test Ring 533", "category": "Test", "platform": "Console"}, "-989602039": {"name": "Test Ring 534", "category": "Test", "platform": "Console"}, "-989566102": {"name": "Test Ring 535", "category": "Test", "platform": "Console"}, "-989530165": {"name": "Test Ring 536", "category": "Test", "platform": "Console"}, "-989494228": {"name": "Test Ring 537", "category": "Test", "platform": "Console"}, "-989458291": {"name": "Test Ring 538", "category": "Test", "platform": "Console"}, "-989422354": {"name": "Test Ring 539", "category": "Test", "platform": "Console"}, "-988559866": {"name": "Test Ring 540", "category": "Test", "platform": "Console"}, "-988523929": {"name": "Test Ring 541", "category": "Test", "platform": "Console"}, "-988487992": {"name": "Test Ring 542", "category": "Test", "platform": "Console"}, "-988452055": {"name": "Test Ring 543", "category": "Test", "platform": "Console"}, "-988416118": {"name": "Test Ring 544", "category": "Test", "platform": "Console"}, "-988380181": {"name": "Test Ring 545", "category": "Test", "platform": "Console"}, "-988344244": {"name": "Test Ring 546", "category": "Test", "platform": "Console"}, "-988308307": {"name": "Test Ring 547", "category": "Test", "platform": "Console"}, "-988272370": {"name": "Test Ring 548", "category": "Test", "platform": "Console"}, "-988236433": {"name": "Test Ring 549", "category": "Test", "platform": "Console"}, "-987373945": {"name": "Test Ring 550", "category": "Test", "platform": "Console"}, "-987338008": {"name": "Test Ring 551", "category": "Test", "platform": "Console"}, "-987302071": {"name": "Test Ring 552", "category": "Test", "platform": "Console"}, "-987266134": {"name": "Test Ring 553", "category": "Test", "platform": "Console"}, "-987230197": {"name": "Test Ring 554", "category": "Test", "platform": "Console"}, "-987194260": {"name": "Test Ring 555", "category": "Test", "platform": "Console"}, "-987158323": {"name": "Test Ring 556", "category": "Test", "platform": "Console"}, "-987122386": {"name": "Test Ring 557", "category": "Test", "platform": "Console"}, "-987086449": {"name": "Test Ring 558", "category": "Test", "platform": "Console"}, "-987050512": {"name": "Test Ring 559", "category": "Test", "platform": "Console"}, "-986188024": {"name": "Test Ring 560", "category": "Test", "platform": "Console"}, "-986152087": {"name": "Test Ring 561", "category": "Test", "platform": "Console"}, "-986116150": {"name": "Test Ring 562", "category": "Test", "platform": "Console"}, "-986080213": {"name": "Test Ring 563", "category": "Test", "platform": "Console"}, "-986044276": {"name": "Test Ring 564", "category": "Test", "platform": "Console"}, "-986008339": {"name": "Test Ring 565", "category": "Test", "platform": "Console"}, "-985972402": {"name": "Test Ring 566", "category": "Test", "platform": "Console"}, "-985936465": {"name": "Test Ring 567", "category": "Test", "platform": "Console"}, "-985900528": {"name": "Test Ring 568", "category": "Test", "platform": "Console"}, "-985864591": {"name": "Test Ring 569", "category": "Test", "platform": "Console"}, "-985002103": {"name": "Test Ring 570", "category": "Test", "platform": "Console"}, "-984966166": {"name": "Test Ring 571", "category": "Test", "platform": "Console"}, "-984930229": {"name": "Test Ring 572", "category": "Test", "platform": "Console"}, "-984894292": {"name": "Test Ring 573", "category": "Test", "platform": "Console"}, "-984858355": {"name": "Test Ring 574", "category": "Test", "platform": "Console"}, "-984822418": {"name": "Test Ring 575", "category": "Test", "platform": "Console"}, "-984786481": {"name": "Test Ring 576", "category": "Test", "platform": "Console"}, "-984750544": {"name": "Test Ring 577", "category": "Test", "platform": "Console"}, "-984714607": {"name": "Test Ring 578", "category": "Test", "platform": "Console"}, "-984678670": {"name": "Test Ring 579", "category": "Test", "platform": "Console"}, "-983816182": {"name": "Test Ring 580", "category": "Test", "platform": "Console"}, "-983780245": {"name": "Test Ring 581", "category": "Test", "platform": "Console"}, "-983744308": {"name": "Test Ring 582", "category": "Test", "platform": "Console"}, "-983708371": {"name": "Test Ring 583", "category": "Test", "platform": "Console"}, "-983672434": {"name": "Test Ring 584", "category": "Test", "platform": "Console"}, "-983636497": {"name": "Test Ring 585", "category": "Test", "platform": "Console"}, "-983600560": {"name": "Test Ring 586", "category": "Test", "platform": "Console"}, "-983564623": {"name": "Test Ring 587", "category": "Test", "platform": "Console"}, "-983528686": {"name": "Test Ring 588", "category": "Test", "platform": "Console"}, "-983492749": {"name": "Test Ring 589", "category": "Test", "platform": "Console"}, "-982630261": {"name": "Test Ring 590", "category": "Test", "platform": "Console"}, "-982594324": {"name": "Test Ring 591", "category": "Test", "platform": "Console"}, "-982558387": {"name": "Test Ring 592", "category": "Test", "platform": "Console"}, "-982522450": {"name": "Test Ring 593", "category": "Test", "platform": "Console"}, "-982486513": {"name": "Test Ring 594", "category": "Test", "platform": "Console"}, "-982450576": {"name": "Test Ring 595", "category": "Test", "platform": "Console"}, "-982414639": {"name": "Test Ring 596", "category": "Test", "platform": "Console"}, "-982378702": {"name": "Test Ring 597", "category": "Test", "platform": "Console"}, "-982342765": {"name": "Test Ring 598", "category": "Test", "platform": "Console"}, "-982306828": {"name": "Test Ring 599", "category": "Test", "platform": "Console"}, "-954168157": {"name": "Test Ring 600", "category": "Test", "platform": "Console"}, "-954132220": {"name": "Test Ring 601", "category": "Test", "platform": "Console"}, "-954096283": {"name": "Test Ring 602", "category": "Test", "platform": "Console"}, "-954060346": {"name": "Test Ring 603", "category": "Test", "platform": "Console"}, "-954024409": {"name": "Test Ring 604", "category": "Test", "platform": "Console"}, "-953988472": {"name": "Test Ring 605", "category": "Test", "platform": "Console"}, "-953952535": {"name": "Test Ring 606", "category": "Test", "platform": "Console"}, "-953916598": {"name": "Test Ring 607", "category": "Test", "platform": "Console"}, "-953880661": {"name": "Test Ring 608", "category": "Test", "platform": "Console"}, "-953844724": {"name": "Test Ring 609", "category": "Test", "platform": "Console"}, "-952982236": {"name": "Test Ring 610", "category": "Test", "platform": "Console"}, "-952946299": {"name": "Test Ring 611", "category": "Test", "platform": "Console"}, "-952910362": {"name": "Test Ring 612", "category": "Test", "platform": "Console"}, "-952874425": {"name": "Test Ring 613", "category": "Test", "platform": "Console"}, "-952838488": {"name": "Test Ring 614", "category": "Test", "platform": "Console"}, "-952802551": {"name": "Test Ring 615", "category": "Test", "platform": "Console"}, "-952766614": {"name": "Test Ring 616", "category": "Test", "platform": "Console"}, "-952730677": {"name": "Test Ring 617", "category": "Test", "platform": "Console"}, "-952694740": {"name": "Test Ring 618", "category": "Test", "platform": "Console"}, "-952658803": {"name": "Test Ring 619", "category": "Test", "platform": "Console"}, "-951796315": {"name": "Test Ring 620", "category": "Test", "platform": "Console"}, "-951760378": {"name": "Test Ring 621", "category": "Test", "platform": "Console"}, "-951724441": {"name": "Test Ring 622", "category": "Test", "platform": "Console"}, "-951688504": {"name": "Test Ring 623", "category": "Test", "platform": "Console"}, "-951652567": {"name": "Test Ring 624", "category": "Test", "platform": "Console"}, "-951616630": {"name": "Test Ring 625", "category": "Test", "platform": "Console"}, "-951580693": {"name": "Test Ring 626", "category": "Test", "platform": "Console"}, "-951544756": {"name": "Test Ring 627", "category": "Test", "platform": "Console"}, "-951508819": {"name": "Test Ring 628", "category": "Test", "platform": "Console"}, "-951472882": {"name": "Test Ring 629", "category": "Test", "platform": "Console"}, "-950610394": {"name": "Test Ring 630", "category": "Test", "platform": "Console"}, "-950574457": {"name": "Test Ring 631", "category": "Test", "platform": "Console"}, "-950538520": {"name": "Test Ring 632", "category": "Test", "platform": "Console"}, "-950502583": {"name": "Test Ring 633", "category": "Test", "platform": "Console"}, "-950466646": {"name": "Test Ring 634", "category": "Test", "platform": "Console"}, "-950430709": {"name": "Test Ring 635", "category": "Test", "platform": "Console"}, "-950394772": {"name": "Test Ring 636", "category": "Test", "platform": "Console"}, "-950358835": {"name": "Test Ring 637", "category": "Test", "platform": "Console"}, "-950322898": {"name": "Test Ring 638", "category": "Test", "platform": "Console"}, "-950286961": {"name": "Test Ring 639", "category": "Test", "platform": "Console"}, "-949424473": {"name": "Test Ring 640", "category": "Test", "platform": "Console"}, "-949388536": {"name": "Test Ring 641", "category": "Test", "platform": "Console"}, "-949352599": {"name": "Test Ring 642", "category": "Test", "platform": "Console"}, "-949316662": {"name": "Test Ring 643", "category": "Test", "platform": "Console"}, "-949280725": {"name": "Test Ring 644", "category": "Test", "platform": "Console"}, "-949244788": {"name": "Test Ring 645", "category": "Test", "platform": "Console"}, "-949208851": {"name": "Test Ring 646", "category": "Test", "platform": "Console"}, "-949172914": {"name": "Test Ring 647", "category": "Test", "platform": "Console"}, "-949136977": {"name": "Test Ring 648", "category": "Test", "platform": "Console"}, "-949101040": {"name": "Test Ring 649", "category": "Test", "platform": "Console"}, "-948238552": {"name": "Test Ring 650", "category": "Test", "platform": "Console"}, "-948202615": {"name": "Test Ring 651", "category": "Test", "platform": "Console"}, "-948166678": {"name": "Test Ring 652", "category": "Test", "platform": "Console"}, "-948130741": {"name": "Test Ring 653", "category": "Test", "platform": "Console"}, "-948094804": {"name": "Test Ring 654", "category": "Test", "platform": "Console"}, "-948058867": {"name": "Test Ring 655", "category": "Test", "platform": "Console"}, "-948022930": {"name": "Test Ring 656", "category": "Test", "platform": "Console"}, "-947986993": {"name": "Test Ring 657", "category": "Test", "platform": "Console"}, "-947951056": {"name": "Test Ring 658", "category": "Test", "platform": "Console"}, "-947915119": {"name": "Test Ring 659", "category": "Test", "platform": "Console"}, "-947052631": {"name": "Test Ring 660", "category": "Test", "platform": "Console"}, "-947016694": {"name": "Test Ring 661", "category": "Test", "platform": "Console"}, "-946980757": {"name": "Test Ring 662", "category": "Test", "platform": "Console"}, "-946944820": {"name": "Test Ring 663", "category": "Test", "platform": "Console"}, "-946908883": {"name": "Test Ring 664", "category": "Test", "platform": "Console"}, "-946872946": {"name": "Test Ring 665", "category": "Test", "platform": "Console"}, "-946837009": {"name": "Test Ring 666", "category": "Test", "platform": "Console"}, "-946801072": {"name": "Test Ring 667", "category": "Test", "platform": "Console"}, "-946765135": {"name": "Test Ring 668", "category": "Test", "platform": "Console"}, "-946729198": {"name": "Test Ring 669", "category": "Test", "platform": "Console"}, "-945866710": {"name": "Test Ring 670", "category": "Test", "platform": "Console"}, "-945830773": {"name": "Test Ring 671", "category": "Test", "platform": "Console"}, "-945794836": {"name": "Test Ring 672", "category": "Test", "platform": "Console"}, "-945758899": {"name": "Test Ring 673", "category": "Test", "platform": "Console"}, "-945722962": {"name": "Test Ring 674", "category": "Test", "platform": "Console"}, "-945687025": {"name": "Test Ring 675", "category": "Test", "platform": "Console"}, "-945651088": {"name": "Test Ring 676", "category": "Test", "platform": "Console"}, "-945615151": {"name": "Test Ring 677", "category": "Test", "platform": "Console"}, "-945579214": {"name": "Test Ring 678", "category": "Test", "platform": "Console"}, "-945543277": {"name": "Test Ring 679", "category": "Test", "platform": "Console"}, "-944680789": {"name": "Test Ring 680", "category": "Test", "platform": "Console"}, "-944644852": {"name": "Test Ring 681", "category": "Test", "platform": "Console"}, "-944608915": {"name": "Test Ring 682", "category": "Test", "platform": "Console"}, "-944572978": {"name": "Test Ring 683", "category": "Test", "platform": "Console"}, "-944537041": {"name": "Test Ring 684", "category": "Test", "platform": "Console"}, "-944501104": {"name": "Test Ring 685", "category": "Test", "platform": "Console"}, "-944465167": {"name": "Test Ring 686", "category": "Test", "platform": "Console"}, "-944429230": {"name": "Test Ring 687", "category": "Test", "platform": "Console"}, "-944393293": {"name": "Test Ring 688", "category": "Test", "platform": "Console"}, "-944357356": {"name": "Test Ring 689", "category": "Test", "platform": "Console"}, "-943494868": {"name": "Test Ring 690", "category": "Test", "platform": "Console"}, "-943458931": {"name": "Test Ring 691", "category": "Test", "platform": "Console"}, "-943422994": {"name": "Test Ring 692", "category": "Test", "platform": "Console"}, "-943387057": {"name": "Test Ring 693", "category": "Test", "platform": "Console"}, "-943351120": {"name": "Test Ring 694", "category": "Test", "platform": "Console"}, "-943315183": {"name": "Test Ring 695", "category": "Test", "platform": "Console"}, "-943279246": {"name": "Test Ring 696", "category": "Test", "platform": "Console"}, "-943243309": {"name": "Test Ring 697", "category": "Test", "platform": "Console"}, "-943207372": {"name": "Test Ring 698", "category": "Test", "platform": "Console"}, "-943171435": {"name": "Test Ring 699", "category": "Test", "platform": "Console"}, "-915032764": {"name": "Test Ring 700", "category": "Test", "platform": "Console"}, "-914996827": {"name": "Test Ring 701", "category": "Test", "platform": "Console"}, "-914960890": {"name": "Test Ring 702", "category": "Test", "platform": "Console"}, "-914924953": {"name": "Test Ring 703", "category": "Test", "platform": "Console"}, "-914889016": {"name": "Test Ring 704", "category": "Test", "platform": "Console"}, "-914853079": {"name": "Test Ring 705", "category": "Test", "platform": "Console"}, "-914817142": {"name": "Test Ring 706", "category": "Test", "platform": "Console"}, "-914781205": {"name": "Test Ring 707", "category": "Test", "platform": "Console"}, "-914745268": {"name": "Test Ring 708", "category": "Test", "platform": "Console"}, "-914709331": {"name": "Test Ring 709", "category": "Test", "platform": "Console"}, "-913846843": {"name": "Test Ring 710", "category": "Test", "platform": "Console"}, "-913810906": {"name": "Test Ring 711", "category": "Test", "platform": "Console"}, "-913774969": {"name": "Test Ring 712", "category": "Test", "platform": "Console"}, "-913739032": {"name": "Test Ring 713", "category": "Test", "platform": "Console"}, "-913703095": {"name": "Test Ring 714", "category": "Test", "platform": "Console"}, "-913667158": {"name": "Test Ring 715", "category": "Test", "platform": "Console"}, "-913631221": {"name": "Test Ring 716", "category": "Test", "platform": "Console"}, "-913595284": {"name": "Test Ring 717", "category": "Test", "platform": "Console"}, "-913559347": {"name": "Test Ring 718", "category": "Test", "platform": "Console"}, "-913523410": {"name": "Test Ring 719", "category": "Test", "platform": "Console"}, "-912660922": {"name": "Test Ring 720", "category": "Test", "platform": "Console"}, "-912624985": {"name": "Test Ring 721", "category": "Test", "platform": "Console"}, "-912589048": {"name": "Test Ring 722", "category": "Test", "platform": "Console"}, "-912553111": {"name": "Test Ring 723", "category": "Test", "platform": "Console"}, "-912517174": {"name": "Test Ring 724", "category": "Test", "platform": "Console"}, "-912481237": {"name": "Test Ring 725", "category": "Test", "platform": "Console"}, "-912445300": {"name": "Test Ring 726", "category": "Test", "platform": "Console"}, "-912409363": {"name": "Test Ring 727", "category": "Test", "platform": "Console"}, "-912373426": {"name": "Test Ring 728", "category": "Test", "platform": "Console"}, "-912337489": {"name": "Test Ring 729", "category": "Test", "platform": "Console"}, "-911475001": {"name": "Test Ring 730", "category": "Test", "platform": "Console"}, "-911439064": {"name": "Test Ring 731", "category": "Test", "platform": "Console"}, "-911403127": {"name": "Test Ring 732", "category": "Test", "platform": "Console"}, "-911367190": {"name": "Test Ring 733", "category": "Test", "platform": "Console"}, "-911331253": {"name": "Test Ring 734", "category": "Test", "platform": "Console"}, "-911295316": {"name": "Test Ring 735", "category": "Test", "platform": "Console"}, "-911259379": {"name": "Test Ring 736", "category": "Test", "platform": "Console"}, "-911223442": {"name": "Test Ring 737", "category": "Test", "platform": "Console"}, "-911187505": {"name": "Test Ring 738", "category": "Test", "platform": "Console"}, "-911151568": {"name": "Test Ring 739", "category": "Test", "platform": "Console"}, "-910289080": {"name": "Test Ring 740", "category": "Test", "platform": "Console"}, "-910253143": {"name": "Test Ring 741", "category": "Test", "platform": "Console"}, "-910217206": {"name": "Test Ring 742", "category": "Test", "platform": "Console"}, "-910181269": {"name": "Test Ring 743", "category": "Test", "platform": "Console"}, "-910145332": {"name": "Test Ring 744", "category": "Test", "platform": "Console"}, "-910109395": {"name": "Test Ring 745", "category": "Test", "platform": "Console"}, "-910073458": {"name": "Test Ring 746", "category": "Test", "platform": "Console"}, "-910037521": {"name": "Test Ring 747", "category": "Test", "platform": "Console"}, "-910001584": {"name": "Test Ring 748", "category": "Test", "platform": "Console"}, "-909965647": {"name": "Test Ring 749", "category": "Test", "platform": "Console"}, "-909103159": {"name": "Test Ring 750", "category": "Test", "platform": "Console"}, "-909067222": {"name": "Test Ring 751", "category": "Test", "platform": "Console"}, "-909031285": {"name": "Test Ring 752", "category": "Test", "platform": "Console"}, "-908995348": {"name": "Test Ring 753", "category": "Test", "platform": "Console"}, "-908959411": {"name": "Test Ring 754", "category": "Test", "platform": "Console"}, "-908923474": {"name": "Test Ring 755", "category": "Test", "platform": "Console"}, "-908887537": {"name": "Test Ring 756", "category": "Test", "platform": "Console"}, "-908851600": {"name": "Test Ring 757", "category": "Test", "platform": "Console"}, "-908815663": {"name": "Test Ring 758", "category": "Test", "platform": "Console"}, "-908779726": {"name": "Test Ring 759", "category": "Test", "platform": "Console"}, "-907917238": {"name": "Test Ring 760", "category": "Test", "platform": "Console"}, "-907881301": {"name": "Test Ring 761", "category": "Test", "platform": "Console"}, "-907845364": {"name": "Test Ring 762", "category": "Test", "platform": "Console"}, "-907809427": {"name": "Test Ring 763", "category": "Test", "platform": "Console"}, "-907773490": {"name": "Test Ring 764", "category": "Test", "platform": "Console"}, "-907737553": {"name": "Test Ring 765", "category": "Test", "platform": "Console"}, "-907701616": {"name": "Test Ring 766", "category": "Test", "platform": "Console"}, "-907665679": {"name": "Test Ring 767", "category": "Test", "platform": "Console"}, "-907629742": {"name": "Test Ring 768", "category": "Test", "platform": "Console"}, "-907593805": {"name": "Test Ring 769", "category": "Test", "platform": "Console"}, "-906731317": {"name": "Test Ring 770", "category": "Test", "platform": "Console"}, "-906695380": {"name": "Test Ring 771", "category": "Test", "platform": "Console"}, "-906659443": {"name": "Test Ring 772", "category": "Test", "platform": "Console"}, "-906623506": {"name": "Test Ring 773", "category": "Test", "platform": "Console"}, "-906587569": {"name": "Test Ring 774", "category": "Test", "platform": "Console"}, "-906551632": {"name": "Test Ring 775", "category": "Test", "platform": "Console"}, "-906515695": {"name": "Test Ring 776", "category": "Test", "platform": "Console"}, "-906479758": {"name": "Test Ring 777", "category": "Test", "platform": "Console"}, "-906443821": {"name": "Test Ring 778", "category": "Test", "platform": "Console"}, "-906407884": {"name": "Test Ring 779", "category": "Test", "platform": "Console"}, "-905545396": {"name": "Test Ring 780", "category": "Test", "platform": "Console"}, "-905509459": {"name": "Test Ring 781", "category": "Test", "platform": "Console"}, "-905473522": {"name": "Test Ring 782", "category": "Test", "platform": "Console"}, "-905437585": {"name": "Test Ring 783", "category": "Test", "platform": "Console"}, "-905401648": {"name": "Test Ring 784", "category": "Test", "platform": "Console"}, "-905365711": {"name": "Test Ring 785", "category": "Test", "platform": "Console"}, "-905329774": {"name": "Test Ring 786", "category": "Test", "platform": "Console"}, "-905293837": {"name": "Test Ring 787", "category": "Test", "platform": "Console"}, "-905257900": {"name": "Test Ring 788", "category": "Test", "platform": "Console"}, "-905221963": {"name": "Test Ring 789", "category": "Test", "platform": "Console"}, "-904359475": {"name": "Test Ring 790", "category": "Test", "platform": "Console"}, "-904323538": {"name": "Test Ring 791", "category": "Test", "platform": "Console"}, "-904287601": {"name": "Test Ring 792", "category": "Test", "platform": "Console"}, "-904251664": {"name": "Test Ring 793", "category": "Test", "platform": "Console"}, "-904215727": {"name": "Test Ring 794", "category": "Test", "platform": "Console"}, "-904179790": {"name": "Test Ring 795", "category": "Test", "platform": "Console"}, "-904143853": {"name": "Test Ring 796", "category": "Test", "platform": "Console"}, "-904107916": {"name": "Test Ring 797", "category": "Test", "platform": "Console"}, "-904071979": {"name": "Test Ring 798", "category": "Test", "platform": "Console"}, "-904036042": {"name": "Test Ring 799", "category": "Test", "platform": "Console"}, "-875897371": {"name": "Test Ring 800", "category": "Test", "platform": "Console"}, "-875861434": {"name": "Test Ring 801", "category": "Test", "platform": "Console"}, "-875825497": {"name": "Test Ring 802", "category": "Test", "platform": "Console"}, "-875789560": {"name": "Test Ring 803", "category": "Test", "platform": "Console"}, "-875753623": {"name": "Test Ring 804", "category": "Test", "platform": "Console"}, "-875717686": {"name": "Test Ring 805", "category": "Test", "platform": "Console"}, "-875681749": {"name": "Test Ring 806", "category": "Test", "platform": "Console"}, "-875645812": {"name": "Test Ring 807", "category": "Test", "platform": "Console"}, "-875609875": {"name": "Test Ring 808", "category": "Test", "platform": "Console"}, "-875573938": {"name": "Test Ring 809", "category": "Test", "platform": "Console"}, "-874711450": {"name": "Test Ring 810", "category": "Test", "platform": "Console"}, "-874675513": {"name": "Test Ring 811", "category": "Test", "platform": "Console"}, "-874639576": {"name": "Test Ring 812", "category": "Test", "platform": "Console"}, "-874603639": {"name": "Test Ring 813", "category": "Test", "platform": "Console"}, "-874567702": {"name": "Test Ring 814", "category": "Test", "platform": "Console"}, "-874531765": {"name": "Test Ring 815", "category": "Test", "platform": "Console"}, "-874495828": {"name": "Test Ring 816", "category": "Test", "platform": "Console"}, "-874459891": {"name": "Test Ring 817", "category": "Test", "platform": "Console"}, "-874423954": {"name": "Test Ring 818", "category": "Test", "platform": "Console"}, "-874388017": {"name": "Test Ring 819", "category": "Test", "platform": "Console"}, "-873525529": {"name": "Test Ring 820", "category": "Test", "platform": "Console"}, "-873489592": {"name": "Test Ring 821", "category": "Test", "platform": "Console"}, "-873453655": {"name": "Test Ring 822", "category": "Test", "platform": "Console"}, "-873417718": {"name": "Test Ring 823", "category": "Test", "platform": "Console"}, "-873381781": {"name": "Test Ring 824", "category": "Test", "platform": "Console"}, "-873345844": {"name": "Test Ring 825", "category": "Test", "platform": "Console"}, "-873309907": {"name": "Test Ring 826", "category": "Test", "platform": "Console"}, "-873273970": {"name": "Test Ring 827", "category": "Test", "platform": "Console"}, "-873238033": {"name": "Test Ring 828", "category": "Test", "platform": "Console"}, "-873202096": {"name": "Test Ring 829", "category": "Test", "platform": "Console"}, "-872339608": {"name": "Test Ring 830", "category": "Test", "platform": "Console"}, "-872303671": {"name": "Test Ring 831", "category": "Test", "platform": "Console"}, "-872267734": {"name": "Test Ring 832", "category": "Test", "platform": "Console"}, "-872231797": {"name": "Test Ring 833", "category": "Test", "platform": "Console"}, "-872195860": {"name": "Test Ring 834", "category": "Test", "platform": "Console"}, "-872159923": {"name": "Test Ring 835", "category": "Test", "platform": "Console"}, "-872123986": {"name": "Test Ring 836", "category": "Test", "platform": "Console"}, "-872088049": {"name": "Test Ring 837", "category": "Test", "platform": "Console"}, "-872052112": {"name": "Test Ring 838", "category": "Test", "platform": "Console"}, "-872016175": {"name": "Test Ring 839", "category": "Test", "platform": "Console"}, "-871153687": {"name": "Test Ring 840", "category": "Test", "platform": "Console"}, "-871117750": {"name": "Test Ring 841", "category": "Test", "platform": "Console"}, "-871081813": {"name": "Test Ring 842", "category": "Test", "platform": "Console"}, "-871045876": {"name": "Test Ring 843", "category": "Test", "platform": "Console"}, "-871009939": {"name": "Test Ring 844", "category": "Test", "platform": "Console"}, "-870974002": {"name": "Test Ring 845", "category": "Test", "platform": "Console"}, "-870938065": {"name": "Test Ring 846", "category": "Test", "platform": "Console"}, "-870902128": {"name": "Test Ring 847", "category": "Test", "platform": "Console"}, "-870866191": {"name": "Test Ring 848", "category": "Test", "platform": "Console"}, "-870830254": {"name": "Test Ring 849", "category": "Test", "platform": "Console"}, "-869967766": {"name": "Test Ring 850", "category": "Test", "platform": "Console"}, "-869931829": {"name": "Test Ring 851", "category": "Test", "platform": "Console"}, "-869895892": {"name": "Test Ring 852", "category": "Test", "platform": "Console"}, "-869859955": {"name": "Test Ring 853", "category": "Test", "platform": "Console"}, "-869824018": {"name": "Test Ring 854", "category": "Test", "platform": "Console"}, "-869788081": {"name": "Test Ring 855", "category": "Test", "platform": "Console"}, "-869752144": {"name": "Test Ring 856", "category": "Test", "platform": "Console"}, "-869716207": {"name": "Test Ring 857", "category": "Test", "platform": "Console"}, "-869680270": {"name": "Test Ring 858", "category": "Test", "platform": "Console"}, "-869644333": {"name": "Test Ring 859", "category": "Test", "platform": "Console"}, "-868781845": {"name": "Test Ring 860", "category": "Test", "platform": "Console"}, "-868745908": {"name": "Test Ring 861", "category": "Test", "platform": "Console"}, "-868709971": {"name": "Test Ring 862", "category": "Test", "platform": "Console"}, "-868674034": {"name": "Test Ring 863", "category": "Test", "platform": "Console"}, "-868638097": {"name": "Test Ring 864", "category": "Test", "platform": "Console"}, "-868602160": {"name": "Test Ring 865", "category": "Test", "platform": "Console"}, "-868566223": {"name": "Test Ring 866", "category": "Test", "platform": "Console"}, "-868530286": {"name": "Test Ring 867", "category": "Test", "platform": "Console"}, "-868494349": {"name": "Test Ring 868", "category": "Test", "platform": "Console"}, "-868458412": {"name": "Test Ring 869", "category": "Test", "platform": "Console"}, "-867595924": {"name": "Test Ring 870", "category": "Test", "platform": "Console"}, "-867559987": {"name": "Test Ring 871", "category": "Test", "platform": "Console"}, "-867524050": {"name": "Test Ring 872", "category": "Test", "platform": "Console"}, "-867488113": {"name": "Test Ring 873", "category": "Test", "platform": "Console"}, "-867452176": {"name": "Test Ring 874", "category": "Test", "platform": "Console"}, "-867416239": {"name": "Test Ring 875", "category": "Test", "platform": "Console"}, "-867380302": {"name": "Test Ring 876", "category": "Test", "platform": "Console"}, "-867344365": {"name": "Test Ring 877", "category": "Test", "platform": "Console"}, "-867308428": {"name": "Test Ring 878", "category": "Test", "platform": "Console"}, "-867272491": {"name": "Test Ring 879", "category": "Test", "platform": "Console"}, "-866410003": {"name": "Test Ring 880", "category": "Test", "platform": "Console"}, "-866374066": {"name": "Test Ring 881", "category": "Test", "platform": "Console"}, "-866338129": {"name": "Test Ring 882", "category": "Test", "platform": "Console"}, "-866302192": {"name": "Test Ring 883", "category": "Test", "platform": "Console"}, "-866266255": {"name": "Test Ring 884", "category": "Test", "platform": "Console"}, "-866230318": {"name": "Test Ring 885", "category": "Test", "platform": "Console"}, "-866194381": {"name": "Test Ring 886", "category": "Test", "platform": "Console"}, "-866158444": {"name": "Test Ring 887", "category": "Test", "platform": "Console"}, "-866122507": {"name": "Test Ring 888", "category": "Test", "platform": "Console"}, "-866086570": {"name": "Test Ring 889", "category": "Test", "platform": "Console"}, "-865224082": {"name": "Test Ring 890", "category": "Test", "platform": "Console"}, "-865188145": {"name": "Test Ring 891", "category": "Test", "platform": "Console"}, "-865152208": {"name": "Test Ring 892", "category": "Test", "platform": "Console"}, "-865116271": {"name": "Test Ring 893", "category": "Test", "platform": "Console"}, "-865080334": {"name": "Test Ring 894", "category": "Test", "platform": "Console"}, "-865044397": {"name": "Test Ring 895", "category": "Test", "platform": "Console"}, "-865008460": {"name": "Test Ring 896", "category": "Test", "platform": "Console"}, "-864972523": {"name": "Test Ring 897", "category": "Test", "platform": "Console"}, "-864936586": {"name": "Test Ring 898", "category": "Test", "platform": "Console"}, "-864900649": {"name": "Test Ring 899", "category": "Test", "platform": "Console"}, "-836761978": {"name": "Test Ring 900", "category": "Test", "platform": "Console"}, "-836726041": {"name": "Test Ring 901", "category": "Test", "platform": "Console"}, "-836690104": {"name": "Test Ring 902", "category": "Test", "platform": "Console"}, "-836654167": {"name": "Test Ring 903", "category": "Test", "platform": "Console"}, "-836618230": {"name": "Test Ring 904", "category": "Test", "platform": "Console"}, "-836582293": {"name": "Test Ring 905", "category": "Test", "platform": "Console"}, "-836546356": {"name": "Test Ring 906", "category": "Test", "platform": "Console"}, "-836510419": {"name": "Test Ring 907", "category": "Test", "platform": "Console"}, "-836474482": {"name": "Test Ring 908", "category": "Test", "platform": "Console"}, "-836438545": {"name": "Test Ring 909", "category": "Test", "platform": "Console"}, "-835576057": {"name": "Test Ring 910", "category": "Test", "platform": "Console"}, "-835540120": {"name": "Test Ring 911", "category": "Test", "platform": "Console"}, "-835504183": {"name": "Test Ring 912", "category": "Test", "platform": "Console"}, "-835468246": {"name": "Test Ring 913", "category": "Test", "platform": "Console"}, "-835432309": {"name": "Test Ring 914", "category": "Test", "platform": "Console"}, "-835396372": {"name": "Test Ring 915", "category": "Test", "platform": "Console"}, "-835360435": {"name": "Test Ring 916", "category": "Test", "platform": "Console"}, "-835324498": {"name": "Test Ring 917", "category": "Test", "platform": "Console"}, "-835288561": {"name": "Test Ring 918", "category": "Test", "platform": "Console"}, "-835252624": {"name": "Test Ring 919", "category": "Test", "platform": "Console"}, "-834390136": {"name": "Test Ring 920", "category": "Test", "platform": "Console"}, "-834354199": {"name": "Test Ring 921", "category": "Test", "platform": "Console"}, "-834318262": {"name": "Test Ring 922", "category": "Test", "platform": "Console"}, "-834282325": {"name": "Test Ring 923", "category": "Test", "platform": "Console"}, "-834246388": {"name": "Test Ring 924", "category": "Test", "platform": "Console"}, "-834210451": {"name": "Test Ring 925", "category": "Test", "platform": "Console"}, "-834174514": {"name": "Test Ring 926", "category": "Test", "platform": "Console"}, "-834138577": {"name": "Test Ring 927", "category": "Test", "platform": "Console"}, "-834102640": {"name": "Test Ring 928", "category": "Test", "platform": "Console"}, "-834066703": {"name": "Test Ring 929", "category": "Test", "platform": "Console"}, "-833204215": {"name": "Test Ring 930", "category": "Test", "platform": "Console"}, "-833168278": {"name": "Test Ring 931", "category": "Test", "platform": "Console"}, "-833132341": {"name": "Test Ring 932", "category": "Test", "platform": "Console"}, "-833096404": {"name": "Test Ring 933", "category": "Test", "platform": "Console"}, "-833060467": {"name": "Test Ring 934", "category": "Test", "platform": "Console"}, "-833024530": {"name": "Test Ring 935", "category": "Test", "platform": "Console"}, "-832988593": {"name": "Test Ring 936", "category": "Test", "platform": "Console"}, "-832952656": {"name": "Test Ring 937", "category": "Test", "platform": "Console"}, "-832916719": {"name": "Test Ring 938", "category": "Test", "platform": "Console"}, "-832880782": {"name": "Test Ring 939", "category": "Test", "platform": "Console"}, "-832018294": {"name": "Test Ring 940", "category": "Test", "platform": "Console"}, "-831982357": {"name": "Test Ring 941", "category": "Test", "platform": "Console"}, "-831946420": {"name": "Test Ring 942", "category": "Test", "platform": "Console"}, "-831910483": {"name": "Test Ring 943", "category": "Test", "platform": "Console"}, "-831874546": {"name": "Test Ring 944", "category": "Test", "platform": "Console"}, "-831838609": {"name": "Test Ring 945", "category": "Test", "platform": "Console"}, "-831802672": {"name": "Test Ring 946", "category": "Test", "platform": "Console"}, "-831766735": {"name": "Test Ring 947", "category": "Test", "platform": "Console"}, "-831730798": {"name": "Test Ring 948", "category": "Test", "platform": "Console"}, "-831694861": {"name": "Test Ring 949", "category": "Test", "platform": "Console"}, "-830832373": {"name": "Test Ring 950", "category": "Test", "platform": "Console"}, "-830796436": {"name": "Test Ring 951", "category": "Test", "platform": "Console"}, "-830760499": {"name": "Test Ring 952", "category": "Test", "platform": "Console"}, "-830724562": {"name": "Test Ring 953", "category": "Test", "platform": "Console"}, "-830688625": {"name": "Test Ring 954", "category": "Test", "platform": "Console"}, "-830652688": {"name": "Test Ring 955", "category": "Test", "platform": "Console"}, "-830616751": {"name": "Test Ring 956", "category": "Test", "platform": "Console"}, "-830580814": {"name": "Test Ring 957", "category": "Test", "platform": "Console"}, "-830544877": {"name": "Test Ring 958", "category": "Test", "platform": "Console"}, "-830508940": {"name": "Test Ring 959", "category": "Test", "platform": "Console"}, "-829646452": {"name": "Test Ring 960", "category": "Test", "platform": "Console"}, "-829610515": {"name": "Test Ring 961", "category": "Test", "platform": "Console"}, "-829574578": {"name": "Test Ring 962", "category": "Test", "platform": "Console"}, "-829538641": {"name": "Test Ring 963", "category": "Test", "platform": "Console"}, "-829502704": {"name": "Test Ring 964", "category": "Test", "platform": "Console"}, "-829466767": {"name": "Test Ring 965", "category": "Test", "platform": "Console"}, "-829430830": {"name": "Test Ring 966", "category": "Test", "platform": "Console"}, "-829394893": {"name": "Test Ring 967", "category": "Test", "platform": "Console"}, "-829358956": {"name": "Test Ring 968", "category": "Test", "platform": "Console"}, "-829323019": {"name": "Test Ring 969", "category": "Test", "platform": "Console"}, "-828460531": {"name": "Test Ring 970", "category": "Test", "platform": "Console"}, "-828424594": {"name": "Test Ring 971", "category": "Test", "platform": "Console"}, "-828388657": {"name": "Test Ring 972", "category": "Test", "platform": "Console"}, "-828352720": {"name": "Test Ring 973", "category": "Test", "platform": "Console"}, "-828316783": {"name": "Test Ring 974", "category": "Test", "platform": "Console"}, "-828280846": {"name": "Test Ring 975", "category": "Test", "platform": "Console"}, "-828244909": {"name": "Test Ring 976", "category": "Test", "platform": "Console"}, "-828208972": {"name": "Test Ring 977", "category": "Test", "platform": "Console"}, "-828173035": {"name": "Test Ring 978", "category": "Test", "platform": "Console"}, "-828137098": {"name": "Test Ring 979", "category": "Test", "platform": "Console"}, "-827274610": {"name": "Test Ring 980", "category": "Test", "platform": "Console"}, "-827238673": {"name": "Test Ring 981", "category": "Test", "platform": "Console"}, "-827202736": {"name": "Test Ring 982", "category": "Test", "platform": "Console"}, "-827166799": {"name": "Test Ring 983", "category": "Test", "platform": "Console"}, "-827130862": {"name": "Test Ring 984", "category": "Test", "platform": "Console"}, "-827094925": {"name": "Test Ring 985", "category": "Test", "platform": "Console"}, "-827058988": {"name": "Test Ring 986", "category": "Test", "platform": "Console"}, "-827023051": {"name": "Test Ring 987", "category": "Test", "platform": "Console"}, "-826987114": {"name": "Test Ring 988", "category": "Test", "platform": "Console"}, "-826951177": {"name": "Test Ring 989", "category": "Test", "platform": "Console"}, "-826088689": {"name": "Test Ring 990", "category": "Test", "platform": "Console"}, "-826052752": {"name": "Test Ring 991", "category": "Test", "platform": "Console"}, "-826016815": {"name": "Test Ring 992", "category": "Test", "platform": "Console"}, "-825980878": {"name": "Test Ring 993", "category": "Test", "platform": "Console"}, "-825944941": {"name": "Test Ring 994", "category": "Test", "platform": "Console"}, "-825909004": {"name": "Test Ring 995", "category": "Test", "platform": "Console"}, "-825873067": {"name": "Test Ring 996", "category": "Test", "platform": "Console"}, "-825837130": {"name": "Test Ring 997", "category": "Test", "platform": "Console"}, "-825801193": {"name": "Test Ring 998", "category": "Test", "platform": "Console"}, "-825765256": {"name": "Test Ring 999", "category": "Test", "platform": "Console"}}, "Voodoo Masks": {"620034067": {"name": "02: Shaman Mask (AR 36-41)", "category": "Voodoo Masks", "platform": "Console"}, "620034068": {"name": "03: Chieftain Mask (AR 60-69)", "category": "Voodoo Masks", "platform": "Console"}, "620034069": {"name": "04: Spirit Mask (AR 84-113)", "category": "Voodoo Masks", "platform": "Console"}, "620035155": {"name": "05: Woodwraith Bark (AR 114-149)", "category": "Voodoo Masks", "platform": "Console"}, "620035156": {"name": "06: Burial Mask (AR 150-185)", "category": "Voodoo Masks", "platform": "Console"}, "620035157": {"name": "07: Naga Mask (AR 186-232)", "category": "Voodoo Masks", "platform": "Console"}, "620035158": {"name": "08: Umbra Mask (AR 232-254)", "category": "Voodoo Masks", "platform": "Console"}, "620036244": {"name": "09: Screaming Mask (AR 255-322)", "category": "Voodoo Masks", "platform": "Console"}, "620036245": {"name": "10: Underworld Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036246": {"name": "11: Manitou Mask (AR 322-359)", "category": "Voodoo Masks", "platform": "Console"}, "620036247": {"name": "12: Deva (AR 360-472)", "category": "Voodoo Masks", "platform": "Console"}, "620036248": {"name": "13: Tribal Mask (AR 472-659)", "category": "Voodoo Masks", "platform": "Console"}, "620036249": {"name": "14: Ascended Mask (AR 660-759)", "category": "Voodoo Masks", "platform": "Console"}, "-1716736265": {"name": "Art Test VoodooMask 1", "category": "Voodoo Masks", "platform": "Console"}, "-1716736264": {"name": "Art Test VoodooMask 2", "category": "Voodoo Masks", "platform": "Console"}, "-1716736263": {"name": "Art Test VoodooMask 3", "category": "Voodoo Masks", "platform": "Console"}, "-1716736262": {"name": "Art Test VoodooMask 4", "category": "Voodoo Masks", "platform": "Console"}, "-1716736261": {"name": "Art Test VoodooMask 5", "category": "Voodoo Masks", "platform": "Console"}, "-801205711": {"name": "Legendary: Carnevil", "category": "Voodoo Masks", "platform": "Console"}, "-801169774": {"name": "Legendary: Mask of Jeram", "category": "Voodoo Masks", "platform": "Console"}, "-840197356": {"name": "Legendary: Quetzalcoatl", "category": "Voodoo Masks", "platform": "Console"}, "-1956786272": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1956783828": {"name": "Legendary: Quetzalcoatl (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555852": {"name": "Legendary: Quetzalcoatl (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840161419": {"name": "Legendary: Split Tusk", "category": "Voodoo Masks", "platform": "Console"}, "-1955600351": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1955597907": {"name": "Legendary: Split Tusk (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555853": {"name": "Legendary: Split Tusk (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840305167": {"name": "Legendary: The Grin Reaper", "category": "Voodoo Masks", "platform": "Console"}, "-1960344035": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1960341591": {"name": "Legendary: The Grin Reaper (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555849": {"name": "Legendary: The Grin Reaper (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840341104": {"name": "Legendary: Tiklandian Visage", "category": "Voodoo Masks", "platform": "Console"}, "-1961529956": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1961527512": {"name": "Legendary: Tiklandian Visage (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555848": {"name": "Legendary: Tiklandian Visage (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840089545": {"name": "Legendary: Visage of Giyua", "category": "Voodoo Masks", "platform": "Console"}, "-1953228509": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1953226065": {"name": "Legendary: Visage of Giyua (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555855": {"name": "Legendary: Visage of Giyua (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "270555854": {"name": "Set: Zunimassa's Attunement (Old-Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-840125482": {"name": "Set: Zunimassa's Vision", "category": "Voodoo Masks", "platform": "Console"}, "-1954414430": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}, "-1954411986": {"name": "Set: Zunimassa's Vision (Legacy)", "category": "Voodoo Masks", "platform": "Console"}}, "Wands": {"88665050": {"name": "01: Lesser Wand (DPS 9.8-11.2)", "category": "Wands", "platform": "Console"}, "88665051": {"name": "02: Oak Wand (DPS 11.2-13.3)", "category": "Wands", "platform": "Console"}, "88665052": {"name": "03: Wand (DPS 14.7-16.8)", "category": "Wands", "platform": "Console"}, "88665053": {"name": "04: Steel Wand (DPS 17.5-19.6)", "category": "Wands", "platform": "Console"}, "88665054": {"name": "05: Mentor Wand (DPS 21.7-23.8)", "category": "Wands", "platform": "Console"}, "88665055": {"name": "06: Enchanter Wand (DPS 25.2-27.3)", "category": "Wands", "platform": "Console"}, "88665056": {"name": "07: Grim Wand (DPS 29.4-31.5)", "category": "Wands", "platform": "Console"}, "88666139": {"name": "08: Petrified Wand (DPS 41.3-43.4)", "category": "Wands", "platform": "Console"}, "88666140": {"name": "09: Duelist Wand (DPS 47.6-49.7)", "category": "Wands", "platform": "Console"}, "88666141": {"name": "10: Jade Wand (DPS 55.3-57.4)", "category": "Wands", "platform": "Console"}, "88666142": {"name": "11: Battle Wand (DPS 65.1-67.2)", "category": "Wands", "platform": "Console"}, "88666143": {"name": "12: Divination Wand (DPS 75.6-77.7)", "category": "Wands", "platform": "Console"}, "88666144": {"name": "13: Sorcery Wand (DPS 89.6-93.8)", "category": "Wands", "platform": "Console"}, "88666145": {"name": "14: Silversteel Wand (DPS 105.0-109.2)", "category": "Wands", "platform": "Console"}, "88667228": {"name": "15: Greater Wand (DPS 115.5-119.7)", "category": "Wands", "platform": "Console"}, "88667229": {"name": "16: Guardian (DPS 127.4-131.6)", "category": "Wands", "platform": "Console"}, "88667230": {"name": "17: Magus Wand (DPS 139.3-145.6)", "category": "Wands", "platform": "Console"}, "88667231": {"name": "18: Spellbinder (DPS 153.3-159.6)", "category": "Wands", "platform": "Console"}, "88667232": {"name": "19: Archmage Wand (DPS 177.1-183.4)", "category": "Wands", "platform": "Console"}, "88667233": {"name": "20: Strike Wand (DPS 203.0-211.4)", "category": "Wands", "platform": "Console"}, "88667234": {"name": "21: Desolator Wand (DPS 235.2-243.6)", "category": "Wands", "platform": "Console"}, "88668317": {"name": "22: Demon's Head Wand (DPS 315.0-321.3)", "category": "Wands", "platform": "Console"}, "88668318": {"name": "23: Diabolic Wand (DPS 385.0-391.3)", "category": "Wands", "platform": "Console"}, "2004783359": {"name": "Art Test Wand 1", "category": "Wands", "platform": "Console"}, "2004783360": {"name": "Art Test Wand 2", "category": "Wands", "platform": "Console"}, "2004783361": {"name": "Art Test Wand 3", "category": "Wands", "platform": "Console"}, "2004783362": {"name": "Art Test Wand 4", "category": "Wands", "platform": "Console"}, "2004783363": {"name": "Art Test Wand 5", "category": "Wands", "platform": "Console"}, "456527018": {"name": "Crafted: Elderwood Wand", "category": "Wands", "platform": "Console"}, "-1415147493": {"name": "Legendary: Aether Walker (Patch 2.1.0)", "category": "Wands", "platform": "Console"}, "1859914464": {"name": "Legendary: Atrophy", "category": "Wands", "platform": "Console"}, "1859806653": {"name": "Legendary: Blackhand Key", "category": "Wands", "platform": "Console"}, "1244000105": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "1244002549": {"name": "Legendary: Blackhand Key (Legacy)", "category": "Wands", "platform": "Console"}, "161873429": {"name": "Legendary: Blackhand Key (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860776952": {"name": "Legendary: Fragment of Destiny", "category": "Wands", "platform": "Console"}, "1276019972": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "1276022416": {"name": "Legendary: Fragment of Destiny (Legacy)", "category": "Wands", "platform": "Console"}, "161873456": {"name": "Legendary: Fragment of Destiny (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859662905": {"name": "Legendary: Gesture of Orpheus", "category": "Wands", "platform": "Console"}, "1239256421": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "1239258865": {"name": "Legendary: Gesture of Orpheus (Legacy)", "category": "Wands", "platform": "Console"}, "161873425": {"name": "Legendary: Gesture of Orpheus (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1247557868": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "1247560312": {"name": "Legendary: Ruinstoke (Legacy)", "category": "Wands", "platform": "Console"}, "161873432": {"name": "Legendary: Ruinstoke (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898798298": {"name": "Legendary: Serpent's Sparker", "category": "Wands", "platform": "Console"}, "1860884763": {"name": "Legendary: Slorak's Madness", "category": "Wands", "platform": "Console"}, "1279577735": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "1279580179": {"name": "Legendary: Slorak's Madness (Legacy)", "category": "Wands", "platform": "Console"}, "161873459": {"name": "Legendary: Slorak's Madness (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1859698842": {"name": "Legendary: Starfire", "category": "Wands", "platform": "Console"}, "1240442342": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "1240444786": {"name": "Legendary: Starfire (Legacy)", "category": "Wands", "platform": "Console"}, "161873426": {"name": "Legendary: Starfire (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1898762361": {"name": "Legendary: Wand of Woh", "category": "Wands", "platform": "Console"}, "-1415147492": {"name": "P1 Wand norm Legendary 02", "category": "Wands", "platform": "Console"}, "161873458": {"name": "Set: Chantodo's Sacred Protector (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1860848826": {"name": "Set: Chantodo's Will", "category": "Wands", "platform": "Console"}, "1278391814": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1278394258": {"name": "Set: Chantodo's Will (Legacy)", "category": "Wands", "platform": "Console"}, "1861064448": {"name": "Set: Hallowed Baton", "category": "Wands", "platform": "Console"}, "161873464": {"name": "Set: Hallowed Rod (Old-Legacy)", "category": "Wands", "platform": "Console"}, "1285507340": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1285509784": {"name": "Set: Hallowed Scepter (Legacy)", "category": "Wands", "platform": "Console"}, "1771839282": {"name": "legendary: Gesture Of Orpheus (Patch 2.2.0)", "category": "Wands", "platform": "Console"}}, "Wizard Hats": {"1755621631": {"name": "02: Journey Mask (AR 36-41)", "category": "Wizard Hats", "platform": "Console"}, "1755621632": {"name": "03: Scholarly Fez (AR 60-69)", "category": "Wizard Hats", "platform": "Console"}, "1755621633": {"name": "04: Charlatan Cap (AR 84-113)", "category": "Wizard Hats", "platform": "Console"}, "1755622719": {"name": "05: Conjurer Shade (AR 114-149)", "category": "Wizard Hats", "platform": "Console"}, "1755622720": {"name": "06: Mystic Shade (AR 150-185)", "category": "Wizard Hats", "platform": "Console"}, "1755622721": {"name": "07: Mentor Cap (AR 186-232)", "category": "Wizard Hats", "platform": "Console"}, "1755622722": {"name": "08: Traveler Hat (AR 232-254)", "category": "Wizard Hats", "platform": "Console"}, "1755623808": {"name": "09: Sage Hat (AR 255-284)", "category": "Wizard Hats", "platform": "Console"}, "1755623809": {"name": "10: Sinister Mask (AR 285-322)", "category": "Wizard Hats", "platform": "Console"}, "1755623810": {"name": "11: Archmage Headpiece (AR 322-359)", "category": "Wizard Hats", "platform": "Console"}, "1755623811": {"name": "12: Elder Hat (AR 360-472)", "category": "Wizard Hats", "platform": "Console"}, "1755623812": {"name": "13: Vizier Hat (AR 472-659)", "category": "Wizard Hats", "platform": "Console"}, "1755623813": {"name": "14: Ascended Headpiece (AR 660-759)", "category": "Wizard Hats", "platform": "Console"}, "376117315": {"name": "Art Test WizardHat 1", "category": "Wizard Hats", "platform": "Console"}, "376117316": {"name": "Art Test WizardHat 2", "category": "Wizard Hats", "platform": "Console"}, "376117317": {"name": "Art Test WizardHat 3", "category": "Wizard Hats", "platform": "Console"}, "376117318": {"name": "Art Test WizardHat 4", "category": "Wizard Hats", "platform": "Console"}, "376117319": {"name": "Art Test WizardHat 5", "category": "Wizard Hats", "platform": "Console"}, "414491869": {"name": "Legendary: Archmage's Vicalyke", "category": "Wizard Hats", "platform": "Console"}, "375356476": {"name": "Legendary: Dark Mage's Shade", "category": "Wizard Hats", "platform": "Console"}, "-498215480": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-498213036": {"name": "Legendary: Dark Mage's Shade (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827188": {"name": "Legendary: Dark Mage's Shade (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414599680": {"name": "Legendary: Mask of Lies", "category": "Wizard Hats", "platform": "Console"}, "375464287": {"name": "Legendary: Storm Crow", "category": "Wizard Hats", "platform": "Console"}, "-494657717": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-494655273": {"name": "Legendary: Storm Crow (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827191": {"name": "Legendary: Storm Crow (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "414563743": {"name": "Legendary: The Magistrate", "category": "Wizard Hats", "platform": "Console"}, "375428350": {"name": "Legendary: The Swami", "category": "Wizard Hats", "platform": "Console"}, "-495843638": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-495841194": {"name": "Legendary: The Swami (Legacy)", "category": "Wizard Hats", "platform": "Console"}, "703827190": {"name": "Legendary: The Swami (Old-Legacy)", "category": "Wizard Hats", "platform": "Console"}, "-936099818": {"name": "Legendary: The Swami (Patch 2.1.0)", "category": "Wizard Hats", "platform": "Console"}, "414527806": {"name": "Legendary: Velvet Camaral", "category": "Wizard Hats", "platform": "Console"}}} \ No newline at end of file From bebdae6463003bb81e1bc38babba7ff63a0d98db Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 26 Nov 2018 10:23:04 +0000 Subject: [PATCH 032/115] Inserts effectiveness values into affix effects for the GUI. --- save_manager/item_handler.py | 5 +++++ settings.py | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/save_manager/item_handler.py b/save_manager/item_handler.py index f2a120b..2ec2014 100644 --- a/save_manager/item_handler.py +++ b/save_manager/item_handler.py @@ -1,5 +1,7 @@ +import re from settings import gbid_list from settings import affixes_list +from settings import affix_regexes def gbid_to_str(gbid): @@ -13,6 +15,9 @@ def gbid_to_str(gbid): def affix_to_str(affix): try: affix_return = affixes_list[str(affix)] + wc = re.search(affix_regexes, affix_return['effect']) + if wc and affix_return['effectiveness']: + affix_return['effect'] = affix_return['effect'].replace(wc.group(0), affix_return['effectiveness']) except KeyError: affix_return = {'effect': 'Unknown Affix'} return affix_return diff --git a/settings.py b/settings.py index f1c3dbc..e29ae7e 100644 --- a/settings.py +++ b/settings.py @@ -5,6 +5,9 @@ with open('settings.json') as f: settings = load(f) +# define affix regexes to insert effect values. +affix_regexes = '(?PX-X|^X | X$)' + # apply settings ASSET_DIR = settings['directories']['ASSET_DIR'] HERO_DIR = settings['directories']['HERO_DIR'] @@ -31,4 +34,4 @@ with open(join(ASSET_DIR, CURRENCY_FILE), "r") as f: currency_list = load(f) with open(join(ASSET_DIR, GBID_CAT_FILE), "r") as f: - gbid_cat = load(f) + gbid_cat = load(f) \ No newline at end of file From be883923ea3adaf7b351e72a82a235084601f8c6 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 26 Nov 2018 10:27:07 +0000 Subject: [PATCH 033/115] Small refactor to de-clutter project main folder. --- Account_pb2.py => pb2_resources/Account_pb2.py | 14 ++++---------- .../Achievements_pb2.py | 4 +--- .../AttributeSerializer_pb2.py | 4 +--- .../ChallengeRifts_pb2.py | 4 +--- .../CosmeticItems_pb2.py | 4 +--- D3Edit.py => pb2_resources/D3Edit.py | 0 .../GameBalance_pb2.py | 0 .../HeroCommon_pb2.py | 0 Hero_pb2.py => pb2_resources/Hero_pb2.py | 12 +++--------- Hireling_pb2.py => pb2_resources/Hireling_pb2.py | 0 .../ItemCrafting_pb2.py | 4 +--- Items_pb2.py => pb2_resources/Items_pb2.py | 5 +---- .../OnlineService_pb2.py | 0 Profile_pb2.py => pb2_resources/Profile_pb2.py | 7 ++----- pb2_resources/__init__.py | 0 save_manager/__init__.py | 3 +-- 16 files changed, 16 insertions(+), 45 deletions(-) rename Account_pb2.py => pb2_resources/Account_pb2.py (99%) rename Achievements_pb2.py => pb2_resources/Achievements_pb2.py (99%) rename AttributeSerializer_pb2.py => pb2_resources/AttributeSerializer_pb2.py (98%) rename ChallengeRifts_pb2.py => pb2_resources/ChallengeRifts_pb2.py (99%) rename CosmeticItems_pb2.py => pb2_resources/CosmeticItems_pb2.py (98%) rename D3Edit.py => pb2_resources/D3Edit.py (100%) rename GameBalance_pb2.py => pb2_resources/GameBalance_pb2.py (100%) rename HeroCommon_pb2.py => pb2_resources/HeroCommon_pb2.py (100%) rename Hero_pb2.py => pb2_resources/Hero_pb2.py (99%) rename Hireling_pb2.py => pb2_resources/Hireling_pb2.py (100%) rename ItemCrafting_pb2.py => pb2_resources/ItemCrafting_pb2.py (99%) rename Items_pb2.py => pb2_resources/Items_pb2.py (99%) rename OnlineService_pb2.py => pb2_resources/OnlineService_pb2.py (100%) rename Profile_pb2.py => pb2_resources/Profile_pb2.py (99%) create mode 100644 pb2_resources/__init__.py diff --git a/Account_pb2.py b/pb2_resources/Account_pb2.py similarity index 99% rename from Account_pb2.py rename to pb2_resources/Account_pb2.py index e0379ac..65aa3fe 100644 --- a/Account_pb2.py +++ b/pb2_resources/Account_pb2.py @@ -11,16 +11,10 @@ _sym_db = _symbol_database.Default() - -import AttributeSerializer_pb2 as AttributeSerializer__pb2 -import Achievements_pb2 as Achievements__pb2 -import Items_pb2 as Items__pb2 -import OnlineService_pb2 as OnlineService__pb2 -import ItemCrafting_pb2 as ItemCrafting__pb2 -import CosmeticItems_pb2 as CosmeticItems__pb2 -import GameBalance_pb2 as GameBalance__pb2 -import ChallengeRifts_pb2 as ChallengeRifts__pb2 - +from pb2_resources import AttributeSerializer_pb2 as AttributeSerializer__pb2, GameBalance_pb2 as GameBalance__pb2, \ + OnlineService_pb2 as OnlineService__pb2, ItemCrafting_pb2 as ItemCrafting__pb2, Items_pb2 as Items__pb2, \ + ChallengeRifts_pb2 as ChallengeRifts__pb2, CosmeticItems_pb2 as CosmeticItems__pb2, \ + Achievements_pb2 as Achievements__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='Account.proto', diff --git a/Achievements_pb2.py b/pb2_resources/Achievements_pb2.py similarity index 99% rename from Achievements_pb2.py rename to pb2_resources/Achievements_pb2.py index 38bfb77..a0ed65b 100644 --- a/Achievements_pb2.py +++ b/pb2_resources/Achievements_pb2.py @@ -11,9 +11,7 @@ _sym_db = _symbol_database.Default() - -import OnlineService_pb2 as OnlineService__pb2 - +from pb2_resources import OnlineService_pb2 as OnlineService__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='Achievements.proto', diff --git a/AttributeSerializer_pb2.py b/pb2_resources/AttributeSerializer_pb2.py similarity index 98% rename from AttributeSerializer_pb2.py rename to pb2_resources/AttributeSerializer_pb2.py index b62c9fb..d9313b0 100644 --- a/AttributeSerializer_pb2.py +++ b/pb2_resources/AttributeSerializer_pb2.py @@ -11,9 +11,7 @@ _sym_db = _symbol_database.Default() - -import GameBalance_pb2 as GameBalance__pb2 - +from pb2_resources import GameBalance_pb2 as GameBalance__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='AttributeSerializer.proto', diff --git a/ChallengeRifts_pb2.py b/pb2_resources/ChallengeRifts_pb2.py similarity index 99% rename from ChallengeRifts_pb2.py rename to pb2_resources/ChallengeRifts_pb2.py index 6944095..5275aeb 100644 --- a/ChallengeRifts_pb2.py +++ b/pb2_resources/ChallengeRifts_pb2.py @@ -11,9 +11,7 @@ _sym_db = _symbol_database.Default() - -import HeroCommon_pb2 as HeroCommon__pb2 - +from pb2_resources import HeroCommon_pb2 as HeroCommon__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='ChallengeRifts.proto', diff --git a/CosmeticItems_pb2.py b/pb2_resources/CosmeticItems_pb2.py similarity index 98% rename from CosmeticItems_pb2.py rename to pb2_resources/CosmeticItems_pb2.py index e202f0d..92964d0 100644 --- a/CosmeticItems_pb2.py +++ b/pb2_resources/CosmeticItems_pb2.py @@ -11,9 +11,7 @@ _sym_db = _symbol_database.Default() - -import GameBalance_pb2 as GameBalance__pb2 - +from pb2_resources import GameBalance_pb2 as GameBalance__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='CosmeticItems.proto', diff --git a/D3Edit.py b/pb2_resources/D3Edit.py similarity index 100% rename from D3Edit.py rename to pb2_resources/D3Edit.py diff --git a/GameBalance_pb2.py b/pb2_resources/GameBalance_pb2.py similarity index 100% rename from GameBalance_pb2.py rename to pb2_resources/GameBalance_pb2.py diff --git a/HeroCommon_pb2.py b/pb2_resources/HeroCommon_pb2.py similarity index 100% rename from HeroCommon_pb2.py rename to pb2_resources/HeroCommon_pb2.py diff --git a/Hero_pb2.py b/pb2_resources/Hero_pb2.py similarity index 99% rename from Hero_pb2.py rename to pb2_resources/Hero_pb2.py index 3c268eb..7d17d64 100644 --- a/Hero_pb2.py +++ b/pb2_resources/Hero_pb2.py @@ -11,15 +11,9 @@ _sym_db = _symbol_database.Default() - -import AttributeSerializer_pb2 as AttributeSerializer__pb2 -import Hireling_pb2 as Hireling__pb2 -import Items_pb2 as Items__pb2 -import OnlineService_pb2 as OnlineService__pb2 -import HeroCommon_pb2 as HeroCommon__pb2 -import Profile_pb2 as Profile__pb2 -import GameBalance_pb2 as GameBalance__pb2 - +from pb2_resources import AttributeSerializer_pb2 as AttributeSerializer__pb2, HeroCommon_pb2 as HeroCommon__pb2, \ + GameBalance_pb2 as GameBalance__pb2, OnlineService_pb2 as OnlineService__pb2, Profile_pb2 as Profile__pb2, \ + Items_pb2 as Items__pb2, Hireling_pb2 as Hireling__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='Hero.proto', diff --git a/Hireling_pb2.py b/pb2_resources/Hireling_pb2.py similarity index 100% rename from Hireling_pb2.py rename to pb2_resources/Hireling_pb2.py diff --git a/ItemCrafting_pb2.py b/pb2_resources/ItemCrafting_pb2.py similarity index 99% rename from ItemCrafting_pb2.py rename to pb2_resources/ItemCrafting_pb2.py index f5db131..9ca4ea4 100644 --- a/ItemCrafting_pb2.py +++ b/pb2_resources/ItemCrafting_pb2.py @@ -11,9 +11,7 @@ _sym_db = _symbol_database.Default() - -import GameBalance_pb2 as GameBalance__pb2 - +from pb2_resources import GameBalance_pb2 as GameBalance__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='ItemCrafting.proto', diff --git a/Items_pb2.py b/pb2_resources/Items_pb2.py similarity index 99% rename from Items_pb2.py rename to pb2_resources/Items_pb2.py index 630cefe..ea8cd2c 100644 --- a/Items_pb2.py +++ b/pb2_resources/Items_pb2.py @@ -11,10 +11,7 @@ _sym_db = _symbol_database.Default() - -import GameBalance_pb2 as GameBalance__pb2 -import OnlineService_pb2 as OnlineService__pb2 - +from pb2_resources import GameBalance_pb2 as GameBalance__pb2, OnlineService_pb2 as OnlineService__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='Items.proto', diff --git a/OnlineService_pb2.py b/pb2_resources/OnlineService_pb2.py similarity index 100% rename from OnlineService_pb2.py rename to pb2_resources/OnlineService_pb2.py diff --git a/Profile_pb2.py b/pb2_resources/Profile_pb2.py similarity index 99% rename from Profile_pb2.py rename to pb2_resources/Profile_pb2.py index d0ddbef..2fce46e 100644 --- a/Profile_pb2.py +++ b/pb2_resources/Profile_pb2.py @@ -11,11 +11,8 @@ _sym_db = _symbol_database.Default() - -import Items_pb2 as Items__pb2 -import OnlineService_pb2 as OnlineService__pb2 -import HeroCommon_pb2 as HeroCommon__pb2 - +from pb2_resources import HeroCommon_pb2 as HeroCommon__pb2, OnlineService_pb2 as OnlineService__pb2, \ + Items_pb2 as Items__pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='Profile.proto', diff --git a/pb2_resources/__init__.py b/pb2_resources/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/save_manager/__init__.py b/save_manager/__init__.py index 34d6073..d7cab63 100644 --- a/save_manager/__init__.py +++ b/save_manager/__init__.py @@ -1,5 +1,4 @@ -import Account_pb2 -import Hero_pb2 +from pb2_resources import Hero_pb2, Account_pb2 import glob from os.path import dirname, basename From 99f15a403dbadaa4d817947b222f4fe25767e3c0 Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 26 Nov 2018 10:30:27 +0000 Subject: [PATCH 034/115] Small refactor to de-clutter project main folder. --- pb2_resources/D3Edit.py => D3Edit.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pb2_resources/D3Edit.py => D3Edit.py (100%) diff --git a/pb2_resources/D3Edit.py b/D3Edit.py similarity index 100% rename from pb2_resources/D3Edit.py rename to D3Edit.py From ed9b09097faa075d66a7755920234be710d3284a Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 26 Nov 2018 11:36:39 +0000 Subject: [PATCH 035/115] Adds linux/darwin venv with dependencies --- D3Edit.py | 18 +- venv/.Python | 1 + venv/bin/activate | 78 + venv/bin/activate.csh | 36 + venv/bin/activate.fish | 76 + venv/bin/activate_this.py | 34 + venv/bin/easy_install | 11 + venv/bin/easy_install-3.7 | 11 + venv/bin/pip | 11 + venv/bin/pip3 | 11 + venv/bin/pip3.7 | 11 + venv/bin/python | 1 + venv/bin/python-config | 78 + venv/bin/python3 | 1 + venv/bin/python3.7 | Bin 0 -> 12552 bytes venv/bin/wheel | 11 + venv/include/python3.7m | 1 + venv/lib/python3.7/__future__.py | 1 + venv/lib/python3.7/_bootlocale.py | 1 + venv/lib/python3.7/_collections_abc.py | 1 + venv/lib/python3.7/_dummy_thread.py | 1 + venv/lib/python3.7/_weakrefset.py | 1 + venv/lib/python3.7/abc.py | 1 + venv/lib/python3.7/base64.py | 1 + venv/lib/python3.7/bisect.py | 1 + venv/lib/python3.7/codecs.py | 1 + venv/lib/python3.7/collections | 1 + venv/lib/python3.7/config-3.7m-darwin | 1 + venv/lib/python3.7/copy.py | 1 + venv/lib/python3.7/copyreg.py | 1 + venv/lib/python3.7/distutils/__init__.py | 101 + venv/lib/python3.7/distutils/distutils.cfg | 6 + venv/lib/python3.7/encodings | 1 + venv/lib/python3.7/enum.py | 1 + venv/lib/python3.7/fnmatch.py | 1 + venv/lib/python3.7/functools.py | 1 + venv/lib/python3.7/genericpath.py | 1 + venv/lib/python3.7/hashlib.py | 1 + venv/lib/python3.7/heapq.py | 1 + venv/lib/python3.7/hmac.py | 1 + venv/lib/python3.7/imp.py | 1 + venv/lib/python3.7/importlib | 1 + venv/lib/python3.7/io.py | 1 + venv/lib/python3.7/keyword.py | 1 + venv/lib/python3.7/lib-dynload | 1 + venv/lib/python3.7/linecache.py | 1 + venv/lib/python3.7/locale.py | 1 + .../lib/python3.7/no-global-site-packages.txt | 0 venv/lib/python3.7/ntpath.py | 1 + venv/lib/python3.7/operator.py | 1 + venv/lib/python3.7/orig-prefix.txt | 1 + venv/lib/python3.7/os.py | 1 + venv/lib/python3.7/posixpath.py | 1 + venv/lib/python3.7/random.py | 1 + venv/lib/python3.7/re.py | 1 + venv/lib/python3.7/readline.so | 1 + venv/lib/python3.7/reprlib.py | 1 + venv/lib/python3.7/rlcompleter.py | 1 + venv/lib/python3.7/shutil.py | 1 + .../python3.7/site-packages/easy_install.py | 5 + .../site-packages/google/protobuf/__init__.py | 39 + .../site-packages/google/protobuf/any_pb2.py | 77 + .../google/protobuf/any_test_pb2.py | 87 + .../site-packages/google/protobuf/api_pb2.py | 249 + .../google/protobuf/compiler/__init__.py | 0 .../google/protobuf/compiler/plugin_pb2.py | 255 + .../google/protobuf/descriptor.py | 1076 +++ .../google/protobuf/descriptor_database.py | 162 + .../google/protobuf/descriptor_pb2.py | 2033 ++++ .../google/protobuf/descriptor_pool.py | 1057 +++ .../google/protobuf/duration_pb2.py | 77 + .../google/protobuf/empty_pb2.py | 63 + .../google/protobuf/field_mask_pb2.py | 70 + .../google/protobuf/internal/__init__.py | 0 .../_api_implementation.cpython-37m-darwin.so | Bin 0 -> 25576 bytes .../protobuf/internal/_parameterized.py | 442 + .../google/protobuf/internal/any_test_pb2.py | 182 + .../protobuf/internal/api_implementation.py | 173 + .../google/protobuf/internal/containers.py | 630 ++ .../google/protobuf/internal/decoder.py | 854 ++ .../internal/descriptor_database_test.py | 124 + .../protobuf/internal/descriptor_pool_test.py | 1055 +++ .../internal/descriptor_pool_test1_pb2.py | 474 + .../internal/descriptor_pool_test2_pb2.py | 266 + .../protobuf/internal/descriptor_test.py | 1036 +++ .../google/protobuf/internal/encoder.py | 828 ++ .../protobuf/internal/enum_type_wrapper.py | 89 + .../protobuf/internal/factory_test1_pb2.py | 190 + .../protobuf/internal/factory_test2_pb2.py | 517 ++ .../internal/file_options_test_pb2.py | 82 + .../protobuf/internal/generator_test.py | 349 + .../internal/import_test_package/__init__.py | 33 + .../internal/import_test_package/inner_pb2.py | 69 + .../internal/import_test_package/outer_pb2.py | 72 + .../protobuf/internal/json_format_test.py | 1038 +++ .../protobuf/internal/message_factory_test.py | 222 + .../protobuf/internal/message_listener.py | 78 + .../internal/message_set_extensions_pb2.py | 209 + .../google/protobuf/internal/message_test.py | 2203 +++++ .../internal/missing_enum_values_pb2.py | 227 + .../internal/more_extensions_dynamic_pb2.py | 103 + .../protobuf/internal/more_extensions_pb2.py | 183 + .../protobuf/internal/more_messages_pb2.py | 103 + .../protobuf/internal/no_package_pb2.py | 97 + .../internal/packed_field_test_pb2.py | 334 + .../protobuf/internal/proto_builder_test.py | 96 + .../protobuf/internal/python_message.py | 1559 ++++ .../protobuf/internal/reflection_test.py | 3106 +++++++ .../internal/service_reflection_test.py | 144 + .../protobuf/internal/symbol_database_test.py | 138 + .../internal/test_bad_identifiers_pb2.py | 163 + .../google/protobuf/internal/test_util.py | 868 ++ .../protobuf/internal/testing_refleaks.py | 126 + .../protobuf/internal/text_encoding_test.py | 72 + .../protobuf/internal/text_format_test.py | 1656 ++++ .../google/protobuf/internal/type_checkers.py | 353 + .../protobuf/internal/unknown_fields_test.py | 336 + .../protobuf/internal/well_known_types.py | 839 ++ .../internal/well_known_types_test.py | 927 ++ .../google/protobuf/internal/wire_format.py | 268 + .../protobuf/internal/wire_format_test.py | 257 + .../google/protobuf/json_format.py | 785 ++ .../protobuf/map_proto2_unittest_pb2.py | 1312 +++ .../google/protobuf/map_unittest_pb2.py | 2813 ++++++ .../site-packages/google/protobuf/message.py | 308 + .../google/protobuf/message_factory.py | 151 + .../google/protobuf/proto_builder.py | 130 + .../google/protobuf/pyext/__init__.py | 4 + .../pyext/_message.cpython-37m-darwin.so | Bin 0 -> 3170208 bytes .../google/protobuf/pyext/cpp_message.py | 65 + .../google/protobuf/pyext/python_pb2.py | 233 + .../google/protobuf/reflection.py | 121 + .../site-packages/google/protobuf/service.py | 226 + .../google/protobuf/service_reflection.py | 284 + .../google/protobuf/source_context_pb2.py | 70 + .../google/protobuf/struct_pb2.py | 279 + .../google/protobuf/symbol_database.py | 189 + .../protobuf/test_messages_proto2_pb2.py | 1990 ++++ .../protobuf/test_messages_proto3_pb2.py | 2044 ++++ .../google/protobuf/text_encoding.py | 107 + .../google/protobuf/text_format.py | 1593 ++++ .../google/protobuf/timestamp_pb2.py | 77 + .../site-packages/google/protobuf/type_pb2.py | 540 ++ .../google/protobuf/unittest_arena_pb2.py | 120 + .../protobuf/unittest_custom_options_pb2.py | 1845 ++++ .../google/protobuf/unittest_import_pb2.py | 137 + .../protobuf/unittest_import_public_pb2.py | 70 + .../google/protobuf/unittest_mset_pb2.py | 255 + .../protobuf/unittest_mset_wire_format_pb2.py | 104 + .../protobuf/unittest_no_arena_import_pb2.py | 69 + .../google/protobuf/unittest_no_arena_pb2.py | 911 ++ .../unittest_no_generic_services_pb2.py | 125 + .../google/protobuf/unittest_pb2.py | 7082 ++++++++++++++ .../protobuf/unittest_proto3_arena_pb2.py | 999 ++ .../google/protobuf/util/__init__.py | 0 .../protobuf/util/json_format_proto3_pb2.py | 1895 ++++ .../google/protobuf/wrappers_pb2.py | 382 + .../pip-18.1.dist-info/INSTALLER | 1 + .../pip-18.1.dist-info/LICENSE.txt | 20 + .../site-packages/pip-18.1.dist-info/METADATA | 70 + .../site-packages/pip-18.1.dist-info/RECORD | 614 ++ .../site-packages/pip-18.1.dist-info/WHEEL | 6 + .../pip-18.1.dist-info/entry_points.txt | 5 + .../pip-18.1.dist-info/top_level.txt | 1 + .../python3.7/site-packages/pip/__init__.py | 1 + .../python3.7/site-packages/pip/__main__.py | 19 + .../site-packages/pip/_internal/__init__.py | 78 + .../site-packages/pip/_internal/build_env.py | 142 + .../site-packages/pip/_internal/cache.py | 202 + .../pip/_internal/cli/__init__.py | 4 + .../pip/_internal/cli/autocompletion.py | 152 + .../pip/_internal/cli/base_command.py | 278 + .../pip/_internal/cli/cmdoptions.py | 714 ++ .../pip/_internal/cli/main_parser.py | 96 + .../site-packages/pip/_internal/cli/parser.py | 261 + .../pip/_internal/cli/status_codes.py | 8 + .../pip/_internal/commands/__init__.py | 79 + .../pip/_internal/commands/check.py | 41 + .../pip/_internal/commands/completion.py | 94 + .../pip/_internal/commands/configuration.py | 227 + .../pip/_internal/commands/download.py | 174 + .../pip/_internal/commands/freeze.py | 96 + .../pip/_internal/commands/hash.py | 57 + .../pip/_internal/commands/help.py | 37 + .../pip/_internal/commands/install.py | 535 ++ .../pip/_internal/commands/list.py | 306 + .../pip/_internal/commands/search.py | 135 + .../pip/_internal/commands/show.py | 168 + .../pip/_internal/commands/uninstall.py | 78 + .../pip/_internal/commands/wheel.py | 183 + .../pip/_internal/configuration.py | 387 + .../site-packages/pip/_internal/download.py | 921 ++ .../site-packages/pip/_internal/exceptions.py | 268 + .../site-packages/pip/_internal/index.py | 899 ++ .../site-packages/pip/_internal/locations.py | 194 + .../pip/_internal/models/__init__.py | 2 + .../pip/_internal/models/candidate.py | 23 + .../pip/_internal/models/format_control.py | 62 + .../pip/_internal/models/index.py | 29 + .../pip/_internal/models/link.py | 141 + .../pip/_internal/operations/__init__.py | 0 .../pip/_internal/operations/check.py | 148 + .../pip/_internal/operations/freeze.py | 264 + .../pip/_internal/operations/prepare.py | 355 + .../site-packages/pip/_internal/pep425tags.py | 317 + .../site-packages/pip/_internal/pyproject.py | 144 + .../pip/_internal/req/__init__.py | 69 + .../pip/_internal/req/constructors.py | 298 + .../pip/_internal/req/req_file.py | 340 + .../pip/_internal/req/req_install.py | 860 ++ .../pip/_internal/req/req_set.py | 181 + .../pip/_internal/req/req_tracker.py | 76 + .../pip/_internal/req/req_uninstall.py | 460 + .../site-packages/pip/_internal/resolve.py | 353 + .../pip/_internal/utils/__init__.py | 0 .../pip/_internal/utils/appdirs.py | 258 + .../pip/_internal/utils/compat.py | 248 + .../pip/_internal/utils/deprecation.py | 89 + .../pip/_internal/utils/encoding.py | 33 + .../pip/_internal/utils/filesystem.py | 28 + .../pip/_internal/utils/glibc.py | 84 + .../pip/_internal/utils/hashes.py | 94 + .../pip/_internal/utils/logging.py | 225 + .../site-packages/pip/_internal/utils/misc.py | 940 ++ .../pip/_internal/utils/models.py | 40 + .../pip/_internal/utils/outdated.py | 154 + .../pip/_internal/utils/packaging.py | 75 + .../pip/_internal/utils/setuptools_build.py | 8 + .../pip/_internal/utils/temp_dir.py | 82 + .../pip/_internal/utils/typing.py | 29 + .../site-packages/pip/_internal/utils/ui.py | 421 + .../pip/_internal/vcs/__init__.py | 509 + .../site-packages/pip/_internal/vcs/bazaar.py | 112 + .../site-packages/pip/_internal/vcs/git.py | 346 + .../pip/_internal/vcs/mercurial.py | 101 + .../pip/_internal/vcs/subversion.py | 213 + .../site-packages/pip/_internal/wheel.py | 831 ++ .../site-packages/pip/_vendor/__init__.py | 110 + .../site-packages/pip/_vendor/appdirs.py | 604 ++ .../pip/_vendor/cachecontrol/__init__.py | 11 + .../pip/_vendor/cachecontrol/_cmd.py | 57 + .../pip/_vendor/cachecontrol/adapter.py | 133 + .../pip/_vendor/cachecontrol/cache.py | 39 + .../_vendor/cachecontrol/caches/__init__.py | 2 + .../_vendor/cachecontrol/caches/file_cache.py | 146 + .../cachecontrol/caches/redis_cache.py | 33 + .../pip/_vendor/cachecontrol/compat.py | 29 + .../pip/_vendor/cachecontrol/controller.py | 367 + .../pip/_vendor/cachecontrol/filewrapper.py | 80 + .../pip/_vendor/cachecontrol/heuristics.py | 135 + .../pip/_vendor/cachecontrol/serialize.py | 186 + .../pip/_vendor/cachecontrol/wrapper.py | 29 + .../pip/_vendor/certifi/__init__.py | 3 + .../pip/_vendor/certifi/__main__.py | 2 + .../pip/_vendor/certifi/cacert.pem | 4300 +++++++++ .../site-packages/pip/_vendor/certifi/core.py | 37 + .../pip/_vendor/chardet/__init__.py | 39 + .../pip/_vendor/chardet/big5freq.py | 386 + .../pip/_vendor/chardet/big5prober.py | 47 + .../pip/_vendor/chardet/chardistribution.py | 233 + .../pip/_vendor/chardet/charsetgroupprober.py | 106 + .../pip/_vendor/chardet/charsetprober.py | 145 + .../pip/_vendor/chardet/cli/__init__.py | 1 + .../pip/_vendor/chardet/cli/chardetect.py | 85 + .../pip/_vendor/chardet/codingstatemachine.py | 88 + .../pip/_vendor/chardet/compat.py | 34 + .../pip/_vendor/chardet/cp949prober.py | 49 + .../pip/_vendor/chardet/enums.py | 76 + .../pip/_vendor/chardet/escprober.py | 101 + .../pip/_vendor/chardet/escsm.py | 246 + .../pip/_vendor/chardet/eucjpprober.py | 92 + .../pip/_vendor/chardet/euckrfreq.py | 195 + .../pip/_vendor/chardet/euckrprober.py | 47 + .../pip/_vendor/chardet/euctwfreq.py | 387 + .../pip/_vendor/chardet/euctwprober.py | 46 + .../pip/_vendor/chardet/gb2312freq.py | 283 + .../pip/_vendor/chardet/gb2312prober.py | 46 + .../pip/_vendor/chardet/hebrewprober.py | 292 + .../pip/_vendor/chardet/jisfreq.py | 325 + .../pip/_vendor/chardet/jpcntx.py | 233 + .../pip/_vendor/chardet/langbulgarianmodel.py | 228 + .../pip/_vendor/chardet/langcyrillicmodel.py | 333 + .../pip/_vendor/chardet/langgreekmodel.py | 225 + .../pip/_vendor/chardet/langhebrewmodel.py | 200 + .../pip/_vendor/chardet/langhungarianmodel.py | 225 + .../pip/_vendor/chardet/langthaimodel.py | 199 + .../pip/_vendor/chardet/langturkishmodel.py | 193 + .../pip/_vendor/chardet/latin1prober.py | 145 + .../pip/_vendor/chardet/mbcharsetprober.py | 91 + .../pip/_vendor/chardet/mbcsgroupprober.py | 54 + .../pip/_vendor/chardet/mbcssm.py | 572 ++ .../pip/_vendor/chardet/sbcharsetprober.py | 132 + .../pip/_vendor/chardet/sbcsgroupprober.py | 73 + .../pip/_vendor/chardet/sjisprober.py | 92 + .../pip/_vendor/chardet/universaldetector.py | 286 + .../pip/_vendor/chardet/utf8prober.py | 82 + .../pip/_vendor/chardet/version.py | 9 + .../pip/_vendor/colorama/__init__.py | 7 + .../pip/_vendor/colorama/ansi.py | 102 + .../pip/_vendor/colorama/ansitowin32.py | 236 + .../pip/_vendor/colorama/initialise.py | 82 + .../pip/_vendor/colorama/win32.py | 156 + .../pip/_vendor/colorama/winterm.py | 162 + .../pip/_vendor/distlib/__init__.py | 23 + .../pip/_vendor/distlib/_backport/__init__.py | 6 + .../pip/_vendor/distlib/_backport/misc.py | 41 + .../pip/_vendor/distlib/_backport/shutil.py | 761 ++ .../_vendor/distlib/_backport/sysconfig.cfg | 84 + .../_vendor/distlib/_backport/sysconfig.py | 788 ++ .../pip/_vendor/distlib/_backport/tarfile.py | 2607 ++++++ .../pip/_vendor/distlib/compat.py | 1120 +++ .../pip/_vendor/distlib/database.py | 1336 +++ .../pip/_vendor/distlib/index.py | 516 ++ .../pip/_vendor/distlib/locators.py | 1292 +++ .../pip/_vendor/distlib/manifest.py | 393 + .../pip/_vendor/distlib/markers.py | 131 + .../pip/_vendor/distlib/metadata.py | 1091 +++ .../pip/_vendor/distlib/resources.py | 355 + .../pip/_vendor/distlib/scripts.py | 415 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 92672 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 102400 bytes .../site-packages/pip/_vendor/distlib/util.py | 1755 ++++ .../pip/_vendor/distlib/version.py | 736 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 89088 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 99328 bytes .../pip/_vendor/distlib/wheel.py | 984 ++ .../site-packages/pip/_vendor/distro.py | 1197 +++ .../pip/_vendor/html5lib/__init__.py | 35 + .../pip/_vendor/html5lib/_ihatexml.py | 288 + .../pip/_vendor/html5lib/_inputstream.py | 923 ++ .../pip/_vendor/html5lib/_tokenizer.py | 1721 ++++ .../pip/_vendor/html5lib/_trie/__init__.py | 14 + .../pip/_vendor/html5lib/_trie/_base.py | 37 + .../pip/_vendor/html5lib/_trie/datrie.py | 44 + .../pip/_vendor/html5lib/_trie/py.py | 67 + .../pip/_vendor/html5lib/_utils.py | 124 + .../pip/_vendor/html5lib/constants.py | 2947 ++++++ .../pip/_vendor/html5lib/filters/__init__.py | 0 .../filters/alphabeticalattributes.py | 29 + .../pip/_vendor/html5lib/filters/base.py | 12 + .../html5lib/filters/inject_meta_charset.py | 73 + .../pip/_vendor/html5lib/filters/lint.py | 93 + .../_vendor/html5lib/filters/optionaltags.py | 207 + .../pip/_vendor/html5lib/filters/sanitizer.py | 896 ++ .../_vendor/html5lib/filters/whitespace.py | 38 + .../pip/_vendor/html5lib/html5parser.py | 2791 ++++++ .../pip/_vendor/html5lib/serializer.py | 409 + .../_vendor/html5lib/treeadapters/__init__.py | 30 + .../_vendor/html5lib/treeadapters/genshi.py | 54 + .../pip/_vendor/html5lib/treeadapters/sax.py | 50 + .../_vendor/html5lib/treebuilders/__init__.py | 88 + .../pip/_vendor/html5lib/treebuilders/base.py | 417 + .../pip/_vendor/html5lib/treebuilders/dom.py | 236 + .../_vendor/html5lib/treebuilders/etree.py | 340 + .../html5lib/treebuilders/etree_lxml.py | 366 + .../_vendor/html5lib/treewalkers/__init__.py | 154 + .../pip/_vendor/html5lib/treewalkers/base.py | 252 + .../pip/_vendor/html5lib/treewalkers/dom.py | 43 + .../pip/_vendor/html5lib/treewalkers/etree.py | 130 + .../html5lib/treewalkers/etree_lxml.py | 213 + .../_vendor/html5lib/treewalkers/genshi.py | 69 + .../pip/_vendor/idna/__init__.py | 2 + .../site-packages/pip/_vendor/idna/codec.py | 118 + .../site-packages/pip/_vendor/idna/compat.py | 12 + .../site-packages/pip/_vendor/idna/core.py | 399 + .../pip/_vendor/idna/idnadata.py | 1893 ++++ .../pip/_vendor/idna/intranges.py | 53 + .../pip/_vendor/idna/package_data.py | 2 + .../pip/_vendor/idna/uts46data.py | 8179 +++++++++++++++++ .../site-packages/pip/_vendor/ipaddress.py | 2419 +++++ .../pip/_vendor/lockfile/__init__.py | 347 + .../pip/_vendor/lockfile/linklockfile.py | 73 + .../pip/_vendor/lockfile/mkdirlockfile.py | 84 + .../pip/_vendor/lockfile/pidlockfile.py | 190 + .../pip/_vendor/lockfile/sqlitelockfile.py | 156 + .../pip/_vendor/lockfile/symlinklockfile.py | 70 + .../pip/_vendor/msgpack/__init__.py | 66 + .../pip/_vendor/msgpack/_version.py | 1 + .../pip/_vendor/msgpack/exceptions.py | 41 + .../pip/_vendor/msgpack/fallback.py | 977 ++ .../pip/_vendor/packaging/__about__.py | 21 + .../pip/_vendor/packaging/__init__.py | 14 + .../pip/_vendor/packaging/_compat.py | 30 + .../pip/_vendor/packaging/_structures.py | 70 + .../pip/_vendor/packaging/markers.py | 301 + .../pip/_vendor/packaging/requirements.py | 130 + .../pip/_vendor/packaging/specifiers.py | 774 ++ .../pip/_vendor/packaging/utils.py | 63 + .../pip/_vendor/packaging/version.py | 441 + .../pip/_vendor/pep517/__init__.py | 4 + .../pip/_vendor/pep517/_in_process.py | 182 + .../site-packages/pip/_vendor/pep517/check.py | 194 + .../pip/_vendor/pep517/colorlog.py | 110 + .../pip/_vendor/pep517/compat.py | 23 + .../pip/_vendor/pep517/envbuild.py | 150 + .../pip/_vendor/pep517/wrappers.py | 134 + .../pip/_vendor/pkg_resources/__init__.py | 3149 +++++++ .../pip/_vendor/pkg_resources/py31compat.py | 23 + .../pip/_vendor/progress/__init__.py | 127 + .../site-packages/pip/_vendor/progress/bar.py | 94 + .../pip/_vendor/progress/counter.py | 48 + .../pip/_vendor/progress/helpers.py | 91 + .../pip/_vendor/progress/spinner.py | 44 + .../site-packages/pip/_vendor/pyparsing.py | 5742 ++++++++++++ .../pip/_vendor/pytoml/__init__.py | 3 + .../site-packages/pip/_vendor/pytoml/core.py | 13 + .../pip/_vendor/pytoml/parser.py | 374 + .../pip/_vendor/pytoml/writer.py | 127 + .../pip/_vendor/requests/__init__.py | 138 + .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 42 + .../pip/_vendor/requests/adapters.py | 530 ++ .../site-packages/pip/_vendor/requests/api.py | 152 + .../pip/_vendor/requests/auth.py | 305 + .../pip/_vendor/requests/certs.py | 18 + .../pip/_vendor/requests/compat.py | 75 + .../pip/_vendor/requests/cookies.py | 546 ++ .../pip/_vendor/requests/exceptions.py | 126 + .../pip/_vendor/requests/help.py | 120 + .../pip/_vendor/requests/hooks.py | 34 + .../pip/_vendor/requests/models.py | 952 ++ .../pip/_vendor/requests/packages.py | 16 + .../pip/_vendor/requests/sessions.py | 741 ++ .../pip/_vendor/requests/status_codes.py | 120 + .../pip/_vendor/requests/structures.py | 103 + .../pip/_vendor/requests/utils.py | 976 ++ .../site-packages/pip/_vendor/retrying.py | 267 + .../site-packages/pip/_vendor/six.py | 891 ++ .../pip/_vendor/urllib3/__init__.py | 97 + .../pip/_vendor/urllib3/_collections.py | 332 + .../pip/_vendor/urllib3/connection.py | 403 + .../pip/_vendor/urllib3/connectionpool.py | 906 ++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 593 ++ .../contrib/_securetransport/low_level.py | 346 + .../pip/_vendor/urllib3/contrib/appengine.py | 305 + .../pip/_vendor/urllib3/contrib/ntlmpool.py | 112 + .../pip/_vendor/urllib3/contrib/pyopenssl.py | 457 + .../urllib3/contrib/securetransport.py | 804 ++ .../pip/_vendor/urllib3/contrib/socks.py | 192 + .../pip/_vendor/urllib3/exceptions.py | 246 + .../pip/_vendor/urllib3/fields.py | 178 + .../pip/_vendor/urllib3/filepost.py | 98 + .../pip/_vendor/urllib3/packages/__init__.py | 5 + .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 53 + .../_vendor/urllib3/packages/ordered_dict.py | 259 + .../pip/_vendor/urllib3/packages/six.py | 868 ++ .../packages/ssl_match_hostname/__init__.py | 19 + .../ssl_match_hostname/_implementation.py | 157 + .../pip/_vendor/urllib3/poolmanager.py | 449 + .../pip/_vendor/urllib3/request.py | 150 + .../pip/_vendor/urllib3/response.py | 676 ++ .../pip/_vendor/urllib3/util/__init__.py | 54 + .../pip/_vendor/urllib3/util/connection.py | 126 + .../pip/_vendor/urllib3/util/queue.py | 21 + .../pip/_vendor/urllib3/util/request.py | 118 + .../pip/_vendor/urllib3/util/response.py | 81 + .../pip/_vendor/urllib3/util/retry.py | 411 + .../pip/_vendor/urllib3/util/ssl_.py | 396 + .../pip/_vendor/urllib3/util/timeout.py | 242 + .../pip/_vendor/urllib3/util/url.py | 230 + .../pip/_vendor/urllib3/util/wait.py | 153 + .../pip/_vendor/webencodings/__init__.py | 342 + .../pip/_vendor/webencodings/labels.py | 231 + .../pip/_vendor/webencodings/mklabels.py | 59 + .../pip/_vendor/webencodings/tests.py | 153 + .../_vendor/webencodings/x_user_defined.py | 325 + .../site-packages/pkg_resources/__init__.py | 3171 +++++++ .../pkg_resources/_vendor/__init__.py | 0 .../pkg_resources/_vendor/appdirs.py | 608 ++ .../_vendor/packaging/__about__.py | 21 + .../_vendor/packaging/__init__.py | 14 + .../_vendor/packaging/_compat.py | 30 + .../_vendor/packaging/_structures.py | 68 + .../_vendor/packaging/markers.py | 301 + .../_vendor/packaging/requirements.py | 127 + .../_vendor/packaging/specifiers.py | 774 ++ .../pkg_resources/_vendor/packaging/utils.py | 14 + .../_vendor/packaging/version.py | 393 + .../pkg_resources/_vendor/pyparsing.py | 5742 ++++++++++++ .../pkg_resources/_vendor/six.py | 868 ++ .../pkg_resources/extern/__init__.py | 73 + .../site-packages/pkg_resources/py31compat.py | 23 + .../protobuf-3.6.1-py3.7-nspkg.pth | 1 + .../protobuf-3.6.1.dist-info/INSTALLER | 1 + .../protobuf-3.6.1.dist-info/METADATA | 22 + .../protobuf-3.6.1.dist-info/RECORD | 199 + .../protobuf-3.6.1.dist-info/WHEEL | 9 + .../namespace_packages.txt | 1 + .../protobuf-3.6.1.dist-info/top_level.txt | 1 + .../setuptools-40.6.2.dist-info/INSTALLER | 1 + .../setuptools-40.6.2.dist-info/LICENSE | 19 + .../setuptools-40.6.2.dist-info/METADATA | 73 + .../setuptools-40.6.2.dist-info/RECORD | 188 + .../setuptools-40.6.2.dist-info/WHEEL | 6 + .../dependency_links.txt | 2 + .../entry_points.txt | 65 + .../setuptools-40.6.2.dist-info/top_level.txt | 3 + .../setuptools-40.6.2.dist-info/zip-safe | 1 + .../site-packages/setuptools/__init__.py | 195 + .../setuptools/_deprecation_warning.py | 7 + .../setuptools/_vendor/__init__.py | 0 .../setuptools/_vendor/packaging/__about__.py | 21 + .../setuptools/_vendor/packaging/__init__.py | 14 + .../setuptools/_vendor/packaging/_compat.py | 30 + .../_vendor/packaging/_structures.py | 68 + .../setuptools/_vendor/packaging/markers.py | 301 + .../_vendor/packaging/requirements.py | 127 + .../_vendor/packaging/specifiers.py | 774 ++ .../setuptools/_vendor/packaging/utils.py | 14 + .../setuptools/_vendor/packaging/version.py | 393 + .../setuptools/_vendor/pyparsing.py | 5742 ++++++++++++ .../site-packages/setuptools/_vendor/six.py | 868 ++ .../site-packages/setuptools/archive_util.py | 173 + .../site-packages/setuptools/build_meta.py | 182 + .../site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes .../site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 18 + .../site-packages/setuptools/command/alias.py | 80 + .../setuptools/command/bdist_egg.py | 502 + .../setuptools/command/bdist_rpm.py | 43 + .../setuptools/command/bdist_wininst.py | 21 + .../setuptools/command/build_clib.py | 98 + .../setuptools/command/build_ext.py | 321 + .../setuptools/command/build_py.py | 270 + .../setuptools/command/develop.py | 218 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2342 +++++ .../setuptools/command/egg_info.py | 716 ++ .../setuptools/command/install.py | 125 + .../setuptools/command/install_egg_info.py | 62 + .../setuptools/command/install_lib.py | 121 + .../setuptools/command/install_scripts.py | 65 + .../setuptools/command/launcher manifest.xml | 15 + .../setuptools/command/py36compat.py | 136 + .../setuptools/command/register.py | 18 + .../setuptools/command/rotate.py | 66 + .../setuptools/command/saveopts.py | 22 + .../site-packages/setuptools/command/sdist.py | 200 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 270 + .../setuptools/command/upload.py | 196 + .../setuptools/command/upload_docs.py | 206 + .../site-packages/setuptools/config.py | 635 ++ .../site-packages/setuptools/dep_util.py | 23 + .../site-packages/setuptools/depends.py | 186 + .../site-packages/setuptools/dist.py | 1147 +++ .../site-packages/setuptools/extension.py | 57 + .../setuptools/extern/__init__.py | 73 + .../site-packages/setuptools/glibc.py | 86 + .../site-packages/setuptools/glob.py | 174 + .../site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes .../site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/launch.py | 35 + .../site-packages/setuptools/lib2to3_ex.py | 62 + .../site-packages/setuptools/monkey.py | 179 + .../site-packages/setuptools/msvc.py | 1301 +++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1128 +++ .../site-packages/setuptools/pep425tags.py | 319 + .../site-packages/setuptools/py27compat.py | 28 + .../site-packages/setuptools/py31compat.py | 32 + .../site-packages/setuptools/py33compat.py | 55 + .../site-packages/setuptools/py36compat.py | 82 + .../site-packages/setuptools/sandbox.py | 491 + .../setuptools/script (dev).tmpl | 6 + .../site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/site-patch.py | 74 + .../site-packages/setuptools/ssl_support.py | 260 + .../site-packages/setuptools/unicode_utils.py | 44 + .../site-packages/setuptools/version.py | 6 + .../site-packages/setuptools/wheel.py | 210 + .../setuptools/windows_support.py | 29 + .../six-1.11.0.dist-info/DESCRIPTION.rst | 27 + .../six-1.11.0.dist-info/INSTALLER | 1 + .../six-1.11.0.dist-info/METADATA | 43 + .../site-packages/six-1.11.0.dist-info/RECORD | 9 + .../site-packages/six-1.11.0.dist-info/WHEEL | 6 + .../six-1.11.0.dist-info/metadata.json | 1 + .../six-1.11.0.dist-info/top_level.txt | 1 + venv/lib/python3.7/site-packages/six.py | 891 ++ .../wheel-0.32.3.dist-info/INSTALLER | 1 + .../wheel-0.32.3.dist-info/LICENSE.txt | 22 + .../wheel-0.32.3.dist-info/METADATA | 60 + .../wheel-0.32.3.dist-info/RECORD | 34 + .../wheel-0.32.3.dist-info/WHEEL | 6 + .../wheel-0.32.3.dist-info/entry_points.txt | 6 + .../wheel-0.32.3.dist-info/top_level.txt | 1 + .../python3.7/site-packages/wheel/__init__.py | 2 + .../python3.7/site-packages/wheel/__main__.py | 19 + .../site-packages/wheel/bdist_wheel.py | 368 + .../site-packages/wheel/cli/__init__.py | 87 + .../site-packages/wheel/cli/convert.py | 269 + .../site-packages/wheel/cli/install.py | 0 .../python3.7/site-packages/wheel/cli/pack.py | 54 + .../site-packages/wheel/cli/unpack.py | 25 + .../python3.7/site-packages/wheel/metadata.py | 141 + .../site-packages/wheel/pep425tags.py | 185 + .../python3.7/site-packages/wheel/pkginfo.py | 43 + .../lib/python3.7/site-packages/wheel/util.py | 41 + .../site-packages/wheel/wheelfile.py | 160 + venv/lib/python3.7/site.py | 758 ++ venv/lib/python3.7/sre_compile.py | 1 + venv/lib/python3.7/sre_constants.py | 1 + venv/lib/python3.7/sre_parse.py | 1 + venv/lib/python3.7/stat.py | 1 + venv/lib/python3.7/struct.py | 1 + venv/lib/python3.7/tarfile.py | 1 + venv/lib/python3.7/tempfile.py | 1 + venv/lib/python3.7/token.py | 1 + venv/lib/python3.7/tokenize.py | 1 + venv/lib/python3.7/types.py | 1 + venv/lib/python3.7/warnings.py | 1 + venv/lib/python3.7/weakref.py | 1 + venv/pip-selfcheck.json | 1 + 619 files changed, 197971 insertions(+), 4 deletions(-) mode change 100644 => 100755 D3Edit.py create mode 120000 venv/.Python create mode 100644 venv/bin/activate create mode 100644 venv/bin/activate.csh create mode 100644 venv/bin/activate.fish create mode 100644 venv/bin/activate_this.py create mode 100755 venv/bin/easy_install create mode 100755 venv/bin/easy_install-3.7 create mode 100755 venv/bin/pip create mode 100755 venv/bin/pip3 create mode 100755 venv/bin/pip3.7 create mode 120000 venv/bin/python create mode 100755 venv/bin/python-config create mode 120000 venv/bin/python3 create mode 100755 venv/bin/python3.7 create mode 100755 venv/bin/wheel create mode 120000 venv/include/python3.7m create mode 120000 venv/lib/python3.7/__future__.py create mode 120000 venv/lib/python3.7/_bootlocale.py create mode 120000 venv/lib/python3.7/_collections_abc.py create mode 120000 venv/lib/python3.7/_dummy_thread.py create mode 120000 venv/lib/python3.7/_weakrefset.py create mode 120000 venv/lib/python3.7/abc.py create mode 120000 venv/lib/python3.7/base64.py create mode 120000 venv/lib/python3.7/bisect.py create mode 120000 venv/lib/python3.7/codecs.py create mode 120000 venv/lib/python3.7/collections create mode 120000 venv/lib/python3.7/config-3.7m-darwin create mode 120000 venv/lib/python3.7/copy.py create mode 120000 venv/lib/python3.7/copyreg.py create mode 100644 venv/lib/python3.7/distutils/__init__.py create mode 100644 venv/lib/python3.7/distutils/distutils.cfg create mode 120000 venv/lib/python3.7/encodings create mode 120000 venv/lib/python3.7/enum.py create mode 120000 venv/lib/python3.7/fnmatch.py create mode 120000 venv/lib/python3.7/functools.py create mode 120000 venv/lib/python3.7/genericpath.py create mode 120000 venv/lib/python3.7/hashlib.py create mode 120000 venv/lib/python3.7/heapq.py create mode 120000 venv/lib/python3.7/hmac.py create mode 120000 venv/lib/python3.7/imp.py create mode 120000 venv/lib/python3.7/importlib create mode 120000 venv/lib/python3.7/io.py create mode 120000 venv/lib/python3.7/keyword.py create mode 120000 venv/lib/python3.7/lib-dynload create mode 120000 venv/lib/python3.7/linecache.py create mode 120000 venv/lib/python3.7/locale.py create mode 100644 venv/lib/python3.7/no-global-site-packages.txt create mode 120000 venv/lib/python3.7/ntpath.py create mode 120000 venv/lib/python3.7/operator.py create mode 100644 venv/lib/python3.7/orig-prefix.txt create mode 120000 venv/lib/python3.7/os.py create mode 120000 venv/lib/python3.7/posixpath.py create mode 120000 venv/lib/python3.7/random.py create mode 120000 venv/lib/python3.7/re.py create mode 120000 venv/lib/python3.7/readline.so create mode 120000 venv/lib/python3.7/reprlib.py create mode 120000 venv/lib/python3.7/rlcompleter.py create mode 120000 venv/lib/python3.7/shutil.py create mode 100644 venv/lib/python3.7/site-packages/easy_install.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/__init__.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/any_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/any_test_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/api_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/compiler/__init__.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/compiler/plugin_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/descriptor.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/descriptor_database.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/descriptor_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/descriptor_pool.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/duration_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/empty_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/field_mask_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/__init__.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/_api_implementation.cpython-37m-darwin.so create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/_parameterized.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/any_test_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/api_implementation.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/containers.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/decoder.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_database_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/encoder.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/enum_type_wrapper.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/factory_test1_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/factory_test2_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/file_options_test_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/generator_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/__init__.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/json_format_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/message_factory_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/message_listener.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/message_set_extensions_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/message_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/missing_enum_values_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/more_messages_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/no_package_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/packed_field_test_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/proto_builder_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/python_message.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/reflection_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/service_reflection_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/symbol_database_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/test_bad_identifiers_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/test_util.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/testing_refleaks.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/text_encoding_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/text_format_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/type_checkers.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/unknown_fields_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format_test.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/json_format.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/map_proto2_unittest_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/map_unittest_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/message.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/message_factory.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/proto_builder.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/pyext/__init__.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/pyext/_message.cpython-37m-darwin.so create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/pyext/cpp_message.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/pyext/python_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/reflection.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/service.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/service_reflection.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/source_context_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/struct_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/symbol_database.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto2_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto3_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/text_encoding.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/text_format.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/timestamp_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/type_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_arena_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_custom_options_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_import_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_import_public_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_import_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_no_generic_services_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/unittest_proto3_arena_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/util/__init__.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/util/json_format_proto3_pb2.py create mode 100644 venv/lib/python3.7/site-packages/google/protobuf/wrappers_pb2.py create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/INSTALLER create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/METADATA create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/RECORD create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/WHEEL create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/entry_points.txt create mode 100644 venv/lib/python3.7/site-packages/pip-18.1.dist-info/top_level.txt create mode 100644 venv/lib/python3.7/site-packages/pip/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/__main__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/build_env.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cache.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/base_command.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/main_parser.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/parser.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/cli/status_codes.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/check.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/completion.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/configuration.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/download.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/freeze.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/hash.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/help.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/install.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/list.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/search.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/show.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/uninstall.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/commands/wheel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/configuration.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/download.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/exceptions.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/index.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/locations.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/models/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/models/candidate.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/models/format_control.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/models/index.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/models/link.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/operations/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/operations/check.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/operations/prepare.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/pep425tags.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/pyproject.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/constructors.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/req_file.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/req_install.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/req_set.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/req_tracker.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/resolve.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/appdirs.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/deprecation.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/encoding.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/filesystem.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/glibc.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/hashes.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/misc.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/models.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/outdated.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/packaging.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/utils/ui.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/vcs/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/vcs/git.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/vcs/subversion.py create mode 100644 venv/lib/python3.7/site-packages/pip/_internal/wheel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/appdirs.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/certifi/core.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5freq.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5prober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/chardistribution.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/chardetect.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/codingstatemachine.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/cp949prober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/enums.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/escprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/escsm.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/eucjpprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrfreq.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwfreq.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312freq.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312prober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/hebrewprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/jisfreq.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/jpcntx.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langgreekmodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langthaimodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/langturkishmodel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/latin1prober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcssm.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/sjisprober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/universaldetector.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/utf8prober.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/chardet/version.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/colorama/win32.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/misc.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/shutil.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/database.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/index.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/locators.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/markers.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/resources.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/util.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/version.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/distro.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_ihatexml.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_inputstream.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_tokenizer.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/_base.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/py.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_utils.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/constants.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/base.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/lint.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/serializer.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/codec.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/core.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/intranges.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/package_data.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/ipaddress.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/lockfile/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/lockfile/linklockfile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/lockfile/pidlockfile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/msgpack/_version.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/__about__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/_compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/markers.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/utils.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/packaging/version.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/_in_process.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/check.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/colorlog.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/envbuild.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pep517/wrappers.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/py31compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/progress/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/progress/bar.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/progress/counter.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/progress/helpers.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/progress/spinner.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pyparsing.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pytoml/core.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pytoml/parser.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/pytoml/writer.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/__version__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/adapters.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/api.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/auth.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/certs.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/compat.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/cookies.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/help.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/hooks.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/models.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/packages.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/sessions.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/structures.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/requests/utils.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/retrying.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/six.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/request.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/response.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/webencodings/labels.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/webencodings/mklabels.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/webencodings/tests.py create mode 100644 venv/lib/python3.7/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_compat.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/_vendor/six.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/extern/__init__.py create mode 100644 venv/lib/python3.7/site-packages/pkg_resources/py31compat.py create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1-py3.7-nspkg.pth create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/INSTALLER create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/METADATA create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/RECORD create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/WHEEL create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt create mode 100644 venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/top_level.txt create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/INSTALLER create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/LICENSE create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/METADATA create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/RECORD create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/WHEEL create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/entry_points.txt create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/top_level.txt create mode 100644 venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/zip-safe create mode 100644 venv/lib/python3.7/site-packages/setuptools/__init__.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_deprecation_warning.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/__init__.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_compat.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/_vendor/six.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/archive_util.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/build_meta.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/cli-32.exe create mode 100644 venv/lib/python3.7/site-packages/setuptools/cli-64.exe create mode 100644 venv/lib/python3.7/site-packages/setuptools/cli.exe create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/__init__.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/alias.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/bdist_egg.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/bdist_rpm.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/bdist_wininst.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/build_clib.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/build_ext.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/build_py.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/develop.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/dist_info.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/easy_install.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/egg_info.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/install.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/install_egg_info.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/install_lib.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/install_scripts.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/launcher manifest.xml create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/py36compat.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/register.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/rotate.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/saveopts.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/sdist.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/setopt.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/test.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/upload.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/command/upload_docs.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/config.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/dep_util.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/depends.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/dist.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/extension.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/extern/__init__.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/glibc.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/glob.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/gui-32.exe create mode 100644 venv/lib/python3.7/site-packages/setuptools/gui-64.exe create mode 100644 venv/lib/python3.7/site-packages/setuptools/gui.exe create mode 100644 venv/lib/python3.7/site-packages/setuptools/launch.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/lib2to3_ex.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/monkey.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/msvc.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/namespaces.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/package_index.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/pep425tags.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/py27compat.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/py31compat.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/py33compat.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/py36compat.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/sandbox.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/script (dev).tmpl create mode 100644 venv/lib/python3.7/site-packages/setuptools/script.tmpl create mode 100644 venv/lib/python3.7/site-packages/setuptools/site-patch.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/ssl_support.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/unicode_utils.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/version.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/wheel.py create mode 100644 venv/lib/python3.7/site-packages/setuptools/windows_support.py create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/INSTALLER create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/METADATA create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/RECORD create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/WHEEL create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/metadata.json create mode 100644 venv/lib/python3.7/site-packages/six-1.11.0.dist-info/top_level.txt create mode 100644 venv/lib/python3.7/site-packages/six.py create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/INSTALLER create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/LICENSE.txt create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/METADATA create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/RECORD create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/WHEEL create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/entry_points.txt create mode 100644 venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/top_level.txt create mode 100644 venv/lib/python3.7/site-packages/wheel/__init__.py create mode 100644 venv/lib/python3.7/site-packages/wheel/__main__.py create mode 100644 venv/lib/python3.7/site-packages/wheel/bdist_wheel.py create mode 100644 venv/lib/python3.7/site-packages/wheel/cli/__init__.py create mode 100644 venv/lib/python3.7/site-packages/wheel/cli/convert.py create mode 100644 venv/lib/python3.7/site-packages/wheel/cli/install.py create mode 100644 venv/lib/python3.7/site-packages/wheel/cli/pack.py create mode 100644 venv/lib/python3.7/site-packages/wheel/cli/unpack.py create mode 100644 venv/lib/python3.7/site-packages/wheel/metadata.py create mode 100644 venv/lib/python3.7/site-packages/wheel/pep425tags.py create mode 100644 venv/lib/python3.7/site-packages/wheel/pkginfo.py create mode 100644 venv/lib/python3.7/site-packages/wheel/util.py create mode 100644 venv/lib/python3.7/site-packages/wheel/wheelfile.py create mode 100644 venv/lib/python3.7/site.py create mode 120000 venv/lib/python3.7/sre_compile.py create mode 120000 venv/lib/python3.7/sre_constants.py create mode 120000 venv/lib/python3.7/sre_parse.py create mode 120000 venv/lib/python3.7/stat.py create mode 120000 venv/lib/python3.7/struct.py create mode 120000 venv/lib/python3.7/tarfile.py create mode 120000 venv/lib/python3.7/tempfile.py create mode 120000 venv/lib/python3.7/token.py create mode 120000 venv/lib/python3.7/tokenize.py create mode 120000 venv/lib/python3.7/types.py create mode 120000 venv/lib/python3.7/warnings.py create mode 120000 venv/lib/python3.7/weakref.py create mode 100644 venv/pip-selfcheck.json diff --git a/D3Edit.py b/D3Edit.py old mode 100644 new mode 100755 index 63f03e1..15cc841 --- a/D3Edit.py +++ b/D3Edit.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 -import save_manager import gui +import platform +import save_manager +from os import getcwd from argparse import ArgumentParser from settings import currency_list -if __name__ == "__main__": +def main(): # parse arguments parser = ArgumentParser(description="A script to encrypt/decrypt and modify Diablo III saves") parser.add_argument("-i", "--in-file", type=str, help="The save file you want to work with") @@ -46,7 +48,15 @@ pass if amount: account.set_currency(id, amount) - - # This should be the only write we do, a final commit_all_changes(). account.commit_account_changes() + + +if __name__ == "__main__": + venv_platforms = ['Linux', 'Darwin'] + # activate Linux/Darwin venvs: + if any(p in platform.system() for p in venv_platforms): + print("activated linux venv") + activate_this_file = "{}/venv/bin/activate_this.py".format(getcwd()) + exec(open(activate_this_file).read(), dict(__file__=activate_this_file)) + main() diff --git a/venv/.Python b/venv/.Python new file mode 120000 index 0000000..2643ec8 --- /dev/null +++ b/venv/.Python @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/Python \ No newline at end of file diff --git a/venv/bin/activate b/venv/bin/activate new file mode 100644 index 0000000..2db0fb2 --- /dev/null +++ b/venv/bin/activate @@ -0,0 +1,78 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_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-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/Users/unixtreme/PycharmProjects/D3Edit/venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="$PS1" + if [ "x" != x ] ; then + PS1="$PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc + +pydoc () { + python -m pydoc "$@" +} + +# 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-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh new file mode 100644 index 0000000..683bcec --- /dev/null +++ b/venv/bin/activate.csh @@ -0,0 +1,36 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . + +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; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/unixtreme/PycharmProjects/D3Edit/venv" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + + +if ("" != "") then + set env_name = "" +else + set env_name = `basename "$VIRTUAL_ENV"` +endif + +# Could be in a non-interactive environment, +# in which case, $prompt is undefined and we wouldn't +# care about the prompt anyway. +if ( $?prompt ) then + set _OLD_VIRTUAL_PROMPT="$prompt" + set prompt = "[$env_name] $prompt" +endif + +unset env_name + +alias pydoc python -m pydoc + +rehash + diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish new file mode 100644 index 0000000..5787901 --- /dev/null +++ b/venv/bin/activate.fish @@ -0,0 +1,76 @@ +# This file must be used using `. bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. +# Do not run it directly. + +function deactivate -d 'Exit virtualenv mode and return to the normal 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" + # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. + set -l fish_function_path + + # Erase virtualenv's `fish_prompt` and restore the original. + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + end + + set -e VIRTUAL_ENV + + if test "$argv[1]" != 'nondestructive' + # Self-destruct! + functions -e pydoc + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/unixtreme/PycharmProjects/D3Edit/venv" + +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 + +function pydoc + python -m pydoc $argv +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # Copy the current `fish_prompt` function as `_old_fish_prompt`. + functions -c fish_prompt _old_fish_prompt + + function fish_prompt + # Save the current $status, for fish_prompts that display it. + set -l old_status $status + + # Prompt override provided? + # If not, just prepend the environment name. + if test -n "" + printf '%s%s' "" (set_color normal) + else + printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") + end + + # Restore the original $status + echo "exit $old_status" | source + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/venv/bin/activate_this.py b/venv/bin/activate_this.py new file mode 100644 index 0000000..f18193b --- /dev/null +++ b/venv/bin/activate_this.py @@ -0,0 +1,34 @@ +"""By using execfile(this_file, dict(__file__=this_file)) you will +activate this virtualenv environment. + +This can be used when you must use an existing Python interpreter, not +the virtualenv bin/python +""" + +try: + __file__ +except NameError: + raise AssertionError( + "You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))") +import sys +import os + +old_os_path = os.environ.get('PATH', '') +os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path +base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if sys.platform == 'win32': + site_packages = os.path.join(base, 'Lib', 'site-packages') +else: + site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages') +prev_sys_path = list(sys.path) +import site +site.addsitedir(site_packages) +sys.real_prefix = sys.prefix +sys.prefix = base +# Move the added items to the front of the path: +new_sys_path = [] +for item in list(sys.path): + if item not in prev_sys_path: + new_sys_path.append(item) + sys.path.remove(item) +sys.path[:0] = new_sys_path diff --git a/venv/bin/easy_install b/venv/bin/easy_install new file mode 100755 index 0000000..e13b5ee --- /dev/null +++ b/venv/bin/easy_install @@ -0,0 +1,11 @@ +#!/Users/unixtreme/PycharmProjects/D3Edit/venv/bin/python3.7 + +# -*- coding: utf-8 -*- +import re +import sys + +from setuptools.command.easy_install import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/easy_install-3.7 b/venv/bin/easy_install-3.7 new file mode 100755 index 0000000..e13b5ee --- /dev/null +++ b/venv/bin/easy_install-3.7 @@ -0,0 +1,11 @@ +#!/Users/unixtreme/PycharmProjects/D3Edit/venv/bin/python3.7 + +# -*- coding: utf-8 -*- +import re +import sys + +from setuptools.command.easy_install import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip b/venv/bin/pip new file mode 100755 index 0000000..efbf426 --- /dev/null +++ b/venv/bin/pip @@ -0,0 +1,11 @@ +#!/Users/unixtreme/PycharmProjects/D3Edit/venv/bin/python3.7 + +# -*- coding: utf-8 -*- +import re +import sys + +from pip._internal import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3 b/venv/bin/pip3 new file mode 100755 index 0000000..efbf426 --- /dev/null +++ b/venv/bin/pip3 @@ -0,0 +1,11 @@ +#!/Users/unixtreme/PycharmProjects/D3Edit/venv/bin/python3.7 + +# -*- coding: utf-8 -*- +import re +import sys + +from pip._internal import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/pip3.7 b/venv/bin/pip3.7 new file mode 100755 index 0000000..efbf426 --- /dev/null +++ b/venv/bin/pip3.7 @@ -0,0 +1,11 @@ +#!/Users/unixtreme/PycharmProjects/D3Edit/venv/bin/python3.7 + +# -*- coding: utf-8 -*- +import re +import sys + +from pip._internal import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/venv/bin/python b/venv/bin/python new file mode 120000 index 0000000..940bee3 --- /dev/null +++ b/venv/bin/python @@ -0,0 +1 @@ +python3.7 \ No newline at end of file diff --git a/venv/bin/python-config b/venv/bin/python-config new file mode 100755 index 0000000..34daac3 --- /dev/null +++ b/venv/bin/python-config @@ -0,0 +1,78 @@ +#!/Users/unixtreme/PycharmProjects/D3Edit/venv/bin/python + +import sys +import getopt +import sysconfig + +valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', + 'ldflags', 'help'] + +if sys.version_info >= (3, 2): + valid_opts.insert(-1, 'extension-suffix') + valid_opts.append('abiflags') +if sys.version_info >= (3, 3): + valid_opts.append('configdir') + + +def exit_with_usage(code=1): + sys.stderr.write("Usage: {0} [{1}]\n".format( + sys.argv[0], '|'.join('--'+opt for opt in valid_opts))) + sys.exit(code) + +try: + opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) +except getopt.error: + exit_with_usage() + +if not opts: + exit_with_usage() + +pyver = sysconfig.get_config_var('VERSION') +getvar = sysconfig.get_config_var + +opt_flags = [flag for (flag, val) in opts] + +if '--help' in opt_flags: + exit_with_usage(code=0) + +for opt in opt_flags: + if opt == '--prefix': + print(sysconfig.get_config_var('prefix')) + + elif opt == '--exec-prefix': + print(sysconfig.get_config_var('exec_prefix')) + + elif opt in ('--includes', '--cflags'): + flags = ['-I' + sysconfig.get_path('include'), + '-I' + sysconfig.get_path('platinclude')] + if opt == '--cflags': + flags.extend(getvar('CFLAGS').split()) + print(' '.join(flags)) + + elif opt in ('--libs', '--ldflags'): + abiflags = getattr(sys, 'abiflags', '') + libs = ['-lpython' + pyver + abiflags] + libs += getvar('LIBS').split() + libs += getvar('SYSLIBS').split() + # add the prefix/lib/pythonX.Y/config dir, but only if there is no + # shared library in prefix/lib/. + if opt == '--ldflags': + if not getvar('Py_ENABLE_SHARED'): + libs.insert(0, '-L' + getvar('LIBPL')) + if not getvar('PYTHONFRAMEWORK'): + libs.extend(getvar('LINKFORSHARED').split()) + print(' '.join(libs)) + + elif opt == '--extension-suffix': + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + if ext_suffix is None: + ext_suffix = sysconfig.get_config_var('SO') + print(ext_suffix) + + elif opt == '--abiflags': + if not getattr(sys, 'abiflags', None): + exit_with_usage() + print(sys.abiflags) + + elif opt == '--configdir': + print(sysconfig.get_config_var('LIBPL')) diff --git a/venv/bin/python3 b/venv/bin/python3 new file mode 120000 index 0000000..940bee3 --- /dev/null +++ b/venv/bin/python3 @@ -0,0 +1 @@ +python3.7 \ No newline at end of file diff --git a/venv/bin/python3.7 b/venv/bin/python3.7 new file mode 100755 index 0000000000000000000000000000000000000000..d94baea1034b17c18c49b29b45618e9f432864a3 GIT binary patch literal 12552 zcmeI2&rcIU6vwBE(kNn)gTG@##Hfc|L=a*$wnz~oDhL=uVkTR=q#L)}W_KItjf;sU zm~g_xa5V8^j0X>1jQ$7y6Kdq(AD{>8_wCM>ZTWFGc`toC``)~HGy9p{OXq$4^XqTB z5Q)7)EbkFQbV2*}3Gq~l`rZK^U0!VS4=~7A>bBEoY&Opw@gJRX*Ay60)1} zh3>|c_TeW~%F*m>w&51Uo4ART^1%*7*|ZOMM;f`MbZqI>O8K%aE55s9z9=2#r}2>x zuV6mqkkU4G%a=-r@ktd=c06CSKGhw2Zzm`2-p-9qMDJXm$`efvn;br5!lqN(HBnhs*9Wg$8W\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0finsertion_point\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x0f \x01(\tBg\n\x1c\x63om.google.protobuf.compilerB\x0cPluginProtosZ9github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + + + + +_VERSION = _descriptor.Descriptor( + name='Version', + full_name='google.protobuf.compiler.Version', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='major', full_name='google.protobuf.compiler.Version.major', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='minor', full_name='google.protobuf.compiler.Version.minor', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='patch', full_name='google.protobuf.compiler.Version.patch', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='suffix', full_name='google.protobuf.compiler.Version.suffix', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=101, + serialized_end=171, +) + + +_CODEGENERATORREQUEST = _descriptor.Descriptor( + name='CodeGeneratorRequest', + full_name='google.protobuf.compiler.CodeGeneratorRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file_to_generate', full_name='google.protobuf.compiler.CodeGeneratorRequest.file_to_generate', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='parameter', full_name='google.protobuf.compiler.CodeGeneratorRequest.parameter', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proto_file', full_name='google.protobuf.compiler.CodeGeneratorRequest.proto_file', index=2, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='compiler_version', full_name='google.protobuf.compiler.CodeGeneratorRequest.compiler_version', index=3, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=174, + serialized_end=360, +) + + +_CODEGENERATORRESPONSE_FILE = _descriptor.Descriptor( + name='File', + full_name='google.protobuf.compiler.CodeGeneratorResponse.File', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='insertion_point', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='content', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.content', index=2, + number=15, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=471, + serialized_end=533, +) + +_CODEGENERATORRESPONSE = _descriptor.Descriptor( + name='CodeGeneratorResponse', + full_name='google.protobuf.compiler.CodeGeneratorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='error', full_name='google.protobuf.compiler.CodeGeneratorResponse.error', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.compiler.CodeGeneratorResponse.file', index=1, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_CODEGENERATORRESPONSE_FILE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=363, + serialized_end=533, +) + +_CODEGENERATORREQUEST.fields_by_name['proto_file'].message_type = google_dot_protobuf_dot_descriptor__pb2._FILEDESCRIPTORPROTO +_CODEGENERATORREQUEST.fields_by_name['compiler_version'].message_type = _VERSION +_CODEGENERATORRESPONSE_FILE.containing_type = _CODEGENERATORRESPONSE +_CODEGENERATORRESPONSE.fields_by_name['file'].message_type = _CODEGENERATORRESPONSE_FILE +DESCRIPTOR.message_types_by_name['Version'] = _VERSION +DESCRIPTOR.message_types_by_name['CodeGeneratorRequest'] = _CODEGENERATORREQUEST +DESCRIPTOR.message_types_by_name['CodeGeneratorResponse'] = _CODEGENERATORRESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Version = _reflection.GeneratedProtocolMessageType('Version', (_message.Message,), dict( + DESCRIPTOR = _VERSION, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version) + )) +_sym_db.RegisterMessage(Version) + +CodeGeneratorRequest = _reflection.GeneratedProtocolMessageType('CodeGeneratorRequest', (_message.Message,), dict( + DESCRIPTOR = _CODEGENERATORREQUEST, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) + )) +_sym_db.RegisterMessage(CodeGeneratorRequest) + +CodeGeneratorResponse = _reflection.GeneratedProtocolMessageType('CodeGeneratorResponse', (_message.Message,), dict( + + File = _reflection.GeneratedProtocolMessageType('File', (_message.Message,), dict( + DESCRIPTOR = _CODEGENERATORRESPONSE_FILE, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) + )) + , + DESCRIPTOR = _CODEGENERATORRESPONSE, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) + )) +_sym_db.RegisterMessage(CodeGeneratorResponse) +_sym_db.RegisterMessage(CodeGeneratorResponse.File) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/descriptor.py b/venv/lib/python3.7/site-packages/google/protobuf/descriptor.py new file mode 100644 index 0000000..8a9ba3d --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/descriptor.py @@ -0,0 +1,1076 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Descriptors essentially contain exactly the information found in a .proto +file, in types that make this information accessible in Python. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import threading +import six + +from google.protobuf.internal import api_implementation + +_USE_C_DESCRIPTORS = False +if api_implementation.Type() == 'cpp': + # Used by MakeDescriptor in cpp mode + import binascii + import os + from google.protobuf.pyext import _message + _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False) + + +class Error(Exception): + """Base error for this module.""" + + +class TypeTransformationError(Error): + """Error transforming between python proto type and corresponding C++ type.""" + + +if _USE_C_DESCRIPTORS: + # This metaclass allows to override the behavior of code like + # isinstance(my_descriptor, FieldDescriptor) + # and make it return True when the descriptor is an instance of the extension + # type written in C++. + class DescriptorMetaclass(type): + def __instancecheck__(cls, obj): + if super(DescriptorMetaclass, cls).__instancecheck__(obj): + return True + if isinstance(obj, cls._C_DESCRIPTOR_CLASS): + return True + return False +else: + # The standard metaclass; nothing changes. + DescriptorMetaclass = type + + +class _Lock(object): + """Wrapper class of threading.Lock(), which is allowed by 'with'.""" + + def __new__(cls): + self = object.__new__(cls) + self._lock = threading.Lock() # pylint: disable=protected-access + return self + + def __enter__(self): + self._lock.acquire() + + def __exit__(self, exc_type, exc_value, exc_tb): + self._lock.release() + + +_lock = threading.Lock() + + +class DescriptorBase(six.with_metaclass(DescriptorMetaclass)): + + """Descriptors base class. + + This class is the base of all descriptor classes. It provides common options + related functionality. + + Attributes: + has_options: True if the descriptor has non-default options. Usually it + is not necessary to read this -- just call GetOptions() which will + happily return the default instance. However, it's sometimes useful + for efficiency, and also useful inside the protobuf implementation to + avoid some bootstrapping issues. + """ + + if _USE_C_DESCRIPTORS: + # The class, or tuple of classes, that are considered as "virtual + # subclasses" of this descriptor class. + _C_DESCRIPTOR_CLASS = () + + def __init__(self, options, serialized_options, options_class_name): + """Initialize the descriptor given its options message and the name of the + class of the options message. The name of the class is required in case + the options message is None and has to be created. + """ + self._options = options + self._options_class_name = options_class_name + self._serialized_options = serialized_options + + # Does this descriptor have non-default options? + self.has_options = (options is not None) or (serialized_options is not None) + + def _SetOptions(self, options, options_class_name): + """Sets the descriptor's options + + This function is used in generated proto2 files to update descriptor + options. It must not be used outside proto2. + """ + self._options = options + self._options_class_name = options_class_name + + # Does this descriptor have non-default options? + self.has_options = options is not None + + def GetOptions(self): + """Retrieves descriptor options. + + This method returns the options set or creates the default options for the + descriptor. + """ + if self._options: + return self._options + + from google.protobuf import descriptor_pb2 + try: + options_class = getattr(descriptor_pb2, + self._options_class_name) + except AttributeError: + raise RuntimeError('Unknown options class name %s!' % + (self._options_class_name)) + + with _lock: + if self._serialized_options is None: + self._options = options_class() + else: + self._options = _ParseOptions(options_class(), + self._serialized_options) + + return self._options + + +class _NestedDescriptorBase(DescriptorBase): + """Common class for descriptors that can be nested.""" + + def __init__(self, options, options_class_name, name, full_name, + file, containing_type, serialized_start=None, + serialized_end=None, serialized_options=None): + """Constructor. + + Args: + options: Protocol message options or None + to use default message options. + options_class_name: (str) The class name of the above options. + + name: (str) Name of this protocol message type. + full_name: (str) Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + file: (FileDescriptor) Reference to file info. + containing_type: if provided, this is a nested descriptor, with this + descriptor as parent, otherwise None. + serialized_start: The start index (inclusive) in block in the + file.serialized_pb that describes this descriptor. + serialized_end: The end index (exclusive) in block in the + file.serialized_pb that describes this descriptor. + serialized_options: Protocol message serilized options or None. + """ + super(_NestedDescriptorBase, self).__init__( + options, serialized_options, options_class_name) + + self.name = name + # TODO(falk): Add function to calculate full_name instead of having it in + # memory? + self.full_name = full_name + self.file = file + self.containing_type = containing_type + + self._serialized_start = serialized_start + self._serialized_end = serialized_end + + def CopyToProto(self, proto): + """Copies this to the matching proto in descriptor_pb2. + + Args: + proto: An empty proto instance from descriptor_pb2. + + Raises: + Error: If self couldnt be serialized, due to to few constructor arguments. + """ + if (self.file is not None and + self._serialized_start is not None and + self._serialized_end is not None): + proto.ParseFromString(self.file.serialized_pb[ + self._serialized_start:self._serialized_end]) + else: + raise Error('Descriptor does not contain serialization.') + + +class Descriptor(_NestedDescriptorBase): + + """Descriptor for a protocol message type. + + A Descriptor instance has the following attributes: + + name: (str) Name of this protocol message type. + full_name: (str) Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + + containing_type: (Descriptor) Reference to the descriptor of the + type containing us, or None if this is top-level. + + fields: (list of FieldDescriptors) Field descriptors for all + fields in this type. + fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor + objects as in |fields|, but indexed by "number" attribute in each + FieldDescriptor. + fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor + objects as in |fields|, but indexed by "name" attribute in each + FieldDescriptor. + fields_by_camelcase_name: (dict str -> FieldDescriptor) Same + FieldDescriptor objects as in |fields|, but indexed by + "camelcase_name" attribute in each FieldDescriptor. + + nested_types: (list of Descriptors) Descriptor references + for all protocol message types nested within this one. + nested_types_by_name: (dict str -> Descriptor) Same Descriptor + objects as in |nested_types|, but indexed by "name" attribute + in each Descriptor. + + enum_types: (list of EnumDescriptors) EnumDescriptor references + for all enums contained within this type. + enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor + objects as in |enum_types|, but indexed by "name" attribute + in each EnumDescriptor. + enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping + from enum value name to EnumValueDescriptor for that value. + + extensions: (list of FieldDescriptor) All extensions defined directly + within this message type (NOT within a nested type). + extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor + objects as |extensions|, but indexed by "name" attribute of each + FieldDescriptor. + + is_extendable: Does this type define any extension ranges? + + oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields + in this message. + oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|, + but indexed by "name" attribute. + + file: (FileDescriptor) Reference to file descriptor. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.Descriptor + + def __new__(cls, name, full_name, filename, containing_type, fields, + nested_types, enum_types, extensions, options=None, + serialized_options=None, + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin + syntax=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindMessageTypeByName(full_name) + + # NOTE(tmarek): The file argument redefining a builtin is nothing we can + # fix right now since we don't know how many clients already rely on the + # name of the argument. + def __init__(self, name, full_name, filename, containing_type, fields, + nested_types, enum_types, extensions, options=None, + serialized_options=None, + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin + syntax=None): + """Arguments to __init__() are as described in the description + of Descriptor fields above. + + Note that filename is an obsolete argument, that is not used anymore. + Please use file.name to access this as an attribute. + """ + super(Descriptor, self).__init__( + options, 'MessageOptions', name, full_name, file, + containing_type, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + + # We have fields in addition to fields_by_name and fields_by_number, + # so that: + # 1. Clients can index fields by "order in which they're listed." + # 2. Clients can easily iterate over all fields with the terse + # syntax: for f in descriptor.fields: ... + self.fields = fields + for field in self.fields: + field.containing_type = self + self.fields_by_number = dict((f.number, f) for f in fields) + self.fields_by_name = dict((f.name, f) for f in fields) + self._fields_by_camelcase_name = None + + self.nested_types = nested_types + for nested_type in nested_types: + nested_type.containing_type = self + self.nested_types_by_name = dict((t.name, t) for t in nested_types) + + self.enum_types = enum_types + for enum_type in self.enum_types: + enum_type.containing_type = self + self.enum_types_by_name = dict((t.name, t) for t in enum_types) + self.enum_values_by_name = dict( + (v.name, v) for t in enum_types for v in t.values) + + self.extensions = extensions + for extension in self.extensions: + extension.extension_scope = self + self.extensions_by_name = dict((f.name, f) for f in extensions) + self.is_extendable = is_extendable + self.extension_ranges = extension_ranges + self.oneofs = oneofs if oneofs is not None else [] + self.oneofs_by_name = dict((o.name, o) for o in self.oneofs) + for oneof in self.oneofs: + oneof.containing_type = self + self.syntax = syntax or "proto2" + + @property + def fields_by_camelcase_name(self): + if self._fields_by_camelcase_name is None: + self._fields_by_camelcase_name = dict( + (f.camelcase_name, f) for f in self.fields) + return self._fields_by_camelcase_name + + def EnumValueName(self, enum, value): + """Returns the string name of an enum value. + + This is just a small helper method to simplify a common operation. + + Args: + enum: string name of the Enum. + value: int, value of the enum. + + Returns: + string name of the enum value. + + Raises: + KeyError if either the Enum doesn't exist or the value is not a valid + value for the enum. + """ + return self.enum_types_by_name[enum].values_by_number[value].name + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.DescriptorProto. + + Args: + proto: An empty descriptor_pb2.DescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(Descriptor, self).CopyToProto(proto) + + +# TODO(robinson): We should have aggressive checking here, +# for example: +# * If you specify a repeated field, you should not be allowed +# to specify a default value. +# * [Other examples here as needed]. +# +# TODO(robinson): for this and other *Descriptor classes, we +# might also want to lock things down aggressively (e.g., +# prevent clients from setting the attributes). Having +# stronger invariants here in general will reduce the number +# of runtime checks we must do in reflection.py... +class FieldDescriptor(DescriptorBase): + + """Descriptor for a single field in a .proto file. + + A FieldDescriptor instance has the following attributes: + + name: (str) Name of this field, exactly as it appears in .proto. + full_name: (str) Name of this field, including containing scope. This is + particularly relevant for extensions. + camelcase_name: (str) Camelcase name of this field. + index: (int) Dense, 0-indexed index giving the order that this + field textually appears within its message in the .proto file. + number: (int) Tag number declared for this field in the .proto file. + + type: (One of the TYPE_* constants below) Declared type. + cpp_type: (One of the CPPTYPE_* constants below) C++ type used to + represent this field. + + label: (One of the LABEL_* constants below) Tells whether this + field is optional, required, or repeated. + has_default_value: (bool) True if this field has a default value defined, + otherwise false. + default_value: (Varies) Default value of this field. Only + meaningful for non-repeated scalar fields. Repeated fields + should always set this to [], and non-repeated composite + fields should always set this to None. + + containing_type: (Descriptor) Descriptor of the protocol message + type that contains this field. Set by the Descriptor constructor + if we're passed into one. + Somewhat confusingly, for extension fields, this is the + descriptor of the EXTENDED message, not the descriptor + of the message containing this field. (See is_extension and + extension_scope below). + message_type: (Descriptor) If a composite field, a descriptor + of the message type contained in this field. Otherwise, this is None. + enum_type: (EnumDescriptor) If this field contains an enum, a + descriptor of that enum. Otherwise, this is None. + + is_extension: True iff this describes an extension field. + extension_scope: (Descriptor) Only meaningful if is_extension is True. + Gives the message that immediately contains this extension field. + Will be None iff we're a top-level (file-level) extension field. + + options: (descriptor_pb2.FieldOptions) Protocol message field options or + None to use default field options. + + containing_oneof: (OneofDescriptor) If the field is a member of a oneof + union, contains its descriptor. Otherwise, None. + + file: (FileDescriptor) Reference to file descriptor. + """ + + # Must be consistent with C++ FieldDescriptor::Type enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + TYPE_DOUBLE = 1 + TYPE_FLOAT = 2 + TYPE_INT64 = 3 + TYPE_UINT64 = 4 + TYPE_INT32 = 5 + TYPE_FIXED64 = 6 + TYPE_FIXED32 = 7 + TYPE_BOOL = 8 + TYPE_STRING = 9 + TYPE_GROUP = 10 + TYPE_MESSAGE = 11 + TYPE_BYTES = 12 + TYPE_UINT32 = 13 + TYPE_ENUM = 14 + TYPE_SFIXED32 = 15 + TYPE_SFIXED64 = 16 + TYPE_SINT32 = 17 + TYPE_SINT64 = 18 + MAX_TYPE = 18 + + # Must be consistent with C++ FieldDescriptor::CppType enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + CPPTYPE_INT32 = 1 + CPPTYPE_INT64 = 2 + CPPTYPE_UINT32 = 3 + CPPTYPE_UINT64 = 4 + CPPTYPE_DOUBLE = 5 + CPPTYPE_FLOAT = 6 + CPPTYPE_BOOL = 7 + CPPTYPE_ENUM = 8 + CPPTYPE_STRING = 9 + CPPTYPE_MESSAGE = 10 + MAX_CPPTYPE = 10 + + _PYTHON_TO_CPP_PROTO_TYPE_MAP = { + TYPE_DOUBLE: CPPTYPE_DOUBLE, + TYPE_FLOAT: CPPTYPE_FLOAT, + TYPE_ENUM: CPPTYPE_ENUM, + TYPE_INT64: CPPTYPE_INT64, + TYPE_SINT64: CPPTYPE_INT64, + TYPE_SFIXED64: CPPTYPE_INT64, + TYPE_UINT64: CPPTYPE_UINT64, + TYPE_FIXED64: CPPTYPE_UINT64, + TYPE_INT32: CPPTYPE_INT32, + TYPE_SFIXED32: CPPTYPE_INT32, + TYPE_SINT32: CPPTYPE_INT32, + TYPE_UINT32: CPPTYPE_UINT32, + TYPE_FIXED32: CPPTYPE_UINT32, + TYPE_BYTES: CPPTYPE_STRING, + TYPE_STRING: CPPTYPE_STRING, + TYPE_BOOL: CPPTYPE_BOOL, + TYPE_MESSAGE: CPPTYPE_MESSAGE, + TYPE_GROUP: CPPTYPE_MESSAGE + } + + # Must be consistent with C++ FieldDescriptor::Label enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + LABEL_OPTIONAL = 1 + LABEL_REQUIRED = 2 + LABEL_REPEATED = 3 + MAX_LABEL = 3 + + # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber, + # and kLastReservedNumber in descriptor.h + MAX_FIELD_NUMBER = (1 << 29) - 1 + FIRST_RESERVED_FIELD_NUMBER = 19000 + LAST_RESERVED_FIELD_NUMBER = 19999 + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FieldDescriptor + + def __new__(cls, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + serialized_options=None, + has_default_value=True, containing_oneof=None, json_name=None, + file=None): # pylint: disable=redefined-builtin + _message.Message._CheckCalledFromGeneratedFile() + if is_extension: + return _message.default_pool.FindExtensionByName(full_name) + else: + return _message.default_pool.FindFieldByName(full_name) + + def __init__(self, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + serialized_options=None, + has_default_value=True, containing_oneof=None, json_name=None, + file=None): # pylint: disable=redefined-builtin + """The arguments are as described in the description of FieldDescriptor + attributes above. + + Note that containing_type may be None, and may be set later if necessary + (to deal with circular references between message types, for example). + Likewise for extension_scope. + """ + super(FieldDescriptor, self).__init__( + options, serialized_options, 'FieldOptions') + self.name = name + self.full_name = full_name + self.file = file + self._camelcase_name = None + if json_name is None: + self.json_name = _ToJsonName(name) + else: + self.json_name = json_name + self.index = index + self.number = number + self.type = type + self.cpp_type = cpp_type + self.label = label + self.has_default_value = has_default_value + self.default_value = default_value + self.containing_type = containing_type + self.message_type = message_type + self.enum_type = enum_type + self.is_extension = is_extension + self.extension_scope = extension_scope + self.containing_oneof = containing_oneof + if api_implementation.Type() == 'cpp': + if is_extension: + self._cdescriptor = _message.default_pool.FindExtensionByName(full_name) + else: + self._cdescriptor = _message.default_pool.FindFieldByName(full_name) + else: + self._cdescriptor = None + + @property + def camelcase_name(self): + if self._camelcase_name is None: + self._camelcase_name = _ToCamelCase(self.name) + return self._camelcase_name + + @staticmethod + def ProtoTypeToCppProtoType(proto_type): + """Converts from a Python proto type to a C++ Proto Type. + + The Python ProtocolBuffer classes specify both the 'Python' datatype and the + 'C++' datatype - and they're not the same. This helper method should + translate from one to another. + + Args: + proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*) + Returns: + descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. + Raises: + TypeTransformationError: when the Python proto type isn't known. + """ + try: + return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type] + except KeyError: + raise TypeTransformationError('Unknown proto_type: %s' % proto_type) + + +class EnumDescriptor(_NestedDescriptorBase): + + """Descriptor for an enum defined in a .proto file. + + An EnumDescriptor instance has the following attributes: + + name: (str) Name of the enum type. + full_name: (str) Full name of the type, including package name + and any enclosing type(s). + + values: (list of EnumValueDescriptors) List of the values + in this enum. + values_by_name: (dict str -> EnumValueDescriptor) Same as |values|, + but indexed by the "name" field of each EnumValueDescriptor. + values_by_number: (dict int -> EnumValueDescriptor) Same as |values|, + but indexed by the "number" field of each EnumValueDescriptor. + containing_type: (Descriptor) Descriptor of the immediate containing + type of this enum, or None if this is an enum defined at the + top level in a .proto file. Set by Descriptor's constructor + if we're passed into one. + file: (FileDescriptor) Reference to file descriptor. + options: (descriptor_pb2.EnumOptions) Enum options message or + None to use default enum options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumDescriptor + + def __new__(cls, name, full_name, filename, values, + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindEnumTypeByName(full_name) + + def __init__(self, name, full_name, filename, values, + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + """Arguments are as described in the attribute description above. + + Note that filename is an obsolete argument, that is not used anymore. + Please use file.name to access this as an attribute. + """ + super(EnumDescriptor, self).__init__( + options, 'EnumOptions', name, full_name, file, + containing_type, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + + self.values = values + for value in self.values: + value.type = self + self.values_by_name = dict((v.name, v) for v in values) + self.values_by_number = dict((v.number, v) for v in values) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.EnumDescriptorProto. + + Args: + proto: An empty descriptor_pb2.EnumDescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(EnumDescriptor, self).CopyToProto(proto) + + +class EnumValueDescriptor(DescriptorBase): + + """Descriptor for a single value within an enum. + + name: (str) Name of this value. + index: (int) Dense, 0-indexed index giving the order that this + value appears textually within its enum in the .proto file. + number: (int) Actual number assigned to this enum value. + type: (EnumDescriptor) EnumDescriptor to which this value + belongs. Set by EnumDescriptor's constructor if we're + passed into one. + options: (descriptor_pb2.EnumValueOptions) Enum value options message or + None to use default enum value options options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor + + def __new__(cls, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None): + _message.Message._CheckCalledFromGeneratedFile() + # There is no way we can build a complete EnumValueDescriptor with the + # given parameters (the name of the Enum is not known, for example). + # Fortunately generated files just pass it to the EnumDescriptor() + # constructor, which will ignore it, so returning None is good enough. + return None + + def __init__(self, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None): + """Arguments are as described in the attribute description above.""" + super(EnumValueDescriptor, self).__init__( + options, serialized_options, 'EnumValueOptions') + self.name = name + self.index = index + self.number = number + self.type = type + + +class OneofDescriptor(DescriptorBase): + """Descriptor for a oneof field. + + name: (str) Name of the oneof field. + full_name: (str) Full name of the oneof field, including package name. + index: (int) 0-based index giving the order of the oneof field inside + its containing type. + containing_type: (Descriptor) Descriptor of the protocol message + type that contains this field. Set by the Descriptor constructor + if we're passed into one. + fields: (list of FieldDescriptor) The list of field descriptors this + oneof can contain. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.OneofDescriptor + + def __new__( + cls, name, full_name, index, containing_type, fields, options=None, + serialized_options=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindOneofByName(full_name) + + def __init__( + self, name, full_name, index, containing_type, fields, options=None, + serialized_options=None): + """Arguments are as described in the attribute description above.""" + super(OneofDescriptor, self).__init__( + options, serialized_options, 'OneofOptions') + self.name = name + self.full_name = full_name + self.index = index + self.containing_type = containing_type + self.fields = fields + + +class ServiceDescriptor(_NestedDescriptorBase): + + """Descriptor for a service. + + name: (str) Name of the service. + full_name: (str) Full name of the service, including package name. + index: (int) 0-indexed index giving the order that this services + definition appears withing the .proto file. + methods: (list of MethodDescriptor) List of methods provided by this + service. + methods_by_name: (dict str -> MethodDescriptor) Same MethodDescriptor + objects as in |methods_by_name|, but indexed by "name" attribute in each + MethodDescriptor. + options: (descriptor_pb2.ServiceOptions) Service options message or + None to use default service options. + file: (FileDescriptor) Reference to file info. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor + + def __new__(cls, name, full_name, index, methods, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access + return _message.default_pool.FindServiceByName(full_name) + + def __init__(self, name, full_name, index, methods, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + super(ServiceDescriptor, self).__init__( + options, 'ServiceOptions', name, full_name, file, + None, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + self.index = index + self.methods = methods + self.methods_by_name = dict((m.name, m) for m in methods) + # Set the containing service for each method in this service. + for method in self.methods: + method.containing_service = self + + def FindMethodByName(self, name): + """Searches for the specified method, and returns its descriptor.""" + return self.methods_by_name.get(name, None) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.ServiceDescriptorProto. + + Args: + proto: An empty descriptor_pb2.ServiceDescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(ServiceDescriptor, self).CopyToProto(proto) + + +class MethodDescriptor(DescriptorBase): + + """Descriptor for a method in a service. + + name: (str) Name of the method within the service. + full_name: (str) Full name of method. + index: (int) 0-indexed index of the method inside the service. + containing_service: (ServiceDescriptor) The service that contains this + method. + input_type: The descriptor of the message that this method accepts. + output_type: The descriptor of the message that this method returns. + options: (descriptor_pb2.MethodOptions) Method options message or + None to use default method options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.MethodDescriptor + + def __new__(cls, name, full_name, index, containing_service, + input_type, output_type, options=None, serialized_options=None): + _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access + return _message.default_pool.FindMethodByName(full_name) + + def __init__(self, name, full_name, index, containing_service, + input_type, output_type, options=None, serialized_options=None): + """The arguments are as described in the description of MethodDescriptor + attributes above. + + Note that containing_service may be None, and may be set later if necessary. + """ + super(MethodDescriptor, self).__init__( + options, serialized_options, 'MethodOptions') + self.name = name + self.full_name = full_name + self.index = index + self.containing_service = containing_service + self.input_type = input_type + self.output_type = output_type + + +class FileDescriptor(DescriptorBase): + """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto. + + Note that enum_types_by_name, extensions_by_name, and dependencies + fields are only set by the message_factory module, and not by the + generated proto code. + + name: name of file, relative to root of source tree. + package: name of the package + syntax: string indicating syntax of the file (can be "proto2" or "proto3") + serialized_pb: (str) Byte string of serialized + descriptor_pb2.FileDescriptorProto. + dependencies: List of other FileDescriptors this FileDescriptor depends on. + public_dependencies: A list of FileDescriptors, subset of the dependencies + above, which were declared as "public". + message_types_by_name: Dict of message names of their descriptors. + enum_types_by_name: Dict of enum names and their descriptors. + extensions_by_name: Dict of extension names and their descriptors. + services_by_name: Dict of services names and their descriptors. + pool: the DescriptorPool this descriptor belongs to. When not passed to the + constructor, the global default pool is used. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FileDescriptor + + def __new__(cls, name, package, options=None, + serialized_options=None, serialized_pb=None, + dependencies=None, public_dependencies=None, + syntax=None, pool=None): + # FileDescriptor() is called from various places, not only from generated + # files, to register dynamic proto files and messages. + if serialized_pb: + # TODO(amauryfa): use the pool passed as argument. This will work only + # for C++-implemented DescriptorPools. + return _message.default_pool.AddSerializedFile(serialized_pb) + else: + return super(FileDescriptor, cls).__new__(cls) + + def __init__(self, name, package, options=None, + serialized_options=None, serialized_pb=None, + dependencies=None, public_dependencies=None, + syntax=None, pool=None): + """Constructor.""" + super(FileDescriptor, self).__init__( + options, serialized_options, 'FileOptions') + + if pool is None: + from google.protobuf import descriptor_pool + pool = descriptor_pool.Default() + self.pool = pool + self.message_types_by_name = {} + self.name = name + self.package = package + self.syntax = syntax or "proto2" + self.serialized_pb = serialized_pb + + self.enum_types_by_name = {} + self.extensions_by_name = {} + self.services_by_name = {} + self.dependencies = (dependencies or []) + self.public_dependencies = (public_dependencies or []) + + if (api_implementation.Type() == 'cpp' and + self.serialized_pb is not None): + _message.default_pool.AddSerializedFile(self.serialized_pb) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.FileDescriptorProto. + + Args: + proto: An empty descriptor_pb2.FileDescriptorProto. + """ + proto.ParseFromString(self.serialized_pb) + + +def _ParseOptions(message, string): + """Parses serialized options. + + This helper function is used to parse serialized options in generated + proto2 files. It must not be used outside proto2. + """ + message.ParseFromString(string) + return message + + +def _ToCamelCase(name): + """Converts name to camel-case and returns it.""" + capitalize_next = False + result = [] + + for c in name: + if c == '_': + if result: + capitalize_next = True + elif capitalize_next: + result.append(c.upper()) + capitalize_next = False + else: + result += c + + # Lower-case the first letter. + if result and result[0].isupper(): + result[0] = result[0].lower() + return ''.join(result) + + +def _OptionsOrNone(descriptor_proto): + """Returns the value of the field `options`, or None if it is not set.""" + if descriptor_proto.HasField('options'): + return descriptor_proto.options + else: + return None + + +def _ToJsonName(name): + """Converts name to Json name and returns it.""" + capitalize_next = False + result = [] + + for c in name: + if c == '_': + capitalize_next = True + elif capitalize_next: + result.append(c.upper()) + capitalize_next = False + else: + result += c + + return ''.join(result) + + +def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, + syntax=None): + """Make a protobuf Descriptor given a DescriptorProto protobuf. + + Handles nested descriptors. Note that this is limited to the scope of defining + a message inside of another message. Composite fields can currently only be + resolved if the message is defined in the same scope as the field. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: Optional package name for the new message Descriptor (string). + build_file_if_cpp: Update the C++ descriptor pool if api matches. + Set to False on recursion, so no duplicates are created. + syntax: The syntax/semantics that should be used. Set to "proto3" to get + proto3 field presence semantics. + Returns: + A Descriptor for protobuf messages. + """ + if api_implementation.Type() == 'cpp' and build_file_if_cpp: + # The C++ implementation requires all descriptors to be backed by the same + # definition in the C++ descriptor pool. To do this, we build a + # FileDescriptorProto with the same definition as this descriptor and build + # it into the pool. + from google.protobuf import descriptor_pb2 + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.message_type.add().MergeFrom(desc_proto) + + # Generate a random name for this proto file to prevent conflicts with any + # imported ones. We need to specify a file name so the descriptor pool + # accepts our FileDescriptorProto, but it is not important what that file + # name is actually set to. + proto_name = binascii.hexlify(os.urandom(16)).decode('ascii') + + if package: + file_descriptor_proto.name = os.path.join(package.replace('.', '/'), + proto_name + '.proto') + file_descriptor_proto.package = package + else: + file_descriptor_proto.name = proto_name + '.proto' + + _message.default_pool.Add(file_descriptor_proto) + result = _message.default_pool.FindFileByName(file_descriptor_proto.name) + + if _USE_C_DESCRIPTORS: + return result.message_types_by_name[desc_proto.name] + + full_message_name = [desc_proto.name] + if package: full_message_name.insert(0, package) + + # Create Descriptors for enum types + enum_types = {} + for enum_proto in desc_proto.enum_type: + full_name = '.'.join(full_message_name + [enum_proto.name]) + enum_desc = EnumDescriptor( + enum_proto.name, full_name, None, [ + EnumValueDescriptor(enum_val.name, ii, enum_val.number) + for ii, enum_val in enumerate(enum_proto.value)]) + enum_types[full_name] = enum_desc + + # Create Descriptors for nested types + nested_types = {} + for nested_proto in desc_proto.nested_type: + full_name = '.'.join(full_message_name + [nested_proto.name]) + # Nested types are just those defined inside of the message, not all types + # used by fields in the message, so no loops are possible here. + nested_desc = MakeDescriptor(nested_proto, + package='.'.join(full_message_name), + build_file_if_cpp=False, + syntax=syntax) + nested_types[full_name] = nested_desc + + fields = [] + for field_proto in desc_proto.field: + full_name = '.'.join(full_message_name + [field_proto.name]) + enum_desc = None + nested_desc = None + if field_proto.json_name: + json_name = field_proto.json_name + else: + json_name = None + if field_proto.HasField('type_name'): + type_name = field_proto.type_name + full_type_name = '.'.join(full_message_name + + [type_name[type_name.rfind('.')+1:]]) + if full_type_name in nested_types: + nested_desc = nested_types[full_type_name] + elif full_type_name in enum_types: + enum_desc = enum_types[full_type_name] + # Else type_name references a non-local type, which isn't implemented + field = FieldDescriptor( + field_proto.name, full_name, field_proto.number - 1, + field_proto.number, field_proto.type, + FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type), + field_proto.label, None, nested_desc, enum_desc, None, False, None, + options=_OptionsOrNone(field_proto), has_default_value=False, + json_name=json_name) + fields.append(field) + + desc_name = '.'.join(full_message_name) + return Descriptor(desc_proto.name, desc_name, None, None, fields, + list(nested_types.values()), list(enum_types.values()), [], + options=_OptionsOrNone(desc_proto)) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/descriptor_database.py b/venv/lib/python3.7/site-packages/google/protobuf/descriptor_database.py new file mode 100644 index 0000000..8b7715c --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/descriptor_database.py @@ -0,0 +1,162 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides a container for DescriptorProtos.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import warnings + + +class Error(Exception): + pass + + +class DescriptorDatabaseConflictingDefinitionError(Error): + """Raised when a proto is added with the same name & different descriptor.""" + + +class DescriptorDatabase(object): + """A container accepting FileDescriptorProtos and maps DescriptorProtos.""" + + def __init__(self): + self._file_desc_protos_by_file = {} + self._file_desc_protos_by_symbol = {} + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this database. + + Args: + file_desc_proto: The FileDescriptorProto to add. + Raises: + DescriptorDatabaseConflictingDefinitionError: if an attempt is made to + add a proto with the same name but different definition than an + exisiting proto in the database. + """ + proto_name = file_desc_proto.name + if proto_name not in self._file_desc_protos_by_file: + self._file_desc_protos_by_file[proto_name] = file_desc_proto + elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: + raise DescriptorDatabaseConflictingDefinitionError( + '%s already added, but with different descriptor.' % proto_name) + else: + return + + # Add all the top-level descriptors to the index. + package = file_desc_proto.package + for message in file_desc_proto.message_type: + for name in _ExtractSymbols(message, package): + self._AddSymbol(name, file_desc_proto) + for enum in file_desc_proto.enum_type: + self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) + for extension in file_desc_proto.extension: + self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) + for service in file_desc_proto.service: + self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) + + def FindFileByName(self, name): + """Finds the file descriptor proto by file name. + + Typically the file name is a relative path ending to a .proto file. The + proto with the given name will have to have been added to this database + using the Add method or else an error will be raised. + + Args: + name: The file name to find. + + Returns: + The file descriptor proto matching the name. + + Raises: + KeyError if no file by the given name was added. + """ + + return self._file_desc_protos_by_file[name] + + def FindFileContainingSymbol(self, symbol): + """Finds the file descriptor proto containing the specified symbol. + + The symbol should be a fully qualified name including the file descriptor's + package and any containing messages. Some examples: + + 'some.package.name.Message' + 'some.package.name.Message.NestedEnum' + 'some.package.name.Message.some_field' + + The file descriptor proto containing the specified symbol must be added to + this database using the Add method or else an error will be raised. + + Args: + symbol: The fully qualified symbol name. + + Returns: + The file descriptor proto containing the symbol. + + Raises: + KeyError if no file contains the specified symbol. + """ + try: + return self._file_desc_protos_by_symbol[symbol] + except KeyError: + # Fields, enum values, and nested extensions are not in + # _file_desc_protos_by_symbol. Try to find the top level + # descriptor. Non-existent nested symbol under a valid top level + # descriptor can also be found. The behavior is the same with + # protobuf C++. + top_level, _, _ = symbol.rpartition('.') + return self._file_desc_protos_by_symbol[top_level] + + def _AddSymbol(self, name, file_desc_proto): + if name in self._file_desc_protos_by_symbol: + warn_msg = ('Conflict register for file "' + file_desc_proto.name + + '": ' + name + + ' is already defined in file "' + + self._file_desc_protos_by_symbol[name].name + '"') + warnings.warn(warn_msg, RuntimeWarning) + self._file_desc_protos_by_symbol[name] = file_desc_proto + + +def _ExtractSymbols(desc_proto, package): + """Pulls out all the symbols from a descriptor proto. + + Args: + desc_proto: The proto to extract symbols from. + package: The package containing the descriptor type. + + Yields: + The fully qualified name found in the descriptor. + """ + message_name = package + '.' + desc_proto.name if package else desc_proto.name + yield message_name + for nested_type in desc_proto.nested_type: + for symbol in _ExtractSymbols(nested_type, message_name): + yield symbol + for enum_type in desc_proto.enum_type: + yield '.'.join((message_name, enum_type.name)) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pb2.py new file mode 100644 index 0000000..34055d7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pb2.py @@ -0,0 +1,2033 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/descriptor.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/descriptor.proto', + package='google.protobuf', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"G\n\x11\x46ileDescriptorSet\x12\x32\n\x04\x66ile\x18\x01 \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\"\xdb\x03\n\x13\x46ileDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07package\x18\x02 \x01(\t\x12\x12\n\ndependency\x18\x03 \x03(\t\x12\x19\n\x11public_dependency\x18\n \x03(\x05\x12\x17\n\x0fweak_dependency\x18\x0b \x03(\x05\x12\x36\n\x0cmessage_type\x18\x04 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x05 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12\x38\n\x07service\x18\x06 \x03(\x0b\x32\'.google.protobuf.ServiceDescriptorProto\x12\x38\n\textension\x18\x07 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12-\n\x07options\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.FileOptions\x12\x39\n\x10source_code_info\x18\t \x01(\x0b\x32\x1f.google.protobuf.SourceCodeInfo\x12\x0e\n\x06syntax\x18\x0c \x01(\t\"\xa9\x05\n\x0f\x44\x65scriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05\x66ield\x18\x02 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x38\n\textension\x18\x06 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x35\n\x0bnested_type\x18\x03 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x04 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12H\n\x0f\x65xtension_range\x18\x05 \x03(\x0b\x32/.google.protobuf.DescriptorProto.ExtensionRange\x12\x39\n\noneof_decl\x18\x08 \x03(\x0b\x32%.google.protobuf.OneofDescriptorProto\x12\x30\n\x07options\x18\x07 \x01(\x0b\x32\x1f.google.protobuf.MessageOptions\x12\x46\n\x0ereserved_range\x18\t \x03(\x0b\x32..google.protobuf.DescriptorProto.ReservedRange\x12\x15\n\rreserved_name\x18\n \x03(\t\x1a\x65\n\x0e\x45xtensionRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\x12\x37\n\x07options\x18\x03 \x01(\x0b\x32&.google.protobuf.ExtensionRangeOptions\x1a+\n\rReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"g\n\x15\x45xtensionRangeOptions\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xbc\x05\n\x14\x46ieldDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12:\n\x05label\x18\x04 \x01(\x0e\x32+.google.protobuf.FieldDescriptorProto.Label\x12\x38\n\x04type\x18\x05 \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x11\n\ttype_name\x18\x06 \x01(\t\x12\x10\n\x08\x65xtendee\x18\x02 \x01(\t\x12\x15\n\rdefault_value\x18\x07 \x01(\t\x12\x13\n\x0boneof_index\x18\t \x01(\x05\x12\x11\n\tjson_name\x18\n \x01(\t\x12.\n\x07options\x18\x08 \x01(\x0b\x32\x1d.google.protobuf.FieldOptions\"\xb6\x02\n\x04Type\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"C\n\x05Label\x12\x12\n\x0eLABEL_OPTIONAL\x10\x01\x12\x12\n\x0eLABEL_REQUIRED\x10\x02\x12\x12\n\x0eLABEL_REPEATED\x10\x03\"T\n\x14OneofDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\x07options\x18\x02 \x01(\x0b\x32\x1d.google.protobuf.OneofOptions\"\xa4\x02\n\x13\x45numDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x03(\x0b\x32).google.protobuf.EnumValueDescriptorProto\x12-\n\x07options\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.EnumOptions\x12N\n\x0ereserved_range\x18\x04 \x03(\x0b\x32\x36.google.protobuf.EnumDescriptorProto.EnumReservedRange\x12\x15\n\rreserved_name\x18\x05 \x03(\t\x1a/\n\x11\x45numReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"l\n\x18\x45numValueDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12\x32\n\x07options\x18\x03 \x01(\x0b\x32!.google.protobuf.EnumValueOptions\"\x90\x01\n\x16ServiceDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06method\x18\x02 \x03(\x0b\x32&.google.protobuf.MethodDescriptorProto\x12\x30\n\x07options\x18\x03 \x01(\x0b\x32\x1f.google.protobuf.ServiceOptions\"\xc1\x01\n\x15MethodDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ninput_type\x18\x02 \x01(\t\x12\x13\n\x0boutput_type\x18\x03 \x01(\t\x12/\n\x07options\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.MethodOptions\x12\x1f\n\x10\x63lient_streaming\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10server_streaming\x18\x06 \x01(\x08:\x05\x66\x61lse\"\xa6\x06\n\x0b\x46ileOptions\x12\x14\n\x0cjava_package\x18\x01 \x01(\t\x12\x1c\n\x14java_outer_classname\x18\x08 \x01(\t\x12\"\n\x13java_multiple_files\x18\n \x01(\x08:\x05\x66\x61lse\x12)\n\x1djava_generate_equals_and_hash\x18\x14 \x01(\x08\x42\x02\x18\x01\x12%\n\x16java_string_check_utf8\x18\x1b \x01(\x08:\x05\x66\x61lse\x12\x46\n\x0coptimize_for\x18\t \x01(\x0e\x32).google.protobuf.FileOptions.OptimizeMode:\x05SPEED\x12\x12\n\ngo_package\x18\x0b \x01(\t\x12\"\n\x13\x63\x63_generic_services\x18\x10 \x01(\x08:\x05\x66\x61lse\x12$\n\x15java_generic_services\x18\x11 \x01(\x08:\x05\x66\x61lse\x12\"\n\x13py_generic_services\x18\x12 \x01(\x08:\x05\x66\x61lse\x12#\n\x14php_generic_services\x18* \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10\x63\x63_enable_arenas\x18\x1f \x01(\x08:\x05\x66\x61lse\x12\x19\n\x11objc_class_prefix\x18$ \x01(\t\x12\x18\n\x10\x63sharp_namespace\x18% \x01(\t\x12\x14\n\x0cswift_prefix\x18\' \x01(\t\x12\x18\n\x10php_class_prefix\x18( \x01(\t\x12\x15\n\rphp_namespace\x18) \x01(\t\x12\x1e\n\x16php_metadata_namespace\x18, \x01(\t\x12\x14\n\x0cruby_package\x18- \x01(\t\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\":\n\x0cOptimizeMode\x12\t\n\x05SPEED\x10\x01\x12\r\n\tCODE_SIZE\x10\x02\x12\x10\n\x0cLITE_RUNTIME\x10\x03*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08&\x10\'\"\xf2\x01\n\x0eMessageOptions\x12&\n\x17message_set_wire_format\x18\x01 \x01(\x08:\x05\x66\x61lse\x12.\n\x1fno_standard_descriptor_accessor\x18\x02 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x11\n\tmap_entry\x18\x07 \x01(\x08\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x08\x10\tJ\x04\x08\t\x10\n\"\x9e\x03\n\x0c\x46ieldOptions\x12:\n\x05\x63type\x18\x01 \x01(\x0e\x32#.google.protobuf.FieldOptions.CType:\x06STRING\x12\x0e\n\x06packed\x18\x02 \x01(\x08\x12?\n\x06jstype\x18\x06 \x01(\x0e\x32$.google.protobuf.FieldOptions.JSType:\tJS_NORMAL\x12\x13\n\x04lazy\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x13\n\x04weak\x18\n \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"/\n\x05\x43Type\x12\n\n\x06STRING\x10\x00\x12\x08\n\x04\x43ORD\x10\x01\x12\x10\n\x0cSTRING_PIECE\x10\x02\"5\n\x06JSType\x12\r\n\tJS_NORMAL\x10\x00\x12\r\n\tJS_STRING\x10\x01\x12\r\n\tJS_NUMBER\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x04\x10\x05\"^\n\x0cOneofOptions\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x93\x01\n\x0b\x45numOptions\x12\x13\n\x0b\x61llow_alias\x18\x02 \x01(\x08\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x05\x10\x06\"}\n\x10\x45numValueOptions\x12\x19\n\ndeprecated\x18\x01 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"{\n\x0eServiceOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xad\x02\n\rMethodOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12_\n\x11idempotency_level\x18\" \x01(\x0e\x32/.google.protobuf.MethodOptions.IdempotencyLevel:\x13IDEMPOTENCY_UNKNOWN\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"P\n\x10IdempotencyLevel\x12\x17\n\x13IDEMPOTENCY_UNKNOWN\x10\x00\x12\x13\n\x0fNO_SIDE_EFFECTS\x10\x01\x12\x0e\n\nIDEMPOTENT\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x9e\x02\n\x13UninterpretedOption\x12;\n\x04name\x18\x02 \x03(\x0b\x32-.google.protobuf.UninterpretedOption.NamePart\x12\x18\n\x10identifier_value\x18\x03 \x01(\t\x12\x1a\n\x12positive_int_value\x18\x04 \x01(\x04\x12\x1a\n\x12negative_int_value\x18\x05 \x01(\x03\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x14\n\x0cstring_value\x18\x07 \x01(\x0c\x12\x17\n\x0f\x61ggregate_value\x18\x08 \x01(\t\x1a\x33\n\x08NamePart\x12\x11\n\tname_part\x18\x01 \x02(\t\x12\x14\n\x0cis_extension\x18\x02 \x02(\x08\"\xd5\x01\n\x0eSourceCodeInfo\x12:\n\x08location\x18\x01 \x03(\x0b\x32(.google.protobuf.SourceCodeInfo.Location\x1a\x86\x01\n\x08Location\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x10\n\x04span\x18\x02 \x03(\x05\x42\x02\x10\x01\x12\x18\n\x10leading_comments\x18\x03 \x01(\t\x12\x19\n\x11trailing_comments\x18\x04 \x01(\t\x12!\n\x19leading_detached_comments\x18\x06 \x03(\t\"\xa7\x01\n\x11GeneratedCodeInfo\x12\x41\n\nannotation\x18\x01 \x03(\x0b\x32-.google.protobuf.GeneratedCodeInfo.Annotation\x1aO\n\nAnnotation\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x13\n\x0bsource_file\x18\x02 \x01(\t\x12\r\n\x05\x62\x65gin\x18\x03 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x04 \x01(\x05\x42\x8f\x01\n\x13\x63om.google.protobufB\x10\x44\x65scriptorProtosH\x01Z>github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection') +) + + + +_FIELDDESCRIPTORPROTO_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='google.protobuf.FieldDescriptorProto.Type', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_DOUBLE', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FLOAT', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT64', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT64', index=3, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT32', index=4, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED64', index=5, number=6, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED32', index=6, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BOOL', index=7, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_STRING', index=8, number=9, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_GROUP', index=9, number=10, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_MESSAGE', index=10, number=11, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BYTES', index=11, number=12, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT32', index=12, number=13, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_ENUM', index=13, number=14, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED32', index=14, number=15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED64', index=15, number=16, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT32', index=16, number=17, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT64', index=17, number=18, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1715, + serialized_end=2025, +) +_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_TYPE) + +_FIELDDESCRIPTORPROTO_LABEL = _descriptor.EnumDescriptor( + name='Label', + full_name='google.protobuf.FieldDescriptorProto.Label', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LABEL_OPTIONAL', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LABEL_REQUIRED', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LABEL_REPEATED', index=2, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2027, + serialized_end=2094, +) +_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_LABEL) + +_FILEOPTIONS_OPTIMIZEMODE = _descriptor.EnumDescriptor( + name='OptimizeMode', + full_name='google.protobuf.FileOptions.OptimizeMode', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SPEED', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CODE_SIZE', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LITE_RUNTIME', index=2, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3662, + serialized_end=3720, +) +_sym_db.RegisterEnumDescriptor(_FILEOPTIONS_OPTIMIZEMODE) + +_FIELDOPTIONS_CTYPE = _descriptor.EnumDescriptor( + name='CType', + full_name='google.protobuf.FieldOptions.CType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='STRING', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CORD', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='STRING_PIECE', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=4280, + serialized_end=4327, +) +_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_CTYPE) + +_FIELDOPTIONS_JSTYPE = _descriptor.EnumDescriptor( + name='JSType', + full_name='google.protobuf.FieldOptions.JSType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='JS_NORMAL', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='JS_STRING', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='JS_NUMBER', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=4329, + serialized_end=4382, +) +_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_JSTYPE) + +_METHODOPTIONS_IDEMPOTENCYLEVEL = _descriptor.EnumDescriptor( + name='IdempotencyLevel', + full_name='google.protobuf.MethodOptions.IdempotencyLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IDEMPOTENCY_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NO_SIDE_EFFECTS', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IDEMPOTENT', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=5110, + serialized_end=5190, +) +_sym_db.RegisterEnumDescriptor(_METHODOPTIONS_IDEMPOTENCYLEVEL) + + +_FILEDESCRIPTORSET = _descriptor.Descriptor( + name='FileDescriptorSet', + full_name='google.protobuf.FileDescriptorSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.FileDescriptorSet.file', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=53, + serialized_end=124, +) + + +_FILEDESCRIPTORPROTO = _descriptor.Descriptor( + name='FileDescriptorProto', + full_name='google.protobuf.FileDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.FileDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='package', full_name='google.protobuf.FileDescriptorProto.package', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dependency', full_name='google.protobuf.FileDescriptorProto.dependency', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='public_dependency', full_name='google.protobuf.FileDescriptorProto.public_dependency', index=3, + number=10, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weak_dependency', full_name='google.protobuf.FileDescriptorProto.weak_dependency', index=4, + number=11, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_type', full_name='google.protobuf.FileDescriptorProto.message_type', index=5, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_type', full_name='google.protobuf.FileDescriptorProto.enum_type', index=6, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='service', full_name='google.protobuf.FileDescriptorProto.service', index=7, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extension', full_name='google.protobuf.FileDescriptorProto.extension', index=8, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.FileDescriptorProto.options', index=9, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_code_info', full_name='google.protobuf.FileDescriptorProto.source_code_info', index=10, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.FileDescriptorProto.syntax', index=11, + number=12, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=127, + serialized_end=602, +) + + +_DESCRIPTORPROTO_EXTENSIONRANGE = _descriptor.Descriptor( + name='ExtensionRange', + full_name='google.protobuf.DescriptorProto.ExtensionRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.DescriptorProto.ExtensionRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.DescriptorProto.ExtensionRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.DescriptorProto.ExtensionRange.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1140, + serialized_end=1241, +) + +_DESCRIPTORPROTO_RESERVEDRANGE = _descriptor.Descriptor( + name='ReservedRange', + full_name='google.protobuf.DescriptorProto.ReservedRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.DescriptorProto.ReservedRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.DescriptorProto.ReservedRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1243, + serialized_end=1286, +) + +_DESCRIPTORPROTO = _descriptor.Descriptor( + name='DescriptorProto', + full_name='google.protobuf.DescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.DescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field', full_name='google.protobuf.DescriptorProto.field', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extension', full_name='google.protobuf.DescriptorProto.extension', index=2, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_type', full_name='google.protobuf.DescriptorProto.nested_type', index=3, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_type', full_name='google.protobuf.DescriptorProto.enum_type', index=4, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extension_range', full_name='google.protobuf.DescriptorProto.extension_range', index=5, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_decl', full_name='google.protobuf.DescriptorProto.oneof_decl', index=6, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.DescriptorProto.options', index=7, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_range', full_name='google.protobuf.DescriptorProto.reserved_range', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_name', full_name='google.protobuf.DescriptorProto.reserved_name', index=9, + number=10, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPROTO_EXTENSIONRANGE, _DESCRIPTORPROTO_RESERVEDRANGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=605, + serialized_end=1286, +) + + +_EXTENSIONRANGEOPTIONS = _descriptor.Descriptor( + name='ExtensionRangeOptions', + full_name='google.protobuf.ExtensionRangeOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.ExtensionRangeOptions.uninterpreted_option', index=0, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=1288, + serialized_end=1391, +) + + +_FIELDDESCRIPTORPROTO = _descriptor.Descriptor( + name='FieldDescriptorProto', + full_name='google.protobuf.FieldDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.FieldDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.FieldDescriptorProto.number', index=1, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='label', full_name='google.protobuf.FieldDescriptorProto.label', index=2, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type', full_name='google.protobuf.FieldDescriptorProto.type', index=3, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type_name', full_name='google.protobuf.FieldDescriptorProto.type_name', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extendee', full_name='google.protobuf.FieldDescriptorProto.extendee', index=5, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_value', full_name='google.protobuf.FieldDescriptorProto.default_value', index=6, + number=7, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_index', full_name='google.protobuf.FieldDescriptorProto.oneof_index', index=7, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='json_name', full_name='google.protobuf.FieldDescriptorProto.json_name', index=8, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.FieldDescriptorProto.options', index=9, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELDDESCRIPTORPROTO_TYPE, + _FIELDDESCRIPTORPROTO_LABEL, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1394, + serialized_end=2094, +) + + +_ONEOFDESCRIPTORPROTO = _descriptor.Descriptor( + name='OneofDescriptorProto', + full_name='google.protobuf.OneofDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.OneofDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.OneofDescriptorProto.options', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2096, + serialized_end=2180, +) + + +_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE = _descriptor.Descriptor( + name='EnumReservedRange', + full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2428, + serialized_end=2475, +) + +_ENUMDESCRIPTORPROTO = _descriptor.Descriptor( + name='EnumDescriptorProto', + full_name='google.protobuf.EnumDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.EnumDescriptorProto.value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_range', full_name='google.protobuf.EnumDescriptorProto.reserved_range', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_name', full_name='google.protobuf.EnumDescriptorProto.reserved_name', index=4, + number=5, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2183, + serialized_end=2475, +) + + +_ENUMVALUEDESCRIPTORPROTO = _descriptor.Descriptor( + name='EnumValueDescriptorProto', + full_name='google.protobuf.EnumValueDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumValueDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.EnumValueDescriptorProto.number', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumValueDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2477, + serialized_end=2585, +) + + +_SERVICEDESCRIPTORPROTO = _descriptor.Descriptor( + name='ServiceDescriptorProto', + full_name='google.protobuf.ServiceDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.ServiceDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='method', full_name='google.protobuf.ServiceDescriptorProto.method', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.ServiceDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2588, + serialized_end=2732, +) + + +_METHODDESCRIPTORPROTO = _descriptor.Descriptor( + name='MethodDescriptorProto', + full_name='google.protobuf.MethodDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.MethodDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='input_type', full_name='google.protobuf.MethodDescriptorProto.input_type', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='output_type', full_name='google.protobuf.MethodDescriptorProto.output_type', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.MethodDescriptorProto.options', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='client_streaming', full_name='google.protobuf.MethodDescriptorProto.client_streaming', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='server_streaming', full_name='google.protobuf.MethodDescriptorProto.server_streaming', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2735, + serialized_end=2928, +) + + +_FILEOPTIONS = _descriptor.Descriptor( + name='FileOptions', + full_name='google.protobuf.FileOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='java_package', full_name='google.protobuf.FileOptions.java_package', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_outer_classname', full_name='google.protobuf.FileOptions.java_outer_classname', index=1, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_multiple_files', full_name='google.protobuf.FileOptions.java_multiple_files', index=2, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_generate_equals_and_hash', full_name='google.protobuf.FileOptions.java_generate_equals_and_hash', index=3, + number=20, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_string_check_utf8', full_name='google.protobuf.FileOptions.java_string_check_utf8', index=4, + number=27, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optimize_for', full_name='google.protobuf.FileOptions.optimize_for', index=5, + number=9, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='go_package', full_name='google.protobuf.FileOptions.go_package', index=6, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cc_generic_services', full_name='google.protobuf.FileOptions.cc_generic_services', index=7, + number=16, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_generic_services', full_name='google.protobuf.FileOptions.java_generic_services', index=8, + number=17, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='py_generic_services', full_name='google.protobuf.FileOptions.py_generic_services', index=9, + number=18, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_generic_services', full_name='google.protobuf.FileOptions.php_generic_services', index=10, + number=42, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.FileOptions.deprecated', index=11, + number=23, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cc_enable_arenas', full_name='google.protobuf.FileOptions.cc_enable_arenas', index=12, + number=31, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='objc_class_prefix', full_name='google.protobuf.FileOptions.objc_class_prefix', index=13, + number=36, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='csharp_namespace', full_name='google.protobuf.FileOptions.csharp_namespace', index=14, + number=37, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='swift_prefix', full_name='google.protobuf.FileOptions.swift_prefix', index=15, + number=39, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_class_prefix', full_name='google.protobuf.FileOptions.php_class_prefix', index=16, + number=40, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_namespace', full_name='google.protobuf.FileOptions.php_namespace', index=17, + number=41, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_metadata_namespace', full_name='google.protobuf.FileOptions.php_metadata_namespace', index=18, + number=44, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ruby_package', full_name='google.protobuf.FileOptions.ruby_package', index=19, + number=45, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.FileOptions.uninterpreted_option', index=20, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FILEOPTIONS_OPTIMIZEMODE, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=2931, + serialized_end=3737, +) + + +_MESSAGEOPTIONS = _descriptor.Descriptor( + name='MessageOptions', + full_name='google.protobuf.MessageOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_set_wire_format', full_name='google.protobuf.MessageOptions.message_set_wire_format', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='no_standard_descriptor_accessor', full_name='google.protobuf.MessageOptions.no_standard_descriptor_accessor', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.MessageOptions.deprecated', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_entry', full_name='google.protobuf.MessageOptions.map_entry', index=3, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.MessageOptions.uninterpreted_option', index=4, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=3740, + serialized_end=3982, +) + + +_FIELDOPTIONS = _descriptor.Descriptor( + name='FieldOptions', + full_name='google.protobuf.FieldOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ctype', full_name='google.protobuf.FieldOptions.ctype', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed', full_name='google.protobuf.FieldOptions.packed', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='jstype', full_name='google.protobuf.FieldOptions.jstype', index=2, + number=6, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lazy', full_name='google.protobuf.FieldOptions.lazy', index=3, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.FieldOptions.deprecated', index=4, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weak', full_name='google.protobuf.FieldOptions.weak', index=5, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.FieldOptions.uninterpreted_option', index=6, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELDOPTIONS_CTYPE, + _FIELDOPTIONS_JSTYPE, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=3985, + serialized_end=4399, +) + + +_ONEOFOPTIONS = _descriptor.Descriptor( + name='OneofOptions', + full_name='google.protobuf.OneofOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.OneofOptions.uninterpreted_option', index=0, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4401, + serialized_end=4495, +) + + +_ENUMOPTIONS = _descriptor.Descriptor( + name='EnumOptions', + full_name='google.protobuf.EnumOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='allow_alias', full_name='google.protobuf.EnumOptions.allow_alias', index=0, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.EnumOptions.deprecated', index=1, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.EnumOptions.uninterpreted_option', index=2, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4498, + serialized_end=4645, +) + + +_ENUMVALUEOPTIONS = _descriptor.Descriptor( + name='EnumValueOptions', + full_name='google.protobuf.EnumValueOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.EnumValueOptions.deprecated', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.EnumValueOptions.uninterpreted_option', index=1, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4647, + serialized_end=4772, +) + + +_SERVICEOPTIONS = _descriptor.Descriptor( + name='ServiceOptions', + full_name='google.protobuf.ServiceOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.ServiceOptions.deprecated', index=0, + number=33, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.ServiceOptions.uninterpreted_option', index=1, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4774, + serialized_end=4897, +) + + +_METHODOPTIONS = _descriptor.Descriptor( + name='MethodOptions', + full_name='google.protobuf.MethodOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.MethodOptions.deprecated', index=0, + number=33, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='idempotency_level', full_name='google.protobuf.MethodOptions.idempotency_level', index=1, + number=34, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.MethodOptions.uninterpreted_option', index=2, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _METHODOPTIONS_IDEMPOTENCYLEVEL, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4900, + serialized_end=5201, +) + + +_UNINTERPRETEDOPTION_NAMEPART = _descriptor.Descriptor( + name='NamePart', + full_name='google.protobuf.UninterpretedOption.NamePart', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name_part', full_name='google.protobuf.UninterpretedOption.NamePart.name_part', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='is_extension', full_name='google.protobuf.UninterpretedOption.NamePart.is_extension', index=1, + number=2, type=8, cpp_type=7, label=2, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5439, + serialized_end=5490, +) + +_UNINTERPRETEDOPTION = _descriptor.Descriptor( + name='UninterpretedOption', + full_name='google.protobuf.UninterpretedOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.UninterpretedOption.name', index=0, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='identifier_value', full_name='google.protobuf.UninterpretedOption.identifier_value', index=1, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='positive_int_value', full_name='google.protobuf.UninterpretedOption.positive_int_value', index=2, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='negative_int_value', full_name='google.protobuf.UninterpretedOption.negative_int_value', index=3, + number=5, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_value', full_name='google.protobuf.UninterpretedOption.double_value', index=4, + number=6, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='google.protobuf.UninterpretedOption.string_value', index=5, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='aggregate_value', full_name='google.protobuf.UninterpretedOption.aggregate_value', index=6, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_UNINTERPRETEDOPTION_NAMEPART, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5204, + serialized_end=5490, +) + + +_SOURCECODEINFO_LOCATION = _descriptor.Descriptor( + name='Location', + full_name='google.protobuf.SourceCodeInfo.Location', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='path', full_name='google.protobuf.SourceCodeInfo.Location.path', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='span', full_name='google.protobuf.SourceCodeInfo.Location.span', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='leading_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_comments', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='trailing_comments', full_name='google.protobuf.SourceCodeInfo.Location.trailing_comments', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='leading_detached_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_detached_comments', index=4, + number=6, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5572, + serialized_end=5706, +) + +_SOURCECODEINFO = _descriptor.Descriptor( + name='SourceCodeInfo', + full_name='google.protobuf.SourceCodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='location', full_name='google.protobuf.SourceCodeInfo.location', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_SOURCECODEINFO_LOCATION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5493, + serialized_end=5706, +) + + +_GENERATEDCODEINFO_ANNOTATION = _descriptor.Descriptor( + name='Annotation', + full_name='google.protobuf.GeneratedCodeInfo.Annotation', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='path', full_name='google.protobuf.GeneratedCodeInfo.Annotation.path', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_file', full_name='google.protobuf.GeneratedCodeInfo.Annotation.source_file', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='begin', full_name='google.protobuf.GeneratedCodeInfo.Annotation.begin', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.GeneratedCodeInfo.Annotation.end', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5797, + serialized_end=5876, +) + +_GENERATEDCODEINFO = _descriptor.Descriptor( + name='GeneratedCodeInfo', + full_name='google.protobuf.GeneratedCodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='annotation', full_name='google.protobuf.GeneratedCodeInfo.annotation', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_GENERATEDCODEINFO_ANNOTATION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5709, + serialized_end=5876, +) + +_FILEDESCRIPTORSET.fields_by_name['file'].message_type = _FILEDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['message_type'].message_type = _DESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['service'].message_type = _SERVICEDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['options'].message_type = _FILEOPTIONS +_FILEDESCRIPTORPROTO.fields_by_name['source_code_info'].message_type = _SOURCECODEINFO +_DESCRIPTORPROTO_EXTENSIONRANGE.fields_by_name['options'].message_type = _EXTENSIONRANGEOPTIONS +_DESCRIPTORPROTO_EXTENSIONRANGE.containing_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO_RESERVEDRANGE.containing_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['field'].message_type = _FIELDDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['nested_type'].message_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['extension_range'].message_type = _DESCRIPTORPROTO_EXTENSIONRANGE +_DESCRIPTORPROTO.fields_by_name['oneof_decl'].message_type = _ONEOFDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['options'].message_type = _MESSAGEOPTIONS +_DESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _DESCRIPTORPROTO_RESERVEDRANGE +_EXTENSIONRANGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDDESCRIPTORPROTO.fields_by_name['label'].enum_type = _FIELDDESCRIPTORPROTO_LABEL +_FIELDDESCRIPTORPROTO.fields_by_name['type'].enum_type = _FIELDDESCRIPTORPROTO_TYPE +_FIELDDESCRIPTORPROTO.fields_by_name['options'].message_type = _FIELDOPTIONS +_FIELDDESCRIPTORPROTO_TYPE.containing_type = _FIELDDESCRIPTORPROTO +_FIELDDESCRIPTORPROTO_LABEL.containing_type = _FIELDDESCRIPTORPROTO +_ONEOFDESCRIPTORPROTO.fields_by_name['options'].message_type = _ONEOFOPTIONS +_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE.containing_type = _ENUMDESCRIPTORPROTO +_ENUMDESCRIPTORPROTO.fields_by_name['value'].message_type = _ENUMVALUEDESCRIPTORPROTO +_ENUMDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMOPTIONS +_ENUMDESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE +_ENUMVALUEDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMVALUEOPTIONS +_SERVICEDESCRIPTORPROTO.fields_by_name['method'].message_type = _METHODDESCRIPTORPROTO +_SERVICEDESCRIPTORPROTO.fields_by_name['options'].message_type = _SERVICEOPTIONS +_METHODDESCRIPTORPROTO.fields_by_name['options'].message_type = _METHODOPTIONS +_FILEOPTIONS.fields_by_name['optimize_for'].enum_type = _FILEOPTIONS_OPTIMIZEMODE +_FILEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FILEOPTIONS_OPTIMIZEMODE.containing_type = _FILEOPTIONS +_MESSAGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDOPTIONS.fields_by_name['ctype'].enum_type = _FIELDOPTIONS_CTYPE +_FIELDOPTIONS.fields_by_name['jstype'].enum_type = _FIELDOPTIONS_JSTYPE +_FIELDOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDOPTIONS_CTYPE.containing_type = _FIELDOPTIONS +_FIELDOPTIONS_JSTYPE.containing_type = _FIELDOPTIONS +_ONEOFOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_ENUMOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_ENUMVALUEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_SERVICEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_METHODOPTIONS.fields_by_name['idempotency_level'].enum_type = _METHODOPTIONS_IDEMPOTENCYLEVEL +_METHODOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_METHODOPTIONS_IDEMPOTENCYLEVEL.containing_type = _METHODOPTIONS +_UNINTERPRETEDOPTION_NAMEPART.containing_type = _UNINTERPRETEDOPTION +_UNINTERPRETEDOPTION.fields_by_name['name'].message_type = _UNINTERPRETEDOPTION_NAMEPART +_SOURCECODEINFO_LOCATION.containing_type = _SOURCECODEINFO +_SOURCECODEINFO.fields_by_name['location'].message_type = _SOURCECODEINFO_LOCATION +_GENERATEDCODEINFO_ANNOTATION.containing_type = _GENERATEDCODEINFO +_GENERATEDCODEINFO.fields_by_name['annotation'].message_type = _GENERATEDCODEINFO_ANNOTATION +DESCRIPTOR.message_types_by_name['FileDescriptorSet'] = _FILEDESCRIPTORSET +DESCRIPTOR.message_types_by_name['FileDescriptorProto'] = _FILEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['DescriptorProto'] = _DESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['ExtensionRangeOptions'] = _EXTENSIONRANGEOPTIONS +DESCRIPTOR.message_types_by_name['FieldDescriptorProto'] = _FIELDDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['OneofDescriptorProto'] = _ONEOFDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['EnumDescriptorProto'] = _ENUMDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['EnumValueDescriptorProto'] = _ENUMVALUEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['ServiceDescriptorProto'] = _SERVICEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['MethodDescriptorProto'] = _METHODDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['FileOptions'] = _FILEOPTIONS +DESCRIPTOR.message_types_by_name['MessageOptions'] = _MESSAGEOPTIONS +DESCRIPTOR.message_types_by_name['FieldOptions'] = _FIELDOPTIONS +DESCRIPTOR.message_types_by_name['OneofOptions'] = _ONEOFOPTIONS +DESCRIPTOR.message_types_by_name['EnumOptions'] = _ENUMOPTIONS +DESCRIPTOR.message_types_by_name['EnumValueOptions'] = _ENUMVALUEOPTIONS +DESCRIPTOR.message_types_by_name['ServiceOptions'] = _SERVICEOPTIONS +DESCRIPTOR.message_types_by_name['MethodOptions'] = _METHODOPTIONS +DESCRIPTOR.message_types_by_name['UninterpretedOption'] = _UNINTERPRETEDOPTION +DESCRIPTOR.message_types_by_name['SourceCodeInfo'] = _SOURCECODEINFO +DESCRIPTOR.message_types_by_name['GeneratedCodeInfo'] = _GENERATEDCODEINFO +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FileDescriptorSet = _reflection.GeneratedProtocolMessageType('FileDescriptorSet', (_message.Message,), dict( + DESCRIPTOR = _FILEDESCRIPTORSET, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + )) +_sym_db.RegisterMessage(FileDescriptorSet) + +FileDescriptorProto = _reflection.GeneratedProtocolMessageType('FileDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _FILEDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + )) +_sym_db.RegisterMessage(FileDescriptorProto) + +DescriptorProto = _reflection.GeneratedProtocolMessageType('DescriptorProto', (_message.Message,), dict( + + ExtensionRange = _reflection.GeneratedProtocolMessageType('ExtensionRange', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPROTO_EXTENSIONRANGE, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + )) + , + + ReservedRange = _reflection.GeneratedProtocolMessageType('ReservedRange', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPROTO_RESERVEDRANGE, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) + )) + , + DESCRIPTOR = _DESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + )) +_sym_db.RegisterMessage(DescriptorProto) +_sym_db.RegisterMessage(DescriptorProto.ExtensionRange) +_sym_db.RegisterMessage(DescriptorProto.ReservedRange) + +ExtensionRangeOptions = _reflection.GeneratedProtocolMessageType('ExtensionRangeOptions', (_message.Message,), dict( + DESCRIPTOR = _EXTENSIONRANGEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions) + )) +_sym_db.RegisterMessage(ExtensionRangeOptions) + +FieldDescriptorProto = _reflection.GeneratedProtocolMessageType('FieldDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _FIELDDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) + )) +_sym_db.RegisterMessage(FieldDescriptorProto) + +OneofDescriptorProto = _reflection.GeneratedProtocolMessageType('OneofDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _ONEOFDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) + )) +_sym_db.RegisterMessage(OneofDescriptorProto) + +EnumDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumDescriptorProto', (_message.Message,), dict( + + EnumReservedRange = _reflection.GeneratedProtocolMessageType('EnumReservedRange', (_message.Message,), dict( + DESCRIPTOR = _ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto.EnumReservedRange) + )) + , + DESCRIPTOR = _ENUMDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + )) +_sym_db.RegisterMessage(EnumDescriptorProto) +_sym_db.RegisterMessage(EnumDescriptorProto.EnumReservedRange) + +EnumValueDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumValueDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _ENUMVALUEDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) + )) +_sym_db.RegisterMessage(EnumValueDescriptorProto) + +ServiceDescriptorProto = _reflection.GeneratedProtocolMessageType('ServiceDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _SERVICEDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) + )) +_sym_db.RegisterMessage(ServiceDescriptorProto) + +MethodDescriptorProto = _reflection.GeneratedProtocolMessageType('MethodDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _METHODDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) + )) +_sym_db.RegisterMessage(MethodDescriptorProto) + +FileOptions = _reflection.GeneratedProtocolMessageType('FileOptions', (_message.Message,), dict( + DESCRIPTOR = _FILEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) + )) +_sym_db.RegisterMessage(FileOptions) + +MessageOptions = _reflection.GeneratedProtocolMessageType('MessageOptions', (_message.Message,), dict( + DESCRIPTOR = _MESSAGEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) + )) +_sym_db.RegisterMessage(MessageOptions) + +FieldOptions = _reflection.GeneratedProtocolMessageType('FieldOptions', (_message.Message,), dict( + DESCRIPTOR = _FIELDOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) + )) +_sym_db.RegisterMessage(FieldOptions) + +OneofOptions = _reflection.GeneratedProtocolMessageType('OneofOptions', (_message.Message,), dict( + DESCRIPTOR = _ONEOFOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.OneofOptions) + )) +_sym_db.RegisterMessage(OneofOptions) + +EnumOptions = _reflection.GeneratedProtocolMessageType('EnumOptions', (_message.Message,), dict( + DESCRIPTOR = _ENUMOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) + )) +_sym_db.RegisterMessage(EnumOptions) + +EnumValueOptions = _reflection.GeneratedProtocolMessageType('EnumValueOptions', (_message.Message,), dict( + DESCRIPTOR = _ENUMVALUEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) + )) +_sym_db.RegisterMessage(EnumValueOptions) + +ServiceOptions = _reflection.GeneratedProtocolMessageType('ServiceOptions', (_message.Message,), dict( + DESCRIPTOR = _SERVICEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) + )) +_sym_db.RegisterMessage(ServiceOptions) + +MethodOptions = _reflection.GeneratedProtocolMessageType('MethodOptions', (_message.Message,), dict( + DESCRIPTOR = _METHODOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) + )) +_sym_db.RegisterMessage(MethodOptions) + +UninterpretedOption = _reflection.GeneratedProtocolMessageType('UninterpretedOption', (_message.Message,), dict( + + NamePart = _reflection.GeneratedProtocolMessageType('NamePart', (_message.Message,), dict( + DESCRIPTOR = _UNINTERPRETEDOPTION_NAMEPART, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) + )) + , + DESCRIPTOR = _UNINTERPRETEDOPTION, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) + )) +_sym_db.RegisterMessage(UninterpretedOption) +_sym_db.RegisterMessage(UninterpretedOption.NamePart) + +SourceCodeInfo = _reflection.GeneratedProtocolMessageType('SourceCodeInfo', (_message.Message,), dict( + + Location = _reflection.GeneratedProtocolMessageType('Location', (_message.Message,), dict( + DESCRIPTOR = _SOURCECODEINFO_LOCATION, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + )) + , + DESCRIPTOR = _SOURCECODEINFO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + )) +_sym_db.RegisterMessage(SourceCodeInfo) +_sym_db.RegisterMessage(SourceCodeInfo.Location) + +GeneratedCodeInfo = _reflection.GeneratedProtocolMessageType('GeneratedCodeInfo', (_message.Message,), dict( + + Annotation = _reflection.GeneratedProtocolMessageType('Annotation', (_message.Message,), dict( + DESCRIPTOR = _GENERATEDCODEINFO_ANNOTATION, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation) + )) + , + DESCRIPTOR = _GENERATEDCODEINFO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo) + )) +_sym_db.RegisterMessage(GeneratedCodeInfo) +_sym_db.RegisterMessage(GeneratedCodeInfo.Annotation) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pool.py b/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pool.py new file mode 100644 index 0000000..7c4331c --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/descriptor_pool.py @@ -0,0 +1,1057 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides DescriptorPool to use as a container for proto2 descriptors. + +The DescriptorPool is used in conjection with a DescriptorDatabase to maintain +a collection of protocol buffer descriptors for use when dynamically creating +message types at runtime. + +For most applications protocol buffers should be used via modules generated by +the protocol buffer compiler tool. This should only be used when the type of +protocol buffers used in an application or library cannot be predetermined. + +Below is a straightforward example on how to use this class: + + pool = DescriptorPool() + file_descriptor_protos = [ ... ] + for file_descriptor_proto in file_descriptor_protos: + pool.Add(file_descriptor_proto) + my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType') + +The message descriptor can be used in conjunction with the message_factory +module in order to create a protocol buffer class that can be encoded and +decoded. + +If you want to get a Python class for the specified proto, use the +helper functions inside google.protobuf.message_factory +directly instead of this class. +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import collections +import warnings + +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import text_encoding + + +_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS # pylint: disable=protected-access + + +def _NormalizeFullyQualifiedName(name): + """Remove leading period from fully-qualified type name. + + Due to b/13860351 in descriptor_database.py, types in the root namespace are + generated with a leading period. This function removes that prefix. + + Args: + name: A str, the fully-qualified symbol name. + + Returns: + A str, the normalized fully-qualified symbol name. + """ + return name.lstrip('.') + + +def _OptionsOrNone(descriptor_proto): + """Returns the value of the field `options`, or None if it is not set.""" + if descriptor_proto.HasField('options'): + return descriptor_proto.options + else: + return None + + +def _IsMessageSetExtension(field): + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL) + + +class DescriptorPool(object): + """A collection of protobufs dynamically constructed by descriptor protos.""" + + if _USE_C_DESCRIPTORS: + + def __new__(cls, descriptor_db=None): + # pylint: disable=protected-access + return descriptor._message.DescriptorPool(descriptor_db) + + def __init__(self, descriptor_db=None): + """Initializes a Pool of proto buffs. + + The descriptor_db argument to the constructor is provided to allow + specialized file descriptor proto lookup code to be triggered on demand. An + example would be an implementation which will read and compile a file + specified in a call to FindFileByName() and not require the call to Add() + at all. Results from this database will be cached internally here as well. + + Args: + descriptor_db: A secondary source of file descriptors. + """ + + self._internal_db = descriptor_database.DescriptorDatabase() + self._descriptor_db = descriptor_db + self._descriptors = {} + self._enum_descriptors = {} + self._service_descriptors = {} + self._file_descriptors = {} + self._toplevel_extensions = {} + # TODO(jieluo): Remove _file_desc_by_toplevel_extension after + # maybe year 2020 for compatibility issue (with 3.4.1 only). + self._file_desc_by_toplevel_extension = {} + # We store extensions in two two-level mappings: The first key is the + # descriptor of the message being extended, the second key is the extension + # full name or its tag number. + self._extensions_by_name = collections.defaultdict(dict) + self._extensions_by_number = collections.defaultdict(dict) + + def _CheckConflictRegister(self, desc): + """Check if the descriptor name conflicts with another of the same name. + + Args: + desc: Descriptor of a message, enum, service or extension. + """ + desc_name = desc.full_name + for register, descriptor_type in [ + (self._descriptors, descriptor.Descriptor), + (self._enum_descriptors, descriptor.EnumDescriptor), + (self._service_descriptors, descriptor.ServiceDescriptor), + (self._toplevel_extensions, descriptor.FieldDescriptor)]: + if desc_name in register: + file_name = register[desc_name].file.name + if not isinstance(desc, descriptor_type) or ( + file_name != desc.file.name): + warn_msg = ('Conflict register for file "' + desc.file.name + + '": ' + desc_name + + ' is already defined in file "' + + file_name + '"') + warnings.warn(warn_msg, RuntimeWarning) + return + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + file_desc_proto: The FileDescriptorProto to add. + """ + + self._internal_db.Add(file_desc_proto) + + def AddSerializedFile(self, serialized_file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + serialized_file_desc_proto: A bytes string, serialization of the + FileDescriptorProto to add. + """ + + # pylint: disable=g-import-not-at-top + from google.protobuf import descriptor_pb2 + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + serialized_file_desc_proto) + self.Add(file_desc_proto) + + def AddDescriptor(self, desc): + """Adds a Descriptor to the pool, non-recursively. + + If the Descriptor contains nested messages or enums, the caller must + explicitly register them. This method also registers the FileDescriptor + associated with the message. + + Args: + desc: A Descriptor. + """ + if not isinstance(desc, descriptor.Descriptor): + raise TypeError('Expected instance of descriptor.Descriptor.') + + self._CheckConflictRegister(desc) + + self._descriptors[desc.full_name] = desc + self._AddFileDescriptor(desc.file) + + def AddEnumDescriptor(self, enum_desc): + """Adds an EnumDescriptor to the pool. + + This method also registers the FileDescriptor associated with the enum. + + Args: + enum_desc: An EnumDescriptor. + """ + + if not isinstance(enum_desc, descriptor.EnumDescriptor): + raise TypeError('Expected instance of descriptor.EnumDescriptor.') + + self._CheckConflictRegister(enum_desc) + self._enum_descriptors[enum_desc.full_name] = enum_desc + self._AddFileDescriptor(enum_desc.file) + + def AddServiceDescriptor(self, service_desc): + """Adds a ServiceDescriptor to the pool. + + Args: + service_desc: A ServiceDescriptor. + """ + + if not isinstance(service_desc, descriptor.ServiceDescriptor): + raise TypeError('Expected instance of descriptor.ServiceDescriptor.') + + self._CheckConflictRegister(service_desc) + self._service_descriptors[service_desc.full_name] = service_desc + + def AddExtensionDescriptor(self, extension): + """Adds a FieldDescriptor describing an extension to the pool. + + Args: + extension: A FieldDescriptor. + + Raises: + AssertionError: when another extension with the same number extends the + same message. + TypeError: when the specified extension is not a + descriptor.FieldDescriptor. + """ + if not (isinstance(extension, descriptor.FieldDescriptor) and + extension.is_extension): + raise TypeError('Expected an extension descriptor.') + + if extension.extension_scope is None: + self._CheckConflictRegister(extension) + self._toplevel_extensions[extension.full_name] = extension + + try: + existing_desc = self._extensions_by_number[ + extension.containing_type][extension.number] + except KeyError: + pass + else: + if extension is not existing_desc: + raise AssertionError( + 'Extensions "%s" and "%s" both try to extend message type "%s" ' + 'with field number %d.' % + (extension.full_name, existing_desc.full_name, + extension.containing_type.full_name, extension.number)) + + self._extensions_by_number[extension.containing_type][ + extension.number] = extension + self._extensions_by_name[extension.containing_type][ + extension.full_name] = extension + + # Also register MessageSet extensions with the type name. + if _IsMessageSetExtension(extension): + self._extensions_by_name[extension.containing_type][ + extension.message_type.full_name] = extension + + def AddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + self._AddFileDescriptor(file_desc) + # TODO(jieluo): This is a temporary solution for FieldDescriptor.file. + # FieldDescriptor.file is added in code gen. Remove this solution after + # maybe 2020 for compatibility reason (with 3.4.1 only). + for extension in list(file_desc.extensions_by_name.values()): + self._file_desc_by_toplevel_extension[ + extension.full_name] = file_desc + + def _AddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + if not isinstance(file_desc, descriptor.FileDescriptor): + raise TypeError('Expected instance of descriptor.FileDescriptor.') + self._file_descriptors[file_desc.name] = file_desc + + def FindFileByName(self, file_name): + """Gets a FileDescriptor by file name. + + Args: + file_name: The path to the file to get a descriptor for. + + Returns: + A FileDescriptor for the named file. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + + try: + return self._file_descriptors[file_name] + except KeyError: + pass + + try: + file_proto = self._internal_db.FindFileByName(file_name) + except KeyError as error: + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileByName(file_name) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file named %s' % file_name) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def FindFileContainingSymbol(self, symbol): + """Gets the FileDescriptor for the file containing the specified symbol. + + Args: + symbol: The name of the symbol to search for. + + Returns: + A FileDescriptor that contains the specified symbol. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + + symbol = _NormalizeFullyQualifiedName(symbol) + try: + return self._descriptors[symbol].file + except KeyError: + pass + + try: + return self._enum_descriptors[symbol].file + except KeyError: + pass + + try: + return self._service_descriptors[symbol].file + except KeyError: + pass + + try: + return self._FindFileContainingSymbolInDb(symbol) + except KeyError: + pass + + try: + return self._file_desc_by_toplevel_extension[symbol] + except KeyError: + pass + + # Try nested extensions inside a message. + message_name, _, extension_name = symbol.rpartition('.') + try: + message = self.FindMessageTypeByName(message_name) + assert message.extensions_by_name[extension_name] + return message.file + except KeyError: + raise KeyError('Cannot find a file containing %s' % symbol) + + def FindMessageTypeByName(self, full_name): + """Loads the named descriptor from the pool. + + Args: + full_name: The full name of the descriptor to load. + + Returns: + The descriptor for the named type. + + Raises: + KeyError: if the message cannot be found in the pool. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._descriptors[full_name] + + def FindEnumTypeByName(self, full_name): + """Loads the named enum descriptor from the pool. + + Args: + full_name: The full name of the enum descriptor to load. + + Returns: + The enum descriptor for the named type. + + Raises: + KeyError: if the enum cannot be found in the pool. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._enum_descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._enum_descriptors[full_name] + + def FindFieldByName(self, full_name): + """Loads the named field descriptor from the pool. + + Args: + full_name: The full name of the field descriptor to load. + + Returns: + The field descriptor for the named field. + + Raises: + KeyError: if the field cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, field_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.fields_by_name[field_name] + + def FindOneofByName(self, full_name): + """Loads the named oneof descriptor from the pool. + + Args: + full_name: The full name of the oneof descriptor to load. + + Returns: + The oneof descriptor for the named oneof. + + Raises: + KeyError: if the oneof cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, oneof_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.oneofs_by_name[oneof_name] + + def FindExtensionByName(self, full_name): + """Loads the named extension descriptor from the pool. + + Args: + full_name: The full name of the extension descriptor to load. + + Returns: + A FieldDescriptor, describing the named extension. + + Raises: + KeyError: if the extension cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + try: + # The proto compiler does not give any link between the FileDescriptor + # and top-level extensions unless the FileDescriptorProto is added to + # the DescriptorDatabase, but this can impact memory usage. + # So we registered these extensions by name explicitly. + return self._toplevel_extensions[full_name] + except KeyError: + pass + message_name, _, extension_name = full_name.rpartition('.') + try: + # Most extensions are nested inside a message. + scope = self.FindMessageTypeByName(message_name) + except KeyError: + # Some extensions are defined at file scope. + scope = self._FindFileContainingSymbolInDb(full_name) + return scope.extensions_by_name[extension_name] + + def FindExtensionByNumber(self, message_descriptor, number): + """Gets the extension of the specified message with the specified number. + + Extensions have to be registered to this pool by calling + AddExtensionDescriptor. + + Args: + message_descriptor: descriptor of the extended message. + number: integer, number of the extension field. + + Returns: + A FieldDescriptor describing the extension. + + Raises: + KeyError: when no extension with the given number is known for the + specified message. + """ + return self._extensions_by_number[message_descriptor][number] + + def FindAllExtensions(self, message_descriptor): + """Gets all the known extension of a given message. + + Extensions have to be registered to this pool by calling + AddExtensionDescriptor. + + Args: + message_descriptor: descriptor of the extended message. + + Returns: + A list of FieldDescriptor describing the extensions. + """ + return list(self._extensions_by_number[message_descriptor].values()) + + def FindServiceByName(self, full_name): + """Loads the named service descriptor from the pool. + + Args: + full_name: The full name of the service descriptor to load. + + Returns: + The service descriptor for the named service. + + Raises: + KeyError: if the service cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._service_descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._service_descriptors[full_name] + + def _FindFileContainingSymbolInDb(self, symbol): + """Finds the file in descriptor DB containing the specified symbol. + + Args: + symbol: The name of the symbol to search for. + + Returns: + A FileDescriptor that contains the specified symbol. + + Raises: + KeyError: if the file cannot be found in the descriptor database. + """ + try: + file_proto = self._internal_db.FindFileContainingSymbol(symbol) + except KeyError as error: + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileContainingSymbol(symbol) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file containing %s' % symbol) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def _ConvertFileProtoToFileDescriptor(self, file_proto): + """Creates a FileDescriptor from a proto or returns a cached copy. + + This method also has the side effect of loading all the symbols found in + the file into the appropriate dictionaries in the pool. + + Args: + file_proto: The proto to convert. + + Returns: + A FileDescriptor matching the passed in proto. + """ + + if file_proto.name not in self._file_descriptors: + built_deps = list(self._GetDeps(file_proto.dependency)) + direct_deps = [self.FindFileByName(n) for n in file_proto.dependency] + public_deps = [direct_deps[i] for i in file_proto.public_dependency] + + file_descriptor = descriptor.FileDescriptor( + pool=self, + name=file_proto.name, + package=file_proto.package, + syntax=file_proto.syntax, + options=_OptionsOrNone(file_proto), + serialized_pb=file_proto.SerializeToString(), + dependencies=direct_deps, + public_dependencies=public_deps) + scope = {} + + # This loop extracts all the message and enum types from all the + # dependencies of the file_proto. This is necessary to create the + # scope of available message types when defining the passed in + # file proto. + for dependency in built_deps: + scope.update(self._ExtractSymbols( + list(dependency.message_types_by_name.values()))) + scope.update((_PrefixWithDot(enum.full_name), enum) + for enum in list(dependency.enum_types_by_name.values())) + + for message_type in file_proto.message_type: + message_desc = self._ConvertMessageDescriptor( + message_type, file_proto.package, file_descriptor, scope, + file_proto.syntax) + file_descriptor.message_types_by_name[message_desc.name] = ( + message_desc) + + for enum_type in file_proto.enum_type: + file_descriptor.enum_types_by_name[enum_type.name] = ( + self._ConvertEnumDescriptor(enum_type, file_proto.package, + file_descriptor, None, scope)) + + for index, extension_proto in enumerate(file_proto.extension): + extension_desc = self._MakeFieldDescriptor( + extension_proto, file_proto.package, index, file_descriptor, + is_extension=True) + extension_desc.containing_type = self._GetTypeFromScope( + file_descriptor.package, extension_proto.extendee, scope) + self._SetFieldType(extension_proto, extension_desc, + file_descriptor.package, scope) + file_descriptor.extensions_by_name[extension_desc.name] = ( + extension_desc) + + for desc_proto in file_proto.message_type: + self._SetAllFieldTypes(file_proto.package, desc_proto, scope) + + if file_proto.package: + desc_proto_prefix = _PrefixWithDot(file_proto.package) + else: + desc_proto_prefix = '' + + for desc_proto in file_proto.message_type: + desc = self._GetTypeFromScope( + desc_proto_prefix, desc_proto.name, scope) + file_descriptor.message_types_by_name[desc_proto.name] = desc + + for index, service_proto in enumerate(file_proto.service): + file_descriptor.services_by_name[service_proto.name] = ( + self._MakeServiceDescriptor(service_proto, index, scope, + file_proto.package, file_descriptor)) + + self.Add(file_proto) + self._file_descriptors[file_proto.name] = file_descriptor + + return self._file_descriptors[file_proto.name] + + def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, + scope=None, syntax=None): + """Adds the proto to the pool in the specified package. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: The package the proto should be located in. + file_desc: The file containing this message. + scope: Dict mapping short and full symbols to message and enum types. + syntax: string indicating syntax of the file ("proto2" or "proto3") + + Returns: + The added descriptor. + """ + + if package: + desc_name = '.'.join((package, desc_proto.name)) + else: + desc_name = desc_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + if scope is None: + scope = {} + + nested = [ + self._ConvertMessageDescriptor( + nested, desc_name, file_desc, scope, syntax) + for nested in desc_proto.nested_type] + enums = [ + self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) + for enum in desc_proto.enum_type] + fields = [self._MakeFieldDescriptor(field, desc_name, index, file_desc) + for index, field in enumerate(desc_proto.field)] + extensions = [ + self._MakeFieldDescriptor(extension, desc_name, index, file_desc, + is_extension=True) + for index, extension in enumerate(desc_proto.extension)] + oneofs = [ + descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), + index, None, [], desc.options) + for index, desc in enumerate(desc_proto.oneof_decl)] + extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range] + if extension_ranges: + is_extendable = True + else: + is_extendable = False + desc = descriptor.Descriptor( + name=desc_proto.name, + full_name=desc_name, + filename=file_name, + containing_type=None, + fields=fields, + oneofs=oneofs, + nested_types=nested, + enum_types=enums, + extensions=extensions, + options=_OptionsOrNone(desc_proto), + is_extendable=is_extendable, + extension_ranges=extension_ranges, + file=file_desc, + serialized_start=None, + serialized_end=None, + syntax=syntax) + for nested in desc.nested_types: + nested.containing_type = desc + for enum in desc.enum_types: + enum.containing_type = desc + for field_index, field_desc in enumerate(desc_proto.field): + if field_desc.HasField('oneof_index'): + oneof_index = field_desc.oneof_index + oneofs[oneof_index].fields.append(fields[field_index]) + fields[field_index].containing_oneof = oneofs[oneof_index] + + scope[_PrefixWithDot(desc_name)] = desc + self._CheckConflictRegister(desc) + self._descriptors[desc_name] = desc + return desc + + def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, + containing_type=None, scope=None): + """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf. + + Args: + enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the enum descriptor. + containing_type: The type containing this enum. + scope: Scope containing available types. + + Returns: + The added descriptor + """ + + if package: + enum_name = '.'.join((package, enum_proto.name)) + else: + enum_name = enum_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + values = [self._MakeEnumValueDescriptor(value, index) + for index, value in enumerate(enum_proto.value)] + desc = descriptor.EnumDescriptor(name=enum_proto.name, + full_name=enum_name, + filename=file_name, + file=file_desc, + values=values, + containing_type=containing_type, + options=_OptionsOrNone(enum_proto)) + scope['.%s' % enum_name] = desc + self._CheckConflictRegister(desc) + self._enum_descriptors[enum_name] = desc + return desc + + def _MakeFieldDescriptor(self, field_proto, message_name, index, + file_desc, is_extension=False): + """Creates a field descriptor from a FieldDescriptorProto. + + For message and enum type fields, this method will do a look up + in the pool for the appropriate descriptor for that type. If it + is unavailable, it will fall back to the _source function to + create it. If this type is still unavailable, construction will + fail. + + Args: + field_proto: The proto describing the field. + message_name: The name of the containing message. + index: Index of the field + file_desc: The file containing the field descriptor. + is_extension: Indication that this field is for an extension. + + Returns: + An initialized FieldDescriptor object + """ + + if message_name: + full_name = '.'.join((message_name, field_proto.name)) + else: + full_name = field_proto.name + + return descriptor.FieldDescriptor( + name=field_proto.name, + full_name=full_name, + index=index, + number=field_proto.number, + type=field_proto.type, + cpp_type=None, + message_type=None, + enum_type=None, + containing_type=None, + label=field_proto.label, + has_default_value=False, + default_value=None, + is_extension=is_extension, + extension_scope=None, + options=_OptionsOrNone(field_proto), + file=file_desc) + + def _SetAllFieldTypes(self, package, desc_proto, scope): + """Sets all the descriptor's fields's types. + + This method also sets the containing types on any extensions. + + Args: + package: The current package of desc_proto. + desc_proto: The message descriptor to update. + scope: Enclosing scope of available types. + """ + + package = _PrefixWithDot(package) + + main_desc = self._GetTypeFromScope(package, desc_proto.name, scope) + + if package == '.': + nested_package = _PrefixWithDot(desc_proto.name) + else: + nested_package = '.'.join([package, desc_proto.name]) + + for field_proto, field_desc in zip(desc_proto.field, main_desc.fields): + self._SetFieldType(field_proto, field_desc, nested_package, scope) + + for extension_proto, extension_desc in ( + list(zip(desc_proto.extension, main_desc.extensions))): + extension_desc.containing_type = self._GetTypeFromScope( + nested_package, extension_proto.extendee, scope) + self._SetFieldType(extension_proto, extension_desc, nested_package, scope) + + for nested_type in desc_proto.nested_type: + self._SetAllFieldTypes(nested_package, nested_type, scope) + + def _SetFieldType(self, field_proto, field_desc, package, scope): + """Sets the field's type, cpp_type, message_type and enum_type. + + Args: + field_proto: Data about the field in proto format. + field_desc: The descriptor to modiy. + package: The package the field's container is in. + scope: Enclosing scope of available types. + """ + if field_proto.type_name: + desc = self._GetTypeFromScope(package, field_proto.type_name, scope) + else: + desc = None + + if not field_proto.HasField('type'): + if isinstance(desc, descriptor.Descriptor): + field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE + else: + field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM + + field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType( + field_proto.type) + + if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE + or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP): + field_desc.message_type = desc + + if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.enum_type = desc + + if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED: + field_desc.has_default_value = False + field_desc.default_value = [] + elif field_proto.HasField('default_value'): + field_desc.has_default_value = True + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = float(field_proto.default_value) + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = field_proto.default_value + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = field_proto.default_value.lower() == 'true' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values_by_name[ + field_proto.default_value].number + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = text_encoding.CUnescape( + field_proto.default_value) + else: + # All other types are of the "int" type. + field_desc.default_value = int(field_proto.default_value) + else: + field_desc.has_default_value = False + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = 0.0 + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = '' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = False + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values[0].number + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = b'' + else: + # All other types are of the "int" type. + field_desc.default_value = 0 + + field_desc.type = field_proto.type + + def _MakeEnumValueDescriptor(self, value_proto, index): + """Creates a enum value descriptor object from a enum value proto. + + Args: + value_proto: The proto describing the enum value. + index: The index of the enum value. + + Returns: + An initialized EnumValueDescriptor object. + """ + + return descriptor.EnumValueDescriptor( + name=value_proto.name, + index=index, + number=value_proto.number, + options=_OptionsOrNone(value_proto), + type=None) + + def _MakeServiceDescriptor(self, service_proto, service_index, scope, + package, file_desc): + """Make a protobuf ServiceDescriptor given a ServiceDescriptorProto. + + Args: + service_proto: The descriptor_pb2.ServiceDescriptorProto protobuf message. + service_index: The index of the service in the File. + scope: Dict mapping short and full symbols to message and enum types. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the service descriptor. + + Returns: + The added descriptor. + """ + + if package: + service_name = '.'.join((package, service_proto.name)) + else: + service_name = service_proto.name + + methods = [self._MakeMethodDescriptor(method_proto, service_name, package, + scope, index) + for index, method_proto in enumerate(service_proto.method)] + desc = descriptor.ServiceDescriptor(name=service_proto.name, + full_name=service_name, + index=service_index, + methods=methods, + options=_OptionsOrNone(service_proto), + file=file_desc) + self._CheckConflictRegister(desc) + self._service_descriptors[service_name] = desc + return desc + + def _MakeMethodDescriptor(self, method_proto, service_name, package, scope, + index): + """Creates a method descriptor from a MethodDescriptorProto. + + Args: + method_proto: The proto describing the method. + service_name: The name of the containing service. + package: Optional package name to look up for types. + scope: Scope containing available types. + index: Index of the method in the service. + + Returns: + An initialized MethodDescriptor object. + """ + full_name = '.'.join((service_name, method_proto.name)) + input_type = self._GetTypeFromScope( + package, method_proto.input_type, scope) + output_type = self._GetTypeFromScope( + package, method_proto.output_type, scope) + return descriptor.MethodDescriptor(name=method_proto.name, + full_name=full_name, + index=index, + containing_service=None, + input_type=input_type, + output_type=output_type, + options=_OptionsOrNone(method_proto)) + + def _ExtractSymbols(self, descriptors): + """Pulls out all the symbols from descriptor protos. + + Args: + descriptors: The messages to extract descriptors from. + Yields: + A two element tuple of the type name and descriptor object. + """ + + for desc in descriptors: + yield (_PrefixWithDot(desc.full_name), desc) + for symbol in self._ExtractSymbols(desc.nested_types): + yield symbol + for enum in desc.enum_types: + yield (_PrefixWithDot(enum.full_name), enum) + + def _GetDeps(self, dependencies): + """Recursively finds dependencies for file protos. + + Args: + dependencies: The names of the files being depended on. + + Yields: + Each direct and indirect dependency. + """ + + for dependency in dependencies: + dep_desc = self.FindFileByName(dependency) + yield dep_desc + for parent_dep in dep_desc.dependencies: + yield parent_dep + + def _GetTypeFromScope(self, package, type_name, scope): + """Finds a given type name in the current scope. + + Args: + package: The package the proto should be located in. + type_name: The name of the type to be found in the scope. + scope: Dict mapping short and full symbols to message and enum types. + + Returns: + The descriptor for the requested type. + """ + if type_name not in scope: + components = _PrefixWithDot(package).split('.') + while components: + possible_match = '.'.join(components + [type_name]) + if possible_match in scope: + type_name = possible_match + break + else: + components.pop(-1) + return scope[type_name] + + +def _PrefixWithDot(name): + return name if name.startswith('.') else '.%s' % name + + +if _USE_C_DESCRIPTORS: + # TODO(amauryfa): This pool could be constructed from Python code, when we + # support a flag like 'use_cpp_generated_pool=True'. + # pylint: disable=protected-access + _DEFAULT = descriptor._message.default_pool +else: + _DEFAULT = DescriptorPool() + + +def Default(): + return _DEFAULT diff --git a/venv/lib/python3.7/site-packages/google/protobuf/duration_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/duration_pb2.py new file mode 100644 index 0000000..2428889 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/duration_pb2.py @@ -0,0 +1,77 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/duration.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/duration.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\rDurationProtoP\001Z*github.com/golang/protobuf/ptypes/duration\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1egoogle/protobuf/duration.proto\x12\x0fgoogle.protobuf\"*\n\x08\x44uration\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x42|\n\x13\x63om.google.protobufB\rDurationProtoP\x01Z*github.com/golang/protobuf/ptypes/duration\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_DURATION = _descriptor.Descriptor( + name='Duration', + full_name='google.protobuf.Duration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='seconds', full_name='google.protobuf.Duration.seconds', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nanos', full_name='google.protobuf.Duration.nanos', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=93, +) + +DESCRIPTOR.message_types_by_name['Duration'] = _DURATION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Duration = _reflection.GeneratedProtocolMessageType('Duration', (_message.Message,), dict( + DESCRIPTOR = _DURATION, + __module__ = 'google.protobuf.duration_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Duration) + )) +_sym_db.RegisterMessage(Duration) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/empty_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/empty_pb2.py new file mode 100644 index 0000000..46682b2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/empty_pb2.py @@ -0,0 +1,63 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/empty.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/empty.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\nEmptyProtoP\001Z\'github.com/golang/protobuf/ptypes/empty\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1bgoogle/protobuf/empty.proto\x12\x0fgoogle.protobuf\"\x07\n\x05\x45mptyBv\n\x13\x63om.google.protobufB\nEmptyProtoP\x01Z\'github.com/golang/protobuf/ptypes/empty\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_EMPTY = _descriptor.Descriptor( + name='Empty', + full_name='google.protobuf.Empty', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=48, + serialized_end=55, +) + +DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), dict( + DESCRIPTOR = _EMPTY, + __module__ = 'google.protobuf.empty_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Empty) + )) +_sym_db.RegisterMessage(Empty) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/field_mask_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/field_mask_pb2.py new file mode 100644 index 0000000..5373887 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/field_mask_pb2.py @@ -0,0 +1,70 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/field_mask.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/field_mask.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\016FieldMaskProtoP\001Z9google.golang.org/genproto/protobuf/field_mask;field_mask\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n google/protobuf/field_mask.proto\x12\x0fgoogle.protobuf\"\x1a\n\tFieldMask\x12\r\n\x05paths\x18\x01 \x03(\tB\x89\x01\n\x13\x63om.google.protobufB\x0e\x46ieldMaskProtoP\x01Z9google.golang.org/genproto/protobuf/field_mask;field_mask\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_FIELDMASK = _descriptor.Descriptor( + name='FieldMask', + full_name='google.protobuf.FieldMask', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='paths', full_name='google.protobuf.FieldMask.paths', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=53, + serialized_end=79, +) + +DESCRIPTOR.message_types_by_name['FieldMask'] = _FIELDMASK +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FieldMask = _reflection.GeneratedProtocolMessageType('FieldMask', (_message.Message,), dict( + DESCRIPTOR = _FIELDMASK, + __module__ = 'google.protobuf.field_mask_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldMask) + )) +_sym_db.RegisterMessage(FieldMask) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/__init__.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/_api_implementation.cpython-37m-darwin.so b/venv/lib/python3.7/site-packages/google/protobuf/internal/_api_implementation.cpython-37m-darwin.so new file mode 100644 index 0000000000000000000000000000000000000000..44f6d8681f61458dc5be87261c28abd73055ac3f GIT binary patch literal 25576 zcmeHOU5p!76~4RKq>i&ByJ;l?E$wWZgrw=(*=3PvQFdh*FnOV*jsx zkDJyDN6#*Ri4xreB$OP#8P^u_Agw+7f)~^SzI*&jm}C(hEHPDwM$|>aXzeana!y&h zUL%LbUK_S-51bJ!X{Vvs=0FE+fesATMY~+H>ptIY$9))Up`9fiAZ-eDkk>lzRNc;E zdhK`uW6!|=mbWA5aJ_n|x)ciZ>iGVSzz&vCirS=gqxwRrTF|BHq648`9j{<)3hgYT znff@@HlE-z3+IwJJb=Ko6o@TT9>nfbi^>0 zI#`-9R7qRRJECt)#*Q13d%F!l*_v5e|4@+^tL3@)vYrH_B*=zQ9|*A^NvPNBSp zg>zoY8hTi%iwDVAcwbQ5hjJH6LyuX3-U7NCwB|Mp+^{`~ybYqWvOQCs8qp~TgrhG!dy zjy$f1V|}bPKMpg7RI=gLljTy5SN_0(#8jfNjH)kBY>oWz7yp3A(k*{#+4by7;;C?m z+6#HwaM=o;;r@^(CPIRMARq_`0)l`bAP5Ko{SkP!`R7w-POsb?U1R_Gm7B5El^j0U ziXY-@F|(FNTu^?TTIXvR=ulS|!)YS{0|zDBG4-%zBo6q2{=@Yvr9vtyH!ry;8*ngS}L?>bbs5 zykL8Fy;7=jh;0?@#cZSOS+kk6)uY{WtcGh_i%#9jEPF-FSF1aoGo6UX)1E&?U<-^` zXIi4RY~_|M*Y-SY!OSc!6q1da7w?z{TVPhfDpjqy$1JyzF9xe}U~4{GrM8YHtTs^N zLlNI+CzcY{3ni~;<;vM_!|ZZ)$(o$ZJ2mgg$@$Dz7g8sV>&(d$3n!-aTqdK_PiKzl z)6@GCst>Y?EBcmQcY!jV1NRCK@PUA$CBNahpXN6@uY1D%DC^u;jAG=NKUyhUZK9ek z;vV=xT zVfSdXd#-M0J$oAMa4KL_x?1vdKmW!ci%Hg)^n68XGJo_5NO zitQ$!YLv=_c^tyu!DKm(N#bC*mZ)U&j(cHp>R{r~Bsf?X4fo&-j1RXK?MqjZV6e5qkd7EOPzAa(PM!5q1h90uJ zjRtJ!{f)li*V#8XZ{Q#u0wCrNkjQtfH)w9(H_9RS9-Rvy%fBmS_>k?k6^$F^6Z|C9 zmkJe-?^>@>9F}}fX0VptnEdwpVcwIT@}uM$a7v?w6~4QM_&lR_Zj^VxTmh2NM?R`A zntwpKjdBpIP>~-)1$pvOebf;p;zo@7<|9zh7-o@CYAsYYC_jO}T?XqvV#1C zvncn0Cq|6rzYL!F39n4tU4Ft3Fy8!@psr0OKjA?0kDGq=_SDWFUbxZv)AYnY`8)EL z_CL%|n1Rka$xon>dqX=eTEYLn{UJ|WgaiRWKoAfF1OY)n5coI{cs7LufJ|!jNf%#i zuQBLGT-=7cu`_GvoeA(b#|T(fEJz(HsEs z^h=mL0P@jX0P@j%0P>XQnWKp>AkVx2!<*ayiH@+L>> class Foo(object): + ... pass + >>> repr(Foo()) + '<__main__.Foo object at 0x23d8610>' + +are turned into '<__main__.Foo>'. For even more descriptive names, +especially in test logs, you can use the named_parameters decorator. In +this case, only tuples are supported, and the first parameters has to +be a string (or an object that returns an apt name when converted via +str()): + + class NamedExample(parameterized.TestCase): + @parameterized.named_parameters( + ('Normal', 'aa', 'aaa', True), + ('EmptyPrefix', '', 'abc', True), + ('BothEmpty', '', '', True)) + def testStartsWith(self, prefix, string, result): + self.assertEqual(result, strings.startswith(prefix)) + +Named tests also have the benefit that they can be run individually +from the command line: + + $ testmodule.py NamedExample.testStartsWithNormal + . + -------------------------------------------------------------------- + Ran 1 test in 0.000s + + OK + +Parameterized Classes +===================== +If invocation arguments are shared across test methods in a single +TestCase class, instead of decorating all test methods +individually, the class itself can be decorated: + + @parameterized.parameters( + (1, 2, 3) + (4, 5, 9)) + class ArithmeticTest(parameterized.TestCase): + def testAdd(self, arg1, arg2, result): + self.assertEqual(arg1 + arg2, result) + + def testSubtract(self, arg2, arg2, result): + self.assertEqual(result - arg1, arg2) + +Inputs from Iterables +===================== +If parameters should be shared across several test cases, or are dynamically +created from other sources, a single non-tuple iterable can be passed into +the decorator. This iterable will be used to obtain the test cases: + + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( + c.op1, c.op2, c.result for c in testcases + ) + def testAddition(self, op1, op2, result): + self.assertEqual(result, op1 + op2) + + +Single-Argument Test Methods +============================ +If a test method takes only one argument, the single argument does not need to +be wrapped into a tuple: + + class NegativeNumberExample(parameterized.TestCase): + @parameterized.parameters( + -1, -3, -4, -5 + ) + def testIsNegative(self, arg): + self.assertTrue(IsNegative(arg)) +""" + +__author__ = 'tmarek@google.com (Torsten Marek)' + +import collections +import functools +import re +import types +try: + import unittest2 as unittest +except ImportError: + import unittest +import uuid + +import six + +ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>') +_SEPARATOR = uuid.uuid1().hex +_FIRST_ARG = object() +_ARGUMENT_REPR = object() + + +def _CleanRepr(obj): + return ADDR_RE.sub(r'<\1>', repr(obj)) + + +# Helper function formerly from the unittest module, removed from it in +# Python 2.7. +def _StrClass(cls): + return '%s.%s' % (cls.__module__, cls.__name__) + + +def _NonStringIterable(obj): + return (isinstance(obj, collections.Iterable) and not + isinstance(obj, six.string_types)) + + +def _FormatParameterList(testcase_params): + if isinstance(testcase_params, collections.Mapping): + return ', '.join('%s=%s' % (argname, _CleanRepr(value)) + for argname, value in list(testcase_params.items())) + elif _NonStringIterable(testcase_params): + return ', '.join(map(_CleanRepr, testcase_params)) + else: + return _FormatParameterList((testcase_params,)) + + +class _ParameterizedTestIter(object): + """Callable and iterable class for producing new test cases.""" + + def __init__(self, test_method, testcases, naming_type): + """Returns concrete test functions for a test and a list of parameters. + + The naming_type is used to determine the name of the concrete + functions as reported by the unittest framework. If naming_type is + _FIRST_ARG, the testcases must be tuples, and the first element must + have a string representation that is a valid Python identifier. + + Args: + test_method: The decorated test method. + testcases: (list of tuple/dict) A list of parameter + tuples/dicts for individual test invocations. + naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR. + """ + self._test_method = test_method + self.testcases = testcases + self._naming_type = naming_type + + def __call__(self, *args, **kwargs): + raise RuntimeError('You appear to be running a parameterized test case ' + 'without having inherited from parameterized.' + 'TestCase. This is bad because none of ' + 'your test cases are actually being run.') + + def __iter__(self): + test_method = self._test_method + naming_type = self._naming_type + + def MakeBoundParamTest(testcase_params): + @functools.wraps(test_method) + def BoundParamTest(self): + if isinstance(testcase_params, collections.Mapping): + test_method(self, **testcase_params) + elif _NonStringIterable(testcase_params): + test_method(self, *testcase_params) + else: + test_method(self, testcase_params) + + if naming_type is _FIRST_ARG: + # Signal the metaclass that the name of the test function is unique + # and descriptive. + BoundParamTest.__x_use_name__ = True + BoundParamTest.__name__ += str(testcase_params[0]) + testcase_params = testcase_params[1:] + elif naming_type is _ARGUMENT_REPR: + # __x_extra_id__ is used to pass naming information to the __new__ + # method of TestGeneratorMetaclass. + # The metaclass will make sure to create a unique, but nondescriptive + # name for this test. + BoundParamTest.__x_extra_id__ = '(%s)' % ( + _FormatParameterList(testcase_params),) + else: + raise RuntimeError('%s is not a valid naming type.' % (naming_type,)) + + BoundParamTest.__doc__ = '%s(%s)' % ( + BoundParamTest.__name__, _FormatParameterList(testcase_params)) + if test_method.__doc__: + BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,) + return BoundParamTest + return (MakeBoundParamTest(c) for c in self.testcases) + + +def _IsSingletonList(testcases): + """True iff testcases contains only a single non-tuple element.""" + return len(testcases) == 1 and not isinstance(testcases[0], tuple) + + +def _ModifyClass(class_object, testcases, naming_type): + assert not getattr(class_object, '_id_suffix', None), ( + 'Cannot add parameters to %s,' + ' which already has parameterized methods.' % (class_object,)) + class_object._id_suffix = id_suffix = {} + # We change the size of __dict__ while we iterate over it, + # which Python 3.x will complain about, so use copy(). + for name, obj in list(class_object.__dict__.copy().items()): + if (name.startswith(unittest.TestLoader.testMethodPrefix) + and isinstance(obj, types.FunctionType)): + delattr(class_object, name) + methods = {} + _UpdateClassDictForParamTestCase( + methods, id_suffix, name, + _ParameterizedTestIter(obj, testcases, naming_type)) + for name, meth in list(methods.items()): + setattr(class_object, name, meth) + + +def _ParameterDecorator(naming_type, testcases): + """Implementation of the parameterization decorators. + + Args: + naming_type: The naming type. + testcases: Testcase parameters. + + Returns: + A function for modifying the decorated object. + """ + def _Apply(obj): + if isinstance(obj, type): + _ModifyClass( + obj, + list(testcases) if not isinstance(testcases, collections.Sequence) + else testcases, + naming_type) + return obj + else: + return _ParameterizedTestIter(obj, testcases, naming_type) + + if _IsSingletonList(testcases): + assert _NonStringIterable(testcases[0]), ( + 'Single parameter argument must be a non-string iterable') + testcases = testcases[0] + + return _Apply + + +def parameters(*testcases): # pylint: disable=invalid-name + """A decorator for creating parameterized tests. + + See the module docstring for a usage example. + Args: + *testcases: Parameters for the decorated method, either a single + iterable, or a list of tuples/dicts/objects (for tests + with only one argument). + + Returns: + A test generator to be handled by TestGeneratorMetaclass. + """ + return _ParameterDecorator(_ARGUMENT_REPR, testcases) + + +def named_parameters(*testcases): # pylint: disable=invalid-name + """A decorator for creating parameterized tests. + + See the module docstring for a usage example. The first element of + each parameter tuple should be a string and will be appended to the + name of the test method. + + Args: + *testcases: Parameters for the decorated method, either a single + iterable, or a list of tuples. + + Returns: + A test generator to be handled by TestGeneratorMetaclass. + """ + return _ParameterDecorator(_FIRST_ARG, testcases) + + +class TestGeneratorMetaclass(type): + """Metaclass for test cases with test generators. + + A test generator is an iterable in a testcase that produces callables. These + callables must be single-argument methods. These methods are injected into + the class namespace and the original iterable is removed. If the name of the + iterable conforms to the test pattern, the injected methods will be picked + up as tests by the unittest framework. + + In general, it is supposed to be used in conjunction with the + parameters decorator. + """ + + def __new__(mcs, class_name, bases, dct): + dct['_id_suffix'] = id_suffix = {} + for name, obj in list(dct.items()): + if (name.startswith(unittest.TestLoader.testMethodPrefix) and + _NonStringIterable(obj)): + iterator = iter(obj) + dct.pop(name) + _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator) + + return type.__new__(mcs, class_name, bases, dct) + + +def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator): + """Adds individual test cases to a dictionary. + + Args: + dct: The target dictionary. + id_suffix: The dictionary for mapping names to test IDs. + name: The original name of the test case. + iterator: The iterator generating the individual test cases. + """ + for idx, func in enumerate(iterator): + assert callable(func), 'Test generators must yield callables, got %r' % ( + func,) + if getattr(func, '__x_use_name__', False): + new_name = func.__name__ + else: + new_name = '%s%s%d' % (name, _SEPARATOR, idx) + assert new_name not in dct, ( + 'Name of parameterized test case "%s" not unique' % (new_name,)) + dct[new_name] = func + id_suffix[new_name] = getattr(func, '__x_extra_id__', '') + + +class TestCase(unittest.TestCase, metaclass=TestGeneratorMetaclass): + """Base class for test cases using the parameters decorator.""" + + def _OriginalName(self): + return self._testMethodName.split(_SEPARATOR)[0] + + def __str__(self): + return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__)) + + def id(self): # pylint: disable=invalid-name + """Returns the descriptive ID of the test. + + This is used internally by the unittesting framework to get a name + for the test to be used in reports. + + Returns: + The test id. + """ + return '%s.%s%s' % (_StrClass(self.__class__), + self._OriginalName(), + self._id_suffix.get(self._testMethodName, '')) + + +def CoopTestCase(other_base_class): + """Returns a new base class with a cooperative metaclass base. + + This enables the TestCase to be used in combination + with other base classes that have custom metaclasses, such as + mox.MoxTestBase. + + Only works with metaclasses that do not override type.__new__. + + Example: + + import google3 + import mox + + from google3.testing.pybase import parameterized + + class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)): + ... + + Args: + other_base_class: (class) A test case base class. + + Returns: + A new class object. + """ + metaclass = type( + 'CoopMetaclass', + (other_base_class.__metaclass__, + TestGeneratorMetaclass), {}) + return metaclass( + 'CoopTestCase', + (other_base_class, TestCase), {}) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/any_test_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/any_test_pb2.py new file mode 100644 index 0000000..f59c0b2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/any_test_pb2.py @@ -0,0 +1,182 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/any_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/any_test.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n\'google/protobuf/internal/any_test.proto\x12\x18google.protobuf.internal\x1a\x19google/protobuf/any.proto\"\xc0\x01\n\x07TestAny\x12#\n\x05value\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x11\n\tint_value\x18\x02 \x01(\x05\x12\x42\n\tmap_value\x18\x03 \x03(\x0b\x32/.google.protobuf.internal.TestAny.MapValueEntry\x1a/\n\rMapValueEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01*\x08\x08\n\x10\x80\x80\x80\x80\x02\"\x85\x01\n\x11TestAnyExtension1\x12\t\n\x01i\x18\x0f \x01(\x05\x32\x65\n\nextension1\x12!.google.protobuf.internal.TestAny\x18\xab\xff\xf6. \x01(\x0b\x32+.google.protobuf.internal.TestAnyExtension1') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,]) + + + + +_TESTANY_MAPVALUEENTRY = _descriptor.Descriptor( + name='MapValueEntry', + full_name='google.protobuf.internal.TestAny.MapValueEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='google.protobuf.internal.TestAny.MapValueEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.internal.TestAny.MapValueEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=232, + serialized_end=279, +) + +_TESTANY = _descriptor.Descriptor( + name='TestAny', + full_name='google.protobuf.internal.TestAny', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.internal.TestAny.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_value', full_name='google.protobuf.internal.TestAny.int_value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_value', full_name='google.protobuf.internal.TestAny.map_value', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTANY_MAPVALUEENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(10, 536870912), ], + oneofs=[ + ], + serialized_start=97, + serialized_end=289, +) + + +_TESTANYEXTENSION1 = _descriptor.Descriptor( + name='TestAnyExtension1', + full_name='google.protobuf.internal.TestAnyExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='google.protobuf.internal.TestAnyExtension1.i', index=0, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='extension1', full_name='google.protobuf.internal.TestAnyExtension1.extension1', index=0, + number=98418603, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=292, + serialized_end=425, +) + +_TESTANY_MAPVALUEENTRY.containing_type = _TESTANY +_TESTANY.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTANY.fields_by_name['map_value'].message_type = _TESTANY_MAPVALUEENTRY +DESCRIPTOR.message_types_by_name['TestAny'] = _TESTANY +DESCRIPTOR.message_types_by_name['TestAnyExtension1'] = _TESTANYEXTENSION1 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAny = _reflection.GeneratedProtocolMessageType('TestAny', (_message.Message,), dict( + + MapValueEntry = _reflection.GeneratedProtocolMessageType('MapValueEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTANY_MAPVALUEENTRY, + __module__ = 'google.protobuf.internal.any_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestAny.MapValueEntry) + )) + , + DESCRIPTOR = _TESTANY, + __module__ = 'google.protobuf.internal.any_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestAny) + )) +_sym_db.RegisterMessage(TestAny) +_sym_db.RegisterMessage(TestAny.MapValueEntry) + +TestAnyExtension1 = _reflection.GeneratedProtocolMessageType('TestAnyExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTANYEXTENSION1, + __module__ = 'google.protobuf.internal.any_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestAnyExtension1) + )) +_sym_db.RegisterMessage(TestAnyExtension1) + +_TESTANYEXTENSION1.extensions_by_name['extension1'].message_type = _TESTANYEXTENSION1 +TestAny.RegisterExtension(_TESTANYEXTENSION1.extensions_by_name['extension1']) + +_TESTANY_MAPVALUEENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/api_implementation.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/api_implementation.py new file mode 100644 index 0000000..ab9e781 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/api_implementation.py @@ -0,0 +1,173 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Determine which implementation of the protobuf API is used in this process. +""" + +import os +import warnings +import sys + +try: + # pylint: disable=g-import-not-at-top + from google.protobuf.internal import _api_implementation + # The compile-time constants in the _api_implementation module can be used to + # switch to a certain implementation of the Python API at build time. + _api_version = _api_implementation.api_version + _proto_extension_modules_exist_in_build = True +except ImportError: + _api_version = -1 # Unspecified by compiler flags. + _proto_extension_modules_exist_in_build = False + +if _api_version == 1: + raise ValueError('api_version=1 is no longer supported.') +if _api_version < 0: # Still unspecified? + try: + # The presence of this module in a build allows the proto implementation to + # be upgraded merely via build deps rather than a compiler flag or the + # runtime environment variable. + # pylint: disable=g-import-not-at-top + from google.protobuf import _use_fast_cpp_protos + # Work around a known issue in the classic bootstrap .par import hook. + if not _use_fast_cpp_protos: + raise ImportError('_use_fast_cpp_protos import succeeded but was None') + del _use_fast_cpp_protos + _api_version = 2 + except ImportError: + try: + # pylint: disable=g-import-not-at-top + from google.protobuf.internal import use_pure_python + del use_pure_python # Avoids a pylint error and namespace pollution. + except ImportError: + # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default; + # it can cause data loss if you have any Python-only extensions to any + # message passed back and forth with C++ code. + # + # TODO(b/17427486): Once that bug is fixed, we want to make both Python 2 + # and Python 3 default to `_api_version = 2` (C++ implementation V2). + pass + +_default_implementation_type = ( + 'python' if _api_version <= 0 else 'cpp') + +# This environment variable can be used to switch to a certain implementation +# of the Python API, overriding the compile-time constants in the +# _api_implementation module. Right now only 'python' and 'cpp' are valid +# values. Any other value will be ignored. +_implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', + _default_implementation_type) + +if _implementation_type != 'python': + _implementation_type = 'cpp' + +if 'PyPy' in sys.version and _implementation_type == 'cpp': + warnings.warn('PyPy does not work yet with cpp protocol buffers. ' + 'Falling back to the python implementation.') + _implementation_type = 'python' + +# This environment variable can be used to switch between the two +# 'cpp' implementations, overriding the compile-time constants in the +# _api_implementation module. Right now only '2' is supported. Any other +# value will cause an error to be raised. +_implementation_version_str = os.getenv( + 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2') + +if _implementation_version_str != '2': + raise ValueError( + 'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' + + _implementation_version_str + '" (supported versions: 2)' + ) + +_implementation_version = int(_implementation_version_str) + + +# Detect if serialization should be deterministic by default +try: + # The presence of this module in a build allows the proto implementation to + # be upgraded merely via build deps. + # + # NOTE: Merely importing this automatically enables deterministic proto + # serialization for C++ code, but we still need to export it as a boolean so + # that we can do the same for `_implementation_type == 'python'`. + # + # NOTE2: It is possible for C++ code to enable deterministic serialization by + # default _without_ affecting Python code, if the C++ implementation is not in + # use by this module. That is intended behavior, so we don't actually expose + # this boolean outside of this module. + # + # pylint: disable=g-import-not-at-top,unused-import + from google.protobuf import enable_deterministic_proto_serialization + _python_deterministic_proto_serialization = True +except ImportError: + _python_deterministic_proto_serialization = False + + +# Usage of this function is discouraged. Clients shouldn't care which +# implementation of the API is in use. Note that there is no guarantee +# that differences between APIs will be maintained. +# Please don't use this function if possible. +def Type(): + return _implementation_type + + +# See comment on 'Type' above. +def Version(): + return _implementation_version + + +# For internal use only +def IsPythonDefaultSerializationDeterministic(): + return _python_deterministic_proto_serialization + +# DO NOT USE: For migration and testing only. Will be removed when Proto3 +# defaults to preserve unknowns. +if _implementation_type == 'cpp': + try: + # pylint: disable=g-import-not-at-top + from google.protobuf.pyext import _message + + def GetPythonProto3PreserveUnknownsDefault(): + return _message.GetPythonProto3PreserveUnknownsDefault() + + def SetPythonProto3PreserveUnknownsDefault(preserve): + _message.SetPythonProto3PreserveUnknownsDefault(preserve) + except ImportError: + # Unrecognized cpp implementation. Skipping the unknown fields APIs. + pass +else: + _python_proto3_preserve_unknowns_default = True + + def GetPythonProto3PreserveUnknownsDefault(): + return _python_proto3_preserve_unknowns_default + + def SetPythonProto3PreserveUnknownsDefault(preserve): + global _python_proto3_preserve_unknowns_default + _python_proto3_preserve_unknowns_default = preserve + diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/containers.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/containers.py new file mode 100644 index 0000000..f46e458 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/containers.py @@ -0,0 +1,630 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains container classes to represent different protocol buffer types. + +This file defines container classes which represent categories of protocol +buffer field types which need extra maintenance. Currently these categories +are: + - Repeated scalar fields - These are all repeated fields which aren't + composite (e.g. they are of simple types like int32, string, etc). + - Repeated composite fields - Repeated fields which are composite. This + includes groups and nested messages. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + +import collections +import sys + +if sys.version_info[0] < 3: + # We would use collections.MutableMapping all the time, but in Python 2 it + # doesn't define __slots__. This causes two significant problems: + # + # 1. we can't disallow arbitrary attribute assignment, even if our derived + # classes *do* define __slots__. + # + # 2. we can't safely derive a C type from it without __slots__ defined (the + # interpreter expects to find a dict at tp_dictoffset, which we can't + # robustly provide. And we don't want an instance dict anyway. + # + # So this is the Python 2.7 definition of Mapping/MutableMapping functions + # verbatim, except that: + # 1. We declare __slots__. + # 2. We don't declare this as a virtual base class. The classes defined + # in collections are the interesting base classes, not us. + # + # Note: deriving from object is critical. It is the only thing that makes + # this a true type, allowing us to derive from it in C++ cleanly and making + # __slots__ properly disallow arbitrary element assignment. + + class Mapping(object): + __slots__ = () + + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def __contains__(self, key): + try: + self[key] + except KeyError: + return False + else: + return True + + def iterkeys(self): + return iter(self) + + def itervalues(self): + for key in self: + yield self[key] + + def iteritems(self): + for key in self: + yield (key, self[key]) + + def keys(self): + return list(self) + + def items(self): + return [(key, self[key]) for key in self] + + def values(self): + return [self[key] for key in self] + + # Mappings are not hashable by default, but subclasses can change this + __hash__ = None + + def __eq__(self, other): + if not isinstance(other, collections.Mapping): + return NotImplemented + return dict(list(self.items())) == dict(list(other.items())) + + def __ne__(self, other): + return not (self == other) + + class MutableMapping(Mapping): + __slots__ = () + + __marker = object() + + def pop(self, key, default=__marker): + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def popitem(self): + try: + key = next(iter(self)) + except StopIteration: + raise KeyError + value = self[key] + del self[key] + return key, value + + def clear(self): + try: + while True: + self.popitem() + except KeyError: + pass + + def update(*args, **kwds): + if len(args) > 2: + raise TypeError("update() takes at most 2 positional " + "arguments ({} given)".format(len(args))) + elif not args: + raise TypeError("update() takes at least 1 argument (0 given)") + self = args[0] + other = args[1] if len(args) >= 2 else () + + if isinstance(other, Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in list(other.keys()): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in list(kwds.items()): + self[key] = value + + def setdefault(self, key, default=None): + try: + return self[key] + except KeyError: + self[key] = default + return default + + collections.Mapping.register(Mapping) + collections.MutableMapping.register(MutableMapping) + +else: + # In Python 3 we can just use MutableMapping directly, because it defines + # __slots__. + MutableMapping = collections.MutableMapping + + +class BaseContainer(object): + + """Base container class.""" + + # Minimizes memory usage and disallows assignment to other attributes. + __slots__ = ['_message_listener', '_values'] + + def __init__(self, message_listener): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + Modified() method when it is modified. + """ + self._message_listener = message_listener + self._values = [] + + def __getitem__(self, key): + """Retrieves item by the specified key.""" + return self._values[key] + + def __len__(self): + """Returns the number of elements in the container.""" + return len(self._values) + + def __ne__(self, other): + """Checks if another instance isn't equal to this one.""" + # The concrete classes should define __eq__. + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + def __repr__(self): + return repr(self._values) + + def sort(self, *args, **kwargs): + # Continue to support the old sort_function keyword argument. + # This is expected to be a rare occurrence, so use LBYL to avoid + # the overhead of actually catching KeyError. + if 'sort_function' in kwargs: + kwargs['cmp'] = kwargs.pop('sort_function') + self._values.sort(*args, **kwargs) + + +class RepeatedScalarFieldContainer(BaseContainer): + + """Simple, type-checked, list-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_type_checker'] + + def __init__(self, message_listener, type_checker): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + Modified() method when it is modified. + type_checker: A type_checkers.ValueChecker instance to run on elements + inserted into this container. + """ + super(RepeatedScalarFieldContainer, self).__init__(message_listener) + self._type_checker = type_checker + + def append(self, value): + """Appends an item to the list. Similar to list.append().""" + self._values.append(self._type_checker.CheckValue(value)) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def insert(self, key, value): + """Inserts the item at the specified position. Similar to list.insert().""" + self._values.insert(key, self._type_checker.CheckValue(value)) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def extend(self, elem_seq): + """Extends by appending the given iterable. Similar to list.extend().""" + + if elem_seq is None: + return + try: + elem_seq_iter = iter(elem_seq) + except TypeError: + if not elem_seq: + # silently ignore falsy inputs :-/. + # TODO(ptucker): Deprecate this behavior. b/18413862 + return + raise + + new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter] + if new_values: + self._values.extend(new_values) + self._message_listener.Modified() + + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one. We do not check the types of the individual fields. + """ + self._values.extend(other._values) + self._message_listener.Modified() + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + + def __setitem__(self, key, value): + """Sets the item on the specified position.""" + if isinstance(key, slice): # PY3 + if key.step is not None: + raise ValueError('Extended slices not supported') + self.__setslice__(key.start, key.stop, value) + else: + self._values[key] = self._type_checker.CheckValue(value) + self._message_listener.Modified() + + def __getslice__(self, start, stop): + """Retrieves the subset of items from between the specified indices.""" + return self._values[start:stop] + + def __setslice__(self, start, stop, values): + """Sets the subset of items from between the specified indices.""" + new_values = [] + for value in values: + new_values.append(self._type_checker.CheckValue(value)) + self._values[start:stop] = new_values + self._message_listener.Modified() + + def __delitem__(self, key): + """Deletes the item at the specified position.""" + del self._values[key] + self._message_listener.Modified() + + def __delslice__(self, start, stop): + """Deletes the subset of items from between the specified indices.""" + del self._values[start:stop] + self._message_listener.Modified() + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + # Special case for the same type which should be common and fast. + if isinstance(other, self.__class__): + return other._values == self._values + # We are presumably comparing against some other sequence type. + return other == self._values + +collections.MutableSequence.register(BaseContainer) + + +class RepeatedCompositeFieldContainer(BaseContainer): + + """Simple, list-like container for holding repeated composite fields.""" + + # Disallows assignment to other attributes. + __slots__ = ['_message_descriptor'] + + def __init__(self, message_listener, message_descriptor): + """ + Note that we pass in a descriptor instead of the generated directly, + since at the time we construct a _RepeatedCompositeFieldContainer we + haven't yet necessarily initialized the type that will be contained in the + container. + + Args: + message_listener: A MessageListener implementation. + The RepeatedCompositeFieldContainer will call this object's + Modified() method when it is modified. + message_descriptor: A Descriptor instance describing the protocol type + that should be present in this container. We'll use the + _concrete_class field of this descriptor when the client calls add(). + """ + super(RepeatedCompositeFieldContainer, self).__init__(message_listener) + self._message_descriptor = message_descriptor + + def add(self, **kwargs): + """Adds a new element at the end of the list and returns it. Keyword + arguments may be used to initialize the element. + """ + new_element = self._message_descriptor._concrete_class(**kwargs) + new_element._SetListener(self._message_listener) + self._values.append(new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + return new_element + + def extend(self, elem_seq): + """Extends by appending the given sequence of elements of the same type + as this one, copying each individual message. + """ + message_class = self._message_descriptor._concrete_class + listener = self._message_listener + values = self._values + for message in elem_seq: + new_element = message_class() + new_element._SetListener(listener) + new_element.MergeFrom(message) + values.append(new_element) + listener.Modified() + + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one, copying each individual message. + """ + self.extend(other._values) + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + + def __getslice__(self, start, stop): + """Retrieves the subset of items from between the specified indices.""" + return self._values[start:stop] + + def __delitem__(self, key): + """Deletes the item at the specified position.""" + del self._values[key] + self._message_listener.Modified() + + def __delslice__(self, start, stop): + """Deletes the subset of items from between the specified indices.""" + del self._values[start:stop] + self._message_listener.Modified() + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + if not isinstance(other, self.__class__): + raise TypeError('Can only compare repeated composite fields against ' + 'other repeated composite fields.') + return self._values == other._values + + +class ScalarMap(MutableMapping): + + """Simple, type-checked, dict-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener', + '_entry_descriptor'] + + def __init__(self, message_listener, key_checker, value_checker, + entry_descriptor): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + entry_descriptor: The MessageDescriptor of a map entry: key and value. + """ + self._message_listener = message_listener + self._key_checker = key_checker + self._value_checker = value_checker + self._entry_descriptor = entry_descriptor + self._values = {} + + def __getitem__(self, key): + try: + return self._values[key] + except KeyError: + key = self._key_checker.CheckValue(key) + val = self._value_checker.DefaultValue() + self._values[key] = val + return val + + def __contains__(self, item): + # We check the key's type to match the strong-typing flavor of the API. + # Also this makes it easier to match the behavior of the C++ implementation. + self._key_checker.CheckValue(item) + return item in self._values + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __setitem__(self, key, value): + checked_key = self._key_checker.CheckValue(key) + checked_value = self._value_checker.CheckValue(value) + self._values[checked_key] = checked_value + self._message_listener.Modified() + + def __delitem__(self, key): + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def __repr__(self): + return repr(self._values) + + def MergeFrom(self, other): + self._values.update(other._values) + self._message_listener.Modified() + + def InvalidateIterators(self): + # It appears that the only way to reliably invalidate iterators to + # self._values is to ensure that its size changes. + original = self._values + self._values = original.copy() + original[None] = None + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + def GetEntryClass(self): + return self._entry_descriptor._concrete_class + + +class MessageMap(MutableMapping): + + """Simple, type-checked, dict-like container for with submessage values.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_values', '_message_listener', + '_message_descriptor', '_entry_descriptor'] + + def __init__(self, message_listener, message_descriptor, key_checker, + entry_descriptor): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + entry_descriptor: The MessageDescriptor of a map entry: key and value. + """ + self._message_listener = message_listener + self._message_descriptor = message_descriptor + self._key_checker = key_checker + self._entry_descriptor = entry_descriptor + self._values = {} + + def __getitem__(self, key): + key = self._key_checker.CheckValue(key) + try: + return self._values[key] + except KeyError: + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + self._values[key] = new_element + self._message_listener.Modified() + + return new_element + + def get_or_create(self, key): + """get_or_create() is an alias for getitem (ie. map[key]). + + Args: + key: The key to get or create in the map. + + This is useful in cases where you want to be explicit that the call is + mutating the map. This can avoid lint errors for statements like this + that otherwise would appear to be pointless statements: + + msg.my_map[key] + """ + return self[key] + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __contains__(self, item): + item = self._key_checker.CheckValue(item) + return item in self._values + + def __setitem__(self, key, value): + raise ValueError('May not set values directly, call my_map[key].foo = 5') + + def __delitem__(self, key): + key = self._key_checker.CheckValue(key) + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def __repr__(self): + return repr(self._values) + + def MergeFrom(self, other): + for key in other: + # According to documentation: "When parsing from the wire or when merging, + # if there are duplicate map keys the last key seen is used". + if key in self: + del self[key] + self[key].CopyFrom(other[key]) + # self._message_listener.Modified() not required here, because + # mutations to submessages already propagate. + + def InvalidateIterators(self): + # It appears that the only way to reliably invalidate iterators to + # self._values is to ensure that its size changes. + original = self._values + self._values = original.copy() + original[None] = None + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + def GetEntryClass(self): + return self._entry_descriptor._concrete_class diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/decoder.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/decoder.py new file mode 100644 index 0000000..923939b --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/decoder.py @@ -0,0 +1,854 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Code for decoding protocol buffer primitives. + +This code is very similar to encoder.py -- read the docs for that module first. + +A "decoder" is a function with the signature: + Decode(buffer, pos, end, message, field_dict) +The arguments are: + buffer: The string containing the encoded message. + pos: The current position in the string. + end: The position in the string where the current message ends. May be + less than len(buffer) if we're reading a sub-message. + message: The message object into which we're parsing. + field_dict: message._fields (avoids a hashtable lookup). +The decoder reads the field and stores it into field_dict, returning the new +buffer position. A decoder for a repeated field may proactively decode all of +the elements of that field, if they appear consecutively. + +Note that decoders may throw any of the following: + IndexError: Indicates a truncated message. + struct.error: Unpacking of a fixed-width field failed. + message.DecodeError: Other errors. + +Decoders are expected to raise an exception if they are called with pos > end. +This allows callers to be lax about bounds checking: it's fineto read past +"end" as long as you are sure that someone else will notice and throw an +exception later on. + +Something up the call stack is expected to catch IndexError and struct.error +and convert them to message.DecodeError. + +Decoders are constructed using decoder constructors with the signature: + MakeDecoder(field_number, is_repeated, is_packed, key, new_default) +The arguments are: + field_number: The field number of the field we want to decode. + is_repeated: Is the field a repeated field? (bool) + is_packed: Is the field a packed field? (bool) + key: The key to use when looking up the field within field_dict. + (This is actually the FieldDescriptor but nothing in this + file should depend on that.) + new_default: A function which takes a message object as a parameter and + returns a new instance of the default value for this field. + (This is called for repeated fields and sub-messages, when an + instance does not already exist.) + +As with encoders, we define a decoder constructor for every type of field. +Then, for every field of every message class we construct an actual decoder. +That decoder goes into a dict indexed by tag, so when we decode a message +we repeatedly read a tag, look up the corresponding decoder, and invoke it. +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import struct + +import six + +if six.PY3: + long = int + +from google.protobuf.internal import encoder +from google.protobuf.internal import wire_format +from google.protobuf import message + + +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF +_NAN = _POS_INF * 0 + + +# This is not for optimization, but rather to avoid conflicts with local +# variables named "message". +_DecodeError = message.DecodeError + + +def _VarintDecoder(mask, result_type): + """Return an encoder for a basic varint value (does not include tag). + + Decoded values will be bitwise-anded with the given mask before being + returned, e.g. to limit them to 32 bits. The returned decoder does not + take the usual "end" parameter -- the caller is expected to do bounds checking + after the fact (often the caller can defer such checking until later). The + decoder returns a (value, new_pos) pair. + """ + + def DecodeVarint(buffer, pos): + result = 0 + shift = 0 + while 1: + b = six.indexbytes(buffer, pos) + result |= ((b & 0x7f) << shift) + pos += 1 + if not (b & 0x80): + result &= mask + result = result_type(result) + return (result, pos) + shift += 7 + if shift >= 64: + raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint + + +def _SignedVarintDecoder(bits, result_type): + """Like _VarintDecoder() but decodes signed values.""" + + signbit = 1 << (bits - 1) + mask = (1 << bits) - 1 + + def DecodeVarint(buffer, pos): + result = 0 + shift = 0 + while 1: + b = six.indexbytes(buffer, pos) + result |= ((b & 0x7f) << shift) + pos += 1 + if not (b & 0x80): + result &= mask + result = (result ^ signbit) - signbit + result = result_type(result) + return (result, pos) + shift += 7 + if shift >= 64: + raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint + +# We force 32-bit values to int and 64-bit values to long to make +# alternate implementations where the distinction is more significant +# (e.g. the C++ implementation) simpler. + +_DecodeVarint = _VarintDecoder((1 << 64) - 1, int) +_DecodeSignedVarint = _SignedVarintDecoder(64, int) + +# Use these versions for values which must be limited to 32 bits. +_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int) +_DecodeSignedVarint32 = _SignedVarintDecoder(32, int) + + +def ReadTag(buffer, pos): + """Read a tag from the buffer, and return a (tag_bytes, new_pos) tuple. + + We return the raw bytes of the tag rather than decoding them. The raw + bytes can then be used to look up the proper decoder. This effectively allows + us to trade some work that would be done in pure-python (decoding a varint) + for work that is done in C (searching for a byte string in a hash table). + In a low-level language it would be much cheaper to decode the varint and + use that, but not in Python. + """ + + start = pos + while six.indexbytes(buffer, pos) & 0x80: + pos += 1 + pos += 1 + return (six.binary_type(buffer[start:pos]), pos) + + +# -------------------------------------------------------------------- + + +def _SimpleDecoder(wire_type, decode_value): + """Return a constructor for a decoder for fields of a particular type. + + Args: + wire_type: The field's wire type. + decode_value: A function which decodes an individual value, e.g. + _DecodeVarint() + """ + + def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default): + if is_packed: + local_DecodeVarint = _DecodeVarint + def DecodePackedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + (endpoint, pos) = local_DecodeVarint(buffer, pos) + endpoint += pos + if endpoint > end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + (element, pos) = decode_value(buffer, pos) + value.append(element) + if pos > endpoint: + del value[-1] # Discard corrupt value. + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_type) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = decode_value(buffer, pos) + value.append(element) + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (field_dict[key], pos) = decode_value(buffer, pos) + if pos > end: + del field_dict[key] # Discard corrupt value. + raise _DecodeError('Truncated message.') + return pos + return DecodeField + + return SpecificDecoder + + +def _ModifiedDecoder(wire_type, decode_value, modify_value): + """Like SimpleDecoder but additionally invokes modify_value on every value + before storing it. Usually modify_value is ZigZagDecode. + """ + + # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but + # not enough to make a significant difference. + + def InnerDecode(buffer, pos): + (result, new_pos) = decode_value(buffer, pos) + return (modify_value(result), new_pos) + return _SimpleDecoder(wire_type, InnerDecode) + + +def _StructPackDecoder(wire_type, format): + """Return a constructor for a decoder for a fixed-width field. + + Args: + wire_type: The field's wire type. + format: The format string to pass to struct.unpack(). + """ + + value_size = struct.calcsize(format) + local_unpack = struct.unpack + + # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but + # not enough to make a significant difference. + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + + def InnerDecode(buffer, pos): + new_pos = pos + value_size + result = local_unpack(format, buffer[pos:new_pos])[0] + return (result, new_pos) + return _SimpleDecoder(wire_type, InnerDecode) + + +def _FloatDecoder(): + """Returns a decoder for a float field. + + This code works around a bug in struct.unpack for non-finite 32-bit + floating-point values. + """ + + local_unpack = struct.unpack + + def InnerDecode(buffer, pos): + # We expect a 32-bit value in little-endian byte order. Bit 1 is the sign + # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand. + new_pos = pos + 4 + float_bytes = buffer[pos:new_pos] + + # If this value has all its exponent bits set, then it's non-finite. + # In Python 2.4, struct.unpack will convert it to a finite 64-bit value. + # To avoid that, we parse it specially. + if (float_bytes[3:4] in b'\x7F\xFF' and float_bytes[2:3] >= b'\x80'): + # If at least one significand bit is set... + if float_bytes[0:3] != b'\x00\x00\x80': + return (_NAN, new_pos) + # If sign bit is set... + if float_bytes[3:4] == b'\xFF': + return (_NEG_INF, new_pos) + return (_POS_INF, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack('= b'\xF0') + and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')): + return (_NAN, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack(' end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + value_start_pos = pos + (element, pos) = _DecodeSignedVarint32(buffer, pos) + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos])) + if pos > endpoint: + if element in enum_type.values_by_number: + del value[-1] # Discard corrupt value. + else: + del message._unknown_fields[-1] + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = _DecodeSignedVarint32(buffer, pos) + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append( + (tag_bytes, buffer[pos:new_pos])) + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value_start_pos = pos + (enum_value, pos) = _DecodeSignedVarint32(buffer, pos) + if pos > end: + raise _DecodeError('Truncated message.') + if enum_value in enum_type.values_by_number: + field_dict[key] = enum_value + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos])) + return pos + return DecodeField + + +# -------------------------------------------------------------------- + + +Int32Decoder = _SimpleDecoder( + wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32) + +Int64Decoder = _SimpleDecoder( + wire_format.WIRETYPE_VARINT, _DecodeSignedVarint) + +UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32) +UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint) + +SInt32Decoder = _ModifiedDecoder( + wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode) +SInt64Decoder = _ModifiedDecoder( + wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode) + +# Note that Python conveniently guarantees that when using the '<' prefix on +# formats, they will also have the same size across all platforms (as opposed +# to without the prefix, where their sizes depend on the C compiler's basic +# type sizes). +Fixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, ' end: + raise _DecodeError('Truncated string.') + value.append(_ConvertToUnicode(buffer[pos:new_pos])) + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos]) + return new_pos + return DecodeField + + +def BytesDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a bytes field.""" + + local_DecodeVarint = _DecodeVarint + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + value.append(buffer[pos:new_pos]) + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + field_dict[key] = buffer[pos:new_pos] + return new_pos + return DecodeField + + +def GroupDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a group field.""" + + end_tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_END_GROUP) + end_tag_len = len(end_tag_bytes) + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_START_GROUP) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read sub-message. + pos = value.add()._InternalParse(buffer, pos, end) + # Read end tag. + new_pos = pos+end_tag_len + if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: + raise _DecodeError('Missing group end tag.') + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read sub-message. + pos = value._InternalParse(buffer, pos, end) + # Read end tag. + new_pos = pos+end_tag_len + if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: + raise _DecodeError('Missing group end tag.') + return new_pos + return DecodeField + + +def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a message field.""" + + local_DecodeVarint = _DecodeVarint + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + if value.add()._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + if value._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it encountered + # an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + return new_pos + return DecodeField + + +# -------------------------------------------------------------------- + +MESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP) + +def MessageSetItemDecoder(descriptor): + """Returns a decoder for a MessageSet item. + + The parameter is the message Descriptor. + + The message set message looks like this: + message MessageSet { + repeated group Item = 1 { + required int32 type_id = 2; + required string message = 3; + } + } + """ + + type_id_tag_bytes = encoder.TagBytes(2, wire_format.WIRETYPE_VARINT) + message_tag_bytes = encoder.TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED) + item_end_tag_bytes = encoder.TagBytes(1, wire_format.WIRETYPE_END_GROUP) + + local_ReadTag = ReadTag + local_DecodeVarint = _DecodeVarint + local_SkipField = SkipField + + def DecodeItem(buffer, pos, end, message, field_dict): + message_set_item_start = pos + type_id = -1 + message_start = -1 + message_end = -1 + + # Technically, type_id and message can appear in any order, so we need + # a little loop here. + while 1: + (tag_bytes, pos) = local_ReadTag(buffer, pos) + if tag_bytes == type_id_tag_bytes: + (type_id, pos) = local_DecodeVarint(buffer, pos) + elif tag_bytes == message_tag_bytes: + (size, message_start) = local_DecodeVarint(buffer, pos) + pos = message_end = message_start + size + elif tag_bytes == item_end_tag_bytes: + break + else: + pos = SkipField(buffer, pos, end, tag_bytes) + if pos == -1: + raise _DecodeError('Missing group end tag.') + + if pos > end: + raise _DecodeError('Truncated message.') + + if type_id == -1: + raise _DecodeError('MessageSet item missing type_id.') + if message_start == -1: + raise _DecodeError('MessageSet item missing message.') + + extension = message.Extensions._FindExtensionByNumber(type_id) + if extension is not None: + value = field_dict.get(extension) + if value is None: + value = field_dict.setdefault( + extension, extension.message_type._concrete_class()) + if value._InternalParse(buffer, message_start,message_end) != message_end: + # The only reason _InternalParse would return early is if it encountered + # an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append((MESSAGE_SET_ITEM_TAG, + buffer[message_set_item_start:pos])) + + return pos + + return DecodeItem + +# -------------------------------------------------------------------- + +def MapDecoder(field_descriptor, new_default, is_message_map): + """Returns a decoder for a map field.""" + + key = field_descriptor + tag_bytes = encoder.TagBytes(field_descriptor.number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + local_DecodeVarint = _DecodeVarint + # Can't read _concrete_class yet; might not be initialized. + message_type = field_descriptor.message_type + + def DecodeMap(buffer, pos, end, message, field_dict): + submsg = message_type._concrete_class() + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + submsg.Clear() + if submsg._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + + if is_message_map: + value[submsg.key].MergeFrom(submsg.value) + else: + value[submsg.key] = submsg.value + + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + + return DecodeMap + +# -------------------------------------------------------------------- +# Optimization is not as heavy here because calls to SkipField() are rare, +# except for handling end-group tags. + +def _SkipVarint(buffer, pos, end): + """Skip a varint value. Returns the new position.""" + # Previously ord(buffer[pos]) raised IndexError when pos is out of range. + # With this code, ord(b'') raises TypeError. Both are handled in + # python_message.py to generate a 'Truncated message' error. + while ord(buffer[pos:pos+1]) & 0x80: + pos += 1 + pos += 1 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipFixed64(buffer, pos, end): + """Skip a fixed64 value. Returns the new position.""" + + pos += 8 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipLengthDelimited(buffer, pos, end): + """Skip a length-delimited value. Returns the new position.""" + + (size, pos) = _DecodeVarint(buffer, pos) + pos += size + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipGroup(buffer, pos, end): + """Skip sub-group. Returns the new position.""" + + while 1: + (tag_bytes, pos) = ReadTag(buffer, pos) + new_pos = SkipField(buffer, pos, end, tag_bytes) + if new_pos == -1: + return pos + pos = new_pos + +def _EndGroup(buffer, pos, end): + """Skipping an END_GROUP tag returns -1 to tell the parent loop to break.""" + + return -1 + +def _SkipFixed32(buffer, pos, end): + """Skip a fixed32 value. Returns the new position.""" + + pos += 4 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _RaiseInvalidWireType(buffer, pos, end): + """Skip function for unknown wire types. Raises an exception.""" + + raise _DecodeError('Tag had invalid wire type.') + +def _FieldSkipper(): + """Constructs the SkipField function.""" + + WIRETYPE_TO_SKIPPER = [ + _SkipVarint, + _SkipFixed64, + _SkipLengthDelimited, + _SkipGroup, + _EndGroup, + _SkipFixed32, + _RaiseInvalidWireType, + _RaiseInvalidWireType, + ] + + wiretype_mask = wire_format.TAG_TYPE_MASK + + def SkipField(buffer, pos, end, tag_bytes): + """Skips a field with the specified tag. + + |pos| should point to the byte immediately after the tag. + + Returns: + The new position (after the tag value), or -1 if the tag is an end-group + tag (in which case the calling loop should break). + """ + + # The wire type is always in the first byte since varints are little-endian. + wire_type = ord(tag_bytes[0:1]) & wiretype_mask + return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end) + + return SkipField + +SkipField = _FieldSkipper() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_database_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_database_test.py new file mode 100644 index 0000000..f97477b --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_database_test.py @@ -0,0 +1,124 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.descriptor_database.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest +import warnings + +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf import descriptor_database + + +class DescriptorDatabaseTest(unittest.TestCase): + + def testAdd(self): + db = descriptor_database.DescriptorDatabase() + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + db.Add(file_desc_proto) + + self.assertEqual(file_desc_proto, db.FindFileByName( + 'google/protobuf/internal/factory_test2.proto')) + # Can find message type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message')) + # Can find nested message type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message')) + # Can find enum type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Enum')) + # Can find nested enum type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum')) + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum')) + # Can find field. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.list_field')) + # Can find enum value. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Enum.FACTORY_2_VALUE_0')) + # Can find top level extension. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.another_field')) + # Can find nested extension inside a message. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.one_more_field')) + + # Can find service. + file_desc_proto2 = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + db.Add(file_desc_proto2) + self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( + 'protobuf_unittest.TestService')) + + # Non-existent field under a valid top level symbol can also be + # found. The behavior is the same with protobuf C++. + self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes.none_field')) + + self.assertRaises(KeyError, + db.FindFileContainingSymbol, + 'protobuf_unittest.NoneMessage') + + def testConflictRegister(self): + db = descriptor_database.DescriptorDatabase() + unittest_fd = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + db.Add(unittest_fd) + conflict_fd = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + conflict_fd.name = 'other_file' + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + db.Add(conflict_fd) + self.assertTrue(len(w)) + self.assertIs(w[0].category, RuntimeWarning) + self.assertIn('Conflict register for file "other_file": ', + str(w[0].message)) + self.assertIn('already defined in file ' + '"google/protobuf/unittest.proto"', + str(w[0].message)) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test.py new file mode 100644 index 0000000..ca83a87 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test.py @@ -0,0 +1,1055 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.descriptor_pool.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import copy +import os +import sys +import warnings + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_import_public_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import descriptor_pool_test1_pb2 +from google.protobuf.internal import descriptor_pool_test2_pb2 +from google.protobuf.internal import factory_test1_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf.internal import file_options_test_pb2 +from google.protobuf.internal import more_messages_pb2 +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool +from google.protobuf import message_factory +from google.protobuf import symbol_database + + + +class DescriptorPoolTestBase(object): + + def testFindFileByName(self): + name1 = 'google/protobuf/internal/factory_test1.proto' + file_desc1 = self.pool.FindFileByName(name1) + self.assertIsInstance(file_desc1, descriptor.FileDescriptor) + self.assertEqual(name1, file_desc1.name) + self.assertEqual('google.protobuf.python.internal', file_desc1.package) + self.assertIn('Factory1Message', file_desc1.message_types_by_name) + + name2 = 'google/protobuf/internal/factory_test2.proto' + file_desc2 = self.pool.FindFileByName(name2) + self.assertIsInstance(file_desc2, descriptor.FileDescriptor) + self.assertEqual(name2, file_desc2.name) + self.assertEqual('google.protobuf.python.internal', file_desc2.package) + self.assertIn('Factory2Message', file_desc2.message_types_by_name) + + def testFindFileByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindFileByName('Does not exist') + + def testFindFileContainingSymbol(self): + file_desc1 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory1Message') + self.assertIsInstance(file_desc1, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test1.proto', + file_desc1.name) + self.assertEqual('google.protobuf.python.internal', file_desc1.package) + self.assertIn('Factory1Message', file_desc1.message_types_by_name) + + file_desc2 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message') + self.assertIsInstance(file_desc2, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test2.proto', + file_desc2.name) + self.assertEqual('google.protobuf.python.internal', file_desc2.package) + self.assertIn('Factory2Message', file_desc2.message_types_by_name) + + # Tests top level extension. + file_desc3 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.another_field') + self.assertIsInstance(file_desc3, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test2.proto', + file_desc3.name) + + # Tests nested extension inside a message. + file_desc4 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + self.assertIsInstance(file_desc4, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test2.proto', + file_desc4.name) + + file_desc5 = self.pool.FindFileContainingSymbol( + 'protobuf_unittest.TestService') + self.assertIsInstance(file_desc5, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/unittest.proto', + file_desc5.name) + + # Tests the generated pool. + assert descriptor_pool.Default().FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + assert descriptor_pool.Default().FindFileContainingSymbol( + 'google.protobuf.python.internal.another_field') + assert descriptor_pool.Default().FindFileContainingSymbol( + 'protobuf_unittest.TestService') + + def testFindFileContainingSymbolFailure(self): + with self.assertRaises(KeyError): + self.pool.FindFileContainingSymbol('Does not exist') + + def testFindMessageTypeByName(self): + msg1 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + self.assertIsInstance(msg1, descriptor.Descriptor) + self.assertEqual('Factory1Message', msg1.name) + self.assertEqual('google.protobuf.python.internal.Factory1Message', + msg1.full_name) + self.assertEqual(None, msg1.containing_type) + self.assertFalse(msg1.has_options) + + nested_msg1 = msg1.nested_types[0] + self.assertEqual('NestedFactory1Message', nested_msg1.name) + self.assertEqual(msg1, nested_msg1.containing_type) + + nested_enum1 = msg1.enum_types[0] + self.assertEqual('NestedFactory1Enum', nested_enum1.name) + self.assertEqual(msg1, nested_enum1.containing_type) + + self.assertEqual(nested_msg1, msg1.fields_by_name[ + 'nested_factory_1_message'].message_type) + self.assertEqual(nested_enum1, msg1.fields_by_name[ + 'nested_factory_1_enum'].enum_type) + + msg2 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + self.assertIsInstance(msg2, descriptor.Descriptor) + self.assertEqual('Factory2Message', msg2.name) + self.assertEqual('google.protobuf.python.internal.Factory2Message', + msg2.full_name) + self.assertIsNone(msg2.containing_type) + + nested_msg2 = msg2.nested_types[0] + self.assertEqual('NestedFactory2Message', nested_msg2.name) + self.assertEqual(msg2, nested_msg2.containing_type) + + nested_enum2 = msg2.enum_types[0] + self.assertEqual('NestedFactory2Enum', nested_enum2.name) + self.assertEqual(msg2, nested_enum2.containing_type) + + self.assertEqual(nested_msg2, msg2.fields_by_name[ + 'nested_factory_2_message'].message_type) + self.assertEqual(nested_enum2, msg2.fields_by_name[ + 'nested_factory_2_enum'].enum_type) + + self.assertTrue(msg2.fields_by_name['int_with_default'].has_default_value) + self.assertEqual( + 1776, msg2.fields_by_name['int_with_default'].default_value) + + self.assertTrue( + msg2.fields_by_name['double_with_default'].has_default_value) + self.assertEqual( + 9.99, msg2.fields_by_name['double_with_default'].default_value) + + self.assertTrue( + msg2.fields_by_name['string_with_default'].has_default_value) + self.assertEqual( + 'hello world', msg2.fields_by_name['string_with_default'].default_value) + + self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default_value) + self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value) + + self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default_value) + self.assertEqual( + 1, msg2.fields_by_name['enum_with_default'].default_value) + + msg3 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message') + self.assertEqual(nested_msg2, msg3) + + self.assertTrue(msg2.fields_by_name['bytes_with_default'].has_default_value) + self.assertEqual( + b'a\xfb\x00c', + msg2.fields_by_name['bytes_with_default'].default_value) + + self.assertEqual(1, len(msg2.oneofs)) + self.assertEqual(1, len(msg2.oneofs_by_name)) + self.assertEqual(2, len(msg2.oneofs[0].fields)) + for name in ['oneof_int', 'oneof_string']: + self.assertEqual(msg2.oneofs[0], + msg2.fields_by_name[name].containing_oneof) + self.assertIn(msg2.fields_by_name[name], msg2.oneofs[0].fields) + + def testFindTypeErrors(self): + self.assertRaises(TypeError, self.pool.FindExtensionByNumber, '') + + # TODO(jieluo): Fix python to raise correct errors. + if api_implementation.Type() == 'cpp': + self.assertRaises(TypeError, self.pool.FindMethodByName, 0) + self.assertRaises(KeyError, self.pool.FindMethodByName, '') + error_type = TypeError + else: + error_type = AttributeError + self.assertRaises(error_type, self.pool.FindMessageTypeByName, 0) + self.assertRaises(error_type, self.pool.FindFieldByName, 0) + self.assertRaises(error_type, self.pool.FindExtensionByName, 0) + self.assertRaises(error_type, self.pool.FindEnumTypeByName, 0) + self.assertRaises(error_type, self.pool.FindOneofByName, 0) + self.assertRaises(error_type, self.pool.FindServiceByName, 0) + self.assertRaises(error_type, self.pool.FindFileContainingSymbol, 0) + if api_implementation.Type() == 'python': + error_type = KeyError + self.assertRaises(error_type, self.pool.FindFileByName, 0) + + def testFindMessageTypeByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindMessageTypeByName('Does not exist') + + def testFindEnumTypeByName(self): + enum1 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory1Enum') + self.assertIsInstance(enum1, descriptor.EnumDescriptor) + self.assertEqual(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number) + self.assertEqual(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number) + self.assertFalse(enum1.has_options) + + nested_enum1 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory1Message.NestedFactory1Enum') + self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor) + self.assertEqual( + 0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number) + self.assertEqual( + 1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number) + + enum2 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory2Enum') + self.assertIsInstance(enum2, descriptor.EnumDescriptor) + self.assertEqual(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number) + self.assertEqual(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number) + + nested_enum2 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum') + self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor) + self.assertEqual( + 0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number) + self.assertEqual( + 1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number) + + def testFindEnumTypeByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindEnumTypeByName('Does not exist') + + def testFindFieldByName(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix cpp extension to find field correctly + # when descriptor pool is using an underlying database. + return + field = self.pool.FindFieldByName( + 'google.protobuf.python.internal.Factory1Message.list_value') + self.assertEqual(field.name, 'list_value') + self.assertEqual(field.label, field.LABEL_REPEATED) + self.assertFalse(field.has_options) + + with self.assertRaises(KeyError): + self.pool.FindFieldByName('Does not exist') + + def testFindOneofByName(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix cpp extension to find oneof correctly + # when descriptor pool is using an underlying database. + return + oneof = self.pool.FindOneofByName( + 'google.protobuf.python.internal.Factory2Message.oneof_field') + self.assertEqual(oneof.name, 'oneof_field') + with self.assertRaises(KeyError): + self.pool.FindOneofByName('Does not exist') + + def testFindExtensionByName(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix cpp extension to find extension correctly + # when descriptor pool is using an underlying database. + return + # An extension defined in a message. + extension = self.pool.FindExtensionByName( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + self.assertEqual(extension.name, 'one_more_field') + # An extension defined at file scope. + extension = self.pool.FindExtensionByName( + 'google.protobuf.python.internal.another_field') + self.assertEqual(extension.name, 'another_field') + self.assertEqual(extension.number, 1002) + with self.assertRaises(KeyError): + self.pool.FindFieldByName('Does not exist') + + def testFindAllExtensions(self): + factory1_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + factory2_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + # An extension defined in a message. + one_more_field = factory2_message.extensions_by_name['one_more_field'] + self.pool.AddExtensionDescriptor(one_more_field) + # An extension defined at file scope. + factory_test2 = self.pool.FindFileByName( + 'google/protobuf/internal/factory_test2.proto') + another_field = factory_test2.extensions_by_name['another_field'] + self.pool.AddExtensionDescriptor(another_field) + + extensions = self.pool.FindAllExtensions(factory1_message) + expected_extension_numbers = set([one_more_field, another_field]) + self.assertEqual(expected_extension_numbers, set(extensions)) + # Verify that mutating the returned list does not affect the pool. + extensions.append('unexpected_element') + # Get the extensions again, the returned value does not contain the + # 'unexpected_element'. + extensions = self.pool.FindAllExtensions(factory1_message) + self.assertEqual(expected_extension_numbers, set(extensions)) + + def testFindExtensionByNumber(self): + factory1_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + factory2_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + # An extension defined in a message. + one_more_field = factory2_message.extensions_by_name['one_more_field'] + self.pool.AddExtensionDescriptor(one_more_field) + # An extension defined at file scope. + factory_test2 = self.pool.FindFileByName( + 'google/protobuf/internal/factory_test2.proto') + another_field = factory_test2.extensions_by_name['another_field'] + self.pool.AddExtensionDescriptor(another_field) + + # An extension defined in a message. + extension = self.pool.FindExtensionByNumber(factory1_message, 1001) + self.assertEqual(extension.name, 'one_more_field') + # An extension defined at file scope. + extension = self.pool.FindExtensionByNumber(factory1_message, 1002) + self.assertEqual(extension.name, 'another_field') + with self.assertRaises(KeyError): + extension = self.pool.FindExtensionByNumber(factory1_message, 1234567) + + def testExtensionsAreNotFields(self): + with self.assertRaises(KeyError): + self.pool.FindFieldByName('google.protobuf.python.internal.another_field') + with self.assertRaises(KeyError): + self.pool.FindFieldByName( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + with self.assertRaises(KeyError): + self.pool.FindExtensionByName( + 'google.protobuf.python.internal.Factory1Message.list_value') + + def testFindService(self): + service = self.pool.FindServiceByName('protobuf_unittest.TestService') + self.assertEqual(service.full_name, 'protobuf_unittest.TestService') + with self.assertRaises(KeyError): + self.pool.FindServiceByName('Does not exist') + + def testUserDefinedDB(self): + db = descriptor_database.DescriptorDatabase() + self.pool = descriptor_pool.DescriptorPool(db) + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + self.testFindMessageTypeByName() + + def testAddSerializedFile(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + self.pool = descriptor_pool.DescriptorPool() + self.pool.AddSerializedFile(self.factory_test1_fd.SerializeToString()) + self.pool.AddSerializedFile(self.factory_test2_fd.SerializeToString()) + self.testFindMessageTypeByName() + + + def testEnumDefaultValue(self): + """Test the default value of enums which don't start at zero.""" + def _CheckDefaultValue(file_descriptor): + default_value = (file_descriptor + .message_types_by_name['DescriptorPoolTest1'] + .fields_by_name['nested_enum'] + .default_value) + self.assertEqual(default_value, + descriptor_pool_test1_pb2.DescriptorPoolTest1.BETA) + # First check what the generated descriptor contains. + _CheckDefaultValue(descriptor_pool_test1_pb2.DESCRIPTOR) + # Then check the generated pool. Normally this is the same descriptor. + file_descriptor = symbol_database.Default().pool.FindFileByName( + 'google/protobuf/internal/descriptor_pool_test1.proto') + self.assertIs(file_descriptor, descriptor_pool_test1_pb2.DESCRIPTOR) + _CheckDefaultValue(file_descriptor) + + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + # Then check the dynamic pool and its internal DescriptorDatabase. + descriptor_proto = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(descriptor_proto) + # And do the same check as above + file_descriptor = self.pool.FindFileByName( + 'google/protobuf/internal/descriptor_pool_test1.proto') + _CheckDefaultValue(file_descriptor) + + def testDefaultValueForCustomMessages(self): + """Check the value returned by non-existent fields.""" + def _CheckValueAndType(value, expected_value, expected_type): + self.assertEqual(value, expected_value) + self.assertIsInstance(value, expected_type) + + def _CheckDefaultValues(msg): + try: + int64 = int + except NameError: # Python3 + int64 = int + try: + unicode_type = str + except NameError: # Python3 + unicode_type = str + _CheckValueAndType(msg.optional_int32, 0, int) + _CheckValueAndType(msg.optional_uint64, 0, (int64, int)) + _CheckValueAndType(msg.optional_float, 0, (float, int)) + _CheckValueAndType(msg.optional_double, 0, (float, int)) + _CheckValueAndType(msg.optional_bool, False, bool) + _CheckValueAndType(msg.optional_string, '', unicode_type) + _CheckValueAndType(msg.optional_bytes, b'', bytes) + _CheckValueAndType(msg.optional_nested_enum, msg.FOO, int) + # First for the generated message + _CheckDefaultValues(unittest_pb2.TestAllTypes()) + # Then for a message built with from the DescriptorPool. + pool = descriptor_pool.DescriptorPool() + pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) + pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_pb2.DESCRIPTOR.serialized_pb)) + pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb)) + message_class = message_factory.MessageFactory(pool).GetPrototype( + pool.FindMessageTypeByName( + unittest_pb2.TestAllTypes.DESCRIPTOR.full_name)) + _CheckDefaultValues(message_class()) + + def testAddFileDescriptor(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto') + self.pool.Add(file_desc) + self.pool.AddSerializedFile(file_desc.SerializeToString()) + + def testComplexNesting(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString( + more_messages_pb2.DESCRIPTOR.serialized_pb) + test1_desc = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) + test2_desc = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(more_messages_desc) + self.pool.Add(test1_desc) + self.pool.Add(test2_desc) + TEST1_FILE.CheckFile(self, self.pool) + TEST2_FILE.CheckFile(self, self.pool) + + def testConflictRegister(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + unittest_fd = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + conflict_fd = copy.deepcopy(unittest_fd) + conflict_fd.name = 'other_file' + if api_implementation.Type() == 'cpp': + try: + self.pool.Add(unittest_fd) + self.pool.Add(conflict_fd) + except TypeError: + pass + else: + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + pool = copy.deepcopy(self.pool) + # No warnings to add the same descriptors. + file_descriptor = unittest_pb2.DESCRIPTOR + pool.AddDescriptor( + file_descriptor.message_types_by_name['TestAllTypes']) + pool.AddEnumDescriptor( + file_descriptor.enum_types_by_name['ForeignEnum']) + pool.AddServiceDescriptor( + file_descriptor.services_by_name['TestService']) + pool.AddExtensionDescriptor( + file_descriptor.extensions_by_name['optional_int32_extension']) + self.assertEqual(len(w), 0) + # Check warnings for conflict descriptors with the same name. + pool.Add(unittest_fd) + pool.Add(conflict_fd) + pool.FindFileByName(unittest_fd.name) + pool.FindFileByName(conflict_fd.name) + self.assertTrue(len(w)) + self.assertIs(w[0].category, RuntimeWarning) + self.assertIn('Conflict register for file "other_file": ', + str(w[0].message)) + self.assertIn('already defined in file ' + '"google/protobuf/unittest.proto"', + str(w[0].message)) + + +class DefaultDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase): + + def setUp(self): + self.pool = descriptor_pool.Default() + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + + def testFindMethods(self): + self.assertIs( + self.pool.FindFileByName('google/protobuf/unittest.proto'), + unittest_pb2.DESCRIPTOR) + self.assertIs( + self.pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'), + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertIs( + self.pool.FindFieldByName( + 'protobuf_unittest.TestAllTypes.optional_int32'), + unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32']) + self.assertIs( + self.pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'), + unittest_pb2.ForeignEnum.DESCRIPTOR) + self.assertIs( + self.pool.FindExtensionByName( + 'protobuf_unittest.optional_int32_extension'), + unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension']) + self.assertIs( + self.pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'), + unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field']) + self.assertIs( + self.pool.FindServiceByName('protobuf_unittest.TestService'), + unittest_pb2.DESCRIPTOR.services_by_name['TestService']) + + +class CreateDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase): + + def setUp(self): + self.pool = descriptor_pool.DescriptorPool() + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(self.factory_test1_fd) + self.pool.Add(self.factory_test2_fd) + + self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) + self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_pb2.DESCRIPTOR.serialized_pb)) + self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb)) + + +class SecondaryDescriptorFromDescriptorDB(DescriptorPoolTestBase, + unittest.TestCase): + + def setUp(self): + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + db = descriptor_database.DescriptorDatabase() + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + db.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) + db.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_pb2.DESCRIPTOR.serialized_pb)) + db.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb)) + self.pool = descriptor_pool.DescriptorPool(descriptor_db=db) + + +class ProtoFile(object): + + def __init__(self, name, package, messages, dependencies=None, + public_dependencies=None): + self.name = name + self.package = package + self.messages = messages + self.dependencies = dependencies or [] + self.public_dependencies = public_dependencies or [] + + def CheckFile(self, test, pool): + file_desc = pool.FindFileByName(self.name) + test.assertEqual(self.name, file_desc.name) + test.assertEqual(self.package, file_desc.package) + dependencies_names = [f.name for f in file_desc.dependencies] + test.assertEqual(self.dependencies, dependencies_names) + public_dependencies_names = [f.name for f in file_desc.public_dependencies] + test.assertEqual(self.public_dependencies, public_dependencies_names) + for name, msg_type in list(self.messages.items()): + msg_type.CheckType(test, None, name, file_desc) + + +class EnumType(object): + + def __init__(self, values): + self.values = values + + def CheckType(self, test, msg_desc, name, file_desc): + enum_desc = msg_desc.enum_types_by_name[name] + test.assertEqual(name, enum_desc.name) + expected_enum_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_enum_full_name, enum_desc.full_name) + test.assertEqual(msg_desc, enum_desc.containing_type) + test.assertEqual(file_desc, enum_desc.file) + for index, (value, number) in enumerate(self.values): + value_desc = enum_desc.values_by_name[value] + test.assertEqual(value, value_desc.name) + test.assertEqual(index, value_desc.index) + test.assertEqual(number, value_desc.number) + test.assertEqual(enum_desc, value_desc.type) + test.assertIn(value, msg_desc.enum_values_by_name) + + +class MessageType(object): + + def __init__(self, type_dict, field_list, is_extendable=False, + extensions=None): + self.type_dict = type_dict + self.field_list = field_list + self.is_extendable = is_extendable + self.extensions = extensions or [] + + def CheckType(self, test, containing_type_desc, name, file_desc): + if containing_type_desc is None: + desc = file_desc.message_types_by_name[name] + expected_full_name = '.'.join([file_desc.package, name]) + else: + desc = containing_type_desc.nested_types_by_name[name] + expected_full_name = '.'.join([containing_type_desc.full_name, name]) + + test.assertEqual(name, desc.name) + test.assertEqual(expected_full_name, desc.full_name) + test.assertEqual(containing_type_desc, desc.containing_type) + test.assertEqual(desc.file, file_desc) + test.assertEqual(self.is_extendable, desc.is_extendable) + for name, subtype in list(self.type_dict.items()): + subtype.CheckType(test, desc, name, file_desc) + + for index, (name, field) in enumerate(self.field_list): + field.CheckField(test, desc, name, index, file_desc) + + for index, (name, field) in enumerate(self.extensions): + field.CheckField(test, desc, name, index, file_desc) + + +class EnumField(object): + + def __init__(self, number, type_name, default_value): + self.number = number + self.type_name = type_name + self.default_value = default_value + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.fields_by_name[name] + enum_desc = msg_desc.enum_types_by_name[self.type_name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_ENUM, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM, + field_desc.cpp_type) + test.assertTrue(field_desc.has_default_value) + test.assertEqual(enum_desc.values_by_name[self.default_value].number, + field_desc.default_value) + test.assertFalse(enum_desc.values_by_name[self.default_value].has_options) + test.assertEqual(msg_desc, field_desc.containing_type) + test.assertEqual(enum_desc, field_desc.enum_type) + test.assertEqual(file_desc, enum_desc.file) + + +class MessageField(object): + + def __init__(self, number, type_name): + self.number = number + self.type_name = type_name + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.fields_by_name[name] + field_type_desc = msg_desc.nested_types_by_name[self.type_name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, + field_desc.cpp_type) + test.assertFalse(field_desc.has_default_value) + test.assertEqual(msg_desc, field_desc.containing_type) + test.assertEqual(field_type_desc, field_desc.message_type) + test.assertEqual(file_desc, field_desc.file) + # TODO(jieluo): Fix python and cpp extension diff for message field + # default value. + if api_implementation.Type() == 'cpp': + test.assertRaises( + NotImplementedError, getattr, field_desc, 'default_value') + + +class StringField(object): + + def __init__(self, number, default_value): + self.number = number + self.default_value = default_value + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.fields_by_name[name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_STRING, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_STRING, + field_desc.cpp_type) + test.assertTrue(field_desc.has_default_value) + test.assertEqual(self.default_value, field_desc.default_value) + test.assertEqual(file_desc, field_desc.file) + + +class ExtensionField(object): + + def __init__(self, number, extended_type): + self.number = number + self.extended_type = extended_type + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.extensions_by_name[name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(index, field_desc.index) + test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, + field_desc.cpp_type) + test.assertFalse(field_desc.has_default_value) + test.assertTrue(field_desc.is_extension) + test.assertEqual(msg_desc, field_desc.extension_scope) + test.assertEqual(msg_desc, field_desc.message_type) + test.assertEqual(self.extended_type, field_desc.containing_type.name) + test.assertEqual(file_desc, field_desc.file) + + +class AddDescriptorTest(unittest.TestCase): + + def _TestMessage(self, prefix): + pool = descriptor_pool.DescriptorPool() + pool.AddDescriptor(unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.TestAllTypes', + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes').full_name) + + # AddDescriptor is not recursive. + with self.assertRaises(KeyError): + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage') + + pool.AddDescriptor(unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.TestAllTypes.NestedMessage', + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name) + + # Files are implicitly also indexed when messages are added. + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileContainingSymbol( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').name) + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testMessage(self): + self._TestMessage('') + self._TestMessage('.') + + def _TestEnum(self, prefix): + pool = descriptor_pool.DescriptorPool() + pool.AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.ForeignEnum', + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.ForeignEnum').full_name) + + # AddEnumDescriptor is not recursive. + with self.assertRaises(KeyError): + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.ForeignEnum.NestedEnum') + + pool.AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.TestAllTypes.NestedEnum', + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) + + # Files are implicitly also indexed when enums are added. + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileContainingSymbol( + prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').name) + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testEnum(self): + self._TestEnum('') + self._TestEnum('.') + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testService(self): + pool = descriptor_pool.DescriptorPool() + with self.assertRaises(KeyError): + pool.FindServiceByName('protobuf_unittest.TestService') + pool.AddServiceDescriptor(unittest_pb2._TESTSERVICE) + self.assertEqual( + 'protobuf_unittest.TestService', + pool.FindServiceByName('protobuf_unittest.TestService').full_name) + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testFile(self): + pool = descriptor_pool.DescriptorPool() + pool.AddFileDescriptor(unittest_pb2.DESCRIPTOR) + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + # AddFileDescriptor is not recursive; messages and enums within files must + # be explicitly registered. + with self.assertRaises(KeyError): + pool.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes') + + def testEmptyDescriptorPool(self): + # Check that an empty DescriptorPool() contains no messages. + pool = descriptor_pool.DescriptorPool() + proto_file_name = descriptor_pb2.DESCRIPTOR.name + self.assertRaises(KeyError, pool.FindFileByName, proto_file_name) + # Add the above file to the pool + file_descriptor = descriptor_pb2.FileDescriptorProto() + descriptor_pb2.DESCRIPTOR.CopyToProto(file_descriptor) + pool.Add(file_descriptor) + # Now it exists. + self.assertTrue(pool.FindFileByName(proto_file_name)) + + def testCustomDescriptorPool(self): + # Create a new pool, and add a file descriptor. + pool = descriptor_pool.DescriptorPool() + file_desc = descriptor_pb2.FileDescriptorProto( + name='some/file.proto', package='package') + file_desc.message_type.add(name='Message') + pool.Add(file_desc) + self.assertEqual(pool.FindFileByName('some/file.proto').name, + 'some/file.proto') + self.assertEqual(pool.FindMessageTypeByName('package.Message').name, + 'Message') + # Test no package + file_proto = descriptor_pb2.FileDescriptorProto( + name='some/filename/container.proto') + message_proto = file_proto.message_type.add( + name='TopMessage') + message_proto.field.add( + name='bb', + number=1, + type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, + label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) + enum_proto = file_proto.enum_type.add(name='TopEnum') + enum_proto.value.add(name='FOREIGN_FOO', number=4) + file_proto.service.add(name='TopService') + pool = descriptor_pool.DescriptorPool() + pool.Add(file_proto) + self.assertEqual('TopMessage', + pool.FindMessageTypeByName('TopMessage').name) + self.assertEqual('TopEnum', pool.FindEnumTypeByName('TopEnum').name) + self.assertEqual('TopService', pool.FindServiceByName('TopService').name) + + def testFileDescriptorOptionsWithCustomDescriptorPool(self): + # Create a descriptor pool, and add a new FileDescriptorProto to it. + pool = descriptor_pool.DescriptorPool() + file_name = 'file_descriptor_options_with_custom_descriptor_pool.proto' + file_descriptor_proto = descriptor_pb2.FileDescriptorProto(name=file_name) + extension_id = file_options_test_pb2.foo_options + file_descriptor_proto.options.Extensions[extension_id].foo_name = 'foo' + pool.Add(file_descriptor_proto) + # The options set on the FileDescriptorProto should be available in the + # descriptor even if they contain extensions that cannot be deserialized + # using the pool. + file_descriptor = pool.FindFileByName(file_name) + options = file_descriptor.GetOptions() + self.assertEqual('foo', options.Extensions[extension_id].foo_name) + # The object returned by GetOptions() is cached. + self.assertIs(options, file_descriptor.GetOptions()) + + def testAddTypeError(self): + pool = descriptor_pool.DescriptorPool() + with self.assertRaises(TypeError): + pool.AddDescriptor(0) + with self.assertRaises(TypeError): + pool.AddEnumDescriptor(0) + with self.assertRaises(TypeError): + pool.AddServiceDescriptor(0) + with self.assertRaises(TypeError): + pool.AddExtensionDescriptor(0) + with self.assertRaises(TypeError): + pool.AddFileDescriptor(0) + + +TEST1_FILE = ProtoFile( + 'google/protobuf/internal/descriptor_pool_test1.proto', + 'google.protobuf.python.internal', + { + 'DescriptorPoolTest1': MessageType({ + 'NestedEnum': EnumType([('ALPHA', 1), ('BETA', 2)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('EPSILON', 5), ('ZETA', 6)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('ETA', 7), ('THETA', 8)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'ETA')), + ('nested_field', StringField(2, 'theta')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'ZETA')), + ('nested_field', StringField(2, 'beta')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'BETA')), + ('nested_message', MessageField(2, 'NestedMessage')), + ], is_extendable=True), + + 'DescriptorPoolTest2': MessageType({ + 'NestedEnum': EnumType([('GAMMA', 3), ('DELTA', 4)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('IOTA', 9), ('KAPPA', 10)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('LAMBDA', 11), ('MU', 12)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'MU')), + ('nested_field', StringField(2, 'lambda')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'IOTA')), + ('nested_field', StringField(2, 'delta')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'GAMMA')), + ('nested_message', MessageField(2, 'NestedMessage')), + ]), + }) + + +TEST2_FILE = ProtoFile( + 'google/protobuf/internal/descriptor_pool_test2.proto', + 'google.protobuf.python.internal', + { + 'DescriptorPoolTest3': MessageType({ + 'NestedEnum': EnumType([('NU', 13), ('XI', 14)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')), + ('nested_field', StringField(2, 'sigma')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'PI')), + ('nested_field', StringField(2, 'nu')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'XI')), + ('nested_message', MessageField(2, 'NestedMessage')), + ], extensions=[ + ('descriptor_pool_test', + ExtensionField(1001, 'DescriptorPoolTest1')), + ]), + }, + dependencies=['google/protobuf/internal/descriptor_pool_test1.proto', + 'google/protobuf/internal/more_messages.proto'], + public_dependencies=['google/protobuf/internal/more_messages.proto']) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py new file mode 100644 index 0000000..56835ea --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py @@ -0,0 +1,474 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/descriptor_pool_test1.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/descriptor_pool_test1.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n4google/protobuf/internal/descriptor_pool_test1.proto\x12\x1fgoogle.protobuf.python.internal\"\xfb\x05\n\x13\x44\x65scriptorPoolTest1\x12Z\n\x0bnested_enum\x18\x01 \x01(\x0e\x32?.google.protobuf.python.internal.DescriptorPoolTest1.NestedEnum:\x04\x42\x45TA\x12Z\n\x0enested_message\x18\x02 \x01(\x0b\x32\x42.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage\x1a\xfd\x03\n\rNestedMessage\x12h\n\x0bnested_enum\x18\x01 \x01(\x0e\x32M.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.NestedEnum:\x04ZETA\x12\x1a\n\x0cnested_field\x18\x02 \x01(\t:\x04\x62\x65ta\x12q\n\x13\x64\x65\x65p_nested_message\x18\x03 \x01(\x0b\x32T.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage\x1a\xcd\x01\n\x11\x44\x65\x65pNestedMessage\x12y\n\x0bnested_enum\x18\x01 \x01(\x0e\x32_.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.NestedEnum:\x03\x45TA\x12\x1b\n\x0cnested_field\x18\x02 \x01(\t:\x05theta\" \n\nNestedEnum\x12\x07\n\x03\x45TA\x10\x07\x12\t\n\x05THETA\x10\x08\"#\n\nNestedEnum\x12\x0b\n\x07\x45PSILON\x10\x05\x12\x08\n\x04ZETA\x10\x06\"!\n\nNestedEnum\x12\t\n\x05\x41LPHA\x10\x01\x12\x08\n\x04\x42\x45TA\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xf1\x05\n\x13\x44\x65scriptorPoolTest2\x12[\n\x0bnested_enum\x18\x01 \x01(\x0e\x32?.google.protobuf.python.internal.DescriptorPoolTest2.NestedEnum:\x05GAMMA\x12Z\n\x0enested_message\x18\x02 \x01(\x0b\x32\x42.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage\x1a\xfc\x03\n\rNestedMessage\x12h\n\x0bnested_enum\x18\x01 \x01(\x0e\x32M.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.NestedEnum:\x04IOTA\x12\x1b\n\x0cnested_field\x18\x02 \x01(\t:\x05\x64\x65lta\x12q\n\x13\x64\x65\x65p_nested_message\x18\x03 \x01(\x0b\x32T.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage\x1a\xcd\x01\n\x11\x44\x65\x65pNestedMessage\x12x\n\x0bnested_enum\x18\x01 \x01(\x0e\x32_.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.NestedEnum:\x02MU\x12\x1c\n\x0cnested_field\x18\x02 \x01(\t:\x06lambda\" \n\nNestedEnum\x12\n\n\x06LAMBDA\x10\x0b\x12\x06\n\x02MU\x10\x0c\"!\n\nNestedEnum\x12\x08\n\x04IOTA\x10\t\x12\t\n\x05KAPPA\x10\n\"\"\n\nNestedEnum\x12\t\n\x05GAMMA\x10\x03\x12\t\n\x05\x44\x45LTA\x10\x04') +) + + + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ETA', index=0, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='THETA', index=1, number=8, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=738, + serialized_end=770, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='EPSILON', index=0, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ZETA', index=1, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=772, + serialized_end=807, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST1_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ALPHA', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BETA', index=1, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=809, + serialized_end=842, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST1_NESTEDENUM) + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LAMBDA', index=0, number=11, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MU', index=1, number=12, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1506, + serialized_end=1538, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IOTA', index=0, number=9, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='KAPPA', index=1, number=10, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1540, + serialized_end=1573, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST2_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='GAMMA', index=0, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DELTA', index=1, number=4, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1575, + serialized_end=1609, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST2_NESTEDENUM) + + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE = _descriptor.Descriptor( + name='DeepNestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("theta").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=565, + serialized_end=770, +) + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=6, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("beta").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deep_nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.deep_nested_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=298, + serialized_end=807, +) + +_DESCRIPTORPOOLTEST1 = _descriptor.Descriptor( + name='DescriptorPoolTest1', + full_name='google.protobuf.python.internal.DescriptorPoolTest1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest1.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest1.nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST1_NESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST1_NESTEDENUM, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=90, + serialized_end=853, +) + + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE = _descriptor.Descriptor( + name='DeepNestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=12, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("lambda").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1333, + serialized_end=1538, +) + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=9, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("delta").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deep_nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.deep_nested_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1065, + serialized_end=1573, +) + +_DESCRIPTORPOOLTEST2 = _descriptor.Descriptor( + name='DescriptorPoolTest2', + full_name='google.protobuf.python.internal.DescriptorPoolTest2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest2.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=3, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest2.nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST2_NESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST2_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=856, + serialized_end=1609, +) + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE.fields_by_name['deep_nested_message'].message_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST1 +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE +_DESCRIPTORPOOLTEST1.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST1_NESTEDENUM +_DESCRIPTORPOOLTEST1.fields_by_name['nested_message'].message_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST1 +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE.fields_by_name['deep_nested_message'].message_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST2 +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE +_DESCRIPTORPOOLTEST2.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST2_NESTEDENUM +_DESCRIPTORPOOLTEST2.fields_by_name['nested_message'].message_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST2 +DESCRIPTOR.message_types_by_name['DescriptorPoolTest1'] = _DESCRIPTORPOOLTEST1 +DESCRIPTOR.message_types_by_name['DescriptorPoolTest2'] = _DESCRIPTORPOOLTEST2 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DescriptorPoolTest1 = _reflection.GeneratedProtocolMessageType('DescriptorPoolTest1', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + + DeepNestedMessage = _reflection.GeneratedProtocolMessageType('DeepNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST1, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest1) + )) +_sym_db.RegisterMessage(DescriptorPoolTest1) +_sym_db.RegisterMessage(DescriptorPoolTest1.NestedMessage) +_sym_db.RegisterMessage(DescriptorPoolTest1.NestedMessage.DeepNestedMessage) + +DescriptorPoolTest2 = _reflection.GeneratedProtocolMessageType('DescriptorPoolTest2', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + + DeepNestedMessage = _reflection.GeneratedProtocolMessageType('DeepNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST2, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest2) + )) +_sym_db.RegisterMessage(DescriptorPoolTest2) +_sym_db.RegisterMessage(DescriptorPoolTest2.NestedMessage) +_sym_db.RegisterMessage(DescriptorPoolTest2.NestedMessage.DeepNestedMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py new file mode 100644 index 0000000..cfc8920 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py @@ -0,0 +1,266 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/descriptor_pool_test2.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf.internal import descriptor_pool_test1_pb2 as google_dot_protobuf_dot_internal_dot_descriptor__pool__test1__pb2 +from google.protobuf.internal import more_messages_pb2 as google_dot_protobuf_dot_internal_dot_more__messages__pb2 + +from google.protobuf.internal.more_messages_pb2 import * + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/descriptor_pool_test2.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n4google/protobuf/internal/descriptor_pool_test2.proto\x12\x1fgoogle.protobuf.python.internal\x1a\x34google/protobuf/internal/descriptor_pool_test1.proto\x1a,google/protobuf/internal/more_messages.proto\"\xef\x06\n\x13\x44\x65scriptorPoolTest3\x12X\n\x0bnested_enum\x18\x01 \x01(\x0e\x32?.google.protobuf.python.internal.DescriptorPoolTest3.NestedEnum:\x02XI\x12Z\n\x0enested_message\x18\x02 \x01(\x0b\x32\x42.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage\x1a\xf7\x03\n\rNestedMessage\x12\x66\n\x0bnested_enum\x18\x01 \x01(\x0e\x32M.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.NestedEnum:\x02PI\x12\x18\n\x0cnested_field\x18\x02 \x01(\t:\x02nu\x12q\n\x13\x64\x65\x65p_nested_message\x18\x03 \x01(\x0b\x32T.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage\x1a\xcd\x01\n\x11\x44\x65\x65pNestedMessage\x12y\n\x0bnested_enum\x18\x01 \x01(\x0e\x32_.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.NestedEnum:\x03RHO\x12\x1b\n\x0cnested_field\x18\x02 \x01(\t:\x05sigma\" \n\nNestedEnum\x12\x07\n\x03RHO\x10\x11\x12\t\n\x05SIGMA\x10\x12\"!\n\nNestedEnum\x12\x0b\n\x07OMICRON\x10\x0f\x12\x06\n\x02PI\x10\x10\"\x1c\n\nNestedEnum\x12\x06\n\x02NU\x10\r\x12\x06\n\x02XI\x10\x0e\x32\x89\x01\n\x14\x64\x65scriptor_pool_test\x12\x34.google.protobuf.python.internal.DescriptorPoolTest1\x18\xe9\x07 \x01(\x0b\x32\x34.google.protobuf.python.internal.DescriptorPoolTest3P\x01') + , + dependencies=[google_dot_protobuf_dot_internal_dot_descriptor__pool__test1__pb2.DESCRIPTOR,google_dot_protobuf_dot_internal_dot_more__messages__pb2.DESCRIPTOR,], + public_dependencies=[google_dot_protobuf_dot_internal_dot_more__messages__pb2.DESCRIPTOR,]) + + + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='RHO', index=0, number=17, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SIGMA', index=1, number=18, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=832, + serialized_end=864, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OMICRON', index=0, number=15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='PI', index=1, number=16, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=866, + serialized_end=899, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST3_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NU', index=0, number=13, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='XI', index=1, number=14, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=901, + serialized_end=929, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST3_NESTEDENUM) + + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE = _descriptor.Descriptor( + name='DeepNestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=17, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("sigma").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=659, + serialized_end=864, +) + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=16, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("nu").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deep_nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.deep_nested_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=396, + serialized_end=899, +) + +_DESCRIPTORPOOLTEST3 = _descriptor.Descriptor( + name='DescriptorPoolTest3', + full_name='google.protobuf.python.internal.DescriptorPoolTest3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest3.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=14, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest3.nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='descriptor_pool_test', full_name='google.protobuf.python.internal.DescriptorPoolTest3.descriptor_pool_test', index=0, + number=1001, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_DESCRIPTORPOOLTEST3_NESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST3_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=190, + serialized_end=1069, +) + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE.fields_by_name['deep_nested_message'].message_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST3 +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE +_DESCRIPTORPOOLTEST3.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST3_NESTEDENUM +_DESCRIPTORPOOLTEST3.fields_by_name['nested_message'].message_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST3 +DESCRIPTOR.message_types_by_name['DescriptorPoolTest3'] = _DESCRIPTORPOOLTEST3 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DescriptorPoolTest3 = _reflection.GeneratedProtocolMessageType('DescriptorPoolTest3', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + + DeepNestedMessage = _reflection.GeneratedProtocolMessageType('DeepNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST3, + __module__ = 'google.protobuf.internal.descriptor_pool_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest3) + )) +_sym_db.RegisterMessage(DescriptorPoolTest3) +_sym_db.RegisterMessage(DescriptorPoolTest3.NestedMessage) +_sym_db.RegisterMessage(DescriptorPoolTest3.NestedMessage.DeepNestedMessage) + +_DESCRIPTORPOOLTEST3.extensions_by_name['descriptor_pool_test'].message_type = _DESCRIPTORPOOLTEST3 +google_dot_protobuf_dot_internal_dot_descriptor__pool__test1__pb2.DescriptorPoolTest1.RegisterExtension(_DESCRIPTORPOOLTEST3.extensions_by_name['descriptor_pool_test']) + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_test.py new file mode 100644 index 0000000..a4fafce --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/descriptor_test.py @@ -0,0 +1,1036 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Unittest for google.protobuf.internal.descriptor.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import sys + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import unittest_custom_options_pb2 +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import test_util +from google.protobuf import descriptor +from google.protobuf import descriptor_pool +from google.protobuf import symbol_database +from google.protobuf import text_format + + +TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """ +name: 'TestEmptyMessage' +""" + + +class DescriptorTest(unittest.TestCase): + + def setUp(self): + file_proto = descriptor_pb2.FileDescriptorProto( + name='some/filename/some.proto', + package='protobuf_unittest') + message_proto = file_proto.message_type.add( + name='NestedMessage') + message_proto.field.add( + name='bb', + number=1, + type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, + label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) + enum_proto = message_proto.enum_type.add( + name='ForeignEnum') + enum_proto.value.add(name='FOREIGN_FOO', number=4) + enum_proto.value.add(name='FOREIGN_BAR', number=5) + enum_proto.value.add(name='FOREIGN_BAZ', number=6) + + file_proto.message_type.add(name='ResponseMessage') + service_proto = file_proto.service.add( + name='Service') + method_proto = service_proto.method.add( + name='CallMethod', + input_type='.protobuf_unittest.NestedMessage', + output_type='.protobuf_unittest.ResponseMessage') + + # Note: Calling DescriptorPool.Add() multiple times with the same file only + # works if the input is canonical; in particular, all type names must be + # fully qualified. + self.pool = self.GetDescriptorPool() + self.pool.Add(file_proto) + self.my_file = self.pool.FindFileByName(file_proto.name) + self.my_message = self.my_file.message_types_by_name[message_proto.name] + self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] + self.my_service = self.my_file.services_by_name[service_proto.name] + self.my_method = self.my_service.methods_by_name[method_proto.name] + + def GetDescriptorPool(self): + return symbol_database.Default().pool + + def testEnumValueName(self): + self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), + 'FOREIGN_FOO') + + self.assertEqual( + self.my_message.enum_types_by_name[ + 'ForeignEnum'].values_by_number[4].name, + self.my_message.EnumValueName('ForeignEnum', 4)) + with self.assertRaises(KeyError): + self.my_message.EnumValueName('ForeignEnum', 999) + with self.assertRaises(KeyError): + self.my_message.EnumValueName('NoneEnum', 999) + with self.assertRaises(TypeError): + self.my_message.EnumValueName() + + def testEnumFixups(self): + self.assertEqual(self.my_enum, self.my_enum.values[0].type) + + def testContainingTypeFixups(self): + self.assertEqual(self.my_message, self.my_message.fields[0].containing_type) + self.assertEqual(self.my_message, self.my_enum.containing_type) + + def testContainingServiceFixups(self): + self.assertEqual(self.my_service, self.my_method.containing_service) + + def testGetOptions(self): + self.assertEqual(self.my_enum.GetOptions(), + descriptor_pb2.EnumOptions()) + self.assertEqual(self.my_enum.values[0].GetOptions(), + descriptor_pb2.EnumValueOptions()) + self.assertEqual(self.my_message.GetOptions(), + descriptor_pb2.MessageOptions()) + self.assertEqual(self.my_message.fields[0].GetOptions(), + descriptor_pb2.FieldOptions()) + self.assertEqual(self.my_method.GetOptions(), + descriptor_pb2.MethodOptions()) + self.assertEqual(self.my_service.GetOptions(), + descriptor_pb2.ServiceOptions()) + + def testSimpleCustomOptions(self): + file_descriptor = unittest_custom_options_pb2.DESCRIPTOR + message_descriptor = (unittest_custom_options_pb2. + TestMessageWithCustomOptions.DESCRIPTOR) + field_descriptor = message_descriptor.fields_by_name['field1'] + oneof_descriptor = message_descriptor.oneofs_by_name['AnOneof'] + enum_descriptor = message_descriptor.enum_types_by_name['AnEnum'] + enum_value_descriptor = (message_descriptor. + enum_values_by_name['ANENUM_VAL2']) + other_enum_value_descriptor = (message_descriptor. + enum_values_by_name['ANENUM_VAL1']) + service_descriptor = (unittest_custom_options_pb2. + TestServiceWithCustomOptions.DESCRIPTOR) + method_descriptor = service_descriptor.FindMethodByName('Foo') + + file_options = file_descriptor.GetOptions() + file_opt1 = unittest_custom_options_pb2.file_opt1 + self.assertEqual(9876543210, file_options.Extensions[file_opt1]) + message_options = message_descriptor.GetOptions() + message_opt1 = unittest_custom_options_pb2.message_opt1 + self.assertEqual(-56, message_options.Extensions[message_opt1]) + field_options = field_descriptor.GetOptions() + field_opt1 = unittest_custom_options_pb2.field_opt1 + self.assertEqual(8765432109, field_options.Extensions[field_opt1]) + field_opt2 = unittest_custom_options_pb2.field_opt2 + self.assertEqual(42, field_options.Extensions[field_opt2]) + oneof_options = oneof_descriptor.GetOptions() + oneof_opt1 = unittest_custom_options_pb2.oneof_opt1 + self.assertEqual(-99, oneof_options.Extensions[oneof_opt1]) + enum_options = enum_descriptor.GetOptions() + enum_opt1 = unittest_custom_options_pb2.enum_opt1 + self.assertEqual(-789, enum_options.Extensions[enum_opt1]) + enum_value_options = enum_value_descriptor.GetOptions() + enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1 + self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1]) + + service_options = service_descriptor.GetOptions() + service_opt1 = unittest_custom_options_pb2.service_opt1 + self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) + method_options = method_descriptor.GetOptions() + method_opt1 = unittest_custom_options_pb2.method_opt1 + self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, + method_options.Extensions[method_opt1]) + + message_descriptor = ( + unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) + self.assertTrue(file_descriptor.has_options) + self.assertFalse(message_descriptor.has_options) + self.assertTrue(field_descriptor.has_options) + self.assertTrue(oneof_descriptor.has_options) + self.assertTrue(enum_descriptor.has_options) + self.assertTrue(enum_value_descriptor.has_options) + self.assertFalse(other_enum_value_descriptor.has_options) + + def testDifferentCustomOptionTypes(self): + kint32min = -2**31 + kint64min = -2**63 + kint32max = 2**31 - 1 + kint64max = 2**63 - 1 + kuint32max = 2**32 - 1 + kuint64max = 2**64 - 1 + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(False, message_options.Extensions[ + unittest_custom_options_pb2.bool_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.int64_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.uint32_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.uint64_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.sint32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.sint64_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.fixed32_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.fixed64_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.sfixed32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.sfixed64_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(True, message_options.Extensions[ + unittest_custom_options_pb2.bool_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.int64_opt]) + self.assertEqual(kuint32max, message_options.Extensions[ + unittest_custom_options_pb2.uint32_opt]) + self.assertEqual(kuint64max, message_options.Extensions[ + unittest_custom_options_pb2.uint64_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.sint32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.sint64_opt]) + self.assertEqual(kuint32max, message_options.Extensions[ + unittest_custom_options_pb2.fixed32_opt]) + self.assertEqual(kuint64max, message_options.Extensions[ + unittest_custom_options_pb2.fixed64_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.sfixed32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.sfixed64_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(-100, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertAlmostEqual(12.3456789, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + self.assertEqual("Hello, \"World\"", message_options.Extensions[ + unittest_custom_options_pb2.string_opt]) + self.assertEqual(b"Hello\0World", message_options.Extensions[ + unittest_custom_options_pb2.bytes_opt]) + dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum + self.assertEqual( + dummy_enum.TEST_OPTION_ENUM_TYPE2, + message_options.Extensions[unittest_custom_options_pb2.enum_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertAlmostEqual(12, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(154, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertAlmostEqual(-12, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(-154, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + + def testComplexExtensionOptions(self): + descriptor =\ + unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR + options = descriptor.GetOptions() + self.assertEqual(42, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].foo) + self.assertEqual(324, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(876, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(987, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].baz) + self.assertEqual(654, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.grault]) + self.assertEqual(743, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.foo) + self.assertEqual(1999, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(2008, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(741, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].foo) + self.assertEqual(1998, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(2121, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(1971, options.Extensions[ + unittest_custom_options_pb2.ComplexOptionType2 + .ComplexOptionType4.complex_opt4].waldo) + self.assertEqual(321, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].fred.waldo) + self.assertEqual(9, options.Extensions[ + unittest_custom_options_pb2.complex_opt3].qux) + self.assertEqual(22, options.Extensions[ + unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh) + self.assertEqual(24, options.Extensions[ + unittest_custom_options_pb2.complexopt6].xyzzy) + + # Check that aggregate options were parsed and saved correctly in + # the appropriate descriptors. + def testAggregateOptions(self): + file_descriptor = unittest_custom_options_pb2.DESCRIPTOR + message_descriptor =\ + unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR + field_descriptor = message_descriptor.fields_by_name["fieldname"] + enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR + enum_value_descriptor = enum_descriptor.values_by_name["VALUE"] + service_descriptor =\ + unittest_custom_options_pb2.AggregateService.DESCRIPTOR + method_descriptor = service_descriptor.FindMethodByName("Method") + + # Tests for the different types of data embedded in fileopt + file_options = file_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.fileopt] + self.assertEqual(100, file_options.i) + self.assertEqual("FileAnnotation", file_options.s) + self.assertEqual("NestedFileAnnotation", file_options.sub.s) + self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[ + unittest_custom_options_pb2.fileopt].s) + self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[ + unittest_custom_options_pb2.AggregateMessageSetElement + .message_set_extension].s) + + # Simple tests for all the other types of annotations + self.assertEqual( + "MessageAnnotation", + message_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.msgopt].s) + self.assertEqual( + "FieldAnnotation", + field_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.fieldopt].s) + self.assertEqual( + "EnumAnnotation", + enum_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.enumopt].s) + self.assertEqual( + "EnumValueAnnotation", + enum_value_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.enumvalopt].s) + self.assertEqual( + "ServiceAnnotation", + service_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.serviceopt].s) + self.assertEqual( + "MethodAnnotation", + method_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.methodopt].s) + + def testNestedOptions(self): + nested_message =\ + unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR + self.assertEqual(1001, nested_message.GetOptions().Extensions[ + unittest_custom_options_pb2.message_opt1]) + nested_field = nested_message.fields_by_name["nested_field"] + self.assertEqual(1002, nested_field.GetOptions().Extensions[ + unittest_custom_options_pb2.field_opt1]) + outer_message =\ + unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR + nested_enum = outer_message.enum_types_by_name["NestedEnum"] + self.assertEqual(1003, nested_enum.GetOptions().Extensions[ + unittest_custom_options_pb2.enum_opt1]) + nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"] + self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[ + unittest_custom_options_pb2.enum_value_opt1]) + nested_extension = outer_message.extensions_by_name["nested_extension"] + self.assertEqual(1005, nested_extension.GetOptions().Extensions[ + unittest_custom_options_pb2.field_opt2]) + + def testFileDescriptorReferences(self): + self.assertEqual(self.my_enum.file, self.my_file) + self.assertEqual(self.my_message.file, self.my_file) + + def testFileDescriptor(self): + self.assertEqual(self.my_file.name, 'some/filename/some.proto') + self.assertEqual(self.my_file.package, 'protobuf_unittest') + self.assertEqual(self.my_file.pool, self.pool) + self.assertFalse(self.my_file.has_options) + self.assertEqual('proto2', self.my_file.syntax) + file_proto = descriptor_pb2.FileDescriptorProto() + self.my_file.CopyToProto(file_proto) + self.assertEqual(self.my_file.serialized_pb, + file_proto.SerializeToString()) + # Generated modules also belong to the default pool. + self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default()) + + @unittest.skipIf( + api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, + 'Immutability of descriptors is only enforced in v2 implementation') + def testImmutableCppDescriptor(self): + file_descriptor = unittest_pb2.DESCRIPTOR + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + field_descriptor = message_descriptor.fields_by_name['optional_int32'] + enum_descriptor = message_descriptor.enum_types_by_name['NestedEnum'] + oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] + with self.assertRaises(AttributeError): + message_descriptor.fields_by_name = None + with self.assertRaises(TypeError): + message_descriptor.fields_by_name['Another'] = None + with self.assertRaises(TypeError): + message_descriptor.fields.append(None) + with self.assertRaises(AttributeError): + field_descriptor.containing_type = message_descriptor + with self.assertRaises(AttributeError): + file_descriptor.has_options = False + with self.assertRaises(AttributeError): + field_descriptor.has_options = False + with self.assertRaises(AttributeError): + oneof_descriptor.has_options = False + with self.assertRaises(AttributeError): + enum_descriptor.has_options = False + with self.assertRaises(AttributeError) as e: + message_descriptor.has_options = True + self.assertEqual('attribute is not writable: has_options', + str(e.exception)) + + +class NewDescriptorTest(DescriptorTest): + """Redo the same tests as above, but with a separate DescriptorPool.""" + + def GetDescriptorPool(self): + return descriptor_pool.DescriptorPool() + + +class GeneratedDescriptorTest(unittest.TestCase): + """Tests for the properties of descriptors in generated code.""" + + def CheckMessageDescriptor(self, message_descriptor): + # Basic properties + self.assertEqual(message_descriptor.name, 'TestAllTypes') + self.assertEqual(message_descriptor.full_name, + 'protobuf_unittest.TestAllTypes') + # Test equality and hashability + self.assertEqual(message_descriptor, message_descriptor) + self.assertEqual(message_descriptor.fields[0].containing_type, + message_descriptor) + self.assertIn(message_descriptor, [message_descriptor]) + self.assertIn(message_descriptor, {message_descriptor: None}) + # Test field containers + self.CheckDescriptorSequence(message_descriptor.fields) + self.CheckDescriptorMapping(message_descriptor.fields_by_name) + self.CheckDescriptorMapping(message_descriptor.fields_by_number) + self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name) + self.CheckDescriptorMapping(message_descriptor.enum_types_by_name) + self.CheckDescriptorMapping(message_descriptor.enum_values_by_name) + self.CheckDescriptorMapping(message_descriptor.oneofs_by_name) + self.CheckDescriptorMapping(message_descriptor.enum_types[0].values_by_name) + # Test extension range + self.assertEqual(message_descriptor.extension_ranges, []) + + def CheckFieldDescriptor(self, field_descriptor): + # Basic properties + self.assertEqual(field_descriptor.name, 'optional_int32') + self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32') + self.assertEqual(field_descriptor.full_name, + 'protobuf_unittest.TestAllTypes.optional_int32') + self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') + self.assertEqual(field_descriptor.file, unittest_pb2.DESCRIPTOR) + # Test equality and hashability + self.assertEqual(field_descriptor, field_descriptor) + self.assertEqual( + field_descriptor.containing_type.fields_by_name['optional_int32'], + field_descriptor) + self.assertEqual( + field_descriptor.containing_type.fields_by_camelcase_name[ + 'optionalInt32'], + field_descriptor) + self.assertIn(field_descriptor, [field_descriptor]) + self.assertIn(field_descriptor, {field_descriptor: None}) + self.assertEqual(None, field_descriptor.extension_scope) + self.assertEqual(None, field_descriptor.enum_type) + if api_implementation.Type() == 'cpp': + # For test coverage only + self.assertEqual(field_descriptor.id, field_descriptor.id) + + def CheckDescriptorSequence(self, sequence): + # Verifies that a property like 'messageDescriptor.fields' has all the + # properties of an immutable abc.Sequence. + self.assertNotEqual(sequence, + unittest_pb2.TestAllExtensions.DESCRIPTOR.fields) + self.assertNotEqual(sequence, []) + self.assertNotEqual(sequence, 1) + self.assertFalse(sequence == 1) # Only for cpp test coverage + self.assertEqual(sequence, sequence) + expected_list = list(sequence) + self.assertEqual(expected_list, sequence) + self.assertGreater(len(sequence), 0) # Sized + self.assertEqual(len(sequence), len(expected_list)) # Iterable + self.assertEqual(sequence[len(sequence) -1], sequence[-1]) + item = sequence[0] + self.assertEqual(item, sequence[0]) + self.assertIn(item, sequence) # Container + self.assertEqual(sequence.index(item), 0) + self.assertEqual(sequence.count(item), 1) + other_item = unittest_pb2.NestedTestAllTypes.DESCRIPTOR.fields[0] + self.assertNotIn(other_item, sequence) + self.assertEqual(sequence.count(other_item), 0) + self.assertRaises(ValueError, sequence.index, other_item) + self.assertRaises(ValueError, sequence.index, []) + reversed_iterator = reversed(sequence) + self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) + self.assertRaises(StopIteration, next, reversed_iterator) + expected_list[0] = 'change value' + self.assertNotEqual(expected_list, sequence) + # TODO(jieluo): Change __repr__ support for DescriptorSequence. + if api_implementation.Type() == 'python': + self.assertEqual(str(list(sequence)), str(sequence)) + else: + self.assertEqual(str(sequence)[0], '<') + + def CheckDescriptorMapping(self, mapping): + # Verifies that a property like 'messageDescriptor.fields' has all the + # properties of an immutable abc.Mapping. + self.assertNotEqual( + mapping, unittest_pb2.TestAllExtensions.DESCRIPTOR.fields_by_name) + self.assertNotEqual(mapping, {}) + self.assertNotEqual(mapping, 1) + self.assertFalse(mapping == 1) # Only for cpp test coverage + excepted_dict = dict(list(mapping.items())) + self.assertEqual(mapping, excepted_dict) + self.assertEqual(mapping, mapping) + self.assertGreater(len(mapping), 0) # Sized + self.assertEqual(len(mapping), len(excepted_dict)) # Iterable + if sys.version_info >= (3,): + key, item = next(iter(list(mapping.items()))) + else: + key, item = list(mapping.items())[0] + self.assertIn(key, mapping) # Container + self.assertEqual(mapping.get(key), item) + with self.assertRaises(TypeError): + mapping.get() + # TODO(jieluo): Fix python and cpp extension diff. + if api_implementation.Type() == 'python': + self.assertRaises(TypeError, mapping.get, []) + else: + self.assertEqual(None, mapping.get([])) + # keys(), iterkeys() &co + item = (next(iter(list(mapping.keys()))), next(iter(list(mapping.values())))) + self.assertEqual(item, next(iter(list(mapping.items())))) + if sys.version_info < (3,): + def CheckItems(seq, iterator): + self.assertEqual(next(iterator), seq[0]) + self.assertEqual(list(iterator), seq[1:]) + CheckItems(list(mapping.keys()), iter(mapping.keys())) + CheckItems(list(mapping.values()), iter(mapping.values())) + CheckItems(list(mapping.items()), iter(mapping.items())) + excepted_dict[key] = 'change value' + self.assertNotEqual(mapping, excepted_dict) + del excepted_dict[key] + excepted_dict['new_key'] = 'new' + self.assertNotEqual(mapping, excepted_dict) + self.assertRaises(KeyError, mapping.__getitem__, 'key_error') + self.assertRaises(KeyError, mapping.__getitem__, len(mapping) + 1) + # TODO(jieluo): Add __repr__ support for DescriptorMapping. + if api_implementation.Type() == 'python': + self.assertEqual(len(str(dict(list(mapping.items())))), len(str(mapping))) + else: + self.assertEqual(str(mapping)[0], '<') + + def testDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.CheckMessageDescriptor(message_descriptor) + field_descriptor = message_descriptor.fields_by_name['optional_int32'] + self.CheckFieldDescriptor(field_descriptor) + field_descriptor = message_descriptor.fields_by_camelcase_name[ + 'optionalInt32'] + self.CheckFieldDescriptor(field_descriptor) + enum_descriptor = unittest_pb2.DESCRIPTOR.enum_types_by_name[ + 'ForeignEnum'] + self.assertEqual(None, enum_descriptor.containing_type) + # Test extension range + self.assertEqual( + unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, + [(1, 536870912)]) + self.assertEqual( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, + [(42, 43), (4143, 4244), (65536, 536870912)]) + + def testCppDescriptorContainer(self): + containing_file = unittest_pb2.DESCRIPTOR + self.CheckDescriptorSequence(containing_file.dependencies) + self.CheckDescriptorMapping(containing_file.message_types_by_name) + self.CheckDescriptorMapping(containing_file.enum_types_by_name) + self.CheckDescriptorMapping(containing_file.services_by_name) + self.CheckDescriptorMapping(containing_file.extensions_by_name) + self.CheckDescriptorMapping( + unittest_pb2.TestNestedExtension.DESCRIPTOR.extensions_by_name) + + def testCppDescriptorContainer_Iterator(self): + # Same test with the iterator + enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] + values_iter = iter(enum.values) + del enum + self.assertEqual('FOO', next(values_iter).name) + + def testServiceDescriptor(self): + service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService'] + self.assertEqual(service_descriptor.name, 'TestService') + self.assertEqual(service_descriptor.methods[0].name, 'Foo') + self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR) + self.assertEqual(service_descriptor.index, 0) + self.CheckDescriptorMapping(service_descriptor.methods_by_name) + + def testOneofDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] + self.assertFalse(oneof_descriptor.has_options) + self.assertEqual(message_descriptor, oneof_descriptor.containing_type) + self.assertEqual('oneof_field', oneof_descriptor.name) + self.assertEqual('protobuf_unittest.TestAllTypes.oneof_field', + oneof_descriptor.full_name) + self.assertEqual(0, oneof_descriptor.index) + + +class DescriptorCopyToProtoTest(unittest.TestCase): + """Tests for CopyTo functions of Descriptor.""" + + def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii): + expected_proto = expected_class() + text_format.Merge(expected_ascii, expected_proto) + + self.assertEqual( + actual_proto, expected_proto, + 'Not equal,\nActual:\n%s\nExpected:\n%s\n' + % (str(actual_proto), str(expected_proto))) + + def _InternalTestCopyToProto(self, desc, expected_proto_class, + expected_proto_ascii): + actual = expected_proto_class() + desc.CopyToProto(actual) + self._AssertProtoEqual( + actual, expected_proto_class, expected_proto_ascii) + + def testCopyToProto_EmptyMessage(self): + self._InternalTestCopyToProto( + unittest_pb2.TestEmptyMessage.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII) + + def testCopyToProto_NestedMessage(self): + TEST_NESTED_MESSAGE_ASCII = """ + name: 'NestedMessage' + field: < + name: 'bb' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_NESTED_MESSAGE_ASCII) + + def testCopyToProto_ForeignNestedMessage(self): + TEST_FOREIGN_NESTED_ASCII = """ + name: 'TestForeignNested' + field: < + name: 'foreign_nested' + number: 1 + label: 1 # Optional + type: 11 # TYPE_MESSAGE + type_name: '.protobuf_unittest.TestAllTypes.NestedMessage' + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestForeignNested.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_FOREIGN_NESTED_ASCII) + + def testCopyToProto_ForeignEnum(self): + TEST_FOREIGN_ENUM_ASCII = """ + name: 'ForeignEnum' + value: < + name: 'FOREIGN_FOO' + number: 4 + > + value: < + name: 'FOREIGN_BAR' + number: 5 + > + value: < + name: 'FOREIGN_BAZ' + number: 6 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.ForeignEnum.DESCRIPTOR, + descriptor_pb2.EnumDescriptorProto, + TEST_FOREIGN_ENUM_ASCII) + + def testCopyToProto_Options(self): + TEST_DEPRECATED_FIELDS_ASCII = """ + name: 'TestDeprecatedFields' + field: < + name: 'deprecated_int32' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + options: < + deprecated: true + > + > + field { + name: "deprecated_int32_in_oneof" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_INT32 + options { + deprecated: true + } + oneof_index: 0 + } + oneof_decl { + name: "oneof_fields" + } + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestDeprecatedFields.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_DEPRECATED_FIELDS_ASCII) + + def testCopyToProto_AllExtensions(self): + TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """ + name: 'TestEmptyMessageWithExtensions' + extension_range: < + start: 1 + end: 536870912 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII) + + def testCopyToProto_SeveralExtensions(self): + TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """ + name: 'TestMultipleExtensionRanges' + extension_range: < + start: 42 + end: 43 + > + extension_range: < + start: 4143 + end: 4244 + > + extension_range: < + start: 65536 + end: 536870912 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) + + def testCopyToProto_FileDescriptor(self): + UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" + name: 'google/protobuf/unittest_import.proto' + package: 'protobuf_unittest_import' + dependency: 'google/protobuf/unittest_import_public.proto' + message_type: < + name: 'ImportMessage' + field: < + name: 'd' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + > + > + """ + + """enum_type: < + name: 'ImportEnum' + value: < + name: 'IMPORT_FOO' + number: 7 + > + value: < + name: 'IMPORT_BAR' + number: 8 + > + value: < + name: 'IMPORT_BAZ' + number: 9 + > + > + enum_type: < + name: 'ImportEnumForMap' + value: < + name: 'UNKNOWN' + number: 0 + > + value: < + name: 'FOO' + number: 1 + > + value: < + name: 'BAR' + number: 2 + > + > + options: < + java_package: 'com.google.protobuf.test' + optimize_for: 1 # SPEED + """ + + """ + cc_enable_arenas: true + > + public_dependency: 0 + """) + self._InternalTestCopyToProto( + unittest_import_pb2.DESCRIPTOR, + descriptor_pb2.FileDescriptorProto, + UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) + + def testCopyToProto_ServiceDescriptor(self): + TEST_SERVICE_ASCII = """ + name: 'TestService' + method: < + name: 'Foo' + input_type: '.protobuf_unittest.FooRequest' + output_type: '.protobuf_unittest.FooResponse' + > + method: < + name: 'Bar' + input_type: '.protobuf_unittest.BarRequest' + output_type: '.protobuf_unittest.BarResponse' + > + """ + self._InternalTestCopyToProto( + unittest_pb2.TestService.DESCRIPTOR, + descriptor_pb2.ServiceDescriptorProto, + TEST_SERVICE_ASCII) + + @unittest.skipIf( + api_implementation.Type() == 'python', + 'It is not implemented in python.') + # TODO(jieluo): Add support for pure python or remove in c extension. + def testCopyToProto_MethodDescriptor(self): + expected_ascii = """ + name: 'Foo' + input_type: '.protobuf_unittest.FooRequest' + output_type: '.protobuf_unittest.FooResponse' + """ + method_descriptor = unittest_pb2.TestService.DESCRIPTOR.FindMethodByName( + 'Foo') + self._InternalTestCopyToProto( + method_descriptor, + descriptor_pb2.MethodDescriptorProto, + expected_ascii) + + @unittest.skipIf( + api_implementation.Type() == 'python', + 'Pure python does not raise error.') + # TODO(jieluo): Fix pure python to check with the proto type. + def testCopyToProto_TypeError(self): + file_proto = descriptor_pb2.FileDescriptorProto() + self.assertRaises(TypeError, + unittest_pb2.TestEmptyMessage.DESCRIPTOR.CopyToProto, + file_proto) + self.assertRaises(TypeError, + unittest_pb2.ForeignEnum.DESCRIPTOR.CopyToProto, + file_proto) + self.assertRaises(TypeError, + unittest_pb2.TestService.DESCRIPTOR.CopyToProto, + file_proto) + proto = descriptor_pb2.DescriptorProto() + self.assertRaises(TypeError, + unittest_import_pb2.DESCRIPTOR.CopyToProto, + proto) + + +class MakeDescriptorTest(unittest.TestCase): + + def testMakeDescriptorWithNestedFields(self): + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = 'Foo2' + message_type = file_descriptor_proto.message_type.add() + message_type.name = file_descriptor_proto.name + nested_type = message_type.nested_type.add() + nested_type.name = 'Sub' + enum_type = nested_type.enum_type.add() + enum_type.name = 'FOO' + enum_type_val = enum_type.value.add() + enum_type_val.name = 'BAR' + enum_type_val.number = 3 + field = message_type.field.add() + field.number = 1 + field.name = 'uint64_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_UINT64 + field = message_type.field.add() + field.number = 2 + field.name = 'nested_message_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_MESSAGE + field.type_name = 'Sub' + enum_field = nested_type.field.add() + enum_field.number = 2 + enum_field.name = 'bar_field' + enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM + enum_field.type_name = 'Foo2.Sub.FOO' + + result = descriptor.MakeDescriptor(message_type) + self.assertEqual(result.fields[0].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_UINT64) + self.assertEqual(result.fields[1].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_MESSAGE) + self.assertEqual(result.fields[1].message_type.containing_type, + result) + self.assertEqual(result.nested_types[0].fields[0].full_name, + 'Foo2.Sub.bar_field') + self.assertEqual(result.nested_types[0].fields[0].enum_type, + result.nested_types[0].enum_types[0]) + self.assertFalse(result.has_options) + self.assertFalse(result.fields[0].has_options) + if api_implementation.Type() == 'cpp': + with self.assertRaises(AttributeError): + result.fields[0].has_options = False + + def testMakeDescriptorWithUnsignedIntField(self): + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = 'Foo' + message_type = file_descriptor_proto.message_type.add() + message_type.name = file_descriptor_proto.name + enum_type = message_type.enum_type.add() + enum_type.name = 'FOO' + enum_type_val = enum_type.value.add() + enum_type_val.name = 'BAR' + enum_type_val.number = 3 + field = message_type.field.add() + field.number = 1 + field.name = 'uint64_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_UINT64 + enum_field = message_type.field.add() + enum_field.number = 2 + enum_field.name = 'bar_field' + enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM + enum_field.type_name = 'Foo.FOO' + + result = descriptor.MakeDescriptor(message_type) + self.assertEqual(result.fields[0].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_UINT64) + + + def testMakeDescriptorWithOptions(self): + descriptor_proto = descriptor_pb2.DescriptorProto() + aggregate_message = unittest_custom_options_pb2.AggregateMessage + aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto) + reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto) + + options = reformed_descriptor.GetOptions() + self.assertEqual(101, + options.Extensions[unittest_custom_options_pb2.msgopt].i) + + def testCamelcaseName(self): + descriptor_proto = descriptor_pb2.DescriptorProto() + descriptor_proto.name = 'Bar' + names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar'] + camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar'] + for index in range(len(names)): + field = descriptor_proto.field.add() + field.number = index + 1 + field.name = names[index] + result = descriptor.MakeDescriptor(descriptor_proto) + for index in range(len(camelcase_names)): + self.assertEqual(result.fields[index].camelcase_name, + camelcase_names[index]) + + def testJsonName(self): + descriptor_proto = descriptor_pb2.DescriptorProto() + descriptor_proto.name = 'TestJsonName' + names = ['field_name', 'fieldName', 'FieldName', + '_field_name', 'FIELD_NAME', 'json_name'] + json_names = ['fieldName', 'fieldName', 'FieldName', + 'FieldName', 'FIELDNAME', '@type'] + for index in range(len(names)): + field = descriptor_proto.field.add() + field.number = index + 1 + field.name = names[index] + field.json_name = '@type' + result = descriptor.MakeDescriptor(descriptor_proto) + for index in range(len(json_names)): + self.assertEqual(result.fields[index].json_name, + json_names[index]) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/encoder.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/encoder.py new file mode 100644 index 0000000..0d1f49d --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/encoder.py @@ -0,0 +1,828 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Code for encoding protocol message primitives. + +Contains the logic for encoding every logical protocol field type +into one of the 5 physical wire types. + +This code is designed to push the Python interpreter's performance to the +limits. + +The basic idea is that at startup time, for every field (i.e. every +FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The +sizer takes a value of this field's type and computes its byte size. The +encoder takes a writer function and a value. It encodes the value into byte +strings and invokes the writer function to write those strings. Typically the +writer function is the write() method of a BytesIO. + +We try to do as much work as possible when constructing the writer and the +sizer rather than when calling them. In particular: +* We copy any needed global functions to local variables, so that we do not need + to do costly global table lookups at runtime. +* Similarly, we try to do any attribute lookups at startup time if possible. +* Every field's tag is encoded to bytes at startup, since it can't change at + runtime. +* Whatever component of the field size we can compute at startup, we do. +* We *avoid* sharing code if doing so would make the code slower and not sharing + does not burden us too much. For example, encoders for repeated fields do + not just call the encoders for singular fields in a loop because this would + add an extra function call overhead for every loop iteration; instead, we + manually inline the single-value encoder into the loop. +* If a Python function lacks a return statement, Python actually generates + instructions to pop the result of the last statement off the stack, push + None onto the stack, and then return that. If we really don't care what + value is returned, then we can save two instructions by returning the + result of the last statement. It looks funny but it helps. +* We assume that type and bounds checking has happened at a higher level. +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import struct + +import six + +from google.protobuf.internal import wire_format + + +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF + + +def _VarintSize(value): + """Compute the size of a varint value.""" + if value <= 0x7f: return 1 + if value <= 0x3fff: return 2 + if value <= 0x1fffff: return 3 + if value <= 0xfffffff: return 4 + if value <= 0x7ffffffff: return 5 + if value <= 0x3ffffffffff: return 6 + if value <= 0x1ffffffffffff: return 7 + if value <= 0xffffffffffffff: return 8 + if value <= 0x7fffffffffffffff: return 9 + return 10 + + +def _SignedVarintSize(value): + """Compute the size of a signed varint value.""" + if value < 0: return 10 + if value <= 0x7f: return 1 + if value <= 0x3fff: return 2 + if value <= 0x1fffff: return 3 + if value <= 0xfffffff: return 4 + if value <= 0x7ffffffff: return 5 + if value <= 0x3ffffffffff: return 6 + if value <= 0x1ffffffffffff: return 7 + if value <= 0xffffffffffffff: return 8 + if value <= 0x7fffffffffffffff: return 9 + return 10 + + +def _TagSize(field_number): + """Returns the number of bytes required to serialize a tag with this field + number.""" + # Just pass in type 0, since the type won't affect the tag+type size. + return _VarintSize(wire_format.PackTag(field_number, 0)) + + +# -------------------------------------------------------------------- +# In this section we define some generic sizers. Each of these functions +# takes parameters specific to a particular field type, e.g. int32 or fixed64. +# It returns another function which in turn takes parameters specific to a +# particular field, e.g. the field number and whether it is repeated or packed. +# Look at the next section to see how these are used. + + +def _SimpleSizer(compute_value_size): + """A sizer which uses the function compute_value_size to compute the size of + each value. Typically compute_value_size is _VarintSize.""" + + def SpecificSizer(field_number, is_repeated, is_packed): + tag_size = _TagSize(field_number) + if is_packed: + local_VarintSize = _VarintSize + def PackedFieldSize(value): + result = 0 + for element in value: + result += compute_value_size(element) + return result + local_VarintSize(result) + tag_size + return PackedFieldSize + elif is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + result += compute_value_size(element) + return result + return RepeatedFieldSize + else: + def FieldSize(value): + return tag_size + compute_value_size(value) + return FieldSize + + return SpecificSizer + + +def _ModifiedSizer(compute_value_size, modify_value): + """Like SimpleSizer, but modify_value is invoked on each value before it is + passed to compute_value_size. modify_value is typically ZigZagEncode.""" + + def SpecificSizer(field_number, is_repeated, is_packed): + tag_size = _TagSize(field_number) + if is_packed: + local_VarintSize = _VarintSize + def PackedFieldSize(value): + result = 0 + for element in value: + result += compute_value_size(modify_value(element)) + return result + local_VarintSize(result) + tag_size + return PackedFieldSize + elif is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + result += compute_value_size(modify_value(element)) + return result + return RepeatedFieldSize + else: + def FieldSize(value): + return tag_size + compute_value_size(modify_value(value)) + return FieldSize + + return SpecificSizer + + +def _FixedSizer(value_size): + """Like _SimpleSizer except for a fixed-size field. The input is the size + of one value.""" + + def SpecificSizer(field_number, is_repeated, is_packed): + tag_size = _TagSize(field_number) + if is_packed: + local_VarintSize = _VarintSize + def PackedFieldSize(value): + result = len(value) * value_size + return result + local_VarintSize(result) + tag_size + return PackedFieldSize + elif is_repeated: + element_size = value_size + tag_size + def RepeatedFieldSize(value): + return len(value) * element_size + return RepeatedFieldSize + else: + field_size = value_size + tag_size + def FieldSize(value): + return field_size + return FieldSize + + return SpecificSizer + + +# ==================================================================== +# Here we declare a sizer constructor for each field type. Each "sizer +# constructor" is a function that takes (field_number, is_repeated, is_packed) +# as parameters and returns a sizer, which in turn takes a field value as +# a parameter and returns its encoded size. + + +Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize) + +UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize) + +SInt32Sizer = SInt64Sizer = _ModifiedSizer( + _SignedVarintSize, wire_format.ZigZagEncode) + +Fixed32Sizer = SFixed32Sizer = FloatSizer = _FixedSizer(4) +Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8) + +BoolSizer = _FixedSizer(1) + + +def StringSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a string field.""" + + tag_size = _TagSize(field_number) + local_VarintSize = _VarintSize + local_len = len + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + l = local_len(element.encode('utf-8')) + result += local_VarintSize(l) + l + return result + return RepeatedFieldSize + else: + def FieldSize(value): + l = local_len(value.encode('utf-8')) + return tag_size + local_VarintSize(l) + l + return FieldSize + + +def BytesSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a bytes field.""" + + tag_size = _TagSize(field_number) + local_VarintSize = _VarintSize + local_len = len + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + l = local_len(element) + result += local_VarintSize(l) + l + return result + return RepeatedFieldSize + else: + def FieldSize(value): + l = local_len(value) + return tag_size + local_VarintSize(l) + l + return FieldSize + + +def GroupSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a group field.""" + + tag_size = _TagSize(field_number) * 2 + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + result += element.ByteSize() + return result + return RepeatedFieldSize + else: + def FieldSize(value): + return tag_size + value.ByteSize() + return FieldSize + + +def MessageSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a message field.""" + + tag_size = _TagSize(field_number) + local_VarintSize = _VarintSize + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + l = element.ByteSize() + result += local_VarintSize(l) + l + return result + return RepeatedFieldSize + else: + def FieldSize(value): + l = value.ByteSize() + return tag_size + local_VarintSize(l) + l + return FieldSize + + +# -------------------------------------------------------------------- +# MessageSet is special: it needs custom logic to compute its size properly. + + +def MessageSetItemSizer(field_number): + """Returns a sizer for extensions of MessageSet. + + The message set message looks like this: + message MessageSet { + repeated group Item = 1 { + required int32 type_id = 2; + required string message = 3; + } + } + """ + static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) + + _TagSize(3)) + local_VarintSize = _VarintSize + + def FieldSize(value): + l = value.ByteSize() + return static_size + local_VarintSize(l) + l + + return FieldSize + + +# -------------------------------------------------------------------- +# Map is special: it needs custom logic to compute its size properly. + + +def MapSizer(field_descriptor, is_message_map): + """Returns a sizer for a map field.""" + + # Can't look at field_descriptor.message_type._concrete_class because it may + # not have been initialized yet. + message_type = field_descriptor.message_type + message_sizer = MessageSizer(field_descriptor.number, False, False) + + def FieldSize(map_value): + total = 0 + for key in map_value: + value = map_value[key] + # It's wasteful to create the messages and throw them away one second + # later since we'll do the same for the actual encode. But there's not an + # obvious way to avoid this within the current design without tons of code + # duplication. For message map, value.ByteSize() should be called to + # update the status. + entry_msg = message_type._concrete_class(key=key, value=value) + total += message_sizer(entry_msg) + if is_message_map: + value.ByteSize() + return total + + return FieldSize + +# ==================================================================== +# Encoders! + + +def _VarintEncoder(): + """Return an encoder for a basic varint value (does not include tag).""" + + def EncodeVarint(write, value, unused_deterministic=None): + bits = value & 0x7f + value >>= 7 + while value: + write(six.int2byte(0x80|bits)) + bits = value & 0x7f + value >>= 7 + return write(six.int2byte(bits)) + + return EncodeVarint + + +def _SignedVarintEncoder(): + """Return an encoder for a basic signed varint value (does not include + tag).""" + + def EncodeSignedVarint(write, value, unused_deterministic=None): + if value < 0: + value += (1 << 64) + bits = value & 0x7f + value >>= 7 + while value: + write(six.int2byte(0x80|bits)) + bits = value & 0x7f + value >>= 7 + return write(six.int2byte(bits)) + + return EncodeSignedVarint + + +_EncodeVarint = _VarintEncoder() +_EncodeSignedVarint = _SignedVarintEncoder() + + +def _VarintBytes(value): + """Encode the given integer as a varint and return the bytes. This is only + called at startup time so it doesn't need to be fast.""" + + pieces = [] + _EncodeVarint(pieces.append, value, True) + return b"".join(pieces) + + +def TagBytes(field_number, wire_type): + """Encode the given tag and return the bytes. Only called at startup.""" + + return six.binary_type( + _VarintBytes(wire_format.PackTag(field_number, wire_type))) + +# -------------------------------------------------------------------- +# As with sizers (see above), we have a number of common encoder +# implementations. + + +def _SimpleEncoder(wire_type, encode_value, compute_value_size): + """Return a constructor for an encoder for fields of a particular type. + + Args: + wire_type: The field's wire type, for encoding tags. + encode_value: A function which encodes an individual value, e.g. + _EncodeVarint(). + compute_value_size: A function which computes the size of an individual + value, e.g. _VarintSize(). + """ + + def SpecificEncoder(field_number, is_repeated, is_packed): + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + size = 0 + for element in value: + size += compute_value_size(element) + local_EncodeVarint(write, size, deterministic) + for element in value: + encode_value(write, element, deterministic) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, deterministic): + for element in value: + write(tag_bytes) + encode_value(write, element, deterministic) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, deterministic): + write(tag_bytes) + return encode_value(write, value, deterministic) + return EncodeField + + return SpecificEncoder + + +def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value): + """Like SimpleEncoder but additionally invokes modify_value on every value + before passing it to encode_value. Usually modify_value is ZigZagEncode.""" + + def SpecificEncoder(field_number, is_repeated, is_packed): + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + size = 0 + for element in value: + size += compute_value_size(modify_value(element)) + local_EncodeVarint(write, size, deterministic) + for element in value: + encode_value(write, modify_value(element), deterministic) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, deterministic): + for element in value: + write(tag_bytes) + encode_value(write, modify_value(element), deterministic) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, deterministic): + write(tag_bytes) + return encode_value(write, modify_value(value), deterministic) + return EncodeField + + return SpecificEncoder + + +def _StructPackEncoder(wire_type, format): + """Return a constructor for an encoder for a fixed-width field. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + value_size = struct.calcsize(format) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size, deterministic) + for element in value: + write(local_struct_pack(format, element)) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, unused_deterministic=None): + for element in value: + write(tag_bytes) + write(local_struct_pack(format, element)) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, unused_deterministic=None): + write(tag_bytes) + return write(local_struct_pack(format, value)) + return EncodeField + + return SpecificEncoder + + +def _FloatingPointEncoder(wire_type, format): + """Return a constructor for an encoder for float fields. + + This is like StructPackEncoder, but catches errors that may be due to + passing non-finite floating-point values to struct.pack, and makes a + second attempt to encode those values. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + value_size = struct.calcsize(format) + if value_size == 4: + def EncodeNonFiniteOrRaise(write, value): + # Remember that the serialized form uses little-endian byte order. + if value == _POS_INF: + write(b'\x00\x00\x80\x7F') + elif value == _NEG_INF: + write(b'\x00\x00\x80\xFF') + elif value != value: # NaN + write(b'\x00\x00\xC0\x7F') + else: + raise + elif value_size == 8: + def EncodeNonFiniteOrRaise(write, value): + if value == _POS_INF: + write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') + elif value == _NEG_INF: + write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') + elif value != value: # NaN + write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') + else: + raise + else: + raise ValueError('Can\'t encode floating-point values that are ' + '%d bytes long (only 4 or 8)' % value_size) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size, deterministic) + for element in value: + # This try/except block is going to be faster than any code that + # we could write to check whether element is finite. + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, unused_deterministic=None): + for element in value: + write(tag_bytes) + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, unused_deterministic=None): + write(tag_bytes) + try: + write(local_struct_pack(format, value)) + except SystemError: + EncodeNonFiniteOrRaise(write, value) + return EncodeField + + return SpecificEncoder + + +# ==================================================================== +# Here we declare an encoder constructor for each field type. These work +# very similarly to sizer constructors, described earlier. + + +Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder( + wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) + +UInt32Encoder = UInt64Encoder = _SimpleEncoder( + wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) + +SInt32Encoder = SInt64Encoder = _ModifiedEncoder( + wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, + wire_format.ZigZagEncode) + +# Note that Python conveniently guarantees that when using the '<' prefix on +# formats, they will also have the same size across all platforms (as opposed +# to without the prefix, where their sizes depend on the C compiler's basic +# type sizes). +Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '\n\x04loop\x18\x01 \x01(\x0b\x32\x30.google.protobuf.python.internal.Factory2Message\"D\n\x19MessageWithNestedEnumOnly\"\'\n\nNestedEnum\x12\x19\n\x15NESTED_MESSAGE_ENUM_0\x10\x00\"\'\n\x11MessageWithOption\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05:\x02\x10\x01*<\n\x0c\x46\x61\x63tory2Enum\x12\x15\n\x11\x46\x41\x43TORY_2_VALUE_0\x10\x00\x12\x15\n\x11\x46\x41\x43TORY_2_VALUE_1\x10\x01:H\n\ranother_field\x12\x30.google.protobuf.python.internal.Factory1Message\x18\xea\x07 \x01(\t') + , + dependencies=[google_dot_protobuf_dot_internal_dot_factory__test1__pb2.DESCRIPTOR,]) + +_FACTORY2ENUM = _descriptor.EnumDescriptor( + name='Factory2Enum', + full_name='google.protobuf.python.internal.Factory2Enum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FACTORY_2_VALUE_0', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FACTORY_2_VALUE_1', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1816, + serialized_end=1876, +) +_sym_db.RegisterEnumDescriptor(_FACTORY2ENUM) + +Factory2Enum = enum_type_wrapper.EnumTypeWrapper(_FACTORY2ENUM) +FACTORY_2_VALUE_0 = 0 +FACTORY_2_VALUE_1 = 1 + +ANOTHER_FIELD_FIELD_NUMBER = 1002 +another_field = _descriptor.FieldDescriptor( + name='another_field', full_name='google.protobuf.python.internal.another_field', index=0, + number=1002, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_FACTORY2MESSAGE_NESTEDFACTORY2ENUM = _descriptor.EnumDescriptor( + name='NestedFactory2Enum', + full_name='google.protobuf.python.internal.Factory2Message.NestedFactory2Enum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NESTED_FACTORY_2_VALUE_0', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NESTED_FACTORY_2_VALUE_1', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1454, + serialized_end=1534, +) +_sym_db.RegisterEnumDescriptor(_FACTORY2MESSAGE_NESTEDFACTORY2ENUM) + +_MESSAGEWITHNESTEDENUMONLY_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NESTED_MESSAGE_ENUM_0', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1734, + serialized_end=1773, +) +_sym_db.RegisterEnumDescriptor(_MESSAGEWITHNESTEDENUMONLY_NESTEDENUM) + + +_FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE = _descriptor.Descriptor( + name='NestedFactory2Message', + full_name='google.protobuf.python.internal.Factory2Message.NestedFactory2Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.python.internal.Factory2Message.NestedFactory2Message.value', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1371, + serialized_end=1409, +) + +_FACTORY2MESSAGE_GROUPED = _descriptor.Descriptor( + name='Grouped', + full_name='google.protobuf.python.internal.Factory2Message.Grouped', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='part_1', full_name='google.protobuf.python.internal.Factory2Message.Grouped.part_1', index=0, + number=13, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='part_2', full_name='google.protobuf.python.internal.Factory2Message.Grouped.part_2', index=1, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1411, + serialized_end=1452, +) + +_FACTORY2MESSAGE = _descriptor.Descriptor( + name='Factory2Message', + full_name='google.protobuf.python.internal.Factory2Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='mandatory', full_name='google.protobuf.python.internal.Factory2Message.mandatory', index=0, + number=1, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='factory_2_enum', full_name='google.protobuf.python.internal.Factory2Message.factory_2_enum', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_2_enum', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_2_enum', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_2_message', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_2_message', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='factory_1_message', full_name='google.protobuf.python.internal.Factory2Message.factory_1_message', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='factory_1_enum', full_name='google.protobuf.python.internal.Factory2Message.factory_1_enum', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_1_enum', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_1_enum', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_1_message', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_1_message', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='circular_message', full_name='google.protobuf.python.internal.Factory2Message.circular_message', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='scalar_value', full_name='google.protobuf.python.internal.Factory2Message.scalar_value', index=9, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='list_value', full_name='google.protobuf.python.internal.Factory2Message.list_value', index=10, + number=11, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='grouped', full_name='google.protobuf.python.internal.Factory2Message.grouped', index=11, + number=12, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='loop', full_name='google.protobuf.python.internal.Factory2Message.loop', index=12, + number=15, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_with_default', full_name='google.protobuf.python.internal.Factory2Message.int_with_default', index=13, + number=16, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=1776, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_with_default', full_name='google.protobuf.python.internal.Factory2Message.double_with_default', index=14, + number=17, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(9.99), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_with_default', full_name='google.protobuf.python.internal.Factory2Message.string_with_default', index=15, + number=18, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello world").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_with_default', full_name='google.protobuf.python.internal.Factory2Message.bool_with_default', index=16, + number=19, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_with_default', full_name='google.protobuf.python.internal.Factory2Message.enum_with_default', index=17, + number=20, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_with_default', full_name='google.protobuf.python.internal.Factory2Message.bytes_with_default', index=18, + number=21, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("a\373\000c"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_int', full_name='google.protobuf.python.internal.Factory2Message.oneof_int', index=19, + number=22, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='google.protobuf.python.internal.Factory2Message.oneof_string', index=20, + number=23, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='one_more_field', full_name='google.protobuf.python.internal.Factory2Message.one_more_field', index=0, + number=1001, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE, _FACTORY2MESSAGE_GROUPED, ], + enum_types=[ + _FACTORY2MESSAGE_NESTEDFACTORY2ENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='google.protobuf.python.internal.Factory2Message.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=128, + serialized_end=1624, +) + + +_LOOPMESSAGE = _descriptor.Descriptor( + name='LoopMessage', + full_name='google.protobuf.python.internal.LoopMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='loop', full_name='google.protobuf.python.internal.LoopMessage.loop', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1626, + serialized_end=1703, +) + + +_MESSAGEWITHNESTEDENUMONLY = _descriptor.Descriptor( + name='MessageWithNestedEnumOnly', + full_name='google.protobuf.python.internal.MessageWithNestedEnumOnly', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _MESSAGEWITHNESTEDENUMONLY_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1705, + serialized_end=1773, +) + + +_MESSAGEWITHOPTION = _descriptor.Descriptor( + name='MessageWithOption', + full_name='google.protobuf.python.internal.MessageWithOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='google.protobuf.python.internal.MessageWithOption.field1', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\020\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1775, + serialized_end=1814, +) + +_FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE.containing_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE_GROUPED.containing_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE.fields_by_name['factory_2_enum'].enum_type = _FACTORY2ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_2_enum'].enum_type = _FACTORY2MESSAGE_NESTEDFACTORY2ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_2_message'].message_type = _FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE +_FACTORY2MESSAGE.fields_by_name['factory_1_message'].message_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1MESSAGE +_FACTORY2MESSAGE.fields_by_name['factory_1_enum'].enum_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_1_enum'].enum_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1MESSAGE_NESTEDFACTORY1ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_1_message'].message_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1MESSAGE_NESTEDFACTORY1MESSAGE +_FACTORY2MESSAGE.fields_by_name['circular_message'].message_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE.fields_by_name['grouped'].message_type = _FACTORY2MESSAGE_GROUPED +_FACTORY2MESSAGE.fields_by_name['loop'].message_type = _LOOPMESSAGE +_FACTORY2MESSAGE.fields_by_name['enum_with_default'].enum_type = _FACTORY2ENUM +_FACTORY2MESSAGE_NESTEDFACTORY2ENUM.containing_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE.oneofs_by_name['oneof_field'].fields.append( + _FACTORY2MESSAGE.fields_by_name['oneof_int']) +_FACTORY2MESSAGE.fields_by_name['oneof_int'].containing_oneof = _FACTORY2MESSAGE.oneofs_by_name['oneof_field'] +_FACTORY2MESSAGE.oneofs_by_name['oneof_field'].fields.append( + _FACTORY2MESSAGE.fields_by_name['oneof_string']) +_FACTORY2MESSAGE.fields_by_name['oneof_string'].containing_oneof = _FACTORY2MESSAGE.oneofs_by_name['oneof_field'] +_LOOPMESSAGE.fields_by_name['loop'].message_type = _FACTORY2MESSAGE +_MESSAGEWITHNESTEDENUMONLY_NESTEDENUM.containing_type = _MESSAGEWITHNESTEDENUMONLY +DESCRIPTOR.message_types_by_name['Factory2Message'] = _FACTORY2MESSAGE +DESCRIPTOR.message_types_by_name['LoopMessage'] = _LOOPMESSAGE +DESCRIPTOR.message_types_by_name['MessageWithNestedEnumOnly'] = _MESSAGEWITHNESTEDENUMONLY +DESCRIPTOR.message_types_by_name['MessageWithOption'] = _MESSAGEWITHOPTION +DESCRIPTOR.enum_types_by_name['Factory2Enum'] = _FACTORY2ENUM +DESCRIPTOR.extensions_by_name['another_field'] = another_field +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Factory2Message = _reflection.GeneratedProtocolMessageType('Factory2Message', (_message.Message,), dict( + + NestedFactory2Message = _reflection.GeneratedProtocolMessageType('NestedFactory2Message', (_message.Message,), dict( + DESCRIPTOR = _FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.Factory2Message.NestedFactory2Message) + )) + , + + Grouped = _reflection.GeneratedProtocolMessageType('Grouped', (_message.Message,), dict( + DESCRIPTOR = _FACTORY2MESSAGE_GROUPED, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.Factory2Message.Grouped) + )) + , + DESCRIPTOR = _FACTORY2MESSAGE, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.Factory2Message) + )) +_sym_db.RegisterMessage(Factory2Message) +_sym_db.RegisterMessage(Factory2Message.NestedFactory2Message) +_sym_db.RegisterMessage(Factory2Message.Grouped) + +LoopMessage = _reflection.GeneratedProtocolMessageType('LoopMessage', (_message.Message,), dict( + DESCRIPTOR = _LOOPMESSAGE, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.LoopMessage) + )) +_sym_db.RegisterMessage(LoopMessage) + +MessageWithNestedEnumOnly = _reflection.GeneratedProtocolMessageType('MessageWithNestedEnumOnly', (_message.Message,), dict( + DESCRIPTOR = _MESSAGEWITHNESTEDENUMONLY, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.MessageWithNestedEnumOnly) + )) +_sym_db.RegisterMessage(MessageWithNestedEnumOnly) + +MessageWithOption = _reflection.GeneratedProtocolMessageType('MessageWithOption', (_message.Message,), dict( + DESCRIPTOR = _MESSAGEWITHOPTION, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.MessageWithOption) + )) +_sym_db.RegisterMessage(MessageWithOption) + +google_dot_protobuf_dot_internal_dot_factory__test1__pb2.Factory1Message.RegisterExtension(another_field) +google_dot_protobuf_dot_internal_dot_factory__test1__pb2.Factory1Message.RegisterExtension(_FACTORY2MESSAGE.extensions_by_name['one_more_field']) + +_MESSAGEWITHOPTION._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/file_options_test_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/file_options_test_pb2.py new file mode 100644 index 0000000..31566ca --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/file_options_test_pb2.py @@ -0,0 +1,82 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/file_options_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/file_options_test.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n0google/protobuf/internal/file_options_test.proto\x12\x1fgoogle.protobuf.python.internal\x1a google/protobuf/descriptor.proto\"\x1e\n\nFooOptions\x12\x10\n\x08\x66oo_name\x18\x01 \x01(\t:a\n\x0b\x66oo_options\x12\x1c.google.protobuf.FileOptions\x18\xac\xec\xb6\x39 \x01(\x0b\x32+.google.protobuf.python.internal.FooOptions') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + + +FOO_OPTIONS_FIELD_NUMBER = 120436268 +foo_options = _descriptor.FieldDescriptor( + name='foo_options', full_name='google.protobuf.python.internal.foo_options', index=0, + number=120436268, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_FOOOPTIONS = _descriptor.Descriptor( + name='FooOptions', + full_name='google.protobuf.python.internal.FooOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_name', full_name='google.protobuf.python.internal.FooOptions.foo_name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=119, + serialized_end=149, +) + +DESCRIPTOR.message_types_by_name['FooOptions'] = _FOOOPTIONS +DESCRIPTOR.extensions_by_name['foo_options'] = foo_options +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FooOptions = _reflection.GeneratedProtocolMessageType('FooOptions', (_message.Message,), dict( + DESCRIPTOR = _FOOOPTIONS, + __module__ = 'google.protobuf.internal.file_options_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.FooOptions) + )) +_sym_db.RegisterMessage(FooOptions) + +foo_options.message_type = _FOOOPTIONS +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(foo_options) + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/generator_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/generator_test.py new file mode 100644 index 0000000..aa7cf8a --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/generator_test.py @@ -0,0 +1,349 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# TODO(robinson): Flesh this out considerably. We focused on reflection_test.py +# first, since it's testing the subtler code, and since it provides decent +# indirect testing of the protocol compiler output. + +"""Unittest that directly tests the output of the pure-Python protocol +compiler. See //google/protobuf/internal/reflection_test.py for a test which +further ensures that we can use Python protocol message objects as we expect. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf.internal import test_bad_identifiers_pb2 +from google.protobuf import unittest_custom_options_pb2 +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_import_public_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_mset_wire_format_pb2 +from google.protobuf import unittest_no_generic_services_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import service +from google.protobuf import symbol_database + +MAX_EXTENSION = 536870912 + + +class GeneratorTest(unittest.TestCase): + + def testNestedMessageDescriptor(self): + field_name = 'optional_nested_message' + proto_type = unittest_pb2.TestAllTypes + self.assertEqual( + proto_type.NestedMessage.DESCRIPTOR, + proto_type.DESCRIPTOR.fields_by_name[field_name].message_type) + + def testEnums(self): + # We test only module-level enums here. + # TODO(robinson): Examine descriptors directly to check + # enum descriptor output. + self.assertEqual(4, unittest_pb2.FOREIGN_FOO) + self.assertEqual(5, unittest_pb2.FOREIGN_BAR) + self.assertEqual(6, unittest_pb2.FOREIGN_BAZ) + + proto = unittest_pb2.TestAllTypes() + self.assertEqual(1, proto.FOO) + self.assertEqual(1, unittest_pb2.TestAllTypes.FOO) + self.assertEqual(2, proto.BAR) + self.assertEqual(2, unittest_pb2.TestAllTypes.BAR) + self.assertEqual(3, proto.BAZ) + self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ) + + def testExtremeDefaultValues(self): + message = unittest_pb2.TestExtremeDefaultValues() + + # Python pre-2.6 does not have isinf() or isnan() functions, so we have + # to provide our own. + def isnan(val): + # NaN is never equal to itself. + return val != val + def isinf(val): + # Infinity times zero equals NaN. + return not isnan(val) and isnan(val * 0) + + self.assertTrue(isinf(message.inf_double)) + self.assertTrue(message.inf_double > 0) + self.assertTrue(isinf(message.neg_inf_double)) + self.assertTrue(message.neg_inf_double < 0) + self.assertTrue(isnan(message.nan_double)) + + self.assertTrue(isinf(message.inf_float)) + self.assertTrue(message.inf_float > 0) + self.assertTrue(isinf(message.neg_inf_float)) + self.assertTrue(message.neg_inf_float < 0) + self.assertTrue(isnan(message.nan_float)) + self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph) + + def testHasDefaultValues(self): + desc = unittest_pb2.TestAllTypes.DESCRIPTOR + + expected_has_default_by_name = { + 'optional_int32': False, + 'repeated_int32': False, + 'optional_nested_message': False, + 'default_int32': True, + } + + has_default_by_name = dict( + [(f.name, f.has_default_value) + for f in desc.fields + if f.name in expected_has_default_by_name]) + self.assertEqual(expected_has_default_by_name, has_default_by_name) + + def testContainingTypeBehaviorForExtensions(self): + self.assertEqual(unittest_pb2.optional_int32_extension.containing_type, + unittest_pb2.TestAllExtensions.DESCRIPTOR) + self.assertEqual(unittest_pb2.TestRequired.single.containing_type, + unittest_pb2.TestAllExtensions.DESCRIPTOR) + + def testExtensionScope(self): + self.assertEqual(unittest_pb2.optional_int32_extension.extension_scope, + None) + self.assertEqual(unittest_pb2.TestRequired.single.extension_scope, + unittest_pb2.TestRequired.DESCRIPTOR) + + def testIsExtension(self): + self.assertTrue(unittest_pb2.optional_int32_extension.is_extension) + self.assertTrue(unittest_pb2.TestRequired.single.is_extension) + + message_descriptor = unittest_pb2.TestRequired.DESCRIPTOR + non_extension_descriptor = message_descriptor.fields_by_name['a'] + self.assertTrue(not non_extension_descriptor.is_extension) + + def testOptions(self): + proto = unittest_mset_wire_format_pb2.TestMessageSet() + self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format) + + def testMessageWithCustomOptions(self): + proto = unittest_custom_options_pb2.TestMessageWithCustomOptions() + enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions() + self.assertTrue(enum_options is not None) + # TODO(gps): We really should test for the presence of the enum_opt1 + # extension and for its value to be set to -789. + + def testNestedTypes(self): + self.assertEqual( + set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types), + set([ + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, + unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR, + unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR, + ])) + self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, []) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, []) + + def testContainingType(self): + self.assertTrue( + unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None) + self.assertTrue( + unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEqual( + unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + + def testContainingTypeInEnumDescriptor(self): + self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None) + self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + + def testPackage(self): + self.assertEqual( + unittest_pb2.TestAllTypes.DESCRIPTOR.file.package, + 'protobuf_unittest') + desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR + self.assertEqual(desc.file.package, 'protobuf_unittest') + self.assertEqual( + unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package, + 'protobuf_unittest_import') + + self.assertEqual( + unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest') + self.assertEqual( + unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package, + 'protobuf_unittest') + self.assertEqual( + unittest_import_pb2._IMPORTENUM.file.package, + 'protobuf_unittest_import') + + def testExtensionRange(self): + self.assertEqual( + unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, []) + self.assertEqual( + unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, + [(1, MAX_EXTENSION)]) + self.assertEqual( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, + [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)]) + + def testFileDescriptor(self): + self.assertEqual(unittest_pb2.DESCRIPTOR.name, + 'google/protobuf/unittest.proto') + self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest') + self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None) + self.assertEqual(unittest_pb2.DESCRIPTOR.dependencies, + [unittest_import_pb2.DESCRIPTOR]) + self.assertEqual(unittest_import_pb2.DESCRIPTOR.dependencies, + [unittest_import_public_pb2.DESCRIPTOR]) + self.assertEqual(unittest_import_pb2.DESCRIPTOR.public_dependencies, + [unittest_import_public_pb2.DESCRIPTOR]) + def testNoGenericServices(self): + self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage")) + self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO")) + self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension")) + + # Make sure unittest_no_generic_services_pb2 has no services subclassing + # Proto2 Service class. + if hasattr(unittest_no_generic_services_pb2, "TestService"): + self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService, + service.Service)) + + def testMessageTypesByName(self): + file_type = unittest_pb2.DESCRIPTOR + self.assertEqual( + unittest_pb2._TESTALLTYPES, + file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name]) + + # Nested messages shouldn't be included in the message_types_by_name + # dictionary (like in the C++ API). + self.assertFalse( + unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in + file_type.message_types_by_name) + + def testEnumTypesByName(self): + file_type = unittest_pb2.DESCRIPTOR + self.assertEqual( + unittest_pb2._FOREIGNENUM, + file_type.enum_types_by_name[unittest_pb2._FOREIGNENUM.name]) + + def testExtensionsByName(self): + file_type = unittest_pb2.DESCRIPTOR + self.assertEqual( + unittest_pb2.my_extension_string, + file_type.extensions_by_name[unittest_pb2.my_extension_string.name]) + + def testPublicImports(self): + # Test public imports as embedded message. + all_type_proto = unittest_pb2.TestAllTypes() + self.assertEqual(0, all_type_proto.optional_public_import_message.e) + + # PublicImportMessage is actually defined in unittest_import_public_pb2 + # module, and is public imported by unittest_import_pb2 module. + public_import_proto = unittest_import_pb2.PublicImportMessage() + self.assertEqual(0, public_import_proto.e) + self.assertTrue(unittest_import_public_pb2.PublicImportMessage is + unittest_import_pb2.PublicImportMessage) + + def testBadIdentifiers(self): + # We're just testing that the code was imported without problems. + message = test_bad_identifiers_pb2.TestBadIdentifiers() + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message], + "foo") + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor], + "bar") + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection], + "baz") + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service], + "qux") + + def testOneof(self): + desc = unittest_pb2.TestAllTypes.DESCRIPTOR + self.assertEqual(1, len(desc.oneofs)) + self.assertEqual('oneof_field', desc.oneofs[0].name) + self.assertEqual(0, desc.oneofs[0].index) + self.assertIs(desc, desc.oneofs[0].containing_type) + self.assertIs(desc.oneofs[0], desc.oneofs_by_name['oneof_field']) + nested_names = set(['oneof_uint32', 'oneof_nested_message', + 'oneof_string', 'oneof_bytes']) + self.assertEqual( + nested_names, + set([field.name for field in desc.oneofs[0].fields])) + for field_name, field_desc in list(desc.fields_by_name.items()): + if field_name in nested_names: + self.assertIs(desc.oneofs[0], field_desc.containing_oneof) + else: + self.assertIsNone(field_desc.containing_oneof) + + +class SymbolDatabaseRegistrationTest(unittest.TestCase): + """Checks that messages, enums and files are correctly registered.""" + + def testGetSymbol(self): + self.assertEqual( + unittest_pb2.TestAllTypes, symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes')) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage, + symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes.NestedMessage')) + with self.assertRaises(KeyError): + symbol_database.Default().GetSymbol('protobuf_unittest.NestedMessage') + self.assertEqual( + unittest_pb2.TestAllTypes.OptionalGroup, + symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes.OptionalGroup')) + self.assertEqual( + unittest_pb2.TestAllTypes.RepeatedGroup, + symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes.RepeatedGroup')) + + def testEnums(self): + self.assertEqual( + 'protobuf_unittest.ForeignEnum', + symbol_database.Default().pool.FindEnumTypeByName( + 'protobuf_unittest.ForeignEnum').full_name) + self.assertEqual( + 'protobuf_unittest.TestAllTypes.NestedEnum', + symbol_database.Default().pool.FindEnumTypeByName( + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) + + def testFindFileByName(self): + self.assertEqual( + 'google/protobuf/unittest.proto', + symbol_database.Default().pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/__init__.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/__init__.py new file mode 100644 index 0000000..5121dd0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/__init__.py @@ -0,0 +1,33 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Sample module importing a nested proto from itself.""" + +from google.protobuf.internal.import_test_package import outer_pb2 as myproto diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py new file mode 100644 index 0000000..61db2a5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py @@ -0,0 +1,69 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/import_test_package/inner.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/import_test_package/inner.proto', + package='google.protobuf.python.internal.import_test_package', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n8google/protobuf/internal/import_test_package/inner.proto\x12\x33google.protobuf.python.internal.import_test_package\"\x1a\n\x05Inner\x12\x11\n\x05value\x18\x01 \x01(\x05:\x02\x35\x37') +) + + + + +_INNER = _descriptor.Descriptor( + name='Inner', + full_name='google.protobuf.python.internal.import_test_package.Inner', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.python.internal.import_test_package.Inner.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=57, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=139, +) + +DESCRIPTOR.message_types_by_name['Inner'] = _INNER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Inner = _reflection.GeneratedProtocolMessageType('Inner', (_message.Message,), dict( + DESCRIPTOR = _INNER, + __module__ = 'google.protobuf.internal.import_test_package.inner_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.import_test_package.Inner) + )) +_sym_db.RegisterMessage(Inner) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py new file mode 100644 index 0000000..966b18c --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py @@ -0,0 +1,72 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/import_test_package/outer.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf.internal.import_test_package import inner_pb2 as google_dot_protobuf_dot_internal_dot_import__test__package_dot_inner__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/import_test_package/outer.proto', + package='google.protobuf.python.internal.import_test_package', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n8google/protobuf/internal/import_test_package/outer.proto\x12\x33google.protobuf.python.internal.import_test_package\x1a\x38google/protobuf/internal/import_test_package/inner.proto\"R\n\x05Outer\x12I\n\x05inner\x18\x01 \x01(\x0b\x32:.google.protobuf.python.internal.import_test_package.Inner') + , + dependencies=[google_dot_protobuf_dot_internal_dot_import__test__package_dot_inner__pb2.DESCRIPTOR,]) + + + + +_OUTER = _descriptor.Descriptor( + name='Outer', + full_name='google.protobuf.python.internal.import_test_package.Outer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='inner', full_name='google.protobuf.python.internal.import_test_package.Outer.inner', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=171, + serialized_end=253, +) + +_OUTER.fields_by_name['inner'].message_type = google_dot_protobuf_dot_internal_dot_import__test__package_dot_inner__pb2._INNER +DESCRIPTOR.message_types_by_name['Outer'] = _OUTER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Outer = _reflection.GeneratedProtocolMessageType('Outer', (_message.Message,), dict( + DESCRIPTOR = _OUTER, + __module__ = 'google.protobuf.internal.import_test_package.outer_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.import_test_package.Outer) + )) +_sym_db.RegisterMessage(Outer) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/json_format_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/json_format_test.py new file mode 100644 index 0000000..3f58e89 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/json_format_test.py @@ -0,0 +1,1038 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.json_format.""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import json +import math +import sys + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import any_pb2 +from google.protobuf import duration_pb2 +from google.protobuf import field_mask_pb2 +from google.protobuf import struct_pb2 +from google.protobuf import timestamp_pb2 +from google.protobuf import wrappers_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf.internal import well_known_types +from google.protobuf import json_format +from google.protobuf.util import json_format_proto3_pb2 + + +class JsonFormatBase(unittest.TestCase): + + def FillAllFields(self, message): + message.int32_value = 20 + message.int64_value = -20 + message.uint32_value = 3120987654 + message.uint64_value = 12345678900 + message.float_value = float('-inf') + message.double_value = 3.1415 + message.bool_value = True + message.string_value = 'foo' + message.bytes_value = b'bar' + message.message_value.value = 10 + message.enum_value = json_format_proto3_pb2.BAR + # Repeated + message.repeated_int32_value.append(0x7FFFFFFF) + message.repeated_int32_value.append(-2147483648) + message.repeated_int64_value.append(9007199254740992) + message.repeated_int64_value.append(-9007199254740992) + message.repeated_uint32_value.append(0xFFFFFFF) + message.repeated_uint32_value.append(0x7FFFFFF) + message.repeated_uint64_value.append(9007199254740992) + message.repeated_uint64_value.append(9007199254740991) + message.repeated_float_value.append(0) + + message.repeated_double_value.append(1E-15) + message.repeated_double_value.append(float('inf')) + message.repeated_bool_value.append(True) + message.repeated_bool_value.append(False) + message.repeated_string_value.append('Few symbols!#$,;') + message.repeated_string_value.append('bar') + message.repeated_bytes_value.append(b'foo') + message.repeated_bytes_value.append(b'bar') + message.repeated_message_value.add().value = 10 + message.repeated_message_value.add().value = 11 + message.repeated_enum_value.append(json_format_proto3_pb2.FOO) + message.repeated_enum_value.append(json_format_proto3_pb2.BAR) + self.message = message + + def CheckParseBack(self, message, parsed_message): + json_format.Parse(json_format.MessageToJson(message), + parsed_message) + self.assertEqual(message, parsed_message) + + def CheckError(self, text, error_message): + message = json_format_proto3_pb2.TestMessage() + self.assertRaisesRegex( + json_format.ParseError, + error_message, + json_format.Parse, text, message) + + +class JsonFormatTest(JsonFormatBase): + + def testEmptyMessageToJson(self): + message = json_format_proto3_pb2.TestMessage() + self.assertEqual(json_format.MessageToJson(message), + '{}') + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + + def testPartialMessageToJson(self): + message = json_format_proto3_pb2.TestMessage( + string_value='test', + repeated_int32_value=[89, 4]) + self.assertEqual(json.loads(json_format.MessageToJson(message)), + json.loads('{"stringValue": "test", ' + '"repeatedInt32Value": [89, 4]}')) + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + + def testAllFieldsToJson(self): + message = json_format_proto3_pb2.TestMessage() + text = ('{"int32Value": 20, ' + '"int64Value": "-20", ' + '"uint32Value": 3120987654,' + '"uint64Value": "12345678900",' + '"floatValue": "-Infinity",' + '"doubleValue": 3.1415,' + '"boolValue": true,' + '"stringValue": "foo",' + '"bytesValue": "YmFy",' + '"messageValue": {"value": 10},' + '"enumValue": "BAR",' + '"repeatedInt32Value": [2147483647, -2147483648],' + '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],' + '"repeatedUint32Value": [268435455, 134217727],' + '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],' + '"repeatedFloatValue": [0],' + '"repeatedDoubleValue": [1e-15, "Infinity"],' + '"repeatedBoolValue": [true, false],' + '"repeatedStringValue": ["Few symbols!#$,;", "bar"],' + '"repeatedBytesValue": ["Zm9v", "YmFy"],' + '"repeatedMessageValue": [{"value": 10}, {"value": 11}],' + '"repeatedEnumValue": ["FOO", "BAR"]' + '}') + self.FillAllFields(message) + self.assertEqual( + json.loads(json_format.MessageToJson(message)), + json.loads(text)) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + + def testUnknownEnumToJsonAndBack(self): + text = '{\n "enumValue": 999\n}' + message = json_format_proto3_pb2.TestMessage() + message.enum_value = 999 + self.assertEqual(json_format.MessageToJson(message), + text) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + + def testExtensionToJsonAndBack(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_text = json_format.MessageToJson( + message + ) + parsed_message = unittest_mset_pb2.TestMessageSetContainer() + json_format.Parse(message_text, parsed_message) + self.assertEqual(message, parsed_message) + + def testExtensionErrors(self): + self.CheckError('{"[extensionField]": {}}', + 'Message type proto3.TestMessage does not have extensions') + + def testExtensionToDictAndBack(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_dict = json_format.MessageToDict( + message + ) + parsed_message = unittest_mset_pb2.TestMessageSetContainer() + json_format.ParseDict(message_dict, parsed_message) + self.assertEqual(message, parsed_message) + + def testExtensionSerializationDictMatchesProto3Spec(self): + """See go/proto3-json-spec for spec. + """ + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_dict = json_format.MessageToDict( + message + ) + golden_dict = { + 'messageSet': { + '[protobuf_unittest.' + 'TestMessageSetExtension1.messageSetExtension]': { + 'i': 23, + }, + '[protobuf_unittest.' + 'TestMessageSetExtension2.messageSetExtension]': { + 'str': 'foo', + }, + }, + } + self.assertEqual(golden_dict, message_dict) + + + def testExtensionSerializationJsonMatchesProto3Spec(self): + """See go/proto3-json-spec for spec. + """ + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_text = json_format.MessageToJson( + message + ) + ext1_text = ('protobuf_unittest.TestMessageSetExtension1.' + 'messageSetExtension') + ext2_text = ('protobuf_unittest.TestMessageSetExtension2.' + 'messageSetExtension') + golden_text = ('{"messageSet": {' + ' "[%s]": {' + ' "i": 23' + ' },' + ' "[%s]": {' + ' "str": "foo"' + ' }' + '}}') % (ext1_text, ext2_text) + self.assertEqual(json.loads(golden_text), json.loads(message_text)) + + + def testJsonEscapeString(self): + message = json_format_proto3_pb2.TestMessage() + if sys.version_info[0] < 3: + message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9' + else: + message.string_value = '&\n<\"\r>\b\t\f\\\001/' + message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8') + self.assertEqual( + json_format.MessageToJson(message), + '{\n "stringValue": ' + '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}') + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + text = '{"int32Value": "\u0031"}' + json_format.Parse(text, message) + self.assertEqual(message.int32_value, 1) + + def testAlwaysSeriliaze(self): + message = json_format_proto3_pb2.TestMessage( + string_value='foo') + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"repeatedStringValue": [],' + '"stringValue": "foo",' + '"repeatedBoolValue": [],' + '"repeatedUint32Value": [],' + '"repeatedInt32Value": [],' + '"enumValue": "FOO",' + '"int32Value": 0,' + '"floatValue": 0,' + '"int64Value": "0",' + '"uint32Value": 0,' + '"repeatedBytesValue": [],' + '"repeatedUint64Value": [],' + '"repeatedDoubleValue": [],' + '"bytesValue": "",' + '"boolValue": false,' + '"repeatedEnumValue": [],' + '"uint64Value": "0",' + '"doubleValue": 0,' + '"repeatedFloatValue": [],' + '"repeatedInt64Value": [],' + '"repeatedMessageValue": []}')) + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + + def testIntegersRepresentedAsFloat(self): + message = json_format_proto3_pb2.TestMessage() + json_format.Parse('{"int32Value": -2.147483648e9}', message) + self.assertEqual(message.int32_value, -2147483648) + json_format.Parse('{"int32Value": 1e5}', message) + self.assertEqual(message.int32_value, 100000) + json_format.Parse('{"int32Value": 1.0}', message) + self.assertEqual(message.int32_value, 1) + + def testMapFields(self): + message = json_format_proto3_pb2.TestNestedMap() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"boolMap": {},' + '"int32Map": {},' + '"int64Map": {},' + '"uint32Map": {},' + '"uint64Map": {},' + '"stringMap": {},' + '"mapMap": {}' + '}')) + message.bool_map[True] = 1 + message.bool_map[False] = 2 + message.int32_map[1] = 2 + message.int32_map[2] = 3 + message.int64_map[1] = 2 + message.int64_map[2] = 3 + message.uint32_map[1] = 2 + message.uint32_map[2] = 3 + message.uint64_map[1] = 2 + message.uint64_map[2] = 3 + message.string_map['1'] = 2 + message.string_map['null'] = 3 + message.map_map['1'].bool_map[True] = 3 + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads('{' + '"boolMap": {"false": 2, "true": 1},' + '"int32Map": {"1": 2, "2": 3},' + '"int64Map": {"1": 2, "2": 3},' + '"uint32Map": {"1": 2, "2": 3},' + '"uint64Map": {"1": 2, "2": 3},' + '"stringMap": {"1": 2, "null": 3},' + '"mapMap": {"1": {"boolMap": {"true": 3}}}' + '}')) + parsed_message = json_format_proto3_pb2.TestNestedMap() + self.CheckParseBack(message, parsed_message) + + def testOneofFields(self): + message = json_format_proto3_pb2.TestOneof() + # Always print does not affect oneof fields. + self.assertEqual( + json_format.MessageToJson(message, True), + '{}') + message.oneof_int32_value = 0 + self.assertEqual( + json_format.MessageToJson(message, True), + '{\n' + ' "oneofInt32Value": 0\n' + '}') + parsed_message = json_format_proto3_pb2.TestOneof() + self.CheckParseBack(message, parsed_message) + + def testSurrogates(self): + # Test correct surrogate handling. + message = json_format_proto3_pb2.TestMessage() + json_format.Parse('{"stringValue": "\\uD83D\\uDE01"}', message) + self.assertEqual(message.string_value, + b'\xF0\x9F\x98\x81'.decode('utf-8', 'strict')) + + # Error case: unpaired high surrogate. + self.CheckError( + '{"stringValue": "\\uD83D"}', + r'Invalid \\uXXXX escape|Unpaired.*surrogate') + + # Unpaired low surrogate. + self.CheckError( + '{"stringValue": "\\uDE01"}', + r'Invalid \\uXXXX escape|Unpaired.*surrogate') + + def testTimestampMessage(self): + message = json_format_proto3_pb2.TestTimestamp() + message.value.seconds = 0 + message.value.nanos = 0 + message.repeated_value.add().seconds = 20 + message.repeated_value[0].nanos = 1 + message.repeated_value.add().seconds = 0 + message.repeated_value[1].nanos = 10000 + message.repeated_value.add().seconds = 100000000 + message.repeated_value[2].nanos = 0 + # Maximum time + message.repeated_value.add().seconds = 253402300799 + message.repeated_value[3].nanos = 999999999 + # Minimum time + message.repeated_value.add().seconds = -62135596800 + message.repeated_value[4].nanos = 0 + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"value": "1970-01-01T00:00:00Z",' + '"repeatedValue": [' + ' "1970-01-01T00:00:20.000000001Z",' + ' "1970-01-01T00:00:00.000010Z",' + ' "1973-03-03T09:46:40Z",' + ' "9999-12-31T23:59:59.999999999Z",' + ' "0001-01-01T00:00:00Z"' + ']' + '}')) + parsed_message = json_format_proto3_pb2.TestTimestamp() + self.CheckParseBack(message, parsed_message) + text = (r'{"value": "1970-01-01T00:00:00.01+08:00",' + r'"repeatedValue":[' + r' "1970-01-01T00:00:00.01+08:30",' + r' "1970-01-01T00:00:00.01-01:23"]}') + json_format.Parse(text, parsed_message) + self.assertEqual(parsed_message.value.seconds, -8 * 3600) + self.assertEqual(parsed_message.value.nanos, 10000000) + self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600) + self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60) + + def testDurationMessage(self): + message = json_format_proto3_pb2.TestDuration() + message.value.seconds = 1 + message.repeated_value.add().seconds = 0 + message.repeated_value[0].nanos = 10 + message.repeated_value.add().seconds = -1 + message.repeated_value[1].nanos = -1000 + message.repeated_value.add().seconds = 10 + message.repeated_value[2].nanos = 11000000 + message.repeated_value.add().seconds = -315576000000 + message.repeated_value.add().seconds = 315576000000 + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"value": "1s",' + '"repeatedValue": [' + ' "0.000000010s",' + ' "-1.000001s",' + ' "10.011s",' + ' "-315576000000s",' + ' "315576000000s"' + ']' + '}')) + parsed_message = json_format_proto3_pb2.TestDuration() + self.CheckParseBack(message, parsed_message) + + def testFieldMaskMessage(self): + message = json_format_proto3_pb2.TestFieldMask() + message.value.paths.append('foo.bar') + message.value.paths.append('bar') + self.assertEqual( + json_format.MessageToJson(message, True), + '{\n' + ' "value": "foo.bar,bar"\n' + '}') + parsed_message = json_format_proto3_pb2.TestFieldMask() + self.CheckParseBack(message, parsed_message) + + def testWrapperMessage(self): + message = json_format_proto3_pb2.TestWrapper() + message.bool_value.value = False + message.int32_value.value = 0 + message.string_value.value = '' + message.bytes_value.value = b'' + message.repeated_bool_value.add().value = True + message.repeated_bool_value.add().value = False + message.repeated_int32_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{\n' + ' "int32Value": 0,' + ' "boolValue": false,' + ' "stringValue": "",' + ' "bytesValue": "",' + ' "repeatedBoolValue": [true, false],' + ' "repeatedInt32Value": [0],' + ' "repeatedUint32Value": [],' + ' "repeatedFloatValue": [],' + ' "repeatedDoubleValue": [],' + ' "repeatedBytesValue": [],' + ' "repeatedInt64Value": [],' + ' "repeatedUint64Value": [],' + ' "repeatedStringValue": []' + '}')) + parsed_message = json_format_proto3_pb2.TestWrapper() + self.CheckParseBack(message, parsed_message) + + def testStructMessage(self): + message = json_format_proto3_pb2.TestStruct() + message.value['name'] = 'Jim' + message.value['age'] = 10 + message.value['attend'] = True + message.value['email'] = None + message.value.get_or_create_struct('address')['city'] = 'SFO' + message.value['address']['house_number'] = 1024 + struct_list = message.value.get_or_create_list('list') + struct_list.extend([6, 'seven', True, False, None]) + struct_list.add_struct()['subkey2'] = 9 + message.repeated_value.add()['age'] = 11 + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{' + ' "value": {' + ' "address": {' + ' "city": "SFO", ' + ' "house_number": 1024' + ' }, ' + ' "age": 10, ' + ' "name": "Jim", ' + ' "attend": true, ' + ' "email": null, ' + ' "list": [6, "seven", true, false, null, {"subkey2": 9}]' + ' },' + ' "repeatedValue": [{"age": 11}, {}]' + '}')) + parsed_message = json_format_proto3_pb2.TestStruct() + self.CheckParseBack(message, parsed_message) + + def testValueMessage(self): + message = json_format_proto3_pb2.TestValue() + message.value.string_value = 'hello' + message.repeated_value.add().number_value = 11.1 + message.repeated_value.add().bool_value = False + message.repeated_value.add().null_value = 0 + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{' + ' "value": "hello",' + ' "repeatedValue": [11.1, false, null]' + '}')) + parsed_message = json_format_proto3_pb2.TestValue() + self.CheckParseBack(message, parsed_message) + # Can't parse back if the Value message is not set. + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{' + ' "value": "hello",' + ' "repeatedValue": [11.1, false, null, null]' + '}')) + message.Clear() + json_format.Parse('{"value": null}', message) + self.assertEqual(message.value.WhichOneof('kind'), 'null_value') + + def testListValueMessage(self): + message = json_format_proto3_pb2.TestListValue() + message.value.values.add().number_value = 11.1 + message.value.values.add().null_value = 0 + message.value.values.add().bool_value = True + message.value.values.add().string_value = 'hello' + message.value.values.add().struct_value['name'] = 'Jim' + message.repeated_value.add().values.add().number_value = 1 + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,' + '"repeatedValue": [[1], []]}')) + parsed_message = json_format_proto3_pb2.TestListValue() + self.CheckParseBack(message, parsed_message) + + def testAnyMessage(self): + message = json_format_proto3_pb2.TestAny() + value1 = json_format_proto3_pb2.MessageType() + value2 = json_format_proto3_pb2.MessageType() + value1.value = 1234 + value2.value = 5678 + message.value.Pack(value1) + message.repeated_value.add().Pack(value1) + message.repeated_value.add().Pack(value2) + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "repeatedValue": [ {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "value": 1234\n' + ' }, {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "value": 5678\n' + ' },\n' + ' {}],\n' + ' "value": {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "value": 1234\n' + ' }\n' + '}\n')) + parsed_message = json_format_proto3_pb2.TestAny() + self.CheckParseBack(message, parsed_message) + # Must print @type first + test_message = json_format_proto3_pb2.TestMessage( + bool_value=True, + int32_value=20, + int64_value=-20, + uint32_value=20, + uint64_value=20, + double_value=3.14, + string_value='foo') + message.Clear() + message.value.Pack(test_message) + self.assertEqual( + json_format.MessageToJson(message, False)[0:68], + '{\n' + ' "value": {\n' + ' "@type": "type.googleapis.com/proto3.TestMessage"') + + def testWellKnownInAnyMessage(self): + message = any_pb2.Any() + int32_value = wrappers_pb2.Int32Value() + int32_value.value = 1234 + message.Pack(int32_value) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": \"type.googleapis.com/google.protobuf.Int32Value\",\n' + ' "value": 1234\n' + '}\n')) + parsed_message = any_pb2.Any() + self.CheckParseBack(message, parsed_message) + + timestamp = timestamp_pb2.Timestamp() + message.Pack(timestamp) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Timestamp",\n' + ' "value": "1970-01-01T00:00:00Z"\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + duration = duration_pb2.Duration() + duration.seconds = 1 + message.Pack(duration) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Duration",\n' + ' "value": "1s"\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + field_mask = field_mask_pb2.FieldMask() + field_mask.paths.append('foo.bar') + field_mask.paths.append('bar') + message.Pack(field_mask) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.FieldMask",\n' + ' "value": "foo.bar,bar"\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + struct_message = struct_pb2.Struct() + struct_message['name'] = 'Jim' + message.Pack(struct_message) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Struct",\n' + ' "value": {"name": "Jim"}\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + nested_any = any_pb2.Any() + int32_value.value = 5678 + nested_any.Pack(int32_value) + message.Pack(nested_any) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Any",\n' + ' "value": {\n' + ' "@type": "type.googleapis.com/google.protobuf.Int32Value",\n' + ' "value": 5678\n' + ' }\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + def testParseNull(self): + message = json_format_proto3_pb2.TestMessage() + parsed_message = json_format_proto3_pb2.TestMessage() + self.FillAllFields(parsed_message) + json_format.Parse('{"int32Value": null, ' + '"int64Value": null, ' + '"uint32Value": null,' + '"uint64Value": null,' + '"floatValue": null,' + '"doubleValue": null,' + '"boolValue": null,' + '"stringValue": null,' + '"bytesValue": null,' + '"messageValue": null,' + '"enumValue": null,' + '"repeatedInt32Value": null,' + '"repeatedInt64Value": null,' + '"repeatedUint32Value": null,' + '"repeatedUint64Value": null,' + '"repeatedFloatValue": null,' + '"repeatedDoubleValue": null,' + '"repeatedBoolValue": null,' + '"repeatedStringValue": null,' + '"repeatedBytesValue": null,' + '"repeatedMessageValue": null,' + '"repeatedEnumValue": null' + '}', + parsed_message) + self.assertEqual(message, parsed_message) + # Null and {} should have different behavior for sub message. + self.assertFalse(parsed_message.HasField('message_value')) + json_format.Parse('{"messageValue": {}}', parsed_message) + self.assertTrue(parsed_message.HasField('message_value')) + # Null is not allowed to be used as an element in repeated field. + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse repeatedInt32Value field: ' + 'null is not allowed to be used as an element in a repeated field.', + json_format.Parse, + '{"repeatedInt32Value":[1, null]}', + parsed_message) + self.CheckError('{"repeatedMessageValue":[null]}', + 'Failed to parse repeatedMessageValue field: null is not' + ' allowed to be used as an element in a repeated field.') + + def testNanFloat(self): + message = json_format_proto3_pb2.TestMessage() + message.float_value = float('nan') + text = '{\n "floatValue": "NaN"\n}' + self.assertEqual(json_format.MessageToJson(message), text) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertTrue(math.isnan(parsed_message.float_value)) + + def testParseEmptyText(self): + self.CheckError('', + r'Failed to load JSON: (Expecting value)|(No JSON).') + + def testParseEnumValue(self): + message = json_format_proto3_pb2.TestMessage() + text = '{"enumValue": 0}' + json_format.Parse(text, message) + text = '{"enumValue": 1}' + json_format.Parse(text, message) + self.CheckError( + '{"enumValue": "baz"}', + 'Failed to parse enumValue field: Invalid enum value baz ' + 'for enum type proto3.EnumType.') + # Proto3 accepts numeric unknown enums. + text = '{"enumValue": 12345}' + json_format.Parse(text, message) + # Proto2 does not accept unknown enums. + message = unittest_pb2.TestAllTypes() + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse optionalNestedEnum field: Invalid enum value 12345 ' + 'for enum type protobuf_unittest.TestAllTypes.NestedEnum.', + json_format.Parse, '{"optionalNestedEnum": 12345}', message) + + def testParseBadIdentifer(self): + self.CheckError('{int32Value: 1}', + (r'Failed to load JSON: Expecting property name' + r'( enclosed in double quotes)?: line 1')) + self.CheckError('{"unknownName": 1}', + 'Message type "proto3.TestMessage" has no field named ' + '"unknownName".') + + def testIgnoreUnknownField(self): + text = '{"unknownName": 1}' + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message, ignore_unknown_fields=True) + text = ('{\n' + ' "repeatedValue": [ {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "unknownName": 1\n' + ' }]\n' + '}\n') + parsed_message = json_format_proto3_pb2.TestAny() + json_format.Parse(text, parsed_message, ignore_unknown_fields=True) + + def testDuplicateField(self): + # Duplicate key check is not supported for python2.6 + if sys.version_info < (2, 7): + return + self.CheckError('{"int32Value": 1,\n"int32Value":2}', + 'Failed to load JSON: duplicate key int32Value.') + + def testInvalidBoolValue(self): + self.CheckError('{"boolValue": 1}', + 'Failed to parse boolValue field: ' + 'Expected true or false without quotes.') + self.CheckError('{"boolValue": "true"}', + 'Failed to parse boolValue field: ' + 'Expected true or false without quotes.') + + def testInvalidIntegerValue(self): + message = json_format_proto3_pb2.TestMessage() + text = '{"int32Value": 0x12345}' + self.assertRaises(json_format.ParseError, + json_format.Parse, text, message) + self.CheckError('{"int32Value": 1.5}', + 'Failed to parse int32Value field: ' + 'Couldn\'t parse integer: 1.5.') + self.CheckError('{"int32Value": 012345}', + (r'Failed to load JSON: Expecting \'?,\'? delimiter: ' + r'line 1.')) + self.CheckError('{"int32Value": " 1 "}', + 'Failed to parse int32Value field: ' + 'Couldn\'t parse integer: " 1 ".') + self.CheckError('{"int32Value": "1 "}', + 'Failed to parse int32Value field: ' + 'Couldn\'t parse integer: "1 ".') + self.CheckError('{"int32Value": 12345678901234567890}', + 'Failed to parse int32Value field: Value out of range: ' + '12345678901234567890.') + self.CheckError('{"uint32Value": -1}', + 'Failed to parse uint32Value field: ' + 'Value out of range: -1.') + + def testInvalidFloatValue(self): + self.CheckError('{"floatValue": "nan"}', + 'Failed to parse floatValue field: Couldn\'t ' + 'parse float "nan", use "NaN" instead.') + + def testInvalidBytesValue(self): + self.CheckError('{"bytesValue": "AQI"}', + 'Failed to parse bytesValue field: Incorrect padding.') + self.CheckError('{"bytesValue": "AQI*"}', + 'Failed to parse bytesValue field: Incorrect padding.') + + def testInvalidRepeated(self): + self.CheckError('{"repeatedInt32Value": 12345}', + (r'Failed to parse repeatedInt32Value field: repeated field' + r' repeatedInt32Value must be in \[\] which is 12345.')) + + def testInvalidMap(self): + message = json_format_proto3_pb2.TestMap() + text = '{"int32Map": {"null": 2, "2": 3}}' + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse int32Map field: invalid literal', + json_format.Parse, text, message) + text = '{"int32Map": {1: 2, "2": 3}}' + self.assertRaisesRegex( + json_format.ParseError, + (r'Failed to load JSON: Expecting property name' + r'( enclosed in double quotes)?: line 1'), + json_format.Parse, text, message) + text = '{"boolMap": {"null": 1}}' + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse boolMap field: Expected "true" or "false", not null.', + json_format.Parse, text, message) + if sys.version_info < (2, 7): + return + text = r'{"stringMap": {"a": 3, "\u0061": 2}}' + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to load JSON: duplicate key a', + json_format.Parse, text, message) + text = r'{"stringMap": 0}' + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse stringMap field: Map field string_map must be ' + 'in a dict which is 0.', + json_format.Parse, text, message) + + def testInvalidTimestamp(self): + message = json_format_proto3_pb2.TestTimestamp() + text = '{"value": "10000-01-01T00:00:00.00Z"}' + self.assertRaisesRegex( + json_format.ParseError, + 'time data \'10000-01-01T00:00:00\' does not match' + ' format \'%Y-%m-%dT%H:%M:%S\'.', + json_format.Parse, text, message) + text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}' + self.assertRaisesRegex( + well_known_types.ParseError, + 'nanos 0123456789012 more than 9 fractional digits.', + json_format.Parse, text, message) + text = '{"value": "1972-01-01T01:00:00.01+08"}' + self.assertRaisesRegex( + well_known_types.ParseError, + (r'Invalid timezone offset value: \+08.'), + json_format.Parse, text, message) + # Time smaller than minimum time. + text = '{"value": "0000-01-01T00:00:00Z"}' + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse value field: year (0 )?is out of range.', + json_format.Parse, text, message) + # Time bigger than maxinum time. + message.value.seconds = 253402300800 + self.assertRaisesRegex( + OverflowError, + 'date value out of range', + json_format.MessageToJson, message) + + def testInvalidOneof(self): + message = json_format_proto3_pb2.TestOneof() + text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}' + self.assertRaisesRegex( + json_format.ParseError, + 'Message type "proto3.TestOneof"' + ' should not have multiple "oneof_value" oneof fields.', + json_format.Parse, text, message) + + def testInvalidListValue(self): + message = json_format_proto3_pb2.TestListValue() + text = '{"value": 1234}' + self.assertRaisesRegex( + json_format.ParseError, + r'Failed to parse value field: ListValue must be in \[\] which is 1234', + json_format.Parse, text, message) + + def testInvalidStruct(self): + message = json_format_proto3_pb2.TestStruct() + text = '{"value": 1234}' + self.assertRaisesRegex( + json_format.ParseError, + 'Failed to parse value field: Struct must be in a dict which is 1234', + json_format.Parse, text, message) + + def testInvalidAny(self): + message = any_pb2.Any() + text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}' + self.assertRaisesRegex( + KeyError, + 'value', + json_format.Parse, text, message) + text = '{"value": 1234}' + self.assertRaisesRegex( + json_format.ParseError, + '@type is missing when parsing any message.', + json_format.Parse, text, message) + text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}' + self.assertRaisesRegex( + TypeError, + 'Can not find message descriptor by type_url: ' + 'type.googleapis.com/MessageNotExist.', + json_format.Parse, text, message) + # Only last part is to be used: b/25630112 + text = (r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",' + r'"value": 1234}') + json_format.Parse(text, message) + + def testPreservingProtoFieldNames(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + self.assertEqual('{\n "int32Value": 12345\n}', + json_format.MessageToJson(message)) + self.assertEqual('{\n "int32_value": 12345\n}', + json_format.MessageToJson(message, False, True)) + # When including_default_value_fields is True. + message = json_format_proto3_pb2.TestTimestamp() + self.assertEqual('{\n "repeatedValue": []\n}', + json_format.MessageToJson(message, True, False)) + self.assertEqual('{\n "repeated_value": []\n}', + json_format.MessageToJson(message, True, True)) + + # Parsers accept both original proto field names and lowerCamelCase names. + message = json_format_proto3_pb2.TestMessage() + json_format.Parse('{"int32Value": 54321}', message) + self.assertEqual(54321, message.int32_value) + json_format.Parse('{"int32_value": 12345}', message) + self.assertEqual(12345, message.int32_value) + + def testIndent(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + self.assertEqual('{\n"int32Value": 12345\n}', + json_format.MessageToJson(message, indent=0)) + + def testFormatEnumsAsInts(self): + message = json_format_proto3_pb2.TestMessage() + message.enum_value = json_format_proto3_pb2.BAR + message.repeated_enum_value.append(json_format_proto3_pb2.FOO) + message.repeated_enum_value.append(json_format_proto3_pb2.BAR) + self.assertEqual(json.loads('{\n' + ' "enumValue": 1,\n' + ' "repeatedEnumValue": [0, 1]\n' + '}\n'), + json.loads(json_format.MessageToJson( + message, use_integers_for_enums=True))) + + def testParseDict(self): + expected = 12345 + js_dict = {'int32Value': expected} + message = json_format_proto3_pb2.TestMessage() + json_format.ParseDict(js_dict, message) + self.assertEqual(expected, message.int32_value) + + def testMessageToDict(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + expected = {'int32Value': 12345} + self.assertEqual(expected, + json_format.MessageToDict(message)) + + def testJsonName(self): + message = json_format_proto3_pb2.TestCustomJsonName() + message.value = 12345 + self.assertEqual('{\n "@value": 12345\n}', + json_format.MessageToJson(message)) + parsed_message = json_format_proto3_pb2.TestCustomJsonName() + self.CheckParseBack(message, parsed_message) + + def testSortKeys(self): + # Testing sort_keys is not perfectly working, as by random luck we could + # get the output sorted. We just use a selection of names. + message = json_format_proto3_pb2.TestMessage(bool_value=True, + int32_value=1, + int64_value=3, + uint32_value=4, + string_value='bla') + self.assertEqual( + json_format.MessageToJson(message, sort_keys=True), + # We use json.dumps() instead of a hardcoded string due to differences + # between Python 2 and Python 3. + json.dumps({'boolValue': True, 'int32Value': 1, 'int64Value': '3', + 'uint32Value': 4, 'stringValue': 'bla'}, + indent=2, sort_keys=True)) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/message_factory_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_factory_test.py new file mode 100644 index 0000000..4dc3e71 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_factory_test.py @@ -0,0 +1,222 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.message_factory.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import factory_test1_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool +from google.protobuf import message_factory + + +class MessageFactoryTest(unittest.TestCase): + + def setUp(self): + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + + def _ExerciseDynamicClass(self, cls): + msg = cls() + msg.mandatory = 42 + msg.nested_factory_2_enum = 0 + msg.nested_factory_2_message.value = 'nested message value' + msg.factory_1_message.factory_1_enum = 1 + msg.factory_1_message.nested_factory_1_enum = 0 + msg.factory_1_message.nested_factory_1_message.value = ( + 'nested message value') + msg.factory_1_message.scalar_value = 22 + msg.factory_1_message.list_value.extend(['one', 'two', 'three']) + msg.factory_1_message.list_value.append('four') + msg.factory_1_enum = 1 + msg.nested_factory_1_enum = 0 + msg.nested_factory_1_message.value = 'nested message value' + msg.circular_message.mandatory = 1 + msg.circular_message.circular_message.mandatory = 2 + msg.circular_message.scalar_value = 'one deep' + msg.scalar_value = 'zero deep' + msg.list_value.extend(['four', 'three', 'two']) + msg.list_value.append('one') + msg.grouped.add() + msg.grouped[0].part_1 = 'hello' + msg.grouped[0].part_2 = 'world' + msg.grouped.add(part_1='testing', part_2='123') + msg.loop.loop.mandatory = 2 + msg.loop.loop.loop.loop.mandatory = 4 + serialized = msg.SerializeToString() + converted = factory_test2_pb2.Factory2Message.FromString(serialized) + reserialized = converted.SerializeToString() + self.assertEqual(serialized, reserialized) + result = cls.FromString(reserialized) + self.assertEqual(msg, result) + + def testGetPrototype(self): + db = descriptor_database.DescriptorDatabase() + pool = descriptor_pool.DescriptorPool(db) + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + factory = message_factory.MessageFactory() + cls = factory.GetPrototype(pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message')) + self.assertFalse(cls is factory_test2_pb2.Factory2Message) + self._ExerciseDynamicClass(cls) + cls2 = factory.GetPrototype(pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message')) + self.assertTrue(cls is cls2) + + def testGetMessages(self): + # performed twice because multiple calls with the same input must be allowed + for _ in range(2): + # GetMessage should work regardless of the order the FileDescriptorProto + # are provided. In particular, the function should succeed when the files + # are not in the topological order of dependencies. + + # Assuming factory_test2_fd depends on factory_test1_fd. + self.assertIn(self.factory_test1_fd.name, + self.factory_test2_fd.dependency) + # Get messages should work when a file comes before its dependencies: + # factory_test2_fd comes before factory_test1_fd. + messages = message_factory.GetMessages([self.factory_test2_fd, + self.factory_test1_fd]) + self.assertTrue( + set(['google.protobuf.python.internal.Factory2Message', + 'google.protobuf.python.internal.Factory1Message'], + ).issubset(set(messages.keys()))) + self._ExerciseDynamicClass( + messages['google.protobuf.python.internal.Factory2Message']) + factory_msg1 = messages['google.protobuf.python.internal.Factory1Message'] + self.assertTrue(set( + ['google.protobuf.python.internal.Factory2Message.one_more_field', + 'google.protobuf.python.internal.another_field'],).issubset(set( + ext.full_name + for ext in factory_msg1.DESCRIPTOR.file.pool.FindAllExtensions( + factory_msg1.DESCRIPTOR)))) + msg1 = messages['google.protobuf.python.internal.Factory1Message']() + ext1 = msg1.Extensions._FindExtensionByName( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + ext2 = msg1.Extensions._FindExtensionByName( + 'google.protobuf.python.internal.another_field') + msg1.Extensions[ext1] = 'test1' + msg1.Extensions[ext2] = 'test2' + self.assertEqual('test1', msg1.Extensions[ext1]) + self.assertEqual('test2', msg1.Extensions[ext2]) + self.assertEqual(None, + msg1.Extensions._FindExtensionByNumber(12321)) + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix len to return the correct value. + # self.assertEqual(2, len(msg1.Extensions)) + self.assertEqual(len(msg1.Extensions), len(msg1.Extensions)) + self.assertRaises(TypeError, + msg1.Extensions._FindExtensionByName, 0) + self.assertRaises(TypeError, + msg1.Extensions._FindExtensionByNumber, '') + else: + self.assertEqual(None, + msg1.Extensions._FindExtensionByName(0)) + self.assertEqual(None, + msg1.Extensions._FindExtensionByNumber('')) + + def testDuplicateExtensionNumber(self): + pool = descriptor_pool.DescriptorPool() + factory = message_factory.MessageFactory(pool=pool) + + # Add Container message. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/container.proto' + f.package = 'google.protobuf.python.internal' + msg = f.message_type.add() + msg.name = 'Container' + rng = msg.extension_range.add() + rng.start = 1 + rng.end = 10 + pool.Add(f) + msgs = factory.GetMessages([f.name]) + self.assertIn('google.protobuf.python.internal.Container', msgs) + + # Extend container. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/extension.proto' + f.package = 'google.protobuf.python.internal' + f.dependency.append('google/protobuf/internal/container.proto') + msg = f.message_type.add() + msg.name = 'Extension' + ext = msg.extension.add() + ext.name = 'extension_field' + ext.number = 2 + ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + ext.type_name = 'Extension' + ext.extendee = 'Container' + pool.Add(f) + msgs = factory.GetMessages([f.name]) + self.assertIn('google.protobuf.python.internal.Extension', msgs) + + # Add Duplicate extending the same field number. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/duplicate.proto' + f.package = 'google.protobuf.python.internal' + f.dependency.append('google/protobuf/internal/container.proto') + msg = f.message_type.add() + msg.name = 'Duplicate' + ext = msg.extension.add() + ext.name = 'extension_field' + ext.number = 2 + ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + ext.type_name = 'Duplicate' + ext.extendee = 'Container' + pool.Add(f) + + with self.assertRaises(Exception) as cm: + factory.GetMessages([f.name]) + + self.assertIn(str(cm.exception), + ['Extensions ' + '"google.protobuf.python.internal.Duplicate.extension_field" and' + ' "google.protobuf.python.internal.Extension.extension_field"' + ' both try to extend message type' + ' "google.protobuf.python.internal.Container"' + ' with field number 2.', + 'Double registration of Extensions']) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/message_listener.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_listener.py new file mode 100644 index 0000000..0fc255a --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_listener.py @@ -0,0 +1,78 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Defines a listener interface for observing certain +state transitions on Message objects. + +Also defines a null implementation of this interface. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + + +class MessageListener(object): + + """Listens for modifications made to a message. Meant to be registered via + Message._SetListener(). + + Attributes: + dirty: If True, then calling Modified() would be a no-op. This can be + used to avoid these calls entirely in the common case. + """ + + def Modified(self): + """Called every time the message is modified in such a way that the parent + message may need to be updated. This currently means either: + (a) The message was modified for the first time, so the parent message + should henceforth mark the message as present. + (b) The message's cached byte size became dirty -- i.e. the message was + modified for the first time after a previous call to ByteSize(). + Therefore the parent should also mark its byte size as dirty. + Note that (a) implies (b), since new objects start out with a client cached + size (zero). However, we document (a) explicitly because it is important. + + Modified() will *only* be called in response to one of these two events -- + not every time the sub-message is modified. + + Note that if the listener's |dirty| attribute is true, then calling + Modified at the moment would be a no-op, so it can be skipped. Performance- + sensitive callers should check this attribute directly before calling since + it will be true most of the time. + """ + + raise NotImplementedError + + +class NullMessageListener(object): + + """No-op MessageListener implementation.""" + + def Modified(self): + pass diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/message_set_extensions_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_set_extensions_pb2.py new file mode 100644 index 0000000..ed992f6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_set_extensions_pb2.py @@ -0,0 +1,209 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/message_set_extensions.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/message_set_extensions.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n5google/protobuf/internal/message_set_extensions.proto\x12\x18google.protobuf.internal\"\x1e\n\x0eTestMessageSet*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\"\xa5\x01\n\x18TestMessageSetExtension1\x12\t\n\x01i\x18\x0f \x01(\x05\x32~\n\x15message_set_extension\x12(.google.protobuf.internal.TestMessageSet\x18\xab\xff\xf6. \x01(\x0b\x32\x32.google.protobuf.internal.TestMessageSetExtension1\"\xa7\x01\n\x18TestMessageSetExtension2\x12\x0b\n\x03str\x18\x19 \x01(\t2~\n\x15message_set_extension\x12(.google.protobuf.internal.TestMessageSet\x18\xca\xff\xf6. \x01(\x0b\x32\x32.google.protobuf.internal.TestMessageSetExtension2\"(\n\x18TestMessageSetExtension3\x12\x0c\n\x04text\x18# \x01(\t:\x7f\n\x16message_set_extension3\x12(.google.protobuf.internal.TestMessageSet\x18\xdf\xff\xf6. \x01(\x0b\x32\x32.google.protobuf.internal.TestMessageSetExtension3') +) + + +MESSAGE_SET_EXTENSION3_FIELD_NUMBER = 98418655 +message_set_extension3 = _descriptor.FieldDescriptor( + name='message_set_extension3', full_name='google.protobuf.internal.message_set_extension3', index=0, + number=98418655, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTMESSAGESET = _descriptor.Descriptor( + name='TestMessageSet', + full_name='google.protobuf.internal.TestMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=83, + serialized_end=113, +) + + +_TESTMESSAGESETEXTENSION1 = _descriptor.Descriptor( + name='TestMessageSetExtension1', + full_name='google.protobuf.internal.TestMessageSetExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='google.protobuf.internal.TestMessageSetExtension1.i', index=0, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='google.protobuf.internal.TestMessageSetExtension1.message_set_extension', index=0, + number=98418603, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=116, + serialized_end=281, +) + + +_TESTMESSAGESETEXTENSION2 = _descriptor.Descriptor( + name='TestMessageSetExtension2', + full_name='google.protobuf.internal.TestMessageSetExtension2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='str', full_name='google.protobuf.internal.TestMessageSetExtension2.str', index=0, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='google.protobuf.internal.TestMessageSetExtension2.message_set_extension', index=0, + number=98418634, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=284, + serialized_end=451, +) + + +_TESTMESSAGESETEXTENSION3 = _descriptor.Descriptor( + name='TestMessageSetExtension3', + full_name='google.protobuf.internal.TestMessageSetExtension3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='text', full_name='google.protobuf.internal.TestMessageSetExtension3.text', index=0, + number=35, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=453, + serialized_end=493, +) + +DESCRIPTOR.message_types_by_name['TestMessageSet'] = _TESTMESSAGESET +DESCRIPTOR.message_types_by_name['TestMessageSetExtension1'] = _TESTMESSAGESETEXTENSION1 +DESCRIPTOR.message_types_by_name['TestMessageSetExtension2'] = _TESTMESSAGESETEXTENSION2 +DESCRIPTOR.message_types_by_name['TestMessageSetExtension3'] = _TESTMESSAGESETEXTENSION3 +DESCRIPTOR.extensions_by_name['message_set_extension3'] = message_set_extension3 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageSet = _reflection.GeneratedProtocolMessageType('TestMessageSet', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESET, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSet) + )) +_sym_db.RegisterMessage(TestMessageSet) + +TestMessageSetExtension1 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION1, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSetExtension1) + )) +_sym_db.RegisterMessage(TestMessageSetExtension1) + +TestMessageSetExtension2 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension2', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION2, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSetExtension2) + )) +_sym_db.RegisterMessage(TestMessageSetExtension2) + +TestMessageSetExtension3 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension3', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION3, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSetExtension3) + )) +_sym_db.RegisterMessage(TestMessageSetExtension3) + +message_set_extension3.message_type = _TESTMESSAGESETEXTENSION3 +TestMessageSet.RegisterExtension(message_set_extension3) +_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION1 +TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension']) +_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION2 +TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension']) + +_TESTMESSAGESET._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/message_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_test.py new file mode 100644 index 0000000..258f0de --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/message_test.py @@ -0,0 +1,2203 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests python protocol buffers against the golden message. + +Note that the golden messages exercise every known field type, thus this +test ends up exercising and verifying nearly all of the parsing and +serialization code in the whole library. + +TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of +sense to call this a test of the "message" module, which only declares an +abstract interface. +""" + +__author__ = 'gps@google.com (Gregory P. Smith)' + + +import collections +import copy +import math +import operator +import pickle +import six +import sys +import warnings + +try: + import unittest2 as unittest # PY26 +except ImportError: + import unittest +try: + cmp # Python 2 +except NameError: + cmp = lambda x, y: (x > y) - (x < y) # Python 3 + +from google.protobuf import map_proto2_unittest_pb2 +from google.protobuf import map_unittest_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf import descriptor_pool +from google.protobuf import message_factory +from google.protobuf import text_format +from google.protobuf.internal import api_implementation +from google.protobuf.internal import encoder +from google.protobuf.internal import packed_field_test_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks +from google.protobuf import message +from google.protobuf.internal import _parameterized + +if six.PY3: + long = int + + +# Python pre-2.6 does not have isinf() or isnan() functions, so we have +# to provide our own. +def isnan(val): + # NaN is never equal to itself. + return val != val +def isinf(val): + # Infinity times zero equals NaN. + return not isnan(val) and isnan(val * 0) +def IsPosInf(val): + return isinf(val) and (val > 0) +def IsNegInf(val): + return isinf(val) and (val < 0) + + +BaseTestCase = testing_refleaks.BaseTestCase + + +@_parameterized.named_parameters( + ('_proto2', unittest_pb2), + ('_proto3', unittest_proto3_arena_pb2)) +class MessageTest(BaseTestCase): + + def testBadUtf8String(self, message_module): + if api_implementation.Type() != 'python': + self.skipTest("Skipping testBadUtf8String, currently only the python " + "api implementation raises UnicodeDecodeError when a " + "string field contains bad utf-8.") + bad_utf8_data = test_util.GoldenFileData('bad_utf8_string') + with self.assertRaises(UnicodeDecodeError) as context: + message_module.TestAllTypes.FromString(bad_utf8_data) + self.assertIn('TestAllTypes.optional_string', str(context.exception)) + + def testGoldenMessage(self, message_module): + # Proto3 doesn't have the "default_foo" members or foreign enums, + # and doesn't preserve unknown fields, so for proto3 we use a golden + # message that doesn't have these fields set. + if message_module is unittest_pb2: + golden_data = test_util.GoldenFileData( + 'golden_message_oneof_implemented') + else: + golden_data = test_util.GoldenFileData('golden_message_proto3') + + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, golden_message) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testGoldenPackedMessage(self, message_module): + golden_data = test_util.GoldenFileData('golden_packed_fields_message') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + all_set = message_module.TestPackedTypes() + test_util.SetAllPackedFields(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testParseErrors(self, message_module): + msg = message_module.TestAllTypes() + self.assertRaises(TypeError, msg.FromString, 0) + self.assertRaises(Exception, msg.FromString, '0') + # TODO(jieluo): Fix cpp extension to raise error instead of warning. + # b/27494216 + end_tag = encoder.TagBytes(1, 4) + if api_implementation.Type() == 'python': + with self.assertRaises(message.DecodeError) as context: + msg.FromString(end_tag) + self.assertEqual('Unexpected end-group tag.', str(context.exception)) + else: + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + msg.FromString(end_tag) + assert len(w) == 1 + assert issubclass(w[-1].category, RuntimeWarning) + self.assertEqual('Unexpected end-group tag: Not all data was converted', + str(w[-1].message)) + + def testDeterminismParameters(self, message_module): + # This message is always deterministically serialized, even if determinism + # is disabled, so we can use it to verify that all the determinism + # parameters work correctly. + golden_data = (b'\xe2\x02\nOne string' + b'\xe2\x02\nTwo string' + b'\xe2\x02\nRed string' + b'\xe2\x02\x0bBlue string') + golden_message = message_module.TestAllTypes() + golden_message.repeated_string.extend([ + 'One string', + 'Two string', + 'Red string', + 'Blue string', + ]) + self.assertEqual(golden_data, + golden_message.SerializeToString(deterministic=None)) + self.assertEqual(golden_data, + golden_message.SerializeToString(deterministic=False)) + self.assertEqual(golden_data, + golden_message.SerializeToString(deterministic=True)) + + class BadArgError(Exception): + pass + + class BadArg(object): + + def __bool__(self): + raise BadArgError() + + def __bool__(self): + raise BadArgError() + + with self.assertRaises(BadArgError): + golden_message.SerializeToString(deterministic=BadArg()) + + def testPickleSupport(self, message_module): + golden_data = test_util.GoldenFileData('golden_message') + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + + def testPositiveInfinity(self, message_module): + if message_module is unittest_pb2: + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCD\x02\x00\x00\x80\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') + else: + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCA\x02\x04\x00\x00\x80\x7F' + b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') + + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsPosInf(golden_message.optional_float)) + self.assertTrue(IsPosInf(golden_message.optional_double)) + self.assertTrue(IsPosInf(golden_message.repeated_float[0])) + self.assertTrue(IsPosInf(golden_message.repeated_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNegativeInfinity(self, message_module): + if message_module is unittest_pb2: + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCD\x02\x00\x00\x80\xFF' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') + else: + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCA\x02\x04\x00\x00\x80\xFF' + b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') + + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsNegInf(golden_message.optional_float)) + self.assertTrue(IsNegInf(golden_message.optional_double)) + self.assertTrue(IsNegInf(golden_message.repeated_float[0])) + self.assertTrue(IsNegInf(golden_message.repeated_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNotANumber(self, message_module): + golden_data = (b'\x5D\x00\x00\xC0\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F' + b'\xCD\x02\x00\x00\xC0\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F') + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(isnan(golden_message.optional_float)) + self.assertTrue(isnan(golden_message.optional_double)) + self.assertTrue(isnan(golden_message.repeated_float[0])) + self.assertTrue(isnan(golden_message.repeated_double[0])) + + # The protocol buffer may serialize to any one of multiple different + # representations of a NaN. Rather than verify a specific representation, + # verify the serialized string can be converted into a correctly + # behaving protocol buffer. + serialized = golden_message.SerializeToString() + message = message_module.TestAllTypes() + message.ParseFromString(serialized) + self.assertTrue(isnan(message.optional_float)) + self.assertTrue(isnan(message.optional_double)) + self.assertTrue(isnan(message.repeated_float[0])) + self.assertTrue(isnan(message.repeated_double[0])) + + def testPositiveInfinityPacked(self, message_module): + golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsPosInf(golden_message.packed_float[0])) + self.assertTrue(IsPosInf(golden_message.packed_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNegativeInfinityPacked(self, message_module): + golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsNegInf(golden_message.packed_float[0])) + self.assertTrue(IsNegInf(golden_message.packed_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNotANumberPacked(self, message_module): + golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(isnan(golden_message.packed_float[0])) + self.assertTrue(isnan(golden_message.packed_double[0])) + + serialized = golden_message.SerializeToString() + message = message_module.TestPackedTypes() + message.ParseFromString(serialized) + self.assertTrue(isnan(message.packed_float[0])) + self.assertTrue(isnan(message.packed_double[0])) + + def testExtremeFloatValues(self, message_module): + message = message_module.TestAllTypes() + + # Most positive exponent, no significand bits set. + kMostPosExponentNoSigBits = math.pow(2, 127) + message.optional_float = kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostPosExponentNoSigBits) + + # Most positive exponent, one significand bit set. + kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127) + message.optional_float = kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostPosExponentOneSigBit) + + # Repeat last two cases with values of same magnitude, but negative. + message.optional_float = -kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits) + + message.optional_float = -kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit) + + # Most negative exponent, no significand bits set. + kMostNegExponentNoSigBits = math.pow(2, -127) + message.optional_float = kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostNegExponentNoSigBits) + + # Most negative exponent, one significand bit set. + kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127) + message.optional_float = kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostNegExponentOneSigBit) + + # Repeat last two cases with values of the same magnitude, but negative. + message.optional_float = -kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits) + + message.optional_float = -kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) + + def testExtremeDoubleValues(self, message_module): + message = message_module.TestAllTypes() + + # Most positive exponent, no significand bits set. + kMostPosExponentNoSigBits = math.pow(2, 1023) + message.optional_double = kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostPosExponentNoSigBits) + + # Most positive exponent, one significand bit set. + kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023) + message.optional_double = kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostPosExponentOneSigBit) + + # Repeat last two cases with values of same magnitude, but negative. + message.optional_double = -kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits) + + message.optional_double = -kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit) + + # Most negative exponent, no significand bits set. + kMostNegExponentNoSigBits = math.pow(2, -1023) + message.optional_double = kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostNegExponentNoSigBits) + + # Most negative exponent, one significand bit set. + kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023) + message.optional_double = kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostNegExponentOneSigBit) + + # Repeat last two cases with values of the same magnitude, but negative. + message.optional_double = -kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits) + + message.optional_double = -kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit) + + def testFloatPrinting(self, message_module): + message = message_module.TestAllTypes() + message.optional_float = 2.0 + self.assertEqual(str(message), 'optional_float: 2.0\n') + + def testHighPrecisionFloatPrinting(self, message_module): + message = message_module.TestAllTypes() + message.optional_double = 0.12345678912345678 + if sys.version_info >= (3,): + self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n') + else: + self.assertEqual(str(message), 'optional_double: 0.123456789123\n') + + def testUnknownFieldPrinting(self, message_module): + populated = message_module.TestAllTypes() + test_util.SetAllNonLazyFields(populated) + empty = message_module.TestEmptyMessage() + empty.ParseFromString(populated.SerializeToString()) + self.assertEqual(str(empty), '') + + def testRepeatedNestedFieldIteration(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_nested_message.add(bb=1) + msg.repeated_nested_message.add(bb=2) + msg.repeated_nested_message.add(bb=3) + msg.repeated_nested_message.add(bb=4) + + self.assertEqual([1, 2, 3, 4], + [m.bb for m in msg.repeated_nested_message]) + self.assertEqual([4, 3, 2, 1], + [m.bb for m in reversed(msg.repeated_nested_message)]) + self.assertEqual([4, 3, 2, 1], + [m.bb for m in msg.repeated_nested_message[::-1]]) + + def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module): + """Check some different types with the default comparator.""" + message = message_module.TestAllTypes() + + # TODO(mattp): would testing more scalar types strengthen test? + message.repeated_int32.append(1) + message.repeated_int32.append(3) + message.repeated_int32.append(2) + message.repeated_int32.sort() + self.assertEqual(message.repeated_int32[0], 1) + self.assertEqual(message.repeated_int32[1], 2) + self.assertEqual(message.repeated_int32[2], 3) + self.assertEqual(str(message.repeated_int32), str([1, 2, 3])) + + message.repeated_float.append(1.1) + message.repeated_float.append(1.3) + message.repeated_float.append(1.2) + message.repeated_float.sort() + self.assertAlmostEqual(message.repeated_float[0], 1.1) + self.assertAlmostEqual(message.repeated_float[1], 1.2) + self.assertAlmostEqual(message.repeated_float[2], 1.3) + + message.repeated_string.append('a') + message.repeated_string.append('c') + message.repeated_string.append('b') + message.repeated_string.sort() + self.assertEqual(message.repeated_string[0], 'a') + self.assertEqual(message.repeated_string[1], 'b') + self.assertEqual(message.repeated_string[2], 'c') + self.assertEqual(str(message.repeated_string), str(['a', 'b', 'c'])) + + message.repeated_bytes.append(b'a') + message.repeated_bytes.append(b'c') + message.repeated_bytes.append(b'b') + message.repeated_bytes.sort() + self.assertEqual(message.repeated_bytes[0], b'a') + self.assertEqual(message.repeated_bytes[1], b'b') + self.assertEqual(message.repeated_bytes[2], b'c') + self.assertEqual(str(message.repeated_bytes), str([b'a', b'b', b'c'])) + + def testSortingRepeatedScalarFieldsCustomComparator(self, message_module): + """Check some different types with custom comparator.""" + message = message_module.TestAllTypes() + + message.repeated_int32.append(-3) + message.repeated_int32.append(-2) + message.repeated_int32.append(-1) + message.repeated_int32.sort(key=abs) + self.assertEqual(message.repeated_int32[0], -1) + self.assertEqual(message.repeated_int32[1], -2) + self.assertEqual(message.repeated_int32[2], -3) + + message.repeated_string.append('aaa') + message.repeated_string.append('bb') + message.repeated_string.append('c') + message.repeated_string.sort(key=len) + self.assertEqual(message.repeated_string[0], 'c') + self.assertEqual(message.repeated_string[1], 'bb') + self.assertEqual(message.repeated_string[2], 'aaa') + + def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module): + """Check passing a custom comparator to sort a repeated composite field.""" + message = message_module.TestAllTypes() + + message.repeated_nested_message.add().bb = 1 + message.repeated_nested_message.add().bb = 3 + message.repeated_nested_message.add().bb = 2 + message.repeated_nested_message.add().bb = 6 + message.repeated_nested_message.add().bb = 5 + message.repeated_nested_message.add().bb = 4 + message.repeated_nested_message.sort(key=operator.attrgetter('bb')) + self.assertEqual(message.repeated_nested_message[0].bb, 1) + self.assertEqual(message.repeated_nested_message[1].bb, 2) + self.assertEqual(message.repeated_nested_message[2].bb, 3) + self.assertEqual(message.repeated_nested_message[3].bb, 4) + self.assertEqual(message.repeated_nested_message[4].bb, 5) + self.assertEqual(message.repeated_nested_message[5].bb, 6) + self.assertEqual(str(message.repeated_nested_message), + '[bb: 1\n, bb: 2\n, bb: 3\n, bb: 4\n, bb: 5\n, bb: 6\n]') + + def testSortingRepeatedCompositeFieldsStable(self, message_module): + """Check passing a custom comparator to sort a repeated composite field.""" + message = message_module.TestAllTypes() + + message.repeated_nested_message.add().bb = 21 + message.repeated_nested_message.add().bb = 20 + message.repeated_nested_message.add().bb = 13 + message.repeated_nested_message.add().bb = 33 + message.repeated_nested_message.add().bb = 11 + message.repeated_nested_message.add().bb = 24 + message.repeated_nested_message.add().bb = 10 + message.repeated_nested_message.sort(key=lambda z: z.bb // 10) + self.assertEqual( + [13, 11, 10, 21, 20, 24, 33], + [n.bb for n in message.repeated_nested_message]) + + # Make sure that for the C++ implementation, the underlying fields + # are actually reordered. + pb = message.SerializeToString() + message.Clear() + message.MergeFromString(pb) + self.assertEqual( + [13, 11, 10, 21, 20, 24, 33], + [n.bb for n in message.repeated_nested_message]) + + def testRepeatedCompositeFieldSortArguments(self, message_module): + """Check sorting a repeated composite field using list.sort() arguments.""" + message = message_module.TestAllTypes() + + get_bb = operator.attrgetter('bb') + cmp_bb = lambda a, b: cmp(a.bb, b.bb) + message.repeated_nested_message.add().bb = 1 + message.repeated_nested_message.add().bb = 3 + message.repeated_nested_message.add().bb = 2 + message.repeated_nested_message.add().bb = 6 + message.repeated_nested_message.add().bb = 5 + message.repeated_nested_message.add().bb = 4 + message.repeated_nested_message.sort(key=get_bb) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [1, 2, 3, 4, 5, 6]) + message.repeated_nested_message.sort(key=get_bb, reverse=True) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [6, 5, 4, 3, 2, 1]) + if sys.version_info >= (3,): return # No cmp sorting in PY3. + message.repeated_nested_message.sort(sort_function=cmp_bb) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [1, 2, 3, 4, 5, 6]) + message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [6, 5, 4, 3, 2, 1]) + + def testRepeatedScalarFieldSortArguments(self, message_module): + """Check sorting a scalar field using list.sort() arguments.""" + message = message_module.TestAllTypes() + + message.repeated_int32.append(-3) + message.repeated_int32.append(-2) + message.repeated_int32.append(-1) + message.repeated_int32.sort(key=abs) + self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) + message.repeated_int32.sort(key=abs, reverse=True) + self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) + if sys.version_info < (3,): # No cmp sorting in PY3. + abs_cmp = lambda a, b: cmp(abs(a), abs(b)) + message.repeated_int32.sort(sort_function=abs_cmp) + self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) + message.repeated_int32.sort(cmp=abs_cmp, reverse=True) + self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) + + message.repeated_string.append('aaa') + message.repeated_string.append('bb') + message.repeated_string.append('c') + message.repeated_string.sort(key=len) + self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) + message.repeated_string.sort(key=len, reverse=True) + self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) + if sys.version_info < (3,): # No cmp sorting in PY3. + len_cmp = lambda a, b: cmp(len(a), len(b)) + message.repeated_string.sort(sort_function=len_cmp) + self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) + message.repeated_string.sort(cmp=len_cmp, reverse=True) + self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) + + def testRepeatedFieldsComparable(self, message_module): + m1 = message_module.TestAllTypes() + m2 = message_module.TestAllTypes() + m1.repeated_int32.append(0) + m1.repeated_int32.append(1) + m1.repeated_int32.append(2) + m2.repeated_int32.append(0) + m2.repeated_int32.append(1) + m2.repeated_int32.append(2) + m1.repeated_nested_message.add().bb = 1 + m1.repeated_nested_message.add().bb = 2 + m1.repeated_nested_message.add().bb = 3 + m2.repeated_nested_message.add().bb = 1 + m2.repeated_nested_message.add().bb = 2 + m2.repeated_nested_message.add().bb = 3 + + if sys.version_info >= (3,): return # No cmp() in PY3. + + # These comparisons should not raise errors. + _ = m1 < m2 + _ = m1.repeated_nested_message < m2.repeated_nested_message + + # Make sure cmp always works. If it wasn't defined, these would be + # id() comparisons and would all fail. + self.assertEqual(cmp(m1, m2), 0) + self.assertEqual(cmp(m1.repeated_int32, m2.repeated_int32), 0) + self.assertEqual(cmp(m1.repeated_int32, [0, 1, 2]), 0) + self.assertEqual(cmp(m1.repeated_nested_message, + m2.repeated_nested_message), 0) + with self.assertRaises(TypeError): + # Can't compare repeated composite containers to lists. + cmp(m1.repeated_nested_message, m2.repeated_nested_message[:]) + + # TODO(anuraag): Implement extensiondict comparison in C++ and then add test + + def testRepeatedFieldsAreSequences(self, message_module): + m = message_module.TestAllTypes() + self.assertIsInstance(m.repeated_int32, collections.MutableSequence) + self.assertIsInstance(m.repeated_nested_message, + collections.MutableSequence) + + def testRepeatedFieldsNotHashable(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(TypeError): + hash(m.repeated_int32) + with self.assertRaises(TypeError): + hash(m.repeated_nested_message) + + def testRepeatedFieldInsideNestedMessage(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.repeated_int32.extend([]) + self.assertTrue(m.HasField('payload')) + + def ensureNestedMessageExists(self, msg, attribute): + """Make sure that a nested message object exists. + + As soon as a nested message attribute is accessed, it will be present in the + _fields dict, without being marked as actually being set. + """ + getattr(msg, attribute) + self.assertFalse(msg.HasField(attribute)) + + def testOneofGetCaseNonexistingField(self, message_module): + m = message_module.TestAllTypes() + self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field') + self.assertRaises(Exception, m.WhichOneof, 0) + + def testOneofDefaultValues(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + + # Oneof is set even when setting it to a default value. + m.oneof_uint32 = 0 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + self.assertFalse(m.HasField('oneof_string')) + + m.oneof_string = "" + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_uint32')) + + def testOneofSemantics(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + + m.oneof_uint32 = 11 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + + m.oneof_string = 'foo' + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertTrue(m.HasField('oneof_string')) + + # Read nested message accessor without accessing submessage. + m.oneof_nested_message + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_nested_message')) + + # Read accessor of nested message without accessing submessage. + m.oneof_nested_message.bb + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_nested_message')) + + m.oneof_nested_message.bb = 11 + self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_string')) + self.assertTrue(m.HasField('oneof_nested_message')) + + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_nested_message')) + self.assertTrue(m.HasField('oneof_bytes')) + + def testOneofCompositeFieldReadAccess(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + + self.ensureNestedMessageExists(m, 'oneof_nested_message') + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertEqual(11, m.oneof_uint32) + + def testOneofWhichOneof(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + + m.oneof_uint32 = 11 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertTrue(m.HasField('oneof_field')) + + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + + m.ClearField('oneof_bytes') + self.assertIs(None, m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + + def testOneofClearField(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m.ClearField('oneof_field') + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertIs(None, m.WhichOneof('oneof_field')) + + def testOneofClearSetField(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m.ClearField('oneof_uint32') + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertIs(None, m.WhichOneof('oneof_field')) + + def testOneofClearUnsetField(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + self.ensureNestedMessageExists(m, 'oneof_nested_message') + m.ClearField('oneof_nested_message') + self.assertEqual(11, m.oneof_uint32) + if message_module is unittest_pb2: + self.assertTrue(m.HasField('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + + def testOneofDeserialize(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + m2.ParseFromString(m.SerializeToString()) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testOneofCopyFrom(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + m2.CopyFrom(m) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testOneofNestedMergeFrom(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.oneof_uint32 = 11 + m2 = message_module.NestedTestAllTypes() + m2.payload.oneof_bytes = b'bb' + m2.child.payload.oneof_bytes = b'bb' + m2.MergeFrom(m) + self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field')) + self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field')) + + def testOneofMessageMergeFrom(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.oneof_nested_message.bb = 11 + m.child.payload.oneof_nested_message.bb = 12 + m2 = message_module.NestedTestAllTypes() + m2.payload.oneof_uint32 = 13 + m2.MergeFrom(m) + self.assertEqual('oneof_nested_message', + m2.payload.WhichOneof('oneof_field')) + self.assertEqual('oneof_nested_message', + m2.child.payload.WhichOneof('oneof_field')) + + def testOneofNestedMessageInit(self, message_module): + m = message_module.TestAllTypes( + oneof_nested_message=message_module.TestAllTypes.NestedMessage()) + self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field')) + + def testOneofClear(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m.Clear() + self.assertIsNone(m.WhichOneof('oneof_field')) + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + + def testAssignByteStringToUnicodeField(self, message_module): + """Assigning a byte string to a string field should result + in the value being converted to a Unicode string.""" + m = message_module.TestAllTypes() + m.optional_string = str('') + self.assertIsInstance(m.optional_string, six.text_type) + + def testLongValuedSlice(self, message_module): + """It should be possible to use long-valued indicies in slices + + This didn't used to work in the v2 C++ implementation. + """ + m = message_module.TestAllTypes() + + # Repeated scalar + m.repeated_int32.append(1) + sl = m.repeated_int32[int(0):int(len(m.repeated_int32))] + self.assertEqual(len(m.repeated_int32), len(sl)) + + # Repeated composite + m.repeated_nested_message.add().bb = 3 + sl = m.repeated_nested_message[int(0):int(len(m.repeated_nested_message))] + self.assertEqual(len(m.repeated_nested_message), len(sl)) + + def testExtendShouldNotSwallowExceptions(self, message_module): + """This didn't use to work in the v2 C++ implementation.""" + m = message_module.TestAllTypes() + with self.assertRaises(NameError) as _: + m.repeated_int32.extend(a for i in range(10)) # pylint: disable=undefined-variable + with self.assertRaises(NameError) as _: + m.repeated_nested_enum.extend( + a for i in range(10)) # pylint: disable=undefined-variable + + FALSY_VALUES = [None, False, 0, 0.0, b'', '', bytearray(), [], {}, set()] + + def testExtendInt32WithNothing(self, message_module): + """Test no-ops extending repeated int32 fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_int32.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_int32) + + m.repeated_int32.extend([]) + self.assertSequenceEqual([], m.repeated_int32) + + def testExtendFloatWithNothing(self, message_module): + """Test no-ops extending repeated float fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_float.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_float) + + m.repeated_float.extend([]) + self.assertSequenceEqual([], m.repeated_float) + + def testExtendStringWithNothing(self, message_module): + """Test no-ops extending repeated string fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_string.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_string) + + m.repeated_string.extend([]) + self.assertSequenceEqual([], m.repeated_string) + + def testExtendInt32WithPythonList(self, message_module): + """Test extending repeated int32 fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend([0]) + self.assertSequenceEqual([0], m.repeated_int32) + m.repeated_int32.extend([1, 2]) + self.assertSequenceEqual([0, 1, 2], m.repeated_int32) + m.repeated_int32.extend([3, 4]) + self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32) + + def testExtendFloatWithPythonList(self, message_module): + """Test extending repeated float fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend([0.0]) + self.assertSequenceEqual([0.0], m.repeated_float) + m.repeated_float.extend([1.0, 2.0]) + self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float) + m.repeated_float.extend([3.0, 4.0]) + self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float) + + def testExtendStringWithPythonList(self, message_module): + """Test extending repeated string fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(['']) + self.assertSequenceEqual([''], m.repeated_string) + m.repeated_string.extend(['11', '22']) + self.assertSequenceEqual(['', '11', '22'], m.repeated_string) + m.repeated_string.extend(['33', '44']) + self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string) + + def testExtendStringWithString(self, message_module): + """Test extending repeated string fields with characters from a string.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend('abc') + self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string) + + class TestIterable(object): + """This iterable object mimics the behavior of numpy.array. + + __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1. + + """ + + def __init__(self, values=None): + self._list = values or [] + + def __bool__(self): + size = len(self._list) + if size == 0: + return False + if size == 1: + return bool(self._list[0]) + raise ValueError('Truth value is ambiguous.') + + def __len__(self): + return len(self._list) + + def __iter__(self): + return self._list.__iter__() + + def testExtendInt32WithIterable(self, message_module): + """Test extending repeated int32 fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([0])) + self.assertSequenceEqual([0], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([1, 2])) + self.assertSequenceEqual([0, 1, 2], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([3, 4])) + self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32) + + def testExtendFloatWithIterable(self, message_module): + """Test extending repeated float fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([0.0])) + self.assertSequenceEqual([0.0], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0])) + self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0])) + self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float) + + def testExtendStringWithIterable(self, message_module): + """Test extending repeated string fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable([''])) + self.assertSequenceEqual([''], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable(['1', '2'])) + self.assertSequenceEqual(['', '1', '2'], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable(['3', '4'])) + self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string) + + def testPickleRepeatedScalarContainer(self, message_module): + # TODO(tibell): The pure-Python implementation support pickling of + # scalar containers in *some* cases. For now the cpp2 version + # throws an exception to avoid a segfault. Investigate if we + # want to support pickling of these fields. + # + # For more information see: https://b2.corp.google.com/u/0/issues/18677897 + if (api_implementation.Type() != 'cpp' or + api_implementation.Version() == 2): + return + m = message_module.TestAllTypes() + with self.assertRaises(pickle.PickleError) as _: + pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL) + + def testSortEmptyRepeatedCompositeContainer(self, message_module): + """Exercise a scenario that has led to segfaults in the past. + """ + m = message_module.TestAllTypes() + m.repeated_nested_message.sort() + + def testHasFieldOnRepeatedField(self, message_module): + """Using HasField on a repeated field should raise an exception. + """ + m = message_module.TestAllTypes() + with self.assertRaises(ValueError) as _: + m.HasField('repeated_int32') + + def testRepeatedScalarFieldPop(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(IndexError) as _: + m.repeated_int32.pop() + m.repeated_int32.extend(list(range(5))) + self.assertEqual(4, m.repeated_int32.pop()) + self.assertEqual(0, m.repeated_int32.pop(0)) + self.assertEqual(2, m.repeated_int32.pop(1)) + self.assertEqual([1, 3], m.repeated_int32) + + def testRepeatedCompositeFieldPop(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(IndexError) as _: + m.repeated_nested_message.pop() + with self.assertRaises(TypeError) as _: + m.repeated_nested_message.pop('0') + for i in range(5): + n = m.repeated_nested_message.add() + n.bb = i + self.assertEqual(4, m.repeated_nested_message.pop().bb) + self.assertEqual(0, m.repeated_nested_message.pop(0).bb) + self.assertEqual(2, m.repeated_nested_message.pop(1).bb) + self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message]) + + def testRepeatedCompareWithSelf(self, message_module): + m = message_module.TestAllTypes() + for i in range(5): + m.repeated_int32.insert(i, i) + n = m.repeated_nested_message.add() + n.bb = i + self.assertSequenceEqual(m.repeated_int32, m.repeated_int32) + self.assertEqual(m.repeated_nested_message, m.repeated_nested_message) + + def testReleasedNestedMessages(self, message_module): + """A case that lead to a segfault when a message detached from its parent + container has itself a child container. + """ + m = message_module.NestedTestAllTypes() + m = m.repeated_child.add() + m = m.child + m = m.repeated_child.add() + self.assertEqual(m.payload.optional_int32, 0) + + def testSetRepeatedComposite(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(AttributeError): + m.repeated_int32 = [] + m.repeated_int32.append(1) + if api_implementation.Type() == 'cpp': + # For test coverage: cpp has a different path if composite + # field is in cache + with self.assertRaises(TypeError): + m.repeated_int32 = [] + else: + with self.assertRaises(AttributeError): + m.repeated_int32 = [] + + +# Class to test proto2-only features (required, extensions, etc.) +class Proto2Test(BaseTestCase): + + def testFieldPresence(self): + message = unittest_pb2.TestAllTypes() + + self.assertFalse(message.HasField("optional_int32")) + self.assertFalse(message.HasField("optional_bool")) + self.assertFalse(message.HasField("optional_nested_message")) + + with self.assertRaises(ValueError): + message.HasField("field_doesnt_exist") + + with self.assertRaises(ValueError): + message.HasField("repeated_int32") + with self.assertRaises(ValueError): + message.HasField("repeated_nested_message") + + self.assertEqual(0, message.optional_int32) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # Fields are set even when setting the values to default values. + message.optional_int32 = 0 + message.optional_bool = False + message.optional_nested_message.bb = 0 + self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField("optional_bool")) + self.assertTrue(message.HasField("optional_nested_message")) + + # Set the fields to non-default values. + message.optional_int32 = 5 + message.optional_bool = True + message.optional_nested_message.bb = 15 + + self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField("optional_bool")) + self.assertTrue(message.HasField("optional_nested_message")) + + # Clearing the fields unsets them and resets their value to default. + message.ClearField("optional_int32") + message.ClearField("optional_bool") + message.ClearField("optional_nested_message") + + self.assertFalse(message.HasField("optional_int32")) + self.assertFalse(message.HasField("optional_bool")) + self.assertFalse(message.HasField("optional_nested_message")) + self.assertEqual(0, message.optional_int32) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + def testAssignInvalidEnum(self): + """Assigning an invalid enum number is not allowed in proto2.""" + m = unittest_pb2.TestAllTypes() + + # Proto2 can not assign unknown enum. + with self.assertRaises(ValueError) as _: + m.optional_nested_enum = 1234567 + self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum.append(2) + m.repeated_nested_enum[0] = 2 + with self.assertRaises(ValueError): + m.repeated_nested_enum[0] = 123456 + + # Unknown enum value can be parsed but is ignored. + m2 = unittest_proto3_arena_pb2.TestAllTypes() + m2.optional_nested_enum = 1234567 + m2.repeated_nested_enum.append(7654321) + serialized = m2.SerializeToString() + + m3 = unittest_pb2.TestAllTypes() + m3.ParseFromString(serialized) + self.assertFalse(m3.HasField('optional_nested_enum')) + # 1 is the default value for optional_nested_enum. + self.assertEqual(1, m3.optional_nested_enum) + self.assertEqual(0, len(m3.repeated_nested_enum)) + m2.Clear() + m2.ParseFromString(m3.SerializeToString()) + self.assertEqual(1234567, m2.optional_nested_enum) + self.assertEqual(7654321, m2.repeated_nested_enum[0]) + + def testUnknownEnumMap(self): + m = map_proto2_unittest_pb2.TestEnumMap() + m.known_map_field[123] = 0 + with self.assertRaises(ValueError): + m.unknown_map_field[1] = 123 + + def testExtensionsErrors(self): + msg = unittest_pb2.TestAllTypes() + self.assertRaises(AttributeError, getattr, msg, 'Extensions') + + def testGoldenExtensions(self): + golden_data = test_util.GoldenFileData('golden_message') + golden_message = unittest_pb2.TestAllExtensions() + golden_message.ParseFromString(golden_data) + all_set = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testGoldenPackedExtensions(self): + golden_data = test_util.GoldenFileData('golden_packed_fields_message') + golden_message = unittest_pb2.TestPackedExtensions() + golden_message.ParseFromString(golden_data) + all_set = unittest_pb2.TestPackedExtensions() + test_util.SetAllPackedExtensions(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testPickleIncompleteProto(self): + golden_message = unittest_pb2.TestRequired(a=1) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + self.assertEqual(unpickled_message.a, 1) + # This is still an incomplete proto - so serializing should fail + self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) + + + # TODO(haberman): this isn't really a proto2-specific test except that this + # message has a required field in it. Should probably be factored out so + # that we can test the other parts with proto3. + def testParsingMerge(self): + """Check the merge behavior when a required or optional field appears + multiple times in the input.""" + messages = [ + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes() ] + messages[0].optional_int32 = 1 + messages[1].optional_int64 = 2 + messages[2].optional_int32 = 3 + messages[2].optional_string = 'hello' + + merged_message = unittest_pb2.TestAllTypes() + merged_message.optional_int32 = 3 + merged_message.optional_int64 = 2 + merged_message.optional_string = 'hello' + + generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator() + generator.field1.extend(messages) + generator.field2.extend(messages) + generator.field3.extend(messages) + generator.ext1.extend(messages) + generator.ext2.extend(messages) + generator.group1.add().field1.MergeFrom(messages[0]) + generator.group1.add().field1.MergeFrom(messages[1]) + generator.group1.add().field1.MergeFrom(messages[2]) + generator.group2.add().field1.MergeFrom(messages[0]) + generator.group2.add().field1.MergeFrom(messages[1]) + generator.group2.add().field1.MergeFrom(messages[2]) + + data = generator.SerializeToString() + parsing_merge = unittest_pb2.TestParsingMerge() + parsing_merge.ParseFromString(data) + + # Required and optional fields should be merged. + self.assertEqual(parsing_merge.required_all_types, merged_message) + self.assertEqual(parsing_merge.optional_all_types, merged_message) + self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types, + merged_message) + self.assertEqual(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.optional_ext], + merged_message) + + # Repeated fields should not be merged. + self.assertEqual(len(parsing_merge.repeated_all_types), 3) + self.assertEqual(len(parsing_merge.repeatedgroup), 3) + self.assertEqual(len(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.repeated_ext]), 3) + + def testPythonicInit(self): + message = unittest_pb2.TestAllTypes( + optional_int32=100, + optional_fixed32=200, + optional_float=300.5, + optional_bytes=b'x', + optionalgroup={'a': 400}, + optional_nested_message={'bb': 500}, + optional_foreign_message={}, + optional_nested_enum='BAZ', + repeatedgroup=[{'a': 600}, + {'a': 700}], + repeated_nested_enum=['FOO', unittest_pb2.TestAllTypes.BAR], + default_int32=800, + oneof_string='y') + self.assertIsInstance(message, unittest_pb2.TestAllTypes) + self.assertEqual(100, message.optional_int32) + self.assertEqual(200, message.optional_fixed32) + self.assertEqual(300.5, message.optional_float) + self.assertEqual(b'x', message.optional_bytes) + self.assertEqual(400, message.optionalgroup.a) + self.assertIsInstance(message.optional_nested_message, + unittest_pb2.TestAllTypes.NestedMessage) + self.assertEqual(500, message.optional_nested_message.bb) + self.assertTrue(message.HasField('optional_foreign_message')) + self.assertEqual(message.optional_foreign_message, + unittest_pb2.ForeignMessage()) + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + self.assertEqual(2, len(message.repeatedgroup)) + self.assertEqual(600, message.repeatedgroup[0].a) + self.assertEqual(700, message.repeatedgroup[1].a) + self.assertEqual(2, len(message.repeated_nested_enum)) + self.assertEqual(unittest_pb2.TestAllTypes.FOO, + message.repeated_nested_enum[0]) + self.assertEqual(unittest_pb2.TestAllTypes.BAR, + message.repeated_nested_enum[1]) + self.assertEqual(800, message.default_int32) + self.assertEqual('y', message.oneof_string) + self.assertFalse(message.HasField('optional_int64')) + self.assertEqual(0, len(message.repeated_float)) + self.assertEqual(42, message.default_int64) + + message = unittest_pb2.TestAllTypes(optional_nested_enum='BAZ') + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes( + optional_nested_message={'INVALID_NESTED_FIELD': 17}) + + with self.assertRaises(TypeError): + unittest_pb2.TestAllTypes( + optional_nested_message={'bb': 'INVALID_VALUE_TYPE'}) + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes(optional_nested_enum='INVALID_LABEL') + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes(repeated_nested_enum='FOO') + + + +# Class to test proto3-only features/behavior (updated field presence & enums) +class Proto3Test(BaseTestCase): + + # Utility method for comparing equality with a map. + def assertMapIterEquals(self, map_iter, dict_value): + # Avoid mutating caller's copy. + dict_value = dict(dict_value) + + for k, v in map_iter: + self.assertEqual(v, dict_value[k]) + del dict_value[k] + + self.assertEqual({}, dict_value) + + def testFieldPresence(self): + message = unittest_proto3_arena_pb2.TestAllTypes() + + # We can't test presence of non-repeated, non-submessage fields. + with self.assertRaises(ValueError): + message.HasField('optional_int32') + with self.assertRaises(ValueError): + message.HasField('optional_float') + with self.assertRaises(ValueError): + message.HasField('optional_string') + with self.assertRaises(ValueError): + message.HasField('optional_bool') + + # But we can still test presence of submessage fields. + self.assertFalse(message.HasField('optional_nested_message')) + + # As with proto2, we can't test presence of fields that don't exist, or + # repeated fields. + with self.assertRaises(ValueError): + message.HasField('field_doesnt_exist') + + with self.assertRaises(ValueError): + message.HasField('repeated_int32') + with self.assertRaises(ValueError): + message.HasField('repeated_nested_message') + + # Fields should default to their type-specific default. + self.assertEqual(0, message.optional_int32) + self.assertEqual(0, message.optional_float) + self.assertEqual('', message.optional_string) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # Setting a submessage should still return proper presence information. + message.optional_nested_message.bb = 0 + self.assertTrue(message.HasField('optional_nested_message')) + + # Set the fields to non-default values. + message.optional_int32 = 5 + message.optional_float = 1.1 + message.optional_string = 'abc' + message.optional_bool = True + message.optional_nested_message.bb = 15 + + # Clearing the fields unsets them and resets their value to default. + message.ClearField('optional_int32') + message.ClearField('optional_float') + message.ClearField('optional_string') + message.ClearField('optional_bool') + message.ClearField('optional_nested_message') + + self.assertEqual(0, message.optional_int32) + self.assertEqual(0, message.optional_float) + self.assertEqual('', message.optional_string) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + def testAssignUnknownEnum(self): + """Assigning an unknown enum value is allowed and preserves the value.""" + m = unittest_proto3_arena_pb2.TestAllTypes() + + # Proto3 can assign unknown enums. + m.optional_nested_enum = 1234567 + self.assertEqual(1234567, m.optional_nested_enum) + m.repeated_nested_enum.append(22334455) + self.assertEqual(22334455, m.repeated_nested_enum[0]) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum[0] = 7654321 + self.assertEqual(7654321, m.repeated_nested_enum[0]) + serialized = m.SerializeToString() + + m2 = unittest_proto3_arena_pb2.TestAllTypes() + m2.ParseFromString(serialized) + self.assertEqual(1234567, m2.optional_nested_enum) + self.assertEqual(7654321, m2.repeated_nested_enum[0]) + + # Map isn't really a proto3-only feature. But there is no proto2 equivalent + # of google/protobuf/map_unittest.proto right now, so it's not easy to + # test both with the same test like we do for the other proto2/proto3 tests. + # (google/protobuf/map_proto2_unittest.proto is very different in the set + # of messages and fields it contains). + def testScalarMapDefaults(self): + msg = map_unittest_pb2.TestMap() + + # Scalars start out unset. + self.assertFalse(-123 in msg.map_int32_int32) + self.assertFalse(-2**33 in msg.map_int64_int64) + self.assertFalse(123 in msg.map_uint32_uint32) + self.assertFalse(2**33 in msg.map_uint64_uint64) + self.assertFalse(123 in msg.map_int32_double) + self.assertFalse(False in msg.map_bool_bool) + self.assertFalse('abc' in msg.map_string_string) + self.assertFalse(111 in msg.map_int32_bytes) + self.assertFalse(888 in msg.map_int32_enum) + + # Accessing an unset key returns the default. + self.assertEqual(0, msg.map_int32_int32[-123]) + self.assertEqual(0, msg.map_int64_int64[-2**33]) + self.assertEqual(0, msg.map_uint32_uint32[123]) + self.assertEqual(0, msg.map_uint64_uint64[2**33]) + self.assertEqual(0.0, msg.map_int32_double[123]) + self.assertTrue(isinstance(msg.map_int32_double[123], float)) + self.assertEqual(False, msg.map_bool_bool[False]) + self.assertTrue(isinstance(msg.map_bool_bool[False], bool)) + self.assertEqual('', msg.map_string_string['abc']) + self.assertEqual(b'', msg.map_int32_bytes[111]) + self.assertEqual(0, msg.map_int32_enum[888]) + + # It also sets the value in the map + self.assertTrue(-123 in msg.map_int32_int32) + self.assertTrue(-2**33 in msg.map_int64_int64) + self.assertTrue(123 in msg.map_uint32_uint32) + self.assertTrue(2**33 in msg.map_uint64_uint64) + self.assertTrue(123 in msg.map_int32_double) + self.assertTrue(False in msg.map_bool_bool) + self.assertTrue('abc' in msg.map_string_string) + self.assertTrue(111 in msg.map_int32_bytes) + self.assertTrue(888 in msg.map_int32_enum) + + self.assertIsInstance(msg.map_string_string['abc'], six.text_type) + + # Accessing an unset key still throws TypeError if the type of the key + # is incorrect. + with self.assertRaises(TypeError): + msg.map_string_string[123] + + with self.assertRaises(TypeError): + 123 in msg.map_string_string + + def testMapGet(self): + # Need to test that get() properly returns the default, even though the dict + # has defaultdict-like semantics. + msg = map_unittest_pb2.TestMap() + + self.assertIsNone(msg.map_int32_int32.get(5)) + self.assertEqual(10, msg.map_int32_int32.get(5, 10)) + self.assertIsNone(msg.map_int32_int32.get(5)) + + msg.map_int32_int32[5] = 15 + self.assertEqual(15, msg.map_int32_int32.get(5)) + self.assertEqual(15, msg.map_int32_int32.get(5)) + with self.assertRaises(TypeError): + msg.map_int32_int32.get('') + + self.assertIsNone(msg.map_int32_foreign_message.get(5)) + self.assertEqual(10, msg.map_int32_foreign_message.get(5, 10)) + + submsg = msg.map_int32_foreign_message[5] + self.assertIs(submsg, msg.map_int32_foreign_message.get(5)) + with self.assertRaises(TypeError): + msg.map_int32_foreign_message.get('') + + def testScalarMap(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_int32)) + self.assertFalse(5 in msg.map_int32_int32) + + msg.map_int32_int32[-123] = -456 + msg.map_int64_int64[-2**33] = -2**34 + msg.map_uint32_uint32[123] = 456 + msg.map_uint64_uint64[2**33] = 2**34 + msg.map_int32_float[2] = 1.2 + msg.map_int32_double[1] = 3.3 + msg.map_string_string['abc'] = '123' + msg.map_bool_bool[True] = True + msg.map_int32_enum[888] = 2 + # Unknown numeric enum is supported in proto3. + msg.map_int32_enum[123] = 456 + + self.assertEqual([], msg.FindInitializationErrors()) + + self.assertEqual(1, len(msg.map_string_string)) + + # Bad key. + with self.assertRaises(TypeError): + msg.map_string_string[123] = '123' + + # Verify that trying to assign a bad key doesn't actually add a member to + # the map. + self.assertEqual(1, len(msg.map_string_string)) + + # Bad value. + with self.assertRaises(TypeError): + msg.map_string_string['123'] = 123 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + # Bad key. + with self.assertRaises(TypeError): + msg2.map_string_string[123] = '123' + + # Bad value. + with self.assertRaises(TypeError): + msg2.map_string_string['123'] = 123 + + self.assertEqual(-456, msg2.map_int32_int32[-123]) + self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) + self.assertEqual(456, msg2.map_uint32_uint32[123]) + self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + self.assertAlmostEqual(1.2, msg.map_int32_float[2]) + self.assertEqual(3.3, msg.map_int32_double[1]) + self.assertEqual('123', msg2.map_string_string['abc']) + self.assertEqual(True, msg2.map_bool_bool[True]) + self.assertEqual(2, msg2.map_int32_enum[888]) + self.assertEqual(456, msg2.map_int32_enum[123]) + # TODO(jieluo): Add cpp extension support. + if api_implementation.Type() == 'python': + self.assertEqual('{-123: -456}', + str(msg2.map_int32_int32)) + + def testMapEntryAlwaysSerialized(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[0] = 0 + msg.map_string_string[''] = '' + self.assertEqual(msg.ByteSize(), 12) + self.assertEqual(b'\n\x04\x08\x00\x10\x00r\x04\n\x00\x12\x00', + msg.SerializeToString()) + + def testStringUnicodeConversionInMap(self): + msg = map_unittest_pb2.TestMap() + + unicode_obj = '\u1234' + bytes_obj = unicode_obj.encode('utf8') + + msg.map_string_string[bytes_obj] = bytes_obj + + (key, value) = list(msg.map_string_string.items())[0] + + self.assertEqual(key, unicode_obj) + self.assertEqual(value, unicode_obj) + + self.assertIsInstance(key, six.text_type) + self.assertIsInstance(value, six.text_type) + + def testMessageMap(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_foreign_message)) + self.assertFalse(5 in msg.map_int32_foreign_message) + + msg.map_int32_foreign_message[123] + # get_or_create() is an alias for getitem. + msg.map_int32_foreign_message.get_or_create(-456) + + self.assertEqual(2, len(msg.map_int32_foreign_message)) + self.assertIn(123, msg.map_int32_foreign_message) + self.assertIn(-456, msg.map_int32_foreign_message) + self.assertEqual(2, len(msg.map_int32_foreign_message)) + + # Bad key. + with self.assertRaises(TypeError): + msg.map_int32_foreign_message['123'] + + # Can't assign directly to submessage. + with self.assertRaises(ValueError): + msg.map_int32_foreign_message[999] = msg.map_int32_foreign_message[123] + + # Verify that trying to assign a bad key doesn't actually add a member to + # the map. + self.assertEqual(2, len(msg.map_int32_foreign_message)) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(2, len(msg2.map_int32_foreign_message)) + self.assertIn(123, msg2.map_int32_foreign_message) + self.assertIn(-456, msg2.map_int32_foreign_message) + self.assertEqual(2, len(msg2.map_int32_foreign_message)) + # TODO(jieluo): Fix text format for message map. + # TODO(jieluo): Add cpp extension support. + if api_implementation.Type() == 'python': + self.assertEqual(15, + len(str(msg2.map_int32_foreign_message))) + + def testNestedMessageMapItemDelete(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_all_types[1].optional_nested_message.bb = 1 + del msg.map_int32_all_types[1] + msg.map_int32_all_types[2].optional_nested_message.bb = 2 + self.assertEqual(1, len(msg.map_int32_all_types)) + msg.map_int32_all_types[1].optional_nested_message.bb = 1 + self.assertEqual(2, len(msg.map_int32_all_types)) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + keys = [1, 2] + # The loop triggers PyErr_Occurred() in c extension. + for key in keys: + del msg2.map_int32_all_types[key] + + def testMapByteSize(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[1] = 1 + size = msg.ByteSize() + msg.map_int32_int32[1] = 128 + self.assertEqual(msg.ByteSize(), size + 1) + + msg.map_int32_foreign_message[19].c = 1 + size = msg.ByteSize() + msg.map_int32_foreign_message[19].c = 128 + self.assertEqual(msg.ByteSize(), size + 1) + + def testMergeFrom(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[12] = 34 + msg.map_int32_int32[56] = 78 + msg.map_int64_int64[22] = 33 + msg.map_int32_foreign_message[111].c = 5 + msg.map_int32_foreign_message[222].c = 10 + + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_int32[12] = 55 + msg2.map_int64_int64[88] = 99 + msg2.map_int32_foreign_message[222].c = 15 + msg2.map_int32_foreign_message[222].d = 20 + old_map_value = msg2.map_int32_foreign_message[222] + + msg2.MergeFrom(msg) + + self.assertEqual(34, msg2.map_int32_int32[12]) + self.assertEqual(78, msg2.map_int32_int32[56]) + self.assertEqual(33, msg2.map_int64_int64[22]) + self.assertEqual(99, msg2.map_int64_int64[88]) + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + self.assertEqual(10, msg2.map_int32_foreign_message[222].c) + self.assertFalse(msg2.map_int32_foreign_message[222].HasField('d')) + if api_implementation.Type() != 'cpp': + # During the call to MergeFrom(), the C++ implementation will have + # deallocated the underlying message, but this is very difficult to detect + # properly. The line below is likely to cause a segmentation fault. + # With the Python implementation, old_map_value is just 'detached' from + # the main message. Using it will not crash of course, but since it still + # have a reference to the parent message I'm sure we can find interesting + # ways to cause inconsistencies. + self.assertEqual(15, old_map_value.c) + + # Verify that there is only one entry per key, even though the MergeFrom + # may have internally created multiple entries for a single key in the + # list representation. + as_dict = {} + for key in msg2.map_int32_foreign_message: + self.assertFalse(key in as_dict) + as_dict[key] = msg2.map_int32_foreign_message[key].c + + self.assertEqual({111: 5, 222: 10}, as_dict) + + # Special case: test that delete of item really removes the item, even if + # there might have physically been duplicate keys due to the previous merge. + # This is only a special case for the C++ implementation which stores the + # map as an array. + del msg2.map_int32_int32[12] + self.assertFalse(12 in msg2.map_int32_int32) + + del msg2.map_int32_foreign_message[222] + self.assertFalse(222 in msg2.map_int32_foreign_message) + with self.assertRaises(TypeError): + del msg2.map_int32_foreign_message[''] + + def testMapMergeFrom(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[12] = 34 + msg.map_int32_int32[56] = 78 + msg.map_int64_int64[22] = 33 + msg.map_int32_foreign_message[111].c = 5 + msg.map_int32_foreign_message[222].c = 10 + + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_int32[12] = 55 + msg2.map_int64_int64[88] = 99 + msg2.map_int32_foreign_message[222].c = 15 + msg2.map_int32_foreign_message[222].d = 20 + + msg2.map_int32_int32.MergeFrom(msg.map_int32_int32) + self.assertEqual(34, msg2.map_int32_int32[12]) + self.assertEqual(78, msg2.map_int32_int32[56]) + + msg2.map_int64_int64.MergeFrom(msg.map_int64_int64) + self.assertEqual(33, msg2.map_int64_int64[22]) + self.assertEqual(99, msg2.map_int64_int64[88]) + + msg2.map_int32_foreign_message.MergeFrom(msg.map_int32_foreign_message) + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + self.assertEqual(10, msg2.map_int32_foreign_message[222].c) + self.assertFalse(msg2.map_int32_foreign_message[222].HasField('d')) + + def testMergeFromBadType(self): + msg = map_unittest_pb2.TestMap() + with self.assertRaisesRegex( + TypeError, + r'Parameter to MergeFrom\(\) must be instance of same class: expected ' + r'.*TestMap got int\.'): + msg.MergeFrom(1) + + def testCopyFromBadType(self): + msg = map_unittest_pb2.TestMap() + with self.assertRaisesRegex( + TypeError, + r'Parameter to [A-Za-z]*From\(\) must be instance of same class: ' + r'expected .*TestMap got int\.'): + msg.CopyFrom(1) + + def testIntegerMapWithLongs(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[int(-123)] = int(-456) + msg.map_int64_int64[int(-2**33)] = int(-2**34) + msg.map_uint32_uint32[int(123)] = int(456) + msg.map_uint64_uint64[int(2**33)] = int(2**34) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(-456, msg2.map_int32_int32[-123]) + self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) + self.assertEqual(456, msg2.map_uint32_uint32[123]) + self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + + def testMapAssignmentCausesPresence(self): + msg = map_unittest_pb2.TestMapSubmessage() + msg.test_map.map_int32_int32[123] = 456 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMapSubmessage() + msg2.ParseFromString(serialized) + + self.assertEqual(msg, msg2) + + # Now test that various mutations of the map properly invalidate the + # cached size of the submessage. + msg.test_map.map_int32_int32[888] = 999 + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_int32.clear() + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + def testMapAssignmentCausesPresenceForSubmessages(self): + msg = map_unittest_pb2.TestMapSubmessage() + msg.test_map.map_int32_foreign_message[123].c = 5 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMapSubmessage() + msg2.ParseFromString(serialized) + + self.assertEqual(msg, msg2) + + # Now test that various mutations of the map properly invalidate the + # cached size of the submessage. + msg.test_map.map_int32_foreign_message[888].c = 7 + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_foreign_message[888].MergeFrom( + msg.test_map.map_int32_foreign_message[123]) + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_foreign_message.clear() + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + def testModifyMapWhileIterating(self): + msg = map_unittest_pb2.TestMap() + + string_string_iter = iter(msg.map_string_string) + int32_foreign_iter = iter(msg.map_int32_foreign_message) + + msg.map_string_string['abc'] = '123' + msg.map_int32_foreign_message[5].c = 5 + + with self.assertRaises(RuntimeError): + for key in string_string_iter: + pass + + with self.assertRaises(RuntimeError): + for key in int32_foreign_iter: + pass + + def testSubmessageMap(self): + msg = map_unittest_pb2.TestMap() + + submsg = msg.map_int32_foreign_message[111] + self.assertIs(submsg, msg.map_int32_foreign_message[111]) + self.assertIsInstance(submsg, unittest_pb2.ForeignMessage) + + submsg.c = 5 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + + # Doesn't allow direct submessage assignment. + with self.assertRaises(ValueError): + msg.map_int32_foreign_message[88] = unittest_pb2.ForeignMessage() + + def testMapIteration(self): + msg = map_unittest_pb2.TestMap() + + for k, v in list(msg.map_int32_int32.items()): + # Should not be reached. + self.assertTrue(False) + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + self.assertEqual(3, len(msg.map_int32_int32)) + + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(list(msg.map_int32_int32.items()), matching_dict) + + def testPython2Map(self): + if sys.version_info < (3,): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + msg.map_int32_int32[5] = 10 + map_int32 = msg.map_int32_int32 + self.assertEqual(4, len(map_int32)) + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(msg.SerializeToString()) + + def CheckItems(seq, iterator): + self.assertEqual(next(iterator), seq[0]) + self.assertEqual(list(iterator), seq[1:]) + + CheckItems(list(map_int32.items()), iter(map_int32.items())) + CheckItems(list(map_int32.keys()), iter(map_int32.keys())) + CheckItems(list(map_int32.values()), iter(map_int32.values())) + + self.assertEqual(6, map_int32.get(3)) + self.assertEqual(None, map_int32.get(999)) + self.assertEqual(6, map_int32.pop(3)) + self.assertEqual(0, map_int32.pop(3)) + self.assertEqual(3, len(map_int32)) + key, value = map_int32.popitem() + self.assertEqual(2 * key, value) + self.assertEqual(2, len(map_int32)) + map_int32.clear() + self.assertEqual(0, len(map_int32)) + + with self.assertRaises(KeyError): + map_int32.popitem() + + self.assertEqual(0, map_int32.setdefault(2)) + self.assertEqual(1, len(map_int32)) + + map_int32.update(msg2.map_int32_int32) + self.assertEqual(4, len(map_int32)) + + with self.assertRaises(TypeError): + map_int32.update(msg2.map_int32_int32, + msg2.map_int32_int32) + with self.assertRaises(TypeError): + map_int32.update(0) + with self.assertRaises(TypeError): + map_int32.update(value=12) + + def testMapItems(self): + # Map items used to have strange behaviors when use c extension. Because + # [] may reorder the map and invalidate any exsting iterators. + # TODO(jieluo): Check if [] reordering the map is a bug or intended + # behavior. + msg = map_unittest_pb2.TestMap() + msg.map_string_string['local_init_op'] = '' + msg.map_string_string['trainable_variables'] = '' + msg.map_string_string['variables'] = '' + msg.map_string_string['init_op'] = '' + msg.map_string_string['summaries'] = '' + items1 = list(msg.map_string_string.items()) + items2 = list(msg.map_string_string.items()) + self.assertEqual(items1, items2) + + def testMapDeterministicSerialization(self): + golden_data = (b'r\x0c\n\x07init_op\x12\x01d' + b'r\n\n\x05item1\x12\x01e' + b'r\n\n\x05item2\x12\x01f' + b'r\n\n\x05item3\x12\x01g' + b'r\x0b\n\x05item4\x12\x02QQ' + b'r\x12\n\rlocal_init_op\x12\x01a' + b'r\x0e\n\tsummaries\x12\x01e' + b'r\x18\n\x13trainable_variables\x12\x01b' + b'r\x0e\n\tvariables\x12\x01c') + msg = map_unittest_pb2.TestMap() + msg.map_string_string['local_init_op'] = 'a' + msg.map_string_string['trainable_variables'] = 'b' + msg.map_string_string['variables'] = 'c' + msg.map_string_string['init_op'] = 'd' + msg.map_string_string['summaries'] = 'e' + msg.map_string_string['item1'] = 'e' + msg.map_string_string['item2'] = 'f' + msg.map_string_string['item3'] = 'g' + msg.map_string_string['item4'] = 'QQ' + + # If deterministic serialization is not working correctly, this will be + # "flaky" depending on the exact python dict hash seed. + # + # Fortunately, there are enough items in this map that it is extremely + # unlikely to ever hit the "right" in-order combination, so the test + # itself should fail reliably. + self.assertEqual(golden_data, msg.SerializeToString(deterministic=True)) + + def testMapIterationClearMessage(self): + # Iterator needs to work even if message and map are deleted. + msg = map_unittest_pb2.TestMap() + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + + it = list(msg.map_int32_int32.items()) + del msg + + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(it, matching_dict) + + def testMapConstruction(self): + msg = map_unittest_pb2.TestMap(map_int32_int32={1: 2, 3: 4}) + self.assertEqual(2, msg.map_int32_int32[1]) + self.assertEqual(4, msg.map_int32_int32[3]) + + msg = map_unittest_pb2.TestMap( + map_int32_foreign_message={3: unittest_pb2.ForeignMessage(c=5)}) + self.assertEqual(5, msg.map_int32_foreign_message[3].c) + + def testMapValidAfterFieldCleared(self): + # Map needs to work even if field is cleared. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + int32_map = msg.map_int32_int32 + + int32_map[2] = 4 + int32_map[3] = 6 + int32_map[4] = 8 + + msg.ClearField('map_int32_int32') + self.assertEqual(b'', msg.SerializeToString()) + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(list(int32_map.items()), matching_dict) + + def testMessageMapValidAfterFieldCleared(self): + # Map needs to work even if field is cleared. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + int32_foreign_message = msg.map_int32_foreign_message + + int32_foreign_message[2].c = 5 + + msg.ClearField('map_int32_foreign_message') + self.assertEqual(b'', msg.SerializeToString()) + self.assertTrue(2 in list(int32_foreign_message.keys())) + + def testMapIterInvalidatedByClearField(self): + # Map iterator is invalidated when field is cleared. + # But this case does need to not crash the interpreter. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + + it = iter(msg.map_int32_int32) + + msg.ClearField('map_int32_int32') + with self.assertRaises(RuntimeError): + for _ in it: + pass + + it = iter(msg.map_int32_foreign_message) + msg.ClearField('map_int32_foreign_message') + with self.assertRaises(RuntimeError): + for _ in it: + pass + + def testMapDelete(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_int32)) + + msg.map_int32_int32[4] = 6 + self.assertEqual(1, len(msg.map_int32_int32)) + + with self.assertRaises(KeyError): + del msg.map_int32_int32[88] + + del msg.map_int32_int32[4] + self.assertEqual(0, len(msg.map_int32_int32)) + + with self.assertRaises(KeyError): + del msg.map_int32_all_types[32] + + def testMapsAreMapping(self): + msg = map_unittest_pb2.TestMap() + self.assertIsInstance(msg.map_int32_int32, collections.Mapping) + self.assertIsInstance(msg.map_int32_int32, collections.MutableMapping) + self.assertIsInstance(msg.map_int32_foreign_message, collections.Mapping) + self.assertIsInstance(msg.map_int32_foreign_message, + collections.MutableMapping) + + def testMapsCompare(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[-123] = -456 + self.assertEqual(msg.map_int32_int32, msg.map_int32_int32) + self.assertEqual(msg.map_int32_foreign_message, + msg.map_int32_foreign_message) + self.assertNotEqual(msg.map_int32_int32, 0) + + def testMapFindInitializationErrorsSmokeTest(self): + msg = map_unittest_pb2.TestMap() + msg.map_string_string['abc'] = '123' + msg.map_int32_int32[35] = 64 + msg.map_string_foreign_message['foo'].c = 5 + self.assertEqual(0, len(msg.FindInitializationErrors())) + + + +class ValidTypeNamesTest(BaseTestCase): + + def assertImportFromName(self, msg, base_name): + # Parse to extra 'some.name' as a string. + tp_name = str(type(msg)).split("'")[1] + valid_names = ('Repeated%sContainer' % base_name, + 'Repeated%sFieldContainer' % base_name) + self.assertTrue(any(tp_name.endswith(v) for v in valid_names), + '%r does end with any of %r' % (tp_name, valid_names)) + + parts = tp_name.split('.') + class_name = parts[-1] + module_name = '.'.join(parts[:-1]) + __import__(module_name, fromlist=[class_name]) + + def testTypeNamesCanBeImported(self): + # If import doesn't work, pickling won't work either. + pb = unittest_pb2.TestAllTypes() + self.assertImportFromName(pb.repeated_int32, 'Scalar') + self.assertImportFromName(pb.repeated_nested_message, 'Composite') + +class PackedFieldTest(BaseTestCase): + + def setMessage(self, message): + message.repeated_int32.append(1) + message.repeated_int64.append(1) + message.repeated_uint32.append(1) + message.repeated_uint64.append(1) + message.repeated_sint32.append(1) + message.repeated_sint64.append(1) + message.repeated_fixed32.append(1) + message.repeated_fixed64.append(1) + message.repeated_sfixed32.append(1) + message.repeated_sfixed64.append(1) + message.repeated_float.append(1.0) + message.repeated_double.append(1.0) + message.repeated_bool.append(True) + message.repeated_nested_enum.append(1) + + def testPackedFields(self): + message = packed_field_test_pb2.TestPackedTypes() + self.setMessage(message) + golden_data = (b'\x0A\x01\x01' + b'\x12\x01\x01' + b'\x1A\x01\x01' + b'\x22\x01\x01' + b'\x2A\x01\x02' + b'\x32\x01\x02' + b'\x3A\x04\x01\x00\x00\x00' + b'\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x4A\x04\x01\x00\x00\x00' + b'\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x5A\x04\x00\x00\x80\x3f' + b'\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f' + b'\x6A\x01\x01' + b'\x72\x01\x01') + self.assertEqual(golden_data, message.SerializeToString()) + + def testUnpackedFields(self): + message = packed_field_test_pb2.TestUnpackedTypes() + self.setMessage(message) + golden_data = (b'\x08\x01' + b'\x10\x01' + b'\x18\x01' + b'\x20\x01' + b'\x28\x02' + b'\x30\x02' + b'\x3D\x01\x00\x00\x00' + b'\x41\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x4D\x01\x00\x00\x00' + b'\x51\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x5D\x00\x00\x80\x3f' + b'\x61\x00\x00\x00\x00\x00\x00\xf0\x3f' + b'\x68\x01' + b'\x70\x01') + self.assertEqual(golden_data, message.SerializeToString()) + + +@unittest.skipIf(api_implementation.Type() != 'cpp' or + sys.version_info < (2, 7), + 'explicit tests of the C++ implementation for PY27 and above') +class OversizeProtosTest(BaseTestCase): + + @classmethod + def setUpClass(cls): + # At the moment, reference cycles between DescriptorPool and Message classes + # are not detected and these objects are never freed. + # To avoid errors with ReferenceLeakChecker, we create the class only once. + file_desc = """ + name: "f/f.msg2" + package: "f" + message_type { + name: "msg1" + field { + name: "payload" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_STRING + } + } + message_type { + name: "msg2" + field { + name: "field" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: "msg1" + } + } + """ + pool = descriptor_pool.DescriptorPool() + desc = descriptor_pb2.FileDescriptorProto() + text_format.Parse(file_desc, desc) + pool.Add(desc) + cls.proto_cls = message_factory.MessageFactory(pool).GetPrototype( + pool.FindMessageTypeByName('f.msg2')) + + def setUp(self): + self.p = self.proto_cls() + self.p.field.payload = 'c' * (1024 * 1024 * 64 + 1) + self.p_serialized = self.p.SerializeToString() + + def testAssertOversizeProto(self): + from google.protobuf.pyext._message import SetAllowOversizeProtos + SetAllowOversizeProtos(False) + q = self.proto_cls() + try: + q.ParseFromString(self.p_serialized) + except message.DecodeError as e: + self.assertEqual(str(e), 'Error parsing message') + + def testSucceedOversizeProto(self): + from google.protobuf.pyext._message import SetAllowOversizeProtos + SetAllowOversizeProtos(True) + q = self.proto_cls() + q.ParseFromString(self.p_serialized) + self.assertEqual(self.p.field.payload, q.field.payload) + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/missing_enum_values_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/missing_enum_values_pb2.py new file mode 100644 index 0000000..5ad6cff --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/missing_enum_values_pb2.py @@ -0,0 +1,227 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/missing_enum_values.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/missing_enum_values.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n2google/protobuf/internal/missing_enum_values.proto\x12\x1fgoogle.protobuf.python.internal\"\xc1\x02\n\x0eTestEnumValues\x12X\n\x14optional_nested_enum\x18\x01 \x01(\x0e\x32:.google.protobuf.python.internal.TestEnumValues.NestedEnum\x12X\n\x14repeated_nested_enum\x18\x02 \x03(\x0e\x32:.google.protobuf.python.internal.TestEnumValues.NestedEnum\x12Z\n\x12packed_nested_enum\x18\x03 \x03(\x0e\x32:.google.protobuf.python.internal.TestEnumValues.NestedEnumB\x02\x10\x01\"\x1f\n\nNestedEnum\x12\x08\n\x04ZERO\x10\x00\x12\x07\n\x03ONE\x10\x01\"\xd3\x02\n\x15TestMissingEnumValues\x12_\n\x14optional_nested_enum\x18\x01 \x01(\x0e\x32\x41.google.protobuf.python.internal.TestMissingEnumValues.NestedEnum\x12_\n\x14repeated_nested_enum\x18\x02 \x03(\x0e\x32\x41.google.protobuf.python.internal.TestMissingEnumValues.NestedEnum\x12\x61\n\x12packed_nested_enum\x18\x03 \x03(\x0e\x32\x41.google.protobuf.python.internal.TestMissingEnumValues.NestedEnumB\x02\x10\x01\"\x15\n\nNestedEnum\x12\x07\n\x03TWO\x10\x02\"\x1b\n\nJustString\x12\r\n\x05\x64ummy\x18\x01 \x02(\t') +) + + + +_TESTENUMVALUES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.TestEnumValues.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ZERO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ONE', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=378, + serialized_end=409, +) +_sym_db.RegisterEnumDescriptor(_TESTENUMVALUES_NESTEDENUM) + +_TESTMISSINGENUMVALUES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.TestMissingEnumValues.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TWO', index=0, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=730, + serialized_end=751, +) +_sym_db.RegisterEnumDescriptor(_TESTMISSINGENUMVALUES_NESTEDENUM) + + +_TESTENUMVALUES = _descriptor.Descriptor( + name='TestEnumValues', + full_name='google.protobuf.python.internal.TestEnumValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='google.protobuf.python.internal.TestEnumValues.optional_nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestEnumValues.repeated_nested_enum', index=1, + number=2, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_nested_enum', full_name='google.protobuf.python.internal.TestEnumValues.packed_nested_enum', index=2, + number=3, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTENUMVALUES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=88, + serialized_end=409, +) + + +_TESTMISSINGENUMVALUES = _descriptor.Descriptor( + name='TestMissingEnumValues', + full_name='google.protobuf.python.internal.TestMissingEnumValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='google.protobuf.python.internal.TestMissingEnumValues.optional_nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestMissingEnumValues.repeated_nested_enum', index=1, + number=2, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_nested_enum', full_name='google.protobuf.python.internal.TestMissingEnumValues.packed_nested_enum', index=2, + number=3, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTMISSINGENUMVALUES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=412, + serialized_end=751, +) + + +_JUSTSTRING = _descriptor.Descriptor( + name='JustString', + full_name='google.protobuf.python.internal.JustString', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='dummy', full_name='google.protobuf.python.internal.JustString.dummy', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=753, + serialized_end=780, +) + +_TESTENUMVALUES.fields_by_name['optional_nested_enum'].enum_type = _TESTENUMVALUES_NESTEDENUM +_TESTENUMVALUES.fields_by_name['repeated_nested_enum'].enum_type = _TESTENUMVALUES_NESTEDENUM +_TESTENUMVALUES.fields_by_name['packed_nested_enum'].enum_type = _TESTENUMVALUES_NESTEDENUM +_TESTENUMVALUES_NESTEDENUM.containing_type = _TESTENUMVALUES +_TESTMISSINGENUMVALUES.fields_by_name['optional_nested_enum'].enum_type = _TESTMISSINGENUMVALUES_NESTEDENUM +_TESTMISSINGENUMVALUES.fields_by_name['repeated_nested_enum'].enum_type = _TESTMISSINGENUMVALUES_NESTEDENUM +_TESTMISSINGENUMVALUES.fields_by_name['packed_nested_enum'].enum_type = _TESTMISSINGENUMVALUES_NESTEDENUM +_TESTMISSINGENUMVALUES_NESTEDENUM.containing_type = _TESTMISSINGENUMVALUES +DESCRIPTOR.message_types_by_name['TestEnumValues'] = _TESTENUMVALUES +DESCRIPTOR.message_types_by_name['TestMissingEnumValues'] = _TESTMISSINGENUMVALUES +DESCRIPTOR.message_types_by_name['JustString'] = _JUSTSTRING +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestEnumValues = _reflection.GeneratedProtocolMessageType('TestEnumValues', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMVALUES, + __module__ = 'google.protobuf.internal.missing_enum_values_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestEnumValues) + )) +_sym_db.RegisterMessage(TestEnumValues) + +TestMissingEnumValues = _reflection.GeneratedProtocolMessageType('TestMissingEnumValues', (_message.Message,), dict( + DESCRIPTOR = _TESTMISSINGENUMVALUES, + __module__ = 'google.protobuf.internal.missing_enum_values_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestMissingEnumValues) + )) +_sym_db.RegisterMessage(TestMissingEnumValues) + +JustString = _reflection.GeneratedProtocolMessageType('JustString', (_message.Message,), dict( + DESCRIPTOR = _JUSTSTRING, + __module__ = 'google.protobuf.internal.missing_enum_values_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.JustString) + )) +_sym_db.RegisterMessage(JustString) + + +_TESTENUMVALUES.fields_by_name['packed_nested_enum']._options = None +_TESTMISSINGENUMVALUES.fields_by_name['packed_nested_enum']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py new file mode 100644 index 0000000..3417ed6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py @@ -0,0 +1,103 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/more_extensions_dynamic.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf.internal import more_extensions_pb2 as google_dot_protobuf_dot_internal_dot_more__extensions__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/more_extensions_dynamic.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n6google/protobuf/internal/more_extensions_dynamic.proto\x12\x18google.protobuf.internal\x1a.google/protobuf/internal/more_extensions.proto\"\x1f\n\x12\x44ynamicMessageType\x12\t\n\x01\x61\x18\x01 \x01(\x05:J\n\x17\x64ynamic_int32_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x64 \x01(\x05:z\n\x19\x64ynamic_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x65 \x01(\x0b\x32,.google.protobuf.internal.DynamicMessageType:\x83\x01\n\"repeated_dynamic_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x66 \x03(\x0b\x32,.google.protobuf.internal.DynamicMessageType') + , + dependencies=[google_dot_protobuf_dot_internal_dot_more__extensions__pb2.DESCRIPTOR,]) + + +DYNAMIC_INT32_EXTENSION_FIELD_NUMBER = 100 +dynamic_int32_extension = _descriptor.FieldDescriptor( + name='dynamic_int32_extension', full_name='google.protobuf.internal.dynamic_int32_extension', index=0, + number=100, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DYNAMIC_MESSAGE_EXTENSION_FIELD_NUMBER = 101 +dynamic_message_extension = _descriptor.FieldDescriptor( + name='dynamic_message_extension', full_name='google.protobuf.internal.dynamic_message_extension', index=1, + number=101, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_DYNAMIC_MESSAGE_EXTENSION_FIELD_NUMBER = 102 +repeated_dynamic_message_extension = _descriptor.FieldDescriptor( + name='repeated_dynamic_message_extension', full_name='google.protobuf.internal.repeated_dynamic_message_extension', index=2, + number=102, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_DYNAMICMESSAGETYPE = _descriptor.Descriptor( + name='DynamicMessageType', + full_name='google.protobuf.internal.DynamicMessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='google.protobuf.internal.DynamicMessageType.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=132, + serialized_end=163, +) + +DESCRIPTOR.message_types_by_name['DynamicMessageType'] = _DYNAMICMESSAGETYPE +DESCRIPTOR.extensions_by_name['dynamic_int32_extension'] = dynamic_int32_extension +DESCRIPTOR.extensions_by_name['dynamic_message_extension'] = dynamic_message_extension +DESCRIPTOR.extensions_by_name['repeated_dynamic_message_extension'] = repeated_dynamic_message_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DynamicMessageType = _reflection.GeneratedProtocolMessageType('DynamicMessageType', (_message.Message,), dict( + DESCRIPTOR = _DYNAMICMESSAGETYPE, + __module__ = 'google.protobuf.internal.more_extensions_dynamic_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.DynamicMessageType) + )) +_sym_db.RegisterMessage(DynamicMessageType) + +google_dot_protobuf_dot_internal_dot_more__extensions__pb2.ExtendedMessage.RegisterExtension(dynamic_int32_extension) +dynamic_message_extension.message_type = _DYNAMICMESSAGETYPE +google_dot_protobuf_dot_internal_dot_more__extensions__pb2.ExtendedMessage.RegisterExtension(dynamic_message_extension) +repeated_dynamic_message_extension.message_type = _DYNAMICMESSAGETYPE +google_dot_protobuf_dot_internal_dot_more__extensions__pb2.ExtendedMessage.RegisterExtension(repeated_dynamic_message_extension) + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_pb2.py new file mode 100644 index 0000000..1433e53 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/more_extensions_pb2.py @@ -0,0 +1,183 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/more_extensions.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/more_extensions.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n.google/protobuf/internal/more_extensions.proto\x12\x18google.protobuf.internal\"P\n\x0fTopLevelMessage\x12=\n\nsubmessage\x18\x01 \x01(\x0b\x32).google.protobuf.internal.ExtendedMessage\"\x1b\n\x0f\x45xtendedMessage*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"-\n\x0e\x46oreignMessage\x12\x1b\n\x13\x66oreign_message_int\x18\x01 \x01(\x05:I\n\x16optional_int_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x01 \x01(\x05:w\n\x1aoptional_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x02 \x01(\x0b\x32(.google.protobuf.internal.ForeignMessage:I\n\x16repeated_int_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x03 \x03(\x05:w\n\x1arepeated_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x04 \x03(\x0b\x32(.google.protobuf.internal.ForeignMessage') +) + + +OPTIONAL_INT_EXTENSION_FIELD_NUMBER = 1 +optional_int_extension = _descriptor.FieldDescriptor( + name='optional_int_extension', full_name='google.protobuf.internal.optional_int_extension', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_MESSAGE_EXTENSION_FIELD_NUMBER = 2 +optional_message_extension = _descriptor.FieldDescriptor( + name='optional_message_extension', full_name='google.protobuf.internal.optional_message_extension', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_INT_EXTENSION_FIELD_NUMBER = 3 +repeated_int_extension = _descriptor.FieldDescriptor( + name='repeated_int_extension', full_name='google.protobuf.internal.repeated_int_extension', index=2, + number=3, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_MESSAGE_EXTENSION_FIELD_NUMBER = 4 +repeated_message_extension = _descriptor.FieldDescriptor( + name='repeated_message_extension', full_name='google.protobuf.internal.repeated_message_extension', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TOPLEVELMESSAGE = _descriptor.Descriptor( + name='TopLevelMessage', + full_name='google.protobuf.internal.TopLevelMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='submessage', full_name='google.protobuf.internal.TopLevelMessage.submessage', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=76, + serialized_end=156, +) + + +_EXTENDEDMESSAGE = _descriptor.Descriptor( + name='ExtendedMessage', + full_name='google.protobuf.internal.ExtendedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=158, + serialized_end=185, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='google.protobuf.internal.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foreign_message_int', full_name='google.protobuf.internal.ForeignMessage.foreign_message_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=187, + serialized_end=232, +) + +_TOPLEVELMESSAGE.fields_by_name['submessage'].message_type = _EXTENDEDMESSAGE +DESCRIPTOR.message_types_by_name['TopLevelMessage'] = _TOPLEVELMESSAGE +DESCRIPTOR.message_types_by_name['ExtendedMessage'] = _EXTENDEDMESSAGE +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.extensions_by_name['optional_int_extension'] = optional_int_extension +DESCRIPTOR.extensions_by_name['optional_message_extension'] = optional_message_extension +DESCRIPTOR.extensions_by_name['repeated_int_extension'] = repeated_int_extension +DESCRIPTOR.extensions_by_name['repeated_message_extension'] = repeated_message_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TopLevelMessage = _reflection.GeneratedProtocolMessageType('TopLevelMessage', (_message.Message,), dict( + DESCRIPTOR = _TOPLEVELMESSAGE, + __module__ = 'google.protobuf.internal.more_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TopLevelMessage) + )) +_sym_db.RegisterMessage(TopLevelMessage) + +ExtendedMessage = _reflection.GeneratedProtocolMessageType('ExtendedMessage', (_message.Message,), dict( + DESCRIPTOR = _EXTENDEDMESSAGE, + __module__ = 'google.protobuf.internal.more_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.ExtendedMessage) + )) +_sym_db.RegisterMessage(ExtendedMessage) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.internal.more_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +ExtendedMessage.RegisterExtension(optional_int_extension) +optional_message_extension.message_type = _FOREIGNMESSAGE +ExtendedMessage.RegisterExtension(optional_message_extension) +ExtendedMessage.RegisterExtension(repeated_int_extension) +repeated_message_extension.message_type = _FOREIGNMESSAGE +ExtendedMessage.RegisterExtension(repeated_message_extension) + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/more_messages_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/more_messages_pb2.py new file mode 100644 index 0000000..99d53dc --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/more_messages_pb2.py @@ -0,0 +1,103 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/more_messages.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/more_messages.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n,google/protobuf/internal/more_messages.proto\x12\x18google.protobuf.internal\"h\n\x10OutOfOrderFields\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05*\x04\x08\x04\x10\x05*\x04\x08\x02\x10\x03:C\n\x0foptional_uint64\x12*.google.protobuf.internal.OutOfOrderFields\x18\x04 \x01(\x04:B\n\x0eoptional_int64\x12*.google.protobuf.internal.OutOfOrderFields\x18\x02 \x01(\x03') +) + + +OPTIONAL_UINT64_FIELD_NUMBER = 4 +optional_uint64 = _descriptor.FieldDescriptor( + name='optional_uint64', full_name='google.protobuf.internal.optional_uint64', index=0, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_INT64_FIELD_NUMBER = 2 +optional_int64 = _descriptor.FieldDescriptor( + name='optional_int64', full_name='google.protobuf.internal.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_OUTOFORDERFIELDS = _descriptor.Descriptor( + name='OutOfOrderFields', + full_name='google.protobuf.internal.OutOfOrderFields', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='google.protobuf.internal.OutOfOrderFields.optional_sint32', index=0, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='google.protobuf.internal.OutOfOrderFields.optional_uint32', index=1, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32', full_name='google.protobuf.internal.OutOfOrderFields.optional_int32', index=2, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 5), (2, 3), ], + oneofs=[ + ], + serialized_start=74, + serialized_end=178, +) + +DESCRIPTOR.message_types_by_name['OutOfOrderFields'] = _OUTOFORDERFIELDS +DESCRIPTOR.extensions_by_name['optional_uint64'] = optional_uint64 +DESCRIPTOR.extensions_by_name['optional_int64'] = optional_int64 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +OutOfOrderFields = _reflection.GeneratedProtocolMessageType('OutOfOrderFields', (_message.Message,), dict( + DESCRIPTOR = _OUTOFORDERFIELDS, + __module__ = 'google.protobuf.internal.more_messages_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.OutOfOrderFields) + )) +_sym_db.RegisterMessage(OutOfOrderFields) + +OutOfOrderFields.RegisterExtension(optional_uint64) +OutOfOrderFields.RegisterExtension(optional_int64) + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/no_package_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/no_package_pb2.py new file mode 100644 index 0000000..8663666 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/no_package_pb2.py @@ -0,0 +1,97 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/no_package.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/no_package.proto', + package='', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n)google/protobuf/internal/no_package.proto\";\n\x10NoPackageMessage\x12\'\n\x0fno_package_enum\x18\x01 \x01(\x0e\x32\x0e.NoPackageEnum*?\n\rNoPackageEnum\x12\x16\n\x12NO_PACKAGE_VALUE_0\x10\x00\x12\x16\n\x12NO_PACKAGE_VALUE_1\x10\x01') +) + +_NOPACKAGEENUM = _descriptor.EnumDescriptor( + name='NoPackageEnum', + full_name='NoPackageEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NO_PACKAGE_VALUE_0', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NO_PACKAGE_VALUE_1', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=106, + serialized_end=169, +) +_sym_db.RegisterEnumDescriptor(_NOPACKAGEENUM) + +NoPackageEnum = enum_type_wrapper.EnumTypeWrapper(_NOPACKAGEENUM) +NO_PACKAGE_VALUE_0 = 0 +NO_PACKAGE_VALUE_1 = 1 + + + +_NOPACKAGEMESSAGE = _descriptor.Descriptor( + name='NoPackageMessage', + full_name='NoPackageMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='no_package_enum', full_name='NoPackageMessage.no_package_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=45, + serialized_end=104, +) + +_NOPACKAGEMESSAGE.fields_by_name['no_package_enum'].enum_type = _NOPACKAGEENUM +DESCRIPTOR.message_types_by_name['NoPackageMessage'] = _NOPACKAGEMESSAGE +DESCRIPTOR.enum_types_by_name['NoPackageEnum'] = _NOPACKAGEENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +NoPackageMessage = _reflection.GeneratedProtocolMessageType('NoPackageMessage', (_message.Message,), dict( + DESCRIPTOR = _NOPACKAGEMESSAGE, + __module__ = 'google.protobuf.internal.no_package_pb2' + # @@protoc_insertion_point(class_scope:NoPackageMessage) + )) +_sym_db.RegisterMessage(NoPackageMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/packed_field_test_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/packed_field_test_pb2.py new file mode 100644 index 0000000..5e95400 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/packed_field_test_pb2.py @@ -0,0 +1,334 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/packed_field_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/packed_field_test.proto', + package='google.protobuf.python.internal', + syntax='proto3', + serialized_options=None, + serialized_pb=_b('\n0google/protobuf/internal/packed_field_test.proto\x12\x1fgoogle.protobuf.python.internal\"\xdb\x03\n\x0fTestPackedTypes\x12\x16\n\x0erepeated_int32\x18\x01 \x03(\x05\x12\x16\n\x0erepeated_int64\x18\x02 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18\x03 \x03(\r\x12\x17\n\x0frepeated_uint64\x18\x04 \x03(\x04\x12\x17\n\x0frepeated_sint32\x18\x05 \x03(\x11\x12\x17\n\x0frepeated_sint64\x18\x06 \x03(\x12\x12\x18\n\x10repeated_fixed32\x18\x07 \x03(\x07\x12\x18\n\x10repeated_fixed64\x18\x08 \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\t \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18\n \x03(\x10\x12\x16\n\x0erepeated_float\x18\x0b \x03(\x02\x12\x17\n\x0frepeated_double\x18\x0c \x03(\x01\x12\x15\n\rrepeated_bool\x18\r \x03(\x08\x12Y\n\x14repeated_nested_enum\x18\x0e \x03(\x0e\x32;.google.protobuf.python.internal.TestPackedTypes.NestedEnum\"\'\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x12\x07\n\x03\x42\x41Z\x10\x02\"\xec\x03\n\x11TestUnpackedTypes\x12\x1a\n\x0erepeated_int32\x18\x01 \x03(\x05\x42\x02\x10\x00\x12\x1a\n\x0erepeated_int64\x18\x02 \x03(\x03\x42\x02\x10\x00\x12\x1b\n\x0frepeated_uint32\x18\x03 \x03(\rB\x02\x10\x00\x12\x1b\n\x0frepeated_uint64\x18\x04 \x03(\x04\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint32\x18\x05 \x03(\x11\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint64\x18\x06 \x03(\x12\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed32\x18\x07 \x03(\x07\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed64\x18\x08 \x03(\x06\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed32\x18\t \x03(\x0f\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed64\x18\n \x03(\x10\x42\x02\x10\x00\x12\x1a\n\x0erepeated_float\x18\x0b \x03(\x02\x42\x02\x10\x00\x12\x1b\n\x0frepeated_double\x18\x0c \x03(\x01\x42\x02\x10\x00\x12\x19\n\rrepeated_bool\x18\r \x03(\x08\x42\x02\x10\x00\x12]\n\x14repeated_nested_enum\x18\x0e \x03(\x0e\x32;.google.protobuf.python.internal.TestPackedTypes.NestedEnumB\x02\x10\x00\x62\x06proto3') +) + + + +_TESTPACKEDTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.TestPackedTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=522, + serialized_end=561, +) +_sym_db.RegisterEnumDescriptor(_TESTPACKEDTYPES_NESTEDENUM) + + +_TESTPACKEDTYPES = _descriptor.Descriptor( + name='TestPackedTypes', + full_name='google.protobuf.python.internal.TestPackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_int64', index=1, + number=2, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_uint32', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_uint64', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sint32', index=4, + number=5, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sint64', index=5, + number=6, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_fixed32', index=6, + number=7, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_fixed64', index=7, + number=8, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_float', index=10, + number=11, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_double', index=11, + number=12, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_bool', index=12, + number=13, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_nested_enum', index=13, + number=14, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTPACKEDTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=86, + serialized_end=561, +) + + +_TESTUNPACKEDTYPES = _descriptor.Descriptor( + name='TestUnpackedTypes', + full_name='google.protobuf.python.internal.TestUnpackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_int64', index=1, + number=2, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_uint32', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_uint64', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sint32', index=4, + number=5, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sint64', index=5, + number=6, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_fixed32', index=6, + number=7, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_fixed64', index=7, + number=8, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_float', index=10, + number=11, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_double', index=11, + number=12, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_bool', index=12, + number=13, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_nested_enum', index=13, + number=14, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=564, + serialized_end=1056, +) + +_TESTPACKEDTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTPACKEDTYPES_NESTEDENUM +_TESTPACKEDTYPES_NESTEDENUM.containing_type = _TESTPACKEDTYPES +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTPACKEDTYPES_NESTEDENUM +DESCRIPTOR.message_types_by_name['TestPackedTypes'] = _TESTPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestUnpackedTypes'] = _TESTUNPACKEDTYPES +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestPackedTypes = _reflection.GeneratedProtocolMessageType('TestPackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDTYPES, + __module__ = 'google.protobuf.internal.packed_field_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestPackedTypes) + )) +_sym_db.RegisterMessage(TestPackedTypes) + +TestUnpackedTypes = _reflection.GeneratedProtocolMessageType('TestUnpackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDTYPES, + __module__ = 'google.protobuf.internal.packed_field_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestUnpackedTypes) + )) +_sym_db.RegisterMessage(TestUnpackedTypes) + + +_TESTUNPACKEDTYPES.fields_by_name['repeated_int32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_int64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_float']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_double']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_bool']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/proto_builder_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/proto_builder_test.py new file mode 100644 index 0000000..36dfbfd --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/proto_builder_test.py @@ -0,0 +1,96 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.proto_builder.""" + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict #PY26 +try: + import unittest2 as unittest +except ImportError: + import unittest + +from google.protobuf import descriptor_pb2 +from google.protobuf import descriptor_pool +from google.protobuf import proto_builder +from google.protobuf import text_format + + +class ProtoBuilderTest(unittest.TestCase): + + def setUp(self): + self.ordered_fields = OrderedDict([ + ('foo', descriptor_pb2.FieldDescriptorProto.TYPE_INT64), + ('bar', descriptor_pb2.FieldDescriptorProto.TYPE_STRING), + ]) + self._fields = dict(self.ordered_fields) + + def testMakeSimpleProtoClass(self): + """Test that we can create a proto class.""" + proto_cls = proto_builder.MakeSimpleProtoClass( + self._fields, + full_name='net.proto2.python.public.proto_builder_test.Test') + proto = proto_cls() + proto.foo = 12345 + proto.bar = 'asdf' + self.assertMultiLineEqual( + 'bar: "asdf"\nfoo: 12345\n', text_format.MessageToString(proto)) + + def testOrderedFields(self): + """Test that the field order is maintained when given an OrderedDict.""" + proto_cls = proto_builder.MakeSimpleProtoClass( + self.ordered_fields, + full_name='net.proto2.python.public.proto_builder_test.OrderedTest') + proto = proto_cls() + proto.foo = 12345 + proto.bar = 'asdf' + self.assertMultiLineEqual( + 'foo: 12345\nbar: "asdf"\n', text_format.MessageToString(proto)) + + def testMakeSameProtoClassTwice(self): + """Test that the DescriptorPool is used.""" + pool = descriptor_pool.DescriptorPool() + proto_cls1 = proto_builder.MakeSimpleProtoClass( + self._fields, + full_name='net.proto2.python.public.proto_builder_test.Test', + pool=pool) + proto_cls2 = proto_builder.MakeSimpleProtoClass( + self._fields, + full_name='net.proto2.python.public.proto_builder_test.Test', + pool=pool) + self.assertIs(proto_cls1.DESCRIPTOR, proto_cls2.DESCRIPTOR) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/python_message.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/python_message.py new file mode 100644 index 0000000..fb25e27 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/python_message.py @@ -0,0 +1,1559 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# This code is meant to work on Python 2.4 and above only. +# +# TODO(robinson): Helpers for verbose, common checks like seeing if a +# descriptor's cpp_type is CPPTYPE_MESSAGE. + +"""Contains a metaclass and helper functions used to create +protocol message classes from Descriptor objects at runtime. + +Recall that a metaclass is the "type" of a class. +(A class is to a metaclass what an instance is to a class.) + +In this case, we use the GeneratedProtocolMessageType metaclass +to inject all the useful functionality into the classes +output by the protocol compiler at compile-time. + +The upshot of all this is that the real implementation +details for ALL pure-Python protocol buffers are *here in +this file*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +from io import BytesIO +import struct +import sys +import weakref + +import six + +# We use "as" to avoid name collisions with variables. +from google.protobuf.internal import api_implementation +from google.protobuf.internal import containers +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.internal import enum_type_wrapper +from google.protobuf.internal import message_listener as message_listener_mod +from google.protobuf.internal import type_checkers +from google.protobuf.internal import well_known_types +from google.protobuf.internal import wire_format +from google.protobuf import descriptor as descriptor_mod +from google.protobuf import message as message_mod +from google.protobuf import text_format + +_FieldDescriptor = descriptor_mod.FieldDescriptor +_AnyFullTypeName = 'google.protobuf.Any' + + +class GeneratedProtocolMessageType(type): + + """Metaclass for protocol message classes created at runtime from Descriptors. + + We add implementations for all methods described in the Message class. We + also create properties to allow getting/setting all fields in the protocol + message. Finally, we create slots to prevent users from accidentally + "setting" nonexistent fields in the protocol message, which then wouldn't get + serialized / deserialized properly. + + The protocol compiler currently uses this metaclass to create protocol + message classes at runtime. Clients can also manually create their own + classes at runtime, as in this example: + + mydescriptor = Descriptor(.....) + factory = symbol_database.Default() + factory.pool.AddDescriptor(mydescriptor) + MyProtoClass = factory.GetPrototype(mydescriptor) + myproto_instance = MyProtoClass() + myproto.foo_field = 23 + ... + """ + + # Must be consistent with the protocol-compiler code in + # proto2/compiler/internal/generator.*. + _DESCRIPTOR_KEY = 'DESCRIPTOR' + + def __new__(cls, name, bases, dictionary): + """Custom allocation for runtime-generated class types. + + We override __new__ because this is apparently the only place + where we can meaningfully set __slots__ on the class we're creating(?). + (The interplay between metaclasses and slots is not very well-documented). + + Args: + name: Name of the class (ignored, but required by the + metaclass protocol). + bases: Base classes of the class we're constructing. + (Should be message.Message). We ignore this field, but + it's required by the metaclass protocol + dictionary: The class dictionary of the class we're + constructing. dictionary[_DESCRIPTOR_KEY] must contain + a Descriptor object describing this protocol message + type. + + Returns: + Newly-allocated class. + """ + descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] + if descriptor.full_name in well_known_types.WKTBASES: + bases += (well_known_types.WKTBASES[descriptor.full_name],) + _AddClassAttributesForNestedExtensions(descriptor, dictionary) + _AddSlots(descriptor, dictionary) + + superclass = super(GeneratedProtocolMessageType, cls) + new_class = superclass.__new__(cls, name, bases, dictionary) + return new_class + + def __init__(cls, name, bases, dictionary): + """Here we perform the majority of our work on the class. + We add enum getters, an __init__ method, implementations + of all Message methods, and properties for all fields + in the protocol type. + + Args: + name: Name of the class (ignored, but required by the + metaclass protocol). + bases: Base classes of the class we're constructing. + (Should be message.Message). We ignore this field, but + it's required by the metaclass protocol + dictionary: The class dictionary of the class we're + constructing. dictionary[_DESCRIPTOR_KEY] must contain + a Descriptor object describing this protocol message + type. + """ + descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] + cls._decoders_by_tag = {} + if (descriptor.has_options and + descriptor.GetOptions().message_set_wire_format): + cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = ( + decoder.MessageSetItemDecoder(descriptor), None) + + # Attach stuff to each FieldDescriptor for quick lookup later on. + for field in descriptor.fields: + _AttachFieldHelpers(cls, field) + + descriptor._concrete_class = cls # pylint: disable=protected-access + _AddEnumValues(descriptor, cls) + _AddInitMethod(descriptor, cls) + _AddPropertiesForFields(descriptor, cls) + _AddPropertiesForExtensions(descriptor, cls) + _AddStaticMethods(cls) + _AddMessageMethods(descriptor, cls) + _AddPrivateHelperMethods(descriptor, cls) + + superclass = super(GeneratedProtocolMessageType, cls) + superclass.__init__(name, bases, dictionary) + + +# Stateless helpers for GeneratedProtocolMessageType below. +# Outside clients should not access these directly. +# +# I opted not to make any of these methods on the metaclass, to make it more +# clear that I'm not really using any state there and to keep clients from +# thinking that they have direct access to these construction helpers. + + +def _PropertyName(proto_field_name): + """Returns the name of the public property attribute which + clients can use to get and (in some cases) set the value + of a protocol message field. + + Args: + proto_field_name: The protocol message field name, exactly + as it appears (or would appear) in a .proto file. + """ + # TODO(robinson): Escape Python keywords (e.g., yield), and test this support. + # nnorwitz makes my day by writing: + # """ + # FYI. See the keyword module in the stdlib. This could be as simple as: + # + # if keyword.iskeyword(proto_field_name): + # return proto_field_name + "_" + # return proto_field_name + # """ + # Kenton says: The above is a BAD IDEA. People rely on being able to use + # getattr() and setattr() to reflectively manipulate field values. If we + # rename the properties, then every such user has to also make sure to apply + # the same transformation. Note that currently if you name a field "yield", + # you can still access it just fine using getattr/setattr -- it's not even + # that cumbersome to do so. + # TODO(kenton): Remove this method entirely if/when everyone agrees with my + # position. + return proto_field_name + + +def _VerifyExtensionHandle(message, extension_handle): + """Verify that the given extension handle is valid.""" + + if not isinstance(extension_handle, _FieldDescriptor): + raise KeyError('HasExtension() expects an extension handle, got: %s' % + extension_handle) + + if not extension_handle.is_extension: + raise KeyError('"%s" is not an extension.' % extension_handle.full_name) + + if not extension_handle.containing_type: + raise KeyError('"%s" is missing a containing_type.' + % extension_handle.full_name) + + if extension_handle.containing_type is not message.DESCRIPTOR: + raise KeyError('Extension "%s" extends message type "%s", but this ' + 'message is of type "%s".' % + (extension_handle.full_name, + extension_handle.containing_type.full_name, + message.DESCRIPTOR.full_name)) + + +def _AddSlots(message_descriptor, dictionary): + """Adds a __slots__ entry to dictionary, containing the names of all valid + attributes for this message type. + + Args: + message_descriptor: A Descriptor instance describing this message type. + dictionary: Class dictionary to which we'll add a '__slots__' entry. + """ + dictionary['__slots__'] = ['_cached_byte_size', + '_cached_byte_size_dirty', + '_fields', + '_unknown_fields', + '_is_present_in_parent', + '_listener', + '_listener_for_children', + '__weakref__', + '_oneofs'] + + +def _IsMessageSetExtension(field): + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == _FieldDescriptor.TYPE_MESSAGE and + field.label == _FieldDescriptor.LABEL_OPTIONAL) + + +def _IsMapField(field): + return (field.type == _FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) + + +def _IsMessageMapField(field): + value_type = field.message_type.fields_by_name["value"] + return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE + + +def _AttachFieldHelpers(cls, field_descriptor): + is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED) + is_packable = (is_repeated and + wire_format.IsTypePackable(field_descriptor.type)) + if not is_packable: + is_packed = False + elif field_descriptor.containing_type.syntax == "proto2": + is_packed = (field_descriptor.has_options and + field_descriptor.GetOptions().packed) + else: + has_packed_false = (field_descriptor.has_options and + field_descriptor.GetOptions().HasField("packed") and + field_descriptor.GetOptions().packed == False) + is_packed = not has_packed_false + is_map_entry = _IsMapField(field_descriptor) + + if is_map_entry: + field_encoder = encoder.MapEncoder(field_descriptor) + sizer = encoder.MapSizer(field_descriptor, + _IsMessageMapField(field_descriptor)) + elif _IsMessageSetExtension(field_descriptor): + field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number) + sizer = encoder.MessageSetItemSizer(field_descriptor.number) + else: + field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed) + sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed) + + field_descriptor._encoder = field_encoder + field_descriptor._sizer = sizer + field_descriptor._default_constructor = _DefaultValueConstructorForField( + field_descriptor) + + def AddDecoder(wiretype, is_packed): + tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype) + decode_type = field_descriptor.type + if (decode_type == _FieldDescriptor.TYPE_ENUM and + type_checkers.SupportsOpenEnums(field_descriptor)): + decode_type = _FieldDescriptor.TYPE_INT32 + + oneof_descriptor = None + if field_descriptor.containing_oneof is not None: + oneof_descriptor = field_descriptor + + if is_map_entry: + is_message_map = _IsMessageMapField(field_descriptor) + + field_decoder = decoder.MapDecoder( + field_descriptor, _GetInitializeDefaultForMap(field_descriptor), + is_message_map) + else: + field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor) + + cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor) + + AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], + False) + + if is_repeated and wire_format.IsTypePackable(field_descriptor.type): + # To support wire compatibility of adding packed = true, add a decoder for + # packed values regardless of the field's options. + AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True) + + +def _AddClassAttributesForNestedExtensions(descriptor, dictionary): + extension_dict = descriptor.extensions_by_name + for extension_name, extension_field in list(extension_dict.items()): + assert extension_name not in dictionary + dictionary[extension_name] = extension_field + + +def _AddEnumValues(descriptor, cls): + """Sets class-level attributes for all enum fields defined in this message. + + Also exporting a class-level object that can name enum values. + + Args: + descriptor: Descriptor object for this message type. + cls: Class we're constructing for this message type. + """ + for enum_type in descriptor.enum_types: + setattr(cls, enum_type.name, enum_type_wrapper.EnumTypeWrapper(enum_type)) + for enum_value in enum_type.values: + setattr(cls, enum_value.name, enum_value.number) + + +def _GetInitializeDefaultForMap(field): + if field.label != _FieldDescriptor.LABEL_REPEATED: + raise ValueError('map_entry set on non-repeated field %s' % ( + field.name)) + fields_by_name = field.message_type.fields_by_name + key_checker = type_checkers.GetTypeChecker(fields_by_name['key']) + + value_field = fields_by_name['value'] + if _IsMessageMapField(field): + def MakeMessageMapDefault(message): + return containers.MessageMap( + message._listener_for_children, value_field.message_type, key_checker, + field.message_type) + return MakeMessageMapDefault + else: + value_checker = type_checkers.GetTypeChecker(value_field) + def MakePrimitiveMapDefault(message): + return containers.ScalarMap( + message._listener_for_children, key_checker, value_checker, + field.message_type) + return MakePrimitiveMapDefault + +def _DefaultValueConstructorForField(field): + """Returns a function which returns a default value for a field. + + Args: + field: FieldDescriptor object for this field. + + The returned function has one argument: + message: Message instance containing this field, or a weakref proxy + of same. + + That function in turn returns a default value for this field. The default + value may refer back to |message| via a weak reference. + """ + + if _IsMapField(field): + return _GetInitializeDefaultForMap(field) + + if field.label == _FieldDescriptor.LABEL_REPEATED: + if field.has_default_value and field.default_value != []: + raise ValueError('Repeated field default value not empty list: %s' % ( + field.default_value)) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + # We can't look at _concrete_class yet since it might not have + # been set. (Depends on order in which we initialize the classes). + message_type = field.message_type + def MakeRepeatedMessageDefault(message): + return containers.RepeatedCompositeFieldContainer( + message._listener_for_children, field.message_type) + return MakeRepeatedMessageDefault + else: + type_checker = type_checkers.GetTypeChecker(field) + def MakeRepeatedScalarDefault(message): + return containers.RepeatedScalarFieldContainer( + message._listener_for_children, type_checker) + return MakeRepeatedScalarDefault + + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + # _concrete_class may not yet be initialized. + message_type = field.message_type + def MakeSubMessageDefault(message): + result = message_type._concrete_class() + result._SetListener( + _OneofListener(message, field) + if field.containing_oneof is not None + else message._listener_for_children) + return result + return MakeSubMessageDefault + + def MakeScalarDefault(message): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return field.default_value + return MakeScalarDefault + + +def _ReraiseTypeErrorWithFieldName(message_name, field_name): + """Re-raise the currently-handled TypeError with the field name added.""" + exc = sys.exc_info()[1] + if len(exc.args) == 1 and type(exc) is TypeError: + # simple TypeError; add field name to exception message + exc = TypeError('%s for field %s.%s' % (str(exc), message_name, field_name)) + + # re-raise possibly-amended exception with original traceback: + six.reraise(type(exc), exc, sys.exc_info()[2]) + + +def _AddInitMethod(message_descriptor, cls): + """Adds an __init__ method to cls.""" + + def _GetIntegerEnumValue(enum_type, value): + """Convert a string or integer enum value to an integer. + + If the value is a string, it is converted to the enum value in + enum_type with the same name. If the value is not a string, it's + returned as-is. (No conversion or bounds-checking is done.) + """ + if isinstance(value, six.string_types): + try: + return enum_type.values_by_name[value].number + except KeyError: + raise ValueError('Enum type %s: unknown label "%s"' % ( + enum_type.full_name, value)) + return value + + def init(self, **kwargs): + self._cached_byte_size = 0 + self._cached_byte_size_dirty = len(kwargs) > 0 + self._fields = {} + # Contains a mapping from oneof field descriptors to the descriptor + # of the currently set field in that oneof field. + self._oneofs = {} + + # _unknown_fields is () when empty for efficiency, and will be turned into + # a list if fields are added. + self._unknown_fields = () + self._is_present_in_parent = False + self._listener = message_listener_mod.NullMessageListener() + self._listener_for_children = _Listener(self) + for field_name, field_value in list(kwargs.items()): + field = _GetFieldByName(message_descriptor, field_name) + if field is None: + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (message_descriptor.name, field_name)) + if field_value is None: + # field=None is the same as no field at all. + continue + if field.label == _FieldDescriptor.LABEL_REPEATED: + copy = field._default_constructor(self) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite + if _IsMapField(field): + if _IsMessageMapField(field): + for key in field_value: + copy[key].MergeFrom(field_value[key]) + else: + copy.update(field_value) + else: + for val in field_value: + if isinstance(val, dict): + copy.add(**val) + else: + copy.add().MergeFrom(val) + else: # Scalar + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = [_GetIntegerEnumValue(field.enum_type, val) + for val in field_value] + copy.extend(field_value) + self._fields[field] = copy + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + copy = field._default_constructor(self) + new_val = field_value + if isinstance(field_value, dict): + new_val = field.message_type._concrete_class(**field_value) + try: + copy.MergeFrom(new_val) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + self._fields[field] = copy + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = _GetIntegerEnumValue(field.enum_type, field_value) + try: + setattr(self, field_name, field_value) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + + init.__module__ = None + init.__doc__ = None + cls.__init__ = init + + +def _GetFieldByName(message_descriptor, field_name): + """Returns a field descriptor by field name. + + Args: + message_descriptor: A Descriptor describing all fields in message. + field_name: The name of the field to retrieve. + Returns: + The field descriptor associated with the field name. + """ + try: + return message_descriptor.fields_by_name[field_name] + except KeyError: + raise ValueError('Protocol message %s has no "%s" field.' % + (message_descriptor.name, field_name)) + + +def _AddPropertiesForFields(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + for field in descriptor.fields: + _AddPropertiesForField(field, cls) + + if descriptor.is_extendable: + # _ExtensionDict is just an adaptor with no state so we allocate a new one + # every time it is accessed. + cls.Extensions = property(lambda self: _ExtensionDict(self)) + + +def _AddPropertiesForField(field, cls): + """Adds a public property for a protocol message field. + Clients can use this property to get and (in the case + of non-repeated scalar fields) directly set the value + of a protocol message field. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # Catch it if we add other types that we should + # handle specially here. + assert _FieldDescriptor.MAX_CPPTYPE == 10 + + constant_name = field.name.upper() + "_FIELD_NUMBER" + setattr(cls, constant_name, field.number) + + if field.label == _FieldDescriptor.LABEL_REPEATED: + _AddPropertiesForRepeatedField(field, cls) + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + _AddPropertiesForNonRepeatedCompositeField(field, cls) + else: + _AddPropertiesForNonRepeatedScalarField(field, cls) + + +def _AddPropertiesForRepeatedField(field, cls): + """Adds a public property for a "repeated" protocol message field. Clients + can use this property to get the value of the field, which will be either a + _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see + below). + + Note that when clients add values to these containers, we perform + type-checking in the case of repeated scalar fields, and we also set any + necessary "has" bits as a side-effect. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to repeated field ' + '"%s" in protocol message object.' % proto_field_name) + + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedScalarField(field, cls): + """Adds a public property for a nonrepeated, scalar protocol message field. + Clients can use this property to get and directly set the value of the field. + Note that when the client sets the value of a field by using this property, + all necessary "has" bits are set as a side-effect, and we also perform + type-checking. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + type_checker = type_checkers.GetTypeChecker(field) + default_value = field.default_value + valid_values = set() + is_proto3 = field.containing_type.syntax == "proto3" + + def getter(self): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return self._fields.get(field, default_value) + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + clear_when_set_to_default = is_proto3 and not field.containing_oneof + + def field_setter(self, new_value): + # pylint: disable=protected-access + # Testing the value for truthiness captures all of the proto3 defaults + # (0, 0.0, enum 0, and False). + new_value = type_checker.CheckValue(new_value) + if clear_when_set_to_default and not new_value: + self._fields.pop(field, None) + else: + self._fields[field] = new_value + # Check _cached_byte_size_dirty inline to improve performance, since scalar + # setters are called frequently. + if not self._cached_byte_size_dirty: + self._Modified() + + if field.containing_oneof: + def setter(self, new_value): + field_setter(self, new_value) + self._UpdateOneofState(field) + else: + setter = field_setter + + setter.__module__ = None + setter.__doc__ = 'Setter for %s.' % proto_field_name + + # Add a property to encapsulate the getter/setter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedCompositeField(field, cls): + """Adds a public property for a nonrepeated, composite protocol message field. + A composite field is a "group" or "message" field. + + Clients can use this property to get the value of the field, but cannot + assign to the property directly. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # TODO(robinson): Remove duplication with similar method + # for non-repeated scalars. + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to composite field ' + '"%s" in protocol message object.' % proto_field_name) + + # Add a property to encapsulate the getter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForExtensions(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + extension_dict = descriptor.extensions_by_name + for extension_name, extension_field in list(extension_dict.items()): + constant_name = extension_name.upper() + "_FIELD_NUMBER" + setattr(cls, constant_name, extension_field.number) + + # TODO(amauryfa): Migrate all users of these attributes to functions like + # pool.FindExtensionByNumber(descriptor). + if descriptor.file is not None: + # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. + pool = descriptor.file.pool + cls._extensions_by_number = pool._extensions_by_number[descriptor] + cls._extensions_by_name = pool._extensions_by_name[descriptor] + +def _AddStaticMethods(cls): + # TODO(robinson): This probably needs to be thread-safe(?) + def RegisterExtension(extension_handle): + extension_handle.containing_type = cls.DESCRIPTOR + # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. + cls.DESCRIPTOR.file.pool.AddExtensionDescriptor(extension_handle) + _AttachFieldHelpers(cls, extension_handle) + cls.RegisterExtension = staticmethod(RegisterExtension) + + def FromString(s): + message = cls() + message.MergeFromString(s) + return message + cls.FromString = staticmethod(FromString) + + +def _IsPresent(item): + """Given a (FieldDescriptor, value) tuple from _fields, return true if the + value should be included in the list returned by ListFields().""" + + if item[0].label == _FieldDescriptor.LABEL_REPEATED: + return bool(item[1]) + elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + return item[1]._is_present_in_parent + else: + return True + + +def _AddListFieldsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ListFields(self): + all_fields = [item for item in list(self._fields.items()) if _IsPresent(item)] + all_fields.sort(key = lambda item: item[0].number) + return all_fields + + cls.ListFields = ListFields + +_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"' +_Proto2HasError = 'Protocol message has no non-repeated field "%s"' + +def _AddHasFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + is_proto3 = (message_descriptor.syntax == "proto3") + error_msg = _Proto3HasError if is_proto3 else _Proto2HasError + + hassable_fields = {} + for field in message_descriptor.fields: + if field.label == _FieldDescriptor.LABEL_REPEATED: + continue + # For proto3, only submessages and fields inside a oneof have presence. + if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and + not field.containing_oneof): + continue + hassable_fields[field.name] = field + + if not is_proto3: + # Fields inside oneofs are never repeated (enforced by the compiler). + for oneof in message_descriptor.oneofs: + hassable_fields[oneof.name] = oneof + + def HasField(self, field_name): + try: + field = hassable_fields[field_name] + except KeyError: + raise ValueError(error_msg % field_name) + + if isinstance(field, descriptor_mod.OneofDescriptor): + try: + return HasField(self, self._oneofs[field].name) + except KeyError: + return False + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(field) + return value is not None and value._is_present_in_parent + else: + return field in self._fields + + cls.HasField = HasField + + +def _AddClearFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def ClearField(self, field_name): + try: + field = message_descriptor.fields_by_name[field_name] + except KeyError: + try: + field = message_descriptor.oneofs_by_name[field_name] + if field in self._oneofs: + field = self._oneofs[field] + else: + return + except KeyError: + raise ValueError('Protocol message %s() has no "%s" field.' % + (message_descriptor.name, field_name)) + + if field in self._fields: + # To match the C++ implementation, we need to invalidate iterators + # for map fields when ClearField() happens. + if hasattr(self._fields[field], 'InvalidateIterators'): + self._fields[field].InvalidateIterators() + + # Note: If the field is a sub-message, its listener will still point + # at us. That's fine, because the worst than can happen is that it + # will call _Modified() and invalidate our byte size. Big deal. + del self._fields[field] + + if self._oneofs.get(field.containing_oneof, None) is field: + del self._oneofs[field.containing_oneof] + + # Always call _Modified() -- even if nothing was changed, this is + # a mutating method, and thus calling it should cause the field to become + # present in the parent message. + self._Modified() + + cls.ClearField = ClearField + + +def _AddClearExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def ClearExtension(self, extension_handle): + _VerifyExtensionHandle(self, extension_handle) + + # Similar to ClearField(), above. + if extension_handle in self._fields: + del self._fields[extension_handle] + self._Modified() + cls.ClearExtension = ClearExtension + + +def _AddHasExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def HasExtension(self, extension_handle): + _VerifyExtensionHandle(self, extension_handle) + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + raise KeyError('"%s" is repeated.' % extension_handle.full_name) + + if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(extension_handle) + return value is not None and value._is_present_in_parent + else: + return extension_handle in self._fields + cls.HasExtension = HasExtension + +def _InternalUnpackAny(msg): + """Unpacks Any message and returns the unpacked message. + + This internal method is different from public Any Unpack method which takes + the target message as argument. _InternalUnpackAny method does not have + target message type and need to find the message type in descriptor pool. + + Args: + msg: An Any message to be unpacked. + + Returns: + The unpacked message. + """ + # TODO(amauryfa): Don't use the factory of generated messages. + # To make Any work with custom factories, use the message factory of the + # parent message. + # pylint: disable=g-import-not-at-top + from google.protobuf import symbol_database + factory = symbol_database.Default() + + type_url = msg.type_url + + if not type_url: + return None + + # TODO(haberman): For now we just strip the hostname. Better logic will be + # required. + type_name = type_url.split('/')[-1] + descriptor = factory.pool.FindMessageTypeByName(type_name) + + if descriptor is None: + return None + + message_class = factory.GetPrototype(descriptor) + message = message_class() + + message.ParseFromString(msg.value) + return message + + +def _AddEqualsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __eq__(self, other): + if (not isinstance(other, message_mod.Message) or + other.DESCRIPTOR != self.DESCRIPTOR): + return False + + if self is other: + return True + + if self.DESCRIPTOR.full_name == _AnyFullTypeName: + any_a = _InternalUnpackAny(self) + any_b = _InternalUnpackAny(other) + if any_a and any_b: + return any_a == any_b + + if not self.ListFields() == other.ListFields(): + return False + + # Sort unknown fields because their order shouldn't affect equality test. + unknown_fields = list(self._unknown_fields) + unknown_fields.sort() + other_unknown_fields = list(other._unknown_fields) + other_unknown_fields.sort() + + return unknown_fields == other_unknown_fields + + cls.__eq__ = __eq__ + + +def _AddStrMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __str__(self): + return text_format.MessageToString(self) + cls.__str__ = __str__ + + +def _AddReprMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __repr__(self): + return text_format.MessageToString(self) + cls.__repr__ = __repr__ + + +def _AddUnicodeMethod(unused_message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def __unicode__(self): + return text_format.MessageToString(self, as_utf8=True).decode('utf-8') + cls.__unicode__ = __unicode__ + + +def _BytesForNonRepeatedElement(value, field_number, field_type): + """Returns the number of bytes needed to serialize a non-repeated element. + The returned byte count includes space for tag information and any + other additional space associated with serializing value. + + Args: + value: Value we're serializing. + field_number: Field number of this value. (Since the field number + is stored as part of a varint-encoded tag, this has an impact + on the total bytes required to serialize the value). + field_type: The type of the field. One of the TYPE_* constants + within FieldDescriptor. + """ + try: + fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type] + return fn(field_number, value) + except KeyError: + raise message_mod.EncodeError('Unrecognized field type: %d' % field_type) + + +def _AddByteSizeMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ByteSize(self): + if not self._cached_byte_size_dirty: + return self._cached_byte_size + + size = 0 + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + size = descriptor.fields_by_name['key']._sizer(self.key) + size += descriptor.fields_by_name['value']._sizer(self.value) + else: + for field_descriptor, field_value in self.ListFields(): + size += field_descriptor._sizer(field_value) + for tag_bytes, value_bytes in self._unknown_fields: + size += len(tag_bytes) + len(value_bytes) + + self._cached_byte_size = size + self._cached_byte_size_dirty = False + self._listener_for_children.dirty = False + return size + + cls.ByteSize = ByteSize + + +def _AddSerializeToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializeToString(self, **kwargs): + # Check if the message has all of its required fields set. + errors = [] + if not self.IsInitialized(): + raise message_mod.EncodeError( + 'Message %s is missing required fields: %s' % ( + self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors()))) + return self.SerializePartialToString(**kwargs) + cls.SerializeToString = SerializeToString + + +def _AddSerializePartialToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializePartialToString(self, **kwargs): + out = BytesIO() + self._InternalSerialize(out.write, **kwargs) + return out.getvalue() + cls.SerializePartialToString = SerializePartialToString + + def InternalSerialize(self, write_bytes, deterministic=None): + if deterministic is None: + deterministic = ( + api_implementation.IsPythonDefaultSerializationDeterministic()) + else: + deterministic = bool(deterministic) + + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + descriptor.fields_by_name['key']._encoder( + write_bytes, self.key, deterministic) + descriptor.fields_by_name['value']._encoder( + write_bytes, self.value, deterministic) + else: + for field_descriptor, field_value in self.ListFields(): + field_descriptor._encoder(write_bytes, field_value, deterministic) + for tag_bytes, value_bytes in self._unknown_fields: + write_bytes(tag_bytes) + write_bytes(value_bytes) + cls._InternalSerialize = InternalSerialize + + +def _AddMergeFromStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def MergeFromString(self, serialized): + length = len(serialized) + try: + if self._InternalParse(serialized, 0, length) != length: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise message_mod.DecodeError('Unexpected end-group tag.') + except (IndexError, TypeError): + # Now ord(buf[p:p+1]) == ord('') gets TypeError. + raise message_mod.DecodeError('Truncated message.') + except struct.error as e: + raise message_mod.DecodeError(e) + return length # Return this for legacy reasons. + cls.MergeFromString = MergeFromString + + local_ReadTag = decoder.ReadTag + local_SkipField = decoder.SkipField + decoders_by_tag = cls._decoders_by_tag + is_proto3 = message_descriptor.syntax == "proto3" + + def InternalParse(self, buffer, pos, end): + self._Modified() + field_dict = self._fields + unknown_field_list = self._unknown_fields + while pos != end: + (tag_bytes, new_pos) = local_ReadTag(buffer, pos) + field_decoder, field_desc = decoders_by_tag.get(tag_bytes, (None, None)) + if field_decoder is None: + value_start_pos = new_pos + new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) + if new_pos == -1: + return pos + if (not is_proto3 or + api_implementation.GetPythonProto3PreserveUnknownsDefault()): + if not unknown_field_list: + unknown_field_list = self._unknown_fields = [] + unknown_field_list.append( + (tag_bytes, buffer[value_start_pos:new_pos])) + pos = new_pos + else: + pos = field_decoder(buffer, new_pos, end, self, field_dict) + if field_desc: + self._UpdateOneofState(field_desc) + return pos + cls._InternalParse = InternalParse + + +def _AddIsInitializedMethod(message_descriptor, cls): + """Adds the IsInitialized and FindInitializationError methods to the + protocol message class.""" + + required_fields = [field for field in message_descriptor.fields + if field.label == _FieldDescriptor.LABEL_REQUIRED] + + def IsInitialized(self, errors=None): + """Checks if all required fields of a message are set. + + Args: + errors: A list which, if provided, will be populated with the field + paths of all missing required fields. + + Returns: + True iff the specified message has all required fields set. + """ + + # Performance is critical so we avoid HasField() and ListFields(). + + for field in required_fields: + if (field not in self._fields or + (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and + not self._fields[field]._is_present_in_parent)): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + for field, value in list(self._fields.items()): # dict can change size! + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + if (field.message_type.has_options and + field.message_type.GetOptions().map_entry): + continue + for element in value: + if not element.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + elif value._is_present_in_parent and not value.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + return True + + cls.IsInitialized = IsInitialized + + def FindInitializationErrors(self): + """Finds required fields which are not initialized. + + Returns: + A list of strings. Each string is a path to an uninitialized field from + the top-level message, e.g. "foo.bar[5].baz". + """ + + errors = [] # simplify things + + for field in required_fields: + if not self.HasField(field.name): + errors.append(field.name) + + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.is_extension: + name = "(%s)" % field.full_name + else: + name = field.name + + if _IsMapField(field): + if _IsMessageMapField(field): + for key in value: + element = value[key] + prefix = "%s[%s]." % (name, key) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + # ScalarMaps can't have any initialization errors. + pass + elif field.label == _FieldDescriptor.LABEL_REPEATED: + for i in range(len(value)): + element = value[i] + prefix = "%s[%d]." % (name, i) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + prefix = name + "." + sub_errors = value.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + + return errors + + cls.FindInitializationErrors = FindInitializationErrors + + +def _AddMergeFromMethod(cls): + LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED + CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE + + def MergeFrom(self, msg): + if not isinstance(msg, cls): + raise TypeError( + "Parameter to MergeFrom() must be instance of same class: " + 'expected %s got %s.' % (cls.__name__, msg.__class__.__name__)) + + assert msg is not self + self._Modified() + + fields = self._fields + + for field, value in list(msg._fields.items()): + if field.label == LABEL_REPEATED: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + elif field.cpp_type == CPPTYPE_MESSAGE: + if value._is_present_in_parent: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + else: + self._fields[field] = value + if field.containing_oneof: + self._UpdateOneofState(field) + + if msg._unknown_fields: + if not self._unknown_fields: + self._unknown_fields = [] + self._unknown_fields.extend(msg._unknown_fields) + + cls.MergeFrom = MergeFrom + + +def _AddWhichOneofMethod(message_descriptor, cls): + def WhichOneof(self, oneof_name): + """Returns the name of the currently set field inside a oneof, or None.""" + try: + field = message_descriptor.oneofs_by_name[oneof_name] + except KeyError: + raise ValueError( + 'Protocol message has no oneof "%s" field.' % oneof_name) + + nested_field = self._oneofs.get(field, None) + if nested_field is not None and self.HasField(nested_field.name): + return nested_field.name + else: + return None + + cls.WhichOneof = WhichOneof + + +def _AddReduceMethod(cls): + def __reduce__(self): # pylint: disable=invalid-name + return (type(self), (), self.__getstate__()) + cls.__reduce__ = __reduce__ + + +def _Clear(self): + # Clear fields. + self._fields = {} + self._unknown_fields = () + self._oneofs = {} + self._Modified() + + +def _DiscardUnknownFields(self): + self._unknown_fields = [] + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + for sub_message in value: + sub_message.DiscardUnknownFields() + else: + value.DiscardUnknownFields() + + +def _SetListener(self, listener): + if listener is None: + self._listener = message_listener_mod.NullMessageListener() + else: + self._listener = listener + + +def _AddMessageMethods(message_descriptor, cls): + """Adds implementations of all Message methods to cls.""" + _AddListFieldsMethod(message_descriptor, cls) + _AddHasFieldMethod(message_descriptor, cls) + _AddClearFieldMethod(message_descriptor, cls) + if message_descriptor.is_extendable: + _AddClearExtensionMethod(cls) + _AddHasExtensionMethod(cls) + _AddEqualsMethod(message_descriptor, cls) + _AddStrMethod(message_descriptor, cls) + _AddReprMethod(message_descriptor, cls) + _AddUnicodeMethod(message_descriptor, cls) + _AddByteSizeMethod(message_descriptor, cls) + _AddSerializeToStringMethod(message_descriptor, cls) + _AddSerializePartialToStringMethod(message_descriptor, cls) + _AddMergeFromStringMethod(message_descriptor, cls) + _AddIsInitializedMethod(message_descriptor, cls) + _AddMergeFromMethod(cls) + _AddWhichOneofMethod(message_descriptor, cls) + _AddReduceMethod(cls) + # Adds methods which do not depend on cls. + cls.Clear = _Clear + cls.DiscardUnknownFields = _DiscardUnknownFields + cls._SetListener = _SetListener + + +def _AddPrivateHelperMethods(message_descriptor, cls): + """Adds implementation of private helper methods to cls.""" + + def Modified(self): + """Sets the _cached_byte_size_dirty bit to true, + and propagates this to our listener iff this was a state change. + """ + + # Note: Some callers check _cached_byte_size_dirty before calling + # _Modified() as an extra optimization. So, if this method is ever + # changed such that it does stuff even when _cached_byte_size_dirty is + # already true, the callers need to be updated. + if not self._cached_byte_size_dirty: + self._cached_byte_size_dirty = True + self._listener_for_children.dirty = True + self._is_present_in_parent = True + self._listener.Modified() + + def _UpdateOneofState(self, field): + """Sets field as the active field in its containing oneof. + + Will also delete currently active field in the oneof, if it is different + from the argument. Does not mark the message as modified. + """ + other_field = self._oneofs.setdefault(field.containing_oneof, field) + if other_field is not field: + del self._fields[other_field] + self._oneofs[field.containing_oneof] = field + + cls._Modified = Modified + cls.SetInParent = Modified + cls._UpdateOneofState = _UpdateOneofState + + +class _Listener(object): + + """MessageListener implementation that a parent message registers with its + child message. + + In order to support semantics like: + + foo.bar.baz.qux = 23 + assert foo.HasField('bar') + + ...child objects must have back references to their parents. + This helper class is at the heart of this support. + """ + + def __init__(self, parent_message): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + """ + # This listener establishes a back reference from a child (contained) object + # to its parent (containing) object. We make this a weak reference to avoid + # creating cyclic garbage when the client finishes with the 'parent' object + # in the tree. + if isinstance(parent_message, weakref.ProxyType): + self._parent_message_weakref = parent_message + else: + self._parent_message_weakref = weakref.proxy(parent_message) + + # As an optimization, we also indicate directly on the listener whether + # or not the parent message is dirty. This way we can avoid traversing + # up the tree in the common case. + self.dirty = False + + def Modified(self): + if self.dirty: + return + try: + # Propagate the signal to our parents iff this is the first field set. + self._parent_message_weakref._Modified() + except ReferenceError: + # We can get here if a client has kept a reference to a child object, + # and is now setting a field on it, but the child's parent has been + # garbage-collected. This is not an error. + pass + + +class _OneofListener(_Listener): + """Special listener implementation for setting composite oneof fields.""" + + def __init__(self, parent_message, field): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + field: The descriptor of the field being set in the parent message. + """ + super(_OneofListener, self).__init__(parent_message) + self._field = field + + def Modified(self): + """Also updates the state of the containing oneof in the parent message.""" + try: + self._parent_message_weakref._UpdateOneofState(self._field) + super(_OneofListener, self).Modified() + except ReferenceError: + pass + + +# TODO(robinson): Move elsewhere? This file is getting pretty ridiculous... +# TODO(robinson): Unify error handling of "unknown extension" crap. +# TODO(robinson): Support iteritems()-style iteration over all +# extensions with the "has" bits turned on? +class _ExtensionDict(object): + + """Dict-like container for supporting an indexable "Extensions" + field on proto instances. + + Note that in all cases we expect extension handles to be + FieldDescriptors. + """ + + def __init__(self, extended_message): + """extended_message: Message instance for which we are the Extensions dict. + """ + + self._extended_message = extended_message + + def __getitem__(self, extension_handle): + """Returns the current value of the given extension handle.""" + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + result = self._extended_message._fields.get(extension_handle) + if result is not None: + return result + + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + result = extension_handle._default_constructor(self._extended_message) + elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + result = extension_handle.message_type._concrete_class() + try: + result._SetListener(self._extended_message._listener_for_children) + except ReferenceError: + pass + else: + # Singular scalar -- just return the default without inserting into the + # dict. + return extension_handle.default_value + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + result = self._extended_message._fields.setdefault( + extension_handle, result) + + return result + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + + my_fields = self._extended_message.ListFields() + other_fields = other._extended_message.ListFields() + + # Get rid of non-extension fields. + my_fields = [ field for field in my_fields if field.is_extension ] + other_fields = [ field for field in other_fields if field.is_extension ] + + return my_fields == other_fields + + def __ne__(self, other): + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + # Note that this is only meaningful for non-repeated, scalar extension + # fields. Note also that we may have to call _Modified() when we do + # successfully set a field this way, to set any necssary "has" bits in the + # ancestors of the extended message. + def __setitem__(self, extension_handle, value): + """If extension_handle specifies a non-repeated, scalar extension + field, sets the value of that field. + """ + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or + extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE): + raise TypeError( + 'Cannot assign to extension "%s" because it is a repeated or ' + 'composite type.' % extension_handle.full_name) + + # It's slightly wasteful to lookup the type checker each time, + # but we expect this to be a vanishingly uncommon case anyway. + type_checker = type_checkers.GetTypeChecker(extension_handle) + # pylint: disable=protected-access + self._extended_message._fields[extension_handle] = ( + type_checker.CheckValue(value)) + self._extended_message._Modified() + + def _FindExtensionByName(self, name): + """Tries to find a known extension with the specified name. + + Args: + name: Extension full name. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_name.get(name, None) + + def _FindExtensionByNumber(self, number): + """Tries to find a known extension with the field number. + + Args: + number: Extension field number. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_number.get(number, None) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/reflection_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/reflection_test.py new file mode 100644 index 0000000..ed2d7ed --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/reflection_test.py @@ -0,0 +1,3106 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Unittest for reflection.py, which also indirectly tests the output of the +pure-Python protocol compiler. +""" + +import copy +import gc +import operator +import six +import struct + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf import descriptor +from google.protobuf import message +from google.protobuf import reflection +from google.protobuf import text_format +from google.protobuf.internal import api_implementation +from google.protobuf.internal import more_extensions_pb2 +from google.protobuf.internal import more_messages_pb2 +from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import wire_format +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks +from google.protobuf.internal import decoder + + +BaseTestCase = testing_refleaks.BaseTestCase + + +class _MiniDecoder(object): + """Decodes a stream of values from a string. + + Once upon a time we actually had a class called decoder.Decoder. Then we + got rid of it during a redesign that made decoding much, much faster overall. + But a couple tests in this file used it to check that the serialized form of + a message was correct. So, this class implements just the methods that were + used by said tests, so that we don't have to rewrite the tests. + """ + + def __init__(self, bytes): + self._bytes = bytes + self._pos = 0 + + def ReadVarint(self): + result, self._pos = decoder._DecodeVarint(self._bytes, self._pos) + return result + + ReadInt32 = ReadVarint + ReadInt64 = ReadVarint + ReadUInt32 = ReadVarint + ReadUInt64 = ReadVarint + + def ReadSInt64(self): + return wire_format.ZigZagDecode(self.ReadVarint()) + + ReadSInt32 = ReadSInt64 + + def ReadFieldNumberAndWireType(self): + return wire_format.UnpackTag(self.ReadVarint()) + + def ReadFloat(self): + result = struct.unpack('\n\ndescriptor\x12%.protobuf_unittest.TestBadIdentifiers\x18\x65 \x01(\t:\x03\x62\x61r:>\n\nreflection\x12%.protobuf_unittest.TestBadIdentifiers\x18\x66 \x01(\t:\x03\x62\x61z:;\n\x07service\x12%.protobuf_unittest.TestBadIdentifiers\x18g \x01(\t:\x03quxB\x03\x90\x01\x01') +) + + +MESSAGE_FIELD_NUMBER = 100 +message = _descriptor.FieldDescriptor( + name='message', full_name='protobuf_unittest.message', index=0, + number=100, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("foo").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DESCRIPTOR_FIELD_NUMBER = 101 +descriptor = _descriptor.FieldDescriptor( + name='descriptor', full_name='protobuf_unittest.descriptor', index=1, + number=101, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("bar").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REFLECTION_FIELD_NUMBER = 102 +reflection = _descriptor.FieldDescriptor( + name='reflection', full_name='protobuf_unittest.reflection', index=2, + number=102, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("baz").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SERVICE_FIELD_NUMBER = 103 +service = _descriptor.FieldDescriptor( + name='service', full_name='protobuf_unittest.service', index=3, + number=103, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("qux").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTBADIDENTIFIERS = _descriptor.Descriptor( + name='TestBadIdentifiers', + full_name='protobuf_unittest.TestBadIdentifiers', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=74, + serialized_end=104, +) + + +_ANOTHERMESSAGE = _descriptor.Descriptor( + name='AnotherMessage', + full_name='protobuf_unittest.AnotherMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=106, + serialized_end=122, +) + +DESCRIPTOR.message_types_by_name['TestBadIdentifiers'] = _TESTBADIDENTIFIERS +DESCRIPTOR.message_types_by_name['AnotherMessage'] = _ANOTHERMESSAGE +DESCRIPTOR.extensions_by_name['message'] = message +DESCRIPTOR.extensions_by_name['descriptor'] = descriptor +DESCRIPTOR.extensions_by_name['reflection'] = reflection +DESCRIPTOR.extensions_by_name['service'] = service +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestBadIdentifiers = _reflection.GeneratedProtocolMessageType('TestBadIdentifiers', (_message.Message,), dict( + DESCRIPTOR = _TESTBADIDENTIFIERS, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestBadIdentifiers) + )) +_sym_db.RegisterMessage(TestBadIdentifiers) + +AnotherMessage = _reflection.GeneratedProtocolMessageType('AnotherMessage', (_message.Message,), dict( + DESCRIPTOR = _ANOTHERMESSAGE, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AnotherMessage) + )) +_sym_db.RegisterMessage(AnotherMessage) + +TestBadIdentifiers.RegisterExtension(message) +TestBadIdentifiers.RegisterExtension(descriptor) +TestBadIdentifiers.RegisterExtension(reflection) +TestBadIdentifiers.RegisterExtension(service) + +DESCRIPTOR._options = None + +_ANOTHERSERVICE = _descriptor.ServiceDescriptor( + name='AnotherService', + full_name='protobuf_unittest.AnotherService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=124, + serialized_end=140, + methods=[ +]) +_sym_db.RegisterServiceDescriptor(_ANOTHERSERVICE) + +DESCRIPTOR.services_by_name['AnotherService'] = _ANOTHERSERVICE + +AnotherService = service_reflection.GeneratedServiceType('AnotherService', (_service.Service,), dict( + DESCRIPTOR = _ANOTHERSERVICE, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + )) + +AnotherService_Stub = service_reflection.GeneratedServiceStubType('AnotherService_Stub', (AnotherService,), dict( + DESCRIPTOR = _ANOTHERSERVICE, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + )) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/test_util.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/test_util.py new file mode 100644 index 0000000..b7927c4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/test_util.py @@ -0,0 +1,868 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Utilities for Python proto2 tests. + +This is intentionally modeled on C++ code in +//google/protobuf/test_util.*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import numbers +import operator +import os.path + +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_pb2 + +try: + int # Python 2 +except NameError: + long = int # Python 3 + + +# Tests whether the given TestAllTypes message is proto2 or not. +# This is used to gate several fields/features that only exist +# for the proto2 version of the message. +def IsProto2(message): + return message.DESCRIPTOR.syntax == "proto2" + + +def SetAllNonLazyFields(message): + """Sets every non-lazy field in the message to a unique value. + + Args: + message: A TestAllTypes instance. + """ + + # + # Optional fields. + # + + message.optional_int32 = 101 + message.optional_int64 = 102 + message.optional_uint32 = 103 + message.optional_uint64 = 104 + message.optional_sint32 = 105 + message.optional_sint64 = 106 + message.optional_fixed32 = 107 + message.optional_fixed64 = 108 + message.optional_sfixed32 = 109 + message.optional_sfixed64 = 110 + message.optional_float = 111 + message.optional_double = 112 + message.optional_bool = True + message.optional_string = '115' + message.optional_bytes = b'116' + + if IsProto2(message): + message.optionalgroup.a = 117 + message.optional_nested_message.bb = 118 + message.optional_foreign_message.c = 119 + message.optional_import_message.d = 120 + message.optional_public_import_message.e = 126 + + message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ + message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ + if IsProto2(message): + message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ + + message.optional_string_piece = '124' + message.optional_cord = '125' + + # + # Repeated fields. + # + + message.repeated_int32.append(201) + message.repeated_int64.append(202) + message.repeated_uint32.append(203) + message.repeated_uint64.append(204) + message.repeated_sint32.append(205) + message.repeated_sint64.append(206) + message.repeated_fixed32.append(207) + message.repeated_fixed64.append(208) + message.repeated_sfixed32.append(209) + message.repeated_sfixed64.append(210) + message.repeated_float.append(211) + message.repeated_double.append(212) + message.repeated_bool.append(True) + message.repeated_string.append('215') + message.repeated_bytes.append(b'216') + + if IsProto2(message): + message.repeatedgroup.add().a = 217 + message.repeated_nested_message.add().bb = 218 + message.repeated_foreign_message.add().c = 219 + message.repeated_import_message.add().d = 220 + message.repeated_lazy_message.add().bb = 227 + + message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR) + if IsProto2(message): + message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR) + + message.repeated_string_piece.append('224') + message.repeated_cord.append('225') + + # Add a second one of each field and set value by index. + message.repeated_int32.append(0) + message.repeated_int64.append(0) + message.repeated_uint32.append(0) + message.repeated_uint64.append(0) + message.repeated_sint32.append(0) + message.repeated_sint64.append(0) + message.repeated_fixed32.append(0) + message.repeated_fixed64.append(0) + message.repeated_sfixed32.append(0) + message.repeated_sfixed64.append(0) + message.repeated_float.append(0) + message.repeated_double.append(0) + message.repeated_bool.append(True) + message.repeated_string.append('0') + message.repeated_bytes.append(b'0') + message.repeated_int32[1] = 301 + message.repeated_int64[1] = 302 + message.repeated_uint32[1] = 303 + message.repeated_uint64[1] = 304 + message.repeated_sint32[1] = 305 + message.repeated_sint64[1] = 306 + message.repeated_fixed32[1] = 307 + message.repeated_fixed64[1] = 308 + message.repeated_sfixed32[1] = 309 + message.repeated_sfixed64[1] = 310 + message.repeated_float[1] = 311 + message.repeated_double[1] = 312 + message.repeated_bool[1] = False + message.repeated_string[1] = '315' + message.repeated_bytes[1] = b'316' + + if IsProto2(message): + message.repeatedgroup.add().a = 317 + message.repeated_nested_message.add().bb = 318 + message.repeated_foreign_message.add().c = 319 + message.repeated_import_message.add().d = 320 + message.repeated_lazy_message.add().bb = 327 + + message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) + message.repeated_nested_enum[1] = unittest_pb2.TestAllTypes.BAZ + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ) + if IsProto2(message): + message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ) + + message.repeated_string_piece.append('324') + message.repeated_cord.append('325') + + # + # Fields that have defaults. + # + + if IsProto2(message): + message.default_int32 = 401 + message.default_int64 = 402 + message.default_uint32 = 403 + message.default_uint64 = 404 + message.default_sint32 = 405 + message.default_sint64 = 406 + message.default_fixed32 = 407 + message.default_fixed64 = 408 + message.default_sfixed32 = 409 + message.default_sfixed64 = 410 + message.default_float = 411 + message.default_double = 412 + message.default_bool = False + message.default_string = '415' + message.default_bytes = b'416' + + message.default_nested_enum = unittest_pb2.TestAllTypes.FOO + message.default_foreign_enum = unittest_pb2.FOREIGN_FOO + message.default_import_enum = unittest_import_pb2.IMPORT_FOO + + message.default_string_piece = '424' + message.default_cord = '425' + + message.oneof_uint32 = 601 + message.oneof_nested_message.bb = 602 + message.oneof_string = '603' + message.oneof_bytes = b'604' + + +def SetAllFields(message): + SetAllNonLazyFields(message) + message.optional_lazy_message.bb = 127 + + +def SetAllExtensions(message): + """Sets every extension in the message to a unique value. + + Args: + message: A unittest_pb2.TestAllExtensions instance. + """ + + extensions = message.Extensions + pb2 = unittest_pb2 + import_pb2 = unittest_import_pb2 + + # + # Optional fields. + # + + extensions[pb2.optional_int32_extension] = 101 + extensions[pb2.optional_int64_extension] = 102 + extensions[pb2.optional_uint32_extension] = 103 + extensions[pb2.optional_uint64_extension] = 104 + extensions[pb2.optional_sint32_extension] = 105 + extensions[pb2.optional_sint64_extension] = 106 + extensions[pb2.optional_fixed32_extension] = 107 + extensions[pb2.optional_fixed64_extension] = 108 + extensions[pb2.optional_sfixed32_extension] = 109 + extensions[pb2.optional_sfixed64_extension] = 110 + extensions[pb2.optional_float_extension] = 111 + extensions[pb2.optional_double_extension] = 112 + extensions[pb2.optional_bool_extension] = True + extensions[pb2.optional_string_extension] = '115' + extensions[pb2.optional_bytes_extension] = b'116' + + extensions[pb2.optionalgroup_extension].a = 117 + extensions[pb2.optional_nested_message_extension].bb = 118 + extensions[pb2.optional_foreign_message_extension].c = 119 + extensions[pb2.optional_import_message_extension].d = 120 + extensions[pb2.optional_public_import_message_extension].e = 126 + extensions[pb2.optional_lazy_message_extension].bb = 127 + + extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ + extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ + extensions[pb2.optional_foreign_enum_extension] = pb2.FOREIGN_BAZ + extensions[pb2.optional_import_enum_extension] = import_pb2.IMPORT_BAZ + + extensions[pb2.optional_string_piece_extension] = '124' + extensions[pb2.optional_cord_extension] = '125' + + # + # Repeated fields. + # + + extensions[pb2.repeated_int32_extension].append(201) + extensions[pb2.repeated_int64_extension].append(202) + extensions[pb2.repeated_uint32_extension].append(203) + extensions[pb2.repeated_uint64_extension].append(204) + extensions[pb2.repeated_sint32_extension].append(205) + extensions[pb2.repeated_sint64_extension].append(206) + extensions[pb2.repeated_fixed32_extension].append(207) + extensions[pb2.repeated_fixed64_extension].append(208) + extensions[pb2.repeated_sfixed32_extension].append(209) + extensions[pb2.repeated_sfixed64_extension].append(210) + extensions[pb2.repeated_float_extension].append(211) + extensions[pb2.repeated_double_extension].append(212) + extensions[pb2.repeated_bool_extension].append(True) + extensions[pb2.repeated_string_extension].append('215') + extensions[pb2.repeated_bytes_extension].append(b'216') + + extensions[pb2.repeatedgroup_extension].add().a = 217 + extensions[pb2.repeated_nested_message_extension].add().bb = 218 + extensions[pb2.repeated_foreign_message_extension].add().c = 219 + extensions[pb2.repeated_import_message_extension].add().d = 220 + extensions[pb2.repeated_lazy_message_extension].add().bb = 227 + + extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR) + extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR) + extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAR) + + extensions[pb2.repeated_string_piece_extension].append('224') + extensions[pb2.repeated_cord_extension].append('225') + + # Append a second one of each field. + extensions[pb2.repeated_int32_extension].append(301) + extensions[pb2.repeated_int64_extension].append(302) + extensions[pb2.repeated_uint32_extension].append(303) + extensions[pb2.repeated_uint64_extension].append(304) + extensions[pb2.repeated_sint32_extension].append(305) + extensions[pb2.repeated_sint64_extension].append(306) + extensions[pb2.repeated_fixed32_extension].append(307) + extensions[pb2.repeated_fixed64_extension].append(308) + extensions[pb2.repeated_sfixed32_extension].append(309) + extensions[pb2.repeated_sfixed64_extension].append(310) + extensions[pb2.repeated_float_extension].append(311) + extensions[pb2.repeated_double_extension].append(312) + extensions[pb2.repeated_bool_extension].append(False) + extensions[pb2.repeated_string_extension].append('315') + extensions[pb2.repeated_bytes_extension].append(b'316') + + extensions[pb2.repeatedgroup_extension].add().a = 317 + extensions[pb2.repeated_nested_message_extension].add().bb = 318 + extensions[pb2.repeated_foreign_message_extension].add().c = 319 + extensions[pb2.repeated_import_message_extension].add().d = 320 + extensions[pb2.repeated_lazy_message_extension].add().bb = 327 + + extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ) + extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ) + extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAZ) + + extensions[pb2.repeated_string_piece_extension].append('324') + extensions[pb2.repeated_cord_extension].append('325') + + # + # Fields with defaults. + # + + extensions[pb2.default_int32_extension] = 401 + extensions[pb2.default_int64_extension] = 402 + extensions[pb2.default_uint32_extension] = 403 + extensions[pb2.default_uint64_extension] = 404 + extensions[pb2.default_sint32_extension] = 405 + extensions[pb2.default_sint64_extension] = 406 + extensions[pb2.default_fixed32_extension] = 407 + extensions[pb2.default_fixed64_extension] = 408 + extensions[pb2.default_sfixed32_extension] = 409 + extensions[pb2.default_sfixed64_extension] = 410 + extensions[pb2.default_float_extension] = 411 + extensions[pb2.default_double_extension] = 412 + extensions[pb2.default_bool_extension] = False + extensions[pb2.default_string_extension] = '415' + extensions[pb2.default_bytes_extension] = b'416' + + extensions[pb2.default_nested_enum_extension] = pb2.TestAllTypes.FOO + extensions[pb2.default_foreign_enum_extension] = pb2.FOREIGN_FOO + extensions[pb2.default_import_enum_extension] = import_pb2.IMPORT_FOO + + extensions[pb2.default_string_piece_extension] = '424' + extensions[pb2.default_cord_extension] = '425' + + extensions[pb2.oneof_uint32_extension] = 601 + extensions[pb2.oneof_nested_message_extension].bb = 602 + extensions[pb2.oneof_string_extension] = '603' + extensions[pb2.oneof_bytes_extension] = b'604' + + +def SetAllFieldsAndExtensions(message): + """Sets every field and extension in the message to a unique value. + + Args: + message: A unittest_pb2.TestAllExtensions message. + """ + message.my_int = 1 + message.my_string = 'foo' + message.my_float = 1.0 + message.Extensions[unittest_pb2.my_extension_int] = 23 + message.Extensions[unittest_pb2.my_extension_string] = 'bar' + + +def ExpectAllFieldsAndExtensionsInOrder(serialized): + """Ensures that serialized is the serialization we expect for a message + filled with SetAllFieldsAndExtensions(). (Specifically, ensures that the + serialization is in canonical, tag-number order). + """ + my_extension_int = unittest_pb2.my_extension_int + my_extension_string = unittest_pb2.my_extension_string + expected_strings = [] + message = unittest_pb2.TestFieldOrderings() + message.my_int = 1 # Field 1. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.Extensions[my_extension_int] = 23 # Field 5. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.my_string = 'foo' # Field 11. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.Extensions[my_extension_string] = 'bar' # Field 50. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.my_float = 1.0 + expected_strings.append(message.SerializeToString()) + message.Clear() + expected = b''.join(expected_strings) + + if expected != serialized: + raise ValueError('Expected %r, found %r' % (expected, serialized)) + + +def ExpectAllFieldsSet(test_case, message): + """Check all fields for correct values have after Set*Fields() is called.""" + test_case.assertTrue(message.HasField('optional_int32')) + test_case.assertTrue(message.HasField('optional_int64')) + test_case.assertTrue(message.HasField('optional_uint32')) + test_case.assertTrue(message.HasField('optional_uint64')) + test_case.assertTrue(message.HasField('optional_sint32')) + test_case.assertTrue(message.HasField('optional_sint64')) + test_case.assertTrue(message.HasField('optional_fixed32')) + test_case.assertTrue(message.HasField('optional_fixed64')) + test_case.assertTrue(message.HasField('optional_sfixed32')) + test_case.assertTrue(message.HasField('optional_sfixed64')) + test_case.assertTrue(message.HasField('optional_float')) + test_case.assertTrue(message.HasField('optional_double')) + test_case.assertTrue(message.HasField('optional_bool')) + test_case.assertTrue(message.HasField('optional_string')) + test_case.assertTrue(message.HasField('optional_bytes')) + + if IsProto2(message): + test_case.assertTrue(message.HasField('optionalgroup')) + test_case.assertTrue(message.HasField('optional_nested_message')) + test_case.assertTrue(message.HasField('optional_foreign_message')) + test_case.assertTrue(message.HasField('optional_import_message')) + + test_case.assertTrue(message.optionalgroup.HasField('a')) + test_case.assertTrue(message.optional_nested_message.HasField('bb')) + test_case.assertTrue(message.optional_foreign_message.HasField('c')) + test_case.assertTrue(message.optional_import_message.HasField('d')) + + test_case.assertTrue(message.HasField('optional_nested_enum')) + test_case.assertTrue(message.HasField('optional_foreign_enum')) + if IsProto2(message): + test_case.assertTrue(message.HasField('optional_import_enum')) + + test_case.assertTrue(message.HasField('optional_string_piece')) + test_case.assertTrue(message.HasField('optional_cord')) + + test_case.assertEqual(101, message.optional_int32) + test_case.assertEqual(102, message.optional_int64) + test_case.assertEqual(103, message.optional_uint32) + test_case.assertEqual(104, message.optional_uint64) + test_case.assertEqual(105, message.optional_sint32) + test_case.assertEqual(106, message.optional_sint64) + test_case.assertEqual(107, message.optional_fixed32) + test_case.assertEqual(108, message.optional_fixed64) + test_case.assertEqual(109, message.optional_sfixed32) + test_case.assertEqual(110, message.optional_sfixed64) + test_case.assertEqual(111, message.optional_float) + test_case.assertEqual(112, message.optional_double) + test_case.assertEqual(True, message.optional_bool) + test_case.assertEqual('115', message.optional_string) + test_case.assertEqual(b'116', message.optional_bytes) + + if IsProto2(message): + test_case.assertEqual(117, message.optionalgroup.a) + test_case.assertEqual(118, message.optional_nested_message.bb) + test_case.assertEqual(119, message.optional_foreign_message.c) + test_case.assertEqual(120, message.optional_import_message.d) + test_case.assertEqual(126, message.optional_public_import_message.e) + test_case.assertEqual(127, message.optional_lazy_message.bb) + + test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + test_case.assertEqual(unittest_pb2.FOREIGN_BAZ, + message.optional_foreign_enum) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.optional_import_enum) + + # ----------------------------------------------------------------- + + test_case.assertEqual(2, len(message.repeated_int32)) + test_case.assertEqual(2, len(message.repeated_int64)) + test_case.assertEqual(2, len(message.repeated_uint32)) + test_case.assertEqual(2, len(message.repeated_uint64)) + test_case.assertEqual(2, len(message.repeated_sint32)) + test_case.assertEqual(2, len(message.repeated_sint64)) + test_case.assertEqual(2, len(message.repeated_fixed32)) + test_case.assertEqual(2, len(message.repeated_fixed64)) + test_case.assertEqual(2, len(message.repeated_sfixed32)) + test_case.assertEqual(2, len(message.repeated_sfixed64)) + test_case.assertEqual(2, len(message.repeated_float)) + test_case.assertEqual(2, len(message.repeated_double)) + test_case.assertEqual(2, len(message.repeated_bool)) + test_case.assertEqual(2, len(message.repeated_string)) + test_case.assertEqual(2, len(message.repeated_bytes)) + + if IsProto2(message): + test_case.assertEqual(2, len(message.repeatedgroup)) + test_case.assertEqual(2, len(message.repeated_nested_message)) + test_case.assertEqual(2, len(message.repeated_foreign_message)) + test_case.assertEqual(2, len(message.repeated_import_message)) + test_case.assertEqual(2, len(message.repeated_nested_enum)) + test_case.assertEqual(2, len(message.repeated_foreign_enum)) + if IsProto2(message): + test_case.assertEqual(2, len(message.repeated_import_enum)) + + test_case.assertEqual(2, len(message.repeated_string_piece)) + test_case.assertEqual(2, len(message.repeated_cord)) + + test_case.assertEqual(201, message.repeated_int32[0]) + test_case.assertEqual(202, message.repeated_int64[0]) + test_case.assertEqual(203, message.repeated_uint32[0]) + test_case.assertEqual(204, message.repeated_uint64[0]) + test_case.assertEqual(205, message.repeated_sint32[0]) + test_case.assertEqual(206, message.repeated_sint64[0]) + test_case.assertEqual(207, message.repeated_fixed32[0]) + test_case.assertEqual(208, message.repeated_fixed64[0]) + test_case.assertEqual(209, message.repeated_sfixed32[0]) + test_case.assertEqual(210, message.repeated_sfixed64[0]) + test_case.assertEqual(211, message.repeated_float[0]) + test_case.assertEqual(212, message.repeated_double[0]) + test_case.assertEqual(True, message.repeated_bool[0]) + test_case.assertEqual('215', message.repeated_string[0]) + test_case.assertEqual(b'216', message.repeated_bytes[0]) + + if IsProto2(message): + test_case.assertEqual(217, message.repeatedgroup[0].a) + test_case.assertEqual(218, message.repeated_nested_message[0].bb) + test_case.assertEqual(219, message.repeated_foreign_message[0].c) + test_case.assertEqual(220, message.repeated_import_message[0].d) + test_case.assertEqual(227, message.repeated_lazy_message[0].bb) + + test_case.assertEqual(unittest_pb2.TestAllTypes.BAR, + message.repeated_nested_enum[0]) + test_case.assertEqual(unittest_pb2.FOREIGN_BAR, + message.repeated_foreign_enum[0]) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAR, + message.repeated_import_enum[0]) + + test_case.assertEqual(301, message.repeated_int32[1]) + test_case.assertEqual(302, message.repeated_int64[1]) + test_case.assertEqual(303, message.repeated_uint32[1]) + test_case.assertEqual(304, message.repeated_uint64[1]) + test_case.assertEqual(305, message.repeated_sint32[1]) + test_case.assertEqual(306, message.repeated_sint64[1]) + test_case.assertEqual(307, message.repeated_fixed32[1]) + test_case.assertEqual(308, message.repeated_fixed64[1]) + test_case.assertEqual(309, message.repeated_sfixed32[1]) + test_case.assertEqual(310, message.repeated_sfixed64[1]) + test_case.assertEqual(311, message.repeated_float[1]) + test_case.assertEqual(312, message.repeated_double[1]) + test_case.assertEqual(False, message.repeated_bool[1]) + test_case.assertEqual('315', message.repeated_string[1]) + test_case.assertEqual(b'316', message.repeated_bytes[1]) + + if IsProto2(message): + test_case.assertEqual(317, message.repeatedgroup[1].a) + test_case.assertEqual(318, message.repeated_nested_message[1].bb) + test_case.assertEqual(319, message.repeated_foreign_message[1].c) + test_case.assertEqual(320, message.repeated_import_message[1].d) + test_case.assertEqual(327, message.repeated_lazy_message[1].bb) + + test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.repeated_nested_enum[1]) + test_case.assertEqual(unittest_pb2.FOREIGN_BAZ, + message.repeated_foreign_enum[1]) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.repeated_import_enum[1]) + + # ----------------------------------------------------------------- + + if IsProto2(message): + test_case.assertTrue(message.HasField('default_int32')) + test_case.assertTrue(message.HasField('default_int64')) + test_case.assertTrue(message.HasField('default_uint32')) + test_case.assertTrue(message.HasField('default_uint64')) + test_case.assertTrue(message.HasField('default_sint32')) + test_case.assertTrue(message.HasField('default_sint64')) + test_case.assertTrue(message.HasField('default_fixed32')) + test_case.assertTrue(message.HasField('default_fixed64')) + test_case.assertTrue(message.HasField('default_sfixed32')) + test_case.assertTrue(message.HasField('default_sfixed64')) + test_case.assertTrue(message.HasField('default_float')) + test_case.assertTrue(message.HasField('default_double')) + test_case.assertTrue(message.HasField('default_bool')) + test_case.assertTrue(message.HasField('default_string')) + test_case.assertTrue(message.HasField('default_bytes')) + + test_case.assertTrue(message.HasField('default_nested_enum')) + test_case.assertTrue(message.HasField('default_foreign_enum')) + test_case.assertTrue(message.HasField('default_import_enum')) + + test_case.assertEqual(401, message.default_int32) + test_case.assertEqual(402, message.default_int64) + test_case.assertEqual(403, message.default_uint32) + test_case.assertEqual(404, message.default_uint64) + test_case.assertEqual(405, message.default_sint32) + test_case.assertEqual(406, message.default_sint64) + test_case.assertEqual(407, message.default_fixed32) + test_case.assertEqual(408, message.default_fixed64) + test_case.assertEqual(409, message.default_sfixed32) + test_case.assertEqual(410, message.default_sfixed64) + test_case.assertEqual(411, message.default_float) + test_case.assertEqual(412, message.default_double) + test_case.assertEqual(False, message.default_bool) + test_case.assertEqual('415', message.default_string) + test_case.assertEqual(b'416', message.default_bytes) + + test_case.assertEqual(unittest_pb2.TestAllTypes.FOO, + message.default_nested_enum) + test_case.assertEqual(unittest_pb2.FOREIGN_FOO, + message.default_foreign_enum) + test_case.assertEqual(unittest_import_pb2.IMPORT_FOO, + message.default_import_enum) + + +def GoldenFile(filename): + """Finds the given golden file and returns a file object representing it.""" + + # Search up the directory tree looking for the C++ protobuf source code. + path = '.' + while os.path.exists(path): + if os.path.exists(os.path.join(path, 'src/google/protobuf')): + # Found it. Load the golden file from the testdata directory. + full_path = os.path.join(path, 'src/google/protobuf/testdata', filename) + return open(full_path, 'rb') + path = os.path.join(path, '..') + + # Search internally. + path = '.' + full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata', + filename) + if os.path.exists(full_path): + # Found it. Load the golden file from the testdata directory. + return open(full_path, 'rb') + + raise RuntimeError( + 'Could not find golden files. This test must be run from within the ' + 'protobuf source package so that it can read test data files from the ' + 'C++ source tree.') + + +def GoldenFileData(filename): + """Finds the given golden file and returns its contents.""" + with GoldenFile(filename) as f: + return f.read() + + +def SetAllPackedFields(message): + """Sets every field in the message to a unique value. + + Args: + message: A TestPackedTypes instance. + """ + message.packed_int32.extend([601, 701]) + message.packed_int64.extend([602, 702]) + message.packed_uint32.extend([603, 703]) + message.packed_uint64.extend([604, 704]) + message.packed_sint32.extend([605, 705]) + message.packed_sint64.extend([606, 706]) + message.packed_fixed32.extend([607, 707]) + message.packed_fixed64.extend([608, 708]) + message.packed_sfixed32.extend([609, 709]) + message.packed_sfixed64.extend([610, 710]) + message.packed_float.extend([611.0, 711.0]) + message.packed_double.extend([612.0, 712.0]) + message.packed_bool.extend([True, False]) + message.packed_enum.extend([unittest_pb2.FOREIGN_BAR, + unittest_pb2.FOREIGN_BAZ]) + + +def SetAllPackedExtensions(message): + """Sets every extension in the message to a unique value. + + Args: + message: A unittest_pb2.TestPackedExtensions instance. + """ + extensions = message.Extensions + pb2 = unittest_pb2 + + extensions[pb2.packed_int32_extension].extend([601, 701]) + extensions[pb2.packed_int64_extension].extend([602, 702]) + extensions[pb2.packed_uint32_extension].extend([603, 703]) + extensions[pb2.packed_uint64_extension].extend([604, 704]) + extensions[pb2.packed_sint32_extension].extend([605, 705]) + extensions[pb2.packed_sint64_extension].extend([606, 706]) + extensions[pb2.packed_fixed32_extension].extend([607, 707]) + extensions[pb2.packed_fixed64_extension].extend([608, 708]) + extensions[pb2.packed_sfixed32_extension].extend([609, 709]) + extensions[pb2.packed_sfixed64_extension].extend([610, 710]) + extensions[pb2.packed_float_extension].extend([611.0, 711.0]) + extensions[pb2.packed_double_extension].extend([612.0, 712.0]) + extensions[pb2.packed_bool_extension].extend([True, False]) + extensions[pb2.packed_enum_extension].extend([unittest_pb2.FOREIGN_BAR, + unittest_pb2.FOREIGN_BAZ]) + + +def SetAllUnpackedFields(message): + """Sets every field in the message to a unique value. + + Args: + message: A unittest_pb2.TestUnpackedTypes instance. + """ + message.unpacked_int32.extend([601, 701]) + message.unpacked_int64.extend([602, 702]) + message.unpacked_uint32.extend([603, 703]) + message.unpacked_uint64.extend([604, 704]) + message.unpacked_sint32.extend([605, 705]) + message.unpacked_sint64.extend([606, 706]) + message.unpacked_fixed32.extend([607, 707]) + message.unpacked_fixed64.extend([608, 708]) + message.unpacked_sfixed32.extend([609, 709]) + message.unpacked_sfixed64.extend([610, 710]) + message.unpacked_float.extend([611.0, 711.0]) + message.unpacked_double.extend([612.0, 712.0]) + message.unpacked_bool.extend([True, False]) + message.unpacked_enum.extend([unittest_pb2.FOREIGN_BAR, + unittest_pb2.FOREIGN_BAZ]) + + +class NonStandardInteger(numbers.Integral): + """An integer object that does not subclass int. + + This is used to verify that both C++ and regular proto systems can handle + integer others than int and long and that they handle them in predictable + ways. + + NonStandardInteger is the minimal legal specification for a custom Integral. + As such, it does not support 0 < x < 5 and it is not hashable. + + Note: This is added here instead of relying on numpy or a similar library + with custom integers to limit dependencies. + """ + + def __init__(self, val, error_string_on_conversion=None): + assert isinstance(val, numbers.Integral) + if isinstance(val, NonStandardInteger): + val = val.val + self.val = val + self.error_string_on_conversion = error_string_on_conversion + + def __long__(self): + if self.error_string_on_conversion: + raise RuntimeError(self.error_string_on_conversion) + return int(self.val) + + def __abs__(self): + return NonStandardInteger(operator.abs(self.val)) + + def __add__(self, y): + return NonStandardInteger(operator.add(self.val, y)) + + def __div__(self, y): + return NonStandardInteger(operator.div(self.val, y)) + + def __eq__(self, y): + return operator.eq(self.val, y) + + def __floordiv__(self, y): + return NonStandardInteger(operator.floordiv(self.val, y)) + + def __truediv__(self, y): + return NonStandardInteger(operator.truediv(self.val, y)) + + def __invert__(self): + return NonStandardInteger(operator.invert(self.val)) + + def __mod__(self, y): + return NonStandardInteger(operator.mod(self.val, y)) + + def __mul__(self, y): + return NonStandardInteger(operator.mul(self.val, y)) + + def __neg__(self): + return NonStandardInteger(operator.neg(self.val)) + + def __pos__(self): + return NonStandardInteger(operator.pos(self.val)) + + def __pow__(self, y): + return NonStandardInteger(operator.pow(self.val, y)) + + def __trunc__(self): + return int(self.val) + + def __radd__(self, y): + return NonStandardInteger(operator.add(y, self.val)) + + def __rdiv__(self, y): + return NonStandardInteger(operator.div(y, self.val)) + + def __rmod__(self, y): + return NonStandardInteger(operator.mod(y, self.val)) + + def __rmul__(self, y): + return NonStandardInteger(operator.mul(y, self.val)) + + def __rpow__(self, y): + return NonStandardInteger(operator.pow(y, self.val)) + + def __rfloordiv__(self, y): + return NonStandardInteger(operator.floordiv(y, self.val)) + + def __rtruediv__(self, y): + return NonStandardInteger(operator.truediv(y, self.val)) + + def __lshift__(self, y): + return NonStandardInteger(operator.lshift(self.val, y)) + + def __rshift__(self, y): + return NonStandardInteger(operator.rshift(self.val, y)) + + def __rlshift__(self, y): + return NonStandardInteger(operator.lshift(y, self.val)) + + def __rrshift__(self, y): + return NonStandardInteger(operator.rshift(y, self.val)) + + def __le__(self, y): + if isinstance(y, NonStandardInteger): + y = y.val + return operator.le(self.val, y) + + def __lt__(self, y): + if isinstance(y, NonStandardInteger): + y = y.val + return operator.lt(self.val, y) + + def __and__(self, y): + return NonStandardInteger(operator.and_(self.val, y)) + + def __or__(self, y): + return NonStandardInteger(operator.or_(self.val, y)) + + def __xor__(self, y): + return NonStandardInteger(operator.xor(self.val, y)) + + def __rand__(self, y): + return NonStandardInteger(operator.and_(y, self.val)) + + def __ror__(self, y): + return NonStandardInteger(operator.or_(y, self.val)) + + def __rxor__(self, y): + return NonStandardInteger(operator.xor(y, self.val)) + + def __bool__(self): + return self.val + + def __bool__(self): + return self.val + + def __ceil__(self): + return self + + def __floor__(self): + return self + + def __int__(self): + if self.error_string_on_conversion: + raise RuntimeError(self.error_string_on_conversion) + return int(self.val) + + def __round__(self): + return self + + def __repr__(self): + return 'NonStandardInteger(%s)' % self.val diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/testing_refleaks.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/testing_refleaks.py new file mode 100644 index 0000000..429c27b --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/testing_refleaks.py @@ -0,0 +1,126 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""A subclass of unittest.TestCase which checks for reference leaks. + +To use: +- Use testing_refleak.BaseTestCase instead of unittest.TestCase +- Configure and compile Python with --with-pydebug + +If sys.gettotalrefcount() is not available (because Python was built without +the Py_DEBUG option), then this module is a no-op and tests will run normally. +""" + +import gc +import sys + +try: + import copyreg as copyreg #PY26 +except ImportError: + import copyreg + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + + +class LocalTestResult(unittest.TestResult): + """A TestResult which forwards events to a parent object, except for Skips.""" + + def __init__(self, parent_result): + unittest.TestResult.__init__(self) + self.parent_result = parent_result + + def addError(self, test, error): + self.parent_result.addError(test, error) + + def addFailure(self, test, error): + self.parent_result.addFailure(test, error) + + def addSkip(self, test, reason): + pass + + +class ReferenceLeakCheckerTestCase(unittest.TestCase): + """A TestCase which runs tests multiple times, collecting reference counts.""" + + NB_RUNS = 3 + + def run(self, result=None): + # python_message.py registers all Message classes to some pickle global + # registry, which makes the classes immortal. + # We save a copy of this registry, and reset it before we could references. + self._saved_pickle_registry = copyreg.dispatch_table.copy() + + # Run the test twice, to warm up the instance attributes. + super(ReferenceLeakCheckerTestCase, self).run(result=result) + super(ReferenceLeakCheckerTestCase, self).run(result=result) + + oldrefcount = 0 + local_result = LocalTestResult(result) + + refcount_deltas = [] + for _ in range(self.NB_RUNS): + oldrefcount = self._getRefcounts() + super(ReferenceLeakCheckerTestCase, self).run(result=local_result) + newrefcount = self._getRefcounts() + refcount_deltas.append(newrefcount - oldrefcount) + print((refcount_deltas, self)) + + try: + self.assertEqual(refcount_deltas, [0] * self.NB_RUNS) + except Exception: # pylint: disable=broad-except + result.addError(self, sys.exc_info()) + + def _getRefcounts(self): + copyreg.dispatch_table.clear() + copyreg.dispatch_table.update(self._saved_pickle_registry) + # It is sometimes necessary to gc.collect() multiple times, to ensure + # that all objects can be collected. + gc.collect() + gc.collect() + gc.collect() + return sys.gettotalrefcount() + + +if hasattr(sys, 'gettotalrefcount'): + BaseTestCase = ReferenceLeakCheckerTestCase + SkipReferenceLeakChecker = unittest.skip + +else: + # When PyDEBUG is not enabled, run the tests normally. + BaseTestCase = unittest.TestCase + + def SkipReferenceLeakChecker(reason): + del reason # Don't skip, so don't need a reason. + def Same(func): + return func + return Same diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/text_encoding_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/text_encoding_test.py new file mode 100644 index 0000000..c7d182c --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/text_encoding_test.py @@ -0,0 +1,72 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.text_encoding.""" + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import text_encoding + +TEST_VALUES = [ + ("foo\\rbar\\nbaz\\t", + "foo\\rbar\\nbaz\\t", + b"foo\rbar\nbaz\t"), + ("\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", + "\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", + b"'full of \"sound\" and \"fury\"'"), + ("signi\\\\fying\\\\ nothing\\\\", + "signi\\\\fying\\\\ nothing\\\\", + b"signi\\fying\\ nothing\\"), + ("\\010\\t\\n\\013\\014\\r", + "\x08\\t\\n\x0b\x0c\\r", + b"\010\011\012\013\014\015")] + + +class TextEncodingTestCase(unittest.TestCase): + def testCEscape(self): + for escaped, escaped_utf8, unescaped in TEST_VALUES: + self.assertEqual(escaped, + text_encoding.CEscape(unescaped, as_utf8=False)) + self.assertEqual(escaped_utf8, + text_encoding.CEscape(unescaped, as_utf8=True)) + + def testCUnescape(self): + for escaped, escaped_utf8, unescaped in TEST_VALUES: + self.assertEqual(unescaped, text_encoding.CUnescape(escaped)) + self.assertEqual(unescaped, text_encoding.CUnescape(escaped_utf8)) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/text_format_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/text_format_test.py new file mode 100644 index 0000000..f405789 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/text_format_test.py @@ -0,0 +1,1656 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.text_format.""" + +__author__ = 'kenton@google.com (Kenton Varda)' + + +import math +import re +import six +import string + +try: + import unittest2 as unittest # PY26, pylint: disable=g-import-not-at-top +except ImportError: + import unittest # pylint: disable=g-import-not-at-top + +from google.protobuf.internal import _parameterized + +from google.protobuf import any_pb2 +from google.protobuf import any_test_pb2 +from google.protobuf import map_unittest_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import any_test_pb2 as test_extend_any +from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import test_util +from google.protobuf import descriptor_pool +from google.protobuf import text_format + + +# Low-level nuts-n-bolts tests. +class SimpleTextFormatTests(unittest.TestCase): + + # The members of _QUOTES are formatted into a regexp template that + # expects single characters. Therefore it's an error (in addition to being + # non-sensical in the first place) to try to specify a "quote mark" that is + # more than one character. + def testQuoteMarksAreSingleChars(self): + for quote in text_format._QUOTES: + self.assertEqual(1, len(quote)) + + +# Base class with some common functionality. +class TextFormatBase(unittest.TestCase): + + def ReadGolden(self, golden_filename): + with test_util.GoldenFile(golden_filename) as f: + return (f.readlines() if str is bytes else # PY3 + [golden_line.decode('utf-8') for golden_line in f]) + + def CompareToGoldenFile(self, text, golden_filename): + golden_lines = self.ReadGolden(golden_filename) + self.assertMultiLineEqual(text, ''.join(golden_lines)) + + def CompareToGoldenText(self, text, golden_text): + self.assertEqual(text, golden_text) + + def RemoveRedundantZeros(self, text): + # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove + # these zeros in order to match the golden file. + text = text.replace('e+0','e+').replace('e+0','e+') \ + .replace('e-0','e-').replace('e-0','e-') + # Floating point fields are printed with .0 suffix even if they are + # actualy integer numbers. + text = re.compile(r'\.0$', re.MULTILINE).sub('', text) + return text + + +@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) +class TextFormatTest(TextFormatBase): + + def testPrintExotic(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append('\u00fc\ua71f') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'repeated_int64: -9223372036854775808\n' + 'repeated_uint64: 18446744073709551615\n' + 'repeated_double: 123.456\n' + 'repeated_double: 1.23e+22\n' + 'repeated_double: 1.23e-18\n' + 'repeated_string:' + ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' + 'repeated_string: "\\303\\274\\352\\234\\237"\n') + + def testPrintExoticUnicodeSubclass(self, message_module): + + class UnicodeSub(six.text_type): + pass + + message = message_module.TestAllTypes() + message.repeated_string.append(UnicodeSub('\u00fc\ua71f')) + self.CompareToGoldenText( + text_format.MessageToString(message), + 'repeated_string: "\\303\\274\\352\\234\\237"\n') + + def testPrintNestedMessageAsOneLine(self, message_module): + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'repeated_nested_message { bb: 42 }') + + def testPrintRepeatedFieldsAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int32.append(1) + message.repeated_int32.append(1) + message.repeated_int32.append(3) + message.repeated_string.append('Google') + message.repeated_string.append('Zurich') + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 ' + 'repeated_string: "Google" repeated_string: "Zurich"') + + def testPrintNestedNewLineInStringAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.optional_string = 'a\nnew\nline' + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'optional_string: "a\\nnew\\nline"') + + def testPrintExoticAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append('\u00fc\ua71f') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString( + message, as_one_line=True)), + 'repeated_int64: -9223372036854775808' + ' repeated_uint64: 18446744073709551615' + ' repeated_double: 123.456' + ' repeated_double: 1.23e+22' + ' repeated_double: 1.23e-18' + ' repeated_string: ' + '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""' + ' repeated_string: "\\303\\274\\352\\234\\237"') + + def testRoundTripExoticAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append('\u00fc\ua71f') + + # Test as_utf8 = False. + wire_text = text_format.MessageToString(message, + as_one_line=True, + as_utf8=False) + parsed_message = message_module.TestAllTypes() + r = text_format.Parse(wire_text, parsed_message) + self.assertIs(r, parsed_message) + self.assertEqual(message, parsed_message) + + # Test as_utf8 = True. + wire_text = text_format.MessageToString(message, + as_one_line=True, + as_utf8=True) + parsed_message = message_module.TestAllTypes() + r = text_format.Parse(wire_text, parsed_message) + self.assertIs(r, parsed_message) + self.assertEqual(message, parsed_message, + '\n%s != %s' % (message, parsed_message)) + + def testPrintRawUtf8String(self, message_module): + message = message_module.TestAllTypes() + message.repeated_string.append('\u00fc\ua71f') + text = text_format.MessageToString(message, as_utf8=True) + self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n') + parsed_message = message_module.TestAllTypes() + text_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message, + '\n%s != %s' % (message, parsed_message)) + + def testPrintFloatFormat(self, message_module): + # Check that float_format argument is passed to sub-message formatting. + message = message_module.NestedTestAllTypes() + # We use 1.25 as it is a round number in binary. The proto 32-bit float + # will not gain additional imprecise digits as a 64-bit Python float and + # show up in its str. 32-bit 1.2 is noisy when extended to 64-bit: + # >>> struct.unpack('f', struct.pack('f', 1.2))[0] + # 1.2000000476837158 + # >>> struct.unpack('f', struct.pack('f', 1.25))[0] + # 1.25 + message.payload.optional_float = 1.25 + # Check rounding at 15 significant digits + message.payload.optional_double = -.000003456789012345678 + # Check no decimal point. + message.payload.repeated_float.append(-5642) + # Check no trailing zeros. + message.payload.repeated_double.append(.000078900) + formatted_fields = ['optional_float: 1.25', + 'optional_double: -3.45678901234568e-6', + 'repeated_float: -5642', 'repeated_double: 7.89e-5'] + text_message = text_format.MessageToString(message, float_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format( + *formatted_fields)) + # as_one_line=True is a separate code branch where float_format is passed. + text_message = text_format.MessageToString(message, + as_one_line=True, + float_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{ {0} {1} {2} {3} }}'.format(*formatted_fields)) + + def testMessageToString(self, message_module): + message = message_module.ForeignMessage() + message.c = 123 + self.assertEqual('c: 123\n', str(message)) + + def testPrintField(self, message_module): + message = message_module.TestAllTypes() + field = message.DESCRIPTOR.fields_by_name['optional_float'] + value = message.optional_float + out = text_format.TextWriter(False) + text_format.PrintField(field, value, out) + self.assertEqual('optional_float: 0.0\n', out.getvalue()) + out.close() + # Test Printer + out = text_format.TextWriter(False) + printer = text_format._Printer(out) + printer.PrintField(field, value) + self.assertEqual('optional_float: 0.0\n', out.getvalue()) + out.close() + + def testPrintFieldValue(self, message_module): + message = message_module.TestAllTypes() + field = message.DESCRIPTOR.fields_by_name['optional_float'] + value = message.optional_float + out = text_format.TextWriter(False) + text_format.PrintFieldValue(field, value, out) + self.assertEqual('0.0', out.getvalue()) + out.close() + # Test Printer + out = text_format.TextWriter(False) + printer = text_format._Printer(out) + printer.PrintFieldValue(field, value) + self.assertEqual('0.0', out.getvalue()) + out.close() + + def testParseAllFields(self, message_module): + message = message_module.TestAllTypes() + test_util.SetAllFields(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = message_module.TestAllTypes() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + def testParseAndMergeUtf8(self, message_module): + message = message_module.TestAllTypes() + test_util.SetAllFields(message) + ascii_text = text_format.MessageToString(message) + ascii_text = ascii_text.encode('utf-8') + + parsed_message = message_module.TestAllTypes() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + parsed_message.Clear() + text_format.Merge(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + if six.PY2: + msg2 = message_module.TestAllTypes() + text = ('optional_string: "café"') + text_format.Merge(text, msg2) + self.assertEqual(msg2.optional_string, 'café') + msg2.Clear() + text_format.Parse(text, msg2) + self.assertEqual(msg2.optional_string, 'café') + + def testParseExotic(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_int64: -9223372036854775808\n' + 'repeated_uint64: 18446744073709551615\n' + 'repeated_double: 123.456\n' + 'repeated_double: 1.23e+22\n' + 'repeated_double: 1.23e-18\n' + 'repeated_string: \n' + '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' + 'repeated_string: "foo" \'corge\' "grault"\n' + 'repeated_string: "\\303\\274\\352\\234\\237"\n' + 'repeated_string: "\\xc3\\xbc"\n' + 'repeated_string: "\xc3\xbc"\n') + text_format.Parse(text, message) + + self.assertEqual(-9223372036854775808, message.repeated_int64[0]) + self.assertEqual(18446744073709551615, message.repeated_uint64[0]) + self.assertEqual(123.456, message.repeated_double[0]) + self.assertEqual(1.23e22, message.repeated_double[1]) + self.assertEqual(1.23e-18, message.repeated_double[2]) + self.assertEqual('\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0]) + self.assertEqual('foocorgegrault', message.repeated_string[1]) + self.assertEqual('\u00fc\ua71f', message.repeated_string[2]) + self.assertEqual('\u00fc', message.repeated_string[3]) + + def testParseTrailingCommas(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_int64: 100;\n' + 'repeated_int64: 200;\n' + 'repeated_int64: 300,\n' + 'repeated_string: "one",\n' + 'repeated_string: "two";\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_int64[0]) + self.assertEqual(200, message.repeated_int64[1]) + self.assertEqual(300, message.repeated_int64[2]) + self.assertEqual('one', message.repeated_string[0]) + self.assertEqual('two', message.repeated_string[1]) + + def testParseRepeatedScalarShortFormat(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_int64: [100, 200];\n' + 'repeated_int64: []\n' + 'repeated_int64: 300,\n' + 'repeated_string: ["one", "two"];\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_int64[0]) + self.assertEqual(200, message.repeated_int64[1]) + self.assertEqual(300, message.repeated_int64[2]) + self.assertEqual('one', message.repeated_string[0]) + self.assertEqual('two', message.repeated_string[1]) + + def testParseRepeatedMessageShortFormat(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_nested_message: [{bb: 100}, {bb: 200}],\n' + 'repeated_nested_message: {bb: 300}\n' + 'repeated_nested_message [{bb: 400}];\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_nested_message[0].bb) + self.assertEqual(200, message.repeated_nested_message[1].bb) + self.assertEqual(300, message.repeated_nested_message[2].bb) + self.assertEqual(400, message.repeated_nested_message[3].bb) + + def testParseEmptyText(self, message_module): + message = message_module.TestAllTypes() + text = '' + text_format.Parse(text, message) + self.assertEqual(message_module.TestAllTypes(), message) + + def testParseInvalidUtf8(self, message_module): + message = message_module.TestAllTypes() + text = 'repeated_string: "\\xc3\\xc3"' + with self.assertRaises(text_format.ParseError) as e: + text_format.Parse(text, message) + self.assertEqual(e.exception.GetLine(), 1) + self.assertEqual(e.exception.GetColumn(), 28) + + def testParseSingleWord(self, message_module): + message = message_module.TestAllTypes() + text = 'foo' + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"foo".'), text_format.Parse, text, message) + + def testParseUnknownField(self, message_module): + message = message_module.TestAllTypes() + text = 'unknown_field: 8\n' + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"unknown_field".'), text_format.Parse, text, message) + + def testParseBadEnumValue(self, message_module): + message = message_module.TestAllTypes() + text = 'optional_nested_enum: BARR' + six.assertRaisesRegex(self, text_format.ParseError, + (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value named BARR.'), text_format.Parse, + text, message) + + def testParseBadIntValue(self, message_module): + message = message_module.TestAllTypes() + text = 'optional_int32: bork' + six.assertRaisesRegex(self, text_format.ParseError, + ('1:17 : Couldn\'t parse integer: bork'), + text_format.Parse, text, message) + + def testParseStringFieldUnescape(self, message_module): + message = message_module.TestAllTypes() + text = r'''repeated_string: "\xf\x62" + repeated_string: "\\xf\\x62" + repeated_string: "\\\xf\\\x62" + repeated_string: "\\\\xf\\\\x62" + repeated_string: "\\\\\xf\\\\\x62" + repeated_string: "\x5cx20"''' + + text_format.Parse(text, message) + + SLASH = '\\' + self.assertEqual('\x0fb', message.repeated_string[0]) + self.assertEqual(SLASH + 'xf' + SLASH + 'x62', message.repeated_string[1]) + self.assertEqual(SLASH + '\x0f' + SLASH + 'b', message.repeated_string[2]) + self.assertEqual(SLASH + SLASH + 'xf' + SLASH + SLASH + 'x62', + message.repeated_string[3]) + self.assertEqual(SLASH + SLASH + '\x0f' + SLASH + SLASH + 'b', + message.repeated_string[4]) + self.assertEqual(SLASH + 'x20', message.repeated_string[5]) + + def testMergeDuplicateScalars(self, message_module): + message = message_module.TestAllTypes() + text = ('optional_int32: 42 ' 'optional_int32: 67') + r = text_format.Merge(text, message) + self.assertIs(r, message) + self.assertEqual(67, message.optional_int32) + + def testMergeDuplicateNestedMessageScalars(self, message_module): + message = message_module.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + r = text_format.Merge(text, message) + self.assertTrue(r is message) + self.assertEqual(2, message.optional_nested_message.bb) + + def testParseOneof(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + text_format.Parse(text_format.MessageToString(m), m2) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testMergeMultipleOneof(self, message_module): + m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) + m2 = message_module.TestAllTypes() + text_format.Merge(m_string, m2) + self.assertEqual('oneof_string', m2.WhichOneof('oneof_field')) + + def testParseMultipleOneof(self, message_module): + m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) + m2 = message_module.TestAllTypes() + with self.assertRaisesRegex(text_format.ParseError, + ' is specified along with field '): + text_format.Parse(m_string, m2) + + +# These are tests that aren't fundamentally specific to proto2, but are at +# the moment because of differences between the proto2 and proto3 test schemas. +# Ideally the schemas would be made more similar so these tests could pass. +class OnlyWorksWithProto2RightNowTests(TextFormatBase): + + def testPrintAllFieldsPointy(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString( + message, pointy_brackets=True)), + 'text_format_unittest_data_pointy_oneof.txt') + + def testParseGolden(self): + golden_text = '\n'.join(self.ReadGolden( + 'text_format_unittest_data_oneof_implemented.txt')) + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.Parse(golden_text, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testPrintAllFields(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_data_oneof_implemented.txt') + + def testPrintInIndexOrder(self): + message = unittest_pb2.TestFieldOrderings() + # Fields are listed in index order instead of field number. + message.my_string = 'str' + message.my_int = 101 + message.my_float = 111 + message.optional_nested_message.oo = 0 + message.optional_nested_message.bb = 1 + message.Extensions[unittest_pb2.my_extension_string] = 'ext_str0' + # Extensions are listed based on the order of extension number. + # Extension number 12. + message.Extensions[unittest_pb2.TestExtensionOrderings2. + test_ext_orderings2].my_string = 'ext_str2' + # Extension number 13. + message.Extensions[unittest_pb2.TestExtensionOrderings1. + test_ext_orderings1].my_string = 'ext_str1' + # Extension number 14. + message.Extensions[ + unittest_pb2.TestExtensionOrderings2.TestExtensionOrderings3. + test_ext_orderings3].my_string = 'ext_str3' + + # Print in index order. + self.CompareToGoldenText( + self.RemoveRedundantZeros( + text_format.MessageToString(message, use_index_order=True)), + 'my_string: "str"\n' + 'my_int: 101\n' + 'my_float: 111\n' + 'optional_nested_message {\n' + ' oo: 0\n' + ' bb: 1\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n' + ' my_string: "ext_str2"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n' + ' my_string: "ext_str1"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3' + '.test_ext_orderings3] {\n' + ' my_string: "ext_str3"\n' + '}\n' + '[protobuf_unittest.my_extension_string]: "ext_str0"\n') + # By default, print in field number order. + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'my_int: 101\n' + 'my_string: "str"\n' + '[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n' + ' my_string: "ext_str2"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n' + ' my_string: "ext_str1"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3' + '.test_ext_orderings3] {\n' + ' my_string: "ext_str3"\n' + '}\n' + '[protobuf_unittest.my_extension_string]: "ext_str0"\n' + 'my_float: 111\n' + 'optional_nested_message {\n' + ' bb: 1\n' + ' oo: 0\n' + '}\n') + + def testMergeLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.MergeLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testParseLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.ParseLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testPrintMap(self): + message = map_unittest_pb2.TestMap() + + message.map_int32_int32[-123] = -456 + message.map_int64_int64[-2**33] = -2**34 + message.map_uint32_uint32[123] = 456 + message.map_uint64_uint64[2**33] = 2**34 + message.map_string_string['abc'] = '123' + message.map_int32_foreign_message[111].c = 5 + + # Maps are serialized to text format using their underlying repeated + # representation. + self.CompareToGoldenText( + text_format.MessageToString(message), 'map_int32_int32 {\n' + ' key: -123\n' + ' value: -456\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + ' value: -17179869184\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + ' value: 456\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + ' value: 17179869184\n' + '}\n' + 'map_string_string {\n' + ' key: "abc"\n' + ' value: "123"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 5\n' + ' }\n' + '}\n') + + def testMapOrderEnforcement(self): + message = map_unittest_pb2.TestMap() + for letter in string.ascii_uppercase[13:26]: + message.map_string_string[letter] = 'dummy' + for letter in reversed(string.ascii_uppercase[0:13]): + message.map_string_string[letter] = 'dummy' + golden = ''.join(('map_string_string {\n key: "%c"\n value: "dummy"\n}\n' + % (letter,) for letter in string.ascii_uppercase)) + self.CompareToGoldenText(text_format.MessageToString(message), golden) + + # TODO(teboring): In c/137553523, not serializing default value for map entry + # message has been fixed. This test needs to be disabled in order to submit + # that cl. Add this back when c/137553523 has been submitted. + # def testMapOrderSemantics(self): + # golden_lines = self.ReadGolden('map_test_data.txt') + + # message = map_unittest_pb2.TestMap() + # text_format.ParseLines(golden_lines, message) + # candidate = text_format.MessageToString(message) + # # The Python implementation emits "1.0" for the double value that the C++ + # # implementation emits as "1". + # candidate = candidate.replace('1.0', '1', 2) + # candidate = candidate.replace('0.0', '0', 2) + # self.assertMultiLineEqual(candidate, ''.join(golden_lines)) + + +# Tests of proto2-only features (MessageSet, extensions, etc.). +class Proto2Tests(TextFormatBase): + + def testPrintMessageSet(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message), 'message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + + message = message_set_extensions_pb2.TestMessageSet() + ext = message_set_extensions_pb2.message_set_extension3 + message.Extensions[ext].text = 'bar' + self.CompareToGoldenText( + text_format.MessageToString(message), + '[google.protobuf.internal.TestMessageSetExtension3] {\n' + ' text: \"bar\"\n' + '}\n') + + def testPrintMessageSetByFieldNumber(self): + out = text_format.TextWriter(False) + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + text_format.PrintMessage(message, out, use_field_number=True) + self.CompareToGoldenText(out.getvalue(), '1 {\n' + ' 1545008 {\n' + ' 15: 23\n' + ' }\n' + ' 1547769 {\n' + ' 25: \"foo\"\n' + ' }\n' + '}\n') + out.close() + + def testPrintMessageSetAsOneLine(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'message_set {' + ' [protobuf_unittest.TestMessageSetExtension1] {' + ' i: 23' + ' }' + ' [protobuf_unittest.TestMessageSetExtension2] {' + ' str: \"foo\"' + ' }' + ' }') + + def testParseMessageSet(self): + message = unittest_pb2.TestAllTypes() + text = ('repeated_uint64: 1\n' 'repeated_uint64: 2\n') + text_format.Parse(text, message) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + def testExtensionInsideAnyMessage(self): + message = test_extend_any.TestAny() + text = ('value {\n' + ' [type.googleapis.com/google.protobuf.internal.TestAny] {\n' + ' [google.protobuf.internal.TestAnyExtension1.extension1] {\n' + ' i: 10\n' + ' }\n' + ' }\n' + '}\n') + text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default()) + self.CompareToGoldenText( + text_format.MessageToString( + message, descriptor_pool=descriptor_pool.Default()), + text) + + def testParseMessageByFieldNumber(self): + message = unittest_pb2.TestAllTypes() + text = ('34: 1\n' 'repeated_uint64: 2\n') + text_format.Parse(text, message, allow_field_number=True) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('1 {\n' + ' 1545008 {\n' + ' 15: 23\n' + ' }\n' + ' 1547769 {\n' + ' 25: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_field_number=True) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + # Can't parse field number without set allow_field_number=True. + message = unittest_pb2.TestAllTypes() + text = '34:1\n' + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"34".'), text_format.Parse, text, message) + + # Can't parse if field number is not found. + text = '1234:1\n' + six.assertRaisesRegex( + self, + text_format.ParseError, + (r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"1234".'), + text_format.Parse, + text, + message, + allow_field_number=True) + + def testPrintAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_extensions_data.txt') + + def testPrintAllExtensionsPointy(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString( + message, pointy_brackets=True)), + 'text_format_unittest_extensions_data_pointy.txt') + + def testParseGoldenExtensions(self): + golden_text = '\n'.join(self.ReadGolden( + 'text_format_unittest_extensions_data.txt')) + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Parse(golden_text, parsed_message) + + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.assertEqual(message, parsed_message) + + def testParseAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + + def testParseAllowedUnknownExtension(self): + # Skip over unknown extension correctly. + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [unknown_extension] {\n' + ' i: 23\n' + ' bin: "\xe0"' + ' [nested_unknown_ext]: {\n' + ' i: 23\n' + ' x: x\n' + ' test: "test_string"\n' + ' floaty_float: -0.315\n' + ' num: -inf\n' + ' multiline_str: "abc"\n' + ' "def"\n' + ' "xyz."\n' + ' [nested_unknown_ext.ext]: <\n' + ' i: 23\n' + ' i: 24\n' + ' pointfloat: .3\n' + ' test: "test_string"\n' + ' floaty_float: -0.315\n' + ' num: -inf\n' + ' long_string: "test" "test2" \n' + ' >\n' + ' }\n' + ' }\n' + ' [unknown_extension]: 5\n' + ' [unknown_extension_with_number_field] {\n' + ' 1: "some_field"\n' + ' 2: -0.451\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_unknown_extension=True) + golden = 'message_set {\n}\n' + self.CompareToGoldenText(text_format.MessageToString(message), golden) + + # Catch parse errors in unknown extension. + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [unknown_extension] {\n' + ' i:\n' # Missing value. + ' }\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + 'Invalid field value: }', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [unknown_extension] {\n' + ' str: "malformed string\n' # Missing closing quote. + ' }\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + 'Invalid field value: "', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [unknown_extension] {\n' + ' str: "malformed\n multiline\n string\n' + ' }\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + 'Invalid field value: "', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [malformed_extension] <\n' + ' i: -5\n' + ' \n' # Missing '>' here. + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + '5:1 : Expected ">".', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + # Don't allow unknown fields with allow_unknown_extension=True. + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' unknown_field: true\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + ('2:3 : Message type ' + '"proto2_wireformat_unittest.TestMessageSet" has no' + ' field named "unknown_field".'), + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + # Parse known extension correctly. + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_unknown_extension=True) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + def testParseBadIdentifier(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { "bb": 1 }') + with self.assertRaises(text_format.ParseError) as e: + text_format.Parse(text, message) + self.assertEqual(str(e.exception), + '1:27 : Expected identifier or number, got "bb".') + + def testParseBadExtension(self): + message = unittest_pb2.TestAllExtensions() + text = '[unknown_extension]: 8\n' + six.assertRaisesRegex(self, text_format.ParseError, + '1:2 : Extension "unknown_extension" not registered.', + text_format.Parse, text, message) + message = unittest_pb2.TestAllTypes() + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:2 : Message type "protobuf_unittest.TestAllTypes" does not have ' + 'extensions.'), text_format.Parse, text, message) + + def testParseNumericUnknownEnum(self): + message = unittest_pb2.TestAllTypes() + text = 'optional_nested_enum: 100' + six.assertRaisesRegex(self, text_format.ParseError, + (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value with number 100.'), text_format.Parse, + text, message) + + def testMergeDuplicateExtensionScalars(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_int32_extension]: 42 ' + '[protobuf_unittest.optional_int32_extension]: 67') + text_format.Merge(text, message) + self.assertEqual(67, + message.Extensions[unittest_pb2.optional_int32_extension]) + + def testParseDuplicateExtensionScalars(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_int32_extension]: 42 ' + '[protobuf_unittest.optional_int32_extension]: 67') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:96 : Message type "protobuf_unittest.TestAllExtensions" ' + 'should not have multiple ' + '"protobuf_unittest.optional_int32_extension" extensions.'), + text_format.Parse, text, message) + + def testParseDuplicateMessages(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:59 : Message type "protobuf_unittest.TestAllTypes" ' + 'should not have multiple "optional_nested_message" fields.'), + text_format.Parse, text, + message) + + def testParseDuplicateExtensionMessages(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_nested_message_extension]: {} ' + '[protobuf_unittest.optional_nested_message_extension]: {}') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:114 : Message type "protobuf_unittest.TestAllExtensions" ' + 'should not have multiple ' + '"protobuf_unittest.optional_nested_message_extension" extensions.'), + text_format.Parse, text, message) + + def testParseDuplicateScalars(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_int32: 42 ' 'optional_int32: 67') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:36 : Message type "protobuf_unittest.TestAllTypes" should not ' + 'have multiple "optional_int32" fields.'), text_format.Parse, text, + message) + + def testParseGroupNotClosed(self): + message = unittest_pb2.TestAllTypes() + text = 'RepeatedGroup: <' + six.assertRaisesRegex(self, text_format.ParseError, '1:16 : Expected ">".', + text_format.Parse, text, message) + text = 'RepeatedGroup: {' + six.assertRaisesRegex(self, text_format.ParseError, '1:16 : Expected "}".', + text_format.Parse, text, message) + + def testParseEmptyGroup(self): + message = unittest_pb2.TestAllTypes() + text = 'OptionalGroup: {}' + text_format.Parse(text, message) + self.assertTrue(message.HasField('optionalgroup')) + + message.Clear() + + message = unittest_pb2.TestAllTypes() + text = 'OptionalGroup: <>' + text_format.Parse(text, message) + self.assertTrue(message.HasField('optionalgroup')) + + # Maps aren't really proto2-only, but our test schema only has maps for + # proto2. + def testParseMap(self): + text = ('map_int32_int32 {\n' + ' key: -123\n' + ' value: -456\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + ' value: -17179869184\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + ' value: 456\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + ' value: 17179869184\n' + '}\n' + 'map_string_string {\n' + ' key: "abc"\n' + ' value: "123"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 5\n' + ' }\n' + '}\n') + message = map_unittest_pb2.TestMap() + text_format.Parse(text, message) + + self.assertEqual(-456, message.map_int32_int32[-123]) + self.assertEqual(-2**34, message.map_int64_int64[-2**33]) + self.assertEqual(456, message.map_uint32_uint32[123]) + self.assertEqual(2**34, message.map_uint64_uint64[2**33]) + self.assertEqual('123', message.map_string_string['abc']) + self.assertEqual(5, message.map_int32_foreign_message[111].c) + + +class Proto3Tests(unittest.TestCase): + + def testPrintMessageExpandAny(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + descriptor_pool=descriptor_pool.Default()), + 'any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + + def testTopAnyMessage(self): + packed_msg = unittest_pb2.OneString() + msg = any_pb2.Any() + msg.Pack(packed_msg) + text = text_format.MessageToString(msg) + other_msg = text_format.Parse(text, any_pb2.Any()) + self.assertEqual(msg, other_msg) + + def testPrintMessageExpandAnyRepeated(self): + packed_message = unittest_pb2.OneString() + message = any_test_pb2.TestAny() + packed_message.data = 'string0' + message.repeated_any_value.add().Pack(packed_message) + packed_message.data = 'string1' + message.repeated_any_value.add().Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message), + 'repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string0"\n' + ' }\n' + '}\n' + 'repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string1"\n' + ' }\n' + '}\n') + + def testPrintMessageExpandAnyDescriptorPoolMissingType(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + empty_pool = descriptor_pool.DescriptorPool() + self.assertEqual( + text_format.MessageToString(message, descriptor_pool=empty_pool), + 'any_value {\n' + ' type_url: "type.googleapis.com/protobuf_unittest.OneString"\n' + ' value: "\\n\\006string"\n' + '}\n') + + def testPrintMessageExpandAnyPointyBrackets(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + pointy_brackets=True), + 'any_value <\n' + ' [type.googleapis.com/protobuf_unittest.OneString] <\n' + ' data: "string"\n' + ' >\n' + '>\n') + + def testPrintMessageExpandAnyAsOneLine(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + as_one_line=True), + 'any_value {' + ' [type.googleapis.com/protobuf_unittest.OneString]' + ' { data: "string" } ' + '}') + + def testPrintMessageExpandAnyAsOneLinePointyBrackets(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + as_one_line=True, + pointy_brackets=True, + descriptor_pool=descriptor_pool.Default()), + 'any_value <' + ' [type.googleapis.com/protobuf_unittest.OneString]' + ' < data: "string" > ' + '>') + + def testUnknownEnums(self): + message = unittest_proto3_arena_pb2.TestAllTypes() + message2 = unittest_proto3_arena_pb2.TestAllTypes() + message.optional_nested_enum = 999 + text_string = text_format.MessageToString(message) + text_format.Parse(text_string, message2) + self.assertEqual(999, message2.optional_nested_enum) + + def testMergeExpandedAny(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + message.Clear() + text_format.Parse(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + + def testMergeExpandedAnyRepeated(self): + message = any_test_pb2.TestAny() + text = ('repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string0"\n' + ' }\n' + '}\n' + 'repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string1"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.repeated_any_value[0].Unpack(packed_message) + self.assertEqual('string0', packed_message.data) + message.repeated_any_value[1].Unpack(packed_message) + self.assertEqual('string1', packed_message.data) + + def testMergeExpandedAnyPointyBrackets(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] <\n' + ' data: "string"\n' + ' >\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + + def testMergeAlternativeUrl(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.otherapi.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + self.assertEqual('type.otherapi.com/protobuf_unittest.OneString', + message.any_value.type_url) + + def testMergeExpandedAnyDescriptorPoolMissingType(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + with self.assertRaises(text_format.ParseError) as e: + empty_pool = descriptor_pool.DescriptorPool() + text_format.Merge(text, message, descriptor_pool=empty_pool) + self.assertEqual( + str(e.exception), + 'Type protobuf_unittest.OneString not found in descriptor pool') + + def testMergeUnexpandedAny(self): + text = ('any_value {\n' + ' type_url: "type.googleapis.com/protobuf_unittest.OneString"\n' + ' value: "\\n\\006string"\n' + '}\n') + message = any_test_pb2.TestAny() + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + + def testMergeMissingAnyEndToken(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n') + with self.assertRaises(text_format.ParseError) as e: + text_format.Merge(text, message) + self.assertEqual(str(e.exception), '3:11 : Expected "}".') + + +class TokenizerTest(unittest.TestCase): + + def testSimpleTokenCases(self): + text = ('identifier1:"string1"\n \n\n' + 'identifier2 : \n \n123 \n identifier3 :\'string\'\n' + 'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n' + 'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n' + 'ID9: 22 ID10: -111111111111111111 ID11: -22\n' + 'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f ' + 'false_bool: 0 true_BOOL:t \n true_bool1: 1 false_BOOL1:f ' + 'False_bool: False True_bool: True X:iNf Y:-inF Z:nAN') + tokenizer = text_format.Tokenizer(text.splitlines()) + methods = [(tokenizer.ConsumeIdentifier, 'identifier1'), ':', + (tokenizer.ConsumeString, 'string1'), + (tokenizer.ConsumeIdentifier, 'identifier2'), ':', + (tokenizer.ConsumeInteger, 123), + (tokenizer.ConsumeIdentifier, 'identifier3'), ':', + (tokenizer.ConsumeString, 'string'), + (tokenizer.ConsumeIdentifier, 'identifiER_4'), ':', + (tokenizer.ConsumeFloat, 1.1e+2), + (tokenizer.ConsumeIdentifier, 'ID5'), ':', + (tokenizer.ConsumeFloat, -0.23), + (tokenizer.ConsumeIdentifier, 'ID6'), ':', + (tokenizer.ConsumeString, 'aaaa\'bbbb'), + (tokenizer.ConsumeIdentifier, 'ID7'), ':', + (tokenizer.ConsumeString, 'aa\"bb'), + (tokenizer.ConsumeIdentifier, 'ID8'), ':', '{', + (tokenizer.ConsumeIdentifier, 'A'), ':', + (tokenizer.ConsumeFloat, float('inf')), + (tokenizer.ConsumeIdentifier, 'B'), ':', + (tokenizer.ConsumeFloat, -float('inf')), + (tokenizer.ConsumeIdentifier, 'C'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'D'), ':', + (tokenizer.ConsumeBool, False), '}', + (tokenizer.ConsumeIdentifier, 'ID9'), ':', + (tokenizer.ConsumeInteger, 22), + (tokenizer.ConsumeIdentifier, 'ID10'), ':', + (tokenizer.ConsumeInteger, -111111111111111111), + (tokenizer.ConsumeIdentifier, 'ID11'), ':', + (tokenizer.ConsumeInteger, -22), + (tokenizer.ConsumeIdentifier, 'ID12'), ':', + (tokenizer.ConsumeInteger, 2222222222222222222), + (tokenizer.ConsumeIdentifier, 'ID13'), ':', + (tokenizer.ConsumeFloat, 1.23456), + (tokenizer.ConsumeIdentifier, 'ID14'), ':', + (tokenizer.ConsumeFloat, 1.2e+2), + (tokenizer.ConsumeIdentifier, 'false_bool'), ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'true_BOOL'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'true_bool1'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'false_BOOL1'), ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'False_bool'), ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'True_bool'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'X'), ':', + (tokenizer.ConsumeFloat, float('inf')), + (tokenizer.ConsumeIdentifier, 'Y'), ':', + (tokenizer.ConsumeFloat, float('-inf')), + (tokenizer.ConsumeIdentifier, 'Z'), ':', + (tokenizer.ConsumeFloat, float('nan'))] + + i = 0 + while not tokenizer.AtEnd(): + m = methods[i] + if isinstance(m, str): + token = tokenizer.token + self.assertEqual(token, m) + tokenizer.NextToken() + elif isinstance(m[1], float) and math.isnan(m[1]): + self.assertTrue(math.isnan(m[0]())) + else: + self.assertEqual(m[1], m[0]()) + i += 1 + + def testConsumeAbstractIntegers(self): + # This test only tests the failures in the integer parsing methods as well + # as the '0' special cases. + int64_max = (1 << 63) - 1 + uint32_max = (1 << 32) - 1 + text = '-1 %d %d' % (uint32_max + 1, int64_max + 1) + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(-1, tokenizer.ConsumeInteger()) + + self.assertEqual(uint32_max + 1, tokenizer.ConsumeInteger()) + + self.assertEqual(int64_max + 1, tokenizer.ConsumeInteger()) + self.assertTrue(tokenizer.AtEnd()) + + text = '-0 0 0 1.2' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(True, tokenizer.TryConsumeInteger()) + self.assertEqual(False, tokenizer.TryConsumeInteger()) + with self.assertRaises(text_format.ParseError): + tokenizer.ConsumeInteger() + self.assertEqual(1.2, tokenizer.ConsumeFloat()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeIntegers(self): + # This test only tests the failures in the integer parsing methods as well + # as the '0' special cases. + int64_max = (1 << 63) - 1 + uint32_max = (1 << 32) - 1 + text = '-1 %d %d' % (uint32_max + 1, int64_max + 1) + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, + text_format._ConsumeUint32, tokenizer) + self.assertRaises(text_format.ParseError, + text_format._ConsumeUint64, tokenizer) + self.assertEqual(-1, text_format._ConsumeInt32(tokenizer)) + + self.assertRaises(text_format.ParseError, + text_format._ConsumeUint32, tokenizer) + self.assertRaises(text_format.ParseError, + text_format._ConsumeInt32, tokenizer) + self.assertEqual(uint32_max + 1, text_format._ConsumeInt64(tokenizer)) + + self.assertRaises(text_format.ParseError, + text_format._ConsumeInt64, tokenizer) + self.assertEqual(int64_max + 1, text_format._ConsumeUint64(tokenizer)) + self.assertTrue(tokenizer.AtEnd()) + + text = '-0 -0 0 0' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(0, text_format._ConsumeUint32(tokenizer)) + self.assertEqual(0, text_format._ConsumeUint64(tokenizer)) + self.assertEqual(0, text_format._ConsumeUint32(tokenizer)) + self.assertEqual(0, text_format._ConsumeUint64(tokenizer)) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeByteString(self): + text = '"string1\'' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = 'string1"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\xt"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\x"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + def testConsumeBool(self): + text = 'not-a-bool' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool) + + def testSkipComment(self): + tokenizer = text_format.Tokenizer('# some comment'.splitlines()) + self.assertTrue(tokenizer.AtEnd()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeComment) + + def testConsumeComment(self): + tokenizer = text_format.Tokenizer('# some comment'.splitlines(), + skip_comments=False) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual('# some comment', tokenizer.ConsumeComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeTwoComments(self): + text = '# some comment\n# another comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertEqual('# some comment', tokenizer.ConsumeComment()) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual('# another comment', tokenizer.ConsumeComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeTrailingComment(self): + text = 'some_number: 4\n# some comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeComment) + + self.assertEqual('some_number', tokenizer.ConsumeIdentifier()) + self.assertEqual(tokenizer.token, ':') + tokenizer.NextToken() + self.assertRaises(text_format.ParseError, tokenizer.ConsumeComment) + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertFalse(tokenizer.AtEnd()) + + self.assertEqual('# some comment', tokenizer.ConsumeComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeLineComment(self): + tokenizer = text_format.Tokenizer('# some comment'.splitlines(), + skip_comments=False) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual((False, '# some comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeTwoLineComments(self): + text = '# some comment\n# another comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertEqual((False, '# some comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual((False, '# another comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeAndCheckTrailingComment(self): + text = 'some_number: 4 # some comment' # trailing comment on the same line + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertRaises(text_format.ParseError, + tokenizer.ConsumeCommentOrTrailingComment) + + self.assertEqual('some_number', tokenizer.ConsumeIdentifier()) + self.assertEqual(tokenizer.token, ':') + tokenizer.NextToken() + self.assertRaises(text_format.ParseError, + tokenizer.ConsumeCommentOrTrailingComment) + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertFalse(tokenizer.AtEnd()) + + self.assertEqual((True, '# some comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testHashinComment(self): + text = 'some_number: 4 # some comment # not a new comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertEqual('some_number', tokenizer.ConsumeIdentifier()) + self.assertEqual(tokenizer.token, ':') + tokenizer.NextToken() + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertEqual((True, '# some comment # not a new comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + +# Tests for pretty printer functionality. +@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) +class PrettyPrinterTest(TextFormatBase): + + def testPrettyPrintNoMatch(self, message_module): + + def printer(message, indent, as_one_line): + del message, indent, as_one_line + return None + + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'repeated_nested_message { bb: 42 }') + + def testPrettyPrintOneLine(self, message_module): + + def printer(m, indent, as_one_line): + del indent, as_one_line + if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR: + return 'My lucky number is %s' % m.bb + + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'repeated_nested_message { My lucky number is 42 }') + + def testPrettyPrintMultiLine(self, message_module): + + def printer(m, indent, as_one_line): + if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR: + line_deliminator = (' ' if as_one_line else '\n') + ' ' * indent + return 'My lucky number is:%s%s' % (line_deliminator, m.bb) + return None + + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'repeated_nested_message { My lucky number is: 42 }') + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=False, message_formatter=printer), + 'repeated_nested_message {\n My lucky number is:\n 42\n}\n') + + def testPrettyPrintEntireMessage(self, message_module): + + def printer(m, indent, as_one_line): + del indent, as_one_line + if m.DESCRIPTOR == message_module.TestAllTypes.DESCRIPTOR: + return 'The is the message!' + return None + + message = message_module.TestAllTypes() + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=False, message_formatter=printer), + 'The is the message!\n') + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'The is the message!') + + def testPrettyPrintMultipleParts(self, message_module): + + def printer(m, indent, as_one_line): + del indent, as_one_line + if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR: + return 'My lucky number is %s' % m.bb + return None + + message = message_module.TestAllTypes() + message.optional_int32 = 61 + msg = message.repeated_nested_message.add() + msg.bb = 42 + msg = message.repeated_nested_message.add() + msg.bb = 99 + msg = message.optional_nested_message + msg.bb = 1 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + ('optional_int32: 61 ' + 'optional_nested_message { My lucky number is 1 } ' + 'repeated_nested_message { My lucky number is 42 } ' + 'repeated_nested_message { My lucky number is 99 }')) + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/type_checkers.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/type_checkers.py new file mode 100644 index 0000000..f3f6d69 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/type_checkers.py @@ -0,0 +1,353 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides type checking routines. + +This module defines type checking utilities in the forms of dictionaries: + +VALUE_CHECKERS: A dictionary of field types and a value validation object. +TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing + function. +TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization + function. +FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their + coresponding wire types. +TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization + function. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import numbers +import six + +if six.PY3: + long = int + +from google.protobuf.internal import api_implementation +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.internal import wire_format +from google.protobuf import descriptor + +_FieldDescriptor = descriptor.FieldDescriptor + +def SupportsOpenEnums(field_descriptor): + return field_descriptor.containing_type.syntax == "proto3" + +def GetTypeChecker(field): + """Returns a type checker for a message field of the specified types. + + Args: + field: FieldDescriptor object for this field. + + Returns: + An instance of TypeChecker which can be used to verify the types + of values assigned to a field of the specified type. + """ + if (field.cpp_type == _FieldDescriptor.CPPTYPE_STRING and + field.type == _FieldDescriptor.TYPE_STRING): + return UnicodeValueChecker() + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + if SupportsOpenEnums(field): + # When open enums are supported, any int32 can be assigned. + return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32] + else: + return EnumValueChecker(field.enum_type) + return _VALUE_CHECKERS[field.cpp_type] + + +# None of the typecheckers below make any attempt to guard against people +# subclassing builtin types and doing weird things. We're not trying to +# protect against malicious clients here, just people accidentally shooting +# themselves in the foot in obvious ways. + +class TypeChecker(object): + + """Type checker used to catch type errors as early as possible + when the client is setting scalar fields in protocol messages. + """ + + def __init__(self, *acceptable_types): + self._acceptable_types = acceptable_types + + def CheckValue(self, proposed_value): + """Type check the provided value and return it. + + The returned value might have been normalized to another type. + """ + if not isinstance(proposed_value, self._acceptable_types): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), self._acceptable_types)) + raise TypeError(message) + return proposed_value + + +class TypeCheckerWithDefault(TypeChecker): + + def __init__(self, default_value, *acceptable_types): + TypeChecker.__init__(self, acceptable_types) + self._default_value = default_value + + def DefaultValue(self): + return self._default_value + + +# IntValueChecker and its subclasses perform integer type-checks +# and bounds-checks. +class IntValueChecker(object): + + """Checker used for integer fields. Performs type-check and range check.""" + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, numbers.Integral): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), six.integer_types)) + raise TypeError(message) + if not self._MIN <= int(proposed_value) <= self._MAX: + raise ValueError('Value out of range: %d' % proposed_value) + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + proposed_value = self._TYPE(proposed_value) + return proposed_value + + def DefaultValue(self): + return 0 + + +class EnumValueChecker(object): + + """Checker used for enum fields. Performs type-check and range check.""" + + def __init__(self, enum_type): + self._enum_type = enum_type + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, numbers.Integral): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), six.integer_types)) + raise TypeError(message) + if int(proposed_value) not in self._enum_type.values_by_number: + raise ValueError('Unknown enum value: %d' % proposed_value) + return proposed_value + + def DefaultValue(self): + return self._enum_type.values[0].number + + +class UnicodeValueChecker(object): + + """Checker used for string fields. + + Always returns a unicode value, even if the input is of type str. + """ + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, (bytes, six.text_type)): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), (bytes, six.text_type))) + raise TypeError(message) + + # If the value is of type 'bytes' make sure that it is valid UTF-8 data. + if isinstance(proposed_value, bytes): + try: + proposed_value = proposed_value.decode('utf-8') + except UnicodeDecodeError: + raise ValueError('%.1024r has type bytes, but isn\'t valid UTF-8 ' + 'encoding. Non-UTF-8 strings must be converted to ' + 'unicode objects before being added.' % + (proposed_value)) + return proposed_value + + def DefaultValue(self): + return "" + + +class Int32ValueChecker(IntValueChecker): + # We're sure to use ints instead of longs here since comparison may be more + # efficient. + _MIN = -2147483648 + _MAX = 2147483647 + _TYPE = int + + +class Uint32ValueChecker(IntValueChecker): + _MIN = 0 + _MAX = (1 << 32) - 1 + _TYPE = int + + +class Int64ValueChecker(IntValueChecker): + _MIN = -(1 << 63) + _MAX = (1 << 63) - 1 + _TYPE = int + + +class Uint64ValueChecker(IntValueChecker): + _MIN = 0 + _MAX = (1 << 64) - 1 + _TYPE = int + + +# Type-checkers for all scalar CPPTYPEs. +_VALUE_CHECKERS = { + _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), + _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), + _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), + _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), + _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault( + 0.0, numbers.Real), + _FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault( + 0.0, numbers.Real), + _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault( + False, bool, numbers.Integral), + _FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes), + } + + +# Map from field type to a function F, such that F(field_num, value) +# gives the total byte size for a value of the given type. This +# byte size includes tag information and any other additional space +# associated with serializing "value". +TYPE_TO_BYTE_SIZE_FN = { + _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize, + _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize, + _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize, + _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize, + _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize, + _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize, + _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize, + _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize, + _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize, + _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize, + _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize, + _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize, + _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize, + _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize, + _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize, + _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize, + _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize, + _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize + } + + +# Maps from field types to encoder constructors. +TYPE_TO_ENCODER = { + _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder, + _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder, + _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder, + _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder, + _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder, + _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder, + _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder, + _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder, + _FieldDescriptor.TYPE_STRING: encoder.StringEncoder, + _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder, + _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder, + _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder, + _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder, + _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder, + _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder, + _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder, + _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder, + _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder, + } + + +# Maps from field types to sizer constructors. +TYPE_TO_SIZER = { + _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer, + _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer, + _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer, + _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer, + _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer, + _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer, + _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer, + _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer, + _FieldDescriptor.TYPE_STRING: encoder.StringSizer, + _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer, + _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer, + _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer, + _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer, + _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer, + _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer, + _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer, + _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer, + _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer, + } + + +# Maps from field type to a decoder constructor. +TYPE_TO_DECODER = { + _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder, + _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder, + _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder, + _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder, + _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder, + _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder, + _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder, + _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder, + _FieldDescriptor.TYPE_STRING: decoder.StringDecoder, + _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder, + _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder, + _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder, + _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder, + _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder, + _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder, + _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder, + _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder, + _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder, + } + +# Maps from field type to expected wiretype. +FIELD_TYPE_TO_WIRE_TYPE = { + _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_STRING: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP, + _FieldDescriptor.TYPE_MESSAGE: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_BYTES: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT, + } diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/unknown_fields_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/unknown_fields_test.py new file mode 100644 index 0000000..8b7de2e --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/unknown_fields_test.py @@ -0,0 +1,336 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for preservation of unknown fields in the pure Python implementation.""" + +__author__ = 'bohdank@google.com (Bohdan Koval)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import encoder +from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import missing_enum_values_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks +from google.protobuf.internal import type_checkers + + +BaseTestCase = testing_refleaks.BaseTestCase + + +# CheckUnknownField() cannot be used by the C++ implementation because +# some protect members are called. It is not a behavior difference +# for python and C++ implementation. +def SkipCheckUnknownFieldIfCppImplementation(func): + return unittest.skipIf( + api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, + 'Addtional test for pure python involved protect members')(func) + + +class UnknownFieldsTest(BaseTestCase): + + def setUp(self): + self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.all_fields = unittest_pb2.TestAllTypes() + test_util.SetAllFields(self.all_fields) + self.all_fields_data = self.all_fields.SerializeToString() + self.empty_message = unittest_pb2.TestEmptyMessage() + self.empty_message.ParseFromString(self.all_fields_data) + + def testSerialize(self): + data = self.empty_message.SerializeToString() + + # Don't use assertEqual because we don't want to dump raw binary data to + # stdout. + self.assertTrue(data == self.all_fields_data) + + def expectSerializeProto3(self, preserve): + message = unittest_proto3_arena_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + if preserve: + self.assertEqual(self.all_fields_data, message.SerializeToString()) + else: + self.assertEqual(0, len(message.SerializeToString())) + + def testSerializeProto3(self): + # Verify that proto3 unknown fields behavior. + default_preserve = (api_implementation + .GetPythonProto3PreserveUnknownsDefault()) + self.expectSerializeProto3(default_preserve) + api_implementation.SetPythonProto3PreserveUnknownsDefault( + not default_preserve) + self.expectSerializeProto3(not default_preserve) + api_implementation.SetPythonProto3PreserveUnknownsDefault(default_preserve) + + def testByteSize(self): + self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize()) + + def testListFields(self): + # Make sure ListFields doesn't return unknown fields. + self.assertEqual(0, len(self.empty_message.ListFields())) + + def testSerializeMessageSetWireFormatUnknownExtension(self): + # Create a message using the message set wire format with an unknown + # message. + raw = unittest_mset_pb2.RawMessageSet() + + # Add an unknown extension. + item = raw.item.add() + item.type_id = 98418603 + message1 = message_set_extensions_pb2.TestMessageSetExtension1() + message1.i = 12345 + item.message = message1.SerializeToString() + + serialized = raw.SerializeToString() + + # Parse message using the message set wire format. + proto = message_set_extensions_pb2.TestMessageSet() + proto.MergeFromString(serialized) + + # Verify that the unknown extension is serialized unchanged + reserialized = proto.SerializeToString() + new_raw = unittest_mset_pb2.RawMessageSet() + new_raw.MergeFromString(reserialized) + self.assertEqual(raw, new_raw) + + def testEquals(self): + message = unittest_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + self.assertEqual(self.empty_message, message) + + self.all_fields.ClearField('optional_string') + message.ParseFromString(self.all_fields.SerializeToString()) + self.assertNotEqual(self.empty_message, message) + + def testDiscardUnknownFields(self): + self.empty_message.DiscardUnknownFields() + self.assertEqual(b'', self.empty_message.SerializeToString()) + # Test message field and repeated message field. + message = unittest_pb2.TestAllTypes() + other_message = unittest_pb2.TestAllTypes() + other_message.optional_string = 'discard' + message.optional_nested_message.ParseFromString( + other_message.SerializeToString()) + message.repeated_nested_message.add().ParseFromString( + other_message.SerializeToString()) + self.assertNotEqual( + b'', message.optional_nested_message.SerializeToString()) + self.assertNotEqual( + b'', message.repeated_nested_message[0].SerializeToString()) + message.DiscardUnknownFields() + self.assertEqual(b'', message.optional_nested_message.SerializeToString()) + self.assertEqual( + b'', message.repeated_nested_message[0].SerializeToString()) + + +class UnknownFieldsAccessorsTest(BaseTestCase): + + def setUp(self): + self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.all_fields = unittest_pb2.TestAllTypes() + test_util.SetAllFields(self.all_fields) + self.all_fields_data = self.all_fields.SerializeToString() + self.empty_message = unittest_pb2.TestEmptyMessage() + self.empty_message.ParseFromString(self.all_fields_data) + + # CheckUnknownField() is an additional Pure Python check which checks + # a detail of unknown fields. It cannot be used by the C++ + # implementation because some protect members are called. + # The test is added for historical reasons. It is not necessary as + # serialized string is checked. + + def CheckUnknownField(self, name, expected_value): + field_descriptor = self.descriptor.fields_by_name[name] + wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] + field_tag = encoder.TagBytes(field_descriptor.number, wire_type) + result_dict = {} + for tag_bytes, value in self.empty_message._unknown_fields: + if tag_bytes == field_tag: + decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes][0] + decoder(value, 0, len(value), self.all_fields, result_dict) + self.assertEqual(expected_value, result_dict[field_descriptor]) + + @SkipCheckUnknownFieldIfCppImplementation + def testCheckUnknownFieldValue(self): + # Test enum. + self.CheckUnknownField('optional_nested_enum', + self.all_fields.optional_nested_enum) + # Test repeated enum. + self.CheckUnknownField('repeated_nested_enum', + self.all_fields.repeated_nested_enum) + + # Test varint. + self.CheckUnknownField('optional_int32', + self.all_fields.optional_int32) + # Test fixed32. + self.CheckUnknownField('optional_fixed32', + self.all_fields.optional_fixed32) + + # Test fixed64. + self.CheckUnknownField('optional_fixed64', + self.all_fields.optional_fixed64) + + # Test lengthd elimited. + self.CheckUnknownField('optional_string', + self.all_fields.optional_string) + + # Test group. + self.CheckUnknownField('optionalgroup', + self.all_fields.optionalgroup) + + def testCopyFrom(self): + message = unittest_pb2.TestEmptyMessage() + message.CopyFrom(self.empty_message) + self.assertEqual(message.SerializeToString(), self.all_fields_data) + + def testMergeFrom(self): + message = unittest_pb2.TestAllTypes() + message.optional_int32 = 1 + message.optional_uint32 = 2 + source = unittest_pb2.TestEmptyMessage() + source.ParseFromString(message.SerializeToString()) + + message.ClearField('optional_int32') + message.optional_int64 = 3 + message.optional_uint32 = 4 + destination = unittest_pb2.TestEmptyMessage() + destination.ParseFromString(message.SerializeToString()) + + destination.MergeFrom(source) + # Check that the fields where correctly merged, even stored in the unknown + # fields set. + message.ParseFromString(destination.SerializeToString()) + self.assertEqual(message.optional_int32, 1) + self.assertEqual(message.optional_uint32, 2) + self.assertEqual(message.optional_int64, 3) + + def testClear(self): + self.empty_message.Clear() + # All cleared, even unknown fields. + self.assertEqual(self.empty_message.SerializeToString(), b'') + + def testUnknownExtensions(self): + message = unittest_pb2.TestEmptyMessageWithExtensions() + message.ParseFromString(self.all_fields_data) + self.assertEqual(message.SerializeToString(), self.all_fields_data) + + +class UnknownEnumValuesTest(BaseTestCase): + + def setUp(self): + self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR + + self.message = missing_enum_values_pb2.TestEnumValues() + # TestEnumValues.ZERO = 0, but does not exist in the other NestedEnum. + self.message.optional_nested_enum = ( + missing_enum_values_pb2.TestEnumValues.ZERO) + self.message.repeated_nested_enum.extend([ + missing_enum_values_pb2.TestEnumValues.ZERO, + missing_enum_values_pb2.TestEnumValues.ONE, + ]) + self.message.packed_nested_enum.extend([ + missing_enum_values_pb2.TestEnumValues.ZERO, + missing_enum_values_pb2.TestEnumValues.ONE, + ]) + self.message_data = self.message.SerializeToString() + self.missing_message = missing_enum_values_pb2.TestMissingEnumValues() + self.missing_message.ParseFromString(self.message_data) + + # CheckUnknownField() is an additional Pure Python check which checks + # a detail of unknown fields. It cannot be used by the C++ + # implementation because some protect members are called. + # The test is added for historical reasons. It is not necessary as + # serialized string is checked. + + def CheckUnknownField(self, name, expected_value): + field_descriptor = self.descriptor.fields_by_name[name] + wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] + field_tag = encoder.TagBytes(field_descriptor.number, wire_type) + result_dict = {} + for tag_bytes, value in self.missing_message._unknown_fields: + if tag_bytes == field_tag: + decoder = missing_enum_values_pb2.TestEnumValues._decoders_by_tag[ + tag_bytes][0] + decoder(value, 0, len(value), self.message, result_dict) + self.assertEqual(expected_value, result_dict[field_descriptor]) + + def testUnknownParseMismatchEnumValue(self): + just_string = missing_enum_values_pb2.JustString() + just_string.dummy = 'blah' + + missing = missing_enum_values_pb2.TestEnumValues() + # The parse is invalid, storing the string proto into the set of + # unknown fields. + missing.ParseFromString(just_string.SerializeToString()) + + # Fetching the enum field shouldn't crash, instead returning the + # default value. + self.assertEqual(missing.optional_nested_enum, 0) + + def testUnknownEnumValue(self): + self.assertFalse(self.missing_message.HasField('optional_nested_enum')) + self.assertEqual(self.missing_message.optional_nested_enum, 2) + # Clear does not do anything. + serialized = self.missing_message.SerializeToString() + self.missing_message.ClearField('optional_nested_enum') + self.assertEqual(self.missing_message.SerializeToString(), serialized) + + def testUnknownRepeatedEnumValue(self): + self.assertEqual([], self.missing_message.repeated_nested_enum) + + def testUnknownPackedEnumValue(self): + self.assertEqual([], self.missing_message.packed_nested_enum) + + @SkipCheckUnknownFieldIfCppImplementation + def testCheckUnknownFieldValueForEnum(self): + self.CheckUnknownField('optional_nested_enum', + self.message.optional_nested_enum) + self.CheckUnknownField('repeated_nested_enum', + self.message.repeated_nested_enum) + self.CheckUnknownField('packed_nested_enum', + self.message.packed_nested_enum) + + def testRoundTrip(self): + new_message = missing_enum_values_pb2.TestEnumValues() + new_message.ParseFromString(self.missing_message.SerializeToString()) + self.assertEqual(self.message, new_message) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types.py new file mode 100644 index 0000000..78e1540 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types.py @@ -0,0 +1,839 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains well known classes. + +This files defines well known classes which need extra maintenance including: + - Any + - Duration + - FieldMask + - Struct + - Timestamp +""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import collections +from datetime import datetime +from datetime import timedelta +import six + +from google.protobuf.descriptor import FieldDescriptor + +_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' +_NANOS_PER_SECOND = 1000000000 +_NANOS_PER_MILLISECOND = 1000000 +_NANOS_PER_MICROSECOND = 1000 +_MILLIS_PER_SECOND = 1000 +_MICROS_PER_SECOND = 1000000 +_SECONDS_PER_DAY = 24 * 3600 +_DURATION_SECONDS_MAX = 315576000000 + + +class Error(Exception): + """Top-level module error.""" + + +class ParseError(Error): + """Thrown in case of parsing error.""" + + +class Any(object): + """Class for Any Message type.""" + + def Pack(self, msg, type_url_prefix='type.googleapis.com/', + deterministic=None): + """Packs the specified message into current Any message.""" + if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/': + self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) + else: + self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) + self.value = msg.SerializeToString(deterministic=deterministic) + + def Unpack(self, msg): + """Unpacks the current Any message into specified message.""" + descriptor = msg.DESCRIPTOR + if not self.Is(descriptor): + return False + msg.ParseFromString(self.value) + return True + + def TypeName(self): + """Returns the protobuf type name of the inner message.""" + # Only last part is to be used: b/25630112 + return self.type_url.split('/')[-1] + + def Is(self, descriptor): + """Checks if this Any represents the given protobuf type.""" + return self.TypeName() == descriptor.full_name + + +class Timestamp(object): + """Class for Timestamp message type.""" + + def ToJsonString(self): + """Converts Timestamp to RFC 3339 date string format. + + Returns: + A string converted from timestamp. The string is always Z-normalized + and uses 3, 6 or 9 fractional digits as required to represent the + exact time. Example of the return format: '1972-01-01T10:00:20.021Z' + """ + nanos = self.nanos % _NANOS_PER_SECOND + total_sec = self.seconds + (self.nanos - nanos) // _NANOS_PER_SECOND + seconds = total_sec % _SECONDS_PER_DAY + days = (total_sec - seconds) // _SECONDS_PER_DAY + dt = datetime(1970, 1, 1) + timedelta(days, seconds) + + result = dt.isoformat() + if (nanos % 1e9) == 0: + # If there are 0 fractional digits, the fractional + # point '.' should be omitted when serializing. + return result + 'Z' + if (nanos % 1e6) == 0: + # Serialize 3 fractional digits. + return result + '.%03dZ' % (nanos / 1e6) + if (nanos % 1e3) == 0: + # Serialize 6 fractional digits. + return result + '.%06dZ' % (nanos / 1e3) + # Serialize 9 fractional digits. + return result + '.%09dZ' % nanos + + def FromJsonString(self, value): + """Parse a RFC 3339 date string format to Timestamp. + + Args: + value: A date string. Any fractional digits (or none) and any offset are + accepted as long as they fit into nano-seconds precision. + Example of accepted format: '1972-01-01T10:00:20.021-05:00' + + Raises: + ParseError: On parsing problems. + """ + timezone_offset = value.find('Z') + if timezone_offset == -1: + timezone_offset = value.find('+') + if timezone_offset == -1: + timezone_offset = value.rfind('-') + if timezone_offset == -1: + raise ParseError( + 'Failed to parse timestamp: missing valid timezone offset.') + time_value = value[0:timezone_offset] + # Parse datetime and nanos. + point_position = time_value.find('.') + if point_position == -1: + second_value = time_value + nano_value = '' + else: + second_value = time_value[:point_position] + nano_value = time_value[point_position + 1:] + date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT) + td = date_object - datetime(1970, 1, 1) + seconds = td.seconds + td.days * _SECONDS_PER_DAY + if len(nano_value) > 9: + raise ParseError( + 'Failed to parse Timestamp: nanos {0} more than ' + '9 fractional digits.'.format(nano_value)) + if nano_value: + nanos = round(float('0.' + nano_value) * 1e9) + else: + nanos = 0 + # Parse timezone offsets. + if value[timezone_offset] == 'Z': + if len(value) != timezone_offset + 1: + raise ParseError('Failed to parse timestamp: invalid trailing' + ' data {0}.'.format(value)) + else: + timezone = value[timezone_offset:] + pos = timezone.find(':') + if pos == -1: + raise ParseError( + 'Invalid timezone offset value: {0}.'.format(timezone)) + if timezone[0] == '+': + seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 + else: + seconds += (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 + # Set seconds and nanos + self.seconds = int(seconds) + self.nanos = int(nanos) + + def GetCurrentTime(self): + """Get the current UTC into Timestamp.""" + self.FromDatetime(datetime.utcnow()) + + def ToNanoseconds(self): + """Converts Timestamp to nanoseconds since epoch.""" + return self.seconds * _NANOS_PER_SECOND + self.nanos + + def ToMicroseconds(self): + """Converts Timestamp to microseconds since epoch.""" + return (self.seconds * _MICROS_PER_SECOND + + self.nanos // _NANOS_PER_MICROSECOND) + + def ToMilliseconds(self): + """Converts Timestamp to milliseconds since epoch.""" + return (self.seconds * _MILLIS_PER_SECOND + + self.nanos // _NANOS_PER_MILLISECOND) + + def ToSeconds(self): + """Converts Timestamp to seconds since epoch.""" + return self.seconds + + def FromNanoseconds(self, nanos): + """Converts nanoseconds since epoch to Timestamp.""" + self.seconds = nanos // _NANOS_PER_SECOND + self.nanos = nanos % _NANOS_PER_SECOND + + def FromMicroseconds(self, micros): + """Converts microseconds since epoch to Timestamp.""" + self.seconds = micros // _MICROS_PER_SECOND + self.nanos = (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND + + def FromMilliseconds(self, millis): + """Converts milliseconds since epoch to Timestamp.""" + self.seconds = millis // _MILLIS_PER_SECOND + self.nanos = (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND + + def FromSeconds(self, seconds): + """Converts seconds since epoch to Timestamp.""" + self.seconds = seconds + self.nanos = 0 + + def ToDatetime(self): + """Converts Timestamp to datetime.""" + return datetime.utcfromtimestamp( + self.seconds + self.nanos / float(_NANOS_PER_SECOND)) + + def FromDatetime(self, dt): + """Converts datetime to Timestamp.""" + td = dt - datetime(1970, 1, 1) + self.seconds = td.seconds + td.days * _SECONDS_PER_DAY + self.nanos = td.microseconds * _NANOS_PER_MICROSECOND + + +class Duration(object): + """Class for Duration message type.""" + + def ToJsonString(self): + """Converts Duration to string format. + + Returns: + A string converted from self. The string format will contains + 3, 6, or 9 fractional digits depending on the precision required to + represent the exact Duration value. For example: "1s", "1.010s", + "1.000000100s", "-3.100s" + """ + _CheckDurationValid(self.seconds, self.nanos) + if self.seconds < 0 or self.nanos < 0: + result = '-' + seconds = - self.seconds + int((0 - self.nanos) // 1e9) + nanos = (0 - self.nanos) % 1e9 + else: + result = '' + seconds = self.seconds + int(self.nanos // 1e9) + nanos = self.nanos % 1e9 + result += '%d' % seconds + if (nanos % 1e9) == 0: + # If there are 0 fractional digits, the fractional + # point '.' should be omitted when serializing. + return result + 's' + if (nanos % 1e6) == 0: + # Serialize 3 fractional digits. + return result + '.%03ds' % (nanos / 1e6) + if (nanos % 1e3) == 0: + # Serialize 6 fractional digits. + return result + '.%06ds' % (nanos / 1e3) + # Serialize 9 fractional digits. + return result + '.%09ds' % nanos + + def FromJsonString(self, value): + """Converts a string to Duration. + + Args: + value: A string to be converted. The string must end with 's'. Any + fractional digits (or none) are accepted as long as they fit into + precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s + + Raises: + ParseError: On parsing problems. + """ + if len(value) < 1 or value[-1] != 's': + raise ParseError( + 'Duration must end with letter "s": {0}.'.format(value)) + try: + pos = value.find('.') + if pos == -1: + seconds = int(value[:-1]) + nanos = 0 + else: + seconds = int(value[:pos]) + if value[0] == '-': + nanos = int(round(float('-0{0}'.format(value[pos: -1])) *1e9)) + else: + nanos = int(round(float('0{0}'.format(value[pos: -1])) *1e9)) + _CheckDurationValid(seconds, nanos) + self.seconds = seconds + self.nanos = nanos + except ValueError: + raise ParseError( + 'Couldn\'t parse duration: {0}.'.format(value)) + + def ToNanoseconds(self): + """Converts a Duration to nanoseconds.""" + return self.seconds * _NANOS_PER_SECOND + self.nanos + + def ToMicroseconds(self): + """Converts a Duration to microseconds.""" + micros = _RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND) + return self.seconds * _MICROS_PER_SECOND + micros + + def ToMilliseconds(self): + """Converts a Duration to milliseconds.""" + millis = _RoundTowardZero(self.nanos, _NANOS_PER_MILLISECOND) + return self.seconds * _MILLIS_PER_SECOND + millis + + def ToSeconds(self): + """Converts a Duration to seconds.""" + return self.seconds + + def FromNanoseconds(self, nanos): + """Converts nanoseconds to Duration.""" + self._NormalizeDuration(nanos // _NANOS_PER_SECOND, + nanos % _NANOS_PER_SECOND) + + def FromMicroseconds(self, micros): + """Converts microseconds to Duration.""" + self._NormalizeDuration( + micros // _MICROS_PER_SECOND, + (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND) + + def FromMilliseconds(self, millis): + """Converts milliseconds to Duration.""" + self._NormalizeDuration( + millis // _MILLIS_PER_SECOND, + (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND) + + def FromSeconds(self, seconds): + """Converts seconds to Duration.""" + self.seconds = seconds + self.nanos = 0 + + def ToTimedelta(self): + """Converts Duration to timedelta.""" + return timedelta( + seconds=self.seconds, microseconds=_RoundTowardZero( + self.nanos, _NANOS_PER_MICROSECOND)) + + def FromTimedelta(self, td): + """Converts timedelta to Duration.""" + self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY, + td.microseconds * _NANOS_PER_MICROSECOND) + + def _NormalizeDuration(self, seconds, nanos): + """Set Duration by seconds and nanos.""" + # Force nanos to be negative if the duration is negative. + if seconds < 0 and nanos > 0: + seconds += 1 + nanos -= _NANOS_PER_SECOND + self.seconds = seconds + self.nanos = nanos + + +def _CheckDurationValid(seconds, nanos): + if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX: + raise Error( + 'Duration is not valid: Seconds {0} must be in range ' + '[-315576000000, 315576000000].'.format(seconds)) + if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND: + raise Error( + 'Duration is not valid: Nanos {0} must be in range ' + '[-999999999, 999999999].'.format(nanos)) + if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0): + raise Error( + 'Duration is not valid: Sign mismatch.') + + +def _RoundTowardZero(value, divider): + """Truncates the remainder part after division.""" + # For some languanges, the sign of the remainder is implementation + # dependent if any of the operands is negative. Here we enforce + # "rounded toward zero" semantics. For example, for (-5) / 2 an + # implementation may give -3 as the result with the remainder being + # 1. This function ensures we always return -2 (closer to zero). + result = value // divider + remainder = value % divider + if result < 0 and remainder > 0: + return result + 1 + else: + return result + + +class FieldMask(object): + """Class for FieldMask message type.""" + + def ToJsonString(self): + """Converts FieldMask to string according to proto3 JSON spec.""" + camelcase_paths = [] + for path in self.paths: + camelcase_paths.append(_SnakeCaseToCamelCase(path)) + return ','.join(camelcase_paths) + + def FromJsonString(self, value): + """Converts string to FieldMask according to proto3 JSON spec.""" + self.Clear() + for path in value.split(','): + self.paths.append(_CamelCaseToSnakeCase(path)) + + def IsValidForDescriptor(self, message_descriptor): + """Checks whether the FieldMask is valid for Message Descriptor.""" + for path in self.paths: + if not _IsValidPath(message_descriptor, path): + return False + return True + + def AllFieldsFromDescriptor(self, message_descriptor): + """Gets all direct fields of Message Descriptor to FieldMask.""" + self.Clear() + for field in message_descriptor.fields: + self.paths.append(field.name) + + def CanonicalFormFromMask(self, mask): + """Converts a FieldMask to the canonical form. + + Removes paths that are covered by another path. For example, + "foo.bar" is covered by "foo" and will be removed if "foo" + is also in the FieldMask. Then sorts all paths in alphabetical order. + + Args: + mask: The original FieldMask to be converted. + """ + tree = _FieldMaskTree(mask) + tree.ToFieldMask(self) + + def Union(self, mask1, mask2): + """Merges mask1 and mask2 into this FieldMask.""" + _CheckFieldMaskMessage(mask1) + _CheckFieldMaskMessage(mask2) + tree = _FieldMaskTree(mask1) + tree.MergeFromFieldMask(mask2) + tree.ToFieldMask(self) + + def Intersect(self, mask1, mask2): + """Intersects mask1 and mask2 into this FieldMask.""" + _CheckFieldMaskMessage(mask1) + _CheckFieldMaskMessage(mask2) + tree = _FieldMaskTree(mask1) + intersection = _FieldMaskTree() + for path in mask2.paths: + tree.IntersectPath(path, intersection) + intersection.ToFieldMask(self) + + def MergeMessage( + self, source, destination, + replace_message_field=False, replace_repeated_field=False): + """Merges fields specified in FieldMask from source to destination. + + Args: + source: Source message. + destination: The destination message to be merged into. + replace_message_field: Replace message field if True. Merge message + field if False. + replace_repeated_field: Replace repeated field if True. Append + elements of repeated field if False. + """ + tree = _FieldMaskTree(self) + tree.MergeMessage( + source, destination, replace_message_field, replace_repeated_field) + + +def _IsValidPath(message_descriptor, path): + """Checks whether the path is valid for Message Descriptor.""" + parts = path.split('.') + last = parts.pop() + for name in parts: + field = message_descriptor.fields_by_name.get(name) + if (field is None or + field.label == FieldDescriptor.LABEL_REPEATED or + field.type != FieldDescriptor.TYPE_MESSAGE): + return False + message_descriptor = field.message_type + return last in message_descriptor.fields_by_name + + +def _CheckFieldMaskMessage(message): + """Raises ValueError if message is not a FieldMask.""" + message_descriptor = message.DESCRIPTOR + if (message_descriptor.name != 'FieldMask' or + message_descriptor.file.name != 'google/protobuf/field_mask.proto'): + raise ValueError('Message {0} is not a FieldMask.'.format( + message_descriptor.full_name)) + + +def _SnakeCaseToCamelCase(path_name): + """Converts a path name from snake_case to camelCase.""" + result = [] + after_underscore = False + for c in path_name: + if c.isupper(): + raise Error('Fail to print FieldMask to Json string: Path name ' + '{0} must not contain uppercase letters.'.format(path_name)) + if after_underscore: + if c.islower(): + result.append(c.upper()) + after_underscore = False + else: + raise Error('Fail to print FieldMask to Json string: The ' + 'character after a "_" must be a lowercase letter ' + 'in path name {0}.'.format(path_name)) + elif c == '_': + after_underscore = True + else: + result += c + + if after_underscore: + raise Error('Fail to print FieldMask to Json string: Trailing "_" ' + 'in path name {0}.'.format(path_name)) + return ''.join(result) + + +def _CamelCaseToSnakeCase(path_name): + """Converts a field name from camelCase to snake_case.""" + result = [] + for c in path_name: + if c == '_': + raise ParseError('Fail to parse FieldMask: Path name ' + '{0} must not contain "_"s.'.format(path_name)) + if c.isupper(): + result += '_' + result += c.lower() + else: + result += c + return ''.join(result) + + +class _FieldMaskTree(object): + """Represents a FieldMask in a tree structure. + + For example, given a FieldMask "foo.bar,foo.baz,bar.baz", + the FieldMaskTree will be: + [_root] -+- foo -+- bar + | | + | +- baz + | + +- bar --- baz + In the tree, each leaf node represents a field path. + """ + + def __init__(self, field_mask=None): + """Initializes the tree by FieldMask.""" + self._root = {} + if field_mask: + self.MergeFromFieldMask(field_mask) + + def MergeFromFieldMask(self, field_mask): + """Merges a FieldMask to the tree.""" + for path in field_mask.paths: + self.AddPath(path) + + def AddPath(self, path): + """Adds a field path into the tree. + + If the field path to add is a sub-path of an existing field path + in the tree (i.e., a leaf node), it means the tree already matches + the given path so nothing will be added to the tree. If the path + matches an existing non-leaf node in the tree, that non-leaf node + will be turned into a leaf node with all its children removed because + the path matches all the node's children. Otherwise, a new path will + be added. + + Args: + path: The field path to add. + """ + node = self._root + for name in path.split('.'): + if name not in node: + node[name] = {} + elif not node[name]: + # Pre-existing empty node implies we already have this entire tree. + return + node = node[name] + # Remove any sub-trees we might have had. + node.clear() + + def ToFieldMask(self, field_mask): + """Converts the tree to a FieldMask.""" + field_mask.Clear() + _AddFieldPaths(self._root, '', field_mask) + + def IntersectPath(self, path, intersection): + """Calculates the intersection part of a field path with this tree. + + Args: + path: The field path to calculates. + intersection: The out tree to record the intersection part. + """ + node = self._root + for name in path.split('.'): + if name not in node: + return + elif not node[name]: + intersection.AddPath(path) + return + node = node[name] + intersection.AddLeafNodes(path, node) + + def AddLeafNodes(self, prefix, node): + """Adds leaf nodes begin with prefix to this tree.""" + if not node: + self.AddPath(prefix) + for name in node: + child_path = prefix + '.' + name + self.AddLeafNodes(child_path, node[name]) + + def MergeMessage( + self, source, destination, + replace_message, replace_repeated): + """Merge all fields specified by this tree from source to destination.""" + _MergeMessage( + self._root, source, destination, replace_message, replace_repeated) + + +def _StrConvert(value): + """Converts value to str if it is not.""" + # This file is imported by c extension and some methods like ClearField + # requires string for the field name. py2/py3 has different text + # type and may use unicode. + if not isinstance(value, str): + return value.encode('utf-8') + return value + + +def _MergeMessage( + node, source, destination, replace_message, replace_repeated): + """Merge all fields specified by a sub-tree from source to destination.""" + source_descriptor = source.DESCRIPTOR + for name in node: + child = node[name] + field = source_descriptor.fields_by_name[name] + if field is None: + raise ValueError('Error: Can\'t find field {0} in message {1}.'.format( + name, source_descriptor.full_name)) + if child: + # Sub-paths are only allowed for singular message fields. + if (field.label == FieldDescriptor.LABEL_REPEATED or + field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE): + raise ValueError('Error: Field {0} in message {1} is not a singular ' + 'message field and cannot have sub-fields.'.format( + name, source_descriptor.full_name)) + if source.HasField(name): + _MergeMessage( + child, getattr(source, name), getattr(destination, name), + replace_message, replace_repeated) + continue + if field.label == FieldDescriptor.LABEL_REPEATED: + if replace_repeated: + destination.ClearField(_StrConvert(name)) + repeated_source = getattr(source, name) + repeated_destination = getattr(destination, name) + if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + for item in repeated_source: + repeated_destination.add().MergeFrom(item) + else: + repeated_destination.extend(repeated_source) + else: + if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + if replace_message: + destination.ClearField(_StrConvert(name)) + if source.HasField(name): + getattr(destination, name).MergeFrom(getattr(source, name)) + else: + setattr(destination, name, getattr(source, name)) + + +def _AddFieldPaths(node, prefix, field_mask): + """Adds the field paths descended from node to field_mask.""" + if not node: + field_mask.paths.append(prefix) + return + for name in sorted(node): + if prefix: + child_path = prefix + '.' + name + else: + child_path = name + _AddFieldPaths(node[name], child_path, field_mask) + + +_INT_OR_FLOAT = six.integer_types + (float,) + + +def _SetStructValue(struct_value, value): + if value is None: + struct_value.null_value = 0 + elif isinstance(value, bool): + # Note: this check must come before the number check because in Python + # True and False are also considered numbers. + struct_value.bool_value = value + elif isinstance(value, six.string_types): + struct_value.string_value = value + elif isinstance(value, _INT_OR_FLOAT): + struct_value.number_value = value + elif isinstance(value, dict): + struct_value.struct_value.Clear() + struct_value.struct_value.update(value) + elif isinstance(value, list): + struct_value.list_value.Clear() + struct_value.list_value.extend(value) + else: + raise ValueError('Unexpected type') + + +def _GetStructValue(struct_value): + which = struct_value.WhichOneof('kind') + if which == 'struct_value': + return struct_value.struct_value + elif which == 'null_value': + return None + elif which == 'number_value': + return struct_value.number_value + elif which == 'string_value': + return struct_value.string_value + elif which == 'bool_value': + return struct_value.bool_value + elif which == 'list_value': + return struct_value.list_value + elif which is None: + raise ValueError('Value not set') + + +class Struct(object): + """Class for Struct message type.""" + + __slots__ = [] + + def __getitem__(self, key): + return _GetStructValue(self.fields[key]) + + def __contains__(self, item): + return item in self.fields + + def __setitem__(self, key, value): + _SetStructValue(self.fields[key], value) + + def __delitem__(self, key): + del self.fields[key] + + def __len__(self): + return len(self.fields) + + def __iter__(self): + return iter(self.fields) + + def keys(self): # pylint: disable=invalid-name + return list(self.fields.keys()) + + def values(self): # pylint: disable=invalid-name + return [self[key] for key in self] + + def items(self): # pylint: disable=invalid-name + return [(key, self[key]) for key in self] + + def get_or_create_list(self, key): + """Returns a list for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('list_value'): + # Clear will mark list_value modified which will indeed create a list. + self.fields[key].list_value.Clear() + return self.fields[key].list_value + + def get_or_create_struct(self, key): + """Returns a struct for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('struct_value'): + # Clear will mark struct_value modified which will indeed create a struct. + self.fields[key].struct_value.Clear() + return self.fields[key].struct_value + + def update(self, dictionary): # pylint: disable=invalid-name + for key, value in list(dictionary.items()): + _SetStructValue(self.fields[key], value) + +collections.MutableMapping.register(Struct) + + +class ListValue(object): + """Class for ListValue message type.""" + + def __len__(self): + return len(self.values) + + def append(self, value): + _SetStructValue(self.values.add(), value) + + def extend(self, elem_seq): + for value in elem_seq: + self.append(value) + + def __getitem__(self, index): + """Retrieves item by the specified index.""" + return _GetStructValue(self.values.__getitem__(index)) + + def __setitem__(self, index, value): + _SetStructValue(self.values.__getitem__(index), value) + + def __delitem__(self, key): + del self.values[key] + + def items(self): + for i in range(len(self)): + yield self[i] + + def add_struct(self): + """Appends and returns a struct value as the next value in the list.""" + struct_value = self.values.add().struct_value + # Clear will mark struct_value modified which will indeed create a struct. + struct_value.Clear() + return struct_value + + def add_list(self): + """Appends and returns a list value as the next value in the list.""" + list_value = self.values.add().list_value + # Clear will mark list_value modified which will indeed create a list. + list_value.Clear() + return list_value + +collections.MutableSequence.register(ListValue) + + +WKTBASES = { + 'google.protobuf.Any': Any, + 'google.protobuf.Duration': Duration, + 'google.protobuf.FieldMask': FieldMask, + 'google.protobuf.ListValue': ListValue, + 'google.protobuf.Struct': Struct, + 'google.protobuf.Timestamp': Timestamp, +} diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types_test.py new file mode 100644 index 0000000..b1ed859 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/well_known_types_test.py @@ -0,0 +1,927 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.internal.well_known_types.""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import collections +from datetime import datetime + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import any_pb2 +from google.protobuf import duration_pb2 +from google.protobuf import field_mask_pb2 +from google.protobuf import struct_pb2 +from google.protobuf import timestamp_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf.internal import any_test_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import well_known_types +from google.protobuf import descriptor +from google.protobuf import text_format + + +class TimeUtilTestBase(unittest.TestCase): + + def CheckTimestampConversion(self, message, text): + self.assertEqual(text, message.ToJsonString()) + parsed_message = timestamp_pb2.Timestamp() + parsed_message.FromJsonString(text) + self.assertEqual(message, parsed_message) + + def CheckDurationConversion(self, message, text): + self.assertEqual(text, message.ToJsonString()) + parsed_message = duration_pb2.Duration() + parsed_message.FromJsonString(text) + self.assertEqual(message, parsed_message) + + +class TimeUtilTest(TimeUtilTestBase): + + def testTimestampSerializeAndParse(self): + message = timestamp_pb2.Timestamp() + # Generated output should contain 3, 6, or 9 fractional digits. + message.seconds = 0 + message.nanos = 0 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00Z') + message.nanos = 10000000 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00.010Z') + message.nanos = 10000 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000010Z') + message.nanos = 10 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000000010Z') + # Test min timestamps. + message.seconds = -62135596800 + message.nanos = 0 + self.CheckTimestampConversion(message, '0001-01-01T00:00:00Z') + # Test max timestamps. + message.seconds = 253402300799 + message.nanos = 999999999 + self.CheckTimestampConversion(message, '9999-12-31T23:59:59.999999999Z') + # Test negative timestamps. + message.seconds = -1 + self.CheckTimestampConversion(message, '1969-12-31T23:59:59.999999999Z') + + # Parsing accepts an fractional digits as long as they fit into nano + # precision. + message.FromJsonString('1970-01-01T00:00:00.1Z') + self.assertEqual(0, message.seconds) + self.assertEqual(100000000, message.nanos) + # Parsing accepts offsets. + message.FromJsonString('1970-01-01T00:00:00-08:00') + self.assertEqual(8 * 3600, message.seconds) + self.assertEqual(0, message.nanos) + + # It is not easy to check with current time. For test coverage only. + message.GetCurrentTime() + self.assertNotEqual(8 * 3600, message.seconds) + + def testDurationSerializeAndParse(self): + message = duration_pb2.Duration() + # Generated output should contain 3, 6, or 9 fractional digits. + message.seconds = 0 + message.nanos = 0 + self.CheckDurationConversion(message, '0s') + message.nanos = 10000000 + self.CheckDurationConversion(message, '0.010s') + message.nanos = 10000 + self.CheckDurationConversion(message, '0.000010s') + message.nanos = 10 + self.CheckDurationConversion(message, '0.000000010s') + + # Test min and max + message.seconds = 315576000000 + message.nanos = 999999999 + self.CheckDurationConversion(message, '315576000000.999999999s') + message.seconds = -315576000000 + message.nanos = -999999999 + self.CheckDurationConversion(message, '-315576000000.999999999s') + + # Parsing accepts an fractional digits as long as they fit into nano + # precision. + message.FromJsonString('0.1s') + self.assertEqual(100000000, message.nanos) + message.FromJsonString('0.0000001s') + self.assertEqual(100, message.nanos) + + def testTimestampIntegerConversion(self): + message = timestamp_pb2.Timestamp() + message.FromNanoseconds(1) + self.assertEqual('1970-01-01T00:00:00.000000001Z', + message.ToJsonString()) + self.assertEqual(1, message.ToNanoseconds()) + + message.FromNanoseconds(-1) + self.assertEqual('1969-12-31T23:59:59.999999999Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToNanoseconds()) + + message.FromMicroseconds(1) + self.assertEqual('1970-01-01T00:00:00.000001Z', + message.ToJsonString()) + self.assertEqual(1, message.ToMicroseconds()) + + message.FromMicroseconds(-1) + self.assertEqual('1969-12-31T23:59:59.999999Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToMicroseconds()) + + message.FromMilliseconds(1) + self.assertEqual('1970-01-01T00:00:00.001Z', + message.ToJsonString()) + self.assertEqual(1, message.ToMilliseconds()) + + message.FromMilliseconds(-1) + self.assertEqual('1969-12-31T23:59:59.999Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToMilliseconds()) + + message.FromSeconds(1) + self.assertEqual('1970-01-01T00:00:01Z', + message.ToJsonString()) + self.assertEqual(1, message.ToSeconds()) + + message.FromSeconds(-1) + self.assertEqual('1969-12-31T23:59:59Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToSeconds()) + + message.FromNanoseconds(1999) + self.assertEqual(1, message.ToMicroseconds()) + # For negative values, Timestamp will be rounded down. + # For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds + # will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than + # "1970-01-01T00:00:00Z" (i.e., 0s). + message.FromNanoseconds(-1999) + self.assertEqual(-2, message.ToMicroseconds()) + + def testDurationIntegerConversion(self): + message = duration_pb2.Duration() + message.FromNanoseconds(1) + self.assertEqual('0.000000001s', + message.ToJsonString()) + self.assertEqual(1, message.ToNanoseconds()) + + message.FromNanoseconds(-1) + self.assertEqual('-0.000000001s', + message.ToJsonString()) + self.assertEqual(-1, message.ToNanoseconds()) + + message.FromMicroseconds(1) + self.assertEqual('0.000001s', + message.ToJsonString()) + self.assertEqual(1, message.ToMicroseconds()) + + message.FromMicroseconds(-1) + self.assertEqual('-0.000001s', + message.ToJsonString()) + self.assertEqual(-1, message.ToMicroseconds()) + + message.FromMilliseconds(1) + self.assertEqual('0.001s', + message.ToJsonString()) + self.assertEqual(1, message.ToMilliseconds()) + + message.FromMilliseconds(-1) + self.assertEqual('-0.001s', + message.ToJsonString()) + self.assertEqual(-1, message.ToMilliseconds()) + + message.FromSeconds(1) + self.assertEqual('1s', message.ToJsonString()) + self.assertEqual(1, message.ToSeconds()) + + message.FromSeconds(-1) + self.assertEqual('-1s', + message.ToJsonString()) + self.assertEqual(-1, message.ToSeconds()) + + # Test truncation behavior. + message.FromNanoseconds(1999) + self.assertEqual(1, message.ToMicroseconds()) + + # For negative values, Duration will be rounded towards 0. + message.FromNanoseconds(-1999) + self.assertEqual(-1, message.ToMicroseconds()) + + def testDatetimeConverison(self): + message = timestamp_pb2.Timestamp() + dt = datetime(1970, 1, 1) + message.FromDatetime(dt) + self.assertEqual(dt, message.ToDatetime()) + + message.FromMilliseconds(1999) + self.assertEqual(datetime(1970, 1, 1, 0, 0, 1, 999000), + message.ToDatetime()) + + def testTimedeltaConversion(self): + message = duration_pb2.Duration() + message.FromNanoseconds(1999999999) + td = message.ToTimedelta() + self.assertEqual(1, td.seconds) + self.assertEqual(999999, td.microseconds) + + message.FromNanoseconds(-1999999999) + td = message.ToTimedelta() + self.assertEqual(-1, td.days) + self.assertEqual(86398, td.seconds) + self.assertEqual(1, td.microseconds) + + message.FromMicroseconds(-1) + td = message.ToTimedelta() + self.assertEqual(-1, td.days) + self.assertEqual(86399, td.seconds) + self.assertEqual(999999, td.microseconds) + converted_message = duration_pb2.Duration() + converted_message.FromTimedelta(td) + self.assertEqual(message, converted_message) + + def testInvalidTimestamp(self): + message = timestamp_pb2.Timestamp() + self.assertRaisesRegex( + well_known_types.ParseError, + 'Failed to parse timestamp: missing valid timezone offset.', + message.FromJsonString, + '') + self.assertRaisesRegex( + well_known_types.ParseError, + 'Failed to parse timestamp: invalid trailing data ' + '1970-01-01T00:00:01Ztrail.', + message.FromJsonString, + '1970-01-01T00:00:01Ztrail') + self.assertRaisesRegex( + ValueError, + 'time data \'10000-01-01T00:00:00\' does not match' + ' format \'%Y-%m-%dT%H:%M:%S\'', + message.FromJsonString, '10000-01-01T00:00:00.00Z') + self.assertRaisesRegex( + well_known_types.ParseError, + 'nanos 0123456789012 more than 9 fractional digits.', + message.FromJsonString, + '1970-01-01T00:00:00.0123456789012Z') + self.assertRaisesRegex( + well_known_types.ParseError, + (r'Invalid timezone offset value: \+08.'), + message.FromJsonString, + '1972-01-01T01:00:00.01+08',) + self.assertRaisesRegex( + ValueError, + 'year (0 )?is out of range', + message.FromJsonString, + '0000-01-01T00:00:00Z') + message.seconds = 253402300800 + self.assertRaisesRegex( + OverflowError, + 'date value out of range', + message.ToJsonString) + + def testInvalidDuration(self): + message = duration_pb2.Duration() + self.assertRaisesRegex( + well_known_types.ParseError, + 'Duration must end with letter "s": 1.', + message.FromJsonString, '1') + self.assertRaisesRegex( + well_known_types.ParseError, + 'Couldn\'t parse duration: 1...2s.', + message.FromJsonString, '1...2s') + text = '-315576000001.000000000s' + self.assertRaisesRegex( + well_known_types.Error, + r'Duration is not valid\: Seconds -315576000001 must be in range' + r' \[-315576000000\, 315576000000\].', + message.FromJsonString, text) + text = '315576000001.000000000s' + self.assertRaisesRegex( + well_known_types.Error, + r'Duration is not valid\: Seconds 315576000001 must be in range' + r' \[-315576000000\, 315576000000\].', + message.FromJsonString, text) + message.seconds = -315576000001 + message.nanos = 0 + self.assertRaisesRegex( + well_known_types.Error, + r'Duration is not valid\: Seconds -315576000001 must be in range' + r' \[-315576000000\, 315576000000\].', + message.ToJsonString) + message.seconds = 0 + message.nanos = 999999999 + 1 + self.assertRaisesRegex( + well_known_types.Error, + r'Duration is not valid\: Nanos 1000000000 must be in range' + r' \[-999999999\, 999999999\].', + message.ToJsonString) + message.seconds = -1 + message.nanos = 1 + self.assertRaisesRegex( + well_known_types.Error, + r'Duration is not valid\: Sign mismatch.', + message.ToJsonString) + + +class FieldMaskTest(unittest.TestCase): + + def testStringFormat(self): + mask = field_mask_pb2.FieldMask() + self.assertEqual('', mask.ToJsonString()) + mask.paths.append('foo') + self.assertEqual('foo', mask.ToJsonString()) + mask.paths.append('bar') + self.assertEqual('foo,bar', mask.ToJsonString()) + + mask.FromJsonString('') + self.assertEqual('', mask.ToJsonString()) + mask.FromJsonString('foo') + self.assertEqual(['foo'], mask.paths) + mask.FromJsonString('foo,bar') + self.assertEqual(['foo', 'bar'], mask.paths) + + # Test camel case + mask.Clear() + mask.paths.append('foo_bar') + self.assertEqual('fooBar', mask.ToJsonString()) + mask.paths.append('bar_quz') + self.assertEqual('fooBar,barQuz', mask.ToJsonString()) + + mask.FromJsonString('') + self.assertEqual('', mask.ToJsonString()) + mask.FromJsonString('fooBar') + self.assertEqual(['foo_bar'], mask.paths) + mask.FromJsonString('fooBar,barQuz') + self.assertEqual(['foo_bar', 'bar_quz'], mask.paths) + + def testDescriptorToFieldMask(self): + mask = field_mask_pb2.FieldMask() + msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + mask.AllFieldsFromDescriptor(msg_descriptor) + self.assertEqual(75, len(mask.paths)) + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + for field in msg_descriptor.fields: + self.assertTrue(field.name in mask.paths) + + def testIsValidForDescriptor(self): + msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + # Empty mask + mask = field_mask_pb2.FieldMask() + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # All fields from descriptor + mask.AllFieldsFromDescriptor(msg_descriptor) + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # Child under optional message + mask.paths.append('optional_nested_message.bb') + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # Repeated field is only allowed in the last position of path + mask.paths.append('repeated_nested_message.bb') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid top level field + mask = field_mask_pb2.FieldMask() + mask.paths.append('xxx') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in root + mask = field_mask_pb2.FieldMask() + mask.paths.append('xxx.zzz') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in internal node + mask = field_mask_pb2.FieldMask() + mask.paths.append('optional_nested_message.xxx.zzz') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in leaf + mask = field_mask_pb2.FieldMask() + mask.paths.append('optional_nested_message.xxx') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + + def testCanonicalFrom(self): + mask = field_mask_pb2.FieldMask() + out_mask = field_mask_pb2.FieldMask() + # Paths will be sorted. + mask.FromJsonString('baz.quz,bar,foo') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('bar,baz.quz,foo', out_mask.ToJsonString()) + # Duplicated paths will be removed. + mask.FromJsonString('foo,bar,foo') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('bar,foo', out_mask.ToJsonString()) + # Sub-paths of other paths will be removed. + mask.FromJsonString('foo.b1,bar.b1,foo.b2,bar') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('bar,foo.b1,foo.b2', out_mask.ToJsonString()) + + # Test more deeply nested cases. + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2.quz,foo.bar.baz2') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo.bar.baz1,foo.bar.baz2', + out_mask.ToJsonString()) + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo.bar.baz1,foo.bar.baz2', + out_mask.ToJsonString()) + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo.bar') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo.bar', out_mask.ToJsonString()) + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo', out_mask.ToJsonString()) + + def testUnion(self): + mask1 = field_mask_pb2.FieldMask() + mask2 = field_mask_pb2.FieldMask() + out_mask = field_mask_pb2.FieldMask() + mask1.FromJsonString('foo,baz') + mask2.FromJsonString('bar,quz') + out_mask.Union(mask1, mask2) + self.assertEqual('bar,baz,foo,quz', out_mask.ToJsonString()) + # Overlap with duplicated paths. + mask1.FromJsonString('foo,baz.bb') + mask2.FromJsonString('baz.bb,quz') + out_mask.Union(mask1, mask2) + self.assertEqual('baz.bb,foo,quz', out_mask.ToJsonString()) + # Overlap with paths covering some other paths. + mask1.FromJsonString('foo.bar.baz,quz') + mask2.FromJsonString('foo.bar,bar') + out_mask.Union(mask1, mask2) + self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString()) + src = unittest_pb2.TestAllTypes() + with self.assertRaises(ValueError): + out_mask.Union(src, mask2) + + def testIntersect(self): + mask1 = field_mask_pb2.FieldMask() + mask2 = field_mask_pb2.FieldMask() + out_mask = field_mask_pb2.FieldMask() + # Test cases without overlapping. + mask1.FromJsonString('foo,baz') + mask2.FromJsonString('bar,quz') + out_mask.Intersect(mask1, mask2) + self.assertEqual('', out_mask.ToJsonString()) + # Overlap with duplicated paths. + mask1.FromJsonString('foo,baz.bb') + mask2.FromJsonString('baz.bb,quz') + out_mask.Intersect(mask1, mask2) + self.assertEqual('baz.bb', out_mask.ToJsonString()) + # Overlap with paths covering some other paths. + mask1.FromJsonString('foo.bar.baz,quz') + mask2.FromJsonString('foo.bar,bar') + out_mask.Intersect(mask1, mask2) + self.assertEqual('foo.bar.baz', out_mask.ToJsonString()) + mask1.FromJsonString('foo.bar,bar') + mask2.FromJsonString('foo.bar.baz,quz') + out_mask.Intersect(mask1, mask2) + self.assertEqual('foo.bar.baz', out_mask.ToJsonString()) + + def testMergeMessage(self): + # Test merge one field. + src = unittest_pb2.TestAllTypes() + test_util.SetAllFields(src) + for field in src.DESCRIPTOR.fields: + if field.containing_oneof: + continue + field_name = field.name + dst = unittest_pb2.TestAllTypes() + # Only set one path to mask. + mask = field_mask_pb2.FieldMask() + mask.paths.append(field_name) + mask.MergeMessage(src, dst) + # The expected result message. + msg = unittest_pb2.TestAllTypes() + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + repeated_src = getattr(src, field_name) + repeated_msg = getattr(msg, field_name) + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + for item in repeated_src: + repeated_msg.add().CopyFrom(item) + else: + repeated_msg.extend(repeated_src) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + getattr(msg, field_name).CopyFrom(getattr(src, field_name)) + else: + setattr(msg, field_name, getattr(src, field_name)) + # Only field specified in mask is merged. + self.assertEqual(msg, dst) + + # Test merge nested fields. + nested_src = unittest_pb2.NestedTestAllTypes() + nested_dst = unittest_pb2.NestedTestAllTypes() + nested_src.child.payload.optional_int32 = 1234 + nested_src.child.child.payload.optional_int32 = 5678 + mask = field_mask_pb2.FieldMask() + mask.FromJsonString('child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(0, nested_dst.child.child.payload.optional_int32) + + mask.FromJsonString('child.child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(5678, nested_dst.child.child.payload.optional_int32) + + nested_dst.Clear() + mask.FromJsonString('child.child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(0, nested_dst.child.payload.optional_int32) + self.assertEqual(5678, nested_dst.child.child.payload.optional_int32) + + nested_dst.Clear() + mask.FromJsonString('child') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(5678, nested_dst.child.child.payload.optional_int32) + + # Test MergeOptions. + nested_dst.Clear() + nested_dst.child.payload.optional_int64 = 4321 + # Message fields will be merged by default. + mask.FromJsonString('child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(4321, nested_dst.child.payload.optional_int64) + # Change the behavior to replace message fields. + mask.FromJsonString('child.payload') + mask.MergeMessage(nested_src, nested_dst, True, False) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(0, nested_dst.child.payload.optional_int64) + + # By default, fields missing in source are not cleared in destination. + nested_dst.payload.optional_int32 = 1234 + self.assertTrue(nested_dst.HasField('payload')) + mask.FromJsonString('payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertTrue(nested_dst.HasField('payload')) + # But they are cleared when replacing message fields. + nested_dst.Clear() + nested_dst.payload.optional_int32 = 1234 + mask.FromJsonString('payload') + mask.MergeMessage(nested_src, nested_dst, True, False) + self.assertFalse(nested_dst.HasField('payload')) + + nested_src.payload.repeated_int32.append(1234) + nested_dst.payload.repeated_int32.append(5678) + # Repeated fields will be appended by default. + mask.FromJsonString('payload.repeatedInt32') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(2, len(nested_dst.payload.repeated_int32)) + self.assertEqual(5678, nested_dst.payload.repeated_int32[0]) + self.assertEqual(1234, nested_dst.payload.repeated_int32[1]) + # Change the behavior to replace repeated fields. + mask.FromJsonString('payload.repeatedInt32') + mask.MergeMessage(nested_src, nested_dst, False, True) + self.assertEqual(1, len(nested_dst.payload.repeated_int32)) + self.assertEqual(1234, nested_dst.payload.repeated_int32[0]) + + # Test Merge oneof field. + new_msg = unittest_pb2.TestOneof2() + dst = unittest_pb2.TestOneof2() + dst.foo_message.qux_int = 1 + mask = field_mask_pb2.FieldMask() + mask.FromJsonString('fooMessage,fooLazyMessage.quxInt') + mask.MergeMessage(new_msg, dst) + self.assertTrue(dst.HasField('foo_message')) + self.assertFalse(dst.HasField('foo_lazy_message')) + + def testMergeErrors(self): + src = unittest_pb2.TestAllTypes() + dst = unittest_pb2.TestAllTypes() + mask = field_mask_pb2.FieldMask() + test_util.SetAllFields(src) + mask.FromJsonString('optionalInt32.field') + with self.assertRaises(ValueError) as e: + mask.MergeMessage(src, dst) + self.assertEqual('Error: Field optional_int32 in message ' + 'protobuf_unittest.TestAllTypes is not a singular ' + 'message field and cannot have sub-fields.', + str(e.exception)) + + def testSnakeCaseToCamelCase(self): + self.assertEqual('fooBar', + well_known_types._SnakeCaseToCamelCase('foo_bar')) + self.assertEqual('FooBar', + well_known_types._SnakeCaseToCamelCase('_foo_bar')) + self.assertEqual('foo3Bar', + well_known_types._SnakeCaseToCamelCase('foo3_bar')) + + # No uppercase letter is allowed. + self.assertRaisesRegex( + well_known_types.Error, + 'Fail to print FieldMask to Json string: Path name Foo must ' + 'not contain uppercase letters.', + well_known_types._SnakeCaseToCamelCase, + 'Foo') + # Any character after a "_" must be a lowercase letter. + # 1. "_" cannot be followed by another "_". + # 2. "_" cannot be followed by a digit. + # 3. "_" cannot appear as the last character. + self.assertRaisesRegex( + well_known_types.Error, + 'Fail to print FieldMask to Json string: The character after a ' + '"_" must be a lowercase letter in path name foo__bar.', + well_known_types._SnakeCaseToCamelCase, + 'foo__bar') + self.assertRaisesRegex( + well_known_types.Error, + 'Fail to print FieldMask to Json string: The character after a ' + '"_" must be a lowercase letter in path name foo_3bar.', + well_known_types._SnakeCaseToCamelCase, + 'foo_3bar') + self.assertRaisesRegex( + well_known_types.Error, + 'Fail to print FieldMask to Json string: Trailing "_" in path ' + 'name foo_bar_.', + well_known_types._SnakeCaseToCamelCase, + 'foo_bar_') + + def testCamelCaseToSnakeCase(self): + self.assertEqual('foo_bar', + well_known_types._CamelCaseToSnakeCase('fooBar')) + self.assertEqual('_foo_bar', + well_known_types._CamelCaseToSnakeCase('FooBar')) + self.assertEqual('foo3_bar', + well_known_types._CamelCaseToSnakeCase('foo3Bar')) + self.assertRaisesRegex( + well_known_types.ParseError, + 'Fail to parse FieldMask: Path name foo_bar must not contain "_"s.', + well_known_types._CamelCaseToSnakeCase, + 'foo_bar') + + +class StructTest(unittest.TestCase): + + def testStruct(self): + struct = struct_pb2.Struct() + self.assertIsInstance(struct, collections.Mapping) + self.assertEqual(0, len(struct)) + struct_class = struct.__class__ + + struct['key1'] = 5 + struct['key2'] = 'abc' + struct['key3'] = True + struct.get_or_create_struct('key4')['subkey'] = 11.0 + struct_list = struct.get_or_create_list('key5') + self.assertIsInstance(struct_list, collections.Sequence) + struct_list.extend([6, 'seven', True, False, None]) + struct_list.add_struct()['subkey2'] = 9 + struct['key6'] = {'subkey': {}} + struct['key7'] = [2, False] + + self.assertEqual(7, len(struct)) + self.assertTrue(isinstance(struct, well_known_types.Struct)) + self.assertEqual(5, struct['key1']) + self.assertEqual('abc', struct['key2']) + self.assertIs(True, struct['key3']) + self.assertEqual(11, struct['key4']['subkey']) + inner_struct = struct_class() + inner_struct['subkey2'] = 9 + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct['key5'].items())) + self.assertEqual({}, dict(struct['key6']['subkey'].fields)) + self.assertEqual([2, False], list(struct['key7'].items())) + + serialized = struct.SerializeToString() + struct2 = struct_pb2.Struct() + struct2.ParseFromString(serialized) + + self.assertEqual(struct, struct2) + for key, value in list(struct.items()): + self.assertIn(key, struct) + self.assertIn(key, struct2) + self.assertEqual(value, struct2[key]) + + self.assertEqual(7, len(list(struct.keys()))) + self.assertEqual(7, len(list(struct.values()))) + for key in list(struct.keys()): + self.assertIn(key, struct) + self.assertIn(key, struct2) + self.assertEqual(struct[key], struct2[key]) + + item = (next(iter(list(struct.keys()))), next(iter(list(struct.values())))) + self.assertEqual(item, next(iter(list(struct.items())))) + + self.assertTrue(isinstance(struct2, well_known_types.Struct)) + self.assertEqual(5, struct2['key1']) + self.assertEqual('abc', struct2['key2']) + self.assertIs(True, struct2['key3']) + self.assertEqual(11, struct2['key4']['subkey']) + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct2['key5'].items())) + + struct_list = struct2['key5'] + self.assertEqual(6, struct_list[0]) + self.assertEqual('seven', struct_list[1]) + self.assertEqual(True, struct_list[2]) + self.assertEqual(False, struct_list[3]) + self.assertEqual(None, struct_list[4]) + self.assertEqual(inner_struct, struct_list[5]) + + struct_list[1] = 7 + self.assertEqual(7, struct_list[1]) + + struct_list.add_list().extend([1, 'two', True, False, None]) + self.assertEqual([1, 'two', True, False, None], + list(struct_list[6].items())) + struct_list.extend([{'nested_struct': 30}, ['nested_list', 99], {}, []]) + self.assertEqual(11, len(struct_list.values)) + self.assertEqual(30, struct_list[7]['nested_struct']) + self.assertEqual('nested_list', struct_list[8][0]) + self.assertEqual(99, struct_list[8][1]) + self.assertEqual({}, dict(struct_list[9].fields)) + self.assertEqual([], list(struct_list[10].items())) + struct_list[0] = {'replace': 'set'} + struct_list[1] = ['replace', 'set'] + self.assertEqual('set', struct_list[0]['replace']) + self.assertEqual(['replace', 'set'], list(struct_list[1].items())) + + text_serialized = str(struct) + struct3 = struct_pb2.Struct() + text_format.Merge(text_serialized, struct3) + self.assertEqual(struct, struct3) + + struct.get_or_create_struct('key3')['replace'] = 12 + self.assertEqual(12, struct['key3']['replace']) + + # Tests empty list. + struct.get_or_create_list('empty_list') + empty_list = struct['empty_list'] + self.assertEqual([], list(empty_list.items())) + list2 = struct_pb2.ListValue() + list2.add_list() + empty_list = list2[0] + self.assertEqual([], list(empty_list.items())) + + # Tests empty struct. + struct.get_or_create_struct('empty_struct') + empty_struct = struct['empty_struct'] + self.assertEqual({}, dict(empty_struct.fields)) + list2.add_struct() + empty_struct = list2[1] + self.assertEqual({}, dict(empty_struct.fields)) + + self.assertEqual(9, len(struct)) + del struct['key3'] + del struct['key4'] + self.assertEqual(7, len(struct)) + self.assertEqual(6, len(struct['key5'])) + del struct['key5'][1] + self.assertEqual(5, len(struct['key5'])) + self.assertEqual([6, True, False, None, inner_struct], + list(struct['key5'].items())) + + def testMergeFrom(self): + struct = struct_pb2.Struct() + struct_class = struct.__class__ + + dictionary = { + 'key1': 5, + 'key2': 'abc', + 'key3': True, + 'key4': {'subkey': 11.0}, + 'key5': [6, 'seven', True, False, None, {'subkey2': 9}], + 'key6': [['nested_list', True]], + 'empty_struct': {}, + 'empty_list': [] + } + struct.update(dictionary) + self.assertEqual(5, struct['key1']) + self.assertEqual('abc', struct['key2']) + self.assertIs(True, struct['key3']) + self.assertEqual(11, struct['key4']['subkey']) + inner_struct = struct_class() + inner_struct['subkey2'] = 9 + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct['key5'].items())) + self.assertEqual(2, len(struct['key6'][0].values)) + self.assertEqual('nested_list', struct['key6'][0][0]) + self.assertEqual(True, struct['key6'][0][1]) + empty_list = struct['empty_list'] + self.assertEqual([], list(empty_list.items())) + empty_struct = struct['empty_struct'] + self.assertEqual({}, dict(empty_struct.fields)) + + # According to documentation: "When parsing from the wire or when merging, + # if there are duplicate map keys the last key seen is used". + duplicate = { + 'key4': {'replace': 20}, + 'key5': [[False, 5]] + } + struct.update(duplicate) + self.assertEqual(1, len(struct['key4'].fields)) + self.assertEqual(20, struct['key4']['replace']) + self.assertEqual(1, len(struct['key5'].values)) + self.assertEqual(False, struct['key5'][0][0]) + self.assertEqual(5, struct['key5'][0][1]) + + +class AnyTest(unittest.TestCase): + + def testAnyMessage(self): + # Creates and sets message. + msg = any_test_pb2.TestAny() + msg_descriptor = msg.DESCRIPTOR + all_types = unittest_pb2.TestAllTypes() + all_descriptor = all_types.DESCRIPTOR + all_types.repeated_string.append('\u00fc\ua71f') + # Packs to Any. + msg.value.Pack(all_types) + self.assertEqual(msg.value.type_url, + 'type.googleapis.com/%s' % all_descriptor.full_name) + self.assertEqual(msg.value.value, + all_types.SerializeToString()) + # Tests Is() method. + self.assertTrue(msg.value.Is(all_descriptor)) + self.assertFalse(msg.value.Is(msg_descriptor)) + # Unpacks Any. + unpacked_message = unittest_pb2.TestAllTypes() + self.assertTrue(msg.value.Unpack(unpacked_message)) + self.assertEqual(all_types, unpacked_message) + # Unpacks to different type. + self.assertFalse(msg.value.Unpack(msg)) + # Only Any messages have Pack method. + try: + msg.Pack(all_types) + except AttributeError: + pass + else: + raise AttributeError('%s should not have Pack method.' % + msg_descriptor.full_name) + + def testMessageName(self): + # Creates and sets message. + submessage = any_test_pb2.TestAny() + submessage.int_value = 12345 + msg = any_pb2.Any() + msg.Pack(submessage) + self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny') + + def testPackWithCustomTypeUrl(self): + submessage = any_test_pb2.TestAny() + submessage.int_value = 12345 + msg = any_pb2.Any() + # Pack with a custom type URL prefix. + msg.Pack(submessage, 'type.myservice.com') + self.assertEqual(msg.type_url, + 'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name) + # Pack with a custom type URL prefix ending with '/'. + msg.Pack(submessage, 'type.myservice.com/') + self.assertEqual(msg.type_url, + 'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name) + # Pack with an empty type URL prefix. + msg.Pack(submessage, '') + self.assertEqual(msg.type_url, + '/%s' % submessage.DESCRIPTOR.full_name) + # Test unpacking the type. + unpacked_message = any_test_pb2.TestAny() + self.assertTrue(msg.Unpack(unpacked_message)) + self.assertEqual(submessage, unpacked_message) + + def testPackDeterministic(self): + submessage = any_test_pb2.TestAny() + for i in range(10): + submessage.map_value[str(i)] = i * 2 + msg = any_pb2.Any() + msg.Pack(submessage, deterministic=True) + serialized = msg.SerializeToString(deterministic=True) + golden = (b'\n4type.googleapis.com/google.protobuf.internal.TestAny\x12F' + b'\x1a\x05\n\x010\x10\x00\x1a\x05\n\x011\x10\x02\x1a\x05\n\x01' + b'2\x10\x04\x1a\x05\n\x013\x10\x06\x1a\x05\n\x014\x10\x08\x1a' + b'\x05\n\x015\x10\n\x1a\x05\n\x016\x10\x0c\x1a\x05\n\x017\x10' + b'\x0e\x1a\x05\n\x018\x10\x10\x1a\x05\n\x019\x10\x12') + self.assertEqual(golden, serialized) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format.py new file mode 100644 index 0000000..883f525 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format.py @@ -0,0 +1,268 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Constants and static functions to support protocol buffer wire format.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import struct +from google.protobuf import descriptor +from google.protobuf import message + + +TAG_TYPE_BITS = 3 # Number of bits used to hold type info in a proto tag. +TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1 # 0x7 + +# These numbers identify the wire type of a protocol buffer value. +# We use the least-significant TAG_TYPE_BITS bits of the varint-encoded +# tag-and-type to store one of these WIRETYPE_* constants. +# These values must match WireType enum in google/protobuf/wire_format.h. +WIRETYPE_VARINT = 0 +WIRETYPE_FIXED64 = 1 +WIRETYPE_LENGTH_DELIMITED = 2 +WIRETYPE_START_GROUP = 3 +WIRETYPE_END_GROUP = 4 +WIRETYPE_FIXED32 = 5 +_WIRETYPE_MAX = 5 + + +# Bounds for various integer types. +INT32_MAX = int((1 << 31) - 1) +INT32_MIN = int(-(1 << 31)) +UINT32_MAX = (1 << 32) - 1 + +INT64_MAX = (1 << 63) - 1 +INT64_MIN = -(1 << 63) +UINT64_MAX = (1 << 64) - 1 + +# "struct" format strings that will encode/decode the specified formats. +FORMAT_UINT32_LITTLE_ENDIAN = '> TAG_TYPE_BITS), (tag & TAG_TYPE_MASK) + + +def ZigZagEncode(value): + """ZigZag Transform: Encodes signed integers so that they can be + effectively used with varint encoding. See wire_format.h for + more details. + """ + if value >= 0: + return value << 1 + return (value << 1) ^ (~0) + + +def ZigZagDecode(value): + """Inverse of ZigZagEncode().""" + if not value & 0x1: + return value >> 1 + return (value >> 1) ^ (~0) + + + +# The *ByteSize() functions below return the number of bytes required to +# serialize "field number + type" information and then serialize the value. + + +def Int32ByteSize(field_number, int32): + return Int64ByteSize(field_number, int32) + + +def Int32ByteSizeNoTag(int32): + return _VarUInt64ByteSizeNoTag(0xffffffffffffffff & int32) + + +def Int64ByteSize(field_number, int64): + # Have to convert to uint before calling UInt64ByteSize(). + return UInt64ByteSize(field_number, 0xffffffffffffffff & int64) + + +def UInt32ByteSize(field_number, uint32): + return UInt64ByteSize(field_number, uint32) + + +def UInt64ByteSize(field_number, uint64): + return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64) + + +def SInt32ByteSize(field_number, int32): + return UInt32ByteSize(field_number, ZigZagEncode(int32)) + + +def SInt64ByteSize(field_number, int64): + return UInt64ByteSize(field_number, ZigZagEncode(int64)) + + +def Fixed32ByteSize(field_number, fixed32): + return TagByteSize(field_number) + 4 + + +def Fixed64ByteSize(field_number, fixed64): + return TagByteSize(field_number) + 8 + + +def SFixed32ByteSize(field_number, sfixed32): + return TagByteSize(field_number) + 4 + + +def SFixed64ByteSize(field_number, sfixed64): + return TagByteSize(field_number) + 8 + + +def FloatByteSize(field_number, flt): + return TagByteSize(field_number) + 4 + + +def DoubleByteSize(field_number, double): + return TagByteSize(field_number) + 8 + + +def BoolByteSize(field_number, b): + return TagByteSize(field_number) + 1 + + +def EnumByteSize(field_number, enum): + return UInt32ByteSize(field_number, enum) + + +def StringByteSize(field_number, string): + return BytesByteSize(field_number, string.encode('utf-8')) + + +def BytesByteSize(field_number, b): + return (TagByteSize(field_number) + + _VarUInt64ByteSizeNoTag(len(b)) + + len(b)) + + +def GroupByteSize(field_number, message): + return (2 * TagByteSize(field_number) # START and END group. + + message.ByteSize()) + + +def MessageByteSize(field_number, message): + return (TagByteSize(field_number) + + _VarUInt64ByteSizeNoTag(message.ByteSize()) + + message.ByteSize()) + + +def MessageSetItemByteSize(field_number, msg): + # First compute the sizes of the tags. + # There are 2 tags for the beginning and ending of the repeated group, that + # is field number 1, one with field number 2 (type_id) and one with field + # number 3 (message). + total_size = (2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3)) + + # Add the number of bytes for type_id. + total_size += _VarUInt64ByteSizeNoTag(field_number) + + message_size = msg.ByteSize() + + # The number of bytes for encoding the length of the message. + total_size += _VarUInt64ByteSizeNoTag(message_size) + + # The size of the message. + total_size += message_size + return total_size + + +def TagByteSize(field_number): + """Returns the bytes required to serialize a tag with this field number.""" + # Just pass in type 0, since the type won't affect the tag+type size. + return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0)) + + +# Private helper function for the *ByteSize() functions above. + +def _VarUInt64ByteSizeNoTag(uint64): + """Returns the number of bytes required to serialize a single varint + using boundary value comparisons. (unrolled loop optimization -WPierce) + uint64 must be unsigned. + """ + if uint64 <= 0x7f: return 1 + if uint64 <= 0x3fff: return 2 + if uint64 <= 0x1fffff: return 3 + if uint64 <= 0xfffffff: return 4 + if uint64 <= 0x7ffffffff: return 5 + if uint64 <= 0x3ffffffffff: return 6 + if uint64 <= 0x1ffffffffffff: return 7 + if uint64 <= 0xffffffffffffff: return 8 + if uint64 <= 0x7fffffffffffffff: return 9 + if uint64 > UINT64_MAX: + raise message.EncodeError('Value out of range: %d' % uint64) + return 10 + + +NON_PACKABLE_TYPES = ( + descriptor.FieldDescriptor.TYPE_STRING, + descriptor.FieldDescriptor.TYPE_GROUP, + descriptor.FieldDescriptor.TYPE_MESSAGE, + descriptor.FieldDescriptor.TYPE_BYTES +) + + +def IsTypePackable(field_type): + """Return true iff packable = true is valid for fields of this type. + + Args: + field_type: a FieldDescriptor::Type value. + + Returns: + True iff fields of this type are packable. + """ + return field_type not in NON_PACKABLE_TYPES diff --git a/venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format_test.py b/venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format_test.py new file mode 100644 index 0000000..da120f3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/internal/wire_format_test.py @@ -0,0 +1,257 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.internal.wire_format.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import message +from google.protobuf.internal import wire_format + + +class WireFormatTest(unittest.TestCase): + + def testPackTag(self): + field_number = 0xabc + tag_type = 2 + self.assertEqual((field_number << 3) | tag_type, + wire_format.PackTag(field_number, tag_type)) + PackTag = wire_format.PackTag + # Number too high. + self.assertRaises(message.EncodeError, PackTag, field_number, 6) + # Number too low. + self.assertRaises(message.EncodeError, PackTag, field_number, -1) + + def testUnpackTag(self): + # Test field numbers that will require various varint sizes. + for expected_field_number in (1, 15, 16, 2047, 2048): + for expected_wire_type in range(6): # Highest-numbered wiretype is 5. + field_number, wire_type = wire_format.UnpackTag( + wire_format.PackTag(expected_field_number, expected_wire_type)) + self.assertEqual(expected_field_number, field_number) + self.assertEqual(expected_wire_type, wire_type) + + self.assertRaises(TypeError, wire_format.UnpackTag, None) + self.assertRaises(TypeError, wire_format.UnpackTag, 'abc') + self.assertRaises(TypeError, wire_format.UnpackTag, 0.0) + self.assertRaises(TypeError, wire_format.UnpackTag, object()) + + def testZigZagEncode(self): + Z = wire_format.ZigZagEncode + self.assertEqual(0, Z(0)) + self.assertEqual(1, Z(-1)) + self.assertEqual(2, Z(1)) + self.assertEqual(3, Z(-2)) + self.assertEqual(4, Z(2)) + self.assertEqual(0xfffffffe, Z(0x7fffffff)) + self.assertEqual(0xffffffff, Z(-0x80000000)) + self.assertEqual(0xfffffffffffffffe, Z(0x7fffffffffffffff)) + self.assertEqual(0xffffffffffffffff, Z(-0x8000000000000000)) + + self.assertRaises(TypeError, Z, None) + self.assertRaises(TypeError, Z, 'abcd') + self.assertRaises(TypeError, Z, 0.0) + self.assertRaises(TypeError, Z, object()) + + def testZigZagDecode(self): + Z = wire_format.ZigZagDecode + self.assertEqual(0, Z(0)) + self.assertEqual(-1, Z(1)) + self.assertEqual(1, Z(2)) + self.assertEqual(-2, Z(3)) + self.assertEqual(2, Z(4)) + self.assertEqual(0x7fffffff, Z(0xfffffffe)) + self.assertEqual(-0x80000000, Z(0xffffffff)) + self.assertEqual(0x7fffffffffffffff, Z(0xfffffffffffffffe)) + self.assertEqual(-0x8000000000000000, Z(0xffffffffffffffff)) + + self.assertRaises(TypeError, Z, None) + self.assertRaises(TypeError, Z, 'abcd') + self.assertRaises(TypeError, Z, 0.0) + self.assertRaises(TypeError, Z, object()) + + def NumericByteSizeTestHelper(self, byte_size_fn, value, expected_value_size): + # Use field numbers that cause various byte sizes for the tag information. + for field_number, tag_bytes in ((15, 1), (16, 2), (2047, 2), (2048, 3)): + expected_size = expected_value_size + tag_bytes + actual_size = byte_size_fn(field_number, value) + self.assertEqual(expected_size, actual_size, + 'byte_size_fn: %s, field_number: %d, value: %r\n' + 'Expected: %d, Actual: %d'% ( + byte_size_fn, field_number, value, expected_size, actual_size)) + + def testByteSizeFunctions(self): + # Test all numeric *ByteSize() functions. + NUMERIC_ARGS = [ + # Int32ByteSize(). + [wire_format.Int32ByteSize, 0, 1], + [wire_format.Int32ByteSize, 127, 1], + [wire_format.Int32ByteSize, 128, 2], + [wire_format.Int32ByteSize, -1, 10], + # Int64ByteSize(). + [wire_format.Int64ByteSize, 0, 1], + [wire_format.Int64ByteSize, 127, 1], + [wire_format.Int64ByteSize, 128, 2], + [wire_format.Int64ByteSize, -1, 10], + # UInt32ByteSize(). + [wire_format.UInt32ByteSize, 0, 1], + [wire_format.UInt32ByteSize, 127, 1], + [wire_format.UInt32ByteSize, 128, 2], + [wire_format.UInt32ByteSize, wire_format.UINT32_MAX, 5], + # UInt64ByteSize(). + [wire_format.UInt64ByteSize, 0, 1], + [wire_format.UInt64ByteSize, 127, 1], + [wire_format.UInt64ByteSize, 128, 2], + [wire_format.UInt64ByteSize, wire_format.UINT64_MAX, 10], + # SInt32ByteSize(). + [wire_format.SInt32ByteSize, 0, 1], + [wire_format.SInt32ByteSize, -1, 1], + [wire_format.SInt32ByteSize, 1, 1], + [wire_format.SInt32ByteSize, -63, 1], + [wire_format.SInt32ByteSize, 63, 1], + [wire_format.SInt32ByteSize, -64, 1], + [wire_format.SInt32ByteSize, 64, 2], + # SInt64ByteSize(). + [wire_format.SInt64ByteSize, 0, 1], + [wire_format.SInt64ByteSize, -1, 1], + [wire_format.SInt64ByteSize, 1, 1], + [wire_format.SInt64ByteSize, -63, 1], + [wire_format.SInt64ByteSize, 63, 1], + [wire_format.SInt64ByteSize, -64, 1], + [wire_format.SInt64ByteSize, 64, 2], + # Fixed32ByteSize(). + [wire_format.Fixed32ByteSize, 0, 4], + [wire_format.Fixed32ByteSize, wire_format.UINT32_MAX, 4], + # Fixed64ByteSize(). + [wire_format.Fixed64ByteSize, 0, 8], + [wire_format.Fixed64ByteSize, wire_format.UINT64_MAX, 8], + # SFixed32ByteSize(). + [wire_format.SFixed32ByteSize, 0, 4], + [wire_format.SFixed32ByteSize, wire_format.INT32_MIN, 4], + [wire_format.SFixed32ByteSize, wire_format.INT32_MAX, 4], + # SFixed64ByteSize(). + [wire_format.SFixed64ByteSize, 0, 8], + [wire_format.SFixed64ByteSize, wire_format.INT64_MIN, 8], + [wire_format.SFixed64ByteSize, wire_format.INT64_MAX, 8], + # FloatByteSize(). + [wire_format.FloatByteSize, 0.0, 4], + [wire_format.FloatByteSize, 1000000000.0, 4], + [wire_format.FloatByteSize, -1000000000.0, 4], + # DoubleByteSize(). + [wire_format.DoubleByteSize, 0.0, 8], + [wire_format.DoubleByteSize, 1000000000.0, 8], + [wire_format.DoubleByteSize, -1000000000.0, 8], + # BoolByteSize(). + [wire_format.BoolByteSize, False, 1], + [wire_format.BoolByteSize, True, 1], + # EnumByteSize(). + [wire_format.EnumByteSize, 0, 1], + [wire_format.EnumByteSize, 127, 1], + [wire_format.EnumByteSize, 128, 2], + [wire_format.EnumByteSize, wire_format.UINT32_MAX, 5], + ] + for args in NUMERIC_ARGS: + self.NumericByteSizeTestHelper(*args) + + # Test strings and bytes. + for byte_size_fn in (wire_format.StringByteSize, wire_format.BytesByteSize): + # 1 byte for tag, 1 byte for length, 3 bytes for contents. + self.assertEqual(5, byte_size_fn(10, 'abc')) + # 2 bytes for tag, 1 byte for length, 3 bytes for contents. + self.assertEqual(6, byte_size_fn(16, 'abc')) + # 2 bytes for tag, 2 bytes for length, 128 bytes for contents. + self.assertEqual(132, byte_size_fn(16, 'a' * 128)) + + # Test UTF-8 string byte size calculation. + # 1 byte for tag, 1 byte for length, 8 bytes for content. + self.assertEqual(10, wire_format.StringByteSize( + 5, b'\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'.decode('utf-8'))) + + class MockMessage(object): + def __init__(self, byte_size): + self.byte_size = byte_size + def ByteSize(self): + return self.byte_size + + message_byte_size = 10 + mock_message = MockMessage(byte_size=message_byte_size) + # Test groups. + # (2 * 1) bytes for begin and end tags, plus message_byte_size. + self.assertEqual(2 + message_byte_size, + wire_format.GroupByteSize(1, mock_message)) + # (2 * 2) bytes for begin and end tags, plus message_byte_size. + self.assertEqual(4 + message_byte_size, + wire_format.GroupByteSize(16, mock_message)) + + # Test messages. + # 1 byte for tag, plus 1 byte for length, plus contents. + self.assertEqual(2 + mock_message.byte_size, + wire_format.MessageByteSize(1, mock_message)) + # 2 bytes for tag, plus 1 byte for length, plus contents. + self.assertEqual(3 + mock_message.byte_size, + wire_format.MessageByteSize(16, mock_message)) + # 2 bytes for tag, plus 2 bytes for length, plus contents. + mock_message.byte_size = 128 + self.assertEqual(4 + mock_message.byte_size, + wire_format.MessageByteSize(16, mock_message)) + + + # Test message set item byte size. + # 4 bytes for tags, plus 1 byte for length, plus 1 byte for type_id, + # plus contents. + mock_message.byte_size = 10 + self.assertEqual(mock_message.byte_size + 6, + wire_format.MessageSetItemByteSize(1, mock_message)) + + # 4 bytes for tags, plus 2 bytes for length, plus 1 byte for type_id, + # plus contents. + mock_message.byte_size = 128 + self.assertEqual(mock_message.byte_size + 7, + wire_format.MessageSetItemByteSize(1, mock_message)) + + # 4 bytes for tags, plus 2 bytes for length, plus 2 byte for type_id, + # plus contents. + self.assertEqual(mock_message.byte_size + 8, + wire_format.MessageSetItemByteSize(128, mock_message)) + + # Too-long varint. + self.assertRaises(message.EncodeError, + wire_format.UInt64ByteSize, 1, 1 << 128) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/lib/python3.7/site-packages/google/protobuf/json_format.py b/venv/lib/python3.7/site-packages/google/protobuf/json_format.py new file mode 100644 index 0000000..8d338d3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/json_format.py @@ -0,0 +1,785 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains routines for printing protocol messages in JSON format. + +Simple usage example: + + # Create a proto object and serialize it to a json format string. + message = my_proto_pb2.MyMessage(foo='bar') + json_string = json_format.MessageToJson(message) + + # Parse a json format string to proto object. + message = json_format.Parse(json_string, my_proto_pb2.MyMessage()) +""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +# pylint: disable=g-statement-before-imports,g-import-not-at-top +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # PY26 +# pylint: enable=g-statement-before-imports,g-import-not-at-top + +import base64 +import json +import math + +from operator import methodcaller + +import re +import sys + +import six + +from google.protobuf import descriptor +from google.protobuf import symbol_database + + +_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' +_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32, + descriptor.FieldDescriptor.CPPTYPE_UINT32, + descriptor.FieldDescriptor.CPPTYPE_INT64, + descriptor.FieldDescriptor.CPPTYPE_UINT64]) +_INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64, + descriptor.FieldDescriptor.CPPTYPE_UINT64]) +_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, + descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) +_INFINITY = 'Infinity' +_NEG_INFINITY = '-Infinity' +_NAN = 'NaN' + +_UNPAIRED_SURROGATE_PATTERN = re.compile(six.u( + r'[\ud800-\udbff](?![\udc00-\udfff])|(?\n\nm_sfixed32\x18\t \x03(\x0b\x32*.protobuf_unittest.TestMaps.MSfixed32Entry\x12>\n\nm_sfixed64\x18\n \x03(\x0b\x32*.protobuf_unittest.TestMaps.MSfixed64Entry\x12\x36\n\x06m_bool\x18\x0b \x03(\x0b\x32&.protobuf_unittest.TestMaps.MBoolEntry\x12:\n\x08m_string\x18\x0c \x03(\x0b\x32(.protobuf_unittest.TestMaps.MStringEntry\x1aO\n\x0bMInt32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aO\n\x0bMInt64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMUint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMUint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMSint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMSint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aQ\n\rMFixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aQ\n\rMFixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aR\n\x0eMSfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aR\n\x0eMSfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aN\n\nMBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\"<\n\x12TestSubmessageMaps\x12&\n\x01m\x18\x01 \x01(\x0b\x32\x1b.protobuf_unittest.TestMaps*Z\n\rProto2MapEnum\x12\x17\n\x13PROTO2_MAP_ENUM_FOO\x10\x00\x12\x17\n\x13PROTO2_MAP_ENUM_BAR\x10\x01\x12\x17\n\x13PROTO2_MAP_ENUM_BAZ\x10\x02*\x86\x01\n\x16Proto2MapEnumPlusExtra\x12\x19\n\x15\x45_PROTO2_MAP_ENUM_FOO\x10\x00\x12\x19\n\x15\x45_PROTO2_MAP_ENUM_BAR\x10\x01\x12\x19\n\x15\x45_PROTO2_MAP_ENUM_BAZ\x10\x02\x12\x1b\n\x17\x45_PROTO2_MAP_ENUM_EXTRA\x10\x03\x42\x03\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,]) + +_PROTO2MAPENUM = _descriptor.EnumDescriptor( + name='Proto2MapEnum', + full_name='protobuf_unittest.Proto2MapEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='PROTO2_MAP_ENUM_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='PROTO2_MAP_ENUM_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='PROTO2_MAP_ENUM_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2946, + serialized_end=3036, +) +_sym_db.RegisterEnumDescriptor(_PROTO2MAPENUM) + +Proto2MapEnum = enum_type_wrapper.EnumTypeWrapper(_PROTO2MAPENUM) +_PROTO2MAPENUMPLUSEXTRA = _descriptor.EnumDescriptor( + name='Proto2MapEnumPlusExtra', + full_name='protobuf_unittest.Proto2MapEnumPlusExtra', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_BAZ', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_EXTRA', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3039, + serialized_end=3173, +) +_sym_db.RegisterEnumDescriptor(_PROTO2MAPENUMPLUSEXTRA) + +Proto2MapEnumPlusExtra = enum_type_wrapper.EnumTypeWrapper(_PROTO2MAPENUMPLUSEXTRA) +PROTO2_MAP_ENUM_FOO = 0 +PROTO2_MAP_ENUM_BAR = 1 +PROTO2_MAP_ENUM_BAZ = 2 +E_PROTO2_MAP_ENUM_FOO = 0 +E_PROTO2_MAP_ENUM_BAR = 1 +E_PROTO2_MAP_ENUM_BAZ = 2 +E_PROTO2_MAP_ENUM_EXTRA = 3 + + + +_TESTENUMMAP_KNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='KnownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMap.KnownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMap.KnownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMap.KnownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=275, + serialized_end=361, +) + +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='UnknownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMap.UnknownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMap.UnknownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMap.UnknownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=363, + serialized_end=451, +) + +_TESTENUMMAP = _descriptor.Descriptor( + name='TestEnumMap', + full_name='protobuf_unittest.TestEnumMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='known_map_field', full_name='protobuf_unittest.TestEnumMap.known_map_field', index=0, + number=101, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unknown_map_field', full_name='protobuf_unittest.TestEnumMap.unknown_map_field', index=1, + number=102, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTENUMMAP_KNOWNMAPFIELDENTRY, _TESTENUMMAP_UNKNOWNMAPFIELDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=104, + serialized_end=451, +) + + +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='KnownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=652, + serialized_end=747, +) + +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='UnknownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=749, + serialized_end=846, +) + +_TESTENUMMAPPLUSEXTRA = _descriptor.Descriptor( + name='TestEnumMapPlusExtra', + full_name='protobuf_unittest.TestEnumMapPlusExtra', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='known_map_field', full_name='protobuf_unittest.TestEnumMapPlusExtra.known_map_field', index=0, + number=101, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unknown_map_field', full_name='protobuf_unittest.TestEnumMapPlusExtra.unknown_map_field', index=1, + number=102, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY, _TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=454, + serialized_end=846, +) + + +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY = _descriptor.Descriptor( + name='ImportEnumAmpEntry', + full_name='protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=952, + serialized_end=1048, +) + +_TESTIMPORTENUMMAP = _descriptor.Descriptor( + name='TestImportEnumMap', + full_name='protobuf_unittest.TestImportEnumMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='import_enum_amp', full_name='protobuf_unittest.TestImportEnumMap.import_enum_amp', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=849, + serialized_end=1048, +) + + +_TESTINTINTMAP_MENTRY = _descriptor.Descriptor( + name='MEntry', + full_name='protobuf_unittest.TestIntIntMap.MEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestIntIntMap.MEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestIntIntMap.MEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1119, + serialized_end=1159, +) + +_TESTINTINTMAP = _descriptor.Descriptor( + name='TestIntIntMap', + full_name='protobuf_unittest.TestIntIntMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='m', full_name='protobuf_unittest.TestIntIntMap.m', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTINTINTMAP_MENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1050, + serialized_end=1159, +) + + +_TESTMAPS_MINT32ENTRY = _descriptor.Descriptor( + name='MInt32Entry', + full_name='protobuf_unittest.TestMaps.MInt32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MInt32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MInt32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1898, + serialized_end=1977, +) + +_TESTMAPS_MINT64ENTRY = _descriptor.Descriptor( + name='MInt64Entry', + full_name='protobuf_unittest.TestMaps.MInt64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MInt64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MInt64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1979, + serialized_end=2058, +) + +_TESTMAPS_MUINT32ENTRY = _descriptor.Descriptor( + name='MUint32Entry', + full_name='protobuf_unittest.TestMaps.MUint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MUint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MUint32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2060, + serialized_end=2140, +) + +_TESTMAPS_MUINT64ENTRY = _descriptor.Descriptor( + name='MUint64Entry', + full_name='protobuf_unittest.TestMaps.MUint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MUint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MUint64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2142, + serialized_end=2222, +) + +_TESTMAPS_MSINT32ENTRY = _descriptor.Descriptor( + name='MSint32Entry', + full_name='protobuf_unittest.TestMaps.MSint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSint32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2224, + serialized_end=2304, +) + +_TESTMAPS_MSINT64ENTRY = _descriptor.Descriptor( + name='MSint64Entry', + full_name='protobuf_unittest.TestMaps.MSint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSint64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2306, + serialized_end=2386, +) + +_TESTMAPS_MFIXED32ENTRY = _descriptor.Descriptor( + name='MFixed32Entry', + full_name='protobuf_unittest.TestMaps.MFixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MFixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MFixed32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2388, + serialized_end=2469, +) + +_TESTMAPS_MFIXED64ENTRY = _descriptor.Descriptor( + name='MFixed64Entry', + full_name='protobuf_unittest.TestMaps.MFixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MFixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MFixed64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2471, + serialized_end=2552, +) + +_TESTMAPS_MSFIXED32ENTRY = _descriptor.Descriptor( + name='MSfixed32Entry', + full_name='protobuf_unittest.TestMaps.MSfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSfixed32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2554, + serialized_end=2636, +) + +_TESTMAPS_MSFIXED64ENTRY = _descriptor.Descriptor( + name='MSfixed64Entry', + full_name='protobuf_unittest.TestMaps.MSfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSfixed64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2638, + serialized_end=2720, +) + +_TESTMAPS_MBOOLENTRY = _descriptor.Descriptor( + name='MBoolEntry', + full_name='protobuf_unittest.TestMaps.MBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MBoolEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2722, + serialized_end=2800, +) + +_TESTMAPS_MSTRINGENTRY = _descriptor.Descriptor( + name='MStringEntry', + full_name='protobuf_unittest.TestMaps.MStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MStringEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2802, + serialized_end=2882, +) + +_TESTMAPS = _descriptor.Descriptor( + name='TestMaps', + full_name='protobuf_unittest.TestMaps', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='m_int32', full_name='protobuf_unittest.TestMaps.m_int32', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_int64', full_name='protobuf_unittest.TestMaps.m_int64', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_uint32', full_name='protobuf_unittest.TestMaps.m_uint32', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_uint64', full_name='protobuf_unittest.TestMaps.m_uint64', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sint32', full_name='protobuf_unittest.TestMaps.m_sint32', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sint64', full_name='protobuf_unittest.TestMaps.m_sint64', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_fixed32', full_name='protobuf_unittest.TestMaps.m_fixed32', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_fixed64', full_name='protobuf_unittest.TestMaps.m_fixed64', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sfixed32', full_name='protobuf_unittest.TestMaps.m_sfixed32', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sfixed64', full_name='protobuf_unittest.TestMaps.m_sfixed64', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_bool', full_name='protobuf_unittest.TestMaps.m_bool', index=10, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_string', full_name='protobuf_unittest.TestMaps.m_string', index=11, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMAPS_MINT32ENTRY, _TESTMAPS_MINT64ENTRY, _TESTMAPS_MUINT32ENTRY, _TESTMAPS_MUINT64ENTRY, _TESTMAPS_MSINT32ENTRY, _TESTMAPS_MSINT64ENTRY, _TESTMAPS_MFIXED32ENTRY, _TESTMAPS_MFIXED64ENTRY, _TESTMAPS_MSFIXED32ENTRY, _TESTMAPS_MSFIXED64ENTRY, _TESTMAPS_MBOOLENTRY, _TESTMAPS_MSTRINGENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1162, + serialized_end=2882, +) + + +_TESTSUBMESSAGEMAPS = _descriptor.Descriptor( + name='TestSubmessageMaps', + full_name='protobuf_unittest.TestSubmessageMaps', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='m', full_name='protobuf_unittest.TestSubmessageMaps.m', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2884, + serialized_end=2944, +) + +_TESTENUMMAP_KNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUM +_TESTENUMMAP_KNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAP +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUM +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAP +_TESTENUMMAP.fields_by_name['known_map_field'].message_type = _TESTENUMMAP_KNOWNMAPFIELDENTRY +_TESTENUMMAP.fields_by_name['unknown_map_field'].message_type = _TESTENUMMAP_UNKNOWNMAPFIELDENTRY +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUMPLUSEXTRA +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAPPLUSEXTRA +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUMPLUSEXTRA +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAPPLUSEXTRA +_TESTENUMMAPPLUSEXTRA.fields_by_name['known_map_field'].message_type = _TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY +_TESTENUMMAPPLUSEXTRA.fields_by_name['unknown_map_field'].message_type = _TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY.fields_by_name['value'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUMFORMAP +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY.containing_type = _TESTIMPORTENUMMAP +_TESTIMPORTENUMMAP.fields_by_name['import_enum_amp'].message_type = _TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY +_TESTINTINTMAP_MENTRY.containing_type = _TESTINTINTMAP +_TESTINTINTMAP.fields_by_name['m'].message_type = _TESTINTINTMAP_MENTRY +_TESTMAPS_MINT32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MINT32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MINT64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MINT64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MUINT32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MUINT32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MUINT64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MUINT64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSINT32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSINT32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSINT64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSINT64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MFIXED32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MFIXED32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MFIXED64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MFIXED64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSFIXED32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSFIXED32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSFIXED64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSFIXED64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MBOOLENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MBOOLENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSTRINGENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSTRINGENTRY.containing_type = _TESTMAPS +_TESTMAPS.fields_by_name['m_int32'].message_type = _TESTMAPS_MINT32ENTRY +_TESTMAPS.fields_by_name['m_int64'].message_type = _TESTMAPS_MINT64ENTRY +_TESTMAPS.fields_by_name['m_uint32'].message_type = _TESTMAPS_MUINT32ENTRY +_TESTMAPS.fields_by_name['m_uint64'].message_type = _TESTMAPS_MUINT64ENTRY +_TESTMAPS.fields_by_name['m_sint32'].message_type = _TESTMAPS_MSINT32ENTRY +_TESTMAPS.fields_by_name['m_sint64'].message_type = _TESTMAPS_MSINT64ENTRY +_TESTMAPS.fields_by_name['m_fixed32'].message_type = _TESTMAPS_MFIXED32ENTRY +_TESTMAPS.fields_by_name['m_fixed64'].message_type = _TESTMAPS_MFIXED64ENTRY +_TESTMAPS.fields_by_name['m_sfixed32'].message_type = _TESTMAPS_MSFIXED32ENTRY +_TESTMAPS.fields_by_name['m_sfixed64'].message_type = _TESTMAPS_MSFIXED64ENTRY +_TESTMAPS.fields_by_name['m_bool'].message_type = _TESTMAPS_MBOOLENTRY +_TESTMAPS.fields_by_name['m_string'].message_type = _TESTMAPS_MSTRINGENTRY +_TESTSUBMESSAGEMAPS.fields_by_name['m'].message_type = _TESTMAPS +DESCRIPTOR.message_types_by_name['TestEnumMap'] = _TESTENUMMAP +DESCRIPTOR.message_types_by_name['TestEnumMapPlusExtra'] = _TESTENUMMAPPLUSEXTRA +DESCRIPTOR.message_types_by_name['TestImportEnumMap'] = _TESTIMPORTENUMMAP +DESCRIPTOR.message_types_by_name['TestIntIntMap'] = _TESTINTINTMAP +DESCRIPTOR.message_types_by_name['TestMaps'] = _TESTMAPS +DESCRIPTOR.message_types_by_name['TestSubmessageMaps'] = _TESTSUBMESSAGEMAPS +DESCRIPTOR.enum_types_by_name['Proto2MapEnum'] = _PROTO2MAPENUM +DESCRIPTOR.enum_types_by_name['Proto2MapEnumPlusExtra'] = _PROTO2MAPENUMPLUSEXTRA +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestEnumMap = _reflection.GeneratedProtocolMessageType('TestEnumMap', (_message.Message,), dict( + + KnownMapFieldEntry = _reflection.GeneratedProtocolMessageType('KnownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAP_KNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMap.KnownMapFieldEntry) + )) + , + + UnknownMapFieldEntry = _reflection.GeneratedProtocolMessageType('UnknownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAP_UNKNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMap.UnknownMapFieldEntry) + )) + , + DESCRIPTOR = _TESTENUMMAP, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMap) + )) +_sym_db.RegisterMessage(TestEnumMap) +_sym_db.RegisterMessage(TestEnumMap.KnownMapFieldEntry) +_sym_db.RegisterMessage(TestEnumMap.UnknownMapFieldEntry) + +TestEnumMapPlusExtra = _reflection.GeneratedProtocolMessageType('TestEnumMapPlusExtra', (_message.Message,), dict( + + KnownMapFieldEntry = _reflection.GeneratedProtocolMessageType('KnownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry) + )) + , + + UnknownMapFieldEntry = _reflection.GeneratedProtocolMessageType('UnknownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry) + )) + , + DESCRIPTOR = _TESTENUMMAPPLUSEXTRA, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMapPlusExtra) + )) +_sym_db.RegisterMessage(TestEnumMapPlusExtra) +_sym_db.RegisterMessage(TestEnumMapPlusExtra.KnownMapFieldEntry) +_sym_db.RegisterMessage(TestEnumMapPlusExtra.UnknownMapFieldEntry) + +TestImportEnumMap = _reflection.GeneratedProtocolMessageType('TestImportEnumMap', (_message.Message,), dict( + + ImportEnumAmpEntry = _reflection.GeneratedProtocolMessageType('ImportEnumAmpEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry) + )) + , + DESCRIPTOR = _TESTIMPORTENUMMAP, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestImportEnumMap) + )) +_sym_db.RegisterMessage(TestImportEnumMap) +_sym_db.RegisterMessage(TestImportEnumMap.ImportEnumAmpEntry) + +TestIntIntMap = _reflection.GeneratedProtocolMessageType('TestIntIntMap', (_message.Message,), dict( + + MEntry = _reflection.GeneratedProtocolMessageType('MEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTINTINTMAP_MENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIntIntMap.MEntry) + )) + , + DESCRIPTOR = _TESTINTINTMAP, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIntIntMap) + )) +_sym_db.RegisterMessage(TestIntIntMap) +_sym_db.RegisterMessage(TestIntIntMap.MEntry) + +TestMaps = _reflection.GeneratedProtocolMessageType('TestMaps', (_message.Message,), dict( + + MInt32Entry = _reflection.GeneratedProtocolMessageType('MInt32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MINT32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MInt32Entry) + )) + , + + MInt64Entry = _reflection.GeneratedProtocolMessageType('MInt64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MINT64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MInt64Entry) + )) + , + + MUint32Entry = _reflection.GeneratedProtocolMessageType('MUint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MUINT32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MUint32Entry) + )) + , + + MUint64Entry = _reflection.GeneratedProtocolMessageType('MUint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MUINT64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MUint64Entry) + )) + , + + MSint32Entry = _reflection.GeneratedProtocolMessageType('MSint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSINT32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSint32Entry) + )) + , + + MSint64Entry = _reflection.GeneratedProtocolMessageType('MSint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSINT64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSint64Entry) + )) + , + + MFixed32Entry = _reflection.GeneratedProtocolMessageType('MFixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MFIXED32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MFixed32Entry) + )) + , + + MFixed64Entry = _reflection.GeneratedProtocolMessageType('MFixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MFIXED64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MFixed64Entry) + )) + , + + MSfixed32Entry = _reflection.GeneratedProtocolMessageType('MSfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSFIXED32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSfixed32Entry) + )) + , + + MSfixed64Entry = _reflection.GeneratedProtocolMessageType('MSfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSFIXED64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSfixed64Entry) + )) + , + + MBoolEntry = _reflection.GeneratedProtocolMessageType('MBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MBOOLENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MBoolEntry) + )) + , + + MStringEntry = _reflection.GeneratedProtocolMessageType('MStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSTRINGENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MStringEntry) + )) + , + DESCRIPTOR = _TESTMAPS, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps) + )) +_sym_db.RegisterMessage(TestMaps) +_sym_db.RegisterMessage(TestMaps.MInt32Entry) +_sym_db.RegisterMessage(TestMaps.MInt64Entry) +_sym_db.RegisterMessage(TestMaps.MUint32Entry) +_sym_db.RegisterMessage(TestMaps.MUint64Entry) +_sym_db.RegisterMessage(TestMaps.MSint32Entry) +_sym_db.RegisterMessage(TestMaps.MSint64Entry) +_sym_db.RegisterMessage(TestMaps.MFixed32Entry) +_sym_db.RegisterMessage(TestMaps.MFixed64Entry) +_sym_db.RegisterMessage(TestMaps.MSfixed32Entry) +_sym_db.RegisterMessage(TestMaps.MSfixed64Entry) +_sym_db.RegisterMessage(TestMaps.MBoolEntry) +_sym_db.RegisterMessage(TestMaps.MStringEntry) + +TestSubmessageMaps = _reflection.GeneratedProtocolMessageType('TestSubmessageMaps', (_message.Message,), dict( + DESCRIPTOR = _TESTSUBMESSAGEMAPS, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSubmessageMaps) + )) +_sym_db.RegisterMessage(TestSubmessageMaps) + + +DESCRIPTOR._options = None +_TESTENUMMAP_KNOWNMAPFIELDENTRY._options = None +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY._options = None +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY._options = None +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY._options = None +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY._options = None +_TESTINTINTMAP_MENTRY._options = None +_TESTMAPS_MINT32ENTRY._options = None +_TESTMAPS_MINT64ENTRY._options = None +_TESTMAPS_MUINT32ENTRY._options = None +_TESTMAPS_MUINT64ENTRY._options = None +_TESTMAPS_MSINT32ENTRY._options = None +_TESTMAPS_MSINT64ENTRY._options = None +_TESTMAPS_MFIXED32ENTRY._options = None +_TESTMAPS_MFIXED64ENTRY._options = None +_TESTMAPS_MSFIXED32ENTRY._options = None +_TESTMAPS_MSFIXED64ENTRY._options = None +_TESTMAPS_MBOOLENTRY._options = None +_TESTMAPS_MSTRINGENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/map_unittest_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/map_unittest_pb2.py new file mode 100644 index 0000000..af1eca0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/map_unittest_pb2.py @@ -0,0 +1,2813 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/map_unittest.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_pb2 as google_dot_protobuf_dot_unittest__pb2 +from google.protobuf import unittest_no_arena_pb2 as google_dot_protobuf_dot_unittest__no__arena__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/map_unittest.proto', + package='protobuf_unittest', + syntax='proto3', + serialized_options=_b('\370\001\001'), + serialized_pb=_b('\n\"google/protobuf/map_unittest.proto\x12\x11protobuf_unittest\x1a\x1egoogle/protobuf/unittest.proto\x1a\'google/protobuf/unittest_no_arena.proto\"\xff\x14\n\x07TestMap\x12\x46\n\x0fmap_int32_int32\x18\x01 \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt32Int32Entry\x12\x46\n\x0fmap_int64_int64\x18\x02 \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt64Int64Entry\x12J\n\x11map_uint32_uint32\x18\x03 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapUint32Uint32Entry\x12J\n\x11map_uint64_uint64\x18\x04 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapUint64Uint64Entry\x12J\n\x11map_sint32_sint32\x18\x05 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapSint32Sint32Entry\x12J\n\x11map_sint64_sint64\x18\x06 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapSint64Sint64Entry\x12N\n\x13map_fixed32_fixed32\x18\x07 \x03(\x0b\x32\x31.protobuf_unittest.TestMap.MapFixed32Fixed32Entry\x12N\n\x13map_fixed64_fixed64\x18\x08 \x03(\x0b\x32\x31.protobuf_unittest.TestMap.MapFixed64Fixed64Entry\x12R\n\x15map_sfixed32_sfixed32\x18\t \x03(\x0b\x32\x33.protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry\x12R\n\x15map_sfixed64_sfixed64\x18\n \x03(\x0b\x32\x33.protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry\x12\x46\n\x0fmap_int32_float\x18\x0b \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt32FloatEntry\x12H\n\x10map_int32_double\x18\x0c \x03(\x0b\x32..protobuf_unittest.TestMap.MapInt32DoubleEntry\x12\x42\n\rmap_bool_bool\x18\r \x03(\x0b\x32+.protobuf_unittest.TestMap.MapBoolBoolEntry\x12J\n\x11map_string_string\x18\x0e \x03(\x0b\x32/.protobuf_unittest.TestMap.MapStringStringEntry\x12\x46\n\x0fmap_int32_bytes\x18\x0f \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt32BytesEntry\x12\x44\n\x0emap_int32_enum\x18\x10 \x03(\x0b\x32,.protobuf_unittest.TestMap.MapInt32EnumEntry\x12Y\n\x19map_int32_foreign_message\x18\x11 \x03(\x0b\x32\x36.protobuf_unittest.TestMap.MapInt32ForeignMessageEntry\x12[\n\x1amap_string_foreign_message\x18\x12 \x03(\x0b\x32\x37.protobuf_unittest.TestMap.MapStringForeignMessageEntry\x12M\n\x13map_int32_all_types\x18\x13 \x03(\x0b\x32\x30.protobuf_unittest.TestMap.MapInt32AllTypesEntry\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12MapInt32BytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1aO\n\x11MapInt32EnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12)\n\x05value\x18\x02 \x01(\x0e\x32\x1a.protobuf_unittest.MapEnum:\x02\x38\x01\x1a`\n\x1bMapInt32ForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:\x02\x38\x01\x1a\x61\n\x1cMapStringForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:\x02\x38\x01\x1aX\n\x15MapInt32AllTypesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes:\x02\x38\x01\"A\n\x11TestMapSubmessage\x12,\n\x08test_map\x18\x01 \x01(\x0b\x32\x1a.protobuf_unittest.TestMap\"\xbc\x01\n\x0eTestMessageMap\x12Q\n\x11map_int32_message\x18\x01 \x03(\x0b\x32\x36.protobuf_unittest.TestMessageMap.MapInt32MessageEntry\x1aW\n\x14MapInt32MessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes:\x02\x38\x01\"\xe3\x01\n\x0fTestSameTypeMap\x12:\n\x04map1\x18\x01 \x03(\x0b\x32,.protobuf_unittest.TestSameTypeMap.Map1Entry\x12:\n\x04map2\x18\x02 \x03(\x0b\x32,.protobuf_unittest.TestSameTypeMap.Map2Entry\x1a+\n\tMap1Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tMap2Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb6\x01\n\x16TestRequiredMessageMap\x12J\n\tmap_field\x18\x01 \x03(\x0b\x32\x37.protobuf_unittest.TestRequiredMessageMap.MapFieldEntry\x1aP\n\rMapFieldEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired:\x02\x38\x01\"\xd2\x14\n\x0cTestArenaMap\x12K\n\x0fmap_int32_int32\x18\x01 \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt32Int32Entry\x12K\n\x0fmap_int64_int64\x18\x02 \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt64Int64Entry\x12O\n\x11map_uint32_uint32\x18\x03 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapUint32Uint32Entry\x12O\n\x11map_uint64_uint64\x18\x04 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapUint64Uint64Entry\x12O\n\x11map_sint32_sint32\x18\x05 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapSint32Sint32Entry\x12O\n\x11map_sint64_sint64\x18\x06 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapSint64Sint64Entry\x12S\n\x13map_fixed32_fixed32\x18\x07 \x03(\x0b\x32\x36.protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry\x12S\n\x13map_fixed64_fixed64\x18\x08 \x03(\x0b\x32\x36.protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry\x12W\n\x15map_sfixed32_sfixed32\x18\t \x03(\x0b\x32\x38.protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry\x12W\n\x15map_sfixed64_sfixed64\x18\n \x03(\x0b\x32\x38.protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry\x12K\n\x0fmap_int32_float\x18\x0b \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt32FloatEntry\x12M\n\x10map_int32_double\x18\x0c \x03(\x0b\x32\x33.protobuf_unittest.TestArenaMap.MapInt32DoubleEntry\x12G\n\rmap_bool_bool\x18\r \x03(\x0b\x32\x30.protobuf_unittest.TestArenaMap.MapBoolBoolEntry\x12O\n\x11map_string_string\x18\x0e \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapStringStringEntry\x12K\n\x0fmap_int32_bytes\x18\x0f \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt32BytesEntry\x12I\n\x0emap_int32_enum\x18\x10 \x03(\x0b\x32\x31.protobuf_unittest.TestArenaMap.MapInt32EnumEntry\x12^\n\x19map_int32_foreign_message\x18\x11 \x03(\x0b\x32;.protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry\x12n\n\"map_int32_foreign_message_no_arena\x18\x12 \x03(\x0b\x32\x42.protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12MapInt32BytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1aO\n\x11MapInt32EnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12)\n\x05value\x18\x02 \x01(\x0e\x32\x1a.protobuf_unittest.MapEnum:\x02\x38\x01\x1a`\n\x1bMapInt32ForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:\x02\x38\x01\x1ap\n\"MapInt32ForeignMessageNoArenaEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.protobuf_unittest_no_arena.ForeignMessage:\x02\x38\x01\"\xe4\x01\n\x1fMessageContainingEnumCalledType\x12J\n\x04type\x18\x01 \x03(\x0b\x32<.protobuf_unittest.MessageContainingEnumCalledType.TypeEntry\x1a_\n\tTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x41\n\x05value\x18\x02 \x01(\x0b\x32\x32.protobuf_unittest.MessageContainingEnumCalledType:\x02\x38\x01\"\x14\n\x04Type\x12\x0c\n\x08TYPE_FOO\x10\x00\"\x9d\x01\n\x1fMessageContainingMapCalledEntry\x12L\n\x05\x65ntry\x18\x01 \x03(\x0b\x32=.protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry\x1a,\n\nEntryEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xad\x01\n\x17TestRecursiveMapMessage\x12<\n\x01\x61\x18\x01 \x03(\x0b\x32\x31.protobuf_unittest.TestRecursiveMapMessage.AEntry\x1aT\n\x06\x41\x45ntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.protobuf_unittest.TestRecursiveMapMessage:\x02\x38\x01*?\n\x07MapEnum\x12\x10\n\x0cMAP_ENUM_FOO\x10\x00\x12\x10\n\x0cMAP_ENUM_BAR\x10\x01\x12\x10\n\x0cMAP_ENUM_BAZ\x10\x02\x42\x03\xf8\x01\x01\x62\x06proto3') + , + dependencies=[google_dot_protobuf_dot_unittest__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__no__arena__pb2.DESCRIPTOR,]) + +_MAPENUM = _descriptor.EnumDescriptor( + name='MapEnum', + full_name='protobuf_unittest.MapEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='MAP_ENUM_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MAP_ENUM_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MAP_ENUM_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6705, + serialized_end=6768, +) +_sym_db.RegisterEnumDescriptor(_MAPENUM) + +MapEnum = enum_type_wrapper.EnumTypeWrapper(_MAPENUM) +MAP_ENUM_FOO = 0 +MAP_ENUM_BAR = 1 +MAP_ENUM_BAZ = 2 + + +_MESSAGECONTAININGENUMCALLEDTYPE_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='protobuf_unittest.MessageContainingEnumCalledType.Type', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_FOO', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6347, + serialized_end=6367, +) +_sym_db.RegisterEnumDescriptor(_MESSAGECONTAININGENUMCALLEDTYPE_TYPE) + + +_TESTMAP_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_unittest.TestMap.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1613, + serialized_end=1665, +) + +_TESTMAP_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_unittest.TestMap.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1667, + serialized_end=1719, +) + +_TESTMAP_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_unittest.TestMap.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1721, + serialized_end=1775, +) + +_TESTMAP_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_unittest.TestMap.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1777, + serialized_end=1831, +) + +_TESTMAP_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_unittest.TestMap.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1833, + serialized_end=1887, +) + +_TESTMAP_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_unittest.TestMap.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1889, + serialized_end=1943, +) + +_TESTMAP_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_unittest.TestMap.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1945, + serialized_end=2001, +) + +_TESTMAP_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_unittest.TestMap.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2003, + serialized_end=2059, +) + +_TESTMAP_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2061, + serialized_end=2119, +) + +_TESTMAP_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2121, + serialized_end=2179, +) + +_TESTMAP_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_unittest.TestMap.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2181, + serialized_end=2233, +) + +_TESTMAP_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_unittest.TestMap.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2235, + serialized_end=2288, +) + +_TESTMAP_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_unittest.TestMap.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2290, + serialized_end=2340, +) + +_TESTMAP_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_unittest.TestMap.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2342, + serialized_end=2396, +) + +_TESTMAP_MAPINT32BYTESENTRY = _descriptor.Descriptor( + name='MapInt32BytesEntry', + full_name='protobuf_unittest.TestMap.MapInt32BytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32BytesEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32BytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2398, + serialized_end=2450, +) + +_TESTMAP_MAPINT32ENUMENTRY = _descriptor.Descriptor( + name='MapInt32EnumEntry', + full_name='protobuf_unittest.TestMap.MapInt32EnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32EnumEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32EnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2452, + serialized_end=2531, +) + +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapInt32ForeignMessageEntry', + full_name='protobuf_unittest.TestMap.MapInt32ForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2533, + serialized_end=2629, +) + +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringForeignMessageEntry', + full_name='protobuf_unittest.TestMap.MapStringForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapStringForeignMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapStringForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2631, + serialized_end=2728, +) + +_TESTMAP_MAPINT32ALLTYPESENTRY = _descriptor.Descriptor( + name='MapInt32AllTypesEntry', + full_name='protobuf_unittest.TestMap.MapInt32AllTypesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32AllTypesEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32AllTypesEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2730, + serialized_end=2818, +) + +_TESTMAP = _descriptor.Descriptor( + name='TestMap', + full_name='protobuf_unittest.TestMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_unittest.TestMap.map_int32_int32', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_unittest.TestMap.map_int64_int64', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_unittest.TestMap.map_uint32_uint32', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_unittest.TestMap.map_uint64_uint64', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_unittest.TestMap.map_sint32_sint32', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_unittest.TestMap.map_sint64_sint64', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_unittest.TestMap.map_fixed32_fixed32', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_unittest.TestMap.map_fixed64_fixed64', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_unittest.TestMap.map_sfixed32_sfixed32', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_unittest.TestMap.map_sfixed64_sfixed64', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_unittest.TestMap.map_int32_float', index=10, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_unittest.TestMap.map_int32_double', index=11, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_unittest.TestMap.map_bool_bool', index=12, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_unittest.TestMap.map_string_string', index=13, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_bytes', full_name='protobuf_unittest.TestMap.map_int32_bytes', index=14, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_enum', full_name='protobuf_unittest.TestMap.map_int32_enum', index=15, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_foreign_message', full_name='protobuf_unittest.TestMap.map_int32_foreign_message', index=16, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_message', full_name='protobuf_unittest.TestMap.map_string_foreign_message', index=17, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_all_types', full_name='protobuf_unittest.TestMap.map_int32_all_types', index=18, + number=19, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMAP_MAPINT32INT32ENTRY, _TESTMAP_MAPINT64INT64ENTRY, _TESTMAP_MAPUINT32UINT32ENTRY, _TESTMAP_MAPUINT64UINT64ENTRY, _TESTMAP_MAPSINT32SINT32ENTRY, _TESTMAP_MAPSINT64SINT64ENTRY, _TESTMAP_MAPFIXED32FIXED32ENTRY, _TESTMAP_MAPFIXED64FIXED64ENTRY, _TESTMAP_MAPSFIXED32SFIXED32ENTRY, _TESTMAP_MAPSFIXED64SFIXED64ENTRY, _TESTMAP_MAPINT32FLOATENTRY, _TESTMAP_MAPINT32DOUBLEENTRY, _TESTMAP_MAPBOOLBOOLENTRY, _TESTMAP_MAPSTRINGSTRINGENTRY, _TESTMAP_MAPINT32BYTESENTRY, _TESTMAP_MAPINT32ENUMENTRY, _TESTMAP_MAPINT32FOREIGNMESSAGEENTRY, _TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY, _TESTMAP_MAPINT32ALLTYPESENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=131, + serialized_end=2818, +) + + +_TESTMAPSUBMESSAGE = _descriptor.Descriptor( + name='TestMapSubmessage', + full_name='protobuf_unittest.TestMapSubmessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='test_map', full_name='protobuf_unittest.TestMapSubmessage.test_map', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2820, + serialized_end=2885, +) + + +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY = _descriptor.Descriptor( + name='MapInt32MessageEntry', + full_name='protobuf_unittest.TestMessageMap.MapInt32MessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMessageMap.MapInt32MessageEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMessageMap.MapInt32MessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2989, + serialized_end=3076, +) + +_TESTMESSAGEMAP = _descriptor.Descriptor( + name='TestMessageMap', + full_name='protobuf_unittest.TestMessageMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_int32_message', full_name='protobuf_unittest.TestMessageMap.map_int32_message', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2888, + serialized_end=3076, +) + + +_TESTSAMETYPEMAP_MAP1ENTRY = _descriptor.Descriptor( + name='Map1Entry', + full_name='protobuf_unittest.TestSameTypeMap.Map1Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestSameTypeMap.Map1Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestSameTypeMap.Map1Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3218, + serialized_end=3261, +) + +_TESTSAMETYPEMAP_MAP2ENTRY = _descriptor.Descriptor( + name='Map2Entry', + full_name='protobuf_unittest.TestSameTypeMap.Map2Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestSameTypeMap.Map2Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestSameTypeMap.Map2Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3263, + serialized_end=3306, +) + +_TESTSAMETYPEMAP = _descriptor.Descriptor( + name='TestSameTypeMap', + full_name='protobuf_unittest.TestSameTypeMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map1', full_name='protobuf_unittest.TestSameTypeMap.map1', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map2', full_name='protobuf_unittest.TestSameTypeMap.map2', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTSAMETYPEMAP_MAP1ENTRY, _TESTSAMETYPEMAP_MAP2ENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3079, + serialized_end=3306, +) + + +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY = _descriptor.Descriptor( + name='MapFieldEntry', + full_name='protobuf_unittest.TestRequiredMessageMap.MapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestRequiredMessageMap.MapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestRequiredMessageMap.MapFieldEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3411, + serialized_end=3491, +) + +_TESTREQUIREDMESSAGEMAP = _descriptor.Descriptor( + name='TestRequiredMessageMap', + full_name='protobuf_unittest.TestRequiredMessageMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_field', full_name='protobuf_unittest.TestRequiredMessageMap.map_field', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3309, + serialized_end=3491, +) + + +_TESTARENAMAP_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_unittest.TestArenaMap.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1613, + serialized_end=1665, +) + +_TESTARENAMAP_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_unittest.TestArenaMap.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1667, + serialized_end=1719, +) + +_TESTARENAMAP_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_unittest.TestArenaMap.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1721, + serialized_end=1775, +) + +_TESTARENAMAP_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_unittest.TestArenaMap.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1777, + serialized_end=1831, +) + +_TESTARENAMAP_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_unittest.TestArenaMap.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1833, + serialized_end=1887, +) + +_TESTARENAMAP_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_unittest.TestArenaMap.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1889, + serialized_end=1943, +) + +_TESTARENAMAP_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1945, + serialized_end=2001, +) + +_TESTARENAMAP_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2003, + serialized_end=2059, +) + +_TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2061, + serialized_end=2119, +) + +_TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2121, + serialized_end=2179, +) + +_TESTARENAMAP_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2181, + serialized_end=2233, +) + +_TESTARENAMAP_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2235, + serialized_end=2288, +) + +_TESTARENAMAP_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_unittest.TestArenaMap.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2290, + serialized_end=2340, +) + +_TESTARENAMAP_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_unittest.TestArenaMap.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2342, + serialized_end=2396, +) + +_TESTARENAMAP_MAPINT32BYTESENTRY = _descriptor.Descriptor( + name='MapInt32BytesEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32BytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32BytesEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32BytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2398, + serialized_end=2450, +) + +_TESTARENAMAP_MAPINT32ENUMENTRY = _descriptor.Descriptor( + name='MapInt32EnumEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32EnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32EnumEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32EnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2452, + serialized_end=2531, +) + +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapInt32ForeignMessageEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2533, + serialized_end=2629, +) + +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY = _descriptor.Descriptor( + name='MapInt32ForeignMessageNoArenaEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6024, + serialized_end=6136, +) + +_TESTARENAMAP = _descriptor.Descriptor( + name='TestArenaMap', + full_name='protobuf_unittest.TestArenaMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_unittest.TestArenaMap.map_int32_int32', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_unittest.TestArenaMap.map_int64_int64', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_unittest.TestArenaMap.map_uint32_uint32', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_unittest.TestArenaMap.map_uint64_uint64', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_unittest.TestArenaMap.map_sint32_sint32', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_unittest.TestArenaMap.map_sint64_sint64', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_unittest.TestArenaMap.map_fixed32_fixed32', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_unittest.TestArenaMap.map_fixed64_fixed64', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_unittest.TestArenaMap.map_sfixed32_sfixed32', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_unittest.TestArenaMap.map_sfixed64_sfixed64', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_unittest.TestArenaMap.map_int32_float', index=10, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_unittest.TestArenaMap.map_int32_double', index=11, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_unittest.TestArenaMap.map_bool_bool', index=12, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_unittest.TestArenaMap.map_string_string', index=13, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_bytes', full_name='protobuf_unittest.TestArenaMap.map_int32_bytes', index=14, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_enum', full_name='protobuf_unittest.TestArenaMap.map_int32_enum', index=15, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_foreign_message', full_name='protobuf_unittest.TestArenaMap.map_int32_foreign_message', index=16, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_foreign_message_no_arena', full_name='protobuf_unittest.TestArenaMap.map_int32_foreign_message_no_arena', index=17, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTARENAMAP_MAPINT32INT32ENTRY, _TESTARENAMAP_MAPINT64INT64ENTRY, _TESTARENAMAP_MAPUINT32UINT32ENTRY, _TESTARENAMAP_MAPUINT64UINT64ENTRY, _TESTARENAMAP_MAPSINT32SINT32ENTRY, _TESTARENAMAP_MAPSINT64SINT64ENTRY, _TESTARENAMAP_MAPFIXED32FIXED32ENTRY, _TESTARENAMAP_MAPFIXED64FIXED64ENTRY, _TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY, _TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY, _TESTARENAMAP_MAPINT32FLOATENTRY, _TESTARENAMAP_MAPINT32DOUBLEENTRY, _TESTARENAMAP_MAPBOOLBOOLENTRY, _TESTARENAMAP_MAPSTRINGSTRINGENTRY, _TESTARENAMAP_MAPINT32BYTESENTRY, _TESTARENAMAP_MAPINT32ENUMENTRY, _TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY, _TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3494, + serialized_end=6136, +) + + +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY = _descriptor.Descriptor( + name='TypeEntry', + full_name='protobuf_unittest.MessageContainingEnumCalledType.TypeEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.MessageContainingEnumCalledType.TypeEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.MessageContainingEnumCalledType.TypeEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6250, + serialized_end=6345, +) + +_MESSAGECONTAININGENUMCALLEDTYPE = _descriptor.Descriptor( + name='MessageContainingEnumCalledType', + full_name='protobuf_unittest.MessageContainingEnumCalledType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='protobuf_unittest.MessageContainingEnumCalledType.type', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY, ], + enum_types=[ + _MESSAGECONTAININGENUMCALLEDTYPE_TYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6139, + serialized_end=6367, +) + + +_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY = _descriptor.Descriptor( + name='EntryEntry', + full_name='protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6483, + serialized_end=6527, +) + +_MESSAGECONTAININGMAPCALLEDENTRY = _descriptor.Descriptor( + name='MessageContainingMapCalledEntry', + full_name='protobuf_unittest.MessageContainingMapCalledEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='entry', full_name='protobuf_unittest.MessageContainingMapCalledEntry.entry', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6370, + serialized_end=6527, +) + + +_TESTRECURSIVEMAPMESSAGE_AENTRY = _descriptor.Descriptor( + name='AEntry', + full_name='protobuf_unittest.TestRecursiveMapMessage.AEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestRecursiveMapMessage.AEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestRecursiveMapMessage.AEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6619, + serialized_end=6703, +) + +_TESTRECURSIVEMAPMESSAGE = _descriptor.Descriptor( + name='TestRecursiveMapMessage', + full_name='protobuf_unittest.TestRecursiveMapMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestRecursiveMapMessage.a', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTRECURSIVEMAPMESSAGE_AENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6530, + serialized_end=6703, +) + +_TESTMAP_MAPINT32INT32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT64INT64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPUINT32UINT32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPUINT64UINT64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSINT32SINT32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSINT64SINT64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPFIXED32FIXED32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPFIXED64FIXED64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32FLOATENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32DOUBLEENTRY.containing_type = _TESTMAP +_TESTMAP_MAPBOOLBOOLENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSTRINGSTRINGENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32BYTESENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32ENUMENTRY.fields_by_name['value'].enum_type = _MAPENUM +_TESTMAP_MAPINT32ENUMENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._FOREIGNMESSAGE +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._FOREIGNMESSAGE +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32ALLTYPESENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLTYPES +_TESTMAP_MAPINT32ALLTYPESENTRY.containing_type = _TESTMAP +_TESTMAP.fields_by_name['map_int32_int32'].message_type = _TESTMAP_MAPINT32INT32ENTRY +_TESTMAP.fields_by_name['map_int64_int64'].message_type = _TESTMAP_MAPINT64INT64ENTRY +_TESTMAP.fields_by_name['map_uint32_uint32'].message_type = _TESTMAP_MAPUINT32UINT32ENTRY +_TESTMAP.fields_by_name['map_uint64_uint64'].message_type = _TESTMAP_MAPUINT64UINT64ENTRY +_TESTMAP.fields_by_name['map_sint32_sint32'].message_type = _TESTMAP_MAPSINT32SINT32ENTRY +_TESTMAP.fields_by_name['map_sint64_sint64'].message_type = _TESTMAP_MAPSINT64SINT64ENTRY +_TESTMAP.fields_by_name['map_fixed32_fixed32'].message_type = _TESTMAP_MAPFIXED32FIXED32ENTRY +_TESTMAP.fields_by_name['map_fixed64_fixed64'].message_type = _TESTMAP_MAPFIXED64FIXED64ENTRY +_TESTMAP.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTMAP_MAPSFIXED32SFIXED32ENTRY +_TESTMAP.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTMAP_MAPSFIXED64SFIXED64ENTRY +_TESTMAP.fields_by_name['map_int32_float'].message_type = _TESTMAP_MAPINT32FLOATENTRY +_TESTMAP.fields_by_name['map_int32_double'].message_type = _TESTMAP_MAPINT32DOUBLEENTRY +_TESTMAP.fields_by_name['map_bool_bool'].message_type = _TESTMAP_MAPBOOLBOOLENTRY +_TESTMAP.fields_by_name['map_string_string'].message_type = _TESTMAP_MAPSTRINGSTRINGENTRY +_TESTMAP.fields_by_name['map_int32_bytes'].message_type = _TESTMAP_MAPINT32BYTESENTRY +_TESTMAP.fields_by_name['map_int32_enum'].message_type = _TESTMAP_MAPINT32ENUMENTRY +_TESTMAP.fields_by_name['map_int32_foreign_message'].message_type = _TESTMAP_MAPINT32FOREIGNMESSAGEENTRY +_TESTMAP.fields_by_name['map_string_foreign_message'].message_type = _TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY +_TESTMAP.fields_by_name['map_int32_all_types'].message_type = _TESTMAP_MAPINT32ALLTYPESENTRY +_TESTMAPSUBMESSAGE.fields_by_name['test_map'].message_type = _TESTMAP +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLTYPES +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY.containing_type = _TESTMESSAGEMAP +_TESTMESSAGEMAP.fields_by_name['map_int32_message'].message_type = _TESTMESSAGEMAP_MAPINT32MESSAGEENTRY +_TESTSAMETYPEMAP_MAP1ENTRY.containing_type = _TESTSAMETYPEMAP +_TESTSAMETYPEMAP_MAP2ENTRY.containing_type = _TESTSAMETYPEMAP +_TESTSAMETYPEMAP.fields_by_name['map1'].message_type = _TESTSAMETYPEMAP_MAP1ENTRY +_TESTSAMETYPEMAP.fields_by_name['map2'].message_type = _TESTSAMETYPEMAP_MAP2ENTRY +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTREQUIRED +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY.containing_type = _TESTREQUIREDMESSAGEMAP +_TESTREQUIREDMESSAGEMAP.fields_by_name['map_field'].message_type = _TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY +_TESTARENAMAP_MAPINT32INT32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT64INT64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPUINT32UINT32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPUINT64UINT64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSINT32SINT32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSINT64SINT64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPFIXED32FIXED32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPFIXED64FIXED64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32FLOATENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32DOUBLEENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPBOOLBOOLENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSTRINGSTRINGENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32BYTESENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32ENUMENTRY.fields_by_name['value'].enum_type = _MAPENUM +_TESTARENAMAP_MAPINT32ENUMENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._FOREIGNMESSAGE +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__no__arena__pb2._FOREIGNMESSAGE +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP.fields_by_name['map_int32_int32'].message_type = _TESTARENAMAP_MAPINT32INT32ENTRY +_TESTARENAMAP.fields_by_name['map_int64_int64'].message_type = _TESTARENAMAP_MAPINT64INT64ENTRY +_TESTARENAMAP.fields_by_name['map_uint32_uint32'].message_type = _TESTARENAMAP_MAPUINT32UINT32ENTRY +_TESTARENAMAP.fields_by_name['map_uint64_uint64'].message_type = _TESTARENAMAP_MAPUINT64UINT64ENTRY +_TESTARENAMAP.fields_by_name['map_sint32_sint32'].message_type = _TESTARENAMAP_MAPSINT32SINT32ENTRY +_TESTARENAMAP.fields_by_name['map_sint64_sint64'].message_type = _TESTARENAMAP_MAPSINT64SINT64ENTRY +_TESTARENAMAP.fields_by_name['map_fixed32_fixed32'].message_type = _TESTARENAMAP_MAPFIXED32FIXED32ENTRY +_TESTARENAMAP.fields_by_name['map_fixed64_fixed64'].message_type = _TESTARENAMAP_MAPFIXED64FIXED64ENTRY +_TESTARENAMAP.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY +_TESTARENAMAP.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY +_TESTARENAMAP.fields_by_name['map_int32_float'].message_type = _TESTARENAMAP_MAPINT32FLOATENTRY +_TESTARENAMAP.fields_by_name['map_int32_double'].message_type = _TESTARENAMAP_MAPINT32DOUBLEENTRY +_TESTARENAMAP.fields_by_name['map_bool_bool'].message_type = _TESTARENAMAP_MAPBOOLBOOLENTRY +_TESTARENAMAP.fields_by_name['map_string_string'].message_type = _TESTARENAMAP_MAPSTRINGSTRINGENTRY +_TESTARENAMAP.fields_by_name['map_int32_bytes'].message_type = _TESTARENAMAP_MAPINT32BYTESENTRY +_TESTARENAMAP.fields_by_name['map_int32_enum'].message_type = _TESTARENAMAP_MAPINT32ENUMENTRY +_TESTARENAMAP.fields_by_name['map_int32_foreign_message'].message_type = _TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY +_TESTARENAMAP.fields_by_name['map_int32_foreign_message_no_arena'].message_type = _TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY.fields_by_name['value'].message_type = _MESSAGECONTAININGENUMCALLEDTYPE +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY.containing_type = _MESSAGECONTAININGENUMCALLEDTYPE +_MESSAGECONTAININGENUMCALLEDTYPE.fields_by_name['type'].message_type = _MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY +_MESSAGECONTAININGENUMCALLEDTYPE_TYPE.containing_type = _MESSAGECONTAININGENUMCALLEDTYPE +_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY.containing_type = _MESSAGECONTAININGMAPCALLEDENTRY +_MESSAGECONTAININGMAPCALLEDENTRY.fields_by_name['entry'].message_type = _MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY +_TESTRECURSIVEMAPMESSAGE_AENTRY.fields_by_name['value'].message_type = _TESTRECURSIVEMAPMESSAGE +_TESTRECURSIVEMAPMESSAGE_AENTRY.containing_type = _TESTRECURSIVEMAPMESSAGE +_TESTRECURSIVEMAPMESSAGE.fields_by_name['a'].message_type = _TESTRECURSIVEMAPMESSAGE_AENTRY +DESCRIPTOR.message_types_by_name['TestMap'] = _TESTMAP +DESCRIPTOR.message_types_by_name['TestMapSubmessage'] = _TESTMAPSUBMESSAGE +DESCRIPTOR.message_types_by_name['TestMessageMap'] = _TESTMESSAGEMAP +DESCRIPTOR.message_types_by_name['TestSameTypeMap'] = _TESTSAMETYPEMAP +DESCRIPTOR.message_types_by_name['TestRequiredMessageMap'] = _TESTREQUIREDMESSAGEMAP +DESCRIPTOR.message_types_by_name['TestArenaMap'] = _TESTARENAMAP +DESCRIPTOR.message_types_by_name['MessageContainingEnumCalledType'] = _MESSAGECONTAININGENUMCALLEDTYPE +DESCRIPTOR.message_types_by_name['MessageContainingMapCalledEntry'] = _MESSAGECONTAININGMAPCALLEDENTRY +DESCRIPTOR.message_types_by_name['TestRecursiveMapMessage'] = _TESTRECURSIVEMAPMESSAGE +DESCRIPTOR.enum_types_by_name['MapEnum'] = _MAPENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMap = _reflection.GeneratedProtocolMessageType('TestMap', (_message.Message,), dict( + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapStringStringEntry) + )) + , + + MapInt32BytesEntry = _reflection.GeneratedProtocolMessageType('MapInt32BytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32BYTESENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32BytesEntry) + )) + , + + MapInt32EnumEntry = _reflection.GeneratedProtocolMessageType('MapInt32EnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32ENUMENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32EnumEntry) + )) + , + + MapInt32ForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapInt32ForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32FOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32ForeignMessageEntry) + )) + , + + MapStringForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapStringForeignMessageEntry) + )) + , + + MapInt32AllTypesEntry = _reflection.GeneratedProtocolMessageType('MapInt32AllTypesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32ALLTYPESENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32AllTypesEntry) + )) + , + DESCRIPTOR = _TESTMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap) + )) +_sym_db.RegisterMessage(TestMap) +_sym_db.RegisterMessage(TestMap.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestMap.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestMap.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestMap.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestMap.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestMap.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestMap.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestMap.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestMap.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestMap.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestMap.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestMap.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestMap.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestMap.MapStringStringEntry) +_sym_db.RegisterMessage(TestMap.MapInt32BytesEntry) +_sym_db.RegisterMessage(TestMap.MapInt32EnumEntry) +_sym_db.RegisterMessage(TestMap.MapInt32ForeignMessageEntry) +_sym_db.RegisterMessage(TestMap.MapStringForeignMessageEntry) +_sym_db.RegisterMessage(TestMap.MapInt32AllTypesEntry) + +TestMapSubmessage = _reflection.GeneratedProtocolMessageType('TestMapSubmessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPSUBMESSAGE, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMapSubmessage) + )) +_sym_db.RegisterMessage(TestMapSubmessage) + +TestMessageMap = _reflection.GeneratedProtocolMessageType('TestMessageMap', (_message.Message,), dict( + + MapInt32MessageEntry = _reflection.GeneratedProtocolMessageType('MapInt32MessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGEMAP_MAPINT32MESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageMap.MapInt32MessageEntry) + )) + , + DESCRIPTOR = _TESTMESSAGEMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageMap) + )) +_sym_db.RegisterMessage(TestMessageMap) +_sym_db.RegisterMessage(TestMessageMap.MapInt32MessageEntry) + +TestSameTypeMap = _reflection.GeneratedProtocolMessageType('TestSameTypeMap', (_message.Message,), dict( + + Map1Entry = _reflection.GeneratedProtocolMessageType('Map1Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTSAMETYPEMAP_MAP1ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSameTypeMap.Map1Entry) + )) + , + + Map2Entry = _reflection.GeneratedProtocolMessageType('Map2Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTSAMETYPEMAP_MAP2ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSameTypeMap.Map2Entry) + )) + , + DESCRIPTOR = _TESTSAMETYPEMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSameTypeMap) + )) +_sym_db.RegisterMessage(TestSameTypeMap) +_sym_db.RegisterMessage(TestSameTypeMap.Map1Entry) +_sym_db.RegisterMessage(TestSameTypeMap.Map2Entry) + +TestRequiredMessageMap = _reflection.GeneratedProtocolMessageType('TestRequiredMessageMap', (_message.Message,), dict( + + MapFieldEntry = _reflection.GeneratedProtocolMessageType('MapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredMessageMap.MapFieldEntry) + )) + , + DESCRIPTOR = _TESTREQUIREDMESSAGEMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredMessageMap) + )) +_sym_db.RegisterMessage(TestRequiredMessageMap) +_sym_db.RegisterMessage(TestRequiredMessageMap.MapFieldEntry) + +TestArenaMap = _reflection.GeneratedProtocolMessageType('TestArenaMap', (_message.Message,), dict( + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapStringStringEntry) + )) + , + + MapInt32BytesEntry = _reflection.GeneratedProtocolMessageType('MapInt32BytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32BYTESENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32BytesEntry) + )) + , + + MapInt32EnumEntry = _reflection.GeneratedProtocolMessageType('MapInt32EnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32ENUMENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32EnumEntry) + )) + , + + MapInt32ForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapInt32ForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry) + )) + , + + MapInt32ForeignMessageNoArenaEntry = _reflection.GeneratedProtocolMessageType('MapInt32ForeignMessageNoArenaEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry) + )) + , + DESCRIPTOR = _TESTARENAMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap) + )) +_sym_db.RegisterMessage(TestArenaMap) +_sym_db.RegisterMessage(TestArenaMap.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestArenaMap.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestArenaMap.MapStringStringEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32BytesEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32EnumEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32ForeignMessageEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32ForeignMessageNoArenaEntry) + +MessageContainingEnumCalledType = _reflection.GeneratedProtocolMessageType('MessageContainingEnumCalledType', (_message.Message,), dict( + + TypeEntry = _reflection.GeneratedProtocolMessageType('TypeEntry', (_message.Message,), dict( + DESCRIPTOR = _MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingEnumCalledType.TypeEntry) + )) + , + DESCRIPTOR = _MESSAGECONTAININGENUMCALLEDTYPE, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingEnumCalledType) + )) +_sym_db.RegisterMessage(MessageContainingEnumCalledType) +_sym_db.RegisterMessage(MessageContainingEnumCalledType.TypeEntry) + +MessageContainingMapCalledEntry = _reflection.GeneratedProtocolMessageType('MessageContainingMapCalledEntry', (_message.Message,), dict( + + EntryEntry = _reflection.GeneratedProtocolMessageType('EntryEntry', (_message.Message,), dict( + DESCRIPTOR = _MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry) + )) + , + DESCRIPTOR = _MESSAGECONTAININGMAPCALLEDENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingMapCalledEntry) + )) +_sym_db.RegisterMessage(MessageContainingMapCalledEntry) +_sym_db.RegisterMessage(MessageContainingMapCalledEntry.EntryEntry) + +TestRecursiveMapMessage = _reflection.GeneratedProtocolMessageType('TestRecursiveMapMessage', (_message.Message,), dict( + + AEntry = _reflection.GeneratedProtocolMessageType('AEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTRECURSIVEMAPMESSAGE_AENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursiveMapMessage.AEntry) + )) + , + DESCRIPTOR = _TESTRECURSIVEMAPMESSAGE, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursiveMapMessage) + )) +_sym_db.RegisterMessage(TestRecursiveMapMessage) +_sym_db.RegisterMessage(TestRecursiveMapMessage.AEntry) + + +DESCRIPTOR._options = None +_TESTMAP_MAPINT32INT32ENTRY._options = None +_TESTMAP_MAPINT64INT64ENTRY._options = None +_TESTMAP_MAPUINT32UINT32ENTRY._options = None +_TESTMAP_MAPUINT64UINT64ENTRY._options = None +_TESTMAP_MAPSINT32SINT32ENTRY._options = None +_TESTMAP_MAPSINT64SINT64ENTRY._options = None +_TESTMAP_MAPFIXED32FIXED32ENTRY._options = None +_TESTMAP_MAPFIXED64FIXED64ENTRY._options = None +_TESTMAP_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTMAP_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTMAP_MAPINT32FLOATENTRY._options = None +_TESTMAP_MAPINT32DOUBLEENTRY._options = None +_TESTMAP_MAPBOOLBOOLENTRY._options = None +_TESTMAP_MAPSTRINGSTRINGENTRY._options = None +_TESTMAP_MAPINT32BYTESENTRY._options = None +_TESTMAP_MAPINT32ENUMENTRY._options = None +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY._options = None +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY._options = None +_TESTMAP_MAPINT32ALLTYPESENTRY._options = None +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY._options = None +_TESTSAMETYPEMAP_MAP1ENTRY._options = None +_TESTSAMETYPEMAP_MAP2ENTRY._options = None +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY._options = None +_TESTARENAMAP_MAPINT32INT32ENTRY._options = None +_TESTARENAMAP_MAPINT64INT64ENTRY._options = None +_TESTARENAMAP_MAPUINT32UINT32ENTRY._options = None +_TESTARENAMAP_MAPUINT64UINT64ENTRY._options = None +_TESTARENAMAP_MAPSINT32SINT32ENTRY._options = None +_TESTARENAMAP_MAPSINT64SINT64ENTRY._options = None +_TESTARENAMAP_MAPFIXED32FIXED32ENTRY._options = None +_TESTARENAMAP_MAPFIXED64FIXED64ENTRY._options = None +_TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTARENAMAP_MAPINT32FLOATENTRY._options = None +_TESTARENAMAP_MAPINT32DOUBLEENTRY._options = None +_TESTARENAMAP_MAPBOOLBOOLENTRY._options = None +_TESTARENAMAP_MAPSTRINGSTRINGENTRY._options = None +_TESTARENAMAP_MAPINT32BYTESENTRY._options = None +_TESTARENAMAP_MAPINT32ENUMENTRY._options = None +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY._options = None +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY._options = None +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY._options = None +_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY._options = None +_TESTRECURSIVEMAPMESSAGE_AENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/message.py b/venv/lib/python3.7/site-packages/google/protobuf/message.py new file mode 100644 index 0000000..eeb0d57 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/message.py @@ -0,0 +1,308 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# TODO(robinson): We should just make these methods all "pure-virtual" and move +# all implementation out, into reflection.py for now. + + +"""Contains an abstract base class for protocol messages.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +class Error(Exception): pass +class DecodeError(Error): pass +class EncodeError(Error): pass + + +class Message(object): + + """Abstract base class for protocol messages. + + Protocol message classes are almost always generated by the protocol + compiler. These generated types subclass Message and implement the methods + shown below. + + TODO(robinson): Link to an HTML document here. + + TODO(robinson): Document that instances of this class will also + have an Extensions attribute with __getitem__ and __setitem__. + Again, not sure how to best convey this. + + TODO(robinson): Document that the class must also have a static + RegisterExtension(extension_field) method. + Not sure how to best express at this point. + """ + + # TODO(robinson): Document these fields and methods. + + __slots__ = [] + + DESCRIPTOR = None + + def __deepcopy__(self, memo=None): + clone = type(self)() + clone.MergeFrom(self) + return clone + + def __eq__(self, other_msg): + """Recursively compares two messages by value and structure.""" + raise NotImplementedError + + def __ne__(self, other_msg): + # Can't just say self != other_msg, since that would infinitely recurse. :) + return not self == other_msg + + def __hash__(self): + raise TypeError('unhashable object') + + def __str__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def __unicode__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def MergeFrom(self, other_msg): + """Merges the contents of the specified message into current message. + + This method merges the contents of the specified message into the current + message. Singular fields that are set in the specified message overwrite + the corresponding fields in the current message. Repeated fields are + appended. Singular sub-messages and groups are recursively merged. + + Args: + other_msg: Message to merge into the current message. + """ + raise NotImplementedError + + def CopyFrom(self, other_msg): + """Copies the content of the specified message into the current message. + + The method clears the current message and then merges the specified + message using MergeFrom. + + Args: + other_msg: Message to copy into the current one. + """ + if self is other_msg: + return + self.Clear() + self.MergeFrom(other_msg) + + def Clear(self): + """Clears all data that was set in the message.""" + raise NotImplementedError + + def SetInParent(self): + """Mark this as present in the parent. + + This normally happens automatically when you assign a field of a + sub-message, but sometimes you want to make the sub-message + present while keeping it empty. If you find yourself using this, + you may want to reconsider your design.""" + raise NotImplementedError + + def IsInitialized(self): + """Checks if the message is initialized. + + Returns: + The method returns True if the message is initialized (i.e. all of its + required fields are set). + """ + raise NotImplementedError + + # TODO(robinson): MergeFromString() should probably return None and be + # implemented in terms of a helper that returns the # of bytes read. Our + # deserialization routines would use the helper when recursively + # deserializing, but the end user would almost always just want the no-return + # MergeFromString(). + + def MergeFromString(self, serialized): + """Merges serialized protocol buffer data into this message. + + When we find a field in |serialized| that is already present + in this message: + - If it's a "repeated" field, we append to the end of our list. + - Else, if it's a scalar, we overwrite our field. + - Else, (it's a nonrepeated composite), we recursively merge + into the existing composite. + + TODO(robinson): Document handling of unknown fields. + + Args: + serialized: Any object that allows us to call buffer(serialized) + to access a string of bytes using the buffer interface. + + TODO(robinson): When we switch to a helper, this will return None. + + Returns: + The number of bytes read from |serialized|. + For non-group messages, this will always be len(serialized), + but for messages which are actually groups, this will + generally be less than len(serialized), since we must + stop when we reach an END_GROUP tag. Note that if + we *do* stop because of an END_GROUP tag, the number + of bytes returned does not include the bytes + for the END_GROUP tag information. + """ + raise NotImplementedError + + def ParseFromString(self, serialized): + """Parse serialized protocol buffer data into this message. + + Like MergeFromString(), except we clear the object first and + do not return the value that MergeFromString returns. + """ + self.Clear() + self.MergeFromString(serialized) + + def SerializeToString(self, **kwargs): + """Serializes the protocol message to a binary string. + + Arguments: + **kwargs: Keyword arguments to the serialize method, accepts + the following keyword args: + deterministic: If true, requests deterministic serialization of the + protobuf, with predictable ordering of map keys. + + Returns: + A binary string representation of the message if all of the required + fields in the message are set (i.e. the message is initialized). + + Raises: + message.EncodeError if the message isn't initialized. + """ + raise NotImplementedError + + def SerializePartialToString(self, **kwargs): + """Serializes the protocol message to a binary string. + + This method is similar to SerializeToString but doesn't check if the + message is initialized. + + Arguments: + **kwargs: Keyword arguments to the serialize method, accepts + the following keyword args: + deterministic: If true, requests deterministic serialization of the + protobuf, with predictable ordering of map keys. + + Returns: + A string representation of the partial message. + """ + raise NotImplementedError + + # TODO(robinson): Decide whether we like these better + # than auto-generated has_foo() and clear_foo() methods + # on the instances themselves. This way is less consistent + # with C++, but it makes reflection-type access easier and + # reduces the number of magically autogenerated things. + # + # TODO(robinson): Be sure to document (and test) exactly + # which field names are accepted here. Are we case-sensitive? + # What do we do with fields that share names with Python keywords + # like 'lambda' and 'yield'? + # + # nnorwitz says: + # """ + # Typically (in python), an underscore is appended to names that are + # keywords. So they would become lambda_ or yield_. + # """ + def ListFields(self): + """Returns a list of (FieldDescriptor, value) tuples for all + fields in the message which are not empty. A message field is + non-empty if HasField() would return true. A singular primitive field + is non-empty if HasField() would return true in proto2 or it is non zero + in proto3. A repeated field is non-empty if it contains at least one + element. The fields are ordered by field number""" + raise NotImplementedError + + def HasField(self, field_name): + """Checks if a certain field is set for the message, or if any field inside + a oneof group is set. Note that if the field_name is not defined in the + message descriptor, ValueError will be raised.""" + raise NotImplementedError + + def ClearField(self, field_name): + """Clears the contents of a given field, or the field set inside a oneof + group. If the name neither refers to a defined field or oneof group, + ValueError is raised.""" + raise NotImplementedError + + def WhichOneof(self, oneof_group): + """Returns the name of the field that is set inside a oneof group, or + None if no field is set. If no group with the given name exists, ValueError + will be raised.""" + raise NotImplementedError + + def HasExtension(self, extension_handle): + raise NotImplementedError + + def ClearExtension(self, extension_handle): + raise NotImplementedError + + def DiscardUnknownFields(self): + raise NotImplementedError + + def ByteSize(self): + """Returns the serialized size of this message. + Recursively calls ByteSize() on all contained messages. + """ + raise NotImplementedError + + def _SetListener(self, message_listener): + """Internal method used by the protocol message implementation. + Clients should not call this directly. + + Sets a listener that this message will call on certain state transitions. + + The purpose of this method is to register back-edges from children to + parents at runtime, for the purpose of setting "has" bits and + byte-size-dirty bits in the parent and ancestor objects whenever a child or + descendant object is modified. + + If the client wants to disconnect this Message from the object tree, she + explicitly sets callback to None. + + If message_listener is None, unregisters any existing listener. Otherwise, + message_listener must implement the MessageListener interface in + internal/message_listener.py, and we discard any listener registered + via a previous _SetListener() call. + """ + raise NotImplementedError + + def __getstate__(self): + """Support the pickle protocol.""" + return dict(serialized=self.SerializePartialToString()) + + def __setstate__(self, state): + """Support the pickle protocol.""" + self.__init__() + self.ParseFromString(state['serialized']) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/message_factory.py b/venv/lib/python3.7/site-packages/google/protobuf/message_factory.py new file mode 100644 index 0000000..6e07404 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/message_factory.py @@ -0,0 +1,151 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides a factory class for generating dynamic messages. + +The easiest way to use this class is if you have access to the FileDescriptor +protos containing the messages you want to create you can just do the following: + +message_classes = message_factory.GetMessages(iterable_of_file_descriptors) +my_proto_instance = message_classes['some.proto.package.MessageName']() +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +from google.protobuf import descriptor_pool +from google.protobuf import message +from google.protobuf import reflection + + +class MessageFactory(object): + """Factory for creating Proto2 messages from descriptors in a pool.""" + + def __init__(self, pool=None): + """Initializes a new factory.""" + self.pool = pool or descriptor_pool.DescriptorPool() + + # local cache of all classes built from protobuf descriptors + self._classes = {} + + def GetPrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Passing a descriptor with a fully qualified name matching a previous + invocation will cause the same class to be returned. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + if descriptor not in self._classes: + descriptor_name = descriptor.name + if str is bytes: # PY2 + descriptor_name = descriptor.name.encode('ascii', 'ignore') + result_class = reflection.GeneratedProtocolMessageType( + descriptor_name, + (message.Message,), + {'DESCRIPTOR': descriptor, '__module__': None}) + # If module not set, it wrongly points to the reflection.py module. + self._classes[descriptor] = result_class + for field in descriptor.fields: + if field.message_type: + self.GetPrototype(field.message_type) + for extension in result_class.DESCRIPTOR.extensions: + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return self._classes[descriptor] + + def GetMessages(self, files): + """Gets all the messages from a specified file. + + This will find and resolve dependencies, failing if the descriptor + pool cannot satisfy them. + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + result = {} + for file_name in files: + file_desc = self.pool.FindFileByName(file_name) + for desc in list(file_desc.message_types_by_name.values()): + result[desc.full_name] = self.GetPrototype(desc) + + # While the extension FieldDescriptors are created by the descriptor pool, + # the python classes created in the factory need them to be registered + # explicitly, which is done below. + # + # The call to RegisterExtension will specifically check if the + # extension was already registered on the object and either + # ignore the registration if the original was the same, or raise + # an error if they were different. + + for extension in list(file_desc.extensions_by_name.values()): + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return result + + +_FACTORY = MessageFactory() + + +def GetMessages(file_protos): + """Builds a dictionary of all the messages available in a set of files. + + Args: + file_protos: Iterable of FileDescriptorProto to build messages out of. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + # The cpp implementation of the protocol buffer library requires to add the + # message in topological order of the dependency graph. + file_by_name = {file_proto.name: file_proto for file_proto in file_protos} + def _AddFile(file_proto): + for dependency in file_proto.dependency: + if dependency in file_by_name: + # Remove from elements to be visited, in order to cut cycles. + _AddFile(file_by_name.pop(dependency)) + _FACTORY.pool.Add(file_proto) + while file_by_name: + _AddFile(file_by_name.popitem()[1]) + return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos]) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/proto_builder.py b/venv/lib/python3.7/site-packages/google/protobuf/proto_builder.py new file mode 100644 index 0000000..128814f --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/proto_builder.py @@ -0,0 +1,130 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Dynamic Protobuf class creator.""" + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict #PY26 +import hashlib +import os + +from google.protobuf import descriptor_pb2 +from google.protobuf import message_factory + + +def _GetMessageFromFactory(factory, full_name): + """Get a proto class from the MessageFactory by name. + + Args: + factory: a MessageFactory instance. + full_name: str, the fully qualified name of the proto type. + Returns: + A class, for the type identified by full_name. + Raises: + KeyError, if the proto is not found in the factory's descriptor pool. + """ + proto_descriptor = factory.pool.FindMessageTypeByName(full_name) + proto_cls = factory.GetPrototype(proto_descriptor) + return proto_cls + + +def MakeSimpleProtoClass(fields, full_name=None, pool=None): + """Create a Protobuf class whose fields are basic types. + + Note: this doesn't validate field names! + + Args: + fields: dict of {name: field_type} mappings for each field in the proto. If + this is an OrderedDict the order will be maintained, otherwise the + fields will be sorted by name. + full_name: optional str, the fully-qualified name of the proto type. + pool: optional DescriptorPool instance. + Returns: + a class, the new protobuf class with a FileDescriptor. + """ + factory = message_factory.MessageFactory(pool=pool) + + if full_name is not None: + try: + proto_cls = _GetMessageFromFactory(factory, full_name) + return proto_cls + except KeyError: + # The factory's DescriptorPool doesn't know about this class yet. + pass + + # Get a list of (name, field_type) tuples from the fields dict. If fields was + # an OrderedDict we keep the order, but otherwise we sort the field to ensure + # consistent ordering. + field_items = list(fields.items()) + if not isinstance(fields, OrderedDict): + field_items = sorted(field_items) + + # Use a consistent file name that is unlikely to conflict with any imported + # proto files. + fields_hash = hashlib.sha1() + for f_name, f_type in field_items: + fields_hash.update(f_name.encode('utf-8')) + fields_hash.update(str(f_type).encode('utf-8')) + proto_file_name = fields_hash.hexdigest() + '.proto' + + # If the proto is anonymous, use the same hash to name it. + if full_name is None: + full_name = ('net.proto2.python.public.proto_builder.AnonymousProto_' + + fields_hash.hexdigest()) + try: + proto_cls = _GetMessageFromFactory(factory, full_name) + return proto_cls + except KeyError: + # The factory's DescriptorPool doesn't know about this class yet. + pass + + # This is the first time we see this proto: add a new descriptor to the pool. + factory.pool.Add( + _MakeFileDescriptorProto(proto_file_name, full_name, field_items)) + return _GetMessageFromFactory(factory, full_name) + + +def _MakeFileDescriptorProto(proto_file_name, full_name, field_items): + """Populate FileDescriptorProto for MessageFactory's DescriptorPool.""" + package, name = full_name.rsplit('.', 1) + file_proto = descriptor_pb2.FileDescriptorProto() + file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name) + file_proto.package = package + desc_proto = file_proto.message_type.add() + desc_proto.name = name + for f_number, (f_name, f_type) in enumerate(field_items, 1): + field_proto = desc_proto.field.add() + field_proto.name = f_name + field_proto.number = f_number + field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + field_proto.type = f_type + return file_proto diff --git a/venv/lib/python3.7/site-packages/google/protobuf/pyext/__init__.py b/venv/lib/python3.7/site-packages/google/protobuf/pyext/__init__.py new file mode 100644 index 0000000..5585614 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/pyext/__init__.py @@ -0,0 +1,4 @@ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/pyext/_message.cpython-37m-darwin.so b/venv/lib/python3.7/site-packages/google/protobuf/pyext/_message.cpython-37m-darwin.so new file mode 100644 index 0000000000000000000000000000000000000000..92cc7a10614e45ee0e3bce47ab6c8d8157d6de55 GIT binary patch literal 3170208 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

7< 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 z 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

-*h6 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®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

2s~VDD{wKt86Mc_Hiuv>7GN!M9?t{J^ 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 z z`osz(3~Tu&Yfx42&~yzmvXgHtt?DnKT6sgm!rcM4cxW%Qn#gu6s8+OiTrUuH)tb}2 zr`fGJd8uR>q~wj%YL z%H2$UD6j}b52B}`;^a1tnSXQ=usbd0VGRvAug;}bpRfVv;pK8+S(fdHfk>W5#lEtt z=zO23rYE&^3Qf5)q)xgAoKU}Q62~zJo`xk47zZW>keSO?t!4;xNWkT5x@dNjT`6O8 z$Qx|vxFrag1ZLQf0L#J*HB7m4imG4iJPE=*I^!TK<*V2mF=Lh!l%@o!V81C;>50=U zYP4KQ#^A0bWOXm{LEcCRGIgyZBZOtj7Kn&f5kZnuCo~MMHWQ0CBb2GBsVN0iaHT+* z+M)dITY_PWbJ^Wg=J=HfqKIS^&?}h2$f9c13KwXc+;A_VV`teiXoxoeL7><4L4NM7 zzoe7Zu&bYU7cP+MiEDS|<|83XiWGA#X0`es{nWOk*H%Chqjys!?Avf@Fk*TF+EzPM zZOCYLc4TIJdTwgQb{Ew2dHW8@LVuV=uco}ElntlR7`c{Jm6sX{I5J;$c2^VbMvPre ztC-c9fe2HqR}DPwn#LtkSrgkWNNQ(%gu}JF%FV+{X(Z=0ZPu4Uvo}w(B%2l?ukc4- z*jPZfuJ<;4(X(3V=L-Q21Ls{M(>7-YS$a`Cmz~hu8GX7%;Gtk|jC>-)YiidJB_=Uo@v#%GH}v2uS0S2~ zv4Kbd*OHWRjVNl^q}Lg7T*^b8%c^p@W~J7m5FTbRF7D2hVDTYZNWoxJJ^aAjvEkY5 ztZF8wruKouz@eKP8_!ORnk$5qa2#k!fO$Q@lwJ5pklrGn_mn%>cI#Pc)K=?GE59@Z zDMOS1qG)u^V3u`-3l%hDu^lyXJd6GBMO@-hDh@fx-hIx!_d3ZjSbRc{53_LEQLJ;Hx>>T2P z&^q?e*MQR#kftf#Yn%q$^#k-p*k&xQ;>zKi*^$LY3JHpG0y(5s#fW0U<}}S^ zUNBr??#M0MyqA^Ph-bc<^RCFYLCwb?K+a-%Gz%iFJLh~Ef{~(y2%DH8WYs2rb#k{E z66P`;olr0R^iUAqYzmOhgMO*LChI7?aJ`k+@{51c0PThrReFx3?g=WJM$s(Wr9kZO z>p%^erBbOF0s@tH<5tljT_N;b(s?ow+)W?3S66Yn?{b#?slb!Vwc$;uJ~q<<(As&^K)cC7RUWnXr-(|MAL!=BxLkOaMlnB=Y&|P9Kbi~Fo4_>v6Kwd z4EOPyVrivk02Cp-l+Z^ti@tP^AX$ zLB+r*7jT8mQ?+u{N_1Qr0-%*Lq*g3HG^mmumg?f+Ax0)+?R_KoQQB0x<7A)12bJ=P<88IlhY9!E(wByxgL`SpeJc zE*M(dVFgVxK2RN(@DVv8UUgy)H$&#(6jm-+vBt3x))<|H8nY;aT*gWAK(XAE$r9Q? zS+eQ5K=vYm_!KpG(`%3ttAfbBY0jv)-rey3=BPgG!DL!y@6!uoBmrj^p$B_{I+2W@ z%@h^_tuCu;uQ-|2VUnb`8$#>PO_c8{ChU4tL?x$SdP})GpVm^!(}cyCtF_F;7`Lvn@g9E|= zEp$u+nrg2IX#0AOn2?xK+$0(_y-nh~?=&V$SilVt<~nPwVaG<=4Ic=9`YI0<9L5%K zTnqx#0Rdn$5JQP8ij_eTl~SnJ$PLrAY3U~O`IFgo1-l!(9X+7?A0n#VJ~b13eu*l2 zOb%eQjrQqM3JN`A>w`6mw%9Wwn6GeyGcnSEs#KC;?$DxIT)KL#jw!~d`rU#>Xd>s2 zW)bTo=qjM62Lpyw)R5elS4c|X_6E$5_@igGXgw+QY}HjpLdTfg^K@}vKxHds?mR3NP7%fntDhwgUN`f``rZ$@GolBMQl^Rj8b3KCrpc1^|cu#VNC@XsBgnddMNKz z-4;@**yB%-7O1gJ?g=9^s7i$h4;|^ImrQQ=2^gS0vGEj{ZWE+x5^sW9F;cK`kF^*b zfAMA$#WNtXDribrBEnd9l2Vl^L$k@VnE%hp@)M~%hNC;kW8s>7FmhM0dktni$E_c9 z-x7o#^nk2OnvP75Fa%Oo&Xf7jx1ZdA^=lcb(n@)uk#88)A7SJ87m3U*1Ldof<4gAHSHXg0r%B3KhRPXpIdt=|>!HGfK!_IC zwgD6$f*z@x+FS`HBBy%%4FN34hbSAM@hE_2?DTqCYYNx{uqR6G3*t>H99HTAyJdp5 z{>|g?43+6tG8JyyDsyS?E+C@FO{#qWd4vQ38ws}EqAkA)IR++Bc)-B*S8@ezJ^M9pMp zr{-rySlIF5`B?^y4UeP#-1JO#WNLDBoF6h#!^fs(7&kRPmzx^P%?wZ8p9O^DC#EN| z1PW0&>Xx0sCr=PO{1A#5#;0S{DDa+}n3|n!gF?O1ftIBpHrAr!Y1L|2FG547AQ(dk zs^Dx{4A$-e*1+aOn-&y%80s+kY^qYKF140(Or+QU)2vD%*g0~q)4M)Y*n4a(vU@{f z)#()BgeFfaIb{l#)DK}>qXuiGvyi$4v}mML&}(|^dB|$o2+>gVKrvZEqaoMoJ;Riv z#!96Mm{bY;3k!LeT3V5tgLDP<$Xw=<4^~Uyfs{wQUp&zQ<2<$=ZB~i4>rI~&r`N!k z+aRV;FrZj2-?Qb0CbtWNXenYR5NLkl?4I7tS@p!8-o9EWMG|P=N4!IK8tKxqbO?fZ z>&EfY*}0mwLxOyJCSS#D$BjXIp%QH!ctQ`J`uidfV{A?d{@llu=292z{FU%3!U{q&I(=RX9xa4u@qJm2 zBHb+~?g#q8YpEe>h`OZY-0P@`+7i?zm@gqvtlZ}`pN0h?!-K;<2~imzY|&Nbh+|D; zHiTo|KT<-u87*v->;sqjOX6S}Gc>*Ch8Y_KxoSSj(2`J{;hY;R6m$*ER&i(un?;b( z3b_ie4Qbv(cyp~ILqjY1vqIdbj=}Qv)Nv6JXW5u2xh(V?!3;z8&;6fGWC$n0&^x7- zt;2*|su3KZWCDbuQEMtTB^?1=W2rxDm08SNKFa? za+)1;kVhL@B}{@KKoiD!$r>_qlPCuFTq$bF=3#7GjENz^1ooGQhU8p)7H8I@H6}O6 zWlpnSen$CZT-$8y#>;?G7Qx69o5g_WJo~IRzigLIAd1k|E}*sN2oB=f6(v%P*0|QL z)M}?7Ah>9k(q+2_68sw1GO{AaSfPnuG7TC3)#b!jry@fHaO3hW z7eZdca^>K&rDg5ZDr=iXGMfl%amV51g4|}}b<4XvqTHyo%Y{zgUUTJ8x^a1z3t@W^ zAKQ zLJ3G8VGqke!O1m<5?abkH70SsdAvHoeL)x;DkOmte+l9=PDAOhdHUohy|b)sXZ2wP zHjAoSSig(CIF<@L8=@AmvdYPtIW)mb2BR^McgV|OjGq{O#8|CS?nQHF^k(D)v>aG) zVDUudwH%zoSI8o7d8%D7D?~SXViNy>7Id1`a7lwDl+i zW<>eL(%p{2M@_Lx^fWnMV$uAHikz*n)~Mb_z>@jiY0++-<4dMmlf(^Tw|2BAh`?aa zdB)v6N3f|g%w_=-pjIzNfB7>)9A<+_$5J}mFh{akDD)hma+aT!&9_#YDV%J8eID0> zIQ)ap8Q|awmc5X;EBUjfqFFJ`j*N^~7i(Nk4-K7~S*`N=A@U`oStqF|EPeSUEov#n zP6HPG#vDW1uc@knMUUNh-WOR$*%mQXbQKjav=VC#Z2V~RA6Q=&pz;H*v2rc1zy#7& zY;(!RO_@YOq8Lc&%KnT`lJHczW!G+mmLO*MrjyAOC zB2e-PTY+vE{6+6?fhhEr7dGs0R5U_~XRu5+2LDiw#8G2Xc80CGQ0u;-cIeB10%N9Z z?0P_>r>!(Jl1Z3MNP5F?QWkN1*QPyMTdvuMvRjf^<(m8Els*+iO(YNVakJ59T&Oe( zQ_egnmHS$IrR(=4mab3Dw(vlOPGQjL=Y>7ZTKUM0+0Tg%%0+z~1f!ArVmKD4`RSdy z>vFnRwMXx2R(oV|9p)@?bzufcnsOfReKLk3jm7pc8ELbwqAfT**&>8k+ig~0{%8aT z0u{aPNQkQLLZpPxX-0K;Pp70+KCMFtGJ_>Om^=)`wA71q?r?g~4w{zB8;CKcZ`ob2 z$%0Y2N9-axJcbCGG*0>M(3VqlWHoj-3di{J9MUOghLa(qvS-Q{Z)8TC*Hi8_*o;K9ix%{+DKyIe+hK=>iDUcQKe@Au=tm zcmYp1WvNa?H?zg*@2SWj^+9cF^y{315cAUF)w))p=P01b-k2F;#`et9%HyKmjnKL= zCQadxHHxBrBTT*RDZEf4L1tXr*W7w1?`M~YbWN6M>vg96hPr-u^|WcX z7b92;U_y_-m@Q1pIyCgMbTaMH1PGGI&dlJ1R#EN}z{0{Dvc`| zXe2~Q(3ep>+M=5H=6$IMpMF6;3_h?Qap2R}S>`J+^wFmV@S+Xylt_sg?er;Q*A-z1 z*o-MO%5`jIbJEk>MVKyNYQkY1Mh|XLDV(aqI2p%$Qo^o9tPB#vz<(5%w zvUTt7?Y=vaP~eTcicnt(X+muvzyBTz(%B$j6;AQuj@`X1<2gLCsxCUI-M!8;3AMY| zn(FON!{d0%;-<4ZO(=I~?q)K_c}_cS{o4>|Bn!!GPnLRN+t3vn0=21Amvg6BAa7>6Ko!}xo(0#-A)d7*UH4|MmC>b90; z=q7&pErk$Bk+|m+!4wxoZxXOZ)1*t$c1;Z6L~J#SNOF<=j?qNWtc5^UVVQ#? zS-4V2XJu_rT!7GO6%rcijMicy!y1e2g;DfM4V+)@lx6OwzG07eg7GOKl~W{AD6|)_ zXrw6|PmnYqtx#~uJ5Z2_CG6hR-efsdO6_;L0n0uD038B`qiZz?67g4wU=XABx;0*LQU@ynK3a!XXuu==p@-;jVIEG zS8d@fVhebn=1{WIFh!g&x)b(~fsY(i4zS~r2%6F9Z`1?J#nqLSHJpzFjhn^R=@O8p z>4tXMwEo0&>+~FP)VSuM1d>RjMKG!946b-!Jv^SoiWYd+Bb7s%&Y6_KqJQVAd>MmH z+eqQw5Wk*h$RQxUflLd-ly1g+74X%Ts^IRt)ekn8X93nQs1cwWBTXPyXwrvZkSRw5 z4@IY7?u&&tFkmJD_u^ntCzQ^531mWuM$cGIEq8l^(UOqCD=AD>@^!NWGkx1*Y04zd zNa8-8Qsf;P0w}q=8JT(tSh4C=+Qs4+Sk~%r_06|ll~}b_Rv}#I6+R}fOt+H+`?bYO z$>0$(>UG&h3%fgQ)5L!(;-x-FyW%)owzjf&9ix8N^^fu2e*y=V|?>P5--X zUyJ_RyPX2eL%#Y5hM zuj!diry!XcX>SuXxoKZbMGsT0CsLi|i4>@DM1uD#R#%)GW z2rN^+AGsZf2Nn#nQ47y$IS|{pufoerN*WBE%#NuIStg3~r)|pwS+_qST5Wk6%uF$9 zELCa?xOqt5sy|tSvRQ;m!KvT}dqGePj^LXDOv91%F$Hou7dCCbX|D+;Ur4OUXKj%#$VhBvW%I6w6}gR&XB~wD!6Q$dm47 zf59uI%B4-XUP(fvKH=Gct~I>Fm5jZ^@_NrqW-xb04mOog*I*$AE(h_+f5cl4B*Q`k zs{)B3D*(I#8HP8|2@IN~VN;)-$XUy(fRJQr=g=SuSQQCH2ag8$JE_~oOLN@*L8xEM z5>jIc(urD5GNi}BS+w1y1sNDp>#qW9eLIsguY5kmP5>hD*tI8lvW3yzQ}Si;IF`m0 z#R!&arBD&rK+2E}K{@P8tTa46OX0%Sdl?02jOff)00O^^zFWj73^hH%iZ$sf4n`_$ zR;Z+8-`wj=jL&6rGxIp4aUyGpTFbT~IPxY#9{WK7%q*Nwt9psrqumH^+nP`)sz5_vxLqT>LIWpY%b5zBf#}pjn+p*Akrz&8fx9%; zYb{Q;V-CTF97^#-q;(PGV+{r@Qn~2?;k}w*xg4>lw~SJ#&)t00o5*bSlK|0j5g`W1ST3-_Bt7!;q#dj7wAe!?e=@)Ptqa8^ z5o|)qE>nWFKoFqBCL8zc2f>cpXv5N_58Y%OZ%quoNq4&CnH*EGR6`w&o1CR;dBX?~ z5N|n8BUsZ3=PUDl5RNiK&ME5Ba##jKMG}=wanYlYDrduaj5g}sa0lg_6#5WP`SSG$ z=)hdM*G=w0US#H3AK`$@f^RN}ejgllT z9|V#h0D2g4uflG)0FA?Vt-CV^E7$Z>NXZ&s z(n%s80#E|u-ZAN4abwcAL&3BO)QY>(S8%|Hq@h;=t}JaNTi^M9lbid?<|YYSp246i z!}>2KG74Q(wS;MHiH0|3R0Vrs7gpK9TXB5X#_)8hyfNynXcMD@wvJ> zTGMDbm_%>SFSIke)JXKUQnjMe%DLdTDRb3pL>mCo?8{g{y2BU3YCVlCXJZq_6~{rS zyLN-(q6s6#X`_gC<#9T+JFYUl;EG*=^)+OR0%c_&vjkvw2(xYrmA3k1I?c}8CG=KG z0<=Bw*#>#t6rZr#Y&hLA`QS2Nyl;>xR0TP3j}R~{Mr|MIf;_Jgoq4tox;@Utn8rf4 zz?!wZ5U3?Bi>J4*LWZ$dPzjKFN7G*;hPpRaX^ljYfHN0W^dNjQHuZhKW>2$H#=YOz z)w>s)diRJRio1i)ifRsb%pP%`gScTzlHs5Q1x%A=T$xSw8Z0NZh*RSC>fs#Ws>L;| zPs@dfiGrv-g-hv+Xt@lQ3li{QP$~t?#gBTV8!I*2Zar_Mq<67k$B;UqRohcS zc}-(8;6+oqYaa(3w2P!vv|ijplwI2;nAPH8yJ&rZYrEK4v4OL(W}gUlcF?(+Nj-A% zf|5RM60jdyZsO}PF#Ln=3$uZ2opO*zXoJI6UkwXOWVQu%Rxllkv5~lpLU&OEL%AhL zhr3`N8y8HlV^Vu!M>LXIcov>6PrTMD@o7w4&k?K>%at{a5C}Bh7cHatcIiT+?Ts`@ z0FOgAQkokway*5iw^nm|nmJrg6t%ze8k(vvL{87@vF**jU}rcw08O(R8q%X+Xh>KV zhQZKKXh2VMry@7OEitsA;ahI}MA7 zF&+#8`vUOX93&K$SBZfvSQT&t(+9|H;FJmXE#Z~RQ&0cxb}rx2juuo&!xTeT3zsid(d1|qD?Egl6oOQv)l z8Ub4bL!&iYZ1G-+W}}^$uynYXZ!XiS!mJN?tFjLmenW6g?oNb=p`~+*4VrkpG0I%# zY9z?5)FwdUSO6Xy&~4bg_s~`<5K+XXc=&EN?ihpE~w+eizN z^Paidk>sM-Ei+o-yiB{YD(-!1V%-M;h&nc!eDU*I+-O|KtS<0nQ9HSl*I_YdSAzOx z>N+kj1F}%Kz9`%$N?02?ocZT>E2->80e0CS$^g-hT9YK8$X2CoN`$@2pQa3M*jml)QshJlaB?^cA(DZd01rv3N(9e02enu>&|@)EfYziHpiGU-Og! z_M8`M{*+;s#?Bpei9-gx7@0&Ea9l!TZ?mbi?$o`uspMKNk0jj`sNqCbg(90qks{+J z-gYPm$lMxPn(#`|kM_lu%X#}Uz<>^h`vcn8baRlq=8lo%GPQ+qLxC@nl2hiZPPjg{ z-Pw3k<(sK`Q)%@){u+|%>uf}_3XhWbvZ0y4rA%5D3+Lc)F>`oI^u_Cql|Vw23f-Yx zR21zn<*wblc-&|J`` or ```` + if completion_type: + options = auto_complete_paths(current, completion_type) + options = ((opt, 0) for opt in options) + for option in options: + opt_label = option[0] + # append '=' to options which require args + if option[1] and option[0][:2] == "--": + opt_label += '=' + print(opt_label) + else: + # show main parser options only when necessary + + opts = [i.option_list for i in parser.option_groups] + opts.append(parser.option_list) + opts = (o for it in opts for o in it) + if current.startswith('-'): + for opt in opts: + if opt.help != optparse.SUPPRESS_HELP: + subcommands += opt._long_opts + opt._short_opts + else: + # get completion type given cwords and all available options + completion_type = get_path_completion_type(cwords, cword, opts) + if completion_type: + subcommands = auto_complete_paths(current, completion_type) + + print(' '.join([x for x in subcommands if x.startswith(current)])) + sys.exit(1) + + +def get_path_completion_type(cwords, cword, opts): + """Get the type of path completion (``file``, ``dir``, ``path`` or None) + + :param cwords: same as the environmental variable ``COMP_WORDS`` + :param cword: same as the environmental variable ``COMP_CWORD`` + :param opts: The available options to check + :return: path completion type (``file``, ``dir``, ``path`` or None) + """ + if cword < 2 or not cwords[cword - 2].startswith('-'): + return + for opt in opts: + if opt.help == optparse.SUPPRESS_HELP: + continue + for o in str(opt).split('/'): + if cwords[cword - 2].split('=')[0] == o: + if not opt.metavar or any( + x in ('path', 'file', 'dir') + for x in opt.metavar.split('/')): + return opt.metavar + + +def auto_complete_paths(current, completion_type): + """If ``completion_type`` is ``file`` or ``path``, list all regular files + and directories starting with ``current``; otherwise only list directories + starting with ``current``. + + :param current: The word to be completed + :param completion_type: path completion type(`file`, `path` or `dir`)i + :return: A generator of regular files and/or directories + """ + directory, filename = os.path.split(current) + current_path = os.path.abspath(directory) + # Don't complete paths if they can't be accessed + if not os.access(current_path, os.R_OK): + return + filename = os.path.normcase(filename) + # list all files that start with ``filename`` + file_list = (x for x in os.listdir(current_path) + if os.path.normcase(x).startswith(filename)) + for f in file_list: + opt = os.path.join(current_path, f) + comp_file = os.path.normcase(os.path.join(directory, f)) + # complete regular files when there is not ```` after option + # complete directories when there is ````, ```` or + # ````after option + if completion_type != 'dir' and os.path.isfile(opt): + yield comp_file + elif os.path.isdir(opt): + yield os.path.join(comp_file, '') diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/base_command.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/base_command.py new file mode 100644 index 0000000..dac4b05 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/base_command.py @@ -0,0 +1,278 @@ +"""Base Command class, and related routines""" +from __future__ import absolute_import + +import logging +import logging.config +import optparse +import os +import sys + +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ( + ConfigOptionParser, UpdatingDefaultsHelpFormatter, +) +from pip._internal.cli.status_codes import ( + ERROR, PREVIOUS_BUILD_DIR_ERROR, SUCCESS, UNKNOWN_ERROR, + VIRTUALENV_NOT_FOUND, +) +from pip._internal.download import PipSession +from pip._internal.exceptions import ( + BadCommand, CommandError, InstallationError, PreviousBuildDirError, + UninstallationError, +) +from pip._internal.index import PackageFinder +from pip._internal.locations import running_under_virtualenv +from pip._internal.req.constructors import ( + install_req_from_editable, install_req_from_line, +) +from pip._internal.req.req_file import parse_requirements +from pip._internal.utils.logging import setup_logging +from pip._internal.utils.misc import get_prog, normalize_path +from pip._internal.utils.outdated import pip_version_check +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional # noqa: F401 + +__all__ = ['Command'] + +logger = logging.getLogger(__name__) + + +class Command(object): + name = None # type: Optional[str] + usage = None # type: Optional[str] + hidden = False # type: bool + ignore_require_venv = False # type: bool + + def __init__(self, isolated=False): + parser_kw = { + 'usage': self.usage, + 'prog': '%s %s' % (get_prog(), self.name), + 'formatter': UpdatingDefaultsHelpFormatter(), + 'add_help_option': False, + 'name': self.name, + 'description': self.__doc__, + 'isolated': isolated, + } + + self.parser = ConfigOptionParser(**parser_kw) + + # Commands should add options to this option group + optgroup_name = '%s Options' % self.name.capitalize() + self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) + + # Add the general options + gen_opts = cmdoptions.make_option_group( + cmdoptions.general_group, + self.parser, + ) + self.parser.add_option_group(gen_opts) + + def _build_session(self, options, retries=None, timeout=None): + session = PipSession( + cache=( + normalize_path(os.path.join(options.cache_dir, "http")) + if options.cache_dir else None + ), + retries=retries if retries is not None else options.retries, + insecure_hosts=options.trusted_hosts, + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = ( + timeout if timeout is not None else options.timeout + ) + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + + return session + + def parse_args(self, args): + # factored out for testability + return self.parser.parse_args(args) + + def main(self, args): + options, args = self.parse_args(args) + + # Set verbosity so that it can be used elsewhere. + self.verbosity = options.verbose - options.quiet + + setup_logging( + verbosity=self.verbosity, + no_color=options.no_color, + user_log_file=options.log, + ) + + # TODO: Try to get these passing down from the command? + # without resorting to os.environ to hold these. + # This also affects isolated builds and it should. + + if options.no_input: + os.environ['PIP_NO_INPUT'] = '1' + + if options.exists_action: + os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) + + if options.require_venv and not self.ignore_require_venv: + # If a venv is required check if it can really be found + if not running_under_virtualenv(): + logger.critical( + 'Could not find an activated virtualenv (required).' + ) + sys.exit(VIRTUALENV_NOT_FOUND) + + try: + status = self.run(options, args) + # FIXME: all commands should return an exit status + # and when it is done, isinstance is not needed anymore + if isinstance(status, int): + return status + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug('Exception information:', exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except (InstallationError, UninstallationError, BadCommand) as exc: + logger.critical(str(exc)) + logger.debug('Exception information:', exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical('ERROR: %s', exc) + logger.debug('Exception information:', exc_info=True) + + return ERROR + except KeyboardInterrupt: + logger.critical('Operation cancelled by user') + logger.debug('Exception information:', exc_info=True) + + return ERROR + except BaseException: + logger.critical('Exception:', exc_info=True) + + return UNKNOWN_ERROR + finally: + allow_version_check = ( + # Does this command have the index_group options? + hasattr(options, "no_index") and + # Is this command allowed to perform this check? + not (options.disable_pip_version_check or options.no_index) + ) + # Check if we're using the latest version of pip available + if allow_version_check: + session = self._build_session( + options, + retries=0, + timeout=min(5, options.timeout) + ) + with session: + pip_version_check(session, options) + + # Shutdown the logging module + logging.shutdown() + + return SUCCESS + + +class RequirementCommand(Command): + + @staticmethod + def populate_requirement_set(requirement_set, args, options, finder, + session, name, wheel_cache): + """ + Marshal cmd line args into a requirement set. + """ + # NOTE: As a side-effect, options.require_hashes and + # requirement_set.require_hashes may be updated + + for filename in options.constraints: + for req_to_add in parse_requirements( + filename, + constraint=True, finder=finder, options=options, + session=session, wheel_cache=wheel_cache): + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for req in args: + req_to_add = install_req_from_line( + req, None, isolated=options.isolated_mode, + wheel_cache=wheel_cache + ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for req in options.editables: + req_to_add = install_req_from_editable( + req, + isolated=options.isolated_mode, + wheel_cache=wheel_cache + ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for filename in options.requirements: + for req_to_add in parse_requirements( + filename, + finder=finder, options=options, session=session, + wheel_cache=wheel_cache): + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + # If --require-hashes was a line in a requirements file, tell + # RequirementSet about it: + requirement_set.require_hashes = options.require_hashes + + if not (args or options.editables or options.requirements): + opts = {'name': name} + if options.find_links: + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(maybe you meant "pip %(name)s %(links)s"?)' % + dict(opts, links=' '.join(options.find_links))) + else: + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(see "pip help %(name)s")' % opts) + + def _build_package_finder(self, options, session, + platform=None, python_versions=None, + abi=None, implementation=None): + """ + Create a package finder appropriate to this requirement command. + """ + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index: + logger.debug('Ignoring indexes: %s', ','.join(index_urls)) + index_urls = [] + + return PackageFinder( + find_links=options.find_links, + format_control=options.format_control, + index_urls=index_urls, + trusted_hosts=options.trusted_hosts, + allow_all_prereleases=options.pre, + process_dependency_links=options.process_dependency_links, + session=session, + platform=platform, + versions=python_versions, + abi=abi, + implementation=implementation, + prefer_binary=options.prefer_binary, + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/cmdoptions.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/cmdoptions.py new file mode 100644 index 0000000..3033cd4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/cmdoptions.py @@ -0,0 +1,714 @@ +""" +shared options and groups + +The principle here is to define options once, but *not* instantiate them +globally. One reason being that options with action='append' can carry state +between parses. pip parses general options twice internally, and shouldn't +pass on state. To be consistent, all options will follow this design. + +""" +from __future__ import absolute_import + +import warnings +from functools import partial +from optparse import SUPPRESS_HELP, Option, OptionGroup + +from pip._internal.exceptions import CommandError +from pip._internal.locations import USER_CACHE_DIR, src_prefix +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.utils.hashes import STRONG_HASHES +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.ui import BAR_TYPES + +if MYPY_CHECK_RUNNING: + from typing import Any # noqa: F401 + + +def make_option_group(group, parser): + """ + Return an OptionGroup object + group -- assumed to be dict with 'name' and 'options' keys + parser -- an optparse Parser + """ + option_group = OptionGroup(parser, group['name']) + for option in group['options']: + option_group.add_option(option()) + return option_group + + +def check_install_build_global(options, check_options=None): + """Disable wheels if per-setup.py call options are set. + + :param options: The OptionParser options to update. + :param check_options: The options to check, if not supplied defaults to + options. + """ + if check_options is None: + check_options = options + + def getname(n): + return getattr(check_options, n, None) + names = ["build_options", "global_options", "install_options"] + if any(map(getname, names)): + control = options.format_control + control.disallow_binaries() + warnings.warn( + 'Disabling all use of wheels due to the use of --build-options ' + '/ --global-options / --install-options.', stacklevel=2, + ) + + +def check_dist_restriction(options, check_target=False): + """Function for determining if custom platform options are allowed. + + :param options: The OptionParser options. + :param check_target: Whether or not to check if --target is being used. + """ + dist_restriction_set = any([ + options.python_version, + options.platform, + options.abi, + options.implementation, + ]) + + binary_only = FormatControl(set(), {':all:'}) + sdist_dependencies_allowed = ( + options.format_control != binary_only and + not options.ignore_dependencies + ) + + # Installations or downloads using dist restrictions must not combine + # source distributions and dist-specific wheels, as they are not + # gauranteed to be locally compatible. + if dist_restriction_set and sdist_dependencies_allowed: + raise CommandError( + "When restricting platform and interpreter constraints using " + "--python-version, --platform, --abi, or --implementation, " + "either --no-deps must be set, or --only-binary=:all: must be " + "set and --no-binary must not be set (or must be set to " + ":none:)." + ) + + if check_target: + if dist_restriction_set and not options.target_dir: + raise CommandError( + "Can not use any platform or abi specific options unless " + "installing via '--target'" + ) + + +########### +# options # +########### + +help_ = partial( + Option, + '-h', '--help', + dest='help', + action='help', + help='Show help.', +) # type: Any + +isolated_mode = partial( + Option, + "--isolated", + dest="isolated_mode", + action="store_true", + default=False, + help=( + "Run pip in an isolated mode, ignoring environment variables and user " + "configuration." + ), +) + +require_virtualenv = partial( + Option, + # Run only if inside a virtualenv, bail if not. + '--require-virtualenv', '--require-venv', + dest='require_venv', + action='store_true', + default=False, + help=SUPPRESS_HELP +) # type: Any + +verbose = partial( + Option, + '-v', '--verbose', + dest='verbose', + action='count', + default=0, + help='Give more output. Option is additive, and can be used up to 3 times.' +) + +no_color = partial( + Option, + '--no-color', + dest='no_color', + action='store_true', + default=False, + help="Suppress colored output", +) + +version = partial( + Option, + '-V', '--version', + dest='version', + action='store_true', + help='Show version and exit.', +) # type: Any + +quiet = partial( + Option, + '-q', '--quiet', + dest='quiet', + action='count', + default=0, + help=( + 'Give less output. Option is additive, and can be used up to 3' + ' times (corresponding to WARNING, ERROR, and CRITICAL logging' + ' levels).' + ), +) # type: Any + +progress_bar = partial( + Option, + '--progress-bar', + dest='progress_bar', + type='choice', + choices=list(BAR_TYPES.keys()), + default='on', + help=( + 'Specify type of progress to be displayed [' + + '|'.join(BAR_TYPES.keys()) + '] (default: %default)' + ), +) # type: Any + +log = partial( + Option, + "--log", "--log-file", "--local-log", + dest="log", + metavar="path", + help="Path to a verbose appending log." +) # type: Any + +no_input = partial( + Option, + # Don't ask for input + '--no-input', + dest='no_input', + action='store_true', + default=False, + help=SUPPRESS_HELP +) # type: Any + +proxy = partial( + Option, + '--proxy', + dest='proxy', + type='str', + default='', + help="Specify a proxy in the form [user:passwd@]proxy.server:port." +) # type: Any + +retries = partial( + Option, + '--retries', + dest='retries', + type='int', + default=5, + help="Maximum number of retries each connection should attempt " + "(default %default times).", +) # type: Any + +timeout = partial( + Option, + '--timeout', '--default-timeout', + metavar='sec', + dest='timeout', + type='float', + default=15, + help='Set the socket timeout (default %default seconds).', +) # type: Any + +skip_requirements_regex = partial( + Option, + # A regex to be used to skip requirements + '--skip-requirements-regex', + dest='skip_requirements_regex', + type='str', + default='', + help=SUPPRESS_HELP, +) # type: Any + + +def exists_action(): + return Option( + # Option when path already exist + '--exists-action', + dest='exists_action', + type='choice', + choices=['s', 'i', 'w', 'b', 'a'], + default=[], + action='append', + metavar='action', + help="Default action when a path already exists: " + "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort).", + ) + + +cert = partial( + Option, + '--cert', + dest='cert', + type='str', + metavar='path', + help="Path to alternate CA bundle.", +) # type: Any + +client_cert = partial( + Option, + '--client-cert', + dest='client_cert', + type='str', + default=None, + metavar='path', + help="Path to SSL client certificate, a single file containing the " + "private key and the certificate in PEM format.", +) # type: Any + +index_url = partial( + Option, + '-i', '--index-url', '--pypi-url', + dest='index_url', + metavar='URL', + default=PyPI.simple_url, + help="Base URL of Python Package Index (default %default). " + "This should point to a repository compliant with PEP 503 " + "(the simple repository API) or a local directory laid out " + "in the same format.", +) # type: Any + + +def extra_index_url(): + return Option( + '--extra-index-url', + dest='extra_index_urls', + metavar='URL', + action='append', + default=[], + help="Extra URLs of package indexes to use in addition to " + "--index-url. Should follow the same rules as " + "--index-url.", + ) + + +no_index = partial( + Option, + '--no-index', + dest='no_index', + action='store_true', + default=False, + help='Ignore package index (only looking at --find-links URLs instead).', +) # type: Any + + +def find_links(): + return Option( + '-f', '--find-links', + dest='find_links', + action='append', + default=[], + metavar='url', + help="If a url or path to an html file, then parse for links to " + "archives. If a local path or file:// url that's a directory, " + "then look for archives in the directory listing.", + ) + + +def trusted_host(): + return Option( + "--trusted-host", + dest="trusted_hosts", + action="append", + metavar="HOSTNAME", + default=[], + help="Mark this host as trusted, even though it does not have valid " + "or any HTTPS.", + ) + + +# Remove after 1.5 +process_dependency_links = partial( + Option, + "--process-dependency-links", + dest="process_dependency_links", + action="store_true", + default=False, + help="Enable the processing of dependency links.", +) # type: Any + + +def constraints(): + return Option( + '-c', '--constraint', + dest='constraints', + action='append', + default=[], + metavar='file', + help='Constrain versions using the given constraints file. ' + 'This option can be used multiple times.' + ) + + +def requirements(): + return Option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help='Install from the given requirements file. ' + 'This option can be used multiple times.' + ) + + +def editable(): + return Option( + '-e', '--editable', + dest='editables', + action='append', + default=[], + metavar='path/url', + help=('Install a project in editable mode (i.e. setuptools ' + '"develop mode") from a local project path or a VCS url.'), + ) + + +src = partial( + Option, + '--src', '--source', '--source-dir', '--source-directory', + dest='src_dir', + metavar='dir', + default=src_prefix, + help='Directory to check out editable projects into. ' + 'The default in a virtualenv is "/src". ' + 'The default for global installs is "/src".' +) # type: Any + + +def _get_format_control(values, option): + """Get a format_control object.""" + return getattr(values, option.dest) + + +def _handle_no_binary(option, opt_str, value, parser): + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, existing.no_binary, existing.only_binary, + ) + + +def _handle_only_binary(option, opt_str, value, parser): + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, existing.only_binary, existing.no_binary, + ) + + +def no_binary(): + format_control = FormatControl(set(), set()) + return Option( + "--no-binary", dest="format_control", action="callback", + callback=_handle_no_binary, type="str", + default=format_control, + help="Do not use binary packages. Can be supplied multiple times, and " + "each time adds to the existing value. Accepts either :all: to " + "disable all binary packages, :none: to empty the set, or one or " + "more package names with commas between them. Note that some " + "packages are tricky to compile and may fail to install when " + "this option is used on them.", + ) + + +def only_binary(): + format_control = FormatControl(set(), set()) + return Option( + "--only-binary", dest="format_control", action="callback", + callback=_handle_only_binary, type="str", + default=format_control, + help="Do not use source packages. Can be supplied multiple times, and " + "each time adds to the existing value. Accepts either :all: to " + "disable all source packages, :none: to empty the set, or one or " + "more package names with commas between them. Packages without " + "binary distributions will fail to install when this option is " + "used on them.", + ) + + +platform = partial( + Option, + '--platform', + dest='platform', + metavar='platform', + default=None, + help=("Only use wheels compatible with . " + "Defaults to the platform of the running system."), +) + + +python_version = partial( + Option, + '--python-version', + dest='python_version', + metavar='python_version', + default=None, + help=("Only use wheels compatible with Python " + "interpreter version . If not specified, then the " + "current system interpreter minor version is used. A major " + "version (e.g. '2') can be specified to match all " + "minor revs of that major version. A minor version " + "(e.g. '34') can also be specified."), +) + + +implementation = partial( + Option, + '--implementation', + dest='implementation', + metavar='implementation', + default=None, + help=("Only use wheels compatible with Python " + "implementation , e.g. 'pp', 'jy', 'cp', " + " or 'ip'. If not specified, then the current " + "interpreter implementation is used. Use 'py' to force " + "implementation-agnostic wheels."), +) + + +abi = partial( + Option, + '--abi', + dest='abi', + metavar='abi', + default=None, + help=("Only use wheels compatible with Python " + "abi , e.g. 'pypy_41'. If not specified, then the " + "current interpreter abi tag is used. Generally " + "you will need to specify --implementation, " + "--platform, and --python-version when using " + "this option."), +) + + +def prefer_binary(): + return Option( + "--prefer-binary", + dest="prefer_binary", + action="store_true", + default=False, + help="Prefer older binary packages over newer source packages." + ) + + +cache_dir = partial( + Option, + "--cache-dir", + dest="cache_dir", + default=USER_CACHE_DIR, + metavar="dir", + help="Store the cache data in ." +) + +no_cache = partial( + Option, + "--no-cache-dir", + dest="cache_dir", + action="store_false", + help="Disable the cache.", +) + +no_deps = partial( + Option, + '--no-deps', '--no-dependencies', + dest='ignore_dependencies', + action='store_true', + default=False, + help="Don't install package dependencies.", +) # type: Any + +build_dir = partial( + Option, + '-b', '--build', '--build-dir', '--build-directory', + dest='build_dir', + metavar='dir', + help='Directory to unpack packages into and build in. Note that ' + 'an initial build still takes place in a temporary directory. ' + 'The location of temporary directories can be controlled by setting ' + 'the TMPDIR environment variable (TEMP on Windows) appropriately. ' + 'When passed, build directories are not cleaned in case of failures.' +) # type: Any + +ignore_requires_python = partial( + Option, + '--ignore-requires-python', + dest='ignore_requires_python', + action='store_true', + help='Ignore the Requires-Python information.' +) # type: Any + +no_build_isolation = partial( + Option, + '--no-build-isolation', + dest='build_isolation', + action='store_false', + default=True, + help='Disable isolation when building a modern source distribution. ' + 'Build dependencies specified by PEP 518 must be already installed ' + 'if this option is used.' +) # type: Any + +install_options = partial( + Option, + '--install-option', + dest='install_options', + action='append', + metavar='options', + help="Extra arguments to be supplied to the setup.py install " + "command (use like --install-option=\"--install-scripts=/usr/local/" + "bin\"). Use multiple --install-option options to pass multiple " + "options to setup.py install. If you are using an option with a " + "directory path, be sure to use absolute path.", +) # type: Any + +global_options = partial( + Option, + '--global-option', + dest='global_options', + action='append', + metavar='options', + help="Extra global options to be supplied to the setup.py " + "call before the install command.", +) # type: Any + +no_clean = partial( + Option, + '--no-clean', + action='store_true', + default=False, + help="Don't clean up build directories." +) # type: Any + +pre = partial( + Option, + '--pre', + action='store_true', + default=False, + help="Include pre-release and development versions. By default, " + "pip only finds stable versions.", +) # type: Any + +disable_pip_version_check = partial( + Option, + "--disable-pip-version-check", + dest="disable_pip_version_check", + action="store_true", + default=False, + help="Don't periodically check PyPI to determine whether a new version " + "of pip is available for download. Implied with --no-index.", +) # type: Any + + +# Deprecated, Remove later +always_unzip = partial( + Option, + '-Z', '--always-unzip', + dest='always_unzip', + action='store_true', + help=SUPPRESS_HELP, +) # type: Any + + +def _merge_hash(option, opt_str, value, parser): + """Given a value spelled "algo:digest", append the digest to a list + pointed to in a dict by the algo name.""" + if not parser.values.hashes: + parser.values.hashes = {} + try: + algo, digest = value.split(':', 1) + except ValueError: + parser.error('Arguments to %s must be a hash name ' + 'followed by a value, like --hash=sha256:abcde...' % + opt_str) + if algo not in STRONG_HASHES: + parser.error('Allowed hash algorithms for %s are %s.' % + (opt_str, ', '.join(STRONG_HASHES))) + parser.values.hashes.setdefault(algo, []).append(digest) + + +hash = partial( + Option, + '--hash', + # Hash values eventually end up in InstallRequirement.hashes due to + # __dict__ copying in process_line(). + dest='hashes', + action='callback', + callback=_merge_hash, + type='string', + help="Verify that the package's archive matches this " + 'hash before installing. Example: --hash=sha256:abcdef...', +) # type: Any + + +require_hashes = partial( + Option, + '--require-hashes', + dest='require_hashes', + action='store_true', + default=False, + help='Require a hash to check each requirement against, for ' + 'repeatable installs. This option is implied when any package in a ' + 'requirements file has a --hash option.', +) # type: Any + + +########## +# groups # +########## + +general_group = { + 'name': 'General Options', + 'options': [ + help_, + isolated_mode, + require_virtualenv, + verbose, + version, + quiet, + log, + no_input, + proxy, + retries, + timeout, + skip_requirements_regex, + exists_action, + trusted_host, + cert, + client_cert, + cache_dir, + no_cache, + disable_pip_version_check, + no_color, + ] +} + +index_group = { + 'name': 'Package Index Options', + 'options': [ + index_url, + extra_index_url, + no_index, + find_links, + process_dependency_links, + ] +} diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/main_parser.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/main_parser.py new file mode 100644 index 0000000..1774a6b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/main_parser.py @@ -0,0 +1,96 @@ +"""A single place for constructing and exposing the main parser +""" + +import os +import sys + +from pip import __version__ +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ( + ConfigOptionParser, UpdatingDefaultsHelpFormatter, +) +from pip._internal.commands import ( + commands_dict, get_similar_commands, get_summaries, +) +from pip._internal.exceptions import CommandError +from pip._internal.utils.misc import get_prog + +__all__ = ["create_main_parser", "parse_command"] + + +def create_main_parser(): + """Creates and returns the main parser for pip's CLI + """ + + parser_kw = { + 'usage': '\n%prog [options]', + 'add_help_option': False, + 'formatter': UpdatingDefaultsHelpFormatter(), + 'name': 'global', + 'prog': get_prog(), + } + + parser = ConfigOptionParser(**parser_kw) + parser.disable_interspersed_args() + + pip_pkg_dir = os.path.abspath(os.path.join( + os.path.dirname(__file__), "..", "..", + )) + parser.version = 'pip %s from %s (python %s)' % ( + __version__, pip_pkg_dir, sys.version[:3], + ) + + # add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) + parser.add_option_group(gen_opts) + + parser.main = True # so the help formatter knows + + # create command listing for description + command_summaries = get_summaries() + description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] + parser.description = '\n'.join(description) + + return parser + + +def parse_command(args): + parser = create_main_parser() + + # Note: parser calls disable_interspersed_args(), so the result of this + # call is to split the initial args into the general options before the + # subcommand and everything else. + # For example: + # args: ['--timeout=5', 'install', '--user', 'INITools'] + # general_options: ['--timeout==5'] + # args_else: ['install', '--user', 'INITools'] + general_options, args_else = parser.parse_args(args) + + # --version + if general_options.version: + sys.stdout.write(parser.version) + sys.stdout.write(os.linesep) + sys.exit() + + # pip || pip help -> print_help() + if not args_else or (args_else[0] == 'help' and len(args_else) == 1): + parser.print_help() + sys.exit() + + # the subcommand name + cmd_name = args_else[0] + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = ['unknown command "%s"' % cmd_name] + if guess: + msg.append('maybe you meant "%s"' % guess) + + raise CommandError(' - '.join(msg)) + + # all the args without the subcommand + cmd_args = args[:] + cmd_args.remove(cmd_name) + + return cmd_name, cmd_args diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/parser.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/parser.py new file mode 100644 index 0000000..e1eaac4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/parser.py @@ -0,0 +1,261 @@ +"""Base option parser setup""" +from __future__ import absolute_import + +import logging +import optparse +import sys +import textwrap +from distutils.util import strtobool + +from pip._vendor.six import string_types + +from pip._internal.cli.status_codes import UNKNOWN_ERROR +from pip._internal.configuration import Configuration, ConfigurationError +from pip._internal.utils.compat import get_terminal_size + +logger = logging.getLogger(__name__) + + +class PrettyHelpFormatter(optparse.IndentedHelpFormatter): + """A prettier/less verbose help formatter for optparse.""" + + def __init__(self, *args, **kwargs): + # help position must be aligned with __init__.parseopts.description + kwargs['max_help_position'] = 30 + kwargs['indent_increment'] = 1 + kwargs['width'] = get_terminal_size()[0] - 2 + optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs) + + def format_option_strings(self, option): + return self._format_option_strings(option, ' <%s>', ', ') + + def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '): + """ + Return a comma-separated list of option strings and metavars. + + :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') + :param mvarfmt: metavar format string - evaluated as mvarfmt % metavar + :param optsep: separator + """ + opts = [] + + if option._short_opts: + opts.append(option._short_opts[0]) + if option._long_opts: + opts.append(option._long_opts[0]) + if len(opts) > 1: + opts.insert(1, optsep) + + if option.takes_value(): + metavar = option.metavar or option.dest.lower() + opts.append(mvarfmt % metavar.lower()) + + return ''.join(opts) + + def format_heading(self, heading): + if heading == 'Options': + return '' + return heading + ':\n' + + def format_usage(self, usage): + """ + Ensure there is only one newline between usage and the first heading + if there is no description. + """ + msg = '\nUsage: %s\n' % self.indent_lines(textwrap.dedent(usage), " ") + return msg + + def format_description(self, description): + # leave full control over description to us + if description: + if hasattr(self.parser, 'main'): + label = 'Commands' + else: + label = 'Description' + # some doc strings have initial newlines, some don't + description = description.lstrip('\n') + # some doc strings have final newlines and spaces, some don't + description = description.rstrip() + # dedent, then reindent + description = self.indent_lines(textwrap.dedent(description), " ") + description = '%s:\n%s\n' % (label, description) + return description + else: + return '' + + def format_epilog(self, epilog): + # leave full control over epilog to us + if epilog: + return epilog + else: + return '' + + def indent_lines(self, text, indent): + new_lines = [indent + line for line in text.split('\n')] + return "\n".join(new_lines) + + +class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): + """Custom help formatter for use in ConfigOptionParser. + + This is updates the defaults before expanding them, allowing + them to show up correctly in the help listing. + """ + + def expand_default(self, option): + if self.parser is not None: + self.parser._update_defaults(self.parser.defaults) + return optparse.IndentedHelpFormatter.expand_default(self, option) + + +class CustomOptionParser(optparse.OptionParser): + + def insert_option_group(self, idx, *args, **kwargs): + """Insert an OptionGroup at a given position.""" + group = self.add_option_group(*args, **kwargs) + + self.option_groups.pop() + self.option_groups.insert(idx, group) + + return group + + @property + def option_list_all(self): + """Get a list of all options, including those in option groups.""" + res = self.option_list[:] + for i in self.option_groups: + res.extend(i.option_list) + + return res + + +class ConfigOptionParser(CustomOptionParser): + """Custom option parser which updates its defaults by checking the + configuration files and environmental variables""" + + def __init__(self, *args, **kwargs): + self.name = kwargs.pop('name') + + isolated = kwargs.pop("isolated", False) + self.config = Configuration(isolated) + + assert self.name + optparse.OptionParser.__init__(self, *args, **kwargs) + + def check_default(self, option, key, val): + try: + return option.check_value(key, val) + except optparse.OptionValueError as exc: + print("An error occurred during configuration: %s" % exc) + sys.exit(3) + + def _get_ordered_configuration_items(self): + # Configuration gives keys in an unordered manner. Order them. + override_order = ["global", self.name, ":env:"] + + # Pool the options into different groups + section_items = {name: [] for name in override_order} + for section_key, val in self.config.items(): + # ignore empty values + if not val: + logger.debug( + "Ignoring configuration key '%s' as it's value is empty.", + section_key + ) + continue + + section, key = section_key.split(".", 1) + if section in override_order: + section_items[section].append((key, val)) + + # Yield each group in their override order + for section in override_order: + for key, val in section_items[section]: + yield key, val + + def _update_defaults(self, defaults): + """Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists).""" + + # Accumulate complex default state. + self.values = optparse.Values(self.defaults) + late_eval = set() + # Then set the options with those values + for key, val in self._get_ordered_configuration_items(): + # '--' because configuration supports only long names + option = self.get_option('--' + key) + + # Ignore options not present in this parser. E.g. non-globals put + # in [global] by users that want them to apply to all applicable + # commands. + if option is None: + continue + + if option.action in ('store_true', 'store_false', 'count'): + try: + val = strtobool(val) + except ValueError: + error_msg = invalid_config_error_message( + option.action, key, val + ) + self.error(error_msg) + + elif option.action == 'append': + val = val.split() + val = [self.check_default(option, key, v) for v in val] + elif option.action == 'callback': + late_eval.add(option.dest) + opt_str = option.get_opt_string() + val = option.convert_value(opt_str, val) + # From take_action + args = option.callback_args or () + kwargs = option.callback_kwargs or {} + option.callback(option, opt_str, val, self, *args, **kwargs) + else: + val = self.check_default(option, key, val) + + defaults[option.dest] = val + + for key in late_eval: + defaults[key] = getattr(self.values, key) + self.values = None + return defaults + + def get_default_values(self): + """Overriding to make updating the defaults after instantiation of + the option parser possible, _update_defaults() does the dirty work.""" + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + # Load the configuration, or error out in case of an error + try: + self.config.load() + except ConfigurationError as err: + self.exit(UNKNOWN_ERROR, str(err)) + + defaults = self._update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + default = defaults.get(option.dest) + if isinstance(default, string_types): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + def error(self, msg): + self.print_usage(sys.stderr) + self.exit(UNKNOWN_ERROR, "%s\n" % msg) + + +def invalid_config_error_message(action, key, val): + """Returns a better error message when invalid configuration option + is provided.""" + if action in ('store_true', 'store_false'): + return ("{0} is not a valid value for {1} option, " + "please specify a boolean value like yes/no, " + "true/false or 1/0 instead.").format(val, key) + + return ("{0} is not a valid value for {1} option, " + "please specify a numerical value like 1/0 " + "instead.").format(val, key) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/status_codes.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/status_codes.py new file mode 100644 index 0000000..275360a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/status_codes.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 +VIRTUALENV_NOT_FOUND = 3 +PREVIOUS_BUILD_DIR_ERROR = 4 +NO_MATCHES_FOUND = 23 diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/__init__.py new file mode 100644 index 0000000..c7d1da3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/__init__.py @@ -0,0 +1,79 @@ +""" +Package containing all pip commands +""" +from __future__ import absolute_import + +from pip._internal.commands.completion import CompletionCommand +from pip._internal.commands.configuration import ConfigurationCommand +from pip._internal.commands.download import DownloadCommand +from pip._internal.commands.freeze import FreezeCommand +from pip._internal.commands.hash import HashCommand +from pip._internal.commands.help import HelpCommand +from pip._internal.commands.list import ListCommand +from pip._internal.commands.check import CheckCommand +from pip._internal.commands.search import SearchCommand +from pip._internal.commands.show import ShowCommand +from pip._internal.commands.install import InstallCommand +from pip._internal.commands.uninstall import UninstallCommand +from pip._internal.commands.wheel import WheelCommand + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Type # noqa: F401 + from pip._internal.cli.base_command import Command # noqa: F401 + +commands_order = [ + InstallCommand, + DownloadCommand, + UninstallCommand, + FreezeCommand, + ListCommand, + ShowCommand, + CheckCommand, + ConfigurationCommand, + SearchCommand, + WheelCommand, + HashCommand, + CompletionCommand, + HelpCommand, +] # type: List[Type[Command]] + +commands_dict = {c.name: c for c in commands_order} + + +def get_summaries(ordered=True): + """Yields sorted (command name, command summary) tuples.""" + + if ordered: + cmditems = _sort_commands(commands_dict, commands_order) + else: + cmditems = commands_dict.items() + + for name, command_class in cmditems: + yield (name, command_class.summary) + + +def get_similar_commands(name): + """Command name auto-correct.""" + from difflib import get_close_matches + + name = name.lower() + + close_commands = get_close_matches(name, commands_dict.keys()) + + if close_commands: + return close_commands[0] + else: + return False + + +def _sort_commands(cmddict, order): + def keyfn(key): + try: + return order.index(key[1]) + except ValueError: + # unordered items should come last + return 0xff + + return sorted(cmddict.items(), key=keyfn) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/check.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/check.py new file mode 100644 index 0000000..1be3ec2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/check.py @@ -0,0 +1,41 @@ +import logging + +from pip._internal.cli.base_command import Command +from pip._internal.operations.check import ( + check_package_set, create_package_set_from_installed, +) + +logger = logging.getLogger(__name__) + + +class CheckCommand(Command): + """Verify installed packages have compatible dependencies.""" + name = 'check' + usage = """ + %prog [options]""" + summary = 'Verify installed packages have compatible dependencies.' + + def run(self, options, args): + package_set = create_package_set_from_installed() + missing, conflicting = check_package_set(package_set) + + for project_name in missing: + version = package_set[project_name].version + for dependency in missing[project_name]: + logger.info( + "%s %s requires %s, which is not installed.", + project_name, version, dependency[0], + ) + + for project_name in conflicting: + version = package_set[project_name].version + for dep_name, dep_version, req in conflicting[project_name]: + logger.info( + "%s %s has requirement %s, but you have %s %s.", + project_name, version, req, dep_name, dep_version, + ) + + if missing or conflicting: + return 1 + else: + logger.info("No broken requirements found.") diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/completion.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/completion.py new file mode 100644 index 0000000..2fcdd39 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/completion.py @@ -0,0 +1,94 @@ +from __future__ import absolute_import + +import sys +import textwrap + +from pip._internal.cli.base_command import Command +from pip._internal.utils.misc import get_prog + +BASE_COMPLETION = """ +# pip %(shell)s completion start%(script)s# pip %(shell)s completion end +""" + +COMPLETION_SCRIPTS = { + 'bash': """ + _pip_completion() + { + COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\ + COMP_CWORD=$COMP_CWORD \\ + PIP_AUTO_COMPLETE=1 $1 ) ) + } + complete -o default -F _pip_completion %(prog)s + """, + 'zsh': """ + function _pip_completion { + local words cword + read -Ac words + read -cn cword + reply=( $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$(( cword-1 )) \\ + PIP_AUTO_COMPLETE=1 $words[1] ) ) + } + compctl -K _pip_completion %(prog)s + """, + 'fish': """ + function __fish_complete_pip + set -lx COMP_WORDS (commandline -o) "" + set -lx COMP_CWORD ( \\ + math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ + ) + set -lx PIP_AUTO_COMPLETE 1 + string split \\ -- (eval $COMP_WORDS[1]) + end + complete -fa "(__fish_complete_pip)" -c %(prog)s + """, +} + + +class CompletionCommand(Command): + """A helper command to be used for command completion.""" + name = 'completion' + summary = 'A helper command used for command completion.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(CompletionCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option( + '--bash', '-b', + action='store_const', + const='bash', + dest='shell', + help='Emit completion code for bash') + cmd_opts.add_option( + '--zsh', '-z', + action='store_const', + const='zsh', + dest='shell', + help='Emit completion code for zsh') + cmd_opts.add_option( + '--fish', '-f', + action='store_const', + const='fish', + dest='shell', + help='Emit completion code for fish') + + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + """Prints the completion code of the given shell""" + shells = COMPLETION_SCRIPTS.keys() + shell_options = ['--' + shell for shell in sorted(shells)] + if options.shell in shells: + script = textwrap.dedent( + COMPLETION_SCRIPTS.get(options.shell, '') % { + 'prog': get_prog(), + } + ) + print(BASE_COMPLETION % {'script': script, 'shell': options.shell}) + else: + sys.stderr.write( + 'ERROR: You must pass %s\n' % ' or '.join(shell_options) + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/configuration.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/configuration.py new file mode 100644 index 0000000..826c08d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/configuration.py @@ -0,0 +1,227 @@ +import logging +import os +import subprocess + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.configuration import Configuration, kinds +from pip._internal.exceptions import PipError +from pip._internal.locations import venv_config_file +from pip._internal.utils.misc import get_prog + +logger = logging.getLogger(__name__) + + +class ConfigurationCommand(Command): + """Manage local and global configuration. + + Subcommands: + + list: List the active configuration (or from the file specified) + edit: Edit the configuration file in an editor + get: Get the value associated with name + set: Set the name=value + unset: Unset the value associated with name + + If none of --user, --global and --venv are passed, a virtual + environment configuration file is used if one is active and the file + exists. Otherwise, all modifications happen on the to the user file by + default. + """ + + name = 'config' + usage = """ + %prog [] list + %prog [] [--editor ] edit + + %prog [] get name + %prog [] set name value + %prog [] unset name + """ + + summary = "Manage local and global configuration." + + def __init__(self, *args, **kwargs): + super(ConfigurationCommand, self).__init__(*args, **kwargs) + + self.configuration = None + + self.cmd_opts.add_option( + '--editor', + dest='editor', + action='store', + default=None, + help=( + 'Editor to use to edit the file. Uses VISUAL or EDITOR ' + 'environment variables if not provided.' + ) + ) + + self.cmd_opts.add_option( + '--global', + dest='global_file', + action='store_true', + default=False, + help='Use the system-wide configuration file only' + ) + + self.cmd_opts.add_option( + '--user', + dest='user_file', + action='store_true', + default=False, + help='Use the user configuration file only' + ) + + self.cmd_opts.add_option( + '--venv', + dest='venv_file', + action='store_true', + default=False, + help='Use the virtualenv configuration file only' + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + handlers = { + "list": self.list_values, + "edit": self.open_in_editor, + "get": self.get_name, + "set": self.set_name_value, + "unset": self.unset_name + } + + # Determine action + if not args or args[0] not in handlers: + logger.error("Need an action ({}) to perform.".format( + ", ".join(sorted(handlers))) + ) + return ERROR + + action = args[0] + + # Determine which configuration files are to be loaded + # Depends on whether the command is modifying. + try: + load_only = self._determine_file( + options, need_value=(action in ["get", "set", "unset", "edit"]) + ) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + # Load a new configuration + self.configuration = Configuration( + isolated=options.isolated_mode, load_only=load_only + ) + self.configuration.load() + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _determine_file(self, options, need_value): + file_options = { + kinds.USER: options.user_file, + kinds.GLOBAL: options.global_file, + kinds.VENV: options.venv_file + } + + if sum(file_options.values()) == 0: + if not need_value: + return None + # Default to user, unless there's a virtualenv file. + elif os.path.exists(venv_config_file): + return kinds.VENV + else: + return kinds.USER + elif sum(file_options.values()) == 1: + # There's probably a better expression for this. + return [key for key in file_options if file_options[key]][0] + + raise PipError( + "Need exactly one file to operate upon " + "(--user, --venv, --global) to perform." + ) + + def list_values(self, options, args): + self._get_n_args(args, "list", n=0) + + for key, value in sorted(self.configuration.items()): + logger.info("%s=%r", key, value) + + def get_name(self, options, args): + key = self._get_n_args(args, "get [name]", n=1) + value = self.configuration.get_value(key) + + logger.info("%s", value) + + def set_name_value(self, options, args): + key, value = self._get_n_args(args, "set [name] [value]", n=2) + self.configuration.set_value(key, value) + + self._save_configuration() + + def unset_name(self, options, args): + key = self._get_n_args(args, "unset [name]", n=1) + self.configuration.unset_value(key) + + self._save_configuration() + + def open_in_editor(self, options, args): + editor = self._determine_editor(options) + + fname = self.configuration.get_file_to_edit() + if fname is None: + raise PipError("Could not determine appropriate file.") + + try: + subprocess.check_call([editor, fname]) + except subprocess.CalledProcessError as e: + raise PipError( + "Editor Subprocess exited with exit code {}" + .format(e.returncode) + ) + + def _get_n_args(self, args, example, n): + """Helper to make sure the command got the right number of arguments + """ + if len(args) != n: + msg = ( + 'Got unexpected number of arguments, expected {}. ' + '(example: "{} config {}")' + ).format(n, get_prog(), example) + raise PipError(msg) + + if n == 1: + return args[0] + else: + return args + + def _save_configuration(self): + # We successfully ran a modifying command. Need to save the + # configuration. + try: + self.configuration.save() + except Exception: + logger.error( + "Unable to save configuration. Please report this as a bug.", + exc_info=1 + ) + raise PipError("Internal Error.") + + def _determine_editor(self, options): + if options.editor is not None: + return options.editor + elif "VISUAL" in os.environ: + return os.environ["VISUAL"] + elif "EDITOR" in os.environ: + return os.environ["EDITOR"] + else: + raise PipError("Could not determine editor to use.") diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/download.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/download.py new file mode 100644 index 0000000..b3f3c6e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/download.py @@ -0,0 +1,174 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import RequirementCommand +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req import RequirementSet +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolve import Resolver +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.misc import ensure_dir, normalize_path +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +class DownloadCommand(RequirementCommand): + """ + Download packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports downloading from "requirements files", which provide + an easy way to specify a whole environment to be downloaded. + """ + name = 'download' + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] ... + %prog [options] ... + %prog [options] ...""" + + summary = 'Download packages.' + + def __init__(self, *args, **kw): + super(DownloadCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option(cmdoptions.constraints()) + cmd_opts.add_option(cmdoptions.requirements()) + cmd_opts.add_option(cmdoptions.build_dir()) + cmd_opts.add_option(cmdoptions.no_deps()) + cmd_opts.add_option(cmdoptions.global_options()) + cmd_opts.add_option(cmdoptions.no_binary()) + cmd_opts.add_option(cmdoptions.only_binary()) + cmd_opts.add_option(cmdoptions.prefer_binary()) + cmd_opts.add_option(cmdoptions.src()) + cmd_opts.add_option(cmdoptions.pre()) + cmd_opts.add_option(cmdoptions.no_clean()) + cmd_opts.add_option(cmdoptions.require_hashes()) + cmd_opts.add_option(cmdoptions.progress_bar()) + cmd_opts.add_option(cmdoptions.no_build_isolation()) + + cmd_opts.add_option( + '-d', '--dest', '--destination-dir', '--destination-directory', + dest='download_dir', + metavar='dir', + default=os.curdir, + help=("Download packages into ."), + ) + + cmd_opts.add_option(cmdoptions.platform()) + cmd_opts.add_option(cmdoptions.python_version()) + cmd_opts.add_option(cmdoptions.implementation()) + cmd_opts.add_option(cmdoptions.abi()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + options.ignore_installed = True + # editable doesn't really make sense for `pip download`, but the bowels + # of the RequirementSet code require that property. + options.editables = [] + + if options.python_version: + python_versions = [options.python_version] + else: + python_versions = None + + cmdoptions.check_dist_restriction(options) + + options.src_dir = os.path.abspath(options.src_dir) + options.download_dir = normalize_path(options.download_dir) + + ensure_dir(options.download_dir) + + with self._build_session(options) as session: + finder = self._build_package_finder( + options=options, + session=session, + platform=options.platform, + python_versions=python_versions, + abi=options.abi, + implementation=options.implementation, + ) + build_delete = (not (options.no_clean or options.build_dir)) + if options.cache_dir and not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "by the current user and caching wheels has been " + "disabled. check the permissions and owner of that " + "directory. If executing pip with sudo, you may want " + "sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + with RequirementTracker() as req_tracker, TempDirectory( + options.build_dir, delete=build_delete, kind="download" + ) as directory: + + requirement_set = RequirementSet( + require_hashes=options.require_hashes, + ) + self.populate_requirement_set( + requirement_set, + args, + options, + finder, + session, + self.name, + None + ) + + preparer = RequirementPreparer( + build_dir=directory.path, + src_dir=options.src_dir, + download_dir=options.download_dir, + wheel_download_dir=None, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + resolver = Resolver( + preparer=preparer, + finder=finder, + session=session, + wheel_cache=None, + use_user_site=False, + upgrade_strategy="to-satisfy-only", + force_reinstall=False, + ignore_dependencies=options.ignore_dependencies, + ignore_requires_python=False, + ignore_installed=True, + isolated=options.isolated_mode, + ) + resolver.resolve(requirement_set) + + downloaded = ' '.join([ + req.name for req in requirement_set.successfully_downloaded + ]) + if downloaded: + logger.info('Successfully downloaded %s', downloaded) + + # Clean up + if not options.no_clean: + requirement_set.cleanup_files() + + return requirement_set diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/freeze.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/freeze.py new file mode 100644 index 0000000..dc9c53a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/freeze.py @@ -0,0 +1,96 @@ +from __future__ import absolute_import + +import sys + +from pip._internal.cache import WheelCache +from pip._internal.cli.base_command import Command +from pip._internal.models.format_control import FormatControl +from pip._internal.operations.freeze import freeze +from pip._internal.utils.compat import stdlib_pkgs + +DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel'} + + +class FreezeCommand(Command): + """ + Output installed packages in requirements format. + + packages are listed in a case-insensitive sorted order. + """ + name = 'freeze' + usage = """ + %prog [options]""" + summary = 'Output installed packages in requirements format.' + log_streams = ("ext://sys.stderr", "ext://sys.stderr") + + def __init__(self, *args, **kw): + super(FreezeCommand, self).__init__(*args, **kw) + + self.cmd_opts.add_option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help="Use the order in the given requirements file and its " + "comments when generating output. This option can be " + "used multiple times.") + self.cmd_opts.add_option( + '-f', '--find-links', + dest='find_links', + action='append', + default=[], + metavar='URL', + help='URL for finding packages, which will be added to the ' + 'output.') + self.cmd_opts.add_option( + '-l', '--local', + dest='local', + action='store_true', + default=False, + help='If in a virtualenv that has global access, do not output ' + 'globally-installed packages.') + self.cmd_opts.add_option( + '--user', + dest='user', + action='store_true', + default=False, + help='Only output packages installed in user-site.') + self.cmd_opts.add_option( + '--all', + dest='freeze_all', + action='store_true', + help='Do not skip these packages in the output:' + ' %s' % ', '.join(DEV_PKGS)) + self.cmd_opts.add_option( + '--exclude-editable', + dest='exclude_editable', + action='store_true', + help='Exclude editable package from output.') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + format_control = FormatControl(set(), set()) + wheel_cache = WheelCache(options.cache_dir, format_control) + skip = set(stdlib_pkgs) + if not options.freeze_all: + skip.update(DEV_PKGS) + + freeze_kwargs = dict( + requirement=options.requirements, + find_links=options.find_links, + local_only=options.local, + user_only=options.user, + skip_regex=options.skip_requirements_regex, + isolated=options.isolated_mode, + wheel_cache=wheel_cache, + skip=skip, + exclude_editable=options.exclude_editable, + ) + + try: + for line in freeze(**freeze_kwargs): + sys.stdout.write(line + '\n') + finally: + wheel_cache.cleanup() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/hash.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/hash.py new file mode 100644 index 0000000..423440e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/hash.py @@ -0,0 +1,57 @@ +from __future__ import absolute_import + +import hashlib +import logging +import sys + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR +from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES +from pip._internal.utils.misc import read_chunks + +logger = logging.getLogger(__name__) + + +class HashCommand(Command): + """ + Compute a hash of a local package archive. + + These can be used with --hash in a requirements file to do repeatable + installs. + + """ + name = 'hash' + usage = '%prog [options] ...' + summary = 'Compute hashes of package archives.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(HashCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-a', '--algorithm', + dest='algorithm', + choices=STRONG_HASHES, + action='store', + default=FAVORITE_HASH, + help='The hash algorithm to use: one of %s' % + ', '.join(STRONG_HASHES)) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + if not args: + self.parser.print_usage(sys.stderr) + return ERROR + + algorithm = options.algorithm + for path in args: + logger.info('%s:\n--hash=%s:%s', + path, algorithm, _hash_of_file(path, algorithm)) + + +def _hash_of_file(path, algorithm): + """Return the hash digest of a file.""" + with open(path, 'rb') as archive: + hash = hashlib.new(algorithm) + for chunk in read_chunks(archive): + hash.update(chunk) + return hash.hexdigest() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/help.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/help.py new file mode 100644 index 0000000..49a81cb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/help.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError + + +class HelpCommand(Command): + """Show help for commands""" + name = 'help' + usage = """ + %prog """ + summary = 'Show help for commands.' + ignore_require_venv = True + + def run(self, options, args): + from pip._internal.commands import commands_dict, get_similar_commands + + try: + # 'pip help' with no args is handled by pip.__init__.parseopt() + cmd_name = args[0] # the command we need help for + except IndexError: + return SUCCESS + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = ['unknown command "%s"' % cmd_name] + if guess: + msg.append('maybe you meant "%s"' % guess) + + raise CommandError(' - '.join(msg)) + + command = commands_dict[cmd_name]() + command.parser.print_help() + + return SUCCESS diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/install.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/install.py new file mode 100644 index 0000000..6fc178f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/install.py @@ -0,0 +1,535 @@ +from __future__ import absolute_import + +import errno +import logging +import operator +import os +import shutil +from optparse import SUPPRESS_HELP + +from pip._vendor import pkg_resources + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import RequirementCommand +from pip._internal.cli.status_codes import ERROR +from pip._internal.exceptions import ( + CommandError, InstallationError, PreviousBuildDirError, +) +from pip._internal.locations import distutils_scheme, virtualenv_no_global +from pip._internal.operations.check import check_install_conflicts +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req import RequirementSet, install_given_reqs +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolve import Resolver +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.misc import ( + ensure_dir, get_installed_version, + protect_pip_from_modification_on_windows, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel import WheelBuilder + +try: + import wheel +except ImportError: + wheel = None + + +logger = logging.getLogger(__name__) + + +class InstallCommand(RequirementCommand): + """ + Install packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports installing from "requirements files", which provide + an easy way to specify a whole environment to be installed. + """ + name = 'install' + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + summary = 'Install packages.' + + def __init__(self, *args, **kw): + super(InstallCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option(cmdoptions.requirements()) + cmd_opts.add_option(cmdoptions.constraints()) + cmd_opts.add_option(cmdoptions.no_deps()) + cmd_opts.add_option(cmdoptions.pre()) + + cmd_opts.add_option(cmdoptions.editable()) + cmd_opts.add_option( + '-t', '--target', + dest='target_dir', + metavar='dir', + default=None, + help='Install packages into . ' + 'By default this will not replace existing files/folders in ' + '. Use --upgrade to replace existing packages in ' + 'with new versions.' + ) + cmd_opts.add_option(cmdoptions.platform()) + cmd_opts.add_option(cmdoptions.python_version()) + cmd_opts.add_option(cmdoptions.implementation()) + cmd_opts.add_option(cmdoptions.abi()) + + cmd_opts.add_option( + '--user', + dest='use_user_site', + action='store_true', + help="Install to the Python user install directory for your " + "platform. Typically ~/.local/, or %APPDATA%\\Python on " + "Windows. (See the Python documentation for site.USER_BASE " + "for full details.)") + cmd_opts.add_option( + '--no-user', + dest='use_user_site', + action='store_false', + help=SUPPRESS_HELP) + cmd_opts.add_option( + '--root', + dest='root_path', + metavar='dir', + default=None, + help="Install everything relative to this alternate root " + "directory.") + cmd_opts.add_option( + '--prefix', + dest='prefix_path', + metavar='dir', + default=None, + help="Installation prefix where lib, bin and other top-level " + "folders are placed") + + cmd_opts.add_option(cmdoptions.build_dir()) + + cmd_opts.add_option(cmdoptions.src()) + + cmd_opts.add_option( + '-U', '--upgrade', + dest='upgrade', + action='store_true', + help='Upgrade all specified packages to the newest available ' + 'version. The handling of dependencies depends on the ' + 'upgrade-strategy used.' + ) + + cmd_opts.add_option( + '--upgrade-strategy', + dest='upgrade_strategy', + default='only-if-needed', + choices=['only-if-needed', 'eager'], + help='Determines how dependency upgrading should be handled ' + '[default: %default]. ' + '"eager" - dependencies are upgraded regardless of ' + 'whether the currently installed version satisfies the ' + 'requirements of the upgraded package(s). ' + '"only-if-needed" - are upgraded only when they do not ' + 'satisfy the requirements of the upgraded package(s).' + ) + + cmd_opts.add_option( + '--force-reinstall', + dest='force_reinstall', + action='store_true', + help='Reinstall all packages even if they are already ' + 'up-to-date.') + + cmd_opts.add_option( + '-I', '--ignore-installed', + dest='ignore_installed', + action='store_true', + help='Ignore the installed packages (reinstalling instead).') + + cmd_opts.add_option(cmdoptions.ignore_requires_python()) + cmd_opts.add_option(cmdoptions.no_build_isolation()) + + cmd_opts.add_option(cmdoptions.install_options()) + cmd_opts.add_option(cmdoptions.global_options()) + + cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile Python source files to bytecode", + ) + + cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile Python source files to bytecode", + ) + + cmd_opts.add_option( + "--no-warn-script-location", + action="store_false", + dest="warn_script_location", + default=True, + help="Do not warn when installing scripts outside PATH", + ) + cmd_opts.add_option( + "--no-warn-conflicts", + action="store_false", + dest="warn_about_conflicts", + default=True, + help="Do not warn about broken dependencies", + ) + + cmd_opts.add_option(cmdoptions.no_binary()) + cmd_opts.add_option(cmdoptions.only_binary()) + cmd_opts.add_option(cmdoptions.prefer_binary()) + cmd_opts.add_option(cmdoptions.no_clean()) + cmd_opts.add_option(cmdoptions.require_hashes()) + cmd_opts.add_option(cmdoptions.progress_bar()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + cmdoptions.check_install_build_global(options) + upgrade_strategy = "to-satisfy-only" + if options.upgrade: + upgrade_strategy = options.upgrade_strategy + + if options.build_dir: + options.build_dir = os.path.abspath(options.build_dir) + + cmdoptions.check_dist_restriction(options, check_target=True) + + if options.python_version: + python_versions = [options.python_version] + else: + python_versions = None + + options.src_dir = os.path.abspath(options.src_dir) + install_options = options.install_options or [] + if options.use_user_site: + if options.prefix_path: + raise CommandError( + "Can not combine '--user' and '--prefix' as they imply " + "different installation locations" + ) + if virtualenv_no_global(): + raise InstallationError( + "Can not perform a '--user' install. User site-packages " + "are not visible in this virtualenv." + ) + install_options.append('--user') + install_options.append('--prefix=') + + target_temp_dir = TempDirectory(kind="target") + if options.target_dir: + options.ignore_installed = True + options.target_dir = os.path.abspath(options.target_dir) + if (os.path.exists(options.target_dir) and not + os.path.isdir(options.target_dir)): + raise CommandError( + "Target path exists but is not a directory, will not " + "continue." + ) + + # Create a target directory for using with the target option + target_temp_dir.create() + install_options.append('--home=' + target_temp_dir.path) + + global_options = options.global_options or [] + + with self._build_session(options) as session: + finder = self._build_package_finder( + options=options, + session=session, + platform=options.platform, + python_versions=python_versions, + abi=options.abi, + implementation=options.implementation, + ) + build_delete = (not (options.no_clean or options.build_dir)) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + if options.cache_dir and not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "by the current user and caching wheels has been " + "disabled. check the permissions and owner of that " + "directory. If executing pip with sudo, you may want " + "sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + with RequirementTracker() as req_tracker, TempDirectory( + options.build_dir, delete=build_delete, kind="install" + ) as directory: + requirement_set = RequirementSet( + require_hashes=options.require_hashes, + check_supported_wheels=not options.target_dir, + ) + + try: + self.populate_requirement_set( + requirement_set, args, options, finder, session, + self.name, wheel_cache + ) + preparer = RequirementPreparer( + build_dir=directory.path, + src_dir=options.src_dir, + download_dir=None, + wheel_download_dir=None, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + resolver = Resolver( + preparer=preparer, + finder=finder, + session=session, + wheel_cache=wheel_cache, + use_user_site=options.use_user_site, + upgrade_strategy=upgrade_strategy, + force_reinstall=options.force_reinstall, + ignore_dependencies=options.ignore_dependencies, + ignore_requires_python=options.ignore_requires_python, + ignore_installed=options.ignore_installed, + isolated=options.isolated_mode, + ) + resolver.resolve(requirement_set) + + protect_pip_from_modification_on_windows( + modifying_pip=requirement_set.has_requirement("pip") + ) + + # If caching is disabled or wheel is not installed don't + # try to build wheels. + if wheel and options.cache_dir: + # build wheels before install. + wb = WheelBuilder( + finder, preparer, wheel_cache, + build_options=[], global_options=[], + ) + # Ignore the result: a failed wheel will be + # installed from the sdist/vcs whatever. + wb.build( + requirement_set.requirements.values(), + session=session, autobuilding=True + ) + + to_install = resolver.get_installation_order( + requirement_set + ) + + # Consistency Checking of the package set we're installing. + should_warn_about_conflicts = ( + not options.ignore_dependencies and + options.warn_about_conflicts + ) + if should_warn_about_conflicts: + self._warn_about_conflicts(to_install) + + # Don't warn about script install locations if + # --target has been specified + warn_script_location = options.warn_script_location + if options.target_dir: + warn_script_location = False + + installed = install_given_reqs( + to_install, + install_options, + global_options, + root=options.root_path, + home=target_temp_dir.path, + prefix=options.prefix_path, + pycompile=options.compile, + warn_script_location=warn_script_location, + use_user_site=options.use_user_site, + ) + + lib_locations = get_lib_location_guesses( + user=options.use_user_site, + home=target_temp_dir.path, + root=options.root_path, + prefix=options.prefix_path, + isolated=options.isolated_mode, + ) + working_set = pkg_resources.WorkingSet(lib_locations) + + reqs = sorted(installed, key=operator.attrgetter('name')) + items = [] + for req in reqs: + item = req.name + try: + installed_version = get_installed_version( + req.name, working_set=working_set + ) + if installed_version: + item += '-' + installed_version + except Exception: + pass + items.append(item) + installed = ' '.join(items) + if installed: + logger.info('Successfully installed %s', installed) + except EnvironmentError as error: + show_traceback = (self.verbosity >= 1) + + message = create_env_error_message( + error, show_traceback, options.use_user_site, + ) + logger.error(message, exc_info=show_traceback) + + return ERROR + except PreviousBuildDirError: + options.no_clean = True + raise + finally: + # Clean up + if not options.no_clean: + requirement_set.cleanup_files() + wheel_cache.cleanup() + + if options.target_dir: + self._handle_target_dir( + options.target_dir, target_temp_dir, options.upgrade + ) + return requirement_set + + def _handle_target_dir(self, target_dir, target_temp_dir, upgrade): + ensure_dir(target_dir) + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + lib_dir_list = [] + + with target_temp_dir: + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + scheme = distutils_scheme('', home=target_temp_dir.path) + purelib_dir = scheme['purelib'] + platlib_dir = scheme['platlib'] + data_dir = scheme['data'] + + if os.path.exists(purelib_dir): + lib_dir_list.append(purelib_dir) + if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: + lib_dir_list.append(platlib_dir) + if os.path.exists(data_dir): + lib_dir_list.append(data_dir) + + for lib_dir in lib_dir_list: + for item in os.listdir(lib_dir): + if lib_dir == data_dir: + ddir = os.path.join(data_dir, item) + if any(s.startswith(ddir) for s in lib_dir_list[:-1]): + continue + target_item_dir = os.path.join(target_dir, item) + if os.path.exists(target_item_dir): + if not upgrade: + logger.warning( + 'Target directory %s already exists. Specify ' + '--upgrade to force replacement.', + target_item_dir + ) + continue + if os.path.islink(target_item_dir): + logger.warning( + 'Target directory %s already exists and is ' + 'a link. Pip will not automatically replace ' + 'links, please remove if replacement is ' + 'desired.', + target_item_dir + ) + continue + if os.path.isdir(target_item_dir): + shutil.rmtree(target_item_dir) + else: + os.remove(target_item_dir) + + shutil.move( + os.path.join(lib_dir, item), + target_item_dir + ) + + def _warn_about_conflicts(self, to_install): + package_set, _dep_info = check_install_conflicts(to_install) + missing, conflicting = _dep_info + + # NOTE: There is some duplication here from pip check + for project_name in missing: + version = package_set[project_name][0] + for dependency in missing[project_name]: + logger.critical( + "%s %s requires %s, which is not installed.", + project_name, version, dependency[1], + ) + + for project_name in conflicting: + version = package_set[project_name][0] + for dep_name, dep_version, req in conflicting[project_name]: + logger.critical( + "%s %s has requirement %s, but you'll have %s %s which is " + "incompatible.", + project_name, version, req, dep_name, dep_version, + ) + + +def get_lib_location_guesses(*args, **kwargs): + scheme = distutils_scheme('', *args, **kwargs) + return [scheme['purelib'], scheme['platlib']] + + +def create_env_error_message(error, show_traceback, using_user_site): + """Format an error message for an EnvironmentError + + It may occur anytime during the execution of the install command. + """ + parts = [] + + # Mention the error if we are not going to show a traceback + parts.append("Could not install packages due to an EnvironmentError") + if not show_traceback: + parts.append(": ") + parts.append(str(error)) + else: + parts.append(".") + + # Spilt the error indication from a helper message (if any) + parts[-1] += "\n" + + # Suggest useful actions to the user: + # (1) using user site-packages or (2) verifying the permissions + if error.errno == errno.EACCES: + user_option_part = "Consider using the `--user` option" + permissions_part = "Check the permissions" + + if not using_user_site: + parts.extend([ + user_option_part, " or ", + permissions_part.lower(), + ]) + else: + parts.append(permissions_part) + parts.append(".\n") + + return "".join(parts).strip() + "\n" diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/list.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/list.py new file mode 100644 index 0000000..c6eeca7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/list.py @@ -0,0 +1,306 @@ +from __future__ import absolute_import + +import json +import logging + +from pip._vendor import six +from pip._vendor.six.moves import zip_longest + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.exceptions import CommandError +from pip._internal.index import PackageFinder +from pip._internal.utils.misc import ( + dist_is_editable, get_installed_distributions, +) +from pip._internal.utils.packaging import get_installer + +logger = logging.getLogger(__name__) + + +class ListCommand(Command): + """ + List installed packages, including editables. + + Packages are listed in a case-insensitive sorted order. + """ + name = 'list' + usage = """ + %prog [options]""" + summary = 'List installed packages.' + + def __init__(self, *args, **kw): + super(ListCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option( + '-o', '--outdated', + action='store_true', + default=False, + help='List outdated packages') + cmd_opts.add_option( + '-u', '--uptodate', + action='store_true', + default=False, + help='List uptodate packages') + cmd_opts.add_option( + '-e', '--editable', + action='store_true', + default=False, + help='List editable projects.') + cmd_opts.add_option( + '-l', '--local', + action='store_true', + default=False, + help=('If in a virtualenv that has global access, do not list ' + 'globally-installed packages.'), + ) + self.cmd_opts.add_option( + '--user', + dest='user', + action='store_true', + default=False, + help='Only output packages installed in user-site.') + + cmd_opts.add_option( + '--pre', + action='store_true', + default=False, + help=("Include pre-release and development versions. By default, " + "pip only finds stable versions."), + ) + + cmd_opts.add_option( + '--format', + action='store', + dest='list_format', + default="columns", + choices=('columns', 'freeze', 'json'), + help="Select the output format among: columns (default), freeze, " + "or json", + ) + + cmd_opts.add_option( + '--not-required', + action='store_true', + dest='not_required', + help="List packages that are not dependencies of " + "installed packages.", + ) + + cmd_opts.add_option( + '--exclude-editable', + action='store_false', + dest='include_editable', + help='Exclude editable package from output.', + ) + cmd_opts.add_option( + '--include-editable', + action='store_true', + dest='include_editable', + help='Include editable package from output.', + default=True, + ) + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, self.parser + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def _build_package_finder(self, options, index_urls, session): + """ + Create a package finder appropriate to this list command. + """ + return PackageFinder( + find_links=options.find_links, + index_urls=index_urls, + allow_all_prereleases=options.pre, + trusted_hosts=options.trusted_hosts, + process_dependency_links=options.process_dependency_links, + session=session, + ) + + def run(self, options, args): + if options.outdated and options.uptodate: + raise CommandError( + "Options --outdated and --uptodate cannot be combined.") + + packages = get_installed_distributions( + local_only=options.local, + user_only=options.user, + editables_only=options.editable, + include_editables=options.include_editable, + ) + + if options.outdated: + packages = self.get_outdated(packages, options) + elif options.uptodate: + packages = self.get_uptodate(packages, options) + + if options.not_required: + packages = self.get_not_required(packages, options) + + self.output_package_listing(packages, options) + + def get_outdated(self, packages, options): + return [ + dist for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version > dist.parsed_version + ] + + def get_uptodate(self, packages, options): + return [ + dist for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version == dist.parsed_version + ] + + def get_not_required(self, packages, options): + dep_keys = set() + for dist in packages: + dep_keys.update(requirement.key for requirement in dist.requires()) + return {pkg for pkg in packages if pkg.key not in dep_keys} + + def iter_packages_latest_infos(self, packages, options): + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index: + logger.debug('Ignoring indexes: %s', ','.join(index_urls)) + index_urls = [] + + dependency_links = [] + for dist in packages: + if dist.has_metadata('dependency_links.txt'): + dependency_links.extend( + dist.get_metadata_lines('dependency_links.txt'), + ) + + with self._build_session(options) as session: + finder = self._build_package_finder(options, index_urls, session) + finder.add_dependency_links(dependency_links) + + for dist in packages: + typ = 'unknown' + all_candidates = finder.find_all_candidates(dist.key) + if not options.pre: + # Remove prereleases + all_candidates = [candidate for candidate in all_candidates + if not candidate.version.is_prerelease] + + if not all_candidates: + continue + best_candidate = max(all_candidates, + key=finder._candidate_sort_key) + remote_version = best_candidate.version + if best_candidate.location.is_wheel: + typ = 'wheel' + else: + typ = 'sdist' + # This is dirty but makes the rest of the code much cleaner + dist.latest_version = remote_version + dist.latest_filetype = typ + yield dist + + def output_package_listing(self, packages, options): + packages = sorted( + packages, + key=lambda dist: dist.project_name.lower(), + ) + if options.list_format == 'columns' and packages: + data, header = format_for_columns(packages, options) + self.output_package_listing_columns(data, header) + elif options.list_format == 'freeze': + for dist in packages: + if options.verbose >= 1: + logger.info("%s==%s (%s)", dist.project_name, + dist.version, dist.location) + else: + logger.info("%s==%s", dist.project_name, dist.version) + elif options.list_format == 'json': + logger.info(format_for_json(packages, options)) + + def output_package_listing_columns(self, data, header): + # insert the header first: we need to know the size of column names + if len(data) > 0: + data.insert(0, header) + + pkg_strings, sizes = tabulate(data) + + # Create and add a separator. + if len(data) > 0: + pkg_strings.insert(1, " ".join(map(lambda x: '-' * x, sizes))) + + for val in pkg_strings: + logger.info(val) + + +def tabulate(vals): + # From pfmoore on GitHub: + # https://github.com/pypa/pip/issues/3651#issuecomment-216932564 + assert len(vals) > 0 + + sizes = [0] * max(len(x) for x in vals) + for row in vals: + sizes = [max(s, len(str(c))) for s, c in zip_longest(sizes, row)] + + result = [] + for row in vals: + display = " ".join([str(c).ljust(s) if c is not None else '' + for s, c in zip_longest(sizes, row)]) + result.append(display) + + return result, sizes + + +def format_for_columns(pkgs, options): + """ + Convert the package data into something usable + by output_package_listing_columns. + """ + running_outdated = options.outdated + # Adjust the header for the `pip list --outdated` case. + if running_outdated: + header = ["Package", "Version", "Latest", "Type"] + else: + header = ["Package", "Version"] + + data = [] + if options.verbose >= 1 or any(dist_is_editable(x) for x in pkgs): + header.append("Location") + if options.verbose >= 1: + header.append("Installer") + + for proj in pkgs: + # if we're working on the 'outdated' list, separate out the + # latest_version and type + row = [proj.project_name, proj.version] + + if running_outdated: + row.append(proj.latest_version) + row.append(proj.latest_filetype) + + if options.verbose >= 1 or dist_is_editable(proj): + row.append(proj.location) + if options.verbose >= 1: + row.append(get_installer(proj)) + + data.append(row) + + return data, header + + +def format_for_json(packages, options): + data = [] + for dist in packages: + info = { + 'name': dist.project_name, + 'version': six.text_type(dist.version), + } + if options.verbose >= 1: + info['location'] = dist.location + info['installer'] = get_installer(dist) + if options.outdated: + info['latest_version'] = six.text_type(dist.latest_version) + info['latest_filetype'] = dist.latest_filetype + data.append(info) + return json.dumps(data) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/search.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/search.py new file mode 100644 index 0000000..c157a31 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/search.py @@ -0,0 +1,135 @@ +from __future__ import absolute_import + +import logging +import sys +import textwrap +from collections import OrderedDict + +from pip._vendor import pkg_resources +from pip._vendor.packaging.version import parse as parse_version +# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import +from pip._vendor.six.moves import xmlrpc_client # type: ignore + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.download import PipXmlrpcTransport +from pip._internal.exceptions import CommandError +from pip._internal.models.index import PyPI +from pip._internal.utils.compat import get_terminal_size +from pip._internal.utils.logging import indent_log + +logger = logging.getLogger(__name__) + + +class SearchCommand(Command): + """Search for PyPI packages whose name or summary contains .""" + name = 'search' + usage = """ + %prog [options] """ + summary = 'Search PyPI for packages.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(SearchCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-i', '--index', + dest='index', + metavar='URL', + default=PyPI.pypi_url, + help='Base URL of Python Package Index (default %default)') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + if not args: + raise CommandError('Missing required argument (search query).') + query = args + pypi_hits = self.search(query, options) + hits = transform_hits(pypi_hits) + + terminal_width = None + if sys.stdout.isatty(): + terminal_width = get_terminal_size()[0] + + print_results(hits, terminal_width=terminal_width) + if pypi_hits: + return SUCCESS + return NO_MATCHES_FOUND + + def search(self, query, options): + index_url = options.index + with self._build_session(options) as session: + transport = PipXmlrpcTransport(index_url, session) + pypi = xmlrpc_client.ServerProxy(index_url, transport) + hits = pypi.search({'name': query, 'summary': query}, 'or') + return hits + + +def transform_hits(hits): + """ + The list from pypi is really a list of versions. We want a list of + packages with the list of versions stored inline. This converts the + list from pypi into one we can use. + """ + packages = OrderedDict() + for hit in hits: + name = hit['name'] + summary = hit['summary'] + version = hit['version'] + + if name not in packages.keys(): + packages[name] = { + 'name': name, + 'summary': summary, + 'versions': [version], + } + else: + packages[name]['versions'].append(version) + + # if this is the highest version, replace summary and score + if version == highest_version(packages[name]['versions']): + packages[name]['summary'] = summary + + return list(packages.values()) + + +def print_results(hits, name_column_width=None, terminal_width=None): + if not hits: + return + if name_column_width is None: + name_column_width = max([ + len(hit['name']) + len(highest_version(hit.get('versions', ['-']))) + for hit in hits + ]) + 4 + + installed_packages = [p.project_name for p in pkg_resources.working_set] + for hit in hits: + name = hit['name'] + summary = hit['summary'] or '' + latest = highest_version(hit.get('versions', ['-'])) + if terminal_width is not None: + target_width = terminal_width - name_column_width - 5 + if target_width > 10: + # wrap and indent summary to fit terminal + summary = textwrap.wrap(summary, target_width) + summary = ('\n' + ' ' * (name_column_width + 3)).join(summary) + + line = '%-*s - %s' % (name_column_width, + '%s (%s)' % (name, latest), summary) + try: + logger.info(line) + if name in installed_packages: + dist = pkg_resources.get_distribution(name) + with indent_log(): + if dist.version == latest: + logger.info('INSTALLED: %s (latest)', dist.version) + else: + logger.info('INSTALLED: %s', dist.version) + logger.info('LATEST: %s', latest) + except UnicodeEncodeError: + pass + + +def highest_version(versions): + return max(versions, key=parse_version) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/show.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/show.py new file mode 100644 index 0000000..f92c9bc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/show.py @@ -0,0 +1,168 @@ +from __future__ import absolute_import + +import logging +import os +from email.parser import FeedParser # type: ignore + +from pip._vendor import pkg_resources +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS + +logger = logging.getLogger(__name__) + + +class ShowCommand(Command): + """ + Show information about one or more installed packages. + + The output is in RFC-compliant mail header format. + """ + name = 'show' + usage = """ + %prog [options] ...""" + summary = 'Show information about installed packages.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(ShowCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-f', '--files', + dest='files', + action='store_true', + default=False, + help='Show the full list of installed files for each package.') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + if not args: + logger.warning('ERROR: Please provide a package name or names.') + return ERROR + query = args + + results = search_packages_info(query) + if not print_results( + results, list_files=options.files, verbose=options.verbose): + return ERROR + return SUCCESS + + +def search_packages_info(query): + """ + Gather details from installed distributions. Print distribution name, + version, location, and installed files. Installed files requires a + pip generated 'installed-files.txt' in the distributions '.egg-info' + directory. + """ + installed = {} + for p in pkg_resources.working_set: + installed[canonicalize_name(p.project_name)] = p + + query_names = [canonicalize_name(name) for name in query] + + for dist in [installed[pkg] for pkg in query_names if pkg in installed]: + package = { + 'name': dist.project_name, + 'version': dist.version, + 'location': dist.location, + 'requires': [dep.project_name for dep in dist.requires()], + } + file_list = None + metadata = None + if isinstance(dist, pkg_resources.DistInfoDistribution): + # RECORDs should be part of .dist-info metadatas + if dist.has_metadata('RECORD'): + lines = dist.get_metadata_lines('RECORD') + paths = [l.split(',')[0] for l in lines] + paths = [os.path.join(dist.location, p) for p in paths] + file_list = [os.path.relpath(p, dist.location) for p in paths] + + if dist.has_metadata('METADATA'): + metadata = dist.get_metadata('METADATA') + else: + # Otherwise use pip's log for .egg-info's + if dist.has_metadata('installed-files.txt'): + paths = dist.get_metadata_lines('installed-files.txt') + paths = [os.path.join(dist.egg_info, p) for p in paths] + file_list = [os.path.relpath(p, dist.location) for p in paths] + + if dist.has_metadata('PKG-INFO'): + metadata = dist.get_metadata('PKG-INFO') + + if dist.has_metadata('entry_points.txt'): + entry_points = dist.get_metadata_lines('entry_points.txt') + package['entry_points'] = entry_points + + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + package['installer'] = line.strip() + break + + # @todo: Should pkg_resources.Distribution have a + # `get_pkg_info` method? + feed_parser = FeedParser() + feed_parser.feed(metadata) + pkg_info_dict = feed_parser.close() + for key in ('metadata-version', 'summary', + 'home-page', 'author', 'author-email', 'license'): + package[key] = pkg_info_dict.get(key) + + # It looks like FeedParser cannot deal with repeated headers + classifiers = [] + for line in metadata.splitlines(): + if line.startswith('Classifier: '): + classifiers.append(line[len('Classifier: '):]) + package['classifiers'] = classifiers + + if file_list: + package['files'] = sorted(file_list) + yield package + + +def print_results(distributions, list_files=False, verbose=False): + """ + Print the informations from installed distributions found. + """ + results_printed = False + for i, dist in enumerate(distributions): + results_printed = True + if i > 0: + logger.info("---") + + name = dist.get('name', '') + required_by = [ + pkg.project_name for pkg in pkg_resources.working_set + if name in [required.name for required in pkg.requires()] + ] + + logger.info("Name: %s", name) + logger.info("Version: %s", dist.get('version', '')) + logger.info("Summary: %s", dist.get('summary', '')) + logger.info("Home-page: %s", dist.get('home-page', '')) + logger.info("Author: %s", dist.get('author', '')) + logger.info("Author-email: %s", dist.get('author-email', '')) + logger.info("License: %s", dist.get('license', '')) + logger.info("Location: %s", dist.get('location', '')) + logger.info("Requires: %s", ', '.join(dist.get('requires', []))) + logger.info("Required-by: %s", ', '.join(required_by)) + + if verbose: + logger.info("Metadata-Version: %s", + dist.get('metadata-version', '')) + logger.info("Installer: %s", dist.get('installer', '')) + logger.info("Classifiers:") + for classifier in dist.get('classifiers', []): + logger.info(" %s", classifier) + logger.info("Entry-points:") + for entry in dist.get('entry_points', []): + logger.info(" %s", entry.strip()) + if list_files: + logger.info("Files:") + for line in dist.get('files', []): + logger.info(" %s", line.strip()) + if "files" not in dist: + logger.info("Cannot locate installed-files.txt") + return results_printed diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/uninstall.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/uninstall.py new file mode 100644 index 0000000..0cd6f54 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/uninstall.py @@ -0,0 +1,78 @@ +from __future__ import absolute_import + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.exceptions import InstallationError +from pip._internal.req import parse_requirements +from pip._internal.req.constructors import install_req_from_line +from pip._internal.utils.misc import protect_pip_from_modification_on_windows + + +class UninstallCommand(Command): + """ + Uninstall packages. + + pip is able to uninstall most installed packages. Known exceptions are: + + - Pure distutils packages installed with ``python setup.py install``, which + leave behind no metadata to determine what files were installed. + - Script wrappers installed by ``python setup.py develop``. + """ + name = 'uninstall' + usage = """ + %prog [options] ... + %prog [options] -r ...""" + summary = 'Uninstall packages.' + + def __init__(self, *args, **kw): + super(UninstallCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help='Uninstall all the packages listed in the given requirements ' + 'file. This option can be used multiple times.', + ) + self.cmd_opts.add_option( + '-y', '--yes', + dest='yes', + action='store_true', + help="Don't ask for confirmation of uninstall deletions.") + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + with self._build_session(options) as session: + reqs_to_uninstall = {} + for name in args: + req = install_req_from_line( + name, isolated=options.isolated_mode, + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + for filename in options.requirements: + for req in parse_requirements( + filename, + options=options, + session=session): + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + if not reqs_to_uninstall: + raise InstallationError( + 'You must give at least one requirement to %(name)s (see ' + '"pip help %(name)s")' % dict(name=self.name) + ) + + protect_pip_from_modification_on_windows( + modifying_pip="pip" in reqs_to_uninstall + ) + + for req in reqs_to_uninstall.values(): + uninstall_pathset = req.uninstall( + auto_confirm=options.yes, verbose=self.verbosity > 0, + ) + if uninstall_pathset: + uninstall_pathset.commit() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/commands/wheel.py b/venv/lib/python3.7/site-packages/pip/_internal/commands/wheel.py new file mode 100644 index 0000000..9c1f149 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/commands/wheel.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +import logging +import os + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import RequirementCommand +from pip._internal.exceptions import CommandError, PreviousBuildDirError +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req import RequirementSet +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolve import Resolver +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel import WheelBuilder + +logger = logging.getLogger(__name__) + + +class WheelCommand(RequirementCommand): + """ + Build Wheel archives for your requirements and dependencies. + + Wheel is a built-package format, and offers the advantage of not + recompiling your software during every install. For more details, see the + wheel docs: https://wheel.readthedocs.io/en/latest/ + + Requirements: setuptools>=0.8, and wheel. + + 'pip wheel' uses the bdist_wheel setuptools extension from the wheel + package to build individual wheels. + + """ + + name = 'wheel' + usage = """ + %prog [options] ... + %prog [options] -r ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + summary = 'Build wheels from your requirements.' + + def __init__(self, *args, **kw): + super(WheelCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option( + '-w', '--wheel-dir', + dest='wheel_dir', + metavar='dir', + default=os.curdir, + help=("Build wheels into , where the default is the " + "current working directory."), + ) + cmd_opts.add_option(cmdoptions.no_binary()) + cmd_opts.add_option(cmdoptions.only_binary()) + cmd_opts.add_option(cmdoptions.prefer_binary()) + cmd_opts.add_option( + '--build-option', + dest='build_options', + metavar='options', + action='append', + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", + ) + cmd_opts.add_option(cmdoptions.no_build_isolation()) + cmd_opts.add_option(cmdoptions.constraints()) + cmd_opts.add_option(cmdoptions.editable()) + cmd_opts.add_option(cmdoptions.requirements()) + cmd_opts.add_option(cmdoptions.src()) + cmd_opts.add_option(cmdoptions.ignore_requires_python()) + cmd_opts.add_option(cmdoptions.no_deps()) + cmd_opts.add_option(cmdoptions.build_dir()) + cmd_opts.add_option(cmdoptions.progress_bar()) + + cmd_opts.add_option( + '--global-option', + dest='global_options', + action='append', + metavar='options', + help="Extra global options to be supplied to the setup.py " + "call before the 'bdist_wheel' command.") + + cmd_opts.add_option( + '--pre', + action='store_true', + default=False, + help=("Include pre-release and development versions. By default, " + "pip only finds stable versions."), + ) + + cmd_opts.add_option(cmdoptions.no_clean()) + cmd_opts.add_option(cmdoptions.require_hashes()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + cmdoptions.check_install_build_global(options) + + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index: + logger.debug('Ignoring indexes: %s', ','.join(index_urls)) + index_urls = [] + + if options.build_dir: + options.build_dir = os.path.abspath(options.build_dir) + + options.src_dir = os.path.abspath(options.src_dir) + + with self._build_session(options) as session: + finder = self._build_package_finder(options, session) + build_delete = (not (options.no_clean or options.build_dir)) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + with RequirementTracker() as req_tracker, TempDirectory( + options.build_dir, delete=build_delete, kind="wheel" + ) as directory: + + requirement_set = RequirementSet( + require_hashes=options.require_hashes, + ) + + try: + self.populate_requirement_set( + requirement_set, args, options, finder, session, + self.name, wheel_cache + ) + + preparer = RequirementPreparer( + build_dir=directory.path, + src_dir=options.src_dir, + download_dir=None, + wheel_download_dir=options.wheel_dir, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + resolver = Resolver( + preparer=preparer, + finder=finder, + session=session, + wheel_cache=wheel_cache, + use_user_site=False, + upgrade_strategy="to-satisfy-only", + force_reinstall=False, + ignore_dependencies=options.ignore_dependencies, + ignore_requires_python=options.ignore_requires_python, + ignore_installed=True, + isolated=options.isolated_mode, + ) + resolver.resolve(requirement_set) + + # build wheels + wb = WheelBuilder( + finder, preparer, wheel_cache, + build_options=options.build_options or [], + global_options=options.global_options or [], + no_clean=options.no_clean, + ) + wheels_built_successfully = wb.build( + requirement_set.requirements.values(), session=session, + ) + if not wheels_built_successfully: + raise CommandError( + "Failed to build one or more wheels" + ) + except PreviousBuildDirError: + options.no_clean = True + raise + finally: + if not options.no_clean: + requirement_set.cleanup_files() + wheel_cache.cleanup() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/configuration.py b/venv/lib/python3.7/site-packages/pip/_internal/configuration.py new file mode 100644 index 0000000..fe6df9b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/configuration.py @@ -0,0 +1,387 @@ +"""Configuration management setup + +Some terminology: +- name + As written in config files. +- value + Value associated with a name +- key + Name combined with it's section (section.name) +- variant + A single word describing where the configuration key-value pair came from +""" + +import locale +import logging +import os + +from pip._vendor import six +from pip._vendor.six.moves import configparser + +from pip._internal.exceptions import ( + ConfigurationError, ConfigurationFileCouldNotBeLoaded, +) +from pip._internal.locations import ( + legacy_config_file, new_config_file, running_under_virtualenv, + site_config_files, venv_config_file, +) +from pip._internal.utils.misc import ensure_dir, enum +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import ( # noqa: F401 + Any, Dict, Iterable, List, NewType, Optional, Tuple + ) + + RawConfigParser = configparser.RawConfigParser # Shorthand + Kind = NewType("Kind", str) + +logger = logging.getLogger(__name__) + + +# NOTE: Maybe use the optionx attribute to normalize keynames. +def _normalize_name(name): + # type: (str) -> str + """Make a name consistent regardless of source (environment or file) + """ + name = name.lower().replace('_', '-') + if name.startswith('--'): + name = name[2:] # only prefer long opts + return name + + +def _disassemble_key(name): + # type: (str) -> List[str] + return name.split(".", 1) + + +# The kinds of configurations there are. +kinds = enum( + USER="user", # User Specific + GLOBAL="global", # System Wide + VENV="venv", # Virtual Environment Specific + ENV="env", # from PIP_CONFIG_FILE + ENV_VAR="env-var", # from Environment Variables +) + + +class Configuration(object): + """Handles management of configuration. + + Provides an interface to accessing and managing configuration files. + + This class converts provides an API that takes "section.key-name" style + keys and stores the value associated with it as "key-name" under the + section "section". + + This allows for a clean interface wherein the both the section and the + key-name are preserved in an easy to manage form in the configuration files + and the data stored is also nice. + """ + + def __init__(self, isolated, load_only=None): + # type: (bool, Kind) -> None + super(Configuration, self).__init__() + + _valid_load_only = [kinds.USER, kinds.GLOBAL, kinds.VENV, None] + if load_only not in _valid_load_only: + raise ConfigurationError( + "Got invalid value for load_only - should be one of {}".format( + ", ".join(map(repr, _valid_load_only[:-1])) + ) + ) + self.isolated = isolated # type: bool + self.load_only = load_only # type: Optional[Kind] + + # The order here determines the override order. + self._override_order = [ + kinds.GLOBAL, kinds.USER, kinds.VENV, kinds.ENV, kinds.ENV_VAR + ] + + self._ignore_env_names = ["version", "help"] + + # Because we keep track of where we got the data from + self._parsers = { + variant: [] for variant in self._override_order + } # type: Dict[Kind, List[Tuple[str, RawConfigParser]]] + self._config = { + variant: {} for variant in self._override_order + } # type: Dict[Kind, Dict[str, Any]] + self._modified_parsers = [] # type: List[Tuple[str, RawConfigParser]] + + def load(self): + # type: () -> None + """Loads configuration from configuration files and environment + """ + self._load_config_files() + if not self.isolated: + self._load_environment_vars() + + def get_file_to_edit(self): + # type: () -> Optional[str] + """Returns the file with highest priority in configuration + """ + assert self.load_only is not None, \ + "Need to be specified a file to be editing" + + try: + return self._get_parser_to_modify()[0] + except IndexError: + return None + + def items(self): + # type: () -> Iterable[Tuple[str, Any]] + """Returns key-value pairs like dict.items() representing the loaded + configuration + """ + return self._dictionary.items() + + def get_value(self, key): + # type: (str) -> Any + """Get a value from the configuration. + """ + try: + return self._dictionary[key] + except KeyError: + raise ConfigurationError("No such key - {}".format(key)) + + def set_value(self, key, value): + # type: (str, Any) -> None + """Modify a value in the configuration. + """ + self._ensure_have_load_only() + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Modify the parser and the configuration + if not parser.has_section(section): + parser.add_section(section) + parser.set(section, name, value) + + self._config[self.load_only][key] = value + self._mark_as_modified(fname, parser) + + def unset_value(self, key): + # type: (str) -> None + """Unset a value in the configuration. + """ + self._ensure_have_load_only() + + if key not in self._config[self.load_only]: + raise ConfigurationError("No such key - {}".format(key)) + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Remove the key in the parser + modified_something = False + if parser.has_section(section): + # Returns whether the option was removed or not + modified_something = parser.remove_option(section, name) + + if modified_something: + # name removed from parser, section may now be empty + section_iter = iter(parser.items(section)) + try: + val = six.next(section_iter) + except StopIteration: + val = None + + if val is None: + parser.remove_section(section) + + self._mark_as_modified(fname, parser) + else: + raise ConfigurationError( + "Fatal Internal error [id=1]. Please report as a bug." + ) + + del self._config[self.load_only][key] + + def save(self): + # type: () -> None + """Save the currentin-memory state. + """ + self._ensure_have_load_only() + + for fname, parser in self._modified_parsers: + logger.info("Writing to %s", fname) + + # Ensure directory exists. + ensure_dir(os.path.dirname(fname)) + + with open(fname, "w") as f: + parser.write(f) # type: ignore + + # + # Private routines + # + + def _ensure_have_load_only(self): + # type: () -> None + if self.load_only is None: + raise ConfigurationError("Needed a specific file to be modifying.") + logger.debug("Will be working with %s variant only", self.load_only) + + @property + def _dictionary(self): + # type: () -> Dict[str, Any] + """A dictionary representing the loaded configuration. + """ + # NOTE: Dictionaries are not populated if not loaded. So, conditionals + # are not needed here. + retval = {} + + for variant in self._override_order: + retval.update(self._config[variant]) + + return retval + + def _load_config_files(self): + # type: () -> None + """Loads configuration from configuration files + """ + config_files = dict(self._iter_config_files()) + if config_files[kinds.ENV][0:1] == [os.devnull]: + logger.debug( + "Skipping loading configuration files due to " + "environment's PIP_CONFIG_FILE being os.devnull" + ) + return + + for variant, files in config_files.items(): + for fname in files: + # If there's specific variant set in `load_only`, load only + # that variant, not the others. + if self.load_only is not None and variant != self.load_only: + logger.debug( + "Skipping file '%s' (variant: %s)", fname, variant + ) + continue + + parser = self._load_file(variant, fname) + + # Keeping track of the parsers used + self._parsers[variant].append((fname, parser)) + + def _load_file(self, variant, fname): + # type: (Kind, str) -> RawConfigParser + logger.debug("For variant '%s', will try loading '%s'", variant, fname) + parser = self._construct_parser(fname) + + for section in parser.sections(): + items = parser.items(section) + self._config[variant].update(self._normalized_keys(section, items)) + + return parser + + def _construct_parser(self, fname): + # type: (str) -> RawConfigParser + parser = configparser.RawConfigParser() + # If there is no such file, don't bother reading it but create the + # parser anyway, to hold the data. + # Doing this is useful when modifying and saving files, where we don't + # need to construct a parser. + if os.path.exists(fname): + try: + parser.read(fname) + except UnicodeDecodeError: + # See https://github.com/pypa/pip/issues/4963 + raise ConfigurationFileCouldNotBeLoaded( + reason="contains invalid {} characters".format( + locale.getpreferredencoding(False) + ), + fname=fname, + ) + except configparser.Error as error: + # See https://github.com/pypa/pip/issues/4893 + raise ConfigurationFileCouldNotBeLoaded(error=error) + return parser + + def _load_environment_vars(self): + # type: () -> None + """Loads configuration from environment variables + """ + self._config[kinds.ENV_VAR].update( + self._normalized_keys(":env:", self._get_environ_vars()) + ) + + def _normalized_keys(self, section, items): + # type: (str, Iterable[Tuple[str, Any]]) -> Dict[str, Any] + """Normalizes items to construct a dictionary with normalized keys. + + This routine is where the names become keys and are made the same + regardless of source - configuration files or environment. + """ + normalized = {} + for name, val in items: + key = section + "." + _normalize_name(name) + normalized[key] = val + return normalized + + def _get_environ_vars(self): + # type: () -> Iterable[Tuple[str, str]] + """Returns a generator with all environmental vars with prefix PIP_""" + for key, val in os.environ.items(): + should_be_yielded = ( + key.startswith("PIP_") and + key[4:].lower() not in self._ignore_env_names + ) + if should_be_yielded: + yield key[4:].lower(), val + + # XXX: This is patched in the tests. + def _iter_config_files(self): + # type: () -> Iterable[Tuple[Kind, List[str]]] + """Yields variant and configuration files associated with it. + + This should be treated like items of a dictionary. + """ + # SMELL: Move the conditions out of this function + + # environment variables have the lowest priority + config_file = os.environ.get('PIP_CONFIG_FILE', None) + if config_file is not None: + yield kinds.ENV, [config_file] + else: + yield kinds.ENV, [] + + # at the base we have any global configuration + yield kinds.GLOBAL, list(site_config_files) + + # per-user configuration next + should_load_user_config = not self.isolated and not ( + config_file and os.path.exists(config_file) + ) + if should_load_user_config: + # The legacy config file is overridden by the new config file + yield kinds.USER, [legacy_config_file, new_config_file] + + # finally virtualenv configuration first trumping others + if running_under_virtualenv(): + yield kinds.VENV, [venv_config_file] + + def _get_parser_to_modify(self): + # type: () -> Tuple[str, RawConfigParser] + # Determine which parser to modify + parsers = self._parsers[self.load_only] + if not parsers: + # This should not happen if everything works correctly. + raise ConfigurationError( + "Fatal Internal error [id=2]. Please report as a bug." + ) + + # Use the highest priority parser. + return parsers[-1] + + # XXX: This is patched in the tests. + def _mark_as_modified(self, fname, parser): + # type: (str, RawConfigParser) -> None + file_parser_tuple = (fname, parser) + if file_parser_tuple not in self._modified_parsers: + self._modified_parsers.append(file_parser_tuple) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/download.py b/venv/lib/python3.7/site-packages/pip/_internal/download.py new file mode 100644 index 0000000..96f3b65 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/download.py @@ -0,0 +1,921 @@ +from __future__ import absolute_import + +import cgi +import email.utils +import getpass +import json +import logging +import mimetypes +import os +import platform +import re +import shutil +import sys + +from pip._vendor import requests, six, urllib3 +from pip._vendor.cachecontrol import CacheControlAdapter +from pip._vendor.cachecontrol.caches import FileCache +from pip._vendor.lockfile import LockError +from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter +from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response +from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.requests.utils import get_netrc_auth +# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import +from pip._vendor.six.moves import xmlrpc_client # type: ignore +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request +from pip._vendor.six.moves.urllib.parse import unquote as urllib_unquote +from pip._vendor.urllib3.util import IS_PYOPENSSL + +import pip +from pip._internal.exceptions import HashMismatch, InstallationError +from pip._internal.locations import write_delete_marker_file +from pip._internal.models.index import PyPI +from pip._internal.utils.encoding import auto_decode +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.glibc import libc_ver +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, ask_path_exists, backup_dir, call_subprocess, consume, + display_path, format_size, get_installed_version, rmtree, splitext, + unpack_file, +) +from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.ui import DownloadProgressProvider +from pip._internal.vcs import vcs + +try: + import ssl # noqa +except ImportError: + ssl = None + +HAS_TLS = (ssl is not None) or IS_PYOPENSSL + +__all__ = ['get_file_content', + 'is_url', 'url_to_path', 'path_to_url', + 'is_archive_file', 'unpack_vcs_link', + 'unpack_file_url', 'is_vcs_url', 'is_file_url', + 'unpack_http_url', 'unpack_url'] + + +logger = logging.getLogger(__name__) + + +def user_agent(): + """ + Return a string representing the user agent. + """ + data = { + "installer": {"name": "pip", "version": pip.__version__}, + "python": platform.python_version(), + "implementation": { + "name": platform.python_implementation(), + }, + } + + if data["implementation"]["name"] == 'CPython': + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == 'PyPy': + if sys.pypy_version_info.releaselevel == 'final': + pypy_version_info = sys.pypy_version_info[:3] + else: + pypy_version_info = sys.pypy_version_info + data["implementation"]["version"] = ".".join( + [str(x) for x in pypy_version_info] + ) + elif data["implementation"]["name"] == 'Jython': + # Complete Guess + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == 'IronPython': + # Complete Guess + data["implementation"]["version"] = platform.python_version() + + if sys.platform.startswith("linux"): + from pip._vendor import distro + distro_infos = dict(filter( + lambda x: x[1], + zip(["name", "version", "id"], distro.linux_distribution()), + )) + libc = dict(filter( + lambda x: x[1], + zip(["lib", "version"], libc_ver()), + )) + if libc: + distro_infos["libc"] = libc + if distro_infos: + data["distro"] = distro_infos + + if sys.platform.startswith("darwin") and platform.mac_ver()[0]: + data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]} + + if platform.system(): + data.setdefault("system", {})["name"] = platform.system() + + if platform.release(): + data.setdefault("system", {})["release"] = platform.release() + + if platform.machine(): + data["cpu"] = platform.machine() + + if HAS_TLS: + data["openssl_version"] = ssl.OPENSSL_VERSION + + setuptools_version = get_installed_version("setuptools") + if setuptools_version is not None: + data["setuptools_version"] = setuptools_version + + return "{data[installer][name]}/{data[installer][version]} {json}".format( + data=data, + json=json.dumps(data, separators=(",", ":"), sort_keys=True), + ) + + +class MultiDomainBasicAuth(AuthBase): + + def __init__(self, prompting=True): + self.prompting = prompting + self.passwords = {} + + def __call__(self, req): + parsed = urllib_parse.urlparse(req.url) + + # Get the netloc without any embedded credentials + netloc = parsed.netloc.rsplit("@", 1)[-1] + + # Set the url of the request to the url without any credentials + req.url = urllib_parse.urlunparse(parsed[:1] + (netloc,) + parsed[2:]) + + # Use any stored credentials that we have for this netloc + username, password = self.passwords.get(netloc, (None, None)) + + # Extract credentials embedded in the url if we have none stored + if username is None: + username, password = self.parse_credentials(parsed.netloc) + + # Get creds from netrc if we still don't have them + if username is None and password is None: + netrc_auth = get_netrc_auth(req.url) + username, password = netrc_auth if netrc_auth else (None, None) + + if username or password: + # Store the username and password + self.passwords[netloc] = (username, password) + + # Send the basic auth with this request + req = HTTPBasicAuth(username or "", password or "")(req) + + # Attach a hook to handle 401 responses + req.register_hook("response", self.handle_401) + + return req + + def handle_401(self, resp, **kwargs): + # We only care about 401 responses, anything else we want to just + # pass through the actual response + if resp.status_code != 401: + return resp + + # We are not able to prompt the user so simply return the response + if not self.prompting: + return resp + + parsed = urllib_parse.urlparse(resp.url) + + # Prompt the user for a new username and password + username = six.moves.input("User for %s: " % parsed.netloc) + password = getpass.getpass("Password: ") + + # Store the new username and password to use for future requests + if username or password: + self.passwords[parsed.netloc] = (username, password) + + # Consume content and release the original connection to allow our new + # request to reuse the same one. + resp.content + resp.raw.release_conn() + + # Add our new username and password to the request + req = HTTPBasicAuth(username or "", password or "")(resp.request) + + # Send our new request + new_resp = resp.connection.send(req, **kwargs) + new_resp.history.append(resp) + + return new_resp + + def parse_credentials(self, netloc): + if "@" in netloc: + userinfo = netloc.rsplit("@", 1)[0] + if ":" in userinfo: + user, pwd = userinfo.split(":", 1) + return (urllib_unquote(user), urllib_unquote(pwd)) + return urllib_unquote(userinfo), None + return None, None + + +class LocalFSAdapter(BaseAdapter): + + def send(self, request, stream=None, timeout=None, verify=None, cert=None, + proxies=None): + pathname = url_to_path(request.url) + + resp = Response() + resp.status_code = 200 + resp.url = request.url + + try: + stats = os.stat(pathname) + except OSError as exc: + resp.status_code = 404 + resp.raw = exc + else: + modified = email.utils.formatdate(stats.st_mtime, usegmt=True) + content_type = mimetypes.guess_type(pathname)[0] or "text/plain" + resp.headers = CaseInsensitiveDict({ + "Content-Type": content_type, + "Content-Length": stats.st_size, + "Last-Modified": modified, + }) + + resp.raw = open(pathname, "rb") + resp.close = resp.raw.close + + return resp + + def close(self): + pass + + +class SafeFileCache(FileCache): + """ + A file based cache which is safe to use even when the target directory may + not be accessible or writable. + """ + + def __init__(self, *args, **kwargs): + super(SafeFileCache, self).__init__(*args, **kwargs) + + # Check to ensure that the directory containing our cache directory + # is owned by the user current executing pip. If it does not exist + # we will check the parent directory until we find one that does exist. + # If it is not owned by the user executing pip then we will disable + # the cache and log a warning. + if not check_path_owner(self.directory): + logger.warning( + "The directory '%s' or its parent directory is not owned by " + "the current user and the cache has been disabled. Please " + "check the permissions and owner of that directory. If " + "executing pip with sudo, you may want sudo's -H flag.", + self.directory, + ) + + # Set our directory to None to disable the Cache + self.directory = None + + def get(self, *args, **kwargs): + # If we don't have a directory, then the cache should be a no-op. + if self.directory is None: + return + + try: + return super(SafeFileCache, self).get(*args, **kwargs) + except (LockError, OSError, IOError): + # We intentionally silence this error, if we can't access the cache + # then we can just skip caching and process the request as if + # caching wasn't enabled. + pass + + def set(self, *args, **kwargs): + # If we don't have a directory, then the cache should be a no-op. + if self.directory is None: + return + + try: + return super(SafeFileCache, self).set(*args, **kwargs) + except (LockError, OSError, IOError): + # We intentionally silence this error, if we can't access the cache + # then we can just skip caching and process the request as if + # caching wasn't enabled. + pass + + def delete(self, *args, **kwargs): + # If we don't have a directory, then the cache should be a no-op. + if self.directory is None: + return + + try: + return super(SafeFileCache, self).delete(*args, **kwargs) + except (LockError, OSError, IOError): + # We intentionally silence this error, if we can't access the cache + # then we can just skip caching and process the request as if + # caching wasn't enabled. + pass + + +class InsecureHTTPAdapter(HTTPAdapter): + + def cert_verify(self, conn, url, verify, cert): + conn.cert_reqs = 'CERT_NONE' + conn.ca_certs = None + + +class PipSession(requests.Session): + + timeout = None + + def __init__(self, *args, **kwargs): + retries = kwargs.pop("retries", 0) + cache = kwargs.pop("cache", None) + insecure_hosts = kwargs.pop("insecure_hosts", []) + + super(PipSession, self).__init__(*args, **kwargs) + + # Attach our User Agent to the request + self.headers["User-Agent"] = user_agent() + + # Attach our Authentication handler to the session + self.auth = MultiDomainBasicAuth() + + # Create our urllib3.Retry instance which will allow us to customize + # how we handle retries. + retries = urllib3.Retry( + # Set the total number of retries that a particular request can + # have. + total=retries, + + # A 503 error from PyPI typically means that the Fastly -> Origin + # connection got interrupted in some way. A 503 error in general + # is typically considered a transient error so we'll go ahead and + # retry it. + # A 500 may indicate transient error in Amazon S3 + # A 520 or 527 - may indicate transient error in CloudFlare + status_forcelist=[500, 503, 520, 527], + + # Add a small amount of back off between failed requests in + # order to prevent hammering the service. + backoff_factor=0.25, + ) + + # We want to _only_ cache responses on securely fetched origins. We do + # this because we can't validate the response of an insecurely fetched + # origin, and we don't want someone to be able to poison the cache and + # require manual eviction from the cache to fix it. + if cache: + secure_adapter = CacheControlAdapter( + cache=SafeFileCache(cache, use_dir_lock=True), + max_retries=retries, + ) + else: + secure_adapter = HTTPAdapter(max_retries=retries) + + # Our Insecure HTTPAdapter disables HTTPS validation. It does not + # support caching (see above) so we'll use it for all http:// URLs as + # well as any https:// host that we've marked as ignoring TLS errors + # for. + insecure_adapter = InsecureHTTPAdapter(max_retries=retries) + + self.mount("https://", secure_adapter) + self.mount("http://", insecure_adapter) + + # Enable file:// urls + self.mount("file://", LocalFSAdapter()) + + # We want to use a non-validating adapter for any requests which are + # deemed insecure. + for host in insecure_hosts: + self.mount("https://{}/".format(host), insecure_adapter) + + def request(self, method, url, *args, **kwargs): + # Allow setting a default timeout on a session + kwargs.setdefault("timeout", self.timeout) + + # Dispatch the actual request + return super(PipSession, self).request(method, url, *args, **kwargs) + + +def get_file_content(url, comes_from=None, session=None): + """Gets the content of a file; it may be a filename, file: URL, or + http: URL. Returns (location, content). Content is unicode. + + :param url: File path or url. + :param comes_from: Origin description of requirements. + :param session: Instance of pip.download.PipSession. + """ + if session is None: + raise TypeError( + "get_file_content() missing 1 required keyword argument: 'session'" + ) + + match = _scheme_re.search(url) + if match: + scheme = match.group(1).lower() + if (scheme == 'file' and comes_from and + comes_from.startswith('http')): + raise InstallationError( + 'Requirements file %s references URL %s, which is local' + % (comes_from, url)) + if scheme == 'file': + path = url.split(':', 1)[1] + path = path.replace('\\', '/') + match = _url_slash_drive_re.match(path) + if match: + path = match.group(1) + ':' + path.split('|', 1)[1] + path = urllib_parse.unquote(path) + if path.startswith('/'): + path = '/' + path.lstrip('/') + url = path + else: + # FIXME: catch some errors + resp = session.get(url) + resp.raise_for_status() + return resp.url, resp.text + try: + with open(url, 'rb') as f: + content = auto_decode(f.read()) + except IOError as exc: + raise InstallationError( + 'Could not open requirements file: %s' % str(exc) + ) + return url, content + + +_scheme_re = re.compile(r'^(http|https|file):', re.I) +_url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I) + + +def is_url(name): + """Returns true if the name looks like a URL""" + if ':' not in name: + return False + scheme = name.split(':', 1)[0].lower() + return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes + + +def url_to_path(url): + """ + Convert a file: URL to a path. + """ + assert url.startswith('file:'), ( + "You can only turn file: urls into filenames (not %r)" % url) + + _, netloc, path, _, _ = urllib_parse.urlsplit(url) + + # if we have a UNC path, prepend UNC share notation + if netloc: + netloc = '\\\\' + netloc + + path = urllib_request.url2pathname(netloc + path) + return path + + +def path_to_url(path): + """ + Convert a path to a file: URL. The path will be made absolute and have + quoted path parts. + """ + path = os.path.normpath(os.path.abspath(path)) + url = urllib_parse.urljoin('file:', urllib_request.pathname2url(path)) + return url + + +def is_archive_file(name): + """Return True if `name` is a considered as an archive file.""" + ext = splitext(name)[1].lower() + if ext in ARCHIVE_EXTENSIONS: + return True + return False + + +def unpack_vcs_link(link, location): + vcs_backend = _get_used_vcs_backend(link) + vcs_backend.unpack(location) + + +def _get_used_vcs_backend(link): + for backend in vcs.backends: + if link.scheme in backend.schemes: + vcs_backend = backend(link.url) + return vcs_backend + + +def is_vcs_url(link): + return bool(_get_used_vcs_backend(link)) + + +def is_file_url(link): + return link.url.lower().startswith('file:') + + +def is_dir_url(link): + """Return whether a file:// Link points to a directory. + + ``link`` must not have any other scheme but file://. Call is_file_url() + first. + + """ + link_path = url_to_path(link.url_without_fragment) + return os.path.isdir(link_path) + + +def _progress_indicator(iterable, *args, **kwargs): + return iterable + + +def _download_url(resp, link, content_file, hashes, progress_bar): + try: + total_length = int(resp.headers['content-length']) + except (ValueError, KeyError, TypeError): + total_length = 0 + + cached_resp = getattr(resp, "from_cache", False) + if logger.getEffectiveLevel() > logging.INFO: + show_progress = False + elif cached_resp: + show_progress = False + elif total_length > (40 * 1000): + show_progress = True + elif not total_length: + show_progress = True + else: + show_progress = False + + show_url = link.show_url + + def resp_read(chunk_size): + try: + # Special case for urllib3. + for chunk in resp.raw.stream( + chunk_size, + # We use decode_content=False here because we don't + # want urllib3 to mess with the raw bytes we get + # from the server. If we decompress inside of + # urllib3 then we cannot verify the checksum + # because the checksum will be of the compressed + # file. This breakage will only occur if the + # server adds a Content-Encoding header, which + # depends on how the server was configured: + # - Some servers will notice that the file isn't a + # compressible file and will leave the file alone + # and with an empty Content-Encoding + # - Some servers will notice that the file is + # already compressed and will leave the file + # alone and will add a Content-Encoding: gzip + # header + # - Some servers won't notice anything at all and + # will take a file that's already been compressed + # and compress it again and set the + # Content-Encoding: gzip header + # + # By setting this not to decode automatically we + # hope to eliminate problems with the second case. + decode_content=False): + yield chunk + except AttributeError: + # Standard file-like object. + while True: + chunk = resp.raw.read(chunk_size) + if not chunk: + break + yield chunk + + def written_chunks(chunks): + for chunk in chunks: + content_file.write(chunk) + yield chunk + + progress_indicator = _progress_indicator + + if link.netloc == PyPI.netloc: + url = show_url + else: + url = link.url_without_fragment + + if show_progress: # We don't show progress on cached responses + progress_indicator = DownloadProgressProvider(progress_bar, + max=total_length) + if total_length: + logger.info("Downloading %s (%s)", url, format_size(total_length)) + else: + logger.info("Downloading %s", url) + elif cached_resp: + logger.info("Using cached %s", url) + else: + logger.info("Downloading %s", url) + + logger.debug('Downloading from URL %s', link) + + downloaded_chunks = written_chunks( + progress_indicator( + resp_read(CONTENT_CHUNK_SIZE), + CONTENT_CHUNK_SIZE + ) + ) + if hashes: + hashes.check_against_chunks(downloaded_chunks) + else: + consume(downloaded_chunks) + + +def _copy_file(filename, location, link): + copy = True + download_location = os.path.join(location, link.filename) + if os.path.exists(download_location): + response = ask_path_exists( + 'The file %s exists. (i)gnore, (w)ipe, (b)ackup, (a)abort' % + display_path(download_location), ('i', 'w', 'b', 'a')) + if response == 'i': + copy = False + elif response == 'w': + logger.warning('Deleting %s', display_path(download_location)) + os.remove(download_location) + elif response == 'b': + dest_file = backup_dir(download_location) + logger.warning( + 'Backing up %s to %s', + display_path(download_location), + display_path(dest_file), + ) + shutil.move(download_location, dest_file) + elif response == 'a': + sys.exit(-1) + if copy: + shutil.copy(filename, download_location) + logger.info('Saved %s', display_path(download_location)) + + +def unpack_http_url(link, location, download_dir=None, + session=None, hashes=None, progress_bar="on"): + if session is None: + raise TypeError( + "unpack_http_url() missing 1 required keyword argument: 'session'" + ) + + with TempDirectory(kind="unpack") as temp_dir: + # If a download dir is specified, is the file already downloaded there? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, + download_dir, + hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + content_type = mimetypes.guess_type(from_path)[0] + else: + # let's download to a tmp dir + from_path, content_type = _download_http_url(link, + session, + temp_dir.path, + hashes, + progress_bar) + + # unpack the archive to the build dir location. even when only + # downloading archives, they have to be unpacked to parse dependencies + unpack_file(from_path, location, content_type, link) + + # a download dir is specified; let's copy the archive there + if download_dir and not already_downloaded_path: + _copy_file(from_path, download_dir, link) + + if not already_downloaded_path: + os.unlink(from_path) + + +def unpack_file_url(link, location, download_dir=None, hashes=None): + """Unpack link into location. + + If download_dir is provided and link points to a file, make a copy + of the link file inside download_dir. + """ + link_path = url_to_path(link.url_without_fragment) + + # If it's a url to a local directory + if is_dir_url(link): + if os.path.isdir(location): + rmtree(location) + shutil.copytree(link_path, location, symlinks=True) + if download_dir: + logger.info('Link is a directory, ignoring download_dir') + return + + # If --require-hashes is off, `hashes` is either empty, the + # link's embedded hash, or MissingHashes; it is required to + # match. If --require-hashes is on, we are satisfied by any + # hash in `hashes` matching: a URL-based or an option-based + # one; no internet-sourced hash will be in `hashes`. + if hashes: + hashes.check_against_path(link_path) + + # If a download dir is specified, is the file already there and valid? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, + download_dir, + hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + else: + from_path = link_path + + content_type = mimetypes.guess_type(from_path)[0] + + # unpack the archive to the build dir location. even when only downloading + # archives, they have to be unpacked to parse dependencies + unpack_file(from_path, location, content_type, link) + + # a download dir is specified and not already downloaded + if download_dir and not already_downloaded_path: + _copy_file(from_path, download_dir, link) + + +def _copy_dist_from_dir(link_path, location): + """Copy distribution files in `link_path` to `location`. + + Invoked when user requests to install a local directory. E.g.: + + pip install . + pip install ~/dev/git-repos/python-prompt-toolkit + + """ + + # Note: This is currently VERY SLOW if you have a lot of data in the + # directory, because it copies everything with `shutil.copytree`. + # What it should really do is build an sdist and install that. + # See https://github.com/pypa/pip/issues/2195 + + if os.path.isdir(location): + rmtree(location) + + # build an sdist + setup_py = 'setup.py' + sdist_args = [sys.executable] + sdist_args.append('-c') + sdist_args.append(SETUPTOOLS_SHIM % setup_py) + sdist_args.append('sdist') + sdist_args += ['--dist-dir', location] + logger.info('Running setup.py sdist for %s', link_path) + + with indent_log(): + call_subprocess(sdist_args, cwd=link_path, show_stdout=False) + + # unpack sdist into `location` + sdist = os.path.join(location, os.listdir(location)[0]) + logger.info('Unpacking sdist %s into %s', sdist, location) + unpack_file(sdist, location, content_type=None, link=None) + + +class PipXmlrpcTransport(xmlrpc_client.Transport): + """Provide a `xmlrpclib.Transport` implementation via a `PipSession` + object. + """ + + def __init__(self, index_url, session, use_datetime=False): + xmlrpc_client.Transport.__init__(self, use_datetime) + index_parts = urllib_parse.urlparse(index_url) + self._scheme = index_parts.scheme + self._session = session + + def request(self, host, handler, request_body, verbose=False): + parts = (self._scheme, host, handler, None, None, None) + url = urllib_parse.urlunparse(parts) + try: + headers = {'Content-Type': 'text/xml'} + response = self._session.post(url, data=request_body, + headers=headers, stream=True) + response.raise_for_status() + self.verbose = verbose + return self.parse_response(response.raw) + except requests.HTTPError as exc: + logger.critical( + "HTTP error %s while getting %s", + exc.response.status_code, url, + ) + raise + + +def unpack_url(link, location, download_dir=None, + only_download=False, session=None, hashes=None, + progress_bar="on"): + """Unpack link. + If link is a VCS link: + if only_download, export into download_dir and ignore location + else unpack into location + for other types of link: + - unpack into location + - if download_dir, copy the file into download_dir + - if only_download, mark location for deletion + + :param hashes: A Hashes object, one of whose embedded hashes must match, + or HashMismatch will be raised. If the Hashes is empty, no matches are + required, and unhashable types of requirements (like VCS ones, which + would ordinarily raise HashUnsupported) are allowed. + """ + # non-editable vcs urls + if is_vcs_url(link): + unpack_vcs_link(link, location) + + # file urls + elif is_file_url(link): + unpack_file_url(link, location, download_dir, hashes=hashes) + + # http urls + else: + if session is None: + session = PipSession() + + unpack_http_url( + link, + location, + download_dir, + session, + hashes=hashes, + progress_bar=progress_bar + ) + if only_download: + write_delete_marker_file(location) + + +def _download_http_url(link, session, temp_dir, hashes, progress_bar): + """Download link url into temp_dir using provided session""" + target_url = link.url.split('#', 1)[0] + try: + resp = session.get( + target_url, + # We use Accept-Encoding: identity here because requests + # defaults to accepting compressed responses. This breaks in + # a variety of ways depending on how the server is configured. + # - Some servers will notice that the file isn't a compressible + # file and will leave the file alone and with an empty + # Content-Encoding + # - Some servers will notice that the file is already + # compressed and will leave the file alone and will add a + # Content-Encoding: gzip header + # - Some servers won't notice anything at all and will take + # a file that's already been compressed and compress it again + # and set the Content-Encoding: gzip header + # By setting this to request only the identity encoding We're + # hoping to eliminate the third case. Hopefully there does not + # exist a server which when given a file will notice it is + # already compressed and that you're not asking for a + # compressed file and will then decompress it before sending + # because if that's the case I don't think it'll ever be + # possible to make this work. + headers={"Accept-Encoding": "identity"}, + stream=True, + ) + resp.raise_for_status() + except requests.HTTPError as exc: + logger.critical( + "HTTP error %s while getting %s", exc.response.status_code, link, + ) + raise + + content_type = resp.headers.get('content-type', '') + filename = link.filename # fallback + # Have a look at the Content-Disposition header for a better guess + content_disposition = resp.headers.get('content-disposition') + if content_disposition: + type, params = cgi.parse_header(content_disposition) + # We use ``or`` here because we don't want to use an "empty" value + # from the filename param. + filename = params.get('filename') or filename + ext = splitext(filename)[1] + if not ext: + ext = mimetypes.guess_extension(content_type) + if ext: + filename += ext + if not ext and link.url != resp.url: + ext = os.path.splitext(resp.url)[1] + if ext: + filename += ext + file_path = os.path.join(temp_dir, filename) + with open(file_path, 'wb') as content_file: + _download_url(resp, link, content_file, hashes, progress_bar) + return file_path, content_type + + +def _check_download_dir(link, download_dir, hashes): + """ Check download_dir for previously downloaded file with correct hash + If a correct file is found return its path else None + """ + download_path = os.path.join(download_dir, link.filename) + if os.path.exists(download_path): + # If already downloaded, does its hash match? + logger.info('File was already downloaded %s', download_path) + if hashes: + try: + hashes.check_against_path(download_path) + except HashMismatch: + logger.warning( + 'Previously-downloaded file %s has bad hash. ' + 'Re-downloading.', + download_path + ) + os.unlink(download_path) + return None + return download_path + return None diff --git a/venv/lib/python3.7/site-packages/pip/_internal/exceptions.py b/venv/lib/python3.7/site-packages/pip/_internal/exceptions.py new file mode 100644 index 0000000..f1ca6f3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/exceptions.py @@ -0,0 +1,268 @@ +"""Exceptions used throughout package""" +from __future__ import absolute_import + +from itertools import chain, groupby, repeat + +from pip._vendor.six import iteritems + + +class PipError(Exception): + """Base pip exception""" + + +class ConfigurationError(PipError): + """General exception in configuration""" + + +class InstallationError(PipError): + """General exception during installation""" + + +class UninstallationError(PipError): + """General exception during uninstallation""" + + +class DistributionNotFound(InstallationError): + """Raised when a distribution cannot be found to satisfy a requirement""" + + +class RequirementsFileParseError(InstallationError): + """Raised when a general error occurs parsing a requirements file line.""" + + +class BestVersionAlreadyInstalled(PipError): + """Raised when the most up-to-date version of a package is already + installed.""" + + +class BadCommand(PipError): + """Raised when virtualenv or a command is not found""" + + +class CommandError(PipError): + """Raised when there is an error in command-line arguments""" + + +class PreviousBuildDirError(PipError): + """Raised when there's a previous conflicting build directory""" + + +class InvalidWheelFilename(InstallationError): + """Invalid wheel filename.""" + + +class UnsupportedWheel(InstallationError): + """Unsupported wheel.""" + + +class HashErrors(InstallationError): + """Multiple HashError instances rolled into one for reporting""" + + def __init__(self): + self.errors = [] + + def append(self, error): + self.errors.append(error) + + def __str__(self): + lines = [] + self.errors.sort(key=lambda e: e.order) + for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__): + lines.append(cls.head) + lines.extend(e.body() for e in errors_of_cls) + if lines: + return '\n'.join(lines) + + def __nonzero__(self): + return bool(self.errors) + + def __bool__(self): + return self.__nonzero__() + + +class HashError(InstallationError): + """ + A failure to verify a package against known-good hashes + + :cvar order: An int sorting hash exception classes by difficulty of + recovery (lower being harder), so the user doesn't bother fretting + about unpinned packages when he has deeper issues, like VCS + dependencies, to deal with. Also keeps error reports in a + deterministic order. + :cvar head: A section heading for display above potentially many + exceptions of this kind + :ivar req: The InstallRequirement that triggered this error. This is + pasted on after the exception is instantiated, because it's not + typically available earlier. + + """ + req = None + head = '' + + def body(self): + """Return a summary of me for display under the heading. + + This default implementation simply prints a description of the + triggering requirement. + + :param req: The InstallRequirement that provoked this error, with + populate_link() having already been called + + """ + return ' %s' % self._requirement_name() + + def __str__(self): + return '%s\n%s' % (self.head, self.body()) + + def _requirement_name(self): + """Return a description of the requirement that triggered me. + + This default implementation returns long description of the req, with + line numbers + + """ + return str(self.req) if self.req else 'unknown package' + + +class VcsHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 0 + head = ("Can't verify hashes for these requirements because we don't " + "have a way to hash version control repositories:") + + +class DirectoryUrlHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 1 + head = ("Can't verify hashes for these file:// requirements because they " + "point to directories:") + + +class HashMissing(HashError): + """A hash was needed for a requirement but is absent.""" + + order = 2 + head = ('Hashes are required in --require-hashes mode, but they are ' + 'missing from some requirements. Here is a list of those ' + 'requirements along with the hashes their downloaded archives ' + 'actually had. Add lines like these to your requirements files to ' + 'prevent tampering. (If you did not enable --require-hashes ' + 'manually, note that it turns on automatically when any package ' + 'has a hash.)') + + def __init__(self, gotten_hash): + """ + :param gotten_hash: The hash of the (possibly malicious) archive we + just downloaded + """ + self.gotten_hash = gotten_hash + + def body(self): + # Dodge circular import. + from pip._internal.utils.hashes import FAVORITE_HASH + + package = None + if self.req: + # In the case of URL-based requirements, display the original URL + # seen in the requirements file rather than the package name, + # so the output can be directly copied into the requirements file. + package = (self.req.original_link if self.req.original_link + # In case someone feeds something downright stupid + # to InstallRequirement's constructor. + else getattr(self.req, 'req', None)) + return ' %s --hash=%s:%s' % (package or 'unknown package', + FAVORITE_HASH, + self.gotten_hash) + + +class HashUnpinned(HashError): + """A requirement had a hash specified but was not pinned to a specific + version.""" + + order = 3 + head = ('In --require-hashes mode, all requirements must have their ' + 'versions pinned with ==. These do not:') + + +class HashMismatch(HashError): + """ + Distribution file hash values don't match. + + :ivar package_name: The name of the package that triggered the hash + mismatch. Feel free to write to this after the exception is raise to + improve its error message. + + """ + order = 4 + head = ('THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS ' + 'FILE. If you have updated the package versions, please update ' + 'the hashes. Otherwise, examine the package contents carefully; ' + 'someone may have tampered with them.') + + def __init__(self, allowed, gots): + """ + :param allowed: A dict of algorithm names pointing to lists of allowed + hex digests + :param gots: A dict of algorithm names pointing to hashes we + actually got from the files under suspicion + """ + self.allowed = allowed + self.gots = gots + + def body(self): + return ' %s:\n%s' % (self._requirement_name(), + self._hash_comparison()) + + def _hash_comparison(self): + """ + Return a comparison of actual and expected hash values. + + Example:: + + Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde + or 123451234512345123451234512345123451234512345 + Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef + + """ + def hash_then_or(hash_name): + # For now, all the decent hashes have 6-char names, so we can get + # away with hard-coding space literals. + return chain([hash_name], repeat(' or')) + + lines = [] + for hash_name, expecteds in iteritems(self.allowed): + prefix = hash_then_or(hash_name) + lines.extend((' Expected %s %s' % (next(prefix), e)) + for e in expecteds) + lines.append(' Got %s\n' % + self.gots[hash_name].hexdigest()) + prefix = ' or' + return '\n'.join(lines) + + +class UnsupportedPythonVersion(InstallationError): + """Unsupported python version according to Requires-Python package + metadata.""" + + +class ConfigurationFileCouldNotBeLoaded(ConfigurationError): + """When there are errors while loading a configuration file + """ + + def __init__(self, reason="could not be loaded", fname=None, error=None): + super(ConfigurationFileCouldNotBeLoaded, self).__init__(error) + self.reason = reason + self.fname = fname + self.error = error + + def __str__(self): + if self.fname is not None: + message_part = " in {}.".format(self.fname) + else: + assert self.error is not None + message_part = ".\n{}\n".format(self.error.message) + return "Configuration file {}{}".format(self.reason, message_part) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/index.py b/venv/lib/python3.7/site-packages/pip/_internal/index.py new file mode 100644 index 0000000..8c2f24f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/index.py @@ -0,0 +1,899 @@ +"""Routines related to PyPI, indexes""" +from __future__ import absolute_import + +import cgi +import itertools +import logging +import mimetypes +import os +import posixpath +import re +import sys +from collections import namedtuple + +from pip._vendor import html5lib, requests, six +from pip._vendor.distlib.compat import unescape +from pip._vendor.packaging import specifiers +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.requests.exceptions import SSLError +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.download import HAS_TLS, is_url, path_to_url, url_to_path +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, DistributionNotFound, InvalidWheelFilename, + UnsupportedWheel, +) +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.models.link import Link +from pip._internal.pep425tags import get_supported +from pip._internal.utils.compat import ipaddress +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, SUPPORTED_EXTENSIONS, normalize_path, + remove_auth_from_url, +) +from pip._internal.utils.packaging import check_requires_python +from pip._internal.wheel import Wheel, wheel_ext + +__all__ = ['FormatControl', 'PackageFinder'] + + +SECURE_ORIGINS = [ + # protocol, hostname, port + # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) + ("https", "*", "*"), + ("*", "localhost", "*"), + ("*", "127.0.0.0/8", "*"), + ("*", "::1/128", "*"), + ("file", "*", None), + # ssh is always secure. + ("ssh", "*", "*"), +] + + +logger = logging.getLogger(__name__) + + +def _get_content_type(url, session): + """Get the Content-Type of the given url, using a HEAD request""" + scheme, netloc, path, query, fragment = urllib_parse.urlsplit(url) + if scheme not in {'http', 'https'}: + # FIXME: some warning or something? + # assertion error? + return '' + + resp = session.head(url, allow_redirects=True) + resp.raise_for_status() + + return resp.headers.get("Content-Type", "") + + +def _handle_get_page_fail(link, reason, url, meth=None): + if meth is None: + meth = logger.debug + meth("Could not fetch URL %s: %s - skipping", link, reason) + + +def _get_html_page(link, session=None): + if session is None: + raise TypeError( + "_get_html_page() missing 1 required keyword argument: 'session'" + ) + + url = link.url + url = url.split('#', 1)[0] + + # Check for VCS schemes that do not support lookup as web pages. + from pip._internal.vcs import VcsSupport + for scheme in VcsSupport.schemes: + if url.lower().startswith(scheme) and url[len(scheme)] in '+:': + logger.debug('Cannot look at %s URL %s', scheme, link) + return None + + try: + filename = link.filename + for bad_ext in ARCHIVE_EXTENSIONS: + if filename.endswith(bad_ext): + content_type = _get_content_type(url, session=session) + if content_type.lower().startswith('text/html'): + break + else: + logger.debug( + 'Skipping page %s because of Content-Type: %s', + link, + content_type, + ) + return + + logger.debug('Getting page %s', url) + + # Tack index.html onto file:// URLs that point to directories + (scheme, netloc, path, params, query, fragment) = \ + urllib_parse.urlparse(url) + if (scheme == 'file' and + os.path.isdir(urllib_request.url2pathname(path))): + # add trailing slash if not present so urljoin doesn't trim + # final segment + if not url.endswith('/'): + url += '/' + url = urllib_parse.urljoin(url, 'index.html') + logger.debug(' file: URL is directory, getting %s', url) + + resp = session.get( + url, + headers={ + "Accept": "text/html", + # We don't want to blindly returned cached data for + # /simple/, because authors generally expecting that + # twine upload && pip install will function, but if + # they've done a pip install in the last ~10 minutes + # it won't. Thus by setting this to zero we will not + # blindly use any cached data, however the benefit of + # using max-age=0 instead of no-cache, is that we will + # still support conditional requests, so we will still + # minimize traffic sent in cases where the page hasn't + # changed at all, we will just always incur the round + # trip for the conditional GET now instead of only + # once per 10 minutes. + # For more information, please see pypa/pip#5670. + "Cache-Control": "max-age=0", + }, + ) + resp.raise_for_status() + + # The check for archives above only works if the url ends with + # something that looks like an archive. However that is not a + # requirement of an url. Unless we issue a HEAD request on every + # url we cannot know ahead of time for sure if something is HTML + # or not. However we can check after we've downloaded it. + content_type = resp.headers.get('Content-Type', 'unknown') + if not content_type.lower().startswith("text/html"): + logger.debug( + 'Skipping page %s because of Content-Type: %s', + link, + content_type, + ) + return + + inst = HTMLPage(resp.content, resp.url, resp.headers) + except requests.HTTPError as exc: + _handle_get_page_fail(link, exc, url) + except SSLError as exc: + reason = "There was a problem confirming the ssl certificate: " + reason += str(exc) + _handle_get_page_fail(link, reason, url, meth=logger.info) + except requests.ConnectionError as exc: + _handle_get_page_fail(link, "connection error: %s" % exc, url) + except requests.Timeout: + _handle_get_page_fail(link, "timed out", url) + else: + return inst + + +class PackageFinder(object): + """This finds packages. + + This is meant to match easy_install's technique for looking for + packages, by reading pages and looking for appropriate links. + """ + + def __init__(self, find_links, index_urls, allow_all_prereleases=False, + trusted_hosts=None, process_dependency_links=False, + session=None, format_control=None, platform=None, + versions=None, abi=None, implementation=None, + prefer_binary=False): + """Create a PackageFinder. + + :param format_control: A FormatControl object or None. Used to control + the selection of source packages / binary packages when consulting + the index and links. + :param platform: A string or None. If None, searches for packages + that are supported by the current system. Otherwise, will find + packages that can be built on the platform passed in. These + packages will only be downloaded for distribution: they will + not be built locally. + :param versions: A list of strings or None. This is passed directly + to pep425tags.py in the get_supported() method. + :param abi: A string or None. This is passed directly + to pep425tags.py in the get_supported() method. + :param implementation: A string or None. This is passed directly + to pep425tags.py in the get_supported() method. + """ + if session is None: + raise TypeError( + "PackageFinder() missing 1 required keyword argument: " + "'session'" + ) + + # Build find_links. If an argument starts with ~, it may be + # a local file relative to a home directory. So try normalizing + # it and if it exists, use the normalized version. + # This is deliberately conservative - it might be fine just to + # blindly normalize anything starting with a ~... + self.find_links = [] + for link in find_links: + if link.startswith('~'): + new_link = normalize_path(link) + if os.path.exists(new_link): + link = new_link + self.find_links.append(link) + + self.index_urls = index_urls + self.dependency_links = [] + + # These are boring links that have already been logged somehow: + self.logged_links = set() + + self.format_control = format_control or FormatControl(set(), set()) + + # Domains that we won't emit warnings for when not using HTTPS + self.secure_origins = [ + ("*", host, "*") + for host in (trusted_hosts if trusted_hosts else []) + ] + + # Do we want to allow _all_ pre-releases? + self.allow_all_prereleases = allow_all_prereleases + + # Do we process dependency links? + self.process_dependency_links = process_dependency_links + + # The Session we'll use to make requests + self.session = session + + # The valid tags to check potential found wheel candidates against + self.valid_tags = get_supported( + versions=versions, + platform=platform, + abi=abi, + impl=implementation, + ) + + # Do we prefer old, but valid, binary dist over new source dist + self.prefer_binary = prefer_binary + + # If we don't have TLS enabled, then WARN if anyplace we're looking + # relies on TLS. + if not HAS_TLS: + for link in itertools.chain(self.index_urls, self.find_links): + parsed = urllib_parse.urlparse(link) + if parsed.scheme == "https": + logger.warning( + "pip is configured with locations that require " + "TLS/SSL, however the ssl module in Python is not " + "available." + ) + break + + def get_formatted_locations(self): + lines = [] + if self.index_urls and self.index_urls != [PyPI.simple_url]: + lines.append( + "Looking in indexes: {}".format(", ".join( + remove_auth_from_url(url) for url in self.index_urls)) + ) + if self.find_links: + lines.append( + "Looking in links: {}".format(", ".join(self.find_links)) + ) + return "\n".join(lines) + + def add_dependency_links(self, links): + # FIXME: this shouldn't be global list this, it should only + # apply to requirements of the package that specifies the + # dependency_links value + # FIXME: also, we should track comes_from (i.e., use Link) + if self.process_dependency_links: + deprecated( + "Dependency Links processing has been deprecated and will be " + "removed in a future release.", + replacement="PEP 508 URL dependencies", + gone_in="18.2", + issue=4187, + ) + self.dependency_links.extend(links) + + @staticmethod + def _sort_locations(locations, expand_dir=False): + """ + Sort locations into "files" (archives) and "urls", and return + a pair of lists (files,urls) + """ + files = [] + urls = [] + + # puts the url for the given file path into the appropriate list + def sort_path(path): + url = path_to_url(path) + if mimetypes.guess_type(url, strict=False)[0] == 'text/html': + urls.append(url) + else: + files.append(url) + + for url in locations: + + is_local_path = os.path.exists(url) + is_file_url = url.startswith('file:') + + if is_local_path or is_file_url: + if is_local_path: + path = url + else: + path = url_to_path(url) + if os.path.isdir(path): + if expand_dir: + path = os.path.realpath(path) + for item in os.listdir(path): + sort_path(os.path.join(path, item)) + elif is_file_url: + urls.append(url) + elif os.path.isfile(path): + sort_path(path) + else: + logger.warning( + "Url '%s' is ignored: it is neither a file " + "nor a directory.", url, + ) + elif is_url(url): + # Only add url with clear scheme + urls.append(url) + else: + logger.warning( + "Url '%s' is ignored. It is either a non-existing " + "path or lacks a specific scheme.", url, + ) + + return files, urls + + def _candidate_sort_key(self, candidate): + """ + Function used to generate link sort key for link tuples. + The greater the return value, the more preferred it is. + If not finding wheels, then sorted by version only. + If finding wheels, then the sort order is by version, then: + 1. existing installs + 2. wheels ordered via Wheel.support_index_min(self.valid_tags) + 3. source archives + If prefer_binary was set, then all wheels are sorted above sources. + Note: it was considered to embed this logic into the Link + comparison operators, but then different sdist links + with the same version, would have to be considered equal + """ + support_num = len(self.valid_tags) + build_tag = tuple() + binary_preference = 0 + if candidate.location.is_wheel: + # can raise InvalidWheelFilename + wheel = Wheel(candidate.location.filename) + if not wheel.supported(self.valid_tags): + raise UnsupportedWheel( + "%s is not a supported wheel for this platform. It " + "can't be sorted." % wheel.filename + ) + if self.prefer_binary: + binary_preference = 1 + pri = -(wheel.support_index_min(self.valid_tags)) + if wheel.build_tag is not None: + match = re.match(r'^(\d+)(.*)$', wheel.build_tag) + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) + else: # sdist + pri = -(support_num) + return (binary_preference, candidate.version, build_tag, pri) + + def _validate_secure_origin(self, logger, location): + # Determine if this url used a secure transport mechanism + parsed = urllib_parse.urlparse(str(location)) + origin = (parsed.scheme, parsed.hostname, parsed.port) + + # The protocol to use to see if the protocol matches. + # Don't count the repository type as part of the protocol: in + # cases such as "git+ssh", only use "ssh". (I.e., Only verify against + # the last scheme.) + protocol = origin[0].rsplit('+', 1)[-1] + + # Determine if our origin is a secure origin by looking through our + # hardcoded list of secure origins, as well as any additional ones + # configured on this PackageFinder instance. + for secure_origin in (SECURE_ORIGINS + self.secure_origins): + if protocol != secure_origin[0] and secure_origin[0] != "*": + continue + + try: + # We need to do this decode dance to ensure that we have a + # unicode object, even on Python 2.x. + addr = ipaddress.ip_address( + origin[1] + if ( + isinstance(origin[1], six.text_type) or + origin[1] is None + ) + else origin[1].decode("utf8") + ) + network = ipaddress.ip_network( + secure_origin[1] + if isinstance(secure_origin[1], six.text_type) + else secure_origin[1].decode("utf8") + ) + except ValueError: + # We don't have both a valid address or a valid network, so + # we'll check this origin against hostnames. + if (origin[1] and + origin[1].lower() != secure_origin[1].lower() and + secure_origin[1] != "*"): + continue + else: + # We have a valid address and network, so see if the address + # is contained within the network. + if addr not in network: + continue + + # Check to see if the port patches + if (origin[2] != secure_origin[2] and + secure_origin[2] != "*" and + secure_origin[2] is not None): + continue + + # If we've gotten here, then this origin matches the current + # secure origin and we should return True + return True + + # If we've gotten to this point, then the origin isn't secure and we + # will not accept it as a valid location to search. We will however + # log a warning that we are ignoring it. + logger.warning( + "The repository located at %s is not a trusted or secure host and " + "is being ignored. If this repository is available via HTTPS we " + "recommend you use HTTPS instead, otherwise you may silence " + "this warning and allow it anyway with '--trusted-host %s'.", + parsed.hostname, + parsed.hostname, + ) + + return False + + def _get_index_urls_locations(self, project_name): + """Returns the locations found via self.index_urls + + Checks the url_name on the main (first in the list) index and + use this url_name to produce all locations + """ + + def mkurl_pypi_url(url): + loc = posixpath.join( + url, + urllib_parse.quote(canonicalize_name(project_name))) + # For maximum compatibility with easy_install, ensure the path + # ends in a trailing slash. Although this isn't in the spec + # (and PyPI can handle it without the slash) some other index + # implementations might break if they relied on easy_install's + # behavior. + if not loc.endswith('/'): + loc = loc + '/' + return loc + + return [mkurl_pypi_url(url) for url in self.index_urls] + + def find_all_candidates(self, project_name): + """Find all available InstallationCandidate for project_name + + This checks index_urls, find_links and dependency_links. + All versions found are returned as an InstallationCandidate list. + + See _link_package_versions for details on which files are accepted + """ + index_locations = self._get_index_urls_locations(project_name) + index_file_loc, index_url_loc = self._sort_locations(index_locations) + fl_file_loc, fl_url_loc = self._sort_locations( + self.find_links, expand_dir=True, + ) + dep_file_loc, dep_url_loc = self._sort_locations(self.dependency_links) + + file_locations = (Link(url) for url in itertools.chain( + index_file_loc, fl_file_loc, dep_file_loc, + )) + + # We trust every url that the user has given us whether it was given + # via --index-url or --find-links + # We explicitly do not trust links that came from dependency_links + # We want to filter out any thing which does not have a secure origin. + url_locations = [ + link for link in itertools.chain( + (Link(url) for url in index_url_loc), + (Link(url) for url in fl_url_loc), + (Link(url) for url in dep_url_loc), + ) + if self._validate_secure_origin(logger, link) + ] + + logger.debug('%d location(s) to search for versions of %s:', + len(url_locations), project_name) + + for location in url_locations: + logger.debug('* %s', location) + + canonical_name = canonicalize_name(project_name) + formats = self.format_control.get_allowed_formats(canonical_name) + search = Search(project_name, canonical_name, formats) + find_links_versions = self._package_versions( + # We trust every directly linked archive in find_links + (Link(url, '-f') for url in self.find_links), + search + ) + + page_versions = [] + for page in self._get_pages(url_locations, project_name): + logger.debug('Analyzing links from page %s', page.url) + with indent_log(): + page_versions.extend( + self._package_versions(page.iter_links(), search) + ) + + dependency_versions = self._package_versions( + (Link(url) for url in self.dependency_links), search + ) + if dependency_versions: + logger.debug( + 'dependency_links found: %s', + ', '.join([ + version.location.url for version in dependency_versions + ]) + ) + + file_versions = self._package_versions(file_locations, search) + if file_versions: + file_versions.sort(reverse=True) + logger.debug( + 'Local files found: %s', + ', '.join([ + url_to_path(candidate.location.url) + for candidate in file_versions + ]) + ) + + # This is an intentional priority ordering + return ( + file_versions + find_links_versions + page_versions + + dependency_versions + ) + + def find_requirement(self, req, upgrade): + """Try to find a Link matching req + + Expects req, an InstallRequirement and upgrade, a boolean + Returns a Link if found, + Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise + """ + all_candidates = self.find_all_candidates(req.name) + + # Filter out anything which doesn't match our specifier + compatible_versions = set( + req.specifier.filter( + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + [str(c.version) for c in all_candidates], + prereleases=( + self.allow_all_prereleases + if self.allow_all_prereleases else None + ), + ) + ) + applicable_candidates = [ + # Again, converting to str to deal with debundling. + c for c in all_candidates if str(c.version) in compatible_versions + ] + + if applicable_candidates: + best_candidate = max(applicable_candidates, + key=self._candidate_sort_key) + else: + best_candidate = None + + if req.satisfied_by is not None: + installed_version = parse_version(req.satisfied_by.version) + else: + installed_version = None + + if installed_version is None and best_candidate is None: + logger.critical( + 'Could not find a version that satisfies the requirement %s ' + '(from versions: %s)', + req, + ', '.join( + sorted( + {str(c.version) for c in all_candidates}, + key=parse_version, + ) + ) + ) + + raise DistributionNotFound( + 'No matching distribution found for %s' % req + ) + + best_installed = False + if installed_version and ( + best_candidate is None or + best_candidate.version <= installed_version): + best_installed = True + + if not upgrade and installed_version is not None: + if best_installed: + logger.debug( + 'Existing installed version (%s) is most up-to-date and ' + 'satisfies requirement', + installed_version, + ) + else: + logger.debug( + 'Existing installed version (%s) satisfies requirement ' + '(most up-to-date version is %s)', + installed_version, + best_candidate.version, + ) + return None + + if best_installed: + # We have an existing version, and its the best version + logger.debug( + 'Installed version (%s) is most up-to-date (past versions: ' + '%s)', + installed_version, + ', '.join(sorted(compatible_versions, key=parse_version)) or + "none", + ) + raise BestVersionAlreadyInstalled + + logger.debug( + 'Using version %s (newest of versions: %s)', + best_candidate.version, + ', '.join(sorted(compatible_versions, key=parse_version)) + ) + return best_candidate.location + + def _get_pages(self, locations, project_name): + """ + Yields (page, page_url) from the given locations, skipping + locations that have errors. + """ + seen = set() + for location in locations: + if location in seen: + continue + seen.add(location) + + page = self._get_page(location) + if page is None: + continue + + yield page + + _py_version_re = re.compile(r'-py([123]\.?[0-9]?)$') + + def _sort_links(self, links): + """ + Returns elements of links in order, non-egg links first, egg links + second, while eliminating duplicates + """ + eggs, no_eggs = [], [] + seen = set() + for link in links: + if link not in seen: + seen.add(link) + if link.egg_fragment: + eggs.append(link) + else: + no_eggs.append(link) + return no_eggs + eggs + + def _package_versions(self, links, search): + result = [] + for link in self._sort_links(links): + v = self._link_package_versions(link, search) + if v is not None: + result.append(v) + return result + + def _log_skipped_link(self, link, reason): + if link not in self.logged_links: + logger.debug('Skipping link %s; %s', link, reason) + self.logged_links.add(link) + + def _link_package_versions(self, link, search): + """Return an InstallationCandidate or None""" + version = None + if link.egg_fragment: + egg_info = link.egg_fragment + ext = link.ext + else: + egg_info, ext = link.splitext() + if not ext: + self._log_skipped_link(link, 'not a file') + return + if ext not in SUPPORTED_EXTENSIONS: + self._log_skipped_link( + link, 'unsupported archive format: %s' % ext, + ) + return + if "binary" not in search.formats and ext == wheel_ext: + self._log_skipped_link( + link, 'No binaries permitted for %s' % search.supplied, + ) + return + if "macosx10" in link.path and ext == '.zip': + self._log_skipped_link(link, 'macosx10 one') + return + if ext == wheel_ext: + try: + wheel = Wheel(link.filename) + except InvalidWheelFilename: + self._log_skipped_link(link, 'invalid wheel filename') + return + if canonicalize_name(wheel.name) != search.canonical: + self._log_skipped_link( + link, 'wrong project name (not %s)' % search.supplied) + return + + if not wheel.supported(self.valid_tags): + self._log_skipped_link( + link, 'it is not compatible with this Python') + return + + version = wheel.version + + # This should be up by the search.ok_binary check, but see issue 2700. + if "source" not in search.formats and ext != wheel_ext: + self._log_skipped_link( + link, 'No sources permitted for %s' % search.supplied, + ) + return + + if not version: + version = egg_info_matches(egg_info, search.supplied, link) + if version is None: + self._log_skipped_link( + link, 'Missing project version for %s' % search.supplied) + return + + match = self._py_version_re.search(version) + if match: + version = version[:match.start()] + py_version = match.group(1) + if py_version != sys.version[:3]: + self._log_skipped_link( + link, 'Python version is incorrect') + return + try: + support_this_python = check_requires_python(link.requires_python) + except specifiers.InvalidSpecifier: + logger.debug("Package %s has an invalid Requires-Python entry: %s", + link.filename, link.requires_python) + support_this_python = True + + if not support_this_python: + logger.debug("The package %s is incompatible with the python" + "version in use. Acceptable python versions are:%s", + link, link.requires_python) + return + logger.debug('Found link %s, version: %s', link, version) + + return InstallationCandidate(search.supplied, version, link) + + def _get_page(self, link): + return _get_html_page(link, session=self.session) + + +def egg_info_matches( + egg_info, search_name, link, + _egg_info_re=re.compile(r'([a-z0-9_.]+)-([a-z0-9_.!+-]+)', re.I)): + """Pull the version part out of a string. + + :param egg_info: The string to parse. E.g. foo-2.1 + :param search_name: The name of the package this belongs to. None to + infer the name. Note that this cannot unambiguously parse strings + like foo-2-2 which might be foo, 2-2 or foo-2, 2. + :param link: The link the string came from, for logging on failure. + """ + match = _egg_info_re.search(egg_info) + if not match: + logger.debug('Could not parse version from link: %s', link) + return None + if search_name is None: + full_match = match.group(0) + return full_match.split('-', 1)[-1] + name = match.group(0).lower() + # To match the "safe" name that pkg_resources creates: + name = name.replace('_', '-') + # project name and version must be separated by a dash + look_for = search_name.lower() + "-" + if name.startswith(look_for): + return match.group(0)[len(look_for):] + else: + return None + + +def _determine_base_url(document, page_url): + """Determine the HTML document's base URL. + + This looks for a ```` tag in the HTML document. If present, its href + attribute denotes the base URL of anchor tags in the document. If there is + no such tag (or if it does not have a valid href attribute), the HTML + file's URL is used as the base URL. + + :param document: An HTML document representation. The current + implementation expects the result of ``html5lib.parse()``. + :param page_url: The URL of the HTML document. + """ + for base in document.findall(".//base"): + href = base.get("href") + if href is not None: + return href + return page_url + + +def _get_encoding_from_headers(headers): + """Determine if we have any encoding information in our headers. + """ + if headers and "Content-Type" in headers: + content_type, params = cgi.parse_header(headers["Content-Type"]) + if "charset" in params: + return params['charset'] + return None + + +_CLEAN_LINK_RE = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + +def _clean_link(url): + """Makes sure a link is fully encoded. That is, if a ' ' shows up in + the link, it will be rewritten to %20 (while not over-quoting + % or other characters).""" + return _CLEAN_LINK_RE.sub(lambda match: '%%%2x' % ord(match.group(0)), url) + + +class HTMLPage(object): + """Represents one page, along with its URL""" + + def __init__(self, content, url, headers=None): + self.content = content + self.url = url + self.headers = headers + + def __str__(self): + return self.url + + def iter_links(self): + """Yields all links in the page""" + document = html5lib.parse( + self.content, + transport_encoding=_get_encoding_from_headers(self.headers), + namespaceHTMLElements=False, + ) + base_url = _determine_base_url(document, self.url) + for anchor in document.findall(".//a"): + if anchor.get("href"): + href = anchor.get("href") + url = _clean_link(urllib_parse.urljoin(base_url, href)) + pyrequire = anchor.get('data-requires-python') + pyrequire = unescape(pyrequire) if pyrequire else None + yield Link(url, self.url, requires_python=pyrequire) + + +Search = namedtuple('Search', 'supplied canonical formats') +"""Capture key aspects of a search. + +:attribute supplied: The user supplied package. +:attribute canonical: The canonical package name. +:attribute formats: The formats allowed for this package. Should be a set + with 'binary' or 'source' or both in it. +""" diff --git a/venv/lib/python3.7/site-packages/pip/_internal/locations.py b/venv/lib/python3.7/site-packages/pip/_internal/locations.py new file mode 100644 index 0000000..183aaa3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/locations.py @@ -0,0 +1,194 @@ +"""Locations where we look for configs, install stuff, etc""" +from __future__ import absolute_import + +import os +import os.path +import platform +import site +import sys +import sysconfig +from distutils import sysconfig as distutils_sysconfig +from distutils.command.install import SCHEME_KEYS # type: ignore + +from pip._internal.utils import appdirs +from pip._internal.utils.compat import WINDOWS, expanduser + +# Application Directories +USER_CACHE_DIR = appdirs.user_cache_dir("pip") + + +DELETE_MARKER_MESSAGE = '''\ +This file is placed here by pip to indicate the source was put +here by pip. + +Once this package is successfully installed this source code will be +deleted (unless you remove this file). +''' +PIP_DELETE_MARKER_FILENAME = 'pip-delete-this-directory.txt' + + +def write_delete_marker_file(directory): + """ + Write the pip delete marker file into this directory. + """ + filepath = os.path.join(directory, PIP_DELETE_MARKER_FILENAME) + with open(filepath, 'w') as marker_fp: + marker_fp.write(DELETE_MARKER_MESSAGE) + + +def running_under_virtualenv(): + """ + Return True if we're running inside a virtualenv, False otherwise. + + """ + if hasattr(sys, 'real_prefix'): + return True + elif sys.prefix != getattr(sys, "base_prefix", sys.prefix): + return True + + return False + + +def virtualenv_no_global(): + """ + Return True if in a venv and no system site packages. + """ + # this mirrors the logic in virtualenv.py for locating the + # no-global-site-packages.txt file + site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) + no_global_file = os.path.join(site_mod_dir, 'no-global-site-packages.txt') + if running_under_virtualenv() and os.path.isfile(no_global_file): + return True + + +if running_under_virtualenv(): + src_prefix = os.path.join(sys.prefix, 'src') +else: + # FIXME: keep src in cwd for now (it is not a temporary folder) + try: + src_prefix = os.path.join(os.getcwd(), 'src') + except OSError: + # In case the current working directory has been renamed or deleted + sys.exit( + "The folder you are executing pip from can no longer be found." + ) + +# under macOS + virtualenv sys.prefix is not properly resolved +# it is something like /path/to/python/bin/.. +# Note: using realpath due to tmp dirs on OSX being symlinks +src_prefix = os.path.abspath(src_prefix) + +# FIXME doesn't account for venv linked to global site-packages + +site_packages = sysconfig.get_path("purelib") +# This is because of a bug in PyPy's sysconfig module, see +# https://bitbucket.org/pypy/pypy/issues/2506/sysconfig-returns-incorrect-paths +# for more information. +if platform.python_implementation().lower() == "pypy": + site_packages = distutils_sysconfig.get_python_lib() +try: + # Use getusersitepackages if this is present, as it ensures that the + # value is initialised properly. + user_site = site.getusersitepackages() +except AttributeError: + user_site = site.USER_SITE +user_dir = expanduser('~') +if WINDOWS: + bin_py = os.path.join(sys.prefix, 'Scripts') + bin_user = os.path.join(user_site, 'Scripts') + # buildout uses 'bin' on Windows too? + if not os.path.exists(bin_py): + bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') + + config_basename = 'pip.ini' + + legacy_storage_dir = os.path.join(user_dir, 'pip') + legacy_config_file = os.path.join( + legacy_storage_dir, + config_basename, + ) +else: + bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') + + config_basename = 'pip.conf' + + legacy_storage_dir = os.path.join(user_dir, '.pip') + legacy_config_file = os.path.join( + legacy_storage_dir, + config_basename, + ) + # Forcing to use /usr/local/bin for standard macOS framework installs + # Also log to ~/Library/Logs/ for use with the Console.app log viewer + if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/': + bin_py = '/usr/local/bin' + +site_config_files = [ + os.path.join(path, config_basename) + for path in appdirs.site_config_dirs('pip') +] + +venv_config_file = os.path.join(sys.prefix, config_basename) +new_config_file = os.path.join(appdirs.user_config_dir("pip"), config_basename) + + +def distutils_scheme(dist_name, user=False, home=None, root=None, + isolated=False, prefix=None): + """ + Return a distutils install scheme + """ + from distutils.dist import Distribution + + scheme = {} + + if isolated: + extra_dist_args = {"script_args": ["--no-user-cfg"]} + else: + extra_dist_args = {} + dist_args = {'name': dist_name} + dist_args.update(extra_dist_args) + + d = Distribution(dist_args) + d.parse_config_files() + i = d.get_command_obj('install', create=True) + # NOTE: setting user or home has the side-effect of creating the home dir + # or user base for installations during finalize_options() + # ideally, we'd prefer a scheme class that has no side-effects. + assert not (user and prefix), "user={} prefix={}".format(user, prefix) + i.user = user or i.user + if user: + i.prefix = "" + i.prefix = prefix or i.prefix + i.home = home or i.home + i.root = root or i.root + i.finalize_options() + for key in SCHEME_KEYS: + scheme[key] = getattr(i, 'install_' + key) + + # install_lib specified in setup.cfg should install *everything* + # into there (i.e. it takes precedence over both purelib and + # platlib). Note, i.install_lib is *always* set after + # finalize_options(); we only want to override here if the user + # has explicitly requested it hence going back to the config + if 'install_lib' in d.get_option_dict('install'): + scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + + if running_under_virtualenv(): + scheme['headers'] = os.path.join( + sys.prefix, + 'include', + 'site', + 'python' + sys.version[:3], + dist_name, + ) + + if root is not None: + path_no_drive = os.path.splitdrive( + os.path.abspath(scheme["headers"]))[1] + scheme["headers"] = os.path.join( + root, + path_no_drive[1:], + ) + + return scheme diff --git a/venv/lib/python3.7/site-packages/pip/_internal/models/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/models/__init__.py new file mode 100644 index 0000000..7855226 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/models/__init__.py @@ -0,0 +1,2 @@ +"""A package that contains models that represent entities. +""" diff --git a/venv/lib/python3.7/site-packages/pip/_internal/models/candidate.py b/venv/lib/python3.7/site-packages/pip/_internal/models/candidate.py new file mode 100644 index 0000000..c736de6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/models/candidate.py @@ -0,0 +1,23 @@ +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.utils.models import KeyBasedCompareMixin + + +class InstallationCandidate(KeyBasedCompareMixin): + """Represents a potential "candidate" for installation. + """ + + def __init__(self, project, version, location): + self.project = project + self.version = parse_version(version) + self.location = location + + super(InstallationCandidate, self).__init__( + key=(self.project, self.version, self.location), + defining_class=InstallationCandidate + ) + + def __repr__(self): + return "".format( + self.project, self.version, self.location, + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/models/format_control.py b/venv/lib/python3.7/site-packages/pip/_internal/models/format_control.py new file mode 100644 index 0000000..2748856 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/models/format_control.py @@ -0,0 +1,62 @@ +from pip._vendor.packaging.utils import canonicalize_name + + +class FormatControl(object): + """A helper class for controlling formats from which packages are installed. + If a field is falsy, it isn't set. If it is {':all:'}, it should match all + packages except those listed in the other field. Only one field can be set + to {':all:'} at a time. The rest of the time exact package name matches + are listed, with any given package only showing up in one field at a time. + """ + def __init__(self, no_binary=None, only_binary=None): + self.no_binary = set() if no_binary is None else no_binary + self.only_binary = set() if only_binary is None else only_binary + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return "{}({}, {})".format( + self.__class__.__name__, + self.no_binary, + self.only_binary + ) + + @staticmethod + def handle_mutual_excludes(value, target, other): + new = value.split(',') + while ':all:' in new: + other.clear() + target.clear() + target.add(':all:') + del new[:new.index(':all:') + 1] + # Without a none, we want to discard everything as :all: covers it + if ':none:' not in new: + return + for name in new: + if name == ':none:': + target.clear() + continue + name = canonicalize_name(name) + other.discard(name) + target.add(name) + + def get_allowed_formats(self, canonical_name): + result = {"binary", "source"} + if canonical_name in self.only_binary: + result.discard('source') + elif canonical_name in self.no_binary: + result.discard('binary') + elif ':all:' in self.only_binary: + result.discard('source') + elif ':all:' in self.no_binary: + result.discard('binary') + return frozenset(result) + + def disallow_binaries(self): + self.handle_mutual_excludes( + ':all:', self.no_binary, self.only_binary, + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/models/index.py b/venv/lib/python3.7/site-packages/pip/_internal/models/index.py new file mode 100644 index 0000000..870a315 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/models/index.py @@ -0,0 +1,29 @@ +from pip._vendor.six.moves.urllib import parse as urllib_parse + + +class PackageIndex(object): + """Represents a Package Index and provides easier access to endpoints + """ + + def __init__(self, url, file_storage_domain): + super(PackageIndex, self).__init__() + self.url = url + self.netloc = urllib_parse.urlsplit(url).netloc + self.simple_url = self._url_for_path('simple') + self.pypi_url = self._url_for_path('pypi') + + # This is part of a temporary hack used to block installs of PyPI + # packages which depend on external urls only necessary until PyPI can + # block such packages themselves + self.file_storage_domain = file_storage_domain + + def _url_for_path(self, path): + return urllib_parse.urljoin(self.url, path) + + +PyPI = PackageIndex( + 'https://pypi.org/', file_storage_domain='files.pythonhosted.org' +) +TestPyPI = PackageIndex( + 'https://test.pypi.org/', file_storage_domain='test-files.pythonhosted.org' +) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/models/link.py b/venv/lib/python3.7/site-packages/pip/_internal/models/link.py new file mode 100644 index 0000000..5decb7c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/models/link.py @@ -0,0 +1,141 @@ +import posixpath +import re + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.download import path_to_url +from pip._internal.utils.misc import splitext +from pip._internal.utils.models import KeyBasedCompareMixin +from pip._internal.wheel import wheel_ext + + +class Link(KeyBasedCompareMixin): + """Represents a parsed link from a Package Index's simple URL + """ + + def __init__(self, url, comes_from=None, requires_python=None): + """ + url: + url of the resource pointed to (href of the link) + comes_from: + instance of HTMLPage where the link was found, or string. + requires_python: + String containing the `Requires-Python` metadata field, specified + in PEP 345. This may be specified by a data-requires-python + attribute in the HTML link tag, as described in PEP 503. + """ + + # url can be a UNC windows share + if url.startswith('\\\\'): + url = path_to_url(url) + + self.url = url + self.comes_from = comes_from + self.requires_python = requires_python if requires_python else None + + super(Link, self).__init__( + key=(self.url), + defining_class=Link + ) + + def __str__(self): + if self.requires_python: + rp = ' (requires-python:%s)' % self.requires_python + else: + rp = '' + if self.comes_from: + return '%s (from %s)%s' % (self.url, self.comes_from, rp) + else: + return str(self.url) + + def __repr__(self): + return '' % self + + @property + def filename(self): + _, netloc, path, _, _ = urllib_parse.urlsplit(self.url) + name = posixpath.basename(path.rstrip('/')) or netloc + name = urllib_parse.unquote(name) + assert name, ('URL %r produced no filename' % self.url) + return name + + @property + def scheme(self): + return urllib_parse.urlsplit(self.url)[0] + + @property + def netloc(self): + return urllib_parse.urlsplit(self.url)[1] + + @property + def path(self): + return urllib_parse.unquote(urllib_parse.urlsplit(self.url)[2]) + + def splitext(self): + return splitext(posixpath.basename(self.path.rstrip('/'))) + + @property + def ext(self): + return self.splitext()[1] + + @property + def url_without_fragment(self): + scheme, netloc, path, query, fragment = urllib_parse.urlsplit(self.url) + return urllib_parse.urlunsplit((scheme, netloc, path, query, None)) + + _egg_fragment_re = re.compile(r'[#&]egg=([^&]*)') + + @property + def egg_fragment(self): + match = self._egg_fragment_re.search(self.url) + if not match: + return None + return match.group(1) + + _subdirectory_fragment_re = re.compile(r'[#&]subdirectory=([^&]*)') + + @property + def subdirectory_fragment(self): + match = self._subdirectory_fragment_re.search(self.url) + if not match: + return None + return match.group(1) + + _hash_re = re.compile( + r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)' + ) + + @property + def hash(self): + match = self._hash_re.search(self.url) + if match: + return match.group(2) + return None + + @property + def hash_name(self): + match = self._hash_re.search(self.url) + if match: + return match.group(1) + return None + + @property + def show_url(self): + return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0]) + + @property + def is_wheel(self): + return self.ext == wheel_ext + + @property + def is_artifact(self): + """ + Determines if this points to an actual artifact (e.g. a tarball) or if + it points to an "abstract" thing like a path or a VCS location. + """ + from pip._internal.vcs import vcs + + if self.scheme in vcs.all_schemes: + return False + + return True diff --git a/venv/lib/python3.7/site-packages/pip/_internal/operations/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pip/_internal/operations/check.py b/venv/lib/python3.7/site-packages/pip/_internal/operations/check.py new file mode 100644 index 0000000..799257a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/operations/check.py @@ -0,0 +1,148 @@ +"""Validation of dependencies of packages +""" + +from collections import namedtuple + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.operations.prepare import make_abstract_dist +from pip._internal.utils.misc import get_installed_distributions +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + from typing import ( # noqa: F401 + Any, Callable, Dict, Iterator, Optional, Set, Tuple, List + ) + + # Shorthands + PackageSet = Dict[str, 'PackageDetails'] + Missing = Tuple[str, Any] + Conflicting = Tuple[str, str, Any] + + MissingDict = Dict[str, List[Missing]] + ConflictingDict = Dict[str, List[Conflicting]] + CheckResult = Tuple[MissingDict, ConflictingDict] + +PackageDetails = namedtuple('PackageDetails', ['version', 'requires']) + + +def create_package_set_from_installed(**kwargs): + # type: (**Any) -> PackageSet + """Converts a list of distributions into a PackageSet. + """ + # Default to using all packages installed on the system + if kwargs == {}: + kwargs = {"local_only": False, "skip": ()} + + package_set = {} + for dist in get_installed_distributions(**kwargs): + name = canonicalize_name(dist.project_name) + package_set[name] = PackageDetails(dist.version, dist.requires()) + return package_set + + +def check_package_set(package_set, should_ignore=None): + # type: (PackageSet, Optional[Callable[[str], bool]]) -> CheckResult + """Check if a package set is consistent + + If should_ignore is passed, it should be a callable that takes a + package name and returns a boolean. + """ + if should_ignore is None: + def should_ignore(name): + return False + + missing = dict() + conflicting = dict() + + for package_name in package_set: + # Info about dependencies of package_name + missing_deps = set() # type: Set[Missing] + conflicting_deps = set() # type: Set[Conflicting] + + if should_ignore(package_name): + continue + + for req in package_set[package_name].requires: + name = canonicalize_name(req.project_name) # type: str + + # Check if it's missing + if name not in package_set: + missed = True + if req.marker is not None: + missed = req.marker.evaluate() + if missed: + missing_deps.add((name, req)) + continue + + # Check if there's a conflict + version = package_set[name].version # type: str + if not req.specifier.contains(version, prereleases=True): + conflicting_deps.add((name, version, req)) + + if missing_deps: + missing[package_name] = sorted(missing_deps, key=str) + if conflicting_deps: + conflicting[package_name] = sorted(conflicting_deps, key=str) + + return missing, conflicting + + +def check_install_conflicts(to_install): + # type: (List[InstallRequirement]) -> Tuple[PackageSet, CheckResult] + """For checking if the dependency graph would be consistent after \ + installing given requirements + """ + # Start from the current state + package_set = create_package_set_from_installed() + # Install packages + would_be_installed = _simulate_installation_of(to_install, package_set) + + # Only warn about directly-dependent packages; create a whitelist of them + whitelist = _create_whitelist(would_be_installed, package_set) + + return ( + package_set, + check_package_set( + package_set, should_ignore=lambda name: name not in whitelist + ) + ) + + +# NOTE from @pradyunsg +# This required a minor update in dependency link handling logic over at +# operations.prepare.IsSDist.dist() to get it working +def _simulate_installation_of(to_install, package_set): + # type: (List[InstallRequirement], PackageSet) -> Set[str] + """Computes the version of packages after installing to_install. + """ + + # Keep track of packages that were installed + installed = set() + + # Modify it as installing requirement_set would (assuming no errors) + for inst_req in to_install: + dist = make_abstract_dist(inst_req).dist(finder=None) + name = canonicalize_name(dist.key) + package_set[name] = PackageDetails(dist.version, dist.requires()) + + installed.add(name) + + return installed + + +def _create_whitelist(would_be_installed, package_set): + # type: (Set[str], PackageSet) -> Set[str] + packages_affected = set(would_be_installed) + + for package_name in package_set: + if package_name in packages_affected: + continue + + for req in package_set[package_name].requires: + if canonicalize_name(req.name) in packages_affected: + packages_affected.add(package_name) + break + + return packages_affected diff --git a/venv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py b/venv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..beb2feb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/operations/freeze.py @@ -0,0 +1,264 @@ +from __future__ import absolute_import + +import collections +import logging +import os +import re + +from pip._vendor import pkg_resources, six +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.pkg_resources import RequirementParseError + +from pip._internal.exceptions import InstallationError +from pip._internal.req.constructors import ( + install_req_from_editable, install_req_from_line, +) +from pip._internal.req.req_file import COMMENT_RE +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.misc import ( + dist_is_editable, get_installed_distributions, make_vcs_requirement_url, +) + +logger = logging.getLogger(__name__) + + +def freeze( + requirement=None, + find_links=None, local_only=None, user_only=None, skip_regex=None, + isolated=False, + wheel_cache=None, + exclude_editable=False, + skip=()): + find_links = find_links or [] + skip_match = None + + if skip_regex: + skip_match = re.compile(skip_regex).search + + dependency_links = [] + + for dist in pkg_resources.working_set: + if dist.has_metadata('dependency_links.txt'): + dependency_links.extend( + dist.get_metadata_lines('dependency_links.txt') + ) + for link in find_links: + if '#egg=' in link: + dependency_links.append(link) + for link in find_links: + yield '-f %s' % link + installations = {} + for dist in get_installed_distributions(local_only=local_only, + skip=(), + user_only=user_only): + try: + req = FrozenRequirement.from_dist( + dist, + dependency_links + ) + except RequirementParseError: + logger.warning( + "Could not parse requirement: %s", + dist.project_name + ) + continue + if exclude_editable and req.editable: + continue + installations[req.name] = req + + if requirement: + # the options that don't get turned into an InstallRequirement + # should only be emitted once, even if the same option is in multiple + # requirements files, so we need to keep track of what has been emitted + # so that we don't emit it again if it's seen again + emitted_options = set() + # keep track of which files a requirement is in so that we can + # give an accurate warning if a requirement appears multiple times. + req_files = collections.defaultdict(list) + for req_file_path in requirement: + with open(req_file_path) as req_file: + for line in req_file: + if (not line.strip() or + line.strip().startswith('#') or + (skip_match and skip_match(line)) or + line.startswith(( + '-r', '--requirement', + '-Z', '--always-unzip', + '-f', '--find-links', + '-i', '--index-url', + '--pre', + '--trusted-host', + '--process-dependency-links', + '--extra-index-url'))): + line = line.rstrip() + if line not in emitted_options: + emitted_options.add(line) + yield line + continue + + if line.startswith('-e') or line.startswith('--editable'): + if line.startswith('-e'): + line = line[2:].strip() + else: + line = line[len('--editable'):].strip().lstrip('=') + line_req = install_req_from_editable( + line, + isolated=isolated, + wheel_cache=wheel_cache, + ) + else: + line_req = install_req_from_line( + COMMENT_RE.sub('', line).strip(), + isolated=isolated, + wheel_cache=wheel_cache, + ) + + if not line_req.name: + logger.info( + "Skipping line in requirement file [%s] because " + "it's not clear what it would install: %s", + req_file_path, line.strip(), + ) + logger.info( + " (add #egg=PackageName to the URL to avoid" + " this warning)" + ) + elif line_req.name not in installations: + # either it's not installed, or it is installed + # but has been processed already + if not req_files[line_req.name]: + logger.warning( + "Requirement file [%s] contains %s, but that " + "package is not installed", + req_file_path, + COMMENT_RE.sub('', line).strip(), + ) + else: + req_files[line_req.name].append(req_file_path) + else: + yield str(installations[line_req.name]).rstrip() + del installations[line_req.name] + req_files[line_req.name].append(req_file_path) + + # Warn about requirements that were included multiple times (in a + # single requirements file or in different requirements files). + for name, files in six.iteritems(req_files): + if len(files) > 1: + logger.warning("Requirement %s included multiple times [%s]", + name, ', '.join(sorted(set(files)))) + + yield( + '## The following requirements were added by ' + 'pip freeze:' + ) + for installation in sorted( + installations.values(), key=lambda x: x.name.lower()): + if canonicalize_name(installation.name) not in skip: + yield str(installation).rstrip() + + +class FrozenRequirement(object): + def __init__(self, name, req, editable, comments=()): + self.name = name + self.req = req + self.editable = editable + self.comments = comments + + _rev_re = re.compile(r'-r(\d+)$') + _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') + + @classmethod + def _init_args_from_dist(cls, dist, dependency_links): + """ + Compute and return arguments (req, editable, comments) to pass to + FrozenRequirement.__init__(). + + This method is for use in FrozenRequirement.from_dist(). + """ + location = os.path.normcase(os.path.abspath(dist.location)) + comments = [] + from pip._internal.vcs import vcs, get_src_requirement + if dist_is_editable(dist) and vcs.get_backend_name(location): + editable = True + try: + req = get_src_requirement(dist, location) + except InstallationError as exc: + logger.warning( + "Error when trying to get requirement for VCS system %s, " + "falling back to uneditable format", exc + ) + req = None + if req is None: + logger.warning( + 'Could not determine repository location of %s', location + ) + comments.append( + '## !! Could not determine repository location' + ) + req = dist.as_requirement() + editable = False + else: + editable = False + req = dist.as_requirement() + specs = req.specs + assert len(specs) == 1 and specs[0][0] in ["==", "==="], \ + 'Expected 1 spec with == or ===; specs = %r; dist = %r' % \ + (specs, dist) + version = specs[0][1] + ver_match = cls._rev_re.search(version) + date_match = cls._date_re.search(version) + if ver_match or date_match: + svn_backend = vcs.get_backend('svn') + if svn_backend: + svn_location = svn_backend().get_location( + dist, + dependency_links, + ) + if not svn_location: + logger.warning( + 'Warning: cannot find svn location for %s', req, + ) + comments.append( + '## FIXME: could not find svn URL in dependency_links ' + 'for this package:' + ) + else: + deprecated( + "SVN editable detection based on dependency links " + "will be dropped in the future.", + replacement=None, + gone_in="18.2", + issue=4187, + ) + comments.append( + '# Installing as editable to satisfy requirement %s:' % + req + ) + if ver_match: + rev = ver_match.group(1) + else: + rev = '{%s}' % date_match.group(1) + editable = True + egg_name = cls.egg_name(dist) + req = make_vcs_requirement_url(svn_location, rev, egg_name) + + return (req, editable, comments) + + @classmethod + def from_dist(cls, dist, dependency_links): + args = cls._init_args_from_dist(dist, dependency_links) + return cls(dist.project_name, *args) + + @staticmethod + def egg_name(dist): + name = dist.egg_name() + match = re.search(r'-py\d\.\d$', name) + if match: + name = name[:match.start()] + return name + + def __str__(self): + req = self.req + if self.editable: + req = '-e %s' % req + return '\n'.join(list(self.comments) + [str(req)]) + '\n' diff --git a/venv/lib/python3.7/site-packages/pip/_internal/operations/prepare.py b/venv/lib/python3.7/site-packages/pip/_internal/operations/prepare.py new file mode 100644 index 0000000..104bea3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/operations/prepare.py @@ -0,0 +1,355 @@ +"""Prepares a distribution for installation +""" + +import logging +import os + +from pip._vendor import pkg_resources, requests + +from pip._internal.build_env import BuildEnvironment +from pip._internal.download import ( + is_dir_url, is_file_url, is_vcs_url, unpack_url, url_to_path, +) +from pip._internal.exceptions import ( + DirectoryUrlHashUnsupported, HashUnpinned, InstallationError, + PreviousBuildDirError, VcsHashUnsupported, +) +from pip._internal.utils.compat import expanduser +from pip._internal.utils.hashes import MissingHashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import display_path, normalize_path +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + + +def make_abstract_dist(req): + """Factory to make an abstract dist object. + + Preconditions: Either an editable req with a source_dir, or satisfied_by or + a wheel link, or a non-editable req with a source_dir. + + :return: A concrete DistAbstraction. + """ + if req.editable: + return IsSDist(req) + elif req.link and req.link.is_wheel: + return IsWheel(req) + else: + return IsSDist(req) + + +class DistAbstraction(object): + """Abstracts out the wheel vs non-wheel Resolver.resolve() logic. + + The requirements for anything installable are as follows: + - we must be able to determine the requirement name + (or we can't correctly handle the non-upgrade case). + - we must be able to generate a list of run-time dependencies + without installing any additional packages (or we would + have to either burn time by doing temporary isolated installs + or alternatively violate pips 'don't start installing unless + all requirements are available' rule - neither of which are + desirable). + - for packages with setup requirements, we must also be able + to determine their requirements without installing additional + packages (for the same reason as run-time dependencies) + - we must be able to create a Distribution object exposing the + above metadata. + """ + + def __init__(self, req): + self.req = req + + def dist(self, finder): + """Return a setuptools Dist object.""" + raise NotImplementedError(self.dist) + + def prep_for_dist(self, finder, build_isolation): + """Ensure that we can get a Dist for this requirement.""" + raise NotImplementedError(self.dist) + + +class IsWheel(DistAbstraction): + + def dist(self, finder): + return list(pkg_resources.find_distributions( + self.req.source_dir))[0] + + def prep_for_dist(self, finder, build_isolation): + # FIXME:https://github.com/pypa/pip/issues/1112 + pass + + +class IsSDist(DistAbstraction): + + def dist(self, finder): + dist = self.req.get_dist() + # FIXME: shouldn't be globally added. + if finder and dist.has_metadata('dependency_links.txt'): + finder.add_dependency_links( + dist.get_metadata_lines('dependency_links.txt') + ) + return dist + + def prep_for_dist(self, finder, build_isolation): + # Prepare for building. We need to: + # 1. Load pyproject.toml (if it exists) + # 2. Set up the build environment + + self.req.load_pyproject_toml() + should_isolate = self.req.use_pep517 and build_isolation + + if should_isolate: + # Isolate in a BuildEnvironment and install the build-time + # requirements. + self.req.build_env = BuildEnvironment() + self.req.build_env.install_requirements( + finder, self.req.pyproject_requires, + "Installing build dependencies" + ) + missing = [] + if self.req.requirements_to_check: + check = self.req.requirements_to_check + missing = self.req.build_env.missing_requirements(check) + if missing: + logger.warning( + "Missing build requirements in pyproject.toml for %s.", + self.req, + ) + logger.warning( + "The project does not specify a build backend, and pip " + "cannot fall back to setuptools without %s.", + " and ".join(map(repr, sorted(missing))) + ) + + self.req.run_egg_info() + self.req.assert_source_matches_version() + + +class Installed(DistAbstraction): + + def dist(self, finder): + return self.req.satisfied_by + + def prep_for_dist(self, finder, build_isolation): + pass + + +class RequirementPreparer(object): + """Prepares a Requirement + """ + + def __init__(self, build_dir, download_dir, src_dir, wheel_download_dir, + progress_bar, build_isolation, req_tracker): + super(RequirementPreparer, self).__init__() + + self.src_dir = src_dir + self.build_dir = build_dir + self.req_tracker = req_tracker + + # Where still packed archives should be written to. If None, they are + # not saved, and are deleted immediately after unpacking. + self.download_dir = download_dir + + # Where still-packed .whl files should be written to. If None, they are + # written to the download_dir parameter. Separate to download_dir to + # permit only keeping wheel archives for pip wheel. + if wheel_download_dir: + wheel_download_dir = normalize_path(wheel_download_dir) + self.wheel_download_dir = wheel_download_dir + + # NOTE + # download_dir and wheel_download_dir overlap semantically and may + # be combined if we're willing to have non-wheel archives present in + # the wheelhouse output by 'pip wheel'. + + self.progress_bar = progress_bar + + # Is build isolation allowed? + self.build_isolation = build_isolation + + @property + def _download_should_save(self): + # TODO: Modify to reduce indentation needed + if self.download_dir: + self.download_dir = expanduser(self.download_dir) + if os.path.exists(self.download_dir): + return True + else: + logger.critical('Could not find download directory') + raise InstallationError( + "Could not find or access download directory '%s'" + % display_path(self.download_dir)) + return False + + def prepare_linked_requirement(self, req, session, finder, + upgrade_allowed, require_hashes): + """Prepare a requirement that would be obtained from req.link + """ + # TODO: Breakup into smaller functions + if req.link and req.link.scheme == 'file': + path = url_to_path(req.link.url) + logger.info('Processing %s', display_path(path)) + else: + logger.info('Collecting %s', req) + + with indent_log(): + # @@ if filesystem packages are not marked + # editable in a req, a non deterministic error + # occurs when the script attempts to unpack the + # build directory + req.ensure_has_source_dir(self.build_dir) + # If a checkout exists, it's unwise to keep going. version + # inconsistencies are logged later, but do not fail the + # installation. + # FIXME: this won't upgrade when there's an existing + # package unpacked in `req.source_dir` + # package unpacked in `req.source_dir` + if os.path.exists(os.path.join(req.source_dir, 'setup.py')): + raise PreviousBuildDirError( + "pip can't proceed with requirements '%s' due to a" + " pre-existing build directory (%s). This is " + "likely due to a previous installation that failed" + ". pip is being responsible and not assuming it " + "can delete this. Please delete it and try again." + % (req, req.source_dir) + ) + req.populate_link(finder, upgrade_allowed, require_hashes) + + # We can't hit this spot and have populate_link return None. + # req.satisfied_by is None here (because we're + # guarded) and upgrade has no impact except when satisfied_by + # is not None. + # Then inside find_requirement existing_applicable -> False + # If no new versions are found, DistributionNotFound is raised, + # otherwise a result is guaranteed. + assert req.link + link = req.link + + # Now that we have the real link, we can tell what kind of + # requirements we have and raise some more informative errors + # than otherwise. (For example, we can raise VcsHashUnsupported + # for a VCS URL rather than HashMissing.) + if require_hashes: + # We could check these first 2 conditions inside + # unpack_url and save repetition of conditions, but then + # we would report less-useful error messages for + # unhashable requirements, complaining that there's no + # hash provided. + if is_vcs_url(link): + raise VcsHashUnsupported() + elif is_file_url(link) and is_dir_url(link): + raise DirectoryUrlHashUnsupported() + if not req.original_link and not req.is_pinned: + # Unpinned packages are asking for trouble when a new + # version is uploaded. This isn't a security check, but + # it saves users a surprising hash mismatch in the + # future. + # + # file:/// URLs aren't pinnable, so don't complain + # about them not being pinned. + raise HashUnpinned() + + hashes = req.hashes(trust_internet=not require_hashes) + if require_hashes and not hashes: + # Known-good hashes are missing for this requirement, so + # shim it with a facade object that will provoke hash + # computation and then raise a HashMissing exception + # showing the user what the hash should be. + hashes = MissingHashes() + + try: + download_dir = self.download_dir + # We always delete unpacked sdists after pip ran. + autodelete_unpacked = True + if req.link.is_wheel and self.wheel_download_dir: + # when doing 'pip wheel` we download wheels to a + # dedicated dir. + download_dir = self.wheel_download_dir + if req.link.is_wheel: + if download_dir: + # When downloading, we only unpack wheels to get + # metadata. + autodelete_unpacked = True + else: + # When installing a wheel, we use the unpacked + # wheel. + autodelete_unpacked = False + unpack_url( + req.link, req.source_dir, + download_dir, autodelete_unpacked, + session=session, hashes=hashes, + progress_bar=self.progress_bar + ) + except requests.HTTPError as exc: + logger.critical( + 'Could not install requirement %s because of error %s', + req, + exc, + ) + raise InstallationError( + 'Could not install requirement %s because of HTTP ' + 'error %s for URL %s' % + (req, exc, req.link) + ) + abstract_dist = make_abstract_dist(req) + with self.req_tracker.track(req): + abstract_dist.prep_for_dist(finder, self.build_isolation) + if self._download_should_save: + # Make a .zip of the source_dir we already created. + if req.link.scheme in vcs.all_schemes: + req.archive(self.download_dir) + return abstract_dist + + def prepare_editable_requirement(self, req, require_hashes, use_user_site, + finder): + """Prepare an editable requirement + """ + assert req.editable, "cannot prepare a non-editable req as editable" + + logger.info('Obtaining %s', req) + + with indent_log(): + if require_hashes: + raise InstallationError( + 'The editable requirement %s cannot be installed when ' + 'requiring hashes, because there is no single file to ' + 'hash.' % req + ) + req.ensure_has_source_dir(self.src_dir) + req.update_editable(not self._download_should_save) + + abstract_dist = make_abstract_dist(req) + with self.req_tracker.track(req): + abstract_dist.prep_for_dist(finder, self.build_isolation) + + if self._download_should_save: + req.archive(self.download_dir) + req.check_if_exists(use_user_site) + + return abstract_dist + + def prepare_installed_requirement(self, req, require_hashes, skip_reason): + """Prepare an already-installed requirement + """ + assert req.satisfied_by, "req should have been satisfied but isn't" + assert skip_reason is not None, ( + "did not get skip reason skipped but req.satisfied_by " + "is set to %r" % (req.satisfied_by,) + ) + logger.info( + 'Requirement %s: %s (%s)', + skip_reason, req, req.satisfied_by.version + ) + with indent_log(): + if require_hashes: + logger.debug( + 'Since it is already installed, we are trusting this ' + 'package without checking its hash. To ensure a ' + 'completely repeatable environment, install into an ' + 'empty virtualenv.' + ) + abstract_dist = Installed(req) + + return abstract_dist diff --git a/venv/lib/python3.7/site-packages/pip/_internal/pep425tags.py b/venv/lib/python3.7/site-packages/pip/_internal/pep425tags.py new file mode 100644 index 0000000..ab1a029 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/pep425tags.py @@ -0,0 +1,317 @@ +"""Generate and work with PEP 425 Compatibility Tags.""" +from __future__ import absolute_import + +import distutils.util +import logging +import platform +import re +import sys +import sysconfig +import warnings +from collections import OrderedDict + +import pip._internal.utils.glibc +from pip._internal.utils.compat import get_extension_suffixes + +logger = logging.getLogger(__name__) + +_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') + + +def get_config_var(var): + try: + return sysconfig.get_config_var(var) + except IOError as e: # Issue #1074 + warnings.warn("{}".format(e), RuntimeWarning) + return None + + +def get_abbr_impl(): + """Return abbreviated implementation name.""" + if hasattr(sys, 'pypy_version_info'): + pyimpl = 'pp' + elif sys.platform.startswith('java'): + pyimpl = 'jy' + elif sys.platform == 'cli': + pyimpl = 'ip' + else: + pyimpl = 'cp' + return pyimpl + + +def get_impl_ver(): + """Return implementation version.""" + impl_ver = get_config_var("py_version_nodot") + if not impl_ver or get_abbr_impl() == 'pp': + impl_ver = ''.join(map(str, get_impl_version_info())) + return impl_ver + + +def get_impl_version_info(): + """Return sys.version_info-like tuple for use in decrementing the minor + version.""" + if get_abbr_impl() == 'pp': + # as per https://github.com/pypa/pip/issues/2882 + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return sys.version_info[0], sys.version_info[1] + + +def get_impl_tag(): + """ + Returns the Tag for this specific implementation. + """ + return "{}{}".format(get_abbr_impl(), get_impl_ver()) + + +def get_flag(var, fallback, expected=True, warn=True): + """Use a fallback method for determining SOABI flags if the needed config + var is unset or unavailable.""" + val = get_config_var(var) + if val is None: + if warn: + logger.debug("Config variable '%s' is unset, Python ABI tag may " + "be incorrect", var) + return fallback() + return val == expected + + +def get_abi_tag(): + """Return the ABI tag based on SOABI (if available) or emulate SOABI + (CPython 2, PyPy).""" + soabi = get_config_var('SOABI') + impl = get_abbr_impl() + if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): + d = '' + m = '' + u = '' + if get_flag('Py_DEBUG', + lambda: hasattr(sys, 'gettotalrefcount'), + warn=(impl == 'cp')): + d = 'd' + if get_flag('WITH_PYMALLOC', + lambda: impl == 'cp', + warn=(impl == 'cp')): + m = 'm' + if get_flag('Py_UNICODE_SIZE', + lambda: sys.maxunicode == 0x10ffff, + expected=4, + warn=(impl == 'cp' and + sys.version_info < (3, 3))) \ + and sys.version_info < (3, 3): + u = 'u' + abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) + elif soabi and soabi.startswith('cpython-'): + abi = 'cp' + soabi.split('-')[1] + elif soabi: + abi = soabi.replace('.', '_').replace('-', '_') + else: + abi = None + return abi + + +def _is_running_32bit(): + return sys.maxsize == 2147483647 + + +def get_platform(): + """Return our platform name 'win32', 'linux_x86_64'""" + if sys.platform == 'darwin': + # distutils.util.get_platform() returns the release based on the value + # of MACOSX_DEPLOYMENT_TARGET on which Python was built, which may + # be significantly older than the user's current machine. + release, _, machine = platform.mac_ver() + split_ver = release.split('.') + + if machine == "x86_64" and _is_running_32bit(): + machine = "i386" + elif machine == "ppc64" and _is_running_32bit(): + machine = "ppc" + + return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) + + # XXX remove distutils dependency + result = distutils.util.get_platform().replace('.', '_').replace('-', '_') + if result == "linux_x86_64" and _is_running_32bit(): + # 32 bit Python program (running on a 64 bit Linux): pip should only + # install and run 32 bit compiled extensions in that case. + result = "linux_i686" + + return result + + +def is_manylinux1_compatible(): + # Only Linux, and only x86-64 / i686 + if get_platform() not in {"linux_x86_64", "linux_i686"}: + return False + + # Check for presence of _manylinux module + try: + import _manylinux + return bool(_manylinux.manylinux1_compatible) + except (ImportError, AttributeError): + # Fall through to heuristic check below + pass + + # Check glibc version. CentOS 5 uses glibc 2.5. + return pip._internal.utils.glibc.have_compatible_glibc(2, 5) + + +def get_darwin_arches(major, minor, machine): + """Return a list of supported arches (including group arches) for + the given major, minor and machine architecture of an macOS machine. + """ + arches = [] + + def _supports_arch(major, minor, arch): + # Looking at the application support for macOS versions in the chart + # provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears + # our timeline looks roughly like: + # + # 10.0 - Introduces ppc support. + # 10.4 - Introduces ppc64, i386, and x86_64 support, however the ppc64 + # and x86_64 support is CLI only, and cannot be used for GUI + # applications. + # 10.5 - Extends ppc64 and x86_64 support to cover GUI applications. + # 10.6 - Drops support for ppc64 + # 10.7 - Drops support for ppc + # + # Given that we do not know if we're installing a CLI or a GUI + # application, we must be conservative and assume it might be a GUI + # application and behave as if ppc64 and x86_64 support did not occur + # until 10.5. + # + # Note: The above information is taken from the "Application support" + # column in the chart not the "Processor support" since I believe + # that we care about what instruction sets an application can use + # not which processors the OS supports. + if arch == 'ppc': + return (major, minor) <= (10, 5) + if arch == 'ppc64': + return (major, minor) == (10, 5) + if arch == 'i386': + return (major, minor) >= (10, 4) + if arch == 'x86_64': + return (major, minor) >= (10, 5) + if arch in groups: + for garch in groups[arch]: + if _supports_arch(major, minor, garch): + return True + return False + + groups = OrderedDict([ + ("fat", ("i386", "ppc")), + ("intel", ("x86_64", "i386")), + ("fat64", ("x86_64", "ppc64")), + ("fat32", ("x86_64", "i386", "ppc")), + ]) + + if _supports_arch(major, minor, machine): + arches.append(machine) + + for garch in groups: + if machine in groups[garch] and _supports_arch(major, minor, garch): + arches.append(garch) + + arches.append('universal') + + return arches + + +def get_supported(versions=None, noarch=False, platform=None, + impl=None, abi=None): + """Return a list of supported tags for each version specified in + `versions`. + + :param versions: a list of string versions, of the form ["33", "32"], + or None. The first version will be assumed to support our ABI. + :param platform: specify the exact platform you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abi: specify the exact abi you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported = [] + + # Versions must be given with respect to the preference + if versions is None: + versions = [] + version_info = get_impl_version_info() + major = version_info[:-1] + # Support all previous minor Python versions. + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = impl or get_abbr_impl() + + abis = [] + + abi = abi or get_abi_tag() + if abi: + abis[0:0] = [abi] + + abi3s = set() + for suffix in get_extension_suffixes(): + if suffix.startswith('.abi'): + abi3s.add(suffix.split('.', 2)[1]) + + abis.extend(sorted(list(abi3s))) + + abis.append('none') + + if not noarch: + arch = platform or get_platform() + if arch.startswith('macosx'): + # support macosx-10.6-intel on macosx-10.9-x86_64 + match = _osx_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + tpl = '{}_{}_%i_%s'.format(name, major) + arches = [] + for m in reversed(range(int(minor) + 1)): + for a in get_darwin_arches(int(major), m, actual_arch): + arches.append(tpl % (m, a)) + else: + # arch pattern didn't match (?!) + arches = [arch] + elif platform is None and is_manylinux1_compatible(): + arches = [arch.replace('linux', 'manylinux1'), arch] + else: + arches = [arch] + + # Current version, current API (built specifically for our Python): + for abi in abis: + for arch in arches: + supported.append(('%s%s' % (impl, versions[0]), abi, arch)) + + # abi3 modules compatible with older version of Python + for version in versions[1:]: + # abi3 was introduced in Python 3.2 + if version in {'31', '30'}: + break + for abi in abi3s: # empty set if not Python 3 + for arch in arches: + supported.append(("%s%s" % (impl, version), abi, arch)) + + # Has binaries, does not use the Python API: + for arch in arches: + supported.append(('py%s' % (versions[0][0]), 'none', arch)) + + # No abi / arch, but requires our implementation: + supported.append(('%s%s' % (impl, versions[0]), 'none', 'any')) + # Tagged specifically as being cross-version compatible + # (with just the major version specified) + supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + # No abi / arch, generic Python + for i, version in enumerate(versions): + supported.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + supported.append(('py%s' % (version[0]), 'none', 'any')) + + return supported + + +implementation_tag = get_impl_tag() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/pyproject.py b/venv/lib/python3.7/site-packages/pip/_internal/pyproject.py new file mode 100644 index 0000000..f938a76 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/pyproject.py @@ -0,0 +1,144 @@ +from __future__ import absolute_import + +import io +import os + +from pip._vendor import pytoml, six + +from pip._internal.exceptions import InstallationError + + +def _is_list_of_str(obj): + return ( + isinstance(obj, list) and + all(isinstance(item, six.string_types) for item in obj) + ) + + +def load_pyproject_toml(use_pep517, pyproject_toml, setup_py, req_name): + """Load the pyproject.toml file. + + Parameters: + use_pep517 - Has the user requested PEP 517 processing? None + means the user hasn't explicitly specified. + pyproject_toml - Location of the project's pyproject.toml file + setup_py - Location of the project's setup.py file + req_name - The name of the requirement we're processing (for + error reporting) + + Returns: + None if we should use the legacy code path, otherwise a tuple + ( + requirements from pyproject.toml, + name of PEP 517 backend, + requirements we should check are installed after setting + up the build environment + ) + """ + has_pyproject = os.path.isfile(pyproject_toml) + has_setup = os.path.isfile(setup_py) + + if has_pyproject: + with io.open(pyproject_toml, encoding="utf-8") as f: + pp_toml = pytoml.load(f) + build_system = pp_toml.get("build-system") + else: + build_system = None + + # The following cases must use PEP 517 + # We check for use_pep517 equalling False because that + # means the user explicitly requested --no-use-pep517 + if has_pyproject and not has_setup: + if use_pep517 is False: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project does not have a setup.py" + ) + use_pep517 = True + elif build_system and "build-backend" in build_system: + if use_pep517 is False: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project specifies a build backend of {} " + "in pyproject.toml".format( + build_system["build-backend"] + ) + ) + use_pep517 = True + + # If we haven't worked out whether to use PEP 517 yet, + # and the user hasn't explicitly stated a preference, + # we do so if the project has a pyproject.toml file. + elif use_pep517 is None: + use_pep517 = has_pyproject + + # At this point, we know whether we're going to use PEP 517. + assert use_pep517 is not None + + # If we're using the legacy code path, there is nothing further + # for us to do here. + if not use_pep517: + return None + + if build_system is None: + # Either the user has a pyproject.toml with no build-system + # section, or the user has no pyproject.toml, but has opted in + # explicitly via --use-pep517. + # In the absence of any explicit backend specification, we + # assume the setuptools backend, and require wheel and a version + # of setuptools that supports that backend. + build_system = { + "requires": ["setuptools>=38.2.5", "wheel"], + "build-backend": "setuptools.build_meta", + } + + # If we're using PEP 517, we have build system information (either + # from pyproject.toml, or defaulted by the code above). + # Note that at this point, we do not know if the user has actually + # specified a backend, though. + assert build_system is not None + + # Ensure that the build-system section in pyproject.toml conforms + # to PEP 518. + error_template = ( + "{package} has a pyproject.toml file that does not comply " + "with PEP 518: {reason}" + ) + + # Specifying the build-system table but not the requires key is invalid + if "requires" not in build_system: + raise InstallationError( + error_template.format(package=req_name, reason=( + "it has a 'build-system' table but not " + "'build-system.requires' which is mandatory in the table" + )) + ) + + # Error out if requires is not a list of strings + requires = build_system["requires"] + if not _is_list_of_str(requires): + raise InstallationError(error_template.format( + package=req_name, + reason="'build-system.requires' is not a list of strings.", + )) + + backend = build_system.get("build-backend") + check = [] + if backend is None: + # If the user didn't specify a backend, we assume they want to use + # the setuptools backend. But we can't be sure they have included + # a version of setuptools which supplies the backend, or wheel + # (which is neede by the backend) in their requirements. So we + # make a note to check that those requirements are present once + # we have set up the environment. + # TODO: Review this - it's quite a lot of work to check for a very + # specific case. The problem is, that case is potentially quite + # common - projects that adopted PEP 518 early for the ability to + # specify requirements to execute setup.py, but never considered + # needing to mention the build tools themselves. The original PEP + # 518 code had a similar check (but implemented in a different + # way). + backend = "setuptools.build_meta" + check = ["setuptools>=38.2.5", "wheel"] + + return (requires, backend, check) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/req/__init__.py new file mode 100644 index 0000000..b270498 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/__init__.py @@ -0,0 +1,69 @@ +from __future__ import absolute_import + +import logging + +from .req_install import InstallRequirement +from .req_set import RequirementSet +from .req_file import parse_requirements +from pip._internal.utils.logging import indent_log + + +__all__ = [ + "RequirementSet", "InstallRequirement", + "parse_requirements", "install_given_reqs", +] + +logger = logging.getLogger(__name__) + + +def install_given_reqs(to_install, install_options, global_options=(), + *args, **kwargs): + """ + Install everything in the given list. + + (to be called after having downloaded and unpacked the packages) + """ + + if to_install: + logger.info( + 'Installing collected packages: %s', + ', '.join([req.name for req in to_install]), + ) + + with indent_log(): + for requirement in to_install: + if requirement.conflicts_with: + logger.info( + 'Found existing installation: %s', + requirement.conflicts_with, + ) + with indent_log(): + uninstalled_pathset = requirement.uninstall( + auto_confirm=True + ) + try: + requirement.install( + install_options, + global_options, + *args, + **kwargs + ) + except Exception: + should_rollback = ( + requirement.conflicts_with and + not requirement.install_succeeded + ) + # if install did not succeed, rollback previous uninstall + if should_rollback: + uninstalled_pathset.rollback() + raise + else: + should_commit = ( + requirement.conflicts_with and + requirement.install_succeeded + ) + if should_commit: + uninstalled_pathset.commit() + requirement.remove_temporary_source() + + return to_install diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/constructors.py b/venv/lib/python3.7/site-packages/pip/_internal/req/constructors.py new file mode 100644 index 0000000..4c4641d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/constructors.py @@ -0,0 +1,298 @@ +"""Backing implementation for InstallRequirement's various constructors + +The idea here is that these formed a major chunk of InstallRequirement's size +so, moving them and support code dedicated to them outside of that class +helps creates for better understandability for the rest of the code. + +These are meant to be used elsewhere within pip to create instances of +InstallRequirement. +""" + +import logging +import os +import re +import traceback + +from pip._vendor.packaging.markers import Marker +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement +from pip._vendor.packaging.specifiers import Specifier +from pip._vendor.pkg_resources import RequirementParseError, parse_requirements + +from pip._internal.download import ( + is_archive_file, is_url, path_to_url, url_to_path, +) +from pip._internal.exceptions import InstallationError +from pip._internal.models.index import PyPI, TestPyPI +from pip._internal.models.link import Link +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.misc import is_installable_dir +from pip._internal.vcs import vcs +from pip._internal.wheel import Wheel + +__all__ = [ + "install_req_from_editable", "install_req_from_line", + "parse_editable" +] + +logger = logging.getLogger(__name__) +operators = Specifier._operators.keys() + + +def _strip_extras(path): + m = re.match(r'^(.+)(\[[^\]]+\])$', path) + extras = None + if m: + path_no_extras = m.group(1) + extras = m.group(2) + else: + path_no_extras = path + + return path_no_extras, extras + + +def parse_editable(editable_req): + """Parses an editable requirement into: + - a requirement name + - an URL + - extras + - editable options + Accepted requirements: + svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir + .[some_extra] + """ + + url = editable_req + + # If a file path is specified with extras, strip off the extras. + url_no_extras, extras = _strip_extras(url) + + if os.path.isdir(url_no_extras): + if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): + raise InstallationError( + "Directory %r is not installable. File 'setup.py' not found." % + url_no_extras + ) + # Treating it as code that has already been checked out + url_no_extras = path_to_url(url_no_extras) + + if url_no_extras.lower().startswith('file:'): + package_name = Link(url_no_extras).egg_fragment + if extras: + return ( + package_name, + url_no_extras, + Requirement("placeholder" + extras.lower()).extras, + ) + else: + return package_name, url_no_extras, None + + for version_control in vcs: + if url.lower().startswith('%s:' % version_control): + url = '%s+%s' % (version_control, url) + break + + if '+' not in url: + raise InstallationError( + '%s should either be a path to a local project or a VCS url ' + 'beginning with svn+, git+, hg+, or bzr+' % + editable_req + ) + + vc_type = url.split('+', 1)[0].lower() + + if not vcs.get_backend(vc_type): + error_message = 'For --editable=%s only ' % editable_req + \ + ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ + ' is currently supported' + raise InstallationError(error_message) + + package_name = Link(url).egg_fragment + if not package_name: + raise InstallationError( + "Could not detect requirement name for '%s', please specify one " + "with #egg=your_package_name" % editable_req + ) + return package_name, url, None + + +def deduce_helpful_msg(req): + """Returns helpful msg in case requirements file does not exist, + or cannot be parsed. + + :params req: Requirements file path + """ + msg = "" + if os.path.exists(req): + msg = " It does exist." + # Try to parse and check if it is a requirements file. + try: + with open(req, 'r') as fp: + # parse first line only + next(parse_requirements(fp.read())) + msg += " The argument you provided " + \ + "(%s) appears to be a" % (req) + \ + " requirements file. If that is the" + \ + " case, use the '-r' flag to install" + \ + " the packages specified within it." + except RequirementParseError: + logger.debug("Cannot parse '%s' as requirements \ + file" % (req), exc_info=1) + else: + msg += " File '%s' does not exist." % (req) + return msg + + +# ---- The actual constructors follow ---- + + +def install_req_from_editable( + editable_req, comes_from=None, isolated=False, options=None, + wheel_cache=None, constraint=False +): + name, url, extras_override = parse_editable(editable_req) + if url.startswith('file:'): + source_dir = url_to_path(url) + else: + source_dir = None + + if name is not None: + try: + req = Requirement(name) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '%s'" % name) + else: + req = None + return InstallRequirement( + req, comes_from, source_dir=source_dir, + editable=True, + link=Link(url), + constraint=constraint, + isolated=isolated, + options=options if options else {}, + wheel_cache=wheel_cache, + extras=extras_override or (), + ) + + +def install_req_from_line( + name, comes_from=None, isolated=False, options=None, wheel_cache=None, + constraint=False +): + """Creates an InstallRequirement from a name, which might be a + requirement, directory containing 'setup.py', filename, or URL. + """ + if is_url(name): + marker_sep = '; ' + else: + marker_sep = ';' + if marker_sep in name: + name, markers = name.split(marker_sep, 1) + markers = markers.strip() + if not markers: + markers = None + else: + markers = Marker(markers) + else: + markers = None + name = name.strip() + req = None + path = os.path.normpath(os.path.abspath(name)) + link = None + extras = None + + if is_url(name): + link = Link(name) + else: + p, extras = _strip_extras(path) + looks_like_dir = os.path.isdir(p) and ( + os.path.sep in name or + (os.path.altsep is not None and os.path.altsep in name) or + name.startswith('.') + ) + if looks_like_dir: + if not is_installable_dir(p): + raise InstallationError( + "Directory %r is not installable. Neither 'setup.py' " + "nor 'pyproject.toml' found." % name + ) + link = Link(path_to_url(p)) + elif is_archive_file(p): + if not os.path.isfile(p): + logger.warning( + 'Requirement %r looks like a filename, but the ' + 'file does not exist', + name + ) + link = Link(path_to_url(p)) + + # it's a local file, dir, or url + if link: + # Handle relative file URLs + if link.scheme == 'file' and re.search(r'\.\./', link.url): + link = Link( + path_to_url(os.path.normpath(os.path.abspath(link.path)))) + # wheel file + if link.is_wheel: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + req = "%s==%s" % (wheel.name, wheel.version) + else: + # set the req to the egg fragment. when it's not there, this + # will become an 'unnamed' requirement + req = link.egg_fragment + + # a requirement specifier + else: + req = name + + if extras: + extras = Requirement("placeholder" + extras.lower()).extras + else: + extras = () + if req is not None: + try: + req = Requirement(req) + except InvalidRequirement: + if os.path.sep in req: + add_msg = "It looks like a path." + add_msg += deduce_helpful_msg(req) + elif '=' in req and not any(op in req for op in operators): + add_msg = "= is not a valid operator. Did you mean == ?" + else: + add_msg = traceback.format_exc() + raise InstallationError( + "Invalid requirement: '%s'\n%s" % (req, add_msg) + ) + + return InstallRequirement( + req, comes_from, link=link, markers=markers, + isolated=isolated, + options=options if options else {}, + wheel_cache=wheel_cache, + constraint=constraint, + extras=extras, + ) + + +def install_req_from_req( + req, comes_from=None, isolated=False, wheel_cache=None +): + try: + req = Requirement(req) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '%s'" % req) + + domains_not_allowed = [ + PyPI.file_storage_domain, + TestPyPI.file_storage_domain, + ] + if req.url and comes_from.link.netloc in domains_not_allowed: + # Explicitly disallow pypi packages that depend on external urls + raise InstallationError( + "Packages installed from PyPI cannot depend on packages " + "which are not also hosted on PyPI.\n" + "%s depends on %s " % (comes_from.name, req) + ) + + return InstallRequirement( + req, comes_from, isolated=isolated, wheel_cache=wheel_cache + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/req_file.py b/venv/lib/python3.7/site-packages/pip/_internal/req/req_file.py new file mode 100644 index 0000000..e7acf7c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/req_file.py @@ -0,0 +1,340 @@ +""" +Requirements file parsing +""" + +from __future__ import absolute_import + +import optparse +import os +import re +import shlex +import sys + +from pip._vendor.six.moves import filterfalse +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.cli import cmdoptions +from pip._internal.download import get_file_content +from pip._internal.exceptions import RequirementsFileParseError +from pip._internal.req.constructors import ( + install_req_from_editable, install_req_from_line, +) + +__all__ = ['parse_requirements'] + +SCHEME_RE = re.compile(r'^(http|https|file):', re.I) +COMMENT_RE = re.compile(r'(^|\s)+#.*$') + +# Matches environment variable-style values in '${MY_VARIABLE_1}' with the +# variable name consisting of only uppercase letters, digits or the '_' +# (underscore). This follows the POSIX standard defined in IEEE Std 1003.1, +# 2013 Edition. +ENV_VAR_RE = re.compile(r'(?P\$\{(?P[A-Z0-9_]+)\})') + +SUPPORTED_OPTIONS = [ + cmdoptions.constraints, + cmdoptions.editable, + cmdoptions.requirements, + cmdoptions.no_index, + cmdoptions.index_url, + cmdoptions.find_links, + cmdoptions.extra_index_url, + cmdoptions.always_unzip, + cmdoptions.no_binary, + cmdoptions.only_binary, + cmdoptions.pre, + cmdoptions.process_dependency_links, + cmdoptions.trusted_host, + cmdoptions.require_hashes, +] + +# options to be passed to requirements +SUPPORTED_OPTIONS_REQ = [ + cmdoptions.install_options, + cmdoptions.global_options, + cmdoptions.hash, +] + +# the 'dest' string values +SUPPORTED_OPTIONS_REQ_DEST = [o().dest for o in SUPPORTED_OPTIONS_REQ] + + +def parse_requirements(filename, finder=None, comes_from=None, options=None, + session=None, constraint=False, wheel_cache=None): + """Parse a requirements file and yield InstallRequirement instances. + + :param filename: Path or url of requirements file. + :param finder: Instance of pip.index.PackageFinder. + :param comes_from: Origin description of requirements. + :param options: cli options. + :param session: Instance of pip.download.PipSession. + :param constraint: If true, parsing a constraint file rather than + requirements file. + :param wheel_cache: Instance of pip.wheel.WheelCache + """ + if session is None: + raise TypeError( + "parse_requirements() missing 1 required keyword argument: " + "'session'" + ) + + _, content = get_file_content( + filename, comes_from=comes_from, session=session + ) + + lines_enum = preprocess(content, options) + + for line_number, line in lines_enum: + req_iter = process_line(line, filename, line_number, finder, + comes_from, options, session, wheel_cache, + constraint=constraint) + for req in req_iter: + yield req + + +def preprocess(content, options): + """Split, filter, and join lines, and return a line iterator + + :param content: the content of the requirements file + :param options: cli options + """ + lines_enum = enumerate(content.splitlines(), start=1) + lines_enum = join_lines(lines_enum) + lines_enum = ignore_comments(lines_enum) + lines_enum = skip_regex(lines_enum, options) + lines_enum = expand_env_variables(lines_enum) + return lines_enum + + +def process_line(line, filename, line_number, finder=None, comes_from=None, + options=None, session=None, wheel_cache=None, + constraint=False): + """Process a single requirements line; This can result in creating/yielding + requirements, or updating the finder. + + For lines that contain requirements, the only options that have an effect + are from SUPPORTED_OPTIONS_REQ, and they are scoped to the + requirement. Other options from SUPPORTED_OPTIONS may be present, but are + ignored. + + For lines that do not contain requirements, the only options that have an + effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may + be present, but are ignored. These lines may contain multiple options + (although our docs imply only one is supported), and all our parsed and + affect the finder. + + :param constraint: If True, parsing a constraints file. + :param options: OptionParser options that we may update + """ + parser = build_parser(line) + defaults = parser.get_default_values() + defaults.index_url = None + if finder: + # `finder.format_control` will be updated during parsing + defaults.format_control = finder.format_control + args_str, options_str = break_args_options(line) + if sys.version_info < (2, 7, 3): + # Prior to 2.7.3, shlex cannot deal with unicode entries + options_str = options_str.encode('utf8') + opts, _ = parser.parse_args(shlex.split(options_str), defaults) + + # preserve for the nested code path + line_comes_from = '%s %s (line %s)' % ( + '-c' if constraint else '-r', filename, line_number, + ) + + # yield a line requirement + if args_str: + isolated = options.isolated_mode if options else False + if options: + cmdoptions.check_install_build_global(options, opts) + # get the options that apply to requirements + req_options = {} + for dest in SUPPORTED_OPTIONS_REQ_DEST: + if dest in opts.__dict__ and opts.__dict__[dest]: + req_options[dest] = opts.__dict__[dest] + yield install_req_from_line( + args_str, line_comes_from, constraint=constraint, + isolated=isolated, options=req_options, wheel_cache=wheel_cache + ) + + # yield an editable requirement + elif opts.editables: + isolated = options.isolated_mode if options else False + yield install_req_from_editable( + opts.editables[0], comes_from=line_comes_from, + constraint=constraint, isolated=isolated, wheel_cache=wheel_cache + ) + + # parse a nested requirements file + elif opts.requirements or opts.constraints: + if opts.requirements: + req_path = opts.requirements[0] + nested_constraint = False + else: + req_path = opts.constraints[0] + nested_constraint = True + # original file is over http + if SCHEME_RE.search(filename): + # do a url join so relative paths work + req_path = urllib_parse.urljoin(filename, req_path) + # original file and nested file are paths + elif not SCHEME_RE.search(req_path): + # do a join so relative paths work + req_path = os.path.join(os.path.dirname(filename), req_path) + # TODO: Why not use `comes_from='-r {} (line {})'` here as well? + parser = parse_requirements( + req_path, finder, comes_from, options, session, + constraint=nested_constraint, wheel_cache=wheel_cache + ) + for req in parser: + yield req + + # percolate hash-checking option upward + elif opts.require_hashes: + options.require_hashes = opts.require_hashes + + # set finder options + elif finder: + if opts.index_url: + finder.index_urls = [opts.index_url] + if opts.no_index is True: + finder.index_urls = [] + if opts.extra_index_urls: + finder.index_urls.extend(opts.extra_index_urls) + if opts.find_links: + # FIXME: it would be nice to keep track of the source + # of the find_links: support a find-links local path + # relative to a requirements file. + value = opts.find_links[0] + req_dir = os.path.dirname(os.path.abspath(filename)) + relative_to_reqs_file = os.path.join(req_dir, value) + if os.path.exists(relative_to_reqs_file): + value = relative_to_reqs_file + finder.find_links.append(value) + if opts.pre: + finder.allow_all_prereleases = True + if opts.process_dependency_links: + finder.process_dependency_links = True + if opts.trusted_hosts: + finder.secure_origins.extend( + ("*", host, "*") for host in opts.trusted_hosts) + + +def break_args_options(line): + """Break up the line into an args and options string. We only want to shlex + (and then optparse) the options, not the args. args can contain markers + which are corrupted by shlex. + """ + tokens = line.split(' ') + args = [] + options = tokens[:] + for token in tokens: + if token.startswith('-') or token.startswith('--'): + break + else: + args.append(token) + options.pop(0) + return ' '.join(args), ' '.join(options) + + +def build_parser(line): + """ + Return a parser for parsing requirement lines + """ + parser = optparse.OptionParser(add_help_option=False) + + option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ + for option_factory in option_factories: + option = option_factory() + parser.add_option(option) + + # By default optparse sys.exits on parsing errors. We want to wrap + # that in our own exception. + def parser_exit(self, msg): + # add offending line + msg = 'Invalid requirement: %s\n%s' % (line, msg) + raise RequirementsFileParseError(msg) + parser.exit = parser_exit + + return parser + + +def join_lines(lines_enum): + """Joins a line ending in '\' with the previous line (except when following + comments). The joined line takes on the index of the first line. + """ + primary_line_number = None + new_line = [] + for line_number, line in lines_enum: + if not line.endswith('\\') or COMMENT_RE.match(line): + if COMMENT_RE.match(line): + # this ensures comments are always matched later + line = ' ' + line + if new_line: + new_line.append(line) + yield primary_line_number, ''.join(new_line) + new_line = [] + else: + yield line_number, line + else: + if not new_line: + primary_line_number = line_number + new_line.append(line.strip('\\')) + + # last line contains \ + if new_line: + yield primary_line_number, ''.join(new_line) + + # TODO: handle space after '\'. + + +def ignore_comments(lines_enum): + """ + Strips comments and filter empty lines. + """ + for line_number, line in lines_enum: + line = COMMENT_RE.sub('', line) + line = line.strip() + if line: + yield line_number, line + + +def skip_regex(lines_enum, options): + """ + Skip lines that match '--skip-requirements-regex' pattern + + Note: the regex pattern is only built once + """ + skip_regex = options.skip_requirements_regex if options else None + if skip_regex: + pattern = re.compile(skip_regex) + lines_enum = filterfalse(lambda e: pattern.search(e[1]), lines_enum) + return lines_enum + + +def expand_env_variables(lines_enum): + """Replace all environment variables that can be retrieved via `os.getenv`. + + The only allowed format for environment variables defined in the + requirement file is `${MY_VARIABLE_1}` to ensure two things: + + 1. Strings that contain a `$` aren't accidentally (partially) expanded. + 2. Ensure consistency across platforms for requirement files. + + These points are the result of a discusssion on the `github pull + request #3514 `_. + + Valid characters in variable names follow the `POSIX standard + `_ and are limited + to uppercase letter, digits and the `_` (underscore). + """ + for line_number, line in lines_enum: + for env_var, var_name in ENV_VAR_RE.findall(line): + value = os.getenv(var_name) + if not value: + continue + + line = line.replace(env_var, value) + + yield line_number, line diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/req_install.py b/venv/lib/python3.7/site-packages/pip/_internal/req/req_install.py new file mode 100644 index 0000000..c2624fe --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/req_install.py @@ -0,0 +1,860 @@ +from __future__ import absolute_import + +import logging +import os +import shutil +import sys +import sysconfig +import zipfile +from distutils.util import change_root + +from pip._vendor import pkg_resources, six +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.pep517.wrappers import Pep517HookCaller + +from pip._internal import wheel +from pip._internal.build_env import NoOpBuildEnvironment +from pip._internal.exceptions import InstallationError +from pip._internal.locations import ( + PIP_DELETE_MARKER_FILENAME, running_under_virtualenv, +) +from pip._internal.models.link import Link +from pip._internal.pyproject import load_pyproject_toml +from pip._internal.req.req_uninstall import UninstallPathSet +from pip._internal.utils.compat import native_str +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + _make_build_dir, ask_path_exists, backup_dir, call_subprocess, + display_path, dist_in_site_packages, dist_in_usersite, ensure_dir, + get_installed_version, rmtree, +) +from pip._internal.utils.packaging import get_metadata +from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.ui import open_spinner +from pip._internal.vcs import vcs +from pip._internal.wheel import move_wheel_files + +logger = logging.getLogger(__name__) + + +class InstallRequirement(object): + """ + Represents something that may be installed later on, may have information + about where to fetch the relavant requirement and also contains logic for + installing the said requirement. + """ + + def __init__(self, req, comes_from, source_dir=None, editable=False, + link=None, update=True, markers=None, + isolated=False, options=None, wheel_cache=None, + constraint=False, extras=()): + assert req is None or isinstance(req, Requirement), req + self.req = req + self.comes_from = comes_from + self.constraint = constraint + if source_dir is not None: + self.source_dir = os.path.normpath(os.path.abspath(source_dir)) + else: + self.source_dir = None + self.editable = editable + + self._wheel_cache = wheel_cache + if link is not None: + self.link = self.original_link = link + else: + self.link = self.original_link = req and req.url and Link(req.url) + + if extras: + self.extras = extras + elif req: + self.extras = { + pkg_resources.safe_extra(extra) for extra in req.extras + } + else: + self.extras = set() + if markers is not None: + self.markers = markers + else: + self.markers = req and req.marker + self._egg_info_path = None + # This holds the pkg_resources.Distribution object if this requirement + # is already available: + self.satisfied_by = None + # This hold the pkg_resources.Distribution object if this requirement + # conflicts with another installed distribution: + self.conflicts_with = None + # Temporary build location + self._temp_build_dir = TempDirectory(kind="req-build") + # Used to store the global directory where the _temp_build_dir should + # have been created. Cf _correct_build_location method. + self._ideal_build_dir = None + # True if the editable should be updated: + self.update = update + # Set to True after successful installation + self.install_succeeded = None + # UninstallPathSet of uninstalled distribution (for possible rollback) + self.uninstalled_pathset = None + self.options = options if options else {} + # Set to True after successful preparation of this requirement + self.prepared = False + self.is_direct = False + + self.isolated = isolated + self.build_env = NoOpBuildEnvironment() + + # The static build requirements (from pyproject.toml) + self.pyproject_requires = None + + # Build requirements that we will check are available + # TODO: We don't do this for --no-build-isolation. Should we? + self.requirements_to_check = [] + + # The PEP 517 backend we should use to build the project + self.pep517_backend = None + + # Are we using PEP 517 for this requirement? + # After pyproject.toml has been loaded, the only valid values are True + # and False. Before loading, None is valid (meaning "use the default"). + # Setting an explicit value before loading pyproject.toml is supported, + # but after loading this flag should be treated as read only. + self.use_pep517 = None + + def __str__(self): + if self.req: + s = str(self.req) + if self.link: + s += ' from %s' % self.link.url + elif self.link: + s = self.link.url + else: + s = '' + if self.satisfied_by is not None: + s += ' in %s' % display_path(self.satisfied_by.location) + if self.comes_from: + if isinstance(self.comes_from, six.string_types): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += ' (from %s)' % comes_from + return s + + def __repr__(self): + return '<%s object: %s editable=%r>' % ( + self.__class__.__name__, str(self), self.editable) + + def populate_link(self, finder, upgrade, require_hashes): + """Ensure that if a link can be found for this, that it is found. + + Note that self.link may still be None - if Upgrade is False and the + requirement is already installed. + + If require_hashes is True, don't use the wheel cache, because cached + wheels, always built locally, have different hashes than the files + downloaded from the index server and thus throw false hash mismatches. + Furthermore, cached wheels at present have undeterministic contents due + to file modification times. + """ + if self.link is None: + self.link = finder.find_requirement(self, upgrade) + if self._wheel_cache is not None and not require_hashes: + old_link = self.link + self.link = self._wheel_cache.get(self.link, self.name) + if old_link != self.link: + logger.debug('Using cached wheel link: %s', self.link) + + # Things that are valid for all kinds of requirements? + @property + def name(self): + if self.req is None: + return None + return native_str(pkg_resources.safe_name(self.req.name)) + + @property + def specifier(self): + return self.req.specifier + + @property + def is_pinned(self): + """Return whether I am pinned to an exact version. + + For example, some-package==1.2 is pinned; some-package>1.2 is not. + """ + specifiers = self.specifier + return (len(specifiers) == 1 and + next(iter(specifiers)).operator in {'==', '==='}) + + @property + def installed_version(self): + return get_installed_version(self.name) + + def match_markers(self, extras_requested=None): + if not extras_requested: + # Provide an extra to safely evaluate the markers + # without matching any extra + extras_requested = ('',) + if self.markers is not None: + return any( + self.markers.evaluate({'extra': extra}) + for extra in extras_requested) + else: + return True + + @property + def has_hash_options(self): + """Return whether any known-good hashes are specified as options. + + These activate --require-hashes mode; hashes specified as part of a + URL do not. + + """ + return bool(self.options.get('hashes', {})) + + def hashes(self, trust_internet=True): + """Return a hash-comparer that considers my option- and URL-based + hashes to be known-good. + + Hashes in URLs--ones embedded in the requirements file, not ones + downloaded from an index server--are almost peers with ones from + flags. They satisfy --require-hashes (whether it was implicitly or + explicitly activated) but do not activate it. md5 and sha224 are not + allowed in flags, which should nudge people toward good algos. We + always OR all hashes together, even ones from URLs. + + :param trust_internet: Whether to trust URL-based (#md5=...) hashes + downloaded from the internet, as by populate_link() + + """ + good_hashes = self.options.get('hashes', {}).copy() + link = self.link if trust_internet else self.original_link + if link and link.hash: + good_hashes.setdefault(link.hash_name, []).append(link.hash) + return Hashes(good_hashes) + + def from_path(self): + """Format a nice indicator to show where this "comes from" + """ + if self.req is None: + return None + s = str(self.req) + if self.comes_from: + if isinstance(self.comes_from, six.string_types): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += '->' + comes_from + return s + + def build_location(self, build_dir): + assert build_dir is not None + if self._temp_build_dir.path is not None: + return self._temp_build_dir.path + if self.req is None: + # for requirement via a path to a directory: the name of the + # package is not available yet so we create a temp directory + # Once run_egg_info will have run, we'll be able + # to fix it via _correct_build_location + # Some systems have /tmp as a symlink which confuses custom + # builds (such as numpy). Thus, we ensure that the real path + # is returned. + self._temp_build_dir.create() + self._ideal_build_dir = build_dir + + return self._temp_build_dir.path + if self.editable: + name = self.name.lower() + else: + name = self.name + # FIXME: Is there a better place to create the build_dir? (hg and bzr + # need this) + if not os.path.exists(build_dir): + logger.debug('Creating directory %s', build_dir) + _make_build_dir(build_dir) + return os.path.join(build_dir, name) + + def _correct_build_location(self): + """Move self._temp_build_dir to self._ideal_build_dir/self.req.name + + For some requirements (e.g. a path to a directory), the name of the + package is not available until we run egg_info, so the build_location + will return a temporary directory and store the _ideal_build_dir. + + This is only called by self.run_egg_info to fix the temporary build + directory. + """ + if self.source_dir is not None: + return + assert self.req is not None + assert self._temp_build_dir.path + assert self._ideal_build_dir.path + old_location = self._temp_build_dir.path + self._temp_build_dir.path = None + + new_location = self.build_location(self._ideal_build_dir) + if os.path.exists(new_location): + raise InstallationError( + 'A package already exists in %s; please remove it to continue' + % display_path(new_location)) + logger.debug( + 'Moving package %s from %s to new location %s', + self, display_path(old_location), display_path(new_location), + ) + shutil.move(old_location, new_location) + self._temp_build_dir.path = new_location + self._ideal_build_dir = None + self.source_dir = os.path.normpath(os.path.abspath(new_location)) + self._egg_info_path = None + + def remove_temporary_source(self): + """Remove the source files from this requirement, if they are marked + for deletion""" + if self.source_dir and os.path.exists( + os.path.join(self.source_dir, PIP_DELETE_MARKER_FILENAME)): + logger.debug('Removing source in %s', self.source_dir) + rmtree(self.source_dir) + self.source_dir = None + self._temp_build_dir.cleanup() + self.build_env.cleanup() + + def check_if_exists(self, use_user_site): + """Find an installed distribution that satisfies or conflicts + with this requirement, and set self.satisfied_by or + self.conflicts_with appropriately. + """ + if self.req is None: + return False + try: + # get_distribution() will resolve the entire list of requirements + # anyway, and we've already determined that we need the requirement + # in question, so strip the marker so that we don't try to + # evaluate it. + no_marker = Requirement(str(self.req)) + no_marker.marker = None + self.satisfied_by = pkg_resources.get_distribution(str(no_marker)) + if self.editable and self.satisfied_by: + self.conflicts_with = self.satisfied_by + # when installing editables, nothing pre-existing should ever + # satisfy + self.satisfied_by = None + return True + except pkg_resources.DistributionNotFound: + return False + except pkg_resources.VersionConflict: + existing_dist = pkg_resources.get_distribution( + self.req.name + ) + if use_user_site: + if dist_in_usersite(existing_dist): + self.conflicts_with = existing_dist + elif (running_under_virtualenv() and + dist_in_site_packages(existing_dist)): + raise InstallationError( + "Will not install to the user site because it will " + "lack sys.path precedence to %s in %s" % + (existing_dist.project_name, existing_dist.location) + ) + else: + self.conflicts_with = existing_dist + return True + + # Things valid for wheels + @property + def is_wheel(self): + return self.link and self.link.is_wheel + + def move_wheel_files(self, wheeldir, root=None, home=None, prefix=None, + warn_script_location=True, use_user_site=False, + pycompile=True): + move_wheel_files( + self.name, self.req, wheeldir, + user=use_user_site, + home=home, + root=root, + prefix=prefix, + pycompile=pycompile, + isolated=self.isolated, + warn_script_location=warn_script_location, + ) + + # Things valid for sdists + @property + def setup_py_dir(self): + return os.path.join( + self.source_dir, + self.link and self.link.subdirectory_fragment or '') + + @property + def setup_py(self): + assert self.source_dir, "No source dir for %s" % self + + setup_py = os.path.join(self.setup_py_dir, 'setup.py') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(setup_py, six.text_type): + setup_py = setup_py.encode(sys.getfilesystemencoding()) + + return setup_py + + @property + def pyproject_toml(self): + assert self.source_dir, "No source dir for %s" % self + + pp_toml = os.path.join(self.setup_py_dir, 'pyproject.toml') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(pp_toml, six.text_type): + pp_toml = pp_toml.encode(sys.getfilesystemencoding()) + + return pp_toml + + def load_pyproject_toml(self): + """Load the pyproject.toml file. + + After calling this routine, all of the attributes related to PEP 517 + processing for this requirement have been set. In particular, the + use_pep517 attribute can be used to determine whether we should + follow the PEP 517 or legacy (setup.py) code path. + """ + pep517_data = load_pyproject_toml( + self.use_pep517, + self.pyproject_toml, + self.setup_py, + str(self) + ) + + if pep517_data is None: + self.use_pep517 = False + else: + self.use_pep517 = True + requires, backend, check = pep517_data + self.requirements_to_check = check + self.pyproject_requires = requires + self.pep517_backend = Pep517HookCaller(self.setup_py_dir, backend) + + def run_egg_info(self): + assert self.source_dir + if self.name: + logger.debug( + 'Running setup.py (path:%s) egg_info for package %s', + self.setup_py, self.name, + ) + else: + logger.debug( + 'Running setup.py (path:%s) egg_info for package from %s', + self.setup_py, self.link, + ) + + with indent_log(): + script = SETUPTOOLS_SHIM % self.setup_py + base_cmd = [sys.executable, '-c', script] + if self.isolated: + base_cmd += ["--no-user-cfg"] + egg_info_cmd = base_cmd + ['egg_info'] + # We can't put the .egg-info files at the root, because then the + # source code will be mistaken for an installed egg, causing + # problems + if self.editable: + egg_base_option = [] + else: + egg_info_dir = os.path.join(self.setup_py_dir, 'pip-egg-info') + ensure_dir(egg_info_dir) + egg_base_option = ['--egg-base', 'pip-egg-info'] + with self.build_env: + call_subprocess( + egg_info_cmd + egg_base_option, + cwd=self.setup_py_dir, + show_stdout=False, + command_desc='python setup.py egg_info') + + if not self.req: + if isinstance(parse_version(self.metadata["Version"]), Version): + op = "==" + else: + op = "===" + self.req = Requirement( + "".join([ + self.metadata["Name"], + op, + self.metadata["Version"], + ]) + ) + self._correct_build_location() + else: + metadata_name = canonicalize_name(self.metadata["Name"]) + if canonicalize_name(self.req.name) != metadata_name: + logger.warning( + 'Running setup.py (path:%s) egg_info for package %s ' + 'produced metadata for project name %s. Fix your ' + '#egg=%s fragments.', + self.setup_py, self.name, metadata_name, self.name + ) + self.req = Requirement(metadata_name) + + @property + def egg_info_path(self): + if self._egg_info_path is None: + if self.editable: + base = self.source_dir + else: + base = os.path.join(self.setup_py_dir, 'pip-egg-info') + filenames = os.listdir(base) + if self.editable: + filenames = [] + for root, dirs, files in os.walk(base): + for dir in vcs.dirnames: + if dir in dirs: + dirs.remove(dir) + # Iterate over a copy of ``dirs``, since mutating + # a list while iterating over it can cause trouble. + # (See https://github.com/pypa/pip/pull/462.) + for dir in list(dirs): + # Don't search in anything that looks like a virtualenv + # environment + if ( + os.path.lexists( + os.path.join(root, dir, 'bin', 'python') + ) or + os.path.exists( + os.path.join( + root, dir, 'Scripts', 'Python.exe' + ) + )): + dirs.remove(dir) + # Also don't search through tests + elif dir == 'test' or dir == 'tests': + dirs.remove(dir) + filenames.extend([os.path.join(root, dir) + for dir in dirs]) + filenames = [f for f in filenames if f.endswith('.egg-info')] + + if not filenames: + raise InstallationError( + "Files/directories not found in %s" % base + ) + # if we have more than one match, we pick the toplevel one. This + # can easily be the case if there is a dist folder which contains + # an extracted tarball for testing purposes. + if len(filenames) > 1: + filenames.sort( + key=lambda x: x.count(os.path.sep) + + (os.path.altsep and x.count(os.path.altsep) or 0) + ) + self._egg_info_path = os.path.join(base, filenames[0]) + return self._egg_info_path + + @property + def metadata(self): + if not hasattr(self, '_metadata'): + self._metadata = get_metadata(self.get_dist()) + + return self._metadata + + def get_dist(self): + """Return a pkg_resources.Distribution built from self.egg_info_path""" + egg_info = self.egg_info_path.rstrip(os.path.sep) + base_dir = os.path.dirname(egg_info) + metadata = pkg_resources.PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + return pkg_resources.Distribution( + os.path.dirname(egg_info), + project_name=dist_name, + metadata=metadata, + ) + + def assert_source_matches_version(self): + assert self.source_dir + version = self.metadata['version'] + if self.req.specifier and version not in self.req.specifier: + logger.warning( + 'Requested %s, but installing version %s', + self, + version, + ) + else: + logger.debug( + 'Source in %s has version %s, which satisfies requirement %s', + display_path(self.source_dir), + version, + self, + ) + + # For both source distributions and editables + def ensure_has_source_dir(self, parent_dir): + """Ensure that a source_dir is set. + + This will create a temporary build dir if the name of the requirement + isn't known yet. + + :param parent_dir: The ideal pip parent_dir for the source_dir. + Generally src_dir for editables and build_dir for sdists. + :return: self.source_dir + """ + if self.source_dir is None: + self.source_dir = self.build_location(parent_dir) + return self.source_dir + + # For editable installations + def install_editable(self, install_options, + global_options=(), prefix=None): + logger.info('Running setup.py develop for %s', self.name) + + if self.isolated: + global_options = list(global_options) + ["--no-user-cfg"] + + if prefix: + prefix_param = ['--prefix={}'.format(prefix)] + install_options = list(install_options) + prefix_param + + with indent_log(): + # FIXME: should we do --install-headers here too? + with self.build_env: + call_subprocess( + [ + sys.executable, + '-c', + SETUPTOOLS_SHIM % self.setup_py + ] + + list(global_options) + + ['develop', '--no-deps'] + + list(install_options), + + cwd=self.setup_py_dir, + show_stdout=False, + ) + + self.install_succeeded = True + + def update_editable(self, obtain=True): + if not self.link: + logger.debug( + "Cannot update repository at %s; repository location is " + "unknown", + self.source_dir, + ) + return + assert self.editable + assert self.source_dir + if self.link.scheme == 'file': + # Static paths don't get updated + return + assert '+' in self.link.url, "bad url: %r" % self.link.url + if not self.update: + return + vc_type, url = self.link.url.split('+', 1) + backend = vcs.get_backend(vc_type) + if backend: + vcs_backend = backend(self.link.url) + if obtain: + vcs_backend.obtain(self.source_dir) + else: + vcs_backend.export(self.source_dir) + else: + assert 0, ( + 'Unexpected version control type (in %s): %s' + % (self.link, vc_type)) + + # Top-level Actions + def uninstall(self, auto_confirm=False, verbose=False, + use_user_site=False): + """ + Uninstall the distribution currently satisfying this requirement. + + Prompts before removing or modifying files unless + ``auto_confirm`` is True. + + Refuses to delete or modify files outside of ``sys.prefix`` - + thus uninstallation within a virtual environment can only + modify that virtual environment, even if the virtualenv is + linked to global site-packages. + + """ + if not self.check_if_exists(use_user_site): + logger.warning("Skipping %s as it is not installed.", self.name) + return + dist = self.satisfied_by or self.conflicts_with + + uninstalled_pathset = UninstallPathSet.from_dist(dist) + uninstalled_pathset.remove(auto_confirm, verbose) + return uninstalled_pathset + + def _clean_zip_name(self, name, prefix): # only used by archive. + assert name.startswith(prefix + os.path.sep), ( + "name %r doesn't start with prefix %r" % (name, prefix) + ) + name = name[len(prefix) + 1:] + name = name.replace(os.path.sep, '/') + return name + + # TODO: Investigate if this should be kept in InstallRequirement + # Seems to be used only when VCS + downloads + def archive(self, build_dir): + assert self.source_dir + create_archive = True + archive_name = '%s-%s.zip' % (self.name, self.metadata["version"]) + archive_path = os.path.join(build_dir, archive_name) + if os.path.exists(archive_path): + response = ask_path_exists( + 'The file %s exists. (i)gnore, (w)ipe, (b)ackup, (a)bort ' % + display_path(archive_path), ('i', 'w', 'b', 'a')) + if response == 'i': + create_archive = False + elif response == 'w': + logger.warning('Deleting %s', display_path(archive_path)) + os.remove(archive_path) + elif response == 'b': + dest_file = backup_dir(archive_path) + logger.warning( + 'Backing up %s to %s', + display_path(archive_path), + display_path(dest_file), + ) + shutil.move(archive_path, dest_file) + elif response == 'a': + sys.exit(-1) + if create_archive: + zip = zipfile.ZipFile( + archive_path, 'w', zipfile.ZIP_DEFLATED, + allowZip64=True + ) + dir = os.path.normcase(os.path.abspath(self.setup_py_dir)) + for dirpath, dirnames, filenames in os.walk(dir): + if 'pip-egg-info' in dirnames: + dirnames.remove('pip-egg-info') + for dirname in dirnames: + dirname = os.path.join(dirpath, dirname) + name = self._clean_zip_name(dirname, dir) + zipdir = zipfile.ZipInfo(self.name + '/' + name + '/') + zipdir.external_attr = 0x1ED << 16 # 0o755 + zip.writestr(zipdir, '') + for filename in filenames: + if filename == PIP_DELETE_MARKER_FILENAME: + continue + filename = os.path.join(dirpath, filename) + name = self._clean_zip_name(filename, dir) + zip.write(filename, self.name + '/' + name) + zip.close() + logger.info('Saved %s', display_path(archive_path)) + + def install(self, install_options, global_options=None, root=None, + home=None, prefix=None, warn_script_location=True, + use_user_site=False, pycompile=True): + global_options = global_options if global_options is not None else [] + if self.editable: + self.install_editable( + install_options, global_options, prefix=prefix, + ) + return + if self.is_wheel: + version = wheel.wheel_version(self.source_dir) + wheel.check_compatibility(version, self.name) + + self.move_wheel_files( + self.source_dir, root=root, prefix=prefix, home=home, + warn_script_location=warn_script_location, + use_user_site=use_user_site, pycompile=pycompile, + ) + self.install_succeeded = True + return + + # Extend the list of global and install options passed on to + # the setup.py call with the ones from the requirements file. + # Options specified in requirements file override those + # specified on the command line, since the last option given + # to setup.py is the one that is used. + global_options = list(global_options) + \ + self.options.get('global_options', []) + install_options = list(install_options) + \ + self.options.get('install_options', []) + + if self.isolated: + global_options = global_options + ["--no-user-cfg"] + + with TempDirectory(kind="record") as temp_dir: + record_filename = os.path.join(temp_dir.path, 'install-record.txt') + install_args = self.get_install_args( + global_options, record_filename, root, prefix, pycompile, + ) + msg = 'Running setup.py install for %s' % (self.name,) + with open_spinner(msg) as spinner: + with indent_log(): + with self.build_env: + call_subprocess( + install_args + install_options, + cwd=self.setup_py_dir, + show_stdout=False, + spinner=spinner, + ) + + if not os.path.exists(record_filename): + logger.debug('Record file %s not found', record_filename) + return + self.install_succeeded = True + + def prepend_root(path): + if root is None or not os.path.isabs(path): + return path + else: + return change_root(root, path) + + with open(record_filename) as f: + for line in f: + directory = os.path.dirname(line) + if directory.endswith('.egg-info'): + egg_info_dir = prepend_root(directory) + break + else: + logger.warning( + 'Could not find .egg-info directory in install record' + ' for %s', + self, + ) + # FIXME: put the record somewhere + # FIXME: should this be an error? + return + new_lines = [] + with open(record_filename) as f: + for line in f: + filename = line.strip() + if os.path.isdir(filename): + filename += os.path.sep + new_lines.append( + os.path.relpath(prepend_root(filename), egg_info_dir) + ) + new_lines.sort() + ensure_dir(egg_info_dir) + inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') + with open(inst_files_path, 'w') as f: + f.write('\n'.join(new_lines) + '\n') + + def get_install_args(self, global_options, record_filename, root, prefix, + pycompile): + install_args = [sys.executable, "-u"] + install_args.append('-c') + install_args.append(SETUPTOOLS_SHIM % self.setup_py) + install_args += list(global_options) + \ + ['install', '--record', record_filename] + install_args += ['--single-version-externally-managed'] + + if root is not None: + install_args += ['--root', root] + if prefix is not None: + install_args += ['--prefix', prefix] + + if pycompile: + install_args += ["--compile"] + else: + install_args += ["--no-compile"] + + if running_under_virtualenv(): + py_ver_str = 'python' + sysconfig.get_python_version() + install_args += ['--install-headers', + os.path.join(sys.prefix, 'include', 'site', + py_ver_str, self.name)] + + return install_args diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/req_set.py b/venv/lib/python3.7/site-packages/pip/_internal/req/req_set.py new file mode 100644 index 0000000..b198317 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/req_set.py @@ -0,0 +1,181 @@ +from __future__ import absolute_import + +import logging +from collections import OrderedDict + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.logging import indent_log +from pip._internal.wheel import Wheel + +logger = logging.getLogger(__name__) + + +class RequirementSet(object): + + def __init__(self, require_hashes=False, check_supported_wheels=True): + """Create a RequirementSet. + """ + + self.requirements = OrderedDict() + self.require_hashes = require_hashes + self.check_supported_wheels = check_supported_wheels + + # Mapping of alias: real_name + self.requirement_aliases = {} + self.unnamed_requirements = [] + self.successfully_downloaded = [] + self.reqs_to_cleanup = [] + + def __str__(self): + reqs = [req for req in self.requirements.values() + if not req.comes_from] + reqs.sort(key=lambda req: req.name.lower()) + return ' '.join([str(req.req) for req in reqs]) + + def __repr__(self): + reqs = [req for req in self.requirements.values()] + reqs.sort(key=lambda req: req.name.lower()) + reqs_str = ', '.join([str(req.req) for req in reqs]) + return ('<%s object; %d requirement(s): %s>' + % (self.__class__.__name__, len(reqs), reqs_str)) + + def add_requirement(self, install_req, parent_req_name=None, + extras_requested=None): + """Add install_req as a requirement to install. + + :param parent_req_name: The name of the requirement that needed this + added. The name is used because when multiple unnamed requirements + resolve to the same name, we could otherwise end up with dependency + links that point outside the Requirements set. parent_req must + already be added. Note that None implies that this is a user + supplied requirement, vs an inferred one. + :param extras_requested: an iterable of extras used to evaluate the + environment markers. + :return: Additional requirements to scan. That is either [] if + the requirement is not applicable, or [install_req] if the + requirement is applicable and has just been added. + """ + name = install_req.name + + # If the markers do not match, ignore this requirement. + if not install_req.match_markers(extras_requested): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + name, install_req.markers, + ) + return [], None + + # If the wheel is not supported, raise an error. + # Should check this after filtering out based on environment markers to + # allow specifying different wheels based on the environment/OS, in a + # single requirements file. + if install_req.link and install_req.link.is_wheel: + wheel = Wheel(install_req.link.filename) + if self.check_supported_wheels and not wheel.supported(): + raise InstallationError( + "%s is not a supported wheel on this platform." % + wheel.filename + ) + + # This next bit is really a sanity check. + assert install_req.is_direct == (parent_req_name is None), ( + "a direct req shouldn't have a parent and also, " + "a non direct req should have a parent" + ) + + # Unnamed requirements are scanned again and the requirement won't be + # added as a dependency until after scanning. + if not name: + # url or path requirement w/o an egg fragment + self.unnamed_requirements.append(install_req) + return [install_req], None + + try: + existing_req = self.get_requirement(name) + except KeyError: + existing_req = None + + has_conflicting_requirement = ( + parent_req_name is None and + existing_req and + not existing_req.constraint and + existing_req.extras == install_req.extras and + existing_req.req.specifier != install_req.req.specifier + ) + if has_conflicting_requirement: + raise InstallationError( + "Double requirement given: %s (already in %s, name=%r)" + % (install_req, existing_req, name) + ) + + # When no existing requirement exists, add the requirement as a + # dependency and it will be scanned again after. + if not existing_req: + self.requirements[name] = install_req + # FIXME: what about other normalizations? E.g., _ vs. -? + if name.lower() != name: + self.requirement_aliases[name.lower()] = name + # We'd want to rescan this requirements later + return [install_req], install_req + + # Assume there's no need to scan, and that we've already + # encountered this for scanning. + if install_req.constraint or not existing_req.constraint: + return [], existing_req + + does_not_satisfy_constraint = ( + install_req.link and + not ( + existing_req.link and + install_req.link.path == existing_req.link.path + ) + ) + if does_not_satisfy_constraint: + self.reqs_to_cleanup.append(install_req) + raise InstallationError( + "Could not satisfy constraints for '%s': " + "installation from path or url cannot be " + "constrained to a version" % name, + ) + # If we're now installing a constraint, mark the existing + # object for real installation. + existing_req.constraint = False + existing_req.extras = tuple(sorted( + set(existing_req.extras) | set(install_req.extras) + )) + logger.debug( + "Setting %s extras to: %s", + existing_req, existing_req.extras, + ) + # Return the existing requirement for addition to the parent and + # scanning again. + return [existing_req], existing_req + + def has_requirement(self, project_name): + name = project_name.lower() + if (name in self.requirements and + not self.requirements[name].constraint or + name in self.requirement_aliases and + not self.requirements[self.requirement_aliases[name]].constraint): + return True + return False + + @property + def has_requirements(self): + return list(req for req in self.requirements.values() if not + req.constraint) or self.unnamed_requirements + + def get_requirement(self, project_name): + for name in project_name, project_name.lower(): + if name in self.requirements: + return self.requirements[name] + if name in self.requirement_aliases: + return self.requirements[self.requirement_aliases[name]] + raise KeyError("No project with the name %r" % project_name) + + def cleanup_files(self): + """Clean up files, remove builds.""" + logger.debug('Cleaning up...') + with indent_log(): + for req in self.reqs_to_cleanup: + req.remove_temporary_source() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/req_tracker.py b/venv/lib/python3.7/site-packages/pip/_internal/req/req_tracker.py new file mode 100644 index 0000000..0a86f4c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/req_tracker.py @@ -0,0 +1,76 @@ +from __future__ import absolute_import + +import contextlib +import errno +import hashlib +import logging +import os + +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +class RequirementTracker(object): + + def __init__(self): + self._root = os.environ.get('PIP_REQ_TRACKER') + if self._root is None: + self._temp_dir = TempDirectory(delete=False, kind='req-tracker') + self._temp_dir.create() + self._root = os.environ['PIP_REQ_TRACKER'] = self._temp_dir.path + logger.debug('Created requirements tracker %r', self._root) + else: + self._temp_dir = None + logger.debug('Re-using requirements tracker %r', self._root) + self._entries = set() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.cleanup() + + def _entry_path(self, link): + hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() + return os.path.join(self._root, hashed) + + def add(self, req): + link = req.link + info = str(req) + entry_path = self._entry_path(link) + try: + with open(entry_path) as fp: + # Error, these's already a build in progress. + raise LookupError('%s is already being built: %s' + % (link, fp.read())) + except IOError as e: + if e.errno != errno.ENOENT: + raise + assert req not in self._entries + with open(entry_path, 'w') as fp: + fp.write(info) + self._entries.add(req) + logger.debug('Added %s to build tracker %r', req, self._root) + + def remove(self, req): + link = req.link + self._entries.remove(req) + os.unlink(self._entry_path(link)) + logger.debug('Removed %s from build tracker %r', req, self._root) + + def cleanup(self): + for req in set(self._entries): + self.remove(req) + remove = self._temp_dir is not None + if remove: + self._temp_dir.cleanup() + logger.debug('%s build tracker %r', + 'Removed' if remove else 'Cleaned', + self._root) + + @contextlib.contextmanager + def track(self, req): + self.add(req) + yield + self.remove(req) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/req/req_uninstall.py b/venv/lib/python3.7/site-packages/pip/_internal/req/req_uninstall.py new file mode 100644 index 0000000..a7d8230 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/req/req_uninstall.py @@ -0,0 +1,460 @@ +from __future__ import absolute_import + +import csv +import functools +import logging +import os +import sys +import sysconfig + +from pip._vendor import pkg_resources + +from pip._internal.exceptions import UninstallationError +from pip._internal.locations import bin_py, bin_user +from pip._internal.utils.compat import WINDOWS, cache_from_source, uses_pycache +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + FakeFile, ask, dist_in_usersite, dist_is_local, egg_link_path, is_local, + normalize_path, renames, +) +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +def _script_names(dist, script_name, is_gui): + """Create the fully qualified name of the files created by + {console,gui}_scripts for the given ``dist``. + Returns the list of file names + """ + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + exe_name = os.path.join(bin_dir, script_name) + paths_to_remove = [exe_name] + if WINDOWS: + paths_to_remove.append(exe_name + '.exe') + paths_to_remove.append(exe_name + '.exe.manifest') + if is_gui: + paths_to_remove.append(exe_name + '-script.pyw') + else: + paths_to_remove.append(exe_name + '-script.py') + return paths_to_remove + + +def _unique(fn): + @functools.wraps(fn) + def unique(*args, **kw): + seen = set() + for item in fn(*args, **kw): + if item not in seen: + seen.add(item) + yield item + return unique + + +@_unique +def uninstallation_paths(dist): + """ + Yield all the uninstallation paths for dist based on RECORD-without-.py[co] + + Yield paths to all the files in RECORD. For each .py file in RECORD, add + the .pyc and .pyo in the same directory. + + UninstallPathSet.add() takes care of the __pycache__ .py[co]. + """ + r = csv.reader(FakeFile(dist.get_metadata_lines('RECORD'))) + for row in r: + path = os.path.join(dist.location, row[0]) + yield path + if path.endswith('.py'): + dn, fn = os.path.split(path) + base = fn[:-3] + path = os.path.join(dn, base + '.pyc') + yield path + path = os.path.join(dn, base + '.pyo') + yield path + + +def compact(paths): + """Compact a path set to contain the minimal number of paths + necessary to contain all paths in the set. If /a/path/ and + /a/path/to/a/file.txt are both in the set, leave only the + shorter path.""" + + sep = os.path.sep + short_paths = set() + for path in sorted(paths, key=len): + should_add = any( + path.startswith(shortpath.rstrip("*")) and + path[len(shortpath.rstrip("*").rstrip(sep))] == sep + for shortpath in short_paths + ) + if not should_add: + short_paths.add(path) + return short_paths + + +def compress_for_output_listing(paths): + """Returns a tuple of 2 sets of which paths to display to user + + The first set contains paths that would be deleted. Files of a package + are not added and the top-level directory of the package has a '*' added + at the end - to signify that all it's contents are removed. + + The second set contains files that would have been skipped in the above + folders. + """ + + will_remove = list(paths) + will_skip = set() + + # Determine folders and files + folders = set() + files = set() + for path in will_remove: + if path.endswith(".pyc"): + continue + if path.endswith("__init__.py") or ".dist-info" in path: + folders.add(os.path.dirname(path)) + files.add(path) + + _normcased_files = set(map(os.path.normcase, files)) + + folders = compact(folders) + + # This walks the tree using os.walk to not miss extra folders + # that might get added. + for folder in folders: + for dirpath, _, dirfiles in os.walk(folder): + for fname in dirfiles: + if fname.endswith(".pyc"): + continue + + file_ = os.path.join(dirpath, fname) + if (os.path.isfile(file_) and + os.path.normcase(file_) not in _normcased_files): + # We are skipping this file. Add it to the set. + will_skip.add(file_) + + will_remove = files | { + os.path.join(folder, "*") for folder in folders + } + + return will_remove, will_skip + + +class UninstallPathSet(object): + """A set of file paths to be removed in the uninstallation of a + requirement.""" + def __init__(self, dist): + self.paths = set() + self._refuse = set() + self.pth = {} + self.dist = dist + self.save_dir = TempDirectory(kind="uninstall") + self._moved_paths = [] + + def _permitted(self, path): + """ + Return True if the given path is one we are permitted to + remove/modify, False otherwise. + + """ + return is_local(path) + + def add(self, path): + head, tail = os.path.split(path) + + # we normalize the head to resolve parent directory symlinks, but not + # the tail, since we only want to uninstall symlinks, not their targets + path = os.path.join(normalize_path(head), os.path.normcase(tail)) + + if not os.path.exists(path): + return + if self._permitted(path): + self.paths.add(path) + else: + self._refuse.add(path) + + # __pycache__ files can show up after 'installed-files.txt' is created, + # due to imports + if os.path.splitext(path)[1] == '.py' and uses_pycache: + self.add(cache_from_source(path)) + + def add_pth(self, pth_file, entry): + pth_file = normalize_path(pth_file) + if self._permitted(pth_file): + if pth_file not in self.pth: + self.pth[pth_file] = UninstallPthEntries(pth_file) + self.pth[pth_file].add(entry) + else: + self._refuse.add(pth_file) + + def _stash(self, path): + return os.path.join( + self.save_dir.path, os.path.splitdrive(path)[1].lstrip(os.path.sep) + ) + + def remove(self, auto_confirm=False, verbose=False): + """Remove paths in ``self.paths`` with confirmation (unless + ``auto_confirm`` is True).""" + + if not self.paths: + logger.info( + "Can't uninstall '%s'. No files were found to uninstall.", + self.dist.project_name, + ) + return + + dist_name_version = ( + self.dist.project_name + "-" + self.dist.version + ) + logger.info('Uninstalling %s:', dist_name_version) + + with indent_log(): + if auto_confirm or self._allowed_to_proceed(verbose): + self.save_dir.create() + + for path in sorted(compact(self.paths)): + new_path = self._stash(path) + logger.debug('Removing file or directory %s', path) + self._moved_paths.append(path) + renames(path, new_path) + for pth in self.pth.values(): + pth.remove() + + logger.info('Successfully uninstalled %s', dist_name_version) + + def _allowed_to_proceed(self, verbose): + """Display which files would be deleted and prompt for confirmation + """ + + def _display(msg, paths): + if not paths: + return + + logger.info(msg) + with indent_log(): + for path in sorted(compact(paths)): + logger.info(path) + + if not verbose: + will_remove, will_skip = compress_for_output_listing(self.paths) + else: + # In verbose mode, display all the files that are going to be + # deleted. + will_remove = list(self.paths) + will_skip = set() + + _display('Would remove:', will_remove) + _display('Would not remove (might be manually added):', will_skip) + _display('Would not remove (outside of prefix):', self._refuse) + + return ask('Proceed (y/n)? ', ('y', 'n')) == 'y' + + def rollback(self): + """Rollback the changes previously made by remove().""" + if self.save_dir.path is None: + logger.error( + "Can't roll back %s; was not uninstalled", + self.dist.project_name, + ) + return False + logger.info('Rolling back uninstall of %s', self.dist.project_name) + for path in self._moved_paths: + tmp_path = self._stash(path) + logger.debug('Replacing %s', path) + renames(tmp_path, path) + for pth in self.pth.values(): + pth.rollback() + + def commit(self): + """Remove temporary save dir: rollback will no longer be possible.""" + self.save_dir.cleanup() + self._moved_paths = [] + + @classmethod + def from_dist(cls, dist): + dist_path = normalize_path(dist.location) + if not dist_is_local(dist): + logger.info( + "Not uninstalling %s at %s, outside environment %s", + dist.key, + dist_path, + sys.prefix, + ) + return cls(dist) + + if dist_path in {p for p in {sysconfig.get_path("stdlib"), + sysconfig.get_path("platstdlib")} + if p}: + logger.info( + "Not uninstalling %s at %s, as it is in the standard library.", + dist.key, + dist_path, + ) + return cls(dist) + + paths_to_remove = cls(dist) + develop_egg_link = egg_link_path(dist) + develop_egg_link_egg_info = '{}.egg-info'.format( + pkg_resources.to_filename(dist.project_name)) + egg_info_exists = dist.egg_info and os.path.exists(dist.egg_info) + # Special case for distutils installed package + distutils_egg_info = getattr(dist._provider, 'path', None) + + # Uninstall cases order do matter as in the case of 2 installs of the + # same package, pip needs to uninstall the currently detected version + if (egg_info_exists and dist.egg_info.endswith('.egg-info') and + not dist.egg_info.endswith(develop_egg_link_egg_info)): + # if dist.egg_info.endswith(develop_egg_link_egg_info), we + # are in fact in the develop_egg_link case + paths_to_remove.add(dist.egg_info) + if dist.has_metadata('installed-files.txt'): + for installed_file in dist.get_metadata( + 'installed-files.txt').splitlines(): + path = os.path.normpath( + os.path.join(dist.egg_info, installed_file) + ) + paths_to_remove.add(path) + # FIXME: need a test for this elif block + # occurs with --single-version-externally-managed/--record outside + # of pip + elif dist.has_metadata('top_level.txt'): + if dist.has_metadata('namespace_packages.txt'): + namespaces = dist.get_metadata('namespace_packages.txt') + else: + namespaces = [] + for top_level_pkg in [ + p for p + in dist.get_metadata('top_level.txt').splitlines() + if p and p not in namespaces]: + path = os.path.join(dist.location, top_level_pkg) + paths_to_remove.add(path) + paths_to_remove.add(path + '.py') + paths_to_remove.add(path + '.pyc') + paths_to_remove.add(path + '.pyo') + + elif distutils_egg_info: + raise UninstallationError( + "Cannot uninstall {!r}. It is a distutils installed project " + "and thus we cannot accurately determine which files belong " + "to it which would lead to only a partial uninstall.".format( + dist.project_name, + ) + ) + + elif dist.location.endswith('.egg'): + # package installed by easy_install + # We cannot match on dist.egg_name because it can slightly vary + # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg + paths_to_remove.add(dist.location) + easy_install_egg = os.path.split(dist.location)[1] + easy_install_pth = os.path.join(os.path.dirname(dist.location), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg) + + elif egg_info_exists and dist.egg_info.endswith('.dist-info'): + for path in uninstallation_paths(dist): + paths_to_remove.add(path) + + elif develop_egg_link: + # develop egg + with open(develop_egg_link, 'r') as fh: + link_pointer = os.path.normcase(fh.readline().strip()) + assert (link_pointer == dist.location), ( + 'Egg-link %s does not match installed location of %s ' + '(at %s)' % (link_pointer, dist.project_name, dist.location) + ) + paths_to_remove.add(develop_egg_link) + easy_install_pth = os.path.join(os.path.dirname(develop_egg_link), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, dist.location) + + else: + logger.debug( + 'Not sure how to uninstall: %s - Check: %s', + dist, dist.location, + ) + + # find distutils scripts= scripts + if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'): + for script in dist.metadata_listdir('scripts'): + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + paths_to_remove.add(os.path.join(bin_dir, script)) + if WINDOWS: + paths_to_remove.add(os.path.join(bin_dir, script) + '.bat') + + # find console_scripts + _scripts_to_remove = [] + console_scripts = dist.get_entry_map(group='console_scripts') + for name in console_scripts.keys(): + _scripts_to_remove.extend(_script_names(dist, name, False)) + # find gui_scripts + gui_scripts = dist.get_entry_map(group='gui_scripts') + for name in gui_scripts.keys(): + _scripts_to_remove.extend(_script_names(dist, name, True)) + + for s in _scripts_to_remove: + paths_to_remove.add(s) + + return paths_to_remove + + +class UninstallPthEntries(object): + def __init__(self, pth_file): + if not os.path.isfile(pth_file): + raise UninstallationError( + "Cannot remove entries from nonexistent file %s" % pth_file + ) + self.file = pth_file + self.entries = set() + self._saved_lines = None + + def add(self, entry): + entry = os.path.normcase(entry) + # On Windows, os.path.normcase converts the entry to use + # backslashes. This is correct for entries that describe absolute + # paths outside of site-packages, but all the others use forward + # slashes. + if WINDOWS and not os.path.splitdrive(entry)[0]: + entry = entry.replace('\\', '/') + self.entries.add(entry) + + def remove(self): + logger.debug('Removing pth entries from %s:', self.file) + with open(self.file, 'rb') as fh: + # windows uses '\r\n' with py3k, but uses '\n' with py2.x + lines = fh.readlines() + self._saved_lines = lines + if any(b'\r\n' in line for line in lines): + endline = '\r\n' + else: + endline = '\n' + # handle missing trailing newline + if lines and not lines[-1].endswith(endline.encode("utf-8")): + lines[-1] = lines[-1] + endline.encode("utf-8") + for entry in self.entries: + try: + logger.debug('Removing entry: %s', entry) + lines.remove((entry + endline).encode("utf-8")) + except ValueError: + pass + with open(self.file, 'wb') as fh: + fh.writelines(lines) + + def rollback(self): + if self._saved_lines is None: + logger.error( + 'Cannot roll back changes to %s, none were made', self.file + ) + return False + logger.debug('Rolling %s back to previous state', self.file) + with open(self.file, 'wb') as fh: + fh.writelines(self._saved_lines) + return True diff --git a/venv/lib/python3.7/site-packages/pip/_internal/resolve.py b/venv/lib/python3.7/site-packages/pip/_internal/resolve.py new file mode 100644 index 0000000..2d9f1c5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/resolve.py @@ -0,0 +1,353 @@ +"""Dependency Resolution + +The dependency resolution in pip is performed as follows: + +for top-level requirements: + a. only one spec allowed per project, regardless of conflicts or not. + otherwise a "double requirement" exception is raised + b. they override sub-dependency requirements. +for sub-dependencies + a. "first found, wins" (where the order is breadth first) +""" + +import logging +from collections import defaultdict +from itertools import chain + +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, DistributionNotFound, HashError, HashErrors, + UnsupportedPythonVersion, +) +from pip._internal.req.constructors import install_req_from_req +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import dist_in_usersite, ensure_dir +from pip._internal.utils.packaging import check_dist_requires_python + +logger = logging.getLogger(__name__) + + +class Resolver(object): + """Resolves which packages need to be installed/uninstalled to perform \ + the requested operation without breaking the requirements of any package. + """ + + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__(self, preparer, session, finder, wheel_cache, use_user_site, + ignore_dependencies, ignore_installed, ignore_requires_python, + force_reinstall, isolated, upgrade_strategy): + super(Resolver, self).__init__() + assert upgrade_strategy in self._allowed_strategies + + self.preparer = preparer + self.finder = finder + self.session = session + + # NOTE: This would eventually be replaced with a cache that can give + # information about both sdist and wheels transparently. + self.wheel_cache = wheel_cache + + self.require_hashes = None # This is set in resolve + + self.upgrade_strategy = upgrade_strategy + self.force_reinstall = force_reinstall + self.isolated = isolated + self.ignore_dependencies = ignore_dependencies + self.ignore_installed = ignore_installed + self.ignore_requires_python = ignore_requires_python + self.use_user_site = use_user_site + + self._discovered_dependencies = defaultdict(list) + + def resolve(self, requirement_set): + """Resolve what operations need to be done + + As a side-effect of this method, the packages (and their dependencies) + are downloaded, unpacked and prepared for installation. This + preparation is done by ``pip.operations.prepare``. + + Once PyPI has static dependency metadata available, it would be + possible to move the preparation to become a step separated from + dependency resolution. + """ + # make the wheelhouse + if self.preparer.wheel_download_dir: + ensure_dir(self.preparer.wheel_download_dir) + + # If any top-level requirement has a hash specified, enter + # hash-checking mode, which requires hashes from all. + root_reqs = ( + requirement_set.unnamed_requirements + + list(requirement_set.requirements.values()) + ) + self.require_hashes = ( + requirement_set.require_hashes or + any(req.has_hash_options for req in root_reqs) + ) + + # Display where finder is looking for packages + locations = self.finder.get_formatted_locations() + if locations: + logger.info(locations) + + # Actually prepare the files, and collect any exceptions. Most hash + # exceptions cannot be checked ahead of time, because + # req.populate_link() needs to be called before we can make decisions + # based on link type. + discovered_reqs = [] + hash_errors = HashErrors() + for req in chain(root_reqs, discovered_reqs): + try: + discovered_reqs.extend( + self._resolve_one(requirement_set, req) + ) + except HashError as exc: + exc.req = req + hash_errors.append(exc) + + if hash_errors: + raise hash_errors + + def _is_upgrade_allowed(self, req): + if self.upgrade_strategy == "to-satisfy-only": + return False + elif self.upgrade_strategy == "eager": + return True + else: + assert self.upgrade_strategy == "only-if-needed" + return req.is_direct + + def _set_req_to_reinstall(self, req): + """ + Set a requirement to be installed. + """ + # Don't uninstall the conflict if doing a user install and the + # conflict is not a user install. + if not self.use_user_site or dist_in_usersite(req.satisfied_by): + req.conflicts_with = req.satisfied_by + req.satisfied_by = None + + # XXX: Stop passing requirement_set for options + def _check_skip_installed(self, req_to_install): + """Check if req_to_install should be skipped. + + This will check if the req is installed, and whether we should upgrade + or reinstall it, taking into account all the relevant user options. + + After calling this req_to_install will only have satisfied_by set to + None if the req_to_install is to be upgraded/reinstalled etc. Any + other value will be a dist recording the current thing installed that + satisfies the requirement. + + Note that for vcs urls and the like we can't assess skipping in this + routine - we simply identify that we need to pull the thing down, + then later on it is pulled down and introspected to assess upgrade/ + reinstalls etc. + + :return: A text reason for why it was skipped, or None. + """ + if self.ignore_installed: + return None + + req_to_install.check_if_exists(self.use_user_site) + if not req_to_install.satisfied_by: + return None + + if self.force_reinstall: + self._set_req_to_reinstall(req_to_install) + return None + + if not self._is_upgrade_allowed(req_to_install): + if self.upgrade_strategy == "only-if-needed": + return 'already satisfied, skipping upgrade' + return 'already satisfied' + + # Check for the possibility of an upgrade. For link-based + # requirements we have to pull the tree down and inspect to assess + # the version #, so it's handled way down. + if not req_to_install.link: + try: + self.finder.find_requirement(req_to_install, upgrade=True) + except BestVersionAlreadyInstalled: + # Then the best version is installed. + return 'already up-to-date' + except DistributionNotFound: + # No distribution found, so we squash the error. It will + # be raised later when we re-try later to do the install. + # Why don't we just raise here? + pass + + self._set_req_to_reinstall(req_to_install) + return None + + def _get_abstract_dist_for(self, req): + """Takes a InstallRequirement and returns a single AbstractDist \ + representing a prepared variant of the same. + """ + assert self.require_hashes is not None, ( + "require_hashes should have been set in Resolver.resolve()" + ) + + if req.editable: + return self.preparer.prepare_editable_requirement( + req, self.require_hashes, self.use_user_site, self.finder, + ) + + # satisfied_by is only evaluated by calling _check_skip_installed, + # so it must be None here. + assert req.satisfied_by is None + skip_reason = self._check_skip_installed(req) + + if req.satisfied_by: + return self.preparer.prepare_installed_requirement( + req, self.require_hashes, skip_reason + ) + + upgrade_allowed = self._is_upgrade_allowed(req) + abstract_dist = self.preparer.prepare_linked_requirement( + req, self.session, self.finder, upgrade_allowed, + self.require_hashes + ) + + # NOTE + # The following portion is for determining if a certain package is + # going to be re-installed/upgraded or not and reporting to the user. + # This should probably get cleaned up in a future refactor. + + # req.req is only avail after unpack for URL + # pkgs repeat check_if_exists to uninstall-on-upgrade + # (#14) + if not self.ignore_installed: + req.check_if_exists(self.use_user_site) + + if req.satisfied_by: + should_modify = ( + self.upgrade_strategy != "to-satisfy-only" or + self.force_reinstall or + self.ignore_installed or + req.link.scheme == 'file' + ) + if should_modify: + self._set_req_to_reinstall(req) + else: + logger.info( + 'Requirement already satisfied (use --upgrade to upgrade):' + ' %s', req, + ) + + return abstract_dist + + def _resolve_one(self, requirement_set, req_to_install): + """Prepare a single requirements file. + + :return: A list of additional InstallRequirements to also install. + """ + # Tell user what we are doing for this requirement: + # obtain (editable), skipping, processing (local url), collecting + # (remote url or package name) + if req_to_install.constraint or req_to_install.prepared: + return [] + + req_to_install.prepared = True + + # register tmp src for cleanup in case something goes wrong + requirement_set.reqs_to_cleanup.append(req_to_install) + + abstract_dist = self._get_abstract_dist_for(req_to_install) + + # Parse and return dependencies + dist = abstract_dist.dist(self.finder) + try: + check_dist_requires_python(dist) + except UnsupportedPythonVersion as err: + if self.ignore_requires_python: + logger.warning(err.args[0]) + else: + raise + + more_reqs = [] + + def add_req(subreq, extras_requested): + sub_install_req = install_req_from_req( + str(subreq), + req_to_install, + isolated=self.isolated, + wheel_cache=self.wheel_cache, + ) + parent_req_name = req_to_install.name + to_scan_again, add_to_parent = requirement_set.add_requirement( + sub_install_req, + parent_req_name=parent_req_name, + extras_requested=extras_requested, + ) + if parent_req_name and add_to_parent: + self._discovered_dependencies[parent_req_name].append( + add_to_parent + ) + more_reqs.extend(to_scan_again) + + with indent_log(): + # We add req_to_install before its dependencies, so that we + # can refer to it when adding dependencies. + if not requirement_set.has_requirement(req_to_install.name): + # 'unnamed' requirements will get added here + req_to_install.is_direct = True + requirement_set.add_requirement( + req_to_install, parent_req_name=None, + ) + + if not self.ignore_dependencies: + if req_to_install.extras: + logger.debug( + "Installing extra requirements: %r", + ','.join(req_to_install.extras), + ) + missing_requested = sorted( + set(req_to_install.extras) - set(dist.extras) + ) + for missing in missing_requested: + logger.warning( + '%s does not provide the extra \'%s\'', + dist, missing + ) + + available_requested = sorted( + set(dist.extras) & set(req_to_install.extras) + ) + for subreq in dist.requires(available_requested): + add_req(subreq, extras_requested=available_requested) + + if not req_to_install.editable and not req_to_install.satisfied_by: + # XXX: --no-install leads this to report 'Successfully + # downloaded' for only non-editable reqs, even though we took + # action on them. + requirement_set.successfully_downloaded.append(req_to_install) + + return more_reqs + + def get_installation_order(self, req_set): + """Create the installation order. + + The installation order is topological - requirements are installed + before the requiring thing. We break cycles at an arbitrary point, + and make no other guarantees. + """ + # The current implementation, which we may change at any point + # installs the user specified things in the order given, except when + # dependencies must come earlier to achieve topological order. + order = [] + ordered_reqs = set() + + def schedule(req): + if req.satisfied_by or req in ordered_reqs: + return + if req.constraint: + return + ordered_reqs.add(req) + for dep in self._discovered_dependencies[req.name]: + schedule(dep) + order.append(req) + + for install_req in req_set.requirements.values(): + schedule(install_req) + return order diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/appdirs.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/appdirs.py new file mode 100644 index 0000000..cc96f98 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/appdirs.py @@ -0,0 +1,258 @@ +""" +This code was taken from https://github.com/ActiveState/appdirs and modified +to suit our purposes. +""" +from __future__ import absolute_import + +import os +import sys + +from pip._vendor.six import PY2, text_type + +from pip._internal.utils.compat import WINDOWS, expanduser + + +def user_cache_dir(appname): + r""" + Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + + Typical user cache directories are: + macOS: ~/Library/Caches/ + Unix: ~/.cache/ (XDG default) + Windows: C:\Users\\AppData\Local\\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go + in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the + non-roaming app data dir (the default returned by `user_data_dir`). Apps + typically put cache data somewhere *under* the given dir here. Some + examples: + ...\Mozilla\Firefox\Profiles\\Cache + ...\Acme\SuperApp\Cache\1.0 + + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + """ + if WINDOWS: + # Get the base path + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + + # When using Python 2, return paths as bytes on Windows like we do on + # other operating systems. See helper function docs for more details. + if PY2 and isinstance(path, text_type): + path = _win_path_to_bytes(path) + + # Add our app name and Cache directory to it + path = os.path.join(path, appname, "Cache") + elif sys.platform == "darwin": + # Get the base path + path = expanduser("~/Library/Caches") + + # Add our app name to it + path = os.path.join(path, appname) + else: + # Get the base path + path = os.getenv("XDG_CACHE_HOME", expanduser("~/.cache")) + + # Add our app name to it + path = os.path.join(path, appname) + + return path + + +def user_data_dir(appname, roaming=False): + r""" + Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user data directories are: + macOS: ~/Library/Application Support/ + if it exists, else ~/.config/ + Unix: ~/.local/share/ # or in + $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\\ ... + ...Application Data\ + Win XP (roaming): C:\Documents and Settings\\Local ... + ...Settings\Application Data\ + Win 7 (not roaming): C:\\Users\\AppData\Local\ + Win 7 (roaming): C:\\Users\\AppData\Roaming\ + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/". + """ + if WINDOWS: + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.join(os.path.normpath(_get_win_folder(const)), appname) + elif sys.platform == "darwin": + path = os.path.join( + expanduser('~/Library/Application Support/'), + appname, + ) if os.path.isdir(os.path.join( + expanduser('~/Library/Application Support/'), + appname, + ) + ) else os.path.join( + expanduser('~/.config/'), + appname, + ) + else: + path = os.path.join( + os.getenv('XDG_DATA_HOME', expanduser("~/.local/share")), + appname, + ) + + return path + + +def user_config_dir(appname, roaming=True): + """Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "roaming" (boolean, default True) can be set False to not use the + Windows roaming appdata directory. That means that for users on a + Windows network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user data directories are: + macOS: same as user_data_dir + Unix: ~/.config/ + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/". + """ + if WINDOWS: + path = user_data_dir(appname, roaming=roaming) + elif sys.platform == "darwin": + path = user_data_dir(appname) + else: + path = os.getenv('XDG_CONFIG_HOME', expanduser("~/.config")) + path = os.path.join(path, appname) + + return path + + +# for the discussion regarding site_config_dirs locations +# see +def site_config_dirs(appname): + r"""Return a list of potential user-shared config dirs for this application. + + "appname" is the name of application. + + Typical user config directories are: + macOS: /Library/Application Support// + Unix: /etc or $XDG_CONFIG_DIRS[i]// for each value in + $XDG_CONFIG_DIRS + Win XP: C:\Documents and Settings\All Users\Application ... + ...Data\\ + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory + on Vista.) + Win 7: Hidden, but writeable on Win 7: + C:\ProgramData\\ + """ + if WINDOWS: + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + pathlist = [os.path.join(path, appname)] + elif sys.platform == 'darwin': + pathlist = [os.path.join('/Library/Application Support', appname)] + else: + # try looking in $XDG_CONFIG_DIRS + xdg_config_dirs = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + if xdg_config_dirs: + pathlist = [ + os.path.join(expanduser(x), appname) + for x in xdg_config_dirs.split(os.pathsep) + ] + else: + pathlist = [] + + # always look in /etc directly as well + pathlist.append('/etc') + + return pathlist + + +# -- Windows support functions -- + +def _get_win_folder_from_registry(csidl_name): + """ + This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + directory, _type = _winreg.QueryValueEx(key, shell_folder_name) + return directory + + +def _get_win_folder_with_ctypes(csidl_name): + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + + +if WINDOWS: + try: + import ctypes + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +def _win_path_to_bytes(path): + """Encode Windows paths to bytes. Only used on Python 2. + + Motivation is to be consistent with other operating systems where paths + are also returned as bytes. This avoids problems mixing bytes and Unicode + elsewhere in the codebase. For more details and discussion see + . + + If encoding using ASCII and MBCS fails, return the original Unicode path. + """ + for encoding in ('ASCII', 'MBCS'): + try: + return path.encode(encoding) + except (UnicodeEncodeError, LookupError): + pass + return path diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/compat.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/compat.py new file mode 100644 index 0000000..3114f2d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/compat.py @@ -0,0 +1,248 @@ +"""Stuff that differs in different Python versions and platform +distributions.""" +from __future__ import absolute_import, division + +import codecs +import locale +import logging +import os +import shutil +import sys + +from pip._vendor.six import text_type + +try: + import ipaddress +except ImportError: + try: + from pip._vendor import ipaddress # type: ignore + except ImportError: + import ipaddr as ipaddress # type: ignore + ipaddress.ip_address = ipaddress.IPAddress + ipaddress.ip_network = ipaddress.IPNetwork + + +__all__ = [ + "ipaddress", "uses_pycache", "console_to_str", "native_str", + "get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size", + "get_extension_suffixes", +] + + +logger = logging.getLogger(__name__) + +if sys.version_info >= (3, 4): + uses_pycache = True + from importlib.util import cache_from_source +else: + import imp + + try: + cache_from_source = imp.cache_from_source # type: ignore + except AttributeError: + # does not use __pycache__ + cache_from_source = None + + uses_pycache = cache_from_source is not None + + +if sys.version_info >= (3, 5): + backslashreplace_decode = "backslashreplace" +else: + # In version 3.4 and older, backslashreplace exists + # but does not support use for decoding. + # We implement our own replace handler for this + # situation, so that we can consistently use + # backslash replacement for all versions. + def backslashreplace_decode_fn(err): + raw_bytes = (err.object[i] for i in range(err.start, err.end)) + if sys.version_info[0] == 2: + # Python 2 gave us characters - convert to numeric bytes + raw_bytes = (ord(b) for b in raw_bytes) + return u"".join(u"\\x%x" % c for c in raw_bytes), err.end + codecs.register_error( + "backslashreplace_decode", + backslashreplace_decode_fn, + ) + backslashreplace_decode = "backslashreplace_decode" + + +def console_to_str(data): + """Return a string, safe for output, of subprocess output. + + We assume the data is in the locale preferred encoding. + If it won't decode properly, we warn the user but decode as + best we can. + + We also ensure that the output can be safely written to + standard output without encoding errors. + """ + + # First, get the encoding we assume. This is the preferred + # encoding for the locale, unless that is not found, or + # it is ASCII, in which case assume UTF-8 + encoding = locale.getpreferredencoding() + if (not encoding) or codecs.lookup(encoding).name == "ascii": + encoding = "utf-8" + + # Now try to decode the data - if we fail, warn the user and + # decode with replacement. + try: + s = data.decode(encoding) + except UnicodeDecodeError: + logger.warning( + "Subprocess output does not appear to be encoded as %s", + encoding, + ) + s = data.decode(encoding, errors=backslashreplace_decode) + + # Make sure we can print the output, by encoding it to the output + # encoding with replacement of unencodable characters, and then + # decoding again. + # We use stderr's encoding because it's less likely to be + # redirected and if we don't find an encoding we skip this + # step (on the assumption that output is wrapped by something + # that won't fail). + # The double getattr is to deal with the possibility that we're + # being called in a situation where sys.__stderr__ doesn't exist, + # or doesn't have an encoding attribute. Neither of these cases + # should occur in normal pip use, but there's no harm in checking + # in case people use pip in (unsupported) unusual situations. + output_encoding = getattr(getattr(sys, "__stderr__", None), + "encoding", None) + + if output_encoding: + s = s.encode(output_encoding, errors="backslashreplace") + s = s.decode(output_encoding) + + return s + + +if sys.version_info >= (3,): + def native_str(s, replace=False): + if isinstance(s, bytes): + return s.decode('utf-8', 'replace' if replace else 'strict') + return s + +else: + def native_str(s, replace=False): + # Replace is ignored -- unicode to UTF-8 can't fail + if isinstance(s, text_type): + return s.encode('utf-8') + return s + + +def get_path_uid(path): + """ + Return path's uid. + + Does not follow symlinks: + https://github.com/pypa/pip/pull/935#discussion_r5307003 + + Placed this function in compat due to differences on AIX and + Jython, that should eventually go away. + + :raises OSError: When path is a symlink or can't be read. + """ + if hasattr(os, 'O_NOFOLLOW'): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + file_uid = os.fstat(fd).st_uid + os.close(fd) + else: # AIX and Jython + # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW + if not os.path.islink(path): + # older versions of Jython don't have `os.fstat` + file_uid = os.stat(path).st_uid + else: + # raise OSError for parity with os.O_NOFOLLOW above + raise OSError( + "%s is a symlink; Will not return uid for symlinks" % path + ) + return file_uid + + +if sys.version_info >= (3, 4): + from importlib.machinery import EXTENSION_SUFFIXES + + def get_extension_suffixes(): + return EXTENSION_SUFFIXES +else: + from imp import get_suffixes + + def get_extension_suffixes(): + return [suffix[0] for suffix in get_suffixes()] + + +def expanduser(path): + """ + Expand ~ and ~user constructions. + + Includes a workaround for https://bugs.python.org/issue14768 + """ + expanded = os.path.expanduser(path) + if path.startswith('~/') and expanded.startswith('//'): + expanded = expanded[1:] + return expanded + + +# packages in the stdlib that may have installation metadata, but should not be +# considered 'installed'. this theoretically could be determined based on +# dist.location (py27:`sysconfig.get_paths()['stdlib']`, +# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may +# make this ineffective, so hard-coding +stdlib_pkgs = {"python", "wsgiref", "argparse"} + + +# windows detection, covers cpython and ironpython +WINDOWS = (sys.platform.startswith("win") or + (sys.platform == 'cli' and os.name == 'nt')) + + +def samefile(file1, file2): + """Provide an alternative for os.path.samefile on Windows/Python2""" + if hasattr(os.path, 'samefile'): + return os.path.samefile(file1, file2) + else: + path1 = os.path.normcase(os.path.abspath(file1)) + path2 = os.path.normcase(os.path.abspath(file2)) + return path1 == path2 + + +if hasattr(shutil, 'get_terminal_size'): + def get_terminal_size(): + """ + Returns a tuple (x, y) representing the width(x) and the height(y) + in characters of the terminal window. + """ + return tuple(shutil.get_terminal_size()) +else: + def get_terminal_size(): + """ + Returns a tuple (x, y) representing the width(x) and the height(y) + in characters of the terminal window. + """ + def ioctl_GWINSZ(fd): + try: + import fcntl + import termios + import struct + cr = struct.unpack_from( + 'hh', + fcntl.ioctl(fd, termios.TIOCGWINSZ, '12345678') + ) + except Exception: + return None + if cr == (0, 0): + return None + return cr + cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) + if not cr: + try: + fd = os.open(os.ctermid(), os.O_RDONLY) + cr = ioctl_GWINSZ(fd) + os.close(fd) + except Exception: + pass + if not cr: + cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80)) + return int(cr[1]), int(cr[0]) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/deprecation.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/deprecation.py new file mode 100644 index 0000000..bd744cf --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/deprecation.py @@ -0,0 +1,89 @@ +""" +A module that implements tooling to enable easy warnings about deprecations. +""" +from __future__ import absolute_import + +import logging +import warnings + +from pip._vendor.packaging.version import parse + +from pip import __version__ as current_version +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Optional # noqa: F401 + + +class PipDeprecationWarning(Warning): + pass + + +_original_showwarning = None # type: Any + + +# Warnings <-> Logging Integration +def _showwarning(message, category, filename, lineno, file=None, line=None): + if file is not None: + if _original_showwarning is not None: + _original_showwarning( + message, category, filename, lineno, file, line, + ) + elif issubclass(category, PipDeprecationWarning): + # We use a specially named logger which will handle all of the + # deprecation messages for pip. + logger = logging.getLogger("pip._internal.deprecations") + logger.warning(message) + else: + _original_showwarning( + message, category, filename, lineno, file, line, + ) + + +def install_warning_logger(): + # Enable our Deprecation Warnings + warnings.simplefilter("default", PipDeprecationWarning, append=True) + + global _original_showwarning + + if _original_showwarning is None: + _original_showwarning = warnings.showwarning + warnings.showwarning = _showwarning + + +def deprecated(reason, replacement, gone_in, issue=None): + # type: (str, Optional[str], Optional[str], Optional[int]) -> None + """Helper to deprecate existing functionality. + + reason: + Textual reason shown to the user about why this functionality has + been deprecated. + replacement: + Textual suggestion shown to the user about what alternative + functionality they can use. + gone_in: + The version of pip does this functionality should get removed in. + Raises errors if pip's current version is greater than or equal to + this. + issue: + Issue number on the tracker that would serve as a useful place for + users to find related discussion and provide feedback. + + Always pass replacement, gone_in and issue as keyword arguments for clarity + at the call site. + """ + + # Construct a nice message. + # This is purposely eagerly formatted as we want it to appear as if someone + # typed this entire message out. + message = "DEPRECATION: " + reason + if replacement is not None: + message += " A possible replacement is {}.".format(replacement) + if issue is not None: + url = "https://github.com/pypa/pip/issues/" + str(issue) + message += " You can find discussion regarding this at {}.".format(url) + + # Raise as an error if it has to be removed. + if gone_in is not None and parse(current_version) >= parse(gone_in): + raise PipDeprecationWarning(message) + warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/encoding.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/encoding.py new file mode 100644 index 0000000..56f6036 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/encoding.py @@ -0,0 +1,33 @@ +import codecs +import locale +import re +import sys + +BOMS = [ + (codecs.BOM_UTF8, 'utf8'), + (codecs.BOM_UTF16, 'utf16'), + (codecs.BOM_UTF16_BE, 'utf16-be'), + (codecs.BOM_UTF16_LE, 'utf16-le'), + (codecs.BOM_UTF32, 'utf32'), + (codecs.BOM_UTF32_BE, 'utf32-be'), + (codecs.BOM_UTF32_LE, 'utf32-le'), +] + +ENCODING_RE = re.compile(br'coding[:=]\s*([-\w.]+)') + + +def auto_decode(data): + """Check a bytes string for a BOM to correctly detect the encoding + + Fallback to locale.getpreferredencoding(False) like open() on Python3""" + for bom, encoding in BOMS: + if data.startswith(bom): + return data[len(bom):].decode(encoding) + # Lets check the first two lines as in PEP263 + for line in data.split(b'\n')[:2]: + if line[0:1] == b'#' and ENCODING_RE.search(line): + encoding = ENCODING_RE.search(line).groups()[0].decode('ascii') + return data.decode(encoding) + return data.decode( + locale.getpreferredencoding(False) or sys.getdefaultencoding(), + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/filesystem.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/filesystem.py new file mode 100644 index 0000000..1e9cebd --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/filesystem.py @@ -0,0 +1,28 @@ +import os +import os.path + +from pip._internal.utils.compat import get_path_uid + + +def check_path_owner(path): + # If we don't have a way to check the effective uid of this process, then + # we'll just assume that we own the directory. + if not hasattr(os, "geteuid"): + return True + + previous = None + while path != previous: + if os.path.lexists(path): + # Check if path is writable by current user. + if os.geteuid() == 0: + # Special handling for root user in order to handle properly + # cases where users use sudo without -H flag. + try: + path_uid = get_path_uid(path) + except OSError: + return False + return path_uid == 0 + else: + return os.access(path, os.W_OK) + else: + previous, path = path, os.path.dirname(path) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/glibc.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/glibc.py new file mode 100644 index 0000000..ebcfc5b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/glibc.py @@ -0,0 +1,84 @@ +from __future__ import absolute_import + +import ctypes +import re +import warnings + + +def glibc_version_string(): + "Returns glibc version string, or None if not using glibc." + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# Separated out from have_compatible_glibc for easier unit testing +def check_glibc_version(version_str, required_major, minimum_minor): + # Parse string and check against requested version. + # + # We use a regexp instead of str.split because we want to discard any + # random junk that might come after the minor version -- this might happen + # in patched/forked versions of glibc (e.g. Linaro's version of glibc + # uses version strings like "2.20-2014.11"). See gh-3588. + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn("Expected glibc version with 2 components major.minor," + " got: %s" % version_str, RuntimeWarning) + return False + return (int(m.group("major")) == required_major and + int(m.group("minor")) >= minimum_minor) + + +def have_compatible_glibc(required_major, minimum_minor): + version_str = glibc_version_string() + if version_str is None: + return False + return check_glibc_version(version_str, required_major, minimum_minor) + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver(): + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/hashes.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/hashes.py new file mode 100644 index 0000000..8b909ba --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/hashes.py @@ -0,0 +1,94 @@ +from __future__ import absolute_import + +import hashlib + +from pip._vendor.six import iteritems, iterkeys, itervalues + +from pip._internal.exceptions import ( + HashMismatch, HashMissing, InstallationError, +) +from pip._internal.utils.misc import read_chunks + +# The recommended hash algo of the moment. Change this whenever the state of +# the art changes; it won't hurt backward compatibility. +FAVORITE_HASH = 'sha256' + + +# Names of hashlib algorithms allowed by the --hash option and ``pip hash`` +# Currently, those are the ones at least as collision-resistant as sha256. +STRONG_HASHES = ['sha256', 'sha384', 'sha512'] + + +class Hashes(object): + """A wrapper that builds multiple hashes at once and checks them against + known-good values + + """ + def __init__(self, hashes=None): + """ + :param hashes: A dict of algorithm names pointing to lists of allowed + hex digests + """ + self._allowed = {} if hashes is None else hashes + + def check_against_chunks(self, chunks): + """Check good hashes against ones built from iterable of chunks of + data. + + Raise HashMismatch if none match. + + """ + gots = {} + for hash_name in iterkeys(self._allowed): + try: + gots[hash_name] = hashlib.new(hash_name) + except (ValueError, TypeError): + raise InstallationError('Unknown hash name: %s' % hash_name) + + for chunk in chunks: + for hash in itervalues(gots): + hash.update(chunk) + + for hash_name, got in iteritems(gots): + if got.hexdigest() in self._allowed[hash_name]: + return + self._raise(gots) + + def _raise(self, gots): + raise HashMismatch(self._allowed, gots) + + def check_against_file(self, file): + """Check good hashes against a file-like object + + Raise HashMismatch if none match. + + """ + return self.check_against_chunks(read_chunks(file)) + + def check_against_path(self, path): + with open(path, 'rb') as file: + return self.check_against_file(file) + + def __nonzero__(self): + """Return whether I know any known-good hashes.""" + return bool(self._allowed) + + def __bool__(self): + return self.__nonzero__() + + +class MissingHashes(Hashes): + """A workalike for Hashes used when we're missing a hash for a requirement + + It computes the actual hash of the requirement and raises a HashMissing + exception showing it to the user. + + """ + def __init__(self): + """Don't offer the ``hashes`` kwarg.""" + # Pass our favorite hash in to generate a "gotten hash". With the + # empty list, it will never match, so an error will always raise. + super(MissingHashes, self).__init__(hashes={FAVORITE_HASH: []}) + + def _raise(self, gots): + raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py new file mode 100644 index 0000000..d9b9541 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/logging.py @@ -0,0 +1,225 @@ +from __future__ import absolute_import + +import contextlib +import logging +import logging.handlers +import os + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.misc import ensure_dir + +try: + import threading +except ImportError: + import dummy_threading as threading # type: ignore + + +try: + from pip._vendor import colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None + + +_log_state = threading.local() +_log_state.indentation = 0 + + +@contextlib.contextmanager +def indent_log(num=2): + """ + A context manager which will cause the log output to be indented for any + log messages emitted inside it. + """ + _log_state.indentation += num + try: + yield + finally: + _log_state.indentation -= num + + +def get_indentation(): + return getattr(_log_state, 'indentation', 0) + + +class IndentingFormatter(logging.Formatter): + + def format(self, record): + """ + Calls the standard formatter, but will indent all of the log messages + by our current indentation level. + """ + formatted = logging.Formatter.format(self, record) + formatted = "".join([ + (" " * get_indentation()) + line + for line in formatted.splitlines(True) + ]) + return formatted + + +def _color_wrap(*colors): + def wrapped(inp): + return "".join(list(colors) + [inp, colorama.Style.RESET_ALL]) + return wrapped + + +class ColorizedStreamHandler(logging.StreamHandler): + + # Don't build up a list of colors if we don't have colorama + if colorama: + COLORS = [ + # This needs to be in order from highest logging level to lowest. + (logging.ERROR, _color_wrap(colorama.Fore.RED)), + (logging.WARNING, _color_wrap(colorama.Fore.YELLOW)), + ] + else: + COLORS = [] + + def __init__(self, stream=None, no_color=None): + logging.StreamHandler.__init__(self, stream) + self._no_color = no_color + + if WINDOWS and colorama: + self.stream = colorama.AnsiToWin32(self.stream) + + def should_color(self): + # Don't colorize things if we do not have colorama or if told not to + if not colorama or self._no_color: + return False + + real_stream = ( + self.stream if not isinstance(self.stream, colorama.AnsiToWin32) + else self.stream.wrapped + ) + + # If the stream is a tty we should color it + if hasattr(real_stream, "isatty") and real_stream.isatty(): + return True + + # If we have an ANSI term we should color it + if os.environ.get("TERM") == "ANSI": + return True + + # If anything else we should not color it + return False + + def format(self, record): + msg = logging.StreamHandler.format(self, record) + + if self.should_color(): + for level, color in self.COLORS: + if record.levelno >= level: + msg = color(msg) + break + + return msg + + +class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): + + def _open(self): + ensure_dir(os.path.dirname(self.baseFilename)) + return logging.handlers.RotatingFileHandler._open(self) + + +class MaxLevelFilter(logging.Filter): + + def __init__(self, level): + self.level = level + + def filter(self, record): + return record.levelno < self.level + + +def setup_logging(verbosity, no_color, user_log_file): + """Configures and sets up all of the logging + """ + + # Determine the level to be logging at. + if verbosity >= 1: + level = "DEBUG" + elif verbosity == -1: + level = "WARNING" + elif verbosity == -2: + level = "ERROR" + elif verbosity <= -3: + level = "CRITICAL" + else: + level = "INFO" + + # The "root" logger should match the "console" level *unless* we also need + # to log to a user log file. + include_user_log = user_log_file is not None + if include_user_log: + additional_log_file = user_log_file + root_level = "DEBUG" + else: + additional_log_file = "/dev/null" + root_level = level + + # Disable any logging besides WARNING unless we have DEBUG level logging + # enabled for vendored libraries. + vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" + + # Shorthands for clarity + log_streams = { + "stdout": "ext://sys.stdout", + "stderr": "ext://sys.stderr", + } + handler_classes = { + "stream": "pip._internal.utils.logging.ColorizedStreamHandler", + "file": "pip._internal.utils.logging.BetterRotatingFileHandler", + } + + logging.config.dictConfig({ + "version": 1, + "disable_existing_loggers": False, + "filters": { + "exclude_warnings": { + "()": "pip._internal.utils.logging.MaxLevelFilter", + "level": logging.WARNING, + }, + }, + "formatters": { + "indent": { + "()": IndentingFormatter, + "format": "%(message)s", + }, + }, + "handlers": { + "console": { + "level": level, + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stdout"], + "filters": ["exclude_warnings"], + "formatter": "indent", + }, + "console_errors": { + "level": "WARNING", + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "formatter": "indent", + }, + "user_log": { + "level": "DEBUG", + "class": handler_classes["file"], + "filename": additional_log_file, + "delay": True, + "formatter": "indent", + }, + }, + "root": { + "level": root_level, + "handlers": ["console", "console_errors"] + ( + ["user_log"] if include_user_log else [] + ), + }, + "loggers": { + "pip._vendor": { + "level": vendored_log_level + } + }, + }) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/misc.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/misc.py new file mode 100644 index 0000000..84a421f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/misc.py @@ -0,0 +1,940 @@ +from __future__ import absolute_import + +import contextlib +import errno +import io +import locale +# we have a submodule named 'logging' which would shadow this if we used the +# regular name: +import logging as std_logging +import os +import posixpath +import re +import shutil +import stat +import subprocess +import sys +import tarfile +import zipfile +from collections import deque + +from pip._vendor import pkg_resources +# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import. +from pip._vendor.retrying import retry # type: ignore +from pip._vendor.six import PY2 +from pip._vendor.six.moves import input +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import CommandError, InstallationError +from pip._internal.locations import ( + running_under_virtualenv, site_packages, user_site, virtualenv_no_global, + write_delete_marker_file, +) +from pip._internal.utils.compat import ( + WINDOWS, console_to_str, expanduser, stdlib_pkgs, +) + +if PY2: + from io import BytesIO as StringIO +else: + from io import StringIO + +__all__ = ['rmtree', 'display_path', 'backup_dir', + 'ask', 'splitext', + 'format_size', 'is_installable_dir', + 'is_svn_page', 'file_contents', + 'split_leading_dir', 'has_leading_dir', + 'normalize_path', + 'renames', 'get_prog', + 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess', + 'captured_stdout', 'ensure_dir', + 'ARCHIVE_EXTENSIONS', 'SUPPORTED_EXTENSIONS', + 'get_installed_version', 'remove_auth_from_url'] + + +logger = std_logging.getLogger(__name__) + +BZ2_EXTENSIONS = ('.tar.bz2', '.tbz') +XZ_EXTENSIONS = ('.tar.xz', '.txz', '.tlz', '.tar.lz', '.tar.lzma') +ZIP_EXTENSIONS = ('.zip', '.whl') +TAR_EXTENSIONS = ('.tar.gz', '.tgz', '.tar') +ARCHIVE_EXTENSIONS = ( + ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS) +SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS +try: + import bz2 # noqa + SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS +except ImportError: + logger.debug('bz2 module is not available') + +try: + # Only for Python 3.3+ + import lzma # noqa + SUPPORTED_EXTENSIONS += XZ_EXTENSIONS +except ImportError: + logger.debug('lzma module is not available') + + +def import_or_raise(pkg_or_module_string, ExceptionType, *args, **kwargs): + try: + return __import__(pkg_or_module_string) + except ImportError: + raise ExceptionType(*args, **kwargs) + + +def ensure_dir(path): + """os.path.makedirs without EEXIST.""" + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + +def get_prog(): + try: + prog = os.path.basename(sys.argv[0]) + if prog in ('__main__.py', '-c'): + return "%s -m pip" % sys.executable + else: + return prog + except (AttributeError, TypeError, IndexError): + pass + return 'pip' + + +# Retry every half second for up to 3 seconds +@retry(stop_max_delay=3000, wait_fixed=500) +def rmtree(dir, ignore_errors=False): + shutil.rmtree(dir, ignore_errors=ignore_errors, + onerror=rmtree_errorhandler) + + +def rmtree_errorhandler(func, path, exc_info): + """On Windows, the files in .svn are read-only, so when rmtree() tries to + remove them, an exception is thrown. We catch that here, remove the + read-only attribute, and hopefully continue without problems.""" + # if file type currently read only + if os.stat(path).st_mode & stat.S_IREAD: + # convert to read/write + os.chmod(path, stat.S_IWRITE) + # use the original function to repeat the operation + func(path) + return + else: + raise + + +def display_path(path): + """Gives the display value for a given path, making it relative to cwd + if possible.""" + path = os.path.normcase(os.path.abspath(path)) + if sys.version_info[0] == 2: + path = path.decode(sys.getfilesystemencoding(), 'replace') + path = path.encode(sys.getdefaultencoding(), 'replace') + if path.startswith(os.getcwd() + os.path.sep): + path = '.' + path[len(os.getcwd()):] + return path + + +def backup_dir(dir, ext='.bak'): + """Figure out the name of a directory to back up the given dir to + (adding .bak, .bak2, etc)""" + n = 1 + extension = ext + while os.path.exists(dir + extension): + n += 1 + extension = ext + str(n) + return dir + extension + + +def ask_path_exists(message, options): + for action in os.environ.get('PIP_EXISTS_ACTION', '').split(): + if action in options: + return action + return ask(message, options) + + +def ask(message, options): + """Ask the message interactively, with the given possible responses""" + while 1: + if os.environ.get('PIP_NO_INPUT'): + raise Exception( + 'No input was expected ($PIP_NO_INPUT set); question: %s' % + message + ) + response = input(message) + response = response.strip().lower() + if response not in options: + print( + 'Your response (%r) was not one of the expected responses: ' + '%s' % (response, ', '.join(options)) + ) + else: + return response + + +def format_size(bytes): + if bytes > 1000 * 1000: + return '%.1fMB' % (bytes / 1000.0 / 1000) + elif bytes > 10 * 1000: + return '%ikB' % (bytes / 1000) + elif bytes > 1000: + return '%.1fkB' % (bytes / 1000.0) + else: + return '%ibytes' % bytes + + +def is_installable_dir(path): + """Is path is a directory containing setup.py or pyproject.toml? + """ + if not os.path.isdir(path): + return False + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + return True + pyproject_toml = os.path.join(path, 'pyproject.toml') + if os.path.isfile(pyproject_toml): + return True + return False + + +def is_svn_page(html): + """ + Returns true if the page appears to be the index page of an svn repository + """ + return (re.search(r'[^<]*Revision \d+:', html) and + re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I)) + + +def file_contents(filename): + with open(filename, 'rb') as fp: + return fp.read().decode('utf-8') + + +def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE): + """Yield pieces of data from a file-like object until EOF.""" + while True: + chunk = file.read(size) + if not chunk: + break + yield chunk + + +def split_leading_dir(path): + path = path.lstrip('/').lstrip('\\') + if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or + '\\' not in path): + return path.split('/', 1) + elif '\\' in path: + return path.split('\\', 1) + else: + return path, '' + + +def has_leading_dir(paths): + """Returns true if all the paths have the same leading path name + (i.e., everything is in one subdirectory in an archive)""" + common_prefix = None + for path in paths: + prefix, rest = split_leading_dir(path) + if not prefix: + return False + elif common_prefix is None: + common_prefix = prefix + elif prefix != common_prefix: + return False + return True + + +def normalize_path(path, resolve_symlinks=True): + """ + Convert a path to its canonical, case-normalized, absolute version. + + """ + path = expanduser(path) + if resolve_symlinks: + path = os.path.realpath(path) + else: + path = os.path.abspath(path) + return os.path.normcase(path) + + +def splitext(path): + """Like os.path.splitext, but take off .tar too""" + base, ext = posixpath.splitext(path) + if base.lower().endswith('.tar'): + ext = base[-4:] + ext + base = base[:-4] + return base, ext + + +def renames(old, new): + """Like os.renames(), but handles renaming across devices.""" + # Implementation borrowed from os.renames(). + head, tail = os.path.split(new) + if head and tail and not os.path.exists(head): + os.makedirs(head) + + shutil.move(old, new) + + head, tail = os.path.split(old) + if head and tail: + try: + os.removedirs(head) + except OSError: + pass + + +def is_local(path): + """ + Return True if path is within sys.prefix, if we're running in a virtualenv. + + If we're not in a virtualenv, all paths are considered "local." + + """ + if not running_under_virtualenv(): + return True + return normalize_path(path).startswith(normalize_path(sys.prefix)) + + +def dist_is_local(dist): + """ + Return True if given Distribution object is installed locally + (i.e. within current virtualenv). + + Always True if we're not in a virtualenv. + + """ + return is_local(dist_location(dist)) + + +def dist_in_usersite(dist): + """ + Return True if given Distribution is installed in user site. + """ + norm_path = normalize_path(dist_location(dist)) + return norm_path.startswith(normalize_path(user_site)) + + +def dist_in_site_packages(dist): + """ + Return True if given Distribution is installed in + sysconfig.get_python_lib(). + """ + return normalize_path( + dist_location(dist) + ).startswith(normalize_path(site_packages)) + + +def dist_is_editable(dist): + """Is distribution an editable install?""" + for path_item in sys.path: + egg_link = os.path.join(path_item, dist.project_name + '.egg-link') + if os.path.isfile(egg_link): + return True + return False + + +def get_installed_distributions(local_only=True, + skip=stdlib_pkgs, + include_editables=True, + editables_only=False, + user_only=False): + """ + Return a list of installed Distribution objects. + + If ``local_only`` is True (default), only return installations + local to the current virtualenv, if in a virtualenv. + + ``skip`` argument is an iterable of lower-case project names to + ignore; defaults to stdlib_pkgs + + If ``include_editables`` is False, don't report editables. + + If ``editables_only`` is True , only report editables. + + If ``user_only`` is True , only report installations in the user + site directory. + + """ + if local_only: + local_test = dist_is_local + else: + def local_test(d): + return True + + if include_editables: + def editable_test(d): + return True + else: + def editable_test(d): + return not dist_is_editable(d) + + if editables_only: + def editables_only_test(d): + return dist_is_editable(d) + else: + def editables_only_test(d): + return True + + if user_only: + user_test = dist_in_usersite + else: + def user_test(d): + return True + + return [d for d in pkg_resources.working_set + if local_test(d) and + d.key not in skip and + editable_test(d) and + editables_only_test(d) and + user_test(d) + ] + + +def egg_link_path(dist): + """ + Return the path for the .egg-link file if it exists, otherwise, None. + + There's 3 scenarios: + 1) not in a virtualenv + try to find in site.USER_SITE, then site_packages + 2) in a no-global virtualenv + try to find in site_packages + 3) in a yes-global virtualenv + try to find in site_packages, then site.USER_SITE + (don't look in global location) + + For #1 and #3, there could be odd cases, where there's an egg-link in 2 + locations. + + This method will just return the first one found. + """ + sites = [] + if running_under_virtualenv(): + if virtualenv_no_global(): + sites.append(site_packages) + else: + sites.append(site_packages) + if user_site: + sites.append(user_site) + else: + if user_site: + sites.append(user_site) + sites.append(site_packages) + + for site in sites: + egglink = os.path.join(site, dist.project_name) + '.egg-link' + if os.path.isfile(egglink): + return egglink + + +def dist_location(dist): + """ + Get the site-packages location of this distribution. Generally + this is dist.location, except in the case of develop-installed + packages, where dist.location is the source code location, and we + want to know where the egg-link file is. + + """ + egg_link = egg_link_path(dist) + if egg_link: + return egg_link + return dist.location + + +def current_umask(): + """Get the current umask which involves having to set it temporarily.""" + mask = os.umask(0) + os.umask(mask) + return mask + + +def unzip_file(filename, location, flatten=True): + """ + Unzip the file (with path `filename`) to the destination `location`. All + files are written based on system defaults and umask (i.e. permissions are + not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + zipfp = open(filename, 'rb') + try: + zip = zipfile.ZipFile(zipfp, allowZip64=True) + leading = has_leading_dir(zip.namelist()) and flatten + for info in zip.infolist(): + name = info.filename + data = zip.read(name) + fn = name + if leading: + fn = split_leading_dir(name)[1] + fn = os.path.join(location, fn) + dir = os.path.dirname(fn) + if fn.endswith('/') or fn.endswith('\\'): + # A directory + ensure_dir(fn) + else: + ensure_dir(dir) + fp = open(fn, 'wb') + try: + fp.write(data) + finally: + fp.close() + mode = info.external_attr >> 16 + # if mode and regular file and any execute permissions for + # user/group/world? + if mode and stat.S_ISREG(mode) and mode & 0o111: + # make dest file have execute for user/group/world + # (chmod +x) no-op on windows per python docs + os.chmod(fn, (0o777 - current_umask() | 0o111)) + finally: + zipfp.close() + + +def untar_file(filename, location): + """ + Untar the file (with path `filename`) to the destination `location`. + All files are written based on system defaults and umask (i.e. permissions + are not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): + mode = 'r:gz' + elif filename.lower().endswith(BZ2_EXTENSIONS): + mode = 'r:bz2' + elif filename.lower().endswith(XZ_EXTENSIONS): + mode = 'r:xz' + elif filename.lower().endswith('.tar'): + mode = 'r' + else: + logger.warning( + 'Cannot determine compression type for file %s', filename, + ) + mode = 'r:*' + tar = tarfile.open(filename, mode) + try: + # note: python<=2.5 doesn't seem to know about pax headers, filter them + leading = has_leading_dir([ + member.name for member in tar.getmembers() + if member.name != 'pax_global_header' + ]) + for member in tar.getmembers(): + fn = member.name + if fn == 'pax_global_header': + continue + if leading: + fn = split_leading_dir(fn)[1] + path = os.path.join(location, fn) + if member.isdir(): + ensure_dir(path) + elif member.issym(): + try: + tar._extract_member(member, path) + except Exception as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + 'In the tar file %s the member %s is invalid: %s', + filename, member.name, exc, + ) + continue + else: + try: + fp = tar.extractfile(member) + except (KeyError, AttributeError) as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + 'In the tar file %s the member %s is invalid: %s', + filename, member.name, exc, + ) + continue + ensure_dir(os.path.dirname(path)) + with open(path, 'wb') as destfp: + shutil.copyfileobj(fp, destfp) + fp.close() + # Update the timestamp (useful for cython compiled files) + tar.utime(member, path) + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + # make dest file have execute for user/group/world + # no-op on windows per python docs + os.chmod(path, (0o777 - current_umask() | 0o111)) + finally: + tar.close() + + +def unpack_file(filename, location, content_type, link): + filename = os.path.realpath(filename) + if (content_type == 'application/zip' or + filename.lower().endswith(ZIP_EXTENSIONS) or + zipfile.is_zipfile(filename)): + unzip_file( + filename, + location, + flatten=not filename.endswith('.whl') + ) + elif (content_type == 'application/x-gzip' or + tarfile.is_tarfile(filename) or + filename.lower().endswith( + TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS)): + untar_file(filename, location) + elif (content_type and content_type.startswith('text/html') and + is_svn_page(file_contents(filename))): + # We don't really care about this + from pip._internal.vcs.subversion import Subversion + Subversion('svn+' + link.url).unpack(location) + else: + # FIXME: handle? + # FIXME: magic signatures? + logger.critical( + 'Cannot unpack file %s (downloaded from %s, content-type: %s); ' + 'cannot detect archive format', + filename, location, content_type, + ) + raise InstallationError( + 'Cannot determine archive format of %s' % location + ) + + +def call_subprocess(cmd, show_stdout=True, cwd=None, + on_returncode='raise', + command_desc=None, + extra_environ=None, unset_environ=None, spinner=None): + """ + Args: + unset_environ: an iterable of environment variable names to unset + prior to calling subprocess.Popen(). + """ + if unset_environ is None: + unset_environ = [] + # This function's handling of subprocess output is confusing and I + # previously broke it terribly, so as penance I will write a long comment + # explaining things. + # + # The obvious thing that affects output is the show_stdout= + # kwarg. show_stdout=True means, let the subprocess write directly to our + # stdout. Even though it is nominally the default, it is almost never used + # inside pip (and should not be used in new code without a very good + # reason); as of 2016-02-22 it is only used in a few places inside the VCS + # wrapper code. Ideally we should get rid of it entirely, because it + # creates a lot of complexity here for a rarely used feature. + # + # Most places in pip set show_stdout=False. What this means is: + # - We connect the child stdout to a pipe, which we read. + # - By default, we hide the output but show a spinner -- unless the + # subprocess exits with an error, in which case we show the output. + # - If the --verbose option was passed (= loglevel is DEBUG), then we show + # the output unconditionally. (But in this case we don't want to show + # the output a second time if it turns out that there was an error.) + # + # stderr is always merged with stdout (even if show_stdout=True). + if show_stdout: + stdout = None + else: + stdout = subprocess.PIPE + if command_desc is None: + cmd_parts = [] + for part in cmd: + if ' ' in part or '\n' in part or '"' in part or "'" in part: + part = '"%s"' % part.replace('"', '\\"') + cmd_parts.append(part) + command_desc = ' '.join(cmd_parts) + logger.debug("Running command %s", command_desc) + env = os.environ.copy() + if extra_environ: + env.update(extra_environ) + for name in unset_environ: + env.pop(name, None) + try: + proc = subprocess.Popen( + cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, + stdout=stdout, cwd=cwd, env=env, + ) + proc.stdin.close() + except Exception as exc: + logger.critical( + "Error %s while executing command %s", exc, command_desc, + ) + raise + all_output = [] + if stdout is not None: + while True: + line = console_to_str(proc.stdout.readline()) + if not line: + break + line = line.rstrip() + all_output.append(line + '\n') + if logger.getEffectiveLevel() <= std_logging.DEBUG: + # Show the line immediately + logger.debug(line) + else: + # Update the spinner + if spinner is not None: + spinner.spin() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() + if spinner is not None: + if proc.returncode: + spinner.finish("error") + else: + spinner.finish("done") + if proc.returncode: + if on_returncode == 'raise': + if (logger.getEffectiveLevel() > std_logging.DEBUG and + not show_stdout): + logger.info( + 'Complete output from command %s:', command_desc, + ) + logger.info( + ''.join(all_output) + + '\n----------------------------------------' + ) + raise InstallationError( + 'Command "%s" failed with error code %s in %s' + % (command_desc, proc.returncode, cwd)) + elif on_returncode == 'warn': + logger.warning( + 'Command "%s" had error code %s in %s', + command_desc, proc.returncode, cwd, + ) + elif on_returncode == 'ignore': + pass + else: + raise ValueError('Invalid value: on_returncode=%s' % + repr(on_returncode)) + if not show_stdout: + return ''.join(all_output) + + +def read_text_file(filename): + """Return the contents of *filename*. + + Try to decode the file contents with utf-8, the preferred system encoding + (e.g., cp1252 on some Windows machines), and latin1, in that order. + Decoding a byte string with latin1 will never raise an error. In the worst + case, the returned string will contain some garbage characters. + + """ + with open(filename, 'rb') as fp: + data = fp.read() + + encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1'] + for enc in encodings: + try: + data = data.decode(enc) + except UnicodeDecodeError: + continue + break + + assert type(data) != bytes # Latin1 should have worked. + return data + + +def _make_build_dir(build_dir): + os.makedirs(build_dir) + write_delete_marker_file(build_dir) + + +class FakeFile(object): + """Wrap a list of lines in an object with readline() to make + ConfigParser happy.""" + def __init__(self, lines): + self._gen = (l for l in lines) + + def readline(self): + try: + try: + return next(self._gen) + except NameError: + return self._gen.next() + except StopIteration: + return '' + + def __iter__(self): + return self._gen + + +class StreamWrapper(StringIO): + + @classmethod + def from_stream(cls, orig_stream): + cls.orig_stream = orig_stream + return cls() + + # compileall.compile_dir() needs stdout.encoding to print to stdout + @property + def encoding(self): + return self.orig_stream.encoding + + +@contextlib.contextmanager +def captured_output(stream_name): + """Return a context manager used by captured_stdout/stdin/stderr + that temporarily replaces the sys stream *stream_name* with a StringIO. + + Taken from Lib/support/__init__.py in the CPython repo. + """ + orig_stdout = getattr(sys, stream_name) + setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) + try: + yield getattr(sys, stream_name) + finally: + setattr(sys, stream_name, orig_stdout) + + +def captured_stdout(): + """Capture the output of sys.stdout: + + with captured_stdout() as stdout: + print('hello') + self.assertEqual(stdout.getvalue(), 'hello\n') + + Taken from Lib/support/__init__.py in the CPython repo. + """ + return captured_output('stdout') + + +class cached_property(object): + """A property that is only computed once per instance and then replaces + itself with an ordinary attribute. Deleting the attribute resets the + property. + + Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175 + """ + + def __init__(self, func): + self.__doc__ = getattr(func, '__doc__') + self.func = func + + def __get__(self, obj, cls): + if obj is None: + # We're being accessed from the class itself, not from an object + return self + value = obj.__dict__[self.func.__name__] = self.func(obj) + return value + + +def get_installed_version(dist_name, working_set=None): + """Get the installed version of dist_name avoiding pkg_resources cache""" + # Create a requirement that we'll look for inside of setuptools. + req = pkg_resources.Requirement.parse(dist_name) + + if working_set is None: + # We want to avoid having this cached, so we need to construct a new + # working set each time. + working_set = pkg_resources.WorkingSet() + + # Get the installed distribution from our working set + dist = working_set.find(req) + + # Check to see if we got an installed distribution or not, if we did + # we want to return it's version. + return dist.version if dist else None + + +def consume(iterator): + """Consume an iterable at C speed.""" + deque(iterator, maxlen=0) + + +# Simulates an enum +def enum(*sequential, **named): + enums = dict(zip(sequential, range(len(sequential))), **named) + reverse = {value: key for key, value in enums.items()} + enums['reverse_mapping'] = reverse + return type('Enum', (), enums) + + +def make_vcs_requirement_url(repo_url, rev, egg_project_name, subdir=None): + """ + Return the URL for a VCS requirement. + + Args: + repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+"). + """ + req = '{}@{}#egg={}'.format(repo_url, rev, egg_project_name) + if subdir: + req += '&subdirectory={}'.format(subdir) + + return req + + +def split_auth_from_netloc(netloc): + """ + Parse out and remove the auth information from a netloc. + + Returns: (netloc, (username, password)). + """ + if '@' not in netloc: + return netloc, (None, None) + + # Split from the right because that's how urllib.parse.urlsplit() + # behaves if more than one @ is present (which can be checked using + # the password attribute of urlsplit()'s return value). + auth, netloc = netloc.rsplit('@', 1) + if ':' in auth: + # Split from the left because that's how urllib.parse.urlsplit() + # behaves if more than one : is present (which again can be checked + # using the password attribute of the return value) + user_pass = tuple(auth.split(':', 1)) + else: + user_pass = auth, None + + return netloc, user_pass + + +def remove_auth_from_url(url): + # Return a copy of url with 'username:password@' removed. + # username/pass params are passed to subversion through flags + # and are not recognized in the url. + + # parsed url + purl = urllib_parse.urlsplit(url) + netloc, user_pass = split_auth_from_netloc(purl.netloc) + + # stripped url + url_pieces = ( + purl.scheme, netloc, purl.path, purl.query, purl.fragment + ) + surl = urllib_parse.urlunsplit(url_pieces) + return surl + + +def protect_pip_from_modification_on_windows(modifying_pip): + """Protection of pip.exe from modification on Windows + + On Windows, any operation modifying pip should be run as: + python -m pip ... + """ + pip_names = [ + "pip.exe", + "pip{}.exe".format(sys.version_info[0]), + "pip{}.{}.exe".format(*sys.version_info[:2]) + ] + + # See https://github.com/pypa/pip/issues/1299 for more discussion + should_show_use_python_msg = ( + modifying_pip and + WINDOWS and + os.path.basename(sys.argv[0]) in pip_names + ) + + if should_show_use_python_msg: + new_command = [ + sys.executable, "-m", "pip" + ] + sys.argv[1:] + raise CommandError( + 'To modify pip, please run the following command:\n{}' + .format(" ".join(new_command)) + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/models.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/models.py new file mode 100644 index 0000000..d5cb80a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/models.py @@ -0,0 +1,40 @@ +"""Utilities for defining models +""" + +import operator + + +class KeyBasedCompareMixin(object): + """Provides comparision capabilities that is based on a key + """ + + def __init__(self, key, defining_class): + self._compare_key = key + self._defining_class = defining_class + + def __hash__(self): + return hash(self._compare_key) + + def __lt__(self, other): + return self._compare(other, operator.__lt__) + + def __le__(self, other): + return self._compare(other, operator.__le__) + + def __gt__(self, other): + return self._compare(other, operator.__gt__) + + def __ge__(self, other): + return self._compare(other, operator.__ge__) + + def __eq__(self, other): + return self._compare(other, operator.__eq__) + + def __ne__(self, other): + return self._compare(other, operator.__ne__) + + def _compare(self, other, method): + if not isinstance(other, self._defining_class): + return NotImplemented + + return method(self._compare_key, other._compare_key) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/outdated.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/outdated.py new file mode 100644 index 0000000..5bfbfe1 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/outdated.py @@ -0,0 +1,154 @@ +from __future__ import absolute_import + +import datetime +import json +import logging +import os.path +import sys + +from pip._vendor import lockfile, pkg_resources +from pip._vendor.packaging import version as packaging_version + +from pip._internal.index import PackageFinder +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.misc import ensure_dir, get_installed_version + +SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" + + +logger = logging.getLogger(__name__) + + +class SelfCheckState(object): + def __init__(self, cache_dir): + self.state = {} + self.statefile_path = None + + # Try to load the existing state + if cache_dir: + self.statefile_path = os.path.join(cache_dir, "selfcheck.json") + try: + with open(self.statefile_path) as statefile: + self.state = json.load(statefile)[sys.prefix] + except (IOError, ValueError, KeyError): + # Explicitly suppressing exceptions, since we don't want to + # error out if the cache file is invalid. + pass + + def save(self, pypi_version, current_time): + # If we do not have a path to cache in, don't bother saving. + if not self.statefile_path: + return + + # Check to make sure that we own the directory + if not check_path_owner(os.path.dirname(self.statefile_path)): + return + + # Now that we've ensured the directory is owned by this user, we'll go + # ahead and make sure that all our directories are created. + ensure_dir(os.path.dirname(self.statefile_path)) + + # Attempt to write out our version check file + with lockfile.LockFile(self.statefile_path): + if os.path.exists(self.statefile_path): + with open(self.statefile_path) as statefile: + state = json.load(statefile) + else: + state = {} + + state[sys.prefix] = { + "last_check": current_time.strftime(SELFCHECK_DATE_FMT), + "pypi_version": pypi_version, + } + + with open(self.statefile_path, "w") as statefile: + json.dump(state, statefile, sort_keys=True, + separators=(",", ":")) + + +def was_installed_by_pip(pkg): + """Checks whether pkg was installed by pip + + This is used not to display the upgrade message when pip is in fact + installed by system package manager, such as dnf on Fedora. + """ + try: + dist = pkg_resources.get_distribution(pkg) + return (dist.has_metadata('INSTALLER') and + 'pip' in dist.get_metadata_lines('INSTALLER')) + except pkg_resources.DistributionNotFound: + return False + + +def pip_version_check(session, options): + """Check for an update for pip. + + Limit the frequency of checks to once per week. State is stored either in + the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix + of the pip script path. + """ + installed_version = get_installed_version("pip") + if not installed_version: + return + + pip_version = packaging_version.parse(installed_version) + pypi_version = None + + try: + state = SelfCheckState(cache_dir=options.cache_dir) + + current_time = datetime.datetime.utcnow() + # Determine if we need to refresh the state + if "last_check" in state.state and "pypi_version" in state.state: + last_check = datetime.datetime.strptime( + state.state["last_check"], + SELFCHECK_DATE_FMT + ) + if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: + pypi_version = state.state["pypi_version"] + + # Refresh the version if we need to or just see if we need to warn + if pypi_version is None: + # Lets use PackageFinder to see what the latest pip version is + finder = PackageFinder( + find_links=options.find_links, + index_urls=[options.index_url] + options.extra_index_urls, + allow_all_prereleases=False, # Explicitly set to False + trusted_hosts=options.trusted_hosts, + process_dependency_links=options.process_dependency_links, + session=session, + ) + all_candidates = finder.find_all_candidates("pip") + if not all_candidates: + return + pypi_version = str( + max(all_candidates, key=lambda c: c.version).version + ) + + # save that we've performed a check + state.save(pypi_version, current_time) + + remote_version = packaging_version.parse(pypi_version) + + # Determine if our pypi_version is older + if (pip_version < remote_version and + pip_version.base_version != remote_version.base_version and + was_installed_by_pip('pip')): + # Advise "python -m pip" on Windows to avoid issues + # with overwriting pip.exe. + if WINDOWS: + pip_cmd = "python -m pip" + else: + pip_cmd = "pip" + logger.warning( + "You are using pip version %s, however version %s is " + "available.\nYou should consider upgrading via the " + "'%s install --upgrade pip' command.", + pip_version, pypi_version, pip_cmd + ) + except Exception: + logger.debug( + "There was an error checking the latest version of pip", + exc_info=True, + ) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/packaging.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/packaging.py new file mode 100644 index 0000000..c43142f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/packaging.py @@ -0,0 +1,75 @@ +from __future__ import absolute_import + +import logging +import sys +from email.parser import FeedParser # type: ignore + +from pip._vendor import pkg_resources +from pip._vendor.packaging import specifiers, version + +from pip._internal import exceptions +from pip._internal.utils.misc import display_path + +logger = logging.getLogger(__name__) + + +def check_requires_python(requires_python): + """ + Check if the python version in use match the `requires_python` specifier. + + Returns `True` if the version of python in use matches the requirement. + Returns `False` if the version of python in use does not matches the + requirement. + + Raises an InvalidSpecifier if `requires_python` have an invalid format. + """ + if requires_python is None: + # The package provides no information + return True + requires_python_specifier = specifiers.SpecifierSet(requires_python) + + # We only use major.minor.micro + python_version = version.parse('.'.join(map(str, sys.version_info[:3]))) + return python_version in requires_python_specifier + + +def get_metadata(dist): + if (isinstance(dist, pkg_resources.DistInfoDistribution) and + dist.has_metadata('METADATA')): + metadata = dist.get_metadata('METADATA') + elif dist.has_metadata('PKG-INFO'): + metadata = dist.get_metadata('PKG-INFO') + else: + logger.warning("No metadata found in %s", display_path(dist.location)) + metadata = '' + + feed_parser = FeedParser() + feed_parser.feed(metadata) + return feed_parser.close() + + +def check_dist_requires_python(dist): + pkg_info_dict = get_metadata(dist) + requires_python = pkg_info_dict.get('Requires-Python') + try: + if not check_requires_python(requires_python): + raise exceptions.UnsupportedPythonVersion( + "%s requires Python '%s' but the running Python is %s" % ( + dist.project_name, + requires_python, + '.'.join(map(str, sys.version_info[:3])),) + ) + except specifiers.InvalidSpecifier as e: + logger.warning( + "Package %s has an invalid Requires-Python entry %s - %s", + dist.project_name, requires_python, e, + ) + return + + +def get_installer(dist): + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + return line.strip() + return '' diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/setuptools_build.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/setuptools_build.py new file mode 100644 index 0000000..03973e9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/setuptools_build.py @@ -0,0 +1,8 @@ +# Shim to wrap setup.py invocation with setuptools +SETUPTOOLS_SHIM = ( + "import setuptools, tokenize;__file__=%r;" + "f=getattr(tokenize, 'open', open)(__file__);" + "code=f.read().replace('\\r\\n', '\\n');" + "f.close();" + "exec(compile(code, __file__, 'exec'))" +) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/temp_dir.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/temp_dir.py new file mode 100644 index 0000000..edc506b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/temp_dir.py @@ -0,0 +1,82 @@ +from __future__ import absolute_import + +import logging +import os.path +import tempfile + +from pip._internal.utils.misc import rmtree + +logger = logging.getLogger(__name__) + + +class TempDirectory(object): + """Helper class that owns and cleans up a temporary directory. + + This class can be used as a context manager or as an OO representation of a + temporary directory. + + Attributes: + path + Location to the created temporary directory or None + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + Methods: + create() + Creates a temporary directory and stores its path in the path + attribute. + cleanup() + Deletes the temporary directory and sets path attribute to None + + When used as a context manager, a temporary directory is created on + entering the context and, if the delete attribute is True, on exiting the + context the created directory is deleted. + """ + + def __init__(self, path=None, delete=None, kind="temp"): + super(TempDirectory, self).__init__() + + if path is None and delete is None: + # If we were not given an explicit directory, and we were not given + # an explicit delete option, then we'll default to deleting. + delete = True + + self.path = path + self.delete = delete + self.kind = kind + + def __repr__(self): + return "<{} {!r}>".format(self.__class__.__name__, self.path) + + def __enter__(self): + self.create() + return self + + def __exit__(self, exc, value, tb): + if self.delete: + self.cleanup() + + def create(self): + """Create a temporary directory and store it's path in self.path + """ + if self.path is not None: + logger.debug( + "Skipped creation of temporary directory: {}".format(self.path) + ) + return + # We realpath here because some systems have their default tmpdir + # symlinked to another directory. This tends to confuse build + # scripts, so we canonicalize the path by traversing potential + # symlinks here. + self.path = os.path.realpath( + tempfile.mkdtemp(prefix="pip-{}-".format(self.kind)) + ) + logger.debug("Created temporary directory: {}".format(self.path)) + + def cleanup(self): + """Remove the temporary directory created and reset state + """ + if self.path is not None and os.path.exists(self.path): + rmtree(self.path) + self.path = None diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py new file mode 100644 index 0000000..e085cdf --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/typing.py @@ -0,0 +1,29 @@ +"""For neatly implementing static typing in pip. + +`mypy` - the static type analysis tool we use - uses the `typing` module, which +provides core functionality fundamental to mypy's functioning. + +Generally, `typing` would be imported at runtime and used in that fashion - +it acts as a no-op at runtime and does not have any run-time overhead by +design. + +As it turns out, `typing` is not vendorable - it uses separate sources for +Python 2/Python 3. Thus, this codebase can not expect it to be present. +To work around this, mypy allows the typing import to be behind a False-y +optional to prevent it from running at runtime and type-comments can be used +to remove the need for the types to be accessible directly during runtime. + +This module provides the False-y guard in a nicely named fashion so that a +curious maintainer can reach here to read this. + +In pip, all static-typing related imports should be guarded as follows: + + from pip._internal.utils.typing import MYPY_CHECK_RUNNING + + if MYPY_CHECK_RUNNING: + from typing import ... # noqa: F401 + +Ref: https://github.com/python/mypy/issues/3216 +""" + +MYPY_CHECK_RUNNING = False diff --git a/venv/lib/python3.7/site-packages/pip/_internal/utils/ui.py b/venv/lib/python3.7/site-packages/pip/_internal/utils/ui.py new file mode 100644 index 0000000..6bab904 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/utils/ui.py @@ -0,0 +1,421 @@ +from __future__ import absolute_import, division + +import contextlib +import itertools +import logging +import sys +import time +from signal import SIGINT, default_int_handler, signal + +from pip._vendor import six +from pip._vendor.progress.bar import ( + Bar, ChargingBar, FillingCirclesBar, FillingSquaresBar, IncrementalBar, + ShadyBar, +) +from pip._vendor.progress.helpers import HIDE_CURSOR, SHOW_CURSOR, WritelnMixin +from pip._vendor.progress.spinner import Spinner + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation +from pip._internal.utils.misc import format_size +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any # noqa: F401 + +try: + from pip._vendor import colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None + +logger = logging.getLogger(__name__) + + +def _select_progress_class(preferred, fallback): + encoding = getattr(preferred.file, "encoding", None) + + # If we don't know what encoding this file is in, then we'll just assume + # that it doesn't support unicode and use the ASCII bar. + if not encoding: + return fallback + + # Collect all of the possible characters we want to use with the preferred + # bar. + characters = [ + getattr(preferred, "empty_fill", six.text_type()), + getattr(preferred, "fill", six.text_type()), + ] + characters += list(getattr(preferred, "phases", [])) + + # Try to decode the characters we're using for the bar using the encoding + # of the given file, if this works then we'll assume that we can use the + # fancier bar and if not we'll fall back to the plaintext bar. + try: + six.text_type().join(characters).encode(encoding) + except UnicodeEncodeError: + return fallback + else: + return preferred + + +_BaseBar = _select_progress_class(IncrementalBar, Bar) # type: Any + + +class InterruptibleMixin(object): + """ + Helper to ensure that self.finish() gets called on keyboard interrupt. + + This allows downloads to be interrupted without leaving temporary state + (like hidden cursors) behind. + + This class is similar to the progress library's existing SigIntMixin + helper, but as of version 1.2, that helper has the following problems: + + 1. It calls sys.exit(). + 2. It discards the existing SIGINT handler completely. + 3. It leaves its own handler in place even after an uninterrupted finish, + which will have unexpected delayed effects if the user triggers an + unrelated keyboard interrupt some time after a progress-displaying + download has already completed, for example. + """ + + def __init__(self, *args, **kwargs): + """ + Save the original SIGINT handler for later. + """ + super(InterruptibleMixin, self).__init__(*args, **kwargs) + + self.original_handler = signal(SIGINT, self.handle_sigint) + + # If signal() returns None, the previous handler was not installed from + # Python, and we cannot restore it. This probably should not happen, + # but if it does, we must restore something sensible instead, at least. + # The least bad option should be Python's default SIGINT handler, which + # just raises KeyboardInterrupt. + if self.original_handler is None: + self.original_handler = default_int_handler + + def finish(self): + """ + Restore the original SIGINT handler after finishing. + + This should happen regardless of whether the progress display finishes + normally, or gets interrupted. + """ + super(InterruptibleMixin, self).finish() + signal(SIGINT, self.original_handler) + + def handle_sigint(self, signum, frame): + """ + Call self.finish() before delegating to the original SIGINT handler. + + This handler should only be in place while the progress display is + active. + """ + self.finish() + self.original_handler(signum, frame) + + +class SilentBar(Bar): + + def update(self): + pass + + +class BlueEmojiBar(IncrementalBar): + + suffix = "%(percent)d%%" + bar_prefix = " " + bar_suffix = " " + phases = (u"\U0001F539", u"\U0001F537", u"\U0001F535") # type: Any + + +class DownloadProgressMixin(object): + + def __init__(self, *args, **kwargs): + super(DownloadProgressMixin, self).__init__(*args, **kwargs) + self.message = (" " * (get_indentation() + 2)) + self.message + + @property + def downloaded(self): + return format_size(self.index) + + @property + def download_speed(self): + # Avoid zero division errors... + if self.avg == 0.0: + return "..." + return format_size(1 / self.avg) + "/s" + + @property + def pretty_eta(self): + if self.eta: + return "eta %s" % self.eta_td + return "" + + def iter(self, it, n=1): + for x in it: + yield x + self.next(n) + self.finish() + + +class WindowsMixin(object): + + def __init__(self, *args, **kwargs): + # The Windows terminal does not support the hide/show cursor ANSI codes + # even with colorama. So we'll ensure that hide_cursor is False on + # Windows. + # This call neds to go before the super() call, so that hide_cursor + # is set in time. The base progress bar class writes the "hide cursor" + # code to the terminal in its init, so if we don't set this soon + # enough, we get a "hide" with no corresponding "show"... + if WINDOWS and self.hide_cursor: + self.hide_cursor = False + + super(WindowsMixin, self).__init__(*args, **kwargs) + + # Check if we are running on Windows and we have the colorama module, + # if we do then wrap our file with it. + if WINDOWS and colorama: + self.file = colorama.AnsiToWin32(self.file) + # The progress code expects to be able to call self.file.isatty() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.isatty = lambda: self.file.wrapped.isatty() + # The progress code expects to be able to call self.file.flush() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.flush = lambda: self.file.wrapped.flush() + + +class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin): + + file = sys.stdout + message = "%(percent)d%%" + suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s" + +# NOTE: The "type: ignore" comments on the following classes are there to +# work around https://github.com/python/typing/issues/241 + + +class DefaultDownloadProgressBar(BaseDownloadProgressBar, + _BaseBar): # type: ignore + pass + + +class DownloadSilentBar(BaseDownloadProgressBar, SilentBar): # type: ignore + pass + + +class DownloadIncrementalBar(BaseDownloadProgressBar, # type: ignore + IncrementalBar): + pass + + +class DownloadChargingBar(BaseDownloadProgressBar, # type: ignore + ChargingBar): + pass + + +class DownloadShadyBar(BaseDownloadProgressBar, ShadyBar): # type: ignore + pass + + +class DownloadFillingSquaresBar(BaseDownloadProgressBar, # type: ignore + FillingSquaresBar): + pass + + +class DownloadFillingCirclesBar(BaseDownloadProgressBar, # type: ignore + FillingCirclesBar): + pass + + +class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, # type: ignore + BlueEmojiBar): + pass + + +class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin, WritelnMixin, Spinner): + + file = sys.stdout + suffix = "%(downloaded)s %(download_speed)s" + + def next_phase(self): + if not hasattr(self, "_phaser"): + self._phaser = itertools.cycle(self.phases) + return next(self._phaser) + + def update(self): + message = self.message % self + phase = self.next_phase() + suffix = self.suffix % self + line = ''.join([ + message, + " " if message else "", + phase, + " " if suffix else "", + suffix, + ]) + + self.writeln(line) + + +BAR_TYPES = { + "off": (DownloadSilentBar, DownloadSilentBar), + "on": (DefaultDownloadProgressBar, DownloadProgressSpinner), + "ascii": (DownloadIncrementalBar, DownloadProgressSpinner), + "pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner), + "emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner) +} + + +def DownloadProgressProvider(progress_bar, max=None): + if max is None or max == 0: + return BAR_TYPES[progress_bar][1]().iter + else: + return BAR_TYPES[progress_bar][0](max=max).iter + + +################################################################ +# Generic "something is happening" spinners +# +# We don't even try using progress.spinner.Spinner here because it's actually +# simpler to reimplement from scratch than to coerce their code into doing +# what we need. +################################################################ + +@contextlib.contextmanager +def hidden_cursor(file): + # The Windows terminal does not support the hide/show cursor ANSI codes, + # even via colorama. So don't even try. + if WINDOWS: + yield + # We don't want to clutter the output with control characters if we're + # writing to a file, or if the user is running with --quiet. + # See https://github.com/pypa/pip/issues/3418 + elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: + yield + else: + file.write(HIDE_CURSOR) + try: + yield + finally: + file.write(SHOW_CURSOR) + + +class RateLimiter(object): + def __init__(self, min_update_interval_seconds): + self._min_update_interval_seconds = min_update_interval_seconds + self._last_update = 0 + + def ready(self): + now = time.time() + delta = now - self._last_update + return delta >= self._min_update_interval_seconds + + def reset(self): + self._last_update = time.time() + + +class InteractiveSpinner(object): + def __init__(self, message, file=None, spin_chars="-\\|/", + # Empirically, 8 updates/second looks nice + min_update_interval_seconds=0.125): + self._message = message + if file is None: + file = sys.stdout + self._file = file + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._finished = False + + self._spin_cycle = itertools.cycle(spin_chars) + + self._file.write(" " * get_indentation() + self._message + " ... ") + self._width = 0 + + def _write(self, status): + assert not self._finished + # Erase what we wrote before by backspacing to the beginning, writing + # spaces to overwrite the old text, and then backspacing again + backup = "\b" * self._width + self._file.write(backup + " " * self._width + backup) + # Now we have a blank slate to add our status + self._file.write(status) + self._width = len(status) + self._file.flush() + self._rate_limiter.reset() + + def spin(self): + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._write(next(self._spin_cycle)) + + def finish(self, final_status): + if self._finished: + return + self._write(final_status) + self._file.write("\n") + self._file.flush() + self._finished = True + + +# Used for dumb terminals, non-interactive installs (no tty), etc. +# We still print updates occasionally (once every 60 seconds by default) to +# act as a keep-alive for systems like Travis-CI that take lack-of-output as +# an indication that a task has frozen. +class NonInteractiveSpinner(object): + def __init__(self, message, min_update_interval_seconds=60): + self._message = message + self._finished = False + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._update("started") + + def _update(self, status): + assert not self._finished + self._rate_limiter.reset() + logger.info("%s: %s", self._message, status) + + def spin(self): + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._update("still running...") + + def finish(self, final_status): + if self._finished: + return + self._update("finished with status '%s'" % (final_status,)) + self._finished = True + + +@contextlib.contextmanager +def open_spinner(message): + # Interactive spinner goes directly to sys.stdout rather than being routed + # through the logging system, but it acts like it has level INFO, + # i.e. it's only displayed if we're at level INFO or better. + # Non-interactive spinner goes through the logging system, so it is always + # in sync with logging configuration. + if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: + spinner = InteractiveSpinner(message) + else: + spinner = NonInteractiveSpinner(message) + try: + with hidden_cursor(sys.stdout): + yield spinner + except KeyboardInterrupt: + spinner.finish("canceled") + raise + except Exception: + spinner.finish("error") + raise + else: + spinner.finish("done") diff --git a/venv/lib/python3.7/site-packages/pip/_internal/vcs/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/vcs/__init__.py new file mode 100644 index 0000000..794b35d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/vcs/__init__.py @@ -0,0 +1,509 @@ +"""Handles all VCS (version control) support""" +from __future__ import absolute_import + +import errno +import logging +import os +import shutil +import sys + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import BadCommand +from pip._internal.utils.misc import ( + display_path, backup_dir, call_subprocess, rmtree, ask_path_exists, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict, Optional, Tuple # noqa: F401 + from pip._internal.cli.base_command import Command # noqa: F401 + +__all__ = ['vcs', 'get_src_requirement'] + + +logger = logging.getLogger(__name__) + + +class RevOptions(object): + + """ + Encapsulates a VCS-specific revision to install, along with any VCS + install options. + + Instances of this class should be treated as if immutable. + """ + + def __init__(self, vcs, rev=None, extra_args=None): + """ + Args: + vcs: a VersionControl object. + rev: the name of the revision to install. + extra_args: a list of extra options. + """ + if extra_args is None: + extra_args = [] + + self.extra_args = extra_args + self.rev = rev + self.vcs = vcs + + def __repr__(self): + return '<RevOptions {}: rev={!r}>'.format(self.vcs.name, self.rev) + + @property + def arg_rev(self): + if self.rev is None: + return self.vcs.default_arg_rev + + return self.rev + + def to_args(self): + """ + Return the VCS-specific command arguments. + """ + args = [] + rev = self.arg_rev + if rev is not None: + args += self.vcs.get_base_rev_args(rev) + args += self.extra_args + + return args + + def to_display(self): + if not self.rev: + return '' + + return ' (to revision {})'.format(self.rev) + + def make_new(self, rev): + """ + Make a copy of the current instance, but with a new rev. + + Args: + rev: the name of the revision for the new object. + """ + return self.vcs.make_rev_options(rev, extra_args=self.extra_args) + + +class VcsSupport(object): + _registry = {} # type: Dict[str, Command] + schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn'] + + def __init__(self): + # Register more schemes with urlparse for various version control + # systems + urllib_parse.uses_netloc.extend(self.schemes) + # Python >= 2.7.4, 3.3 doesn't have uses_fragment + if getattr(urllib_parse, 'uses_fragment', None): + urllib_parse.uses_fragment.extend(self.schemes) + super(VcsSupport, self).__init__() + + def __iter__(self): + return self._registry.__iter__() + + @property + def backends(self): + return list(self._registry.values()) + + @property + def dirnames(self): + return [backend.dirname for backend in self.backends] + + @property + def all_schemes(self): + schemes = [] + for backend in self.backends: + schemes.extend(backend.schemes) + return schemes + + def register(self, cls): + if not hasattr(cls, 'name'): + logger.warning('Cannot register VCS %s', cls.__name__) + return + if cls.name not in self._registry: + self._registry[cls.name] = cls + logger.debug('Registered VCS backend: %s', cls.name) + + def unregister(self, cls=None, name=None): + if name in self._registry: + del self._registry[name] + elif cls in self._registry.values(): + del self._registry[cls.name] + else: + logger.warning('Cannot unregister because no class or name given') + + def get_backend_name(self, location): + """ + Return the name of the version control backend if found at given + location, e.g. vcs.get_backend_name('/path/to/vcs/checkout') + """ + for vc_type in self._registry.values(): + if vc_type.controls_location(location): + logger.debug('Determine that %s uses VCS: %s', + location, vc_type.name) + return vc_type.name + return None + + def get_backend(self, name): + name = name.lower() + if name in self._registry: + return self._registry[name] + + def get_backend_from_location(self, location): + vc_type = self.get_backend_name(location) + if vc_type: + return self.get_backend(vc_type) + return None + + +vcs = VcsSupport() + + +class VersionControl(object): + name = '' + dirname = '' + # List of supported schemes for this Version Control + schemes = () # type: Tuple[str, ...] + # Iterable of environment variable names to pass to call_subprocess(). + unset_environ = () # type: Tuple[str, ...] + default_arg_rev = None # type: Optional[str] + + def __init__(self, url=None, *args, **kwargs): + self.url = url + super(VersionControl, self).__init__(*args, **kwargs) + + def get_base_rev_args(self, rev): + """ + Return the base revision arguments for a vcs command. + + Args: + rev: the name of a revision to install. Cannot be None. + """ + raise NotImplementedError + + def make_rev_options(self, rev=None, extra_args=None): + """ + Return a RevOptions object. + + Args: + rev: the name of a revision to install. + extra_args: a list of extra options. + """ + return RevOptions(self, rev, extra_args=extra_args) + + def _is_local_repository(self, repo): + """ + posix absolute paths start with os.path.sep, + win32 ones start with drive (like c:\\folder) + """ + drive, tail = os.path.splitdrive(repo) + return repo.startswith(os.path.sep) or drive + + def export(self, location): + """ + Export the repository at the url to the destination location + i.e. only download the files, without vcs informations + """ + raise NotImplementedError + + def get_netloc_and_auth(self, netloc, scheme): + """ + Parse the repository URL's netloc, and return the new netloc to use + along with auth information. + + Args: + netloc: the original repository URL netloc. + scheme: the repository URL's scheme without the vcs prefix. + + This is mainly for the Subversion class to override, so that auth + information can be provided via the --username and --password options + instead of through the URL. For other subclasses like Git without + such an option, auth information must stay in the URL. + + Returns: (netloc, (username, password)). + """ + return netloc, (None, None) + + def get_url_rev_and_auth(self, url): + """ + Parse the repository URL to use, and return the URL, revision, + and auth info to use. + + Returns: (url, rev, (username, password)). + """ + scheme, netloc, path, query, frag = urllib_parse.urlsplit(url) + if '+' not in scheme: + raise ValueError( + "Sorry, {!r} is a malformed VCS url. " + "The format is <vcs>+<protocol>://<url>, " + "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url) + ) + # Remove the vcs prefix. + scheme = scheme.split('+', 1)[1] + netloc, user_pass = self.get_netloc_and_auth(netloc, scheme) + rev = None + if '@' in path: + path, rev = path.rsplit('@', 1) + url = urllib_parse.urlunsplit((scheme, netloc, path, query, '')) + return url, rev, user_pass + + def make_rev_args(self, username, password): + """ + Return the RevOptions "extra arguments" to use in obtain(). + """ + return [] + + def get_url_rev_options(self, url): + """ + Return the URL and RevOptions object to use in obtain() and in + some cases export(), as a tuple (url, rev_options). + """ + url, rev, user_pass = self.get_url_rev_and_auth(url) + username, password = user_pass + extra_args = self.make_rev_args(username, password) + rev_options = self.make_rev_options(rev, extra_args=extra_args) + + return url, rev_options + + def normalize_url(self, url): + """ + Normalize a URL for comparison by unquoting it and removing any + trailing slash. + """ + return urllib_parse.unquote(url).rstrip('/') + + def compare_urls(self, url1, url2): + """ + Compare two repo URLs for identity, ignoring incidental differences. + """ + return (self.normalize_url(url1) == self.normalize_url(url2)) + + def fetch_new(self, dest, url, rev_options): + """ + Fetch a revision from a repository, in the case that this is the + first fetch from the repository. + + Args: + dest: the directory to fetch the repository to. + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def switch(self, dest, url, rev_options): + """ + Switch the repo at ``dest`` to point to ``URL``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def update(self, dest, url, rev_options): + """ + Update an already-existing repo to the given ``rev_options``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def is_commit_id_equal(self, dest, name): + """ + Return whether the id of the current commit equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + raise NotImplementedError + + def obtain(self, dest): + """ + Install or update in editable mode the package represented by this + VersionControl object. + + Args: + dest: the repository directory in which to install or update. + """ + url, rev_options = self.get_url_rev_options(self.url) + + if not os.path.exists(dest): + self.fetch_new(dest, url, rev_options) + return + + rev_display = rev_options.to_display() + if self.is_repository_directory(dest): + existing_url = self.get_url(dest) + if self.compare_urls(existing_url, url): + logger.debug( + '%s in %s exists, and has correct URL (%s)', + self.repo_name.title(), + display_path(dest), + url, + ) + if not self.is_commit_id_equal(dest, rev_options.rev): + logger.info( + 'Updating %s %s%s', + display_path(dest), + self.repo_name, + rev_display, + ) + self.update(dest, url, rev_options) + else: + logger.info('Skipping because already up-to-date.') + return + + logger.warning( + '%s %s in %s exists with URL %s', + self.name, + self.repo_name, + display_path(dest), + existing_url, + ) + prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', + ('s', 'i', 'w', 'b')) + else: + logger.warning( + 'Directory %s already exists, and is not a %s %s.', + dest, + self.name, + self.repo_name, + ) + prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b')) + + logger.warning( + 'The plan is to install the %s repository %s', + self.name, + url, + ) + response = ask_path_exists('What to do? %s' % prompt[0], prompt[1]) + + if response == 'a': + sys.exit(-1) + + if response == 'w': + logger.warning('Deleting %s', display_path(dest)) + rmtree(dest) + self.fetch_new(dest, url, rev_options) + return + + if response == 'b': + dest_dir = backup_dir(dest) + logger.warning( + 'Backing up %s to %s', display_path(dest), dest_dir, + ) + shutil.move(dest, dest_dir) + self.fetch_new(dest, url, rev_options) + return + + # Do nothing if the response is "i". + if response == 's': + logger.info( + 'Switching %s %s to %s%s', + self.repo_name, + display_path(dest), + url, + rev_display, + ) + self.switch(dest, url, rev_options) + + def unpack(self, location): + """ + Clean up current location and download the url repository + (and vcs infos) into location + """ + if os.path.exists(location): + rmtree(location) + self.obtain(location) + + def get_src_requirement(self, dist, location): + """ + Return a string representing the requirement needed to + redownload the files currently present in location, something + like: + {repository_url}@{revision}#egg={project_name}-{version_identifier} + """ + raise NotImplementedError + + def get_url(self, location): + """ + Return the url used at location + """ + raise NotImplementedError + + def get_revision(self, location): + """ + Return the current commit id of the files at the given location. + """ + raise NotImplementedError + + def run_command(self, cmd, show_stdout=True, cwd=None, + on_returncode='raise', + command_desc=None, + extra_environ=None, spinner=None): + """ + Run a VCS subcommand + This is simply a wrapper around call_subprocess that adds the VCS + command name, and checks that the VCS is available + """ + cmd = [self.name] + cmd + try: + return call_subprocess(cmd, show_stdout, cwd, + on_returncode, + command_desc, extra_environ, + unset_environ=self.unset_environ, + spinner=spinner) + except OSError as e: + # errno.ENOENT = no such file or directory + # In other words, the VCS executable isn't available + if e.errno == errno.ENOENT: + raise BadCommand( + 'Cannot find command %r - do you have ' + '%r installed and in your ' + 'PATH?' % (self.name, self.name)) + else: + raise # re-raise exception if a different error occurred + + @classmethod + def is_repository_directory(cls, path): + """ + Return whether a directory path is a repository directory. + """ + logger.debug('Checking in %s for %s (%s)...', + path, cls.dirname, cls.name) + return os.path.exists(os.path.join(path, cls.dirname)) + + @classmethod + def controls_location(cls, location): + """ + Check if a location is controlled by the vcs. + It is meant to be overridden to implement smarter detection + mechanisms for specific vcs. + + This can do more than is_repository_directory() alone. For example, + the Git override checks that Git is actually available. + """ + return cls.is_repository_directory(location) + + +def get_src_requirement(dist, location): + version_control = vcs.get_backend_from_location(location) + if version_control: + try: + return version_control().get_src_requirement(dist, + location) + except BadCommand: + logger.warning( + 'cannot determine version of editable source in %s ' + '(%s command not found in path)', + location, + version_control.name, + ) + return dist.as_requirement() + logger.warning( + 'cannot determine version of editable source in %s (is not SVN ' + 'checkout, Git clone, Mercurial clone or Bazaar branch)', + location, + ) + return dist.as_requirement() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/vcs/bazaar.py b/venv/lib/python3.7/site-packages/pip/_internal/vcs/bazaar.py new file mode 100644 index 0000000..3cc66c9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/vcs/bazaar.py @@ -0,0 +1,112 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.download import path_to_url +from pip._internal.utils.misc import ( + display_path, make_vcs_requirement_url, rmtree, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.vcs import VersionControl, vcs + +logger = logging.getLogger(__name__) + + +class Bazaar(VersionControl): + name = 'bzr' + dirname = '.bzr' + repo_name = 'branch' + schemes = ( + 'bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp', + 'bzr+lp', + ) + + def __init__(self, url=None, *args, **kwargs): + super(Bazaar, self).__init__(url, *args, **kwargs) + # This is only needed for python <2.7.5 + # Register lp but do not expose as a scheme to support bzr+lp. + if getattr(urllib_parse, 'uses_fragment', None): + urllib_parse.uses_fragment.extend(['lp']) + + def get_base_rev_args(self, rev): + return ['-r', rev] + + def export(self, location): + """ + Export the Bazaar repository at the url to the destination location + """ + # Remove the location to make sure Bazaar can export it correctly + if os.path.exists(location): + rmtree(location) + + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + + self.run_command( + ['export', location], + cwd=temp_dir.path, show_stdout=False, + ) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Checking out %s%s to %s', + url, + rev_display, + display_path(dest), + ) + cmd_args = ['branch', '-q'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) + + def switch(self, dest, url, rev_options): + self.run_command(['switch', url], cwd=dest) + + def update(self, dest, url, rev_options): + cmd_args = ['pull', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def get_url_rev_and_auth(self, url): + # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it + url, rev, user_pass = super(Bazaar, self).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'bzr+' + url + return url, rev, user_pass + + def get_url(self, location): + urls = self.run_command(['info'], show_stdout=False, cwd=location) + for line in urls.splitlines(): + line = line.strip() + for x in ('checkout of branch: ', + 'parent branch: '): + if line.startswith(x): + repo = line.split(x)[1] + if self._is_local_repository(repo): + return path_to_url(repo) + return repo + return None + + def get_revision(self, location): + revision = self.run_command( + ['revno'], show_stdout=False, cwd=location, + ) + return revision.splitlines()[-1] + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if not repo: + return None + if not repo.lower().startswith('bzr:'): + repo = 'bzr+' + repo + current_rev = self.get_revision(location) + egg_project_name = dist.egg_name().split('-', 1)[0] + return make_vcs_requirement_url(repo, current_rev, egg_project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Bazaar) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/vcs/git.py b/venv/lib/python3.7/site-packages/pip/_internal/vcs/git.py new file mode 100644 index 0000000..9778539 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/vcs/git.py @@ -0,0 +1,346 @@ +from __future__ import absolute_import + +import logging +import os.path +import re + +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.exceptions import BadCommand +from pip._internal.utils.compat import samefile +from pip._internal.utils.misc import display_path, make_vcs_requirement_url +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.vcs import VersionControl, vcs + +urlsplit = urllib_parse.urlsplit +urlunsplit = urllib_parse.urlunsplit + + +logger = logging.getLogger(__name__) + + +HASH_REGEX = re.compile('[a-fA-F0-9]{40}') + + +def looks_like_hash(sha): + return bool(HASH_REGEX.match(sha)) + + +class Git(VersionControl): + name = 'git' + dirname = '.git' + repo_name = 'clone' + schemes = ( + 'git', 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file', + ) + # Prevent the user's environment variables from interfering with pip: + # https://github.com/pypa/pip/issues/1130 + unset_environ = ('GIT_DIR', 'GIT_WORK_TREE') + default_arg_rev = 'HEAD' + + def __init__(self, url=None, *args, **kwargs): + + # Works around an apparent Git bug + # (see https://article.gmane.org/gmane.comp.version-control.git/146500) + if url: + scheme, netloc, path, query, fragment = urlsplit(url) + if scheme.endswith('file'): + initial_slashes = path[:-len(path.lstrip('/'))] + newpath = ( + initial_slashes + + urllib_request.url2pathname(path) + .replace('\\', '/').lstrip('/') + ) + url = urlunsplit((scheme, netloc, newpath, query, fragment)) + after_plus = scheme.find('+') + 1 + url = scheme[:after_plus] + urlunsplit( + (scheme[after_plus:], netloc, newpath, query, fragment), + ) + + super(Git, self).__init__(url, *args, **kwargs) + + def get_base_rev_args(self, rev): + return [rev] + + def get_git_version(self): + VERSION_PFX = 'git version ' + version = self.run_command(['version'], show_stdout=False) + if version.startswith(VERSION_PFX): + version = version[len(VERSION_PFX):].split()[0] + else: + version = '' + # get first 3 positions of the git version becasue + # on windows it is x.y.z.windows.t, and this parses as + # LegacyVersion which always smaller than a Version. + version = '.'.join(version.split('.')[:3]) + return parse_version(version) + + def get_branch(self, location): + """ + Return the current branch, or None if HEAD isn't at a branch + (e.g. detached HEAD). + """ + args = ['rev-parse', '--abbrev-ref', 'HEAD'] + output = self.run_command(args, show_stdout=False, cwd=location) + branch = output.strip() + + if branch == 'HEAD': + return None + + return branch + + def export(self, location): + """Export the Git repository at the url to the destination location""" + if not location.endswith('/'): + location = location + '/' + + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + self.run_command( + ['checkout-index', '-a', '-f', '--prefix', location], + show_stdout=False, cwd=temp_dir.path + ) + + def get_revision_sha(self, dest, rev): + """ + Return (sha_or_none, is_branch), where sha_or_none is a commit hash + if the revision names a remote branch or tag, otherwise None. + + Args: + dest: the repository directory. + rev: the revision name. + """ + # Pass rev to pre-filter the list. + output = self.run_command(['show-ref', rev], cwd=dest, + show_stdout=False, on_returncode='ignore') + refs = {} + for line in output.strip().splitlines(): + try: + sha, ref = line.split() + except ValueError: + # Include the offending line to simplify troubleshooting if + # this error ever occurs. + raise ValueError('unexpected show-ref line: {!r}'.format(line)) + + refs[ref] = sha + + branch_ref = 'refs/remotes/origin/{}'.format(rev) + tag_ref = 'refs/tags/{}'.format(rev) + + sha = refs.get(branch_ref) + if sha is not None: + return (sha, True) + + sha = refs.get(tag_ref) + + return (sha, False) + + def resolve_revision(self, dest, url, rev_options): + """ + Resolve a revision to a new RevOptions object with the SHA1 of the + branch, tag, or ref if found. + + Args: + rev_options: a RevOptions object. + """ + rev = rev_options.arg_rev + sha, is_branch = self.get_revision_sha(dest, rev) + + if sha is not None: + rev_options = rev_options.make_new(sha) + rev_options.branch_name = rev if is_branch else None + + return rev_options + + # Do not show a warning for the common case of something that has + # the form of a Git commit hash. + if not looks_like_hash(rev): + logger.warning( + "Did not find branch or tag '%s', assuming revision or ref.", + rev, + ) + + if not rev.startswith('refs/'): + return rev_options + + # If it looks like a ref, we have to fetch it explicitly. + self.run_command( + ['fetch', '-q', url] + rev_options.to_args(), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + sha = self.get_revision(dest, rev='FETCH_HEAD') + rev_options = rev_options.make_new(sha) + + return rev_options + + def is_commit_id_equal(self, dest, name): + """ + Return whether the current commit hash equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + if not name: + # Then avoid an unnecessary subprocess call. + return False + + return self.get_revision(dest) == name + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Cloning %s%s to %s', url, rev_display, display_path(dest), + ) + self.run_command(['clone', '-q', url, dest]) + + if rev_options.rev: + # Then a specific revision was requested. + rev_options = self.resolve_revision(dest, url, rev_options) + branch_name = getattr(rev_options, 'branch_name', None) + if branch_name is None: + # Only do a checkout if the current commit id doesn't match + # the requested revision. + if not self.is_commit_id_equal(dest, rev_options.rev): + cmd_args = ['checkout', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + elif self.get_branch(dest) != branch_name: + # Then a specific branch was requested, and that branch + # is not yet checked out. + track_branch = 'origin/{}'.format(branch_name) + cmd_args = [ + 'checkout', '-b', branch_name, '--track', track_branch, + ] + self.run_command(cmd_args, cwd=dest) + + #: repo may contain submodules + self.update_submodules(dest) + + def switch(self, dest, url, rev_options): + self.run_command(['config', 'remote.origin.url', url], cwd=dest) + cmd_args = ['checkout', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + self.update_submodules(dest) + + def update(self, dest, url, rev_options): + # First fetch changes from the default remote + if self.get_git_version() >= parse_version('1.9.0'): + # fetch tags in addition to everything else + self.run_command(['fetch', '-q', '--tags'], cwd=dest) + else: + self.run_command(['fetch', '-q'], cwd=dest) + # Then reset to wanted revision (maybe even origin/master) + rev_options = self.resolve_revision(dest, url, rev_options) + cmd_args = ['reset', '--hard', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + #: update submodules + self.update_submodules(dest) + + def get_url(self, location): + """Return URL of the first remote encountered.""" + remotes = self.run_command( + ['config', '--get-regexp', r'remote\..*\.url'], + show_stdout=False, cwd=location, + ) + remotes = remotes.splitlines() + found_remote = remotes[0] + for remote in remotes: + if remote.startswith('remote.origin.url '): + found_remote = remote + break + url = found_remote.split(' ')[1] + return url.strip() + + def get_revision(self, location, rev=None): + if rev is None: + rev = 'HEAD' + current_rev = self.run_command( + ['rev-parse', rev], show_stdout=False, cwd=location, + ) + return current_rev.strip() + + def _get_subdirectory(self, location): + """Return the relative path of setup.py to the git repo root.""" + # find the repo root + git_dir = self.run_command(['rev-parse', '--git-dir'], + show_stdout=False, cwd=location).strip() + if not os.path.isabs(git_dir): + git_dir = os.path.join(location, git_dir) + root_dir = os.path.join(git_dir, '..') + # find setup.py + orig_location = location + while not os.path.exists(os.path.join(location, 'setup.py')): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding setup.py + logger.warning( + "Could not find setup.py for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + # relative path of setup.py to repo root + if samefile(root_dir, location): + return None + return os.path.relpath(location, root_dir) + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if not repo.lower().startswith('git:'): + repo = 'git+' + repo + current_rev = self.get_revision(location) + egg_project_name = dist.egg_name().split('-', 1)[0] + subdir = self._get_subdirectory(location) + req = make_vcs_requirement_url(repo, current_rev, egg_project_name, + subdir=subdir) + + return req + + def get_url_rev_and_auth(self, url): + """ + Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. + That's required because although they use SSH they sometimes don't + work with a ssh:// scheme (e.g. GitHub). But we need a scheme for + parsing. Hence we remove it again afterwards and return it as a stub. + """ + if '://' not in url: + assert 'file:' not in url + url = url.replace('git+', 'git+ssh://') + url, rev, user_pass = super(Git, self).get_url_rev_and_auth(url) + url = url.replace('ssh://', '') + else: + url, rev, user_pass = super(Git, self).get_url_rev_and_auth(url) + + return url, rev, user_pass + + def update_submodules(self, location): + if not os.path.exists(os.path.join(location, '.gitmodules')): + return + self.run_command( + ['submodule', 'update', '--init', '--recursive', '-q'], + cwd=location, + ) + + @classmethod + def controls_location(cls, location): + if super(Git, cls).controls_location(location): + return True + try: + r = cls().run_command(['rev-parse'], + cwd=location, + show_stdout=False, + on_returncode='ignore') + return not r + except BadCommand: + logger.debug("could not determine if %s is under git control " + "because git is not available", location) + return False + + +vcs.register(Git) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/vcs/mercurial.py b/venv/lib/python3.7/site-packages/pip/_internal/vcs/mercurial.py new file mode 100644 index 0000000..17cfb67 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/vcs/mercurial.py @@ -0,0 +1,101 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._vendor.six.moves import configparser + +from pip._internal.download import path_to_url +from pip._internal.utils.misc import display_path, make_vcs_requirement_url +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.vcs import VersionControl, vcs + +logger = logging.getLogger(__name__) + + +class Mercurial(VersionControl): + name = 'hg' + dirname = '.hg' + repo_name = 'clone' + schemes = ('hg', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http') + + def get_base_rev_args(self, rev): + return [rev] + + def export(self, location): + """Export the Hg repository at the url to the destination location""" + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + + self.run_command( + ['archive', location], show_stdout=False, cwd=temp_dir.path + ) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Cloning hg %s%s to %s', + url, + rev_display, + display_path(dest), + ) + self.run_command(['clone', '--noupdate', '-q', url, dest]) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def switch(self, dest, url, rev_options): + repo_config = os.path.join(dest, self.dirname, 'hgrc') + config = configparser.SafeConfigParser() + try: + config.read(repo_config) + config.set('paths', 'default', url) + with open(repo_config, 'w') as config_file: + config.write(config_file) + except (OSError, configparser.NoSectionError) as exc: + logger.warning( + 'Could not switch Mercurial repository to %s: %s', url, exc, + ) + else: + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def update(self, dest, url, rev_options): + self.run_command(['pull', '-q'], cwd=dest) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def get_url(self, location): + url = self.run_command( + ['showconfig', 'paths.default'], + show_stdout=False, cwd=location).strip() + if self._is_local_repository(url): + url = path_to_url(url) + return url.strip() + + def get_revision(self, location): + current_revision = self.run_command( + ['parents', '--template={rev}'], + show_stdout=False, cwd=location).strip() + return current_revision + + def get_revision_hash(self, location): + current_rev_hash = self.run_command( + ['parents', '--template={node}'], + show_stdout=False, cwd=location).strip() + return current_rev_hash + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if not repo.lower().startswith('hg:'): + repo = 'hg+' + repo + current_rev_hash = self.get_revision_hash(location) + egg_project_name = dist.egg_name().split('-', 1)[0] + return make_vcs_requirement_url(repo, current_rev_hash, + egg_project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Mercurial) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/vcs/subversion.py b/venv/lib/python3.7/site-packages/pip/_internal/vcs/subversion.py new file mode 100644 index 0000000..6f7cb5d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/vcs/subversion.py @@ -0,0 +1,213 @@ +from __future__ import absolute_import + +import logging +import os +import re + +from pip._internal.models.link import Link +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + display_path, make_vcs_requirement_url, rmtree, split_auth_from_netloc, +) +from pip._internal.vcs import VersionControl, vcs + +_svn_xml_url_re = re.compile('url="([^"]+)"') +_svn_rev_re = re.compile(r'committed-rev="(\d+)"') +_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') +_svn_info_xml_url_re = re.compile(r'<url>(.*)</url>') + + +logger = logging.getLogger(__name__) + + +class Subversion(VersionControl): + name = 'svn' + dirname = '.svn' + repo_name = 'checkout' + schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn') + + def get_base_rev_args(self, rev): + return ['-r', rev] + + def export(self, location): + """Export the svn repository at the url to the destination location""" + url, rev_options = self.get_url_rev_options(self.url) + + logger.info('Exporting svn repository %s to %s', url, location) + with indent_log(): + if os.path.exists(location): + # Subversion doesn't like to check out over an existing + # directory --force fixes this, but was only added in svn 1.5 + rmtree(location) + cmd_args = ['export'] + rev_options.to_args() + [url, location] + self.run_command(cmd_args, show_stdout=False) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Checking out %s%s to %s', + url, + rev_display, + display_path(dest), + ) + cmd_args = ['checkout', '-q'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) + + def switch(self, dest, url, rev_options): + cmd_args = ['switch'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) + + def update(self, dest, url, rev_options): + cmd_args = ['update'] + rev_options.to_args() + [dest] + self.run_command(cmd_args) + + def get_location(self, dist, dependency_links): + for url in dependency_links: + egg_fragment = Link(url).egg_fragment + if not egg_fragment: + continue + if '-' in egg_fragment: + # FIXME: will this work when a package has - in the name? + key = '-'.join(egg_fragment.split('-')[:-1]).lower() + else: + key = egg_fragment + if key == dist.key: + return url.split('#', 1)[0] + return None + + def get_revision(self, location): + """ + Return the maximum revision for all files under a given location + """ + # Note: taken from setuptools.command.egg_info + revision = 0 + + for base, dirs, files in os.walk(location): + if self.dirname not in dirs: + dirs[:] = [] + continue # no sense walking uncontrolled subdirs + dirs.remove(self.dirname) + entries_fn = os.path.join(base, self.dirname, 'entries') + if not os.path.exists(entries_fn): + # FIXME: should we warn? + continue + + dirurl, localrev = self._get_svn_url_rev(base) + + if base == location: + base = dirurl + '/' # save the root url + elif not dirurl or not dirurl.startswith(base): + dirs[:] = [] + continue # not part of the same svn tree, skip it + revision = max(revision, localrev) + return revision + + def get_netloc_and_auth(self, netloc, scheme): + """ + This override allows the auth information to be passed to svn via the + --username and --password options instead of via the URL. + """ + if scheme == 'ssh': + # The --username and --password options can't be used for + # svn+ssh URLs, so keep the auth information in the URL. + return super(Subversion, self).get_netloc_and_auth( + netloc, scheme) + + return split_auth_from_netloc(netloc) + + def get_url_rev_and_auth(self, url): + # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it + url, rev, user_pass = super(Subversion, self).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'svn+' + url + return url, rev, user_pass + + def make_rev_args(self, username, password): + extra_args = [] + if username: + extra_args += ['--username', username] + if password: + extra_args += ['--password', password] + + return extra_args + + def get_url(self, location): + # In cases where the source is in a subdirectory, not alongside + # setup.py we have to look up in the location until we find a real + # setup.py + orig_location = location + while not os.path.exists(os.path.join(location, 'setup.py')): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding setup.py + logger.warning( + "Could not find setup.py for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + + return self._get_svn_url_rev(location)[0] + + def _get_svn_url_rev(self, location): + from pip._internal.exceptions import InstallationError + + entries_path = os.path.join(location, self.dirname, 'entries') + if os.path.exists(entries_path): + with open(entries_path) as f: + data = f.read() + else: # subversion >= 1.7 does not have the 'entries' file + data = '' + + if (data.startswith('8') or + data.startswith('9') or + data.startswith('10')): + data = list(map(str.splitlines, data.split('\n\x0c\n'))) + del data[0][0] # get rid of the '8' + url = data[0][3] + revs = [int(d[9]) for d in data if len(d) > 9 and d[9]] + [0] + elif data.startswith('<?xml'): + match = _svn_xml_url_re.search(data) + if not match: + raise ValueError('Badly formatted data: %r' % data) + url = match.group(1) # get repository URL + revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)] + [0] + else: + try: + # subversion >= 1.7 + xml = self.run_command( + ['info', '--xml', location], + show_stdout=False, + ) + url = _svn_info_xml_url_re.search(xml).group(1) + revs = [ + int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml) + ] + except InstallationError: + url, revs = None, [] + + if revs: + rev = max(revs) + else: + rev = 0 + + return url, rev + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if repo is None: + return None + repo = 'svn+' + repo + rev = self.get_revision(location) + # FIXME: why not project name? + egg_project_name = dist.egg_name().split('-', 1)[0] + return make_vcs_requirement_url(repo, rev, egg_project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Subversion) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/wheel.py b/venv/lib/python3.7/site-packages/pip/_internal/wheel.py new file mode 100644 index 0000000..5ce890e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/wheel.py @@ -0,0 +1,831 @@ +""" +Support for installing and building the "wheel" binary package format. +""" +from __future__ import absolute_import + +import collections +import compileall +import csv +import hashlib +import logging +import os.path +import re +import shutil +import stat +import sys +import warnings +from base64 import urlsafe_b64encode +from email.parser import Parser + +from pip._vendor import pkg_resources +from pip._vendor.distlib.scripts import ScriptMaker +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.six import StringIO + +from pip._internal import pep425tags +from pip._internal.download import path_to_url, unpack_url +from pip._internal.exceptions import ( + InstallationError, InvalidWheelFilename, UnsupportedWheel, +) +from pip._internal.locations import ( + PIP_DELETE_MARKER_FILENAME, distutils_scheme, +) +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + call_subprocess, captured_stdout, ensure_dir, read_chunks, +) +from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.ui import open_spinner + +if MYPY_CHECK_RUNNING: + from typing import Dict, List, Optional # noqa: F401 + +wheel_ext = '.whl' + +VERSION_COMPATIBLE = (1, 0) + + +logger = logging.getLogger(__name__) + + +def rehash(path, blocksize=1 << 20): + """Return (hash, length) for path using hashlib.sha256()""" + h = hashlib.sha256() + length = 0 + with open(path, 'rb') as f: + for block in read_chunks(f, size=blocksize): + length += len(block) + h.update(block) + digest = 'sha256=' + urlsafe_b64encode( + h.digest() + ).decode('latin1').rstrip('=') + return (digest, length) + + +def open_for_csv(name, mode): + if sys.version_info[0] < 3: + nl = {} + bin = 'b' + else: + nl = {'newline': ''} + bin = '' + return open(name, mode + bin, **nl) + + +def fix_script(path): + """Replace #!python with #!/path/to/python + Return True if file was changed.""" + # XXX RECORD hashes will need to be updated + if os.path.isfile(path): + with open(path, 'rb') as script: + firstline = script.readline() + if not firstline.startswith(b'#!python'): + return False + exename = sys.executable.encode(sys.getfilesystemencoding()) + firstline = b'#!' + exename + os.linesep.encode("ascii") + rest = script.read() + with open(path, 'wb') as script: + script.write(firstline) + script.write(rest) + return True + + +dist_info_re = re.compile(r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>.+?))?) + \.dist-info$""", re.VERBOSE) + + +def root_is_purelib(name, wheeldir): + """ + Return True if the extracted wheel in wheeldir should go into purelib. + """ + name_folded = name.replace("-", "_") + for item in os.listdir(wheeldir): + match = dist_info_re.match(item) + if match and match.group('name') == name_folded: + with open(os.path.join(wheeldir, item, 'WHEEL')) as wheel: + for line in wheel: + line = line.lower().rstrip() + if line == "root-is-purelib: true": + return True + return False + + +def get_entrypoints(filename): + if not os.path.exists(filename): + return {}, {} + + # This is done because you can pass a string to entry_points wrappers which + # means that they may or may not be valid INI files. The attempt here is to + # strip leading and trailing whitespace in order to make them valid INI + # files. + with open(filename) as fp: + data = StringIO() + for line in fp: + data.write(line.strip()) + data.write("\n") + data.seek(0) + + # get the entry points and then the script names + entry_points = pkg_resources.EntryPoint.parse_map(data) + console = entry_points.get('console_scripts', {}) + gui = entry_points.get('gui_scripts', {}) + + def _split_ep(s): + """get the string representation of EntryPoint, remove space and split + on '='""" + return str(s).replace(" ", "").split("=") + + # convert the EntryPoint objects into strings with module:function + console = dict(_split_ep(v) for v in console.values()) + gui = dict(_split_ep(v) for v in gui.values()) + return console, gui + + +def message_about_scripts_not_on_PATH(scripts): + # type: (List[str]) -> Optional[str] + """Determine if any scripts are not on PATH and format a warning. + + Returns a warning message if one or more scripts are not on PATH, + otherwise None. + """ + if not scripts: + return None + + # Group scripts by the path they were installed in + grouped_by_dir = collections.defaultdict(set) # type: Dict[str, set] + for destfile in scripts: + parent_dir = os.path.dirname(destfile) + script_name = os.path.basename(destfile) + grouped_by_dir[parent_dir].add(script_name) + + # We don't want to warn for directories that are on PATH. + not_warn_dirs = [ + os.path.normcase(i).rstrip(os.sep) for i in + os.environ.get("PATH", "").split(os.pathsep) + ] + # If an executable sits with sys.executable, we don't warn for it. + # This covers the case of venv invocations without activating the venv. + not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) + warn_for = { + parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() + if os.path.normcase(parent_dir) not in not_warn_dirs + } + if not warn_for: + return None + + # Format a message + msg_lines = [] + for parent_dir, scripts in warn_for.items(): + scripts = sorted(scripts) + if len(scripts) == 1: + start_text = "script {} is".format(scripts[0]) + else: + start_text = "scripts {} are".format( + ", ".join(scripts[:-1]) + " and " + scripts[-1] + ) + + msg_lines.append( + "The {} installed in '{}' which is not on PATH." + .format(start_text, parent_dir) + ) + + last_line_fmt = ( + "Consider adding {} to PATH or, if you prefer " + "to suppress this warning, use --no-warn-script-location." + ) + if len(msg_lines) == 1: + msg_lines.append(last_line_fmt.format("this directory")) + else: + msg_lines.append(last_line_fmt.format("these directories")) + + # Returns the formatted multiline message + return "\n".join(msg_lines) + + +def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, + pycompile=True, scheme=None, isolated=False, prefix=None, + warn_script_location=True): + """Install a wheel""" + + if not scheme: + scheme = distutils_scheme( + name, user=user, home=home, root=root, isolated=isolated, + prefix=prefix, + ) + + if root_is_purelib(name, wheeldir): + lib_dir = scheme['purelib'] + else: + lib_dir = scheme['platlib'] + + info_dir = [] + data_dirs = [] + source = wheeldir.rstrip(os.path.sep) + os.path.sep + + # Record details of the files moved + # installed = files copied from the wheel to the destination + # changed = files changed while installing (scripts #! line typically) + # generated = files newly generated during the install (script wrappers) + installed = {} + changed = set() + generated = [] + + # Compile all of the pyc files that we're going to be installing + if pycompile: + with captured_stdout() as stdout: + with warnings.catch_warnings(): + warnings.filterwarnings('ignore') + compileall.compile_dir(source, force=True, quiet=True) + logger.debug(stdout.getvalue()) + + def normpath(src, p): + return os.path.relpath(src, p).replace(os.path.sep, '/') + + def record_installed(srcfile, destfile, modified=False): + """Map archive RECORD paths to installation RECORD paths.""" + oldpath = normpath(srcfile, wheeldir) + newpath = normpath(destfile, lib_dir) + installed[oldpath] = newpath + if modified: + changed.add(destfile) + + def clobber(source, dest, is_base, fixer=None, filter=None): + ensure_dir(dest) # common for the 'include' path + + for dir, subdirs, files in os.walk(source): + basedir = dir[len(source):].lstrip(os.path.sep) + destdir = os.path.join(dest, basedir) + if is_base and basedir.split(os.path.sep, 1)[0].endswith('.data'): + continue + for s in subdirs: + destsubdir = os.path.join(dest, basedir, s) + if is_base and basedir == '' and destsubdir.endswith('.data'): + data_dirs.append(s) + continue + elif (is_base and + s.endswith('.dist-info') and + canonicalize_name(s).startswith( + canonicalize_name(req.name))): + assert not info_dir, ('Multiple .dist-info directories: ' + + destsubdir + ', ' + + ', '.join(info_dir)) + info_dir.append(destsubdir) + for f in files: + # Skip unwanted files + if filter and filter(f): + continue + srcfile = os.path.join(dir, f) + destfile = os.path.join(dest, basedir, f) + # directory creation is lazy and after the file filtering above + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + ensure_dir(destdir) + + # copyfile (called below) truncates the destination if it + # exists and then writes the new contents. This is fine in most + # cases, but can cause a segfault if pip has loaded a shared + # object (e.g. from pyopenssl through its vendored urllib3) + # Since the shared object is mmap'd an attempt to call a + # symbol in it will then cause a segfault. Unlinking the file + # allows writing of new contents while allowing the process to + # continue to use the old copy. + if os.path.exists(destfile): + os.unlink(destfile) + + # We use copyfile (not move, copy, or copy2) to be extra sure + # that we are not moving directories over (copyfile fails for + # directories) as well as to ensure that we are not copying + # over any metadata because we want more control over what + # metadata we actually copy over. + shutil.copyfile(srcfile, destfile) + + # Copy over the metadata for the file, currently this only + # includes the atime and mtime. + st = os.stat(srcfile) + if hasattr(os, "utime"): + os.utime(destfile, (st.st_atime, st.st_mtime)) + + # If our file is executable, then make our destination file + # executable. + if os.access(srcfile, os.X_OK): + st = os.stat(srcfile) + permissions = ( + st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + ) + os.chmod(destfile, permissions) + + changed = False + if fixer: + changed = fixer(destfile) + record_installed(srcfile, destfile, changed) + + clobber(source, lib_dir, True) + + assert info_dir, "%s .dist-info directory not found" % req + + # Get the defined entry points + ep_file = os.path.join(info_dir[0], 'entry_points.txt') + console, gui = get_entrypoints(ep_file) + + def is_entrypoint_wrapper(name): + # EP, EP.exe and EP-script.py are scripts generated for + # entry point EP by setuptools + if name.lower().endswith('.exe'): + matchname = name[:-4] + elif name.lower().endswith('-script.py'): + matchname = name[:-10] + elif name.lower().endswith(".pya"): + matchname = name[:-4] + else: + matchname = name + # Ignore setuptools-generated scripts + return (matchname in console or matchname in gui) + + for datadir in data_dirs: + fixer = None + filter = None + for subdir in os.listdir(os.path.join(wheeldir, datadir)): + fixer = None + if subdir == 'scripts': + fixer = fix_script + filter = is_entrypoint_wrapper + source = os.path.join(wheeldir, datadir, subdir) + dest = scheme[subdir] + clobber(source, dest, False, fixer=fixer, filter=filter) + + maker = ScriptMaker(None, scheme['scripts']) + + # Ensure old scripts are overwritten. + # See https://github.com/pypa/pip/issues/1800 + maker.clobber = True + + # Ensure we don't generate any variants for scripts because this is almost + # never what somebody wants. + # See https://bitbucket.org/pypa/distlib/issue/35/ + maker.variants = {''} + + # This is required because otherwise distlib creates scripts that are not + # executable. + # See https://bitbucket.org/pypa/distlib/issue/32/ + maker.set_mode = True + + # Simplify the script and fix the fact that the default script swallows + # every single stack trace. + # See https://bitbucket.org/pypa/distlib/issue/34/ + # See https://bitbucket.org/pypa/distlib/issue/33/ + def _get_script_text(entry): + if entry.suffix is None: + raise InstallationError( + "Invalid script entry point: %s for req: %s - A callable " + "suffix is required. Cf https://packaging.python.org/en/" + "latest/distributing.html#console-scripts for more " + "information." % (entry, req) + ) + return maker.script_template % { + "module": entry.prefix, + "import_name": entry.suffix.split(".")[0], + "func": entry.suffix, + } + + maker._get_script_text = _get_script_text + maker.script_template = r"""# -*- coding: utf-8 -*- +import re +import sys + +from %(module)s import %(import_name)s + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(%(func)s()) +""" + + # Special case pip and setuptools to generate versioned wrappers + # + # The issue is that some projects (specifically, pip and setuptools) use + # code in setup.py to create "versioned" entry points - pip2.7 on Python + # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into + # the wheel metadata at build time, and so if the wheel is installed with + # a *different* version of Python the entry points will be wrong. The + # correct fix for this is to enhance the metadata to be able to describe + # such versioned entry points, but that won't happen till Metadata 2.0 is + # available. + # In the meantime, projects using versioned entry points will either have + # incorrect versioned entry points, or they will not be able to distribute + # "universal" wheels (i.e., they will need a wheel per Python version). + # + # Because setuptools and pip are bundled with _ensurepip and virtualenv, + # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we + # override the versioned entry points in the wheel and generate the + # correct ones. This code is purely a short-term measure until Metadata 2.0 + # is available. + # + # To add the level of hack in this section of code, in order to support + # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment + # variable which will control which version scripts get installed. + # + # ENSUREPIP_OPTIONS=altinstall + # - Only pipX.Y and easy_install-X.Y will be generated and installed + # ENSUREPIP_OPTIONS=install + # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note + # that this option is technically if ENSUREPIP_OPTIONS is set and is + # not altinstall + # DEFAULT + # - The default behavior is to install pip, pipX, pipX.Y, easy_install + # and easy_install-X.Y. + pip_script = console.pop('pip', None) + if pip_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + spec = 'pip = ' + pip_script + generated.extend(maker.make(spec)) + + if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": + spec = 'pip%s = %s' % (sys.version[:1], pip_script) + generated.extend(maker.make(spec)) + + spec = 'pip%s = %s' % (sys.version[:3], pip_script) + generated.extend(maker.make(spec)) + # Delete any other versioned pip entry points + pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)] + for k in pip_ep: + del console[k] + easy_install_script = console.pop('easy_install', None) + if easy_install_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + spec = 'easy_install = ' + easy_install_script + generated.extend(maker.make(spec)) + + spec = 'easy_install-%s = %s' % (sys.version[:3], easy_install_script) + generated.extend(maker.make(spec)) + # Delete any other versioned easy_install entry points + easy_install_ep = [ + k for k in console if re.match(r'easy_install(-\d\.\d)?$', k) + ] + for k in easy_install_ep: + del console[k] + + # Generate the console and GUI entry points specified in the wheel + if len(console) > 0: + generated_console_scripts = maker.make_multiple( + ['%s = %s' % kv for kv in console.items()] + ) + generated.extend(generated_console_scripts) + + if warn_script_location: + msg = message_about_scripts_not_on_PATH(generated_console_scripts) + if msg is not None: + logger.warning(msg) + + if len(gui) > 0: + generated.extend( + maker.make_multiple( + ['%s = %s' % kv for kv in gui.items()], + {'gui': True} + ) + ) + + # Record pip as the installer + installer = os.path.join(info_dir[0], 'INSTALLER') + temp_installer = os.path.join(info_dir[0], 'INSTALLER.pip') + with open(temp_installer, 'wb') as installer_file: + installer_file.write(b'pip\n') + shutil.move(temp_installer, installer) + generated.append(installer) + + # Record details of all files installed + record = os.path.join(info_dir[0], 'RECORD') + temp_record = os.path.join(info_dir[0], 'RECORD.pip') + with open_for_csv(record, 'r') as record_in: + with open_for_csv(temp_record, 'w+') as record_out: + reader = csv.reader(record_in) + writer = csv.writer(record_out) + outrows = [] + for row in reader: + row[0] = installed.pop(row[0], row[0]) + if row[0] in changed: + row[1], row[2] = rehash(row[0]) + outrows.append(tuple(row)) + for f in generated: + digest, length = rehash(f) + outrows.append((normpath(f, lib_dir), digest, length)) + for f in installed: + outrows.append((installed[f], '', '')) + for row in sorted(outrows): + writer.writerow(row) + shutil.move(temp_record, record) + + +def wheel_version(source_dir): + """ + Return the Wheel-Version of an extracted wheel, if possible. + + Otherwise, return False if we couldn't parse / extract it. + """ + try: + dist = [d for d in pkg_resources.find_on_path(None, source_dir)][0] + + wheel_data = dist.get_metadata('WHEEL') + wheel_data = Parser().parsestr(wheel_data) + + version = wheel_data['Wheel-Version'].strip() + version = tuple(map(int, version.split('.'))) + return version + except Exception: + return False + + +def check_compatibility(version, name): + """ + Raises errors or warns if called with an incompatible Wheel-Version. + + Pip should refuse to install a Wheel-Version that's a major series + ahead of what it's compatible with (e.g 2.0 > 1.1); and warn when + installing a version only minor version ahead (e.g 1.2 > 1.1). + + version: a 2-tuple representing a Wheel-Version (Major, Minor) + name: name of wheel or package to raise exception about + + :raises UnsupportedWheel: when an incompatible Wheel-Version is given + """ + if not version: + raise UnsupportedWheel( + "%s is in an unsupported or invalid wheel" % name + ) + if version[0] > VERSION_COMPATIBLE[0]: + raise UnsupportedWheel( + "%s's Wheel-Version (%s) is not compatible with this version " + "of pip" % (name, '.'.join(map(str, version))) + ) + elif version > VERSION_COMPATIBLE: + logger.warning( + 'Installing from a newer Wheel-Version (%s)', + '.'.join(map(str, version)), + ) + + +class Wheel(object): + """A wheel file""" + + # TODO: maybe move the install code into this class + + wheel_file_re = re.compile( + r"""^(?P<namever>(?P<name>.+?)-(?P<ver>.*?)) + ((-(?P<build>\d[^-]*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?) + \.whl|\.dist-info)$""", + re.VERBOSE + ) + + def __init__(self, filename): + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ + wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename( + "%s is not a valid wheel filename." % filename + ) + self.filename = filename + self.name = wheel_info.group('name').replace('_', '-') + # we'll assume "_" means "-" due to wheel naming scheme + # (https://github.com/pypa/pip/issues/1150) + self.version = wheel_info.group('ver').replace('_', '-') + self.build_tag = wheel_info.group('build') + self.pyversions = wheel_info.group('pyver').split('.') + self.abis = wheel_info.group('abi').split('.') + self.plats = wheel_info.group('plat').split('.') + + # All the tag combinations from this file + self.file_tags = { + (x, y, z) for x in self.pyversions + for y in self.abis for z in self.plats + } + + def support_index_min(self, tags=None): + """ + Return the lowest index that one of the wheel's file_tag combinations + achieves in the supported_tags list e.g. if there are 8 supported tags, + and one of the file tags is first in the list, then return 0. Returns + None is the wheel is not supported. + """ + if tags is None: # for mock + tags = pep425tags.get_supported() + indexes = [tags.index(c) for c in self.file_tags if c in tags] + return min(indexes) if indexes else None + + def supported(self, tags=None): + """Is this wheel supported on this system?""" + if tags is None: # for mock + tags = pep425tags.get_supported() + return bool(set(tags).intersection(self.file_tags)) + + +class WheelBuilder(object): + """Build wheels from a RequirementSet.""" + + def __init__(self, finder, preparer, wheel_cache, + build_options=None, global_options=None, no_clean=False): + self.finder = finder + self.preparer = preparer + self.wheel_cache = wheel_cache + + self._wheel_dir = preparer.wheel_download_dir + + self.build_options = build_options or [] + self.global_options = global_options or [] + self.no_clean = no_clean + + def _build_one(self, req, output_dir, python_tag=None): + """Build one wheel. + + :return: The filename of the built wheel, or None if the build failed. + """ + # Install build deps into temporary directory (PEP 518) + with req.build_env: + return self._build_one_inside_env(req, output_dir, + python_tag=python_tag) + + def _build_one_inside_env(self, req, output_dir, python_tag=None): + with TempDirectory(kind="wheel") as temp_dir: + if self.__build_one(req, temp_dir.path, python_tag=python_tag): + try: + wheel_name = os.listdir(temp_dir.path)[0] + wheel_path = os.path.join(output_dir, wheel_name) + shutil.move( + os.path.join(temp_dir.path, wheel_name), wheel_path + ) + logger.info('Stored in directory: %s', output_dir) + return wheel_path + except Exception: + pass + # Ignore return, we can't do anything else useful. + self._clean_one(req) + return None + + def _base_setup_args(self, req): + # NOTE: Eventually, we'd want to also -S to the flags here, when we're + # isolating. Currently, it breaks Python in virtualenvs, because it + # relies on site.py to find parts of the standard library outside the + # virtualenv. + return [ + sys.executable, '-u', '-c', + SETUPTOOLS_SHIM % req.setup_py + ] + list(self.global_options) + + def __build_one(self, req, tempd, python_tag=None): + base_args = self._base_setup_args(req) + + spin_message = 'Running setup.py bdist_wheel for %s' % (req.name,) + with open_spinner(spin_message) as spinner: + logger.debug('Destination directory: %s', tempd) + wheel_args = base_args + ['bdist_wheel', '-d', tempd] \ + + self.build_options + + if python_tag is not None: + wheel_args += ["--python-tag", python_tag] + + try: + call_subprocess(wheel_args, cwd=req.setup_py_dir, + show_stdout=False, spinner=spinner) + return True + except Exception: + spinner.finish("error") + logger.error('Failed building wheel for %s', req.name) + return False + + def _clean_one(self, req): + base_args = self._base_setup_args(req) + + logger.info('Running setup.py clean for %s', req.name) + clean_args = base_args + ['clean', '--all'] + try: + call_subprocess(clean_args, cwd=req.source_dir, show_stdout=False) + return True + except Exception: + logger.error('Failed cleaning build dir for %s', req.name) + return False + + def build(self, requirements, session, autobuilding=False): + """Build wheels. + + :param unpack: If True, replace the sdist we built from with the + newly built wheel, in preparation for installation. + :return: True if all the wheels built correctly. + """ + from pip._internal import index + from pip._internal.models.link import Link + + building_is_possible = self._wheel_dir or ( + autobuilding and self.wheel_cache.cache_dir + ) + assert building_is_possible + + buildset = [] + format_control = self.finder.format_control + for req in requirements: + if req.constraint: + continue + if req.is_wheel: + if not autobuilding: + logger.info( + 'Skipping %s, due to already being wheel.', req.name, + ) + elif autobuilding and req.editable: + pass + elif autobuilding and not req.source_dir: + pass + elif autobuilding and req.link and not req.link.is_artifact: + # VCS checkout. Build wheel just for this run. + buildset.append((req, True)) + else: + ephem_cache = False + if autobuilding: + link = req.link + base, ext = link.splitext() + if index.egg_info_matches(base, None, link) is None: + # E.g. local directory. Build wheel just for this run. + ephem_cache = True + if "binary" not in format_control.get_allowed_formats( + canonicalize_name(req.name)): + logger.info( + "Skipping bdist_wheel for %s, due to binaries " + "being disabled for it.", req.name, + ) + continue + buildset.append((req, ephem_cache)) + + if not buildset: + return True + + # Build the wheels. + logger.info( + 'Building wheels for collected packages: %s', + ', '.join([req.name for (req, _) in buildset]), + ) + _cache = self.wheel_cache # shorter name + with indent_log(): + build_success, build_failure = [], [] + for req, ephem in buildset: + python_tag = None + if autobuilding: + python_tag = pep425tags.implementation_tag + if ephem: + output_dir = _cache.get_ephem_path_for_link(req.link) + else: + output_dir = _cache.get_path_for_link(req.link) + try: + ensure_dir(output_dir) + except OSError as e: + logger.warning("Building wheel for %s failed: %s", + req.name, e) + build_failure.append(req) + continue + else: + output_dir = self._wheel_dir + wheel_file = self._build_one( + req, output_dir, + python_tag=python_tag, + ) + if wheel_file: + build_success.append(req) + if autobuilding: + # XXX: This is mildly duplicative with prepare_files, + # but not close enough to pull out to a single common + # method. + # The code below assumes temporary source dirs - + # prevent it doing bad things. + if req.source_dir and not os.path.exists(os.path.join( + req.source_dir, PIP_DELETE_MARKER_FILENAME)): + raise AssertionError( + "bad source dir - missing marker") + # Delete the source we built the wheel from + req.remove_temporary_source() + # set the build directory again - name is known from + # the work prepare_files did. + req.source_dir = req.build_location( + self.preparer.build_dir + ) + # Update the link for this. + req.link = Link(path_to_url(wheel_file)) + assert req.link.is_wheel + # extract the wheel into the dir + unpack_url( + req.link, req.source_dir, None, False, + session=session, + ) + else: + build_failure.append(req) + + # notify success/failure + if build_success: + logger.info( + 'Successfully built %s', + ' '.join([req.name for req in build_success]), + ) + if build_failure: + logger.info( + 'Failed to build %s', + ' '.join([req.name for req in build_failure]), + ) + # Return True if all builds were successful + return len(build_failure) == 0 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000..a0aae81 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,110 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import + +import glob +import os.path +import sys + +# Downstream redistributors which have debundled our dependencies should also +# patch this value to be true. This will trigger the additional patching +# to cause things like "six" to be available as pip. +DEBUNDLED = False + +# By default, look in this directory for a bunch of .whl files which we will +# add to the beginning of sys.path before attempting to import anything. This +# is done to support downstream re-distributors like Debian and Fedora who +# wish to create their own Wheels for our dependencies to aid in debundling. +WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) + + +# Define a small helper function to alias our vendored modules to the real ones +# if the vendored ones do not exist. This idea of this was taken from +# https://github.com/kennethreitz/requests/pull/2567. +def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: + __import__(vendored_name, globals(), locals(), level=0) + except ImportError: + try: + __import__(modulename, globals(), locals(), level=0) + except ImportError: + # We can just silently allow import failures to pass here. If we + # got to this point it means that ``import pip._vendor.whatever`` + # failed and so did ``import whatever``. Since we're importing this + # upfront in an attempt to alias imports, not erroring here will + # just mean we get a regular import error whenever pip *actually* + # tries to import one of these modules to use it, which actually + # gives us a better error message than we would have otherwise + # gotten. + pass + else: + sys.modules[vendored_name] = sys.modules[modulename] + base, head = vendored_name.rsplit(".", 1) + setattr(sys.modules[base], head, sys.modules[modulename]) + + +# If we're operating in a debundled setup, then we want to go ahead and trigger +# the aliasing of our vendored libraries as well as looking for wheels to add +# to our sys.path. This will cause all of this code to be a no-op typically +# however downstream redistributors can enable it in a consistent way across +# all platforms. +if DEBUNDLED: + # Actually look inside of WHEEL_DIR to find .whl files and add them to the + # front of our sys.path. + sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path + + # Actually alias all of our vendored dependencies. + vendored("cachecontrol") + vendored("colorama") + vendored("distlib") + vendored("distro") + vendored("html5lib") + vendored("lockfile") + vendored("six") + vendored("six.moves") + vendored("six.moves.urllib") + vendored("six.moves.urllib.parse") + vendored("packaging") + vendored("packaging.version") + vendored("packaging.specifiers") + vendored("pkg_resources") + vendored("progress") + vendored("pytoml") + vendored("retrying") + vendored("requests") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") + vendored("requests.packages.urllib3.connection") + vendored("requests.packages.urllib3.connectionpool") + vendored("requests.packages.urllib3.contrib") + vendored("requests.packages.urllib3.contrib.ntlmpool") + vendored("requests.packages.urllib3.contrib.pyopenssl") + vendored("requests.packages.urllib3.exceptions") + vendored("requests.packages.urllib3.fields") + vendored("requests.packages.urllib3.filepost") + vendored("requests.packages.urllib3.packages") + vendored("requests.packages.urllib3.packages.ordered_dict") + vendored("requests.packages.urllib3.packages.six") + vendored("requests.packages.urllib3.packages.ssl_match_hostname") + vendored("requests.packages.urllib3.packages.ssl_match_hostname." + "_implementation") + vendored("requests.packages.urllib3.poolmanager") + vendored("requests.packages.urllib3.request") + vendored("requests.packages.urllib3.response") + vendored("requests.packages.urllib3.util") + vendored("requests.packages.urllib3.util.connection") + vendored("requests.packages.urllib3.util.request") + vendored("requests.packages.urllib3.util.response") + vendored("requests.packages.urllib3.util.retry") + vendored("requests.packages.urllib3.util.ssl_") + vendored("requests.packages.urllib3.util.timeout") + vendored("requests.packages.urllib3.util.url") + vendored("urllib3") diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/appdirs.py b/venv/lib/python3.7/site-packages/pip/_vendor/appdirs.py new file mode 100644 index 0000000..2bd3911 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/appdirs.py @@ -0,0 +1,604 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2005-2010 ActiveState Software Inc. +# Copyright (c) 2013 Eddy Petrișor + +"""Utilities for determining application-specific dirs. + +See <http://github.com/ActiveState/appdirs> for details and usage. +""" +# Dev Notes: +# - MSDN on where to store app data files: +# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 +# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +__version_info__ = (1, 4, 3) +__version__ = '.'.join(map(str, __version_info__)) + + +import sys +import os + +PY3 = sys.version_info[0] == 3 + +if PY3: + unicode = str + +if sys.platform.startswith('java'): + import platform + os_name = platform.java_ver()[3][0] + if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. + system = 'win32' + elif os_name.startswith('Mac'): # "Mac OS X", etc. + system = 'darwin' + else: # "Linux", "SunOS", "FreeBSD", etc. + # Setting this to "linux2" is not ideal, but only Windows or Mac + # are actually checked for and the rest of the module expects + # *sys.platform* style strings. + system = 'linux2' +else: + system = sys.platform + + + +def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user data directories are: + Mac OS X: ~/Library/Application Support/<AppName> + Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> + Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> + Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> + Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/<AppName>". + """ + if system == "win32": + if appauthor is None: + appauthor = appname + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.normpath(_get_win_folder(const)) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('~/Library/Application Support/') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of data dirs should be + returned. By default, the first item from XDG_DATA_DIRS is + returned, or '/usr/local/share/<AppName>', + if XDG_DATA_DIRS is not set + + Typical site data directories are: + Mac OS X: /Library/Application Support/<AppName> + Unix: /usr/local/share/<AppName> or /usr/share/<AppName> + Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. + + For Unix, this is using the $XDG_DATA_DIRS[0] default. + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('/Library/Application Support') + if appname: + path = os.path.join(path, appname) + else: + # XDG default for $XDG_DATA_DIRS + # only first, if multipath is False + path = os.getenv('XDG_DATA_DIRS', + os.pathsep.join(['/usr/local/share', '/usr/share'])) + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + if appname and version: + path = os.path.join(path, version) + return path + + +def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user config directories are: + Mac OS X: same as user_data_dir + Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of config dirs should be + returned. By default, the first item from XDG_CONFIG_DIRS is + returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set + + Typical site config directories are: + Mac OS X: same as site_data_dir + Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in + $XDG_CONFIG_DIRS + Win *: same as site_data_dir + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + + For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system in ["win32", "darwin"]: + path = site_data_dir(appname, appauthor) + if appname and version: + path = os.path.join(path, version) + else: + # XDG default for $XDG_CONFIG_DIRS + # only first, if multipath is False + path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + +def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Cache" to the base app data dir for Windows. See + discussion below. + + Typical user cache directories are: + Mac OS X: ~/Library/Caches/<AppName> + Unix: ~/.cache/<AppName> (XDG default) + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go in + the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming + app data dir (the default returned by `user_data_dir` above). Apps typically + put cache data somewhere *under* the given dir here. Some examples: + ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache + ...\Acme\SuperApp\Cache\1.0 + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + This can be disabled with the `opinion=False` option. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + if opinion: + path = os.path.join(path, "Cache") + elif system == 'darwin': + path = os.path.expanduser('~/Library/Caches') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific state dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific log dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Logs" to the base app data dir for Windows, and "log" to the + base cache dir for Unix. See discussion below. + + Typical user log directories are: + Mac OS X: ~/Library/Logs/<AppName> + Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs + + On Windows the only suggestion in the MSDN docs is that local settings + go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in + examples of what some windows apps use for a logs dir.) + + OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` + value for Windows and appends "log" to the user cache dir for Unix. + This can be disabled with the `opinion=False` option. + """ + if system == "darwin": + path = os.path.join( + os.path.expanduser('~/Library/Logs'), + appname) + elif system == "win32": + path = user_data_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "Logs") + else: + path = user_cache_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "log") + if appname and version: + path = os.path.join(path, version) + return path + + +class AppDirs(object): + """Convenience wrapper for getting application dirs.""" + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): + self.appname = appname + self.appauthor = appauthor + self.version = version + self.roaming = roaming + self.multipath = multipath + + @property + def user_data_dir(self): + return user_data_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_data_dir(self): + return site_data_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_config_dir(self): + return user_config_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_config_dir(self): + return site_config_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_cache_dir(self): + return user_cache_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_state_dir(self): + return user_state_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_log_dir(self): + return user_log_dir(self.appname, self.appauthor, + version=self.version) + + +#---- internal support stuff + +def _get_win_folder_from_registry(csidl_name): + """This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + if PY3: + import winreg as _winreg + else: + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + dir, type = _winreg.QueryValueEx(key, shell_folder_name) + return dir + + +def _get_win_folder_with_pywin32(csidl_name): + from win32com.shell import shellcon, shell + dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) + # Try to make this a unicode path because SHGetFolderPath does + # not return unicode strings when there is unicode data in the + # path. + try: + dir = unicode(dir) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + try: + import win32api + dir = win32api.GetShortPathName(dir) + except ImportError: + pass + except UnicodeError: + pass + return dir + + +def _get_win_folder_with_ctypes(csidl_name): + import ctypes + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + +def _get_win_folder_with_jna(csidl_name): + import array + from com.sun import jna + from com.sun.jna.platform import win32 + + buf_size = win32.WinDef.MAX_PATH * 2 + buf = array.zeros('c', buf_size) + shell = win32.Shell32.INSTANCE + shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf = array.zeros('c', buf_size) + kernel = win32.Kernel32.INSTANCE + if kernel.GetShortPathName(dir, buf, buf_size): + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + return dir + +if system == "win32": + try: + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + try: + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +#---- self test code + +if __name__ == "__main__": + appname = "MyApp" + appauthor = "MyCompany" + + props = ("user_data_dir", + "user_config_dir", + "user_cache_dir", + "user_state_dir", + "user_log_dir", + "site_data_dir", + "site_config_dir") + + print("-- app dirs %s --" % __version__) + + print("-- app dirs (with optional 'version')") + dirs = AppDirs(appname, appauthor, version="1.0") + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'version')") + dirs = AppDirs(appname, appauthor) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'appauthor')") + dirs = AppDirs(appname) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (with disabled 'appauthor')") + dirs = AppDirs(appname, appauthor=False) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__init__.py new file mode 100644 index 0000000..8fdee66 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/__init__.py @@ -0,0 +1,11 @@ +"""CacheControl import Interface. + +Make it easy to import from cachecontrol without long namespaces. +""" +__author__ = "Eric Larson" +__email__ = "eric@ionrock.org" +__version__ = "0.12.5" + +from .wrapper import CacheControl +from .adapter import CacheControlAdapter +from .controller import CacheController diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/_cmd.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/_cmd.py new file mode 100644 index 0000000..f1e0ad9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/_cmd.py @@ -0,0 +1,57 @@ +import logging + +from pip._vendor import requests + +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.cache import DictCache +from pip._vendor.cachecontrol.controller import logger + +from argparse import ArgumentParser + + +def setup_logging(): + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + logger.addHandler(handler) + + +def get_session(): + adapter = CacheControlAdapter( + DictCache(), cache_etags=True, serializer=None, heuristic=None + ) + sess = requests.Session() + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + sess.cache_controller = adapter.controller + return sess + + +def get_args(): + parser = ArgumentParser() + parser.add_argument("url", help="The URL to try and cache") + return parser.parse_args() + + +def main(args=None): + args = get_args() + sess = get_session() + + # Make a request to get a response + resp = sess.get(args.url) + + # Turn on logging + setup_logging() + + # try setting the cache + sess.cache_controller.cache_response(resp.request, resp.raw) + + # Now try to get it + if sess.cache_controller.cached_request(resp.request): + print("Cached!") + else: + print("Not cached :(") + + +if __name__ == "__main__": + main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/adapter.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/adapter.py new file mode 100644 index 0000000..780eb28 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/adapter.py @@ -0,0 +1,133 @@ +import types +import functools +import zlib + +from pip._vendor.requests.adapters import HTTPAdapter + +from .controller import CacheController +from .cache import DictCache +from .filewrapper import CallbackFileWrapper + + +class CacheControlAdapter(HTTPAdapter): + invalidating_methods = {"PUT", "DELETE"} + + def __init__( + self, + cache=None, + cache_etags=True, + controller_class=None, + serializer=None, + heuristic=None, + cacheable_methods=None, + *args, + **kw + ): + super(CacheControlAdapter, self).__init__(*args, **kw) + self.cache = cache or DictCache() + self.heuristic = heuristic + self.cacheable_methods = cacheable_methods or ("GET",) + + controller_factory = controller_class or CacheController + self.controller = controller_factory( + self.cache, cache_etags=cache_etags, serializer=serializer + ) + + def send(self, request, cacheable_methods=None, **kw): + """ + Send a request. Use the request information to see if it + exists in the cache and cache the response if we need to and can. + """ + cacheable = cacheable_methods or self.cacheable_methods + if request.method in cacheable: + try: + cached_response = self.controller.cached_request(request) + except zlib.error: + cached_response = None + if cached_response: + return self.build_response(request, cached_response, from_cache=True) + + # check for etags and add headers if appropriate + request.headers.update(self.controller.conditional_headers(request)) + + resp = super(CacheControlAdapter, self).send(request, **kw) + + return resp + + def build_response( + self, request, response, from_cache=False, cacheable_methods=None + ): + """ + Build a response by making a request or using the cache. + + This will end up calling send and returning a potentially + cached response + """ + cacheable = cacheable_methods or self.cacheable_methods + if not from_cache and request.method in cacheable: + # Check for any heuristics that might update headers + # before trying to cache. + if self.heuristic: + response = self.heuristic.apply(response) + + # apply any expiration heuristics + if response.status == 304: + # We must have sent an ETag request. This could mean + # that we've been expired already or that we simply + # have an etag. In either case, we want to try and + # update the cache if that is the case. + cached_response = self.controller.update_cached_response( + request, response + ) + + if cached_response is not response: + from_cache = True + + # We are done with the server response, read a + # possible response body (compliant servers will + # not return one, but we cannot be 100% sure) and + # release the connection back to the pool. + response.read(decode_content=False) + response.release_conn() + + response = cached_response + + # We always cache the 301 responses + elif response.status == 301: + self.controller.cache_response(request, response) + else: + # Wrap the response file with a wrapper that will cache the + # response when the stream has been consumed. + response._fp = CallbackFileWrapper( + response._fp, + functools.partial( + self.controller.cache_response, request, response + ), + ) + if response.chunked: + super_update_chunk_length = response._update_chunk_length + + def _update_chunk_length(self): + super_update_chunk_length() + if self.chunk_left == 0: + self._fp._close() + + response._update_chunk_length = types.MethodType( + _update_chunk_length, response + ) + + resp = super(CacheControlAdapter, self).build_response(request, response) + + # See if we should invalidate the cache. + if request.method in self.invalidating_methods and resp.ok: + cache_url = self.controller.cache_url(request.url) + self.cache.delete(cache_url) + + # Give the request a from_cache attr to let people use it + resp.from_cache = from_cache + + return resp + + def close(self): + self.cache.close() + super(CacheControlAdapter, self).close() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/cache.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/cache.py new file mode 100644 index 0000000..94e0773 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/cache.py @@ -0,0 +1,39 @@ +""" +The cache object API for implementing caches. The default is a thread +safe in-memory dictionary. +""" +from threading import Lock + + +class BaseCache(object): + + def get(self, key): + raise NotImplementedError() + + def set(self, key, value): + raise NotImplementedError() + + def delete(self, key): + raise NotImplementedError() + + def close(self): + pass + + +class DictCache(BaseCache): + + def __init__(self, init_dict=None): + self.lock = Lock() + self.data = init_dict or {} + + def get(self, key): + return self.data.get(key, None) + + def set(self, key, value): + with self.lock: + self.data.update({key: value}) + + def delete(self, key): + with self.lock: + if key in self.data: + self.data.pop(key) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py new file mode 100644 index 0000000..0e1658f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/__init__.py @@ -0,0 +1,2 @@ +from .file_cache import FileCache # noqa +from .redis_cache import RedisCache # noqa diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py new file mode 100644 index 0000000..1ba0080 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py @@ -0,0 +1,146 @@ +import hashlib +import os +from textwrap import dedent + +from ..cache import BaseCache +from ..controller import CacheController + +try: + FileNotFoundError +except NameError: + # py2.X + FileNotFoundError = (IOError, OSError) + + +def _secure_open_write(filename, fmode): + # We only want to write to this file, so open it in write only mode + flags = os.O_WRONLY + + # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only + # will open *new* files. + # We specify this because we want to ensure that the mode we pass is the + # mode of the file. + flags |= os.O_CREAT | os.O_EXCL + + # Do not follow symlinks to prevent someone from making a symlink that + # we follow and insecurely open a cache file. + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + + # On Windows we'll mark this file as binary + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + + # Before we open our file, we want to delete any existing file that is + # there + try: + os.remove(filename) + except (IOError, OSError): + # The file must not exist already, so we can just skip ahead to opening + pass + + # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a + # race condition happens between the os.remove and this line, that an + # error will be raised. Because we utilize a lockfile this should only + # happen if someone is attempting to attack us. + fd = os.open(filename, flags, fmode) + try: + return os.fdopen(fd, "wb") + + except: + # An error occurred wrapping our FD in a file object + os.close(fd) + raise + + +class FileCache(BaseCache): + + def __init__( + self, + directory, + forever=False, + filemode=0o0600, + dirmode=0o0700, + use_dir_lock=None, + lock_class=None, + ): + + if use_dir_lock is not None and lock_class is not None: + raise ValueError("Cannot use use_dir_lock and lock_class together") + + try: + from pip._vendor.lockfile import LockFile + from pip._vendor.lockfile.mkdirlockfile import MkdirLockFile + except ImportError: + notice = dedent( + """ + NOTE: In order to use the FileCache you must have + lockfile installed. You can install it via pip: + pip install lockfile + """ + ) + raise ImportError(notice) + + else: + if use_dir_lock: + lock_class = MkdirLockFile + + elif lock_class is None: + lock_class = LockFile + + self.directory = directory + self.forever = forever + self.filemode = filemode + self.dirmode = dirmode + self.lock_class = lock_class + + @staticmethod + def encode(x): + return hashlib.sha224(x.encode()).hexdigest() + + def _fn(self, name): + # NOTE: This method should not change as some may depend on it. + # See: https://github.com/ionrock/cachecontrol/issues/63 + hashed = self.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key): + name = self._fn(key) + try: + with open(name, "rb") as fh: + return fh.read() + + except FileNotFoundError: + return None + + def set(self, key, value): + name = self._fn(key) + + # Make sure the directory exists + try: + os.makedirs(os.path.dirname(name), self.dirmode) + except (IOError, OSError): + pass + + with self.lock_class(name) as lock: + # Write our actual file + with _secure_open_write(lock.path, self.filemode) as fh: + fh.write(value) + + def delete(self, key): + name = self._fn(key) + if not self.forever: + try: + os.remove(name) + except FileNotFoundError: + pass + + +def url_to_file_path(url, filecache): + """Return the file cache path based on the URL. + + This does not ensure the file exists! + """ + key = CacheController.cache_url(url) + return filecache._fn(key) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py new file mode 100644 index 0000000..ed705ce --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -0,0 +1,33 @@ +from __future__ import division + +from datetime import datetime +from pip._vendor.cachecontrol.cache import BaseCache + + +class RedisCache(BaseCache): + + def __init__(self, conn): + self.conn = conn + + def get(self, key): + return self.conn.get(key) + + def set(self, key, value, expires=None): + if not expires: + self.conn.set(key, value) + else: + expires = expires - datetime.utcnow() + self.conn.setex(key, int(expires.total_seconds()), value) + + def delete(self, key): + self.conn.delete(key) + + def clear(self): + """Helper for clearing all the keys in a database. Use with + caution!""" + for key in self.conn.keys(): + self.conn.delete(key) + + def close(self): + """Redis uses connection pooling, no need to close the connection.""" + pass diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/compat.py new file mode 100644 index 0000000..33b5aed --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/compat.py @@ -0,0 +1,29 @@ +try: + from urllib.parse import urljoin +except ImportError: + from urlparse import urljoin + + +try: + import cPickle as pickle +except ImportError: + import pickle + + +# Handle the case where the requests module has been patched to not have +# urllib3 bundled as part of its source. +try: + from pip._vendor.requests.packages.urllib3.response import HTTPResponse +except ImportError: + from pip._vendor.urllib3.response import HTTPResponse + +try: + from pip._vendor.requests.packages.urllib3.util import is_fp_closed +except ImportError: + from pip._vendor.urllib3.util import is_fp_closed + +# Replicate some six behaviour +try: + text_type = unicode +except NameError: + text_type = str diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/controller.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/controller.py new file mode 100644 index 0000000..1b2b943 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/controller.py @@ -0,0 +1,367 @@ +""" +The httplib2 algorithms ported for use with requests. +""" +import logging +import re +import calendar +import time +from email.utils import parsedate_tz + +from pip._vendor.requests.structures import CaseInsensitiveDict + +from .cache import DictCache +from .serialize import Serializer + + +logger = logging.getLogger(__name__) + +URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") + + +def parse_uri(uri): + """Parses a URI using the regex given in Appendix B of RFC 3986. + + (scheme, authority, path, query, fragment) = parse_uri(uri) + """ + groups = URI.match(uri).groups() + return (groups[1], groups[3], groups[4], groups[6], groups[8]) + + +class CacheController(object): + """An interface to see if request should cached or not. + """ + + def __init__( + self, cache=None, cache_etags=True, serializer=None, status_codes=None + ): + self.cache = cache or DictCache() + self.cache_etags = cache_etags + self.serializer = serializer or Serializer() + self.cacheable_status_codes = status_codes or (200, 203, 300, 301) + + @classmethod + def _urlnorm(cls, uri): + """Normalize the URL to create a safe key for the cache""" + (scheme, authority, path, query, fragment) = parse_uri(uri) + if not scheme or not authority: + raise Exception("Only absolute URIs are allowed. uri = %s" % uri) + + scheme = scheme.lower() + authority = authority.lower() + + if not path: + path = "/" + + # Could do syntax based normalization of the URI before + # computing the digest. See Section 6.2.2 of Std 66. + request_uri = query and "?".join([path, query]) or path + defrag_uri = scheme + "://" + authority + request_uri + + return defrag_uri + + @classmethod + def cache_url(cls, uri): + return cls._urlnorm(uri) + + def parse_cache_control(self, headers): + known_directives = { + # https://tools.ietf.org/html/rfc7234#section-5.2 + "max-age": (int, True), + "max-stale": (int, False), + "min-fresh": (int, True), + "no-cache": (None, False), + "no-store": (None, False), + "no-transform": (None, False), + "only-if-cached": (None, False), + "must-revalidate": (None, False), + "public": (None, False), + "private": (None, False), + "proxy-revalidate": (None, False), + "s-maxage": (int, True), + } + + cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) + + retval = {} + + for cc_directive in cc_headers.split(","): + if not cc_directive.strip(): + continue + + parts = cc_directive.split("=", 1) + directive = parts[0].strip() + + try: + typ, required = known_directives[directive] + except KeyError: + logger.debug("Ignoring unknown cache-control directive: %s", directive) + continue + + if not typ or not required: + retval[directive] = None + if typ: + try: + retval[directive] = typ(parts[1].strip()) + except IndexError: + if required: + logger.debug( + "Missing value for cache-control " "directive: %s", + directive, + ) + except ValueError: + logger.debug( + "Invalid value for cache-control directive " "%s, must be %s", + directive, + typ.__name__, + ) + + return retval + + def cached_request(self, request): + """ + Return a cached response if it exists in the cache, otherwise + return False. + """ + cache_url = self.cache_url(request.url) + logger.debug('Looking up "%s" in the cache', cache_url) + cc = self.parse_cache_control(request.headers) + + # Bail out if the request insists on fresh data + if "no-cache" in cc: + logger.debug('Request header has "no-cache", cache bypassed') + return False + + if "max-age" in cc and cc["max-age"] == 0: + logger.debug('Request header has "max_age" as 0, cache bypassed') + return False + + # Request allows serving from the cache, let's see if we find something + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return False + + # Check whether it can be deserialized + resp = self.serializer.loads(request, cache_data) + if not resp: + logger.warning("Cache entry deserialization failed, entry ignored") + return False + + # If we have a cached 301, return it immediately. We don't + # need to test our response for other headers b/c it is + # intrinsically "cacheable" as it is Permanent. + # See: + # https://tools.ietf.org/html/rfc7231#section-6.4.2 + # + # Client can try to refresh the value by repeating the request + # with cache busting headers as usual (ie no-cache). + if resp.status == 301: + msg = ( + 'Returning cached "301 Moved Permanently" response ' + "(ignoring date and etag information)" + ) + logger.debug(msg) + return resp + + headers = CaseInsensitiveDict(resp.headers) + if not headers or "date" not in headers: + if "etag" not in headers: + # Without date or etag, the cached response can never be used + # and should be deleted. + logger.debug("Purging cached response: no date or etag") + self.cache.delete(cache_url) + logger.debug("Ignoring cached response: no date") + return False + + now = time.time() + date = calendar.timegm(parsedate_tz(headers["date"])) + current_age = max(0, now - date) + logger.debug("Current age based on date: %i", current_age) + + # TODO: There is an assumption that the result will be a + # urllib3 response object. This may not be best since we + # could probably avoid instantiating or constructing the + # response until we know we need it. + resp_cc = self.parse_cache_control(headers) + + # determine freshness + freshness_lifetime = 0 + + # Check the max-age pragma in the cache control header + if "max-age" in resp_cc: + freshness_lifetime = resp_cc["max-age"] + logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) + + # If there isn't a max-age, check for an expires header + elif "expires" in headers: + expires = parsedate_tz(headers["expires"]) + if expires is not None: + expire_time = calendar.timegm(expires) - date + freshness_lifetime = max(0, expire_time) + logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) + + # Determine if we are setting freshness limit in the + # request. Note, this overrides what was in the response. + if "max-age" in cc: + freshness_lifetime = cc["max-age"] + logger.debug( + "Freshness lifetime from request max-age: %i", freshness_lifetime + ) + + if "min-fresh" in cc: + min_fresh = cc["min-fresh"] + # adjust our current age by our min fresh + current_age += min_fresh + logger.debug("Adjusted current age from min-fresh: %i", current_age) + + # Return entry if it is fresh enough + if freshness_lifetime > current_age: + logger.debug('The response is "fresh", returning cached response') + logger.debug("%i > %i", freshness_lifetime, current_age) + return resp + + # we're not fresh. If we don't have an Etag, clear it out + if "etag" not in headers: + logger.debug('The cached response is "stale" with no etag, purging') + self.cache.delete(cache_url) + + # return the original handler + return False + + def conditional_headers(self, request): + cache_url = self.cache_url(request.url) + resp = self.serializer.loads(request, self.cache.get(cache_url)) + new_headers = {} + + if resp: + headers = CaseInsensitiveDict(resp.headers) + + if "etag" in headers: + new_headers["If-None-Match"] = headers["ETag"] + + if "last-modified" in headers: + new_headers["If-Modified-Since"] = headers["Last-Modified"] + + return new_headers + + def cache_response(self, request, response, body=None, status_codes=None): + """ + Algorithm for caching requests. + + This assumes a requests Response object. + """ + # From httplib2: Don't cache 206's since we aren't going to + # handle byte range requests + cacheable_status_codes = status_codes or self.cacheable_status_codes + if response.status not in cacheable_status_codes: + logger.debug( + "Status code %s not in %s", response.status, cacheable_status_codes + ) + return + + response_headers = CaseInsensitiveDict(response.headers) + + # If we've been given a body, our response has a Content-Length, that + # Content-Length is valid then we can check to see if the body we've + # been given matches the expected size, and if it doesn't we'll just + # skip trying to cache it. + if ( + body is not None + and "content-length" in response_headers + and response_headers["content-length"].isdigit() + and int(response_headers["content-length"]) != len(body) + ): + return + + cc_req = self.parse_cache_control(request.headers) + cc = self.parse_cache_control(response_headers) + + cache_url = self.cache_url(request.url) + logger.debug('Updating cache with response from "%s"', cache_url) + + # Delete it from the cache if we happen to have it stored there + no_store = False + if "no-store" in cc: + no_store = True + logger.debug('Response header has "no-store"') + if "no-store" in cc_req: + no_store = True + logger.debug('Request header has "no-store"') + if no_store and self.cache.get(cache_url): + logger.debug('Purging existing cache entry to honor "no-store"') + self.cache.delete(cache_url) + if no_store: + return + + # If we've been given an etag, then keep the response + if self.cache_etags and "etag" in response_headers: + logger.debug("Caching due to etag") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + # Add to the cache any 301s. We do this before looking that + # the Date headers. + elif response.status == 301: + logger.debug("Caching permanant redirect") + self.cache.set(cache_url, self.serializer.dumps(request, response)) + + # Add to the cache if the response headers demand it. If there + # is no date header then we can't do anything about expiring + # the cache. + elif "date" in response_headers: + # cache when there is a max-age > 0 + if "max-age" in cc and cc["max-age"] > 0: + logger.debug("Caching b/c date exists and max-age > 0") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + # If the request can expire, it means we should cache it + # in the meantime. + elif "expires" in response_headers: + if response_headers["expires"]: + logger.debug("Caching b/c of expires header") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + def update_cached_response(self, request, response): + """On a 304 we will get a new set of headers that we want to + update our cached value with, assuming we have one. + + This should only ever be called when we've sent an ETag and + gotten a 304 as the response. + """ + cache_url = self.cache_url(request.url) + + cached_response = self.serializer.loads(request, self.cache.get(cache_url)) + + if not cached_response: + # we didn't have a cached response + return response + + # Lets update our headers with the headers from the new request: + # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 + # + # The server isn't supposed to send headers that would make + # the cached body invalid. But... just in case, we'll be sure + # to strip out ones we know that might be problmatic due to + # typical assumptions. + excluded_headers = ["content-length"] + + cached_response.headers.update( + dict( + (k, v) + for k, v in response.headers.items() + if k.lower() not in excluded_headers + ) + ) + + # we want a 200 b/c we have content via the cache + cached_response.status = 200 + + # update our cache + self.cache.set(cache_url, self.serializer.dumps(request, cached_response)) + + return cached_response diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py new file mode 100644 index 0000000..30ed4c5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/filewrapper.py @@ -0,0 +1,80 @@ +from io import BytesIO + + +class CallbackFileWrapper(object): + """ + Small wrapper around a fp object which will tee everything read into a + buffer, and when that file is closed it will execute a callback with the + contents of that buffer. + + All attributes are proxied to the underlying file object. + + This class uses members with a double underscore (__) leading prefix so as + not to accidentally shadow an attribute. + """ + + def __init__(self, fp, callback): + self.__buf = BytesIO() + self.__fp = fp + self.__callback = callback + + def __getattr__(self, name): + # The vaguaries of garbage collection means that self.__fp is + # not always set. By using __getattribute__ and the private + # name[0] allows looking up the attribute value and raising an + # AttributeError when it doesn't exist. This stop thigns from + # infinitely recursing calls to getattr in the case where + # self.__fp hasn't been set. + # + # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers + fp = self.__getattribute__("_CallbackFileWrapper__fp") + return getattr(fp, name) + + def __is_fp_closed(self): + try: + return self.__fp.fp is None + + except AttributeError: + pass + + try: + return self.__fp.closed + + except AttributeError: + pass + + # We just don't cache it then. + # TODO: Add some logging here... + return False + + def _close(self): + if self.__callback: + self.__callback(self.__buf.getvalue()) + + # We assign this to None here, because otherwise we can get into + # really tricky problems where the CPython interpreter dead locks + # because the callback is holding a reference to something which + # has a __del__ method. Setting this to None breaks the cycle + # and allows the garbage collector to do it's thing normally. + self.__callback = None + + def read(self, amt=None): + data = self.__fp.read(amt) + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data + + def _safe_read(self, amt): + data = self.__fp._safe_read(amt) + if amt == 2 and data == b"\r\n": + # urllib executes this read to toss the CRLF at the end + # of the chunk. + return data + + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/heuristics.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/heuristics.py new file mode 100644 index 0000000..6c0e979 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/heuristics.py @@ -0,0 +1,135 @@ +import calendar +import time + +from email.utils import formatdate, parsedate, parsedate_tz + +from datetime import datetime, timedelta + +TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" + + +def expire_after(delta, date=None): + date = date or datetime.utcnow() + return date + delta + + +def datetime_to_header(dt): + return formatdate(calendar.timegm(dt.timetuple())) + + +class BaseHeuristic(object): + + def warning(self, response): + """ + Return a valid 1xx warning header value describing the cache + adjustments. + + The response is provided too allow warnings like 113 + http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need + to explicitly say response is over 24 hours old. + """ + return '110 - "Response is Stale"' + + def update_headers(self, response): + """Update the response headers with any new headers. + + NOTE: This SHOULD always include some Warning header to + signify that the response was cached by the client, not + by way of the provided headers. + """ + return {} + + def apply(self, response): + updated_headers = self.update_headers(response) + + if updated_headers: + response.headers.update(updated_headers) + warning_header_value = self.warning(response) + if warning_header_value is not None: + response.headers.update({"Warning": warning_header_value}) + + return response + + +class OneDayCache(BaseHeuristic): + """ + Cache the response by providing an expires 1 day in the + future. + """ + + def update_headers(self, response): + headers = {} + + if "expires" not in response.headers: + date = parsedate(response.headers["date"]) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) + headers["expires"] = datetime_to_header(expires) + headers["cache-control"] = "public" + return headers + + +class ExpiresAfter(BaseHeuristic): + """ + Cache **all** requests for a defined time period. + """ + + def __init__(self, **kw): + self.delta = timedelta(**kw) + + def update_headers(self, response): + expires = expire_after(self.delta) + return {"expires": datetime_to_header(expires), "cache-control": "public"} + + def warning(self, response): + tmpl = "110 - Automatically cached for %s. Response might be stale" + return tmpl % self.delta + + +class LastModified(BaseHeuristic): + """ + If there is no Expires header already, fall back on Last-Modified + using the heuristic from + http://tools.ietf.org/html/rfc7234#section-4.2.2 + to calculate a reasonable value. + + Firefox also does something like this per + https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ + http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 + Unlike mozilla we limit this to 24-hr. + """ + cacheable_by_default_statuses = { + 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 + } + + def update_headers(self, resp): + headers = resp.headers + + if "expires" in headers: + return {} + + if "cache-control" in headers and headers["cache-control"] != "public": + return {} + + if resp.status not in self.cacheable_by_default_statuses: + return {} + + if "date" not in headers or "last-modified" not in headers: + return {} + + date = calendar.timegm(parsedate_tz(headers["date"])) + last_modified = parsedate(headers["last-modified"]) + if date is None or last_modified is None: + return {} + + now = time.time() + current_age = max(0, now - date) + delta = date - calendar.timegm(last_modified) + freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) + if freshness_lifetime <= current_age: + return {} + + expires = date + freshness_lifetime + return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} + + def warning(self, resp): + return None diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/serialize.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/serialize.py new file mode 100644 index 0000000..ec43ff2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/serialize.py @@ -0,0 +1,186 @@ +import base64 +import io +import json +import zlib + +from pip._vendor import msgpack +from pip._vendor.requests.structures import CaseInsensitiveDict + +from .compat import HTTPResponse, pickle, text_type + + +def _b64_decode_bytes(b): + return base64.b64decode(b.encode("ascii")) + + +def _b64_decode_str(s): + return _b64_decode_bytes(s).decode("utf8") + + +class Serializer(object): + + def dumps(self, request, response, body=None): + response_headers = CaseInsensitiveDict(response.headers) + + if body is None: + body = response.read(decode_content=False) + + # NOTE: 99% sure this is dead code. I'm only leaving it + # here b/c I don't have a test yet to prove + # it. Basically, before using + # `cachecontrol.filewrapper.CallbackFileWrapper`, + # this made an effort to reset the file handle. The + # `CallbackFileWrapper` short circuits this code by + # setting the body as the content is consumed, the + # result being a `body` argument is *always* passed + # into cache_response, and in turn, + # `Serializer.dump`. + response._fp = io.BytesIO(body) + + # NOTE: This is all a bit weird, but it's really important that on + # Python 2.x these objects are unicode and not str, even when + # they contain only ascii. The problem here is that msgpack + # understands the difference between unicode and bytes and we + # have it set to differentiate between them, however Python 2 + # doesn't know the difference. Forcing these to unicode will be + # enough to have msgpack know the difference. + data = { + u"response": { + u"body": body, + u"headers": dict( + (text_type(k), text_type(v)) for k, v in response.headers.items() + ), + u"status": response.status, + u"version": response.version, + u"reason": text_type(response.reason), + u"strict": response.strict, + u"decode_content": response.decode_content, + } + } + + # Construct our vary headers + data[u"vary"] = {} + if u"vary" in response_headers: + varied_headers = response_headers[u"vary"].split(",") + for header in varied_headers: + header = text_type(header).strip() + header_value = request.headers.get(header, None) + if header_value is not None: + header_value = text_type(header_value) + data[u"vary"][header] = header_value + + return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) + + def loads(self, request, data): + # Short circuit if we've been given an empty set of data + if not data: + return + + # Determine what version of the serializer the data was serialized + # with + try: + ver, data = data.split(b",", 1) + except ValueError: + ver = b"cc=0" + + # Make sure that our "ver" is actually a version and isn't a false + # positive from a , being in the data stream. + if ver[:3] != b"cc=": + data = ver + data + ver = b"cc=0" + + # Get the version number out of the cc=N + ver = ver.split(b"=", 1)[-1].decode("ascii") + + # Dispatch to the actual load method for the given version + try: + return getattr(self, "_loads_v{}".format(ver))(request, data) + + except AttributeError: + # This is a version we don't have a loads function for, so we'll + # just treat it as a miss and return None + return + + def prepare_response(self, request, cached): + """Verify our vary headers match and construct a real urllib3 + HTTPResponse object. + """ + # Special case the '*' Vary value as it means we cannot actually + # determine if the cached response is suitable for this request. + if "*" in cached.get("vary", {}): + return + + # Ensure that the Vary headers for the cached response match our + # request + for header, value in cached.get("vary", {}).items(): + if request.headers.get(header, None) != value: + return + + body_raw = cached["response"].pop("body") + + headers = CaseInsensitiveDict(data=cached["response"]["headers"]) + if headers.get("transfer-encoding", "") == "chunked": + headers.pop("transfer-encoding") + + cached["response"]["headers"] = headers + + try: + body = io.BytesIO(body_raw) + except TypeError: + # This can happen if cachecontrol serialized to v1 format (pickle) + # using Python 2. A Python 2 str(byte string) will be unpickled as + # a Python 3 str (unicode string), which will cause the above to + # fail with: + # + # TypeError: 'str' does not support the buffer interface + body = io.BytesIO(body_raw.encode("utf8")) + + return HTTPResponse(body=body, preload_content=False, **cached["response"]) + + def _loads_v0(self, request, data): + # The original legacy cache data. This doesn't contain enough + # information to construct everything we need, so we'll treat this as + # a miss. + return + + def _loads_v1(self, request, data): + try: + cached = pickle.loads(data) + except ValueError: + return + + return self.prepare_response(request, cached) + + def _loads_v2(self, request, data): + try: + cached = json.loads(zlib.decompress(data).decode("utf8")) + except (ValueError, zlib.error): + return + + # We need to decode the items that we've base64 encoded + cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) + cached["response"]["headers"] = dict( + (_b64_decode_str(k), _b64_decode_str(v)) + for k, v in cached["response"]["headers"].items() + ) + cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) + cached["vary"] = dict( + (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) + for k, v in cached["vary"].items() + ) + + return self.prepare_response(request, cached) + + def _loads_v3(self, request, data): + # Due to Python 2 encoding issues, it's impossible to know for sure + # exactly how to load v3 entries, thus we'll treat these as a miss so + # that they get rewritten out as v4 entries. + return + + def _loads_v4(self, request, data): + try: + cached = msgpack.loads(data, encoding="utf-8") + except ValueError: + return + + return self.prepare_response(request, cached) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/wrapper.py b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/wrapper.py new file mode 100644 index 0000000..265bfc8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/cachecontrol/wrapper.py @@ -0,0 +1,29 @@ +from .adapter import CacheControlAdapter +from .cache import DictCache + + +def CacheControl( + sess, + cache=None, + cache_etags=True, + serializer=None, + heuristic=None, + controller_class=None, + adapter_class=None, + cacheable_methods=None, +): + + cache = cache or DictCache() + adapter_class = adapter_class or CacheControlAdapter + adapter = adapter_class( + cache, + cache_etags=cache_etags, + serializer=serializer, + heuristic=heuristic, + controller_class=controller_class, + cacheable_methods=cacheable_methods, + ) + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + return sess diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__init__.py new file mode 100644 index 0000000..aa329fb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__init__.py @@ -0,0 +1,3 @@ +from .core import where, old_where + +__version__ = "2018.08.24" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__main__.py b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__main__.py new file mode 100644 index 0000000..ae2aff5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/__main__.py @@ -0,0 +1,2 @@ +from pip._vendor.certifi import where +print(where()) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/certifi/cacert.pem b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/cacert.pem new file mode 100644 index 0000000..85de024 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/cacert.pem @@ -0,0 +1,4300 @@ + +# 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=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Label: "GlobalSign Root CA - R2" +# Serial: 4835703278459682885658125 +# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 +# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe +# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 3 Public Primary Certification Authority - G3" +# Serial: 206684696279472310254277870180966723415 +# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 +# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 +# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----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=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Label: "AddTrust External Root" +# Serial: 1 +# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f +# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 +# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----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=GeoTrust Global CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. +# Label: "GeoTrust Global CA" +# Serial: 144470 +# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 +# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 +# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Label: "GeoTrust Universal CA" +# Serial: 1 +# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 +# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 +# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Universal CA 2" +# Serial: 1 +# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 +# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 +# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Label: "Visa eCommerce Root" +# Serial: 25952180776285836048024890241505565794 +# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 +# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 +# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----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 Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Label: "QuoVadis Root CA" +# Serial: 985026699 +# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 +# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 +# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----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=Sonera Class2 CA O=Sonera +# Subject: CN=Sonera Class2 CA O=Sonera +# Label: "Sonera Class 2 Root CA" +# Serial: 29 +# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb +# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 +# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----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: O=Government Root Certification Authority +# Subject: O=Government Root Certification Authority +# Label: "Taiwan GRCA" +# Serial: 42023070807708724159991140556527066870 +# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e +# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 +# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----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=Class 2 Primary CA O=Certplus +# Subject: CN=Class 2 Primary CA O=Certplus +# Label: "Certplus Class 2 Primary CA" +# Serial: 177770208045934040241468760488327595043 +# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b +# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb +# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Label: "DST Root CA X3" +# Serial: 91299735575339953335919266965803778155 +# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 +# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 +# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----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----- +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 +-----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----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Label: "GeoTrust Primary Certification Authority" +# Serial: 32798226551256963324313806436981982369 +# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf +# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 +# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA" +# Serial: 69529181992039203566298953787712940909 +# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 +# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 +# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" +# Serial: 33037644167568058970164719475676101450 +# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c +# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 +# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----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=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Label: "Network Solutions Certificate Authority" +# Serial: 116697915152937497490437556386812487904 +# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e +# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce +# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----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=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GA CA" +# Serial: 86718877871133159090080555911823548314 +# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 +# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 +# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----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: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Label: "Deutsche Telekom Root CA 2" +# Serial: 38 +# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08 +# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf +# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3 +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc +# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc +# Label: "Cybertrust Global Root" +# Serial: 4835703278459682877484360 +# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 +# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 +# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----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=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G3" +# Serial: 28809105769928564313984085209975885599 +# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 +# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd +# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G2" +# Serial: 71758320672825410020661621085256472406 +# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f +# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 +# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G3" +# Serial: 127614157056681299805556476275995414779 +# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 +# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 +# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G2" +# Serial: 80682863203381065782177908751794619243 +# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a +# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 +# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Universal Root Certification Authority" +# Serial: 85209574734084581917763752644031726877 +# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 +# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 +# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" +# Serial: 63143484348153506665311985501458640051 +# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 +# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a +# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----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=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G2" +# Serial: 10000012 +# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a +# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 +# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----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=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Label: "Chambers of Commerce Root - 2008" +# Serial: 11806822484801597146 +# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 +# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c +# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Label: "Global Chambersign Root - 2008" +# Serial: 14541511773111788494 +# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 +# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c +# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----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=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2011" +# Serial: 0 +# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 +# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d +# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----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: O=Trustis Limited OU=Trustis FPS Root CA +# Subject: O=Trustis Limited OU=Trustis FPS Root CA +# Label: "Trustis FPS Root CA" +# Serial: 36053640375399034304724988975563710553 +# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d +# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 +# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----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=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Label: "EE Certification Centre Root CA" +# Serial: 112324828676200291871926431888494945866 +# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f +# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 +# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----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 - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 14367148294922964480859022125800977897474 +# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e +# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb +# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----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=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G3" +# Serial: 10003001 +# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 +# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc +# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX +DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP +cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW +IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX +xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy +KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR +9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az +5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 +6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 +Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP +bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt +BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt +XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd +INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp +LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 +Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp +gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh +/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw +0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A +fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq +4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR +1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ +QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM +94B7IWcnMFk= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden EV Root CA" +# Serial: 10000013 +# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba +# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb +# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----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=Certinomis - Root CA O=Certinomis OU=0002 433998903 +# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 +# Label: "Certinomis - Root CA" +# Serial: 1 +# MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f +# SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8 +# SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb +BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz +MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx +FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g +Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 +fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl +LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV +WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF +TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb +5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc +CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri +wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ +wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG +m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 +F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng +WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 +2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ +0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw +F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS +g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj +qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN +h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ +ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V +btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj +Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ +8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW +gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= +-----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=LuxTrust Global Root 2 O=LuxTrust S.A. +# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A. +# Label: "LuxTrust Global Root 2" +# Serial: 59914338225734147123941058376788110305822489521 +# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c +# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f +# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5 +-----BEGIN CERTIFICATE----- +MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL +BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV +BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw +MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B +LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F +ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem +hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1 +EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn +Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4 +zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ +96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m +j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g +DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+ +8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j +X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH +hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB +KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0 +Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT ++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL +BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9 +BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO +jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9 +loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c +qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+ +2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/ +JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre +zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf +LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+ +x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6 +oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr +-----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=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-1" +# Serial: 15752444095811006489 +# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45 +# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a +# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-2" +# Serial: 2711694510199101698 +# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64 +# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0 +# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor ECA-1" +# Serial: 9548242946988625984 +# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c +# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd +# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----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----- diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/certifi/core.py b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/core.py new file mode 100644 index 0000000..eab9d1d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/certifi/core.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem. +""" +import os +import warnings + + +class DeprecatedBundleWarning(DeprecationWarning): + """ + The weak security bundle is being deprecated. Please bother your service + provider to get them to stop using cross-signed roots. + """ + + +def where(): + f = os.path.dirname(__file__) + + return os.path.join(f, 'cacert.pem') + + +def old_where(): + warnings.warn( + "The weak security bundle has been removed. certifi.old_where() is now an alias " + "of certifi.where(). Please update your code to use certifi.where() instead. " + "certifi.old_where() will be removed in 2018.", + DeprecatedBundleWarning + ) + return where() + +if __name__ == '__main__': + print(where()) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__init__.py new file mode 100644 index 0000000..0f9f820 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/__init__.py @@ -0,0 +1,39 @@ +######################## BEGIN LICENSE BLOCK ######################## +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +from .compat import PY2, PY3 +from .universaldetector import UniversalDetector +from .version import __version__, VERSION + + +def detect(byte_str): + """ + Detect the encoding of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{0}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + detector = UniversalDetector() + detector.feed(byte_str) + return detector.close() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5freq.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5freq.py new file mode 100644 index 0000000..38f3251 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5freq.py @@ -0,0 +1,386 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Big5 frequency table +# by Taiwan's Mandarin Promotion Council +# <http://www.edu.tw:81/mandr/> +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +BIG5_CHAR_TO_FREQ_ORDER = ( + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 +) + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5prober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5prober.py new file mode 100644 index 0000000..98f9970 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/big5prober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import Big5DistributionAnalysis +from .mbcssm import BIG5_SM_MODEL + + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + super(Big5Prober, self).__init__() + self.coding_sm = CodingStateMachine(BIG5_SM_MODEL) + self.distribution_analyzer = Big5DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "Big5" + + @property + def language(self): + return "Chinese" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/chardistribution.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/chardistribution.py new file mode 100644 index 0000000..c0395f4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/chardistribution.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .euctwfreq import (EUCTW_CHAR_TO_FREQ_ORDER, EUCTW_TABLE_SIZE, + EUCTW_TYPICAL_DISTRIBUTION_RATIO) +from .euckrfreq import (EUCKR_CHAR_TO_FREQ_ORDER, EUCKR_TABLE_SIZE, + EUCKR_TYPICAL_DISTRIBUTION_RATIO) +from .gb2312freq import (GB2312_CHAR_TO_FREQ_ORDER, GB2312_TABLE_SIZE, + GB2312_TYPICAL_DISTRIBUTION_RATIO) +from .big5freq import (BIG5_CHAR_TO_FREQ_ORDER, BIG5_TABLE_SIZE, + BIG5_TYPICAL_DISTRIBUTION_RATIO) +from .jisfreq import (JIS_CHAR_TO_FREQ_ORDER, JIS_TABLE_SIZE, + JIS_TYPICAL_DISTRIBUTION_RATIO) + + +class CharDistributionAnalysis(object): + ENOUGH_DATA_THRESHOLD = 1024 + SURE_YES = 0.99 + SURE_NO = 0.01 + MINIMUM_DATA_THRESHOLD = 3 + + def __init__(self): + # Mapping table to get frequency order from char order (get from + # GetOrder()) + self._char_to_freq_order = None + self._table_size = None # Size of above table + # This is a constant value which varies from language to language, + # used in calculating confidence. See + # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html + # for further detail. + self.typical_distribution_ratio = None + self._done = None + self._total_chars = None + self._freq_chars = None + self.reset() + + def reset(self): + """reset analyser, clear any state""" + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + self._total_chars = 0 # Total characters encountered + # The number of characters whose frequency order is less than 512 + self._freq_chars = 0 + + def feed(self, char, char_len): + """feed a character with known length""" + if char_len == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(char) + else: + order = -1 + if order >= 0: + self._total_chars += 1 + # order is valid + if order < self._table_size: + if 512 > self._char_to_freq_order[order]: + self._freq_chars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, + # return negative answer + if self._total_chars <= 0 or self._freq_chars <= self.MINIMUM_DATA_THRESHOLD: + return self.SURE_NO + + if self._total_chars != self._freq_chars: + r = (self._freq_chars / ((self._total_chars - self._freq_chars) + * self.typical_distribution_ratio)) + if r < self.SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return self.SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. + # For charset detection, certain amount of data is enough + return self._total_chars > self.ENOUGH_DATA_THRESHOLD + + def get_order(self, byte_str): + # We do not handle characters based on the original encoding string, + # but convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency + # table. + return -1 + + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCTWDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCTW_CHAR_TO_FREQ_ORDER + self._table_size = EUCTW_TABLE_SIZE + self.typical_distribution_ratio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xC4: + return 94 * (first_char - 0xC4) + byte_str[1] - 0xA1 + else: + return -1 + + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCKRDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCKR_CHAR_TO_FREQ_ORDER + self._table_size = EUCKR_TABLE_SIZE + self.typical_distribution_ratio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xB0: + return 94 * (first_char - 0xB0) + byte_str[1] - 0xA1 + else: + return -1 + + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(GB2312DistributionAnalysis, self).__init__() + self._char_to_freq_order = GB2312_CHAR_TO_FREQ_ORDER + self._table_size = GB2312_TABLE_SIZE + self.typical_distribution_ratio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0xB0) and (second_char >= 0xA1): + return 94 * (first_char - 0xB0) + second_char - 0xA1 + else: + return -1 + + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(Big5DistributionAnalysis, self).__init__() + self._char_to_freq_order = BIG5_CHAR_TO_FREQ_ORDER + self._table_size = BIG5_TABLE_SIZE + self.typical_distribution_ratio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if first_char >= 0xA4: + if second_char >= 0xA1: + return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 + else: + return 157 * (first_char - 0xA4) + second_char - 0x40 + else: + return -1 + + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(SJISDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0x81) and (first_char <= 0x9F): + order = 188 * (first_char - 0x81) + elif (first_char >= 0xE0) and (first_char <= 0xEF): + order = 188 * (first_char - 0xE0 + 31) + else: + return -1 + order = order + second_char - 0x40 + if second_char > 0x7F: + order = -1 + return order + + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCJPDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + char = byte_str[0] + if char >= 0xA0: + return 94 * (char - 0xA1) + byte_str[1] - 0xa1 + else: + return -1 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py new file mode 100644 index 0000000..8b3738e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetgroupprober.py @@ -0,0 +1,106 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState +from .charsetprober import CharSetProber + + +class CharSetGroupProber(CharSetProber): + def __init__(self, lang_filter=None): + super(CharSetGroupProber, self).__init__(lang_filter=lang_filter) + self._active_num = 0 + self.probers = [] + self._best_guess_prober = None + + def reset(self): + super(CharSetGroupProber, self).reset() + self._active_num = 0 + for prober in self.probers: + if prober: + prober.reset() + prober.active = True + self._active_num += 1 + self._best_guess_prober = None + + @property + def charset_name(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.charset_name + + @property + def language(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.language + + def feed(self, byte_str): + for prober in self.probers: + if not prober: + continue + if not prober.active: + continue + state = prober.feed(byte_str) + if not state: + continue + if state == ProbingState.FOUND_IT: + self._best_guess_prober = prober + return self.state + elif state == ProbingState.NOT_ME: + prober.active = False + self._active_num -= 1 + if self._active_num <= 0: + self._state = ProbingState.NOT_ME + return self.state + return self.state + + def get_confidence(self): + state = self.state + if state == ProbingState.FOUND_IT: + return 0.99 + elif state == ProbingState.NOT_ME: + return 0.01 + best_conf = 0.0 + self._best_guess_prober = None + for prober in self.probers: + if not prober: + continue + if not prober.active: + self.logger.debug('%s not active', prober.charset_name) + continue + conf = prober.get_confidence() + self.logger.debug('%s %s confidence = %s', prober.charset_name, prober.language, conf) + if best_conf < conf: + best_conf = conf + self._best_guess_prober = prober + if not self._best_guess_prober: + return 0.0 + return best_conf diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetprober.py new file mode 100644 index 0000000..eac4e59 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/charsetprober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging +import re + +from .enums import ProbingState + + +class CharSetProber(object): + + SHORTCUT_THRESHOLD = 0.95 + + def __init__(self, lang_filter=None): + self._state = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + + def reset(self): + self._state = ProbingState.DETECTING + + @property + def charset_name(self): + return None + + def feed(self, buf): + pass + + @property + def state(self): + return self._state + + def get_confidence(self): + return 0.0 + + @staticmethod + def filter_high_byte_only(buf): + buf = re.sub(b'([\x00-\x7F])+', b' ', buf) + return buf + + @staticmethod + def filter_international_words(buf): + """ + We define three types of bytes: + alphabet: english alphabets [a-zA-Z] + international: international characters [\x80-\xFF] + marker: everything else [^a-zA-Z\x80-\xFF] + + The input buffer can be thought to contain a series of words delimited + by markers. This function works to filter all words that contain at + least one international character. All contiguous sequences of markers + are replaced by a single space ascii character. + + This filter applies to all scripts which do not use English characters. + """ + filtered = bytearray() + + # This regex expression filters out only words that have at-least one + # international character. The word may include one marker character at + # the end. + words = re.findall(b'[a-zA-Z]*[\x80-\xFF]+[a-zA-Z]*[^a-zA-Z\x80-\xFF]?', + buf) + + for word in words: + filtered.extend(word[:-1]) + + # If the last character in the word is a marker, replace it with a + # space as markers shouldn't affect our analysis (they are used + # similarly across all languages and may thus have similar + # frequencies). + last_char = word[-1:] + if not last_char.isalpha() and last_char < b'\x80': + last_char = b' ' + filtered.extend(last_char) + + return filtered + + @staticmethod + def filter_with_english_letters(buf): + """ + Returns a copy of ``buf`` that retains only the sequences of English + alphabet and high byte characters that are not between <> characters. + Also retains English alphabet and high byte characters immediately + before occurrences of >. + + This filter can be applied to all scripts which contain both English + characters and extended ASCII characters, but is currently only used by + ``Latin1Prober``. + """ + filtered = bytearray() + in_tag = False + prev = 0 + + for curr in range(len(buf)): + # Slice here to get bytes instead of an int with Python 3 + buf_char = buf[curr:curr + 1] + # Check if we're coming out of or entering an HTML tag + if buf_char == b'>': + in_tag = False + elif buf_char == b'<': + in_tag = True + + # If current character is not extended-ASCII and not alphabetic... + if buf_char < b'\x80' and not buf_char.isalpha(): + # ...and we're not in a tag + if curr > prev and not in_tag: + # Keep everything after last non-extended-ASCII, + # non-alphabetic character + filtered.extend(buf[prev:curr]) + # Output a space to delimit stretch we kept + filtered.extend(b' ') + prev = curr + 1 + + # If we're not in a tag... + if not in_tag: + # Keep everything after last non-extended-ASCII, non-alphabetic + # character + filtered.extend(buf[prev:]) + + return filtered diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/chardetect.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/chardetect.py new file mode 100644 index 0000000..c61136b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cli/chardetect.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +""" +Script which takes one or more file paths and reports on their detected +encodings + +Example:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +If no paths are provided, it takes its input from stdin. + +""" + +from __future__ import absolute_import, print_function, unicode_literals + +import argparse +import sys + +from pip._vendor.chardet import __version__ +from pip._vendor.chardet.compat import PY2 +from pip._vendor.chardet.universaldetector import UniversalDetector + + +def description_of(lines, name='stdin'): + """ + Return a string describing the probable encoding of a file or + list of strings. + + :param lines: The lines to get the encoding of. + :type lines: Iterable of bytes + :param name: Name of file or collection of lines + :type name: str + """ + u = UniversalDetector() + for line in lines: + line = bytearray(line) + u.feed(line) + # shortcut out of the loop to save reading further - particularly useful if we read a BOM. + if u.done: + break + u.close() + result = u.result + if PY2: + name = name.decode(sys.getfilesystemencoding(), 'ignore') + if result['encoding']: + return '{0}: {1} with confidence {2}'.format(name, result['encoding'], + result['confidence']) + else: + return '{0}: no result'.format(name) + + +def main(argv=None): + """ + Handles command line arguments and gets things started. + + :param argv: List of arguments, as if specified on the command-line. + If None, ``sys.argv[1:]`` is used instead. + :type argv: list of str + """ + # Get command line arguments + parser = argparse.ArgumentParser( + description="Takes one or more file paths and reports their detected \ + encodings") + parser.add_argument('input', + help='File whose encoding we would like to determine. \ + (default: stdin)', + type=argparse.FileType('rb'), nargs='*', + default=[sys.stdin if PY2 else sys.stdin.buffer]) + parser.add_argument('--version', action='version', + version='%(prog)s {0}'.format(__version__)) + args = parser.parse_args(argv) + + for f in args.input: + if f.isatty(): + print("You are running chardetect interactively. Press " + + "CTRL-D twice at the start of a blank line to signal the " + + "end of your input. If you want help, run chardetect " + + "--help\n", file=sys.stderr) + print(description_of(f, f.name)) + + +if __name__ == '__main__': + main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/codingstatemachine.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/codingstatemachine.py new file mode 100644 index 0000000..68fba44 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/codingstatemachine.py @@ -0,0 +1,88 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging + +from .enums import MachineState + + +class CodingStateMachine(object): + """ + A state machine to verify a byte sequence for a particular encoding. For + each byte the detector receives, it will feed that byte to every active + state machine available, one byte at a time. The state machine changes its + state based on its previous state and the byte it receives. There are 3 + states in a state machine that are of interest to an auto-detector: + + START state: This is the state to start with, or a legal byte sequence + (i.e. a valid code point) for character has been identified. + + ME state: This indicates that the state machine identified a byte sequence + that is specific to the charset it is designed for and that + there is no other possible encoding which can contain this byte + sequence. This will to lead to an immediate positive answer for + the detector. + + ERROR state: This indicates the state machine identified an illegal byte + sequence for that encoding. This will lead to an immediate + negative answer for this encoding. Detector will exclude this + encoding from consideration from here on. + """ + def __init__(self, sm): + self._model = sm + self._curr_byte_pos = 0 + self._curr_char_len = 0 + self._curr_state = None + self.logger = logging.getLogger(__name__) + self.reset() + + def reset(self): + self._curr_state = MachineState.START + + def next_state(self, c): + # for each byte we get its class + # if it is first byte, we also get byte length + byte_class = self._model['class_table'][c] + if self._curr_state == MachineState.START: + self._curr_byte_pos = 0 + self._curr_char_len = self._model['char_len_table'][byte_class] + # from byte's class and state_table, we get its next state + curr_state = (self._curr_state * self._model['class_factor'] + + byte_class) + self._curr_state = self._model['state_table'][curr_state] + self._curr_byte_pos += 1 + return self._curr_state + + def get_current_charlen(self): + return self._curr_char_len + + def get_coding_state_machine(self): + return self._model['name'] + + @property + def language(self): + return self._model['language'] diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/compat.py new file mode 100644 index 0000000..ddd7468 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/compat.py @@ -0,0 +1,34 @@ +######################## BEGIN LICENSE BLOCK ######################## +# Contributor(s): +# Dan Blanchard +# Ian Cordasco +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys + + +if sys.version_info < (3, 0): + PY2 = True + PY3 = False + base_str = (str, unicode) + text_type = unicode +else: + PY2 = False + PY3 = True + base_str = (bytes, str) + text_type = str diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cp949prober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cp949prober.py new file mode 100644 index 0000000..efd793a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/cp949prober.py @@ -0,0 +1,49 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .chardistribution import EUCKRDistributionAnalysis +from .codingstatemachine import CodingStateMachine +from .mbcharsetprober import MultiByteCharSetProber +from .mbcssm import CP949_SM_MODEL + + +class CP949Prober(MultiByteCharSetProber): + def __init__(self): + super(CP949Prober, self).__init__() + self.coding_sm = CodingStateMachine(CP949_SM_MODEL) + # NOTE: CP949 is a superset of EUC-KR, so the distribution should be + # not different. + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "CP949" + + @property + def language(self): + return "Korean" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/enums.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/enums.py new file mode 100644 index 0000000..0451207 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/enums.py @@ -0,0 +1,76 @@ +""" +All of the Enums that are used throughout the chardet package. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + + +class InputState(object): + """ + This enum represents the different states a universal detector can be in. + """ + PURE_ASCII = 0 + ESC_ASCII = 1 + HIGH_BYTE = 2 + + +class LanguageFilter(object): + """ + This enum represents the different language filters we can apply to a + ``UniversalDetector``. + """ + CHINESE_SIMPLIFIED = 0x01 + CHINESE_TRADITIONAL = 0x02 + JAPANESE = 0x04 + KOREAN = 0x08 + NON_CJK = 0x10 + ALL = 0x1F + CHINESE = CHINESE_SIMPLIFIED | CHINESE_TRADITIONAL + CJK = CHINESE | JAPANESE | KOREAN + + +class ProbingState(object): + """ + This enum represents the different states a prober can be in. + """ + DETECTING = 0 + FOUND_IT = 1 + NOT_ME = 2 + + +class MachineState(object): + """ + This enum represents the different states a state machine can be in. + """ + START = 0 + ERROR = 1 + ITS_ME = 2 + + +class SequenceLikelihood(object): + """ + This enum represents the likelihood of a character following the previous one. + """ + NEGATIVE = 0 + UNLIKELY = 1 + LIKELY = 2 + POSITIVE = 3 + + @classmethod + def get_num_categories(cls): + """:returns: The number of likelihood categories in the enum.""" + return 4 + + +class CharacterCategory(object): + """ + This enum represents the different categories language models for + ``SingleByteCharsetProber`` put characters into. + + Anything less than CONTROL is considered a letter. + """ + UNDEFINED = 255 + LINE_BREAK = 254 + SYMBOL = 253 + DIGIT = 252 + CONTROL = 251 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escprober.py new file mode 100644 index 0000000..c70493f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escprober.py @@ -0,0 +1,101 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .codingstatemachine import CodingStateMachine +from .enums import LanguageFilter, ProbingState, MachineState +from .escsm import (HZ_SM_MODEL, ISO2022CN_SM_MODEL, ISO2022JP_SM_MODEL, + ISO2022KR_SM_MODEL) + + +class EscCharSetProber(CharSetProber): + """ + This CharSetProber uses a "code scheme" approach for detecting encodings, + whereby easily recognizable escape or shift sequences are relied on to + identify these encodings. + """ + + def __init__(self, lang_filter=None): + super(EscCharSetProber, self).__init__(lang_filter=lang_filter) + self.coding_sm = [] + if self.lang_filter & LanguageFilter.CHINESE_SIMPLIFIED: + self.coding_sm.append(CodingStateMachine(HZ_SM_MODEL)) + self.coding_sm.append(CodingStateMachine(ISO2022CN_SM_MODEL)) + if self.lang_filter & LanguageFilter.JAPANESE: + self.coding_sm.append(CodingStateMachine(ISO2022JP_SM_MODEL)) + if self.lang_filter & LanguageFilter.KOREAN: + self.coding_sm.append(CodingStateMachine(ISO2022KR_SM_MODEL)) + self.active_sm_count = None + self._detected_charset = None + self._detected_language = None + self._state = None + self.reset() + + def reset(self): + super(EscCharSetProber, self).reset() + for coding_sm in self.coding_sm: + if not coding_sm: + continue + coding_sm.active = True + coding_sm.reset() + self.active_sm_count = len(self.coding_sm) + self._detected_charset = None + self._detected_language = None + + @property + def charset_name(self): + return self._detected_charset + + @property + def language(self): + return self._detected_language + + def get_confidence(self): + if self._detected_charset: + return 0.99 + else: + return 0.00 + + def feed(self, byte_str): + for c in byte_str: + for coding_sm in self.coding_sm: + if not coding_sm or not coding_sm.active: + continue + coding_state = coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + coding_sm.active = False + self.active_sm_count -= 1 + if self.active_sm_count <= 0: + self._state = ProbingState.NOT_ME + return self.state + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + self._detected_charset = coding_sm.get_coding_state_machine() + self._detected_language = coding_sm.language + return self.state + + return self.state diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escsm.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escsm.py new file mode 100644 index 0000000..0069523 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/escsm.py @@ -0,0 +1,246 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +HZ_CLS = ( +1,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,0,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,4,0,5,2,0, # 78 - 7f +1,1,1,1,1,1,1,1, # 80 - 87 +1,1,1,1,1,1,1,1, # 88 - 8f +1,1,1,1,1,1,1,1, # 90 - 97 +1,1,1,1,1,1,1,1, # 98 - 9f +1,1,1,1,1,1,1,1, # a0 - a7 +1,1,1,1,1,1,1,1, # a8 - af +1,1,1,1,1,1,1,1, # b0 - b7 +1,1,1,1,1,1,1,1, # b8 - bf +1,1,1,1,1,1,1,1, # c0 - c7 +1,1,1,1,1,1,1,1, # c8 - cf +1,1,1,1,1,1,1,1, # d0 - d7 +1,1,1,1,1,1,1,1, # d8 - df +1,1,1,1,1,1,1,1, # e0 - e7 +1,1,1,1,1,1,1,1, # e8 - ef +1,1,1,1,1,1,1,1, # f0 - f7 +1,1,1,1,1,1,1,1, # f8 - ff +) + +HZ_ST = ( +MachineState.START,MachineState.ERROR, 3,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START, 4,MachineState.ERROR,# 10-17 + 5,MachineState.ERROR, 6,MachineState.ERROR, 5, 5, 4,MachineState.ERROR,# 18-1f + 4,MachineState.ERROR, 4, 4, 4,MachineState.ERROR, 4,MachineState.ERROR,# 20-27 + 4,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 28-2f +) + +HZ_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +HZ_SM_MODEL = {'class_table': HZ_CLS, + 'class_factor': 6, + 'state_table': HZ_ST, + 'char_len_table': HZ_CHAR_LEN_TABLE, + 'name': "HZ-GB-2312", + 'language': 'Chinese'} + +ISO2022CN_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,3,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,4,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022CN_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 20-27 + 5, 6,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,# 38-3f +) + +ISO2022CN_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022CN_SM_MODEL = {'class_table': ISO2022CN_CLS, + 'class_factor': 9, + 'state_table': ISO2022CN_ST, + 'char_len_table': ISO2022CN_CHAR_LEN_TABLE, + 'name': "ISO-2022-CN", + 'language': 'Chinese'} + +ISO2022JP_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,2,2, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,7,0,0,0, # 20 - 27 +3,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +6,0,4,0,8,0,0,0, # 40 - 47 +0,9,5,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022JP_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 20-27 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 6,MachineState.ITS_ME,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 38-3f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.START,# 40-47 +) + +ISO2022JP_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022JP_SM_MODEL = {'class_table': ISO2022JP_CLS, + 'class_factor': 10, + 'state_table': ISO2022JP_ST, + 'char_len_table': ISO2022JP_CHAR_LEN_TABLE, + 'name': "ISO-2022-JP", + 'language': 'Japanese'} + +ISO2022KR_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,3,0,0,0, # 20 - 27 +0,4,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,5,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022KR_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 10-17 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 20-27 +) + +ISO2022KR_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +ISO2022KR_SM_MODEL = {'class_table': ISO2022KR_CLS, + 'class_factor': 6, + 'state_table': ISO2022KR_ST, + 'char_len_table': ISO2022KR_CHAR_LEN_TABLE, + 'name': "ISO-2022-KR", + 'language': 'Korean'} + + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/eucjpprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/eucjpprober.py new file mode 100644 index 0000000..20ce8f7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/eucjpprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState, MachineState +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCJPDistributionAnalysis +from .jpcntx import EUCJPContextAnalysis +from .mbcssm import EUCJP_SM_MODEL + + +class EUCJPProber(MultiByteCharSetProber): + def __init__(self): + super(EUCJPProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCJP_SM_MODEL) + self.distribution_analyzer = EUCJPDistributionAnalysis() + self.context_analyzer = EUCJPContextAnalysis() + self.reset() + + def reset(self): + super(EUCJPProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return "EUC-JP" + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + # PY3K: byte_str is a byte array, so byte_str[i] is an int, not a byte + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char, char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrfreq.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrfreq.py new file mode 100644 index 0000000..b68078c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrfreq.py @@ -0,0 +1,195 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKR_CHAR_TO_FREQ_ORDER = ( + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +) + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrprober.py new file mode 100644 index 0000000..345a060 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euckrprober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import EUCKR_SM_MODEL + + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + super(EUCKRProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCKR_SM_MODEL) + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-KR" + + @property + def language(self): + return "Korean" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwfreq.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwfreq.py new file mode 100644 index 0000000..ed7a995 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwfreq.py @@ -0,0 +1,387 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# <http:#www.edu.tw:81/mandr/> + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 5376 + +EUCTW_CHAR_TO_FREQ_ORDER = ( + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +) + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwprober.py new file mode 100644 index 0000000..35669cc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/euctwprober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCTWDistributionAnalysis +from .mbcssm import EUCTW_SM_MODEL + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + super(EUCTWProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCTW_SM_MODEL) + self.distribution_analyzer = EUCTWDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-TW" + + @property + def language(self): + return "Taiwan" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312freq.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312freq.py new file mode 100644 index 0000000..697837b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312freq.py @@ -0,0 +1,283 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312_CHAR_TO_FREQ_ORDER = ( +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, #last 512 +) + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312prober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312prober.py new file mode 100644 index 0000000..8446d2d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/gb2312prober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import GB2312DistributionAnalysis +from .mbcssm import GB2312_SM_MODEL + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + super(GB2312Prober, self).__init__() + self.coding_sm = CodingStateMachine(GB2312_SM_MODEL) + self.distribution_analyzer = GB2312DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "GB2312" + + @property + def language(self): + return "Chinese" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/hebrewprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/hebrewprober.py new file mode 100644 index 0000000..b0e1bf4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/hebrewprober.py @@ -0,0 +1,292 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +class HebrewProber(CharSetProber): + # windows-1255 / ISO-8859-8 code points of interest + FINAL_KAF = 0xea + NORMAL_KAF = 0xeb + FINAL_MEM = 0xed + NORMAL_MEM = 0xee + FINAL_NUN = 0xef + NORMAL_NUN = 0xf0 + FINAL_PE = 0xf3 + NORMAL_PE = 0xf4 + FINAL_TSADI = 0xf5 + NORMAL_TSADI = 0xf6 + + # Minimum Visual vs Logical final letter score difference. + # If the difference is below this, don't rely solely on the final letter score + # distance. + MIN_FINAL_CHAR_DISTANCE = 5 + + # Minimum Visual vs Logical model score difference. + # If the difference is below this, don't rely at all on the model score + # distance. + MIN_MODEL_DISTANCE = 0.01 + + VISUAL_HEBREW_NAME = "ISO-8859-8" + LOGICAL_HEBREW_NAME = "windows-1255" + + def __init__(self): + super(HebrewProber, self).__init__() + self._final_char_logical_score = None + self._final_char_visual_score = None + self._prev = None + self._before_prev = None + self._logical_prober = None + self._visual_prober = None + self.reset() + + def reset(self): + self._final_char_logical_score = 0 + self._final_char_visual_score = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate + # a word delimiter at the beginning of the data + self._prev = ' ' + self._before_prev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._logical_prober = logicalProber + self._visual_prober = visualProber + + def is_final(self, c): + return c in [self.FINAL_KAF, self.FINAL_MEM, self.FINAL_NUN, + self.FINAL_PE, self.FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters + # causing the Non-Final tsadi to appear at an end of a word even + # though this is not the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being + # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' + # for example legally end with a Non-Final Pe or Kaf. However, the + # benefit of these letters as Non-Final letters outweighs the damage + # since these words are quite rare. + return c in [self.NORMAL_KAF, self.NORMAL_MEM, + self.NORMAL_NUN, self.NORMAL_PE] + + def feed(self, byte_str): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew + # or visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is + # an indication that the text is laid out "naturally" since the + # final letter really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In + # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, + # should not end with the Non-Final form of that letter. Exceptions + # to this rule are mentioned above in isNonFinal(). This is an + # indication that the text is laid out backwards. +1 for visual + # score + # 3) A word longer than 1 letter, starting with a final letter. Final + # letters should not appear at the beginning of a word. This is an + # indication that the text is laid out backwards. +1 for visual + # score. + # + # The visual score and logical score are accumulated throughout the + # text and are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since + # that case is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with + # spaces) so the word boundary detection works properly. [MAP] + + if self.state == ProbingState.NOT_ME: + # Both model probers say it's not them. No reason to continue. + return ProbingState.NOT_ME + + byte_str = self.filter_high_byte_only(byte_str) + + for cur in byte_str: + if cur == ' ': + # We stand on a space - a word just ended + if self._before_prev != ' ': + # next-to-last char was not a space so self._prev is not a + # 1 letter word + if self.is_final(self._prev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._final_char_logical_score += 1 + elif self.is_non_final(self._prev): + # case (2) [-2:not space][-1:Non-Final letter][ + # cur:space] + self._final_char_visual_score += 1 + else: + # Not standing on a space + if ((self._before_prev == ' ') and + (self.is_final(self._prev)) and (cur != ' ')): + # case (3) [-2:space][-1:final letter][cur:not space] + self._final_char_visual_score += 1 + self._before_prev = self._prev + self._prev = cur + + # Forever detecting, till the end or until both model probers return + # ProbingState.NOT_ME (handled above) + return ProbingState.DETECTING + + @property + def charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._final_char_logical_score - self._final_char_visual_score + if finalsub >= self.MIN_FINAL_CHAR_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if finalsub <= -self.MIN_FINAL_CHAR_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = (self._logical_prober.get_confidence() + - self._visual_prober.get_confidence()) + if modelsub > self.MIN_MODEL_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if modelsub < -self.MIN_MODEL_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the + # day. + if finalsub < 0.0: + return self.VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to + # Logical. + return self.LOGICAL_HEBREW_NAME + + @property + def language(self): + return 'Hebrew' + + @property + def state(self): + # Remain active as long as any of the model probers are active. + if (self._logical_prober.state == ProbingState.NOT_ME) and \ + (self._visual_prober.state == ProbingState.NOT_ME): + return ProbingState.NOT_ME + return ProbingState.DETECTING diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jisfreq.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jisfreq.py new file mode 100644 index 0000000..83fc082 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jisfreq.py @@ -0,0 +1,325 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JIS_CHAR_TO_FREQ_ORDER = ( + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +) + + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jpcntx.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jpcntx.py new file mode 100644 index 0000000..20044e4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/jpcntx.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( +(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis(object): + NUM_OF_CATEGORY = 6 + DONT_KNOW = -1 + ENOUGH_REL_THRESHOLD = 100 + MAX_REL_THRESHOLD = 1000 + MINIMUM_DATA_THRESHOLD = 4 + + def __init__(self): + self._total_rel = None + self._rel_sample = None + self._need_to_skip_char_num = None + self._last_char_order = None + self._done = None + self.reset() + + def reset(self): + self._total_rel = 0 # total sequence received + # category counters, each integer counts sequence in its category + self._rel_sample = [0] * self.NUM_OF_CATEGORY + # if last byte in current buffer is not the last byte of a character, + # we need to know how many bytes to skip in next buffer + self._need_to_skip_char_num = 0 + self._last_char_order = -1 # The order of previous char + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + + def feed(self, byte_str, num_bytes): + if self._done: + return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not + # complete, we record how many byte needed to complete that character + # and skip these bytes here. We can choose to record those bytes as + # well and analyse the character once it is complete, but since a + # character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._need_to_skip_char_num + while i < num_bytes: + order, char_len = self.get_order(byte_str[i:i + 2]) + i += char_len + if i > num_bytes: + self._need_to_skip_char_num = i - num_bytes + self._last_char_order = -1 + else: + if (order != -1) and (self._last_char_order != -1): + self._total_rel += 1 + if self._total_rel > self.MAX_REL_THRESHOLD: + self._done = True + break + self._rel_sample[jp2CharContext[self._last_char_order][order]] += 1 + self._last_char_order = order + + def got_enough_data(self): + return self._total_rel > self.ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._total_rel > self.MINIMUM_DATA_THRESHOLD: + return (self._total_rel - self._rel_sample[0]) / self._total_rel + else: + return self.DONT_KNOW + + def get_order(self, byte_str): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def __init__(self): + super(SJISContextAnalysis, self).__init__() + self._charset_name = "SHIFT_JIS" + + @property + def charset_name(self): + return self._charset_name + + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC): + char_len = 2 + if (first_char == 0x87) or (0xFA <= first_char <= 0xFC): + self._charset_name = "CP932" + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 202) and (0x9F <= second_char <= 0xF1): + return second_char - 0x9F, char_len + + return -1, char_len + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): + char_len = 2 + elif first_char == 0x8F: + char_len = 3 + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): + return second_char - 0xA1, char_len + + return -1, char_len + + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py new file mode 100644 index 0000000..2aa4fb2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langbulgarianmodel.py @@ -0,0 +1,228 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +# this table is modified base on win1251BulgarianCharToOrderMap, so +# only number <64 is sure valid + +Latin5_BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 +210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 + 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 + 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 +) + +win1251BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 +221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 + 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 + 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 96.9392% +# first 1024 sequences:3.0618% +# rest sequences: 0.2992% +# negative sequences: 0.0020% +BulgarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, +3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, +0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, +0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, +0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, +0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, +2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, +3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, +1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, +3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, +1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, +2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, +2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, +3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, +1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, +2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, +2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, +1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, +2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, +2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, +2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, +1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, +2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, +1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, +3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, +1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, +3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, +1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, +2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, +1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, +2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, +1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, +2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, +1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, +2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, +1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, +0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, +1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, +1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, +1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, +0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, +1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, +1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +) + +Latin5BulgarianModel = { + 'char_to_order_map': Latin5_BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Bulgairan', +} + +Win1251BulgarianModel = { + 'char_to_order_map': win1251BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Bulgarian', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py new file mode 100644 index 0000000..e5f9a1f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langcyrillicmodel.py @@ -0,0 +1,333 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# KOI8-R language model +# Character Mapping Table: +KOI8R_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 +223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 + 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 + 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 + 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 + 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 +) + +win1251_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +) + +latin5_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +macCyrillic_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, +) + +IBM855_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, +206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, + 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, +220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, +230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, + 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, + 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, +250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, +) + +IBM866_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 97.6601% +# first 1024 sequences: 2.3389% +# rest sequences: 0.1237% +# negative sequences: 0.0009% +RussianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, +1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, +1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, +2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, +1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, +3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, +1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, +2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, +1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, +1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, +1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, +1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, +3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, +1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, +2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, +1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, +2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, +1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, +1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, +1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, +3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, +3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, +1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, +1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, +0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, +1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, +1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, +0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, +1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, +2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, +1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, +1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, +2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, +1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, +1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, +0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, +0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, +2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, +0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +) + +Koi8rModel = { + 'char_to_order_map': KOI8R_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "KOI8-R", + 'language': 'Russian', +} + +Win1251CyrillicModel = { + 'char_to_order_map': win1251_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Russian', +} + +Latin5CyrillicModel = { + 'char_to_order_map': latin5_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Russian', +} + +MacCyrillicModel = { + 'char_to_order_map': macCyrillic_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "MacCyrillic", + 'language': 'Russian', +} + +Ibm866Model = { + 'char_to_order_map': IBM866_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM866", + 'language': 'Russian', +} + +Ibm855Model = { + 'char_to_order_map': IBM855_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM855", + 'language': 'Russian', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langgreekmodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langgreekmodel.py new file mode 100644 index 0000000..5332221 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin7_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +win1253_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.2851% +# first 1024 sequences:1.7001% +# rest sequences: 0.0359% +# negative sequences: 0.0148% +GreekLangModel = ( +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, +2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, +2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, +2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, +0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, +3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, +2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, +0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, +0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, +0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, +0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, +0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, +0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, +0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, +0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, +0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, +0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, +0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, +0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, +0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, +0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, +0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, +0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, +0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin7GreekModel = { + 'char_to_order_map': Latin7_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-7", + 'language': 'Greek', +} + +Win1253GreekModel = { + 'char_to_order_map': win1253_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "windows-1253", + 'language': 'Greek', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py new file mode 100644 index 0000000..58f4c87 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhebrewmodel.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Simon Montagu +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Shoshannah Forbes - original C code (?) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Windows-1255 language model +# Character Mapping Table: +WIN1255_CHAR_TO_ORDER_MAP = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 + 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 +253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 + 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 +124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, +215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, + 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, +106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, + 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, +238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, + 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, + 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.4004% +# first 1024 sequences: 1.5981% +# rest sequences: 0.087% +# negative sequences: 0.0015% +HEBREW_LANG_MODEL = ( +0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, +3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, +1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, +1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, +1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, +1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, +0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, +0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, +0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, +0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, +0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, +0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, +0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, +0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, +0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, +0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, +0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, +0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, +0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, +1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, +1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, +2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, +0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, +) + +Win1255HebrewModel = { + 'char_to_order_map': WIN1255_CHAR_TO_ORDER_MAP, + 'precedence_matrix': HEBREW_LANG_MODEL, + 'typical_positive_ratio': 0.984004, + 'keep_english_letter': False, + 'charset_name': "windows-1255", + 'language': 'Hebrew', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py new file mode 100644 index 0000000..bb7c095 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin2_HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, + 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, + 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, +245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +win1250HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, +177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, + 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, + 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, +245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 94.7368% +# first 1024 sequences:5.2623% +# rest sequences: 0.8894% +# negative sequences: 0.0009% +HungarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, +3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, +0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, +1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, +1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, +3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, +2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, +2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, +2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, +2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, +1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, +1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, +3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, +1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, +1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, +2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, +2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, +2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, +3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, +1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, +1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, +1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, +2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, +1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, +2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, +2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, +1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, +1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, +0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, +2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, +2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, +1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, +1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, +2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, +2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, +2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, +1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, +0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +) + +Latin2HungarianModel = { + 'char_to_order_map': Latin2_HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-2", + 'language': 'Hungarian', +} + +Win1250HungarianModel = { + 'char_to_order_map': win1250HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "windows-1250", + 'language': 'Hungarian', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langthaimodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langthaimodel.py new file mode 100644 index 0000000..15f94c2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langthaimodel.py @@ -0,0 +1,199 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# The following result for thai was collected from a limited sample (1M). + +# Character Mapping Table: +TIS620CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 +188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 +253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 + 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 +209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, +223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, +236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, + 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, + 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, + 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, + 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, + 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 92.6386% +# first 1024 sequences:7.3177% +# rest sequences: 1.0230% +# negative sequences: 0.0436% +ThaiLangModel = ( +0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, +0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, +3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, +0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, +3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, +3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, +3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, +3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, +2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, +3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, +1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, +3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, +1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, +0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, +0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, +2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, +0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, +3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, +2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, +2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, +3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, +3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, +3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, +3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, +1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, +0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, +0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, +3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, +3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, +1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, +3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, +3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, +0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, +0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, +1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, +1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, +3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, +0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, +3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, +0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, +0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, +0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, +0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, +0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, +0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, +0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, +3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, +2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, +0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, +3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, +1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, +1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +TIS620ThaiModel = { + 'char_to_order_map': TIS620CharToOrderMap, + 'precedence_matrix': ThaiLangModel, + 'typical_positive_ratio': 0.926386, + 'keep_english_letter': False, + 'charset_name': "TIS-620", + 'language': 'Thai', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langturkishmodel.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langturkishmodel.py new file mode 100644 index 0000000..a427a45 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/langturkishmodel.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Özgür Baskın - Turkish Language Model +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin5_TurkishCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255, 23, 37, 47, 39, 29, 52, 36, 45, 53, 60, 16, 49, 20, 46, 42, + 48, 69, 44, 35, 31, 51, 38, 62, 65, 43, 56,255,255,255,255,255, +255, 1, 21, 28, 12, 2, 18, 27, 25, 3, 24, 10, 5, 13, 4, 15, + 26, 64, 7, 8, 9, 14, 32, 57, 58, 11, 22,255,255,255,255,255, +180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165, +164,163,162,161,160,159,101,158,157,156,155,154,153,152,151,106, +150,149,148,147,146,145,144,100,143,142,141,140,139,138,137,136, + 94, 80, 93,135,105,134,133, 63,132,131,130,129,128,127,126,125, +124,104, 73, 99, 79, 85,123, 54,122, 98, 92,121,120, 91,103,119, + 68,118,117, 97,116,115, 50, 90,114,113,112,111, 55, 41, 40, 86, + 89, 70, 59, 78, 71, 82, 88, 33, 77, 66, 84, 83,110, 75, 61, 96, + 30, 67,109, 74, 87,102, 34, 95, 81,108, 76, 72, 17, 6, 19,107, +) + +TurkishLangModel = ( +3,2,3,3,3,1,3,3,3,3,3,3,3,3,2,1,1,3,3,1,3,3,0,3,3,3,3,3,0,3,1,3, +3,2,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,3,1,0,3,3,1,3,3,0,3,3,3,3,3,0,3,0,3, +3,1,1,0,1,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,0,1,0,1, +3,3,2,3,3,0,3,3,3,3,3,3,3,2,3,1,1,3,3,0,3,3,1,2,3,3,3,3,0,3,0,3, +3,1,1,0,0,0,1,0,0,0,0,1,1,0,1,2,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,1, +3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,1,3,3,2,0,3,2,1,2,2,1,3,3,0,0,0,2, +2,2,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1, +3,3,3,2,3,3,1,2,3,3,3,3,3,3,3,1,3,2,1,0,3,2,0,1,2,3,3,2,1,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0, +1,0,1,3,3,1,3,3,3,3,3,3,3,1,2,0,0,2,3,0,2,3,0,0,2,2,2,3,0,3,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,0,3,2,0,2,3,2,3,3,1,0,0,2, +3,2,0,0,1,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,2,0,0,1, +3,3,3,2,3,3,2,3,3,3,3,2,3,3,3,0,3,3,0,0,2,1,0,0,2,3,2,2,0,0,0,2, +2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,2,0,0,1, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,0,1,3,2,1,1,3,2,3,2,1,0,0,2, +2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,2,0,2,3,0,0,2,2,2,2,0,0,0,2, +3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,3,3,3,3,2,2,2,2,3,2,3,3,0,3,3,1,1,2,2,0,0,2,2,3,2,0,0,1,3, +0,3,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1, +3,3,3,2,3,3,3,2,1,2,2,3,2,3,3,0,3,2,0,0,1,1,0,1,1,2,1,2,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0, +3,3,3,2,3,3,2,3,2,2,2,3,3,3,3,1,3,1,1,0,3,2,1,1,3,3,2,3,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,2,1,0,3,3,1,3,3,0,1,3,3,2,3,0,3,0,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +2,2,2,3,3,0,3,3,3,3,3,3,3,3,3,0,0,3,2,0,3,3,0,3,2,3,3,3,0,3,1,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,1,2,0,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,3,3,1,2,3,3,1,0,0,1,0,0,3,3,2,3,0,0,2,0,0,2,0,2,0,0,0,2,0,2,0, +0,3,1,0,1,0,0,0,2,2,1,0,1,1,2,1,2,2,2,0,2,1,1,0,0,0,2,0,0,0,0,0, +1,2,1,3,3,0,3,3,3,3,3,2,3,0,0,0,0,2,3,0,2,3,1,0,2,3,1,3,0,3,0,2, +3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,3,2,2,3,2,2,0,1,2,3,0,1,2,1,0,1,0,0,0,1,0,2,2,0,0,0,1, +1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0, +3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,0,2,1,2,0,2,1,0,0,1,1,2,1,0,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,0,2,1,3,0,0,2,0,0,3,3,0,3,0,0,1,0,1,2,0,0,1,1,2,2,0,1,0, +0,1,2,1,1,0,1,0,1,1,1,1,1,0,1,1,1,2,2,1,2,0,1,0,0,0,0,0,0,1,0,0, +3,3,3,2,3,2,3,3,0,2,2,2,3,3,3,0,3,0,0,0,2,2,0,1,2,1,1,1,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +3,3,3,3,3,3,2,1,2,2,3,3,3,3,2,0,2,0,0,0,2,2,0,0,2,1,3,3,0,0,1,1, +1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0, +1,1,2,3,3,0,3,3,3,3,3,3,2,2,0,2,0,2,3,2,3,2,2,2,2,2,2,2,1,3,2,3, +2,0,2,1,2,2,2,2,1,1,2,2,1,2,2,1,2,0,0,2,1,1,0,2,1,0,0,1,0,0,0,1, +2,3,3,1,1,1,0,1,1,1,2,3,2,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,2,2,1,3,3,3,0,2,1,2,0,2,1,0,0,1,1,1,1,1,0,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,2,3,3,3,3,3,2,3,1,2,3,3,1,2,0,0,0,0,0,0,0,3,2,1,1,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +3,3,3,2,2,3,3,2,1,1,1,1,1,3,3,0,3,1,0,0,1,1,0,0,3,1,2,1,0,0,0,0, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, +3,3,3,2,2,3,2,2,2,3,2,1,1,3,3,0,3,0,0,0,0,1,0,0,3,1,1,2,0,0,0,1, +1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,3,3,0,3,3,3,3,3,2,2,2,1,2,0,2,1,2,2,1,1,0,1,2,2,2,2,2,2,2, +0,0,2,1,2,1,2,1,0,1,1,3,1,2,1,1,2,0,0,2,0,1,0,1,0,1,0,0,0,1,0,1, +3,3,3,1,3,3,3,0,1,1,0,2,2,3,1,0,3,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,2,2,1,0,0,1,0,0,3,3,1,3,0,0,1,1,0,2,0,3,0,0,0,2,0,1,1, +0,1,2,0,1,2,2,0,2,2,2,2,1,0,2,1,1,0,2,0,2,1,2,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,2,3,2,0,2,2,2,1,3,2,0,2,1,2,0,1,2,0,0,1,0,2,2,0,0,0,2, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0, +3,3,3,0,3,3,1,1,2,3,1,0,3,2,3,0,3,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0, +1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,3,3,2,3,3,2,2,0,0,0,0,1,2,0,1,3,0,0,0,3,1,1,0,3,0,2, +2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,2,2,1,0,3,1,1,1,1,3,3,2,3,0,0,1,0,1,2,0,2,2,0,2,2,0,2,1, +0,2,2,1,1,1,1,0,2,1,1,0,1,1,1,1,2,1,2,1,2,0,1,0,1,0,0,0,0,0,0,0, +3,3,3,0,1,1,3,0,0,1,1,0,0,2,2,0,3,0,0,1,1,0,1,0,0,0,0,0,2,0,0,0, +0,3,1,0,1,0,1,0,2,0,0,1,0,1,0,1,1,1,2,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,0,2,0,1,1,1,0,0,3,3,0,2,0,0,1,0,0,2,1,1,0,1,0,1,0,1,0, +0,2,0,1,2,0,2,0,2,1,1,0,1,0,2,1,1,0,2,1,1,0,1,0,0,0,1,1,0,0,0,0, +3,2,3,0,1,0,0,0,0,0,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,0,2,0,0,0, +0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,2,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,0,2,3,0,0,1,0,1,0,2,3,2,3,0,0,1,3,0,2,1,0,0,0,0,2,0,1,0, +0,2,1,0,0,1,1,0,2,1,0,0,1,0,0,1,1,0,1,1,2,0,1,0,0,0,0,1,0,0,0,0, +3,2,2,0,0,1,1,0,0,0,0,0,0,3,1,1,1,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0, +0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,2,3,2,2,1,2,2,1,1,2,0,1,3,2,2,2,0,0,2,2,0,0,0,1,2,1, +3,0,2,1,1,0,1,1,1,0,1,2,2,2,1,1,2,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0, +0,1,1,2,3,0,3,3,3,2,2,2,2,1,0,1,0,1,0,1,2,2,0,0,2,2,1,3,1,1,2,1, +0,0,1,1,2,0,1,1,0,0,1,2,0,2,1,1,2,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0, +3,3,2,0,0,3,1,0,0,0,0,0,0,3,2,1,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,2,1,1,0,0,1,0,1,2,0,0,1,1,0,0,2,1,1,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,1,0,0,0,0,1,0,0,3,3,2,2,0,0,1,0,0,2,0,1,0,0,0,2,0,1,0, +0,0,1,1,0,0,2,0,2,1,0,0,1,1,2,1,2,0,2,1,2,1,1,1,0,0,1,1,0,0,0,0, +3,3,2,0,0,2,2,0,0,0,1,1,0,2,2,1,3,1,0,1,0,1,2,0,0,0,0,0,1,0,1,0, +0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,0,0,0,1,0,0,1,0,0,2,3,1,2,0,0,1,0,0,2,0,0,0,1,0,2,0,2,0, +0,1,1,2,2,1,2,0,2,1,1,0,0,1,1,0,1,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,1,0,0,1,1,0,3,3,1,2,0,0,1,0,0,2,0,2,0,1,1,2,0,0,0, +0,0,1,1,1,1,2,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +3,3,3,0,2,2,3,2,0,0,1,0,0,2,3,1,0,0,0,0,0,0,2,0,2,0,0,0,2,0,0,0, +0,1,1,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,0,0,0,0,0,0,1,0,0,2,2,2,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,0,2,1,1,0,1,0,2,1,1,0,0,1,1,2,1,0,2,0,2,0,1,0,0,0,2,0,0,0,0,0, +0,0,0,2,2,0,2,1,1,1,1,2,2,0,0,1,0,1,0,0,1,3,0,0,0,0,1,0,0,2,1,0, +0,0,1,0,1,0,0,0,0,0,2,1,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +2,0,0,2,3,0,2,3,1,2,2,0,2,0,0,2,0,2,1,1,1,2,1,0,0,1,2,1,1,2,1,0, +1,0,2,0,1,0,1,1,0,0,2,2,1,2,1,1,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,0,0,0,1,0,0,3,2,0,1,0,0,1,0,0,2,0,0,0,1,2,1,0,1,0, +0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,2,2,0,2,2,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,0,1,0,0,0,1,1,1,1, +0,0,2,1,0,1,1,1,0,1,1,2,1,2,1,1,2,0,1,1,2,1,0,2,0,0,0,0,0,0,0,0, +3,2,2,0,0,2,0,0,0,0,0,0,0,2,2,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,0, +0,2,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,0,2,2,0,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0, +2,0,1,0,1,0,1,1,0,0,1,2,0,1,0,1,1,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0, +2,2,2,0,1,1,0,0,0,1,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,1,2,0,1,0, +0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,1,1,1,0,0,0,0,1,2,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +1,1,2,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,1, +0,0,1,2,2,0,2,1,2,1,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,2,2,0,0,0,1,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin5TurkishModel = { + 'char_to_order_map': Latin5_TurkishCharToOrderMap, + 'precedence_matrix': TurkishLangModel, + 'typical_positive_ratio': 0.970290, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-9", + 'language': 'Turkish', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/latin1prober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/latin1prober.py new file mode 100644 index 0000000..7d1e8c2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/latin1prober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( +# UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + + +class Latin1Prober(CharSetProber): + def __init__(self): + super(Latin1Prober, self).__init__() + self._last_char_class = None + self._freq_counter = None + self.reset() + + def reset(self): + self._last_char_class = OTH + self._freq_counter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + @property + def charset_name(self): + return "ISO-8859-1" + + @property + def language(self): + return "" + + def feed(self, byte_str): + byte_str = self.filter_with_english_letters(byte_str) + for c in byte_str: + char_class = Latin1_CharToClass[c] + freq = Latin1ClassModel[(self._last_char_class * CLASS_NUM) + + char_class] + if freq == 0: + self._state = ProbingState.NOT_ME + break + self._freq_counter[freq] += 1 + self._last_char_class = char_class + + return self.state + + def get_confidence(self): + if self.state == ProbingState.NOT_ME: + return 0.01 + + total = sum(self._freq_counter) + if total < 0.01: + confidence = 0.0 + else: + confidence = ((self._freq_counter[3] - self._freq_counter[1] * 20.0) + / total) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate + # detector can take priority. + confidence = confidence * 0.73 + return confidence diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py new file mode 100644 index 0000000..6256ecf --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcharsetprober.py @@ -0,0 +1,91 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState + + +class MultiByteCharSetProber(CharSetProber): + """ + MultiByteCharSetProber + """ + + def __init__(self, lang_filter=None): + super(MultiByteCharSetProber, self).__init__(lang_filter=lang_filter) + self.distribution_analyzer = None + self.coding_sm = None + self._last_char = [0, 0] + + def reset(self): + super(MultiByteCharSetProber, self).reset() + if self.coding_sm: + self.coding_sm.reset() + if self.distribution_analyzer: + self.distribution_analyzer.reset() + self._last_char = [0, 0] + + @property + def charset_name(self): + raise NotImplementedError + + @property + def language(self): + raise NotImplementedError + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.distribution_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + return self.distribution_analyzer.get_confidence() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py new file mode 100644 index 0000000..530abe7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .utf8prober import UTF8Prober +from .sjisprober import SJISProber +from .eucjpprober import EUCJPProber +from .gb2312prober import GB2312Prober +from .euckrprober import EUCKRProber +from .cp949prober import CP949Prober +from .big5prober import Big5Prober +from .euctwprober import EUCTWProber + + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self, lang_filter=None): + super(MBCSGroupProber, self).__init__(lang_filter=lang_filter) + self.probers = [ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + CP949Prober(), + Big5Prober(), + EUCTWProber() + ] + self.reset() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcssm.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcssm.py new file mode 100644 index 0000000..8360d0f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/mbcssm.py @@ -0,0 +1,572 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +# BIG5 + +BIG5_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +BIG5_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,#08-0f + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START#10-17 +) + +BIG5_CHAR_LEN_TABLE = (0, 1, 1, 2, 0) + +BIG5_SM_MODEL = {'class_table': BIG5_CLS, + 'class_factor': 5, + 'state_table': BIG5_ST, + 'char_len_table': BIG5_CHAR_LEN_TABLE, + 'name': 'Big5'} + +# CP949 + +CP949_CLS = ( + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f + 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f + 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f + 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f + 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f + 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f + 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f + 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f + 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af + 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf + 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff +) + +CP949_ST = ( +#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START, 4, 5,MachineState.ERROR, 6, # MachineState.START + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, # MachineState.ERROR + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME, # MachineState.ITS_ME + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 3 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 4 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 5 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 6 +) + +CP949_CHAR_LEN_TABLE = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) + +CP949_SM_MODEL = {'class_table': CP949_CLS, + 'class_factor': 10, + 'state_table': CP949_ST, + 'char_len_table': CP949_CHAR_LEN_TABLE, + 'name': 'CP949'} + +# EUC-JP + +EUCJP_CLS = ( + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5 # f8 - ff +) + +EUCJP_ST = ( + 3, 4, 3, 5,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 3,MachineState.ERROR,#18-1f + 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START#20-27 +) + +EUCJP_CHAR_LEN_TABLE = (2, 2, 2, 3, 1, 0) + +EUCJP_SM_MODEL = {'class_table': EUCJP_CLS, + 'class_factor': 6, + 'state_table': EUCJP_ST, + 'char_len_table': EUCJP_CHAR_LEN_TABLE, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0 # f8 - ff +) + +EUCKR_ST = ( + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #08-0f +) + +EUCKR_CHAR_LEN_TABLE = (0, 1, 2, 0) + +EUCKR_SM_MODEL = {'class_table': EUCKR_CLS, + 'class_factor': 4, + 'state_table': EUCKR_ST, + 'char_len_table': EUCKR_CHAR_LEN_TABLE, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_CLS = ( + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +EUCTW_ST = ( + MachineState.ERROR,MachineState.ERROR,MachineState.START, 3, 3, 3, 4,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.ERROR,#10-17 + MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,#20-27 + MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +EUCTW_CHAR_LEN_TABLE = (0, 0, 1, 2, 2, 2, 3) + +EUCTW_SM_MODEL = {'class_table': EUCTW_CLS, + 'class_factor': 7, + 'state_table': EUCTW_ST, + 'char_len_table': EUCTW_CHAR_LEN_TABLE, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0 # f8 - ff +) + +GB2312_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, 3,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,#10-17 + 4,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#20-27 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validating +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312_CHAR_LEN_TABLE = (0, 1, 1, 1, 1, 1, 2) + +GB2312_SM_MODEL = {'class_table': GB2312_CLS, + 'class_factor': 7, + 'state_table': GB2312_ST, + 'char_len_table': GB2312_CHAR_LEN_TABLE, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,2,2,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,0,0,0) # f8 - ff + + +SJIS_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START #10-17 +) + +SJIS_CHAR_LEN_TABLE = (0, 1, 1, 2, 0, 0) + +SJIS_SM_MODEL = {'class_table': SJIS_CLS, + 'class_factor': 6, + 'state_table': SJIS_ST, + 'char_len_table': SJIS_CHAR_LEN_TABLE, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2BE_ST = ( + 5, 7, 7,MachineState.ERROR, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,#10-17 + 6, 6, 6, 6, 6,MachineState.ITS_ME, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,MachineState.ERROR,#20-27 + 5, 8, 6, 6,MachineState.ERROR, 6, 6, 6,#28-2f + 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2BE_CHAR_LEN_TABLE = (2, 2, 2, 0, 2, 2) + +UCS2BE_SM_MODEL = {'class_table': UCS2BE_CLS, + 'class_factor': 6, + 'state_table': UCS2BE_ST, + 'char_len_table': UCS2BE_CHAR_LEN_TABLE, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2LE_ST = ( + 6, 6, 7, 6, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 5, 5, 5,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#10-17 + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,MachineState.ERROR,#20-27 + 5, 5, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5,#28-2f + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2LE_CHAR_LEN_TABLE = (2, 2, 2, 2, 2, 2) + +UCS2LE_SM_MODEL = {'class_table': UCS2LE_CLS, + 'class_factor': 6, + 'state_table': UCS2LE_ST, + 'char_len_table': UCS2LE_CHAR_LEN_TABLE, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0 # f8 - ff +) + +UTF8_ST = ( + MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#20-27 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#28-2f + MachineState.ERROR,MachineState.ERROR, 5, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#30-37 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#38-3f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#40-47 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#48-4f + MachineState.ERROR,MachineState.ERROR, 7, 7, 7, 7,MachineState.ERROR,MachineState.ERROR,#50-57 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#58-5f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 7, 7,MachineState.ERROR,MachineState.ERROR,#60-67 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#68-6f + MachineState.ERROR,MachineState.ERROR, 9, 9, 9, 9,MachineState.ERROR,MachineState.ERROR,#70-77 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#78-7f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 9,MachineState.ERROR,MachineState.ERROR,#80-87 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#88-8f + MachineState.ERROR,MachineState.ERROR, 12, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,#90-97 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#98-9f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12,MachineState.ERROR,MachineState.ERROR,#a0-a7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#a8-af + MachineState.ERROR,MachineState.ERROR, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b0-b7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b8-bf + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,#c0-c7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR #c8-cf +) + +UTF8_CHAR_LEN_TABLE = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8_SM_MODEL = {'class_table': UTF8_CLS, + 'class_factor': 16, + 'state_table': UTF8_ST, + 'char_len_table': UTF8_CHAR_LEN_TABLE, + 'name': 'UTF-8'} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py new file mode 100644 index 0000000..0adb51d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcharsetprober.py @@ -0,0 +1,132 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import CharacterCategory, ProbingState, SequenceLikelihood + + +class SingleByteCharSetProber(CharSetProber): + SAMPLE_SIZE = 64 + SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 + POSITIVE_SHORTCUT_THRESHOLD = 0.95 + NEGATIVE_SHORTCUT_THRESHOLD = 0.05 + + def __init__(self, model, reversed=False, name_prober=None): + super(SingleByteCharSetProber, self).__init__() + self._model = model + # TRUE if we need to reverse every pair in the model lookup + self._reversed = reversed + # Optional auxiliary prober for name decision + self._name_prober = name_prober + self._last_order = None + self._seq_counters = None + self._total_seqs = None + self._total_char = None + self._freq_char = None + self.reset() + + def reset(self): + super(SingleByteCharSetProber, self).reset() + # char order of last character + self._last_order = 255 + self._seq_counters = [0] * SequenceLikelihood.get_num_categories() + self._total_seqs = 0 + self._total_char = 0 + # characters that fall in our sampling range + self._freq_char = 0 + + @property + def charset_name(self): + if self._name_prober: + return self._name_prober.charset_name + else: + return self._model['charset_name'] + + @property + def language(self): + if self._name_prober: + return self._name_prober.language + else: + return self._model.get('language') + + def feed(self, byte_str): + if not self._model['keep_english_letter']: + byte_str = self.filter_international_words(byte_str) + if not byte_str: + return self.state + char_to_order_map = self._model['char_to_order_map'] + for i, c in enumerate(byte_str): + # XXX: Order is in range 1-64, so one would think we want 0-63 here, + # but that leads to 27 more test failures than before. + order = char_to_order_map[c] + # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but + # CharacterCategory.SYMBOL is actually 253, so we use CONTROL + # to make it closer to the original intent. The only difference + # is whether or not we count digits and control characters for + # _total_char purposes. + if order < CharacterCategory.CONTROL: + self._total_char += 1 + if order < self.SAMPLE_SIZE: + self._freq_char += 1 + if self._last_order < self.SAMPLE_SIZE: + self._total_seqs += 1 + if not self._reversed: + i = (self._last_order * self.SAMPLE_SIZE) + order + model = self._model['precedence_matrix'][i] + else: # reverse the order of the letters in the lookup + i = (order * self.SAMPLE_SIZE) + self._last_order + model = self._model['precedence_matrix'][i] + self._seq_counters[model] += 1 + self._last_order = order + + charset_name = self._model['charset_name'] + if self.state == ProbingState.DETECTING: + if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: + confidence = self.get_confidence() + if confidence > self.POSITIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, we have a winner', + charset_name, confidence) + self._state = ProbingState.FOUND_IT + elif confidence < self.NEGATIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, below negative ' + 'shortcut threshhold %s', charset_name, + confidence, + self.NEGATIVE_SHORTCUT_THRESHOLD) + self._state = ProbingState.NOT_ME + + return self.state + + def get_confidence(self): + r = 0.01 + if self._total_seqs > 0: + r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / + self._total_seqs / self._model['typical_positive_ratio']) + r = r * self._freq_char / self._total_char + if r >= 1.0: + r = 0.99 + return r diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py new file mode 100644 index 0000000..98e95dc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sbcsgroupprober.py @@ -0,0 +1,73 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .sbcharsetprober import SingleByteCharSetProber +from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, + Latin5CyrillicModel, MacCyrillicModel, + Ibm866Model, Ibm855Model) +from .langgreekmodel import Latin7GreekModel, Win1253GreekModel +from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel +# from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel +from .langthaimodel import TIS620ThaiModel +from .langhebrewmodel import Win1255HebrewModel +from .hebrewprober import HebrewProber +from .langturkishmodel import Latin5TurkishModel + + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + super(SBCSGroupProber, self).__init__() + self.probers = [ + SingleByteCharSetProber(Win1251CyrillicModel), + SingleByteCharSetProber(Koi8rModel), + SingleByteCharSetProber(Latin5CyrillicModel), + SingleByteCharSetProber(MacCyrillicModel), + SingleByteCharSetProber(Ibm866Model), + SingleByteCharSetProber(Ibm855Model), + SingleByteCharSetProber(Latin7GreekModel), + SingleByteCharSetProber(Win1253GreekModel), + SingleByteCharSetProber(Latin5BulgarianModel), + SingleByteCharSetProber(Win1251BulgarianModel), + # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) + # after we retrain model. + # SingleByteCharSetProber(Latin2HungarianModel), + # SingleByteCharSetProber(Win1250HungarianModel), + SingleByteCharSetProber(TIS620ThaiModel), + SingleByteCharSetProber(Latin5TurkishModel), + ] + hebrew_prober = HebrewProber() + logical_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, + False, hebrew_prober) + visual_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, True, + hebrew_prober) + hebrew_prober.set_model_probers(logical_hebrew_prober, visual_hebrew_prober) + self.probers.extend([hebrew_prober, logical_hebrew_prober, + visual_hebrew_prober]) + + self.reset() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sjisprober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sjisprober.py new file mode 100644 index 0000000..9e29623 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/sjisprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import SJISDistributionAnalysis +from .jpcntx import SJISContextAnalysis +from .mbcssm import SJIS_SM_MODEL +from .enums import ProbingState, MachineState + + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + super(SJISProber, self).__init__() + self.coding_sm = CodingStateMachine(SJIS_SM_MODEL) + self.distribution_analyzer = SJISDistributionAnalysis() + self.context_analyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + super(SJISProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return self.context_analyzer.charset_name + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char[2 - char_len:], + char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i + 1 - char_len:i + 3 + - char_len], char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/universaldetector.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/universaldetector.py new file mode 100644 index 0000000..7b4e92d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/universaldetector.py @@ -0,0 +1,286 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### +""" +Module containing the UniversalDetector detector class, which is the primary +class a user of ``chardet`` should use. + +:author: Mark Pilgrim (initial port to Python) +:author: Shy Shalom (original C code) +:author: Dan Blanchard (major refactoring for 3.0) +:author: Ian Cordasco +""" + + +import codecs +import logging +import re + +from .charsetgroupprober import CharSetGroupProber +from .enums import InputState, LanguageFilter, ProbingState +from .escprober import EscCharSetProber +from .latin1prober import Latin1Prober +from .mbcsgroupprober import MBCSGroupProber +from .sbcsgroupprober import SBCSGroupProber + + +class UniversalDetector(object): + """ + The ``UniversalDetector`` class underlies the ``chardet.detect`` function + and coordinates all of the different charset probers. + + To get a ``dict`` containing an encoding and its confidence, you can simply + run: + + .. code:: + + u = UniversalDetector() + u.feed(some_bytes) + u.close() + detected = u.result + + """ + + MINIMUM_THRESHOLD = 0.20 + HIGH_BYTE_DETECTOR = re.compile(b'[\x80-\xFF]') + ESC_DETECTOR = re.compile(b'(\033|~{)') + WIN_BYTE_DETECTOR = re.compile(b'[\x80-\x9F]') + ISO_WIN_MAP = {'iso-8859-1': 'Windows-1252', + 'iso-8859-2': 'Windows-1250', + 'iso-8859-5': 'Windows-1251', + 'iso-8859-6': 'Windows-1256', + 'iso-8859-7': 'Windows-1253', + 'iso-8859-8': 'Windows-1255', + 'iso-8859-9': 'Windows-1254', + 'iso-8859-13': 'Windows-1257'} + + def __init__(self, lang_filter=LanguageFilter.ALL): + self._esc_charset_prober = None + self._charset_probers = [] + self.result = None + self.done = None + self._got_data = None + self._input_state = None + self._last_char = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + self._has_win_bytes = None + self.reset() + + def reset(self): + """ + Reset the UniversalDetector and all of its probers back to their + initial states. This is called by ``__init__``, so you only need to + call this directly in between analyses of different documents. + """ + self.result = {'encoding': None, 'confidence': 0.0, 'language': None} + self.done = False + self._got_data = False + self._has_win_bytes = False + self._input_state = InputState.PURE_ASCII + self._last_char = b'' + if self._esc_charset_prober: + self._esc_charset_prober.reset() + for prober in self._charset_probers: + prober.reset() + + def feed(self, byte_str): + """ + Takes a chunk of a document and feeds it through all of the relevant + charset probers. + + After calling ``feed``, you can check the value of the ``done`` + attribute to see if you need to continue feeding the + ``UniversalDetector`` more data, or if it has made a prediction + (in the ``result`` attribute). + + .. note:: + You should always call ``close`` when you're done feeding in your + document if ``done`` is not already ``True``. + """ + if self.done: + return + + if not len(byte_str): + return + + if not isinstance(byte_str, bytearray): + byte_str = bytearray(byte_str) + + # First check for known BOMs, since these are guaranteed to be correct + if not self._got_data: + # If the data starts with BOM, we know it is UTF + if byte_str.startswith(codecs.BOM_UTF8): + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8-SIG", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_UTF32_LE, + codecs.BOM_UTF32_BE)): + # FF FE 00 00 UTF-32, little-endian BOM + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\xFE\xFF\x00\x00'): + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = {'encoding': "X-ISO-10646-UCS-4-3412", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\x00\x00\xFF\xFE'): + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = {'encoding': "X-ISO-10646-UCS-4-2143", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_LE, codecs.BOM_BE)): + # FF FE UTF-16, little endian BOM + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16", + 'confidence': 1.0, + 'language': ''} + + self._got_data = True + if self.result['encoding'] is not None: + self.done = True + return + + # If none of those matched and we've only see ASCII so far, check + # for high bytes and escape sequences + if self._input_state == InputState.PURE_ASCII: + if self.HIGH_BYTE_DETECTOR.search(byte_str): + self._input_state = InputState.HIGH_BYTE + elif self._input_state == InputState.PURE_ASCII and \ + self.ESC_DETECTOR.search(self._last_char + byte_str): + self._input_state = InputState.ESC_ASCII + + self._last_char = byte_str[-1:] + + # If we've seen escape sequences, use the EscCharSetProber, which + # uses a simple state machine to check for known escape sequences in + # HZ and ISO-2022 encodings, since those are the only encodings that + # use such sequences. + if self._input_state == InputState.ESC_ASCII: + if not self._esc_charset_prober: + self._esc_charset_prober = EscCharSetProber(self.lang_filter) + if self._esc_charset_prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': + self._esc_charset_prober.charset_name, + 'confidence': + self._esc_charset_prober.get_confidence(), + 'language': + self._esc_charset_prober.language} + self.done = True + # If we've seen high bytes (i.e., those with values greater than 127), + # we need to do more complicated checks using all our multi-byte and + # single-byte probers that are left. The single-byte probers + # use character bigram distributions to determine the encoding, whereas + # the multi-byte probers use a combination of character unigram and + # bigram distributions. + elif self._input_state == InputState.HIGH_BYTE: + if not self._charset_probers: + self._charset_probers = [MBCSGroupProber(self.lang_filter)] + # If we're checking non-CJK encodings, use single-byte prober + if self.lang_filter & LanguageFilter.NON_CJK: + self._charset_probers.append(SBCSGroupProber()) + self._charset_probers.append(Latin1Prober()) + for prober in self._charset_probers: + if prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': prober.charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language} + self.done = True + break + if self.WIN_BYTE_DETECTOR.search(byte_str): + self._has_win_bytes = True + + def close(self): + """ + Stop analyzing the current document and come up with a final + prediction. + + :returns: The ``result`` attribute, a ``dict`` with the keys + `encoding`, `confidence`, and `language`. + """ + # Don't bother with checks if we're already done + if self.done: + return self.result + self.done = True + + if not self._got_data: + self.logger.debug('no data received!') + + # Default to ASCII if it is all we've seen so far + elif self._input_state == InputState.PURE_ASCII: + self.result = {'encoding': 'ascii', + 'confidence': 1.0, + 'language': ''} + + # If we have seen non-ASCII, return the best that met MINIMUM_THRESHOLD + elif self._input_state == InputState.HIGH_BYTE: + prober_confidence = None + max_prober_confidence = 0.0 + max_prober = None + for prober in self._charset_probers: + if not prober: + continue + prober_confidence = prober.get_confidence() + if prober_confidence > max_prober_confidence: + max_prober_confidence = prober_confidence + max_prober = prober + if max_prober and (max_prober_confidence > self.MINIMUM_THRESHOLD): + charset_name = max_prober.charset_name + lower_charset_name = max_prober.charset_name.lower() + confidence = max_prober.get_confidence() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if self._has_win_bytes: + charset_name = self.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + self.result = {'encoding': charset_name, + 'confidence': confidence, + 'language': max_prober.language} + + # Log all prober confidences if none met MINIMUM_THRESHOLD + if self.logger.getEffectiveLevel() == logging.DEBUG: + if self.result['encoding'] is None: + self.logger.debug('no probers hit minimum threshold') + for group_prober in self._charset_probers: + if not group_prober: + continue + if isinstance(group_prober, CharSetGroupProber): + for prober in group_prober.probers: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + else: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + return self.result diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/utf8prober.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/utf8prober.py new file mode 100644 index 0000000..6c3196c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/utf8prober.py @@ -0,0 +1,82 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState +from .codingstatemachine import CodingStateMachine +from .mbcssm import UTF8_SM_MODEL + + + +class UTF8Prober(CharSetProber): + ONE_CHAR_PROB = 0.5 + + def __init__(self): + super(UTF8Prober, self).__init__() + self.coding_sm = CodingStateMachine(UTF8_SM_MODEL) + self._num_mb_chars = None + self.reset() + + def reset(self): + super(UTF8Prober, self).reset() + self.coding_sm.reset() + self._num_mb_chars = 0 + + @property + def charset_name(self): + return "utf-8" + + @property + def language(self): + return "" + + def feed(self, byte_str): + for c in byte_str: + coding_state = self.coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + if self.coding_sm.get_current_charlen() >= 2: + self._num_mb_chars += 1 + + if self.state == ProbingState.DETECTING: + if self.get_confidence() > self.SHORTCUT_THRESHOLD: + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + unlike = 0.99 + if self._num_mb_chars < 6: + unlike *= self.ONE_CHAR_PROB ** self._num_mb_chars + return 1.0 - unlike + else: + return unlike diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/chardet/version.py b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/version.py new file mode 100644 index 0000000..bb2a34a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/chardet/version.py @@ -0,0 +1,9 @@ +""" +This module exists only to simplify retrieving the version number of chardet +from within setup.py and from chardet subpackages. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + +__version__ = "3.0.4" +VERSION = __version__.split('.') diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__init__.py new file mode 100644 index 0000000..f4d9ce2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/__init__.py @@ -0,0 +1,7 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit, colorama_text +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.3.9' + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansi.py b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansi.py new file mode 100644 index 0000000..7877658 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansi.py @@ -0,0 +1,102 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\007' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + +def set_title(title): + return OSC + '2;' + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + 'J' + +def clear_line(mode=2): + return CSI + str(mode) + 'K' + + +class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + 'A' + def DOWN(self, n=1): + return CSI + str(n) + 'B' + def FORWARD(self, n=1): + return CSI + str(n) + 'C' + def BACK(self, n=1): + return CSI + str(n) + 'D' + def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + + +class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansitowin32.py b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansitowin32.py new file mode 100644 index 0000000..1d6e605 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/ansitowin32.py @@ -0,0 +1,236 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll, winapi_test + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +def is_stream_closed(stream): + return not hasattr(stream, 'closed') or stream.closed + + +def is_a_tty(stream): + return hasattr(stream, 'isatty') and stream.isatty() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def write(self, text): + self.__convertor.write(text) + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + + # should we strip ANSI sequences from our output? + if strip is None: + strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped)) + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped) + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not is_stream_closed(self.wrapped): + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command in '\x07': # \x07 = BEL + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/colorama/initialise.py b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/initialise.py new file mode 100644 index 0000000..834962a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/initialise.py @@ -0,0 +1,82 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import contextlib +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = None +orig_stderr = None + +wrapped_stdout = None +wrapped_stderr = None + +atexit_done = False + + +def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +@contextlib.contextmanager +def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/colorama/win32.py b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/win32.py new file mode 100644 index 0000000..8262e35 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/win32.py @@ -0,0 +1,156 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None + winapi_test = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW + _SetConsoleTitleW.argtypes = [ + wintypes.LPCWSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + handles = { + STDOUT: _GetStdHandle(STDOUT), + STDERR: _GetStdHandle(STDERR), + } + + def _winapi_test(handle): + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) + + def winapi_test(): + return any(_winapi_test(h) for h in handles.values()) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = handles[stream_id] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = handles[stream_id] + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = handles[stream_id] + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = handles[stream_id] + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = handles[stream_id] + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/colorama/winterm.py b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/winterm.py new file mode 100644 index 0000000..60309d3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/colorama/winterm.py @@ -0,0 +1,162 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + + def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + if mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + if mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__init__.py new file mode 100644 index 0000000..d4aab45 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import logging + +__version__ = '0.2.7' + +class DistlibException(Exception): + pass + +try: + from logging import NullHandler +except ImportError: # pragma: no cover + class NullHandler(logging.Handler): + def handle(self, record): pass + def emit(self, record): pass + def createLock(self): self.lock = None + +logger = logging.getLogger(__name__) +logger.addHandler(NullHandler()) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__init__.py new file mode 100644 index 0000000..f7dbf4c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/__init__.py @@ -0,0 +1,6 @@ +"""Modules copied from Python 3 standard libraries, for internal use only. + +Individual classes and functions are found in d2._backport.misc. Intended +usage is to always import things missing from 3.1 from that module: the +built-in/stdlib objects will be used if found. +""" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/misc.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/misc.py new file mode 100644 index 0000000..cfb318d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/misc.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Backports for individual classes and functions.""" + +import os +import sys + +__all__ = ['cache_from_source', 'callable', 'fsencode'] + + +try: + from imp import cache_from_source +except ImportError: + def cache_from_source(py_file, debug=__debug__): + ext = debug and 'c' or 'o' + return py_file + ext + + +try: + callable = callable +except NameError: + from collections import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode +except AttributeError: + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, str): + return filename.encode(sys.getfilesystemencoding()) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/shutil.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/shutil.py new file mode 100644 index 0000000..159e49e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/shutil.py @@ -0,0 +1,761 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Utility functions for copying and archiving files and directory trees. + +XXX The functions here don't copy the resource fork or other metadata on Mac. + +""" + +import os +import sys +import stat +from os.path import abspath +import fnmatch +import collections +import errno +from . import tarfile + +try: + import bz2 + _BZ2_SUPPORTED = True +except ImportError: + _BZ2_SUPPORTED = False + +try: + from pwd import getpwnam +except ImportError: + getpwnam = None + +try: + from grp import getgrnam +except ImportError: + getgrnam = None + +__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", + "copytree", "move", "rmtree", "Error", "SpecialFileError", + "ExecError", "make_archive", "get_archive_formats", + "register_archive_format", "unregister_archive_format", + "get_unpack_formats", "register_unpack_format", + "unregister_unpack_format", "unpack_archive", "ignore_patterns"] + +class Error(EnvironmentError): + pass + +class SpecialFileError(EnvironmentError): + """Raised when trying to do a kind of operation (e.g. copying) which is + not supported on a special file (e.g. a named pipe)""" + +class ExecError(EnvironmentError): + """Raised when a command could not be executed""" + +class ReadError(EnvironmentError): + """Raised when an archive cannot be read""" + +class RegistryError(Exception): + """Raised when a registry operation with the archiving + and unpacking registries fails""" + + +try: + WindowsError +except NameError: + WindowsError = None + +def copyfileobj(fsrc, fdst, length=16*1024): + """copy data from file-like object fsrc to file-like object fdst""" + while 1: + buf = fsrc.read(length) + if not buf: + break + fdst.write(buf) + +def _samefile(src, dst): + # Macintosh, Unix. + if hasattr(os.path, 'samefile'): + try: + return os.path.samefile(src, dst) + except OSError: + return False + + # All other platforms: check for same pathname. + return (os.path.normcase(os.path.abspath(src)) == + os.path.normcase(os.path.abspath(dst))) + +def copyfile(src, dst): + """Copy data from src to dst""" + if _samefile(src, dst): + raise Error("`%s` and `%s` are the same file" % (src, dst)) + + for fn in [src, dst]: + try: + st = os.stat(fn) + except OSError: + # File most likely does not exist + pass + else: + # XXX What about other special files? (sockets, devices...) + if stat.S_ISFIFO(st.st_mode): + raise SpecialFileError("`%s` is a named pipe" % fn) + + with open(src, 'rb') as fsrc: + with open(dst, 'wb') as fdst: + copyfileobj(fsrc, fdst) + +def copymode(src, dst): + """Copy mode bits from src to dst""" + if hasattr(os, 'chmod'): + st = os.stat(src) + mode = stat.S_IMODE(st.st_mode) + os.chmod(dst, mode) + +def copystat(src, dst): + """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" + st = os.stat(src) + mode = stat.S_IMODE(st.st_mode) + if hasattr(os, 'utime'): + os.utime(dst, (st.st_atime, st.st_mtime)) + if hasattr(os, 'chmod'): + os.chmod(dst, mode) + if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): + try: + os.chflags(dst, st.st_flags) + except OSError as why: + if (not hasattr(errno, 'EOPNOTSUPP') or + why.errno != errno.EOPNOTSUPP): + raise + +def copy(src, dst): + """Copy data and mode bits ("cp src dst"). + + The destination may be a directory. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst) + copymode(src, dst) + +def copy2(src, dst): + """Copy data and all stat info ("cp -p src dst"). + + The destination may be a directory. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst) + copystat(src, dst) + +def ignore_patterns(*patterns): + """Function that can be used as copytree() ignore parameter. + + Patterns is a sequence of glob-style patterns + that are used to exclude files""" + def _ignore_patterns(path, names): + ignored_names = [] + for pattern in patterns: + ignored_names.extend(fnmatch.filter(names, pattern)) + return set(ignored_names) + return _ignore_patterns + +def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, + ignore_dangling_symlinks=False): + """Recursively copy a directory tree. + + The destination directory must not already exist. + If exception(s) occur, an Error is raised with a list of reasons. + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. If the file pointed by the symlink doesn't + exist, an exception will be added in the list of errors raised in + an Error exception at the end of the copy process. + + You can set the optional ignore_dangling_symlinks flag to true if you + want to silence this exception. Notice that this has no effect on + platforms that don't support os.symlink. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + The optional copy_function argument is a callable that will be used + to copy each file. It will be called with the source path and the + destination path as arguments. By default, copy2() is used, but any + function that supports the same signature (like copy()) can be used. + + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if os.path.islink(srcname): + linkto = os.readlink(srcname) + if symlinks: + os.symlink(linkto, dstname) + else: + # ignore dangling symlink if the flag is on + if not os.path.exists(linkto) and ignore_dangling_symlinks: + continue + # otherwise let the copy occurs. copy2 will raise an error + copy_function(srcname, dstname) + elif os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, copy_function) + else: + # Will raise a SpecialFileError for unsupported file types + copy_function(srcname, dstname) + # catch the Error from the recursive copytree so that we can + # continue with other files + except Error as err: + errors.extend(err.args[0]) + except EnvironmentError as why: + errors.append((srcname, dstname, str(why))) + try: + copystat(src, dst) + except OSError as why: + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) + if errors: + raise Error(errors) + +def rmtree(path, ignore_errors=False, onerror=None): + """Recursively delete a directory tree. + + If ignore_errors is set, errors are ignored; otherwise, if onerror + is set, it is called to handle the error with arguments (func, + path, exc_info) where func is os.listdir, os.remove, or os.rmdir; + path is the argument to that function that caused it to fail; and + exc_info is a tuple returned by sys.exc_info(). If ignore_errors + is false and onerror is None, an exception is raised. + + """ + if ignore_errors: + def onerror(*args): + pass + elif onerror is None: + def onerror(*args): + raise + try: + if os.path.islink(path): + # symlinks to directories are forbidden, see bug #1669 + raise OSError("Cannot call rmtree on a symbolic link") + except OSError: + onerror(os.path.islink, path, sys.exc_info()) + # can't continue even if onerror hook returns + return + names = [] + try: + names = os.listdir(path) + except os.error: + onerror(os.listdir, path, sys.exc_info()) + for name in names: + fullname = os.path.join(path, name) + try: + mode = os.lstat(fullname).st_mode + except os.error: + mode = 0 + if stat.S_ISDIR(mode): + rmtree(fullname, ignore_errors, onerror) + else: + try: + os.remove(fullname) + except os.error: + onerror(os.remove, fullname, sys.exc_info()) + try: + os.rmdir(path) + except os.error: + onerror(os.rmdir, path, sys.exc_info()) + + +def _basename(path): + # A basename() variant which first strips the trailing slash, if present. + # Thus we always get the last component of the path, even for directories. + return os.path.basename(path.rstrip(os.path.sep)) + +def move(src, dst): + """Recursively move a file or directory to another location. This is + similar to the Unix "mv" command. + + If the destination is a directory or a symlink to a directory, the source + is moved inside the directory. The destination path must not already + exist. + + If the destination already exists but is not a directory, it may be + overwritten depending on os.rename() semantics. + + If the destination is on our current filesystem, then rename() is used. + Otherwise, src is copied to the destination and then removed. + A lot more could be done here... A look at a mv.c shows a lot of + the issues this implementation glosses over. + + """ + real_dst = dst + if os.path.isdir(dst): + if _samefile(src, dst): + # We might be on a case insensitive filesystem, + # perform the rename anyway. + os.rename(src, dst) + return + + real_dst = os.path.join(dst, _basename(src)) + if os.path.exists(real_dst): + raise Error("Destination path '%s' already exists" % real_dst) + try: + os.rename(src, real_dst) + except OSError: + if os.path.isdir(src): + if _destinsrc(src, dst): + raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) + copytree(src, real_dst, symlinks=True) + rmtree(src) + else: + copy2(src, real_dst) + os.unlink(src) + +def _destinsrc(src, dst): + src = abspath(src) + dst = abspath(dst) + if not src.endswith(os.path.sep): + src += os.path.sep + if not dst.endswith(os.path.sep): + dst += os.path.sep + return dst.startswith(src) + +def _get_gid(name): + """Returns a gid, given a group name.""" + if getgrnam is None or name is None: + return None + try: + result = getgrnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _get_uid(name): + """Returns an uid, given a user name.""" + if getpwnam is None or name is None: + return None + try: + result = getpwnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, + owner=None, group=None, logger=None): + """Create a (possibly compressed) tar file from all the files under + 'base_dir'. + + 'compress' must be "gzip" (the default), "bzip2", or None. + + 'owner' and 'group' can be used to define an owner and a group for the + archive that is being built. If not provided, the current owner and group + will be used. + + The output tar file will be named 'base_name' + ".tar", possibly plus + the appropriate compression extension (".gz", or ".bz2"). + + Returns the output filename. + """ + tar_compression = {'gzip': 'gz', None: ''} + compress_ext = {'gzip': '.gz'} + + if _BZ2_SUPPORTED: + tar_compression['bzip2'] = 'bz2' + compress_ext['bzip2'] = '.bz2' + + # flags for compression program, each element of list will be an argument + if compress is not None and compress not in compress_ext: + raise ValueError("bad value for 'compress', or compression format not " + "supported : {0}".format(compress)) + + archive_name = base_name + '.tar' + compress_ext.get(compress, '') + archive_dir = os.path.dirname(archive_name) + + if not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # creating the tarball + if logger is not None: + logger.info('Creating tar archive') + + uid = _get_uid(owner) + gid = _get_gid(group) + + def _set_uid_gid(tarinfo): + if gid is not None: + tarinfo.gid = gid + tarinfo.gname = group + if uid is not None: + tarinfo.uid = uid + tarinfo.uname = owner + return tarinfo + + if not dry_run: + tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + return archive_name + +def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): + # XXX see if we want to keep an external call here + if verbose: + zipoptions = "-r" + else: + zipoptions = "-rq" + from distutils.errors import DistutilsExecError + from distutils.spawn import spawn + try: + spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) + except DistutilsExecError: + # XXX really should distinguish between "couldn't find + # external 'zip' command" and "zip failed". + raise ExecError("unable to create zip file '%s': " + "could neither import the 'zipfile' module nor " + "find a standalone zip utility") % zip_filename + +def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): + """Create a zip file from all the files under 'base_dir'. + + The output zip file will be named 'base_name' + ".zip". Uses either the + "zipfile" Python module (if available) or the InfoZIP "zip" utility + (if installed and found on the default search path). If neither tool is + available, raises ExecError. Returns the name of the output zip + file. + """ + zip_filename = base_name + ".zip" + archive_dir = os.path.dirname(base_name) + + if not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # If zipfile module is not available, try spawning an external 'zip' + # command. + try: + import zipfile + except ImportError: + zipfile = None + + if zipfile is None: + _call_external_zip(base_dir, zip_filename, verbose, dry_run) + else: + if logger is not None: + logger.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + zip = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) + + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zip.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + zip.close() + + return zip_filename + +_ARCHIVE_FORMATS = { + 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), + 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), + 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), + 'zip': (_make_zipfile, [], "ZIP file"), + } + +if _BZ2_SUPPORTED: + _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], + "bzip2'ed tar-file") + +def get_archive_formats(): + """Returns a list of supported formats for archiving and unarchiving. + + Each element of the returned sequence is a tuple (name, description) + """ + formats = [(name, registry[2]) for name, registry in + _ARCHIVE_FORMATS.items()] + formats.sort() + return formats + +def register_archive_format(name, function, extra_args=None, description=''): + """Registers an archive format. + + name is the name of the format. function is the callable that will be + used to create archives. If provided, extra_args is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_archive_formats() function. + """ + if extra_args is None: + extra_args = [] + if not isinstance(function, collections.Callable): + raise TypeError('The %s object is not callable' % function) + if not isinstance(extra_args, (tuple, list)): + raise TypeError('extra_args needs to be a sequence') + for element in extra_args: + if not isinstance(element, (tuple, list)) or len(element) !=2: + raise TypeError('extra_args elements are : (arg_name, value)') + + _ARCHIVE_FORMATS[name] = (function, extra_args, description) + +def unregister_archive_format(name): + del _ARCHIVE_FORMATS[name] + +def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, + dry_run=0, owner=None, group=None, logger=None): + """Create an archive file (eg. zip or tar). + + 'base_name' is the name of the file to create, minus any format-specific + extension; 'format' is the archive format: one of "zip", "tar", "bztar" + or "gztar". + + 'root_dir' is a directory that will be the root directory of the + archive; ie. we typically chdir into 'root_dir' before creating the + archive. 'base_dir' is the directory where we start archiving from; + ie. 'base_dir' will be the common prefix of all files and + directories in the archive. 'root_dir' and 'base_dir' both default + to the current directory. Returns the name of the archive file. + + 'owner' and 'group' are used when creating a tar archive. By default, + uses the current owner and group. + """ + save_cwd = os.getcwd() + if root_dir is not None: + if logger is not None: + logger.debug("changing into '%s'", root_dir) + base_name = os.path.abspath(base_name) + if not dry_run: + os.chdir(root_dir) + + if base_dir is None: + base_dir = os.curdir + + kwargs = {'dry_run': dry_run, 'logger': logger} + + try: + format_info = _ARCHIVE_FORMATS[format] + except KeyError: + raise ValueError("unknown archive format '%s'" % format) + + func = format_info[0] + for arg, val in format_info[1]: + kwargs[arg] = val + + if format != 'zip': + kwargs['owner'] = owner + kwargs['group'] = group + + try: + filename = func(base_name, base_dir, **kwargs) + finally: + if root_dir is not None: + if logger is not None: + logger.debug("changing back to '%s'", save_cwd) + os.chdir(save_cwd) + + return filename + + +def get_unpack_formats(): + """Returns a list of supported formats for unpacking. + + Each element of the returned sequence is a tuple + (name, extensions, description) + """ + formats = [(name, info[0], info[3]) for name, info in + _UNPACK_FORMATS.items()] + formats.sort() + return formats + +def _check_unpack_options(extensions, function, extra_args): + """Checks what gets registered as an unpacker.""" + # first make sure no other unpacker is registered for this extension + existing_extensions = {} + for name, info in _UNPACK_FORMATS.items(): + for ext in info[0]: + existing_extensions[ext] = name + + for extension in extensions: + if extension in existing_extensions: + msg = '%s is already registered for "%s"' + raise RegistryError(msg % (extension, + existing_extensions[extension])) + + if not isinstance(function, collections.Callable): + raise TypeError('The registered function must be a callable') + + +def register_unpack_format(name, extensions, function, extra_args=None, + description=''): + """Registers an unpack format. + + `name` is the name of the format. `extensions` is a list of extensions + corresponding to the format. + + `function` is the callable that will be + used to unpack archives. The callable will receive archives to unpack. + If it's unable to handle an archive, it needs to raise a ReadError + exception. + + If provided, `extra_args` is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_unpack_formats() function. + """ + if extra_args is None: + extra_args = [] + _check_unpack_options(extensions, function, extra_args) + _UNPACK_FORMATS[name] = extensions, function, extra_args, description + +def unregister_unpack_format(name): + """Removes the pack format from the registry.""" + del _UNPACK_FORMATS[name] + +def _ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + +def _unpack_zipfile(filename, extract_dir): + """Unpack zip `filename` to `extract_dir` + """ + try: + import zipfile + except ImportError: + raise ReadError('zlib not supported, cannot unpack this archive.') + + if not zipfile.is_zipfile(filename): + raise ReadError("%s is not a zip file" % filename) + + zip = zipfile.ZipFile(filename) + try: + for info in zip.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name: + continue + + target = os.path.join(extract_dir, *name.split('/')) + if not target: + continue + + _ensure_directory(target) + if not name.endswith('/'): + # file + data = zip.read(info.filename) + f = open(target, 'wb') + try: + f.write(data) + finally: + f.close() + del data + finally: + zip.close() + +def _unpack_tarfile(filename, extract_dir): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise ReadError( + "%s is not a compressed or uncompressed tar file" % filename) + try: + tarobj.extractall(extract_dir) + finally: + tarobj.close() + +_UNPACK_FORMATS = { + 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), + 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), + 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") + } + +if _BZ2_SUPPORTED: + _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], + "bzip2'ed tar-file") + +def _find_unpack_format(filename): + for name, info in _UNPACK_FORMATS.items(): + for extension in info[0]: + if filename.endswith(extension): + return name + return None + +def unpack_archive(filename, extract_dir=None, format=None): + """Unpack an archive. + + `filename` is the name of the archive. + + `extract_dir` is the name of the target directory, where the archive + is unpacked. If not provided, the current working directory is used. + + `format` is the archive format: one of "zip", "tar", or "gztar". Or any + other registered format. If not provided, unpack_archive will use the + filename extension and see if an unpacker was registered for that + extension. + + In case none is found, a ValueError is raised. + """ + if extract_dir is None: + extract_dir = os.getcwd() + + if format is not None: + try: + format_info = _UNPACK_FORMATS[format] + except KeyError: + raise ValueError("Unknown unpack format '{0}'".format(format)) + + func = format_info[1] + func(filename, extract_dir, **dict(format_info[2])) + else: + # we need to look at the registered unpackers supported extensions + format = _find_unpack_format(filename) + if format is None: + raise ReadError("Unknown archive format '{0}'".format(filename)) + + func = _UNPACK_FORMATS[format][1] + kwargs = dict(_UNPACK_FORMATS[format][2]) + func(filename, extract_dir, **kwargs) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg new file mode 100644 index 0000000..1746bd0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg @@ -0,0 +1,84 @@ +[posix_prefix] +# Configuration directories. Some of these come straight out of the +# configure script. They are for implementing the other variables, not to +# be used directly in [resource_locations]. +confdir = /etc +datadir = /usr/share +libdir = /usr/lib +statedir = /var +# User resource directory +local = ~/.local/{distribution.name} + +stdlib = {base}/lib/python{py_version_short} +platstdlib = {platbase}/lib/python{py_version_short} +purelib = {base}/lib/python{py_version_short}/site-packages +platlib = {platbase}/lib/python{py_version_short}/site-packages +include = {base}/include/python{py_version_short}{abiflags} +platinclude = {platbase}/include/python{py_version_short}{abiflags} +data = {base} + +[posix_home] +stdlib = {base}/lib/python +platstdlib = {base}/lib/python +purelib = {base}/lib/python +platlib = {base}/lib/python +include = {base}/include/python +platinclude = {base}/include/python +scripts = {base}/bin +data = {base} + +[nt] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2_home] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[nt_user] +stdlib = {userbase}/Python{py_version_nodot} +platstdlib = {userbase}/Python{py_version_nodot} +purelib = {userbase}/Python{py_version_nodot}/site-packages +platlib = {userbase}/Python{py_version_nodot}/site-packages +include = {userbase}/Python{py_version_nodot}/Include +scripts = {userbase}/Scripts +data = {userbase} + +[posix_user] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[osx_framework_user] +stdlib = {userbase}/lib/python +platstdlib = {userbase}/lib/python +purelib = {userbase}/lib/python/site-packages +platlib = {userbase}/lib/python/site-packages +include = {userbase}/include +scripts = {userbase}/bin +data = {userbase} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py new file mode 100644 index 0000000..1df3aba --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/sysconfig.py @@ -0,0 +1,788 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Access to Python's configuration information.""" + +import codecs +import os +import re +import sys +from os.path import pardir, realpath +try: + import configparser +except ImportError: + import ConfigParser as configparser + + +__all__ = [ + 'get_config_h_filename', + 'get_config_var', + 'get_config_vars', + 'get_makefile_filename', + 'get_path', + 'get_path_names', + 'get_paths', + 'get_platform', + 'get_python_version', + 'get_scheme_names', + 'parse_config_h', +] + + +def _safe_realpath(path): + try: + return realpath(path) + except OSError: + return path + + +if sys.executable: + _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) +else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + _PROJECT_BASE = _safe_realpath(os.getcwd()) + +if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) +# PC/VS7.1 +if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) +# PC/AMD64 +if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) + + +def is_python_build(): + for fn in ("Setup.dist", "Setup.local"): + if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): + return True + return False + +_PYTHON_BUILD = is_python_build() + +_cfg_read = False + +def _ensure_cfg_read(): + global _cfg_read + if not _cfg_read: + from ..resources import finder + backport_package = __name__.rsplit('.', 1)[0] + _finder = finder(backport_package) + _cfgfile = _finder.find('sysconfig.cfg') + assert _cfgfile, 'sysconfig.cfg exists' + with _cfgfile.as_stream() as s: + _SCHEMES.readfp(s) + if _PYTHON_BUILD: + for scheme in ('posix_prefix', 'posix_home'): + _SCHEMES.set(scheme, 'include', '{srcdir}/Include') + _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.') + + _cfg_read = True + + +_SCHEMES = configparser.RawConfigParser() +_VAR_REPL = re.compile(r'\{([^{]*?)\}') + +def _expand_globals(config): + _ensure_cfg_read() + if config.has_section('globals'): + globals = config.items('globals') + else: + globals = tuple() + + sections = config.sections() + for section in sections: + if section == 'globals': + continue + for option, value in globals: + if config.has_option(section, option): + continue + config.set(section, option, value) + config.remove_section('globals') + + # now expanding local variables defined in the cfg file + # + for section in config.sections(): + variables = dict(config.items(section)) + + def _replacer(matchobj): + name = matchobj.group(1) + if name in variables: + return variables[name] + return matchobj.group(0) + + for option, value in config.items(section): + config.set(section, option, _VAR_REPL.sub(_replacer, value)) + +#_expand_globals(_SCHEMES) + + # FIXME don't rely on sys.version here, its format is an implementation detail + # of CPython, use sys.version_info or sys.hexversion +_PY_VERSION = sys.version.split()[0] +_PY_VERSION_SHORT = sys.version[:3] +_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2] +_PREFIX = os.path.normpath(sys.prefix) +_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +_CONFIG_VARS = None +_USER_BASE = None + + +def _subst_vars(path, local_vars): + """In the string `path`, replace tokens like {some.thing} with the + corresponding value from the map `local_vars`. + + If there is no corresponding value, leave the token unchanged. + """ + def _replacer(matchobj): + name = matchobj.group(1) + if name in local_vars: + return local_vars[name] + elif name in os.environ: + return os.environ[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, path) + + +def _extend_dict(target_dict, other_dict): + target_keys = target_dict.keys() + for key, value in other_dict.items(): + if key in target_keys: + continue + target_dict[key] = value + + +def _expand_vars(scheme, vars): + res = {} + if vars is None: + vars = {} + _extend_dict(vars, get_config_vars()) + + for key, value in _SCHEMES.items(scheme): + if os.name in ('posix', 'nt'): + value = os.path.expanduser(value) + res[key] = os.path.normpath(_subst_vars(value, vars)) + return res + + +def format_value(value, vars): + def _replacer(matchobj): + name = matchobj.group(1) + if name in vars: + return vars[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, value) + + +def _get_default_scheme(): + if os.name == 'posix': + # the default scheme for posix is posix_prefix + return 'posix_prefix' + return os.name + + +def _getuserbase(): + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + # what about 'os2emx', 'riscos' ? + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + return env_base + else: + return joinuser(base, "Python") + + if sys.platform == "darwin": + framework = get_config_var("PYTHONFRAMEWORK") + if framework: + if env_base: + return env_base + else: + return joinuser("~", "Library", framework, "%d.%d" % + sys.version_info[:2]) + + if env_base: + return env_base + else: + return joinuser("~", ".local") + + +def _parse_makefile(filename, vars=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + # Regexes needed for parsing Makefile (and similar syntaxes, + # like old-style Setup files). + _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") + _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") + _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + + if vars is None: + vars = {} + done = {} + notdone = {} + + with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f: + lines = f.readlines() + + for line in lines: + if line.startswith('#') or line.strip() == '': + continue + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m is not None: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if (name.startswith('PY_') and + name[3:] in renamed_variables): + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + + else: + done[n] = item = "" + + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: + value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + variables.remove(name) + + if (name.startswith('PY_') and + name[3:] in renamed_variables): + + name = name[3:] + if name not in done: + done[name] = value + + else: + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value + variables.remove(name) + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + vars.update(done) + return vars + + +def get_makefile_filename(): + """Return the path of the Makefile.""" + if _PYTHON_BUILD: + return os.path.join(_PROJECT_BASE, "Makefile") + if hasattr(sys, 'abiflags'): + config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags) + else: + config_dir_name = 'config' + return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') + + +def _init_posix(vars): + """Initialize the module as appropriate for POSIX systems.""" + # load the installed Makefile: + makefile = get_makefile_filename() + try: + _parse_makefile(makefile, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % makefile + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # load the installed pyconfig.h: + config_h = get_config_h_filename() + try: + with open(config_h) as f: + parse_config_h(f, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % config_h + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # On AIX, there are wrong paths to the linker scripts in the Makefile + # -- these paths are relative to the Python source, but when installed + # the scripts are in another directory. + if _PYTHON_BUILD: + vars['LDSHARED'] = vars['BLDSHARED'] + + +def _init_non_posix(vars): + """Initialize the module as appropriate for NT""" + # set basic install directories + vars['LIBDEST'] = get_path('stdlib') + vars['BINLIBDEST'] = get_path('platstdlib') + vars['INCLUDEPY'] = get_path('include') + vars['SO'] = '.pyd' + vars['EXE'] = '.exe' + vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT + vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + +# +# public APIs +# + + +def parse_config_h(fp, vars=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if vars is None: + vars = {} + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + + while True: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: + v = int(v) + except ValueError: + pass + vars[n] = v + else: + m = undef_rx.match(line) + if m: + vars[m.group(1)] = 0 + return vars + + +def get_config_h_filename(): + """Return the path of pyconfig.h.""" + if _PYTHON_BUILD: + if os.name == "nt": + inc_dir = os.path.join(_PROJECT_BASE, "PC") + else: + inc_dir = _PROJECT_BASE + else: + inc_dir = get_path('platinclude') + return os.path.join(inc_dir, 'pyconfig.h') + + +def get_scheme_names(): + """Return a tuple containing the schemes names.""" + return tuple(sorted(_SCHEMES.sections())) + + +def get_path_names(): + """Return a tuple containing the paths names.""" + # xxx see if we want a static list + return _SCHEMES.options('posix_prefix') + + +def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): + """Return a mapping containing an install scheme. + + ``scheme`` is the install scheme name. If not provided, it will + return the default scheme for the current platform. + """ + _ensure_cfg_read() + if expand: + return _expand_vars(scheme, vars) + else: + return dict(_SCHEMES.items(scheme)) + + +def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): + """Return a path corresponding to the scheme. + + ``scheme`` is the install scheme name. + """ + return get_paths(scheme, vars, expand)[name] + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. + + On Unix, this means every variable defined in Python's installed Makefile; + On Windows and Mac OS it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _CONFIG_VARS + if _CONFIG_VARS is None: + _CONFIG_VARS = {} + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # distutils2 module. + _CONFIG_VARS['prefix'] = _PREFIX + _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX + _CONFIG_VARS['py_version'] = _PY_VERSION + _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT + _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] + _CONFIG_VARS['base'] = _PREFIX + _CONFIG_VARS['platbase'] = _EXEC_PREFIX + _CONFIG_VARS['projectbase'] = _PROJECT_BASE + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = '' + + if os.name in ('nt', 'os2'): + _init_non_posix(_CONFIG_VARS) + if os.name == 'posix': + _init_posix(_CONFIG_VARS) + # Setting 'userbase' is done below the call to the + # init function to enable using 'get_config_var' in + # the init-function. + if sys.version >= '2.6': + _CONFIG_VARS['userbase'] = _getuserbase() + + if 'srcdir' not in _CONFIG_VARS: + _CONFIG_VARS['srcdir'] = _PROJECT_BASE + else: + _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) + + # Convert srcdir into an absolute path if it appears necessary. + # Normally it is relative to the build directory. However, during + # testing, for example, we might be running a non-installed python + # from a different directory. + if _PYTHON_BUILD and os.name == "posix": + base = _PROJECT_BASE + try: + cwd = os.getcwd() + except OSError: + cwd = None + if (not os.path.isabs(_CONFIG_VARS['srcdir']) and + base != cwd): + # srcdir is relative and we are not in the same directory + # as the executable. Assume executable is in the build + # directory and make srcdir absolute. + srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) + _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) + + if sys.platform == 'darwin': + kernel_version = os.uname()[2] # Kernel version (8.4.3) + major_version = int(kernel_version.split('.')[0]) + + if major_version < 8: + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _CONFIG_VARS[key] = flags + else: + # Allow the user to override the architecture flags using + # an environment variable. + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _CONFIG_VARS[key] = flags + + # If we're on OSX 10.5 or later and the user tries to + # compiles an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. + # + # The major usecase for this is users using a Python.org + # binary installer on OSX 10.6: that installer uses + # the 10.4u SDK, but that SDK is not installed by default + # when you install Xcode. + # + CFLAGS = _CONFIG_VARS.get('CFLAGS', '') + m = re.search(r'-isysroot\s+(\S+)', CFLAGS) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-isysroot\s+\S+(\s|$)', ' ', flags) + _CONFIG_VARS[key] = flags + + if args: + vals = [] + for name in args: + vals.append(_CONFIG_VARS.get(name)) + return vals + else: + return _CONFIG_VARS + + +def get_config_var(name): + """Return the value of a single variable using the dictionary returned by + 'get_config_vars()'. + + Equivalent to get_config_vars().get(name) + """ + return get_config_vars().get(name) + + +def get_platform(): + """Return a string that identifies the current platform. + + This is used mainly to distinguish platform-specific build directories and + platform-specific built distributions. Typically includes the OS name + and version and the architecture (as supplied by 'os.uname()'), + although the exact information included depends on the OS; eg. for IRIX + the architecture isn't particularly important (IRIX only runs on SGI + hardware), but for Linux the kernel version isn't particularly + important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + irix-5.3 + irix64-6.2 + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win-ia64 (64bit Windows on Itanium) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + """ + if os.name == 'nt': + # sniff sys.version for architecture. + prefix = " bit (" + i = sys.version.find(prefix) + if i == -1: + return sys.platform + j = sys.version.find(")", i) + look = sys.version[i+len(prefix):j].lower() + if look == 'amd64': + return 'win-amd64' + if look == 'itanium': + return 'win-ia64' + return sys.platform + + if os.name != "posix" or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + osname, host, release, version, machine = os.uname() + + # Convert the OS name to lowercase, remove '/' characters + # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname[:5] == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = "%d.%s" % (int(release[0]) - 3, release[2:]) + # fall through to standard osname-release-machine representation + elif osname[:4] == "irix": # could be "irix64"! + return "%s-%s" % (osname, release) + elif osname[:3] == "aix": + return "%s-%s.%s" % (osname, version, release) + elif osname[:6] == "cygwin": + osname = "cygwin" + rel_re = re.compile(r'[\d.]+') + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + # + # For our purposes, we'll assume that the system version from + # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set + # to. This makes the compatibility story a bit more sane because the + # machine is going to compile and link as if it were + # MACOSX_DEPLOYMENT_TARGET. + cfgvars = get_config_vars() + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + + if True: + # Always calculate the release of the running machine, + # needed to determine if we can build fat binaries or not. + + macrelease = macver + # Get the system version. Reading this plist is a documented + # way to get the system version (see the documentation for + # the Gestalt Manager) + try: + f = open('/System/Library/CoreServices/SystemVersion.plist') + except IOError: + # We're on a plain darwin box, fall back to the default + # behaviour. + pass + else: + try: + m = re.search(r'<key>ProductUserVisibleVersion</key>\s*' + r'<string>(.*?)</string>', f.read()) + finally: + f.close() + if m is not None: + macrelease = '.'.join(m.group(1).split('.')[:2]) + # else: fall back to the default behaviour + + if not macver: + macver = macrelease + + if macver: + release = macver + osname = "macosx" + + if ((macrelease + '.') >= '10.4.' and + '-arch' in get_config_vars().get('CFLAGS', '').strip()): + # The universal build will build fat binaries, but not on + # systems before 10.4 + # + # Try to detect 4-way universal builds, those have machine-type + # 'universal' instead of 'fat'. + + machine = 'fat' + cflags = get_config_vars().get('CFLAGS') + + archs = re.findall(r'-arch\s+(\S+)', cflags) + archs = tuple(sorted(set(archs))) + + if len(archs) == 1: + machine = archs[0] + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): + machine = 'intel' + elif archs == ('i386', 'ppc', 'x86_64'): + machine = 'fat3' + elif archs == ('ppc64', 'x86_64'): + machine = 'fat64' + elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): + machine = 'universal' + else: + raise ValueError( + "Don't know machine value for archs=%r" % (archs,)) + + elif machine == 'i386': + # On OSX the machine type returned by uname is always the + # 32-bit variant, even if the executable architecture is + # the 64-bit variant + if sys.maxsize >= 2**32: + machine = 'x86_64' + + elif machine in ('PowerPC', 'Power_Macintosh'): + # Pick a sane name for the PPC architecture. + # See 'i386' case + if sys.maxsize >= 2**32: + machine = 'ppc64' + else: + machine = 'ppc' + + return "%s-%s-%s" % (osname, release, machine) + + +def get_python_version(): + return _PY_VERSION_SHORT + + +def _print_dict(title, data): + for index, (key, value) in enumerate(sorted(data.items())): + if index == 0: + print('%s: ' % (title)) + print('\t%s = "%s"' % (key, value)) + + +def _main(): + """Display all information sysconfig detains.""" + print('Platform: "%s"' % get_platform()) + print('Python version: "%s"' % get_python_version()) + print('Current installation scheme: "%s"' % _get_default_scheme()) + print() + _print_dict('Paths', get_paths()) + print() + _print_dict('Variables', get_config_vars()) + + +if __name__ == '__main__': + _main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py new file mode 100644 index 0000000..d66d856 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/_backport/tarfile.py @@ -0,0 +1,2607 @@ +#------------------------------------------------------------------- +# tarfile.py +#------------------------------------------------------------------- +# Copyright (C) 2002 Lars Gustaebel <lars@gustaebel.de> +# All rights reserved. +# +# 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. +# +from __future__ import print_function + +"""Read from and write to tar format archives. +""" + +__version__ = "$Revision$" + +version = "0.9.0" +__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" +__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" +__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" +__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." + +#--------- +# Imports +#--------- +import sys +import os +import stat +import errno +import time +import struct +import copy +import re + +try: + import grp, pwd +except ImportError: + grp = pwd = None + +# os.symlink on Windows prior to 6.0 raises NotImplementedError +symlink_exception = (AttributeError, NotImplementedError) +try: + # WindowsError (1314) will be raised if the caller does not hold the + # SeCreateSymbolicLinkPrivilege privilege + symlink_exception += (WindowsError,) +except NameError: + pass + +# from tarfile import * +__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] + +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins + +_open = builtins.open # Since 'open' is TarFile.open + +#--------------------------------------------------------- +# tar constants +#--------------------------------------------------------- +NUL = b"\0" # the null character +BLOCKSIZE = 512 # length of processing blocks +RECORDSIZE = BLOCKSIZE * 20 # length of records +GNU_MAGIC = b"ustar \0" # magic gnu tar string +POSIX_MAGIC = b"ustar\x0000" # magic posix tar string + +LENGTH_NAME = 100 # maximum length of a filename +LENGTH_LINK = 100 # maximum length of a linkname +LENGTH_PREFIX = 155 # maximum length of the prefix field + +REGTYPE = b"0" # regular file +AREGTYPE = b"\0" # regular file +LNKTYPE = b"1" # link (inside tarfile) +SYMTYPE = b"2" # symbolic link +CHRTYPE = b"3" # character special device +BLKTYPE = b"4" # block special device +DIRTYPE = b"5" # directory +FIFOTYPE = b"6" # fifo special device +CONTTYPE = b"7" # contiguous file + +GNUTYPE_LONGNAME = b"L" # GNU tar longname +GNUTYPE_LONGLINK = b"K" # GNU tar longlink +GNUTYPE_SPARSE = b"S" # GNU tar sparse file + +XHDTYPE = b"x" # POSIX.1-2001 extended header +XGLTYPE = b"g" # POSIX.1-2001 global header +SOLARIS_XHDTYPE = b"X" # Solaris extended header + +USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format +GNU_FORMAT = 1 # GNU tar format +PAX_FORMAT = 2 # POSIX.1-2001 (pax) format +DEFAULT_FORMAT = GNU_FORMAT + +#--------------------------------------------------------- +# tarfile constants +#--------------------------------------------------------- +# File types that tarfile supports: +SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, + SYMTYPE, DIRTYPE, FIFOTYPE, + CONTTYPE, CHRTYPE, BLKTYPE, + GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# File types that will be treated as a regular file. +REGULAR_TYPES = (REGTYPE, AREGTYPE, + CONTTYPE, GNUTYPE_SPARSE) + +# File types that are part of the GNU tar format. +GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# Fields from a pax header that override a TarInfo attribute. +PAX_FIELDS = ("path", "linkpath", "size", "mtime", + "uid", "gid", "uname", "gname") + +# Fields from a pax header that are affected by hdrcharset. +PAX_NAME_FIELDS = set(("path", "linkpath", "uname", "gname")) + +# Fields in a pax header that are numbers, all other fields +# are treated as strings. +PAX_NUMBER_FIELDS = { + "atime": float, + "ctime": float, + "mtime": float, + "uid": int, + "gid": int, + "size": int +} + +#--------------------------------------------------------- +# Bits used in the mode field, values in octal. +#--------------------------------------------------------- +S_IFLNK = 0o120000 # symbolic link +S_IFREG = 0o100000 # regular file +S_IFBLK = 0o060000 # block device +S_IFDIR = 0o040000 # directory +S_IFCHR = 0o020000 # character device +S_IFIFO = 0o010000 # fifo + +TSUID = 0o4000 # set UID on execution +TSGID = 0o2000 # set GID on execution +TSVTX = 0o1000 # reserved + +TUREAD = 0o400 # read by owner +TUWRITE = 0o200 # write by owner +TUEXEC = 0o100 # execute/search by owner +TGREAD = 0o040 # read by group +TGWRITE = 0o020 # write by group +TGEXEC = 0o010 # execute/search by group +TOREAD = 0o004 # read by other +TOWRITE = 0o002 # write by other +TOEXEC = 0o001 # execute/search by other + +#--------------------------------------------------------- +# initialization +#--------------------------------------------------------- +if os.name in ("nt", "ce"): + ENCODING = "utf-8" +else: + ENCODING = sys.getfilesystemencoding() + +#--------------------------------------------------------- +# Some useful functions +#--------------------------------------------------------- + +def stn(s, length, encoding, errors): + """Convert a string to a null-terminated bytes object. + """ + s = s.encode(encoding, errors) + return s[:length] + (length - len(s)) * NUL + +def nts(s, encoding, errors): + """Convert a null-terminated bytes object to a string. + """ + p = s.find(b"\0") + if p != -1: + s = s[:p] + return s.decode(encoding, errors) + +def nti(s): + """Convert a number field to a python number. + """ + # There are two possible encodings for a number field, see + # itn() below. + if s[0] != chr(0o200): + try: + n = int(nts(s, "ascii", "strict") or "0", 8) + except ValueError: + raise InvalidHeaderError("invalid header") + else: + n = 0 + for i in range(len(s) - 1): + n <<= 8 + n += ord(s[i + 1]) + return n + +def itn(n, digits=8, format=DEFAULT_FORMAT): + """Convert a python number to a number field. + """ + # POSIX 1003.1-1988 requires numbers to be encoded as a string of + # octal digits followed by a null-byte, this allows values up to + # (8**(digits-1))-1. GNU tar allows storing numbers greater than + # that if necessary. A leading 0o200 byte indicates this particular + # encoding, the following digits-1 bytes are a big-endian + # representation. This allows values up to (256**(digits-1))-1. + if 0 <= n < 8 ** (digits - 1): + s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL + else: + if format != GNU_FORMAT or n >= 256 ** (digits - 1): + raise ValueError("overflow in number field") + + if n < 0: + # XXX We mimic GNU tar's behaviour with negative numbers, + # this could raise OverflowError. + n = struct.unpack("L", struct.pack("l", n))[0] + + s = bytearray() + for i in range(digits - 1): + s.insert(0, n & 0o377) + n >>= 8 + s.insert(0, 0o200) + return s + +def calc_chksums(buf): + """Calculate the checksum for a member's header by summing up all + characters except for the chksum field which is treated as if + it was filled with spaces. According to the GNU tar sources, + some tars (Sun and NeXT) calculate chksum with signed char, + which will be different if there are chars in the buffer with + the high bit set. So we calculate two checksums, unsigned and + signed. + """ + unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) + signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) + return unsigned_chksum, signed_chksum + +def copyfileobj(src, dst, length=None): + """Copy length bytes from fileobj src to fileobj dst. + If length is None, copy the entire content. + """ + if length == 0: + return + if length is None: + while True: + buf = src.read(16*1024) + if not buf: + break + dst.write(buf) + return + + BUFSIZE = 16 * 1024 + blocks, remainder = divmod(length, BUFSIZE) + for b in range(blocks): + buf = src.read(BUFSIZE) + if len(buf) < BUFSIZE: + raise IOError("end of file reached") + dst.write(buf) + + if remainder != 0: + buf = src.read(remainder) + if len(buf) < remainder: + raise IOError("end of file reached") + dst.write(buf) + return + +filemode_table = ( + ((S_IFLNK, "l"), + (S_IFREG, "-"), + (S_IFBLK, "b"), + (S_IFDIR, "d"), + (S_IFCHR, "c"), + (S_IFIFO, "p")), + + ((TUREAD, "r"),), + ((TUWRITE, "w"),), + ((TUEXEC|TSUID, "s"), + (TSUID, "S"), + (TUEXEC, "x")), + + ((TGREAD, "r"),), + ((TGWRITE, "w"),), + ((TGEXEC|TSGID, "s"), + (TSGID, "S"), + (TGEXEC, "x")), + + ((TOREAD, "r"),), + ((TOWRITE, "w"),), + ((TOEXEC|TSVTX, "t"), + (TSVTX, "T"), + (TOEXEC, "x")) +) + +def filemode(mode): + """Convert a file's mode to a string of the form + -rwxrwxrwx. + Used by TarFile.list() + """ + perm = [] + for table in filemode_table: + for bit, char in table: + if mode & bit == bit: + perm.append(char) + break + else: + perm.append("-") + return "".join(perm) + +class TarError(Exception): + """Base exception.""" + pass +class ExtractError(TarError): + """General exception for extract errors.""" + pass +class ReadError(TarError): + """Exception for unreadable tar archives.""" + pass +class CompressionError(TarError): + """Exception for unavailable compression methods.""" + pass +class StreamError(TarError): + """Exception for unsupported operations on stream-like TarFiles.""" + pass +class HeaderError(TarError): + """Base exception for header errors.""" + pass +class EmptyHeaderError(HeaderError): + """Exception for empty headers.""" + pass +class TruncatedHeaderError(HeaderError): + """Exception for truncated headers.""" + pass +class EOFHeaderError(HeaderError): + """Exception for end of file headers.""" + pass +class InvalidHeaderError(HeaderError): + """Exception for invalid headers.""" + pass +class SubsequentHeaderError(HeaderError): + """Exception for missing and invalid extended headers.""" + pass + +#--------------------------- +# internal stream interface +#--------------------------- +class _LowLevelFile(object): + """Low-level file object. Supports reading and writing. + It is used instead of a regular file object for streaming + access. + """ + + def __init__(self, name, mode): + mode = { + "r": os.O_RDONLY, + "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + }[mode] + if hasattr(os, "O_BINARY"): + mode |= os.O_BINARY + self.fd = os.open(name, mode, 0o666) + + def close(self): + os.close(self.fd) + + def read(self, size): + return os.read(self.fd, size) + + def write(self, s): + os.write(self.fd, s) + +class _Stream(object): + """Class that serves as an adapter between TarFile and + a stream-like object. The stream-like object only + needs to have a read() or write() method and is accessed + blockwise. Use of gzip or bzip2 compression is possible. + A stream-like object could be for example: sys.stdin, + sys.stdout, a socket, a tape device etc. + + _Stream is intended to be used only internally. + """ + + def __init__(self, name, mode, comptype, fileobj, bufsize): + """Construct a _Stream object. + """ + self._extfileobj = True + if fileobj is None: + fileobj = _LowLevelFile(name, mode) + self._extfileobj = False + + if comptype == '*': + # Enable transparent compression detection for the + # stream interface + fileobj = _StreamProxy(fileobj) + comptype = fileobj.getcomptype() + + self.name = name or "" + self.mode = mode + self.comptype = comptype + self.fileobj = fileobj + self.bufsize = bufsize + self.buf = b"" + self.pos = 0 + self.closed = False + + try: + if comptype == "gz": + try: + import zlib + except ImportError: + raise CompressionError("zlib module is not available") + self.zlib = zlib + self.crc = zlib.crc32(b"") + if mode == "r": + self._init_read_gz() + else: + self._init_write_gz() + + if comptype == "bz2": + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + if mode == "r": + self.dbuf = b"" + self.cmp = bz2.BZ2Decompressor() + else: + self.cmp = bz2.BZ2Compressor() + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + def __del__(self): + if hasattr(self, "closed") and not self.closed: + self.close() + + def _init_write_gz(self): + """Initialize for writing with gzip compression. + """ + self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, + -self.zlib.MAX_WBITS, + self.zlib.DEF_MEM_LEVEL, + 0) + timestamp = struct.pack("<L", int(time.time())) + self.__write(b"\037\213\010\010" + timestamp + b"\002\377") + if self.name.endswith(".gz"): + self.name = self.name[:-3] + # RFC1952 says we must use ISO-8859-1 for the FNAME field. + self.__write(self.name.encode("iso-8859-1", "replace") + NUL) + + def write(self, s): + """Write string s to the stream. + """ + if self.comptype == "gz": + self.crc = self.zlib.crc32(s, self.crc) + self.pos += len(s) + if self.comptype != "tar": + s = self.cmp.compress(s) + self.__write(s) + + def __write(self, s): + """Write string s to the stream if a whole new block + is ready to be written. + """ + self.buf += s + while len(self.buf) > self.bufsize: + self.fileobj.write(self.buf[:self.bufsize]) + self.buf = self.buf[self.bufsize:] + + def close(self): + """Close the _Stream object. No operation should be + done on it afterwards. + """ + if self.closed: + return + + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() + + if self.mode == "w" and self.buf: + self.fileobj.write(self.buf) + self.buf = b"" + if self.comptype == "gz": + # The native zlib crc is an unsigned 32-bit integer, but + # the Python wrapper implicitly casts that to a signed C + # long. So, on a 32-bit box self.crc may "look negative", + # while the same crc on a 64-bit box may "look positive". + # To avoid irksome warnings from the `struct` module, force + # it to look positive on all boxes. + self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff)) + self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF)) + + if not self._extfileobj: + self.fileobj.close() + + self.closed = True + + def _init_read_gz(self): + """Initialize for reading a gzip compressed fileobj. + """ + self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS) + self.dbuf = b"" + + # taken from gzip.GzipFile with some alterations + if self.__read(2) != b"\037\213": + raise ReadError("not a gzip file") + if self.__read(1) != b"\010": + raise CompressionError("unsupported compression method") + + flag = ord(self.__read(1)) + self.__read(6) + + if flag & 4: + xlen = ord(self.__read(1)) + 256 * ord(self.__read(1)) + self.read(xlen) + if flag & 8: + while True: + s = self.__read(1) + if not s or s == NUL: + break + if flag & 16: + while True: + s = self.__read(1) + if not s or s == NUL: + break + if flag & 2: + self.__read(2) + + def tell(self): + """Return the stream's file pointer position. + """ + return self.pos + + def seek(self, pos=0): + """Set the stream's file pointer to pos. Negative seeking + is forbidden. + """ + if pos - self.pos >= 0: + blocks, remainder = divmod(pos - self.pos, self.bufsize) + for i in range(blocks): + self.read(self.bufsize) + self.read(remainder) + else: + raise StreamError("seeking backwards is not allowed") + return self.pos + + def read(self, size=None): + """Return the next size number of bytes from the stream. + If size is not defined, return all bytes of the stream + up to EOF. + """ + if size is None: + t = [] + while True: + buf = self._read(self.bufsize) + if not buf: + break + t.append(buf) + buf = "".join(t) + else: + buf = self._read(size) + self.pos += len(buf) + return buf + + def _read(self, size): + """Return size bytes from the stream. + """ + if self.comptype == "tar": + return self.__read(size) + + c = len(self.dbuf) + while c < size: + buf = self.__read(self.bufsize) + if not buf: + break + try: + buf = self.cmp.decompress(buf) + except IOError: + raise ReadError("invalid compressed data") + self.dbuf += buf + c += len(buf) + buf = self.dbuf[:size] + self.dbuf = self.dbuf[size:] + return buf + + def __read(self, size): + """Return size bytes from stream. If internal buffer is empty, + read another block from the stream. + """ + c = len(self.buf) + while c < size: + buf = self.fileobj.read(self.bufsize) + if not buf: + break + self.buf += buf + c += len(buf) + buf = self.buf[:size] + self.buf = self.buf[size:] + return buf +# class _Stream + +class _StreamProxy(object): + """Small proxy class that enables transparent compression + detection for the Stream interface (mode 'r|*'). + """ + + def __init__(self, fileobj): + self.fileobj = fileobj + self.buf = self.fileobj.read(BLOCKSIZE) + + def read(self, size): + self.read = self.fileobj.read + return self.buf + + def getcomptype(self): + if self.buf.startswith(b"\037\213\010"): + return "gz" + if self.buf.startswith(b"BZh91"): + return "bz2" + return "tar" + + def close(self): + self.fileobj.close() +# class StreamProxy + +class _BZ2Proxy(object): + """Small proxy class that enables external file object + support for "r:bz2" and "w:bz2" modes. This is actually + a workaround for a limitation in bz2 module's BZ2File + class which (unlike gzip.GzipFile) has no support for + a file object argument. + """ + + blocksize = 16 * 1024 + + def __init__(self, fileobj, mode): + self.fileobj = fileobj + self.mode = mode + self.name = getattr(self.fileobj, "name", None) + self.init() + + def init(self): + import bz2 + self.pos = 0 + if self.mode == "r": + self.bz2obj = bz2.BZ2Decompressor() + self.fileobj.seek(0) + self.buf = b"" + else: + self.bz2obj = bz2.BZ2Compressor() + + def read(self, size): + x = len(self.buf) + while x < size: + raw = self.fileobj.read(self.blocksize) + if not raw: + break + data = self.bz2obj.decompress(raw) + self.buf += data + x += len(data) + + buf = self.buf[:size] + self.buf = self.buf[size:] + self.pos += len(buf) + return buf + + def seek(self, pos): + if pos < self.pos: + self.init() + self.read(pos - self.pos) + + def tell(self): + return self.pos + + def write(self, data): + self.pos += len(data) + raw = self.bz2obj.compress(data) + self.fileobj.write(raw) + + def close(self): + if self.mode == "w": + raw = self.bz2obj.flush() + self.fileobj.write(raw) +# class _BZ2Proxy + +#------------------------ +# Extraction file object +#------------------------ +class _FileInFile(object): + """A thin wrapper around an existing file object that + provides a part of its data as an individual file + object. + """ + + def __init__(self, fileobj, offset, size, blockinfo=None): + self.fileobj = fileobj + self.offset = offset + self.size = size + self.position = 0 + + if blockinfo is None: + blockinfo = [(0, size)] + + # Construct a map with data and zero blocks. + self.map_index = 0 + self.map = [] + lastpos = 0 + realpos = self.offset + for offset, size in blockinfo: + if offset > lastpos: + self.map.append((False, lastpos, offset, None)) + self.map.append((True, offset, offset + size, realpos)) + realpos += size + lastpos = offset + size + if lastpos < self.size: + self.map.append((False, lastpos, self.size, None)) + + def seekable(self): + if not hasattr(self.fileobj, "seekable"): + # XXX gzip.GzipFile and bz2.BZ2File + return True + return self.fileobj.seekable() + + def tell(self): + """Return the current file position. + """ + return self.position + + def seek(self, position): + """Seek to a position in the file. + """ + self.position = position + + def read(self, size=None): + """Read data from the file. + """ + if size is None: + size = self.size - self.position + else: + size = min(size, self.size - self.position) + + buf = b"" + while size > 0: + while True: + data, start, stop, offset = self.map[self.map_index] + if start <= self.position < stop: + break + else: + self.map_index += 1 + if self.map_index == len(self.map): + self.map_index = 0 + length = min(size, stop - self.position) + if data: + self.fileobj.seek(offset + (self.position - start)) + buf += self.fileobj.read(length) + else: + buf += NUL * length + size -= length + self.position += length + return buf +#class _FileInFile + + +class ExFileObject(object): + """File-like object for reading an archive member. + Is returned by TarFile.extractfile(). + """ + blocksize = 1024 + + def __init__(self, tarfile, tarinfo): + self.fileobj = _FileInFile(tarfile.fileobj, + tarinfo.offset_data, + tarinfo.size, + tarinfo.sparse) + self.name = tarinfo.name + self.mode = "r" + self.closed = False + self.size = tarinfo.size + + self.position = 0 + self.buffer = b"" + + def readable(self): + return True + + def writable(self): + return False + + def seekable(self): + return self.fileobj.seekable() + + def read(self, size=None): + """Read at most size bytes from the file. If size is not + present or None, read all data until EOF is reached. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + buf = b"" + if self.buffer: + if size is None: + buf = self.buffer + self.buffer = b"" + else: + buf = self.buffer[:size] + self.buffer = self.buffer[size:] + + if size is None: + buf += self.fileobj.read() + else: + buf += self.fileobj.read(size - len(buf)) + + self.position += len(buf) + return buf + + # XXX TextIOWrapper uses the read1() method. + read1 = read + + def readline(self, size=-1): + """Read one entire line from the file. If size is present + and non-negative, return a string with at most that + size, which may be an incomplete line. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + while True: + buf = self.fileobj.read(self.blocksize) + self.buffer += buf + if not buf or b"\n" in buf: + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + pos = len(self.buffer) + break + + if size != -1: + pos = min(size, pos) + + buf = self.buffer[:pos] + self.buffer = self.buffer[pos:] + self.position += len(buf) + return buf + + def readlines(self): + """Return a list with all remaining lines. + """ + result = [] + while True: + line = self.readline() + if not line: break + result.append(line) + return result + + def tell(self): + """Return the current file position. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + return self.position + + def seek(self, pos, whence=os.SEEK_SET): + """Seek to a position in the file. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + if whence == os.SEEK_SET: + self.position = min(max(pos, 0), self.size) + elif whence == os.SEEK_CUR: + if pos < 0: + self.position = max(self.position + pos, 0) + else: + self.position = min(self.position + pos, self.size) + elif whence == os.SEEK_END: + self.position = max(min(self.size + pos, self.size), 0) + else: + raise ValueError("Invalid argument") + + self.buffer = b"" + self.fileobj.seek(self.position) + + def close(self): + """Close the file object. + """ + self.closed = True + + def __iter__(self): + """Get an iterator over the file's lines. + """ + while True: + line = self.readline() + if not line: + break + yield line +#class ExFileObject + +#------------------ +# Exported Classes +#------------------ +class TarInfo(object): + """Informational class which holds the details about an + archive member given by a tar header block. + TarInfo objects are returned by TarFile.getmember(), + TarFile.getmembers() and TarFile.gettarinfo() and are + usually created internally. + """ + + __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", + "chksum", "type", "linkname", "uname", "gname", + "devmajor", "devminor", + "offset", "offset_data", "pax_headers", "sparse", + "tarfile", "_sparse_structs", "_link_target") + + def __init__(self, name=""): + """Construct a TarInfo object. name is the optional name + of the member. + """ + self.name = name # member name + self.mode = 0o644 # file permissions + self.uid = 0 # user id + self.gid = 0 # group id + self.size = 0 # file size + self.mtime = 0 # modification time + self.chksum = 0 # header checksum + self.type = REGTYPE # member type + self.linkname = "" # link name + self.uname = "" # user name + self.gname = "" # group name + self.devmajor = 0 # device major number + self.devminor = 0 # device minor number + + self.offset = 0 # the tar header starts here + self.offset_data = 0 # the file's data starts here + + self.sparse = None # sparse member information + self.pax_headers = {} # pax header information + + # In pax headers the "name" and "linkname" field are called + # "path" and "linkpath". + def _getpath(self): + return self.name + def _setpath(self, name): + self.name = name + path = property(_getpath, _setpath) + + def _getlinkpath(self): + return self.linkname + def _setlinkpath(self, linkname): + self.linkname = linkname + linkpath = property(_getlinkpath, _setlinkpath) + + def __repr__(self): + return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) + + def get_info(self): + """Return the TarInfo's attributes as a dictionary. + """ + info = { + "name": self.name, + "mode": self.mode & 0o7777, + "uid": self.uid, + "gid": self.gid, + "size": self.size, + "mtime": self.mtime, + "chksum": self.chksum, + "type": self.type, + "linkname": self.linkname, + "uname": self.uname, + "gname": self.gname, + "devmajor": self.devmajor, + "devminor": self.devminor + } + + if info["type"] == DIRTYPE and not info["name"].endswith("/"): + info["name"] += "/" + + return info + + def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): + """Return a tar header as a string of 512 byte blocks. + """ + info = self.get_info() + + if format == USTAR_FORMAT: + return self.create_ustar_header(info, encoding, errors) + elif format == GNU_FORMAT: + return self.create_gnu_header(info, encoding, errors) + elif format == PAX_FORMAT: + return self.create_pax_header(info, encoding) + else: + raise ValueError("invalid format") + + def create_ustar_header(self, info, encoding, errors): + """Return the object as a ustar header block. + """ + info["magic"] = POSIX_MAGIC + + if len(info["linkname"]) > LENGTH_LINK: + raise ValueError("linkname is too long") + + if len(info["name"]) > LENGTH_NAME: + info["prefix"], info["name"] = self._posix_split_name(info["name"]) + + return self._create_header(info, USTAR_FORMAT, encoding, errors) + + def create_gnu_header(self, info, encoding, errors): + """Return the object as a GNU header block sequence. + """ + info["magic"] = GNU_MAGIC + + buf = b"" + if len(info["linkname"]) > LENGTH_LINK: + buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) + + if len(info["name"]) > LENGTH_NAME: + buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) + + return buf + self._create_header(info, GNU_FORMAT, encoding, errors) + + def create_pax_header(self, info, encoding): + """Return the object as a ustar header block. If it cannot be + represented this way, prepend a pax extended header sequence + with supplement information. + """ + info["magic"] = POSIX_MAGIC + pax_headers = self.pax_headers.copy() + + # Test string fields for values that exceed the field length or cannot + # be represented in ASCII encoding. + for name, hname, length in ( + ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), + ("uname", "uname", 32), ("gname", "gname", 32)): + + if hname in pax_headers: + # The pax header has priority. + continue + + # Try to encode the string as ASCII. + try: + info[name].encode("ascii", "strict") + except UnicodeEncodeError: + pax_headers[hname] = info[name] + continue + + if len(info[name]) > length: + pax_headers[hname] = info[name] + + # Test number fields for values that exceed the field limit or values + # that like to be stored as float. + for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): + if name in pax_headers: + # The pax header has priority. Avoid overflow. + info[name] = 0 + continue + + val = info[name] + if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): + pax_headers[name] = str(val) + info[name] = 0 + + # Create a pax extended header if necessary. + if pax_headers: + buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) + else: + buf = b"" + + return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") + + @classmethod + def create_pax_global_header(cls, pax_headers): + """Return the object as a pax global header block sequence. + """ + return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf8") + + def _posix_split_name(self, name): + """Split a name longer than 100 chars into a prefix + and a name part. + """ + prefix = name[:LENGTH_PREFIX + 1] + while prefix and prefix[-1] != "/": + prefix = prefix[:-1] + + name = name[len(prefix):] + prefix = prefix[:-1] + + if not prefix or len(name) > LENGTH_NAME: + raise ValueError("name is too long") + return prefix, name + + @staticmethod + def _create_header(info, format, encoding, errors): + """Return a header block. info is a dictionary with file + information, format must be one of the *_FORMAT constants. + """ + parts = [ + stn(info.get("name", ""), 100, encoding, errors), + itn(info.get("mode", 0) & 0o7777, 8, format), + itn(info.get("uid", 0), 8, format), + itn(info.get("gid", 0), 8, format), + itn(info.get("size", 0), 12, format), + itn(info.get("mtime", 0), 12, format), + b" ", # checksum field + info.get("type", REGTYPE), + stn(info.get("linkname", ""), 100, encoding, errors), + info.get("magic", POSIX_MAGIC), + stn(info.get("uname", ""), 32, encoding, errors), + stn(info.get("gname", ""), 32, encoding, errors), + itn(info.get("devmajor", 0), 8, format), + itn(info.get("devminor", 0), 8, format), + stn(info.get("prefix", ""), 155, encoding, errors) + ] + + buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) + chksum = calc_chksums(buf[-BLOCKSIZE:])[0] + buf = buf[:-364] + ("%06o\0" % chksum).encode("ascii") + buf[-357:] + return buf + + @staticmethod + def _create_payload(payload): + """Return the string payload filled with zero bytes + up to the next 512 byte border. + """ + blocks, remainder = divmod(len(payload), BLOCKSIZE) + if remainder > 0: + payload += (BLOCKSIZE - remainder) * NUL + return payload + + @classmethod + def _create_gnu_long_header(cls, name, type, encoding, errors): + """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence + for name. + """ + name = name.encode(encoding, errors) + NUL + + info = {} + info["name"] = "././@LongLink" + info["type"] = type + info["size"] = len(name) + info["magic"] = GNU_MAGIC + + # create extended header + name blocks. + return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ + cls._create_payload(name) + + @classmethod + def _create_pax_generic_header(cls, pax_headers, type, encoding): + """Return a POSIX.1-2008 extended or global header sequence + that contains a list of keyword, value pairs. The values + must be strings. + """ + # Check if one of the fields contains surrogate characters and thereby + # forces hdrcharset=BINARY, see _proc_pax() for more information. + binary = False + for keyword, value in pax_headers.items(): + try: + value.encode("utf8", "strict") + except UnicodeEncodeError: + binary = True + break + + records = b"" + if binary: + # Put the hdrcharset field at the beginning of the header. + records += b"21 hdrcharset=BINARY\n" + + for keyword, value in pax_headers.items(): + keyword = keyword.encode("utf8") + if binary: + # Try to restore the original byte representation of `value'. + # Needless to say, that the encoding must match the string. + value = value.encode(encoding, "surrogateescape") + else: + value = value.encode("utf8") + + l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' + n = p = 0 + while True: + n = l + len(str(p)) + if n == p: + break + p = n + records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" + + # We use a hardcoded "././@PaxHeader" name like star does + # instead of the one that POSIX recommends. + info = {} + info["name"] = "././@PaxHeader" + info["type"] = type + info["size"] = len(records) + info["magic"] = POSIX_MAGIC + + # Create pax header + record blocks. + return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ + cls._create_payload(records) + + @classmethod + def frombuf(cls, buf, encoding, errors): + """Construct a TarInfo object from a 512 byte bytes object. + """ + if len(buf) == 0: + raise EmptyHeaderError("empty header") + if len(buf) != BLOCKSIZE: + raise TruncatedHeaderError("truncated header") + if buf.count(NUL) == BLOCKSIZE: + raise EOFHeaderError("end of file header") + + chksum = nti(buf[148:156]) + if chksum not in calc_chksums(buf): + raise InvalidHeaderError("bad checksum") + + obj = cls() + obj.name = nts(buf[0:100], encoding, errors) + obj.mode = nti(buf[100:108]) + obj.uid = nti(buf[108:116]) + obj.gid = nti(buf[116:124]) + obj.size = nti(buf[124:136]) + obj.mtime = nti(buf[136:148]) + obj.chksum = chksum + obj.type = buf[156:157] + obj.linkname = nts(buf[157:257], encoding, errors) + obj.uname = nts(buf[265:297], encoding, errors) + obj.gname = nts(buf[297:329], encoding, errors) + obj.devmajor = nti(buf[329:337]) + obj.devminor = nti(buf[337:345]) + prefix = nts(buf[345:500], encoding, errors) + + # Old V7 tar format represents a directory as a regular + # file with a trailing slash. + if obj.type == AREGTYPE and obj.name.endswith("/"): + obj.type = DIRTYPE + + # The old GNU sparse format occupies some of the unused + # space in the buffer for up to 4 sparse structures. + # Save the them for later processing in _proc_sparse(). + if obj.type == GNUTYPE_SPARSE: + pos = 386 + structs = [] + for i in range(4): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[482]) + origsize = nti(buf[483:495]) + obj._sparse_structs = (structs, isextended, origsize) + + # Remove redundant slashes from directories. + if obj.isdir(): + obj.name = obj.name.rstrip("/") + + # Reconstruct a ustar longname. + if prefix and obj.type not in GNU_TYPES: + obj.name = prefix + "/" + obj.name + return obj + + @classmethod + def fromtarfile(cls, tarfile): + """Return the next TarInfo object from TarFile object + tarfile. + """ + buf = tarfile.fileobj.read(BLOCKSIZE) + obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) + obj.offset = tarfile.fileobj.tell() - BLOCKSIZE + return obj._proc_member(tarfile) + + #-------------------------------------------------------------------------- + # The following are methods that are called depending on the type of a + # member. The entry point is _proc_member() which can be overridden in a + # subclass to add custom _proc_*() methods. A _proc_*() method MUST + # implement the following + # operations: + # 1. Set self.offset_data to the position where the data blocks begin, + # if there is data that follows. + # 2. Set tarfile.offset to the position where the next member's header will + # begin. + # 3. Return self or another valid TarInfo object. + def _proc_member(self, tarfile): + """Choose the right processing method depending on + the type and call it. + """ + if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): + return self._proc_gnulong(tarfile) + elif self.type == GNUTYPE_SPARSE: + return self._proc_sparse(tarfile) + elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): + return self._proc_pax(tarfile) + else: + return self._proc_builtin(tarfile) + + def _proc_builtin(self, tarfile): + """Process a builtin type or an unknown type which + will be treated as a regular file. + """ + self.offset_data = tarfile.fileobj.tell() + offset = self.offset_data + if self.isreg() or self.type not in SUPPORTED_TYPES: + # Skip the following data blocks. + offset += self._block(self.size) + tarfile.offset = offset + + # Patch the TarInfo object with saved global + # header information. + self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) + + return self + + def _proc_gnulong(self, tarfile): + """Process the blocks that hold a GNU longname + or longlink member. + """ + buf = tarfile.fileobj.read(self._block(self.size)) + + # Fetch the next header and process it. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Patch the TarInfo object from the next header with + # the longname information. + next.offset = self.offset + if self.type == GNUTYPE_LONGNAME: + next.name = nts(buf, tarfile.encoding, tarfile.errors) + elif self.type == GNUTYPE_LONGLINK: + next.linkname = nts(buf, tarfile.encoding, tarfile.errors) + + return next + + def _proc_sparse(self, tarfile): + """Process a GNU sparse header plus extra headers. + """ + # We already collected some sparse structures in frombuf(). + structs, isextended, origsize = self._sparse_structs + del self._sparse_structs + + # Collect sparse structures from extended header blocks. + while isextended: + buf = tarfile.fileobj.read(BLOCKSIZE) + pos = 0 + for i in range(21): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + if offset and numbytes: + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[504]) + self.sparse = structs + + self.offset_data = tarfile.fileobj.tell() + tarfile.offset = self.offset_data + self._block(self.size) + self.size = origsize + return self + + def _proc_pax(self, tarfile): + """Process an extended or global header as described in + POSIX.1-2008. + """ + # Read the header information. + buf = tarfile.fileobj.read(self._block(self.size)) + + # A pax header stores supplemental information for either + # the following file (extended) or all following files + # (global). + if self.type == XGLTYPE: + pax_headers = tarfile.pax_headers + else: + pax_headers = tarfile.pax_headers.copy() + + # Check if the pax header contains a hdrcharset field. This tells us + # the encoding of the path, linkpath, uname and gname fields. Normally, + # these fields are UTF-8 encoded but since POSIX.1-2008 tar + # implementations are allowed to store them as raw binary strings if + # the translation to UTF-8 fails. + match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) + if match is not None: + pax_headers["hdrcharset"] = match.group(1).decode("utf8") + + # For the time being, we don't care about anything other than "BINARY". + # The only other value that is currently allowed by the standard is + # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. + hdrcharset = pax_headers.get("hdrcharset") + if hdrcharset == "BINARY": + encoding = tarfile.encoding + else: + encoding = "utf8" + + # Parse pax header information. A record looks like that: + # "%d %s=%s\n" % (length, keyword, value). length is the size + # of the complete record including the length field itself and + # the newline. keyword and value are both UTF-8 encoded strings. + regex = re.compile(br"(\d+) ([^=]+)=") + pos = 0 + while True: + match = regex.match(buf, pos) + if not match: + break + + length, keyword = match.groups() + length = int(length) + value = buf[match.end(2) + 1:match.start(1) + length - 1] + + # Normally, we could just use "utf8" as the encoding and "strict" + # as the error handler, but we better not take the risk. For + # example, GNU tar <= 1.23 is known to store filenames it cannot + # translate to UTF-8 as raw strings (unfortunately without a + # hdrcharset=BINARY header). + # We first try the strict standard encoding, and if that fails we + # fall back on the user's encoding and error handler. + keyword = self._decode_pax_field(keyword, "utf8", "utf8", + tarfile.errors) + if keyword in PAX_NAME_FIELDS: + value = self._decode_pax_field(value, encoding, tarfile.encoding, + tarfile.errors) + else: + value = self._decode_pax_field(value, "utf8", "utf8", + tarfile.errors) + + pax_headers[keyword] = value + pos += length + + # Fetch the next header. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Process GNU sparse information. + if "GNU.sparse.map" in pax_headers: + # GNU extended sparse format version 0.1. + self._proc_gnusparse_01(next, pax_headers) + + elif "GNU.sparse.size" in pax_headers: + # GNU extended sparse format version 0.0. + self._proc_gnusparse_00(next, pax_headers, buf) + + elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": + # GNU extended sparse format version 1.0. + self._proc_gnusparse_10(next, pax_headers, tarfile) + + if self.type in (XHDTYPE, SOLARIS_XHDTYPE): + # Patch the TarInfo object with the extended header info. + next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) + next.offset = self.offset + + if "size" in pax_headers: + # If the extended header replaces the size field, + # we need to recalculate the offset where the next + # header starts. + offset = next.offset_data + if next.isreg() or next.type not in SUPPORTED_TYPES: + offset += next._block(next.size) + tarfile.offset = offset + + return next + + def _proc_gnusparse_00(self, next, pax_headers, buf): + """Process a GNU tar extended sparse header, version 0.0. + """ + offsets = [] + for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): + offsets.append(int(match.group(1))) + numbytes = [] + for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): + numbytes.append(int(match.group(1))) + next.sparse = list(zip(offsets, numbytes)) + + def _proc_gnusparse_01(self, next, pax_headers): + """Process a GNU tar extended sparse header, version 0.1. + """ + sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _proc_gnusparse_10(self, next, pax_headers, tarfile): + """Process a GNU tar extended sparse header, version 1.0. + """ + fields = None + sparse = [] + buf = tarfile.fileobj.read(BLOCKSIZE) + fields, buf = buf.split(b"\n", 1) + fields = int(fields) + while len(sparse) < fields * 2: + if b"\n" not in buf: + buf += tarfile.fileobj.read(BLOCKSIZE) + number, buf = buf.split(b"\n", 1) + sparse.append(int(number)) + next.offset_data = tarfile.fileobj.tell() + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _apply_pax_info(self, pax_headers, encoding, errors): + """Replace fields with supplemental information from a previous + pax extended or global header. + """ + for keyword, value in pax_headers.items(): + if keyword == "GNU.sparse.name": + setattr(self, "path", value) + elif keyword == "GNU.sparse.size": + setattr(self, "size", int(value)) + elif keyword == "GNU.sparse.realsize": + setattr(self, "size", int(value)) + elif keyword in PAX_FIELDS: + if keyword in PAX_NUMBER_FIELDS: + try: + value = PAX_NUMBER_FIELDS[keyword](value) + except ValueError: + value = 0 + if keyword == "path": + value = value.rstrip("/") + setattr(self, keyword, value) + + self.pax_headers = pax_headers.copy() + + def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): + """Decode a single field from a pax record. + """ + try: + return value.decode(encoding, "strict") + except UnicodeDecodeError: + return value.decode(fallback_encoding, fallback_errors) + + def _block(self, count): + """Round up a byte count by BLOCKSIZE and return it, + e.g. _block(834) => 1024. + """ + blocks, remainder = divmod(count, BLOCKSIZE) + if remainder: + blocks += 1 + return blocks * BLOCKSIZE + + def isreg(self): + return self.type in REGULAR_TYPES + def isfile(self): + return self.isreg() + def isdir(self): + return self.type == DIRTYPE + def issym(self): + return self.type == SYMTYPE + def islnk(self): + return self.type == LNKTYPE + def ischr(self): + return self.type == CHRTYPE + def isblk(self): + return self.type == BLKTYPE + def isfifo(self): + return self.type == FIFOTYPE + def issparse(self): + return self.sparse is not None + def isdev(self): + return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) +# class TarInfo + +class TarFile(object): + """The TarFile Class provides an interface to tar archives. + """ + + debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) + + dereference = False # If true, add content of linked file to the + # tar file, else the link. + + ignore_zeros = False # If true, skips empty or invalid blocks and + # continues processing. + + errorlevel = 1 # If 0, fatal errors only appear in debug + # messages (if debug >= 0). If > 0, errors + # are passed to the caller as exceptions. + + format = DEFAULT_FORMAT # The format to use when creating an archive. + + encoding = ENCODING # Encoding for 8-bit character strings. + + errors = None # Error handler for unicode conversion. + + tarinfo = TarInfo # The default TarInfo class to use. + + fileobject = ExFileObject # The default ExFileObject class to use. + + def __init__(self, name=None, mode="r", fileobj=None, format=None, + tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, + errors="surrogateescape", pax_headers=None, debug=None, errorlevel=None): + """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to + read from an existing archive, 'a' to append data to an existing + file or 'w' to create a new file overwriting an existing one. `mode' + defaults to 'r'. + If `fileobj' is given, it is used for reading or writing data. If it + can be determined, `mode' is overridden by `fileobj's mode. + `fileobj' is not closed, when TarFile is closed. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + self.mode = mode + self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] + + if not fileobj: + if self.mode == "a" and not os.path.exists(name): + # Create nonexistent files in append mode. + self.mode = "w" + self._mode = "wb" + fileobj = bltn_open(name, self._mode) + self._extfileobj = False + else: + if name is None and hasattr(fileobj, "name"): + name = fileobj.name + if hasattr(fileobj, "mode"): + self._mode = fileobj.mode + self._extfileobj = True + self.name = os.path.abspath(name) if name else None + self.fileobj = fileobj + + # Init attributes. + if format is not None: + self.format = format + if tarinfo is not None: + self.tarinfo = tarinfo + if dereference is not None: + self.dereference = dereference + if ignore_zeros is not None: + self.ignore_zeros = ignore_zeros + if encoding is not None: + self.encoding = encoding + self.errors = errors + + if pax_headers is not None and self.format == PAX_FORMAT: + self.pax_headers = pax_headers + else: + self.pax_headers = {} + + if debug is not None: + self.debug = debug + if errorlevel is not None: + self.errorlevel = errorlevel + + # Init datastructures. + self.closed = False + self.members = [] # list of members as TarInfo objects + self._loaded = False # flag if all members have been read + self.offset = self.fileobj.tell() + # current position in the archive file + self.inodes = {} # dictionary caching the inodes of + # archive members already added + + try: + if self.mode == "r": + self.firstmember = None + self.firstmember = self.next() + + if self.mode == "a": + # Move to the end of the archive, + # before the first empty block. + while True: + self.fileobj.seek(self.offset) + try: + tarinfo = self.tarinfo.fromtarfile(self) + self.members.append(tarinfo) + except EOFHeaderError: + self.fileobj.seek(self.offset) + break + except HeaderError as e: + raise ReadError(str(e)) + + if self.mode in "aw": + self._loaded = True + + if self.pax_headers: + buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) + self.fileobj.write(buf) + self.offset += len(buf) + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + #-------------------------------------------------------------------------- + # Below are the classmethods which act as alternate constructors to the + # TarFile class. The open() method is the only one that is needed for + # public use; it is the "super"-constructor and is able to select an + # adequate "sub"-constructor for a particular compression using the mapping + # from OPEN_METH. + # + # This concept allows one to subclass TarFile without losing the comfort of + # the super-constructor. A sub-constructor is registered and made available + # by adding it to the mapping in OPEN_METH. + + @classmethod + def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): + """Open a tar archive for reading, writing or appending. Return + an appropriate TarFile class. + + mode: + 'r' or 'r:*' open for reading with transparent compression + 'r:' open for reading exclusively uncompressed + 'r:gz' open for reading with gzip compression + 'r:bz2' open for reading with bzip2 compression + 'a' or 'a:' open for appending, creating the file if necessary + 'w' or 'w:' open for writing without compression + 'w:gz' open for writing with gzip compression + 'w:bz2' open for writing with bzip2 compression + + 'r|*' open a stream of tar blocks with transparent compression + 'r|' open an uncompressed stream of tar blocks for reading + 'r|gz' open a gzip compressed stream of tar blocks + 'r|bz2' open a bzip2 compressed stream of tar blocks + 'w|' open an uncompressed stream for writing + 'w|gz' open a gzip compressed stream for writing + 'w|bz2' open a bzip2 compressed stream for writing + """ + + if not name and not fileobj: + raise ValueError("nothing to open") + + if mode in ("r", "r:*"): + # Find out which *open() is appropriate for opening the file. + for comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + if fileobj is not None: + saved_pos = fileobj.tell() + try: + return func(name, "r", fileobj, **kwargs) + except (ReadError, CompressionError) as e: + if fileobj is not None: + fileobj.seek(saved_pos) + continue + raise ReadError("file could not be opened successfully") + + elif ":" in mode: + filemode, comptype = mode.split(":", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + # Select the *open() function according to + # given compression. + if comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + else: + raise CompressionError("unknown compression type %r" % comptype) + return func(name, filemode, fileobj, **kwargs) + + elif "|" in mode: + filemode, comptype = mode.split("|", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + if filemode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + stream = _Stream(name, filemode, comptype, fileobj, bufsize) + try: + t = cls(name, filemode, stream, **kwargs) + except: + stream.close() + raise + t._extfileobj = False + return t + + elif mode in "aw": + return cls.taropen(name, mode, fileobj, **kwargs) + + raise ValueError("undiscernible mode") + + @classmethod + def taropen(cls, name, mode="r", fileobj=None, **kwargs): + """Open uncompressed tar archive name for reading or writing. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + return cls(name, mode, fileobj, **kwargs) + + @classmethod + def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open gzip compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + try: + import gzip + gzip.GzipFile + except (ImportError, AttributeError): + raise CompressionError("gzip module is not available") + + extfileobj = fileobj is not None + try: + fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + t = cls.taropen(name, mode, fileobj, **kwargs) + except IOError: + if not extfileobj and fileobj is not None: + fileobj.close() + if fileobj is None: + raise + raise ReadError("not a gzip file") + except: + if not extfileobj and fileobj is not None: + fileobj.close() + raise + t._extfileobj = extfileobj + return t + + @classmethod + def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open bzip2 compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'.") + + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + + if fileobj is not None: + fileobj = _BZ2Proxy(fileobj, mode) + else: + fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except (IOError, EOFError): + fileobj.close() + raise ReadError("not a bzip2 file") + t._extfileobj = False + return t + + # All *open() methods are registered here. + OPEN_METH = { + "tar": "taropen", # uncompressed tar + "gz": "gzopen", # gzip compressed tar + "bz2": "bz2open" # bzip2 compressed tar + } + + #-------------------------------------------------------------------------- + # The public methods which TarFile provides: + + def close(self): + """Close the TarFile. In write-mode, two finishing zero blocks are + appended to the archive. + """ + if self.closed: + return + + if self.mode in "aw": + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + + if not self._extfileobj: + self.fileobj.close() + self.closed = True + + def getmember(self, name): + """Return a TarInfo object for member `name'. If `name' can not be + found in the archive, KeyError is raised. If a member occurs more + than once in the archive, its last occurrence is assumed to be the + most up-to-date version. + """ + tarinfo = self._getmember(name) + if tarinfo is None: + raise KeyError("filename %r not found" % name) + return tarinfo + + def getmembers(self): + """Return the members of the archive as a list of TarInfo objects. The + list has the same order as the members in the archive. + """ + self._check() + if not self._loaded: # if we want to obtain a list of + self._load() # all members, we first have to + # scan the whole archive. + return self.members + + def getnames(self): + """Return the members of the archive as a list of their names. It has + the same order as the list returned by getmembers(). + """ + return [tarinfo.name for tarinfo in self.getmembers()] + + def gettarinfo(self, name=None, arcname=None, fileobj=None): + """Create a TarInfo object for either the file `name' or the file + object `fileobj' (using os.fstat on its file descriptor). You can + modify some of the TarInfo's attributes before you add it using + addfile(). If given, `arcname' specifies an alternative name for the + file in the archive. + """ + self._check("aw") + + # When fileobj is given, replace name by + # fileobj's real name. + if fileobj is not None: + name = fileobj.name + + # Building the name of the member in the archive. + # Backward slashes are converted to forward slashes, + # Absolute paths are turned to relative paths. + if arcname is None: + arcname = name + drv, arcname = os.path.splitdrive(arcname) + arcname = arcname.replace(os.sep, "/") + arcname = arcname.lstrip("/") + + # Now, fill the TarInfo object with + # information specific for the file. + tarinfo = self.tarinfo() + tarinfo.tarfile = self + + # Use os.stat or os.lstat, depending on platform + # and if symlinks shall be resolved. + if fileobj is None: + if hasattr(os, "lstat") and not self.dereference: + statres = os.lstat(name) + else: + statres = os.stat(name) + else: + statres = os.fstat(fileobj.fileno()) + linkname = "" + + stmd = statres.st_mode + if stat.S_ISREG(stmd): + inode = (statres.st_ino, statres.st_dev) + if not self.dereference and statres.st_nlink > 1 and \ + inode in self.inodes and arcname != self.inodes[inode]: + # Is it a hardlink to an already + # archived file? + type = LNKTYPE + linkname = self.inodes[inode] + else: + # The inode is added only if its valid. + # For win32 it is always 0. + type = REGTYPE + if inode[0]: + self.inodes[inode] = arcname + elif stat.S_ISDIR(stmd): + type = DIRTYPE + elif stat.S_ISFIFO(stmd): + type = FIFOTYPE + elif stat.S_ISLNK(stmd): + type = SYMTYPE + linkname = os.readlink(name) + elif stat.S_ISCHR(stmd): + type = CHRTYPE + elif stat.S_ISBLK(stmd): + type = BLKTYPE + else: + return None + + # Fill the TarInfo object with all + # information we can get. + tarinfo.name = arcname + tarinfo.mode = stmd + tarinfo.uid = statres.st_uid + tarinfo.gid = statres.st_gid + if type == REGTYPE: + tarinfo.size = statres.st_size + else: + tarinfo.size = 0 + tarinfo.mtime = statres.st_mtime + tarinfo.type = type + tarinfo.linkname = linkname + if pwd: + try: + tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] + except KeyError: + pass + if grp: + try: + tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] + except KeyError: + pass + + if type in (CHRTYPE, BLKTYPE): + if hasattr(os, "major") and hasattr(os, "minor"): + tarinfo.devmajor = os.major(statres.st_rdev) + tarinfo.devminor = os.minor(statres.st_rdev) + return tarinfo + + def list(self, verbose=True): + """Print a table of contents to sys.stdout. If `verbose' is False, only + the names of the members are printed. If it is True, an `ls -l'-like + output is produced. + """ + self._check() + + for tarinfo in self: + if verbose: + print(filemode(tarinfo.mode), end=' ') + print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid), end=' ') + if tarinfo.ischr() or tarinfo.isblk(): + print("%10s" % ("%d,%d" \ + % (tarinfo.devmajor, tarinfo.devminor)), end=' ') + else: + print("%10d" % tarinfo.size, end=' ') + print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6], end=' ') + + print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + + if verbose: + if tarinfo.issym(): + print("->", tarinfo.linkname, end=' ') + if tarinfo.islnk(): + print("link to", tarinfo.linkname, end=' ') + print() + + def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): + """Add the file `name' to the archive. `name' may be any type of file + (directory, fifo, symbolic link, etc.). If given, `arcname' + specifies an alternative name for the file in the archive. + Directories are added recursively by default. This can be avoided by + setting `recursive' to False. `exclude' is a function that should + return True for each filename to be excluded. `filter' is a function + that expects a TarInfo object argument and returns the changed + TarInfo object, if it returns None the TarInfo object will be + excluded from the archive. + """ + self._check("aw") + + if arcname is None: + arcname = name + + # Exclude pathnames. + if exclude is not None: + import warnings + warnings.warn("use the filter argument instead", + DeprecationWarning, 2) + if exclude(name): + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Skip if somebody tries to archive the archive... + if self.name is not None and os.path.abspath(name) == self.name: + self._dbg(2, "tarfile: Skipped %r" % name) + return + + self._dbg(1, name) + + # Create a TarInfo object from the file. + tarinfo = self.gettarinfo(name, arcname) + + if tarinfo is None: + self._dbg(1, "tarfile: Unsupported type %r" % name) + return + + # Change or exclude the TarInfo object. + if filter is not None: + tarinfo = filter(tarinfo) + if tarinfo is None: + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Append the tar header and data to the archive. + if tarinfo.isreg(): + f = bltn_open(name, "rb") + self.addfile(tarinfo, f) + f.close() + + elif tarinfo.isdir(): + self.addfile(tarinfo) + if recursive: + for f in os.listdir(name): + self.add(os.path.join(name, f), os.path.join(arcname, f), + recursive, exclude, filter=filter) + + else: + self.addfile(tarinfo) + + def addfile(self, tarinfo, fileobj=None): + """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is + given, tarinfo.size bytes are read from it and added to the archive. + You can create TarInfo objects using gettarinfo(). + On Windows platforms, `fileobj' should always be opened with mode + 'rb' to avoid irritation about the file size. + """ + self._check("aw") + + tarinfo = copy.copy(tarinfo) + + buf = tarinfo.tobuf(self.format, self.encoding, self.errors) + self.fileobj.write(buf) + self.offset += len(buf) + + # If there's data to follow, append it. + if fileobj is not None: + copyfileobj(fileobj, self.fileobj, tarinfo.size) + blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) + if remainder > 0: + self.fileobj.write(NUL * (BLOCKSIZE - remainder)) + blocks += 1 + self.offset += blocks * BLOCKSIZE + + self.members.append(tarinfo) + + def extractall(self, path=".", members=None): + """Extract all members from the archive to the current working + directory and set owner, modification time and permissions on + directories afterwards. `path' specifies a different directory + to extract to. `members' is optional and must be a subset of the + list returned by getmembers(). + """ + directories = [] + + if members is None: + members = self + + for tarinfo in members: + if tarinfo.isdir(): + # Extract directories with a safe mode. + directories.append(tarinfo) + tarinfo = copy.copy(tarinfo) + tarinfo.mode = 0o700 + # Do not set_attrs directories, as we will do that further down + self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) + + # Reverse sort directories. + directories.sort(key=lambda a: a.name) + directories.reverse() + + # Set correct owner, mtime and filemode on directories. + for tarinfo in directories: + dirpath = os.path.join(path, tarinfo.name) + try: + self.chown(tarinfo, dirpath) + self.utime(tarinfo, dirpath) + self.chmod(tarinfo, dirpath) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extract(self, member, path="", set_attrs=True): + """Extract a member from the archive to the current working directory, + using its full name. Its file information is extracted as accurately + as possible. `member' may be a filename or a TarInfo object. You can + specify a different directory using `path'. File attributes (owner, + mtime, mode) are set unless `set_attrs' is False. + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + # Prepare the link target for makelink(). + if tarinfo.islnk(): + tarinfo._link_target = os.path.join(path, tarinfo.linkname) + + try: + self._extract_member(tarinfo, os.path.join(path, tarinfo.name), + set_attrs=set_attrs) + except EnvironmentError as e: + if self.errorlevel > 0: + raise + else: + if e.filename is None: + self._dbg(1, "tarfile: %s" % e.strerror) + else: + self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extractfile(self, member): + """Extract a member from the archive as a file object. `member' may be + a filename or a TarInfo object. If `member' is a regular file, a + file-like object is returned. If `member' is a link, a file-like + object is constructed from the link's target. If `member' is none of + the above, None is returned. + The file-like object is read-only and provides the following + methods: read(), readline(), readlines(), seek() and tell() + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + if tarinfo.isreg(): + return self.fileobject(self, tarinfo) + + elif tarinfo.type not in SUPPORTED_TYPES: + # If a member's type is unknown, it is treated as a + # regular file. + return self.fileobject(self, tarinfo) + + elif tarinfo.islnk() or tarinfo.issym(): + if isinstance(self.fileobj, _Stream): + # A small but ugly workaround for the case that someone tries + # to extract a (sym)link as a file-object from a non-seekable + # stream of tar blocks. + raise StreamError("cannot extract (sym)link as file object") + else: + # A (sym)link's file object is its target's file object. + return self.extractfile(self._find_link_target(tarinfo)) + else: + # If there's no data associated with the member (directory, chrdev, + # blkdev, etc.), return None instead of a file object. + return None + + def _extract_member(self, tarinfo, targetpath, set_attrs=True): + """Extract the TarInfo object tarinfo to a physical + file called targetpath. + """ + # Fetch the TarInfo object for the given name + # and build the destination pathname, replacing + # forward slashes to platform specific separators. + targetpath = targetpath.rstrip("/") + targetpath = targetpath.replace("/", os.sep) + + # Create all upper directories. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + # Create directories that are not part of the archive with + # default permissions. + os.makedirs(upperdirs) + + if tarinfo.islnk() or tarinfo.issym(): + self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) + else: + self._dbg(1, tarinfo.name) + + if tarinfo.isreg(): + self.makefile(tarinfo, targetpath) + elif tarinfo.isdir(): + self.makedir(tarinfo, targetpath) + elif tarinfo.isfifo(): + self.makefifo(tarinfo, targetpath) + elif tarinfo.ischr() or tarinfo.isblk(): + self.makedev(tarinfo, targetpath) + elif tarinfo.islnk() or tarinfo.issym(): + self.makelink(tarinfo, targetpath) + elif tarinfo.type not in SUPPORTED_TYPES: + self.makeunknown(tarinfo, targetpath) + else: + self.makefile(tarinfo, targetpath) + + if set_attrs: + self.chown(tarinfo, targetpath) + if not tarinfo.issym(): + self.chmod(tarinfo, targetpath) + self.utime(tarinfo, targetpath) + + #-------------------------------------------------------------------------- + # Below are the different file methods. They are called via + # _extract_member() when extract() is called. They can be replaced in a + # subclass to implement other functionality. + + def makedir(self, tarinfo, targetpath): + """Make a directory called targetpath. + """ + try: + # Use a safe mode for the directory, the real mode is set + # later in _extract_member(). + os.mkdir(targetpath, 0o700) + except EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + + def makefile(self, tarinfo, targetpath): + """Make a file called targetpath. + """ + source = self.fileobj + source.seek(tarinfo.offset_data) + target = bltn_open(targetpath, "wb") + if tarinfo.sparse is not None: + for offset, size in tarinfo.sparse: + target.seek(offset) + copyfileobj(source, target, size) + else: + copyfileobj(source, target, tarinfo.size) + target.seek(tarinfo.size) + target.truncate() + target.close() + + def makeunknown(self, tarinfo, targetpath): + """Make a file from a TarInfo object with an unknown type + at targetpath. + """ + self.makefile(tarinfo, targetpath) + self._dbg(1, "tarfile: Unknown file type %r, " \ + "extracted as regular file." % tarinfo.type) + + def makefifo(self, tarinfo, targetpath): + """Make a fifo called targetpath. + """ + if hasattr(os, "mkfifo"): + os.mkfifo(targetpath) + else: + raise ExtractError("fifo not supported by system") + + def makedev(self, tarinfo, targetpath): + """Make a character or block device called targetpath. + """ + if not hasattr(os, "mknod") or not hasattr(os, "makedev"): + raise ExtractError("special devices not supported by system") + + mode = tarinfo.mode + if tarinfo.isblk(): + mode |= stat.S_IFBLK + else: + mode |= stat.S_IFCHR + + os.mknod(targetpath, mode, + os.makedev(tarinfo.devmajor, tarinfo.devminor)) + + def makelink(self, tarinfo, targetpath): + """Make a (symbolic) link called targetpath. If it cannot be created + (platform limitation), we try to make a copy of the referenced file + instead of a link. + """ + try: + # For systems that support symbolic and hard links. + if tarinfo.issym(): + os.symlink(tarinfo.linkname, targetpath) + else: + # See extract(). + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except symlink_exception: + if tarinfo.issym(): + linkpath = os.path.join(os.path.dirname(tarinfo.name), + tarinfo.linkname) + else: + linkpath = tarinfo.linkname + else: + try: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") + + def chown(self, tarinfo, targetpath): + """Set owner of targetpath according to tarinfo. + """ + if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: + # We have to be root to do so. + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid + try: + if tarinfo.issym() and hasattr(os, "lchown"): + os.lchown(targetpath, u, g) + else: + if sys.platform != "os2emx": + os.chown(targetpath, u, g) + except EnvironmentError as e: + raise ExtractError("could not change owner") + + def chmod(self, tarinfo, targetpath): + """Set file permissions of targetpath according to tarinfo. + """ + if hasattr(os, 'chmod'): + try: + os.chmod(targetpath, tarinfo.mode) + except EnvironmentError as e: + raise ExtractError("could not change mode") + + def utime(self, tarinfo, targetpath): + """Set modification time of targetpath according to tarinfo. + """ + if not hasattr(os, 'utime'): + return + try: + os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) + except EnvironmentError as e: + raise ExtractError("could not change modification time") + + #-------------------------------------------------------------------------- + def next(self): + """Return the next member of the archive as a TarInfo object, when + TarFile is opened for reading. Return None if there is no more + available. + """ + self._check("ra") + if self.firstmember is not None: + m = self.firstmember + self.firstmember = None + return m + + # Read the next block. + self.fileobj.seek(self.offset) + tarinfo = None + while True: + try: + tarinfo = self.tarinfo.fromtarfile(self) + except EOFHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + except InvalidHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + elif self.offset == 0: + raise ReadError(str(e)) + except EmptyHeaderError: + if self.offset == 0: + raise ReadError("empty file") + except TruncatedHeaderError as e: + if self.offset == 0: + raise ReadError(str(e)) + except SubsequentHeaderError as e: + raise ReadError(str(e)) + break + + if tarinfo is not None: + self.members.append(tarinfo) + else: + self._loaded = True + + return tarinfo + + #-------------------------------------------------------------------------- + # Little helper methods: + + def _getmember(self, name, tarinfo=None, normalize=False): + """Find an archive member by name from bottom to top. + If tarinfo is given, it is used as the starting point. + """ + # Ensure that all members have been loaded. + members = self.getmembers() + + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] + + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member + + def _load(self): + """Read through the entire archive file and look for readable + members. + """ + while True: + tarinfo = self.next() + if tarinfo is None: + break + self._loaded = True + + def _check(self, mode=None): + """Check if TarFile is still open, and if the operation's mode + corresponds to TarFile's mode. + """ + if self.closed: + raise IOError("%s is closed" % self.__class__.__name__) + if mode is not None and self.mode not in mode: + raise IOError("bad operation for mode %r" % self.mode) + + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + + def __iter__(self): + """Provide an iterator object. + """ + if self._loaded: + return iter(self.members) + else: + return TarIter(self) + + def _dbg(self, level, msg): + """Write debugging output to sys.stderr. + """ + if level <= self.debug: + print(msg, file=sys.stderr) + + def __enter__(self): + self._check() + return self + + def __exit__(self, type, value, traceback): + if type is None: + self.close() + else: + # An exception occurred. We must not call close() because + # it would try to write end-of-archive blocks and padding. + if not self._extfileobj: + self.fileobj.close() + self.closed = True +# class TarFile + +class TarIter(object): + """Iterator Class. + + for tarinfo in TarFile(...): + suite... + """ + + def __init__(self, tarfile): + """Construct a TarIter object. + """ + self.tarfile = tarfile + self.index = 0 + def __iter__(self): + """Return iterator object. + """ + return self + + def __next__(self): + """Return the next item using TarFile's next() method. + When all members have been read, set TarFile as _loaded. + """ + # Fix for SF #1100429: Under rare circumstances it can + # happen that getmembers() is called during iteration, + # which will cause TarIter to stop prematurely. + if not self.tarfile._loaded: + tarinfo = self.tarfile.next() + if not tarinfo: + self.tarfile._loaded = True + raise StopIteration + else: + try: + tarinfo = self.tarfile.members[self.index] + except IndexError: + raise StopIteration + self.index += 1 + return tarinfo + + next = __next__ # for Python 2.x + +#-------------------- +# exported functions +#-------------------- +def is_tarfile(name): + """Return True if name points to a tar archive that we + are able to handle, else return False. + """ + try: + t = open(name) + t.close() + return True + except TarError: + return False + +bltn_open = open +open = TarFile.open diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/compat.py new file mode 100644 index 0000000..ff328c8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/compat.py @@ -0,0 +1,1120 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import absolute_import + +import os +import re +import sys + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + +if sys.version_info[0] < 3: # pragma: no cover + from StringIO import StringIO + string_types = basestring, + text_type = unicode + from types import FileType as file_type + import __builtin__ as builtins + import ConfigParser as configparser + from ._backport import shutil + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit + from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, + pathname2url, ContentTooShortError, splittype) + + def quote(s): + if isinstance(s, unicode): + s = s.encode('utf-8') + return _quote(s) + + import urllib2 + from urllib2 import (Request, urlopen, URLError, HTTPError, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib2 import HTTPSHandler + import httplib + import xmlrpclib + import Queue as queue + from HTMLParser import HTMLParser + import htmlentitydefs + raw_input = raw_input + from itertools import ifilter as filter + from itertools import ifilterfalse as filterfalse + + _userprog = None + def splituser(host): + """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + global _userprog + if _userprog is None: + import re + _userprog = re.compile('^(.*)@(.*)$') + + match = _userprog.match(host) + if match: return match.group(1, 2) + return None, host + +else: # pragma: no cover + from io import StringIO + string_types = str, + text_type = str + from io import TextIOWrapper as file_type + import builtins + import configparser + import shutil + from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, + unquote, urlsplit, urlunsplit, splittype) + from urllib.request import (urlopen, urlretrieve, Request, url2pathname, + pathname2url, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib.request import HTTPSHandler + from urllib.error import HTTPError, URLError, ContentTooShortError + import http.client as httplib + import urllib.request as urllib2 + import xmlrpc.client as xmlrpclib + import queue + from html.parser import HTMLParser + import html.entities as htmlentitydefs + raw_input = input + from itertools import filterfalse + filter = filter + +try: + from ssl import match_hostname, CertificateError +except ImportError: # pragma: no cover + class CertificateError(ValueError): + pass + + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + parts = dn.split('.') + leftmost, remainder = parts[0], parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +try: + from types import SimpleNamespace as Container +except ImportError: # pragma: no cover + class Container(object): + """ + A generic container for when multiple values need to be returned + """ + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +try: + from shutil import which +except ImportError: # pragma: no cover + # Implementation from Python 3.3 + def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if not os.curdir in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None + + +# ZipFile is a context manager in 2.7, but not in 2.6 + +from zipfile import ZipFile as BaseZipFile + +if hasattr(BaseZipFile, '__enter__'): # pragma: no cover + ZipFile = BaseZipFile +else: # pragma: no cover + from zipfile import ZipExtFile as BaseZipExtFile + + class ZipExtFile(BaseZipExtFile): + def __init__(self, base): + self.__dict__.update(base.__dict__) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + class ZipFile(BaseZipFile): + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + def open(self, *args, **kwargs): + base = BaseZipFile.open(self, *args, **kwargs) + return ZipExtFile(base) + +try: + from platform import python_implementation +except ImportError: # pragma: no cover + def python_implementation(): + """Return a string identifying the Python implementation.""" + if 'PyPy' in sys.version: + return 'PyPy' + if os.name == 'java': + return 'Jython' + if sys.version.startswith('IronPython'): + return 'IronPython' + return 'CPython' + +try: + import sysconfig +except ImportError: # pragma: no cover + from ._backport import sysconfig + +try: + callable = callable +except NameError: # pragma: no cover + from collections import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode + fsdecode = os.fsdecode +except AttributeError: # pragma: no cover + # Issue #99: on some systems (e.g. containerised), + # sys.getfilesystemencoding() returns None, and we need a real value, + # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and + # sys.getfilesystemencoding(): the return value is "the user’s preference + # according to the result of nl_langinfo(CODESET), or None if the + # nl_langinfo(CODESET) failed." + _fsencoding = sys.getfilesystemencoding() or 'utf-8' + if _fsencoding == 'mbcs': + _fserrors = 'strict' + else: + _fserrors = 'surrogateescape' + + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, text_type): + return filename.encode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + + def fsdecode(filename): + if isinstance(filename, text_type): + return filename + elif isinstance(filename, bytes): + return filename.decode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + +try: + from tokenize import detect_encoding +except ImportError: # pragma: no cover + from codecs import BOM_UTF8, lookup + import re + + cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") + + def _get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace("_", "-") + if enc == "utf-8" or enc.startswith("utf-8-"): + return "utf-8" + if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ + enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): + return "iso-8859-1" + return orig_enc + + def detect_encoding(readline): + """ + The detect_encoding() function is used to detect the encoding that should + be used to decode a Python source file. It requires one argument, readline, + in the same way as the tokenize() generator. + + It will call readline a maximum of twice, and return the encoding used + (as a string) and a list of any lines (left as bytes) it has read in. + + It detects the encoding from the presence of a utf-8 bom or an encoding + cookie as specified in pep-0263. If both a bom and a cookie are present, + but disagree, a SyntaxError will be raised. If the encoding cookie is an + invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, + 'utf-8-sig' is returned. + + If no encoding is specified, then the default of 'utf-8' will be returned. + """ + try: + filename = readline.__self__.name + except AttributeError: + filename = None + bom_found = False + encoding = None + default = 'utf-8' + def read_or_stop(): + try: + return readline() + except StopIteration: + return b'' + + def find_cookie(line): + try: + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') + except UnicodeDecodeError: + msg = "invalid or missing encoding declaration" + if filename is not None: + msg = '{} for {!r}'.format(msg, filename) + raise SyntaxError(msg) + + matches = cookie_re.findall(line_string) + if not matches: + return None + encoding = _get_normal_name(matches[0]) + try: + codec = lookup(encoding) + except LookupError: + # This behaviour mimics the Python interpreter + if filename is None: + msg = "unknown encoding: " + encoding + else: + msg = "unknown encoding for {!r}: {}".format(filename, + encoding) + raise SyntaxError(msg) + + if bom_found: + if codec.name != 'utf-8': + # This behaviour mimics the Python interpreter + if filename is None: + msg = 'encoding problem: utf-8' + else: + msg = 'encoding problem for {!r}: utf-8'.format(filename) + raise SyntaxError(msg) + encoding += '-sig' + return encoding + + first = read_or_stop() + if first.startswith(BOM_UTF8): + bom_found = True + first = first[3:] + default = 'utf-8-sig' + if not first: + return default, [] + + encoding = find_cookie(first) + if encoding: + return encoding, [first] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + +# For converting & <-> & etc. +try: + from html import escape +except ImportError: + from cgi import escape +if sys.version_info[:2] < (3, 4): + unescape = HTMLParser().unescape +else: + from html import unescape + +try: + from collections import ChainMap +except ImportError: # pragma: no cover + from collections import MutableMapping + + try: + from reprlib import recursive_repr as _recursive_repr + except ImportError: + def _recursive_repr(fillvalue='...'): + ''' + Decorator to make a repr function return fillvalue for a recursive + call + ''' + + def decorating_function(user_function): + repr_running = set() + + def wrapper(self): + key = id(self), get_ident() + if key in repr_running: + return fillvalue + repr_running.add(key) + try: + result = user_function(self) + finally: + repr_running.discard(key) + return result + + # Can't use functools.wraps() here because of bootstrap issues + wrapper.__module__ = getattr(user_function, '__module__') + wrapper.__doc__ = getattr(user_function, '__doc__') + wrapper.__name__ = getattr(user_function, '__name__') + wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) + return wrapper + + return decorating_function + + class ChainMap(MutableMapping): + ''' A ChainMap groups multiple dicts (or other mappings) together + to create a single, updateable view. + + The underlying mappings are stored in a list. That list is public and can + accessed or updated using the *maps* attribute. There is no other state. + + Lookups search the underlying mappings successively until a key is found. + In contrast, writes, updates, and deletions only operate on the first + mapping. + + ''' + + def __init__(self, *maps): + '''Initialize a ChainMap by setting *maps* to the given mappings. + If no mappings are provided, a single empty dictionary is used. + + ''' + self.maps = list(maps) or [{}] # always at least one map + + def __missing__(self, key): + raise KeyError(key) + + def __getitem__(self, key): + for mapping in self.maps: + try: + return mapping[key] # can't use 'key in mapping' with defaultdict + except KeyError: + pass + return self.__missing__(key) # support subclasses that define __missing__ + + def get(self, key, default=None): + return self[key] if key in self else default + + def __len__(self): + return len(set().union(*self.maps)) # reuses stored hash values if possible + + def __iter__(self): + return iter(set().union(*self.maps)) + + def __contains__(self, key): + return any(key in m for m in self.maps) + + def __bool__(self): + return any(self.maps) + + @_recursive_repr() + def __repr__(self): + return '{0.__class__.__name__}({1})'.format( + self, ', '.join(map(repr, self.maps))) + + @classmethod + def fromkeys(cls, iterable, *args): + 'Create a ChainMap with a single dict created from the iterable.' + return cls(dict.fromkeys(iterable, *args)) + + def copy(self): + 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' + return self.__class__(self.maps[0].copy(), *self.maps[1:]) + + __copy__ = copy + + def new_child(self): # like Django's Context.push() + 'New ChainMap with a new dict followed by all previous maps.' + return self.__class__({}, *self.maps) + + @property + def parents(self): # like Django's Context.pop() + 'New ChainMap from maps[1:].' + return self.__class__(*self.maps[1:]) + + def __setitem__(self, key, value): + self.maps[0][key] = value + + def __delitem__(self, key): + try: + del self.maps[0][key] + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def popitem(self): + 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' + try: + return self.maps[0].popitem() + except KeyError: + raise KeyError('No keys found in the first mapping.') + + def pop(self, key, *args): + 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' + try: + return self.maps[0].pop(key, *args) + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def clear(self): + 'Clear maps[0], leaving maps[1:] intact.' + self.maps[0].clear() + +try: + from importlib.util import cache_from_source # Python >= 3.4 +except ImportError: # pragma: no cover + try: + from imp import cache_from_source + except ImportError: # pragma: no cover + def cache_from_source(path, debug_override=None): + assert path.endswith('.py') + if debug_override is None: + debug_override = __debug__ + if debug_override: + suffix = 'c' + else: + suffix = 'o' + return path + suffix + +try: + from collections import OrderedDict +except ImportError: # pragma: no cover +## {{{ http://code.activestate.com/recipes/576693/ (r9) +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. + try: + from thread import get_ident as _get_ident + except ImportError: + from dummy_thread import get_ident as _get_ident + + try: + from _abcoll import KeysView, ValuesView, ItemsView + except ImportError: + pass + + + class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running=None): + 'od.__repr__() <==> repr(od)' + if not _repr_running: _repr_running = {} + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + +try: + from logging.config import BaseConfigurator, valid_ident +except ImportError: # pragma: no cover + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + + def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + + # The ConvertingXXX classes are wrappers around standard Python containers, + # and they serve to convert any suitable values in the container. The + # conversion converts base dicts, lists and tuples to their wrapped + # equivalents, whereas strings which match a conversion format are converted + # appropriately. + # + # Each wrapper should have a configurator attribute holding the actual + # configurator to use for conversion. + + class ConvertingDict(dict): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def get(self, key, default=None): + value = dict.get(self, key, default) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class ConvertingList(list): + """A converting list wrapper.""" + def __getitem__(self, key): + value = list.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, idx=-1): + value = list.pop(self, idx) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + class ConvertingTuple(tuple): + """A converting tuple wrapper.""" + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = staticmethod(__import__) + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + #print d, rest + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int(idx) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + #rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance(value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance(value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, string_types): + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/database.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/database.py new file mode 100644 index 0000000..a19905e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/database.py @@ -0,0 +1,1336 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""PEP 376 implementation.""" + +from __future__ import unicode_literals + +import base64 +import codecs +import contextlib +import hashlib +import logging +import os +import posixpath +import sys +import zipimport + +from . import DistlibException, resources +from .compat import StringIO +from .version import get_scheme, UnsupportedVersionError +from .metadata import Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME +from .util import (parse_requirement, cached_property, parse_name_and_version, + read_exports, write_exports, CSVReader, CSVWriter) + + +__all__ = ['Distribution', 'BaseInstalledDistribution', + 'InstalledDistribution', 'EggInfoDistribution', + 'DistributionPath'] + + +logger = logging.getLogger(__name__) + +EXPORTS_FILENAME = 'pydist-exports.json' +COMMANDS_FILENAME = 'pydist-commands.json' + +DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', + 'RESOURCES', EXPORTS_FILENAME, 'SHARED') + +DISTINFO_EXT = '.dist-info' + + +class _Cache(object): + """ + A simple cache mapping names and .dist-info paths to distributions + """ + def __init__(self): + """ + Initialise an instance. There is normally one for each DistributionPath. + """ + self.name = {} + self.path = {} + self.generated = False + + def clear(self): + """ + Clear the cache, setting it to its initial state. + """ + self.name.clear() + self.path.clear() + self.generated = False + + def add(self, dist): + """ + Add a distribution to the cache. + :param dist: The distribution to add. + """ + if dist.path not in self.path: + self.path[dist.path] = dist + self.name.setdefault(dist.key, []).append(dist) + + +class DistributionPath(object): + """ + Represents a set of distributions installed on a path (typically sys.path). + """ + def __init__(self, path=None, include_egg=False): + """ + Create an instance from a path, optionally including legacy (distutils/ + setuptools/distribute) distributions. + :param path: The path to use, as a list of directories. If not specified, + sys.path is used. + :param include_egg: If True, this instance will look for and return legacy + distributions as well as those based on PEP 376. + """ + if path is None: + path = sys.path + self.path = path + self._include_dist = True + self._include_egg = include_egg + + self._cache = _Cache() + self._cache_egg = _Cache() + self._cache_enabled = True + self._scheme = get_scheme('default') + + def _get_cache_enabled(self): + return self._cache_enabled + + def _set_cache_enabled(self, value): + self._cache_enabled = value + + cache_enabled = property(_get_cache_enabled, _set_cache_enabled) + + def clear_cache(self): + """ + Clears the internal cache. + """ + self._cache.clear() + self._cache_egg.clear() + + + def _yield_distributions(self): + """ + Yield .dist-info and/or .egg(-info) distributions. + """ + # We need to check if we've seen some resources already, because on + # some Linux systems (e.g. some Debian/Ubuntu variants) there are + # symlinks which alias other files in the environment. + seen = set() + for path in self.path: + finder = resources.finder_for_path(path) + if finder is None: + continue + r = finder.find('') + if not r or not r.is_container: + continue + rset = sorted(r.resources) + for entry in rset: + r = finder.find(entry) + if not r or r.path in seen: + continue + if self._include_dist and entry.endswith(DISTINFO_EXT): + possible_filenames = [METADATA_FILENAME, WHEEL_METADATA_FILENAME] + for metadata_filename in possible_filenames: + metadata_path = posixpath.join(entry, metadata_filename) + pydist = finder.find(metadata_path) + if pydist: + break + else: + continue + + with contextlib.closing(pydist.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + logger.debug('Found %s', r.path) + seen.add(r.path) + yield new_dist_class(r.path, metadata=metadata, + env=self) + elif self._include_egg and entry.endswith(('.egg-info', + '.egg')): + logger.debug('Found %s', r.path) + seen.add(r.path) + yield old_dist_class(r.path, self) + + def _generate_cache(self): + """ + Scan the path for distributions and populate the cache with + those that are found. + """ + gen_dist = not self._cache.generated + gen_egg = self._include_egg and not self._cache_egg.generated + if gen_dist or gen_egg: + for dist in self._yield_distributions(): + if isinstance(dist, InstalledDistribution): + self._cache.add(dist) + else: + self._cache_egg.add(dist) + + if gen_dist: + self._cache.generated = True + if gen_egg: + self._cache_egg.generated = True + + @classmethod + def distinfo_dirname(cls, name, version): + """ + The *name* and *version* parameters are converted into their + filename-escaped form, i.e. any ``'-'`` characters are replaced + with ``'_'`` other than the one in ``'dist-info'`` and the one + separating the name from the version number. + + :parameter name: is converted to a standard distribution name by replacing + any runs of non- alphanumeric characters with a single + ``'-'``. + :type name: string + :parameter version: is converted to a standard version string. Spaces + become dots, and all other non-alphanumeric characters + (except dots) become dashes, with runs of multiple + dashes condensed to a single dash. + :type version: string + :returns: directory name + :rtype: string""" + name = name.replace('-', '_') + return '-'.join([name, version]) + DISTINFO_EXT + + def get_distributions(self): + """ + Provides an iterator that looks for distributions and returns + :class:`InstalledDistribution` or + :class:`EggInfoDistribution` instances for each one of them. + + :rtype: iterator of :class:`InstalledDistribution` and + :class:`EggInfoDistribution` instances + """ + if not self._cache_enabled: + for dist in self._yield_distributions(): + yield dist + else: + self._generate_cache() + + for dist in self._cache.path.values(): + yield dist + + if self._include_egg: + for dist in self._cache_egg.path.values(): + yield dist + + def get_distribution(self, name): + """ + Looks for a named distribution on the path. + + This function only returns the first result found, as no more than one + value is expected. If nothing is found, ``None`` is returned. + + :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` + or ``None`` + """ + result = None + name = name.lower() + if not self._cache_enabled: + for dist in self._yield_distributions(): + if dist.key == name: + result = dist + break + else: + self._generate_cache() + + if name in self._cache.name: + result = self._cache.name[name][0] + elif self._include_egg and name in self._cache_egg.name: + result = self._cache_egg.name[name][0] + return result + + def provides_distribution(self, name, version=None): + """ + Iterates over all distributions to find which distributions provide *name*. + If a *version* is provided, it will be used to filter the results. + + This function only returns the first result found, since no more than + one values are expected. If the directory is not found, returns ``None``. + + :parameter version: a version specifier that indicates the version + required, conforming to the format in ``PEP-345`` + + :type name: string + :type version: string + """ + matcher = None + if version is not None: + try: + matcher = self._scheme.matcher('%s (%s)' % (name, version)) + except ValueError: + raise DistlibException('invalid name or version: %r, %r' % + (name, version)) + + for dist in self.get_distributions(): + # We hit a problem on Travis where enum34 was installed and doesn't + # have a provides attribute ... + if not hasattr(dist, 'provides'): + logger.debug('No "provides": %s', dist) + else: + provided = dist.provides + + for p in provided: + p_name, p_ver = parse_name_and_version(p) + if matcher is None: + if p_name == name: + yield dist + break + else: + if p_name == name and matcher.match(p_ver): + yield dist + break + + def get_file_path(self, name, relative_path): + """ + Return the path to a resource file. + """ + dist = self.get_distribution(name) + if dist is None: + raise LookupError('no distribution named %r found' % name) + return dist.get_resource_path(relative_path) + + def get_exported_entries(self, category, name=None): + """ + Return all of the exported entries in a particular category. + + :param category: The category to search for entries. + :param name: If specified, only entries with that name are returned. + """ + for dist in self.get_distributions(): + r = dist.exports + if category in r: + d = r[category] + if name is not None: + if name in d: + yield d[name] + else: + for v in d.values(): + yield v + + +class Distribution(object): + """ + A base class for distributions, whether installed or from indexes. + Either way, it must have some metadata, so that's all that's needed + for construction. + """ + + build_time_dependency = False + """ + Set to True if it's known to be only a build-time dependency (i.e. + not needed after installation). + """ + + requested = False + """A boolean that indicates whether the ``REQUESTED`` metadata file is + present (in other words, whether the package was installed by user + request or it was installed as a dependency).""" + + def __init__(self, metadata): + """ + Initialise an instance. + :param metadata: The instance of :class:`Metadata` describing this + distribution. + """ + self.metadata = metadata + self.name = metadata.name + self.key = self.name.lower() # for case-insensitive comparisons + self.version = metadata.version + self.locator = None + self.digest = None + self.extras = None # additional features requested + self.context = None # environment marker overrides + self.download_urls = set() + self.digests = {} + + @property + def source_url(self): + """ + The source archive download URL for this distribution. + """ + return self.metadata.source_url + + download_url = source_url # Backward compatibility + + @property + def name_and_version(self): + """ + A utility property which displays the name and version in parentheses. + """ + return '%s (%s)' % (self.name, self.version) + + @property + def provides(self): + """ + A set of distribution names and versions provided by this distribution. + :return: A set of "name (version)" strings. + """ + plist = self.metadata.provides + s = '%s (%s)' % (self.name, self.version) + if s not in plist: + plist.append(s) + return plist + + def _get_requirements(self, req_attr): + md = self.metadata + logger.debug('Getting requirements from metadata %r', md.todict()) + reqts = getattr(md, req_attr) + return set(md.get_requirements(reqts, extras=self.extras, + env=self.context)) + + @property + def run_requires(self): + return self._get_requirements('run_requires') + + @property + def meta_requires(self): + return self._get_requirements('meta_requires') + + @property + def build_requires(self): + return self._get_requirements('build_requires') + + @property + def test_requires(self): + return self._get_requirements('test_requires') + + @property + def dev_requires(self): + return self._get_requirements('dev_requires') + + def matches_requirement(self, req): + """ + Say if this instance matches (fulfills) a requirement. + :param req: The requirement to match. + :rtype req: str + :return: True if it matches, else False. + """ + # Requirement may contain extras - parse to lose those + # from what's passed to the matcher + r = parse_requirement(req) + scheme = get_scheme(self.metadata.scheme) + try: + matcher = scheme.matcher(r.requirement) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + result = False + for p in self.provides: + p_name, p_ver = parse_name_and_version(p) + if p_name != name: + continue + try: + result = matcher.match(p_ver) + break + except UnsupportedVersionError: + pass + return result + + def __repr__(self): + """ + Return a textual representation of this instance, + """ + if self.source_url: + suffix = ' [%s]' % self.source_url + else: + suffix = '' + return '<Distribution %s (%s)%s>' % (self.name, self.version, suffix) + + def __eq__(self, other): + """ + See if this distribution is the same as another. + :param other: The distribution to compare with. To be equal to one + another. distributions must have the same type, name, + version and source_url. + :return: True if it is the same, else False. + """ + if type(other) is not type(self): + result = False + else: + result = (self.name == other.name and + self.version == other.version and + self.source_url == other.source_url) + return result + + def __hash__(self): + """ + Compute hash in a way which matches the equality test. + """ + return hash(self.name) + hash(self.version) + hash(self.source_url) + + +class BaseInstalledDistribution(Distribution): + """ + This is the base class for installed distributions (whether PEP 376 or + legacy). + """ + + hasher = None + + def __init__(self, metadata, path, env=None): + """ + Initialise an instance. + :param metadata: An instance of :class:`Metadata` which describes the + distribution. This will normally have been initialised + from a metadata file in the ``path``. + :param path: The path of the ``.dist-info`` or ``.egg-info`` + directory for the distribution. + :param env: This is normally the :class:`DistributionPath` + instance where this distribution was found. + """ + super(BaseInstalledDistribution, self).__init__(metadata) + self.path = path + self.dist_path = env + + def get_hash(self, data, hasher=None): + """ + Get the hash of some data, using a particular hash algorithm, if + specified. + + :param data: The data to be hashed. + :type data: bytes + :param hasher: The name of a hash implementation, supported by hashlib, + or ``None``. Examples of valid values are ``'sha1'``, + ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and + ``'sha512'``. If no hasher is specified, the ``hasher`` + attribute of the :class:`InstalledDistribution` instance + is used. If the hasher is determined to be ``None``, MD5 + is used as the hashing algorithm. + :returns: The hash of the data. If a hasher was explicitly specified, + the returned hash will be prefixed with the specified hasher + followed by '='. + :rtype: str + """ + if hasher is None: + hasher = self.hasher + if hasher is None: + hasher = hashlib.md5 + prefix = '' + else: + hasher = getattr(hashlib, hasher) + prefix = '%s=' % self.hasher + digest = hasher(data).digest() + digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') + return '%s%s' % (prefix, digest) + + +class InstalledDistribution(BaseInstalledDistribution): + """ + Created with the *path* of the ``.dist-info`` directory provided to the + constructor. It reads the metadata contained in ``pydist.json`` when it is + instantiated., or uses a passed in Metadata instance (useful for when + dry-run mode is being used). + """ + + hasher = 'sha256' + + def __init__(self, path, metadata=None, env=None): + self.modules = [] + self.finder = finder = resources.finder_for_path(path) + if finder is None: + raise ValueError('finder unavailable for %s' % path) + if env and env._cache_enabled and path in env._cache.path: + metadata = env._cache.path[path].metadata + elif metadata is None: + r = finder.find(METADATA_FILENAME) + # Temporary - for Wheel 0.23 support + if r is None: + r = finder.find(WHEEL_METADATA_FILENAME) + # Temporary - for legacy support + if r is None: + r = finder.find('METADATA') + if r is None: + raise ValueError('no %s found in %s' % (METADATA_FILENAME, + path)) + with contextlib.closing(r.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + + super(InstalledDistribution, self).__init__(metadata, path, env) + + if env and env._cache_enabled: + env._cache.add(self) + + r = finder.find('REQUESTED') + self.requested = r is not None + p = os.path.join(path, 'top_level.txt') + if os.path.exists(p): + with open(p, 'rb') as f: + data = f.read() + self.modules = data.splitlines() + + def __repr__(self): + return '<InstalledDistribution %r %s at %r>' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def _get_records(self): + """ + Get the list of installed files for the distribution + :return: A list of tuples of path, hash and size. Note that hash and + size might be ``None`` for some entries. The path is exactly + as stored in the file (which is as in PEP 376). + """ + results = [] + r = self.get_distinfo_resource('RECORD') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as record_reader: + # Base location is parent dir of .dist-info dir + #base_location = os.path.dirname(self.path) + #base_location = os.path.abspath(base_location) + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + #if not os.path.isabs(path): + # path = path.replace('/', os.sep) + # path = os.path.join(base_location, path) + results.append((path, checksum, size)) + return results + + @cached_property + def exports(self): + """ + Return the information exported by this distribution. + :return: A dictionary of exports, mapping an export category to a dict + of :class:`ExportEntry` instances describing the individual + export entries, and keyed by name. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + result = self.read_exports() + return result + + def read_exports(self): + """ + Read exports data from a file in .ini format. + + :return: A dictionary of exports, mapping an export category to a list + of :class:`ExportEntry` instances describing the individual + export entries. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + with contextlib.closing(r.as_stream()) as stream: + result = read_exports(stream) + return result + + def write_exports(self, exports): + """ + Write a dictionary of exports to a file in .ini format. + :param exports: A dictionary of exports, mapping an export category to + a list of :class:`ExportEntry` instances describing the + individual export entries. + """ + rf = self.get_distinfo_file(EXPORTS_FILENAME) + with open(rf, 'w') as f: + write_exports(exports, f) + + def get_resource_path(self, relative_path): + """ + NOTE: This API may change in the future. + + Return the absolute path to a resource file with the given relative + path. + + :param relative_path: The path, relative to .dist-info, of the resource + of interest. + :return: The absolute path where the resource is to be found. + """ + r = self.get_distinfo_resource('RESOURCES') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as resources_reader: + for relative, destination in resources_reader: + if relative == relative_path: + return destination + raise KeyError('no resource file with relative path %r ' + 'is installed' % relative_path) + + def list_installed_files(self): + """ + Iterates over the ``RECORD`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: iterator of (path, hash, size) + """ + for result in self._get_records(): + yield result + + def write_installed_files(self, paths, prefix, dry_run=False): + """ + Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any + existing ``RECORD`` file is silently overwritten. + + prefix is used to determine when to write absolute paths. + """ + prefix = os.path.join(prefix, '') + base = os.path.dirname(self.path) + base_under_prefix = base.startswith(prefix) + base = os.path.join(base, '') + record_path = self.get_distinfo_file('RECORD') + logger.info('creating %s', record_path) + if dry_run: + return None + with CSVWriter(record_path) as writer: + for path in paths: + if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): + # do not put size and hash, as in PEP-376 + hash_value = size = '' + else: + size = '%d' % os.path.getsize(path) + with open(path, 'rb') as fp: + hash_value = self.get_hash(fp.read()) + if path.startswith(base) or (base_under_prefix and + path.startswith(prefix)): + path = os.path.relpath(path, base) + writer.writerow((path, hash_value, size)) + + # add the RECORD file itself + if record_path.startswith(base): + record_path = os.path.relpath(record_path, base) + writer.writerow((record_path, '', '')) + return record_path + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + base = os.path.dirname(self.path) + record_path = self.get_distinfo_file('RECORD') + for path, hash_value, size in self.list_installed_files(): + if not os.path.isabs(path): + path = os.path.join(base, path) + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + elif os.path.isfile(path): + actual_size = str(os.path.getsize(path)) + if size and actual_size != size: + mismatches.append((path, 'size', size, actual_size)) + elif hash_value: + if '=' in hash_value: + hasher = hash_value.split('=', 1)[0] + else: + hasher = None + + with open(path, 'rb') as f: + actual_hash = self.get_hash(f.read(), hasher) + if actual_hash != hash_value: + mismatches.append((path, 'hash', hash_value, actual_hash)) + return mismatches + + @cached_property + def shared_locations(self): + """ + A dictionary of shared locations whose keys are in the set 'prefix', + 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. + The corresponding value is the absolute path of that category for + this distribution, and takes into account any paths selected by the + user at installation time (e.g. via command-line arguments). In the + case of the 'namespace' key, this would be a list of absolute paths + for the roots of namespace packages in this distribution. + + The first time this property is accessed, the relevant information is + read from the SHARED file in the .dist-info directory. + """ + result = {} + shared_path = os.path.join(self.path, 'SHARED') + if os.path.isfile(shared_path): + with codecs.open(shared_path, 'r', encoding='utf-8') as f: + lines = f.read().splitlines() + for line in lines: + key, value = line.split('=', 1) + if key == 'namespace': + result.setdefault(key, []).append(value) + else: + result[key] = value + return result + + def write_shared_locations(self, paths, dry_run=False): + """ + Write shared location information to the SHARED file in .dist-info. + :param paths: A dictionary as described in the documentation for + :meth:`shared_locations`. + :param dry_run: If True, the action is logged but no file is actually + written. + :return: The path of the file written to. + """ + shared_path = os.path.join(self.path, 'SHARED') + logger.info('creating %s', shared_path) + if dry_run: + return None + lines = [] + for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): + path = paths[key] + if os.path.isdir(paths[key]): + lines.append('%s=%s' % (key, path)) + for ns in paths.get('namespace', ()): + lines.append('namespace=%s' % ns) + + with codecs.open(shared_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + return shared_path + + def get_distinfo_resource(self, path): + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + finder = resources.finder_for_path(self.path) + if finder is None: + raise DistlibException('Unable to get a finder for %s' % self.path) + return finder.find(path) + + def get_distinfo_file(self, path): + """ + Returns a path located under the ``.dist-info`` directory. Returns a + string representing the path. + + :parameter path: a ``'/'``-separated path relative to the + ``.dist-info`` directory or an absolute path; + If *path* is an absolute path and doesn't start + with the ``.dist-info`` directory path, + a :class:`DistlibException` is raised + :type path: str + :rtype: str + """ + # Check if it is an absolute path # XXX use relpath, add tests + if path.find(os.sep) >= 0: + # it's an absolute path? + distinfo_dirname, path = path.split(os.sep)[-2:] + if distinfo_dirname != self.path.split(os.sep)[-1]: + raise DistlibException( + 'dist-info file %r does not belong to the %r %s ' + 'distribution' % (path, self.name, self.version)) + + # The file must be relative + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + + return os.path.join(self.path, path) + + def list_distinfo_files(self): + """ + Iterates over the ``RECORD`` entries and returns paths for each line if + the path is pointing to a file located in the ``.dist-info`` directory + or one of its subdirectories. + + :returns: iterator of paths + """ + base = os.path.dirname(self.path) + for path, checksum, size in self._get_records(): + # XXX add separator or use real relpath algo + if not os.path.isabs(path): + path = os.path.join(base, path) + if path.startswith(self.path): + yield path + + def __eq__(self, other): + return (isinstance(other, InstalledDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + + +class EggInfoDistribution(BaseInstalledDistribution): + """Created with the *path* of the ``.egg-info`` directory or file provided + to the constructor. It reads the metadata contained in the file itself, or + if the given path happens to be a directory, the metadata is read from the + file ``PKG-INFO`` under that directory.""" + + requested = True # as we have no way of knowing, assume it was + shared_locations = {} + + def __init__(self, path, env=None): + def set_name_and_version(s, n, v): + s.name = n + s.key = n.lower() # for case-insensitive comparisons + s.version = v + + self.path = path + self.dist_path = env + if env and env._cache_enabled and path in env._cache_egg.path: + metadata = env._cache_egg.path[path].metadata + set_name_and_version(self, metadata.name, metadata.version) + else: + metadata = self._get_metadata(path) + + # Need to be set before caching + set_name_and_version(self, metadata.name, metadata.version) + + if env and env._cache_enabled: + env._cache_egg.add(self) + super(EggInfoDistribution, self).__init__(metadata, path, env) + + def _get_metadata(self, path): + requires = None + + def parse_requires_data(data): + """Create a list of dependencies from a requires.txt file. + + *data*: the contents of a setuptools-produced requires.txt file. + """ + reqs = [] + lines = data.splitlines() + for line in lines: + line = line.strip() + if line.startswith('['): + logger.warning('Unexpected line: quitting requirement scan: %r', + line) + break + r = parse_requirement(line) + if not r: + logger.warning('Not recognised as a requirement: %r', line) + continue + if r.extras: + logger.warning('extra requirements in requires.txt are ' + 'not supported') + if not r.constraints: + reqs.append(r.name) + else: + cons = ', '.join('%s%s' % c for c in r.constraints) + reqs.append('%s (%s)' % (r.name, cons)) + return reqs + + def parse_requires_path(req_path): + """Create a list of dependencies from a requires.txt file. + + *req_path*: the path to a setuptools-produced requires.txt file. + """ + + reqs = [] + try: + with codecs.open(req_path, 'r', 'utf-8') as fp: + reqs = parse_requires_data(fp.read()) + except IOError: + pass + return reqs + + tl_path = tl_data = None + if path.endswith('.egg'): + if os.path.isdir(path): + p = os.path.join(path, 'EGG-INFO') + meta_path = os.path.join(p, 'PKG-INFO') + metadata = Metadata(path=meta_path, scheme='legacy') + req_path = os.path.join(p, 'requires.txt') + tl_path = os.path.join(p, 'top_level.txt') + requires = parse_requires_path(req_path) + else: + # FIXME handle the case where zipfile is not available + zipf = zipimport.zipimporter(path) + fileobj = StringIO( + zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) + metadata = Metadata(fileobj=fileobj, scheme='legacy') + try: + data = zipf.get_data('EGG-INFO/requires.txt') + tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8') + requires = parse_requires_data(data.decode('utf-8')) + except IOError: + requires = None + elif path.endswith('.egg-info'): + if os.path.isdir(path): + req_path = os.path.join(path, 'requires.txt') + requires = parse_requires_path(req_path) + path = os.path.join(path, 'PKG-INFO') + tl_path = os.path.join(path, 'top_level.txt') + metadata = Metadata(path=path, scheme='legacy') + else: + raise DistlibException('path must end with .egg-info or .egg, ' + 'got %r' % path) + + if requires: + metadata.add_requirements(requires) + # look for top-level modules in top_level.txt, if present + if tl_data is None: + if tl_path is not None and os.path.exists(tl_path): + with open(tl_path, 'rb') as f: + tl_data = f.read().decode('utf-8') + if not tl_data: + tl_data = [] + else: + tl_data = tl_data.splitlines() + self.modules = tl_data + return metadata + + def __repr__(self): + return '<EggInfoDistribution %r %s at %r>' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + for path, _, _ in self.list_installed_files(): + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + return mismatches + + def list_installed_files(self): + """ + Iterates over the ``installed-files.txt`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: a list of (path, hash, size) + """ + + def _md5(path): + f = open(path, 'rb') + try: + content = f.read() + finally: + f.close() + return hashlib.md5(content).hexdigest() + + def _size(path): + return os.stat(path).st_size + + record_path = os.path.join(self.path, 'installed-files.txt') + result = [] + if os.path.exists(record_path): + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + p = os.path.normpath(os.path.join(self.path, line)) + # "./" is present as a marker between installed files + # and installation metadata files + if not os.path.exists(p): + logger.warning('Non-existent file: %s', p) + if p.endswith(('.pyc', '.pyo')): + continue + #otherwise fall through and fail + if not os.path.isdir(p): + result.append((p, _md5(p), _size(p))) + result.append((record_path, None, None)) + return result + + def list_distinfo_files(self, absolute=False): + """ + Iterates over the ``installed-files.txt`` entries and returns paths for + each line if the path is pointing to a file located in the + ``.egg-info`` directory or one of its subdirectories. + + :parameter absolute: If *absolute* is ``True``, each returned path is + transformed into a local absolute path. Otherwise the + raw value from ``installed-files.txt`` is returned. + :type absolute: boolean + :returns: iterator of paths + """ + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + skip = True + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line == './': + skip = False + continue + if not skip: + p = os.path.normpath(os.path.join(self.path, line)) + if p.startswith(self.path): + if absolute: + yield p + else: + yield line + + def __eq__(self, other): + return (isinstance(other, EggInfoDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + +new_dist_class = InstalledDistribution +old_dist_class = EggInfoDistribution + + +class DependencyGraph(object): + """ + Represents a dependency graph between distributions. + + The dependency relationships are stored in an ``adjacency_list`` that maps + distributions to a list of ``(other, label)`` tuples where ``other`` + is a distribution and the edge is labeled with ``label`` (i.e. the version + specifier, if such was provided). Also, for more efficient traversal, for + every distribution ``x``, a list of predecessors is kept in + ``reverse_list[x]``. An edge from distribution ``a`` to + distribution ``b`` means that ``a`` depends on ``b``. If any missing + dependencies are found, they are stored in ``missing``, which is a + dictionary that maps distributions to a list of requirements that were not + provided by any other distributions. + """ + + def __init__(self): + self.adjacency_list = {} + self.reverse_list = {} + self.missing = {} + + def add_distribution(self, distribution): + """Add the *distribution* to the graph. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + """ + self.adjacency_list[distribution] = [] + self.reverse_list[distribution] = [] + #self.missing[distribution] = [] + + def add_edge(self, x, y, label=None): + """Add an edge from distribution *x* to distribution *y* with the given + *label*. + + :type x: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type y: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type label: ``str`` or ``None`` + """ + self.adjacency_list[x].append((y, label)) + # multiple edges are allowed, so be careful + if x not in self.reverse_list[y]: + self.reverse_list[y].append(x) + + def add_missing(self, distribution, requirement): + """ + Add a missing *requirement* for the given *distribution*. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + :type requirement: ``str`` + """ + logger.debug('%s missing %r', distribution, requirement) + self.missing.setdefault(distribution, []).append(requirement) + + def _repr_dist(self, dist): + return '%s %s' % (dist.name, dist.version) + + def repr_node(self, dist, level=1): + """Prints only a subgraph""" + output = [self._repr_dist(dist)] + for other, label in self.adjacency_list[dist]: + dist = self._repr_dist(other) + if label is not None: + dist = '%s [%s]' % (dist, label) + output.append(' ' * level + str(dist)) + suboutput = self.repr_node(other, level + 1) + subs = suboutput.split('\n') + output.extend(subs[1:]) + return '\n'.join(output) + + def to_dot(self, f, skip_disconnected=True): + """Writes a DOT output for the graph to the provided file *f*. + + If *skip_disconnected* is set to ``True``, then all distributions + that are not dependent on any other distribution are skipped. + + :type f: has to support ``file``-like operations + :type skip_disconnected: ``bool`` + """ + disconnected = [] + + f.write("digraph dependencies {\n") + for dist, adjs in self.adjacency_list.items(): + if len(adjs) == 0 and not skip_disconnected: + disconnected.append(dist) + for other, label in adjs: + if not label is None: + f.write('"%s" -> "%s" [label="%s"]\n' % + (dist.name, other.name, label)) + else: + f.write('"%s" -> "%s"\n' % (dist.name, other.name)) + if not skip_disconnected and len(disconnected) > 0: + f.write('subgraph disconnected {\n') + f.write('label = "Disconnected"\n') + f.write('bgcolor = red\n') + + for dist in disconnected: + f.write('"%s"' % dist.name) + f.write('\n') + f.write('}\n') + f.write('}\n') + + def topological_sort(self): + """ + Perform a topological sort of the graph. + :return: A tuple, the first element of which is a topologically sorted + list of distributions, and the second element of which is a + list of distributions that cannot be sorted because they have + circular dependencies and so form a cycle. + """ + result = [] + # Make a shallow copy of the adjacency list + alist = {} + for k, v in self.adjacency_list.items(): + alist[k] = v[:] + while True: + # See what we can remove in this run + to_remove = [] + for k, v in list(alist.items())[:]: + if not v: + to_remove.append(k) + del alist[k] + if not to_remove: + # What's left in alist (if anything) is a cycle. + break + # Remove from the adjacency list of others + for k, v in alist.items(): + alist[k] = [(d, r) for d, r in v if d not in to_remove] + logger.debug('Moving to result: %s', + ['%s (%s)' % (d.name, d.version) for d in to_remove]) + result.extend(to_remove) + return result, list(alist.keys()) + + def __repr__(self): + """Representation of the graph""" + output = [] + for dist, adjs in self.adjacency_list.items(): + output.append(self.repr_node(dist)) + return '\n'.join(output) + + +def make_graph(dists, scheme='default'): + """Makes a dependency graph from the given distributions. + + :parameter dists: a list of distributions + :type dists: list of :class:`distutils2.database.InstalledDistribution` and + :class:`distutils2.database.EggInfoDistribution` instances + :rtype: a :class:`DependencyGraph` instance + """ + scheme = get_scheme(scheme) + graph = DependencyGraph() + provided = {} # maps names to lists of (version, dist) tuples + + # first, build the graph and find out what's provided + for dist in dists: + graph.add_distribution(dist) + + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + provided.setdefault(name, []).append((version, dist)) + + # now make the edges + for dist in dists: + requires = (dist.run_requires | dist.meta_requires | + dist.build_requires | dist.dev_requires) + for req in requires: + try: + matcher = scheme.matcher(req) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + matched = False + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + graph.add_edge(dist, provider, req) + matched = True + break + if not matched: + graph.add_missing(dist, req) + return graph + + +def get_dependent_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + dependent on *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + dep = [dist] # dependent distributions + todo = graph.reverse_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop() + dep.append(d) + for succ in graph.reverse_list[d]: + if succ not in dep: + todo.append(succ) + + dep.pop(0) # remove dist from dep, was there to prevent infinite loops + return dep + + +def get_required_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + required by *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + req = [] # required distributions + todo = graph.adjacency_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop()[0] + req.append(d) + for pred in graph.adjacency_list[d]: + if pred not in req: + todo.append(pred) + + return req + + +def make_dist(name, version, **kwargs): + """ + A convenience method for making a dist given just a name and version. + """ + summary = kwargs.pop('summary', 'Placeholder for summary') + md = Metadata(**kwargs) + md.name = name + md.version = version + md.summary = summary or 'Placeholder for summary' + return Distribution(md) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/index.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/index.py new file mode 100644 index 0000000..2406be2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/index.py @@ -0,0 +1,516 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import hashlib +import logging +import os +import shutil +import subprocess +import tempfile +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread + +from . import DistlibException +from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, + urlparse, build_opener, string_types) +from .util import cached_property, zip_dir, ServerProxy + +logger = logging.getLogger(__name__) + +DEFAULT_INDEX = 'https://pypi.python.org/pypi' +DEFAULT_REALM = 'pypi' + +class PackageIndex(object): + """ + This class represents a package index compatible with PyPI, the Python + Package Index. + """ + + boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' + + def __init__(self, url=None): + """ + Initialise an instance. + + :param url: The URL of the index. If not specified, the URL for PyPI is + used. + """ + self.url = url or DEFAULT_INDEX + self.read_configuration() + scheme, netloc, path, params, query, frag = urlparse(self.url) + if params or query or frag or scheme not in ('http', 'https'): + raise DistlibException('invalid repository: %s' % self.url) + self.password_handler = None + self.ssl_verifier = None + self.gpg = None + self.gpg_home = None + with open(os.devnull, 'w') as sink: + # Use gpg by default rather than gpg2, as gpg2 insists on + # prompting for passwords + for s in ('gpg', 'gpg2'): + try: + rc = subprocess.check_call([s, '--version'], stdout=sink, + stderr=sink) + if rc == 0: + self.gpg = s + break + except OSError: + pass + + def _get_pypirc_command(self): + """ + Get the distutils command for interacting with PyPI configurations. + :return: the command. + """ + from distutils.core import Distribution + from distutils.config import PyPIRCCommand + d = Distribution() + return PyPIRCCommand(d) + + def read_configuration(self): + """ + Read the PyPI access configuration as supported by distutils, getting + PyPI to do the actual work. This populates ``username``, ``password``, + ``realm`` and ``url`` attributes from the configuration. + """ + # get distutils to do the work + c = self._get_pypirc_command() + c.repository = self.url + cfg = c._read_pypirc() + self.username = cfg.get('username') + self.password = cfg.get('password') + self.realm = cfg.get('realm', 'pypi') + self.url = cfg.get('repository', self.url) + + def save_configuration(self): + """ + Save the PyPI access configuration. You must have set ``username`` and + ``password`` attributes before calling this method. + + Again, distutils is used to do the actual work. + """ + self.check_credentials() + # get distutils to do the work + c = self._get_pypirc_command() + c._store_pypirc(self.username, self.password) + + def check_credentials(self): + """ + Check that ``username`` and ``password`` have been set, and raise an + exception if not. + """ + if self.username is None or self.password is None: + raise DistlibException('username and password must be set') + pm = HTTPPasswordMgr() + _, netloc, _, _, _, _ = urlparse(self.url) + pm.add_password(self.realm, netloc, self.username, self.password) + self.password_handler = HTTPBasicAuthHandler(pm) + + def register(self, metadata): + """ + Register a distribution on PyPI, using the provided metadata. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the distribution to be + registered. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + metadata.validate() + d = metadata.todict() + d[':action'] = 'verify' + request = self.encode_request(d.items(), []) + response = self.send_request(request) + d[':action'] = 'submit' + request = self.encode_request(d.items(), []) + return self.send_request(request) + + def _reader(self, name, stream, outbuf): + """ + Thread runner for reading lines of from a subprocess into a buffer. + + :param name: The logical name of the stream (used for logging only). + :param stream: The stream to read from. This will typically a pipe + connected to the output stream of a subprocess. + :param outbuf: The list to append the read lines to. + """ + while True: + s = stream.readline() + if not s: + break + s = s.decode('utf-8').rstrip() + outbuf.append(s) + logger.debug('%s: %s' % (name, s)) + stream.close() + + def get_sign_command(self, filename, signer, sign_password, + keystore=None): + """ + Return a suitable command for signing a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The signing command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + if sign_password is not None: + cmd.extend(['--batch', '--passphrase-fd', '0']) + td = tempfile.mkdtemp() + sf = os.path.join(td, os.path.basename(filename) + '.asc') + cmd.extend(['--detach-sign', '--armor', '--local-user', + signer, '--output', sf, filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd, sf + + def run_command(self, cmd, input_data=None): + """ + Run a command in a child process , passing it any input data specified. + + :param cmd: The command to run. + :param input_data: If specified, this must be a byte string containing + data to be sent to the child process. + :return: A tuple consisting of the subprocess' exit code, a list of + lines read from the subprocess' ``stdout``, and a list of + lines read from the subprocess' ``stderr``. + """ + kwargs = { + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + } + if input_data is not None: + kwargs['stdin'] = subprocess.PIPE + stdout = [] + stderr = [] + p = subprocess.Popen(cmd, **kwargs) + # We don't use communicate() here because we may need to + # get clever with interacting with the command + t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) + t1.start() + t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) + t2.start() + if input_data is not None: + p.stdin.write(input_data) + p.stdin.close() + + p.wait() + t1.join() + t2.join() + return p.returncode, stdout, stderr + + def sign_file(self, filename, signer, sign_password, keystore=None): + """ + Sign a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The absolute pathname of the file where the signature is + stored. + """ + cmd, sig_file = self.get_sign_command(filename, signer, sign_password, + keystore) + rc, stdout, stderr = self.run_command(cmd, + sign_password.encode('utf-8')) + if rc != 0: + raise DistlibException('sign command failed with error ' + 'code %s' % rc) + return sig_file + + def upload_file(self, metadata, filename, signer=None, sign_password=None, + filetype='sdist', pyversion='source', keystore=None): + """ + Upload a release file to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the file to be uploaded. + :param filename: The pathname of the file to be uploaded. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param filetype: The type of the file being uploaded. This is the + distutils command which produced that file, e.g. + ``sdist`` or ``bdist_wheel``. + :param pyversion: The version of Python which the release relates + to. For code compatible with any Python, this would + be ``source``, otherwise it would be e.g. ``3.2``. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.exists(filename): + raise DistlibException('not found: %s' % filename) + metadata.validate() + d = metadata.todict() + sig_file = None + if signer: + if not self.gpg: + logger.warning('no signing program available - not signed') + else: + sig_file = self.sign_file(filename, signer, sign_password, + keystore) + with open(filename, 'rb') as f: + file_data = f.read() + md5_digest = hashlib.md5(file_data).hexdigest() + sha256_digest = hashlib.sha256(file_data).hexdigest() + d.update({ + ':action': 'file_upload', + 'protocol_version': '1', + 'filetype': filetype, + 'pyversion': pyversion, + 'md5_digest': md5_digest, + 'sha256_digest': sha256_digest, + }) + files = [('content', os.path.basename(filename), file_data)] + if sig_file: + with open(sig_file, 'rb') as f: + sig_data = f.read() + files.append(('gpg_signature', os.path.basename(sig_file), + sig_data)) + shutil.rmtree(os.path.dirname(sig_file)) + request = self.encode_request(d.items(), files) + return self.send_request(request) + + def upload_documentation(self, metadata, doc_dir): + """ + Upload documentation to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the documentation to be + uploaded. + :param doc_dir: The pathname of the directory which contains the + documentation. This should be the directory that + contains the ``index.html`` for the documentation. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.isdir(doc_dir): + raise DistlibException('not a directory: %r' % doc_dir) + fn = os.path.join(doc_dir, 'index.html') + if not os.path.exists(fn): + raise DistlibException('not found: %r' % fn) + metadata.validate() + name, version = metadata.name, metadata.version + zip_data = zip_dir(doc_dir).getvalue() + fields = [(':action', 'doc_upload'), + ('name', name), ('version', version)] + files = [('content', name, zip_data)] + request = self.encode_request(fields, files) + return self.send_request(request) + + def get_verify_command(self, signature_filename, data_filename, + keystore=None): + """ + Return a suitable command for verifying a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The verifying command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + cmd.extend(['--verify', signature_filename, data_filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd + + def verify_signature(self, signature_filename, data_filename, + keystore=None): + """ + Verify a signature for a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: True if the signature was verified, else False. + """ + if not self.gpg: + raise DistlibException('verification unavailable because gpg ' + 'unavailable') + cmd = self.get_verify_command(signature_filename, data_filename, + keystore) + rc, stdout, stderr = self.run_command(cmd) + if rc not in (0, 1): + raise DistlibException('verify command failed with error ' + 'code %s' % rc) + return rc == 0 + + def download_file(self, url, destfile, digest=None, reporthook=None): + """ + This is a convenience method for downloading a file from an URL. + Normally, this will be a file from the index, though currently + no check is made for this (i.e. a file can be downloaded from + anywhere). + + The method is just like the :func:`urlretrieve` function in the + standard library, except that it allows digest computation to be + done during download and checking that the downloaded data + matched any expected value. + + :param url: The URL of the file to be downloaded (assumed to be + available via an HTTP GET request). + :param destfile: The pathname where the downloaded file is to be + saved. + :param digest: If specified, this must be a (hasher, value) + tuple, where hasher is the algorithm used (e.g. + ``'md5'``) and ``value`` is the expected value. + :param reporthook: The same as for :func:`urlretrieve` in the + standard library. + """ + if digest is None: + digester = None + logger.debug('No digest specified') + else: + if isinstance(digest, (list, tuple)): + hasher, digest = digest + else: + hasher = 'md5' + digester = getattr(hashlib, hasher)() + logger.debug('Digest specified: %s' % digest) + # The following code is equivalent to urlretrieve. + # We need to do it this way so that we can compute the + # digest of the file as we go. + with open(destfile, 'wb') as dfp: + # addinfourl is not a context manager on 2.x + # so we have to use try/finally + sfp = self.send_request(Request(url)) + try: + headers = sfp.info() + blocksize = 8192 + size = -1 + read = 0 + blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) + if reporthook: + reporthook(blocknum, blocksize, size) + while True: + block = sfp.read(blocksize) + if not block: + break + read += len(block) + dfp.write(block) + if digester: + digester.update(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, blocksize, size) + finally: + sfp.close() + + # check that we got the whole file, if we can + if size >= 0 and read < size: + raise DistlibException( + 'retrieval incomplete: got only %d out of %d bytes' + % (read, size)) + # if we have a digest, it must match. + if digester: + actual = digester.hexdigest() + if digest != actual: + raise DistlibException('%s digest mismatch for %s: expected ' + '%s, got %s' % (hasher, destfile, + digest, actual)) + logger.debug('Digest verified: %s', digest) + + def send_request(self, req): + """ + Send a standard library :class:`Request` to PyPI and return its + response. + + :param req: The request to send. + :return: The HTTP response from PyPI (a standard library HTTPResponse). + """ + handlers = [] + if self.password_handler: + handlers.append(self.password_handler) + if self.ssl_verifier: + handlers.append(self.ssl_verifier) + opener = build_opener(*handlers) + return opener.open(req) + + def encode_request(self, fields, files): + """ + Encode fields and files for posting to an HTTP server. + + :param fields: The fields to send as a list of (fieldname, value) + tuples. + :param files: The files to send as a list of (fieldname, filename, + file_bytes) tuple. + """ + # Adapted from packaging, which in turn was adapted from + # http://code.activestate.com/recipes/146306 + + parts = [] + boundary = self.boundary + for k, values in fields: + if not isinstance(values, (list, tuple)): + values = [values] + + for v in values: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"' % + k).encode('utf-8'), + b'', + v.encode('utf-8'))) + for key, filename, value in files: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)).encode('utf-8'), + b'', + value)) + + parts.extend((b'--' + boundary + b'--', b'')) + + body = b'\r\n'.join(parts) + ct = b'multipart/form-data; boundary=' + boundary + headers = { + 'Content-type': ct, + 'Content-length': str(len(body)) + } + return Request(self.url, body, headers) + + def search(self, terms, operator=None): + if isinstance(terms, string_types): + terms = {'name': terms} + rpc_proxy = ServerProxy(self.url, timeout=3.0) + try: + return rpc_proxy.search(terms, operator or 'and') + finally: + rpc_proxy('close')() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/locators.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/locators.py new file mode 100644 index 0000000..11d2636 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/locators.py @@ -0,0 +1,1292 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# + +import gzip +from io import BytesIO +import json +import logging +import os +import posixpath +import re +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import zlib + +from . import DistlibException +from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, + queue, quote, unescape, string_types, build_opener, + HTTPRedirectHandler as BaseRedirectHandler, text_type, + Request, HTTPError, URLError) +from .database import Distribution, DistributionPath, make_dist +from .metadata import Metadata, MetadataInvalidError +from .util import (cached_property, parse_credentials, ensure_slash, + split_filename, get_project_data, parse_requirement, + parse_name_and_version, ServerProxy, normalize_name) +from .version import get_scheme, UnsupportedVersionError +from .wheel import Wheel, is_compatible + +logger = logging.getLogger(__name__) + +HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)') +CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) +HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') +DEFAULT_INDEX = 'https://pypi.python.org/pypi' + +def get_all_distribution_names(url=None): + """ + Return all distribution names known by an index. + :param url: The URL of the index. + :return: A list of all known distribution names. + """ + if url is None: + url = DEFAULT_INDEX + client = ServerProxy(url, timeout=3.0) + try: + return client.list_packages() + finally: + client('close')() + +class RedirectHandler(BaseRedirectHandler): + """ + A class to work around a bug in some Python 3.2.x releases. + """ + # There's a bug in the base version for some 3.2.x + # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header + # returns e.g. /abc, it bails because it says the scheme '' + # is bogus, when actually it should use the request's + # URL for the scheme. See Python issue #13696. + def http_error_302(self, req, fp, code, msg, headers): + # Some servers (incorrectly) return multiple Location headers + # (so probably same goes for URI). Use first header. + newurl = None + for key in ('location', 'uri'): + if key in headers: + newurl = headers[key] + break + if newurl is None: # pragma: no cover + return + urlparts = urlparse(newurl) + if urlparts.scheme == '': + newurl = urljoin(req.get_full_url(), newurl) + if hasattr(headers, 'replace_header'): + headers.replace_header(key, newurl) + else: + headers[key] = newurl + return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, + headers) + + http_error_301 = http_error_303 = http_error_307 = http_error_302 + +class Locator(object): + """ + A base class for locators - things that locate distributions. + """ + source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') + binary_extensions = ('.egg', '.exe', '.whl') + excluded_extensions = ('.pdf',) + + # A list of tags indicating which wheels you want to match. The default + # value of None matches against the tags compatible with the running + # Python. If you want to match other values, set wheel_tags on a locator + # instance to a list of tuples (pyver, abi, arch) which you want to match. + wheel_tags = None + + downloadable_extensions = source_extensions + ('.whl',) + + def __init__(self, scheme='default'): + """ + Initialise an instance. + :param scheme: Because locators look for most recent versions, they + need to know the version scheme to use. This specifies + the current PEP-recommended scheme - use ``'legacy'`` + if you need to support existing distributions on PyPI. + """ + self._cache = {} + self.scheme = scheme + # Because of bugs in some of the handlers on some of the platforms, + # we use our own opener rather than just using urlopen. + self.opener = build_opener(RedirectHandler()) + # If get_project() is called from locate(), the matcher instance + # is set from the requirement passed to locate(). See issue #18 for + # why this can be useful to know. + self.matcher = None + self.errors = queue.Queue() + + def get_errors(self): + """ + Return any errors which have occurred. + """ + result = [] + while not self.errors.empty(): # pragma: no cover + try: + e = self.errors.get(False) + result.append(e) + except self.errors.Empty: + continue + self.errors.task_done() + return result + + def clear_errors(self): + """ + Clear any errors which may have been logged. + """ + # Just get the errors and throw them away + self.get_errors() + + def clear_cache(self): + self._cache.clear() + + def _get_scheme(self): + return self._scheme + + def _set_scheme(self, value): + self._scheme = value + + scheme = property(_get_scheme, _set_scheme) + + def _get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This should be implemented in subclasses. + + If called from a locate() request, self.matcher will be set to a + matcher for the requirement to satisfy, otherwise it will be None. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This calls _get_project to do all the work, and just implements a caching layer on top. + """ + if self._cache is None: # pragma: no cover + result = self._get_project(name) + elif name in self._cache: + result = self._cache[name] + else: + self.clear_errors() + result = self._get_project(name) + self._cache[name] = result + return result + + def score_url(self, url): + """ + Give an url a score which can be used to choose preferred URLs + for a given project release. + """ + t = urlparse(url) + basename = posixpath.basename(t.path) + compatible = True + is_wheel = basename.endswith('.whl') + is_downloadable = basename.endswith(self.downloadable_extensions) + if is_wheel: + compatible = is_compatible(Wheel(basename), self.wheel_tags) + return (t.scheme == 'https', 'pypi.python.org' in t.netloc, + is_downloadable, is_wheel, compatible, basename) + + def prefer_url(self, url1, url2): + """ + Choose one of two URLs where both are candidates for distribution + archives for the same version of a distribution (for example, + .tar.gz vs. zip). + + The current implementation favours https:// URLs over http://, archives + from PyPI over those from other locations, wheel compatibility (if a + wheel) and then the archive name. + """ + result = url2 + if url1: + s1 = self.score_url(url1) + s2 = self.score_url(url2) + if s1 > s2: + result = url1 + if result != url2: + logger.debug('Not replacing %r with %r', url1, url2) + else: + logger.debug('Replacing %r with %r', url1, url2) + return result + + def split_filename(self, filename, project_name): + """ + Attempt to split a filename in project name, version and Python version. + """ + return split_filename(filename, project_name) + + def convert_url_to_download_info(self, url, project_name): + """ + See if a URL is a candidate for a download URL for a project (the URL + has typically been scraped from an HTML page). + + If it is, a dictionary is returned with keys "name", "version", + "filename" and "url"; otherwise, None is returned. + """ + def same_project(name1, name2): + return normalize_name(name1) == normalize_name(name2) + + result = None + scheme, netloc, path, params, query, frag = urlparse(url) + if frag.lower().startswith('egg='): # pragma: no cover + logger.debug('%s: version hint in fragment: %r', + project_name, frag) + m = HASHER_HASH.match(frag) + if m: + algo, digest = m.groups() + else: + algo, digest = None, None + origpath = path + if path and path[-1] == '/': # pragma: no cover + path = path[:-1] + if path.endswith('.whl'): + try: + wheel = Wheel(path) + if is_compatible(wheel, self.wheel_tags): + if project_name is None: + include = True + else: + include = same_project(wheel.name, project_name) + if include: + result = { + 'name': wheel.name, + 'version': wheel.version, + 'filename': wheel.filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + 'python-version': ', '.join( + ['.'.join(list(v[2:])) for v in wheel.pyver]), + } + except Exception as e: # pragma: no cover + logger.warning('invalid path for wheel: %s', path) + elif not path.endswith(self.downloadable_extensions): # pragma: no cover + logger.debug('Not downloadable: %s', path) + else: # downloadable extension + path = filename = posixpath.basename(path) + for ext in self.downloadable_extensions: + if path.endswith(ext): + path = path[:-len(ext)] + t = self.split_filename(path, project_name) + if not t: # pragma: no cover + logger.debug('No match for project/version: %s', path) + else: + name, version, pyver = t + if not project_name or same_project(project_name, name): + result = { + 'name': name, + 'version': version, + 'filename': filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + #'packagetype': 'sdist', + } + if pyver: # pragma: no cover + result['python-version'] = pyver + break + if result and algo: + result['%s_digest' % algo] = digest + return result + + def _get_digest(self, info): + """ + Get a digest from a dictionary by looking at keys of the form + 'algo_digest'. + + Returns a 2-tuple (algo, digest) if found, else None. Currently + looks only for SHA256, then MD5. + """ + result = None + for algo in ('sha256', 'md5'): + key = '%s_digest' % algo + if key in info: + result = (algo, info[key]) + break + return result + + def _update_version_data(self, result, info): + """ + Update a result dictionary (the final result from _get_project) with a + dictionary for a specific version, which typically holds information + gleaned from a filename or URL for an archive for the distribution. + """ + name = info.pop('name') + version = info.pop('version') + if version in result: + dist = result[version] + md = dist.metadata + else: + dist = make_dist(name, version, scheme=self.scheme) + md = dist.metadata + dist.digest = digest = self._get_digest(info) + url = info['url'] + result['digests'][url] = digest + if md.source_url != info['url']: + md.source_url = self.prefer_url(md.source_url, url) + result['urls'].setdefault(version, set()).add(url) + dist.locator = self + result[version] = dist + + def locate(self, requirement, prereleases=False): + """ + Find the most recent distribution which matches the given + requirement. + + :param requirement: A requirement of the form 'foo (1.0)' or perhaps + 'foo (>= 1.0, < 2.0, != 1.3)' + :param prereleases: If ``True``, allow pre-release versions + to be located. Otherwise, pre-release versions + are not returned. + :return: A :class:`Distribution` instance, or ``None`` if no such + distribution could be located. + """ + result = None + r = parse_requirement(requirement) + if r is None: # pragma: no cover + raise DistlibException('Not a valid requirement: %r' % requirement) + scheme = get_scheme(self.scheme) + self.matcher = matcher = scheme.matcher(r.requirement) + logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) + versions = self.get_project(r.name) + if len(versions) > 2: # urls and digests keys are present + # sometimes, versions are invalid + slist = [] + vcls = matcher.version_class + for k in versions: + if k in ('urls', 'digests'): + continue + try: + if not matcher.match(k): + logger.debug('%s did not match %r', matcher, k) + else: + if prereleases or not vcls(k).is_prerelease: + slist.append(k) + else: + logger.debug('skipping pre-release ' + 'version %s of %s', k, matcher.name) + except Exception: # pragma: no cover + logger.warning('error matching %s with %r', matcher, k) + pass # slist.append(k) + if len(slist) > 1: + slist = sorted(slist, key=scheme.key) + if slist: + logger.debug('sorted list: %s', slist) + version = slist[-1] + result = versions[version] + if result: + if r.extras: + result.extras = r.extras + result.download_urls = versions.get('urls', {}).get(version, set()) + d = {} + sd = versions.get('digests', {}) + for url in result.download_urls: + if url in sd: # pragma: no cover + d[url] = sd[url] + result.digests = d + self.matcher = None + return result + + +class PyPIRPCLocator(Locator): + """ + This locator uses XML-RPC to locate distributions. It therefore + cannot be used with simple mirrors (that only mirror file content). + """ + def __init__(self, url, **kwargs): + """ + Initialise an instance. + + :param url: The URL to use for XML-RPC. + :param kwargs: Passed to the superclass constructor. + """ + super(PyPIRPCLocator, self).__init__(**kwargs) + self.base_url = url + self.client = ServerProxy(url, timeout=3.0) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + return set(self.client.list_packages()) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + versions = self.client.package_releases(name, True) + for v in versions: + urls = self.client.release_urls(name, v) + data = self.client.release_data(name, v) + metadata = Metadata(scheme=self.scheme) + metadata.name = data['name'] + metadata.version = data['version'] + metadata.license = data.get('license') + metadata.keywords = data.get('keywords', []) + metadata.summary = data.get('summary') + dist = Distribution(metadata) + if urls: + info = urls[0] + metadata.source_url = info['url'] + dist.digest = self._get_digest(info) + dist.locator = self + result[v] = dist + for info in urls: + url = info['url'] + digest = self._get_digest(info) + result['urls'].setdefault(v, set()).add(url) + result['digests'][url] = digest + return result + +class PyPIJSONLocator(Locator): + """ + This locator uses PyPI's JSON interface. It's very limited in functionality + and probably not worth using. + """ + def __init__(self, url, **kwargs): + super(PyPIJSONLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + url = urljoin(self.base_url, '%s/json' % quote(name)) + try: + resp = self.opener.open(url) + data = resp.read().decode() # for now + d = json.loads(data) + md = Metadata(scheme=self.scheme) + data = d['info'] + md.name = data['name'] + md.version = data['version'] + md.license = data.get('license') + md.keywords = data.get('keywords', []) + md.summary = data.get('summary') + dist = Distribution(md) + dist.locator = self + urls = d['urls'] + result[md.version] = dist + for info in d['urls']: + url = info['url'] + dist.download_urls.add(url) + dist.digests[url] = self._get_digest(info) + result['urls'].setdefault(md.version, set()).add(url) + result['digests'][url] = self._get_digest(info) + # Now get other releases + for version, infos in d['releases'].items(): + if version == md.version: + continue # already done + omd = Metadata(scheme=self.scheme) + omd.name = md.name + omd.version = version + odist = Distribution(omd) + odist.locator = self + result[version] = odist + for info in infos: + url = info['url'] + odist.download_urls.add(url) + odist.digests[url] = self._get_digest(info) + result['urls'].setdefault(version, set()).add(url) + result['digests'][url] = self._get_digest(info) +# for info in urls: +# md.source_url = info['url'] +# dist.digest = self._get_digest(info) +# dist.locator = self +# for info in urls: +# url = info['url'] +# result['urls'].setdefault(md.version, set()).add(url) +# result['digests'][url] = self._get_digest(info) + except Exception as e: + self.errors.put(text_type(e)) + logger.exception('JSON fetch failed: %s', e) + return result + + +class Page(object): + """ + This class represents a scraped HTML page. + """ + # The following slightly hairy-looking regex just looks for the contents of + # an anchor link, which has an attribute "href" either immediately preceded + # or immediately followed by a "rel" attribute. The attribute values can be + # declared with double quotes, single quotes or no quotes - which leads to + # the length of the expression. + _href = re.compile(""" +(rel\\s*=\\s*(?:"(?P<rel1>[^"]*)"|'(?P<rel2>[^']*)'|(?P<rel3>[^>\\s\n]*))\\s+)? +href\\s*=\\s*(?:"(?P<url1>[^"]*)"|'(?P<url2>[^']*)'|(?P<url3>[^>\\s\n]*)) +(\\s+rel\\s*=\\s*(?:"(?P<rel4>[^"]*)"|'(?P<rel5>[^']*)'|(?P<rel6>[^>\\s\n]*)))? +""", re.I | re.S | re.X) + _base = re.compile(r"""<base\s+href\s*=\s*['"]?([^'">]+)""", re.I | re.S) + + def __init__(self, data, url): + """ + Initialise an instance with the Unicode page contents and the URL they + came from. + """ + self.data = data + self.base_url = self.url = url + m = self._base.search(self.data) + if m: + self.base_url = m.group(1) + + _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + @cached_property + def links(self): + """ + Return the URLs of all the links on a page together with information + about their "rel" attribute, for determining which ones to treat as + downloads and which ones to queue for further scraping. + """ + def clean(url): + "Tidy up an URL." + scheme, netloc, path, params, query, frag = urlparse(url) + return urlunparse((scheme, netloc, quote(path), + params, query, frag)) + + result = set() + for match in self._href.finditer(self.data): + d = match.groupdict('') + rel = (d['rel1'] or d['rel2'] or d['rel3'] or + d['rel4'] or d['rel5'] or d['rel6']) + url = d['url1'] or d['url2'] or d['url3'] + url = urljoin(self.base_url, url) + url = unescape(url) + url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) + result.add((url, rel)) + # We sort the result, hoping to bring the most recent versions + # to the front + result = sorted(result, key=lambda t: t[0], reverse=True) + return result + + +class SimpleScrapingLocator(Locator): + """ + A locator which scrapes HTML pages to locate downloads for a distribution. + This runs multiple threads to do the I/O; performance is at least as good + as pip's PackageFinder, which works in an analogous fashion. + """ + + # These are used to deal with various Content-Encoding schemes. + decoders = { + 'deflate': zlib.decompress, + 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(), + 'none': lambda b: b, + } + + def __init__(self, url, timeout=None, num_workers=10, **kwargs): + """ + Initialise an instance. + :param url: The root URL to use for scraping. + :param timeout: The timeout, in seconds, to be applied to requests. + This defaults to ``None`` (no timeout specified). + :param num_workers: The number of worker threads you want to do I/O, + This defaults to 10. + :param kwargs: Passed to the superclass. + """ + super(SimpleScrapingLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + self.timeout = timeout + self._page_cache = {} + self._seen = set() + self._to_fetch = queue.Queue() + self._bad_hosts = set() + self.skip_externals = False + self.num_workers = num_workers + self._lock = threading.RLock() + # See issue #45: we need to be resilient when the locator is used + # in a thread, e.g. with concurrent.futures. We can't use self._lock + # as it is for coordinating our internal threads - the ones created + # in _prepare_threads. + self._gplock = threading.RLock() + + def _prepare_threads(self): + """ + Threads are created only when get_project is called, and terminate + before it returns. They are there primarily to parallelise I/O (i.e. + fetching web pages). + """ + self._threads = [] + for i in range(self.num_workers): + t = threading.Thread(target=self._fetch) + t.setDaemon(True) + t.start() + self._threads.append(t) + + def _wait_threads(self): + """ + Tell all the threads to terminate (by sending a sentinel value) and + wait for them to do so. + """ + # Note that you need two loops, since you can't say which + # thread will get each sentinel + for t in self._threads: + self._to_fetch.put(None) # sentinel + for t in self._threads: + t.join() + self._threads = [] + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + with self._gplock: + self.result = result + self.project_name = name + url = urljoin(self.base_url, '%s/' % quote(name)) + self._seen.clear() + self._page_cache.clear() + self._prepare_threads() + try: + logger.debug('Queueing %s', url) + self._to_fetch.put(url) + self._to_fetch.join() + finally: + self._wait_threads() + del self.result + return result + + platform_dependent = re.compile(r'\b(linux-(i\d86|x86_64|arm\w+)|' + r'win(32|-amd64)|macosx-?\d+)\b', re.I) + + def _is_platform_dependent(self, url): + """ + Does an URL refer to a platform-specific download? + """ + return self.platform_dependent.search(url) + + def _process_download(self, url): + """ + See if an URL is a suitable download for a project. + + If it is, register information in the result dictionary (for + _get_project) about the specific version it's for. + + Note that the return value isn't actually used other than as a boolean + value. + """ + if self._is_platform_dependent(url): + info = None + else: + info = self.convert_url_to_download_info(url, self.project_name) + logger.debug('process_download: %s -> %s', url, info) + if info: + with self._lock: # needed because self.result is shared + self._update_version_data(self.result, info) + return info + + def _should_queue(self, link, referrer, rel): + """ + Determine whether a link URL from a referring page and with a + particular "rel" attribute should be queued for scraping. + """ + scheme, netloc, path, _, _, _ = urlparse(link) + if path.endswith(self.source_extensions + self.binary_extensions + + self.excluded_extensions): + result = False + elif self.skip_externals and not link.startswith(self.base_url): + result = False + elif not referrer.startswith(self.base_url): + result = False + elif rel not in ('homepage', 'download'): + result = False + elif scheme not in ('http', 'https', 'ftp'): + result = False + elif self._is_platform_dependent(link): + result = False + else: + host = netloc.split(':', 1)[0] + if host.lower() == 'localhost': + result = False + else: + result = True + logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, + referrer, result) + return result + + def _fetch(self): + """ + Get a URL to fetch from the work queue, get the HTML page, examine its + links for download candidates and candidates for further scraping. + + This is a handy method to run in a thread. + """ + while True: + url = self._to_fetch.get() + try: + if url: + page = self.get_page(url) + if page is None: # e.g. after an error + continue + for link, rel in page.links: + if link not in self._seen: + try: + self._seen.add(link) + if (not self._process_download(link) and + self._should_queue(link, url, rel)): + logger.debug('Queueing %s from %s', link, url) + self._to_fetch.put(link) + except MetadataInvalidError: # e.g. invalid versions + pass + except Exception as e: # pragma: no cover + self.errors.put(text_type(e)) + finally: + # always do this, to avoid hangs :-) + self._to_fetch.task_done() + if not url: + #logger.debug('Sentinel seen, quitting.') + break + + def get_page(self, url): + """ + Get the HTML for an URL, possibly from an in-memory cache. + + XXX TODO Note: this cache is never actually cleared. It's assumed that + the data won't get stale over the lifetime of a locator instance (not + necessarily true for the default_locator). + """ + # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api + scheme, netloc, path, _, _, _ = urlparse(url) + if scheme == 'file' and os.path.isdir(url2pathname(path)): + url = urljoin(ensure_slash(url), 'index.html') + + if url in self._page_cache: + result = self._page_cache[url] + logger.debug('Returning %s from cache: %s', url, result) + else: + host = netloc.split(':', 1)[0] + result = None + if host in self._bad_hosts: + logger.debug('Skipping %s due to bad host %s', url, host) + else: + req = Request(url, headers={'Accept-encoding': 'identity'}) + try: + logger.debug('Fetching %s', url) + resp = self.opener.open(req, timeout=self.timeout) + logger.debug('Fetched %s', url) + headers = resp.info() + content_type = headers.get('Content-Type', '') + if HTML_CONTENT_TYPE.match(content_type): + final_url = resp.geturl() + data = resp.read() + encoding = headers.get('Content-Encoding') + if encoding: + decoder = self.decoders[encoding] # fail if not found + data = decoder(data) + encoding = 'utf-8' + m = CHARSET.search(content_type) + if m: + encoding = m.group(1) + try: + data = data.decode(encoding) + except UnicodeError: # pragma: no cover + data = data.decode('latin-1') # fallback + result = Page(data, final_url) + self._page_cache[final_url] = result + except HTTPError as e: + if e.code != 404: + logger.exception('Fetch failed: %s: %s', url, e) + except URLError as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + with self._lock: + self._bad_hosts.add(host) + except Exception as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + finally: + self._page_cache[url] = result # even if None (failure) + return result + + _distname_re = re.compile('<a href=[^>]*>([^<]+)<') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + page = self.get_page(self.base_url) + if not page: + raise DistlibException('Unable to get %s' % self.base_url) + for match in self._distname_re.finditer(page.data): + result.add(match.group(1)) + return result + +class DirectoryLocator(Locator): + """ + This class locates distributions in a directory tree. + """ + + def __init__(self, path, **kwargs): + """ + Initialise an instance. + :param path: The root of the directory tree to search. + :param kwargs: Passed to the superclass constructor, + except for: + * recursive - if True (the default), subdirectories are + recursed into. If False, only the top-level directory + is searched, + """ + self.recursive = kwargs.pop('recursive', True) + super(DirectoryLocator, self).__init__(**kwargs) + path = os.path.abspath(path) + if not os.path.isdir(path): # pragma: no cover + raise DistlibException('Not a directory: %r' % path) + self.base_dir = path + + def should_include(self, filename, parent): + """ + Should a filename be considered as a candidate for a distribution + archive? As well as the filename, the directory which contains it + is provided, though not used by the current implementation. + """ + return filename.endswith(self.downloadable_extensions) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, name) + if info: + self._update_version_data(result, info) + if not self.recursive: + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, None) + if info: + result.add(info['name']) + if not self.recursive: + break + return result + +class JSONLocator(Locator): + """ + This locator uses special extended metadata (not available on PyPI) and is + the basis of performant dependency resolution in distlib. Other locators + require archive downloads before dependencies can be determined! As you + might imagine, that can be slow. + """ + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + data = get_project_data(name) + if data: + for info in data.get('files', []): + if info['ptype'] != 'sdist' or info['pyversion'] != 'source': + continue + # We don't store summary in project metadata as it makes + # the data bigger for no benefit during dependency + # resolution + dist = make_dist(data['name'], info['version'], + summary=data.get('summary', + 'Placeholder for summary'), + scheme=self.scheme) + md = dist.metadata + md.source_url = info['url'] + # TODO SHA256 digest + if 'digest' in info and info['digest']: + dist.digest = ('md5', info['digest']) + md.dependencies = info.get('requirements', {}) + dist.exports = info.get('exports', {}) + result[dist.version] = dist + result['urls'].setdefault(dist.version, set()).add(info['url']) + return result + +class DistPathLocator(Locator): + """ + This locator finds installed distributions in a path. It can be useful for + adding to an :class:`AggregatingLocator`. + """ + def __init__(self, distpath, **kwargs): + """ + Initialise an instance. + + :param distpath: A :class:`DistributionPath` instance to search. + """ + super(DistPathLocator, self).__init__(**kwargs) + assert isinstance(distpath, DistributionPath) + self.distpath = distpath + + def _get_project(self, name): + dist = self.distpath.get_distribution(name) + if dist is None: + result = {'urls': {}, 'digests': {}} + else: + result = { + dist.version: dist, + 'urls': {dist.version: set([dist.source_url])}, + 'digests': {dist.version: set([None])} + } + return result + + +class AggregatingLocator(Locator): + """ + This class allows you to chain and/or merge a list of locators. + """ + def __init__(self, *locators, **kwargs): + """ + Initialise an instance. + + :param locators: The list of locators to search. + :param kwargs: Passed to the superclass constructor, + except for: + * merge - if False (the default), the first successful + search from any of the locators is returned. If True, + the results from all locators are merged (this can be + slow). + """ + self.merge = kwargs.pop('merge', False) + self.locators = locators + super(AggregatingLocator, self).__init__(**kwargs) + + def clear_cache(self): + super(AggregatingLocator, self).clear_cache() + for locator in self.locators: + locator.clear_cache() + + def _set_scheme(self, value): + self._scheme = value + for locator in self.locators: + locator.scheme = value + + scheme = property(Locator.scheme.fget, _set_scheme) + + def _get_project(self, name): + result = {} + for locator in self.locators: + d = locator.get_project(name) + if d: + if self.merge: + files = result.get('urls', {}) + digests = result.get('digests', {}) + # next line could overwrite result['urls'], result['digests'] + result.update(d) + df = result.get('urls') + if files and df: + for k, v in files.items(): + if k in df: + df[k] |= v + else: + df[k] = v + dd = result.get('digests') + if digests and dd: + dd.update(digests) + else: + # See issue #18. If any dists are found and we're looking + # for specific constraints, we only return something if + # a match is found. For example, if a DirectoryLocator + # returns just foo (1.0) while we're looking for + # foo (>= 2.0), we'll pretend there was nothing there so + # that subsequent locators can be queried. Otherwise we + # would just return foo (1.0) which would then lead to a + # failure to find foo (>= 2.0), because other locators + # weren't searched. Note that this only matters when + # merge=False. + if self.matcher is None: + found = True + else: + found = False + for k in d: + if self.matcher.match(k): + found = True + break + if found: + result = d + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for locator in self.locators: + try: + result |= locator.get_distribution_names() + except NotImplementedError: + pass + return result + + +# We use a legacy scheme simply because most of the dists on PyPI use legacy +# versions which don't conform to PEP 426 / PEP 440. +default_locator = AggregatingLocator( + JSONLocator(), + SimpleScrapingLocator('https://pypi.python.org/simple/', + timeout=3.0), + scheme='legacy') + +locate = default_locator.locate + +NAME_VERSION_RE = re.compile(r'(?P<name>[\w-]+)\s*' + r'\(\s*(==\s*)?(?P<ver>[^)]+)\)$') + +class DependencyFinder(object): + """ + Locate dependencies for distributions. + """ + + def __init__(self, locator=None): + """ + Initialise an instance, using the specified locator + to locate distributions. + """ + self.locator = locator or default_locator + self.scheme = get_scheme(self.locator.scheme) + + def add_distribution(self, dist): + """ + Add a distribution to the finder. This will update internal information + about who provides what. + :param dist: The distribution to add. + """ + logger.debug('adding distribution %s', dist) + name = dist.key + self.dists_by_name[name] = dist + self.dists[(name, dist.version)] = dist + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + self.provided.setdefault(name, set()).add((version, dist)) + + def remove_distribution(self, dist): + """ + Remove a distribution from the finder. This will update internal + information about who provides what. + :param dist: The distribution to remove. + """ + logger.debug('removing distribution %s', dist) + name = dist.key + del self.dists_by_name[name] + del self.dists[(name, dist.version)] + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Remove from provided: %s, %s, %s', name, version, dist) + s = self.provided[name] + s.remove((version, dist)) + if not s: + del self.provided[name] + + def get_matcher(self, reqt): + """ + Get a version matcher for a requirement. + :param reqt: The requirement + :type reqt: str + :return: A version matcher (an instance of + :class:`distlib.version.Matcher`). + """ + try: + matcher = self.scheme.matcher(reqt) + except UnsupportedVersionError: # pragma: no cover + # XXX compat-mode if cannot read the version + name = reqt.split()[0] + matcher = self.scheme.matcher(name) + return matcher + + def find_providers(self, reqt): + """ + Find the distributions which can fulfill a requirement. + + :param reqt: The requirement. + :type reqt: str + :return: A set of distribution which can fulfill the requirement. + """ + matcher = self.get_matcher(reqt) + name = matcher.key # case-insensitive + result = set() + provided = self.provided + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + result.add(provider) + break + return result + + def try_to_replace(self, provider, other, problems): + """ + Attempt to replace one provider with another. This is typically used + when resolving dependencies from multiple sources, e.g. A requires + (B >= 1.0) while C requires (B >= 1.1). + + For successful replacement, ``provider`` must meet all the requirements + which ``other`` fulfills. + + :param provider: The provider we are trying to replace with. + :param other: The provider we're trying to replace. + :param problems: If False is returned, this will contain what + problems prevented replacement. This is currently + a tuple of the literal string 'cantreplace', + ``provider``, ``other`` and the set of requirements + that ``provider`` couldn't fulfill. + :return: True if we can replace ``other`` with ``provider``, else + False. + """ + rlist = self.reqts[other] + unmatched = set() + for s in rlist: + matcher = self.get_matcher(s) + if not matcher.match(provider.version): + unmatched.add(s) + if unmatched: + # can't replace other with provider + problems.add(('cantreplace', provider, other, + frozenset(unmatched))) + result = False + else: + # can replace other with provider + self.remove_distribution(other) + del self.reqts[other] + for s in rlist: + self.reqts.setdefault(provider, set()).add(s) + self.add_distribution(provider) + result = True + return result + + def find(self, requirement, meta_extras=None, prereleases=False): + """ + Find a distribution and all distributions it depends on. + + :param requirement: The requirement specifying the distribution to + find, or a Distribution instance. + :param meta_extras: A list of meta extras such as :test:, :build: and + so on. + :param prereleases: If ``True``, allow pre-release versions to be + returned - otherwise, don't return prereleases + unless they're all that's available. + + Return a set of :class:`Distribution` instances and a set of + problems. + + The distributions returned should be such that they have the + :attr:`required` attribute set to ``True`` if they were + from the ``requirement`` passed to ``find()``, and they have the + :attr:`build_time_dependency` attribute set to ``True`` unless they + are post-installation dependencies of the ``requirement``. + + The problems should be a tuple consisting of the string + ``'unsatisfied'`` and the requirement which couldn't be satisfied + by any distribution known to the locator. + """ + + self.provided = {} + self.dists = {} + self.dists_by_name = {} + self.reqts = {} + + meta_extras = set(meta_extras or []) + if ':*:' in meta_extras: + meta_extras.remove(':*:') + # :meta: and :run: are implicitly included + meta_extras |= set([':test:', ':build:', ':dev:']) + + if isinstance(requirement, Distribution): + dist = odist = requirement + logger.debug('passed %s as requirement', odist) + else: + dist = odist = self.locator.locate(requirement, + prereleases=prereleases) + if dist is None: + raise DistlibException('Unable to locate %r' % requirement) + logger.debug('located %s', odist) + dist.requested = True + problems = set() + todo = set([dist]) + install_dists = set([odist]) + while todo: + dist = todo.pop() + name = dist.key # case-insensitive + if name not in self.dists_by_name: + self.add_distribution(dist) + else: + #import pdb; pdb.set_trace() + other = self.dists_by_name[name] + if other != dist: + self.try_to_replace(dist, other, problems) + + ireqts = dist.run_requires | dist.meta_requires + sreqts = dist.build_requires + ereqts = set() + if meta_extras and dist in install_dists: + for key in ('test', 'build', 'dev'): + e = ':%s:' % key + if e in meta_extras: + ereqts |= getattr(dist, '%s_requires' % key) + all_reqts = ireqts | sreqts | ereqts + for r in all_reqts: + providers = self.find_providers(r) + if not providers: + logger.debug('No providers found for %r', r) + provider = self.locator.locate(r, prereleases=prereleases) + # If no provider is found and we didn't consider + # prereleases, consider them now. + if provider is None and not prereleases: + provider = self.locator.locate(r, prereleases=True) + if provider is None: + logger.debug('Cannot satisfy %r', r) + problems.add(('unsatisfied', r)) + else: + n, v = provider.key, provider.version + if (n, v) not in self.dists: + todo.add(provider) + providers.add(provider) + if r in ireqts and dist in install_dists: + install_dists.add(provider) + logger.debug('Adding %s to install_dists', + provider.name_and_version) + for p in providers: + name = p.key + if name not in self.dists_by_name: + self.reqts.setdefault(p, set()).add(r) + else: + other = self.dists_by_name[name] + if other != p: + # see if other can be replaced by p + self.try_to_replace(p, other, problems) + + dists = set(self.dists.values()) + for dist in dists: + dist.build_time_dependency = dist not in install_dists + if dist.build_time_dependency: + logger.debug('%s is a build-time dependency only.', + dist.name_and_version) + logger.debug('find done for %s', odist) + return dists, problems diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/manifest.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/manifest.py new file mode 100644 index 0000000..ca0fe44 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/manifest.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Class representing the list of files in a distribution. + +Equivalent to distutils.filelist, but fixes some problems. +""" +import fnmatch +import logging +import os +import re +import sys + +from . import DistlibException +from .compat import fsdecode +from .util import convert_path + + +__all__ = ['Manifest'] + +logger = logging.getLogger(__name__) + +# a \ followed by some spaces + EOL +_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M) +_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) + +# +# Due to the different results returned by fnmatch.translate, we need +# to do slightly different processing for Python 2.7 and 3.2 ... this needed +# to be brought in for Python 3.6 onwards. +# +_PYTHON_VERSION = sys.version_info[:2] + +class Manifest(object): + """A list of files built by on exploring the filesystem and filtered by + applying various patterns to what we find there. + """ + + def __init__(self, base=None): + """ + Initialise an instance. + + :param base: The base directory to explore under. + """ + self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) + self.prefix = self.base + os.sep + self.allfiles = None + self.files = set() + + # + # Public API + # + + def findall(self): + """Find all files under the base and set ``allfiles`` to the absolute + pathnames of files found. + """ + from stat import S_ISREG, S_ISDIR, S_ISLNK + + self.allfiles = allfiles = [] + root = self.base + stack = [root] + pop = stack.pop + push = stack.append + + while stack: + root = pop() + names = os.listdir(root) + + for name in names: + fullname = os.path.join(root, name) + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat.st_mode + if S_ISREG(mode): + allfiles.append(fsdecode(fullname)) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push(fullname) + + def add(self, item): + """ + Add a file to the manifest. + + :param item: The pathname to add. This can be relative to the base. + """ + if not item.startswith(self.prefix): + item = os.path.join(self.base, item) + self.files.add(os.path.normpath(item)) + + def add_many(self, items): + """ + Add a list of files to the manifest. + + :param items: The pathnames to add. These can be relative to the base. + """ + for item in items: + self.add(item) + + def sorted(self, wantdirs=False): + """ + Return sorted files in directory order + """ + + def add_dir(dirs, d): + dirs.add(d) + logger.debug('add_dir added %s', d) + if d != self.base: + parent, _ = os.path.split(d) + assert parent not in ('', '/') + add_dir(dirs, parent) + + result = set(self.files) # make a copy! + if wantdirs: + dirs = set() + for f in result: + add_dir(dirs, os.path.dirname(f)) + result |= dirs + return [os.path.join(*path_tuple) for path_tuple in + sorted(os.path.split(path) for path in result)] + + def clear(self): + """Clear all collected files.""" + self.files = set() + self.allfiles = [] + + def process_directive(self, directive): + """ + Process a directive which either adds some files from ``allfiles`` to + ``files``, or removes some files from ``files``. + + :param directive: The directive to process. This should be in a format + compatible with distutils ``MANIFEST.in`` files: + + http://docs.python.org/distutils/sourcedist.html#commands + """ + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dirpattern). + action, patterns, thedir, dirpattern = self._parse_directive(directive) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=True): + logger.warning('no files found matching %r', pattern) + + elif action == 'exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=True) + #if not found: + # logger.warning('no previously-included files ' + # 'found matching %r', pattern) + + elif action == 'global-include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=False): + logger.warning('no files found matching %r ' + 'anywhere in distribution', pattern) + + elif action == 'global-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=False) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found anywhere in ' + # 'distribution', pattern) + + elif action == 'recursive-include': + for pattern in patterns: + if not self._include_pattern(pattern, prefix=thedir): + logger.warning('no files found matching %r ' + 'under directory %r', pattern, thedir) + + elif action == 'recursive-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, prefix=thedir) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found under directory %r', + # pattern, thedir) + + elif action == 'graft': + if not self._include_pattern(None, prefix=dirpattern): + logger.warning('no directories found matching %r', + dirpattern) + + elif action == 'prune': + if not self._exclude_pattern(None, prefix=dirpattern): + logger.warning('no previously-included directories found ' + 'matching %r', dirpattern) + else: # pragma: no cover + # This should never happen, as it should be caught in + # _parse_template_line + raise DistlibException( + 'invalid action %r' % action) + + # + # Private API + # + + def _parse_directive(self, directive): + """ + Validate a directive. + :param directive: The directive to validate. + :return: A tuple of action, patterns, thedir, dir_patterns + """ + words = directive.split() + if len(words) == 1 and words[0] not in ('include', 'exclude', + 'global-include', + 'global-exclude', + 'recursive-include', + 'recursive-exclude', + 'graft', 'prune'): + # no action given, let's use the default 'include' + words.insert(0, 'include') + + action = words[0] + patterns = thedir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistlibException( + '%r expects <pattern1> <pattern2> ...' % action) + + patterns = [convert_path(word) for word in words[1:]] + + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistlibException( + '%r expects <dir> <pattern1> <pattern2> ...' % action) + + thedir = convert_path(words[1]) + patterns = [convert_path(word) for word in words[2:]] + + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistlibException( + '%r expects a single <dir_pattern>' % action) + + dir_pattern = convert_path(words[1]) + + else: + raise DistlibException('unknown action %r' % action) + + return action, patterns, thedir, dir_pattern + + def _include_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. + + Patterns are not quite the same as implemented by the 'fnmatch' + module: '*' and '?' match non-special characters, where "special" + is platform-dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return True if files are found. + """ + # XXX docstring lying about what the special chars are? + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.files.add(name) + found = True + return found + + def _exclude_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. + + Other parameters are the same as for 'include_pattern()', above. + The list 'self.files' is modified in place. Return True if files are + found. + + This API is public to allow e.g. exclusion of SCM subdirs, e.g. when + packaging source distributions + """ + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + for f in list(self.files): + if pattern_re.search(f): + self.files.remove(f) + found = True + return found + + def _translate_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Translate a shell-like wildcard pattern to a compiled regular + expression. + + Return the compiled regex. If 'is_regex' true, + then 'pattern' is directly compiled to a regex (if it's a string) + or just returned as-is (assumes it's a regex object). + """ + if is_regex: + if isinstance(pattern, str): + return re.compile(pattern) + else: + return pattern + + if _PYTHON_VERSION > (3, 2): + # ditch start and end characters + start, _, end = self._glob_to_re('_').partition('_') + + if pattern: + pattern_re = self._glob_to_re(pattern) + if _PYTHON_VERSION > (3, 2): + assert pattern_re.startswith(start) and pattern_re.endswith(end) + else: + pattern_re = '' + + base = re.escape(os.path.join(self.base, '')) + if prefix is not None: + # ditch end of pattern character + if _PYTHON_VERSION <= (3, 2): + empty_pattern = self._glob_to_re('') + prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] + else: + prefix_re = self._glob_to_re(prefix) + assert prefix_re.startswith(start) and prefix_re.endswith(end) + prefix_re = prefix_re[len(start): len(prefix_re) - len(end)] + sep = os.sep + if os.sep == '\\': + sep = r'\\' + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + sep.join((prefix_re, + '.*' + pattern_re)) + else: + pattern_re = pattern_re[len(start): len(pattern_re) - len(end)] + pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep, + pattern_re, end) + else: # no prefix -- respect anchor flag + if anchor: + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + pattern_re + else: + pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):]) + + return re.compile(pattern_re) + + def _glob_to_re(self, pattern): + """Translate a shell-like glob pattern to a regular expression. + + Return a string containing the regex. Differs from + 'fnmatch.translate()' in that '*' does not match "special characters" + (which are platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', escaped, pattern_re) + return pattern_re diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/markers.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/markers.py new file mode 100644 index 0000000..ee1f3e2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/markers.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Parser for the environment markers micro-language defined in PEP 508. +""" + +# Note: In PEP 345, the micro-language was Python compatible, so the ast +# module could be used to parse it. However, PEP 508 introduced operators such +# as ~= and === which aren't in Python, necessitating a different approach. + +import os +import sys +import platform +import re + +from .compat import python_implementation, urlparse, string_types +from .util import in_venv, parse_marker + +__all__ = ['interpret'] + +def _is_literal(o): + if not isinstance(o, string_types) or not o: + return False + return o[0] in '\'"' + +class Evaluator(object): + """ + This class is used to evaluate marker expessions. + """ + + operations = { + '==': lambda x, y: x == y, + '===': lambda x, y: x == y, + '~=': lambda x, y: x == y or x > y, + '!=': lambda x, y: x != y, + '<': lambda x, y: x < y, + '<=': lambda x, y: x == y or x < y, + '>': lambda x, y: x > y, + '>=': lambda x, y: x == y or x > y, + 'and': lambda x, y: x and y, + 'or': lambda x, y: x or y, + 'in': lambda x, y: x in y, + 'not in': lambda x, y: x not in y, + } + + def evaluate(self, expr, context): + """ + Evaluate a marker expression returned by the :func:`parse_requirement` + function in the specified context. + """ + if isinstance(expr, string_types): + if expr[0] in '\'"': + result = expr[1:-1] + else: + if expr not in context: + raise SyntaxError('unknown variable: %s' % expr) + result = context[expr] + else: + assert isinstance(expr, dict) + op = expr['op'] + if op not in self.operations: + raise NotImplementedError('op not implemented: %s' % op) + elhs = expr['lhs'] + erhs = expr['rhs'] + if _is_literal(expr['lhs']) and _is_literal(expr['rhs']): + raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs)) + + lhs = self.evaluate(elhs, context) + rhs = self.evaluate(erhs, context) + result = self.operations[op](lhs, rhs) + return result + +def default_context(): + def format_full_version(info): + version = '%s.%s.%s' % (info.major, info.minor, info.micro) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + if hasattr(sys, 'implementation'): + implementation_version = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + implementation_version = '0' + implementation_name = '' + + result = { + 'implementation_name': implementation_name, + 'implementation_version': implementation_version, + 'os_name': os.name, + 'platform_machine': platform.machine(), + 'platform_python_implementation': platform.python_implementation(), + 'platform_release': platform.release(), + 'platform_system': platform.system(), + 'platform_version': platform.version(), + 'platform_in_venv': str(in_venv()), + 'python_full_version': platform.python_version(), + 'python_version': platform.python_version()[:3], + 'sys_platform': sys.platform, + } + return result + +DEFAULT_CONTEXT = default_context() +del default_context + +evaluator = Evaluator() + +def interpret(marker, execution_context=None): + """ + Interpret a marker and return a result depending on environment. + + :param marker: The marker to interpret. + :type marker: str + :param execution_context: The context used for name lookup. + :type execution_context: mapping + """ + try: + expr, rest = parse_marker(marker) + except Exception as e: + raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e)) + if rest and rest[0] != '#': + raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest)) + context = dict(DEFAULT_CONTEXT) + if execution_context: + context.update(execution_context) + return evaluator.evaluate(expr, context) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/metadata.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/metadata.py new file mode 100644 index 0000000..6d6470f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/metadata.py @@ -0,0 +1,1091 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Implementation of the Metadata for Python packages PEPs. + +Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental). +""" +from __future__ import unicode_literals + +import codecs +from email import message_from_file +import json +import logging +import re + + +from . import DistlibException, __version__ +from .compat import StringIO, string_types, text_type +from .markers import interpret +from .util import extract_by_key, get_extras +from .version import get_scheme, PEP440_VERSION_RE + +logger = logging.getLogger(__name__) + + +class MetadataMissingError(DistlibException): + """A required metadata is missing""" + + +class MetadataConflictError(DistlibException): + """Attempt to read or write metadata fields that are conflictual.""" + + +class MetadataUnrecognizedVersionError(DistlibException): + """Unknown metadata version number.""" + + +class MetadataInvalidError(DistlibException): + """A metadata value is invalid""" + +# public API of this module +__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] + +# Encoding used for the PKG-INFO files +PKG_INFO_ENCODING = 'utf-8' + +# preferred version. Hopefully will be changed +# to 1.2 once PEP 345 is supported everywhere +PKG_INFO_PREFERRED_VERSION = '1.1' + +_LINE_PREFIX_1_2 = re.compile('\n \\|') +_LINE_PREFIX_PRE_1_2 = re.compile('\n ') +_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License') + +_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License', 'Classifier', 'Download-URL', 'Obsoletes', + 'Provides', 'Requires') + +_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', + 'Download-URL') + +_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External') + +_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', + 'Obsoletes-Dist', 'Requires-External', 'Maintainer', + 'Maintainer-email', 'Project-URL') + +_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External', 'Private-Version', + 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension', + 'Provides-Extra') + +_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', + 'Setup-Requires-Dist', 'Extension') + +_566_FIELDS = _426_FIELDS + ('Description-Content-Type',) + +_566_MARKERS = ('Description-Content-Type',) + +_ALL_FIELDS = set() +_ALL_FIELDS.update(_241_FIELDS) +_ALL_FIELDS.update(_314_FIELDS) +_ALL_FIELDS.update(_345_FIELDS) +_ALL_FIELDS.update(_426_FIELDS) +_ALL_FIELDS.update(_566_FIELDS) + +EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') + + +def _version2fieldlist(version): + if version == '1.0': + return _241_FIELDS + elif version == '1.1': + return _314_FIELDS + elif version == '1.2': + return _345_FIELDS + elif version in ('1.3', '2.1'): + return _345_FIELDS + _566_FIELDS + elif version == '2.0': + return _426_FIELDS + raise MetadataUnrecognizedVersionError(version) + + +def _best_version(fields): + """Detect the best version depending on the fields used.""" + def _has_marker(keys, markers): + for marker in markers: + if marker in keys: + return True + return False + + keys = [] + for key, value in fields.items(): + if value in ([], 'UNKNOWN', None): + continue + keys.append(key) + + possible_versions = ['1.0', '1.1', '1.2', '1.3', '2.0', '2.1'] + + # first let's try to see if a field is not part of one of the version + for key in keys: + if key not in _241_FIELDS and '1.0' in possible_versions: + possible_versions.remove('1.0') + logger.debug('Removed 1.0 due to %s', key) + if key not in _314_FIELDS and '1.1' in possible_versions: + possible_versions.remove('1.1') + logger.debug('Removed 1.1 due to %s', key) + if key not in _345_FIELDS and '1.2' in possible_versions: + possible_versions.remove('1.2') + logger.debug('Removed 1.2 due to %s', key) + if key not in _566_FIELDS and '1.3' in possible_versions: + possible_versions.remove('1.3') + logger.debug('Removed 1.3 due to %s', key) + if key not in _566_FIELDS and '2.1' in possible_versions: + if key != 'Description': # In 2.1, description allowed after headers + possible_versions.remove('2.1') + logger.debug('Removed 2.1 due to %s', key) + if key not in _426_FIELDS and '2.0' in possible_versions: + possible_versions.remove('2.0') + logger.debug('Removed 2.0 due to %s', key) + + # possible_version contains qualified versions + if len(possible_versions) == 1: + return possible_versions[0] # found ! + elif len(possible_versions) == 0: + logger.debug('Out of options - unknown metadata set: %s', fields) + raise MetadataConflictError('Unknown metadata set') + + # let's see if one unique marker is found + is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) + is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) + is_2_1 = '2.1' in possible_versions and _has_marker(keys, _566_MARKERS) + is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) + if int(is_1_1) + int(is_1_2) + int(is_2_1) + int(is_2_0) > 1: + raise MetadataConflictError('You used incompatible 1.1/1.2/2.0/2.1 fields') + + # we have the choice, 1.0, or 1.2, or 2.0 + # - 1.0 has a broken Summary field but works with all tools + # - 1.1 is to avoid + # - 1.2 fixes Summary but has little adoption + # - 2.0 adds more features and is very new + if not is_1_1 and not is_1_2 and not is_2_1 and not is_2_0: + # we couldn't find any specific marker + if PKG_INFO_PREFERRED_VERSION in possible_versions: + return PKG_INFO_PREFERRED_VERSION + if is_1_1: + return '1.1' + if is_1_2: + return '1.2' + if is_2_1: + return '2.1' + + return '2.0' + +_ATTR2FIELD = { + 'metadata_version': 'Metadata-Version', + 'name': 'Name', + 'version': 'Version', + 'platform': 'Platform', + 'supported_platform': 'Supported-Platform', + 'summary': 'Summary', + 'description': 'Description', + 'keywords': 'Keywords', + 'home_page': 'Home-page', + 'author': 'Author', + 'author_email': 'Author-email', + 'maintainer': 'Maintainer', + 'maintainer_email': 'Maintainer-email', + 'license': 'License', + 'classifier': 'Classifier', + 'download_url': 'Download-URL', + 'obsoletes_dist': 'Obsoletes-Dist', + 'provides_dist': 'Provides-Dist', + 'requires_dist': 'Requires-Dist', + 'setup_requires_dist': 'Setup-Requires-Dist', + 'requires_python': 'Requires-Python', + 'requires_external': 'Requires-External', + 'requires': 'Requires', + 'provides': 'Provides', + 'obsoletes': 'Obsoletes', + 'project_url': 'Project-URL', + 'private_version': 'Private-Version', + 'obsoleted_by': 'Obsoleted-By', + 'extension': 'Extension', + 'provides_extra': 'Provides-Extra', +} + +_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') +_VERSIONS_FIELDS = ('Requires-Python',) +_VERSION_FIELDS = ('Version',) +_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', + 'Requires', 'Provides', 'Obsoletes-Dist', + 'Provides-Dist', 'Requires-Dist', 'Requires-External', + 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', + 'Provides-Extra', 'Extension') +_LISTTUPLEFIELDS = ('Project-URL',) + +_ELEMENTSFIELD = ('Keywords',) + +_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') + +_MISSING = object() + +_FILESAFE = re.compile('[^A-Za-z0-9.]+') + + +def _get_name_and_version(name, version, for_filename=False): + """Return the distribution name with version. + + If for_filename is true, return a filename-escaped form.""" + if for_filename: + # For both name and version any runs of non-alphanumeric or '.' + # characters are replaced with a single '-'. Additionally any + # spaces in the version string become '.' + name = _FILESAFE.sub('-', name) + version = _FILESAFE.sub('-', version.replace(' ', '.')) + return '%s-%s' % (name, version) + + +class LegacyMetadata(object): + """The legacy metadata of a release. + + Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can + instantiate the class with one of these arguments (or none): + - *path*, the path to a metadata file + - *fileobj* give a file-like object with metadata as content + - *mapping* is a dict-like object + - *scheme* is a version scheme name + """ + # TODO document the mapping API and UNKNOWN default key + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._fields = {} + self.requires_files = [] + self._dependencies = None + self.scheme = scheme + if path is not None: + self.read(path) + elif fileobj is not None: + self.read_file(fileobj) + elif mapping is not None: + self.update(mapping) + self.set_metadata_version() + + def set_metadata_version(self): + self._fields['Metadata-Version'] = _best_version(self._fields) + + def _write_field(self, fileobj, name, value): + fileobj.write('%s: %s\n' % (name, value)) + + def __getitem__(self, name): + return self.get(name) + + def __setitem__(self, name, value): + return self.set(name, value) + + def __delitem__(self, name): + field_name = self._convert_name(name) + try: + del self._fields[field_name] + except KeyError: + raise KeyError(name) + + def __contains__(self, name): + return (name in self._fields or + self._convert_name(name) in self._fields) + + def _convert_name(self, name): + if name in _ALL_FIELDS: + return name + name = name.replace('-', '_').lower() + return _ATTR2FIELD.get(name, name) + + def _default_value(self, name): + if name in _LISTFIELDS or name in _ELEMENTSFIELD: + return [] + return 'UNKNOWN' + + def _remove_line_prefix(self, value): + if self.metadata_version in ('1.0', '1.1'): + return _LINE_PREFIX_PRE_1_2.sub('\n', value) + else: + return _LINE_PREFIX_1_2.sub('\n', value) + + def __getattr__(self, name): + if name in _ATTR2FIELD: + return self[name] + raise AttributeError(name) + + # + # Public API + # + +# dependencies = property(_get_dependencies, _set_dependencies) + + def get_fullname(self, filesafe=False): + """Return the distribution name with version. + + If filesafe is true, return a filename-escaped form.""" + return _get_name_and_version(self['Name'], self['Version'], filesafe) + + def is_field(self, name): + """return True if name is a valid metadata key""" + name = self._convert_name(name) + return name in _ALL_FIELDS + + def is_multi_field(self, name): + name = self._convert_name(name) + return name in _LISTFIELDS + + def read(self, filepath): + """Read the metadata values from a file path.""" + fp = codecs.open(filepath, 'r', encoding='utf-8') + try: + self.read_file(fp) + finally: + fp.close() + + def read_file(self, fileob): + """Read the metadata values from a file object.""" + msg = message_from_file(fileob) + self._fields['Metadata-Version'] = msg['metadata-version'] + + # When reading, get all the fields we can + for field in _ALL_FIELDS: + if field not in msg: + continue + if field in _LISTFIELDS: + # we can have multiple lines + values = msg.get_all(field) + if field in _LISTTUPLEFIELDS and values is not None: + values = [tuple(value.split(',')) for value in values] + self.set(field, values) + else: + # single line + value = msg[field] + if value is not None and value != 'UNKNOWN': + self.set(field, value) + logger.debug('Attempting to set metadata for %s', self) + self.set_metadata_version() + + def write(self, filepath, skip_unknown=False): + """Write the metadata fields to filepath.""" + fp = codecs.open(filepath, 'w', encoding='utf-8') + try: + self.write_file(fp, skip_unknown) + finally: + fp.close() + + def write_file(self, fileobject, skip_unknown=False): + """Write the PKG-INFO format data to a file object.""" + self.set_metadata_version() + + for field in _version2fieldlist(self['Metadata-Version']): + values = self.get(field) + if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): + continue + if field in _ELEMENTSFIELD: + self._write_field(fileobject, field, ','.join(values)) + continue + if field not in _LISTFIELDS: + if field == 'Description': + if self.metadata_version in ('1.0', '1.1'): + values = values.replace('\n', '\n ') + else: + values = values.replace('\n', '\n |') + values = [values] + + if field in _LISTTUPLEFIELDS: + values = [','.join(value) for value in values] + + for value in values: + self._write_field(fileobject, field, value) + + def update(self, other=None, **kwargs): + """Set metadata values from the given iterable `other` and kwargs. + + Behavior is like `dict.update`: If `other` has a ``keys`` method, + they are looped over and ``self[key]`` is assigned ``other[key]``. + Else, ``other`` is an iterable of ``(key, value)`` iterables. + + Keys that don't match a metadata field or that have an empty value are + dropped. + """ + def _set(key, value): + if key in _ATTR2FIELD and value: + self.set(self._convert_name(key), value) + + if not other: + # other is None or empty container + pass + elif hasattr(other, 'keys'): + for k in other.keys(): + _set(k, other[k]) + else: + for k, v in other: + _set(k, v) + + if kwargs: + for k, v in kwargs.items(): + _set(k, v) + + def set(self, name, value): + """Control then set a metadata field.""" + name = self._convert_name(name) + + if ((name in _ELEMENTSFIELD or name == 'Platform') and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [v.strip() for v in value.split(',')] + else: + value = [] + elif (name in _LISTFIELDS and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [value] + else: + value = [] + + if logger.isEnabledFor(logging.WARNING): + project_name = self['Name'] + + scheme = get_scheme(self.scheme) + if name in _PREDICATE_FIELDS and value is not None: + for v in value: + # check that the values are valid + if not scheme.is_valid_matcher(v.split(';')[0]): + logger.warning( + "'%s': '%s' is not valid (field '%s')", + project_name, v, name) + # FIXME this rejects UNKNOWN, is that right? + elif name in _VERSIONS_FIELDS and value is not None: + if not scheme.is_valid_constraint_list(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + elif name in _VERSION_FIELDS and value is not None: + if not scheme.is_valid_version(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + + if name in _UNICODEFIELDS: + if name == 'Description': + value = self._remove_line_prefix(value) + + self._fields[name] = value + + def get(self, name, default=_MISSING): + """Get a metadata field.""" + name = self._convert_name(name) + if name not in self._fields: + if default is _MISSING: + default = self._default_value(name) + return default + if name in _UNICODEFIELDS: + value = self._fields[name] + return value + elif name in _LISTFIELDS: + value = self._fields[name] + if value is None: + return [] + res = [] + for val in value: + if name not in _LISTTUPLEFIELDS: + res.append(val) + else: + # That's for Project-URL + res.append((val[0], val[1])) + return res + + elif name in _ELEMENTSFIELD: + value = self._fields[name] + if isinstance(value, string_types): + return value.split(',') + return self._fields[name] + + def check(self, strict=False): + """Check if the metadata is compliant. If strict is True then raise if + no Name or Version are provided""" + self.set_metadata_version() + + # XXX should check the versions (if the file was loaded) + missing, warnings = [], [] + + for attr in ('Name', 'Version'): # required by PEP 345 + if attr not in self: + missing.append(attr) + + if strict and missing != []: + msg = 'missing required metadata: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + + for attr in ('Home-page', 'Author'): + if attr not in self: + missing.append(attr) + + # checking metadata 1.2 (XXX needs to check 1.1, 1.0) + if self['Metadata-Version'] != '1.2': + return missing, warnings + + scheme = get_scheme(self.scheme) + + def are_valid_constraints(value): + for v in value: + if not scheme.is_valid_matcher(v.split(';')[0]): + return False + return True + + for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), + (_VERSIONS_FIELDS, + scheme.is_valid_constraint_list), + (_VERSION_FIELDS, + scheme.is_valid_version)): + for field in fields: + value = self.get(field, None) + if value is not None and not controller(value): + warnings.append("Wrong value for '%s': %s" % (field, value)) + + return missing, warnings + + def todict(self, skip_missing=False): + """Return fields as a dict. + + Field names will be converted to use the underscore-lowercase style + instead of hyphen-mixed case (i.e. home_page instead of Home-page). + """ + self.set_metadata_version() + + mapping_1_0 = ( + ('metadata_version', 'Metadata-Version'), + ('name', 'Name'), + ('version', 'Version'), + ('summary', 'Summary'), + ('home_page', 'Home-page'), + ('author', 'Author'), + ('author_email', 'Author-email'), + ('license', 'License'), + ('description', 'Description'), + ('keywords', 'Keywords'), + ('platform', 'Platform'), + ('classifiers', 'Classifier'), + ('download_url', 'Download-URL'), + ) + + data = {} + for key, field_name in mapping_1_0: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] + + if self['Metadata-Version'] == '1.2': + mapping_1_2 = ( + ('requires_dist', 'Requires-Dist'), + ('requires_python', 'Requires-Python'), + ('requires_external', 'Requires-External'), + ('provides_dist', 'Provides-Dist'), + ('obsoletes_dist', 'Obsoletes-Dist'), + ('project_url', 'Project-URL'), + ('maintainer', 'Maintainer'), + ('maintainer_email', 'Maintainer-email'), + ) + for key, field_name in mapping_1_2: + if not skip_missing or field_name in self._fields: + if key != 'project_url': + data[key] = self[field_name] + else: + data[key] = [','.join(u) for u in self[field_name]] + + elif self['Metadata-Version'] == '1.1': + mapping_1_1 = ( + ('provides', 'Provides'), + ('requires', 'Requires'), + ('obsoletes', 'Obsoletes'), + ) + for key, field_name in mapping_1_1: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] + + return data + + def add_requirements(self, requirements): + if self['Metadata-Version'] == '1.1': + # we can't have 1.1 metadata *and* Setuptools requires + for field in ('Obsoletes', 'Requires', 'Provides'): + if field in self: + del self[field] + self['Requires-Dist'] += requirements + + # Mapping API + # TODO could add iter* variants + + def keys(self): + return list(_version2fieldlist(self['Metadata-Version'])) + + def __iter__(self): + for key in self.keys(): + yield key + + def values(self): + return [self[key] for key in self.keys()] + + def items(self): + return [(key, self[key]) for key in self.keys()] + + def __repr__(self): + return '<%s %s %s>' % (self.__class__.__name__, self.name, + self.version) + + +METADATA_FILENAME = 'pydist.json' +WHEEL_METADATA_FILENAME = 'metadata.json' + + +class Metadata(object): + """ + The metadata of a release. This implementation uses 2.0 (JSON) + metadata where possible. If not possible, it wraps a LegacyMetadata + instance which handles the key-value metadata format. + """ + + METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$') + + NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) + + VERSION_MATCHER = PEP440_VERSION_RE + + SUMMARY_MATCHER = re.compile('.{1,2047}') + + METADATA_VERSION = '2.0' + + GENERATOR = 'distlib (%s)' % __version__ + + MANDATORY_KEYS = { + 'name': (), + 'version': (), + 'summary': ('legacy',), + } + + INDEX_KEYS = ('name version license summary description author ' + 'author_email keywords platform home_page classifiers ' + 'download_url') + + DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' + 'dev_requires provides meta_requires obsoleted_by ' + 'supports_environments') + + SYNTAX_VALIDATORS = { + 'metadata_version': (METADATA_VERSION_MATCHER, ()), + 'name': (NAME_MATCHER, ('legacy',)), + 'version': (VERSION_MATCHER, ('legacy',)), + 'summary': (SUMMARY_MATCHER, ('legacy',)), + } + + __slots__ = ('_legacy', '_data', 'scheme') + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._legacy = None + self._data = None + self.scheme = scheme + #import pdb; pdb.set_trace() + if mapping is not None: + try: + self._validate_mapping(mapping, scheme) + self._data = mapping + except MetadataUnrecognizedVersionError: + self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) + self.validate() + else: + data = None + if path: + with open(path, 'rb') as f: + data = f.read() + elif fileobj: + data = fileobj.read() + if data is None: + # Initialised with no args - to be added + self._data = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + else: + if not isinstance(data, text_type): + data = data.decode('utf-8') + try: + self._data = json.loads(data) + self._validate_mapping(self._data, scheme) + except ValueError: + # Note: MetadataUnrecognizedVersionError does not + # inherit from ValueError (it's a DistlibException, + # which should not inherit from ValueError). + # The ValueError comes from the json.load - if that + # succeeds and we get a validation error, we want + # that to propagate + self._legacy = LegacyMetadata(fileobj=StringIO(data), + scheme=scheme) + self.validate() + + common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) + + none_list = (None, list) + none_dict = (None, dict) + + mapped_keys = { + 'run_requires': ('Requires-Dist', list), + 'build_requires': ('Setup-Requires-Dist', list), + 'dev_requires': none_list, + 'test_requires': none_list, + 'meta_requires': none_list, + 'extras': ('Provides-Extra', list), + 'modules': none_list, + 'namespaces': none_list, + 'exports': none_dict, + 'commands': none_dict, + 'classifiers': ('Classifier', list), + 'source_url': ('Download-URL', None), + 'metadata_version': ('Metadata-Version', None), + } + + del none_list, none_dict + + def __getattribute__(self, key): + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, maker = mapped[key] + if self._legacy: + if lk is None: + result = None if maker is None else maker() + else: + result = self._legacy.get(lk) + else: + value = None if maker is None else maker() + if key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + result = self._data.get(key, value) + else: + # special cases for PEP 459 + sentinel = object() + result = sentinel + d = self._data.get('extensions') + if d: + if key == 'commands': + result = d.get('python.commands', value) + elif key == 'classifiers': + d = d.get('python.details') + if d: + result = d.get(key, value) + else: + d = d.get('python.exports') + if not d: + d = self._data.get('python.exports') + if d: + result = d.get(key, value) + if result is sentinel: + result = value + elif key not in common: + result = object.__getattribute__(self, key) + elif self._legacy: + result = self._legacy.get(key) + else: + result = self._data.get(key) + return result + + def _validate_value(self, key, value, scheme=None): + if key in self.SYNTAX_VALIDATORS: + pattern, exclusions = self.SYNTAX_VALIDATORS[key] + if (scheme or self.scheme) not in exclusions: + m = pattern.match(value) + if not m: + raise MetadataInvalidError("'%s' is an invalid value for " + "the '%s' property" % (value, + key)) + + def __setattr__(self, key, value): + self._validate_value(key, value) + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, _ = mapped[key] + if self._legacy: + if lk is None: + raise NotImplementedError + self._legacy[lk] = value + elif key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + self._data[key] = value + else: + # special cases for PEP 459 + d = self._data.setdefault('extensions', {}) + if key == 'commands': + d['python.commands'] = value + elif key == 'classifiers': + d = d.setdefault('python.details', {}) + d[key] = value + else: + d = d.setdefault('python.exports', {}) + d[key] = value + elif key not in common: + object.__setattr__(self, key, value) + else: + if key == 'keywords': + if isinstance(value, string_types): + value = value.strip() + if value: + value = value.split() + else: + value = [] + if self._legacy: + self._legacy[key] = value + else: + self._data[key] = value + + @property + def name_and_version(self): + return _get_name_and_version(self.name, self.version, True) + + @property + def provides(self): + if self._legacy: + result = self._legacy['Provides-Dist'] + else: + result = self._data.setdefault('provides', []) + s = '%s (%s)' % (self.name, self.version) + if s not in result: + result.append(s) + return result + + @provides.setter + def provides(self, value): + if self._legacy: + self._legacy['Provides-Dist'] = value + else: + self._data['provides'] = value + + def get_requirements(self, reqts, extras=None, env=None): + """ + Base method to get dependencies, given a set of extras + to satisfy and an optional environment context. + :param reqts: A list of sometimes-wanted dependencies, + perhaps dependent on extras and environment. + :param extras: A list of optional components being requested. + :param env: An optional environment for marker evaluation. + """ + if self._legacy: + result = reqts + else: + result = [] + extras = get_extras(extras or [], self.extras) + for d in reqts: + if 'extra' not in d and 'environment' not in d: + # unconditional + include = True + else: + if 'extra' not in d: + # Not extra-dependent - only environment-dependent + include = True + else: + include = d.get('extra') in extras + if include: + # Not excluded because of extras, check environment + marker = d.get('environment') + if marker: + include = interpret(marker, env) + if include: + result.extend(d['requires']) + for key in ('build', 'dev', 'test'): + e = ':%s:' % key + if e in extras: + extras.remove(e) + # A recursive call, but it should terminate since 'test' + # has been removed from the extras + reqts = self._data.get('%s_requires' % key, []) + result.extend(self.get_requirements(reqts, extras=extras, + env=env)) + return result + + @property + def dictionary(self): + if self._legacy: + return self._from_legacy() + return self._data + + @property + def dependencies(self): + if self._legacy: + raise NotImplementedError + else: + return extract_by_key(self._data, self.DEPENDENCY_KEYS) + + @dependencies.setter + def dependencies(self, value): + if self._legacy: + raise NotImplementedError + else: + self._data.update(value) + + def _validate_mapping(self, mapping, scheme): + if mapping.get('metadata_version') != self.METADATA_VERSION: + raise MetadataUnrecognizedVersionError() + missing = [] + for key, exclusions in self.MANDATORY_KEYS.items(): + if key not in mapping: + if scheme not in exclusions: + missing.append(key) + if missing: + msg = 'Missing metadata items: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + for k, v in mapping.items(): + self._validate_value(k, v, scheme) + + def validate(self): + if self._legacy: + missing, warnings = self._legacy.check(True) + if missing or warnings: + logger.warning('Metadata: missing: %s, warnings: %s', + missing, warnings) + else: + self._validate_mapping(self._data, self.scheme) + + def todict(self): + if self._legacy: + return self._legacy.todict(True) + else: + result = extract_by_key(self._data, self.INDEX_KEYS) + return result + + def _from_legacy(self): + assert self._legacy and not self._data + result = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + lmd = self._legacy.todict(True) # skip missing ones + for k in ('name', 'version', 'license', 'summary', 'description', + 'classifier'): + if k in lmd: + if k == 'classifier': + nk = 'classifiers' + else: + nk = k + result[nk] = lmd[k] + kw = lmd.get('Keywords', []) + if kw == ['']: + kw = [] + result['keywords'] = kw + keys = (('requires_dist', 'run_requires'), + ('setup_requires_dist', 'build_requires')) + for ok, nk in keys: + if ok in lmd and lmd[ok]: + result[nk] = [{'requires': lmd[ok]}] + result['provides'] = self.provides + author = {} + maintainer = {} + return result + + LEGACY_MAPPING = { + 'name': 'Name', + 'version': 'Version', + 'license': 'License', + 'summary': 'Summary', + 'description': 'Description', + 'classifiers': 'Classifier', + } + + def _to_legacy(self): + def process_entries(entries): + reqts = set() + for e in entries: + extra = e.get('extra') + env = e.get('environment') + rlist = e['requires'] + for r in rlist: + if not env and not extra: + reqts.add(r) + else: + marker = '' + if extra: + marker = 'extra == "%s"' % extra + if env: + if marker: + marker = '(%s) and %s' % (env, marker) + else: + marker = env + reqts.add(';'.join((r, marker))) + return reqts + + assert self._data and not self._legacy + result = LegacyMetadata() + nmd = self._data + for nk, ok in self.LEGACY_MAPPING.items(): + if nk in nmd: + result[ok] = nmd[nk] + r1 = process_entries(self.run_requires + self.meta_requires) + r2 = process_entries(self.build_requires + self.dev_requires) + if self.extras: + result['Provides-Extra'] = sorted(self.extras) + result['Requires-Dist'] = sorted(r1) + result['Setup-Requires-Dist'] = sorted(r2) + # TODO: other fields such as contacts + return result + + def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): + if [path, fileobj].count(None) != 1: + raise ValueError('Exactly one of path and fileobj is needed') + self.validate() + if legacy: + if self._legacy: + legacy_md = self._legacy + else: + legacy_md = self._to_legacy() + if path: + legacy_md.write(path, skip_unknown=skip_unknown) + else: + legacy_md.write_file(fileobj, skip_unknown=skip_unknown) + else: + if self._legacy: + d = self._from_legacy() + else: + d = self._data + if fileobj: + json.dump(d, fileobj, ensure_ascii=True, indent=2, + sort_keys=True) + else: + with codecs.open(path, 'w', 'utf-8') as f: + json.dump(d, f, ensure_ascii=True, indent=2, + sort_keys=True) + + def add_requirements(self, requirements): + if self._legacy: + self._legacy.add_requirements(requirements) + else: + run_requires = self._data.setdefault('run_requires', []) + always = None + for entry in run_requires: + if 'environment' not in entry and 'extra' not in entry: + always = entry + break + if always is None: + always = { 'requires': requirements } + run_requires.insert(0, always) + else: + rset = set(always['requires']) | set(requirements) + always['requires'] = sorted(rset) + + def __repr__(self): + name = self.name or '(no name)' + version = self.version or 'no version' + return '<%s %s %s (%s)>' % (self.__class__.__name__, + self.metadata_version, name, version) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/resources.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/resources.py new file mode 100644 index 0000000..1884016 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/resources.py @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import bisect +import io +import logging +import os +import pkgutil +import shutil +import sys +import types +import zipimport + +from . import DistlibException +from .util import cached_property, get_cache_base, path_to_cache_dir, Cache + +logger = logging.getLogger(__name__) + + +cache = None # created when needed + + +class ResourceCache(Cache): + def __init__(self, base=None): + if base is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('resource-cache')) + super(ResourceCache, self).__init__(base) + + def is_stale(self, resource, path): + """ + Is the cache stale for the given resource? + + :param resource: The :class:`Resource` being cached. + :param path: The path of the resource in the cache. + :return: True if the cache is stale. + """ + # Cache invalidation is a hard problem :-) + return True + + def get(self, resource): + """ + Get a resource into the cache, + + :param resource: A :class:`Resource` instance. + :return: The pathname of the resource in the cache. + """ + prefix, path = resource.finder.get_cache_info(resource) + if prefix is None: + result = path + else: + result = os.path.join(self.base, self.prefix_to_dir(prefix), path) + dirname = os.path.dirname(result) + if not os.path.isdir(dirname): + os.makedirs(dirname) + if not os.path.exists(result): + stale = True + else: + stale = self.is_stale(resource, path) + if stale: + # write the bytes of the resource to the cache location + with open(result, 'wb') as f: + f.write(resource.bytes) + return result + + +class ResourceBase(object): + def __init__(self, finder, name): + self.finder = finder + self.name = name + + +class Resource(ResourceBase): + """ + A class representing an in-package resource, such as a data file. This is + not normally instantiated by user code, but rather by a + :class:`ResourceFinder` which manages the resource. + """ + is_container = False # Backwards compatibility + + def as_stream(self): + """ + Get the resource as a stream. + + This is not a property to make it obvious that it returns a new stream + each time. + """ + return self.finder.get_stream(self) + + @cached_property + def file_path(self): + global cache + if cache is None: + cache = ResourceCache() + return cache.get(self) + + @cached_property + def bytes(self): + return self.finder.get_bytes(self) + + @cached_property + def size(self): + return self.finder.get_size(self) + + +class ResourceContainer(ResourceBase): + is_container = True # Backwards compatibility + + @cached_property + def resources(self): + return self.finder.get_resources(self) + + +class ResourceFinder(object): + """ + Resource finder for file system resources. + """ + + if sys.platform.startswith('java'): + skipped_extensions = ('.pyc', '.pyo', '.class') + else: + skipped_extensions = ('.pyc', '.pyo') + + def __init__(self, module): + self.module = module + self.loader = getattr(module, '__loader__', None) + self.base = os.path.dirname(getattr(module, '__file__', '')) + + def _adjust_path(self, path): + return os.path.realpath(path) + + def _make_path(self, resource_name): + # Issue #50: need to preserve type of path on Python 2.x + # like os.path._get_sep + if isinstance(resource_name, bytes): # should only happen on 2.x + sep = b'/' + else: + sep = '/' + parts = resource_name.split(sep) + parts.insert(0, self.base) + result = os.path.join(*parts) + return self._adjust_path(result) + + def _find(self, path): + return os.path.exists(path) + + def get_cache_info(self, resource): + return None, resource.path + + def find(self, resource_name): + path = self._make_path(resource_name) + if not self._find(path): + result = None + else: + if self._is_directory(path): + result = ResourceContainer(self, resource_name) + else: + result = Resource(self, resource_name) + result.path = path + return result + + def get_stream(self, resource): + return open(resource.path, 'rb') + + def get_bytes(self, resource): + with open(resource.path, 'rb') as f: + return f.read() + + def get_size(self, resource): + return os.path.getsize(resource.path) + + def get_resources(self, resource): + def allowed(f): + return (f != '__pycache__' and not + f.endswith(self.skipped_extensions)) + return set([f for f in os.listdir(resource.path) if allowed(f)]) + + def is_container(self, resource): + return self._is_directory(resource.path) + + _is_directory = staticmethod(os.path.isdir) + + def iterator(self, resource_name): + resource = self.find(resource_name) + if resource is not None: + todo = [resource] + while todo: + resource = todo.pop(0) + yield resource + if resource.is_container: + rname = resource.name + for name in resource.resources: + if not rname: + new_name = name + else: + new_name = '/'.join([rname, name]) + child = self.find(new_name) + if child.is_container: + todo.append(child) + else: + yield child + + +class ZipResourceFinder(ResourceFinder): + """ + Resource finder for resources in .zip files. + """ + def __init__(self, module): + super(ZipResourceFinder, self).__init__(module) + archive = self.loader.archive + self.prefix_len = 1 + len(archive) + # PyPy doesn't have a _files attr on zipimporter, and you can't set one + if hasattr(self.loader, '_files'): + self._files = self.loader._files + else: + self._files = zipimport._zip_directory_cache[archive] + self.index = sorted(self._files) + + def _adjust_path(self, path): + return path + + def _find(self, path): + path = path[self.prefix_len:] + if path in self._files: + result = True + else: + if path and path[-1] != os.sep: + path = path + os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + if not result: + logger.debug('_find failed: %r %r', path, self.loader.prefix) + else: + logger.debug('_find worked: %r %r', path, self.loader.prefix) + return result + + def get_cache_info(self, resource): + prefix = self.loader.archive + path = resource.path[1 + len(prefix):] + return prefix, path + + def get_bytes(self, resource): + return self.loader.get_data(resource.path) + + def get_stream(self, resource): + return io.BytesIO(self.get_bytes(resource)) + + def get_size(self, resource): + path = resource.path[self.prefix_len:] + return self._files[path][3] + + def get_resources(self, resource): + path = resource.path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + plen = len(path) + result = set() + i = bisect.bisect(self.index, path) + while i < len(self.index): + if not self.index[i].startswith(path): + break + s = self.index[i][plen:] + result.add(s.split(os.sep, 1)[0]) # only immediate children + i += 1 + return result + + def _is_directory(self, path): + path = path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + return result + +_finder_registry = { + type(None): ResourceFinder, + zipimport.zipimporter: ZipResourceFinder +} + +try: + # In Python 3.6, _frozen_importlib -> _frozen_importlib_external + try: + import _frozen_importlib_external as _fi + except ImportError: + import _frozen_importlib as _fi + _finder_registry[_fi.SourceFileLoader] = ResourceFinder + _finder_registry[_fi.FileFinder] = ResourceFinder + del _fi +except (ImportError, AttributeError): + pass + + +def register_finder(loader, finder_maker): + _finder_registry[type(loader)] = finder_maker + +_finder_cache = {} + + +def finder(package): + """ + Return a resource finder for a package. + :param package: The name of the package. + :return: A :class:`ResourceFinder` instance for the package. + """ + if package in _finder_cache: + result = _finder_cache[package] + else: + if package not in sys.modules: + __import__(package) + module = sys.modules[package] + path = getattr(module, '__path__', None) + if path is None: + raise DistlibException('You cannot get a finder for a module, ' + 'only for a package') + loader = getattr(module, '__loader__', None) + finder_maker = _finder_registry.get(type(loader)) + if finder_maker is None: + raise DistlibException('Unable to locate finder for %r' % package) + result = finder_maker(module) + _finder_cache[package] = result + return result + + +_dummy_module = types.ModuleType(str('__dummy__')) + + +def finder_for_path(path): + """ + Return a resource finder for a path, which should represent a container. + + :param path: The path. + :return: A :class:`ResourceFinder` instance for the path. + """ + result = None + # calls any path hooks, gets importer into cache + pkgutil.get_importer(path) + loader = sys.path_importer_cache.get(path) + finder = _finder_registry.get(type(loader)) + if finder: + module = _dummy_module + module.__file__ = os.path.join(path, '') + module.__loader__ = loader + result = finder(module) + return result diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/scripts.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/scripts.py new file mode 100644 index 0000000..0b7c3d0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/scripts.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from io import BytesIO +import logging +import os +import re +import struct +import sys + +from .compat import sysconfig, detect_encoding, ZipFile +from .resources import finder +from .util import (FileOperator, get_export_entry, convert_path, + get_executable, in_venv) + +logger = logging.getLogger(__name__) + +_DEFAULT_MANIFEST = ''' +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" + processorArchitecture="X86" + name="%s" + type="win32"/> + + <!-- Identify the application security requirements. --> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly>'''.strip() + +# check if Python is called on the first line with this expression +FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') +SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- +if __name__ == '__main__': + import sys, re + + def _resolve(module, func): + __import__(module) + mod = sys.modules[module] + parts = func.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + try: + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + + func = _resolve('%(module)s', '%(func)s') + rc = func() # None interpreted as 0 + except Exception as e: # only supporting Python >= 2.6 + sys.stderr.write('%%s\n' %% e) + rc = 1 + sys.exit(rc) +''' + + +def _enquote_executable(executable): + if ' ' in executable: + # make sure we quote only the executable in case of env + # for example /usr/bin/env "/dir with spaces/bin/jython" + # instead of "/usr/bin/env /dir with spaces/bin/jython" + # otherwise whole + if executable.startswith('/usr/bin/env '): + env, _executable = executable.split(' ', 1) + if ' ' in _executable and not _executable.startswith('"'): + executable = '%s "%s"' % (env, _executable) + else: + if not executable.startswith('"'): + executable = '"%s"' % executable + return executable + + +class ScriptMaker(object): + """ + A class to copy or create scripts from source scripts or callable + specifications. + """ + script_template = SCRIPT_TEMPLATE + + executable = None # for shebangs + + def __init__(self, source_dir, target_dir, add_launchers=True, + dry_run=False, fileop=None): + self.source_dir = source_dir + self.target_dir = target_dir + self.add_launchers = add_launchers + self.force = False + self.clobber = False + # It only makes sense to set mode bits on POSIX. + self.set_mode = (os.name == 'posix') or (os.name == 'java' and + os._name == 'posix') + self.variants = set(('', 'X.Y')) + self._fileop = fileop or FileOperator(dry_run) + + self._is_nt = os.name == 'nt' or ( + os.name == 'java' and os._name == 'nt') + + def _get_alternate_executable(self, executable, options): + if options.get('gui', False) and self._is_nt: # pragma: no cover + dn, fn = os.path.split(executable) + fn = fn.replace('python', 'pythonw') + executable = os.path.join(dn, fn) + return executable + + if sys.platform.startswith('java'): # pragma: no cover + def _is_shell(self, executable): + """ + Determine if the specified executable is a script + (contains a #! line) + """ + try: + with open(executable) as fp: + return fp.read(2) == '#!' + except (OSError, IOError): + logger.warning('Failed to open %s', executable) + return False + + def _fix_jython_executable(self, executable): + if self._is_shell(executable): + # Workaround for Jython is not needed on Linux systems. + import java + + if java.lang.System.getProperty('os.name') == 'Linux': + return executable + elif executable.lower().endswith('jython.exe'): + # Use wrapper exe for Jython on Windows + return executable + return '/usr/bin/env %s' % executable + + def _build_shebang(self, executable, post_interp): + """ + Build a shebang line. In the simple case (on Windows, or a shebang line + which is not too long or contains spaces) use a simple formulation for + the shebang. Otherwise, use /bin/sh as the executable, with a contrived + shebang which allows the script to run either under Python or sh, using + suitable quoting. Thanks to Harald Nordgren for his input. + + See also: http://www.in-ulm.de/~mascheck/various/shebang/#length + https://hg.mozilla.org/mozilla-central/file/tip/mach + """ + if os.name != 'posix': + simple_shebang = True + else: + # Add 3 for '#!' prefix and newline suffix. + shebang_length = len(executable) + len(post_interp) + 3 + if sys.platform == 'darwin': + max_shebang_length = 512 + else: + max_shebang_length = 127 + simple_shebang = ((b' ' not in executable) and + (shebang_length <= max_shebang_length)) + + if simple_shebang: + result = b'#!' + executable + post_interp + b'\n' + else: + result = b'#!/bin/sh\n' + result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n' + result += b"' '''" + return result + + def _get_shebang(self, encoding, post_interp=b'', options=None): + enquote = True + if self.executable: + executable = self.executable + enquote = False # assume this will be taken care of + elif not sysconfig.is_python_build(): + executable = get_executable() + elif in_venv(): # pragma: no cover + executable = os.path.join(sysconfig.get_path('scripts'), + 'python%s' % sysconfig.get_config_var('EXE')) + else: # pragma: no cover + executable = os.path.join( + sysconfig.get_config_var('BINDIR'), + 'python%s%s' % (sysconfig.get_config_var('VERSION'), + sysconfig.get_config_var('EXE'))) + if options: + executable = self._get_alternate_executable(executable, options) + + if sys.platform.startswith('java'): # pragma: no cover + executable = self._fix_jython_executable(executable) + # Normalise case for Windows + executable = os.path.normcase(executable) + # If the user didn't specify an executable, it may be necessary to + # cater for executable paths with spaces (not uncommon on Windows) + if enquote: + executable = _enquote_executable(executable) + # Issue #51: don't use fsencode, since we later try to + # check that the shebang is decodable using utf-8. + executable = executable.encode('utf-8') + # in case of IronPython, play safe and enable frames support + if (sys.platform == 'cli' and '-X:Frames' not in post_interp + and '-X:FullFrames' not in post_interp): # pragma: no cover + post_interp += b' -X:Frames' + shebang = self._build_shebang(executable, post_interp) + # Python parser starts to read a script using UTF-8 until + # it gets a #coding:xxx cookie. The shebang has to be the + # first line of a file, the #coding:xxx cookie cannot be + # written before. So the shebang has to be decodable from + # UTF-8. + try: + shebang.decode('utf-8') + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable from utf-8' % shebang) + # If the script is encoded to a custom encoding (use a + # #coding:xxx cookie), the shebang has to be decodable from + # the script encoding too. + if encoding != 'utf-8': + try: + shebang.decode(encoding) + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable ' + 'from the script encoding (%r)' % (shebang, encoding)) + return shebang + + def _get_script_text(self, entry): + return self.script_template % dict(module=entry.prefix, + func=entry.suffix) + + manifest = _DEFAULT_MANIFEST + + def get_manifest(self, exename): + base = os.path.basename(exename) + return self.manifest % base + + def _write_script(self, names, shebang, script_bytes, filenames, ext): + use_launcher = self.add_launchers and self._is_nt + linesep = os.linesep.encode('utf-8') + if not use_launcher: + script_bytes = shebang + linesep + script_bytes + else: # pragma: no cover + if ext == 'py': + launcher = self._get_launcher('t') + else: + launcher = self._get_launcher('w') + stream = BytesIO() + with ZipFile(stream, 'w') as zf: + zf.writestr('__main__.py', script_bytes) + zip_data = stream.getvalue() + script_bytes = launcher + shebang + linesep + zip_data + for name in names: + outname = os.path.join(self.target_dir, name) + if use_launcher: # pragma: no cover + n, e = os.path.splitext(outname) + if e.startswith('.py'): + outname = n + outname = '%s.exe' % outname + try: + self._fileop.write_binary_file(outname, script_bytes) + except Exception: + # Failed writing an executable - it might be in use. + logger.warning('Failed to write executable - trying to ' + 'use .deleteme logic') + dfname = '%s.deleteme' % outname + if os.path.exists(dfname): + os.remove(dfname) # Not allowed to fail here + os.rename(outname, dfname) # nor here + self._fileop.write_binary_file(outname, script_bytes) + logger.debug('Able to replace executable using ' + '.deleteme logic') + try: + os.remove(dfname) + except Exception: + pass # still in use - ignore error + else: + if self._is_nt and not outname.endswith('.' + ext): # pragma: no cover + outname = '%s.%s' % (outname, ext) + if os.path.exists(outname) and not self.clobber: + logger.warning('Skipping existing file %s', outname) + continue + self._fileop.write_binary_file(outname, script_bytes) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + + def _make_script(self, entry, filenames, options=None): + post_interp = b'' + if options: + args = options.get('interpreter_args', []) + if args: + args = ' %s' % ' '.join(args) + post_interp = args.encode('utf-8') + shebang = self._get_shebang('utf-8', post_interp, options=options) + script = self._get_script_text(entry).encode('utf-8') + name = entry.name + scriptnames = set() + if '' in self.variants: + scriptnames.add(name) + if 'X' in self.variants: + scriptnames.add('%s%s' % (name, sys.version[0])) + if 'X.Y' in self.variants: + scriptnames.add('%s-%s' % (name, sys.version[:3])) + if options and options.get('gui', False): + ext = 'pyw' + else: + ext = 'py' + self._write_script(scriptnames, shebang, script, filenames, ext) + + def _copy_script(self, script, filenames): + adjust = False + script = os.path.join(self.source_dir, convert_path(script)) + outname = os.path.join(self.target_dir, os.path.basename(script)) + if not self.force and not self._fileop.newer(script, outname): + logger.debug('not copying %s (up-to-date)', script) + return + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, 'rb') + except IOError: # pragma: no cover + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: # pragma: no cover + logger.warning('%s: %s is an empty file (skipping)', + self.get_command_name(), script) + return + + match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) + if match: + adjust = True + post_interp = match.group(1) or b'' + + if not adjust: + if f: + f.close() + self._fileop.copy_file(script, outname) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + else: + logger.info('copying and adjusting %s -> %s', script, + self.target_dir) + if not self._fileop.dry_run: + encoding, lines = detect_encoding(f.readline) + f.seek(0) + shebang = self._get_shebang(encoding, post_interp) + if b'pythonw' in first_line: # pragma: no cover + ext = 'pyw' + else: + ext = 'py' + n = os.path.basename(outname) + self._write_script([n], shebang, f.read(), filenames, ext) + if f: + f.close() + + @property + def dry_run(self): + return self._fileop.dry_run + + @dry_run.setter + def dry_run(self, value): + self._fileop.dry_run = value + + if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'): # pragma: no cover + # Executable launcher support. + # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ + + def _get_launcher(self, kind): + if struct.calcsize('P') == 8: # 64-bit + bits = '64' + else: + bits = '32' + name = '%s%s.exe' % (kind, bits) + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + distlib_package = __name__.rsplit('.', 1)[0] + result = finder(distlib_package).find(name).bytes + return result + + # Public API follows + + def make(self, specification, options=None): + """ + Make a script. + + :param specification: The specification, which is either a valid export + entry specification (to make a script from a + callable) or a filename (to make a script by + copying from a source location). + :param options: A dictionary of options controlling script generation. + :return: A list of all absolute pathnames written to. + """ + filenames = [] + entry = get_export_entry(specification) + if entry is None: + self._copy_script(specification, filenames) + else: + self._make_script(entry, filenames, options=options) + return filenames + + def make_multiple(self, specifications, options=None): + """ + Take a list of specifications and make scripts from them, + :param specifications: A list of specifications. + :return: A list of all absolute pathnames written to, + """ + filenames = [] + for specification in specifications: + filenames.extend(self.make(specification, options)) + return filenames diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/t32.exe b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/t32.exe new file mode 100644 index 0000000000000000000000000000000000000000..a09d926872d84ae22a617dfe9ebb560d420b37de GIT binary patch literal 92672 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/t64.exe b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/t64.exe new file mode 100644 index 0000000000000000000000000000000000000000..9da9b40de922fb203df6b9a1d0ad4139af536850 GIT binary patch literal 102400 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�vlnW`{LoXpTySn$@;x8yoz96jn?+Kk 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�?dYNUd4WaURX_A__M4W}D0!0n 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/util.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/util.py new file mode 100644 index 0000000..0b14a93 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/util.py @@ -0,0 +1,1755 @@ +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import codecs +from collections import deque +import contextlib +import csv +from glob import iglob as std_iglob +import io +import json +import logging +import os +import py_compile +import re +import socket +try: + import ssl +except ImportError: # pragma: no cover + ssl = None +import subprocess +import sys +import tarfile +import tempfile +import textwrap + +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import time + +from . import DistlibException +from .compat import (string_types, text_type, shutil, raw_input, StringIO, + cache_from_source, urlopen, urljoin, httplib, xmlrpclib, + splittype, HTTPHandler, BaseConfigurator, valid_ident, + Container, configparser, URLError, ZipFile, fsdecode, + unquote, urlparse) + +logger = logging.getLogger(__name__) + +# +# Requirement parsing code as per PEP 508 +# + +IDENTIFIER = re.compile(r'^([\w\.-]+)\s*') +VERSION_IDENTIFIER = re.compile(r'^([\w\.*+-]+)\s*') +COMPARE_OP = re.compile(r'^(<=?|>=?|={2,3}|[~!]=)\s*') +MARKER_OP = re.compile(r'^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*') +OR = re.compile(r'^or\b\s*') +AND = re.compile(r'^and\b\s*') +NON_SPACE = re.compile(r'(\S+)\s*') +STRING_CHUNK = re.compile(r'([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)') + + +def parse_marker(marker_string): + """ + Parse a marker string and return a dictionary containing a marker expression. + + The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in + the expression grammar, or strings. A string contained in quotes is to be + interpreted as a literal string, and a string not contained in quotes is a + variable (such as os_name). + """ + def marker_var(remaining): + # either identifier, or literal string + m = IDENTIFIER.match(remaining) + if m: + result = m.groups()[0] + remaining = remaining[m.end():] + elif not remaining: + raise SyntaxError('unexpected end of input') + else: + q = remaining[0] + if q not in '\'"': + raise SyntaxError('invalid expression: %s' % remaining) + oq = '\'"'.replace(q, '') + remaining = remaining[1:] + parts = [q] + while remaining: + # either a string chunk, or oq, or q to terminate + if remaining[0] == q: + break + elif remaining[0] == oq: + parts.append(oq) + remaining = remaining[1:] + else: + m = STRING_CHUNK.match(remaining) + if not m: + raise SyntaxError('error in string literal: %s' % remaining) + parts.append(m.groups()[0]) + remaining = remaining[m.end():] + else: + s = ''.join(parts) + raise SyntaxError('unterminated string: %s' % s) + parts.append(q) + result = ''.join(parts) + remaining = remaining[1:].lstrip() # skip past closing quote + return result, remaining + + def marker_expr(remaining): + if remaining and remaining[0] == '(': + result, remaining = marker(remaining[1:].lstrip()) + if remaining[0] != ')': + raise SyntaxError('unterminated parenthesis: %s' % remaining) + remaining = remaining[1:].lstrip() + else: + lhs, remaining = marker_var(remaining) + while remaining: + m = MARKER_OP.match(remaining) + if not m: + break + op = m.groups()[0] + remaining = remaining[m.end():] + rhs, remaining = marker_var(remaining) + lhs = {'op': op, 'lhs': lhs, 'rhs': rhs} + result = lhs + return result, remaining + + def marker_and(remaining): + lhs, remaining = marker_expr(remaining) + while remaining: + m = AND.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_expr(remaining) + lhs = {'op': 'and', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + def marker(remaining): + lhs, remaining = marker_and(remaining) + while remaining: + m = OR.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_and(remaining) + lhs = {'op': 'or', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + return marker(marker_string) + + +def parse_requirement(req): + """ + Parse a requirement passed in as a string. Return a Container + whose attributes contain the various parts of the requirement. + """ + remaining = req.strip() + if not remaining or remaining.startswith('#'): + return None + m = IDENTIFIER.match(remaining) + if not m: + raise SyntaxError('name expected: %s' % remaining) + distname = m.groups()[0] + remaining = remaining[m.end():] + extras = mark_expr = versions = uri = None + if remaining and remaining[0] == '[': + i = remaining.find(']', 1) + if i < 0: + raise SyntaxError('unterminated extra: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + extras = [] + while s: + m = IDENTIFIER.match(s) + if not m: + raise SyntaxError('malformed extra: %s' % s) + extras.append(m.groups()[0]) + s = s[m.end():] + if not s: + break + if s[0] != ',': + raise SyntaxError('comma expected in extras: %s' % s) + s = s[1:].lstrip() + if not extras: + extras = None + if remaining: + if remaining[0] == '@': + # it's a URI + remaining = remaining[1:].lstrip() + m = NON_SPACE.match(remaining) + if not m: + raise SyntaxError('invalid URI: %s' % remaining) + uri = m.groups()[0] + t = urlparse(uri) + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not (t.scheme and t.netloc): + raise SyntaxError('Invalid URL: %s' % uri) + remaining = remaining[m.end():].lstrip() + else: + + def get_versions(ver_remaining): + """ + Return a list of operator, version tuples if any are + specified, else None. + """ + m = COMPARE_OP.match(ver_remaining) + versions = None + if m: + versions = [] + while True: + op = m.groups()[0] + ver_remaining = ver_remaining[m.end():] + m = VERSION_IDENTIFIER.match(ver_remaining) + if not m: + raise SyntaxError('invalid version: %s' % ver_remaining) + v = m.groups()[0] + versions.append((op, v)) + ver_remaining = ver_remaining[m.end():] + if not ver_remaining or ver_remaining[0] != ',': + break + ver_remaining = ver_remaining[1:].lstrip() + m = COMPARE_OP.match(ver_remaining) + if not m: + raise SyntaxError('invalid constraint: %s' % ver_remaining) + if not versions: + versions = None + return versions, ver_remaining + + if remaining[0] != '(': + versions, remaining = get_versions(remaining) + else: + i = remaining.find(')', 1) + if i < 0: + raise SyntaxError('unterminated parenthesis: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + # As a special diversion from PEP 508, allow a version number + # a.b.c in parentheses as a synonym for ~= a.b.c (because this + # is allowed in earlier PEPs) + if COMPARE_OP.match(s): + versions, _ = get_versions(s) + else: + m = VERSION_IDENTIFIER.match(s) + if not m: + raise SyntaxError('invalid constraint: %s' % s) + v = m.groups()[0] + s = s[m.end():].lstrip() + if s: + raise SyntaxError('invalid constraint: %s' % s) + versions = [('~=', v)] + + if remaining: + if remaining[0] != ';': + raise SyntaxError('invalid requirement: %s' % remaining) + remaining = remaining[1:].lstrip() + + mark_expr, remaining = parse_marker(remaining) + + if remaining and remaining[0] != '#': + raise SyntaxError('unexpected trailing data: %s' % remaining) + + if not versions: + rs = distname + else: + rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions])) + return Container(name=distname, extras=extras, constraints=versions, + marker=mark_expr, url=uri, requirement=rs) + + +def get_resources_dests(resources_root, rules): + """Find destinations for resources files""" + + def get_rel_path(root, path): + # normalizes and returns a lstripped-/-separated path + root = root.replace(os.path.sep, '/') + path = path.replace(os.path.sep, '/') + assert path.startswith(root) + return path[len(root):].lstrip('/') + + destinations = {} + for base, suffix, dest in rules: + prefix = os.path.join(resources_root, base) + for abs_base in iglob(prefix): + abs_glob = os.path.join(abs_base, suffix) + for abs_path in iglob(abs_glob): + resource_file = get_rel_path(resources_root, abs_path) + if dest is None: # remove the entry if it was here + destinations.pop(resource_file, None) + else: + rel_path = get_rel_path(abs_base, abs_path) + rel_dest = dest.replace(os.path.sep, '/').rstrip('/') + destinations[resource_file] = rel_dest + '/' + rel_path + return destinations + + +def in_venv(): + if hasattr(sys, 'real_prefix'): + # virtualenv venvs + result = True + else: + # PEP 405 venvs + result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) + return result + + +def get_executable(): +# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as +# changes to the stub launcher mean that sys.executable always points +# to the stub on OS X +# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' +# in os.environ): +# result = os.environ['__PYVENV_LAUNCHER__'] +# else: +# result = sys.executable +# return result + result = os.path.normcase(sys.executable) + if not isinstance(result, text_type): + result = fsdecode(result) + return result + + +def proceed(prompt, allowed_chars, error_prompt=None, default=None): + p = prompt + while True: + s = raw_input(p) + p = prompt + if not s and default: + s = default + if s: + c = s[0].lower() + if c in allowed_chars: + break + if error_prompt: + p = '%c: %s\n%s' % (c, error_prompt, prompt) + return c + + +def extract_by_key(d, keys): + if isinstance(keys, string_types): + keys = keys.split() + result = {} + for key in keys: + if key in d: + result[key] = d[key] + return result + +def read_exports(stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + # Try to load as JSON, falling back on legacy format + data = stream.read() + stream = StringIO(data) + try: + jdata = json.load(stream) + result = jdata['extensions']['python.exports']['exports'] + for group, entries in result.items(): + for k, v in entries.items(): + s = '%s = %s' % (k, v) + entry = get_export_entry(s) + assert entry is not None + entries[k] = entry + return result + except Exception: + stream.seek(0, 0) + + def read_stream(cp, stream): + if hasattr(cp, 'read_file'): + cp.read_file(stream) + else: + cp.readfp(stream) + + cp = configparser.ConfigParser() + try: + read_stream(cp, stream) + except configparser.MissingSectionHeaderError: + stream.close() + data = textwrap.dedent(data) + stream = StringIO(data) + read_stream(cp, stream) + + result = {} + for key in cp.sections(): + result[key] = entries = {} + for name, value in cp.items(key): + s = '%s = %s' % (name, value) + entry = get_export_entry(s) + assert entry is not None + #entry.dist = self + entries[name] = entry + return result + + +def write_exports(exports, stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getwriter('utf-8')(stream) + cp = configparser.ConfigParser() + for k, v in exports.items(): + # TODO check k, v for valid values + cp.add_section(k) + for entry in v.values(): + if entry.suffix is None: + s = entry.prefix + else: + s = '%s:%s' % (entry.prefix, entry.suffix) + if entry.flags: + s = '%s [%s]' % (s, ', '.join(entry.flags)) + cp.set(k, entry.name, s) + cp.write(stream) + + +@contextlib.contextmanager +def tempdir(): + td = tempfile.mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + +@contextlib.contextmanager +def chdir(d): + cwd = os.getcwd() + try: + os.chdir(d) + yield + finally: + os.chdir(cwd) + + +@contextlib.contextmanager +def socket_timeout(seconds=15): + cto = socket.getdefaulttimeout() + try: + socket.setdefaulttimeout(seconds) + yield + finally: + socket.setdefaulttimeout(cto) + + +class cached_property(object): + def __init__(self, func): + self.func = func + #for attr in ('__name__', '__module__', '__doc__'): + # setattr(self, attr, getattr(func, attr, None)) + + def __get__(self, obj, cls=None): + if obj is None: + return self + value = self.func(obj) + object.__setattr__(obj, self.func.__name__, value) + #obj.__dict__[self.func.__name__] = value = self.func(obj) + return value + +def convert_path(pathname): + """Return 'pathname' as a name that will work on the native filesystem. + + The path is split on '/' and put back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError("path '%s' cannot be absolute" % pathname) + if pathname[-1] == '/': + raise ValueError("path '%s' cannot end with '/'" % pathname) + + paths = pathname.split('/') + while os.curdir in paths: + paths.remove(os.curdir) + if not paths: + return os.curdir + return os.path.join(*paths) + + +class FileOperator(object): + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.ensured = set() + self._init_record() + + def _init_record(self): + self.record = False + self.files_written = set() + self.dirs_created = set() + + def record_as_written(self, path): + if self.record: + self.files_written.add(path) + + def newer(self, source, target): + """Tell if the target is newer than the source. + + Returns true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. + + Returns false if both exist and 'target' is the same age or younger + than 'source'. Raise PackagingFileError if 'source' does not exist. + + Note that this test is not very accurate: files created in the same + second will have the same "age". + """ + if not os.path.exists(source): + raise DistlibException("file '%r' does not exist" % + os.path.abspath(source)) + if not os.path.exists(target): + return True + + return os.stat(source).st_mtime > os.stat(target).st_mtime + + def copy_file(self, infile, outfile, check=True): + """Copy a file respecting dry-run and force flags. + """ + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying %s to %s', infile, outfile) + if not self.dry_run: + msg = None + if check: + if os.path.islink(outfile): + msg = '%s is a symlink' % outfile + elif os.path.exists(outfile) and not os.path.isfile(outfile): + msg = '%s is a non-regular file' % outfile + if msg: + raise ValueError(msg + ' which would be overwritten') + shutil.copyfile(infile, outfile) + self.record_as_written(outfile) + + def copy_stream(self, instream, outfile, encoding=None): + assert not os.path.isdir(outfile) + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying stream %s to %s', instream, outfile) + if not self.dry_run: + if encoding is None: + outstream = open(outfile, 'wb') + else: + outstream = codecs.open(outfile, 'w', encoding=encoding) + try: + shutil.copyfileobj(instream, outstream) + finally: + outstream.close() + self.record_as_written(outfile) + + def write_binary_file(self, path, data): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + with open(path, 'wb') as f: + f.write(data) + self.record_as_written(path) + + def write_text_file(self, path, data, encoding): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + with open(path, 'wb') as f: + f.write(data.encode(encoding)) + self.record_as_written(path) + + def set_mode(self, bits, mask, files): + if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'): + # Set the executable bits (owner, group, and world) on + # all the files specified. + for f in files: + if self.dry_run: + logger.info("changing mode of %s", f) + else: + mode = (os.stat(f).st_mode | bits) & mask + logger.info("changing mode of %s to %o", f, mode) + os.chmod(f, mode) + + set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) + + def ensure_dir(self, path): + path = os.path.abspath(path) + if path not in self.ensured and not os.path.exists(path): + self.ensured.add(path) + d, f = os.path.split(path) + self.ensure_dir(d) + logger.info('Creating %s' % path) + if not self.dry_run: + os.mkdir(path) + if self.record: + self.dirs_created.add(path) + + def byte_compile(self, path, optimize=False, force=False, prefix=None): + dpath = cache_from_source(path, not optimize) + logger.info('Byte-compiling %s to %s', path, dpath) + if not self.dry_run: + if force or self.newer(path, dpath): + if not prefix: + diagpath = None + else: + assert path.startswith(prefix) + diagpath = path[len(prefix):] + py_compile.compile(path, dpath, diagpath, True) # raise error + self.record_as_written(dpath) + return dpath + + def ensure_removed(self, path): + if os.path.exists(path): + if os.path.isdir(path) and not os.path.islink(path): + logger.debug('Removing directory tree at %s', path) + if not self.dry_run: + shutil.rmtree(path) + if self.record: + if path in self.dirs_created: + self.dirs_created.remove(path) + else: + if os.path.islink(path): + s = 'link' + else: + s = 'file' + logger.debug('Removing %s %s', s, path) + if not self.dry_run: + os.remove(path) + if self.record: + if path in self.files_written: + self.files_written.remove(path) + + def is_writable(self, path): + result = False + while not result: + if os.path.exists(path): + result = os.access(path, os.W_OK) + break + parent = os.path.dirname(path) + if parent == path: + break + path = parent + return result + + def commit(self): + """ + Commit recorded changes, turn off recording, return + changes. + """ + assert self.record + result = self.files_written, self.dirs_created + self._init_record() + return result + + def rollback(self): + if not self.dry_run: + for f in list(self.files_written): + if os.path.exists(f): + os.remove(f) + # dirs should all be empty now, except perhaps for + # __pycache__ subdirs + # reverse so that subdirs appear before their parents + dirs = sorted(self.dirs_created, reverse=True) + for d in dirs: + flist = os.listdir(d) + if flist: + assert flist == ['__pycache__'] + sd = os.path.join(d, flist[0]) + os.rmdir(sd) + os.rmdir(d) # should fail if non-empty + self._init_record() + +def resolve(module_name, dotted_path): + if module_name in sys.modules: + mod = sys.modules[module_name] + else: + mod = __import__(module_name) + if dotted_path is None: + result = mod + else: + parts = dotted_path.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + +class ExportEntry(object): + def __init__(self, name, prefix, suffix, flags): + self.name = name + self.prefix = prefix + self.suffix = suffix + self.flags = flags + + @cached_property + def value(self): + return resolve(self.prefix, self.suffix) + + def __repr__(self): # pragma: no cover + return '<ExportEntry %s = %s:%s %s>' % (self.name, self.prefix, + self.suffix, self.flags) + + def __eq__(self, other): + if not isinstance(other, ExportEntry): + result = False + else: + result = (self.name == other.name and + self.prefix == other.prefix and + self.suffix == other.suffix and + self.flags == other.flags) + return result + + __hash__ = object.__hash__ + + +ENTRY_RE = re.compile(r'''(?P<name>(\w|[-.+])+) + \s*=\s*(?P<callable>(\w+)([:\.]\w+)*) + \s*(\[\s*(?P<flags>\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? + ''', re.VERBOSE) + +def get_export_entry(specification): + m = ENTRY_RE.search(specification) + if not m: + result = None + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + else: + d = m.groupdict() + name = d['name'] + path = d['callable'] + colons = path.count(':') + if colons == 0: + prefix, suffix = path, None + else: + if colons != 1: + raise DistlibException("Invalid specification " + "'%s'" % specification) + prefix, suffix = path.split(':') + flags = d['flags'] + if flags is None: + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + flags = [] + else: + flags = [f.strip() for f in flags.split(',')] + result = ExportEntry(name, prefix, suffix, flags) + return result + + +def get_cache_base(suffix=None): + """ + Return the default base location for distlib caches. If the directory does + not exist, it is created. Use the suffix provided for the base directory, + and default to '.distlib' if it isn't provided. + + On Windows, if LOCALAPPDATA is defined in the environment, then it is + assumed to be a directory, and will be the parent directory of the result. + On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home + directory - using os.expanduser('~') - will be the parent directory of + the result. + + The result is just the directory '.distlib' in the parent directory as + determined above, or with the name specified with ``suffix``. + """ + if suffix is None: + suffix = '.distlib' + if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: + result = os.path.expandvars('$localappdata') + else: + # Assume posix, or old Windows + result = os.path.expanduser('~') + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if os.path.isdir(result): + usable = os.access(result, os.W_OK) + if not usable: + logger.warning('Directory exists but is not writable: %s', result) + else: + try: + os.makedirs(result) + usable = True + except OSError: + logger.warning('Unable to create %s', result, exc_info=True) + usable = False + if not usable: + result = tempfile.mkdtemp() + logger.warning('Default location unusable, using %s', result) + return os.path.join(result, suffix) + + +def path_to_cache_dir(path): + """ + Convert an absolute path to a directory name for use in a cache. + + The algorithm used is: + + #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. + #. Any occurrence of ``os.sep`` is replaced with ``'--'``. + #. ``'.cache'`` is appended. + """ + d, p = os.path.splitdrive(os.path.abspath(path)) + if d: + d = d.replace(':', '---') + p = p.replace(os.sep, '--') + return d + p + '.cache' + + +def ensure_slash(s): + if not s.endswith('/'): + return s + '/' + return s + + +def parse_credentials(netloc): + username = password = None + if '@' in netloc: + prefix, netloc = netloc.split('@', 1) + if ':' not in prefix: + username = prefix + else: + username, password = prefix.split(':', 1) + return username, password, netloc + + +def get_process_umask(): + result = os.umask(0o22) + os.umask(result) + return result + +def is_string_sequence(seq): + result = True + i = None + for i, s in enumerate(seq): + if not isinstance(s, string_types): + result = False + break + assert i is not None + return result + +PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' + '([a-z0-9_.+-]+)', re.I) +PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') + + +def split_filename(filename, project_name=None): + """ + Extract name, version, python version from a filename (no extension) + + Return name, version, pyver or None + """ + result = None + pyver = None + filename = unquote(filename).replace(' ', '-') + m = PYTHON_VERSION.search(filename) + if m: + pyver = m.group(1) + filename = filename[:m.start()] + if project_name and len(filename) > len(project_name) + 1: + m = re.match(re.escape(project_name) + r'\b', filename) + if m: + n = m.end() + result = filename[:n], filename[n + 1:], pyver + if result is None: + m = PROJECT_NAME_AND_VERSION.match(filename) + if m: + result = m.group(1), m.group(3), pyver + return result + +# Allow spaces in name because of legacy dists like "Twisted Core" +NAME_VERSION_RE = re.compile(r'(?P<name>[\w .-]+)\s*' + r'\(\s*(?P<ver>[^\s)]+)\)$') + +def parse_name_and_version(p): + """ + A utility method used to get name and version from a string. + + From e.g. a Provides-Dist value. + + :param p: A value in a form 'foo (1.0)' + :return: The name and version as a tuple. + """ + m = NAME_VERSION_RE.match(p) + if not m: + raise DistlibException('Ill-formed name/version string: \'%s\'' % p) + d = m.groupdict() + return d['name'].strip().lower(), d['ver'] + +def get_extras(requested, available): + result = set() + requested = set(requested or []) + available = set(available or []) + if '*' in requested: + requested.remove('*') + result |= available + for r in requested: + if r == '-': + result.add(r) + elif r.startswith('-'): + unwanted = r[1:] + if unwanted not in available: + logger.warning('undeclared extra: %s' % unwanted) + if unwanted in result: + result.remove(unwanted) + else: + if r not in available: + logger.warning('undeclared extra: %s' % r) + result.add(r) + return result +# +# Extended metadata functionality +# + +def _get_external_data(url): + result = {} + try: + # urlopen might fail if it runs into redirections, + # because of Python issue #13696. Fixed in locators + # using a custom redirect handler. + resp = urlopen(url) + headers = resp.info() + ct = headers.get('Content-Type') + if not ct.startswith('application/json'): + logger.debug('Unexpected response for JSON request: %s', ct) + else: + reader = codecs.getreader('utf-8')(resp) + #data = reader.read().decode('utf-8') + #result = json.loads(data) + result = json.load(reader) + except Exception as e: + logger.exception('Failed to get external data for %s: %s', url, e) + return result + +_external_data_base_url = 'https://www.red-dove.com/pypi/projects/' + +def get_project_data(name): + url = '%s/%s/project.json' % (name[0].upper(), name) + url = urljoin(_external_data_base_url, url) + result = _get_external_data(url) + return result + +def get_package_data(name, version): + url = '%s/%s/package-%s.json' % (name[0].upper(), name, version) + url = urljoin(_external_data_base_url, url) + return _get_external_data(url) + + +class Cache(object): + """ + A class implementing a cache for resources that need to live in the file system + e.g. shared libraries. This class was moved from resources to here because it + could be used by other modules, e.g. the wheel module. + """ + + def __init__(self, base): + """ + Initialise an instance. + + :param base: The base directory where the cache should be located. + """ + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if not os.path.isdir(base): # pragma: no cover + os.makedirs(base) + if (os.stat(base).st_mode & 0o77) != 0: + logger.warning('Directory \'%s\' is not private', base) + self.base = os.path.abspath(os.path.normpath(base)) + + def prefix_to_dir(self, prefix): + """ + Converts a resource prefix to a directory name in the cache. + """ + return path_to_cache_dir(prefix) + + def clear(self): + """ + Clear the cache. + """ + not_removed = [] + for fn in os.listdir(self.base): + fn = os.path.join(self.base, fn) + try: + if os.path.islink(fn) or os.path.isfile(fn): + os.remove(fn) + elif os.path.isdir(fn): + shutil.rmtree(fn) + except Exception: + not_removed.append(fn) + return not_removed + + +class EventMixin(object): + """ + A very simple publish/subscribe system. + """ + def __init__(self): + self._subscribers = {} + + def add(self, event, subscriber, append=True): + """ + Add a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be added (and called when the + event is published). + :param append: Whether to append or prepend the subscriber to an + existing subscriber list for the event. + """ + subs = self._subscribers + if event not in subs: + subs[event] = deque([subscriber]) + else: + sq = subs[event] + if append: + sq.append(subscriber) + else: + sq.appendleft(subscriber) + + def remove(self, event, subscriber): + """ + Remove a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be removed. + """ + subs = self._subscribers + if event not in subs: + raise ValueError('No subscribers: %r' % event) + subs[event].remove(subscriber) + + def get_subscribers(self, event): + """ + Return an iterator for the subscribers for an event. + :param event: The event to return subscribers for. + """ + return iter(self._subscribers.get(event, ())) + + def publish(self, event, *args, **kwargs): + """ + Publish a event and return a list of values returned by its + subscribers. + + :param event: The event to publish. + :param args: The positional arguments to pass to the event's + subscribers. + :param kwargs: The keyword arguments to pass to the event's + subscribers. + """ + result = [] + for subscriber in self.get_subscribers(event): + try: + value = subscriber(event, *args, **kwargs) + except Exception: + logger.exception('Exception during event publication') + value = None + result.append(value) + logger.debug('publish %s: args = %s, kwargs = %s, result = %s', + event, args, kwargs, result) + return result + +# +# Simple sequencing +# +class Sequencer(object): + def __init__(self): + self._preds = {} + self._succs = {} + self._nodes = set() # nodes with no preds/succs + + def add_node(self, node): + self._nodes.add(node) + + def remove_node(self, node, edges=False): + if node in self._nodes: + self._nodes.remove(node) + if edges: + for p in set(self._preds.get(node, ())): + self.remove(p, node) + for s in set(self._succs.get(node, ())): + self.remove(node, s) + # Remove empties + for k, v in list(self._preds.items()): + if not v: + del self._preds[k] + for k, v in list(self._succs.items()): + if not v: + del self._succs[k] + + def add(self, pred, succ): + assert pred != succ + self._preds.setdefault(succ, set()).add(pred) + self._succs.setdefault(pred, set()).add(succ) + + def remove(self, pred, succ): + assert pred != succ + try: + preds = self._preds[succ] + succs = self._succs[pred] + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of anything' % succ) + try: + preds.remove(pred) + succs.remove(succ) + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of %r' % (succ, pred)) + + def is_step(self, step): + return (step in self._preds or step in self._succs or + step in self._nodes) + + def get_steps(self, final): + if not self.is_step(final): + raise ValueError('Unknown: %r' % final) + result = [] + todo = [] + seen = set() + todo.append(final) + while todo: + step = todo.pop(0) + if step in seen: + # if a step was already seen, + # move it to the end (so it will appear earlier + # when reversed on return) ... but not for the + # final step, as that would be confusing for + # users + if step != final: + result.remove(step) + result.append(step) + else: + seen.add(step) + result.append(step) + preds = self._preds.get(step, ()) + todo.extend(preds) + return reversed(result) + + @property + def strong_connections(self): + #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + index_counter = [0] + stack = [] + lowlinks = {} + index = {} + result = [] + + graph = self._succs + + def strongconnect(node): + # set the depth index for this node to the smallest unused index + index[node] = index_counter[0] + lowlinks[node] = index_counter[0] + index_counter[0] += 1 + stack.append(node) + + # Consider successors + try: + successors = graph[node] + except Exception: + successors = [] + for successor in successors: + if successor not in lowlinks: + # Successor has not yet been visited + strongconnect(successor) + lowlinks[node] = min(lowlinks[node],lowlinks[successor]) + elif successor in stack: + # the successor is in the stack and hence in the current + # strongly connected component (SCC) + lowlinks[node] = min(lowlinks[node],index[successor]) + + # If `node` is a root node, pop the stack and generate an SCC + if lowlinks[node] == index[node]: + connected_component = [] + + while True: + successor = stack.pop() + connected_component.append(successor) + if successor == node: break + component = tuple(connected_component) + # storing the result + result.append(component) + + for node in graph: + if node not in lowlinks: + strongconnect(node) + + return result + + @property + def dot(self): + result = ['digraph G {'] + for succ in self._preds: + preds = self._preds[succ] + for pred in preds: + result.append(' %s -> %s;' % (pred, succ)) + for node in self._nodes: + result.append(' %s;' % node) + result.append('}') + return '\n'.join(result) + +# +# Unarchiving functionality for zip, tar, tgz, tbz, whl +# + +ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', + '.tgz', '.tbz', '.whl') + +def unarchive(archive_filename, dest_dir, format=None, check=True): + + def check_path(path): + if not isinstance(path, text_type): + path = path.decode('utf-8') + p = os.path.abspath(os.path.join(dest_dir, path)) + if not p.startswith(dest_dir) or p[plen] != os.sep: + raise ValueError('path outside destination: %r' % p) + + dest_dir = os.path.abspath(dest_dir) + plen = len(dest_dir) + archive = None + if format is None: + if archive_filename.endswith(('.zip', '.whl')): + format = 'zip' + elif archive_filename.endswith(('.tar.gz', '.tgz')): + format = 'tgz' + mode = 'r:gz' + elif archive_filename.endswith(('.tar.bz2', '.tbz')): + format = 'tbz' + mode = 'r:bz2' + elif archive_filename.endswith('.tar'): + format = 'tar' + mode = 'r' + else: # pragma: no cover + raise ValueError('Unknown format for %r' % archive_filename) + try: + if format == 'zip': + archive = ZipFile(archive_filename, 'r') + if check: + names = archive.namelist() + for name in names: + check_path(name) + else: + archive = tarfile.open(archive_filename, mode) + if check: + names = archive.getnames() + for name in names: + check_path(name) + if format != 'zip' and sys.version_info[0] < 3: + # See Python issue 17153. If the dest path contains Unicode, + # tarfile extraction fails on Python 2.x if a member path name + # contains non-ASCII characters - it leads to an implicit + # bytes -> unicode conversion using ASCII to decode. + for tarinfo in archive.getmembers(): + if not isinstance(tarinfo.name, text_type): + tarinfo.name = tarinfo.name.decode('utf-8') + archive.extractall(dest_dir) + + finally: + if archive: + archive.close() + + +def zip_dir(directory): + """zip a directory tree into a BytesIO object""" + result = io.BytesIO() + dlen = len(directory) + with ZipFile(result, "w") as zf: + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + rel = root[dlen:] + dest = os.path.join(rel, name) + zf.write(full, dest) + return result + +# +# Simple progress bar +# + +UNITS = ('', 'K', 'M', 'G','T','P') + + +class Progress(object): + unknown = 'UNKNOWN' + + def __init__(self, minval=0, maxval=100): + assert maxval is None or maxval >= minval + self.min = self.cur = minval + self.max = maxval + self.started = None + self.elapsed = 0 + self.done = False + + def update(self, curval): + assert self.min <= curval + assert self.max is None or curval <= self.max + self.cur = curval + now = time.time() + if self.started is None: + self.started = now + else: + self.elapsed = now - self.started + + def increment(self, incr): + assert incr >= 0 + self.update(self.cur + incr) + + def start(self): + self.update(self.min) + return self + + def stop(self): + if self.max is not None: + self.update(self.max) + self.done = True + + @property + def maximum(self): + return self.unknown if self.max is None else self.max + + @property + def percentage(self): + if self.done: + result = '100 %' + elif self.max is None: + result = ' ?? %' + else: + v = 100.0 * (self.cur - self.min) / (self.max - self.min) + result = '%3d %%' % v + return result + + def format_duration(self, duration): + if (duration <= 0) and self.max is None or self.cur == self.min: + result = '??:??:??' + #elif duration < 1: + # result = '--:--:--' + else: + result = time.strftime('%H:%M:%S', time.gmtime(duration)) + return result + + @property + def ETA(self): + if self.done: + prefix = 'Done' + t = self.elapsed + #import pdb; pdb.set_trace() + else: + prefix = 'ETA ' + if self.max is None: + t = -1 + elif self.elapsed == 0 or (self.cur == self.min): + t = 0 + else: + #import pdb; pdb.set_trace() + t = float(self.max - self.min) + t /= self.cur - self.min + t = (t - 1) * self.elapsed + return '%s: %s' % (prefix, self.format_duration(t)) + + @property + def speed(self): + if self.elapsed == 0: + result = 0.0 + else: + result = (self.cur - self.min) / self.elapsed + for unit in UNITS: + if result < 1000: + break + result /= 1000.0 + return '%d %sB/s' % (result, unit) + +# +# Glob functionality +# + +RICH_GLOB = re.compile(r'\{([^}]*)\}') +_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') +_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') + + +def iglob(path_glob): + """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" + if _CHECK_RECURSIVE_GLOB.search(path_glob): + msg = """invalid glob %r: recursive glob "**" must be used alone""" + raise ValueError(msg % path_glob) + if _CHECK_MISMATCH_SET.search(path_glob): + msg = """invalid glob %r: mismatching set marker '{' or '}'""" + raise ValueError(msg % path_glob) + return _iglob(path_glob) + + +def _iglob(path_glob): + rich_path_glob = RICH_GLOB.split(path_glob, 1) + if len(rich_path_glob) > 1: + assert len(rich_path_glob) == 3, rich_path_glob + prefix, set, suffix = rich_path_glob + for item in set.split(','): + for path in _iglob(''.join((prefix, item, suffix))): + yield path + else: + if '**' not in path_glob: + for item in std_iglob(path_glob): + yield item + else: + prefix, radical = path_glob.split('**', 1) + if prefix == '': + prefix = '.' + if radical == '': + radical = '*' + else: + # we support both + radical = radical.lstrip('/') + radical = radical.lstrip('\\') + for path, dir, files in os.walk(prefix): + path = os.path.normpath(path) + for fn in _iglob(os.path.join(path, radical)): + yield fn + +if ssl: + from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname, + CertificateError) + + +# +# HTTPSConnection which verifies certificates/matches domains +# + + class HTTPSConnection(httplib.HTTPSConnection): + ca_certs = None # set this to the path to the certs file (.pem) + check_domain = True # only used if ca_certs is not None + + # noinspection PyPropertyAccess + def connect(self): + sock = socket.create_connection((self.host, self.port), self.timeout) + if getattr(self, '_tunnel_host', False): + self.sock = sock + self._tunnel() + + if not hasattr(ssl, 'SSLContext'): + # For 2.x + if self.ca_certs: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, + cert_reqs=cert_reqs, + ssl_version=ssl.PROTOCOL_SSLv23, + ca_certs=self.ca_certs) + else: # pragma: no cover + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + context.options |= ssl.OP_NO_SSLv2 + if self.cert_file: + context.load_cert_chain(self.cert_file, self.key_file) + kwargs = {} + if self.ca_certs: + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(cafile=self.ca_certs) + if getattr(ssl, 'HAS_SNI', False): + kwargs['server_hostname'] = self.host + self.sock = context.wrap_socket(sock, **kwargs) + if self.ca_certs and self.check_domain: + try: + match_hostname(self.sock.getpeercert(), self.host) + logger.debug('Host verified: %s', self.host) + except CertificateError: # pragma: no cover + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + class HTTPSHandler(BaseHTTPSHandler): + def __init__(self, ca_certs, check_domain=True): + BaseHTTPSHandler.__init__(self) + self.ca_certs = ca_certs + self.check_domain = check_domain + + def _conn_maker(self, *args, **kwargs): + """ + This is called to create a connection instance. Normally you'd + pass a connection class to do_open, but it doesn't actually check for + a class, and just expects a callable. As long as we behave just as a + constructor would have, we should be OK. If it ever changes so that + we *must* pass a class, we'll create an UnsafeHTTPSConnection class + which just sets check_domain to False in the class definition, and + choose which one to pass to do_open. + """ + result = HTTPSConnection(*args, **kwargs) + if self.ca_certs: + result.ca_certs = self.ca_certs + result.check_domain = self.check_domain + return result + + def https_open(self, req): + try: + return self.do_open(self._conn_maker, req) + except URLError as e: + if 'certificate verify failed' in str(e.reason): + raise CertificateError('Unable to verify server certificate ' + 'for %s' % req.host) + else: + raise + + # + # To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- + # Middle proxy using HTTP listens on port 443, or an index mistakenly serves + # HTML containing a http://xyz link when it should be https://xyz), + # you can use the following handler class, which does not allow HTTP traffic. + # + # It works by inheriting from HTTPHandler - so build_opener won't add a + # handler for HTTP itself. + # + class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): + def http_open(self, req): + raise URLError('Unexpected HTTP request on what should be a secure ' + 'connection: %s' % req) + +# +# XML-RPC with timeouts +# + +_ver_info = sys.version_info[:2] + +if _ver_info == (2, 6): + class HTTP(httplib.HTTP): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + + if ssl: + class HTTPS(httplib.HTTPS): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + +class Transport(xmlrpclib.Transport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.Transport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, x509 = self.get_host_info(host) + if _ver_info == (2, 6): + result = HTTP(h, timeout=self.timeout) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPConnection(h) + result = self._connection[1] + return result + +if ssl: + class SafeTransport(xmlrpclib.SafeTransport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.SafeTransport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, kwargs = self.get_host_info(host) + if not kwargs: + kwargs = {} + kwargs['timeout'] = self.timeout + if _ver_info == (2, 6): + result = HTTPS(host, None, **kwargs) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPSConnection(h, None, + **kwargs) + result = self._connection[1] + return result + + +class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, **kwargs): + self.timeout = timeout = kwargs.pop('timeout', None) + # The above classes only come into play if a timeout + # is specified + if timeout is not None: + scheme, _ = splittype(uri) + use_datetime = kwargs.get('use_datetime', 0) + if scheme == 'https': + tcls = SafeTransport + else: + tcls = Transport + kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) + self.transport = t + xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) + +# +# CSV functionality. This is provided because on 2.x, the csv module can't +# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. +# + +def _csv_open(fn, mode, **kwargs): + if sys.version_info[0] < 3: + mode += 'b' + else: + kwargs['newline'] = '' + # Python 3 determines encoding from locale. Force 'utf-8' + # file encoding to match other forced utf-8 encoding + kwargs['encoding'] = 'utf-8' + return open(fn, mode, **kwargs) + + +class CSVBase(object): + defaults = { + 'delimiter': str(','), # The strs are used because we need native + 'quotechar': str('"'), # str in the csv API (2.x won't take + 'lineterminator': str('\n') # Unicode) + } + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.stream.close() + + +class CSVReader(CSVBase): + def __init__(self, **kwargs): + if 'stream' in kwargs: + stream = kwargs['stream'] + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + self.stream = stream + else: + self.stream = _csv_open(kwargs['path'], 'r') + self.reader = csv.reader(self.stream, **self.defaults) + + def __iter__(self): + return self + + def next(self): + result = next(self.reader) + if sys.version_info[0] < 3: + for i, item in enumerate(result): + if not isinstance(item, text_type): + result[i] = item.decode('utf-8') + return result + + __next__ = next + +class CSVWriter(CSVBase): + def __init__(self, fn, **kwargs): + self.stream = _csv_open(fn, 'w') + self.writer = csv.writer(self.stream, **self.defaults) + + def writerow(self, row): + if sys.version_info[0] < 3: + r = [] + for item in row: + if isinstance(item, text_type): + item = item.encode('utf-8') + r.append(item) + row = r + self.writer.writerow(row) + +# +# Configurator functionality +# + +class Configurator(BaseConfigurator): + + value_converters = dict(BaseConfigurator.value_converters) + value_converters['inc'] = 'inc_convert' + + def __init__(self, config, base=None): + super(Configurator, self).__init__(config) + self.base = base or os.getcwd() + + def configure_custom(self, config): + def convert(o): + if isinstance(o, (list, tuple)): + result = type(o)([convert(i) for i in o]) + elif isinstance(o, dict): + if '()' in o: + result = self.configure_custom(o) + else: + result = {} + for k in o: + result[k] = convert(o[k]) + else: + result = self.convert(o) + return result + + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + args = config.pop('[]', ()) + if args: + args = tuple([convert(o) for o in args]) + items = [(k, convert(config[k])) for k in config if valid_ident(k)] + kwargs = dict(items) + result = c(*args, **kwargs) + if props: + for n, v in props.items(): + setattr(result, n, convert(v)) + return result + + def __getitem__(self, key): + result = self.config[key] + if isinstance(result, dict) and '()' in result: + self.config[key] = result = self.configure_custom(result) + return result + + def inc_convert(self, value): + """Default converter for the inc:// protocol.""" + if not os.path.isabs(value): + value = os.path.join(self.base, value) + with codecs.open(value, 'r', encoding='utf-8') as f: + result = json.load(f) + return result + + +class SubprocessMixin(object): + """ + Mixin for running subprocesses and capturing their output + """ + def __init__(self, verbose=False, progress=None): + self.verbose = verbose + self.progress = progress + + def reader(self, stream, context): + """ + Read lines from a subprocess' output stream and either pass to a progress + callable (if specified) or write progress information to sys.stderr. + """ + progress = self.progress + verbose = self.verbose + while True: + s = stream.readline() + if not s: + break + if progress is not None: + progress(s, context) + else: + if not verbose: + sys.stderr.write('.') + else: + sys.stderr.write(s.decode('utf-8')) + sys.stderr.flush() + stream.close() + + def run_command(self, cmd, **kwargs): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, **kwargs) + t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) + t1.start() + t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) + t2.start() + p.wait() + t1.join() + t2.join() + if self.progress is not None: + self.progress('done.', 'main') + elif self.verbose: + sys.stderr.write('done.\n') + return p + + +def normalize_name(name): + """Normalize a python package name a la PEP 503""" + # https://www.python.org/dev/peps/pep-0503/#normalized-names + return re.sub('[-_.]+', '-', name).lower() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/version.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/version.py new file mode 100644 index 0000000..3eebe18 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/version.py @@ -0,0 +1,736 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Implementation of a flexible versioning scheme providing support for PEP-440, +setuptools-compatible and semantic versioning. +""" + +import logging +import re + +from .compat import string_types +from .util import parse_requirement + +__all__ = ['NormalizedVersion', 'NormalizedMatcher', + 'LegacyVersion', 'LegacyMatcher', + 'SemanticVersion', 'SemanticMatcher', + 'UnsupportedVersionError', 'get_scheme'] + +logger = logging.getLogger(__name__) + + +class UnsupportedVersionError(ValueError): + """This is an unsupported version.""" + pass + + +class Version(object): + def __init__(self, s): + self._string = s = s.strip() + self._parts = parts = self.parse(s) + assert isinstance(parts, tuple) + assert len(parts) > 0 + + def parse(self, s): + raise NotImplementedError('please implement in a subclass') + + def _check_compatible(self, other): + if type(self) != type(other): + raise TypeError('cannot compare %r and %r' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + def __lt__(self, other): + self._check_compatible(other) + return self._parts < other._parts + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__lt__(other) or self.__eq__(other) + + def __ge__(self, other): + return self.__gt__(other) or self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self._parts) + + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + @property + def is_prerelease(self): + raise NotImplementedError('Please implement in subclasses.') + + +class Matcher(object): + version_class = None + + # value is either a callable or the name of a method + _operators = { + '<': lambda v, c, p: v < c, + '>': lambda v, c, p: v > c, + '<=': lambda v, c, p: v == c or v < c, + '>=': lambda v, c, p: v == c or v > c, + '==': lambda v, c, p: v == c, + '===': lambda v, c, p: v == c, + # by default, compatible => >=. + '~=': lambda v, c, p: v == c or v > c, + '!=': lambda v, c, p: v != c, + } + + # this is a method only to support alternative implementations + # via overriding + def parse_requirement(self, s): + return parse_requirement(s) + + def __init__(self, s): + if self.version_class is None: + raise ValueError('Please specify a version class') + self._string = s = s.strip() + r = self.parse_requirement(s) + if not r: + raise ValueError('Not valid: %r' % s) + self.name = r.name + self.key = self.name.lower() # for case-insensitive comparisons + clist = [] + if r.constraints: + # import pdb; pdb.set_trace() + for op, s in r.constraints: + if s.endswith('.*'): + if op not in ('==', '!='): + raise ValueError('\'.*\' not allowed for ' + '%r constraints' % op) + # Could be a partial version (e.g. for '2.*') which + # won't parse as a version, so keep it as a string + vn, prefix = s[:-2], True + # Just to check that vn is a valid version + self.version_class(vn) + else: + # Should parse as a version, so we can create an + # instance for the comparison + vn, prefix = self.version_class(s), False + clist.append((op, vn, prefix)) + self._parts = tuple(clist) + + def match(self, version): + """ + Check if the provided version matches the constraints. + + :param version: The version to match against this instance. + :type version: String or :class:`Version` instance. + """ + if isinstance(version, string_types): + version = self.version_class(version) + for operator, constraint, prefix in self._parts: + f = self._operators.get(operator) + if isinstance(f, string_types): + f = getattr(self, f) + if not f: + msg = ('%r not implemented ' + 'for %s' % (operator, self.__class__.__name__)) + raise NotImplementedError(msg) + if not f(version, constraint, prefix): + return False + return True + + @property + def exact_version(self): + result = None + if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='): + result = self._parts[0][1] + return result + + def _check_compatible(self, other): + if type(self) != type(other) or self.name != other.name: + raise TypeError('cannot compare %s and %s' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self.key == other.key and self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self.key) + hash(self._parts) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + +PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?' + r'(\.(post)(\d+))?(\.(dev)(\d+))?' + r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$') + + +def _pep_440_key(s): + s = s.strip() + m = PEP440_VERSION_RE.match(s) + if not m: + raise UnsupportedVersionError('Not a valid version: %s' % s) + groups = m.groups() + nums = tuple(int(v) for v in groups[1].split('.')) + while len(nums) > 1 and nums[-1] == 0: + nums = nums[:-1] + + if not groups[0]: + epoch = 0 + else: + epoch = int(groups[0]) + pre = groups[4:6] + post = groups[7:9] + dev = groups[10:12] + local = groups[13] + if pre == (None, None): + pre = () + else: + pre = pre[0], int(pre[1]) + if post == (None, None): + post = () + else: + post = post[0], int(post[1]) + if dev == (None, None): + dev = () + else: + dev = dev[0], int(dev[1]) + if local is None: + local = () + else: + parts = [] + for part in local.split('.'): + # to ensure that numeric compares as > lexicographic, avoid + # comparing them directly, but encode a tuple which ensures + # correct sorting + if part.isdigit(): + part = (1, int(part)) + else: + part = (0, part) + parts.append(part) + local = tuple(parts) + if not pre: + # either before pre-release, or final release and after + if not post and dev: + # before pre-release + pre = ('a', -1) # to sort before a0 + else: + pre = ('z',) # to sort after all pre-releases + # now look at the state of post and dev. + if not post: + post = ('_',) # sort before 'a' + if not dev: + dev = ('final',) + + #print('%s -> %s' % (s, m.groups())) + return epoch, nums, pre, post, dev, local + + +_normalized_key = _pep_440_key + + +class NormalizedVersion(Version): + """A rational version. + + Good: + 1.2 # equivalent to "1.2.0" + 1.2.0 + 1.2a1 + 1.2.3a2 + 1.2.3b1 + 1.2.3c1 + 1.2.3.4 + TODO: fill this out + + Bad: + 1 # minimum two numbers + 1.2a # release level must have a release serial + 1.2.3b + """ + def parse(self, s): + result = _normalized_key(s) + # _normalized_key loses trailing zeroes in the release + # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 + # However, PEP 440 prefix matching needs it: for example, + # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). + m = PEP440_VERSION_RE.match(s) # must succeed + groups = m.groups() + self._release_clause = tuple(int(v) for v in groups[1].split('.')) + return result + + PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) + + @property + def is_prerelease(self): + return any(t[0] in self.PREREL_TAGS for t in self._parts if t) + + +def _match_prefix(x, y): + x = str(x) + y = str(y) + if x == y: + return True + if not x.startswith(y): + return False + n = len(y) + return x[n] == '.' + + +class NormalizedMatcher(Matcher): + version_class = NormalizedVersion + + # value is either a callable or the name of a method + _operators = { + '~=': '_match_compatible', + '<': '_match_lt', + '>': '_match_gt', + '<=': '_match_le', + '>=': '_match_ge', + '==': '_match_eq', + '===': '_match_arbitrary', + '!=': '_match_ne', + } + + def _adjust_local(self, version, constraint, prefix): + if prefix: + strip_local = '+' not in constraint and version._parts[-1] + else: + # both constraint and version are + # NormalizedVersion instances. + # If constraint does not have a local component, + # ensure the version doesn't, either. + strip_local = not constraint._parts[-1] and version._parts[-1] + if strip_local: + s = version._string.split('+', 1)[0] + version = self.version_class(s) + return version, constraint + + def _match_lt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version >= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_gt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version <= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_le(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version <= constraint + + def _match_ge(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version >= constraint + + def _match_eq(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version == constraint) + else: + result = _match_prefix(version, constraint) + return result + + def _match_arbitrary(self, version, constraint, prefix): + return str(version) == str(constraint) + + def _match_ne(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version != constraint) + else: + result = not _match_prefix(version, constraint) + return result + + def _match_compatible(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version == constraint: + return True + if version < constraint: + return False +# if not prefix: +# return True + release_clause = constraint._release_clause + if len(release_clause) > 1: + release_clause = release_clause[:-1] + pfx = '.'.join([str(i) for i in release_clause]) + return _match_prefix(version, pfx) + +_REPLACEMENTS = ( + (re.compile('[.+-]$'), ''), # remove trailing puncts + (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start + (re.compile('^[.-]'), ''), # remove leading puncts + (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses + (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha + (re.compile(r'\b(pre-alpha|prealpha)\b'), + 'pre.alpha'), # standardise + (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses +) + +_SUFFIX_REPLACEMENTS = ( + (re.compile('^[:~._+-]+'), ''), # remove leading puncts + (re.compile('[,*")([\\]]'), ''), # remove unwanted chars + (re.compile('[~:+_ -]'), '.'), # replace illegal chars + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\.$'), ''), # trailing '.' +) + +_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') + + +def _suggest_semantic_version(s): + """ + Try to suggest a semantic form for a version for which + _suggest_normalized_version couldn't come up with anything. + """ + result = s.strip().lower() + for pat, repl in _REPLACEMENTS: + result = pat.sub(repl, result) + if not result: + result = '0.0.0' + + # Now look for numeric prefix, and separate it out from + # the rest. + #import pdb; pdb.set_trace() + m = _NUMERIC_PREFIX.match(result) + if not m: + prefix = '0.0.0' + suffix = result + else: + prefix = m.groups()[0].split('.') + prefix = [int(i) for i in prefix] + while len(prefix) < 3: + prefix.append(0) + if len(prefix) == 3: + suffix = result[m.end():] + else: + suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] + prefix = prefix[:3] + prefix = '.'.join([str(i) for i in prefix]) + suffix = suffix.strip() + if suffix: + #import pdb; pdb.set_trace() + # massage the suffix. + for pat, repl in _SUFFIX_REPLACEMENTS: + suffix = pat.sub(repl, suffix) + + if not suffix: + result = prefix + else: + sep = '-' if 'dev' in suffix else '+' + result = prefix + sep + suffix + if not is_semver(result): + result = None + return result + + +def _suggest_normalized_version(s): + """Suggest a normalized version close to the given version string. + + If you have a version string that isn't rational (i.e. NormalizedVersion + doesn't like it) then you might be able to get an equivalent (or close) + rational version from this function. + + This does a number of simple normalizations to the given string, based + on observation of versions currently in use on PyPI. Given a dump of + those version during PyCon 2009, 4287 of them: + - 2312 (53.93%) match NormalizedVersion without change + with the automatic suggestion + - 3474 (81.04%) match when using this suggestion method + + @param s {str} An irrational version string. + @returns A rational version string, or None, if couldn't determine one. + """ + try: + _normalized_key(s) + return s # already rational + except UnsupportedVersionError: + pass + + rs = s.lower() + + # part of this could use maketrans + for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), + ('beta', 'b'), ('rc', 'c'), ('-final', ''), + ('-pre', 'c'), + ('-release', ''), ('.release', ''), ('-stable', ''), + ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), + ('final', '')): + rs = rs.replace(orig, repl) + + # if something ends with dev or pre, we add a 0 + rs = re.sub(r"pre$", r"pre0", rs) + rs = re.sub(r"dev$", r"dev0", rs) + + # if we have something like "b-2" or "a.2" at the end of the + # version, that is probably beta, alpha, etc + # let's remove the dash or dot + rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) + + # 1.0-dev-r371 -> 1.0.dev371 + # 0.1-dev-r79 -> 0.1.dev79 + rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) + + # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 + rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) + + # Clean: v0.3, v1.0 + if rs.startswith('v'): + rs = rs[1:] + + # Clean leading '0's on numbers. + #TODO: unintended side-effect on, e.g., "2003.05.09" + # PyPI stats: 77 (~2%) better + rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) + + # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers + # zero. + # PyPI stats: 245 (7.56%) better + rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) + + # the 'dev-rNNN' tag is a dev tag + rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) + + # clean the - when used as a pre delimiter + rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) + + # a terminal "dev" or "devel" can be changed into ".dev0" + rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) + + # a terminal "dev" can be changed into ".dev0" + rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) + + # a terminal "final" or "stable" can be removed + rs = re.sub(r"(final|stable)$", "", rs) + + # The 'r' and the '-' tags are post release tags + # 0.4a1.r10 -> 0.4a1.post10 + # 0.9.33-17222 -> 0.9.33.post17222 + # 0.9.33-r17222 -> 0.9.33.post17222 + rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) + + # Clean 'r' instead of 'dev' usage: + # 0.9.33+r17222 -> 0.9.33.dev17222 + # 1.0dev123 -> 1.0.dev123 + # 1.0.git123 -> 1.0.dev123 + # 1.0.bzr123 -> 1.0.dev123 + # 0.1a0dev.123 -> 0.1a0.dev123 + # PyPI stats: ~150 (~4%) better + rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) + + # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: + # 0.2.pre1 -> 0.2c1 + # 0.2-c1 -> 0.2c1 + # 1.0preview123 -> 1.0c123 + # PyPI stats: ~21 (0.62%) better + rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) + + # Tcl/Tk uses "px" for their post release markers + rs = re.sub(r"p(\d+)$", r".post\1", rs) + + try: + _normalized_key(rs) + except UnsupportedVersionError: + rs = None + return rs + +# +# Legacy version processing (distribute-compatible) +# + +_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) +_VERSION_REPLACE = { + 'pre': 'c', + 'preview': 'c', + '-': 'final-', + 'rc': 'c', + 'dev': '@', + '': None, + '.': None, +} + + +def _legacy_key(s): + def get_parts(s): + result = [] + for p in _VERSION_PART.split(s.lower()): + p = _VERSION_REPLACE.get(p, p) + if p: + if '0' <= p[:1] <= '9': + p = p.zfill(8) + else: + p = '*' + p + result.append(p) + result.append('*final') + return result + + result = [] + for p in get_parts(s): + if p.startswith('*'): + if p < '*final': + while result and result[-1] == '*final-': + result.pop() + while result and result[-1] == '00000000': + result.pop() + result.append(p) + return tuple(result) + + +class LegacyVersion(Version): + def parse(self, s): + return _legacy_key(s) + + @property + def is_prerelease(self): + result = False + for x in self._parts: + if (isinstance(x, string_types) and x.startswith('*') and + x < '*final'): + result = True + break + return result + + +class LegacyMatcher(Matcher): + version_class = LegacyVersion + + _operators = dict(Matcher._operators) + _operators['~='] = '_match_compatible' + + numeric_re = re.compile(r'^(\d+(\.\d+)*)') + + def _match_compatible(self, version, constraint, prefix): + if version < constraint: + return False + m = self.numeric_re.match(str(constraint)) + if not m: + logger.warning('Cannot compute compatible match for version %s ' + ' and constraint %s', version, constraint) + return True + s = m.groups()[0] + if '.' in s: + s = s.rsplit('.', 1)[0] + return _match_prefix(version, s) + +# +# Semantic versioning +# + +_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' + r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' + r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) + + +def is_semver(s): + return _SEMVER_RE.match(s) + + +def _semantic_key(s): + def make_tuple(s, absent): + if s is None: + result = (absent,) + else: + parts = s[1:].split('.') + # We can't compare ints and strings on Python 3, so fudge it + # by zero-filling numeric values so simulate a numeric comparison + result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) + return result + + m = is_semver(s) + if not m: + raise UnsupportedVersionError(s) + groups = m.groups() + major, minor, patch = [int(i) for i in groups[:3]] + # choose the '|' and '*' so that versions sort correctly + pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') + return (major, minor, patch), pre, build + + +class SemanticVersion(Version): + def parse(self, s): + return _semantic_key(s) + + @property + def is_prerelease(self): + return self._parts[1][0] != '|' + + +class SemanticMatcher(Matcher): + version_class = SemanticVersion + + +class VersionScheme(object): + def __init__(self, key, matcher, suggester=None): + self.key = key + self.matcher = matcher + self.suggester = suggester + + def is_valid_version(self, s): + try: + self.matcher.version_class(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_matcher(self, s): + try: + self.matcher(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_constraint_list(self, s): + """ + Used for processing some metadata fields + """ + return self.is_valid_matcher('dummy_name (%s)' % s) + + def suggest(self, s): + if self.suggester is None: + result = None + else: + result = self.suggester(s) + return result + +_SCHEMES = { + 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, + _suggest_normalized_version), + 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), + 'semantic': VersionScheme(_semantic_key, SemanticMatcher, + _suggest_semantic_version), +} + +_SCHEMES['default'] = _SCHEMES['normalized'] + + +def get_scheme(name): + if name not in _SCHEMES: + raise ValueError('unknown scheme name: %r' % name) + return _SCHEMES[name] diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/w32.exe b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/w32.exe new file mode 100644 index 0000000000000000000000000000000000000000..732215a9d34ccb7b417d637a7646d9b843ecafa8 GIT binary patch literal 89088 zcmeFae|S?>wm*FGqitH!CO`{C3REl(SahnPNDYM`O{q#T7)Xdvz$<hz5gjb&0FD$| zPs=nt#$jgk-tk`NUb*PJIy$3wMg@OiORy=5PEkZ0P^;6cyPm2=Y8#~Xyq~pC(iU~@ z_dd`2ywCg3TS)e=wSTX@_S$Q$y;FJf9>F9Cf*Bu86NCeB>CeT#|L3nblC!40kR?2m z{>H@z3`^g*ct!B1Tk<#8{Ol(+x7?n8>n(TO@iQ_1pEl;#NO$D_^p5<p8@>6r|7^p? zD>5@P3KB)%InlPUc<U{5lb_$uJ2!U@!dIxT&CTYnHuoCtzCL#`-1%8w%`JjkymkHD zpYr&>Cg9H}+(GW%^wV2|ROUbGfyXTfOART)i?<!WISJD#7!6|#8G`TvV*Xu^z32+K zc6>T0?9%;4K}Zn{6fx`yPa}*$9C+R!7zI~72c&$InY+UdMGBkF3c`HyxD3K09`bzW z?_q;rO&5ec#{?noJ4vI19bbHBt~vx^h2FH$V8i|^#EsiUg#JboP3@w-(&Uf&%NK<8 zSJZ5{MZ852W)~s>WeT(LIf&1wKNqULLI)GN_(-E-D)X~ZK=1;t<%*guHMhdg`-(mb zHzDv1KBN9zR9?--O+N$ReOXAr81V9z!X5SJ5`=3<1^<8V|AP@&sr2}Qvp;hQT24iW zOHg|EiZd1ojV;oo#(r^ba2`^8T22{~_UQ@YMZp7O1R*2@?SerFE~TuJB_wDaYC0h8 zfONF1t%{=H`W`bdYp+>YBsg9Ty9ec3iy+O3xa}TIvPK#Q&udyx1MvwG0(#iaGC|N| zJ#3?<Y4YLRkU`54s9BYRjyISA>){9$tW;Y34lPnX=&>D4X~|k7c$TwEfOzs@Yh#Nz z`FV;`(w!E`sKg@`2E}bDY>ku^4XS@tV(WO*<eu67;0Clk;vRHp!Qf<+5w0B!*Y>g? zYH=KK#%%Yu1~&m>IlB^#2^syGG|2AB1(}4aOcaC%!)}%`I7AIC2(Ro3yW`GSttng^ z_xb=ECor!L{-PNO>_ulJ3%fm=O0X!s%)$GZ?~I94l-^KEAX0n$?4wGpr7&i4#~)OB zQD%2NrWUKtZuYT1Vnu}AeF`cSgx>Rkk@}Lg{WltgT76VeA2aic`cTnpXrt2WXmJkM z9%u<Rp-*9{$HQ)>Xm?McyDyZ28Ux7mpxy?mnmvzMMr-85vkRrJLaDRx>|I7je+cM+ zj{RJ(3Vrgke;W@#D!y%U%fQLtlPKTAzWtVuOQdXpwsy6eRjt^cZ%0D4bF7$F;f!th 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ð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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/w64.exe b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/w64.exe new file mode 100644 index 0000000000000000000000000000000000000000..c41bd0a011fd760ce20ba795d9e535e0d2c39876 GIT binary patch literal 99328 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 B=L-M; literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distlib/wheel.py b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/wheel.py new file mode 100644 index 0000000..7737223 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distlib/wheel.py @@ -0,0 +1,984 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import base64 +import codecs +import datetime +import distutils.util +from email import message_from_file +import hashlib +import imp +import json +import logging +import os +import posixpath +import re +import shutil +import sys +import tempfile +import zipfile + +from . import __version__, DistlibException +from .compat import sysconfig, ZipFile, fsdecode, text_type, filter +from .database import InstalledDistribution +from .metadata import Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME +from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, + cached_property, get_cache_base, read_exports, tempdir) +from .version import NormalizedVersion, UnsupportedVersionError + +logger = logging.getLogger(__name__) + +cache = None # created when needed + +if hasattr(sys, 'pypy_version_info'): # pragma: no cover + IMP_PREFIX = 'pp' +elif sys.platform.startswith('java'): # pragma: no cover + IMP_PREFIX = 'jy' +elif sys.platform == 'cli': # pragma: no cover + IMP_PREFIX = 'ip' +else: + IMP_PREFIX = 'cp' + +VER_SUFFIX = sysconfig.get_config_var('py_version_nodot') +if not VER_SUFFIX: # pragma: no cover + VER_SUFFIX = '%s%s' % sys.version_info[:2] +PYVER = 'py' + VER_SUFFIX +IMPVER = IMP_PREFIX + VER_SUFFIX + +ARCH = distutils.util.get_platform().replace('-', '_').replace('.', '_') + +ABI = sysconfig.get_config_var('SOABI') +if ABI and ABI.startswith('cpython-'): + ABI = ABI.replace('cpython-', 'cp') +else: + def _derive_abi(): + parts = ['cp', VER_SUFFIX] + if sysconfig.get_config_var('Py_DEBUG'): + parts.append('d') + if sysconfig.get_config_var('WITH_PYMALLOC'): + parts.append('m') + if sysconfig.get_config_var('Py_UNICODE_SIZE') == 4: + parts.append('u') + return ''.join(parts) + ABI = _derive_abi() + del _derive_abi + +FILENAME_RE = re.compile(r''' +(?P<nm>[^-]+) +-(?P<vn>\d+[^-]*) +(-(?P<bn>\d+[^-]*))? +-(?P<py>\w+\d+(\.\w+\d+)*) +-(?P<bi>\w+) +-(?P<ar>\w+(\.\w+)*) +\.whl$ +''', re.IGNORECASE | re.VERBOSE) + +NAME_VERSION_RE = re.compile(r''' +(?P<nm>[^-]+) +-(?P<vn>\d+[^-]*) +(-(?P<bn>\d+[^-]*))?$ +''', re.IGNORECASE | re.VERBOSE) + +SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') +SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$') +SHEBANG_PYTHON = b'#!python' +SHEBANG_PYTHONW = b'#!pythonw' + +if os.sep == '/': + to_posix = lambda o: o +else: + to_posix = lambda o: o.replace(os.sep, '/') + + +class Mounter(object): + def __init__(self): + self.impure_wheels = {} + self.libs = {} + + def add(self, pathname, extensions): + self.impure_wheels[pathname] = extensions + self.libs.update(extensions) + + def remove(self, pathname): + extensions = self.impure_wheels.pop(pathname) + for k, v in extensions: + if k in self.libs: + del self.libs[k] + + def find_module(self, fullname, path=None): + if fullname in self.libs: + result = self + else: + result = None + return result + + def load_module(self, fullname): + if fullname in sys.modules: + result = sys.modules[fullname] + else: + if fullname not in self.libs: + raise ImportError('unable to find extension for %s' % fullname) + result = imp.load_dynamic(fullname, self.libs[fullname]) + result.__loader__ = self + parts = fullname.rsplit('.', 1) + if len(parts) > 1: + result.__package__ = parts[0] + return result + +_hook = Mounter() + + +class Wheel(object): + """ + Class to build and install from Wheel files (PEP 427). + """ + + wheel_version = (1, 1) + hash_kind = 'sha256' + + def __init__(self, filename=None, sign=False, verify=False): + """ + Initialise an instance using a (valid) filename. + """ + self.sign = sign + self.should_verify = verify + self.buildver = '' + self.pyver = [PYVER] + self.abi = ['none'] + self.arch = ['any'] + self.dirname = os.getcwd() + if filename is None: + self.name = 'dummy' + self.version = '0.1' + self._filename = self.filename + else: + m = NAME_VERSION_RE.match(filename) + if m: + info = m.groupdict('') + self.name = info['nm'] + # Reinstate the local version separator + self.version = info['vn'].replace('_', '-') + self.buildver = info['bn'] + self._filename = self.filename + else: + dirname, filename = os.path.split(filename) + m = FILENAME_RE.match(filename) + if not m: + raise DistlibException('Invalid name or ' + 'filename: %r' % filename) + if dirname: + self.dirname = os.path.abspath(dirname) + self._filename = filename + info = m.groupdict('') + self.name = info['nm'] + self.version = info['vn'] + self.buildver = info['bn'] + self.pyver = info['py'].split('.') + self.abi = info['bi'].split('.') + self.arch = info['ar'].split('.') + + @property + def filename(self): + """ + Build and return a filename from the various components. + """ + if self.buildver: + buildver = '-' + self.buildver + else: + buildver = '' + pyver = '.'.join(self.pyver) + abi = '.'.join(self.abi) + arch = '.'.join(self.arch) + # replace - with _ as a local version separator + version = self.version.replace('-', '_') + return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, + pyver, abi, arch) + + @property + def exists(self): + path = os.path.join(self.dirname, self.filename) + return os.path.isfile(path) + + @property + def tags(self): + for pyver in self.pyver: + for abi in self.abi: + for arch in self.arch: + yield pyver, abi, arch + + @cached_property + def metadata(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + wrapper = codecs.getreader('utf-8') + with ZipFile(pathname, 'r') as zf: + wheel_metadata = self.get_wheel_metadata(zf) + wv = wheel_metadata['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if file_version < (1, 1): + fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME, 'METADATA'] + else: + fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME] + result = None + for fn in fns: + try: + metadata_filename = posixpath.join(info_dir, fn) + with zf.open(metadata_filename) as bf: + wf = wrapper(bf) + result = Metadata(fileobj=wf) + if result: + break + except KeyError: + pass + if not result: + raise ValueError('Invalid wheel, because metadata is ' + 'missing: looked in %s' % ', '.join(fns)) + return result + + def get_wheel_metadata(self, zf): + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + metadata_filename = posixpath.join(info_dir, 'WHEEL') + with zf.open(metadata_filename) as bf: + wf = codecs.getreader('utf-8')(bf) + message = message_from_file(wf) + return dict(message) + + @cached_property + def info(self): + pathname = os.path.join(self.dirname, self.filename) + with ZipFile(pathname, 'r') as zf: + result = self.get_wheel_metadata(zf) + return result + + def process_shebang(self, data): + m = SHEBANG_RE.match(data) + if m: + end = m.end() + shebang, data_after_shebang = data[:end], data[end:] + # Preserve any arguments after the interpreter + if b'pythonw' in shebang.lower(): + shebang_python = SHEBANG_PYTHONW + else: + shebang_python = SHEBANG_PYTHON + m = SHEBANG_DETAIL_RE.match(shebang) + if m: + args = b' ' + m.groups()[-1] + else: + args = b'' + shebang = shebang_python + args + data = shebang + data_after_shebang + else: + cr = data.find(b'\r') + lf = data.find(b'\n') + if cr < 0 or cr > lf: + term = b'\n' + else: + if data[cr:cr + 2] == b'\r\n': + term = b'\r\n' + else: + term = b'\r' + data = SHEBANG_PYTHON + term + data + return data + + def get_hash(self, data, hash_kind=None): + if hash_kind is None: + hash_kind = self.hash_kind + try: + hasher = getattr(hashlib, hash_kind) + except AttributeError: + raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) + result = hasher(data).digest() + result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') + return hash_kind, result + + def write_record(self, records, record_path, base): + records = list(records) # make a copy for sorting + p = to_posix(os.path.relpath(record_path, base)) + records.append((p, '', '')) + records.sort() + with CSVWriter(record_path) as writer: + for row in records: + writer.writerow(row) + + def write_records(self, info, libdir, archive_paths): + records = [] + distinfo, info_dir = info + hasher = getattr(hashlib, self.hash_kind) + for ap, p in archive_paths: + with open(p, 'rb') as f: + data = f.read() + digest = '%s=%s' % self.get_hash(data) + size = os.path.getsize(p) + records.append((ap, digest, size)) + + p = os.path.join(distinfo, 'RECORD') + self.write_record(records, p, libdir) + ap = to_posix(os.path.join(info_dir, 'RECORD')) + archive_paths.append((ap, p)) + + def build_zip(self, pathname, archive_paths): + with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: + for ap, p in archive_paths: + logger.debug('Wrote %s to %s in wheel', p, ap) + zf.write(p, ap) + + def build(self, paths, tags=None, wheel_version=None): + """ + Build a wheel from files in specified paths, and use any specified tags + when determining the name of the wheel. + """ + if tags is None: + tags = {} + + libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] + if libkey == 'platlib': + is_pure = 'false' + default_pyver = [IMPVER] + default_abi = [ABI] + default_arch = [ARCH] + else: + is_pure = 'true' + default_pyver = [PYVER] + default_abi = ['none'] + default_arch = ['any'] + + self.pyver = tags.get('pyver', default_pyver) + self.abi = tags.get('abi', default_abi) + self.arch = tags.get('arch', default_arch) + + libdir = paths[libkey] + + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + archive_paths = [] + + # First, stuff which is not in site-packages + for key in ('data', 'headers', 'scripts'): + if key not in paths: + continue + path = paths[key] + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + for fn in files: + p = fsdecode(os.path.join(root, fn)) + rp = os.path.relpath(p, path) + ap = to_posix(os.path.join(data_dir, key, rp)) + archive_paths.append((ap, p)) + if key == 'scripts' and not p.endswith('.exe'): + with open(p, 'rb') as f: + data = f.read() + data = self.process_shebang(data) + with open(p, 'wb') as f: + f.write(data) + + # Now, stuff which is in site-packages, other than the + # distinfo stuff. + path = libdir + distinfo = None + for root, dirs, files in os.walk(path): + if root == path: + # At the top level only, save distinfo for later + # and skip it for now + for i, dn in enumerate(dirs): + dn = fsdecode(dn) + if dn.endswith('.dist-info'): + distinfo = os.path.join(root, dn) + del dirs[i] + break + assert distinfo, '.dist-info directory expected, not found' + + for fn in files: + # comment out next suite to leave .pyc files in + if fsdecode(fn).endswith(('.pyc', '.pyo')): + continue + p = os.path.join(root, fn) + rp = to_posix(os.path.relpath(p, path)) + archive_paths.append((rp, p)) + + # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. + files = os.listdir(distinfo) + for fn in files: + if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'): + p = fsdecode(os.path.join(distinfo, fn)) + ap = to_posix(os.path.join(info_dir, fn)) + archive_paths.append((ap, p)) + + wheel_metadata = [ + 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), + 'Generator: distlib %s' % __version__, + 'Root-Is-Purelib: %s' % is_pure, + ] + for pyver, abi, arch in self.tags: + wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) + p = os.path.join(distinfo, 'WHEEL') + with open(p, 'w') as f: + f.write('\n'.join(wheel_metadata)) + ap = to_posix(os.path.join(info_dir, 'WHEEL')) + archive_paths.append((ap, p)) + + # Now, at last, RECORD. + # Paths in here are archive paths - nothing else makes sense. + self.write_records((distinfo, info_dir), libdir, archive_paths) + # Now, ready to build the zip file + pathname = os.path.join(self.dirname, self.filename) + self.build_zip(pathname, archive_paths) + return pathname + + def install(self, paths, maker, **kwargs): + """ + Install a wheel to the specified paths. If kwarg ``warner`` is + specified, it should be a callable, which will be called with two + tuples indicating the wheel version of this software and the wheel + version in the file, if there is a discrepancy in the versions. + This can be used to issue any warnings to raise any exceptions. + If kwarg ``lib_only`` is True, only the purelib/platlib files are + installed, and the headers, scripts, data and dist-info metadata are + not written. + + The return value is a :class:`InstalledDistribution` instance unless + ``options.lib_only`` is True, in which case the return value is ``None``. + """ + + dry_run = maker.dry_run + warner = kwargs.get('warner') + lib_only = kwargs.get('lib_only', False) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if (file_version != self.wheel_version) and warner: + warner(self.wheel_version, file_version) + + if message['Root-Is-Purelib'] == 'true': + libdir = paths['purelib'] + else: + libdir = paths['platlib'] + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + data_pfx = posixpath.join(data_dir, '') + info_pfx = posixpath.join(info_dir, '') + script_pfx = posixpath.join(data_dir, 'scripts', '') + + # make a new instance rather than a copy of maker's, + # as we mutate it + fileop = FileOperator(dry_run=dry_run) + fileop.record = True # so we can rollback if needed + + bc = not sys.dont_write_bytecode # Double negatives. Lovely! + + outfiles = [] # for RECORD writing + + # for script copying/shebang processing + workdir = tempfile.mkdtemp() + # set target dir later + # we default add_launchers to False, as the + # Python Launcher should be used instead + maker.source_dir = workdir + maker.target_dir = None + try: + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + if u_arcname.endswith('/RECORD.jws'): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + if lib_only and u_arcname.startswith((info_pfx, data_pfx)): + logger.debug('lib_only: skipping %s', u_arcname) + continue + is_script = (u_arcname.startswith(script_pfx) + and not u_arcname.endswith('.exe')) + + if u_arcname.startswith(data_pfx): + _, where, rp = u_arcname.split('/', 2) + outfile = os.path.join(paths[where], convert_path(rp)) + else: + # meant for site-packages. + if u_arcname in (wheel_metadata_name, record_name): + continue + outfile = os.path.join(libdir, convert_path(u_arcname)) + if not is_script: + with zf.open(arcname) as bf: + fileop.copy_stream(bf, outfile) + outfiles.append(outfile) + # Double check the digest of the written file + if not dry_run and row[1]: + with open(outfile, 'rb') as bf: + data = bf.read() + _, newdigest = self.get_hash(data, kind) + if newdigest != digest: + raise DistlibException('digest mismatch ' + 'on write for ' + '%s' % outfile) + if bc and outfile.endswith('.py'): + try: + pyc = fileop.byte_compile(outfile) + outfiles.append(pyc) + except Exception: + # Don't give up if byte-compilation fails, + # but log it and perhaps warn the user + logger.warning('Byte-compilation failed', + exc_info=True) + else: + fn = os.path.basename(convert_path(arcname)) + workname = os.path.join(workdir, fn) + with zf.open(arcname) as bf: + fileop.copy_stream(bf, workname) + + dn, fn = os.path.split(outfile) + maker.target_dir = dn + filenames = maker.make(fn) + fileop.set_executable_mode(filenames) + outfiles.extend(filenames) + + if lib_only: + logger.debug('lib_only: returning None') + dist = None + else: + # Generate scripts + + # Try to get pydist.json so we can see if there are + # any commands to generate. If this fails (e.g. because + # of a legacy wheel), log a warning but don't give up. + commands = None + file_version = self.info['Wheel-Version'] + if file_version == '1.0': + # Use legacy info + ep = posixpath.join(info_dir, 'entry_points.txt') + try: + with zf.open(ep) as bwf: + epdata = read_exports(bwf) + commands = {} + for key in ('console', 'gui'): + k = '%s_scripts' % key + if k in epdata: + commands['wrap_%s' % key] = d = {} + for v in epdata[k].values(): + s = '%s:%s' % (v.prefix, v.suffix) + if v.flags: + s += ' %s' % v.flags + d[v.name] = s + except Exception: + logger.warning('Unable to read legacy script ' + 'metadata, so cannot generate ' + 'scripts') + else: + try: + with zf.open(metadata_name) as bwf: + wf = wrapper(bwf) + commands = json.load(wf).get('extensions') + if commands: + commands = commands.get('python.commands') + except Exception: + logger.warning('Unable to read JSON metadata, so ' + 'cannot generate scripts') + if commands: + console_scripts = commands.get('wrap_console', {}) + gui_scripts = commands.get('wrap_gui', {}) + if console_scripts or gui_scripts: + script_dir = paths.get('scripts', '') + if not os.path.isdir(script_dir): + raise ValueError('Valid script path not ' + 'specified') + maker.target_dir = script_dir + for k, v in console_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script) + fileop.set_executable_mode(filenames) + + if gui_scripts: + options = {'gui': True } + for k, v in gui_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script, options) + fileop.set_executable_mode(filenames) + + p = os.path.join(libdir, info_dir) + dist = InstalledDistribution(p) + + # Write SHARED + paths = dict(paths) # don't change passed in dict + del paths['purelib'] + del paths['platlib'] + paths['lib'] = libdir + p = dist.write_shared_locations(paths, dry_run) + if p: + outfiles.append(p) + + # Write RECORD + dist.write_installed_files(outfiles, paths['prefix'], + dry_run) + return dist + except Exception: # pragma: no cover + logger.exception('installation failed.') + fileop.rollback() + raise + finally: + shutil.rmtree(workdir) + + def _get_dylib_cache(self): + global cache + if cache is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('dylib-cache'), + sys.version[:3]) + cache = Cache(base) + return cache + + def _get_extensions(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + arcname = posixpath.join(info_dir, 'EXTENSIONS') + wrapper = codecs.getreader('utf-8') + result = [] + with ZipFile(pathname, 'r') as zf: + try: + with zf.open(arcname) as bf: + wf = wrapper(bf) + extensions = json.load(wf) + cache = self._get_dylib_cache() + prefix = cache.prefix_to_dir(pathname) + cache_base = os.path.join(cache.base, prefix) + if not os.path.isdir(cache_base): + os.makedirs(cache_base) + for name, relpath in extensions.items(): + dest = os.path.join(cache_base, convert_path(relpath)) + if not os.path.exists(dest): + extract = True + else: + file_time = os.stat(dest).st_mtime + file_time = datetime.datetime.fromtimestamp(file_time) + info = zf.getinfo(relpath) + wheel_time = datetime.datetime(*info.date_time) + extract = wheel_time > file_time + if extract: + zf.extract(relpath, cache_base) + result.append((name, dest)) + except KeyError: + pass + return result + + def is_compatible(self): + """ + Determine if a wheel is compatible with the running system. + """ + return is_compatible(self) + + def is_mountable(self): + """ + Determine if a wheel is asserted as mountable by its metadata. + """ + return True # for now - metadata details TBD + + def mount(self, append=False): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if not self.is_compatible(): + msg = 'Wheel %s not compatible with this Python.' % pathname + raise DistlibException(msg) + if not self.is_mountable(): + msg = 'Wheel %s is marked as not mountable.' % pathname + raise DistlibException(msg) + if pathname in sys.path: + logger.debug('%s already in path', pathname) + else: + if append: + sys.path.append(pathname) + else: + sys.path.insert(0, pathname) + extensions = self._get_extensions() + if extensions: + if _hook not in sys.meta_path: + sys.meta_path.append(_hook) + _hook.add(pathname, extensions) + + def unmount(self): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if pathname not in sys.path: + logger.debug('%s not in path', pathname) + else: + sys.path.remove(pathname) + if pathname in _hook.impure_wheels: + _hook.remove(pathname) + if not _hook.impure_wheels: + if _hook in sys.meta_path: + sys.meta_path.remove(_hook) + + def verify(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + # TODO version verification + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + if u_arcname.endswith('/RECORD.jws'): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + def update(self, modifier, dest_dir=None, **kwargs): + """ + Update the contents of a wheel in a generic way. The modifier should + be a callable which expects a dictionary argument: its keys are + archive-entry paths, and its values are absolute filesystem paths + where the contents the corresponding archive entries can be found. The + modifier is free to change the contents of the files pointed to, add + new entries and remove entries, before returning. This method will + extract the entire contents of the wheel to a temporary location, call + the modifier, and then use the passed (and possibly updated) + dictionary to write a new wheel. If ``dest_dir`` is specified, the new + wheel is written there -- otherwise, the original wheel is overwritten. + + The modifier should return True if it updated the wheel, else False. + This method returns the same value the modifier returns. + """ + + def get_version(path_map, info_dir): + version = path = None + key = '%s/%s' % (info_dir, METADATA_FILENAME) + if key not in path_map: + key = '%s/PKG-INFO' % info_dir + if key in path_map: + path = path_map[key] + version = Metadata(path=path).version + return version, path + + def update_version(version, path): + updated = None + try: + v = NormalizedVersion(version) + i = version.find('-') + if i < 0: + updated = '%s+1' % version + else: + parts = [int(s) for s in version[i + 1:].split('.')] + parts[-1] += 1 + updated = '%s+%s' % (version[:i], + '.'.join(str(i) for i in parts)) + except UnsupportedVersionError: + logger.debug('Cannot update non-compliant (PEP-440) ' + 'version %r', version) + if updated: + md = Metadata(path=path) + md.version = updated + legacy = not path.endswith(METADATA_FILENAME) + md.write(path=path, legacy=legacy) + logger.debug('Version updated from %r to %r', version, + updated) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + record_name = posixpath.join(info_dir, 'RECORD') + with tempdir() as workdir: + with ZipFile(pathname, 'r') as zf: + path_map = {} + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if u_arcname == record_name: + continue + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + zf.extract(zinfo, workdir) + path = os.path.join(workdir, convert_path(u_arcname)) + path_map[u_arcname] = path + + # Remember the version. + original_version, _ = get_version(path_map, info_dir) + # Files extracted. Call the modifier. + modified = modifier(path_map, **kwargs) + if modified: + # Something changed - need to build a new wheel. + current_version, path = get_version(path_map, info_dir) + if current_version and (current_version == original_version): + # Add or update local version to signify changes. + update_version(current_version, path) + # Decide where the new wheel goes. + if dest_dir is None: + fd, newpath = tempfile.mkstemp(suffix='.whl', + prefix='wheel-update-', + dir=workdir) + os.close(fd) + else: + if not os.path.isdir(dest_dir): + raise DistlibException('Not a directory: %r' % dest_dir) + newpath = os.path.join(dest_dir, self.filename) + archive_paths = list(path_map.items()) + distinfo = os.path.join(workdir, info_dir) + info = distinfo, info_dir + self.write_records(info, workdir, archive_paths) + self.build_zip(newpath, archive_paths) + if dest_dir is None: + shutil.copyfile(newpath, pathname) + return modified + +def compatible_tags(): + """ + Return (pyver, abi, arch) tuples compatible with this Python. + """ + versions = [VER_SUFFIX] + major = VER_SUFFIX[0] + for minor in range(sys.version_info[1] - 1, - 1, -1): + versions.append(''.join([major, str(minor)])) + + abis = [] + for suffix, _, _ in imp.get_suffixes(): + if suffix.startswith('.abi'): + abis.append(suffix.split('.', 2)[1]) + abis.sort() + if ABI != 'none': + abis.insert(0, ABI) + abis.append('none') + result = [] + + arches = [ARCH] + if sys.platform == 'darwin': + m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH) + if m: + name, major, minor, arch = m.groups() + minor = int(minor) + matches = [arch] + if arch in ('i386', 'ppc'): + matches.append('fat') + if arch in ('i386', 'ppc', 'x86_64'): + matches.append('fat3') + if arch in ('ppc64', 'x86_64'): + matches.append('fat64') + if arch in ('i386', 'x86_64'): + matches.append('intel') + if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'): + matches.append('universal') + while minor >= 0: + for match in matches: + s = '%s_%s_%s_%s' % (name, major, minor, match) + if s != ARCH: # already there + arches.append(s) + minor -= 1 + + # Most specific - our Python version, ABI and arch + for abi in abis: + for arch in arches: + result.append((''.join((IMP_PREFIX, versions[0])), abi, arch)) + + # where no ABI / arch dependency, but IMP_PREFIX dependency + for i, version in enumerate(versions): + result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) + if i == 0: + result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) + + # no IMP_PREFIX, ABI or arch dependency + for i, version in enumerate(versions): + result.append((''.join(('py', version)), 'none', 'any')) + if i == 0: + result.append((''.join(('py', version[0])), 'none', 'any')) + return set(result) + + +COMPATIBLE_TAGS = compatible_tags() + +del compatible_tags + + +def is_compatible(wheel, tags=None): + if not isinstance(wheel, Wheel): + wheel = Wheel(wheel) # assume it's a filename + result = False + if tags is None: + tags = COMPATIBLE_TAGS + for ver, abi, arch in tags: + if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: + result = True + break + return result diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/distro.py b/venv/lib/python3.7/site-packages/pip/_vendor/distro.py new file mode 100644 index 0000000..aa4defc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/distro.py @@ -0,0 +1,1197 @@ +# Copyright 2015,2016,2017 Nir Cohen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +The ``distro`` package (``distro`` stands for Linux Distribution) provides +information about the Linux distribution it runs on, such as a reliable +machine-readable distro ID, or version information. + +It is a renewed alternative implementation for Python's original +:py:func:`platform.linux_distribution` function, but it provides much more +functionality. An alternative implementation became necessary because Python +3.5 deprecated this function, and Python 3.7 is expected to remove it +altogether. Its predecessor function :py:func:`platform.dist` was already +deprecated since Python 2.6 and is also expected to be removed in Python 3.7. +Still, there are many cases in which access to OS distribution information +is needed. See `Python issue 1322 <https://bugs.python.org/issue1322>`_ for +more information. +""" + +import os +import re +import sys +import json +import shlex +import logging +import argparse +import subprocess + + +_UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc') +_OS_RELEASE_BASENAME = 'os-release' + +#: Translation table for normalizing the "ID" attribute defined in os-release +#: files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as defined in the os-release file, translated to lower case, +#: with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_OS_ID = {} + +#: Translation table for normalizing the "Distributor ID" attribute returned by +#: the lsb_release command, for use by the :func:`distro.id` method. +#: +#: * Key: Value as returned by the lsb_release command, translated to lower +#: case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_LSB_ID = { + 'enterpriseenterprise': 'oracle', # Oracle Enterprise Linux + 'redhatenterpriseworkstation': 'rhel', # RHEL 6, 7 Workstation + 'redhatenterpriseserver': 'rhel', # RHEL 6, 7 Server +} + +#: Translation table for normalizing the distro ID derived from the file name +#: of distro release files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as derived from the file name of a distro release file, +#: translated to lower case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_DISTRO_ID = { + 'redhat': 'rhel', # RHEL 6.x, 7.x +} + +# Pattern for content of distro release file (reversed) +_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( + r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)') + +# Pattern for base file name of distro release file +_DISTRO_RELEASE_BASENAME_PATTERN = re.compile( + r'(\w+)[-_](release|version)$') + +# Base file names to be ignored when searching for distro release file +_DISTRO_RELEASE_IGNORE_BASENAMES = ( + 'debian_version', + 'lsb-release', + 'oem-release', + _OS_RELEASE_BASENAME, + 'system-release' +) + + +def linux_distribution(full_distribution_name=True): + """ + Return information about the current OS distribution as a tuple + ``(id_name, version, codename)`` with items as follows: + + * ``id_name``: If *full_distribution_name* is false, the result of + :func:`distro.id`. Otherwise, the result of :func:`distro.name`. + + * ``version``: The result of :func:`distro.version`. + + * ``codename``: The result of :func:`distro.codename`. + + The interface of this function is compatible with the original + :py:func:`platform.linux_distribution` function, supporting a subset of + its parameters. + + The data it returns may not exactly be the same, because it uses more data + sources than the original function, and that may lead to different data if + the OS distribution is not consistent across multiple data sources it + provides (there are indeed such distributions ...). + + Another reason for differences is the fact that the :func:`distro.id` + method normalizes the distro ID string to a reliable machine-readable value + for a number of popular OS distributions. + """ + return _distro.linux_distribution(full_distribution_name) + + +def id(): + """ + Return the distro ID of the current distribution, as a + machine-readable string. + + For a number of OS distributions, the returned distro ID value is + *reliable*, in the sense that it is documented and that it does not change + across releases of the distribution. + + This package maintains the following reliable distro ID values: + + ============== ========================================= + Distro ID Distribution + ============== ========================================= + "ubuntu" Ubuntu + "debian" Debian + "rhel" RedHat Enterprise Linux + "centos" CentOS + "fedora" Fedora + "sles" SUSE Linux Enterprise Server + "opensuse" openSUSE + "amazon" Amazon Linux + "arch" Arch Linux + "cloudlinux" CloudLinux OS + "exherbo" Exherbo Linux + "gentoo" GenToo Linux + "ibm_powerkvm" IBM PowerKVM + "kvmibm" KVM for IBM z Systems + "linuxmint" Linux Mint + "mageia" Mageia + "mandriva" Mandriva Linux + "parallels" Parallels + "pidora" Pidora + "raspbian" Raspbian + "oracle" Oracle Linux (and Oracle Enterprise Linux) + "scientific" Scientific Linux + "slackware" Slackware + "xenserver" XenServer + "openbsd" OpenBSD + "netbsd" NetBSD + "freebsd" FreeBSD + ============== ========================================= + + If you have a need to get distros for reliable IDs added into this set, + or if you find that the :func:`distro.id` function returns a different + distro ID for one of the listed distros, please create an issue in the + `distro issue tracker`_. + + **Lookup hierarchy and transformations:** + + First, the ID is obtained from the following sources, in the specified + order. The first available and non-empty value is used: + + * the value of the "ID" attribute of the os-release file, + + * the value of the "Distributor ID" attribute returned by the lsb_release + command, + + * the first part of the file name of the distro release file, + + The so determined ID value then passes the following transformations, + before it is returned by this method: + + * it is translated to lower case, + + * blanks (which should not be there anyway) are translated to underscores, + + * a normalization of the ID is performed, based upon + `normalization tables`_. The purpose of this normalization is to ensure + that the ID is as reliable as possible, even across incompatible changes + in the OS distributions. A common reason for an incompatible change is + the addition of an os-release file, or the addition of the lsb_release + command, with ID values that differ from what was previously determined + from the distro release file name. + """ + return _distro.id() + + +def name(pretty=False): + """ + Return the name of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the name is returned without version or codename. + (e.g. "CentOS Linux") + + If *pretty* is true, the version and codename are appended. + (e.g. "CentOS Linux 7.1.1503 (Core)") + + **Lookup hierarchy:** + + The name is obtained from the following sources, in the specified order. + The first available and non-empty value is used: + + * If *pretty* is false: + + - the value of the "NAME" attribute of the os-release file, + + - the value of the "Distributor ID" attribute returned by the lsb_release + command, + + - the value of the "<name>" field of the distro release file. + + * If *pretty* is true: + + - the value of the "PRETTY_NAME" attribute of the os-release file, + + - the value of the "Description" attribute returned by the lsb_release + command, + + - the value of the "<name>" field of the distro release file, appended + with the value of the pretty version ("<version_id>" and "<codename>" + fields) of the distro release file, if available. + """ + return _distro.name(pretty) + + +def version(pretty=False, best=False): + """ + Return the version of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the version is returned without codename (e.g. + "7.0"). + + If *pretty* is true, the codename in parenthesis is appended, if the + codename is non-empty (e.g. "7.0 (Maipo)"). + + Some distributions provide version numbers with different precisions in + the different sources of distribution information. Examining the different + sources in a fixed priority order does not always yield the most precise + version (e.g. for Debian 8.2, or CentOS 7.1). + + The *best* parameter can be used to control the approach for the returned + version: + + If *best* is false, the first non-empty version number in priority order of + the examined sources is returned. + + If *best* is true, the most precise version number out of all examined + sources is returned. + + **Lookup hierarchy:** + + In all cases, the version number is obtained from the following sources. + If *best* is false, this order represents the priority order: + + * the value of the "VERSION_ID" attribute of the os-release file, + * the value of the "Release" attribute returned by the lsb_release + command, + * the version number parsed from the "<version_id>" field of the first line + of the distro release file, + * the version number parsed from the "PRETTY_NAME" attribute of the + os-release file, if it follows the format of the distro release files. + * the version number parsed from the "Description" attribute returned by + the lsb_release command, if it follows the format of the distro release + files. + """ + return _distro.version(pretty, best) + + +def version_parts(best=False): + """ + Return the version of the current OS distribution as a tuple + ``(major, minor, build_number)`` with items as follows: + + * ``major``: The result of :func:`distro.major_version`. + + * ``minor``: The result of :func:`distro.minor_version`. + + * ``build_number``: The result of :func:`distro.build_number`. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.version_parts(best) + + +def major_version(best=False): + """ + Return the major version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The major version is the first + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.major_version(best) + + +def minor_version(best=False): + """ + Return the minor version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The minor version is the second + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.minor_version(best) + + +def build_number(best=False): + """ + Return the build number of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The build number is the third part + of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.build_number(best) + + +def like(): + """ + Return a space-separated list of distro IDs of distributions that are + closely related to the current OS distribution in regards to packaging + and programming interfaces, for example distributions the current + distribution is a derivative from. + + **Lookup hierarchy:** + + This information item is only provided by the os-release file. + For details, see the description of the "ID_LIKE" attribute in the + `os-release man page + <http://www.freedesktop.org/software/systemd/man/os-release.html>`_. + """ + return _distro.like() + + +def codename(): + """ + Return the codename for the release of the current OS distribution, + as a string. + + If the distribution does not have a codename, an empty string is returned. + + Note that the returned codename is not always really a codename. For + example, openSUSE returns "x86_64". This function does not handle such + cases in any special way and just returns the string it finds, if any. + + **Lookup hierarchy:** + + * the codename within the "VERSION" attribute of the os-release file, if + provided, + + * the value of the "Codename" attribute returned by the lsb_release + command, + + * the value of the "<codename>" field of the distro release file. + """ + return _distro.codename() + + +def info(pretty=False, best=False): + """ + Return certain machine-readable information items about the current OS + distribution in a dictionary, as shown in the following example: + + .. sourcecode:: python + + { + 'id': 'rhel', + 'version': '7.0', + 'version_parts': { + 'major': '7', + 'minor': '0', + 'build_number': '' + }, + 'like': 'fedora', + 'codename': 'Maipo' + } + + The dictionary structure and keys are always the same, regardless of which + information items are available in the underlying data sources. The values + for the various keys are as follows: + + * ``id``: The result of :func:`distro.id`. + + * ``version``: The result of :func:`distro.version`. + + * ``version_parts -> major``: The result of :func:`distro.major_version`. + + * ``version_parts -> minor``: The result of :func:`distro.minor_version`. + + * ``version_parts -> build_number``: The result of + :func:`distro.build_number`. + + * ``like``: The result of :func:`distro.like`. + + * ``codename``: The result of :func:`distro.codename`. + + For a description of the *pretty* and *best* parameters, see the + :func:`distro.version` method. + """ + return _distro.info(pretty, best) + + +def os_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the os-release file data source of the current OS distribution. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_info() + + +def lsb_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the lsb_release command data source of the current OS distribution. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_info() + + +def distro_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_info() + + +def uname_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + """ + return _distro.uname_info() + + +def os_release_attr(attribute): + """ + Return a single named information item from the os-release file data source + of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_attr(attribute) + + +def lsb_release_attr(attribute): + """ + Return a single named information item from the lsb_release command output + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_attr(attribute) + + +def distro_release_attr(attribute): + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_attr(attribute) + + +def uname_attr(attribute): + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + """ + return _distro.uname_attr(attribute) + + +class cached_property(object): + """A version of @property which caches the value. On access, it calls the + underlying function and sets the value in `__dict__` so future accesses + will not re-call the property. + """ + def __init__(self, f): + self._fname = f.__name__ + self._f = f + + def __get__(self, obj, owner): + assert obj is not None, 'call {} on an instance'.format(self._fname) + ret = obj.__dict__[self._fname] = self._f(obj) + return ret + + +class LinuxDistribution(object): + """ + Provides information about a OS distribution. + + This package creates a private module-global instance of this class with + default initialization arguments, that is used by the + `consolidated accessor functions`_ and `single source accessor functions`_. + By using default initialization arguments, that module-global instance + returns data about the current OS distribution (i.e. the distro this + package runs on). + + Normally, it is not necessary to create additional instances of this class. + However, in situations where control is needed over the exact data sources + that are used, instances of this class can be created with a specific + distro release file, or a specific os-release file, or without invoking the + lsb_release command. + """ + + def __init__(self, + include_lsb=True, + os_release_file='', + distro_release_file='', + include_uname=True): + """ + The initialization method of this class gathers information from the + available data sources, and stores that in private instance attributes. + Subsequent access to the information items uses these private instance + attributes, so that the data sources are read only once. + + Parameters: + + * ``include_lsb`` (bool): Controls whether the + `lsb_release command output`_ is included as a data source. + + If the lsb_release command is not available in the program execution + path, the data source for the lsb_release command will be empty. + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is to be used as a data source. + + An empty string (the default) will cause the default path name to + be used (see `os-release file`_ for details). + + If the specified or defaulted os-release file does not exist, the + data source for the os-release file will be empty. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is to be used as a data source. + + An empty string (the default) will cause a default search algorithm + to be used (see `distro release file`_ for details). + + If the specified distro release file does not exist, or if no default + distro release file can be found, the data source for the distro + release file will be empty. + + * ``include_name`` (bool): Controls whether uname command output is + included as a data source. If the uname command is not available in + the program execution path the data source for the uname command will + be empty. + + Public instance attributes: + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. + This controls whether the lsb information will be loaded. + + * ``include_uname`` (bool): The result of the ``include_uname`` + parameter. This controls whether the uname information will + be loaded. + + Raises: + + * :py:exc:`IOError`: Some I/O issue with an os-release file or distro + release file. + + * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had + some issue (other than not being available in the program execution + path). + + * :py:exc:`UnicodeError`: A data source has unexpected characters or + uses an unexpected encoding. + """ + self.os_release_file = os_release_file or \ + os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME) + self.distro_release_file = distro_release_file or '' # updated later + self.include_lsb = include_lsb + self.include_uname = include_uname + + def __repr__(self): + """Return repr of all info + """ + return \ + "LinuxDistribution(" \ + "os_release_file={self.os_release_file!r}, " \ + "distro_release_file={self.distro_release_file!r}, " \ + "include_lsb={self.include_lsb!r}, " \ + "include_uname={self.include_uname!r}, " \ + "_os_release_info={self._os_release_info!r}, " \ + "_lsb_release_info={self._lsb_release_info!r}, " \ + "_distro_release_info={self._distro_release_info!r}, " \ + "_uname_info={self._uname_info!r})".format( + self=self) + + def linux_distribution(self, full_distribution_name=True): + """ + Return information about the OS distribution that is compatible + with Python's :func:`platform.linux_distribution`, supporting a subset + of its parameters. + + For details, see :func:`distro.linux_distribution`. + """ + return ( + self.name() if full_distribution_name else self.id(), + self.version(), + self.codename() + ) + + def id(self): + """Return the distro ID of the OS distribution, as a string. + + For details, see :func:`distro.id`. + """ + def normalize(distro_id, table): + distro_id = distro_id.lower().replace(' ', '_') + return table.get(distro_id, distro_id) + + distro_id = self.os_release_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_OS_ID) + + distro_id = self.lsb_release_attr('distributor_id') + if distro_id: + return normalize(distro_id, NORMALIZED_LSB_ID) + + distro_id = self.distro_release_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + distro_id = self.uname_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + return '' + + def name(self, pretty=False): + """ + Return the name of the OS distribution, as a string. + + For details, see :func:`distro.name`. + """ + name = self.os_release_attr('name') \ + or self.lsb_release_attr('distributor_id') \ + or self.distro_release_attr('name') \ + or self.uname_attr('name') + if pretty: + name = self.os_release_attr('pretty_name') \ + or self.lsb_release_attr('description') + if not name: + name = self.distro_release_attr('name') \ + or self.uname_attr('name') + version = self.version(pretty=True) + if version: + name = name + ' ' + version + return name or '' + + def version(self, pretty=False, best=False): + """ + Return the version of the OS distribution, as a string. + + For details, see :func:`distro.version`. + """ + versions = [ + self.os_release_attr('version_id'), + self.lsb_release_attr('release'), + self.distro_release_attr('version_id'), + self._parse_distro_release_content( + self.os_release_attr('pretty_name')).get('version_id', ''), + self._parse_distro_release_content( + self.lsb_release_attr('description')).get('version_id', ''), + self.uname_attr('release') + ] + version = '' + if best: + # This algorithm uses the last version in priority order that has + # the best precision. If the versions are not in conflict, that + # does not matter; otherwise, using the last one instead of the + # first one might be considered a surprise. + for v in versions: + if v.count(".") > version.count(".") or version == '': + version = v + else: + for v in versions: + if v != '': + version = v + break + if pretty and version and self.codename(): + version = u'{0} ({1})'.format(version, self.codename()) + return version + + def version_parts(self, best=False): + """ + Return the version of the OS distribution, as a tuple of version + numbers. + + For details, see :func:`distro.version_parts`. + """ + version_str = self.version(best=best) + if version_str: + version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?') + matches = version_regex.match(version_str) + if matches: + major, minor, build_number = matches.groups() + return major, minor or '', build_number or '' + return '', '', '' + + def major_version(self, best=False): + """ + Return the major version number of the current distribution. + + For details, see :func:`distro.major_version`. + """ + return self.version_parts(best)[0] + + def minor_version(self, best=False): + """ + Return the minor version number of the current distribution. + + For details, see :func:`distro.minor_version`. + """ + return self.version_parts(best)[1] + + def build_number(self, best=False): + """ + Return the build number of the current distribution. + + For details, see :func:`distro.build_number`. + """ + return self.version_parts(best)[2] + + def like(self): + """ + Return the IDs of distributions that are like the OS distribution. + + For details, see :func:`distro.like`. + """ + return self.os_release_attr('id_like') or '' + + def codename(self): + """ + Return the codename of the OS distribution. + + For details, see :func:`distro.codename`. + """ + return self.os_release_attr('codename') \ + or self.lsb_release_attr('codename') \ + or self.distro_release_attr('codename') \ + or '' + + def info(self, pretty=False, best=False): + """ + Return certain machine-readable information about the OS + distribution. + + For details, see :func:`distro.info`. + """ + return dict( + id=self.id(), + version=self.version(pretty, best), + version_parts=dict( + major=self.major_version(best), + minor=self.minor_version(best), + build_number=self.build_number(best) + ), + like=self.like(), + codename=self.codename(), + ) + + def os_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the os-release file data source of the OS distribution. + + For details, see :func:`distro.os_release_info`. + """ + return self._os_release_info + + def lsb_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the lsb_release command data source of the OS + distribution. + + For details, see :func:`distro.lsb_release_info`. + """ + return self._lsb_release_info + + def distro_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the distro release file data source of the OS + distribution. + + For details, see :func:`distro.distro_release_info`. + """ + return self._distro_release_info + + def uname_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the uname command data source of the OS distribution. + + For details, see :func:`distro.uname_info`. + """ + + def os_release_attr(self, attribute): + """ + Return a single named information item from the os-release file data + source of the OS distribution. + + For details, see :func:`distro.os_release_attr`. + """ + return self._os_release_info.get(attribute, '') + + def lsb_release_attr(self, attribute): + """ + Return a single named information item from the lsb_release command + output data source of the OS distribution. + + For details, see :func:`distro.lsb_release_attr`. + """ + return self._lsb_release_info.get(attribute, '') + + def distro_release_attr(self, attribute): + """ + Return a single named information item from the distro release file + data source of the OS distribution. + + For details, see :func:`distro.distro_release_attr`. + """ + return self._distro_release_info.get(attribute, '') + + def uname_attr(self, attribute): + """ + Return a single named information item from the uname command + output data source of the OS distribution. + + For details, see :func:`distro.uname_release_attr`. + """ + return self._uname_info.get(attribute, '') + + @cached_property + def _os_release_info(self): + """ + Get the information items from the specified os-release file. + + Returns: + A dictionary containing all information items. + """ + if os.path.isfile(self.os_release_file): + with open(self.os_release_file) as release_file: + return self._parse_os_release_content(release_file) + return {} + + @staticmethod + def _parse_os_release_content(lines): + """ + Parse the lines of an os-release file. + + Parameters: + + * lines: Iterable through the lines in the os-release file. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + lexer = shlex.shlex(lines, posix=True) + lexer.whitespace_split = True + + # The shlex module defines its `wordchars` variable using literals, + # making it dependent on the encoding of the Python source file. + # In Python 2.6 and 2.7, the shlex source file is encoded in + # 'iso-8859-1', and the `wordchars` variable is defined as a byte + # string. This causes a UnicodeDecodeError to be raised when the + # parsed content is a unicode object. The following fix resolves that + # (... but it should be fixed in shlex...): + if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes): + lexer.wordchars = lexer.wordchars.decode('iso-8859-1') + + tokens = list(lexer) + for token in tokens: + # At this point, all shell-like parsing has been done (i.e. + # comments processed, quotes and backslash escape sequences + # processed, multi-line values assembled, trailing newlines + # stripped, etc.), so the tokens are now either: + # * variable assignments: var=value + # * commands or their arguments (not allowed in os-release) + if '=' in token: + k, v = token.split('=', 1) + if isinstance(v, bytes): + v = v.decode('utf-8') + props[k.lower()] = v + if k == 'VERSION': + # this handles cases in which the codename is in + # the `(CODENAME)` (rhel, centos, fedora) format + # or in the `, CODENAME` format (Ubuntu). + codename = re.search(r'(\(\D+\))|,(\s+)?\D+', v) + if codename: + codename = codename.group() + codename = codename.strip('()') + codename = codename.strip(',') + codename = codename.strip() + # codename appears within paranthese. + props['codename'] = codename + else: + props['codename'] = '' + else: + # Ignore any tokens that are not variable assignments + pass + return props + + @cached_property + def _lsb_release_info(self): + """ + Get the information items from the lsb_release command output. + + Returns: + A dictionary containing all information items. + """ + if not self.include_lsb: + return {} + with open(os.devnull, 'w') as devnull: + try: + cmd = ('lsb_release', '-a') + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: # Command not found + return {} + content = stdout.decode(sys.getfilesystemencoding()).splitlines() + return self._parse_lsb_release_content(content) + + @staticmethod + def _parse_lsb_release_content(lines): + """ + Parse the output of the lsb_release command. + + Parameters: + + * lines: Iterable through the lines of the lsb_release output. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + for line in lines: + kv = line.strip('\n').split(':', 1) + if len(kv) != 2: + # Ignore lines without colon. + continue + k, v = kv + props.update({k.replace(' ', '_').lower(): v.strip()}) + return props + + @cached_property + def _uname_info(self): + with open(os.devnull, 'w') as devnull: + try: + cmd = ('uname', '-rs') + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: + return {} + content = stdout.decode(sys.getfilesystemencoding()).splitlines() + return self._parse_uname_content(content) + + @staticmethod + def _parse_uname_content(lines): + props = {} + match = re.search(r'^([^\s]+)\s+([\d\.]+)', lines[0].strip()) + if match: + name, version = match.groups() + + # This is to prevent the Linux kernel version from + # appearing as the 'best' version on otherwise + # identifiable distributions. + if name == 'Linux': + return {} + props['id'] = name.lower() + props['name'] = name + props['release'] = version + return props + + @cached_property + def _distro_release_info(self): + """ + Get the information items from the specified distro release file. + + Returns: + A dictionary containing all information items. + """ + if self.distro_release_file: + # If it was specified, we use it and parse what we can, even if + # its file name or content does not match the expected pattern. + distro_info = self._parse_distro_release_file( + self.distro_release_file) + basename = os.path.basename(self.distro_release_file) + # The file name pattern for user-specified distro release files + # is somewhat more tolerant (compared to when searching for the + # file), because we want to use what was specified as best as + # possible. + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match: + distro_info['id'] = match.group(1) + return distro_info + else: + try: + basenames = os.listdir(_UNIXCONFDIR) + # We sort for repeatability in cases where there are multiple + # distro specific files; e.g. CentOS, Oracle, Enterprise all + # containing `redhat-release` on top of their own. + basenames.sort() + except OSError: + # This may occur when /etc is not readable but we can't be + # sure about the *-release files. Check common entries of + # /etc for information. If they turn out to not be there the + # error is handled in `_parse_distro_release_file()`. + basenames = ['SuSE-release', + 'arch-release', + 'base-release', + 'centos-release', + 'fedora-release', + 'gentoo-release', + 'mageia-release', + 'mandrake-release', + 'mandriva-release', + 'mandrivalinux-release', + 'manjaro-release', + 'oracle-release', + 'redhat-release', + 'sl-release', + 'slackware-version'] + for basename in basenames: + if basename in _DISTRO_RELEASE_IGNORE_BASENAMES: + continue + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match: + filepath = os.path.join(_UNIXCONFDIR, basename) + distro_info = self._parse_distro_release_file(filepath) + if 'name' in distro_info: + # The name is always present if the pattern matches + self.distro_release_file = filepath + distro_info['id'] = match.group(1) + return distro_info + return {} + + def _parse_distro_release_file(self, filepath): + """ + Parse a distro release file. + + Parameters: + + * filepath: Path name of the distro release file. + + Returns: + A dictionary containing all information items. + """ + try: + with open(filepath) as fp: + # Only parse the first line. For instance, on SLES there + # are multiple lines. We don't want them... + return self._parse_distro_release_content(fp.readline()) + except (OSError, IOError): + # Ignore not being able to read a specific, seemingly version + # related file. + # See https://github.com/nir0s/distro/issues/162 + return {} + + @staticmethod + def _parse_distro_release_content(line): + """ + Parse a line from a distro release file. + + Parameters: + * line: Line from the distro release file. Must be a unicode string + or a UTF-8 encoded byte string. + + Returns: + A dictionary containing all information items. + """ + if isinstance(line, bytes): + line = line.decode('utf-8') + matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match( + line.strip()[::-1]) + distro_info = {} + if matches: + # regexp ensures non-None + distro_info['name'] = matches.group(3)[::-1] + if matches.group(2): + distro_info['version_id'] = matches.group(2)[::-1] + if matches.group(1): + distro_info['codename'] = matches.group(1)[::-1] + elif line: + distro_info['name'] = line.strip() + return distro_info + + +_distro = LinuxDistribution() + + +def main(): + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(logging.StreamHandler(sys.stdout)) + + parser = argparse.ArgumentParser(description="OS distro info tool") + parser.add_argument( + '--json', + '-j', + help="Output in machine readable format", + action="store_true") + args = parser.parse_args() + + if args.json: + logger.info(json.dumps(info(), indent=4, sort_keys=True)) + else: + logger.info('Name: %s', name(pretty=True)) + distribution_version = version(pretty=True) + logger.info('Version: %s', distribution_version) + distribution_codename = codename() + logger.info('Codename: %s', distribution_codename) + + +if __name__ == '__main__': + main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__init__.py new file mode 100644 index 0000000..0491234 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/__init__.py @@ -0,0 +1,35 @@ +""" +HTML parsing library based on the `WHATWG HTML specification +<https://whatwg.org/html>`_. The parser is designed to be compatible with +existing HTML found in the wild and implements well-defined error recovery that +is largely compatible with modern desktop web browsers. + +Example usage:: + + from pip._vendor import html5lib + with open("my_document.html", "rb") as f: + tree = html5lib.parse(f) + +For convenience, this module re-exports the following names: + +* :func:`~.html5parser.parse` +* :func:`~.html5parser.parseFragment` +* :class:`~.html5parser.HTMLParser` +* :func:`~.treebuilders.getTreeBuilder` +* :func:`~.treewalkers.getTreeWalker` +* :func:`~.serializer.serialize` +""" + +from __future__ import absolute_import, division, unicode_literals + +from .html5parser import HTMLParser, parse, parseFragment +from .treebuilders import getTreeBuilder +from .treewalkers import getTreeWalker +from .serializer import serialize + +__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", + "getTreeWalker", "serialize"] + +# this has to be at the top level, see how setup.py parses this +#: Distribution version number. +__version__ = "1.0.1" diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_ihatexml.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_ihatexml.py new file mode 100644 index 0000000..4c77717 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_ihatexml.py @@ -0,0 +1,288 @@ +from __future__ import absolute_import, division, unicode_literals + +import re +import warnings + +from .constants import DataLossWarning + +baseChar = """ +[#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | +[#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | +[#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | +[#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | +[#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | +[#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | +[#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | +[#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | +[#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | +[#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | +[#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | +[#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | +[#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | +[#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | +[#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | +[#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | +[#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | +[#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | +[#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | +[#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | +[#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | +[#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | +[#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | +[#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | +[#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | +[#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | +[#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | +[#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | +[#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | +[#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | +#x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | +#x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | +#x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | +[#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | +[#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | +#x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | +[#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | +[#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | +[#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | +[#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | +[#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | +#x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | +[#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | +[#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | +[#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | +[#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]""" + +ideographic = """[#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]""" + +combiningCharacter = """ +[#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] | +[#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 | +[#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] | +[#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] | +#x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] | +[#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] | +[#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | +#x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] | +[#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC | +[#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] | +#x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] | +[#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | +[#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] | +[#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] | +[#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] | +[#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | +#x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | +[#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | +#x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] | +[#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] | +[#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] | +#x3099 | #x309A""" + +digit = """ +[#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] | +[#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] | +[#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] | +[#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]""" + +extender = """ +#x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46 | #x0EC6 | #x3005 | +#[#x3031-#x3035] | [#x309D-#x309E] | [#x30FC-#x30FE]""" + +letter = " | ".join([baseChar, ideographic]) + +# Without the +name = " | ".join([letter, digit, ".", "-", "_", combiningCharacter, + extender]) +nameFirst = " | ".join([letter, "_"]) + +reChar = re.compile(r"#x([\d|A-F]{4,4})") +reCharRange = re.compile(r"\[#x([\d|A-F]{4,4})-#x([\d|A-F]{4,4})\]") + + +def charStringToList(chars): + charRanges = [item.strip() for item in chars.split(" | ")] + rv = [] + for item in charRanges: + foundMatch = False + for regexp in (reChar, reCharRange): + match = regexp.match(item) + if match is not None: + rv.append([hexToInt(item) for item in match.groups()]) + if len(rv[-1]) == 1: + rv[-1] = rv[-1] * 2 + foundMatch = True + break + if not foundMatch: + assert len(item) == 1 + + rv.append([ord(item)] * 2) + rv = normaliseCharList(rv) + return rv + + +def normaliseCharList(charList): + charList = sorted(charList) + for item in charList: + assert item[1] >= item[0] + rv = [] + i = 0 + while i < len(charList): + j = 1 + rv.append(charList[i]) + while i + j < len(charList) and charList[i + j][0] <= rv[-1][1] + 1: + rv[-1][1] = charList[i + j][1] + j += 1 + i += j + return rv + +# We don't really support characters above the BMP :( +max_unicode = int("FFFF", 16) + + +def missingRanges(charList): + rv = [] + if charList[0] != 0: + rv.append([0, charList[0][0] - 1]) + for i, item in enumerate(charList[:-1]): + rv.append([item[1] + 1, charList[i + 1][0] - 1]) + if charList[-1][1] != max_unicode: + rv.append([charList[-1][1] + 1, max_unicode]) + return rv + + +def listToRegexpStr(charList): + rv = [] + for item in charList: + if item[0] == item[1]: + rv.append(escapeRegexp(chr(item[0]))) + else: + rv.append(escapeRegexp(chr(item[0])) + "-" + + escapeRegexp(chr(item[1]))) + return "[%s]" % "".join(rv) + + +def hexToInt(hex_str): + return int(hex_str, 16) + + +def escapeRegexp(string): + specialCharacters = (".", "^", "$", "*", "+", "?", "{", "}", + "[", "]", "|", "(", ")", "-") + for char in specialCharacters: + string = string.replace(char, "\\" + char) + + return string + +# output from the above +nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u02cf\u02d2-\u02ff\u0346-\u035f\u0362-\u0385\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482\u0487-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u0590\u05a2\u05ba\u05be\u05c0\u05c3\u05c5-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u063f\u0653-\u065f\u066a-\u066f\u06b8-\u06b9\u06bf\u06cf\u06d4\u06e9\u06ee-\u06ef\u06fa-\u0900\u0904\u093a-\u093b\u094e-\u0950\u0955-\u0957\u0964-\u0965\u0970-\u0980\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09bd\u09c5-\u09c6\u09c9-\u09ca\u09ce-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09f2-\u0a01\u0a03-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a58\u0a5d\u0a5f-\u0a65\u0a75-\u0a80\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0adf\u0ae1-\u0ae5\u0af0-\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3b\u0b44-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b62-\u0b65\u0b70-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bd6\u0bd8-\u0be6\u0bf0-\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c3d\u0c45\u0c49\u0c4e-\u0c54\u0c57-\u0c5f\u0c62-\u0c65\u0c70-\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbd\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce2-\u0ce5\u0cf0-\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d3d\u0d44-\u0d45\u0d49\u0d4e-\u0d56\u0d58-\u0d5f\u0d62-\u0d65\u0d70-\u0e00\u0e2f\u0e3b-\u0e3f\u0e4f\u0e5a-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0f17\u0f1a-\u0f1f\u0f2a-\u0f34\u0f36\u0f38\u0f3a-\u0f3d\u0f48\u0f6a-\u0f70\u0f85\u0f8c-\u0f8f\u0f96\u0f98\u0fae-\u0fb0\u0fb8\u0fba-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u20cf\u20dd-\u20e0\u20e2-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3004\u3006\u3008-\u3020\u3030\u3036-\u3040\u3095-\u3098\u309b-\u309c\u309f-\u30a0\u30fb\u30ff-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa + +nonXmlNameFirstBMPRegexp = re.compile('[\x00-@\\[-\\^`\\{-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u0385\u0387\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u0640\u064b-\u0670\u06b8-\u06b9\u06bf\u06cf\u06d4\u06d6-\u06e4\u06e7-\u0904\u093a-\u093c\u093e-\u0957\u0962-\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09db\u09de\u09e2-\u09ef\u09f2-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a58\u0a5d\u0a5f-\u0a71\u0a75-\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abc\u0abe-\u0adf\u0ae1-\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3c\u0b3e-\u0b5b\u0b5e\u0b62-\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c5f\u0c62-\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cdd\u0cdf\u0ce2-\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d5f\u0d62-\u0e00\u0e2f\u0e31\u0e34-\u0e3f\u0e46-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eb1\u0eb4-\u0ebc\u0ebe-\u0ebf\u0ec5-\u0f3f\u0f48\u0f6a-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3006\u3008-\u3020\u302a-\u3040\u3095-\u30a0\u30fb-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa + +# Simpler things +nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\\-'()+,./:=?;!*#@$_%]") + + +class InfosetFilter(object): + replacementRegexp = re.compile(r"U[\dA-F]{5,5}") + + def __init__(self, + dropXmlnsLocalName=False, + dropXmlnsAttrNs=False, + preventDoubleDashComments=False, + preventDashAtCommentEnd=False, + replaceFormFeedCharacters=True, + preventSingleQuotePubid=False): + + self.dropXmlnsLocalName = dropXmlnsLocalName + self.dropXmlnsAttrNs = dropXmlnsAttrNs + + self.preventDoubleDashComments = preventDoubleDashComments + self.preventDashAtCommentEnd = preventDashAtCommentEnd + + self.replaceFormFeedCharacters = replaceFormFeedCharacters + + self.preventSingleQuotePubid = preventSingleQuotePubid + + self.replaceCache = {} + + def coerceAttribute(self, name, namespace=None): + if self.dropXmlnsLocalName and name.startswith("xmlns:"): + warnings.warn("Attributes cannot begin with xmlns", DataLossWarning) + return None + elif (self.dropXmlnsAttrNs and + namespace == "http://www.w3.org/2000/xmlns/"): + warnings.warn("Attributes cannot be in the xml namespace", DataLossWarning) + return None + else: + return self.toXmlName(name) + + def coerceElement(self, name): + return self.toXmlName(name) + + def coerceComment(self, data): + if self.preventDoubleDashComments: + while "--" in data: + warnings.warn("Comments cannot contain adjacent dashes", DataLossWarning) + data = data.replace("--", "- -") + if data.endswith("-"): + warnings.warn("Comments cannot end in a dash", DataLossWarning) + data += " " + return data + + def coerceCharacters(self, data): + if self.replaceFormFeedCharacters: + for _ in range(data.count("\x0C")): + warnings.warn("Text cannot contain U+000C", DataLossWarning) + data = data.replace("\x0C", " ") + # Other non-xml characters + return data + + def coercePubid(self, data): + dataOutput = data + for char in nonPubidCharRegexp.findall(data): + warnings.warn("Coercing non-XML pubid", DataLossWarning) + replacement = self.getReplacementCharacter(char) + dataOutput = dataOutput.replace(char, replacement) + if self.preventSingleQuotePubid and dataOutput.find("'") >= 0: + warnings.warn("Pubid cannot contain single quote", DataLossWarning) + dataOutput = dataOutput.replace("'", self.getReplacementCharacter("'")) + return dataOutput + + def toXmlName(self, name): + nameFirst = name[0] + nameRest = name[1:] + m = nonXmlNameFirstBMPRegexp.match(nameFirst) + if m: + warnings.warn("Coercing non-XML name", DataLossWarning) + nameFirstOutput = self.getReplacementCharacter(nameFirst) + else: + nameFirstOutput = nameFirst + + nameRestOutput = nameRest + replaceChars = set(nonXmlNameBMPRegexp.findall(nameRest)) + for char in replaceChars: + warnings.warn("Coercing non-XML name", DataLossWarning) + replacement = self.getReplacementCharacter(char) + nameRestOutput = nameRestOutput.replace(char, replacement) + return nameFirstOutput + nameRestOutput + + def getReplacementCharacter(self, char): + if char in self.replaceCache: + replacement = self.replaceCache[char] + else: + replacement = self.escapeChar(char) + return replacement + + def fromXmlName(self, name): + for item in set(self.replacementRegexp.findall(name)): + name = name.replace(item, self.unescapeChar(item)) + return name + + def escapeChar(self, char): + replacement = "U%05X" % ord(char) + self.replaceCache[char] = replacement + return replacement + + def unescapeChar(self, charcode): + return chr(int(charcode[1:], 16)) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_inputstream.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_inputstream.py new file mode 100644 index 0000000..a65e55f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_inputstream.py @@ -0,0 +1,923 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import text_type, binary_type +from pip._vendor.six.moves import http_client, urllib + +import codecs +import re + +from pip._vendor import webencodings + +from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase +from .constants import _ReparseException +from . import _utils + +from io import StringIO + +try: + from io import BytesIO +except ImportError: + BytesIO = StringIO + +# Non-unicode versions of constants for use in the pre-parser +spaceCharactersBytes = frozenset([item.encode("ascii") for item in spaceCharacters]) +asciiLettersBytes = frozenset([item.encode("ascii") for item in asciiLetters]) +asciiUppercaseBytes = frozenset([item.encode("ascii") for item in asciiUppercase]) +spacesAngleBrackets = spaceCharactersBytes | frozenset([b">", b"<"]) + + +invalid_unicode_no_surrogate = "[\u0001-\u0008\u000B\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\uFFFE\uFFFF\U0001FFFE\U0001FFFF\U0002FFFE\U0002FFFF\U0003FFFE\U0003FFFF\U0004FFFE\U0004FFFF\U0005FFFE\U0005FFFF\U0006FFFE\U0006FFFF\U0007FFFE\U0007FFFF\U0008FFFE\U0008FFFF\U0009FFFE\U0009FFFF\U000AFFFE\U000AFFFF\U000BFFFE\U000BFFFF\U000CFFFE\U000CFFFF\U000DFFFE\U000DFFFF\U000EFFFE\U000EFFFF\U000FFFFE\U000FFFFF\U0010FFFE\U0010FFFF]" # noqa + +if _utils.supports_lone_surrogates: + # Use one extra step of indirection and create surrogates with + # eval. Not using this indirection would introduce an illegal + # unicode literal on platforms not supporting such lone + # surrogates. + assert invalid_unicode_no_surrogate[-1] == "]" and invalid_unicode_no_surrogate.count("]") == 1 + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate[:-1] + + eval('"\\uD800-\\uDFFF"') + # pylint:disable=eval-used + "]") +else: + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate) + +non_bmp_invalid_codepoints = set([0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, + 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, + 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, + 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, + 0x10FFFE, 0x10FFFF]) + +ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005C\u005B-\u0060\u007B-\u007E]") + +# Cache for charsUntil() +charsUntilRegEx = {} + + +class BufferedStream(object): + """Buffering for streams that do not have buffering of their own + + The buffer is implemented as a list of chunks on the assumption that + joining many strings will be slow since it is O(n**2) + """ + + def __init__(self, stream): + self.stream = stream + self.buffer = [] + self.position = [-1, 0] # chunk number, offset + + def tell(self): + pos = 0 + for chunk in self.buffer[:self.position[0]]: + pos += len(chunk) + pos += self.position[1] + return pos + + def seek(self, pos): + assert pos <= self._bufferedBytes() + offset = pos + i = 0 + while len(self.buffer[i]) < offset: + offset -= len(self.buffer[i]) + i += 1 + self.position = [i, offset] + + def read(self, bytes): + if not self.buffer: + return self._readStream(bytes) + elif (self.position[0] == len(self.buffer) and + self.position[1] == len(self.buffer[-1])): + return self._readStream(bytes) + else: + return self._readFromBuffer(bytes) + + def _bufferedBytes(self): + return sum([len(item) for item in self.buffer]) + + def _readStream(self, bytes): + data = self.stream.read(bytes) + self.buffer.append(data) + self.position[0] += 1 + self.position[1] = len(data) + return data + + def _readFromBuffer(self, bytes): + remainingBytes = bytes + rv = [] + bufferIndex = self.position[0] + bufferOffset = self.position[1] + while bufferIndex < len(self.buffer) and remainingBytes != 0: + assert remainingBytes > 0 + bufferedData = self.buffer[bufferIndex] + + if remainingBytes <= len(bufferedData) - bufferOffset: + bytesToRead = remainingBytes + self.position = [bufferIndex, bufferOffset + bytesToRead] + else: + bytesToRead = len(bufferedData) - bufferOffset + self.position = [bufferIndex, len(bufferedData)] + bufferIndex += 1 + rv.append(bufferedData[bufferOffset:bufferOffset + bytesToRead]) + remainingBytes -= bytesToRead + + bufferOffset = 0 + + if remainingBytes: + rv.append(self._readStream(remainingBytes)) + + return b"".join(rv) + + +def HTMLInputStream(source, **kwargs): + # Work around Python bug #20007: read(0) closes the connection. + # http://bugs.python.org/issue20007 + if (isinstance(source, http_client.HTTPResponse) or + # Also check for addinfourl wrapping HTTPResponse + (isinstance(source, urllib.response.addbase) and + isinstance(source.fp, http_client.HTTPResponse))): + isUnicode = False + elif hasattr(source, "read"): + isUnicode = isinstance(source.read(0), text_type) + else: + isUnicode = isinstance(source, text_type) + + if isUnicode: + encodings = [x for x in kwargs if x.endswith("_encoding")] + if encodings: + raise TypeError("Cannot set an encoding with a unicode input, set %r" % encodings) + + return HTMLUnicodeInputStream(source, **kwargs) + else: + return HTMLBinaryInputStream(source, **kwargs) + + +class HTMLUnicodeInputStream(object): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + _defaultChunkSize = 10240 + + def __init__(self, source): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + """ + + if not _utils.supports_lone_surrogates: + # Such platforms will have already checked for such + # surrogate errors, so no need to do this checking. + self.reportCharacterErrors = None + elif len("\U0010FFFF") == 1: + self.reportCharacterErrors = self.characterErrorsUCS4 + else: + self.reportCharacterErrors = self.characterErrorsUCS2 + + # List of where new lines occur + self.newLines = [0] + + self.charEncoding = (lookupEncoding("utf-8"), "certain") + self.dataStream = self.openStream(source) + + self.reset() + + def reset(self): + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + self.errors = [] + + # number of (complete) lines in previous chunks + self.prevNumLines = 0 + # number of columns in the last line of the previous chunk + self.prevNumCols = 0 + + # Deal with CR LF and surrogates split over chunk boundaries + self._bufferedCharacter = None + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = StringIO(source) + + return stream + + def _position(self, offset): + chunk = self.chunk + nLines = chunk.count('\n', 0, offset) + positionLine = self.prevNumLines + nLines + lastLinePos = chunk.rfind('\n', 0, offset) + if lastLinePos == -1: + positionColumn = self.prevNumCols + offset + else: + positionColumn = offset - (lastLinePos + 1) + return (positionLine, positionColumn) + + def position(self): + """Returns (line, col) of the current position in the stream.""" + line, col = self._position(self.chunkOffset) + return (line + 1, col) + + def char(self): + """ Read one character from the stream or queue if available. Return + EOF when EOF is reached. + """ + # Read a new chunk from the input stream if necessary + if self.chunkOffset >= self.chunkSize: + if not self.readChunk(): + return EOF + + chunkOffset = self.chunkOffset + char = self.chunk[chunkOffset] + self.chunkOffset = chunkOffset + 1 + + return char + + def readChunk(self, chunkSize=None): + if chunkSize is None: + chunkSize = self._defaultChunkSize + + self.prevNumLines, self.prevNumCols = self._position(self.chunkSize) + + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + + data = self.dataStream.read(chunkSize) + + # Deal with CR LF and surrogates broken across chunks + if self._bufferedCharacter: + data = self._bufferedCharacter + data + self._bufferedCharacter = None + elif not data: + # We have no more data, bye-bye stream + return False + + if len(data) > 1: + lastv = ord(data[-1]) + if lastv == 0x0D or 0xD800 <= lastv <= 0xDBFF: + self._bufferedCharacter = data[-1] + data = data[:-1] + + if self.reportCharacterErrors: + self.reportCharacterErrors(data) + + # Replace invalid characters + data = data.replace("\r\n", "\n") + data = data.replace("\r", "\n") + + self.chunk = data + self.chunkSize = len(data) + + return True + + def characterErrorsUCS4(self, data): + for _ in range(len(invalid_unicode_re.findall(data))): + self.errors.append("invalid-codepoint") + + def characterErrorsUCS2(self, data): + # Someone picked the wrong compile option + # You lose + skip = False + for match in invalid_unicode_re.finditer(data): + if skip: + continue + codepoint = ord(match.group()) + pos = match.start() + # Pretty sure there should be endianness issues here + if _utils.isSurrogatePair(data[pos:pos + 2]): + # We have a surrogate pair! + char_val = _utils.surrogatePairToCodepoint(data[pos:pos + 2]) + if char_val in non_bmp_invalid_codepoints: + self.errors.append("invalid-codepoint") + skip = True + elif (codepoint >= 0xD800 and codepoint <= 0xDFFF and + pos == len(data) - 1): + self.errors.append("invalid-codepoint") + else: + skip = False + self.errors.append("invalid-codepoint") + + def charsUntil(self, characters, opposite=False): + """ Returns a string of characters from the stream up to but not + including any character in 'characters' or EOF. 'characters' must be + a container that supports the 'in' method and iteration over its + characters. + """ + + # Use a cache of regexps to find the required characters + try: + chars = charsUntilRegEx[(characters, opposite)] + except KeyError: + if __debug__: + for c in characters: + assert(ord(c) < 128) + regex = "".join(["\\x%02x" % ord(c) for c in characters]) + if not opposite: + regex = "^%s" % regex + chars = charsUntilRegEx[(characters, opposite)] = re.compile("[%s]+" % regex) + + rv = [] + + while True: + # Find the longest matching prefix + m = chars.match(self.chunk, self.chunkOffset) + if m is None: + # If nothing matched, and it wasn't because we ran out of chunk, + # then stop + if self.chunkOffset != self.chunkSize: + break + else: + end = m.end() + # If not the whole chunk matched, return everything + # up to the part that didn't match + if end != self.chunkSize: + rv.append(self.chunk[self.chunkOffset:end]) + self.chunkOffset = end + break + # If the whole remainder of the chunk matched, + # use it all and read the next chunk + rv.append(self.chunk[self.chunkOffset:]) + if not self.readChunk(): + # Reached EOF + break + + r = "".join(rv) + return r + + def unget(self, char): + # Only one character is allowed to be ungotten at once - it must + # be consumed again before any further call to unget + if char is not None: + if self.chunkOffset == 0: + # unget is called quite rarely, so it's a good idea to do + # more work here if it saves a bit of work in the frequently + # called char and charsUntil. + # So, just prepend the ungotten character onto the current + # chunk: + self.chunk = char + self.chunk + self.chunkSize += 1 + else: + self.chunkOffset -= 1 + assert self.chunk[self.chunkOffset] == char + + +class HTMLBinaryInputStream(HTMLUnicodeInputStream): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + def __init__(self, source, override_encoding=None, transport_encoding=None, + same_origin_parent_encoding=None, likely_encoding=None, + default_encoding="windows-1252", useChardet=True): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + """ + # Raw Stream - for unicode objects this will encode to utf-8 and set + # self.charEncoding as appropriate + self.rawStream = self.openStream(source) + + HTMLUnicodeInputStream.__init__(self, self.rawStream) + + # Encoding Information + # Number of bytes to use when looking for a meta element with + # encoding information + self.numBytesMeta = 1024 + # Number of bytes to use when using detecting encoding using chardet + self.numBytesChardet = 100 + # Things from args + self.override_encoding = override_encoding + self.transport_encoding = transport_encoding + self.same_origin_parent_encoding = same_origin_parent_encoding + self.likely_encoding = likely_encoding + self.default_encoding = default_encoding + + # Determine encoding + self.charEncoding = self.determineEncoding(useChardet) + assert self.charEncoding[0] is not None + + # Call superclass + self.reset() + + def reset(self): + self.dataStream = self.charEncoding[0].codec_info.streamreader(self.rawStream, 'replace') + HTMLUnicodeInputStream.reset(self) + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = BytesIO(source) + + try: + stream.seek(stream.tell()) + except: # pylint:disable=bare-except + stream = BufferedStream(stream) + + return stream + + def determineEncoding(self, chardet=True): + # BOMs take precedence over everything + # This will also read past the BOM if present + charEncoding = self.detectBOM(), "certain" + if charEncoding[0] is not None: + return charEncoding + + # If we've been overriden, we've been overriden + charEncoding = lookupEncoding(self.override_encoding), "certain" + if charEncoding[0] is not None: + return charEncoding + + # Now check the transport layer + charEncoding = lookupEncoding(self.transport_encoding), "certain" + if charEncoding[0] is not None: + return charEncoding + + # Look for meta elements with encoding information + charEncoding = self.detectEncodingMeta(), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Parent document encoding + charEncoding = lookupEncoding(self.same_origin_parent_encoding), "tentative" + if charEncoding[0] is not None and not charEncoding[0].name.startswith("utf-16"): + return charEncoding + + # "likely" encoding + charEncoding = lookupEncoding(self.likely_encoding), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Guess with chardet, if available + if chardet: + try: + from pip._vendor.chardet.universaldetector import UniversalDetector + except ImportError: + pass + else: + buffers = [] + detector = UniversalDetector() + while not detector.done: + buffer = self.rawStream.read(self.numBytesChardet) + assert isinstance(buffer, bytes) + if not buffer: + break + buffers.append(buffer) + detector.feed(buffer) + detector.close() + encoding = lookupEncoding(detector.result['encoding']) + self.rawStream.seek(0) + if encoding is not None: + return encoding, "tentative" + + # Try the default encoding + charEncoding = lookupEncoding(self.default_encoding), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Fallback to html5lib's default if even that hasn't worked + return lookupEncoding("windows-1252"), "tentative" + + def changeEncoding(self, newEncoding): + assert self.charEncoding[1] != "certain" + newEncoding = lookupEncoding(newEncoding) + if newEncoding is None: + return + if newEncoding.name in ("utf-16be", "utf-16le"): + newEncoding = lookupEncoding("utf-8") + assert newEncoding is not None + elif newEncoding == self.charEncoding[0]: + self.charEncoding = (self.charEncoding[0], "certain") + else: + self.rawStream.seek(0) + self.charEncoding = (newEncoding, "certain") + self.reset() + raise _ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding)) + + def detectBOM(self): + """Attempts to detect at BOM at the start of the stream. If + an encoding can be determined from the BOM return the name of the + encoding otherwise return None""" + bomDict = { + codecs.BOM_UTF8: 'utf-8', + codecs.BOM_UTF16_LE: 'utf-16le', codecs.BOM_UTF16_BE: 'utf-16be', + codecs.BOM_UTF32_LE: 'utf-32le', codecs.BOM_UTF32_BE: 'utf-32be' + } + + # Go to beginning of file and read in 4 bytes + string = self.rawStream.read(4) + assert isinstance(string, bytes) + + # Try detecting the BOM using bytes from the string + encoding = bomDict.get(string[:3]) # UTF-8 + seek = 3 + if not encoding: + # Need to detect UTF-32 before UTF-16 + encoding = bomDict.get(string) # UTF-32 + seek = 4 + if not encoding: + encoding = bomDict.get(string[:2]) # UTF-16 + seek = 2 + + # Set the read position past the BOM if one was found, otherwise + # set it to the start of the stream + if encoding: + self.rawStream.seek(seek) + return lookupEncoding(encoding) + else: + self.rawStream.seek(0) + return None + + def detectEncodingMeta(self): + """Report the encoding declared by the meta element + """ + buffer = self.rawStream.read(self.numBytesMeta) + assert isinstance(buffer, bytes) + parser = EncodingParser(buffer) + self.rawStream.seek(0) + encoding = parser.getEncoding() + + if encoding is not None and encoding.name in ("utf-16be", "utf-16le"): + encoding = lookupEncoding("utf-8") + + return encoding + + +class EncodingBytes(bytes): + """String-like object with an associated position and various extra methods + If the position is ever greater than the string length then an exception is + raised""" + def __new__(self, value): + assert isinstance(value, bytes) + return bytes.__new__(self, value.lower()) + + def __init__(self, value): + # pylint:disable=unused-argument + self._position = -1 + + def __iter__(self): + return self + + def __next__(self): + p = self._position = self._position + 1 + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + return self[p:p + 1] + + def next(self): + # Py2 compat + return self.__next__() + + def previous(self): + p = self._position + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + self._position = p = p - 1 + return self[p:p + 1] + + def setPosition(self, position): + if self._position >= len(self): + raise StopIteration + self._position = position + + def getPosition(self): + if self._position >= len(self): + raise StopIteration + if self._position >= 0: + return self._position + else: + return None + + position = property(getPosition, setPosition) + + def getCurrentByte(self): + return self[self.position:self.position + 1] + + currentByte = property(getCurrentByte) + + def skip(self, chars=spaceCharactersBytes): + """Skip past a list of characters""" + p = self.position # use property for the error-checking + while p < len(self): + c = self[p:p + 1] + if c not in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def skipUntil(self, chars): + p = self.position + while p < len(self): + c = self[p:p + 1] + if c in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def matchBytes(self, bytes): + """Look for a sequence of bytes at the start of a string. If the bytes + are found return True and advance the position to the byte after the + match. Otherwise return False and leave the position alone""" + p = self.position + data = self[p:p + len(bytes)] + rv = data.startswith(bytes) + if rv: + self.position += len(bytes) + return rv + + def jumpTo(self, bytes): + """Look for the next sequence of bytes matching a given sequence. If + a match is found advance the position to the last byte of the match""" + newPosition = self[self.position:].find(bytes) + if newPosition > -1: + # XXX: This is ugly, but I can't see a nicer way to fix this. + if self._position == -1: + self._position = 0 + self._position += (newPosition + len(bytes) - 1) + return True + else: + raise StopIteration + + +class EncodingParser(object): + """Mini parser for detecting character encoding from meta elements""" + + def __init__(self, data): + """string - the data to work on for encoding detection""" + self.data = EncodingBytes(data) + self.encoding = None + + def getEncoding(self): + methodDispatch = ( + (b"<!--", self.handleComment), + (b"<meta", self.handleMeta), + (b"</", self.handlePossibleEndTag), + (b"<!", self.handleOther), + (b"<?", self.handleOther), + (b"<", self.handlePossibleStartTag)) + for _ in self.data: + keepParsing = True + for key, method in methodDispatch: + if self.data.matchBytes(key): + try: + keepParsing = method() + break + except StopIteration: + keepParsing = False + break + if not keepParsing: + break + + return self.encoding + + def handleComment(self): + """Skip over comments""" + return self.data.jumpTo(b"-->") + + def handleMeta(self): + if self.data.currentByte not in spaceCharactersBytes: + # if we have <meta not followed by a space so just keep going + return True + # We have a valid meta element we want to search for attributes + hasPragma = False + pendingEncoding = None + while True: + # Try to find the next attribute after the current position + attr = self.getAttribute() + if attr is None: + return True + else: + if attr[0] == b"http-equiv": + hasPragma = attr[1] == b"content-type" + if hasPragma and pendingEncoding is not None: + self.encoding = pendingEncoding + return False + elif attr[0] == b"charset": + tentativeEncoding = attr[1] + codec = lookupEncoding(tentativeEncoding) + if codec is not None: + self.encoding = codec + return False + elif attr[0] == b"content": + contentParser = ContentAttrParser(EncodingBytes(attr[1])) + tentativeEncoding = contentParser.parse() + if tentativeEncoding is not None: + codec = lookupEncoding(tentativeEncoding) + if codec is not None: + if hasPragma: + self.encoding = codec + return False + else: + pendingEncoding = codec + + def handlePossibleStartTag(self): + return self.handlePossibleTag(False) + + def handlePossibleEndTag(self): + next(self.data) + return self.handlePossibleTag(True) + + def handlePossibleTag(self, endTag): + data = self.data + if data.currentByte not in asciiLettersBytes: + # If the next byte is not an ascii letter either ignore this + # fragment (possible start tag case) or treat it according to + # handleOther + if endTag: + data.previous() + self.handleOther() + return True + + c = data.skipUntil(spacesAngleBrackets) + if c == b"<": + # return to the first step in the overall "two step" algorithm + # reprocessing the < byte + data.previous() + else: + # Read all attributes + attr = self.getAttribute() + while attr is not None: + attr = self.getAttribute() + return True + + def handleOther(self): + return self.data.jumpTo(b">") + + def getAttribute(self): + """Return a name,value pair for the next attribute in the stream, + if one is found, or None""" + data = self.data + # Step 1 (skip chars) + c = data.skip(spaceCharactersBytes | frozenset([b"/"])) + assert c is None or len(c) == 1 + # Step 2 + if c in (b">", None): + return None + # Step 3 + attrName = [] + attrValue = [] + # Step 4 attribute name + while True: + if c == b"=" and attrName: + break + elif c in spaceCharactersBytes: + # Step 6! + c = data.skip() + break + elif c in (b"/", b">"): + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrName.append(c.lower()) + elif c is None: + return None + else: + attrName.append(c) + # Step 5 + c = next(data) + # Step 7 + if c != b"=": + data.previous() + return b"".join(attrName), b"" + # Step 8 + next(data) + # Step 9 + c = data.skip() + # Step 10 + if c in (b"'", b'"'): + # 10.1 + quoteChar = c + while True: + # 10.2 + c = next(data) + # 10.3 + if c == quoteChar: + next(data) + return b"".join(attrName), b"".join(attrValue) + # 10.4 + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + # 10.5 + else: + attrValue.append(c) + elif c == b">": + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + # Step 11 + while True: + c = next(data) + if c in spacesAngleBrackets: + return b"".join(attrName), b"".join(attrValue) + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + + +class ContentAttrParser(object): + def __init__(self, data): + assert isinstance(data, bytes) + self.data = data + + def parse(self): + try: + # Check if the attr name is charset + # otherwise return + self.data.jumpTo(b"charset") + self.data.position += 1 + self.data.skip() + if not self.data.currentByte == b"=": + # If there is no = sign keep looking for attrs + return None + self.data.position += 1 + self.data.skip() + # Look for an encoding between matching quote marks + if self.data.currentByte in (b'"', b"'"): + quoteMark = self.data.currentByte + self.data.position += 1 + oldPosition = self.data.position + if self.data.jumpTo(quoteMark): + return self.data[oldPosition:self.data.position] + else: + return None + else: + # Unquoted value + oldPosition = self.data.position + try: + self.data.skipUntil(spaceCharactersBytes) + return self.data[oldPosition:self.data.position] + except StopIteration: + # Return the whole remaining value + return self.data[oldPosition:] + except StopIteration: + return None + + +def lookupEncoding(encoding): + """Return the python codec name corresponding to an encoding or None if the + string doesn't correspond to a valid encoding.""" + if isinstance(encoding, binary_type): + try: + encoding = encoding.decode("ascii") + except UnicodeDecodeError: + return None + + if encoding is not None: + try: + return webencodings.lookup(encoding) + except AttributeError: + return None + else: + return None diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_tokenizer.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_tokenizer.py new file mode 100644 index 0000000..178f6e7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_tokenizer.py @@ -0,0 +1,1721 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import unichr as chr + +from collections import deque + +from .constants import spaceCharacters +from .constants import entities +from .constants import asciiLetters, asciiUpper2Lower +from .constants import digits, hexDigits, EOF +from .constants import tokenTypes, tagTokenTypes +from .constants import replacementCharacters + +from ._inputstream import HTMLInputStream + +from ._trie import Trie + +entitiesTrie = Trie(entities) + + +class HTMLTokenizer(object): + """ This class takes care of tokenizing HTML. + + * self.currentToken + Holds the token that is currently being processed. + + * self.state + Holds a reference to the method to be invoked... XXX + + * self.stream + Points to HTMLInputStream object. + """ + + def __init__(self, stream, parser=None, **kwargs): + + self.stream = HTMLInputStream(stream, **kwargs) + self.parser = parser + + # Setup the initial tokenizer state + self.escapeFlag = False + self.lastFourChars = [] + self.state = self.dataState + self.escape = False + + # The current token being created + self.currentToken = None + super(HTMLTokenizer, self).__init__() + + def __iter__(self): + """ This is where the magic happens. + + We do our usually processing through the states and when we have a token + to return we yield the token which pauses processing until the next token + is requested. + """ + self.tokenQueue = deque([]) + # Start processing. When EOF is reached self.state will return False + # instead of True and the loop will terminate. + while self.state(): + while self.stream.errors: + yield {"type": tokenTypes["ParseError"], "data": self.stream.errors.pop(0)} + while self.tokenQueue: + yield self.tokenQueue.popleft() + + def consumeNumberEntity(self, isHex): + """This function returns either U+FFFD or the character based on the + decimal or hexadecimal representation. It also discards ";" if present. + If not present self.tokenQueue.append({"type": tokenTypes["ParseError"]}) is invoked. + """ + + allowed = digits + radix = 10 + if isHex: + allowed = hexDigits + radix = 16 + + charStack = [] + + # Consume all the characters that are in range while making sure we + # don't hit an EOF. + c = self.stream.char() + while c in allowed and c is not EOF: + charStack.append(c) + c = self.stream.char() + + # Convert the set of characters consumed to an int. + charAsInt = int("".join(charStack), radix) + + # Certain characters get replaced with others + if charAsInt in replacementCharacters: + char = replacementCharacters[charAsInt] + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + elif ((0xD800 <= charAsInt <= 0xDFFF) or + (charAsInt > 0x10FFFF)): + char = "\uFFFD" + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + else: + # Should speed up this check somehow (e.g. move the set to a constant) + if ((0x0001 <= charAsInt <= 0x0008) or + (0x000E <= charAsInt <= 0x001F) or + (0x007F <= charAsInt <= 0x009F) or + (0xFDD0 <= charAsInt <= 0xFDEF) or + charAsInt in frozenset([0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, + 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, + 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, + 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, + 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, + 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, + 0xFFFFF, 0x10FFFE, 0x10FFFF])): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + try: + # Try/except needed as UCS-2 Python builds' unichar only works + # within the BMP. + char = chr(charAsInt) + except ValueError: + v = charAsInt - 0x10000 + char = chr(0xD800 | (v >> 10)) + chr(0xDC00 | (v & 0x3FF)) + + # Discard the ; if present. Otherwise, put it back on the queue and + # invoke parseError on parser. + if c != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "numeric-entity-without-semicolon"}) + self.stream.unget(c) + + return char + + def consumeEntity(self, allowedChar=None, fromAttribute=False): + # Initialise to the default output for when no entity is matched + output = "&" + + charStack = [self.stream.char()] + if (charStack[0] in spaceCharacters or charStack[0] in (EOF, "<", "&") or + (allowedChar is not None and allowedChar == charStack[0])): + self.stream.unget(charStack[0]) + + elif charStack[0] == "#": + # Read the next character to see if it's hex or decimal + hex = False + charStack.append(self.stream.char()) + if charStack[-1] in ("x", "X"): + hex = True + charStack.append(self.stream.char()) + + # charStack[-1] should be the first digit + if (hex and charStack[-1] in hexDigits) \ + or (not hex and charStack[-1] in digits): + # At least one digit found, so consume the whole number + self.stream.unget(charStack[-1]) + output = self.consumeNumberEntity(hex) + else: + # No digits found + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "expected-numeric-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + else: + # At this point in the process might have named entity. Entities + # are stored in the global variable "entities". + # + # Consume characters and compare to these to a substring of the + # entity names in the list until the substring no longer matches. + while (charStack[-1] is not EOF): + if not entitiesTrie.has_keys_with_prefix("".join(charStack)): + break + charStack.append(self.stream.char()) + + # At this point we have a string that starts with some characters + # that may match an entity + # Try to find the longest entity the string will match to take care + # of ¬i for instance. + try: + entityName = entitiesTrie.longest_prefix("".join(charStack[:-1])) + entityLength = len(entityName) + except KeyError: + entityName = None + + if entityName is not None: + if entityName[-1] != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "named-entity-without-semicolon"}) + if (entityName[-1] != ";" and fromAttribute and + (charStack[entityLength] in asciiLetters or + charStack[entityLength] in digits or + charStack[entityLength] == "=")): + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + else: + output = entities[entityName] + self.stream.unget(charStack.pop()) + output += "".join(charStack[entityLength:]) + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-named-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + if fromAttribute: + self.currentToken["data"][-1][1] += output + else: + if output in spaceCharacters: + tokenType = "SpaceCharacters" + else: + tokenType = "Characters" + self.tokenQueue.append({"type": tokenTypes[tokenType], "data": output}) + + def processEntityInAttribute(self, allowedChar): + """This method replaces the need for "entityInAttributeValueState". + """ + self.consumeEntity(allowedChar=allowedChar, fromAttribute=True) + + def emitCurrentToken(self): + """This method is a generic handler for emitting the tags. It also sets + the state to "data" because that's what's needed after a token has been + emitted. + """ + token = self.currentToken + # Add token to the queue to be yielded + if (token["type"] in tagTokenTypes): + token["name"] = token["name"].translate(asciiUpper2Lower) + if token["type"] == tokenTypes["EndTag"]: + if token["data"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "attributes-in-end-tag"}) + if token["selfClosing"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "self-closing-flag-on-end-tag"}) + self.tokenQueue.append(token) + self.state = self.dataState + + # Below are the various tokenizer states worked out. + def dataState(self): + data = self.stream.char() + if data == "&": + self.state = self.entityDataState + elif data == "<": + self.state = self.tagOpenState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\u0000"}) + elif data is EOF: + # Tokenization ends. + return False + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any <!-- or --> sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def entityDataState(self): + self.consumeEntity() + self.state = self.dataState + return True + + def rcdataState(self): + data = self.stream.char() + if data == "&": + self.state = self.characterReferenceInRcdata + elif data == "<": + self.state = self.rcdataLessThanSignState + elif data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any <!-- or --> sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def characterReferenceInRcdata(self): + self.consumeEntity() + self.state = self.rcdataState + return True + + def rawtextState(self): + data = self.stream.char() + if data == "<": + self.state = self.rawtextLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataState(self): + data = self.stream.char() + if data == "<": + self.state = self.scriptDataLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def plaintextState(self): + data = self.stream.char() + if data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + self.stream.charsUntil("\u0000")}) + return True + + def tagOpenState(self): + data = self.stream.char() + if data == "!": + self.state = self.markupDeclarationOpenState + elif data == "/": + self.state = self.closeTagOpenState + elif data in asciiLetters: + self.currentToken = {"type": tokenTypes["StartTag"], + "name": data, "data": [], + "selfClosing": False, + "selfClosingAcknowledged": False} + self.state = self.tagNameState + elif data == ">": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-right-bracket"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<>"}) + self.state = self.dataState + elif data == "?": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-question-mark"}) + self.stream.unget(data) + self.state = self.bogusCommentState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.dataState + return True + + def closeTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.currentToken = {"type": tokenTypes["EndTag"], "name": data, + "data": [], "selfClosing": False} + self.state = self.tagNameState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-right-bracket"}) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-eof"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.state = self.dataState + else: + # XXX data can be _'_... + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-char", + "datavars": {"data": data}}) + self.stream.unget(data) + self.state = self.bogusCommentState + return True + + def tagNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-tag-name"}) + self.state = self.dataState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + else: + self.currentToken["name"] += data + # (Don't use charsUntil here, because tag names are + # very short and it's faster to not do anything fancy) + return True + + def rcdataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rcdataEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rcdataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rawtextLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rawtextEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def rawtextEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rawtextEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def rawtextEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def scriptDataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEndTagOpenState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<!"}) + self.state = self.scriptDataEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.scriptDataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapeStartState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapeStartDashState + else: + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapeStartDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashDashState + else: + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashState + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.state = self.dataState + else: + chars = self.stream.charsUntil(("<", "-", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashDashState + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEscapedEndTagOpenState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<" + data}) + self.temporaryBuffer = data + self.state = self.scriptDataDoubleEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer = data + self.state = self.scriptDataEscapedEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapeStartState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataDoubleEscapedState + else: + self.state = self.scriptDataEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + return True + + def scriptDataDoubleEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "/"}) + self.temporaryBuffer = "" + self.state = self.scriptDataDoubleEscapeEndState + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapeEndState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataEscapedState + else: + self.state = self.scriptDataDoubleEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def beforeAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data in ("'", '"', "=", "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-name-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def attributeNameState(self): + data = self.stream.char() + leavingThisState = True + emitToken = False + if data == "=": + self.state = self.beforeAttributeValueState + elif data in asciiLetters: + self.currentToken["data"][-1][0] += data +\ + self.stream.charsUntil(asciiLetters, True) + leavingThisState = False + elif data == ">": + # XXX If we emit here the attributes are converted to a dict + # without being checked and when the code below runs we error + # because data is a dict not a list + emitToken = True + elif data in spaceCharacters: + self.state = self.afterAttributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][0] += "\uFFFD" + leavingThisState = False + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"][-1][0] += data + leavingThisState = False + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-attribute-name"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][0] += data + leavingThisState = False + + if leavingThisState: + # Attributes are not dropped at this stage. That happens when the + # start tag token is emitted so values can still be safely appended + # to attributes, but we do want to report the parse error in time. + self.currentToken["data"][-1][0] = ( + self.currentToken["data"][-1][0].translate(asciiUpper2Lower)) + for name, _ in self.currentToken["data"][:-1]: + if self.currentToken["data"][-1][0] == name: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "duplicate-attribute"}) + break + # XXX Fix for above XXX + if emitToken: + self.emitCurrentToken() + return True + + def afterAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "=": + self.state = self.beforeAttributeValueState + elif data == ">": + self.emitCurrentToken() + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-after-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-end-of-tag-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def beforeAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "\"": + self.state = self.attributeValueDoubleQuotedState + elif data == "&": + self.state = self.attributeValueUnQuotedState + self.stream.unget(data) + elif data == "'": + self.state = self.attributeValueSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-right-bracket"}) + self.emitCurrentToken() + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + self.state = self.attributeValueUnQuotedState + elif data in ("=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "equals-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + return True + + def attributeValueDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute('"') + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-double-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("\"", "&", "\u0000")) + return True + + def attributeValueSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute("'") + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-single-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("'", "&", "\u0000")) + return True + + def attributeValueUnQuotedState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == "&": + self.processEntityInAttribute(">") + elif data == ">": + self.emitCurrentToken() + elif data in ('"', "'", "=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-no-quotes"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.stream.charsUntil( + frozenset(("&", ">", '"', "'", "=", "<", "`", "\u0000")) | spaceCharacters) + return True + + def afterAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-EOF-after-attribute-value"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-attribute-value"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def selfClosingStartTagState(self): + data = self.stream.char() + if data == ">": + self.currentToken["selfClosing"] = True + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "unexpected-EOF-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def bogusCommentState(self): + # Make a new comment token and give it as value all the characters + # until the first > or EOF (charsUntil checks for EOF automatically) + # and emit it. + data = self.stream.charsUntil(">") + data = data.replace("\u0000", "\uFFFD") + self.tokenQueue.append( + {"type": tokenTypes["Comment"], "data": data}) + + # Eat the character directly after the bogus comment which is either a + # ">" or an EOF. + self.stream.char() + self.state = self.dataState + return True + + def markupDeclarationOpenState(self): + charStack = [self.stream.char()] + if charStack[-1] == "-": + charStack.append(self.stream.char()) + if charStack[-1] == "-": + self.currentToken = {"type": tokenTypes["Comment"], "data": ""} + self.state = self.commentStartState + return True + elif charStack[-1] in ('d', 'D'): + matched = True + for expected in (('o', 'O'), ('c', 'C'), ('t', 'T'), + ('y', 'Y'), ('p', 'P'), ('e', 'E')): + charStack.append(self.stream.char()) + if charStack[-1] not in expected: + matched = False + break + if matched: + self.currentToken = {"type": tokenTypes["Doctype"], + "name": "", + "publicId": None, "systemId": None, + "correct": True} + self.state = self.doctypeState + return True + elif (charStack[-1] == "[" and + self.parser is not None and + self.parser.tree.openElements and + self.parser.tree.openElements[-1].namespace != self.parser.tree.defaultNamespace): + matched = True + for expected in ["C", "D", "A", "T", "A", "["]: + charStack.append(self.stream.char()) + if charStack[-1] != expected: + matched = False + break + if matched: + self.state = self.cdataSectionState + return True + + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-dashes-or-doctype"}) + + while charStack: + self.stream.unget(charStack.pop()) + self.state = self.bogusCommentState + return True + + def commentStartState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentStartDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + self.state = self.commentState + return True + + def commentStartDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + \ + self.stream.charsUntil(("-", "\u0000")) + return True + + def commentEndDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentEndState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--\uFFFD" + self.state = self.commentState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-bang-after-double-dash-in-comment"}) + self.state = self.commentEndBangState + elif data == "-": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-dash-after-double-dash-in-comment"}) + self.currentToken["data"] += data + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-double-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-comment"}) + self.currentToken["data"] += "--" + data + self.state = self.commentState + return True + + def commentEndBangState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "-": + self.currentToken["data"] += "--!" + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--!\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-bang-state"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "--!" + data + self.state = self.commentState + return True + + def doctypeState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "need-space-after-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeNameState + return True + + def beforeDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-right-bracket"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] = "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] = data + self.state = self.doctypeNameState + return True + + def doctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.state = self.afterDoctypeNameState + elif data == ">": + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype-name"}) + self.currentToken["correct"] = False + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] += data + return True + + def afterDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.currentToken["correct"] = False + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + if data in ("p", "P"): + matched = True + for expected in (("u", "U"), ("b", "B"), ("l", "L"), + ("i", "I"), ("c", "C")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypePublicKeywordState + return True + elif data in ("s", "S"): + matched = True + for expected in (("y", "Y"), ("s", "S"), ("t", "T"), + ("e", "E"), ("m", "M")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypeSystemKeywordState + return True + + # All the characters read before the current 'data' will be + # [a-zA-Z], so they're garbage in the bogus doctype and can be + # discarded; only the latest character might be '>' or EOF + # and needs to be ungetted + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-space-or-right-bracket-in-doctype", "datavars": + {"data": data}}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + + return True + + def afterDoctypePublicKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypePublicIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + return True + + def beforeDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypePublicIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def doctypePublicIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def afterDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.betweenDoctypePublicAndSystemIdentifiersState + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def betweenDoctypePublicAndSystemIdentifiersState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def afterDoctypeSystemKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeSystemIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + return True + + def beforeDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypeSystemIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def doctypeSystemIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def afterDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.state = self.bogusDoctypeState + return True + + def bogusDoctypeState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + # XXX EMIT + self.stream.unget(data) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + pass + return True + + def cdataSectionState(self): + data = [] + while True: + data.append(self.stream.charsUntil("]")) + data.append(self.stream.charsUntil(">")) + char = self.stream.char() + if char == EOF: + break + else: + assert char == ">" + if data[-1][-2:] == "]]": + data[-1] = data[-1][:-2] + break + else: + data.append(char) + + data = "".join(data) # pylint:disable=redefined-variable-type + # Deal with null here rather than in the parser + nullCount = data.count("\u0000") + if nullCount > 0: + for _ in range(nullCount): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + data = data.replace("\u0000", "\uFFFD") + if data: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": data}) + self.state = self.dataState + return True diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py new file mode 100644 index 0000000..a5ba4bf --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/__init__.py @@ -0,0 +1,14 @@ +from __future__ import absolute_import, division, unicode_literals + +from .py import Trie as PyTrie + +Trie = PyTrie + +# pylint:disable=wrong-import-position +try: + from .datrie import Trie as DATrie +except ImportError: + pass +else: + Trie = DATrie +# pylint:enable=wrong-import-position diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/_base.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/_base.py new file mode 100644 index 0000000..a1158bb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/_base.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import, division, unicode_literals + +from collections import Mapping + + +class Trie(Mapping): + """Abstract base class for tries""" + + def keys(self, prefix=None): + # pylint:disable=arguments-differ + keys = super(Trie, self).keys() + + if prefix is None: + return set(keys) + + return {x for x in keys if x.startswith(prefix)} + + def has_keys_with_prefix(self, prefix): + for key in self.keys(): + if key.startswith(prefix): + return True + + return False + + def longest_prefix(self, prefix): + if prefix in self: + return prefix + + for i in range(1, len(prefix) + 1): + if prefix[:-i] in self: + return prefix[:-i] + + raise KeyError(prefix) + + def longest_prefix_item(self, prefix): + lprefix = self.longest_prefix(prefix) + return (lprefix, self[lprefix]) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py new file mode 100644 index 0000000..e2e5f86 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/datrie.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import, division, unicode_literals + +from datrie import Trie as DATrie +from pip._vendor.six import text_type + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + chars = set() + for key in data.keys(): + if not isinstance(key, text_type): + raise TypeError("All keys must be strings") + for char in key: + chars.add(char) + + self._data = DATrie("".join(chars)) + for key, value in data.items(): + self._data[key] = value + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + raise NotImplementedError() + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + return self._data.keys(prefix) + + def has_keys_with_prefix(self, prefix): + return self._data.has_keys_with_prefix(prefix) + + def longest_prefix(self, prefix): + return self._data.longest_prefix(prefix) + + def longest_prefix_item(self, prefix): + return self._data.longest_prefix_item(prefix) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/py.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/py.py new file mode 100644 index 0000000..c178b21 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_trie/py.py @@ -0,0 +1,67 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from bisect import bisect_left + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + if not all(isinstance(x, text_type) for x in data.keys()): + raise TypeError("All keys must be strings") + + self._data = data + self._keys = sorted(data.keys()) + self._cachestr = "" + self._cachepoints = (0, len(data)) + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + return iter(self._data) + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + if prefix is None or prefix == "" or not self._keys: + return set(self._keys) + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + start = i = bisect_left(self._keys, prefix, lo, hi) + else: + start = i = bisect_left(self._keys, prefix) + + keys = set() + if start == len(self._keys): + return keys + + while self._keys[i].startswith(prefix): + keys.add(self._keys[i]) + i += 1 + + self._cachestr = prefix + self._cachepoints = (start, i) + + return keys + + def has_keys_with_prefix(self, prefix): + if prefix in self._data: + return True + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + i = bisect_left(self._keys, prefix, lo, hi) + else: + i = bisect_left(self._keys, prefix) + + if i == len(self._keys): + return False + + return self._keys[i].startswith(prefix) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_utils.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_utils.py new file mode 100644 index 0000000..0703afb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/_utils.py @@ -0,0 +1,124 @@ +from __future__ import absolute_import, division, unicode_literals + +from types import ModuleType + +from pip._vendor.six import text_type + +try: + import xml.etree.cElementTree as default_etree +except ImportError: + import xml.etree.ElementTree as default_etree + + +__all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair", + "surrogatePairToCodepoint", "moduleFactoryFactory", + "supports_lone_surrogates"] + + +# Platforms not supporting lone surrogates (\uD800-\uDFFF) should be +# caught by the below test. In general this would be any platform +# using UTF-16 as its encoding of unicode strings, such as +# Jython. This is because UTF-16 itself is based on the use of such +# surrogates, and there is no mechanism to further escape such +# escapes. +try: + _x = eval('"\\uD800"') # pylint:disable=eval-used + if not isinstance(_x, text_type): + # We need this with u"" because of http://bugs.jython.org/issue2039 + _x = eval('u"\\uD800"') # pylint:disable=eval-used + assert isinstance(_x, text_type) +except: # pylint:disable=bare-except + supports_lone_surrogates = False +else: + supports_lone_surrogates = True + + +class MethodDispatcher(dict): + """Dict with 2 special properties: + + On initiation, keys that are lists, sets or tuples are converted to + multiple keys so accessing any one of the items in the original + list-like object returns the matching value + + md = MethodDispatcher({("foo", "bar"):"baz"}) + md["foo"] == "baz" + + A default value which can be set through the default attribute. + """ + + def __init__(self, items=()): + # Using _dictEntries instead of directly assigning to self is about + # twice as fast. Please do careful performance testing before changing + # anything here. + _dictEntries = [] + for name, value in items: + if isinstance(name, (list, tuple, frozenset, set)): + for item in name: + _dictEntries.append((item, value)) + else: + _dictEntries.append((name, value)) + dict.__init__(self, _dictEntries) + assert len(self) == len(_dictEntries) + self.default = None + + def __getitem__(self, key): + return dict.get(self, key, self.default) + + +# Some utility functions to deal with weirdness around UCS2 vs UCS4 +# python builds + +def isSurrogatePair(data): + return (len(data) == 2 and + ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and + ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF) + + +def surrogatePairToCodepoint(data): + char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 + + (ord(data[1]) - 0xDC00)) + return char_val + +# Module Factory Factory (no, this isn't Java, I know) +# Here to stop this being duplicated all over the place. + + +def moduleFactoryFactory(factory): + moduleCache = {} + + def moduleFactory(baseModule, *args, **kwargs): + if isinstance(ModuleType.__name__, type("")): + name = "_%s_factory" % baseModule.__name__ + else: + name = b"_%s_factory" % baseModule.__name__ + + kwargs_tuple = tuple(kwargs.items()) + + try: + return moduleCache[name][args][kwargs_tuple] + except KeyError: + mod = ModuleType(name) + objs = factory(baseModule, *args, **kwargs) + mod.__dict__.update(objs) + if "name" not in moduleCache: + moduleCache[name] = {} + if "args" not in moduleCache[name]: + moduleCache[name][args] = {} + if "kwargs" not in moduleCache[name][args]: + moduleCache[name][args][kwargs_tuple] = {} + moduleCache[name][args][kwargs_tuple] = mod + return mod + + return moduleFactory + + +def memoize(func): + cache = {} + + def wrapped(*args, **kwargs): + key = (tuple(args), tuple(kwargs.items())) + if key not in cache: + cache[key] = func(*args, **kwargs) + return cache[key] + + return wrapped diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/constants.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/constants.py new file mode 100644 index 0000000..1ff8041 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/constants.py @@ -0,0 +1,2947 @@ +from __future__ import absolute_import, division, unicode_literals + +import string + +EOF = None + +E = { + "null-character": + "Null character in input stream, replaced with U+FFFD.", + "invalid-codepoint": + "Invalid codepoint in stream.", + "incorrectly-placed-solidus": + "Solidus (/) incorrectly placed in tag.", + "incorrect-cr-newline-entity": + "Incorrect CR newline entity, replaced with LF.", + "illegal-windows-1252-entity": + "Entity used with illegal number (windows-1252 reference).", + "cant-convert-numeric-entity": + "Numeric entity couldn't be converted to character " + "(codepoint U+%(charAsInt)08x).", + "illegal-codepoint-for-numeric-entity": + "Numeric entity represents an illegal codepoint: " + "U+%(charAsInt)08x.", + "numeric-entity-without-semicolon": + "Numeric entity didn't end with ';'.", + "expected-numeric-entity-but-got-eof": + "Numeric entity expected. Got end of file instead.", + "expected-numeric-entity": + "Numeric entity expected but none found.", + "named-entity-without-semicolon": + "Named entity didn't end with ';'.", + "expected-named-entity": + "Named entity expected. Got none.", + "attributes-in-end-tag": + "End tag contains unexpected attributes.", + 'self-closing-flag-on-end-tag': + "End tag contains unexpected self-closing flag.", + "expected-tag-name-but-got-right-bracket": + "Expected tag name. Got '>' instead.", + "expected-tag-name-but-got-question-mark": + "Expected tag name. Got '?' instead. (HTML doesn't " + "support processing instructions.)", + "expected-tag-name": + "Expected tag name. Got something else instead", + "expected-closing-tag-but-got-right-bracket": + "Expected closing tag. Got '>' instead. Ignoring '</>'.", + "expected-closing-tag-but-got-eof": + "Expected closing tag. Unexpected end of file.", + "expected-closing-tag-but-got-char": + "Expected closing tag. Unexpected character '%(data)s' found.", + "eof-in-tag-name": + "Unexpected end of file in the tag name.", + "expected-attribute-name-but-got-eof": + "Unexpected end of file. Expected attribute name instead.", + "eof-in-attribute-name": + "Unexpected end of file in attribute name.", + "invalid-character-in-attribute-name": + "Invalid character in attribute name", + "duplicate-attribute": + "Dropped duplicate attribute on tag.", + "expected-end-of-tag-name-but-got-eof": + "Unexpected end of file. Expected = or end of tag.", + "expected-attribute-value-but-got-eof": + "Unexpected end of file. Expected attribute value.", + "expected-attribute-value-but-got-right-bracket": + "Expected attribute value. Got '>' instead.", + 'equals-in-unquoted-attribute-value': + "Unexpected = in unquoted attribute", + 'unexpected-character-in-unquoted-attribute-value': + "Unexpected character in unquoted attribute", + "invalid-character-after-attribute-name": + "Unexpected character after attribute name.", + "unexpected-character-after-attribute-value": + "Unexpected character after attribute value.", + "eof-in-attribute-value-double-quote": + "Unexpected end of file in attribute value (\").", + "eof-in-attribute-value-single-quote": + "Unexpected end of file in attribute value (').", + "eof-in-attribute-value-no-quotes": + "Unexpected end of file in attribute value.", + "unexpected-EOF-after-solidus-in-tag": + "Unexpected end of file in tag. Expected >", + "unexpected-character-after-solidus-in-tag": + "Unexpected character after / in tag. Expected >", + "expected-dashes-or-doctype": + "Expected '--' or 'DOCTYPE'. Not found.", + "unexpected-bang-after-double-dash-in-comment": + "Unexpected ! after -- in comment", + "unexpected-space-after-double-dash-in-comment": + "Unexpected space after -- in comment", + "incorrect-comment": + "Incorrect comment.", + "eof-in-comment": + "Unexpected end of file in comment.", + "eof-in-comment-end-dash": + "Unexpected end of file in comment (-)", + "unexpected-dash-after-double-dash-in-comment": + "Unexpected '-' after '--' found in comment.", + "eof-in-comment-double-dash": + "Unexpected end of file in comment (--).", + "eof-in-comment-end-space-state": + "Unexpected end of file in comment.", + "eof-in-comment-end-bang-state": + "Unexpected end of file in comment.", + "unexpected-char-in-comment": + "Unexpected character in comment found.", + "need-space-after-doctype": + "No space after literal string 'DOCTYPE'.", + "expected-doctype-name-but-got-right-bracket": + "Unexpected > character. Expected DOCTYPE name.", + "expected-doctype-name-but-got-eof": + "Unexpected end of file. Expected DOCTYPE name.", + "eof-in-doctype-name": + "Unexpected end of file in DOCTYPE name.", + "eof-in-doctype": + "Unexpected end of file in DOCTYPE.", + "expected-space-or-right-bracket-in-doctype": + "Expected space or '>'. Got '%(data)s'", + "unexpected-end-of-doctype": + "Unexpected end of DOCTYPE.", + "unexpected-char-in-doctype": + "Unexpected character in DOCTYPE.", + "eof-in-innerhtml": + "XXX innerHTML EOF", + "unexpected-doctype": + "Unexpected DOCTYPE. Ignored.", + "non-html-root": + "html needs to be the first start tag.", + "expected-doctype-but-got-eof": + "Unexpected End of file. Expected DOCTYPE.", + "unknown-doctype": + "Erroneous DOCTYPE.", + "expected-doctype-but-got-chars": + "Unexpected non-space characters. Expected DOCTYPE.", + "expected-doctype-but-got-start-tag": + "Unexpected start tag (%(name)s). Expected DOCTYPE.", + "expected-doctype-but-got-end-tag": + "Unexpected end tag (%(name)s). Expected DOCTYPE.", + "end-tag-after-implied-root": + "Unexpected end tag (%(name)s) after the (implied) root element.", + "expected-named-closing-tag-but-got-eof": + "Unexpected end of file. Expected end tag (%(name)s).", + "two-heads-are-not-better-than-one": + "Unexpected start tag head in existing head. Ignored.", + "unexpected-end-tag": + "Unexpected end tag (%(name)s). Ignored.", + "unexpected-start-tag-out-of-my-head": + "Unexpected start tag (%(name)s) that can be in head. Moved.", + "unexpected-start-tag": + "Unexpected start tag (%(name)s).", + "missing-end-tag": + "Missing end tag (%(name)s).", + "missing-end-tags": + "Missing end tags (%(name)s).", + "unexpected-start-tag-implies-end-tag": + "Unexpected start tag (%(startName)s) " + "implies end tag (%(endName)s).", + "unexpected-start-tag-treated-as": + "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", + "deprecated-tag": + "Unexpected start tag %(name)s. Don't use it!", + "unexpected-start-tag-ignored": + "Unexpected start tag %(name)s. Ignored.", + "expected-one-end-tag-but-got-another": + "Unexpected end tag (%(gotName)s). " + "Missing end tag (%(expectedName)s).", + "end-tag-too-early": + "End tag (%(name)s) seen too early. Expected other end tag.", + "end-tag-too-early-named": + "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", + "end-tag-too-early-ignored": + "End tag (%(name)s) seen too early. Ignored.", + "adoption-agency-1.1": + "End tag (%(name)s) violates step 1, " + "paragraph 1 of the adoption agency algorithm.", + "adoption-agency-1.2": + "End tag (%(name)s) violates step 1, " + "paragraph 2 of the adoption agency algorithm.", + "adoption-agency-1.3": + "End tag (%(name)s) violates step 1, " + "paragraph 3 of the adoption agency algorithm.", + "adoption-agency-4.4": + "End tag (%(name)s) violates step 4, " + "paragraph 4 of the adoption agency algorithm.", + "unexpected-end-tag-treated-as": + "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", + "no-end-tag": + "This element (%(name)s) has no end tag.", + "unexpected-implied-end-tag-in-table": + "Unexpected implied end tag (%(name)s) in the table phase.", + "unexpected-implied-end-tag-in-table-body": + "Unexpected implied end tag (%(name)s) in the table body phase.", + "unexpected-char-implies-table-voodoo": + "Unexpected non-space characters in " + "table context caused voodoo mode.", + "unexpected-hidden-input-in-table": + "Unexpected input with type hidden in table context.", + "unexpected-form-in-table": + "Unexpected form in table context.", + "unexpected-start-tag-implies-table-voodoo": + "Unexpected start tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-end-tag-implies-table-voodoo": + "Unexpected end tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-cell-in-table-body": + "Unexpected table cell start tag (%(name)s) " + "in the table body phase.", + "unexpected-cell-end-tag": + "Got table cell end tag (%(name)s) " + "while required end tags are missing.", + "unexpected-end-tag-in-table-body": + "Unexpected end tag (%(name)s) in the table body phase. Ignored.", + "unexpected-implied-end-tag-in-table-row": + "Unexpected implied end tag (%(name)s) in the table row phase.", + "unexpected-end-tag-in-table-row": + "Unexpected end tag (%(name)s) in the table row phase. Ignored.", + "unexpected-select-in-select": + "Unexpected select start tag in the select phase " + "treated as select end tag.", + "unexpected-input-in-select": + "Unexpected input start tag in the select phase.", + "unexpected-start-tag-in-select": + "Unexpected start tag token (%(name)s in the select phase. " + "Ignored.", + "unexpected-end-tag-in-select": + "Unexpected end tag (%(name)s) in the select phase. Ignored.", + "unexpected-table-element-start-tag-in-select-in-table": + "Unexpected table element start tag (%(name)s) in the select in table phase.", + "unexpected-table-element-end-tag-in-select-in-table": + "Unexpected table element end tag (%(name)s) in the select in table phase.", + "unexpected-char-after-body": + "Unexpected non-space characters in the after body phase.", + "unexpected-start-tag-after-body": + "Unexpected start tag token (%(name)s)" + " in the after body phase.", + "unexpected-end-tag-after-body": + "Unexpected end tag token (%(name)s)" + " in the after body phase.", + "unexpected-char-in-frameset": + "Unexpected characters in the frameset phase. Characters ignored.", + "unexpected-start-tag-in-frameset": + "Unexpected start tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-frameset-in-frameset-innerhtml": + "Unexpected end tag token (frameset) " + "in the frameset phase (innerHTML).", + "unexpected-end-tag-in-frameset": + "Unexpected end tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-char-after-frameset": + "Unexpected non-space characters in the " + "after frameset phase. Ignored.", + "unexpected-start-tag-after-frameset": + "Unexpected start tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-frameset": + "Unexpected end tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-body-innerhtml": + "Unexpected end tag after body(innerHtml)", + "expected-eof-but-got-char": + "Unexpected non-space characters. Expected end of file.", + "expected-eof-but-got-start-tag": + "Unexpected start tag (%(name)s)" + ". Expected end of file.", + "expected-eof-but-got-end-tag": + "Unexpected end tag (%(name)s)" + ". Expected end of file.", + "eof-in-table": + "Unexpected end of file. Expected table content.", + "eof-in-select": + "Unexpected end of file. Expected select content.", + "eof-in-frameset": + "Unexpected end of file. Expected frameset content.", + "eof-in-script-in-script": + "Unexpected end of file. Expected script content.", + "eof-in-foreign-lands": + "Unexpected end of file. Expected foreign content", + "non-void-element-with-trailing-solidus": + "Trailing solidus not allowed on element %(name)s", + "unexpected-html-element-in-foreign-content": + "Element %(name)s not allowed in a non-html context", + "unexpected-end-tag-before-html": + "Unexpected end tag (%(name)s) before html.", + "unexpected-inhead-noscript-tag": + "Element %(name)s not allowed in a inhead-noscript context", + "eof-in-head-noscript": + "Unexpected end of file. Expected inhead-noscript content", + "char-in-head-noscript": + "Unexpected non-space character. Expected inhead-noscript content", + "XXX-undefined-error": + "Undefined error (this sucks and should be fixed)", +} + +namespaces = { + "html": "http://www.w3.org/1999/xhtml", + "mathml": "http://www.w3.org/1998/Math/MathML", + "svg": "http://www.w3.org/2000/svg", + "xlink": "http://www.w3.org/1999/xlink", + "xml": "http://www.w3.org/XML/1998/namespace", + "xmlns": "http://www.w3.org/2000/xmlns/" +} + +scopingElements = frozenset([ + (namespaces["html"], "applet"), + (namespaces["html"], "caption"), + (namespaces["html"], "html"), + (namespaces["html"], "marquee"), + (namespaces["html"], "object"), + (namespaces["html"], "table"), + (namespaces["html"], "td"), + (namespaces["html"], "th"), + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext"), + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title"), +]) + +formattingElements = frozenset([ + (namespaces["html"], "a"), + (namespaces["html"], "b"), + (namespaces["html"], "big"), + (namespaces["html"], "code"), + (namespaces["html"], "em"), + (namespaces["html"], "font"), + (namespaces["html"], "i"), + (namespaces["html"], "nobr"), + (namespaces["html"], "s"), + (namespaces["html"], "small"), + (namespaces["html"], "strike"), + (namespaces["html"], "strong"), + (namespaces["html"], "tt"), + (namespaces["html"], "u") +]) + +specialElements = frozenset([ + (namespaces["html"], "address"), + (namespaces["html"], "applet"), + (namespaces["html"], "area"), + (namespaces["html"], "article"), + (namespaces["html"], "aside"), + (namespaces["html"], "base"), + (namespaces["html"], "basefont"), + (namespaces["html"], "bgsound"), + (namespaces["html"], "blockquote"), + (namespaces["html"], "body"), + (namespaces["html"], "br"), + (namespaces["html"], "button"), + (namespaces["html"], "caption"), + (namespaces["html"], "center"), + (namespaces["html"], "col"), + (namespaces["html"], "colgroup"), + (namespaces["html"], "command"), + (namespaces["html"], "dd"), + (namespaces["html"], "details"), + (namespaces["html"], "dir"), + (namespaces["html"], "div"), + (namespaces["html"], "dl"), + (namespaces["html"], "dt"), + (namespaces["html"], "embed"), + (namespaces["html"], "fieldset"), + (namespaces["html"], "figure"), + (namespaces["html"], "footer"), + (namespaces["html"], "form"), + (namespaces["html"], "frame"), + (namespaces["html"], "frameset"), + (namespaces["html"], "h1"), + (namespaces["html"], "h2"), + (namespaces["html"], "h3"), + (namespaces["html"], "h4"), + (namespaces["html"], "h5"), + (namespaces["html"], "h6"), + (namespaces["html"], "head"), + (namespaces["html"], "header"), + (namespaces["html"], "hr"), + (namespaces["html"], "html"), + (namespaces["html"], "iframe"), + # Note that image is commented out in the spec as "this isn't an + # element that can end up on the stack, so it doesn't matter," + (namespaces["html"], "image"), + (namespaces["html"], "img"), + (namespaces["html"], "input"), + (namespaces["html"], "isindex"), + (namespaces["html"], "li"), + (namespaces["html"], "link"), + (namespaces["html"], "listing"), + (namespaces["html"], "marquee"), + (namespaces["html"], "menu"), + (namespaces["html"], "meta"), + (namespaces["html"], "nav"), + (namespaces["html"], "noembed"), + (namespaces["html"], "noframes"), + (namespaces["html"], "noscript"), + (namespaces["html"], "object"), + (namespaces["html"], "ol"), + (namespaces["html"], "p"), + (namespaces["html"], "param"), + (namespaces["html"], "plaintext"), + (namespaces["html"], "pre"), + (namespaces["html"], "script"), + (namespaces["html"], "section"), + (namespaces["html"], "select"), + (namespaces["html"], "style"), + (namespaces["html"], "table"), + (namespaces["html"], "tbody"), + (namespaces["html"], "td"), + (namespaces["html"], "textarea"), + (namespaces["html"], "tfoot"), + (namespaces["html"], "th"), + (namespaces["html"], "thead"), + (namespaces["html"], "title"), + (namespaces["html"], "tr"), + (namespaces["html"], "ul"), + (namespaces["html"], "wbr"), + (namespaces["html"], "xmp"), + (namespaces["svg"], "foreignObject") +]) + +htmlIntegrationPointElements = frozenset([ + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title") +]) + +mathmlTextIntegrationPointElements = frozenset([ + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext") +]) + +adjustSVGAttributes = { + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "contentscripttype": "contentScriptType", + "contentstyletype": "contentStyleType", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "externalresourcesrequired": "externalResourcesRequired", + "filterres": "filterRes", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan" +} + +adjustMathMLAttributes = {"definitionurl": "definitionURL"} + +adjustForeignAttributes = { + "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), + "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), + "xlink:href": ("xlink", "href", namespaces["xlink"]), + "xlink:role": ("xlink", "role", namespaces["xlink"]), + "xlink:show": ("xlink", "show", namespaces["xlink"]), + "xlink:title": ("xlink", "title", namespaces["xlink"]), + "xlink:type": ("xlink", "type", namespaces["xlink"]), + "xml:base": ("xml", "base", namespaces["xml"]), + "xml:lang": ("xml", "lang", namespaces["xml"]), + "xml:space": ("xml", "space", namespaces["xml"]), + "xmlns": (None, "xmlns", namespaces["xmlns"]), + "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) +} + +unadjustForeignAttributes = dict([((ns, local), qname) for qname, (prefix, local, ns) in + adjustForeignAttributes.items()]) + +spaceCharacters = frozenset([ + "\t", + "\n", + "\u000C", + " ", + "\r" +]) + +tableInsertModeElements = frozenset([ + "table", + "tbody", + "tfoot", + "thead", + "tr" +]) + +asciiLowercase = frozenset(string.ascii_lowercase) +asciiUppercase = frozenset(string.ascii_uppercase) +asciiLetters = frozenset(string.ascii_letters) +digits = frozenset(string.digits) +hexDigits = frozenset(string.hexdigits) + +asciiUpper2Lower = dict([(ord(c), ord(c.lower())) + for c in string.ascii_uppercase]) + +# Heading elements need to be ordered +headingElements = ( + "h1", + "h2", + "h3", + "h4", + "h5", + "h6" +) + +voidElements = frozenset([ + "base", + "command", + "event-source", + "link", + "meta", + "hr", + "br", + "img", + "embed", + "param", + "area", + "col", + "input", + "source", + "track" +]) + +cdataElements = frozenset(['title', 'textarea']) + +rcdataElements = frozenset([ + 'style', + 'script', + 'xmp', + 'iframe', + 'noembed', + 'noframes', + 'noscript' +]) + +booleanAttributes = { + "": frozenset(["irrelevant", "itemscope"]), + "style": frozenset(["scoped"]), + "img": frozenset(["ismap"]), + "audio": frozenset(["autoplay", "controls"]), + "video": frozenset(["autoplay", "controls"]), + "script": frozenset(["defer", "async"]), + "details": frozenset(["open"]), + "datagrid": frozenset(["multiple", "disabled"]), + "command": frozenset(["hidden", "disabled", "checked", "default"]), + "hr": frozenset(["noshade"]), + "menu": frozenset(["autosubmit"]), + "fieldset": frozenset(["disabled", "readonly"]), + "option": frozenset(["disabled", "readonly", "selected"]), + "optgroup": frozenset(["disabled", "readonly"]), + "button": frozenset(["disabled", "autofocus"]), + "input": frozenset(["disabled", "readonly", "required", "autofocus", "checked", "ismap"]), + "select": frozenset(["disabled", "readonly", "autofocus", "multiple"]), + "output": frozenset(["disabled", "readonly"]), + "iframe": frozenset(["seamless"]), +} + +# entitiesWindows1252 has to be _ordered_ and needs to have an index. It +# therefore can't be a frozenset. +entitiesWindows1252 = ( + 8364, # 0x80 0x20AC EURO SIGN + 65533, # 0x81 UNDEFINED + 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK + 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK + 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK + 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS + 8224, # 0x86 0x2020 DAGGER + 8225, # 0x87 0x2021 DOUBLE DAGGER + 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT + 8240, # 0x89 0x2030 PER MILLE SIGN + 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON + 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE + 65533, # 0x8D UNDEFINED + 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON + 65533, # 0x8F UNDEFINED + 65533, # 0x90 UNDEFINED + 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK + 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK + 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK + 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK + 8226, # 0x95 0x2022 BULLET + 8211, # 0x96 0x2013 EN DASH + 8212, # 0x97 0x2014 EM DASH + 732, # 0x98 0x02DC SMALL TILDE + 8482, # 0x99 0x2122 TRADE MARK SIGN + 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON + 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE + 65533, # 0x9D UNDEFINED + 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON + 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS +) + +xmlEntities = frozenset(['lt;', 'gt;', 'amp;', 'apos;', 'quot;']) + +entities = { + "AElig": "\xc6", + "AElig;": "\xc6", + "AMP": "&", + "AMP;": "&", + "Aacute": "\xc1", + "Aacute;": "\xc1", + "Abreve;": "\u0102", + "Acirc": "\xc2", + "Acirc;": "\xc2", + "Acy;": "\u0410", + "Afr;": "\U0001d504", + "Agrave": "\xc0", + "Agrave;": "\xc0", + "Alpha;": "\u0391", + "Amacr;": "\u0100", + "And;": "\u2a53", + "Aogon;": "\u0104", + "Aopf;": "\U0001d538", + "ApplyFunction;": "\u2061", + "Aring": "\xc5", + "Aring;": "\xc5", + "Ascr;": "\U0001d49c", + "Assign;": "\u2254", + "Atilde": "\xc3", + "Atilde;": "\xc3", + "Auml": "\xc4", + "Auml;": "\xc4", + "Backslash;": "\u2216", + "Barv;": "\u2ae7", + "Barwed;": "\u2306", + "Bcy;": "\u0411", + "Because;": "\u2235", + "Bernoullis;": "\u212c", + "Beta;": "\u0392", + "Bfr;": "\U0001d505", + "Bopf;": "\U0001d539", + "Breve;": "\u02d8", + "Bscr;": "\u212c", + "Bumpeq;": "\u224e", + "CHcy;": "\u0427", + "COPY": "\xa9", + "COPY;": "\xa9", + "Cacute;": "\u0106", + "Cap;": "\u22d2", + "CapitalDifferentialD;": "\u2145", + "Cayleys;": "\u212d", + "Ccaron;": "\u010c", + "Ccedil": "\xc7", + "Ccedil;": "\xc7", + "Ccirc;": "\u0108", + "Cconint;": "\u2230", + "Cdot;": "\u010a", + "Cedilla;": "\xb8", + "CenterDot;": "\xb7", + "Cfr;": "\u212d", + "Chi;": "\u03a7", + "CircleDot;": "\u2299", + "CircleMinus;": "\u2296", + "CirclePlus;": "\u2295", + "CircleTimes;": "\u2297", + "ClockwiseContourIntegral;": "\u2232", + "CloseCurlyDoubleQuote;": "\u201d", + "CloseCurlyQuote;": "\u2019", + "Colon;": "\u2237", + "Colone;": "\u2a74", + "Congruent;": "\u2261", + "Conint;": "\u222f", + "ContourIntegral;": "\u222e", + "Copf;": "\u2102", + "Coproduct;": "\u2210", + "CounterClockwiseContourIntegral;": "\u2233", + "Cross;": "\u2a2f", + "Cscr;": "\U0001d49e", + "Cup;": "\u22d3", + "CupCap;": "\u224d", + "DD;": "\u2145", + "DDotrahd;": "\u2911", + "DJcy;": "\u0402", + "DScy;": "\u0405", + "DZcy;": "\u040f", + "Dagger;": "\u2021", + "Darr;": "\u21a1", + "Dashv;": "\u2ae4", + "Dcaron;": "\u010e", + "Dcy;": "\u0414", + "Del;": "\u2207", + "Delta;": "\u0394", + "Dfr;": "\U0001d507", + "DiacriticalAcute;": "\xb4", + "DiacriticalDot;": "\u02d9", + "DiacriticalDoubleAcute;": "\u02dd", + "DiacriticalGrave;": "`", + "DiacriticalTilde;": "\u02dc", + "Diamond;": "\u22c4", + "DifferentialD;": "\u2146", + "Dopf;": "\U0001d53b", + "Dot;": "\xa8", + "DotDot;": "\u20dc", + "DotEqual;": "\u2250", + "DoubleContourIntegral;": "\u222f", + "DoubleDot;": "\xa8", + "DoubleDownArrow;": "\u21d3", + "DoubleLeftArrow;": "\u21d0", + "DoubleLeftRightArrow;": "\u21d4", + "DoubleLeftTee;": "\u2ae4", + "DoubleLongLeftArrow;": "\u27f8", + "DoubleLongLeftRightArrow;": "\u27fa", + "DoubleLongRightArrow;": "\u27f9", + "DoubleRightArrow;": "\u21d2", + "DoubleRightTee;": "\u22a8", + "DoubleUpArrow;": "\u21d1", + "DoubleUpDownArrow;": "\u21d5", + "DoubleVerticalBar;": "\u2225", + "DownArrow;": "\u2193", + "DownArrowBar;": "\u2913", + "DownArrowUpArrow;": "\u21f5", + "DownBreve;": "\u0311", + "DownLeftRightVector;": "\u2950", + "DownLeftTeeVector;": "\u295e", + "DownLeftVector;": "\u21bd", + "DownLeftVectorBar;": "\u2956", + "DownRightTeeVector;": "\u295f", + "DownRightVector;": "\u21c1", + "DownRightVectorBar;": "\u2957", + "DownTee;": "\u22a4", + "DownTeeArrow;": "\u21a7", + "Downarrow;": "\u21d3", + "Dscr;": "\U0001d49f", + "Dstrok;": "\u0110", + "ENG;": "\u014a", + "ETH": "\xd0", + "ETH;": "\xd0", + "Eacute": "\xc9", + "Eacute;": "\xc9", + "Ecaron;": "\u011a", + "Ecirc": "\xca", + "Ecirc;": "\xca", + "Ecy;": "\u042d", + "Edot;": "\u0116", + "Efr;": "\U0001d508", + "Egrave": "\xc8", + "Egrave;": "\xc8", + "Element;": "\u2208", + "Emacr;": "\u0112", + "EmptySmallSquare;": "\u25fb", + "EmptyVerySmallSquare;": "\u25ab", + "Eogon;": "\u0118", + "Eopf;": "\U0001d53c", + "Epsilon;": "\u0395", + "Equal;": "\u2a75", + "EqualTilde;": "\u2242", + "Equilibrium;": "\u21cc", + "Escr;": "\u2130", + "Esim;": "\u2a73", + "Eta;": "\u0397", + "Euml": "\xcb", + "Euml;": "\xcb", + "Exists;": "\u2203", + "ExponentialE;": "\u2147", + "Fcy;": "\u0424", + "Ffr;": "\U0001d509", + "FilledSmallSquare;": "\u25fc", + "FilledVerySmallSquare;": "\u25aa", + "Fopf;": "\U0001d53d", + "ForAll;": "\u2200", + "Fouriertrf;": "\u2131", + "Fscr;": "\u2131", + "GJcy;": "\u0403", + "GT": ">", + "GT;": ">", + "Gamma;": "\u0393", + "Gammad;": "\u03dc", + "Gbreve;": "\u011e", + "Gcedil;": "\u0122", + "Gcirc;": "\u011c", + "Gcy;": "\u0413", + "Gdot;": "\u0120", + "Gfr;": "\U0001d50a", + "Gg;": "\u22d9", + "Gopf;": "\U0001d53e", + "GreaterEqual;": "\u2265", + "GreaterEqualLess;": "\u22db", + "GreaterFullEqual;": "\u2267", + "GreaterGreater;": "\u2aa2", + "GreaterLess;": "\u2277", + "GreaterSlantEqual;": "\u2a7e", + "GreaterTilde;": "\u2273", + "Gscr;": "\U0001d4a2", + "Gt;": "\u226b", + "HARDcy;": "\u042a", + "Hacek;": "\u02c7", + "Hat;": "^", + "Hcirc;": "\u0124", + "Hfr;": "\u210c", + "HilbertSpace;": "\u210b", + "Hopf;": "\u210d", + "HorizontalLine;": "\u2500", + "Hscr;": "\u210b", + "Hstrok;": "\u0126", + "HumpDownHump;": "\u224e", + "HumpEqual;": "\u224f", + "IEcy;": "\u0415", + "IJlig;": "\u0132", + "IOcy;": "\u0401", + "Iacute": "\xcd", + "Iacute;": "\xcd", + "Icirc": "\xce", + "Icirc;": "\xce", + "Icy;": "\u0418", + "Idot;": "\u0130", + "Ifr;": "\u2111", + "Igrave": "\xcc", + "Igrave;": "\xcc", + "Im;": "\u2111", + "Imacr;": "\u012a", + "ImaginaryI;": "\u2148", + "Implies;": "\u21d2", + "Int;": "\u222c", + "Integral;": "\u222b", + "Intersection;": "\u22c2", + "InvisibleComma;": "\u2063", + "InvisibleTimes;": "\u2062", + "Iogon;": "\u012e", + "Iopf;": "\U0001d540", + "Iota;": "\u0399", + "Iscr;": "\u2110", + "Itilde;": "\u0128", + "Iukcy;": "\u0406", + "Iuml": "\xcf", + "Iuml;": "\xcf", + "Jcirc;": "\u0134", + "Jcy;": "\u0419", + "Jfr;": "\U0001d50d", + "Jopf;": "\U0001d541", + "Jscr;": "\U0001d4a5", + "Jsercy;": "\u0408", + "Jukcy;": "\u0404", + "KHcy;": "\u0425", + "KJcy;": "\u040c", + "Kappa;": "\u039a", + "Kcedil;": "\u0136", + "Kcy;": "\u041a", + "Kfr;": "\U0001d50e", + "Kopf;": "\U0001d542", + "Kscr;": "\U0001d4a6", + "LJcy;": "\u0409", + "LT": "<", + "LT;": "<", + "Lacute;": "\u0139", + "Lambda;": "\u039b", + "Lang;": "\u27ea", + "Laplacetrf;": "\u2112", + "Larr;": "\u219e", + "Lcaron;": "\u013d", + "Lcedil;": "\u013b", + "Lcy;": "\u041b", + "LeftAngleBracket;": "\u27e8", + "LeftArrow;": "\u2190", + "LeftArrowBar;": "\u21e4", + "LeftArrowRightArrow;": "\u21c6", + "LeftCeiling;": "\u2308", + "LeftDoubleBracket;": "\u27e6", + "LeftDownTeeVector;": "\u2961", + "LeftDownVector;": "\u21c3", + "LeftDownVectorBar;": "\u2959", + "LeftFloor;": "\u230a", + "LeftRightArrow;": "\u2194", + "LeftRightVector;": "\u294e", + "LeftTee;": "\u22a3", + "LeftTeeArrow;": "\u21a4", + "LeftTeeVector;": "\u295a", + "LeftTriangle;": "\u22b2", + "LeftTriangleBar;": "\u29cf", + "LeftTriangleEqual;": "\u22b4", + "LeftUpDownVector;": "\u2951", + "LeftUpTeeVector;": "\u2960", + "LeftUpVector;": "\u21bf", + "LeftUpVectorBar;": "\u2958", + "LeftVector;": "\u21bc", + "LeftVectorBar;": "\u2952", + "Leftarrow;": "\u21d0", + "Leftrightarrow;": "\u21d4", + "LessEqualGreater;": "\u22da", + "LessFullEqual;": "\u2266", + "LessGreater;": "\u2276", + "LessLess;": "\u2aa1", + "LessSlantEqual;": "\u2a7d", + "LessTilde;": "\u2272", + "Lfr;": "\U0001d50f", + "Ll;": "\u22d8", + "Lleftarrow;": "\u21da", + "Lmidot;": "\u013f", + "LongLeftArrow;": "\u27f5", + "LongLeftRightArrow;": "\u27f7", + "LongRightArrow;": "\u27f6", + "Longleftarrow;": "\u27f8", + "Longleftrightarrow;": "\u27fa", + "Longrightarrow;": "\u27f9", + "Lopf;": "\U0001d543", + "LowerLeftArrow;": "\u2199", + "LowerRightArrow;": "\u2198", + "Lscr;": "\u2112", + "Lsh;": "\u21b0", + "Lstrok;": "\u0141", + "Lt;": "\u226a", + "Map;": "\u2905", + "Mcy;": "\u041c", + "MediumSpace;": "\u205f", + "Mellintrf;": "\u2133", + "Mfr;": "\U0001d510", + "MinusPlus;": "\u2213", + "Mopf;": "\U0001d544", + "Mscr;": "\u2133", + "Mu;": "\u039c", + "NJcy;": "\u040a", + "Nacute;": "\u0143", + "Ncaron;": "\u0147", + "Ncedil;": "\u0145", + "Ncy;": "\u041d", + "NegativeMediumSpace;": "\u200b", + "NegativeThickSpace;": "\u200b", + "NegativeThinSpace;": "\u200b", + "NegativeVeryThinSpace;": "\u200b", + "NestedGreaterGreater;": "\u226b", + "NestedLessLess;": "\u226a", + "NewLine;": "\n", + "Nfr;": "\U0001d511", + "NoBreak;": "\u2060", + "NonBreakingSpace;": "\xa0", + "Nopf;": "\u2115", + "Not;": "\u2aec", + "NotCongruent;": "\u2262", + "NotCupCap;": "\u226d", + "NotDoubleVerticalBar;": "\u2226", + "NotElement;": "\u2209", + "NotEqual;": "\u2260", + "NotEqualTilde;": "\u2242\u0338", + "NotExists;": "\u2204", + "NotGreater;": "\u226f", + "NotGreaterEqual;": "\u2271", + "NotGreaterFullEqual;": "\u2267\u0338", + "NotGreaterGreater;": "\u226b\u0338", + "NotGreaterLess;": "\u2279", + "NotGreaterSlantEqual;": "\u2a7e\u0338", + "NotGreaterTilde;": "\u2275", + "NotHumpDownHump;": "\u224e\u0338", + "NotHumpEqual;": "\u224f\u0338", + "NotLeftTriangle;": "\u22ea", + "NotLeftTriangleBar;": "\u29cf\u0338", + "NotLeftTriangleEqual;": "\u22ec", + "NotLess;": "\u226e", + "NotLessEqual;": "\u2270", + "NotLessGreater;": "\u2278", + "NotLessLess;": "\u226a\u0338", + "NotLessSlantEqual;": "\u2a7d\u0338", + "NotLessTilde;": "\u2274", + "NotNestedGreaterGreater;": "\u2aa2\u0338", + "NotNestedLessLess;": "\u2aa1\u0338", + "NotPrecedes;": "\u2280", + "NotPrecedesEqual;": "\u2aaf\u0338", + "NotPrecedesSlantEqual;": "\u22e0", + "NotReverseElement;": "\u220c", + "NotRightTriangle;": "\u22eb", + "NotRightTriangleBar;": "\u29d0\u0338", + "NotRightTriangleEqual;": "\u22ed", + "NotSquareSubset;": "\u228f\u0338", + "NotSquareSubsetEqual;": "\u22e2", + "NotSquareSuperset;": "\u2290\u0338", + "NotSquareSupersetEqual;": "\u22e3", + "NotSubset;": "\u2282\u20d2", + "NotSubsetEqual;": "\u2288", + "NotSucceeds;": "\u2281", + "NotSucceedsEqual;": "\u2ab0\u0338", + "NotSucceedsSlantEqual;": "\u22e1", + "NotSucceedsTilde;": "\u227f\u0338", + "NotSuperset;": "\u2283\u20d2", + "NotSupersetEqual;": "\u2289", + "NotTilde;": "\u2241", + "NotTildeEqual;": "\u2244", + "NotTildeFullEqual;": "\u2247", + "NotTildeTilde;": "\u2249", + "NotVerticalBar;": "\u2224", + "Nscr;": "\U0001d4a9", + "Ntilde": "\xd1", + "Ntilde;": "\xd1", + "Nu;": "\u039d", + "OElig;": "\u0152", + "Oacute": "\xd3", + "Oacute;": "\xd3", + "Ocirc": "\xd4", + "Ocirc;": "\xd4", + "Ocy;": "\u041e", + "Odblac;": "\u0150", + "Ofr;": "\U0001d512", + "Ograve": "\xd2", + "Ograve;": "\xd2", + "Omacr;": "\u014c", + "Omega;": "\u03a9", + "Omicron;": "\u039f", + "Oopf;": "\U0001d546", + "OpenCurlyDoubleQuote;": "\u201c", + "OpenCurlyQuote;": "\u2018", + "Or;": "\u2a54", + "Oscr;": "\U0001d4aa", + "Oslash": "\xd8", + "Oslash;": "\xd8", + "Otilde": "\xd5", + "Otilde;": "\xd5", + "Otimes;": "\u2a37", + "Ouml": "\xd6", + "Ouml;": "\xd6", + "OverBar;": "\u203e", + "OverBrace;": "\u23de", + "OverBracket;": "\u23b4", + "OverParenthesis;": "\u23dc", + "PartialD;": "\u2202", + "Pcy;": "\u041f", + "Pfr;": "\U0001d513", + "Phi;": "\u03a6", + "Pi;": "\u03a0", + "PlusMinus;": "\xb1", + "Poincareplane;": "\u210c", + "Popf;": "\u2119", + "Pr;": "\u2abb", + "Precedes;": "\u227a", + "PrecedesEqual;": "\u2aaf", + "PrecedesSlantEqual;": "\u227c", + "PrecedesTilde;": "\u227e", + "Prime;": "\u2033", + "Product;": "\u220f", + "Proportion;": "\u2237", + "Proportional;": "\u221d", + "Pscr;": "\U0001d4ab", + "Psi;": "\u03a8", + "QUOT": "\"", + "QUOT;": "\"", + "Qfr;": "\U0001d514", + "Qopf;": "\u211a", + "Qscr;": "\U0001d4ac", + "RBarr;": "\u2910", + "REG": "\xae", + "REG;": "\xae", + "Racute;": "\u0154", + "Rang;": "\u27eb", + "Rarr;": "\u21a0", + "Rarrtl;": "\u2916", + "Rcaron;": "\u0158", + "Rcedil;": "\u0156", + "Rcy;": "\u0420", + "Re;": "\u211c", + "ReverseElement;": "\u220b", + "ReverseEquilibrium;": "\u21cb", + "ReverseUpEquilibrium;": "\u296f", + "Rfr;": "\u211c", + "Rho;": "\u03a1", + "RightAngleBracket;": "\u27e9", + "RightArrow;": "\u2192", + "RightArrowBar;": "\u21e5", + "RightArrowLeftArrow;": "\u21c4", + "RightCeiling;": "\u2309", + "RightDoubleBracket;": "\u27e7", + "RightDownTeeVector;": "\u295d", + "RightDownVector;": "\u21c2", + "RightDownVectorBar;": "\u2955", + "RightFloor;": "\u230b", + "RightTee;": "\u22a2", + "RightTeeArrow;": "\u21a6", + "RightTeeVector;": "\u295b", + "RightTriangle;": "\u22b3", + "RightTriangleBar;": "\u29d0", + "RightTriangleEqual;": "\u22b5", + "RightUpDownVector;": "\u294f", + "RightUpTeeVector;": "\u295c", + "RightUpVector;": "\u21be", + "RightUpVectorBar;": "\u2954", + "RightVector;": "\u21c0", + "RightVectorBar;": "\u2953", + "Rightarrow;": "\u21d2", + "Ropf;": "\u211d", + "RoundImplies;": "\u2970", + "Rrightarrow;": "\u21db", + "Rscr;": "\u211b", + "Rsh;": "\u21b1", + "RuleDelayed;": "\u29f4", + "SHCHcy;": "\u0429", + "SHcy;": "\u0428", + "SOFTcy;": "\u042c", + "Sacute;": "\u015a", + "Sc;": "\u2abc", + "Scaron;": "\u0160", + "Scedil;": "\u015e", + "Scirc;": "\u015c", + "Scy;": "\u0421", + "Sfr;": "\U0001d516", + "ShortDownArrow;": "\u2193", + "ShortLeftArrow;": "\u2190", + "ShortRightArrow;": "\u2192", + "ShortUpArrow;": "\u2191", + "Sigma;": "\u03a3", + "SmallCircle;": "\u2218", + "Sopf;": "\U0001d54a", + "Sqrt;": "\u221a", + "Square;": "\u25a1", + "SquareIntersection;": "\u2293", + "SquareSubset;": "\u228f", + "SquareSubsetEqual;": "\u2291", + "SquareSuperset;": "\u2290", + "SquareSupersetEqual;": "\u2292", + "SquareUnion;": "\u2294", + "Sscr;": "\U0001d4ae", + "Star;": "\u22c6", + "Sub;": "\u22d0", + "Subset;": "\u22d0", + "SubsetEqual;": "\u2286", + "Succeeds;": "\u227b", + "SucceedsEqual;": "\u2ab0", + "SucceedsSlantEqual;": "\u227d", + "SucceedsTilde;": "\u227f", + "SuchThat;": "\u220b", + "Sum;": "\u2211", + "Sup;": "\u22d1", + "Superset;": "\u2283", + "SupersetEqual;": "\u2287", + "Supset;": "\u22d1", + "THORN": "\xde", + "THORN;": "\xde", + "TRADE;": "\u2122", + "TSHcy;": "\u040b", + "TScy;": "\u0426", + "Tab;": "\t", + "Tau;": "\u03a4", + "Tcaron;": "\u0164", + "Tcedil;": "\u0162", + "Tcy;": "\u0422", + "Tfr;": "\U0001d517", + "Therefore;": "\u2234", + "Theta;": "\u0398", + "ThickSpace;": "\u205f\u200a", + "ThinSpace;": "\u2009", + "Tilde;": "\u223c", + "TildeEqual;": "\u2243", + "TildeFullEqual;": "\u2245", + "TildeTilde;": "\u2248", + "Topf;": "\U0001d54b", + "TripleDot;": "\u20db", + "Tscr;": "\U0001d4af", + "Tstrok;": "\u0166", + "Uacute": "\xda", + "Uacute;": "\xda", + "Uarr;": "\u219f", + "Uarrocir;": "\u2949", + "Ubrcy;": "\u040e", + "Ubreve;": "\u016c", + "Ucirc": "\xdb", + "Ucirc;": "\xdb", + "Ucy;": "\u0423", + "Udblac;": "\u0170", + "Ufr;": "\U0001d518", + "Ugrave": "\xd9", + "Ugrave;": "\xd9", + "Umacr;": "\u016a", + "UnderBar;": "_", + "UnderBrace;": "\u23df", + "UnderBracket;": "\u23b5", + "UnderParenthesis;": "\u23dd", + "Union;": "\u22c3", + "UnionPlus;": "\u228e", + "Uogon;": "\u0172", + "Uopf;": "\U0001d54c", + "UpArrow;": "\u2191", + "UpArrowBar;": "\u2912", + "UpArrowDownArrow;": "\u21c5", + "UpDownArrow;": "\u2195", + "UpEquilibrium;": "\u296e", + "UpTee;": "\u22a5", + "UpTeeArrow;": "\u21a5", + "Uparrow;": "\u21d1", + "Updownarrow;": "\u21d5", + "UpperLeftArrow;": "\u2196", + "UpperRightArrow;": "\u2197", + "Upsi;": "\u03d2", + "Upsilon;": "\u03a5", + "Uring;": "\u016e", + "Uscr;": "\U0001d4b0", + "Utilde;": "\u0168", + "Uuml": "\xdc", + "Uuml;": "\xdc", + "VDash;": "\u22ab", + "Vbar;": "\u2aeb", + "Vcy;": "\u0412", + "Vdash;": "\u22a9", + "Vdashl;": "\u2ae6", + "Vee;": "\u22c1", + "Verbar;": "\u2016", + "Vert;": "\u2016", + "VerticalBar;": "\u2223", + "VerticalLine;": "|", + "VerticalSeparator;": "\u2758", + "VerticalTilde;": "\u2240", + "VeryThinSpace;": "\u200a", + "Vfr;": "\U0001d519", + "Vopf;": "\U0001d54d", + "Vscr;": "\U0001d4b1", + "Vvdash;": "\u22aa", + "Wcirc;": "\u0174", + "Wedge;": "\u22c0", + "Wfr;": "\U0001d51a", + "Wopf;": "\U0001d54e", + "Wscr;": "\U0001d4b2", + "Xfr;": "\U0001d51b", + "Xi;": "\u039e", + "Xopf;": "\U0001d54f", + "Xscr;": "\U0001d4b3", + "YAcy;": "\u042f", + "YIcy;": "\u0407", + "YUcy;": "\u042e", + "Yacute": "\xdd", + "Yacute;": "\xdd", + "Ycirc;": "\u0176", + "Ycy;": "\u042b", + "Yfr;": "\U0001d51c", + "Yopf;": "\U0001d550", + "Yscr;": "\U0001d4b4", + "Yuml;": "\u0178", + "ZHcy;": "\u0416", + "Zacute;": "\u0179", + "Zcaron;": "\u017d", + "Zcy;": "\u0417", + "Zdot;": "\u017b", + "ZeroWidthSpace;": "\u200b", + "Zeta;": "\u0396", + "Zfr;": "\u2128", + "Zopf;": "\u2124", + "Zscr;": "\U0001d4b5", + "aacute": "\xe1", + "aacute;": "\xe1", + "abreve;": "\u0103", + "ac;": "\u223e", + "acE;": "\u223e\u0333", + "acd;": "\u223f", + "acirc": "\xe2", + "acirc;": "\xe2", + "acute": "\xb4", + "acute;": "\xb4", + "acy;": "\u0430", + "aelig": "\xe6", + "aelig;": "\xe6", + "af;": "\u2061", + "afr;": "\U0001d51e", + "agrave": "\xe0", + "agrave;": "\xe0", + "alefsym;": "\u2135", + "aleph;": "\u2135", + "alpha;": "\u03b1", + "amacr;": "\u0101", + "amalg;": "\u2a3f", + "amp": "&", + "amp;": "&", + "and;": "\u2227", + "andand;": "\u2a55", + "andd;": "\u2a5c", + "andslope;": "\u2a58", + "andv;": "\u2a5a", + "ang;": "\u2220", + "ange;": "\u29a4", + "angle;": "\u2220", + "angmsd;": "\u2221", + "angmsdaa;": "\u29a8", + "angmsdab;": "\u29a9", + "angmsdac;": "\u29aa", + "angmsdad;": "\u29ab", + "angmsdae;": "\u29ac", + "angmsdaf;": "\u29ad", + "angmsdag;": "\u29ae", + "angmsdah;": "\u29af", + "angrt;": "\u221f", + "angrtvb;": "\u22be", + "angrtvbd;": "\u299d", + "angsph;": "\u2222", + "angst;": "\xc5", + "angzarr;": "\u237c", + "aogon;": "\u0105", + "aopf;": "\U0001d552", + "ap;": "\u2248", + "apE;": "\u2a70", + "apacir;": "\u2a6f", + "ape;": "\u224a", + "apid;": "\u224b", + "apos;": "'", + "approx;": "\u2248", + "approxeq;": "\u224a", + "aring": "\xe5", + "aring;": "\xe5", + "ascr;": "\U0001d4b6", + "ast;": "*", + "asymp;": "\u2248", + "asympeq;": "\u224d", + "atilde": "\xe3", + "atilde;": "\xe3", + "auml": "\xe4", + "auml;": "\xe4", + "awconint;": "\u2233", + "awint;": "\u2a11", + "bNot;": "\u2aed", + "backcong;": "\u224c", + "backepsilon;": "\u03f6", + "backprime;": "\u2035", + "backsim;": "\u223d", + "backsimeq;": "\u22cd", + "barvee;": "\u22bd", + "barwed;": "\u2305", + "barwedge;": "\u2305", + "bbrk;": "\u23b5", + "bbrktbrk;": "\u23b6", + "bcong;": "\u224c", + "bcy;": "\u0431", + "bdquo;": "\u201e", + "becaus;": "\u2235", + "because;": "\u2235", + "bemptyv;": "\u29b0", + "bepsi;": "\u03f6", + "bernou;": "\u212c", + "beta;": "\u03b2", + "beth;": "\u2136", + "between;": "\u226c", + "bfr;": "\U0001d51f", + "bigcap;": "\u22c2", + "bigcirc;": "\u25ef", + "bigcup;": "\u22c3", + "bigodot;": "\u2a00", + "bigoplus;": "\u2a01", + "bigotimes;": "\u2a02", + "bigsqcup;": "\u2a06", + "bigstar;": "\u2605", + "bigtriangledown;": "\u25bd", + "bigtriangleup;": "\u25b3", + "biguplus;": "\u2a04", + "bigvee;": "\u22c1", + "bigwedge;": "\u22c0", + "bkarow;": "\u290d", + "blacklozenge;": "\u29eb", + "blacksquare;": "\u25aa", + "blacktriangle;": "\u25b4", + "blacktriangledown;": "\u25be", + "blacktriangleleft;": "\u25c2", + "blacktriangleright;": "\u25b8", + "blank;": "\u2423", + "blk12;": "\u2592", + "blk14;": "\u2591", + "blk34;": "\u2593", + "block;": "\u2588", + "bne;": "=\u20e5", + "bnequiv;": "\u2261\u20e5", + "bnot;": "\u2310", + "bopf;": "\U0001d553", + "bot;": "\u22a5", + "bottom;": "\u22a5", + "bowtie;": "\u22c8", + "boxDL;": "\u2557", + "boxDR;": "\u2554", + "boxDl;": "\u2556", + "boxDr;": "\u2553", + "boxH;": "\u2550", + "boxHD;": "\u2566", + "boxHU;": "\u2569", + "boxHd;": "\u2564", + "boxHu;": "\u2567", + "boxUL;": "\u255d", + "boxUR;": "\u255a", + "boxUl;": "\u255c", + "boxUr;": "\u2559", + "boxV;": "\u2551", + "boxVH;": "\u256c", + "boxVL;": "\u2563", + "boxVR;": "\u2560", + "boxVh;": "\u256b", + "boxVl;": "\u2562", + "boxVr;": "\u255f", + "boxbox;": "\u29c9", + "boxdL;": "\u2555", + "boxdR;": "\u2552", + "boxdl;": "\u2510", + "boxdr;": "\u250c", + "boxh;": "\u2500", + "boxhD;": "\u2565", + "boxhU;": "\u2568", + "boxhd;": "\u252c", + "boxhu;": "\u2534", + "boxminus;": "\u229f", + "boxplus;": "\u229e", + "boxtimes;": "\u22a0", + "boxuL;": "\u255b", + "boxuR;": "\u2558", + "boxul;": "\u2518", + "boxur;": "\u2514", + "boxv;": "\u2502", + "boxvH;": "\u256a", + "boxvL;": "\u2561", + "boxvR;": "\u255e", + "boxvh;": "\u253c", + "boxvl;": "\u2524", + "boxvr;": "\u251c", + "bprime;": "\u2035", + "breve;": "\u02d8", + "brvbar": "\xa6", + "brvbar;": "\xa6", + "bscr;": "\U0001d4b7", + "bsemi;": "\u204f", + "bsim;": "\u223d", + "bsime;": "\u22cd", + "bsol;": "\\", + "bsolb;": "\u29c5", + "bsolhsub;": "\u27c8", + "bull;": "\u2022", + "bullet;": "\u2022", + "bump;": "\u224e", + "bumpE;": "\u2aae", + "bumpe;": "\u224f", + "bumpeq;": "\u224f", + "cacute;": "\u0107", + "cap;": "\u2229", + "capand;": "\u2a44", + "capbrcup;": "\u2a49", + "capcap;": "\u2a4b", + "capcup;": "\u2a47", + "capdot;": "\u2a40", + "caps;": "\u2229\ufe00", + "caret;": "\u2041", + "caron;": "\u02c7", + "ccaps;": "\u2a4d", + "ccaron;": "\u010d", + "ccedil": "\xe7", + "ccedil;": "\xe7", + "ccirc;": "\u0109", + "ccups;": "\u2a4c", + "ccupssm;": "\u2a50", + "cdot;": "\u010b", + "cedil": "\xb8", + "cedil;": "\xb8", + "cemptyv;": "\u29b2", + "cent": "\xa2", + "cent;": "\xa2", + "centerdot;": "\xb7", + "cfr;": "\U0001d520", + "chcy;": "\u0447", + "check;": "\u2713", + "checkmark;": "\u2713", + "chi;": "\u03c7", + "cir;": "\u25cb", + "cirE;": "\u29c3", + "circ;": "\u02c6", + "circeq;": "\u2257", + "circlearrowleft;": "\u21ba", + "circlearrowright;": "\u21bb", + "circledR;": "\xae", + "circledS;": "\u24c8", + "circledast;": "\u229b", + "circledcirc;": "\u229a", + "circleddash;": "\u229d", + "cire;": "\u2257", + "cirfnint;": "\u2a10", + "cirmid;": "\u2aef", + "cirscir;": "\u29c2", + "clubs;": "\u2663", + "clubsuit;": "\u2663", + "colon;": ":", + "colone;": "\u2254", + "coloneq;": "\u2254", + "comma;": ",", + "commat;": "@", + "comp;": "\u2201", + "compfn;": "\u2218", + "complement;": "\u2201", + "complexes;": "\u2102", + "cong;": "\u2245", + "congdot;": "\u2a6d", + "conint;": "\u222e", + "copf;": "\U0001d554", + "coprod;": "\u2210", + "copy": "\xa9", + "copy;": "\xa9", + "copysr;": "\u2117", + "crarr;": "\u21b5", + "cross;": "\u2717", + "cscr;": "\U0001d4b8", + "csub;": "\u2acf", + "csube;": "\u2ad1", + "csup;": "\u2ad0", + "csupe;": "\u2ad2", + "ctdot;": "\u22ef", + "cudarrl;": "\u2938", + "cudarrr;": "\u2935", + "cuepr;": "\u22de", + "cuesc;": "\u22df", + "cularr;": "\u21b6", + "cularrp;": "\u293d", + "cup;": "\u222a", + "cupbrcap;": "\u2a48", + "cupcap;": "\u2a46", + "cupcup;": "\u2a4a", + "cupdot;": "\u228d", + "cupor;": "\u2a45", + "cups;": "\u222a\ufe00", + "curarr;": "\u21b7", + "curarrm;": "\u293c", + "curlyeqprec;": "\u22de", + "curlyeqsucc;": "\u22df", + "curlyvee;": "\u22ce", + "curlywedge;": "\u22cf", + "curren": "\xa4", + "curren;": "\xa4", + "curvearrowleft;": "\u21b6", + "curvearrowright;": "\u21b7", + "cuvee;": "\u22ce", + "cuwed;": "\u22cf", + "cwconint;": "\u2232", + "cwint;": "\u2231", + "cylcty;": "\u232d", + "dArr;": "\u21d3", + "dHar;": "\u2965", + "dagger;": "\u2020", + "daleth;": "\u2138", + "darr;": "\u2193", + "dash;": "\u2010", + "dashv;": "\u22a3", + "dbkarow;": "\u290f", + "dblac;": "\u02dd", + "dcaron;": "\u010f", + "dcy;": "\u0434", + "dd;": "\u2146", + "ddagger;": "\u2021", + "ddarr;": "\u21ca", + "ddotseq;": "\u2a77", + "deg": "\xb0", + "deg;": "\xb0", + "delta;": "\u03b4", + "demptyv;": "\u29b1", + "dfisht;": "\u297f", + "dfr;": "\U0001d521", + "dharl;": "\u21c3", + "dharr;": "\u21c2", + "diam;": "\u22c4", + "diamond;": "\u22c4", + "diamondsuit;": "\u2666", + "diams;": "\u2666", + "die;": "\xa8", + "digamma;": "\u03dd", + "disin;": "\u22f2", + "div;": "\xf7", + "divide": "\xf7", + "divide;": "\xf7", + "divideontimes;": "\u22c7", + "divonx;": "\u22c7", + "djcy;": "\u0452", + "dlcorn;": "\u231e", + "dlcrop;": "\u230d", + "dollar;": "$", + "dopf;": "\U0001d555", + "dot;": "\u02d9", + "doteq;": "\u2250", + "doteqdot;": "\u2251", + "dotminus;": "\u2238", + "dotplus;": "\u2214", + "dotsquare;": "\u22a1", + "doublebarwedge;": "\u2306", + "downarrow;": "\u2193", + "downdownarrows;": "\u21ca", + "downharpoonleft;": "\u21c3", + "downharpoonright;": "\u21c2", + "drbkarow;": "\u2910", + "drcorn;": "\u231f", + "drcrop;": "\u230c", + "dscr;": "\U0001d4b9", + "dscy;": "\u0455", + "dsol;": "\u29f6", + "dstrok;": "\u0111", + "dtdot;": "\u22f1", + "dtri;": "\u25bf", + "dtrif;": "\u25be", + "duarr;": "\u21f5", + "duhar;": "\u296f", + "dwangle;": "\u29a6", + "dzcy;": "\u045f", + "dzigrarr;": "\u27ff", + "eDDot;": "\u2a77", + "eDot;": "\u2251", + "eacute": "\xe9", + "eacute;": "\xe9", + "easter;": "\u2a6e", + "ecaron;": "\u011b", + "ecir;": "\u2256", + "ecirc": "\xea", + "ecirc;": "\xea", + "ecolon;": "\u2255", + "ecy;": "\u044d", + "edot;": "\u0117", + "ee;": "\u2147", + "efDot;": "\u2252", + "efr;": "\U0001d522", + "eg;": "\u2a9a", + "egrave": "\xe8", + "egrave;": "\xe8", + "egs;": "\u2a96", + "egsdot;": "\u2a98", + "el;": "\u2a99", + "elinters;": "\u23e7", + "ell;": "\u2113", + "els;": "\u2a95", + "elsdot;": "\u2a97", + "emacr;": "\u0113", + "empty;": "\u2205", + "emptyset;": "\u2205", + "emptyv;": "\u2205", + "emsp13;": "\u2004", + "emsp14;": "\u2005", + "emsp;": "\u2003", + "eng;": "\u014b", + "ensp;": "\u2002", + "eogon;": "\u0119", + "eopf;": "\U0001d556", + "epar;": "\u22d5", + "eparsl;": "\u29e3", + "eplus;": "\u2a71", + "epsi;": "\u03b5", + "epsilon;": "\u03b5", + "epsiv;": "\u03f5", + "eqcirc;": "\u2256", + "eqcolon;": "\u2255", + "eqsim;": "\u2242", + "eqslantgtr;": "\u2a96", + "eqslantless;": "\u2a95", + "equals;": "=", + "equest;": "\u225f", + "equiv;": "\u2261", + "equivDD;": "\u2a78", + "eqvparsl;": "\u29e5", + "erDot;": "\u2253", + "erarr;": "\u2971", + "escr;": "\u212f", + "esdot;": "\u2250", + "esim;": "\u2242", + "eta;": "\u03b7", + "eth": "\xf0", + "eth;": "\xf0", + "euml": "\xeb", + "euml;": "\xeb", + "euro;": "\u20ac", + "excl;": "!", + "exist;": "\u2203", + "expectation;": "\u2130", + "exponentiale;": "\u2147", + "fallingdotseq;": "\u2252", + "fcy;": "\u0444", + "female;": "\u2640", + "ffilig;": "\ufb03", + "fflig;": "\ufb00", + "ffllig;": "\ufb04", + "ffr;": "\U0001d523", + "filig;": "\ufb01", + "fjlig;": "fj", + "flat;": "\u266d", + "fllig;": "\ufb02", + "fltns;": "\u25b1", + "fnof;": "\u0192", + "fopf;": "\U0001d557", + "forall;": "\u2200", + "fork;": "\u22d4", + "forkv;": "\u2ad9", + "fpartint;": "\u2a0d", + "frac12": "\xbd", + "frac12;": "\xbd", + "frac13;": "\u2153", + "frac14": "\xbc", + "frac14;": "\xbc", + "frac15;": "\u2155", + "frac16;": "\u2159", + "frac18;": "\u215b", + "frac23;": "\u2154", + "frac25;": "\u2156", + "frac34": "\xbe", + "frac34;": "\xbe", + "frac35;": "\u2157", + "frac38;": "\u215c", + "frac45;": "\u2158", + "frac56;": "\u215a", + "frac58;": "\u215d", + "frac78;": "\u215e", + "frasl;": "\u2044", + "frown;": "\u2322", + "fscr;": "\U0001d4bb", + "gE;": "\u2267", + "gEl;": "\u2a8c", + "gacute;": "\u01f5", + "gamma;": "\u03b3", + "gammad;": "\u03dd", + "gap;": "\u2a86", + "gbreve;": "\u011f", + "gcirc;": "\u011d", + "gcy;": "\u0433", + "gdot;": "\u0121", + "ge;": "\u2265", + "gel;": "\u22db", + "geq;": "\u2265", + "geqq;": "\u2267", + "geqslant;": "\u2a7e", + "ges;": "\u2a7e", + "gescc;": "\u2aa9", + "gesdot;": "\u2a80", + "gesdoto;": "\u2a82", + "gesdotol;": "\u2a84", + "gesl;": "\u22db\ufe00", + "gesles;": "\u2a94", + "gfr;": "\U0001d524", + "gg;": "\u226b", + "ggg;": "\u22d9", + "gimel;": "\u2137", + "gjcy;": "\u0453", + "gl;": "\u2277", + "glE;": "\u2a92", + "gla;": "\u2aa5", + "glj;": "\u2aa4", + "gnE;": "\u2269", + "gnap;": "\u2a8a", + "gnapprox;": "\u2a8a", + "gne;": "\u2a88", + "gneq;": "\u2a88", + "gneqq;": "\u2269", + "gnsim;": "\u22e7", + "gopf;": "\U0001d558", + "grave;": "`", + "gscr;": "\u210a", + "gsim;": "\u2273", + "gsime;": "\u2a8e", + "gsiml;": "\u2a90", + "gt": ">", + "gt;": ">", + "gtcc;": "\u2aa7", + "gtcir;": "\u2a7a", + "gtdot;": "\u22d7", + "gtlPar;": "\u2995", + "gtquest;": "\u2a7c", + "gtrapprox;": "\u2a86", + "gtrarr;": "\u2978", + "gtrdot;": "\u22d7", + "gtreqless;": "\u22db", + "gtreqqless;": "\u2a8c", + "gtrless;": "\u2277", + "gtrsim;": "\u2273", + "gvertneqq;": "\u2269\ufe00", + "gvnE;": "\u2269\ufe00", + "hArr;": "\u21d4", + "hairsp;": "\u200a", + "half;": "\xbd", + "hamilt;": "\u210b", + "hardcy;": "\u044a", + "harr;": "\u2194", + "harrcir;": "\u2948", + "harrw;": "\u21ad", + "hbar;": "\u210f", + "hcirc;": "\u0125", + "hearts;": "\u2665", + "heartsuit;": "\u2665", + "hellip;": "\u2026", + "hercon;": "\u22b9", + "hfr;": "\U0001d525", + "hksearow;": "\u2925", + "hkswarow;": "\u2926", + "hoarr;": "\u21ff", + "homtht;": "\u223b", + "hookleftarrow;": "\u21a9", + "hookrightarrow;": "\u21aa", + "hopf;": "\U0001d559", + "horbar;": "\u2015", + "hscr;": "\U0001d4bd", + "hslash;": "\u210f", + "hstrok;": "\u0127", + "hybull;": "\u2043", + "hyphen;": "\u2010", + "iacute": "\xed", + "iacute;": "\xed", + "ic;": "\u2063", + "icirc": "\xee", + "icirc;": "\xee", + "icy;": "\u0438", + "iecy;": "\u0435", + "iexcl": "\xa1", + "iexcl;": "\xa1", + "iff;": "\u21d4", + "ifr;": "\U0001d526", + "igrave": "\xec", + "igrave;": "\xec", + "ii;": "\u2148", + "iiiint;": "\u2a0c", + "iiint;": "\u222d", + "iinfin;": "\u29dc", + "iiota;": "\u2129", + "ijlig;": "\u0133", + "imacr;": "\u012b", + "image;": "\u2111", + "imagline;": "\u2110", + "imagpart;": "\u2111", + "imath;": "\u0131", + "imof;": "\u22b7", + "imped;": "\u01b5", + "in;": "\u2208", + "incare;": "\u2105", + "infin;": "\u221e", + "infintie;": "\u29dd", + "inodot;": "\u0131", + "int;": "\u222b", + "intcal;": "\u22ba", + "integers;": "\u2124", + "intercal;": "\u22ba", + "intlarhk;": "\u2a17", + "intprod;": "\u2a3c", + "iocy;": "\u0451", + "iogon;": "\u012f", + "iopf;": "\U0001d55a", + "iota;": "\u03b9", + "iprod;": "\u2a3c", + "iquest": "\xbf", + "iquest;": "\xbf", + "iscr;": "\U0001d4be", + "isin;": "\u2208", + "isinE;": "\u22f9", + "isindot;": "\u22f5", + "isins;": "\u22f4", + "isinsv;": "\u22f3", + "isinv;": "\u2208", + "it;": "\u2062", + "itilde;": "\u0129", + "iukcy;": "\u0456", + "iuml": "\xef", + "iuml;": "\xef", + "jcirc;": "\u0135", + "jcy;": "\u0439", + "jfr;": "\U0001d527", + "jmath;": "\u0237", + "jopf;": "\U0001d55b", + "jscr;": "\U0001d4bf", + "jsercy;": "\u0458", + "jukcy;": "\u0454", + "kappa;": "\u03ba", + "kappav;": "\u03f0", + "kcedil;": "\u0137", + "kcy;": "\u043a", + "kfr;": "\U0001d528", + "kgreen;": "\u0138", + "khcy;": "\u0445", + "kjcy;": "\u045c", + "kopf;": "\U0001d55c", + "kscr;": "\U0001d4c0", + "lAarr;": "\u21da", + "lArr;": "\u21d0", + "lAtail;": "\u291b", + "lBarr;": "\u290e", + "lE;": "\u2266", + "lEg;": "\u2a8b", + "lHar;": "\u2962", + "lacute;": "\u013a", + "laemptyv;": "\u29b4", + "lagran;": "\u2112", + "lambda;": "\u03bb", + "lang;": "\u27e8", + "langd;": "\u2991", + "langle;": "\u27e8", + "lap;": "\u2a85", + "laquo": "\xab", + "laquo;": "\xab", + "larr;": "\u2190", + "larrb;": "\u21e4", + "larrbfs;": "\u291f", + "larrfs;": "\u291d", + "larrhk;": "\u21a9", + "larrlp;": "\u21ab", + "larrpl;": "\u2939", + "larrsim;": "\u2973", + "larrtl;": "\u21a2", + "lat;": "\u2aab", + "latail;": "\u2919", + "late;": "\u2aad", + "lates;": "\u2aad\ufe00", + "lbarr;": "\u290c", + "lbbrk;": "\u2772", + "lbrace;": "{", + "lbrack;": "[", + "lbrke;": "\u298b", + "lbrksld;": "\u298f", + "lbrkslu;": "\u298d", + "lcaron;": "\u013e", + "lcedil;": "\u013c", + "lceil;": "\u2308", + "lcub;": "{", + "lcy;": "\u043b", + "ldca;": "\u2936", + "ldquo;": "\u201c", + "ldquor;": "\u201e", + "ldrdhar;": "\u2967", + "ldrushar;": "\u294b", + "ldsh;": "\u21b2", + "le;": "\u2264", + "leftarrow;": "\u2190", + "leftarrowtail;": "\u21a2", + "leftharpoondown;": "\u21bd", + "leftharpoonup;": "\u21bc", + "leftleftarrows;": "\u21c7", + "leftrightarrow;": "\u2194", + "leftrightarrows;": "\u21c6", + "leftrightharpoons;": "\u21cb", + "leftrightsquigarrow;": "\u21ad", + "leftthreetimes;": "\u22cb", + "leg;": "\u22da", + "leq;": "\u2264", + "leqq;": "\u2266", + "leqslant;": "\u2a7d", + "les;": "\u2a7d", + "lescc;": "\u2aa8", + "lesdot;": "\u2a7f", + "lesdoto;": "\u2a81", + "lesdotor;": "\u2a83", + "lesg;": "\u22da\ufe00", + "lesges;": "\u2a93", + "lessapprox;": "\u2a85", + "lessdot;": "\u22d6", + "lesseqgtr;": "\u22da", + "lesseqqgtr;": "\u2a8b", + "lessgtr;": "\u2276", + "lesssim;": "\u2272", + "lfisht;": "\u297c", + "lfloor;": "\u230a", + "lfr;": "\U0001d529", + "lg;": "\u2276", + "lgE;": "\u2a91", + "lhard;": "\u21bd", + "lharu;": "\u21bc", + "lharul;": "\u296a", + "lhblk;": "\u2584", + "ljcy;": "\u0459", + "ll;": "\u226a", + "llarr;": "\u21c7", + "llcorner;": "\u231e", + "llhard;": "\u296b", + "lltri;": "\u25fa", + "lmidot;": "\u0140", + "lmoust;": "\u23b0", + "lmoustache;": "\u23b0", + "lnE;": "\u2268", + "lnap;": "\u2a89", + "lnapprox;": "\u2a89", + "lne;": "\u2a87", + "lneq;": "\u2a87", + "lneqq;": "\u2268", + "lnsim;": "\u22e6", + "loang;": "\u27ec", + "loarr;": "\u21fd", + "lobrk;": "\u27e6", + "longleftarrow;": "\u27f5", + "longleftrightarrow;": "\u27f7", + "longmapsto;": "\u27fc", + "longrightarrow;": "\u27f6", + "looparrowleft;": "\u21ab", + "looparrowright;": "\u21ac", + "lopar;": "\u2985", + "lopf;": "\U0001d55d", + "loplus;": "\u2a2d", + "lotimes;": "\u2a34", + "lowast;": "\u2217", + "lowbar;": "_", + "loz;": "\u25ca", + "lozenge;": "\u25ca", + "lozf;": "\u29eb", + "lpar;": "(", + "lparlt;": "\u2993", + "lrarr;": "\u21c6", + "lrcorner;": "\u231f", + "lrhar;": "\u21cb", + "lrhard;": "\u296d", + "lrm;": "\u200e", + "lrtri;": "\u22bf", + "lsaquo;": "\u2039", + "lscr;": "\U0001d4c1", + "lsh;": "\u21b0", + "lsim;": "\u2272", + "lsime;": "\u2a8d", + "lsimg;": "\u2a8f", + "lsqb;": "[", + "lsquo;": "\u2018", + "lsquor;": "\u201a", + "lstrok;": "\u0142", + "lt": "<", + "lt;": "<", + "ltcc;": "\u2aa6", + "ltcir;": "\u2a79", + "ltdot;": "\u22d6", + "lthree;": "\u22cb", + "ltimes;": "\u22c9", + "ltlarr;": "\u2976", + "ltquest;": "\u2a7b", + "ltrPar;": "\u2996", + "ltri;": "\u25c3", + "ltrie;": "\u22b4", + "ltrif;": "\u25c2", + "lurdshar;": "\u294a", + "luruhar;": "\u2966", + "lvertneqq;": "\u2268\ufe00", + "lvnE;": "\u2268\ufe00", + "mDDot;": "\u223a", + "macr": "\xaf", + "macr;": "\xaf", + "male;": "\u2642", + "malt;": "\u2720", + "maltese;": "\u2720", + "map;": "\u21a6", + "mapsto;": "\u21a6", + "mapstodown;": "\u21a7", + "mapstoleft;": "\u21a4", + "mapstoup;": "\u21a5", + "marker;": "\u25ae", + "mcomma;": "\u2a29", + "mcy;": "\u043c", + "mdash;": "\u2014", + "measuredangle;": "\u2221", + "mfr;": "\U0001d52a", + "mho;": "\u2127", + "micro": "\xb5", + "micro;": "\xb5", + "mid;": "\u2223", + "midast;": "*", + "midcir;": "\u2af0", + "middot": "\xb7", + "middot;": "\xb7", + "minus;": "\u2212", + "minusb;": "\u229f", + "minusd;": "\u2238", + "minusdu;": "\u2a2a", + "mlcp;": "\u2adb", + "mldr;": "\u2026", + "mnplus;": "\u2213", + "models;": "\u22a7", + "mopf;": "\U0001d55e", + "mp;": "\u2213", + "mscr;": "\U0001d4c2", + "mstpos;": "\u223e", + "mu;": "\u03bc", + "multimap;": "\u22b8", + "mumap;": "\u22b8", + "nGg;": "\u22d9\u0338", + "nGt;": "\u226b\u20d2", + "nGtv;": "\u226b\u0338", + "nLeftarrow;": "\u21cd", + "nLeftrightarrow;": "\u21ce", + "nLl;": "\u22d8\u0338", + "nLt;": "\u226a\u20d2", + "nLtv;": "\u226a\u0338", + "nRightarrow;": "\u21cf", + "nVDash;": "\u22af", + "nVdash;": "\u22ae", + "nabla;": "\u2207", + "nacute;": "\u0144", + "nang;": "\u2220\u20d2", + "nap;": "\u2249", + "napE;": "\u2a70\u0338", + "napid;": "\u224b\u0338", + "napos;": "\u0149", + "napprox;": "\u2249", + "natur;": "\u266e", + "natural;": "\u266e", + "naturals;": "\u2115", + "nbsp": "\xa0", + "nbsp;": "\xa0", + "nbump;": "\u224e\u0338", + "nbumpe;": "\u224f\u0338", + "ncap;": "\u2a43", + "ncaron;": "\u0148", + "ncedil;": "\u0146", + "ncong;": "\u2247", + "ncongdot;": "\u2a6d\u0338", + "ncup;": "\u2a42", + "ncy;": "\u043d", + "ndash;": "\u2013", + "ne;": "\u2260", + "neArr;": "\u21d7", + "nearhk;": "\u2924", + "nearr;": "\u2197", + "nearrow;": "\u2197", + "nedot;": "\u2250\u0338", + "nequiv;": "\u2262", + "nesear;": "\u2928", + "nesim;": "\u2242\u0338", + "nexist;": "\u2204", + "nexists;": "\u2204", + "nfr;": "\U0001d52b", + "ngE;": "\u2267\u0338", + "nge;": "\u2271", + "ngeq;": "\u2271", + "ngeqq;": "\u2267\u0338", + "ngeqslant;": "\u2a7e\u0338", + "nges;": "\u2a7e\u0338", + "ngsim;": "\u2275", + "ngt;": "\u226f", + "ngtr;": "\u226f", + "nhArr;": "\u21ce", + "nharr;": "\u21ae", + "nhpar;": "\u2af2", + "ni;": "\u220b", + "nis;": "\u22fc", + "nisd;": "\u22fa", + "niv;": "\u220b", + "njcy;": "\u045a", + "nlArr;": "\u21cd", + "nlE;": "\u2266\u0338", + "nlarr;": "\u219a", + "nldr;": "\u2025", + "nle;": "\u2270", + "nleftarrow;": "\u219a", + "nleftrightarrow;": "\u21ae", + "nleq;": "\u2270", + "nleqq;": "\u2266\u0338", + "nleqslant;": "\u2a7d\u0338", + "nles;": "\u2a7d\u0338", + "nless;": "\u226e", + "nlsim;": "\u2274", + "nlt;": "\u226e", + "nltri;": "\u22ea", + "nltrie;": "\u22ec", + "nmid;": "\u2224", + "nopf;": "\U0001d55f", + "not": "\xac", + "not;": "\xac", + "notin;": "\u2209", + "notinE;": "\u22f9\u0338", + "notindot;": "\u22f5\u0338", + "notinva;": "\u2209", + "notinvb;": "\u22f7", + "notinvc;": "\u22f6", + "notni;": "\u220c", + "notniva;": "\u220c", + "notnivb;": "\u22fe", + "notnivc;": "\u22fd", + "npar;": "\u2226", + "nparallel;": "\u2226", + "nparsl;": "\u2afd\u20e5", + "npart;": "\u2202\u0338", + "npolint;": "\u2a14", + "npr;": "\u2280", + "nprcue;": "\u22e0", + "npre;": "\u2aaf\u0338", + "nprec;": "\u2280", + "npreceq;": "\u2aaf\u0338", + "nrArr;": "\u21cf", + "nrarr;": "\u219b", + "nrarrc;": "\u2933\u0338", + "nrarrw;": "\u219d\u0338", + "nrightarrow;": "\u219b", + "nrtri;": "\u22eb", + "nrtrie;": "\u22ed", + "nsc;": "\u2281", + "nsccue;": "\u22e1", + "nsce;": "\u2ab0\u0338", + "nscr;": "\U0001d4c3", + "nshortmid;": "\u2224", + "nshortparallel;": "\u2226", + "nsim;": "\u2241", + "nsime;": "\u2244", + "nsimeq;": "\u2244", + "nsmid;": "\u2224", + "nspar;": "\u2226", + "nsqsube;": "\u22e2", + "nsqsupe;": "\u22e3", + "nsub;": "\u2284", + "nsubE;": "\u2ac5\u0338", + "nsube;": "\u2288", + "nsubset;": "\u2282\u20d2", + "nsubseteq;": "\u2288", + "nsubseteqq;": "\u2ac5\u0338", + "nsucc;": "\u2281", + "nsucceq;": "\u2ab0\u0338", + "nsup;": "\u2285", + "nsupE;": "\u2ac6\u0338", + "nsupe;": "\u2289", + "nsupset;": "\u2283\u20d2", + "nsupseteq;": "\u2289", + "nsupseteqq;": "\u2ac6\u0338", + "ntgl;": "\u2279", + "ntilde": "\xf1", + "ntilde;": "\xf1", + "ntlg;": "\u2278", + "ntriangleleft;": "\u22ea", + "ntrianglelefteq;": "\u22ec", + "ntriangleright;": "\u22eb", + "ntrianglerighteq;": "\u22ed", + "nu;": "\u03bd", + "num;": "#", + "numero;": "\u2116", + "numsp;": "\u2007", + "nvDash;": "\u22ad", + "nvHarr;": "\u2904", + "nvap;": "\u224d\u20d2", + "nvdash;": "\u22ac", + "nvge;": "\u2265\u20d2", + "nvgt;": ">\u20d2", + "nvinfin;": "\u29de", + "nvlArr;": "\u2902", + "nvle;": "\u2264\u20d2", + "nvlt;": "<\u20d2", + "nvltrie;": "\u22b4\u20d2", + "nvrArr;": "\u2903", + "nvrtrie;": "\u22b5\u20d2", + "nvsim;": "\u223c\u20d2", + "nwArr;": "\u21d6", + "nwarhk;": "\u2923", + "nwarr;": "\u2196", + "nwarrow;": "\u2196", + "nwnear;": "\u2927", + "oS;": "\u24c8", + "oacute": "\xf3", + "oacute;": "\xf3", + "oast;": "\u229b", + "ocir;": "\u229a", + "ocirc": "\xf4", + "ocirc;": "\xf4", + "ocy;": "\u043e", + "odash;": "\u229d", + "odblac;": "\u0151", + "odiv;": "\u2a38", + "odot;": "\u2299", + "odsold;": "\u29bc", + "oelig;": "\u0153", + "ofcir;": "\u29bf", + "ofr;": "\U0001d52c", + "ogon;": "\u02db", + "ograve": "\xf2", + "ograve;": "\xf2", + "ogt;": "\u29c1", + "ohbar;": "\u29b5", + "ohm;": "\u03a9", + "oint;": "\u222e", + "olarr;": "\u21ba", + "olcir;": "\u29be", + "olcross;": "\u29bb", + "oline;": "\u203e", + "olt;": "\u29c0", + "omacr;": "\u014d", + "omega;": "\u03c9", + "omicron;": "\u03bf", + "omid;": "\u29b6", + "ominus;": "\u2296", + "oopf;": "\U0001d560", + "opar;": "\u29b7", + "operp;": "\u29b9", + "oplus;": "\u2295", + "or;": "\u2228", + "orarr;": "\u21bb", + "ord;": "\u2a5d", + "order;": "\u2134", + "orderof;": "\u2134", + "ordf": "\xaa", + "ordf;": "\xaa", + "ordm": "\xba", + "ordm;": "\xba", + "origof;": "\u22b6", + "oror;": "\u2a56", + "orslope;": "\u2a57", + "orv;": "\u2a5b", + "oscr;": "\u2134", + "oslash": "\xf8", + "oslash;": "\xf8", + "osol;": "\u2298", + "otilde": "\xf5", + "otilde;": "\xf5", + "otimes;": "\u2297", + "otimesas;": "\u2a36", + "ouml": "\xf6", + "ouml;": "\xf6", + "ovbar;": "\u233d", + "par;": "\u2225", + "para": "\xb6", + "para;": "\xb6", + "parallel;": "\u2225", + "parsim;": "\u2af3", + "parsl;": "\u2afd", + "part;": "\u2202", + "pcy;": "\u043f", + "percnt;": "%", + "period;": ".", + "permil;": "\u2030", + "perp;": "\u22a5", + "pertenk;": "\u2031", + "pfr;": "\U0001d52d", + "phi;": "\u03c6", + "phiv;": "\u03d5", + "phmmat;": "\u2133", + "phone;": "\u260e", + "pi;": "\u03c0", + "pitchfork;": "\u22d4", + "piv;": "\u03d6", + "planck;": "\u210f", + "planckh;": "\u210e", + "plankv;": "\u210f", + "plus;": "+", + "plusacir;": "\u2a23", + "plusb;": "\u229e", + "pluscir;": "\u2a22", + "plusdo;": "\u2214", + "plusdu;": "\u2a25", + "pluse;": "\u2a72", + "plusmn": "\xb1", + "plusmn;": "\xb1", + "plussim;": "\u2a26", + "plustwo;": "\u2a27", + "pm;": "\xb1", + "pointint;": "\u2a15", + "popf;": "\U0001d561", + "pound": "\xa3", + "pound;": "\xa3", + "pr;": "\u227a", + "prE;": "\u2ab3", + "prap;": "\u2ab7", + "prcue;": "\u227c", + "pre;": "\u2aaf", + "prec;": "\u227a", + "precapprox;": "\u2ab7", + "preccurlyeq;": "\u227c", + "preceq;": "\u2aaf", + "precnapprox;": "\u2ab9", + "precneqq;": "\u2ab5", + "precnsim;": "\u22e8", + "precsim;": "\u227e", + "prime;": "\u2032", + "primes;": "\u2119", + "prnE;": "\u2ab5", + "prnap;": "\u2ab9", + "prnsim;": "\u22e8", + "prod;": "\u220f", + "profalar;": "\u232e", + "profline;": "\u2312", + "profsurf;": "\u2313", + "prop;": "\u221d", + "propto;": "\u221d", + "prsim;": "\u227e", + "prurel;": "\u22b0", + "pscr;": "\U0001d4c5", + "psi;": "\u03c8", + "puncsp;": "\u2008", + "qfr;": "\U0001d52e", + "qint;": "\u2a0c", + "qopf;": "\U0001d562", + "qprime;": "\u2057", + "qscr;": "\U0001d4c6", + "quaternions;": "\u210d", + "quatint;": "\u2a16", + "quest;": "?", + "questeq;": "\u225f", + "quot": "\"", + "quot;": "\"", + "rAarr;": "\u21db", + "rArr;": "\u21d2", + "rAtail;": "\u291c", + "rBarr;": "\u290f", + "rHar;": "\u2964", + "race;": "\u223d\u0331", + "racute;": "\u0155", + "radic;": "\u221a", + "raemptyv;": "\u29b3", + "rang;": "\u27e9", + "rangd;": "\u2992", + "range;": "\u29a5", + "rangle;": "\u27e9", + "raquo": "\xbb", + "raquo;": "\xbb", + "rarr;": "\u2192", + "rarrap;": "\u2975", + "rarrb;": "\u21e5", + "rarrbfs;": "\u2920", + "rarrc;": "\u2933", + "rarrfs;": "\u291e", + "rarrhk;": "\u21aa", + "rarrlp;": "\u21ac", + "rarrpl;": "\u2945", + "rarrsim;": "\u2974", + "rarrtl;": "\u21a3", + "rarrw;": "\u219d", + "ratail;": "\u291a", + "ratio;": "\u2236", + "rationals;": "\u211a", + "rbarr;": "\u290d", + "rbbrk;": "\u2773", + "rbrace;": "}", + "rbrack;": "]", + "rbrke;": "\u298c", + "rbrksld;": "\u298e", + "rbrkslu;": "\u2990", + "rcaron;": "\u0159", + "rcedil;": "\u0157", + "rceil;": "\u2309", + "rcub;": "}", + "rcy;": "\u0440", + "rdca;": "\u2937", + "rdldhar;": "\u2969", + "rdquo;": "\u201d", + "rdquor;": "\u201d", + "rdsh;": "\u21b3", + "real;": "\u211c", + "realine;": "\u211b", + "realpart;": "\u211c", + "reals;": "\u211d", + "rect;": "\u25ad", + "reg": "\xae", + "reg;": "\xae", + "rfisht;": "\u297d", + "rfloor;": "\u230b", + "rfr;": "\U0001d52f", + "rhard;": "\u21c1", + "rharu;": "\u21c0", + "rharul;": "\u296c", + "rho;": "\u03c1", + "rhov;": "\u03f1", + "rightarrow;": "\u2192", + "rightarrowtail;": "\u21a3", + "rightharpoondown;": "\u21c1", + "rightharpoonup;": "\u21c0", + "rightleftarrows;": "\u21c4", + "rightleftharpoons;": "\u21cc", + "rightrightarrows;": "\u21c9", + "rightsquigarrow;": "\u219d", + "rightthreetimes;": "\u22cc", + "ring;": "\u02da", + "risingdotseq;": "\u2253", + "rlarr;": "\u21c4", + "rlhar;": "\u21cc", + "rlm;": "\u200f", + "rmoust;": "\u23b1", + "rmoustache;": "\u23b1", + "rnmid;": "\u2aee", + "roang;": "\u27ed", + "roarr;": "\u21fe", + "robrk;": "\u27e7", + "ropar;": "\u2986", + "ropf;": "\U0001d563", + "roplus;": "\u2a2e", + "rotimes;": "\u2a35", + "rpar;": ")", + "rpargt;": "\u2994", + "rppolint;": "\u2a12", + "rrarr;": "\u21c9", + "rsaquo;": "\u203a", + "rscr;": "\U0001d4c7", + "rsh;": "\u21b1", + "rsqb;": "]", + "rsquo;": "\u2019", + "rsquor;": "\u2019", + "rthree;": "\u22cc", + "rtimes;": "\u22ca", + "rtri;": "\u25b9", + "rtrie;": "\u22b5", + "rtrif;": "\u25b8", + "rtriltri;": "\u29ce", + "ruluhar;": "\u2968", + "rx;": "\u211e", + "sacute;": "\u015b", + "sbquo;": "\u201a", + "sc;": "\u227b", + "scE;": "\u2ab4", + "scap;": "\u2ab8", + "scaron;": "\u0161", + "sccue;": "\u227d", + "sce;": "\u2ab0", + "scedil;": "\u015f", + "scirc;": "\u015d", + "scnE;": "\u2ab6", + "scnap;": "\u2aba", + "scnsim;": "\u22e9", + "scpolint;": "\u2a13", + "scsim;": "\u227f", + "scy;": "\u0441", + "sdot;": "\u22c5", + "sdotb;": "\u22a1", + "sdote;": "\u2a66", + "seArr;": "\u21d8", + "searhk;": "\u2925", + "searr;": "\u2198", + "searrow;": "\u2198", + "sect": "\xa7", + "sect;": "\xa7", + "semi;": ";", + "seswar;": "\u2929", + "setminus;": "\u2216", + "setmn;": "\u2216", + "sext;": "\u2736", + "sfr;": "\U0001d530", + "sfrown;": "\u2322", + "sharp;": "\u266f", + "shchcy;": "\u0449", + "shcy;": "\u0448", + "shortmid;": "\u2223", + "shortparallel;": "\u2225", + "shy": "\xad", + "shy;": "\xad", + "sigma;": "\u03c3", + "sigmaf;": "\u03c2", + "sigmav;": "\u03c2", + "sim;": "\u223c", + "simdot;": "\u2a6a", + "sime;": "\u2243", + "simeq;": "\u2243", + "simg;": "\u2a9e", + "simgE;": "\u2aa0", + "siml;": "\u2a9d", + "simlE;": "\u2a9f", + "simne;": "\u2246", + "simplus;": "\u2a24", + "simrarr;": "\u2972", + "slarr;": "\u2190", + "smallsetminus;": "\u2216", + "smashp;": "\u2a33", + "smeparsl;": "\u29e4", + "smid;": "\u2223", + "smile;": "\u2323", + "smt;": "\u2aaa", + "smte;": "\u2aac", + "smtes;": "\u2aac\ufe00", + "softcy;": "\u044c", + "sol;": "/", + "solb;": "\u29c4", + "solbar;": "\u233f", + "sopf;": "\U0001d564", + "spades;": "\u2660", + "spadesuit;": "\u2660", + "spar;": "\u2225", + "sqcap;": "\u2293", + "sqcaps;": "\u2293\ufe00", + "sqcup;": "\u2294", + "sqcups;": "\u2294\ufe00", + "sqsub;": "\u228f", + "sqsube;": "\u2291", + "sqsubset;": "\u228f", + "sqsubseteq;": "\u2291", + "sqsup;": "\u2290", + "sqsupe;": "\u2292", + "sqsupset;": "\u2290", + "sqsupseteq;": "\u2292", + "squ;": "\u25a1", + "square;": "\u25a1", + "squarf;": "\u25aa", + "squf;": "\u25aa", + "srarr;": "\u2192", + "sscr;": "\U0001d4c8", + "ssetmn;": "\u2216", + "ssmile;": "\u2323", + "sstarf;": "\u22c6", + "star;": "\u2606", + "starf;": "\u2605", + "straightepsilon;": "\u03f5", + "straightphi;": "\u03d5", + "strns;": "\xaf", + "sub;": "\u2282", + "subE;": "\u2ac5", + "subdot;": "\u2abd", + "sube;": "\u2286", + "subedot;": "\u2ac3", + "submult;": "\u2ac1", + "subnE;": "\u2acb", + "subne;": "\u228a", + "subplus;": "\u2abf", + "subrarr;": "\u2979", + "subset;": "\u2282", + "subseteq;": "\u2286", + "subseteqq;": "\u2ac5", + "subsetneq;": "\u228a", + "subsetneqq;": "\u2acb", + "subsim;": "\u2ac7", + "subsub;": "\u2ad5", + "subsup;": "\u2ad3", + "succ;": "\u227b", + "succapprox;": "\u2ab8", + "succcurlyeq;": "\u227d", + "succeq;": "\u2ab0", + "succnapprox;": "\u2aba", + "succneqq;": "\u2ab6", + "succnsim;": "\u22e9", + "succsim;": "\u227f", + "sum;": "\u2211", + "sung;": "\u266a", + "sup1": "\xb9", + "sup1;": "\xb9", + "sup2": "\xb2", + "sup2;": "\xb2", + "sup3": "\xb3", + "sup3;": "\xb3", + "sup;": "\u2283", + "supE;": "\u2ac6", + "supdot;": "\u2abe", + "supdsub;": "\u2ad8", + "supe;": "\u2287", + "supedot;": "\u2ac4", + "suphsol;": "\u27c9", + "suphsub;": "\u2ad7", + "suplarr;": "\u297b", + "supmult;": "\u2ac2", + "supnE;": "\u2acc", + "supne;": "\u228b", + "supplus;": "\u2ac0", + "supset;": "\u2283", + "supseteq;": "\u2287", + "supseteqq;": "\u2ac6", + "supsetneq;": "\u228b", + "supsetneqq;": "\u2acc", + "supsim;": "\u2ac8", + "supsub;": "\u2ad4", + "supsup;": "\u2ad6", + "swArr;": "\u21d9", + "swarhk;": "\u2926", + "swarr;": "\u2199", + "swarrow;": "\u2199", + "swnwar;": "\u292a", + "szlig": "\xdf", + "szlig;": "\xdf", + "target;": "\u2316", + "tau;": "\u03c4", + "tbrk;": "\u23b4", + "tcaron;": "\u0165", + "tcedil;": "\u0163", + "tcy;": "\u0442", + "tdot;": "\u20db", + "telrec;": "\u2315", + "tfr;": "\U0001d531", + "there4;": "\u2234", + "therefore;": "\u2234", + "theta;": "\u03b8", + "thetasym;": "\u03d1", + "thetav;": "\u03d1", + "thickapprox;": "\u2248", + "thicksim;": "\u223c", + "thinsp;": "\u2009", + "thkap;": "\u2248", + "thksim;": "\u223c", + "thorn": "\xfe", + "thorn;": "\xfe", + "tilde;": "\u02dc", + "times": "\xd7", + "times;": "\xd7", + "timesb;": "\u22a0", + "timesbar;": "\u2a31", + "timesd;": "\u2a30", + "tint;": "\u222d", + "toea;": "\u2928", + "top;": "\u22a4", + "topbot;": "\u2336", + "topcir;": "\u2af1", + "topf;": "\U0001d565", + "topfork;": "\u2ada", + "tosa;": "\u2929", + "tprime;": "\u2034", + "trade;": "\u2122", + "triangle;": "\u25b5", + "triangledown;": "\u25bf", + "triangleleft;": "\u25c3", + "trianglelefteq;": "\u22b4", + "triangleq;": "\u225c", + "triangleright;": "\u25b9", + "trianglerighteq;": "\u22b5", + "tridot;": "\u25ec", + "trie;": "\u225c", + "triminus;": "\u2a3a", + "triplus;": "\u2a39", + "trisb;": "\u29cd", + "tritime;": "\u2a3b", + "trpezium;": "\u23e2", + "tscr;": "\U0001d4c9", + "tscy;": "\u0446", + "tshcy;": "\u045b", + "tstrok;": "\u0167", + "twixt;": "\u226c", + "twoheadleftarrow;": "\u219e", + "twoheadrightarrow;": "\u21a0", + "uArr;": "\u21d1", + "uHar;": "\u2963", + "uacute": "\xfa", + "uacute;": "\xfa", + "uarr;": "\u2191", + "ubrcy;": "\u045e", + "ubreve;": "\u016d", + "ucirc": "\xfb", + "ucirc;": "\xfb", + "ucy;": "\u0443", + "udarr;": "\u21c5", + "udblac;": "\u0171", + "udhar;": "\u296e", + "ufisht;": "\u297e", + "ufr;": "\U0001d532", + "ugrave": "\xf9", + "ugrave;": "\xf9", + "uharl;": "\u21bf", + "uharr;": "\u21be", + "uhblk;": "\u2580", + "ulcorn;": "\u231c", + "ulcorner;": "\u231c", + "ulcrop;": "\u230f", + "ultri;": "\u25f8", + "umacr;": "\u016b", + "uml": "\xa8", + "uml;": "\xa8", + "uogon;": "\u0173", + "uopf;": "\U0001d566", + "uparrow;": "\u2191", + "updownarrow;": "\u2195", + "upharpoonleft;": "\u21bf", + "upharpoonright;": "\u21be", + "uplus;": "\u228e", + "upsi;": "\u03c5", + "upsih;": "\u03d2", + "upsilon;": "\u03c5", + "upuparrows;": "\u21c8", + "urcorn;": "\u231d", + "urcorner;": "\u231d", + "urcrop;": "\u230e", + "uring;": "\u016f", + "urtri;": "\u25f9", + "uscr;": "\U0001d4ca", + "utdot;": "\u22f0", + "utilde;": "\u0169", + "utri;": "\u25b5", + "utrif;": "\u25b4", + "uuarr;": "\u21c8", + "uuml": "\xfc", + "uuml;": "\xfc", + "uwangle;": "\u29a7", + "vArr;": "\u21d5", + "vBar;": "\u2ae8", + "vBarv;": "\u2ae9", + "vDash;": "\u22a8", + "vangrt;": "\u299c", + "varepsilon;": "\u03f5", + "varkappa;": "\u03f0", + "varnothing;": "\u2205", + "varphi;": "\u03d5", + "varpi;": "\u03d6", + "varpropto;": "\u221d", + "varr;": "\u2195", + "varrho;": "\u03f1", + "varsigma;": "\u03c2", + "varsubsetneq;": "\u228a\ufe00", + "varsubsetneqq;": "\u2acb\ufe00", + "varsupsetneq;": "\u228b\ufe00", + "varsupsetneqq;": "\u2acc\ufe00", + "vartheta;": "\u03d1", + "vartriangleleft;": "\u22b2", + "vartriangleright;": "\u22b3", + "vcy;": "\u0432", + "vdash;": "\u22a2", + "vee;": "\u2228", + "veebar;": "\u22bb", + "veeeq;": "\u225a", + "vellip;": "\u22ee", + "verbar;": "|", + "vert;": "|", + "vfr;": "\U0001d533", + "vltri;": "\u22b2", + "vnsub;": "\u2282\u20d2", + "vnsup;": "\u2283\u20d2", + "vopf;": "\U0001d567", + "vprop;": "\u221d", + "vrtri;": "\u22b3", + "vscr;": "\U0001d4cb", + "vsubnE;": "\u2acb\ufe00", + "vsubne;": "\u228a\ufe00", + "vsupnE;": "\u2acc\ufe00", + "vsupne;": "\u228b\ufe00", + "vzigzag;": "\u299a", + "wcirc;": "\u0175", + "wedbar;": "\u2a5f", + "wedge;": "\u2227", + "wedgeq;": "\u2259", + "weierp;": "\u2118", + "wfr;": "\U0001d534", + "wopf;": "\U0001d568", + "wp;": "\u2118", + "wr;": "\u2240", + "wreath;": "\u2240", + "wscr;": "\U0001d4cc", + "xcap;": "\u22c2", + "xcirc;": "\u25ef", + "xcup;": "\u22c3", + "xdtri;": "\u25bd", + "xfr;": "\U0001d535", + "xhArr;": "\u27fa", + "xharr;": "\u27f7", + "xi;": "\u03be", + "xlArr;": "\u27f8", + "xlarr;": "\u27f5", + "xmap;": "\u27fc", + "xnis;": "\u22fb", + "xodot;": "\u2a00", + "xopf;": "\U0001d569", + "xoplus;": "\u2a01", + "xotime;": "\u2a02", + "xrArr;": "\u27f9", + "xrarr;": "\u27f6", + "xscr;": "\U0001d4cd", + "xsqcup;": "\u2a06", + "xuplus;": "\u2a04", + "xutri;": "\u25b3", + "xvee;": "\u22c1", + "xwedge;": "\u22c0", + "yacute": "\xfd", + "yacute;": "\xfd", + "yacy;": "\u044f", + "ycirc;": "\u0177", + "ycy;": "\u044b", + "yen": "\xa5", + "yen;": "\xa5", + "yfr;": "\U0001d536", + "yicy;": "\u0457", + "yopf;": "\U0001d56a", + "yscr;": "\U0001d4ce", + "yucy;": "\u044e", + "yuml": "\xff", + "yuml;": "\xff", + "zacute;": "\u017a", + "zcaron;": "\u017e", + "zcy;": "\u0437", + "zdot;": "\u017c", + "zeetrf;": "\u2128", + "zeta;": "\u03b6", + "zfr;": "\U0001d537", + "zhcy;": "\u0436", + "zigrarr;": "\u21dd", + "zopf;": "\U0001d56b", + "zscr;": "\U0001d4cf", + "zwj;": "\u200d", + "zwnj;": "\u200c", +} + +replacementCharacters = { + 0x0: "\uFFFD", + 0x0d: "\u000D", + 0x80: "\u20AC", + 0x81: "\u0081", + 0x82: "\u201A", + 0x83: "\u0192", + 0x84: "\u201E", + 0x85: "\u2026", + 0x86: "\u2020", + 0x87: "\u2021", + 0x88: "\u02C6", + 0x89: "\u2030", + 0x8A: "\u0160", + 0x8B: "\u2039", + 0x8C: "\u0152", + 0x8D: "\u008D", + 0x8E: "\u017D", + 0x8F: "\u008F", + 0x90: "\u0090", + 0x91: "\u2018", + 0x92: "\u2019", + 0x93: "\u201C", + 0x94: "\u201D", + 0x95: "\u2022", + 0x96: "\u2013", + 0x97: "\u2014", + 0x98: "\u02DC", + 0x99: "\u2122", + 0x9A: "\u0161", + 0x9B: "\u203A", + 0x9C: "\u0153", + 0x9D: "\u009D", + 0x9E: "\u017E", + 0x9F: "\u0178", +} + +tokenTypes = { + "Doctype": 0, + "Characters": 1, + "SpaceCharacters": 2, + "StartTag": 3, + "EndTag": 4, + "EmptyTag": 5, + "Comment": 6, + "ParseError": 7 +} + +tagTokenTypes = frozenset([tokenTypes["StartTag"], tokenTypes["EndTag"], + tokenTypes["EmptyTag"]]) + + +prefixes = dict([(v, k) for k, v in namespaces.items()]) +prefixes["http://www.w3.org/1998/Math/MathML"] = "math" + + +class DataLossWarning(UserWarning): + """Raised when the current tree is unable to represent the input data""" + pass + + +class _ReparseException(Exception): + pass diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py new file mode 100644 index 0000000..5ba926e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py @@ -0,0 +1,29 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + +from collections import OrderedDict + + +def _attr_key(attr): + """Return an appropriate key for an attribute for sorting + + Attributes have a namespace that can be either ``None`` or a string. We + can't compare the two because they're different types, so we convert + ``None`` to an empty string first. + + """ + return (attr[0][0] or ''), attr[0][1] + + +class Filter(base.Filter): + """Alphabetizes attributes for elements""" + def __iter__(self): + for token in base.Filter.__iter__(self): + if token["type"] in ("StartTag", "EmptyTag"): + attrs = OrderedDict() + for name, value in sorted(token["data"].items(), + key=_attr_key): + attrs[name] = value + token["data"] = attrs + yield token diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/base.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/base.py new file mode 100644 index 0000000..c7dbaed --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/base.py @@ -0,0 +1,12 @@ +from __future__ import absolute_import, division, unicode_literals + + +class Filter(object): + def __init__(self, source): + self.source = source + + def __iter__(self): + return iter(self.source) + + def __getattr__(self, name): + return getattr(self.source, name) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py new file mode 100644 index 0000000..aefb5c8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py @@ -0,0 +1,73 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + + +class Filter(base.Filter): + """Injects ``<meta charset=ENCODING>`` tag into head of document""" + def __init__(self, source, encoding): + """Creates a Filter + + :arg source: the source token stream + + :arg encoding: the encoding to set + + """ + base.Filter.__init__(self, source) + self.encoding = encoding + + def __iter__(self): + state = "pre_head" + meta_found = (self.encoding is None) + pending = [] + + for token in base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag": + if token["name"].lower() == "head": + state = "in_head" + + elif type == "EmptyTag": + if token["name"].lower() == "meta": + # replace charset with actual encoding + has_http_equiv_content_type = False + for (namespace, name), value in token["data"].items(): + if namespace is not None: + continue + elif name.lower() == 'charset': + token["data"][(namespace, name)] = self.encoding + meta_found = True + break + elif name == 'http-equiv' and value.lower() == 'content-type': + has_http_equiv_content_type = True + else: + if has_http_equiv_content_type and (None, "content") in token["data"]: + token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding + meta_found = True + + elif token["name"].lower() == "head" and not meta_found: + # insert meta into empty head + yield {"type": "StartTag", "name": "head", + "data": token["data"]} + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + yield {"type": "EndTag", "name": "head"} + meta_found = True + continue + + elif type == "EndTag": + if token["name"].lower() == "head" and pending: + # insert meta into head (if necessary) and flush pending queue + yield pending.pop(0) + if not meta_found: + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + while pending: + yield pending.pop(0) + meta_found = True + state = "post_head" + + if state == "in_head": + pending.append(token) + else: + yield token diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/lint.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/lint.py new file mode 100644 index 0000000..fcc07ee --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/lint.py @@ -0,0 +1,93 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import text_type + +from . import base +from ..constants import namespaces, voidElements + +from ..constants import spaceCharacters +spaceCharacters = "".join(spaceCharacters) + + +class Filter(base.Filter): + """Lints the token stream for errors + + If it finds any errors, it'll raise an ``AssertionError``. + + """ + def __init__(self, source, require_matching_tags=True): + """Creates a Filter + + :arg source: the source token stream + + :arg require_matching_tags: whether or not to require matching tags + + """ + super(Filter, self).__init__(source) + self.require_matching_tags = require_matching_tags + + def __iter__(self): + open_elements = [] + for token in base.Filter.__iter__(self): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + namespace = token["namespace"] + name = token["name"] + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + assert isinstance(token["data"], dict) + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + assert type == "EmptyTag" + else: + assert type == "StartTag" + if type == "StartTag" and self.require_matching_tags: + open_elements.append((namespace, name)) + for (namespace, name), value in token["data"].items(): + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + assert isinstance(value, text_type) + + elif type == "EndTag": + namespace = token["namespace"] + name = token["name"] + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + assert False, "Void element reported as EndTag token: %(tag)s" % {"tag": name} + elif self.require_matching_tags: + start = open_elements.pop() + assert start == (namespace, name) + + elif type == "Comment": + data = token["data"] + assert isinstance(data, text_type) + + elif type in ("Characters", "SpaceCharacters"): + data = token["data"] + assert isinstance(data, text_type) + assert data != "" + if type == "SpaceCharacters": + assert data.strip(spaceCharacters) == "" + + elif type == "Doctype": + name = token["name"] + assert name is None or isinstance(name, text_type) + assert token["publicId"] is None or isinstance(name, text_type) + assert token["systemId"] is None or isinstance(name, text_type) + + elif type == "Entity": + assert isinstance(token["name"], text_type) + + elif type == "SerializerError": + assert isinstance(token["data"], text_type) + + else: + assert False, "Unknown token type: %(type)s" % {"type": type} + + yield token diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py new file mode 100644 index 0000000..4a86501 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/optionaltags.py @@ -0,0 +1,207 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + + +class Filter(base.Filter): + """Removes optional tags from the token stream""" + def slider(self): + previous1 = previous2 = None + for token in self.source: + if previous1 is not None: + yield previous2, previous1, token + previous2 = previous1 + previous1 = token + if previous1 is not None: + yield previous2, previous1, None + + def __iter__(self): + for previous, token, next in self.slider(): + type = token["type"] + if type == "StartTag": + if (token["data"] or + not self.is_optional_start(token["name"], previous, next)): + yield token + elif type == "EndTag": + if not self.is_optional_end(token["name"], next): + yield token + else: + yield token + + def is_optional_start(self, tagname, previous, next): + type = next and next["type"] or None + if tagname in 'html': + # An html element's start tag may be omitted if the first thing + # inside the html element is not a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname == 'head': + # A head element's start tag may be omitted if the first thing + # inside the head element is an element. + # XXX: we also omit the start tag if the head element is empty + if type in ("StartTag", "EmptyTag"): + return True + elif type == "EndTag": + return next["name"] == "head" + elif tagname == 'body': + # A body element's start tag may be omitted if the first thing + # inside the body element is not a space character or a comment, + # except if the first thing inside the body element is a script + # or style element and the node immediately preceding the body + # element is a head element whose end tag has been omitted. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we do not look at the preceding event, so we never omit + # the body element's start tag if it's followed by a script or + # a style element. + return next["name"] not in ('script', 'style') + else: + return True + elif tagname == 'colgroup': + # A colgroup element's start tag may be omitted if the first thing + # inside the colgroup element is a col element, and if the element + # is not immediately preceded by another colgroup element whose + # end tag has been omitted. + if type in ("StartTag", "EmptyTag"): + # XXX: we do not look at the preceding event, so instead we never + # omit the colgroup element's end tag when it is immediately + # followed by another colgroup element. See is_optional_end. + return next["name"] == "col" + else: + return False + elif tagname == 'tbody': + # A tbody element's start tag may be omitted if the first thing + # inside the tbody element is a tr element, and if the element is + # not immediately preceded by a tbody, thead, or tfoot element + # whose end tag has been omitted. + if type == "StartTag": + # omit the thead and tfoot elements' end tag when they are + # immediately followed by a tbody element. See is_optional_end. + if previous and previous['type'] == 'EndTag' and \ + previous['name'] in ('tbody', 'thead', 'tfoot'): + return False + return next["name"] == 'tr' + else: + return False + return False + + def is_optional_end(self, tagname, next): + type = next and next["type"] or None + if tagname in ('html', 'head', 'body'): + # An html element's end tag may be omitted if the html element + # is not immediately followed by a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname in ('li', 'optgroup', 'tr'): + # A li element's end tag may be omitted if the li element is + # immediately followed by another li element or if there is + # no more content in the parent element. + # An optgroup element's end tag may be omitted if the optgroup + # element is immediately followed by another optgroup element, + # or if there is no more content in the parent element. + # A tr element's end tag may be omitted if the tr element is + # immediately followed by another tr element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] == tagname + else: + return type == "EndTag" or type is None + elif tagname in ('dt', 'dd'): + # A dt element's end tag may be omitted if the dt element is + # immediately followed by another dt element or a dd element. + # A dd element's end tag may be omitted if the dd element is + # immediately followed by another dd element or a dt element, + # or if there is no more content in the parent element. + if type == "StartTag": + return next["name"] in ('dt', 'dd') + elif tagname == 'dd': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'p': + # A p element's end tag may be omitted if the p element is + # immediately followed by an address, article, aside, + # blockquote, datagrid, dialog, dir, div, dl, fieldset, + # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, + # nav, ol, p, pre, section, table, or ul, element, or if + # there is no more content in the parent element. + if type in ("StartTag", "EmptyTag"): + return next["name"] in ('address', 'article', 'aside', + 'blockquote', 'datagrid', 'dialog', + 'dir', 'div', 'dl', 'fieldset', 'footer', + 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'header', 'hr', 'menu', 'nav', 'ol', + 'p', 'pre', 'section', 'table', 'ul') + else: + return type == "EndTag" or type is None + elif tagname == 'option': + # An option element's end tag may be omitted if the option + # element is immediately followed by another option element, + # or if it is immediately followed by an <code>optgroup</code> + # element, or if there is no more content in the parent + # element. + if type == "StartTag": + return next["name"] in ('option', 'optgroup') + else: + return type == "EndTag" or type is None + elif tagname in ('rt', 'rp'): + # An rt element's end tag may be omitted if the rt element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + # An rp element's end tag may be omitted if the rp element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('rt', 'rp') + else: + return type == "EndTag" or type is None + elif tagname == 'colgroup': + # A colgroup element's end tag may be omitted if the colgroup + # element is not immediately followed by a space character or + # a comment. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we also look for an immediately following colgroup + # element. See is_optional_start. + return next["name"] != 'colgroup' + else: + return True + elif tagname in ('thead', 'tbody'): + # A thead element's end tag may be omitted if the thead element + # is immediately followed by a tbody or tfoot element. + # A tbody element's end tag may be omitted if the tbody element + # is immediately followed by a tbody or tfoot element, or if + # there is no more content in the parent element. + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] in ['tbody', 'tfoot'] + elif tagname == 'tbody': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'tfoot': + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] == 'tbody' + else: + return type == "EndTag" or type is None + elif tagname in ('td', 'th'): + # A td element's end tag may be omitted if the td element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + # A th element's end tag may be omitted if the th element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('td', 'th') + else: + return type == "EndTag" or type is None + return False diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py new file mode 100644 index 0000000..af8e77b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/sanitizer.py @@ -0,0 +1,896 @@ +from __future__ import absolute_import, division, unicode_literals + +import re +from xml.sax.saxutils import escape, unescape + +from pip._vendor.six.moves import urllib_parse as urlparse + +from . import base +from ..constants import namespaces, prefixes + +__all__ = ["Filter"] + + +allowed_elements = frozenset(( + (namespaces['html'], 'a'), + (namespaces['html'], 'abbr'), + (namespaces['html'], 'acronym'), + (namespaces['html'], 'address'), + (namespaces['html'], 'area'), + (namespaces['html'], 'article'), + (namespaces['html'], 'aside'), + (namespaces['html'], 'audio'), + (namespaces['html'], 'b'), + (namespaces['html'], 'big'), + (namespaces['html'], 'blockquote'), + (namespaces['html'], 'br'), + (namespaces['html'], 'button'), + (namespaces['html'], 'canvas'), + (namespaces['html'], 'caption'), + (namespaces['html'], 'center'), + (namespaces['html'], 'cite'), + (namespaces['html'], 'code'), + (namespaces['html'], 'col'), + (namespaces['html'], 'colgroup'), + (namespaces['html'], 'command'), + (namespaces['html'], 'datagrid'), + (namespaces['html'], 'datalist'), + (namespaces['html'], 'dd'), + (namespaces['html'], 'del'), + (namespaces['html'], 'details'), + (namespaces['html'], 'dfn'), + (namespaces['html'], 'dialog'), + (namespaces['html'], 'dir'), + (namespaces['html'], 'div'), + (namespaces['html'], 'dl'), + (namespaces['html'], 'dt'), + (namespaces['html'], 'em'), + (namespaces['html'], 'event-source'), + (namespaces['html'], 'fieldset'), + (namespaces['html'], 'figcaption'), + (namespaces['html'], 'figure'), + (namespaces['html'], 'footer'), + (namespaces['html'], 'font'), + (namespaces['html'], 'form'), + (namespaces['html'], 'header'), + (namespaces['html'], 'h1'), + (namespaces['html'], 'h2'), + (namespaces['html'], 'h3'), + (namespaces['html'], 'h4'), + (namespaces['html'], 'h5'), + (namespaces['html'], 'h6'), + (namespaces['html'], 'hr'), + (namespaces['html'], 'i'), + (namespaces['html'], 'img'), + (namespaces['html'], 'input'), + (namespaces['html'], 'ins'), + (namespaces['html'], 'keygen'), + (namespaces['html'], 'kbd'), + (namespaces['html'], 'label'), + (namespaces['html'], 'legend'), + (namespaces['html'], 'li'), + (namespaces['html'], 'm'), + (namespaces['html'], 'map'), + (namespaces['html'], 'menu'), + (namespaces['html'], 'meter'), + (namespaces['html'], 'multicol'), + (namespaces['html'], 'nav'), + (namespaces['html'], 'nextid'), + (namespaces['html'], 'ol'), + (namespaces['html'], 'output'), + (namespaces['html'], 'optgroup'), + (namespaces['html'], 'option'), + (namespaces['html'], 'p'), + (namespaces['html'], 'pre'), + (namespaces['html'], 'progress'), + (namespaces['html'], 'q'), + (namespaces['html'], 's'), + (namespaces['html'], 'samp'), + (namespaces['html'], 'section'), + (namespaces['html'], 'select'), + (namespaces['html'], 'small'), + (namespaces['html'], 'sound'), + (namespaces['html'], 'source'), + (namespaces['html'], 'spacer'), + (namespaces['html'], 'span'), + (namespaces['html'], 'strike'), + (namespaces['html'], 'strong'), + (namespaces['html'], 'sub'), + (namespaces['html'], 'sup'), + (namespaces['html'], 'table'), + (namespaces['html'], 'tbody'), + (namespaces['html'], 'td'), + (namespaces['html'], 'textarea'), + (namespaces['html'], 'time'), + (namespaces['html'], 'tfoot'), + (namespaces['html'], 'th'), + (namespaces['html'], 'thead'), + (namespaces['html'], 'tr'), + (namespaces['html'], 'tt'), + (namespaces['html'], 'u'), + (namespaces['html'], 'ul'), + (namespaces['html'], 'var'), + (namespaces['html'], 'video'), + (namespaces['mathml'], 'maction'), + (namespaces['mathml'], 'math'), + (namespaces['mathml'], 'merror'), + (namespaces['mathml'], 'mfrac'), + (namespaces['mathml'], 'mi'), + (namespaces['mathml'], 'mmultiscripts'), + (namespaces['mathml'], 'mn'), + (namespaces['mathml'], 'mo'), + (namespaces['mathml'], 'mover'), + (namespaces['mathml'], 'mpadded'), + (namespaces['mathml'], 'mphantom'), + (namespaces['mathml'], 'mprescripts'), + (namespaces['mathml'], 'mroot'), + (namespaces['mathml'], 'mrow'), + (namespaces['mathml'], 'mspace'), + (namespaces['mathml'], 'msqrt'), + (namespaces['mathml'], 'mstyle'), + (namespaces['mathml'], 'msub'), + (namespaces['mathml'], 'msubsup'), + (namespaces['mathml'], 'msup'), + (namespaces['mathml'], 'mtable'), + (namespaces['mathml'], 'mtd'), + (namespaces['mathml'], 'mtext'), + (namespaces['mathml'], 'mtr'), + (namespaces['mathml'], 'munder'), + (namespaces['mathml'], 'munderover'), + (namespaces['mathml'], 'none'), + (namespaces['svg'], 'a'), + (namespaces['svg'], 'animate'), + (namespaces['svg'], 'animateColor'), + (namespaces['svg'], 'animateMotion'), + (namespaces['svg'], 'animateTransform'), + (namespaces['svg'], 'clipPath'), + (namespaces['svg'], 'circle'), + (namespaces['svg'], 'defs'), + (namespaces['svg'], 'desc'), + (namespaces['svg'], 'ellipse'), + (namespaces['svg'], 'font-face'), + (namespaces['svg'], 'font-face-name'), + (namespaces['svg'], 'font-face-src'), + (namespaces['svg'], 'g'), + (namespaces['svg'], 'glyph'), + (namespaces['svg'], 'hkern'), + (namespaces['svg'], 'linearGradient'), + (namespaces['svg'], 'line'), + (namespaces['svg'], 'marker'), + (namespaces['svg'], 'metadata'), + (namespaces['svg'], 'missing-glyph'), + (namespaces['svg'], 'mpath'), + (namespaces['svg'], 'path'), + (namespaces['svg'], 'polygon'), + (namespaces['svg'], 'polyline'), + (namespaces['svg'], 'radialGradient'), + (namespaces['svg'], 'rect'), + (namespaces['svg'], 'set'), + (namespaces['svg'], 'stop'), + (namespaces['svg'], 'svg'), + (namespaces['svg'], 'switch'), + (namespaces['svg'], 'text'), + (namespaces['svg'], 'title'), + (namespaces['svg'], 'tspan'), + (namespaces['svg'], 'use'), +)) + +allowed_attributes = frozenset(( + # HTML attributes + (None, 'abbr'), + (None, 'accept'), + (None, 'accept-charset'), + (None, 'accesskey'), + (None, 'action'), + (None, 'align'), + (None, 'alt'), + (None, 'autocomplete'), + (None, 'autofocus'), + (None, 'axis'), + (None, 'background'), + (None, 'balance'), + (None, 'bgcolor'), + (None, 'bgproperties'), + (None, 'border'), + (None, 'bordercolor'), + (None, 'bordercolordark'), + (None, 'bordercolorlight'), + (None, 'bottompadding'), + (None, 'cellpadding'), + (None, 'cellspacing'), + (None, 'ch'), + (None, 'challenge'), + (None, 'char'), + (None, 'charoff'), + (None, 'choff'), + (None, 'charset'), + (None, 'checked'), + (None, 'cite'), + (None, 'class'), + (None, 'clear'), + (None, 'color'), + (None, 'cols'), + (None, 'colspan'), + (None, 'compact'), + (None, 'contenteditable'), + (None, 'controls'), + (None, 'coords'), + (None, 'data'), + (None, 'datafld'), + (None, 'datapagesize'), + (None, 'datasrc'), + (None, 'datetime'), + (None, 'default'), + (None, 'delay'), + (None, 'dir'), + (None, 'disabled'), + (None, 'draggable'), + (None, 'dynsrc'), + (None, 'enctype'), + (None, 'end'), + (None, 'face'), + (None, 'for'), + (None, 'form'), + (None, 'frame'), + (None, 'galleryimg'), + (None, 'gutter'), + (None, 'headers'), + (None, 'height'), + (None, 'hidefocus'), + (None, 'hidden'), + (None, 'high'), + (None, 'href'), + (None, 'hreflang'), + (None, 'hspace'), + (None, 'icon'), + (None, 'id'), + (None, 'inputmode'), + (None, 'ismap'), + (None, 'keytype'), + (None, 'label'), + (None, 'leftspacing'), + (None, 'lang'), + (None, 'list'), + (None, 'longdesc'), + (None, 'loop'), + (None, 'loopcount'), + (None, 'loopend'), + (None, 'loopstart'), + (None, 'low'), + (None, 'lowsrc'), + (None, 'max'), + (None, 'maxlength'), + (None, 'media'), + (None, 'method'), + (None, 'min'), + (None, 'multiple'), + (None, 'name'), + (None, 'nohref'), + (None, 'noshade'), + (None, 'nowrap'), + (None, 'open'), + (None, 'optimum'), + (None, 'pattern'), + (None, 'ping'), + (None, 'point-size'), + (None, 'poster'), + (None, 'pqg'), + (None, 'preload'), + (None, 'prompt'), + (None, 'radiogroup'), + (None, 'readonly'), + (None, 'rel'), + (None, 'repeat-max'), + (None, 'repeat-min'), + (None, 'replace'), + (None, 'required'), + (None, 'rev'), + (None, 'rightspacing'), + (None, 'rows'), + (None, 'rowspan'), + (None, 'rules'), + (None, 'scope'), + (None, 'selected'), + (None, 'shape'), + (None, 'size'), + (None, 'span'), + (None, 'src'), + (None, 'start'), + (None, 'step'), + (None, 'style'), + (None, 'summary'), + (None, 'suppress'), + (None, 'tabindex'), + (None, 'target'), + (None, 'template'), + (None, 'title'), + (None, 'toppadding'), + (None, 'type'), + (None, 'unselectable'), + (None, 'usemap'), + (None, 'urn'), + (None, 'valign'), + (None, 'value'), + (None, 'variable'), + (None, 'volume'), + (None, 'vspace'), + (None, 'vrml'), + (None, 'width'), + (None, 'wrap'), + (namespaces['xml'], 'lang'), + # MathML attributes + (None, 'actiontype'), + (None, 'align'), + (None, 'columnalign'), + (None, 'columnalign'), + (None, 'columnalign'), + (None, 'columnlines'), + (None, 'columnspacing'), + (None, 'columnspan'), + (None, 'depth'), + (None, 'display'), + (None, 'displaystyle'), + (None, 'equalcolumns'), + (None, 'equalrows'), + (None, 'fence'), + (None, 'fontstyle'), + (None, 'fontweight'), + (None, 'frame'), + (None, 'height'), + (None, 'linethickness'), + (None, 'lspace'), + (None, 'mathbackground'), + (None, 'mathcolor'), + (None, 'mathvariant'), + (None, 'mathvariant'), + (None, 'maxsize'), + (None, 'minsize'), + (None, 'other'), + (None, 'rowalign'), + (None, 'rowalign'), + (None, 'rowalign'), + (None, 'rowlines'), + (None, 'rowspacing'), + (None, 'rowspan'), + (None, 'rspace'), + (None, 'scriptlevel'), + (None, 'selection'), + (None, 'separator'), + (None, 'stretchy'), + (None, 'width'), + (None, 'width'), + (namespaces['xlink'], 'href'), + (namespaces['xlink'], 'show'), + (namespaces['xlink'], 'type'), + # SVG attributes + (None, 'accent-height'), + (None, 'accumulate'), + (None, 'additive'), + (None, 'alphabetic'), + (None, 'arabic-form'), + (None, 'ascent'), + (None, 'attributeName'), + (None, 'attributeType'), + (None, 'baseProfile'), + (None, 'bbox'), + (None, 'begin'), + (None, 'by'), + (None, 'calcMode'), + (None, 'cap-height'), + (None, 'class'), + (None, 'clip-path'), + (None, 'color'), + (None, 'color-rendering'), + (None, 'content'), + (None, 'cx'), + (None, 'cy'), + (None, 'd'), + (None, 'dx'), + (None, 'dy'), + (None, 'descent'), + (None, 'display'), + (None, 'dur'), + (None, 'end'), + (None, 'fill'), + (None, 'fill-opacity'), + (None, 'fill-rule'), + (None, 'font-family'), + (None, 'font-size'), + (None, 'font-stretch'), + (None, 'font-style'), + (None, 'font-variant'), + (None, 'font-weight'), + (None, 'from'), + (None, 'fx'), + (None, 'fy'), + (None, 'g1'), + (None, 'g2'), + (None, 'glyph-name'), + (None, 'gradientUnits'), + (None, 'hanging'), + (None, 'height'), + (None, 'horiz-adv-x'), + (None, 'horiz-origin-x'), + (None, 'id'), + (None, 'ideographic'), + (None, 'k'), + (None, 'keyPoints'), + (None, 'keySplines'), + (None, 'keyTimes'), + (None, 'lang'), + (None, 'marker-end'), + (None, 'marker-mid'), + (None, 'marker-start'), + (None, 'markerHeight'), + (None, 'markerUnits'), + (None, 'markerWidth'), + (None, 'mathematical'), + (None, 'max'), + (None, 'min'), + (None, 'name'), + (None, 'offset'), + (None, 'opacity'), + (None, 'orient'), + (None, 'origin'), + (None, 'overline-position'), + (None, 'overline-thickness'), + (None, 'panose-1'), + (None, 'path'), + (None, 'pathLength'), + (None, 'points'), + (None, 'preserveAspectRatio'), + (None, 'r'), + (None, 'refX'), + (None, 'refY'), + (None, 'repeatCount'), + (None, 'repeatDur'), + (None, 'requiredExtensions'), + (None, 'requiredFeatures'), + (None, 'restart'), + (None, 'rotate'), + (None, 'rx'), + (None, 'ry'), + (None, 'slope'), + (None, 'stemh'), + (None, 'stemv'), + (None, 'stop-color'), + (None, 'stop-opacity'), + (None, 'strikethrough-position'), + (None, 'strikethrough-thickness'), + (None, 'stroke'), + (None, 'stroke-dasharray'), + (None, 'stroke-dashoffset'), + (None, 'stroke-linecap'), + (None, 'stroke-linejoin'), + (None, 'stroke-miterlimit'), + (None, 'stroke-opacity'), + (None, 'stroke-width'), + (None, 'systemLanguage'), + (None, 'target'), + (None, 'text-anchor'), + (None, 'to'), + (None, 'transform'), + (None, 'type'), + (None, 'u1'), + (None, 'u2'), + (None, 'underline-position'), + (None, 'underline-thickness'), + (None, 'unicode'), + (None, 'unicode-range'), + (None, 'units-per-em'), + (None, 'values'), + (None, 'version'), + (None, 'viewBox'), + (None, 'visibility'), + (None, 'width'), + (None, 'widths'), + (None, 'x'), + (None, 'x-height'), + (None, 'x1'), + (None, 'x2'), + (namespaces['xlink'], 'actuate'), + (namespaces['xlink'], 'arcrole'), + (namespaces['xlink'], 'href'), + (namespaces['xlink'], 'role'), + (namespaces['xlink'], 'show'), + (namespaces['xlink'], 'title'), + (namespaces['xlink'], 'type'), + (namespaces['xml'], 'base'), + (namespaces['xml'], 'lang'), + (namespaces['xml'], 'space'), + (None, 'y'), + (None, 'y1'), + (None, 'y2'), + (None, 'zoomAndPan'), +)) + +attr_val_is_uri = frozenset(( + (None, 'href'), + (None, 'src'), + (None, 'cite'), + (None, 'action'), + (None, 'longdesc'), + (None, 'poster'), + (None, 'background'), + (None, 'datasrc'), + (None, 'dynsrc'), + (None, 'lowsrc'), + (None, 'ping'), + (namespaces['xlink'], 'href'), + (namespaces['xml'], 'base'), +)) + +svg_attr_val_allows_ref = frozenset(( + (None, 'clip-path'), + (None, 'color-profile'), + (None, 'cursor'), + (None, 'fill'), + (None, 'filter'), + (None, 'marker'), + (None, 'marker-start'), + (None, 'marker-mid'), + (None, 'marker-end'), + (None, 'mask'), + (None, 'stroke'), +)) + +svg_allow_local_href = frozenset(( + (None, 'altGlyph'), + (None, 'animate'), + (None, 'animateColor'), + (None, 'animateMotion'), + (None, 'animateTransform'), + (None, 'cursor'), + (None, 'feImage'), + (None, 'filter'), + (None, 'linearGradient'), + (None, 'pattern'), + (None, 'radialGradient'), + (None, 'textpath'), + (None, 'tref'), + (None, 'set'), + (None, 'use') +)) + +allowed_css_properties = frozenset(( + 'azimuth', + 'background-color', + 'border-bottom-color', + 'border-collapse', + 'border-color', + 'border-left-color', + 'border-right-color', + 'border-top-color', + 'clear', + 'color', + 'cursor', + 'direction', + 'display', + 'elevation', + 'float', + 'font', + 'font-family', + 'font-size', + 'font-style', + 'font-variant', + 'font-weight', + 'height', + 'letter-spacing', + 'line-height', + 'overflow', + 'pause', + 'pause-after', + 'pause-before', + 'pitch', + 'pitch-range', + 'richness', + 'speak', + 'speak-header', + 'speak-numeral', + 'speak-punctuation', + 'speech-rate', + 'stress', + 'text-align', + 'text-decoration', + 'text-indent', + 'unicode-bidi', + 'vertical-align', + 'voice-family', + 'volume', + 'white-space', + 'width', +)) + +allowed_css_keywords = frozenset(( + 'auto', + 'aqua', + 'black', + 'block', + 'blue', + 'bold', + 'both', + 'bottom', + 'brown', + 'center', + 'collapse', + 'dashed', + 'dotted', + 'fuchsia', + 'gray', + 'green', + '!important', + 'italic', + 'left', + 'lime', + 'maroon', + 'medium', + 'none', + 'navy', + 'normal', + 'nowrap', + 'olive', + 'pointer', + 'purple', + 'red', + 'right', + 'solid', + 'silver', + 'teal', + 'top', + 'transparent', + 'underline', + 'white', + 'yellow', +)) + +allowed_svg_properties = frozenset(( + 'fill', + 'fill-opacity', + 'fill-rule', + 'stroke', + 'stroke-width', + 'stroke-linecap', + 'stroke-linejoin', + 'stroke-opacity', +)) + +allowed_protocols = frozenset(( + 'ed2k', + 'ftp', + 'http', + 'https', + 'irc', + 'mailto', + 'news', + 'gopher', + 'nntp', + 'telnet', + 'webcal', + 'xmpp', + 'callto', + 'feed', + 'urn', + 'aim', + 'rsync', + 'tag', + 'ssh', + 'sftp', + 'rtsp', + 'afs', + 'data', +)) + +allowed_content_types = frozenset(( + 'image/png', + 'image/jpeg', + 'image/gif', + 'image/webp', + 'image/bmp', + 'text/plain', +)) + + +data_content_type = re.compile(r''' + ^ + # Match a content type <application>/<type> + (?P<content_type>[-a-zA-Z0-9.]+/[-a-zA-Z0-9.]+) + # Match any character set and encoding + (?:(?:;charset=(?:[-a-zA-Z0-9]+)(?:;(?:base64))?) + |(?:;(?:base64))?(?:;charset=(?:[-a-zA-Z0-9]+))?) + # Assume the rest is data + ,.* + $ + ''', + re.VERBOSE) + + +class Filter(base.Filter): + """Sanitizes token stream of XHTML+MathML+SVG and of inline style attributes""" + def __init__(self, + source, + allowed_elements=allowed_elements, + allowed_attributes=allowed_attributes, + allowed_css_properties=allowed_css_properties, + allowed_css_keywords=allowed_css_keywords, + allowed_svg_properties=allowed_svg_properties, + allowed_protocols=allowed_protocols, + allowed_content_types=allowed_content_types, + attr_val_is_uri=attr_val_is_uri, + svg_attr_val_allows_ref=svg_attr_val_allows_ref, + svg_allow_local_href=svg_allow_local_href): + """Creates a Filter + + :arg allowed_elements: set of elements to allow--everything else will + be escaped + + :arg allowed_attributes: set of attributes to allow in + elements--everything else will be stripped + + :arg allowed_css_properties: set of CSS properties to allow--everything + else will be stripped + + :arg allowed_css_keywords: set of CSS keywords to allow--everything + else will be stripped + + :arg allowed_svg_properties: set of SVG properties to allow--everything + else will be removed + + :arg allowed_protocols: set of allowed protocols for URIs + + :arg allowed_content_types: set of allowed content types for ``data`` URIs. + + :arg attr_val_is_uri: set of attributes that have URI values--values + that have a scheme not listed in ``allowed_protocols`` are removed + + :arg svg_attr_val_allows_ref: set of SVG attributes that can have + references + + :arg svg_allow_local_href: set of SVG elements that can have local + hrefs--these are removed + + """ + super(Filter, self).__init__(source) + self.allowed_elements = allowed_elements + self.allowed_attributes = allowed_attributes + self.allowed_css_properties = allowed_css_properties + self.allowed_css_keywords = allowed_css_keywords + self.allowed_svg_properties = allowed_svg_properties + self.allowed_protocols = allowed_protocols + self.allowed_content_types = allowed_content_types + self.attr_val_is_uri = attr_val_is_uri + self.svg_attr_val_allows_ref = svg_attr_val_allows_ref + self.svg_allow_local_href = svg_allow_local_href + + def __iter__(self): + for token in base.Filter.__iter__(self): + token = self.sanitize_token(token) + if token: + yield token + + # Sanitize the +html+, escaping all elements not in ALLOWED_ELEMENTS, and + # stripping out all attributes not in ALLOWED_ATTRIBUTES. Style attributes + # are parsed, and a restricted set, specified by ALLOWED_CSS_PROPERTIES and + # ALLOWED_CSS_KEYWORDS, are allowed through. attributes in ATTR_VAL_IS_URI + # are scanned, and only URI schemes specified in ALLOWED_PROTOCOLS are + # allowed. + # + # sanitize_html('<script> do_nasty_stuff() </script>') + # => <script> do_nasty_stuff() </script> + # sanitize_html('<a href="javascript: sucker();">Click here for $100</a>') + # => <a>Click here for $100</a> + def sanitize_token(self, token): + + # accommodate filters which use token_type differently + token_type = token["type"] + if token_type in ("StartTag", "EndTag", "EmptyTag"): + name = token["name"] + namespace = token["namespace"] + if ((namespace, name) in self.allowed_elements or + (namespace is None and + (namespaces["html"], name) in self.allowed_elements)): + return self.allowed_token(token) + else: + return self.disallowed_token(token) + elif token_type == "Comment": + pass + else: + return token + + def allowed_token(self, token): + if "data" in token: + attrs = token["data"] + attr_names = set(attrs.keys()) + + # Remove forbidden attributes + for to_remove in (attr_names - self.allowed_attributes): + del token["data"][to_remove] + attr_names.remove(to_remove) + + # Remove attributes with disallowed URL values + for attr in (attr_names & self.attr_val_is_uri): + assert attr in attrs + # I don't have a clue where this regexp comes from or why it matches those + # characters, nor why we call unescape. I just know it's always been here. + # Should you be worried by this comment in a sanitizer? Yes. On the other hand, all + # this will do is remove *more* than it otherwise would. + val_unescaped = re.sub("[`\x00-\x20\x7f-\xa0\\s]+", '', + unescape(attrs[attr])).lower() + # remove replacement characters from unescaped characters + val_unescaped = val_unescaped.replace("\ufffd", "") + try: + uri = urlparse.urlparse(val_unescaped) + except ValueError: + uri = None + del attrs[attr] + if uri and uri.scheme: + if uri.scheme not in self.allowed_protocols: + del attrs[attr] + if uri.scheme == 'data': + m = data_content_type.match(uri.path) + if not m: + del attrs[attr] + elif m.group('content_type') not in self.allowed_content_types: + del attrs[attr] + + for attr in self.svg_attr_val_allows_ref: + if attr in attrs: + attrs[attr] = re.sub(r'url\s*\(\s*[^#\s][^)]+?\)', + ' ', + unescape(attrs[attr])) + if (token["name"] in self.svg_allow_local_href and + (namespaces['xlink'], 'href') in attrs and re.search(r'^\s*[^#\s].*', + attrs[(namespaces['xlink'], 'href')])): + del attrs[(namespaces['xlink'], 'href')] + if (None, 'style') in attrs: + attrs[(None, 'style')] = self.sanitize_css(attrs[(None, 'style')]) + token["data"] = attrs + return token + + def disallowed_token(self, token): + token_type = token["type"] + if token_type == "EndTag": + token["data"] = "</%s>" % token["name"] + elif token["data"]: + assert token_type in ("StartTag", "EmptyTag") + attrs = [] + for (ns, name), v in token["data"].items(): + attrs.append(' %s="%s"' % (name if ns is None else "%s:%s" % (prefixes[ns], name), escape(v))) + token["data"] = "<%s%s>" % (token["name"], ''.join(attrs)) + else: + token["data"] = "<%s>" % token["name"] + if token.get("selfClosing"): + token["data"] = token["data"][:-1] + "/>" + + token["type"] = "Characters" + + del token["name"] + return token + + def sanitize_css(self, style): + # disallow urls + style = re.compile(r'url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) + + # gauntlet + if not re.match(r"""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): + return '' + if not re.match(r"^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): + return '' + + clean = [] + for prop, value in re.findall(r"([-\w]+)\s*:\s*([^:;]*)", style): + if not value: + continue + if prop.lower() in self.allowed_css_properties: + clean.append(prop + ': ' + value + ';') + elif prop.split('-')[0].lower() in ['background', 'border', 'margin', + 'padding']: + for keyword in value.split(): + if keyword not in self.allowed_css_keywords and \ + not re.match(r"^(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): # noqa + break + else: + clean.append(prop + ': ' + value + ';') + elif prop.lower() in self.allowed_svg_properties: + clean.append(prop + ': ' + value + ';') + + return ' '.join(clean) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py new file mode 100644 index 0000000..0d12584 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/filters/whitespace.py @@ -0,0 +1,38 @@ +from __future__ import absolute_import, division, unicode_literals + +import re + +from . import base +from ..constants import rcdataElements, spaceCharacters +spaceCharacters = "".join(spaceCharacters) + +SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) + + +class Filter(base.Filter): + """Collapses whitespace except in pre, textarea, and script elements""" + spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) + + def __iter__(self): + preserve = 0 + for token in base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag" \ + and (preserve or token["name"] in self.spacePreserveElements): + preserve += 1 + + elif type == "EndTag" and preserve: + preserve -= 1 + + elif not preserve and type == "SpaceCharacters" and token["data"]: + # Test on token["data"] above to not introduce spaces where there were not + token["data"] = " " + + elif not preserve and type == "Characters": + token["data"] = collapse_spaces(token["data"]) + + yield token + + +def collapse_spaces(text): + return SPACES_REGEX.sub(' ', text) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py new file mode 100644 index 0000000..ae41a13 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/html5parser.py @@ -0,0 +1,2791 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import with_metaclass, viewkeys + +import types +from collections import OrderedDict + +from . import _inputstream +from . import _tokenizer + +from . import treebuilders +from .treebuilders.base import Marker + +from . import _utils +from .constants import ( + spaceCharacters, asciiUpper2Lower, + specialElements, headingElements, cdataElements, rcdataElements, + tokenTypes, tagTokenTypes, + namespaces, + htmlIntegrationPointElements, mathmlTextIntegrationPointElements, + adjustForeignAttributes as adjustForeignAttributesMap, + adjustMathMLAttributes, adjustSVGAttributes, + E, + _ReparseException +) + + +def parse(doc, treebuilder="etree", namespaceHTMLElements=True, **kwargs): + """Parse an HTML document as a string or file-like object into a tree + + :arg doc: the document to parse as a string or file-like object + + :arg treebuilder: the treebuilder to use when parsing + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + :returns: parsed tree + + Example: + + >>> from html5lib.html5parser import parse + >>> parse('<html><body><p>This is a doc</p></body></html>') + <Element u'{http://www.w3.org/1999/xhtml}html' at 0x7feac4909db0> + + """ + tb = treebuilders.getTreeBuilder(treebuilder) + p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) + return p.parse(doc, **kwargs) + + +def parseFragment(doc, container="div", treebuilder="etree", namespaceHTMLElements=True, **kwargs): + """Parse an HTML fragment as a string or file-like object into a tree + + :arg doc: the fragment to parse as a string or file-like object + + :arg container: the container context to parse the fragment in + + :arg treebuilder: the treebuilder to use when parsing + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + :returns: parsed tree + + Example: + + >>> from html5lib.html5libparser import parseFragment + >>> parseFragment('<b>this is a fragment</b>') + <Element u'DOCUMENT_FRAGMENT' at 0x7feac484b090> + + """ + tb = treebuilders.getTreeBuilder(treebuilder) + p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) + return p.parseFragment(doc, container=container, **kwargs) + + +def method_decorator_metaclass(function): + class Decorated(type): + def __new__(meta, classname, bases, classDict): + for attributeName, attribute in classDict.items(): + if isinstance(attribute, types.FunctionType): + attribute = function(attribute) + + classDict[attributeName] = attribute + return type.__new__(meta, classname, bases, classDict) + return Decorated + + +class HTMLParser(object): + """HTML parser + + Generates a tree structure from a stream of (possibly malformed) HTML. + + """ + + def __init__(self, tree=None, strict=False, namespaceHTMLElements=True, debug=False): + """ + :arg tree: a treebuilder class controlling the type of tree that will be + returned. Built in treebuilders can be accessed through + html5lib.treebuilders.getTreeBuilder(treeType) + + :arg strict: raise an exception when a parse error is encountered + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + :arg debug: whether or not to enable debug mode which logs things + + Example: + + >>> from html5lib.html5parser import HTMLParser + >>> parser = HTMLParser() # generates parser with etree builder + >>> parser = HTMLParser('lxml', strict=True) # generates parser with lxml builder which is strict + + """ + + # Raise an exception on the first error encountered + self.strict = strict + + if tree is None: + tree = treebuilders.getTreeBuilder("etree") + self.tree = tree(namespaceHTMLElements) + self.errors = [] + + self.phases = dict([(name, cls(self, self.tree)) for name, cls in + getPhases(debug).items()]) + + def _parse(self, stream, innerHTML=False, container="div", scripting=False, **kwargs): + + self.innerHTMLMode = innerHTML + self.container = container + self.scripting = scripting + self.tokenizer = _tokenizer.HTMLTokenizer(stream, parser=self, **kwargs) + self.reset() + + try: + self.mainLoop() + except _ReparseException: + self.reset() + self.mainLoop() + + def reset(self): + self.tree.reset() + self.firstStartTag = False + self.errors = [] + self.log = [] # only used with debug mode + # "quirks" / "limited quirks" / "no quirks" + self.compatMode = "no quirks" + + if self.innerHTMLMode: + self.innerHTML = self.container.lower() + + if self.innerHTML in cdataElements: + self.tokenizer.state = self.tokenizer.rcdataState + elif self.innerHTML in rcdataElements: + self.tokenizer.state = self.tokenizer.rawtextState + elif self.innerHTML == 'plaintext': + self.tokenizer.state = self.tokenizer.plaintextState + else: + # state already is data state + # self.tokenizer.state = self.tokenizer.dataState + pass + self.phase = self.phases["beforeHtml"] + self.phase.insertHtmlElement() + self.resetInsertionMode() + else: + self.innerHTML = False # pylint:disable=redefined-variable-type + self.phase = self.phases["initial"] + + self.lastPhase = None + + self.beforeRCDataPhase = None + + self.framesetOK = True + + @property + def documentEncoding(self): + """Name of the character encoding that was used to decode the input stream, or + :obj:`None` if that is not determined yet + + """ + if not hasattr(self, 'tokenizer'): + return None + return self.tokenizer.stream.charEncoding[0].name + + def isHTMLIntegrationPoint(self, element): + if (element.name == "annotation-xml" and + element.namespace == namespaces["mathml"]): + return ("encoding" in element.attributes and + element.attributes["encoding"].translate( + asciiUpper2Lower) in + ("text/html", "application/xhtml+xml")) + else: + return (element.namespace, element.name) in htmlIntegrationPointElements + + def isMathMLTextIntegrationPoint(self, element): + return (element.namespace, element.name) in mathmlTextIntegrationPointElements + + def mainLoop(self): + CharactersToken = tokenTypes["Characters"] + SpaceCharactersToken = tokenTypes["SpaceCharacters"] + StartTagToken = tokenTypes["StartTag"] + EndTagToken = tokenTypes["EndTag"] + CommentToken = tokenTypes["Comment"] + DoctypeToken = tokenTypes["Doctype"] + ParseErrorToken = tokenTypes["ParseError"] + + for token in self.normalizedTokens(): + prev_token = None + new_token = token + while new_token is not None: + prev_token = new_token + currentNode = self.tree.openElements[-1] if self.tree.openElements else None + currentNodeNamespace = currentNode.namespace if currentNode else None + currentNodeName = currentNode.name if currentNode else None + + type = new_token["type"] + + if type == ParseErrorToken: + self.parseError(new_token["data"], new_token.get("datavars", {})) + new_token = None + else: + if (len(self.tree.openElements) == 0 or + currentNodeNamespace == self.tree.defaultNamespace or + (self.isMathMLTextIntegrationPoint(currentNode) and + ((type == StartTagToken and + token["name"] not in frozenset(["mglyph", "malignmark"])) or + type in (CharactersToken, SpaceCharactersToken))) or + (currentNodeNamespace == namespaces["mathml"] and + currentNodeName == "annotation-xml" and + type == StartTagToken and + token["name"] == "svg") or + (self.isHTMLIntegrationPoint(currentNode) and + type in (StartTagToken, CharactersToken, SpaceCharactersToken))): + phase = self.phase + else: + phase = self.phases["inForeignContent"] + + if type == CharactersToken: + new_token = phase.processCharacters(new_token) + elif type == SpaceCharactersToken: + new_token = phase.processSpaceCharacters(new_token) + elif type == StartTagToken: + new_token = phase.processStartTag(new_token) + elif type == EndTagToken: + new_token = phase.processEndTag(new_token) + elif type == CommentToken: + new_token = phase.processComment(new_token) + elif type == DoctypeToken: + new_token = phase.processDoctype(new_token) + + if (type == StartTagToken and prev_token["selfClosing"] and + not prev_token["selfClosingAcknowledged"]): + self.parseError("non-void-element-with-trailing-solidus", + {"name": prev_token["name"]}) + + # When the loop finishes it's EOF + reprocess = True + phases = [] + while reprocess: + phases.append(self.phase) + reprocess = self.phase.processEOF() + if reprocess: + assert self.phase not in phases + + def normalizedTokens(self): + for token in self.tokenizer: + yield self.normalizeToken(token) + + def parse(self, stream, *args, **kwargs): + """Parse a HTML document into a well-formed tree + + :arg stream: a file-like object or string containing the HTML to be parsed + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element). + + :arg scripting: treat noscript elements as if JavaScript was turned on + + :returns: parsed tree + + Example: + + >>> from html5lib.html5parser import HTMLParser + >>> parser = HTMLParser() + >>> parser.parse('<html><body><p>This is a doc</p></body></html>') + <Element u'{http://www.w3.org/1999/xhtml}html' at 0x7feac4909db0> + + """ + self._parse(stream, False, None, *args, **kwargs) + return self.tree.getDocument() + + def parseFragment(self, stream, *args, **kwargs): + """Parse a HTML fragment into a well-formed tree fragment + + :arg container: name of the element we're setting the innerHTML + property if set to None, default to 'div' + + :arg stream: a file-like object or string containing the HTML to be parsed + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + :arg scripting: treat noscript elements as if JavaScript was turned on + + :returns: parsed tree + + Example: + + >>> from html5lib.html5libparser import HTMLParser + >>> parser = HTMLParser() + >>> parser.parseFragment('<b>this is a fragment</b>') + <Element u'DOCUMENT_FRAGMENT' at 0x7feac484b090> + + """ + self._parse(stream, True, *args, **kwargs) + return self.tree.getFragment() + + def parseError(self, errorcode="XXX-undefined-error", datavars=None): + # XXX The idea is to make errorcode mandatory. + if datavars is None: + datavars = {} + self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) + if self.strict: + raise ParseError(E[errorcode] % datavars) + + def normalizeToken(self, token): + # HTML5 specific normalizations to the token stream + if token["type"] == tokenTypes["StartTag"]: + raw = token["data"] + token["data"] = OrderedDict(raw) + if len(raw) > len(token["data"]): + # we had some duplicated attribute, fix so first wins + token["data"].update(raw[::-1]) + + return token + + def adjustMathMLAttributes(self, token): + adjust_attributes(token, adjustMathMLAttributes) + + def adjustSVGAttributes(self, token): + adjust_attributes(token, adjustSVGAttributes) + + def adjustForeignAttributes(self, token): + adjust_attributes(token, adjustForeignAttributesMap) + + def reparseTokenNormal(self, token): + # pylint:disable=unused-argument + self.parser.phase() + + def resetInsertionMode(self): + # The name of this method is mostly historical. (It's also used in the + # specification.) + last = False + newModes = { + "select": "inSelect", + "td": "inCell", + "th": "inCell", + "tr": "inRow", + "tbody": "inTableBody", + "thead": "inTableBody", + "tfoot": "inTableBody", + "caption": "inCaption", + "colgroup": "inColumnGroup", + "table": "inTable", + "head": "inBody", + "body": "inBody", + "frameset": "inFrameset", + "html": "beforeHead" + } + for node in self.tree.openElements[::-1]: + nodeName = node.name + new_phase = None + if node == self.tree.openElements[0]: + assert self.innerHTML + last = True + nodeName = self.innerHTML + # Check for conditions that should only happen in the innerHTML + # case + if nodeName in ("select", "colgroup", "head", "html"): + assert self.innerHTML + + if not last and node.namespace != self.tree.defaultNamespace: + continue + + if nodeName in newModes: + new_phase = self.phases[newModes[nodeName]] + break + elif last: + new_phase = self.phases["inBody"] + break + + self.phase = new_phase + + def parseRCDataRawtext(self, token, contentType): + # Generic RCDATA/RAWTEXT Parsing algorithm + assert contentType in ("RAWTEXT", "RCDATA") + + self.tree.insertElement(token) + + if contentType == "RAWTEXT": + self.tokenizer.state = self.tokenizer.rawtextState + else: + self.tokenizer.state = self.tokenizer.rcdataState + + self.originalPhase = self.phase + + self.phase = self.phases["text"] + + +@_utils.memoize +def getPhases(debug): + def log(function): + """Logger that records which phase processes each token""" + type_names = dict((value, key) for key, value in + tokenTypes.items()) + + def wrapped(self, *args, **kwargs): + if function.__name__.startswith("process") and len(args) > 0: + token = args[0] + try: + info = {"type": type_names[token['type']]} + except: + raise + if token['type'] in tagTokenTypes: + info["name"] = token['name'] + + self.parser.log.append((self.parser.tokenizer.state.__name__, + self.parser.phase.__class__.__name__, + self.__class__.__name__, + function.__name__, + info)) + return function(self, *args, **kwargs) + else: + return function(self, *args, **kwargs) + return wrapped + + def getMetaclass(use_metaclass, metaclass_func): + if use_metaclass: + return method_decorator_metaclass(metaclass_func) + else: + return type + + # pylint:disable=unused-argument + class Phase(with_metaclass(getMetaclass(debug, log))): + """Base class for helper object that implements each phase of processing + """ + + def __init__(self, parser, tree): + self.parser = parser + self.tree = tree + + def processEOF(self): + raise NotImplementedError + + def processComment(self, token): + # For most phases the following is correct. Where it's not it will be + # overridden. + self.tree.insertComment(token, self.tree.openElements[-1]) + + def processDoctype(self, token): + self.parser.parseError("unexpected-doctype") + + def processCharacters(self, token): + self.tree.insertText(token["data"]) + + def processSpaceCharacters(self, token): + self.tree.insertText(token["data"]) + + def processStartTag(self, token): + return self.startTagHandler[token["name"]](token) + + def startTagHtml(self, token): + if not self.parser.firstStartTag and token["name"] == "html": + self.parser.parseError("non-html-root") + # XXX Need a check here to see if the first start tag token emitted is + # this token... If it's not, invoke self.parser.parseError(). + for attr, value in token["data"].items(): + if attr not in self.tree.openElements[0].attributes: + self.tree.openElements[0].attributes[attr] = value + self.parser.firstStartTag = False + + def processEndTag(self, token): + return self.endTagHandler[token["name"]](token) + + class InitialPhase(Phase): + def processSpaceCharacters(self, token): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + correct = token["correct"] + + if (name != "html" or publicId is not None or + systemId is not None and systemId != "about:legacy-compat"): + self.parser.parseError("unknown-doctype") + + if publicId is None: + publicId = "" + + self.tree.insertDoctype(token) + + if publicId != "": + publicId = publicId.translate(asciiUpper2Lower) + + if (not correct or token["name"] != "html" or + publicId.startswith( + ("+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//")) or + publicId in ("-//w3o//dtd w3 html strict 3.0//en//", + "-/w3c/dtd html 4.0 transitional/en", + "html") or + publicId.startswith( + ("-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//")) and + systemId is None or + systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): + self.parser.compatMode = "quirks" + elif (publicId.startswith( + ("-//w3c//dtd xhtml 1.0 frameset//", + "-//w3c//dtd xhtml 1.0 transitional//")) or + publicId.startswith( + ("-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//")) and + systemId is not None): + self.parser.compatMode = "limited quirks" + + self.parser.phase = self.parser.phases["beforeHtml"] + + def anythingElse(self): + self.parser.compatMode = "quirks" + self.parser.phase = self.parser.phases["beforeHtml"] + + def processCharacters(self, token): + self.parser.parseError("expected-doctype-but-got-chars") + self.anythingElse() + return token + + def processStartTag(self, token): + self.parser.parseError("expected-doctype-but-got-start-tag", + {"name": token["name"]}) + self.anythingElse() + return token + + def processEndTag(self, token): + self.parser.parseError("expected-doctype-but-got-end-tag", + {"name": token["name"]}) + self.anythingElse() + return token + + def processEOF(self): + self.parser.parseError("expected-doctype-but-got-eof") + self.anythingElse() + return True + + class BeforeHtmlPhase(Phase): + # helper methods + def insertHtmlElement(self): + self.tree.insertRoot(impliedTagToken("html", "StartTag")) + self.parser.phase = self.parser.phases["beforeHead"] + + # other + def processEOF(self): + self.insertHtmlElement() + return True + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + pass + + def processCharacters(self, token): + self.insertHtmlElement() + return token + + def processStartTag(self, token): + if token["name"] == "html": + self.parser.firstStartTag = True + self.insertHtmlElement() + return token + + def processEndTag(self, token): + if token["name"] not in ("head", "body", "html", "br"): + self.parser.parseError("unexpected-end-tag-before-html", + {"name": token["name"]}) + else: + self.insertHtmlElement() + return token + + class BeforeHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("head", "body", "html", "br"), self.endTagImplyHead) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.startTagHead(impliedTagToken("head", "StartTag")) + return True + + def processSpaceCharacters(self, token): + pass + + def processCharacters(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagHead(self, token): + self.tree.insertElement(token) + self.tree.headPointer = self.tree.openElements[-1] + self.parser.phase = self.parser.phases["inHead"] + + def startTagOther(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def endTagImplyHead(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def endTagOther(self, token): + self.parser.parseError("end-tag-after-implied-root", + {"name": token["name"]}) + + class InHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("title", self.startTagTitle), + (("noframes", "style"), self.startTagNoFramesStyle), + ("noscript", self.startTagNoscript), + ("script", self.startTagScript), + (("base", "basefont", "bgsound", "command", "link"), + self.startTagBaseLinkCommand), + ("meta", self.startTagMeta), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("head", self.endTagHead), + (("br", "html", "body"), self.endTagHtmlBodyBr) + ]) + self.endTagHandler.default = self.endTagOther + + # the real thing + def processEOF(self): + self.anythingElse() + return True + + def processCharacters(self, token): + self.anythingElse() + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagHead(self, token): + self.parser.parseError("two-heads-are-not-better-than-one") + + def startTagBaseLinkCommand(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagMeta(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + attributes = token["data"] + if self.parser.tokenizer.stream.charEncoding[1] == "tentative": + if "charset" in attributes: + self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) + elif ("content" in attributes and + "http-equiv" in attributes and + attributes["http-equiv"].lower() == "content-type"): + # Encoding it as UTF-8 here is a hack, as really we should pass + # the abstract Unicode string, and just use the + # ContentAttrParser on that, but using UTF-8 allows all chars + # to be encoded and as a ASCII-superset works. + data = _inputstream.EncodingBytes(attributes["content"].encode("utf-8")) + parser = _inputstream.ContentAttrParser(data) + codec = parser.parse() + self.parser.tokenizer.stream.changeEncoding(codec) + + def startTagTitle(self, token): + self.parser.parseRCDataRawtext(token, "RCDATA") + + def startTagNoFramesStyle(self, token): + # Need to decide whether to implement the scripting-disabled case + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagNoscript(self, token): + if self.parser.scripting: + self.parser.parseRCDataRawtext(token, "RAWTEXT") + else: + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inHeadNoscript"] + + def startTagScript(self, token): + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState + self.parser.originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["text"] + + def startTagOther(self, token): + self.anythingElse() + return token + + def endTagHead(self, token): + node = self.parser.tree.openElements.pop() + assert node.name == "head", "Expected head got %s" % node.name + self.parser.phase = self.parser.phases["afterHead"] + + def endTagHtmlBodyBr(self, token): + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + self.endTagHead(impliedTagToken("head")) + + class InHeadNoscriptPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("basefont", "bgsound", "link", "meta", "noframes", "style"), self.startTagBaseLinkCommand), + (("head", "noscript"), self.startTagHeadNoscript), + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("noscript", self.endTagNoscript), + ("br", self.endTagBr), + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.parser.parseError("eof-in-head-noscript") + self.anythingElse() + return True + + def processComment(self, token): + return self.parser.phases["inHead"].processComment(token) + + def processCharacters(self, token): + self.parser.parseError("char-in-head-noscript") + self.anythingElse() + return token + + def processSpaceCharacters(self, token): + return self.parser.phases["inHead"].processSpaceCharacters(token) + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagBaseLinkCommand(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagHeadNoscript(self, token): + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + + def startTagOther(self, token): + self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) + self.anythingElse() + return token + + def endTagNoscript(self, token): + node = self.parser.tree.openElements.pop() + assert node.name == "noscript", "Expected noscript got %s" % node.name + self.parser.phase = self.parser.phases["inHead"] + + def endTagBr(self, token): + self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + # Caller must raise parse error first! + self.endTagNoscript(impliedTagToken("noscript")) + + class AfterHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("body", self.startTagBody), + ("frameset", self.startTagFrameset), + (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", + "style", "title"), + self.startTagFromHead), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + self.endTagHandler = _utils.MethodDispatcher([(("body", "html", "br"), + self.endTagHtmlBodyBr)]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.anythingElse() + return True + + def processCharacters(self, token): + self.anythingElse() + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagBody(self, token): + self.parser.framesetOK = False + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inBody"] + + def startTagFrameset(self, token): + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inFrameset"] + + def startTagFromHead(self, token): + self.parser.parseError("unexpected-start-tag-out-of-my-head", + {"name": token["name"]}) + self.tree.openElements.append(self.tree.headPointer) + self.parser.phases["inHead"].processStartTag(token) + for node in self.tree.openElements[::-1]: + if node.name == "head": + self.tree.openElements.remove(node) + break + + def startTagHead(self, token): + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + + def startTagOther(self, token): + self.anythingElse() + return token + + def endTagHtmlBodyBr(self, token): + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + self.tree.insertElement(impliedTagToken("body", "StartTag")) + self.parser.phase = self.parser.phases["inBody"] + self.parser.framesetOK = True + + class InBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody + # the really-really-really-very crazy mode + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + # Set this to the default handler + self.processSpaceCharacters = self.processSpaceCharactersNonPre + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("base", "basefont", "bgsound", "command", "link", "meta", + "script", "style", "title"), + self.startTagProcessInHead), + ("body", self.startTagBody), + ("frameset", self.startTagFrameset), + (("address", "article", "aside", "blockquote", "center", "details", + "dir", "div", "dl", "fieldset", "figcaption", "figure", + "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", + "section", "summary", "ul"), + self.startTagCloseP), + (headingElements, self.startTagHeading), + (("pre", "listing"), self.startTagPreListing), + ("form", self.startTagForm), + (("li", "dd", "dt"), self.startTagListItem), + ("plaintext", self.startTagPlaintext), + ("a", self.startTagA), + (("b", "big", "code", "em", "font", "i", "s", "small", "strike", + "strong", "tt", "u"), self.startTagFormatting), + ("nobr", self.startTagNobr), + ("button", self.startTagButton), + (("applet", "marquee", "object"), self.startTagAppletMarqueeObject), + ("xmp", self.startTagXmp), + ("table", self.startTagTable), + (("area", "br", "embed", "img", "keygen", "wbr"), + self.startTagVoidFormatting), + (("param", "source", "track"), self.startTagParamSource), + ("input", self.startTagInput), + ("hr", self.startTagHr), + ("image", self.startTagImage), + ("isindex", self.startTagIsIndex), + ("textarea", self.startTagTextarea), + ("iframe", self.startTagIFrame), + ("noscript", self.startTagNoscript), + (("noembed", "noframes"), self.startTagRawtext), + ("select", self.startTagSelect), + (("rp", "rt"), self.startTagRpRt), + (("option", "optgroup"), self.startTagOpt), + (("math"), self.startTagMath), + (("svg"), self.startTagSvg), + (("caption", "col", "colgroup", "frame", "head", + "tbody", "td", "tfoot", "th", "thead", + "tr"), self.startTagMisplaced) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("body", self.endTagBody), + ("html", self.endTagHtml), + (("address", "article", "aside", "blockquote", "button", "center", + "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", + "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", + "section", "summary", "ul"), self.endTagBlock), + ("form", self.endTagForm), + ("p", self.endTagP), + (("dd", "dt", "li"), self.endTagListItem), + (headingElements, self.endTagHeading), + (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", + "strike", "strong", "tt", "u"), self.endTagFormatting), + (("applet", "marquee", "object"), self.endTagAppletMarqueeObject), + ("br", self.endTagBr), + ]) + self.endTagHandler.default = self.endTagOther + + def isMatchingFormattingElement(self, node1, node2): + return (node1.name == node2.name and + node1.namespace == node2.namespace and + node1.attributes == node2.attributes) + + # helper + def addFormattingElement(self, token): + self.tree.insertElement(token) + element = self.tree.openElements[-1] + + matchingElements = [] + for node in self.tree.activeFormattingElements[::-1]: + if node is Marker: + break + elif self.isMatchingFormattingElement(node, element): + matchingElements.append(node) + + assert len(matchingElements) <= 3 + if len(matchingElements) == 3: + self.tree.activeFormattingElements.remove(matchingElements[-1]) + self.tree.activeFormattingElements.append(element) + + # the real deal + def processEOF(self): + allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td", + "tfoot", "th", "thead", "tr", "body", + "html")) + for node in self.tree.openElements[::-1]: + if node.name not in allowed_elements: + self.parser.parseError("expected-closing-tag-but-got-eof") + break + # Stop parsing + + def processSpaceCharactersDropNewline(self, token): + # Sometimes (start of <pre>, <listing>, and <textarea> blocks) we + # want to drop leading newlines + data = token["data"] + self.processSpaceCharacters = self.processSpaceCharactersNonPre + if (data.startswith("\n") and + self.tree.openElements[-1].name in ("pre", "listing", "textarea") and + not self.tree.openElements[-1].hasContent()): + data = data[1:] + if data: + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(data) + + def processCharacters(self, token): + if token["data"] == "\u0000": + # The tokenizer should always emit null on its own + return + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(token["data"]) + # This must be bad for performance + if (self.parser.framesetOK and + any([char not in spaceCharacters + for char in token["data"]])): + self.parser.framesetOK = False + + def processSpaceCharactersNonPre(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(token["data"]) + + def startTagProcessInHead(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagBody(self, token): + self.parser.parseError("unexpected-start-tag", {"name": "body"}) + if (len(self.tree.openElements) == 1 or + self.tree.openElements[1].name != "body"): + assert self.parser.innerHTML + else: + self.parser.framesetOK = False + for attr, value in token["data"].items(): + if attr not in self.tree.openElements[1].attributes: + self.tree.openElements[1].attributes[attr] = value + + def startTagFrameset(self, token): + self.parser.parseError("unexpected-start-tag", {"name": "frameset"}) + if (len(self.tree.openElements) == 1 or self.tree.openElements[1].name != "body"): + assert self.parser.innerHTML + elif not self.parser.framesetOK: + pass + else: + if self.tree.openElements[1].parent: + self.tree.openElements[1].parent.removeChild(self.tree.openElements[1]) + while self.tree.openElements[-1].name != "html": + self.tree.openElements.pop() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inFrameset"] + + def startTagCloseP(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + + def startTagPreListing(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.framesetOK = False + self.processSpaceCharacters = self.processSpaceCharactersDropNewline + + def startTagForm(self, token): + if self.tree.formPointer: + self.parser.parseError("unexpected-start-tag", {"name": "form"}) + else: + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.tree.formPointer = self.tree.openElements[-1] + + def startTagListItem(self, token): + self.parser.framesetOK = False + + stopNamesMap = {"li": ["li"], + "dt": ["dt", "dd"], + "dd": ["dt", "dd"]} + stopNames = stopNamesMap[token["name"]] + for node in reversed(self.tree.openElements): + if node.name in stopNames: + self.parser.phase.processEndTag( + impliedTagToken(node.name, "EndTag")) + break + if (node.nameTuple in specialElements and + node.name not in ("address", "div", "p")): + break + + if self.tree.elementInScope("p", variant="button"): + self.parser.phase.processEndTag( + impliedTagToken("p", "EndTag")) + + self.tree.insertElement(token) + + def startTagPlaintext(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.plaintextState + + def startTagHeading(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + if self.tree.openElements[-1].name in headingElements: + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagA(self, token): + afeAElement = self.tree.elementInActiveFormattingElements("a") + if afeAElement: + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "a", "endName": "a"}) + self.endTagFormatting(impliedTagToken("a")) + if afeAElement in self.tree.openElements: + self.tree.openElements.remove(afeAElement) + if afeAElement in self.tree.activeFormattingElements: + self.tree.activeFormattingElements.remove(afeAElement) + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagFormatting(self, token): + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagNobr(self, token): + self.tree.reconstructActiveFormattingElements() + if self.tree.elementInScope("nobr"): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "nobr", "endName": "nobr"}) + self.processEndTag(impliedTagToken("nobr")) + # XXX Need tests that trigger the following + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagButton(self, token): + if self.tree.elementInScope("button"): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "button", "endName": "button"}) + self.processEndTag(impliedTagToken("button")) + return token + else: + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.parser.framesetOK = False + + def startTagAppletMarqueeObject(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.tree.activeFormattingElements.append(Marker) + self.parser.framesetOK = False + + def startTagXmp(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.reconstructActiveFormattingElements() + self.parser.framesetOK = False + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagTable(self, token): + if self.parser.compatMode != "quirks": + if self.tree.elementInScope("p", variant="button"): + self.processEndTag(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.framesetOK = False + self.parser.phase = self.parser.phases["inTable"] + + def startTagVoidFormatting(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + self.parser.framesetOK = False + + def startTagInput(self, token): + framesetOK = self.parser.framesetOK + self.startTagVoidFormatting(token) + if ("type" in token["data"] and + token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): + # input type=hidden doesn't change framesetOK + self.parser.framesetOK = framesetOK + + def startTagParamSource(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagHr(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + self.parser.framesetOK = False + + def startTagImage(self, token): + # No really... + self.parser.parseError("unexpected-start-tag-treated-as", + {"originalName": "image", "newName": "img"}) + self.processStartTag(impliedTagToken("img", "StartTag", + attributes=token["data"], + selfClosing=token["selfClosing"])) + + def startTagIsIndex(self, token): + self.parser.parseError("deprecated-tag", {"name": "isindex"}) + if self.tree.formPointer: + return + form_attrs = {} + if "action" in token["data"]: + form_attrs["action"] = token["data"]["action"] + self.processStartTag(impliedTagToken("form", "StartTag", + attributes=form_attrs)) + self.processStartTag(impliedTagToken("hr", "StartTag")) + self.processStartTag(impliedTagToken("label", "StartTag")) + # XXX Localization ... + if "prompt" in token["data"]: + prompt = token["data"]["prompt"] + else: + prompt = "This is a searchable index. Enter search keywords: " + self.processCharacters( + {"type": tokenTypes["Characters"], "data": prompt}) + attributes = token["data"].copy() + if "action" in attributes: + del attributes["action"] + if "prompt" in attributes: + del attributes["prompt"] + attributes["name"] = "isindex" + self.processStartTag(impliedTagToken("input", "StartTag", + attributes=attributes, + selfClosing=token["selfClosing"])) + self.processEndTag(impliedTagToken("label")) + self.processStartTag(impliedTagToken("hr", "StartTag")) + self.processEndTag(impliedTagToken("form")) + + def startTagTextarea(self, token): + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.rcdataState + self.processSpaceCharacters = self.processSpaceCharactersDropNewline + self.parser.framesetOK = False + + def startTagIFrame(self, token): + self.parser.framesetOK = False + self.startTagRawtext(token) + + def startTagNoscript(self, token): + if self.parser.scripting: + self.startTagRawtext(token) + else: + self.startTagOther(token) + + def startTagRawtext(self, token): + """iframe, noembed noframes, noscript(if scripting enabled)""" + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagOpt(self, token): + if self.tree.openElements[-1].name == "option": + self.parser.phase.processEndTag(impliedTagToken("option")) + self.tree.reconstructActiveFormattingElements() + self.parser.tree.insertElement(token) + + def startTagSelect(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.parser.framesetOK = False + if self.parser.phase in (self.parser.phases["inTable"], + self.parser.phases["inCaption"], + self.parser.phases["inColumnGroup"], + self.parser.phases["inTableBody"], + self.parser.phases["inRow"], + self.parser.phases["inCell"]): + self.parser.phase = self.parser.phases["inSelectInTable"] + else: + self.parser.phase = self.parser.phases["inSelect"] + + def startTagRpRt(self, token): + if self.tree.elementInScope("ruby"): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "ruby": + self.parser.parseError() + self.tree.insertElement(token) + + def startTagMath(self, token): + self.tree.reconstructActiveFormattingElements() + self.parser.adjustMathMLAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = namespaces["mathml"] + self.tree.insertElement(token) + # Need to get the parse error right for the case where the token + # has a namespace not equal to the xmlns attribute + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagSvg(self, token): + self.tree.reconstructActiveFormattingElements() + self.parser.adjustSVGAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = namespaces["svg"] + self.tree.insertElement(token) + # Need to get the parse error right for the case where the token + # has a namespace not equal to the xmlns attribute + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagMisplaced(self, token): + """ Elements that should be children of other elements that have a + different insertion mode; here they are ignored + "caption", "col", "colgroup", "frame", "frameset", "head", + "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", + "tr", "noscript" + """ + self.parser.parseError("unexpected-start-tag-ignored", {"name": token["name"]}) + + def startTagOther(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + + def endTagP(self, token): + if not self.tree.elementInScope("p", variant="button"): + self.startTagCloseP(impliedTagToken("p", "StartTag")) + self.parser.parseError("unexpected-end-tag", {"name": "p"}) + self.endTagP(impliedTagToken("p", "EndTag")) + else: + self.tree.generateImpliedEndTags("p") + if self.tree.openElements[-1].name != "p": + self.parser.parseError("unexpected-end-tag", {"name": "p"}) + node = self.tree.openElements.pop() + while node.name != "p": + node = self.tree.openElements.pop() + + def endTagBody(self, token): + if not self.tree.elementInScope("body"): + self.parser.parseError() + return + elif self.tree.openElements[-1].name != "body": + for node in self.tree.openElements[2:]: + if node.name not in frozenset(("dd", "dt", "li", "optgroup", + "option", "p", "rp", "rt", + "tbody", "td", "tfoot", + "th", "thead", "tr", "body", + "html")): + # Not sure this is the correct name for the parse error + self.parser.parseError( + "expected-one-end-tag-but-got-another", + {"gotName": "body", "expectedName": node.name}) + break + self.parser.phase = self.parser.phases["afterBody"] + + def endTagHtml(self, token): + # We repeat the test for the body end tag token being ignored here + if self.tree.elementInScope("body"): + self.endTagBody(impliedTagToken("body")) + return token + + def endTagBlock(self, token): + # Put us back in the right whitespace handling mode + if token["name"] == "pre": + self.processSpaceCharacters = self.processSpaceCharactersNonPre + inScope = self.tree.elementInScope(token["name"]) + if inScope: + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + if inScope: + node = self.tree.openElements.pop() + while node.name != token["name"]: + node = self.tree.openElements.pop() + + def endTagForm(self, token): + node = self.tree.formPointer + self.tree.formPointer = None + if node is None or not self.tree.elementInScope(node): + self.parser.parseError("unexpected-end-tag", + {"name": "form"}) + else: + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1] != node: + self.parser.parseError("end-tag-too-early-ignored", + {"name": "form"}) + self.tree.openElements.remove(node) + + def endTagListItem(self, token): + if token["name"] == "li": + variant = "list" + else: + variant = None + if not self.tree.elementInScope(token["name"], variant=variant): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + else: + self.tree.generateImpliedEndTags(exclude=token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError( + "end-tag-too-early", + {"name": token["name"]}) + node = self.tree.openElements.pop() + while node.name != token["name"]: + node = self.tree.openElements.pop() + + def endTagHeading(self, token): + for item in headingElements: + if self.tree.elementInScope(item): + self.tree.generateImpliedEndTags() + break + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + + for item in headingElements: + if self.tree.elementInScope(item): + item = self.tree.openElements.pop() + while item.name not in headingElements: + item = self.tree.openElements.pop() + break + + def endTagFormatting(self, token): + """The much-feared adoption agency algorithm""" + # http://svn.whatwg.org/webapps/complete.html#adoptionAgency revision 7867 + # XXX Better parseError messages appreciated. + + # Step 1 + outerLoopCounter = 0 + + # Step 2 + while outerLoopCounter < 8: + + # Step 3 + outerLoopCounter += 1 + + # Step 4: + + # Let the formatting element be the last element in + # the list of active formatting elements that: + # - is between the end of the list and the last scope + # marker in the list, if any, or the start of the list + # otherwise, and + # - has the same tag name as the token. + formattingElement = self.tree.elementInActiveFormattingElements( + token["name"]) + if (not formattingElement or + (formattingElement in self.tree.openElements and + not self.tree.elementInScope(formattingElement.name))): + # If there is no such node, then abort these steps + # and instead act as described in the "any other + # end tag" entry below. + self.endTagOther(token) + return + + # Otherwise, if there is such a node, but that node is + # not in the stack of open elements, then this is a + # parse error; remove the element from the list, and + # abort these steps. + elif formattingElement not in self.tree.openElements: + self.parser.parseError("adoption-agency-1.2", {"name": token["name"]}) + self.tree.activeFormattingElements.remove(formattingElement) + return + + # Otherwise, if there is such a node, and that node is + # also in the stack of open elements, but the element + # is not in scope, then this is a parse error; ignore + # the token, and abort these steps. + elif not self.tree.elementInScope(formattingElement.name): + self.parser.parseError("adoption-agency-4.4", {"name": token["name"]}) + return + + # Otherwise, there is a formatting element and that + # element is in the stack and is in scope. If the + # element is not the current node, this is a parse + # error. In any case, proceed with the algorithm as + # written in the following steps. + else: + if formattingElement != self.tree.openElements[-1]: + self.parser.parseError("adoption-agency-1.3", {"name": token["name"]}) + + # Step 5: + + # Let the furthest block be the topmost node in the + # stack of open elements that is lower in the stack + # than the formatting element, and is an element in + # the special category. There might not be one. + afeIndex = self.tree.openElements.index(formattingElement) + furthestBlock = None + for element in self.tree.openElements[afeIndex:]: + if element.nameTuple in specialElements: + furthestBlock = element + break + + # Step 6: + + # If there is no furthest block, then the UA must + # first pop all the nodes from the bottom of the stack + # of open elements, from the current node up to and + # including the formatting element, then remove the + # formatting element from the list of active + # formatting elements, and finally abort these steps. + if furthestBlock is None: + element = self.tree.openElements.pop() + while element != formattingElement: + element = self.tree.openElements.pop() + self.tree.activeFormattingElements.remove(element) + return + + # Step 7 + commonAncestor = self.tree.openElements[afeIndex - 1] + + # Step 8: + # The bookmark is supposed to help us identify where to reinsert + # nodes in step 15. We have to ensure that we reinsert nodes after + # the node before the active formatting element. Note the bookmark + # can move in step 9.7 + bookmark = self.tree.activeFormattingElements.index(formattingElement) + + # Step 9 + lastNode = node = furthestBlock + innerLoopCounter = 0 + + index = self.tree.openElements.index(node) + while innerLoopCounter < 3: + innerLoopCounter += 1 + # Node is element before node in open elements + index -= 1 + node = self.tree.openElements[index] + if node not in self.tree.activeFormattingElements: + self.tree.openElements.remove(node) + continue + # Step 9.6 + if node == formattingElement: + break + # Step 9.7 + if lastNode == furthestBlock: + bookmark = self.tree.activeFormattingElements.index(node) + 1 + # Step 9.8 + clone = node.cloneNode() + # Replace node with clone + self.tree.activeFormattingElements[ + self.tree.activeFormattingElements.index(node)] = clone + self.tree.openElements[ + self.tree.openElements.index(node)] = clone + node = clone + # Step 9.9 + # Remove lastNode from its parents, if any + if lastNode.parent: + lastNode.parent.removeChild(lastNode) + node.appendChild(lastNode) + # Step 9.10 + lastNode = node + + # Step 10 + # Foster parent lastNode if commonAncestor is a + # table, tbody, tfoot, thead, or tr we need to foster + # parent the lastNode + if lastNode.parent: + lastNode.parent.removeChild(lastNode) + + if commonAncestor.name in frozenset(("table", "tbody", "tfoot", "thead", "tr")): + parent, insertBefore = self.tree.getTableMisnestedNodePosition() + parent.insertBefore(lastNode, insertBefore) + else: + commonAncestor.appendChild(lastNode) + + # Step 11 + clone = formattingElement.cloneNode() + + # Step 12 + furthestBlock.reparentChildren(clone) + + # Step 13 + furthestBlock.appendChild(clone) + + # Step 14 + self.tree.activeFormattingElements.remove(formattingElement) + self.tree.activeFormattingElements.insert(bookmark, clone) + + # Step 15 + self.tree.openElements.remove(formattingElement) + self.tree.openElements.insert( + self.tree.openElements.index(furthestBlock) + 1, clone) + + def endTagAppletMarqueeObject(self, token): + if self.tree.elementInScope(token["name"]): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + + if self.tree.elementInScope(token["name"]): + element = self.tree.openElements.pop() + while element.name != token["name"]: + element = self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + + def endTagBr(self, token): + self.parser.parseError("unexpected-end-tag-treated-as", + {"originalName": "br", "newName": "br element"}) + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(impliedTagToken("br", "StartTag")) + self.tree.openElements.pop() + + def endTagOther(self, token): + for node in self.tree.openElements[::-1]: + if node.name == token["name"]: + self.tree.generateImpliedEndTags(exclude=token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + while self.tree.openElements.pop() != node: + pass + break + else: + if node.nameTuple in specialElements: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + break + + class TextPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([]) + self.startTagHandler.default = self.startTagOther + self.endTagHandler = _utils.MethodDispatcher([ + ("script", self.endTagScript)]) + self.endTagHandler.default = self.endTagOther + + def processCharacters(self, token): + self.tree.insertText(token["data"]) + + def processEOF(self): + self.parser.parseError("expected-named-closing-tag-but-got-eof", + {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + self.parser.phase = self.parser.originalPhase + return True + + def startTagOther(self, token): + assert False, "Tried to process start tag %s in RCDATA/RAWTEXT mode" % token['name'] + + def endTagScript(self, token): + node = self.tree.openElements.pop() + assert node.name == "script" + self.parser.phase = self.parser.originalPhase + # The rest of this method is all stuff that only happens if + # document.write works + + def endTagOther(self, token): + self.tree.openElements.pop() + self.parser.phase = self.parser.originalPhase + + class InTablePhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-table + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("caption", self.startTagCaption), + ("colgroup", self.startTagColgroup), + ("col", self.startTagCol), + (("tbody", "tfoot", "thead"), self.startTagRowGroup), + (("td", "th", "tr"), self.startTagImplyTbody), + ("table", self.startTagTable), + (("style", "script"), self.startTagStyleScript), + ("input", self.startTagInput), + ("form", self.startTagForm) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("table", self.endTagTable), + (("body", "caption", "col", "colgroup", "html", "tbody", "td", + "tfoot", "th", "thead", "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods + def clearStackToTableContext(self): + # "clear the stack back to a table context" + while self.tree.openElements[-1].name not in ("table", "html"): + # self.parser.parseError("unexpected-implied-end-tag-in-table", + # {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + # When the current node is <html> it's an innerHTML case + + # processing methods + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-table") + else: + assert self.parser.innerHTML + # Stop parsing + + def processSpaceCharacters(self, token): + originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["inTableText"] + self.parser.phase.originalPhase = originalPhase + self.parser.phase.processSpaceCharacters(token) + + def processCharacters(self, token): + originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["inTableText"] + self.parser.phase.originalPhase = originalPhase + self.parser.phase.processCharacters(token) + + def insertText(self, token): + # If we get here there must be at least one non-whitespace character + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processCharacters(token) + self.tree.insertFromTable = False + + def startTagCaption(self, token): + self.clearStackToTableContext() + self.tree.activeFormattingElements.append(Marker) + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inCaption"] + + def startTagColgroup(self, token): + self.clearStackToTableContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inColumnGroup"] + + def startTagCol(self, token): + self.startTagColgroup(impliedTagToken("colgroup", "StartTag")) + return token + + def startTagRowGroup(self, token): + self.clearStackToTableContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inTableBody"] + + def startTagImplyTbody(self, token): + self.startTagRowGroup(impliedTagToken("tbody", "StartTag")) + return token + + def startTagTable(self, token): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "table", "endName": "table"}) + self.parser.phase.processEndTag(impliedTagToken("table")) + if not self.parser.innerHTML: + return token + + def startTagStyleScript(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagInput(self, token): + if ("type" in token["data"] and + token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): + self.parser.parseError("unexpected-hidden-input-in-table") + self.tree.insertElement(token) + # XXX associate with form + self.tree.openElements.pop() + else: + self.startTagOther(token) + + def startTagForm(self, token): + self.parser.parseError("unexpected-form-in-table") + if self.tree.formPointer is None: + self.tree.insertElement(token) + self.tree.formPointer = self.tree.openElements[-1] + self.tree.openElements.pop() + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-implies-table-voodoo", {"name": token["name"]}) + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processStartTag(token) + self.tree.insertFromTable = False + + def endTagTable(self, token): + if self.tree.elementInScope("table", variant="table"): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "table": + self.parser.parseError("end-tag-too-early-named", + {"gotName": "table", + "expectedName": self.tree.openElements[-1].name}) + while self.tree.openElements[-1].name != "table": + self.tree.openElements.pop() + self.tree.openElements.pop() + self.parser.resetInsertionMode() + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-implies-table-voodoo", {"name": token["name"]}) + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processEndTag(token) + self.tree.insertFromTable = False + + class InTableTextPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.originalPhase = None + self.characterTokens = [] + + def flushCharacters(self): + data = "".join([item["data"] for item in self.characterTokens]) + if any([item not in spaceCharacters for item in data]): + token = {"type": tokenTypes["Characters"], "data": data} + self.parser.phases["inTable"].insertText(token) + elif data: + self.tree.insertText(data) + self.characterTokens = [] + + def processComment(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + def processEOF(self): + self.flushCharacters() + self.parser.phase = self.originalPhase + return True + + def processCharacters(self, token): + if token["data"] == "\u0000": + return + self.characterTokens.append(token) + + def processSpaceCharacters(self, token): + # pretty sure we should never reach here + self.characterTokens.append(token) + # assert False + + def processStartTag(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + def processEndTag(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + class InCaptionPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-caption + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.startTagTableElement) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("caption", self.endTagCaption), + ("table", self.endTagTable), + (("body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + def ignoreEndTagCaption(self): + return not self.tree.elementInScope("caption", variant="table") + + def processEOF(self): + self.parser.phases["inBody"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inBody"].processCharacters(token) + + def startTagTableElement(self, token): + self.parser.parseError() + # XXX Have to duplicate logic here to find out if the tag is ignored + ignoreEndTag = self.ignoreEndTagCaption() + self.parser.phase.processEndTag(impliedTagToken("caption")) + if not ignoreEndTag: + return token + + def startTagOther(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def endTagCaption(self, token): + if not self.ignoreEndTagCaption(): + # AT this code is quite similar to endTagTable in "InTable" + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "caption": + self.parser.parseError("expected-one-end-tag-but-got-another", + {"gotName": "caption", + "expectedName": self.tree.openElements[-1].name}) + while self.tree.openElements[-1].name != "caption": + self.tree.openElements.pop() + self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + self.parser.phase = self.parser.phases["inTable"] + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagTable(self, token): + self.parser.parseError() + ignoreEndTag = self.ignoreEndTagCaption() + self.parser.phase.processEndTag(impliedTagToken("caption")) + if not ignoreEndTag: + return token + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inBody"].processEndTag(token) + + class InColumnGroupPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-column + + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("col", self.startTagCol) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("colgroup", self.endTagColgroup), + ("col", self.endTagCol) + ]) + self.endTagHandler.default = self.endTagOther + + def ignoreEndTagColgroup(self): + return self.tree.openElements[-1].name == "html" + + def processEOF(self): + if self.tree.openElements[-1].name == "html": + assert self.parser.innerHTML + return + else: + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return True + + def processCharacters(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + def startTagCol(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagOther(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + def endTagColgroup(self, token): + if self.ignoreEndTagColgroup(): + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + else: + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTable"] + + def endTagCol(self, token): + self.parser.parseError("no-end-tag", {"name": "col"}) + + def endTagOther(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + class InTableBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-table0 + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("tr", self.startTagTr), + (("td", "th"), self.startTagTableCell), + (("caption", "col", "colgroup", "tbody", "tfoot", "thead"), + self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), + ("table", self.endTagTable), + (("body", "caption", "col", "colgroup", "html", "td", "th", + "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods + def clearStackToTableBodyContext(self): + while self.tree.openElements[-1].name not in ("tbody", "tfoot", + "thead", "html"): + # self.parser.parseError("unexpected-implied-end-tag-in-table", + # {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + if self.tree.openElements[-1].name == "html": + assert self.parser.innerHTML + + # the rest + def processEOF(self): + self.parser.phases["inTable"].processEOF() + + def processSpaceCharacters(self, token): + return self.parser.phases["inTable"].processSpaceCharacters(token) + + def processCharacters(self, token): + return self.parser.phases["inTable"].processCharacters(token) + + def startTagTr(self, token): + self.clearStackToTableBodyContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inRow"] + + def startTagTableCell(self, token): + self.parser.parseError("unexpected-cell-in-table-body", + {"name": token["name"]}) + self.startTagTr(impliedTagToken("tr", "StartTag")) + return token + + def startTagTableOther(self, token): + # XXX AT Any ideas on how to share this with endTagTable? + if (self.tree.elementInScope("tbody", variant="table") or + self.tree.elementInScope("thead", variant="table") or + self.tree.elementInScope("tfoot", variant="table")): + self.clearStackToTableBodyContext() + self.endTagTableRowGroup( + impliedTagToken(self.tree.openElements[-1].name)) + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def startTagOther(self, token): + return self.parser.phases["inTable"].processStartTag(token) + + def endTagTableRowGroup(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.clearStackToTableBodyContext() + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTable"] + else: + self.parser.parseError("unexpected-end-tag-in-table-body", + {"name": token["name"]}) + + def endTagTable(self, token): + if (self.tree.elementInScope("tbody", variant="table") or + self.tree.elementInScope("thead", variant="table") or + self.tree.elementInScope("tfoot", variant="table")): + self.clearStackToTableBodyContext() + self.endTagTableRowGroup( + impliedTagToken(self.tree.openElements[-1].name)) + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag-in-table-body", + {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inTable"].processEndTag(token) + + class InRowPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-row + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("td", "th"), self.startTagTableCell), + (("caption", "col", "colgroup", "tbody", "tfoot", "thead", + "tr"), self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("tr", self.endTagTr), + ("table", self.endTagTable), + (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), + (("body", "caption", "col", "colgroup", "html", "td", "th"), + self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods (XXX unify this with other table helper methods) + def clearStackToTableRowContext(self): + while self.tree.openElements[-1].name not in ("tr", "html"): + self.parser.parseError("unexpected-implied-end-tag-in-table-row", + {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + + def ignoreEndTagTr(self): + return not self.tree.elementInScope("tr", variant="table") + + # the rest + def processEOF(self): + self.parser.phases["inTable"].processEOF() + + def processSpaceCharacters(self, token): + return self.parser.phases["inTable"].processSpaceCharacters(token) + + def processCharacters(self, token): + return self.parser.phases["inTable"].processCharacters(token) + + def startTagTableCell(self, token): + self.clearStackToTableRowContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inCell"] + self.tree.activeFormattingElements.append(Marker) + + def startTagTableOther(self, token): + ignoreEndTag = self.ignoreEndTagTr() + self.endTagTr(impliedTagToken("tr")) + # XXX how are we sure it's always ignored in the innerHTML case? + if not ignoreEndTag: + return token + + def startTagOther(self, token): + return self.parser.phases["inTable"].processStartTag(token) + + def endTagTr(self, token): + if not self.ignoreEndTagTr(): + self.clearStackToTableRowContext() + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTableBody"] + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagTable(self, token): + ignoreEndTag = self.ignoreEndTagTr() + self.endTagTr(impliedTagToken("tr")) + # Reprocess the current tag if the tr end tag was not ignored + # XXX how are we sure it's always ignored in the innerHTML case? + if not ignoreEndTag: + return token + + def endTagTableRowGroup(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.endTagTr(impliedTagToken("tr")) + return token + else: + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag-in-table-row", + {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inTable"].processEndTag(token) + + class InCellPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-cell + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("td", "th"), self.endTagTableCell), + (("body", "caption", "col", "colgroup", "html"), self.endTagIgnore), + (("table", "tbody", "tfoot", "thead", "tr"), self.endTagImply) + ]) + self.endTagHandler.default = self.endTagOther + + # helper + def closeCell(self): + if self.tree.elementInScope("td", variant="table"): + self.endTagTableCell(impliedTagToken("td")) + elif self.tree.elementInScope("th", variant="table"): + self.endTagTableCell(impliedTagToken("th")) + + # the rest + def processEOF(self): + self.parser.phases["inBody"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inBody"].processCharacters(token) + + def startTagTableOther(self, token): + if (self.tree.elementInScope("td", variant="table") or + self.tree.elementInScope("th", variant="table")): + self.closeCell() + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def startTagOther(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def endTagTableCell(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.tree.generateImpliedEndTags(token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("unexpected-cell-end-tag", + {"name": token["name"]}) + while True: + node = self.tree.openElements.pop() + if node.name == token["name"]: + break + else: + self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + self.parser.phase = self.parser.phases["inRow"] + else: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagImply(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.closeCell() + return token + else: + # sometimes innerHTML case + self.parser.parseError() + + def endTagOther(self, token): + return self.parser.phases["inBody"].processEndTag(token) + + class InSelectPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("option", self.startTagOption), + ("optgroup", self.startTagOptgroup), + ("select", self.startTagSelect), + (("input", "keygen", "textarea"), self.startTagInput), + ("script", self.startTagScript) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("option", self.endTagOption), + ("optgroup", self.endTagOptgroup), + ("select", self.endTagSelect) + ]) + self.endTagHandler.default = self.endTagOther + + # http://www.whatwg.org/specs/web-apps/current-work/#in-select + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-select") + else: + assert self.parser.innerHTML + + def processCharacters(self, token): + if token["data"] == "\u0000": + return + self.tree.insertText(token["data"]) + + def startTagOption(self, token): + # We need to imply </option> if <option> is the current node. + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagOptgroup(self, token): + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + if self.tree.openElements[-1].name == "optgroup": + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagSelect(self, token): + self.parser.parseError("unexpected-select-in-select") + self.endTagSelect(impliedTagToken("select")) + + def startTagInput(self, token): + self.parser.parseError("unexpected-input-in-select") + if self.tree.elementInScope("select", variant="select"): + self.endTagSelect(impliedTagToken("select")) + return token + else: + assert self.parser.innerHTML + + def startTagScript(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-in-select", + {"name": token["name"]}) + + def endTagOption(self, token): + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + else: + self.parser.parseError("unexpected-end-tag-in-select", + {"name": "option"}) + + def endTagOptgroup(self, token): + # </optgroup> implicitly closes <option> + if (self.tree.openElements[-1].name == "option" and + self.tree.openElements[-2].name == "optgroup"): + self.tree.openElements.pop() + # It also closes </optgroup> + if self.tree.openElements[-1].name == "optgroup": + self.tree.openElements.pop() + # But nothing else + else: + self.parser.parseError("unexpected-end-tag-in-select", + {"name": "optgroup"}) + + def endTagSelect(self, token): + if self.tree.elementInScope("select", variant="select"): + node = self.tree.openElements.pop() + while node.name != "select": + node = self.tree.openElements.pop() + self.parser.resetInsertionMode() + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-in-select", + {"name": token["name"]}) + + class InSelectInTablePhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), + self.startTagTable) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), + self.endTagTable) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.parser.phases["inSelect"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inSelect"].processCharacters(token) + + def startTagTable(self, token): + self.parser.parseError("unexpected-table-element-start-tag-in-select-in-table", {"name": token["name"]}) + self.endTagOther(impliedTagToken("select")) + return token + + def startTagOther(self, token): + return self.parser.phases["inSelect"].processStartTag(token) + + def endTagTable(self, token): + self.parser.parseError("unexpected-table-element-end-tag-in-select-in-table", {"name": token["name"]}) + if self.tree.elementInScope(token["name"], variant="table"): + self.endTagOther(impliedTagToken("select")) + return token + + def endTagOther(self, token): + return self.parser.phases["inSelect"].processEndTag(token) + + class InForeignContentPhase(Phase): + breakoutElements = frozenset(["b", "big", "blockquote", "body", "br", + "center", "code", "dd", "div", "dl", "dt", + "em", "embed", "h1", "h2", "h3", + "h4", "h5", "h6", "head", "hr", "i", "img", + "li", "listing", "menu", "meta", "nobr", + "ol", "p", "pre", "ruby", "s", "small", + "span", "strong", "strike", "sub", "sup", + "table", "tt", "u", "ul", "var"]) + + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + def adjustSVGTagNames(self, token): + replacements = {"altglyph": "altGlyph", + "altglyphdef": "altGlyphDef", + "altglyphitem": "altGlyphItem", + "animatecolor": "animateColor", + "animatemotion": "animateMotion", + "animatetransform": "animateTransform", + "clippath": "clipPath", + "feblend": "feBlend", + "fecolormatrix": "feColorMatrix", + "fecomponenttransfer": "feComponentTransfer", + "fecomposite": "feComposite", + "feconvolvematrix": "feConvolveMatrix", + "fediffuselighting": "feDiffuseLighting", + "fedisplacementmap": "feDisplacementMap", + "fedistantlight": "feDistantLight", + "feflood": "feFlood", + "fefunca": "feFuncA", + "fefuncb": "feFuncB", + "fefuncg": "feFuncG", + "fefuncr": "feFuncR", + "fegaussianblur": "feGaussianBlur", + "feimage": "feImage", + "femerge": "feMerge", + "femergenode": "feMergeNode", + "femorphology": "feMorphology", + "feoffset": "feOffset", + "fepointlight": "fePointLight", + "fespecularlighting": "feSpecularLighting", + "fespotlight": "feSpotLight", + "fetile": "feTile", + "feturbulence": "feTurbulence", + "foreignobject": "foreignObject", + "glyphref": "glyphRef", + "lineargradient": "linearGradient", + "radialgradient": "radialGradient", + "textpath": "textPath"} + + if token["name"] in replacements: + token["name"] = replacements[token["name"]] + + def processCharacters(self, token): + if token["data"] == "\u0000": + token["data"] = "\uFFFD" + elif (self.parser.framesetOK and + any(char not in spaceCharacters for char in token["data"])): + self.parser.framesetOK = False + Phase.processCharacters(self, token) + + def processStartTag(self, token): + currentNode = self.tree.openElements[-1] + if (token["name"] in self.breakoutElements or + (token["name"] == "font" and + set(token["data"].keys()) & set(["color", "face", "size"]))): + self.parser.parseError("unexpected-html-element-in-foreign-content", + {"name": token["name"]}) + while (self.tree.openElements[-1].namespace != + self.tree.defaultNamespace and + not self.parser.isHTMLIntegrationPoint(self.tree.openElements[-1]) and + not self.parser.isMathMLTextIntegrationPoint(self.tree.openElements[-1])): + self.tree.openElements.pop() + return token + + else: + if currentNode.namespace == namespaces["mathml"]: + self.parser.adjustMathMLAttributes(token) + elif currentNode.namespace == namespaces["svg"]: + self.adjustSVGTagNames(token) + self.parser.adjustSVGAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = currentNode.namespace + self.tree.insertElement(token) + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def processEndTag(self, token): + nodeIndex = len(self.tree.openElements) - 1 + node = self.tree.openElements[-1] + if node.name.translate(asciiUpper2Lower) != token["name"]: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + while True: + if node.name.translate(asciiUpper2Lower) == token["name"]: + # XXX this isn't in the spec but it seems necessary + if self.parser.phase == self.parser.phases["inTableText"]: + self.parser.phase.flushCharacters() + self.parser.phase = self.parser.phase.originalPhase + while self.tree.openElements.pop() != node: + assert self.tree.openElements + new_token = None + break + nodeIndex -= 1 + + node = self.tree.openElements[nodeIndex] + if node.namespace != self.tree.defaultNamespace: + continue + else: + new_token = self.parser.phase.processEndTag(token) + break + return new_token + + class AfterBodyPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([("html", self.endTagHtml)]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + # Stop parsing + pass + + def processComment(self, token): + # This is needed because data is to be appended to the <html> element + # here and not to whatever is currently open. + self.tree.insertComment(token, self.tree.openElements[0]) + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-after-body") + self.parser.phase = self.parser.phases["inBody"] + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-after-body", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + def endTagHtml(self, name): + if self.parser.innerHTML: + self.parser.parseError("unexpected-end-tag-after-body-innerhtml") + else: + self.parser.phase = self.parser.phases["afterAfterBody"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-after-body", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + class InFramesetPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-frameset + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("frameset", self.startTagFrameset), + ("frame", self.startTagFrame), + ("noframes", self.startTagNoframes) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("frameset", self.endTagFrameset) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-frameset") + else: + assert self.parser.innerHTML + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-in-frameset") + + def startTagFrameset(self, token): + self.tree.insertElement(token) + + def startTagFrame(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + + def startTagNoframes(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-in-frameset", + {"name": token["name"]}) + + def endTagFrameset(self, token): + if self.tree.openElements[-1].name == "html": + # innerHTML case + self.parser.parseError("unexpected-frameset-in-frameset-innerhtml") + else: + self.tree.openElements.pop() + if (not self.parser.innerHTML and + self.tree.openElements[-1].name != "frameset"): + # If we're not in innerHTML mode and the current node is not a + # "frameset" element (anymore) then switch. + self.parser.phase = self.parser.phases["afterFrameset"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-in-frameset", + {"name": token["name"]}) + + class AfterFramesetPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#after3 + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("noframes", self.startTagNoframes) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("html", self.endTagHtml) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + # Stop parsing + pass + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-after-frameset") + + def startTagNoframes(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-after-frameset", + {"name": token["name"]}) + + def endTagHtml(self, token): + self.parser.phase = self.parser.phases["afterAfterFrameset"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-after-frameset", + {"name": token["name"]}) + + class AfterAfterBodyPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml) + ]) + self.startTagHandler.default = self.startTagOther + + def processEOF(self): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + return self.parser.phases["inBody"].processSpaceCharacters(token) + + def processCharacters(self, token): + self.parser.parseError("expected-eof-but-got-char") + self.parser.phase = self.parser.phases["inBody"] + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("expected-eof-but-got-start-tag", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + def processEndTag(self, token): + self.parser.parseError("expected-eof-but-got-end-tag", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + class AfterAfterFramesetPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("noframes", self.startTagNoFrames) + ]) + self.startTagHandler.default = self.startTagOther + + def processEOF(self): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + return self.parser.phases["inBody"].processSpaceCharacters(token) + + def processCharacters(self, token): + self.parser.parseError("expected-eof-but-got-char") + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagNoFrames(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("expected-eof-but-got-start-tag", + {"name": token["name"]}) + + def processEndTag(self, token): + self.parser.parseError("expected-eof-but-got-end-tag", + {"name": token["name"]}) + # pylint:enable=unused-argument + + return { + "initial": InitialPhase, + "beforeHtml": BeforeHtmlPhase, + "beforeHead": BeforeHeadPhase, + "inHead": InHeadPhase, + "inHeadNoscript": InHeadNoscriptPhase, + "afterHead": AfterHeadPhase, + "inBody": InBodyPhase, + "text": TextPhase, + "inTable": InTablePhase, + "inTableText": InTableTextPhase, + "inCaption": InCaptionPhase, + "inColumnGroup": InColumnGroupPhase, + "inTableBody": InTableBodyPhase, + "inRow": InRowPhase, + "inCell": InCellPhase, + "inSelect": InSelectPhase, + "inSelectInTable": InSelectInTablePhase, + "inForeignContent": InForeignContentPhase, + "afterBody": AfterBodyPhase, + "inFrameset": InFramesetPhase, + "afterFrameset": AfterFramesetPhase, + "afterAfterBody": AfterAfterBodyPhase, + "afterAfterFrameset": AfterAfterFramesetPhase, + # XXX after after frameset + } + + +def adjust_attributes(token, replacements): + needs_adjustment = viewkeys(token['data']) & viewkeys(replacements) + if needs_adjustment: + token['data'] = OrderedDict((replacements.get(k, k), v) + for k, v in token['data'].items()) + + +def impliedTagToken(name, type="EndTag", attributes=None, + selfClosing=False): + if attributes is None: + attributes = {} + return {"type": tokenTypes[type], "name": name, "data": attributes, + "selfClosing": selfClosing} + + +class ParseError(Exception): + """Error in parsed document""" + pass diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/serializer.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/serializer.py new file mode 100644 index 0000000..53f4d44 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/serializer.py @@ -0,0 +1,409 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +import re + +from codecs import register_error, xmlcharrefreplace_errors + +from .constants import voidElements, booleanAttributes, spaceCharacters +from .constants import rcdataElements, entities, xmlEntities +from . import treewalkers, _utils +from xml.sax.saxutils import escape + +_quoteAttributeSpecChars = "".join(spaceCharacters) + "\"'=<>`" +_quoteAttributeSpec = re.compile("[" + _quoteAttributeSpecChars + "]") +_quoteAttributeLegacy = re.compile("[" + _quoteAttributeSpecChars + + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n" + "\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15" + "\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x2f\x60\xa0\u1680\u180e\u180f\u2000" + "\u2001\u2002\u2003\u2004\u2005\u2006\u2007" + "\u2008\u2009\u200a\u2028\u2029\u202f\u205f" + "\u3000]") + + +_encode_entity_map = {} +_is_ucs4 = len("\U0010FFFF") == 1 +for k, v in list(entities.items()): + # skip multi-character entities + if ((_is_ucs4 and len(v) > 1) or + (not _is_ucs4 and len(v) > 2)): + continue + if v != "&": + if len(v) == 2: + v = _utils.surrogatePairToCodepoint(v) + else: + v = ord(v) + if v not in _encode_entity_map or k.islower(): + # prefer < over < and similarly for &, >, etc. + _encode_entity_map[v] = k + + +def htmlentityreplace_errors(exc): + if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)): + res = [] + codepoints = [] + skip = False + for i, c in enumerate(exc.object[exc.start:exc.end]): + if skip: + skip = False + continue + index = i + exc.start + if _utils.isSurrogatePair(exc.object[index:min([exc.end, index + 2])]): + codepoint = _utils.surrogatePairToCodepoint(exc.object[index:index + 2]) + skip = True + else: + codepoint = ord(c) + codepoints.append(codepoint) + for cp in codepoints: + e = _encode_entity_map.get(cp) + if e: + res.append("&") + res.append(e) + if not e.endswith(";"): + res.append(";") + else: + res.append("&#x%s;" % (hex(cp)[2:])) + return ("".join(res), exc.end) + else: + return xmlcharrefreplace_errors(exc) + + +register_error("htmlentityreplace", htmlentityreplace_errors) + + +def serialize(input, tree="etree", encoding=None, **serializer_opts): + """Serializes the input token stream using the specified treewalker + + :arg input: the token stream to serialize + + :arg tree: the treewalker to use + + :arg encoding: the encoding to use + + :arg serializer_opts: any options to pass to the + :py:class:`html5lib.serializer.HTMLSerializer` that gets created + + :returns: the tree serialized as a string + + Example: + + >>> from html5lib.html5parser import parse + >>> from html5lib.serializer import serialize + >>> token_stream = parse('<html><body><p>Hi!</p></body></html>') + >>> serialize(token_stream, omit_optional_tags=False) + '<html><head></head><body><p>Hi!</p></body></html>' + + """ + # XXX: Should we cache this? + walker = treewalkers.getTreeWalker(tree) + s = HTMLSerializer(**serializer_opts) + return s.render(walker(input), encoding) + + +class HTMLSerializer(object): + + # attribute quoting options + quote_attr_values = "legacy" # be secure by default + quote_char = '"' + use_best_quote_char = True + + # tag syntax options + omit_optional_tags = True + minimize_boolean_attributes = True + use_trailing_solidus = False + space_before_trailing_solidus = True + + # escaping options + escape_lt_in_attrs = False + escape_rcdata = False + resolve_entities = True + + # miscellaneous options + alphabetical_attributes = False + inject_meta_charset = True + strip_whitespace = False + sanitize = False + + options = ("quote_attr_values", "quote_char", "use_best_quote_char", + "omit_optional_tags", "minimize_boolean_attributes", + "use_trailing_solidus", "space_before_trailing_solidus", + "escape_lt_in_attrs", "escape_rcdata", "resolve_entities", + "alphabetical_attributes", "inject_meta_charset", + "strip_whitespace", "sanitize") + + def __init__(self, **kwargs): + """Initialize HTMLSerializer + + :arg inject_meta_charset: Whether or not to inject the meta charset. + + Defaults to ``True``. + + :arg quote_attr_values: Whether to quote attribute values that don't + require quoting per legacy browser behavior (``"legacy"``), when + required by the standard (``"spec"``), or always (``"always"``). + + Defaults to ``"legacy"``. + + :arg quote_char: Use given quote character for attribute quoting. + + Defaults to ``"`` which will use double quotes unless attribute + value contains a double quote, in which case single quotes are + used. + + :arg escape_lt_in_attrs: Whether or not to escape ``<`` in attribute + values. + + Defaults to ``False``. + + :arg escape_rcdata: Whether to escape characters that need to be + escaped within normal elements within rcdata elements such as + style. + + Defaults to ``False``. + + :arg resolve_entities: Whether to resolve named character entities that + appear in the source tree. The XML predefined entities < > + & " ' are unaffected by this setting. + + Defaults to ``True``. + + :arg strip_whitespace: Whether to remove semantically meaningless + whitespace. (This compresses all whitespace to a single space + except within ``pre``.) + + Defaults to ``False``. + + :arg minimize_boolean_attributes: Shortens boolean attributes to give + just the attribute value, for example:: + + <input disabled="disabled"> + + becomes:: + + <input disabled> + + Defaults to ``True``. + + :arg use_trailing_solidus: Includes a close-tag slash at the end of the + start tag of void elements (empty elements whose end tag is + forbidden). E.g. ``<hr/>``. + + Defaults to ``False``. + + :arg space_before_trailing_solidus: Places a space immediately before + the closing slash in a tag using a trailing solidus. E.g. + ``<hr />``. Requires ``use_trailing_solidus=True``. + + Defaults to ``True``. + + :arg sanitize: Strip all unsafe or unknown constructs from output. + See :py:class:`html5lib.filters.sanitizer.Filter`. + + Defaults to ``False``. + + :arg omit_optional_tags: Omit start/end tags that are optional. + + Defaults to ``True``. + + :arg alphabetical_attributes: Reorder attributes to be in alphabetical order. + + Defaults to ``False``. + + """ + unexpected_args = frozenset(kwargs) - frozenset(self.options) + if len(unexpected_args) > 0: + raise TypeError("__init__() got an unexpected keyword argument '%s'" % next(iter(unexpected_args))) + if 'quote_char' in kwargs: + self.use_best_quote_char = False + for attr in self.options: + setattr(self, attr, kwargs.get(attr, getattr(self, attr))) + self.errors = [] + self.strict = False + + def encode(self, string): + assert(isinstance(string, text_type)) + if self.encoding: + return string.encode(self.encoding, "htmlentityreplace") + else: + return string + + def encodeStrict(self, string): + assert(isinstance(string, text_type)) + if self.encoding: + return string.encode(self.encoding, "strict") + else: + return string + + def serialize(self, treewalker, encoding=None): + # pylint:disable=too-many-nested-blocks + self.encoding = encoding + in_cdata = False + self.errors = [] + + if encoding and self.inject_meta_charset: + from .filters.inject_meta_charset import Filter + treewalker = Filter(treewalker, encoding) + # Alphabetical attributes is here under the assumption that none of + # the later filters add or change order of attributes; it needs to be + # before the sanitizer so escaped elements come out correctly + if self.alphabetical_attributes: + from .filters.alphabeticalattributes import Filter + treewalker = Filter(treewalker) + # WhitespaceFilter should be used before OptionalTagFilter + # for maximum efficiently of this latter filter + if self.strip_whitespace: + from .filters.whitespace import Filter + treewalker = Filter(treewalker) + if self.sanitize: + from .filters.sanitizer import Filter + treewalker = Filter(treewalker) + if self.omit_optional_tags: + from .filters.optionaltags import Filter + treewalker = Filter(treewalker) + + for token in treewalker: + type = token["type"] + if type == "Doctype": + doctype = "<!DOCTYPE %s" % token["name"] + + if token["publicId"]: + doctype += ' PUBLIC "%s"' % token["publicId"] + elif token["systemId"]: + doctype += " SYSTEM" + if token["systemId"]: + if token["systemId"].find('"') >= 0: + if token["systemId"].find("'") >= 0: + self.serializeError("System identifer contains both single and double quote characters") + quote_char = "'" + else: + quote_char = '"' + doctype += " %s%s%s" % (quote_char, token["systemId"], quote_char) + + doctype += ">" + yield self.encodeStrict(doctype) + + elif type in ("Characters", "SpaceCharacters"): + if type == "SpaceCharacters" or in_cdata: + if in_cdata and token["data"].find("</") >= 0: + self.serializeError("Unexpected </ in CDATA") + yield self.encode(token["data"]) + else: + yield self.encode(escape(token["data"])) + + elif type in ("StartTag", "EmptyTag"): + name = token["name"] + yield self.encodeStrict("<%s" % name) + if name in rcdataElements and not self.escape_rcdata: + in_cdata = True + elif in_cdata: + self.serializeError("Unexpected child element of a CDATA element") + for (_, attr_name), attr_value in token["data"].items(): + # TODO: Add namespace support here + k = attr_name + v = attr_value + yield self.encodeStrict(' ') + + yield self.encodeStrict(k) + if not self.minimize_boolean_attributes or \ + (k not in booleanAttributes.get(name, tuple()) and + k not in booleanAttributes.get("", tuple())): + yield self.encodeStrict("=") + if self.quote_attr_values == "always" or len(v) == 0: + quote_attr = True + elif self.quote_attr_values == "spec": + quote_attr = _quoteAttributeSpec.search(v) is not None + elif self.quote_attr_values == "legacy": + quote_attr = _quoteAttributeLegacy.search(v) is not None + else: + raise ValueError("quote_attr_values must be one of: " + "'always', 'spec', or 'legacy'") + v = v.replace("&", "&") + if self.escape_lt_in_attrs: + v = v.replace("<", "<") + if quote_attr: + quote_char = self.quote_char + if self.use_best_quote_char: + if "'" in v and '"' not in v: + quote_char = '"' + elif '"' in v and "'" not in v: + quote_char = "'" + if quote_char == "'": + v = v.replace("'", "'") + else: + v = v.replace('"', """) + yield self.encodeStrict(quote_char) + yield self.encode(v) + yield self.encodeStrict(quote_char) + else: + yield self.encode(v) + if name in voidElements and self.use_trailing_solidus: + if self.space_before_trailing_solidus: + yield self.encodeStrict(" /") + else: + yield self.encodeStrict("/") + yield self.encode(">") + + elif type == "EndTag": + name = token["name"] + if name in rcdataElements: + in_cdata = False + elif in_cdata: + self.serializeError("Unexpected child element of a CDATA element") + yield self.encodeStrict("</%s>" % name) + + elif type == "Comment": + data = token["data"] + if data.find("--") >= 0: + self.serializeError("Comment contains --") + yield self.encodeStrict("<!--%s-->" % token["data"]) + + elif type == "Entity": + name = token["name"] + key = name + ";" + if key not in entities: + self.serializeError("Entity %s not recognized" % name) + if self.resolve_entities and key not in xmlEntities: + data = entities[key] + else: + data = "&%s;" % name + yield self.encodeStrict(data) + + else: + self.serializeError(token["data"]) + + def render(self, treewalker, encoding=None): + """Serializes the stream from the treewalker into a string + + :arg treewalker: the treewalker to serialize + + :arg encoding: the string encoding to use + + :returns: the serialized tree + + Example: + + >>> from html5lib import parse, getTreeWalker + >>> from html5lib.serializer import HTMLSerializer + >>> token_stream = parse('<html><body>Hi!</body></html>') + >>> walker = getTreeWalker('etree') + >>> serializer = HTMLSerializer(omit_optional_tags=False) + >>> serializer.render(walker(token_stream)) + '<html><head></head><body>Hi!</body></html>' + + """ + if encoding: + return b"".join(list(self.serialize(treewalker, encoding))) + else: + return "".join(list(self.serialize(treewalker))) + + def serializeError(self, data="XXX ERROR MESSAGE NEEDED"): + # XXX The idea is to make data mandatory. + self.errors.append(data) + if self.strict: + raise SerializeError + + +class SerializeError(Exception): + """Error in serialized tree""" + pass diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py new file mode 100644 index 0000000..7ef5959 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py @@ -0,0 +1,30 @@ +"""Tree adapters let you convert from one tree structure to another + +Example: + +.. code-block:: python + + from pip._vendor import html5lib + from pip._vendor.html5lib.treeadapters import genshi + + doc = '<html><body>Hi!</body></html>' + treebuilder = html5lib.getTreeBuilder('etree') + parser = html5lib.HTMLParser(tree=treebuilder) + tree = parser.parse(doc) + TreeWalker = html5lib.getTreeWalker('etree') + + genshi_tree = genshi.to_genshi(TreeWalker(tree)) + +""" +from __future__ import absolute_import, division, unicode_literals + +from . import sax + +__all__ = ["sax"] + +try: + from . import genshi # noqa +except ImportError: + pass +else: + __all__.append("genshi") diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py new file mode 100644 index 0000000..61d5fb6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py @@ -0,0 +1,54 @@ +from __future__ import absolute_import, division, unicode_literals + +from genshi.core import QName, Attrs +from genshi.core import START, END, TEXT, COMMENT, DOCTYPE + + +def to_genshi(walker): + """Convert a tree to a genshi tree + + :arg walker: the treewalker to use to walk the tree to convert it + + :returns: generator of genshi nodes + + """ + text = [] + for token in walker: + type = token["type"] + if type in ("Characters", "SpaceCharacters"): + text.append(token["data"]) + elif text: + yield TEXT, "".join(text), (None, -1, -1) + text = [] + + if type in ("StartTag", "EmptyTag"): + if token["namespace"]: + name = "{%s}%s" % (token["namespace"], token["name"]) + else: + name = token["name"] + attrs = Attrs([(QName("{%s}%s" % attr if attr[0] is not None else attr[1]), value) + for attr, value in token["data"].items()]) + yield (START, (QName(name), attrs), (None, -1, -1)) + if type == "EmptyTag": + type = "EndTag" + + if type == "EndTag": + if token["namespace"]: + name = "{%s}%s" % (token["namespace"], token["name"]) + else: + name = token["name"] + + yield END, QName(name), (None, -1, -1) + + elif type == "Comment": + yield COMMENT, token["data"], (None, -1, -1) + + elif type == "Doctype": + yield DOCTYPE, (token["name"], token["publicId"], + token["systemId"]), (None, -1, -1) + + else: + pass # FIXME: What to do? + + if text: + yield TEXT, "".join(text), (None, -1, -1) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py new file mode 100644 index 0000000..f4ccea5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treeadapters/sax.py @@ -0,0 +1,50 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.sax.xmlreader import AttributesNSImpl + +from ..constants import adjustForeignAttributes, unadjustForeignAttributes + +prefix_mapping = {} +for prefix, localName, namespace in adjustForeignAttributes.values(): + if prefix is not None: + prefix_mapping[prefix] = namespace + + +def to_sax(walker, handler): + """Call SAX-like content handler based on treewalker walker + + :arg walker: the treewalker to use to walk the tree to convert it + + :arg handler: SAX handler to use + + """ + handler.startDocument() + for prefix, namespace in prefix_mapping.items(): + handler.startPrefixMapping(prefix, namespace) + + for token in walker: + type = token["type"] + if type == "Doctype": + continue + elif type in ("StartTag", "EmptyTag"): + attrs = AttributesNSImpl(token["data"], + unadjustForeignAttributes) + handler.startElementNS((token["namespace"], token["name"]), + token["name"], + attrs) + if type == "EmptyTag": + handler.endElementNS((token["namespace"], token["name"]), + token["name"]) + elif type == "EndTag": + handler.endElementNS((token["namespace"], token["name"]), + token["name"]) + elif type in ("Characters", "SpaceCharacters"): + handler.characters(token["data"]) + elif type == "Comment": + pass + else: + assert False, "Unknown token type" + + for prefix, namespace in prefix_mapping.items(): + handler.endPrefixMapping(prefix) + handler.endDocument() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py new file mode 100644 index 0000000..d44447e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py @@ -0,0 +1,88 @@ +"""A collection of modules for building different kinds of trees from HTML +documents. + +To create a treebuilder for a new type of tree, you need to do +implement several things: + +1. A set of classes for various types of elements: Document, Doctype, Comment, + Element. These must implement the interface of ``base.treebuilders.Node`` + (although comment nodes have a different signature for their constructor, + see ``treebuilders.etree.Comment``) Textual content may also be implemented + as another node type, or not, as your tree implementation requires. + +2. A treebuilder object (called ``TreeBuilder`` by convention) that inherits + from ``treebuilders.base.TreeBuilder``. This has 4 required attributes: + + * ``documentClass`` - the class to use for the bottommost node of a document + * ``elementClass`` - the class to use for HTML Elements + * ``commentClass`` - the class to use for comments + * ``doctypeClass`` - the class to use for doctypes + + It also has one required method: + + * ``getDocument`` - Returns the root node of the complete document tree + +3. If you wish to run the unit tests, you must also create a ``testSerializer`` + method on your treebuilder which accepts a node and returns a string + containing Node and its children serialized according to the format used in + the unittests + +""" + +from __future__ import absolute_import, division, unicode_literals + +from .._utils import default_etree + +treeBuilderCache = {} + + +def getTreeBuilder(treeType, implementation=None, **kwargs): + """Get a TreeBuilder class for various types of trees with built-in support + + :arg treeType: the name of the tree type required (case-insensitive). Supported + values are: + + * "dom" - A generic builder for DOM implementations, defaulting to a + xml.dom.minidom based implementation. + * "etree" - A generic builder for tree implementations exposing an + ElementTree-like interface, defaulting to xml.etree.cElementTree if + available and xml.etree.ElementTree if not. + * "lxml" - A etree-based builder for lxml.etree, handling limitations + of lxml's implementation. + + :arg implementation: (Currently applies to the "etree" and "dom" tree + types). A module implementing the tree type e.g. xml.etree.ElementTree + or xml.etree.cElementTree. + + :arg kwargs: Any additional options to pass to the TreeBuilder when + creating it. + + Example: + + >>> from html5lib.treebuilders import getTreeBuilder + >>> builder = getTreeBuilder('etree') + + """ + + treeType = treeType.lower() + if treeType not in treeBuilderCache: + if treeType == "dom": + from . import dom + # Come up with a sane default (pref. from the stdlib) + if implementation is None: + from xml.dom import minidom + implementation = minidom + # NEVER cache here, caching is done in the dom submodule + return dom.getDomModule(implementation, **kwargs).TreeBuilder + elif treeType == "lxml": + from . import etree_lxml + treeBuilderCache[treeType] = etree_lxml.TreeBuilder + elif treeType == "etree": + from . import etree + if implementation is None: + implementation = default_etree + # NEVER cache here, caching is done in the etree submodule + return etree.getETreeModule(implementation, **kwargs).TreeBuilder + else: + raise ValueError("""Unrecognised treebuilder "%s" """ % treeType) + return treeBuilderCache.get(treeType) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py new file mode 100644 index 0000000..73973db --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/base.py @@ -0,0 +1,417 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from ..constants import scopingElements, tableInsertModeElements, namespaces + +# The scope markers are inserted when entering object elements, +# marquees, table cells, and table captions, and are used to prevent formatting +# from "leaking" into tables, object elements, and marquees. +Marker = None + +listElementsMap = { + None: (frozenset(scopingElements), False), + "button": (frozenset(scopingElements | set([(namespaces["html"], "button")])), False), + "list": (frozenset(scopingElements | set([(namespaces["html"], "ol"), + (namespaces["html"], "ul")])), False), + "table": (frozenset([(namespaces["html"], "html"), + (namespaces["html"], "table")]), False), + "select": (frozenset([(namespaces["html"], "optgroup"), + (namespaces["html"], "option")]), True) +} + + +class Node(object): + """Represents an item in the tree""" + def __init__(self, name): + """Creates a Node + + :arg name: The tag name associated with the node + + """ + # The tag name assocaited with the node + self.name = name + # The parent of the current node (or None for the document node) + self.parent = None + # The value of the current node (applies to text nodes and comments) + self.value = None + # A dict holding name -> value pairs for attributes of the node + self.attributes = {} + # A list of child nodes of the current node. This must include all + # elements but not necessarily other node types. + self.childNodes = [] + # A list of miscellaneous flags that can be set on the node. + self._flags = [] + + def __str__(self): + attributesStr = " ".join(["%s=\"%s\"" % (name, value) + for name, value in + self.attributes.items()]) + if attributesStr: + return "<%s %s>" % (self.name, attributesStr) + else: + return "<%s>" % (self.name) + + def __repr__(self): + return "<%s>" % (self.name) + + def appendChild(self, node): + """Insert node as a child of the current node + + :arg node: the node to insert + + """ + raise NotImplementedError + + def insertText(self, data, insertBefore=None): + """Insert data as text in the current node, positioned before the + start of node insertBefore or to the end of the node's text. + + :arg data: the data to insert + + :arg insertBefore: True if you want to insert the text before the node + and False if you want to insert it after the node + + """ + raise NotImplementedError + + def insertBefore(self, node, refNode): + """Insert node as a child of the current node, before refNode in the + list of child nodes. Raises ValueError if refNode is not a child of + the current node + + :arg node: the node to insert + + :arg refNode: the child node to insert the node before + + """ + raise NotImplementedError + + def removeChild(self, node): + """Remove node from the children of the current node + + :arg node: the child node to remove + + """ + raise NotImplementedError + + def reparentChildren(self, newParent): + """Move all the children of the current node to newParent. + This is needed so that trees that don't store text as nodes move the + text in the correct way + + :arg newParent: the node to move all this node's children to + + """ + # XXX - should this method be made more general? + for child in self.childNodes: + newParent.appendChild(child) + self.childNodes = [] + + def cloneNode(self): + """Return a shallow copy of the current node i.e. a node with the same + name and attributes but with no parent or child nodes + """ + raise NotImplementedError + + def hasContent(self): + """Return true if the node has children or text, false otherwise + """ + raise NotImplementedError + + +class ActiveFormattingElements(list): + def append(self, node): + equalCount = 0 + if node != Marker: + for element in self[::-1]: + if element == Marker: + break + if self.nodesEqual(element, node): + equalCount += 1 + if equalCount == 3: + self.remove(element) + break + list.append(self, node) + + def nodesEqual(self, node1, node2): + if not node1.nameTuple == node2.nameTuple: + return False + + if not node1.attributes == node2.attributes: + return False + + return True + + +class TreeBuilder(object): + """Base treebuilder implementation + + * documentClass - the class to use for the bottommost node of a document + * elementClass - the class to use for HTML Elements + * commentClass - the class to use for comments + * doctypeClass - the class to use for doctypes + + """ + # pylint:disable=not-callable + + # Document class + documentClass = None + + # The class to use for creating a node + elementClass = None + + # The class to use for creating comments + commentClass = None + + # The class to use for creating doctypes + doctypeClass = None + + # Fragment class + fragmentClass = None + + def __init__(self, namespaceHTMLElements): + """Create a TreeBuilder + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + """ + if namespaceHTMLElements: + self.defaultNamespace = "http://www.w3.org/1999/xhtml" + else: + self.defaultNamespace = None + self.reset() + + def reset(self): + self.openElements = [] + self.activeFormattingElements = ActiveFormattingElements() + + # XXX - rename these to headElement, formElement + self.headPointer = None + self.formPointer = None + + self.insertFromTable = False + + self.document = self.documentClass() + + def elementInScope(self, target, variant=None): + + # If we pass a node in we match that. if we pass a string + # match any node with that name + exactNode = hasattr(target, "nameTuple") + if not exactNode: + if isinstance(target, text_type): + target = (namespaces["html"], target) + assert isinstance(target, tuple) + + listElements, invert = listElementsMap[variant] + + for node in reversed(self.openElements): + if exactNode and node == target: + return True + elif not exactNode and node.nameTuple == target: + return True + elif (invert ^ (node.nameTuple in listElements)): + return False + + assert False # We should never reach this point + + def reconstructActiveFormattingElements(self): + # Within this algorithm the order of steps described in the + # specification is not quite the same as the order of steps in the + # code. It should still do the same though. + + # Step 1: stop the algorithm when there's nothing to do. + if not self.activeFormattingElements: + return + + # Step 2 and step 3: we start with the last element. So i is -1. + i = len(self.activeFormattingElements) - 1 + entry = self.activeFormattingElements[i] + if entry == Marker or entry in self.openElements: + return + + # Step 6 + while entry != Marker and entry not in self.openElements: + if i == 0: + # This will be reset to 0 below + i = -1 + break + i -= 1 + # Step 5: let entry be one earlier in the list. + entry = self.activeFormattingElements[i] + + while True: + # Step 7 + i += 1 + + # Step 8 + entry = self.activeFormattingElements[i] + clone = entry.cloneNode() # Mainly to get a new copy of the attributes + + # Step 9 + element = self.insertElement({"type": "StartTag", + "name": clone.name, + "namespace": clone.namespace, + "data": clone.attributes}) + + # Step 10 + self.activeFormattingElements[i] = element + + # Step 11 + if element == self.activeFormattingElements[-1]: + break + + def clearActiveFormattingElements(self): + entry = self.activeFormattingElements.pop() + while self.activeFormattingElements and entry != Marker: + entry = self.activeFormattingElements.pop() + + def elementInActiveFormattingElements(self, name): + """Check if an element exists between the end of the active + formatting elements and the last marker. If it does, return it, else + return false""" + + for item in self.activeFormattingElements[::-1]: + # Check for Marker first because if it's a Marker it doesn't have a + # name attribute. + if item == Marker: + break + elif item.name == name: + return item + return False + + def insertRoot(self, token): + element = self.createElement(token) + self.openElements.append(element) + self.document.appendChild(element) + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + doctype = self.doctypeClass(name, publicId, systemId) + self.document.appendChild(doctype) + + def insertComment(self, token, parent=None): + if parent is None: + parent = self.openElements[-1] + parent.appendChild(self.commentClass(token["data"])) + + def createElement(self, token): + """Create an element but don't insert it anywhere""" + name = token["name"] + namespace = token.get("namespace", self.defaultNamespace) + element = self.elementClass(name, namespace) + element.attributes = token["data"] + return element + + def _getInsertFromTable(self): + return self._insertFromTable + + def _setInsertFromTable(self, value): + """Switch the function used to insert an element from the + normal one to the misnested table one and back again""" + self._insertFromTable = value + if value: + self.insertElement = self.insertElementTable + else: + self.insertElement = self.insertElementNormal + + insertFromTable = property(_getInsertFromTable, _setInsertFromTable) + + def insertElementNormal(self, token): + name = token["name"] + assert isinstance(name, text_type), "Element %s not unicode" % name + namespace = token.get("namespace", self.defaultNamespace) + element = self.elementClass(name, namespace) + element.attributes = token["data"] + self.openElements[-1].appendChild(element) + self.openElements.append(element) + return element + + def insertElementTable(self, token): + """Create an element and insert it into the tree""" + element = self.createElement(token) + if self.openElements[-1].name not in tableInsertModeElements: + return self.insertElementNormal(token) + else: + # We should be in the InTable mode. This means we want to do + # special magic element rearranging + parent, insertBefore = self.getTableMisnestedNodePosition() + if insertBefore is None: + parent.appendChild(element) + else: + parent.insertBefore(element, insertBefore) + self.openElements.append(element) + return element + + def insertText(self, data, parent=None): + """Insert text data.""" + if parent is None: + parent = self.openElements[-1] + + if (not self.insertFromTable or (self.insertFromTable and + self.openElements[-1].name + not in tableInsertModeElements)): + parent.insertText(data) + else: + # We should be in the InTable mode. This means we want to do + # special magic element rearranging + parent, insertBefore = self.getTableMisnestedNodePosition() + parent.insertText(data, insertBefore) + + def getTableMisnestedNodePosition(self): + """Get the foster parent element, and sibling to insert before + (or None) when inserting a misnested table node""" + # The foster parent element is the one which comes before the most + # recently opened table element + # XXX - this is really inelegant + lastTable = None + fosterParent = None + insertBefore = None + for elm in self.openElements[::-1]: + if elm.name == "table": + lastTable = elm + break + if lastTable: + # XXX - we should really check that this parent is actually a + # node here + if lastTable.parent: + fosterParent = lastTable.parent + insertBefore = lastTable + else: + fosterParent = self.openElements[ + self.openElements.index(lastTable) - 1] + else: + fosterParent = self.openElements[0] + return fosterParent, insertBefore + + def generateImpliedEndTags(self, exclude=None): + name = self.openElements[-1].name + # XXX td, th and tr are not actually needed + if (name in frozenset(("dd", "dt", "li", "option", "optgroup", "p", "rp", "rt")) and + name != exclude): + self.openElements.pop() + # XXX This is not entirely what the specification says. We should + # investigate it more closely. + self.generateImpliedEndTags(exclude) + + def getDocument(self): + """Return the final tree""" + return self.document + + def getFragment(self): + """Return the final fragment""" + # assert self.innerHTML + fragment = self.fragmentClass() + self.openElements[0].reparentChildren(fragment) + return fragment + + def testSerializer(self, node): + """Serialize the subtree of node in the format required by unit tests + + :arg node: the node from which to start serializing + + """ + raise NotImplementedError diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py new file mode 100644 index 0000000..dcfac22 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/dom.py @@ -0,0 +1,236 @@ +from __future__ import absolute_import, division, unicode_literals + + +from collections import MutableMapping +from xml.dom import minidom, Node +import weakref + +from . import base +from .. import constants +from ..constants import namespaces +from .._utils import moduleFactoryFactory + + +def getDomBuilder(DomImplementation): + Dom = DomImplementation + + class AttrList(MutableMapping): + def __init__(self, element): + self.element = element + + def __iter__(self): + return iter(self.element.attributes.keys()) + + def __setitem__(self, name, value): + if isinstance(name, tuple): + raise NotImplementedError + else: + attr = self.element.ownerDocument.createAttribute(name) + attr.value = value + self.element.attributes[name] = attr + + def __len__(self): + return len(self.element.attributes) + + def items(self): + return list(self.element.attributes.items()) + + def values(self): + return list(self.element.attributes.values()) + + def __getitem__(self, name): + if isinstance(name, tuple): + raise NotImplementedError + else: + return self.element.attributes[name].value + + def __delitem__(self, name): + if isinstance(name, tuple): + raise NotImplementedError + else: + del self.element.attributes[name] + + class NodeBuilder(base.Node): + def __init__(self, element): + base.Node.__init__(self, element.nodeName) + self.element = element + + namespace = property(lambda self: hasattr(self.element, "namespaceURI") and + self.element.namespaceURI or None) + + def appendChild(self, node): + node.parent = self + self.element.appendChild(node.element) + + def insertText(self, data, insertBefore=None): + text = self.element.ownerDocument.createTextNode(data) + if insertBefore: + self.element.insertBefore(text, insertBefore.element) + else: + self.element.appendChild(text) + + def insertBefore(self, node, refNode): + self.element.insertBefore(node.element, refNode.element) + node.parent = self + + def removeChild(self, node): + if node.element.parentNode == self.element: + self.element.removeChild(node.element) + node.parent = None + + def reparentChildren(self, newParent): + while self.element.hasChildNodes(): + child = self.element.firstChild + self.element.removeChild(child) + newParent.element.appendChild(child) + self.childNodes = [] + + def getAttributes(self): + return AttrList(self.element) + + def setAttributes(self, attributes): + if attributes: + for name, value in list(attributes.items()): + if isinstance(name, tuple): + if name[0] is not None: + qualifiedName = (name[0] + ":" + name[1]) + else: + qualifiedName = name[1] + self.element.setAttributeNS(name[2], qualifiedName, + value) + else: + self.element.setAttribute( + name, value) + attributes = property(getAttributes, setAttributes) + + def cloneNode(self): + return NodeBuilder(self.element.cloneNode(False)) + + def hasContent(self): + return self.element.hasChildNodes() + + def getNameTuple(self): + if self.namespace is None: + return namespaces["html"], self.name + else: + return self.namespace, self.name + + nameTuple = property(getNameTuple) + + class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable + def documentClass(self): + self.dom = Dom.getDOMImplementation().createDocument(None, None, None) + return weakref.proxy(self) + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + domimpl = Dom.getDOMImplementation() + doctype = domimpl.createDocumentType(name, publicId, systemId) + self.document.appendChild(NodeBuilder(doctype)) + if Dom == minidom: + doctype.ownerDocument = self.dom + + def elementClass(self, name, namespace=None): + if namespace is None and self.defaultNamespace is None: + node = self.dom.createElement(name) + else: + node = self.dom.createElementNS(namespace, name) + + return NodeBuilder(node) + + def commentClass(self, data): + return NodeBuilder(self.dom.createComment(data)) + + def fragmentClass(self): + return NodeBuilder(self.dom.createDocumentFragment()) + + def appendChild(self, node): + self.dom.appendChild(node.element) + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + return self.dom + + def getFragment(self): + return base.TreeBuilder.getFragment(self).element + + def insertText(self, data, parent=None): + data = data + if parent != self: + base.TreeBuilder.insertText(self, data, parent) + else: + # HACK: allow text nodes as children of the document node + if hasattr(self.dom, '_child_node_types'): + # pylint:disable=protected-access + if Node.TEXT_NODE not in self.dom._child_node_types: + self.dom._child_node_types = list(self.dom._child_node_types) + self.dom._child_node_types.append(Node.TEXT_NODE) + self.dom.appendChild(self.dom.createTextNode(data)) + + implementation = DomImplementation + name = None + + def testSerializer(element): + element.normalize() + rv = [] + + def serializeElement(element, indent=0): + if element.nodeType == Node.DOCUMENT_TYPE_NODE: + if element.name: + if element.publicId or element.systemId: + publicId = element.publicId or "" + systemId = element.systemId or "" + rv.append("""|%s<!DOCTYPE %s "%s" "%s">""" % + (' ' * indent, element.name, publicId, systemId)) + else: + rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name)) + else: + rv.append("|%s<!DOCTYPE >" % (' ' * indent,)) + elif element.nodeType == Node.DOCUMENT_NODE: + rv.append("#document") + elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE: + rv.append("#document-fragment") + elif element.nodeType == Node.COMMENT_NODE: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.nodeValue)) + elif element.nodeType == Node.TEXT_NODE: + rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue)) + else: + if (hasattr(element, "namespaceURI") and + element.namespaceURI is not None): + name = "%s %s" % (constants.prefixes[element.namespaceURI], + element.nodeName) + else: + name = element.nodeName + rv.append("|%s<%s>" % (' ' * indent, name)) + if element.hasAttributes(): + attributes = [] + for i in range(len(element.attributes)): + attr = element.attributes.item(i) + name = attr.nodeName + value = attr.value + ns = attr.namespaceURI + if ns: + name = "%s %s" % (constants.prefixes[ns], attr.localName) + else: + name = attr.nodeName + attributes.append((name, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + indent += 2 + for child in element.childNodes: + serializeElement(child, indent) + serializeElement(element, 0) + + return "\n".join(rv) + + return locals() + + +# The actual means to get a module! +getDomModule = moduleFactoryFactory(getDomBuilder) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py new file mode 100644 index 0000000..0dedf44 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree.py @@ -0,0 +1,340 @@ +from __future__ import absolute_import, division, unicode_literals +# pylint:disable=protected-access + +from pip._vendor.six import text_type + +import re + +from . import base +from .. import _ihatexml +from .. import constants +from ..constants import namespaces +from .._utils import moduleFactoryFactory + +tag_regexp = re.compile("{([^}]*)}(.*)") + + +def getETreeBuilder(ElementTreeImplementation, fullTree=False): + ElementTree = ElementTreeImplementation + ElementTreeCommentType = ElementTree.Comment("asd").tag + + class Element(base.Node): + def __init__(self, name, namespace=None): + self._name = name + self._namespace = namespace + self._element = ElementTree.Element(self._getETreeTag(name, + namespace)) + if namespace is None: + self.nameTuple = namespaces["html"], self._name + else: + self.nameTuple = self._namespace, self._name + self.parent = None + self._childNodes = [] + self._flags = [] + + def _getETreeTag(self, name, namespace): + if namespace is None: + etree_tag = name + else: + etree_tag = "{%s}%s" % (namespace, name) + return etree_tag + + def _setName(self, name): + self._name = name + self._element.tag = self._getETreeTag(self._name, self._namespace) + + def _getName(self): + return self._name + + name = property(_getName, _setName) + + def _setNamespace(self, namespace): + self._namespace = namespace + self._element.tag = self._getETreeTag(self._name, self._namespace) + + def _getNamespace(self): + return self._namespace + + namespace = property(_getNamespace, _setNamespace) + + def _getAttributes(self): + return self._element.attrib + + def _setAttributes(self, attributes): + # Delete existing attributes first + # XXX - there may be a better way to do this... + for key in list(self._element.attrib.keys()): + del self._element.attrib[key] + for key, value in attributes.items(): + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], key[1]) + else: + name = key + self._element.set(name, value) + + attributes = property(_getAttributes, _setAttributes) + + def _getChildNodes(self): + return self._childNodes + + def _setChildNodes(self, value): + del self._element[:] + self._childNodes = [] + for element in value: + self.insertChild(element) + + childNodes = property(_getChildNodes, _setChildNodes) + + def hasContent(self): + """Return true if the node has children or text""" + return bool(self._element.text or len(self._element)) + + def appendChild(self, node): + self._childNodes.append(node) + self._element.append(node._element) + node.parent = self + + def insertBefore(self, node, refNode): + index = list(self._element).index(refNode._element) + self._element.insert(index, node._element) + node.parent = self + + def removeChild(self, node): + self._childNodes.remove(node) + self._element.remove(node._element) + node.parent = None + + def insertText(self, data, insertBefore=None): + if not(len(self._element)): + if not self._element.text: + self._element.text = "" + self._element.text += data + elif insertBefore is None: + # Insert the text as the tail of the last child element + if not self._element[-1].tail: + self._element[-1].tail = "" + self._element[-1].tail += data + else: + # Insert the text before the specified node + children = list(self._element) + index = children.index(insertBefore._element) + if index > 0: + if not self._element[index - 1].tail: + self._element[index - 1].tail = "" + self._element[index - 1].tail += data + else: + if not self._element.text: + self._element.text = "" + self._element.text += data + + def cloneNode(self): + element = type(self)(self.name, self.namespace) + for name, value in self.attributes.items(): + element.attributes[name] = value + return element + + def reparentChildren(self, newParent): + if newParent.childNodes: + newParent.childNodes[-1]._element.tail += self._element.text + else: + if not newParent._element.text: + newParent._element.text = "" + if self._element.text is not None: + newParent._element.text += self._element.text + self._element.text = "" + base.Node.reparentChildren(self, newParent) + + class Comment(Element): + def __init__(self, data): + # Use the superclass constructor to set all properties on the + # wrapper element + self._element = ElementTree.Comment(data) + self.parent = None + self._childNodes = [] + self._flags = [] + + def _getData(self): + return self._element.text + + def _setData(self, value): + self._element.text = value + + data = property(_getData, _setData) + + class DocumentType(Element): + def __init__(self, name, publicId, systemId): + Element.__init__(self, "<!DOCTYPE>") + self._element.text = name + self.publicId = publicId + self.systemId = systemId + + def _getPublicId(self): + return self._element.get("publicId", "") + + def _setPublicId(self, value): + if value is not None: + self._element.set("publicId", value) + + publicId = property(_getPublicId, _setPublicId) + + def _getSystemId(self): + return self._element.get("systemId", "") + + def _setSystemId(self, value): + if value is not None: + self._element.set("systemId", value) + + systemId = property(_getSystemId, _setSystemId) + + class Document(Element): + def __init__(self): + Element.__init__(self, "DOCUMENT_ROOT") + + class DocumentFragment(Element): + def __init__(self): + Element.__init__(self, "DOCUMENT_FRAGMENT") + + def testSerializer(element): + rv = [] + + def serializeElement(element, indent=0): + if not(hasattr(element, "tag")): + element = element.getroot() + if element.tag == "<!DOCTYPE>": + if element.get("publicId") or element.get("systemId"): + publicId = element.get("publicId") or "" + systemId = element.get("systemId") or "" + rv.append("""<!DOCTYPE %s "%s" "%s">""" % + (element.text, publicId, systemId)) + else: + rv.append("<!DOCTYPE %s>" % (element.text,)) + elif element.tag == "DOCUMENT_ROOT": + rv.append("#document") + if element.text is not None: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + if element.tail is not None: + raise TypeError("Document node cannot have tail") + if hasattr(element, "attrib") and len(element.attrib): + raise TypeError("Document node cannot have attributes") + elif element.tag == ElementTreeCommentType: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) + else: + assert isinstance(element.tag, text_type), \ + "Expected unicode, got %s, %s" % (type(element.tag), element.tag) + nsmatch = tag_regexp.match(element.tag) + + if nsmatch is None: + name = element.tag + else: + ns, name = nsmatch.groups() + prefix = constants.prefixes[ns] + name = "%s %s" % (prefix, name) + rv.append("|%s<%s>" % (' ' * indent, name)) + + if hasattr(element, "attrib"): + attributes = [] + for name, value in element.attrib.items(): + nsmatch = tag_regexp.match(name) + if nsmatch is not None: + ns, name = nsmatch.groups() + prefix = constants.prefixes[ns] + attr_string = "%s %s" % (prefix, name) + else: + attr_string = name + attributes.append((attr_string, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + if element.text: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + indent += 2 + for child in element: + serializeElement(child, indent) + if element.tail: + rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) + serializeElement(element, 0) + + return "\n".join(rv) + + def tostring(element): # pylint:disable=unused-variable + """Serialize an element and its child nodes to a string""" + rv = [] + filter = _ihatexml.InfosetFilter() + + def serializeElement(element): + if isinstance(element, ElementTree.ElementTree): + element = element.getroot() + + if element.tag == "<!DOCTYPE>": + if element.get("publicId") or element.get("systemId"): + publicId = element.get("publicId") or "" + systemId = element.get("systemId") or "" + rv.append("""<!DOCTYPE %s PUBLIC "%s" "%s">""" % + (element.text, publicId, systemId)) + else: + rv.append("<!DOCTYPE %s>" % (element.text,)) + elif element.tag == "DOCUMENT_ROOT": + if element.text is not None: + rv.append(element.text) + if element.tail is not None: + raise TypeError("Document node cannot have tail") + if hasattr(element, "attrib") and len(element.attrib): + raise TypeError("Document node cannot have attributes") + + for child in element: + serializeElement(child) + + elif element.tag == ElementTreeCommentType: + rv.append("<!--%s-->" % (element.text,)) + else: + # This is assumed to be an ordinary element + if not element.attrib: + rv.append("<%s>" % (filter.fromXmlName(element.tag),)) + else: + attr = " ".join(["%s=\"%s\"" % ( + filter.fromXmlName(name), value) + for name, value in element.attrib.items()]) + rv.append("<%s %s>" % (element.tag, attr)) + if element.text: + rv.append(element.text) + + for child in element: + serializeElement(child) + + rv.append("</%s>" % (element.tag,)) + + if element.tail: + rv.append(element.tail) + + serializeElement(element) + + return "".join(rv) + + class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable + documentClass = Document + doctypeClass = DocumentType + elementClass = Element + commentClass = Comment + fragmentClass = DocumentFragment + implementation = ElementTreeImplementation + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + if fullTree: + return self.document._element + else: + if self.defaultNamespace is not None: + return self.document._element.find( + "{%s}html" % self.defaultNamespace) + else: + return self.document._element.find("html") + + def getFragment(self): + return base.TreeBuilder.getFragment(self)._element + + return locals() + + +getETreeModule = moduleFactoryFactory(getETreeBuilder) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py new file mode 100644 index 0000000..ca12a99 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py @@ -0,0 +1,366 @@ +"""Module for supporting the lxml.etree library. The idea here is to use as much +of the native library as possible, without using fragile hacks like custom element +names that break between releases. The downside of this is that we cannot represent +all possible trees; specifically the following are known to cause problems: + +Text or comments as siblings of the root element +Docypes with no name + +When any of these things occur, we emit a DataLossWarning +""" + +from __future__ import absolute_import, division, unicode_literals +# pylint:disable=protected-access + +import warnings +import re +import sys + +from . import base +from ..constants import DataLossWarning +from .. import constants +from . import etree as etree_builders +from .. import _ihatexml + +import lxml.etree as etree + + +fullTree = True +tag_regexp = re.compile("{([^}]*)}(.*)") + +comment_type = etree.Comment("asd").tag + + +class DocumentType(object): + def __init__(self, name, publicId, systemId): + self.name = name + self.publicId = publicId + self.systemId = systemId + + +class Document(object): + def __init__(self): + self._elementTree = None + self._childNodes = [] + + def appendChild(self, element): + self._elementTree.getroot().addnext(element._element) + + def _getChildNodes(self): + return self._childNodes + + childNodes = property(_getChildNodes) + + +def testSerializer(element): + rv = [] + infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) + + def serializeElement(element, indent=0): + if not hasattr(element, "tag"): + if hasattr(element, "getroot"): + # Full tree case + rv.append("#document") + if element.docinfo.internalDTD: + if not (element.docinfo.public_id or + element.docinfo.system_url): + dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name + else: + dtd_str = """<!DOCTYPE %s "%s" "%s">""" % ( + element.docinfo.root_name, + element.docinfo.public_id, + element.docinfo.system_url) + rv.append("|%s%s" % (' ' * (indent + 2), dtd_str)) + next_element = element.getroot() + while next_element.getprevious() is not None: + next_element = next_element.getprevious() + while next_element is not None: + serializeElement(next_element, indent + 2) + next_element = next_element.getnext() + elif isinstance(element, str) or isinstance(element, bytes): + # Text in a fragment + assert isinstance(element, str) or sys.version_info[0] == 2 + rv.append("|%s\"%s\"" % (' ' * indent, element)) + else: + # Fragment case + rv.append("#document-fragment") + for next_element in element: + serializeElement(next_element, indent + 2) + elif element.tag == comment_type: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) + if hasattr(element, "tail") and element.tail: + rv.append("|%s\"%s\"" % (' ' * indent, element.tail)) + else: + assert isinstance(element, etree._Element) + nsmatch = etree_builders.tag_regexp.match(element.tag) + if nsmatch is not None: + ns = nsmatch.group(1) + tag = nsmatch.group(2) + prefix = constants.prefixes[ns] + rv.append("|%s<%s %s>" % (' ' * indent, prefix, + infosetFilter.fromXmlName(tag))) + else: + rv.append("|%s<%s>" % (' ' * indent, + infosetFilter.fromXmlName(element.tag))) + + if hasattr(element, "attrib"): + attributes = [] + for name, value in element.attrib.items(): + nsmatch = tag_regexp.match(name) + if nsmatch is not None: + ns, name = nsmatch.groups() + name = infosetFilter.fromXmlName(name) + prefix = constants.prefixes[ns] + attr_string = "%s %s" % (prefix, name) + else: + attr_string = infosetFilter.fromXmlName(name) + attributes.append((attr_string, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + + if element.text: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + indent += 2 + for child in element: + serializeElement(child, indent) + if hasattr(element, "tail") and element.tail: + rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) + serializeElement(element, 0) + + return "\n".join(rv) + + +def tostring(element): + """Serialize an element and its child nodes to a string""" + rv = [] + + def serializeElement(element): + if not hasattr(element, "tag"): + if element.docinfo.internalDTD: + if element.docinfo.doctype: + dtd_str = element.docinfo.doctype + else: + dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name + rv.append(dtd_str) + serializeElement(element.getroot()) + + elif element.tag == comment_type: + rv.append("<!--%s-->" % (element.text,)) + + else: + # This is assumed to be an ordinary element + if not element.attrib: + rv.append("<%s>" % (element.tag,)) + else: + attr = " ".join(["%s=\"%s\"" % (name, value) + for name, value in element.attrib.items()]) + rv.append("<%s %s>" % (element.tag, attr)) + if element.text: + rv.append(element.text) + + for child in element: + serializeElement(child) + + rv.append("</%s>" % (element.tag,)) + + if hasattr(element, "tail") and element.tail: + rv.append(element.tail) + + serializeElement(element) + + return "".join(rv) + + +class TreeBuilder(base.TreeBuilder): + documentClass = Document + doctypeClass = DocumentType + elementClass = None + commentClass = None + fragmentClass = Document + implementation = etree + + def __init__(self, namespaceHTMLElements, fullTree=False): + builder = etree_builders.getETreeModule(etree, fullTree=fullTree) + infosetFilter = self.infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) + self.namespaceHTMLElements = namespaceHTMLElements + + class Attributes(dict): + def __init__(self, element, value=None): + if value is None: + value = {} + self._element = element + dict.__init__(self, value) # pylint:disable=non-parent-init-called + for key, value in self.items(): + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) + else: + name = infosetFilter.coerceAttribute(key) + self._element._element.attrib[name] = value + + def __setitem__(self, key, value): + dict.__setitem__(self, key, value) + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) + else: + name = infosetFilter.coerceAttribute(key) + self._element._element.attrib[name] = value + + class Element(builder.Element): + def __init__(self, name, namespace): + name = infosetFilter.coerceElement(name) + builder.Element.__init__(self, name, namespace=namespace) + self._attributes = Attributes(self) + + def _setName(self, name): + self._name = infosetFilter.coerceElement(name) + self._element.tag = self._getETreeTag( + self._name, self._namespace) + + def _getName(self): + return infosetFilter.fromXmlName(self._name) + + name = property(_getName, _setName) + + def _getAttributes(self): + return self._attributes + + def _setAttributes(self, attributes): + self._attributes = Attributes(self, attributes) + + attributes = property(_getAttributes, _setAttributes) + + def insertText(self, data, insertBefore=None): + data = infosetFilter.coerceCharacters(data) + builder.Element.insertText(self, data, insertBefore) + + def appendChild(self, child): + builder.Element.appendChild(self, child) + + class Comment(builder.Comment): + def __init__(self, data): + data = infosetFilter.coerceComment(data) + builder.Comment.__init__(self, data) + + def _setData(self, data): + data = infosetFilter.coerceComment(data) + self._element.text = data + + def _getData(self): + return self._element.text + + data = property(_getData, _setData) + + self.elementClass = Element + self.commentClass = Comment + # self.fragmentClass = builder.DocumentFragment + base.TreeBuilder.__init__(self, namespaceHTMLElements) + + def reset(self): + base.TreeBuilder.reset(self) + self.insertComment = self.insertCommentInitial + self.initial_comments = [] + self.doctype = None + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + if fullTree: + return self.document._elementTree + else: + return self.document._elementTree.getroot() + + def getFragment(self): + fragment = [] + element = self.openElements[0]._element + if element.text: + fragment.append(element.text) + fragment.extend(list(element)) + if element.tail: + fragment.append(element.tail) + return fragment + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + if not name: + warnings.warn("lxml cannot represent empty doctype", DataLossWarning) + self.doctype = None + else: + coercedName = self.infosetFilter.coerceElement(name) + if coercedName != name: + warnings.warn("lxml cannot represent non-xml doctype", DataLossWarning) + + doctype = self.doctypeClass(coercedName, publicId, systemId) + self.doctype = doctype + + def insertCommentInitial(self, data, parent=None): + assert parent is None or parent is self.document + assert self.document._elementTree is None + self.initial_comments.append(data) + + def insertCommentMain(self, data, parent=None): + if (parent == self.document and + self.document._elementTree.getroot()[-1].tag == comment_type): + warnings.warn("lxml cannot represent adjacent comments beyond the root elements", DataLossWarning) + super(TreeBuilder, self).insertComment(data, parent) + + def insertRoot(self, token): + # Because of the way libxml2 works, it doesn't seem to be possible to + # alter information like the doctype after the tree has been parsed. + # Therefore we need to use the built-in parser to create our initial + # tree, after which we can add elements like normal + docStr = "" + if self.doctype: + assert self.doctype.name + docStr += "<!DOCTYPE %s" % self.doctype.name + if (self.doctype.publicId is not None or + self.doctype.systemId is not None): + docStr += (' PUBLIC "%s" ' % + (self.infosetFilter.coercePubid(self.doctype.publicId or ""))) + if self.doctype.systemId: + sysid = self.doctype.systemId + if sysid.find("'") >= 0 and sysid.find('"') >= 0: + warnings.warn("DOCTYPE system cannot contain single and double quotes", DataLossWarning) + sysid = sysid.replace("'", 'U00027') + if sysid.find("'") >= 0: + docStr += '"%s"' % sysid + else: + docStr += "'%s'" % sysid + else: + docStr += "''" + docStr += ">" + if self.doctype.name != token["name"]: + warnings.warn("lxml cannot represent doctype with a different name to the root element", DataLossWarning) + docStr += "<THIS_SHOULD_NEVER_APPEAR_PUBLICLY/>" + root = etree.fromstring(docStr) + + # Append the initial comments: + for comment_token in self.initial_comments: + comment = self.commentClass(comment_token["data"]) + root.addprevious(comment._element) + + # Create the root document and add the ElementTree to it + self.document = self.documentClass() + self.document._elementTree = root.getroottree() + + # Give the root element the right name + name = token["name"] + namespace = token.get("namespace", self.defaultNamespace) + if namespace is None: + etree_tag = name + else: + etree_tag = "{%s}%s" % (namespace, name) + root.tag = etree_tag + + # Add the root element to the internal child/open data structures + root_element = self.elementClass(name, namespace) + root_element._element = root + self.document._childNodes.append(root_element) + self.openElements.append(root_element) + + # Reset to the default insert comment function + self.insertComment = self.insertCommentMain diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py new file mode 100644 index 0000000..9bec207 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py @@ -0,0 +1,154 @@ +"""A collection of modules for iterating through different kinds of +tree, generating tokens identical to those produced by the tokenizer +module. + +To create a tree walker for a new type of tree, you need to do +implement a tree walker object (called TreeWalker by convention) that +implements a 'serialize' method taking a tree as sole argument and +returning an iterator generating tokens. +""" + +from __future__ import absolute_import, division, unicode_literals + +from .. import constants +from .._utils import default_etree + +__all__ = ["getTreeWalker", "pprint"] + +treeWalkerCache = {} + + +def getTreeWalker(treeType, implementation=None, **kwargs): + """Get a TreeWalker class for various types of tree with built-in support + + :arg str treeType: the name of the tree type required (case-insensitive). + Supported values are: + + * "dom": The xml.dom.minidom DOM implementation + * "etree": A generic walker for tree implementations exposing an + elementtree-like interface (known to work with ElementTree, + cElementTree and lxml.etree). + * "lxml": Optimized walker for lxml.etree + * "genshi": a Genshi stream + + :arg implementation: A module implementing the tree type e.g. + xml.etree.ElementTree or cElementTree (Currently applies to the "etree" + tree type only). + + :arg kwargs: keyword arguments passed to the etree walker--for other + walkers, this has no effect + + :returns: a TreeWalker class + + """ + + treeType = treeType.lower() + if treeType not in treeWalkerCache: + if treeType == "dom": + from . import dom + treeWalkerCache[treeType] = dom.TreeWalker + elif treeType == "genshi": + from . import genshi + treeWalkerCache[treeType] = genshi.TreeWalker + elif treeType == "lxml": + from . import etree_lxml + treeWalkerCache[treeType] = etree_lxml.TreeWalker + elif treeType == "etree": + from . import etree + if implementation is None: + implementation = default_etree + # XXX: NEVER cache here, caching is done in the etree submodule + return etree.getETreeModule(implementation, **kwargs).TreeWalker + return treeWalkerCache.get(treeType) + + +def concatenateCharacterTokens(tokens): + pendingCharacters = [] + for token in tokens: + type = token["type"] + if type in ("Characters", "SpaceCharacters"): + pendingCharacters.append(token["data"]) + else: + if pendingCharacters: + yield {"type": "Characters", "data": "".join(pendingCharacters)} + pendingCharacters = [] + yield token + if pendingCharacters: + yield {"type": "Characters", "data": "".join(pendingCharacters)} + + +def pprint(walker): + """Pretty printer for tree walkers + + Takes a TreeWalker instance and pretty prints the output of walking the tree. + + :arg walker: a TreeWalker instance + + """ + output = [] + indent = 0 + for token in concatenateCharacterTokens(walker): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + # tag name + if token["namespace"] and token["namespace"] != constants.namespaces["html"]: + if token["namespace"] in constants.prefixes: + ns = constants.prefixes[token["namespace"]] + else: + ns = token["namespace"] + name = "%s %s" % (ns, token["name"]) + else: + name = token["name"] + output.append("%s<%s>" % (" " * indent, name)) + indent += 2 + # attributes (sorted for consistent ordering) + attrs = token["data"] + for (namespace, localname), value in sorted(attrs.items()): + if namespace: + if namespace in constants.prefixes: + ns = constants.prefixes[namespace] + else: + ns = namespace + name = "%s %s" % (ns, localname) + else: + name = localname + output.append("%s%s=\"%s\"" % (" " * indent, name, value)) + # self-closing + if type == "EmptyTag": + indent -= 2 + + elif type == "EndTag": + indent -= 2 + + elif type == "Comment": + output.append("%s<!-- %s -->" % (" " * indent, token["data"])) + + elif type == "Doctype": + if token["name"]: + if token["publicId"]: + output.append("""%s<!DOCTYPE %s "%s" "%s">""" % + (" " * indent, + token["name"], + token["publicId"], + token["systemId"] if token["systemId"] else "")) + elif token["systemId"]: + output.append("""%s<!DOCTYPE %s "" "%s">""" % + (" " * indent, + token["name"], + token["systemId"])) + else: + output.append("%s<!DOCTYPE %s>" % (" " * indent, + token["name"])) + else: + output.append("%s<!DOCTYPE >" % (" " * indent,)) + + elif type == "Characters": + output.append("%s\"%s\"" % (" " * indent, token["data"])) + + elif type == "SpaceCharacters": + assert False, "concatenateCharacterTokens should have got rid of all Space tokens" + + else: + raise ValueError("Unknown token type, %s" % type) + + return "\n".join(output) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py new file mode 100644 index 0000000..80c474c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/base.py @@ -0,0 +1,252 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.dom import Node +from ..constants import namespaces, voidElements, spaceCharacters + +__all__ = ["DOCUMENT", "DOCTYPE", "TEXT", "ELEMENT", "COMMENT", "ENTITY", "UNKNOWN", + "TreeWalker", "NonRecursiveTreeWalker"] + +DOCUMENT = Node.DOCUMENT_NODE +DOCTYPE = Node.DOCUMENT_TYPE_NODE +TEXT = Node.TEXT_NODE +ELEMENT = Node.ELEMENT_NODE +COMMENT = Node.COMMENT_NODE +ENTITY = Node.ENTITY_NODE +UNKNOWN = "<#UNKNOWN#>" + +spaceCharacters = "".join(spaceCharacters) + + +class TreeWalker(object): + """Walks a tree yielding tokens + + Tokens are dicts that all have a ``type`` field specifying the type of the + token. + + """ + def __init__(self, tree): + """Creates a TreeWalker + + :arg tree: the tree to walk + + """ + self.tree = tree + + def __iter__(self): + raise NotImplementedError + + def error(self, msg): + """Generates an error token with the given message + + :arg msg: the error message + + :returns: SerializeError token + + """ + return {"type": "SerializeError", "data": msg} + + def emptyTag(self, namespace, name, attrs, hasChildren=False): + """Generates an EmptyTag token + + :arg namespace: the namespace of the token--can be ``None`` + + :arg name: the name of the element + + :arg attrs: the attributes of the element as a dict + + :arg hasChildren: whether or not to yield a SerializationError because + this tag shouldn't have children + + :returns: EmptyTag token + + """ + yield {"type": "EmptyTag", "name": name, + "namespace": namespace, + "data": attrs} + if hasChildren: + yield self.error("Void element has children") + + def startTag(self, namespace, name, attrs): + """Generates a StartTag token + + :arg namespace: the namespace of the token--can be ``None`` + + :arg name: the name of the element + + :arg attrs: the attributes of the element as a dict + + :returns: StartTag token + + """ + return {"type": "StartTag", + "name": name, + "namespace": namespace, + "data": attrs} + + def endTag(self, namespace, name): + """Generates an EndTag token + + :arg namespace: the namespace of the token--can be ``None`` + + :arg name: the name of the element + + :returns: EndTag token + + """ + return {"type": "EndTag", + "name": name, + "namespace": namespace} + + def text(self, data): + """Generates SpaceCharacters and Characters tokens + + Depending on what's in the data, this generates one or more + ``SpaceCharacters`` and ``Characters`` tokens. + + For example: + + >>> from html5lib.treewalkers.base import TreeWalker + >>> # Give it an empty tree just so it instantiates + >>> walker = TreeWalker([]) + >>> list(walker.text('')) + [] + >>> list(walker.text(' ')) + [{u'data': ' ', u'type': u'SpaceCharacters'}] + >>> list(walker.text(' abc ')) # doctest: +NORMALIZE_WHITESPACE + [{u'data': ' ', u'type': u'SpaceCharacters'}, + {u'data': u'abc', u'type': u'Characters'}, + {u'data': u' ', u'type': u'SpaceCharacters'}] + + :arg data: the text data + + :returns: one or more ``SpaceCharacters`` and ``Characters`` tokens + + """ + data = data + middle = data.lstrip(spaceCharacters) + left = data[:len(data) - len(middle)] + if left: + yield {"type": "SpaceCharacters", "data": left} + data = middle + middle = data.rstrip(spaceCharacters) + right = data[len(middle):] + if middle: + yield {"type": "Characters", "data": middle} + if right: + yield {"type": "SpaceCharacters", "data": right} + + def comment(self, data): + """Generates a Comment token + + :arg data: the comment + + :returns: Comment token + + """ + return {"type": "Comment", "data": data} + + def doctype(self, name, publicId=None, systemId=None): + """Generates a Doctype token + + :arg name: + + :arg publicId: + + :arg systemId: + + :returns: the Doctype token + + """ + return {"type": "Doctype", + "name": name, + "publicId": publicId, + "systemId": systemId} + + def entity(self, name): + """Generates an Entity token + + :arg name: the entity name + + :returns: an Entity token + + """ + return {"type": "Entity", "name": name} + + def unknown(self, nodeType): + """Handles unknown node types""" + return self.error("Unknown node type: " + nodeType) + + +class NonRecursiveTreeWalker(TreeWalker): + def getNodeDetails(self, node): + raise NotImplementedError + + def getFirstChild(self, node): + raise NotImplementedError + + def getNextSibling(self, node): + raise NotImplementedError + + def getParentNode(self, node): + raise NotImplementedError + + def __iter__(self): + currentNode = self.tree + while currentNode is not None: + details = self.getNodeDetails(currentNode) + type, details = details[0], details[1:] + hasChildren = False + + if type == DOCTYPE: + yield self.doctype(*details) + + elif type == TEXT: + for token in self.text(*details): + yield token + + elif type == ELEMENT: + namespace, name, attributes, hasChildren = details + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + for token in self.emptyTag(namespace, name, attributes, + hasChildren): + yield token + hasChildren = False + else: + yield self.startTag(namespace, name, attributes) + + elif type == COMMENT: + yield self.comment(details[0]) + + elif type == ENTITY: + yield self.entity(details[0]) + + elif type == DOCUMENT: + hasChildren = True + + else: + yield self.unknown(details[0]) + + if hasChildren: + firstChild = self.getFirstChild(currentNode) + else: + firstChild = None + + if firstChild is not None: + currentNode = firstChild + else: + while currentNode is not None: + details = self.getNodeDetails(currentNode) + type, details = details[0], details[1:] + if type == ELEMENT: + namespace, name, attributes, hasChildren = details + if (namespace and namespace != namespaces["html"]) or name not in voidElements: + yield self.endTag(namespace, name) + if self.tree is currentNode: + currentNode = None + break + nextSibling = self.getNextSibling(currentNode) + if nextSibling is not None: + currentNode = nextSibling + break + else: + currentNode = self.getParentNode(currentNode) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py new file mode 100644 index 0000000..b0c89b0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/dom.py @@ -0,0 +1,43 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.dom import Node + +from . import base + + +class TreeWalker(base.NonRecursiveTreeWalker): + def getNodeDetails(self, node): + if node.nodeType == Node.DOCUMENT_TYPE_NODE: + return base.DOCTYPE, node.name, node.publicId, node.systemId + + elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): + return base.TEXT, node.nodeValue + + elif node.nodeType == Node.ELEMENT_NODE: + attrs = {} + for attr in list(node.attributes.keys()): + attr = node.getAttributeNode(attr) + if attr.namespaceURI: + attrs[(attr.namespaceURI, attr.localName)] = attr.value + else: + attrs[(None, attr.name)] = attr.value + return (base.ELEMENT, node.namespaceURI, node.nodeName, + attrs, node.hasChildNodes()) + + elif node.nodeType == Node.COMMENT_NODE: + return base.COMMENT, node.nodeValue + + elif node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE): + return (base.DOCUMENT,) + + else: + return base.UNKNOWN, node.nodeType + + def getFirstChild(self, node): + return node.firstChild + + def getNextSibling(self, node): + return node.nextSibling + + def getParentNode(self, node): + return node.parentNode diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py new file mode 100644 index 0000000..95fc0c1 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree.py @@ -0,0 +1,130 @@ +from __future__ import absolute_import, division, unicode_literals + +from collections import OrderedDict +import re + +from pip._vendor.six import string_types + +from . import base +from .._utils import moduleFactoryFactory + +tag_regexp = re.compile("{([^}]*)}(.*)") + + +def getETreeBuilder(ElementTreeImplementation): + ElementTree = ElementTreeImplementation + ElementTreeCommentType = ElementTree.Comment("asd").tag + + class TreeWalker(base.NonRecursiveTreeWalker): # pylint:disable=unused-variable + """Given the particular ElementTree representation, this implementation, + to avoid using recursion, returns "nodes" as tuples with the following + content: + + 1. The current element + + 2. The index of the element relative to its parent + + 3. A stack of ancestor elements + + 4. A flag "text", "tail" or None to indicate if the current node is a + text node; either the text or tail of the current element (1) + """ + def getNodeDetails(self, node): + if isinstance(node, tuple): # It might be the root Element + elt, _, _, flag = node + if flag in ("text", "tail"): + return base.TEXT, getattr(elt, flag) + else: + node = elt + + if not(hasattr(node, "tag")): + node = node.getroot() + + if node.tag in ("DOCUMENT_ROOT", "DOCUMENT_FRAGMENT"): + return (base.DOCUMENT,) + + elif node.tag == "<!DOCTYPE>": + return (base.DOCTYPE, node.text, + node.get("publicId"), node.get("systemId")) + + elif node.tag == ElementTreeCommentType: + return base.COMMENT, node.text + + else: + assert isinstance(node.tag, string_types), type(node.tag) + # This is assumed to be an ordinary element + match = tag_regexp.match(node.tag) + if match: + namespace, tag = match.groups() + else: + namespace = None + tag = node.tag + attrs = OrderedDict() + for name, value in list(node.attrib.items()): + match = tag_regexp.match(name) + if match: + attrs[(match.group(1), match.group(2))] = value + else: + attrs[(None, name)] = value + return (base.ELEMENT, namespace, tag, + attrs, len(node) or node.text) + + def getFirstChild(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + element, key, parents, flag = node, None, [], None + + if flag in ("text", "tail"): + return None + else: + if element.text: + return element, key, parents, "text" + elif len(element): + parents.append(element) + return element[0], 0, parents, None + else: + return None + + def getNextSibling(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + return None + + if flag == "text": + if len(element): + parents.append(element) + return element[0], 0, parents, None + else: + return None + else: + if element.tail and flag != "tail": + return element, key, parents, "tail" + elif key < len(parents[-1]) - 1: + return parents[-1][key + 1], key + 1, parents, None + else: + return None + + def getParentNode(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + return None + + if flag == "text": + if not parents: + return element + else: + return element, key, parents, None + else: + parent = parents.pop() + if not parents: + return parent + else: + assert list(parents[-1]).count(parent) == 1 + return parent, list(parents[-1]).index(parent), parents, None + + return locals() + +getETreeModule = moduleFactoryFactory(getETreeBuilder) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py new file mode 100644 index 0000000..e81ddf3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py @@ -0,0 +1,213 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from lxml import etree +from ..treebuilders.etree import tag_regexp + +from . import base + +from .. import _ihatexml + + +def ensure_str(s): + if s is None: + return None + elif isinstance(s, text_type): + return s + else: + return s.decode("ascii", "strict") + + +class Root(object): + def __init__(self, et): + self.elementtree = et + self.children = [] + + try: + if et.docinfo.internalDTD: + self.children.append(Doctype(self, + ensure_str(et.docinfo.root_name), + ensure_str(et.docinfo.public_id), + ensure_str(et.docinfo.system_url))) + except AttributeError: + pass + + try: + node = et.getroot() + except AttributeError: + node = et + + while node.getprevious() is not None: + node = node.getprevious() + while node is not None: + self.children.append(node) + node = node.getnext() + + self.text = None + self.tail = None + + def __getitem__(self, key): + return self.children[key] + + def getnext(self): + return None + + def __len__(self): + return 1 + + +class Doctype(object): + def __init__(self, root_node, name, public_id, system_id): + self.root_node = root_node + self.name = name + self.public_id = public_id + self.system_id = system_id + + self.text = None + self.tail = None + + def getnext(self): + return self.root_node.children[1] + + +class FragmentRoot(Root): + def __init__(self, children): + self.children = [FragmentWrapper(self, child) for child in children] + self.text = self.tail = None + + def getnext(self): + return None + + +class FragmentWrapper(object): + def __init__(self, fragment_root, obj): + self.root_node = fragment_root + self.obj = obj + if hasattr(self.obj, 'text'): + self.text = ensure_str(self.obj.text) + else: + self.text = None + if hasattr(self.obj, 'tail'): + self.tail = ensure_str(self.obj.tail) + else: + self.tail = None + + def __getattr__(self, name): + return getattr(self.obj, name) + + def getnext(self): + siblings = self.root_node.children + idx = siblings.index(self) + if idx < len(siblings) - 1: + return siblings[idx + 1] + else: + return None + + def __getitem__(self, key): + return self.obj[key] + + def __bool__(self): + return bool(self.obj) + + def getparent(self): + return None + + def __str__(self): + return str(self.obj) + + def __unicode__(self): + return str(self.obj) + + def __len__(self): + return len(self.obj) + + +class TreeWalker(base.NonRecursiveTreeWalker): + def __init__(self, tree): + # pylint:disable=redefined-variable-type + if isinstance(tree, list): + self.fragmentChildren = set(tree) + tree = FragmentRoot(tree) + else: + self.fragmentChildren = set() + tree = Root(tree) + base.NonRecursiveTreeWalker.__init__(self, tree) + self.filter = _ihatexml.InfosetFilter() + + def getNodeDetails(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + return base.TEXT, ensure_str(getattr(node, key)) + + elif isinstance(node, Root): + return (base.DOCUMENT,) + + elif isinstance(node, Doctype): + return base.DOCTYPE, node.name, node.public_id, node.system_id + + elif isinstance(node, FragmentWrapper) and not hasattr(node, "tag"): + return base.TEXT, ensure_str(node.obj) + + elif node.tag == etree.Comment: + return base.COMMENT, ensure_str(node.text) + + elif node.tag == etree.Entity: + return base.ENTITY, ensure_str(node.text)[1:-1] # strip &; + + else: + # This is assumed to be an ordinary element + match = tag_regexp.match(ensure_str(node.tag)) + if match: + namespace, tag = match.groups() + else: + namespace = None + tag = ensure_str(node.tag) + attrs = {} + for name, value in list(node.attrib.items()): + name = ensure_str(name) + value = ensure_str(value) + match = tag_regexp.match(name) + if match: + attrs[(match.group(1), match.group(2))] = value + else: + attrs[(None, name)] = value + return (base.ELEMENT, namespace, self.filter.fromXmlName(tag), + attrs, len(node) > 0 or node.text) + + def getFirstChild(self, node): + assert not isinstance(node, tuple), "Text nodes have no children" + + assert len(node) or node.text, "Node has no children" + if node.text: + return (node, "text") + else: + return node[0] + + def getNextSibling(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + if key == "text": + # XXX: we cannot use a "bool(node) and node[0] or None" construct here + # because node[0] might evaluate to False if it has no child element + if len(node): + return node[0] + else: + return None + else: # tail + return node.getnext() + + return (node, "tail") if node.tail else node.getnext() + + def getParentNode(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + if key == "text": + return node + # else: fallback to "normal" processing + elif node in self.fragmentChildren: + return None + + return node.getparent() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py new file mode 100644 index 0000000..7483be2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py @@ -0,0 +1,69 @@ +from __future__ import absolute_import, division, unicode_literals + +from genshi.core import QName +from genshi.core import START, END, XML_NAMESPACE, DOCTYPE, TEXT +from genshi.core import START_NS, END_NS, START_CDATA, END_CDATA, PI, COMMENT + +from . import base + +from ..constants import voidElements, namespaces + + +class TreeWalker(base.TreeWalker): + def __iter__(self): + # Buffer the events so we can pass in the following one + previous = None + for event in self.tree: + if previous is not None: + for token in self.tokens(previous, event): + yield token + previous = event + + # Don't forget the final event! + if previous is not None: + for token in self.tokens(previous, None): + yield token + + def tokens(self, event, next): + kind, data, _ = event + if kind == START: + tag, attribs = data + name = tag.localname + namespace = tag.namespace + converted_attribs = {} + for k, v in attribs: + if isinstance(k, QName): + converted_attribs[(k.namespace, k.localname)] = v + else: + converted_attribs[(None, k)] = v + + if namespace == namespaces["html"] and name in voidElements: + for token in self.emptyTag(namespace, name, converted_attribs, + not next or next[0] != END or + next[1] != tag): + yield token + else: + yield self.startTag(namespace, name, converted_attribs) + + elif kind == END: + name = data.localname + namespace = data.namespace + if namespace != namespaces["html"] or name not in voidElements: + yield self.endTag(namespace, name) + + elif kind == COMMENT: + yield self.comment(data) + + elif kind == TEXT: + for token in self.text(data): + yield token + + elif kind == DOCTYPE: + yield self.doctype(*data) + + elif kind in (XML_NAMESPACE, DOCTYPE, START_NS, END_NS, + START_CDATA, END_CDATA, PI): + pass + + else: + yield self.unknown(kind) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/__init__.py new file mode 100644 index 0000000..847bf93 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/__init__.py @@ -0,0 +1,2 @@ +from .package_data import __version__ +from .core import * diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/codec.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/codec.py new file mode 100644 index 0000000..98c65ea --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/codec.py @@ -0,0 +1,118 @@ +from .core import encode, decode, alabel, ulabel, IDNAError +import codecs +import re + +_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') + +class Codec(codecs.Codec): + + def encode(self, data, errors='strict'): + + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return "", 0 + + return encode(data), len(data) + + def decode(self, data, errors='strict'): + + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return u"", 0 + + return decode(data), len(data) + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, data, errors, final): + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return ("", 0) + + labels = _unicode_dots_re.split(data) + trailing_dot = u'' + if labels: + if not labels[-1]: + trailing_dot = '.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = '.' + + result = [] + size = 0 + for label in labels: + result.append(alabel(label)) + if size: + size += 1 + size += len(label) + + # Join with U+002E + result = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, data, errors, final): + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return (u"", 0) + + # IDNA allows decoding to operate on Unicode strings, too. + if isinstance(data, unicode): + labels = _unicode_dots_re.split(data) + else: + # Must be ASCII string + data = str(data) + unicode(data, "ascii") + labels = data.split(".") + + trailing_dot = u'' + if labels: + if not labels[-1]: + trailing_dot = u'.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = u'.' + + result = [] + size = 0 + for label in labels: + result.append(ulabel(label)) + if size: + size += 1 + size += len(label) + + result = u".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + +class StreamReader(Codec, codecs.StreamReader): + pass + +def getregentry(): + return codecs.CodecInfo( + name='idna', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/compat.py new file mode 100644 index 0000000..4d47f33 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/compat.py @@ -0,0 +1,12 @@ +from .core import * +from .codec import * + +def ToASCII(label): + return encode(label) + +def ToUnicode(label): + return decode(label) + +def nameprep(s): + raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/core.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/core.py new file mode 100644 index 0000000..090c2c1 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/core.py @@ -0,0 +1,399 @@ +from . import idnadata +import bisect +import unicodedata +import re +import sys +from .intranges import intranges_contain + +_virama_combining_class = 9 +_alabel_prefix = b'xn--' +_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') + +if sys.version_info[0] == 3: + unicode = str + unichr = chr + +class IDNAError(UnicodeError): + """ Base exception for all IDNA-encoding related problems """ + pass + + +class IDNABidiError(IDNAError): + """ Exception when bidirectional requirements are not satisfied """ + pass + + +class InvalidCodepoint(IDNAError): + """ Exception when a disallowed or unallocated codepoint is used """ + pass + + +class InvalidCodepointContext(IDNAError): + """ Exception when the codepoint is not valid in the context it is used """ + pass + + +def _combining_class(cp): + v = unicodedata.combining(unichr(cp)) + if v == 0: + if not unicodedata.name(unichr(cp)): + raise ValueError("Unknown character in unicodedata") + return v + +def _is_script(cp, script): + return intranges_contain(ord(cp), idnadata.scripts[script]) + +def _punycode(s): + return s.encode('punycode') + +def _unot(s): + return 'U+{0:04X}'.format(s) + + +def valid_label_length(label): + + if len(label) > 63: + return False + return True + + +def valid_string_length(label, trailing_dot): + + if len(label) > (254 if trailing_dot else 253): + return False + return True + + +def check_bidi(label, check_ltr=False): + + # Bidi rules should only be applied if string contains RTL characters + bidi_label = False + for (idx, cp) in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + if direction == '': + # String likely comes from a newer version of Unicode + raise IDNABidiError('Unknown directionality in label {0} at position {1}'.format(repr(label), idx)) + if direction in ['R', 'AL', 'AN']: + bidi_label = True + if not bidi_label and not check_ltr: + return True + + # Bidi rule 1 + direction = unicodedata.bidirectional(label[0]) + if direction in ['R', 'AL']: + rtl = True + elif direction == 'L': + rtl = False + else: + raise IDNABidiError('First codepoint in label {0} must be directionality L, R or AL'.format(repr(label))) + + valid_ending = False + number_type = False + for (idx, cp) in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + + if rtl: + # Bidi rule 2 + if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: + raise IDNABidiError('Invalid direction for codepoint at position {0} in a right-to-left label'.format(idx)) + # Bidi rule 3 + if direction in ['R', 'AL', 'EN', 'AN']: + valid_ending = True + elif direction != 'NSM': + valid_ending = False + # Bidi rule 4 + if direction in ['AN', 'EN']: + if not number_type: + number_type = direction + else: + if number_type != direction: + raise IDNABidiError('Can not mix numeral types in a right-to-left label') + else: + # Bidi rule 5 + if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: + raise IDNABidiError('Invalid direction for codepoint at position {0} in a left-to-right label'.format(idx)) + # Bidi rule 6 + if direction in ['L', 'EN']: + valid_ending = True + elif direction != 'NSM': + valid_ending = False + + if not valid_ending: + raise IDNABidiError('Label ends with illegal codepoint directionality') + + return True + + +def check_initial_combiner(label): + + if unicodedata.category(label[0])[0] == 'M': + raise IDNAError('Label begins with an illegal combining character') + return True + + +def check_hyphen_ok(label): + + if label[2:4] == '--': + raise IDNAError('Label has disallowed hyphens in 3rd and 4th position') + if label[0] == '-' or label[-1] == '-': + raise IDNAError('Label must not start or end with a hyphen') + return True + + +def check_nfc(label): + + if unicodedata.normalize('NFC', label) != label: + raise IDNAError('Label must be in Normalization Form C') + + +def valid_contextj(label, pos): + + cp_value = ord(label[pos]) + + if cp_value == 0x200c: + + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + + ok = False + for i in range(pos-1, -1, -1): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord('T'): + continue + if joining_type in [ord('L'), ord('D')]: + ok = True + break + + if not ok: + return False + + ok = False + for i in range(pos+1, len(label)): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord('T'): + continue + if joining_type in [ord('R'), ord('D')]: + ok = True + break + return ok + + if cp_value == 0x200d: + + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + return False + + else: + + return False + + +def valid_contexto(label, pos, exception=False): + + cp_value = ord(label[pos]) + + if cp_value == 0x00b7: + if 0 < pos < len(label)-1: + if ord(label[pos - 1]) == 0x006c and ord(label[pos + 1]) == 0x006c: + return True + return False + + elif cp_value == 0x0375: + if pos < len(label)-1 and len(label) > 1: + return _is_script(label[pos + 1], 'Greek') + return False + + elif cp_value == 0x05f3 or cp_value == 0x05f4: + if pos > 0: + return _is_script(label[pos - 1], 'Hebrew') + return False + + elif cp_value == 0x30fb: + for cp in label: + if cp == u'\u30fb': + continue + if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'): + return True + return False + + elif 0x660 <= cp_value <= 0x669: + for cp in label: + if 0x6f0 <= ord(cp) <= 0x06f9: + return False + return True + + elif 0x6f0 <= cp_value <= 0x6f9: + for cp in label: + if 0x660 <= ord(cp) <= 0x0669: + return False + return True + + +def check_label(label): + + if isinstance(label, (bytes, bytearray)): + label = label.decode('utf-8') + if len(label) == 0: + raise IDNAError('Empty Label') + + check_nfc(label) + check_hyphen_ok(label) + check_initial_combiner(label) + + for (pos, cp) in enumerate(label): + cp_value = ord(cp) + if intranges_contain(cp_value, idnadata.codepoint_classes['PVALID']): + continue + elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']): + try: + if not valid_contextj(label, pos): + raise InvalidCodepointContext('Joiner {0} not allowed at position {1} in {2}'.format( + _unot(cp_value), pos+1, repr(label))) + except ValueError: + raise IDNAError('Unknown codepoint adjacent to joiner {0} at position {1} in {2}'.format( + _unot(cp_value), pos+1, repr(label))) + elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']): + if not valid_contexto(label, pos): + raise InvalidCodepointContext('Codepoint {0} not allowed at position {1} in {2}'.format(_unot(cp_value), pos+1, repr(label))) + else: + raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label))) + + check_bidi(label) + + +def alabel(label): + + try: + label = label.encode('ascii') + try: + ulabel(label) + except IDNAError: + raise IDNAError('The label {0} is not a valid A-label'.format(label)) + if not valid_label_length(label): + raise IDNAError('Label too long') + return label + except UnicodeEncodeError: + pass + + if not label: + raise IDNAError('No Input') + + label = unicode(label) + check_label(label) + label = _punycode(label) + label = _alabel_prefix + label + + if not valid_label_length(label): + raise IDNAError('Label too long') + + return label + + +def ulabel(label): + + if not isinstance(label, (bytes, bytearray)): + try: + label = label.encode('ascii') + except UnicodeEncodeError: + check_label(label) + return label + + label = label.lower() + if label.startswith(_alabel_prefix): + label = label[len(_alabel_prefix):] + else: + check_label(label) + return label.decode('ascii') + + label = label.decode('punycode') + check_label(label) + return label + + +def uts46_remap(domain, std3_rules=True, transitional=False): + """Re-map the characters in the string according to UTS46 processing.""" + from .uts46data import uts46data + output = u"" + try: + for pos, char in enumerate(domain): + code_point = ord(char) + uts46row = uts46data[code_point if code_point < 256 else + bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + status = uts46row[1] + replacement = uts46row[2] if len(uts46row) == 3 else None + if (status == "V" or + (status == "D" and not transitional) or + (status == "3" and not std3_rules and replacement is None)): + output += char + elif replacement is not None and (status == "M" or + (status == "3" and not std3_rules) or + (status == "D" and transitional)): + output += replacement + elif status != "I": + raise IndexError() + return unicodedata.normalize("NFC", output) + except IndexError: + raise InvalidCodepoint( + "Codepoint {0} not allowed at position {1} in {2}".format( + _unot(code_point), pos + 1, repr(domain))) + + +def encode(s, strict=False, uts46=False, std3_rules=False, transitional=False): + + if isinstance(s, (bytes, bytearray)): + s = s.decode("ascii") + if uts46: + s = uts46_remap(s, std3_rules, transitional) + trailing_dot = False + result = [] + if strict: + labels = s.split('.') + else: + labels = _unicode_dots_re.split(s) + if not labels or labels == ['']: + raise IDNAError('Empty domain') + if labels[-1] == '': + del labels[-1] + trailing_dot = True + for label in labels: + s = alabel(label) + if s: + result.append(s) + else: + raise IDNAError('Empty label') + if trailing_dot: + result.append(b'') + s = b'.'.join(result) + if not valid_string_length(s, trailing_dot): + raise IDNAError('Domain too long') + return s + + +def decode(s, strict=False, uts46=False, std3_rules=False): + + if isinstance(s, (bytes, bytearray)): + s = s.decode("ascii") + if uts46: + s = uts46_remap(s, std3_rules, False) + trailing_dot = False + result = [] + if not strict: + labels = _unicode_dots_re.split(s) + else: + labels = s.split(u'.') + if not labels or labels == ['']: + raise IDNAError('Empty domain') + if not labels[-1]: + del labels[-1] + trailing_dot = True + for label in labels: + s = ulabel(label) + if s: + result.append(s) + else: + raise IDNAError('Empty label') + if trailing_dot: + result.append(u'') + return u'.'.join(result) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/idnadata.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/idnadata.py new file mode 100644 index 0000000..17974e2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/idnadata.py @@ -0,0 +1,1893 @@ +# This file is automatically generated by tools/idna-data + +__version__ = "10.0.0" +scripts = { + 'Greek': ( + 0x37000000374, + 0x37500000378, + 0x37a0000037e, + 0x37f00000380, + 0x38400000385, + 0x38600000387, + 0x3880000038b, + 0x38c0000038d, + 0x38e000003a2, + 0x3a3000003e2, + 0x3f000000400, + 0x1d2600001d2b, + 0x1d5d00001d62, + 0x1d6600001d6b, + 0x1dbf00001dc0, + 0x1f0000001f16, + 0x1f1800001f1e, + 0x1f2000001f46, + 0x1f4800001f4e, + 0x1f5000001f58, + 0x1f5900001f5a, + 0x1f5b00001f5c, + 0x1f5d00001f5e, + 0x1f5f00001f7e, + 0x1f8000001fb5, + 0x1fb600001fc5, + 0x1fc600001fd4, + 0x1fd600001fdc, + 0x1fdd00001ff0, + 0x1ff200001ff5, + 0x1ff600001fff, + 0x212600002127, + 0xab650000ab66, + 0x101400001018f, + 0x101a0000101a1, + 0x1d2000001d246, + ), + 'Han': ( + 0x2e8000002e9a, + 0x2e9b00002ef4, + 0x2f0000002fd6, + 0x300500003006, + 0x300700003008, + 0x30210000302a, + 0x30380000303c, + 0x340000004db6, + 0x4e0000009feb, + 0xf9000000fa6e, + 0xfa700000fada, + 0x200000002a6d7, + 0x2a7000002b735, + 0x2b7400002b81e, + 0x2b8200002cea2, + 0x2ceb00002ebe1, + 0x2f8000002fa1e, + ), + 'Hebrew': ( + 0x591000005c8, + 0x5d0000005eb, + 0x5f0000005f5, + 0xfb1d0000fb37, + 0xfb380000fb3d, + 0xfb3e0000fb3f, + 0xfb400000fb42, + 0xfb430000fb45, + 0xfb460000fb50, + ), + 'Hiragana': ( + 0x304100003097, + 0x309d000030a0, + 0x1b0010001b11f, + 0x1f2000001f201, + ), + 'Katakana': ( + 0x30a1000030fb, + 0x30fd00003100, + 0x31f000003200, + 0x32d0000032ff, + 0x330000003358, + 0xff660000ff70, + 0xff710000ff9e, + 0x1b0000001b001, + ), +} +joining_types = { + 0x600: 85, + 0x601: 85, + 0x602: 85, + 0x603: 85, + 0x604: 85, + 0x605: 85, + 0x608: 85, + 0x60b: 85, + 0x620: 68, + 0x621: 85, + 0x622: 82, + 0x623: 82, + 0x624: 82, + 0x625: 82, + 0x626: 68, + 0x627: 82, + 0x628: 68, + 0x629: 82, + 0x62a: 68, + 0x62b: 68, + 0x62c: 68, + 0x62d: 68, + 0x62e: 68, + 0x62f: 82, + 0x630: 82, + 0x631: 82, + 0x632: 82, + 0x633: 68, + 0x634: 68, + 0x635: 68, + 0x636: 68, + 0x637: 68, + 0x638: 68, + 0x639: 68, + 0x63a: 68, + 0x63b: 68, + 0x63c: 68, + 0x63d: 68, + 0x63e: 68, + 0x63f: 68, + 0x640: 67, + 0x641: 68, + 0x642: 68, + 0x643: 68, + 0x644: 68, + 0x645: 68, + 0x646: 68, + 0x647: 68, + 0x648: 82, + 0x649: 68, + 0x64a: 68, + 0x66e: 68, + 0x66f: 68, + 0x671: 82, + 0x672: 82, + 0x673: 82, + 0x674: 85, + 0x675: 82, + 0x676: 82, + 0x677: 82, + 0x678: 68, + 0x679: 68, + 0x67a: 68, + 0x67b: 68, + 0x67c: 68, + 0x67d: 68, + 0x67e: 68, + 0x67f: 68, + 0x680: 68, + 0x681: 68, + 0x682: 68, + 0x683: 68, + 0x684: 68, + 0x685: 68, + 0x686: 68, + 0x687: 68, + 0x688: 82, + 0x689: 82, + 0x68a: 82, + 0x68b: 82, + 0x68c: 82, + 0x68d: 82, + 0x68e: 82, + 0x68f: 82, + 0x690: 82, + 0x691: 82, + 0x692: 82, + 0x693: 82, + 0x694: 82, + 0x695: 82, + 0x696: 82, + 0x697: 82, + 0x698: 82, + 0x699: 82, + 0x69a: 68, + 0x69b: 68, + 0x69c: 68, + 0x69d: 68, + 0x69e: 68, + 0x69f: 68, + 0x6a0: 68, + 0x6a1: 68, + 0x6a2: 68, + 0x6a3: 68, + 0x6a4: 68, + 0x6a5: 68, + 0x6a6: 68, + 0x6a7: 68, + 0x6a8: 68, + 0x6a9: 68, + 0x6aa: 68, + 0x6ab: 68, + 0x6ac: 68, + 0x6ad: 68, + 0x6ae: 68, + 0x6af: 68, + 0x6b0: 68, + 0x6b1: 68, + 0x6b2: 68, + 0x6b3: 68, + 0x6b4: 68, + 0x6b5: 68, + 0x6b6: 68, + 0x6b7: 68, + 0x6b8: 68, + 0x6b9: 68, + 0x6ba: 68, + 0x6bb: 68, + 0x6bc: 68, + 0x6bd: 68, + 0x6be: 68, + 0x6bf: 68, + 0x6c0: 82, + 0x6c1: 68, + 0x6c2: 68, + 0x6c3: 82, + 0x6c4: 82, + 0x6c5: 82, + 0x6c6: 82, + 0x6c7: 82, + 0x6c8: 82, + 0x6c9: 82, + 0x6ca: 82, + 0x6cb: 82, + 0x6cc: 68, + 0x6cd: 82, + 0x6ce: 68, + 0x6cf: 82, + 0x6d0: 68, + 0x6d1: 68, + 0x6d2: 82, + 0x6d3: 82, + 0x6d5: 82, + 0x6dd: 85, + 0x6ee: 82, + 0x6ef: 82, + 0x6fa: 68, + 0x6fb: 68, + 0x6fc: 68, + 0x6ff: 68, + 0x710: 82, + 0x712: 68, + 0x713: 68, + 0x714: 68, + 0x715: 82, + 0x716: 82, + 0x717: 82, + 0x718: 82, + 0x719: 82, + 0x71a: 68, + 0x71b: 68, + 0x71c: 68, + 0x71d: 68, + 0x71e: 82, + 0x71f: 68, + 0x720: 68, + 0x721: 68, + 0x722: 68, + 0x723: 68, + 0x724: 68, + 0x725: 68, + 0x726: 68, + 0x727: 68, + 0x728: 82, + 0x729: 68, + 0x72a: 82, + 0x72b: 68, + 0x72c: 82, + 0x72d: 68, + 0x72e: 68, + 0x72f: 82, + 0x74d: 82, + 0x74e: 68, + 0x74f: 68, + 0x750: 68, + 0x751: 68, + 0x752: 68, + 0x753: 68, + 0x754: 68, + 0x755: 68, + 0x756: 68, + 0x757: 68, + 0x758: 68, + 0x759: 82, + 0x75a: 82, + 0x75b: 82, + 0x75c: 68, + 0x75d: 68, + 0x75e: 68, + 0x75f: 68, + 0x760: 68, + 0x761: 68, + 0x762: 68, + 0x763: 68, + 0x764: 68, + 0x765: 68, + 0x766: 68, + 0x767: 68, + 0x768: 68, + 0x769: 68, + 0x76a: 68, + 0x76b: 82, + 0x76c: 82, + 0x76d: 68, + 0x76e: 68, + 0x76f: 68, + 0x770: 68, + 0x771: 82, + 0x772: 68, + 0x773: 82, + 0x774: 82, + 0x775: 68, + 0x776: 68, + 0x777: 68, + 0x778: 82, + 0x779: 82, + 0x77a: 68, + 0x77b: 68, + 0x77c: 68, + 0x77d: 68, + 0x77e: 68, + 0x77f: 68, + 0x7ca: 68, + 0x7cb: 68, + 0x7cc: 68, + 0x7cd: 68, + 0x7ce: 68, + 0x7cf: 68, + 0x7d0: 68, + 0x7d1: 68, + 0x7d2: 68, + 0x7d3: 68, + 0x7d4: 68, + 0x7d5: 68, + 0x7d6: 68, + 0x7d7: 68, + 0x7d8: 68, + 0x7d9: 68, + 0x7da: 68, + 0x7db: 68, + 0x7dc: 68, + 0x7dd: 68, + 0x7de: 68, + 0x7df: 68, + 0x7e0: 68, + 0x7e1: 68, + 0x7e2: 68, + 0x7e3: 68, + 0x7e4: 68, + 0x7e5: 68, + 0x7e6: 68, + 0x7e7: 68, + 0x7e8: 68, + 0x7e9: 68, + 0x7ea: 68, + 0x7fa: 67, + 0x840: 82, + 0x841: 68, + 0x842: 68, + 0x843: 68, + 0x844: 68, + 0x845: 68, + 0x846: 82, + 0x847: 82, + 0x848: 68, + 0x849: 82, + 0x84a: 68, + 0x84b: 68, + 0x84c: 68, + 0x84d: 68, + 0x84e: 68, + 0x84f: 68, + 0x850: 68, + 0x851: 68, + 0x852: 68, + 0x853: 68, + 0x854: 82, + 0x855: 68, + 0x856: 85, + 0x857: 85, + 0x858: 85, + 0x860: 68, + 0x861: 85, + 0x862: 68, + 0x863: 68, + 0x864: 68, + 0x865: 68, + 0x866: 85, + 0x867: 82, + 0x868: 68, + 0x869: 82, + 0x86a: 82, + 0x8a0: 68, + 0x8a1: 68, + 0x8a2: 68, + 0x8a3: 68, + 0x8a4: 68, + 0x8a5: 68, + 0x8a6: 68, + 0x8a7: 68, + 0x8a8: 68, + 0x8a9: 68, + 0x8aa: 82, + 0x8ab: 82, + 0x8ac: 82, + 0x8ad: 85, + 0x8ae: 82, + 0x8af: 68, + 0x8b0: 68, + 0x8b1: 82, + 0x8b2: 82, + 0x8b3: 68, + 0x8b4: 68, + 0x8b6: 68, + 0x8b7: 68, + 0x8b8: 68, + 0x8b9: 82, + 0x8ba: 68, + 0x8bb: 68, + 0x8bc: 68, + 0x8bd: 68, + 0x8e2: 85, + 0x1806: 85, + 0x1807: 68, + 0x180a: 67, + 0x180e: 85, + 0x1820: 68, + 0x1821: 68, + 0x1822: 68, + 0x1823: 68, + 0x1824: 68, + 0x1825: 68, + 0x1826: 68, + 0x1827: 68, + 0x1828: 68, + 0x1829: 68, + 0x182a: 68, + 0x182b: 68, + 0x182c: 68, + 0x182d: 68, + 0x182e: 68, + 0x182f: 68, + 0x1830: 68, + 0x1831: 68, + 0x1832: 68, + 0x1833: 68, + 0x1834: 68, + 0x1835: 68, + 0x1836: 68, + 0x1837: 68, + 0x1838: 68, + 0x1839: 68, + 0x183a: 68, + 0x183b: 68, + 0x183c: 68, + 0x183d: 68, + 0x183e: 68, + 0x183f: 68, + 0x1840: 68, + 0x1841: 68, + 0x1842: 68, + 0x1843: 68, + 0x1844: 68, + 0x1845: 68, + 0x1846: 68, + 0x1847: 68, + 0x1848: 68, + 0x1849: 68, + 0x184a: 68, + 0x184b: 68, + 0x184c: 68, + 0x184d: 68, + 0x184e: 68, + 0x184f: 68, + 0x1850: 68, + 0x1851: 68, + 0x1852: 68, + 0x1853: 68, + 0x1854: 68, + 0x1855: 68, + 0x1856: 68, + 0x1857: 68, + 0x1858: 68, + 0x1859: 68, + 0x185a: 68, + 0x185b: 68, + 0x185c: 68, + 0x185d: 68, + 0x185e: 68, + 0x185f: 68, + 0x1860: 68, + 0x1861: 68, + 0x1862: 68, + 0x1863: 68, + 0x1864: 68, + 0x1865: 68, + 0x1866: 68, + 0x1867: 68, + 0x1868: 68, + 0x1869: 68, + 0x186a: 68, + 0x186b: 68, + 0x186c: 68, + 0x186d: 68, + 0x186e: 68, + 0x186f: 68, + 0x1870: 68, + 0x1871: 68, + 0x1872: 68, + 0x1873: 68, + 0x1874: 68, + 0x1875: 68, + 0x1876: 68, + 0x1877: 68, + 0x1880: 85, + 0x1881: 85, + 0x1882: 85, + 0x1883: 85, + 0x1884: 85, + 0x1885: 84, + 0x1886: 84, + 0x1887: 68, + 0x1888: 68, + 0x1889: 68, + 0x188a: 68, + 0x188b: 68, + 0x188c: 68, + 0x188d: 68, + 0x188e: 68, + 0x188f: 68, + 0x1890: 68, + 0x1891: 68, + 0x1892: 68, + 0x1893: 68, + 0x1894: 68, + 0x1895: 68, + 0x1896: 68, + 0x1897: 68, + 0x1898: 68, + 0x1899: 68, + 0x189a: 68, + 0x189b: 68, + 0x189c: 68, + 0x189d: 68, + 0x189e: 68, + 0x189f: 68, + 0x18a0: 68, + 0x18a1: 68, + 0x18a2: 68, + 0x18a3: 68, + 0x18a4: 68, + 0x18a5: 68, + 0x18a6: 68, + 0x18a7: 68, + 0x18a8: 68, + 0x18aa: 68, + 0x200c: 85, + 0x200d: 67, + 0x202f: 85, + 0x2066: 85, + 0x2067: 85, + 0x2068: 85, + 0x2069: 85, + 0xa840: 68, + 0xa841: 68, + 0xa842: 68, + 0xa843: 68, + 0xa844: 68, + 0xa845: 68, + 0xa846: 68, + 0xa847: 68, + 0xa848: 68, + 0xa849: 68, + 0xa84a: 68, + 0xa84b: 68, + 0xa84c: 68, + 0xa84d: 68, + 0xa84e: 68, + 0xa84f: 68, + 0xa850: 68, + 0xa851: 68, + 0xa852: 68, + 0xa853: 68, + 0xa854: 68, + 0xa855: 68, + 0xa856: 68, + 0xa857: 68, + 0xa858: 68, + 0xa859: 68, + 0xa85a: 68, + 0xa85b: 68, + 0xa85c: 68, + 0xa85d: 68, + 0xa85e: 68, + 0xa85f: 68, + 0xa860: 68, + 0xa861: 68, + 0xa862: 68, + 0xa863: 68, + 0xa864: 68, + 0xa865: 68, + 0xa866: 68, + 0xa867: 68, + 0xa868: 68, + 0xa869: 68, + 0xa86a: 68, + 0xa86b: 68, + 0xa86c: 68, + 0xa86d: 68, + 0xa86e: 68, + 0xa86f: 68, + 0xa870: 68, + 0xa871: 68, + 0xa872: 76, + 0xa873: 85, + 0x10ac0: 68, + 0x10ac1: 68, + 0x10ac2: 68, + 0x10ac3: 68, + 0x10ac4: 68, + 0x10ac5: 82, + 0x10ac6: 85, + 0x10ac7: 82, + 0x10ac8: 85, + 0x10ac9: 82, + 0x10aca: 82, + 0x10acb: 85, + 0x10acc: 85, + 0x10acd: 76, + 0x10ace: 82, + 0x10acf: 82, + 0x10ad0: 82, + 0x10ad1: 82, + 0x10ad2: 82, + 0x10ad3: 68, + 0x10ad4: 68, + 0x10ad5: 68, + 0x10ad6: 68, + 0x10ad7: 76, + 0x10ad8: 68, + 0x10ad9: 68, + 0x10ada: 68, + 0x10adb: 68, + 0x10adc: 68, + 0x10add: 82, + 0x10ade: 68, + 0x10adf: 68, + 0x10ae0: 68, + 0x10ae1: 82, + 0x10ae2: 85, + 0x10ae3: 85, + 0x10ae4: 82, + 0x10aeb: 68, + 0x10aec: 68, + 0x10aed: 68, + 0x10aee: 68, + 0x10aef: 82, + 0x10b80: 68, + 0x10b81: 82, + 0x10b82: 68, + 0x10b83: 82, + 0x10b84: 82, + 0x10b85: 82, + 0x10b86: 68, + 0x10b87: 68, + 0x10b88: 68, + 0x10b89: 82, + 0x10b8a: 68, + 0x10b8b: 68, + 0x10b8c: 82, + 0x10b8d: 68, + 0x10b8e: 82, + 0x10b8f: 82, + 0x10b90: 68, + 0x10b91: 82, + 0x10ba9: 82, + 0x10baa: 82, + 0x10bab: 82, + 0x10bac: 82, + 0x10bad: 68, + 0x10bae: 68, + 0x10baf: 85, + 0x1e900: 68, + 0x1e901: 68, + 0x1e902: 68, + 0x1e903: 68, + 0x1e904: 68, + 0x1e905: 68, + 0x1e906: 68, + 0x1e907: 68, + 0x1e908: 68, + 0x1e909: 68, + 0x1e90a: 68, + 0x1e90b: 68, + 0x1e90c: 68, + 0x1e90d: 68, + 0x1e90e: 68, + 0x1e90f: 68, + 0x1e910: 68, + 0x1e911: 68, + 0x1e912: 68, + 0x1e913: 68, + 0x1e914: 68, + 0x1e915: 68, + 0x1e916: 68, + 0x1e917: 68, + 0x1e918: 68, + 0x1e919: 68, + 0x1e91a: 68, + 0x1e91b: 68, + 0x1e91c: 68, + 0x1e91d: 68, + 0x1e91e: 68, + 0x1e91f: 68, + 0x1e920: 68, + 0x1e921: 68, + 0x1e922: 68, + 0x1e923: 68, + 0x1e924: 68, + 0x1e925: 68, + 0x1e926: 68, + 0x1e927: 68, + 0x1e928: 68, + 0x1e929: 68, + 0x1e92a: 68, + 0x1e92b: 68, + 0x1e92c: 68, + 0x1e92d: 68, + 0x1e92e: 68, + 0x1e92f: 68, + 0x1e930: 68, + 0x1e931: 68, + 0x1e932: 68, + 0x1e933: 68, + 0x1e934: 68, + 0x1e935: 68, + 0x1e936: 68, + 0x1e937: 68, + 0x1e938: 68, + 0x1e939: 68, + 0x1e93a: 68, + 0x1e93b: 68, + 0x1e93c: 68, + 0x1e93d: 68, + 0x1e93e: 68, + 0x1e93f: 68, + 0x1e940: 68, + 0x1e941: 68, + 0x1e942: 68, + 0x1e943: 68, +} +codepoint_classes = { + 'PVALID': ( + 0x2d0000002e, + 0x300000003a, + 0x610000007b, + 0xdf000000f7, + 0xf800000100, + 0x10100000102, + 0x10300000104, + 0x10500000106, + 0x10700000108, + 0x1090000010a, + 0x10b0000010c, + 0x10d0000010e, + 0x10f00000110, + 0x11100000112, + 0x11300000114, + 0x11500000116, + 0x11700000118, + 0x1190000011a, + 0x11b0000011c, + 0x11d0000011e, + 0x11f00000120, + 0x12100000122, + 0x12300000124, + 0x12500000126, + 0x12700000128, + 0x1290000012a, + 0x12b0000012c, + 0x12d0000012e, + 0x12f00000130, + 0x13100000132, + 0x13500000136, + 0x13700000139, + 0x13a0000013b, + 0x13c0000013d, + 0x13e0000013f, + 0x14200000143, + 0x14400000145, + 0x14600000147, + 0x14800000149, + 0x14b0000014c, + 0x14d0000014e, + 0x14f00000150, + 0x15100000152, + 0x15300000154, + 0x15500000156, + 0x15700000158, + 0x1590000015a, + 0x15b0000015c, + 0x15d0000015e, + 0x15f00000160, + 0x16100000162, + 0x16300000164, + 0x16500000166, + 0x16700000168, + 0x1690000016a, + 0x16b0000016c, + 0x16d0000016e, + 0x16f00000170, + 0x17100000172, + 0x17300000174, + 0x17500000176, + 0x17700000178, + 0x17a0000017b, + 0x17c0000017d, + 0x17e0000017f, + 0x18000000181, + 0x18300000184, + 0x18500000186, + 0x18800000189, + 0x18c0000018e, + 0x19200000193, + 0x19500000196, + 0x1990000019c, + 0x19e0000019f, + 0x1a1000001a2, + 0x1a3000001a4, + 0x1a5000001a6, + 0x1a8000001a9, + 0x1aa000001ac, + 0x1ad000001ae, + 0x1b0000001b1, + 0x1b4000001b5, + 0x1b6000001b7, + 0x1b9000001bc, + 0x1bd000001c4, + 0x1ce000001cf, + 0x1d0000001d1, + 0x1d2000001d3, + 0x1d4000001d5, + 0x1d6000001d7, + 0x1d8000001d9, + 0x1da000001db, + 0x1dc000001de, + 0x1df000001e0, + 0x1e1000001e2, + 0x1e3000001e4, + 0x1e5000001e6, + 0x1e7000001e8, + 0x1e9000001ea, + 0x1eb000001ec, + 0x1ed000001ee, + 0x1ef000001f1, + 0x1f5000001f6, + 0x1f9000001fa, + 0x1fb000001fc, + 0x1fd000001fe, + 0x1ff00000200, + 0x20100000202, + 0x20300000204, + 0x20500000206, + 0x20700000208, + 0x2090000020a, + 0x20b0000020c, + 0x20d0000020e, + 0x20f00000210, + 0x21100000212, + 0x21300000214, + 0x21500000216, + 0x21700000218, + 0x2190000021a, + 0x21b0000021c, + 0x21d0000021e, + 0x21f00000220, + 0x22100000222, + 0x22300000224, + 0x22500000226, + 0x22700000228, + 0x2290000022a, + 0x22b0000022c, + 0x22d0000022e, + 0x22f00000230, + 0x23100000232, + 0x2330000023a, + 0x23c0000023d, + 0x23f00000241, + 0x24200000243, + 0x24700000248, + 0x2490000024a, + 0x24b0000024c, + 0x24d0000024e, + 0x24f000002b0, + 0x2b9000002c2, + 0x2c6000002d2, + 0x2ec000002ed, + 0x2ee000002ef, + 0x30000000340, + 0x34200000343, + 0x3460000034f, + 0x35000000370, + 0x37100000372, + 0x37300000374, + 0x37700000378, + 0x37b0000037e, + 0x39000000391, + 0x3ac000003cf, + 0x3d7000003d8, + 0x3d9000003da, + 0x3db000003dc, + 0x3dd000003de, + 0x3df000003e0, + 0x3e1000003e2, + 0x3e3000003e4, + 0x3e5000003e6, + 0x3e7000003e8, + 0x3e9000003ea, + 0x3eb000003ec, + 0x3ed000003ee, + 0x3ef000003f0, + 0x3f3000003f4, + 0x3f8000003f9, + 0x3fb000003fd, + 0x43000000460, + 0x46100000462, + 0x46300000464, + 0x46500000466, + 0x46700000468, + 0x4690000046a, + 0x46b0000046c, + 0x46d0000046e, + 0x46f00000470, + 0x47100000472, + 0x47300000474, + 0x47500000476, + 0x47700000478, + 0x4790000047a, + 0x47b0000047c, + 0x47d0000047e, + 0x47f00000480, + 0x48100000482, + 0x48300000488, + 0x48b0000048c, + 0x48d0000048e, + 0x48f00000490, + 0x49100000492, + 0x49300000494, + 0x49500000496, + 0x49700000498, + 0x4990000049a, + 0x49b0000049c, + 0x49d0000049e, + 0x49f000004a0, + 0x4a1000004a2, + 0x4a3000004a4, + 0x4a5000004a6, + 0x4a7000004a8, + 0x4a9000004aa, + 0x4ab000004ac, + 0x4ad000004ae, + 0x4af000004b0, + 0x4b1000004b2, + 0x4b3000004b4, + 0x4b5000004b6, + 0x4b7000004b8, + 0x4b9000004ba, + 0x4bb000004bc, + 0x4bd000004be, + 0x4bf000004c0, + 0x4c2000004c3, + 0x4c4000004c5, + 0x4c6000004c7, + 0x4c8000004c9, + 0x4ca000004cb, + 0x4cc000004cd, + 0x4ce000004d0, + 0x4d1000004d2, + 0x4d3000004d4, + 0x4d5000004d6, + 0x4d7000004d8, + 0x4d9000004da, + 0x4db000004dc, + 0x4dd000004de, + 0x4df000004e0, + 0x4e1000004e2, + 0x4e3000004e4, + 0x4e5000004e6, + 0x4e7000004e8, + 0x4e9000004ea, + 0x4eb000004ec, + 0x4ed000004ee, + 0x4ef000004f0, + 0x4f1000004f2, + 0x4f3000004f4, + 0x4f5000004f6, + 0x4f7000004f8, + 0x4f9000004fa, + 0x4fb000004fc, + 0x4fd000004fe, + 0x4ff00000500, + 0x50100000502, + 0x50300000504, + 0x50500000506, + 0x50700000508, + 0x5090000050a, + 0x50b0000050c, + 0x50d0000050e, + 0x50f00000510, + 0x51100000512, + 0x51300000514, + 0x51500000516, + 0x51700000518, + 0x5190000051a, + 0x51b0000051c, + 0x51d0000051e, + 0x51f00000520, + 0x52100000522, + 0x52300000524, + 0x52500000526, + 0x52700000528, + 0x5290000052a, + 0x52b0000052c, + 0x52d0000052e, + 0x52f00000530, + 0x5590000055a, + 0x56100000587, + 0x591000005be, + 0x5bf000005c0, + 0x5c1000005c3, + 0x5c4000005c6, + 0x5c7000005c8, + 0x5d0000005eb, + 0x5f0000005f3, + 0x6100000061b, + 0x62000000640, + 0x64100000660, + 0x66e00000675, + 0x679000006d4, + 0x6d5000006dd, + 0x6df000006e9, + 0x6ea000006f0, + 0x6fa00000700, + 0x7100000074b, + 0x74d000007b2, + 0x7c0000007f6, + 0x8000000082e, + 0x8400000085c, + 0x8600000086b, + 0x8a0000008b5, + 0x8b6000008be, + 0x8d4000008e2, + 0x8e300000958, + 0x96000000964, + 0x96600000970, + 0x97100000984, + 0x9850000098d, + 0x98f00000991, + 0x993000009a9, + 0x9aa000009b1, + 0x9b2000009b3, + 0x9b6000009ba, + 0x9bc000009c5, + 0x9c7000009c9, + 0x9cb000009cf, + 0x9d7000009d8, + 0x9e0000009e4, + 0x9e6000009f2, + 0x9fc000009fd, + 0xa0100000a04, + 0xa0500000a0b, + 0xa0f00000a11, + 0xa1300000a29, + 0xa2a00000a31, + 0xa3200000a33, + 0xa3500000a36, + 0xa3800000a3a, + 0xa3c00000a3d, + 0xa3e00000a43, + 0xa4700000a49, + 0xa4b00000a4e, + 0xa5100000a52, + 0xa5c00000a5d, + 0xa6600000a76, + 0xa8100000a84, + 0xa8500000a8e, + 0xa8f00000a92, + 0xa9300000aa9, + 0xaaa00000ab1, + 0xab200000ab4, + 0xab500000aba, + 0xabc00000ac6, + 0xac700000aca, + 0xacb00000ace, + 0xad000000ad1, + 0xae000000ae4, + 0xae600000af0, + 0xaf900000b00, + 0xb0100000b04, + 0xb0500000b0d, + 0xb0f00000b11, + 0xb1300000b29, + 0xb2a00000b31, + 0xb3200000b34, + 0xb3500000b3a, + 0xb3c00000b45, + 0xb4700000b49, + 0xb4b00000b4e, + 0xb5600000b58, + 0xb5f00000b64, + 0xb6600000b70, + 0xb7100000b72, + 0xb8200000b84, + 0xb8500000b8b, + 0xb8e00000b91, + 0xb9200000b96, + 0xb9900000b9b, + 0xb9c00000b9d, + 0xb9e00000ba0, + 0xba300000ba5, + 0xba800000bab, + 0xbae00000bba, + 0xbbe00000bc3, + 0xbc600000bc9, + 0xbca00000bce, + 0xbd000000bd1, + 0xbd700000bd8, + 0xbe600000bf0, + 0xc0000000c04, + 0xc0500000c0d, + 0xc0e00000c11, + 0xc1200000c29, + 0xc2a00000c3a, + 0xc3d00000c45, + 0xc4600000c49, + 0xc4a00000c4e, + 0xc5500000c57, + 0xc5800000c5b, + 0xc6000000c64, + 0xc6600000c70, + 0xc8000000c84, + 0xc8500000c8d, + 0xc8e00000c91, + 0xc9200000ca9, + 0xcaa00000cb4, + 0xcb500000cba, + 0xcbc00000cc5, + 0xcc600000cc9, + 0xcca00000cce, + 0xcd500000cd7, + 0xcde00000cdf, + 0xce000000ce4, + 0xce600000cf0, + 0xcf100000cf3, + 0xd0000000d04, + 0xd0500000d0d, + 0xd0e00000d11, + 0xd1200000d45, + 0xd4600000d49, + 0xd4a00000d4f, + 0xd5400000d58, + 0xd5f00000d64, + 0xd6600000d70, + 0xd7a00000d80, + 0xd8200000d84, + 0xd8500000d97, + 0xd9a00000db2, + 0xdb300000dbc, + 0xdbd00000dbe, + 0xdc000000dc7, + 0xdca00000dcb, + 0xdcf00000dd5, + 0xdd600000dd7, + 0xdd800000de0, + 0xde600000df0, + 0xdf200000df4, + 0xe0100000e33, + 0xe3400000e3b, + 0xe4000000e4f, + 0xe5000000e5a, + 0xe8100000e83, + 0xe8400000e85, + 0xe8700000e89, + 0xe8a00000e8b, + 0xe8d00000e8e, + 0xe9400000e98, + 0xe9900000ea0, + 0xea100000ea4, + 0xea500000ea6, + 0xea700000ea8, + 0xeaa00000eac, + 0xead00000eb3, + 0xeb400000eba, + 0xebb00000ebe, + 0xec000000ec5, + 0xec600000ec7, + 0xec800000ece, + 0xed000000eda, + 0xede00000ee0, + 0xf0000000f01, + 0xf0b00000f0c, + 0xf1800000f1a, + 0xf2000000f2a, + 0xf3500000f36, + 0xf3700000f38, + 0xf3900000f3a, + 0xf3e00000f43, + 0xf4400000f48, + 0xf4900000f4d, + 0xf4e00000f52, + 0xf5300000f57, + 0xf5800000f5c, + 0xf5d00000f69, + 0xf6a00000f6d, + 0xf7100000f73, + 0xf7400000f75, + 0xf7a00000f81, + 0xf8200000f85, + 0xf8600000f93, + 0xf9400000f98, + 0xf9900000f9d, + 0xf9e00000fa2, + 0xfa300000fa7, + 0xfa800000fac, + 0xfad00000fb9, + 0xfba00000fbd, + 0xfc600000fc7, + 0x10000000104a, + 0x10500000109e, + 0x10d0000010fb, + 0x10fd00001100, + 0x120000001249, + 0x124a0000124e, + 0x125000001257, + 0x125800001259, + 0x125a0000125e, + 0x126000001289, + 0x128a0000128e, + 0x1290000012b1, + 0x12b2000012b6, + 0x12b8000012bf, + 0x12c0000012c1, + 0x12c2000012c6, + 0x12c8000012d7, + 0x12d800001311, + 0x131200001316, + 0x13180000135b, + 0x135d00001360, + 0x138000001390, + 0x13a0000013f6, + 0x14010000166d, + 0x166f00001680, + 0x16810000169b, + 0x16a0000016eb, + 0x16f1000016f9, + 0x17000000170d, + 0x170e00001715, + 0x172000001735, + 0x174000001754, + 0x17600000176d, + 0x176e00001771, + 0x177200001774, + 0x1780000017b4, + 0x17b6000017d4, + 0x17d7000017d8, + 0x17dc000017de, + 0x17e0000017ea, + 0x18100000181a, + 0x182000001878, + 0x1880000018ab, + 0x18b0000018f6, + 0x19000000191f, + 0x19200000192c, + 0x19300000193c, + 0x19460000196e, + 0x197000001975, + 0x1980000019ac, + 0x19b0000019ca, + 0x19d0000019da, + 0x1a0000001a1c, + 0x1a2000001a5f, + 0x1a6000001a7d, + 0x1a7f00001a8a, + 0x1a9000001a9a, + 0x1aa700001aa8, + 0x1ab000001abe, + 0x1b0000001b4c, + 0x1b5000001b5a, + 0x1b6b00001b74, + 0x1b8000001bf4, + 0x1c0000001c38, + 0x1c4000001c4a, + 0x1c4d00001c7e, + 0x1cd000001cd3, + 0x1cd400001cfa, + 0x1d0000001d2c, + 0x1d2f00001d30, + 0x1d3b00001d3c, + 0x1d4e00001d4f, + 0x1d6b00001d78, + 0x1d7900001d9b, + 0x1dc000001dfa, + 0x1dfb00001e00, + 0x1e0100001e02, + 0x1e0300001e04, + 0x1e0500001e06, + 0x1e0700001e08, + 0x1e0900001e0a, + 0x1e0b00001e0c, + 0x1e0d00001e0e, + 0x1e0f00001e10, + 0x1e1100001e12, + 0x1e1300001e14, + 0x1e1500001e16, + 0x1e1700001e18, + 0x1e1900001e1a, + 0x1e1b00001e1c, + 0x1e1d00001e1e, + 0x1e1f00001e20, + 0x1e2100001e22, + 0x1e2300001e24, + 0x1e2500001e26, + 0x1e2700001e28, + 0x1e2900001e2a, + 0x1e2b00001e2c, + 0x1e2d00001e2e, + 0x1e2f00001e30, + 0x1e3100001e32, + 0x1e3300001e34, + 0x1e3500001e36, + 0x1e3700001e38, + 0x1e3900001e3a, + 0x1e3b00001e3c, + 0x1e3d00001e3e, + 0x1e3f00001e40, + 0x1e4100001e42, + 0x1e4300001e44, + 0x1e4500001e46, + 0x1e4700001e48, + 0x1e4900001e4a, + 0x1e4b00001e4c, + 0x1e4d00001e4e, + 0x1e4f00001e50, + 0x1e5100001e52, + 0x1e5300001e54, + 0x1e5500001e56, + 0x1e5700001e58, + 0x1e5900001e5a, + 0x1e5b00001e5c, + 0x1e5d00001e5e, + 0x1e5f00001e60, + 0x1e6100001e62, + 0x1e6300001e64, + 0x1e6500001e66, + 0x1e6700001e68, + 0x1e6900001e6a, + 0x1e6b00001e6c, + 0x1e6d00001e6e, + 0x1e6f00001e70, + 0x1e7100001e72, + 0x1e7300001e74, + 0x1e7500001e76, + 0x1e7700001e78, + 0x1e7900001e7a, + 0x1e7b00001e7c, + 0x1e7d00001e7e, + 0x1e7f00001e80, + 0x1e8100001e82, + 0x1e8300001e84, + 0x1e8500001e86, + 0x1e8700001e88, + 0x1e8900001e8a, + 0x1e8b00001e8c, + 0x1e8d00001e8e, + 0x1e8f00001e90, + 0x1e9100001e92, + 0x1e9300001e94, + 0x1e9500001e9a, + 0x1e9c00001e9e, + 0x1e9f00001ea0, + 0x1ea100001ea2, + 0x1ea300001ea4, + 0x1ea500001ea6, + 0x1ea700001ea8, + 0x1ea900001eaa, + 0x1eab00001eac, + 0x1ead00001eae, + 0x1eaf00001eb0, + 0x1eb100001eb2, + 0x1eb300001eb4, + 0x1eb500001eb6, + 0x1eb700001eb8, + 0x1eb900001eba, + 0x1ebb00001ebc, + 0x1ebd00001ebe, + 0x1ebf00001ec0, + 0x1ec100001ec2, + 0x1ec300001ec4, + 0x1ec500001ec6, + 0x1ec700001ec8, + 0x1ec900001eca, + 0x1ecb00001ecc, + 0x1ecd00001ece, + 0x1ecf00001ed0, + 0x1ed100001ed2, + 0x1ed300001ed4, + 0x1ed500001ed6, + 0x1ed700001ed8, + 0x1ed900001eda, + 0x1edb00001edc, + 0x1edd00001ede, + 0x1edf00001ee0, + 0x1ee100001ee2, + 0x1ee300001ee4, + 0x1ee500001ee6, + 0x1ee700001ee8, + 0x1ee900001eea, + 0x1eeb00001eec, + 0x1eed00001eee, + 0x1eef00001ef0, + 0x1ef100001ef2, + 0x1ef300001ef4, + 0x1ef500001ef6, + 0x1ef700001ef8, + 0x1ef900001efa, + 0x1efb00001efc, + 0x1efd00001efe, + 0x1eff00001f08, + 0x1f1000001f16, + 0x1f2000001f28, + 0x1f3000001f38, + 0x1f4000001f46, + 0x1f5000001f58, + 0x1f6000001f68, + 0x1f7000001f71, + 0x1f7200001f73, + 0x1f7400001f75, + 0x1f7600001f77, + 0x1f7800001f79, + 0x1f7a00001f7b, + 0x1f7c00001f7d, + 0x1fb000001fb2, + 0x1fb600001fb7, + 0x1fc600001fc7, + 0x1fd000001fd3, + 0x1fd600001fd8, + 0x1fe000001fe3, + 0x1fe400001fe8, + 0x1ff600001ff7, + 0x214e0000214f, + 0x218400002185, + 0x2c3000002c5f, + 0x2c6100002c62, + 0x2c6500002c67, + 0x2c6800002c69, + 0x2c6a00002c6b, + 0x2c6c00002c6d, + 0x2c7100002c72, + 0x2c7300002c75, + 0x2c7600002c7c, + 0x2c8100002c82, + 0x2c8300002c84, + 0x2c8500002c86, + 0x2c8700002c88, + 0x2c8900002c8a, + 0x2c8b00002c8c, + 0x2c8d00002c8e, + 0x2c8f00002c90, + 0x2c9100002c92, + 0x2c9300002c94, + 0x2c9500002c96, + 0x2c9700002c98, + 0x2c9900002c9a, + 0x2c9b00002c9c, + 0x2c9d00002c9e, + 0x2c9f00002ca0, + 0x2ca100002ca2, + 0x2ca300002ca4, + 0x2ca500002ca6, + 0x2ca700002ca8, + 0x2ca900002caa, + 0x2cab00002cac, + 0x2cad00002cae, + 0x2caf00002cb0, + 0x2cb100002cb2, + 0x2cb300002cb4, + 0x2cb500002cb6, + 0x2cb700002cb8, + 0x2cb900002cba, + 0x2cbb00002cbc, + 0x2cbd00002cbe, + 0x2cbf00002cc0, + 0x2cc100002cc2, + 0x2cc300002cc4, + 0x2cc500002cc6, + 0x2cc700002cc8, + 0x2cc900002cca, + 0x2ccb00002ccc, + 0x2ccd00002cce, + 0x2ccf00002cd0, + 0x2cd100002cd2, + 0x2cd300002cd4, + 0x2cd500002cd6, + 0x2cd700002cd8, + 0x2cd900002cda, + 0x2cdb00002cdc, + 0x2cdd00002cde, + 0x2cdf00002ce0, + 0x2ce100002ce2, + 0x2ce300002ce5, + 0x2cec00002ced, + 0x2cee00002cf2, + 0x2cf300002cf4, + 0x2d0000002d26, + 0x2d2700002d28, + 0x2d2d00002d2e, + 0x2d3000002d68, + 0x2d7f00002d97, + 0x2da000002da7, + 0x2da800002daf, + 0x2db000002db7, + 0x2db800002dbf, + 0x2dc000002dc7, + 0x2dc800002dcf, + 0x2dd000002dd7, + 0x2dd800002ddf, + 0x2de000002e00, + 0x2e2f00002e30, + 0x300500003008, + 0x302a0000302e, + 0x303c0000303d, + 0x304100003097, + 0x30990000309b, + 0x309d0000309f, + 0x30a1000030fb, + 0x30fc000030ff, + 0x31050000312f, + 0x31a0000031bb, + 0x31f000003200, + 0x340000004db6, + 0x4e0000009feb, + 0xa0000000a48d, + 0xa4d00000a4fe, + 0xa5000000a60d, + 0xa6100000a62c, + 0xa6410000a642, + 0xa6430000a644, + 0xa6450000a646, + 0xa6470000a648, + 0xa6490000a64a, + 0xa64b0000a64c, + 0xa64d0000a64e, + 0xa64f0000a650, + 0xa6510000a652, + 0xa6530000a654, + 0xa6550000a656, + 0xa6570000a658, + 0xa6590000a65a, + 0xa65b0000a65c, + 0xa65d0000a65e, + 0xa65f0000a660, + 0xa6610000a662, + 0xa6630000a664, + 0xa6650000a666, + 0xa6670000a668, + 0xa6690000a66a, + 0xa66b0000a66c, + 0xa66d0000a670, + 0xa6740000a67e, + 0xa67f0000a680, + 0xa6810000a682, + 0xa6830000a684, + 0xa6850000a686, + 0xa6870000a688, + 0xa6890000a68a, + 0xa68b0000a68c, + 0xa68d0000a68e, + 0xa68f0000a690, + 0xa6910000a692, + 0xa6930000a694, + 0xa6950000a696, + 0xa6970000a698, + 0xa6990000a69a, + 0xa69b0000a69c, + 0xa69e0000a6e6, + 0xa6f00000a6f2, + 0xa7170000a720, + 0xa7230000a724, + 0xa7250000a726, + 0xa7270000a728, + 0xa7290000a72a, + 0xa72b0000a72c, + 0xa72d0000a72e, + 0xa72f0000a732, + 0xa7330000a734, + 0xa7350000a736, + 0xa7370000a738, + 0xa7390000a73a, + 0xa73b0000a73c, + 0xa73d0000a73e, + 0xa73f0000a740, + 0xa7410000a742, + 0xa7430000a744, + 0xa7450000a746, + 0xa7470000a748, + 0xa7490000a74a, + 0xa74b0000a74c, + 0xa74d0000a74e, + 0xa74f0000a750, + 0xa7510000a752, + 0xa7530000a754, + 0xa7550000a756, + 0xa7570000a758, + 0xa7590000a75a, + 0xa75b0000a75c, + 0xa75d0000a75e, + 0xa75f0000a760, + 0xa7610000a762, + 0xa7630000a764, + 0xa7650000a766, + 0xa7670000a768, + 0xa7690000a76a, + 0xa76b0000a76c, + 0xa76d0000a76e, + 0xa76f0000a770, + 0xa7710000a779, + 0xa77a0000a77b, + 0xa77c0000a77d, + 0xa77f0000a780, + 0xa7810000a782, + 0xa7830000a784, + 0xa7850000a786, + 0xa7870000a789, + 0xa78c0000a78d, + 0xa78e0000a790, + 0xa7910000a792, + 0xa7930000a796, + 0xa7970000a798, + 0xa7990000a79a, + 0xa79b0000a79c, + 0xa79d0000a79e, + 0xa79f0000a7a0, + 0xa7a10000a7a2, + 0xa7a30000a7a4, + 0xa7a50000a7a6, + 0xa7a70000a7a8, + 0xa7a90000a7aa, + 0xa7b50000a7b6, + 0xa7b70000a7b8, + 0xa7f70000a7f8, + 0xa7fa0000a828, + 0xa8400000a874, + 0xa8800000a8c6, + 0xa8d00000a8da, + 0xa8e00000a8f8, + 0xa8fb0000a8fc, + 0xa8fd0000a8fe, + 0xa9000000a92e, + 0xa9300000a954, + 0xa9800000a9c1, + 0xa9cf0000a9da, + 0xa9e00000a9ff, + 0xaa000000aa37, + 0xaa400000aa4e, + 0xaa500000aa5a, + 0xaa600000aa77, + 0xaa7a0000aac3, + 0xaadb0000aade, + 0xaae00000aaf0, + 0xaaf20000aaf7, + 0xab010000ab07, + 0xab090000ab0f, + 0xab110000ab17, + 0xab200000ab27, + 0xab280000ab2f, + 0xab300000ab5b, + 0xab600000ab66, + 0xabc00000abeb, + 0xabec0000abee, + 0xabf00000abfa, + 0xac000000d7a4, + 0xfa0e0000fa10, + 0xfa110000fa12, + 0xfa130000fa15, + 0xfa1f0000fa20, + 0xfa210000fa22, + 0xfa230000fa25, + 0xfa270000fa2a, + 0xfb1e0000fb1f, + 0xfe200000fe30, + 0xfe730000fe74, + 0x100000001000c, + 0x1000d00010027, + 0x100280001003b, + 0x1003c0001003e, + 0x1003f0001004e, + 0x100500001005e, + 0x10080000100fb, + 0x101fd000101fe, + 0x102800001029d, + 0x102a0000102d1, + 0x102e0000102e1, + 0x1030000010320, + 0x1032d00010341, + 0x103420001034a, + 0x103500001037b, + 0x103800001039e, + 0x103a0000103c4, + 0x103c8000103d0, + 0x104280001049e, + 0x104a0000104aa, + 0x104d8000104fc, + 0x1050000010528, + 0x1053000010564, + 0x1060000010737, + 0x1074000010756, + 0x1076000010768, + 0x1080000010806, + 0x1080800010809, + 0x1080a00010836, + 0x1083700010839, + 0x1083c0001083d, + 0x1083f00010856, + 0x1086000010877, + 0x108800001089f, + 0x108e0000108f3, + 0x108f4000108f6, + 0x1090000010916, + 0x109200001093a, + 0x10980000109b8, + 0x109be000109c0, + 0x10a0000010a04, + 0x10a0500010a07, + 0x10a0c00010a14, + 0x10a1500010a18, + 0x10a1900010a34, + 0x10a3800010a3b, + 0x10a3f00010a40, + 0x10a6000010a7d, + 0x10a8000010a9d, + 0x10ac000010ac8, + 0x10ac900010ae7, + 0x10b0000010b36, + 0x10b4000010b56, + 0x10b6000010b73, + 0x10b8000010b92, + 0x10c0000010c49, + 0x10cc000010cf3, + 0x1100000011047, + 0x1106600011070, + 0x1107f000110bb, + 0x110d0000110e9, + 0x110f0000110fa, + 0x1110000011135, + 0x1113600011140, + 0x1115000011174, + 0x1117600011177, + 0x11180000111c5, + 0x111ca000111cd, + 0x111d0000111db, + 0x111dc000111dd, + 0x1120000011212, + 0x1121300011238, + 0x1123e0001123f, + 0x1128000011287, + 0x1128800011289, + 0x1128a0001128e, + 0x1128f0001129e, + 0x1129f000112a9, + 0x112b0000112eb, + 0x112f0000112fa, + 0x1130000011304, + 0x113050001130d, + 0x1130f00011311, + 0x1131300011329, + 0x1132a00011331, + 0x1133200011334, + 0x113350001133a, + 0x1133c00011345, + 0x1134700011349, + 0x1134b0001134e, + 0x1135000011351, + 0x1135700011358, + 0x1135d00011364, + 0x113660001136d, + 0x1137000011375, + 0x114000001144b, + 0x114500001145a, + 0x11480000114c6, + 0x114c7000114c8, + 0x114d0000114da, + 0x11580000115b6, + 0x115b8000115c1, + 0x115d8000115de, + 0x1160000011641, + 0x1164400011645, + 0x116500001165a, + 0x11680000116b8, + 0x116c0000116ca, + 0x117000001171a, + 0x1171d0001172c, + 0x117300001173a, + 0x118c0000118ea, + 0x118ff00011900, + 0x11a0000011a3f, + 0x11a4700011a48, + 0x11a5000011a84, + 0x11a8600011a9a, + 0x11ac000011af9, + 0x11c0000011c09, + 0x11c0a00011c37, + 0x11c3800011c41, + 0x11c5000011c5a, + 0x11c7200011c90, + 0x11c9200011ca8, + 0x11ca900011cb7, + 0x11d0000011d07, + 0x11d0800011d0a, + 0x11d0b00011d37, + 0x11d3a00011d3b, + 0x11d3c00011d3e, + 0x11d3f00011d48, + 0x11d5000011d5a, + 0x120000001239a, + 0x1248000012544, + 0x130000001342f, + 0x1440000014647, + 0x1680000016a39, + 0x16a4000016a5f, + 0x16a6000016a6a, + 0x16ad000016aee, + 0x16af000016af5, + 0x16b0000016b37, + 0x16b4000016b44, + 0x16b5000016b5a, + 0x16b6300016b78, + 0x16b7d00016b90, + 0x16f0000016f45, + 0x16f5000016f7f, + 0x16f8f00016fa0, + 0x16fe000016fe2, + 0x17000000187ed, + 0x1880000018af3, + 0x1b0000001b11f, + 0x1b1700001b2fc, + 0x1bc000001bc6b, + 0x1bc700001bc7d, + 0x1bc800001bc89, + 0x1bc900001bc9a, + 0x1bc9d0001bc9f, + 0x1da000001da37, + 0x1da3b0001da6d, + 0x1da750001da76, + 0x1da840001da85, + 0x1da9b0001daa0, + 0x1daa10001dab0, + 0x1e0000001e007, + 0x1e0080001e019, + 0x1e01b0001e022, + 0x1e0230001e025, + 0x1e0260001e02b, + 0x1e8000001e8c5, + 0x1e8d00001e8d7, + 0x1e9220001e94b, + 0x1e9500001e95a, + 0x200000002a6d7, + 0x2a7000002b735, + 0x2b7400002b81e, + 0x2b8200002cea2, + 0x2ceb00002ebe1, + ), + 'CONTEXTJ': ( + 0x200c0000200e, + ), + 'CONTEXTO': ( + 0xb7000000b8, + 0x37500000376, + 0x5f3000005f5, + 0x6600000066a, + 0x6f0000006fa, + 0x30fb000030fc, + ), +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/intranges.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/intranges.py new file mode 100644 index 0000000..fa8a735 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/intranges.py @@ -0,0 +1,53 @@ +""" +Given a list of integers, made up of (hopefully) a small number of long runs +of consecutive integers, compute a representation of the form +((start1, end1), (start2, end2) ...). Then answer the question "was x present +in the original list?" in time O(log(# runs)). +""" + +import bisect + +def intranges_from_list(list_): + """Represent a list of integers as a sequence of ranges: + ((start_0, end_0), (start_1, end_1), ...), such that the original + integers are exactly those x such that start_i <= x < end_i for some i. + + Ranges are encoded as single integers (start << 32 | end), not as tuples. + """ + + sorted_list = sorted(list_) + ranges = [] + last_write = -1 + for i in range(len(sorted_list)): + if i+1 < len(sorted_list): + if sorted_list[i] == sorted_list[i+1]-1: + continue + current_range = sorted_list[last_write+1:i+1] + ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) + last_write = i + + return tuple(ranges) + +def _encode_range(start, end): + return (start << 32) | end + +def _decode_range(r): + return (r >> 32), (r & ((1 << 32) - 1)) + + +def intranges_contain(int_, ranges): + """Determine if `int_` falls into one of the ranges in `ranges`.""" + tuple_ = _encode_range(int_, 0) + pos = bisect.bisect_left(ranges, tuple_) + # we could be immediately ahead of a tuple (start, end) + # with start < int_ <= end + if pos > 0: + left, right = _decode_range(ranges[pos-1]) + if left <= int_ < right: + return True + # or we could be immediately behind a tuple (int_, end) + if pos < len(ranges): + left, _ = _decode_range(ranges[pos]) + if left == int_: + return True + return False diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/package_data.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/package_data.py new file mode 100644 index 0000000..39c192b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/package_data.py @@ -0,0 +1,2 @@ +__version__ = '2.7' + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/idna/uts46data.py b/venv/lib/python3.7/site-packages/pip/_vendor/idna/uts46data.py new file mode 100644 index 0000000..79731cb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/idna/uts46data.py @@ -0,0 +1,8179 @@ +# This file is automatically generated by tools/idna-data +# vim: set fileencoding=utf-8 : + +"""IDNA Mapping Table from UTS46.""" + + +__version__ = "10.0.0" +def _seg_0(): + return [ + (0x0, '3'), + (0x1, '3'), + (0x2, '3'), + (0x3, '3'), + (0x4, '3'), + (0x5, '3'), + (0x6, '3'), + (0x7, '3'), + (0x8, '3'), + (0x9, '3'), + (0xA, '3'), + (0xB, '3'), + (0xC, '3'), + (0xD, '3'), + (0xE, '3'), + (0xF, '3'), + (0x10, '3'), + (0x11, '3'), + (0x12, '3'), + (0x13, '3'), + (0x14, '3'), + (0x15, '3'), + (0x16, '3'), + (0x17, '3'), + (0x18, '3'), + (0x19, '3'), + (0x1A, '3'), + (0x1B, '3'), + (0x1C, '3'), + (0x1D, '3'), + (0x1E, '3'), + (0x1F, '3'), + (0x20, '3'), + (0x21, '3'), + (0x22, '3'), + (0x23, '3'), + (0x24, '3'), + (0x25, '3'), + (0x26, '3'), + (0x27, '3'), + (0x28, '3'), + (0x29, '3'), + (0x2A, '3'), + (0x2B, '3'), + (0x2C, '3'), + (0x2D, 'V'), + (0x2E, 'V'), + (0x2F, '3'), + (0x30, 'V'), + (0x31, 'V'), + (0x32, 'V'), + (0x33, 'V'), + (0x34, 'V'), + (0x35, 'V'), + (0x36, 'V'), + (0x37, 'V'), + (0x38, 'V'), + (0x39, 'V'), + (0x3A, '3'), + (0x3B, '3'), + (0x3C, '3'), + (0x3D, '3'), + (0x3E, '3'), + (0x3F, '3'), + (0x40, '3'), + (0x41, 'M', u'a'), + (0x42, 'M', u'b'), + (0x43, 'M', u'c'), + (0x44, 'M', u'd'), + (0x45, 'M', u'e'), + (0x46, 'M', u'f'), + (0x47, 'M', u'g'), + (0x48, 'M', u'h'), + (0x49, 'M', u'i'), + (0x4A, 'M', u'j'), + (0x4B, 'M', u'k'), + (0x4C, 'M', u'l'), + (0x4D, 'M', u'm'), + (0x4E, 'M', u'n'), + (0x4F, 'M', u'o'), + (0x50, 'M', u'p'), + (0x51, 'M', u'q'), + (0x52, 'M', u'r'), + (0x53, 'M', u's'), + (0x54, 'M', u't'), + (0x55, 'M', u'u'), + (0x56, 'M', u'v'), + (0x57, 'M', u'w'), + (0x58, 'M', u'x'), + (0x59, 'M', u'y'), + (0x5A, 'M', u'z'), + (0x5B, '3'), + (0x5C, '3'), + (0x5D, '3'), + (0x5E, '3'), + (0x5F, '3'), + (0x60, '3'), + (0x61, 'V'), + (0x62, 'V'), + (0x63, 'V'), + ] + +def _seg_1(): + return [ + (0x64, 'V'), + (0x65, 'V'), + (0x66, 'V'), + (0x67, 'V'), + (0x68, 'V'), + (0x69, 'V'), + (0x6A, 'V'), + (0x6B, 'V'), + (0x6C, 'V'), + (0x6D, 'V'), + (0x6E, 'V'), + (0x6F, 'V'), + (0x70, 'V'), + (0x71, 'V'), + (0x72, 'V'), + (0x73, 'V'), + (0x74, 'V'), + (0x75, 'V'), + (0x76, 'V'), + (0x77, 'V'), + (0x78, 'V'), + (0x79, 'V'), + (0x7A, 'V'), + (0x7B, '3'), + (0x7C, '3'), + (0x7D, '3'), + (0x7E, '3'), + (0x7F, '3'), + (0x80, 'X'), + (0x81, 'X'), + (0x82, 'X'), + (0x83, 'X'), + (0x84, 'X'), + (0x85, 'X'), + (0x86, 'X'), + (0x87, 'X'), + (0x88, 'X'), + (0x89, 'X'), + (0x8A, 'X'), + (0x8B, 'X'), + (0x8C, 'X'), + (0x8D, 'X'), + (0x8E, 'X'), + (0x8F, 'X'), + (0x90, 'X'), + (0x91, 'X'), + (0x92, 'X'), + (0x93, 'X'), + (0x94, 'X'), + (0x95, 'X'), + (0x96, 'X'), + (0x97, 'X'), + (0x98, 'X'), + (0x99, 'X'), + (0x9A, 'X'), + (0x9B, 'X'), + (0x9C, 'X'), + (0x9D, 'X'), + (0x9E, 'X'), + (0x9F, 'X'), + (0xA0, '3', u' '), + (0xA1, 'V'), + (0xA2, 'V'), + (0xA3, 'V'), + (0xA4, 'V'), + (0xA5, 'V'), + (0xA6, 'V'), + (0xA7, 'V'), + (0xA8, '3', u' ̈'), + (0xA9, 'V'), + (0xAA, 'M', u'a'), + (0xAB, 'V'), + (0xAC, 'V'), + (0xAD, 'I'), + (0xAE, 'V'), + (0xAF, '3', u' ̄'), + (0xB0, 'V'), + (0xB1, 'V'), + (0xB2, 'M', u'2'), + (0xB3, 'M', u'3'), + (0xB4, '3', u' ́'), + (0xB5, 'M', u'μ'), + (0xB6, 'V'), + (0xB7, 'V'), + (0xB8, '3', u' ̧'), + (0xB9, 'M', u'1'), + (0xBA, 'M', u'o'), + (0xBB, 'V'), + (0xBC, 'M', u'1⁄4'), + (0xBD, 'M', u'1⁄2'), + (0xBE, 'M', u'3⁄4'), + (0xBF, 'V'), + (0xC0, 'M', u'à'), + (0xC1, 'M', u'á'), + (0xC2, 'M', u'â'), + (0xC3, 'M', u'ã'), + (0xC4, 'M', u'ä'), + (0xC5, 'M', u'å'), + (0xC6, 'M', u'æ'), + (0xC7, 'M', u'ç'), + ] + +def _seg_2(): + return [ + (0xC8, 'M', u'è'), + (0xC9, 'M', u'é'), + (0xCA, 'M', u'ê'), + (0xCB, 'M', u'ë'), + (0xCC, 'M', u'ì'), + (0xCD, 'M', u'í'), + (0xCE, 'M', u'î'), + (0xCF, 'M', u'ï'), + (0xD0, 'M', u'ð'), + (0xD1, 'M', u'ñ'), + (0xD2, 'M', u'ò'), + (0xD3, 'M', u'ó'), + (0xD4, 'M', u'ô'), + (0xD5, 'M', u'õ'), + (0xD6, 'M', u'ö'), + (0xD7, 'V'), + (0xD8, 'M', u'ø'), + (0xD9, 'M', u'ù'), + (0xDA, 'M', u'ú'), + (0xDB, 'M', u'û'), + (0xDC, 'M', u'ü'), + (0xDD, 'M', u'ý'), + (0xDE, 'M', u'þ'), + (0xDF, 'D', u'ss'), + (0xE0, 'V'), + (0xE1, 'V'), + (0xE2, 'V'), + (0xE3, 'V'), + (0xE4, 'V'), + (0xE5, 'V'), + (0xE6, 'V'), + (0xE7, 'V'), + (0xE8, 'V'), + (0xE9, 'V'), + (0xEA, 'V'), + (0xEB, 'V'), + (0xEC, 'V'), + (0xED, 'V'), + (0xEE, 'V'), + (0xEF, 'V'), + (0xF0, 'V'), + (0xF1, 'V'), + (0xF2, 'V'), + (0xF3, 'V'), + (0xF4, 'V'), + (0xF5, 'V'), + (0xF6, 'V'), + (0xF7, 'V'), + (0xF8, 'V'), + (0xF9, 'V'), + (0xFA, 'V'), + (0xFB, 'V'), + (0xFC, 'V'), + (0xFD, 'V'), + (0xFE, 'V'), + (0xFF, 'V'), + (0x100, 'M', u'ā'), + (0x101, 'V'), + (0x102, 'M', u'ă'), + (0x103, 'V'), + (0x104, 'M', u'ą'), + (0x105, 'V'), + (0x106, 'M', u'ć'), + (0x107, 'V'), + (0x108, 'M', u'ĉ'), + (0x109, 'V'), + (0x10A, 'M', u'ċ'), + (0x10B, 'V'), + (0x10C, 'M', u'č'), + (0x10D, 'V'), + (0x10E, 'M', u'ď'), + (0x10F, 'V'), + (0x110, 'M', u'đ'), + (0x111, 'V'), + (0x112, 'M', u'ē'), + (0x113, 'V'), + (0x114, 'M', u'ĕ'), + (0x115, 'V'), + (0x116, 'M', u'ė'), + (0x117, 'V'), + (0x118, 'M', u'ę'), + (0x119, 'V'), + (0x11A, 'M', u'ě'), + (0x11B, 'V'), + (0x11C, 'M', u'ĝ'), + (0x11D, 'V'), + (0x11E, 'M', u'ğ'), + (0x11F, 'V'), + (0x120, 'M', u'ġ'), + (0x121, 'V'), + (0x122, 'M', u'ģ'), + (0x123, 'V'), + (0x124, 'M', u'ĥ'), + (0x125, 'V'), + (0x126, 'M', u'ħ'), + (0x127, 'V'), + (0x128, 'M', u'ĩ'), + (0x129, 'V'), + (0x12A, 'M', u'ī'), + (0x12B, 'V'), + ] + +def _seg_3(): + return [ + (0x12C, 'M', u'ĭ'), + (0x12D, 'V'), + (0x12E, 'M', u'į'), + (0x12F, 'V'), + (0x130, 'M', u'i̇'), + (0x131, 'V'), + (0x132, 'M', u'ij'), + (0x134, 'M', u'ĵ'), + (0x135, 'V'), + (0x136, 'M', u'ķ'), + (0x137, 'V'), + (0x139, 'M', u'ĺ'), + (0x13A, 'V'), + (0x13B, 'M', u'ļ'), + (0x13C, 'V'), + (0x13D, 'M', u'ľ'), + (0x13E, 'V'), + (0x13F, 'M', u'l·'), + (0x141, 'M', u'ł'), + (0x142, 'V'), + (0x143, 'M', u'ń'), + (0x144, 'V'), + (0x145, 'M', u'ņ'), + (0x146, 'V'), + (0x147, 'M', u'ň'), + (0x148, 'V'), + (0x149, 'M', u'ʼn'), + (0x14A, 'M', u'ŋ'), + (0x14B, 'V'), + (0x14C, 'M', u'ō'), + (0x14D, 'V'), + (0x14E, 'M', u'ŏ'), + (0x14F, 'V'), + (0x150, 'M', u'ő'), + (0x151, 'V'), + (0x152, 'M', u'œ'), + (0x153, 'V'), + (0x154, 'M', u'ŕ'), + (0x155, 'V'), + (0x156, 'M', u'ŗ'), + (0x157, 'V'), + (0x158, 'M', u'ř'), + (0x159, 'V'), + (0x15A, 'M', u'ś'), + (0x15B, 'V'), + (0x15C, 'M', u'ŝ'), + (0x15D, 'V'), + (0x15E, 'M', u'ş'), + (0x15F, 'V'), + (0x160, 'M', u'š'), + (0x161, 'V'), + (0x162, 'M', u'ţ'), + (0x163, 'V'), + (0x164, 'M', u'ť'), + (0x165, 'V'), + (0x166, 'M', u'ŧ'), + (0x167, 'V'), + (0x168, 'M', u'ũ'), + (0x169, 'V'), + (0x16A, 'M', u'ū'), + (0x16B, 'V'), + (0x16C, 'M', u'ŭ'), + (0x16D, 'V'), + (0x16E, 'M', u'ů'), + (0x16F, 'V'), + (0x170, 'M', u'ű'), + (0x171, 'V'), + (0x172, 'M', u'ų'), + (0x173, 'V'), + (0x174, 'M', u'ŵ'), + (0x175, 'V'), + (0x176, 'M', u'ŷ'), + (0x177, 'V'), + (0x178, 'M', u'ÿ'), + (0x179, 'M', u'ź'), + (0x17A, 'V'), + (0x17B, 'M', u'ż'), + (0x17C, 'V'), + (0x17D, 'M', u'ž'), + (0x17E, 'V'), + (0x17F, 'M', u's'), + (0x180, 'V'), + (0x181, 'M', u'ɓ'), + (0x182, 'M', u'ƃ'), + (0x183, 'V'), + (0x184, 'M', u'ƅ'), + (0x185, 'V'), + (0x186, 'M', u'ɔ'), + (0x187, 'M', u'ƈ'), + (0x188, 'V'), + (0x189, 'M', u'ɖ'), + (0x18A, 'M', u'ɗ'), + (0x18B, 'M', u'ƌ'), + (0x18C, 'V'), + (0x18E, 'M', u'ǝ'), + (0x18F, 'M', u'ə'), + (0x190, 'M', u'ɛ'), + (0x191, 'M', u'ƒ'), + (0x192, 'V'), + (0x193, 'M', u'ɠ'), + ] + +def _seg_4(): + return [ + (0x194, 'M', u'ɣ'), + (0x195, 'V'), + (0x196, 'M', u'ɩ'), + (0x197, 'M', u'ɨ'), + (0x198, 'M', u'ƙ'), + (0x199, 'V'), + (0x19C, 'M', u'ɯ'), + (0x19D, 'M', u'ɲ'), + (0x19E, 'V'), + (0x19F, 'M', u'ɵ'), + (0x1A0, 'M', u'ơ'), + (0x1A1, 'V'), + (0x1A2, 'M', u'ƣ'), + (0x1A3, 'V'), + (0x1A4, 'M', u'ƥ'), + (0x1A5, 'V'), + (0x1A6, 'M', u'ʀ'), + (0x1A7, 'M', u'ƨ'), + (0x1A8, 'V'), + (0x1A9, 'M', u'ʃ'), + (0x1AA, 'V'), + (0x1AC, 'M', u'ƭ'), + (0x1AD, 'V'), + (0x1AE, 'M', u'ʈ'), + (0x1AF, 'M', u'ư'), + (0x1B0, 'V'), + (0x1B1, 'M', u'ʊ'), + (0x1B2, 'M', u'ʋ'), + (0x1B3, 'M', u'ƴ'), + (0x1B4, 'V'), + (0x1B5, 'M', u'ƶ'), + (0x1B6, 'V'), + (0x1B7, 'M', u'ʒ'), + (0x1B8, 'M', u'ƹ'), + (0x1B9, 'V'), + (0x1BC, 'M', u'ƽ'), + (0x1BD, 'V'), + (0x1C4, 'M', u'dž'), + (0x1C7, 'M', u'lj'), + (0x1CA, 'M', u'nj'), + (0x1CD, 'M', u'ǎ'), + (0x1CE, 'V'), + (0x1CF, 'M', u'ǐ'), + (0x1D0, 'V'), + (0x1D1, 'M', u'ǒ'), + (0x1D2, 'V'), + (0x1D3, 'M', u'ǔ'), + (0x1D4, 'V'), + (0x1D5, 'M', u'ǖ'), + (0x1D6, 'V'), + (0x1D7, 'M', u'ǘ'), + (0x1D8, 'V'), + (0x1D9, 'M', u'ǚ'), + (0x1DA, 'V'), + (0x1DB, 'M', u'ǜ'), + (0x1DC, 'V'), + (0x1DE, 'M', u'ǟ'), + (0x1DF, 'V'), + (0x1E0, 'M', u'ǡ'), + (0x1E1, 'V'), + (0x1E2, 'M', u'ǣ'), + (0x1E3, 'V'), + (0x1E4, 'M', u'ǥ'), + (0x1E5, 'V'), + (0x1E6, 'M', u'ǧ'), + (0x1E7, 'V'), + (0x1E8, 'M', u'ǩ'), + (0x1E9, 'V'), + (0x1EA, 'M', u'ǫ'), + (0x1EB, 'V'), + (0x1EC, 'M', u'ǭ'), + (0x1ED, 'V'), + (0x1EE, 'M', u'ǯ'), + (0x1EF, 'V'), + (0x1F1, 'M', u'dz'), + (0x1F4, 'M', u'ǵ'), + (0x1F5, 'V'), + (0x1F6, 'M', u'ƕ'), + (0x1F7, 'M', u'ƿ'), + (0x1F8, 'M', u'ǹ'), + (0x1F9, 'V'), + (0x1FA, 'M', u'ǻ'), + (0x1FB, 'V'), + (0x1FC, 'M', u'ǽ'), + (0x1FD, 'V'), + (0x1FE, 'M', u'ǿ'), + (0x1FF, 'V'), + (0x200, 'M', u'ȁ'), + (0x201, 'V'), + (0x202, 'M', u'ȃ'), + (0x203, 'V'), + (0x204, 'M', u'ȅ'), + (0x205, 'V'), + (0x206, 'M', u'ȇ'), + (0x207, 'V'), + (0x208, 'M', u'ȉ'), + (0x209, 'V'), + (0x20A, 'M', u'ȋ'), + (0x20B, 'V'), + (0x20C, 'M', u'ȍ'), + ] + +def _seg_5(): + return [ + (0x20D, 'V'), + (0x20E, 'M', u'ȏ'), + (0x20F, 'V'), + (0x210, 'M', u'ȑ'), + (0x211, 'V'), + (0x212, 'M', u'ȓ'), + (0x213, 'V'), + (0x214, 'M', u'ȕ'), + (0x215, 'V'), + (0x216, 'M', u'ȗ'), + (0x217, 'V'), + (0x218, 'M', u'ș'), + (0x219, 'V'), + (0x21A, 'M', u'ț'), + (0x21B, 'V'), + (0x21C, 'M', u'ȝ'), + (0x21D, 'V'), + (0x21E, 'M', u'ȟ'), + (0x21F, 'V'), + (0x220, 'M', u'ƞ'), + (0x221, 'V'), + (0x222, 'M', u'ȣ'), + (0x223, 'V'), + (0x224, 'M', u'ȥ'), + (0x225, 'V'), + (0x226, 'M', u'ȧ'), + (0x227, 'V'), + (0x228, 'M', u'ȩ'), + (0x229, 'V'), + (0x22A, 'M', u'ȫ'), + (0x22B, 'V'), + (0x22C, 'M', u'ȭ'), + (0x22D, 'V'), + (0x22E, 'M', u'ȯ'), + (0x22F, 'V'), + (0x230, 'M', u'ȱ'), + (0x231, 'V'), + (0x232, 'M', u'ȳ'), + (0x233, 'V'), + (0x23A, 'M', u'ⱥ'), + (0x23B, 'M', u'ȼ'), + (0x23C, 'V'), + (0x23D, 'M', u'ƚ'), + (0x23E, 'M', u'ⱦ'), + (0x23F, 'V'), + (0x241, 'M', u'ɂ'), + (0x242, 'V'), + (0x243, 'M', u'ƀ'), + (0x244, 'M', u'ʉ'), + (0x245, 'M', u'ʌ'), + (0x246, 'M', u'ɇ'), + (0x247, 'V'), + (0x248, 'M', u'ɉ'), + (0x249, 'V'), + (0x24A, 'M', u'ɋ'), + (0x24B, 'V'), + (0x24C, 'M', u'ɍ'), + (0x24D, 'V'), + (0x24E, 'M', u'ɏ'), + (0x24F, 'V'), + (0x2B0, 'M', u'h'), + (0x2B1, 'M', u'ɦ'), + (0x2B2, 'M', u'j'), + (0x2B3, 'M', u'r'), + (0x2B4, 'M', u'ɹ'), + (0x2B5, 'M', u'ɻ'), + (0x2B6, 'M', u'ʁ'), + (0x2B7, 'M', u'w'), + (0x2B8, 'M', u'y'), + (0x2B9, 'V'), + (0x2D8, '3', u' ̆'), + (0x2D9, '3', u' ̇'), + (0x2DA, '3', u' ̊'), + (0x2DB, '3', u' ̨'), + (0x2DC, '3', u' ̃'), + (0x2DD, '3', u' ̋'), + (0x2DE, 'V'), + (0x2E0, 'M', u'ɣ'), + (0x2E1, 'M', u'l'), + (0x2E2, 'M', u's'), + (0x2E3, 'M', u'x'), + (0x2E4, 'M', u'ʕ'), + (0x2E5, 'V'), + (0x340, 'M', u'̀'), + (0x341, 'M', u'́'), + (0x342, 'V'), + (0x343, 'M', u'̓'), + (0x344, 'M', u'̈́'), + (0x345, 'M', u'ι'), + (0x346, 'V'), + (0x34F, 'I'), + (0x350, 'V'), + (0x370, 'M', u'ͱ'), + (0x371, 'V'), + (0x372, 'M', u'ͳ'), + (0x373, 'V'), + (0x374, 'M', u'ʹ'), + (0x375, 'V'), + (0x376, 'M', u'ͷ'), + (0x377, 'V'), + ] + +def _seg_6(): + return [ + (0x378, 'X'), + (0x37A, '3', u' ι'), + (0x37B, 'V'), + (0x37E, '3', u';'), + (0x37F, 'M', u'ϳ'), + (0x380, 'X'), + (0x384, '3', u' ́'), + (0x385, '3', u' ̈́'), + (0x386, 'M', u'ά'), + (0x387, 'M', u'·'), + (0x388, 'M', u'έ'), + (0x389, 'M', u'ή'), + (0x38A, 'M', u'ί'), + (0x38B, 'X'), + (0x38C, 'M', u'ό'), + (0x38D, 'X'), + (0x38E, 'M', u'ύ'), + (0x38F, 'M', u'ώ'), + (0x390, 'V'), + (0x391, 'M', u'α'), + (0x392, 'M', u'β'), + (0x393, 'M', u'γ'), + (0x394, 'M', u'δ'), + (0x395, 'M', u'ε'), + (0x396, 'M', u'ζ'), + (0x397, 'M', u'η'), + (0x398, 'M', u'θ'), + (0x399, 'M', u'ι'), + (0x39A, 'M', u'κ'), + (0x39B, 'M', u'λ'), + (0x39C, 'M', u'μ'), + (0x39D, 'M', u'ν'), + (0x39E, 'M', u'ξ'), + (0x39F, 'M', u'ο'), + (0x3A0, 'M', u'π'), + (0x3A1, 'M', u'ρ'), + (0x3A2, 'X'), + (0x3A3, 'M', u'σ'), + (0x3A4, 'M', u'τ'), + (0x3A5, 'M', u'υ'), + (0x3A6, 'M', u'φ'), + (0x3A7, 'M', u'χ'), + (0x3A8, 'M', u'ψ'), + (0x3A9, 'M', u'ω'), + (0x3AA, 'M', u'ϊ'), + (0x3AB, 'M', u'ϋ'), + (0x3AC, 'V'), + (0x3C2, 'D', u'σ'), + (0x3C3, 'V'), + (0x3CF, 'M', u'ϗ'), + (0x3D0, 'M', u'β'), + (0x3D1, 'M', u'θ'), + (0x3D2, 'M', u'υ'), + (0x3D3, 'M', u'ύ'), + (0x3D4, 'M', u'ϋ'), + (0x3D5, 'M', u'φ'), + (0x3D6, 'M', u'π'), + (0x3D7, 'V'), + (0x3D8, 'M', u'ϙ'), + (0x3D9, 'V'), + (0x3DA, 'M', u'ϛ'), + (0x3DB, 'V'), + (0x3DC, 'M', u'ϝ'), + (0x3DD, 'V'), + (0x3DE, 'M', u'ϟ'), + (0x3DF, 'V'), + (0x3E0, 'M', u'ϡ'), + (0x3E1, 'V'), + (0x3E2, 'M', u'ϣ'), + (0x3E3, 'V'), + (0x3E4, 'M', u'ϥ'), + (0x3E5, 'V'), + (0x3E6, 'M', u'ϧ'), + (0x3E7, 'V'), + (0x3E8, 'M', u'ϩ'), + (0x3E9, 'V'), + (0x3EA, 'M', u'ϫ'), + (0x3EB, 'V'), + (0x3EC, 'M', u'ϭ'), + (0x3ED, 'V'), + (0x3EE, 'M', u'ϯ'), + (0x3EF, 'V'), + (0x3F0, 'M', u'κ'), + (0x3F1, 'M', u'ρ'), + (0x3F2, 'M', u'σ'), + (0x3F3, 'V'), + (0x3F4, 'M', u'θ'), + (0x3F5, 'M', u'ε'), + (0x3F6, 'V'), + (0x3F7, 'M', u'ϸ'), + (0x3F8, 'V'), + (0x3F9, 'M', u'σ'), + (0x3FA, 'M', u'ϻ'), + (0x3FB, 'V'), + (0x3FD, 'M', u'ͻ'), + (0x3FE, 'M', u'ͼ'), + (0x3FF, 'M', u'ͽ'), + (0x400, 'M', u'ѐ'), + (0x401, 'M', u'ё'), + (0x402, 'M', u'ђ'), + ] + +def _seg_7(): + return [ + (0x403, 'M', u'ѓ'), + (0x404, 'M', u'є'), + (0x405, 'M', u'ѕ'), + (0x406, 'M', u'і'), + (0x407, 'M', u'ї'), + (0x408, 'M', u'ј'), + (0x409, 'M', u'љ'), + (0x40A, 'M', u'њ'), + (0x40B, 'M', u'ћ'), + (0x40C, 'M', u'ќ'), + (0x40D, 'M', u'ѝ'), + (0x40E, 'M', u'ў'), + (0x40F, 'M', u'џ'), + (0x410, 'M', u'а'), + (0x411, 'M', u'б'), + (0x412, 'M', u'в'), + (0x413, 'M', u'г'), + (0x414, 'M', u'д'), + (0x415, 'M', u'е'), + (0x416, 'M', u'ж'), + (0x417, 'M', u'з'), + (0x418, 'M', u'и'), + (0x419, 'M', u'й'), + (0x41A, 'M', u'к'), + (0x41B, 'M', u'л'), + (0x41C, 'M', u'м'), + (0x41D, 'M', u'н'), + (0x41E, 'M', u'о'), + (0x41F, 'M', u'п'), + (0x420, 'M', u'р'), + (0x421, 'M', u'с'), + (0x422, 'M', u'т'), + (0x423, 'M', u'у'), + (0x424, 'M', u'ф'), + (0x425, 'M', u'х'), + (0x426, 'M', u'ц'), + (0x427, 'M', u'ч'), + (0x428, 'M', u'ш'), + (0x429, 'M', u'щ'), + (0x42A, 'M', u'ъ'), + (0x42B, 'M', u'ы'), + (0x42C, 'M', u'ь'), + (0x42D, 'M', u'э'), + (0x42E, 'M', u'ю'), + (0x42F, 'M', u'я'), + (0x430, 'V'), + (0x460, 'M', u'ѡ'), + (0x461, 'V'), + (0x462, 'M', u'ѣ'), + (0x463, 'V'), + (0x464, 'M', u'ѥ'), + (0x465, 'V'), + (0x466, 'M', u'ѧ'), + (0x467, 'V'), + (0x468, 'M', u'ѩ'), + (0x469, 'V'), + (0x46A, 'M', u'ѫ'), + (0x46B, 'V'), + (0x46C, 'M', u'ѭ'), + (0x46D, 'V'), + (0x46E, 'M', u'ѯ'), + (0x46F, 'V'), + (0x470, 'M', u'ѱ'), + (0x471, 'V'), + (0x472, 'M', u'ѳ'), + (0x473, 'V'), + (0x474, 'M', u'ѵ'), + (0x475, 'V'), + (0x476, 'M', u'ѷ'), + (0x477, 'V'), + (0x478, 'M', u'ѹ'), + (0x479, 'V'), + (0x47A, 'M', u'ѻ'), + (0x47B, 'V'), + (0x47C, 'M', u'ѽ'), + (0x47D, 'V'), + (0x47E, 'M', u'ѿ'), + (0x47F, 'V'), + (0x480, 'M', u'ҁ'), + (0x481, 'V'), + (0x48A, 'M', u'ҋ'), + (0x48B, 'V'), + (0x48C, 'M', u'ҍ'), + (0x48D, 'V'), + (0x48E, 'M', u'ҏ'), + (0x48F, 'V'), + (0x490, 'M', u'ґ'), + (0x491, 'V'), + (0x492, 'M', u'ғ'), + (0x493, 'V'), + (0x494, 'M', u'ҕ'), + (0x495, 'V'), + (0x496, 'M', u'җ'), + (0x497, 'V'), + (0x498, 'M', u'ҙ'), + (0x499, 'V'), + (0x49A, 'M', u'қ'), + (0x49B, 'V'), + (0x49C, 'M', u'ҝ'), + (0x49D, 'V'), + ] + +def _seg_8(): + return [ + (0x49E, 'M', u'ҟ'), + (0x49F, 'V'), + (0x4A0, 'M', u'ҡ'), + (0x4A1, 'V'), + (0x4A2, 'M', u'ң'), + (0x4A3, 'V'), + (0x4A4, 'M', u'ҥ'), + (0x4A5, 'V'), + (0x4A6, 'M', u'ҧ'), + (0x4A7, 'V'), + (0x4A8, 'M', u'ҩ'), + (0x4A9, 'V'), + (0x4AA, 'M', u'ҫ'), + (0x4AB, 'V'), + (0x4AC, 'M', u'ҭ'), + (0x4AD, 'V'), + (0x4AE, 'M', u'ү'), + (0x4AF, 'V'), + (0x4B0, 'M', u'ұ'), + (0x4B1, 'V'), + (0x4B2, 'M', u'ҳ'), + (0x4B3, 'V'), + (0x4B4, 'M', u'ҵ'), + (0x4B5, 'V'), + (0x4B6, 'M', u'ҷ'), + (0x4B7, 'V'), + (0x4B8, 'M', u'ҹ'), + (0x4B9, 'V'), + (0x4BA, 'M', u'һ'), + (0x4BB, 'V'), + (0x4BC, 'M', u'ҽ'), + (0x4BD, 'V'), + (0x4BE, 'M', u'ҿ'), + (0x4BF, 'V'), + (0x4C0, 'X'), + (0x4C1, 'M', u'ӂ'), + (0x4C2, 'V'), + (0x4C3, 'M', u'ӄ'), + (0x4C4, 'V'), + (0x4C5, 'M', u'ӆ'), + (0x4C6, 'V'), + (0x4C7, 'M', u'ӈ'), + (0x4C8, 'V'), + (0x4C9, 'M', u'ӊ'), + (0x4CA, 'V'), + (0x4CB, 'M', u'ӌ'), + (0x4CC, 'V'), + (0x4CD, 'M', u'ӎ'), + (0x4CE, 'V'), + (0x4D0, 'M', u'ӑ'), + (0x4D1, 'V'), + (0x4D2, 'M', u'ӓ'), + (0x4D3, 'V'), + (0x4D4, 'M', u'ӕ'), + (0x4D5, 'V'), + (0x4D6, 'M', u'ӗ'), + (0x4D7, 'V'), + (0x4D8, 'M', u'ә'), + (0x4D9, 'V'), + (0x4DA, 'M', u'ӛ'), + (0x4DB, 'V'), + (0x4DC, 'M', u'ӝ'), + (0x4DD, 'V'), + (0x4DE, 'M', u'ӟ'), + (0x4DF, 'V'), + (0x4E0, 'M', u'ӡ'), + (0x4E1, 'V'), + (0x4E2, 'M', u'ӣ'), + (0x4E3, 'V'), + (0x4E4, 'M', u'ӥ'), + (0x4E5, 'V'), + (0x4E6, 'M', u'ӧ'), + (0x4E7, 'V'), + (0x4E8, 'M', u'ө'), + (0x4E9, 'V'), + (0x4EA, 'M', u'ӫ'), + (0x4EB, 'V'), + (0x4EC, 'M', u'ӭ'), + (0x4ED, 'V'), + (0x4EE, 'M', u'ӯ'), + (0x4EF, 'V'), + (0x4F0, 'M', u'ӱ'), + (0x4F1, 'V'), + (0x4F2, 'M', u'ӳ'), + (0x4F3, 'V'), + (0x4F4, 'M', u'ӵ'), + (0x4F5, 'V'), + (0x4F6, 'M', u'ӷ'), + (0x4F7, 'V'), + (0x4F8, 'M', u'ӹ'), + (0x4F9, 'V'), + (0x4FA, 'M', u'ӻ'), + (0x4FB, 'V'), + (0x4FC, 'M', u'ӽ'), + (0x4FD, 'V'), + (0x4FE, 'M', u'ӿ'), + (0x4FF, 'V'), + (0x500, 'M', u'ԁ'), + (0x501, 'V'), + (0x502, 'M', u'ԃ'), + ] + +def _seg_9(): + return [ + (0x503, 'V'), + (0x504, 'M', u'ԅ'), + (0x505, 'V'), + (0x506, 'M', u'ԇ'), + (0x507, 'V'), + (0x508, 'M', u'ԉ'), + (0x509, 'V'), + (0x50A, 'M', u'ԋ'), + (0x50B, 'V'), + (0x50C, 'M', u'ԍ'), + (0x50D, 'V'), + (0x50E, 'M', u'ԏ'), + (0x50F, 'V'), + (0x510, 'M', u'ԑ'), + (0x511, 'V'), + (0x512, 'M', u'ԓ'), + (0x513, 'V'), + (0x514, 'M', u'ԕ'), + (0x515, 'V'), + (0x516, 'M', u'ԗ'), + (0x517, 'V'), + (0x518, 'M', u'ԙ'), + (0x519, 'V'), + (0x51A, 'M', u'ԛ'), + (0x51B, 'V'), + (0x51C, 'M', u'ԝ'), + (0x51D, 'V'), + (0x51E, 'M', u'ԟ'), + (0x51F, 'V'), + (0x520, 'M', u'ԡ'), + (0x521, 'V'), + (0x522, 'M', u'ԣ'), + (0x523, 'V'), + (0x524, 'M', u'ԥ'), + (0x525, 'V'), + (0x526, 'M', u'ԧ'), + (0x527, 'V'), + (0x528, 'M', u'ԩ'), + (0x529, 'V'), + (0x52A, 'M', u'ԫ'), + (0x52B, 'V'), + (0x52C, 'M', u'ԭ'), + (0x52D, 'V'), + (0x52E, 'M', u'ԯ'), + (0x52F, 'V'), + (0x530, 'X'), + (0x531, 'M', u'ա'), + (0x532, 'M', u'բ'), + (0x533, 'M', u'գ'), + (0x534, 'M', u'դ'), + (0x535, 'M', u'ե'), + (0x536, 'M', u'զ'), + (0x537, 'M', u'է'), + (0x538, 'M', u'ը'), + (0x539, 'M', u'թ'), + (0x53A, 'M', u'ժ'), + (0x53B, 'M', u'ի'), + (0x53C, 'M', u'լ'), + (0x53D, 'M', u'խ'), + (0x53E, 'M', u'ծ'), + (0x53F, 'M', u'կ'), + (0x540, 'M', u'հ'), + (0x541, 'M', u'ձ'), + (0x542, 'M', u'ղ'), + (0x543, 'M', u'ճ'), + (0x544, 'M', u'մ'), + (0x545, 'M', u'յ'), + (0x546, 'M', u'ն'), + (0x547, 'M', u'շ'), + (0x548, 'M', u'ո'), + (0x549, 'M', u'չ'), + (0x54A, 'M', u'պ'), + (0x54B, 'M', u'ջ'), + (0x54C, 'M', u'ռ'), + (0x54D, 'M', u'ս'), + (0x54E, 'M', u'վ'), + (0x54F, 'M', u'տ'), + (0x550, 'M', u'ր'), + (0x551, 'M', u'ց'), + (0x552, 'M', u'ւ'), + (0x553, 'M', u'փ'), + (0x554, 'M', u'ք'), + (0x555, 'M', u'օ'), + (0x556, 'M', u'ֆ'), + (0x557, 'X'), + (0x559, 'V'), + (0x560, 'X'), + (0x561, 'V'), + (0x587, 'M', u'եւ'), + (0x588, 'X'), + (0x589, 'V'), + (0x58B, 'X'), + (0x58D, 'V'), + (0x590, 'X'), + (0x591, 'V'), + (0x5C8, 'X'), + (0x5D0, 'V'), + (0x5EB, 'X'), + (0x5F0, 'V'), + (0x5F5, 'X'), + ] + +def _seg_10(): + return [ + (0x606, 'V'), + (0x61C, 'X'), + (0x61E, 'V'), + (0x675, 'M', u'اٴ'), + (0x676, 'M', u'وٴ'), + (0x677, 'M', u'ۇٴ'), + (0x678, 'M', u'يٴ'), + (0x679, 'V'), + (0x6DD, 'X'), + (0x6DE, 'V'), + (0x70E, 'X'), + (0x710, 'V'), + (0x74B, 'X'), + (0x74D, 'V'), + (0x7B2, 'X'), + (0x7C0, 'V'), + (0x7FB, 'X'), + (0x800, 'V'), + (0x82E, 'X'), + (0x830, 'V'), + (0x83F, 'X'), + (0x840, 'V'), + (0x85C, 'X'), + (0x85E, 'V'), + (0x85F, 'X'), + (0x860, 'V'), + (0x86B, 'X'), + (0x8A0, 'V'), + (0x8B5, 'X'), + (0x8B6, 'V'), + (0x8BE, 'X'), + (0x8D4, 'V'), + (0x8E2, 'X'), + (0x8E3, 'V'), + (0x958, 'M', u'क़'), + (0x959, 'M', u'ख़'), + (0x95A, 'M', u'ग़'), + (0x95B, 'M', u'ज़'), + (0x95C, 'M', u'ड़'), + (0x95D, 'M', u'ढ़'), + (0x95E, 'M', u'फ़'), + (0x95F, 'M', u'य़'), + (0x960, 'V'), + (0x984, 'X'), + (0x985, 'V'), + (0x98D, 'X'), + (0x98F, 'V'), + (0x991, 'X'), + (0x993, 'V'), + (0x9A9, 'X'), + (0x9AA, 'V'), + (0x9B1, 'X'), + (0x9B2, 'V'), + (0x9B3, 'X'), + (0x9B6, 'V'), + (0x9BA, 'X'), + (0x9BC, 'V'), + (0x9C5, 'X'), + (0x9C7, 'V'), + (0x9C9, 'X'), + (0x9CB, 'V'), + (0x9CF, 'X'), + (0x9D7, 'V'), + (0x9D8, 'X'), + (0x9DC, 'M', u'ড়'), + (0x9DD, 'M', u'ঢ়'), + (0x9DE, 'X'), + (0x9DF, 'M', u'য়'), + (0x9E0, 'V'), + (0x9E4, 'X'), + (0x9E6, 'V'), + (0x9FE, 'X'), + (0xA01, 'V'), + (0xA04, 'X'), + (0xA05, 'V'), + (0xA0B, 'X'), + (0xA0F, 'V'), + (0xA11, 'X'), + (0xA13, 'V'), + (0xA29, 'X'), + (0xA2A, 'V'), + (0xA31, 'X'), + (0xA32, 'V'), + (0xA33, 'M', u'ਲ਼'), + (0xA34, 'X'), + (0xA35, 'V'), + (0xA36, 'M', u'ਸ਼'), + (0xA37, 'X'), + (0xA38, 'V'), + (0xA3A, 'X'), + (0xA3C, 'V'), + (0xA3D, 'X'), + (0xA3E, 'V'), + (0xA43, 'X'), + (0xA47, 'V'), + (0xA49, 'X'), + (0xA4B, 'V'), + (0xA4E, 'X'), + (0xA51, 'V'), + (0xA52, 'X'), + ] + +def _seg_11(): + return [ + (0xA59, 'M', u'ਖ਼'), + (0xA5A, 'M', u'ਗ਼'), + (0xA5B, 'M', u'ਜ਼'), + (0xA5C, 'V'), + (0xA5D, 'X'), + (0xA5E, 'M', u'ਫ਼'), + (0xA5F, 'X'), + (0xA66, 'V'), + (0xA76, 'X'), + (0xA81, 'V'), + (0xA84, 'X'), + (0xA85, 'V'), + (0xA8E, 'X'), + (0xA8F, 'V'), + (0xA92, 'X'), + (0xA93, 'V'), + (0xAA9, 'X'), + (0xAAA, 'V'), + (0xAB1, 'X'), + (0xAB2, 'V'), + (0xAB4, 'X'), + (0xAB5, 'V'), + (0xABA, 'X'), + (0xABC, 'V'), + (0xAC6, 'X'), + (0xAC7, 'V'), + (0xACA, 'X'), + (0xACB, 'V'), + (0xACE, 'X'), + (0xAD0, 'V'), + (0xAD1, 'X'), + (0xAE0, 'V'), + (0xAE4, 'X'), + (0xAE6, 'V'), + (0xAF2, 'X'), + (0xAF9, 'V'), + (0xB00, 'X'), + (0xB01, 'V'), + (0xB04, 'X'), + (0xB05, 'V'), + (0xB0D, 'X'), + (0xB0F, 'V'), + (0xB11, 'X'), + (0xB13, 'V'), + (0xB29, 'X'), + (0xB2A, 'V'), + (0xB31, 'X'), + (0xB32, 'V'), + (0xB34, 'X'), + (0xB35, 'V'), + (0xB3A, 'X'), + (0xB3C, 'V'), + (0xB45, 'X'), + (0xB47, 'V'), + (0xB49, 'X'), + (0xB4B, 'V'), + (0xB4E, 'X'), + (0xB56, 'V'), + (0xB58, 'X'), + (0xB5C, 'M', u'ଡ଼'), + (0xB5D, 'M', u'ଢ଼'), + (0xB5E, 'X'), + (0xB5F, 'V'), + (0xB64, 'X'), + (0xB66, 'V'), + (0xB78, 'X'), + (0xB82, 'V'), + (0xB84, 'X'), + (0xB85, 'V'), + (0xB8B, 'X'), + (0xB8E, 'V'), + (0xB91, 'X'), + (0xB92, 'V'), + (0xB96, 'X'), + (0xB99, 'V'), + (0xB9B, 'X'), + (0xB9C, 'V'), + (0xB9D, 'X'), + (0xB9E, 'V'), + (0xBA0, 'X'), + (0xBA3, 'V'), + (0xBA5, 'X'), + (0xBA8, 'V'), + (0xBAB, 'X'), + (0xBAE, 'V'), + (0xBBA, 'X'), + (0xBBE, 'V'), + (0xBC3, 'X'), + (0xBC6, 'V'), + (0xBC9, 'X'), + (0xBCA, 'V'), + (0xBCE, 'X'), + (0xBD0, 'V'), + (0xBD1, 'X'), + (0xBD7, 'V'), + (0xBD8, 'X'), + (0xBE6, 'V'), + (0xBFB, 'X'), + (0xC00, 'V'), + (0xC04, 'X'), + ] + +def _seg_12(): + return [ + (0xC05, 'V'), + (0xC0D, 'X'), + (0xC0E, 'V'), + (0xC11, 'X'), + (0xC12, 'V'), + (0xC29, 'X'), + (0xC2A, 'V'), + (0xC3A, 'X'), + (0xC3D, 'V'), + (0xC45, 'X'), + (0xC46, 'V'), + (0xC49, 'X'), + (0xC4A, 'V'), + (0xC4E, 'X'), + (0xC55, 'V'), + (0xC57, 'X'), + (0xC58, 'V'), + (0xC5B, 'X'), + (0xC60, 'V'), + (0xC64, 'X'), + (0xC66, 'V'), + (0xC70, 'X'), + (0xC78, 'V'), + (0xC84, 'X'), + (0xC85, 'V'), + (0xC8D, 'X'), + (0xC8E, 'V'), + (0xC91, 'X'), + (0xC92, 'V'), + (0xCA9, 'X'), + (0xCAA, 'V'), + (0xCB4, 'X'), + (0xCB5, 'V'), + (0xCBA, 'X'), + (0xCBC, 'V'), + (0xCC5, 'X'), + (0xCC6, 'V'), + (0xCC9, 'X'), + (0xCCA, 'V'), + (0xCCE, 'X'), + (0xCD5, 'V'), + (0xCD7, 'X'), + (0xCDE, 'V'), + (0xCDF, 'X'), + (0xCE0, 'V'), + (0xCE4, 'X'), + (0xCE6, 'V'), + (0xCF0, 'X'), + (0xCF1, 'V'), + (0xCF3, 'X'), + (0xD00, 'V'), + (0xD04, 'X'), + (0xD05, 'V'), + (0xD0D, 'X'), + (0xD0E, 'V'), + (0xD11, 'X'), + (0xD12, 'V'), + (0xD45, 'X'), + (0xD46, 'V'), + (0xD49, 'X'), + (0xD4A, 'V'), + (0xD50, 'X'), + (0xD54, 'V'), + (0xD64, 'X'), + (0xD66, 'V'), + (0xD80, 'X'), + (0xD82, 'V'), + (0xD84, 'X'), + (0xD85, 'V'), + (0xD97, 'X'), + (0xD9A, 'V'), + (0xDB2, 'X'), + (0xDB3, 'V'), + (0xDBC, 'X'), + (0xDBD, 'V'), + (0xDBE, 'X'), + (0xDC0, 'V'), + (0xDC7, 'X'), + (0xDCA, 'V'), + (0xDCB, 'X'), + (0xDCF, 'V'), + (0xDD5, 'X'), + (0xDD6, 'V'), + (0xDD7, 'X'), + (0xDD8, 'V'), + (0xDE0, 'X'), + (0xDE6, 'V'), + (0xDF0, 'X'), + (0xDF2, 'V'), + (0xDF5, 'X'), + (0xE01, 'V'), + (0xE33, 'M', u'ํา'), + (0xE34, 'V'), + (0xE3B, 'X'), + (0xE3F, 'V'), + (0xE5C, 'X'), + (0xE81, 'V'), + (0xE83, 'X'), + (0xE84, 'V'), + (0xE85, 'X'), + ] + +def _seg_13(): + return [ + (0xE87, 'V'), + (0xE89, 'X'), + (0xE8A, 'V'), + (0xE8B, 'X'), + (0xE8D, 'V'), + (0xE8E, 'X'), + (0xE94, 'V'), + (0xE98, 'X'), + (0xE99, 'V'), + (0xEA0, 'X'), + (0xEA1, 'V'), + (0xEA4, 'X'), + (0xEA5, 'V'), + (0xEA6, 'X'), + (0xEA7, 'V'), + (0xEA8, 'X'), + (0xEAA, 'V'), + (0xEAC, 'X'), + (0xEAD, 'V'), + (0xEB3, 'M', u'ໍາ'), + (0xEB4, 'V'), + (0xEBA, 'X'), + (0xEBB, 'V'), + (0xEBE, 'X'), + (0xEC0, 'V'), + (0xEC5, 'X'), + (0xEC6, 'V'), + (0xEC7, 'X'), + (0xEC8, 'V'), + (0xECE, 'X'), + (0xED0, 'V'), + (0xEDA, 'X'), + (0xEDC, 'M', u'ຫນ'), + (0xEDD, 'M', u'ຫມ'), + (0xEDE, 'V'), + (0xEE0, 'X'), + (0xF00, 'V'), + (0xF0C, 'M', u'་'), + (0xF0D, 'V'), + (0xF43, 'M', u'གྷ'), + (0xF44, 'V'), + (0xF48, 'X'), + (0xF49, 'V'), + (0xF4D, 'M', u'ཌྷ'), + (0xF4E, 'V'), + (0xF52, 'M', u'དྷ'), + (0xF53, 'V'), + (0xF57, 'M', u'བྷ'), + (0xF58, 'V'), + (0xF5C, 'M', u'ཛྷ'), + (0xF5D, 'V'), + (0xF69, 'M', u'ཀྵ'), + (0xF6A, 'V'), + (0xF6D, 'X'), + (0xF71, 'V'), + (0xF73, 'M', u'ཱི'), + (0xF74, 'V'), + (0xF75, 'M', u'ཱུ'), + (0xF76, 'M', u'ྲྀ'), + (0xF77, 'M', u'ྲཱྀ'), + (0xF78, 'M', u'ླྀ'), + (0xF79, 'M', u'ླཱྀ'), + (0xF7A, 'V'), + (0xF81, 'M', u'ཱྀ'), + (0xF82, 'V'), + (0xF93, 'M', u'ྒྷ'), + (0xF94, 'V'), + (0xF98, 'X'), + (0xF99, 'V'), + (0xF9D, 'M', u'ྜྷ'), + (0xF9E, 'V'), + (0xFA2, 'M', u'ྡྷ'), + (0xFA3, 'V'), + (0xFA7, 'M', u'ྦྷ'), + (0xFA8, 'V'), + (0xFAC, 'M', u'ྫྷ'), + (0xFAD, 'V'), + (0xFB9, 'M', u'ྐྵ'), + (0xFBA, 'V'), + (0xFBD, 'X'), + (0xFBE, 'V'), + (0xFCD, 'X'), + (0xFCE, 'V'), + (0xFDB, 'X'), + (0x1000, 'V'), + (0x10A0, 'X'), + (0x10C7, 'M', u'ⴧ'), + (0x10C8, 'X'), + (0x10CD, 'M', u'ⴭ'), + (0x10CE, 'X'), + (0x10D0, 'V'), + (0x10FC, 'M', u'ნ'), + (0x10FD, 'V'), + (0x115F, 'X'), + (0x1161, 'V'), + (0x1249, 'X'), + (0x124A, 'V'), + (0x124E, 'X'), + (0x1250, 'V'), + (0x1257, 'X'), + ] + +def _seg_14(): + return [ + (0x1258, 'V'), + (0x1259, 'X'), + (0x125A, 'V'), + (0x125E, 'X'), + (0x1260, 'V'), + (0x1289, 'X'), + (0x128A, 'V'), + (0x128E, 'X'), + (0x1290, 'V'), + (0x12B1, 'X'), + (0x12B2, 'V'), + (0x12B6, 'X'), + (0x12B8, 'V'), + (0x12BF, 'X'), + (0x12C0, 'V'), + (0x12C1, 'X'), + (0x12C2, 'V'), + (0x12C6, 'X'), + (0x12C8, 'V'), + (0x12D7, 'X'), + (0x12D8, 'V'), + (0x1311, 'X'), + (0x1312, 'V'), + (0x1316, 'X'), + (0x1318, 'V'), + (0x135B, 'X'), + (0x135D, 'V'), + (0x137D, 'X'), + (0x1380, 'V'), + (0x139A, 'X'), + (0x13A0, 'V'), + (0x13F6, 'X'), + (0x13F8, 'M', u'Ᏸ'), + (0x13F9, 'M', u'Ᏹ'), + (0x13FA, 'M', u'Ᏺ'), + (0x13FB, 'M', u'Ᏻ'), + (0x13FC, 'M', u'Ᏼ'), + (0x13FD, 'M', u'Ᏽ'), + (0x13FE, 'X'), + (0x1400, 'V'), + (0x1680, 'X'), + (0x1681, 'V'), + (0x169D, 'X'), + (0x16A0, 'V'), + (0x16F9, 'X'), + (0x1700, 'V'), + (0x170D, 'X'), + (0x170E, 'V'), + (0x1715, 'X'), + (0x1720, 'V'), + (0x1737, 'X'), + (0x1740, 'V'), + (0x1754, 'X'), + (0x1760, 'V'), + (0x176D, 'X'), + (0x176E, 'V'), + (0x1771, 'X'), + (0x1772, 'V'), + (0x1774, 'X'), + (0x1780, 'V'), + (0x17B4, 'X'), + (0x17B6, 'V'), + (0x17DE, 'X'), + (0x17E0, 'V'), + (0x17EA, 'X'), + (0x17F0, 'V'), + (0x17FA, 'X'), + (0x1800, 'V'), + (0x1806, 'X'), + (0x1807, 'V'), + (0x180B, 'I'), + (0x180E, 'X'), + (0x1810, 'V'), + (0x181A, 'X'), + (0x1820, 'V'), + (0x1878, 'X'), + (0x1880, 'V'), + (0x18AB, 'X'), + (0x18B0, 'V'), + (0x18F6, 'X'), + (0x1900, 'V'), + (0x191F, 'X'), + (0x1920, 'V'), + (0x192C, 'X'), + (0x1930, 'V'), + (0x193C, 'X'), + (0x1940, 'V'), + (0x1941, 'X'), + (0x1944, 'V'), + (0x196E, 'X'), + (0x1970, 'V'), + (0x1975, 'X'), + (0x1980, 'V'), + (0x19AC, 'X'), + (0x19B0, 'V'), + (0x19CA, 'X'), + (0x19D0, 'V'), + (0x19DB, 'X'), + (0x19DE, 'V'), + (0x1A1C, 'X'), + ] + +def _seg_15(): + return [ + (0x1A1E, 'V'), + (0x1A5F, 'X'), + (0x1A60, 'V'), + (0x1A7D, 'X'), + (0x1A7F, 'V'), + (0x1A8A, 'X'), + (0x1A90, 'V'), + (0x1A9A, 'X'), + (0x1AA0, 'V'), + (0x1AAE, 'X'), + (0x1AB0, 'V'), + (0x1ABF, 'X'), + (0x1B00, 'V'), + (0x1B4C, 'X'), + (0x1B50, 'V'), + (0x1B7D, 'X'), + (0x1B80, 'V'), + (0x1BF4, 'X'), + (0x1BFC, 'V'), + (0x1C38, 'X'), + (0x1C3B, 'V'), + (0x1C4A, 'X'), + (0x1C4D, 'V'), + (0x1C80, 'M', u'в'), + (0x1C81, 'M', u'д'), + (0x1C82, 'M', u'о'), + (0x1C83, 'M', u'с'), + (0x1C84, 'M', u'т'), + (0x1C86, 'M', u'ъ'), + (0x1C87, 'M', u'ѣ'), + (0x1C88, 'M', u'ꙋ'), + (0x1C89, 'X'), + (0x1CC0, 'V'), + (0x1CC8, 'X'), + (0x1CD0, 'V'), + (0x1CFA, 'X'), + (0x1D00, 'V'), + (0x1D2C, 'M', u'a'), + (0x1D2D, 'M', u'æ'), + (0x1D2E, 'M', u'b'), + (0x1D2F, 'V'), + (0x1D30, 'M', u'd'), + (0x1D31, 'M', u'e'), + (0x1D32, 'M', u'ǝ'), + (0x1D33, 'M', u'g'), + (0x1D34, 'M', u'h'), + (0x1D35, 'M', u'i'), + (0x1D36, 'M', u'j'), + (0x1D37, 'M', u'k'), + (0x1D38, 'M', u'l'), + (0x1D39, 'M', u'm'), + (0x1D3A, 'M', u'n'), + (0x1D3B, 'V'), + (0x1D3C, 'M', u'o'), + (0x1D3D, 'M', u'ȣ'), + (0x1D3E, 'M', u'p'), + (0x1D3F, 'M', u'r'), + (0x1D40, 'M', u't'), + (0x1D41, 'M', u'u'), + (0x1D42, 'M', u'w'), + (0x1D43, 'M', u'a'), + (0x1D44, 'M', u'ɐ'), + (0x1D45, 'M', u'ɑ'), + (0x1D46, 'M', u'ᴂ'), + (0x1D47, 'M', u'b'), + (0x1D48, 'M', u'd'), + (0x1D49, 'M', u'e'), + (0x1D4A, 'M', u'ə'), + (0x1D4B, 'M', u'ɛ'), + (0x1D4C, 'M', u'ɜ'), + (0x1D4D, 'M', u'g'), + (0x1D4E, 'V'), + (0x1D4F, 'M', u'k'), + (0x1D50, 'M', u'm'), + (0x1D51, 'M', u'ŋ'), + (0x1D52, 'M', u'o'), + (0x1D53, 'M', u'ɔ'), + (0x1D54, 'M', u'ᴖ'), + (0x1D55, 'M', u'ᴗ'), + (0x1D56, 'M', u'p'), + (0x1D57, 'M', u't'), + (0x1D58, 'M', u'u'), + (0x1D59, 'M', u'ᴝ'), + (0x1D5A, 'M', u'ɯ'), + (0x1D5B, 'M', u'v'), + (0x1D5C, 'M', u'ᴥ'), + (0x1D5D, 'M', u'β'), + (0x1D5E, 'M', u'γ'), + (0x1D5F, 'M', u'δ'), + (0x1D60, 'M', u'φ'), + (0x1D61, 'M', u'χ'), + (0x1D62, 'M', u'i'), + (0x1D63, 'M', u'r'), + (0x1D64, 'M', u'u'), + (0x1D65, 'M', u'v'), + (0x1D66, 'M', u'β'), + (0x1D67, 'M', u'γ'), + (0x1D68, 'M', u'ρ'), + (0x1D69, 'M', u'φ'), + (0x1D6A, 'M', u'χ'), + ] + +def _seg_16(): + return [ + (0x1D6B, 'V'), + (0x1D78, 'M', u'н'), + (0x1D79, 'V'), + (0x1D9B, 'M', u'ɒ'), + (0x1D9C, 'M', u'c'), + (0x1D9D, 'M', u'ɕ'), + (0x1D9E, 'M', u'ð'), + (0x1D9F, 'M', u'ɜ'), + (0x1DA0, 'M', u'f'), + (0x1DA1, 'M', u'ɟ'), + (0x1DA2, 'M', u'ɡ'), + (0x1DA3, 'M', u'ɥ'), + (0x1DA4, 'M', u'ɨ'), + (0x1DA5, 'M', u'ɩ'), + (0x1DA6, 'M', u'ɪ'), + (0x1DA7, 'M', u'ᵻ'), + (0x1DA8, 'M', u'ʝ'), + (0x1DA9, 'M', u'ɭ'), + (0x1DAA, 'M', u'ᶅ'), + (0x1DAB, 'M', u'ʟ'), + (0x1DAC, 'M', u'ɱ'), + (0x1DAD, 'M', u'ɰ'), + (0x1DAE, 'M', u'ɲ'), + (0x1DAF, 'M', u'ɳ'), + (0x1DB0, 'M', u'ɴ'), + (0x1DB1, 'M', u'ɵ'), + (0x1DB2, 'M', u'ɸ'), + (0x1DB3, 'M', u'ʂ'), + (0x1DB4, 'M', u'ʃ'), + (0x1DB5, 'M', u'ƫ'), + (0x1DB6, 'M', u'ʉ'), + (0x1DB7, 'M', u'ʊ'), + (0x1DB8, 'M', u'ᴜ'), + (0x1DB9, 'M', u'ʋ'), + (0x1DBA, 'M', u'ʌ'), + (0x1DBB, 'M', u'z'), + (0x1DBC, 'M', u'ʐ'), + (0x1DBD, 'M', u'ʑ'), + (0x1DBE, 'M', u'ʒ'), + (0x1DBF, 'M', u'θ'), + (0x1DC0, 'V'), + (0x1DFA, 'X'), + (0x1DFB, 'V'), + (0x1E00, 'M', u'ḁ'), + (0x1E01, 'V'), + (0x1E02, 'M', u'ḃ'), + (0x1E03, 'V'), + (0x1E04, 'M', u'ḅ'), + (0x1E05, 'V'), + (0x1E06, 'M', u'ḇ'), + (0x1E07, 'V'), + (0x1E08, 'M', u'ḉ'), + (0x1E09, 'V'), + (0x1E0A, 'M', u'ḋ'), + (0x1E0B, 'V'), + (0x1E0C, 'M', u'ḍ'), + (0x1E0D, 'V'), + (0x1E0E, 'M', u'ḏ'), + (0x1E0F, 'V'), + (0x1E10, 'M', u'ḑ'), + (0x1E11, 'V'), + (0x1E12, 'M', u'ḓ'), + (0x1E13, 'V'), + (0x1E14, 'M', u'ḕ'), + (0x1E15, 'V'), + (0x1E16, 'M', u'ḗ'), + (0x1E17, 'V'), + (0x1E18, 'M', u'ḙ'), + (0x1E19, 'V'), + (0x1E1A, 'M', u'ḛ'), + (0x1E1B, 'V'), + (0x1E1C, 'M', u'ḝ'), + (0x1E1D, 'V'), + (0x1E1E, 'M', u'ḟ'), + (0x1E1F, 'V'), + (0x1E20, 'M', u'ḡ'), + (0x1E21, 'V'), + (0x1E22, 'M', u'ḣ'), + (0x1E23, 'V'), + (0x1E24, 'M', u'ḥ'), + (0x1E25, 'V'), + (0x1E26, 'M', u'ḧ'), + (0x1E27, 'V'), + (0x1E28, 'M', u'ḩ'), + (0x1E29, 'V'), + (0x1E2A, 'M', u'ḫ'), + (0x1E2B, 'V'), + (0x1E2C, 'M', u'ḭ'), + (0x1E2D, 'V'), + (0x1E2E, 'M', u'ḯ'), + (0x1E2F, 'V'), + (0x1E30, 'M', u'ḱ'), + (0x1E31, 'V'), + (0x1E32, 'M', u'ḳ'), + (0x1E33, 'V'), + (0x1E34, 'M', u'ḵ'), + (0x1E35, 'V'), + (0x1E36, 'M', u'ḷ'), + (0x1E37, 'V'), + (0x1E38, 'M', u'ḹ'), + ] + +def _seg_17(): + return [ + (0x1E39, 'V'), + (0x1E3A, 'M', u'ḻ'), + (0x1E3B, 'V'), + (0x1E3C, 'M', u'ḽ'), + (0x1E3D, 'V'), + (0x1E3E, 'M', u'ḿ'), + (0x1E3F, 'V'), + (0x1E40, 'M', u'ṁ'), + (0x1E41, 'V'), + (0x1E42, 'M', u'ṃ'), + (0x1E43, 'V'), + (0x1E44, 'M', u'ṅ'), + (0x1E45, 'V'), + (0x1E46, 'M', u'ṇ'), + (0x1E47, 'V'), + (0x1E48, 'M', u'ṉ'), + (0x1E49, 'V'), + (0x1E4A, 'M', u'ṋ'), + (0x1E4B, 'V'), + (0x1E4C, 'M', u'ṍ'), + (0x1E4D, 'V'), + (0x1E4E, 'M', u'ṏ'), + (0x1E4F, 'V'), + (0x1E50, 'M', u'ṑ'), + (0x1E51, 'V'), + (0x1E52, 'M', u'ṓ'), + (0x1E53, 'V'), + (0x1E54, 'M', u'ṕ'), + (0x1E55, 'V'), + (0x1E56, 'M', u'ṗ'), + (0x1E57, 'V'), + (0x1E58, 'M', u'ṙ'), + (0x1E59, 'V'), + (0x1E5A, 'M', u'ṛ'), + (0x1E5B, 'V'), + (0x1E5C, 'M', u'ṝ'), + (0x1E5D, 'V'), + (0x1E5E, 'M', u'ṟ'), + (0x1E5F, 'V'), + (0x1E60, 'M', u'ṡ'), + (0x1E61, 'V'), + (0x1E62, 'M', u'ṣ'), + (0x1E63, 'V'), + (0x1E64, 'M', u'ṥ'), + (0x1E65, 'V'), + (0x1E66, 'M', u'ṧ'), + (0x1E67, 'V'), + (0x1E68, 'M', u'ṩ'), + (0x1E69, 'V'), + (0x1E6A, 'M', u'ṫ'), + (0x1E6B, 'V'), + (0x1E6C, 'M', u'ṭ'), + (0x1E6D, 'V'), + (0x1E6E, 'M', u'ṯ'), + (0x1E6F, 'V'), + (0x1E70, 'M', u'ṱ'), + (0x1E71, 'V'), + (0x1E72, 'M', u'ṳ'), + (0x1E73, 'V'), + (0x1E74, 'M', u'ṵ'), + (0x1E75, 'V'), + (0x1E76, 'M', u'ṷ'), + (0x1E77, 'V'), + (0x1E78, 'M', u'ṹ'), + (0x1E79, 'V'), + (0x1E7A, 'M', u'ṻ'), + (0x1E7B, 'V'), + (0x1E7C, 'M', u'ṽ'), + (0x1E7D, 'V'), + (0x1E7E, 'M', u'ṿ'), + (0x1E7F, 'V'), + (0x1E80, 'M', u'ẁ'), + (0x1E81, 'V'), + (0x1E82, 'M', u'ẃ'), + (0x1E83, 'V'), + (0x1E84, 'M', u'ẅ'), + (0x1E85, 'V'), + (0x1E86, 'M', u'ẇ'), + (0x1E87, 'V'), + (0x1E88, 'M', u'ẉ'), + (0x1E89, 'V'), + (0x1E8A, 'M', u'ẋ'), + (0x1E8B, 'V'), + (0x1E8C, 'M', u'ẍ'), + (0x1E8D, 'V'), + (0x1E8E, 'M', u'ẏ'), + (0x1E8F, 'V'), + (0x1E90, 'M', u'ẑ'), + (0x1E91, 'V'), + (0x1E92, 'M', u'ẓ'), + (0x1E93, 'V'), + (0x1E94, 'M', u'ẕ'), + (0x1E95, 'V'), + (0x1E9A, 'M', u'aʾ'), + (0x1E9B, 'M', u'ṡ'), + (0x1E9C, 'V'), + (0x1E9E, 'M', u'ss'), + (0x1E9F, 'V'), + (0x1EA0, 'M', u'ạ'), + (0x1EA1, 'V'), + ] + +def _seg_18(): + return [ + (0x1EA2, 'M', u'ả'), + (0x1EA3, 'V'), + (0x1EA4, 'M', u'ấ'), + (0x1EA5, 'V'), + (0x1EA6, 'M', u'ầ'), + (0x1EA7, 'V'), + (0x1EA8, 'M', u'ẩ'), + (0x1EA9, 'V'), + (0x1EAA, 'M', u'ẫ'), + (0x1EAB, 'V'), + (0x1EAC, 'M', u'ậ'), + (0x1EAD, 'V'), + (0x1EAE, 'M', u'ắ'), + (0x1EAF, 'V'), + (0x1EB0, 'M', u'ằ'), + (0x1EB1, 'V'), + (0x1EB2, 'M', u'ẳ'), + (0x1EB3, 'V'), + (0x1EB4, 'M', u'ẵ'), + (0x1EB5, 'V'), + (0x1EB6, 'M', u'ặ'), + (0x1EB7, 'V'), + (0x1EB8, 'M', u'ẹ'), + (0x1EB9, 'V'), + (0x1EBA, 'M', u'ẻ'), + (0x1EBB, 'V'), + (0x1EBC, 'M', u'ẽ'), + (0x1EBD, 'V'), + (0x1EBE, 'M', u'ế'), + (0x1EBF, 'V'), + (0x1EC0, 'M', u'ề'), + (0x1EC1, 'V'), + (0x1EC2, 'M', u'ể'), + (0x1EC3, 'V'), + (0x1EC4, 'M', u'ễ'), + (0x1EC5, 'V'), + (0x1EC6, 'M', u'ệ'), + (0x1EC7, 'V'), + (0x1EC8, 'M', u'ỉ'), + (0x1EC9, 'V'), + (0x1ECA, 'M', u'ị'), + (0x1ECB, 'V'), + (0x1ECC, 'M', u'ọ'), + (0x1ECD, 'V'), + (0x1ECE, 'M', u'ỏ'), + (0x1ECF, 'V'), + (0x1ED0, 'M', u'ố'), + (0x1ED1, 'V'), + (0x1ED2, 'M', u'ồ'), + (0x1ED3, 'V'), + (0x1ED4, 'M', u'ổ'), + (0x1ED5, 'V'), + (0x1ED6, 'M', u'ỗ'), + (0x1ED7, 'V'), + (0x1ED8, 'M', u'ộ'), + (0x1ED9, 'V'), + (0x1EDA, 'M', u'ớ'), + (0x1EDB, 'V'), + (0x1EDC, 'M', u'ờ'), + (0x1EDD, 'V'), + (0x1EDE, 'M', u'ở'), + (0x1EDF, 'V'), + (0x1EE0, 'M', u'ỡ'), + (0x1EE1, 'V'), + (0x1EE2, 'M', u'ợ'), + (0x1EE3, 'V'), + (0x1EE4, 'M', u'ụ'), + (0x1EE5, 'V'), + (0x1EE6, 'M', u'ủ'), + (0x1EE7, 'V'), + (0x1EE8, 'M', u'ứ'), + (0x1EE9, 'V'), + (0x1EEA, 'M', u'ừ'), + (0x1EEB, 'V'), + (0x1EEC, 'M', u'ử'), + (0x1EED, 'V'), + (0x1EEE, 'M', u'ữ'), + (0x1EEF, 'V'), + (0x1EF0, 'M', u'ự'), + (0x1EF1, 'V'), + (0x1EF2, 'M', u'ỳ'), + (0x1EF3, 'V'), + (0x1EF4, 'M', u'ỵ'), + (0x1EF5, 'V'), + (0x1EF6, 'M', u'ỷ'), + (0x1EF7, 'V'), + (0x1EF8, 'M', u'ỹ'), + (0x1EF9, 'V'), + (0x1EFA, 'M', u'ỻ'), + (0x1EFB, 'V'), + (0x1EFC, 'M', u'ỽ'), + (0x1EFD, 'V'), + (0x1EFE, 'M', u'ỿ'), + (0x1EFF, 'V'), + (0x1F08, 'M', u'ἀ'), + (0x1F09, 'M', u'ἁ'), + (0x1F0A, 'M', u'ἂ'), + (0x1F0B, 'M', u'ἃ'), + (0x1F0C, 'M', u'ἄ'), + (0x1F0D, 'M', u'ἅ'), + ] + +def _seg_19(): + return [ + (0x1F0E, 'M', u'ἆ'), + (0x1F0F, 'M', u'ἇ'), + (0x1F10, 'V'), + (0x1F16, 'X'), + (0x1F18, 'M', u'ἐ'), + (0x1F19, 'M', u'ἑ'), + (0x1F1A, 'M', u'ἒ'), + (0x1F1B, 'M', u'ἓ'), + (0x1F1C, 'M', u'ἔ'), + (0x1F1D, 'M', u'ἕ'), + (0x1F1E, 'X'), + (0x1F20, 'V'), + (0x1F28, 'M', u'ἠ'), + (0x1F29, 'M', u'ἡ'), + (0x1F2A, 'M', u'ἢ'), + (0x1F2B, 'M', u'ἣ'), + (0x1F2C, 'M', u'ἤ'), + (0x1F2D, 'M', u'ἥ'), + (0x1F2E, 'M', u'ἦ'), + (0x1F2F, 'M', u'ἧ'), + (0x1F30, 'V'), + (0x1F38, 'M', u'ἰ'), + (0x1F39, 'M', u'ἱ'), + (0x1F3A, 'M', u'ἲ'), + (0x1F3B, 'M', u'ἳ'), + (0x1F3C, 'M', u'ἴ'), + (0x1F3D, 'M', u'ἵ'), + (0x1F3E, 'M', u'ἶ'), + (0x1F3F, 'M', u'ἷ'), + (0x1F40, 'V'), + (0x1F46, 'X'), + (0x1F48, 'M', u'ὀ'), + (0x1F49, 'M', u'ὁ'), + (0x1F4A, 'M', u'ὂ'), + (0x1F4B, 'M', u'ὃ'), + (0x1F4C, 'M', u'ὄ'), + (0x1F4D, 'M', u'ὅ'), + (0x1F4E, 'X'), + (0x1F50, 'V'), + (0x1F58, 'X'), + (0x1F59, 'M', u'ὑ'), + (0x1F5A, 'X'), + (0x1F5B, 'M', u'ὓ'), + (0x1F5C, 'X'), + (0x1F5D, 'M', u'ὕ'), + (0x1F5E, 'X'), + (0x1F5F, 'M', u'ὗ'), + (0x1F60, 'V'), + (0x1F68, 'M', u'ὠ'), + (0x1F69, 'M', u'ὡ'), + (0x1F6A, 'M', u'ὢ'), + (0x1F6B, 'M', u'ὣ'), + (0x1F6C, 'M', u'ὤ'), + (0x1F6D, 'M', u'ὥ'), + (0x1F6E, 'M', u'ὦ'), + (0x1F6F, 'M', u'ὧ'), + (0x1F70, 'V'), + (0x1F71, 'M', u'ά'), + (0x1F72, 'V'), + (0x1F73, 'M', u'έ'), + (0x1F74, 'V'), + (0x1F75, 'M', u'ή'), + (0x1F76, 'V'), + (0x1F77, 'M', u'ί'), + (0x1F78, 'V'), + (0x1F79, 'M', u'ό'), + (0x1F7A, 'V'), + (0x1F7B, 'M', u'ύ'), + (0x1F7C, 'V'), + (0x1F7D, 'M', u'ώ'), + (0x1F7E, 'X'), + (0x1F80, 'M', u'ἀι'), + (0x1F81, 'M', u'ἁι'), + (0x1F82, 'M', u'ἂι'), + (0x1F83, 'M', u'ἃι'), + (0x1F84, 'M', u'ἄι'), + (0x1F85, 'M', u'ἅι'), + (0x1F86, 'M', u'ἆι'), + (0x1F87, 'M', u'ἇι'), + (0x1F88, 'M', u'ἀι'), + (0x1F89, 'M', u'ἁι'), + (0x1F8A, 'M', u'ἂι'), + (0x1F8B, 'M', u'ἃι'), + (0x1F8C, 'M', u'ἄι'), + (0x1F8D, 'M', u'ἅι'), + (0x1F8E, 'M', u'ἆι'), + (0x1F8F, 'M', u'ἇι'), + (0x1F90, 'M', u'ἠι'), + (0x1F91, 'M', u'ἡι'), + (0x1F92, 'M', u'ἢι'), + (0x1F93, 'M', u'ἣι'), + (0x1F94, 'M', u'ἤι'), + (0x1F95, 'M', u'ἥι'), + (0x1F96, 'M', u'ἦι'), + (0x1F97, 'M', u'ἧι'), + (0x1F98, 'M', u'ἠι'), + (0x1F99, 'M', u'ἡι'), + (0x1F9A, 'M', u'ἢι'), + (0x1F9B, 'M', u'ἣι'), + (0x1F9C, 'M', u'ἤι'), + ] + +def _seg_20(): + return [ + (0x1F9D, 'M', u'ἥι'), + (0x1F9E, 'M', u'ἦι'), + (0x1F9F, 'M', u'ἧι'), + (0x1FA0, 'M', u'ὠι'), + (0x1FA1, 'M', u'ὡι'), + (0x1FA2, 'M', u'ὢι'), + (0x1FA3, 'M', u'ὣι'), + (0x1FA4, 'M', u'ὤι'), + (0x1FA5, 'M', u'ὥι'), + (0x1FA6, 'M', u'ὦι'), + (0x1FA7, 'M', u'ὧι'), + (0x1FA8, 'M', u'ὠι'), + (0x1FA9, 'M', u'ὡι'), + (0x1FAA, 'M', u'ὢι'), + (0x1FAB, 'M', u'ὣι'), + (0x1FAC, 'M', u'ὤι'), + (0x1FAD, 'M', u'ὥι'), + (0x1FAE, 'M', u'ὦι'), + (0x1FAF, 'M', u'ὧι'), + (0x1FB0, 'V'), + (0x1FB2, 'M', u'ὰι'), + (0x1FB3, 'M', u'αι'), + (0x1FB4, 'M', u'άι'), + (0x1FB5, 'X'), + (0x1FB6, 'V'), + (0x1FB7, 'M', u'ᾶι'), + (0x1FB8, 'M', u'ᾰ'), + (0x1FB9, 'M', u'ᾱ'), + (0x1FBA, 'M', u'ὰ'), + (0x1FBB, 'M', u'ά'), + (0x1FBC, 'M', u'αι'), + (0x1FBD, '3', u' ̓'), + (0x1FBE, 'M', u'ι'), + (0x1FBF, '3', u' ̓'), + (0x1FC0, '3', u' ͂'), + (0x1FC1, '3', u' ̈͂'), + (0x1FC2, 'M', u'ὴι'), + (0x1FC3, 'M', u'ηι'), + (0x1FC4, 'M', u'ήι'), + (0x1FC5, 'X'), + (0x1FC6, 'V'), + (0x1FC7, 'M', u'ῆι'), + (0x1FC8, 'M', u'ὲ'), + (0x1FC9, 'M', u'έ'), + (0x1FCA, 'M', u'ὴ'), + (0x1FCB, 'M', u'ή'), + (0x1FCC, 'M', u'ηι'), + (0x1FCD, '3', u' ̓̀'), + (0x1FCE, '3', u' ̓́'), + (0x1FCF, '3', u' ̓͂'), + (0x1FD0, 'V'), + (0x1FD3, 'M', u'ΐ'), + (0x1FD4, 'X'), + (0x1FD6, 'V'), + (0x1FD8, 'M', u'ῐ'), + (0x1FD9, 'M', u'ῑ'), + (0x1FDA, 'M', u'ὶ'), + (0x1FDB, 'M', u'ί'), + (0x1FDC, 'X'), + (0x1FDD, '3', u' ̔̀'), + (0x1FDE, '3', u' ̔́'), + (0x1FDF, '3', u' ̔͂'), + (0x1FE0, 'V'), + (0x1FE3, 'M', u'ΰ'), + (0x1FE4, 'V'), + (0x1FE8, 'M', u'ῠ'), + (0x1FE9, 'M', u'ῡ'), + (0x1FEA, 'M', u'ὺ'), + (0x1FEB, 'M', u'ύ'), + (0x1FEC, 'M', u'ῥ'), + (0x1FED, '3', u' ̈̀'), + (0x1FEE, '3', u' ̈́'), + (0x1FEF, '3', u'`'), + (0x1FF0, 'X'), + (0x1FF2, 'M', u'ὼι'), + (0x1FF3, 'M', u'ωι'), + (0x1FF4, 'M', u'ώι'), + (0x1FF5, 'X'), + (0x1FF6, 'V'), + (0x1FF7, 'M', u'ῶι'), + (0x1FF8, 'M', u'ὸ'), + (0x1FF9, 'M', u'ό'), + (0x1FFA, 'M', u'ὼ'), + (0x1FFB, 'M', u'ώ'), + (0x1FFC, 'M', u'ωι'), + (0x1FFD, '3', u' ́'), + (0x1FFE, '3', u' ̔'), + (0x1FFF, 'X'), + (0x2000, '3', u' '), + (0x200B, 'I'), + (0x200C, 'D', u''), + (0x200E, 'X'), + (0x2010, 'V'), + (0x2011, 'M', u'‐'), + (0x2012, 'V'), + (0x2017, '3', u' ̳'), + (0x2018, 'V'), + (0x2024, 'X'), + (0x2027, 'V'), + (0x2028, 'X'), + ] + +def _seg_21(): + return [ + (0x202F, '3', u' '), + (0x2030, 'V'), + (0x2033, 'M', u'′′'), + (0x2034, 'M', u'′′′'), + (0x2035, 'V'), + (0x2036, 'M', u'‵‵'), + (0x2037, 'M', u'‵‵‵'), + (0x2038, 'V'), + (0x203C, '3', u'!!'), + (0x203D, 'V'), + (0x203E, '3', u' ̅'), + (0x203F, 'V'), + (0x2047, '3', u'??'), + (0x2048, '3', u'?!'), + (0x2049, '3', u'!?'), + (0x204A, 'V'), + (0x2057, 'M', u'′′′′'), + (0x2058, 'V'), + (0x205F, '3', u' '), + (0x2060, 'I'), + (0x2061, 'X'), + (0x2064, 'I'), + (0x2065, 'X'), + (0x2070, 'M', u'0'), + (0x2071, 'M', u'i'), + (0x2072, 'X'), + (0x2074, 'M', u'4'), + (0x2075, 'M', u'5'), + (0x2076, 'M', u'6'), + (0x2077, 'M', u'7'), + (0x2078, 'M', u'8'), + (0x2079, 'M', u'9'), + (0x207A, '3', u'+'), + (0x207B, 'M', u'−'), + (0x207C, '3', u'='), + (0x207D, '3', u'('), + (0x207E, '3', u')'), + (0x207F, 'M', u'n'), + (0x2080, 'M', u'0'), + (0x2081, 'M', u'1'), + (0x2082, 'M', u'2'), + (0x2083, 'M', u'3'), + (0x2084, 'M', u'4'), + (0x2085, 'M', u'5'), + (0x2086, 'M', u'6'), + (0x2087, 'M', u'7'), + (0x2088, 'M', u'8'), + (0x2089, 'M', u'9'), + (0x208A, '3', u'+'), + (0x208B, 'M', u'−'), + (0x208C, '3', u'='), + (0x208D, '3', u'('), + (0x208E, '3', u')'), + (0x208F, 'X'), + (0x2090, 'M', u'a'), + (0x2091, 'M', u'e'), + (0x2092, 'M', u'o'), + (0x2093, 'M', u'x'), + (0x2094, 'M', u'ə'), + (0x2095, 'M', u'h'), + (0x2096, 'M', u'k'), + (0x2097, 'M', u'l'), + (0x2098, 'M', u'm'), + (0x2099, 'M', u'n'), + (0x209A, 'M', u'p'), + (0x209B, 'M', u's'), + (0x209C, 'M', u't'), + (0x209D, 'X'), + (0x20A0, 'V'), + (0x20A8, 'M', u'rs'), + (0x20A9, 'V'), + (0x20C0, 'X'), + (0x20D0, 'V'), + (0x20F1, 'X'), + (0x2100, '3', u'a/c'), + (0x2101, '3', u'a/s'), + (0x2102, 'M', u'c'), + (0x2103, 'M', u'°c'), + (0x2104, 'V'), + (0x2105, '3', u'c/o'), + (0x2106, '3', u'c/u'), + (0x2107, 'M', u'ɛ'), + (0x2108, 'V'), + (0x2109, 'M', u'°f'), + (0x210A, 'M', u'g'), + (0x210B, 'M', u'h'), + (0x210F, 'M', u'ħ'), + (0x2110, 'M', u'i'), + (0x2112, 'M', u'l'), + (0x2114, 'V'), + (0x2115, 'M', u'n'), + (0x2116, 'M', u'no'), + (0x2117, 'V'), + (0x2119, 'M', u'p'), + (0x211A, 'M', u'q'), + (0x211B, 'M', u'r'), + (0x211E, 'V'), + (0x2120, 'M', u'sm'), + (0x2121, 'M', u'tel'), + (0x2122, 'M', u'tm'), + ] + +def _seg_22(): + return [ + (0x2123, 'V'), + (0x2124, 'M', u'z'), + (0x2125, 'V'), + (0x2126, 'M', u'ω'), + (0x2127, 'V'), + (0x2128, 'M', u'z'), + (0x2129, 'V'), + (0x212A, 'M', u'k'), + (0x212B, 'M', u'å'), + (0x212C, 'M', u'b'), + (0x212D, 'M', u'c'), + (0x212E, 'V'), + (0x212F, 'M', u'e'), + (0x2131, 'M', u'f'), + (0x2132, 'X'), + (0x2133, 'M', u'm'), + (0x2134, 'M', u'o'), + (0x2135, 'M', u'א'), + (0x2136, 'M', u'ב'), + (0x2137, 'M', u'ג'), + (0x2138, 'M', u'ד'), + (0x2139, 'M', u'i'), + (0x213A, 'V'), + (0x213B, 'M', u'fax'), + (0x213C, 'M', u'π'), + (0x213D, 'M', u'γ'), + (0x213F, 'M', u'π'), + (0x2140, 'M', u'∑'), + (0x2141, 'V'), + (0x2145, 'M', u'd'), + (0x2147, 'M', u'e'), + (0x2148, 'M', u'i'), + (0x2149, 'M', u'j'), + (0x214A, 'V'), + (0x2150, 'M', u'1⁄7'), + (0x2151, 'M', u'1⁄9'), + (0x2152, 'M', u'1⁄10'), + (0x2153, 'M', u'1⁄3'), + (0x2154, 'M', u'2⁄3'), + (0x2155, 'M', u'1⁄5'), + (0x2156, 'M', u'2⁄5'), + (0x2157, 'M', u'3⁄5'), + (0x2158, 'M', u'4⁄5'), + (0x2159, 'M', u'1⁄6'), + (0x215A, 'M', u'5⁄6'), + (0x215B, 'M', u'1⁄8'), + (0x215C, 'M', u'3⁄8'), + (0x215D, 'M', u'5⁄8'), + (0x215E, 'M', u'7⁄8'), + (0x215F, 'M', u'1⁄'), + (0x2160, 'M', u'i'), + (0x2161, 'M', u'ii'), + (0x2162, 'M', u'iii'), + (0x2163, 'M', u'iv'), + (0x2164, 'M', u'v'), + (0x2165, 'M', u'vi'), + (0x2166, 'M', u'vii'), + (0x2167, 'M', u'viii'), + (0x2168, 'M', u'ix'), + (0x2169, 'M', u'x'), + (0x216A, 'M', u'xi'), + (0x216B, 'M', u'xii'), + (0x216C, 'M', u'l'), + (0x216D, 'M', u'c'), + (0x216E, 'M', u'd'), + (0x216F, 'M', u'm'), + (0x2170, 'M', u'i'), + (0x2171, 'M', u'ii'), + (0x2172, 'M', u'iii'), + (0x2173, 'M', u'iv'), + (0x2174, 'M', u'v'), + (0x2175, 'M', u'vi'), + (0x2176, 'M', u'vii'), + (0x2177, 'M', u'viii'), + (0x2178, 'M', u'ix'), + (0x2179, 'M', u'x'), + (0x217A, 'M', u'xi'), + (0x217B, 'M', u'xii'), + (0x217C, 'M', u'l'), + (0x217D, 'M', u'c'), + (0x217E, 'M', u'd'), + (0x217F, 'M', u'm'), + (0x2180, 'V'), + (0x2183, 'X'), + (0x2184, 'V'), + (0x2189, 'M', u'0⁄3'), + (0x218A, 'V'), + (0x218C, 'X'), + (0x2190, 'V'), + (0x222C, 'M', u'∫∫'), + (0x222D, 'M', u'∫∫∫'), + (0x222E, 'V'), + (0x222F, 'M', u'∮∮'), + (0x2230, 'M', u'∮∮∮'), + (0x2231, 'V'), + (0x2260, '3'), + (0x2261, 'V'), + (0x226E, '3'), + (0x2270, 'V'), + (0x2329, 'M', u'〈'), + ] + +def _seg_23(): + return [ + (0x232A, 'M', u'〉'), + (0x232B, 'V'), + (0x2427, 'X'), + (0x2440, 'V'), + (0x244B, 'X'), + (0x2460, 'M', u'1'), + (0x2461, 'M', u'2'), + (0x2462, 'M', u'3'), + (0x2463, 'M', u'4'), + (0x2464, 'M', u'5'), + (0x2465, 'M', u'6'), + (0x2466, 'M', u'7'), + (0x2467, 'M', u'8'), + (0x2468, 'M', u'9'), + (0x2469, 'M', u'10'), + (0x246A, 'M', u'11'), + (0x246B, 'M', u'12'), + (0x246C, 'M', u'13'), + (0x246D, 'M', u'14'), + (0x246E, 'M', u'15'), + (0x246F, 'M', u'16'), + (0x2470, 'M', u'17'), + (0x2471, 'M', u'18'), + (0x2472, 'M', u'19'), + (0x2473, 'M', u'20'), + (0x2474, '3', u'(1)'), + (0x2475, '3', u'(2)'), + (0x2476, '3', u'(3)'), + (0x2477, '3', u'(4)'), + (0x2478, '3', u'(5)'), + (0x2479, '3', u'(6)'), + (0x247A, '3', u'(7)'), + (0x247B, '3', u'(8)'), + (0x247C, '3', u'(9)'), + (0x247D, '3', u'(10)'), + (0x247E, '3', u'(11)'), + (0x247F, '3', u'(12)'), + (0x2480, '3', u'(13)'), + (0x2481, '3', u'(14)'), + (0x2482, '3', u'(15)'), + (0x2483, '3', u'(16)'), + (0x2484, '3', u'(17)'), + (0x2485, '3', u'(18)'), + (0x2486, '3', u'(19)'), + (0x2487, '3', u'(20)'), + (0x2488, 'X'), + (0x249C, '3', u'(a)'), + (0x249D, '3', u'(b)'), + (0x249E, '3', u'(c)'), + (0x249F, '3', u'(d)'), + (0x24A0, '3', u'(e)'), + (0x24A1, '3', u'(f)'), + (0x24A2, '3', u'(g)'), + (0x24A3, '3', u'(h)'), + (0x24A4, '3', u'(i)'), + (0x24A5, '3', u'(j)'), + (0x24A6, '3', u'(k)'), + (0x24A7, '3', u'(l)'), + (0x24A8, '3', u'(m)'), + (0x24A9, '3', u'(n)'), + (0x24AA, '3', u'(o)'), + (0x24AB, '3', u'(p)'), + (0x24AC, '3', u'(q)'), + (0x24AD, '3', u'(r)'), + (0x24AE, '3', u'(s)'), + (0x24AF, '3', u'(t)'), + (0x24B0, '3', u'(u)'), + (0x24B1, '3', u'(v)'), + (0x24B2, '3', u'(w)'), + (0x24B3, '3', u'(x)'), + (0x24B4, '3', u'(y)'), + (0x24B5, '3', u'(z)'), + (0x24B6, 'M', u'a'), + (0x24B7, 'M', u'b'), + (0x24B8, 'M', u'c'), + (0x24B9, 'M', u'd'), + (0x24BA, 'M', u'e'), + (0x24BB, 'M', u'f'), + (0x24BC, 'M', u'g'), + (0x24BD, 'M', u'h'), + (0x24BE, 'M', u'i'), + (0x24BF, 'M', u'j'), + (0x24C0, 'M', u'k'), + (0x24C1, 'M', u'l'), + (0x24C2, 'M', u'm'), + (0x24C3, 'M', u'n'), + (0x24C4, 'M', u'o'), + (0x24C5, 'M', u'p'), + (0x24C6, 'M', u'q'), + (0x24C7, 'M', u'r'), + (0x24C8, 'M', u's'), + (0x24C9, 'M', u't'), + (0x24CA, 'M', u'u'), + (0x24CB, 'M', u'v'), + (0x24CC, 'M', u'w'), + (0x24CD, 'M', u'x'), + (0x24CE, 'M', u'y'), + (0x24CF, 'M', u'z'), + (0x24D0, 'M', u'a'), + (0x24D1, 'M', u'b'), + ] + +def _seg_24(): + return [ + (0x24D2, 'M', u'c'), + (0x24D3, 'M', u'd'), + (0x24D4, 'M', u'e'), + (0x24D5, 'M', u'f'), + (0x24D6, 'M', u'g'), + (0x24D7, 'M', u'h'), + (0x24D8, 'M', u'i'), + (0x24D9, 'M', u'j'), + (0x24DA, 'M', u'k'), + (0x24DB, 'M', u'l'), + (0x24DC, 'M', u'm'), + (0x24DD, 'M', u'n'), + (0x24DE, 'M', u'o'), + (0x24DF, 'M', u'p'), + (0x24E0, 'M', u'q'), + (0x24E1, 'M', u'r'), + (0x24E2, 'M', u's'), + (0x24E3, 'M', u't'), + (0x24E4, 'M', u'u'), + (0x24E5, 'M', u'v'), + (0x24E6, 'M', u'w'), + (0x24E7, 'M', u'x'), + (0x24E8, 'M', u'y'), + (0x24E9, 'M', u'z'), + (0x24EA, 'M', u'0'), + (0x24EB, 'V'), + (0x2A0C, 'M', u'∫∫∫∫'), + (0x2A0D, 'V'), + (0x2A74, '3', u'::='), + (0x2A75, '3', u'=='), + (0x2A76, '3', u'==='), + (0x2A77, 'V'), + (0x2ADC, 'M', u'⫝̸'), + (0x2ADD, 'V'), + (0x2B74, 'X'), + (0x2B76, 'V'), + (0x2B96, 'X'), + (0x2B98, 'V'), + (0x2BBA, 'X'), + (0x2BBD, 'V'), + (0x2BC9, 'X'), + (0x2BCA, 'V'), + (0x2BD3, 'X'), + (0x2BEC, 'V'), + (0x2BF0, 'X'), + (0x2C00, 'M', u'ⰰ'), + (0x2C01, 'M', u'ⰱ'), + (0x2C02, 'M', u'ⰲ'), + (0x2C03, 'M', u'ⰳ'), + (0x2C04, 'M', u'ⰴ'), + (0x2C05, 'M', u'ⰵ'), + (0x2C06, 'M', u'ⰶ'), + (0x2C07, 'M', u'ⰷ'), + (0x2C08, 'M', u'ⰸ'), + (0x2C09, 'M', u'ⰹ'), + (0x2C0A, 'M', u'ⰺ'), + (0x2C0B, 'M', u'ⰻ'), + (0x2C0C, 'M', u'ⰼ'), + (0x2C0D, 'M', u'ⰽ'), + (0x2C0E, 'M', u'ⰾ'), + (0x2C0F, 'M', u'ⰿ'), + (0x2C10, 'M', u'ⱀ'), + (0x2C11, 'M', u'ⱁ'), + (0x2C12, 'M', u'ⱂ'), + (0x2C13, 'M', u'ⱃ'), + (0x2C14, 'M', u'ⱄ'), + (0x2C15, 'M', u'ⱅ'), + (0x2C16, 'M', u'ⱆ'), + (0x2C17, 'M', u'ⱇ'), + (0x2C18, 'M', u'ⱈ'), + (0x2C19, 'M', u'ⱉ'), + (0x2C1A, 'M', u'ⱊ'), + (0x2C1B, 'M', u'ⱋ'), + (0x2C1C, 'M', u'ⱌ'), + (0x2C1D, 'M', u'ⱍ'), + (0x2C1E, 'M', u'ⱎ'), + (0x2C1F, 'M', u'ⱏ'), + (0x2C20, 'M', u'ⱐ'), + (0x2C21, 'M', u'ⱑ'), + (0x2C22, 'M', u'ⱒ'), + (0x2C23, 'M', u'ⱓ'), + (0x2C24, 'M', u'ⱔ'), + (0x2C25, 'M', u'ⱕ'), + (0x2C26, 'M', u'ⱖ'), + (0x2C27, 'M', u'ⱗ'), + (0x2C28, 'M', u'ⱘ'), + (0x2C29, 'M', u'ⱙ'), + (0x2C2A, 'M', u'ⱚ'), + (0x2C2B, 'M', u'ⱛ'), + (0x2C2C, 'M', u'ⱜ'), + (0x2C2D, 'M', u'ⱝ'), + (0x2C2E, 'M', u'ⱞ'), + (0x2C2F, 'X'), + (0x2C30, 'V'), + (0x2C5F, 'X'), + (0x2C60, 'M', u'ⱡ'), + (0x2C61, 'V'), + (0x2C62, 'M', u'ɫ'), + (0x2C63, 'M', u'ᵽ'), + (0x2C64, 'M', u'ɽ'), + ] + +def _seg_25(): + return [ + (0x2C65, 'V'), + (0x2C67, 'M', u'ⱨ'), + (0x2C68, 'V'), + (0x2C69, 'M', u'ⱪ'), + (0x2C6A, 'V'), + (0x2C6B, 'M', u'ⱬ'), + (0x2C6C, 'V'), + (0x2C6D, 'M', u'ɑ'), + (0x2C6E, 'M', u'ɱ'), + (0x2C6F, 'M', u'ɐ'), + (0x2C70, 'M', u'ɒ'), + (0x2C71, 'V'), + (0x2C72, 'M', u'ⱳ'), + (0x2C73, 'V'), + (0x2C75, 'M', u'ⱶ'), + (0x2C76, 'V'), + (0x2C7C, 'M', u'j'), + (0x2C7D, 'M', u'v'), + (0x2C7E, 'M', u'ȿ'), + (0x2C7F, 'M', u'ɀ'), + (0x2C80, 'M', u'ⲁ'), + (0x2C81, 'V'), + (0x2C82, 'M', u'ⲃ'), + (0x2C83, 'V'), + (0x2C84, 'M', u'ⲅ'), + (0x2C85, 'V'), + (0x2C86, 'M', u'ⲇ'), + (0x2C87, 'V'), + (0x2C88, 'M', u'ⲉ'), + (0x2C89, 'V'), + (0x2C8A, 'M', u'ⲋ'), + (0x2C8B, 'V'), + (0x2C8C, 'M', u'ⲍ'), + (0x2C8D, 'V'), + (0x2C8E, 'M', u'ⲏ'), + (0x2C8F, 'V'), + (0x2C90, 'M', u'ⲑ'), + (0x2C91, 'V'), + (0x2C92, 'M', u'ⲓ'), + (0x2C93, 'V'), + (0x2C94, 'M', u'ⲕ'), + (0x2C95, 'V'), + (0x2C96, 'M', u'ⲗ'), + (0x2C97, 'V'), + (0x2C98, 'M', u'ⲙ'), + (0x2C99, 'V'), + (0x2C9A, 'M', u'ⲛ'), + (0x2C9B, 'V'), + (0x2C9C, 'M', u'ⲝ'), + (0x2C9D, 'V'), + (0x2C9E, 'M', u'ⲟ'), + (0x2C9F, 'V'), + (0x2CA0, 'M', u'ⲡ'), + (0x2CA1, 'V'), + (0x2CA2, 'M', u'ⲣ'), + (0x2CA3, 'V'), + (0x2CA4, 'M', u'ⲥ'), + (0x2CA5, 'V'), + (0x2CA6, 'M', u'ⲧ'), + (0x2CA7, 'V'), + (0x2CA8, 'M', u'ⲩ'), + (0x2CA9, 'V'), + (0x2CAA, 'M', u'ⲫ'), + (0x2CAB, 'V'), + (0x2CAC, 'M', u'ⲭ'), + (0x2CAD, 'V'), + (0x2CAE, 'M', u'ⲯ'), + (0x2CAF, 'V'), + (0x2CB0, 'M', u'ⲱ'), + (0x2CB1, 'V'), + (0x2CB2, 'M', u'ⲳ'), + (0x2CB3, 'V'), + (0x2CB4, 'M', u'ⲵ'), + (0x2CB5, 'V'), + (0x2CB6, 'M', u'ⲷ'), + (0x2CB7, 'V'), + (0x2CB8, 'M', u'ⲹ'), + (0x2CB9, 'V'), + (0x2CBA, 'M', u'ⲻ'), + (0x2CBB, 'V'), + (0x2CBC, 'M', u'ⲽ'), + (0x2CBD, 'V'), + (0x2CBE, 'M', u'ⲿ'), + (0x2CBF, 'V'), + (0x2CC0, 'M', u'ⳁ'), + (0x2CC1, 'V'), + (0x2CC2, 'M', u'ⳃ'), + (0x2CC3, 'V'), + (0x2CC4, 'M', u'ⳅ'), + (0x2CC5, 'V'), + (0x2CC6, 'M', u'ⳇ'), + (0x2CC7, 'V'), + (0x2CC8, 'M', u'ⳉ'), + (0x2CC9, 'V'), + (0x2CCA, 'M', u'ⳋ'), + (0x2CCB, 'V'), + (0x2CCC, 'M', u'ⳍ'), + (0x2CCD, 'V'), + (0x2CCE, 'M', u'ⳏ'), + (0x2CCF, 'V'), + ] + +def _seg_26(): + return [ + (0x2CD0, 'M', u'ⳑ'), + (0x2CD1, 'V'), + (0x2CD2, 'M', u'ⳓ'), + (0x2CD3, 'V'), + (0x2CD4, 'M', u'ⳕ'), + (0x2CD5, 'V'), + (0x2CD6, 'M', u'ⳗ'), + (0x2CD7, 'V'), + (0x2CD8, 'M', u'ⳙ'), + (0x2CD9, 'V'), + (0x2CDA, 'M', u'ⳛ'), + (0x2CDB, 'V'), + (0x2CDC, 'M', u'ⳝ'), + (0x2CDD, 'V'), + (0x2CDE, 'M', u'ⳟ'), + (0x2CDF, 'V'), + (0x2CE0, 'M', u'ⳡ'), + (0x2CE1, 'V'), + (0x2CE2, 'M', u'ⳣ'), + (0x2CE3, 'V'), + (0x2CEB, 'M', u'ⳬ'), + (0x2CEC, 'V'), + (0x2CED, 'M', u'ⳮ'), + (0x2CEE, 'V'), + (0x2CF2, 'M', u'ⳳ'), + (0x2CF3, 'V'), + (0x2CF4, 'X'), + (0x2CF9, 'V'), + (0x2D26, 'X'), + (0x2D27, 'V'), + (0x2D28, 'X'), + (0x2D2D, 'V'), + (0x2D2E, 'X'), + (0x2D30, 'V'), + (0x2D68, 'X'), + (0x2D6F, 'M', u'ⵡ'), + (0x2D70, 'V'), + (0x2D71, 'X'), + (0x2D7F, 'V'), + (0x2D97, 'X'), + (0x2DA0, 'V'), + (0x2DA7, 'X'), + (0x2DA8, 'V'), + (0x2DAF, 'X'), + (0x2DB0, 'V'), + (0x2DB7, 'X'), + (0x2DB8, 'V'), + (0x2DBF, 'X'), + (0x2DC0, 'V'), + (0x2DC7, 'X'), + (0x2DC8, 'V'), + (0x2DCF, 'X'), + (0x2DD0, 'V'), + (0x2DD7, 'X'), + (0x2DD8, 'V'), + (0x2DDF, 'X'), + (0x2DE0, 'V'), + (0x2E4A, 'X'), + (0x2E80, 'V'), + (0x2E9A, 'X'), + (0x2E9B, 'V'), + (0x2E9F, 'M', u'母'), + (0x2EA0, 'V'), + (0x2EF3, 'M', u'龟'), + (0x2EF4, 'X'), + (0x2F00, 'M', u'一'), + (0x2F01, 'M', u'丨'), + (0x2F02, 'M', u'丶'), + (0x2F03, 'M', u'丿'), + (0x2F04, 'M', u'乙'), + (0x2F05, 'M', u'亅'), + (0x2F06, 'M', u'二'), + (0x2F07, 'M', u'亠'), + (0x2F08, 'M', u'人'), + (0x2F09, 'M', u'儿'), + (0x2F0A, 'M', u'入'), + (0x2F0B, 'M', u'八'), + (0x2F0C, 'M', u'冂'), + (0x2F0D, 'M', u'冖'), + (0x2F0E, 'M', u'冫'), + (0x2F0F, 'M', u'几'), + (0x2F10, 'M', u'凵'), + (0x2F11, 'M', u'刀'), + (0x2F12, 'M', u'力'), + (0x2F13, 'M', u'勹'), + (0x2F14, 'M', u'匕'), + (0x2F15, 'M', u'匚'), + (0x2F16, 'M', u'匸'), + (0x2F17, 'M', u'十'), + (0x2F18, 'M', u'卜'), + (0x2F19, 'M', u'卩'), + (0x2F1A, 'M', u'厂'), + (0x2F1B, 'M', u'厶'), + (0x2F1C, 'M', u'又'), + (0x2F1D, 'M', u'口'), + (0x2F1E, 'M', u'囗'), + (0x2F1F, 'M', u'土'), + (0x2F20, 'M', u'士'), + (0x2F21, 'M', u'夂'), + (0x2F22, 'M', u'夊'), + ] + +def _seg_27(): + return [ + (0x2F23, 'M', u'夕'), + (0x2F24, 'M', u'大'), + (0x2F25, 'M', u'女'), + (0x2F26, 'M', u'子'), + (0x2F27, 'M', u'宀'), + (0x2F28, 'M', u'寸'), + (0x2F29, 'M', u'小'), + (0x2F2A, 'M', u'尢'), + (0x2F2B, 'M', u'尸'), + (0x2F2C, 'M', u'屮'), + (0x2F2D, 'M', u'山'), + (0x2F2E, 'M', u'巛'), + (0x2F2F, 'M', u'工'), + (0x2F30, 'M', u'己'), + (0x2F31, 'M', u'巾'), + (0x2F32, 'M', u'干'), + (0x2F33, 'M', u'幺'), + (0x2F34, 'M', u'广'), + (0x2F35, 'M', u'廴'), + (0x2F36, 'M', u'廾'), + (0x2F37, 'M', u'弋'), + (0x2F38, 'M', u'弓'), + (0x2F39, 'M', u'彐'), + (0x2F3A, 'M', u'彡'), + (0x2F3B, 'M', u'彳'), + (0x2F3C, 'M', u'心'), + (0x2F3D, 'M', u'戈'), + (0x2F3E, 'M', u'戶'), + (0x2F3F, 'M', u'手'), + (0x2F40, 'M', u'支'), + (0x2F41, 'M', u'攴'), + (0x2F42, 'M', u'文'), + (0x2F43, 'M', u'斗'), + (0x2F44, 'M', u'斤'), + (0x2F45, 'M', u'方'), + (0x2F46, 'M', u'无'), + (0x2F47, 'M', u'日'), + (0x2F48, 'M', u'曰'), + (0x2F49, 'M', u'月'), + (0x2F4A, 'M', u'木'), + (0x2F4B, 'M', u'欠'), + (0x2F4C, 'M', u'止'), + (0x2F4D, 'M', u'歹'), + (0x2F4E, 'M', u'殳'), + (0x2F4F, 'M', u'毋'), + (0x2F50, 'M', u'比'), + (0x2F51, 'M', u'毛'), + (0x2F52, 'M', u'氏'), + (0x2F53, 'M', u'气'), + (0x2F54, 'M', u'水'), + (0x2F55, 'M', u'火'), + (0x2F56, 'M', u'爪'), + (0x2F57, 'M', u'父'), + (0x2F58, 'M', u'爻'), + (0x2F59, 'M', u'爿'), + (0x2F5A, 'M', u'片'), + (0x2F5B, 'M', u'牙'), + (0x2F5C, 'M', u'牛'), + (0x2F5D, 'M', u'犬'), + (0x2F5E, 'M', u'玄'), + (0x2F5F, 'M', u'玉'), + (0x2F60, 'M', u'瓜'), + (0x2F61, 'M', u'瓦'), + (0x2F62, 'M', u'甘'), + (0x2F63, 'M', u'生'), + (0x2F64, 'M', u'用'), + (0x2F65, 'M', u'田'), + (0x2F66, 'M', u'疋'), + (0x2F67, 'M', u'疒'), + (0x2F68, 'M', u'癶'), + (0x2F69, 'M', u'白'), + (0x2F6A, 'M', u'皮'), + (0x2F6B, 'M', u'皿'), + (0x2F6C, 'M', u'目'), + (0x2F6D, 'M', u'矛'), + (0x2F6E, 'M', u'矢'), + (0x2F6F, 'M', u'石'), + (0x2F70, 'M', u'示'), + (0x2F71, 'M', u'禸'), + (0x2F72, 'M', u'禾'), + (0x2F73, 'M', u'穴'), + (0x2F74, 'M', u'立'), + (0x2F75, 'M', u'竹'), + (0x2F76, 'M', u'米'), + (0x2F77, 'M', u'糸'), + (0x2F78, 'M', u'缶'), + (0x2F79, 'M', u'网'), + (0x2F7A, 'M', u'羊'), + (0x2F7B, 'M', u'羽'), + (0x2F7C, 'M', u'老'), + (0x2F7D, 'M', u'而'), + (0x2F7E, 'M', u'耒'), + (0x2F7F, 'M', u'耳'), + (0x2F80, 'M', u'聿'), + (0x2F81, 'M', u'肉'), + (0x2F82, 'M', u'臣'), + (0x2F83, 'M', u'自'), + (0x2F84, 'M', u'至'), + (0x2F85, 'M', u'臼'), + (0x2F86, 'M', u'舌'), + ] + +def _seg_28(): + return [ + (0x2F87, 'M', u'舛'), + (0x2F88, 'M', u'舟'), + (0x2F89, 'M', u'艮'), + (0x2F8A, 'M', u'色'), + (0x2F8B, 'M', u'艸'), + (0x2F8C, 'M', u'虍'), + (0x2F8D, 'M', u'虫'), + (0x2F8E, 'M', u'血'), + (0x2F8F, 'M', u'行'), + (0x2F90, 'M', u'衣'), + (0x2F91, 'M', u'襾'), + (0x2F92, 'M', u'見'), + (0x2F93, 'M', u'角'), + (0x2F94, 'M', u'言'), + (0x2F95, 'M', u'谷'), + (0x2F96, 'M', u'豆'), + (0x2F97, 'M', u'豕'), + (0x2F98, 'M', u'豸'), + (0x2F99, 'M', u'貝'), + (0x2F9A, 'M', u'赤'), + (0x2F9B, 'M', u'走'), + (0x2F9C, 'M', u'足'), + (0x2F9D, 'M', u'身'), + (0x2F9E, 'M', u'車'), + (0x2F9F, 'M', u'辛'), + (0x2FA0, 'M', u'辰'), + (0x2FA1, 'M', u'辵'), + (0x2FA2, 'M', u'邑'), + (0x2FA3, 'M', u'酉'), + (0x2FA4, 'M', u'釆'), + (0x2FA5, 'M', u'里'), + (0x2FA6, 'M', u'金'), + (0x2FA7, 'M', u'長'), + (0x2FA8, 'M', u'門'), + (0x2FA9, 'M', u'阜'), + (0x2FAA, 'M', u'隶'), + (0x2FAB, 'M', u'隹'), + (0x2FAC, 'M', u'雨'), + (0x2FAD, 'M', u'靑'), + (0x2FAE, 'M', u'非'), + (0x2FAF, 'M', u'面'), + (0x2FB0, 'M', u'革'), + (0x2FB1, 'M', u'韋'), + (0x2FB2, 'M', u'韭'), + (0x2FB3, 'M', u'音'), + (0x2FB4, 'M', u'頁'), + (0x2FB5, 'M', u'風'), + (0x2FB6, 'M', u'飛'), + (0x2FB7, 'M', u'食'), + (0x2FB8, 'M', u'首'), + (0x2FB9, 'M', u'香'), + (0x2FBA, 'M', u'馬'), + (0x2FBB, 'M', u'骨'), + (0x2FBC, 'M', u'高'), + (0x2FBD, 'M', u'髟'), + (0x2FBE, 'M', u'鬥'), + (0x2FBF, 'M', u'鬯'), + (0x2FC0, 'M', u'鬲'), + (0x2FC1, 'M', u'鬼'), + (0x2FC2, 'M', u'魚'), + (0x2FC3, 'M', u'鳥'), + (0x2FC4, 'M', u'鹵'), + (0x2FC5, 'M', u'鹿'), + (0x2FC6, 'M', u'麥'), + (0x2FC7, 'M', u'麻'), + (0x2FC8, 'M', u'黃'), + (0x2FC9, 'M', u'黍'), + (0x2FCA, 'M', u'黑'), + (0x2FCB, 'M', u'黹'), + (0x2FCC, 'M', u'黽'), + (0x2FCD, 'M', u'鼎'), + (0x2FCE, 'M', u'鼓'), + (0x2FCF, 'M', u'鼠'), + (0x2FD0, 'M', u'鼻'), + (0x2FD1, 'M', u'齊'), + (0x2FD2, 'M', u'齒'), + (0x2FD3, 'M', u'龍'), + (0x2FD4, 'M', u'龜'), + (0x2FD5, 'M', u'龠'), + (0x2FD6, 'X'), + (0x3000, '3', u' '), + (0x3001, 'V'), + (0x3002, 'M', u'.'), + (0x3003, 'V'), + (0x3036, 'M', u'〒'), + (0x3037, 'V'), + (0x3038, 'M', u'十'), + (0x3039, 'M', u'卄'), + (0x303A, 'M', u'卅'), + (0x303B, 'V'), + (0x3040, 'X'), + (0x3041, 'V'), + (0x3097, 'X'), + (0x3099, 'V'), + (0x309B, '3', u' ゙'), + (0x309C, '3', u' ゚'), + (0x309D, 'V'), + (0x309F, 'M', u'より'), + (0x30A0, 'V'), + (0x30FF, 'M', u'コト'), + ] + +def _seg_29(): + return [ + (0x3100, 'X'), + (0x3105, 'V'), + (0x312F, 'X'), + (0x3131, 'M', u'ᄀ'), + (0x3132, 'M', u'ᄁ'), + (0x3133, 'M', u'ᆪ'), + (0x3134, 'M', u'ᄂ'), + (0x3135, 'M', u'ᆬ'), + (0x3136, 'M', u'ᆭ'), + (0x3137, 'M', u'ᄃ'), + (0x3138, 'M', u'ᄄ'), + (0x3139, 'M', u'ᄅ'), + (0x313A, 'M', u'ᆰ'), + (0x313B, 'M', u'ᆱ'), + (0x313C, 'M', u'ᆲ'), + (0x313D, 'M', u'ᆳ'), + (0x313E, 'M', u'ᆴ'), + (0x313F, 'M', u'ᆵ'), + (0x3140, 'M', u'ᄚ'), + (0x3141, 'M', u'ᄆ'), + (0x3142, 'M', u'ᄇ'), + (0x3143, 'M', u'ᄈ'), + (0x3144, 'M', u'ᄡ'), + (0x3145, 'M', u'ᄉ'), + (0x3146, 'M', u'ᄊ'), + (0x3147, 'M', u'ᄋ'), + (0x3148, 'M', u'ᄌ'), + (0x3149, 'M', u'ᄍ'), + (0x314A, 'M', u'ᄎ'), + (0x314B, 'M', u'ᄏ'), + (0x314C, 'M', u'ᄐ'), + (0x314D, 'M', u'ᄑ'), + (0x314E, 'M', u'ᄒ'), + (0x314F, 'M', u'ᅡ'), + (0x3150, 'M', u'ᅢ'), + (0x3151, 'M', u'ᅣ'), + (0x3152, 'M', u'ᅤ'), + (0x3153, 'M', u'ᅥ'), + (0x3154, 'M', u'ᅦ'), + (0x3155, 'M', u'ᅧ'), + (0x3156, 'M', u'ᅨ'), + (0x3157, 'M', u'ᅩ'), + (0x3158, 'M', u'ᅪ'), + (0x3159, 'M', u'ᅫ'), + (0x315A, 'M', u'ᅬ'), + (0x315B, 'M', u'ᅭ'), + (0x315C, 'M', u'ᅮ'), + (0x315D, 'M', u'ᅯ'), + (0x315E, 'M', u'ᅰ'), + (0x315F, 'M', u'ᅱ'), + (0x3160, 'M', u'ᅲ'), + (0x3161, 'M', u'ᅳ'), + (0x3162, 'M', u'ᅴ'), + (0x3163, 'M', u'ᅵ'), + (0x3164, 'X'), + (0x3165, 'M', u'ᄔ'), + (0x3166, 'M', u'ᄕ'), + (0x3167, 'M', u'ᇇ'), + (0x3168, 'M', u'ᇈ'), + (0x3169, 'M', u'ᇌ'), + (0x316A, 'M', u'ᇎ'), + (0x316B, 'M', u'ᇓ'), + (0x316C, 'M', u'ᇗ'), + (0x316D, 'M', u'ᇙ'), + (0x316E, 'M', u'ᄜ'), + (0x316F, 'M', u'ᇝ'), + (0x3170, 'M', u'ᇟ'), + (0x3171, 'M', u'ᄝ'), + (0x3172, 'M', u'ᄞ'), + (0x3173, 'M', u'ᄠ'), + (0x3174, 'M', u'ᄢ'), + (0x3175, 'M', u'ᄣ'), + (0x3176, 'M', u'ᄧ'), + (0x3177, 'M', u'ᄩ'), + (0x3178, 'M', u'ᄫ'), + (0x3179, 'M', u'ᄬ'), + (0x317A, 'M', u'ᄭ'), + (0x317B, 'M', u'ᄮ'), + (0x317C, 'M', u'ᄯ'), + (0x317D, 'M', u'ᄲ'), + (0x317E, 'M', u'ᄶ'), + (0x317F, 'M', u'ᅀ'), + (0x3180, 'M', u'ᅇ'), + (0x3181, 'M', u'ᅌ'), + (0x3182, 'M', u'ᇱ'), + (0x3183, 'M', u'ᇲ'), + (0x3184, 'M', u'ᅗ'), + (0x3185, 'M', u'ᅘ'), + (0x3186, 'M', u'ᅙ'), + (0x3187, 'M', u'ᆄ'), + (0x3188, 'M', u'ᆅ'), + (0x3189, 'M', u'ᆈ'), + (0x318A, 'M', u'ᆑ'), + (0x318B, 'M', u'ᆒ'), + (0x318C, 'M', u'ᆔ'), + (0x318D, 'M', u'ᆞ'), + (0x318E, 'M', u'ᆡ'), + (0x318F, 'X'), + (0x3190, 'V'), + (0x3192, 'M', u'一'), + ] + +def _seg_30(): + return [ + (0x3193, 'M', u'二'), + (0x3194, 'M', u'三'), + (0x3195, 'M', u'四'), + (0x3196, 'M', u'上'), + (0x3197, 'M', u'中'), + (0x3198, 'M', u'下'), + (0x3199, 'M', u'甲'), + (0x319A, 'M', u'乙'), + (0x319B, 'M', u'丙'), + (0x319C, 'M', u'丁'), + (0x319D, 'M', u'天'), + (0x319E, 'M', u'地'), + (0x319F, 'M', u'人'), + (0x31A0, 'V'), + (0x31BB, 'X'), + (0x31C0, 'V'), + (0x31E4, 'X'), + (0x31F0, 'V'), + (0x3200, '3', u'(ᄀ)'), + (0x3201, '3', u'(ᄂ)'), + (0x3202, '3', u'(ᄃ)'), + (0x3203, '3', u'(ᄅ)'), + (0x3204, '3', u'(ᄆ)'), + (0x3205, '3', u'(ᄇ)'), + (0x3206, '3', u'(ᄉ)'), + (0x3207, '3', u'(ᄋ)'), + (0x3208, '3', u'(ᄌ)'), + (0x3209, '3', u'(ᄎ)'), + (0x320A, '3', u'(ᄏ)'), + (0x320B, '3', u'(ᄐ)'), + (0x320C, '3', u'(ᄑ)'), + (0x320D, '3', u'(ᄒ)'), + (0x320E, '3', u'(가)'), + (0x320F, '3', u'(나)'), + (0x3210, '3', u'(다)'), + (0x3211, '3', u'(라)'), + (0x3212, '3', u'(마)'), + (0x3213, '3', u'(바)'), + (0x3214, '3', u'(사)'), + (0x3215, '3', u'(아)'), + (0x3216, '3', u'(자)'), + (0x3217, '3', u'(차)'), + (0x3218, '3', u'(카)'), + (0x3219, '3', u'(타)'), + (0x321A, '3', u'(파)'), + (0x321B, '3', u'(하)'), + (0x321C, '3', u'(주)'), + (0x321D, '3', u'(오전)'), + (0x321E, '3', u'(오후)'), + (0x321F, 'X'), + (0x3220, '3', u'(一)'), + (0x3221, '3', u'(二)'), + (0x3222, '3', u'(三)'), + (0x3223, '3', u'(四)'), + (0x3224, '3', u'(五)'), + (0x3225, '3', u'(六)'), + (0x3226, '3', u'(七)'), + (0x3227, '3', u'(八)'), + (0x3228, '3', u'(九)'), + (0x3229, '3', u'(十)'), + (0x322A, '3', u'(月)'), + (0x322B, '3', u'(火)'), + (0x322C, '3', u'(水)'), + (0x322D, '3', u'(木)'), + (0x322E, '3', u'(金)'), + (0x322F, '3', u'(土)'), + (0x3230, '3', u'(日)'), + (0x3231, '3', u'(株)'), + (0x3232, '3', u'(有)'), + (0x3233, '3', u'(社)'), + (0x3234, '3', u'(名)'), + (0x3235, '3', u'(特)'), + (0x3236, '3', u'(財)'), + (0x3237, '3', u'(祝)'), + (0x3238, '3', u'(労)'), + (0x3239, '3', u'(代)'), + (0x323A, '3', u'(呼)'), + (0x323B, '3', u'(学)'), + (0x323C, '3', u'(監)'), + (0x323D, '3', u'(企)'), + (0x323E, '3', u'(資)'), + (0x323F, '3', u'(協)'), + (0x3240, '3', u'(祭)'), + (0x3241, '3', u'(休)'), + (0x3242, '3', u'(自)'), + (0x3243, '3', u'(至)'), + (0x3244, 'M', u'問'), + (0x3245, 'M', u'幼'), + (0x3246, 'M', u'文'), + (0x3247, 'M', u'箏'), + (0x3248, 'V'), + (0x3250, 'M', u'pte'), + (0x3251, 'M', u'21'), + (0x3252, 'M', u'22'), + (0x3253, 'M', u'23'), + (0x3254, 'M', u'24'), + (0x3255, 'M', u'25'), + (0x3256, 'M', u'26'), + (0x3257, 'M', u'27'), + (0x3258, 'M', u'28'), + ] + +def _seg_31(): + return [ + (0x3259, 'M', u'29'), + (0x325A, 'M', u'30'), + (0x325B, 'M', u'31'), + (0x325C, 'M', u'32'), + (0x325D, 'M', u'33'), + (0x325E, 'M', u'34'), + (0x325F, 'M', u'35'), + (0x3260, 'M', u'ᄀ'), + (0x3261, 'M', u'ᄂ'), + (0x3262, 'M', u'ᄃ'), + (0x3263, 'M', u'ᄅ'), + (0x3264, 'M', u'ᄆ'), + (0x3265, 'M', u'ᄇ'), + (0x3266, 'M', u'ᄉ'), + (0x3267, 'M', u'ᄋ'), + (0x3268, 'M', u'ᄌ'), + (0x3269, 'M', u'ᄎ'), + (0x326A, 'M', u'ᄏ'), + (0x326B, 'M', u'ᄐ'), + (0x326C, 'M', u'ᄑ'), + (0x326D, 'M', u'ᄒ'), + (0x326E, 'M', u'가'), + (0x326F, 'M', u'나'), + (0x3270, 'M', u'다'), + (0x3271, 'M', u'라'), + (0x3272, 'M', u'마'), + (0x3273, 'M', u'바'), + (0x3274, 'M', u'사'), + (0x3275, 'M', u'아'), + (0x3276, 'M', u'자'), + (0x3277, 'M', u'차'), + (0x3278, 'M', u'카'), + (0x3279, 'M', u'타'), + (0x327A, 'M', u'파'), + (0x327B, 'M', u'하'), + (0x327C, 'M', u'참고'), + (0x327D, 'M', u'주의'), + (0x327E, 'M', u'우'), + (0x327F, 'V'), + (0x3280, 'M', u'一'), + (0x3281, 'M', u'二'), + (0x3282, 'M', u'三'), + (0x3283, 'M', u'四'), + (0x3284, 'M', u'五'), + (0x3285, 'M', u'六'), + (0x3286, 'M', u'七'), + (0x3287, 'M', u'八'), + (0x3288, 'M', u'九'), + (0x3289, 'M', u'十'), + (0x328A, 'M', u'月'), + (0x328B, 'M', u'火'), + (0x328C, 'M', u'水'), + (0x328D, 'M', u'木'), + (0x328E, 'M', u'金'), + (0x328F, 'M', u'土'), + (0x3290, 'M', u'日'), + (0x3291, 'M', u'株'), + (0x3292, 'M', u'有'), + (0x3293, 'M', u'社'), + (0x3294, 'M', u'名'), + (0x3295, 'M', u'特'), + (0x3296, 'M', u'財'), + (0x3297, 'M', u'祝'), + (0x3298, 'M', u'労'), + (0x3299, 'M', u'秘'), + (0x329A, 'M', u'男'), + (0x329B, 'M', u'女'), + (0x329C, 'M', u'適'), + (0x329D, 'M', u'優'), + (0x329E, 'M', u'印'), + (0x329F, 'M', u'注'), + (0x32A0, 'M', u'項'), + (0x32A1, 'M', u'休'), + (0x32A2, 'M', u'写'), + (0x32A3, 'M', u'正'), + (0x32A4, 'M', u'上'), + (0x32A5, 'M', u'中'), + (0x32A6, 'M', u'下'), + (0x32A7, 'M', u'左'), + (0x32A8, 'M', u'右'), + (0x32A9, 'M', u'医'), + (0x32AA, 'M', u'宗'), + (0x32AB, 'M', u'学'), + (0x32AC, 'M', u'監'), + (0x32AD, 'M', u'企'), + (0x32AE, 'M', u'資'), + (0x32AF, 'M', u'協'), + (0x32B0, 'M', u'夜'), + (0x32B1, 'M', u'36'), + (0x32B2, 'M', u'37'), + (0x32B3, 'M', u'38'), + (0x32B4, 'M', u'39'), + (0x32B5, 'M', u'40'), + (0x32B6, 'M', u'41'), + (0x32B7, 'M', u'42'), + (0x32B8, 'M', u'43'), + (0x32B9, 'M', u'44'), + (0x32BA, 'M', u'45'), + (0x32BB, 'M', u'46'), + (0x32BC, 'M', u'47'), + ] + +def _seg_32(): + return [ + (0x32BD, 'M', u'48'), + (0x32BE, 'M', u'49'), + (0x32BF, 'M', u'50'), + (0x32C0, 'M', u'1月'), + (0x32C1, 'M', u'2月'), + (0x32C2, 'M', u'3月'), + (0x32C3, 'M', u'4月'), + (0x32C4, 'M', u'5月'), + (0x32C5, 'M', u'6月'), + (0x32C6, 'M', u'7月'), + (0x32C7, 'M', u'8月'), + (0x32C8, 'M', u'9月'), + (0x32C9, 'M', u'10月'), + (0x32CA, 'M', u'11月'), + (0x32CB, 'M', u'12月'), + (0x32CC, 'M', u'hg'), + (0x32CD, 'M', u'erg'), + (0x32CE, 'M', u'ev'), + (0x32CF, 'M', u'ltd'), + (0x32D0, 'M', u'ア'), + (0x32D1, 'M', u'イ'), + (0x32D2, 'M', u'ウ'), + (0x32D3, 'M', u'エ'), + (0x32D4, 'M', u'オ'), + (0x32D5, 'M', u'カ'), + (0x32D6, 'M', u'キ'), + (0x32D7, 'M', u'ク'), + (0x32D8, 'M', u'ケ'), + (0x32D9, 'M', u'コ'), + (0x32DA, 'M', u'サ'), + (0x32DB, 'M', u'シ'), + (0x32DC, 'M', u'ス'), + (0x32DD, 'M', u'セ'), + (0x32DE, 'M', u'ソ'), + (0x32DF, 'M', u'タ'), + (0x32E0, 'M', u'チ'), + (0x32E1, 'M', u'ツ'), + (0x32E2, 'M', u'テ'), + (0x32E3, 'M', u'ト'), + (0x32E4, 'M', u'ナ'), + (0x32E5, 'M', u'ニ'), + (0x32E6, 'M', u'ヌ'), + (0x32E7, 'M', u'ネ'), + (0x32E8, 'M', u'ノ'), + (0x32E9, 'M', u'ハ'), + (0x32EA, 'M', u'ヒ'), + (0x32EB, 'M', u'フ'), + (0x32EC, 'M', u'ヘ'), + (0x32ED, 'M', u'ホ'), + (0x32EE, 'M', u'マ'), + (0x32EF, 'M', u'ミ'), + (0x32F0, 'M', u'ム'), + (0x32F1, 'M', u'メ'), + (0x32F2, 'M', u'モ'), + (0x32F3, 'M', u'ヤ'), + (0x32F4, 'M', u'ユ'), + (0x32F5, 'M', u'ヨ'), + (0x32F6, 'M', u'ラ'), + (0x32F7, 'M', u'リ'), + (0x32F8, 'M', u'ル'), + (0x32F9, 'M', u'レ'), + (0x32FA, 'M', u'ロ'), + (0x32FB, 'M', u'ワ'), + (0x32FC, 'M', u'ヰ'), + (0x32FD, 'M', u'ヱ'), + (0x32FE, 'M', u'ヲ'), + (0x32FF, 'X'), + (0x3300, 'M', u'アパート'), + (0x3301, 'M', u'アルファ'), + (0x3302, 'M', u'アンペア'), + (0x3303, 'M', u'アール'), + (0x3304, 'M', u'イニング'), + (0x3305, 'M', u'インチ'), + (0x3306, 'M', u'ウォン'), + (0x3307, 'M', u'エスクード'), + (0x3308, 'M', u'エーカー'), + (0x3309, 'M', u'オンス'), + (0x330A, 'M', u'オーム'), + (0x330B, 'M', u'カイリ'), + (0x330C, 'M', u'カラット'), + (0x330D, 'M', u'カロリー'), + (0x330E, 'M', u'ガロン'), + (0x330F, 'M', u'ガンマ'), + (0x3310, 'M', u'ギガ'), + (0x3311, 'M', u'ギニー'), + (0x3312, 'M', u'キュリー'), + (0x3313, 'M', u'ギルダー'), + (0x3314, 'M', u'キロ'), + (0x3315, 'M', u'キログラム'), + (0x3316, 'M', u'キロメートル'), + (0x3317, 'M', u'キロワット'), + (0x3318, 'M', u'グラム'), + (0x3319, 'M', u'グラムトン'), + (0x331A, 'M', u'クルゼイロ'), + (0x331B, 'M', u'クローネ'), + (0x331C, 'M', u'ケース'), + (0x331D, 'M', u'コルナ'), + (0x331E, 'M', u'コーポ'), + (0x331F, 'M', u'サイクル'), + (0x3320, 'M', u'サンチーム'), + ] + +def _seg_33(): + return [ + (0x3321, 'M', u'シリング'), + (0x3322, 'M', u'センチ'), + (0x3323, 'M', u'セント'), + (0x3324, 'M', u'ダース'), + (0x3325, 'M', u'デシ'), + (0x3326, 'M', u'ドル'), + (0x3327, 'M', u'トン'), + (0x3328, 'M', u'ナノ'), + (0x3329, 'M', u'ノット'), + (0x332A, 'M', u'ハイツ'), + (0x332B, 'M', u'パーセント'), + (0x332C, 'M', u'パーツ'), + (0x332D, 'M', u'バーレル'), + (0x332E, 'M', u'ピアストル'), + (0x332F, 'M', u'ピクル'), + (0x3330, 'M', u'ピコ'), + (0x3331, 'M', u'ビル'), + (0x3332, 'M', u'ファラッド'), + (0x3333, 'M', u'フィート'), + (0x3334, 'M', u'ブッシェル'), + (0x3335, 'M', u'フラン'), + (0x3336, 'M', u'ヘクタール'), + (0x3337, 'M', u'ペソ'), + (0x3338, 'M', u'ペニヒ'), + (0x3339, 'M', u'ヘルツ'), + (0x333A, 'M', u'ペンス'), + (0x333B, 'M', u'ページ'), + (0x333C, 'M', u'ベータ'), + (0x333D, 'M', u'ポイント'), + (0x333E, 'M', u'ボルト'), + (0x333F, 'M', u'ホン'), + (0x3340, 'M', u'ポンド'), + (0x3341, 'M', u'ホール'), + (0x3342, 'M', u'ホーン'), + (0x3343, 'M', u'マイクロ'), + (0x3344, 'M', u'マイル'), + (0x3345, 'M', u'マッハ'), + (0x3346, 'M', u'マルク'), + (0x3347, 'M', u'マンション'), + (0x3348, 'M', u'ミクロン'), + (0x3349, 'M', u'ミリ'), + (0x334A, 'M', u'ミリバール'), + (0x334B, 'M', u'メガ'), + (0x334C, 'M', u'メガトン'), + (0x334D, 'M', u'メートル'), + (0x334E, 'M', u'ヤード'), + (0x334F, 'M', u'ヤール'), + (0x3350, 'M', u'ユアン'), + (0x3351, 'M', u'リットル'), + (0x3352, 'M', u'リラ'), + (0x3353, 'M', u'ルピー'), + (0x3354, 'M', u'ルーブル'), + (0x3355, 'M', u'レム'), + (0x3356, 'M', u'レントゲン'), + (0x3357, 'M', u'ワット'), + (0x3358, 'M', u'0点'), + (0x3359, 'M', u'1点'), + (0x335A, 'M', u'2点'), + (0x335B, 'M', u'3点'), + (0x335C, 'M', u'4点'), + (0x335D, 'M', u'5点'), + (0x335E, 'M', u'6点'), + (0x335F, 'M', u'7点'), + (0x3360, 'M', u'8点'), + (0x3361, 'M', u'9点'), + (0x3362, 'M', u'10点'), + (0x3363, 'M', u'11点'), + (0x3364, 'M', u'12点'), + (0x3365, 'M', u'13点'), + (0x3366, 'M', u'14点'), + (0x3367, 'M', u'15点'), + (0x3368, 'M', u'16点'), + (0x3369, 'M', u'17点'), + (0x336A, 'M', u'18点'), + (0x336B, 'M', u'19点'), + (0x336C, 'M', u'20点'), + (0x336D, 'M', u'21点'), + (0x336E, 'M', u'22点'), + (0x336F, 'M', u'23点'), + (0x3370, 'M', u'24点'), + (0x3371, 'M', u'hpa'), + (0x3372, 'M', u'da'), + (0x3373, 'M', u'au'), + (0x3374, 'M', u'bar'), + (0x3375, 'M', u'ov'), + (0x3376, 'M', u'pc'), + (0x3377, 'M', u'dm'), + (0x3378, 'M', u'dm2'), + (0x3379, 'M', u'dm3'), + (0x337A, 'M', u'iu'), + (0x337B, 'M', u'平成'), + (0x337C, 'M', u'昭和'), + (0x337D, 'M', u'大正'), + (0x337E, 'M', u'明治'), + (0x337F, 'M', u'株式会社'), + (0x3380, 'M', u'pa'), + (0x3381, 'M', u'na'), + (0x3382, 'M', u'μa'), + (0x3383, 'M', u'ma'), + (0x3384, 'M', u'ka'), + ] + +def _seg_34(): + return [ + (0x3385, 'M', u'kb'), + (0x3386, 'M', u'mb'), + (0x3387, 'M', u'gb'), + (0x3388, 'M', u'cal'), + (0x3389, 'M', u'kcal'), + (0x338A, 'M', u'pf'), + (0x338B, 'M', u'nf'), + (0x338C, 'M', u'μf'), + (0x338D, 'M', u'μg'), + (0x338E, 'M', u'mg'), + (0x338F, 'M', u'kg'), + (0x3390, 'M', u'hz'), + (0x3391, 'M', u'khz'), + (0x3392, 'M', u'mhz'), + (0x3393, 'M', u'ghz'), + (0x3394, 'M', u'thz'), + (0x3395, 'M', u'μl'), + (0x3396, 'M', u'ml'), + (0x3397, 'M', u'dl'), + (0x3398, 'M', u'kl'), + (0x3399, 'M', u'fm'), + (0x339A, 'M', u'nm'), + (0x339B, 'M', u'μm'), + (0x339C, 'M', u'mm'), + (0x339D, 'M', u'cm'), + (0x339E, 'M', u'km'), + (0x339F, 'M', u'mm2'), + (0x33A0, 'M', u'cm2'), + (0x33A1, 'M', u'm2'), + (0x33A2, 'M', u'km2'), + (0x33A3, 'M', u'mm3'), + (0x33A4, 'M', u'cm3'), + (0x33A5, 'M', u'm3'), + (0x33A6, 'M', u'km3'), + (0x33A7, 'M', u'm∕s'), + (0x33A8, 'M', u'm∕s2'), + (0x33A9, 'M', u'pa'), + (0x33AA, 'M', u'kpa'), + (0x33AB, 'M', u'mpa'), + (0x33AC, 'M', u'gpa'), + (0x33AD, 'M', u'rad'), + (0x33AE, 'M', u'rad∕s'), + (0x33AF, 'M', u'rad∕s2'), + (0x33B0, 'M', u'ps'), + (0x33B1, 'M', u'ns'), + (0x33B2, 'M', u'μs'), + (0x33B3, 'M', u'ms'), + (0x33B4, 'M', u'pv'), + (0x33B5, 'M', u'nv'), + (0x33B6, 'M', u'μv'), + (0x33B7, 'M', u'mv'), + (0x33B8, 'M', u'kv'), + (0x33B9, 'M', u'mv'), + (0x33BA, 'M', u'pw'), + (0x33BB, 'M', u'nw'), + (0x33BC, 'M', u'μw'), + (0x33BD, 'M', u'mw'), + (0x33BE, 'M', u'kw'), + (0x33BF, 'M', u'mw'), + (0x33C0, 'M', u'kω'), + (0x33C1, 'M', u'mω'), + (0x33C2, 'X'), + (0x33C3, 'M', u'bq'), + (0x33C4, 'M', u'cc'), + (0x33C5, 'M', u'cd'), + (0x33C6, 'M', u'c∕kg'), + (0x33C7, 'X'), + (0x33C8, 'M', u'db'), + (0x33C9, 'M', u'gy'), + (0x33CA, 'M', u'ha'), + (0x33CB, 'M', u'hp'), + (0x33CC, 'M', u'in'), + (0x33CD, 'M', u'kk'), + (0x33CE, 'M', u'km'), + (0x33CF, 'M', u'kt'), + (0x33D0, 'M', u'lm'), + (0x33D1, 'M', u'ln'), + (0x33D2, 'M', u'log'), + (0x33D3, 'M', u'lx'), + (0x33D4, 'M', u'mb'), + (0x33D5, 'M', u'mil'), + (0x33D6, 'M', u'mol'), + (0x33D7, 'M', u'ph'), + (0x33D8, 'X'), + (0x33D9, 'M', u'ppm'), + (0x33DA, 'M', u'pr'), + (0x33DB, 'M', u'sr'), + (0x33DC, 'M', u'sv'), + (0x33DD, 'M', u'wb'), + (0x33DE, 'M', u'v∕m'), + (0x33DF, 'M', u'a∕m'), + (0x33E0, 'M', u'1日'), + (0x33E1, 'M', u'2日'), + (0x33E2, 'M', u'3日'), + (0x33E3, 'M', u'4日'), + (0x33E4, 'M', u'5日'), + (0x33E5, 'M', u'6日'), + (0x33E6, 'M', u'7日'), + (0x33E7, 'M', u'8日'), + (0x33E8, 'M', u'9日'), + ] + +def _seg_35(): + return [ + (0x33E9, 'M', u'10日'), + (0x33EA, 'M', u'11日'), + (0x33EB, 'M', u'12日'), + (0x33EC, 'M', u'13日'), + (0x33ED, 'M', u'14日'), + (0x33EE, 'M', u'15日'), + (0x33EF, 'M', u'16日'), + (0x33F0, 'M', u'17日'), + (0x33F1, 'M', u'18日'), + (0x33F2, 'M', u'19日'), + (0x33F3, 'M', u'20日'), + (0x33F4, 'M', u'21日'), + (0x33F5, 'M', u'22日'), + (0x33F6, 'M', u'23日'), + (0x33F7, 'M', u'24日'), + (0x33F8, 'M', u'25日'), + (0x33F9, 'M', u'26日'), + (0x33FA, 'M', u'27日'), + (0x33FB, 'M', u'28日'), + (0x33FC, 'M', u'29日'), + (0x33FD, 'M', u'30日'), + (0x33FE, 'M', u'31日'), + (0x33FF, 'M', u'gal'), + (0x3400, 'V'), + (0x4DB6, 'X'), + (0x4DC0, 'V'), + (0x9FEB, 'X'), + (0xA000, 'V'), + (0xA48D, 'X'), + (0xA490, 'V'), + (0xA4C7, 'X'), + (0xA4D0, 'V'), + (0xA62C, 'X'), + (0xA640, 'M', u'ꙁ'), + (0xA641, 'V'), + (0xA642, 'M', u'ꙃ'), + (0xA643, 'V'), + (0xA644, 'M', u'ꙅ'), + (0xA645, 'V'), + (0xA646, 'M', u'ꙇ'), + (0xA647, 'V'), + (0xA648, 'M', u'ꙉ'), + (0xA649, 'V'), + (0xA64A, 'M', u'ꙋ'), + (0xA64B, 'V'), + (0xA64C, 'M', u'ꙍ'), + (0xA64D, 'V'), + (0xA64E, 'M', u'ꙏ'), + (0xA64F, 'V'), + (0xA650, 'M', u'ꙑ'), + (0xA651, 'V'), + (0xA652, 'M', u'ꙓ'), + (0xA653, 'V'), + (0xA654, 'M', u'ꙕ'), + (0xA655, 'V'), + (0xA656, 'M', u'ꙗ'), + (0xA657, 'V'), + (0xA658, 'M', u'ꙙ'), + (0xA659, 'V'), + (0xA65A, 'M', u'ꙛ'), + (0xA65B, 'V'), + (0xA65C, 'M', u'ꙝ'), + (0xA65D, 'V'), + (0xA65E, 'M', u'ꙟ'), + (0xA65F, 'V'), + (0xA660, 'M', u'ꙡ'), + (0xA661, 'V'), + (0xA662, 'M', u'ꙣ'), + (0xA663, 'V'), + (0xA664, 'M', u'ꙥ'), + (0xA665, 'V'), + (0xA666, 'M', u'ꙧ'), + (0xA667, 'V'), + (0xA668, 'M', u'ꙩ'), + (0xA669, 'V'), + (0xA66A, 'M', u'ꙫ'), + (0xA66B, 'V'), + (0xA66C, 'M', u'ꙭ'), + (0xA66D, 'V'), + (0xA680, 'M', u'ꚁ'), + (0xA681, 'V'), + (0xA682, 'M', u'ꚃ'), + (0xA683, 'V'), + (0xA684, 'M', u'ꚅ'), + (0xA685, 'V'), + (0xA686, 'M', u'ꚇ'), + (0xA687, 'V'), + (0xA688, 'M', u'ꚉ'), + (0xA689, 'V'), + (0xA68A, 'M', u'ꚋ'), + (0xA68B, 'V'), + (0xA68C, 'M', u'ꚍ'), + (0xA68D, 'V'), + (0xA68E, 'M', u'ꚏ'), + (0xA68F, 'V'), + (0xA690, 'M', u'ꚑ'), + (0xA691, 'V'), + (0xA692, 'M', u'ꚓ'), + (0xA693, 'V'), + (0xA694, 'M', u'ꚕ'), + ] + +def _seg_36(): + return [ + (0xA695, 'V'), + (0xA696, 'M', u'ꚗ'), + (0xA697, 'V'), + (0xA698, 'M', u'ꚙ'), + (0xA699, 'V'), + (0xA69A, 'M', u'ꚛ'), + (0xA69B, 'V'), + (0xA69C, 'M', u'ъ'), + (0xA69D, 'M', u'ь'), + (0xA69E, 'V'), + (0xA6F8, 'X'), + (0xA700, 'V'), + (0xA722, 'M', u'ꜣ'), + (0xA723, 'V'), + (0xA724, 'M', u'ꜥ'), + (0xA725, 'V'), + (0xA726, 'M', u'ꜧ'), + (0xA727, 'V'), + (0xA728, 'M', u'ꜩ'), + (0xA729, 'V'), + (0xA72A, 'M', u'ꜫ'), + (0xA72B, 'V'), + (0xA72C, 'M', u'ꜭ'), + (0xA72D, 'V'), + (0xA72E, 'M', u'ꜯ'), + (0xA72F, 'V'), + (0xA732, 'M', u'ꜳ'), + (0xA733, 'V'), + (0xA734, 'M', u'ꜵ'), + (0xA735, 'V'), + (0xA736, 'M', u'ꜷ'), + (0xA737, 'V'), + (0xA738, 'M', u'ꜹ'), + (0xA739, 'V'), + (0xA73A, 'M', u'ꜻ'), + (0xA73B, 'V'), + (0xA73C, 'M', u'ꜽ'), + (0xA73D, 'V'), + (0xA73E, 'M', u'ꜿ'), + (0xA73F, 'V'), + (0xA740, 'M', u'ꝁ'), + (0xA741, 'V'), + (0xA742, 'M', u'ꝃ'), + (0xA743, 'V'), + (0xA744, 'M', u'ꝅ'), + (0xA745, 'V'), + (0xA746, 'M', u'ꝇ'), + (0xA747, 'V'), + (0xA748, 'M', u'ꝉ'), + (0xA749, 'V'), + (0xA74A, 'M', u'ꝋ'), + (0xA74B, 'V'), + (0xA74C, 'M', u'ꝍ'), + (0xA74D, 'V'), + (0xA74E, 'M', u'ꝏ'), + (0xA74F, 'V'), + (0xA750, 'M', u'ꝑ'), + (0xA751, 'V'), + (0xA752, 'M', u'ꝓ'), + (0xA753, 'V'), + (0xA754, 'M', u'ꝕ'), + (0xA755, 'V'), + (0xA756, 'M', u'ꝗ'), + (0xA757, 'V'), + (0xA758, 'M', u'ꝙ'), + (0xA759, 'V'), + (0xA75A, 'M', u'ꝛ'), + (0xA75B, 'V'), + (0xA75C, 'M', u'ꝝ'), + (0xA75D, 'V'), + (0xA75E, 'M', u'ꝟ'), + (0xA75F, 'V'), + (0xA760, 'M', u'ꝡ'), + (0xA761, 'V'), + (0xA762, 'M', u'ꝣ'), + (0xA763, 'V'), + (0xA764, 'M', u'ꝥ'), + (0xA765, 'V'), + (0xA766, 'M', u'ꝧ'), + (0xA767, 'V'), + (0xA768, 'M', u'ꝩ'), + (0xA769, 'V'), + (0xA76A, 'M', u'ꝫ'), + (0xA76B, 'V'), + (0xA76C, 'M', u'ꝭ'), + (0xA76D, 'V'), + (0xA76E, 'M', u'ꝯ'), + (0xA76F, 'V'), + (0xA770, 'M', u'ꝯ'), + (0xA771, 'V'), + (0xA779, 'M', u'ꝺ'), + (0xA77A, 'V'), + (0xA77B, 'M', u'ꝼ'), + (0xA77C, 'V'), + (0xA77D, 'M', u'ᵹ'), + (0xA77E, 'M', u'ꝿ'), + (0xA77F, 'V'), + (0xA780, 'M', u'ꞁ'), + (0xA781, 'V'), + (0xA782, 'M', u'ꞃ'), + ] + +def _seg_37(): + return [ + (0xA783, 'V'), + (0xA784, 'M', u'ꞅ'), + (0xA785, 'V'), + (0xA786, 'M', u'ꞇ'), + (0xA787, 'V'), + (0xA78B, 'M', u'ꞌ'), + (0xA78C, 'V'), + (0xA78D, 'M', u'ɥ'), + (0xA78E, 'V'), + (0xA790, 'M', u'ꞑ'), + (0xA791, 'V'), + (0xA792, 'M', u'ꞓ'), + (0xA793, 'V'), + (0xA796, 'M', u'ꞗ'), + (0xA797, 'V'), + (0xA798, 'M', u'ꞙ'), + (0xA799, 'V'), + (0xA79A, 'M', u'ꞛ'), + (0xA79B, 'V'), + (0xA79C, 'M', u'ꞝ'), + (0xA79D, 'V'), + (0xA79E, 'M', u'ꞟ'), + (0xA79F, 'V'), + (0xA7A0, 'M', u'ꞡ'), + (0xA7A1, 'V'), + (0xA7A2, 'M', u'ꞣ'), + (0xA7A3, 'V'), + (0xA7A4, 'M', u'ꞥ'), + (0xA7A5, 'V'), + (0xA7A6, 'M', u'ꞧ'), + (0xA7A7, 'V'), + (0xA7A8, 'M', u'ꞩ'), + (0xA7A9, 'V'), + (0xA7AA, 'M', u'ɦ'), + (0xA7AB, 'M', u'ɜ'), + (0xA7AC, 'M', u'ɡ'), + (0xA7AD, 'M', u'ɬ'), + (0xA7AE, 'M', u'ɪ'), + (0xA7AF, 'X'), + (0xA7B0, 'M', u'ʞ'), + (0xA7B1, 'M', u'ʇ'), + (0xA7B2, 'M', u'ʝ'), + (0xA7B3, 'M', u'ꭓ'), + (0xA7B4, 'M', u'ꞵ'), + (0xA7B5, 'V'), + (0xA7B6, 'M', u'ꞷ'), + (0xA7B7, 'V'), + (0xA7B8, 'X'), + (0xA7F7, 'V'), + (0xA7F8, 'M', u'ħ'), + (0xA7F9, 'M', u'œ'), + (0xA7FA, 'V'), + (0xA82C, 'X'), + (0xA830, 'V'), + (0xA83A, 'X'), + (0xA840, 'V'), + (0xA878, 'X'), + (0xA880, 'V'), + (0xA8C6, 'X'), + (0xA8CE, 'V'), + (0xA8DA, 'X'), + (0xA8E0, 'V'), + (0xA8FE, 'X'), + (0xA900, 'V'), + (0xA954, 'X'), + (0xA95F, 'V'), + (0xA97D, 'X'), + (0xA980, 'V'), + (0xA9CE, 'X'), + (0xA9CF, 'V'), + (0xA9DA, 'X'), + (0xA9DE, 'V'), + (0xA9FF, 'X'), + (0xAA00, 'V'), + (0xAA37, 'X'), + (0xAA40, 'V'), + (0xAA4E, 'X'), + (0xAA50, 'V'), + (0xAA5A, 'X'), + (0xAA5C, 'V'), + (0xAAC3, 'X'), + (0xAADB, 'V'), + (0xAAF7, 'X'), + (0xAB01, 'V'), + (0xAB07, 'X'), + (0xAB09, 'V'), + (0xAB0F, 'X'), + (0xAB11, 'V'), + (0xAB17, 'X'), + (0xAB20, 'V'), + (0xAB27, 'X'), + (0xAB28, 'V'), + (0xAB2F, 'X'), + (0xAB30, 'V'), + (0xAB5C, 'M', u'ꜧ'), + (0xAB5D, 'M', u'ꬷ'), + (0xAB5E, 'M', u'ɫ'), + (0xAB5F, 'M', u'ꭒ'), + (0xAB60, 'V'), + (0xAB66, 'X'), + ] + +def _seg_38(): + return [ + (0xAB70, 'M', u'Ꭰ'), + (0xAB71, 'M', u'Ꭱ'), + (0xAB72, 'M', u'Ꭲ'), + (0xAB73, 'M', u'Ꭳ'), + (0xAB74, 'M', u'Ꭴ'), + (0xAB75, 'M', u'Ꭵ'), + (0xAB76, 'M', u'Ꭶ'), + (0xAB77, 'M', u'Ꭷ'), + (0xAB78, 'M', u'Ꭸ'), + (0xAB79, 'M', u'Ꭹ'), + (0xAB7A, 'M', u'Ꭺ'), + (0xAB7B, 'M', u'Ꭻ'), + (0xAB7C, 'M', u'Ꭼ'), + (0xAB7D, 'M', u'Ꭽ'), + (0xAB7E, 'M', u'Ꭾ'), + (0xAB7F, 'M', u'Ꭿ'), + (0xAB80, 'M', u'Ꮀ'), + (0xAB81, 'M', u'Ꮁ'), + (0xAB82, 'M', u'Ꮂ'), + (0xAB83, 'M', u'Ꮃ'), + (0xAB84, 'M', u'Ꮄ'), + (0xAB85, 'M', u'Ꮅ'), + (0xAB86, 'M', u'Ꮆ'), + (0xAB87, 'M', u'Ꮇ'), + (0xAB88, 'M', u'Ꮈ'), + (0xAB89, 'M', u'Ꮉ'), + (0xAB8A, 'M', u'Ꮊ'), + (0xAB8B, 'M', u'Ꮋ'), + (0xAB8C, 'M', u'Ꮌ'), + (0xAB8D, 'M', u'Ꮍ'), + (0xAB8E, 'M', u'Ꮎ'), + (0xAB8F, 'M', u'Ꮏ'), + (0xAB90, 'M', u'Ꮐ'), + (0xAB91, 'M', u'Ꮑ'), + (0xAB92, 'M', u'Ꮒ'), + (0xAB93, 'M', u'Ꮓ'), + (0xAB94, 'M', u'Ꮔ'), + (0xAB95, 'M', u'Ꮕ'), + (0xAB96, 'M', u'Ꮖ'), + (0xAB97, 'M', u'Ꮗ'), + (0xAB98, 'M', u'Ꮘ'), + (0xAB99, 'M', u'Ꮙ'), + (0xAB9A, 'M', u'Ꮚ'), + (0xAB9B, 'M', u'Ꮛ'), + (0xAB9C, 'M', u'Ꮜ'), + (0xAB9D, 'M', u'Ꮝ'), + (0xAB9E, 'M', u'Ꮞ'), + (0xAB9F, 'M', u'Ꮟ'), + (0xABA0, 'M', u'Ꮠ'), + (0xABA1, 'M', u'Ꮡ'), + (0xABA2, 'M', u'Ꮢ'), + (0xABA3, 'M', u'Ꮣ'), + (0xABA4, 'M', u'Ꮤ'), + (0xABA5, 'M', u'Ꮥ'), + (0xABA6, 'M', u'Ꮦ'), + (0xABA7, 'M', u'Ꮧ'), + (0xABA8, 'M', u'Ꮨ'), + (0xABA9, 'M', u'Ꮩ'), + (0xABAA, 'M', u'Ꮪ'), + (0xABAB, 'M', u'Ꮫ'), + (0xABAC, 'M', u'Ꮬ'), + (0xABAD, 'M', u'Ꮭ'), + (0xABAE, 'M', u'Ꮮ'), + (0xABAF, 'M', u'Ꮯ'), + (0xABB0, 'M', u'Ꮰ'), + (0xABB1, 'M', u'Ꮱ'), + (0xABB2, 'M', u'Ꮲ'), + (0xABB3, 'M', u'Ꮳ'), + (0xABB4, 'M', u'Ꮴ'), + (0xABB5, 'M', u'Ꮵ'), + (0xABB6, 'M', u'Ꮶ'), + (0xABB7, 'M', u'Ꮷ'), + (0xABB8, 'M', u'Ꮸ'), + (0xABB9, 'M', u'Ꮹ'), + (0xABBA, 'M', u'Ꮺ'), + (0xABBB, 'M', u'Ꮻ'), + (0xABBC, 'M', u'Ꮼ'), + (0xABBD, 'M', u'Ꮽ'), + (0xABBE, 'M', u'Ꮾ'), + (0xABBF, 'M', u'Ꮿ'), + (0xABC0, 'V'), + (0xABEE, 'X'), + (0xABF0, 'V'), + (0xABFA, 'X'), + (0xAC00, 'V'), + (0xD7A4, 'X'), + (0xD7B0, 'V'), + (0xD7C7, 'X'), + (0xD7CB, 'V'), + (0xD7FC, 'X'), + (0xF900, 'M', u'豈'), + (0xF901, 'M', u'更'), + (0xF902, 'M', u'車'), + (0xF903, 'M', u'賈'), + (0xF904, 'M', u'滑'), + (0xF905, 'M', u'串'), + (0xF906, 'M', u'句'), + (0xF907, 'M', u'龜'), + (0xF909, 'M', u'契'), + (0xF90A, 'M', u'金'), + ] + +def _seg_39(): + return [ + (0xF90B, 'M', u'喇'), + (0xF90C, 'M', u'奈'), + (0xF90D, 'M', u'懶'), + (0xF90E, 'M', u'癩'), + (0xF90F, 'M', u'羅'), + (0xF910, 'M', u'蘿'), + (0xF911, 'M', u'螺'), + (0xF912, 'M', u'裸'), + (0xF913, 'M', u'邏'), + (0xF914, 'M', u'樂'), + (0xF915, 'M', u'洛'), + (0xF916, 'M', u'烙'), + (0xF917, 'M', u'珞'), + (0xF918, 'M', u'落'), + (0xF919, 'M', u'酪'), + (0xF91A, 'M', u'駱'), + (0xF91B, 'M', u'亂'), + (0xF91C, 'M', u'卵'), + (0xF91D, 'M', u'欄'), + (0xF91E, 'M', u'爛'), + (0xF91F, 'M', u'蘭'), + (0xF920, 'M', u'鸞'), + (0xF921, 'M', u'嵐'), + (0xF922, 'M', u'濫'), + (0xF923, 'M', u'藍'), + (0xF924, 'M', u'襤'), + (0xF925, 'M', u'拉'), + (0xF926, 'M', u'臘'), + (0xF927, 'M', u'蠟'), + (0xF928, 'M', u'廊'), + (0xF929, 'M', u'朗'), + (0xF92A, 'M', u'浪'), + (0xF92B, 'M', u'狼'), + (0xF92C, 'M', u'郎'), + (0xF92D, 'M', u'來'), + (0xF92E, 'M', u'冷'), + (0xF92F, 'M', u'勞'), + (0xF930, 'M', u'擄'), + (0xF931, 'M', u'櫓'), + (0xF932, 'M', u'爐'), + (0xF933, 'M', u'盧'), + (0xF934, 'M', u'老'), + (0xF935, 'M', u'蘆'), + (0xF936, 'M', u'虜'), + (0xF937, 'M', u'路'), + (0xF938, 'M', u'露'), + (0xF939, 'M', u'魯'), + (0xF93A, 'M', u'鷺'), + (0xF93B, 'M', u'碌'), + (0xF93C, 'M', u'祿'), + (0xF93D, 'M', u'綠'), + (0xF93E, 'M', u'菉'), + (0xF93F, 'M', u'錄'), + (0xF940, 'M', u'鹿'), + (0xF941, 'M', u'論'), + (0xF942, 'M', u'壟'), + (0xF943, 'M', u'弄'), + (0xF944, 'M', u'籠'), + (0xF945, 'M', u'聾'), + (0xF946, 'M', u'牢'), + (0xF947, 'M', u'磊'), + (0xF948, 'M', u'賂'), + (0xF949, 'M', u'雷'), + (0xF94A, 'M', u'壘'), + (0xF94B, 'M', u'屢'), + (0xF94C, 'M', u'樓'), + (0xF94D, 'M', u'淚'), + (0xF94E, 'M', u'漏'), + (0xF94F, 'M', u'累'), + (0xF950, 'M', u'縷'), + (0xF951, 'M', u'陋'), + (0xF952, 'M', u'勒'), + (0xF953, 'M', u'肋'), + (0xF954, 'M', u'凜'), + (0xF955, 'M', u'凌'), + (0xF956, 'M', u'稜'), + (0xF957, 'M', u'綾'), + (0xF958, 'M', u'菱'), + (0xF959, 'M', u'陵'), + (0xF95A, 'M', u'讀'), + (0xF95B, 'M', u'拏'), + (0xF95C, 'M', u'樂'), + (0xF95D, 'M', u'諾'), + (0xF95E, 'M', u'丹'), + (0xF95F, 'M', u'寧'), + (0xF960, 'M', u'怒'), + (0xF961, 'M', u'率'), + (0xF962, 'M', u'異'), + (0xF963, 'M', u'北'), + (0xF964, 'M', u'磻'), + (0xF965, 'M', u'便'), + (0xF966, 'M', u'復'), + (0xF967, 'M', u'不'), + (0xF968, 'M', u'泌'), + (0xF969, 'M', u'數'), + (0xF96A, 'M', u'索'), + (0xF96B, 'M', u'參'), + (0xF96C, 'M', u'塞'), + (0xF96D, 'M', u'省'), + (0xF96E, 'M', u'葉'), + ] + +def _seg_40(): + return [ + (0xF96F, 'M', u'說'), + (0xF970, 'M', u'殺'), + (0xF971, 'M', u'辰'), + (0xF972, 'M', u'沈'), + (0xF973, 'M', u'拾'), + (0xF974, 'M', u'若'), + (0xF975, 'M', u'掠'), + (0xF976, 'M', u'略'), + (0xF977, 'M', u'亮'), + (0xF978, 'M', u'兩'), + (0xF979, 'M', u'凉'), + (0xF97A, 'M', u'梁'), + (0xF97B, 'M', u'糧'), + (0xF97C, 'M', u'良'), + (0xF97D, 'M', u'諒'), + (0xF97E, 'M', u'量'), + (0xF97F, 'M', u'勵'), + (0xF980, 'M', u'呂'), + (0xF981, 'M', u'女'), + (0xF982, 'M', u'廬'), + (0xF983, 'M', u'旅'), + (0xF984, 'M', u'濾'), + (0xF985, 'M', u'礪'), + (0xF986, 'M', u'閭'), + (0xF987, 'M', u'驪'), + (0xF988, 'M', u'麗'), + (0xF989, 'M', u'黎'), + (0xF98A, 'M', u'力'), + (0xF98B, 'M', u'曆'), + (0xF98C, 'M', u'歷'), + (0xF98D, 'M', u'轢'), + (0xF98E, 'M', u'年'), + (0xF98F, 'M', u'憐'), + (0xF990, 'M', u'戀'), + (0xF991, 'M', u'撚'), + (0xF992, 'M', u'漣'), + (0xF993, 'M', u'煉'), + (0xF994, 'M', u'璉'), + (0xF995, 'M', u'秊'), + (0xF996, 'M', u'練'), + (0xF997, 'M', u'聯'), + (0xF998, 'M', u'輦'), + (0xF999, 'M', u'蓮'), + (0xF99A, 'M', u'連'), + (0xF99B, 'M', u'鍊'), + (0xF99C, 'M', u'列'), + (0xF99D, 'M', u'劣'), + (0xF99E, 'M', u'咽'), + (0xF99F, 'M', u'烈'), + (0xF9A0, 'M', u'裂'), + (0xF9A1, 'M', u'說'), + (0xF9A2, 'M', u'廉'), + (0xF9A3, 'M', u'念'), + (0xF9A4, 'M', u'捻'), + (0xF9A5, 'M', u'殮'), + (0xF9A6, 'M', u'簾'), + (0xF9A7, 'M', u'獵'), + (0xF9A8, 'M', u'令'), + (0xF9A9, 'M', u'囹'), + (0xF9AA, 'M', u'寧'), + (0xF9AB, 'M', u'嶺'), + (0xF9AC, 'M', u'怜'), + (0xF9AD, 'M', u'玲'), + (0xF9AE, 'M', u'瑩'), + (0xF9AF, 'M', u'羚'), + (0xF9B0, 'M', u'聆'), + (0xF9B1, 'M', u'鈴'), + (0xF9B2, 'M', u'零'), + (0xF9B3, 'M', u'靈'), + (0xF9B4, 'M', u'領'), + (0xF9B5, 'M', u'例'), + (0xF9B6, 'M', u'禮'), + (0xF9B7, 'M', u'醴'), + (0xF9B8, 'M', u'隸'), + (0xF9B9, 'M', u'惡'), + (0xF9BA, 'M', u'了'), + (0xF9BB, 'M', u'僚'), + (0xF9BC, 'M', u'寮'), + (0xF9BD, 'M', u'尿'), + (0xF9BE, 'M', u'料'), + (0xF9BF, 'M', u'樂'), + (0xF9C0, 'M', u'燎'), + (0xF9C1, 'M', u'療'), + (0xF9C2, 'M', u'蓼'), + (0xF9C3, 'M', u'遼'), + (0xF9C4, 'M', u'龍'), + (0xF9C5, 'M', u'暈'), + (0xF9C6, 'M', u'阮'), + (0xF9C7, 'M', u'劉'), + (0xF9C8, 'M', u'杻'), + (0xF9C9, 'M', u'柳'), + (0xF9CA, 'M', u'流'), + (0xF9CB, 'M', u'溜'), + (0xF9CC, 'M', u'琉'), + (0xF9CD, 'M', u'留'), + (0xF9CE, 'M', u'硫'), + (0xF9CF, 'M', u'紐'), + (0xF9D0, 'M', u'類'), + (0xF9D1, 'M', u'六'), + (0xF9D2, 'M', u'戮'), + ] + +def _seg_41(): + return [ + (0xF9D3, 'M', u'陸'), + (0xF9D4, 'M', u'倫'), + (0xF9D5, 'M', u'崙'), + (0xF9D6, 'M', u'淪'), + (0xF9D7, 'M', u'輪'), + (0xF9D8, 'M', u'律'), + (0xF9D9, 'M', u'慄'), + (0xF9DA, 'M', u'栗'), + (0xF9DB, 'M', u'率'), + (0xF9DC, 'M', u'隆'), + (0xF9DD, 'M', u'利'), + (0xF9DE, 'M', u'吏'), + (0xF9DF, 'M', u'履'), + (0xF9E0, 'M', u'易'), + (0xF9E1, 'M', u'李'), + (0xF9E2, 'M', u'梨'), + (0xF9E3, 'M', u'泥'), + (0xF9E4, 'M', u'理'), + (0xF9E5, 'M', u'痢'), + (0xF9E6, 'M', u'罹'), + (0xF9E7, 'M', u'裏'), + (0xF9E8, 'M', u'裡'), + (0xF9E9, 'M', u'里'), + (0xF9EA, 'M', u'離'), + (0xF9EB, 'M', u'匿'), + (0xF9EC, 'M', u'溺'), + (0xF9ED, 'M', u'吝'), + (0xF9EE, 'M', u'燐'), + (0xF9EF, 'M', u'璘'), + (0xF9F0, 'M', u'藺'), + (0xF9F1, 'M', u'隣'), + (0xF9F2, 'M', u'鱗'), + (0xF9F3, 'M', u'麟'), + (0xF9F4, 'M', u'林'), + (0xF9F5, 'M', u'淋'), + (0xF9F6, 'M', u'臨'), + (0xF9F7, 'M', u'立'), + (0xF9F8, 'M', u'笠'), + (0xF9F9, 'M', u'粒'), + (0xF9FA, 'M', u'狀'), + (0xF9FB, 'M', u'炙'), + (0xF9FC, 'M', u'識'), + (0xF9FD, 'M', u'什'), + (0xF9FE, 'M', u'茶'), + (0xF9FF, 'M', u'刺'), + (0xFA00, 'M', u'切'), + (0xFA01, 'M', u'度'), + (0xFA02, 'M', u'拓'), + (0xFA03, 'M', u'糖'), + (0xFA04, 'M', u'宅'), + (0xFA05, 'M', u'洞'), + (0xFA06, 'M', u'暴'), + (0xFA07, 'M', u'輻'), + (0xFA08, 'M', u'行'), + (0xFA09, 'M', u'降'), + (0xFA0A, 'M', u'見'), + (0xFA0B, 'M', u'廓'), + (0xFA0C, 'M', u'兀'), + (0xFA0D, 'M', u'嗀'), + (0xFA0E, 'V'), + (0xFA10, 'M', u'塚'), + (0xFA11, 'V'), + (0xFA12, 'M', u'晴'), + (0xFA13, 'V'), + (0xFA15, 'M', u'凞'), + (0xFA16, 'M', u'猪'), + (0xFA17, 'M', u'益'), + (0xFA18, 'M', u'礼'), + (0xFA19, 'M', u'神'), + (0xFA1A, 'M', u'祥'), + (0xFA1B, 'M', u'福'), + (0xFA1C, 'M', u'靖'), + (0xFA1D, 'M', u'精'), + (0xFA1E, 'M', u'羽'), + (0xFA1F, 'V'), + (0xFA20, 'M', u'蘒'), + (0xFA21, 'V'), + (0xFA22, 'M', u'諸'), + (0xFA23, 'V'), + (0xFA25, 'M', u'逸'), + (0xFA26, 'M', u'都'), + (0xFA27, 'V'), + (0xFA2A, 'M', u'飯'), + (0xFA2B, 'M', u'飼'), + (0xFA2C, 'M', u'館'), + (0xFA2D, 'M', u'鶴'), + (0xFA2E, 'M', u'郞'), + (0xFA2F, 'M', u'隷'), + (0xFA30, 'M', u'侮'), + (0xFA31, 'M', u'僧'), + (0xFA32, 'M', u'免'), + (0xFA33, 'M', u'勉'), + (0xFA34, 'M', u'勤'), + (0xFA35, 'M', u'卑'), + (0xFA36, 'M', u'喝'), + (0xFA37, 'M', u'嘆'), + (0xFA38, 'M', u'器'), + (0xFA39, 'M', u'塀'), + (0xFA3A, 'M', u'墨'), + (0xFA3B, 'M', u'層'), + ] + +def _seg_42(): + return [ + (0xFA3C, 'M', u'屮'), + (0xFA3D, 'M', u'悔'), + (0xFA3E, 'M', u'慨'), + (0xFA3F, 'M', u'憎'), + (0xFA40, 'M', u'懲'), + (0xFA41, 'M', u'敏'), + (0xFA42, 'M', u'既'), + (0xFA43, 'M', u'暑'), + (0xFA44, 'M', u'梅'), + (0xFA45, 'M', u'海'), + (0xFA46, 'M', u'渚'), + (0xFA47, 'M', u'漢'), + (0xFA48, 'M', u'煮'), + (0xFA49, 'M', u'爫'), + (0xFA4A, 'M', u'琢'), + (0xFA4B, 'M', u'碑'), + (0xFA4C, 'M', u'社'), + (0xFA4D, 'M', u'祉'), + (0xFA4E, 'M', u'祈'), + (0xFA4F, 'M', u'祐'), + (0xFA50, 'M', u'祖'), + (0xFA51, 'M', u'祝'), + (0xFA52, 'M', u'禍'), + (0xFA53, 'M', u'禎'), + (0xFA54, 'M', u'穀'), + (0xFA55, 'M', u'突'), + (0xFA56, 'M', u'節'), + (0xFA57, 'M', u'練'), + (0xFA58, 'M', u'縉'), + (0xFA59, 'M', u'繁'), + (0xFA5A, 'M', u'署'), + (0xFA5B, 'M', u'者'), + (0xFA5C, 'M', u'臭'), + (0xFA5D, 'M', u'艹'), + (0xFA5F, 'M', u'著'), + (0xFA60, 'M', u'褐'), + (0xFA61, 'M', u'視'), + (0xFA62, 'M', u'謁'), + (0xFA63, 'M', u'謹'), + (0xFA64, 'M', u'賓'), + (0xFA65, 'M', u'贈'), + (0xFA66, 'M', u'辶'), + (0xFA67, 'M', u'逸'), + (0xFA68, 'M', u'難'), + (0xFA69, 'M', u'響'), + (0xFA6A, 'M', u'頻'), + (0xFA6B, 'M', u'恵'), + (0xFA6C, 'M', u'𤋮'), + (0xFA6D, 'M', u'舘'), + (0xFA6E, 'X'), + (0xFA70, 'M', u'並'), + (0xFA71, 'M', u'况'), + (0xFA72, 'M', u'全'), + (0xFA73, 'M', u'侀'), + (0xFA74, 'M', u'充'), + (0xFA75, 'M', u'冀'), + (0xFA76, 'M', u'勇'), + (0xFA77, 'M', u'勺'), + (0xFA78, 'M', u'喝'), + (0xFA79, 'M', u'啕'), + (0xFA7A, 'M', u'喙'), + (0xFA7B, 'M', u'嗢'), + (0xFA7C, 'M', u'塚'), + (0xFA7D, 'M', u'墳'), + (0xFA7E, 'M', u'奄'), + (0xFA7F, 'M', u'奔'), + (0xFA80, 'M', u'婢'), + (0xFA81, 'M', u'嬨'), + (0xFA82, 'M', u'廒'), + (0xFA83, 'M', u'廙'), + (0xFA84, 'M', u'彩'), + (0xFA85, 'M', u'徭'), + (0xFA86, 'M', u'惘'), + (0xFA87, 'M', u'慎'), + (0xFA88, 'M', u'愈'), + (0xFA89, 'M', u'憎'), + (0xFA8A, 'M', u'慠'), + (0xFA8B, 'M', u'懲'), + (0xFA8C, 'M', u'戴'), + (0xFA8D, 'M', u'揄'), + (0xFA8E, 'M', u'搜'), + (0xFA8F, 'M', u'摒'), + (0xFA90, 'M', u'敖'), + (0xFA91, 'M', u'晴'), + (0xFA92, 'M', u'朗'), + (0xFA93, 'M', u'望'), + (0xFA94, 'M', u'杖'), + (0xFA95, 'M', u'歹'), + (0xFA96, 'M', u'殺'), + (0xFA97, 'M', u'流'), + (0xFA98, 'M', u'滛'), + (0xFA99, 'M', u'滋'), + (0xFA9A, 'M', u'漢'), + (0xFA9B, 'M', u'瀞'), + (0xFA9C, 'M', u'煮'), + (0xFA9D, 'M', u'瞧'), + (0xFA9E, 'M', u'爵'), + (0xFA9F, 'M', u'犯'), + (0xFAA0, 'M', u'猪'), + (0xFAA1, 'M', u'瑱'), + ] + +def _seg_43(): + return [ + (0xFAA2, 'M', u'甆'), + (0xFAA3, 'M', u'画'), + (0xFAA4, 'M', u'瘝'), + (0xFAA5, 'M', u'瘟'), + (0xFAA6, 'M', u'益'), + (0xFAA7, 'M', u'盛'), + (0xFAA8, 'M', u'直'), + (0xFAA9, 'M', u'睊'), + (0xFAAA, 'M', u'着'), + (0xFAAB, 'M', u'磌'), + (0xFAAC, 'M', u'窱'), + (0xFAAD, 'M', u'節'), + (0xFAAE, 'M', u'类'), + (0xFAAF, 'M', u'絛'), + (0xFAB0, 'M', u'練'), + (0xFAB1, 'M', u'缾'), + (0xFAB2, 'M', u'者'), + (0xFAB3, 'M', u'荒'), + (0xFAB4, 'M', u'華'), + (0xFAB5, 'M', u'蝹'), + (0xFAB6, 'M', u'襁'), + (0xFAB7, 'M', u'覆'), + (0xFAB8, 'M', u'視'), + (0xFAB9, 'M', u'調'), + (0xFABA, 'M', u'諸'), + (0xFABB, 'M', u'請'), + (0xFABC, 'M', u'謁'), + (0xFABD, 'M', u'諾'), + (0xFABE, 'M', u'諭'), + (0xFABF, 'M', u'謹'), + (0xFAC0, 'M', u'變'), + (0xFAC1, 'M', u'贈'), + (0xFAC2, 'M', u'輸'), + (0xFAC3, 'M', u'遲'), + (0xFAC4, 'M', u'醙'), + (0xFAC5, 'M', u'鉶'), + (0xFAC6, 'M', u'陼'), + (0xFAC7, 'M', u'難'), + (0xFAC8, 'M', u'靖'), + (0xFAC9, 'M', u'韛'), + (0xFACA, 'M', u'響'), + (0xFACB, 'M', u'頋'), + (0xFACC, 'M', u'頻'), + (0xFACD, 'M', u'鬒'), + (0xFACE, 'M', u'龜'), + (0xFACF, 'M', u'𢡊'), + (0xFAD0, 'M', u'𢡄'), + (0xFAD1, 'M', u'𣏕'), + (0xFAD2, 'M', u'㮝'), + (0xFAD3, 'M', u'䀘'), + (0xFAD4, 'M', u'䀹'), + (0xFAD5, 'M', u'𥉉'), + (0xFAD6, 'M', u'𥳐'), + (0xFAD7, 'M', u'𧻓'), + (0xFAD8, 'M', u'齃'), + (0xFAD9, 'M', u'龎'), + (0xFADA, 'X'), + (0xFB00, 'M', u'ff'), + (0xFB01, 'M', u'fi'), + (0xFB02, 'M', u'fl'), + (0xFB03, 'M', u'ffi'), + (0xFB04, 'M', u'ffl'), + (0xFB05, 'M', u'st'), + (0xFB07, 'X'), + (0xFB13, 'M', u'մն'), + (0xFB14, 'M', u'մե'), + (0xFB15, 'M', u'մի'), + (0xFB16, 'M', u'վն'), + (0xFB17, 'M', u'մխ'), + (0xFB18, 'X'), + (0xFB1D, 'M', u'יִ'), + (0xFB1E, 'V'), + (0xFB1F, 'M', u'ײַ'), + (0xFB20, 'M', u'ע'), + (0xFB21, 'M', u'א'), + (0xFB22, 'M', u'ד'), + (0xFB23, 'M', u'ה'), + (0xFB24, 'M', u'כ'), + (0xFB25, 'M', u'ל'), + (0xFB26, 'M', u'ם'), + (0xFB27, 'M', u'ר'), + (0xFB28, 'M', u'ת'), + (0xFB29, '3', u'+'), + (0xFB2A, 'M', u'שׁ'), + (0xFB2B, 'M', u'שׂ'), + (0xFB2C, 'M', u'שּׁ'), + (0xFB2D, 'M', u'שּׂ'), + (0xFB2E, 'M', u'אַ'), + (0xFB2F, 'M', u'אָ'), + (0xFB30, 'M', u'אּ'), + (0xFB31, 'M', u'בּ'), + (0xFB32, 'M', u'גּ'), + (0xFB33, 'M', u'דּ'), + (0xFB34, 'M', u'הּ'), + (0xFB35, 'M', u'וּ'), + (0xFB36, 'M', u'זּ'), + (0xFB37, 'X'), + (0xFB38, 'M', u'טּ'), + (0xFB39, 'M', u'יּ'), + (0xFB3A, 'M', u'ךּ'), + ] + +def _seg_44(): + return [ + (0xFB3B, 'M', u'כּ'), + (0xFB3C, 'M', u'לּ'), + (0xFB3D, 'X'), + (0xFB3E, 'M', u'מּ'), + (0xFB3F, 'X'), + (0xFB40, 'M', u'נּ'), + (0xFB41, 'M', u'סּ'), + (0xFB42, 'X'), + (0xFB43, 'M', u'ףּ'), + (0xFB44, 'M', u'פּ'), + (0xFB45, 'X'), + (0xFB46, 'M', u'צּ'), + (0xFB47, 'M', u'קּ'), + (0xFB48, 'M', u'רּ'), + (0xFB49, 'M', u'שּ'), + (0xFB4A, 'M', u'תּ'), + (0xFB4B, 'M', u'וֹ'), + (0xFB4C, 'M', u'בֿ'), + (0xFB4D, 'M', u'כֿ'), + (0xFB4E, 'M', u'פֿ'), + (0xFB4F, 'M', u'אל'), + (0xFB50, 'M', u'ٱ'), + (0xFB52, 'M', u'ٻ'), + (0xFB56, 'M', u'پ'), + (0xFB5A, 'M', u'ڀ'), + (0xFB5E, 'M', u'ٺ'), + (0xFB62, 'M', u'ٿ'), + (0xFB66, 'M', u'ٹ'), + (0xFB6A, 'M', u'ڤ'), + (0xFB6E, 'M', u'ڦ'), + (0xFB72, 'M', u'ڄ'), + (0xFB76, 'M', u'ڃ'), + (0xFB7A, 'M', u'چ'), + (0xFB7E, 'M', u'ڇ'), + (0xFB82, 'M', u'ڍ'), + (0xFB84, 'M', u'ڌ'), + (0xFB86, 'M', u'ڎ'), + (0xFB88, 'M', u'ڈ'), + (0xFB8A, 'M', u'ژ'), + (0xFB8C, 'M', u'ڑ'), + (0xFB8E, 'M', u'ک'), + (0xFB92, 'M', u'گ'), + (0xFB96, 'M', u'ڳ'), + (0xFB9A, 'M', u'ڱ'), + (0xFB9E, 'M', u'ں'), + (0xFBA0, 'M', u'ڻ'), + (0xFBA4, 'M', u'ۀ'), + (0xFBA6, 'M', u'ہ'), + (0xFBAA, 'M', u'ھ'), + (0xFBAE, 'M', u'ے'), + (0xFBB0, 'M', u'ۓ'), + (0xFBB2, 'V'), + (0xFBC2, 'X'), + (0xFBD3, 'M', u'ڭ'), + (0xFBD7, 'M', u'ۇ'), + (0xFBD9, 'M', u'ۆ'), + (0xFBDB, 'M', u'ۈ'), + (0xFBDD, 'M', u'ۇٴ'), + (0xFBDE, 'M', u'ۋ'), + (0xFBE0, 'M', u'ۅ'), + (0xFBE2, 'M', u'ۉ'), + (0xFBE4, 'M', u'ې'), + (0xFBE8, 'M', u'ى'), + (0xFBEA, 'M', u'ئا'), + (0xFBEC, 'M', u'ئە'), + (0xFBEE, 'M', u'ئو'), + (0xFBF0, 'M', u'ئۇ'), + (0xFBF2, 'M', u'ئۆ'), + (0xFBF4, 'M', u'ئۈ'), + (0xFBF6, 'M', u'ئې'), + (0xFBF9, 'M', u'ئى'), + (0xFBFC, 'M', u'ی'), + (0xFC00, 'M', u'ئج'), + (0xFC01, 'M', u'ئح'), + (0xFC02, 'M', u'ئم'), + (0xFC03, 'M', u'ئى'), + (0xFC04, 'M', u'ئي'), + (0xFC05, 'M', u'بج'), + (0xFC06, 'M', u'بح'), + (0xFC07, 'M', u'بخ'), + (0xFC08, 'M', u'بم'), + (0xFC09, 'M', u'بى'), + (0xFC0A, 'M', u'بي'), + (0xFC0B, 'M', u'تج'), + (0xFC0C, 'M', u'تح'), + (0xFC0D, 'M', u'تخ'), + (0xFC0E, 'M', u'تم'), + (0xFC0F, 'M', u'تى'), + (0xFC10, 'M', u'تي'), + (0xFC11, 'M', u'ثج'), + (0xFC12, 'M', u'ثم'), + (0xFC13, 'M', u'ثى'), + (0xFC14, 'M', u'ثي'), + (0xFC15, 'M', u'جح'), + (0xFC16, 'M', u'جم'), + (0xFC17, 'M', u'حج'), + (0xFC18, 'M', u'حم'), + (0xFC19, 'M', u'خج'), + (0xFC1A, 'M', u'خح'), + (0xFC1B, 'M', u'خم'), + ] + +def _seg_45(): + return [ + (0xFC1C, 'M', u'سج'), + (0xFC1D, 'M', u'سح'), + (0xFC1E, 'M', u'سخ'), + (0xFC1F, 'M', u'سم'), + (0xFC20, 'M', u'صح'), + (0xFC21, 'M', u'صم'), + (0xFC22, 'M', u'ضج'), + (0xFC23, 'M', u'ضح'), + (0xFC24, 'M', u'ضخ'), + (0xFC25, 'M', u'ضم'), + (0xFC26, 'M', u'طح'), + (0xFC27, 'M', u'طم'), + (0xFC28, 'M', u'ظم'), + (0xFC29, 'M', u'عج'), + (0xFC2A, 'M', u'عم'), + (0xFC2B, 'M', u'غج'), + (0xFC2C, 'M', u'غم'), + (0xFC2D, 'M', u'فج'), + (0xFC2E, 'M', u'فح'), + (0xFC2F, 'M', u'فخ'), + (0xFC30, 'M', u'فم'), + (0xFC31, 'M', u'فى'), + (0xFC32, 'M', u'في'), + (0xFC33, 'M', u'قح'), + (0xFC34, 'M', u'قم'), + (0xFC35, 'M', u'قى'), + (0xFC36, 'M', u'قي'), + (0xFC37, 'M', u'كا'), + (0xFC38, 'M', u'كج'), + (0xFC39, 'M', u'كح'), + (0xFC3A, 'M', u'كخ'), + (0xFC3B, 'M', u'كل'), + (0xFC3C, 'M', u'كم'), + (0xFC3D, 'M', u'كى'), + (0xFC3E, 'M', u'كي'), + (0xFC3F, 'M', u'لج'), + (0xFC40, 'M', u'لح'), + (0xFC41, 'M', u'لخ'), + (0xFC42, 'M', u'لم'), + (0xFC43, 'M', u'لى'), + (0xFC44, 'M', u'لي'), + (0xFC45, 'M', u'مج'), + (0xFC46, 'M', u'مح'), + (0xFC47, 'M', u'مخ'), + (0xFC48, 'M', u'مم'), + (0xFC49, 'M', u'مى'), + (0xFC4A, 'M', u'مي'), + (0xFC4B, 'M', u'نج'), + (0xFC4C, 'M', u'نح'), + (0xFC4D, 'M', u'نخ'), + (0xFC4E, 'M', u'نم'), + (0xFC4F, 'M', u'نى'), + (0xFC50, 'M', u'ني'), + (0xFC51, 'M', u'هج'), + (0xFC52, 'M', u'هم'), + (0xFC53, 'M', u'هى'), + (0xFC54, 'M', u'هي'), + (0xFC55, 'M', u'يج'), + (0xFC56, 'M', u'يح'), + (0xFC57, 'M', u'يخ'), + (0xFC58, 'M', u'يم'), + (0xFC59, 'M', u'يى'), + (0xFC5A, 'M', u'يي'), + (0xFC5B, 'M', u'ذٰ'), + (0xFC5C, 'M', u'رٰ'), + (0xFC5D, 'M', u'ىٰ'), + (0xFC5E, '3', u' ٌّ'), + (0xFC5F, '3', u' ٍّ'), + (0xFC60, '3', u' َّ'), + (0xFC61, '3', u' ُّ'), + (0xFC62, '3', u' ِّ'), + (0xFC63, '3', u' ّٰ'), + (0xFC64, 'M', u'ئر'), + (0xFC65, 'M', u'ئز'), + (0xFC66, 'M', u'ئم'), + (0xFC67, 'M', u'ئن'), + (0xFC68, 'M', u'ئى'), + (0xFC69, 'M', u'ئي'), + (0xFC6A, 'M', u'بر'), + (0xFC6B, 'M', u'بز'), + (0xFC6C, 'M', u'بم'), + (0xFC6D, 'M', u'بن'), + (0xFC6E, 'M', u'بى'), + (0xFC6F, 'M', u'بي'), + (0xFC70, 'M', u'تر'), + (0xFC71, 'M', u'تز'), + (0xFC72, 'M', u'تم'), + (0xFC73, 'M', u'تن'), + (0xFC74, 'M', u'تى'), + (0xFC75, 'M', u'تي'), + (0xFC76, 'M', u'ثر'), + (0xFC77, 'M', u'ثز'), + (0xFC78, 'M', u'ثم'), + (0xFC79, 'M', u'ثن'), + (0xFC7A, 'M', u'ثى'), + (0xFC7B, 'M', u'ثي'), + (0xFC7C, 'M', u'فى'), + (0xFC7D, 'M', u'في'), + (0xFC7E, 'M', u'قى'), + (0xFC7F, 'M', u'قي'), + ] + +def _seg_46(): + return [ + (0xFC80, 'M', u'كا'), + (0xFC81, 'M', u'كل'), + (0xFC82, 'M', u'كم'), + (0xFC83, 'M', u'كى'), + (0xFC84, 'M', u'كي'), + (0xFC85, 'M', u'لم'), + (0xFC86, 'M', u'لى'), + (0xFC87, 'M', u'لي'), + (0xFC88, 'M', u'ما'), + (0xFC89, 'M', u'مم'), + (0xFC8A, 'M', u'نر'), + (0xFC8B, 'M', u'نز'), + (0xFC8C, 'M', u'نم'), + (0xFC8D, 'M', u'نن'), + (0xFC8E, 'M', u'نى'), + (0xFC8F, 'M', u'ني'), + (0xFC90, 'M', u'ىٰ'), + (0xFC91, 'M', u'ير'), + (0xFC92, 'M', u'يز'), + (0xFC93, 'M', u'يم'), + (0xFC94, 'M', u'ين'), + (0xFC95, 'M', u'يى'), + (0xFC96, 'M', u'يي'), + (0xFC97, 'M', u'ئج'), + (0xFC98, 'M', u'ئح'), + (0xFC99, 'M', u'ئخ'), + (0xFC9A, 'M', u'ئم'), + (0xFC9B, 'M', u'ئه'), + (0xFC9C, 'M', u'بج'), + (0xFC9D, 'M', u'بح'), + (0xFC9E, 'M', u'بخ'), + (0xFC9F, 'M', u'بم'), + (0xFCA0, 'M', u'به'), + (0xFCA1, 'M', u'تج'), + (0xFCA2, 'M', u'تح'), + (0xFCA3, 'M', u'تخ'), + (0xFCA4, 'M', u'تم'), + (0xFCA5, 'M', u'ته'), + (0xFCA6, 'M', u'ثم'), + (0xFCA7, 'M', u'جح'), + (0xFCA8, 'M', u'جم'), + (0xFCA9, 'M', u'حج'), + (0xFCAA, 'M', u'حم'), + (0xFCAB, 'M', u'خج'), + (0xFCAC, 'M', u'خم'), + (0xFCAD, 'M', u'سج'), + (0xFCAE, 'M', u'سح'), + (0xFCAF, 'M', u'سخ'), + (0xFCB0, 'M', u'سم'), + (0xFCB1, 'M', u'صح'), + (0xFCB2, 'M', u'صخ'), + (0xFCB3, 'M', u'صم'), + (0xFCB4, 'M', u'ضج'), + (0xFCB5, 'M', u'ضح'), + (0xFCB6, 'M', u'ضخ'), + (0xFCB7, 'M', u'ضم'), + (0xFCB8, 'M', u'طح'), + (0xFCB9, 'M', u'ظم'), + (0xFCBA, 'M', u'عج'), + (0xFCBB, 'M', u'عم'), + (0xFCBC, 'M', u'غج'), + (0xFCBD, 'M', u'غم'), + (0xFCBE, 'M', u'فج'), + (0xFCBF, 'M', u'فح'), + (0xFCC0, 'M', u'فخ'), + (0xFCC1, 'M', u'فم'), + (0xFCC2, 'M', u'قح'), + (0xFCC3, 'M', u'قم'), + (0xFCC4, 'M', u'كج'), + (0xFCC5, 'M', u'كح'), + (0xFCC6, 'M', u'كخ'), + (0xFCC7, 'M', u'كل'), + (0xFCC8, 'M', u'كم'), + (0xFCC9, 'M', u'لج'), + (0xFCCA, 'M', u'لح'), + (0xFCCB, 'M', u'لخ'), + (0xFCCC, 'M', u'لم'), + (0xFCCD, 'M', u'له'), + (0xFCCE, 'M', u'مج'), + (0xFCCF, 'M', u'مح'), + (0xFCD0, 'M', u'مخ'), + (0xFCD1, 'M', u'مم'), + (0xFCD2, 'M', u'نج'), + (0xFCD3, 'M', u'نح'), + (0xFCD4, 'M', u'نخ'), + (0xFCD5, 'M', u'نم'), + (0xFCD6, 'M', u'نه'), + (0xFCD7, 'M', u'هج'), + (0xFCD8, 'M', u'هم'), + (0xFCD9, 'M', u'هٰ'), + (0xFCDA, 'M', u'يج'), + (0xFCDB, 'M', u'يح'), + (0xFCDC, 'M', u'يخ'), + (0xFCDD, 'M', u'يم'), + (0xFCDE, 'M', u'يه'), + (0xFCDF, 'M', u'ئم'), + (0xFCE0, 'M', u'ئه'), + (0xFCE1, 'M', u'بم'), + (0xFCE2, 'M', u'به'), + (0xFCE3, 'M', u'تم'), + ] + +def _seg_47(): + return [ + (0xFCE4, 'M', u'ته'), + (0xFCE5, 'M', u'ثم'), + (0xFCE6, 'M', u'ثه'), + (0xFCE7, 'M', u'سم'), + (0xFCE8, 'M', u'سه'), + (0xFCE9, 'M', u'شم'), + (0xFCEA, 'M', u'شه'), + (0xFCEB, 'M', u'كل'), + (0xFCEC, 'M', u'كم'), + (0xFCED, 'M', u'لم'), + (0xFCEE, 'M', u'نم'), + (0xFCEF, 'M', u'نه'), + (0xFCF0, 'M', u'يم'), + (0xFCF1, 'M', u'يه'), + (0xFCF2, 'M', u'ـَّ'), + (0xFCF3, 'M', u'ـُّ'), + (0xFCF4, 'M', u'ـِّ'), + (0xFCF5, 'M', u'طى'), + (0xFCF6, 'M', u'طي'), + (0xFCF7, 'M', u'عى'), + (0xFCF8, 'M', u'عي'), + (0xFCF9, 'M', u'غى'), + (0xFCFA, 'M', u'غي'), + (0xFCFB, 'M', u'سى'), + (0xFCFC, 'M', u'سي'), + (0xFCFD, 'M', u'شى'), + (0xFCFE, 'M', u'شي'), + (0xFCFF, 'M', u'حى'), + (0xFD00, 'M', u'حي'), + (0xFD01, 'M', u'جى'), + (0xFD02, 'M', u'جي'), + (0xFD03, 'M', u'خى'), + (0xFD04, 'M', u'خي'), + (0xFD05, 'M', u'صى'), + (0xFD06, 'M', u'صي'), + (0xFD07, 'M', u'ضى'), + (0xFD08, 'M', u'ضي'), + (0xFD09, 'M', u'شج'), + (0xFD0A, 'M', u'شح'), + (0xFD0B, 'M', u'شخ'), + (0xFD0C, 'M', u'شم'), + (0xFD0D, 'M', u'شر'), + (0xFD0E, 'M', u'سر'), + (0xFD0F, 'M', u'صر'), + (0xFD10, 'M', u'ضر'), + (0xFD11, 'M', u'طى'), + (0xFD12, 'M', u'طي'), + (0xFD13, 'M', u'عى'), + (0xFD14, 'M', u'عي'), + (0xFD15, 'M', u'غى'), + (0xFD16, 'M', u'غي'), + (0xFD17, 'M', u'سى'), + (0xFD18, 'M', u'سي'), + (0xFD19, 'M', u'شى'), + (0xFD1A, 'M', u'شي'), + (0xFD1B, 'M', u'حى'), + (0xFD1C, 'M', u'حي'), + (0xFD1D, 'M', u'جى'), + (0xFD1E, 'M', u'جي'), + (0xFD1F, 'M', u'خى'), + (0xFD20, 'M', u'خي'), + (0xFD21, 'M', u'صى'), + (0xFD22, 'M', u'صي'), + (0xFD23, 'M', u'ضى'), + (0xFD24, 'M', u'ضي'), + (0xFD25, 'M', u'شج'), + (0xFD26, 'M', u'شح'), + (0xFD27, 'M', u'شخ'), + (0xFD28, 'M', u'شم'), + (0xFD29, 'M', u'شر'), + (0xFD2A, 'M', u'سر'), + (0xFD2B, 'M', u'صر'), + (0xFD2C, 'M', u'ضر'), + (0xFD2D, 'M', u'شج'), + (0xFD2E, 'M', u'شح'), + (0xFD2F, 'M', u'شخ'), + (0xFD30, 'M', u'شم'), + (0xFD31, 'M', u'سه'), + (0xFD32, 'M', u'شه'), + (0xFD33, 'M', u'طم'), + (0xFD34, 'M', u'سج'), + (0xFD35, 'M', u'سح'), + (0xFD36, 'M', u'سخ'), + (0xFD37, 'M', u'شج'), + (0xFD38, 'M', u'شح'), + (0xFD39, 'M', u'شخ'), + (0xFD3A, 'M', u'طم'), + (0xFD3B, 'M', u'ظم'), + (0xFD3C, 'M', u'اً'), + (0xFD3E, 'V'), + (0xFD40, 'X'), + (0xFD50, 'M', u'تجم'), + (0xFD51, 'M', u'تحج'), + (0xFD53, 'M', u'تحم'), + (0xFD54, 'M', u'تخم'), + (0xFD55, 'M', u'تمج'), + (0xFD56, 'M', u'تمح'), + (0xFD57, 'M', u'تمخ'), + (0xFD58, 'M', u'جمح'), + (0xFD5A, 'M', u'حمي'), + ] + +def _seg_48(): + return [ + (0xFD5B, 'M', u'حمى'), + (0xFD5C, 'M', u'سحج'), + (0xFD5D, 'M', u'سجح'), + (0xFD5E, 'M', u'سجى'), + (0xFD5F, 'M', u'سمح'), + (0xFD61, 'M', u'سمج'), + (0xFD62, 'M', u'سمم'), + (0xFD64, 'M', u'صحح'), + (0xFD66, 'M', u'صمم'), + (0xFD67, 'M', u'شحم'), + (0xFD69, 'M', u'شجي'), + (0xFD6A, 'M', u'شمخ'), + (0xFD6C, 'M', u'شمم'), + (0xFD6E, 'M', u'ضحى'), + (0xFD6F, 'M', u'ضخم'), + (0xFD71, 'M', u'طمح'), + (0xFD73, 'M', u'طمم'), + (0xFD74, 'M', u'طمي'), + (0xFD75, 'M', u'عجم'), + (0xFD76, 'M', u'عمم'), + (0xFD78, 'M', u'عمى'), + (0xFD79, 'M', u'غمم'), + (0xFD7A, 'M', u'غمي'), + (0xFD7B, 'M', u'غمى'), + (0xFD7C, 'M', u'فخم'), + (0xFD7E, 'M', u'قمح'), + (0xFD7F, 'M', u'قمم'), + (0xFD80, 'M', u'لحم'), + (0xFD81, 'M', u'لحي'), + (0xFD82, 'M', u'لحى'), + (0xFD83, 'M', u'لجج'), + (0xFD85, 'M', u'لخم'), + (0xFD87, 'M', u'لمح'), + (0xFD89, 'M', u'محج'), + (0xFD8A, 'M', u'محم'), + (0xFD8B, 'M', u'محي'), + (0xFD8C, 'M', u'مجح'), + (0xFD8D, 'M', u'مجم'), + (0xFD8E, 'M', u'مخج'), + (0xFD8F, 'M', u'مخم'), + (0xFD90, 'X'), + (0xFD92, 'M', u'مجخ'), + (0xFD93, 'M', u'همج'), + (0xFD94, 'M', u'همم'), + (0xFD95, 'M', u'نحم'), + (0xFD96, 'M', u'نحى'), + (0xFD97, 'M', u'نجم'), + (0xFD99, 'M', u'نجى'), + (0xFD9A, 'M', u'نمي'), + (0xFD9B, 'M', u'نمى'), + (0xFD9C, 'M', u'يمم'), + (0xFD9E, 'M', u'بخي'), + (0xFD9F, 'M', u'تجي'), + (0xFDA0, 'M', u'تجى'), + (0xFDA1, 'M', u'تخي'), + (0xFDA2, 'M', u'تخى'), + (0xFDA3, 'M', u'تمي'), + (0xFDA4, 'M', u'تمى'), + (0xFDA5, 'M', u'جمي'), + (0xFDA6, 'M', u'جحى'), + (0xFDA7, 'M', u'جمى'), + (0xFDA8, 'M', u'سخى'), + (0xFDA9, 'M', u'صحي'), + (0xFDAA, 'M', u'شحي'), + (0xFDAB, 'M', u'ضحي'), + (0xFDAC, 'M', u'لجي'), + (0xFDAD, 'M', u'لمي'), + (0xFDAE, 'M', u'يحي'), + (0xFDAF, 'M', u'يجي'), + (0xFDB0, 'M', u'يمي'), + (0xFDB1, 'M', u'ممي'), + (0xFDB2, 'M', u'قمي'), + (0xFDB3, 'M', u'نحي'), + (0xFDB4, 'M', u'قمح'), + (0xFDB5, 'M', u'لحم'), + (0xFDB6, 'M', u'عمي'), + (0xFDB7, 'M', u'كمي'), + (0xFDB8, 'M', u'نجح'), + (0xFDB9, 'M', u'مخي'), + (0xFDBA, 'M', u'لجم'), + (0xFDBB, 'M', u'كمم'), + (0xFDBC, 'M', u'لجم'), + (0xFDBD, 'M', u'نجح'), + (0xFDBE, 'M', u'جحي'), + (0xFDBF, 'M', u'حجي'), + (0xFDC0, 'M', u'مجي'), + (0xFDC1, 'M', u'فمي'), + (0xFDC2, 'M', u'بحي'), + (0xFDC3, 'M', u'كمم'), + (0xFDC4, 'M', u'عجم'), + (0xFDC5, 'M', u'صمم'), + (0xFDC6, 'M', u'سخي'), + (0xFDC7, 'M', u'نجي'), + (0xFDC8, 'X'), + (0xFDF0, 'M', u'صلے'), + (0xFDF1, 'M', u'قلے'), + (0xFDF2, 'M', u'الله'), + (0xFDF3, 'M', u'اكبر'), + (0xFDF4, 'M', u'محمد'), + (0xFDF5, 'M', u'صلعم'), + ] + +def _seg_49(): + return [ + (0xFDF6, 'M', u'رسول'), + (0xFDF7, 'M', u'عليه'), + (0xFDF8, 'M', u'وسلم'), + (0xFDF9, 'M', u'صلى'), + (0xFDFA, '3', u'صلى الله عليه وسلم'), + (0xFDFB, '3', u'جل جلاله'), + (0xFDFC, 'M', u'ریال'), + (0xFDFD, 'V'), + (0xFDFE, 'X'), + (0xFE00, 'I'), + (0xFE10, '3', u','), + (0xFE11, 'M', u'、'), + (0xFE12, 'X'), + (0xFE13, '3', u':'), + (0xFE14, '3', u';'), + (0xFE15, '3', u'!'), + (0xFE16, '3', u'?'), + (0xFE17, 'M', u'〖'), + (0xFE18, 'M', u'〗'), + (0xFE19, 'X'), + (0xFE20, 'V'), + (0xFE30, 'X'), + (0xFE31, 'M', u'—'), + (0xFE32, 'M', u'–'), + (0xFE33, '3', u'_'), + (0xFE35, '3', u'('), + (0xFE36, '3', u')'), + (0xFE37, '3', u'{'), + (0xFE38, '3', u'}'), + (0xFE39, 'M', u'〔'), + (0xFE3A, 'M', u'〕'), + (0xFE3B, 'M', u'【'), + (0xFE3C, 'M', u'】'), + (0xFE3D, 'M', u'《'), + (0xFE3E, 'M', u'》'), + (0xFE3F, 'M', u'〈'), + (0xFE40, 'M', u'〉'), + (0xFE41, 'M', u'「'), + (0xFE42, 'M', u'」'), + (0xFE43, 'M', u'『'), + (0xFE44, 'M', u'』'), + (0xFE45, 'V'), + (0xFE47, '3', u'['), + (0xFE48, '3', u']'), + (0xFE49, '3', u' ̅'), + (0xFE4D, '3', u'_'), + (0xFE50, '3', u','), + (0xFE51, 'M', u'、'), + (0xFE52, 'X'), + (0xFE54, '3', u';'), + (0xFE55, '3', u':'), + (0xFE56, '3', u'?'), + (0xFE57, '3', u'!'), + (0xFE58, 'M', u'—'), + (0xFE59, '3', u'('), + (0xFE5A, '3', u')'), + (0xFE5B, '3', u'{'), + (0xFE5C, '3', u'}'), + (0xFE5D, 'M', u'〔'), + (0xFE5E, 'M', u'〕'), + (0xFE5F, '3', u'#'), + (0xFE60, '3', u'&'), + (0xFE61, '3', u'*'), + (0xFE62, '3', u'+'), + (0xFE63, 'M', u'-'), + (0xFE64, '3', u'<'), + (0xFE65, '3', u'>'), + (0xFE66, '3', u'='), + (0xFE67, 'X'), + (0xFE68, '3', u'\\'), + (0xFE69, '3', u'$'), + (0xFE6A, '3', u'%'), + (0xFE6B, '3', u'@'), + (0xFE6C, 'X'), + (0xFE70, '3', u' ً'), + (0xFE71, 'M', u'ـً'), + (0xFE72, '3', u' ٌ'), + (0xFE73, 'V'), + (0xFE74, '3', u' ٍ'), + (0xFE75, 'X'), + (0xFE76, '3', u' َ'), + (0xFE77, 'M', u'ـَ'), + (0xFE78, '3', u' ُ'), + (0xFE79, 'M', u'ـُ'), + (0xFE7A, '3', u' ِ'), + (0xFE7B, 'M', u'ـِ'), + (0xFE7C, '3', u' ّ'), + (0xFE7D, 'M', u'ـّ'), + (0xFE7E, '3', u' ْ'), + (0xFE7F, 'M', u'ـْ'), + (0xFE80, 'M', u'ء'), + (0xFE81, 'M', u'آ'), + (0xFE83, 'M', u'أ'), + (0xFE85, 'M', u'ؤ'), + (0xFE87, 'M', u'إ'), + (0xFE89, 'M', u'ئ'), + (0xFE8D, 'M', u'ا'), + (0xFE8F, 'M', u'ب'), + (0xFE93, 'M', u'ة'), + (0xFE95, 'M', u'ت'), + ] + +def _seg_50(): + return [ + (0xFE99, 'M', u'ث'), + (0xFE9D, 'M', u'ج'), + (0xFEA1, 'M', u'ح'), + (0xFEA5, 'M', u'خ'), + (0xFEA9, 'M', u'د'), + (0xFEAB, 'M', u'ذ'), + (0xFEAD, 'M', u'ر'), + (0xFEAF, 'M', u'ز'), + (0xFEB1, 'M', u'س'), + (0xFEB5, 'M', u'ش'), + (0xFEB9, 'M', u'ص'), + (0xFEBD, 'M', u'ض'), + (0xFEC1, 'M', u'ط'), + (0xFEC5, 'M', u'ظ'), + (0xFEC9, 'M', u'ع'), + (0xFECD, 'M', u'غ'), + (0xFED1, 'M', u'ف'), + (0xFED5, 'M', u'ق'), + (0xFED9, 'M', u'ك'), + (0xFEDD, 'M', u'ل'), + (0xFEE1, 'M', u'م'), + (0xFEE5, 'M', u'ن'), + (0xFEE9, 'M', u'ه'), + (0xFEED, 'M', u'و'), + (0xFEEF, 'M', u'ى'), + (0xFEF1, 'M', u'ي'), + (0xFEF5, 'M', u'لآ'), + (0xFEF7, 'M', u'لأ'), + (0xFEF9, 'M', u'لإ'), + (0xFEFB, 'M', u'لا'), + (0xFEFD, 'X'), + (0xFEFF, 'I'), + (0xFF00, 'X'), + (0xFF01, '3', u'!'), + (0xFF02, '3', u'"'), + (0xFF03, '3', u'#'), + (0xFF04, '3', u'$'), + (0xFF05, '3', u'%'), + (0xFF06, '3', u'&'), + (0xFF07, '3', u'\''), + (0xFF08, '3', u'('), + (0xFF09, '3', u')'), + (0xFF0A, '3', u'*'), + (0xFF0B, '3', u'+'), + (0xFF0C, '3', u','), + (0xFF0D, 'M', u'-'), + (0xFF0E, 'M', u'.'), + (0xFF0F, '3', u'/'), + (0xFF10, 'M', u'0'), + (0xFF11, 'M', u'1'), + (0xFF12, 'M', u'2'), + (0xFF13, 'M', u'3'), + (0xFF14, 'M', u'4'), + (0xFF15, 'M', u'5'), + (0xFF16, 'M', u'6'), + (0xFF17, 'M', u'7'), + (0xFF18, 'M', u'8'), + (0xFF19, 'M', u'9'), + (0xFF1A, '3', u':'), + (0xFF1B, '3', u';'), + (0xFF1C, '3', u'<'), + (0xFF1D, '3', u'='), + (0xFF1E, '3', u'>'), + (0xFF1F, '3', u'?'), + (0xFF20, '3', u'@'), + (0xFF21, 'M', u'a'), + (0xFF22, 'M', u'b'), + (0xFF23, 'M', u'c'), + (0xFF24, 'M', u'd'), + (0xFF25, 'M', u'e'), + (0xFF26, 'M', u'f'), + (0xFF27, 'M', u'g'), + (0xFF28, 'M', u'h'), + (0xFF29, 'M', u'i'), + (0xFF2A, 'M', u'j'), + (0xFF2B, 'M', u'k'), + (0xFF2C, 'M', u'l'), + (0xFF2D, 'M', u'm'), + (0xFF2E, 'M', u'n'), + (0xFF2F, 'M', u'o'), + (0xFF30, 'M', u'p'), + (0xFF31, 'M', u'q'), + (0xFF32, 'M', u'r'), + (0xFF33, 'M', u's'), + (0xFF34, 'M', u't'), + (0xFF35, 'M', u'u'), + (0xFF36, 'M', u'v'), + (0xFF37, 'M', u'w'), + (0xFF38, 'M', u'x'), + (0xFF39, 'M', u'y'), + (0xFF3A, 'M', u'z'), + (0xFF3B, '3', u'['), + (0xFF3C, '3', u'\\'), + (0xFF3D, '3', u']'), + (0xFF3E, '3', u'^'), + (0xFF3F, '3', u'_'), + (0xFF40, '3', u'`'), + (0xFF41, 'M', u'a'), + (0xFF42, 'M', u'b'), + (0xFF43, 'M', u'c'), + ] + +def _seg_51(): + return [ + (0xFF44, 'M', u'd'), + (0xFF45, 'M', u'e'), + (0xFF46, 'M', u'f'), + (0xFF47, 'M', u'g'), + (0xFF48, 'M', u'h'), + (0xFF49, 'M', u'i'), + (0xFF4A, 'M', u'j'), + (0xFF4B, 'M', u'k'), + (0xFF4C, 'M', u'l'), + (0xFF4D, 'M', u'm'), + (0xFF4E, 'M', u'n'), + (0xFF4F, 'M', u'o'), + (0xFF50, 'M', u'p'), + (0xFF51, 'M', u'q'), + (0xFF52, 'M', u'r'), + (0xFF53, 'M', u's'), + (0xFF54, 'M', u't'), + (0xFF55, 'M', u'u'), + (0xFF56, 'M', u'v'), + (0xFF57, 'M', u'w'), + (0xFF58, 'M', u'x'), + (0xFF59, 'M', u'y'), + (0xFF5A, 'M', u'z'), + (0xFF5B, '3', u'{'), + (0xFF5C, '3', u'|'), + (0xFF5D, '3', u'}'), + (0xFF5E, '3', u'~'), + (0xFF5F, 'M', u'⦅'), + (0xFF60, 'M', u'⦆'), + (0xFF61, 'M', u'.'), + (0xFF62, 'M', u'「'), + (0xFF63, 'M', u'」'), + (0xFF64, 'M', u'、'), + (0xFF65, 'M', u'・'), + (0xFF66, 'M', u'ヲ'), + (0xFF67, 'M', u'ァ'), + (0xFF68, 'M', u'ィ'), + (0xFF69, 'M', u'ゥ'), + (0xFF6A, 'M', u'ェ'), + (0xFF6B, 'M', u'ォ'), + (0xFF6C, 'M', u'ャ'), + (0xFF6D, 'M', u'ュ'), + (0xFF6E, 'M', u'ョ'), + (0xFF6F, 'M', u'ッ'), + (0xFF70, 'M', u'ー'), + (0xFF71, 'M', u'ア'), + (0xFF72, 'M', u'イ'), + (0xFF73, 'M', u'ウ'), + (0xFF74, 'M', u'エ'), + (0xFF75, 'M', u'オ'), + (0xFF76, 'M', u'カ'), + (0xFF77, 'M', u'キ'), + (0xFF78, 'M', u'ク'), + (0xFF79, 'M', u'ケ'), + (0xFF7A, 'M', u'コ'), + (0xFF7B, 'M', u'サ'), + (0xFF7C, 'M', u'シ'), + (0xFF7D, 'M', u'ス'), + (0xFF7E, 'M', u'セ'), + (0xFF7F, 'M', u'ソ'), + (0xFF80, 'M', u'タ'), + (0xFF81, 'M', u'チ'), + (0xFF82, 'M', u'ツ'), + (0xFF83, 'M', u'テ'), + (0xFF84, 'M', u'ト'), + (0xFF85, 'M', u'ナ'), + (0xFF86, 'M', u'ニ'), + (0xFF87, 'M', u'ヌ'), + (0xFF88, 'M', u'ネ'), + (0xFF89, 'M', u'ノ'), + (0xFF8A, 'M', u'ハ'), + (0xFF8B, 'M', u'ヒ'), + (0xFF8C, 'M', u'フ'), + (0xFF8D, 'M', u'ヘ'), + (0xFF8E, 'M', u'ホ'), + (0xFF8F, 'M', u'マ'), + (0xFF90, 'M', u'ミ'), + (0xFF91, 'M', u'ム'), + (0xFF92, 'M', u'メ'), + (0xFF93, 'M', u'モ'), + (0xFF94, 'M', u'ヤ'), + (0xFF95, 'M', u'ユ'), + (0xFF96, 'M', u'ヨ'), + (0xFF97, 'M', u'ラ'), + (0xFF98, 'M', u'リ'), + (0xFF99, 'M', u'ル'), + (0xFF9A, 'M', u'レ'), + (0xFF9B, 'M', u'ロ'), + (0xFF9C, 'M', u'ワ'), + (0xFF9D, 'M', u'ン'), + (0xFF9E, 'M', u'゙'), + (0xFF9F, 'M', u'゚'), + (0xFFA0, 'X'), + (0xFFA1, 'M', u'ᄀ'), + (0xFFA2, 'M', u'ᄁ'), + (0xFFA3, 'M', u'ᆪ'), + (0xFFA4, 'M', u'ᄂ'), + (0xFFA5, 'M', u'ᆬ'), + (0xFFA6, 'M', u'ᆭ'), + (0xFFA7, 'M', u'ᄃ'), + ] + +def _seg_52(): + return [ + (0xFFA8, 'M', u'ᄄ'), + (0xFFA9, 'M', u'ᄅ'), + (0xFFAA, 'M', u'ᆰ'), + (0xFFAB, 'M', u'ᆱ'), + (0xFFAC, 'M', u'ᆲ'), + (0xFFAD, 'M', u'ᆳ'), + (0xFFAE, 'M', u'ᆴ'), + (0xFFAF, 'M', u'ᆵ'), + (0xFFB0, 'M', u'ᄚ'), + (0xFFB1, 'M', u'ᄆ'), + (0xFFB2, 'M', u'ᄇ'), + (0xFFB3, 'M', u'ᄈ'), + (0xFFB4, 'M', u'ᄡ'), + (0xFFB5, 'M', u'ᄉ'), + (0xFFB6, 'M', u'ᄊ'), + (0xFFB7, 'M', u'ᄋ'), + (0xFFB8, 'M', u'ᄌ'), + (0xFFB9, 'M', u'ᄍ'), + (0xFFBA, 'M', u'ᄎ'), + (0xFFBB, 'M', u'ᄏ'), + (0xFFBC, 'M', u'ᄐ'), + (0xFFBD, 'M', u'ᄑ'), + (0xFFBE, 'M', u'ᄒ'), + (0xFFBF, 'X'), + (0xFFC2, 'M', u'ᅡ'), + (0xFFC3, 'M', u'ᅢ'), + (0xFFC4, 'M', u'ᅣ'), + (0xFFC5, 'M', u'ᅤ'), + (0xFFC6, 'M', u'ᅥ'), + (0xFFC7, 'M', u'ᅦ'), + (0xFFC8, 'X'), + (0xFFCA, 'M', u'ᅧ'), + (0xFFCB, 'M', u'ᅨ'), + (0xFFCC, 'M', u'ᅩ'), + (0xFFCD, 'M', u'ᅪ'), + (0xFFCE, 'M', u'ᅫ'), + (0xFFCF, 'M', u'ᅬ'), + (0xFFD0, 'X'), + (0xFFD2, 'M', u'ᅭ'), + (0xFFD3, 'M', u'ᅮ'), + (0xFFD4, 'M', u'ᅯ'), + (0xFFD5, 'M', u'ᅰ'), + (0xFFD6, 'M', u'ᅱ'), + (0xFFD7, 'M', u'ᅲ'), + (0xFFD8, 'X'), + (0xFFDA, 'M', u'ᅳ'), + (0xFFDB, 'M', u'ᅴ'), + (0xFFDC, 'M', u'ᅵ'), + (0xFFDD, 'X'), + (0xFFE0, 'M', u'¢'), + (0xFFE1, 'M', u'£'), + (0xFFE2, 'M', u'¬'), + (0xFFE3, '3', u' ̄'), + (0xFFE4, 'M', u'¦'), + (0xFFE5, 'M', u'¥'), + (0xFFE6, 'M', u'₩'), + (0xFFE7, 'X'), + (0xFFE8, 'M', u'│'), + (0xFFE9, 'M', u'←'), + (0xFFEA, 'M', u'↑'), + (0xFFEB, 'M', u'→'), + (0xFFEC, 'M', u'↓'), + (0xFFED, 'M', u'■'), + (0xFFEE, 'M', u'○'), + (0xFFEF, 'X'), + (0x10000, 'V'), + (0x1000C, 'X'), + (0x1000D, 'V'), + (0x10027, 'X'), + (0x10028, 'V'), + (0x1003B, 'X'), + (0x1003C, 'V'), + (0x1003E, 'X'), + (0x1003F, 'V'), + (0x1004E, 'X'), + (0x10050, 'V'), + (0x1005E, 'X'), + (0x10080, 'V'), + (0x100FB, 'X'), + (0x10100, 'V'), + (0x10103, 'X'), + (0x10107, 'V'), + (0x10134, 'X'), + (0x10137, 'V'), + (0x1018F, 'X'), + (0x10190, 'V'), + (0x1019C, 'X'), + (0x101A0, 'V'), + (0x101A1, 'X'), + (0x101D0, 'V'), + (0x101FE, 'X'), + (0x10280, 'V'), + (0x1029D, 'X'), + (0x102A0, 'V'), + (0x102D1, 'X'), + (0x102E0, 'V'), + (0x102FC, 'X'), + (0x10300, 'V'), + (0x10324, 'X'), + (0x1032D, 'V'), + ] + +def _seg_53(): + return [ + (0x1034B, 'X'), + (0x10350, 'V'), + (0x1037B, 'X'), + (0x10380, 'V'), + (0x1039E, 'X'), + (0x1039F, 'V'), + (0x103C4, 'X'), + (0x103C8, 'V'), + (0x103D6, 'X'), + (0x10400, 'M', u'𐐨'), + (0x10401, 'M', u'𐐩'), + (0x10402, 'M', u'𐐪'), + (0x10403, 'M', u'𐐫'), + (0x10404, 'M', u'𐐬'), + (0x10405, 'M', u'𐐭'), + (0x10406, 'M', u'𐐮'), + (0x10407, 'M', u'𐐯'), + (0x10408, 'M', u'𐐰'), + (0x10409, 'M', u'𐐱'), + (0x1040A, 'M', u'𐐲'), + (0x1040B, 'M', u'𐐳'), + (0x1040C, 'M', u'𐐴'), + (0x1040D, 'M', u'𐐵'), + (0x1040E, 'M', u'𐐶'), + (0x1040F, 'M', u'𐐷'), + (0x10410, 'M', u'𐐸'), + (0x10411, 'M', u'𐐹'), + (0x10412, 'M', u'𐐺'), + (0x10413, 'M', u'𐐻'), + (0x10414, 'M', u'𐐼'), + (0x10415, 'M', u'𐐽'), + (0x10416, 'M', u'𐐾'), + (0x10417, 'M', u'𐐿'), + (0x10418, 'M', u'𐑀'), + (0x10419, 'M', u'𐑁'), + (0x1041A, 'M', u'𐑂'), + (0x1041B, 'M', u'𐑃'), + (0x1041C, 'M', u'𐑄'), + (0x1041D, 'M', u'𐑅'), + (0x1041E, 'M', u'𐑆'), + (0x1041F, 'M', u'𐑇'), + (0x10420, 'M', u'𐑈'), + (0x10421, 'M', u'𐑉'), + (0x10422, 'M', u'𐑊'), + (0x10423, 'M', u'𐑋'), + (0x10424, 'M', u'𐑌'), + (0x10425, 'M', u'𐑍'), + (0x10426, 'M', u'𐑎'), + (0x10427, 'M', u'𐑏'), + (0x10428, 'V'), + (0x1049E, 'X'), + (0x104A0, 'V'), + (0x104AA, 'X'), + (0x104B0, 'M', u'𐓘'), + (0x104B1, 'M', u'𐓙'), + (0x104B2, 'M', u'𐓚'), + (0x104B3, 'M', u'𐓛'), + (0x104B4, 'M', u'𐓜'), + (0x104B5, 'M', u'𐓝'), + (0x104B6, 'M', u'𐓞'), + (0x104B7, 'M', u'𐓟'), + (0x104B8, 'M', u'𐓠'), + (0x104B9, 'M', u'𐓡'), + (0x104BA, 'M', u'𐓢'), + (0x104BB, 'M', u'𐓣'), + (0x104BC, 'M', u'𐓤'), + (0x104BD, 'M', u'𐓥'), + (0x104BE, 'M', u'𐓦'), + (0x104BF, 'M', u'𐓧'), + (0x104C0, 'M', u'𐓨'), + (0x104C1, 'M', u'𐓩'), + (0x104C2, 'M', u'𐓪'), + (0x104C3, 'M', u'𐓫'), + (0x104C4, 'M', u'𐓬'), + (0x104C5, 'M', u'𐓭'), + (0x104C6, 'M', u'𐓮'), + (0x104C7, 'M', u'𐓯'), + (0x104C8, 'M', u'𐓰'), + (0x104C9, 'M', u'𐓱'), + (0x104CA, 'M', u'𐓲'), + (0x104CB, 'M', u'𐓳'), + (0x104CC, 'M', u'𐓴'), + (0x104CD, 'M', u'𐓵'), + (0x104CE, 'M', u'𐓶'), + (0x104CF, 'M', u'𐓷'), + (0x104D0, 'M', u'𐓸'), + (0x104D1, 'M', u'𐓹'), + (0x104D2, 'M', u'𐓺'), + (0x104D3, 'M', u'𐓻'), + (0x104D4, 'X'), + (0x104D8, 'V'), + (0x104FC, 'X'), + (0x10500, 'V'), + (0x10528, 'X'), + (0x10530, 'V'), + (0x10564, 'X'), + (0x1056F, 'V'), + (0x10570, 'X'), + (0x10600, 'V'), + (0x10737, 'X'), + ] + +def _seg_54(): + return [ + (0x10740, 'V'), + (0x10756, 'X'), + (0x10760, 'V'), + (0x10768, 'X'), + (0x10800, 'V'), + (0x10806, 'X'), + (0x10808, 'V'), + (0x10809, 'X'), + (0x1080A, 'V'), + (0x10836, 'X'), + (0x10837, 'V'), + (0x10839, 'X'), + (0x1083C, 'V'), + (0x1083D, 'X'), + (0x1083F, 'V'), + (0x10856, 'X'), + (0x10857, 'V'), + (0x1089F, 'X'), + (0x108A7, 'V'), + (0x108B0, 'X'), + (0x108E0, 'V'), + (0x108F3, 'X'), + (0x108F4, 'V'), + (0x108F6, 'X'), + (0x108FB, 'V'), + (0x1091C, 'X'), + (0x1091F, 'V'), + (0x1093A, 'X'), + (0x1093F, 'V'), + (0x10940, 'X'), + (0x10980, 'V'), + (0x109B8, 'X'), + (0x109BC, 'V'), + (0x109D0, 'X'), + (0x109D2, 'V'), + (0x10A04, 'X'), + (0x10A05, 'V'), + (0x10A07, 'X'), + (0x10A0C, 'V'), + (0x10A14, 'X'), + (0x10A15, 'V'), + (0x10A18, 'X'), + (0x10A19, 'V'), + (0x10A34, 'X'), + (0x10A38, 'V'), + (0x10A3B, 'X'), + (0x10A3F, 'V'), + (0x10A48, 'X'), + (0x10A50, 'V'), + (0x10A59, 'X'), + (0x10A60, 'V'), + (0x10AA0, 'X'), + (0x10AC0, 'V'), + (0x10AE7, 'X'), + (0x10AEB, 'V'), + (0x10AF7, 'X'), + (0x10B00, 'V'), + (0x10B36, 'X'), + (0x10B39, 'V'), + (0x10B56, 'X'), + (0x10B58, 'V'), + (0x10B73, 'X'), + (0x10B78, 'V'), + (0x10B92, 'X'), + (0x10B99, 'V'), + (0x10B9D, 'X'), + (0x10BA9, 'V'), + (0x10BB0, 'X'), + (0x10C00, 'V'), + (0x10C49, 'X'), + (0x10C80, 'M', u'𐳀'), + (0x10C81, 'M', u'𐳁'), + (0x10C82, 'M', u'𐳂'), + (0x10C83, 'M', u'𐳃'), + (0x10C84, 'M', u'𐳄'), + (0x10C85, 'M', u'𐳅'), + (0x10C86, 'M', u'𐳆'), + (0x10C87, 'M', u'𐳇'), + (0x10C88, 'M', u'𐳈'), + (0x10C89, 'M', u'𐳉'), + (0x10C8A, 'M', u'𐳊'), + (0x10C8B, 'M', u'𐳋'), + (0x10C8C, 'M', u'𐳌'), + (0x10C8D, 'M', u'𐳍'), + (0x10C8E, 'M', u'𐳎'), + (0x10C8F, 'M', u'𐳏'), + (0x10C90, 'M', u'𐳐'), + (0x10C91, 'M', u'𐳑'), + (0x10C92, 'M', u'𐳒'), + (0x10C93, 'M', u'𐳓'), + (0x10C94, 'M', u'𐳔'), + (0x10C95, 'M', u'𐳕'), + (0x10C96, 'M', u'𐳖'), + (0x10C97, 'M', u'𐳗'), + (0x10C98, 'M', u'𐳘'), + (0x10C99, 'M', u'𐳙'), + (0x10C9A, 'M', u'𐳚'), + (0x10C9B, 'M', u'𐳛'), + (0x10C9C, 'M', u'𐳜'), + (0x10C9D, 'M', u'𐳝'), + ] + +def _seg_55(): + return [ + (0x10C9E, 'M', u'𐳞'), + (0x10C9F, 'M', u'𐳟'), + (0x10CA0, 'M', u'𐳠'), + (0x10CA1, 'M', u'𐳡'), + (0x10CA2, 'M', u'𐳢'), + (0x10CA3, 'M', u'𐳣'), + (0x10CA4, 'M', u'𐳤'), + (0x10CA5, 'M', u'𐳥'), + (0x10CA6, 'M', u'𐳦'), + (0x10CA7, 'M', u'𐳧'), + (0x10CA8, 'M', u'𐳨'), + (0x10CA9, 'M', u'𐳩'), + (0x10CAA, 'M', u'𐳪'), + (0x10CAB, 'M', u'𐳫'), + (0x10CAC, 'M', u'𐳬'), + (0x10CAD, 'M', u'𐳭'), + (0x10CAE, 'M', u'𐳮'), + (0x10CAF, 'M', u'𐳯'), + (0x10CB0, 'M', u'𐳰'), + (0x10CB1, 'M', u'𐳱'), + (0x10CB2, 'M', u'𐳲'), + (0x10CB3, 'X'), + (0x10CC0, 'V'), + (0x10CF3, 'X'), + (0x10CFA, 'V'), + (0x10D00, 'X'), + (0x10E60, 'V'), + (0x10E7F, 'X'), + (0x11000, 'V'), + (0x1104E, 'X'), + (0x11052, 'V'), + (0x11070, 'X'), + (0x1107F, 'V'), + (0x110BD, 'X'), + (0x110BE, 'V'), + (0x110C2, 'X'), + (0x110D0, 'V'), + (0x110E9, 'X'), + (0x110F0, 'V'), + (0x110FA, 'X'), + (0x11100, 'V'), + (0x11135, 'X'), + (0x11136, 'V'), + (0x11144, 'X'), + (0x11150, 'V'), + (0x11177, 'X'), + (0x11180, 'V'), + (0x111CE, 'X'), + (0x111D0, 'V'), + (0x111E0, 'X'), + (0x111E1, 'V'), + (0x111F5, 'X'), + (0x11200, 'V'), + (0x11212, 'X'), + (0x11213, 'V'), + (0x1123F, 'X'), + (0x11280, 'V'), + (0x11287, 'X'), + (0x11288, 'V'), + (0x11289, 'X'), + (0x1128A, 'V'), + (0x1128E, 'X'), + (0x1128F, 'V'), + (0x1129E, 'X'), + (0x1129F, 'V'), + (0x112AA, 'X'), + (0x112B0, 'V'), + (0x112EB, 'X'), + (0x112F0, 'V'), + (0x112FA, 'X'), + (0x11300, 'V'), + (0x11304, 'X'), + (0x11305, 'V'), + (0x1130D, 'X'), + (0x1130F, 'V'), + (0x11311, 'X'), + (0x11313, 'V'), + (0x11329, 'X'), + (0x1132A, 'V'), + (0x11331, 'X'), + (0x11332, 'V'), + (0x11334, 'X'), + (0x11335, 'V'), + (0x1133A, 'X'), + (0x1133C, 'V'), + (0x11345, 'X'), + (0x11347, 'V'), + (0x11349, 'X'), + (0x1134B, 'V'), + (0x1134E, 'X'), + (0x11350, 'V'), + (0x11351, 'X'), + (0x11357, 'V'), + (0x11358, 'X'), + (0x1135D, 'V'), + (0x11364, 'X'), + (0x11366, 'V'), + (0x1136D, 'X'), + (0x11370, 'V'), + (0x11375, 'X'), + ] + +def _seg_56(): + return [ + (0x11400, 'V'), + (0x1145A, 'X'), + (0x1145B, 'V'), + (0x1145C, 'X'), + (0x1145D, 'V'), + (0x1145E, 'X'), + (0x11480, 'V'), + (0x114C8, 'X'), + (0x114D0, 'V'), + (0x114DA, 'X'), + (0x11580, 'V'), + (0x115B6, 'X'), + (0x115B8, 'V'), + (0x115DE, 'X'), + (0x11600, 'V'), + (0x11645, 'X'), + (0x11650, 'V'), + (0x1165A, 'X'), + (0x11660, 'V'), + (0x1166D, 'X'), + (0x11680, 'V'), + (0x116B8, 'X'), + (0x116C0, 'V'), + (0x116CA, 'X'), + (0x11700, 'V'), + (0x1171A, 'X'), + (0x1171D, 'V'), + (0x1172C, 'X'), + (0x11730, 'V'), + (0x11740, 'X'), + (0x118A0, 'M', u'𑣀'), + (0x118A1, 'M', u'𑣁'), + (0x118A2, 'M', u'𑣂'), + (0x118A3, 'M', u'𑣃'), + (0x118A4, 'M', u'𑣄'), + (0x118A5, 'M', u'𑣅'), + (0x118A6, 'M', u'𑣆'), + (0x118A7, 'M', u'𑣇'), + (0x118A8, 'M', u'𑣈'), + (0x118A9, 'M', u'𑣉'), + (0x118AA, 'M', u'𑣊'), + (0x118AB, 'M', u'𑣋'), + (0x118AC, 'M', u'𑣌'), + (0x118AD, 'M', u'𑣍'), + (0x118AE, 'M', u'𑣎'), + (0x118AF, 'M', u'𑣏'), + (0x118B0, 'M', u'𑣐'), + (0x118B1, 'M', u'𑣑'), + (0x118B2, 'M', u'𑣒'), + (0x118B3, 'M', u'𑣓'), + (0x118B4, 'M', u'𑣔'), + (0x118B5, 'M', u'𑣕'), + (0x118B6, 'M', u'𑣖'), + (0x118B7, 'M', u'𑣗'), + (0x118B8, 'M', u'𑣘'), + (0x118B9, 'M', u'𑣙'), + (0x118BA, 'M', u'𑣚'), + (0x118BB, 'M', u'𑣛'), + (0x118BC, 'M', u'𑣜'), + (0x118BD, 'M', u'𑣝'), + (0x118BE, 'M', u'𑣞'), + (0x118BF, 'M', u'𑣟'), + (0x118C0, 'V'), + (0x118F3, 'X'), + (0x118FF, 'V'), + (0x11900, 'X'), + (0x11A00, 'V'), + (0x11A48, 'X'), + (0x11A50, 'V'), + (0x11A84, 'X'), + (0x11A86, 'V'), + (0x11A9D, 'X'), + (0x11A9E, 'V'), + (0x11AA3, 'X'), + (0x11AC0, 'V'), + (0x11AF9, 'X'), + (0x11C00, 'V'), + (0x11C09, 'X'), + (0x11C0A, 'V'), + (0x11C37, 'X'), + (0x11C38, 'V'), + (0x11C46, 'X'), + (0x11C50, 'V'), + (0x11C6D, 'X'), + (0x11C70, 'V'), + (0x11C90, 'X'), + (0x11C92, 'V'), + (0x11CA8, 'X'), + (0x11CA9, 'V'), + (0x11CB7, 'X'), + (0x11D00, 'V'), + (0x11D07, 'X'), + (0x11D08, 'V'), + (0x11D0A, 'X'), + (0x11D0B, 'V'), + (0x11D37, 'X'), + (0x11D3A, 'V'), + (0x11D3B, 'X'), + (0x11D3C, 'V'), + (0x11D3E, 'X'), + ] + +def _seg_57(): + return [ + (0x11D3F, 'V'), + (0x11D48, 'X'), + (0x11D50, 'V'), + (0x11D5A, 'X'), + (0x12000, 'V'), + (0x1239A, 'X'), + (0x12400, 'V'), + (0x1246F, 'X'), + (0x12470, 'V'), + (0x12475, 'X'), + (0x12480, 'V'), + (0x12544, 'X'), + (0x13000, 'V'), + (0x1342F, 'X'), + (0x14400, 'V'), + (0x14647, 'X'), + (0x16800, 'V'), + (0x16A39, 'X'), + (0x16A40, 'V'), + (0x16A5F, 'X'), + (0x16A60, 'V'), + (0x16A6A, 'X'), + (0x16A6E, 'V'), + (0x16A70, 'X'), + (0x16AD0, 'V'), + (0x16AEE, 'X'), + (0x16AF0, 'V'), + (0x16AF6, 'X'), + (0x16B00, 'V'), + (0x16B46, 'X'), + (0x16B50, 'V'), + (0x16B5A, 'X'), + (0x16B5B, 'V'), + (0x16B62, 'X'), + (0x16B63, 'V'), + (0x16B78, 'X'), + (0x16B7D, 'V'), + (0x16B90, 'X'), + (0x16F00, 'V'), + (0x16F45, 'X'), + (0x16F50, 'V'), + (0x16F7F, 'X'), + (0x16F8F, 'V'), + (0x16FA0, 'X'), + (0x16FE0, 'V'), + (0x16FE2, 'X'), + (0x17000, 'V'), + (0x187ED, 'X'), + (0x18800, 'V'), + (0x18AF3, 'X'), + (0x1B000, 'V'), + (0x1B11F, 'X'), + (0x1B170, 'V'), + (0x1B2FC, 'X'), + (0x1BC00, 'V'), + (0x1BC6B, 'X'), + (0x1BC70, 'V'), + (0x1BC7D, 'X'), + (0x1BC80, 'V'), + (0x1BC89, 'X'), + (0x1BC90, 'V'), + (0x1BC9A, 'X'), + (0x1BC9C, 'V'), + (0x1BCA0, 'I'), + (0x1BCA4, 'X'), + (0x1D000, 'V'), + (0x1D0F6, 'X'), + (0x1D100, 'V'), + (0x1D127, 'X'), + (0x1D129, 'V'), + (0x1D15E, 'M', u'𝅗𝅥'), + (0x1D15F, 'M', u'𝅘𝅥'), + (0x1D160, 'M', u'𝅘𝅥𝅮'), + (0x1D161, 'M', u'𝅘𝅥𝅯'), + (0x1D162, 'M', u'𝅘𝅥𝅰'), + (0x1D163, 'M', u'𝅘𝅥𝅱'), + (0x1D164, 'M', u'𝅘𝅥𝅲'), + (0x1D165, 'V'), + (0x1D173, 'X'), + (0x1D17B, 'V'), + (0x1D1BB, 'M', u'𝆹𝅥'), + (0x1D1BC, 'M', u'𝆺𝅥'), + (0x1D1BD, 'M', u'𝆹𝅥𝅮'), + (0x1D1BE, 'M', u'𝆺𝅥𝅮'), + (0x1D1BF, 'M', u'𝆹𝅥𝅯'), + (0x1D1C0, 'M', u'𝆺𝅥𝅯'), + (0x1D1C1, 'V'), + (0x1D1E9, 'X'), + (0x1D200, 'V'), + (0x1D246, 'X'), + (0x1D300, 'V'), + (0x1D357, 'X'), + (0x1D360, 'V'), + (0x1D372, 'X'), + (0x1D400, 'M', u'a'), + (0x1D401, 'M', u'b'), + (0x1D402, 'M', u'c'), + (0x1D403, 'M', u'd'), + (0x1D404, 'M', u'e'), + (0x1D405, 'M', u'f'), + ] + +def _seg_58(): + return [ + (0x1D406, 'M', u'g'), + (0x1D407, 'M', u'h'), + (0x1D408, 'M', u'i'), + (0x1D409, 'M', u'j'), + (0x1D40A, 'M', u'k'), + (0x1D40B, 'M', u'l'), + (0x1D40C, 'M', u'm'), + (0x1D40D, 'M', u'n'), + (0x1D40E, 'M', u'o'), + (0x1D40F, 'M', u'p'), + (0x1D410, 'M', u'q'), + (0x1D411, 'M', u'r'), + (0x1D412, 'M', u's'), + (0x1D413, 'M', u't'), + (0x1D414, 'M', u'u'), + (0x1D415, 'M', u'v'), + (0x1D416, 'M', u'w'), + (0x1D417, 'M', u'x'), + (0x1D418, 'M', u'y'), + (0x1D419, 'M', u'z'), + (0x1D41A, 'M', u'a'), + (0x1D41B, 'M', u'b'), + (0x1D41C, 'M', u'c'), + (0x1D41D, 'M', u'd'), + (0x1D41E, 'M', u'e'), + (0x1D41F, 'M', u'f'), + (0x1D420, 'M', u'g'), + (0x1D421, 'M', u'h'), + (0x1D422, 'M', u'i'), + (0x1D423, 'M', u'j'), + (0x1D424, 'M', u'k'), + (0x1D425, 'M', u'l'), + (0x1D426, 'M', u'm'), + (0x1D427, 'M', u'n'), + (0x1D428, 'M', u'o'), + (0x1D429, 'M', u'p'), + (0x1D42A, 'M', u'q'), + (0x1D42B, 'M', u'r'), + (0x1D42C, 'M', u's'), + (0x1D42D, 'M', u't'), + (0x1D42E, 'M', u'u'), + (0x1D42F, 'M', u'v'), + (0x1D430, 'M', u'w'), + (0x1D431, 'M', u'x'), + (0x1D432, 'M', u'y'), + (0x1D433, 'M', u'z'), + (0x1D434, 'M', u'a'), + (0x1D435, 'M', u'b'), + (0x1D436, 'M', u'c'), + (0x1D437, 'M', u'd'), + (0x1D438, 'M', u'e'), + (0x1D439, 'M', u'f'), + (0x1D43A, 'M', u'g'), + (0x1D43B, 'M', u'h'), + (0x1D43C, 'M', u'i'), + (0x1D43D, 'M', u'j'), + (0x1D43E, 'M', u'k'), + (0x1D43F, 'M', u'l'), + (0x1D440, 'M', u'm'), + (0x1D441, 'M', u'n'), + (0x1D442, 'M', u'o'), + (0x1D443, 'M', u'p'), + (0x1D444, 'M', u'q'), + (0x1D445, 'M', u'r'), + (0x1D446, 'M', u's'), + (0x1D447, 'M', u't'), + (0x1D448, 'M', u'u'), + (0x1D449, 'M', u'v'), + (0x1D44A, 'M', u'w'), + (0x1D44B, 'M', u'x'), + (0x1D44C, 'M', u'y'), + (0x1D44D, 'M', u'z'), + (0x1D44E, 'M', u'a'), + (0x1D44F, 'M', u'b'), + (0x1D450, 'M', u'c'), + (0x1D451, 'M', u'd'), + (0x1D452, 'M', u'e'), + (0x1D453, 'M', u'f'), + (0x1D454, 'M', u'g'), + (0x1D455, 'X'), + (0x1D456, 'M', u'i'), + (0x1D457, 'M', u'j'), + (0x1D458, 'M', u'k'), + (0x1D459, 'M', u'l'), + (0x1D45A, 'M', u'm'), + (0x1D45B, 'M', u'n'), + (0x1D45C, 'M', u'o'), + (0x1D45D, 'M', u'p'), + (0x1D45E, 'M', u'q'), + (0x1D45F, 'M', u'r'), + (0x1D460, 'M', u's'), + (0x1D461, 'M', u't'), + (0x1D462, 'M', u'u'), + (0x1D463, 'M', u'v'), + (0x1D464, 'M', u'w'), + (0x1D465, 'M', u'x'), + (0x1D466, 'M', u'y'), + (0x1D467, 'M', u'z'), + (0x1D468, 'M', u'a'), + (0x1D469, 'M', u'b'), + ] + +def _seg_59(): + return [ + (0x1D46A, 'M', u'c'), + (0x1D46B, 'M', u'd'), + (0x1D46C, 'M', u'e'), + (0x1D46D, 'M', u'f'), + (0x1D46E, 'M', u'g'), + (0x1D46F, 'M', u'h'), + (0x1D470, 'M', u'i'), + (0x1D471, 'M', u'j'), + (0x1D472, 'M', u'k'), + (0x1D473, 'M', u'l'), + (0x1D474, 'M', u'm'), + (0x1D475, 'M', u'n'), + (0x1D476, 'M', u'o'), + (0x1D477, 'M', u'p'), + (0x1D478, 'M', u'q'), + (0x1D479, 'M', u'r'), + (0x1D47A, 'M', u's'), + (0x1D47B, 'M', u't'), + (0x1D47C, 'M', u'u'), + (0x1D47D, 'M', u'v'), + (0x1D47E, 'M', u'w'), + (0x1D47F, 'M', u'x'), + (0x1D480, 'M', u'y'), + (0x1D481, 'M', u'z'), + (0x1D482, 'M', u'a'), + (0x1D483, 'M', u'b'), + (0x1D484, 'M', u'c'), + (0x1D485, 'M', u'd'), + (0x1D486, 'M', u'e'), + (0x1D487, 'M', u'f'), + (0x1D488, 'M', u'g'), + (0x1D489, 'M', u'h'), + (0x1D48A, 'M', u'i'), + (0x1D48B, 'M', u'j'), + (0x1D48C, 'M', u'k'), + (0x1D48D, 'M', u'l'), + (0x1D48E, 'M', u'm'), + (0x1D48F, 'M', u'n'), + (0x1D490, 'M', u'o'), + (0x1D491, 'M', u'p'), + (0x1D492, 'M', u'q'), + (0x1D493, 'M', u'r'), + (0x1D494, 'M', u's'), + (0x1D495, 'M', u't'), + (0x1D496, 'M', u'u'), + (0x1D497, 'M', u'v'), + (0x1D498, 'M', u'w'), + (0x1D499, 'M', u'x'), + (0x1D49A, 'M', u'y'), + (0x1D49B, 'M', u'z'), + (0x1D49C, 'M', u'a'), + (0x1D49D, 'X'), + (0x1D49E, 'M', u'c'), + (0x1D49F, 'M', u'd'), + (0x1D4A0, 'X'), + (0x1D4A2, 'M', u'g'), + (0x1D4A3, 'X'), + (0x1D4A5, 'M', u'j'), + (0x1D4A6, 'M', u'k'), + (0x1D4A7, 'X'), + (0x1D4A9, 'M', u'n'), + (0x1D4AA, 'M', u'o'), + (0x1D4AB, 'M', u'p'), + (0x1D4AC, 'M', u'q'), + (0x1D4AD, 'X'), + (0x1D4AE, 'M', u's'), + (0x1D4AF, 'M', u't'), + (0x1D4B0, 'M', u'u'), + (0x1D4B1, 'M', u'v'), + (0x1D4B2, 'M', u'w'), + (0x1D4B3, 'M', u'x'), + (0x1D4B4, 'M', u'y'), + (0x1D4B5, 'M', u'z'), + (0x1D4B6, 'M', u'a'), + (0x1D4B7, 'M', u'b'), + (0x1D4B8, 'M', u'c'), + (0x1D4B9, 'M', u'd'), + (0x1D4BA, 'X'), + (0x1D4BB, 'M', u'f'), + (0x1D4BC, 'X'), + (0x1D4BD, 'M', u'h'), + (0x1D4BE, 'M', u'i'), + (0x1D4BF, 'M', u'j'), + (0x1D4C0, 'M', u'k'), + (0x1D4C1, 'M', u'l'), + (0x1D4C2, 'M', u'm'), + (0x1D4C3, 'M', u'n'), + (0x1D4C4, 'X'), + (0x1D4C5, 'M', u'p'), + (0x1D4C6, 'M', u'q'), + (0x1D4C7, 'M', u'r'), + (0x1D4C8, 'M', u's'), + (0x1D4C9, 'M', u't'), + (0x1D4CA, 'M', u'u'), + (0x1D4CB, 'M', u'v'), + (0x1D4CC, 'M', u'w'), + (0x1D4CD, 'M', u'x'), + (0x1D4CE, 'M', u'y'), + (0x1D4CF, 'M', u'z'), + (0x1D4D0, 'M', u'a'), + ] + +def _seg_60(): + return [ + (0x1D4D1, 'M', u'b'), + (0x1D4D2, 'M', u'c'), + (0x1D4D3, 'M', u'd'), + (0x1D4D4, 'M', u'e'), + (0x1D4D5, 'M', u'f'), + (0x1D4D6, 'M', u'g'), + (0x1D4D7, 'M', u'h'), + (0x1D4D8, 'M', u'i'), + (0x1D4D9, 'M', u'j'), + (0x1D4DA, 'M', u'k'), + (0x1D4DB, 'M', u'l'), + (0x1D4DC, 'M', u'm'), + (0x1D4DD, 'M', u'n'), + (0x1D4DE, 'M', u'o'), + (0x1D4DF, 'M', u'p'), + (0x1D4E0, 'M', u'q'), + (0x1D4E1, 'M', u'r'), + (0x1D4E2, 'M', u's'), + (0x1D4E3, 'M', u't'), + (0x1D4E4, 'M', u'u'), + (0x1D4E5, 'M', u'v'), + (0x1D4E6, 'M', u'w'), + (0x1D4E7, 'M', u'x'), + (0x1D4E8, 'M', u'y'), + (0x1D4E9, 'M', u'z'), + (0x1D4EA, 'M', u'a'), + (0x1D4EB, 'M', u'b'), + (0x1D4EC, 'M', u'c'), + (0x1D4ED, 'M', u'd'), + (0x1D4EE, 'M', u'e'), + (0x1D4EF, 'M', u'f'), + (0x1D4F0, 'M', u'g'), + (0x1D4F1, 'M', u'h'), + (0x1D4F2, 'M', u'i'), + (0x1D4F3, 'M', u'j'), + (0x1D4F4, 'M', u'k'), + (0x1D4F5, 'M', u'l'), + (0x1D4F6, 'M', u'm'), + (0x1D4F7, 'M', u'n'), + (0x1D4F8, 'M', u'o'), + (0x1D4F9, 'M', u'p'), + (0x1D4FA, 'M', u'q'), + (0x1D4FB, 'M', u'r'), + (0x1D4FC, 'M', u's'), + (0x1D4FD, 'M', u't'), + (0x1D4FE, 'M', u'u'), + (0x1D4FF, 'M', u'v'), + (0x1D500, 'M', u'w'), + (0x1D501, 'M', u'x'), + (0x1D502, 'M', u'y'), + (0x1D503, 'M', u'z'), + (0x1D504, 'M', u'a'), + (0x1D505, 'M', u'b'), + (0x1D506, 'X'), + (0x1D507, 'M', u'd'), + (0x1D508, 'M', u'e'), + (0x1D509, 'M', u'f'), + (0x1D50A, 'M', u'g'), + (0x1D50B, 'X'), + (0x1D50D, 'M', u'j'), + (0x1D50E, 'M', u'k'), + (0x1D50F, 'M', u'l'), + (0x1D510, 'M', u'm'), + (0x1D511, 'M', u'n'), + (0x1D512, 'M', u'o'), + (0x1D513, 'M', u'p'), + (0x1D514, 'M', u'q'), + (0x1D515, 'X'), + (0x1D516, 'M', u's'), + (0x1D517, 'M', u't'), + (0x1D518, 'M', u'u'), + (0x1D519, 'M', u'v'), + (0x1D51A, 'M', u'w'), + (0x1D51B, 'M', u'x'), + (0x1D51C, 'M', u'y'), + (0x1D51D, 'X'), + (0x1D51E, 'M', u'a'), + (0x1D51F, 'M', u'b'), + (0x1D520, 'M', u'c'), + (0x1D521, 'M', u'd'), + (0x1D522, 'M', u'e'), + (0x1D523, 'M', u'f'), + (0x1D524, 'M', u'g'), + (0x1D525, 'M', u'h'), + (0x1D526, 'M', u'i'), + (0x1D527, 'M', u'j'), + (0x1D528, 'M', u'k'), + (0x1D529, 'M', u'l'), + (0x1D52A, 'M', u'm'), + (0x1D52B, 'M', u'n'), + (0x1D52C, 'M', u'o'), + (0x1D52D, 'M', u'p'), + (0x1D52E, 'M', u'q'), + (0x1D52F, 'M', u'r'), + (0x1D530, 'M', u's'), + (0x1D531, 'M', u't'), + (0x1D532, 'M', u'u'), + (0x1D533, 'M', u'v'), + (0x1D534, 'M', u'w'), + (0x1D535, 'M', u'x'), + ] + +def _seg_61(): + return [ + (0x1D536, 'M', u'y'), + (0x1D537, 'M', u'z'), + (0x1D538, 'M', u'a'), + (0x1D539, 'M', u'b'), + (0x1D53A, 'X'), + (0x1D53B, 'M', u'd'), + (0x1D53C, 'M', u'e'), + (0x1D53D, 'M', u'f'), + (0x1D53E, 'M', u'g'), + (0x1D53F, 'X'), + (0x1D540, 'M', u'i'), + (0x1D541, 'M', u'j'), + (0x1D542, 'M', u'k'), + (0x1D543, 'M', u'l'), + (0x1D544, 'M', u'm'), + (0x1D545, 'X'), + (0x1D546, 'M', u'o'), + (0x1D547, 'X'), + (0x1D54A, 'M', u's'), + (0x1D54B, 'M', u't'), + (0x1D54C, 'M', u'u'), + (0x1D54D, 'M', u'v'), + (0x1D54E, 'M', u'w'), + (0x1D54F, 'M', u'x'), + (0x1D550, 'M', u'y'), + (0x1D551, 'X'), + (0x1D552, 'M', u'a'), + (0x1D553, 'M', u'b'), + (0x1D554, 'M', u'c'), + (0x1D555, 'M', u'd'), + (0x1D556, 'M', u'e'), + (0x1D557, 'M', u'f'), + (0x1D558, 'M', u'g'), + (0x1D559, 'M', u'h'), + (0x1D55A, 'M', u'i'), + (0x1D55B, 'M', u'j'), + (0x1D55C, 'M', u'k'), + (0x1D55D, 'M', u'l'), + (0x1D55E, 'M', u'm'), + (0x1D55F, 'M', u'n'), + (0x1D560, 'M', u'o'), + (0x1D561, 'M', u'p'), + (0x1D562, 'M', u'q'), + (0x1D563, 'M', u'r'), + (0x1D564, 'M', u's'), + (0x1D565, 'M', u't'), + (0x1D566, 'M', u'u'), + (0x1D567, 'M', u'v'), + (0x1D568, 'M', u'w'), + (0x1D569, 'M', u'x'), + (0x1D56A, 'M', u'y'), + (0x1D56B, 'M', u'z'), + (0x1D56C, 'M', u'a'), + (0x1D56D, 'M', u'b'), + (0x1D56E, 'M', u'c'), + (0x1D56F, 'M', u'd'), + (0x1D570, 'M', u'e'), + (0x1D571, 'M', u'f'), + (0x1D572, 'M', u'g'), + (0x1D573, 'M', u'h'), + (0x1D574, 'M', u'i'), + (0x1D575, 'M', u'j'), + (0x1D576, 'M', u'k'), + (0x1D577, 'M', u'l'), + (0x1D578, 'M', u'm'), + (0x1D579, 'M', u'n'), + (0x1D57A, 'M', u'o'), + (0x1D57B, 'M', u'p'), + (0x1D57C, 'M', u'q'), + (0x1D57D, 'M', u'r'), + (0x1D57E, 'M', u's'), + (0x1D57F, 'M', u't'), + (0x1D580, 'M', u'u'), + (0x1D581, 'M', u'v'), + (0x1D582, 'M', u'w'), + (0x1D583, 'M', u'x'), + (0x1D584, 'M', u'y'), + (0x1D585, 'M', u'z'), + (0x1D586, 'M', u'a'), + (0x1D587, 'M', u'b'), + (0x1D588, 'M', u'c'), + (0x1D589, 'M', u'd'), + (0x1D58A, 'M', u'e'), + (0x1D58B, 'M', u'f'), + (0x1D58C, 'M', u'g'), + (0x1D58D, 'M', u'h'), + (0x1D58E, 'M', u'i'), + (0x1D58F, 'M', u'j'), + (0x1D590, 'M', u'k'), + (0x1D591, 'M', u'l'), + (0x1D592, 'M', u'm'), + (0x1D593, 'M', u'n'), + (0x1D594, 'M', u'o'), + (0x1D595, 'M', u'p'), + (0x1D596, 'M', u'q'), + (0x1D597, 'M', u'r'), + (0x1D598, 'M', u's'), + (0x1D599, 'M', u't'), + (0x1D59A, 'M', u'u'), + (0x1D59B, 'M', u'v'), + ] + +def _seg_62(): + return [ + (0x1D59C, 'M', u'w'), + (0x1D59D, 'M', u'x'), + (0x1D59E, 'M', u'y'), + (0x1D59F, 'M', u'z'), + (0x1D5A0, 'M', u'a'), + (0x1D5A1, 'M', u'b'), + (0x1D5A2, 'M', u'c'), + (0x1D5A3, 'M', u'd'), + (0x1D5A4, 'M', u'e'), + (0x1D5A5, 'M', u'f'), + (0x1D5A6, 'M', u'g'), + (0x1D5A7, 'M', u'h'), + (0x1D5A8, 'M', u'i'), + (0x1D5A9, 'M', u'j'), + (0x1D5AA, 'M', u'k'), + (0x1D5AB, 'M', u'l'), + (0x1D5AC, 'M', u'm'), + (0x1D5AD, 'M', u'n'), + (0x1D5AE, 'M', u'o'), + (0x1D5AF, 'M', u'p'), + (0x1D5B0, 'M', u'q'), + (0x1D5B1, 'M', u'r'), + (0x1D5B2, 'M', u's'), + (0x1D5B3, 'M', u't'), + (0x1D5B4, 'M', u'u'), + (0x1D5B5, 'M', u'v'), + (0x1D5B6, 'M', u'w'), + (0x1D5B7, 'M', u'x'), + (0x1D5B8, 'M', u'y'), + (0x1D5B9, 'M', u'z'), + (0x1D5BA, 'M', u'a'), + (0x1D5BB, 'M', u'b'), + (0x1D5BC, 'M', u'c'), + (0x1D5BD, 'M', u'd'), + (0x1D5BE, 'M', u'e'), + (0x1D5BF, 'M', u'f'), + (0x1D5C0, 'M', u'g'), + (0x1D5C1, 'M', u'h'), + (0x1D5C2, 'M', u'i'), + (0x1D5C3, 'M', u'j'), + (0x1D5C4, 'M', u'k'), + (0x1D5C5, 'M', u'l'), + (0x1D5C6, 'M', u'm'), + (0x1D5C7, 'M', u'n'), + (0x1D5C8, 'M', u'o'), + (0x1D5C9, 'M', u'p'), + (0x1D5CA, 'M', u'q'), + (0x1D5CB, 'M', u'r'), + (0x1D5CC, 'M', u's'), + (0x1D5CD, 'M', u't'), + (0x1D5CE, 'M', u'u'), + (0x1D5CF, 'M', u'v'), + (0x1D5D0, 'M', u'w'), + (0x1D5D1, 'M', u'x'), + (0x1D5D2, 'M', u'y'), + (0x1D5D3, 'M', u'z'), + (0x1D5D4, 'M', u'a'), + (0x1D5D5, 'M', u'b'), + (0x1D5D6, 'M', u'c'), + (0x1D5D7, 'M', u'd'), + (0x1D5D8, 'M', u'e'), + (0x1D5D9, 'M', u'f'), + (0x1D5DA, 'M', u'g'), + (0x1D5DB, 'M', u'h'), + (0x1D5DC, 'M', u'i'), + (0x1D5DD, 'M', u'j'), + (0x1D5DE, 'M', u'k'), + (0x1D5DF, 'M', u'l'), + (0x1D5E0, 'M', u'm'), + (0x1D5E1, 'M', u'n'), + (0x1D5E2, 'M', u'o'), + (0x1D5E3, 'M', u'p'), + (0x1D5E4, 'M', u'q'), + (0x1D5E5, 'M', u'r'), + (0x1D5E6, 'M', u's'), + (0x1D5E7, 'M', u't'), + (0x1D5E8, 'M', u'u'), + (0x1D5E9, 'M', u'v'), + (0x1D5EA, 'M', u'w'), + (0x1D5EB, 'M', u'x'), + (0x1D5EC, 'M', u'y'), + (0x1D5ED, 'M', u'z'), + (0x1D5EE, 'M', u'a'), + (0x1D5EF, 'M', u'b'), + (0x1D5F0, 'M', u'c'), + (0x1D5F1, 'M', u'd'), + (0x1D5F2, 'M', u'e'), + (0x1D5F3, 'M', u'f'), + (0x1D5F4, 'M', u'g'), + (0x1D5F5, 'M', u'h'), + (0x1D5F6, 'M', u'i'), + (0x1D5F7, 'M', u'j'), + (0x1D5F8, 'M', u'k'), + (0x1D5F9, 'M', u'l'), + (0x1D5FA, 'M', u'm'), + (0x1D5FB, 'M', u'n'), + (0x1D5FC, 'M', u'o'), + (0x1D5FD, 'M', u'p'), + (0x1D5FE, 'M', u'q'), + (0x1D5FF, 'M', u'r'), + ] + +def _seg_63(): + return [ + (0x1D600, 'M', u's'), + (0x1D601, 'M', u't'), + (0x1D602, 'M', u'u'), + (0x1D603, 'M', u'v'), + (0x1D604, 'M', u'w'), + (0x1D605, 'M', u'x'), + (0x1D606, 'M', u'y'), + (0x1D607, 'M', u'z'), + (0x1D608, 'M', u'a'), + (0x1D609, 'M', u'b'), + (0x1D60A, 'M', u'c'), + (0x1D60B, 'M', u'd'), + (0x1D60C, 'M', u'e'), + (0x1D60D, 'M', u'f'), + (0x1D60E, 'M', u'g'), + (0x1D60F, 'M', u'h'), + (0x1D610, 'M', u'i'), + (0x1D611, 'M', u'j'), + (0x1D612, 'M', u'k'), + (0x1D613, 'M', u'l'), + (0x1D614, 'M', u'm'), + (0x1D615, 'M', u'n'), + (0x1D616, 'M', u'o'), + (0x1D617, 'M', u'p'), + (0x1D618, 'M', u'q'), + (0x1D619, 'M', u'r'), + (0x1D61A, 'M', u's'), + (0x1D61B, 'M', u't'), + (0x1D61C, 'M', u'u'), + (0x1D61D, 'M', u'v'), + (0x1D61E, 'M', u'w'), + (0x1D61F, 'M', u'x'), + (0x1D620, 'M', u'y'), + (0x1D621, 'M', u'z'), + (0x1D622, 'M', u'a'), + (0x1D623, 'M', u'b'), + (0x1D624, 'M', u'c'), + (0x1D625, 'M', u'd'), + (0x1D626, 'M', u'e'), + (0x1D627, 'M', u'f'), + (0x1D628, 'M', u'g'), + (0x1D629, 'M', u'h'), + (0x1D62A, 'M', u'i'), + (0x1D62B, 'M', u'j'), + (0x1D62C, 'M', u'k'), + (0x1D62D, 'M', u'l'), + (0x1D62E, 'M', u'm'), + (0x1D62F, 'M', u'n'), + (0x1D630, 'M', u'o'), + (0x1D631, 'M', u'p'), + (0x1D632, 'M', u'q'), + (0x1D633, 'M', u'r'), + (0x1D634, 'M', u's'), + (0x1D635, 'M', u't'), + (0x1D636, 'M', u'u'), + (0x1D637, 'M', u'v'), + (0x1D638, 'M', u'w'), + (0x1D639, 'M', u'x'), + (0x1D63A, 'M', u'y'), + (0x1D63B, 'M', u'z'), + (0x1D63C, 'M', u'a'), + (0x1D63D, 'M', u'b'), + (0x1D63E, 'M', u'c'), + (0x1D63F, 'M', u'd'), + (0x1D640, 'M', u'e'), + (0x1D641, 'M', u'f'), + (0x1D642, 'M', u'g'), + (0x1D643, 'M', u'h'), + (0x1D644, 'M', u'i'), + (0x1D645, 'M', u'j'), + (0x1D646, 'M', u'k'), + (0x1D647, 'M', u'l'), + (0x1D648, 'M', u'm'), + (0x1D649, 'M', u'n'), + (0x1D64A, 'M', u'o'), + (0x1D64B, 'M', u'p'), + (0x1D64C, 'M', u'q'), + (0x1D64D, 'M', u'r'), + (0x1D64E, 'M', u's'), + (0x1D64F, 'M', u't'), + (0x1D650, 'M', u'u'), + (0x1D651, 'M', u'v'), + (0x1D652, 'M', u'w'), + (0x1D653, 'M', u'x'), + (0x1D654, 'M', u'y'), + (0x1D655, 'M', u'z'), + (0x1D656, 'M', u'a'), + (0x1D657, 'M', u'b'), + (0x1D658, 'M', u'c'), + (0x1D659, 'M', u'd'), + (0x1D65A, 'M', u'e'), + (0x1D65B, 'M', u'f'), + (0x1D65C, 'M', u'g'), + (0x1D65D, 'M', u'h'), + (0x1D65E, 'M', u'i'), + (0x1D65F, 'M', u'j'), + (0x1D660, 'M', u'k'), + (0x1D661, 'M', u'l'), + (0x1D662, 'M', u'm'), + (0x1D663, 'M', u'n'), + ] + +def _seg_64(): + return [ + (0x1D664, 'M', u'o'), + (0x1D665, 'M', u'p'), + (0x1D666, 'M', u'q'), + (0x1D667, 'M', u'r'), + (0x1D668, 'M', u's'), + (0x1D669, 'M', u't'), + (0x1D66A, 'M', u'u'), + (0x1D66B, 'M', u'v'), + (0x1D66C, 'M', u'w'), + (0x1D66D, 'M', u'x'), + (0x1D66E, 'M', u'y'), + (0x1D66F, 'M', u'z'), + (0x1D670, 'M', u'a'), + (0x1D671, 'M', u'b'), + (0x1D672, 'M', u'c'), + (0x1D673, 'M', u'd'), + (0x1D674, 'M', u'e'), + (0x1D675, 'M', u'f'), + (0x1D676, 'M', u'g'), + (0x1D677, 'M', u'h'), + (0x1D678, 'M', u'i'), + (0x1D679, 'M', u'j'), + (0x1D67A, 'M', u'k'), + (0x1D67B, 'M', u'l'), + (0x1D67C, 'M', u'm'), + (0x1D67D, 'M', u'n'), + (0x1D67E, 'M', u'o'), + (0x1D67F, 'M', u'p'), + (0x1D680, 'M', u'q'), + (0x1D681, 'M', u'r'), + (0x1D682, 'M', u's'), + (0x1D683, 'M', u't'), + (0x1D684, 'M', u'u'), + (0x1D685, 'M', u'v'), + (0x1D686, 'M', u'w'), + (0x1D687, 'M', u'x'), + (0x1D688, 'M', u'y'), + (0x1D689, 'M', u'z'), + (0x1D68A, 'M', u'a'), + (0x1D68B, 'M', u'b'), + (0x1D68C, 'M', u'c'), + (0x1D68D, 'M', u'd'), + (0x1D68E, 'M', u'e'), + (0x1D68F, 'M', u'f'), + (0x1D690, 'M', u'g'), + (0x1D691, 'M', u'h'), + (0x1D692, 'M', u'i'), + (0x1D693, 'M', u'j'), + (0x1D694, 'M', u'k'), + (0x1D695, 'M', u'l'), + (0x1D696, 'M', u'm'), + (0x1D697, 'M', u'n'), + (0x1D698, 'M', u'o'), + (0x1D699, 'M', u'p'), + (0x1D69A, 'M', u'q'), + (0x1D69B, 'M', u'r'), + (0x1D69C, 'M', u's'), + (0x1D69D, 'M', u't'), + (0x1D69E, 'M', u'u'), + (0x1D69F, 'M', u'v'), + (0x1D6A0, 'M', u'w'), + (0x1D6A1, 'M', u'x'), + (0x1D6A2, 'M', u'y'), + (0x1D6A3, 'M', u'z'), + (0x1D6A4, 'M', u'ı'), + (0x1D6A5, 'M', u'ȷ'), + (0x1D6A6, 'X'), + (0x1D6A8, 'M', u'α'), + (0x1D6A9, 'M', u'β'), + (0x1D6AA, 'M', u'γ'), + (0x1D6AB, 'M', u'δ'), + (0x1D6AC, 'M', u'ε'), + (0x1D6AD, 'M', u'ζ'), + (0x1D6AE, 'M', u'η'), + (0x1D6AF, 'M', u'θ'), + (0x1D6B0, 'M', u'ι'), + (0x1D6B1, 'M', u'κ'), + (0x1D6B2, 'M', u'λ'), + (0x1D6B3, 'M', u'μ'), + (0x1D6B4, 'M', u'ν'), + (0x1D6B5, 'M', u'ξ'), + (0x1D6B6, 'M', u'ο'), + (0x1D6B7, 'M', u'π'), + (0x1D6B8, 'M', u'ρ'), + (0x1D6B9, 'M', u'θ'), + (0x1D6BA, 'M', u'σ'), + (0x1D6BB, 'M', u'τ'), + (0x1D6BC, 'M', u'υ'), + (0x1D6BD, 'M', u'φ'), + (0x1D6BE, 'M', u'χ'), + (0x1D6BF, 'M', u'ψ'), + (0x1D6C0, 'M', u'ω'), + (0x1D6C1, 'M', u'∇'), + (0x1D6C2, 'M', u'α'), + (0x1D6C3, 'M', u'β'), + (0x1D6C4, 'M', u'γ'), + (0x1D6C5, 'M', u'δ'), + (0x1D6C6, 'M', u'ε'), + (0x1D6C7, 'M', u'ζ'), + (0x1D6C8, 'M', u'η'), + ] + +def _seg_65(): + return [ + (0x1D6C9, 'M', u'θ'), + (0x1D6CA, 'M', u'ι'), + (0x1D6CB, 'M', u'κ'), + (0x1D6CC, 'M', u'λ'), + (0x1D6CD, 'M', u'μ'), + (0x1D6CE, 'M', u'ν'), + (0x1D6CF, 'M', u'ξ'), + (0x1D6D0, 'M', u'ο'), + (0x1D6D1, 'M', u'π'), + (0x1D6D2, 'M', u'ρ'), + (0x1D6D3, 'M', u'σ'), + (0x1D6D5, 'M', u'τ'), + (0x1D6D6, 'M', u'υ'), + (0x1D6D7, 'M', u'φ'), + (0x1D6D8, 'M', u'χ'), + (0x1D6D9, 'M', u'ψ'), + (0x1D6DA, 'M', u'ω'), + (0x1D6DB, 'M', u'∂'), + (0x1D6DC, 'M', u'ε'), + (0x1D6DD, 'M', u'θ'), + (0x1D6DE, 'M', u'κ'), + (0x1D6DF, 'M', u'φ'), + (0x1D6E0, 'M', u'ρ'), + (0x1D6E1, 'M', u'π'), + (0x1D6E2, 'M', u'α'), + (0x1D6E3, 'M', u'β'), + (0x1D6E4, 'M', u'γ'), + (0x1D6E5, 'M', u'δ'), + (0x1D6E6, 'M', u'ε'), + (0x1D6E7, 'M', u'ζ'), + (0x1D6E8, 'M', u'η'), + (0x1D6E9, 'M', u'θ'), + (0x1D6EA, 'M', u'ι'), + (0x1D6EB, 'M', u'κ'), + (0x1D6EC, 'M', u'λ'), + (0x1D6ED, 'M', u'μ'), + (0x1D6EE, 'M', u'ν'), + (0x1D6EF, 'M', u'ξ'), + (0x1D6F0, 'M', u'ο'), + (0x1D6F1, 'M', u'π'), + (0x1D6F2, 'M', u'ρ'), + (0x1D6F3, 'M', u'θ'), + (0x1D6F4, 'M', u'σ'), + (0x1D6F5, 'M', u'τ'), + (0x1D6F6, 'M', u'υ'), + (0x1D6F7, 'M', u'φ'), + (0x1D6F8, 'M', u'χ'), + (0x1D6F9, 'M', u'ψ'), + (0x1D6FA, 'M', u'ω'), + (0x1D6FB, 'M', u'∇'), + (0x1D6FC, 'M', u'α'), + (0x1D6FD, 'M', u'β'), + (0x1D6FE, 'M', u'γ'), + (0x1D6FF, 'M', u'δ'), + (0x1D700, 'M', u'ε'), + (0x1D701, 'M', u'ζ'), + (0x1D702, 'M', u'η'), + (0x1D703, 'M', u'θ'), + (0x1D704, 'M', u'ι'), + (0x1D705, 'M', u'κ'), + (0x1D706, 'M', u'λ'), + (0x1D707, 'M', u'μ'), + (0x1D708, 'M', u'ν'), + (0x1D709, 'M', u'ξ'), + (0x1D70A, 'M', u'ο'), + (0x1D70B, 'M', u'π'), + (0x1D70C, 'M', u'ρ'), + (0x1D70D, 'M', u'σ'), + (0x1D70F, 'M', u'τ'), + (0x1D710, 'M', u'υ'), + (0x1D711, 'M', u'φ'), + (0x1D712, 'M', u'χ'), + (0x1D713, 'M', u'ψ'), + (0x1D714, 'M', u'ω'), + (0x1D715, 'M', u'∂'), + (0x1D716, 'M', u'ε'), + (0x1D717, 'M', u'θ'), + (0x1D718, 'M', u'κ'), + (0x1D719, 'M', u'φ'), + (0x1D71A, 'M', u'ρ'), + (0x1D71B, 'M', u'π'), + (0x1D71C, 'M', u'α'), + (0x1D71D, 'M', u'β'), + (0x1D71E, 'M', u'γ'), + (0x1D71F, 'M', u'δ'), + (0x1D720, 'M', u'ε'), + (0x1D721, 'M', u'ζ'), + (0x1D722, 'M', u'η'), + (0x1D723, 'M', u'θ'), + (0x1D724, 'M', u'ι'), + (0x1D725, 'M', u'κ'), + (0x1D726, 'M', u'λ'), + (0x1D727, 'M', u'μ'), + (0x1D728, 'M', u'ν'), + (0x1D729, 'M', u'ξ'), + (0x1D72A, 'M', u'ο'), + (0x1D72B, 'M', u'π'), + (0x1D72C, 'M', u'ρ'), + (0x1D72D, 'M', u'θ'), + (0x1D72E, 'M', u'σ'), + ] + +def _seg_66(): + return [ + (0x1D72F, 'M', u'τ'), + (0x1D730, 'M', u'υ'), + (0x1D731, 'M', u'φ'), + (0x1D732, 'M', u'χ'), + (0x1D733, 'M', u'ψ'), + (0x1D734, 'M', u'ω'), + (0x1D735, 'M', u'∇'), + (0x1D736, 'M', u'α'), + (0x1D737, 'M', u'β'), + (0x1D738, 'M', u'γ'), + (0x1D739, 'M', u'δ'), + (0x1D73A, 'M', u'ε'), + (0x1D73B, 'M', u'ζ'), + (0x1D73C, 'M', u'η'), + (0x1D73D, 'M', u'θ'), + (0x1D73E, 'M', u'ι'), + (0x1D73F, 'M', u'κ'), + (0x1D740, 'M', u'λ'), + (0x1D741, 'M', u'μ'), + (0x1D742, 'M', u'ν'), + (0x1D743, 'M', u'ξ'), + (0x1D744, 'M', u'ο'), + (0x1D745, 'M', u'π'), + (0x1D746, 'M', u'ρ'), + (0x1D747, 'M', u'σ'), + (0x1D749, 'M', u'τ'), + (0x1D74A, 'M', u'υ'), + (0x1D74B, 'M', u'φ'), + (0x1D74C, 'M', u'χ'), + (0x1D74D, 'M', u'ψ'), + (0x1D74E, 'M', u'ω'), + (0x1D74F, 'M', u'∂'), + (0x1D750, 'M', u'ε'), + (0x1D751, 'M', u'θ'), + (0x1D752, 'M', u'κ'), + (0x1D753, 'M', u'φ'), + (0x1D754, 'M', u'ρ'), + (0x1D755, 'M', u'π'), + (0x1D756, 'M', u'α'), + (0x1D757, 'M', u'β'), + (0x1D758, 'M', u'γ'), + (0x1D759, 'M', u'δ'), + (0x1D75A, 'M', u'ε'), + (0x1D75B, 'M', u'ζ'), + (0x1D75C, 'M', u'η'), + (0x1D75D, 'M', u'θ'), + (0x1D75E, 'M', u'ι'), + (0x1D75F, 'M', u'κ'), + (0x1D760, 'M', u'λ'), + (0x1D761, 'M', u'μ'), + (0x1D762, 'M', u'ν'), + (0x1D763, 'M', u'ξ'), + (0x1D764, 'M', u'ο'), + (0x1D765, 'M', u'π'), + (0x1D766, 'M', u'ρ'), + (0x1D767, 'M', u'θ'), + (0x1D768, 'M', u'σ'), + (0x1D769, 'M', u'τ'), + (0x1D76A, 'M', u'υ'), + (0x1D76B, 'M', u'φ'), + (0x1D76C, 'M', u'χ'), + (0x1D76D, 'M', u'ψ'), + (0x1D76E, 'M', u'ω'), + (0x1D76F, 'M', u'∇'), + (0x1D770, 'M', u'α'), + (0x1D771, 'M', u'β'), + (0x1D772, 'M', u'γ'), + (0x1D773, 'M', u'δ'), + (0x1D774, 'M', u'ε'), + (0x1D775, 'M', u'ζ'), + (0x1D776, 'M', u'η'), + (0x1D777, 'M', u'θ'), + (0x1D778, 'M', u'ι'), + (0x1D779, 'M', u'κ'), + (0x1D77A, 'M', u'λ'), + (0x1D77B, 'M', u'μ'), + (0x1D77C, 'M', u'ν'), + (0x1D77D, 'M', u'ξ'), + (0x1D77E, 'M', u'ο'), + (0x1D77F, 'M', u'π'), + (0x1D780, 'M', u'ρ'), + (0x1D781, 'M', u'σ'), + (0x1D783, 'M', u'τ'), + (0x1D784, 'M', u'υ'), + (0x1D785, 'M', u'φ'), + (0x1D786, 'M', u'χ'), + (0x1D787, 'M', u'ψ'), + (0x1D788, 'M', u'ω'), + (0x1D789, 'M', u'∂'), + (0x1D78A, 'M', u'ε'), + (0x1D78B, 'M', u'θ'), + (0x1D78C, 'M', u'κ'), + (0x1D78D, 'M', u'φ'), + (0x1D78E, 'M', u'ρ'), + (0x1D78F, 'M', u'π'), + (0x1D790, 'M', u'α'), + (0x1D791, 'M', u'β'), + (0x1D792, 'M', u'γ'), + (0x1D793, 'M', u'δ'), + (0x1D794, 'M', u'ε'), + ] + +def _seg_67(): + return [ + (0x1D795, 'M', u'ζ'), + (0x1D796, 'M', u'η'), + (0x1D797, 'M', u'θ'), + (0x1D798, 'M', u'ι'), + (0x1D799, 'M', u'κ'), + (0x1D79A, 'M', u'λ'), + (0x1D79B, 'M', u'μ'), + (0x1D79C, 'M', u'ν'), + (0x1D79D, 'M', u'ξ'), + (0x1D79E, 'M', u'ο'), + (0x1D79F, 'M', u'π'), + (0x1D7A0, 'M', u'ρ'), + (0x1D7A1, 'M', u'θ'), + (0x1D7A2, 'M', u'σ'), + (0x1D7A3, 'M', u'τ'), + (0x1D7A4, 'M', u'υ'), + (0x1D7A5, 'M', u'φ'), + (0x1D7A6, 'M', u'χ'), + (0x1D7A7, 'M', u'ψ'), + (0x1D7A8, 'M', u'ω'), + (0x1D7A9, 'M', u'∇'), + (0x1D7AA, 'M', u'α'), + (0x1D7AB, 'M', u'β'), + (0x1D7AC, 'M', u'γ'), + (0x1D7AD, 'M', u'δ'), + (0x1D7AE, 'M', u'ε'), + (0x1D7AF, 'M', u'ζ'), + (0x1D7B0, 'M', u'η'), + (0x1D7B1, 'M', u'θ'), + (0x1D7B2, 'M', u'ι'), + (0x1D7B3, 'M', u'κ'), + (0x1D7B4, 'M', u'λ'), + (0x1D7B5, 'M', u'μ'), + (0x1D7B6, 'M', u'ν'), + (0x1D7B7, 'M', u'ξ'), + (0x1D7B8, 'M', u'ο'), + (0x1D7B9, 'M', u'π'), + (0x1D7BA, 'M', u'ρ'), + (0x1D7BB, 'M', u'σ'), + (0x1D7BD, 'M', u'τ'), + (0x1D7BE, 'M', u'υ'), + (0x1D7BF, 'M', u'φ'), + (0x1D7C0, 'M', u'χ'), + (0x1D7C1, 'M', u'ψ'), + (0x1D7C2, 'M', u'ω'), + (0x1D7C3, 'M', u'∂'), + (0x1D7C4, 'M', u'ε'), + (0x1D7C5, 'M', u'θ'), + (0x1D7C6, 'M', u'κ'), + (0x1D7C7, 'M', u'φ'), + (0x1D7C8, 'M', u'ρ'), + (0x1D7C9, 'M', u'π'), + (0x1D7CA, 'M', u'ϝ'), + (0x1D7CC, 'X'), + (0x1D7CE, 'M', u'0'), + (0x1D7CF, 'M', u'1'), + (0x1D7D0, 'M', u'2'), + (0x1D7D1, 'M', u'3'), + (0x1D7D2, 'M', u'4'), + (0x1D7D3, 'M', u'5'), + (0x1D7D4, 'M', u'6'), + (0x1D7D5, 'M', u'7'), + (0x1D7D6, 'M', u'8'), + (0x1D7D7, 'M', u'9'), + (0x1D7D8, 'M', u'0'), + (0x1D7D9, 'M', u'1'), + (0x1D7DA, 'M', u'2'), + (0x1D7DB, 'M', u'3'), + (0x1D7DC, 'M', u'4'), + (0x1D7DD, 'M', u'5'), + (0x1D7DE, 'M', u'6'), + (0x1D7DF, 'M', u'7'), + (0x1D7E0, 'M', u'8'), + (0x1D7E1, 'M', u'9'), + (0x1D7E2, 'M', u'0'), + (0x1D7E3, 'M', u'1'), + (0x1D7E4, 'M', u'2'), + (0x1D7E5, 'M', u'3'), + (0x1D7E6, 'M', u'4'), + (0x1D7E7, 'M', u'5'), + (0x1D7E8, 'M', u'6'), + (0x1D7E9, 'M', u'7'), + (0x1D7EA, 'M', u'8'), + (0x1D7EB, 'M', u'9'), + (0x1D7EC, 'M', u'0'), + (0x1D7ED, 'M', u'1'), + (0x1D7EE, 'M', u'2'), + (0x1D7EF, 'M', u'3'), + (0x1D7F0, 'M', u'4'), + (0x1D7F1, 'M', u'5'), + (0x1D7F2, 'M', u'6'), + (0x1D7F3, 'M', u'7'), + (0x1D7F4, 'M', u'8'), + (0x1D7F5, 'M', u'9'), + (0x1D7F6, 'M', u'0'), + (0x1D7F7, 'M', u'1'), + (0x1D7F8, 'M', u'2'), + (0x1D7F9, 'M', u'3'), + (0x1D7FA, 'M', u'4'), + (0x1D7FB, 'M', u'5'), + ] + +def _seg_68(): + return [ + (0x1D7FC, 'M', u'6'), + (0x1D7FD, 'M', u'7'), + (0x1D7FE, 'M', u'8'), + (0x1D7FF, 'M', u'9'), + (0x1D800, 'V'), + (0x1DA8C, 'X'), + (0x1DA9B, 'V'), + (0x1DAA0, 'X'), + (0x1DAA1, 'V'), + (0x1DAB0, 'X'), + (0x1E000, 'V'), + (0x1E007, 'X'), + (0x1E008, 'V'), + (0x1E019, 'X'), + (0x1E01B, 'V'), + (0x1E022, 'X'), + (0x1E023, 'V'), + (0x1E025, 'X'), + (0x1E026, 'V'), + (0x1E02B, 'X'), + (0x1E800, 'V'), + (0x1E8C5, 'X'), + (0x1E8C7, 'V'), + (0x1E8D7, 'X'), + (0x1E900, 'M', u'𞤢'), + (0x1E901, 'M', u'𞤣'), + (0x1E902, 'M', u'𞤤'), + (0x1E903, 'M', u'𞤥'), + (0x1E904, 'M', u'𞤦'), + (0x1E905, 'M', u'𞤧'), + (0x1E906, 'M', u'𞤨'), + (0x1E907, 'M', u'𞤩'), + (0x1E908, 'M', u'𞤪'), + (0x1E909, 'M', u'𞤫'), + (0x1E90A, 'M', u'𞤬'), + (0x1E90B, 'M', u'𞤭'), + (0x1E90C, 'M', u'𞤮'), + (0x1E90D, 'M', u'𞤯'), + (0x1E90E, 'M', u'𞤰'), + (0x1E90F, 'M', u'𞤱'), + (0x1E910, 'M', u'𞤲'), + (0x1E911, 'M', u'𞤳'), + (0x1E912, 'M', u'𞤴'), + (0x1E913, 'M', u'𞤵'), + (0x1E914, 'M', u'𞤶'), + (0x1E915, 'M', u'𞤷'), + (0x1E916, 'M', u'𞤸'), + (0x1E917, 'M', u'𞤹'), + (0x1E918, 'M', u'𞤺'), + (0x1E919, 'M', u'𞤻'), + (0x1E91A, 'M', u'𞤼'), + (0x1E91B, 'M', u'𞤽'), + (0x1E91C, 'M', u'𞤾'), + (0x1E91D, 'M', u'𞤿'), + (0x1E91E, 'M', u'𞥀'), + (0x1E91F, 'M', u'𞥁'), + (0x1E920, 'M', u'𞥂'), + (0x1E921, 'M', u'𞥃'), + (0x1E922, 'V'), + (0x1E94B, 'X'), + (0x1E950, 'V'), + (0x1E95A, 'X'), + (0x1E95E, 'V'), + (0x1E960, 'X'), + (0x1EE00, 'M', u'ا'), + (0x1EE01, 'M', u'ب'), + (0x1EE02, 'M', u'ج'), + (0x1EE03, 'M', u'د'), + (0x1EE04, 'X'), + (0x1EE05, 'M', u'و'), + (0x1EE06, 'M', u'ز'), + (0x1EE07, 'M', u'ح'), + (0x1EE08, 'M', u'ط'), + (0x1EE09, 'M', u'ي'), + (0x1EE0A, 'M', u'ك'), + (0x1EE0B, 'M', u'ل'), + (0x1EE0C, 'M', u'م'), + (0x1EE0D, 'M', u'ن'), + (0x1EE0E, 'M', u'س'), + (0x1EE0F, 'M', u'ع'), + (0x1EE10, 'M', u'ف'), + (0x1EE11, 'M', u'ص'), + (0x1EE12, 'M', u'ق'), + (0x1EE13, 'M', u'ر'), + (0x1EE14, 'M', u'ش'), + (0x1EE15, 'M', u'ت'), + (0x1EE16, 'M', u'ث'), + (0x1EE17, 'M', u'خ'), + (0x1EE18, 'M', u'ذ'), + (0x1EE19, 'M', u'ض'), + (0x1EE1A, 'M', u'ظ'), + (0x1EE1B, 'M', u'غ'), + (0x1EE1C, 'M', u'ٮ'), + (0x1EE1D, 'M', u'ں'), + (0x1EE1E, 'M', u'ڡ'), + (0x1EE1F, 'M', u'ٯ'), + (0x1EE20, 'X'), + (0x1EE21, 'M', u'ب'), + (0x1EE22, 'M', u'ج'), + (0x1EE23, 'X'), + ] + +def _seg_69(): + return [ + (0x1EE24, 'M', u'ه'), + (0x1EE25, 'X'), + (0x1EE27, 'M', u'ح'), + (0x1EE28, 'X'), + (0x1EE29, 'M', u'ي'), + (0x1EE2A, 'M', u'ك'), + (0x1EE2B, 'M', u'ل'), + (0x1EE2C, 'M', u'م'), + (0x1EE2D, 'M', u'ن'), + (0x1EE2E, 'M', u'س'), + (0x1EE2F, 'M', u'ع'), + (0x1EE30, 'M', u'ف'), + (0x1EE31, 'M', u'ص'), + (0x1EE32, 'M', u'ق'), + (0x1EE33, 'X'), + (0x1EE34, 'M', u'ش'), + (0x1EE35, 'M', u'ت'), + (0x1EE36, 'M', u'ث'), + (0x1EE37, 'M', u'خ'), + (0x1EE38, 'X'), + (0x1EE39, 'M', u'ض'), + (0x1EE3A, 'X'), + (0x1EE3B, 'M', u'غ'), + (0x1EE3C, 'X'), + (0x1EE42, 'M', u'ج'), + (0x1EE43, 'X'), + (0x1EE47, 'M', u'ح'), + (0x1EE48, 'X'), + (0x1EE49, 'M', u'ي'), + (0x1EE4A, 'X'), + (0x1EE4B, 'M', u'ل'), + (0x1EE4C, 'X'), + (0x1EE4D, 'M', u'ن'), + (0x1EE4E, 'M', u'س'), + (0x1EE4F, 'M', u'ع'), + (0x1EE50, 'X'), + (0x1EE51, 'M', u'ص'), + (0x1EE52, 'M', u'ق'), + (0x1EE53, 'X'), + (0x1EE54, 'M', u'ش'), + (0x1EE55, 'X'), + (0x1EE57, 'M', u'خ'), + (0x1EE58, 'X'), + (0x1EE59, 'M', u'ض'), + (0x1EE5A, 'X'), + (0x1EE5B, 'M', u'غ'), + (0x1EE5C, 'X'), + (0x1EE5D, 'M', u'ں'), + (0x1EE5E, 'X'), + (0x1EE5F, 'M', u'ٯ'), + (0x1EE60, 'X'), + (0x1EE61, 'M', u'ب'), + (0x1EE62, 'M', u'ج'), + (0x1EE63, 'X'), + (0x1EE64, 'M', u'ه'), + (0x1EE65, 'X'), + (0x1EE67, 'M', u'ح'), + (0x1EE68, 'M', u'ط'), + (0x1EE69, 'M', u'ي'), + (0x1EE6A, 'M', u'ك'), + (0x1EE6B, 'X'), + (0x1EE6C, 'M', u'م'), + (0x1EE6D, 'M', u'ن'), + (0x1EE6E, 'M', u'س'), + (0x1EE6F, 'M', u'ع'), + (0x1EE70, 'M', u'ف'), + (0x1EE71, 'M', u'ص'), + (0x1EE72, 'M', u'ق'), + (0x1EE73, 'X'), + (0x1EE74, 'M', u'ش'), + (0x1EE75, 'M', u'ت'), + (0x1EE76, 'M', u'ث'), + (0x1EE77, 'M', u'خ'), + (0x1EE78, 'X'), + (0x1EE79, 'M', u'ض'), + (0x1EE7A, 'M', u'ظ'), + (0x1EE7B, 'M', u'غ'), + (0x1EE7C, 'M', u'ٮ'), + (0x1EE7D, 'X'), + (0x1EE7E, 'M', u'ڡ'), + (0x1EE7F, 'X'), + (0x1EE80, 'M', u'ا'), + (0x1EE81, 'M', u'ب'), + (0x1EE82, 'M', u'ج'), + (0x1EE83, 'M', u'د'), + (0x1EE84, 'M', u'ه'), + (0x1EE85, 'M', u'و'), + (0x1EE86, 'M', u'ز'), + (0x1EE87, 'M', u'ح'), + (0x1EE88, 'M', u'ط'), + (0x1EE89, 'M', u'ي'), + (0x1EE8A, 'X'), + (0x1EE8B, 'M', u'ل'), + (0x1EE8C, 'M', u'م'), + (0x1EE8D, 'M', u'ن'), + (0x1EE8E, 'M', u'س'), + (0x1EE8F, 'M', u'ع'), + (0x1EE90, 'M', u'ف'), + (0x1EE91, 'M', u'ص'), + (0x1EE92, 'M', u'ق'), + ] + +def _seg_70(): + return [ + (0x1EE93, 'M', u'ر'), + (0x1EE94, 'M', u'ش'), + (0x1EE95, 'M', u'ت'), + (0x1EE96, 'M', u'ث'), + (0x1EE97, 'M', u'خ'), + (0x1EE98, 'M', u'ذ'), + (0x1EE99, 'M', u'ض'), + (0x1EE9A, 'M', u'ظ'), + (0x1EE9B, 'M', u'غ'), + (0x1EE9C, 'X'), + (0x1EEA1, 'M', u'ب'), + (0x1EEA2, 'M', u'ج'), + (0x1EEA3, 'M', u'د'), + (0x1EEA4, 'X'), + (0x1EEA5, 'M', u'و'), + (0x1EEA6, 'M', u'ز'), + (0x1EEA7, 'M', u'ح'), + (0x1EEA8, 'M', u'ط'), + (0x1EEA9, 'M', u'ي'), + (0x1EEAA, 'X'), + (0x1EEAB, 'M', u'ل'), + (0x1EEAC, 'M', u'م'), + (0x1EEAD, 'M', u'ن'), + (0x1EEAE, 'M', u'س'), + (0x1EEAF, 'M', u'ع'), + (0x1EEB0, 'M', u'ف'), + (0x1EEB1, 'M', u'ص'), + (0x1EEB2, 'M', u'ق'), + (0x1EEB3, 'M', u'ر'), + (0x1EEB4, 'M', u'ش'), + (0x1EEB5, 'M', u'ت'), + (0x1EEB6, 'M', u'ث'), + (0x1EEB7, 'M', u'خ'), + (0x1EEB8, 'M', u'ذ'), + (0x1EEB9, 'M', u'ض'), + (0x1EEBA, 'M', u'ظ'), + (0x1EEBB, 'M', u'غ'), + (0x1EEBC, 'X'), + (0x1EEF0, 'V'), + (0x1EEF2, 'X'), + (0x1F000, 'V'), + (0x1F02C, 'X'), + (0x1F030, 'V'), + (0x1F094, 'X'), + (0x1F0A0, 'V'), + (0x1F0AF, 'X'), + (0x1F0B1, 'V'), + (0x1F0C0, 'X'), + (0x1F0C1, 'V'), + (0x1F0D0, 'X'), + (0x1F0D1, 'V'), + (0x1F0F6, 'X'), + (0x1F101, '3', u'0,'), + (0x1F102, '3', u'1,'), + (0x1F103, '3', u'2,'), + (0x1F104, '3', u'3,'), + (0x1F105, '3', u'4,'), + (0x1F106, '3', u'5,'), + (0x1F107, '3', u'6,'), + (0x1F108, '3', u'7,'), + (0x1F109, '3', u'8,'), + (0x1F10A, '3', u'9,'), + (0x1F10B, 'V'), + (0x1F10D, 'X'), + (0x1F110, '3', u'(a)'), + (0x1F111, '3', u'(b)'), + (0x1F112, '3', u'(c)'), + (0x1F113, '3', u'(d)'), + (0x1F114, '3', u'(e)'), + (0x1F115, '3', u'(f)'), + (0x1F116, '3', u'(g)'), + (0x1F117, '3', u'(h)'), + (0x1F118, '3', u'(i)'), + (0x1F119, '3', u'(j)'), + (0x1F11A, '3', u'(k)'), + (0x1F11B, '3', u'(l)'), + (0x1F11C, '3', u'(m)'), + (0x1F11D, '3', u'(n)'), + (0x1F11E, '3', u'(o)'), + (0x1F11F, '3', u'(p)'), + (0x1F120, '3', u'(q)'), + (0x1F121, '3', u'(r)'), + (0x1F122, '3', u'(s)'), + (0x1F123, '3', u'(t)'), + (0x1F124, '3', u'(u)'), + (0x1F125, '3', u'(v)'), + (0x1F126, '3', u'(w)'), + (0x1F127, '3', u'(x)'), + (0x1F128, '3', u'(y)'), + (0x1F129, '3', u'(z)'), + (0x1F12A, 'M', u'〔s〕'), + (0x1F12B, 'M', u'c'), + (0x1F12C, 'M', u'r'), + (0x1F12D, 'M', u'cd'), + (0x1F12E, 'M', u'wz'), + (0x1F12F, 'X'), + (0x1F130, 'M', u'a'), + (0x1F131, 'M', u'b'), + (0x1F132, 'M', u'c'), + (0x1F133, 'M', u'd'), + ] + +def _seg_71(): + return [ + (0x1F134, 'M', u'e'), + (0x1F135, 'M', u'f'), + (0x1F136, 'M', u'g'), + (0x1F137, 'M', u'h'), + (0x1F138, 'M', u'i'), + (0x1F139, 'M', u'j'), + (0x1F13A, 'M', u'k'), + (0x1F13B, 'M', u'l'), + (0x1F13C, 'M', u'm'), + (0x1F13D, 'M', u'n'), + (0x1F13E, 'M', u'o'), + (0x1F13F, 'M', u'p'), + (0x1F140, 'M', u'q'), + (0x1F141, 'M', u'r'), + (0x1F142, 'M', u's'), + (0x1F143, 'M', u't'), + (0x1F144, 'M', u'u'), + (0x1F145, 'M', u'v'), + (0x1F146, 'M', u'w'), + (0x1F147, 'M', u'x'), + (0x1F148, 'M', u'y'), + (0x1F149, 'M', u'z'), + (0x1F14A, 'M', u'hv'), + (0x1F14B, 'M', u'mv'), + (0x1F14C, 'M', u'sd'), + (0x1F14D, 'M', u'ss'), + (0x1F14E, 'M', u'ppv'), + (0x1F14F, 'M', u'wc'), + (0x1F150, 'V'), + (0x1F16A, 'M', u'mc'), + (0x1F16B, 'M', u'md'), + (0x1F16C, 'X'), + (0x1F170, 'V'), + (0x1F190, 'M', u'dj'), + (0x1F191, 'V'), + (0x1F1AD, 'X'), + (0x1F1E6, 'V'), + (0x1F200, 'M', u'ほか'), + (0x1F201, 'M', u'ココ'), + (0x1F202, 'M', u'サ'), + (0x1F203, 'X'), + (0x1F210, 'M', u'手'), + (0x1F211, 'M', u'字'), + (0x1F212, 'M', u'双'), + (0x1F213, 'M', u'デ'), + (0x1F214, 'M', u'二'), + (0x1F215, 'M', u'多'), + (0x1F216, 'M', u'解'), + (0x1F217, 'M', u'天'), + (0x1F218, 'M', u'交'), + (0x1F219, 'M', u'映'), + (0x1F21A, 'M', u'無'), + (0x1F21B, 'M', u'料'), + (0x1F21C, 'M', u'前'), + (0x1F21D, 'M', u'後'), + (0x1F21E, 'M', u'再'), + (0x1F21F, 'M', u'新'), + (0x1F220, 'M', u'初'), + (0x1F221, 'M', u'終'), + (0x1F222, 'M', u'生'), + (0x1F223, 'M', u'販'), + (0x1F224, 'M', u'声'), + (0x1F225, 'M', u'吹'), + (0x1F226, 'M', u'演'), + (0x1F227, 'M', u'投'), + (0x1F228, 'M', u'捕'), + (0x1F229, 'M', u'一'), + (0x1F22A, 'M', u'三'), + (0x1F22B, 'M', u'遊'), + (0x1F22C, 'M', u'左'), + (0x1F22D, 'M', u'中'), + (0x1F22E, 'M', u'右'), + (0x1F22F, 'M', u'指'), + (0x1F230, 'M', u'走'), + (0x1F231, 'M', u'打'), + (0x1F232, 'M', u'禁'), + (0x1F233, 'M', u'空'), + (0x1F234, 'M', u'合'), + (0x1F235, 'M', u'満'), + (0x1F236, 'M', u'有'), + (0x1F237, 'M', u'月'), + (0x1F238, 'M', u'申'), + (0x1F239, 'M', u'割'), + (0x1F23A, 'M', u'営'), + (0x1F23B, 'M', u'配'), + (0x1F23C, 'X'), + (0x1F240, 'M', u'〔本〕'), + (0x1F241, 'M', u'〔三〕'), + (0x1F242, 'M', u'〔二〕'), + (0x1F243, 'M', u'〔安〕'), + (0x1F244, 'M', u'〔点〕'), + (0x1F245, 'M', u'〔打〕'), + (0x1F246, 'M', u'〔盗〕'), + (0x1F247, 'M', u'〔勝〕'), + (0x1F248, 'M', u'〔敗〕'), + (0x1F249, 'X'), + (0x1F250, 'M', u'得'), + (0x1F251, 'M', u'可'), + (0x1F252, 'X'), + (0x1F260, 'V'), + ] + +def _seg_72(): + return [ + (0x1F266, 'X'), + (0x1F300, 'V'), + (0x1F6D5, 'X'), + (0x1F6E0, 'V'), + (0x1F6ED, 'X'), + (0x1F6F0, 'V'), + (0x1F6F9, 'X'), + (0x1F700, 'V'), + (0x1F774, 'X'), + (0x1F780, 'V'), + (0x1F7D5, 'X'), + (0x1F800, 'V'), + (0x1F80C, 'X'), + (0x1F810, 'V'), + (0x1F848, 'X'), + (0x1F850, 'V'), + (0x1F85A, 'X'), + (0x1F860, 'V'), + (0x1F888, 'X'), + (0x1F890, 'V'), + (0x1F8AE, 'X'), + (0x1F900, 'V'), + (0x1F90C, 'X'), + (0x1F910, 'V'), + (0x1F93F, 'X'), + (0x1F940, 'V'), + (0x1F94D, 'X'), + (0x1F950, 'V'), + (0x1F96C, 'X'), + (0x1F980, 'V'), + (0x1F998, 'X'), + (0x1F9C0, 'V'), + (0x1F9C1, 'X'), + (0x1F9D0, 'V'), + (0x1F9E7, 'X'), + (0x20000, 'V'), + (0x2A6D7, 'X'), + (0x2A700, 'V'), + (0x2B735, 'X'), + (0x2B740, 'V'), + (0x2B81E, 'X'), + (0x2B820, 'V'), + (0x2CEA2, 'X'), + (0x2CEB0, 'V'), + (0x2EBE1, 'X'), + (0x2F800, 'M', u'丽'), + (0x2F801, 'M', u'丸'), + (0x2F802, 'M', u'乁'), + (0x2F803, 'M', u'𠄢'), + (0x2F804, 'M', u'你'), + (0x2F805, 'M', u'侮'), + (0x2F806, 'M', u'侻'), + (0x2F807, 'M', u'倂'), + (0x2F808, 'M', u'偺'), + (0x2F809, 'M', u'備'), + (0x2F80A, 'M', u'僧'), + (0x2F80B, 'M', u'像'), + (0x2F80C, 'M', u'㒞'), + (0x2F80D, 'M', u'𠘺'), + (0x2F80E, 'M', u'免'), + (0x2F80F, 'M', u'兔'), + (0x2F810, 'M', u'兤'), + (0x2F811, 'M', u'具'), + (0x2F812, 'M', u'𠔜'), + (0x2F813, 'M', u'㒹'), + (0x2F814, 'M', u'內'), + (0x2F815, 'M', u'再'), + (0x2F816, 'M', u'𠕋'), + (0x2F817, 'M', u'冗'), + (0x2F818, 'M', u'冤'), + (0x2F819, 'M', u'仌'), + (0x2F81A, 'M', u'冬'), + (0x2F81B, 'M', u'况'), + (0x2F81C, 'M', u'𩇟'), + (0x2F81D, 'M', u'凵'), + (0x2F81E, 'M', u'刃'), + (0x2F81F, 'M', u'㓟'), + (0x2F820, 'M', u'刻'), + (0x2F821, 'M', u'剆'), + (0x2F822, 'M', u'割'), + (0x2F823, 'M', u'剷'), + (0x2F824, 'M', u'㔕'), + (0x2F825, 'M', u'勇'), + (0x2F826, 'M', u'勉'), + (0x2F827, 'M', u'勤'), + (0x2F828, 'M', u'勺'), + (0x2F829, 'M', u'包'), + (0x2F82A, 'M', u'匆'), + (0x2F82B, 'M', u'北'), + (0x2F82C, 'M', u'卉'), + (0x2F82D, 'M', u'卑'), + (0x2F82E, 'M', u'博'), + (0x2F82F, 'M', u'即'), + (0x2F830, 'M', u'卽'), + (0x2F831, 'M', u'卿'), + (0x2F834, 'M', u'𠨬'), + (0x2F835, 'M', u'灰'), + (0x2F836, 'M', u'及'), + (0x2F837, 'M', u'叟'), + (0x2F838, 'M', u'𠭣'), + ] + +def _seg_73(): + return [ + (0x2F839, 'M', u'叫'), + (0x2F83A, 'M', u'叱'), + (0x2F83B, 'M', u'吆'), + (0x2F83C, 'M', u'咞'), + (0x2F83D, 'M', u'吸'), + (0x2F83E, 'M', u'呈'), + (0x2F83F, 'M', u'周'), + (0x2F840, 'M', u'咢'), + (0x2F841, 'M', u'哶'), + (0x2F842, 'M', u'唐'), + (0x2F843, 'M', u'啓'), + (0x2F844, 'M', u'啣'), + (0x2F845, 'M', u'善'), + (0x2F847, 'M', u'喙'), + (0x2F848, 'M', u'喫'), + (0x2F849, 'M', u'喳'), + (0x2F84A, 'M', u'嗂'), + (0x2F84B, 'M', u'圖'), + (0x2F84C, 'M', u'嘆'), + (0x2F84D, 'M', u'圗'), + (0x2F84E, 'M', u'噑'), + (0x2F84F, 'M', u'噴'), + (0x2F850, 'M', u'切'), + (0x2F851, 'M', u'壮'), + (0x2F852, 'M', u'城'), + (0x2F853, 'M', u'埴'), + (0x2F854, 'M', u'堍'), + (0x2F855, 'M', u'型'), + (0x2F856, 'M', u'堲'), + (0x2F857, 'M', u'報'), + (0x2F858, 'M', u'墬'), + (0x2F859, 'M', u'𡓤'), + (0x2F85A, 'M', u'売'), + (0x2F85B, 'M', u'壷'), + (0x2F85C, 'M', u'夆'), + (0x2F85D, 'M', u'多'), + (0x2F85E, 'M', u'夢'), + (0x2F85F, 'M', u'奢'), + (0x2F860, 'M', u'𡚨'), + (0x2F861, 'M', u'𡛪'), + (0x2F862, 'M', u'姬'), + (0x2F863, 'M', u'娛'), + (0x2F864, 'M', u'娧'), + (0x2F865, 'M', u'姘'), + (0x2F866, 'M', u'婦'), + (0x2F867, 'M', u'㛮'), + (0x2F868, 'X'), + (0x2F869, 'M', u'嬈'), + (0x2F86A, 'M', u'嬾'), + (0x2F86C, 'M', u'𡧈'), + (0x2F86D, 'M', u'寃'), + (0x2F86E, 'M', u'寘'), + (0x2F86F, 'M', u'寧'), + (0x2F870, 'M', u'寳'), + (0x2F871, 'M', u'𡬘'), + (0x2F872, 'M', u'寿'), + (0x2F873, 'M', u'将'), + (0x2F874, 'X'), + (0x2F875, 'M', u'尢'), + (0x2F876, 'M', u'㞁'), + (0x2F877, 'M', u'屠'), + (0x2F878, 'M', u'屮'), + (0x2F879, 'M', u'峀'), + (0x2F87A, 'M', u'岍'), + (0x2F87B, 'M', u'𡷤'), + (0x2F87C, 'M', u'嵃'), + (0x2F87D, 'M', u'𡷦'), + (0x2F87E, 'M', u'嵮'), + (0x2F87F, 'M', u'嵫'), + (0x2F880, 'M', u'嵼'), + (0x2F881, 'M', u'巡'), + (0x2F882, 'M', u'巢'), + (0x2F883, 'M', u'㠯'), + (0x2F884, 'M', u'巽'), + (0x2F885, 'M', u'帨'), + (0x2F886, 'M', u'帽'), + (0x2F887, 'M', u'幩'), + (0x2F888, 'M', u'㡢'), + (0x2F889, 'M', u'𢆃'), + (0x2F88A, 'M', u'㡼'), + (0x2F88B, 'M', u'庰'), + (0x2F88C, 'M', u'庳'), + (0x2F88D, 'M', u'庶'), + (0x2F88E, 'M', u'廊'), + (0x2F88F, 'M', u'𪎒'), + (0x2F890, 'M', u'廾'), + (0x2F891, 'M', u'𢌱'), + (0x2F893, 'M', u'舁'), + (0x2F894, 'M', u'弢'), + (0x2F896, 'M', u'㣇'), + (0x2F897, 'M', u'𣊸'), + (0x2F898, 'M', u'𦇚'), + (0x2F899, 'M', u'形'), + (0x2F89A, 'M', u'彫'), + (0x2F89B, 'M', u'㣣'), + (0x2F89C, 'M', u'徚'), + (0x2F89D, 'M', u'忍'), + (0x2F89E, 'M', u'志'), + (0x2F89F, 'M', u'忹'), + (0x2F8A0, 'M', u'悁'), + ] + +def _seg_74(): + return [ + (0x2F8A1, 'M', u'㤺'), + (0x2F8A2, 'M', u'㤜'), + (0x2F8A3, 'M', u'悔'), + (0x2F8A4, 'M', u'𢛔'), + (0x2F8A5, 'M', u'惇'), + (0x2F8A6, 'M', u'慈'), + (0x2F8A7, 'M', u'慌'), + (0x2F8A8, 'M', u'慎'), + (0x2F8A9, 'M', u'慌'), + (0x2F8AA, 'M', u'慺'), + (0x2F8AB, 'M', u'憎'), + (0x2F8AC, 'M', u'憲'), + (0x2F8AD, 'M', u'憤'), + (0x2F8AE, 'M', u'憯'), + (0x2F8AF, 'M', u'懞'), + (0x2F8B0, 'M', u'懲'), + (0x2F8B1, 'M', u'懶'), + (0x2F8B2, 'M', u'成'), + (0x2F8B3, 'M', u'戛'), + (0x2F8B4, 'M', u'扝'), + (0x2F8B5, 'M', u'抱'), + (0x2F8B6, 'M', u'拔'), + (0x2F8B7, 'M', u'捐'), + (0x2F8B8, 'M', u'𢬌'), + (0x2F8B9, 'M', u'挽'), + (0x2F8BA, 'M', u'拼'), + (0x2F8BB, 'M', u'捨'), + (0x2F8BC, 'M', u'掃'), + (0x2F8BD, 'M', u'揤'), + (0x2F8BE, 'M', u'𢯱'), + (0x2F8BF, 'M', u'搢'), + (0x2F8C0, 'M', u'揅'), + (0x2F8C1, 'M', u'掩'), + (0x2F8C2, 'M', u'㨮'), + (0x2F8C3, 'M', u'摩'), + (0x2F8C4, 'M', u'摾'), + (0x2F8C5, 'M', u'撝'), + (0x2F8C6, 'M', u'摷'), + (0x2F8C7, 'M', u'㩬'), + (0x2F8C8, 'M', u'敏'), + (0x2F8C9, 'M', u'敬'), + (0x2F8CA, 'M', u'𣀊'), + (0x2F8CB, 'M', u'旣'), + (0x2F8CC, 'M', u'書'), + (0x2F8CD, 'M', u'晉'), + (0x2F8CE, 'M', u'㬙'), + (0x2F8CF, 'M', u'暑'), + (0x2F8D0, 'M', u'㬈'), + (0x2F8D1, 'M', u'㫤'), + (0x2F8D2, 'M', u'冒'), + (0x2F8D3, 'M', u'冕'), + (0x2F8D4, 'M', u'最'), + (0x2F8D5, 'M', u'暜'), + (0x2F8D6, 'M', u'肭'), + (0x2F8D7, 'M', u'䏙'), + (0x2F8D8, 'M', u'朗'), + (0x2F8D9, 'M', u'望'), + (0x2F8DA, 'M', u'朡'), + (0x2F8DB, 'M', u'杞'), + (0x2F8DC, 'M', u'杓'), + (0x2F8DD, 'M', u'𣏃'), + (0x2F8DE, 'M', u'㭉'), + (0x2F8DF, 'M', u'柺'), + (0x2F8E0, 'M', u'枅'), + (0x2F8E1, 'M', u'桒'), + (0x2F8E2, 'M', u'梅'), + (0x2F8E3, 'M', u'𣑭'), + (0x2F8E4, 'M', u'梎'), + (0x2F8E5, 'M', u'栟'), + (0x2F8E6, 'M', u'椔'), + (0x2F8E7, 'M', u'㮝'), + (0x2F8E8, 'M', u'楂'), + (0x2F8E9, 'M', u'榣'), + (0x2F8EA, 'M', u'槪'), + (0x2F8EB, 'M', u'檨'), + (0x2F8EC, 'M', u'𣚣'), + (0x2F8ED, 'M', u'櫛'), + (0x2F8EE, 'M', u'㰘'), + (0x2F8EF, 'M', u'次'), + (0x2F8F0, 'M', u'𣢧'), + (0x2F8F1, 'M', u'歔'), + (0x2F8F2, 'M', u'㱎'), + (0x2F8F3, 'M', u'歲'), + (0x2F8F4, 'M', u'殟'), + (0x2F8F5, 'M', u'殺'), + (0x2F8F6, 'M', u'殻'), + (0x2F8F7, 'M', u'𣪍'), + (0x2F8F8, 'M', u'𡴋'), + (0x2F8F9, 'M', u'𣫺'), + (0x2F8FA, 'M', u'汎'), + (0x2F8FB, 'M', u'𣲼'), + (0x2F8FC, 'M', u'沿'), + (0x2F8FD, 'M', u'泍'), + (0x2F8FE, 'M', u'汧'), + (0x2F8FF, 'M', u'洖'), + (0x2F900, 'M', u'派'), + (0x2F901, 'M', u'海'), + (0x2F902, 'M', u'流'), + (0x2F903, 'M', u'浩'), + (0x2F904, 'M', u'浸'), + ] + +def _seg_75(): + return [ + (0x2F905, 'M', u'涅'), + (0x2F906, 'M', u'𣴞'), + (0x2F907, 'M', u'洴'), + (0x2F908, 'M', u'港'), + (0x2F909, 'M', u'湮'), + (0x2F90A, 'M', u'㴳'), + (0x2F90B, 'M', u'滋'), + (0x2F90C, 'M', u'滇'), + (0x2F90D, 'M', u'𣻑'), + (0x2F90E, 'M', u'淹'), + (0x2F90F, 'M', u'潮'), + (0x2F910, 'M', u'𣽞'), + (0x2F911, 'M', u'𣾎'), + (0x2F912, 'M', u'濆'), + (0x2F913, 'M', u'瀹'), + (0x2F914, 'M', u'瀞'), + (0x2F915, 'M', u'瀛'), + (0x2F916, 'M', u'㶖'), + (0x2F917, 'M', u'灊'), + (0x2F918, 'M', u'災'), + (0x2F919, 'M', u'灷'), + (0x2F91A, 'M', u'炭'), + (0x2F91B, 'M', u'𠔥'), + (0x2F91C, 'M', u'煅'), + (0x2F91D, 'M', u'𤉣'), + (0x2F91E, 'M', u'熜'), + (0x2F91F, 'X'), + (0x2F920, 'M', u'爨'), + (0x2F921, 'M', u'爵'), + (0x2F922, 'M', u'牐'), + (0x2F923, 'M', u'𤘈'), + (0x2F924, 'M', u'犀'), + (0x2F925, 'M', u'犕'), + (0x2F926, 'M', u'𤜵'), + (0x2F927, 'M', u'𤠔'), + (0x2F928, 'M', u'獺'), + (0x2F929, 'M', u'王'), + (0x2F92A, 'M', u'㺬'), + (0x2F92B, 'M', u'玥'), + (0x2F92C, 'M', u'㺸'), + (0x2F92E, 'M', u'瑇'), + (0x2F92F, 'M', u'瑜'), + (0x2F930, 'M', u'瑱'), + (0x2F931, 'M', u'璅'), + (0x2F932, 'M', u'瓊'), + (0x2F933, 'M', u'㼛'), + (0x2F934, 'M', u'甤'), + (0x2F935, 'M', u'𤰶'), + (0x2F936, 'M', u'甾'), + (0x2F937, 'M', u'𤲒'), + (0x2F938, 'M', u'異'), + (0x2F939, 'M', u'𢆟'), + (0x2F93A, 'M', u'瘐'), + (0x2F93B, 'M', u'𤾡'), + (0x2F93C, 'M', u'𤾸'), + (0x2F93D, 'M', u'𥁄'), + (0x2F93E, 'M', u'㿼'), + (0x2F93F, 'M', u'䀈'), + (0x2F940, 'M', u'直'), + (0x2F941, 'M', u'𥃳'), + (0x2F942, 'M', u'𥃲'), + (0x2F943, 'M', u'𥄙'), + (0x2F944, 'M', u'𥄳'), + (0x2F945, 'M', u'眞'), + (0x2F946, 'M', u'真'), + (0x2F948, 'M', u'睊'), + (0x2F949, 'M', u'䀹'), + (0x2F94A, 'M', u'瞋'), + (0x2F94B, 'M', u'䁆'), + (0x2F94C, 'M', u'䂖'), + (0x2F94D, 'M', u'𥐝'), + (0x2F94E, 'M', u'硎'), + (0x2F94F, 'M', u'碌'), + (0x2F950, 'M', u'磌'), + (0x2F951, 'M', u'䃣'), + (0x2F952, 'M', u'𥘦'), + (0x2F953, 'M', u'祖'), + (0x2F954, 'M', u'𥚚'), + (0x2F955, 'M', u'𥛅'), + (0x2F956, 'M', u'福'), + (0x2F957, 'M', u'秫'), + (0x2F958, 'M', u'䄯'), + (0x2F959, 'M', u'穀'), + (0x2F95A, 'M', u'穊'), + (0x2F95B, 'M', u'穏'), + (0x2F95C, 'M', u'𥥼'), + (0x2F95D, 'M', u'𥪧'), + (0x2F95F, 'X'), + (0x2F960, 'M', u'䈂'), + (0x2F961, 'M', u'𥮫'), + (0x2F962, 'M', u'篆'), + (0x2F963, 'M', u'築'), + (0x2F964, 'M', u'䈧'), + (0x2F965, 'M', u'𥲀'), + (0x2F966, 'M', u'糒'), + (0x2F967, 'M', u'䊠'), + (0x2F968, 'M', u'糨'), + (0x2F969, 'M', u'糣'), + (0x2F96A, 'M', u'紀'), + (0x2F96B, 'M', u'𥾆'), + ] + +def _seg_76(): + return [ + (0x2F96C, 'M', u'絣'), + (0x2F96D, 'M', u'䌁'), + (0x2F96E, 'M', u'緇'), + (0x2F96F, 'M', u'縂'), + (0x2F970, 'M', u'繅'), + (0x2F971, 'M', u'䌴'), + (0x2F972, 'M', u'𦈨'), + (0x2F973, 'M', u'𦉇'), + (0x2F974, 'M', u'䍙'), + (0x2F975, 'M', u'𦋙'), + (0x2F976, 'M', u'罺'), + (0x2F977, 'M', u'𦌾'), + (0x2F978, 'M', u'羕'), + (0x2F979, 'M', u'翺'), + (0x2F97A, 'M', u'者'), + (0x2F97B, 'M', u'𦓚'), + (0x2F97C, 'M', u'𦔣'), + (0x2F97D, 'M', u'聠'), + (0x2F97E, 'M', u'𦖨'), + (0x2F97F, 'M', u'聰'), + (0x2F980, 'M', u'𣍟'), + (0x2F981, 'M', u'䏕'), + (0x2F982, 'M', u'育'), + (0x2F983, 'M', u'脃'), + (0x2F984, 'M', u'䐋'), + (0x2F985, 'M', u'脾'), + (0x2F986, 'M', u'媵'), + (0x2F987, 'M', u'𦞧'), + (0x2F988, 'M', u'𦞵'), + (0x2F989, 'M', u'𣎓'), + (0x2F98A, 'M', u'𣎜'), + (0x2F98B, 'M', u'舁'), + (0x2F98C, 'M', u'舄'), + (0x2F98D, 'M', u'辞'), + (0x2F98E, 'M', u'䑫'), + (0x2F98F, 'M', u'芑'), + (0x2F990, 'M', u'芋'), + (0x2F991, 'M', u'芝'), + (0x2F992, 'M', u'劳'), + (0x2F993, 'M', u'花'), + (0x2F994, 'M', u'芳'), + (0x2F995, 'M', u'芽'), + (0x2F996, 'M', u'苦'), + (0x2F997, 'M', u'𦬼'), + (0x2F998, 'M', u'若'), + (0x2F999, 'M', u'茝'), + (0x2F99A, 'M', u'荣'), + (0x2F99B, 'M', u'莭'), + (0x2F99C, 'M', u'茣'), + (0x2F99D, 'M', u'莽'), + (0x2F99E, 'M', u'菧'), + (0x2F99F, 'M', u'著'), + (0x2F9A0, 'M', u'荓'), + (0x2F9A1, 'M', u'菊'), + (0x2F9A2, 'M', u'菌'), + (0x2F9A3, 'M', u'菜'), + (0x2F9A4, 'M', u'𦰶'), + (0x2F9A5, 'M', u'𦵫'), + (0x2F9A6, 'M', u'𦳕'), + (0x2F9A7, 'M', u'䔫'), + (0x2F9A8, 'M', u'蓱'), + (0x2F9A9, 'M', u'蓳'), + (0x2F9AA, 'M', u'蔖'), + (0x2F9AB, 'M', u'𧏊'), + (0x2F9AC, 'M', u'蕤'), + (0x2F9AD, 'M', u'𦼬'), + (0x2F9AE, 'M', u'䕝'), + (0x2F9AF, 'M', u'䕡'), + (0x2F9B0, 'M', u'𦾱'), + (0x2F9B1, 'M', u'𧃒'), + (0x2F9B2, 'M', u'䕫'), + (0x2F9B3, 'M', u'虐'), + (0x2F9B4, 'M', u'虜'), + (0x2F9B5, 'M', u'虧'), + (0x2F9B6, 'M', u'虩'), + (0x2F9B7, 'M', u'蚩'), + (0x2F9B8, 'M', u'蚈'), + (0x2F9B9, 'M', u'蜎'), + (0x2F9BA, 'M', u'蛢'), + (0x2F9BB, 'M', u'蝹'), + (0x2F9BC, 'M', u'蜨'), + (0x2F9BD, 'M', u'蝫'), + (0x2F9BE, 'M', u'螆'), + (0x2F9BF, 'X'), + (0x2F9C0, 'M', u'蟡'), + (0x2F9C1, 'M', u'蠁'), + (0x2F9C2, 'M', u'䗹'), + (0x2F9C3, 'M', u'衠'), + (0x2F9C4, 'M', u'衣'), + (0x2F9C5, 'M', u'𧙧'), + (0x2F9C6, 'M', u'裗'), + (0x2F9C7, 'M', u'裞'), + (0x2F9C8, 'M', u'䘵'), + (0x2F9C9, 'M', u'裺'), + (0x2F9CA, 'M', u'㒻'), + (0x2F9CB, 'M', u'𧢮'), + (0x2F9CC, 'M', u'𧥦'), + (0x2F9CD, 'M', u'䚾'), + (0x2F9CE, 'M', u'䛇'), + (0x2F9CF, 'M', u'誠'), + ] + +def _seg_77(): + return [ + (0x2F9D0, 'M', u'諭'), + (0x2F9D1, 'M', u'變'), + (0x2F9D2, 'M', u'豕'), + (0x2F9D3, 'M', u'𧲨'), + (0x2F9D4, 'M', u'貫'), + (0x2F9D5, 'M', u'賁'), + (0x2F9D6, 'M', u'贛'), + (0x2F9D7, 'M', u'起'), + (0x2F9D8, 'M', u'𧼯'), + (0x2F9D9, 'M', u'𠠄'), + (0x2F9DA, 'M', u'跋'), + (0x2F9DB, 'M', u'趼'), + (0x2F9DC, 'M', u'跰'), + (0x2F9DD, 'M', u'𠣞'), + (0x2F9DE, 'M', u'軔'), + (0x2F9DF, 'M', u'輸'), + (0x2F9E0, 'M', u'𨗒'), + (0x2F9E1, 'M', u'𨗭'), + (0x2F9E2, 'M', u'邔'), + (0x2F9E3, 'M', u'郱'), + (0x2F9E4, 'M', u'鄑'), + (0x2F9E5, 'M', u'𨜮'), + (0x2F9E6, 'M', u'鄛'), + (0x2F9E7, 'M', u'鈸'), + (0x2F9E8, 'M', u'鋗'), + (0x2F9E9, 'M', u'鋘'), + (0x2F9EA, 'M', u'鉼'), + (0x2F9EB, 'M', u'鏹'), + (0x2F9EC, 'M', u'鐕'), + (0x2F9ED, 'M', u'𨯺'), + (0x2F9EE, 'M', u'開'), + (0x2F9EF, 'M', u'䦕'), + (0x2F9F0, 'M', u'閷'), + (0x2F9F1, 'M', u'𨵷'), + (0x2F9F2, 'M', u'䧦'), + (0x2F9F3, 'M', u'雃'), + (0x2F9F4, 'M', u'嶲'), + (0x2F9F5, 'M', u'霣'), + (0x2F9F6, 'M', u'𩅅'), + (0x2F9F7, 'M', u'𩈚'), + (0x2F9F8, 'M', u'䩮'), + (0x2F9F9, 'M', u'䩶'), + (0x2F9FA, 'M', u'韠'), + (0x2F9FB, 'M', u'𩐊'), + (0x2F9FC, 'M', u'䪲'), + (0x2F9FD, 'M', u'𩒖'), + (0x2F9FE, 'M', u'頋'), + (0x2FA00, 'M', u'頩'), + (0x2FA01, 'M', u'𩖶'), + (0x2FA02, 'M', u'飢'), + (0x2FA03, 'M', u'䬳'), + (0x2FA04, 'M', u'餩'), + (0x2FA05, 'M', u'馧'), + (0x2FA06, 'M', u'駂'), + (0x2FA07, 'M', u'駾'), + (0x2FA08, 'M', u'䯎'), + (0x2FA09, 'M', u'𩬰'), + (0x2FA0A, 'M', u'鬒'), + (0x2FA0B, 'M', u'鱀'), + (0x2FA0C, 'M', u'鳽'), + (0x2FA0D, 'M', u'䳎'), + (0x2FA0E, 'M', u'䳭'), + (0x2FA0F, 'M', u'鵧'), + (0x2FA10, 'M', u'𪃎'), + (0x2FA11, 'M', u'䳸'), + (0x2FA12, 'M', u'𪄅'), + (0x2FA13, 'M', u'𪈎'), + (0x2FA14, 'M', u'𪊑'), + (0x2FA15, 'M', u'麻'), + (0x2FA16, 'M', u'䵖'), + (0x2FA17, 'M', u'黹'), + (0x2FA18, 'M', u'黾'), + (0x2FA19, 'M', u'鼅'), + (0x2FA1A, 'M', u'鼏'), + (0x2FA1B, 'M', u'鼖'), + (0x2FA1C, 'M', u'鼻'), + (0x2FA1D, 'M', u'𪘀'), + (0x2FA1E, 'X'), + (0xE0100, 'I'), + (0xE01F0, 'X'), + ] + +uts46data = tuple( + _seg_0() + + _seg_1() + + _seg_2() + + _seg_3() + + _seg_4() + + _seg_5() + + _seg_6() + + _seg_7() + + _seg_8() + + _seg_9() + + _seg_10() + + _seg_11() + + _seg_12() + + _seg_13() + + _seg_14() + + _seg_15() + + _seg_16() + + _seg_17() + + _seg_18() + + _seg_19() + + _seg_20() + + _seg_21() + + _seg_22() + + _seg_23() + + _seg_24() + + _seg_25() + + _seg_26() + + _seg_27() + + _seg_28() + + _seg_29() + + _seg_30() + + _seg_31() + + _seg_32() + + _seg_33() + + _seg_34() + + _seg_35() + + _seg_36() + + _seg_37() + + _seg_38() + + _seg_39() + + _seg_40() + + _seg_41() + + _seg_42() + + _seg_43() + + _seg_44() + + _seg_45() + + _seg_46() + + _seg_47() + + _seg_48() + + _seg_49() + + _seg_50() + + _seg_51() + + _seg_52() + + _seg_53() + + _seg_54() + + _seg_55() + + _seg_56() + + _seg_57() + + _seg_58() + + _seg_59() + + _seg_60() + + _seg_61() + + _seg_62() + + _seg_63() + + _seg_64() + + _seg_65() + + _seg_66() + + _seg_67() + + _seg_68() + + _seg_69() + + _seg_70() + + _seg_71() + + _seg_72() + + _seg_73() + + _seg_74() + + _seg_75() + + _seg_76() + + _seg_77() +) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/ipaddress.py b/venv/lib/python3.7/site-packages/pip/_vendor/ipaddress.py new file mode 100644 index 0000000..f2d0766 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/ipaddress.py @@ -0,0 +1,2419 @@ +# Copyright 2007 Google Inc. +# Licensed to PSF under a Contributor Agreement. + +"""A fast, lightweight IPv4/IPv6 manipulation library in Python. + +This library is used to create/poke/manipulate IPv4 and IPv6 addresses +and networks. + +""" + +from __future__ import unicode_literals + + +import itertools +import struct + +__version__ = '1.0.22' + +# Compatibility functions +_compat_int_types = (int,) +try: + _compat_int_types = (int, long) +except NameError: + pass +try: + _compat_str = unicode +except NameError: + _compat_str = str + assert bytes != str +if b'\0'[0] == 0: # Python 3 semantics + def _compat_bytes_to_byte_vals(byt): + return byt +else: + def _compat_bytes_to_byte_vals(byt): + return [struct.unpack(b'!B', b)[0] for b in byt] +try: + _compat_int_from_byte_vals = int.from_bytes +except AttributeError: + def _compat_int_from_byte_vals(bytvals, endianess): + assert endianess == 'big' + res = 0 + for bv in bytvals: + assert isinstance(bv, _compat_int_types) + res = (res << 8) + bv + return res + + +def _compat_to_bytes(intval, length, endianess): + assert isinstance(intval, _compat_int_types) + assert endianess == 'big' + if length == 4: + if intval < 0 or intval >= 2 ** 32: + raise struct.error("integer out of range for 'I' format code") + return struct.pack(b'!I', intval) + elif length == 16: + if intval < 0 or intval >= 2 ** 128: + raise struct.error("integer out of range for 'QQ' format code") + return struct.pack(b'!QQ', intval >> 64, intval & 0xffffffffffffffff) + else: + raise NotImplementedError() + + +if hasattr(int, 'bit_length'): + # Not int.bit_length , since that won't work in 2.7 where long exists + def _compat_bit_length(i): + return i.bit_length() +else: + def _compat_bit_length(i): + for res in itertools.count(): + if i >> res == 0: + return res + + +def _compat_range(start, end, step=1): + assert step > 0 + i = start + while i < end: + yield i + i += step + + +class _TotalOrderingMixin(object): + __slots__ = () + + # Helper that derives the other comparison operations from + # __lt__ and __eq__ + # We avoid functools.total_ordering because it doesn't handle + # NotImplemented correctly yet (http://bugs.python.org/issue10042) + def __eq__(self, other): + raise NotImplementedError + + def __ne__(self, other): + equal = self.__eq__(other) + if equal is NotImplemented: + return NotImplemented + return not equal + + def __lt__(self, other): + raise NotImplementedError + + def __le__(self, other): + less = self.__lt__(other) + if less is NotImplemented or not less: + return self.__eq__(other) + return less + + def __gt__(self, other): + less = self.__lt__(other) + if less is NotImplemented: + return NotImplemented + equal = self.__eq__(other) + if equal is NotImplemented: + return NotImplemented + return not (less or equal) + + def __ge__(self, other): + less = self.__lt__(other) + if less is NotImplemented: + return NotImplemented + return not less + + +IPV4LENGTH = 32 +IPV6LENGTH = 128 + + +class AddressValueError(ValueError): + """A Value Error related to the address.""" + + +class NetmaskValueError(ValueError): + """A Value Error related to the netmask.""" + + +def ip_address(address): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP address. Either IPv4 or + IPv6 addresses may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + + Returns: + An IPv4Address or IPv6Address object. + + Raises: + ValueError: if the *address* passed isn't either a v4 or a v6 + address + + """ + try: + return IPv4Address(address) + except (AddressValueError, NetmaskValueError): + pass + + try: + return IPv6Address(address) + except (AddressValueError, NetmaskValueError): + pass + + if isinstance(address, bytes): + raise AddressValueError( + '%r does not appear to be an IPv4 or IPv6 address. ' + 'Did you pass in a bytes (str in Python 2) instead of' + ' a unicode object?' % address) + + raise ValueError('%r does not appear to be an IPv4 or IPv6 address' % + address) + + +def ip_network(address, strict=True): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP network. Either IPv4 or + IPv6 networks may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + + Returns: + An IPv4Network or IPv6Network object. + + Raises: + ValueError: if the string passed isn't either a v4 or a v6 + address. Or if the network has host bits set. + + """ + try: + return IPv4Network(address, strict) + except (AddressValueError, NetmaskValueError): + pass + + try: + return IPv6Network(address, strict) + except (AddressValueError, NetmaskValueError): + pass + + if isinstance(address, bytes): + raise AddressValueError( + '%r does not appear to be an IPv4 or IPv6 network. ' + 'Did you pass in a bytes (str in Python 2) instead of' + ' a unicode object?' % address) + + raise ValueError('%r does not appear to be an IPv4 or IPv6 network' % + address) + + +def ip_interface(address): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP address. Either IPv4 or + IPv6 addresses may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + + Returns: + An IPv4Interface or IPv6Interface object. + + Raises: + ValueError: if the string passed isn't either a v4 or a v6 + address. + + Notes: + The IPv?Interface classes describe an Address on a particular + Network, so they're basically a combination of both the Address + and Network classes. + + """ + try: + return IPv4Interface(address) + except (AddressValueError, NetmaskValueError): + pass + + try: + return IPv6Interface(address) + except (AddressValueError, NetmaskValueError): + pass + + raise ValueError('%r does not appear to be an IPv4 or IPv6 interface' % + address) + + +def v4_int_to_packed(address): + """Represent an address as 4 packed bytes in network (big-endian) order. + + Args: + address: An integer representation of an IPv4 IP address. + + Returns: + The integer address packed as 4 bytes in network (big-endian) order. + + Raises: + ValueError: If the integer is negative or too large to be an + IPv4 IP address. + + """ + try: + return _compat_to_bytes(address, 4, 'big') + except (struct.error, OverflowError): + raise ValueError("Address negative or too large for IPv4") + + +def v6_int_to_packed(address): + """Represent an address as 16 packed bytes in network (big-endian) order. + + Args: + address: An integer representation of an IPv6 IP address. + + Returns: + The integer address packed as 16 bytes in network (big-endian) order. + + """ + try: + return _compat_to_bytes(address, 16, 'big') + except (struct.error, OverflowError): + raise ValueError("Address negative or too large for IPv6") + + +def _split_optional_netmask(address): + """Helper to split the netmask and raise AddressValueError if needed""" + addr = _compat_str(address).split('/') + if len(addr) > 2: + raise AddressValueError("Only one '/' permitted in %r" % address) + return addr + + +def _find_address_range(addresses): + """Find a sequence of sorted deduplicated IPv#Address. + + Args: + addresses: a list of IPv#Address objects. + + Yields: + A tuple containing the first and last IP addresses in the sequence. + + """ + it = iter(addresses) + first = last = next(it) + for ip in it: + if ip._ip != last._ip + 1: + yield first, last + first = ip + last = ip + yield first, last + + +def _count_righthand_zero_bits(number, bits): + """Count the number of zero bits on the right hand side. + + Args: + number: an integer. + bits: maximum number of bits to count. + + Returns: + The number of zero bits on the right hand side of the number. + + """ + if number == 0: + return bits + return min(bits, _compat_bit_length(~number & (number - 1))) + + +def summarize_address_range(first, last): + """Summarize a network range given the first and last IP addresses. + + Example: + >>> list(summarize_address_range(IPv4Address('192.0.2.0'), + ... IPv4Address('192.0.2.130'))) + ... #doctest: +NORMALIZE_WHITESPACE + [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'), + IPv4Network('192.0.2.130/32')] + + Args: + first: the first IPv4Address or IPv6Address in the range. + last: the last IPv4Address or IPv6Address in the range. + + Returns: + An iterator of the summarized IPv(4|6) network objects. + + Raise: + TypeError: + If the first and last objects are not IP addresses. + If the first and last objects are not the same version. + ValueError: + If the last object is not greater than the first. + If the version of the first address is not 4 or 6. + + """ + if (not (isinstance(first, _BaseAddress) and + isinstance(last, _BaseAddress))): + raise TypeError('first and last must be IP addresses, not networks') + if first.version != last.version: + raise TypeError("%s and %s are not of the same version" % ( + first, last)) + if first > last: + raise ValueError('last IP address must be greater than first') + + if first.version == 4: + ip = IPv4Network + elif first.version == 6: + ip = IPv6Network + else: + raise ValueError('unknown IP version') + + ip_bits = first._max_prefixlen + first_int = first._ip + last_int = last._ip + while first_int <= last_int: + nbits = min(_count_righthand_zero_bits(first_int, ip_bits), + _compat_bit_length(last_int - first_int + 1) - 1) + net = ip((first_int, ip_bits - nbits)) + yield net + first_int += 1 << nbits + if first_int - 1 == ip._ALL_ONES: + break + + +def _collapse_addresses_internal(addresses): + """Loops through the addresses, collapsing concurrent netblocks. + + Example: + + ip1 = IPv4Network('192.0.2.0/26') + ip2 = IPv4Network('192.0.2.64/26') + ip3 = IPv4Network('192.0.2.128/26') + ip4 = IPv4Network('192.0.2.192/26') + + _collapse_addresses_internal([ip1, ip2, ip3, ip4]) -> + [IPv4Network('192.0.2.0/24')] + + This shouldn't be called directly; it is called via + collapse_addresses([]). + + Args: + addresses: A list of IPv4Network's or IPv6Network's + + Returns: + A list of IPv4Network's or IPv6Network's depending on what we were + passed. + + """ + # First merge + to_merge = list(addresses) + subnets = {} + while to_merge: + net = to_merge.pop() + supernet = net.supernet() + existing = subnets.get(supernet) + if existing is None: + subnets[supernet] = net + elif existing != net: + # Merge consecutive subnets + del subnets[supernet] + to_merge.append(supernet) + # Then iterate over resulting networks, skipping subsumed subnets + last = None + for net in sorted(subnets.values()): + if last is not None: + # Since they are sorted, + # last.network_address <= net.network_address is a given. + if last.broadcast_address >= net.broadcast_address: + continue + yield net + last = net + + +def collapse_addresses(addresses): + """Collapse a list of IP objects. + + Example: + collapse_addresses([IPv4Network('192.0.2.0/25'), + IPv4Network('192.0.2.128/25')]) -> + [IPv4Network('192.0.2.0/24')] + + Args: + addresses: An iterator of IPv4Network or IPv6Network objects. + + Returns: + An iterator of the collapsed IPv(4|6)Network objects. + + Raises: + TypeError: If passed a list of mixed version objects. + + """ + addrs = [] + ips = [] + nets = [] + + # split IP addresses and networks + for ip in addresses: + if isinstance(ip, _BaseAddress): + if ips and ips[-1]._version != ip._version: + raise TypeError("%s and %s are not of the same version" % ( + ip, ips[-1])) + ips.append(ip) + elif ip._prefixlen == ip._max_prefixlen: + if ips and ips[-1]._version != ip._version: + raise TypeError("%s and %s are not of the same version" % ( + ip, ips[-1])) + try: + ips.append(ip.ip) + except AttributeError: + ips.append(ip.network_address) + else: + if nets and nets[-1]._version != ip._version: + raise TypeError("%s and %s are not of the same version" % ( + ip, nets[-1])) + nets.append(ip) + + # sort and dedup + ips = sorted(set(ips)) + + # find consecutive address ranges in the sorted sequence and summarize them + if ips: + for first, last in _find_address_range(ips): + addrs.extend(summarize_address_range(first, last)) + + return _collapse_addresses_internal(addrs + nets) + + +def get_mixed_type_key(obj): + """Return a key suitable for sorting between networks and addresses. + + Address and Network objects are not sortable by default; they're + fundamentally different so the expression + + IPv4Address('192.0.2.0') <= IPv4Network('192.0.2.0/24') + + doesn't make any sense. There are some times however, where you may wish + to have ipaddress sort these for you anyway. If you need to do this, you + can use this function as the key= argument to sorted(). + + Args: + obj: either a Network or Address object. + Returns: + appropriate key. + + """ + if isinstance(obj, _BaseNetwork): + return obj._get_networks_key() + elif isinstance(obj, _BaseAddress): + return obj._get_address_key() + return NotImplemented + + +class _IPAddressBase(_TotalOrderingMixin): + + """The mother class.""" + + __slots__ = () + + @property + def exploded(self): + """Return the longhand version of the IP address as a string.""" + return self._explode_shorthand_ip_string() + + @property + def compressed(self): + """Return the shorthand version of the IP address as a string.""" + return _compat_str(self) + + @property + def reverse_pointer(self): + """The name of the reverse DNS pointer for the IP address, e.g.: + >>> ipaddress.ip_address("127.0.0.1").reverse_pointer + '1.0.0.127.in-addr.arpa' + >>> ipaddress.ip_address("2001:db8::1").reverse_pointer + '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa' + + """ + return self._reverse_pointer() + + @property + def version(self): + msg = '%200s has no version specified' % (type(self),) + raise NotImplementedError(msg) + + def _check_int_address(self, address): + if address < 0: + msg = "%d (< 0) is not permitted as an IPv%d address" + raise AddressValueError(msg % (address, self._version)) + if address > self._ALL_ONES: + msg = "%d (>= 2**%d) is not permitted as an IPv%d address" + raise AddressValueError(msg % (address, self._max_prefixlen, + self._version)) + + def _check_packed_address(self, address, expected_len): + address_len = len(address) + if address_len != expected_len: + msg = ( + '%r (len %d != %d) is not permitted as an IPv%d address. ' + 'Did you pass in a bytes (str in Python 2) instead of' + ' a unicode object?') + raise AddressValueError(msg % (address, address_len, + expected_len, self._version)) + + @classmethod + def _ip_int_from_prefix(cls, prefixlen): + """Turn the prefix length into a bitwise netmask + + Args: + prefixlen: An integer, the prefix length. + + Returns: + An integer. + + """ + return cls._ALL_ONES ^ (cls._ALL_ONES >> prefixlen) + + @classmethod + def _prefix_from_ip_int(cls, ip_int): + """Return prefix length from the bitwise netmask. + + Args: + ip_int: An integer, the netmask in expanded bitwise format + + Returns: + An integer, the prefix length. + + Raises: + ValueError: If the input intermingles zeroes & ones + """ + trailing_zeroes = _count_righthand_zero_bits(ip_int, + cls._max_prefixlen) + prefixlen = cls._max_prefixlen - trailing_zeroes + leading_ones = ip_int >> trailing_zeroes + all_ones = (1 << prefixlen) - 1 + if leading_ones != all_ones: + byteslen = cls._max_prefixlen // 8 + details = _compat_to_bytes(ip_int, byteslen, 'big') + msg = 'Netmask pattern %r mixes zeroes & ones' + raise ValueError(msg % details) + return prefixlen + + @classmethod + def _report_invalid_netmask(cls, netmask_str): + msg = '%r is not a valid netmask' % netmask_str + raise NetmaskValueError(msg) + + @classmethod + def _prefix_from_prefix_string(cls, prefixlen_str): + """Return prefix length from a numeric string + + Args: + prefixlen_str: The string to be converted + + Returns: + An integer, the prefix length. + + Raises: + NetmaskValueError: If the input is not a valid netmask + """ + # int allows a leading +/- as well as surrounding whitespace, + # so we ensure that isn't the case + if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): + cls._report_invalid_netmask(prefixlen_str) + try: + prefixlen = int(prefixlen_str) + except ValueError: + cls._report_invalid_netmask(prefixlen_str) + if not (0 <= prefixlen <= cls._max_prefixlen): + cls._report_invalid_netmask(prefixlen_str) + return prefixlen + + @classmethod + def _prefix_from_ip_string(cls, ip_str): + """Turn a netmask/hostmask string into a prefix length + + Args: + ip_str: The netmask/hostmask to be converted + + Returns: + An integer, the prefix length. + + Raises: + NetmaskValueError: If the input is not a valid netmask/hostmask + """ + # Parse the netmask/hostmask like an IP address. + try: + ip_int = cls._ip_int_from_string(ip_str) + except AddressValueError: + cls._report_invalid_netmask(ip_str) + + # Try matching a netmask (this would be /1*0*/ as a bitwise regexp). + # Note that the two ambiguous cases (all-ones and all-zeroes) are + # treated as netmasks. + try: + return cls._prefix_from_ip_int(ip_int) + except ValueError: + pass + + # Invert the bits, and try matching a /0+1+/ hostmask instead. + ip_int ^= cls._ALL_ONES + try: + return cls._prefix_from_ip_int(ip_int) + except ValueError: + cls._report_invalid_netmask(ip_str) + + def __reduce__(self): + return self.__class__, (_compat_str(self),) + + +class _BaseAddress(_IPAddressBase): + + """A generic IP object. + + This IP class contains the version independent methods which are + used by single IP addresses. + """ + + __slots__ = () + + def __int__(self): + return self._ip + + def __eq__(self, other): + try: + return (self._ip == other._ip and + self._version == other._version) + except AttributeError: + return NotImplemented + + def __lt__(self, other): + if not isinstance(other, _IPAddressBase): + return NotImplemented + if not isinstance(other, _BaseAddress): + raise TypeError('%s and %s are not of the same type' % ( + self, other)) + if self._version != other._version: + raise TypeError('%s and %s are not of the same version' % ( + self, other)) + if self._ip != other._ip: + return self._ip < other._ip + return False + + # Shorthand for Integer addition and subtraction. This is not + # meant to ever support addition/subtraction of addresses. + def __add__(self, other): + if not isinstance(other, _compat_int_types): + return NotImplemented + return self.__class__(int(self) + other) + + def __sub__(self, other): + if not isinstance(other, _compat_int_types): + return NotImplemented + return self.__class__(int(self) - other) + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, _compat_str(self)) + + def __str__(self): + return _compat_str(self._string_from_ip_int(self._ip)) + + def __hash__(self): + return hash(hex(int(self._ip))) + + def _get_address_key(self): + return (self._version, self) + + def __reduce__(self): + return self.__class__, (self._ip,) + + +class _BaseNetwork(_IPAddressBase): + + """A generic IP network object. + + This IP class contains the version independent methods which are + used by networks. + + """ + def __init__(self, address): + self._cache = {} + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, _compat_str(self)) + + def __str__(self): + return '%s/%d' % (self.network_address, self.prefixlen) + + def hosts(self): + """Generate Iterator over usable hosts in a network. + + This is like __iter__ except it doesn't return the network + or broadcast addresses. + + """ + network = int(self.network_address) + broadcast = int(self.broadcast_address) + for x in _compat_range(network + 1, broadcast): + yield self._address_class(x) + + def __iter__(self): + network = int(self.network_address) + broadcast = int(self.broadcast_address) + for x in _compat_range(network, broadcast + 1): + yield self._address_class(x) + + def __getitem__(self, n): + network = int(self.network_address) + broadcast = int(self.broadcast_address) + if n >= 0: + if network + n > broadcast: + raise IndexError('address out of range') + return self._address_class(network + n) + else: + n += 1 + if broadcast + n < network: + raise IndexError('address out of range') + return self._address_class(broadcast + n) + + def __lt__(self, other): + if not isinstance(other, _IPAddressBase): + return NotImplemented + if not isinstance(other, _BaseNetwork): + raise TypeError('%s and %s are not of the same type' % ( + self, other)) + if self._version != other._version: + raise TypeError('%s and %s are not of the same version' % ( + self, other)) + if self.network_address != other.network_address: + return self.network_address < other.network_address + if self.netmask != other.netmask: + return self.netmask < other.netmask + return False + + def __eq__(self, other): + try: + return (self._version == other._version and + self.network_address == other.network_address and + int(self.netmask) == int(other.netmask)) + except AttributeError: + return NotImplemented + + def __hash__(self): + return hash(int(self.network_address) ^ int(self.netmask)) + + def __contains__(self, other): + # always false if one is v4 and the other is v6. + if self._version != other._version: + return False + # dealing with another network. + if isinstance(other, _BaseNetwork): + return False + # dealing with another address + else: + # address + return (int(self.network_address) <= int(other._ip) <= + int(self.broadcast_address)) + + def overlaps(self, other): + """Tell if self is partly contained in other.""" + return self.network_address in other or ( + self.broadcast_address in other or ( + other.network_address in self or ( + other.broadcast_address in self))) + + @property + def broadcast_address(self): + x = self._cache.get('broadcast_address') + if x is None: + x = self._address_class(int(self.network_address) | + int(self.hostmask)) + self._cache['broadcast_address'] = x + return x + + @property + def hostmask(self): + x = self._cache.get('hostmask') + if x is None: + x = self._address_class(int(self.netmask) ^ self._ALL_ONES) + self._cache['hostmask'] = x + return x + + @property + def with_prefixlen(self): + return '%s/%d' % (self.network_address, self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (self.network_address, self.netmask) + + @property + def with_hostmask(self): + return '%s/%s' % (self.network_address, self.hostmask) + + @property + def num_addresses(self): + """Number of hosts in the current subnet.""" + return int(self.broadcast_address) - int(self.network_address) + 1 + + @property + def _address_class(self): + # Returning bare address objects (rather than interfaces) allows for + # more consistent behaviour across the network address, broadcast + # address and individual host addresses. + msg = '%200s has no associated address class' % (type(self),) + raise NotImplementedError(msg) + + @property + def prefixlen(self): + return self._prefixlen + + def address_exclude(self, other): + """Remove an address from a larger block. + + For example: + + addr1 = ip_network('192.0.2.0/28') + addr2 = ip_network('192.0.2.1/32') + list(addr1.address_exclude(addr2)) = + [IPv4Network('192.0.2.0/32'), IPv4Network('192.0.2.2/31'), + IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')] + + or IPv6: + + addr1 = ip_network('2001:db8::1/32') + addr2 = ip_network('2001:db8::1/128') + list(addr1.address_exclude(addr2)) = + [ip_network('2001:db8::1/128'), + ip_network('2001:db8::2/127'), + ip_network('2001:db8::4/126'), + ip_network('2001:db8::8/125'), + ... + ip_network('2001:db8:8000::/33')] + + Args: + other: An IPv4Network or IPv6Network object of the same type. + + Returns: + An iterator of the IPv(4|6)Network objects which is self + minus other. + + Raises: + TypeError: If self and other are of differing address + versions, or if other is not a network object. + ValueError: If other is not completely contained by self. + + """ + if not self._version == other._version: + raise TypeError("%s and %s are not of the same version" % ( + self, other)) + + if not isinstance(other, _BaseNetwork): + raise TypeError("%s is not a network object" % other) + + if not other.subnet_of(self): + raise ValueError('%s not contained in %s' % (other, self)) + if other == self: + return + + # Make sure we're comparing the network of other. + other = other.__class__('%s/%s' % (other.network_address, + other.prefixlen)) + + s1, s2 = self.subnets() + while s1 != other and s2 != other: + if other.subnet_of(s1): + yield s2 + s1, s2 = s1.subnets() + elif other.subnet_of(s2): + yield s1 + s1, s2 = s2.subnets() + else: + # If we got here, there's a bug somewhere. + raise AssertionError('Error performing exclusion: ' + 's1: %s s2: %s other: %s' % + (s1, s2, other)) + if s1 == other: + yield s2 + elif s2 == other: + yield s1 + else: + # If we got here, there's a bug somewhere. + raise AssertionError('Error performing exclusion: ' + 's1: %s s2: %s other: %s' % + (s1, s2, other)) + + def compare_networks(self, other): + """Compare two IP objects. + + This is only concerned about the comparison of the integer + representation of the network addresses. This means that the + host bits aren't considered at all in this method. If you want + to compare host bits, you can easily enough do a + 'HostA._ip < HostB._ip' + + Args: + other: An IP object. + + Returns: + If the IP versions of self and other are the same, returns: + + -1 if self < other: + eg: IPv4Network('192.0.2.0/25') < IPv4Network('192.0.2.128/25') + IPv6Network('2001:db8::1000/124') < + IPv6Network('2001:db8::2000/124') + 0 if self == other + eg: IPv4Network('192.0.2.0/24') == IPv4Network('192.0.2.0/24') + IPv6Network('2001:db8::1000/124') == + IPv6Network('2001:db8::1000/124') + 1 if self > other + eg: IPv4Network('192.0.2.128/25') > IPv4Network('192.0.2.0/25') + IPv6Network('2001:db8::2000/124') > + IPv6Network('2001:db8::1000/124') + + Raises: + TypeError if the IP versions are different. + + """ + # does this need to raise a ValueError? + if self._version != other._version: + raise TypeError('%s and %s are not of the same type' % ( + self, other)) + # self._version == other._version below here: + if self.network_address < other.network_address: + return -1 + if self.network_address > other.network_address: + return 1 + # self.network_address == other.network_address below here: + if self.netmask < other.netmask: + return -1 + if self.netmask > other.netmask: + return 1 + return 0 + + def _get_networks_key(self): + """Network-only key function. + + Returns an object that identifies this address' network and + netmask. This function is a suitable "key" argument for sorted() + and list.sort(). + + """ + return (self._version, self.network_address, self.netmask) + + def subnets(self, prefixlen_diff=1, new_prefix=None): + """The subnets which join to make the current subnet. + + In the case that self contains only one IP + (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 + for IPv6), yield an iterator with just ourself. + + Args: + prefixlen_diff: An integer, the amount the prefix length + should be increased by. This should not be set if + new_prefix is also set. + new_prefix: The desired new prefix length. This must be a + larger number (smaller prefix) than the existing prefix. + This should not be set if prefixlen_diff is also set. + + Returns: + An iterator of IPv(4|6) objects. + + Raises: + ValueError: The prefixlen_diff is too small or too large. + OR + prefixlen_diff and new_prefix are both set or new_prefix + is a smaller number than the current prefix (smaller + number means a larger network) + + """ + if self._prefixlen == self._max_prefixlen: + yield self + return + + if new_prefix is not None: + if new_prefix < self._prefixlen: + raise ValueError('new prefix must be longer') + if prefixlen_diff != 1: + raise ValueError('cannot set prefixlen_diff and new_prefix') + prefixlen_diff = new_prefix - self._prefixlen + + if prefixlen_diff < 0: + raise ValueError('prefix length diff must be > 0') + new_prefixlen = self._prefixlen + prefixlen_diff + + if new_prefixlen > self._max_prefixlen: + raise ValueError( + 'prefix length diff %d is invalid for netblock %s' % ( + new_prefixlen, self)) + + start = int(self.network_address) + end = int(self.broadcast_address) + 1 + step = (int(self.hostmask) + 1) >> prefixlen_diff + for new_addr in _compat_range(start, end, step): + current = self.__class__((new_addr, new_prefixlen)) + yield current + + def supernet(self, prefixlen_diff=1, new_prefix=None): + """The supernet containing the current network. + + Args: + prefixlen_diff: An integer, the amount the prefix length of + the network should be decreased by. For example, given a + /24 network and a prefixlen_diff of 3, a supernet with a + /21 netmask is returned. + + Returns: + An IPv4 network object. + + Raises: + ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have + a negative prefix length. + OR + If prefixlen_diff and new_prefix are both set or new_prefix is a + larger number than the current prefix (larger number means a + smaller network) + + """ + if self._prefixlen == 0: + return self + + if new_prefix is not None: + if new_prefix > self._prefixlen: + raise ValueError('new prefix must be shorter') + if prefixlen_diff != 1: + raise ValueError('cannot set prefixlen_diff and new_prefix') + prefixlen_diff = self._prefixlen - new_prefix + + new_prefixlen = self.prefixlen - prefixlen_diff + if new_prefixlen < 0: + raise ValueError( + 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % + (self.prefixlen, prefixlen_diff)) + return self.__class__(( + int(self.network_address) & (int(self.netmask) << prefixlen_diff), + new_prefixlen)) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is a multicast address. + See RFC 2373 2.7 for details. + + """ + return (self.network_address.is_multicast and + self.broadcast_address.is_multicast) + + @staticmethod + def _is_subnet_of(a, b): + try: + # Always false if one is v4 and the other is v6. + if a._version != b._version: + raise TypeError("%s and %s are not of the same version" (a, b)) + return (b.network_address <= a.network_address and + b.broadcast_address >= a.broadcast_address) + except AttributeError: + raise TypeError("Unable to test subnet containment " + "between %s and %s" % (a, b)) + + def subnet_of(self, other): + """Return True if this network is a subnet of other.""" + return self._is_subnet_of(self, other) + + def supernet_of(self, other): + """Return True if this network is a supernet of other.""" + return self._is_subnet_of(other, self) + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within one of the + reserved IPv6 Network ranges. + + """ + return (self.network_address.is_reserved and + self.broadcast_address.is_reserved) + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is reserved per RFC 4291. + + """ + return (self.network_address.is_link_local and + self.broadcast_address.is_link_local) + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per + iana-ipv4-special-registry or iana-ipv6-special-registry. + + """ + return (self.network_address.is_private and + self.broadcast_address.is_private) + + @property + def is_global(self): + """Test if this address is allocated for public networks. + + Returns: + A boolean, True if the address is not reserved per + iana-ipv4-special-registry or iana-ipv6-special-registry. + + """ + return not self.is_private + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 2373 2.5.2. + + """ + return (self.network_address.is_unspecified and + self.broadcast_address.is_unspecified) + + @property + def is_loopback(self): + """Test if the address is a loopback address. + + Returns: + A boolean, True if the address is a loopback address as defined in + RFC 2373 2.5.3. + + """ + return (self.network_address.is_loopback and + self.broadcast_address.is_loopback) + + +class _BaseV4(object): + + """Base IPv4 object. + + The following methods are used by IPv4 objects in both single IP + addresses and networks. + + """ + + __slots__ = () + _version = 4 + # Equivalent to 255.255.255.255 or 32 bits of 1's. + _ALL_ONES = (2 ** IPV4LENGTH) - 1 + _DECIMAL_DIGITS = frozenset('0123456789') + + # the valid octets for host and netmasks. only useful for IPv4. + _valid_mask_octets = frozenset([255, 254, 252, 248, 240, 224, 192, 128, 0]) + + _max_prefixlen = IPV4LENGTH + # There are only a handful of valid v4 netmasks, so we cache them all + # when constructed (see _make_netmask()). + _netmask_cache = {} + + def _explode_shorthand_ip_string(self): + return _compat_str(self) + + @classmethod + def _make_netmask(cls, arg): + """Make a (netmask, prefix_len) tuple from the given argument. + + Argument can be: + - an integer (the prefix length) + - a string representing the prefix length (e.g. "24") + - a string representing the prefix netmask (e.g. "255.255.255.0") + """ + if arg not in cls._netmask_cache: + if isinstance(arg, _compat_int_types): + prefixlen = arg + else: + try: + # Check for a netmask in prefix length form + prefixlen = cls._prefix_from_prefix_string(arg) + except NetmaskValueError: + # Check for a netmask or hostmask in dotted-quad form. + # This may raise NetmaskValueError. + prefixlen = cls._prefix_from_ip_string(arg) + netmask = IPv4Address(cls._ip_int_from_prefix(prefixlen)) + cls._netmask_cache[arg] = netmask, prefixlen + return cls._netmask_cache[arg] + + @classmethod + def _ip_int_from_string(cls, ip_str): + """Turn the given IP string into an integer for comparison. + + Args: + ip_str: A string, the IP ip_str. + + Returns: + The IP ip_str as an integer. + + Raises: + AddressValueError: if ip_str isn't a valid IPv4 Address. + + """ + if not ip_str: + raise AddressValueError('Address cannot be empty') + + octets = ip_str.split('.') + if len(octets) != 4: + raise AddressValueError("Expected 4 octets in %r" % ip_str) + + try: + return _compat_int_from_byte_vals( + map(cls._parse_octet, octets), 'big') + except ValueError as exc: + raise AddressValueError("%s in %r" % (exc, ip_str)) + + @classmethod + def _parse_octet(cls, octet_str): + """Convert a decimal octet into an integer. + + Args: + octet_str: A string, the number to parse. + + Returns: + The octet as an integer. + + Raises: + ValueError: if the octet isn't strictly a decimal from [0..255]. + + """ + if not octet_str: + raise ValueError("Empty octet not permitted") + # Whitelist the characters, since int() allows a lot of bizarre stuff. + if not cls._DECIMAL_DIGITS.issuperset(octet_str): + msg = "Only decimal digits permitted in %r" + raise ValueError(msg % octet_str) + # We do the length check second, since the invalid character error + # is likely to be more informative for the user + if len(octet_str) > 3: + msg = "At most 3 characters permitted in %r" + raise ValueError(msg % octet_str) + # Convert to integer (we know digits are legal) + octet_int = int(octet_str, 10) + # Any octets that look like they *might* be written in octal, + # and which don't look exactly the same in both octal and + # decimal are rejected as ambiguous + if octet_int > 7 and octet_str[0] == '0': + msg = "Ambiguous (octal/decimal) value in %r not permitted" + raise ValueError(msg % octet_str) + if octet_int > 255: + raise ValueError("Octet %d (> 255) not permitted" % octet_int) + return octet_int + + @classmethod + def _string_from_ip_int(cls, ip_int): + """Turns a 32-bit integer into dotted decimal notation. + + Args: + ip_int: An integer, the IP address. + + Returns: + The IP address as a string in dotted decimal notation. + + """ + return '.'.join(_compat_str(struct.unpack(b'!B', b)[0] + if isinstance(b, bytes) + else b) + for b in _compat_to_bytes(ip_int, 4, 'big')) + + def _is_hostmask(self, ip_str): + """Test if the IP string is a hostmask (rather than a netmask). + + Args: + ip_str: A string, the potential hostmask. + + Returns: + A boolean, True if the IP string is a hostmask. + + """ + bits = ip_str.split('.') + try: + parts = [x for x in map(int, bits) if x in self._valid_mask_octets] + except ValueError: + return False + if len(parts) != len(bits): + return False + if parts[0] < parts[-1]: + return True + return False + + def _reverse_pointer(self): + """Return the reverse DNS pointer name for the IPv4 address. + + This implements the method described in RFC1035 3.5. + + """ + reverse_octets = _compat_str(self).split('.')[::-1] + return '.'.join(reverse_octets) + '.in-addr.arpa' + + @property + def max_prefixlen(self): + return self._max_prefixlen + + @property + def version(self): + return self._version + + +class IPv4Address(_BaseV4, _BaseAddress): + + """Represent and manipulate single IPv4 Addresses.""" + + __slots__ = ('_ip', '__weakref__') + + def __init__(self, address): + + """ + Args: + address: A string or integer representing the IP + + Additionally, an integer can be passed, so + IPv4Address('192.0.2.1') == IPv4Address(3221225985). + or, more generally + IPv4Address(int(IPv4Address('192.0.2.1'))) == + IPv4Address('192.0.2.1') + + Raises: + AddressValueError: If ipaddress isn't a valid IPv4 address. + + """ + # Efficient constructor from integer. + if isinstance(address, _compat_int_types): + self._check_int_address(address) + self._ip = address + return + + # Constructing from a packed address + if isinstance(address, bytes): + self._check_packed_address(address, 4) + bvs = _compat_bytes_to_byte_vals(address) + self._ip = _compat_int_from_byte_vals(bvs, 'big') + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP string. + addr_str = _compat_str(address) + if '/' in addr_str: + raise AddressValueError("Unexpected '/' in %r" % address) + self._ip = self._ip_int_from_string(addr_str) + + @property + def packed(self): + """The binary representation of this address.""" + return v4_int_to_packed(self._ip) + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within the + reserved IPv4 Network range. + + """ + return self in self._constants._reserved_network + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per + iana-ipv4-special-registry. + + """ + return any(self in net for net in self._constants._private_networks) + + @property + def is_global(self): + return ( + self not in self._constants._public_network and + not self.is_private) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is multicast. + See RFC 3171 for details. + + """ + return self in self._constants._multicast_network + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 5735 3. + + """ + return self == self._constants._unspecified_address + + @property + def is_loopback(self): + """Test if the address is a loopback address. + + Returns: + A boolean, True if the address is a loopback per RFC 3330. + + """ + return self in self._constants._loopback_network + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is link-local per RFC 3927. + + """ + return self in self._constants._linklocal_network + + +class IPv4Interface(IPv4Address): + + def __init__(self, address): + if isinstance(address, (bytes, _compat_int_types)): + IPv4Address.__init__(self, address) + self.network = IPv4Network(self._ip) + self._prefixlen = self._max_prefixlen + return + + if isinstance(address, tuple): + IPv4Address.__init__(self, address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + + self.network = IPv4Network(address, strict=False) + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + return + + addr = _split_optional_netmask(address) + IPv4Address.__init__(self, addr[0]) + + self.network = IPv4Network(address, strict=False) + self._prefixlen = self.network._prefixlen + + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + + def __str__(self): + return '%s/%d' % (self._string_from_ip_int(self._ip), + self.network.prefixlen) + + def __eq__(self, other): + address_equal = IPv4Address.__eq__(self, other) + if not address_equal or address_equal is NotImplemented: + return address_equal + try: + return self.network == other.network + except AttributeError: + # An interface with an associated network is NOT the + # same as an unassociated address. That's why the hash + # takes the extra info into account. + return False + + def __lt__(self, other): + address_less = IPv4Address.__lt__(self, other) + if address_less is NotImplemented: + return NotImplemented + try: + return (self.network < other.network or + self.network == other.network and address_less) + except AttributeError: + # We *do* allow addresses and interfaces to be sorted. The + # unassociated address is considered less than all interfaces. + return False + + def __hash__(self): + return self._ip ^ self._prefixlen ^ int(self.network.network_address) + + __reduce__ = _IPAddressBase.__reduce__ + + @property + def ip(self): + return IPv4Address(self._ip) + + @property + def with_prefixlen(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.netmask) + + @property + def with_hostmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.hostmask) + + +class IPv4Network(_BaseV4, _BaseNetwork): + + """This class represents and manipulates 32-bit IPv4 network + addresses.. + + Attributes: [examples for IPv4Network('192.0.2.0/27')] + .network_address: IPv4Address('192.0.2.0') + .hostmask: IPv4Address('0.0.0.31') + .broadcast_address: IPv4Address('192.0.2.32') + .netmask: IPv4Address('255.255.255.224') + .prefixlen: 27 + + """ + # Class to use when creating address objects + _address_class = IPv4Address + + def __init__(self, address, strict=True): + + """Instantiate a new IPv4 network object. + + Args: + address: A string or integer representing the IP [& network]. + '192.0.2.0/24' + '192.0.2.0/255.255.255.0' + '192.0.0.2/0.0.0.255' + are all functionally the same in IPv4. Similarly, + '192.0.2.1' + '192.0.2.1/255.255.255.255' + '192.0.2.1/32' + are also functionally equivalent. That is to say, failing to + provide a subnetmask will create an object with a mask of /32. + + If the mask (portion after the / in the argument) is given in + dotted quad form, it is treated as a netmask if it starts with a + non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it + starts with a zero field (e.g. 0.255.255.255 == /8), with the + single exception of an all-zero mask which is treated as a + netmask == /0. If no mask is given, a default of /32 is used. + + Additionally, an integer can be passed, so + IPv4Network('192.0.2.1') == IPv4Network(3221225985) + or, more generally + IPv4Interface(int(IPv4Interface('192.0.2.1'))) == + IPv4Interface('192.0.2.1') + + Raises: + AddressValueError: If ipaddress isn't a valid IPv4 address. + NetmaskValueError: If the netmask isn't valid for + an IPv4 address. + ValueError: If strict is True and a network address is not + supplied. + + """ + _BaseNetwork.__init__(self, address) + + # Constructing from a packed address or integer + if isinstance(address, (_compat_int_types, bytes)): + self.network_address = IPv4Address(address) + self.netmask, self._prefixlen = self._make_netmask( + self._max_prefixlen) + # fixme: address/network test here. + return + + if isinstance(address, tuple): + if len(address) > 1: + arg = address[1] + else: + # We weren't given an address[1] + arg = self._max_prefixlen + self.network_address = IPv4Address(address[0]) + self.netmask, self._prefixlen = self._make_netmask(arg) + packed = int(self.network_address) + if packed & int(self.netmask) != packed: + if strict: + raise ValueError('%s has host bits set' % self) + else: + self.network_address = IPv4Address(packed & + int(self.netmask)) + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + addr = _split_optional_netmask(address) + self.network_address = IPv4Address(self._ip_int_from_string(addr[0])) + + if len(addr) == 2: + arg = addr[1] + else: + arg = self._max_prefixlen + self.netmask, self._prefixlen = self._make_netmask(arg) + + if strict: + if (IPv4Address(int(self.network_address) & int(self.netmask)) != + self.network_address): + raise ValueError('%s has host bits set' % self) + self.network_address = IPv4Address(int(self.network_address) & + int(self.netmask)) + + if self._prefixlen == (self._max_prefixlen - 1): + self.hosts = self.__iter__ + + @property + def is_global(self): + """Test if this address is allocated for public networks. + + Returns: + A boolean, True if the address is not reserved per + iana-ipv4-special-registry. + + """ + return (not (self.network_address in IPv4Network('100.64.0.0/10') and + self.broadcast_address in IPv4Network('100.64.0.0/10')) and + not self.is_private) + + +class _IPv4Constants(object): + + _linklocal_network = IPv4Network('169.254.0.0/16') + + _loopback_network = IPv4Network('127.0.0.0/8') + + _multicast_network = IPv4Network('224.0.0.0/4') + + _public_network = IPv4Network('100.64.0.0/10') + + _private_networks = [ + IPv4Network('0.0.0.0/8'), + IPv4Network('10.0.0.0/8'), + IPv4Network('127.0.0.0/8'), + IPv4Network('169.254.0.0/16'), + IPv4Network('172.16.0.0/12'), + IPv4Network('192.0.0.0/29'), + IPv4Network('192.0.0.170/31'), + IPv4Network('192.0.2.0/24'), + IPv4Network('192.168.0.0/16'), + IPv4Network('198.18.0.0/15'), + IPv4Network('198.51.100.0/24'), + IPv4Network('203.0.113.0/24'), + IPv4Network('240.0.0.0/4'), + IPv4Network('255.255.255.255/32'), + ] + + _reserved_network = IPv4Network('240.0.0.0/4') + + _unspecified_address = IPv4Address('0.0.0.0') + + +IPv4Address._constants = _IPv4Constants + + +class _BaseV6(object): + + """Base IPv6 object. + + The following methods are used by IPv6 objects in both single IP + addresses and networks. + + """ + + __slots__ = () + _version = 6 + _ALL_ONES = (2 ** IPV6LENGTH) - 1 + _HEXTET_COUNT = 8 + _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef') + _max_prefixlen = IPV6LENGTH + + # There are only a bunch of valid v6 netmasks, so we cache them all + # when constructed (see _make_netmask()). + _netmask_cache = {} + + @classmethod + def _make_netmask(cls, arg): + """Make a (netmask, prefix_len) tuple from the given argument. + + Argument can be: + - an integer (the prefix length) + - a string representing the prefix length (e.g. "24") + - a string representing the prefix netmask (e.g. "255.255.255.0") + """ + if arg not in cls._netmask_cache: + if isinstance(arg, _compat_int_types): + prefixlen = arg + else: + prefixlen = cls._prefix_from_prefix_string(arg) + netmask = IPv6Address(cls._ip_int_from_prefix(prefixlen)) + cls._netmask_cache[arg] = netmask, prefixlen + return cls._netmask_cache[arg] + + @classmethod + def _ip_int_from_string(cls, ip_str): + """Turn an IPv6 ip_str into an integer. + + Args: + ip_str: A string, the IPv6 ip_str. + + Returns: + An int, the IPv6 address + + Raises: + AddressValueError: if ip_str isn't a valid IPv6 Address. + + """ + if not ip_str: + raise AddressValueError('Address cannot be empty') + + parts = ip_str.split(':') + + # An IPv6 address needs at least 2 colons (3 parts). + _min_parts = 3 + if len(parts) < _min_parts: + msg = "At least %d parts expected in %r" % (_min_parts, ip_str) + raise AddressValueError(msg) + + # If the address has an IPv4-style suffix, convert it to hexadecimal. + if '.' in parts[-1]: + try: + ipv4_int = IPv4Address(parts.pop())._ip + except AddressValueError as exc: + raise AddressValueError("%s in %r" % (exc, ip_str)) + parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF)) + parts.append('%x' % (ipv4_int & 0xFFFF)) + + # An IPv6 address can't have more than 8 colons (9 parts). + # The extra colon comes from using the "::" notation for a single + # leading or trailing zero part. + _max_parts = cls._HEXTET_COUNT + 1 + if len(parts) > _max_parts: + msg = "At most %d colons permitted in %r" % ( + _max_parts - 1, ip_str) + raise AddressValueError(msg) + + # Disregarding the endpoints, find '::' with nothing in between. + # This indicates that a run of zeroes has been skipped. + skip_index = None + for i in _compat_range(1, len(parts) - 1): + if not parts[i]: + if skip_index is not None: + # Can't have more than one '::' + msg = "At most one '::' permitted in %r" % ip_str + raise AddressValueError(msg) + skip_index = i + + # parts_hi is the number of parts to copy from above/before the '::' + # parts_lo is the number of parts to copy from below/after the '::' + if skip_index is not None: + # If we found a '::', then check if it also covers the endpoints. + parts_hi = skip_index + parts_lo = len(parts) - skip_index - 1 + if not parts[0]: + parts_hi -= 1 + if parts_hi: + msg = "Leading ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # ^: requires ^:: + if not parts[-1]: + parts_lo -= 1 + if parts_lo: + msg = "Trailing ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # :$ requires ::$ + parts_skipped = cls._HEXTET_COUNT - (parts_hi + parts_lo) + if parts_skipped < 1: + msg = "Expected at most %d other parts with '::' in %r" + raise AddressValueError(msg % (cls._HEXTET_COUNT - 1, ip_str)) + else: + # Otherwise, allocate the entire address to parts_hi. The + # endpoints could still be empty, but _parse_hextet() will check + # for that. + if len(parts) != cls._HEXTET_COUNT: + msg = "Exactly %d parts expected without '::' in %r" + raise AddressValueError(msg % (cls._HEXTET_COUNT, ip_str)) + if not parts[0]: + msg = "Leading ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # ^: requires ^:: + if not parts[-1]: + msg = "Trailing ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # :$ requires ::$ + parts_hi = len(parts) + parts_lo = 0 + parts_skipped = 0 + + try: + # Now, parse the hextets into a 128-bit integer. + ip_int = 0 + for i in range(parts_hi): + ip_int <<= 16 + ip_int |= cls._parse_hextet(parts[i]) + ip_int <<= 16 * parts_skipped + for i in range(-parts_lo, 0): + ip_int <<= 16 + ip_int |= cls._parse_hextet(parts[i]) + return ip_int + except ValueError as exc: + raise AddressValueError("%s in %r" % (exc, ip_str)) + + @classmethod + def _parse_hextet(cls, hextet_str): + """Convert an IPv6 hextet string into an integer. + + Args: + hextet_str: A string, the number to parse. + + Returns: + The hextet as an integer. + + Raises: + ValueError: if the input isn't strictly a hex number from + [0..FFFF]. + + """ + # Whitelist the characters, since int() allows a lot of bizarre stuff. + if not cls._HEX_DIGITS.issuperset(hextet_str): + raise ValueError("Only hex digits permitted in %r" % hextet_str) + # We do the length check second, since the invalid character error + # is likely to be more informative for the user + if len(hextet_str) > 4: + msg = "At most 4 characters permitted in %r" + raise ValueError(msg % hextet_str) + # Length check means we can skip checking the integer value + return int(hextet_str, 16) + + @classmethod + def _compress_hextets(cls, hextets): + """Compresses a list of hextets. + + Compresses a list of strings, replacing the longest continuous + sequence of "0" in the list with "" and adding empty strings at + the beginning or at the end of the string such that subsequently + calling ":".join(hextets) will produce the compressed version of + the IPv6 address. + + Args: + hextets: A list of strings, the hextets to compress. + + Returns: + A list of strings. + + """ + best_doublecolon_start = -1 + best_doublecolon_len = 0 + doublecolon_start = -1 + doublecolon_len = 0 + for index, hextet in enumerate(hextets): + if hextet == '0': + doublecolon_len += 1 + if doublecolon_start == -1: + # Start of a sequence of zeros. + doublecolon_start = index + if doublecolon_len > best_doublecolon_len: + # This is the longest sequence of zeros so far. + best_doublecolon_len = doublecolon_len + best_doublecolon_start = doublecolon_start + else: + doublecolon_len = 0 + doublecolon_start = -1 + + if best_doublecolon_len > 1: + best_doublecolon_end = (best_doublecolon_start + + best_doublecolon_len) + # For zeros at the end of the address. + if best_doublecolon_end == len(hextets): + hextets += [''] + hextets[best_doublecolon_start:best_doublecolon_end] = [''] + # For zeros at the beginning of the address. + if best_doublecolon_start == 0: + hextets = [''] + hextets + + return hextets + + @classmethod + def _string_from_ip_int(cls, ip_int=None): + """Turns a 128-bit integer into hexadecimal notation. + + Args: + ip_int: An integer, the IP address. + + Returns: + A string, the hexadecimal representation of the address. + + Raises: + ValueError: The address is bigger than 128 bits of all ones. + + """ + if ip_int is None: + ip_int = int(cls._ip) + + if ip_int > cls._ALL_ONES: + raise ValueError('IPv6 address is too large') + + hex_str = '%032x' % ip_int + hextets = ['%x' % int(hex_str[x:x + 4], 16) for x in range(0, 32, 4)] + + hextets = cls._compress_hextets(hextets) + return ':'.join(hextets) + + def _explode_shorthand_ip_string(self): + """Expand a shortened IPv6 address. + + Args: + ip_str: A string, the IPv6 address. + + Returns: + A string, the expanded IPv6 address. + + """ + if isinstance(self, IPv6Network): + ip_str = _compat_str(self.network_address) + elif isinstance(self, IPv6Interface): + ip_str = _compat_str(self.ip) + else: + ip_str = _compat_str(self) + + ip_int = self._ip_int_from_string(ip_str) + hex_str = '%032x' % ip_int + parts = [hex_str[x:x + 4] for x in range(0, 32, 4)] + if isinstance(self, (_BaseNetwork, IPv6Interface)): + return '%s/%d' % (':'.join(parts), self._prefixlen) + return ':'.join(parts) + + def _reverse_pointer(self): + """Return the reverse DNS pointer name for the IPv6 address. + + This implements the method described in RFC3596 2.5. + + """ + reverse_chars = self.exploded[::-1].replace(':', '') + return '.'.join(reverse_chars) + '.ip6.arpa' + + @property + def max_prefixlen(self): + return self._max_prefixlen + + @property + def version(self): + return self._version + + +class IPv6Address(_BaseV6, _BaseAddress): + + """Represent and manipulate single IPv6 Addresses.""" + + __slots__ = ('_ip', '__weakref__') + + def __init__(self, address): + """Instantiate a new IPv6 address object. + + Args: + address: A string or integer representing the IP + + Additionally, an integer can be passed, so + IPv6Address('2001:db8::') == + IPv6Address(42540766411282592856903984951653826560) + or, more generally + IPv6Address(int(IPv6Address('2001:db8::'))) == + IPv6Address('2001:db8::') + + Raises: + AddressValueError: If address isn't a valid IPv6 address. + + """ + # Efficient constructor from integer. + if isinstance(address, _compat_int_types): + self._check_int_address(address) + self._ip = address + return + + # Constructing from a packed address + if isinstance(address, bytes): + self._check_packed_address(address, 16) + bvs = _compat_bytes_to_byte_vals(address) + self._ip = _compat_int_from_byte_vals(bvs, 'big') + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP string. + addr_str = _compat_str(address) + if '/' in addr_str: + raise AddressValueError("Unexpected '/' in %r" % address) + self._ip = self._ip_int_from_string(addr_str) + + @property + def packed(self): + """The binary representation of this address.""" + return v6_int_to_packed(self._ip) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is a multicast address. + See RFC 2373 2.7 for details. + + """ + return self in self._constants._multicast_network + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within one of the + reserved IPv6 Network ranges. + + """ + return any(self in x for x in self._constants._reserved_networks) + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is reserved per RFC 4291. + + """ + return self in self._constants._linklocal_network + + @property + def is_site_local(self): + """Test if the address is reserved for site-local. + + Note that the site-local address space has been deprecated by RFC 3879. + Use is_private to test if this address is in the space of unique local + addresses as defined by RFC 4193. + + Returns: + A boolean, True if the address is reserved per RFC 3513 2.5.6. + + """ + return self in self._constants._sitelocal_network + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per + iana-ipv6-special-registry. + + """ + return any(self in net for net in self._constants._private_networks) + + @property + def is_global(self): + """Test if this address is allocated for public networks. + + Returns: + A boolean, true if the address is not reserved per + iana-ipv6-special-registry. + + """ + return not self.is_private + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 2373 2.5.2. + + """ + return self._ip == 0 + + @property + def is_loopback(self): + """Test if the address is a loopback address. + + Returns: + A boolean, True if the address is a loopback address as defined in + RFC 2373 2.5.3. + + """ + return self._ip == 1 + + @property + def ipv4_mapped(self): + """Return the IPv4 mapped address. + + Returns: + If the IPv6 address is a v4 mapped address, return the + IPv4 mapped address. Return None otherwise. + + """ + if (self._ip >> 32) != 0xFFFF: + return None + return IPv4Address(self._ip & 0xFFFFFFFF) + + @property + def teredo(self): + """Tuple of embedded teredo IPs. + + Returns: + Tuple of the (server, client) IPs or None if the address + doesn't appear to be a teredo address (doesn't start with + 2001::/32) + + """ + if (self._ip >> 96) != 0x20010000: + return None + return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF), + IPv4Address(~self._ip & 0xFFFFFFFF)) + + @property + def sixtofour(self): + """Return the IPv4 6to4 embedded address. + + Returns: + The IPv4 6to4-embedded address if present or None if the + address doesn't appear to contain a 6to4 embedded address. + + """ + if (self._ip >> 112) != 0x2002: + return None + return IPv4Address((self._ip >> 80) & 0xFFFFFFFF) + + +class IPv6Interface(IPv6Address): + + def __init__(self, address): + if isinstance(address, (bytes, _compat_int_types)): + IPv6Address.__init__(self, address) + self.network = IPv6Network(self._ip) + self._prefixlen = self._max_prefixlen + return + if isinstance(address, tuple): + IPv6Address.__init__(self, address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + self.network = IPv6Network(address, strict=False) + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + return + + addr = _split_optional_netmask(address) + IPv6Address.__init__(self, addr[0]) + self.network = IPv6Network(address, strict=False) + self.netmask = self.network.netmask + self._prefixlen = self.network._prefixlen + self.hostmask = self.network.hostmask + + def __str__(self): + return '%s/%d' % (self._string_from_ip_int(self._ip), + self.network.prefixlen) + + def __eq__(self, other): + address_equal = IPv6Address.__eq__(self, other) + if not address_equal or address_equal is NotImplemented: + return address_equal + try: + return self.network == other.network + except AttributeError: + # An interface with an associated network is NOT the + # same as an unassociated address. That's why the hash + # takes the extra info into account. + return False + + def __lt__(self, other): + address_less = IPv6Address.__lt__(self, other) + if address_less is NotImplemented: + return NotImplemented + try: + return (self.network < other.network or + self.network == other.network and address_less) + except AttributeError: + # We *do* allow addresses and interfaces to be sorted. The + # unassociated address is considered less than all interfaces. + return False + + def __hash__(self): + return self._ip ^ self._prefixlen ^ int(self.network.network_address) + + __reduce__ = _IPAddressBase.__reduce__ + + @property + def ip(self): + return IPv6Address(self._ip) + + @property + def with_prefixlen(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.netmask) + + @property + def with_hostmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.hostmask) + + @property + def is_unspecified(self): + return self._ip == 0 and self.network.is_unspecified + + @property + def is_loopback(self): + return self._ip == 1 and self.network.is_loopback + + +class IPv6Network(_BaseV6, _BaseNetwork): + + """This class represents and manipulates 128-bit IPv6 networks. + + Attributes: [examples for IPv6('2001:db8::1000/124')] + .network_address: IPv6Address('2001:db8::1000') + .hostmask: IPv6Address('::f') + .broadcast_address: IPv6Address('2001:db8::100f') + .netmask: IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0') + .prefixlen: 124 + + """ + + # Class to use when creating address objects + _address_class = IPv6Address + + def __init__(self, address, strict=True): + """Instantiate a new IPv6 Network object. + + Args: + address: A string or integer representing the IPv6 network or the + IP and prefix/netmask. + '2001:db8::/128' + '2001:db8:0000:0000:0000:0000:0000:0000/128' + '2001:db8::' + are all functionally the same in IPv6. That is to say, + failing to provide a subnetmask will create an object with + a mask of /128. + + Additionally, an integer can be passed, so + IPv6Network('2001:db8::') == + IPv6Network(42540766411282592856903984951653826560) + or, more generally + IPv6Network(int(IPv6Network('2001:db8::'))) == + IPv6Network('2001:db8::') + + strict: A boolean. If true, ensure that we have been passed + A true network address, eg, 2001:db8::1000/124 and not an + IP address on a network, eg, 2001:db8::1/124. + + Raises: + AddressValueError: If address isn't a valid IPv6 address. + NetmaskValueError: If the netmask isn't valid for + an IPv6 address. + ValueError: If strict was True and a network address was not + supplied. + + """ + _BaseNetwork.__init__(self, address) + + # Efficient constructor from integer or packed address + if isinstance(address, (bytes, _compat_int_types)): + self.network_address = IPv6Address(address) + self.netmask, self._prefixlen = self._make_netmask( + self._max_prefixlen) + return + + if isinstance(address, tuple): + if len(address) > 1: + arg = address[1] + else: + arg = self._max_prefixlen + self.netmask, self._prefixlen = self._make_netmask(arg) + self.network_address = IPv6Address(address[0]) + packed = int(self.network_address) + if packed & int(self.netmask) != packed: + if strict: + raise ValueError('%s has host bits set' % self) + else: + self.network_address = IPv6Address(packed & + int(self.netmask)) + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + addr = _split_optional_netmask(address) + + self.network_address = IPv6Address(self._ip_int_from_string(addr[0])) + + if len(addr) == 2: + arg = addr[1] + else: + arg = self._max_prefixlen + self.netmask, self._prefixlen = self._make_netmask(arg) + + if strict: + if (IPv6Address(int(self.network_address) & int(self.netmask)) != + self.network_address): + raise ValueError('%s has host bits set' % self) + self.network_address = IPv6Address(int(self.network_address) & + int(self.netmask)) + + if self._prefixlen == (self._max_prefixlen - 1): + self.hosts = self.__iter__ + + def hosts(self): + """Generate Iterator over usable hosts in a network. + + This is like __iter__ except it doesn't return the + Subnet-Router anycast address. + + """ + network = int(self.network_address) + broadcast = int(self.broadcast_address) + for x in _compat_range(network + 1, broadcast + 1): + yield self._address_class(x) + + @property + def is_site_local(self): + """Test if the address is reserved for site-local. + + Note that the site-local address space has been deprecated by RFC 3879. + Use is_private to test if this address is in the space of unique local + addresses as defined by RFC 4193. + + Returns: + A boolean, True if the address is reserved per RFC 3513 2.5.6. + + """ + return (self.network_address.is_site_local and + self.broadcast_address.is_site_local) + + +class _IPv6Constants(object): + + _linklocal_network = IPv6Network('fe80::/10') + + _multicast_network = IPv6Network('ff00::/8') + + _private_networks = [ + IPv6Network('::1/128'), + IPv6Network('::/128'), + IPv6Network('::ffff:0:0/96'), + IPv6Network('100::/64'), + IPv6Network('2001::/23'), + IPv6Network('2001:2::/48'), + IPv6Network('2001:db8::/32'), + IPv6Network('2001:10::/28'), + IPv6Network('fc00::/7'), + IPv6Network('fe80::/10'), + ] + + _reserved_networks = [ + IPv6Network('::/8'), IPv6Network('100::/8'), + IPv6Network('200::/7'), IPv6Network('400::/6'), + IPv6Network('800::/5'), IPv6Network('1000::/4'), + IPv6Network('4000::/3'), IPv6Network('6000::/3'), + IPv6Network('8000::/3'), IPv6Network('A000::/3'), + IPv6Network('C000::/3'), IPv6Network('E000::/4'), + IPv6Network('F000::/5'), IPv6Network('F800::/6'), + IPv6Network('FE00::/9'), + ] + + _sitelocal_network = IPv6Network('fec0::/10') + + +IPv6Address._constants = _IPv6Constants diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/__init__.py new file mode 100644 index 0000000..a6f44a5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/__init__.py @@ -0,0 +1,347 @@ +# -*- coding: utf-8 -*- + +""" +lockfile.py - Platform-independent advisory file locks. + +Requires Python 2.5 unless you apply 2.4.diff +Locking is done on a per-thread basis instead of a per-process basis. + +Usage: + +>>> lock = LockFile('somefile') +>>> try: +... lock.acquire() +... except AlreadyLocked: +... print 'somefile', 'is locked already.' +... except LockFailed: +... print 'somefile', 'can\\'t be locked.' +... else: +... print 'got lock' +got lock +>>> print lock.is_locked() +True +>>> lock.release() + +>>> lock = LockFile('somefile') +>>> print lock.is_locked() +False +>>> with lock: +... print lock.is_locked() +True +>>> print lock.is_locked() +False + +>>> lock = LockFile('somefile') +>>> # It is okay to lock twice from the same thread... +>>> with lock: +... lock.acquire() +... +>>> # Though no counter is kept, so you can't unlock multiple times... +>>> print lock.is_locked() +False + +Exceptions: + + Error - base class for other exceptions + LockError - base class for all locking exceptions + AlreadyLocked - Another thread or process already holds the lock + LockFailed - Lock failed for some other reason + UnlockError - base class for all unlocking exceptions + AlreadyUnlocked - File was not locked. + NotMyLock - File was locked but not by the current thread/process +""" + +from __future__ import absolute_import + +import functools +import os +import socket +import threading +import warnings + +# Work with PEP8 and non-PEP8 versions of threading module. +if not hasattr(threading, "current_thread"): + threading.current_thread = threading.currentThread +if not hasattr(threading.Thread, "get_name"): + threading.Thread.get_name = threading.Thread.getName + +__all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked', + 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock', + 'LinkFileLock', 'MkdirFileLock', 'SQLiteFileLock', + 'LockBase', 'locked'] + + +class Error(Exception): + """ + Base class for other exceptions. + + >>> try: + ... raise Error + ... except Exception: + ... pass + """ + pass + + +class LockError(Error): + """ + Base class for error arising from attempts to acquire the lock. + + >>> try: + ... raise LockError + ... except Error: + ... pass + """ + pass + + +class LockTimeout(LockError): + """Raised when lock creation fails within a user-defined period of time. + + >>> try: + ... raise LockTimeout + ... except LockError: + ... pass + """ + pass + + +class AlreadyLocked(LockError): + """Some other thread/process is locking the file. + + >>> try: + ... raise AlreadyLocked + ... except LockError: + ... pass + """ + pass + + +class LockFailed(LockError): + """Lock file creation failed for some other reason. + + >>> try: + ... raise LockFailed + ... except LockError: + ... pass + """ + pass + + +class UnlockError(Error): + """ + Base class for errors arising from attempts to release the lock. + + >>> try: + ... raise UnlockError + ... except Error: + ... pass + """ + pass + + +class NotLocked(UnlockError): + """Raised when an attempt is made to unlock an unlocked file. + + >>> try: + ... raise NotLocked + ... except UnlockError: + ... pass + """ + pass + + +class NotMyLock(UnlockError): + """Raised when an attempt is made to unlock a file someone else locked. + + >>> try: + ... raise NotMyLock + ... except UnlockError: + ... pass + """ + pass + + +class _SharedBase(object): + def __init__(self, path): + self.path = path + + def acquire(self, timeout=None): + """ + Acquire the lock. + + * If timeout is omitted (or None), wait forever trying to lock the + file. + + * If timeout > 0, try to acquire the lock for that many seconds. If + the lock period expires and the file is still locked, raise + LockTimeout. + + * If timeout <= 0, raise AlreadyLocked immediately if the file is + already locked. + """ + raise NotImplemented("implement in subclass") + + def release(self): + """ + Release the lock. + + If the file is not locked, raise NotLocked. + """ + raise NotImplemented("implement in subclass") + + def __enter__(self): + """ + Context manager support. + """ + self.acquire() + return self + + def __exit__(self, *_exc): + """ + Context manager support. + """ + self.release() + + def __repr__(self): + return "<%s: %r>" % (self.__class__.__name__, self.path) + + +class LockBase(_SharedBase): + """Base class for platform-specific lock classes.""" + def __init__(self, path, threaded=True, timeout=None): + """ + >>> lock = LockBase('somefile') + >>> lock = LockBase('somefile', threaded=False) + """ + super(LockBase, self).__init__(path) + self.lock_file = os.path.abspath(path) + ".lock" + self.hostname = socket.gethostname() + self.pid = os.getpid() + if threaded: + t = threading.current_thread() + # Thread objects in Python 2.4 and earlier do not have ident + # attrs. Worm around that. + ident = getattr(t, "ident", hash(t)) + self.tname = "-%x" % (ident & 0xffffffff) + else: + self.tname = "" + dirname = os.path.dirname(self.lock_file) + + # unique name is mostly about the current process, but must + # also contain the path -- otherwise, two adjacent locked + # files conflict (one file gets locked, creating lock-file and + # unique file, the other one gets locked, creating lock-file + # and overwriting the already existing lock-file, then one + # gets unlocked, deleting both lock-file and unique file, + # finally the last lock errors out upon releasing. + self.unique_name = os.path.join(dirname, + "%s%s.%s%s" % (self.hostname, + self.tname, + self.pid, + hash(self.path))) + self.timeout = timeout + + def is_locked(self): + """ + Tell whether or not the file is locked. + """ + raise NotImplemented("implement in subclass") + + def i_am_locking(self): + """ + Return True if this object is locking the file. + """ + raise NotImplemented("implement in subclass") + + def break_lock(self): + """ + Remove a lock. Useful if a locking thread failed to unlock. + """ + raise NotImplemented("implement in subclass") + + def __repr__(self): + return "<%s: %r -- %r>" % (self.__class__.__name__, self.unique_name, + self.path) + + +def _fl_helper(cls, mod, *args, **kwds): + warnings.warn("Import from %s module instead of lockfile package" % mod, + DeprecationWarning, stacklevel=2) + # This is a bit funky, but it's only for awhile. The way the unit tests + # are constructed this function winds up as an unbound method, so it + # actually takes three args, not two. We want to toss out self. + if not isinstance(args[0], str): + # We are testing, avoid the first arg + args = args[1:] + if len(args) == 1 and not kwds: + kwds["threaded"] = True + return cls(*args, **kwds) + + +def LinkFileLock(*args, **kwds): + """Factory function provided for backwards compatibility. + + Do not use in new code. Instead, import LinkLockFile from the + lockfile.linklockfile module. + """ + from . import linklockfile + return _fl_helper(linklockfile.LinkLockFile, "lockfile.linklockfile", + *args, **kwds) + + +def MkdirFileLock(*args, **kwds): + """Factory function provided for backwards compatibility. + + Do not use in new code. Instead, import MkdirLockFile from the + lockfile.mkdirlockfile module. + """ + from . import mkdirlockfile + return _fl_helper(mkdirlockfile.MkdirLockFile, "lockfile.mkdirlockfile", + *args, **kwds) + + +def SQLiteFileLock(*args, **kwds): + """Factory function provided for backwards compatibility. + + Do not use in new code. Instead, import SQLiteLockFile from the + lockfile.mkdirlockfile module. + """ + from . import sqlitelockfile + return _fl_helper(sqlitelockfile.SQLiteLockFile, "lockfile.sqlitelockfile", + *args, **kwds) + + +def locked(path, timeout=None): + """Decorator which enables locks for decorated function. + + Arguments: + - path: path for lockfile. + - timeout (optional): Timeout for acquiring lock. + + Usage: + @locked('/var/run/myname', timeout=0) + def myname(...): + ... + """ + def decor(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + lock = FileLock(path, timeout=timeout) + lock.acquire() + try: + return func(*args, **kwargs) + finally: + lock.release() + return wrapper + return decor + + +if hasattr(os, "link"): + from . import linklockfile as _llf + LockFile = _llf.LinkLockFile +else: + from . import mkdirlockfile as _mlf + LockFile = _mlf.MkdirLockFile + +FileLock = LockFile diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/linklockfile.py b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/linklockfile.py new file mode 100644 index 0000000..2ca9be0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/linklockfile.py @@ -0,0 +1,73 @@ +from __future__ import absolute_import + +import time +import os + +from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, + AlreadyLocked) + + +class LinkLockFile(LockBase): + """Lock access to a file using atomic property of link(2). + + >>> lock = LinkLockFile('somefile') + >>> lock = LinkLockFile('somefile', threaded=False) + """ + + def acquire(self, timeout=None): + try: + open(self.unique_name, "wb").close() + except IOError: + raise LockFailed("failed to create %s" % self.unique_name) + + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + while True: + # Try and create a hard link to it. + try: + os.link(self.unique_name, self.lock_file) + except OSError: + # Link creation failed. Maybe we've double-locked? + nlinks = os.stat(self.unique_name).st_nlink + if nlinks == 2: + # The original link plus the one I created == 2. We're + # good to go. + return + else: + # Otherwise the lock creation failed. + if timeout is not None and time.time() > end_time: + os.unlink(self.unique_name) + if timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(timeout is not None and timeout / 10 or 0.1) + else: + # Link creation succeeded. We're good to go. + return + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + elif not os.path.exists(self.unique_name): + raise NotMyLock("%s is locked, but not by me" % self.path) + os.unlink(self.unique_name) + os.unlink(self.lock_file) + + def is_locked(self): + return os.path.exists(self.lock_file) + + def i_am_locking(self): + return (self.is_locked() and + os.path.exists(self.unique_name) and + os.stat(self.unique_name).st_nlink == 2) + + def break_lock(self): + if os.path.exists(self.lock_file): + os.unlink(self.lock_file) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py new file mode 100644 index 0000000..05a8c96 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/mkdirlockfile.py @@ -0,0 +1,84 @@ +from __future__ import absolute_import, division + +import time +import os +import sys +import errno + +from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, + AlreadyLocked) + + +class MkdirLockFile(LockBase): + """Lock file by creating a directory.""" + def __init__(self, path, threaded=True, timeout=None): + """ + >>> lock = MkdirLockFile('somefile') + >>> lock = MkdirLockFile('somefile', threaded=False) + """ + LockBase.__init__(self, path, threaded, timeout) + # Lock file itself is a directory. Place the unique file name into + # it. + self.unique_name = os.path.join(self.lock_file, + "%s.%s%s" % (self.hostname, + self.tname, + self.pid)) + + def acquire(self, timeout=None): + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + if timeout is None: + wait = 0.1 + else: + wait = max(0, timeout / 10) + + while True: + try: + os.mkdir(self.lock_file) + except OSError: + err = sys.exc_info()[1] + if err.errno == errno.EEXIST: + # Already locked. + if os.path.exists(self.unique_name): + # Already locked by me. + return + if timeout is not None and time.time() > end_time: + if timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + # Someone else has the lock. + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(wait) + else: + # Couldn't create the lock for some other reason + raise LockFailed("failed to create %s" % self.lock_file) + else: + open(self.unique_name, "wb").close() + return + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + elif not os.path.exists(self.unique_name): + raise NotMyLock("%s is locked, but not by me" % self.path) + os.unlink(self.unique_name) + os.rmdir(self.lock_file) + + def is_locked(self): + return os.path.exists(self.lock_file) + + def i_am_locking(self): + return (self.is_locked() and + os.path.exists(self.unique_name)) + + def break_lock(self): + if os.path.exists(self.lock_file): + for name in os.listdir(self.lock_file): + os.unlink(os.path.join(self.lock_file, name)) + os.rmdir(self.lock_file) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/pidlockfile.py b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/pidlockfile.py new file mode 100644 index 0000000..069e85b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/pidlockfile.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- + +# pidlockfile.py +# +# Copyright © 2008–2009 Ben Finney <ben+python@benfinney.id.au> +# +# This is free software: you may copy, modify, and/or distribute this work +# under the terms of the Python Software Foundation License, version 2 or +# later as published by the Python Software Foundation. +# No warranty expressed or implied. See the file LICENSE.PSF-2 for details. + +""" Lockfile behaviour implemented via Unix PID files. + """ + +from __future__ import absolute_import + +import errno +import os +import time + +from . import (LockBase, AlreadyLocked, LockFailed, NotLocked, NotMyLock, + LockTimeout) + + +class PIDLockFile(LockBase): + """ Lockfile implemented as a Unix PID file. + + The lock file is a normal file named by the attribute `path`. + A lock's PID file contains a single line of text, containing + the process ID (PID) of the process that acquired the lock. + + >>> lock = PIDLockFile('somefile') + >>> lock = PIDLockFile('somefile') + """ + + def __init__(self, path, threaded=False, timeout=None): + # pid lockfiles don't support threaded operation, so always force + # False as the threaded arg. + LockBase.__init__(self, path, False, timeout) + self.unique_name = self.path + + def read_pid(self): + """ Get the PID from the lock file. + """ + return read_pid_from_pidfile(self.path) + + def is_locked(self): + """ Test if the lock is currently held. + + The lock is held if the PID file for this lock exists. + + """ + return os.path.exists(self.path) + + def i_am_locking(self): + """ Test if the lock is held by the current process. + + Returns ``True`` if the current process ID matches the + number stored in the PID file. + """ + return self.is_locked() and os.getpid() == self.read_pid() + + def acquire(self, timeout=None): + """ Acquire the lock. + + Creates the PID file for this lock, or raises an error if + the lock could not be acquired. + """ + + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + while True: + try: + write_pid_to_pidfile(self.path) + except OSError as exc: + if exc.errno == errno.EEXIST: + # The lock creation failed. Maybe sleep a bit. + if time.time() > end_time: + if timeout is not None and timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(timeout is not None and timeout / 10 or 0.1) + else: + raise LockFailed("failed to create %s" % self.path) + else: + return + + def release(self): + """ Release the lock. + + Removes the PID file to release the lock, or raises an + error if the current process does not hold the lock. + + """ + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + if not self.i_am_locking(): + raise NotMyLock("%s is locked, but not by me" % self.path) + remove_existing_pidfile(self.path) + + def break_lock(self): + """ Break an existing lock. + + Removes the PID file if it already exists, otherwise does + nothing. + + """ + remove_existing_pidfile(self.path) + + +def read_pid_from_pidfile(pidfile_path): + """ Read the PID recorded in the named PID file. + + Read and return the numeric PID recorded as text in the named + PID file. If the PID file cannot be read, or if the content is + not a valid PID, return ``None``. + + """ + pid = None + try: + pidfile = open(pidfile_path, 'r') + except IOError: + pass + else: + # According to the FHS 2.3 section on PID files in /var/run: + # + # The file must consist of the process identifier in + # ASCII-encoded decimal, followed by a newline character. + # + # Programs that read PID files should be somewhat flexible + # in what they accept; i.e., they should ignore extra + # whitespace, leading zeroes, absence of the trailing + # newline, or additional lines in the PID file. + + line = pidfile.readline().strip() + try: + pid = int(line) + except ValueError: + pass + pidfile.close() + + return pid + + +def write_pid_to_pidfile(pidfile_path): + """ Write the PID in the named PID file. + + Get the numeric process ID (“PID”) of the current process + and write it to the named file as a line of text. + + """ + open_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY) + open_mode = 0o644 + pidfile_fd = os.open(pidfile_path, open_flags, open_mode) + pidfile = os.fdopen(pidfile_fd, 'w') + + # According to the FHS 2.3 section on PID files in /var/run: + # + # The file must consist of the process identifier in + # ASCII-encoded decimal, followed by a newline character. For + # example, if crond was process number 25, /var/run/crond.pid + # would contain three characters: two, five, and newline. + + pid = os.getpid() + pidfile.write("%s\n" % pid) + pidfile.close() + + +def remove_existing_pidfile(pidfile_path): + """ Remove the named PID file if it exists. + + Removing a PID file that doesn't already exist puts us in the + desired state, so we ignore the condition if the file does not + exist. + + """ + try: + os.remove(pidfile_path) + except OSError as exc: + if exc.errno == errno.ENOENT: + pass + else: + raise diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py new file mode 100644 index 0000000..f997e24 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/sqlitelockfile.py @@ -0,0 +1,156 @@ +from __future__ import absolute_import, division + +import time +import os + +try: + unicode +except NameError: + unicode = str + +from . import LockBase, NotLocked, NotMyLock, LockTimeout, AlreadyLocked + + +class SQLiteLockFile(LockBase): + "Demonstrate SQL-based locking." + + testdb = None + + def __init__(self, path, threaded=True, timeout=None): + """ + >>> lock = SQLiteLockFile('somefile') + >>> lock = SQLiteLockFile('somefile', threaded=False) + """ + LockBase.__init__(self, path, threaded, timeout) + self.lock_file = unicode(self.lock_file) + self.unique_name = unicode(self.unique_name) + + if SQLiteLockFile.testdb is None: + import tempfile + _fd, testdb = tempfile.mkstemp() + os.close(_fd) + os.unlink(testdb) + del _fd, tempfile + SQLiteLockFile.testdb = testdb + + import sqlite3 + self.connection = sqlite3.connect(SQLiteLockFile.testdb) + + c = self.connection.cursor() + try: + c.execute("create table locks" + "(" + " lock_file varchar(32)," + " unique_name varchar(32)" + ")") + except sqlite3.OperationalError: + pass + else: + self.connection.commit() + import atexit + atexit.register(os.unlink, SQLiteLockFile.testdb) + + def acquire(self, timeout=None): + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + if timeout is None: + wait = 0.1 + elif timeout <= 0: + wait = 0 + else: + wait = timeout / 10 + + cursor = self.connection.cursor() + + while True: + if not self.is_locked(): + # Not locked. Try to lock it. + cursor.execute("insert into locks" + " (lock_file, unique_name)" + " values" + " (?, ?)", + (self.lock_file, self.unique_name)) + self.connection.commit() + + # Check to see if we are the only lock holder. + cursor.execute("select * from locks" + " where unique_name = ?", + (self.unique_name,)) + rows = cursor.fetchall() + if len(rows) > 1: + # Nope. Someone else got there. Remove our lock. + cursor.execute("delete from locks" + " where unique_name = ?", + (self.unique_name,)) + self.connection.commit() + else: + # Yup. We're done, so go home. + return + else: + # Check to see if we are the only lock holder. + cursor.execute("select * from locks" + " where unique_name = ?", + (self.unique_name,)) + rows = cursor.fetchall() + if len(rows) == 1: + # We're the locker, so go home. + return + + # Maybe we should wait a bit longer. + if timeout is not None and time.time() > end_time: + if timeout > 0: + # No more waiting. + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + # Someone else has the lock and we are impatient.. + raise AlreadyLocked("%s is already locked" % self.path) + + # Well, okay. We'll give it a bit longer. + time.sleep(wait) + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + if not self.i_am_locking(): + raise NotMyLock("%s is locked, but not by me (by %s)" % + (self.unique_name, self._who_is_locking())) + cursor = self.connection.cursor() + cursor.execute("delete from locks" + " where unique_name = ?", + (self.unique_name,)) + self.connection.commit() + + def _who_is_locking(self): + cursor = self.connection.cursor() + cursor.execute("select unique_name from locks" + " where lock_file = ?", + (self.lock_file,)) + return cursor.fetchone()[0] + + def is_locked(self): + cursor = self.connection.cursor() + cursor.execute("select * from locks" + " where lock_file = ?", + (self.lock_file,)) + rows = cursor.fetchall() + return not not rows + + def i_am_locking(self): + cursor = self.connection.cursor() + cursor.execute("select * from locks" + " where lock_file = ?" + " and unique_name = ?", + (self.lock_file, self.unique_name)) + return not not cursor.fetchall() + + def break_lock(self): + cursor = self.connection.cursor() + cursor.execute("delete from locks" + " where lock_file = ?", + (self.lock_file,)) + self.connection.commit() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py new file mode 100644 index 0000000..23b41f5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/lockfile/symlinklockfile.py @@ -0,0 +1,70 @@ +from __future__ import absolute_import + +import os +import time + +from . import (LockBase, NotLocked, NotMyLock, LockTimeout, + AlreadyLocked) + + +class SymlinkLockFile(LockBase): + """Lock access to a file using symlink(2).""" + + def __init__(self, path, threaded=True, timeout=None): + # super(SymlinkLockFile).__init(...) + LockBase.__init__(self, path, threaded, timeout) + # split it back! + self.unique_name = os.path.split(self.unique_name)[1] + + def acquire(self, timeout=None): + # Hopefully unnecessary for symlink. + # try: + # open(self.unique_name, "wb").close() + # except IOError: + # raise LockFailed("failed to create %s" % self.unique_name) + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + while True: + # Try and create a symbolic link to it. + try: + os.symlink(self.unique_name, self.lock_file) + except OSError: + # Link creation failed. Maybe we've double-locked? + if self.i_am_locking(): + # Linked to out unique name. Proceed. + return + else: + # Otherwise the lock creation failed. + if timeout is not None and time.time() > end_time: + if timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(timeout / 10 if timeout is not None else 0.1) + else: + # Link creation succeeded. We're good to go. + return + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + elif not self.i_am_locking(): + raise NotMyLock("%s is locked, but not by me" % self.path) + os.unlink(self.lock_file) + + def is_locked(self): + return os.path.islink(self.lock_file) + + def i_am_locking(self): + return (os.path.islink(self.lock_file) + and os.readlink(self.lock_file) == self.unique_name) + + def break_lock(self): + if os.path.islink(self.lock_file): # exists && link + os.unlink(self.lock_file) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__init__.py new file mode 100644 index 0000000..2afca5a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/__init__.py @@ -0,0 +1,66 @@ +# coding: utf-8 +from pip._vendor.msgpack._version import version +from pip._vendor.msgpack.exceptions import * + +from collections import namedtuple + + +class ExtType(namedtuple('ExtType', 'code data')): + """ExtType represents ext type in msgpack.""" + def __new__(cls, code, data): + if not isinstance(code, int): + raise TypeError("code must be int") + if not isinstance(data, bytes): + raise TypeError("data must be bytes") + if not 0 <= code <= 127: + raise ValueError("code must be 0~127") + return super(ExtType, cls).__new__(cls, code, data) + + +import os +if os.environ.get('MSGPACK_PUREPYTHON'): + from pip._vendor.msgpack.fallback import Packer, unpackb, Unpacker +else: + try: + from pip._vendor.msgpack._packer import Packer + from pip._vendor.msgpack._unpacker import unpackb, Unpacker + except ImportError: + from pip._vendor.msgpack.fallback import Packer, unpackb, Unpacker + + +def pack(o, stream, **kwargs): + """ + Pack object `o` and write it to `stream` + + See :class:`Packer` for options. + """ + packer = Packer(**kwargs) + stream.write(packer.pack(o)) + + +def packb(o, **kwargs): + """ + Pack object `o` and return packed bytes + + See :class:`Packer` for options. + """ + return Packer(**kwargs).pack(o) + + +def unpack(stream, **kwargs): + """ + Unpack an object from `stream`. + + Raises `ExtraData` when `stream` contains extra bytes. + See :class:`Unpacker` for options. + """ + data = stream.read() + return unpackb(data, **kwargs) + + +# alias for compatibility to simplejson/marshal/pickle. +load = unpack +loads = unpackb + +dump = pack +dumps = packb diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/_version.py b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/_version.py new file mode 100644 index 0000000..d28f0de --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/_version.py @@ -0,0 +1 @@ +version = (0, 5, 6) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/exceptions.py b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/exceptions.py new file mode 100644 index 0000000..9766881 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/exceptions.py @@ -0,0 +1,41 @@ +class UnpackException(Exception): + """Deprecated. Use Exception instead to catch all exception during unpacking.""" + + +class BufferFull(UnpackException): + pass + + +class OutOfData(UnpackException): + pass + + +class UnpackValueError(UnpackException, ValueError): + """Deprecated. Use ValueError instead.""" + + +class ExtraData(UnpackValueError): + def __init__(self, unpacked, extra): + self.unpacked = unpacked + self.extra = extra + + def __str__(self): + return "unpack(b) received extra data." + + +class PackException(Exception): + """Deprecated. Use Exception instead to catch all exception during packing.""" + + +class PackValueError(PackException, ValueError): + """PackValueError is raised when type of input data is supported but it's value is unsupported. + + Deprecated. Use ValueError instead. + """ + + +class PackOverflowError(PackValueError, OverflowError): + """PackOverflowError is raised when integer value is out of range of msgpack support [-2**31, 2**32). + + Deprecated. Use ValueError instead. + """ diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/fallback.py b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/fallback.py new file mode 100644 index 0000000..9418421 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/msgpack/fallback.py @@ -0,0 +1,977 @@ +"""Fallback pure Python implementation of msgpack""" + +import sys +import struct +import warnings + +if sys.version_info[0] == 3: + PY3 = True + int_types = int + Unicode = str + xrange = range + def dict_iteritems(d): + return d.items() +else: + PY3 = False + int_types = (int, long) + Unicode = unicode + def dict_iteritems(d): + return d.iteritems() + + +if hasattr(sys, 'pypy_version_info'): + # cStringIO is slow on PyPy, StringIO is faster. However: PyPy's own + # StringBuilder is fastest. + from __pypy__ import newlist_hint + try: + from __pypy__.builders import BytesBuilder as StringBuilder + except ImportError: + from __pypy__.builders import StringBuilder + USING_STRINGBUILDER = True + class StringIO(object): + def __init__(self, s=b''): + if s: + self.builder = StringBuilder(len(s)) + self.builder.append(s) + else: + self.builder = StringBuilder() + def write(self, s): + if isinstance(s, memoryview): + s = s.tobytes() + elif isinstance(s, bytearray): + s = bytes(s) + self.builder.append(s) + def getvalue(self): + return self.builder.build() +else: + USING_STRINGBUILDER = False + from io import BytesIO as StringIO + newlist_hint = lambda size: [] + + +from pip._vendor.msgpack.exceptions import ( + BufferFull, + OutOfData, + UnpackValueError, + PackValueError, + PackOverflowError, + ExtraData) + +from pip._vendor.msgpack import ExtType + + +EX_SKIP = 0 +EX_CONSTRUCT = 1 +EX_READ_ARRAY_HEADER = 2 +EX_READ_MAP_HEADER = 3 + +TYPE_IMMEDIATE = 0 +TYPE_ARRAY = 1 +TYPE_MAP = 2 +TYPE_RAW = 3 +TYPE_BIN = 4 +TYPE_EXT = 5 + +DEFAULT_RECURSE_LIMIT = 511 + + +def _check_type_strict(obj, t, type=type, tuple=tuple): + if type(t) is tuple: + return type(obj) in t + else: + return type(obj) is t + + +def _get_data_from_buffer(obj): + try: + view = memoryview(obj) + except TypeError: + # try to use legacy buffer protocol if 2.7, otherwise re-raise + if not PY3: + view = memoryview(buffer(obj)) + warnings.warn("using old buffer interface to unpack %s; " + "this leads to unpacking errors if slicing is used and " + "will be removed in a future version" % type(obj), + RuntimeWarning) + else: + raise + if view.itemsize != 1: + raise ValueError("cannot unpack from multi-byte object") + return view + + +def unpack(stream, **kwargs): + warnings.warn( + "Direct calling implementation's unpack() is deprecated, Use msgpack.unpack() or unpackb() instead.", + PendingDeprecationWarning) + data = stream.read() + return unpackb(data, **kwargs) + + +def unpackb(packed, **kwargs): + """ + Unpack an object from `packed`. + + Raises `ExtraData` when `packed` contains extra bytes. + See :class:`Unpacker` for options. + """ + unpacker = Unpacker(None, **kwargs) + unpacker.feed(packed) + try: + ret = unpacker._unpack() + except OutOfData: + raise UnpackValueError("Data is not enough.") + if unpacker._got_extradata(): + raise ExtraData(ret, unpacker._get_extradata()) + return ret + + +class Unpacker(object): + """Streaming unpacker. + + arguments: + + :param file_like: + File-like object having `.read(n)` method. + If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable. + + :param int read_size: + Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`) + + :param bool use_list: + If true, unpack msgpack array to Python list. + Otherwise, unpack to Python tuple. (default: True) + + :param bool raw: + If true, unpack msgpack raw to Python bytes (default). + Otherwise, unpack to Python str (or unicode on Python 2) by decoding + with UTF-8 encoding (recommended). + Currently, the default is true, but it will be changed to false in + near future. So you must specify it explicitly for keeping backward + compatibility. + + *encoding* option which is deprecated overrides this option. + + :param callable object_hook: + When specified, it should be callable. + Unpacker calls it with a dict argument after unpacking msgpack map. + (See also simplejson) + + :param callable object_pairs_hook: + When specified, it should be callable. + Unpacker calls it with a list of key-value pairs after unpacking msgpack map. + (See also simplejson) + + :param str encoding: + Encoding used for decoding msgpack raw. + If it is None (default), msgpack raw is deserialized to Python bytes. + + :param str unicode_errors: + (deprecated) Used for decoding msgpack raw with *encoding*. + (default: `'strict'`) + + :param int max_buffer_size: + Limits size of data waiting unpacked. 0 means system's INT_MAX (default). + Raises `BufferFull` exception when it is insufficient. + You should set this parameter when unpacking data from untrusted source. + + :param int max_str_len: + Limits max length of str. (default: 2**31-1) + + :param int max_bin_len: + Limits max length of bin. (default: 2**31-1) + + :param int max_array_len: + Limits max length of array. (default: 2**31-1) + + :param int max_map_len: + Limits max length of map. (default: 2**31-1) + + + example of streaming deserialize from file-like object:: + + unpacker = Unpacker(file_like, raw=False) + for o in unpacker: + process(o) + + example of streaming deserialize from socket:: + + unpacker = Unpacker(raw=False) + while True: + buf = sock.recv(1024**2) + if not buf: + break + unpacker.feed(buf) + for o in unpacker: + process(o) + """ + + def __init__(self, file_like=None, read_size=0, use_list=True, raw=True, + object_hook=None, object_pairs_hook=None, list_hook=None, + encoding=None, unicode_errors=None, max_buffer_size=0, + ext_hook=ExtType, + max_str_len=2147483647, # 2**32-1 + max_bin_len=2147483647, + max_array_len=2147483647, + max_map_len=2147483647, + max_ext_len=2147483647): + + if encoding is not None: + warnings.warn( + "encoding is deprecated, Use raw=False instead.", + PendingDeprecationWarning) + + if unicode_errors is None: + unicode_errors = 'strict' + + if file_like is None: + self._feeding = True + else: + if not callable(file_like.read): + raise TypeError("`file_like.read` must be callable") + self.file_like = file_like + self._feeding = False + + #: array of bytes fed. + self._buffer = bytearray() + # Some very old pythons don't support `struct.unpack_from()` with a + # `bytearray`. So we wrap it in a `buffer()` there. + if sys.version_info < (2, 7, 6): + self._buffer_view = buffer(self._buffer) + else: + self._buffer_view = self._buffer + #: Which position we currently reads + self._buff_i = 0 + + # When Unpacker is used as an iterable, between the calls to next(), + # the buffer is not "consumed" completely, for efficiency sake. + # Instead, it is done sloppily. To make sure we raise BufferFull at + # the correct moments, we have to keep track of how sloppy we were. + # Furthermore, when the buffer is incomplete (that is: in the case + # we raise an OutOfData) we need to rollback the buffer to the correct + # state, which _buf_checkpoint records. + self._buf_checkpoint = 0 + + self._max_buffer_size = max_buffer_size or 2**31-1 + if read_size > self._max_buffer_size: + raise ValueError("read_size must be smaller than max_buffer_size") + self._read_size = read_size or min(self._max_buffer_size, 16*1024) + self._raw = bool(raw) + self._encoding = encoding + self._unicode_errors = unicode_errors + self._use_list = use_list + self._list_hook = list_hook + self._object_hook = object_hook + self._object_pairs_hook = object_pairs_hook + self._ext_hook = ext_hook + self._max_str_len = max_str_len + self._max_bin_len = max_bin_len + self._max_array_len = max_array_len + self._max_map_len = max_map_len + self._max_ext_len = max_ext_len + self._stream_offset = 0 + + if list_hook is not None and not callable(list_hook): + raise TypeError('`list_hook` is not callable') + if object_hook is not None and not callable(object_hook): + raise TypeError('`object_hook` is not callable') + if object_pairs_hook is not None and not callable(object_pairs_hook): + raise TypeError('`object_pairs_hook` is not callable') + if object_hook is not None and object_pairs_hook is not None: + raise TypeError("object_pairs_hook and object_hook are mutually " + "exclusive") + if not callable(ext_hook): + raise TypeError("`ext_hook` is not callable") + + def feed(self, next_bytes): + assert self._feeding + view = _get_data_from_buffer(next_bytes) + if (len(self._buffer) - self._buff_i + len(view) > self._max_buffer_size): + raise BufferFull + + # Strip buffer before checkpoint before reading file. + if self._buf_checkpoint > 0: + del self._buffer[:self._buf_checkpoint] + self._buff_i -= self._buf_checkpoint + self._buf_checkpoint = 0 + + self._buffer += view + + def _consume(self): + """ Gets rid of the used parts of the buffer. """ + self._stream_offset += self._buff_i - self._buf_checkpoint + self._buf_checkpoint = self._buff_i + + def _got_extradata(self): + return self._buff_i < len(self._buffer) + + def _get_extradata(self): + return self._buffer[self._buff_i:] + + def read_bytes(self, n): + return self._read(n) + + def _read(self, n): + # (int) -> bytearray + self._reserve(n) + i = self._buff_i + self._buff_i = i+n + return self._buffer[i:i+n] + + def _reserve(self, n): + remain_bytes = len(self._buffer) - self._buff_i - n + + # Fast path: buffer has n bytes already + if remain_bytes >= 0: + return + + if self._feeding: + self._buff_i = self._buf_checkpoint + raise OutOfData + + # Strip buffer before checkpoint before reading file. + if self._buf_checkpoint > 0: + del self._buffer[:self._buf_checkpoint] + self._buff_i -= self._buf_checkpoint + self._buf_checkpoint = 0 + + # Read from file + remain_bytes = -remain_bytes + while remain_bytes > 0: + to_read_bytes = max(self._read_size, remain_bytes) + read_data = self.file_like.read(to_read_bytes) + if not read_data: + break + assert isinstance(read_data, bytes) + self._buffer += read_data + remain_bytes -= len(read_data) + + if len(self._buffer) < n + self._buff_i: + self._buff_i = 0 # rollback + raise OutOfData + + def _read_header(self, execute=EX_CONSTRUCT): + typ = TYPE_IMMEDIATE + n = 0 + obj = None + self._reserve(1) + b = self._buffer[self._buff_i] + self._buff_i += 1 + if b & 0b10000000 == 0: + obj = b + elif b & 0b11100000 == 0b11100000: + obj = -1 - (b ^ 0xff) + elif b & 0b11100000 == 0b10100000: + n = b & 0b00011111 + typ = TYPE_RAW + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b & 0b11110000 == 0b10010000: + n = b & 0b00001111 + typ = TYPE_ARRAY + if n > self._max_array_len: + raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) + elif b & 0b11110000 == 0b10000000: + n = b & 0b00001111 + typ = TYPE_MAP + if n > self._max_map_len: + raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) + elif b == 0xc0: + obj = None + elif b == 0xc2: + obj = False + elif b == 0xc3: + obj = True + elif b == 0xc4: + typ = TYPE_BIN + self._reserve(1) + n = self._buffer[self._buff_i] + self._buff_i += 1 + if n > self._max_bin_len: + raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) + obj = self._read(n) + elif b == 0xc5: + typ = TYPE_BIN + self._reserve(2) + n = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0] + self._buff_i += 2 + if n > self._max_bin_len: + raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) + obj = self._read(n) + elif b == 0xc6: + typ = TYPE_BIN + self._reserve(4) + n = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + if n > self._max_bin_len: + raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) + obj = self._read(n) + elif b == 0xc7: # ext 8 + typ = TYPE_EXT + self._reserve(2) + L, n = struct.unpack_from('Bb', self._buffer_view, self._buff_i) + self._buff_i += 2 + if L > self._max_ext_len: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) + obj = self._read(L) + elif b == 0xc8: # ext 16 + typ = TYPE_EXT + self._reserve(3) + L, n = struct.unpack_from('>Hb', self._buffer_view, self._buff_i) + self._buff_i += 3 + if L > self._max_ext_len: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) + obj = self._read(L) + elif b == 0xc9: # ext 32 + typ = TYPE_EXT + self._reserve(5) + L, n = struct.unpack_from('>Ib', self._buffer_view, self._buff_i) + self._buff_i += 5 + if L > self._max_ext_len: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) + obj = self._read(L) + elif b == 0xca: + self._reserve(4) + obj = struct.unpack_from(">f", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + elif b == 0xcb: + self._reserve(8) + obj = struct.unpack_from(">d", self._buffer_view, self._buff_i)[0] + self._buff_i += 8 + elif b == 0xcc: + self._reserve(1) + obj = self._buffer[self._buff_i] + self._buff_i += 1 + elif b == 0xcd: + self._reserve(2) + obj = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0] + self._buff_i += 2 + elif b == 0xce: + self._reserve(4) + obj = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + elif b == 0xcf: + self._reserve(8) + obj = struct.unpack_from(">Q", self._buffer_view, self._buff_i)[0] + self._buff_i += 8 + elif b == 0xd0: + self._reserve(1) + obj = struct.unpack_from("b", self._buffer_view, self._buff_i)[0] + self._buff_i += 1 + elif b == 0xd1: + self._reserve(2) + obj = struct.unpack_from(">h", self._buffer_view, self._buff_i)[0] + self._buff_i += 2 + elif b == 0xd2: + self._reserve(4) + obj = struct.unpack_from(">i", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + elif b == 0xd3: + self._reserve(8) + obj = struct.unpack_from(">q", self._buffer_view, self._buff_i)[0] + self._buff_i += 8 + elif b == 0xd4: # fixext 1 + typ = TYPE_EXT + if self._max_ext_len < 1: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (1, self._max_ext_len)) + self._reserve(2) + n, obj = struct.unpack_from("b1s", self._buffer_view, self._buff_i) + self._buff_i += 2 + elif b == 0xd5: # fixext 2 + typ = TYPE_EXT + if self._max_ext_len < 2: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (2, self._max_ext_len)) + self._reserve(3) + n, obj = struct.unpack_from("b2s", self._buffer_view, self._buff_i) + self._buff_i += 3 + elif b == 0xd6: # fixext 4 + typ = TYPE_EXT + if self._max_ext_len < 4: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (4, self._max_ext_len)) + self._reserve(5) + n, obj = struct.unpack_from("b4s", self._buffer_view, self._buff_i) + self._buff_i += 5 + elif b == 0xd7: # fixext 8 + typ = TYPE_EXT + if self._max_ext_len < 8: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (8, self._max_ext_len)) + self._reserve(9) + n, obj = struct.unpack_from("b8s", self._buffer_view, self._buff_i) + self._buff_i += 9 + elif b == 0xd8: # fixext 16 + typ = TYPE_EXT + if self._max_ext_len < 16: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (16, self._max_ext_len)) + self._reserve(17) + n, obj = struct.unpack_from("b16s", self._buffer_view, self._buff_i) + self._buff_i += 17 + elif b == 0xd9: + typ = TYPE_RAW + self._reserve(1) + n = self._buffer[self._buff_i] + self._buff_i += 1 + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b == 0xda: + typ = TYPE_RAW + self._reserve(2) + n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) + self._buff_i += 2 + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b == 0xdb: + typ = TYPE_RAW + self._reserve(4) + n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) + self._buff_i += 4 + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b == 0xdc: + typ = TYPE_ARRAY + self._reserve(2) + n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) + self._buff_i += 2 + if n > self._max_array_len: + raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) + elif b == 0xdd: + typ = TYPE_ARRAY + self._reserve(4) + n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) + self._buff_i += 4 + if n > self._max_array_len: + raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) + elif b == 0xde: + self._reserve(2) + n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) + self._buff_i += 2 + if n > self._max_map_len: + raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) + typ = TYPE_MAP + elif b == 0xdf: + self._reserve(4) + n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) + self._buff_i += 4 + if n > self._max_map_len: + raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) + typ = TYPE_MAP + else: + raise UnpackValueError("Unknown header: 0x%x" % b) + return typ, n, obj + + def _unpack(self, execute=EX_CONSTRUCT): + typ, n, obj = self._read_header(execute) + + if execute == EX_READ_ARRAY_HEADER: + if typ != TYPE_ARRAY: + raise UnpackValueError("Expected array") + return n + if execute == EX_READ_MAP_HEADER: + if typ != TYPE_MAP: + raise UnpackValueError("Expected map") + return n + # TODO should we eliminate the recursion? + if typ == TYPE_ARRAY: + if execute == EX_SKIP: + for i in xrange(n): + # TODO check whether we need to call `list_hook` + self._unpack(EX_SKIP) + return + ret = newlist_hint(n) + for i in xrange(n): + ret.append(self._unpack(EX_CONSTRUCT)) + if self._list_hook is not None: + ret = self._list_hook(ret) + # TODO is the interaction between `list_hook` and `use_list` ok? + return ret if self._use_list else tuple(ret) + if typ == TYPE_MAP: + if execute == EX_SKIP: + for i in xrange(n): + # TODO check whether we need to call hooks + self._unpack(EX_SKIP) + self._unpack(EX_SKIP) + return + if self._object_pairs_hook is not None: + ret = self._object_pairs_hook( + (self._unpack(EX_CONSTRUCT), + self._unpack(EX_CONSTRUCT)) + for _ in xrange(n)) + else: + ret = {} + for _ in xrange(n): + key = self._unpack(EX_CONSTRUCT) + ret[key] = self._unpack(EX_CONSTRUCT) + if self._object_hook is not None: + ret = self._object_hook(ret) + return ret + if execute == EX_SKIP: + return + if typ == TYPE_RAW: + if self._encoding is not None: + obj = obj.decode(self._encoding, self._unicode_errors) + elif self._raw: + obj = bytes(obj) + else: + obj = obj.decode('utf_8') + return obj + if typ == TYPE_EXT: + return self._ext_hook(n, bytes(obj)) + if typ == TYPE_BIN: + return bytes(obj) + assert typ == TYPE_IMMEDIATE + return obj + + def __iter__(self): + return self + + def __next__(self): + try: + ret = self._unpack(EX_CONSTRUCT) + self._consume() + return ret + except OutOfData: + self._consume() + raise StopIteration + + next = __next__ + + def skip(self, write_bytes=None): + self._unpack(EX_SKIP) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + + def unpack(self, write_bytes=None): + ret = self._unpack(EX_CONSTRUCT) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + return ret + + def read_array_header(self, write_bytes=None): + ret = self._unpack(EX_READ_ARRAY_HEADER) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + return ret + + def read_map_header(self, write_bytes=None): + ret = self._unpack(EX_READ_MAP_HEADER) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + return ret + + def tell(self): + return self._stream_offset + + +class Packer(object): + """ + MessagePack Packer + + usage: + + packer = Packer() + astream.write(packer.pack(a)) + astream.write(packer.pack(b)) + + Packer's constructor has some keyword arguments: + + :param callable default: + Convert user type to builtin type that Packer supports. + See also simplejson's document. + + :param bool use_single_float: + Use single precision float type for float. (default: False) + + :param bool autoreset: + Reset buffer after each pack and return its content as `bytes`. (default: True). + If set this to false, use `bytes()` to get content and `.reset()` to clear buffer. + + :param bool use_bin_type: + Use bin type introduced in msgpack spec 2.0 for bytes. + It also enables str8 type for unicode. + + :param bool strict_types: + If set to true, types will be checked to be exact. Derived classes + from serializeable types will not be serialized and will be + treated as unsupported type and forwarded to default. + Additionally tuples will not be serialized as lists. + This is useful when trying to implement accurate serialization + for python types. + + :param str encoding: + (deprecated) Convert unicode to bytes with this encoding. (default: 'utf-8') + + :param str unicode_errors: + Error handler for encoding unicode. (default: 'strict') + """ + def __init__(self, default=None, encoding=None, unicode_errors=None, + use_single_float=False, autoreset=True, use_bin_type=False, + strict_types=False): + if encoding is None: + encoding = 'utf_8' + else: + warnings.warn( + "encoding is deprecated, Use raw=False instead.", + PendingDeprecationWarning) + + if unicode_errors is None: + unicode_errors = 'strict' + + self._strict_types = strict_types + self._use_float = use_single_float + self._autoreset = autoreset + self._use_bin_type = use_bin_type + self._encoding = encoding + self._unicode_errors = unicode_errors + self._buffer = StringIO() + if default is not None: + if not callable(default): + raise TypeError("default must be callable") + self._default = default + + def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, + check=isinstance, check_type_strict=_check_type_strict): + default_used = False + if self._strict_types: + check = check_type_strict + list_types = list + else: + list_types = (list, tuple) + while True: + if nest_limit < 0: + raise PackValueError("recursion limit exceeded") + if obj is None: + return self._buffer.write(b"\xc0") + if check(obj, bool): + if obj: + return self._buffer.write(b"\xc3") + return self._buffer.write(b"\xc2") + if check(obj, int_types): + if 0 <= obj < 0x80: + return self._buffer.write(struct.pack("B", obj)) + if -0x20 <= obj < 0: + return self._buffer.write(struct.pack("b", obj)) + if 0x80 <= obj <= 0xff: + return self._buffer.write(struct.pack("BB", 0xcc, obj)) + if -0x80 <= obj < 0: + return self._buffer.write(struct.pack(">Bb", 0xd0, obj)) + if 0xff < obj <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xcd, obj)) + if -0x8000 <= obj < -0x80: + return self._buffer.write(struct.pack(">Bh", 0xd1, obj)) + if 0xffff < obj <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xce, obj)) + if -0x80000000 <= obj < -0x8000: + return self._buffer.write(struct.pack(">Bi", 0xd2, obj)) + if 0xffffffff < obj <= 0xffffffffffffffff: + return self._buffer.write(struct.pack(">BQ", 0xcf, obj)) + if -0x8000000000000000 <= obj < -0x80000000: + return self._buffer.write(struct.pack(">Bq", 0xd3, obj)) + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = True + continue + raise PackOverflowError("Integer value out of range") + if check(obj, (bytes, bytearray)): + n = len(obj) + if n >= 2**32: + raise PackValueError("%s is too large" % type(obj).__name__) + self._pack_bin_header(n) + return self._buffer.write(obj) + if check(obj, Unicode): + if self._encoding is None: + raise TypeError( + "Can't encode unicode string: " + "no encoding is specified") + obj = obj.encode(self._encoding, self._unicode_errors) + n = len(obj) + if n >= 2**32: + raise PackValueError("String is too large") + self._pack_raw_header(n) + return self._buffer.write(obj) + if check(obj, memoryview): + n = len(obj) * obj.itemsize + if n >= 2**32: + raise PackValueError("Memoryview is too large") + self._pack_bin_header(n) + return self._buffer.write(obj) + if check(obj, float): + if self._use_float: + return self._buffer.write(struct.pack(">Bf", 0xca, obj)) + return self._buffer.write(struct.pack(">Bd", 0xcb, obj)) + if check(obj, ExtType): + code = obj.code + data = obj.data + assert isinstance(code, int) + assert isinstance(data, bytes) + L = len(data) + if L == 1: + self._buffer.write(b'\xd4') + elif L == 2: + self._buffer.write(b'\xd5') + elif L == 4: + self._buffer.write(b'\xd6') + elif L == 8: + self._buffer.write(b'\xd7') + elif L == 16: + self._buffer.write(b'\xd8') + elif L <= 0xff: + self._buffer.write(struct.pack(">BB", 0xc7, L)) + elif L <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xc8, L)) + else: + self._buffer.write(struct.pack(">BI", 0xc9, L)) + self._buffer.write(struct.pack("b", code)) + self._buffer.write(data) + return + if check(obj, list_types): + n = len(obj) + self._pack_array_header(n) + for i in xrange(n): + self._pack(obj[i], nest_limit - 1) + return + if check(obj, dict): + return self._pack_map_pairs(len(obj), dict_iteritems(obj), + nest_limit - 1) + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = 1 + continue + raise TypeError("Cannot serialize %r" % (obj, )) + + def pack(self, obj): + try: + self._pack(obj) + except: + self._buffer = StringIO() # force reset + raise + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_map_pairs(self, pairs): + self._pack_map_pairs(len(pairs), pairs) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_array_header(self, n): + if n >= 2**32: + raise PackValueError + self._pack_array_header(n) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_map_header(self, n): + if n >= 2**32: + raise PackValueError + self._pack_map_header(n) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_ext_type(self, typecode, data): + if not isinstance(typecode, int): + raise TypeError("typecode must have int type.") + if not 0 <= typecode <= 127: + raise ValueError("typecode should be 0-127") + if not isinstance(data, bytes): + raise TypeError("data must have bytes type") + L = len(data) + if L > 0xffffffff: + raise PackValueError("Too large data") + if L == 1: + self._buffer.write(b'\xd4') + elif L == 2: + self._buffer.write(b'\xd5') + elif L == 4: + self._buffer.write(b'\xd6') + elif L == 8: + self._buffer.write(b'\xd7') + elif L == 16: + self._buffer.write(b'\xd8') + elif L <= 0xff: + self._buffer.write(b'\xc7' + struct.pack('B', L)) + elif L <= 0xffff: + self._buffer.write(b'\xc8' + struct.pack('>H', L)) + else: + self._buffer.write(b'\xc9' + struct.pack('>I', L)) + self._buffer.write(struct.pack('B', typecode)) + self._buffer.write(data) + + def _pack_array_header(self, n): + if n <= 0x0f: + return self._buffer.write(struct.pack('B', 0x90 + n)) + if n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xdc, n)) + if n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xdd, n)) + raise PackValueError("Array is too large") + + def _pack_map_header(self, n): + if n <= 0x0f: + return self._buffer.write(struct.pack('B', 0x80 + n)) + if n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xde, n)) + if n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xdf, n)) + raise PackValueError("Dict is too large") + + def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT): + self._pack_map_header(n) + for (k, v) in pairs: + self._pack(k, nest_limit - 1) + self._pack(v, nest_limit - 1) + + def _pack_raw_header(self, n): + if n <= 0x1f: + self._buffer.write(struct.pack('B', 0xa0 + n)) + elif self._use_bin_type and n <= 0xff: + self._buffer.write(struct.pack('>BB', 0xd9, n)) + elif n <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xda, n)) + elif n <= 0xffffffff: + self._buffer.write(struct.pack(">BI", 0xdb, n)) + else: + raise PackValueError('Raw is too large') + + def _pack_bin_header(self, n): + if not self._use_bin_type: + return self._pack_raw_header(n) + elif n <= 0xff: + return self._buffer.write(struct.pack('>BB', 0xc4, n)) + elif n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xc5, n)) + elif n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xc6, n)) + else: + raise PackValueError('Bin is too large') + + def bytes(self): + return self._buffer.getvalue() + + def reset(self): + self._buffer = StringIO() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__about__.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__about__.py new file mode 100644 index 0000000..21fc6ce --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "18.0" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2018 %s" % __author__ diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_structures.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_structures.py new file mode 100644 index 0000000..e9fc4a0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/_structures.py @@ -0,0 +1,70 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + + +NegativeInfinity = NegativeInfinity() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/markers.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/markers.py new file mode 100644 index 0000000..e5834ce --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from pip._vendor.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from pip._vendor.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from pip._vendor.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "<Marker({0!r})>".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/requirements.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/requirements.py new file mode 100644 index 0000000..d40bd8c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/requirements.py @@ -0,0 +1,130 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from pip._vendor.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from pip._vendor.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from pip._vendor.pyparsing import Literal as L # noqa +from pip._vendor.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPARATOR = SEMICOLON +MARKER = MARKER_SEPARATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd +# pyparsing isn't thread safe during initialization, so we do it eagerly, see +# issue #104 +REQUIREMENT.parseString("x[]") + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement("Parse error at \"{0!r}\": {1}".format( + requirement_string[e.loc:e.loc + 8], e.msg + )) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL: {0}".format(req.url)) + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "<Requirement({0!r})>".format(str(self)) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/specifiers.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..4c79899 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(==|!=|<=|>=|<|>)) + \s* + (?P<version> + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(~=|==|!=|<=|>=|<|>|===)) + (?P<version> + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?<!==|!=|~=) # We have special cases for these + # operators so we want to make sure they + # don't match here. + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<SpecifierSet({0!r}{1})>".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/utils.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/utils.py new file mode 100644 index 0000000..4b94a82 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/utils.py @@ -0,0 +1,63 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + +from .version import InvalidVersion, Version + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() + + +def canonicalize_version(version): + """ + This is very similar to Version.__str__, but has one subtle differences + with the way it handles the release segment. + """ + + try: + version = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + + parts = [] + + # Epoch + if version.epoch != 0: + parts.append("{0}!".format(version.epoch)) + + # Release segment + # NB: This strips trailing '.0's to normalize + parts.append( + re.sub( + r'(\.0)+$', + '', + ".".join(str(x) for x in version.release) + ) + ) + + # Pre-release + if version.pre is not None: + parts.append("".join(str(x) for x in version.pre)) + + # Post-release + if version.post is not None: + parts.append(".post{0}".format(version.post)) + + # Development release + if version.dev is not None: + parts.append(".dev{0}".format(version.dev)) + + # Local version segment + if version.local is not None: + parts.append("+{0}".format(version.local)) + + return "".join(parts) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/packaging/version.py b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/version.py new file mode 100644 index 0000000..6ed5cbb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/packaging/version.py @@ -0,0 +1,441 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "<LegacyVersion({0})>".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def epoch(self): + return -1 + + @property + def release(self): + return None + + @property + def pre(self): + return None + + @property + def post(self): + return None + + @property + def dev(self): + return None + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + @property + def is_devrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P<epoch>[0-9]+)!)? # epoch + (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment + (?P<pre> # pre-release + [-_\.]? + (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) + [-_\.]? + (?P<pre_n>[0-9]+)? + )? + (?P<post> # post release + (?:-(?P<post_n1>[0-9]+)) + | + (?: + [-_\.]? + (?P<post_l>post|rev|r) + [-_\.]? + (?P<post_n2>[0-9]+)? + ) + )? + (?P<dev> # dev release + [-_\.]? + (?P<dev_l>dev) + [-_\.]? + (?P<dev_n>[0-9]+)? + )? + ) + (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version +""" + + +class Version(_BaseVersion): + + _regex = re.compile( + r"^\s*" + VERSION_PATTERN + r"\s*$", + re.VERBOSE | re.IGNORECASE, + ) + + def __init__(self, version): + # Validate the version and parse it into pieces + match = self._regex.search(version) + if not match: + raise InvalidVersion("Invalid version: '{0}'".format(version)) + + # Store the parsed out pieces of the version + self._version = _Version( + epoch=int(match.group("epoch")) if match.group("epoch") else 0, + release=tuple(int(i) for i in match.group("release").split(".")), + pre=_parse_letter_version( + match.group("pre_l"), + match.group("pre_n"), + ), + post=_parse_letter_version( + match.group("post_l"), + match.group("post_n1") or match.group("post_n2"), + ), + dev=_parse_letter_version( + match.group("dev_l"), + match.group("dev_n"), + ), + local=_parse_local_version(match.group("local")), + ) + + # Generate a key which will be used for sorting + self._key = _cmpkey( + self._version.epoch, + self._version.release, + self._version.pre, + self._version.post, + self._version.dev, + self._version.local, + ) + + def __repr__(self): + return "<Version({0})>".format(repr(str(self))) + + def __str__(self): + parts = [] + + # Epoch + if self.epoch != 0: + parts.append("{0}!".format(self.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self.release)) + + # Pre-release + if self.pre is not None: + parts.append("".join(str(x) for x in self.pre)) + + # Post-release + if self.post is not None: + parts.append(".post{0}".format(self.post)) + + # Development release + if self.dev is not None: + parts.append(".dev{0}".format(self.dev)) + + # Local version segment + if self.local is not None: + parts.append("+{0}".format(self.local)) + + return "".join(parts) + + @property + def epoch(self): + return self._version.epoch + + @property + def release(self): + return self._version.release + + @property + def pre(self): + return self._version.pre + + @property + def post(self): + return self._version.post[1] if self._version.post else None + + @property + def dev(self): + return self._version.dev[1] if self._version.dev else None + + @property + def local(self): + if self._version.local: + return ".".join(str(x) for x in self._version.local) + else: + return None + + @property + def public(self): + return str(self).split("+", 1)[0] + + @property + def base_version(self): + parts = [] + + # Epoch + if self.epoch != 0: + parts.append("{0}!".format(self.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self.release)) + + return "".join(parts) + + @property + def is_prerelease(self): + return self.dev is not None or self.pre is not None + + @property + def is_postrelease(self): + return self.post is not None + + @property + def is_devrelease(self): + return self.dev is not None + + +def _parse_letter_version(letter, number): + if letter: + # We consider there to be an implicit 0 in a pre-release if there is + # not a numeral associated with it. + if number is None: + number = 0 + + # We normalize any letters to their lower case form + letter = letter.lower() + + # We consider some words to be alternate spellings of other words and + # in those cases we want to normalize the spellings to our preferred + # spelling. + if letter == "alpha": + letter = "a" + elif letter == "beta": + letter = "b" + elif letter in ["c", "pre", "preview"]: + letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" + + return letter, int(number) + if not letter and number: + # We assume if we are given a number, but we are not given a letter + # then this is using the implicit post release syntax (e.g. 1.0-1) + letter = "post" + + return letter, int(number) + + +_local_version_separators = re.compile(r"[\._-]") + + +def _parse_local_version(local): + """ + Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). + """ + if local is not None: + return tuple( + part.lower() if not part.isdigit() else int(part) + for part in _local_version_separators.split(local) + ) + + +def _cmpkey(epoch, release, pre, post, dev, local): + # When we compare a release version, we want to compare it with all of the + # trailing zeros removed. So we'll use a reverse the list, drop all the now + # leading zeros until we come to something non zero, then take the rest + # re-reverse it back into the correct order and make it a tuple and use + # that for our sorting key. + release = tuple( + reversed(list( + itertools.dropwhile( + lambda x: x == 0, + reversed(release), + ) + )) + ) + + # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. + # We'll do this by abusing the pre segment, but we _only_ want to do this + # if there is not a pre or a post segment. If we have one of those then + # the normal sorting rules will handle this case correctly. + if pre is None and post is None and dev is not None: + pre = -Infinity + # Versions without a pre-release (except as noted above) should sort after + # those with one. + elif pre is None: + pre = Infinity + + # Versions without a post segment should sort before those with one. + if post is None: + post = -Infinity + + # Versions without a development segment should sort after those with one. + if dev is None: + dev = Infinity + + if local is None: + # Versions without a local segment should sort before those with one. + local = -Infinity + else: + # Versions with a local segment need that segment parsed to implement + # the sorting rules in PEP440. + # - Alpha numeric segments sort before numeric segments + # - Alpha numeric segments sort lexicographically + # - Numeric segments sort numerically + # - Shorter versions sort before longer versions when the prefixes + # match exactly + local = tuple( + (i, "") if isinstance(i, int) else (-Infinity, i) + for i in local + ) + + return epoch, release, pre, post, dev, local diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__init__.py new file mode 100644 index 0000000..8beedea --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/__init__.py @@ -0,0 +1,4 @@ +"""Wrappers to build Python packages using PEP 517 hooks +""" + +__version__ = '0.2' diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/_in_process.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/_in_process.py new file mode 100644 index 0000000..baa14d3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/_in_process.py @@ -0,0 +1,182 @@ +"""This is invoked in a subprocess to call the build backend hooks. + +It expects: +- Command line args: hook_name, control_dir +- Environment variable: PEP517_BUILD_BACKEND=entry.point:spec +- control_dir/input.json: + - {"kwargs": {...}} + +Results: +- control_dir/output.json + - {"return_val": ...} +""" +from glob import glob +from importlib import import_module +import os +from os.path import join as pjoin +import re +import shutil +import sys + +# This is run as a script, not a module, so it can't do a relative import +import compat + +def _build_backend(): + """Find and load the build backend""" + ep = os.environ['PEP517_BUILD_BACKEND'] + mod_path, _, obj_path = ep.partition(':') + obj = import_module(mod_path) + if obj_path: + for path_part in obj_path.split('.'): + obj = getattr(obj, path_part) + return obj + +def get_requires_for_build_wheel(config_settings): + """Invoke the optional get_requires_for_build_wheel hook + + Returns [] if the hook is not defined. + """ + backend = _build_backend() + try: + hook = backend.get_requires_for_build_wheel + except AttributeError: + return [] + else: + return hook(config_settings) + +def prepare_metadata_for_build_wheel(metadata_directory, config_settings): + """Invoke optional prepare_metadata_for_build_wheel + + Implements a fallback by building a wheel if the hook isn't defined. + """ + backend = _build_backend() + try: + hook = backend.prepare_metadata_for_build_wheel + except AttributeError: + return _get_wheel_metadata_from_wheel(backend, metadata_directory, + config_settings) + else: + return hook(metadata_directory, config_settings) + +WHEEL_BUILT_MARKER = 'PEP517_ALREADY_BUILT_WHEEL' + +def _dist_info_files(whl_zip): + """Identify the .dist-info folder inside a wheel ZipFile.""" + res = [] + for path in whl_zip.namelist(): + m = re.match(r'[^/\\]+-[^/\\]+\.dist-info/', path) + if m: + res.append(path) + if res: + return res + raise Exception("No .dist-info folder found in wheel") + +def _get_wheel_metadata_from_wheel(backend, metadata_directory, config_settings): + """Build a wheel and extract the metadata from it. + + Fallback for when the build backend does not define the 'get_wheel_metadata' + hook. + """ + from zipfile import ZipFile + whl_basename = backend.build_wheel(metadata_directory, config_settings) + with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), 'wb'): + pass # Touch marker file + + whl_file = os.path.join(metadata_directory, whl_basename) + with ZipFile(whl_file) as zipf: + dist_info = _dist_info_files(zipf) + zipf.extractall(path=metadata_directory, members=dist_info) + return dist_info[0].split('/')[0] + +def _find_already_built_wheel(metadata_directory): + """Check for a wheel already built during the get_wheel_metadata hook. + """ + if not metadata_directory: + return None + metadata_parent = os.path.dirname(metadata_directory) + if not os.path.isfile(pjoin(metadata_parent, WHEEL_BUILT_MARKER)): + return None + + whl_files = glob(os.path.join(metadata_parent, '*.whl')) + if not whl_files: + print('Found wheel built marker, but no .whl files') + return None + if len(whl_files) > 1: + print('Found multiple .whl files; unspecified behaviour. ' + 'Will call build_wheel.') + return None + + # Exactly one .whl file + return whl_files[0] + +def build_wheel(wheel_directory, config_settings, metadata_directory=None): + """Invoke the mandatory build_wheel hook. + + If a wheel was already built in the prepare_metadata_for_build_wheel fallback, this + will copy it rather than rebuilding the wheel. + """ + prebuilt_whl = _find_already_built_wheel(metadata_directory) + if prebuilt_whl: + shutil.copy2(prebuilt_whl, wheel_directory) + return os.path.basename(prebuilt_whl) + + return _build_backend().build_wheel(wheel_directory, config_settings, + metadata_directory) + + +def get_requires_for_build_sdist(config_settings): + """Invoke the optional get_requires_for_build_wheel hook + + Returns [] if the hook is not defined. + """ + backend = _build_backend() + try: + hook = backend.get_requires_for_build_sdist + except AttributeError: + return [] + else: + return hook(config_settings) + +class _DummyException(Exception): + """Nothing should ever raise this exception""" + +class GotUnsupportedOperation(Exception): + """For internal use when backend raises UnsupportedOperation""" + +def build_sdist(sdist_directory, config_settings): + """Invoke the mandatory build_sdist hook.""" + backend = _build_backend() + try: + return backend.build_sdist(sdist_directory, config_settings) + except getattr(backend, 'UnsupportedOperation', _DummyException): + raise GotUnsupportedOperation + +HOOK_NAMES = { + 'get_requires_for_build_wheel', + 'prepare_metadata_for_build_wheel', + 'build_wheel', + 'get_requires_for_build_sdist', + 'build_sdist', +} + +def main(): + if len(sys.argv) < 3: + sys.exit("Needs args: hook_name, control_dir") + hook_name = sys.argv[1] + control_dir = sys.argv[2] + if hook_name not in HOOK_NAMES: + sys.exit("Unknown hook: %s" % hook_name) + hook = globals()[hook_name] + + hook_input = compat.read_json(pjoin(control_dir, 'input.json')) + + json_out = {'unsupported': False, 'return_val': None} + try: + json_out['return_val'] = hook(**hook_input['kwargs']) + except GotUnsupportedOperation: + json_out['unsupported'] = True + + compat.write_json(json_out, pjoin(control_dir, 'output.json'), indent=2) + +if __name__ == '__main__': + main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/check.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/check.py new file mode 100644 index 0000000..c65d51c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/check.py @@ -0,0 +1,194 @@ +"""Check a project and backend by attempting to build using PEP 517 hooks. +""" +import argparse +import logging +import os +from os.path import isfile, join as pjoin +from pip._vendor.pytoml import TomlError, load as toml_load +import shutil +from subprocess import CalledProcessError +import sys +import tarfile +from tempfile import mkdtemp +import zipfile + +from .colorlog import enable_colourful_output +from .envbuild import BuildEnvironment +from .wrappers import Pep517HookCaller + +log = logging.getLogger(__name__) + +def check_build_sdist(hooks): + with BuildEnvironment() as env: + try: + env.pip_install(hooks.build_sys_requires) + log.info('Installed static build dependencies') + except CalledProcessError: + log.error('Failed to install static build dependencies') + return False + + try: + reqs = hooks.get_requires_for_build_sdist({}) + log.info('Got build requires: %s', reqs) + except: + log.error('Failure in get_requires_for_build_sdist', exc_info=True) + return False + + try: + env.pip_install(reqs) + log.info('Installed dynamic build dependencies') + except CalledProcessError: + log.error('Failed to install dynamic build dependencies') + return False + + td = mkdtemp() + log.info('Trying to build sdist in %s', td) + try: + try: + filename = hooks.build_sdist(td, {}) + log.info('build_sdist returned %r', filename) + except: + log.info('Failure in build_sdist', exc_info=True) + return False + + if not filename.endswith('.tar.gz'): + log.error("Filename %s doesn't have .tar.gz extension", filename) + return False + + path = pjoin(td, filename) + if isfile(path): + log.info("Output file %s exists", path) + else: + log.error("Output file %s does not exist", path) + return False + + if tarfile.is_tarfile(path): + log.info("Output file is a tar file") + else: + log.error("Output file is not a tar file") + return False + + finally: + shutil.rmtree(td) + + return True + +def check_build_wheel(hooks): + with BuildEnvironment() as env: + try: + env.pip_install(hooks.build_sys_requires) + log.info('Installed static build dependencies') + except CalledProcessError: + log.error('Failed to install static build dependencies') + return False + + try: + reqs = hooks.get_requires_for_build_wheel({}) + log.info('Got build requires: %s', reqs) + except: + log.error('Failure in get_requires_for_build_sdist', exc_info=True) + return False + + try: + env.pip_install(reqs) + log.info('Installed dynamic build dependencies') + except CalledProcessError: + log.error('Failed to install dynamic build dependencies') + return False + + td = mkdtemp() + log.info('Trying to build wheel in %s', td) + try: + try: + filename = hooks.build_wheel(td, {}) + log.info('build_wheel returned %r', filename) + except: + log.info('Failure in build_wheel', exc_info=True) + return False + + if not filename.endswith('.whl'): + log.error("Filename %s doesn't have .whl extension", filename) + return False + + path = pjoin(td, filename) + if isfile(path): + log.info("Output file %s exists", path) + else: + log.error("Output file %s does not exist", path) + return False + + if zipfile.is_zipfile(path): + log.info("Output file is a zip file") + else: + log.error("Output file is not a zip file") + return False + + finally: + shutil.rmtree(td) + + return True + + +def check(source_dir): + pyproject = pjoin(source_dir, 'pyproject.toml') + if isfile(pyproject): + log.info('Found pyproject.toml') + else: + log.error('Missing pyproject.toml') + return False + + try: + with open(pyproject) as f: + pyproject_data = toml_load(f) + # Ensure the mandatory data can be loaded + buildsys = pyproject_data['build-system'] + requires = buildsys['requires'] + backend = buildsys['build-backend'] + log.info('Loaded pyproject.toml') + except (TomlError, KeyError): + log.error("Invalid pyproject.toml", exc_info=True) + return False + + hooks = Pep517HookCaller(source_dir, backend) + + sdist_ok = check_build_sdist(hooks) + wheel_ok = check_build_wheel(hooks) + + if not sdist_ok: + log.warning('Sdist checks failed; scroll up to see') + if not wheel_ok: + log.warning('Wheel checks failed') + + return sdist_ok + + +def main(argv=None): + ap = argparse.ArgumentParser() + ap.add_argument('source_dir', + help="A directory containing pyproject.toml") + args = ap.parse_args(argv) + + enable_colourful_output() + + ok = check(args.source_dir) + + if ok: + print(ansi('Checks passed', 'green')) + else: + print(ansi('Checks failed', 'red')) + sys.exit(1) + +ansi_codes = { + 'reset': '\x1b[0m', + 'bold': '\x1b[1m', + 'red': '\x1b[31m', + 'green': '\x1b[32m', +} +def ansi(s, attr): + if os.name != 'nt' and sys.stdout.isatty(): + return ansi_codes[attr] + str(s) + ansi_codes['reset'] + else: + return str(s) + +if __name__ == '__main__': + main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/colorlog.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/colorlog.py new file mode 100644 index 0000000..26cf748 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/colorlog.py @@ -0,0 +1,110 @@ +"""Nicer log formatting with colours. + +Code copied from Tornado, Apache licensed. +""" +# Copyright 2012 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging +import sys + +try: + import curses +except ImportError: + curses = None + +def _stderr_supports_color(): + color = False + if curses and hasattr(sys.stderr, 'isatty') and sys.stderr.isatty(): + try: + curses.setupterm() + if curses.tigetnum("colors") > 0: + color = True + except Exception: + pass + return color + +class LogFormatter(logging.Formatter): + """Log formatter with colour support + """ + DEFAULT_COLORS = { + logging.INFO: 2, # Green + logging.WARNING: 3, # Yellow + logging.ERROR: 1, # Red + logging.CRITICAL: 1, + } + + def __init__(self, color=True, datefmt=None): + r""" + :arg bool color: Enables color support. + :arg string fmt: Log message format. + It will be applied to the attributes dict of log records. The + text between ``%(color)s`` and ``%(end_color)s`` will be colored + depending on the level if color support is on. + :arg dict colors: color mappings from logging level to terminal color + code + :arg string datefmt: Datetime format. + Used for formatting ``(asctime)`` placeholder in ``prefix_fmt``. + .. versionchanged:: 3.2 + Added ``fmt`` and ``datefmt`` arguments. + """ + logging.Formatter.__init__(self, datefmt=datefmt) + self._colors = {} + if color and _stderr_supports_color(): + # The curses module has some str/bytes confusion in + # python3. Until version 3.2.3, most methods return + # bytes, but only accept strings. In addition, we want to + # output these strings with the logging module, which + # works with unicode strings. The explicit calls to + # unicode() below are harmless in python2 but will do the + # right conversion in python 3. + fg_color = (curses.tigetstr("setaf") or + curses.tigetstr("setf") or "") + if (3, 0) < sys.version_info < (3, 2, 3): + fg_color = str(fg_color, "ascii") + + for levelno, code in self.DEFAULT_COLORS.items(): + self._colors[levelno] = str(curses.tparm(fg_color, code), "ascii") + self._normal = str(curses.tigetstr("sgr0"), "ascii") + + scr = curses.initscr() + self.termwidth = scr.getmaxyx()[1] + curses.endwin() + else: + self._normal = '' + # Default width is usually 80, but too wide is worse than too narrow + self.termwidth = 70 + + def formatMessage(self, record): + l = len(record.message) + right_text = '{initial}-{name}'.format(initial=record.levelname[0], + name=record.name) + if l + len(right_text) < self.termwidth: + space = ' ' * (self.termwidth - (l + len(right_text))) + else: + space = ' ' + + if record.levelno in self._colors: + start_color = self._colors[record.levelno] + end_color = self._normal + else: + start_color = end_color = '' + + return record.message + space + start_color + right_text + end_color + +def enable_colourful_output(level=logging.INFO): + handler = logging.StreamHandler() + handler.setFormatter(LogFormatter()) + logging.root.addHandler(handler) + logging.root.setLevel(level) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/compat.py new file mode 100644 index 0000000..01c66fc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/compat.py @@ -0,0 +1,23 @@ +"""Handle reading and writing JSON in UTF-8, on Python 3 and 2.""" +import json +import sys + +if sys.version_info[0] >= 3: + # Python 3 + def write_json(obj, path, **kwargs): + with open(path, 'w', encoding='utf-8') as f: + json.dump(obj, f, **kwargs) + + def read_json(path): + with open(path, 'r', encoding='utf-8') as f: + return json.load(f) + +else: + # Python 2 + def write_json(obj, path, **kwargs): + with open(path, 'wb') as f: + json.dump(obj, f, encoding='utf-8', **kwargs) + + def read_json(path): + with open(path, 'rb') as f: + return json.load(f) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/envbuild.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/envbuild.py new file mode 100644 index 0000000..c264f46 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/envbuild.py @@ -0,0 +1,150 @@ +"""Build wheels/sdists by installing build deps to a temporary environment. +""" + +import os +import logging +from pip._vendor import pytoml +import shutil +from subprocess import check_call +import sys +from sysconfig import get_paths +from tempfile import mkdtemp + +from .wrappers import Pep517HookCaller + +log = logging.getLogger(__name__) + +def _load_pyproject(source_dir): + with open(os.path.join(source_dir, 'pyproject.toml')) as f: + pyproject_data = pytoml.load(f) + buildsys = pyproject_data['build-system'] + return buildsys['requires'], buildsys['build-backend'] + + +class BuildEnvironment(object): + """Context manager to install build deps in a simple temporary environment + + Based on code I wrote for pip, which is MIT licensed. + """ + # Copyright (c) 2008-2016 The pip developers (see AUTHORS.txt file) + # + # 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. + + path = None + + def __init__(self, cleanup=True): + self._cleanup = cleanup + + def __enter__(self): + self.path = mkdtemp(prefix='pep517-build-env-') + log.info('Temporary build environment: %s', self.path) + + self.save_path = os.environ.get('PATH', None) + self.save_pythonpath = os.environ.get('PYTHONPATH', None) + + install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix' + install_dirs = get_paths(install_scheme, vars={ + 'base': self.path, + 'platbase': self.path, + }) + + scripts = install_dirs['scripts'] + if self.save_path: + os.environ['PATH'] = scripts + os.pathsep + self.save_path + else: + os.environ['PATH'] = scripts + os.pathsep + os.defpath + + if install_dirs['purelib'] == install_dirs['platlib']: + lib_dirs = install_dirs['purelib'] + else: + lib_dirs = install_dirs['purelib'] + os.pathsep + \ + install_dirs['platlib'] + if self.save_pythonpath: + os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ + self.save_pythonpath + else: + os.environ['PYTHONPATH'] = lib_dirs + + return self + + def pip_install(self, reqs): + """Install dependencies into this env by calling pip in a subprocess""" + if not reqs: + return + log.info('Calling pip to install %s', reqs) + check_call([sys.executable, '-m', 'pip', 'install', '--ignore-installed', + '--prefix', self.path] + list(reqs)) + + def __exit__(self, exc_type, exc_val, exc_tb): + if self._cleanup and (self.path is not None) and os.path.isdir(self.path): + shutil.rmtree(self.path) + + if self.save_path is None: + os.environ.pop('PATH', None) + else: + os.environ['PATH'] = self.save_path + + if self.save_pythonpath is None: + os.environ.pop('PYTHONPATH', None) + else: + os.environ['PYTHONPATH'] = self.save_pythonpath + +def build_wheel(source_dir, wheel_dir, config_settings=None): + """Build a wheel from a source directory using PEP 517 hooks. + + :param str source_dir: Source directory containing pyproject.toml + :param str wheel_dir: Target directory to create wheel in + :param dict config_settings: Options to pass to build backend + + This is a blocking function which will run pip in a subprocess to install + build requirements. + """ + if config_settings is None: + config_settings = {} + requires, backend = _load_pyproject(source_dir) + hooks = Pep517HookCaller(source_dir, backend) + + with BuildEnvironment() as env: + env.pip_install(requires) + reqs = hooks.get_requires_for_build_wheel(config_settings) + env.pip_install(reqs) + return hooks.build_wheel(wheel_dir, config_settings) + + +def build_sdist(source_dir, sdist_dir, config_settings=None): + """Build an sdist from a source directory using PEP 517 hooks. + + :param str source_dir: Source directory containing pyproject.toml + :param str sdist_dir: Target directory to place sdist in + :param dict config_settings: Options to pass to build backend + + This is a blocking function which will run pip in a subprocess to install + build requirements. + """ + if config_settings is None: + config_settings = {} + requires, backend = _load_pyproject(source_dir) + hooks = Pep517HookCaller(source_dir, backend) + + with BuildEnvironment() as env: + env.pip_install(requires) + reqs = hooks.get_requires_for_build_sdist(config_settings) + env.pip_install(reqs) + return hooks.build_sdist(sdist_dir, config_settings) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pep517/wrappers.py b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/wrappers.py new file mode 100644 index 0000000..28260f3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pep517/wrappers.py @@ -0,0 +1,134 @@ +from contextlib import contextmanager +import os +from os.path import dirname, abspath, join as pjoin +import shutil +from subprocess import check_call +import sys +from tempfile import mkdtemp + +from . import compat + +_in_proc_script = pjoin(dirname(abspath(__file__)), '_in_process.py') + +@contextmanager +def tempdir(): + td = mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + +class UnsupportedOperation(Exception): + """May be raised by build_sdist if the backend indicates that it can't.""" + +class Pep517HookCaller(object): + """A wrapper around a source directory to be built with a PEP 517 backend. + + source_dir : The path to the source directory, containing pyproject.toml. + backend : The build backend spec, as per PEP 517, from pyproject.toml. + """ + def __init__(self, source_dir, build_backend): + self.source_dir = abspath(source_dir) + self.build_backend = build_backend + + def get_requires_for_build_wheel(self, config_settings=None): + """Identify packages required for building a wheel + + Returns a list of dependency specifications, e.g.: + ["wheel >= 0.25", "setuptools"] + + This does not include requirements specified in pyproject.toml. + It returns the result of calling the equivalently named hook in a + subprocess. + """ + return self._call_hook('get_requires_for_build_wheel', { + 'config_settings': config_settings + }) + + def prepare_metadata_for_build_wheel(self, metadata_directory, config_settings=None): + """Prepare a *.dist-info folder with metadata for this project. + + Returns the name of the newly created folder. + + If the build backend defines a hook with this name, it will be called + in a subprocess. If not, the backend will be asked to build a wheel, + and the dist-info extracted from that. + """ + return self._call_hook('prepare_metadata_for_build_wheel', { + 'metadata_directory': abspath(metadata_directory), + 'config_settings': config_settings, + }) + + def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None): + """Build a wheel from this project. + + Returns the name of the newly created file. + + In general, this will call the 'build_wheel' hook in the backend. + However, if that was previously called by + 'prepare_metadata_for_build_wheel', and the same metadata_directory is + used, the previously built wheel will be copied to wheel_directory. + """ + if metadata_directory is not None: + metadata_directory = abspath(metadata_directory) + return self._call_hook('build_wheel', { + 'wheel_directory': abspath(wheel_directory), + 'config_settings': config_settings, + 'metadata_directory': metadata_directory, + }) + + def get_requires_for_build_sdist(self, config_settings=None): + """Identify packages required for building a wheel + + Returns a list of dependency specifications, e.g.: + ["setuptools >= 26"] + + This does not include requirements specified in pyproject.toml. + It returns the result of calling the equivalently named hook in a + subprocess. + """ + return self._call_hook('get_requires_for_build_sdist', { + 'config_settings': config_settings + }) + + def build_sdist(self, sdist_directory, config_settings=None): + """Build an sdist from this project. + + Returns the name of the newly created file. + + This calls the 'build_sdist' backend hook in a subprocess. + """ + return self._call_hook('build_sdist', { + 'sdist_directory': abspath(sdist_directory), + 'config_settings': config_settings, + }) + + + def _call_hook(self, hook_name, kwargs): + env = os.environ.copy() + + # On Python 2, pytoml returns Unicode values (which is correct) but the + # environment passed to check_call needs to contain string values. We + # convert here by encoding using ASCII (the backend can only contain + # letters, digits and _, . and : characters, and will be used as a + # Python identifier, so non-ASCII content is wrong on Python 2 in + # any case). + if sys.version_info[0] == 2: + build_backend = self.build_backend.encode('ASCII') + else: + build_backend = self.build_backend + + env['PEP517_BUILD_BACKEND'] = build_backend + with tempdir() as td: + compat.write_json({'kwargs': kwargs}, pjoin(td, 'input.json'), + indent=2) + + # Run the hook in a subprocess + check_call([sys.executable, _in_proc_script, hook_name, td], + cwd=self.source_dir, env=env) + + data = compat.read_json(pjoin(td, 'output.json')) + if data.get('unsupported'): + raise UnsupportedOperation + return data['return_val'] + diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__init__.py new file mode 100644 index 0000000..0b432f6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/__init__.py @@ -0,0 +1,3149 @@ +# coding: utf-8 +""" +Package resource API +-------------------- + +A resource is a logical file contained within a package, or a logical +subdirectory thereof. The package resource API expects resource names +to have their path parts separated with ``/``, *not* whatever the local +path separator is. Do not use os.path operations to manipulate resource +names being passed into the API. + +The package resource API is designed to work with normal filesystem packages, +.egg files, and unpacked .egg files. It can also work in a limited way with +.zip files and with custom PEP 302 loaders that support the ``get_data()`` +method. +""" + +from __future__ import absolute_import + +import sys +import os +import io +import time +import re +import types +import zipfile +import zipimport +import warnings +import stat +import functools +import pkgutil +import operator +import platform +import collections +import plistlib +import email.parser +import errno +import tempfile +import textwrap +import itertools +import inspect +from pkgutil import get_importer + +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + +try: + FileExistsError +except NameError: + FileExistsError = OSError + +from pip._vendor import six +from pip._vendor.six.moves import urllib, map, filter + +# capture these to bypass sandboxing +from os import utime +try: + from os import mkdir, rename, unlink + WRITE_SUPPORT = True +except ImportError: + # no write support, probably under GAE + WRITE_SUPPORT = False + +from os import open as os_open +from os.path import isdir, split + +try: + import importlib.machinery as importlib_machinery + # access attribute to force import under delayed import mechanisms. + importlib_machinery.__name__ +except ImportError: + importlib_machinery = None + +from . import py31compat +from pip._vendor import appdirs +from pip._vendor import packaging +__import__('pip._vendor.packaging.version') +__import__('pip._vendor.packaging.specifiers') +__import__('pip._vendor.packaging.requirements') +__import__('pip._vendor.packaging.markers') + + +__metaclass__ = type + + +if (3, 0) < sys.version_info < (3, 4): + raise RuntimeError("Python 3.4 or later is required") + +if six.PY2: + # Those builtin exceptions are only defined in Python 3 + PermissionError = None + NotADirectoryError = None + +# declare some globals that will be defined later to +# satisfy the linters. +require = None +working_set = None +add_activation_listener = None +resources_stream = None +cleanup_resources = None +resource_dir = None +resource_stream = None +set_extraction_path = None +resource_isdir = None +resource_string = None +iter_entry_points = None +resource_listdir = None +resource_filename = None +resource_exists = None +_distribution_finders = None +_namespace_handlers = None +_namespace_packages = None + + +class PEP440Warning(RuntimeWarning): + """ + Used when there is an issue with a version or specifier not complying with + PEP 440. + """ + + +def parse_version(v): + try: + return packaging.version.Version(v) + except packaging.version.InvalidVersion: + return packaging.version.LegacyVersion(v) + + +_state_vars = {} + + +def _declare_state(vartype, **kw): + globals().update(kw) + _state_vars.update(dict.fromkeys(kw, vartype)) + + +def __getstate__(): + state = {} + g = globals() + for k, v in _state_vars.items(): + state[k] = g['_sget_' + v](g[k]) + return state + + +def __setstate__(state): + g = globals() + for k, v in state.items(): + g['_sset_' + _state_vars[k]](k, g[k], v) + return state + + +def _sget_dict(val): + return val.copy() + + +def _sset_dict(key, ob, state): + ob.clear() + ob.update(state) + + +def _sget_object(val): + return val.__getstate__() + + +def _sset_object(key, ob, state): + ob.__setstate__(state) + + +_sget_none = _sset_none = lambda *args: None + + +def get_supported_platform(): + """Return this platform's maximum compatible version. + + distutils.util.get_platform() normally reports the minimum version + of Mac OS X that would be required to *use* extensions produced by + distutils. But what we want when checking compatibility is to know the + version of Mac OS X that we are *running*. To allow usage of packages that + explicitly require a newer version of Mac OS X, we must also know the + current version of the OS. + + If this condition occurs for any other platform with a version in its + platform strings, this function should be extended accordingly. + """ + plat = get_build_platform() + m = macosVersionString.match(plat) + if m is not None and sys.platform == "darwin": + try: + plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + except ValueError: + # not Mac OS X + pass + return plat + + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'iter_entry_points', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'Environment', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError', 'VersionConflict', 'DistributionNotFound', + 'UnknownExtra', 'ExtractionError', + + # Warnings + 'PEP440Warning', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Deprecated/backward compatibility only + 'run_main', 'AvailableDistributions', +] + + +class ResolutionError(Exception): + """Abstract base for dependency resolution errors""" + + def __repr__(self): + return self.__class__.__name__ + repr(self.args) + + +class VersionConflict(ResolutionError): + """ + An already-installed version conflicts with the requested version. + + Should be initialized with the installed Distribution and the requested + Requirement. + """ + + _template = "{self.dist} is installed but {self.req} is required" + + @property + def dist(self): + return self.args[0] + + @property + def req(self): + return self.args[1] + + def report(self): + return self._template.format(**locals()) + + def with_context(self, required_by): + """ + If required_by is non-empty, return a version of self that is a + ContextualVersionConflict. + """ + if not required_by: + return self + args = self.args + (required_by,) + return ContextualVersionConflict(*args) + + +class ContextualVersionConflict(VersionConflict): + """ + A VersionConflict that accepts a third parameter, the set of the + requirements that required the installed Distribution. + """ + + _template = VersionConflict._template + ' by {self.required_by}' + + @property + def required_by(self): + return self.args[2] + + +class DistributionNotFound(ResolutionError): + """A requested distribution was not found""" + + _template = ("The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}") + + @property + def req(self): + return self.args[0] + + @property + def requirers(self): + return self.args[1] + + @property + def requirers_str(self): + if not self.requirers: + return 'the application' + return ', '.join(self.requirers) + + def report(self): + return self._template.format(**locals()) + + def __str__(self): + return self.report() + + +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" + + +_provider_factories = {} + +PY_MAJOR = sys.version[:3] +EGG_DIST = 3 +BINARY_DIST = 2 +SOURCE_DIST = 1 +CHECKOUT_DIST = 0 +DEVELOP_DIST = -1 + + +def register_loader_type(loader_type, provider_factory): + """Register `provider_factory` to make providers for `loader_type` + + `loader_type` is the type or class of a PEP 302 ``module.__loader__``, + and `provider_factory` is a function that, passed a *module* object, + returns an ``IResourceProvider`` for that module. + """ + _provider_factories[loader_type] = provider_factory + + +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq, Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] + try: + module = sys.modules[moduleOrReq] + except KeyError: + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] + loader = getattr(module, '__loader__', None) + return _find_adapter(_provider_factories, loader)(module) + + +def _macosx_vers(_cache=[]): + if not _cache: + version = platform.mac_ver()[0] + # fallback for MacPorts + if version == '': + plist = '/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists(plist): + if hasattr(plistlib, 'readPlist'): + plist_content = plistlib.readPlist(plist) + if 'ProductVersion' in plist_content: + version = plist_content['ProductVersion'] + + _cache.append(version.split('.')) + return _cache[0] + + +def _macosx_arch(machine): + return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) + + +def get_build_platform(): + """Return this platform's string for platform-specific distributions + + XXX Currently this is the same as ``distutils.util.get_platform()``, but it + needs some hacks for Linux and Mac OS X. + """ + from sysconfig import get_platform + + plat = get_platform() + if sys.platform == "darwin" and not plat.startswith('macosx-'): + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d-%s" % ( + int(version[0]), int(version[1]), + _macosx_arch(machine), + ) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + return plat + + +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +# XXX backward compat +get_platform = get_build_platform + + +def compatible_platforms(provided, required): + """Can code for the `provided` platform run on the `required` platform? + + Returns true if either platform is ``None``, or the platforms are equal. + + XXX Needs compatibility checks for Linux and other unixy OSes. + """ + if provided is None or required is None or provided == required: + # easy case + return True + + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + return True + # egg isn't macosx or legacy darwin + return False + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(3) != reqMac.group(3): + return False + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here + return False + + +def run_script(dist_spec, script_name): + """Locate distribution `dist_spec` and run its `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].run_script(script_name, ns) + + +# backward compatibility +run_main = run_script + + +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist, six.string_types): + dist = Requirement.parse(dist) + if isinstance(dist, Requirement): + dist = get_provider(dist) + if not isinstance(dist, Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist + + +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) + + +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) + + +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) + + +class IMetadataProvider: + def has_metadata(name): + """Does the package's distribution contain the named metadata?""" + + def get_metadata(name): + """The named metadata resource as a string""" + + def get_metadata_lines(name): + """Yield named metadata resource as list of non-blank non-comment lines + + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" + + def metadata_isdir(name): + """Is the named metadata a directory? (like ``os.path.isdir()``)""" + + def metadata_listdir(name): + """List of metadata names in the directory (like ``os.listdir()``)""" + + def run_script(script_name, namespace): + """Execute the named script in the supplied namespace dictionary""" + + +class IResourceProvider(IMetadataProvider): + """An object that provides access to package resources""" + + def get_resource_filename(manager, resource_name): + """Return a true filesystem path for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_stream(manager, resource_name): + """Return a readable file-like object for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_string(manager, resource_name): + """Return a string containing the contents of `resource_name` + + `manager` must be an ``IResourceManager``""" + + def has_resource(resource_name): + """Does the package contain the named resource?""" + + def resource_isdir(resource_name): + """Is the named resource a directory? (like ``os.path.isdir()``)""" + + def resource_listdir(resource_name): + """List of resource names in the directory (like ``os.listdir()``)""" + + +class WorkingSet: + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + @classmethod + def _build_master(cls): + """ + Prepare the master working set. + """ + ws = cls() + try: + from __main__ import __requires__ + except ImportError: + # The main program does not list any requirements + return ws + + # ensure the requirements are met + try: + ws.require(__requires__) + except VersionConflict: + return cls._build_from_requirements(__requires__) + + return ws + + @classmethod + def _build_from_requirements(cls, req_spec): + """ + Build a working set from a requirement spec. Rewrites sys.path. + """ + # try it without defaults already on sys.path + # by starting with an empty path + ws = cls([]) + reqs = parse_requirements(req_spec) + dists = ws.resolve(reqs, Environment()) + for dist in dists: + ws.add(dist) + + # add any missing entries from sys.path + for entry in sys.path: + if entry not in ws.entries: + ws.add_entry(entry) + + # then copy back to sys.path + sys.path[:] = ws.entries + return ws + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry, True)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, True): + self.add(dist, entry, False) + + def __contains__(self, dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + # XXX add more info + raise VersionConflict(dist, req) + return dist + + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` + + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + return ( + entry + for dist in self + for entry in dist.get_entry_map(group).values() + if name is None or name == entry.name + ) + + def run_script(self, requires, script_name): + """Locate distribution for `requires` and run `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + self.require(requires)[0].run_script(script_name, ns) + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + seen = {} + for item in self.entries: + if item not in self.entry_keys: + # workaround a cache issue + continue + + for key in self.entry_keys[item]: + if key not in seen: + seen[key] = 1 + yield self.by_key[key] + + def add(self, dist, entry=None, insert=True, replace=False): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set, unless `replace=True`. + If it's added, any callbacks registered with the ``subscribe()`` method + will be called. + """ + if insert: + dist.insert_on(self.entries, entry, replace=replace) + + if entry is None: + entry = dist.location + keys = self.entry_keys.setdefault(entry, []) + keys2 = self.entry_keys.setdefault(dist.location, []) + if not replace and dist.key in self.by_key: + # ignore hidden distros + return + + self.by_key[dist.key] = dist + if dist.key not in keys: + keys.append(dist.key) + if dist.key not in keys2: + keys2.append(dist.key) + self._added_new(dist) + + def resolve(self, requirements, env=None, installer=None, + replace_conflicting=False, extras=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``Environment`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + + Unless `replace_conflicting=True`, raises a VersionConflict exception + if + any requirements are found on the path that have the correct name but + the wrong version. Otherwise, if an `installer` is supplied it will be + invoked to obtain the correct version of the requirement and activate + it. + + `extras` is a list of the extras to be used with these requirements. + This is important because extra requirements may look like `my_req; + extra = "my_extra"`, which would otherwise be interpreted as a purely + optional requirement. Instead, we want to be able to assert that these + requirements are truly required. + """ + + # set up the stack + requirements = list(requirements)[::-1] + # set of processed requirements + processed = {} + # key -> dist + best = {} + to_activate = [] + + req_extras = _ReqExtras() + + # Mapping of requirement to set of distributions that required it; + # useful for reporting info about conflicts. + required_by = collections.defaultdict(set) + + while requirements: + # process dependencies breadth-first + req = requirements.pop(0) + if req in processed: + # Ignore cyclic or redundant dependencies + continue + + if not req_extras.markers_pass(req, extras): + continue + + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None or (dist not in req and replace_conflicting): + ws = self + if env is None: + if dist is None: + env = Environment(self.entries) + else: + # Use an empty environment and workingset to avoid + # any further conflicts with the conflicting + # distribution + env = Environment([]) + ws = WorkingSet([]) + dist = best[req.key] = env.best_match( + req, ws, installer, + replace_conflicting=replace_conflicting + ) + if dist is None: + requirers = required_by.get(req, None) + raise DistributionNotFound(req, requirers) + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + dependent_req = required_by[req] + raise VersionConflict(dist, req).with_context(dependent_req) + + # push the new requirements onto the stack + new_requirements = dist.requires(req.extras)[::-1] + requirements.extend(new_requirements) + + # Register the new requirements needed by req + for new_requirement in new_requirements: + required_by[new_requirement].add(req.project_name) + req_extras[new_requirement] = req.extras + + processed[req] = True + + # return list of distros to activate + return to_activate + + def find_plugins( + self, plugin_env, full_env=None, installer=None, fallback=True): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + # add plugins+libs to sys.path + map(working_set.add, distributions) + # display errors + print('Could not load', errors) + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + # scan project names in alphabetic order + plugin_projects.sort() + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + # put all our entries in shadow_set + list(map(shadow_set.add, self)) + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError as v: + # save error info + error_info[dist] = v + if fallback: + # try the next older version of project + continue + else: + # give up on this project, keep going + break + + else: + list(map(shadow_set.add, resolvees)) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + def subscribe(self, callback, existing=True): + """Invoke `callback` for all distributions + + If `existing=True` (default), + call on all existing ones, as well. + """ + if callback in self.callbacks: + return + self.callbacks.append(callback) + if not existing: + return + for dist in self: + callback(dist) + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + def __getstate__(self): + return ( + self.entries[:], self.entry_keys.copy(), self.by_key.copy(), + self.callbacks[:] + ) + + def __setstate__(self, e_k_b_c): + entries, keys, by_key, callbacks = e_k_b_c + self.entries = entries[:] + self.entry_keys = keys.copy() + self.by_key = by_key.copy() + self.callbacks = callbacks[:] + + +class _ReqExtras(dict): + """ + Map each requirement to the extras that demanded it. + """ + + def markers_pass(self, req, extras=None): + """ + Evaluate markers for req against each extra that + demanded it. + + Return False if the req has a marker and fails + evaluation. Otherwise, return True. + """ + extra_evals = ( + req.marker.evaluate({'extra': extra}) + for extra in self.get(req, ()) + (extras or (None,)) + ) + return not req.marker or any(extra_evals) + + +class Environment: + """Searchable snapshot of distributions on a search path""" + + def __init__( + self, search_path=None, platform=get_supported_platform(), + python=PY_MAJOR): + """Snapshot distributions available on a search path + + Any distributions found on `search_path` are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. + + `platform` is an optional string specifying the name of the platform + that platform-specific distributions must be compatible with. If + unspecified, it defaults to the current platform. `python` is an + optional string naming the desired version of Python (e.g. ``'3.6'``); + it defaults to the current version. + + You may explicitly set `platform` (and/or `python`) to ``None`` if you + wish to map *all* distributions, not just those compatible with the + running platform or Python version. + """ + self._distmap = {} + self.platform = platform + self.python = python + self.scan(search_path) + + def can_add(self, dist): + """Is distribution `dist` acceptable for this environment? + + The distribution must match the platform and python version + requirements specified when this environment was created, or False + is returned. + """ + py_compat = ( + self.python is None + or dist.py_version is None + or dist.py_version == self.python + ) + return py_compat and compatible_platforms(dist.platform, self.platform) + + def remove(self, dist): + """Remove `dist` from the environment""" + self._distmap[dist.key].remove(dist) + + def scan(self, search_path=None): + """Scan `search_path` for distributions usable in this environment + + Any distributions found are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. Only distributions conforming to + the platform/python version defined at initialization are added. + """ + if search_path is None: + search_path = sys.path + + for item in search_path: + for dist in find_distributions(item): + self.add(dist) + + def __getitem__(self, project_name): + """Return a newest-to-oldest list of distributions for `project_name` + + Uses case-insensitive `project_name` comparison, assuming all the + project's distributions use their project's name converted to all + lowercase as their key. + + """ + distribution_key = project_name.lower() + return self._distmap.get(distribution_key, []) + + def add(self, dist): + """Add `dist` if we ``can_add()`` it and it has not already been added + """ + if self.can_add(dist) and dist.has_version(): + dists = self._distmap.setdefault(dist.key, []) + if dist not in dists: + dists.append(dist) + dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) + + def best_match( + self, req, working_set, installer=None, replace_conflicting=False): + """Find distribution best matching `req` and usable on `working_set` + + This calls the ``find(req)`` method of the `working_set` to see if a + suitable distribution is already active. (This may raise + ``VersionConflict`` if an unsuitable version of the project is already + active in the specified `working_set`.) If a suitable distribution + isn't active, this method returns the newest distribution in the + environment that meets the ``Requirement`` in `req`. If no suitable + distribution is found, and `installer` is supplied, then the result of + calling the environment's ``obtain(req, installer)`` method will be + returned. + """ + try: + dist = working_set.find(req) + except VersionConflict: + if not replace_conflicting: + raise + dist = None + if dist is not None: + return dist + for dist in self[req.key]: + if dist in req: + return dist + # try to download/install + return self.obtain(req, installer) + + def obtain(self, requirement, installer=None): + """Obtain a distribution matching `requirement` (e.g. via download) + + Obtain a distro that matches requirement (e.g. via download). In the + base ``Environment`` class, this routine just returns + ``installer(requirement)``, unless `installer` is None, in which case + None is returned instead. This method is a hook that allows subclasses + to attempt other ways of obtaining a distribution before falling back + to the `installer` argument.""" + if installer is not None: + return installer(requirement) + + def __iter__(self): + """Yield the unique project names of the available distributions""" + for key in self._distmap.keys(): + if self[key]: + yield key + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other, Distribution): + self.add(other) + elif isinstance(other, Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + +# XXX backward compatibility +AvailableDistributions = Environment + + +class ExtractionError(RuntimeError): + """An error occurred extracting a resource + + The following attributes are available from instances of this exception: + + manager + The resource manager that raised this exception + + cache_path + The base directory for resource extraction + + original_error + The exception instance that caused extraction to fail + """ + + +class ResourceManager: + """Manage resource extraction and packages""" + extraction_path = None + + def __init__(self): + self.cached_files = {} + + def resource_exists(self, package_or_requirement, resource_name): + """Does the named resource exist?""" + return get_provider(package_or_requirement).has_resource(resource_name) + + def resource_isdir(self, package_or_requirement, resource_name): + """Is the named resource an existing directory?""" + return get_provider(package_or_requirement).resource_isdir( + resource_name + ) + + def resource_filename(self, package_or_requirement, resource_name): + """Return a true filesystem path for specified resource""" + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name + ) + + def resource_stream(self, package_or_requirement, resource_name): + """Return a readable file-like object for specified resource""" + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name + ) + + def resource_string(self, package_or_requirement, resource_name): + """Return specified resource as a string""" + return get_provider(package_or_requirement).get_resource_string( + self, resource_name + ) + + def resource_listdir(self, package_or_requirement, resource_name): + """List the contents of the named resource directory""" + return get_provider(package_or_requirement).resource_listdir( + resource_name + ) + + def extraction_error(self): + """Give an error message for problems extracting file(s)""" + + old_exc = sys.exc_info()[1] + cache_path = self.extraction_path or get_default_cache() + + tmpl = textwrap.dedent(""" + Can't extract file(s) to egg cache + + The following error occurred while trying to extract file(s) + to the Python egg cache: + + {old_exc} + + The Python egg cache directory is currently set to: + + {cache_path} + + Perhaps your account does not have write access to this directory? + You can change the cache directory by setting the PYTHON_EGG_CACHE + environment variable to point to an accessible directory. + """).lstrip() + err = ExtractionError(tmpl.format(**locals())) + err.manager = self + err.cache_path = cache_path + err.original_error = old_exc + raise err + + def get_cache_path(self, archive_name, names=()): + """Return absolute location in cache for `archive_name` and `names` + + The parent directory of the resulting path will be created if it does + not already exist. `archive_name` should be the base filename of the + enclosing egg (which may not be the name of the enclosing zipfile!), + including its ".egg" extension. `names`, if provided, should be a + sequence of path name parts "under" the egg's extraction location. + + This method should only be called by resource providers that need to + obtain an extraction location, and only for names they intend to + extract, as it tracks the generated names for possible cleanup later. + """ + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name + '-tmp', *names) + try: + _bypass_ensure_directory(target_path) + except Exception: + self.extraction_error() + + self._warn_unsafe_extraction_path(extract_path) + + self.cached_files[target_path] = 1 + return target_path + + @staticmethod + def _warn_unsafe_extraction_path(path): + """ + If the default extraction path is overridden and set to an insecure + location, such as /tmp, it opens up an opportunity for an attacker to + replace an extracted file with an unauthorized payload. Warn the user + if a known insecure location is used. + + See Distribute #375 for more details. + """ + if os.name == 'nt' and not path.startswith(os.environ['windir']): + # On Windows, permissions are generally restrictive by default + # and temp directories are not writable by other users, so + # bypass the warning. + return + mode = os.stat(path).st_mode + if mode & stat.S_IWOTH or mode & stat.S_IWGRP: + msg = ( + "%s is writable by group/others and vulnerable to attack " + "when " + "used with get_resource_filename. Consider a more secure " + "location (set with .set_extraction_path or the " + "PYTHON_EGG_CACHE environment variable)." % path + ) + warnings.warn(msg, UserWarning) + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` + + This is where Mac header rewrites should be done; other platforms don't + have anything special they should do. + + Resource providers should call this method ONLY after successfully + extracting a compressed resource. They must NOT call it on resources + that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. + """ + + if os.name == 'posix': + # Make the resource executable + mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 + os.chmod(tempname, mode) + + def set_extraction_path(self, path): + """Set the base path where resources will be extracted to, if needed. + + If you do not call this routine before any extractions take place, the + path defaults to the return value of ``get_default_cache()``. (Which + is based on the ``PYTHON_EGG_CACHE`` environment variable, with various + platform-specific fallbacks. See that routine's documentation for more + details.) + + Resources are extracted to subdirectories of this path based upon + information given by the ``IResourceProvider``. You may set this to a + temporary directory, but then you must call ``cleanup_resources()`` to + delete the extracted files when done. There is no guarantee that + ``cleanup_resources()`` will be able to remove all extracted files. + + (Note: you may not change the extraction path for a given resource + manager once resources have been extracted, unless you first call + ``cleanup_resources()``.) + """ + if self.cached_files: + raise ValueError( + "Can't change extraction path, files already extracted" + ) + + self.extraction_path = path + + def cleanup_resources(self, force=False): + """ + Delete all extracted resource files and directories, returning a list + of the file and directory names that could not be successfully removed. + This function does not have any concurrency protection, so it should + generally only be called when the extraction path is a temporary + directory exclusive to a single process. This method is not + automatically called; you must call it explicitly or register it as an + ``atexit`` function if you wish to ensure cleanup of a temporary + directory used for extractions. + """ + # XXX + + +def get_default_cache(): + """ + Return the ``PYTHON_EGG_CACHE`` environment variable + or a platform-relevant user cache dir for an app + named "Python-Eggs". + """ + return ( + os.environ.get('PYTHON_EGG_CACHE') + or appdirs.user_cache_dir(appname='Python-Eggs') + ) + + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """ + Convert an arbitrary string to a standard version string + """ + try: + # normalize the version + return str(packaging.version.Version(version)) + except packaging.version.InvalidVersion: + version = version.replace(' ', '.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-', '_') + + +def invalid_marker(text): + """ + Validate text as a PEP 508 environment marker; return an exception + if invalid or False otherwise. + """ + try: + evaluate_marker(text) + except SyntaxError as e: + e.filename = None + e.lineno = None + return e + return False + + +def evaluate_marker(text, extra=None): + """ + Evaluate a PEP 508 environment marker. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. + + This implementation uses the 'pyparsing' module. + """ + try: + marker = packaging.markers.Marker(text) + return marker.evaluate() + except packaging.markers.InvalidMarker as e: + raise SyntaxError(e) + + +class NullProvider: + """Try to implement resources and metadata for arbitrary PEP 302 loaders""" + + egg_name = None + egg_info = None + loader = None + + def __init__(self, module): + self.loader = getattr(module, '__loader__', None) + self.module_path = os.path.dirname(getattr(module, '__file__', '')) + + def get_resource_filename(self, manager, resource_name): + return self._fn(self.module_path, resource_name) + + def get_resource_stream(self, manager, resource_name): + return io.BytesIO(self.get_resource_string(manager, resource_name)) + + def get_resource_string(self, manager, resource_name): + return self._get(self._fn(self.module_path, resource_name)) + + def has_resource(self, resource_name): + return self._has(self._fn(self.module_path, resource_name)) + + def has_metadata(self, name): + return self.egg_info and self._has(self._fn(self.egg_info, name)) + + def get_metadata(self, name): + if not self.egg_info: + return "" + value = self._get(self._fn(self.egg_info, name)) + return value.decode('utf-8') if six.PY3 else value + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + def resource_isdir(self, resource_name): + return self._isdir(self._fn(self.module_path, resource_name)) + + def metadata_isdir(self, name): + return self.egg_info and self._isdir(self._fn(self.egg_info, name)) + + def resource_listdir(self, resource_name): + return self._listdir(self._fn(self.module_path, resource_name)) + + def metadata_listdir(self, name): + if self.egg_info: + return self._listdir(self._fn(self.egg_info, name)) + return [] + + def run_script(self, script_name, namespace): + script = 'scripts/' + script_name + if not self.has_metadata(script): + raise ResolutionError( + "Script {script!r} not found in metadata at {self.egg_info!r}" + .format(**locals()), + ) + script_text = self.get_metadata(script).replace('\r\n', '\n') + script_text = script_text.replace('\r', '\n') + script_filename = self._fn(self.egg_info, script) + namespace['__file__'] = script_filename + if os.path.exists(script_filename): + source = open(script_filename).read() + code = compile(source, script_filename, 'exec') + exec(code, namespace, namespace) + else: + from linecache import cache + cache[script_filename] = ( + len(script_text), 0, script_text.split('\n'), script_filename + ) + script_code = compile(script_text, script_filename, 'exec') + exec(script_code, namespace, namespace) + + def _has(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _isdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _listdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _fn(self, base, resource_name): + if resource_name: + return os.path.join(base, *resource_name.split('/')) + return base + + def _get(self, path): + if hasattr(self.loader, 'get_data'): + return self.loader.get_data(path) + raise NotImplementedError( + "Can't perform this operation for loaders without 'get_data()'" + ) + + +register_loader_type(object, NullProvider) + + +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" + + def __init__(self, module): + NullProvider.__init__(self, module) + self._setup_prefix() + + def _setup_prefix(self): + # we assume here that our metadata may be nested inside a "basket" + # of multiple eggs; that's why we use module_path instead of .archive + path = self.module_path + old = None + while path != old: + if _is_egg_path(path): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path + break + old = path + path, base = os.path.split(path) + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + + def _isdir(self, path): + return os.path.isdir(path) + + def _listdir(self, path): + return os.listdir(path) + + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + + def _get(self, path): + with open(path, 'rb') as stream: + return stream.read() + + @classmethod + def _register(cls): + loader_names = 'SourceFileLoader', 'SourcelessFileLoader', + for name in loader_names: + loader_cls = getattr(importlib_machinery, name, type(None)) + register_loader_type(loader_cls, cls) + + +DefaultProvider._register() + + +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + + module_path = None + + _isdir = _has = lambda self, path: False + + def _get(self, path): + return '' + + def _listdir(self, path): + return [] + + def __init__(self): + pass + + +empty_provider = EmptyProvider() + + +class ZipManifests(dict): + """ + zip manifest builder + """ + + @classmethod + def build(cls, path): + """ + Build a dictionary similar to the zipimport directory + caches, except instead of tuples, store ZipInfo objects. + + Use a platform-specific path separator (os.sep) for the path keys + for compatibility with pypy on Windows. + """ + with zipfile.ZipFile(path) as zfile: + items = ( + ( + name.replace('/', os.sep), + zfile.getinfo(name), + ) + for name in zfile.namelist() + ) + return dict(items) + + load = build + + +class MemoizedZipManifests(ZipManifests): + """ + Memoized zipfile manifests. + """ + manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') + + def load(self, path): + """ + Load a manifest at path or return a suitable manifest already loaded. + """ + path = os.path.normpath(path) + mtime = os.stat(path).st_mtime + + if path not in self or self[path].mtime != mtime: + manifest = self.build(path) + self[path] = self.manifest_mod(manifest, mtime) + + return self[path].manifest + + +class ZipProvider(EggProvider): + """Resource support for zips and eggs""" + + eagers = None + _zip_manifests = MemoizedZipManifests() + + def __init__(self, module): + EggProvider.__init__(self, module) + self.zip_pre = self.loader.archive + os.sep + + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + fspath = fspath.rstrip(os.sep) + if fspath == self.loader.archive: + return '' + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.zip_pre) + ) + + def _parts(self, zip_path): + # Convert a zipfile subpath into an egg-relative path part list. + # pseudo-fs path + fspath = self.zip_pre + zip_path + if fspath.startswith(self.egg_root + os.sep): + return fspath[len(self.egg_root) + 1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.egg_root) + ) + + @property + def zipinfo(self): + return self._zip_manifests.load(self.loader.archive) + + def get_resource_filename(self, manager, resource_name): + if not self.egg_name: + raise NotImplementedError( + "resource_filename() only supported for .egg, not .zip" + ) + # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) + eagers = self._get_eager_resources() + if '/'.join(self._parts(zip_path)) in eagers: + for name in eagers: + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) + + @staticmethod + def _get_date_and_size(zip_stat): + size = zip_stat.file_size + # ymdhms+wday, yday, dst + date_time = zip_stat.date_time + (0, 0, -1) + # 1980 offset already done + timestamp = time.mktime(date_time) + return timestamp, size + + def _extract_resource(self, manager, zip_path): + + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + # return the extracted directory name + return os.path.dirname(last) + + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + + if not WRITE_SUPPORT: + raise IOError('"os.rename" and "os.unlink" are not supported ' + 'on this platform') + try: + + real_path = manager.get_cache_path( + self.egg_name, self._parts(zip_path) + ) + + if self._is_current(real_path, zip_path): + return real_path + + outf, tmpnam = _mkstemp( + ".$extract", + dir=os.path.dirname(real_path), + ) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + utime(tmpnam, (timestamp, timestamp)) + manager.postprocess(tmpnam, real_path) + + try: + rename(tmpnam, real_path) + + except os.error: + if os.path.isfile(real_path): + if self._is_current(real_path, zip_path): + # the file became current since it was checked above, + # so proceed. + return real_path + # Windows, del old file and retry + elif os.name == 'nt': + unlink(real_path) + rename(tmpnam, real_path) + return real_path + raise + + except os.error: + # report a user-friendly error + manager.extraction_error() + + return real_path + + def _is_current(self, file_path, zip_path): + """ + Return True if the file_path is current for this zip_path + """ + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + if not os.path.isfile(file_path): + return False + stat = os.stat(file_path) + if stat.st_size != size or stat.st_mtime != timestamp: + return False + # check that the contents match + zip_contents = self.loader.get_data(zip_path) + with open(file_path, 'rb') as f: + file_contents = f.read() + return zip_contents == file_contents + + def _get_eager_resources(self): + if self.eagers is None: + eagers = [] + for name in ('native_libs.txt', 'eager_resources.txt'): + if self.has_metadata(name): + eagers.extend(self.get_metadata_lines(name)) + self.eagers = eagers + return self.eagers + + def _index(self): + try: + return self._dirindex + except AttributeError: + ind = {} + for path in self.zipinfo: + parts = path.split(os.sep) + while parts: + parent = os.sep.join(parts[:-1]) + if parent in ind: + ind[parent].append(parts[-1]) + break + else: + ind[parent] = [parts.pop()] + self._dirindex = ind + return ind + + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() + + def _isdir(self, fspath): + return self._zipinfo_name(fspath) in self._index() + + def _listdir(self, fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) + + def _eager_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.egg_root, resource_name)) + + def _resource_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.module_path, resource_name)) + + +register_loader_type(zipimport.zipimporter, ZipProvider) + + +class FileMetadata(EmptyProvider): + """Metadata handler for standalone PKG-INFO files + + Usage:: + + metadata = FileMetadata("/path/to/PKG-INFO") + + This provider rejects all data and metadata requests except for PKG-INFO, + which is treated as existing, and will be the contents of the file at + the provided location. + """ + + def __init__(self, path): + self.path = path + + def has_metadata(self, name): + return name == 'PKG-INFO' and os.path.isfile(self.path) + + def get_metadata(self, name): + if name != 'PKG-INFO': + raise KeyError("No metadata except PKG-INFO is available") + + with io.open(self.path, encoding='utf-8', errors="replace") as f: + metadata = f.read() + self._warn_on_replacement(metadata) + return metadata + + def _warn_on_replacement(self, metadata): + # Python 2.7 compat for: replacement_char = '�' + replacement_char = b'\xef\xbf\xbd'.decode('utf-8') + if replacement_char in metadata: + tmpl = "{self.path} could not be properly decoded in UTF-8" + msg = tmpl.format(**locals()) + warnings.warn(msg) + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + +class PathMetadata(DefaultProvider): + """Metadata provider for egg directories + + Usage:: + + # Development eggs: + + egg_info = "/path/to/PackageName.egg-info" + base_dir = os.path.dirname(egg_info) + metadata = PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + dist = Distribution(basedir, project_name=dist_name, metadata=metadata) + + # Unpacked egg directories: + + egg_path = "/path/to/PackageName-ver-pyver-etc.egg" + metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) + dist = Distribution.from_filename(egg_path, metadata=metadata) + """ + + def __init__(self, path, egg_info): + self.module_path = path + self.egg_info = egg_info + + +class EggMetadata(ZipProvider): + """Metadata provider for .egg files""" + + def __init__(self, importer): + """Create a metadata provider from a zipimporter""" + + self.zip_pre = importer.archive + os.sep + self.loader = importer + if importer.prefix: + self.module_path = os.path.join(importer.archive, importer.prefix) + else: + self.module_path = importer.archive + self._setup_prefix() + + +_declare_state('dict', _distribution_finders={}) + + +def register_finder(importer_type, distribution_finder): + """Register `distribution_finder` to find distributions in sys.path items + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `distribution_finder` is a callable that, passed a path + item and the importer instance, yields ``Distribution`` instances found on + that path item. See ``pkg_resources.find_on_path`` for an example.""" + _distribution_finders[importer_type] = distribution_finder + + +def find_distributions(path_item, only=False): + """Yield distributions accessible via `path_item`""" + importer = get_importer(path_item) + finder = _find_adapter(_distribution_finders, importer) + return finder(importer, path_item, only) + + +def find_eggs_in_zip(importer, path_item, only=False): + """ + Find eggs in zip files; possibly multiple nested eggs. + """ + if importer.archive.endswith('.whl'): + # wheels are not supported with this finder + # they don't have PKG-INFO metadata, and won't ever contain eggs + return + metadata = EggMetadata(importer) + if metadata.has_metadata('PKG-INFO'): + yield Distribution.from_filename(path_item, metadata=metadata) + if only: + # don't yield nested distros + return + for subitem in metadata.resource_listdir('/'): + if _is_egg_path(subitem): + subpath = os.path.join(path_item, subitem) + dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) + for dist in dists: + yield dist + elif subitem.lower().endswith('.dist-info'): + subpath = os.path.join(path_item, subitem) + submeta = EggMetadata(zipimport.zipimporter(subpath)) + submeta.egg_info = subpath + yield Distribution.from_location(path_item, subitem, submeta) + + +register_finder(zipimport.zipimporter, find_eggs_in_zip) + + +def find_nothing(importer, path_item, only=False): + return () + + +register_finder(object, find_nothing) + + +def _by_version_descending(names): + """ + Given a list of filenames, return them in descending order + by version number. + + >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' + >>> _by_version_descending(names) + ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] + """ + def _by_version(name): + """ + Parse each component of the filename + """ + name, ext = os.path.splitext(name) + parts = itertools.chain(name.split('-'), [ext]) + return [packaging.version.parse(part) for part in parts] + + return sorted(names, key=_by_version, reverse=True) + + +def find_on_path(importer, path_item, only=False): + """Yield distributions accessible on a sys.path directory""" + path_item = _normalize_cached(path_item) + + if _is_unpacked_egg(path_item): + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item, 'EGG-INFO') + ) + ) + return + + entries = safe_listdir(path_item) + + # for performance, before sorting by version, + # screen entries for only those that will yield + # distributions + filtered = ( + entry + for entry in entries + if dist_factory(path_item, entry, only) + ) + + # scan for .egg and .egg-info in directory + path_item_entries = _by_version_descending(filtered) + for entry in path_item_entries: + fullpath = os.path.join(path_item, entry) + factory = dist_factory(path_item, entry, only) + for dist in factory(fullpath): + yield dist + + +def dist_factory(path_item, entry, only): + """ + Return a dist_factory for a path_item and entry + """ + lower = entry.lower() + is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) + return ( + distributions_from_metadata + if is_meta else + find_distributions + if not only and _is_egg_path(entry) else + resolve_egg_link + if not only and lower.endswith('.egg-link') else + NoDists() + ) + + +class NoDists: + """ + >>> bool(NoDists()) + False + + >>> list(NoDists()('anything')) + [] + """ + def __bool__(self): + return False + if six.PY2: + __nonzero__ = __bool__ + + def __call__(self, fullpath): + return iter(()) + + +def safe_listdir(path): + """ + Attempt to list contents of path, but suppress some exceptions. + """ + try: + return os.listdir(path) + except (PermissionError, NotADirectoryError): + pass + except OSError as e: + # Ignore the directory if does not exist, not a directory or + # permission denied + ignorable = ( + e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) + # Python 2 on Windows needs to be handled this way :( + or getattr(e, "winerror", None) == 267 + ) + if not ignorable: + raise + return () + + +def distributions_from_metadata(path): + root = os.path.dirname(path) + if os.path.isdir(path): + if len(os.listdir(path)) == 0: + # empty metadata dir; skip + return + metadata = PathMetadata(root, path) + else: + metadata = FileMetadata(path) + entry = os.path.basename(path) + yield Distribution.from_location( + root, entry, metadata, precedence=DEVELOP_DIST, + ) + + +def non_empty_lines(path): + """ + Yield non-empty lines from file at path + """ + with open(path) as f: + for line in f: + line = line.strip() + if line: + yield line + + +def resolve_egg_link(path): + """ + Given a path to an .egg-link, resolve distributions + present in the referenced path. + """ + referenced_paths = non_empty_lines(path) + resolved_paths = ( + os.path.join(os.path.dirname(path), ref) + for ref in referenced_paths + ) + dist_groups = map(find_distributions, resolved_paths) + return next(dist_groups, ()) + + +register_finder(pkgutil.ImpImporter, find_on_path) + +if hasattr(importlib_machinery, 'FileFinder'): + register_finder(importlib_machinery.FileFinder, find_on_path) + +_declare_state('dict', _namespace_handlers={}) +_declare_state('dict', _namespace_packages={}) + + +def register_namespace_handler(importer_type, namespace_handler): + """Register `namespace_handler` to declare namespace packages + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `namespace_handler` is a callable like this:: + + def namespace_handler(importer, path_entry, moduleName, module): + # return a path_entry to use for child packages + + Namespace handlers are only called if the importer object has already + agreed that it can handle the relevant path item, and they should only + return a subpath if the module __path__ does not already contain an + equivalent subpath. For an example namespace handler, see + ``pkg_resources.file_ns_handler``. + """ + _namespace_handlers[importer_type] = namespace_handler + + +def _handle_ns(packageName, path_item): + """Ensure that named package includes a subpath of path_item (if needed)""" + + importer = get_importer(path_item) + if importer is None: + return None + + # capture warnings due to #1111 + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + loader = importer.find_module(packageName) + + if loader is None: + return None + module = sys.modules.get(packageName) + if module is None: + module = sys.modules[packageName] = types.ModuleType(packageName) + module.__path__ = [] + _set_parent_ns(packageName) + elif not hasattr(module, '__path__'): + raise TypeError("Not a package:", packageName) + handler = _find_adapter(_namespace_handlers, importer) + subpath = handler(importer, path_item, packageName, module) + if subpath is not None: + path = module.__path__ + path.append(subpath) + loader.load_module(packageName) + _rebuild_mod_path(path, packageName, module) + return subpath + + +def _rebuild_mod_path(orig_path, package_name, module): + """ + Rebuild module.__path__ ensuring that all entries are ordered + corresponding to their sys.path order + """ + sys_path = [_normalize_cached(p) for p in sys.path] + + def safe_sys_path_index(entry): + """ + Workaround for #520 and #513. + """ + try: + return sys_path.index(entry) + except ValueError: + return float('inf') + + def position_in_sys_path(path): + """ + Return the ordinal of the path based on its position in sys.path + """ + path_parts = path.split(os.sep) + module_parts = package_name.count('.') + 1 + parts = path_parts[:-module_parts] + return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) + + new_path = sorted(orig_path, key=position_in_sys_path) + new_path = [_normalize_cached(p) for p in new_path] + + if isinstance(module.__path__, list): + module.__path__[:] = new_path + else: + module.__path__ = new_path + + +def declare_namespace(packageName): + """Declare that package 'packageName' is a namespace package""" + + _imp.acquire_lock() + try: + if packageName in _namespace_packages: + return + + path = sys.path + parent, _, _ = packageName.rpartition('.') + + if parent: + declare_namespace(parent) + if parent not in _namespace_packages: + __import__(parent) + try: + path = sys.modules[parent].__path__ + except AttributeError: + raise TypeError("Not a package:", parent) + + # Track what packages are namespaces, so when new path items are added, + # they can be updated + _namespace_packages.setdefault(parent or None, []).append(packageName) + _namespace_packages.setdefault(packageName, []) + + for path_item in path: + # Ensure all the parent's path items are reflected in the child, + # if they apply + _handle_ns(packageName, path_item) + + finally: + _imp.release_lock() + + +def fixup_namespace_packages(path_item, parent=None): + """Ensure that previously-declared namespace packages include path_item""" + _imp.acquire_lock() + try: + for package in _namespace_packages.get(parent, ()): + subpath = _handle_ns(package, path_item) + if subpath: + fixup_namespace_packages(subpath, package) + finally: + _imp.release_lock() + + +def file_ns_handler(importer, path_item, packageName, module): + """Compute an ns-package subpath for a filesystem or zipfile importer""" + + subpath = os.path.join(path_item, packageName.split('.')[-1]) + normalized = _normalize_cached(subpath) + for item in module.__path__: + if _normalize_cached(item) == normalized: + break + else: + # Only return the path if it's not already there + return subpath + + +register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) +register_namespace_handler(zipimport.zipimporter, file_ns_handler) + +if hasattr(importlib_machinery, 'FileFinder'): + register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) + + +def null_ns_handler(importer, path_item, packageName, module): + return None + + +register_namespace_handler(object, null_ns_handler) + + +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(filename)) + + +def _normalize_cached(filename, _cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result + + +def _is_egg_path(path): + """ + Determine if given path appears to be an egg. + """ + return path.lower().endswith('.egg') + + +def _is_unpacked_egg(path): + """ + Determine if given path appears to be an unpacked egg. + """ + return ( + _is_egg_path(path) and + os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) + ) + + +def _set_parent_ns(packageName): + parts = packageName.split('.') + name = parts.pop() + if parts: + parent = '.'.join(parts) + setattr(sys.modules[parent], name, sys.modules[packageName]) + + +def yield_lines(strs): + """Yield non-empty/non-comment lines of a string or sequence""" + if isinstance(strs, six.string_types): + for s in strs.splitlines(): + s = s.strip() + # skip blank lines/comments + if s and not s.startswith('#'): + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + + +MODULE = re.compile(r"\w+(\.\w+)*$").match +EGG_NAME = re.compile( + r""" + (?P<name>[^-]+) ( + -(?P<ver>[^-]+) ( + -py(?P<pyver>[^-]+) ( + -(?P<plat>.+) + )? + )? + )? + """, + re.VERBOSE | re.IGNORECASE, +).match + + +class EntryPoint: + """Object representing an advertised importable object""" + + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = tuple(extras) + self.dist = dist + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self, require=True, *args, **kwargs): + """ + Require packages for this EntryPoint, then resolve it. + """ + if not require or args or kwargs: + warnings.warn( + "Parameters to load are deprecated. Call .resolve and " + ".require separately.", + DeprecationWarning, + stacklevel=2, + ) + if require: + self.require(*args, **kwargs) + return self.resolve() + + def resolve(self): + """ + Resolve the entry point from its module and attrs. + """ + module = __import__(self.module_name, fromlist=['__name__'], level=0) + try: + return functools.reduce(getattr, self.attrs, module) + except AttributeError as exc: + raise ImportError(str(exc)) + + def require(self, env=None, installer=None): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + + # Get the requirements for this entry point with all its extras and + # then resolve them. We have to pass `extras` along when resolving so + # that the working set knows what extras we want. Otherwise, for + # dist-info distributions, the working set will assume that the + # requirements for that extra are purely optional and skip over them. + reqs = self.dist.requires(self.extras) + items = working_set.resolve(reqs, env, installer, extras=self.extras) + list(map(working_set.add, items)) + + pattern = re.compile( + r'\s*' + r'(?P<name>.+?)\s*' + r'=\s*' + r'(?P<module>[\w.]+)\s*' + r'(:\s*(?P<attr>[\w.]+))?\s*' + r'(?P<extras>\[.*\])?\s*$' + ) + + @classmethod + def parse(cls, src, dist=None): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1, extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + m = cls.pattern.match(src) + if not m: + msg = "EntryPoint must be in 'name=module:attrs [extras]' format" + raise ValueError(msg, src) + res = m.groupdict() + extras = cls._parse_extras(res['extras']) + attrs = res['attr'].split('.') if res['attr'] else () + return cls(res['name'], res['module'], attrs, extras, dist) + + @classmethod + def _parse_extras(cls, extras_spec): + if not extras_spec: + return () + req = Requirement.parse('x' + extras_spec) + if req.specs: + raise ValueError() + return req.extras + + @classmethod + def parse_group(cls, group, lines, dist=None): + """Parse an entry point group""" + if not MODULE(group): + raise ValueError("Invalid group name", group) + this = {} + for line in yield_lines(lines): + ep = cls.parse(line, dist) + if ep.name in this: + raise ValueError("Duplicate entry point", group, ep.name) + this[ep.name] = ep + return this + + @classmethod + def parse_map(cls, data, dist=None): + """Parse a map of entry point groups""" + if isinstance(data, dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for group, lines in data: + if group is None: + if not lines: + continue + raise ValueError("Entry points must be listed in groups") + group = group.strip() + if group in maps: + raise ValueError("Duplicate group name", group) + maps[group] = cls.parse_group(group, lines, dist) + return maps + + +def _remove_md5_fragment(location): + if not location: + return '' + parsed = urllib.parse.urlparse(location) + if parsed[-1].startswith('md5='): + return urllib.parse.urlunparse(parsed[:-1] + ('',)) + return location + + +def _version_from_file(lines): + """ + Given an iterable of lines from a Metadata file, return + the value of the Version field, if present, or None otherwise. + """ + def is_version_line(line): + return line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) + line = next(iter(version_lines), '') + _, _, value = line.partition(':') + return safe_version(value.strip()) or None + + +class Distribution: + """Wrap an actual or potential sys.path entry w/metadata""" + PKG_INFO = 'PKG-INFO' + + def __init__( + self, location=None, metadata=None, project_name=None, + version=None, py_version=PY_MAJOR, platform=None, + precedence=EGG_DIST): + self.project_name = safe_name(project_name or 'Unknown') + if version is not None: + self._version = safe_version(version) + self.py_version = py_version + self.platform = platform + self.location = location + self.precedence = precedence + self._provider = metadata or empty_provider + + @classmethod + def from_location(cls, location, basename, metadata=None, **kw): + project_name, version, py_version, platform = [None] * 4 + basename, ext = os.path.splitext(basename) + if ext.lower() in _distributionImpl: + cls = _distributionImpl[ext.lower()] + + match = EGG_NAME(basename) + if match: + project_name, version, py_version, platform = match.group( + 'name', 'ver', 'pyver', 'plat' + ) + return cls( + location, metadata, project_name=project_name, version=version, + py_version=py_version, platform=platform, **kw + )._reload_version() + + def _reload_version(self): + return self + + @property + def hashcmp(self): + return ( + self.parsed_version, + self.precedence, + self.key, + _remove_md5_fragment(self.location), + self.py_version or '', + self.platform or '', + ) + + def __hash__(self): + return hash(self.hashcmp) + + def __lt__(self, other): + return self.hashcmp < other.hashcmp + + def __le__(self, other): + return self.hashcmp <= other.hashcmp + + def __gt__(self, other): + return self.hashcmp > other.hashcmp + + def __ge__(self, other): + return self.hashcmp >= other.hashcmp + + def __eq__(self, other): + if not isinstance(other, self.__class__): + # It's not a Distribution, so they are not equal + return False + return self.hashcmp == other.hashcmp + + def __ne__(self, other): + return not self == other + + # These properties have to be lazy so that we don't have to load any + # metadata until/unless it's actually needed. (i.e., some distributions + # may not know their name or version without loading PKG-INFO) + + @property + def key(self): + try: + return self._key + except AttributeError: + self._key = key = self.project_name.lower() + return key + + @property + def parsed_version(self): + if not hasattr(self, "_parsed_version"): + self._parsed_version = parse_version(self.version) + + return self._parsed_version + + def _warn_legacy_version(self): + LV = packaging.version.LegacyVersion + is_legacy = isinstance(self._parsed_version, LV) + if not is_legacy: + return + + # While an empty version is technically a legacy version and + # is not a valid PEP 440 version, it's also unlikely to + # actually come from someone and instead it is more likely that + # it comes from setuptools attempting to parse a filename and + # including it in the list. So for that we'll gate this warning + # on if the version is anything at all or not. + if not self.version: + return + + tmpl = textwrap.dedent(""" + '{project_name} ({version})' is being parsed as a legacy, + non PEP 440, + version. You may find odd behavior and sort order. + In particular it will be sorted as less than 0.0. It + is recommended to migrate to PEP 440 compatible + versions. + """).strip().replace('\n', ' ') + + warnings.warn(tmpl.format(**vars(self)), PEP440Warning) + + @property + def version(self): + try: + return self._version + except AttributeError: + version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if version is None: + tmpl = "Missing 'Version:' header and/or %s file" + raise ValueError(tmpl % self.PKG_INFO, self) + return version + + @property + def _dep_map(self): + """ + A map of extra to its list of (direct) requirements + for this distribution, including the null extra. + """ + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._filter_extras(self._build_dep_map()) + return self.__dep_map + + @staticmethod + def _filter_extras(dm): + """ + Given a mapping of extras to dependencies, strip off + environment markers and filter out any dependencies + not matching the markers. + """ + for extra in list(filter(None, dm)): + new_extra = extra + reqs = dm.pop(extra) + new_extra, _, marker = extra.partition(':') + fails_marker = marker and ( + invalid_marker(marker) + or not evaluate_marker(marker) + ) + if fails_marker: + reqs = [] + new_extra = safe_extra(new_extra) or None + + dm.setdefault(new_extra, []).extend(reqs) + return dm + + def _build_dep_map(self): + dm = {} + for name in 'requires.txt', 'depends.txt': + for extra, reqs in split_sections(self._get_metadata(name)): + dm.setdefault(extra, []).extend(parse_requirements(reqs)) + return dm + + def requires(self, extras=()): + """List of Requirements needed for this distro if `extras` are used""" + dm = self._dep_map + deps = [] + deps.extend(dm.get(None, ())) + for ext in extras: + try: + deps.extend(dm[safe_extra(ext)]) + except KeyError: + raise UnknownExtra( + "%s has no such extra feature %r" % (self, ext) + ) + return deps + + def _get_metadata(self, name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + def activate(self, path=None, replace=False): + """Ensure distribution is importable on `path` (default=sys.path)""" + if path is None: + path = sys.path + self.insert_on(path, replace=replace) + if path is sys.path: + fixup_namespace_packages(self.location) + for pkg in self._get_metadata('namespace_packages.txt'): + if pkg in sys.modules: + declare_namespace(pkg) + + def egg_name(self): + """Return what this distribution's standard .egg filename should be""" + filename = "%s-%s-py%s" % ( + to_filename(self.project_name), to_filename(self.version), + self.py_version or PY_MAJOR + ) + + if self.platform: + filename += '-' + self.platform + return filename + + def __repr__(self): + if self.location: + return "%s (%s)" % (self, self.location) + else: + return str(self) + + def __str__(self): + try: + version = getattr(self, 'version', None) + except ValueError: + version = None + version = version or "[unknown version]" + return "%s %s" % (self.project_name, version) + + def __getattr__(self, attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError(attr) + return getattr(self._provider, attr) + + def __dir__(self): + return list( + set(super(Distribution, self).__dir__()) + | set( + attr for attr in self._provider.__dir__() + if not attr.startswith('_') + ) + ) + + if not hasattr(object, '__dir__'): + # python 2.7 not supported + del __dir__ + + @classmethod + def from_filename(cls, filename, metadata=None, **kw): + return cls.from_location( + _normalize_cached(filename), os.path.basename(filename), metadata, + **kw + ) + + def as_requirement(self): + """Return a ``Requirement`` that matches this distribution exactly""" + if isinstance(self.parsed_version, packaging.version.Version): + spec = "%s==%s" % (self.project_name, self.parsed_version) + else: + spec = "%s===%s" % (self.project_name, self.parsed_version) + + return Requirement.parse(spec) + + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group, name) + if ep is None: + raise ImportError("Entry point %r not found" % ((group, name),)) + return ep.load() + + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt'), self + ) + if group is not None: + return ep_map.get(group, {}) + return ep_map + + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + def insert_on(self, path, loc=None, replace=False): + """Ensure self.location is on path + + If replace=False (default): + - If location is already in path anywhere, do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent. + - Else: add to the end of path. + If replace=True: + - If location is already on path anywhere (not eggs) + or higher priority than its parent (eggs) + do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent, + removing any lower-priority entries. + - Else: add it to the front of path. + """ + + loc = loc or self.location + if not loc: + return + + nloc = _normalize_cached(loc) + bdir = os.path.dirname(nloc) + npath = [(p and _normalize_cached(p) or p) for p in path] + + for p, item in enumerate(npath): + if item == nloc: + if replace: + break + else: + # don't modify path (even removing duplicates) if + # found and not replace + return + elif item == bdir and self.precedence == EGG_DIST: + # if it's an .egg, give it precedence over its directory + # UNLESS it's already been added to sys.path and replace=False + if (not replace) and nloc in npath[p:]: + return + if path is sys.path: + self.check_version_conflict() + path.insert(p, loc) + npath.insert(p, nloc) + break + else: + if path is sys.path: + self.check_version_conflict() + if replace: + path.insert(0, loc) + else: + path.append(loc) + return + + # p is the spot where we found or inserted loc; now remove duplicates + while True: + try: + np = npath.index(nloc, p + 1) + except ValueError: + break + else: + del npath[np], path[np] + # ha! + p = np + + return + + def check_version_conflict(self): + if self.key == 'setuptools': + # ignore the inevitable setuptools self-conflicts :( + return + + nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) + loc = normalize_path(self.location) + for modname in self._get_metadata('top_level.txt'): + if (modname not in sys.modules or modname in nsp + or modname in _namespace_packages): + continue + if modname in ('pkg_resources', 'setuptools', 'site'): + continue + fn = getattr(sys.modules[modname], '__file__', None) + if fn and (normalize_path(fn).startswith(loc) or + fn.startswith(self.location)): + continue + issue_warning( + "Module %s was already imported from %s, but %s is being added" + " to sys.path" % (modname, fn, self.location), + ) + + def has_version(self): + try: + self.version + except ValueError: + issue_warning("Unbuilt egg for " + repr(self)) + return False + return True + + def clone(self, **kw): + """Copy this distribution, substituting in any changed keyword args""" + names = 'project_name version py_version platform location precedence' + for attr in names.split(): + kw.setdefault(attr, getattr(self, attr, None)) + kw.setdefault('metadata', self._provider) + return self.__class__(**kw) + + @property + def extras(self): + return [dep for dep in self._dep_map if dep] + + +class EggInfoDistribution(Distribution): + def _reload_version(self): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + take an extra step and try to get the version number from + the metadata file itself instead of the filename. + """ + md_version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if md_version: + self._version = md_version + return self + + +class DistInfoDistribution(Distribution): + """ + Wrap an actual or potential sys.path entry + w/metadata, .dist-info style. + """ + PKG_INFO = 'METADATA' + EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") + + @property + def _parsed_pkg_info(self): + """Parse and cache metadata""" + try: + return self._pkg_info + except AttributeError: + metadata = self.get_metadata(self.PKG_INFO) + self._pkg_info = email.parser.Parser().parsestr(metadata) + return self._pkg_info + + @property + def _dep_map(self): + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._compute_dependencies() + return self.__dep_map + + def _compute_dependencies(self): + """Recompute this distribution's dependencies.""" + dm = self.__dep_map = {None: []} + + reqs = [] + # Including any condition expressions + for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: + reqs.extend(parse_requirements(req)) + + def reqs_for_extra(extra): + for req in reqs: + if not req.marker or req.marker.evaluate({'extra': extra}): + yield req + + common = frozenset(reqs_for_extra(None)) + dm[None].extend(common) + + for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: + s_extra = safe_extra(extra.strip()) + dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) + + return dm + + +_distributionImpl = { + '.egg': Distribution, + '.egg-info': EggInfoDistribution, + '.dist-info': DistInfoDistribution, +} + + +def issue_warning(*args, **kw): + level = 1 + g = globals() + try: + # find the first stack frame that is *not* code in + # the pkg_resources module, to use for the warning + while sys._getframe(level).f_globals is g: + level += 1 + except ValueError: + pass + warnings.warn(stacklevel=level + 1, *args, **kw) + + +class RequirementParseError(ValueError): + def __str__(self): + return ' '.join(self.args) + + +def parse_requirements(strs): + """Yield ``Requirement`` objects for each specification in `strs` + + `strs` must be a string, or a (possibly-nested) iterable thereof. + """ + # create a steppable iterator, so we can handle \-continuations + lines = iter(yield_lines(strs)) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if ' #' in line: + line = line[:line.find(' #')] + # If there is a line continuation, drop it, and append the next line. + if line.endswith('\\'): + line = line[:-2].strip() + try: + line += next(lines) + except StopIteration: + return + yield Requirement(line) + + +class Requirement(packaging.requirements.Requirement): + def __init__(self, requirement_string): + """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" + try: + super(Requirement, self).__init__(requirement_string) + except packaging.requirements.InvalidRequirement as e: + raise RequirementParseError(str(e)) + self.unsafe_name = self.name + project_name = safe_name(self.name) + self.project_name, self.key = project_name, project_name.lower() + self.specs = [ + (spec.operator, spec.version) for spec in self.specifier] + self.extras = tuple(map(safe_extra, self.extras)) + self.hashCmp = ( + self.key, + self.specifier, + frozenset(self.extras), + str(self.marker) if self.marker else None, + ) + self.__hash = hash(self.hashCmp) + + def __eq__(self, other): + return ( + isinstance(other, Requirement) and + self.hashCmp == other.hashCmp + ) + + def __ne__(self, other): + return not self == other + + def __contains__(self, item): + if isinstance(item, Distribution): + if item.key != self.key: + return False + + item = item.version + + # Allow prereleases always in order to match the previous behavior of + # this method. In the future this should be smarter and follow PEP 440 + # more accurately. + return self.specifier.contains(item, prereleases=True) + + def __hash__(self): + return self.__hash + + def __repr__(self): + return "Requirement.parse(%r)" % str(self) + + @staticmethod + def parse(s): + req, = parse_requirements(s) + return req + + +def _always_object(classes): + """ + Ensure object appears in the mro even + for old-style classes. + """ + if object not in classes: + return classes + (object,) + return classes + + +def _find_adapter(registry, ob): + """Return an adapter factory for `ob` from `registry`""" + types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) + for t in types: + if t in registry: + return registry[t] + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + py31compat.makedirs(dirname, exist_ok=True) + + +def _bypass_ensure_directory(path): + """Sandbox-bypassing version of ensure_directory()""" + if not WRITE_SUPPORT: + raise IOError('"os.mkdir" not supported on this platform.') + dirname, filename = split(path) + if dirname and filename and not isdir(dirname): + _bypass_ensure_directory(dirname) + try: + mkdir(dirname, 0o755) + except FileExistsError: + pass + + +def split_sections(s): + """Split a string or iterable thereof into (section, content) pairs + + Each ``section`` is a stripped version of the section header ("[section]") + and each ``content`` is a list of stripped lines excluding blank lines and + comment-only lines. If there are any such lines before the first section + header, they're returned in a first ``section`` of ``None``. + """ + section = None + content = [] + for line in yield_lines(s): + if line.startswith("["): + if line.endswith("]"): + if section or content: + yield section, content + section = line[1:-1].strip() + content = [] + else: + raise ValueError("Invalid section heading", line) + else: + content.append(line) + + # wrap up last segment + yield section, content + + +def _mkstemp(*args, **kw): + old_open = os.open + try: + # temporarily bypass sandboxing + os.open = os_open + return tempfile.mkstemp(*args, **kw) + finally: + # and then put it back + os.open = old_open + + +# Silence the PEP440Warning by default, so that end users don't get hit by it +# randomly just because they use pkg_resources. We want to append the rule +# because we want earlier uses of filterwarnings to take precedence over this +# one. +warnings.filterwarnings("ignore", category=PEP440Warning, append=True) + + +# from jaraco.functools 1.3 +def _call_aside(f, *args, **kwargs): + f(*args, **kwargs) + return f + + +@_call_aside +def _initialize(g=globals()): + "Set up global resource manager (deliberately not state-saved)" + manager = ResourceManager() + g['_manager'] = manager + g.update( + (name, getattr(manager, name)) + for name in dir(manager) + if not name.startswith('_') + ) + + +@_call_aside +def _initialize_master_working_set(): + """ + Prepare the master working set and make the ``require()`` + API available. + + This function has explicit effects on the global state + of pkg_resources. It is intended to be invoked once at + the initialization of this module. + + Invocation by other packages is unsupported and done + at their own risk. + """ + working_set = WorkingSet._build_master() + _declare_state('object', working_set=working_set) + + require = working_set.require + iter_entry_points = working_set.iter_entry_points + add_activation_listener = working_set.subscribe + run_script = working_set.run_script + # backward compatibility + run_main = run_script + # Activate all distributions already on sys.path with replace=False and + # ensure that all distributions added to the working set in the future + # (e.g. by calling ``require()``) will get activated as well, + # with higher priority (replace=True). + tuple( + dist.activate(replace=False) + for dist in working_set + ) + add_activation_listener( + lambda dist: dist.activate(replace=True), + existing=False, + ) + working_set.entries = [] + # match order + list(map(working_set.add_entry, sys.path)) + globals().update(locals()) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/py31compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/py31compat.py new file mode 100644 index 0000000..a2d3007 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pkg_resources/py31compat.py @@ -0,0 +1,23 @@ +import os +import errno +import sys + +from pip._vendor import six + + +def _makedirs_31(path, exist_ok=False): + try: + os.makedirs(path) + except OSError as exc: + if not exist_ok or exc.errno != errno.EEXIST: + raise + + +# rely on compatibility behavior until mode considerations +# and exists_ok considerations are disentangled. +# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 +needs_makedirs = ( + six.PY2 or + (3, 4) <= sys.version_info < (3, 4, 1) +) +makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/progress/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/progress/__init__.py new file mode 100644 index 0000000..a41f65d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/progress/__init__.py @@ -0,0 +1,127 @@ +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import division + +from collections import deque +from datetime import timedelta +from math import ceil +from sys import stderr +from time import time + + +__version__ = '1.4' + + +class Infinite(object): + file = stderr + sma_window = 10 # Simple Moving Average window + + def __init__(self, *args, **kwargs): + self.index = 0 + self.start_ts = time() + self.avg = 0 + self._ts = self.start_ts + self._xput = deque(maxlen=self.sma_window) + for key, val in kwargs.items(): + setattr(self, key, val) + + def __getitem__(self, key): + if key.startswith('_'): + return None + return getattr(self, key, None) + + @property + def elapsed(self): + return int(time() - self.start_ts) + + @property + def elapsed_td(self): + return timedelta(seconds=self.elapsed) + + def update_avg(self, n, dt): + if n > 0: + self._xput.append(dt / n) + self.avg = sum(self._xput) / len(self._xput) + + def update(self): + pass + + def start(self): + pass + + def finish(self): + pass + + def next(self, n=1): + now = time() + dt = now - self._ts + self.update_avg(n, dt) + self._ts = now + self.index = self.index + n + self.update() + + def iter(self, it): + try: + for x in it: + yield x + self.next() + finally: + self.finish() + + +class Progress(Infinite): + def __init__(self, *args, **kwargs): + super(Progress, self).__init__(*args, **kwargs) + self.max = kwargs.get('max', 100) + + @property + def eta(self): + return int(ceil(self.avg * self.remaining)) + + @property + def eta_td(self): + return timedelta(seconds=self.eta) + + @property + def percent(self): + return self.progress * 100 + + @property + def progress(self): + return min(1, self.index / self.max) + + @property + def remaining(self): + return max(self.max - self.index, 0) + + def start(self): + self.update() + + def goto(self, index): + incr = index - self.index + self.next(incr) + + def iter(self, it): + try: + self.max = len(it) + except TypeError: + pass + + try: + for x in it: + yield x + self.next() + finally: + self.finish() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/progress/bar.py b/venv/lib/python3.7/site-packages/pip/_vendor/progress/bar.py new file mode 100644 index 0000000..025e61c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/progress/bar.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import unicode_literals + +import sys + +from . import Progress +from .helpers import WritelnMixin + + +class Bar(WritelnMixin, Progress): + width = 32 + message = '' + suffix = '%(index)d/%(max)d' + bar_prefix = ' |' + bar_suffix = '| ' + empty_fill = ' ' + fill = '#' + hide_cursor = True + + def update(self): + filled_length = int(self.width * self.progress) + empty_length = self.width - filled_length + + message = self.message % self + bar = self.fill * filled_length + empty = self.empty_fill * empty_length + suffix = self.suffix % self + line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix, + suffix]) + self.writeln(line) + + +class ChargingBar(Bar): + suffix = '%(percent)d%%' + bar_prefix = ' ' + bar_suffix = ' ' + empty_fill = '∙' + fill = '█' + + +class FillingSquaresBar(ChargingBar): + empty_fill = '▢' + fill = '▣' + + +class FillingCirclesBar(ChargingBar): + empty_fill = '◯' + fill = '◉' + + +class IncrementalBar(Bar): + if sys.platform.startswith('win'): + phases = (u' ', u'▌', u'█') + else: + phases = (' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█') + + def update(self): + nphases = len(self.phases) + filled_len = self.width * self.progress + nfull = int(filled_len) # Number of full chars + phase = int((filled_len - nfull) * nphases) # Phase of last char + nempty = self.width - nfull # Number of empty chars + + message = self.message % self + bar = self.phases[-1] * nfull + current = self.phases[phase] if phase > 0 else '' + empty = self.empty_fill * max(0, nempty - len(current)) + suffix = self.suffix % self + line = ''.join([message, self.bar_prefix, bar, current, empty, + self.bar_suffix, suffix]) + self.writeln(line) + + +class PixelBar(IncrementalBar): + phases = ('⡀', '⡄', '⡆', '⡇', '⣇', '⣧', '⣷', '⣿') + + +class ShadyBar(IncrementalBar): + phases = (' ', '░', '▒', '▓', '█') diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/progress/counter.py b/venv/lib/python3.7/site-packages/pip/_vendor/progress/counter.py new file mode 100644 index 0000000..6b45a1e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/progress/counter.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import unicode_literals +from . import Infinite, Progress +from .helpers import WriteMixin + + +class Counter(WriteMixin, Infinite): + message = '' + hide_cursor = True + + def update(self): + self.write(str(self.index)) + + +class Countdown(WriteMixin, Progress): + hide_cursor = True + + def update(self): + self.write(str(self.remaining)) + + +class Stack(WriteMixin, Progress): + phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█') + hide_cursor = True + + def update(self): + nphases = len(self.phases) + i = min(nphases - 1, int(self.progress * nphases)) + self.write(self.phases[i]) + + +class Pie(Stack): + phases = ('○', '◔', '◑', '◕', '●') diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/progress/helpers.py b/venv/lib/python3.7/site-packages/pip/_vendor/progress/helpers.py new file mode 100644 index 0000000..0cde44e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/progress/helpers.py @@ -0,0 +1,91 @@ +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import print_function + + +HIDE_CURSOR = '\x1b[?25l' +SHOW_CURSOR = '\x1b[?25h' + + +class WriteMixin(object): + hide_cursor = False + + def __init__(self, message=None, **kwargs): + super(WriteMixin, self).__init__(**kwargs) + self._width = 0 + if message: + self.message = message + + if self.file and self.file.isatty(): + if self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + print(self.message, end='', file=self.file) + self.file.flush() + + def write(self, s): + if self.file and self.file.isatty(): + b = '\b' * self._width + c = s.ljust(self._width) + print(b + c, end='', file=self.file) + self._width = max(self._width, len(s)) + self.file.flush() + + def finish(self): + if self.file and self.file.isatty() and self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + +class WritelnMixin(object): + hide_cursor = False + + def __init__(self, message=None, **kwargs): + super(WritelnMixin, self).__init__(**kwargs) + if message: + self.message = message + + if self.file and self.file.isatty() and self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + + def clearln(self): + if self.file and self.file.isatty(): + print('\r\x1b[K', end='', file=self.file) + + def writeln(self, line): + if self.file and self.file.isatty(): + self.clearln() + print(line, end='', file=self.file) + self.file.flush() + + def finish(self): + if self.file and self.file.isatty(): + print(file=self.file) + if self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + +from signal import signal, SIGINT +from sys import exit + + +class SigIntMixin(object): + """Registers a signal handler that calls finish on SIGINT""" + + def __init__(self, *args, **kwargs): + super(SigIntMixin, self).__init__(*args, **kwargs) + signal(SIGINT, self._sigint_handler) + + def _sigint_handler(self, signum, frame): + self.finish() + exit(0) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/progress/spinner.py b/venv/lib/python3.7/site-packages/pip/_vendor/progress/spinner.py new file mode 100644 index 0000000..464c7b2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/progress/spinner.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import unicode_literals +from . import Infinite +from .helpers import WriteMixin + + +class Spinner(WriteMixin, Infinite): + message = '' + phases = ('-', '\\', '|', '/') + hide_cursor = True + + def update(self): + i = self.index % len(self.phases) + self.write(self.phases[i]) + + +class PieSpinner(Spinner): + phases = ['◷', '◶', '◵', '◴'] + + +class MoonSpinner(Spinner): + phases = ['◑', '◒', '◐', '◓'] + + +class LineSpinner(Spinner): + phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻'] + +class PixelSpinner(Spinner): + phases = ['⣾','⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pyparsing.py b/venv/lib/python3.7/site-packages/pip/_vendor/pyparsing.py new file mode 100644 index 0000000..865152d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pyparsing.py @@ -0,0 +1,5742 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2018 Paul T. McGuire +# +# 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. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pip._vendor.pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes + - construct character word-group expressions using the L{Word} class + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes + - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones + - associate names with your parsed results using L{ParserElement.setResultsName} + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} + - find more useful common expressions in the L{pyparsing_common} namespace class +""" + +__version__ = "2.2.1" +__versionTime__ = "18 Sep 2018 00:49 UTC" +__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + # Python 3 + from collections.abc import Iterable + from collections.abc import MutableMapping +except ImportError: + # Python 2.7 + from collections import Iterable + from collections import MutableMapping + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "</", resTag, ">" ] + + out += [ nl, indent, "</", selfTag, ">" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) + +def lineno(loc,strg): + """Returns current line number within a string, counting newlines as line separators. + The first line is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [frame_summary[:2]] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [frame_summary[:2]] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "<parse action>" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, <TAB> and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}<parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. + + See examples in L{I{copy}<copy>}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or preloc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + from pip._vendor import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}<parseWithTabs>}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}<parseString>} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of <TAB>s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{<TAB>} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): + throwException = True + + if throwException: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except Exception: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "<SPC>", + "\t": "<TAB>", + "\n": "<LF>", + "\r": "<CR>", + "\f": "<FF>", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc<len(instring): + if instring[loc] == "\n": + return loc+1, "\n" + else: + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class StringStart(_PositionToken): + """ + Matches if current position is at the beginning of the parse string + """ + def __init__( self ): + super(StringStart,self).__init__() + self.errmsg = "Expected start of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc != 0: + # see if entire string up to here is just whitespace and ignoreables + if loc != self.preParse( instring, 0 ): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class StringEnd(_PositionToken): + """ + Matches if current position is at the end of the parse string + """ + def __init__( self ): + super(StringEnd,self).__init__() + self.errmsg = "Expected end of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc < len(instring): + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + elif loc > len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + +class ParseExpression(ParserElement): + """ + Abstract subclass of ParserElement, for combining and post-processing parsed tokens. + """ + def __init__( self, exprs, savelist = False ): + super(ParseExpression,self).__init__(savelist) + if isinstance( exprs, _generatorType ): + exprs = list(exprs) + + if isinstance( exprs, basestring ): + self.exprs = [ ParserElement._literalStringClass( exprs ) ] + elif isinstance( exprs, Iterable ): + exprs = list(exprs) + # if sequence of strings provided, wrap with Literal + if all(isinstance(expr, basestring) for expr in exprs): + exprs = map(ParserElement._literalStringClass, exprs) + self.exprs = list(exprs) + else: + try: + self.exprs = list( exprs ) + except TypeError: + self.exprs = [ exprs ] + self.callPreparse = False + + def __getitem__( self, i ): + return self.exprs[i] + + def append( self, other ): + self.exprs.append( other ) + self.strRepr = None + return self + + def leaveWhitespace( self ): + """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on + all contained expressions.""" + self.skipWhitespace = False + self.exprs = [ e.copy() for e in self.exprs ] + for e in self.exprs: + e.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + else: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + return self + + def __str__( self ): + try: + return super(ParseExpression,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) + return self.strRepr + + def streamline( self ): + super(ParseExpression,self).streamline() + + for e in self.exprs: + e.streamline() + + # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) + # but only if there are no parse actions or resultsNames on the nested And's + # (likewise for Or's and MatchFirst's) + if ( len(self.exprs) == 2 ): + other = self.exprs[0] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = other.exprs[:] + [ self.exprs[1] ] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + other = self.exprs[-1] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = self.exprs[:-1] + other.exprs[:] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + self.errmsg = "Expected " + _ustr(self) + + return self + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ParseExpression,self).setResultsName(name,listAllMatches) + return ret + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + for e in self.exprs: + e.validate(tmp) + self.checkRecursion( [] ) + + def copy(self): + ret = super(ParseExpression,self).copy() + ret.exprs = [e.copy() for e in self.exprs] + return ret + +class And(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found in the given order. + Expressions may be separated by whitespace. + May be constructed using the C{'+'} operator. + May also be constructed using the C{'-'} operator, which will suppress backtracking. + + Example:: + integer = Word(nums) + name_expr = OneOrMore(Word(alphas)) + + expr = And([integer("id"),name_expr("name"),integer("age")]) + # more easily written as: + expr = integer("id") + name_expr("name") + integer("age") + """ + + class _ErrorStop(Empty): + def __init__(self, *args, **kwargs): + super(And._ErrorStop,self).__init__(*args, **kwargs) + self.name = '-' + self.leaveWhitespace() + + def __init__( self, exprs, savelist = True ): + super(And,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.setWhitespaceChars( self.exprs[0].whiteChars ) + self.skipWhitespace = self.exprs[0].skipWhitespace + self.callPreparse = True + + def parseImpl( self, instring, loc, doActions=True ): + # pass False as last arg to _parse for first element, since we already + # pre-parsed the string as part of our And pre-parsing + loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False + for e in self.exprs[1:]: + if isinstance(e, And._ErrorStop): + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseSyntaxException: + raise + except ParseBaseException as pe: + pe.__traceback__ = None + raise ParseSyntaxException._from_exception(pe) + except IndexError: + raise ParseSyntaxException(instring, len(instring), self.errmsg, self) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) + if exprtokens or exprtokens.haskeys(): + resultlist += exprtokens + return loc, resultlist + + def __iadd__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #And( [ self, other ] ) + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + if not e.mayReturnEmpty: + break + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + +class Or(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the expression that matches the longest string will be used. + May be constructed using the C{'^'} operator. + + Example:: + # construct Or using '^' operator + + number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) + prints:: + [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(Or,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + matches = [] + for e in self.exprs: + try: + loc2 = e.tryParse( instring, loc ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens)))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <<leaving remove_duplicate_chars (ret: 'dfjkls') + ['dfjkls'] + """ + f = _trim_arity(f) + def z(*paArgs): + thisFunc = f.__name__ + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) + raise + sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) + return ret + try: + z.__name__ = f.__name__ + except AttributeError: + pass + return z + +# +# global helpers +# +def delimitedList( expr, delim=",", combine=False ): + """ + Helper to define a delimited list of expressions - the delimiter defaults to ','. + By default, the list elements and delimiters can have intervening whitespace, and + comments, but this can be overridden by passing C{combine=True} in the constructor. + If C{combine} is set to C{True}, the matching tokens are returned as a single token + string, with the delimiters included; otherwise, the matching tokens are returned + as a list of tokens, with the delimiters suppressed. + + Example:: + delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test <b> bold <i>text</i> </b> normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + ['<b> bold <i>text</i> </b>'] + ['<i>text</i>'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{<TAB>} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString<ParserElement.transformString>}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("</") + tagStr + ">") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the <A> tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{<TD>} or C{<DIV>}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' + <div> + Some text + <div type="grid">1 4 0 1 0</div> + <div type="graph">1,3 2,3 1,1</div> + <div>this has no type</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' + <div> + Some text + <div class="grid">1 4 0 1 0</div> + <div class="graph">1,3 2,3 1,1</div> + <div>this <div> has no class</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") +"Comment of the form C{<!-- ... -->}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) + - common L{programming identifiers<identifier>} + - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) + - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} + - L{UUID<uuid>} + - L{comma-separated list<comma_separated_list>} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__init__.py new file mode 100644 index 0000000..8dc7315 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/__init__.py @@ -0,0 +1,3 @@ +from .core import TomlError +from .parser import load, loads +from .writer import dump, dumps diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/core.py b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/core.py new file mode 100644 index 0000000..c182734 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/core.py @@ -0,0 +1,13 @@ +class TomlError(RuntimeError): + def __init__(self, message, line, col, filename): + RuntimeError.__init__(self, message, line, col, filename) + self.message = message + self.line = line + self.col = col + self.filename = filename + + def __str__(self): + return '{}({}, {}): {}'.format(self.filename, self.line, self.col, self.message) + + def __repr__(self): + return 'TomlError({!r}, {!r}, {!r}, {!r})'.format(self.message, self.line, self.col, self.filename) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/parser.py b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/parser.py new file mode 100644 index 0000000..9f94e92 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/parser.py @@ -0,0 +1,374 @@ +import string, re, sys, datetime +from .core import TomlError + +if sys.version_info[0] == 2: + _chr = unichr +else: + _chr = chr + +def load(fin, translate=lambda t, x, v: v, object_pairs_hook=dict): + return loads(fin.read(), translate=translate, object_pairs_hook=object_pairs_hook, filename=getattr(fin, 'name', repr(fin))) + +def loads(s, filename='<string>', translate=lambda t, x, v: v, object_pairs_hook=dict): + if isinstance(s, bytes): + s = s.decode('utf-8') + + s = s.replace('\r\n', '\n') + + root = object_pairs_hook() + tables = object_pairs_hook() + scope = root + + src = _Source(s, filename=filename) + ast = _p_toml(src, object_pairs_hook=object_pairs_hook) + + def error(msg): + raise TomlError(msg, pos[0], pos[1], filename) + + def process_value(v, object_pairs_hook): + kind, text, value, pos = v + if kind == 'str' and value.startswith('\n'): + value = value[1:] + if kind == 'array': + if value and any(k != value[0][0] for k, t, v, p in value[1:]): + error('array-type-mismatch') + value = [process_value(item, object_pairs_hook=object_pairs_hook) for item in value] + elif kind == 'table': + value = object_pairs_hook([(k, process_value(value[k], object_pairs_hook=object_pairs_hook)) for k in value]) + return translate(kind, text, value) + + for kind, value, pos in ast: + if kind == 'kv': + k, v = value + if k in scope: + error('duplicate_keys. Key "{0}" was used more than once.'.format(k)) + scope[k] = process_value(v, object_pairs_hook=object_pairs_hook) + else: + is_table_array = (kind == 'table_array') + cur = tables + for name in value[:-1]: + if isinstance(cur.get(name), list): + d, cur = cur[name][-1] + else: + d, cur = cur.setdefault(name, (None, object_pairs_hook())) + + scope = object_pairs_hook() + name = value[-1] + if name not in cur: + if is_table_array: + cur[name] = [(scope, object_pairs_hook())] + else: + cur[name] = (scope, object_pairs_hook()) + elif isinstance(cur[name], list): + if not is_table_array: + error('table_type_mismatch') + cur[name].append((scope, object_pairs_hook())) + else: + if is_table_array: + error('table_type_mismatch') + old_scope, next_table = cur[name] + if old_scope is not None: + error('duplicate_tables') + cur[name] = (scope, next_table) + + def merge_tables(scope, tables): + if scope is None: + scope = object_pairs_hook() + for k in tables: + if k in scope: + error('key_table_conflict') + v = tables[k] + if isinstance(v, list): + scope[k] = [merge_tables(sc, tbl) for sc, tbl in v] + else: + scope[k] = merge_tables(v[0], v[1]) + return scope + + return merge_tables(root, tables) + +class _Source: + def __init__(self, s, filename=None): + self.s = s + self._pos = (1, 1) + self._last = None + self._filename = filename + self.backtrack_stack = [] + + def last(self): + return self._last + + def pos(self): + return self._pos + + def fail(self): + return self._expect(None) + + def consume_dot(self): + if self.s: + self._last = self.s[0] + self.s = self[1:] + self._advance(self._last) + return self._last + return None + + def expect_dot(self): + return self._expect(self.consume_dot()) + + def consume_eof(self): + if not self.s: + self._last = '' + return True + return False + + def expect_eof(self): + return self._expect(self.consume_eof()) + + def consume(self, s): + if self.s.startswith(s): + self.s = self.s[len(s):] + self._last = s + self._advance(s) + return True + return False + + def expect(self, s): + return self._expect(self.consume(s)) + + def consume_re(self, re): + m = re.match(self.s) + if m: + self.s = self.s[len(m.group(0)):] + self._last = m + self._advance(m.group(0)) + return m + return None + + def expect_re(self, re): + return self._expect(self.consume_re(re)) + + def __enter__(self): + self.backtrack_stack.append((self.s, self._pos)) + + def __exit__(self, type, value, traceback): + if type is None: + self.backtrack_stack.pop() + else: + self.s, self._pos = self.backtrack_stack.pop() + return type == TomlError + + def commit(self): + self.backtrack_stack[-1] = (self.s, self._pos) + + def _expect(self, r): + if not r: + raise TomlError('msg', self._pos[0], self._pos[1], self._filename) + return r + + def _advance(self, s): + suffix_pos = s.rfind('\n') + if suffix_pos == -1: + self._pos = (self._pos[0], self._pos[1] + len(s)) + else: + self._pos = (self._pos[0] + s.count('\n'), len(s) - suffix_pos) + +_ews_re = re.compile(r'(?:[ \t]|#[^\n]*\n|#[^\n]*\Z|\n)*') +def _p_ews(s): + s.expect_re(_ews_re) + +_ws_re = re.compile(r'[ \t]*') +def _p_ws(s): + s.expect_re(_ws_re) + +_escapes = { 'b': '\b', 'n': '\n', 'r': '\r', 't': '\t', '"': '"', '\'': '\'', + '\\': '\\', '/': '/', 'f': '\f' } + +_basicstr_re = re.compile(r'[^"\\\000-\037]*') +_short_uni_re = re.compile(r'u([0-9a-fA-F]{4})') +_long_uni_re = re.compile(r'U([0-9a-fA-F]{8})') +_escapes_re = re.compile('[bnrt"\'\\\\/f]') +_newline_esc_re = re.compile('\n[ \t\n]*') +def _p_basicstr_content(s, content=_basicstr_re): + res = [] + while True: + res.append(s.expect_re(content).group(0)) + if not s.consume('\\'): + break + if s.consume_re(_newline_esc_re): + pass + elif s.consume_re(_short_uni_re) or s.consume_re(_long_uni_re): + res.append(_chr(int(s.last().group(1), 16))) + else: + s.expect_re(_escapes_re) + res.append(_escapes[s.last().group(0)]) + return ''.join(res) + +_key_re = re.compile(r'[0-9a-zA-Z-_]+') +def _p_key(s): + with s: + s.expect('"') + r = _p_basicstr_content(s, _basicstr_re) + s.expect('"') + return r + if s.consume('\''): + if s.consume('\'\''): + r = s.expect_re(_litstr_ml_re).group(0) + s.expect('\'\'\'') + else: + r = s.expect_re(_litstr_re).group(0) + s.expect('\'') + return r + return s.expect_re(_key_re).group(0) + +_float_re = re.compile(r'[+-]?(?:0|[1-9](?:_?\d)*)(?:\.\d(?:_?\d)*)?(?:[eE][+-]?(?:\d(?:_?\d)*))?') +_datetime_re = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))') + +_basicstr_ml_re = re.compile(r'(?:(?:|"|"")[^"\\\000-\011\013-\037])*') +_litstr_re = re.compile(r"[^'\000\010\012-\037]*") +_litstr_ml_re = re.compile(r"(?:(?:|'|'')(?:[^'\000-\010\013-\037]))*") +def _p_value(s, object_pairs_hook): + pos = s.pos() + + if s.consume('true'): + return 'bool', s.last(), True, pos + if s.consume('false'): + return 'bool', s.last(), False, pos + + if s.consume('"'): + if s.consume('""'): + r = _p_basicstr_content(s, _basicstr_ml_re) + s.expect('"""') + else: + r = _p_basicstr_content(s, _basicstr_re) + s.expect('"') + return 'str', r, r, pos + + if s.consume('\''): + if s.consume('\'\''): + r = s.expect_re(_litstr_ml_re).group(0) + s.expect('\'\'\'') + else: + r = s.expect_re(_litstr_re).group(0) + s.expect('\'') + return 'str', r, r, pos + + if s.consume_re(_datetime_re): + m = s.last() + s0 = m.group(0) + r = map(int, m.groups()[:6]) + if m.group(7): + micro = float(m.group(7)) + else: + micro = 0 + + if m.group(8): + g = int(m.group(8), 10) * 60 + int(m.group(9), 10) + tz = _TimeZone(datetime.timedelta(0, g * 60)) + else: + tz = _TimeZone(datetime.timedelta(0, 0)) + + y, m, d, H, M, S = r + dt = datetime.datetime(y, m, d, H, M, S, int(micro * 1000000), tz) + return 'datetime', s0, dt, pos + + if s.consume_re(_float_re): + m = s.last().group(0) + r = m.replace('_','') + if '.' in m or 'e' in m or 'E' in m: + return 'float', m, float(r), pos + else: + return 'int', m, int(r, 10), pos + + if s.consume('['): + items = [] + with s: + while True: + _p_ews(s) + items.append(_p_value(s, object_pairs_hook=object_pairs_hook)) + s.commit() + _p_ews(s) + s.expect(',') + s.commit() + _p_ews(s) + s.expect(']') + return 'array', None, items, pos + + if s.consume('{'): + _p_ws(s) + items = object_pairs_hook() + if not s.consume('}'): + k = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + items[k] = _p_value(s, object_pairs_hook=object_pairs_hook) + _p_ws(s) + while s.consume(','): + _p_ws(s) + k = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + items[k] = _p_value(s, object_pairs_hook=object_pairs_hook) + _p_ws(s) + s.expect('}') + return 'table', None, items, pos + + s.fail() + +def _p_stmt(s, object_pairs_hook): + pos = s.pos() + if s.consume( '['): + is_array = s.consume('[') + _p_ws(s) + keys = [_p_key(s)] + _p_ws(s) + while s.consume('.'): + _p_ws(s) + keys.append(_p_key(s)) + _p_ws(s) + s.expect(']') + if is_array: + s.expect(']') + return 'table_array' if is_array else 'table', keys, pos + + key = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + value = _p_value(s, object_pairs_hook=object_pairs_hook) + return 'kv', (key, value), pos + +_stmtsep_re = re.compile(r'(?:[ \t]*(?:#[^\n]*)?\n)+[ \t]*') +def _p_toml(s, object_pairs_hook): + stmts = [] + _p_ews(s) + with s: + stmts.append(_p_stmt(s, object_pairs_hook=object_pairs_hook)) + while True: + s.commit() + s.expect_re(_stmtsep_re) + stmts.append(_p_stmt(s, object_pairs_hook=object_pairs_hook)) + _p_ews(s) + s.expect_eof() + return stmts + +class _TimeZone(datetime.tzinfo): + def __init__(self, offset): + self._offset = offset + + def utcoffset(self, dt): + return self._offset + + def dst(self, dt): + return None + + def tzname(self, dt): + m = self._offset.total_seconds() // 60 + if m < 0: + res = '-' + m = -m + else: + res = '+' + h = m // 60 + m = m - h * 60 + return '{}{:.02}{:.02}'.format(res, h, m) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/writer.py b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/writer.py new file mode 100644 index 0000000..6eaf5d7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/pytoml/writer.py @@ -0,0 +1,127 @@ +from __future__ import unicode_literals +import io, datetime, math, sys + +if sys.version_info[0] == 3: + long = int + unicode = str + + +def dumps(obj, sort_keys=False): + fout = io.StringIO() + dump(obj, fout, sort_keys=sort_keys) + return fout.getvalue() + + +_escapes = {'\n': 'n', '\r': 'r', '\\': '\\', '\t': 't', '\b': 'b', '\f': 'f', '"': '"'} + + +def _escape_string(s): + res = [] + start = 0 + + def flush(): + if start != i: + res.append(s[start:i]) + return i + 1 + + i = 0 + while i < len(s): + c = s[i] + if c in '"\\\n\r\t\b\f': + start = flush() + res.append('\\' + _escapes[c]) + elif ord(c) < 0x20: + start = flush() + res.append('\\u%04x' % ord(c)) + i += 1 + + flush() + return '"' + ''.join(res) + '"' + + +def _escape_id(s): + if any(not c.isalnum() and c not in '-_' for c in s): + return _escape_string(s) + return s + + +def _format_list(v): + return '[{0}]'.format(', '.join(_format_value(obj) for obj in v)) + +# Formula from: +# https://docs.python.org/2/library/datetime.html#datetime.timedelta.total_seconds +# Once support for py26 is dropped, this can be replaced by td.total_seconds() +def _total_seconds(td): + return ((td.microseconds + + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.0**6) + +def _format_value(v): + if isinstance(v, bool): + return 'true' if v else 'false' + if isinstance(v, int) or isinstance(v, long): + return unicode(v) + if isinstance(v, float): + if math.isnan(v) or math.isinf(v): + raise ValueError("{0} is not a valid TOML value".format(v)) + else: + return repr(v) + elif isinstance(v, unicode) or isinstance(v, bytes): + return _escape_string(v) + elif isinstance(v, datetime.datetime): + offs = v.utcoffset() + offs = _total_seconds(offs) // 60 if offs is not None else 0 + + if offs == 0: + suffix = 'Z' + else: + if offs > 0: + suffix = '+' + else: + suffix = '-' + offs = -offs + suffix = '{0}{1:.02}{2:.02}'.format(suffix, offs // 60, offs % 60) + + if v.microsecond: + return v.strftime('%Y-%m-%dT%H:%M:%S.%f') + suffix + else: + return v.strftime('%Y-%m-%dT%H:%M:%S') + suffix + elif isinstance(v, list): + return _format_list(v) + else: + raise RuntimeError(v) + + +def dump(obj, fout, sort_keys=False): + tables = [((), obj, False)] + + while tables: + name, table, is_array = tables.pop() + if name: + section_name = '.'.join(_escape_id(c) for c in name) + if is_array: + fout.write('[[{0}]]\n'.format(section_name)) + else: + fout.write('[{0}]\n'.format(section_name)) + + table_keys = sorted(table.keys()) if sort_keys else table.keys() + new_tables = [] + has_kv = False + for k in table_keys: + v = table[k] + if isinstance(v, dict): + new_tables.append((name + (k,), v, False)) + elif isinstance(v, list) and v and all(isinstance(o, dict) for o in v): + new_tables.extend((name + (k,), d, True) for d in v) + elif v is None: + # based on mojombo's comment: https://github.com/toml-lang/toml/issues/146#issuecomment-25019344 + fout.write( + '#{} = null # To use: uncomment and replace null with value\n'.format(_escape_id(k))) + has_kv = True + else: + fout.write('{0} = {1}\n'.format(_escape_id(k), _format_value(v))) + has_kv = True + + tables.extend(reversed(new_tables)) + + if (name or has_kv) and tables: + fout.write('\n') diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/__init__.py new file mode 100644 index 0000000..3f3f4f2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/__init__.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- + +# __ +# /__) _ _ _ _ _/ _ +# / ( (- (/ (/ (- _) / _) +# / + +""" +Requests HTTP Library +~~~~~~~~~~~~~~~~~~~~~ + +Requests is an HTTP library, written in Python, for human beings. Basic GET +usage: + + >>> import requests + >>> r = requests.get('https://www.python.org') + >>> r.status_code + 200 + >>> 'Python is a programming language' in r.content + True + +... or POST: + + >>> payload = dict(key1='value1', key2='value2') + >>> r = requests.post('http://httpbin.org/post', data=payload) + >>> print(r.text) + { + ... + "form": { + "key2": "value2", + "key1": "value1" + }, + ... + } + +The other HTTP methods are supported - see `requests.api`. Full documentation +is at <http://python-requests.org>. + +:copyright: (c) 2017 by Kenneth Reitz. +:license: Apache 2.0, see LICENSE for more details. +""" + +from pip._vendor import urllib3 +from pip._vendor import chardet +import warnings +from .exceptions import RequestsDependencyWarning + + +def check_compatibility(urllib3_version, chardet_version): + urllib3_version = urllib3_version.split('.') + assert urllib3_version != ['dev'] # Verify urllib3 isn't installed from git. + + # Sometimes, urllib3 only reports its version as 16.1. + if len(urllib3_version) == 2: + urllib3_version.append('0') + + # Check urllib3 for compatibility. + major, minor, patch = urllib3_version # noqa: F811 + major, minor, patch = int(major), int(minor), int(patch) + # urllib3 >= 1.21.1, <= 1.23 + assert major == 1 + assert minor >= 21 + assert minor <= 23 + + # Check chardet for compatibility. + major, minor, patch = chardet_version.split('.')[:3] + major, minor, patch = int(major), int(minor), int(patch) + # chardet >= 3.0.2, < 3.1.0 + assert major == 3 + assert minor < 1 + assert patch >= 2 + + +def _check_cryptography(cryptography_version): + # cryptography < 1.3.4 + try: + cryptography_version = list(map(int, cryptography_version.split('.'))) + except ValueError: + return + + if cryptography_version < [1, 3, 4]: + warning = 'Old version of cryptography ({0}) may cause slowdown.'.format(cryptography_version) + warnings.warn(warning, RequestsDependencyWarning) + +# Check imported dependencies for compatibility. +try: + check_compatibility(urllib3.__version__, chardet.__version__) +except (AssertionError, ValueError): + warnings.warn("urllib3 ({0}) or chardet ({1}) doesn't match a supported " + "version!".format(urllib3.__version__, chardet.__version__), + RequestsDependencyWarning) + +# Attempt to enable urllib3's SNI support, if possible +from pip._internal.utils.compat import WINDOWS +if not WINDOWS: + try: + from pip._vendor.urllib3.contrib import pyopenssl + pyopenssl.inject_into_urllib3() + + # Check cryptography version + from cryptography import __version__ as cryptography_version + _check_cryptography(cryptography_version) + except ImportError: + pass + +# urllib3's DependencyWarnings should be silenced. +from pip._vendor.urllib3.exceptions import DependencyWarning +warnings.simplefilter('ignore', DependencyWarning) + +from .__version__ import __title__, __description__, __url__, __version__ +from .__version__ import __build__, __author__, __author_email__, __license__ +from .__version__ import __copyright__, __cake__ + +from . import utils +from . import packages +from .models import Request, Response, PreparedRequest +from .api import request, get, head, post, patch, put, delete, options +from .sessions import session, Session +from .status_codes import codes +from .exceptions import ( + RequestException, Timeout, URLRequired, + TooManyRedirects, HTTPError, ConnectionError, + FileModeWarning, ConnectTimeout, ReadTimeout +) + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +logging.getLogger(__name__).addHandler(NullHandler()) + +# FileModeWarnings go off per the default. +warnings.simplefilter('default', FileModeWarning, append=True) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/__version__.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/__version__.py new file mode 100644 index 0000000..ef61ec0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/__version__.py @@ -0,0 +1,14 @@ +# .-. .-. .-. . . .-. .-. .-. .-. +# |( |- |.| | | |- `-. | `-. +# ' ' `-' `-`.`-' `-' `-' ' `-' + +__title__ = 'requests' +__description__ = 'Python HTTP for Humans.' +__url__ = 'http://python-requests.org' +__version__ = '2.19.1' +__build__ = 0x021901 +__author__ = 'Kenneth Reitz' +__author_email__ = 'me@kennethreitz.org' +__license__ = 'Apache 2.0' +__copyright__ = 'Copyright 2018 Kenneth Reitz' +__cake__ = u'\u2728 \U0001f370 \u2728' diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/_internal_utils.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/_internal_utils.py new file mode 100644 index 0000000..759d9a5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/_internal_utils.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +""" +requests._internal_utils +~~~~~~~~~~~~~~ + +Provides utility functions that are consumed internally by Requests +which depend on extremely few external helpers (such as compat) +""" + +from .compat import is_py2, builtin_str, str + + +def to_native_string(string, encoding='ascii'): + """Given a string object, regardless of type, returns a representation of + that string in the native string type, encoding and decoding where + necessary. This assumes ASCII unless told otherwise. + """ + if isinstance(string, builtin_str): + out = string + else: + if is_py2: + out = string.encode(encoding) + else: + out = string.decode(encoding) + + return out + + +def unicode_is_ascii(u_string): + """Determine if unicode string only contains ASCII characters. + + :param str u_string: unicode string to check. Must be unicode + and not Python 2 `str`. + :rtype: bool + """ + assert isinstance(u_string, str) + try: + u_string.encode('ascii') + return True + except UnicodeEncodeError: + return False diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/adapters.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/adapters.py new file mode 100644 index 0000000..f6f3f99 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/adapters.py @@ -0,0 +1,530 @@ +# -*- coding: utf-8 -*- + +""" +requests.adapters +~~~~~~~~~~~~~~~~~ + +This module contains the transport adapters that Requests uses to define +and maintain connections. +""" + +import os.path +import socket + +from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url +from pip._vendor.urllib3.response import HTTPResponse +from pip._vendor.urllib3.util import parse_url +from pip._vendor.urllib3.util import Timeout as TimeoutSauce +from pip._vendor.urllib3.util.retry import Retry +from pip._vendor.urllib3.exceptions import ClosedPoolError +from pip._vendor.urllib3.exceptions import ConnectTimeoutError +from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError +from pip._vendor.urllib3.exceptions import MaxRetryError +from pip._vendor.urllib3.exceptions import NewConnectionError +from pip._vendor.urllib3.exceptions import ProxyError as _ProxyError +from pip._vendor.urllib3.exceptions import ProtocolError +from pip._vendor.urllib3.exceptions import ReadTimeoutError +from pip._vendor.urllib3.exceptions import SSLError as _SSLError +from pip._vendor.urllib3.exceptions import ResponseError + +from .models import Response +from .compat import urlparse, basestring +from .utils import (DEFAULT_CA_BUNDLE_PATH, extract_zipped_paths, + get_encoding_from_headers, prepend_scheme_if_needed, + get_auth_from_url, urldefragauth, select_proxy) +from .structures import CaseInsensitiveDict +from .cookies import extract_cookies_to_jar +from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError, + ProxyError, RetryError, InvalidSchema, InvalidProxyURL) +from .auth import _basic_auth_str + +try: + from pip._vendor.urllib3.contrib.socks import SOCKSProxyManager +except ImportError: + def SOCKSProxyManager(*args, **kwargs): + raise InvalidSchema("Missing dependencies for SOCKS support.") + +DEFAULT_POOLBLOCK = False +DEFAULT_POOLSIZE = 10 +DEFAULT_RETRIES = 0 +DEFAULT_POOL_TIMEOUT = None + + +class BaseAdapter(object): + """The Base Transport Adapter""" + + def __init__(self): + super(BaseAdapter, self).__init__() + + def send(self, request, stream=False, timeout=None, verify=True, + cert=None, proxies=None): + """Sends PreparedRequest object. Returns Response object. + + :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. + :param stream: (optional) Whether to stream the request content. + :param timeout: (optional) How long to wait for the server to send + data before giving up, as a float, or a :ref:`(connect timeout, + read timeout) <timeouts>` tuple. + :type timeout: float or tuple + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use + :param cert: (optional) Any user-provided SSL certificate to be trusted. + :param proxies: (optional) The proxies dictionary to apply to the request. + """ + raise NotImplementedError + + def close(self): + """Cleans up adapter specific items.""" + raise NotImplementedError + + +class HTTPAdapter(BaseAdapter): + """The built-in HTTP Adapter for urllib3. + + Provides a general-case interface for Requests sessions to contact HTTP and + HTTPS urls by implementing the Transport Adapter interface. This class will + usually be created by the :class:`Session <Session>` class under the + covers. + + :param pool_connections: The number of urllib3 connection pools to cache. + :param pool_maxsize: The maximum number of connections to save in the pool. + :param max_retries: The maximum number of retries each connection + should attempt. Note, this applies only to failed DNS lookups, socket + connections and connection timeouts, never to requests where data has + made it to the server. By default, Requests does not retry failed + connections. If you need granular control over the conditions under + which we retry a request, import urllib3's ``Retry`` class and pass + that instead. + :param pool_block: Whether the connection pool should block for connections. + + Usage:: + + >>> import requests + >>> s = requests.Session() + >>> a = requests.adapters.HTTPAdapter(max_retries=3) + >>> s.mount('http://', a) + """ + __attrs__ = ['max_retries', 'config', '_pool_connections', '_pool_maxsize', + '_pool_block'] + + def __init__(self, pool_connections=DEFAULT_POOLSIZE, + pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_RETRIES, + pool_block=DEFAULT_POOLBLOCK): + if max_retries == DEFAULT_RETRIES: + self.max_retries = Retry(0, read=False) + else: + self.max_retries = Retry.from_int(max_retries) + self.config = {} + self.proxy_manager = {} + + super(HTTPAdapter, self).__init__() + + self._pool_connections = pool_connections + self._pool_maxsize = pool_maxsize + self._pool_block = pool_block + + self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) + + def __getstate__(self): + return dict((attr, getattr(self, attr, None)) for attr in + self.__attrs__) + + def __setstate__(self, state): + # Can't handle by adding 'proxy_manager' to self.__attrs__ because + # self.poolmanager uses a lambda function, which isn't pickleable. + self.proxy_manager = {} + self.config = {} + + for attr, value in state.items(): + setattr(self, attr, value) + + self.init_poolmanager(self._pool_connections, self._pool_maxsize, + block=self._pool_block) + + def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs): + """Initializes a urllib3 PoolManager. + + This method should not be called from user code, and is only + exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param connections: The number of urllib3 connection pools to cache. + :param maxsize: The maximum number of connections to save in the pool. + :param block: Block when no free connections are available. + :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager. + """ + # save these values for pickling + self._pool_connections = connections + self._pool_maxsize = maxsize + self._pool_block = block + + self.poolmanager = PoolManager(num_pools=connections, maxsize=maxsize, + block=block, strict=True, **pool_kwargs) + + def proxy_manager_for(self, proxy, **proxy_kwargs): + """Return urllib3 ProxyManager for the given proxy. + + This method should not be called from user code, and is only + exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param proxy: The proxy to return a urllib3 ProxyManager for. + :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager. + :returns: ProxyManager + :rtype: urllib3.ProxyManager + """ + if proxy in self.proxy_manager: + manager = self.proxy_manager[proxy] + elif proxy.lower().startswith('socks'): + username, password = get_auth_from_url(proxy) + manager = self.proxy_manager[proxy] = SOCKSProxyManager( + proxy, + username=username, + password=password, + num_pools=self._pool_connections, + maxsize=self._pool_maxsize, + block=self._pool_block, + **proxy_kwargs + ) + else: + proxy_headers = self.proxy_headers(proxy) + manager = self.proxy_manager[proxy] = proxy_from_url( + proxy, + proxy_headers=proxy_headers, + num_pools=self._pool_connections, + maxsize=self._pool_maxsize, + block=self._pool_block, + **proxy_kwargs) + + return manager + + def cert_verify(self, conn, url, verify, cert): + """Verify a SSL certificate. This method should not be called from user + code, and is only exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param conn: The urllib3 connection object associated with the cert. + :param url: The requested URL. + :param verify: Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use + :param cert: The SSL certificate to verify. + """ + if url.lower().startswith('https') and verify: + + cert_loc = None + + # Allow self-specified cert location. + if verify is not True: + cert_loc = verify + + if not cert_loc: + cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) + + if not cert_loc or not os.path.exists(cert_loc): + raise IOError("Could not find a suitable TLS CA certificate bundle, " + "invalid path: {0}".format(cert_loc)) + + conn.cert_reqs = 'CERT_REQUIRED' + + if not os.path.isdir(cert_loc): + conn.ca_certs = cert_loc + else: + conn.ca_cert_dir = cert_loc + else: + conn.cert_reqs = 'CERT_NONE' + conn.ca_certs = None + conn.ca_cert_dir = None + + if cert: + if not isinstance(cert, basestring): + conn.cert_file = cert[0] + conn.key_file = cert[1] + else: + conn.cert_file = cert + conn.key_file = None + if conn.cert_file and not os.path.exists(conn.cert_file): + raise IOError("Could not find the TLS certificate file, " + "invalid path: {0}".format(conn.cert_file)) + if conn.key_file and not os.path.exists(conn.key_file): + raise IOError("Could not find the TLS key file, " + "invalid path: {0}".format(conn.key_file)) + + def build_response(self, req, resp): + """Builds a :class:`Response <requests.Response>` object from a urllib3 + response. This should not be called from user code, and is only exposed + for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>` + + :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response. + :param resp: The urllib3 response object. + :rtype: requests.Response + """ + response = Response() + + # Fallback to None if there's no status_code, for whatever reason. + response.status_code = getattr(resp, 'status', None) + + # Make headers case-insensitive. + response.headers = CaseInsensitiveDict(getattr(resp, 'headers', {})) + + # Set encoding. + response.encoding = get_encoding_from_headers(response.headers) + response.raw = resp + response.reason = response.raw.reason + + if isinstance(req.url, bytes): + response.url = req.url.decode('utf-8') + else: + response.url = req.url + + # Add new cookies from the server. + extract_cookies_to_jar(response.cookies, req, resp) + + # Give the Response some context. + response.request = req + response.connection = self + + return response + + def get_connection(self, url, proxies=None): + """Returns a urllib3 connection for the given URL. This should not be + called from user code, and is only exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param url: The URL to connect to. + :param proxies: (optional) A Requests-style dictionary of proxies used on this request. + :rtype: urllib3.ConnectionPool + """ + proxy = select_proxy(url, proxies) + + if proxy: + proxy = prepend_scheme_if_needed(proxy, 'http') + proxy_url = parse_url(proxy) + if not proxy_url.host: + raise InvalidProxyURL("Please check proxy URL. It is malformed" + " and could be missing the host.") + proxy_manager = self.proxy_manager_for(proxy) + conn = proxy_manager.connection_from_url(url) + else: + # Only scheme should be lower case + parsed = urlparse(url) + url = parsed.geturl() + conn = self.poolmanager.connection_from_url(url) + + return conn + + def close(self): + """Disposes of any internal state. + + Currently, this closes the PoolManager and any active ProxyManager, + which closes any pooled connections. + """ + self.poolmanager.clear() + for proxy in self.proxy_manager.values(): + proxy.clear() + + def request_url(self, request, proxies): + """Obtain the url to use when making the final request. + + If the message is being sent through a HTTP proxy, the full URL has to + be used. Otherwise, we should only use the path portion of the URL. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. + :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs. + :rtype: str + """ + proxy = select_proxy(request.url, proxies) + scheme = urlparse(request.url).scheme + + is_proxied_http_request = (proxy and scheme != 'https') + using_socks_proxy = False + if proxy: + proxy_scheme = urlparse(proxy).scheme.lower() + using_socks_proxy = proxy_scheme.startswith('socks') + + url = request.path_url + if is_proxied_http_request and not using_socks_proxy: + url = urldefragauth(request.url) + + return url + + def add_headers(self, request, **kwargs): + """Add any headers needed by the connection. As of v2.0 this does + nothing by default, but is left for overriding by users that subclass + the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to. + :param kwargs: The keyword arguments from the call to send(). + """ + pass + + def proxy_headers(self, proxy): + """Returns a dictionary of the headers to add to any request sent + through a proxy. This works with urllib3 magic to ensure that they are + correctly sent to the proxy, rather than in a tunnelled request if + CONNECT is being used. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param proxies: The url of the proxy being used for this request. + :rtype: dict + """ + headers = {} + username, password = get_auth_from_url(proxy) + + if username: + headers['Proxy-Authorization'] = _basic_auth_str(username, + password) + + return headers + + def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): + """Sends PreparedRequest object. Returns Response object. + + :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. + :param stream: (optional) Whether to stream the request content. + :param timeout: (optional) How long to wait for the server to send + data before giving up, as a float, or a :ref:`(connect timeout, + read timeout) <timeouts>` tuple. + :type timeout: float or tuple or urllib3 Timeout object + :param verify: (optional) Either a boolean, in which case it controls whether + we verify the server's TLS certificate, or a string, in which case it + must be a path to a CA bundle to use + :param cert: (optional) Any user-provided SSL certificate to be trusted. + :param proxies: (optional) The proxies dictionary to apply to the request. + :rtype: requests.Response + """ + + conn = self.get_connection(request.url, proxies) + + self.cert_verify(conn, request.url, verify, cert) + url = self.request_url(request, proxies) + self.add_headers(request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies) + + chunked = not (request.body is None or 'Content-Length' in request.headers) + + if isinstance(timeout, tuple): + try: + connect, read = timeout + timeout = TimeoutSauce(connect=connect, read=read) + except ValueError as e: + # this may raise a string formatting error. + err = ("Invalid timeout {0}. Pass a (connect, read) " + "timeout tuple, or a single float to set " + "both timeouts to the same value".format(timeout)) + raise ValueError(err) + elif isinstance(timeout, TimeoutSauce): + pass + else: + timeout = TimeoutSauce(connect=timeout, read=timeout) + + try: + if not chunked: + resp = conn.urlopen( + method=request.method, + url=url, + body=request.body, + headers=request.headers, + redirect=False, + assert_same_host=False, + preload_content=False, + decode_content=False, + retries=self.max_retries, + timeout=timeout + ) + + # Send the request. + else: + if hasattr(conn, 'proxy_pool'): + conn = conn.proxy_pool + + low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT) + + try: + low_conn.putrequest(request.method, + url, + skip_accept_encoding=True) + + for header, value in request.headers.items(): + low_conn.putheader(header, value) + + low_conn.endheaders() + + for i in request.body: + low_conn.send(hex(len(i))[2:].encode('utf-8')) + low_conn.send(b'\r\n') + low_conn.send(i) + low_conn.send(b'\r\n') + low_conn.send(b'0\r\n\r\n') + + # Receive the response from the server + try: + # For Python 2.7+ versions, use buffering of HTTP + # responses + r = low_conn.getresponse(buffering=True) + except TypeError: + # For compatibility with Python 2.6 versions and back + r = low_conn.getresponse() + + resp = HTTPResponse.from_httplib( + r, + pool=conn, + connection=low_conn, + preload_content=False, + decode_content=False + ) + except: + # If we hit any problems here, clean up the connection. + # Then, reraise so that we can handle the actual exception. + low_conn.close() + raise + + except (ProtocolError, socket.error) as err: + raise ConnectionError(err, request=request) + + except MaxRetryError as e: + if isinstance(e.reason, ConnectTimeoutError): + # TODO: Remove this in 3.0.0: see #2811 + if not isinstance(e.reason, NewConnectionError): + raise ConnectTimeout(e, request=request) + + if isinstance(e.reason, ResponseError): + raise RetryError(e, request=request) + + if isinstance(e.reason, _ProxyError): + raise ProxyError(e, request=request) + + if isinstance(e.reason, _SSLError): + # This branch is for urllib3 v1.22 and later. + raise SSLError(e, request=request) + + raise ConnectionError(e, request=request) + + except ClosedPoolError as e: + raise ConnectionError(e, request=request) + + except _ProxyError as e: + raise ProxyError(e) + + except (_SSLError, _HTTPError) as e: + if isinstance(e, _SSLError): + # This branch is for urllib3 versions earlier than v1.22 + raise SSLError(e, request=request) + elif isinstance(e, ReadTimeoutError): + raise ReadTimeout(e, request=request) + else: + raise + + return self.build_response(request, resp) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/api.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/api.py new file mode 100644 index 0000000..a2cc84d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/api.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- + +""" +requests.api +~~~~~~~~~~~~ + +This module implements the Requests API. + +:copyright: (c) 2012 by Kenneth Reitz. +:license: Apache2, see LICENSE for more details. +""" + +from . import sessions + + +def request(method, url, **kwargs): + """Constructs and sends a :class:`Request <Request>`. + + :param method: method for the new :class:`Request` object. + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. + :param data: (optional) Dictionary or list of tuples ``[(key, value)]`` (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. + :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. + :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. + ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` + or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string + defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers + to add for the file. + :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. + :param timeout: (optional) How many seconds to wait for the server to send data + before giving up, as a float, or a :ref:`(connect timeout, read + timeout) <timeouts>` tuple. + :type timeout: float or tuple + :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``. + :type allow_redirects: bool + :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use. Defaults to ``True``. + :param stream: (optional) if ``False``, the response content will be immediately downloaded. + :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. + :return: :class:`Response <Response>` object + :rtype: requests.Response + + Usage:: + + >>> import requests + >>> req = requests.request('GET', 'http://httpbin.org/get') + <Response [200]> + """ + + # By using the 'with' statement we are sure the session is closed, thus we + # avoid leaving sockets open which can trigger a ResourceWarning in some + # cases, and look like a memory leak in others. + with sessions.Session() as session: + return session.request(method=method, url=url, **kwargs) + + +def get(url, params=None, **kwargs): + r"""Sends a GET request. + + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return request('get', url, params=params, **kwargs) + + +def options(url, **kwargs): + r"""Sends an OPTIONS request. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return request('options', url, **kwargs) + + +def head(url, **kwargs): + r"""Sends a HEAD request. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', False) + return request('head', url, **kwargs) + + +def post(url, data=None, json=None, **kwargs): + r"""Sends a POST request. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('post', url, data=data, json=json, **kwargs) + + +def put(url, data=None, **kwargs): + r"""Sends a PUT request. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('put', url, data=data, **kwargs) + + +def patch(url, data=None, **kwargs): + r"""Sends a PATCH request. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('patch', url, data=data, **kwargs) + + +def delete(url, **kwargs): + r"""Sends a DELETE request. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('delete', url, **kwargs) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/auth.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/auth.py new file mode 100644 index 0000000..4ae4594 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/auth.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- + +""" +requests.auth +~~~~~~~~~~~~~ + +This module contains the authentication handlers for Requests. +""" + +import os +import re +import time +import hashlib +import threading +import warnings + +from base64 import b64encode + +from .compat import urlparse, str, basestring +from .cookies import extract_cookies_to_jar +from ._internal_utils import to_native_string +from .utils import parse_dict_header + +CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' +CONTENT_TYPE_MULTI_PART = 'multipart/form-data' + + +def _basic_auth_str(username, password): + """Returns a Basic Auth string.""" + + # "I want us to put a big-ol' comment on top of it that + # says that this behaviour is dumb but we need to preserve + # it because people are relying on it." + # - Lukasa + # + # These are here solely to maintain backwards compatibility + # for things like ints. This will be removed in 3.0.0. + if not isinstance(username, basestring): + warnings.warn( + "Non-string usernames will no longer be supported in Requests " + "3.0.0. Please convert the object you've passed in ({0!r}) to " + "a string or bytes object in the near future to avoid " + "problems.".format(username), + category=DeprecationWarning, + ) + username = str(username) + + if not isinstance(password, basestring): + warnings.warn( + "Non-string passwords will no longer be supported in Requests " + "3.0.0. Please convert the object you've passed in ({0!r}) to " + "a string or bytes object in the near future to avoid " + "problems.".format(password), + category=DeprecationWarning, + ) + password = str(password) + # -- End Removal -- + + if isinstance(username, str): + username = username.encode('latin1') + + if isinstance(password, str): + password = password.encode('latin1') + + authstr = 'Basic ' + to_native_string( + b64encode(b':'.join((username, password))).strip() + ) + + return authstr + + +class AuthBase(object): + """Base class that all auth implementations derive from""" + + def __call__(self, r): + raise NotImplementedError('Auth hooks must be callable.') + + +class HTTPBasicAuth(AuthBase): + """Attaches HTTP Basic Authentication to the given Request object.""" + + def __init__(self, username, password): + self.username = username + self.password = password + + def __eq__(self, other): + return all([ + self.username == getattr(other, 'username', None), + self.password == getattr(other, 'password', None) + ]) + + def __ne__(self, other): + return not self == other + + def __call__(self, r): + r.headers['Authorization'] = _basic_auth_str(self.username, self.password) + return r + + +class HTTPProxyAuth(HTTPBasicAuth): + """Attaches HTTP Proxy Authentication to a given Request object.""" + + def __call__(self, r): + r.headers['Proxy-Authorization'] = _basic_auth_str(self.username, self.password) + return r + + +class HTTPDigestAuth(AuthBase): + """Attaches HTTP Digest Authentication to the given Request object.""" + + def __init__(self, username, password): + self.username = username + self.password = password + # Keep state in per-thread local storage + self._thread_local = threading.local() + + def init_per_thread_state(self): + # Ensure state is initialized just once per-thread + if not hasattr(self._thread_local, 'init'): + self._thread_local.init = True + self._thread_local.last_nonce = '' + self._thread_local.nonce_count = 0 + self._thread_local.chal = {} + self._thread_local.pos = None + self._thread_local.num_401_calls = None + + def build_digest_header(self, method, url): + """ + :rtype: str + """ + + realm = self._thread_local.chal['realm'] + nonce = self._thread_local.chal['nonce'] + qop = self._thread_local.chal.get('qop') + algorithm = self._thread_local.chal.get('algorithm') + opaque = self._thread_local.chal.get('opaque') + hash_utf8 = None + + if algorithm is None: + _algorithm = 'MD5' + else: + _algorithm = algorithm.upper() + # lambdas assume digest modules are imported at the top level + if _algorithm == 'MD5' or _algorithm == 'MD5-SESS': + def md5_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.md5(x).hexdigest() + hash_utf8 = md5_utf8 + elif _algorithm == 'SHA': + def sha_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha1(x).hexdigest() + hash_utf8 = sha_utf8 + elif _algorithm == 'SHA-256': + def sha256_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha256(x).hexdigest() + hash_utf8 = sha256_utf8 + elif _algorithm == 'SHA-512': + def sha512_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha512(x).hexdigest() + hash_utf8 = sha512_utf8 + + KD = lambda s, d: hash_utf8("%s:%s" % (s, d)) + + if hash_utf8 is None: + return None + + # XXX not implemented yet + entdig = None + p_parsed = urlparse(url) + #: path is request-uri defined in RFC 2616 which should not be empty + path = p_parsed.path or "/" + if p_parsed.query: + path += '?' + p_parsed.query + + A1 = '%s:%s:%s' % (self.username, realm, self.password) + A2 = '%s:%s' % (method, path) + + HA1 = hash_utf8(A1) + HA2 = hash_utf8(A2) + + if nonce == self._thread_local.last_nonce: + self._thread_local.nonce_count += 1 + else: + self._thread_local.nonce_count = 1 + ncvalue = '%08x' % self._thread_local.nonce_count + s = str(self._thread_local.nonce_count).encode('utf-8') + s += nonce.encode('utf-8') + s += time.ctime().encode('utf-8') + s += os.urandom(8) + + cnonce = (hashlib.sha1(s).hexdigest()[:16]) + if _algorithm == 'MD5-SESS': + HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce)) + + if not qop: + respdig = KD(HA1, "%s:%s" % (nonce, HA2)) + elif qop == 'auth' or 'auth' in qop.split(','): + noncebit = "%s:%s:%s:%s:%s" % ( + nonce, ncvalue, cnonce, 'auth', HA2 + ) + respdig = KD(HA1, noncebit) + else: + # XXX handle auth-int. + return None + + self._thread_local.last_nonce = nonce + + # XXX should the partial digests be encoded too? + base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \ + 'response="%s"' % (self.username, realm, nonce, path, respdig) + if opaque: + base += ', opaque="%s"' % opaque + if algorithm: + base += ', algorithm="%s"' % algorithm + if entdig: + base += ', digest="%s"' % entdig + if qop: + base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce) + + return 'Digest %s' % (base) + + def handle_redirect(self, r, **kwargs): + """Reset num_401_calls counter on redirects.""" + if r.is_redirect: + self._thread_local.num_401_calls = 1 + + def handle_401(self, r, **kwargs): + """ + Takes the given response and tries digest-auth, if needed. + + :rtype: requests.Response + """ + + # If response is not 4xx, do not auth + # See https://github.com/requests/requests/issues/3772 + if not 400 <= r.status_code < 500: + self._thread_local.num_401_calls = 1 + return r + + if self._thread_local.pos is not None: + # Rewind the file position indicator of the body to where + # it was to resend the request. + r.request.body.seek(self._thread_local.pos) + s_auth = r.headers.get('www-authenticate', '') + + if 'digest' in s_auth.lower() and self._thread_local.num_401_calls < 2: + + self._thread_local.num_401_calls += 1 + pat = re.compile(r'digest ', flags=re.IGNORECASE) + self._thread_local.chal = parse_dict_header(pat.sub('', s_auth, count=1)) + + # Consume content and release the original connection + # to allow our new request to reuse the same one. + r.content + r.close() + prep = r.request.copy() + extract_cookies_to_jar(prep._cookies, r.request, r.raw) + prep.prepare_cookies(prep._cookies) + + prep.headers['Authorization'] = self.build_digest_header( + prep.method, prep.url) + _r = r.connection.send(prep, **kwargs) + _r.history.append(r) + _r.request = prep + + return _r + + self._thread_local.num_401_calls = 1 + return r + + def __call__(self, r): + # Initialize per-thread state, if needed + self.init_per_thread_state() + # If we have a saved nonce, skip the 401 + if self._thread_local.last_nonce: + r.headers['Authorization'] = self.build_digest_header(r.method, r.url) + try: + self._thread_local.pos = r.body.tell() + except AttributeError: + # In the case of HTTPDigestAuth being reused and the body of + # the previous request was a file-like object, pos has the + # file position of the previous body. Ensure it's set to + # None. + self._thread_local.pos = None + r.register_hook('response', self.handle_401) + r.register_hook('response', self.handle_redirect) + self._thread_local.num_401_calls = 1 + + return r + + def __eq__(self, other): + return all([ + self.username == getattr(other, 'username', None), + self.password == getattr(other, 'password', None) + ]) + + def __ne__(self, other): + return not self == other diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/certs.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/certs.py new file mode 100644 index 0000000..06a594e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/certs.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +requests.certs +~~~~~~~~~~~~~~ + +This module returns the preferred default CA certificate bundle. There is +only one — the one from the certifi package. + +If you are packaging Requests, e.g., for a Linux distribution or a managed +environment, you can change the definition of where() to return a separately +packaged CA bundle. +""" +from pip._vendor.certifi import where + +if __name__ == '__main__': + print(where()) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/compat.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/compat.py new file mode 100644 index 0000000..ec5d305 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/compat.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- + +""" +requests.compat +~~~~~~~~~~~~~~~ + +This module handles import compatibility issues between Python 2 and +Python 3. +""" + +from pip._vendor import chardet + +import sys + +# ------- +# Pythons +# ------- + +# Syntax sugar. +_ver = sys.version_info + +#: Python 2.x? +is_py2 = (_ver[0] == 2) + +#: Python 3.x? +is_py3 = (_ver[0] == 3) + +# Note: We've patched out simplejson support in pip because it prevents +# upgrading simplejson on Windows. +# try: +# import simplejson as json +# except (ImportError, SyntaxError): +# # simplejson does not support Python 3.2, it throws a SyntaxError +# # because of u'...' Unicode literals. +import json + +# --------- +# Specifics +# --------- + +if is_py2: + from urllib import ( + quote, unquote, quote_plus, unquote_plus, urlencode, getproxies, + proxy_bypass, proxy_bypass_environment, getproxies_environment) + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urldefrag + from urllib2 import parse_http_list + import cookielib + from Cookie import Morsel + from StringIO import StringIO + from collections import Callable, Mapping, MutableMapping + + from pip._vendor.urllib3.packages.ordered_dict import OrderedDict + + builtin_str = str + bytes = str + str = unicode + basestring = basestring + numeric_types = (int, long, float) + integer_types = (int, long) + +elif is_py3: + from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag + from urllib.request import parse_http_list, getproxies, proxy_bypass, proxy_bypass_environment, getproxies_environment + from http import cookiejar as cookielib + from http.cookies import Morsel + from io import StringIO + from collections import OrderedDict + from collections.abc import Callable, Mapping, MutableMapping + + builtin_str = str + str = str + bytes = bytes + basestring = (str, bytes) + numeric_types = (int, float) + integer_types = (int,) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/cookies.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/cookies.py new file mode 100644 index 0000000..50883a8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/cookies.py @@ -0,0 +1,546 @@ +# -*- coding: utf-8 -*- + +""" +requests.cookies +~~~~~~~~~~~~~~~~ + +Compatibility code to be able to use `cookielib.CookieJar` with requests. + +requests.utils imports from here, so be careful with imports. +""" + +import copy +import time +import calendar + +from ._internal_utils import to_native_string +from .compat import cookielib, urlparse, urlunparse, Morsel, MutableMapping + +try: + import threading +except ImportError: + import dummy_threading as threading + + +class MockRequest(object): + """Wraps a `requests.Request` to mimic a `urllib2.Request`. + + The code in `cookielib.CookieJar` expects this interface in order to correctly + manage cookie policies, i.e., determine whether a cookie can be set, given the + domains of the request and the cookie. + + The original request object is read-only. The client is responsible for collecting + the new headers via `get_new_headers()` and interpreting them appropriately. You + probably want `get_cookie_header`, defined below. + """ + + def __init__(self, request): + self._r = request + self._new_headers = {} + self.type = urlparse(self._r.url).scheme + + def get_type(self): + return self.type + + def get_host(self): + return urlparse(self._r.url).netloc + + def get_origin_req_host(self): + return self.get_host() + + def get_full_url(self): + # Only return the response's URL if the user hadn't set the Host + # header + if not self._r.headers.get('Host'): + return self._r.url + # If they did set it, retrieve it and reconstruct the expected domain + host = to_native_string(self._r.headers['Host'], encoding='utf-8') + parsed = urlparse(self._r.url) + # Reconstruct the URL as we expect it + return urlunparse([ + parsed.scheme, host, parsed.path, parsed.params, parsed.query, + parsed.fragment + ]) + + def is_unverifiable(self): + return True + + def has_header(self, name): + return name in self._r.headers or name in self._new_headers + + def get_header(self, name, default=None): + return self._r.headers.get(name, self._new_headers.get(name, default)) + + def add_header(self, key, val): + """cookielib has no legitimate use for this method; add it back if you find one.""" + raise NotImplementedError("Cookie headers should be added with add_unredirected_header()") + + def add_unredirected_header(self, name, value): + self._new_headers[name] = value + + def get_new_headers(self): + return self._new_headers + + @property + def unverifiable(self): + return self.is_unverifiable() + + @property + def origin_req_host(self): + return self.get_origin_req_host() + + @property + def host(self): + return self.get_host() + + +class MockResponse(object): + """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. + + ...what? Basically, expose the parsed HTTP headers from the server response + the way `cookielib` expects to see them. + """ + + def __init__(self, headers): + """Make a MockResponse for `cookielib` to read. + + :param headers: a httplib.HTTPMessage or analogous carrying the headers + """ + self._headers = headers + + def info(self): + return self._headers + + def getheaders(self, name): + self._headers.getheaders(name) + + +def extract_cookies_to_jar(jar, request, response): + """Extract the cookies from the response into a CookieJar. + + :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) + :param request: our own requests.Request object + :param response: urllib3.HTTPResponse object + """ + if not (hasattr(response, '_original_response') and + response._original_response): + return + # the _original_response field is the wrapped httplib.HTTPResponse object, + req = MockRequest(request) + # pull out the HTTPMessage with the headers and put it in the mock: + res = MockResponse(response._original_response.msg) + jar.extract_cookies(res, req) + + +def get_cookie_header(jar, request): + """ + Produce an appropriate Cookie header string to be sent with `request`, or None. + + :rtype: str + """ + r = MockRequest(request) + jar.add_cookie_header(r) + return r.get_new_headers().get('Cookie') + + +def remove_cookie_by_name(cookiejar, name, domain=None, path=None): + """Unsets a cookie by name, by default over all domains and paths. + + Wraps CookieJar.clear(), is O(n). + """ + clearables = [] + for cookie in cookiejar: + if cookie.name != name: + continue + if domain is not None and domain != cookie.domain: + continue + if path is not None and path != cookie.path: + continue + clearables.append((cookie.domain, cookie.path, cookie.name)) + + for domain, path, name in clearables: + cookiejar.clear(domain, path, name) + + +class CookieConflictError(RuntimeError): + """There are two cookies that meet the criteria specified in the cookie jar. + Use .get and .set and include domain and path args in order to be more specific. + """ + + +class RequestsCookieJar(cookielib.CookieJar, MutableMapping): + """Compatibility class; is a cookielib.CookieJar, but exposes a dict + interface. + + This is the CookieJar we create by default for requests and sessions that + don't specify one, since some clients may expect response.cookies and + session.cookies to support dict operations. + + Requests does not use the dict interface internally; it's just for + compatibility with external client code. All requests code should work + out of the box with externally provided instances of ``CookieJar``, e.g. + ``LWPCookieJar`` and ``FileCookieJar``. + + Unlike a regular CookieJar, this class is pickleable. + + .. warning:: dictionary operations that are normally O(1) may be O(n). + """ + + def get(self, name, default=None, domain=None, path=None): + """Dict-like get() that also supports optional domain and path args in + order to resolve naming collisions from using one cookie jar over + multiple domains. + + .. warning:: operation is O(n), not O(1). + """ + try: + return self._find_no_duplicates(name, domain, path) + except KeyError: + return default + + def set(self, name, value, **kwargs): + """Dict-like set() that also supports optional domain and path args in + order to resolve naming collisions from using one cookie jar over + multiple domains. + """ + # support client code that unsets cookies by assignment of a None value: + if value is None: + remove_cookie_by_name(self, name, domain=kwargs.get('domain'), path=kwargs.get('path')) + return + + if isinstance(value, Morsel): + c = morsel_to_cookie(value) + else: + c = create_cookie(name, value, **kwargs) + self.set_cookie(c) + return c + + def iterkeys(self): + """Dict-like iterkeys() that returns an iterator of names of cookies + from the jar. + + .. seealso:: itervalues() and iteritems(). + """ + for cookie in iter(self): + yield cookie.name + + def keys(self): + """Dict-like keys() that returns a list of names of cookies from the + jar. + + .. seealso:: values() and items(). + """ + return list(self.iterkeys()) + + def itervalues(self): + """Dict-like itervalues() that returns an iterator of values of cookies + from the jar. + + .. seealso:: iterkeys() and iteritems(). + """ + for cookie in iter(self): + yield cookie.value + + def values(self): + """Dict-like values() that returns a list of values of cookies from the + jar. + + .. seealso:: keys() and items(). + """ + return list(self.itervalues()) + + def iteritems(self): + """Dict-like iteritems() that returns an iterator of name-value tuples + from the jar. + + .. seealso:: iterkeys() and itervalues(). + """ + for cookie in iter(self): + yield cookie.name, cookie.value + + def items(self): + """Dict-like items() that returns a list of name-value tuples from the + jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a + vanilla python dict of key value pairs. + + .. seealso:: keys() and values(). + """ + return list(self.iteritems()) + + def list_domains(self): + """Utility method to list all the domains in the jar.""" + domains = [] + for cookie in iter(self): + if cookie.domain not in domains: + domains.append(cookie.domain) + return domains + + def list_paths(self): + """Utility method to list all the paths in the jar.""" + paths = [] + for cookie in iter(self): + if cookie.path not in paths: + paths.append(cookie.path) + return paths + + def multiple_domains(self): + """Returns True if there are multiple domains in the jar. + Returns False otherwise. + + :rtype: bool + """ + domains = [] + for cookie in iter(self): + if cookie.domain is not None and cookie.domain in domains: + return True + domains.append(cookie.domain) + return False # there is only one domain in jar + + def get_dict(self, domain=None, path=None): + """Takes as an argument an optional domain and path and returns a plain + old Python dict of name-value pairs of cookies that meet the + requirements. + + :rtype: dict + """ + dictionary = {} + for cookie in iter(self): + if ( + (domain is None or cookie.domain == domain) and + (path is None or cookie.path == path) + ): + dictionary[cookie.name] = cookie.value + return dictionary + + def __contains__(self, name): + try: + return super(RequestsCookieJar, self).__contains__(name) + except CookieConflictError: + return True + + def __getitem__(self, name): + """Dict-like __getitem__() for compatibility with client code. Throws + exception if there are more than one cookie with name. In that case, + use the more explicit get() method instead. + + .. warning:: operation is O(n), not O(1). + """ + return self._find_no_duplicates(name) + + def __setitem__(self, name, value): + """Dict-like __setitem__ for compatibility with client code. Throws + exception if there is already a cookie of that name in the jar. In that + case, use the more explicit set() method instead. + """ + self.set(name, value) + + def __delitem__(self, name): + """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s + ``remove_cookie_by_name()``. + """ + remove_cookie_by_name(self, name) + + def set_cookie(self, cookie, *args, **kwargs): + if hasattr(cookie.value, 'startswith') and cookie.value.startswith('"') and cookie.value.endswith('"'): + cookie.value = cookie.value.replace('\\"', '') + return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs) + + def update(self, other): + """Updates this jar with cookies from another CookieJar or dict-like""" + if isinstance(other, cookielib.CookieJar): + for cookie in other: + self.set_cookie(copy.copy(cookie)) + else: + super(RequestsCookieJar, self).update(other) + + def _find(self, name, domain=None, path=None): + """Requests uses this method internally to get cookie values. + + If there are conflicting cookies, _find arbitrarily chooses one. + See _find_no_duplicates if you want an exception thrown if there are + conflicting cookies. + + :param name: a string containing name of cookie + :param domain: (optional) string containing domain of cookie + :param path: (optional) string containing path of cookie + :return: cookie.value + """ + for cookie in iter(self): + if cookie.name == name: + if domain is None or cookie.domain == domain: + if path is None or cookie.path == path: + return cookie.value + + raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) + + def _find_no_duplicates(self, name, domain=None, path=None): + """Both ``__get_item__`` and ``get`` call this function: it's never + used elsewhere in Requests. + + :param name: a string containing name of cookie + :param domain: (optional) string containing domain of cookie + :param path: (optional) string containing path of cookie + :raises KeyError: if cookie is not found + :raises CookieConflictError: if there are multiple cookies + that match name and optionally domain and path + :return: cookie.value + """ + toReturn = None + for cookie in iter(self): + if cookie.name == name: + if domain is None or cookie.domain == domain: + if path is None or cookie.path == path: + if toReturn is not None: # if there are multiple cookies that meet passed in criteria + raise CookieConflictError('There are multiple cookies with name, %r' % (name)) + toReturn = cookie.value # we will eventually return this as long as no cookie conflict + + if toReturn: + return toReturn + raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) + + def __getstate__(self): + """Unlike a normal CookieJar, this class is pickleable.""" + state = self.__dict__.copy() + # remove the unpickleable RLock object + state.pop('_cookies_lock') + return state + + def __setstate__(self, state): + """Unlike a normal CookieJar, this class is pickleable.""" + self.__dict__.update(state) + if '_cookies_lock' not in self.__dict__: + self._cookies_lock = threading.RLock() + + def copy(self): + """Return a copy of this RequestsCookieJar.""" + new_cj = RequestsCookieJar() + new_cj.set_policy(self.get_policy()) + new_cj.update(self) + return new_cj + + def get_policy(self): + """Return the CookiePolicy instance used.""" + return self._policy + + +def _copy_cookie_jar(jar): + if jar is None: + return None + + if hasattr(jar, 'copy'): + # We're dealing with an instance of RequestsCookieJar + return jar.copy() + # We're dealing with a generic CookieJar instance + new_jar = copy.copy(jar) + new_jar.clear() + for cookie in jar: + new_jar.set_cookie(copy.copy(cookie)) + return new_jar + + +def create_cookie(name, value, **kwargs): + """Make a cookie from underspecified parameters. + + By default, the pair of `name` and `value` will be set for the domain '' + and sent on every request (this is sometimes called a "supercookie"). + """ + result = dict( + version=0, + name=name, + value=value, + port=None, + domain='', + path='/', + secure=False, + expires=None, + discard=True, + comment=None, + comment_url=None, + rest={'HttpOnly': None}, + rfc2109=False,) + + badargs = set(kwargs) - set(result) + if badargs: + err = 'create_cookie() got unexpected keyword arguments: %s' + raise TypeError(err % list(badargs)) + + result.update(kwargs) + result['port_specified'] = bool(result['port']) + result['domain_specified'] = bool(result['domain']) + result['domain_initial_dot'] = result['domain'].startswith('.') + result['path_specified'] = bool(result['path']) + + return cookielib.Cookie(**result) + + +def morsel_to_cookie(morsel): + """Convert a Morsel object into a Cookie containing the one k/v pair.""" + + expires = None + if morsel['max-age']: + try: + expires = int(time.time() + int(morsel['max-age'])) + except ValueError: + raise TypeError('max-age: %s must be integer' % morsel['max-age']) + elif morsel['expires']: + time_template = '%a, %d-%b-%Y %H:%M:%S GMT' + expires = calendar.timegm( + time.strptime(morsel['expires'], time_template) + ) + return create_cookie( + comment=morsel['comment'], + comment_url=bool(morsel['comment']), + discard=False, + domain=morsel['domain'], + expires=expires, + name=morsel.key, + path=morsel['path'], + port=None, + rest={'HttpOnly': morsel['httponly']}, + rfc2109=False, + secure=bool(morsel['secure']), + value=morsel.value, + version=morsel['version'] or 0, + ) + + +def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): + """Returns a CookieJar from a key/value dictionary. + + :param cookie_dict: Dict of key/values to insert into CookieJar. + :param cookiejar: (optional) A cookiejar to add the cookies to. + :param overwrite: (optional) If False, will not replace cookies + already in the jar with new ones. + """ + if cookiejar is None: + cookiejar = RequestsCookieJar() + + if cookie_dict is not None: + names_from_jar = [cookie.name for cookie in cookiejar] + for name in cookie_dict: + if overwrite or (name not in names_from_jar): + cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) + + return cookiejar + + +def merge_cookies(cookiejar, cookies): + """Add cookies to cookiejar and returns a merged CookieJar. + + :param cookiejar: CookieJar object to add the cookies to. + :param cookies: Dictionary or CookieJar object to be added. + """ + if not isinstance(cookiejar, cookielib.CookieJar): + raise ValueError('You can only merge into CookieJar') + + if isinstance(cookies, dict): + cookiejar = cookiejar_from_dict( + cookies, cookiejar=cookiejar, overwrite=False) + elif isinstance(cookies, cookielib.CookieJar): + try: + cookiejar.update(cookies) + except AttributeError: + for cookie_in_jar in cookies: + cookiejar.set_cookie(cookie_in_jar) + + return cookiejar diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/exceptions.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/exceptions.py new file mode 100644 index 0000000..a91e1fd --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/exceptions.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- + +""" +requests.exceptions +~~~~~~~~~~~~~~~~~~~ + +This module contains the set of Requests' exceptions. +""" +from pip._vendor.urllib3.exceptions import HTTPError as BaseHTTPError + + +class RequestException(IOError): + """There was an ambiguous exception that occurred while handling your + request. + """ + + def __init__(self, *args, **kwargs): + """Initialize RequestException with `request` and `response` objects.""" + response = kwargs.pop('response', None) + self.response = response + self.request = kwargs.pop('request', None) + if (response is not None and not self.request and + hasattr(response, 'request')): + self.request = self.response.request + super(RequestException, self).__init__(*args, **kwargs) + + +class HTTPError(RequestException): + """An HTTP error occurred.""" + + +class ConnectionError(RequestException): + """A Connection error occurred.""" + + +class ProxyError(ConnectionError): + """A proxy error occurred.""" + + +class SSLError(ConnectionError): + """An SSL error occurred.""" + + +class Timeout(RequestException): + """The request timed out. + + Catching this error will catch both + :exc:`~requests.exceptions.ConnectTimeout` and + :exc:`~requests.exceptions.ReadTimeout` errors. + """ + + +class ConnectTimeout(ConnectionError, Timeout): + """The request timed out while trying to connect to the remote server. + + Requests that produced this error are safe to retry. + """ + + +class ReadTimeout(Timeout): + """The server did not send any data in the allotted amount of time.""" + + +class URLRequired(RequestException): + """A valid URL is required to make a request.""" + + +class TooManyRedirects(RequestException): + """Too many redirects.""" + + +class MissingSchema(RequestException, ValueError): + """The URL schema (e.g. http or https) is missing.""" + + +class InvalidSchema(RequestException, ValueError): + """See defaults.py for valid schemas.""" + + +class InvalidURL(RequestException, ValueError): + """The URL provided was somehow invalid.""" + + +class InvalidHeader(RequestException, ValueError): + """The header value provided was somehow invalid.""" + + +class InvalidProxyURL(InvalidURL): + """The proxy URL provided is invalid.""" + + +class ChunkedEncodingError(RequestException): + """The server declared chunked encoding but sent an invalid chunk.""" + + +class ContentDecodingError(RequestException, BaseHTTPError): + """Failed to decode response content""" + + +class StreamConsumedError(RequestException, TypeError): + """The content for this response was already consumed""" + + +class RetryError(RequestException): + """Custom retries logic failed""" + + +class UnrewindableBodyError(RequestException): + """Requests encountered an error when trying to rewind a body""" + +# Warnings + + +class RequestsWarning(Warning): + """Base warning for Requests.""" + pass + + +class FileModeWarning(RequestsWarning, DeprecationWarning): + """A file was opened in text mode, but Requests determined its binary length.""" + pass + + +class RequestsDependencyWarning(RequestsWarning): + """An imported dependency doesn't match the expected version range.""" + pass diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/help.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/help.py new file mode 100644 index 0000000..df1b4eb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/help.py @@ -0,0 +1,120 @@ +"""Module containing bug report helper(s).""" +from __future__ import print_function + +import json +import platform +import sys +import ssl + +from pip._vendor import idna +from pip._vendor import urllib3 +from pip._vendor import chardet + +from . import __version__ as requests_version + +try: + from pip._vendor.urllib3.contrib import pyopenssl +except ImportError: + pyopenssl = None + OpenSSL = None + cryptography = None +else: + import OpenSSL + import cryptography + + +def _implementation(): + """Return a dict with the Python implementation and version. + + Provide both the name and the version of the Python implementation + currently running. For example, on CPython 2.7.5 it will return + {'name': 'CPython', 'version': '2.7.5'}. + + This function works best on CPython and PyPy: in particular, it probably + doesn't work for Jython or IronPython. Future investigation should be done + to work out the correct shape of the code for those platforms. + """ + implementation = platform.python_implementation() + + if implementation == 'CPython': + implementation_version = platform.python_version() + elif implementation == 'PyPy': + implementation_version = '%s.%s.%s' % (sys.pypy_version_info.major, + sys.pypy_version_info.minor, + sys.pypy_version_info.micro) + if sys.pypy_version_info.releaselevel != 'final': + implementation_version = ''.join([ + implementation_version, sys.pypy_version_info.releaselevel + ]) + elif implementation == 'Jython': + implementation_version = platform.python_version() # Complete Guess + elif implementation == 'IronPython': + implementation_version = platform.python_version() # Complete Guess + else: + implementation_version = 'Unknown' + + return {'name': implementation, 'version': implementation_version} + + +def info(): + """Generate information for a bug report.""" + try: + platform_info = { + 'system': platform.system(), + 'release': platform.release(), + } + except IOError: + platform_info = { + 'system': 'Unknown', + 'release': 'Unknown', + } + + implementation_info = _implementation() + urllib3_info = {'version': urllib3.__version__} + chardet_info = {'version': chardet.__version__} + + pyopenssl_info = { + 'version': None, + 'openssl_version': '', + } + if OpenSSL: + pyopenssl_info = { + 'version': OpenSSL.__version__, + 'openssl_version': '%x' % OpenSSL.SSL.OPENSSL_VERSION_NUMBER, + } + cryptography_info = { + 'version': getattr(cryptography, '__version__', ''), + } + idna_info = { + 'version': getattr(idna, '__version__', ''), + } + + # OPENSSL_VERSION_NUMBER doesn't exist in the Python 2.6 ssl module. + system_ssl = getattr(ssl, 'OPENSSL_VERSION_NUMBER', None) + system_ssl_info = { + 'version': '%x' % system_ssl if system_ssl is not None else '' + } + + return { + 'platform': platform_info, + 'implementation': implementation_info, + 'system_ssl': system_ssl_info, + 'using_pyopenssl': pyopenssl is not None, + 'pyOpenSSL': pyopenssl_info, + 'urllib3': urllib3_info, + 'chardet': chardet_info, + 'cryptography': cryptography_info, + 'idna': idna_info, + 'requests': { + 'version': requests_version, + }, + } + + +def main(): + """Pretty-print the bug information as JSON.""" + print(json.dumps(info(), sort_keys=True, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/hooks.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/hooks.py new file mode 100644 index 0000000..32b32de --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/hooks.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +""" +requests.hooks +~~~~~~~~~~~~~~ + +This module provides the capabilities for the Requests hooks system. + +Available hooks: + +``response``: + The response generated from a Request. +""" +HOOKS = ['response'] + + +def default_hooks(): + return dict((event, []) for event in HOOKS) + +# TODO: response is the only one + + +def dispatch_hook(key, hooks, hook_data, **kwargs): + """Dispatches a hook dictionary on a given piece of data.""" + hooks = hooks or dict() + hooks = hooks.get(key) + if hooks: + if hasattr(hooks, '__call__'): + hooks = [hooks] + for hook in hooks: + _hook_data = hook(hook_data, **kwargs) + if _hook_data is not None: + hook_data = _hook_data + return hook_data diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/models.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/models.py new file mode 100644 index 0000000..4230535 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/models.py @@ -0,0 +1,952 @@ +# -*- coding: utf-8 -*- + +""" +requests.models +~~~~~~~~~~~~~~~ + +This module contains the primary objects that power Requests. +""" + +import datetime +import sys + +# Import encoding now, to avoid implicit import later. +# Implicit import within threads may cause LookupError when standard library is in a ZIP, +# such as in Embedded Python. See https://github.com/requests/requests/issues/3578. +import encodings.idna + +from pip._vendor.urllib3.fields import RequestField +from pip._vendor.urllib3.filepost import encode_multipart_formdata +from pip._vendor.urllib3.util import parse_url +from pip._vendor.urllib3.exceptions import ( + DecodeError, ReadTimeoutError, ProtocolError, LocationParseError) + +from io import UnsupportedOperation +from .hooks import default_hooks +from .structures import CaseInsensitiveDict + +from .auth import HTTPBasicAuth +from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar +from .exceptions import ( + HTTPError, MissingSchema, InvalidURL, ChunkedEncodingError, + ContentDecodingError, ConnectionError, StreamConsumedError) +from ._internal_utils import to_native_string, unicode_is_ascii +from .utils import ( + guess_filename, get_auth_from_url, requote_uri, + stream_decode_response_unicode, to_key_val_list, parse_header_links, + iter_slices, guess_json_utf, super_len, check_header_validity) +from .compat import ( + Callable, Mapping, + cookielib, urlunparse, urlsplit, urlencode, str, bytes, + is_py2, chardet, builtin_str, basestring) +from .compat import json as complexjson +from .status_codes import codes + +#: The set of HTTP status codes that indicate an automatically +#: processable redirect. +REDIRECT_STATI = ( + codes.moved, # 301 + codes.found, # 302 + codes.other, # 303 + codes.temporary_redirect, # 307 + codes.permanent_redirect, # 308 +) + +DEFAULT_REDIRECT_LIMIT = 30 +CONTENT_CHUNK_SIZE = 10 * 1024 +ITER_CHUNK_SIZE = 512 + + +class RequestEncodingMixin(object): + @property + def path_url(self): + """Build the path URL to use.""" + + url = [] + + p = urlsplit(self.url) + + path = p.path + if not path: + path = '/' + + url.append(path) + + query = p.query + if query: + url.append('?') + url.append(query) + + return ''.join(url) + + @staticmethod + def _encode_params(data): + """Encode parameters in a piece of data. + + Will successfully encode parameters when passed as a dict or a list of + 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary + if parameters are supplied as a dict. + """ + + if isinstance(data, (str, bytes)): + return data + elif hasattr(data, 'read'): + return data + elif hasattr(data, '__iter__'): + result = [] + for k, vs in to_key_val_list(data): + if isinstance(vs, basestring) or not hasattr(vs, '__iter__'): + vs = [vs] + for v in vs: + if v is not None: + result.append( + (k.encode('utf-8') if isinstance(k, str) else k, + v.encode('utf-8') if isinstance(v, str) else v)) + return urlencode(result, doseq=True) + else: + return data + + @staticmethod + def _encode_files(files, data): + """Build the body for a multipart/form-data request. + + Will successfully encode files when passed as a dict or a list of + tuples. Order is retained if data is a list of tuples but arbitrary + if parameters are supplied as a dict. + The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) + or 4-tuples (filename, fileobj, contentype, custom_headers). + """ + if (not files): + raise ValueError("Files must be provided.") + elif isinstance(data, basestring): + raise ValueError("Data must not be a string.") + + new_fields = [] + fields = to_key_val_list(data or {}) + files = to_key_val_list(files or {}) + + for field, val in fields: + if isinstance(val, basestring) or not hasattr(val, '__iter__'): + val = [val] + for v in val: + if v is not None: + # Don't call str() on bytestrings: in Py3 it all goes wrong. + if not isinstance(v, bytes): + v = str(v) + + new_fields.append( + (field.decode('utf-8') if isinstance(field, bytes) else field, + v.encode('utf-8') if isinstance(v, str) else v)) + + for (k, v) in files: + # support for explicit filename + ft = None + fh = None + if isinstance(v, (tuple, list)): + if len(v) == 2: + fn, fp = v + elif len(v) == 3: + fn, fp, ft = v + else: + fn, fp, ft, fh = v + else: + fn = guess_filename(v) or k + fp = v + + if isinstance(fp, (str, bytes, bytearray)): + fdata = fp + elif hasattr(fp, 'read'): + fdata = fp.read() + elif fp is None: + continue + else: + fdata = fp + + rf = RequestField(name=k, data=fdata, filename=fn, headers=fh) + rf.make_multipart(content_type=ft) + new_fields.append(rf) + + body, content_type = encode_multipart_formdata(new_fields) + + return body, content_type + + +class RequestHooksMixin(object): + def register_hook(self, event, hook): + """Properly register a hook.""" + + if event not in self.hooks: + raise ValueError('Unsupported event specified, with event name "%s"' % (event)) + + if isinstance(hook, Callable): + self.hooks[event].append(hook) + elif hasattr(hook, '__iter__'): + self.hooks[event].extend(h for h in hook if isinstance(h, Callable)) + + def deregister_hook(self, event, hook): + """Deregister a previously registered hook. + Returns True if the hook existed, False if not. + """ + + try: + self.hooks[event].remove(hook) + return True + except ValueError: + return False + + +class Request(RequestHooksMixin): + """A user-created :class:`Request <Request>` object. + + Used to prepare a :class:`PreparedRequest <PreparedRequest>`, which is sent to the server. + + :param method: HTTP method to use. + :param url: URL to send. + :param headers: dictionary of headers to send. + :param files: dictionary of {filename: fileobject} files to multipart upload. + :param data: the body to attach to the request. If a dictionary is provided, form-encoding will take place. + :param json: json for the body to attach to the request (if files or data is not specified). + :param params: dictionary of URL parameters to append to the URL. + :param auth: Auth handler or (user, pass) tuple. + :param cookies: dictionary or CookieJar of cookies to attach to this request. + :param hooks: dictionary of callback hooks, for internal usage. + + Usage:: + + >>> import requests + >>> req = requests.Request('GET', 'http://httpbin.org/get') + >>> req.prepare() + <PreparedRequest [GET]> + """ + + def __init__(self, + method=None, url=None, headers=None, files=None, data=None, + params=None, auth=None, cookies=None, hooks=None, json=None): + + # Default empty dicts for dict params. + data = [] if data is None else data + files = [] if files is None else files + headers = {} if headers is None else headers + params = {} if params is None else params + hooks = {} if hooks is None else hooks + + self.hooks = default_hooks() + for (k, v) in list(hooks.items()): + self.register_hook(event=k, hook=v) + + self.method = method + self.url = url + self.headers = headers + self.files = files + self.data = data + self.json = json + self.params = params + self.auth = auth + self.cookies = cookies + + def __repr__(self): + return '<Request [%s]>' % (self.method) + + def prepare(self): + """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it.""" + p = PreparedRequest() + p.prepare( + method=self.method, + url=self.url, + headers=self.headers, + files=self.files, + data=self.data, + json=self.json, + params=self.params, + auth=self.auth, + cookies=self.cookies, + hooks=self.hooks, + ) + return p + + +class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): + """The fully mutable :class:`PreparedRequest <PreparedRequest>` object, + containing the exact bytes that will be sent to the server. + + Generated from either a :class:`Request <Request>` object or manually. + + Usage:: + + >>> import requests + >>> req = requests.Request('GET', 'http://httpbin.org/get') + >>> r = req.prepare() + <PreparedRequest [GET]> + + >>> s = requests.Session() + >>> s.send(r) + <Response [200]> + """ + + def __init__(self): + #: HTTP verb to send to the server. + self.method = None + #: HTTP URL to send the request to. + self.url = None + #: dictionary of HTTP headers. + self.headers = None + # The `CookieJar` used to create the Cookie header will be stored here + # after prepare_cookies is called + self._cookies = None + #: request body to send to the server. + self.body = None + #: dictionary of callback hooks, for internal usage. + self.hooks = default_hooks() + #: integer denoting starting position of a readable file-like body. + self._body_position = None + + def prepare(self, + method=None, url=None, headers=None, files=None, data=None, + params=None, auth=None, cookies=None, hooks=None, json=None): + """Prepares the entire request with the given parameters.""" + + self.prepare_method(method) + self.prepare_url(url, params) + self.prepare_headers(headers) + self.prepare_cookies(cookies) + self.prepare_body(data, files, json) + self.prepare_auth(auth, url) + + # Note that prepare_auth must be last to enable authentication schemes + # such as OAuth to work on a fully prepared request. + + # This MUST go after prepare_auth. Authenticators could add a hook + self.prepare_hooks(hooks) + + def __repr__(self): + return '<PreparedRequest [%s]>' % (self.method) + + def copy(self): + p = PreparedRequest() + p.method = self.method + p.url = self.url + p.headers = self.headers.copy() if self.headers is not None else None + p._cookies = _copy_cookie_jar(self._cookies) + p.body = self.body + p.hooks = self.hooks + p._body_position = self._body_position + return p + + def prepare_method(self, method): + """Prepares the given HTTP method.""" + self.method = method + if self.method is not None: + self.method = to_native_string(self.method.upper()) + + @staticmethod + def _get_idna_encoded_host(host): + from pip._vendor import idna + + try: + host = idna.encode(host, uts46=True).decode('utf-8') + except idna.IDNAError: + raise UnicodeError + return host + + def prepare_url(self, url, params): + """Prepares the given HTTP URL.""" + #: Accept objects that have string representations. + #: We're unable to blindly call unicode/str functions + #: as this will include the bytestring indicator (b'') + #: on python 3.x. + #: https://github.com/requests/requests/pull/2238 + if isinstance(url, bytes): + url = url.decode('utf8') + else: + url = unicode(url) if is_py2 else str(url) + + # Remove leading whitespaces from url + url = url.lstrip() + + # Don't do any URL preparation for non-HTTP schemes like `mailto`, + # `data` etc to work around exceptions from `url_parse`, which + # handles RFC 3986 only. + if ':' in url and not url.lower().startswith('http'): + self.url = url + return + + # Support for unicode domain names and paths. + try: + scheme, auth, host, port, path, query, fragment = parse_url(url) + except LocationParseError as e: + raise InvalidURL(*e.args) + + if not scheme: + error = ("Invalid URL {0!r}: No schema supplied. Perhaps you meant http://{0}?") + error = error.format(to_native_string(url, 'utf8')) + + raise MissingSchema(error) + + if not host: + raise InvalidURL("Invalid URL %r: No host supplied" % url) + + # In general, we want to try IDNA encoding the hostname if the string contains + # non-ASCII characters. This allows users to automatically get the correct IDNA + # behaviour. For strings containing only ASCII characters, we need to also verify + # it doesn't start with a wildcard (*), before allowing the unencoded hostname. + if not unicode_is_ascii(host): + try: + host = self._get_idna_encoded_host(host) + except UnicodeError: + raise InvalidURL('URL has an invalid label.') + elif host.startswith(u'*'): + raise InvalidURL('URL has an invalid label.') + + # Carefully reconstruct the network location + netloc = auth or '' + if netloc: + netloc += '@' + netloc += host + if port: + netloc += ':' + str(port) + + # Bare domains aren't valid URLs. + if not path: + path = '/' + + if is_py2: + if isinstance(scheme, str): + scheme = scheme.encode('utf-8') + if isinstance(netloc, str): + netloc = netloc.encode('utf-8') + if isinstance(path, str): + path = path.encode('utf-8') + if isinstance(query, str): + query = query.encode('utf-8') + if isinstance(fragment, str): + fragment = fragment.encode('utf-8') + + if isinstance(params, (str, bytes)): + params = to_native_string(params) + + enc_params = self._encode_params(params) + if enc_params: + if query: + query = '%s&%s' % (query, enc_params) + else: + query = enc_params + + url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment])) + self.url = url + + def prepare_headers(self, headers): + """Prepares the given HTTP headers.""" + + self.headers = CaseInsensitiveDict() + if headers: + for header in headers.items(): + # Raise exception on invalid header value. + check_header_validity(header) + name, value = header + self.headers[to_native_string(name)] = value + + def prepare_body(self, data, files, json=None): + """Prepares the given HTTP body data.""" + + # Check if file, fo, generator, iterator. + # If not, run through normal process. + + # Nottin' on you. + body = None + content_type = None + + if not data and json is not None: + # urllib3 requires a bytes-like body. Python 2's json.dumps + # provides this natively, but Python 3 gives a Unicode string. + content_type = 'application/json' + body = complexjson.dumps(json) + if not isinstance(body, bytes): + body = body.encode('utf-8') + + is_stream = all([ + hasattr(data, '__iter__'), + not isinstance(data, (basestring, list, tuple, Mapping)) + ]) + + try: + length = super_len(data) + except (TypeError, AttributeError, UnsupportedOperation): + length = None + + if is_stream: + body = data + + if getattr(body, 'tell', None) is not None: + # Record the current file position before reading. + # This will allow us to rewind a file in the event + # of a redirect. + try: + self._body_position = body.tell() + except (IOError, OSError): + # This differentiates from None, allowing us to catch + # a failed `tell()` later when trying to rewind the body + self._body_position = object() + + if files: + raise NotImplementedError('Streamed bodies and files are mutually exclusive.') + + if length: + self.headers['Content-Length'] = builtin_str(length) + else: + self.headers['Transfer-Encoding'] = 'chunked' + else: + # Multi-part file uploads. + if files: + (body, content_type) = self._encode_files(files, data) + else: + if data: + body = self._encode_params(data) + if isinstance(data, basestring) or hasattr(data, 'read'): + content_type = None + else: + content_type = 'application/x-www-form-urlencoded' + + self.prepare_content_length(body) + + # Add content-type if it wasn't explicitly provided. + if content_type and ('content-type' not in self.headers): + self.headers['Content-Type'] = content_type + + self.body = body + + def prepare_content_length(self, body): + """Prepare Content-Length header based on request method and body""" + if body is not None: + length = super_len(body) + if length: + # If length exists, set it. Otherwise, we fallback + # to Transfer-Encoding: chunked. + self.headers['Content-Length'] = builtin_str(length) + elif self.method not in ('GET', 'HEAD') and self.headers.get('Content-Length') is None: + # Set Content-Length to 0 for methods that can have a body + # but don't provide one. (i.e. not GET or HEAD) + self.headers['Content-Length'] = '0' + + def prepare_auth(self, auth, url=''): + """Prepares the given HTTP auth data.""" + + # If no Auth is explicitly provided, extract it from the URL first. + if auth is None: + url_auth = get_auth_from_url(self.url) + auth = url_auth if any(url_auth) else None + + if auth: + if isinstance(auth, tuple) and len(auth) == 2: + # special-case basic HTTP auth + auth = HTTPBasicAuth(*auth) + + # Allow auth to make its changes. + r = auth(self) + + # Update self to reflect the auth changes. + self.__dict__.update(r.__dict__) + + # Recompute Content-Length + self.prepare_content_length(self.body) + + def prepare_cookies(self, cookies): + """Prepares the given HTTP cookie data. + + This function eventually generates a ``Cookie`` header from the + given cookies using cookielib. Due to cookielib's design, the header + will not be regenerated if it already exists, meaning this function + can only be called once for the life of the + :class:`PreparedRequest <PreparedRequest>` object. Any subsequent calls + to ``prepare_cookies`` will have no actual effect, unless the "Cookie" + header is removed beforehand. + """ + if isinstance(cookies, cookielib.CookieJar): + self._cookies = cookies + else: + self._cookies = cookiejar_from_dict(cookies) + + cookie_header = get_cookie_header(self._cookies, self) + if cookie_header is not None: + self.headers['Cookie'] = cookie_header + + def prepare_hooks(self, hooks): + """Prepares the given hooks.""" + # hooks can be passed as None to the prepare method and to this + # method. To prevent iterating over None, simply use an empty list + # if hooks is False-y + hooks = hooks or [] + for event in hooks: + self.register_hook(event, hooks[event]) + + +class Response(object): + """The :class:`Response <Response>` object, which contains a + server's response to an HTTP request. + """ + + __attrs__ = [ + '_content', 'status_code', 'headers', 'url', 'history', + 'encoding', 'reason', 'cookies', 'elapsed', 'request' + ] + + def __init__(self): + self._content = False + self._content_consumed = False + self._next = None + + #: Integer Code of responded HTTP Status, e.g. 404 or 200. + self.status_code = None + + #: Case-insensitive Dictionary of Response Headers. + #: For example, ``headers['content-encoding']`` will return the + #: value of a ``'Content-Encoding'`` response header. + self.headers = CaseInsensitiveDict() + + #: File-like object representation of response (for advanced usage). + #: Use of ``raw`` requires that ``stream=True`` be set on the request. + # This requirement does not apply for use internally to Requests. + self.raw = None + + #: Final URL location of Response. + self.url = None + + #: Encoding to decode with when accessing r.text. + self.encoding = None + + #: A list of :class:`Response <Response>` objects from + #: the history of the Request. Any redirect responses will end + #: up here. The list is sorted from the oldest to the most recent request. + self.history = [] + + #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK". + self.reason = None + + #: A CookieJar of Cookies the server sent back. + self.cookies = cookiejar_from_dict({}) + + #: The amount of time elapsed between sending the request + #: and the arrival of the response (as a timedelta). + #: This property specifically measures the time taken between sending + #: the first byte of the request and finishing parsing the headers. It + #: is therefore unaffected by consuming the response content or the + #: value of the ``stream`` keyword argument. + self.elapsed = datetime.timedelta(0) + + #: The :class:`PreparedRequest <PreparedRequest>` object to which this + #: is a response. + self.request = None + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def __getstate__(self): + # Consume everything; accessing the content attribute makes + # sure the content has been fully read. + if not self._content_consumed: + self.content + + return dict( + (attr, getattr(self, attr, None)) + for attr in self.__attrs__ + ) + + def __setstate__(self, state): + for name, value in state.items(): + setattr(self, name, value) + + # pickled objects do not have .raw + setattr(self, '_content_consumed', True) + setattr(self, 'raw', None) + + def __repr__(self): + return '<Response [%s]>' % (self.status_code) + + def __bool__(self): + """Returns True if :attr:`status_code` is less than 400. + + This attribute checks if the status code of the response is between + 400 and 600 to see if there was a client error or a server error. If + the status code, is between 200 and 400, this will return True. This + is **not** a check to see if the response code is ``200 OK``. + """ + return self.ok + + def __nonzero__(self): + """Returns True if :attr:`status_code` is less than 400. + + This attribute checks if the status code of the response is between + 400 and 600 to see if there was a client error or a server error. If + the status code, is between 200 and 400, this will return True. This + is **not** a check to see if the response code is ``200 OK``. + """ + return self.ok + + def __iter__(self): + """Allows you to use a response as an iterator.""" + return self.iter_content(128) + + @property + def ok(self): + """Returns True if :attr:`status_code` is less than 400, False if not. + + This attribute checks if the status code of the response is between + 400 and 600 to see if there was a client error or a server error. If + the status code is between 200 and 400, this will return True. This + is **not** a check to see if the response code is ``200 OK``. + """ + try: + self.raise_for_status() + except HTTPError: + return False + return True + + @property + def is_redirect(self): + """True if this Response is a well-formed HTTP redirect that could have + been processed automatically (by :meth:`Session.resolve_redirects`). + """ + return ('location' in self.headers and self.status_code in REDIRECT_STATI) + + @property + def is_permanent_redirect(self): + """True if this Response one of the permanent versions of redirect.""" + return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect)) + + @property + def next(self): + """Returns a PreparedRequest for the next request in a redirect chain, if there is one.""" + return self._next + + @property + def apparent_encoding(self): + """The apparent encoding, provided by the chardet library.""" + return chardet.detect(self.content)['encoding'] + + def iter_content(self, chunk_size=1, decode_unicode=False): + """Iterates over the response data. When stream=True is set on the + request, this avoids reading the content at once into memory for + large responses. The chunk size is the number of bytes it should + read into memory. This is not necessarily the length of each item + returned as decoding can take place. + + chunk_size must be of type int or None. A value of None will + function differently depending on the value of `stream`. + stream=True will read data as it arrives in whatever size the + chunks are received. If stream=False, data is returned as + a single chunk. + + If decode_unicode is True, content will be decoded using the best + available encoding based on the response. + """ + + def generate(): + # Special case for urllib3. + if hasattr(self.raw, 'stream'): + try: + for chunk in self.raw.stream(chunk_size, decode_content=True): + yield chunk + except ProtocolError as e: + raise ChunkedEncodingError(e) + except DecodeError as e: + raise ContentDecodingError(e) + except ReadTimeoutError as e: + raise ConnectionError(e) + else: + # Standard file-like object. + while True: + chunk = self.raw.read(chunk_size) + if not chunk: + break + yield chunk + + self._content_consumed = True + + if self._content_consumed and isinstance(self._content, bool): + raise StreamConsumedError() + elif chunk_size is not None and not isinstance(chunk_size, int): + raise TypeError("chunk_size must be an int, it is instead a %s." % type(chunk_size)) + # simulate reading small chunks of the content + reused_chunks = iter_slices(self._content, chunk_size) + + stream_chunks = generate() + + chunks = reused_chunks if self._content_consumed else stream_chunks + + if decode_unicode: + chunks = stream_decode_response_unicode(chunks, self) + + return chunks + + def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None, delimiter=None): + """Iterates over the response data, one line at a time. When + stream=True is set on the request, this avoids reading the + content at once into memory for large responses. + + .. note:: This method is not reentrant safe. + """ + + pending = None + + for chunk in self.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode): + + if pending is not None: + chunk = pending + chunk + + if delimiter: + lines = chunk.split(delimiter) + else: + lines = chunk.splitlines() + + if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]: + pending = lines.pop() + else: + pending = None + + for line in lines: + yield line + + if pending is not None: + yield pending + + @property + def content(self): + """Content of the response, in bytes.""" + + if self._content is False: + # Read the contents. + if self._content_consumed: + raise RuntimeError( + 'The content for this response was already consumed') + + if self.status_code == 0 or self.raw is None: + self._content = None + else: + self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b'' + + self._content_consumed = True + # don't need to release the connection; that's been handled by urllib3 + # since we exhausted the data. + return self._content + + @property + def text(self): + """Content of the response, in unicode. + + If Response.encoding is None, encoding will be guessed using + ``chardet``. + + The encoding of the response content is determined based solely on HTTP + headers, following RFC 2616 to the letter. If you can take advantage of + non-HTTP knowledge to make a better guess at the encoding, you should + set ``r.encoding`` appropriately before accessing this property. + """ + + # Try charset from content-type + content = None + encoding = self.encoding + + if not self.content: + return str('') + + # Fallback to auto-detected encoding. + if self.encoding is None: + encoding = self.apparent_encoding + + # Decode unicode from given encoding. + try: + content = str(self.content, encoding, errors='replace') + except (LookupError, TypeError): + # A LookupError is raised if the encoding was not found which could + # indicate a misspelling or similar mistake. + # + # A TypeError can be raised if encoding is None + # + # So we try blindly encoding. + content = str(self.content, errors='replace') + + return content + + def json(self, **kwargs): + r"""Returns the json-encoded content of a response, if any. + + :param \*\*kwargs: Optional arguments that ``json.loads`` takes. + :raises ValueError: If the response body does not contain valid json. + """ + + if not self.encoding and self.content and len(self.content) > 3: + # No encoding set. JSON RFC 4627 section 3 states we should expect + # UTF-8, -16 or -32. Detect which one to use; If the detection or + # decoding fails, fall back to `self.text` (using chardet to make + # a best guess). + encoding = guess_json_utf(self.content) + if encoding is not None: + try: + return complexjson.loads( + self.content.decode(encoding), **kwargs + ) + except UnicodeDecodeError: + # Wrong UTF codec detected; usually because it's not UTF-8 + # but some other 8-bit codec. This is an RFC violation, + # and the server didn't bother to tell us what codec *was* + # used. + pass + return complexjson.loads(self.text, **kwargs) + + @property + def links(self): + """Returns the parsed header links of the response, if any.""" + + header = self.headers.get('link') + + # l = MultiDict() + l = {} + + if header: + links = parse_header_links(header) + + for link in links: + key = link.get('rel') or link.get('url') + l[key] = link + + return l + + def raise_for_status(self): + """Raises stored :class:`HTTPError`, if one occurred.""" + + http_error_msg = '' + if isinstance(self.reason, bytes): + # We attempt to decode utf-8 first because some servers + # choose to localize their reason strings. If the string + # isn't utf-8, we fall back to iso-8859-1 for all other + # encodings. (See PR #3538) + try: + reason = self.reason.decode('utf-8') + except UnicodeDecodeError: + reason = self.reason.decode('iso-8859-1') + else: + reason = self.reason + + if 400 <= self.status_code < 500: + http_error_msg = u'%s Client Error: %s for url: %s' % (self.status_code, reason, self.url) + + elif 500 <= self.status_code < 600: + http_error_msg = u'%s Server Error: %s for url: %s' % (self.status_code, reason, self.url) + + if http_error_msg: + raise HTTPError(http_error_msg, response=self) + + def close(self): + """Releases the connection back to the pool. Once this method has been + called the underlying ``raw`` object must not be accessed again. + + *Note: Should not normally need to be called explicitly.* + """ + if not self._content_consumed: + self.raw.close() + + release_conn = getattr(self.raw, 'release_conn', None) + if release_conn is not None: + release_conn() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/packages.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/packages.py new file mode 100644 index 0000000..9582fa7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/packages.py @@ -0,0 +1,16 @@ +import sys + +# This code exists for backwards compatibility reasons. +# I don't like it either. Just look the other way. :) + +for package in ('urllib3', 'idna', 'chardet'): + vendored_package = "pip._vendor." + package + locals()[package] = __import__(vendored_package) + # This traversal is apparently necessary such that the identities are + # preserved (requests.packages.urllib3.* is urllib3.*) + for mod in list(sys.modules): + if mod == vendored_package or mod.startswith(vendored_package + '.'): + unprefixed_mod = mod[len("pip._vendor."):] + sys.modules['pip._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] + +# Kinda cool, though, right? diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/sessions.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/sessions.py new file mode 100644 index 0000000..ba13526 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/sessions.py @@ -0,0 +1,741 @@ +# -*- coding: utf-8 -*- + +""" +requests.session +~~~~~~~~~~~~~~~~ + +This module provides a Session object to manage and persist settings across +requests (cookies, auth, proxies). +""" +import os +import sys +import time +from datetime import timedelta + +from .auth import _basic_auth_str +from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse, Mapping +from .cookies import ( + cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) +from .models import Request, PreparedRequest, DEFAULT_REDIRECT_LIMIT +from .hooks import default_hooks, dispatch_hook +from ._internal_utils import to_native_string +from .utils import to_key_val_list, default_headers +from .exceptions import ( + TooManyRedirects, InvalidSchema, ChunkedEncodingError, ContentDecodingError) + +from .structures import CaseInsensitiveDict +from .adapters import HTTPAdapter + +from .utils import ( + requote_uri, get_environ_proxies, get_netrc_auth, should_bypass_proxies, + get_auth_from_url, rewind_body +) + +from .status_codes import codes + +# formerly defined here, reexposed here for backward compatibility +from .models import REDIRECT_STATI + +# Preferred clock, based on which one is more accurate on a given system. +if sys.platform == 'win32': + try: # Python 3.4+ + preferred_clock = time.perf_counter + except AttributeError: # Earlier than Python 3. + preferred_clock = time.clock +else: + preferred_clock = time.time + + +def merge_setting(request_setting, session_setting, dict_class=OrderedDict): + """Determines appropriate setting for a given request, taking into account + the explicit setting on that request, and the setting in the session. If a + setting is a dictionary, they will be merged together using `dict_class` + """ + + if session_setting is None: + return request_setting + + if request_setting is None: + return session_setting + + # Bypass if not a dictionary (e.g. verify) + if not ( + isinstance(session_setting, Mapping) and + isinstance(request_setting, Mapping) + ): + return request_setting + + merged_setting = dict_class(to_key_val_list(session_setting)) + merged_setting.update(to_key_val_list(request_setting)) + + # Remove keys that are set to None. Extract keys first to avoid altering + # the dictionary during iteration. + none_keys = [k for (k, v) in merged_setting.items() if v is None] + for key in none_keys: + del merged_setting[key] + + return merged_setting + + +def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): + """Properly merges both requests and session hooks. + + This is necessary because when request_hooks == {'response': []}, the + merge breaks Session hooks entirely. + """ + if session_hooks is None or session_hooks.get('response') == []: + return request_hooks + + if request_hooks is None or request_hooks.get('response') == []: + return session_hooks + + return merge_setting(request_hooks, session_hooks, dict_class) + + +class SessionRedirectMixin(object): + + def get_redirect_target(self, resp): + """Receives a Response. Returns a redirect URI or ``None``""" + # Due to the nature of how requests processes redirects this method will + # be called at least once upon the original response and at least twice + # on each subsequent redirect response (if any). + # If a custom mixin is used to handle this logic, it may be advantageous + # to cache the redirect location onto the response object as a private + # attribute. + if resp.is_redirect: + location = resp.headers['location'] + # Currently the underlying http module on py3 decode headers + # in latin1, but empirical evidence suggests that latin1 is very + # rarely used with non-ASCII characters in HTTP headers. + # It is more likely to get UTF8 header rather than latin1. + # This causes incorrect handling of UTF8 encoded location headers. + # To solve this, we re-encode the location in latin1. + if is_py3: + location = location.encode('latin1') + return to_native_string(location, 'utf8') + return None + + def resolve_redirects(self, resp, req, stream=False, timeout=None, + verify=True, cert=None, proxies=None, yield_requests=False, **adapter_kwargs): + """Receives a Response. Returns a generator of Responses or Requests.""" + + hist = [] # keep track of history + + url = self.get_redirect_target(resp) + previous_fragment = urlparse(req.url).fragment + while url: + prepared_request = req.copy() + + # Update history and keep track of redirects. + # resp.history must ignore the original request in this loop + hist.append(resp) + resp.history = hist[1:] + + try: + resp.content # Consume socket so it can be released + except (ChunkedEncodingError, ContentDecodingError, RuntimeError): + resp.raw.read(decode_content=False) + + if len(resp.history) >= self.max_redirects: + raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp) + + # Release the connection back into the pool. + resp.close() + + # Handle redirection without scheme (see: RFC 1808 Section 4) + if url.startswith('//'): + parsed_rurl = urlparse(resp.url) + url = '%s:%s' % (to_native_string(parsed_rurl.scheme), url) + + # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2) + parsed = urlparse(url) + if parsed.fragment == '' and previous_fragment: + parsed = parsed._replace(fragment=previous_fragment) + elif parsed.fragment: + previous_fragment = parsed.fragment + url = parsed.geturl() + + # Facilitate relative 'location' headers, as allowed by RFC 7231. + # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') + # Compliant with RFC3986, we percent encode the url. + if not parsed.netloc: + url = urljoin(resp.url, requote_uri(url)) + else: + url = requote_uri(url) + + prepared_request.url = to_native_string(url) + + self.rebuild_method(prepared_request, resp) + + # https://github.com/requests/requests/issues/1084 + if resp.status_code not in (codes.temporary_redirect, codes.permanent_redirect): + # https://github.com/requests/requests/issues/3490 + purged_headers = ('Content-Length', 'Content-Type', 'Transfer-Encoding') + for header in purged_headers: + prepared_request.headers.pop(header, None) + prepared_request.body = None + + headers = prepared_request.headers + try: + del headers['Cookie'] + except KeyError: + pass + + # Extract any cookies sent on the response to the cookiejar + # in the new request. Because we've mutated our copied prepared + # request, use the old one that we haven't yet touched. + extract_cookies_to_jar(prepared_request._cookies, req, resp.raw) + merge_cookies(prepared_request._cookies, self.cookies) + prepared_request.prepare_cookies(prepared_request._cookies) + + # Rebuild auth and proxy information. + proxies = self.rebuild_proxies(prepared_request, proxies) + self.rebuild_auth(prepared_request, resp) + + # A failed tell() sets `_body_position` to `object()`. This non-None + # value ensures `rewindable` will be True, allowing us to raise an + # UnrewindableBodyError, instead of hanging the connection. + rewindable = ( + prepared_request._body_position is not None and + ('Content-Length' in headers or 'Transfer-Encoding' in headers) + ) + + # Attempt to rewind consumed file-like object. + if rewindable: + rewind_body(prepared_request) + + # Override the original request. + req = prepared_request + + if yield_requests: + yield req + else: + + resp = self.send( + req, + stream=stream, + timeout=timeout, + verify=verify, + cert=cert, + proxies=proxies, + allow_redirects=False, + **adapter_kwargs + ) + + extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) + + # extract redirect url, if any, for the next loop + url = self.get_redirect_target(resp) + yield resp + + def rebuild_auth(self, prepared_request, response): + """When being redirected we may want to strip authentication from the + request to avoid leaking credentials. This method intelligently removes + and reapplies authentication where possible to avoid credential loss. + """ + headers = prepared_request.headers + url = prepared_request.url + + if 'Authorization' in headers: + # If we get redirected to a new host, we should strip out any + # authentication headers. + original_parsed = urlparse(response.request.url) + redirect_parsed = urlparse(url) + + if (original_parsed.hostname != redirect_parsed.hostname): + del headers['Authorization'] + + # .netrc might have more auth for us on our new host. + new_auth = get_netrc_auth(url) if self.trust_env else None + if new_auth is not None: + prepared_request.prepare_auth(new_auth) + + return + + def rebuild_proxies(self, prepared_request, proxies): + """This method re-evaluates the proxy configuration by considering the + environment variables. If we are redirected to a URL covered by + NO_PROXY, we strip the proxy configuration. Otherwise, we set missing + proxy keys for this URL (in case they were stripped by a previous + redirect). + + This method also replaces the Proxy-Authorization header where + necessary. + + :rtype: dict + """ + proxies = proxies if proxies is not None else {} + headers = prepared_request.headers + url = prepared_request.url + scheme = urlparse(url).scheme + new_proxies = proxies.copy() + no_proxy = proxies.get('no_proxy') + + bypass_proxy = should_bypass_proxies(url, no_proxy=no_proxy) + if self.trust_env and not bypass_proxy: + environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) + + proxy = environ_proxies.get(scheme, environ_proxies.get('all')) + + if proxy: + new_proxies.setdefault(scheme, proxy) + + if 'Proxy-Authorization' in headers: + del headers['Proxy-Authorization'] + + try: + username, password = get_auth_from_url(new_proxies[scheme]) + except KeyError: + username, password = None, None + + if username and password: + headers['Proxy-Authorization'] = _basic_auth_str(username, password) + + return new_proxies + + def rebuild_method(self, prepared_request, response): + """When being redirected we may want to change the method of the request + based on certain specs or browser behavior. + """ + method = prepared_request.method + + # http://tools.ietf.org/html/rfc7231#section-6.4.4 + if response.status_code == codes.see_other and method != 'HEAD': + method = 'GET' + + # Do what the browsers do, despite standards... + # First, turn 302s into GETs. + if response.status_code == codes.found and method != 'HEAD': + method = 'GET' + + # Second, if a POST is responded to with a 301, turn it into a GET. + # This bizarre behaviour is explained in Issue 1704. + if response.status_code == codes.moved and method == 'POST': + method = 'GET' + + prepared_request.method = method + + +class Session(SessionRedirectMixin): + """A Requests session. + + Provides cookie persistence, connection-pooling, and configuration. + + Basic Usage:: + + >>> import requests + >>> s = requests.Session() + >>> s.get('http://httpbin.org/get') + <Response [200]> + + Or as a context manager:: + + >>> with requests.Session() as s: + >>> s.get('http://httpbin.org/get') + <Response [200]> + """ + + __attrs__ = [ + 'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify', + 'cert', 'prefetch', 'adapters', 'stream', 'trust_env', + 'max_redirects', + ] + + def __init__(self): + + #: A case-insensitive dictionary of headers to be sent on each + #: :class:`Request <Request>` sent from this + #: :class:`Session <Session>`. + self.headers = default_headers() + + #: Default Authentication tuple or object to attach to + #: :class:`Request <Request>`. + self.auth = None + + #: Dictionary mapping protocol or protocol and host to the URL of the proxy + #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to + #: be used on each :class:`Request <Request>`. + self.proxies = {} + + #: Event-handling hooks. + self.hooks = default_hooks() + + #: Dictionary of querystring data to attach to each + #: :class:`Request <Request>`. The dictionary values may be lists for + #: representing multivalued query parameters. + self.params = {} + + #: Stream response content default. + self.stream = False + + #: SSL Verification default. + self.verify = True + + #: SSL client certificate default, if String, path to ssl client + #: cert file (.pem). If Tuple, ('cert', 'key') pair. + self.cert = None + + #: Maximum number of redirects allowed. If the request exceeds this + #: limit, a :class:`TooManyRedirects` exception is raised. + #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is + #: 30. + self.max_redirects = DEFAULT_REDIRECT_LIMIT + + #: Trust environment settings for proxy configuration, default + #: authentication and similar. + self.trust_env = True + + #: A CookieJar containing all currently outstanding cookies set on this + #: session. By default it is a + #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but + #: may be any other ``cookielib.CookieJar`` compatible object. + self.cookies = cookiejar_from_dict({}) + + # Default connection adapters. + self.adapters = OrderedDict() + self.mount('https://', HTTPAdapter()) + self.mount('http://', HTTPAdapter()) + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def prepare_request(self, request): + """Constructs a :class:`PreparedRequest <PreparedRequest>` for + transmission and returns it. The :class:`PreparedRequest` has settings + merged from the :class:`Request <Request>` instance and those of the + :class:`Session`. + + :param request: :class:`Request` instance to prepare with this + session's settings. + :rtype: requests.PreparedRequest + """ + cookies = request.cookies or {} + + # Bootstrap CookieJar. + if not isinstance(cookies, cookielib.CookieJar): + cookies = cookiejar_from_dict(cookies) + + # Merge with session cookies + merged_cookies = merge_cookies( + merge_cookies(RequestsCookieJar(), self.cookies), cookies) + + # Set environment's basic authentication if not explicitly set. + auth = request.auth + if self.trust_env and not auth and not self.auth: + auth = get_netrc_auth(request.url) + + p = PreparedRequest() + p.prepare( + method=request.method.upper(), + url=request.url, + files=request.files, + data=request.data, + json=request.json, + headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict), + params=merge_setting(request.params, self.params), + auth=merge_setting(auth, self.auth), + cookies=merged_cookies, + hooks=merge_hooks(request.hooks, self.hooks), + ) + return p + + def request(self, method, url, + params=None, data=None, headers=None, cookies=None, files=None, + auth=None, timeout=None, allow_redirects=True, proxies=None, + hooks=None, stream=None, verify=None, cert=None, json=None): + """Constructs a :class:`Request <Request>`, prepares it and sends it. + Returns :class:`Response <Response>` object. + + :param method: method for the new :class:`Request` object. + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query + string for the :class:`Request`. + :param data: (optional) Dictionary, bytes, or file-like object to send + in the body of the :class:`Request`. + :param json: (optional) json to send in the body of the + :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the + :class:`Request`. + :param cookies: (optional) Dict or CookieJar object to send with the + :class:`Request`. + :param files: (optional) Dictionary of ``'filename': file-like-objects`` + for multipart encoding upload. + :param auth: (optional) Auth tuple or callable to enable + Basic/Digest/Custom HTTP Auth. + :param timeout: (optional) How long to wait for the server to send + data before giving up, as a float, or a :ref:`(connect timeout, + read timeout) <timeouts>` tuple. + :type timeout: float or tuple + :param allow_redirects: (optional) Set to True by default. + :type allow_redirects: bool + :param proxies: (optional) Dictionary mapping protocol or protocol and + hostname to the URL of the proxy. + :param stream: (optional) whether to immediately download the response + content. Defaults to ``False``. + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use. Defaults to ``True``. + :param cert: (optional) if String, path to ssl client cert file (.pem). + If Tuple, ('cert', 'key') pair. + :rtype: requests.Response + """ + # Create the Request. + req = Request( + method=method.upper(), + url=url, + headers=headers, + files=files, + data=data or {}, + json=json, + params=params or {}, + auth=auth, + cookies=cookies, + hooks=hooks, + ) + prep = self.prepare_request(req) + + proxies = proxies or {} + + settings = self.merge_environment_settings( + prep.url, proxies, stream, verify, cert + ) + + # Send the request. + send_kwargs = { + 'timeout': timeout, + 'allow_redirects': allow_redirects, + } + send_kwargs.update(settings) + resp = self.send(prep, **send_kwargs) + + return resp + + def get(self, url, **kwargs): + r"""Sends a GET request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return self.request('GET', url, **kwargs) + + def options(self, url, **kwargs): + r"""Sends a OPTIONS request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return self.request('OPTIONS', url, **kwargs) + + def head(self, url, **kwargs): + r"""Sends a HEAD request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', False) + return self.request('HEAD', url, **kwargs) + + def post(self, url, data=None, json=None, **kwargs): + r"""Sends a POST request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('POST', url, data=data, json=json, **kwargs) + + def put(self, url, data=None, **kwargs): + r"""Sends a PUT request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('PUT', url, data=data, **kwargs) + + def patch(self, url, data=None, **kwargs): + r"""Sends a PATCH request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('PATCH', url, data=data, **kwargs) + + def delete(self, url, **kwargs): + r"""Sends a DELETE request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('DELETE', url, **kwargs) + + def send(self, request, **kwargs): + """Send a given PreparedRequest. + + :rtype: requests.Response + """ + # Set defaults that the hooks can utilize to ensure they always have + # the correct parameters to reproduce the previous request. + kwargs.setdefault('stream', self.stream) + kwargs.setdefault('verify', self.verify) + kwargs.setdefault('cert', self.cert) + kwargs.setdefault('proxies', self.proxies) + + # It's possible that users might accidentally send a Request object. + # Guard against that specific failure case. + if isinstance(request, Request): + raise ValueError('You can only send PreparedRequests.') + + # Set up variables needed for resolve_redirects and dispatching of hooks + allow_redirects = kwargs.pop('allow_redirects', True) + stream = kwargs.get('stream') + hooks = request.hooks + + # Get the appropriate adapter to use + adapter = self.get_adapter(url=request.url) + + # Start time (approximately) of the request + start = preferred_clock() + + # Send the request + r = adapter.send(request, **kwargs) + + # Total elapsed time of the request (approximately) + elapsed = preferred_clock() - start + r.elapsed = timedelta(seconds=elapsed) + + # Response manipulation hooks + r = dispatch_hook('response', hooks, r, **kwargs) + + # Persist cookies + if r.history: + + # If the hooks create history then we want those cookies too + for resp in r.history: + extract_cookies_to_jar(self.cookies, resp.request, resp.raw) + + extract_cookies_to_jar(self.cookies, request, r.raw) + + # Redirect resolving generator. + gen = self.resolve_redirects(r, request, **kwargs) + + # Resolve redirects if allowed. + history = [resp for resp in gen] if allow_redirects else [] + + # Shuffle things around if there's history. + if history: + # Insert the first (original) request at the start + history.insert(0, r) + # Get the last request made + r = history.pop() + r.history = history + + # If redirects aren't being followed, store the response on the Request for Response.next(). + if not allow_redirects: + try: + r._next = next(self.resolve_redirects(r, request, yield_requests=True, **kwargs)) + except StopIteration: + pass + + if not stream: + r.content + + return r + + def merge_environment_settings(self, url, proxies, stream, verify, cert): + """ + Check the environment and merge it with some settings. + + :rtype: dict + """ + # Gather clues from the surrounding environment. + if self.trust_env: + # Set environment's proxies. + no_proxy = proxies.get('no_proxy') if proxies is not None else None + env_proxies = get_environ_proxies(url, no_proxy=no_proxy) + for (k, v) in env_proxies.items(): + proxies.setdefault(k, v) + + # Look for requests environment configuration and be compatible + # with cURL. + if verify is True or verify is None: + verify = (os.environ.get('REQUESTS_CA_BUNDLE') or + os.environ.get('CURL_CA_BUNDLE')) + + # Merge all the kwargs. + proxies = merge_setting(proxies, self.proxies) + stream = merge_setting(stream, self.stream) + verify = merge_setting(verify, self.verify) + cert = merge_setting(cert, self.cert) + + return {'verify': verify, 'proxies': proxies, 'stream': stream, + 'cert': cert} + + def get_adapter(self, url): + """ + Returns the appropriate connection adapter for the given URL. + + :rtype: requests.adapters.BaseAdapter + """ + for (prefix, adapter) in self.adapters.items(): + + if url.lower().startswith(prefix.lower()): + return adapter + + # Nothing matches :-/ + raise InvalidSchema("No connection adapters were found for '%s'" % url) + + def close(self): + """Closes all adapters and as such the session""" + for v in self.adapters.values(): + v.close() + + def mount(self, prefix, adapter): + """Registers a connection adapter to a prefix. + + Adapters are sorted in descending order by prefix length. + """ + self.adapters[prefix] = adapter + keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] + + for key in keys_to_move: + self.adapters[key] = self.adapters.pop(key) + + def __getstate__(self): + state = dict((attr, getattr(self, attr, None)) for attr in self.__attrs__) + return state + + def __setstate__(self, state): + for attr, value in state.items(): + setattr(self, attr, value) + + +def session(): + """ + Returns a :class:`Session` for context-management. + + :rtype: Session + """ + + return Session() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/status_codes.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/status_codes.py new file mode 100644 index 0000000..ff462c6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/status_codes.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +""" +The ``codes`` object defines a mapping from common names for HTTP statuses +to their numerical codes, accessible either as attributes or as dictionary +items. + +>>> requests.codes['temporary_redirect'] +307 +>>> requests.codes.teapot +418 +>>> requests.codes['\o/'] +200 + +Some codes have multiple names, and both upper- and lower-case versions of +the names are allowed. For example, ``codes.ok``, ``codes.OK``, and +``codes.okay`` all correspond to the HTTP status code 200. +""" + +from .structures import LookupDict + +_codes = { + + # Informational. + 100: ('continue',), + 101: ('switching_protocols',), + 102: ('processing',), + 103: ('checkpoint',), + 122: ('uri_too_long', 'request_uri_too_long'), + 200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'), + 201: ('created',), + 202: ('accepted',), + 203: ('non_authoritative_info', 'non_authoritative_information'), + 204: ('no_content',), + 205: ('reset_content', 'reset'), + 206: ('partial_content', 'partial'), + 207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'), + 208: ('already_reported',), + 226: ('im_used',), + + # Redirection. + 300: ('multiple_choices',), + 301: ('moved_permanently', 'moved', '\\o-'), + 302: ('found',), + 303: ('see_other', 'other'), + 304: ('not_modified',), + 305: ('use_proxy',), + 306: ('switch_proxy',), + 307: ('temporary_redirect', 'temporary_moved', 'temporary'), + 308: ('permanent_redirect', + 'resume_incomplete', 'resume',), # These 2 to be removed in 3.0 + + # Client Error. + 400: ('bad_request', 'bad'), + 401: ('unauthorized',), + 402: ('payment_required', 'payment'), + 403: ('forbidden',), + 404: ('not_found', '-o-'), + 405: ('method_not_allowed', 'not_allowed'), + 406: ('not_acceptable',), + 407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'), + 408: ('request_timeout', 'timeout'), + 409: ('conflict',), + 410: ('gone',), + 411: ('length_required',), + 412: ('precondition_failed', 'precondition'), + 413: ('request_entity_too_large',), + 414: ('request_uri_too_large',), + 415: ('unsupported_media_type', 'unsupported_media', 'media_type'), + 416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'), + 417: ('expectation_failed',), + 418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'), + 421: ('misdirected_request',), + 422: ('unprocessable_entity', 'unprocessable'), + 423: ('locked',), + 424: ('failed_dependency', 'dependency'), + 425: ('unordered_collection', 'unordered'), + 426: ('upgrade_required', 'upgrade'), + 428: ('precondition_required', 'precondition'), + 429: ('too_many_requests', 'too_many'), + 431: ('header_fields_too_large', 'fields_too_large'), + 444: ('no_response', 'none'), + 449: ('retry_with', 'retry'), + 450: ('blocked_by_windows_parental_controls', 'parental_controls'), + 451: ('unavailable_for_legal_reasons', 'legal_reasons'), + 499: ('client_closed_request',), + + # Server Error. + 500: ('internal_server_error', 'server_error', '/o\\', '✗'), + 501: ('not_implemented',), + 502: ('bad_gateway',), + 503: ('service_unavailable', 'unavailable'), + 504: ('gateway_timeout',), + 505: ('http_version_not_supported', 'http_version'), + 506: ('variant_also_negotiates',), + 507: ('insufficient_storage',), + 509: ('bandwidth_limit_exceeded', 'bandwidth'), + 510: ('not_extended',), + 511: ('network_authentication_required', 'network_auth', 'network_authentication'), +} + +codes = LookupDict(name='status_codes') + +def _init(): + for code, titles in _codes.items(): + for title in titles: + setattr(codes, title, code) + if not title.startswith(('\\', '/')): + setattr(codes, title.upper(), code) + + def doc(code): + names = ', '.join('``%s``' % n for n in _codes[code]) + return '* %d: %s' % (code, names) + + global __doc__ + __doc__ = (__doc__ + '\n' + + '\n'.join(doc(code) for code in sorted(_codes)) + if __doc__ is not None else None) + +_init() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/structures.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/structures.py new file mode 100644 index 0000000..da930e2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/structures.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- + +""" +requests.structures +~~~~~~~~~~~~~~~~~~~ + +Data structures that power Requests. +""" + +from .compat import OrderedDict, Mapping, MutableMapping + + +class CaseInsensitiveDict(MutableMapping): + """A case-insensitive ``dict``-like object. + + Implements all methods and operations of + ``MutableMapping`` as well as dict's ``copy``. Also + provides ``lower_items``. + + All keys are expected to be strings. The structure remembers the + case of the last key to be set, and ``iter(instance)``, + ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` + will contain case-sensitive keys. However, querying and contains + testing is case insensitive:: + + cid = CaseInsensitiveDict() + cid['Accept'] = 'application/json' + cid['aCCEPT'] == 'application/json' # True + list(cid) == ['Accept'] # True + + For example, ``headers['content-encoding']`` will return the + value of a ``'Content-Encoding'`` response header, regardless + of how the header name was originally stored. + + If the constructor, ``.update``, or equality comparison + operations are given keys that have equal ``.lower()``s, the + behavior is undefined. + """ + + def __init__(self, data=None, **kwargs): + self._store = OrderedDict() + if data is None: + data = {} + self.update(data, **kwargs) + + def __setitem__(self, key, value): + # Use the lowercased key for lookups, but store the actual + # key alongside the value. + self._store[key.lower()] = (key, value) + + def __getitem__(self, key): + return self._store[key.lower()][1] + + def __delitem__(self, key): + del self._store[key.lower()] + + def __iter__(self): + return (casedkey for casedkey, mappedvalue in self._store.values()) + + def __len__(self): + return len(self._store) + + def lower_items(self): + """Like iteritems(), but with all lowercase keys.""" + return ( + (lowerkey, keyval[1]) + for (lowerkey, keyval) + in self._store.items() + ) + + def __eq__(self, other): + if isinstance(other, Mapping): + other = CaseInsensitiveDict(other) + else: + return NotImplemented + # Compare insensitively + return dict(self.lower_items()) == dict(other.lower_items()) + + # Copy is required + def copy(self): + return CaseInsensitiveDict(self._store.values()) + + def __repr__(self): + return str(dict(self.items())) + + +class LookupDict(dict): + """Dictionary lookup object.""" + + def __init__(self, name=None): + self.name = name + super(LookupDict, self).__init__() + + def __repr__(self): + return '<lookup \'%s\'>' % (self.name) + + def __getitem__(self, key): + # We allow fall-through here, so values default to None + + return self.__dict__.get(key, None) + + def get(self, key, default=None): + return self.__dict__.get(key, default) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/requests/utils.py b/venv/lib/python3.7/site-packages/pip/_vendor/requests/utils.py new file mode 100644 index 0000000..431f6be --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/requests/utils.py @@ -0,0 +1,976 @@ +# -*- coding: utf-8 -*- + +""" +requests.utils +~~~~~~~~~~~~~~ + +This module provides utility functions that are used within Requests +that are also useful for external consumption. +""" + +import codecs +import contextlib +import io +import os +import re +import socket +import struct +import sys +import tempfile +import warnings +import zipfile + +from .__version__ import __version__ +from . import certs +# to_native_string is unused here, but imported here for backwards compatibility +from ._internal_utils import to_native_string +from .compat import parse_http_list as _parse_list_header +from .compat import ( + quote, urlparse, bytes, str, OrderedDict, unquote, getproxies, + proxy_bypass, urlunparse, basestring, integer_types, is_py3, + proxy_bypass_environment, getproxies_environment, Mapping) +from .cookies import cookiejar_from_dict +from .structures import CaseInsensitiveDict +from .exceptions import ( + InvalidURL, InvalidHeader, FileModeWarning, UnrewindableBodyError) + +NETRC_FILES = ('.netrc', '_netrc') + +DEFAULT_CA_BUNDLE_PATH = certs.where() + + +if sys.platform == 'win32': + # provide a proxy_bypass version on Windows without DNS lookups + + def proxy_bypass_registry(host): + try: + if is_py3: + import winreg + else: + import _winreg as winreg + except ImportError: + return False + + try: + internetSettings = winreg.OpenKey(winreg.HKEY_CURRENT_USER, + r'Software\Microsoft\Windows\CurrentVersion\Internet Settings') + # ProxyEnable could be REG_SZ or REG_DWORD, normalizing it + proxyEnable = int(winreg.QueryValueEx(internetSettings, + 'ProxyEnable')[0]) + # ProxyOverride is almost always a string + proxyOverride = winreg.QueryValueEx(internetSettings, + 'ProxyOverride')[0] + except OSError: + return False + if not proxyEnable or not proxyOverride: + return False + + # make a check value list from the registry entry: replace the + # '<local>' string by the localhost entry and the corresponding + # canonical entry. + proxyOverride = proxyOverride.split(';') + # now check if we match one of the registry values. + for test in proxyOverride: + if test == '<local>': + if '.' not in host: + return True + test = test.replace(".", r"\.") # mask dots + test = test.replace("*", r".*") # change glob sequence + test = test.replace("?", r".") # change glob char + if re.match(test, host, re.I): + return True + return False + + def proxy_bypass(host): # noqa + """Return True, if the host should be bypassed. + + Checks proxy settings gathered from the environment, if specified, + or the registry. + """ + if getproxies_environment(): + return proxy_bypass_environment(host) + else: + return proxy_bypass_registry(host) + + +def dict_to_sequence(d): + """Returns an internal sequence dictionary update.""" + + if hasattr(d, 'items'): + d = d.items() + + return d + + +def super_len(o): + total_length = None + current_position = 0 + + if hasattr(o, '__len__'): + total_length = len(o) + + elif hasattr(o, 'len'): + total_length = o.len + + elif hasattr(o, 'fileno'): + try: + fileno = o.fileno() + except io.UnsupportedOperation: + pass + else: + total_length = os.fstat(fileno).st_size + + # Having used fstat to determine the file length, we need to + # confirm that this file was opened up in binary mode. + if 'b' not in o.mode: + warnings.warn(( + "Requests has determined the content-length for this " + "request using the binary size of the file: however, the " + "file has been opened in text mode (i.e. without the 'b' " + "flag in the mode). This may lead to an incorrect " + "content-length. In Requests 3.0, support will be removed " + "for files in text mode."), + FileModeWarning + ) + + if hasattr(o, 'tell'): + try: + current_position = o.tell() + except (OSError, IOError): + # This can happen in some weird situations, such as when the file + # is actually a special file descriptor like stdin. In this + # instance, we don't know what the length is, so set it to zero and + # let requests chunk it instead. + if total_length is not None: + current_position = total_length + else: + if hasattr(o, 'seek') and total_length is None: + # StringIO and BytesIO have seek but no useable fileno + try: + # seek to end of file + o.seek(0, 2) + total_length = o.tell() + + # seek back to current position to support + # partially read file-like objects + o.seek(current_position or 0) + except (OSError, IOError): + total_length = 0 + + if total_length is None: + total_length = 0 + + return max(0, total_length - current_position) + + +def get_netrc_auth(url, raise_errors=False): + """Returns the Requests tuple auth for a given url from netrc.""" + + try: + from netrc import netrc, NetrcParseError + + netrc_path = None + + for f in NETRC_FILES: + try: + loc = os.path.expanduser('~/{0}'.format(f)) + except KeyError: + # os.path.expanduser can fail when $HOME is undefined and + # getpwuid fails. See http://bugs.python.org/issue20164 & + # https://github.com/requests/requests/issues/1846 + return + + if os.path.exists(loc): + netrc_path = loc + break + + # Abort early if there isn't one. + if netrc_path is None: + return + + ri = urlparse(url) + + # Strip port numbers from netloc. This weird `if...encode`` dance is + # used for Python 3.2, which doesn't support unicode literals. + splitstr = b':' + if isinstance(url, str): + splitstr = splitstr.decode('ascii') + host = ri.netloc.split(splitstr)[0] + + try: + _netrc = netrc(netrc_path).authenticators(host) + if _netrc: + # Return with login / password + login_i = (0 if _netrc[0] else 1) + return (_netrc[login_i], _netrc[2]) + except (NetrcParseError, IOError): + # If there was a parsing error or a permissions issue reading the file, + # we'll just skip netrc auth unless explicitly asked to raise errors. + if raise_errors: + raise + + # AppEngine hackiness. + except (ImportError, AttributeError): + pass + + +def guess_filename(obj): + """Tries to guess the filename of the given object.""" + name = getattr(obj, 'name', None) + if (name and isinstance(name, basestring) and name[0] != '<' and + name[-1] != '>'): + return os.path.basename(name) + + +def extract_zipped_paths(path): + """Replace nonexistent paths that look like they refer to a member of a zip + archive with the location of an extracted copy of the target, or else + just return the provided path unchanged. + """ + if os.path.exists(path): + # this is already a valid path, no need to do anything further + return path + + # find the first valid part of the provided path and treat that as a zip archive + # assume the rest of the path is the name of a member in the archive + archive, member = os.path.split(path) + while archive and not os.path.exists(archive): + archive, prefix = os.path.split(archive) + member = '/'.join([prefix, member]) + + if not zipfile.is_zipfile(archive): + return path + + zip_file = zipfile.ZipFile(archive) + if member not in zip_file.namelist(): + return path + + # we have a valid zip archive and a valid member of that archive + tmp = tempfile.gettempdir() + extracted_path = os.path.join(tmp, *member.split('/')) + if not os.path.exists(extracted_path): + extracted_path = zip_file.extract(member, path=tmp) + + return extracted_path + + +def from_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. Unless it can not be represented as such, return an + OrderedDict, e.g., + + :: + + >>> from_key_val_list([('key', 'val')]) + OrderedDict([('key', 'val')]) + >>> from_key_val_list('string') + ValueError: need more than 1 value to unpack + >>> from_key_val_list({'key': 'val'}) + OrderedDict([('key', 'val')]) + + :rtype: OrderedDict + """ + if value is None: + return None + + if isinstance(value, (str, bytes, bool, int)): + raise ValueError('cannot encode objects that are not 2-tuples') + + return OrderedDict(value) + + +def to_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. If it can be, return a list of tuples, e.g., + + :: + + >>> to_key_val_list([('key', 'val')]) + [('key', 'val')] + >>> to_key_val_list({'key': 'val'}) + [('key', 'val')] + >>> to_key_val_list('string') + ValueError: cannot encode objects that are not 2-tuples. + + :rtype: list + """ + if value is None: + return None + + if isinstance(value, (str, bytes, bool, int)): + raise ValueError('cannot encode objects that are not 2-tuples') + + if isinstance(value, Mapping): + value = value.items() + + return list(value) + + +# From mitsuhiko/werkzeug (used with permission). +def parse_list_header(value): + """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` + :rtype: 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 + + +# From mitsuhiko/werkzeug (used with permission). +def parse_dict_header(value): + """Parse lists of key, value pairs as described by RFC 2068 Section 2 and + convert them into a python dict: + + >>> 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. + + :param value: a string with a dict header. + :return: :class:`dict` + :rtype: dict + """ + result = {} + 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 + + +# From mitsuhiko/werkzeug (used with permission). +def unquote_header_value(value, is_filename=False): + 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. + + :param value: the header value to unquote. + :rtype: str + """ + 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 dict_from_cookiejar(cj): + """Returns a key/value dictionary from a CookieJar. + + :param cj: CookieJar object to extract cookies from. + :rtype: dict + """ + + cookie_dict = {} + + for cookie in cj: + cookie_dict[cookie.name] = cookie.value + + return cookie_dict + + +def add_dict_to_cookiejar(cj, cookie_dict): + """Returns a CookieJar from a key/value dictionary. + + :param cj: CookieJar to insert cookies into. + :param cookie_dict: Dict of key/values to insert into CookieJar. + :rtype: CookieJar + """ + + return cookiejar_from_dict(cookie_dict, cj) + + +def get_encodings_from_content(content): + """Returns encodings from given content string. + + :param content: bytestring to extract encodings from. + """ + warnings.warn(( + 'In requests 3.0, get_encodings_from_content will be removed. For ' + 'more information, please see the discussion on issue #2266. (This' + ' warning should only appear once.)'), + DeprecationWarning) + + charset_re = re.compile(r'<meta.*?charset=["\']*(.+?)["\'>]', flags=re.I) + pragma_re = re.compile(r'<meta.*?content=["\']*;?charset=(.+?)["\'>]', flags=re.I) + xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]') + + return (charset_re.findall(content) + + pragma_re.findall(content) + + xml_re.findall(content)) + + +def _parse_content_type_header(header): + """Returns content type and parameters from given header + + :param header: string + :return: tuple containing content type and dictionary of + parameters + """ + + tokens = header.split(';') + content_type, params = tokens[0].strip(), tokens[1:] + params_dict = {} + items_to_strip = "\"' " + + for param in params: + param = param.strip() + if param: + key, value = param, True + index_of_equals = param.find("=") + if index_of_equals != -1: + key = param[:index_of_equals].strip(items_to_strip) + value = param[index_of_equals + 1:].strip(items_to_strip) + params_dict[key] = value + return content_type, params_dict + + +def get_encoding_from_headers(headers): + """Returns encodings from given HTTP Header Dict. + + :param headers: dictionary to extract encoding from. + :rtype: str + """ + + content_type = headers.get('content-type') + + if not content_type: + return None + + content_type, params = _parse_content_type_header(content_type) + + if 'charset' in params: + return params['charset'].strip("'\"") + + if 'text' in content_type: + return 'ISO-8859-1' + + +def stream_decode_response_unicode(iterator, r): + """Stream decodes a iterator.""" + + if r.encoding is None: + for item in iterator: + yield item + return + + decoder = codecs.getincrementaldecoder(r.encoding)(errors='replace') + for chunk in iterator: + rv = decoder.decode(chunk) + if rv: + yield rv + rv = decoder.decode(b'', final=True) + if rv: + yield rv + + +def iter_slices(string, slice_length): + """Iterate over slices of a string.""" + pos = 0 + if slice_length is None or slice_length <= 0: + slice_length = len(string) + while pos < len(string): + yield string[pos:pos + slice_length] + pos += slice_length + + +def get_unicode_from_response(r): + """Returns the requested content back in unicode. + + :param r: Response object to get unicode content from. + + Tried: + + 1. charset from content-type + 2. fall back and replace all unicode characters + + :rtype: str + """ + warnings.warn(( + 'In requests 3.0, get_unicode_from_response will be removed. For ' + 'more information, please see the discussion on issue #2266. (This' + ' warning should only appear once.)'), + DeprecationWarning) + + tried_encodings = [] + + # Try charset from content-type + encoding = get_encoding_from_headers(r.headers) + + if encoding: + try: + return str(r.content, encoding) + except UnicodeError: + tried_encodings.append(encoding) + + # Fall back: + try: + return str(r.content, encoding, errors='replace') + except TypeError: + return r.content + + +# The unreserved URI characters (RFC 3986) +UNRESERVED_SET = frozenset( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~") + + +def unquote_unreserved(uri): + """Un-escape any percent-escape sequences in a URI that are unreserved + characters. This leaves all reserved, illegal and non-ASCII bytes encoded. + + :rtype: str + """ + parts = uri.split('%') + for i in range(1, len(parts)): + h = parts[i][0:2] + if len(h) == 2 and h.isalnum(): + try: + c = chr(int(h, 16)) + except ValueError: + raise InvalidURL("Invalid percent-escape sequence: '%s'" % h) + + if c in UNRESERVED_SET: + parts[i] = c + parts[i][2:] + else: + parts[i] = '%' + parts[i] + else: + parts[i] = '%' + parts[i] + return ''.join(parts) + + +def requote_uri(uri): + """Re-quote the given URI. + + This function passes the given URI through an unquote/quote cycle to + ensure that it is fully and consistently quoted. + + :rtype: str + """ + safe_with_percent = "!#$%&'()*+,/:;=?@[]~" + safe_without_percent = "!#$&'()*+,/:;=?@[]~" + try: + # Unquote only the unreserved characters + # Then quote only illegal characters (do not quote reserved, + # unreserved, or '%') + return quote(unquote_unreserved(uri), safe=safe_with_percent) + except InvalidURL: + # We couldn't unquote the given URI, so let's try quoting it, but + # there may be unquoted '%'s in the URI. We need to make sure they're + # properly quoted so they do not cause issues elsewhere. + return quote(uri, safe=safe_without_percent) + + +def address_in_network(ip, net): + """This function allows you to check if an IP belongs to a network subnet + + Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24 + returns False if ip = 192.168.1.1 and net = 192.168.100.0/24 + + :rtype: bool + """ + ipaddr = struct.unpack('=L', socket.inet_aton(ip))[0] + netaddr, bits = net.split('/') + netmask = struct.unpack('=L', socket.inet_aton(dotted_netmask(int(bits))))[0] + network = struct.unpack('=L', socket.inet_aton(netaddr))[0] & netmask + return (ipaddr & netmask) == (network & netmask) + + +def dotted_netmask(mask): + """Converts mask from /xx format to xxx.xxx.xxx.xxx + + Example: if mask is 24 function returns 255.255.255.0 + + :rtype: str + """ + bits = 0xffffffff ^ (1 << 32 - mask) - 1 + return socket.inet_ntoa(struct.pack('>I', bits)) + + +def is_ipv4_address(string_ip): + """ + :rtype: bool + """ + try: + socket.inet_aton(string_ip) + except socket.error: + return False + return True + + +def is_valid_cidr(string_network): + """ + Very simple check of the cidr format in no_proxy variable. + + :rtype: bool + """ + if string_network.count('/') == 1: + try: + mask = int(string_network.split('/')[1]) + except ValueError: + return False + + if mask < 1 or mask > 32: + return False + + try: + socket.inet_aton(string_network.split('/')[0]) + except socket.error: + return False + else: + return False + return True + + +@contextlib.contextmanager +def set_environ(env_name, value): + """Set the environment variable 'env_name' to 'value' + + Save previous value, yield, and then restore the previous value stored in + the environment variable 'env_name'. + + If 'value' is None, do nothing""" + value_changed = value is not None + if value_changed: + old_value = os.environ.get(env_name) + os.environ[env_name] = value + try: + yield + finally: + if value_changed: + if old_value is None: + del os.environ[env_name] + else: + os.environ[env_name] = old_value + + +def should_bypass_proxies(url, no_proxy): + """ + Returns whether we should bypass proxies or not. + + :rtype: bool + """ + # Prioritize lowercase environment variables over uppercase + # to keep a consistent behaviour with other http projects (curl, wget). + get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper()) + + # First check whether no_proxy is defined. If it is, check that the URL + # we're getting isn't in the no_proxy list. + no_proxy_arg = no_proxy + if no_proxy is None: + no_proxy = get_proxy('no_proxy') + parsed = urlparse(url) + + if no_proxy: + # We need to check whether we match here. We need to see if we match + # the end of the hostname, both with and without the port. + no_proxy = ( + host for host in no_proxy.replace(' ', '').split(',') if host + ) + + if is_ipv4_address(parsed.hostname): + for proxy_ip in no_proxy: + if is_valid_cidr(proxy_ip): + if address_in_network(parsed.hostname, proxy_ip): + return True + elif parsed.hostname == proxy_ip: + # If no_proxy ip was defined in plain IP notation instead of cidr notation & + # matches the IP of the index + return True + else: + host_with_port = parsed.hostname + if parsed.port: + host_with_port += ':{0}'.format(parsed.port) + + for host in no_proxy: + if parsed.hostname.endswith(host) or host_with_port.endswith(host): + # The URL does match something in no_proxy, so we don't want + # to apply the proxies on this URL. + return True + + # If the system proxy settings indicate that this URL should be bypassed, + # don't proxy. + # The proxy_bypass function is incredibly buggy on OS X in early versions + # of Python 2.6, so allow this call to fail. Only catch the specific + # exceptions we've seen, though: this call failing in other ways can reveal + # legitimate problems. + with set_environ('no_proxy', no_proxy_arg): + try: + bypass = proxy_bypass(parsed.hostname) + except (TypeError, socket.gaierror): + bypass = False + + if bypass: + return True + + return False + + +def get_environ_proxies(url, no_proxy=None): + """ + Return a dict of environment proxies. + + :rtype: dict + """ + if should_bypass_proxies(url, no_proxy=no_proxy): + return {} + else: + return getproxies() + + +def select_proxy(url, proxies): + """Select a proxy for the url, if applicable. + + :param url: The url being for the request + :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs + """ + proxies = proxies or {} + urlparts = urlparse(url) + if urlparts.hostname is None: + return proxies.get(urlparts.scheme, proxies.get('all')) + + proxy_keys = [ + urlparts.scheme + '://' + urlparts.hostname, + urlparts.scheme, + 'all://' + urlparts.hostname, + 'all', + ] + proxy = None + for proxy_key in proxy_keys: + if proxy_key in proxies: + proxy = proxies[proxy_key] + break + + return proxy + + +def default_user_agent(name="python-requests"): + """ + Return a string representing the default user agent. + + :rtype: str + """ + return '%s/%s' % (name, __version__) + + +def default_headers(): + """ + :rtype: requests.structures.CaseInsensitiveDict + """ + return CaseInsensitiveDict({ + 'User-Agent': default_user_agent(), + 'Accept-Encoding': ', '.join(('gzip', 'deflate')), + 'Accept': '*/*', + 'Connection': 'keep-alive', + }) + + +def parse_header_links(value): + """Return a list of parsed link headers proxies. + + i.e. Link: <http:/.../front.jpeg>; rel=front; type="image/jpeg",<http://.../back.jpeg>; rel=back;type="image/jpeg" + + :rtype: list + """ + + links = [] + + replace_chars = ' \'"' + + value = value.strip(replace_chars) + if not value: + return links + + for val in re.split(', *<', value): + try: + url, params = val.split(';', 1) + except ValueError: + url, params = val, '' + + link = {'url': url.strip('<> \'"')} + + for param in params.split(';'): + try: + key, value = param.split('=') + except ValueError: + break + + link[key.strip(replace_chars)] = value.strip(replace_chars) + + links.append(link) + + return links + + +# Null bytes; no need to recreate these on each call to guess_json_utf +_null = '\x00'.encode('ascii') # encoding to ASCII for Python 3 +_null2 = _null * 2 +_null3 = _null * 3 + + +def guess_json_utf(data): + """ + :rtype: str + """ + # JSON always starts with two ASCII characters, so detection is as + # easy as counting the nulls and from their location and count + # determine the encoding. Also detect a BOM, if present. + sample = data[:4] + if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE): + return 'utf-32' # BOM included + if sample[:3] == codecs.BOM_UTF8: + return 'utf-8-sig' # BOM included, MS style (discouraged) + if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE): + return 'utf-16' # BOM included + nullcount = sample.count(_null) + if nullcount == 0: + return 'utf-8' + if nullcount == 2: + if sample[::2] == _null2: # 1st and 3rd are null + return 'utf-16-be' + if sample[1::2] == _null2: # 2nd and 4th are null + return 'utf-16-le' + # Did not detect 2 valid UTF-16 ascii-range characters + if nullcount == 3: + if sample[:3] == _null3: + return 'utf-32-be' + if sample[1:] == _null3: + return 'utf-32-le' + # Did not detect a valid UTF-32 ascii-range character + return None + + +def prepend_scheme_if_needed(url, new_scheme): + """Given a URL that may or may not have a scheme, prepend the given scheme. + Does not replace a present scheme with the one provided as an argument. + + :rtype: str + """ + scheme, netloc, path, params, query, fragment = urlparse(url, new_scheme) + + # urlparse is a finicky beast, and sometimes decides that there isn't a + # netloc present. Assume that it's being over-cautious, and switch netloc + # and path if urlparse decided there was no netloc. + if not netloc: + netloc, path = path, netloc + + return urlunparse((scheme, netloc, path, params, query, fragment)) + + +def get_auth_from_url(url): + """Given a url with authentication components, extract them into a tuple of + username,password. + + :rtype: (str,str) + """ + parsed = urlparse(url) + + try: + auth = (unquote(parsed.username), unquote(parsed.password)) + except (AttributeError, TypeError): + auth = ('', '') + + return auth + + +# Moved outside of function to avoid recompile every call +_CLEAN_HEADER_REGEX_BYTE = re.compile(b'^\\S[^\\r\\n]*$|^$') +_CLEAN_HEADER_REGEX_STR = re.compile(r'^\S[^\r\n]*$|^$') + + +def check_header_validity(header): + """Verifies that header value is a string which doesn't contain + leading whitespace or return characters. This prevents unintended + header injection. + + :param header: tuple, in the format (name, value). + """ + name, value = header + + if isinstance(value, bytes): + pat = _CLEAN_HEADER_REGEX_BYTE + else: + pat = _CLEAN_HEADER_REGEX_STR + try: + if not pat.match(value): + raise InvalidHeader("Invalid return character or leading space in header: %s" % name) + except TypeError: + raise InvalidHeader("Value for header {%s: %s} must be of type str or " + "bytes, not %s" % (name, value, type(value))) + + +def urldefragauth(url): + """ + Given a url remove the fragment and the authentication part. + + :rtype: str + """ + scheme, netloc, path, params, query, fragment = urlparse(url) + + # see func:`prepend_scheme_if_needed` + if not netloc: + netloc, path = path, netloc + + netloc = netloc.rsplit('@', 1)[-1] + + return urlunparse((scheme, netloc, path, params, query, '')) + + +def rewind_body(prepared_request): + """Move file pointer back to its recorded starting position + so it can be read again on redirect. + """ + body_seek = getattr(prepared_request.body, 'seek', None) + if body_seek is not None and isinstance(prepared_request._body_position, integer_types): + try: + body_seek(prepared_request._body_position) + except (IOError, OSError): + raise UnrewindableBodyError("An error occurred when rewinding request " + "body for redirect.") + else: + raise UnrewindableBodyError("Unable to rewind request body for redirect.") diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/retrying.py b/venv/lib/python3.7/site-packages/pip/_vendor/retrying.py new file mode 100644 index 0000000..6d1e627 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/retrying.py @@ -0,0 +1,267 @@ +## Copyright 2013-2014 Ray Holder +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. + +import random +from pip._vendor import six +import sys +import time +import traceback + + +# sys.maxint / 2, since Python 3.2 doesn't have a sys.maxint... +MAX_WAIT = 1073741823 + + +def retry(*dargs, **dkw): + """ + Decorator function that instantiates the Retrying object + @param *dargs: positional arguments passed to Retrying object + @param **dkw: keyword arguments passed to the Retrying object + """ + # support both @retry and @retry() as valid syntax + if len(dargs) == 1 and callable(dargs[0]): + def wrap_simple(f): + + @six.wraps(f) + def wrapped_f(*args, **kw): + return Retrying().call(f, *args, **kw) + + return wrapped_f + + return wrap_simple(dargs[0]) + + else: + def wrap(f): + + @six.wraps(f) + def wrapped_f(*args, **kw): + return Retrying(*dargs, **dkw).call(f, *args, **kw) + + return wrapped_f + + return wrap + + +class Retrying(object): + + def __init__(self, + stop=None, wait=None, + stop_max_attempt_number=None, + stop_max_delay=None, + wait_fixed=None, + wait_random_min=None, wait_random_max=None, + wait_incrementing_start=None, wait_incrementing_increment=None, + wait_exponential_multiplier=None, wait_exponential_max=None, + retry_on_exception=None, + retry_on_result=None, + wrap_exception=False, + stop_func=None, + wait_func=None, + wait_jitter_max=None): + + self._stop_max_attempt_number = 5 if stop_max_attempt_number is None else stop_max_attempt_number + self._stop_max_delay = 100 if stop_max_delay is None else stop_max_delay + self._wait_fixed = 1000 if wait_fixed is None else wait_fixed + self._wait_random_min = 0 if wait_random_min is None else wait_random_min + self._wait_random_max = 1000 if wait_random_max is None else wait_random_max + self._wait_incrementing_start = 0 if wait_incrementing_start is None else wait_incrementing_start + self._wait_incrementing_increment = 100 if wait_incrementing_increment is None else wait_incrementing_increment + self._wait_exponential_multiplier = 1 if wait_exponential_multiplier is None else wait_exponential_multiplier + self._wait_exponential_max = MAX_WAIT if wait_exponential_max is None else wait_exponential_max + self._wait_jitter_max = 0 if wait_jitter_max is None else wait_jitter_max + + # TODO add chaining of stop behaviors + # stop behavior + stop_funcs = [] + if stop_max_attempt_number is not None: + stop_funcs.append(self.stop_after_attempt) + + if stop_max_delay is not None: + stop_funcs.append(self.stop_after_delay) + + if stop_func is not None: + self.stop = stop_func + + elif stop is None: + self.stop = lambda attempts, delay: any(f(attempts, delay) for f in stop_funcs) + + else: + self.stop = getattr(self, stop) + + # TODO add chaining of wait behaviors + # wait behavior + wait_funcs = [lambda *args, **kwargs: 0] + if wait_fixed is not None: + wait_funcs.append(self.fixed_sleep) + + if wait_random_min is not None or wait_random_max is not None: + wait_funcs.append(self.random_sleep) + + if wait_incrementing_start is not None or wait_incrementing_increment is not None: + wait_funcs.append(self.incrementing_sleep) + + if wait_exponential_multiplier is not None or wait_exponential_max is not None: + wait_funcs.append(self.exponential_sleep) + + if wait_func is not None: + self.wait = wait_func + + elif wait is None: + self.wait = lambda attempts, delay: max(f(attempts, delay) for f in wait_funcs) + + else: + self.wait = getattr(self, wait) + + # retry on exception filter + if retry_on_exception is None: + self._retry_on_exception = self.always_reject + else: + self._retry_on_exception = retry_on_exception + + # TODO simplify retrying by Exception types + # retry on result filter + if retry_on_result is None: + self._retry_on_result = self.never_reject + else: + self._retry_on_result = retry_on_result + + self._wrap_exception = wrap_exception + + def stop_after_attempt(self, previous_attempt_number, delay_since_first_attempt_ms): + """Stop after the previous attempt >= stop_max_attempt_number.""" + return previous_attempt_number >= self._stop_max_attempt_number + + def stop_after_delay(self, previous_attempt_number, delay_since_first_attempt_ms): + """Stop after the time from the first attempt >= stop_max_delay.""" + return delay_since_first_attempt_ms >= self._stop_max_delay + + def no_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """Don't sleep at all before retrying.""" + return 0 + + def fixed_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """Sleep a fixed amount of time between each retry.""" + return self._wait_fixed + + def random_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """Sleep a random amount of time between wait_random_min and wait_random_max""" + return random.randint(self._wait_random_min, self._wait_random_max) + + def incrementing_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """ + Sleep an incremental amount of time after each attempt, starting at + wait_incrementing_start and incrementing by wait_incrementing_increment + """ + result = self._wait_incrementing_start + (self._wait_incrementing_increment * (previous_attempt_number - 1)) + if result < 0: + result = 0 + return result + + def exponential_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + exp = 2 ** previous_attempt_number + result = self._wait_exponential_multiplier * exp + if result > self._wait_exponential_max: + result = self._wait_exponential_max + if result < 0: + result = 0 + return result + + def never_reject(self, result): + return False + + def always_reject(self, result): + return True + + def should_reject(self, attempt): + reject = False + if attempt.has_exception: + reject |= self._retry_on_exception(attempt.value[1]) + else: + reject |= self._retry_on_result(attempt.value) + + return reject + + def call(self, fn, *args, **kwargs): + start_time = int(round(time.time() * 1000)) + attempt_number = 1 + while True: + try: + attempt = Attempt(fn(*args, **kwargs), attempt_number, False) + except: + tb = sys.exc_info() + attempt = Attempt(tb, attempt_number, True) + + if not self.should_reject(attempt): + return attempt.get(self._wrap_exception) + + delay_since_first_attempt_ms = int(round(time.time() * 1000)) - start_time + if self.stop(attempt_number, delay_since_first_attempt_ms): + if not self._wrap_exception and attempt.has_exception: + # get() on an attempt with an exception should cause it to be raised, but raise just in case + raise attempt.get() + else: + raise RetryError(attempt) + else: + sleep = self.wait(attempt_number, delay_since_first_attempt_ms) + if self._wait_jitter_max: + jitter = random.random() * self._wait_jitter_max + sleep = sleep + max(0, jitter) + time.sleep(sleep / 1000.0) + + attempt_number += 1 + + +class Attempt(object): + """ + An Attempt encapsulates a call to a target function that may end as a + normal return value from the function or an Exception depending on what + occurred during the execution. + """ + + def __init__(self, value, attempt_number, has_exception): + self.value = value + self.attempt_number = attempt_number + self.has_exception = has_exception + + def get(self, wrap_exception=False): + """ + Return the return value of this Attempt instance or raise an Exception. + If wrap_exception is true, this Attempt is wrapped inside of a + RetryError before being raised. + """ + if self.has_exception: + if wrap_exception: + raise RetryError(self) + else: + six.reraise(self.value[0], self.value[1], self.value[2]) + else: + return self.value + + def __repr__(self): + if self.has_exception: + return "Attempts: {0}, Error:\n{1}".format(self.attempt_number, "".join(traceback.format_tb(self.value[2]))) + else: + return "Attempts: {0}, Value: {1}".format(self.attempt_number, self.value) + + +class RetryError(Exception): + """ + A RetryError encapsulates the last Attempt instance right before giving up. + """ + + def __init__(self, last_attempt): + self.last_attempt = last_attempt + + def __str__(self): + return "RetryError[{0}]".format(self.last_attempt) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/six.py b/venv/lib/python3.7/site-packages/pip/_vendor/six.py new file mode 100644 index 0000000..6bf4fd3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/six.py @@ -0,0 +1,891 @@ +# Copyright (c) 2010-2017 Benjamin Peterson +# +# 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. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.11.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + try: + if from_value is None: + raise value + raise value from from_value + finally: + value = None +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__init__.py new file mode 100644 index 0000000..4bd533b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/__init__.py @@ -0,0 +1,97 @@ +""" +urllib3 - Thread-safe connection pooling and re-using. +""" + +from __future__ import absolute_import +import warnings + +from .connectionpool import ( + HTTPConnectionPool, + HTTPSConnectionPool, + connection_from_url +) + +from . import exceptions +from .filepost import encode_multipart_formdata +from .poolmanager import PoolManager, ProxyManager, proxy_from_url +from .response import HTTPResponse +from .util.request import make_headers +from .util.url import get_host +from .util.timeout import Timeout +from .util.retry import Retry + + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +__author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' +__license__ = 'MIT' +__version__ = '1.23' + +__all__ = ( + 'HTTPConnectionPool', + 'HTTPSConnectionPool', + 'PoolManager', + 'ProxyManager', + 'HTTPResponse', + 'Retry', + 'Timeout', + 'add_stderr_logger', + 'connection_from_url', + 'disable_warnings', + 'encode_multipart_formdata', + 'get_host', + 'make_headers', + 'proxy_from_url', +) + +logging.getLogger(__name__).addHandler(NullHandler()) + + +def add_stderr_logger(level=logging.DEBUG): + """ + Helper for quickly adding a StreamHandler to the logger. Useful for + debugging. + + Returns the handler after adding it. + """ + # This method needs to be in this __init__.py to get the __name__ correct + # even if urllib3 is vendored within another package. + logger = logging.getLogger(__name__) + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) + logger.addHandler(handler) + logger.setLevel(level) + logger.debug('Added a stderr logging handler to logger: %s', __name__) + return handler + + +# ... Clean up. +del NullHandler + + +# All warning filters *must* be appended unless you're really certain that they +# shouldn't be: otherwise, it's very hard for users to use most Python +# mechanisms to silence them. +# SecurityWarning's always go off by default. +warnings.simplefilter('always', exceptions.SecurityWarning, append=True) +# SubjectAltNameWarning's should go off once per host +warnings.simplefilter('default', exceptions.SubjectAltNameWarning, append=True) +# InsecurePlatformWarning's don't vary between requests, so we keep it default. +warnings.simplefilter('default', exceptions.InsecurePlatformWarning, + append=True) +# SNIMissingWarnings should go off only once. +warnings.simplefilter('default', exceptions.SNIMissingWarning, append=True) + + +def disable_warnings(category=exceptions.HTTPWarning): + """ + Helper for quickly disabling all urllib3 warnings. + """ + warnings.simplefilter('ignore', category) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/_collections.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/_collections.py new file mode 100644 index 0000000..6e36b84 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/_collections.py @@ -0,0 +1,332 @@ +from __future__ import absolute_import +try: + from collections.abc import Mapping, MutableMapping +except ImportError: + from collections import Mapping, MutableMapping +try: + from threading import RLock +except ImportError: # Platform-specific: No threads available + class RLock: + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, traceback): + pass + + +try: # Python 2.7+ + from collections import OrderedDict +except ImportError: + from .packages.ordered_dict import OrderedDict +from .exceptions import InvalidHeader +from .packages.six import iterkeys, itervalues, PY3 + + +__all__ = ['RecentlyUsedContainer', 'HTTPHeaderDict'] + + +_Null = object() + + +class RecentlyUsedContainer(MutableMapping): + """ + Provides a thread-safe dict-like container which maintains up to + ``maxsize`` keys while throwing away the least-recently-used keys beyond + ``maxsize``. + + :param maxsize: + Maximum number of recent elements to retain. + + :param dispose_func: + Every time an item is evicted from the container, + ``dispose_func(value)`` is called. Callback which will get called + """ + + ContainerCls = OrderedDict + + def __init__(self, maxsize=10, dispose_func=None): + self._maxsize = maxsize + self.dispose_func = dispose_func + + self._container = self.ContainerCls() + self.lock = RLock() + + def __getitem__(self, key): + # Re-insert the item, moving it to the end of the eviction line. + with self.lock: + item = self._container.pop(key) + self._container[key] = item + return item + + def __setitem__(self, key, value): + evicted_value = _Null + with self.lock: + # Possibly evict the existing value of 'key' + evicted_value = self._container.get(key, _Null) + self._container[key] = value + + # If we didn't evict an existing value, we might have to evict the + # least recently used item from the beginning of the container. + if len(self._container) > self._maxsize: + _key, evicted_value = self._container.popitem(last=False) + + if self.dispose_func and evicted_value is not _Null: + self.dispose_func(evicted_value) + + def __delitem__(self, key): + with self.lock: + value = self._container.pop(key) + + if self.dispose_func: + self.dispose_func(value) + + def __len__(self): + with self.lock: + return len(self._container) + + def __iter__(self): + raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.') + + def clear(self): + with self.lock: + # Copy pointers to all values, then wipe the mapping + values = list(itervalues(self._container)) + self._container.clear() + + if self.dispose_func: + for value in values: + self.dispose_func(value) + + def keys(self): + with self.lock: + return list(iterkeys(self._container)) + + +class HTTPHeaderDict(MutableMapping): + """ + :param headers: + An iterable of field-value pairs. Must not contain multiple field names + when compared case-insensitively. + + :param kwargs: + Additional field-value pairs to pass in to ``dict.update``. + + A ``dict`` like container for storing HTTP Headers. + + Field names are stored and compared case-insensitively in compliance with + RFC 7230. Iteration provides the first case-sensitive key seen for each + case-insensitive pair. + + Using ``__setitem__`` syntax overwrites fields that compare equal + case-insensitively in order to maintain ``dict``'s api. For fields that + compare equal, instead create a new ``HTTPHeaderDict`` and use ``.add`` + in a loop. + + If multiple fields that are equal case-insensitively are passed to the + constructor or ``.update``, the behavior is undefined and some will be + lost. + + >>> headers = HTTPHeaderDict() + >>> headers.add('Set-Cookie', 'foo=bar') + >>> headers.add('set-cookie', 'baz=quxx') + >>> headers['content-length'] = '7' + >>> headers['SET-cookie'] + 'foo=bar, baz=quxx' + >>> headers['Content-Length'] + '7' + """ + + def __init__(self, headers=None, **kwargs): + super(HTTPHeaderDict, self).__init__() + self._container = OrderedDict() + if headers is not None: + if isinstance(headers, HTTPHeaderDict): + self._copy_from(headers) + else: + self.extend(headers) + if kwargs: + self.extend(kwargs) + + def __setitem__(self, key, val): + self._container[key.lower()] = [key, val] + return self._container[key.lower()] + + def __getitem__(self, key): + val = self._container[key.lower()] + return ', '.join(val[1:]) + + def __delitem__(self, key): + del self._container[key.lower()] + + def __contains__(self, key): + return key.lower() in self._container + + def __eq__(self, other): + if not isinstance(other, Mapping) and not hasattr(other, 'keys'): + return False + if not isinstance(other, type(self)): + other = type(self)(other) + return (dict((k.lower(), v) for k, v in self.itermerged()) == + dict((k.lower(), v) for k, v in other.itermerged())) + + def __ne__(self, other): + return not self.__eq__(other) + + if not PY3: # Python 2 + iterkeys = MutableMapping.iterkeys + itervalues = MutableMapping.itervalues + + __marker = object() + + def __len__(self): + return len(self._container) + + def __iter__(self): + # Only provide the originally cased names + for vals in self._container.values(): + yield vals[0] + + def pop(self, key, default=__marker): + '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + ''' + # Using the MutableMapping function directly fails due to the private marker. + # Using ordinary dict.pop would expose the internal structures. + # So let's reinvent the wheel. + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def discard(self, key): + try: + del self[key] + except KeyError: + pass + + def add(self, key, val): + """Adds a (name, value) pair, doesn't overwrite the value if it already + exists. + + >>> headers = HTTPHeaderDict(foo='bar') + >>> headers.add('Foo', 'baz') + >>> headers['foo'] + 'bar, baz' + """ + key_lower = key.lower() + new_vals = [key, val] + # Keep the common case aka no item present as fast as possible + vals = self._container.setdefault(key_lower, new_vals) + if new_vals is not vals: + vals.append(val) + + def extend(self, *args, **kwargs): + """Generic import function for any type of header-like object. + Adapted version of MutableMapping.update in order to insert items + with self.add instead of self.__setitem__ + """ + if len(args) > 1: + raise TypeError("extend() takes at most 1 positional " + "arguments ({0} given)".format(len(args))) + other = args[0] if len(args) >= 1 else () + + if isinstance(other, HTTPHeaderDict): + for key, val in other.iteritems(): + self.add(key, val) + elif isinstance(other, Mapping): + for key in other: + self.add(key, other[key]) + elif hasattr(other, "keys"): + for key in other.keys(): + self.add(key, other[key]) + else: + for key, value in other: + self.add(key, value) + + for key, value in kwargs.items(): + self.add(key, value) + + def getlist(self, key, default=__marker): + """Returns a list of all the values for the named field. Returns an + empty list if the key doesn't exist.""" + try: + vals = self._container[key.lower()] + except KeyError: + if default is self.__marker: + return [] + return default + else: + return vals[1:] + + # Backwards compatibility for httplib + getheaders = getlist + getallmatchingheaders = getlist + iget = getlist + + # Backwards compatibility for http.cookiejar + get_all = getlist + + def __repr__(self): + return "%s(%s)" % (type(self).__name__, dict(self.itermerged())) + + def _copy_from(self, other): + for key in other: + val = other.getlist(key) + if isinstance(val, list): + # Don't need to convert tuples + val = list(val) + self._container[key.lower()] = [key] + val + + def copy(self): + clone = type(self)() + clone._copy_from(self) + return clone + + def iteritems(self): + """Iterate over all header lines, including duplicate ones.""" + for key in self: + vals = self._container[key.lower()] + for val in vals[1:]: + yield vals[0], val + + def itermerged(self): + """Iterate over all headers, merging duplicate ones together.""" + for key in self: + val = self._container[key.lower()] + yield val[0], ', '.join(val[1:]) + + def items(self): + return list(self.iteritems()) + + @classmethod + def from_httplib(cls, message): # Python 2 + """Read headers from a Python 2 httplib message object.""" + # python2.7 does not expose a proper API for exporting multiheaders + # efficiently. This function re-reads raw lines from the message + # object and extracts the multiheaders properly. + obs_fold_continued_leaders = (' ', '\t') + headers = [] + + for line in message.headers: + if line.startswith(obs_fold_continued_leaders): + if not headers: + # We received a header line that starts with OWS as described + # in RFC-7230 S3.2.4. This indicates a multiline header, but + # there exists no previous header to which we can attach it. + raise InvalidHeader( + 'Header continuation with no previous header: %s' % line + ) + else: + key, value = headers[-1] + headers[-1] = (key, value + ' ' + line.strip()) + continue + + key, value = line.split(':', 1) + headers.append((key, value.strip())) + + return cls(headers) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connection.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connection.py new file mode 100644 index 0000000..a03b573 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connection.py @@ -0,0 +1,403 @@ +from __future__ import absolute_import +import datetime +import logging +import os +import sys +import socket +from socket import error as SocketError, timeout as SocketTimeout +import warnings +from .packages import six +from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection +from .packages.six.moves.http_client import HTTPException # noqa: F401 + +try: # Compiled with SSL? + import ssl + BaseSSLError = ssl.SSLError +except (ImportError, AttributeError): # Platform-specific: No SSL. + ssl = None + + class BaseSSLError(BaseException): + pass + + +try: # Python 3: + # Not a no-op, we're adding this to the namespace so it can be imported. + ConnectionError = ConnectionError +except NameError: # Python 2: + class ConnectionError(Exception): + pass + + +from .exceptions import ( + NewConnectionError, + ConnectTimeoutError, + SubjectAltNameWarning, + SystemTimeWarning, +) +from .packages.ssl_match_hostname import match_hostname, CertificateError + +from .util.ssl_ import ( + resolve_cert_reqs, + resolve_ssl_version, + assert_fingerprint, + create_urllib3_context, + ssl_wrap_socket +) + + +from .util import connection + +from ._collections import HTTPHeaderDict + +log = logging.getLogger(__name__) + +port_by_scheme = { + 'http': 80, + 'https': 443, +} + +# When updating RECENT_DATE, move it to within two years of the current date, +# and not less than 6 months ago. +# Example: if Today is 2018-01-01, then RECENT_DATE should be any date on or +# after 2016-01-01 (today - 2 years) AND before 2017-07-01 (today - 6 months) +RECENT_DATE = datetime.date(2017, 6, 30) + + +class DummyConnection(object): + """Used to detect a failed ConnectionCls import.""" + pass + + +class HTTPConnection(_HTTPConnection, object): + """ + Based on httplib.HTTPConnection but provides an extra constructor + backwards-compatibility layer between older and newer Pythons. + + Additional keyword parameters are used to configure attributes of the connection. + Accepted parameters include: + + - ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool` + - ``source_address``: Set the source address for the current connection. + + .. note:: This is ignored for Python 2.6. It is only applied for 2.7 and 3.x + + - ``socket_options``: Set specific options on the underlying socket. If not specified, then + defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling + Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. + + For example, if you wish to enable TCP Keep Alive in addition to the defaults, + you might pass:: + + HTTPConnection.default_socket_options + [ + (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), + ] + + Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). + """ + + default_port = port_by_scheme['http'] + + #: Disable Nagle's algorithm by default. + #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]`` + default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)] + + #: Whether this connection verifies the host's certificate. + is_verified = False + + def __init__(self, *args, **kw): + if six.PY3: # Python 3 + kw.pop('strict', None) + + # Pre-set source_address in case we have an older Python like 2.6. + self.source_address = kw.get('source_address') + + if sys.version_info < (2, 7): # Python 2.6 + # _HTTPConnection on Python 2.6 will balk at this keyword arg, but + # not newer versions. We can still use it when creating a + # connection though, so we pop it *after* we have saved it as + # self.source_address. + kw.pop('source_address', None) + + #: The socket options provided by the user. If no options are + #: provided, we use the default options. + self.socket_options = kw.pop('socket_options', self.default_socket_options) + + # Superclass also sets self.source_address in Python 2.7+. + _HTTPConnection.__init__(self, *args, **kw) + + @property + def host(self): + """ + Getter method to remove any trailing dots that indicate the hostname is an FQDN. + + In general, SSL certificates don't include the trailing dot indicating a + fully-qualified domain name, and thus, they don't validate properly when + checked against a domain name that includes the dot. In addition, some + servers may not expect to receive the trailing dot when provided. + + However, the hostname with trailing dot is critical to DNS resolution; doing a + lookup with the trailing dot will properly only resolve the appropriate FQDN, + whereas a lookup without a trailing dot will search the system's search domain + list. Thus, it's important to keep the original host around for use only in + those cases where it's appropriate (i.e., when doing DNS lookup to establish the + actual TCP connection across which we're going to send HTTP requests). + """ + return self._dns_host.rstrip('.') + + @host.setter + def host(self, value): + """ + Setter for the `host` property. + + We assume that only urllib3 uses the _dns_host attribute; httplib itself + only uses `host`, and it seems reasonable that other libraries follow suit. + """ + self._dns_host = value + + def _new_conn(self): + """ Establish a socket connection and set nodelay settings on it. + + :return: New socket connection. + """ + extra_kw = {} + if self.source_address: + extra_kw['source_address'] = self.source_address + + if self.socket_options: + extra_kw['socket_options'] = self.socket_options + + try: + conn = connection.create_connection( + (self._dns_host, self.port), self.timeout, **extra_kw) + + except SocketTimeout as e: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout)) + + except SocketError as e: + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e) + + return conn + + def _prepare_conn(self, conn): + self.sock = conn + # the _tunnel_host attribute was added in python 2.6.3 (via + # http://hg.python.org/cpython/rev/0f57b30a152f) so pythons 2.6(0-2) do + # not have them. + if getattr(self, '_tunnel_host', None): + # TODO: Fix tunnel so it doesn't depend on self.sock state. + self._tunnel() + # Mark this connection as not reusable + self.auto_open = 0 + + def connect(self): + conn = self._new_conn() + self._prepare_conn(conn) + + def request_chunked(self, method, url, body=None, headers=None): + """ + Alternative to the common request method, which sends the + body with chunked encoding and not as one block + """ + headers = HTTPHeaderDict(headers if headers is not None else {}) + skip_accept_encoding = 'accept-encoding' in headers + skip_host = 'host' in headers + self.putrequest( + method, + url, + skip_accept_encoding=skip_accept_encoding, + skip_host=skip_host + ) + for header, value in headers.items(): + self.putheader(header, value) + if 'transfer-encoding' not in headers: + self.putheader('Transfer-Encoding', 'chunked') + self.endheaders() + + if body is not None: + stringish_types = six.string_types + (six.binary_type,) + if isinstance(body, stringish_types): + body = (body,) + for chunk in body: + if not chunk: + continue + if not isinstance(chunk, six.binary_type): + chunk = chunk.encode('utf8') + len_str = hex(len(chunk))[2:] + self.send(len_str.encode('utf-8')) + self.send(b'\r\n') + self.send(chunk) + self.send(b'\r\n') + + # After the if clause, to always have a closed body + self.send(b'0\r\n\r\n') + + +class HTTPSConnection(HTTPConnection): + default_port = port_by_scheme['https'] + + ssl_version = None + + def __init__(self, host, port=None, key_file=None, cert_file=None, + strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, + ssl_context=None, **kw): + + HTTPConnection.__init__(self, host, port, strict=strict, + timeout=timeout, **kw) + + self.key_file = key_file + self.cert_file = cert_file + self.ssl_context = ssl_context + + # Required property for Google AppEngine 1.9.0 which otherwise causes + # HTTPS requests to go out as HTTP. (See Issue #356) + self._protocol = 'https' + + def connect(self): + conn = self._new_conn() + self._prepare_conn(conn) + + if self.ssl_context is None: + self.ssl_context = create_urllib3_context( + ssl_version=resolve_ssl_version(None), + cert_reqs=resolve_cert_reqs(None), + ) + + self.sock = ssl_wrap_socket( + sock=conn, + keyfile=self.key_file, + certfile=self.cert_file, + ssl_context=self.ssl_context, + ) + + +class VerifiedHTTPSConnection(HTTPSConnection): + """ + Based on httplib.HTTPSConnection but wraps the socket with + SSL certification. + """ + cert_reqs = None + ca_certs = None + ca_cert_dir = None + ssl_version = None + assert_fingerprint = None + + def set_cert(self, key_file=None, cert_file=None, + cert_reqs=None, ca_certs=None, + assert_hostname=None, assert_fingerprint=None, + ca_cert_dir=None): + """ + This method should only be called once, before the connection is used. + """ + # If cert_reqs is not provided, we can try to guess. If the user gave + # us a cert database, we assume they want to use it: otherwise, if + # they gave us an SSL Context object we should use whatever is set for + # it. + if cert_reqs is None: + if ca_certs or ca_cert_dir: + cert_reqs = 'CERT_REQUIRED' + elif self.ssl_context is not None: + cert_reqs = self.ssl_context.verify_mode + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + self.ca_certs = ca_certs and os.path.expanduser(ca_certs) + self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) + + def connect(self): + # Add certificate verification + conn = self._new_conn() + + hostname = self.host + if getattr(self, '_tunnel_host', None): + # _tunnel_host was added in Python 2.6.3 + # (See: http://hg.python.org/cpython/rev/0f57b30a152f) + + self.sock = conn + # Calls self._set_hostport(), so self.host is + # self._tunnel_host below. + self._tunnel() + # Mark this connection as not reusable + self.auto_open = 0 + + # Override the host with the one we're requesting data from. + hostname = self._tunnel_host + + is_time_off = datetime.date.today() < RECENT_DATE + if is_time_off: + warnings.warn(( + 'System time is way off (before {0}). This will probably ' + 'lead to SSL verification errors').format(RECENT_DATE), + SystemTimeWarning + ) + + # Wrap socket using verification with the root certs in + # trusted_root_certs + if self.ssl_context is None: + self.ssl_context = create_urllib3_context( + ssl_version=resolve_ssl_version(self.ssl_version), + cert_reqs=resolve_cert_reqs(self.cert_reqs), + ) + + context = self.ssl_context + context.verify_mode = resolve_cert_reqs(self.cert_reqs) + self.sock = ssl_wrap_socket( + sock=conn, + keyfile=self.key_file, + certfile=self.cert_file, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + server_hostname=hostname, + ssl_context=context) + + if self.assert_fingerprint: + assert_fingerprint(self.sock.getpeercert(binary_form=True), + self.assert_fingerprint) + elif context.verify_mode != ssl.CERT_NONE \ + and not getattr(context, 'check_hostname', False) \ + and self.assert_hostname is not False: + # While urllib3 attempts to always turn off hostname matching from + # the TLS library, this cannot always be done. So we check whether + # the TLS Library still thinks it's matching hostnames. + cert = self.sock.getpeercert() + if not cert.get('subjectAltName', ()): + warnings.warn(( + 'Certificate for {0} has no `subjectAltName`, falling back to check for a ' + '`commonName` for now. This feature is being removed by major browsers and ' + 'deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 ' + 'for details.)'.format(hostname)), + SubjectAltNameWarning + ) + _match_hostname(cert, self.assert_hostname or hostname) + + self.is_verified = ( + context.verify_mode == ssl.CERT_REQUIRED or + self.assert_fingerprint is not None + ) + + +def _match_hostname(cert, asserted_hostname): + try: + match_hostname(cert, asserted_hostname) + except CertificateError as e: + log.error( + 'Certificate did not match expected hostname: %s. ' + 'Certificate: %s', asserted_hostname, cert + ) + # Add cert to exception and reraise so client code can inspect + # the cert when catching the exception, if they want to + e._peer_cert = cert + raise + + +if ssl: + # Make a copy for testing. + UnverifiedHTTPSConnection = HTTPSConnection + HTTPSConnection = VerifiedHTTPSConnection +else: + HTTPSConnection = DummyConnection diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connectionpool.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connectionpool.py new file mode 100644 index 0000000..8fcb0bc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/connectionpool.py @@ -0,0 +1,906 @@ +from __future__ import absolute_import +import errno +import logging +import sys +import warnings + +from socket import error as SocketError, timeout as SocketTimeout +import socket + + +from .exceptions import ( + ClosedPoolError, + ProtocolError, + EmptyPoolError, + HeaderParsingError, + HostChangedError, + LocationValueError, + MaxRetryError, + ProxyError, + ReadTimeoutError, + SSLError, + TimeoutError, + InsecureRequestWarning, + NewConnectionError, +) +from .packages.ssl_match_hostname import CertificateError +from .packages import six +from .packages.six.moves import queue +from .connection import ( + port_by_scheme, + DummyConnection, + HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection, + HTTPException, BaseSSLError, +) +from .request import RequestMethods +from .response import HTTPResponse + +from .util.connection import is_connection_dropped +from .util.request import set_file_position +from .util.response import assert_header_parsing +from .util.retry import Retry +from .util.timeout import Timeout +from .util.url import get_host, Url, NORMALIZABLE_SCHEMES +from .util.queue import LifoQueue + + +xrange = six.moves.xrange + +log = logging.getLogger(__name__) + +_Default = object() + + +# Pool objects +class ConnectionPool(object): + """ + Base class for all connection pools, such as + :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. + """ + + scheme = None + QueueCls = LifoQueue + + def __init__(self, host, port=None): + if not host: + raise LocationValueError("No host specified.") + + self.host = _ipv6_host(host, self.scheme) + self._proxy_host = host.lower() + self.port = port + + def __str__(self): + return '%s(host=%r, port=%r)' % (type(self).__name__, + self.host, self.port) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + # Return False to re-raise any potential exceptions + return False + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + pass + + +# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 +_blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK]) + + +class HTTPConnectionPool(ConnectionPool, RequestMethods): + """ + Thread-safe connection pool for one host. + + :param host: + Host used for this HTTP Connection (e.g. "localhost"), passed into + :class:`httplib.HTTPConnection`. + + :param port: + Port used for this HTTP Connection (None is equivalent to 80), passed + into :class:`httplib.HTTPConnection`. + + :param strict: + Causes BadStatusLine to be raised if the status line can't be parsed + as a valid HTTP/1.0 or 1.1 status line, passed into + :class:`httplib.HTTPConnection`. + + .. note:: + Only works in Python 2. This parameter is ignored in Python 3. + + :param timeout: + Socket timeout in seconds for each individual connection. This can + be a float or integer, which sets the timeout for the HTTP request, + or an instance of :class:`urllib3.util.Timeout` which gives you more + fine-grained control over request timeouts. After the constructor has + been parsed, this is always a `urllib3.util.Timeout` object. + + :param maxsize: + Number of connections to save that can be reused. More than 1 is useful + in multithreaded situations. If ``block`` is set to False, more + connections will be created but they will not be saved once they've + been used. + + :param block: + If set to True, no more than ``maxsize`` connections will be used at + a time. When no free connections are available, the call will block + until a connection has been released. This is a useful side effect for + particular multithreaded situations where one does not want to use more + than maxsize connections per host to prevent flooding. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param retries: + Retry configuration to use by default with requests in this pool. + + :param _proxy: + Parsed proxy URL, should not be used directly, instead, see + :class:`urllib3.connectionpool.ProxyManager`" + + :param _proxy_headers: + A dictionary with proxy headers, should not be used directly, + instead, see :class:`urllib3.connectionpool.ProxyManager`" + + :param \\**conn_kw: + Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, + :class:`urllib3.connection.HTTPSConnection` instances. + """ + + scheme = 'http' + ConnectionCls = HTTPConnection + ResponseCls = HTTPResponse + + def __init__(self, host, port=None, strict=False, + timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False, + headers=None, retries=None, + _proxy=None, _proxy_headers=None, + **conn_kw): + ConnectionPool.__init__(self, host, port) + RequestMethods.__init__(self, headers) + + self.strict = strict + + if not isinstance(timeout, Timeout): + timeout = Timeout.from_float(timeout) + + if retries is None: + retries = Retry.DEFAULT + + self.timeout = timeout + self.retries = retries + + self.pool = self.QueueCls(maxsize) + self.block = block + + self.proxy = _proxy + self.proxy_headers = _proxy_headers or {} + + # Fill the queue up so that doing get() on it will block properly + for _ in xrange(maxsize): + self.pool.put(None) + + # These are mostly for testing and debugging purposes. + self.num_connections = 0 + self.num_requests = 0 + self.conn_kw = conn_kw + + if self.proxy: + # Enable Nagle's algorithm for proxies, to avoid packet fragmentation. + # We cannot know if the user has added default socket options, so we cannot replace the + # list. + self.conn_kw.setdefault('socket_options', []) + + def _new_conn(self): + """ + Return a fresh :class:`HTTPConnection`. + """ + self.num_connections += 1 + log.debug("Starting new HTTP connection (%d): %s:%s", + self.num_connections, self.host, self.port or "80") + + conn = self.ConnectionCls(host=self.host, port=self.port, + timeout=self.timeout.connect_timeout, + strict=self.strict, **self.conn_kw) + return conn + + def _get_conn(self, timeout=None): + """ + Get a connection. Will return a pooled connection if one is available. + + If no connections are available and :prop:`.block` is ``False``, then a + fresh connection is returned. + + :param timeout: + Seconds to wait before giving up and raising + :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and + :prop:`.block` is ``True``. + """ + conn = None + try: + conn = self.pool.get(block=self.block, timeout=timeout) + + except AttributeError: # self.pool is None + raise ClosedPoolError(self, "Pool is closed.") + + except queue.Empty: + if self.block: + raise EmptyPoolError(self, + "Pool reached maximum size and no more " + "connections are allowed.") + pass # Oh well, we'll create a new connection then + + # If this is a persistent connection, check if it got disconnected + if conn and is_connection_dropped(conn): + log.debug("Resetting dropped connection: %s", self.host) + conn.close() + if getattr(conn, 'auto_open', 1) == 0: + # This is a proxied connection that has been mutated by + # httplib._tunnel() and cannot be reused (since it would + # attempt to bypass the proxy) + conn = None + + return conn or self._new_conn() + + def _put_conn(self, conn): + """ + Put a connection back into the pool. + + :param conn: + Connection object for the current host and port as returned by + :meth:`._new_conn` or :meth:`._get_conn`. + + If the pool is already full, the connection is closed and discarded + because we exceeded maxsize. If connections are discarded frequently, + then maxsize should be increased. + + If the pool is closed, then the connection will be closed and discarded. + """ + try: + self.pool.put(conn, block=False) + return # Everything is dandy, done. + except AttributeError: + # self.pool is None. + pass + except queue.Full: + # This should never happen if self.block == True + log.warning( + "Connection pool is full, discarding connection: %s", + self.host) + + # Connection never got put back into the pool, close it. + if conn: + conn.close() + + def _validate_conn(self, conn): + """ + Called right before a request is made, after the socket is created. + """ + pass + + def _prepare_proxy(self, conn): + # Nothing to do for HTTP connections. + pass + + def _get_timeout(self, timeout): + """ Helper that always returns a :class:`urllib3.util.Timeout` """ + if timeout is _Default: + return self.timeout.clone() + + if isinstance(timeout, Timeout): + return timeout.clone() + else: + # User passed us an int/float. This is for backwards compatibility, + # can be removed later + return Timeout.from_float(timeout) + + def _raise_timeout(self, err, url, timeout_value): + """Is the error actually a timeout? Will raise a ReadTimeout or pass""" + + if isinstance(err, SocketTimeout): + raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) + + # See the above comment about EAGAIN in Python 3. In Python 2 we have + # to specifically catch it and throw the timeout error + if hasattr(err, 'errno') and err.errno in _blocking_errnos: + raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) + + # Catch possible read timeouts thrown as SSL errors. If not the + # case, rethrow the original. We need to do this because of: + # http://bugs.python.org/issue10272 + if 'timed out' in str(err) or 'did not complete (read)' in str(err): # Python 2.6 + raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) + + def _make_request(self, conn, method, url, timeout=_Default, chunked=False, + **httplib_request_kw): + """ + Perform a request on a given urllib connection object taken from our + pool. + + :param conn: + a connection from one of our connection pools + + :param timeout: + Socket timeout in seconds for the request. This can be a + float or integer, which will set the same timeout value for + the socket connect and the socket read, or an instance of + :class:`urllib3.util.Timeout`, which gives you more fine-grained + control over your timeouts. + """ + self.num_requests += 1 + + timeout_obj = self._get_timeout(timeout) + timeout_obj.start_connect() + conn.timeout = timeout_obj.connect_timeout + + # Trigger any extra validation we need to do. + try: + self._validate_conn(conn) + except (SocketTimeout, BaseSSLError) as e: + # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout. + self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) + raise + + # conn.request() calls httplib.*.request, not the method in + # urllib3.request. It also calls makefile (recv) on the socket. + if chunked: + conn.request_chunked(method, url, **httplib_request_kw) + else: + conn.request(method, url, **httplib_request_kw) + + # Reset the timeout for the recv() on the socket + read_timeout = timeout_obj.read_timeout + + # App Engine doesn't have a sock attr + if getattr(conn, 'sock', None): + # In Python 3 socket.py will catch EAGAIN and return None when you + # try and read into the file pointer created by http.client, which + # instead raises a BadStatusLine exception. Instead of catching + # the exception and assuming all BadStatusLine exceptions are read + # timeouts, check for a zero timeout before making the request. + if read_timeout == 0: + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % read_timeout) + if read_timeout is Timeout.DEFAULT_TIMEOUT: + conn.sock.settimeout(socket.getdefaulttimeout()) + else: # None or a value + conn.sock.settimeout(read_timeout) + + # Receive the response from the server + try: + try: # Python 2.7, use buffering of HTTP responses + httplib_response = conn.getresponse(buffering=True) + except TypeError: # Python 2.6 and older, Python 3 + try: + httplib_response = conn.getresponse() + except Exception as e: + # Remove the TypeError from the exception chain in Python 3; + # otherwise it looks like a programming error was the cause. + six.raise_from(e, None) + except (SocketTimeout, BaseSSLError, SocketError) as e: + self._raise_timeout(err=e, url=url, timeout_value=read_timeout) + raise + + # AppEngine doesn't have a version attr. + http_version = getattr(conn, '_http_vsn_str', 'HTTP/?') + log.debug("%s://%s:%s \"%s %s %s\" %s %s", self.scheme, self.host, self.port, + method, url, http_version, httplib_response.status, + httplib_response.length) + + try: + assert_header_parsing(httplib_response.msg) + except (HeaderParsingError, TypeError) as hpe: # Platform-specific: Python 3 + log.warning( + 'Failed to parse headers (url=%s): %s', + self._absolute_url(url), hpe, exc_info=True) + + return httplib_response + + def _absolute_url(self, path): + return Url(scheme=self.scheme, host=self.host, port=self.port, path=path).url + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + if self.pool is None: + return + # Disable access to the pool + old_pool, self.pool = self.pool, None + + try: + while True: + conn = old_pool.get(block=False) + if conn: + conn.close() + + except queue.Empty: + pass # Done. + + def is_same_host(self, url): + """ + Check if the given ``url`` is a member of the same host as this + connection pool. + """ + if url.startswith('/'): + return True + + # TODO: Add optional support for socket.gethostbyname checking. + scheme, host, port = get_host(url) + + host = _ipv6_host(host, self.scheme) + + # Use explicit default port for comparison when none is given + if self.port and not port: + port = port_by_scheme.get(scheme) + elif not self.port and port == port_by_scheme.get(scheme): + port = None + + return (scheme, host, port) == (self.scheme, self.host, self.port) + + def urlopen(self, method, url, body=None, headers=None, retries=None, + redirect=True, assert_same_host=True, timeout=_Default, + pool_timeout=None, release_conn=None, chunked=False, + body_pos=None, **response_kw): + """ + Get a connection from the pool and perform an HTTP request. This is the + lowest level call for making a request, so you'll need to specify all + the raw details. + + .. note:: + + More commonly, it's appropriate to use a convenience method provided + by :class:`.RequestMethods`, such as :meth:`request`. + + .. note:: + + `release_conn` will only behave as expected if + `preload_content=False` because we want to make + `preload_content=False` the default behaviour someday soon without + breaking backwards compatibility. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param body: + Data to send in the request body (useful for creating + POST requests, see HTTPConnectionPool.post_url for + more convenience). + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param retries: + Configure the number of retries to allow before raising a + :class:`~urllib3.exceptions.MaxRetryError` exception. + + Pass ``None`` to retry until you receive a response. Pass a + :class:`~urllib3.util.retry.Retry` object for fine-grained control + over different types of retries. + Pass an integer number to retry connection errors that many times, + but no other types of errors. Pass zero to never retry. + + If ``False``, then retries are disabled and any exception is raised + immediately. Also, instead of raising a MaxRetryError on redirects, + the redirect response will be returned. + + :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. + + :param redirect: + If True, automatically handle redirects (status codes 301, 302, + 303, 307, 308). Each redirect counts as a retry. Disabling retries + will disable redirect, too. + + :param assert_same_host: + If ``True``, will make sure that the host of the pool requests is + consistent else will raise HostChangedError. When False, you can + use the pool on an HTTP proxy and request foreign hosts. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param pool_timeout: + If set and the pool is set to block=True, then this method will + block for ``pool_timeout`` seconds and raise EmptyPoolError if no + connection is available within the time period. + + :param release_conn: + If False, then the urlopen call will not release the connection + back into the pool once a response is received (but will release if + you read the entire contents of the response such as when + `preload_content=True`). This is useful if you're not preloading + the response's content immediately. You will need to call + ``r.release_conn()`` on the response ``r`` to return the connection + back into the pool. If None, it takes the value of + ``response_kw.get('preload_content', True)``. + + :param chunked: + If True, urllib3 will send the body using chunked transfer + encoding. Otherwise, urllib3 will send the body using the standard + content-length form. Defaults to False. + + :param int body_pos: + Position to seek to in file-like body in the event of a retry or + redirect. Typically this won't need to be set because urllib3 will + auto-populate the value when needed. + + :param \\**response_kw: + Additional parameters are passed to + :meth:`urllib3.response.HTTPResponse.from_httplib` + """ + if headers is None: + headers = self.headers + + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect, default=self.retries) + + if release_conn is None: + release_conn = response_kw.get('preload_content', True) + + # Check host + if assert_same_host and not self.is_same_host(url): + raise HostChangedError(self, url, retries) + + conn = None + + # Track whether `conn` needs to be released before + # returning/raising/recursing. Update this variable if necessary, and + # leave `release_conn` constant throughout the function. That way, if + # the function recurses, the original value of `release_conn` will be + # passed down into the recursive call, and its value will be respected. + # + # See issue #651 [1] for details. + # + # [1] <https://github.com/shazow/urllib3/issues/651> + release_this_conn = release_conn + + # Merge the proxy headers. Only do this in HTTP. We have to copy the + # headers dict so we can safely change it without those changes being + # reflected in anyone else's copy. + if self.scheme == 'http': + headers = headers.copy() + headers.update(self.proxy_headers) + + # Must keep the exception bound to a separate variable or else Python 3 + # complains about UnboundLocalError. + err = None + + # Keep track of whether we cleanly exited the except block. This + # ensures we do proper cleanup in finally. + clean_exit = False + + # Rewind body position, if needed. Record current position + # for future rewinds in the event of a redirect/retry. + body_pos = set_file_position(body, body_pos) + + try: + # Request a connection from the queue. + timeout_obj = self._get_timeout(timeout) + conn = self._get_conn(timeout=pool_timeout) + + conn.timeout = timeout_obj.connect_timeout + + is_new_proxy_conn = self.proxy is not None and not getattr(conn, 'sock', None) + if is_new_proxy_conn: + self._prepare_proxy(conn) + + # Make the request on the httplib connection object. + httplib_response = self._make_request(conn, method, url, + timeout=timeout_obj, + body=body, headers=headers, + chunked=chunked) + + # If we're going to release the connection in ``finally:``, then + # the response doesn't need to know about the connection. Otherwise + # it will also try to release it and we'll have a double-release + # mess. + response_conn = conn if not release_conn else None + + # Pass method to Response for length checking + response_kw['request_method'] = method + + # Import httplib's response into our own wrapper object + response = self.ResponseCls.from_httplib(httplib_response, + pool=self, + connection=response_conn, + retries=retries, + **response_kw) + + # Everything went great! + clean_exit = True + + except queue.Empty: + # Timed out by queue. + raise EmptyPoolError(self, "No pool connections are available.") + + except (TimeoutError, HTTPException, SocketError, ProtocolError, + BaseSSLError, SSLError, CertificateError) as e: + # Discard the connection for these exceptions. It will be + # replaced during the next _get_conn() call. + clean_exit = False + if isinstance(e, (BaseSSLError, CertificateError)): + e = SSLError(e) + elif isinstance(e, (SocketError, NewConnectionError)) and self.proxy: + e = ProxyError('Cannot connect to proxy.', e) + elif isinstance(e, (SocketError, HTTPException)): + e = ProtocolError('Connection aborted.', e) + + retries = retries.increment(method, url, error=e, _pool=self, + _stacktrace=sys.exc_info()[2]) + retries.sleep() + + # Keep track of the error for the retry warning. + err = e + + finally: + if not clean_exit: + # We hit some kind of exception, handled or otherwise. We need + # to throw the connection away unless explicitly told not to. + # Close the connection, set the variable to None, and make sure + # we put the None back in the pool to avoid leaking it. + conn = conn and conn.close() + release_this_conn = True + + if release_this_conn: + # Put the connection back to be reused. If the connection is + # expired then it will be None, which will get replaced with a + # fresh connection during _get_conn. + self._put_conn(conn) + + if not conn: + # Try again + log.warning("Retrying (%r) after connection " + "broken by '%r': %s", retries, err, url) + return self.urlopen(method, url, body, headers, retries, + redirect, assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, body_pos=body_pos, + **response_kw) + + def drain_and_release_conn(response): + try: + # discard any remaining response body, the connection will be + # released back to the pool once the entire response is read + response.read() + except (TimeoutError, HTTPException, SocketError, ProtocolError, + BaseSSLError, SSLError) as e: + pass + + # Handle redirect? + redirect_location = redirect and response.get_redirect_location() + if redirect_location: + if response.status == 303: + method = 'GET' + + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_redirect: + # Drain and release the connection for this response, since + # we're not returning it to be released manually. + drain_and_release_conn(response) + raise + return response + + # drain and return the connection to the pool before recursing + drain_and_release_conn(response) + + retries.sleep_for_retry(response) + log.debug("Redirecting %s -> %s", url, redirect_location) + return self.urlopen( + method, redirect_location, body, headers, + retries=retries, redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, body_pos=body_pos, + **response_kw) + + # Check if we should retry the HTTP response. + has_retry_after = bool(response.getheader('Retry-After')) + if retries.is_retry(method, response.status, has_retry_after): + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_status: + # Drain and release the connection for this response, since + # we're not returning it to be released manually. + drain_and_release_conn(response) + raise + return response + + # drain and return the connection to the pool before recursing + drain_and_release_conn(response) + + retries.sleep(response) + log.debug("Retry: %s", url) + return self.urlopen( + method, url, body, headers, + retries=retries, redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, + body_pos=body_pos, **response_kw) + + return response + + +class HTTPSConnectionPool(HTTPConnectionPool): + """ + Same as :class:`.HTTPConnectionPool`, but HTTPS. + + When Python is compiled with the :mod:`ssl` module, then + :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates, + instead of :class:`.HTTPSConnection`. + + :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, + ``assert_hostname`` and ``host`` in this order to verify connections. + If ``assert_hostname`` is False, no verification is done. + + The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, + ``ca_cert_dir``, and ``ssl_version`` are only used if :mod:`ssl` is + available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade + the connection socket into an SSL socket. + """ + + scheme = 'https' + ConnectionCls = HTTPSConnection + + def __init__(self, host, port=None, + strict=False, timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, + block=False, headers=None, retries=None, + _proxy=None, _proxy_headers=None, + key_file=None, cert_file=None, cert_reqs=None, + ca_certs=None, ssl_version=None, + assert_hostname=None, assert_fingerprint=None, + ca_cert_dir=None, **conn_kw): + + HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize, + block, headers, retries, _proxy, _proxy_headers, + **conn_kw) + + if ca_certs and cert_reqs is None: + cert_reqs = 'CERT_REQUIRED' + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.ca_certs = ca_certs + self.ca_cert_dir = ca_cert_dir + self.ssl_version = ssl_version + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + + def _prepare_conn(self, conn): + """ + Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` + and establish the tunnel if proxy is used. + """ + + if isinstance(conn, VerifiedHTTPSConnection): + conn.set_cert(key_file=self.key_file, + cert_file=self.cert_file, + cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + assert_hostname=self.assert_hostname, + assert_fingerprint=self.assert_fingerprint) + conn.ssl_version = self.ssl_version + return conn + + def _prepare_proxy(self, conn): + """ + Establish tunnel connection early, because otherwise httplib + would improperly set Host: header to proxy's IP:port. + """ + # Python 2.7+ + try: + set_tunnel = conn.set_tunnel + except AttributeError: # Platform-specific: Python 2.6 + set_tunnel = conn._set_tunnel + + if sys.version_info <= (2, 6, 4) and not self.proxy_headers: # Python 2.6.4 and older + set_tunnel(self._proxy_host, self.port) + else: + set_tunnel(self._proxy_host, self.port, self.proxy_headers) + + conn.connect() + + def _new_conn(self): + """ + Return a fresh :class:`httplib.HTTPSConnection`. + """ + self.num_connections += 1 + log.debug("Starting new HTTPS connection (%d): %s:%s", + self.num_connections, self.host, self.port or "443") + + if not self.ConnectionCls or self.ConnectionCls is DummyConnection: + raise SSLError("Can't connect to HTTPS URL because the SSL " + "module is not available.") + + actual_host = self.host + actual_port = self.port + if self.proxy is not None: + actual_host = self.proxy.host + actual_port = self.proxy.port + + conn = self.ConnectionCls(host=actual_host, port=actual_port, + timeout=self.timeout.connect_timeout, + strict=self.strict, **self.conn_kw) + + return self._prepare_conn(conn) + + def _validate_conn(self, conn): + """ + Called right before a request is made, after the socket is created. + """ + super(HTTPSConnectionPool, self)._validate_conn(conn) + + # Force connect early to allow us to validate the connection. + if not getattr(conn, 'sock', None): # AppEngine might not have `.sock` + conn.connect() + + if not conn.is_verified: + warnings.warn(( + 'Unverified HTTPS request is being made. ' + 'Adding certificate verification is strongly advised. See: ' + 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' + '#ssl-warnings'), + InsecureRequestWarning) + + +def connection_from_url(url, **kw): + """ + Given a url, return an :class:`.ConnectionPool` instance of its host. + + This is a shortcut for not having to parse out the scheme, host, and port + of the url before creating an :class:`.ConnectionPool` instance. + + :param url: + Absolute URL string that must include the scheme. Port is optional. + + :param \\**kw: + Passes additional parameters to the constructor of the appropriate + :class:`.ConnectionPool`. Useful for specifying things like + timeout, maxsize, headers, etc. + + Example:: + + >>> conn = connection_from_url('http://google.com/') + >>> r = conn.request('GET', '/') + """ + scheme, host, port = get_host(url) + port = port or port_by_scheme.get(scheme, 80) + if scheme == 'https': + return HTTPSConnectionPool(host, port=port, **kw) + else: + return HTTPConnectionPool(host, port=port, **kw) + + +def _ipv6_host(host, scheme): + """ + Process IPv6 address literals + """ + + # httplib doesn't like it when we include brackets in IPv6 addresses + # Specifically, if we include brackets but also pass the port then + # httplib crazily doubles up the square brackets on the Host header. + # Instead, we need to make sure we never pass ``None`` as the port. + # However, for backward compatibility reasons we can't actually + # *assert* that. See http://bugs.python.org/issue28539 + # + # Also if an IPv6 address literal has a zone identifier, the + # percent sign might be URIencoded, convert it back into ASCII + if host.startswith('[') and host.endswith(']'): + host = host.replace('%25', '%').strip('[]') + if scheme in NORMALIZABLE_SCHEMES: + host = host.lower() + return host diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py new file mode 100644 index 0000000..bcf41c0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py @@ -0,0 +1,593 @@ +""" +This module uses ctypes to bind a whole bunch of functions and constants from +SecureTransport. The goal here is to provide the low-level API to +SecureTransport. These are essentially the C-level functions and constants, and +they're pretty gross to work with. + +This code is a bastardised version of the code found in Will Bond's oscrypto +library. An enormous debt is owed to him for blazing this trail for us. For +that reason, this code should be considered to be covered both by urllib3's +license and by oscrypto's: + + Copyright (c) 2015-2016 Will Bond <will@wbond.net> + + 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. +""" +from __future__ import absolute_import + +import platform +from ctypes.util import find_library +from ctypes import ( + c_void_p, c_int32, c_char_p, c_size_t, c_byte, c_uint32, c_ulong, c_long, + c_bool +) +from ctypes import CDLL, POINTER, CFUNCTYPE + + +security_path = find_library('Security') +if not security_path: + raise ImportError('The library Security could not be found') + + +core_foundation_path = find_library('CoreFoundation') +if not core_foundation_path: + raise ImportError('The library CoreFoundation could not be found') + + +version = platform.mac_ver()[0] +version_info = tuple(map(int, version.split('.'))) +if version_info < (10, 8): + raise OSError( + 'Only OS X 10.8 and newer are supported, not %s.%s' % ( + version_info[0], version_info[1] + ) + ) + +Security = CDLL(security_path, use_errno=True) +CoreFoundation = CDLL(core_foundation_path, use_errno=True) + +Boolean = c_bool +CFIndex = c_long +CFStringEncoding = c_uint32 +CFData = c_void_p +CFString = c_void_p +CFArray = c_void_p +CFMutableArray = c_void_p +CFDictionary = c_void_p +CFError = c_void_p +CFType = c_void_p +CFTypeID = c_ulong + +CFTypeRef = POINTER(CFType) +CFAllocatorRef = c_void_p + +OSStatus = c_int32 + +CFDataRef = POINTER(CFData) +CFStringRef = POINTER(CFString) +CFArrayRef = POINTER(CFArray) +CFMutableArrayRef = POINTER(CFMutableArray) +CFDictionaryRef = POINTER(CFDictionary) +CFArrayCallBacks = c_void_p +CFDictionaryKeyCallBacks = c_void_p +CFDictionaryValueCallBacks = c_void_p + +SecCertificateRef = POINTER(c_void_p) +SecExternalFormat = c_uint32 +SecExternalItemType = c_uint32 +SecIdentityRef = POINTER(c_void_p) +SecItemImportExportFlags = c_uint32 +SecItemImportExportKeyParameters = c_void_p +SecKeychainRef = POINTER(c_void_p) +SSLProtocol = c_uint32 +SSLCipherSuite = c_uint32 +SSLContextRef = POINTER(c_void_p) +SecTrustRef = POINTER(c_void_p) +SSLConnectionRef = c_uint32 +SecTrustResultType = c_uint32 +SecTrustOptionFlags = c_uint32 +SSLProtocolSide = c_uint32 +SSLConnectionType = c_uint32 +SSLSessionOption = c_uint32 + + +try: + Security.SecItemImport.argtypes = [ + CFDataRef, + CFStringRef, + POINTER(SecExternalFormat), + POINTER(SecExternalItemType), + SecItemImportExportFlags, + POINTER(SecItemImportExportKeyParameters), + SecKeychainRef, + POINTER(CFArrayRef), + ] + Security.SecItemImport.restype = OSStatus + + Security.SecCertificateGetTypeID.argtypes = [] + Security.SecCertificateGetTypeID.restype = CFTypeID + + Security.SecIdentityGetTypeID.argtypes = [] + Security.SecIdentityGetTypeID.restype = CFTypeID + + Security.SecKeyGetTypeID.argtypes = [] + Security.SecKeyGetTypeID.restype = CFTypeID + + Security.SecCertificateCreateWithData.argtypes = [ + CFAllocatorRef, + CFDataRef + ] + Security.SecCertificateCreateWithData.restype = SecCertificateRef + + Security.SecCertificateCopyData.argtypes = [ + SecCertificateRef + ] + Security.SecCertificateCopyData.restype = CFDataRef + + Security.SecCopyErrorMessageString.argtypes = [ + OSStatus, + c_void_p + ] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SecIdentityCreateWithCertificate.argtypes = [ + CFTypeRef, + SecCertificateRef, + POINTER(SecIdentityRef) + ] + Security.SecIdentityCreateWithCertificate.restype = OSStatus + + Security.SecKeychainCreate.argtypes = [ + c_char_p, + c_uint32, + c_void_p, + Boolean, + c_void_p, + POINTER(SecKeychainRef) + ] + Security.SecKeychainCreate.restype = OSStatus + + Security.SecKeychainDelete.argtypes = [ + SecKeychainRef + ] + Security.SecKeychainDelete.restype = OSStatus + + Security.SecPKCS12Import.argtypes = [ + CFDataRef, + CFDictionaryRef, + POINTER(CFArrayRef) + ] + Security.SecPKCS12Import.restype = OSStatus + + SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, c_void_p, POINTER(c_size_t)) + SSLWriteFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t)) + + Security.SSLSetIOFuncs.argtypes = [ + SSLContextRef, + SSLReadFunc, + SSLWriteFunc + ] + Security.SSLSetIOFuncs.restype = OSStatus + + Security.SSLSetPeerID.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t + ] + Security.SSLSetPeerID.restype = OSStatus + + Security.SSLSetCertificate.argtypes = [ + SSLContextRef, + CFArrayRef + ] + Security.SSLSetCertificate.restype = OSStatus + + Security.SSLSetCertificateAuthorities.argtypes = [ + SSLContextRef, + CFTypeRef, + Boolean + ] + Security.SSLSetCertificateAuthorities.restype = OSStatus + + Security.SSLSetConnection.argtypes = [ + SSLContextRef, + SSLConnectionRef + ] + Security.SSLSetConnection.restype = OSStatus + + Security.SSLSetPeerDomainName.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t + ] + Security.SSLSetPeerDomainName.restype = OSStatus + + Security.SSLHandshake.argtypes = [ + SSLContextRef + ] + Security.SSLHandshake.restype = OSStatus + + Security.SSLRead.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t, + POINTER(c_size_t) + ] + Security.SSLRead.restype = OSStatus + + Security.SSLWrite.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t, + POINTER(c_size_t) + ] + Security.SSLWrite.restype = OSStatus + + Security.SSLClose.argtypes = [ + SSLContextRef + ] + Security.SSLClose.restype = OSStatus + + Security.SSLGetNumberSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetNumberSupportedCiphers.restype = OSStatus + + Security.SSLGetSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t) + ] + Security.SSLGetSupportedCiphers.restype = OSStatus + + Security.SSLSetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + c_size_t + ] + Security.SSLSetEnabledCiphers.restype = OSStatus + + Security.SSLGetNumberEnabledCiphers.argtype = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetNumberEnabledCiphers.restype = OSStatus + + Security.SSLGetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t) + ] + Security.SSLGetEnabledCiphers.restype = OSStatus + + Security.SSLGetNegotiatedCipher.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite) + ] + Security.SSLGetNegotiatedCipher.restype = OSStatus + + Security.SSLGetNegotiatedProtocolVersion.argtypes = [ + SSLContextRef, + POINTER(SSLProtocol) + ] + Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus + + Security.SSLCopyPeerTrust.argtypes = [ + SSLContextRef, + POINTER(SecTrustRef) + ] + Security.SSLCopyPeerTrust.restype = OSStatus + + Security.SecTrustSetAnchorCertificates.argtypes = [ + SecTrustRef, + CFArrayRef + ] + Security.SecTrustSetAnchorCertificates.restype = OSStatus + + Security.SecTrustSetAnchorCertificatesOnly.argstypes = [ + SecTrustRef, + Boolean + ] + Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus + + Security.SecTrustEvaluate.argtypes = [ + SecTrustRef, + POINTER(SecTrustResultType) + ] + Security.SecTrustEvaluate.restype = OSStatus + + Security.SecTrustGetCertificateCount.argtypes = [ + SecTrustRef + ] + Security.SecTrustGetCertificateCount.restype = CFIndex + + Security.SecTrustGetCertificateAtIndex.argtypes = [ + SecTrustRef, + CFIndex + ] + Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef + + Security.SSLCreateContext.argtypes = [ + CFAllocatorRef, + SSLProtocolSide, + SSLConnectionType + ] + Security.SSLCreateContext.restype = SSLContextRef + + Security.SSLSetSessionOption.argtypes = [ + SSLContextRef, + SSLSessionOption, + Boolean + ] + Security.SSLSetSessionOption.restype = OSStatus + + Security.SSLSetProtocolVersionMin.argtypes = [ + SSLContextRef, + SSLProtocol + ] + Security.SSLSetProtocolVersionMin.restype = OSStatus + + Security.SSLSetProtocolVersionMax.argtypes = [ + SSLContextRef, + SSLProtocol + ] + Security.SSLSetProtocolVersionMax.restype = OSStatus + + Security.SecCopyErrorMessageString.argtypes = [ + OSStatus, + c_void_p + ] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SSLReadFunc = SSLReadFunc + Security.SSLWriteFunc = SSLWriteFunc + Security.SSLContextRef = SSLContextRef + Security.SSLProtocol = SSLProtocol + Security.SSLCipherSuite = SSLCipherSuite + Security.SecIdentityRef = SecIdentityRef + Security.SecKeychainRef = SecKeychainRef + Security.SecTrustRef = SecTrustRef + Security.SecTrustResultType = SecTrustResultType + Security.SecExternalFormat = SecExternalFormat + Security.OSStatus = OSStatus + + Security.kSecImportExportPassphrase = CFStringRef.in_dll( + Security, 'kSecImportExportPassphrase' + ) + Security.kSecImportItemIdentity = CFStringRef.in_dll( + Security, 'kSecImportItemIdentity' + ) + + # CoreFoundation time! + CoreFoundation.CFRetain.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFRetain.restype = CFTypeRef + + CoreFoundation.CFRelease.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFRelease.restype = None + + CoreFoundation.CFGetTypeID.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFGetTypeID.restype = CFTypeID + + CoreFoundation.CFStringCreateWithCString.argtypes = [ + CFAllocatorRef, + c_char_p, + CFStringEncoding + ] + CoreFoundation.CFStringCreateWithCString.restype = CFStringRef + + CoreFoundation.CFStringGetCStringPtr.argtypes = [ + CFStringRef, + CFStringEncoding + ] + CoreFoundation.CFStringGetCStringPtr.restype = c_char_p + + CoreFoundation.CFStringGetCString.argtypes = [ + CFStringRef, + c_char_p, + CFIndex, + CFStringEncoding + ] + CoreFoundation.CFStringGetCString.restype = c_bool + + CoreFoundation.CFDataCreate.argtypes = [ + CFAllocatorRef, + c_char_p, + CFIndex + ] + CoreFoundation.CFDataCreate.restype = CFDataRef + + CoreFoundation.CFDataGetLength.argtypes = [ + CFDataRef + ] + CoreFoundation.CFDataGetLength.restype = CFIndex + + CoreFoundation.CFDataGetBytePtr.argtypes = [ + CFDataRef + ] + CoreFoundation.CFDataGetBytePtr.restype = c_void_p + + CoreFoundation.CFDictionaryCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + POINTER(CFTypeRef), + CFIndex, + CFDictionaryKeyCallBacks, + CFDictionaryValueCallBacks + ] + CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef + + CoreFoundation.CFDictionaryGetValue.argtypes = [ + CFDictionaryRef, + CFTypeRef + ] + CoreFoundation.CFDictionaryGetValue.restype = CFTypeRef + + CoreFoundation.CFArrayCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + CFIndex, + CFArrayCallBacks, + ] + CoreFoundation.CFArrayCreate.restype = CFArrayRef + + CoreFoundation.CFArrayCreateMutable.argtypes = [ + CFAllocatorRef, + CFIndex, + CFArrayCallBacks + ] + CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef + + CoreFoundation.CFArrayAppendValue.argtypes = [ + CFMutableArrayRef, + c_void_p + ] + CoreFoundation.CFArrayAppendValue.restype = None + + CoreFoundation.CFArrayGetCount.argtypes = [ + CFArrayRef + ] + CoreFoundation.CFArrayGetCount.restype = CFIndex + + CoreFoundation.CFArrayGetValueAtIndex.argtypes = [ + CFArrayRef, + CFIndex + ] + CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p + + CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( + CoreFoundation, 'kCFAllocatorDefault' + ) + CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll(CoreFoundation, 'kCFTypeArrayCallBacks') + CoreFoundation.kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll( + CoreFoundation, 'kCFTypeDictionaryKeyCallBacks' + ) + CoreFoundation.kCFTypeDictionaryValueCallBacks = c_void_p.in_dll( + CoreFoundation, 'kCFTypeDictionaryValueCallBacks' + ) + + CoreFoundation.CFTypeRef = CFTypeRef + CoreFoundation.CFArrayRef = CFArrayRef + CoreFoundation.CFStringRef = CFStringRef + CoreFoundation.CFDictionaryRef = CFDictionaryRef + +except (AttributeError): + raise ImportError('Error initializing ctypes') + + +class CFConst(object): + """ + A class object that acts as essentially a namespace for CoreFoundation + constants. + """ + kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) + + +class SecurityConst(object): + """ + A class object that acts as essentially a namespace for Security constants. + """ + kSSLSessionOptionBreakOnServerAuth = 0 + + kSSLProtocol2 = 1 + kSSLProtocol3 = 2 + kTLSProtocol1 = 4 + kTLSProtocol11 = 7 + kTLSProtocol12 = 8 + + kSSLClientSide = 1 + kSSLStreamType = 0 + + kSecFormatPEMSequence = 10 + + kSecTrustResultInvalid = 0 + kSecTrustResultProceed = 1 + # This gap is present on purpose: this was kSecTrustResultConfirm, which + # is deprecated. + kSecTrustResultDeny = 3 + kSecTrustResultUnspecified = 4 + kSecTrustResultRecoverableTrustFailure = 5 + kSecTrustResultFatalTrustFailure = 6 + kSecTrustResultOtherError = 7 + + errSSLProtocol = -9800 + errSSLWouldBlock = -9803 + errSSLClosedGraceful = -9805 + errSSLClosedNoNotify = -9816 + errSSLClosedAbort = -9806 + + errSSLXCertChainInvalid = -9807 + errSSLCrypto = -9809 + errSSLInternal = -9810 + errSSLCertExpired = -9814 + errSSLCertNotYetValid = -9815 + errSSLUnknownRootCert = -9812 + errSSLNoRootCert = -9813 + errSSLHostNameMismatch = -9843 + errSSLPeerHandshakeFail = -9824 + errSSLPeerUserCancelled = -9839 + errSSLWeakPeerEphemeralDHKey = -9850 + errSSLServerAuthCompleted = -9841 + errSSLRecordOverflow = -9847 + + errSecVerifyFailed = -67808 + errSecNoTrustSettings = -25263 + errSecItemNotFound = -25300 + errSecInvalidTrustSettings = -25262 + + # Cipher suites. We only pick the ones our default cipher string allows. + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030 + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F + TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3 + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F + TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2 + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B + TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A + TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 + TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 + TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 + TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032 + TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C + TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D + TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C + TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 + TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F + TLS_AES_128_GCM_SHA256 = 0x1301 + TLS_AES_256_GCM_SHA384 = 0x1302 + TLS_CHACHA20_POLY1305_SHA256 = 0x1303 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py new file mode 100644 index 0000000..b13cd9e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py @@ -0,0 +1,346 @@ +""" +Low-level helpers for the SecureTransport bindings. + +These are Python functions that are not directly related to the high-level APIs +but are necessary to get them to work. They include a whole bunch of low-level +CoreFoundation messing about and memory management. The concerns in this module +are almost entirely about trying to avoid memory leaks and providing +appropriate and useful assistance to the higher-level code. +""" +import base64 +import ctypes +import itertools +import re +import os +import ssl +import tempfile + +from .bindings import Security, CoreFoundation, CFConst + + +# This regular expression is used to grab PEM data out of a PEM bundle. +_PEM_CERTS_RE = re.compile( + b"-----BEGIN CERTIFICATE-----\n(.*?)\n-----END CERTIFICATE-----", re.DOTALL +) + + +def _cf_data_from_bytes(bytestring): + """ + Given a bytestring, create a CFData object from it. This CFData object must + be CFReleased by the caller. + """ + return CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, bytestring, len(bytestring) + ) + + +def _cf_dictionary_from_tuples(tuples): + """ + Given a list of Python tuples, create an associated CFDictionary. + """ + dictionary_size = len(tuples) + + # We need to get the dictionary keys and values out in the same order. + keys = (t[0] for t in tuples) + values = (t[1] for t in tuples) + cf_keys = (CoreFoundation.CFTypeRef * dictionary_size)(*keys) + cf_values = (CoreFoundation.CFTypeRef * dictionary_size)(*values) + + return CoreFoundation.CFDictionaryCreate( + CoreFoundation.kCFAllocatorDefault, + cf_keys, + cf_values, + dictionary_size, + CoreFoundation.kCFTypeDictionaryKeyCallBacks, + CoreFoundation.kCFTypeDictionaryValueCallBacks, + ) + + +def _cf_string_to_unicode(value): + """ + Creates a Unicode string from a CFString object. Used entirely for error + reporting. + + Yes, it annoys me quite a lot that this function is this complex. + """ + value_as_void_p = ctypes.cast(value, ctypes.POINTER(ctypes.c_void_p)) + + string = CoreFoundation.CFStringGetCStringPtr( + value_as_void_p, + CFConst.kCFStringEncodingUTF8 + ) + if string is None: + buffer = ctypes.create_string_buffer(1024) + result = CoreFoundation.CFStringGetCString( + value_as_void_p, + buffer, + 1024, + CFConst.kCFStringEncodingUTF8 + ) + if not result: + raise OSError('Error copying C string from CFStringRef') + string = buffer.value + if string is not None: + string = string.decode('utf-8') + return string + + +def _assert_no_error(error, exception_class=None): + """ + Checks the return code and throws an exception if there is an error to + report + """ + if error == 0: + return + + cf_error_string = Security.SecCopyErrorMessageString(error, None) + output = _cf_string_to_unicode(cf_error_string) + CoreFoundation.CFRelease(cf_error_string) + + if output is None or output == u'': + output = u'OSStatus %s' % error + + if exception_class is None: + exception_class = ssl.SSLError + + raise exception_class(output) + + +def _cert_array_from_pem(pem_bundle): + """ + Given a bundle of certs in PEM format, turns them into a CFArray of certs + that can be used to validate a cert chain. + """ + # Normalize the PEM bundle's line endings. + pem_bundle = pem_bundle.replace(b"\r\n", b"\n") + + der_certs = [ + base64.b64decode(match.group(1)) + for match in _PEM_CERTS_RE.finditer(pem_bundle) + ] + if not der_certs: + raise ssl.SSLError("No root certificates specified") + + cert_array = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks) + ) + if not cert_array: + raise ssl.SSLError("Unable to allocate memory!") + + try: + for der_bytes in der_certs: + certdata = _cf_data_from_bytes(der_bytes) + if not certdata: + raise ssl.SSLError("Unable to allocate memory!") + cert = Security.SecCertificateCreateWithData( + CoreFoundation.kCFAllocatorDefault, certdata + ) + CoreFoundation.CFRelease(certdata) + if not cert: + raise ssl.SSLError("Unable to build cert object!") + + CoreFoundation.CFArrayAppendValue(cert_array, cert) + CoreFoundation.CFRelease(cert) + except Exception: + # We need to free the array before the exception bubbles further. + # We only want to do that if an error occurs: otherwise, the caller + # should free. + CoreFoundation.CFRelease(cert_array) + + return cert_array + + +def _is_cert(item): + """ + Returns True if a given CFTypeRef is a certificate. + """ + expected = Security.SecCertificateGetTypeID() + return CoreFoundation.CFGetTypeID(item) == expected + + +def _is_identity(item): + """ + Returns True if a given CFTypeRef is an identity. + """ + expected = Security.SecIdentityGetTypeID() + return CoreFoundation.CFGetTypeID(item) == expected + + +def _temporary_keychain(): + """ + This function creates a temporary Mac keychain that we can use to work with + credentials. This keychain uses a one-time password and a temporary file to + store the data. We expect to have one keychain per socket. The returned + SecKeychainRef must be freed by the caller, including calling + SecKeychainDelete. + + Returns a tuple of the SecKeychainRef and the path to the temporary + directory that contains it. + """ + # Unfortunately, SecKeychainCreate requires a path to a keychain. This + # means we cannot use mkstemp to use a generic temporary file. Instead, + # we're going to create a temporary directory and a filename to use there. + # This filename will be 8 random bytes expanded into base64. We also need + # some random bytes to password-protect the keychain we're creating, so we + # ask for 40 random bytes. + random_bytes = os.urandom(40) + filename = base64.b16encode(random_bytes[:8]).decode('utf-8') + password = base64.b16encode(random_bytes[8:]) # Must be valid UTF-8 + tempdirectory = tempfile.mkdtemp() + + keychain_path = os.path.join(tempdirectory, filename).encode('utf-8') + + # We now want to create the keychain itself. + keychain = Security.SecKeychainRef() + status = Security.SecKeychainCreate( + keychain_path, + len(password), + password, + False, + None, + ctypes.byref(keychain) + ) + _assert_no_error(status) + + # Having created the keychain, we want to pass it off to the caller. + return keychain, tempdirectory + + +def _load_items_from_file(keychain, path): + """ + Given a single file, loads all the trust objects from it into arrays and + the keychain. + Returns a tuple of lists: the first list is a list of identities, the + second a list of certs. + """ + certificates = [] + identities = [] + result_array = None + + with open(path, 'rb') as f: + raw_filedata = f.read() + + try: + filedata = CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, + raw_filedata, + len(raw_filedata) + ) + result_array = CoreFoundation.CFArrayRef() + result = Security.SecItemImport( + filedata, # cert data + None, # Filename, leaving it out for now + None, # What the type of the file is, we don't care + None, # what's in the file, we don't care + 0, # import flags + None, # key params, can include passphrase in the future + keychain, # The keychain to insert into + ctypes.byref(result_array) # Results + ) + _assert_no_error(result) + + # A CFArray is not very useful to us as an intermediary + # representation, so we are going to extract the objects we want + # and then free the array. We don't need to keep hold of keys: the + # keychain already has them! + result_count = CoreFoundation.CFArrayGetCount(result_array) + for index in range(result_count): + item = CoreFoundation.CFArrayGetValueAtIndex( + result_array, index + ) + item = ctypes.cast(item, CoreFoundation.CFTypeRef) + + if _is_cert(item): + CoreFoundation.CFRetain(item) + certificates.append(item) + elif _is_identity(item): + CoreFoundation.CFRetain(item) + identities.append(item) + finally: + if result_array: + CoreFoundation.CFRelease(result_array) + + CoreFoundation.CFRelease(filedata) + + return (identities, certificates) + + +def _load_client_cert_chain(keychain, *paths): + """ + Load certificates and maybe keys from a number of files. Has the end goal + of returning a CFArray containing one SecIdentityRef, and then zero or more + SecCertificateRef objects, suitable for use as a client certificate trust + chain. + """ + # Ok, the strategy. + # + # This relies on knowing that macOS will not give you a SecIdentityRef + # unless you have imported a key into a keychain. This is a somewhat + # artificial limitation of macOS (for example, it doesn't necessarily + # affect iOS), but there is nothing inside Security.framework that lets you + # get a SecIdentityRef without having a key in a keychain. + # + # So the policy here is we take all the files and iterate them in order. + # Each one will use SecItemImport to have one or more objects loaded from + # it. We will also point at a keychain that macOS can use to work with the + # private key. + # + # Once we have all the objects, we'll check what we actually have. If we + # already have a SecIdentityRef in hand, fab: we'll use that. Otherwise, + # we'll take the first certificate (which we assume to be our leaf) and + # ask the keychain to give us a SecIdentityRef with that cert's associated + # key. + # + # We'll then return a CFArray containing the trust chain: one + # SecIdentityRef and then zero-or-more SecCertificateRef objects. The + # responsibility for freeing this CFArray will be with the caller. This + # CFArray must remain alive for the entire connection, so in practice it + # will be stored with a single SSLSocket, along with the reference to the + # keychain. + certificates = [] + identities = [] + + # Filter out bad paths. + paths = (path for path in paths if path) + + try: + for file_path in paths: + new_identities, new_certs = _load_items_from_file( + keychain, file_path + ) + identities.extend(new_identities) + certificates.extend(new_certs) + + # Ok, we have everything. The question is: do we have an identity? If + # not, we want to grab one from the first cert we have. + if not identities: + new_identity = Security.SecIdentityRef() + status = Security.SecIdentityCreateWithCertificate( + keychain, + certificates[0], + ctypes.byref(new_identity) + ) + _assert_no_error(status) + identities.append(new_identity) + + # We now want to release the original certificate, as we no longer + # need it. + CoreFoundation.CFRelease(certificates.pop(0)) + + # We now need to build a new CFArray that holds the trust chain. + trust_chain = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + for item in itertools.chain(identities, certificates): + # ArrayAppendValue does a CFRetain on the item. That's fine, + # because the finally block will release our other refs to them. + CoreFoundation.CFArrayAppendValue(trust_chain, item) + + return trust_chain + finally: + for obj in itertools.chain(identities, certificates): + CoreFoundation.CFRelease(obj) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py new file mode 100644 index 0000000..59f2a61 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/appengine.py @@ -0,0 +1,305 @@ +""" +This module provides a pool manager that uses Google App Engine's +`URLFetch Service <https://cloud.google.com/appengine/docs/python/urlfetch>`_. + +Example usage:: + + from pip._vendor.urllib3 import PoolManager + from pip._vendor.urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox + + if is_appengine_sandbox(): + # AppEngineManager uses AppEngine's URLFetch API behind the scenes + http = AppEngineManager() + else: + # PoolManager uses a socket-level API behind the scenes + http = PoolManager() + + r = http.request('GET', 'https://google.com/') + +There are `limitations <https://cloud.google.com/appengine/docs/python/\ +urlfetch/#Python_Quotas_and_limits>`_ to the URLFetch service and it may not be +the best choice for your application. There are three options for using +urllib3 on Google App Engine: + +1. You can use :class:`AppEngineManager` with URLFetch. URLFetch is + cost-effective in many circumstances as long as your usage is within the + limitations. +2. You can use a normal :class:`~urllib3.PoolManager` by enabling sockets. + Sockets also have `limitations and restrictions + <https://cloud.google.com/appengine/docs/python/sockets/\ + #limitations-and-restrictions>`_ and have a lower free quota than URLFetch. + To use sockets, be sure to specify the following in your ``app.yaml``:: + + env_variables: + GAE_USE_SOCKETS_HTTPLIB : 'true' + +3. If you are using `App Engine Flexible +<https://cloud.google.com/appengine/docs/flexible/>`_, you can use the standard +:class:`PoolManager` without any configuration or special environment variables. +""" + +from __future__ import absolute_import +import logging +import os +import warnings +from ..packages.six.moves.urllib.parse import urljoin + +from ..exceptions import ( + HTTPError, + HTTPWarning, + MaxRetryError, + ProtocolError, + TimeoutError, + SSLError +) + +from ..packages.six import BytesIO +from ..request import RequestMethods +from ..response import HTTPResponse +from ..util.timeout import Timeout +from ..util.retry import Retry + +try: + from google.appengine.api import urlfetch +except ImportError: + urlfetch = None + + +log = logging.getLogger(__name__) + + +class AppEnginePlatformWarning(HTTPWarning): + pass + + +class AppEnginePlatformError(HTTPError): + pass + + +class AppEngineManager(RequestMethods): + """ + Connection manager for Google App Engine sandbox applications. + + This manager uses the URLFetch service directly instead of using the + emulated httplib, and is subject to URLFetch limitations as described in + the App Engine documentation `here + <https://cloud.google.com/appengine/docs/python/urlfetch>`_. + + Notably it will raise an :class:`AppEnginePlatformError` if: + * URLFetch is not available. + * If you attempt to use this on App Engine Flexible, as full socket + support is available. + * If a request size is more than 10 megabytes. + * If a response size is more than 32 megabtyes. + * If you use an unsupported request method such as OPTIONS. + + Beyond those cases, it will raise normal urllib3 errors. + """ + + def __init__(self, headers=None, retries=None, validate_certificate=True, + urlfetch_retries=True): + if not urlfetch: + raise AppEnginePlatformError( + "URLFetch is not available in this environment.") + + if is_prod_appengine_mvms(): + raise AppEnginePlatformError( + "Use normal urllib3.PoolManager instead of AppEngineManager" + "on Managed VMs, as using URLFetch is not necessary in " + "this environment.") + + warnings.warn( + "urllib3 is using URLFetch on Google App Engine sandbox instead " + "of sockets. To use sockets directly instead of URLFetch see " + "https://urllib3.readthedocs.io/en/latest/reference/urllib3.contrib.html.", + AppEnginePlatformWarning) + + RequestMethods.__init__(self, headers) + self.validate_certificate = validate_certificate + self.urlfetch_retries = urlfetch_retries + + self.retries = retries or Retry.DEFAULT + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + # Return False to re-raise any potential exceptions + return False + + def urlopen(self, method, url, body=None, headers=None, + retries=None, redirect=True, timeout=Timeout.DEFAULT_TIMEOUT, + **response_kw): + + retries = self._get_retries(retries, redirect) + + try: + follow_redirects = ( + redirect and + retries.redirect != 0 and + retries.total) + response = urlfetch.fetch( + url, + payload=body, + method=method, + headers=headers or {}, + allow_truncated=False, + follow_redirects=self.urlfetch_retries and follow_redirects, + deadline=self._get_absolute_timeout(timeout), + validate_certificate=self.validate_certificate, + ) + except urlfetch.DeadlineExceededError as e: + raise TimeoutError(self, e) + + except urlfetch.InvalidURLError as e: + if 'too large' in str(e): + raise AppEnginePlatformError( + "URLFetch request too large, URLFetch only " + "supports requests up to 10mb in size.", e) + raise ProtocolError(e) + + except urlfetch.DownloadError as e: + if 'Too many redirects' in str(e): + raise MaxRetryError(self, url, reason=e) + raise ProtocolError(e) + + except urlfetch.ResponseTooLargeError as e: + raise AppEnginePlatformError( + "URLFetch response too large, URLFetch only supports" + "responses up to 32mb in size.", e) + + except urlfetch.SSLCertificateError as e: + raise SSLError(e) + + except urlfetch.InvalidMethodError as e: + raise AppEnginePlatformError( + "URLFetch does not support method: %s" % method, e) + + http_response = self._urlfetch_response_to_http_response( + response, retries=retries, **response_kw) + + # Handle redirect? + redirect_location = redirect and http_response.get_redirect_location() + if redirect_location: + # Check for redirect response + if (self.urlfetch_retries and retries.raise_on_redirect): + raise MaxRetryError(self, url, "too many redirects") + else: + if http_response.status == 303: + method = 'GET' + + try: + retries = retries.increment(method, url, response=http_response, _pool=self) + except MaxRetryError: + if retries.raise_on_redirect: + raise MaxRetryError(self, url, "too many redirects") + return http_response + + retries.sleep_for_retry(http_response) + log.debug("Redirecting %s -> %s", url, redirect_location) + redirect_url = urljoin(url, redirect_location) + return self.urlopen( + method, redirect_url, body, headers, + retries=retries, redirect=redirect, + timeout=timeout, **response_kw) + + # Check if we should retry the HTTP response. + has_retry_after = bool(http_response.getheader('Retry-After')) + if retries.is_retry(method, http_response.status, has_retry_after): + retries = retries.increment( + method, url, response=http_response, _pool=self) + log.debug("Retry: %s", url) + retries.sleep(http_response) + return self.urlopen( + method, url, + body=body, headers=headers, + retries=retries, redirect=redirect, + timeout=timeout, **response_kw) + + return http_response + + def _urlfetch_response_to_http_response(self, urlfetch_resp, **response_kw): + + if is_prod_appengine(): + # Production GAE handles deflate encoding automatically, but does + # not remove the encoding header. + content_encoding = urlfetch_resp.headers.get('content-encoding') + + if content_encoding == 'deflate': + del urlfetch_resp.headers['content-encoding'] + + transfer_encoding = urlfetch_resp.headers.get('transfer-encoding') + # We have a full response's content, + # so let's make sure we don't report ourselves as chunked data. + if transfer_encoding == 'chunked': + encodings = transfer_encoding.split(",") + encodings.remove('chunked') + urlfetch_resp.headers['transfer-encoding'] = ','.join(encodings) + + original_response = HTTPResponse( + # In order for decoding to work, we must present the content as + # a file-like object. + body=BytesIO(urlfetch_resp.content), + msg=urlfetch_resp.header_msg, + headers=urlfetch_resp.headers, + status=urlfetch_resp.status_code, + **response_kw + ) + + return HTTPResponse( + body=BytesIO(urlfetch_resp.content), + headers=urlfetch_resp.headers, + status=urlfetch_resp.status_code, + original_response=original_response, + **response_kw + ) + + def _get_absolute_timeout(self, timeout): + if timeout is Timeout.DEFAULT_TIMEOUT: + return None # Defer to URLFetch's default. + if isinstance(timeout, Timeout): + if timeout._read is not None or timeout._connect is not None: + warnings.warn( + "URLFetch does not support granular timeout settings, " + "reverting to total or default URLFetch timeout.", + AppEnginePlatformWarning) + return timeout.total + return timeout + + def _get_retries(self, retries, redirect): + if not isinstance(retries, Retry): + retries = Retry.from_int( + retries, redirect=redirect, default=self.retries) + + if retries.connect or retries.read or retries.redirect: + warnings.warn( + "URLFetch only supports total retries and does not " + "recognize connect, read, or redirect retry parameters.", + AppEnginePlatformWarning) + + return retries + + +def is_appengine(): + return (is_local_appengine() or + is_prod_appengine() or + is_prod_appengine_mvms()) + + +def is_appengine_sandbox(): + return is_appengine() and not is_prod_appengine_mvms() + + +def is_local_appengine(): + return ('APPENGINE_RUNTIME' in os.environ and + 'Development/' in os.environ['SERVER_SOFTWARE']) + + +def is_prod_appengine(): + return ('APPENGINE_RUNTIME' in os.environ and + 'Google App Engine/' in os.environ['SERVER_SOFTWARE'] and + not is_prod_appengine_mvms()) + + +def is_prod_appengine_mvms(): + return os.environ.get('GAE_VM', False) == 'true' diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py new file mode 100644 index 0000000..642e99e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py @@ -0,0 +1,112 @@ +""" +NTLM authenticating pool, contributed by erikcederstran + +Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10 +""" +from __future__ import absolute_import + +from logging import getLogger +from ntlm import ntlm + +from .. import HTTPSConnectionPool +from ..packages.six.moves.http_client import HTTPSConnection + + +log = getLogger(__name__) + + +class NTLMConnectionPool(HTTPSConnectionPool): + """ + Implements an NTLM authentication version of an urllib3 connection pool + """ + + scheme = 'https' + + def __init__(self, user, pw, authurl, *args, **kwargs): + """ + authurl is a random URL on the server that is protected by NTLM. + user is the Windows user, probably in the DOMAIN\\username format. + pw is the password for the user. + """ + super(NTLMConnectionPool, self).__init__(*args, **kwargs) + self.authurl = authurl + self.rawuser = user + user_parts = user.split('\\', 1) + self.domain = user_parts[0].upper() + self.user = user_parts[1] + self.pw = pw + + def _new_conn(self): + # Performs the NTLM handshake that secures the connection. The socket + # must be kept open while requests are performed. + self.num_connections += 1 + log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s', + self.num_connections, self.host, self.authurl) + + headers = {} + headers['Connection'] = 'Keep-Alive' + req_header = 'Authorization' + resp_header = 'www-authenticate' + + conn = HTTPSConnection(host=self.host, port=self.port) + + # Send negotiation message + headers[req_header] = ( + 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) + log.debug('Request headers: %s', headers) + conn.request('GET', self.authurl, None, headers) + res = conn.getresponse() + reshdr = dict(res.getheaders()) + log.debug('Response status: %s %s', res.status, res.reason) + log.debug('Response headers: %s', reshdr) + log.debug('Response data: %s [...]', res.read(100)) + + # Remove the reference to the socket, so that it can not be closed by + # the response object (we want to keep the socket open) + res.fp = None + + # Server should respond with a challenge message + auth_header_values = reshdr[resp_header].split(', ') + auth_header_value = None + for s in auth_header_values: + if s[:5] == 'NTLM ': + auth_header_value = s[5:] + if auth_header_value is None: + raise Exception('Unexpected %s response header: %s' % + (resp_header, reshdr[resp_header])) + + # Send authentication message + ServerChallenge, NegotiateFlags = \ + ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) + auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, + self.user, + self.domain, + self.pw, + NegotiateFlags) + headers[req_header] = 'NTLM %s' % auth_msg + log.debug('Request headers: %s', headers) + conn.request('GET', self.authurl, None, headers) + res = conn.getresponse() + log.debug('Response status: %s %s', res.status, res.reason) + log.debug('Response headers: %s', dict(res.getheaders())) + log.debug('Response data: %s [...]', res.read()[:100]) + if res.status != 200: + if res.status == 401: + raise Exception('Server rejected request: wrong ' + 'username or password') + raise Exception('Wrong server response: %s %s' % + (res.status, res.reason)) + + res.fp = None + log.debug('Connection established') + return conn + + def urlopen(self, method, url, body=None, headers=None, retries=3, + redirect=True, assert_same_host=True): + if headers is None: + headers = {} + headers['Connection'] = 'Keep-Alive' + return super(NTLMConnectionPool, self).urlopen(method, url, body, + headers, retries, + redirect, + assert_same_host) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py new file mode 100644 index 0000000..6dd3a01 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py @@ -0,0 +1,457 @@ +""" +SSL with SNI_-support for Python 2. Follow these instructions if you would +like to verify SSL certificates in Python 2. Note, the default libraries do +*not* do certificate checking; you need to do additional work to validate +certificates yourself. + +This needs the following packages installed: + +* pyOpenSSL (tested with 16.0.0) +* cryptography (minimum 1.3.4, from pyopenssl) +* idna (minimum 2.0, from cryptography) + +However, pyopenssl depends on cryptography, which depends on idna, so while we +use all three directly here we end up having relatively few packages required. + +You can install them with the following command: + + pip install pyopenssl cryptography idna + +To activate certificate checking, call +:func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code +before you begin making HTTP requests. This can be done in a ``sitecustomize`` +module, or at any other time before your application begins using ``urllib3``, +like this:: + + try: + import urllib3.contrib.pyopenssl + urllib3.contrib.pyopenssl.inject_into_urllib3() + except ImportError: + pass + +Now you can use :mod:`urllib3` as you normally would, and it will support SNI +when the required modules are installed. + +Activating this module also has the positive side effect of disabling SSL/TLS +compression in Python 2 (see `CRIME attack`_). + +If you want to configure the default list of supported cipher suites, you can +set the ``urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST`` variable. + +.. _sni: https://en.wikipedia.org/wiki/Server_Name_Indication +.. _crime attack: https://en.wikipedia.org/wiki/CRIME_(security_exploit) +""" +from __future__ import absolute_import + +import OpenSSL.SSL +from cryptography import x509 +from cryptography.hazmat.backends.openssl import backend as openssl_backend +from cryptography.hazmat.backends.openssl.x509 import _Certificate +try: + from cryptography.x509 import UnsupportedExtension +except ImportError: + # UnsupportedExtension is gone in cryptography >= 2.1.0 + class UnsupportedExtension(Exception): + pass + +from socket import timeout, error as SocketError +from io import BytesIO + +try: # Platform-specific: Python 2 + from socket import _fileobject +except ImportError: # Platform-specific: Python 3 + _fileobject = None + from ..packages.backports.makefile import backport_makefile + +import logging +import ssl +from ..packages import six +import sys + +from .. import util + +__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] + +# SNI always works. +HAS_SNI = True + +# Map from urllib3 to PyOpenSSL compatible parameter-values. +_openssl_versions = { + ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, + ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, +} + +if hasattr(ssl, 'PROTOCOL_TLSv1_1') and hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'): + _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD + +if hasattr(ssl, 'PROTOCOL_TLSv1_2') and hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'): + _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD + +try: + _openssl_versions.update({ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD}) +except AttributeError: + pass + +_stdlib_to_openssl_verify = { + ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, + ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, + ssl.CERT_REQUIRED: + OpenSSL.SSL.VERIFY_PEER + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, +} +_openssl_to_stdlib_verify = dict( + (v, k) for k, v in _stdlib_to_openssl_verify.items() +) + +# OpenSSL will only write 16K at a time +SSL_WRITE_BLOCKSIZE = 16384 + +orig_util_HAS_SNI = util.HAS_SNI +orig_util_SSLContext = util.ssl_.SSLContext + + +log = logging.getLogger(__name__) + + +def inject_into_urllib3(): + 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.' + + _validate_dependencies_met() + + util.ssl_.SSLContext = PyOpenSSLContext + util.HAS_SNI = HAS_SNI + util.ssl_.HAS_SNI = HAS_SNI + util.IS_PYOPENSSL = True + util.ssl_.IS_PYOPENSSL = True + + +def extract_from_urllib3(): + 'Undo monkey-patching by :func:`inject_into_urllib3`.' + + util.ssl_.SSLContext = orig_util_SSLContext + util.HAS_SNI = orig_util_HAS_SNI + util.ssl_.HAS_SNI = orig_util_HAS_SNI + util.IS_PYOPENSSL = False + util.ssl_.IS_PYOPENSSL = False + + +def _validate_dependencies_met(): + """ + Verifies that PyOpenSSL's package-level dependencies have been met. + Throws `ImportError` if they are not met. + """ + # Method added in `cryptography==1.1`; not available in older versions + from cryptography.x509.extensions import Extensions + if getattr(Extensions, "get_extension_for_class", None) is None: + raise ImportError("'cryptography' module missing required functionality. " + "Try upgrading to v1.3.4 or newer.") + + # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509 + # attribute is only present on those versions. + from OpenSSL.crypto import X509 + x509 = X509() + if getattr(x509, "_x509", None) is None: + raise ImportError("'pyOpenSSL' module missing required functionality. " + "Try upgrading to v0.14 or newer.") + + +def _dnsname_to_stdlib(name): + """ + Converts a dNSName SubjectAlternativeName field to the form used by the + standard library on the given Python version. + + Cryptography produces a dNSName as a unicode string that was idna-decoded + from ASCII bytes. We need to idna-encode that string to get it back, and + then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib + uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8). + """ + def idna_encode(name): + """ + Borrowed wholesale from the Python Cryptography Project. It turns out + that we can't just safely call `idna.encode`: it can explode for + wildcard names. This avoids that problem. + """ + from pip._vendor import idna + + for prefix in [u'*.', u'.']: + if name.startswith(prefix): + name = name[len(prefix):] + return prefix.encode('ascii') + idna.encode(name) + return idna.encode(name) + + name = idna_encode(name) + if sys.version_info >= (3, 0): + name = name.decode('utf-8') + return name + + +def get_subj_alt_name(peer_cert): + """ + Given an PyOpenSSL certificate, provides all the subject alternative names. + """ + # Pass the cert to cryptography, which has much better APIs for this. + if hasattr(peer_cert, "to_cryptography"): + cert = peer_cert.to_cryptography() + else: + # This is technically using private APIs, but should work across all + # relevant versions before PyOpenSSL got a proper API for this. + cert = _Certificate(openssl_backend, peer_cert._x509) + + # We want to find the SAN extension. Ask Cryptography to locate it (it's + # faster than looping in Python) + try: + ext = cert.extensions.get_extension_for_class( + x509.SubjectAlternativeName + ).value + except x509.ExtensionNotFound: + # No such extension, return the empty list. + return [] + except (x509.DuplicateExtension, UnsupportedExtension, + x509.UnsupportedGeneralNameType, UnicodeError) as e: + # A problem has been found with the quality of the certificate. Assume + # no SAN field is present. + log.warning( + "A problem was encountered with the certificate that prevented " + "urllib3 from finding the SubjectAlternativeName field. This can " + "affect certificate validation. The error was %s", + e, + ) + return [] + + # We want to return dNSName and iPAddress fields. We need to cast the IPs + # back to strings because the match_hostname function wants them as + # strings. + # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8 + # decoded. This is pretty frustrating, but that's what the standard library + # does with certificates, and so we need to attempt to do the same. + names = [ + ('DNS', _dnsname_to_stdlib(name)) + for name in ext.get_values_for_type(x509.DNSName) + ] + names.extend( + ('IP Address', str(name)) + for name in ext.get_values_for_type(x509.IPAddress) + ) + + return names + + +class WrappedSocket(object): + '''API-compatibility wrapper for Python OpenSSL's Connection-class. + + Note: _makefile_refs, _drop() and _reuse() are needed for the garbage + collector of pypy. + ''' + + def __init__(self, connection, socket, suppress_ragged_eofs=True): + self.connection = connection + self.socket = socket + self.suppress_ragged_eofs = suppress_ragged_eofs + self._makefile_refs = 0 + self._closed = False + + def fileno(self): + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self): + if self._makefile_refs > 0: + self._makefile_refs -= 1 + if self._closed: + self.close() + + def recv(self, *args, **kwargs): + try: + data = self.connection.recv(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'): + return b'' + else: + raise SocketError(str(e)) + except OpenSSL.SSL.ZeroReturnError as e: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return b'' + else: + raise + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout('The read operation timed out') + else: + return self.recv(*args, **kwargs) + else: + return data + + def recv_into(self, *args, **kwargs): + try: + return self.connection.recv_into(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'): + return 0 + else: + raise SocketError(str(e)) + except OpenSSL.SSL.ZeroReturnError as e: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return 0 + else: + raise + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout('The read operation timed out') + else: + return self.recv_into(*args, **kwargs) + + def settimeout(self, timeout): + return self.socket.settimeout(timeout) + + def _send_until_done(self, data): + while True: + try: + return self.connection.send(data) + except OpenSSL.SSL.WantWriteError: + if not util.wait_for_write(self.socket, self.socket.gettimeout()): + raise timeout() + continue + except OpenSSL.SSL.SysCallError as e: + raise SocketError(str(e)) + + def sendall(self, data): + total_sent = 0 + while total_sent < len(data): + sent = self._send_until_done(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE]) + total_sent += sent + + def shutdown(self): + # FIXME rethrow compatible exceptions should we ever use this + self.connection.shutdown() + + def close(self): + if self._makefile_refs < 1: + try: + self._closed = True + return self.connection.close() + except OpenSSL.SSL.Error: + return + else: + self._makefile_refs -= 1 + + def getpeercert(self, binary_form=False): + x509 = self.connection.get_peer_certificate() + + if not x509: + return x509 + + if binary_form: + return OpenSSL.crypto.dump_certificate( + OpenSSL.crypto.FILETYPE_ASN1, + x509) + + return { + 'subject': ( + (('commonName', x509.get_subject().CN),), + ), + 'subjectAltName': get_subj_alt_name(x509) + } + + def _reuse(self): + self._makefile_refs += 1 + + def _drop(self): + if self._makefile_refs < 1: + self.close() + else: + self._makefile_refs -= 1 + + +if _fileobject: # Platform-specific: Python 2 + def makefile(self, mode, bufsize=-1): + self._makefile_refs += 1 + return _fileobject(self, mode, bufsize, close=True) +else: # Platform-specific: Python 3 + makefile = backport_makefile + +WrappedSocket.makefile = makefile + + +class PyOpenSSLContext(object): + """ + I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible + for translating the interface of the standard library ``SSLContext`` object + to calls into PyOpenSSL. + """ + def __init__(self, protocol): + self.protocol = _openssl_versions[protocol] + self._ctx = OpenSSL.SSL.Context(self.protocol) + self._options = 0 + self.check_hostname = False + + @property + def options(self): + return self._options + + @options.setter + def options(self, value): + self._options = value + self._ctx.set_options(value) + + @property + def verify_mode(self): + return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()] + + @verify_mode.setter + def verify_mode(self, value): + self._ctx.set_verify( + _stdlib_to_openssl_verify[value], + _verify_callback + ) + + def set_default_verify_paths(self): + self._ctx.set_default_verify_paths() + + def set_ciphers(self, ciphers): + if isinstance(ciphers, six.text_type): + ciphers = ciphers.encode('utf-8') + self._ctx.set_cipher_list(ciphers) + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + if cafile is not None: + cafile = cafile.encode('utf-8') + if capath is not None: + capath = capath.encode('utf-8') + self._ctx.load_verify_locations(cafile, capath) + if cadata is not None: + self._ctx.load_verify_locations(BytesIO(cadata)) + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._ctx.use_certificate_chain_file(certfile) + if password is not None: + self._ctx.set_passwd_cb(lambda max_length, prompt_twice, userdata: password) + self._ctx.use_privatekey_file(keyfile or certfile) + + def wrap_socket(self, sock, server_side=False, + do_handshake_on_connect=True, suppress_ragged_eofs=True, + server_hostname=None): + cnx = OpenSSL.SSL.Connection(self._ctx, sock) + + if isinstance(server_hostname, six.text_type): # Platform-specific: Python 3 + server_hostname = server_hostname.encode('utf-8') + + if server_hostname is not None: + cnx.set_tlsext_host_name(server_hostname) + + cnx.set_connect_state() + + while True: + try: + cnx.do_handshake() + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(sock, sock.gettimeout()): + raise timeout('select timed out') + continue + except OpenSSL.SSL.Error as e: + raise ssl.SSLError('bad handshake: %r' % e) + break + + return WrappedSocket(cnx, sock) + + +def _verify_callback(cnx, x509, err_no, err_depth, return_code): + return err_no == 0 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py new file mode 100644 index 0000000..77cb59e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/securetransport.py @@ -0,0 +1,804 @@ +""" +SecureTranport support for urllib3 via ctypes. + +This makes platform-native TLS available to urllib3 users on macOS without the +use of a compiler. This is an important feature because the Python Package +Index is moving to become a TLSv1.2-or-higher server, and the default OpenSSL +that ships with macOS is not capable of doing TLSv1.2. The only way to resolve +this is to give macOS users an alternative solution to the problem, and that +solution is to use SecureTransport. + +We use ctypes here because this solution must not require a compiler. That's +because pip is not allowed to require a compiler either. + +This is not intended to be a seriously long-term solution to this problem. +The hope is that PEP 543 will eventually solve this issue for us, at which +point we can retire this contrib module. But in the short term, we need to +solve the impending tire fire that is Python on Mac without this kind of +contrib module. So...here we are. + +To use this module, simply import and inject it:: + + import urllib3.contrib.securetransport + urllib3.contrib.securetransport.inject_into_urllib3() + +Happy TLSing! +""" +from __future__ import absolute_import + +import contextlib +import ctypes +import errno +import os.path +import shutil +import socket +import ssl +import threading +import weakref + +from .. import util +from ._securetransport.bindings import ( + Security, SecurityConst, CoreFoundation +) +from ._securetransport.low_level import ( + _assert_no_error, _cert_array_from_pem, _temporary_keychain, + _load_client_cert_chain +) + +try: # Platform-specific: Python 2 + from socket import _fileobject +except ImportError: # Platform-specific: Python 3 + _fileobject = None + from ..packages.backports.makefile import backport_makefile + +__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] + +# SNI always works +HAS_SNI = True + +orig_util_HAS_SNI = util.HAS_SNI +orig_util_SSLContext = util.ssl_.SSLContext + +# This dictionary is used by the read callback to obtain a handle to the +# calling wrapped socket. This is a pretty silly approach, but for now it'll +# do. I feel like I should be able to smuggle a handle to the wrapped socket +# directly in the SSLConnectionRef, but for now this approach will work I +# guess. +# +# We need to lock around this structure for inserts, but we don't do it for +# reads/writes in the callbacks. The reasoning here goes as follows: +# +# 1. It is not possible to call into the callbacks before the dictionary is +# populated, so once in the callback the id must be in the dictionary. +# 2. The callbacks don't mutate the dictionary, they only read from it, and +# so cannot conflict with any of the insertions. +# +# This is good: if we had to lock in the callbacks we'd drastically slow down +# the performance of this code. +_connection_refs = weakref.WeakValueDictionary() +_connection_ref_lock = threading.Lock() + +# Limit writes to 16kB. This is OpenSSL's limit, but we'll cargo-cult it over +# for no better reason than we need *a* limit, and this one is right there. +SSL_WRITE_BLOCKSIZE = 16384 + +# This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to +# individual cipher suites. We need to do this because this is how +# SecureTransport wants them. +CIPHER_SUITES = [ + SecurityConst.TLS_AES_256_GCM_SHA384, + SecurityConst.TLS_CHACHA20_POLY1305_SHA256, + SecurityConst.TLS_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA, +] + +# Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of +# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version. +_protocol_to_min_max = { + ssl.PROTOCOL_SSLv23: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12), +} + +if hasattr(ssl, "PROTOCOL_SSLv2"): + _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = ( + SecurityConst.kSSLProtocol2, SecurityConst.kSSLProtocol2 + ) +if hasattr(ssl, "PROTOCOL_SSLv3"): + _protocol_to_min_max[ssl.PROTOCOL_SSLv3] = ( + SecurityConst.kSSLProtocol3, SecurityConst.kSSLProtocol3 + ) +if hasattr(ssl, "PROTOCOL_TLSv1"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1] = ( + SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol1 + ) +if hasattr(ssl, "PROTOCOL_TLSv1_1"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = ( + SecurityConst.kTLSProtocol11, SecurityConst.kTLSProtocol11 + ) +if hasattr(ssl, "PROTOCOL_TLSv1_2"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = ( + SecurityConst.kTLSProtocol12, SecurityConst.kTLSProtocol12 + ) +if hasattr(ssl, "PROTOCOL_TLS"): + _protocol_to_min_max[ssl.PROTOCOL_TLS] = _protocol_to_min_max[ssl.PROTOCOL_SSLv23] + + +def inject_into_urllib3(): + """ + Monkey-patch urllib3 with SecureTransport-backed SSL-support. + """ + util.ssl_.SSLContext = SecureTransportContext + util.HAS_SNI = HAS_SNI + util.ssl_.HAS_SNI = HAS_SNI + util.IS_SECURETRANSPORT = True + util.ssl_.IS_SECURETRANSPORT = True + + +def extract_from_urllib3(): + """ + Undo monkey-patching by :func:`inject_into_urllib3`. + """ + util.ssl_.SSLContext = orig_util_SSLContext + util.HAS_SNI = orig_util_HAS_SNI + util.ssl_.HAS_SNI = orig_util_HAS_SNI + util.IS_SECURETRANSPORT = False + util.ssl_.IS_SECURETRANSPORT = False + + +def _read_callback(connection_id, data_buffer, data_length_pointer): + """ + SecureTransport read callback. This is called by ST to request that data + be returned from the socket. + """ + wrapped_socket = None + try: + wrapped_socket = _connection_refs.get(connection_id) + if wrapped_socket is None: + return SecurityConst.errSSLInternal + base_socket = wrapped_socket.socket + + requested_length = data_length_pointer[0] + + timeout = wrapped_socket.gettimeout() + error = None + read_count = 0 + + try: + while read_count < requested_length: + if timeout is None or timeout >= 0: + if not util.wait_for_read(base_socket, timeout): + raise socket.error(errno.EAGAIN, 'timed out') + + remaining = requested_length - read_count + buffer = (ctypes.c_char * remaining).from_address( + data_buffer + read_count + ) + chunk_size = base_socket.recv_into(buffer, remaining) + read_count += chunk_size + if not chunk_size: + if not read_count: + return SecurityConst.errSSLClosedGraceful + break + except (socket.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + data_length_pointer[0] = read_count + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedAbort + raise + + data_length_pointer[0] = read_count + + if read_count != requested_length: + return SecurityConst.errSSLWouldBlock + + return 0 + except Exception as e: + if wrapped_socket is not None: + wrapped_socket._exception = e + return SecurityConst.errSSLInternal + + +def _write_callback(connection_id, data_buffer, data_length_pointer): + """ + SecureTransport write callback. This is called by ST to request that data + actually be sent on the network. + """ + wrapped_socket = None + try: + wrapped_socket = _connection_refs.get(connection_id) + if wrapped_socket is None: + return SecurityConst.errSSLInternal + base_socket = wrapped_socket.socket + + bytes_to_write = data_length_pointer[0] + data = ctypes.string_at(data_buffer, bytes_to_write) + + timeout = wrapped_socket.gettimeout() + error = None + sent = 0 + + try: + while sent < bytes_to_write: + if timeout is None or timeout >= 0: + if not util.wait_for_write(base_socket, timeout): + raise socket.error(errno.EAGAIN, 'timed out') + chunk_sent = base_socket.send(data) + sent += chunk_sent + + # This has some needless copying here, but I'm not sure there's + # much value in optimising this data path. + data = data[chunk_sent:] + except (socket.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + data_length_pointer[0] = sent + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedAbort + raise + + data_length_pointer[0] = sent + + if sent != bytes_to_write: + return SecurityConst.errSSLWouldBlock + + return 0 + except Exception as e: + if wrapped_socket is not None: + wrapped_socket._exception = e + return SecurityConst.errSSLInternal + + +# We need to keep these two objects references alive: if they get GC'd while +# in use then SecureTransport could attempt to call a function that is in freed +# memory. That would be...uh...bad. Yeah, that's the word. Bad. +_read_callback_pointer = Security.SSLReadFunc(_read_callback) +_write_callback_pointer = Security.SSLWriteFunc(_write_callback) + + +class WrappedSocket(object): + """ + API-compatibility wrapper for Python's OpenSSL wrapped socket object. + + Note: _makefile_refs, _drop(), and _reuse() are needed for the garbage + collector of PyPy. + """ + def __init__(self, socket): + self.socket = socket + self.context = None + self._makefile_refs = 0 + self._closed = False + self._exception = None + self._keychain = None + self._keychain_dir = None + self._client_cert_chain = None + + # We save off the previously-configured timeout and then set it to + # zero. This is done because we use select and friends to handle the + # timeouts, but if we leave the timeout set on the lower socket then + # Python will "kindly" call select on that socket again for us. Avoid + # that by forcing the timeout to zero. + self._timeout = self.socket.gettimeout() + self.socket.settimeout(0) + + @contextlib.contextmanager + def _raise_on_error(self): + """ + A context manager that can be used to wrap calls that do I/O from + SecureTransport. If any of the I/O callbacks hit an exception, this + context manager will correctly propagate the exception after the fact. + This avoids silently swallowing those exceptions. + + It also correctly forces the socket closed. + """ + self._exception = None + + # We explicitly don't catch around this yield because in the unlikely + # event that an exception was hit in the block we don't want to swallow + # it. + yield + if self._exception is not None: + exception, self._exception = self._exception, None + self.close() + raise exception + + def _set_ciphers(self): + """ + Sets up the allowed ciphers. By default this matches the set in + util.ssl_.DEFAULT_CIPHERS, at least as supported by macOS. This is done + custom and doesn't allow changing at this time, mostly because parsing + OpenSSL cipher strings is going to be a freaking nightmare. + """ + ciphers = (Security.SSLCipherSuite * len(CIPHER_SUITES))(*CIPHER_SUITES) + result = Security.SSLSetEnabledCiphers( + self.context, ciphers, len(CIPHER_SUITES) + ) + _assert_no_error(result) + + def _custom_validate(self, verify, trust_bundle): + """ + Called when we have set custom validation. We do this in two cases: + first, when cert validation is entirely disabled; and second, when + using a custom trust DB. + """ + # If we disabled cert validation, just say: cool. + if not verify: + return + + # We want data in memory, so load it up. + if os.path.isfile(trust_bundle): + with open(trust_bundle, 'rb') as f: + trust_bundle = f.read() + + cert_array = None + trust = Security.SecTrustRef() + + try: + # Get a CFArray that contains the certs we want. + cert_array = _cert_array_from_pem(trust_bundle) + + # Ok, now the hard part. We want to get the SecTrustRef that ST has + # created for this connection, shove our CAs into it, tell ST to + # ignore everything else it knows, and then ask if it can build a + # chain. This is a buuuunch of code. + result = Security.SSLCopyPeerTrust( + self.context, ctypes.byref(trust) + ) + _assert_no_error(result) + if not trust: + raise ssl.SSLError("Failed to copy trust reference") + + result = Security.SecTrustSetAnchorCertificates(trust, cert_array) + _assert_no_error(result) + + result = Security.SecTrustSetAnchorCertificatesOnly(trust, True) + _assert_no_error(result) + + trust_result = Security.SecTrustResultType() + result = Security.SecTrustEvaluate( + trust, ctypes.byref(trust_result) + ) + _assert_no_error(result) + finally: + if trust: + CoreFoundation.CFRelease(trust) + + if cert_array is not None: + CoreFoundation.CFRelease(cert_array) + + # Ok, now we can look at what the result was. + successes = ( + SecurityConst.kSecTrustResultUnspecified, + SecurityConst.kSecTrustResultProceed + ) + if trust_result.value not in successes: + raise ssl.SSLError( + "certificate verify failed, error code: %d" % + trust_result.value + ) + + def handshake(self, + server_hostname, + verify, + trust_bundle, + min_version, + max_version, + client_cert, + client_key, + client_key_passphrase): + """ + Actually performs the TLS handshake. This is run automatically by + wrapped socket, and shouldn't be needed in user code. + """ + # First, we do the initial bits of connection setup. We need to create + # a context, set its I/O funcs, and set the connection reference. + self.context = Security.SSLCreateContext( + None, SecurityConst.kSSLClientSide, SecurityConst.kSSLStreamType + ) + result = Security.SSLSetIOFuncs( + self.context, _read_callback_pointer, _write_callback_pointer + ) + _assert_no_error(result) + + # Here we need to compute the handle to use. We do this by taking the + # id of self modulo 2**31 - 1. If this is already in the dictionary, we + # just keep incrementing by one until we find a free space. + with _connection_ref_lock: + handle = id(self) % 2147483647 + while handle in _connection_refs: + handle = (handle + 1) % 2147483647 + _connection_refs[handle] = self + + result = Security.SSLSetConnection(self.context, handle) + _assert_no_error(result) + + # If we have a server hostname, we should set that too. + if server_hostname: + if not isinstance(server_hostname, bytes): + server_hostname = server_hostname.encode('utf-8') + + result = Security.SSLSetPeerDomainName( + self.context, server_hostname, len(server_hostname) + ) + _assert_no_error(result) + + # Setup the ciphers. + self._set_ciphers() + + # Set the minimum and maximum TLS versions. + result = Security.SSLSetProtocolVersionMin(self.context, min_version) + _assert_no_error(result) + result = Security.SSLSetProtocolVersionMax(self.context, max_version) + _assert_no_error(result) + + # If there's a trust DB, we need to use it. We do that by telling + # SecureTransport to break on server auth. We also do that if we don't + # want to validate the certs at all: we just won't actually do any + # authing in that case. + if not verify or trust_bundle is not None: + result = Security.SSLSetSessionOption( + self.context, + SecurityConst.kSSLSessionOptionBreakOnServerAuth, + True + ) + _assert_no_error(result) + + # If there's a client cert, we need to use it. + if client_cert: + self._keychain, self._keychain_dir = _temporary_keychain() + self._client_cert_chain = _load_client_cert_chain( + self._keychain, client_cert, client_key + ) + result = Security.SSLSetCertificate( + self.context, self._client_cert_chain + ) + _assert_no_error(result) + + while True: + with self._raise_on_error(): + result = Security.SSLHandshake(self.context) + + if result == SecurityConst.errSSLWouldBlock: + raise socket.timeout("handshake timed out") + elif result == SecurityConst.errSSLServerAuthCompleted: + self._custom_validate(verify, trust_bundle) + continue + else: + _assert_no_error(result) + break + + def fileno(self): + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self): + if self._makefile_refs > 0: + self._makefile_refs -= 1 + if self._closed: + self.close() + + def recv(self, bufsiz): + buffer = ctypes.create_string_buffer(bufsiz) + bytes_read = self.recv_into(buffer, bufsiz) + data = buffer[:bytes_read] + return data + + def recv_into(self, buffer, nbytes=None): + # Read short on EOF. + if self._closed: + return 0 + + if nbytes is None: + nbytes = len(buffer) + + buffer = (ctypes.c_char * nbytes).from_buffer(buffer) + processed_bytes = ctypes.c_size_t(0) + + with self._raise_on_error(): + result = Security.SSLRead( + self.context, buffer, nbytes, ctypes.byref(processed_bytes) + ) + + # There are some result codes that we want to treat as "not always + # errors". Specifically, those are errSSLWouldBlock, + # errSSLClosedGraceful, and errSSLClosedNoNotify. + if (result == SecurityConst.errSSLWouldBlock): + # If we didn't process any bytes, then this was just a time out. + # However, we can get errSSLWouldBlock in situations when we *did* + # read some data, and in those cases we should just read "short" + # and return. + if processed_bytes.value == 0: + # Timed out, no data read. + raise socket.timeout("recv timed out") + elif result in (SecurityConst.errSSLClosedGraceful, SecurityConst.errSSLClosedNoNotify): + # The remote peer has closed this connection. We should do so as + # well. Note that we don't actually return here because in + # principle this could actually be fired along with return data. + # It's unlikely though. + self.close() + else: + _assert_no_error(result) + + # Ok, we read and probably succeeded. We should return whatever data + # was actually read. + return processed_bytes.value + + def settimeout(self, timeout): + self._timeout = timeout + + def gettimeout(self): + return self._timeout + + def send(self, data): + processed_bytes = ctypes.c_size_t(0) + + with self._raise_on_error(): + result = Security.SSLWrite( + self.context, data, len(data), ctypes.byref(processed_bytes) + ) + + if result == SecurityConst.errSSLWouldBlock and processed_bytes.value == 0: + # Timed out + raise socket.timeout("send timed out") + else: + _assert_no_error(result) + + # We sent, and probably succeeded. Tell them how much we sent. + return processed_bytes.value + + def sendall(self, data): + total_sent = 0 + while total_sent < len(data): + sent = self.send(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE]) + total_sent += sent + + def shutdown(self): + with self._raise_on_error(): + Security.SSLClose(self.context) + + def close(self): + # TODO: should I do clean shutdown here? Do I have to? + if self._makefile_refs < 1: + self._closed = True + if self.context: + CoreFoundation.CFRelease(self.context) + self.context = None + if self._client_cert_chain: + CoreFoundation.CFRelease(self._client_cert_chain) + self._client_cert_chain = None + if self._keychain: + Security.SecKeychainDelete(self._keychain) + CoreFoundation.CFRelease(self._keychain) + shutil.rmtree(self._keychain_dir) + self._keychain = self._keychain_dir = None + return self.socket.close() + else: + self._makefile_refs -= 1 + + def getpeercert(self, binary_form=False): + # Urgh, annoying. + # + # Here's how we do this: + # + # 1. Call SSLCopyPeerTrust to get hold of the trust object for this + # connection. + # 2. Call SecTrustGetCertificateAtIndex for index 0 to get the leaf. + # 3. To get the CN, call SecCertificateCopyCommonName and process that + # string so that it's of the appropriate type. + # 4. To get the SAN, we need to do something a bit more complex: + # a. Call SecCertificateCopyValues to get the data, requesting + # kSecOIDSubjectAltName. + # b. Mess about with this dictionary to try to get the SANs out. + # + # This is gross. Really gross. It's going to be a few hundred LoC extra + # just to repeat something that SecureTransport can *already do*. So my + # operating assumption at this time is that what we want to do is + # instead to just flag to urllib3 that it shouldn't do its own hostname + # validation when using SecureTransport. + if not binary_form: + raise ValueError( + "SecureTransport only supports dumping binary certs" + ) + trust = Security.SecTrustRef() + certdata = None + der_bytes = None + + try: + # Grab the trust store. + result = Security.SSLCopyPeerTrust( + self.context, ctypes.byref(trust) + ) + _assert_no_error(result) + if not trust: + # Probably we haven't done the handshake yet. No biggie. + return None + + cert_count = Security.SecTrustGetCertificateCount(trust) + if not cert_count: + # Also a case that might happen if we haven't handshaked. + # Handshook? Handshaken? + return None + + leaf = Security.SecTrustGetCertificateAtIndex(trust, 0) + assert leaf + + # Ok, now we want the DER bytes. + certdata = Security.SecCertificateCopyData(leaf) + assert certdata + + data_length = CoreFoundation.CFDataGetLength(certdata) + data_buffer = CoreFoundation.CFDataGetBytePtr(certdata) + der_bytes = ctypes.string_at(data_buffer, data_length) + finally: + if certdata: + CoreFoundation.CFRelease(certdata) + if trust: + CoreFoundation.CFRelease(trust) + + return der_bytes + + def _reuse(self): + self._makefile_refs += 1 + + def _drop(self): + if self._makefile_refs < 1: + self.close() + else: + self._makefile_refs -= 1 + + +if _fileobject: # Platform-specific: Python 2 + def makefile(self, mode, bufsize=-1): + self._makefile_refs += 1 + return _fileobject(self, mode, bufsize, close=True) +else: # Platform-specific: Python 3 + def makefile(self, mode="r", buffering=None, *args, **kwargs): + # We disable buffering with SecureTransport because it conflicts with + # the buffering that ST does internally (see issue #1153 for more). + buffering = 0 + return backport_makefile(self, mode, buffering, *args, **kwargs) + +WrappedSocket.makefile = makefile + + +class SecureTransportContext(object): + """ + I am a wrapper class for the SecureTransport library, to translate the + interface of the standard library ``SSLContext`` object to calls into + SecureTransport. + """ + def __init__(self, protocol): + self._min_version, self._max_version = _protocol_to_min_max[protocol] + self._options = 0 + self._verify = False + self._trust_bundle = None + self._client_cert = None + self._client_key = None + self._client_key_passphrase = None + + @property + def check_hostname(self): + """ + SecureTransport cannot have its hostname checking disabled. For more, + see the comment on getpeercert() in this file. + """ + return True + + @check_hostname.setter + def check_hostname(self, value): + """ + SecureTransport cannot have its hostname checking disabled. For more, + see the comment on getpeercert() in this file. + """ + pass + + @property + def options(self): + # TODO: Well, crap. + # + # So this is the bit of the code that is the most likely to cause us + # trouble. Essentially we need to enumerate all of the SSL options that + # users might want to use and try to see if we can sensibly translate + # them, or whether we should just ignore them. + return self._options + + @options.setter + def options(self, value): + # TODO: Update in line with above. + self._options = value + + @property + def verify_mode(self): + return ssl.CERT_REQUIRED if self._verify else ssl.CERT_NONE + + @verify_mode.setter + def verify_mode(self, value): + self._verify = True if value == ssl.CERT_REQUIRED else False + + def set_default_verify_paths(self): + # So, this has to do something a bit weird. Specifically, what it does + # is nothing. + # + # This means that, if we had previously had load_verify_locations + # called, this does not undo that. We need to do that because it turns + # out that the rest of the urllib3 code will attempt to load the + # default verify paths if it hasn't been told about any paths, even if + # the context itself was sometime earlier. We resolve that by just + # ignoring it. + pass + + def load_default_certs(self): + return self.set_default_verify_paths() + + def set_ciphers(self, ciphers): + # For now, we just require the default cipher string. + if ciphers != util.ssl_.DEFAULT_CIPHERS: + raise ValueError( + "SecureTransport doesn't support custom cipher strings" + ) + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + # OK, we only really support cadata and cafile. + if capath is not None: + raise ValueError( + "SecureTransport does not support cert directories" + ) + + self._trust_bundle = cafile or cadata + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._client_cert = certfile + self._client_key = keyfile + self._client_cert_passphrase = password + + def wrap_socket(self, sock, server_side=False, + do_handshake_on_connect=True, suppress_ragged_eofs=True, + server_hostname=None): + # So, what do we do here? Firstly, we assert some properties. This is a + # stripped down shim, so there is some functionality we don't support. + # See PEP 543 for the real deal. + assert not server_side + assert do_handshake_on_connect + assert suppress_ragged_eofs + + # Ok, we're good to go. Now we want to create the wrapped socket object + # and store it in the appropriate place. + wrapped_socket = WrappedSocket(sock) + + # Now we can handshake + wrapped_socket.handshake( + server_hostname, self._verify, self._trust_bundle, + self._min_version, self._max_version, self._client_cert, + self._client_key, self._client_key_passphrase + ) + return wrapped_socket diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/socks.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/socks.py new file mode 100644 index 0000000..811e312 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/contrib/socks.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +""" +This module contains provisional support for SOCKS proxies from within +urllib3. This module supports SOCKS4 (specifically the SOCKS4A variant) and +SOCKS5. To enable its functionality, either install PySocks or install this +module with the ``socks`` extra. + +The SOCKS implementation supports the full range of urllib3 features. It also +supports the following SOCKS features: + +- SOCKS4 +- SOCKS4a +- SOCKS5 +- Usernames and passwords for the SOCKS proxy + +Known Limitations: + +- Currently PySocks does not support contacting remote websites via literal + IPv6 addresses. Any such connection attempt will fail. You must use a domain + name. +- Currently PySocks does not support IPv6 connections to the SOCKS proxy. Any + such connection attempt will fail. +""" +from __future__ import absolute_import + +try: + import socks +except ImportError: + import warnings + from ..exceptions import DependencyWarning + + warnings.warn(( + 'SOCKS support in urllib3 requires the installation of optional ' + 'dependencies: specifically, PySocks. For more information, see ' + 'https://urllib3.readthedocs.io/en/latest/contrib.html#socks-proxies' + ), + DependencyWarning + ) + raise + +from socket import error as SocketError, timeout as SocketTimeout + +from ..connection import ( + HTTPConnection, HTTPSConnection +) +from ..connectionpool import ( + HTTPConnectionPool, HTTPSConnectionPool +) +from ..exceptions import ConnectTimeoutError, NewConnectionError +from ..poolmanager import PoolManager +from ..util.url import parse_url + +try: + import ssl +except ImportError: + ssl = None + + +class SOCKSConnection(HTTPConnection): + """ + A plain-text HTTP connection that connects via a SOCKS proxy. + """ + def __init__(self, *args, **kwargs): + self._socks_options = kwargs.pop('_socks_options') + super(SOCKSConnection, self).__init__(*args, **kwargs) + + def _new_conn(self): + """ + Establish a new connection via the SOCKS proxy. + """ + extra_kw = {} + if self.source_address: + extra_kw['source_address'] = self.source_address + + if self.socket_options: + extra_kw['socket_options'] = self.socket_options + + try: + conn = socks.create_connection( + (self.host, self.port), + proxy_type=self._socks_options['socks_version'], + proxy_addr=self._socks_options['proxy_host'], + proxy_port=self._socks_options['proxy_port'], + proxy_username=self._socks_options['username'], + proxy_password=self._socks_options['password'], + proxy_rdns=self._socks_options['rdns'], + timeout=self.timeout, + **extra_kw + ) + + except SocketTimeout as e: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout)) + + except socks.ProxyError as e: + # This is fragile as hell, but it seems to be the only way to raise + # useful errors here. + if e.socket_err: + error = e.socket_err + if isinstance(error, SocketTimeout): + raise ConnectTimeoutError( + self, + "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout) + ) + else: + raise NewConnectionError( + self, + "Failed to establish a new connection: %s" % error + ) + else: + raise NewConnectionError( + self, + "Failed to establish a new connection: %s" % e + ) + + except SocketError as e: # Defensive: PySocks should catch all these. + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e) + + return conn + + +# We don't need to duplicate the Verified/Unverified distinction from +# urllib3/connection.py here because the HTTPSConnection will already have been +# correctly set to either the Verified or Unverified form by that module. This +# means the SOCKSHTTPSConnection will automatically be the correct type. +class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection): + pass + + +class SOCKSHTTPConnectionPool(HTTPConnectionPool): + ConnectionCls = SOCKSConnection + + +class SOCKSHTTPSConnectionPool(HTTPSConnectionPool): + ConnectionCls = SOCKSHTTPSConnection + + +class SOCKSProxyManager(PoolManager): + """ + A version of the urllib3 ProxyManager that routes connections via the + defined SOCKS proxy. + """ + pool_classes_by_scheme = { + 'http': SOCKSHTTPConnectionPool, + 'https': SOCKSHTTPSConnectionPool, + } + + def __init__(self, proxy_url, username=None, password=None, + num_pools=10, headers=None, **connection_pool_kw): + parsed = parse_url(proxy_url) + + if username is None and password is None and parsed.auth is not None: + split = parsed.auth.split(':') + if len(split) == 2: + username, password = split + if parsed.scheme == 'socks5': + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = False + elif parsed.scheme == 'socks5h': + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = True + elif parsed.scheme == 'socks4': + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = False + elif parsed.scheme == 'socks4a': + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = True + else: + raise ValueError( + "Unable to determine SOCKS version from %s" % proxy_url + ) + + self.proxy_url = proxy_url + + socks_options = { + 'socks_version': socks_version, + 'proxy_host': parsed.host, + 'proxy_port': parsed.port, + 'username': username, + 'password': password, + 'rdns': rdns + } + connection_pool_kw['_socks_options'] = socks_options + + super(SOCKSProxyManager, self).__init__( + num_pools, headers, **connection_pool_kw + ) + + self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/exceptions.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/exceptions.py new file mode 100644 index 0000000..7bbaa98 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/exceptions.py @@ -0,0 +1,246 @@ +from __future__ import absolute_import +from .packages.six.moves.http_client import ( + IncompleteRead as httplib_IncompleteRead +) +# Base Exceptions + + +class HTTPError(Exception): + "Base exception used by this module." + pass + + +class HTTPWarning(Warning): + "Base warning used by this module." + pass + + +class PoolError(HTTPError): + "Base exception for errors caused within a pool." + def __init__(self, pool, message): + self.pool = pool + HTTPError.__init__(self, "%s: %s" % (pool, message)) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, None) + + +class RequestError(PoolError): + "Base exception for PoolErrors that have associated URLs." + def __init__(self, pool, url, message): + self.url = url + PoolError.__init__(self, pool, message) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, self.url, None) + + +class SSLError(HTTPError): + "Raised when SSL certificate fails in an HTTPS connection." + pass + + +class ProxyError(HTTPError): + "Raised when the connection to a proxy fails." + pass + + +class DecodeError(HTTPError): + "Raised when automatic decoding based on Content-Type fails." + pass + + +class ProtocolError(HTTPError): + "Raised when something unexpected happens mid-request/response." + pass + + +#: Renamed to ProtocolError but aliased for backwards compatibility. +ConnectionError = ProtocolError + + +# Leaf Exceptions + +class MaxRetryError(RequestError): + """Raised when the maximum number of retries is exceeded. + + :param pool: The connection pool + :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool` + :param string url: The requested Url + :param exceptions.Exception reason: The underlying error + + """ + + def __init__(self, pool, url, reason=None): + self.reason = reason + + message = "Max retries exceeded with url: %s (Caused by %r)" % ( + url, reason) + + RequestError.__init__(self, pool, url, message) + + +class HostChangedError(RequestError): + "Raised when an existing pool gets a request for a foreign host." + + def __init__(self, pool, url, retries=3): + message = "Tried to open a foreign host with url: %s" % url + RequestError.__init__(self, pool, url, message) + self.retries = retries + + +class TimeoutStateError(HTTPError): + """ Raised when passing an invalid state to a timeout """ + pass + + +class TimeoutError(HTTPError): + """ Raised when a socket timeout error occurs. + + Catching this error will catch both :exc:`ReadTimeoutErrors + <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`. + """ + pass + + +class ReadTimeoutError(TimeoutError, RequestError): + "Raised when a socket timeout occurs while receiving data from a server" + pass + + +# This timeout error does not have a URL attached and needs to inherit from the +# base HTTPError +class ConnectTimeoutError(TimeoutError): + "Raised when a socket timeout occurs while connecting to a server" + pass + + +class NewConnectionError(ConnectTimeoutError, PoolError): + "Raised when we fail to establish a new connection. Usually ECONNREFUSED." + pass + + +class EmptyPoolError(PoolError): + "Raised when a pool runs out of connections and no more are allowed." + pass + + +class ClosedPoolError(PoolError): + "Raised when a request enters a pool after the pool has been closed." + pass + + +class LocationValueError(ValueError, HTTPError): + "Raised when there is something wrong with a given URL input." + pass + + +class LocationParseError(LocationValueError): + "Raised when get_host or similar fails to parse the URL input." + + def __init__(self, location): + message = "Failed to parse: %s" % location + HTTPError.__init__(self, message) + + self.location = location + + +class ResponseError(HTTPError): + "Used as a container for an error reason supplied in a MaxRetryError." + GENERIC_ERROR = 'too many error responses' + SPECIFIC_ERROR = 'too many {status_code} error responses' + + +class SecurityWarning(HTTPWarning): + "Warned when performing security reducing actions" + pass + + +class SubjectAltNameWarning(SecurityWarning): + "Warned when connecting to a host with a certificate missing a SAN." + pass + + +class InsecureRequestWarning(SecurityWarning): + "Warned when making an unverified HTTPS request." + pass + + +class SystemTimeWarning(SecurityWarning): + "Warned when system time is suspected to be wrong" + pass + + +class InsecurePlatformWarning(SecurityWarning): + "Warned when certain SSL configuration is not available on a platform." + pass + + +class SNIMissingWarning(HTTPWarning): + "Warned when making a HTTPS request without SNI available." + pass + + +class DependencyWarning(HTTPWarning): + """ + Warned when an attempt is made to import a module with missing optional + dependencies. + """ + pass + + +class ResponseNotChunked(ProtocolError, ValueError): + "Response needs to be chunked in order to read it as chunks." + pass + + +class BodyNotHttplibCompatible(HTTPError): + """ + Body should be httplib.HTTPResponse like (have an fp attribute which + returns raw chunks) for read_chunked(). + """ + pass + + +class IncompleteRead(HTTPError, httplib_IncompleteRead): + """ + Response length doesn't match expected Content-Length + + Subclass of http_client.IncompleteRead to allow int value + for `partial` to avoid creating large objects on streamed + reads. + """ + def __init__(self, partial, expected): + super(IncompleteRead, self).__init__(partial, expected) + + def __repr__(self): + return ('IncompleteRead(%i bytes read, ' + '%i more expected)' % (self.partial, self.expected)) + + +class InvalidHeader(HTTPError): + "The header provided was somehow invalid." + pass + + +class ProxySchemeUnknown(AssertionError, ValueError): + "ProxyManager does not support the supplied scheme" + # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. + + def __init__(self, scheme): + message = "Not supported proxy scheme %s" % scheme + super(ProxySchemeUnknown, self).__init__(message) + + +class HeaderParsingError(HTTPError): + "Raised by assert_header_parsing, but we convert it to a log.warning statement." + def __init__(self, defects, unparsed_data): + message = '%s, unparsed data: %r' % (defects or 'Unknown', unparsed_data) + super(HeaderParsingError, self).__init__(message) + + +class UnrewindableBodyError(HTTPError): + "urllib3 encountered an error when trying to rewind a body" + pass diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/fields.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/fields.py new file mode 100644 index 0000000..37fe64a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/fields.py @@ -0,0 +1,178 @@ +from __future__ import absolute_import +import email.utils +import mimetypes + +from .packages import six + + +def guess_content_type(filename, default='application/octet-stream'): + """ + Guess the "Content-Type" of a file. + + :param filename: + The filename to guess the "Content-Type" of using :mod:`mimetypes`. + :param default: + If no "Content-Type" can be guessed, default to `default`. + """ + if filename: + return mimetypes.guess_type(filename)[0] or default + return default + + +def format_header_param(name, value): + """ + Helper function to format and quote a single header parameter. + + Particularly useful for header parameters which might contain + non-ASCII values, like file names. This follows RFC 2231, as + suggested by RFC 2388 Section 4.4. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + if not any(ch in value for ch in '"\\\r\n'): + result = '%s="%s"' % (name, value) + try: + result.encode('ascii') + except (UnicodeEncodeError, UnicodeDecodeError): + pass + else: + return result + if not six.PY3 and isinstance(value, six.text_type): # Python 2: + value = value.encode('utf-8') + value = email.utils.encode_rfc2231(value, 'utf-8') + value = '%s*=%s' % (name, value) + return value + + +class RequestField(object): + """ + A data container for request body parameters. + + :param name: + The name of this request field. + :param data: + The data/value body. + :param filename: + An optional filename of the request field. + :param headers: + An optional dict-like object of headers to initially use for the field. + """ + def __init__(self, name, data, filename=None, headers=None): + self._name = name + self._filename = filename + self.data = data + self.headers = {} + if headers: + self.headers = dict(headers) + + @classmethod + def from_tuples(cls, fieldname, value): + """ + A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters. + + Supports constructing :class:`~urllib3.fields.RequestField` from + parameter of key/value strings AND key/filetuple. A filetuple is a + (filename, data, MIME type) tuple where the MIME type is optional. + For example:: + + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + + Field names and filenames must be unicode. + """ + if isinstance(value, tuple): + if len(value) == 3: + filename, data, content_type = value + else: + filename, data = value + content_type = guess_content_type(filename) + else: + filename = None + content_type = None + data = value + + request_param = cls(fieldname, data, filename=filename) + request_param.make_multipart(content_type=content_type) + + return request_param + + def _render_part(self, name, value): + """ + Overridable helper function to format a single header parameter. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + return format_header_param(name, value) + + def _render_parts(self, header_parts): + """ + Helper function to format and quote a single header. + + Useful for single headers that are composed of multiple items. E.g., + 'Content-Disposition' fields. + + :param header_parts: + A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format + as `k1="v1"; k2="v2"; ...`. + """ + parts = [] + iterable = header_parts + if isinstance(header_parts, dict): + iterable = header_parts.items() + + for name, value in iterable: + if value is not None: + parts.append(self._render_part(name, value)) + + return '; '.join(parts) + + def render_headers(self): + """ + Renders the headers for this request field. + """ + lines = [] + + sort_keys = ['Content-Disposition', 'Content-Type', 'Content-Location'] + for sort_key in sort_keys: + if self.headers.get(sort_key, False): + lines.append('%s: %s' % (sort_key, self.headers[sort_key])) + + for header_name, header_value in self.headers.items(): + if header_name not in sort_keys: + if header_value: + lines.append('%s: %s' % (header_name, header_value)) + + lines.append('\r\n') + return '\r\n'.join(lines) + + def make_multipart(self, content_disposition=None, content_type=None, + content_location=None): + """ + Makes this request field into a multipart request field. + + This method overrides "Content-Disposition", "Content-Type" and + "Content-Location" headers to the request parameter. + + :param content_type: + The 'Content-Type' of the request body. + :param content_location: + The 'Content-Location' of the request body. + + """ + self.headers['Content-Disposition'] = content_disposition or 'form-data' + self.headers['Content-Disposition'] += '; '.join([ + '', self._render_parts( + (('name', self._name), ('filename', self._filename)) + ) + ]) + self.headers['Content-Type'] = content_type + self.headers['Content-Location'] = content_location diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/filepost.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/filepost.py new file mode 100644 index 0000000..78f1e19 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/filepost.py @@ -0,0 +1,98 @@ +from __future__ import absolute_import +import binascii +import codecs +import os + +from io import BytesIO + +from .packages import six +from .packages.six import b +from .fields import RequestField + +writer = codecs.lookup('utf-8')[3] + + +def choose_boundary(): + """ + Our embarrassingly-simple replacement for mimetools.choose_boundary. + """ + boundary = binascii.hexlify(os.urandom(16)) + if six.PY3: + boundary = boundary.decode('ascii') + return boundary + + +def iter_field_objects(fields): + """ + Iterate over fields. + + Supports list of (k, v) tuples and dicts, and lists of + :class:`~urllib3.fields.RequestField`. + + """ + if isinstance(fields, dict): + i = six.iteritems(fields) + else: + i = iter(fields) + + for field in i: + if isinstance(field, RequestField): + yield field + else: + yield RequestField.from_tuples(*field) + + +def iter_fields(fields): + """ + .. deprecated:: 1.6 + + Iterate over fields. + + The addition of :class:`~urllib3.fields.RequestField` makes this function + obsolete. Instead, use :func:`iter_field_objects`, which returns + :class:`~urllib3.fields.RequestField` objects. + + Supports list of (k, v) tuples and dicts. + """ + if isinstance(fields, dict): + return ((k, v) for k, v in six.iteritems(fields)) + + return ((k, v) for k, v in fields) + + +def encode_multipart_formdata(fields, boundary=None): + """ + Encode a dictionary of ``fields`` using the multipart/form-data MIME format. + + :param fields: + Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). + + :param boundary: + If not specified, then a random boundary will be generated using + :func:`urllib3.filepost.choose_boundary`. + """ + body = BytesIO() + if boundary is None: + boundary = choose_boundary() + + for field in iter_field_objects(fields): + body.write(b('--%s\r\n' % (boundary))) + + writer(body).write(field.render_headers()) + data = field.data + + if isinstance(data, int): + data = str(data) # Backwards compatibility + + if isinstance(data, six.text_type): + writer(body).write(data) + else: + body.write(data) + + body.write(b'\r\n') + + body.write(b('--%s--\r\n' % (boundary))) + + content_type = str('multipart/form-data; boundary=%s' % boundary) + + return body.getvalue(), content_type diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__init__.py new file mode 100644 index 0000000..170e974 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/__init__.py @@ -0,0 +1,5 @@ +from __future__ import absolute_import + +from . import ssl_match_hostname + +__all__ = ('ssl_match_hostname', ) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py new file mode 100644 index 0000000..75b80dc --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +""" +backports.makefile +~~~~~~~~~~~~~~~~~~ + +Backports the Python 3 ``socket.makefile`` method for use with anything that +wants to create a "fake" socket object. +""" +import io + +from socket import SocketIO + + +def backport_makefile(self, mode="r", buffering=None, encoding=None, + errors=None, newline=None): + """ + Backport of ``socket.makefile`` from Python 3.5. + """ + if not set(mode) <= set(["r", "w", "b"]): + raise ValueError( + "invalid mode %r (only r, w, b allowed)" % (mode,) + ) + writing = "w" in mode + reading = "r" in mode or not writing + assert reading or writing + binary = "b" in mode + rawmode = "" + if reading: + rawmode += "r" + if writing: + rawmode += "w" + raw = SocketIO(self, rawmode) + self._makefile_refs += 1 + if buffering is None: + buffering = -1 + if buffering < 0: + buffering = io.DEFAULT_BUFFER_SIZE + if buffering == 0: + if not binary: + raise ValueError("unbuffered streams must be binary") + return raw + if reading and writing: + buffer = io.BufferedRWPair(raw, raw, buffering) + elif reading: + buffer = io.BufferedReader(raw, buffering) + else: + assert writing + buffer = io.BufferedWriter(raw, buffering) + if binary: + return buffer + text = io.TextIOWrapper(buffer, encoding, errors, newline) + text.mode = mode + return text diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py new file mode 100644 index 0000000..4479363 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py @@ -0,0 +1,259 @@ +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. +# Copyright 2009 Raymond Hettinger, released under the MIT License. +# http://code.activestate.com/recipes/576693/ +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + +try: + from _abcoll import KeysView, ValuesView, ItemsView +except ImportError: + pass + + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/six.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# 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. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py new file mode 100644 index 0000000..d6594eb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py @@ -0,0 +1,19 @@ +import sys + +try: + # Our match_hostname function is the same as 3.5's, so we only want to + # import the match_hostname function if it's at least that good. + if sys.version_info < (3, 5): + raise ImportError("Fallback to vendored code") + + from ssl import CertificateError, match_hostname +except ImportError: + try: + # Backport of the function from a pypi module + from backports.ssl_match_hostname import CertificateError, match_hostname + except ImportError: + # Our vendored copy + from ._implementation import CertificateError, match_hostname + +# Not needed, but documenting what we provide. +__all__ = ('CertificateError', 'match_hostname') diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py new file mode 100644 index 0000000..92c9bc7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py @@ -0,0 +1,157 @@ +"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" + +# Note: This file is under the PSF license as the code comes from the python +# stdlib. http://docs.python.org/3/license.html + +import re +import sys + +# ipaddress has been backported to 2.6+ in pypi. If it is installed on the +# system, use it to handle IPAddress ServerAltnames (this was added in +# python-3.5) otherwise only do DNS matching. This allows +# backports.ssl_match_hostname to continue to be used all the way back to +# python-2.4. +try: + from pip._vendor import ipaddress +except ImportError: + ipaddress = None + +__version__ = '3.5.0.1' + + +class CertificateError(ValueError): + pass + + +def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r'.') + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + +def _to_unicode(obj): + if isinstance(obj, str) and sys.version_info < (3,): + obj = unicode(obj, encoding='ascii', errors='strict') + return obj + +def _ipaddress_match(ipname, host_ip): + """Exact matching of IP addresses. + + RFC 6125 explicitly doesn't define an algorithm for this + (section 1.7.2 - "Out of Scope"). + """ + # OpenSSL may add a trailing newline to a subjectAltName's IP address + # Divergence from upstream: ipaddress can't handle byte str + ip = ipaddress.ip_address(_to_unicode(ipname).rstrip()) + return ip == host_ip + + +def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + try: + # Divergence from upstream: ipaddress can't handle byte str + host_ip = ipaddress.ip_address(_to_unicode(hostname)) + except ValueError: + # Not an IP address (common case) + host_ip = None + except UnicodeError: + # Divergence from upstream: Have to deal with ipaddress not taking + # byte strings. addresses should be all ascii, so we consider it not + # an ipaddress in this case + host_ip = None + except AttributeError: + # Divergence from upstream: Make ipaddress library optional + if ipaddress is None: + host_ip = None + else: + raise + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if host_ip is None and _dnsname_match(value, hostname): + return + dnsnames.append(value) + elif key == 'IP Address': + if host_ip is not None and _ipaddress_match(value, host_ip): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/poolmanager.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/poolmanager.py new file mode 100644 index 0000000..506a3c9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/poolmanager.py @@ -0,0 +1,449 @@ +from __future__ import absolute_import +import collections +import functools +import logging + +from ._collections import RecentlyUsedContainer +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool +from .connectionpool import port_by_scheme +from .exceptions import LocationValueError, MaxRetryError, ProxySchemeUnknown +from .packages.six.moves.urllib.parse import urljoin +from .request import RequestMethods +from .util.url import parse_url +from .util.retry import Retry + + +__all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url'] + + +log = logging.getLogger(__name__) + +SSL_KEYWORDS = ('key_file', 'cert_file', 'cert_reqs', 'ca_certs', + 'ssl_version', 'ca_cert_dir', 'ssl_context') + +# All known keyword arguments that could be provided to the pool manager, its +# pools, or the underlying connections. This is used to construct a pool key. +_key_fields = ( + 'key_scheme', # str + 'key_host', # str + 'key_port', # int + 'key_timeout', # int or float or Timeout + 'key_retries', # int or Retry + 'key_strict', # bool + 'key_block', # bool + 'key_source_address', # str + 'key_key_file', # str + 'key_cert_file', # str + 'key_cert_reqs', # str + 'key_ca_certs', # str + 'key_ssl_version', # str + 'key_ca_cert_dir', # str + 'key_ssl_context', # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext + 'key_maxsize', # int + 'key_headers', # dict + 'key__proxy', # parsed proxy url + 'key__proxy_headers', # dict + 'key_socket_options', # list of (level (int), optname (int), value (int or str)) tuples + 'key__socks_options', # dict + 'key_assert_hostname', # bool or string + 'key_assert_fingerprint', # str +) + +#: The namedtuple class used to construct keys for the connection pool. +#: All custom key schemes should include the fields in this key at a minimum. +PoolKey = collections.namedtuple('PoolKey', _key_fields) + + +def _default_key_normalizer(key_class, request_context): + """ + Create a pool key out of a request context dictionary. + + According to RFC 3986, both the scheme and host are case-insensitive. + Therefore, this function normalizes both before constructing the pool + key for an HTTPS request. If you wish to change this behaviour, provide + alternate callables to ``key_fn_by_scheme``. + + :param key_class: + The class to use when constructing the key. This should be a namedtuple + with the ``scheme`` and ``host`` keys at a minimum. + :type key_class: namedtuple + :param request_context: + A dictionary-like object that contain the context for a request. + :type request_context: dict + + :return: A namedtuple that can be used as a connection pool key. + :rtype: PoolKey + """ + # Since we mutate the dictionary, make a copy first + context = request_context.copy() + context['scheme'] = context['scheme'].lower() + context['host'] = context['host'].lower() + + # These are both dictionaries and need to be transformed into frozensets + for key in ('headers', '_proxy_headers', '_socks_options'): + if key in context and context[key] is not None: + context[key] = frozenset(context[key].items()) + + # The socket_options key may be a list and needs to be transformed into a + # tuple. + socket_opts = context.get('socket_options') + if socket_opts is not None: + context['socket_options'] = tuple(socket_opts) + + # Map the kwargs to the names in the namedtuple - this is necessary since + # namedtuples can't have fields starting with '_'. + for key in list(context.keys()): + context['key_' + key] = context.pop(key) + + # Default to ``None`` for keys missing from the context + for field in key_class._fields: + if field not in context: + context[field] = None + + return key_class(**context) + + +#: A dictionary that maps a scheme to a callable that creates a pool key. +#: This can be used to alter the way pool keys are constructed, if desired. +#: Each PoolManager makes a copy of this dictionary so they can be configured +#: globally here, or individually on the instance. +key_fn_by_scheme = { + 'http': functools.partial(_default_key_normalizer, PoolKey), + 'https': functools.partial(_default_key_normalizer, PoolKey), +} + +pool_classes_by_scheme = { + 'http': HTTPConnectionPool, + 'https': HTTPSConnectionPool, +} + + +class PoolManager(RequestMethods): + """ + Allows for arbitrary requests while transparently keeping track of + necessary connection pools for you. + + :param num_pools: + Number of connection pools to cache before discarding the least + recently used pool. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param \\**connection_pool_kw: + Additional parameters are used to create fresh + :class:`urllib3.connectionpool.ConnectionPool` instances. + + Example:: + + >>> manager = PoolManager(num_pools=2) + >>> r = manager.request('GET', 'http://google.com/') + >>> r = manager.request('GET', 'http://google.com/mail') + >>> r = manager.request('GET', 'http://yahoo.com/') + >>> len(manager.pools) + 2 + + """ + + proxy = None + + def __init__(self, num_pools=10, headers=None, **connection_pool_kw): + RequestMethods.__init__(self, headers) + self.connection_pool_kw = connection_pool_kw + self.pools = RecentlyUsedContainer(num_pools, + dispose_func=lambda p: p.close()) + + # Locally set the pool classes and keys so other PoolManagers can + # override them. + self.pool_classes_by_scheme = pool_classes_by_scheme + self.key_fn_by_scheme = key_fn_by_scheme.copy() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.clear() + # Return False to re-raise any potential exceptions + return False + + def _new_pool(self, scheme, host, port, request_context=None): + """ + Create a new :class:`ConnectionPool` based on host, port, scheme, and + any additional pool keyword arguments. + + If ``request_context`` is provided, it is provided as keyword arguments + to the pool class used. This method is used to actually create the + connection pools handed out by :meth:`connection_from_url` and + companion methods. It is intended to be overridden for customization. + """ + pool_cls = self.pool_classes_by_scheme[scheme] + if request_context is None: + request_context = self.connection_pool_kw.copy() + + # Although the context has everything necessary to create the pool, + # this function has historically only used the scheme, host, and port + # in the positional args. When an API change is acceptable these can + # be removed. + for key in ('scheme', 'host', 'port'): + request_context.pop(key, None) + + if scheme == 'http': + for kw in SSL_KEYWORDS: + request_context.pop(kw, None) + + return pool_cls(host, port, **request_context) + + def clear(self): + """ + Empty our store of pools and direct them all to close. + + This will not affect in-flight connections, but they will not be + re-used after completion. + """ + self.pools.clear() + + def connection_from_host(self, host, port=None, scheme='http', pool_kwargs=None): + """ + Get a :class:`ConnectionPool` based on the host, port, and scheme. + + If ``port`` isn't given, it will be derived from the ``scheme`` using + ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is + provided, it is merged with the instance's ``connection_pool_kw`` + variable and used to create the new connection pool, if one is + needed. + """ + + if not host: + raise LocationValueError("No host specified.") + + request_context = self._merge_pool_kwargs(pool_kwargs) + request_context['scheme'] = scheme or 'http' + if not port: + port = port_by_scheme.get(request_context['scheme'].lower(), 80) + request_context['port'] = port + request_context['host'] = host + + return self.connection_from_context(request_context) + + def connection_from_context(self, request_context): + """ + Get a :class:`ConnectionPool` based on the request context. + + ``request_context`` must at least contain the ``scheme`` key and its + value must be a key in ``key_fn_by_scheme`` instance variable. + """ + scheme = request_context['scheme'].lower() + pool_key_constructor = self.key_fn_by_scheme[scheme] + pool_key = pool_key_constructor(request_context) + + return self.connection_from_pool_key(pool_key, request_context=request_context) + + def connection_from_pool_key(self, pool_key, request_context=None): + """ + Get a :class:`ConnectionPool` based on the provided pool key. + + ``pool_key`` should be a namedtuple that only contains immutable + objects. At a minimum it must have the ``scheme``, ``host``, and + ``port`` fields. + """ + with self.pools.lock: + # If the scheme, host, or port doesn't match existing open + # connections, open a new ConnectionPool. + pool = self.pools.get(pool_key) + if pool: + return pool + + # Make a fresh ConnectionPool of the desired type + scheme = request_context['scheme'] + host = request_context['host'] + port = request_context['port'] + pool = self._new_pool(scheme, host, port, request_context=request_context) + self.pools[pool_key] = pool + + return pool + + def connection_from_url(self, url, pool_kwargs=None): + """ + Similar to :func:`urllib3.connectionpool.connection_from_url`. + + If ``pool_kwargs`` is not provided and a new pool needs to be + constructed, ``self.connection_pool_kw`` is used to initialize + the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs`` + is provided, it is used instead. Note that if a new pool does not + need to be created for the request, the provided ``pool_kwargs`` are + not used. + """ + u = parse_url(url) + return self.connection_from_host(u.host, port=u.port, scheme=u.scheme, + pool_kwargs=pool_kwargs) + + def _merge_pool_kwargs(self, override): + """ + Merge a dictionary of override values for self.connection_pool_kw. + + This does not modify self.connection_pool_kw and returns a new dict. + Any keys in the override dictionary with a value of ``None`` are + removed from the merged dictionary. + """ + base_pool_kwargs = self.connection_pool_kw.copy() + if override: + for key, value in override.items(): + if value is None: + try: + del base_pool_kwargs[key] + except KeyError: + pass + else: + base_pool_kwargs[key] = value + return base_pool_kwargs + + def urlopen(self, method, url, redirect=True, **kw): + """ + Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` + with custom cross-host redirect logic and only sends the request-uri + portion of the ``url``. + + The given ``url`` parameter must be absolute, such that an appropriate + :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. + """ + u = parse_url(url) + conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + kw['assert_same_host'] = False + kw['redirect'] = False + + if 'headers' not in kw: + kw['headers'] = self.headers.copy() + + if self.proxy is not None and u.scheme == "http": + response = conn.urlopen(method, url, **kw) + else: + response = conn.urlopen(method, u.request_uri, **kw) + + redirect_location = redirect and response.get_redirect_location() + if not redirect_location: + return response + + # Support relative URLs for redirecting. + redirect_location = urljoin(url, redirect_location) + + # RFC 7231, Section 6.4.4 + if response.status == 303: + method = 'GET' + + retries = kw.get('retries') + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect) + + # Strip headers marked as unsafe to forward to the redirected location. + # Check remove_headers_on_redirect to avoid a potential network call within + # conn.is_same_host() which may use socket.gethostbyname() in the future. + if (retries.remove_headers_on_redirect + and not conn.is_same_host(redirect_location)): + for header in retries.remove_headers_on_redirect: + kw['headers'].pop(header, None) + + try: + retries = retries.increment(method, url, response=response, _pool=conn) + except MaxRetryError: + if retries.raise_on_redirect: + raise + return response + + kw['retries'] = retries + kw['redirect'] = redirect + + log.info("Redirecting %s -> %s", url, redirect_location) + return self.urlopen(method, redirect_location, **kw) + + +class ProxyManager(PoolManager): + """ + Behaves just like :class:`PoolManager`, but sends all requests through + the defined proxy, using the CONNECT method for HTTPS URLs. + + :param proxy_url: + The URL of the proxy to be used. + + :param proxy_headers: + A dictionary containing headers that will be sent to the proxy. In case + of HTTP they are being sent with each request, while in the + HTTPS/CONNECT case they are sent only once. Could be used for proxy + authentication. + + Example: + >>> proxy = urllib3.ProxyManager('http://localhost:3128/') + >>> r1 = proxy.request('GET', 'http://google.com/') + >>> r2 = proxy.request('GET', 'http://httpbin.org/') + >>> len(proxy.pools) + 1 + >>> r3 = proxy.request('GET', 'https://httpbin.org/') + >>> r4 = proxy.request('GET', 'https://twitter.com/') + >>> len(proxy.pools) + 3 + + """ + + def __init__(self, proxy_url, num_pools=10, headers=None, + proxy_headers=None, **connection_pool_kw): + + if isinstance(proxy_url, HTTPConnectionPool): + proxy_url = '%s://%s:%i' % (proxy_url.scheme, proxy_url.host, + proxy_url.port) + proxy = parse_url(proxy_url) + if not proxy.port: + port = port_by_scheme.get(proxy.scheme, 80) + proxy = proxy._replace(port=port) + + if proxy.scheme not in ("http", "https"): + raise ProxySchemeUnknown(proxy.scheme) + + self.proxy = proxy + self.proxy_headers = proxy_headers or {} + + connection_pool_kw['_proxy'] = self.proxy + connection_pool_kw['_proxy_headers'] = self.proxy_headers + + super(ProxyManager, self).__init__( + num_pools, headers, **connection_pool_kw) + + def connection_from_host(self, host, port=None, scheme='http', pool_kwargs=None): + if scheme == "https": + return super(ProxyManager, self).connection_from_host( + host, port, scheme, pool_kwargs=pool_kwargs) + + return super(ProxyManager, self).connection_from_host( + self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs) + + def _set_proxy_headers(self, url, headers=None): + """ + Sets headers needed by proxies: specifically, the Accept and Host + headers. Only sets headers not provided by the user. + """ + headers_ = {'Accept': '*/*'} + + netloc = parse_url(url).netloc + if netloc: + headers_['Host'] = netloc + + if headers: + headers_.update(headers) + return headers_ + + def urlopen(self, method, url, redirect=True, **kw): + "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." + u = parse_url(url) + + if u.scheme == "http": + # For proxied HTTPS requests, httplib sets the necessary headers + # on the CONNECT to the proxy. For HTTP, we'll definitely + # need to set 'Host' at the very least. + headers = kw.get('headers', self.headers) + kw['headers'] = self._set_proxy_headers(url, headers) + + return super(ProxyManager, self).urlopen(method, url, redirect=redirect, **kw) + + +def proxy_from_url(url, **kw): + return ProxyManager(proxy_url=url, **kw) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/request.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/request.py new file mode 100644 index 0000000..1be3334 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/request.py @@ -0,0 +1,150 @@ +from __future__ import absolute_import + +from .filepost import encode_multipart_formdata +from .packages.six.moves.urllib.parse import urlencode + + +__all__ = ['RequestMethods'] + + +class RequestMethods(object): + """ + Convenience mixin for classes who implement a :meth:`urlopen` method, such + as :class:`~urllib3.connectionpool.HTTPConnectionPool` and + :class:`~urllib3.poolmanager.PoolManager`. + + Provides behavior for making common types of HTTP request methods and + decides which type of request field encoding to use. + + Specifically, + + :meth:`.request_encode_url` is for sending requests whose fields are + encoded in the URL (such as GET, HEAD, DELETE). + + :meth:`.request_encode_body` is for sending requests whose fields are + encoded in the *body* of the request using multipart or www-form-urlencoded + (such as for POST, PUT, PATCH). + + :meth:`.request` is for making any kind of request, it will look up the + appropriate encoding format and use one of the above two methods to make + the request. + + Initializer parameters: + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + """ + + _encode_url_methods = set(['DELETE', 'GET', 'HEAD', 'OPTIONS']) + + def __init__(self, headers=None): + self.headers = headers or {} + + def urlopen(self, method, url, body=None, headers=None, + encode_multipart=True, multipart_boundary=None, + **kw): # Abstract + raise NotImplementedError("Classes extending RequestMethods must implement " + "their own ``urlopen`` method.") + + def request(self, method, url, fields=None, headers=None, **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the appropriate encoding of + ``fields`` based on the ``method`` used. + + This is a convenience method that requires the least amount of manual + effort. It can be used in most situations, while still having the + option to drop down to more specific methods when necessary, such as + :meth:`request_encode_url`, :meth:`request_encode_body`, + or even the lowest level :meth:`urlopen`. + """ + method = method.upper() + + urlopen_kw['request_url'] = url + + if method in self._encode_url_methods: + return self.request_encode_url(method, url, fields=fields, + headers=headers, + **urlopen_kw) + else: + return self.request_encode_body(method, url, fields=fields, + headers=headers, + **urlopen_kw) + + def request_encode_url(self, method, url, fields=None, headers=None, + **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the url. This is useful for request methods like GET, HEAD, DELETE, etc. + """ + if headers is None: + headers = self.headers + + extra_kw = {'headers': headers} + extra_kw.update(urlopen_kw) + + if fields: + url += '?' + urlencode(fields) + + return self.urlopen(method, url, **extra_kw) + + def request_encode_body(self, method, url, fields=None, headers=None, + encode_multipart=True, multipart_boundary=None, + **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the body. This is useful for request methods like POST, PUT, PATCH, etc. + + When ``encode_multipart=True`` (default), then + :meth:`urllib3.filepost.encode_multipart_formdata` is used to encode + the payload with the appropriate content type. Otherwise + :meth:`urllib.urlencode` is used with the + 'application/x-www-form-urlencoded' content type. + + Multipart encoding must be used when posting files, and it's reasonably + safe to use it in other times too. However, it may break request + signing, such as with OAuth. + + Supports an optional ``fields`` parameter of key/value strings AND + key/filetuple. A filetuple is a (filename, data, MIME type) tuple where + the MIME type is optional. For example:: + + fields = { + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), + 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + } + + When uploading a file, providing a filename (the first parameter of the + tuple) is optional but recommended to best mimic behavior of browsers. + + Note that if ``headers`` are supplied, the 'Content-Type' header will + be overwritten because it depends on the dynamic random boundary string + which is used to compose the body of the request. The random boundary + string can be explicitly set with the ``multipart_boundary`` parameter. + """ + if headers is None: + headers = self.headers + + extra_kw = {'headers': {}} + + if fields: + if 'body' in urlopen_kw: + raise TypeError( + "request got values for both 'fields' and 'body', can only specify one.") + + if encode_multipart: + body, content_type = encode_multipart_formdata(fields, boundary=multipart_boundary) + else: + body, content_type = urlencode(fields), 'application/x-www-form-urlencoded' + + extra_kw['body'] = body + extra_kw['headers'] = {'Content-Type': content_type} + + extra_kw['headers'].update(headers) + extra_kw.update(urlopen_kw) + + return self.urlopen(method, url, **extra_kw) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/response.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/response.py new file mode 100644 index 0000000..9873cb9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/response.py @@ -0,0 +1,676 @@ +from __future__ import absolute_import +from contextlib import contextmanager +import zlib +import io +import logging +from socket import timeout as SocketTimeout +from socket import error as SocketError + +from ._collections import HTTPHeaderDict +from .exceptions import ( + BodyNotHttplibCompatible, ProtocolError, DecodeError, ReadTimeoutError, + ResponseNotChunked, IncompleteRead, InvalidHeader +) +from .packages.six import string_types as basestring, binary_type, PY3 +from .packages.six.moves import http_client as httplib +from .connection import HTTPException, BaseSSLError +from .util.response import is_fp_closed, is_response_to_head + +log = logging.getLogger(__name__) + + +class DeflateDecoder(object): + + def __init__(self): + self._first_try = True + self._data = binary_type() + self._obj = zlib.decompressobj() + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + if not data: + return data + + if not self._first_try: + return self._obj.decompress(data) + + self._data += data + try: + decompressed = self._obj.decompress(data) + if decompressed: + self._first_try = False + self._data = None + return decompressed + except zlib.error: + self._first_try = False + self._obj = zlib.decompressobj(-zlib.MAX_WBITS) + try: + return self.decompress(self._data) + finally: + self._data = None + + +class GzipDecoderState(object): + + FIRST_MEMBER = 0 + OTHER_MEMBERS = 1 + SWALLOW_DATA = 2 + + +class GzipDecoder(object): + + def __init__(self): + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + self._state = GzipDecoderState.FIRST_MEMBER + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + ret = binary_type() + if self._state == GzipDecoderState.SWALLOW_DATA or not data: + return ret + while True: + try: + ret += self._obj.decompress(data) + except zlib.error: + previous_state = self._state + # Ignore data after the first error + self._state = GzipDecoderState.SWALLOW_DATA + if previous_state == GzipDecoderState.OTHER_MEMBERS: + # Allow trailing garbage acceptable in other gzip clients + return ret + raise + data = self._obj.unused_data + if not data: + return ret + self._state = GzipDecoderState.OTHER_MEMBERS + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + + +def _get_decoder(mode): + if mode == 'gzip': + return GzipDecoder() + + return DeflateDecoder() + + +class HTTPResponse(io.IOBase): + """ + HTTP Response container. + + Backwards-compatible to httplib's HTTPResponse but the response ``body`` is + loaded and decoded on-demand when the ``data`` property is accessed. This + class is also compatible with the Python standard library's :mod:`io` + module, and can hence be treated as a readable object in the context of that + framework. + + Extra parameters for behaviour not present in httplib.HTTPResponse: + + :param preload_content: + If True, the response's body will be preloaded during construction. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param original_response: + When this HTTPResponse wrapper is generated from an httplib.HTTPResponse + object, it's convenient to include the original for debug purposes. It's + otherwise unused. + + :param retries: + The retries contains the last :class:`~urllib3.util.retry.Retry` that + was used during the request. + + :param enforce_content_length: + Enforce content length checking. Body returned by server must match + value of Content-Length header, if present. Otherwise, raise error. + """ + + CONTENT_DECODERS = ['gzip', 'deflate'] + REDIRECT_STATUSES = [301, 302, 303, 307, 308] + + def __init__(self, body='', headers=None, status=0, version=0, reason=None, + strict=0, preload_content=True, decode_content=True, + original_response=None, pool=None, connection=None, msg=None, + retries=None, enforce_content_length=False, + request_method=None, request_url=None): + + if isinstance(headers, HTTPHeaderDict): + self.headers = headers + else: + self.headers = HTTPHeaderDict(headers) + self.status = status + self.version = version + self.reason = reason + self.strict = strict + self.decode_content = decode_content + self.retries = retries + self.enforce_content_length = enforce_content_length + + self._decoder = None + self._body = None + self._fp = None + self._original_response = original_response + self._fp_bytes_read = 0 + self.msg = msg + self._request_url = request_url + + if body and isinstance(body, (basestring, binary_type)): + self._body = body + + self._pool = pool + self._connection = connection + + if hasattr(body, 'read'): + self._fp = body + + # Are we using the chunked-style of transfer encoding? + self.chunked = False + self.chunk_left = None + tr_enc = self.headers.get('transfer-encoding', '').lower() + # Don't incur the penalty of creating a list and then discarding it + encodings = (enc.strip() for enc in tr_enc.split(",")) + if "chunked" in encodings: + self.chunked = True + + # Determine length of response + self.length_remaining = self._init_length(request_method) + + # If requested, preload the body. + if preload_content and not self._body: + self._body = self.read(decode_content=decode_content) + + def get_redirect_location(self): + """ + Should we redirect and where to? + + :returns: Truthy redirect location string if we got a redirect status + code and valid location. ``None`` if redirect status and no + location. ``False`` if not a redirect status code. + """ + if self.status in self.REDIRECT_STATUSES: + return self.headers.get('location') + + return False + + def release_conn(self): + if not self._pool or not self._connection: + return + + self._pool._put_conn(self._connection) + self._connection = None + + @property + def data(self): + # For backwords-compat with earlier urllib3 0.4 and earlier. + if self._body: + return self._body + + if self._fp: + return self.read(cache_content=True) + + @property + def connection(self): + return self._connection + + def isclosed(self): + return is_fp_closed(self._fp) + + def tell(self): + """ + Obtain the number of bytes pulled over the wire so far. May differ from + the amount of content returned by :meth:``HTTPResponse.read`` if bytes + are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + + def _init_length(self, request_method): + """ + Set initial length value for Response content if available. + """ + length = self.headers.get('content-length') + + if length is not None: + if self.chunked: + # This Response will fail with an IncompleteRead if it can't be + # received as chunked. This method falls back to attempt reading + # the response before raising an exception. + log.warning("Received response with both Content-Length and " + "Transfer-Encoding set. This is expressly forbidden " + "by RFC 7230 sec 3.3.2. Ignoring Content-Length and " + "attempting to process response as Transfer-Encoding: " + "chunked.") + return None + + try: + # RFC 7230 section 3.3.2 specifies multiple content lengths can + # be sent in a single Content-Length header + # (e.g. Content-Length: 42, 42). This line ensures the values + # are all valid ints and that as long as the `set` length is 1, + # all values are the same. Otherwise, the header is invalid. + lengths = set([int(val) for val in length.split(',')]) + if len(lengths) > 1: + raise InvalidHeader("Content-Length contained multiple " + "unmatching values (%s)" % length) + length = lengths.pop() + except ValueError: + length = None + else: + if length < 0: + length = None + + # Convert status to int for comparison + # In some cases, httplib returns a status of "_UNKNOWN" + try: + status = int(self.status) + except ValueError: + status = 0 + + # Check for responses that shouldn't include a body + if status in (204, 304) or 100 <= status < 200 or request_method == 'HEAD': + length = 0 + + return length + + def _init_decoder(self): + """ + Set-up the _decoder attribute if necessary. + """ + # Note: content-encoding value should be case-insensitive, per RFC 7230 + # Section 3.2 + content_encoding = self.headers.get('content-encoding', '').lower() + if self._decoder is None and content_encoding in self.CONTENT_DECODERS: + self._decoder = _get_decoder(content_encoding) + + def _decode(self, data, decode_content, flush_decoder): + """ + Decode the data passed in and potentially flush the decoder. + """ + try: + if decode_content and self._decoder: + data = self._decoder.decompress(data) + except (IOError, zlib.error) as e: + content_encoding = self.headers.get('content-encoding', '').lower() + raise DecodeError( + "Received response with content-encoding: %s, but " + "failed to decode it." % content_encoding, e) + + if flush_decoder and decode_content: + data += self._flush_decoder() + + return data + + def _flush_decoder(self): + """ + Flushes the decoder. Should only be called if the decoder is actually + being used. + """ + if self._decoder: + buf = self._decoder.decompress(b'') + return buf + self._decoder.flush() + + return b'' + + @contextmanager + def _error_catcher(self): + """ + Catch low-level python exceptions, instead re-raising urllib3 + variants, so that low-level exceptions are not leaked in the + high-level api. + + On exit, release the connection back to the pool. + """ + clean_exit = False + + try: + try: + yield + + except SocketTimeout: + # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but + # there is yet no clean way to get at it from this context. + raise ReadTimeoutError(self._pool, None, 'Read timed out.') + + except BaseSSLError as e: + # FIXME: Is there a better way to differentiate between SSLErrors? + if 'read operation timed out' not in str(e): # Defensive: + # This shouldn't happen but just in case we're missing an edge + # case, let's avoid swallowing SSL errors. + raise + + raise ReadTimeoutError(self._pool, None, 'Read timed out.') + + except (HTTPException, SocketError) as e: + # This includes IncompleteRead. + raise ProtocolError('Connection broken: %r' % e, e) + + # If no exception is thrown, we should avoid cleaning up + # unnecessarily. + clean_exit = True + finally: + # If we didn't terminate cleanly, we need to throw away our + # connection. + if not clean_exit: + # The response may not be closed but we're not going to use it + # anymore so close it now to ensure that the connection is + # released back to the pool. + if self._original_response: + self._original_response.close() + + # Closing the response may not actually be sufficient to close + # everything, so if we have a hold of the connection close that + # too. + if self._connection: + self._connection.close() + + # If we hold the original response but it's closed now, we should + # return the connection back to the pool. + if self._original_response and self._original_response.isclosed(): + self.release_conn() + + def read(self, amt=None, decode_content=None, cache_content=False): + """ + Similar to :meth:`httplib.HTTPResponse.read`, but with two additional + parameters: ``decode_content`` and ``cache_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param cache_content: + If True, will save the returned data such that the same result is + returned despite of the state of the underlying file object. This + is useful if you want the ``.data`` property to continue working + after having ``.read()`` the file object. (Overridden if ``amt`` is + set.) + """ + self._init_decoder() + if decode_content is None: + decode_content = self.decode_content + + if self._fp is None: + return + + flush_decoder = False + data = None + + with self._error_catcher(): + if amt is None: + # cStringIO doesn't like amt=None + data = self._fp.read() + flush_decoder = True + else: + cache_content = False + data = self._fp.read(amt) + if amt != 0 and not data: # Platform-specific: Buggy versions of Python. + # Close the connection when no data is returned + # + # This is redundant to what httplib/http.client _should_ + # already do. However, versions of python released before + # December 15, 2012 (http://bugs.python.org/issue16298) do + # not properly close the connection in all cases. There is + # no harm in redundantly calling close. + self._fp.close() + flush_decoder = True + if self.enforce_content_length and self.length_remaining not in (0, None): + # This is an edge case that httplib failed to cover due + # to concerns of backward compatibility. We're + # addressing it here to make sure IncompleteRead is + # raised during streaming, so all calls with incorrect + # Content-Length are caught. + raise IncompleteRead(self._fp_bytes_read, self.length_remaining) + + if data: + self._fp_bytes_read += len(data) + if self.length_remaining is not None: + self.length_remaining -= len(data) + + data = self._decode(data, decode_content, flush_decoder) + + if cache_content: + self._body = data + + return data + + def stream(self, amt=2**16, decode_content=None): + """ + A generator wrapper for the read() method. A call will block until + ``amt`` bytes have been read from the connection or until the + connection is closed. + + :param amt: + How much of the content to read. The generator will return up to + much data per iteration, but may return less. This is particularly + likely when using compressed data. However, the empty string will + never be returned. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + if self.chunked and self.supports_chunked_reads(): + for line in self.read_chunked(amt, decode_content=decode_content): + yield line + else: + while not is_fp_closed(self._fp): + data = self.read(amt=amt, decode_content=decode_content) + + if data: + yield data + + @classmethod + def from_httplib(ResponseCls, r, **response_kw): + """ + Given an :class:`httplib.HTTPResponse` instance ``r``, return a + corresponding :class:`urllib3.response.HTTPResponse` object. + + Remaining parameters are passed to the HTTPResponse constructor, along + with ``original_response=r``. + """ + headers = r.msg + + if not isinstance(headers, HTTPHeaderDict): + if PY3: # Python 3 + headers = HTTPHeaderDict(headers.items()) + else: # Python 2 + headers = HTTPHeaderDict.from_httplib(headers) + + # HTTPResponse objects in Python 3 don't have a .strict attribute + strict = getattr(r, 'strict', 0) + resp = ResponseCls(body=r, + headers=headers, + status=r.status, + version=r.version, + reason=r.reason, + strict=strict, + original_response=r, + **response_kw) + return resp + + # Backwards-compatibility methods for httplib.HTTPResponse + def getheaders(self): + return self.headers + + def getheader(self, name, default=None): + return self.headers.get(name, default) + + # Backwards compatibility for http.cookiejar + def info(self): + return self.headers + + # Overrides from io.IOBase + def close(self): + if not self.closed: + self._fp.close() + + if self._connection: + self._connection.close() + + @property + def closed(self): + if self._fp is None: + return True + elif hasattr(self._fp, 'isclosed'): + return self._fp.isclosed() + elif hasattr(self._fp, 'closed'): + return self._fp.closed + else: + return True + + def fileno(self): + if self._fp is None: + raise IOError("HTTPResponse has no file to get a fileno from") + elif hasattr(self._fp, "fileno"): + return self._fp.fileno() + else: + raise IOError("The file-like object this HTTPResponse is wrapped " + "around has no file descriptor") + + def flush(self): + if self._fp is not None and hasattr(self._fp, 'flush'): + return self._fp.flush() + + def readable(self): + # This method is required for `io` module compatibility. + return True + + def readinto(self, b): + # This method is required for `io` module compatibility. + temp = self.read(len(b)) + if len(temp) == 0: + return 0 + else: + b[:len(temp)] = temp + return len(temp) + + def supports_chunked_reads(self): + """ + Checks if the underlying file-like object looks like a + httplib.HTTPResponse object. We do this by testing for the fp + attribute. If it is present we assume it returns raw chunks as + processed by read_chunked(). + """ + return hasattr(self._fp, 'fp') + + def _update_chunk_length(self): + # First, we'll figure out length of a chunk and then + # we'll try to read it from socket. + if self.chunk_left is not None: + return + line = self._fp.fp.readline() + line = line.split(b';', 1)[0] + try: + self.chunk_left = int(line, 16) + except ValueError: + # Invalid chunked protocol response, abort. + self.close() + raise httplib.IncompleteRead(line) + + def _handle_chunk(self, amt): + returned_chunk = None + if amt is None: + chunk = self._fp._safe_read(self.chunk_left) + returned_chunk = chunk + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + elif amt < self.chunk_left: + value = self._fp._safe_read(amt) + self.chunk_left = self.chunk_left - amt + returned_chunk = value + elif amt == self.chunk_left: + value = self._fp._safe_read(amt) + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + returned_chunk = value + else: # amt > self.chunk_left + returned_chunk = self._fp._safe_read(self.chunk_left) + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + return returned_chunk + + def read_chunked(self, amt=None, decode_content=None): + """ + Similar to :meth:`HTTPResponse.read`, but with an additional + parameter: ``decode_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + self._init_decoder() + # FIXME: Rewrite this method and make it a class with a better structured logic. + if not self.chunked: + raise ResponseNotChunked( + "Response is not chunked. " + "Header 'transfer-encoding: chunked' is missing.") + if not self.supports_chunked_reads(): + raise BodyNotHttplibCompatible( + "Body should be httplib.HTTPResponse like. " + "It should have have an fp attribute which returns raw chunks.") + + with self._error_catcher(): + # Don't bother reading the body of a HEAD request. + if self._original_response and is_response_to_head(self._original_response): + self._original_response.close() + return + + # If a response is already read and closed + # then return immediately. + if self._fp.fp is None: + return + + while True: + self._update_chunk_length() + if self.chunk_left == 0: + break + chunk = self._handle_chunk(amt) + decoded = self._decode(chunk, decode_content=decode_content, + flush_decoder=False) + if decoded: + yield decoded + + if decode_content: + # On CPython and PyPy, we should never need to flush the + # decoder. However, on Jython we *might* need to, so + # lets defensively do it anyway. + decoded = self._flush_decoder() + if decoded: # Platform-specific: Jython. + yield decoded + + # Chunk content ends with \r\n: discard it. + while True: + line = self._fp.fp.readline() + if not line: + # Some sites may not end with '\r\n'. + break + if line == b'\r\n': + break + + # We read everything; close the "file". + if self._original_response: + self._original_response.close() + + def geturl(self): + """ + Returns the URL that was the source of this response. + If the request that generated this response redirected, this method + will return the final redirect location. + """ + if self.retries is not None and len(self.retries.history): + return self.retries.history[-1].redirect_location + else: + return self._request_url diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__init__.py new file mode 100644 index 0000000..2f2770b --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/__init__.py @@ -0,0 +1,54 @@ +from __future__ import absolute_import +# For backwards compatibility, provide imports that used to be here. +from .connection import is_connection_dropped +from .request import make_headers +from .response import is_fp_closed +from .ssl_ import ( + SSLContext, + HAS_SNI, + IS_PYOPENSSL, + IS_SECURETRANSPORT, + assert_fingerprint, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) +from .timeout import ( + current_time, + Timeout, +) + +from .retry import Retry +from .url import ( + get_host, + parse_url, + split_first, + Url, +) +from .wait import ( + wait_for_read, + wait_for_write +) + +__all__ = ( + 'HAS_SNI', + 'IS_PYOPENSSL', + 'IS_SECURETRANSPORT', + 'SSLContext', + 'Retry', + 'Timeout', + 'Url', + 'assert_fingerprint', + 'current_time', + 'is_connection_dropped', + 'is_fp_closed', + 'get_host', + 'parse_url', + 'make_headers', + 'resolve_cert_reqs', + 'resolve_ssl_version', + 'split_first', + 'ssl_wrap_socket', + 'wait_for_read', + 'wait_for_write' +) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/connection.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/connection.py new file mode 100644 index 0000000..5cf488f --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/connection.py @@ -0,0 +1,126 @@ +from __future__ import absolute_import +import socket +from .wait import NoWayToWaitForSocketError, wait_for_read + + +def is_connection_dropped(conn): # Platform-specific + """ + Returns True if the connection is dropped and should be closed. + + :param conn: + :class:`httplib.HTTPConnection` object. + + Note: For platforms like AppEngine, this will always return ``False`` to + let the platform handle connection recycling transparently for us. + """ + sock = getattr(conn, 'sock', False) + if sock is False: # Platform-specific: AppEngine + return False + if sock is None: # Connection already closed (such as by httplib). + return True + try: + # Returns True if readable, which here means it's been dropped + return wait_for_read(sock, timeout=0.0) + except NoWayToWaitForSocketError: # Platform-specific: AppEngine + return False + + +# This function is copied from socket.py in the Python 2.7 standard +# library test suite. Added to its signature is only `socket_options`. +# One additional modification is that we avoid binding to IPv6 servers +# discovered in DNS if the system doesn't have IPv6 functionality. +def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, + source_address=None, socket_options=None): + """Connect to *address* and return the socket object. + + Convenience function. Connect to *address* (a 2-tuple ``(host, + port)``) and return the socket object. Passing the optional + *timeout* parameter will set the timeout on the socket instance + before attempting to connect. If no *timeout* is supplied, the + global default timeout setting returned by :func:`getdefaulttimeout` + is used. If *source_address* is set it must be a tuple of (host, port) + for the socket to bind as a source address before making the connection. + An host of '' or port 0 tells the OS to use the default. + """ + + host, port = address + if host.startswith('['): + host = host.strip('[]') + err = None + + # Using the value from allowed_gai_family() in the context of getaddrinfo lets + # us select whether to work with IPv4 DNS records, IPv6 records, or both. + # The original create_connection function always returns all records. + family = allowed_gai_family() + + for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None + try: + sock = socket.socket(af, socktype, proto) + + # If provided, set socket level options before connecting. + _set_socket_options(sock, socket_options) + + if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: + sock.settimeout(timeout) + if source_address: + sock.bind(source_address) + sock.connect(sa) + return sock + + except socket.error as e: + err = e + if sock is not None: + sock.close() + sock = None + + if err is not None: + raise err + + raise socket.error("getaddrinfo returns an empty list") + + +def _set_socket_options(sock, options): + if options is None: + return + + for opt in options: + sock.setsockopt(*opt) + + +def allowed_gai_family(): + """This function is designed to work in the context of + getaddrinfo, where family=socket.AF_UNSPEC is the default and + will perform a DNS search for both IPv6 and IPv4 records.""" + + family = socket.AF_INET + if HAS_IPV6: + family = socket.AF_UNSPEC + return family + + +def _has_ipv6(host): + """ Returns True if the system can bind an IPv6 address. """ + sock = None + has_ipv6 = False + + if socket.has_ipv6: + # has_ipv6 returns true if cPython was compiled with IPv6 support. + # It does not tell us if the system has IPv6 support enabled. To + # determine that we must bind to an IPv6 address. + # https://github.com/shazow/urllib3/pull/611 + # https://bugs.python.org/issue658327 + try: + sock = socket.socket(socket.AF_INET6) + sock.bind((host, 0)) + has_ipv6 = True + except Exception: + pass + + if sock: + sock.close() + return has_ipv6 + + +HAS_IPV6 = _has_ipv6('::1') diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/queue.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/queue.py new file mode 100644 index 0000000..d3d379a --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/queue.py @@ -0,0 +1,21 @@ +import collections +from ..packages import six +from ..packages.six.moves import queue + +if six.PY2: + # Queue is imported for side effects on MS Windows. See issue #229. + import Queue as _unused_module_Queue # noqa: F401 + + +class LifoQueue(queue.Queue): + def _init(self, _): + self.queue = collections.deque() + + def _qsize(self, len=len): + return len(self.queue) + + def _put(self, item): + self.queue.append(item) + + def _get(self): + return self.queue.pop() diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/request.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/request.py new file mode 100644 index 0000000..3ddfcd5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/request.py @@ -0,0 +1,118 @@ +from __future__ import absolute_import +from base64 import b64encode + +from ..packages.six import b, integer_types +from ..exceptions import UnrewindableBodyError + +ACCEPT_ENCODING = 'gzip,deflate' +_FAILEDTELL = object() + + +def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, + basic_auth=None, proxy_basic_auth=None, disable_cache=None): + """ + Shortcuts for generating request headers. + + :param keep_alive: + If ``True``, adds 'connection: keep-alive' header. + + :param accept_encoding: + Can be a boolean, list, or string. + ``True`` translates to 'gzip,deflate'. + List will get joined by comma. + String will be used as provided. + + :param user_agent: + String representing the user-agent you want, such as + "python-urllib3/0.6" + + :param basic_auth: + Colon-separated username:password string for 'authorization: basic ...' + auth header. + + :param proxy_basic_auth: + Colon-separated username:password string for 'proxy-authorization: basic ...' + auth header. + + :param disable_cache: + If ``True``, adds 'cache-control: no-cache' header. + + Example:: + + >>> make_headers(keep_alive=True, user_agent="Batman/1.0") + {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} + >>> make_headers(accept_encoding=True) + {'accept-encoding': 'gzip,deflate'} + """ + headers = {} + if accept_encoding: + if isinstance(accept_encoding, str): + pass + elif isinstance(accept_encoding, list): + accept_encoding = ','.join(accept_encoding) + else: + accept_encoding = ACCEPT_ENCODING + headers['accept-encoding'] = accept_encoding + + if user_agent: + headers['user-agent'] = user_agent + + if keep_alive: + headers['connection'] = 'keep-alive' + + if basic_auth: + headers['authorization'] = 'Basic ' + \ + b64encode(b(basic_auth)).decode('utf-8') + + if proxy_basic_auth: + headers['proxy-authorization'] = 'Basic ' + \ + b64encode(b(proxy_basic_auth)).decode('utf-8') + + if disable_cache: + headers['cache-control'] = 'no-cache' + + return headers + + +def set_file_position(body, pos): + """ + If a position is provided, move file to that point. + Otherwise, we'll attempt to record a position for future use. + """ + if pos is not None: + rewind_body(body, pos) + elif getattr(body, 'tell', None) is not None: + try: + pos = body.tell() + except (IOError, OSError): + # This differentiates from None, allowing us to catch + # a failed `tell()` later when trying to rewind the body. + pos = _FAILEDTELL + + return pos + + +def rewind_body(body, body_pos): + """ + Attempt to rewind body to a certain position. + Primarily used for request redirects and retries. + + :param body: + File-like object that supports seek. + + :param int pos: + Position to seek to in file. + """ + body_seek = getattr(body, 'seek', None) + if body_seek is not None and isinstance(body_pos, integer_types): + try: + body_seek(body_pos) + except (IOError, OSError): + raise UnrewindableBodyError("An error occurred when rewinding request " + "body for redirect/retry.") + elif body_pos is _FAILEDTELL: + raise UnrewindableBodyError("Unable to record file position for rewinding " + "request body during a redirect/retry.") + else: + raise ValueError("body_pos must be of type integer, " + "instead it was %s." % type(body_pos)) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/response.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/response.py new file mode 100644 index 0000000..67cf730 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/response.py @@ -0,0 +1,81 @@ +from __future__ import absolute_import +from ..packages.six.moves import http_client as httplib + +from ..exceptions import HeaderParsingError + + +def is_fp_closed(obj): + """ + Checks whether a given file-like object is closed. + + :param obj: + The file-like object to check. + """ + + try: + # Check `isclosed()` first, in case Python3 doesn't set `closed`. + # GH Issue #928 + return obj.isclosed() + except AttributeError: + pass + + try: + # Check via the official file-like-object way. + return obj.closed + except AttributeError: + pass + + try: + # Check if the object is a container for another file-like object that + # gets released on exhaustion (e.g. HTTPResponse). + return obj.fp is None + except AttributeError: + pass + + raise ValueError("Unable to determine whether fp is closed.") + + +def assert_header_parsing(headers): + """ + Asserts whether all headers have been successfully parsed. + Extracts encountered errors from the result of parsing headers. + + Only works on Python 3. + + :param headers: Headers to verify. + :type headers: `httplib.HTTPMessage`. + + :raises urllib3.exceptions.HeaderParsingError: + If parsing errors are found. + """ + + # This will fail silently if we pass in the wrong kind of parameter. + # To make debugging easier add an explicit check. + if not isinstance(headers, httplib.HTTPMessage): + raise TypeError('expected httplib.Message, got {0}.'.format( + type(headers))) + + defects = getattr(headers, 'defects', None) + get_payload = getattr(headers, 'get_payload', None) + + unparsed_data = None + if get_payload: # Platform-specific: Python 3. + unparsed_data = get_payload() + + if defects or unparsed_data: + raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) + + +def is_response_to_head(response): + """ + Checks whether the request of a response has been a HEAD-request. + Handles the quirks of AppEngine. + + :param conn: + :type conn: :class:`httplib.HTTPResponse` + """ + # FIXME: Can we do this somehow without accessing private httplib _method? + method = response._method + if isinstance(method, int): # Platform-specific: Appengine + return method == 3 + return method.upper() == 'HEAD' diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/retry.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/retry.py new file mode 100644 index 0000000..7ad3dc6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/retry.py @@ -0,0 +1,411 @@ +from __future__ import absolute_import +import time +import logging +from collections import namedtuple +from itertools import takewhile +import email +import re + +from ..exceptions import ( + ConnectTimeoutError, + MaxRetryError, + ProtocolError, + ReadTimeoutError, + ResponseError, + InvalidHeader, +) +from ..packages import six + + +log = logging.getLogger(__name__) + + +# Data structure for representing the metadata of requests that result in a retry. +RequestHistory = namedtuple('RequestHistory', ["method", "url", "error", + "status", "redirect_location"]) + + +class Retry(object): + """ Retry configuration. + + Each retry attempt will create a new Retry object with updated values, so + they can be safely reused. + + Retries can be defined as a default for a pool:: + + retries = Retry(connect=5, read=2, redirect=5) + http = PoolManager(retries=retries) + response = http.request('GET', 'http://example.com/') + + Or per-request (which overrides the default for the pool):: + + response = http.request('GET', 'http://example.com/', retries=Retry(10)) + + Retries can be disabled by passing ``False``:: + + response = http.request('GET', 'http://example.com/', retries=False) + + Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless + retries are disabled, in which case the causing exception will be raised. + + :param int total: + Total number of retries to allow. Takes precedence over other counts. + + Set to ``None`` to remove this constraint and fall back on other + counts. It's a good idea to set this to some sensibly-high value to + account for unexpected edge cases and avoid infinite retry loops. + + Set to ``0`` to fail on the first retry. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int connect: + How many connection-related errors to retry on. + + These are errors raised before the request is sent to the remote server, + which we assume has not triggered the server to process the request. + + Set to ``0`` to fail on the first retry of this type. + + :param int read: + How many times to retry on read errors. + + These errors are raised after the request was sent to the server, so the + request may have side-effects. + + Set to ``0`` to fail on the first retry of this type. + + :param int redirect: + How many redirects to perform. Limit this to avoid infinite redirect + loops. + + A redirect is a HTTP response with a status code 301, 302, 303, 307 or + 308. + + Set to ``0`` to fail on the first retry of this type. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int status: + How many times to retry on bad status codes. + + These are retries made on responses, where status code matches + ``status_forcelist``. + + Set to ``0`` to fail on the first retry of this type. + + :param iterable method_whitelist: + Set of uppercased HTTP method verbs that we should retry on. + + By default, we only retry on methods which are considered to be + idempotent (multiple requests with the same parameters end with the + same state). See :attr:`Retry.DEFAULT_METHOD_WHITELIST`. + + Set to a ``False`` value to retry on any verb. + + :param iterable status_forcelist: + A set of integer HTTP status codes that we should force a retry on. + A retry is initiated if the request method is in ``method_whitelist`` + and the response status code is in ``status_forcelist``. + + By default, this is disabled with ``None``. + + :param float backoff_factor: + A backoff factor to apply between attempts after the second try + (most errors are resolved immediately by a second try without a + delay). urllib3 will sleep for:: + + {backoff factor} * (2 ^ ({number of total retries} - 1)) + + seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep + for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer + than :attr:`Retry.BACKOFF_MAX`. + + By default, backoff is disabled (set to 0). + + :param bool raise_on_redirect: Whether, if the number of redirects is + exhausted, to raise a MaxRetryError, or to return a response with a + response code in the 3xx range. + + :param bool raise_on_status: Similar meaning to ``raise_on_redirect``: + whether we should raise an exception, or return a response, + if status falls in ``status_forcelist`` range and retries have + been exhausted. + + :param tuple history: The history of the request encountered during + each call to :meth:`~Retry.increment`. The list is in the order + the requests occurred. Each list item is of class :class:`RequestHistory`. + + :param bool respect_retry_after_header: + Whether to respect Retry-After header on status codes defined as + :attr:`Retry.RETRY_AFTER_STATUS_CODES` or not. + + :param iterable remove_headers_on_redirect: + Sequence of headers to remove from the request when a response + indicating a redirect is returned before firing off the redirected + request. + """ + + DEFAULT_METHOD_WHITELIST = frozenset([ + 'HEAD', 'GET', 'PUT', 'DELETE', 'OPTIONS', 'TRACE']) + + RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) + + DEFAULT_REDIRECT_HEADERS_BLACKLIST = frozenset(['Authorization']) + + #: Maximum backoff time. + BACKOFF_MAX = 120 + + def __init__(self, total=10, connect=None, read=None, redirect=None, status=None, + method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None, + backoff_factor=0, raise_on_redirect=True, raise_on_status=True, + history=None, respect_retry_after_header=True, + remove_headers_on_redirect=DEFAULT_REDIRECT_HEADERS_BLACKLIST): + + self.total = total + self.connect = connect + self.read = read + self.status = status + + if redirect is False or total is False: + redirect = 0 + raise_on_redirect = False + + self.redirect = redirect + self.status_forcelist = status_forcelist or set() + self.method_whitelist = method_whitelist + self.backoff_factor = backoff_factor + self.raise_on_redirect = raise_on_redirect + self.raise_on_status = raise_on_status + self.history = history or tuple() + self.respect_retry_after_header = respect_retry_after_header + self.remove_headers_on_redirect = remove_headers_on_redirect + + def new(self, **kw): + params = dict( + total=self.total, + connect=self.connect, read=self.read, redirect=self.redirect, status=self.status, + method_whitelist=self.method_whitelist, + status_forcelist=self.status_forcelist, + backoff_factor=self.backoff_factor, + raise_on_redirect=self.raise_on_redirect, + raise_on_status=self.raise_on_status, + history=self.history, + remove_headers_on_redirect=self.remove_headers_on_redirect + ) + params.update(kw) + return type(self)(**params) + + @classmethod + def from_int(cls, retries, redirect=True, default=None): + """ Backwards-compatibility for the old retries format.""" + if retries is None: + retries = default if default is not None else cls.DEFAULT + + if isinstance(retries, Retry): + return retries + + redirect = bool(redirect) and None + new_retries = cls(retries, redirect=redirect) + log.debug("Converted retries value: %r -> %r", retries, new_retries) + return new_retries + + def get_backoff_time(self): + """ Formula for computing the current backoff + + :rtype: float + """ + # We want to consider only the last consecutive errors sequence (Ignore redirects). + consecutive_errors_len = len(list(takewhile(lambda x: x.redirect_location is None, + reversed(self.history)))) + if consecutive_errors_len <= 1: + return 0 + + backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1)) + return min(self.BACKOFF_MAX, backoff_value) + + def parse_retry_after(self, retry_after): + # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = int(retry_after) + else: + retry_date_tuple = email.utils.parsedate(retry_after) + if retry_date_tuple is None: + raise InvalidHeader("Invalid Retry-After header: %s" % retry_after) + retry_date = time.mktime(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: + seconds = 0 + + return seconds + + def get_retry_after(self, response): + """ Get the value of Retry-After in seconds. """ + + retry_after = response.getheader("Retry-After") + + if retry_after is None: + return None + + return self.parse_retry_after(retry_after) + + def sleep_for_retry(self, response=None): + retry_after = self.get_retry_after(response) + if retry_after: + time.sleep(retry_after) + return True + + return False + + def _sleep_backoff(self): + backoff = self.get_backoff_time() + if backoff <= 0: + return + time.sleep(backoff) + + def sleep(self, response=None): + """ Sleep between retry attempts. + + This method will respect a server's ``Retry-After`` response header + and sleep the duration of the time requested. If that is not present, it + will use an exponential backoff. By default, the backoff factor is 0 and + this method will return immediately. + """ + + if response: + slept = self.sleep_for_retry(response) + if slept: + return + + self._sleep_backoff() + + def _is_connection_error(self, err): + """ Errors when we're fairly sure that the server did not receive the + request, so it should be safe to retry. + """ + return isinstance(err, ConnectTimeoutError) + + def _is_read_error(self, err): + """ Errors that occur after the request has been started, so we should + assume that the server began processing it. + """ + return isinstance(err, (ReadTimeoutError, ProtocolError)) + + def _is_method_retryable(self, method): + """ Checks if a given HTTP method should be retried upon, depending if + it is included on the method whitelist. + """ + if self.method_whitelist and method.upper() not in self.method_whitelist: + return False + + return True + + def is_retry(self, method, status_code, has_retry_after=False): + """ Is this method/status code retryable? (Based on whitelists and control + variables such as the number of total retries to allow, whether to + respect the Retry-After header, whether this header is present, and + whether the returned status code is on the list of status codes to + be retried upon on the presence of the aforementioned header) + """ + if not self._is_method_retryable(method): + return False + + if self.status_forcelist and status_code in self.status_forcelist: + return True + + return (self.total and self.respect_retry_after_header and + has_retry_after and (status_code in self.RETRY_AFTER_STATUS_CODES)) + + def is_exhausted(self): + """ Are we out of retries? """ + retry_counts = (self.total, self.connect, self.read, self.redirect, self.status) + retry_counts = list(filter(None, retry_counts)) + if not retry_counts: + return False + + return min(retry_counts) < 0 + + def increment(self, method=None, url=None, response=None, error=None, + _pool=None, _stacktrace=None): + """ Return a new Retry object with incremented retry counters. + + :param response: A response object, or None, if the server did not + return a response. + :type response: :class:`~urllib3.response.HTTPResponse` + :param Exception error: An error encountered during the request, or + None if the response was received successfully. + + :return: A new ``Retry`` object. + """ + if self.total is False and error: + # Disabled, indicate to re-raise the error. + raise six.reraise(type(error), error, _stacktrace) + + total = self.total + if total is not None: + total -= 1 + + connect = self.connect + read = self.read + redirect = self.redirect + status_count = self.status + cause = 'unknown' + status = None + redirect_location = None + + if error and self._is_connection_error(error): + # Connect retry? + if connect is False: + raise six.reraise(type(error), error, _stacktrace) + elif connect is not None: + connect -= 1 + + elif error and self._is_read_error(error): + # Read retry? + if read is False or not self._is_method_retryable(method): + raise six.reraise(type(error), error, _stacktrace) + elif read is not None: + read -= 1 + + elif response and response.get_redirect_location(): + # Redirect retry? + if redirect is not None: + redirect -= 1 + cause = 'too many redirects' + redirect_location = response.get_redirect_location() + status = response.status + + else: + # Incrementing because of a server error like a 500 in + # status_forcelist and a the given method is in the whitelist + cause = ResponseError.GENERIC_ERROR + if response and response.status: + if status_count is not None: + status_count -= 1 + cause = ResponseError.SPECIFIC_ERROR.format( + status_code=response.status) + status = response.status + + history = self.history + (RequestHistory(method, url, error, status, redirect_location),) + + new_retry = self.new( + total=total, + connect=connect, read=read, redirect=redirect, status=status_count, + history=history) + + if new_retry.is_exhausted(): + raise MaxRetryError(_pool, url, error or ResponseError(cause)) + + log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) + + return new_retry + + def __repr__(self): + return ('{cls.__name__}(total={self.total}, connect={self.connect}, ' + 'read={self.read}, redirect={self.redirect}, status={self.status})').format( + cls=type(self), self=self) + + +# For backwards compatibility (equivalent to pre-v1.9): +Retry.DEFAULT = Retry(3) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/ssl_.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/ssl_.py new file mode 100644 index 0000000..3254280 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/ssl_.py @@ -0,0 +1,396 @@ +from __future__ import absolute_import +import errno +import warnings +import hmac +import socket + +from binascii import hexlify, unhexlify +from hashlib import md5, sha1, sha256 + +from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning +from ..packages import six + + +SSLContext = None +HAS_SNI = False +IS_PYOPENSSL = False +IS_SECURETRANSPORT = False + +# Maps the length of a digest to a possible hash function producing this digest +HASHFUNC_MAP = { + 32: md5, + 40: sha1, + 64: sha256, +} + + +def _const_compare_digest_backport(a, b): + """ + Compare two digests of equal length in constant time. + + The digests must be of type str/bytes. + Returns True if the digests match, and False otherwise. + """ + result = abs(len(a) - len(b)) + for l, r in zip(bytearray(a), bytearray(b)): + result |= l ^ r + return result == 0 + + +_const_compare_digest = getattr(hmac, 'compare_digest', + _const_compare_digest_backport) + + +try: # Test for SSL features + import ssl + from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23 + from ssl import HAS_SNI # Has SNI? +except ImportError: + pass + + +try: + from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION +except ImportError: + OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000 + OP_NO_COMPRESSION = 0x20000 + + +# Python 2.7 and earlier didn't have inet_pton on non-Linux +# so we fallback on inet_aton in those cases. This means that +# we can only detect IPv4 addresses in this case. +if hasattr(socket, 'inet_pton'): + inet_pton = socket.inet_pton +else: + # Maybe we can use ipaddress if the user has urllib3[secure]? + try: + from pip._vendor import ipaddress + + def inet_pton(_, host): + if isinstance(host, six.binary_type): + host = host.decode('ascii') + return ipaddress.ip_address(host) + + except ImportError: # Platform-specific: Non-Linux + def inet_pton(_, host): + return socket.inet_aton(host) + + +# A secure default. +# Sources for more information on TLS ciphers: +# +# - https://wiki.mozilla.org/Security/Server_Side_TLS +# - https://www.ssllabs.com/projects/best-practices/index.html +# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ +# +# The general intent is: +# - Prefer TLS 1.3 cipher suites +# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE), +# - prefer ECDHE over DHE for better performance, +# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and +# security, +# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common, +# - disable NULL authentication, MD5 MACs and DSS for security reasons. +DEFAULT_CIPHERS = ':'.join([ + 'TLS13-AES-256-GCM-SHA384', + 'TLS13-CHACHA20-POLY1305-SHA256', + 'TLS13-AES-128-GCM-SHA256', + 'ECDH+AESGCM', + 'ECDH+CHACHA20', + 'DH+AESGCM', + 'DH+CHACHA20', + 'ECDH+AES256', + 'DH+AES256', + 'ECDH+AES128', + 'DH+AES', + 'RSA+AESGCM', + 'RSA+AES', + '!aNULL', + '!eNULL', + '!MD5', +]) + +try: + from ssl import SSLContext # Modern SSL? +except ImportError: + import sys + + class SSLContext(object): # Platform-specific: Python 2 & 3.1 + supports_set_ciphers = ((2, 7) <= sys.version_info < (3,) or + (3, 2) <= sys.version_info) + + def __init__(self, protocol_version): + self.protocol = protocol_version + # Use default values from a real SSLContext + self.check_hostname = False + self.verify_mode = ssl.CERT_NONE + self.ca_certs = None + self.options = 0 + self.certfile = None + self.keyfile = None + self.ciphers = None + + def load_cert_chain(self, certfile, keyfile): + self.certfile = certfile + self.keyfile = keyfile + + def load_verify_locations(self, cafile=None, capath=None): + self.ca_certs = cafile + + if capath is not None: + raise SSLError("CA directories not supported in older Pythons") + + def set_ciphers(self, cipher_suite): + if not self.supports_set_ciphers: + raise TypeError( + 'Your version of Python does not support setting ' + 'a custom cipher suite. Please upgrade to Python ' + '2.7, 3.2, or later if you need this functionality.' + ) + self.ciphers = cipher_suite + + def wrap_socket(self, socket, server_hostname=None, server_side=False): + warnings.warn( + 'A true SSLContext object is not available. This prevents ' + 'urllib3 from configuring SSL appropriately and may cause ' + 'certain SSL connections to fail. You can upgrade to a newer ' + 'version of Python to solve this. For more information, see ' + 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' + '#ssl-warnings', + InsecurePlatformWarning + ) + kwargs = { + 'keyfile': self.keyfile, + 'certfile': self.certfile, + 'ca_certs': self.ca_certs, + 'cert_reqs': self.verify_mode, + 'ssl_version': self.protocol, + 'server_side': server_side, + } + if self.supports_set_ciphers: # Platform-specific: Python 2.7+ + return wrap_socket(socket, ciphers=self.ciphers, **kwargs) + else: # Platform-specific: Python 2.6 + return wrap_socket(socket, **kwargs) + + +def assert_fingerprint(cert, fingerprint): + """ + Checks if given fingerprint matches the supplied certificate. + + :param cert: + Certificate as bytes object. + :param fingerprint: + Fingerprint as string of hexdigits, can be interspersed by colons. + """ + + fingerprint = fingerprint.replace(':', '').lower() + digest_length = len(fingerprint) + hashfunc = HASHFUNC_MAP.get(digest_length) + if not hashfunc: + raise SSLError( + 'Fingerprint of invalid length: {0}'.format(fingerprint)) + + # We need encode() here for py32; works on py2 and p33. + fingerprint_bytes = unhexlify(fingerprint.encode()) + + cert_digest = hashfunc(cert).digest() + + if not _const_compare_digest(cert_digest, fingerprint_bytes): + raise SSLError('Fingerprints did not match. Expected "{0}", got "{1}".' + .format(fingerprint, hexlify(cert_digest))) + + +def resolve_cert_reqs(candidate): + """ + Resolves the argument to a numeric constant, which can be passed to + the wrap_socket function/method from the ssl module. + Defaults to :data:`ssl.CERT_NONE`. + If given a string it is assumed to be the name of the constant in the + :mod:`ssl` module or its abbreviation. + (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. + If it's neither `None` nor a string we assume it is already the numeric + constant which can directly be passed to wrap_socket. + """ + if candidate is None: + return CERT_NONE + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, 'CERT_' + candidate) + return res + + return candidate + + +def resolve_ssl_version(candidate): + """ + like resolve_cert_reqs + """ + if candidate is None: + return PROTOCOL_SSLv23 + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, 'PROTOCOL_' + candidate) + return res + + return candidate + + +def create_urllib3_context(ssl_version=None, cert_reqs=None, + options=None, ciphers=None): + """All arguments have the same meaning as ``ssl_wrap_socket``. + + By default, this function does a lot of the same work that + ``ssl.create_default_context`` does on Python 3.4+. It: + + - Disables SSLv2, SSLv3, and compression + - Sets a restricted set of server ciphers + + If you wish to enable SSLv3, you can do:: + + from pip._vendor.urllib3.util import ssl_ + context = ssl_.create_urllib3_context() + context.options &= ~ssl_.OP_NO_SSLv3 + + You can do the same to enable compression (substituting ``COMPRESSION`` + for ``SSLv3`` in the last line above). + + :param ssl_version: + The desired protocol version to use. This will default to + PROTOCOL_SSLv23 which will negotiate the highest protocol that both + the server and your installation of OpenSSL support. + :param cert_reqs: + Whether to require the certificate verification. This defaults to + ``ssl.CERT_REQUIRED``. + :param options: + Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, + ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``. + :param ciphers: + Which cipher suites to allow the server to select. + :returns: + Constructed SSLContext object with specified options + :rtype: SSLContext + """ + context = SSLContext(ssl_version or ssl.PROTOCOL_SSLv23) + + # Setting the default here, as we may have no ssl module on import + cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs + + if options is None: + options = 0 + # SSLv2 is easily broken and is considered harmful and dangerous + options |= OP_NO_SSLv2 + # SSLv3 has several problems and is now dangerous + options |= OP_NO_SSLv3 + # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ + # (issue #309) + options |= OP_NO_COMPRESSION + + context.options |= options + + if getattr(context, 'supports_set_ciphers', True): # Platform-specific: Python 2.6 + context.set_ciphers(ciphers or DEFAULT_CIPHERS) + + context.verify_mode = cert_reqs + if getattr(context, 'check_hostname', None) is not None: # Platform-specific: Python 3.2 + # We do our own verification, including fingerprints and alternative + # hostnames. So disable it here + context.check_hostname = False + return context + + +def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, + ca_certs=None, server_hostname=None, + ssl_version=None, ciphers=None, ssl_context=None, + ca_cert_dir=None): + """ + All arguments except for server_hostname, ssl_context, and ca_cert_dir have + the same meaning as they do when using :func:`ssl.wrap_socket`. + + :param server_hostname: + When SNI is supported, the expected hostname of the certificate + :param ssl_context: + A pre-made :class:`SSLContext` object. If none is provided, one will + be created using :func:`create_urllib3_context`. + :param ciphers: + A string of ciphers we wish the client to support. This is not + supported on Python 2.6 as the ssl module does not support it. + :param ca_cert_dir: + A directory containing CA certificates in multiple separate files, as + supported by OpenSSL's -CApath flag or the capath argument to + SSLContext.load_verify_locations(). + """ + context = ssl_context + if context is None: + # Note: This branch of code and all the variables in it are no longer + # used by urllib3 itself. We should consider deprecating and removing + # this code. + context = create_urllib3_context(ssl_version, cert_reqs, + ciphers=ciphers) + + if ca_certs or ca_cert_dir: + try: + context.load_verify_locations(ca_certs, ca_cert_dir) + except IOError as e: # Platform-specific: Python 2.6, 2.7, 3.2 + raise SSLError(e) + # Py33 raises FileNotFoundError which subclasses OSError + # These are not equivalent unless we check the errno attribute + except OSError as e: # Platform-specific: Python 3.3 and beyond + if e.errno == errno.ENOENT: + raise SSLError(e) + raise + elif getattr(context, 'load_default_certs', None) is not None: + # try to load OS default certs; works well on Windows (require Python3.4+) + context.load_default_certs() + + if certfile: + context.load_cert_chain(certfile, keyfile) + + # If we detect server_hostname is an IP address then the SNI + # extension should not be used according to RFC3546 Section 3.1 + # We shouldn't warn the user if SNI isn't available but we would + # not be using SNI anyways due to IP address for server_hostname. + if ((server_hostname is not None and not is_ipaddress(server_hostname)) + or IS_SECURETRANSPORT): + if HAS_SNI and server_hostname is not None: + return context.wrap_socket(sock, server_hostname=server_hostname) + + warnings.warn( + 'An HTTPS request has been made, but the SNI (Server Name ' + 'Indication) extension to TLS is not available on this platform. ' + 'This may cause the server to present an incorrect TLS ' + 'certificate, which can cause validation failures. You can upgrade to ' + 'a newer version of Python to solve this. For more information, see ' + 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' + '#ssl-warnings', + SNIMissingWarning + ) + + return context.wrap_socket(sock) + + +def is_ipaddress(hostname): + """Detects whether the hostname given is an IP address. + + :param str hostname: Hostname to examine. + :return: True if the hostname is an IP address, False otherwise. + """ + if six.PY3 and isinstance(hostname, six.binary_type): + # IDN A-label bytes are ASCII compatible. + hostname = hostname.decode('ascii') + + families = [socket.AF_INET] + if hasattr(socket, 'AF_INET6'): + families.append(socket.AF_INET6) + + for af in families: + try: + inet_pton(af, hostname) + except (socket.error, ValueError, OSError): + pass + else: + return True + return False diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/timeout.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/timeout.py new file mode 100644 index 0000000..cec817e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/timeout.py @@ -0,0 +1,242 @@ +from __future__ import absolute_import +# The default socket timeout, used by httplib to indicate that no timeout was +# specified by the user +from socket import _GLOBAL_DEFAULT_TIMEOUT +import time + +from ..exceptions import TimeoutStateError + +# A sentinel value to indicate that no timeout was specified by the user in +# urllib3 +_Default = object() + + +# Use time.monotonic if available. +current_time = getattr(time, "monotonic", time.time) + + +class Timeout(object): + """ Timeout configuration. + + Timeouts can be defined as a default for a pool:: + + timeout = Timeout(connect=2.0, read=7.0) + http = PoolManager(timeout=timeout) + response = http.request('GET', 'http://example.com/') + + Or per-request (which overrides the default for the pool):: + + response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) + + Timeouts can be disabled by setting all the parameters to ``None``:: + + no_timeout = Timeout(connect=None, read=None) + response = http.request('GET', 'http://example.com/, timeout=no_timeout) + + + :param total: + This combines the connect and read timeouts into one; the read timeout + will be set to the time leftover from the connect attempt. In the + event that both a connect timeout and a total are specified, or a read + timeout and a total are specified, the shorter timeout will be applied. + + Defaults to None. + + :type total: integer, float, or None + + :param connect: + The maximum amount of time to wait for a connection attempt to a server + to succeed. Omitting the parameter will default the connect timeout to + the system default, probably `the global default timeout in socket.py + <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. + None will set an infinite timeout for connection attempts. + + :type connect: integer, float, or None + + :param read: + The maximum amount of time to wait between consecutive + read operations for a response from the server. Omitting + the parameter will default the read timeout to the system + default, probably `the global default timeout in socket.py + <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. + None will set an infinite timeout. + + :type read: integer, float, or None + + .. note:: + + Many factors can affect the total amount of time for urllib3 to return + an HTTP response. + + For example, Python's DNS resolver does not obey the timeout specified + on the socket. Other factors that can affect total request time include + high CPU load, high swap, the program running at a low priority level, + or other behaviors. + + In addition, the read and total timeouts only measure the time between + read operations on the socket connecting the client and the server, + not the total amount of time for the request to return a complete + response. For most requests, the timeout is raised because the server + has not sent the first byte in the specified time. This is not always + the case; if a server streams one byte every fifteen seconds, a timeout + of 20 seconds will not trigger, even though the request will take + several minutes to complete. + + If your goal is to cut off any request after a set amount of wall clock + time, consider having a second "watcher" thread to cut off a slow + request. + """ + + #: A sentinel object representing the default timeout value + DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT + + def __init__(self, total=None, connect=_Default, read=_Default): + self._connect = self._validate_timeout(connect, 'connect') + self._read = self._validate_timeout(read, 'read') + self.total = self._validate_timeout(total, 'total') + self._start_connect = None + + def __str__(self): + return '%s(connect=%r, read=%r, total=%r)' % ( + type(self).__name__, self._connect, self._read, self.total) + + @classmethod + def _validate_timeout(cls, value, name): + """ Check that a timeout attribute is valid. + + :param value: The timeout value to validate + :param name: The name of the timeout attribute to validate. This is + used to specify in error messages. + :return: The validated and casted version of the given value. + :raises ValueError: If it is a numeric value less than or equal to + zero, or the type is not an integer, float, or None. + """ + if value is _Default: + return cls.DEFAULT_TIMEOUT + + if value is None or value is cls.DEFAULT_TIMEOUT: + return value + + if isinstance(value, bool): + raise ValueError("Timeout cannot be a boolean value. It must " + "be an int, float or None.") + try: + float(value) + except (TypeError, ValueError): + raise ValueError("Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value)) + + try: + if value <= 0: + raise ValueError("Attempted to set %s timeout to %s, but the " + "timeout cannot be set to a value less " + "than or equal to 0." % (name, value)) + except TypeError: # Python 3 + raise ValueError("Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value)) + + return value + + @classmethod + def from_float(cls, timeout): + """ Create a new Timeout from a legacy timeout value. + + The timeout value used by httplib.py sets the same timeout on the + connect(), and recv() socket requests. This creates a :class:`Timeout` + object that sets the individual timeouts to the ``timeout`` value + passed to this function. + + :param timeout: The legacy timeout value. + :type timeout: integer, float, sentinel default object, or None + :return: Timeout object + :rtype: :class:`Timeout` + """ + return Timeout(read=timeout, connect=timeout) + + def clone(self): + """ Create a copy of the timeout object + + Timeout properties are stored per-pool but each request needs a fresh + Timeout object to ensure each one has its own start/stop configured. + + :return: a copy of the timeout object + :rtype: :class:`Timeout` + """ + # We can't use copy.deepcopy because that will also create a new object + # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to + # detect the user default. + return Timeout(connect=self._connect, read=self._read, + total=self.total) + + def start_connect(self): + """ Start the timeout clock, used during a connect() attempt + + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to start a timer that has been started already. + """ + if self._start_connect is not None: + raise TimeoutStateError("Timeout timer has already been started.") + self._start_connect = current_time() + return self._start_connect + + def get_connect_duration(self): + """ Gets the time elapsed since the call to :meth:`start_connect`. + + :return: Elapsed time. + :rtype: float + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to get duration for a timer that hasn't been started. + """ + if self._start_connect is None: + raise TimeoutStateError("Can't get connect duration for timer " + "that has not started.") + return current_time() - self._start_connect + + @property + def connect_timeout(self): + """ Get the value to use when setting a connection timeout. + + This will be a positive float or integer, the value None + (never timeout), or the default system timeout. + + :return: Connect timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + """ + if self.total is None: + return self._connect + + if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: + return self.total + + return min(self._connect, self.total) + + @property + def read_timeout(self): + """ Get the value for the read timeout. + + This assumes some time has elapsed in the connection timeout and + computes the read timeout appropriately. + + If self.total is set, the read timeout is dependent on the amount of + time taken by the connect timeout. If the connection time has not been + established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be + raised. + + :return: Value to use for the read timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` + has not yet been called on this object. + """ + if (self.total is not None and + self.total is not self.DEFAULT_TIMEOUT and + self._read is not None and + self._read is not self.DEFAULT_TIMEOUT): + # In case the connect timeout has not yet been established. + if self._start_connect is None: + return self._read + return max(0, min(self.total - self.get_connect_duration(), + self._read)) + elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: + return max(0, self.total - self.get_connect_duration()) + else: + return self._read diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/url.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/url.py new file mode 100644 index 0000000..6b6f996 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/url.py @@ -0,0 +1,230 @@ +from __future__ import absolute_import +from collections import namedtuple + +from ..exceptions import LocationParseError + + +url_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment'] + +# We only want to normalize urls with an HTTP(S) scheme. +# urllib3 infers URLs without a scheme (None) to be http. +NORMALIZABLE_SCHEMES = ('http', 'https', None) + + +class Url(namedtuple('Url', url_attrs)): + """ + Datastructure for representing an HTTP URL. Used as a return value for + :func:`parse_url`. Both the scheme and host are normalized as they are + both case-insensitive according to RFC 3986. + """ + __slots__ = () + + def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None, + query=None, fragment=None): + if path and not path.startswith('/'): + path = '/' + path + if scheme: + scheme = scheme.lower() + if host and scheme in NORMALIZABLE_SCHEMES: + host = host.lower() + return super(Url, cls).__new__(cls, scheme, auth, host, port, path, + query, fragment) + + @property + def hostname(self): + """For backwards-compatibility with urlparse. We're nice like that.""" + return self.host + + @property + def request_uri(self): + """Absolute path including the query string.""" + uri = self.path or '/' + + if self.query is not None: + uri += '?' + self.query + + return uri + + @property + def netloc(self): + """Network location including host and port""" + if self.port: + return '%s:%d' % (self.host, self.port) + return self.host + + @property + def url(self): + """ + Convert self into a url + + This function should more or less round-trip with :func:`.parse_url`. The + returned url may not be exactly the same as the url inputted to + :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls + with a blank port will have : removed). + + Example: :: + + >>> U = parse_url('http://google.com/mail/') + >>> U.url + 'http://google.com/mail/' + >>> Url('http', 'username:password', 'host.com', 80, + ... '/path', 'query', 'fragment').url + 'http://username:password@host.com:80/path?query#fragment' + """ + scheme, auth, host, port, path, query, fragment = self + url = '' + + # We use "is not None" we want things to happen with empty strings (or 0 port) + if scheme is not None: + url += scheme + '://' + if auth is not None: + url += auth + '@' + if host is not None: + url += host + if port is not None: + url += ':' + str(port) + if path is not None: + url += path + if query is not None: + url += '?' + query + if fragment is not None: + url += '#' + fragment + + return url + + def __str__(self): + return self.url + + +def split_first(s, delims): + """ + Given a string and an iterable of delimiters, split on the first found + delimiter. Return two split parts and the matched delimiter. + + If not found, then the first part is the full input string. + + Example:: + + >>> split_first('foo/bar?baz', '?/=') + ('foo', 'bar?baz', '/') + >>> split_first('foo/bar?baz', '123') + ('foo/bar?baz', '', None) + + Scales linearly with number of delims. Not ideal for large number of delims. + """ + min_idx = None + min_delim = None + for d in delims: + idx = s.find(d) + if idx < 0: + continue + + if min_idx is None or idx < min_idx: + min_idx = idx + min_delim = d + + if min_idx is None or min_idx < 0: + return s, '', None + + return s[:min_idx], s[min_idx + 1:], min_delim + + +def parse_url(url): + """ + Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is + performed to parse incomplete urls. Fields not provided will be None. + + Partly backwards-compatible with :mod:`urlparse`. + + Example:: + + >>> parse_url('http://google.com/mail/') + Url(scheme='http', host='google.com', port=None, path='/mail/', ...) + >>> parse_url('google.com:80') + Url(scheme=None, host='google.com', port=80, path=None, ...) + >>> parse_url('/foo?bar') + Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) + """ + + # While this code has overlap with stdlib's urlparse, it is much + # simplified for our needs and less annoying. + # Additionally, this implementations does silly things to be optimal + # on CPython. + + if not url: + # Empty + return Url() + + scheme = None + auth = None + host = None + port = None + path = None + fragment = None + query = None + + # Scheme + if '://' in url: + scheme, url = url.split('://', 1) + + # Find the earliest Authority Terminator + # (http://tools.ietf.org/html/rfc3986#section-3.2) + url, path_, delim = split_first(url, ['/', '?', '#']) + + if delim: + # Reassemble the path + path = delim + path_ + + # Auth + if '@' in url: + # Last '@' denotes end of auth part + auth, url = url.rsplit('@', 1) + + # IPv6 + if url and url[0] == '[': + host, url = url.split(']', 1) + host += ']' + + # Port + if ':' in url: + _host, port = url.split(':', 1) + + if not host: + host = _host + + if port: + # If given, ports must be integers. No whitespace, no plus or + # minus prefixes, no non-integer digits such as ^2 (superscript). + if not port.isdigit(): + raise LocationParseError(url) + try: + port = int(port) + except ValueError: + raise LocationParseError(url) + else: + # Blank ports are cool, too. (rfc3986#section-3.2.3) + port = None + + elif not host and url: + host = url + + if not path: + return Url(scheme, auth, host, port, path, query, fragment) + + # Fragment + if '#' in path: + path, fragment = path.split('#', 1) + + # Query + if '?' in path: + path, query = path.split('?', 1) + + return Url(scheme, auth, host, port, path, query, fragment) + + +def get_host(url): + """ + Deprecated. Use :func:`parse_url` instead. + """ + p = parse_url(url) + return p.scheme or 'http', p.hostname, p.port diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/wait.py b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/wait.py new file mode 100644 index 0000000..fa686ef --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/urllib3/util/wait.py @@ -0,0 +1,153 @@ +import errno +from functools import partial +import select +import sys +try: + from time import monotonic +except ImportError: + from time import time as monotonic + +__all__ = ["NoWayToWaitForSocketError", "wait_for_read", "wait_for_write"] + + +class NoWayToWaitForSocketError(Exception): + pass + + +# How should we wait on sockets? +# +# There are two types of APIs you can use for waiting on sockets: the fancy +# modern stateful APIs like epoll/kqueue, and the older stateless APIs like +# select/poll. The stateful APIs are more efficient when you have a lots of +# sockets to keep track of, because you can set them up once and then use them +# lots of times. But we only ever want to wait on a single socket at a time +# and don't want to keep track of state, so the stateless APIs are actually +# more efficient. So we want to use select() or poll(). +# +# Now, how do we choose between select() and poll()? On traditional Unixes, +# select() has a strange calling convention that makes it slow, or fail +# altogether, for high-numbered file descriptors. The point of poll() is to fix +# that, so on Unixes, we prefer poll(). +# +# On Windows, there is no poll() (or at least Python doesn't provide a wrapper +# for it), but that's OK, because on Windows, select() doesn't have this +# strange calling convention; plain select() works fine. +# +# So: on Windows we use select(), and everywhere else we use poll(). We also +# fall back to select() in case poll() is somehow broken or missing. + +if sys.version_info >= (3, 5): + # Modern Python, that retries syscalls by default + def _retry_on_intr(fn, timeout): + return fn(timeout) +else: + # Old and broken Pythons. + def _retry_on_intr(fn, timeout): + if timeout is not None and timeout <= 0: + return fn(timeout) + + if timeout is None: + deadline = float("inf") + else: + deadline = monotonic() + timeout + + while True: + try: + return fn(timeout) + # OSError for 3 <= pyver < 3.5, select.error for pyver <= 2.7 + except (OSError, select.error) as e: + # 'e.args[0]' incantation works for both OSError and select.error + if e.args[0] != errno.EINTR: + raise + else: + timeout = deadline - monotonic() + if timeout < 0: + timeout = 0 + if timeout == float("inf"): + timeout = None + continue + + +def select_wait_for_socket(sock, read=False, write=False, timeout=None): + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + rcheck = [] + wcheck = [] + if read: + rcheck.append(sock) + if write: + wcheck.append(sock) + # When doing a non-blocking connect, most systems signal success by + # marking the socket writable. Windows, though, signals success by marked + # it as "exceptional". We paper over the difference by checking the write + # sockets for both conditions. (The stdlib selectors module does the same + # thing.) + fn = partial(select.select, rcheck, wcheck, wcheck) + rready, wready, xready = _retry_on_intr(fn, timeout) + return bool(rready or wready or xready) + + +def poll_wait_for_socket(sock, read=False, write=False, timeout=None): + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + mask = 0 + if read: + mask |= select.POLLIN + if write: + mask |= select.POLLOUT + poll_obj = select.poll() + poll_obj.register(sock, mask) + + # For some reason, poll() takes timeout in milliseconds + def do_poll(t): + if t is not None: + t *= 1000 + return poll_obj.poll(t) + + return bool(_retry_on_intr(do_poll, timeout)) + + +def null_wait_for_socket(*args, **kwargs): + raise NoWayToWaitForSocketError("no select-equivalent available") + + +def _have_working_poll(): + # Apparently some systems have a select.poll that fails as soon as you try + # to use it, either due to strange configuration or broken monkeypatching + # from libraries like eventlet/greenlet. + try: + poll_obj = select.poll() + poll_obj.poll(0) + except (AttributeError, OSError): + return False + else: + return True + + +def wait_for_socket(*args, **kwargs): + # We delay choosing which implementation to use until the first time we're + # called. We could do it at import time, but then we might make the wrong + # decision if someone goes wild with monkeypatching select.poll after + # we're imported. + global wait_for_socket + if _have_working_poll(): + wait_for_socket = poll_wait_for_socket + elif hasattr(select, "select"): + wait_for_socket = select_wait_for_socket + else: # Platform-specific: Appengine. + wait_for_socket = null_wait_for_socket + return wait_for_socket(*args, **kwargs) + + +def wait_for_read(sock, timeout=None): + """ Waits for reading to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, read=True, timeout=timeout) + + +def wait_for_write(sock, timeout=None): + """ Waits for writing to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, write=True, timeout=timeout) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__init__.py b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__init__.py new file mode 100644 index 0000000..d21d697 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/__init__.py @@ -0,0 +1,342 @@ +# coding: utf-8 +""" + + webencodings + ~~~~~~~~~~~~ + + This is a Python implementation of the `WHATWG Encoding standard + <http://encoding.spec.whatwg.org/>`. See README for details. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +from __future__ import unicode_literals + +import codecs + +from .labels import LABELS + + +VERSION = '0.5.1' + + +# Some names in Encoding are not valid Python aliases. Remap these. +PYTHON_NAMES = { + 'iso-8859-8-i': 'iso-8859-8', + 'x-mac-cyrillic': 'mac-cyrillic', + 'macintosh': 'mac-roman', + 'windows-874': 'cp874'} + +CACHE = {} + + +def ascii_lower(string): + r"""Transform (only) ASCII letters to lower case: A-Z is mapped to a-z. + + :param string: An Unicode string. + :returns: A new Unicode string. + + This is used for `ASCII case-insensitive + <http://encoding.spec.whatwg.org/#ascii-case-insensitive>`_ + matching of encoding labels. + The same matching is also used, among other things, + for `CSS keywords <http://dev.w3.org/csswg/css-values/#keywords>`_. + + This is different from the :meth:`~py:str.lower` method of Unicode strings + which also affect non-ASCII characters, + sometimes mapping them into the ASCII range: + + >>> keyword = u'Bac\N{KELVIN SIGN}ground' + >>> assert keyword.lower() == u'background' + >>> assert ascii_lower(keyword) != keyword.lower() + >>> assert ascii_lower(keyword) == u'bac\N{KELVIN SIGN}ground' + + """ + # This turns out to be faster than unicode.translate() + return string.encode('utf8').lower().decode('utf8') + + +def lookup(label): + """ + Look for an encoding by its label. + This is the spec’s `get an encoding + <http://encoding.spec.whatwg.org/#concept-encoding-get>`_ algorithm. + Supported labels are listed there. + + :param label: A string. + :returns: + An :class:`Encoding` object, or :obj:`None` for an unknown label. + + """ + # Only strip ASCII whitespace: U+0009, U+000A, U+000C, U+000D, and U+0020. + label = ascii_lower(label.strip('\t\n\f\r ')) + name = LABELS.get(label) + if name is None: + return None + encoding = CACHE.get(name) + if encoding is None: + if name == 'x-user-defined': + from .x_user_defined import codec_info + else: + python_name = PYTHON_NAMES.get(name, name) + # Any python_name value that gets to here should be valid. + codec_info = codecs.lookup(python_name) + encoding = Encoding(name, codec_info) + CACHE[name] = encoding + return encoding + + +def _get_encoding(encoding_or_label): + """ + Accept either an encoding object or label. + + :param encoding: An :class:`Encoding` object or a label string. + :returns: An :class:`Encoding` object. + :raises: :exc:`~exceptions.LookupError` for an unknown label. + + """ + if hasattr(encoding_or_label, 'codec_info'): + return encoding_or_label + + encoding = lookup(encoding_or_label) + if encoding is None: + raise LookupError('Unknown encoding label: %r' % encoding_or_label) + return encoding + + +class Encoding(object): + """Reresents a character encoding such as UTF-8, + that can be used for decoding or encoding. + + .. attribute:: name + + Canonical name of the encoding + + .. attribute:: codec_info + + The actual implementation of the encoding, + a stdlib :class:`~codecs.CodecInfo` object. + See :func:`codecs.register`. + + """ + def __init__(self, name, codec_info): + self.name = name + self.codec_info = codec_info + + def __repr__(self): + return '<Encoding %s>' % self.name + + +#: The UTF-8 encoding. Should be used for new content and formats. +UTF8 = lookup('utf-8') + +_UTF16LE = lookup('utf-16le') +_UTF16BE = lookup('utf-16be') + + +def decode(input, fallback_encoding, errors='replace'): + """ + Decode a single string. + + :param input: A byte string + :param fallback_encoding: + An :class:`Encoding` object or a label string. + The encoding to use if :obj:`input` does note have a BOM. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :return: + A ``(output, encoding)`` tuple of an Unicode string + and an :obj:`Encoding`. + + """ + # Fail early if `encoding` is an invalid label. + fallback_encoding = _get_encoding(fallback_encoding) + bom_encoding, input = _detect_bom(input) + encoding = bom_encoding or fallback_encoding + return encoding.codec_info.decode(input, errors)[0], encoding + + +def _detect_bom(input): + """Return (bom_encoding, input), with any BOM removed from the input.""" + if input.startswith(b'\xFF\xFE'): + return _UTF16LE, input[2:] + if input.startswith(b'\xFE\xFF'): + return _UTF16BE, input[2:] + if input.startswith(b'\xEF\xBB\xBF'): + return UTF8, input[3:] + return None, input + + +def encode(input, encoding=UTF8, errors='strict'): + """ + Encode a single string. + + :param input: An Unicode string. + :param encoding: An :class:`Encoding` object or a label string. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :return: A byte string. + + """ + return _get_encoding(encoding).codec_info.encode(input, errors)[0] + + +def iter_decode(input, fallback_encoding, errors='replace'): + """ + "Pull"-based decoder. + + :param input: + An iterable of byte strings. + + The input is first consumed just enough to determine the encoding + based on the precense of a BOM, + then consumed on demand when the return value is. + :param fallback_encoding: + An :class:`Encoding` object or a label string. + The encoding to use if :obj:`input` does note have a BOM. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :returns: + An ``(output, encoding)`` tuple. + :obj:`output` is an iterable of Unicode strings, + :obj:`encoding` is the :obj:`Encoding` that is being used. + + """ + + decoder = IncrementalDecoder(fallback_encoding, errors) + generator = _iter_decode_generator(input, decoder) + encoding = next(generator) + return generator, encoding + + +def _iter_decode_generator(input, decoder): + """Return a generator that first yields the :obj:`Encoding`, + then yields output chukns as Unicode strings. + + """ + decode = decoder.decode + input = iter(input) + for chunck in input: + output = decode(chunck) + if output: + assert decoder.encoding is not None + yield decoder.encoding + yield output + break + else: + # Input exhausted without determining the encoding + output = decode(b'', final=True) + assert decoder.encoding is not None + yield decoder.encoding + if output: + yield output + return + + for chunck in input: + output = decode(chunck) + if output: + yield output + output = decode(b'', final=True) + if output: + yield output + + +def iter_encode(input, encoding=UTF8, errors='strict'): + """ + “Pull”-based encoder. + + :param input: An iterable of Unicode strings. + :param encoding: An :class:`Encoding` object or a label string. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :returns: An iterable of byte strings. + + """ + # Fail early if `encoding` is an invalid label. + encode = IncrementalEncoder(encoding, errors).encode + return _iter_encode_generator(input, encode) + + +def _iter_encode_generator(input, encode): + for chunck in input: + output = encode(chunck) + if output: + yield output + output = encode('', final=True) + if output: + yield output + + +class IncrementalDecoder(object): + """ + “Push”-based decoder. + + :param fallback_encoding: + An :class:`Encoding` object or a label string. + The encoding to use if :obj:`input` does note have a BOM. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + + """ + def __init__(self, fallback_encoding, errors='replace'): + # Fail early if `encoding` is an invalid label. + self._fallback_encoding = _get_encoding(fallback_encoding) + self._errors = errors + self._buffer = b'' + self._decoder = None + #: The actual :class:`Encoding` that is being used, + #: or :obj:`None` if that is not determined yet. + #: (Ie. if there is not enough input yet to determine + #: if there is a BOM.) + self.encoding = None # Not known yet. + + def decode(self, input, final=False): + """Decode one chunk of the input. + + :param input: A byte string. + :param final: + Indicate that no more input is available. + Must be :obj:`True` if this is the last call. + :returns: An Unicode string. + + """ + decoder = self._decoder + if decoder is not None: + return decoder(input, final) + + input = self._buffer + input + encoding, input = _detect_bom(input) + if encoding is None: + if len(input) < 3 and not final: # Not enough data yet. + self._buffer = input + return '' + else: # No BOM + encoding = self._fallback_encoding + decoder = encoding.codec_info.incrementaldecoder(self._errors).decode + self._decoder = decoder + self.encoding = encoding + return decoder(input, final) + + +class IncrementalEncoder(object): + """ + “Push”-based encoder. + + :param encoding: An :class:`Encoding` object or a label string. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + + .. method:: encode(input, final=False) + + :param input: An Unicode string. + :param final: + Indicate that no more input is available. + Must be :obj:`True` if this is the last call. + :returns: A byte string. + + """ + def __init__(self, encoding=UTF8, errors='strict'): + encoding = _get_encoding(encoding) + self.encode = encoding.codec_info.incrementalencoder(errors).encode diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/labels.py b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/labels.py new file mode 100644 index 0000000..29cbf91 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/labels.py @@ -0,0 +1,231 @@ +""" + + webencodings.labels + ~~~~~~~~~~~~~~~~~~~ + + Map encoding labels to their name. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +# XXX Do not edit! +# This file is automatically generated by mklabels.py + +LABELS = { + 'unicode-1-1-utf-8': 'utf-8', + 'utf-8': 'utf-8', + 'utf8': 'utf-8', + '866': 'ibm866', + 'cp866': 'ibm866', + 'csibm866': 'ibm866', + 'ibm866': 'ibm866', + 'csisolatin2': 'iso-8859-2', + 'iso-8859-2': 'iso-8859-2', + 'iso-ir-101': 'iso-8859-2', + 'iso8859-2': 'iso-8859-2', + 'iso88592': 'iso-8859-2', + 'iso_8859-2': 'iso-8859-2', + 'iso_8859-2:1987': 'iso-8859-2', + 'l2': 'iso-8859-2', + 'latin2': 'iso-8859-2', + 'csisolatin3': 'iso-8859-3', + 'iso-8859-3': 'iso-8859-3', + 'iso-ir-109': 'iso-8859-3', + 'iso8859-3': 'iso-8859-3', + 'iso88593': 'iso-8859-3', + 'iso_8859-3': 'iso-8859-3', + 'iso_8859-3:1988': 'iso-8859-3', + 'l3': 'iso-8859-3', + 'latin3': 'iso-8859-3', + 'csisolatin4': 'iso-8859-4', + 'iso-8859-4': 'iso-8859-4', + 'iso-ir-110': 'iso-8859-4', + 'iso8859-4': 'iso-8859-4', + 'iso88594': 'iso-8859-4', + 'iso_8859-4': 'iso-8859-4', + 'iso_8859-4:1988': 'iso-8859-4', + 'l4': 'iso-8859-4', + 'latin4': 'iso-8859-4', + 'csisolatincyrillic': 'iso-8859-5', + 'cyrillic': 'iso-8859-5', + 'iso-8859-5': 'iso-8859-5', + 'iso-ir-144': 'iso-8859-5', + 'iso8859-5': 'iso-8859-5', + 'iso88595': 'iso-8859-5', + 'iso_8859-5': 'iso-8859-5', + 'iso_8859-5:1988': 'iso-8859-5', + 'arabic': 'iso-8859-6', + 'asmo-708': 'iso-8859-6', + 'csiso88596e': 'iso-8859-6', + 'csiso88596i': 'iso-8859-6', + 'csisolatinarabic': 'iso-8859-6', + 'ecma-114': 'iso-8859-6', + 'iso-8859-6': 'iso-8859-6', + 'iso-8859-6-e': 'iso-8859-6', + 'iso-8859-6-i': 'iso-8859-6', + 'iso-ir-127': 'iso-8859-6', + 'iso8859-6': 'iso-8859-6', + 'iso88596': 'iso-8859-6', + 'iso_8859-6': 'iso-8859-6', + 'iso_8859-6:1987': 'iso-8859-6', + 'csisolatingreek': 'iso-8859-7', + 'ecma-118': 'iso-8859-7', + 'elot_928': 'iso-8859-7', + 'greek': 'iso-8859-7', + 'greek8': 'iso-8859-7', + 'iso-8859-7': 'iso-8859-7', + 'iso-ir-126': 'iso-8859-7', + 'iso8859-7': 'iso-8859-7', + 'iso88597': 'iso-8859-7', + 'iso_8859-7': 'iso-8859-7', + 'iso_8859-7:1987': 'iso-8859-7', + 'sun_eu_greek': 'iso-8859-7', + 'csiso88598e': 'iso-8859-8', + 'csisolatinhebrew': 'iso-8859-8', + 'hebrew': 'iso-8859-8', + 'iso-8859-8': 'iso-8859-8', + 'iso-8859-8-e': 'iso-8859-8', + 'iso-ir-138': 'iso-8859-8', + 'iso8859-8': 'iso-8859-8', + 'iso88598': 'iso-8859-8', + 'iso_8859-8': 'iso-8859-8', + 'iso_8859-8:1988': 'iso-8859-8', + 'visual': 'iso-8859-8', + 'csiso88598i': 'iso-8859-8-i', + 'iso-8859-8-i': 'iso-8859-8-i', + 'logical': 'iso-8859-8-i', + 'csisolatin6': 'iso-8859-10', + 'iso-8859-10': 'iso-8859-10', + 'iso-ir-157': 'iso-8859-10', + 'iso8859-10': 'iso-8859-10', + 'iso885910': 'iso-8859-10', + 'l6': 'iso-8859-10', + 'latin6': 'iso-8859-10', + 'iso-8859-13': 'iso-8859-13', + 'iso8859-13': 'iso-8859-13', + 'iso885913': 'iso-8859-13', + 'iso-8859-14': 'iso-8859-14', + 'iso8859-14': 'iso-8859-14', + 'iso885914': 'iso-8859-14', + 'csisolatin9': 'iso-8859-15', + 'iso-8859-15': 'iso-8859-15', + 'iso8859-15': 'iso-8859-15', + 'iso885915': 'iso-8859-15', + 'iso_8859-15': 'iso-8859-15', + 'l9': 'iso-8859-15', + 'iso-8859-16': 'iso-8859-16', + 'cskoi8r': 'koi8-r', + 'koi': 'koi8-r', + 'koi8': 'koi8-r', + 'koi8-r': 'koi8-r', + 'koi8_r': 'koi8-r', + 'koi8-u': 'koi8-u', + 'csmacintosh': 'macintosh', + 'mac': 'macintosh', + 'macintosh': 'macintosh', + 'x-mac-roman': 'macintosh', + 'dos-874': 'windows-874', + 'iso-8859-11': 'windows-874', + 'iso8859-11': 'windows-874', + 'iso885911': 'windows-874', + 'tis-620': 'windows-874', + 'windows-874': 'windows-874', + 'cp1250': 'windows-1250', + 'windows-1250': 'windows-1250', + 'x-cp1250': 'windows-1250', + 'cp1251': 'windows-1251', + 'windows-1251': 'windows-1251', + 'x-cp1251': 'windows-1251', + 'ansi_x3.4-1968': 'windows-1252', + 'ascii': 'windows-1252', + 'cp1252': 'windows-1252', + 'cp819': 'windows-1252', + 'csisolatin1': 'windows-1252', + 'ibm819': 'windows-1252', + 'iso-8859-1': 'windows-1252', + 'iso-ir-100': 'windows-1252', + 'iso8859-1': 'windows-1252', + 'iso88591': 'windows-1252', + 'iso_8859-1': 'windows-1252', + 'iso_8859-1:1987': 'windows-1252', + 'l1': 'windows-1252', + 'latin1': 'windows-1252', + 'us-ascii': 'windows-1252', + 'windows-1252': 'windows-1252', + 'x-cp1252': 'windows-1252', + 'cp1253': 'windows-1253', + 'windows-1253': 'windows-1253', + 'x-cp1253': 'windows-1253', + 'cp1254': 'windows-1254', + 'csisolatin5': 'windows-1254', + 'iso-8859-9': 'windows-1254', + 'iso-ir-148': 'windows-1254', + 'iso8859-9': 'windows-1254', + 'iso88599': 'windows-1254', + 'iso_8859-9': 'windows-1254', + 'iso_8859-9:1989': 'windows-1254', + 'l5': 'windows-1254', + 'latin5': 'windows-1254', + 'windows-1254': 'windows-1254', + 'x-cp1254': 'windows-1254', + 'cp1255': 'windows-1255', + 'windows-1255': 'windows-1255', + 'x-cp1255': 'windows-1255', + 'cp1256': 'windows-1256', + 'windows-1256': 'windows-1256', + 'x-cp1256': 'windows-1256', + 'cp1257': 'windows-1257', + 'windows-1257': 'windows-1257', + 'x-cp1257': 'windows-1257', + 'cp1258': 'windows-1258', + 'windows-1258': 'windows-1258', + 'x-cp1258': 'windows-1258', + 'x-mac-cyrillic': 'x-mac-cyrillic', + 'x-mac-ukrainian': 'x-mac-cyrillic', + 'chinese': 'gbk', + 'csgb2312': 'gbk', + 'csiso58gb231280': 'gbk', + 'gb2312': 'gbk', + 'gb_2312': 'gbk', + 'gb_2312-80': 'gbk', + 'gbk': 'gbk', + 'iso-ir-58': 'gbk', + 'x-gbk': 'gbk', + 'gb18030': 'gb18030', + 'hz-gb-2312': 'hz-gb-2312', + 'big5': 'big5', + 'big5-hkscs': 'big5', + 'cn-big5': 'big5', + 'csbig5': 'big5', + 'x-x-big5': 'big5', + 'cseucpkdfmtjapanese': 'euc-jp', + 'euc-jp': 'euc-jp', + 'x-euc-jp': 'euc-jp', + 'csiso2022jp': 'iso-2022-jp', + 'iso-2022-jp': 'iso-2022-jp', + 'csshiftjis': 'shift_jis', + 'ms_kanji': 'shift_jis', + 'shift-jis': 'shift_jis', + 'shift_jis': 'shift_jis', + 'sjis': 'shift_jis', + 'windows-31j': 'shift_jis', + 'x-sjis': 'shift_jis', + 'cseuckr': 'euc-kr', + 'csksc56011987': 'euc-kr', + 'euc-kr': 'euc-kr', + 'iso-ir-149': 'euc-kr', + 'korean': 'euc-kr', + 'ks_c_5601-1987': 'euc-kr', + 'ks_c_5601-1989': 'euc-kr', + 'ksc5601': 'euc-kr', + 'ksc_5601': 'euc-kr', + 'windows-949': 'euc-kr', + 'csiso2022kr': 'iso-2022-kr', + 'iso-2022-kr': 'iso-2022-kr', + 'utf-16be': 'utf-16be', + 'utf-16': 'utf-16le', + 'utf-16le': 'utf-16le', + 'x-user-defined': 'x-user-defined', +} diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/mklabels.py b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/mklabels.py new file mode 100644 index 0000000..295dc92 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/mklabels.py @@ -0,0 +1,59 @@ +""" + + webencodings.mklabels + ~~~~~~~~~~~~~~~~~~~~~ + + Regenarate the webencodings.labels module. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +import json +try: + from urllib import urlopen +except ImportError: + from urllib.request import urlopen + + +def assert_lower(string): + assert string == string.lower() + return string + + +def generate(url): + parts = ['''\ +""" + + webencodings.labels + ~~~~~~~~~~~~~~~~~~~ + + Map encoding labels to their name. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +# XXX Do not edit! +# This file is automatically generated by mklabels.py + +LABELS = { +'''] + labels = [ + (repr(assert_lower(label)).lstrip('u'), + repr(encoding['name']).lstrip('u')) + for category in json.loads(urlopen(url).read().decode('ascii')) + for encoding in category['encodings'] + for label in encoding['labels']] + max_len = max(len(label) for label, name in labels) + parts.extend( + ' %s:%s %s,\n' % (label, ' ' * (max_len - len(label)), name) + for label, name in labels) + parts.append('}') + return ''.join(parts) + + +if __name__ == '__main__': + print(generate('http://encoding.spec.whatwg.org/encodings.json')) diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/tests.py b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/tests.py new file mode 100644 index 0000000..e12c10d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/tests.py @@ -0,0 +1,153 @@ +# coding: utf-8 +""" + + webencodings.tests + ~~~~~~~~~~~~~~~~~~ + + A basic test suite for Encoding. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +from __future__ import unicode_literals + +from . import (lookup, LABELS, decode, encode, iter_decode, iter_encode, + IncrementalDecoder, IncrementalEncoder, UTF8) + + +def assert_raises(exception, function, *args, **kwargs): + try: + function(*args, **kwargs) + except exception: + return + else: # pragma: no cover + raise AssertionError('Did not raise %s.' % exception) + + +def test_labels(): + assert lookup('utf-8').name == 'utf-8' + assert lookup('Utf-8').name == 'utf-8' + assert lookup('UTF-8').name == 'utf-8' + assert lookup('utf8').name == 'utf-8' + assert lookup('utf8').name == 'utf-8' + assert lookup('utf8 ').name == 'utf-8' + assert lookup(' \r\nutf8\t').name == 'utf-8' + assert lookup('u8') is None # Python label. + assert lookup('utf-8 ') is None # Non-ASCII white space. + + assert lookup('US-ASCII').name == 'windows-1252' + assert lookup('iso-8859-1').name == 'windows-1252' + assert lookup('latin1').name == 'windows-1252' + assert lookup('LATIN1').name == 'windows-1252' + assert lookup('latin-1') is None + assert lookup('LATİN1') is None # ASCII-only case insensitivity. + + +def test_all_labels(): + for label in LABELS: + assert decode(b'', label) == ('', lookup(label)) + assert encode('', label) == b'' + for repeat in [0, 1, 12]: + output, _ = iter_decode([b''] * repeat, label) + assert list(output) == [] + assert list(iter_encode([''] * repeat, label)) == [] + decoder = IncrementalDecoder(label) + assert decoder.decode(b'') == '' + assert decoder.decode(b'', final=True) == '' + encoder = IncrementalEncoder(label) + assert encoder.encode('') == b'' + assert encoder.encode('', final=True) == b'' + # All encoding names are valid labels too: + for name in set(LABELS.values()): + assert lookup(name).name == name + + +def test_invalid_label(): + assert_raises(LookupError, decode, b'\xEF\xBB\xBF\xc3\xa9', 'invalid') + assert_raises(LookupError, encode, 'é', 'invalid') + assert_raises(LookupError, iter_decode, [], 'invalid') + assert_raises(LookupError, iter_encode, [], 'invalid') + assert_raises(LookupError, IncrementalDecoder, 'invalid') + assert_raises(LookupError, IncrementalEncoder, 'invalid') + + +def test_decode(): + assert decode(b'\x80', 'latin1') == ('€', lookup('latin1')) + assert decode(b'\x80', lookup('latin1')) == ('€', lookup('latin1')) + assert decode(b'\xc3\xa9', 'utf8') == ('é', lookup('utf8')) + assert decode(b'\xc3\xa9', UTF8) == ('é', lookup('utf8')) + assert decode(b'\xc3\xa9', 'ascii') == ('é', lookup('ascii')) + assert decode(b'\xEF\xBB\xBF\xc3\xa9', 'ascii') == ('é', lookup('utf8')) # UTF-8 with BOM + + assert decode(b'\xFE\xFF\x00\xe9', 'ascii') == ('é', lookup('utf-16be')) # UTF-16-BE with BOM + assert decode(b'\xFF\xFE\xe9\x00', 'ascii') == ('é', lookup('utf-16le')) # UTF-16-LE with BOM + assert decode(b'\xFE\xFF\xe9\x00', 'ascii') == ('\ue900', lookup('utf-16be')) + assert decode(b'\xFF\xFE\x00\xe9', 'ascii') == ('\ue900', lookup('utf-16le')) + + assert decode(b'\x00\xe9', 'UTF-16BE') == ('é', lookup('utf-16be')) + assert decode(b'\xe9\x00', 'UTF-16LE') == ('é', lookup('utf-16le')) + assert decode(b'\xe9\x00', 'UTF-16') == ('é', lookup('utf-16le')) + + assert decode(b'\xe9\x00', 'UTF-16BE') == ('\ue900', lookup('utf-16be')) + assert decode(b'\x00\xe9', 'UTF-16LE') == ('\ue900', lookup('utf-16le')) + assert decode(b'\x00\xe9', 'UTF-16') == ('\ue900', lookup('utf-16le')) + + +def test_encode(): + assert encode('é', 'latin1') == b'\xe9' + assert encode('é', 'utf8') == b'\xc3\xa9' + assert encode('é', 'utf8') == b'\xc3\xa9' + assert encode('é', 'utf-16') == b'\xe9\x00' + assert encode('é', 'utf-16le') == b'\xe9\x00' + assert encode('é', 'utf-16be') == b'\x00\xe9' + + +def test_iter_decode(): + def iter_decode_to_string(input, fallback_encoding): + output, _encoding = iter_decode(input, fallback_encoding) + return ''.join(output) + assert iter_decode_to_string([], 'latin1') == '' + assert iter_decode_to_string([b''], 'latin1') == '' + assert iter_decode_to_string([b'\xe9'], 'latin1') == 'é' + assert iter_decode_to_string([b'hello'], 'latin1') == 'hello' + assert iter_decode_to_string([b'he', b'llo'], 'latin1') == 'hello' + assert iter_decode_to_string([b'hell', b'o'], 'latin1') == 'hello' + assert iter_decode_to_string([b'\xc3\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([b'\xEF\xBB\xBF\xc3\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'\xEF\xBB\xBF', b'\xc3', b'\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'\xEF\xBB\xBF', b'a', b'\xc3'], 'latin1') == 'a\uFFFD' + assert iter_decode_to_string([ + b'', b'\xEF', b'', b'', b'\xBB\xBF\xc3', b'\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([b'\xEF\xBB\xBF'], 'latin1') == '' + assert iter_decode_to_string([b'\xEF\xBB'], 'latin1') == 'ï»' + assert iter_decode_to_string([b'\xFE\xFF\x00\xe9'], 'latin1') == 'é' + assert iter_decode_to_string([b'\xFF\xFE\xe9\x00'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'', b'\xFF', b'', b'', b'\xFE\xe9', b'\x00'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'', b'h\xe9', b'llo'], 'x-user-defined') == 'h\uF7E9llo' + + +def test_iter_encode(): + assert b''.join(iter_encode([], 'latin1')) == b'' + assert b''.join(iter_encode([''], 'latin1')) == b'' + assert b''.join(iter_encode(['é'], 'latin1')) == b'\xe9' + assert b''.join(iter_encode(['', 'é', '', ''], 'latin1')) == b'\xe9' + assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16')) == b'\xe9\x00' + assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16le')) == b'\xe9\x00' + assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16be')) == b'\x00\xe9' + assert b''.join(iter_encode([ + '', 'h\uF7E9', '', 'llo'], 'x-user-defined')) == b'h\xe9llo' + + +def test_x_user_defined(): + encoded = b'2,\x0c\x0b\x1aO\xd9#\xcb\x0f\xc9\xbbt\xcf\xa8\xca' + decoded = '2,\x0c\x0b\x1aO\uf7d9#\uf7cb\x0f\uf7c9\uf7bbt\uf7cf\uf7a8\uf7ca' + encoded = b'aa' + decoded = 'aa' + assert decode(encoded, 'x-user-defined') == (decoded, lookup('x-user-defined')) + assert encode(decoded, 'x-user-defined') == encoded diff --git a/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/x_user_defined.py b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/x_user_defined.py new file mode 100644 index 0000000..d16e326 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_vendor/webencodings/x_user_defined.py @@ -0,0 +1,325 @@ +# coding: utf-8 +""" + + webencodings.x_user_defined + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + An implementation of the x-user-defined encoding. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +from __future__ import unicode_literals + +import codecs + + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self, input, errors='strict'): + return codecs.charmap_encode(input, errors, encoding_table) + + def decode(self, input, errors='strict'): + return codecs.charmap_decode(input, errors, decoding_table) + + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input, self.errors, encoding_table)[0] + + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input, self.errors, decoding_table)[0] + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + + +class StreamReader(Codec, codecs.StreamReader): + pass + + +### encodings module API + +codec_info = codecs.CodecInfo( + name='x-user-defined', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, +) + + +### Decoding Table + +# Python 3: +# for c in range(256): print(' %r' % chr(c if c < 128 else c + 0xF700)) +decoding_table = ( + '\x00' + '\x01' + '\x02' + '\x03' + '\x04' + '\x05' + '\x06' + '\x07' + '\x08' + '\t' + '\n' + '\x0b' + '\x0c' + '\r' + '\x0e' + '\x0f' + '\x10' + '\x11' + '\x12' + '\x13' + '\x14' + '\x15' + '\x16' + '\x17' + '\x18' + '\x19' + '\x1a' + '\x1b' + '\x1c' + '\x1d' + '\x1e' + '\x1f' + ' ' + '!' + '"' + '#' + '$' + '%' + '&' + "'" + '(' + ')' + '*' + '+' + ',' + '-' + '.' + '/' + '0' + '1' + '2' + '3' + '4' + '5' + '6' + '7' + '8' + '9' + ':' + ';' + '<' + '=' + '>' + '?' + '@' + 'A' + 'B' + 'C' + 'D' + 'E' + 'F' + 'G' + 'H' + 'I' + 'J' + 'K' + 'L' + 'M' + 'N' + 'O' + 'P' + 'Q' + 'R' + 'S' + 'T' + 'U' + 'V' + 'W' + 'X' + 'Y' + 'Z' + '[' + '\\' + ']' + '^' + '_' + '`' + 'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g' + 'h' + 'i' + 'j' + 'k' + 'l' + 'm' + 'n' + 'o' + 'p' + 'q' + 'r' + 's' + 't' + 'u' + 'v' + 'w' + 'x' + 'y' + 'z' + '{' + '|' + '}' + '~' + '\x7f' + '\uf780' + '\uf781' + '\uf782' + '\uf783' + '\uf784' + '\uf785' + '\uf786' + '\uf787' + '\uf788' + '\uf789' + '\uf78a' + '\uf78b' + '\uf78c' + '\uf78d' + '\uf78e' + '\uf78f' + '\uf790' + '\uf791' + '\uf792' + '\uf793' + '\uf794' + '\uf795' + '\uf796' + '\uf797' + '\uf798' + '\uf799' + '\uf79a' + '\uf79b' + '\uf79c' + '\uf79d' + '\uf79e' + '\uf79f' + '\uf7a0' + '\uf7a1' + '\uf7a2' + '\uf7a3' + '\uf7a4' + '\uf7a5' + '\uf7a6' + '\uf7a7' + '\uf7a8' + '\uf7a9' + '\uf7aa' + '\uf7ab' + '\uf7ac' + '\uf7ad' + '\uf7ae' + '\uf7af' + '\uf7b0' + '\uf7b1' + '\uf7b2' + '\uf7b3' + '\uf7b4' + '\uf7b5' + '\uf7b6' + '\uf7b7' + '\uf7b8' + '\uf7b9' + '\uf7ba' + '\uf7bb' + '\uf7bc' + '\uf7bd' + '\uf7be' + '\uf7bf' + '\uf7c0' + '\uf7c1' + '\uf7c2' + '\uf7c3' + '\uf7c4' + '\uf7c5' + '\uf7c6' + '\uf7c7' + '\uf7c8' + '\uf7c9' + '\uf7ca' + '\uf7cb' + '\uf7cc' + '\uf7cd' + '\uf7ce' + '\uf7cf' + '\uf7d0' + '\uf7d1' + '\uf7d2' + '\uf7d3' + '\uf7d4' + '\uf7d5' + '\uf7d6' + '\uf7d7' + '\uf7d8' + '\uf7d9' + '\uf7da' + '\uf7db' + '\uf7dc' + '\uf7dd' + '\uf7de' + '\uf7df' + '\uf7e0' + '\uf7e1' + '\uf7e2' + '\uf7e3' + '\uf7e4' + '\uf7e5' + '\uf7e6' + '\uf7e7' + '\uf7e8' + '\uf7e9' + '\uf7ea' + '\uf7eb' + '\uf7ec' + '\uf7ed' + '\uf7ee' + '\uf7ef' + '\uf7f0' + '\uf7f1' + '\uf7f2' + '\uf7f3' + '\uf7f4' + '\uf7f5' + '\uf7f6' + '\uf7f7' + '\uf7f8' + '\uf7f9' + '\uf7fa' + '\uf7fb' + '\uf7fc' + '\uf7fd' + '\uf7fe' + '\uf7ff' +) + +### Encoding table +encoding_table = codecs.charmap_build(decoding_table) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/__init__.py b/venv/lib/python3.7/site-packages/pkg_resources/__init__.py new file mode 100644 index 0000000..6ca68da --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/__init__.py @@ -0,0 +1,3171 @@ +# coding: utf-8 +""" +Package resource API +-------------------- + +A resource is a logical file contained within a package, or a logical +subdirectory thereof. The package resource API expects resource names +to have their path parts separated with ``/``, *not* whatever the local +path separator is. Do not use os.path operations to manipulate resource +names being passed into the API. + +The package resource API is designed to work with normal filesystem packages, +.egg files, and unpacked .egg files. It can also work in a limited way with +.zip files and with custom PEP 302 loaders that support the ``get_data()`` +method. +""" + +from __future__ import absolute_import + +import sys +import os +import io +import time +import re +import types +import zipfile +import zipimport +import warnings +import stat +import functools +import pkgutil +import operator +import platform +import collections +import plistlib +import email.parser +import errno +import tempfile +import textwrap +import itertools +import inspect +from pkgutil import get_importer + +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + +try: + FileExistsError +except NameError: + FileExistsError = OSError + +from pkg_resources.extern import six +from pkg_resources.extern.six.moves import urllib, map, filter + +# capture these to bypass sandboxing +from os import utime +try: + from os import mkdir, rename, unlink + WRITE_SUPPORT = True +except ImportError: + # no write support, probably under GAE + WRITE_SUPPORT = False + +from os import open as os_open +from os.path import isdir, split + +try: + import importlib.machinery as importlib_machinery + # access attribute to force import under delayed import mechanisms. + importlib_machinery.__name__ +except ImportError: + importlib_machinery = None + +from . import py31compat +from pkg_resources.extern import appdirs +from pkg_resources.extern import packaging +__import__('pkg_resources.extern.packaging.version') +__import__('pkg_resources.extern.packaging.specifiers') +__import__('pkg_resources.extern.packaging.requirements') +__import__('pkg_resources.extern.packaging.markers') + + +__metaclass__ = type + + +if (3, 0) < sys.version_info < (3, 4): + raise RuntimeError("Python 3.4 or later is required") + +if six.PY2: + # Those builtin exceptions are only defined in Python 3 + PermissionError = None + NotADirectoryError = None + +# declare some globals that will be defined later to +# satisfy the linters. +require = None +working_set = None +add_activation_listener = None +resources_stream = None +cleanup_resources = None +resource_dir = None +resource_stream = None +set_extraction_path = None +resource_isdir = None +resource_string = None +iter_entry_points = None +resource_listdir = None +resource_filename = None +resource_exists = None +_distribution_finders = None +_namespace_handlers = None +_namespace_packages = None + + +class PEP440Warning(RuntimeWarning): + """ + Used when there is an issue with a version or specifier not complying with + PEP 440. + """ + + +def parse_version(v): + try: + return packaging.version.Version(v) + except packaging.version.InvalidVersion: + return packaging.version.LegacyVersion(v) + + +_state_vars = {} + + +def _declare_state(vartype, **kw): + globals().update(kw) + _state_vars.update(dict.fromkeys(kw, vartype)) + + +def __getstate__(): + state = {} + g = globals() + for k, v in _state_vars.items(): + state[k] = g['_sget_' + v](g[k]) + return state + + +def __setstate__(state): + g = globals() + for k, v in state.items(): + g['_sset_' + _state_vars[k]](k, g[k], v) + return state + + +def _sget_dict(val): + return val.copy() + + +def _sset_dict(key, ob, state): + ob.clear() + ob.update(state) + + +def _sget_object(val): + return val.__getstate__() + + +def _sset_object(key, ob, state): + ob.__setstate__(state) + + +_sget_none = _sset_none = lambda *args: None + + +def get_supported_platform(): + """Return this platform's maximum compatible version. + + distutils.util.get_platform() normally reports the minimum version + of Mac OS X that would be required to *use* extensions produced by + distutils. But what we want when checking compatibility is to know the + version of Mac OS X that we are *running*. To allow usage of packages that + explicitly require a newer version of Mac OS X, we must also know the + current version of the OS. + + If this condition occurs for any other platform with a version in its + platform strings, this function should be extended accordingly. + """ + plat = get_build_platform() + m = macosVersionString.match(plat) + if m is not None and sys.platform == "darwin": + try: + plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + except ValueError: + # not Mac OS X + pass + return plat + + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'iter_entry_points', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'Environment', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError', 'VersionConflict', 'DistributionNotFound', + 'UnknownExtra', 'ExtractionError', + + # Warnings + 'PEP440Warning', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Warnings + 'PkgResourcesDeprecationWarning', + + # Deprecated/backward compatibility only + 'run_main', 'AvailableDistributions', +] + + +class ResolutionError(Exception): + """Abstract base for dependency resolution errors""" + + def __repr__(self): + return self.__class__.__name__ + repr(self.args) + + +class VersionConflict(ResolutionError): + """ + An already-installed version conflicts with the requested version. + + Should be initialized with the installed Distribution and the requested + Requirement. + """ + + _template = "{self.dist} is installed but {self.req} is required" + + @property + def dist(self): + return self.args[0] + + @property + def req(self): + return self.args[1] + + def report(self): + return self._template.format(**locals()) + + def with_context(self, required_by): + """ + If required_by is non-empty, return a version of self that is a + ContextualVersionConflict. + """ + if not required_by: + return self + args = self.args + (required_by,) + return ContextualVersionConflict(*args) + + +class ContextualVersionConflict(VersionConflict): + """ + A VersionConflict that accepts a third parameter, the set of the + requirements that required the installed Distribution. + """ + + _template = VersionConflict._template + ' by {self.required_by}' + + @property + def required_by(self): + return self.args[2] + + +class DistributionNotFound(ResolutionError): + """A requested distribution was not found""" + + _template = ("The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}") + + @property + def req(self): + return self.args[0] + + @property + def requirers(self): + return self.args[1] + + @property + def requirers_str(self): + if not self.requirers: + return 'the application' + return ', '.join(self.requirers) + + def report(self): + return self._template.format(**locals()) + + def __str__(self): + return self.report() + + +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" + + +_provider_factories = {} + +PY_MAJOR = sys.version[:3] +EGG_DIST = 3 +BINARY_DIST = 2 +SOURCE_DIST = 1 +CHECKOUT_DIST = 0 +DEVELOP_DIST = -1 + + +def register_loader_type(loader_type, provider_factory): + """Register `provider_factory` to make providers for `loader_type` + + `loader_type` is the type or class of a PEP 302 ``module.__loader__``, + and `provider_factory` is a function that, passed a *module* object, + returns an ``IResourceProvider`` for that module. + """ + _provider_factories[loader_type] = provider_factory + + +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq, Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] + try: + module = sys.modules[moduleOrReq] + except KeyError: + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] + loader = getattr(module, '__loader__', None) + return _find_adapter(_provider_factories, loader)(module) + + +def _macosx_vers(_cache=[]): + if not _cache: + version = platform.mac_ver()[0] + # fallback for MacPorts + if version == '': + plist = '/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists(plist): + if hasattr(plistlib, 'readPlist'): + plist_content = plistlib.readPlist(plist) + if 'ProductVersion' in plist_content: + version = plist_content['ProductVersion'] + + _cache.append(version.split('.')) + return _cache[0] + + +def _macosx_arch(machine): + return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) + + +def get_build_platform(): + """Return this platform's string for platform-specific distributions + + XXX Currently this is the same as ``distutils.util.get_platform()``, but it + needs some hacks for Linux and Mac OS X. + """ + from sysconfig import get_platform + + plat = get_platform() + if sys.platform == "darwin" and not plat.startswith('macosx-'): + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d-%s" % ( + int(version[0]), int(version[1]), + _macosx_arch(machine), + ) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + return plat + + +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +# XXX backward compat +get_platform = get_build_platform + + +def compatible_platforms(provided, required): + """Can code for the `provided` platform run on the `required` platform? + + Returns true if either platform is ``None``, or the platforms are equal. + + XXX Needs compatibility checks for Linux and other unixy OSes. + """ + if provided is None or required is None or provided == required: + # easy case + return True + + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + return True + # egg isn't macosx or legacy darwin + return False + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(3) != reqMac.group(3): + return False + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here + return False + + +def run_script(dist_spec, script_name): + """Locate distribution `dist_spec` and run its `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].run_script(script_name, ns) + + +# backward compatibility +run_main = run_script + + +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist, six.string_types): + dist = Requirement.parse(dist) + if isinstance(dist, Requirement): + dist = get_provider(dist) + if not isinstance(dist, Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist + + +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) + + +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) + + +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) + + +class IMetadataProvider: + def has_metadata(name): + """Does the package's distribution contain the named metadata?""" + + def get_metadata(name): + """The named metadata resource as a string""" + + def get_metadata_lines(name): + """Yield named metadata resource as list of non-blank non-comment lines + + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" + + def metadata_isdir(name): + """Is the named metadata a directory? (like ``os.path.isdir()``)""" + + def metadata_listdir(name): + """List of metadata names in the directory (like ``os.listdir()``)""" + + def run_script(script_name, namespace): + """Execute the named script in the supplied namespace dictionary""" + + +class IResourceProvider(IMetadataProvider): + """An object that provides access to package resources""" + + def get_resource_filename(manager, resource_name): + """Return a true filesystem path for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_stream(manager, resource_name): + """Return a readable file-like object for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_string(manager, resource_name): + """Return a string containing the contents of `resource_name` + + `manager` must be an ``IResourceManager``""" + + def has_resource(resource_name): + """Does the package contain the named resource?""" + + def resource_isdir(resource_name): + """Is the named resource a directory? (like ``os.path.isdir()``)""" + + def resource_listdir(resource_name): + """List of resource names in the directory (like ``os.listdir()``)""" + + +class WorkingSet: + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + @classmethod + def _build_master(cls): + """ + Prepare the master working set. + """ + ws = cls() + try: + from __main__ import __requires__ + except ImportError: + # The main program does not list any requirements + return ws + + # ensure the requirements are met + try: + ws.require(__requires__) + except VersionConflict: + return cls._build_from_requirements(__requires__) + + return ws + + @classmethod + def _build_from_requirements(cls, req_spec): + """ + Build a working set from a requirement spec. Rewrites sys.path. + """ + # try it without defaults already on sys.path + # by starting with an empty path + ws = cls([]) + reqs = parse_requirements(req_spec) + dists = ws.resolve(reqs, Environment()) + for dist in dists: + ws.add(dist) + + # add any missing entries from sys.path + for entry in sys.path: + if entry not in ws.entries: + ws.add_entry(entry) + + # then copy back to sys.path + sys.path[:] = ws.entries + return ws + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry, True)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, True): + self.add(dist, entry, False) + + def __contains__(self, dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + # XXX add more info + raise VersionConflict(dist, req) + return dist + + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` + + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + return ( + entry + for dist in self + for entry in dist.get_entry_map(group).values() + if name is None or name == entry.name + ) + + def run_script(self, requires, script_name): + """Locate distribution for `requires` and run `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + self.require(requires)[0].run_script(script_name, ns) + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + seen = {} + for item in self.entries: + if item not in self.entry_keys: + # workaround a cache issue + continue + + for key in self.entry_keys[item]: + if key not in seen: + seen[key] = 1 + yield self.by_key[key] + + def add(self, dist, entry=None, insert=True, replace=False): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set, unless `replace=True`. + If it's added, any callbacks registered with the ``subscribe()`` method + will be called. + """ + if insert: + dist.insert_on(self.entries, entry, replace=replace) + + if entry is None: + entry = dist.location + keys = self.entry_keys.setdefault(entry, []) + keys2 = self.entry_keys.setdefault(dist.location, []) + if not replace and dist.key in self.by_key: + # ignore hidden distros + return + + self.by_key[dist.key] = dist + if dist.key not in keys: + keys.append(dist.key) + if dist.key not in keys2: + keys2.append(dist.key) + self._added_new(dist) + + def resolve(self, requirements, env=None, installer=None, + replace_conflicting=False, extras=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``Environment`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + + Unless `replace_conflicting=True`, raises a VersionConflict exception + if + any requirements are found on the path that have the correct name but + the wrong version. Otherwise, if an `installer` is supplied it will be + invoked to obtain the correct version of the requirement and activate + it. + + `extras` is a list of the extras to be used with these requirements. + This is important because extra requirements may look like `my_req; + extra = "my_extra"`, which would otherwise be interpreted as a purely + optional requirement. Instead, we want to be able to assert that these + requirements are truly required. + """ + + # set up the stack + requirements = list(requirements)[::-1] + # set of processed requirements + processed = {} + # key -> dist + best = {} + to_activate = [] + + req_extras = _ReqExtras() + + # Mapping of requirement to set of distributions that required it; + # useful for reporting info about conflicts. + required_by = collections.defaultdict(set) + + while requirements: + # process dependencies breadth-first + req = requirements.pop(0) + if req in processed: + # Ignore cyclic or redundant dependencies + continue + + if not req_extras.markers_pass(req, extras): + continue + + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None or (dist not in req and replace_conflicting): + ws = self + if env is None: + if dist is None: + env = Environment(self.entries) + else: + # Use an empty environment and workingset to avoid + # any further conflicts with the conflicting + # distribution + env = Environment([]) + ws = WorkingSet([]) + dist = best[req.key] = env.best_match( + req, ws, installer, + replace_conflicting=replace_conflicting + ) + if dist is None: + requirers = required_by.get(req, None) + raise DistributionNotFound(req, requirers) + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + dependent_req = required_by[req] + raise VersionConflict(dist, req).with_context(dependent_req) + + # push the new requirements onto the stack + new_requirements = dist.requires(req.extras)[::-1] + requirements.extend(new_requirements) + + # Register the new requirements needed by req + for new_requirement in new_requirements: + required_by[new_requirement].add(req.project_name) + req_extras[new_requirement] = req.extras + + processed[req] = True + + # return list of distros to activate + return to_activate + + def find_plugins( + self, plugin_env, full_env=None, installer=None, fallback=True): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + # add plugins+libs to sys.path + map(working_set.add, distributions) + # display errors + print('Could not load', errors) + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + # scan project names in alphabetic order + plugin_projects.sort() + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + # put all our entries in shadow_set + list(map(shadow_set.add, self)) + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError as v: + # save error info + error_info[dist] = v + if fallback: + # try the next older version of project + continue + else: + # give up on this project, keep going + break + + else: + list(map(shadow_set.add, resolvees)) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + def subscribe(self, callback, existing=True): + """Invoke `callback` for all distributions + + If `existing=True` (default), + call on all existing ones, as well. + """ + if callback in self.callbacks: + return + self.callbacks.append(callback) + if not existing: + return + for dist in self: + callback(dist) + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + def __getstate__(self): + return ( + self.entries[:], self.entry_keys.copy(), self.by_key.copy(), + self.callbacks[:] + ) + + def __setstate__(self, e_k_b_c): + entries, keys, by_key, callbacks = e_k_b_c + self.entries = entries[:] + self.entry_keys = keys.copy() + self.by_key = by_key.copy() + self.callbacks = callbacks[:] + + +class _ReqExtras(dict): + """ + Map each requirement to the extras that demanded it. + """ + + def markers_pass(self, req, extras=None): + """ + Evaluate markers for req against each extra that + demanded it. + + Return False if the req has a marker and fails + evaluation. Otherwise, return True. + """ + extra_evals = ( + req.marker.evaluate({'extra': extra}) + for extra in self.get(req, ()) + (extras or (None,)) + ) + return not req.marker or any(extra_evals) + + +class Environment: + """Searchable snapshot of distributions on a search path""" + + def __init__( + self, search_path=None, platform=get_supported_platform(), + python=PY_MAJOR): + """Snapshot distributions available on a search path + + Any distributions found on `search_path` are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. + + `platform` is an optional string specifying the name of the platform + that platform-specific distributions must be compatible with. If + unspecified, it defaults to the current platform. `python` is an + optional string naming the desired version of Python (e.g. ``'3.6'``); + it defaults to the current version. + + You may explicitly set `platform` (and/or `python`) to ``None`` if you + wish to map *all* distributions, not just those compatible with the + running platform or Python version. + """ + self._distmap = {} + self.platform = platform + self.python = python + self.scan(search_path) + + def can_add(self, dist): + """Is distribution `dist` acceptable for this environment? + + The distribution must match the platform and python version + requirements specified when this environment was created, or False + is returned. + """ + py_compat = ( + self.python is None + or dist.py_version is None + or dist.py_version == self.python + ) + return py_compat and compatible_platforms(dist.platform, self.platform) + + def remove(self, dist): + """Remove `dist` from the environment""" + self._distmap[dist.key].remove(dist) + + def scan(self, search_path=None): + """Scan `search_path` for distributions usable in this environment + + Any distributions found are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. Only distributions conforming to + the platform/python version defined at initialization are added. + """ + if search_path is None: + search_path = sys.path + + for item in search_path: + for dist in find_distributions(item): + self.add(dist) + + def __getitem__(self, project_name): + """Return a newest-to-oldest list of distributions for `project_name` + + Uses case-insensitive `project_name` comparison, assuming all the + project's distributions use their project's name converted to all + lowercase as their key. + + """ + distribution_key = project_name.lower() + return self._distmap.get(distribution_key, []) + + def add(self, dist): + """Add `dist` if we ``can_add()`` it and it has not already been added + """ + if self.can_add(dist) and dist.has_version(): + dists = self._distmap.setdefault(dist.key, []) + if dist not in dists: + dists.append(dist) + dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) + + def best_match( + self, req, working_set, installer=None, replace_conflicting=False): + """Find distribution best matching `req` and usable on `working_set` + + This calls the ``find(req)`` method of the `working_set` to see if a + suitable distribution is already active. (This may raise + ``VersionConflict`` if an unsuitable version of the project is already + active in the specified `working_set`.) If a suitable distribution + isn't active, this method returns the newest distribution in the + environment that meets the ``Requirement`` in `req`. If no suitable + distribution is found, and `installer` is supplied, then the result of + calling the environment's ``obtain(req, installer)`` method will be + returned. + """ + try: + dist = working_set.find(req) + except VersionConflict: + if not replace_conflicting: + raise + dist = None + if dist is not None: + return dist + for dist in self[req.key]: + if dist in req: + return dist + # try to download/install + return self.obtain(req, installer) + + def obtain(self, requirement, installer=None): + """Obtain a distribution matching `requirement` (e.g. via download) + + Obtain a distro that matches requirement (e.g. via download). In the + base ``Environment`` class, this routine just returns + ``installer(requirement)``, unless `installer` is None, in which case + None is returned instead. This method is a hook that allows subclasses + to attempt other ways of obtaining a distribution before falling back + to the `installer` argument.""" + if installer is not None: + return installer(requirement) + + def __iter__(self): + """Yield the unique project names of the available distributions""" + for key in self._distmap.keys(): + if self[key]: + yield key + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other, Distribution): + self.add(other) + elif isinstance(other, Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + +# XXX backward compatibility +AvailableDistributions = Environment + + +class ExtractionError(RuntimeError): + """An error occurred extracting a resource + + The following attributes are available from instances of this exception: + + manager + The resource manager that raised this exception + + cache_path + The base directory for resource extraction + + original_error + The exception instance that caused extraction to fail + """ + + +class ResourceManager: + """Manage resource extraction and packages""" + extraction_path = None + + def __init__(self): + self.cached_files = {} + + def resource_exists(self, package_or_requirement, resource_name): + """Does the named resource exist?""" + return get_provider(package_or_requirement).has_resource(resource_name) + + def resource_isdir(self, package_or_requirement, resource_name): + """Is the named resource an existing directory?""" + return get_provider(package_or_requirement).resource_isdir( + resource_name + ) + + def resource_filename(self, package_or_requirement, resource_name): + """Return a true filesystem path for specified resource""" + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name + ) + + def resource_stream(self, package_or_requirement, resource_name): + """Return a readable file-like object for specified resource""" + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name + ) + + def resource_string(self, package_or_requirement, resource_name): + """Return specified resource as a string""" + return get_provider(package_or_requirement).get_resource_string( + self, resource_name + ) + + def resource_listdir(self, package_or_requirement, resource_name): + """List the contents of the named resource directory""" + return get_provider(package_or_requirement).resource_listdir( + resource_name + ) + + def extraction_error(self): + """Give an error message for problems extracting file(s)""" + + old_exc = sys.exc_info()[1] + cache_path = self.extraction_path or get_default_cache() + + tmpl = textwrap.dedent(""" + Can't extract file(s) to egg cache + + The following error occurred while trying to extract file(s) + to the Python egg cache: + + {old_exc} + + The Python egg cache directory is currently set to: + + {cache_path} + + Perhaps your account does not have write access to this directory? + You can change the cache directory by setting the PYTHON_EGG_CACHE + environment variable to point to an accessible directory. + """).lstrip() + err = ExtractionError(tmpl.format(**locals())) + err.manager = self + err.cache_path = cache_path + err.original_error = old_exc + raise err + + def get_cache_path(self, archive_name, names=()): + """Return absolute location in cache for `archive_name` and `names` + + The parent directory of the resulting path will be created if it does + not already exist. `archive_name` should be the base filename of the + enclosing egg (which may not be the name of the enclosing zipfile!), + including its ".egg" extension. `names`, if provided, should be a + sequence of path name parts "under" the egg's extraction location. + + This method should only be called by resource providers that need to + obtain an extraction location, and only for names they intend to + extract, as it tracks the generated names for possible cleanup later. + """ + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name + '-tmp', *names) + try: + _bypass_ensure_directory(target_path) + except Exception: + self.extraction_error() + + self._warn_unsafe_extraction_path(extract_path) + + self.cached_files[target_path] = 1 + return target_path + + @staticmethod + def _warn_unsafe_extraction_path(path): + """ + If the default extraction path is overridden and set to an insecure + location, such as /tmp, it opens up an opportunity for an attacker to + replace an extracted file with an unauthorized payload. Warn the user + if a known insecure location is used. + + See Distribute #375 for more details. + """ + if os.name == 'nt' and not path.startswith(os.environ['windir']): + # On Windows, permissions are generally restrictive by default + # and temp directories are not writable by other users, so + # bypass the warning. + return + mode = os.stat(path).st_mode + if mode & stat.S_IWOTH or mode & stat.S_IWGRP: + msg = ( + "%s is writable by group/others and vulnerable to attack " + "when " + "used with get_resource_filename. Consider a more secure " + "location (set with .set_extraction_path or the " + "PYTHON_EGG_CACHE environment variable)." % path + ) + warnings.warn(msg, UserWarning) + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` + + This is where Mac header rewrites should be done; other platforms don't + have anything special they should do. + + Resource providers should call this method ONLY after successfully + extracting a compressed resource. They must NOT call it on resources + that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. + """ + + if os.name == 'posix': + # Make the resource executable + mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 + os.chmod(tempname, mode) + + def set_extraction_path(self, path): + """Set the base path where resources will be extracted to, if needed. + + If you do not call this routine before any extractions take place, the + path defaults to the return value of ``get_default_cache()``. (Which + is based on the ``PYTHON_EGG_CACHE`` environment variable, with various + platform-specific fallbacks. See that routine's documentation for more + details.) + + Resources are extracted to subdirectories of this path based upon + information given by the ``IResourceProvider``. You may set this to a + temporary directory, but then you must call ``cleanup_resources()`` to + delete the extracted files when done. There is no guarantee that + ``cleanup_resources()`` will be able to remove all extracted files. + + (Note: you may not change the extraction path for a given resource + manager once resources have been extracted, unless you first call + ``cleanup_resources()``.) + """ + if self.cached_files: + raise ValueError( + "Can't change extraction path, files already extracted" + ) + + self.extraction_path = path + + def cleanup_resources(self, force=False): + """ + Delete all extracted resource files and directories, returning a list + of the file and directory names that could not be successfully removed. + This function does not have any concurrency protection, so it should + generally only be called when the extraction path is a temporary + directory exclusive to a single process. This method is not + automatically called; you must call it explicitly or register it as an + ``atexit`` function if you wish to ensure cleanup of a temporary + directory used for extractions. + """ + # XXX + + +def get_default_cache(): + """ + Return the ``PYTHON_EGG_CACHE`` environment variable + or a platform-relevant user cache dir for an app + named "Python-Eggs". + """ + return ( + os.environ.get('PYTHON_EGG_CACHE') + or appdirs.user_cache_dir(appname='Python-Eggs') + ) + + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """ + Convert an arbitrary string to a standard version string + """ + try: + # normalize the version + return str(packaging.version.Version(version)) + except packaging.version.InvalidVersion: + version = version.replace(' ', '.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-', '_') + + +def invalid_marker(text): + """ + Validate text as a PEP 508 environment marker; return an exception + if invalid or False otherwise. + """ + try: + evaluate_marker(text) + except SyntaxError as e: + e.filename = None + e.lineno = None + return e + return False + + +def evaluate_marker(text, extra=None): + """ + Evaluate a PEP 508 environment marker. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. + + This implementation uses the 'pyparsing' module. + """ + try: + marker = packaging.markers.Marker(text) + return marker.evaluate() + except packaging.markers.InvalidMarker as e: + raise SyntaxError(e) + + +class NullProvider: + """Try to implement resources and metadata for arbitrary PEP 302 loaders""" + + egg_name = None + egg_info = None + loader = None + + def __init__(self, module): + self.loader = getattr(module, '__loader__', None) + self.module_path = os.path.dirname(getattr(module, '__file__', '')) + + def get_resource_filename(self, manager, resource_name): + return self._fn(self.module_path, resource_name) + + def get_resource_stream(self, manager, resource_name): + return io.BytesIO(self.get_resource_string(manager, resource_name)) + + def get_resource_string(self, manager, resource_name): + return self._get(self._fn(self.module_path, resource_name)) + + def has_resource(self, resource_name): + return self._has(self._fn(self.module_path, resource_name)) + + def has_metadata(self, name): + return self.egg_info and self._has(self._fn(self.egg_info, name)) + + def get_metadata(self, name): + if not self.egg_info: + return "" + value = self._get(self._fn(self.egg_info, name)) + return value.decode('utf-8') if six.PY3 else value + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + def resource_isdir(self, resource_name): + return self._isdir(self._fn(self.module_path, resource_name)) + + def metadata_isdir(self, name): + return self.egg_info and self._isdir(self._fn(self.egg_info, name)) + + def resource_listdir(self, resource_name): + return self._listdir(self._fn(self.module_path, resource_name)) + + def metadata_listdir(self, name): + if self.egg_info: + return self._listdir(self._fn(self.egg_info, name)) + return [] + + def run_script(self, script_name, namespace): + script = 'scripts/' + script_name + if not self.has_metadata(script): + raise ResolutionError( + "Script {script!r} not found in metadata at {self.egg_info!r}" + .format(**locals()), + ) + script_text = self.get_metadata(script).replace('\r\n', '\n') + script_text = script_text.replace('\r', '\n') + script_filename = self._fn(self.egg_info, script) + namespace['__file__'] = script_filename + if os.path.exists(script_filename): + source = open(script_filename).read() + code = compile(source, script_filename, 'exec') + exec(code, namespace, namespace) + else: + from linecache import cache + cache[script_filename] = ( + len(script_text), 0, script_text.split('\n'), script_filename + ) + script_code = compile(script_text, script_filename, 'exec') + exec(script_code, namespace, namespace) + + def _has(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _isdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _listdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _fn(self, base, resource_name): + if resource_name: + return os.path.join(base, *resource_name.split('/')) + return base + + def _get(self, path): + if hasattr(self.loader, 'get_data'): + return self.loader.get_data(path) + raise NotImplementedError( + "Can't perform this operation for loaders without 'get_data()'" + ) + + +register_loader_type(object, NullProvider) + + +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" + + def __init__(self, module): + NullProvider.__init__(self, module) + self._setup_prefix() + + def _setup_prefix(self): + # we assume here that our metadata may be nested inside a "basket" + # of multiple eggs; that's why we use module_path instead of .archive + path = self.module_path + old = None + while path != old: + if _is_egg_path(path): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path + break + old = path + path, base = os.path.split(path) + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + + def _isdir(self, path): + return os.path.isdir(path) + + def _listdir(self, path): + return os.listdir(path) + + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + + def _get(self, path): + with open(path, 'rb') as stream: + return stream.read() + + @classmethod + def _register(cls): + loader_names = 'SourceFileLoader', 'SourcelessFileLoader', + for name in loader_names: + loader_cls = getattr(importlib_machinery, name, type(None)) + register_loader_type(loader_cls, cls) + + +DefaultProvider._register() + + +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + + module_path = None + + _isdir = _has = lambda self, path: False + + def _get(self, path): + return '' + + def _listdir(self, path): + return [] + + def __init__(self): + pass + + +empty_provider = EmptyProvider() + + +class ZipManifests(dict): + """ + zip manifest builder + """ + + @classmethod + def build(cls, path): + """ + Build a dictionary similar to the zipimport directory + caches, except instead of tuples, store ZipInfo objects. + + Use a platform-specific path separator (os.sep) for the path keys + for compatibility with pypy on Windows. + """ + with zipfile.ZipFile(path) as zfile: + items = ( + ( + name.replace('/', os.sep), + zfile.getinfo(name), + ) + for name in zfile.namelist() + ) + return dict(items) + + load = build + + +class MemoizedZipManifests(ZipManifests): + """ + Memoized zipfile manifests. + """ + manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') + + def load(self, path): + """ + Load a manifest at path or return a suitable manifest already loaded. + """ + path = os.path.normpath(path) + mtime = os.stat(path).st_mtime + + if path not in self or self[path].mtime != mtime: + manifest = self.build(path) + self[path] = self.manifest_mod(manifest, mtime) + + return self[path].manifest + + +class ZipProvider(EggProvider): + """Resource support for zips and eggs""" + + eagers = None + _zip_manifests = MemoizedZipManifests() + + def __init__(self, module): + EggProvider.__init__(self, module) + self.zip_pre = self.loader.archive + os.sep + + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + fspath = fspath.rstrip(os.sep) + if fspath == self.loader.archive: + return '' + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.zip_pre) + ) + + def _parts(self, zip_path): + # Convert a zipfile subpath into an egg-relative path part list. + # pseudo-fs path + fspath = self.zip_pre + zip_path + if fspath.startswith(self.egg_root + os.sep): + return fspath[len(self.egg_root) + 1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.egg_root) + ) + + @property + def zipinfo(self): + return self._zip_manifests.load(self.loader.archive) + + def get_resource_filename(self, manager, resource_name): + if not self.egg_name: + raise NotImplementedError( + "resource_filename() only supported for .egg, not .zip" + ) + # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) + eagers = self._get_eager_resources() + if '/'.join(self._parts(zip_path)) in eagers: + for name in eagers: + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) + + @staticmethod + def _get_date_and_size(zip_stat): + size = zip_stat.file_size + # ymdhms+wday, yday, dst + date_time = zip_stat.date_time + (0, 0, -1) + # 1980 offset already done + timestamp = time.mktime(date_time) + return timestamp, size + + def _extract_resource(self, manager, zip_path): + + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + # return the extracted directory name + return os.path.dirname(last) + + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + + if not WRITE_SUPPORT: + raise IOError('"os.rename" and "os.unlink" are not supported ' + 'on this platform') + try: + + real_path = manager.get_cache_path( + self.egg_name, self._parts(zip_path) + ) + + if self._is_current(real_path, zip_path): + return real_path + + outf, tmpnam = _mkstemp( + ".$extract", + dir=os.path.dirname(real_path), + ) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + utime(tmpnam, (timestamp, timestamp)) + manager.postprocess(tmpnam, real_path) + + try: + rename(tmpnam, real_path) + + except os.error: + if os.path.isfile(real_path): + if self._is_current(real_path, zip_path): + # the file became current since it was checked above, + # so proceed. + return real_path + # Windows, del old file and retry + elif os.name == 'nt': + unlink(real_path) + rename(tmpnam, real_path) + return real_path + raise + + except os.error: + # report a user-friendly error + manager.extraction_error() + + return real_path + + def _is_current(self, file_path, zip_path): + """ + Return True if the file_path is current for this zip_path + """ + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + if not os.path.isfile(file_path): + return False + stat = os.stat(file_path) + if stat.st_size != size or stat.st_mtime != timestamp: + return False + # check that the contents match + zip_contents = self.loader.get_data(zip_path) + with open(file_path, 'rb') as f: + file_contents = f.read() + return zip_contents == file_contents + + def _get_eager_resources(self): + if self.eagers is None: + eagers = [] + for name in ('native_libs.txt', 'eager_resources.txt'): + if self.has_metadata(name): + eagers.extend(self.get_metadata_lines(name)) + self.eagers = eagers + return self.eagers + + def _index(self): + try: + return self._dirindex + except AttributeError: + ind = {} + for path in self.zipinfo: + parts = path.split(os.sep) + while parts: + parent = os.sep.join(parts[:-1]) + if parent in ind: + ind[parent].append(parts[-1]) + break + else: + ind[parent] = [parts.pop()] + self._dirindex = ind + return ind + + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() + + def _isdir(self, fspath): + return self._zipinfo_name(fspath) in self._index() + + def _listdir(self, fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) + + def _eager_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.egg_root, resource_name)) + + def _resource_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.module_path, resource_name)) + + +register_loader_type(zipimport.zipimporter, ZipProvider) + + +class FileMetadata(EmptyProvider): + """Metadata handler for standalone PKG-INFO files + + Usage:: + + metadata = FileMetadata("/path/to/PKG-INFO") + + This provider rejects all data and metadata requests except for PKG-INFO, + which is treated as existing, and will be the contents of the file at + the provided location. + """ + + def __init__(self, path): + self.path = path + + def has_metadata(self, name): + return name == 'PKG-INFO' and os.path.isfile(self.path) + + def get_metadata(self, name): + if name != 'PKG-INFO': + raise KeyError("No metadata except PKG-INFO is available") + + with io.open(self.path, encoding='utf-8', errors="replace") as f: + metadata = f.read() + self._warn_on_replacement(metadata) + return metadata + + def _warn_on_replacement(self, metadata): + # Python 2.7 compat for: replacement_char = '�' + replacement_char = b'\xef\xbf\xbd'.decode('utf-8') + if replacement_char in metadata: + tmpl = "{self.path} could not be properly decoded in UTF-8" + msg = tmpl.format(**locals()) + warnings.warn(msg) + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + +class PathMetadata(DefaultProvider): + """Metadata provider for egg directories + + Usage:: + + # Development eggs: + + egg_info = "/path/to/PackageName.egg-info" + base_dir = os.path.dirname(egg_info) + metadata = PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + dist = Distribution(basedir, project_name=dist_name, metadata=metadata) + + # Unpacked egg directories: + + egg_path = "/path/to/PackageName-ver-pyver-etc.egg" + metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) + dist = Distribution.from_filename(egg_path, metadata=metadata) + """ + + def __init__(self, path, egg_info): + self.module_path = path + self.egg_info = egg_info + + +class EggMetadata(ZipProvider): + """Metadata provider for .egg files""" + + def __init__(self, importer): + """Create a metadata provider from a zipimporter""" + + self.zip_pre = importer.archive + os.sep + self.loader = importer + if importer.prefix: + self.module_path = os.path.join(importer.archive, importer.prefix) + else: + self.module_path = importer.archive + self._setup_prefix() + + +_declare_state('dict', _distribution_finders={}) + + +def register_finder(importer_type, distribution_finder): + """Register `distribution_finder` to find distributions in sys.path items + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `distribution_finder` is a callable that, passed a path + item and the importer instance, yields ``Distribution`` instances found on + that path item. See ``pkg_resources.find_on_path`` for an example.""" + _distribution_finders[importer_type] = distribution_finder + + +def find_distributions(path_item, only=False): + """Yield distributions accessible via `path_item`""" + importer = get_importer(path_item) + finder = _find_adapter(_distribution_finders, importer) + return finder(importer, path_item, only) + + +def find_eggs_in_zip(importer, path_item, only=False): + """ + Find eggs in zip files; possibly multiple nested eggs. + """ + if importer.archive.endswith('.whl'): + # wheels are not supported with this finder + # they don't have PKG-INFO metadata, and won't ever contain eggs + return + metadata = EggMetadata(importer) + if metadata.has_metadata('PKG-INFO'): + yield Distribution.from_filename(path_item, metadata=metadata) + if only: + # don't yield nested distros + return + for subitem in metadata.resource_listdir('/'): + if _is_egg_path(subitem): + subpath = os.path.join(path_item, subitem) + dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) + for dist in dists: + yield dist + elif subitem.lower().endswith('.dist-info'): + subpath = os.path.join(path_item, subitem) + submeta = EggMetadata(zipimport.zipimporter(subpath)) + submeta.egg_info = subpath + yield Distribution.from_location(path_item, subitem, submeta) + + +register_finder(zipimport.zipimporter, find_eggs_in_zip) + + +def find_nothing(importer, path_item, only=False): + return () + + +register_finder(object, find_nothing) + + +def _by_version_descending(names): + """ + Given a list of filenames, return them in descending order + by version number. + + >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' + >>> _by_version_descending(names) + ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] + """ + def _by_version(name): + """ + Parse each component of the filename + """ + name, ext = os.path.splitext(name) + parts = itertools.chain(name.split('-'), [ext]) + return [packaging.version.parse(part) for part in parts] + + return sorted(names, key=_by_version, reverse=True) + + +def find_on_path(importer, path_item, only=False): + """Yield distributions accessible on a sys.path directory""" + path_item = _normalize_cached(path_item) + + if _is_unpacked_egg(path_item): + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item, 'EGG-INFO') + ) + ) + return + + entries = safe_listdir(path_item) + + # for performance, before sorting by version, + # screen entries for only those that will yield + # distributions + filtered = ( + entry + for entry in entries + if dist_factory(path_item, entry, only) + ) + + # scan for .egg and .egg-info in directory + path_item_entries = _by_version_descending(filtered) + for entry in path_item_entries: + fullpath = os.path.join(path_item, entry) + factory = dist_factory(path_item, entry, only) + for dist in factory(fullpath): + yield dist + + +def dist_factory(path_item, entry, only): + """ + Return a dist_factory for a path_item and entry + """ + lower = entry.lower() + is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) + return ( + distributions_from_metadata + if is_meta else + find_distributions + if not only and _is_egg_path(entry) else + resolve_egg_link + if not only and lower.endswith('.egg-link') else + NoDists() + ) + + +class NoDists: + """ + >>> bool(NoDists()) + False + + >>> list(NoDists()('anything')) + [] + """ + def __bool__(self): + return False + if six.PY2: + __nonzero__ = __bool__ + + def __call__(self, fullpath): + return iter(()) + + +def safe_listdir(path): + """ + Attempt to list contents of path, but suppress some exceptions. + """ + try: + return os.listdir(path) + except (PermissionError, NotADirectoryError): + pass + except OSError as e: + # Ignore the directory if does not exist, not a directory or + # permission denied + ignorable = ( + e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) + # Python 2 on Windows needs to be handled this way :( + or getattr(e, "winerror", None) == 267 + ) + if not ignorable: + raise + return () + + +def distributions_from_metadata(path): + root = os.path.dirname(path) + if os.path.isdir(path): + if len(os.listdir(path)) == 0: + # empty metadata dir; skip + return + metadata = PathMetadata(root, path) + else: + metadata = FileMetadata(path) + entry = os.path.basename(path) + yield Distribution.from_location( + root, entry, metadata, precedence=DEVELOP_DIST, + ) + + +def non_empty_lines(path): + """ + Yield non-empty lines from file at path + """ + with open(path) as f: + for line in f: + line = line.strip() + if line: + yield line + + +def resolve_egg_link(path): + """ + Given a path to an .egg-link, resolve distributions + present in the referenced path. + """ + referenced_paths = non_empty_lines(path) + resolved_paths = ( + os.path.join(os.path.dirname(path), ref) + for ref in referenced_paths + ) + dist_groups = map(find_distributions, resolved_paths) + return next(dist_groups, ()) + + +register_finder(pkgutil.ImpImporter, find_on_path) + +if hasattr(importlib_machinery, 'FileFinder'): + register_finder(importlib_machinery.FileFinder, find_on_path) + +_declare_state('dict', _namespace_handlers={}) +_declare_state('dict', _namespace_packages={}) + + +def register_namespace_handler(importer_type, namespace_handler): + """Register `namespace_handler` to declare namespace packages + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `namespace_handler` is a callable like this:: + + def namespace_handler(importer, path_entry, moduleName, module): + # return a path_entry to use for child packages + + Namespace handlers are only called if the importer object has already + agreed that it can handle the relevant path item, and they should only + return a subpath if the module __path__ does not already contain an + equivalent subpath. For an example namespace handler, see + ``pkg_resources.file_ns_handler``. + """ + _namespace_handlers[importer_type] = namespace_handler + + +def _handle_ns(packageName, path_item): + """Ensure that named package includes a subpath of path_item (if needed)""" + + importer = get_importer(path_item) + if importer is None: + return None + + # capture warnings due to #1111 + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + loader = importer.find_module(packageName) + + if loader is None: + return None + module = sys.modules.get(packageName) + if module is None: + module = sys.modules[packageName] = types.ModuleType(packageName) + module.__path__ = [] + _set_parent_ns(packageName) + elif not hasattr(module, '__path__'): + raise TypeError("Not a package:", packageName) + handler = _find_adapter(_namespace_handlers, importer) + subpath = handler(importer, path_item, packageName, module) + if subpath is not None: + path = module.__path__ + path.append(subpath) + loader.load_module(packageName) + _rebuild_mod_path(path, packageName, module) + return subpath + + +def _rebuild_mod_path(orig_path, package_name, module): + """ + Rebuild module.__path__ ensuring that all entries are ordered + corresponding to their sys.path order + """ + sys_path = [_normalize_cached(p) for p in sys.path] + + def safe_sys_path_index(entry): + """ + Workaround for #520 and #513. + """ + try: + return sys_path.index(entry) + except ValueError: + return float('inf') + + def position_in_sys_path(path): + """ + Return the ordinal of the path based on its position in sys.path + """ + path_parts = path.split(os.sep) + module_parts = package_name.count('.') + 1 + parts = path_parts[:-module_parts] + return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) + + new_path = sorted(orig_path, key=position_in_sys_path) + new_path = [_normalize_cached(p) for p in new_path] + + if isinstance(module.__path__, list): + module.__path__[:] = new_path + else: + module.__path__ = new_path + + +def declare_namespace(packageName): + """Declare that package 'packageName' is a namespace package""" + + _imp.acquire_lock() + try: + if packageName in _namespace_packages: + return + + path = sys.path + parent, _, _ = packageName.rpartition('.') + + if parent: + declare_namespace(parent) + if parent not in _namespace_packages: + __import__(parent) + try: + path = sys.modules[parent].__path__ + except AttributeError: + raise TypeError("Not a package:", parent) + + # Track what packages are namespaces, so when new path items are added, + # they can be updated + _namespace_packages.setdefault(parent or None, []).append(packageName) + _namespace_packages.setdefault(packageName, []) + + for path_item in path: + # Ensure all the parent's path items are reflected in the child, + # if they apply + _handle_ns(packageName, path_item) + + finally: + _imp.release_lock() + + +def fixup_namespace_packages(path_item, parent=None): + """Ensure that previously-declared namespace packages include path_item""" + _imp.acquire_lock() + try: + for package in _namespace_packages.get(parent, ()): + subpath = _handle_ns(package, path_item) + if subpath: + fixup_namespace_packages(subpath, package) + finally: + _imp.release_lock() + + +def file_ns_handler(importer, path_item, packageName, module): + """Compute an ns-package subpath for a filesystem or zipfile importer""" + + subpath = os.path.join(path_item, packageName.split('.')[-1]) + normalized = _normalize_cached(subpath) + for item in module.__path__: + if _normalize_cached(item) == normalized: + break + else: + # Only return the path if it's not already there + return subpath + + +register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) +register_namespace_handler(zipimport.zipimporter, file_ns_handler) + +if hasattr(importlib_machinery, 'FileFinder'): + register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) + + +def null_ns_handler(importer, path_item, packageName, module): + return None + + +register_namespace_handler(object, null_ns_handler) + + +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename)))) + + +def _cygwin_patch(filename): # pragma: nocover + """ + Contrary to POSIX 2008, on Cygwin, getcwd (3) contains + symlink components. Using + os.path.abspath() works around this limitation. A fix in os.getcwd() + would probably better, in Cygwin even more so, except + that this seems to be by design... + """ + return os.path.abspath(filename) if sys.platform == 'cygwin' else filename + + +def _normalize_cached(filename, _cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result + + +def _is_egg_path(path): + """ + Determine if given path appears to be an egg. + """ + return path.lower().endswith('.egg') + + +def _is_unpacked_egg(path): + """ + Determine if given path appears to be an unpacked egg. + """ + return ( + _is_egg_path(path) and + os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) + ) + + +def _set_parent_ns(packageName): + parts = packageName.split('.') + name = parts.pop() + if parts: + parent = '.'.join(parts) + setattr(sys.modules[parent], name, sys.modules[packageName]) + + +def yield_lines(strs): + """Yield non-empty/non-comment lines of a string or sequence""" + if isinstance(strs, six.string_types): + for s in strs.splitlines(): + s = s.strip() + # skip blank lines/comments + if s and not s.startswith('#'): + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + + +MODULE = re.compile(r"\w+(\.\w+)*$").match +EGG_NAME = re.compile( + r""" + (?P<name>[^-]+) ( + -(?P<ver>[^-]+) ( + -py(?P<pyver>[^-]+) ( + -(?P<plat>.+) + )? + )? + )? + """, + re.VERBOSE | re.IGNORECASE, +).match + + +class EntryPoint: + """Object representing an advertised importable object""" + + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = tuple(extras) + self.dist = dist + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self, require=True, *args, **kwargs): + """ + Require packages for this EntryPoint, then resolve it. + """ + if not require or args or kwargs: + warnings.warn( + "Parameters to load are deprecated. Call .resolve and " + ".require separately.", + PkgResourcesDeprecationWarning, + stacklevel=2, + ) + if require: + self.require(*args, **kwargs) + return self.resolve() + + def resolve(self): + """ + Resolve the entry point from its module and attrs. + """ + module = __import__(self.module_name, fromlist=['__name__'], level=0) + try: + return functools.reduce(getattr, self.attrs, module) + except AttributeError as exc: + raise ImportError(str(exc)) + + def require(self, env=None, installer=None): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + + # Get the requirements for this entry point with all its extras and + # then resolve them. We have to pass `extras` along when resolving so + # that the working set knows what extras we want. Otherwise, for + # dist-info distributions, the working set will assume that the + # requirements for that extra are purely optional and skip over them. + reqs = self.dist.requires(self.extras) + items = working_set.resolve(reqs, env, installer, extras=self.extras) + list(map(working_set.add, items)) + + pattern = re.compile( + r'\s*' + r'(?P<name>.+?)\s*' + r'=\s*' + r'(?P<module>[\w.]+)\s*' + r'(:\s*(?P<attr>[\w.]+))?\s*' + r'(?P<extras>\[.*\])?\s*$' + ) + + @classmethod + def parse(cls, src, dist=None): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1, extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + m = cls.pattern.match(src) + if not m: + msg = "EntryPoint must be in 'name=module:attrs [extras]' format" + raise ValueError(msg, src) + res = m.groupdict() + extras = cls._parse_extras(res['extras']) + attrs = res['attr'].split('.') if res['attr'] else () + return cls(res['name'], res['module'], attrs, extras, dist) + + @classmethod + def _parse_extras(cls, extras_spec): + if not extras_spec: + return () + req = Requirement.parse('x' + extras_spec) + if req.specs: + raise ValueError() + return req.extras + + @classmethod + def parse_group(cls, group, lines, dist=None): + """Parse an entry point group""" + if not MODULE(group): + raise ValueError("Invalid group name", group) + this = {} + for line in yield_lines(lines): + ep = cls.parse(line, dist) + if ep.name in this: + raise ValueError("Duplicate entry point", group, ep.name) + this[ep.name] = ep + return this + + @classmethod + def parse_map(cls, data, dist=None): + """Parse a map of entry point groups""" + if isinstance(data, dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for group, lines in data: + if group is None: + if not lines: + continue + raise ValueError("Entry points must be listed in groups") + group = group.strip() + if group in maps: + raise ValueError("Duplicate group name", group) + maps[group] = cls.parse_group(group, lines, dist) + return maps + + +def _remove_md5_fragment(location): + if not location: + return '' + parsed = urllib.parse.urlparse(location) + if parsed[-1].startswith('md5='): + return urllib.parse.urlunparse(parsed[:-1] + ('',)) + return location + + +def _version_from_file(lines): + """ + Given an iterable of lines from a Metadata file, return + the value of the Version field, if present, or None otherwise. + """ + def is_version_line(line): + return line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) + line = next(iter(version_lines), '') + _, _, value = line.partition(':') + return safe_version(value.strip()) or None + + +class Distribution: + """Wrap an actual or potential sys.path entry w/metadata""" + PKG_INFO = 'PKG-INFO' + + def __init__( + self, location=None, metadata=None, project_name=None, + version=None, py_version=PY_MAJOR, platform=None, + precedence=EGG_DIST): + self.project_name = safe_name(project_name or 'Unknown') + if version is not None: + self._version = safe_version(version) + self.py_version = py_version + self.platform = platform + self.location = location + self.precedence = precedence + self._provider = metadata or empty_provider + + @classmethod + def from_location(cls, location, basename, metadata=None, **kw): + project_name, version, py_version, platform = [None] * 4 + basename, ext = os.path.splitext(basename) + if ext.lower() in _distributionImpl: + cls = _distributionImpl[ext.lower()] + + match = EGG_NAME(basename) + if match: + project_name, version, py_version, platform = match.group( + 'name', 'ver', 'pyver', 'plat' + ) + return cls( + location, metadata, project_name=project_name, version=version, + py_version=py_version, platform=platform, **kw + )._reload_version() + + def _reload_version(self): + return self + + @property + def hashcmp(self): + return ( + self.parsed_version, + self.precedence, + self.key, + _remove_md5_fragment(self.location), + self.py_version or '', + self.platform or '', + ) + + def __hash__(self): + return hash(self.hashcmp) + + def __lt__(self, other): + return self.hashcmp < other.hashcmp + + def __le__(self, other): + return self.hashcmp <= other.hashcmp + + def __gt__(self, other): + return self.hashcmp > other.hashcmp + + def __ge__(self, other): + return self.hashcmp >= other.hashcmp + + def __eq__(self, other): + if not isinstance(other, self.__class__): + # It's not a Distribution, so they are not equal + return False + return self.hashcmp == other.hashcmp + + def __ne__(self, other): + return not self == other + + # These properties have to be lazy so that we don't have to load any + # metadata until/unless it's actually needed. (i.e., some distributions + # may not know their name or version without loading PKG-INFO) + + @property + def key(self): + try: + return self._key + except AttributeError: + self._key = key = self.project_name.lower() + return key + + @property + def parsed_version(self): + if not hasattr(self, "_parsed_version"): + self._parsed_version = parse_version(self.version) + + return self._parsed_version + + def _warn_legacy_version(self): + LV = packaging.version.LegacyVersion + is_legacy = isinstance(self._parsed_version, LV) + if not is_legacy: + return + + # While an empty version is technically a legacy version and + # is not a valid PEP 440 version, it's also unlikely to + # actually come from someone and instead it is more likely that + # it comes from setuptools attempting to parse a filename and + # including it in the list. So for that we'll gate this warning + # on if the version is anything at all or not. + if not self.version: + return + + tmpl = textwrap.dedent(""" + '{project_name} ({version})' is being parsed as a legacy, + non PEP 440, + version. You may find odd behavior and sort order. + In particular it will be sorted as less than 0.0. It + is recommended to migrate to PEP 440 compatible + versions. + """).strip().replace('\n', ' ') + + warnings.warn(tmpl.format(**vars(self)), PEP440Warning) + + @property + def version(self): + try: + return self._version + except AttributeError: + version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if version is None: + tmpl = "Missing 'Version:' header and/or %s file" + raise ValueError(tmpl % self.PKG_INFO, self) + return version + + @property + def _dep_map(self): + """ + A map of extra to its list of (direct) requirements + for this distribution, including the null extra. + """ + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._filter_extras(self._build_dep_map()) + return self.__dep_map + + @staticmethod + def _filter_extras(dm): + """ + Given a mapping of extras to dependencies, strip off + environment markers and filter out any dependencies + not matching the markers. + """ + for extra in list(filter(None, dm)): + new_extra = extra + reqs = dm.pop(extra) + new_extra, _, marker = extra.partition(':') + fails_marker = marker and ( + invalid_marker(marker) + or not evaluate_marker(marker) + ) + if fails_marker: + reqs = [] + new_extra = safe_extra(new_extra) or None + + dm.setdefault(new_extra, []).extend(reqs) + return dm + + def _build_dep_map(self): + dm = {} + for name in 'requires.txt', 'depends.txt': + for extra, reqs in split_sections(self._get_metadata(name)): + dm.setdefault(extra, []).extend(parse_requirements(reqs)) + return dm + + def requires(self, extras=()): + """List of Requirements needed for this distro if `extras` are used""" + dm = self._dep_map + deps = [] + deps.extend(dm.get(None, ())) + for ext in extras: + try: + deps.extend(dm[safe_extra(ext)]) + except KeyError: + raise UnknownExtra( + "%s has no such extra feature %r" % (self, ext) + ) + return deps + + def _get_metadata(self, name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + def activate(self, path=None, replace=False): + """Ensure distribution is importable on `path` (default=sys.path)""" + if path is None: + path = sys.path + self.insert_on(path, replace=replace) + if path is sys.path: + fixup_namespace_packages(self.location) + for pkg in self._get_metadata('namespace_packages.txt'): + if pkg in sys.modules: + declare_namespace(pkg) + + def egg_name(self): + """Return what this distribution's standard .egg filename should be""" + filename = "%s-%s-py%s" % ( + to_filename(self.project_name), to_filename(self.version), + self.py_version or PY_MAJOR + ) + + if self.platform: + filename += '-' + self.platform + return filename + + def __repr__(self): + if self.location: + return "%s (%s)" % (self, self.location) + else: + return str(self) + + def __str__(self): + try: + version = getattr(self, 'version', None) + except ValueError: + version = None + version = version or "[unknown version]" + return "%s %s" % (self.project_name, version) + + def __getattr__(self, attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError(attr) + return getattr(self._provider, attr) + + def __dir__(self): + return list( + set(super(Distribution, self).__dir__()) + | set( + attr for attr in self._provider.__dir__() + if not attr.startswith('_') + ) + ) + + if not hasattr(object, '__dir__'): + # python 2.7 not supported + del __dir__ + + @classmethod + def from_filename(cls, filename, metadata=None, **kw): + return cls.from_location( + _normalize_cached(filename), os.path.basename(filename), metadata, + **kw + ) + + def as_requirement(self): + """Return a ``Requirement`` that matches this distribution exactly""" + if isinstance(self.parsed_version, packaging.version.Version): + spec = "%s==%s" % (self.project_name, self.parsed_version) + else: + spec = "%s===%s" % (self.project_name, self.parsed_version) + + return Requirement.parse(spec) + + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group, name) + if ep is None: + raise ImportError("Entry point %r not found" % ((group, name),)) + return ep.load() + + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt'), self + ) + if group is not None: + return ep_map.get(group, {}) + return ep_map + + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + def insert_on(self, path, loc=None, replace=False): + """Ensure self.location is on path + + If replace=False (default): + - If location is already in path anywhere, do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent. + - Else: add to the end of path. + If replace=True: + - If location is already on path anywhere (not eggs) + or higher priority than its parent (eggs) + do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent, + removing any lower-priority entries. + - Else: add it to the front of path. + """ + + loc = loc or self.location + if not loc: + return + + nloc = _normalize_cached(loc) + bdir = os.path.dirname(nloc) + npath = [(p and _normalize_cached(p) or p) for p in path] + + for p, item in enumerate(npath): + if item == nloc: + if replace: + break + else: + # don't modify path (even removing duplicates) if + # found and not replace + return + elif item == bdir and self.precedence == EGG_DIST: + # if it's an .egg, give it precedence over its directory + # UNLESS it's already been added to sys.path and replace=False + if (not replace) and nloc in npath[p:]: + return + if path is sys.path: + self.check_version_conflict() + path.insert(p, loc) + npath.insert(p, nloc) + break + else: + if path is sys.path: + self.check_version_conflict() + if replace: + path.insert(0, loc) + else: + path.append(loc) + return + + # p is the spot where we found or inserted loc; now remove duplicates + while True: + try: + np = npath.index(nloc, p + 1) + except ValueError: + break + else: + del npath[np], path[np] + # ha! + p = np + + return + + def check_version_conflict(self): + if self.key == 'setuptools': + # ignore the inevitable setuptools self-conflicts :( + return + + nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) + loc = normalize_path(self.location) + for modname in self._get_metadata('top_level.txt'): + if (modname not in sys.modules or modname in nsp + or modname in _namespace_packages): + continue + if modname in ('pkg_resources', 'setuptools', 'site'): + continue + fn = getattr(sys.modules[modname], '__file__', None) + if fn and (normalize_path(fn).startswith(loc) or + fn.startswith(self.location)): + continue + issue_warning( + "Module %s was already imported from %s, but %s is being added" + " to sys.path" % (modname, fn, self.location), + ) + + def has_version(self): + try: + self.version + except ValueError: + issue_warning("Unbuilt egg for " + repr(self)) + return False + return True + + def clone(self, **kw): + """Copy this distribution, substituting in any changed keyword args""" + names = 'project_name version py_version platform location precedence' + for attr in names.split(): + kw.setdefault(attr, getattr(self, attr, None)) + kw.setdefault('metadata', self._provider) + return self.__class__(**kw) + + @property + def extras(self): + return [dep for dep in self._dep_map if dep] + + +class EggInfoDistribution(Distribution): + def _reload_version(self): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + take an extra step and try to get the version number from + the metadata file itself instead of the filename. + """ + md_version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if md_version: + self._version = md_version + return self + + +class DistInfoDistribution(Distribution): + """ + Wrap an actual or potential sys.path entry + w/metadata, .dist-info style. + """ + PKG_INFO = 'METADATA' + EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") + + @property + def _parsed_pkg_info(self): + """Parse and cache metadata""" + try: + return self._pkg_info + except AttributeError: + metadata = self.get_metadata(self.PKG_INFO) + self._pkg_info = email.parser.Parser().parsestr(metadata) + return self._pkg_info + + @property + def _dep_map(self): + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._compute_dependencies() + return self.__dep_map + + def _compute_dependencies(self): + """Recompute this distribution's dependencies.""" + dm = self.__dep_map = {None: []} + + reqs = [] + # Including any condition expressions + for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: + reqs.extend(parse_requirements(req)) + + def reqs_for_extra(extra): + for req in reqs: + if not req.marker or req.marker.evaluate({'extra': extra}): + yield req + + common = frozenset(reqs_for_extra(None)) + dm[None].extend(common) + + for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: + s_extra = safe_extra(extra.strip()) + dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) + + return dm + + +_distributionImpl = { + '.egg': Distribution, + '.egg-info': EggInfoDistribution, + '.dist-info': DistInfoDistribution, +} + + +def issue_warning(*args, **kw): + level = 1 + g = globals() + try: + # find the first stack frame that is *not* code in + # the pkg_resources module, to use for the warning + while sys._getframe(level).f_globals is g: + level += 1 + except ValueError: + pass + warnings.warn(stacklevel=level + 1, *args, **kw) + + +class RequirementParseError(ValueError): + def __str__(self): + return ' '.join(self.args) + + +def parse_requirements(strs): + """Yield ``Requirement`` objects for each specification in `strs` + + `strs` must be a string, or a (possibly-nested) iterable thereof. + """ + # create a steppable iterator, so we can handle \-continuations + lines = iter(yield_lines(strs)) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if ' #' in line: + line = line[:line.find(' #')] + # If there is a line continuation, drop it, and append the next line. + if line.endswith('\\'): + line = line[:-2].strip() + try: + line += next(lines) + except StopIteration: + return + yield Requirement(line) + + +class Requirement(packaging.requirements.Requirement): + def __init__(self, requirement_string): + """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" + try: + super(Requirement, self).__init__(requirement_string) + except packaging.requirements.InvalidRequirement as e: + raise RequirementParseError(str(e)) + self.unsafe_name = self.name + project_name = safe_name(self.name) + self.project_name, self.key = project_name, project_name.lower() + self.specs = [ + (spec.operator, spec.version) for spec in self.specifier] + self.extras = tuple(map(safe_extra, self.extras)) + self.hashCmp = ( + self.key, + self.specifier, + frozenset(self.extras), + str(self.marker) if self.marker else None, + ) + self.__hash = hash(self.hashCmp) + + def __eq__(self, other): + return ( + isinstance(other, Requirement) and + self.hashCmp == other.hashCmp + ) + + def __ne__(self, other): + return not self == other + + def __contains__(self, item): + if isinstance(item, Distribution): + if item.key != self.key: + return False + + item = item.version + + # Allow prereleases always in order to match the previous behavior of + # this method. In the future this should be smarter and follow PEP 440 + # more accurately. + return self.specifier.contains(item, prereleases=True) + + def __hash__(self): + return self.__hash + + def __repr__(self): + return "Requirement.parse(%r)" % str(self) + + @staticmethod + def parse(s): + req, = parse_requirements(s) + return req + + +def _always_object(classes): + """ + Ensure object appears in the mro even + for old-style classes. + """ + if object not in classes: + return classes + (object,) + return classes + + +def _find_adapter(registry, ob): + """Return an adapter factory for `ob` from `registry`""" + types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) + for t in types: + if t in registry: + return registry[t] + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + py31compat.makedirs(dirname, exist_ok=True) + + +def _bypass_ensure_directory(path): + """Sandbox-bypassing version of ensure_directory()""" + if not WRITE_SUPPORT: + raise IOError('"os.mkdir" not supported on this platform.') + dirname, filename = split(path) + if dirname and filename and not isdir(dirname): + _bypass_ensure_directory(dirname) + try: + mkdir(dirname, 0o755) + except FileExistsError: + pass + + +def split_sections(s): + """Split a string or iterable thereof into (section, content) pairs + + Each ``section`` is a stripped version of the section header ("[section]") + and each ``content`` is a list of stripped lines excluding blank lines and + comment-only lines. If there are any such lines before the first section + header, they're returned in a first ``section`` of ``None``. + """ + section = None + content = [] + for line in yield_lines(s): + if line.startswith("["): + if line.endswith("]"): + if section or content: + yield section, content + section = line[1:-1].strip() + content = [] + else: + raise ValueError("Invalid section heading", line) + else: + content.append(line) + + # wrap up last segment + yield section, content + + +def _mkstemp(*args, **kw): + old_open = os.open + try: + # temporarily bypass sandboxing + os.open = os_open + return tempfile.mkstemp(*args, **kw) + finally: + # and then put it back + os.open = old_open + + +# Silence the PEP440Warning by default, so that end users don't get hit by it +# randomly just because they use pkg_resources. We want to append the rule +# because we want earlier uses of filterwarnings to take precedence over this +# one. +warnings.filterwarnings("ignore", category=PEP440Warning, append=True) + + +# from jaraco.functools 1.3 +def _call_aside(f, *args, **kwargs): + f(*args, **kwargs) + return f + + +@_call_aside +def _initialize(g=globals()): + "Set up global resource manager (deliberately not state-saved)" + manager = ResourceManager() + g['_manager'] = manager + g.update( + (name, getattr(manager, name)) + for name in dir(manager) + if not name.startswith('_') + ) + + +@_call_aside +def _initialize_master_working_set(): + """ + Prepare the master working set and make the ``require()`` + API available. + + This function has explicit effects on the global state + of pkg_resources. It is intended to be invoked once at + the initialization of this module. + + Invocation by other packages is unsupported and done + at their own risk. + """ + working_set = WorkingSet._build_master() + _declare_state('object', working_set=working_set) + + require = working_set.require + iter_entry_points = working_set.iter_entry_points + add_activation_listener = working_set.subscribe + run_script = working_set.run_script + # backward compatibility + run_main = run_script + # Activate all distributions already on sys.path with replace=False and + # ensure that all distributions added to the working set in the future + # (e.g. by calling ``require()``) will get activated as well, + # with higher priority (replace=True). + tuple( + dist.activate(replace=False) + for dist in working_set + ) + add_activation_listener( + lambda dist: dist.activate(replace=True), + existing=False, + ) + working_set.entries = [] + # match order + list(map(working_set.add_entry, sys.path)) + globals().update(locals()) + +class PkgResourcesDeprecationWarning(Warning): + """ + Base class for warning about deprecations in ``pkg_resources`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__init__.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/appdirs.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/appdirs.py new file mode 100644 index 0000000..ae67001 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/appdirs.py @@ -0,0 +1,608 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2005-2010 ActiveState Software Inc. +# Copyright (c) 2013 Eddy Petrișor + +"""Utilities for determining application-specific dirs. + +See <http://github.com/ActiveState/appdirs> for details and usage. +""" +# Dev Notes: +# - MSDN on where to store app data files: +# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 +# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +__version_info__ = (1, 4, 3) +__version__ = '.'.join(map(str, __version_info__)) + + +import sys +import os + +PY3 = sys.version_info[0] == 3 + +if PY3: + unicode = str + +if sys.platform.startswith('java'): + import platform + os_name = platform.java_ver()[3][0] + if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. + system = 'win32' + elif os_name.startswith('Mac'): # "Mac OS X", etc. + system = 'darwin' + else: # "Linux", "SunOS", "FreeBSD", etc. + # Setting this to "linux2" is not ideal, but only Windows or Mac + # are actually checked for and the rest of the module expects + # *sys.platform* style strings. + system = 'linux2' +else: + system = sys.platform + + + +def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user data directories are: + Mac OS X: ~/Library/Application Support/<AppName> + Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> + Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> + Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> + Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/<AppName>". + """ + if system == "win32": + if appauthor is None: + appauthor = appname + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.normpath(_get_win_folder(const)) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('~/Library/Application Support/') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of data dirs should be + returned. By default, the first item from XDG_DATA_DIRS is + returned, or '/usr/local/share/<AppName>', + if XDG_DATA_DIRS is not set + + Typical site data directories are: + Mac OS X: /Library/Application Support/<AppName> + Unix: /usr/local/share/<AppName> or /usr/share/<AppName> + Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. + + For Unix, this is using the $XDG_DATA_DIRS[0] default. + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('/Library/Application Support') + if appname: + path = os.path.join(path, appname) + else: + # XDG default for $XDG_DATA_DIRS + # only first, if multipath is False + path = os.getenv('XDG_DATA_DIRS', + os.pathsep.join(['/usr/local/share', '/usr/share'])) + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + if appname and version: + path = os.path.join(path, version) + return path + + +def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user config directories are: + Mac OS X: same as user_data_dir + Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of config dirs should be + returned. By default, the first item from XDG_CONFIG_DIRS is + returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set + + Typical site config directories are: + Mac OS X: same as site_data_dir + Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in + $XDG_CONFIG_DIRS + Win *: same as site_data_dir + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + + For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system in ["win32", "darwin"]: + path = site_data_dir(appname, appauthor) + if appname and version: + path = os.path.join(path, version) + else: + # XDG default for $XDG_CONFIG_DIRS + # only first, if multipath is False + path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + +def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Cache" to the base app data dir for Windows. See + discussion below. + + Typical user cache directories are: + Mac OS X: ~/Library/Caches/<AppName> + Unix: ~/.cache/<AppName> (XDG default) + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go in + the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming + app data dir (the default returned by `user_data_dir` above). Apps typically + put cache data somewhere *under* the given dir here. Some examples: + ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache + ...\Acme\SuperApp\Cache\1.0 + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + This can be disabled with the `opinion=False` option. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + if opinion: + path = os.path.join(path, "Cache") + elif system == 'darwin': + path = os.path.expanduser('~/Library/Caches') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific state dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific log dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Logs" to the base app data dir for Windows, and "log" to the + base cache dir for Unix. See discussion below. + + Typical user log directories are: + Mac OS X: ~/Library/Logs/<AppName> + Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs + + On Windows the only suggestion in the MSDN docs is that local settings + go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in + examples of what some windows apps use for a logs dir.) + + OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` + value for Windows and appends "log" to the user cache dir for Unix. + This can be disabled with the `opinion=False` option. + """ + if system == "darwin": + path = os.path.join( + os.path.expanduser('~/Library/Logs'), + appname) + elif system == "win32": + path = user_data_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "Logs") + else: + path = user_cache_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "log") + if appname and version: + path = os.path.join(path, version) + return path + + +class AppDirs(object): + """Convenience wrapper for getting application dirs.""" + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): + self.appname = appname + self.appauthor = appauthor + self.version = version + self.roaming = roaming + self.multipath = multipath + + @property + def user_data_dir(self): + return user_data_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_data_dir(self): + return site_data_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_config_dir(self): + return user_config_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_config_dir(self): + return site_config_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_cache_dir(self): + return user_cache_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_state_dir(self): + return user_state_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_log_dir(self): + return user_log_dir(self.appname, self.appauthor, + version=self.version) + + +#---- internal support stuff + +def _get_win_folder_from_registry(csidl_name): + """This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + if PY3: + import winreg as _winreg + else: + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + dir, type = _winreg.QueryValueEx(key, shell_folder_name) + return dir + + +def _get_win_folder_with_pywin32(csidl_name): + from win32com.shell import shellcon, shell + dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) + # Try to make this a unicode path because SHGetFolderPath does + # not return unicode strings when there is unicode data in the + # path. + try: + dir = unicode(dir) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + try: + import win32api + dir = win32api.GetShortPathName(dir) + except ImportError: + pass + except UnicodeError: + pass + return dir + + +def _get_win_folder_with_ctypes(csidl_name): + import ctypes + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + +def _get_win_folder_with_jna(csidl_name): + import array + from com.sun import jna + from com.sun.jna.platform import win32 + + buf_size = win32.WinDef.MAX_PATH * 2 + buf = array.zeros('c', buf_size) + shell = win32.Shell32.INSTANCE + shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf = array.zeros('c', buf_size) + kernel = win32.Kernel32.INSTANCE + if kernel.GetShortPathName(dir, buf, buf_size): + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + return dir + +if system == "win32": + try: + import win32com.shell + _get_win_folder = _get_win_folder_with_pywin32 + except ImportError: + try: + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + try: + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +#---- self test code + +if __name__ == "__main__": + appname = "MyApp" + appauthor = "MyCompany" + + props = ("user_data_dir", + "user_config_dir", + "user_cache_dir", + "user_state_dir", + "user_log_dir", + "site_data_dir", + "site_config_dir") + + print("-- app dirs %s --" % __version__) + + print("-- app dirs (with optional 'version')") + dirs = AppDirs(appname, appauthor, version="1.0") + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'version')") + dirs = AppDirs(appname, appauthor) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'appauthor')") + dirs = AppDirs(appname) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (with disabled 'appauthor')") + dirs = AppDirs(appname, appauthor=False) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__about__.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__about__.py new file mode 100644 index 0000000..95d330e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "16.8" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__init__.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_compat.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_structures.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_structures.py new file mode 100644 index 0000000..ccc2786 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + +NegativeInfinity = NegativeInfinity() diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/markers.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/markers.py new file mode 100644 index 0000000..892e578 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from pkg_resources.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from pkg_resources.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from pkg_resources.extern.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "<Marker({0!r})>".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/requirements.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/requirements.py new file mode 100644 index 0000000..0c8c4a3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/requirements.py @@ -0,0 +1,127 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from pkg_resources.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from pkg_resources.extern.pyparsing import Literal as L # noqa +from pkg_resources.extern.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPERATOR = SEMICOLON +MARKER = MARKER_SEPERATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + "Invalid requirement, parse error at \"{0!r}\"".format( + requirement_string[e.loc:e.loc + 8])) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL given") + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "<Requirement({0!r})>".format(str(self)) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..7f5a76c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the begining. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(==|!=|<=|>=|<|>)) + \s* + (?P<version> + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(~=|==|!=|<=|>=|<|>|===)) + (?P<version> + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?<!==|!=|~=) # We have special cases for these + # operators so we want to make sure they + # don't match here. + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is techincally greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<SpecifierSet({0!r}{1})>".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/utils.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/utils.py new file mode 100644 index 0000000..942387c --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/utils.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/version.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/version.py new file mode 100644 index 0000000..83b5ee8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/packaging/version.py @@ -0,0 +1,393 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "<LegacyVersion({0})>".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P<epoch>[0-9]+)!)? # epoch + (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment + (?P<pre> # pre-release + [-_\.]? + (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) + [-_\.]? + (?P<pre_n>[0-9]+)? + )? + (?P<post> # post release + (?:-(?P<post_n1>[0-9]+)) + | + (?: + [-_\.]? + (?P<post_l>post|rev|r) + [-_\.]? + (?P<post_n2>[0-9]+)? + ) + )? + (?P<dev> # dev release + [-_\.]? + (?P<dev_l>dev) + [-_\.]? + (?P<dev_n>[0-9]+)? + )? + ) + (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version +""" + + +class Version(_BaseVersion): + + _regex = re.compile( + r"^\s*" + VERSION_PATTERN + r"\s*$", + re.VERBOSE | re.IGNORECASE, + ) + + def __init__(self, version): + # Validate the version and parse it into pieces + match = self._regex.search(version) + if not match: + raise InvalidVersion("Invalid version: '{0}'".format(version)) + + # Store the parsed out pieces of the version + self._version = _Version( + epoch=int(match.group("epoch")) if match.group("epoch") else 0, + release=tuple(int(i) for i in match.group("release").split(".")), + pre=_parse_letter_version( + match.group("pre_l"), + match.group("pre_n"), + ), + post=_parse_letter_version( + match.group("post_l"), + match.group("post_n1") or match.group("post_n2"), + ), + dev=_parse_letter_version( + match.group("dev_l"), + match.group("dev_n"), + ), + local=_parse_local_version(match.group("local")), + ) + + # Generate a key which will be used for sorting + self._key = _cmpkey( + self._version.epoch, + self._version.release, + self._version.pre, + self._version.post, + self._version.dev, + self._version.local, + ) + + def __repr__(self): + return "<Version({0})>".format(repr(str(self))) + + def __str__(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + # Pre-release + if self._version.pre is not None: + parts.append("".join(str(x) for x in self._version.pre)) + + # Post-release + if self._version.post is not None: + parts.append(".post{0}".format(self._version.post[1])) + + # Development release + if self._version.dev is not None: + parts.append(".dev{0}".format(self._version.dev[1])) + + # Local version segment + if self._version.local is not None: + parts.append( + "+{0}".format(".".join(str(x) for x in self._version.local)) + ) + + return "".join(parts) + + @property + def public(self): + return str(self).split("+", 1)[0] + + @property + def base_version(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + return "".join(parts) + + @property + def local(self): + version_string = str(self) + if "+" in version_string: + return version_string.split("+", 1)[1] + + @property + def is_prerelease(self): + return bool(self._version.dev or self._version.pre) + + @property + def is_postrelease(self): + return bool(self._version.post) + + +def _parse_letter_version(letter, number): + if letter: + # We consider there to be an implicit 0 in a pre-release if there is + # not a numeral associated with it. + if number is None: + number = 0 + + # We normalize any letters to their lower case form + letter = letter.lower() + + # We consider some words to be alternate spellings of other words and + # in those cases we want to normalize the spellings to our preferred + # spelling. + if letter == "alpha": + letter = "a" + elif letter == "beta": + letter = "b" + elif letter in ["c", "pre", "preview"]: + letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" + + return letter, int(number) + if not letter and number: + # We assume if we are given a number, but we are not given a letter + # then this is using the implicit post release syntax (e.g. 1.0-1) + letter = "post" + + return letter, int(number) + + +_local_version_seperators = re.compile(r"[\._-]") + + +def _parse_local_version(local): + """ + Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). + """ + if local is not None: + return tuple( + part.lower() if not part.isdigit() else int(part) + for part in _local_version_seperators.split(local) + ) + + +def _cmpkey(epoch, release, pre, post, dev, local): + # When we compare a release version, we want to compare it with all of the + # trailing zeros removed. So we'll use a reverse the list, drop all the now + # leading zeros until we come to something non zero, then take the rest + # re-reverse it back into the correct order and make it a tuple and use + # that for our sorting key. + release = tuple( + reversed(list( + itertools.dropwhile( + lambda x: x == 0, + reversed(release), + ) + )) + ) + + # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. + # We'll do this by abusing the pre segment, but we _only_ want to do this + # if there is not a pre or a post segment. If we have one of those then + # the normal sorting rules will handle this case correctly. + if pre is None and post is None and dev is not None: + pre = -Infinity + # Versions without a pre-release (except as noted above) should sort after + # those with one. + elif pre is None: + pre = Infinity + + # Versions without a post segment should sort before those with one. + if post is None: + post = -Infinity + + # Versions without a development segment should sort after those with one. + if dev is None: + dev = Infinity + + if local is None: + # Versions without a local segment should sort before those with one. + local = -Infinity + else: + # Versions with a local segment need that segment parsed to implement + # the sorting rules in PEP440. + # - Alpha numeric segments sort before numeric segments + # - Alpha numeric segments sort lexicographically + # - Numeric segments sort numerically + # - Shorter versions sort before longer versions when the prefixes + # match exactly + local = tuple( + (i, "") if isinstance(i, int) else (-Infinity, i) + for i in local + ) + + return epoch, release, pre, post, dev, local diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/pyparsing.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/pyparsing.py new file mode 100644 index 0000000..4aa30ee --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/pyparsing.py @@ -0,0 +1,5742 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2018 Paul T. McGuire +# +# 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. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes + - construct character word-group expressions using the L{Word} class + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes + - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones + - associate names with your parsed results using L{ParserElement.setResultsName} + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} + - find more useful common expressions in the L{pyparsing_common} namespace class +""" + +__version__ = "2.2.1" +__versionTime__ = "18 Sep 2018 00:49 UTC" +__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + # Python 3 + from collections.abc import Iterable + from collections.abc import MutableMapping +except ImportError: + # Python 2.7 + from collections import Iterable + from collections import MutableMapping + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "</", resTag, ">" ] + + out += [ nl, indent, "</", selfTag, ">" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) + +def lineno(loc,strg): + """Returns current line number within a string, counting newlines as line separators. + The first line is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [frame_summary[:2]] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [frame_summary[:2]] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "<parse action>" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, <TAB> and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}<parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. + + See examples in L{I{copy}<copy>}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or preloc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}<parseWithTabs>}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}<parseString>} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of <TAB>s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{<TAB>} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): + throwException = True + + if throwException: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except Exception: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "<SPC>", + "\t": "<TAB>", + "\n": "<LF>", + "\r": "<CR>", + "\f": "<FF>", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc<len(instring): + if instring[loc] == "\n": + return loc+1, "\n" + else: + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class StringStart(_PositionToken): + """ + Matches if current position is at the beginning of the parse string + """ + def __init__( self ): + super(StringStart,self).__init__() + self.errmsg = "Expected start of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc != 0: + # see if entire string up to here is just whitespace and ignoreables + if loc != self.preParse( instring, 0 ): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class StringEnd(_PositionToken): + """ + Matches if current position is at the end of the parse string + """ + def __init__( self ): + super(StringEnd,self).__init__() + self.errmsg = "Expected end of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc < len(instring): + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + elif loc > len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + +class ParseExpression(ParserElement): + """ + Abstract subclass of ParserElement, for combining and post-processing parsed tokens. + """ + def __init__( self, exprs, savelist = False ): + super(ParseExpression,self).__init__(savelist) + if isinstance( exprs, _generatorType ): + exprs = list(exprs) + + if isinstance( exprs, basestring ): + self.exprs = [ ParserElement._literalStringClass( exprs ) ] + elif isinstance( exprs, Iterable ): + exprs = list(exprs) + # if sequence of strings provided, wrap with Literal + if all(isinstance(expr, basestring) for expr in exprs): + exprs = map(ParserElement._literalStringClass, exprs) + self.exprs = list(exprs) + else: + try: + self.exprs = list( exprs ) + except TypeError: + self.exprs = [ exprs ] + self.callPreparse = False + + def __getitem__( self, i ): + return self.exprs[i] + + def append( self, other ): + self.exprs.append( other ) + self.strRepr = None + return self + + def leaveWhitespace( self ): + """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on + all contained expressions.""" + self.skipWhitespace = False + self.exprs = [ e.copy() for e in self.exprs ] + for e in self.exprs: + e.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + else: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + return self + + def __str__( self ): + try: + return super(ParseExpression,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) + return self.strRepr + + def streamline( self ): + super(ParseExpression,self).streamline() + + for e in self.exprs: + e.streamline() + + # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) + # but only if there are no parse actions or resultsNames on the nested And's + # (likewise for Or's and MatchFirst's) + if ( len(self.exprs) == 2 ): + other = self.exprs[0] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = other.exprs[:] + [ self.exprs[1] ] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + other = self.exprs[-1] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = self.exprs[:-1] + other.exprs[:] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + self.errmsg = "Expected " + _ustr(self) + + return self + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ParseExpression,self).setResultsName(name,listAllMatches) + return ret + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + for e in self.exprs: + e.validate(tmp) + self.checkRecursion( [] ) + + def copy(self): + ret = super(ParseExpression,self).copy() + ret.exprs = [e.copy() for e in self.exprs] + return ret + +class And(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found in the given order. + Expressions may be separated by whitespace. + May be constructed using the C{'+'} operator. + May also be constructed using the C{'-'} operator, which will suppress backtracking. + + Example:: + integer = Word(nums) + name_expr = OneOrMore(Word(alphas)) + + expr = And([integer("id"),name_expr("name"),integer("age")]) + # more easily written as: + expr = integer("id") + name_expr("name") + integer("age") + """ + + class _ErrorStop(Empty): + def __init__(self, *args, **kwargs): + super(And._ErrorStop,self).__init__(*args, **kwargs) + self.name = '-' + self.leaveWhitespace() + + def __init__( self, exprs, savelist = True ): + super(And,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.setWhitespaceChars( self.exprs[0].whiteChars ) + self.skipWhitespace = self.exprs[0].skipWhitespace + self.callPreparse = True + + def parseImpl( self, instring, loc, doActions=True ): + # pass False as last arg to _parse for first element, since we already + # pre-parsed the string as part of our And pre-parsing + loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False + for e in self.exprs[1:]: + if isinstance(e, And._ErrorStop): + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseSyntaxException: + raise + except ParseBaseException as pe: + pe.__traceback__ = None + raise ParseSyntaxException._from_exception(pe) + except IndexError: + raise ParseSyntaxException(instring, len(instring), self.errmsg, self) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) + if exprtokens or exprtokens.haskeys(): + resultlist += exprtokens + return loc, resultlist + + def __iadd__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #And( [ self, other ] ) + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + if not e.mayReturnEmpty: + break + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + +class Or(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the expression that matches the longest string will be used. + May be constructed using the C{'^'} operator. + + Example:: + # construct Or using '^' operator + + number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) + prints:: + [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(Or,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + matches = [] + for e in self.exprs: + try: + loc2 = e.tryParse( instring, loc ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens)))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <<leaving remove_duplicate_chars (ret: 'dfjkls') + ['dfjkls'] + """ + f = _trim_arity(f) + def z(*paArgs): + thisFunc = f.__name__ + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) + raise + sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) + return ret + try: + z.__name__ = f.__name__ + except AttributeError: + pass + return z + +# +# global helpers +# +def delimitedList( expr, delim=",", combine=False ): + """ + Helper to define a delimited list of expressions - the delimiter defaults to ','. + By default, the list elements and delimiters can have intervening whitespace, and + comments, but this can be overridden by passing C{combine=True} in the constructor. + If C{combine} is set to C{True}, the matching tokens are returned as a single token + string, with the delimiters included; otherwise, the matching tokens are returned + as a list of tokens, with the delimiters suppressed. + + Example:: + delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test <b> bold <i>text</i> </b> normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + ['<b> bold <i>text</i> </b>'] + ['<i>text</i>'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{<TAB>} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString<ParserElement.transformString>}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("</") + tagStr + ">") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the <A> tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{<TD>} or C{<DIV>}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' + <div> + Some text + <div type="grid">1 4 0 1 0</div> + <div type="graph">1,3 2,3 1,1</div> + <div>this has no type</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' + <div> + Some text + <div class="grid">1 4 0 1 0</div> + <div class="graph">1,3 2,3 1,1</div> + <div>this <div> has no class</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") +"Comment of the form C{<!-- ... -->}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) + - common L{programming identifiers<identifier>} + - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) + - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} + - L{UUID<uuid>} + - L{comma-separated list<comma_separated_list>} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/_vendor/six.py b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/_vendor/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# 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. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/venv/lib/python3.7/site-packages/pkg_resources/extern/__init__.py b/venv/lib/python3.7/site-packages/pkg_resources/extern/__init__.py new file mode 100644 index 0000000..c1eb9e9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/extern/__init__.py @@ -0,0 +1,73 @@ +import sys + + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from root_name. + """ + + def __init__(self, root_name, vendored_names=(), vendor_pkg=None): + self.root_name = root_name + self.vendored_names = set(vendored_names) + self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') + + @property + def search_path(self): + """ + Search first the vendor package then as a natural package. + """ + yield self.vendor_pkg + '.' + yield '' + + def find_module(self, fullname, path=None): + """ + Return self when fullname starts with root_name and the + target module is one vendored through this importer. + """ + root, base, target = fullname.partition(self.root_name + '.') + if root: + return + if not any(map(target.startswith, self.vendored_names)): + return + return self + + def load_module(self, fullname): + """ + Iterate over the search path to locate and load fullname. + """ + root, base, target = fullname.partition(self.root_name + '.') + for prefix in self.search_path: + try: + extant = prefix + target + __import__(extant) + mod = sys.modules[extant] + sys.modules[fullname] = mod + # mysterious hack: + # Remove the reference to the extant package/module + # on later Python versions to cause relative imports + # in the vendor package to resolve the same modules + # as those going through this importer. + if prefix and sys.version_info > (3, 3): + del sys.modules[extant] + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + def install(self): + """ + Install this importer into sys.meta_path if not already present. + """ + if self not in sys.meta_path: + sys.meta_path.append(self) + + +names = 'packaging', 'pyparsing', 'six', 'appdirs' +VendorImporter(__name__, names).install() diff --git a/venv/lib/python3.7/site-packages/pkg_resources/py31compat.py b/venv/lib/python3.7/site-packages/pkg_resources/py31compat.py new file mode 100644 index 0000000..a381c42 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pkg_resources/py31compat.py @@ -0,0 +1,23 @@ +import os +import errno +import sys + +from .extern import six + + +def _makedirs_31(path, exist_ok=False): + try: + os.makedirs(path) + except OSError as exc: + if not exist_ok or exc.errno != errno.EEXIST: + raise + + +# rely on compatibility behavior until mode considerations +# and exists_ok considerations are disentangled. +# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 +needs_makedirs = ( + six.PY2 or + (3, 4) <= sys.version_info < (3, 4, 1) +) +makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1-py3.7-nspkg.pth b/venv/lib/python3.7/site-packages/protobuf-3.6.1-py3.7-nspkg.pth new file mode 100644 index 0000000..baef7a0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1-py3.7-nspkg.pth @@ -0,0 +1 @@ +import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('google', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('google', [os.path.dirname(p)])));m = m or sys.modules.setdefault('google', types.ModuleType('google'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/INSTALLER b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/METADATA b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/METADATA new file mode 100644 index 0000000..b843f7b --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/METADATA @@ -0,0 +1,22 @@ +Metadata-Version: 2.1 +Name: protobuf +Version: 3.6.1 +Summary: Protocol Buffers +Home-page: https://developers.google.com/protocol-buffers/ +Maintainer: protobuf@googlegroups.com +Maintainer-email: protobuf@googlegroups.com +License: 3-Clause BSD License +Download-URL: https://github.com/google/protobuf/releases +Platform: UNKNOWN +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Requires-Dist: six (>=1.9) +Requires-Dist: setuptools + +Protocol Buffers are Google's data interchange format + + diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/RECORD b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/RECORD new file mode 100644 index 0000000..ce6c6f0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/RECORD @@ -0,0 +1,199 @@ +google/protobuf/__init__.py,sha256=IXZY1uQZo6uUYULttDPrk1xt42Nn7TeEThamsEf7drA,1890 +google/protobuf/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/__pycache__/any_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/any_test_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/api_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor_database.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor_pool.cpython-37.pyc,, +google/protobuf/__pycache__/duration_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/empty_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/field_mask_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/json_format.cpython-37.pyc,, +google/protobuf/__pycache__/map_proto2_unittest_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/map_unittest_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/message.cpython-37.pyc,, +google/protobuf/__pycache__/message_factory.cpython-37.pyc,, +google/protobuf/__pycache__/proto_builder.cpython-37.pyc,, +google/protobuf/__pycache__/reflection.cpython-37.pyc,, +google/protobuf/__pycache__/service.cpython-37.pyc,, +google/protobuf/__pycache__/service_reflection.cpython-37.pyc,, +google/protobuf/__pycache__/source_context_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/struct_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/symbol_database.cpython-37.pyc,, +google/protobuf/__pycache__/test_messages_proto2_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/test_messages_proto3_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/text_encoding.cpython-37.pyc,, +google/protobuf/__pycache__/text_format.cpython-37.pyc,, +google/protobuf/__pycache__/timestamp_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/type_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_arena_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_custom_options_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_import_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_import_public_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_mset_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_mset_wire_format_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_no_arena_import_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_no_arena_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_no_generic_services_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_proto3_arena_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/wrappers_pb2.cpython-37.pyc,, +google/protobuf/any_pb2.py,sha256=jX1N3BZPQ1ljpWBj-_H8pu1U3ED8XsGSj5uWWfR4uAM,2616 +google/protobuf/any_test_pb2.py,sha256=Je2Pnm0M7pBWkvbh_s5j3MdfZ4a55-pru2O5U5fxmWo,3233 +google/protobuf/api_pb2.py,sha256=7mhGaMy5mJ6PsTmBj51s4-K4dZ9xk4SJo5nbmcOClIw,11001 +google/protobuf/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +google/protobuf/compiler/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/compiler/__pycache__/plugin_pb2.cpython-37.pyc,, +google/protobuf/compiler/plugin_pb2.py,sha256=dRdhy2Y_SOYQG4PIQMt0rfEooBFAk8HF-phU6_-QwB8,10823 +google/protobuf/descriptor.py,sha256=AZCOUjTKshZaUUOfrgx-w-9okNe2fnHgJH8DKe-0SAI,41646 +google/protobuf/descriptor_database.py,sha256=70o7KvrTdzAQyVWmRTGXFHuXNvKFhp4zAKfNLDhwgb4,6295 +google/protobuf/descriptor_pb2.py,sha256=khZQjsmMwCYXKI2RARk5P15dbiDKkP1HZ8isUMD1tJU,92218 +google/protobuf/descriptor_pool.py,sha256=fBkm1lQWBxQ5QM40MGTK0bAR_KfC1GLg5VVWoqcRNZc,37914 +google/protobuf/duration_pb2.py,sha256=rAlKCSzzY0wBt6WMxu8Z2LQqBfzqIpjfWtJwTEr_U2c,2710 +google/protobuf/empty_pb2.py,sha256=dKScylLS-ViOg3Dt-rRzLFaVsJKEePOZBZ04m18J54o,1859 +google/protobuf/field_mask_pb2.py,sha256=e2VW6az0kh9mfjG-vkrj48ecr2r-q3jV_EJy5cDkIW8,2341 +google/protobuf/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +google/protobuf/internal/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/internal/__pycache__/_parameterized.cpython-37.pyc,, +google/protobuf/internal/__pycache__/any_test_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/api_implementation.cpython-37.pyc,, +google/protobuf/internal/__pycache__/containers.cpython-37.pyc,, +google/protobuf/internal/__pycache__/decoder.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_database_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_pool_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_pool_test1_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_pool_test2_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/encoder.cpython-37.pyc,, +google/protobuf/internal/__pycache__/enum_type_wrapper.cpython-37.pyc,, +google/protobuf/internal/__pycache__/factory_test1_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/factory_test2_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/file_options_test_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/generator_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/json_format_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_factory_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_listener.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_set_extensions_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/missing_enum_values_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/more_extensions_dynamic_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/more_extensions_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/more_messages_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/no_package_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/packed_field_test_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/proto_builder_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/python_message.cpython-37.pyc,, +google/protobuf/internal/__pycache__/reflection_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/service_reflection_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/symbol_database_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/test_bad_identifiers_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/test_util.cpython-37.pyc,, +google/protobuf/internal/__pycache__/testing_refleaks.cpython-37.pyc,, +google/protobuf/internal/__pycache__/text_encoding_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/text_format_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/type_checkers.cpython-37.pyc,, +google/protobuf/internal/__pycache__/unknown_fields_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/well_known_types.cpython-37.pyc,, +google/protobuf/internal/__pycache__/well_known_types_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/wire_format.cpython-37.pyc,, +google/protobuf/internal/__pycache__/wire_format_test.cpython-37.pyc,, +google/protobuf/internal/_api_implementation.cpython-37m-darwin.so,sha256=fg6yL2RKmaOeNMOhb4MSu4WpS7hELilpSUl3mLEgrtg,25576 +google/protobuf/internal/_parameterized.py,sha256=-U4z1D7oWqbANirvgTKo7USBGisW9_qHergUcaqCer0,15360 +google/protobuf/internal/any_test_pb2.py,sha256=zlLAkahTnDZ1EMzfLojTHvO6IvpbrfWHGIG-1YzCdE8,7055 +google/protobuf/internal/api_implementation.py,sha256=LnP9LiGKTRAVkB7_3qS7Xlqp-nOp4LJROwIdurajGv0,7237 +google/protobuf/internal/containers.py,sha256=VXPu39UMCbc_Z9gKwO3MnePheTvuTzJTlP2DhAHRr1A,21000 +google/protobuf/internal/decoder.py,sha256=W60_blcES_wFPb94d1O8uJzoGwjwJkswh8L79kFrRKs,31289 +google/protobuf/internal/descriptor_database_test.py,sha256=DTo554U0s1pIyfAmEUQmMgPBZUPGkYjkuIzfo9cuoPY,5511 +google/protobuf/internal/descriptor_pool_test.py,sha256=-LLG3Sb5FZbfO00ymr-R5Gmin6HWmTn24CW4g1lswmY,46062 +google/protobuf/internal/descriptor_pool_test1_pb2.py,sha256=IKpOjuT-PfIjs-R5y_SGX3nFKUtFIyBXNq4cNPWLp7Y,21326 +google/protobuf/internal/descriptor_pool_test2_pb2.py,sha256=mLSGMQ7LHgfISFnNFrDC9W2E_8N18E81q7B2v03u-Y8,12614 +google/protobuf/internal/descriptor_test.py,sha256=79pA433a-0UwKh-LNeqzPS-9rR1kaUwmic1QgxSu5IM,43095 +google/protobuf/internal/encoder.py,sha256=e4NkXj540EEdk0fUsTcYKiPB2aofGnW_eYiHJnEmWC0,28587 +google/protobuf/internal/enum_type_wrapper.py,sha256=S7yGMF9PamOpMkiur5edHi25zjuIsRluavCvNVlh4hQ,3554 +google/protobuf/internal/factory_test1_pb2.py,sha256=sf_5gHL-n3KG3h1qLpxEBMXkWA2jOIXKax3YnvndV7c,7954 +google/protobuf/internal/factory_test2_pb2.py,sha256=e5HNqsI7t2AjM3kzvqZlUFw4IReskb1qULVBWfdzMGI,25201 +google/protobuf/internal/file_options_test_pb2.py,sha256=nNLdJKh-r-JiNSunNuIdzz7bn1G5nRBJtkt0aNf0np8,3072 +google/protobuf/internal/generator_test.py,sha256=SDUXJ0CSS59dILr-WyR6tbn5B3VhPylG1Js1Wbq2h7k,14779 +google/protobuf/internal/import_test_package/__init__.py,sha256=Dct4MqAtKH6cguzoEmmhey5QUBZcpwBP8o1KwS0Z8H4,1768 +google/protobuf/internal/import_test_package/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/internal/import_test_package/__pycache__/inner_pb2.cpython-37.pyc,, +google/protobuf/internal/import_test_package/__pycache__/outer_pb2.cpython-37.pyc,, +google/protobuf/internal/import_test_package/inner_pb2.py,sha256=TB9Cv_qsg_4T9jSsouaUGJietNC9SflWwt_XBRdsQys,2204 +google/protobuf/internal/import_test_package/outer_pb2.py,sha256=Q1c7YtNWYDSgVI9YhDbsMFRooJaeuJUm8SyIc3D7ek8,2694 +google/protobuf/internal/json_format_test.py,sha256=FK7lUnGWRjAzv8YXtnQPOB2lZjvGplTW1GR2uiLbdro,42030 +google/protobuf/internal/message_factory_test.py,sha256=5j1C0UaTCtHA3djoMTEk8qHa9dIcgpqLomuxRoKZ2gI,9670 +google/protobuf/internal/message_listener.py,sha256=Qwc5gkifAvWzhm3b0v-nXJkozNTgL-L92XAslngFaow,3367 +google/protobuf/internal/message_set_extensions_pb2.py,sha256=arQVEw130wj6ZHdkhnCoQ9O1I_8Ptnt5N36gNaSLbbk,8404 +google/protobuf/internal/message_test.py,sha256=NEXJ6lcSjbjPaulC-csqECSsTCLvdnSLZR2avD3q6DI,88415 +google/protobuf/internal/missing_enum_values_pb2.py,sha256=zzBQK26qmctAqXlQykunC_QZoBd2Q_KDnUrk0eM9A6o,9356 +google/protobuf/internal/more_extensions_dynamic_pb2.py,sha256=cGONkEkOTkuj1ise6S1tvBke3UQd_Z56n06rXAP94kk,5005 +google/protobuf/internal/more_extensions_pb2.py,sha256=3TWgANFY_blVY6bXAbzdl52tkUaVMxqCOYy_lk4kpxw,7386 +google/protobuf/internal/more_messages_pb2.py,sha256=44oWSpPB2X-cEA4TbGSKfTLZ8YbzVOa5KSln2mEfVGs,4312 +google/protobuf/internal/no_package_pb2.py,sha256=lbExkdz53McjKrJsjX_b61Djy2TZkyA3dQL9NfeDbng,3026 +google/protobuf/internal/packed_field_test_pb2.py,sha256=uyVVoIBsycPeqr9N8yb7UMEoYUmGRYDy4M6hDwuvoS4,17924 +google/protobuf/internal/proto_builder_test.py,sha256=P7Q0_UHmkqSXi2QP-6zC_gMN88mF6efI2UYnM2iylCo,3770 +google/protobuf/internal/python_message.py,sha256=j1v-WeDnuZOTiiAZ3FVm8tP8TbhI_I_NlxoXGwbO2H4,57876 +google/protobuf/internal/reflection_test.py,sha256=yDHE2T8JEY34cyDL-YiNfgKubenpfud1mayEf_uY_Vo,128264 +google/protobuf/internal/service_reflection_test.py,sha256=jYtRs4vKa2FzQzgwj8azRDHExaYK6DlPO780d0ov858,5412 +google/protobuf/internal/symbol_database_test.py,sha256=fyzmO4nMO-ovNUn0IHewDc_2TSTpE1gBDENWF727wkM,5650 +google/protobuf/internal/test_bad_identifiers_pb2.py,sha256=O02edr6ZvCnDWr5YsfFQOPOks3B4W0MxYcIc9XhklcI,5917 +google/protobuf/internal/test_util.py,sha256=fXhJJpv8L-ta1-wSdiRK_QuixyRsXwoATsIqxxk_4nA,33922 +google/protobuf/internal/testing_refleaks.py,sha256=1DOwsGhNPRtvlwNgRhMEzvrmdO-Rqv91oUuoua7V90M,4508 +google/protobuf/internal/text_encoding_test.py,sha256=56hukUTsINXsld66zDjHqxg9-P2cZb3_sOdSAli1SSI,2903 +google/protobuf/internal/text_format_test.py,sha256=x02pSbzkbhDpANT2b3HZLDr7Q9g_CxPs6WqtL5kAygM,68043 +google/protobuf/internal/type_checkers.py,sha256=KWStklpr_AcjqgtIhbCIzEX6-xpYmu7zbaB4F_IuFD0,14226 +google/protobuf/internal/unknown_fields_test.py,sha256=t9x7Mjz2eU8Qg0zqrbnySnNMCyIoqmOQK8AIYxsbQJc,13868 +google/protobuf/internal/well_known_types.py,sha256=Q1_1EsNWx_BiWdVti4D8dDKtLGLwSJl_Qybc8SPyI8g,28460 +google/protobuf/internal/well_known_types_test.py,sha256=yLfJhTj-23clUUBUMNa2W7gTa-srf87CKHi7Nx32_dY,36016 +google/protobuf/internal/wire_format.py,sha256=7Wz8gV7QOvoTzLMWrwlWSg7hIJ_T8Pm1w8_WLhpieVw,8444 +google/protobuf/internal/wire_format_test.py,sha256=UNUam8dc8Ex9V2EELOCd0tKIY2yLGBTDtV8y75LGyz0,10930 +google/protobuf/json_format.py,sha256=MkKzgAuF-ilClod4RVX9mxDe0A3hfOHJuH3J4H7I5XA,29835 +google/protobuf/map_proto2_unittest_pb2.py,sha256=as6RUX1ziZpHDvOhXxSo_bYfdIuBh-nm8cJgmpt7wq8,53646 +google/protobuf/map_unittest_pb2.py,sha256=UENFUlJb0miJAjhunttGDS7_C8ozEmMb8Bb7opiFZSQ,121531 +google/protobuf/message.py,sha256=chs-OnslNPDyHnhPinhOMHnYj6N1170o28n8A2yfDfE,11454 +google/protobuf/message_factory.py,sha256=EzW6mlLteZ7ou1S6aiEbPBrqun3omY38-pjvfNHTn_c,6291 +google/protobuf/proto_builder.py,sha256=dN2e2IYXvfxcG-9qClb-EUgLLASSL0n-ZSBuFr8CM9M,5208 +google/protobuf/pyext/__init__.py,sha256=8SXBh8YGxPXGDmFtR_n90wt5xWvc5CEp_L5Pn687VaU,150 +google/protobuf/pyext/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/pyext/__pycache__/cpp_message.cpython-37.pyc,, +google/protobuf/pyext/__pycache__/python_pb2.cpython-37.pyc,, +google/protobuf/pyext/_message.cpython-37m-darwin.so,sha256=zu-o4rfW5MqdcOuXkPBDjJ004SbtNNiiwmcqAJu140c,3170208 +google/protobuf/pyext/cpp_message.py,sha256=D0-bxtjf1Ri8b0GubL5xgkkEB_z_mIf847yrRvVqDBU,2851 +google/protobuf/pyext/python_pb2.py,sha256=10npuLYyZfV_XDXPPU9-IRN8_yzVgG-VMzEfKCgdVKw,9753 +google/protobuf/reflection.py,sha256=xq_d3T1T6hNdbeVPdMgR1xKynewj_02uPa4MlictXBo,4568 +google/protobuf/service.py,sha256=wRQxBH9JJRY3h8WPR5V3OTW-BWuX0YZlBLmwnjCL41w,9144 +google/protobuf/service_reflection.py,sha256=9EgQ3T-Haae0i8RQkVqqfpchNT9VxdDnBL46DGyKW-Y,11023 +google/protobuf/source_context_pb2.py,sha256=bJkN-fRy8fqWPQCYdx8DNumkjBLFxgBWbT1YT-oJCsY,2456 +google/protobuf/struct_pb2.py,sha256=TAOOgrEz8gl30SXdYNbpHNrkJd7EAHWys09wG321WGk,10807 +google/protobuf/symbol_database.py,sha256=BYDAo0nWWfVTTUmeYwi4R8AR0VQEE5uwAvDGGtOLh3A,6429 +google/protobuf/test_messages_proto2_pb2.py,sha256=hM2VaXwQi3I3VXGYuYMi_77DVnoHeTbEsWsARiG00Q4,104956 +google/protobuf/test_messages_proto3_pb2.py,sha256=Vxdjj7Gym9Vc9eJU6XUNSDpwlp0cyWB9qwDNEqmPn0s,115424 +google/protobuf/text_encoding.py,sha256=jmPTJzMNTwNC2p97swdNfH3qGnSIop-zxWREO9cR6X0,4617 +google/protobuf/text_format.py,sha256=9O5re1366Fo68AHxW2DNgaZNjRRWYtoMKQJw0sce8zI,51634 +google/protobuf/timestamp_pb2.py,sha256=iO97wijlMxP2AYj-HxwjL8ugVlgkbO7wHX6SDqt50ek,2730 +google/protobuf/type_pb2.py,sha256=al7co5w3ENZ8snO8PUjqio9fgpEpn7eJ8-v-GGW4qCs,22405 +google/protobuf/unittest_arena_pb2.py,sha256=ZPZzTa1KEqNiLXMU6XYOHTnvjvW6SEc0vr-Zo1KDoBs,4459 +google/protobuf/unittest_custom_options_pb2.py,sha256=aUHqihyca3aPZa9XitRjVNCG6Ku7CE99peGU1nP2Z-s,84726 +google/protobuf/unittest_import_pb2.py,sha256=KqQmCPgRjQFsgkkFLXTWXFJwwr3GT6TDmx-xa4AFENQ,4608 +google/protobuf/unittest_import_public_pb2.py,sha256=cJH7slGJMMoF114TBT_Xhc0I91gK3zjmvSsL74RtJVk,2261 +google/protobuf/unittest_mset_pb2.py,sha256=JpWHQ_jK4PFckn2NCp7iGBZMFxzYU29sVtWqy3nMF2s,9999 +google/protobuf/unittest_mset_wire_format_pb2.py,sha256=TR6QhsVlUPxEVVTf3dwzgPCgzWYj6NL9kKMN2fKMwCw,3619 +google/protobuf/unittest_no_arena_import_pb2.py,sha256=dMklN5NC1XjhKC2BeXPJqpbl_au_gRpy87kDYsX_JAw,2239 +google/protobuf/unittest_no_arena_pb2.py,sha256=mxWKvqnFqkAyEd5ZvWAoGeJq19BJtr3WQLEv1Q2fDXw,51593 +google/protobuf/unittest_no_generic_services_pb2.py,sha256=2OROGsxYLF2LARGgAkplHZ0iDUZsrdFwoxqVZTJptBE,4306 +google/protobuf/unittest_pb2.py,sha256=M2M32bPdb1iupAX3iI6IJLYWJRNmaHlqB3Cpqkx6CCU,352539 +google/protobuf/unittest_proto3_arena_pb2.py,sha256=Ncnw8Fo9W41xdiixLjri0ILhCacH4ghe90Z-58T_ALQ,54739 +google/protobuf/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +google/protobuf/util/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/util/__pycache__/json_format_proto3_pb2.cpython-37.pyc,, +google/protobuf/util/json_format_proto3_pb2.py,sha256=3JpbT2bhs4H0Ytkw9iryFYH1N0VOhllvhwYkxz7PbbM,81998 +google/protobuf/wrappers_pb2.py,sha256=ydUcYPdruald1EgKMqa5A6mF-4s9XS-mDl-DQGkMngs,11626 +protobuf-3.6.1-py3.7-nspkg.pth,sha256=xH5gTxc4UipYP3qrbP-4CCHNGBV97eBR4QqhheCvBl4,539 +protobuf-3.6.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +protobuf-3.6.1.dist-info/METADATA,sha256=hRV6PbqoILWnWiRTCgIRhOhG8yQ6kAbW0zI-_Kd7HRM,724 +protobuf-3.6.1.dist-info/RECORD,, +protobuf-3.6.1.dist-info/WHEEL,sha256=nszrZlPic-Dk3DQ9lDsh3XIa5qiFPLReHnxHUr4rHiI,249 +protobuf-3.6.1.dist-info/namespace_packages.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7 +protobuf-3.6.1.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7 diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/WHEEL b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/WHEEL new file mode 100644 index 0000000..05e4d69 --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/WHEEL @@ -0,0 +1,9 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.2) +Root-Is-Purelib: false +Tag: cp37-cp37m-macosx_10_6_intel +Tag: cp37-cp37m-macosx_10_9_intel +Tag: cp37-cp37m-macosx_10_9_x86_64 +Tag: cp37-cp37m-macosx_10_10_intel +Tag: cp37-cp37m-macosx_10_10_x86_64 + diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt new file mode 100644 index 0000000..cb42911 --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt @@ -0,0 +1 @@ +google diff --git a/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/top_level.txt b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/top_level.txt new file mode 100644 index 0000000..cb42911 --- /dev/null +++ b/venv/lib/python3.7/site-packages/protobuf-3.6.1.dist-info/top_level.txt @@ -0,0 +1 @@ +google diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/INSTALLER b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/LICENSE b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/LICENSE new file mode 100644 index 0000000..6e0693b --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2016 Jason R Coombs <jaraco@jaraco.com> + +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/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/METADATA b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/METADATA new file mode 100644 index 0000000..5a5fde1 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/METADATA @@ -0,0 +1,73 @@ +Metadata-Version: 2.1 +Name: setuptools +Version: 40.6.2 +Summary: Easily download, build, install, upgrade, and uninstall Python packages +Home-page: https://github.com/pypa/setuptools +Author: Python Packaging Authority +Author-email: distutils-sig@python.org +License: UNKNOWN +Project-URL: Documentation, https://setuptools.readthedocs.io/ +Keywords: CPAN PyPI distutils eggs package management +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +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 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Archiving :: Packaging +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* +Description-Content-Type: text/x-rst; charset=UTF-8 +Provides-Extra: certs +Requires-Dist: certifi (==2016.9.26); extra == 'certs' +Provides-Extra: ssl +Requires-Dist: wincertstore (==0.2); (sys_platform=='win32') and extra == 'ssl' + +.. image:: https://img.shields.io/pypi/v/setuptools.svg + :target: https://pypi.org/project/setuptools + +.. image:: https://readthedocs.org/projects/setuptools/badge/?version=latest + :target: https://setuptools.readthedocs.io + +.. image:: https://img.shields.io/travis/pypa/setuptools/master.svg?label=Linux%20build%20%40%20Travis%20CI + :target: https://travis-ci.org/pypa/setuptools + +.. image:: https://img.shields.io/appveyor/ci/pypa/setuptools/master.svg?label=Windows%20build%20%40%20Appveyor + :target: https://ci.appveyor.com/project/pypa/setuptools/branch/master + +.. image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg + :target: https://codecov.io/gh/pypa/setuptools + +.. image:: https://img.shields.io/pypi/pyversions/setuptools.svg + +.. image:: https://tidelift.com/badges/github/pypa/setuptools + :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme + +See the `Installation Instructions +<https://packaging.python.org/installing/>`_ in the Python Packaging +User's Guide for instructions on installing, upgrading, and uninstalling +Setuptools. + +Questions and comments should be directed to the `distutils-sig +mailing list <http://mail.python.org/pipermail/distutils-sig/>`_. +Bug reports and especially tested patches may be +submitted directly to the `bug tracker +<https://github.com/pypa/setuptools/issues>`_. + + +Code of Conduct +--------------- + +Everyone interacting in the setuptools project's codebases, issue trackers, +chat rooms, and mailing lists is expected to follow the +`PyPA Code of Conduct <https://www.pypa.io/en/latest/code-of-conduct/>`_. + + diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/RECORD b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/RECORD new file mode 100644 index 0000000..53c1345 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/RECORD @@ -0,0 +1,188 @@ +easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 +pkg_resources/__init__.py,sha256=d7w_yqCD39lZE0-qxhWXPYoc-pZc3G2mD7EU2xhRLpM,104720 +pkg_resources/py31compat.py,sha256=-WQ0e4c3RG_acdhwC3gLiXhP_lg4G5q7XYkZkQg0gxU,558 +pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources/_vendor/appdirs.py,sha256=MievUEuv3l_mQISH5SF0shDk_BNhHHzYiAPrT3ITN4I,24701 +pkg_resources/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pkg_resources/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 +pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +pkg_resources/_vendor/packaging/markers.py,sha256=uEcBBtGvzqltgnArqb9c4RrcInXezDLos14zbBHhWJo,8248 +pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 +pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +pkg_resources/extern/__init__.py,sha256=cHiEfHuLmm6rs5Ve_ztBfMI7Lr31vss-D4wkqF5xzlI,2498 +setuptools/__init__.py,sha256=ipsF2yFkfHmryPP8ASJEtOj9N9OuYkk8HxxIJyOHtj0,6001 +setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 +setuptools/archive_util.py,sha256=kw8Ib_lKjCcnPKNbS7h8HztRVK0d5RacU3r_KRdVnmM,6592 +setuptools/build_meta.py,sha256=qg4RfvgZF1uZPuO1VMioG8JRhNMp5fHrwgpgkYpnzc8,6021 +setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 +setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/config.py,sha256=nCkzIQRWTpVwvtSlFm1kOeSLMMHXmB7hENxwZUT6X9Q,19751 +setuptools/dep_util.py,sha256=fgixvC1R7sH3r13ktyf7N0FALoqEXL1cBarmNpSEoWg,935 +setuptools/depends.py,sha256=hC8QIDcM3VDpRXvRVA6OfL9AaQfxvhxHcN_w6sAyNq8,5837 +setuptools/dist.py,sha256=HyRYLlPp_gkcnvQf8o1RsGq99LtghAeAfxWxbf40KxA,44675 +setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 +setuptools/glibc.py,sha256=X64VvGPL2AbURKwYRsWJOXXGAYOiF_v2qixeTkAULuU,3146 +setuptools/glob.py,sha256=o75cHrOxYsvn854thSxE0x9k8JrKDuhP_rRXlVB00Q4,5084 +setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 +setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 +setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 +setuptools/monkey.py,sha256=FGc9fffh7gAxMLFmJs2DW_OYWpBjkdbNS2n14UAK4NA,5264 +setuptools/msvc.py,sha256=uuRFaZzjJt5Fv3ZmyKUUuLtjx12_8G9RILigGec4irI,40838 +setuptools/namespaces.py,sha256=F0Nrbv8KCT2OrO7rwa03om4N4GZKAlnce-rr-cgDQa8,3199 +setuptools/package_index.py,sha256=yeifZQhJVRwPSaQmRrVPxbXRy-1lF5KdTFV8NAb3YcE,40342 +setuptools/pep425tags.py,sha256=bSGwlybcIpssx9kAv_hqAUJzfEpXSzYRp2u-nDYPdbk,10862 +setuptools/py27compat.py,sha256=3mwxRMDk5Q5O1rSXOERbQDXhFqwDJhhUitfMW_qpUCo,536 +setuptools/py31compat.py,sha256=REvrUBibUHgqI9S-ww0C9bhU-n8PyaQ8Slr1_NRxaaE,820 +setuptools/py33compat.py,sha256=OubjldHJH1KGE1CKt1kRU-Q55keftHT3ea1YoL0ZSco,1195 +setuptools/py36compat.py,sha256=VUDWxmu5rt4QHlGTRtAFu6W5jvfL6WBjeDAzeoBy0OM,2891 +setuptools/sandbox.py,sha256=9UbwfEL5QY436oMI1LtFWohhoZ-UzwHvGyZjUH_qhkw,14276 +setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 +setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 +setuptools/site-patch.py,sha256=OumkIHMuoSenRSW1382kKWI1VAwxNE86E5W8iDd34FY,2302 +setuptools/ssl_support.py,sha256=YBDJsCZjSp62CWjxmSkke9kn9rhHHj25Cus6zhJRW3c,8492 +setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 +setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 +setuptools/wheel.py,sha256=A8hKSqHWZ5KM0-VP_DtptxpMxVF9pQwjWZcHGklxq2o,8102 +setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 +setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +setuptools/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +setuptools/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 +setuptools/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +setuptools/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +setuptools/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +setuptools/_vendor/packaging/markers.py,sha256=Gvpk9EY20yKaMTiKgQZ8yFEEpodqVgVYtfekoic1Yts,8239 +setuptools/_vendor/packaging/requirements.py,sha256=t44M2HVWtr8phIz2OhnILzuGT3rTATaovctV1dpnVIg,4343 +setuptools/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +setuptools/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +setuptools/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +setuptools/command/__init__.py,sha256=NWzJ0A1BEengZpVeqUyWLNm2bk4P3F4iL5QUErHy7kA,594 +setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 +setuptools/command/bdist_egg.py,sha256=be-IBpr1zhS9i6GjKANJgzkbH3ChImdWY7S-j0r2BK8,18167 +setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 +setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 +setuptools/command/build_clib.py,sha256=bQ9aBr-5ZSO-9fGsGsDLz0mnnFteHUZnftVLkhvHDq0,4484 +setuptools/command/build_ext.py,sha256=81CTgsqjBjNl_HOgCJ1lQ5vv1NIM3RBpcoVGpqT4N1M,12897 +setuptools/command/build_py.py,sha256=yWyYaaS9F3o9JbIczn064A5g1C5_UiKRDxGaTqYbtLE,9596 +setuptools/command/develop.py,sha256=Sl1iMOORbAnp5BqiXmyMBD0uuvEnhSfOCqbxIPRiJPc,8060 +setuptools/command/dist_info.py,sha256=5t6kOfrdgALT-P3ogss6PF9k-Leyesueycuk3dUyZnI,960 +setuptools/command/easy_install.py,sha256=telww7CuPsoTtvlpY-ktnZGT85cZ6xGCGZa0vHvFJ-Q,87273 +setuptools/command/egg_info.py,sha256=3lsuTHQFjmAw6slzRrB3HjLiF2TaImpWHREllAPhyv8,25541 +setuptools/command/install.py,sha256=a0EZpL_A866KEdhicTGbuyD_TYl1sykfzdrri-zazT4,4683 +setuptools/command/install_egg_info.py,sha256=bMgeIeRiXzQ4DAGPV1328kcjwQjHjOWU4FngAWLV78Q,2203 +setuptools/command/install_lib.py,sha256=11mxf0Ch12NsuYwS8PHwXBRvyh671QAM4cTRh7epzG0,3840 +setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 +setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 +setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 +setuptools/command/register.py,sha256=LO3MvYKPE8dN1m-KkrBRHC68ZFoPvA_vI8Xgp7vv6zI,534 +setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 +setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 +setuptools/command/sdist.py,sha256=obDTe2BmWt2PlnFPZZh7e0LWvemEsbCCO9MzhrTZjm8,6711 +setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 +setuptools/command/test.py,sha256=fSl5OsZWSmFR3QJRvyy2OxbcYkuIkPvykWNOhFvAcUA,9228 +setuptools/command/upload.py,sha256=BpQCjKtJZ4kEb0qIOiTjlJtbpapmNacC27nG2ZlSxTY,6825 +setuptools/command/upload_docs.py,sha256=oXiGplM_cUKLwE4CWWw98RzCufAu8tBhMC97GegFcms,7311 +setuptools/extern/__init__.py,sha256=TxeNKFMSfBMzBpBDiHx8Dh3RzsdVmvWaXhtZ03DZMs0,2499 +setuptools-40.6.2.dist-info/LICENSE,sha256=wyo6w5WvYyHv0ovnPQagDw22q4h9HCHU_sRhKNIFbVo,1078 +setuptools-40.6.2.dist-info/METADATA,sha256=xD5qjTNmFccxhrkNSRwX2ksMINOFNLCysl5ESfOrYRE,3092 +setuptools-40.6.2.dist-info/WHEEL,sha256=CihQvCnsGZQBGAHLEUMf0IdA4fRduS_NBUTMgCTtvPM,110 +setuptools-40.6.2.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 +setuptools-40.6.2.dist-info/entry_points.txt,sha256=jBqCYDlVjl__sjYFGXo1JQGIMAYFJE-prYWUtnMZEew,2990 +setuptools-40.6.2.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 +setuptools-40.6.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +setuptools-40.6.2.dist-info/RECORD,, +../../../bin/easy_install,sha256=6Z3GrIxowGAFMuTfS6Wu6fUgk0M-URaOm734J3Jy3AQ,276 +../../../bin/easy_install-3.7,sha256=6Z3GrIxowGAFMuTfS6Wu6fUgk0M-URaOm734J3Jy3AQ,276 +setuptools-40.6.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +__pycache__/easy_install.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/_structures.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/version.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/requirements.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/markers.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/_compat.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/utils.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/__about__.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/__init__.cpython-37.pyc,, +setuptools/_vendor/__pycache__/six.cpython-37.pyc,, +setuptools/_vendor/__pycache__/pyparsing.cpython-37.pyc,, +setuptools/_vendor/__pycache__/__init__.cpython-37.pyc,, +setuptools/__pycache__/py31compat.cpython-37.pyc,, +setuptools/__pycache__/package_index.cpython-37.pyc,, +setuptools/__pycache__/windows_support.cpython-37.pyc,, +setuptools/__pycache__/sandbox.cpython-37.pyc,, +setuptools/__pycache__/site-patch.cpython-37.pyc,, +setuptools/__pycache__/version.cpython-37.pyc,, +setuptools/__pycache__/wheel.cpython-37.pyc,, +setuptools/__pycache__/unicode_utils.cpython-37.pyc,, +setuptools/__pycache__/launch.cpython-37.pyc,, +setuptools/__pycache__/config.cpython-37.pyc,, +setuptools/__pycache__/depends.cpython-37.pyc,, +setuptools/__pycache__/ssl_support.cpython-37.pyc,, +setuptools/__pycache__/glibc.cpython-37.pyc,, +setuptools/__pycache__/py27compat.cpython-37.pyc,, +setuptools/__pycache__/_deprecation_warning.cpython-37.pyc,, +setuptools/__pycache__/msvc.cpython-37.pyc,, +setuptools/__pycache__/glob.cpython-37.pyc,, +setuptools/__pycache__/pep425tags.cpython-37.pyc,, +setuptools/__pycache__/py36compat.cpython-37.pyc,, +setuptools/__pycache__/monkey.cpython-37.pyc,, +setuptools/__pycache__/lib2to3_ex.cpython-37.pyc,, +setuptools/__pycache__/py33compat.cpython-37.pyc,, +setuptools/__pycache__/dist.cpython-37.pyc,, +setuptools/__pycache__/build_meta.cpython-37.pyc,, +setuptools/__pycache__/dep_util.cpython-37.pyc,, +setuptools/__pycache__/namespaces.cpython-37.pyc,, +setuptools/__pycache__/archive_util.cpython-37.pyc,, +setuptools/__pycache__/extension.cpython-37.pyc,, +setuptools/__pycache__/__init__.cpython-37.pyc,, +setuptools/command/__pycache__/register.cpython-37.pyc,, +setuptools/command/__pycache__/alias.cpython-37.pyc,, +setuptools/command/__pycache__/bdist_egg.cpython-37.pyc,, +setuptools/command/__pycache__/setopt.cpython-37.pyc,, +setuptools/command/__pycache__/install_lib.cpython-37.pyc,, +setuptools/command/__pycache__/bdist_rpm.cpython-37.pyc,, +setuptools/command/__pycache__/dist_info.cpython-37.pyc,, +setuptools/command/__pycache__/develop.cpython-37.pyc,, +setuptools/command/__pycache__/build_clib.cpython-37.pyc,, +setuptools/command/__pycache__/build_py.cpython-37.pyc,, +setuptools/command/__pycache__/sdist.cpython-37.pyc,, +setuptools/command/__pycache__/upload.cpython-37.pyc,, +setuptools/command/__pycache__/py36compat.cpython-37.pyc,, +setuptools/command/__pycache__/egg_info.cpython-37.pyc,, +setuptools/command/__pycache__/install.cpython-37.pyc,, +setuptools/command/__pycache__/easy_install.cpython-37.pyc,, +setuptools/command/__pycache__/upload_docs.cpython-37.pyc,, +setuptools/command/__pycache__/rotate.cpython-37.pyc,, +setuptools/command/__pycache__/build_ext.cpython-37.pyc,, +setuptools/command/__pycache__/saveopts.cpython-37.pyc,, +setuptools/command/__pycache__/bdist_wininst.cpython-37.pyc,, +setuptools/command/__pycache__/test.cpython-37.pyc,, +setuptools/command/__pycache__/__init__.cpython-37.pyc,, +setuptools/command/__pycache__/install_egg_info.cpython-37.pyc,, +setuptools/command/__pycache__/install_scripts.cpython-37.pyc,, +setuptools/extern/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/version.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/markers.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/utils.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/appdirs.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/six.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/pyparsing.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/__pycache__/py31compat.cpython-37.pyc,, +pkg_resources/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/extern/__pycache__/__init__.cpython-37.pyc,, diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/WHEEL b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/WHEEL new file mode 100644 index 0000000..dea0e20 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt new file mode 100644 index 0000000..e87d021 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt @@ -0,0 +1,2 @@ +https://files.pythonhosted.org/packages/source/c/certifi/certifi-2016.9.26.tar.gz#md5=baa81e951a29958563689d868ef1064d +https://files.pythonhosted.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2 diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/entry_points.txt b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/entry_points.txt new file mode 100644 index 0000000..4159fd0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/entry_points.txt @@ -0,0 +1,65 @@ +[console_scripts] +easy_install = setuptools.command.easy_install:main +easy_install-3.6 = setuptools.command.easy_install:main + +[distutils.commands] +alias = setuptools.command.alias:alias +bdist_egg = setuptools.command.bdist_egg:bdist_egg +bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm +bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst +build_clib = setuptools.command.build_clib:build_clib +build_ext = setuptools.command.build_ext:build_ext +build_py = setuptools.command.build_py:build_py +develop = setuptools.command.develop:develop +dist_info = setuptools.command.dist_info:dist_info +easy_install = setuptools.command.easy_install:easy_install +egg_info = setuptools.command.egg_info:egg_info +install = setuptools.command.install:install +install_egg_info = setuptools.command.install_egg_info:install_egg_info +install_lib = setuptools.command.install_lib:install_lib +install_scripts = setuptools.command.install_scripts:install_scripts +register = setuptools.command.register:register +rotate = setuptools.command.rotate:rotate +saveopts = setuptools.command.saveopts:saveopts +sdist = setuptools.command.sdist:sdist +setopt = setuptools.command.setopt:setopt +test = setuptools.command.test:test +upload = setuptools.command.upload:upload +upload_docs = setuptools.command.upload_docs:upload_docs + +[distutils.setup_keywords] +convert_2to3_doctests = setuptools.dist:assert_string_list +dependency_links = setuptools.dist:assert_string_list +eager_resources = setuptools.dist:assert_string_list +entry_points = setuptools.dist:check_entry_points +exclude_package_data = setuptools.dist:check_package_data +extras_require = setuptools.dist:check_extras +include_package_data = setuptools.dist:assert_bool +install_requires = setuptools.dist:check_requirements +namespace_packages = setuptools.dist:check_nsp +package_data = setuptools.dist:check_package_data +packages = setuptools.dist:check_packages +python_requires = setuptools.dist:check_specifier +setup_requires = setuptools.dist:check_requirements +test_loader = setuptools.dist:check_importable +test_runner = setuptools.dist:check_importable +test_suite = setuptools.dist:check_test_suite +tests_require = setuptools.dist:check_requirements +use_2to3 = setuptools.dist:assert_bool +use_2to3_exclude_fixers = setuptools.dist:assert_string_list +use_2to3_fixers = setuptools.dist:assert_string_list +zip_safe = setuptools.dist:assert_bool + +[egg_info.writers] +PKG-INFO = setuptools.command.egg_info:write_pkg_info +dependency_links.txt = setuptools.command.egg_info:overwrite_arg +depends.txt = setuptools.command.egg_info:warn_depends_obsolete +eager_resources.txt = setuptools.command.egg_info:overwrite_arg +entry_points.txt = setuptools.command.egg_info:write_entries +namespace_packages.txt = setuptools.command.egg_info:overwrite_arg +requires.txt = setuptools.command.egg_info:write_requirements +top_level.txt = setuptools.command.egg_info:write_toplevel_names + +[setuptools.installation] +eggsecutable = setuptools.command.easy_install:bootstrap + diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/top_level.txt b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/top_level.txt new file mode 100644 index 0000000..4577c6a --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/top_level.txt @@ -0,0 +1,3 @@ +easy_install +pkg_resources +setuptools diff --git a/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/zip-safe b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools-40.6.2.dist-info/zip-safe @@ -0,0 +1 @@ + diff --git a/venv/lib/python3.7/site-packages/setuptools/__init__.py b/venv/lib/python3.7/site-packages/setuptools/__init__.py new file mode 100644 index 0000000..e438036 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/__init__.py @@ -0,0 +1,195 @@ +"""Extensions to the 'distutils' for large or complex distributions""" + +import os +import sys +import functools +import distutils.core +import distutils.filelist +from distutils.util import convert_path +from fnmatch import fnmatchcase + +from ._deprecation_warning import SetuptoolsDeprecationWarning + +from setuptools.extern.six import PY3 +from setuptools.extern.six.moves import filter, map + +import setuptools.version +from setuptools.extension import Extension +from setuptools.dist import Distribution, Feature +from setuptools.depends import Require +from . import monkey + +__metaclass__ = type + + +__all__ = [ + 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', + 'SetuptoolsDeprecationWarning', + 'find_packages' +] + +if PY3: + __all__.append('find_namespace_packages') + +__version__ = setuptools.version.__version__ + +bootstrap_install_from = None + +# If we run 2to3 on .py files, should we also convert docstrings? +# Default: yes; assume that we can detect doctests reliably +run_2to3_on_doctests = True +# Standard package names for fixer packages +lib2to3_fixer_packages = ['lib2to3.fixes'] + + +class PackageFinder: + """ + Generate a list of all Python packages found within a directory + """ + + @classmethod + def find(cls, where='.', exclude=(), include=('*',)): + """Return a list all Python packages found within directory 'where' + + 'where' is the root directory which will be searched for packages. It + should be supplied as a "cross-platform" (i.e. URL-style) path; it will + be converted to the appropriate local path syntax. + + 'exclude' is a sequence of package names to exclude; '*' can be used + as a wildcard in the names, such that 'foo.*' will exclude all + subpackages of 'foo' (but not 'foo' itself). + + 'include' is a sequence of package names to include. If it's + specified, only the named packages will be included. If it's not + specified, all found packages will be included. 'include' can contain + shell style wildcard patterns just like 'exclude'. + """ + + return list(cls._find_packages_iter( + convert_path(where), + cls._build_filter('ez_setup', '*__pycache__', *exclude), + cls._build_filter(*include))) + + @classmethod + def _find_packages_iter(cls, where, exclude, include): + """ + All the packages found in 'where' that pass the 'include' filter, but + not the 'exclude' filter. + """ + for root, dirs, files in os.walk(where, followlinks=True): + # Copy dirs to iterate over it, then empty dirs. + all_dirs = dirs[:] + dirs[:] = [] + + for dir in all_dirs: + full_path = os.path.join(root, dir) + rel_path = os.path.relpath(full_path, where) + package = rel_path.replace(os.path.sep, '.') + + # Skip directory trees that are not valid packages + if ('.' in dir or not cls._looks_like_package(full_path)): + continue + + # Should this package be included? + if include(package) and not exclude(package): + yield package + + # Keep searching subdirectories, as there may be more packages + # down there, even if the parent was excluded. + dirs.append(dir) + + @staticmethod + def _looks_like_package(path): + """Does a directory look like a package?""" + return os.path.isfile(os.path.join(path, '__init__.py')) + + @staticmethod + def _build_filter(*patterns): + """ + Given a list of patterns, return a callable that will be true only if + the input matches at least one of the patterns. + """ + return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) + + +class PEP420PackageFinder(PackageFinder): + @staticmethod + def _looks_like_package(path): + return True + + +find_packages = PackageFinder.find + +if PY3: + find_namespace_packages = PEP420PackageFinder.find + + +def _install_setup_requires(attrs): + # Note: do not use `setuptools.Distribution` directly, as + # our PEP 517 backend patch `distutils.core.Distribution`. + dist = distutils.core.Distribution(dict( + (k, v) for k, v in attrs.items() + if k in ('dependency_links', 'setup_requires') + )) + # Honor setup.cfg's options. + dist.parse_config_files(ignore_option_errors=True) + if dist.setup_requires: + dist.fetch_build_eggs(dist.setup_requires) + + +def setup(**attrs): + # Make sure we have any requirements needed to interpret 'attrs'. + _install_setup_requires(attrs) + return distutils.core.setup(**attrs) + +setup.__doc__ = distutils.core.setup.__doc__ + + +_Command = monkey.get_unpatched(distutils.core.Command) + + +class Command(_Command): + __doc__ = _Command.__doc__ + + command_consumes_arguments = False + + def __init__(self, dist, **kw): + """ + Construct the command for dist, updating + vars(self) with any keyword parameters. + """ + _Command.__init__(self, dist) + vars(self).update(kw) + + def reinitialize_command(self, command, reinit_subcommands=0, **kw): + cmd = _Command.reinitialize_command(self, command, reinit_subcommands) + vars(cmd).update(kw) + return cmd + + +def _find_all_simple(path): + """ + Find all files under 'path' + """ + results = ( + os.path.join(base, file) + for base, dirs, files in os.walk(path, followlinks=True) + for file in files + ) + return filter(os.path.isfile, results) + + +def findall(dir=os.curdir): + """ + Find all files under 'dir' and return the list of full filenames. + Unless dir is '.', return full filenames with dir prepended. + """ + files = _find_all_simple(dir) + if dir == os.curdir: + make_rel = functools.partial(os.path.relpath, start=dir) + files = map(make_rel, files) + return list(files) + + +# Apply monkey patches +monkey.patch_all() diff --git a/venv/lib/python3.7/site-packages/setuptools/_deprecation_warning.py b/venv/lib/python3.7/site-packages/setuptools/_deprecation_warning.py new file mode 100644 index 0000000..086b64d --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_deprecation_warning.py @@ -0,0 +1,7 @@ +class SetuptoolsDeprecationWarning(Warning): + """ + Base class for warning deprecations in ``setuptools`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/__init__.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__about__.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__about__.py new file mode 100644 index 0000000..95d330e --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "16.8" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__init__.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_compat.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_structures.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_structures.py new file mode 100644 index 0000000..ccc2786 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + +NegativeInfinity = NegativeInfinity() diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/markers.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/markers.py new file mode 100644 index 0000000..031332a --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from setuptools.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from setuptools.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from setuptools.extern.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "<Marker({0!r})>".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/requirements.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/requirements.py new file mode 100644 index 0000000..5b49341 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/requirements.py @@ -0,0 +1,127 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from setuptools.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from setuptools.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from setuptools.extern.pyparsing import Literal as L # noqa +from setuptools.extern.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPERATOR = SEMICOLON +MARKER = MARKER_SEPERATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + "Invalid requirement, parse error at \"{0!r}\"".format( + requirement_string[e.loc:e.loc + 8])) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL given") + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "<Requirement({0!r})>".format(str(self)) diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/specifiers.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..7f5a76c --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the begining. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(==|!=|<=|>=|<|>)) + \s* + (?P<version> + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(~=|==|!=|<=|>=|<|>|===)) + (?P<version> + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?<!==|!=|~=) # We have special cases for these + # operators so we want to make sure they + # don't match here. + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is techincally greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<SpecifierSet({0!r}{1})>".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/utils.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/utils.py new file mode 100644 index 0000000..942387c --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/utils.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/version.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/version.py new file mode 100644 index 0000000..83b5ee8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/packaging/version.py @@ -0,0 +1,393 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "<LegacyVersion({0})>".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P<epoch>[0-9]+)!)? # epoch + (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment + (?P<pre> # pre-release + [-_\.]? + (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) + [-_\.]? + (?P<pre_n>[0-9]+)? + )? + (?P<post> # post release + (?:-(?P<post_n1>[0-9]+)) + | + (?: + [-_\.]? + (?P<post_l>post|rev|r) + [-_\.]? + (?P<post_n2>[0-9]+)? + ) + )? + (?P<dev> # dev release + [-_\.]? + (?P<dev_l>dev) + [-_\.]? + (?P<dev_n>[0-9]+)? + )? + ) + (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version +""" + + +class Version(_BaseVersion): + + _regex = re.compile( + r"^\s*" + VERSION_PATTERN + r"\s*$", + re.VERBOSE | re.IGNORECASE, + ) + + def __init__(self, version): + # Validate the version and parse it into pieces + match = self._regex.search(version) + if not match: + raise InvalidVersion("Invalid version: '{0}'".format(version)) + + # Store the parsed out pieces of the version + self._version = _Version( + epoch=int(match.group("epoch")) if match.group("epoch") else 0, + release=tuple(int(i) for i in match.group("release").split(".")), + pre=_parse_letter_version( + match.group("pre_l"), + match.group("pre_n"), + ), + post=_parse_letter_version( + match.group("post_l"), + match.group("post_n1") or match.group("post_n2"), + ), + dev=_parse_letter_version( + match.group("dev_l"), + match.group("dev_n"), + ), + local=_parse_local_version(match.group("local")), + ) + + # Generate a key which will be used for sorting + self._key = _cmpkey( + self._version.epoch, + self._version.release, + self._version.pre, + self._version.post, + self._version.dev, + self._version.local, + ) + + def __repr__(self): + return "<Version({0})>".format(repr(str(self))) + + def __str__(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + # Pre-release + if self._version.pre is not None: + parts.append("".join(str(x) for x in self._version.pre)) + + # Post-release + if self._version.post is not None: + parts.append(".post{0}".format(self._version.post[1])) + + # Development release + if self._version.dev is not None: + parts.append(".dev{0}".format(self._version.dev[1])) + + # Local version segment + if self._version.local is not None: + parts.append( + "+{0}".format(".".join(str(x) for x in self._version.local)) + ) + + return "".join(parts) + + @property + def public(self): + return str(self).split("+", 1)[0] + + @property + def base_version(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + return "".join(parts) + + @property + def local(self): + version_string = str(self) + if "+" in version_string: + return version_string.split("+", 1)[1] + + @property + def is_prerelease(self): + return bool(self._version.dev or self._version.pre) + + @property + def is_postrelease(self): + return bool(self._version.post) + + +def _parse_letter_version(letter, number): + if letter: + # We consider there to be an implicit 0 in a pre-release if there is + # not a numeral associated with it. + if number is None: + number = 0 + + # We normalize any letters to their lower case form + letter = letter.lower() + + # We consider some words to be alternate spellings of other words and + # in those cases we want to normalize the spellings to our preferred + # spelling. + if letter == "alpha": + letter = "a" + elif letter == "beta": + letter = "b" + elif letter in ["c", "pre", "preview"]: + letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" + + return letter, int(number) + if not letter and number: + # We assume if we are given a number, but we are not given a letter + # then this is using the implicit post release syntax (e.g. 1.0-1) + letter = "post" + + return letter, int(number) + + +_local_version_seperators = re.compile(r"[\._-]") + + +def _parse_local_version(local): + """ + Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). + """ + if local is not None: + return tuple( + part.lower() if not part.isdigit() else int(part) + for part in _local_version_seperators.split(local) + ) + + +def _cmpkey(epoch, release, pre, post, dev, local): + # When we compare a release version, we want to compare it with all of the + # trailing zeros removed. So we'll use a reverse the list, drop all the now + # leading zeros until we come to something non zero, then take the rest + # re-reverse it back into the correct order and make it a tuple and use + # that for our sorting key. + release = tuple( + reversed(list( + itertools.dropwhile( + lambda x: x == 0, + reversed(release), + ) + )) + ) + + # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. + # We'll do this by abusing the pre segment, but we _only_ want to do this + # if there is not a pre or a post segment. If we have one of those then + # the normal sorting rules will handle this case correctly. + if pre is None and post is None and dev is not None: + pre = -Infinity + # Versions without a pre-release (except as noted above) should sort after + # those with one. + elif pre is None: + pre = Infinity + + # Versions without a post segment should sort before those with one. + if post is None: + post = -Infinity + + # Versions without a development segment should sort after those with one. + if dev is None: + dev = Infinity + + if local is None: + # Versions without a local segment should sort before those with one. + local = -Infinity + else: + # Versions with a local segment need that segment parsed to implement + # the sorting rules in PEP440. + # - Alpha numeric segments sort before numeric segments + # - Alpha numeric segments sort lexicographically + # - Numeric segments sort numerically + # - Shorter versions sort before longer versions when the prefixes + # match exactly + local = tuple( + (i, "") if isinstance(i, int) else (-Infinity, i) + for i in local + ) + + return epoch, release, pre, post, dev, local diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/pyparsing.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/pyparsing.py new file mode 100644 index 0000000..4aa30ee --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/pyparsing.py @@ -0,0 +1,5742 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2018 Paul T. McGuire +# +# 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. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes + - construct character word-group expressions using the L{Word} class + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes + - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones + - associate names with your parsed results using L{ParserElement.setResultsName} + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} + - find more useful common expressions in the L{pyparsing_common} namespace class +""" + +__version__ = "2.2.1" +__versionTime__ = "18 Sep 2018 00:49 UTC" +__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + # Python 3 + from collections.abc import Iterable + from collections.abc import MutableMapping +except ImportError: + # Python 2.7 + from collections import Iterable + from collections import MutableMapping + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "</", resTag, ">" ] + + out += [ nl, indent, "</", selfTag, ">" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) + +def lineno(loc,strg): + """Returns current line number within a string, counting newlines as line separators. + The first line is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [frame_summary[:2]] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [frame_summary[:2]] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "<parse action>" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, <TAB> and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}<parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. + + See examples in L{I{copy}<copy>}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or preloc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}<parseWithTabs>}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}<parseString>} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of <TAB>s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{<TAB>} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): + throwException = True + + if throwException: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except Exception: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "<SPC>", + "\t": "<TAB>", + "\n": "<LF>", + "\r": "<CR>", + "\f": "<FF>", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc<len(instring): + if instring[loc] == "\n": + return loc+1, "\n" + else: + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class StringStart(_PositionToken): + """ + Matches if current position is at the beginning of the parse string + """ + def __init__( self ): + super(StringStart,self).__init__() + self.errmsg = "Expected start of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc != 0: + # see if entire string up to here is just whitespace and ignoreables + if loc != self.preParse( instring, 0 ): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class StringEnd(_PositionToken): + """ + Matches if current position is at the end of the parse string + """ + def __init__( self ): + super(StringEnd,self).__init__() + self.errmsg = "Expected end of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc < len(instring): + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + elif loc > len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + +class ParseExpression(ParserElement): + """ + Abstract subclass of ParserElement, for combining and post-processing parsed tokens. + """ + def __init__( self, exprs, savelist = False ): + super(ParseExpression,self).__init__(savelist) + if isinstance( exprs, _generatorType ): + exprs = list(exprs) + + if isinstance( exprs, basestring ): + self.exprs = [ ParserElement._literalStringClass( exprs ) ] + elif isinstance( exprs, Iterable ): + exprs = list(exprs) + # if sequence of strings provided, wrap with Literal + if all(isinstance(expr, basestring) for expr in exprs): + exprs = map(ParserElement._literalStringClass, exprs) + self.exprs = list(exprs) + else: + try: + self.exprs = list( exprs ) + except TypeError: + self.exprs = [ exprs ] + self.callPreparse = False + + def __getitem__( self, i ): + return self.exprs[i] + + def append( self, other ): + self.exprs.append( other ) + self.strRepr = None + return self + + def leaveWhitespace( self ): + """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on + all contained expressions.""" + self.skipWhitespace = False + self.exprs = [ e.copy() for e in self.exprs ] + for e in self.exprs: + e.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + else: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + return self + + def __str__( self ): + try: + return super(ParseExpression,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) + return self.strRepr + + def streamline( self ): + super(ParseExpression,self).streamline() + + for e in self.exprs: + e.streamline() + + # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) + # but only if there are no parse actions or resultsNames on the nested And's + # (likewise for Or's and MatchFirst's) + if ( len(self.exprs) == 2 ): + other = self.exprs[0] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = other.exprs[:] + [ self.exprs[1] ] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + other = self.exprs[-1] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = self.exprs[:-1] + other.exprs[:] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + self.errmsg = "Expected " + _ustr(self) + + return self + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ParseExpression,self).setResultsName(name,listAllMatches) + return ret + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + for e in self.exprs: + e.validate(tmp) + self.checkRecursion( [] ) + + def copy(self): + ret = super(ParseExpression,self).copy() + ret.exprs = [e.copy() for e in self.exprs] + return ret + +class And(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found in the given order. + Expressions may be separated by whitespace. + May be constructed using the C{'+'} operator. + May also be constructed using the C{'-'} operator, which will suppress backtracking. + + Example:: + integer = Word(nums) + name_expr = OneOrMore(Word(alphas)) + + expr = And([integer("id"),name_expr("name"),integer("age")]) + # more easily written as: + expr = integer("id") + name_expr("name") + integer("age") + """ + + class _ErrorStop(Empty): + def __init__(self, *args, **kwargs): + super(And._ErrorStop,self).__init__(*args, **kwargs) + self.name = '-' + self.leaveWhitespace() + + def __init__( self, exprs, savelist = True ): + super(And,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.setWhitespaceChars( self.exprs[0].whiteChars ) + self.skipWhitespace = self.exprs[0].skipWhitespace + self.callPreparse = True + + def parseImpl( self, instring, loc, doActions=True ): + # pass False as last arg to _parse for first element, since we already + # pre-parsed the string as part of our And pre-parsing + loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False + for e in self.exprs[1:]: + if isinstance(e, And._ErrorStop): + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseSyntaxException: + raise + except ParseBaseException as pe: + pe.__traceback__ = None + raise ParseSyntaxException._from_exception(pe) + except IndexError: + raise ParseSyntaxException(instring, len(instring), self.errmsg, self) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) + if exprtokens or exprtokens.haskeys(): + resultlist += exprtokens + return loc, resultlist + + def __iadd__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #And( [ self, other ] ) + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + if not e.mayReturnEmpty: + break + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + +class Or(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the expression that matches the longest string will be used. + May be constructed using the C{'^'} operator. + + Example:: + # construct Or using '^' operator + + number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) + prints:: + [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(Or,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + matches = [] + for e in self.exprs: + try: + loc2 = e.tryParse( instring, loc ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens)))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <<leaving remove_duplicate_chars (ret: 'dfjkls') + ['dfjkls'] + """ + f = _trim_arity(f) + def z(*paArgs): + thisFunc = f.__name__ + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) + raise + sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) + return ret + try: + z.__name__ = f.__name__ + except AttributeError: + pass + return z + +# +# global helpers +# +def delimitedList( expr, delim=",", combine=False ): + """ + Helper to define a delimited list of expressions - the delimiter defaults to ','. + By default, the list elements and delimiters can have intervening whitespace, and + comments, but this can be overridden by passing C{combine=True} in the constructor. + If C{combine} is set to C{True}, the matching tokens are returned as a single token + string, with the delimiters included; otherwise, the matching tokens are returned + as a list of tokens, with the delimiters suppressed. + + Example:: + delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test <b> bold <i>text</i> </b> normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + ['<b> bold <i>text</i> </b>'] + ['<i>text</i>'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{<TAB>} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString<ParserElement.transformString>}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("</") + tagStr + ">") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the <A> tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{<TD>} or C{<DIV>}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' + <div> + Some text + <div type="grid">1 4 0 1 0</div> + <div type="graph">1,3 2,3 1,1</div> + <div>this has no type</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' + <div> + Some text + <div class="grid">1 4 0 1 0</div> + <div class="graph">1,3 2,3 1,1</div> + <div>this <div> has no class</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") +"Comment of the form C{<!-- ... -->}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) + - common L{programming identifiers<identifier>} + - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) + - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} + - L{UUID<uuid>} + - L{comma-separated list<comma_separated_list>} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/venv/lib/python3.7/site-packages/setuptools/_vendor/six.py b/venv/lib/python3.7/site-packages/setuptools/_vendor/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/_vendor/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# 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. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/venv/lib/python3.7/site-packages/setuptools/archive_util.py b/venv/lib/python3.7/site-packages/setuptools/archive_util.py new file mode 100644 index 0000000..8143604 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/archive_util.py @@ -0,0 +1,173 @@ +"""Utilities for extracting common archive formats""" + +import zipfile +import tarfile +import os +import shutil +import posixpath +import contextlib +from distutils.errors import DistutilsError + +from pkg_resources import ensure_directory + +__all__ = [ + "unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter", + "UnrecognizedFormat", "extraction_drivers", "unpack_directory", +] + + +class UnrecognizedFormat(DistutilsError): + """Couldn't recognize the archive type""" + + +def default_filter(src, dst): + """The default progress/filter callback; returns True for all files""" + return dst + + +def unpack_archive(filename, extract_dir, progress_filter=default_filter, + drivers=None): + """Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat`` + + `progress_filter` is a function taking two arguments: a source path + internal to the archive ('/'-separated), and a filesystem path where it + will be extracted. The callback must return the desired extract path + (which may be the same as the one passed in), or else ``None`` to skip + that file or directory. The callback can thus be used to report on the + progress of the extraction, as well as to filter the items extracted or + alter their extraction paths. + + `drivers`, if supplied, must be a non-empty sequence of functions with the + same signature as this function (minus the `drivers` argument), that raise + ``UnrecognizedFormat`` if they do not support extracting the designated + archive type. The `drivers` are tried in sequence until one is found that + does not raise an error, or until all are exhausted (in which case + ``UnrecognizedFormat`` is raised). If you do not supply a sequence of + drivers, the module's ``extraction_drivers`` constant will be used, which + means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that + order. + """ + for driver in drivers or extraction_drivers: + try: + driver(filename, extract_dir, progress_filter) + except UnrecognizedFormat: + continue + else: + return + else: + raise UnrecognizedFormat( + "Not a recognized archive type: %s" % filename + ) + + +def unpack_directory(filename, extract_dir, progress_filter=default_filter): + """"Unpack" a directory, using the same interface as for archives + + Raises ``UnrecognizedFormat`` if `filename` is not a directory + """ + if not os.path.isdir(filename): + raise UnrecognizedFormat("%s is not a directory" % filename) + + paths = { + filename: ('', extract_dir), + } + for base, dirs, files in os.walk(filename): + src, dst = paths[base] + for d in dirs: + paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d) + for f in files: + target = os.path.join(dst, f) + target = progress_filter(src + f, target) + if not target: + # skip non-files + continue + ensure_directory(target) + f = os.path.join(base, f) + shutil.copyfile(f, target) + shutil.copystat(f, target) + + +def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): + """Unpack zip `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined + by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + + if not zipfile.is_zipfile(filename): + raise UnrecognizedFormat("%s is not a zip file" % (filename,)) + + with zipfile.ZipFile(filename) as z: + for info in z.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name.split('/'): + continue + + target = os.path.join(extract_dir, *name.split('/')) + target = progress_filter(name, target) + if not target: + continue + if name.endswith('/'): + # directory + ensure_directory(target) + else: + # file + ensure_directory(target) + data = z.read(info.filename) + with open(target, 'wb') as f: + f.write(data) + unix_attributes = info.external_attr >> 16 + if unix_attributes: + os.chmod(target, unix_attributes) + + +def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined + by ``tarfile.open()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise UnrecognizedFormat( + "%s is not a compressed or uncompressed tar file" % (filename,) + ) + with contextlib.closing(tarobj): + # don't do any chowning! + tarobj.chown = lambda *args: None + for member in tarobj: + name = member.name + # don't extract absolute paths or ones with .. in them + if not name.startswith('/') and '..' not in name.split('/'): + prelim_dst = os.path.join(extract_dir, *name.split('/')) + + # resolve any links and to extract the link targets as normal + # files + while member is not None and (member.islnk() or member.issym()): + linkpath = member.linkname + if member.issym(): + base = posixpath.dirname(member.name) + linkpath = posixpath.join(base, linkpath) + linkpath = posixpath.normpath(linkpath) + member = tarobj._getmember(linkpath) + + if member is not None and (member.isfile() or member.isdir()): + final_dst = progress_filter(name, prelim_dst) + if final_dst: + if final_dst.endswith(os.sep): + final_dst = final_dst[:-1] + try: + # XXX Ugh + tarobj._extract_member(member, final_dst) + except tarfile.ExtractError: + # chown/chmod/mkfifo/mknode/makedev failed + pass + return True + + +extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile diff --git a/venv/lib/python3.7/site-packages/setuptools/build_meta.py b/venv/lib/python3.7/site-packages/setuptools/build_meta.py new file mode 100644 index 0000000..0067a7a --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/build_meta.py @@ -0,0 +1,182 @@ +"""A PEP 517 interface to setuptools + +Previously, when a user or a command line tool (let's call it a "frontend") +needed to make a request of setuptools to take a certain action, for +example, generating a list of installation requirements, the frontend would +would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line. + +PEP 517 defines a different method of interfacing with setuptools. Rather +than calling "setup.py" directly, the frontend should: + + 1. Set the current directory to the directory with a setup.py file + 2. Import this module into a safe python interpreter (one in which + setuptools can potentially set global variables or crash hard). + 3. Call one of the functions defined in PEP 517. + +What each function does is defined in PEP 517. However, here is a "casual" +definition of the functions (this definition should not be relied on for +bug reports or API stability): + + - `build_wheel`: build a wheel in the folder and return the basename + - `get_requires_for_build_wheel`: get the `setup_requires` to build + - `prepare_metadata_for_build_wheel`: get the `install_requires` + - `build_sdist`: build an sdist in the folder and return the basename + - `get_requires_for_build_sdist`: get the `setup_requires` to build + +Again, this is not a formal definition! Just a "taste" of the module. +""" + +import os +import sys +import tokenize +import shutil +import contextlib + +import setuptools +import distutils + + +class SetupRequirementsError(BaseException): + def __init__(self, specifiers): + self.specifiers = specifiers + + +class Distribution(setuptools.dist.Distribution): + def fetch_build_eggs(self, specifiers): + raise SetupRequirementsError(specifiers) + + @classmethod + @contextlib.contextmanager + def patch(cls): + """ + Replace + distutils.dist.Distribution with this class + for the duration of this context. + """ + orig = distutils.core.Distribution + distutils.core.Distribution = cls + try: + yield + finally: + distutils.core.Distribution = orig + + +def _to_str(s): + """ + Convert a filename to a string (on Python 2, explicitly + a byte string, not Unicode) as distutils checks for the + exact type str. + """ + if sys.version_info[0] == 2 and not isinstance(s, str): + # Assume it's Unicode, as that's what the PEP says + # should be provided. + return s.encode(sys.getfilesystemencoding()) + return s + + +def _run_setup(setup_script='setup.py'): + # Note that we can reuse our build directory between calls + # Correctness comes first, then optimization later + __file__ = setup_script + __name__ = '__main__' + f = getattr(tokenize, 'open', open)(__file__) + code = f.read().replace('\\r\\n', '\\n') + f.close() + exec(compile(code, __file__, 'exec'), locals()) + + +def _fix_config(config_settings): + config_settings = config_settings or {} + config_settings.setdefault('--global-option', []) + return config_settings + + +def _get_build_requires(config_settings, requirements): + config_settings = _fix_config(config_settings) + + sys.argv = sys.argv[:1] + ['egg_info'] + \ + config_settings["--global-option"] + try: + with Distribution.patch(): + _run_setup() + except SetupRequirementsError as e: + requirements += e.specifiers + + return requirements + + +def _get_immediate_subdirectories(a_dir): + return [name for name in os.listdir(a_dir) + if os.path.isdir(os.path.join(a_dir, name))] + + +def get_requires_for_build_wheel(config_settings=None): + config_settings = _fix_config(config_settings) + return _get_build_requires(config_settings, requirements=['setuptools', 'wheel']) + + +def get_requires_for_build_sdist(config_settings=None): + config_settings = _fix_config(config_settings) + return _get_build_requires(config_settings, requirements=['setuptools']) + + +def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None): + sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', _to_str(metadata_directory)] + _run_setup() + + dist_info_directory = metadata_directory + while True: + dist_infos = [f for f in os.listdir(dist_info_directory) + if f.endswith('.dist-info')] + + if len(dist_infos) == 0 and \ + len(_get_immediate_subdirectories(dist_info_directory)) == 1: + dist_info_directory = os.path.join( + dist_info_directory, os.listdir(dist_info_directory)[0]) + continue + + assert len(dist_infos) == 1 + break + + # PEP 517 requires that the .dist-info directory be placed in the + # metadata_directory. To comply, we MUST copy the directory to the root + if dist_info_directory != metadata_directory: + shutil.move( + os.path.join(dist_info_directory, dist_infos[0]), + metadata_directory) + shutil.rmtree(dist_info_directory, ignore_errors=True) + + return dist_infos[0] + + +def build_wheel(wheel_directory, config_settings=None, + metadata_directory=None): + config_settings = _fix_config(config_settings) + wheel_directory = os.path.abspath(wheel_directory) + sys.argv = sys.argv[:1] + ['bdist_wheel'] + \ + config_settings["--global-option"] + _run_setup() + if wheel_directory != 'dist': + shutil.rmtree(wheel_directory) + shutil.copytree('dist', wheel_directory) + + wheels = [f for f in os.listdir(wheel_directory) + if f.endswith('.whl')] + + assert len(wheels) == 1 + return wheels[0] + + +def build_sdist(sdist_directory, config_settings=None): + config_settings = _fix_config(config_settings) + sdist_directory = os.path.abspath(sdist_directory) + sys.argv = sys.argv[:1] + ['sdist'] + \ + config_settings["--global-option"] + \ + ["--dist-dir", sdist_directory] + _run_setup() + + sdists = [f for f in os.listdir(sdist_directory) + if f.endswith('.tar.gz')] + + assert len(sdists) == 1 + return sdists[0] diff --git a/venv/lib/python3.7/site-packages/setuptools/cli-32.exe b/venv/lib/python3.7/site-packages/setuptools/cli-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*G<xQC7$Bg`f~d>lC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)F<LB!IdzF`7%cck^aLb_J<@DD#CfB0B$E^bzV@-Vr`q!&`=<s^68_Wa_GZ_v^?aY zU=VZGXAzm5x{LcyVkUd8JxnNsqtS!3fw-nje@5tui@0AmI$b-*P5O7)s<z9AVj!{a zusK!aLirXkGmKBs9|=}}+<^)RB1ao<^{^>kX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~<iO|JiNP|OD zR=9Lm@@Ua+Eq87EAwAZBPGrH*)zP)xEF>B0I<PUu3WRluor4HwG59U@*GT3C4#)*> z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU<Qo&ds@10tJ4pnneT?LI)M|HS1v7YY$x9Bv-SsJ$Cl+xPAV;6Eqk-srxG9 z{LT5_#k!V#{GO}ibh%Xvw5jxHs@yzGY~@?`(yJD$GqsX;X$pypI5DT^o5eVu9#Z@z zw!tumU}_j8#vZXTB&Vb!;K(WYBw))aIfHo=I@urFFfxYS9PyXWVFQN5U;5Dw%tIz$ zw`nTQR_c;mZr;Y5QwPf3_^KR#GvcZKkFXD~jQGWdi~_bGh!>?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDU<yTk`c&RTk8mVQAOK~qMQ#2raos*zaqlvJZo>L()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#<Dz&@nl0LRIeY=p^I1%{g=J)$y zJ4tny{}tcKG0i7qLLJtU;jl;LnJu8bQak(kB&;UDjom{#=dp=&3s}YXYz3C()*?Ie zpOr>*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM<W!B9QJEa7>_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|<P zZAhQVQAqt{KX8b!o72`jV*h~V{I<6~6`|CSYi!tcFRq-OP_ri!l#8;keBk$FyRh37 zh-vx<nho1V<uSlQEH;(ry7_afSZop_PK$8boQKoq+i)shoyMOs4}aFK<j<xGJnq14 zb2)CC*WtE#b4An68qy4#ciQ16Pbjcq3r`~(syir#2qbbvYtKWddcXwdfk_9bi9C9n ze)1pT^3siP-~5MsCpR}_o2eh^LneJBm*p>KZqkLal4YCRR9VNhIM|rBqmzzcImvcx z66fD`zj4}M-A;gyA17cSC-oI$`q?*q&8~)Qv|C#(aSFd|hYbf}FFVB?n3Q?Svt+Td z#AW4x=9X}?aizE|`r{}3l-H&b6-{_j#STR!lD001vu;K>KT;*^ChCevBwCMFpg{JI zv``4YsjK1&142Pl%%A#u3rbGso1<_fngd1`+}!pMu@z5Me_5UFxiPYKqFL4_`WXmY zeWJrZUKzrrMuBcHupOq4Wr12sE*T-*CXh;FA=)Q+BMN(?DJ!kq?%Ww`xlG3e;lz2t zY?tl;i?gHO_79VwJ_cThq^>FqRUPlqS?IuI+CfSbNkv_1l~7eGaCwRmuOF|ic1ac2 z9ldo$TN~LhX~J01P75nyi&d8=Y@QNZ5e<=6v_R3rM}nN}5ae`^LV&sAD<=;*z=!~` zvJ0@i!orMuT*5kyXNzJnxfU!+#FTW(syy@yj7XX8#zD_9TWBSg(;KZ25VO;is;-&R zf(29n3U}agkC`j4sjX{=`D1EkCC@enOA~v{GOLYQKAdPN6+?W+QE4fLMhrW4RG<SI z@?qI-KY>bH5^K(rm4T}`=ra<6GP2}cRBE9K8^r(O+ZvKpJDL~qNguPmwQZp-8m7V@ zN^KFU8@Q*E7UJswZD=OYtct4KqA&NDKSOfc-#M>@o#)4;YLqtENdFS^3K9&dFBr|M z*loqE3X2sMmi8hv#7H5<kgna*Z>rqGc_y=ShEbHT^m7S`?4d%B+(-6dYGI-*t5E+< z^P3gqvBIHjFQNKiDKj-p;Y*MmMAXOK^8{gVhrBn?Un}%9(JqaGPiann?Ll$aX-{n1 z!AnT<v!xN*zo+dH+)yR$d)}fNUUOcJ)Xz$%vH5mur0%L;@p((;IW$raH52Q@7``Z{ z?rO>WyjwZ7y=hrziEYVZVX)-}D^!8a+Bc<5#*3h1xvWqS7I$WL>iwNNvp;P<;TX`| zOF6ZibFB4T(YJC~mj~?Ev*ln|9sgYVFTcLiEi{YE;!ZWj>X*aK9|va;HulW-D`RH9 zw=O#R&of(j+rwMS%oCi;+oFskQ}@q2q4x)O3<fKs&%WtzzFD};-G{Hxx)V?F$WHWF z7(*i07&g=2&}`P4G>k5e6yDx`kLvQs@M`+D)vGA+`X6%Dl9YOA?Qrurfg>XqT9E@^ zgWxOT&hX+yo>7=HCb!3BO$p54I3{j@qbN!+nu>Ti*O~vw`5RU!f_JXS+*x#-zFp@m zr}GGVhgT1=p-TFp#dtAVjM3QdpDoi{l*z?1s=d~(E;Fkn=*i8+oB<M)E&5W?I^M)M zknOw+hdKDcP%Q}tuai)WoEa!7&-Iumsf3KA>cJ3Ib?Vh+rZWNZ$pO`dl8LcBv_cAA zc18lYB|rc<0u%wEdTGEup|%_S`L>@ui4LTkvnNApm<q=y*er!iCv8V>#>+b4WIF<} z^J}=w7L&$J%unXCb|Wy{z3WVlMDNhz3o7S-3)6oqjx)7WX0HTEH<C-Do)>{-=9>q+ zXXtoVPHKfVJMk8bt&h;MII}u~0l79^#`5CdW6Ef!eb|E&Q{UJ$n$yP;^Jd)qhw~ej zB?c~nN*%0zm%$}MD%|<q*x?^2$-sGY)_qDIsjoQeKH{k^*%_~Mm`JG>VZuS8W+Qtf zS+Uu?;oSPL<h#s;p3UgxZ3c;@9(LZhh9?&RH`z;Ufi?^GL|RbrQ|i$u#k>L}G`jMH zn3`(J{6K%B(Gykos(!d}z)Wr!%sjC6=V@s)qG1MJN~uoVlq{jeI#XKPMI;@L^`RBZ z<X%K$e<C_&9&p~HQ%fuI$-p5?U{jDsR}QoVqzzw}E77mP5v&U`27f1F&0F8zlxE2) ze=M@fh-;2;q_!ewec2frY%fKQkh6Y#Ck=~JBu;z6vOFXzd7O1mkt`yaC)8Gn>0Fhm zEI{|uQr0z1gk4W{mj*%4Z*00DBL5ko{4X}2{Dl0wAi#aSmq_r~FBHL|;}P&0k>OU! zhx64h5vSKwffV0W4JQs2dFBrfQx(B{AK=BGc`U!}S&BFnE6QSvw?`~m^}8j(4$IzQ z_WzjR?fD!VI8Aa=N;O96$f<JeDN}@@k24)dnpa7nV{o~|y480HWd%qi09M-w5HA7H z5t)dJA9OeU2(Ddz+nofIxgaM#sfN{v)}n+p872aEFyGb(<(TUTpJ(1Bv9RRP<lWbe zn*X9W;yA^EqlAv1#u2Gg|1wrNw~{@z1W#o_GFNuVYLs|BsZ*hkg_h`Il0YDiCHm+W zmS~Y0wwCC%sMd>IWzW@IV2KtfOm4MwFVU~FM5pwL+-yY-+$4mvEEjvjP+5JUm8n(w zTE>U0(q9W!VAi2soP~_07HUw%Pt_tTYxD^79a6Fw-(PjP4xwLxv3Ycv!%RV}m`xvC zX`nx*(H@IF+EJ)392Ul)-t@Oj>L>VGb7%C~V}eWde6yYkCcYR2>L5_BFiz*D#3I_* zY)|v0XvW#xv=Y0=d;t!!=&NUW2H8t2>2H>>rUwQga=@Hd8s$Z+x+rNk0%K7J*cGvn za#2GFTwHgcx}(hY&AoeJJ>OtvvdouZfGLkWz?5@JX6KrhfDJ0`xz(qU+f2hY)2ykx zl5dMrs#`m^OO;aljpVNpXHI7j?NBazjFr-P<5NZ{lysyym6ILI!i}auR#r=s8-sHH zo|F}x&aDr!mLdRfA3dBON<#lrL!uSm7=o9syd*hDuX`F0HkX``(5Ixonj|KOyUg3^ zQc-Q1zi|oXoEJ7t`z@l)r8HbVnV=3@R147(4T%Z?MF>|u+vhb+dmd}f?PMV8SW8Om zNGeF;<~ukE61hiT7Fejt`7XmU^|R{ev+p#`i$*Qly)%e2TjDu=LV)p<*h6u5gyTBv zF2X}pxW+%<Fj!P}AZas9RZ`k$Jvv1owwn8%W?{}x!+bkqQCghlz9l!;d?w_cXMXg@ z&=}JPT7tF@L2ahnMB72@q!wG|Y3@>;eRIVAvq#45Tg=WlQSFR|)0f>5G`p(9xM7}| zFKtPEbWZkN=1qLjD*3c&W=C5QZ78nOyIt7^bEIKqkTQs5B8y0Tx?-c7F3RU`pPOs` z_?hl<U&@p~CMd0Mfz5AN1#S&Vwsi0NvWloHbK|_KEOMjJm}q8E=E&9JuvOv6IZ8ov zcoQ8$o#cQM?=kPAi}LePW480inT%^k+4bRRjjowT_3NF_?RV~cwfUrD02;pIjR9GK zQO@U%q%4cq2SOIu>A-(AYe*|k@#n%-mt4P66m+?M)nmWXqWP-^>As_PEzQPQQFQR8 z8-h3Q39C3Q91oVz2*#A-KL%2bY;8!cmJ9uHA`|<v{z~0`eQ`+GHZb5=o_|mCd#>C8 z$NX`>3!Xc-34zzMQ(s0p^HbkPL0@}t>MK)QkhQHnsYONA8Y3sjLq95yD8o_vXX;;L z>_rtUVz~Yrx{&>y!BX_$%=h%m(WLsmNbc^@hvIY`rx=`G3p{Y^ZC06YKwy@l-|)Hh zU=6u>PjJFvP!kJ(Tc+sbM_EIjrY|G=W}4NvvWB>k^nM4`K&TNt=8t0byviN1Lph6= zm_yLKL?eam;`vUGWXllNQpvgH+$3sPb_yL=Bg|EjmK*vv&mK-$JqW8%=|ASK>2#&P z_Hr|Y5Dkgu7#^X*C_?v-?p6bh!n7?WmSW!JeSwnSm}M7T5((zV1Sgd@d05#6N@`iq zIof-m%Wyrh&Os_zmvwFpf)UBIy{<8BeDtovo%NaL&_|tBV$bJ-C;E$apFPY)zG1$1 z&owMVml>CDJKAdL5zE6EYkt$pYmLfF?wDG0`I8N*#DQu4-A7E6KcN`U27=18Fz;s6 zgRIKZJ=&bE;>8osoUL9Ryh=TbC>SSDx$a_ae4Sb3Y{(ciQKVJ&x*C=an(TMl4xLH2 zXX$$5{C?<{&`X7#bw|C!?@WU>(wf=M60Egk4C)t`yyBd`(C=(qFld4VoFf6R4+pHN zK8Ll6cJ>?zJRuIOK|)?8A%{uGgm6egv3W?S%i_2=V{%GzdHk`#X)(c}lhxAXtow#+ zFHp)}cHUdTEBD@=-@HTIVx!PQ#~t7^T8*<#^hS~|xc9~6%di^At;m{`IHO;U1JyJ& z?$6LV#Y%45gWjnIu3a5-`VNydN5;meS;L)mKjUK-hMMbbbJA&Cbq9~|S=gw!q$wS} z<Z(t^y7;u%;xGk;LG3lcOw_zt$NHvB?!ZTuJIo+vtIY)W*7UDg7nZYhgoJ`|`U@?# zf&SRW>>!$M`UNJWuIMmgl*gmkLk_ZS(?`c%lMZ(&XFK8NP#)0^vSl6vFEG>}Yt=qY z>WCarV-#iQR(@uObO3d9Zj~Ae<}6f(n;Hky?Oz`=r|lj-I0#^gmZN5;ee)19uN-uf zbLW7xnioz$Qqpv@afoy00q1WU<dahvrqv*^Tb#kb-RY_O47=@EAgz1AjGqJEU%$BD z#{P{%{LcENgC^i$Gs0h&&6#v8aM9Ug50ykMQMk~#qpD^cswS=IIHD-)jLMD@Eu?Zl zXzx^j#tYp#^O##HK)x^gH2Y8oBzw6P^DLtqvNE>|&pEgH8343To6masFPXZZ+i2fw zw(TOJh6NWV1zH#tgBTU7eP2E-U^0`E%lVvRweM3##v6R|Hc)r2ZWu6UP8uu_SKF^7 z5Ei+b&tX|(bW>KeN_C)b7q?VhC2@*pFT<#gaK20zQb%f_ppm8Xf&=AdHBgp?2g=0N zzUt06{THYVS>0fh!O|&%MP5GTWr9DpB_rmtxWJV%cw()<Th-`+9pNw^epR)x<&H5y zNn}p<5E>yvDADh1(g)ek#K;gD6diD^_G>B>y~3*2ri=>?y@k#|fr6r^y=jEkKl3E7 z4M}aqf+KgXac<4$1&vT`xA250AV##H0=5ek@I!)vK3Iwme$0oDmHS)WNy*wIdYTYj zZRu7LFxIS58JMfP!&x-K4>+HK()5vW=nSz9Me#w3T`4{giqU44ixK<NS-`KgQcF~+ z$)Xx~#$%3oPu5N7C1^%ShRb#_>rd!tunBaOeaO;`@Gg0VSi}FyYeUlc*jfuoTFFEd zOR8Z4RTBHrnM_v=qLS_KTIyGvYt1|?i!+C4y??`sV=b9MS0Ju6Q)C6T`W3;Z%o85d ziENh~l0#_RtCgzGELP8JHB9M!#^AHfT3W1T^h?P+q1$V+gEe9y%{FPzuSsRs@Ay-r z&&$%MWa*cg*GZ8R;SHL@d5gHczoSYe+a|;+l&uAZooROH4pP=g`GeNXPLfFzb`#S1 z2_-JE19Kg4B`^wb`OGw9drEbu!t~n%qeIJiU}$Ld55)5#)skz}?aZlPlQ8z#UJ#-| zYO^vmzd2P;V*j5ETWQQ}A;NIjCB|%xCEmF;jXrG6JdLv!xSAK@X@Sdl!B-26nk^;Q zowGGGn&>N2cRRN_tq77S`L(hZ^0u`V19Af$;OpSM*@-NJvG_<B4C7r?o87^iy*8Wb zMrpq6c67@_sMBrzt2>@@hy5J^v<IIiJ1y|!Q!YK$isdqQoTPDML_TG>d5CVZ8v5tF zwQ7lkRx1I6-#=R@`m)Md`q#Na+?08k)vz7fn~b?P7;2Kt8t}>IiMVUrKGxYujGZWb zLanz`MzcgG7IDuLahiX|7e$b)I}hh9p%{<(HOiH54&kp~Ytv~>ArTCn#S8~^$oQ)X zh^?`%yGTMs6NUtL_ntBL;MAmDP#8v#36b}%i_U$y`ln#i)B;*>S*Pvjco$ClL? z%=q~elnuXpj0WVh4c6?B5^b?x@W;C;BYJ#|yQV(-^BV8xS@qdyP_7}XGtF%KKWAjn zLectNCDB|O$s?N`pgU^fn(!runKLO{ZL*IDdN#goZ=z)9FDy|a4b+7tIf&rq{hz40 z&UP~#62@?Yv#|LPJJk&HQ3e)?F*x^tH_b5TT8Z=h%QKll3XntrekU{W1ucz%R_!vl zu6JTwtI@B2wku%k4*@aLHLf+aS<jd)!%M#cTQ)o{<ty6y;vrvlB!}@s{CO0_`ltZs z3fJ>dHs*_rgZ{Wh2W%`KXEPa`u}qU^8Nd`Gtzm`f-1-zBi0iySJ$H?3COIw5Sts}8 z<+Vm%m)h*yTBpLCW?Q^x1F!Vd+Cd-yYm=~2?%cW>C+BZ7&rJ<xIqNRtBg?sU36IuH zGk8uOY8JK)$4P80(iq7HrP*8qcI&NRs5o4XL)iMFv+i5c$~Hy3oMB$wp_-Th?yNKL zAangr28eU(Pbpw+wfW(1ey17vQuDUsxUj8DIfV^QQ0G0jGyEy5^P3)CLis=cawvai z-5gx4GVHJ%DF#_>{WkI2`jH<!Izhz8W}oAaF^s~#^M*_X2XtOm#D*kvo)l8G*-}>+ z<t5PsS#I^dD)cT0YpM^@RaIwOUV(>b9w~ZgNut<T7H`U!4Nfz|w82YY^r-kX#J6>( zRG;4bHiKMr_Jpiv$aIiF9yPwvac%awnv<K8gmQS^5Q443>2~cp8C&!2=C}j(2#tMi zjAaHm5bPpSUwa%RYp-#*{ngfz;(tXArj2S*S=&8{L(57D#>Sy>ye}&aBu|6{WXYoR zJy=+9jhe&f&&Pd^I=}K3&D!?hXM~&KKNL|-rI@I}J}9IBm%CT4Pr(h2lA`RU!W}#z zTt1O71J@X3uEEEm16dpYC#BMwiUd{3p3PQWl4fnzvSl_Q9@M}hNeE;-!hE}nWGGc1 zPd%s4GDneKLvjGcS1HB`9XaviNE~IJ5)rQKQ@w;(FbQa{p*Dyv{NvkHXAi;5a-v(C z`r^gH3Wfzd%G^(xROzgOnu~kNc%v|Y{{$u`D4$wu6mDT|WDAsPz{x$PmVRmi?cZF+ z-U3yHJ4XL3ya%Jx{3B1Os@RU`W_KkhwTO`EP<`_mS~KR8U+7dTIE{Ja&Tt#Gon$nl zE(dWJp-%nLFGR6dIAy<_TXIXDnE(n>ay2-K8OIy5nAx_qmLyOgtQ6Fj%*-=qe@HKi z0nCq$syuW4!}7)5RiQ;?m+>J6id0FQbux>KbU4=#b?)3Fg%G{}A@pSk=NYO@J@Gx( z+{gD5$inzGt&2vIBM=9%&Ys$We)D#=;$X>?T(d~*H3&8|nSsg$L4-o()4BCDnT9d8 zE_0<UD}u4Lw;fd;UFHK1Sw-$AMSfUDn)r(v5hd^Sk`)Y2*Ymsk6l$eaD9LZJB+_ZC z?#wseq9VdWMx##Wq_ehmu!z%RL@#$oFo~*F_DyBDl?uh~G*>`&P_=OS)^ylwt2<5* zvwCk}v{^^0RD(Mo4Ce-R%T811{Z?J%>mVhkZSqsZUab`AH#ms$5NI#mLjx`}s<cDr zd(bT?x#j~c4Ean`t;tA{$e7DliznxUyYchy8+U-d7c;x*N+iTJseQy>ob@d<%w|L( zocFxQ+iwIN$`Lbg(^wA>sk1CDaCHq1dn;88aoAtv)vqavty0V_rw}n1A$&%RTW^fp zY)}2T(vF=bG5SC~B*4=@Q8ksK&3H(1Umvsi=+-mqUO_!8b(bJ>RT_kck`^w4=oz2- zwmQq2dD6<s{fq(TOjQ^`MAUW8j=)Q)pKZQtBiUBnNhi3h<-*+j`^bGNgVvX9{sEGR zNO&hvNz2S>)<X=Yal0`ZAdBD?=G#SKJjZ;G*RVweNW@0_IHN=HbIvdd$%?KtCDDXl zS-puTv{HE}Vwupja?ML6W68l~ZcsT0fl8=k*}`^H<U@)jw_TZWQdA3@6ACGl0(xdK zv6O82hzlWrpNr9j5G_^2VwJ3Rizru3uw+-GLsw+ulN!^ZTID%+Zm>hOs(rtPvK;BG z{Y=ms-NO?H{RW<b%v>f<@R!l@1ap~PGv8k0k3-q__{PCC@7C5Fh^ikPxV*RPmYM_6 z0kfvSzBw?k$ERj&%~qlI8?ow$vto~Q!31rW=wT=8P}xDGS$oy?u<(xFOYiHeWgsP# zT)aFG=O0)ID^^KfcN36{h|5_lk9ol<i^Xs#!VJ1=)5TyRo4{4=Mm$HcD9|-JJ&<fh zkv<f^_enN#g)O(Tku&Sh7?;YX7>2Erhw1%VG`GJQ^J0PAl8jr?Yx*E!U4=K2it(Ud zQ6rhrtZtLI1dW*3;fTHQ-7(GY#w6b|7=sK8vsi6UF!k;QP1I`7T{{)D%r}j9f6JY_ z`axh=-H>^}`P?qy;<rl2GrJD5de^xKlln23Oy<F+EPK<&BrJD#Zc35s&LNx|Ji}&J zXm_K>er7j3=la1cXR(2P^}~G5U@)^Y9R^W~(Yf&ei6pNG>XS)n>Z@{y@SU?&+x_PP zwi4TIm{g4?h9h`GI^_u<CDQ?3teJ-(%{L@AWgch0dr;Ksu;h1GD-v@Vd?KD%8=f^m z;~-ZoK9U+x<NkT(4r1pAmLrJ72_nawwuDKdgr0<*Fp4!2$;P1$QjoiH>ccL{tvDS( zC7i=<#ERSNqK5joFl%3Dof%|KBvEU5qQ@ea%d`kN0xVuIHgfZRyPgfKsk;4%Cssd! zRZy@kcG~O{Xfb=dB)TDUpTCpV$~J|+y5e-hioLf6Tpsh<?=bFK?P5~WABz$q<20L1 zgK^Njk^zL6F8vdO>o_n_hSP(E;qsV|s#j?^8BAB(5Hf@{N#z(eFM>tMXu;~1uk&K# zE;Rzpm%)M=;(^<h1j!5clYZyCd5BydPFZnUI5nru$8oe_LALrZ21JRzsDzD_MOjK( zk00E|rj4;t{uou#?P7|O!p$-N?LHWDp|9zbIyggai<?WN4itPete-Y-G=orT;ji9@ zLZ=ymGJHhw=e8|l=poY$b}_LL$-0_PXX|5f%|!A;LiZHb1)@|=P1CS_a;kCA%$JSh zxHn`U3rtF09;IJZvp#yJae2*p+iYVjBMKEb-&RqNfxq_i50rAjaJMzrB+u3l!Dye9 ziMZoyHmr2-3XD;W@iY-=yLLglF9DNcS7U9=rn>O${@GT2SY*Q<WH6{6fu7s|*TK2< zT3P#Nn0GR%^BYE+f1!axn_2WK8jB`q6;Wudt(Y3NX71&$7WkD1)-24lgPvS-^RHD$ z_24>}7pOi8US|%YNHQuI9Dx}gPKACg9BY2xSRbtn$9iuY9oSBsmKgV3c(wEn=%-nK zD|%o2NhvE{vveJc2sn-K3I^M)_Ob0-oNJyT-AUD_7&*4H{_58PGyIvmsB7>#GLE9O zM_%Yt+6~?L-bud7E~=~mV~m!R6?=_4{MCo0O}Rex{k}23X2mR8`5ssCbIoY$sMFI9 zV=R9en4=k(1bGJ`JxbOSr0X_SY1>&{IxnuM;$(R1rZhlZsNjrRzXB)?&li~var z?B}%klDLWDf^4)nO#Q>nX4L#{frSueKHj{6e&Bw?L>`d{`ZHFsWS3ZmQoc`R>p!Zt z)MWNo*@Q0+(@KUAHQ#)n2!1ZmKjktmg>5tXOlEwvo@l;@bE{CFH1qfBRZ%~VD0^FK zYxkW_5R7B$+uR~XI@m1DA|0`t2h;L9#E9HeM)1wN?ybHta2K0&yD%+>v34#tOPGE6 z`4T2CtnhJRUgKcr&fU(Poo6zxgN->hy>T#X%%RSme-YWd)|AY6<Q>vM0lNYNQ&yn% zUR-P#5K5nU)Yx-dWQHOQ5Jo1y$g%9Mk}!8IeeMr47nESfX>;2=StXRpPm!JqVOg!O zss1JtXWbeChf1w%MT>HGxYweE6iHzp10k|K23P|lvUm(HB!wrCOfHOAC+sN2t35LB zOh)u5<f*#!IgOW4DXvp=1(w6XCDf~{2e47@U+w>B9syRTR=6tT`Fqj2nANt5guo2m zFRo1DZ{oTuaTy*M?|e>p@X=?|N4fNYq|h*m3`rtjb3S)K(tr~W*Ak!p*pjtM&|QE` z1g;w|3YQ_Trwmq5RfH^6ge+BrELDUoRfH^6gsiVr1gXj)W9({XO@BJWxitVf8QE40 zLOB<V*u~}OEb%~M+|m&GzUoKm-f$<4BQ9%Yue(_y!71{a^buyY_Xq#|XDDPs%>2Ws z#?1K7`D%?yj@5<1AMJ1LLKc%*@PGU7yMNKNXMh&qIPd`w1JXJYm<B8WRsu!9-9SC? zFz__+B5(jW4s-yHF5&^nKrT=M+zs3V+z<Q!*a;j0jsd5DGl2bbjG6(Xfr&seun_n< zPy*Z!JPqsx{seRYgCIwZ1g-=!fTchQPzP)SegOOo_$_c4I0bY7age!&1CxR40S|CH zPzG!S?gbtLegW(T4g>E39l%IX`-wm@a3j$7_kLoU_KWm1ZQ4y~+M(s#*}g5UJIHUI zPSYM7*7F_qSY1$D>MeBZ<?cJYy4$<HSa+`~FZ8-sSC+4FS5%g-@>W$%;b7krZdIkX zK=(%axhGU<{MY7`8>NNrvT{ksyGmSfD<~6()x~9nZqEk2sJu*h8hXL)rCx%Nv^H*R zh4Ps~G%44(vEA{?E4*bY)KyihDvK-hDHR(epUO-M>aj|vX=}79ZIxE8Rcc=TP0<Rq zQvT7GTA603_bVh>ZDN^GT57!tV<JYH(52a8w3uj@Ju@@2pZumLX&x2Wo$Og2>(H)C zO3L#<8gjb@-_RT@i&pZ}wDlG1`8fyy(bwVN;ozTqYEO+#*R)Fkeo@gjd%u`iNB_71 z@dF1rU4t(gk}&k*OA?0-A2D*&=rQiGmyR1h;j+soUUB85$yZIeI_a8gr%szb<GSRO znW?j8U;nkV^c&`6WX_$JHUGw&7Gy76<XOBVXDJptm*;=|=37?WdfUo^+gBBOSKm=o zTykgWnzHhWyDF=6W9_>28}9zb#_CO*6`47+OuE!lUR<VoD=E`WTBf!{Tgcx9+EndY zS}cRN1**Im-riy7mR8NJ^m;X(IbJ=tpwv+B^CI5UOH0dFN#shSOfO#Jb$cr-%PZZQ zHjvI;x?oXGj^!esTF(51^CCXAj78b$^B4BGESZrsb=ttV^fGrrMMY`xssg>3AyZUP z<z7?3uq?n`*S%{hbQ!Xx<pm7gBCmUnJDhiE@$Hobl^fi})VZ?KyGk$JFeT1Y>Mf}9 zGO)|^f>p#MMnvkDSGlW<ii+||e7pr~+^Z@4n(|67Y4Ey6m0*f0Jmr`2O&u6_l{>ws z7zSx)=geOaF>~~y;wpDRRh4(m?WG&sg+^s@*&XgOl3FXppd!U(#d>i;Y4P1E`M9ML zo;e~F_7c;5yKx8K?hWNeWn@{WxaaF`g03mA(%q%ScX~-(s#EE$GD>xK`D*v7g3?mS zjFyrzUA3xwO@*4`6R%!XT6u+gwNbW8wW*rn1wDl-tI{itRXUaDzw*o|EzK?{E>m@v zdS5H`R@1wz+_<C2T~$%Aij{)k41fZrb3}thw%0X%+N-<nUaRw#EVbHOFQU-pWvjeX zzIuB|K2o+M$zu*FN%?v*C=B^un=JlDnOb!iIXxlVMc#r6tF)wZ?R8&L$92UK5mmqS z#G7%!cvX7gm&BVc@hS{P+uGtv-6$yS=^*Jzm4TFtIdOruzpcDXmhGz<II?=Hg|)j} z*Q7|io_eeGlzC89PInc0*A}nx_Jj?!k#~Is^M*}9TBc`as&>9cwU0rLp)hM0cEx%T zdqSa%f;;<$zi_*RA{7?s1r%YR)#VY>Qce0w?_GwsN(v*Rd`W15p#xdT))X_L7<AI# zGTe<aqe>cZUBTaR%G35qstwOO?!9I7T6x(TZ<$UVB&=$~^M);`yu*-yRjR=yteQ`& zS;TaiuobdCcdtZ}ge-4fHG(xQyLeS)c~$vp-JM&kYB^`pr0(`uU@dwqPg)%FVak*# z+AQ|&J1SYt$_iMKjj}t-%GZ@$PalSwFjLm(v2k&1q7rPTTO#x0<g^R2zWR;gT^RfF zdm!SyiFdUb;*JiC?svpDyWh7(yu<A4cIU1@_xpDu-eYQN?y0G*VMDgvQ*+OjnuLD+ z*patx-AaLyl4?9P^_oMQczLoXuZI1WP1)nACwuqAn)(`IX>7|yMMVxr?D~p|brlu8 z_G7&NzyG<lzW*kIA6ftU`ke1O3ry+D{?%z;{MS2tt=97|O8aX6B2(C+_56#5xcycB zh2y*bzwdwT3;pj#!{h(q5fD||{SSfXuk;J|pggxk_56#D`fC5e@y|D=|6^`{Z3akA z3H%G^C|^DAE)ntm5B&Ou|7x}E3FXpy-mSN&D47H`wOf33TkrX1eM6)F-llKex9!{a zf9Jd3d*J&IKJ@TEJo1k}_~E15AKUTx6Hor=sUQE3pFI83pZ(J_KmWxqfA#Fn=bnGz z*S~r3rQiN;SM%;Ydw<{3x^Mr1mk<8o&?|?Jyn6JtKfeCPu{Ym(`}jZq>75fN-+k}Y zzx?@qv+Z94r~mDP58FTb_m4Y1Idiu2)4zPy#pTGq`9O5x1J74F5dCM@|35qbzq$SY z+JW@K{^~&bpI!f~teI=p%&Zd9gjUFJvOAlfTV6Ks)3UR#E-bv77k-{>O-lzj6LXGJ zM`vwe`P%OHMVywzImcVUk<<#1Zrov1>6&(<QL56o5nNf)O0TFa7MetMLFK9<o^!po zR~j5t#qY*~GWAM6lD<Z|lBPylk`7QtybY3u#Fw}dN6RVDjmkniB)!UF^|rLgsH_UP z<#`LsyrGY!pwZ%-U0$YqbBxflK$o~0@if9~gp)8D{u+n;5RD~|qiOlN99<oH#C=(n zw{p?#C7cuH_Z*Ui;(_0Sf+{_oGv-=I4i!d)a<jgzWVCE(N(Fa#Zzx}%t}V;STr&0A zDH#hOKaeL`QvwP?c_<b&wAzO%Q*#=CcAz<E6&i;&qN!*xX*hm!7A;(~Z0UGy3TIyV z4%3sS+^&+reNCZqzlFRuaH?3dq`X`*;Fo1R{+IsNT$HXIhC^v1_TlT;X^TN)A3A?h zkaeNtX&N+m^$dT%0qstH;qQHY{9hc`+y7vM|Bol6X)git3&+1V!hhEEG%XE?^zWPh zdoz3cAC8DG@qV7#+dndY@lTy?`OAAO@8NRv&1cv3R=5lKfBdxz`;SUb(^3HWT`2xl z^LqRDE$3%9_V({vzB?Cwx&Kc+J#~9A;{8~k_9|b}6Yd)k?|t)|p5Hsa$aLQRdYbkj zAir>ZBmJ+sIZe9;i1gppryTXS_V$nL*F@;USBGfC;q?2K?~0NO$CrF(miG4V8~^$Z zz5OHem-q{7zuf=oExrBw_UHKT_4e<Z{!8Ega{r~<d;9k-|I1JG_U}6{zx^Z2U*q?O zCwuz5Z#fqHtamzn{fl<@_U~KI0SD5wrJs^X=r>3MojVc!>izt0p32|GQ&|!<&s*lL zgt#=vqLj_iD@!xiLc4)ag`Y0mhdDx04|5>O?0E&n`rPu$94I-ZUTbI6zNgJmypm8b zw#R?6K}3&8G^?PjuoMj96G=6@ywE81&V^XJ5Sk64-_kOLVn3%6QZdB99CllX;qZc@ z7kCTSdcWZQm!4Ftg!43Ql0B!?3odbKG&x8?(hCbA7K8uvi;85TR7l)8<!jbZq6Nie zWZy1jwbFsHBXz%C(#X*ZEk}505=Y9rbVG$#n`QYHK*g*Oq##}U9hg(8msadkf$Qu` z!_>R(7W^M7e*=<zSs3Zivh2&sic|{~X0Bfal11&wPBAgY*eTrwy<d->UzOp7hJJ^) z(nEEn>)w|f1UFHnFHL(gIt%)yVs2=UsdtN!af>R6N2;LxK6<|NfDkslh4af`eF+6m z)0!jQ!9K$7ITAO0jz`lHq%{_0X3P5tN(1MlxKNE5FdyxD`_j@X0$BW%S@IR)qI^x> zyE!eh<x3T@LwX~k^goMeuceCoIv?ET`}REAT8$y?O!NZihau7+qv_X_ImC15+au{^ zg*g?)WmY%e6eSsE_E0u+bm3l9rE9w+&o6pt3oZ~NPph-%6&HHv6cto1EzcH8@eLbv zueSUA=`dO!SN&kk8ci#(=UOyz)dKmp#fG<XgU4H`xH7N_RC$>_CDPVQi&xzl8mB*r zXq(Ugqj7T7_*7`$Qn*y<Rchq&raf$1qL(f!TL+S>{aBS?iP!3mTf-#?^-i5iIkYIy zvkydkGkwAIZ-|;(YE%_T+BX=hS9>d&X@8DhFekg9!fHo)VvMc3EtZyt8%Q%FL(vv# z)_jt-m-$7!IlWy7(<b>ZP|O!=%4zS*IFa1D*?m7zHOeWzo6==yb4tsryrBtvuQggi z>ruM)a71ku8G41G%jkWeSExKKMrK~bDzG86%1Nf!ErdI}rlO$I+g;n--Y%5-n3OSM z9OV{N77Jr0UArlB$->M9oCgX^IV_dgmcUk!bT#ddR-D2`tF7<Lq%A_7EAtph04cpH zgwBAy-GGlqoBj9i|LzvpB?|HQ$<v}xh05y+JtH0nS_#&3!JqgG{P*v_Ti~m<z`{SL z{pRPxewXpD<I>dFDt#B-`T)nMV2ubY{4f4woL&rs$D}RvZs(Z@^aBP0$f0Qcfmk3O zaD<-XCf`y7@e`h0*iX`xxbj3Rhsr~yi?|I2E((F<Jr)r6>41EvhrZ{8zFFW^oFyUm zoY0eHTBV=QQ}SjxR_Uza=>}MEkw-%21CX*xJ)}G}fRwp5^xVQz{C$A<*8x%<xd3<t z@Pp9zcAiqc#{tRjM}UNT4v;z>0>u9fK>QPF6ltGuoAKJcHblus#4r3Eeullm-+iBb z{ri6ZweT1652y2A@9DbW&#J5Yg1`S7ZE<0ygjK%_6UF~))L&|G!66XZ$uBqr-2Zjj zfSUY2J`{?Ef`>)h9gnkNt=zI<%h*uoJo%3Gvi%9`S^L8iUGkQ;sYX4YB7F0Xw|2NK z?=SqVMfO#GX`$z{Uom`oDEv;szw+3r$A)YF@|gM9%~oO&f4kG)v|Ysz-BF9*y7eu$ zcH3JeZ(SP^(t52udhAappr>84$%<L}Zx-!tPAFt}4gW&KztLga@bq3O{H@<o&c0<8 zd)47zQ6Nog|1eFf_$W=QADON_Nd6LDp3>KX=g3d?)=o1`;TQ*b%AWlwPua^IJY^Ce ze?Lv_#ZU7T9HXA+5T3X26r5%}&tW{f{+y-_=ed{X2%h)y6kMT@=V+c8Jjd`n@h@qb zo99zJ$MSsURGP91=Hj`YZ;j^$9_{a?X?OEH!BYm?ah^e*2YDWXzWY^x;iK><NmuF= zT9h<tpA!21!H?6l?*iL^dx3hO4yXav0~J6Ka0}o8vVd7YGB6ED0wx0!f$@MF7zrc- z34jZT2kb!Sztbmx2}t-8JdXi~fxW<sz%#((z@xw;z&2nbPyzI}_w>2+=@jadL7(4y z#b1Zbp`VPADB?+6d4_+|PVRo+k#0QiPsT~)ucpF^-~N%s&+_Cfjr9Hxzk4$Nw)lss zmkZ@sGN!|sN4^W6LqL8q7E^(*12QhY4?GLJ27C+*reTtRg@9a?3CEd<Up}x7cmVhn sa1{7=KrVY;4P*nQ!2j#Nzb3L0-REZu{lfJw?Z8eMa0{>$=sSM?C)~1m4*&oF literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/setuptools/cli-64.exe b/venv/lib/python3.7/site-packages/setuptools/cli-64.exe new file mode 100644 index 0000000000000000000000000000000000000000..675e6bf3743f3d3011c238657e7128ee9960ef7f GIT binary patch literal 74752 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 &sjKl@1{;unAiW2w^OujNoW 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/setuptools/cli.exe b/venv/lib/python3.7/site-packages/setuptools/cli.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/setuptools/command/__init__.py b/venv/lib/python3.7/site-packages/setuptools/command/__init__.py new file mode 100644 index 0000000..fe619e2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/__init__.py @@ -0,0 +1,18 @@ +__all__ = [ + 'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop', + 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', + 'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts', + 'register', 'bdist_wininst', 'upload_docs', 'upload', 'build_clib', + 'dist_info', +] + +from distutils.command.bdist import bdist +import sys + +from setuptools.command import install_scripts + +if 'egg' not in bdist.format_commands: + bdist.format_command['egg'] = ('bdist_egg', "Python .egg file") + bdist.format_commands.append('egg') + +del bdist, sys diff --git a/venv/lib/python3.7/site-packages/setuptools/command/alias.py b/venv/lib/python3.7/site-packages/setuptools/command/alias.py new file mode 100644 index 0000000..4532b1c --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/alias.py @@ -0,0 +1,80 @@ +from distutils.errors import DistutilsOptionError + +from setuptools.extern.six.moves import map + +from setuptools.command.setopt import edit_config, option_base, config_file + + +def shquote(arg): + """Quote an argument for later parsing by shlex.split()""" + for c in '"', "'", "\\", "#": + if c in arg: + return repr(arg) + if arg.split() != [arg]: + return repr(arg) + return arg + + +class alias(option_base): + """Define a shortcut that invokes one or more commands""" + + description = "define a shortcut to invoke one or more commands" + command_consumes_arguments = True + + user_options = [ + ('remove', 'r', 'remove (unset) the alias'), + ] + option_base.user_options + + boolean_options = option_base.boolean_options + ['remove'] + + def initialize_options(self): + option_base.initialize_options(self) + self.args = None + self.remove = None + + def finalize_options(self): + option_base.finalize_options(self) + if self.remove and len(self.args) != 1: + raise DistutilsOptionError( + "Must specify exactly one argument (the alias name) when " + "using --remove" + ) + + def run(self): + aliases = self.distribution.get_option_dict('aliases') + + if not self.args: + print("Command Aliases") + print("---------------") + for alias in aliases: + print("setup.py alias", format_alias(alias, aliases)) + return + + elif len(self.args) == 1: + alias, = self.args + if self.remove: + command = None + elif alias in aliases: + print("setup.py alias", format_alias(alias, aliases)) + return + else: + print("No alias definition found for %r" % alias) + return + else: + alias = self.args[0] + command = ' '.join(map(shquote, self.args[1:])) + + edit_config(self.filename, {'aliases': {alias: command}}, self.dry_run) + + +def format_alias(name, aliases): + source, command = aliases[name] + if source == config_file('global'): + source = '--global-config ' + elif source == config_file('user'): + source = '--user-config ' + elif source == config_file('local'): + source = '' + else: + source = '--filename=%r' % source + return source + name + ' ' + command diff --git a/venv/lib/python3.7/site-packages/setuptools/command/bdist_egg.py b/venv/lib/python3.7/site-packages/setuptools/command/bdist_egg.py new file mode 100644 index 0000000..9f8df91 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/bdist_egg.py @@ -0,0 +1,502 @@ +"""setuptools.command.bdist_egg + +Build .egg distributions""" + +from distutils.errors import DistutilsSetupError +from distutils.dir_util import remove_tree, mkpath +from distutils import log +from types import CodeType +import sys +import os +import re +import textwrap +import marshal + +from setuptools.extern import six + +from pkg_resources import get_build_platform, Distribution, ensure_directory +from pkg_resources import EntryPoint +from setuptools.extension import Library +from setuptools import Command + +try: + # Python 2.7 or >=3.2 + from sysconfig import get_path, get_python_version + + def _get_purelib(): + return get_path("purelib") +except ImportError: + from distutils.sysconfig import get_python_lib, get_python_version + + def _get_purelib(): + return get_python_lib(False) + + +def strip_module(filename): + if '.' in filename: + filename = os.path.splitext(filename)[0] + if filename.endswith('module'): + filename = filename[:-6] + return filename + + +def sorted_walk(dir): + """Do os.walk in a reproducible way, + independent of indeterministic filesystem readdir order + """ + for base, dirs, files in os.walk(dir): + dirs.sort() + files.sort() + yield base, dirs, files + + +def write_stub(resource, pyfile): + _stub_template = textwrap.dedent(""" + def __bootstrap__(): + global __bootstrap__, __loader__, __file__ + import sys, pkg_resources, imp + __file__ = pkg_resources.resource_filename(__name__, %r) + __loader__ = None; del __bootstrap__, __loader__ + imp.load_dynamic(__name__,__file__) + __bootstrap__() + """).lstrip() + with open(pyfile, 'w') as f: + f.write(_stub_template % resource) + + +class bdist_egg(Command): + description = "create an \"egg\" distribution" + + user_options = [ + ('bdist-dir=', 'b', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', "platform name to embed in generated filenames " + "(default: %s)" % get_build_platform()), + ('exclude-source-files', None, + "remove all .py files from the generated egg"), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ] + + boolean_options = [ + 'keep-temp', 'skip-build', 'exclude-source-files' + ] + + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None + self.keep_temp = 0 + self.dist_dir = None + self.skip_build = 0 + self.egg_output = None + self.exclude_source_files = None + + def finalize_options(self): + ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info") + self.egg_info = ei_cmd.egg_info + + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'egg') + + if self.plat_name is None: + self.plat_name = get_build_platform() + + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + + if self.egg_output is None: + + # Compute filename of the output egg + basename = Distribution( + None, None, ei_cmd.egg_name, ei_cmd.egg_version, + get_python_version(), + self.distribution.has_ext_modules() and self.plat_name + ).egg_name() + + self.egg_output = os.path.join(self.dist_dir, basename + '.egg') + + def do_install_data(self): + # Hack for packages that install data to install's --install-lib + self.get_finalized_command('install').install_lib = self.bdist_dir + + site_packages = os.path.normcase(os.path.realpath(_get_purelib())) + old, self.distribution.data_files = self.distribution.data_files, [] + + for item in old: + if isinstance(item, tuple) and len(item) == 2: + if os.path.isabs(item[0]): + realpath = os.path.realpath(item[0]) + normalized = os.path.normcase(realpath) + if normalized == site_packages or normalized.startswith( + site_packages + os.sep + ): + item = realpath[len(site_packages) + 1:], item[1] + # XXX else: raise ??? + self.distribution.data_files.append(item) + + try: + log.info("installing package data to %s", self.bdist_dir) + self.call_command('install_data', force=0, root=None) + finally: + self.distribution.data_files = old + + def get_outputs(self): + return [self.egg_output] + + def call_command(self, cmdname, **kw): + """Invoke reinitialized command `cmdname` with keyword args""" + for dirname in INSTALL_DIRECTORY_ATTRS: + kw.setdefault(dirname, self.bdist_dir) + kw.setdefault('skip_build', self.skip_build) + kw.setdefault('dry_run', self.dry_run) + cmd = self.reinitialize_command(cmdname, **kw) + self.run_command(cmdname) + return cmd + + def run(self): + # Generate metadata first + self.run_command("egg_info") + # We run install_lib before install_data, because some data hacks + # pull their data path from the install_lib command. + log.info("installing library code to %s", self.bdist_dir) + instcmd = self.get_finalized_command('install') + old_root = instcmd.root + instcmd.root = None + if self.distribution.has_c_libraries() and not self.skip_build: + self.run_command('build_clib') + cmd = self.call_command('install_lib', warn_dir=0) + instcmd.root = old_root + + all_outputs, ext_outputs = self.get_ext_outputs() + self.stubs = [] + to_compile = [] + for (p, ext_name) in enumerate(ext_outputs): + filename, ext = os.path.splitext(ext_name) + pyfile = os.path.join(self.bdist_dir, strip_module(filename) + + '.py') + self.stubs.append(pyfile) + log.info("creating stub loader for %s", ext_name) + if not self.dry_run: + write_stub(os.path.basename(ext_name), pyfile) + to_compile.append(pyfile) + ext_outputs[p] = ext_name.replace(os.sep, '/') + + if to_compile: + cmd.byte_compile(to_compile) + if self.distribution.data_files: + self.do_install_data() + + # Make the EGG-INFO directory + archive_root = self.bdist_dir + egg_info = os.path.join(archive_root, 'EGG-INFO') + self.mkpath(egg_info) + if self.distribution.scripts: + script_dir = os.path.join(egg_info, 'scripts') + log.info("installing scripts to %s", script_dir) + self.call_command('install_scripts', install_dir=script_dir, + no_ep=1) + + self.copy_metadata_to(egg_info) + native_libs = os.path.join(egg_info, "native_libs.txt") + if all_outputs: + log.info("writing %s", native_libs) + if not self.dry_run: + ensure_directory(native_libs) + libs_file = open(native_libs, 'wt') + libs_file.write('\n'.join(all_outputs)) + libs_file.write('\n') + libs_file.close() + elif os.path.isfile(native_libs): + log.info("removing %s", native_libs) + if not self.dry_run: + os.unlink(native_libs) + + write_safety_flag( + os.path.join(archive_root, 'EGG-INFO'), self.zip_safe() + ) + + if os.path.exists(os.path.join(self.egg_info, 'depends.txt')): + log.warn( + "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" + "Use the install_requires/extras_require setup() args instead." + ) + + if self.exclude_source_files: + self.zap_pyfiles() + + # Make the archive + make_zipfile(self.egg_output, archive_root, verbose=self.verbose, + dry_run=self.dry_run, mode=self.gen_header()) + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) + + # Add to 'Distribution.dist_files' so that the "upload" command works + getattr(self.distribution, 'dist_files', []).append( + ('bdist_egg', get_python_version(), self.egg_output)) + + def zap_pyfiles(self): + log.info("Removing .py files from temporary directory") + for base, dirs, files in walk_egg(self.bdist_dir): + for name in files: + path = os.path.join(base, name) + + if name.endswith('.py'): + log.debug("Deleting %s", path) + os.unlink(path) + + if base.endswith('__pycache__'): + path_old = path + + pattern = r'(?P<name>.+)\.(?P<magic>[^.]+)\.pyc' + m = re.match(pattern, name) + path_new = os.path.join( + base, os.pardir, m.group('name') + '.pyc') + log.info( + "Renaming file from [%s] to [%s]" + % (path_old, path_new)) + try: + os.remove(path_new) + except OSError: + pass + os.rename(path_old, path_new) + + def zip_safe(self): + safe = getattr(self.distribution, 'zip_safe', None) + if safe is not None: + return safe + log.warn("zip_safe flag not set; analyzing archive contents...") + return analyze_egg(self.bdist_dir, self.stubs) + + def gen_header(self): + epm = EntryPoint.parse_map(self.distribution.entry_points or '') + ep = epm.get('setuptools.installation', {}).get('eggsecutable') + if ep is None: + return 'w' # not an eggsecutable, do it the usual way. + + if not ep.attrs or ep.extras: + raise DistutilsSetupError( + "eggsecutable entry point (%r) cannot have 'extras' " + "or refer to a module" % (ep,) + ) + + pyver = sys.version[:3] + pkg = ep.module_name + full = '.'.join(ep.attrs) + base = ep.attrs[0] + basename = os.path.basename(self.egg_output) + + header = ( + "#!/bin/sh\n" + 'if [ `basename $0` = "%(basename)s" ]\n' + 'then exec python%(pyver)s -c "' + "import sys, os; sys.path.insert(0, os.path.abspath('$0')); " + "from %(pkg)s import %(base)s; sys.exit(%(full)s())" + '" "$@"\n' + 'else\n' + ' echo $0 is not the correct name for this egg file.\n' + ' echo Please rename it back to %(basename)s and try again.\n' + ' exec false\n' + 'fi\n' + ) % locals() + + if not self.dry_run: + mkpath(os.path.dirname(self.egg_output), dry_run=self.dry_run) + f = open(self.egg_output, 'w') + f.write(header) + f.close() + return 'a' + + def copy_metadata_to(self, target_dir): + "Copy metadata (egg info) to the target_dir" + # normalize the path (so that a forward-slash in egg_info will + # match using startswith below) + norm_egg_info = os.path.normpath(self.egg_info) + prefix = os.path.join(norm_egg_info, '') + for path in self.ei_cmd.filelist.files: + if path.startswith(prefix): + target = os.path.join(target_dir, path[len(prefix):]) + ensure_directory(target) + self.copy_file(path, target) + + def get_ext_outputs(self): + """Get a list of relative paths to C extensions in the output distro""" + + all_outputs = [] + ext_outputs = [] + + paths = {self.bdist_dir: ''} + for base, dirs, files in sorted_walk(self.bdist_dir): + for filename in files: + if os.path.splitext(filename)[1].lower() in NATIVE_EXTENSIONS: + all_outputs.append(paths[base] + filename) + for filename in dirs: + paths[os.path.join(base, filename)] = (paths[base] + + filename + '/') + + if self.distribution.has_ext_modules(): + build_cmd = self.get_finalized_command('build_ext') + for ext in build_cmd.extensions: + if isinstance(ext, Library): + continue + fullname = build_cmd.get_ext_fullname(ext.name) + filename = build_cmd.get_ext_filename(fullname) + if not os.path.basename(filename).startswith('dl-'): + if os.path.exists(os.path.join(self.bdist_dir, filename)): + ext_outputs.append(filename) + + return all_outputs, ext_outputs + + +NATIVE_EXTENSIONS = dict.fromkeys('.dll .so .dylib .pyd'.split()) + + +def walk_egg(egg_dir): + """Walk an unpacked egg's contents, skipping the metadata directory""" + walker = sorted_walk(egg_dir) + base, dirs, files = next(walker) + if 'EGG-INFO' in dirs: + dirs.remove('EGG-INFO') + yield base, dirs, files + for bdf in walker: + yield bdf + + +def analyze_egg(egg_dir, stubs): + # check for existing flag in EGG-INFO + for flag, fn in safety_flags.items(): + if os.path.exists(os.path.join(egg_dir, 'EGG-INFO', fn)): + return flag + if not can_scan(): + return False + safe = True + for base, dirs, files in walk_egg(egg_dir): + for name in files: + if name.endswith('.py') or name.endswith('.pyw'): + continue + elif name.endswith('.pyc') or name.endswith('.pyo'): + # always scan, even if we already know we're not safe + safe = scan_module(egg_dir, base, name, stubs) and safe + return safe + + +def write_safety_flag(egg_dir, safe): + # Write or remove zip safety flag file(s) + for flag, fn in safety_flags.items(): + fn = os.path.join(egg_dir, fn) + if os.path.exists(fn): + if safe is None or bool(safe) != flag: + os.unlink(fn) + elif safe is not None and bool(safe) == flag: + f = open(fn, 'wt') + f.write('\n') + f.close() + + +safety_flags = { + True: 'zip-safe', + False: 'not-zip-safe', +} + + +def scan_module(egg_dir, base, name, stubs): + """Check whether module possibly uses unsafe-for-zipfile stuff""" + + filename = os.path.join(base, name) + if filename[:-1] in stubs: + return True # Extension module + pkg = base[len(egg_dir) + 1:].replace(os.sep, '.') + module = pkg + (pkg and '.' or '') + os.path.splitext(name)[0] + if six.PY2: + skip = 8 # skip magic & date + elif sys.version_info < (3, 7): + skip = 12 # skip magic & date & file size + else: + skip = 16 # skip magic & reserved? & date & file size + f = open(filename, 'rb') + f.read(skip) + code = marshal.load(f) + f.close() + safe = True + symbols = dict.fromkeys(iter_symbols(code)) + for bad in ['__file__', '__path__']: + if bad in symbols: + log.warn("%s: module references %s", module, bad) + safe = False + if 'inspect' in symbols: + for bad in [ + 'getsource', 'getabsfile', 'getsourcefile', 'getfile' + 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', + 'getinnerframes', 'getouterframes', 'stack', 'trace' + ]: + if bad in symbols: + log.warn("%s: module MAY be using inspect.%s", module, bad) + safe = False + return safe + + +def iter_symbols(code): + """Yield names and strings used by `code` and its nested code objects""" + for name in code.co_names: + yield name + for const in code.co_consts: + if isinstance(const, six.string_types): + yield const + elif isinstance(const, CodeType): + for name in iter_symbols(const): + yield name + + +def can_scan(): + if not sys.platform.startswith('java') and sys.platform != 'cli': + # CPython, PyPy, etc. + return True + log.warn("Unable to analyze compiled code on this platform.") + log.warn("Please ask the author to include a 'zip_safe'" + " setting (either True or False) in the package's setup.py") + + +# Attribute names of options for commands that might need to be convinced to +# install to the egg build directory + +INSTALL_DIRECTORY_ATTRS = [ + 'install_lib', 'install_dir', 'install_data', 'install_base' +] + + +def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True, + mode='w'): + """Create a zip file from all the files under 'base_dir'. The output + zip file will be named 'base_dir' + ".zip". Uses either the "zipfile" + Python module (if available) or the InfoZIP "zip" utility (if installed + and found on the default search path). If neither tool is available, + raises DistutilsExecError. Returns the name of the output zip file. + """ + import zipfile + + mkpath(os.path.dirname(zip_filename), dry_run=dry_run) + log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir) + + def visit(z, dirname, names): + for name in names: + path = os.path.normpath(os.path.join(dirname, name)) + if os.path.isfile(path): + p = path[len(base_dir) + 1:] + if not dry_run: + z.write(path, p) + log.debug("adding '%s'", p) + + compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED + if not dry_run: + z = zipfile.ZipFile(zip_filename, mode, compression=compression) + for dirname, dirs, files in sorted_walk(base_dir): + visit(z, dirname, files) + z.close() + else: + for dirname, dirs, files in sorted_walk(base_dir): + visit(None, dirname, files) + return zip_filename diff --git a/venv/lib/python3.7/site-packages/setuptools/command/bdist_rpm.py b/venv/lib/python3.7/site-packages/setuptools/command/bdist_rpm.py new file mode 100644 index 0000000..7073092 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/bdist_rpm.py @@ -0,0 +1,43 @@ +import distutils.command.bdist_rpm as orig + + +class bdist_rpm(orig.bdist_rpm): + """ + Override the default bdist_rpm behavior to do the following: + + 1. Run egg_info to ensure the name and version are properly calculated. + 2. Always run 'install' using --single-version-externally-managed to + disable eggs in RPM distributions. + 3. Replace dash with underscore in the version numbers for better RPM + compatibility. + """ + + def run(self): + # ensure distro name is up-to-date + self.run_command('egg_info') + + orig.bdist_rpm.run(self) + + def _make_spec_file(self): + version = self.distribution.get_version() + rpmversion = version.replace('-', '_') + spec = orig.bdist_rpm._make_spec_file(self) + line23 = '%define version ' + version + line24 = '%define version ' + rpmversion + spec = [ + line.replace( + "Source0: %{name}-%{version}.tar", + "Source0: %{name}-%{unmangled_version}.tar" + ).replace( + "setup.py install ", + "setup.py install --single-version-externally-managed " + ).replace( + "%setup", + "%setup -n %{name}-%{unmangled_version}" + ).replace(line23, line24) + for line in spec + ] + insert_loc = spec.index(line24) + 1 + unmangled_version = "%define unmangled_version " + version + spec.insert(insert_loc, unmangled_version) + return spec diff --git a/venv/lib/python3.7/site-packages/setuptools/command/bdist_wininst.py b/venv/lib/python3.7/site-packages/setuptools/command/bdist_wininst.py new file mode 100644 index 0000000..073de97 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/bdist_wininst.py @@ -0,0 +1,21 @@ +import distutils.command.bdist_wininst as orig + + +class bdist_wininst(orig.bdist_wininst): + def reinitialize_command(self, command, reinit_subcommands=0): + """ + Supplement reinitialize_command to work around + http://bugs.python.org/issue20819 + """ + cmd = self.distribution.reinitialize_command( + command, reinit_subcommands) + if command in ('install', 'install_lib'): + cmd.install_lib = None + return cmd + + def run(self): + self._is_running = True + try: + orig.bdist_wininst.run(self) + finally: + self._is_running = False diff --git a/venv/lib/python3.7/site-packages/setuptools/command/build_clib.py b/venv/lib/python3.7/site-packages/setuptools/command/build_clib.py new file mode 100644 index 0000000..09caff6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/build_clib.py @@ -0,0 +1,98 @@ +import distutils.command.build_clib as orig +from distutils.errors import DistutilsSetupError +from distutils import log +from setuptools.dep_util import newer_pairwise_group + + +class build_clib(orig.build_clib): + """ + Override the default build_clib behaviour to do the following: + + 1. Implement a rudimentary timestamp-based dependency system + so 'compile()' doesn't run every time. + 2. Add more keys to the 'build_info' dictionary: + * obj_deps - specify dependencies for each object compiled. + this should be a dictionary mapping a key + with the source filename to a list of + dependencies. Use an empty string for global + dependencies. + * cflags - specify a list of additional flags to pass to + the compiler. + """ + + def build_libraries(self, libraries): + for (lib_name, build_info) in libraries: + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % lib_name) + sources = list(sources) + + log.info("building '%s' library", lib_name) + + # Make sure everything is the correct type. + # obj_deps should be a dictionary of keys as sources + # and a list/tuple of files that are its dependencies. + obj_deps = build_info.get('obj_deps', dict()) + if not isinstance(obj_deps, dict): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + dependencies = [] + + # Get the global dependencies that are specified by the '' key. + # These will go into every source's dependency list. + global_deps = obj_deps.get('', list()) + if not isinstance(global_deps, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + + # Build the list to be used by newer_pairwise_group + # each source will be auto-added to its dependencies. + for source in sources: + src_deps = [source] + src_deps.extend(global_deps) + extra_deps = obj_deps.get(source, list()) + if not isinstance(extra_deps, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + src_deps.extend(extra_deps) + dependencies.append(src_deps) + + expected_objects = self.compiler.object_filenames( + sources, + output_dir=self.build_temp + ) + + if newer_pairwise_group(dependencies, expected_objects) != ([], []): + # First, compile the source code to object files in the library + # directory. (This should probably change to putting object + # files in a temporary build directory.) + macros = build_info.get('macros') + include_dirs = build_info.get('include_dirs') + cflags = build_info.get('cflags') + objects = self.compiler.compile( + sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=include_dirs, + extra_postargs=cflags, + debug=self.debug + ) + + # Now "link" the object files together into a static library. + # (On Unix at least, this isn't really linking -- it just + # builds an archive. Whatever.) + self.compiler.create_static_lib( + expected_objects, + lib_name, + output_dir=self.build_clib, + debug=self.debug + ) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/build_ext.py b/venv/lib/python3.7/site-packages/setuptools/command/build_ext.py new file mode 100644 index 0000000..60a8a32 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/build_ext.py @@ -0,0 +1,321 @@ +import os +import sys +import itertools +import imp +from distutils.command.build_ext import build_ext as _du_build_ext +from distutils.file_util import copy_file +from distutils.ccompiler import new_compiler +from distutils.sysconfig import customize_compiler, get_config_var +from distutils.errors import DistutilsError +from distutils import log + +from setuptools.extension import Library +from setuptools.extern import six + +try: + # Attempt to use Cython for building extensions, if available + from Cython.Distutils.build_ext import build_ext as _build_ext + # Additionally, assert that the compiler module will load + # also. Ref #1229. + __import__('Cython.Compiler.Main') +except ImportError: + _build_ext = _du_build_ext + +# make sure _config_vars is initialized +get_config_var("LDSHARED") +from distutils.sysconfig import _config_vars as _CONFIG_VARS + + +def _customize_compiler_for_shlib(compiler): + if sys.platform == "darwin": + # building .dylib requires additional compiler flags on OSX; here we + # temporarily substitute the pyconfig.h variables so that distutils' + # 'customize_compiler' uses them before we build the shared libraries. + tmp = _CONFIG_VARS.copy() + try: + # XXX Help! I don't have any idea whether these are right... + _CONFIG_VARS['LDSHARED'] = ( + "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup") + _CONFIG_VARS['CCSHARED'] = " -dynamiclib" + _CONFIG_VARS['SO'] = ".dylib" + customize_compiler(compiler) + finally: + _CONFIG_VARS.clear() + _CONFIG_VARS.update(tmp) + else: + customize_compiler(compiler) + + +have_rtld = False +use_stubs = False +libtype = 'shared' + +if sys.platform == "darwin": + use_stubs = True +elif os.name != 'nt': + try: + import dl + use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW') + except ImportError: + pass + +if_dl = lambda s: s if have_rtld else '' + + +def get_abi3_suffix(): + """Return the file extension for an abi3-compliant Extension()""" + for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION): + if '.abi3' in suffix: # Unix + return suffix + elif suffix == '.pyd': # Windows + return suffix + + +class build_ext(_build_ext): + def run(self): + """Build extensions in build directory, then copy if --inplace""" + old_inplace, self.inplace = self.inplace, 0 + _build_ext.run(self) + self.inplace = old_inplace + if old_inplace: + self.copy_extensions_to_source() + + def copy_extensions_to_source(self): + build_py = self.get_finalized_command('build_py') + for ext in self.extensions: + fullname = self.get_ext_fullname(ext.name) + filename = self.get_ext_filename(fullname) + modpath = fullname.split('.') + package = '.'.join(modpath[:-1]) + package_dir = build_py.get_package_dir(package) + dest_filename = os.path.join(package_dir, + os.path.basename(filename)) + src_filename = os.path.join(self.build_lib, filename) + + # Always copy, even if source is older than destination, to ensure + # that the right extensions for the current Python/platform are + # used. + copy_file( + src_filename, dest_filename, verbose=self.verbose, + dry_run=self.dry_run + ) + if ext._needs_stub: + self.write_stub(package_dir or os.curdir, ext, True) + + def get_ext_filename(self, fullname): + filename = _build_ext.get_ext_filename(self, fullname) + if fullname in self.ext_map: + ext = self.ext_map[fullname] + use_abi3 = ( + six.PY3 + and getattr(ext, 'py_limited_api') + and get_abi3_suffix() + ) + if use_abi3: + so_ext = get_config_var('EXT_SUFFIX') + filename = filename[:-len(so_ext)] + filename = filename + get_abi3_suffix() + if isinstance(ext, Library): + fn, ext = os.path.splitext(filename) + return self.shlib_compiler.library_filename(fn, libtype) + elif use_stubs and ext._links_to_dynamic: + d, fn = os.path.split(filename) + return os.path.join(d, 'dl-' + fn) + return filename + + def initialize_options(self): + _build_ext.initialize_options(self) + self.shlib_compiler = None + self.shlibs = [] + self.ext_map = {} + + def finalize_options(self): + _build_ext.finalize_options(self) + self.extensions = self.extensions or [] + self.check_extensions_list(self.extensions) + self.shlibs = [ext for ext in self.extensions + if isinstance(ext, Library)] + if self.shlibs: + self.setup_shlib_compiler() + for ext in self.extensions: + ext._full_name = self.get_ext_fullname(ext.name) + for ext in self.extensions: + fullname = ext._full_name + self.ext_map[fullname] = ext + + # distutils 3.1 will also ask for module names + # XXX what to do with conflicts? + self.ext_map[fullname.split('.')[-1]] = ext + + ltd = self.shlibs and self.links_to_dynamic(ext) or False + ns = ltd and use_stubs and not isinstance(ext, Library) + ext._links_to_dynamic = ltd + ext._needs_stub = ns + filename = ext._file_name = self.get_ext_filename(fullname) + libdir = os.path.dirname(os.path.join(self.build_lib, filename)) + if ltd and libdir not in ext.library_dirs: + ext.library_dirs.append(libdir) + if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs: + ext.runtime_library_dirs.append(os.curdir) + + def setup_shlib_compiler(self): + compiler = self.shlib_compiler = new_compiler( + compiler=self.compiler, dry_run=self.dry_run, force=self.force + ) + _customize_compiler_for_shlib(compiler) + + if self.include_dirs is not None: + compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name, value) in self.define: + compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + compiler.undefine_macro(macro) + if self.libraries is not None: + compiler.set_libraries(self.libraries) + if self.library_dirs is not None: + compiler.set_library_dirs(self.library_dirs) + if self.rpath is not None: + compiler.set_runtime_library_dirs(self.rpath) + if self.link_objects is not None: + compiler.set_link_objects(self.link_objects) + + # hack so distutils' build_extension() builds a library instead + compiler.link_shared_object = link_shared_object.__get__(compiler) + + def get_export_symbols(self, ext): + if isinstance(ext, Library): + return ext.export_symbols + return _build_ext.get_export_symbols(self, ext) + + def build_extension(self, ext): + ext._convert_pyx_sources_to_lang() + _compiler = self.compiler + try: + if isinstance(ext, Library): + self.compiler = self.shlib_compiler + _build_ext.build_extension(self, ext) + if ext._needs_stub: + cmd = self.get_finalized_command('build_py').build_lib + self.write_stub(cmd, ext) + finally: + self.compiler = _compiler + + def links_to_dynamic(self, ext): + """Return true if 'ext' links to a dynamic lib in the same package""" + # XXX this should check to ensure the lib is actually being built + # XXX as dynamic, and not just using a locally-found version or a + # XXX static-compiled version + libnames = dict.fromkeys([lib._full_name for lib in self.shlibs]) + pkg = '.'.join(ext._full_name.split('.')[:-1] + ['']) + return any(pkg + libname in libnames for libname in ext.libraries) + + def get_outputs(self): + return _build_ext.get_outputs(self) + self.__get_stubs_outputs() + + def __get_stubs_outputs(self): + # assemble the base name for each extension that needs a stub + ns_ext_bases = ( + os.path.join(self.build_lib, *ext._full_name.split('.')) + for ext in self.extensions + if ext._needs_stub + ) + # pair each base with the extension + pairs = itertools.product(ns_ext_bases, self.__get_output_extensions()) + return list(base + fnext for base, fnext in pairs) + + def __get_output_extensions(self): + yield '.py' + yield '.pyc' + if self.get_finalized_command('build_py').optimize: + yield '.pyo' + + def write_stub(self, output_dir, ext, compile=False): + log.info("writing stub loader for %s to %s", ext._full_name, + output_dir) + stub_file = (os.path.join(output_dir, *ext._full_name.split('.')) + + '.py') + if compile and os.path.exists(stub_file): + raise DistutilsError(stub_file + " already exists! Please delete.") + if not self.dry_run: + f = open(stub_file, 'w') + f.write( + '\n'.join([ + "def __bootstrap__():", + " global __bootstrap__, __file__, __loader__", + " import sys, os, pkg_resources, imp" + if_dl(", dl"), + " __file__ = pkg_resources.resource_filename" + "(__name__,%r)" + % os.path.basename(ext._file_name), + " del __bootstrap__", + " if '__loader__' in globals():", + " del __loader__", + if_dl(" old_flags = sys.getdlopenflags()"), + " old_dir = os.getcwd()", + " try:", + " os.chdir(os.path.dirname(__file__))", + if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"), + " imp.load_dynamic(__name__,__file__)", + " finally:", + if_dl(" sys.setdlopenflags(old_flags)"), + " os.chdir(old_dir)", + "__bootstrap__()", + "" # terminal \n + ]) + ) + f.close() + if compile: + from distutils.util import byte_compile + + byte_compile([stub_file], optimize=0, + force=True, dry_run=self.dry_run) + optimize = self.get_finalized_command('install_lib').optimize + if optimize > 0: + byte_compile([stub_file], optimize=optimize, + force=True, dry_run=self.dry_run) + if os.path.exists(stub_file) and not self.dry_run: + os.unlink(stub_file) + + +if use_stubs or os.name == 'nt': + # Build shared libraries + # + def link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + self.link( + self.SHARED_LIBRARY, objects, output_libname, + output_dir, libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, extra_preargs, extra_postargs, + build_temp, target_lang + ) +else: + # Build static libraries everywhere else + libtype = 'static' + + def link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + # XXX we need to either disallow these attrs on Library instances, + # or warn/abort here if set, or something... + # libraries=None, library_dirs=None, runtime_library_dirs=None, + # export_symbols=None, extra_preargs=None, extra_postargs=None, + # build_temp=None + + assert output_dir is None # distutils build_ext doesn't pass this + output_dir, filename = os.path.split(output_libname) + basename, ext = os.path.splitext(filename) + if self.library_filename("x").startswith('lib'): + # strip 'lib' prefix; this is kludgy if some platform uses + # a different prefix + basename = basename[3:] + + self.create_static_lib( + objects, basename, output_dir, debug, target_lang + ) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/build_py.py b/venv/lib/python3.7/site-packages/setuptools/command/build_py.py new file mode 100644 index 0000000..b0314fd --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/build_py.py @@ -0,0 +1,270 @@ +from glob import glob +from distutils.util import convert_path +import distutils.command.build_py as orig +import os +import fnmatch +import textwrap +import io +import distutils.errors +import itertools + +from setuptools.extern import six +from setuptools.extern.six.moves import map, filter, filterfalse + +try: + from setuptools.lib2to3_ex import Mixin2to3 +except ImportError: + + class Mixin2to3: + def run_2to3(self, files, doctests=True): + "do nothing" + + +class build_py(orig.build_py, Mixin2to3): + """Enhanced 'build_py' command that includes data files with packages + + The data files are specified via a 'package_data' argument to 'setup()'. + See 'setuptools.dist.Distribution' for more details. + + Also, this version of the 'build_py' command allows you to specify both + 'py_modules' and 'packages' in the same setup operation. + """ + + def finalize_options(self): + orig.build_py.finalize_options(self) + self.package_data = self.distribution.package_data + self.exclude_package_data = (self.distribution.exclude_package_data or + {}) + if 'data_files' in self.__dict__: + del self.__dict__['data_files'] + self.__updated_files = [] + self.__doctests_2to3 = [] + + def run(self): + """Build modules, packages, and copy data files to build directory""" + if not self.py_modules and not self.packages: + return + + if self.py_modules: + self.build_modules() + + if self.packages: + self.build_packages() + self.build_package_data() + + self.run_2to3(self.__updated_files, False) + self.run_2to3(self.__updated_files, True) + self.run_2to3(self.__doctests_2to3, True) + + # Only compile actual .py files, using our base class' idea of what our + # output files are. + self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0)) + + def __getattr__(self, attr): + "lazily compute data files" + if attr == 'data_files': + self.data_files = self._get_data_files() + return self.data_files + return orig.build_py.__getattr__(self, attr) + + def build_module(self, module, module_file, package): + if six.PY2 and isinstance(package, six.string_types): + # avoid errors on Python 2 when unicode is passed (#190) + package = package.split('.') + outfile, copied = orig.build_py.build_module(self, module, module_file, + package) + if copied: + self.__updated_files.append(outfile) + return outfile, copied + + def _get_data_files(self): + """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" + self.analyze_manifest() + return list(map(self._get_pkg_data_files, self.packages or ())) + + def _get_pkg_data_files(self, package): + # Locate package source directory + src_dir = self.get_package_dir(package) + + # Compute package build directory + build_dir = os.path.join(*([self.build_lib] + package.split('.'))) + + # Strip directory from globbed filenames + filenames = [ + os.path.relpath(file, src_dir) + for file in self.find_data_files(package, src_dir) + ] + return package, src_dir, build_dir, filenames + + def find_data_files(self, package, src_dir): + """Return filenames for package's data files in 'src_dir'""" + patterns = self._get_platform_patterns( + self.package_data, + package, + src_dir, + ) + globs_expanded = map(glob, patterns) + # flatten the expanded globs into an iterable of matches + globs_matches = itertools.chain.from_iterable(globs_expanded) + glob_files = filter(os.path.isfile, globs_matches) + files = itertools.chain( + self.manifest_files.get(package, []), + glob_files, + ) + return self.exclude_data_files(package, src_dir, files) + + def build_package_data(self): + """Copy data files into build directory""" + for package, src_dir, build_dir, filenames in self.data_files: + for filename in filenames: + target = os.path.join(build_dir, filename) + self.mkpath(os.path.dirname(target)) + srcfile = os.path.join(src_dir, filename) + outf, copied = self.copy_file(srcfile, target) + srcfile = os.path.abspath(srcfile) + if (copied and + srcfile in self.distribution.convert_2to3_doctests): + self.__doctests_2to3.append(outf) + + def analyze_manifest(self): + self.manifest_files = mf = {} + if not self.distribution.include_package_data: + return + src_dirs = {} + for package in self.packages or (): + # Locate package source directory + src_dirs[assert_relative(self.get_package_dir(package))] = package + + self.run_command('egg_info') + ei_cmd = self.get_finalized_command('egg_info') + for path in ei_cmd.filelist.files: + d, f = os.path.split(assert_relative(path)) + prev = None + oldf = f + while d and d != prev and d not in src_dirs: + prev = d + d, df = os.path.split(d) + f = os.path.join(df, f) + if d in src_dirs: + if path.endswith('.py') and f == oldf: + continue # it's a module, not data + mf.setdefault(src_dirs[d], []).append(path) + + def get_data_files(self): + pass # Lazily compute data files in _get_data_files() function. + + def check_package(self, package, package_dir): + """Check namespace packages' __init__ for declare_namespace""" + try: + return self.packages_checked[package] + except KeyError: + pass + + init_py = orig.build_py.check_package(self, package, package_dir) + self.packages_checked[package] = init_py + + if not init_py or not self.distribution.namespace_packages: + return init_py + + for pkg in self.distribution.namespace_packages: + if pkg == package or pkg.startswith(package + '.'): + break + else: + return init_py + + with io.open(init_py, 'rb') as f: + contents = f.read() + if b'declare_namespace' not in contents: + raise distutils.errors.DistutilsError( + "Namespace package problem: %s is a namespace package, but " + "its\n__init__.py does not call declare_namespace()! Please " + 'fix it.\n(See the setuptools manual under ' + '"Namespace Packages" for details.)\n"' % (package,) + ) + return init_py + + def initialize_options(self): + self.packages_checked = {} + orig.build_py.initialize_options(self) + + def get_package_dir(self, package): + res = orig.build_py.get_package_dir(self, package) + if self.distribution.src_root is not None: + return os.path.join(self.distribution.src_root, res) + return res + + def exclude_data_files(self, package, src_dir, files): + """Filter filenames for package's data files in 'src_dir'""" + files = list(files) + patterns = self._get_platform_patterns( + self.exclude_package_data, + package, + src_dir, + ) + match_groups = ( + fnmatch.filter(files, pattern) + for pattern in patterns + ) + # flatten the groups of matches into an iterable of matches + matches = itertools.chain.from_iterable(match_groups) + bad = set(matches) + keepers = ( + fn + for fn in files + if fn not in bad + ) + # ditch dupes + return list(_unique_everseen(keepers)) + + @staticmethod + def _get_platform_patterns(spec, package, src_dir): + """ + yield platform-specific path patterns (suitable for glob + or fn_match) from a glob-based spec (such as + self.package_data or self.exclude_package_data) + matching package in src_dir. + """ + raw_patterns = itertools.chain( + spec.get('', []), + spec.get(package, []), + ) + return ( + # Each pattern has to be converted to a platform-specific path + os.path.join(src_dir, convert_path(pattern)) + for pattern in raw_patterns + ) + + +# from Python docs +def _unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +def assert_relative(path): + if not os.path.isabs(path): + return path + from distutils.errors import DistutilsSetupError + + msg = textwrap.dedent(""" + Error: setup script specifies an absolute path: + + %s + + setup() arguments must *always* be /-separated paths relative to the + setup.py directory, *never* absolute paths. + """).lstrip() % path + raise DistutilsSetupError(msg) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/develop.py b/venv/lib/python3.7/site-packages/setuptools/command/develop.py new file mode 100644 index 0000000..fdc9fc4 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/develop.py @@ -0,0 +1,218 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsError, DistutilsOptionError +import os +import glob +import io + +from setuptools.extern import six + +from pkg_resources import Distribution, PathMetadata, normalize_path +from setuptools.command.easy_install import easy_install +from setuptools import namespaces +import setuptools + +__metaclass__ = type + + +class develop(namespaces.DevelopInstaller, easy_install): + """Set up package for development""" + + description = "install package in 'development mode'" + + user_options = easy_install.user_options + [ + ("uninstall", "u", "Uninstall this source package"), + ("egg-path=", None, "Set the path to be used in the .egg-link file"), + ] + + boolean_options = easy_install.boolean_options + ['uninstall'] + + command_consumes_arguments = False # override base + + def run(self): + if self.uninstall: + self.multi_version = True + self.uninstall_link() + self.uninstall_namespaces() + else: + self.install_for_development() + self.warn_deprecated_options() + + def initialize_options(self): + self.uninstall = None + self.egg_path = None + easy_install.initialize_options(self) + self.setup_path = None + self.always_copy_from = '.' # always copy eggs installed in curdir + + def finalize_options(self): + ei = self.get_finalized_command("egg_info") + if ei.broken_egg_info: + template = "Please rename %r to %r before using 'develop'" + args = ei.egg_info, ei.broken_egg_info + raise DistutilsError(template % args) + self.args = [ei.egg_name] + + easy_install.finalize_options(self) + self.expand_basedirs() + self.expand_dirs() + # pick up setup-dir .egg files only: no .egg-info + self.package_index.scan(glob.glob('*.egg')) + + egg_link_fn = ei.egg_name + '.egg-link' + self.egg_link = os.path.join(self.install_dir, egg_link_fn) + self.egg_base = ei.egg_base + if self.egg_path is None: + self.egg_path = os.path.abspath(ei.egg_base) + + target = normalize_path(self.egg_base) + egg_path = normalize_path(os.path.join(self.install_dir, + self.egg_path)) + if egg_path != target: + raise DistutilsOptionError( + "--egg-path must be a relative path from the install" + " directory to " + target + ) + + # Make a distribution for the package's source + self.dist = Distribution( + target, + PathMetadata(target, os.path.abspath(ei.egg_info)), + project_name=ei.egg_name + ) + + self.setup_path = self._resolve_setup_path( + self.egg_base, + self.install_dir, + self.egg_path, + ) + + @staticmethod + def _resolve_setup_path(egg_base, install_dir, egg_path): + """ + Generate a path from egg_base back to '.' where the + setup script resides and ensure that path points to the + setup path from $install_dir/$egg_path. + """ + path_to_setup = egg_base.replace(os.sep, '/').rstrip('/') + if path_to_setup != os.curdir: + path_to_setup = '../' * (path_to_setup.count('/') + 1) + resolved = normalize_path( + os.path.join(install_dir, egg_path, path_to_setup) + ) + if resolved != normalize_path(os.curdir): + raise DistutilsOptionError( + "Can't get a consistent path to setup script from" + " installation directory", resolved, normalize_path(os.curdir)) + return path_to_setup + + def install_for_development(self): + if six.PY3 and getattr(self.distribution, 'use_2to3', False): + # If we run 2to3 we can not do this inplace: + + # Ensure metadata is up-to-date + self.reinitialize_command('build_py', inplace=0) + self.run_command('build_py') + bpy_cmd = self.get_finalized_command("build_py") + build_path = normalize_path(bpy_cmd.build_lib) + + # Build extensions + self.reinitialize_command('egg_info', egg_base=build_path) + self.run_command('egg_info') + + self.reinitialize_command('build_ext', inplace=0) + self.run_command('build_ext') + + # Fixup egg-link and easy-install.pth + ei_cmd = self.get_finalized_command("egg_info") + self.egg_path = build_path + self.dist.location = build_path + # XXX + self.dist._provider = PathMetadata(build_path, ei_cmd.egg_info) + else: + # Without 2to3 inplace works fine: + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + + self.install_site_py() # ensure that target dir is site-safe + if setuptools.bootstrap_install_from: + self.easy_install(setuptools.bootstrap_install_from) + setuptools.bootstrap_install_from = None + + self.install_namespaces() + + # create an .egg-link in the installation dir, pointing to our egg + log.info("Creating %s (link to %s)", self.egg_link, self.egg_base) + if not self.dry_run: + with open(self.egg_link, "w") as f: + f.write(self.egg_path + "\n" + self.setup_path) + # postprocess the installed distro, fixing up .pth, installing scripts, + # and handling requirements + self.process_distribution(None, self.dist, not self.no_deps) + + def uninstall_link(self): + if os.path.exists(self.egg_link): + log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) + egg_link_file = open(self.egg_link) + contents = [line.rstrip() for line in egg_link_file] + egg_link_file.close() + if contents not in ([self.egg_path], + [self.egg_path, self.setup_path]): + log.warn("Link points to %s: uninstall aborted", contents) + return + if not self.dry_run: + os.unlink(self.egg_link) + if not self.dry_run: + self.update_pth(self.dist) # remove any .pth link to us + if self.distribution.scripts: + # XXX should also check for entry point scripts! + log.warn("Note: you must uninstall or replace scripts manually!") + + def install_egg_scripts(self, dist): + if dist is not self.dist: + # Installing a dependency, so fall back to normal behavior + return easy_install.install_egg_scripts(self, dist) + + # create wrapper scripts in the script dir, pointing to dist.scripts + + # new-style... + self.install_wrapper_scripts(dist) + + # ...and old-style + for script_name in self.distribution.scripts or []: + script_path = os.path.abspath(convert_path(script_name)) + script_name = os.path.basename(script_path) + with io.open(script_path) as strm: + script_text = strm.read() + self.install_script(dist, script_name, script_text, script_path) + + def install_wrapper_scripts(self, dist): + dist = VersionlessRequirement(dist) + return easy_install.install_wrapper_scripts(self, dist) + + +class VersionlessRequirement: + """ + Adapt a pkg_resources.Distribution to simply return the project + name as the 'requirement' so that scripts will work across + multiple versions. + + >>> dist = Distribution(project_name='foo', version='1.0') + >>> str(dist.as_requirement()) + 'foo==1.0' + >>> adapted_dist = VersionlessRequirement(dist) + >>> str(adapted_dist.as_requirement()) + 'foo' + """ + + def __init__(self, dist): + self.__dist = dist + + def __getattr__(self, name): + return getattr(self.__dist, name) + + def as_requirement(self): + return self.project_name diff --git a/venv/lib/python3.7/site-packages/setuptools/command/dist_info.py b/venv/lib/python3.7/site-packages/setuptools/command/dist_info.py new file mode 100644 index 0000000..c45258f --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/dist_info.py @@ -0,0 +1,36 @@ +""" +Create a dist_info directory +As defined in the wheel specification +""" + +import os + +from distutils.core import Command +from distutils import log + + +class dist_info(Command): + + description = 'create a .dist-info directory' + + user_options = [ + ('egg-base=', 'e', "directory containing .egg-info directories" + " (default: top of the source tree)"), + ] + + def initialize_options(self): + self.egg_base = None + + def finalize_options(self): + pass + + def run(self): + egg_info = self.get_finalized_command('egg_info') + egg_info.egg_base = self.egg_base + egg_info.finalize_options() + egg_info.run() + dist_info_dir = egg_info.egg_info[:-len('.egg-info')] + '.dist-info' + log.info("creating '{}'".format(os.path.abspath(dist_info_dir))) + + bdist_wheel = self.get_finalized_command('bdist_wheel') + bdist_wheel.egg2dist(egg_info.egg_info, dist_info_dir) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/easy_install.py b/venv/lib/python3.7/site-packages/setuptools/command/easy_install.py new file mode 100644 index 0000000..06c9827 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/easy_install.py @@ -0,0 +1,2342 @@ +#!/usr/bin/env python +""" +Easy Install +------------ + +A tool for doing automatic download/extract/build of distutils-based Python +packages. For detailed documentation, see the accompanying EasyInstall.txt +file, or visit the `EasyInstall home page`__. + +__ https://setuptools.readthedocs.io/en/latest/easy_install.html + +""" + +from glob import glob +from distutils.util import get_platform +from distutils.util import convert_path, subst_vars +from distutils.errors import ( + DistutilsArgError, DistutilsOptionError, + DistutilsError, DistutilsPlatformError, +) +from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS +from distutils import log, dir_util +from distutils.command.build_scripts import first_line_re +from distutils.spawn import find_executable +import sys +import os +import zipimport +import shutil +import tempfile +import zipfile +import re +import stat +import random +import textwrap +import warnings +import site +import struct +import contextlib +import subprocess +import shlex +import io + + +from sysconfig import get_config_vars, get_path + +from setuptools import SetuptoolsDeprecationWarning + +from setuptools.extern import six +from setuptools.extern.six.moves import configparser, map + +from setuptools import Command +from setuptools.sandbox import run_setup +from setuptools.py27compat import rmtree_safe +from setuptools.command import setopt +from setuptools.archive_util import unpack_archive +from setuptools.package_index import ( + PackageIndex, parse_requirement_arg, URL_SCHEME, +) +from setuptools.command import bdist_egg, egg_info +from setuptools.wheel import Wheel +from pkg_resources import ( + yield_lines, normalize_path, resource_string, ensure_directory, + get_distribution, find_distributions, Environment, Requirement, + Distribution, PathMetadata, EggMetadata, WorkingSet, DistributionNotFound, + VersionConflict, DEVELOP_DIST, +) +import pkg_resources.py31compat + +__metaclass__ = type + +# Turn on PEP440Warnings +warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) + +__all__ = [ + 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', + 'main', 'get_exe_prefixes', +] + + +def is_64bit(): + return struct.calcsize("P") == 8 + + +def samefile(p1, p2): + """ + Determine if two paths reference the same file. + + Augments os.path.samefile to work on Windows and + suppresses errors if the path doesn't exist. + """ + both_exist = os.path.exists(p1) and os.path.exists(p2) + use_samefile = hasattr(os.path, 'samefile') and both_exist + if use_samefile: + return os.path.samefile(p1, p2) + norm_p1 = os.path.normpath(os.path.normcase(p1)) + norm_p2 = os.path.normpath(os.path.normcase(p2)) + return norm_p1 == norm_p2 + + +if six.PY2: + + def _to_bytes(s): + return s + + def isascii(s): + try: + six.text_type(s, 'ascii') + return True + except UnicodeError: + return False +else: + + def _to_bytes(s): + return s.encode('utf8') + + def isascii(s): + try: + s.encode('ascii') + return True + except UnicodeError: + return False + + +_one_liner = lambda text: textwrap.dedent(text).strip().replace('\n', '; ') + + +class easy_install(Command): + """Manage a download/build/install process""" + description = "Find/get/install Python packages" + command_consumes_arguments = True + + user_options = [ + ('prefix=', None, "installation prefix"), + ("zip-ok", "z", "install package as a zipfile"), + ("multi-version", "m", "make apps have to require() a version"), + ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), + ("install-dir=", "d", "install package to DIR"), + ("script-dir=", "s", "install scripts to DIR"), + ("exclude-scripts", "x", "Don't install scripts"), + ("always-copy", "a", "Copy all needed packages to install dir"), + ("index-url=", "i", "base URL of Python Package Index"), + ("find-links=", "f", "additional URL(s) to search for packages"), + ("build-directory=", "b", + "download/extract/build in DIR; keep the results"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('record=', None, + "filename in which to record list of installed files"), + ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), + ('site-dirs=', 'S', "list of directories where .pth files work"), + ('editable', 'e', "Install specified packages in editable form"), + ('no-deps', 'N', "don't install dependencies"), + ('allow-hosts=', 'H', "pattern(s) that hostnames must match"), + ('local-snapshots-ok', 'l', + "allow building eggs from local checkouts"), + ('version', None, "print version information and exit"), + ('no-find-links', None, + "Don't load find-links defined in packages being installed") + ] + boolean_options = [ + 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', + 'editable', + 'no-deps', 'local-snapshots-ok', 'version' + ] + + if site.ENABLE_USER_SITE: + help_msg = "install in user site-package '%s'" % site.USER_SITE + user_options.append(('user', None, help_msg)) + boolean_options.append('user') + + negative_opt = {'always-unzip': 'zip-ok'} + create_index = PackageIndex + + def initialize_options(self): + # the --user option seems to be an opt-in one, + # so the default should be False. + self.user = 0 + self.zip_ok = self.local_snapshots_ok = None + self.install_dir = self.script_dir = self.exclude_scripts = None + self.index_url = None + self.find_links = None + self.build_directory = None + self.args = None + self.optimize = self.record = None + self.upgrade = self.always_copy = self.multi_version = None + self.editable = self.no_deps = self.allow_hosts = None + self.root = self.prefix = self.no_report = None + self.version = None + self.install_purelib = None # for pure module distributions + self.install_platlib = None # non-pure (dists w/ extensions) + self.install_headers = None # for C/C++ headers + self.install_lib = None # set to either purelib or platlib + self.install_scripts = None + self.install_data = None + self.install_base = None + self.install_platbase = None + if site.ENABLE_USER_SITE: + self.install_userbase = site.USER_BASE + self.install_usersite = site.USER_SITE + else: + self.install_userbase = None + self.install_usersite = None + self.no_find_links = None + + # Options not specifiable via command line + self.package_index = None + self.pth_file = self.always_copy_from = None + self.site_dirs = None + self.installed_projects = {} + self.sitepy_installed = False + # Always read easy_install options, even if we are subclassed, or have + # an independent instance created. This ensures that defaults will + # always come from the standard configuration file(s)' "easy_install" + # section, even if this is a "develop" or "install" command, or some + # other embedding. + self._dry_run = None + self.verbose = self.distribution.verbose + self.distribution._set_command_options( + self, self.distribution.get_option_dict('easy_install') + ) + + def delete_blockers(self, blockers): + extant_blockers = ( + filename for filename in blockers + if os.path.exists(filename) or os.path.islink(filename) + ) + list(map(self._delete_path, extant_blockers)) + + def _delete_path(self, path): + log.info("Deleting %s", path) + if self.dry_run: + return + + is_tree = os.path.isdir(path) and not os.path.islink(path) + remover = rmtree if is_tree else os.unlink + remover(path) + + @staticmethod + def _render_version(): + """ + Render the Setuptools version and installation details, then exit. + """ + ver = sys.version[:3] + dist = get_distribution('setuptools') + tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})' + print(tmpl.format(**locals())) + raise SystemExit() + + def finalize_options(self): + self.version and self._render_version() + + py_version = sys.version.split()[0] + prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix') + + self.config_vars = { + 'dist_name': self.distribution.get_name(), + 'dist_version': self.distribution.get_version(), + 'dist_fullname': self.distribution.get_fullname(), + 'py_version': py_version, + 'py_version_short': py_version[0:3], + 'py_version_nodot': py_version[0] + py_version[2], + 'sys_prefix': prefix, + 'prefix': prefix, + 'sys_exec_prefix': exec_prefix, + 'exec_prefix': exec_prefix, + # Only python 3.2+ has abiflags + 'abiflags': getattr(sys, 'abiflags', ''), + } + + if site.ENABLE_USER_SITE: + self.config_vars['userbase'] = self.install_userbase + self.config_vars['usersite'] = self.install_usersite + + self._fix_install_dir_for_user_site() + + self.expand_basedirs() + self.expand_dirs() + + self._expand( + 'install_dir', 'script_dir', 'build_directory', + 'site_dirs', + ) + # If a non-default installation directory was specified, default the + # script directory to match it. + if self.script_dir is None: + self.script_dir = self.install_dir + + if self.no_find_links is None: + self.no_find_links = False + + # Let install_dir get set by install_lib command, which in turn + # gets its info from the install command, and takes into account + # --prefix and --home and all that other crud. + self.set_undefined_options( + 'install_lib', ('install_dir', 'install_dir') + ) + # Likewise, set default script_dir from 'install_scripts.install_dir' + self.set_undefined_options( + 'install_scripts', ('install_dir', 'script_dir') + ) + + if self.user and self.install_purelib: + self.install_dir = self.install_purelib + self.script_dir = self.install_scripts + # default --record from the install command + self.set_undefined_options('install', ('record', 'record')) + # Should this be moved to the if statement below? It's not used + # elsewhere + normpath = map(normalize_path, sys.path) + self.all_site_dirs = get_site_dirs() + if self.site_dirs is not None: + site_dirs = [ + os.path.expanduser(s.strip()) for s in + self.site_dirs.split(',') + ] + for d in site_dirs: + if not os.path.isdir(d): + log.warn("%s (in --site-dirs) does not exist", d) + elif normalize_path(d) not in normpath: + raise DistutilsOptionError( + d + " (in --site-dirs) is not on sys.path" + ) + else: + self.all_site_dirs.append(normalize_path(d)) + if not self.editable: + self.check_site_dir() + self.index_url = self.index_url or "https://pypi.org/simple/" + self.shadow_path = self.all_site_dirs[:] + for path_item in self.install_dir, normalize_path(self.script_dir): + if path_item not in self.shadow_path: + self.shadow_path.insert(0, path_item) + + if self.allow_hosts is not None: + hosts = [s.strip() for s in self.allow_hosts.split(',')] + else: + hosts = ['*'] + if self.package_index is None: + self.package_index = self.create_index( + self.index_url, search_path=self.shadow_path, hosts=hosts, + ) + self.local_index = Environment(self.shadow_path + sys.path) + + if self.find_links is not None: + if isinstance(self.find_links, six.string_types): + self.find_links = self.find_links.split() + else: + self.find_links = [] + if self.local_snapshots_ok: + self.package_index.scan_egg_links(self.shadow_path + sys.path) + if not self.no_find_links: + self.package_index.add_find_links(self.find_links) + self.set_undefined_options('install_lib', ('optimize', 'optimize')) + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + if not (0 <= self.optimize <= 2): + raise ValueError + except ValueError: + raise DistutilsOptionError("--optimize must be 0, 1, or 2") + + if self.editable and not self.build_directory: + raise DistutilsArgError( + "Must specify a build directory (-b) when using --editable" + ) + if not self.args: + raise DistutilsArgError( + "No urls, filenames, or requirements specified (see --help)") + + self.outputs = [] + + def _fix_install_dir_for_user_site(self): + """ + Fix the install_dir if "--user" was used. + """ + if not self.user or not site.ENABLE_USER_SITE: + return + + self.create_home_path() + if self.install_userbase is None: + msg = "User base directory is not specified" + raise DistutilsPlatformError(msg) + self.install_base = self.install_platbase = self.install_userbase + scheme_name = os.name.replace('posix', 'unix') + '_user' + self.select_scheme(scheme_name) + + def _expand_attrs(self, attrs): + for attr in attrs: + val = getattr(self, attr) + if val is not None: + if os.name == 'posix' or os.name == 'nt': + val = os.path.expanduser(val) + val = subst_vars(val, self.config_vars) + setattr(self, attr, val) + + def expand_basedirs(self): + """Calls `os.path.expanduser` on install_base, install_platbase and + root.""" + self._expand_attrs(['install_base', 'install_platbase', 'root']) + + def expand_dirs(self): + """Calls `os.path.expanduser` on install dirs.""" + dirs = [ + 'install_purelib', + 'install_platlib', + 'install_lib', + 'install_headers', + 'install_scripts', + 'install_data', + ] + self._expand_attrs(dirs) + + def run(self): + if self.verbose != self.distribution.verbose: + log.set_verbosity(self.verbose) + try: + for spec in self.args: + self.easy_install(spec, not self.no_deps) + if self.record: + outputs = self.outputs + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in range(len(outputs)): + outputs[counter] = outputs[counter][root_len:] + from distutils import file_util + + self.execute( + file_util.write_file, (self.record, outputs), + "writing list of installed files to '%s'" % + self.record + ) + self.warn_deprecated_options() + finally: + log.set_verbosity(self.distribution.verbose) + + def pseudo_tempname(self): + """Return a pseudo-tempname base in the install directory. + This code is intentionally naive; if a malicious party can write to + the target directory you're already in deep doodoo. + """ + try: + pid = os.getpid() + except Exception: + pid = random.randint(0, sys.maxsize) + return os.path.join(self.install_dir, "test-easy-install-%s" % pid) + + def warn_deprecated_options(self): + pass + + def check_site_dir(self): + """Verify that self.install_dir is .pth-capable dir, if needed""" + + instdir = normalize_path(self.install_dir) + pth_file = os.path.join(instdir, 'easy-install.pth') + + # Is it a configured, PYTHONPATH, implicit, or explicit site dir? + is_site_dir = instdir in self.all_site_dirs + + if not is_site_dir and not self.multi_version: + # No? Then directly test whether it does .pth file processing + is_site_dir = self.check_pth_processing() + else: + # make sure we can write to target dir + testfile = self.pseudo_tempname() + '.write-test' + test_exists = os.path.exists(testfile) + try: + if test_exists: + os.unlink(testfile) + open(testfile, 'w').close() + os.unlink(testfile) + except (OSError, IOError): + self.cant_write_to_target() + + if not is_site_dir and not self.multi_version: + # Can't install non-multi to non-site dir + raise DistutilsError(self.no_default_version_msg()) + + if is_site_dir: + if self.pth_file is None: + self.pth_file = PthDistributions(pth_file, self.all_site_dirs) + else: + self.pth_file = None + + if instdir not in map(normalize_path, _pythonpath()): + # only PYTHONPATH dirs need a site.py, so pretend it's there + self.sitepy_installed = True + elif self.multi_version and not os.path.exists(pth_file): + self.sitepy_installed = True # don't need site.py in this case + self.pth_file = None # and don't create a .pth file + self.install_dir = instdir + + __cant_write_msg = textwrap.dedent(""" + can't create or remove files in install directory + + The following error occurred while trying to add or remove files in the + installation directory: + + %s + + The installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: + + %s + """).lstrip() + + __not_exists_id = textwrap.dedent(""" + This directory does not currently exist. Please create it and try again, or + choose a different installation directory (using the -d or --install-dir + option). + """).lstrip() + + __access_msg = textwrap.dedent(""" + Perhaps your account does not have write access to this directory? If the + installation directory is a system-owned directory, you may need to sign in + as the administrator or "root" account. If you do not have administrative + access to this machine, you may wish to choose a different installation + directory, preferably one that is listed in your PYTHONPATH environment + variable. + + For information on other options, you may wish to consult the + documentation at: + + https://setuptools.readthedocs.io/en/latest/easy_install.html + + Please make the appropriate changes for your system and try again. + """).lstrip() + + def cant_write_to_target(self): + msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,) + + if not os.path.exists(self.install_dir): + msg += '\n' + self.__not_exists_id + else: + msg += '\n' + self.__access_msg + raise DistutilsError(msg) + + def check_pth_processing(self): + """Empirically verify whether .pth files are supported in inst. dir""" + instdir = self.install_dir + log.info("Checking .pth file support in %s", instdir) + pth_file = self.pseudo_tempname() + ".pth" + ok_file = pth_file + '.ok' + ok_exists = os.path.exists(ok_file) + tmpl = _one_liner(""" + import os + f = open({ok_file!r}, 'w') + f.write('OK') + f.close() + """) + '\n' + try: + if ok_exists: + os.unlink(ok_file) + dirname = os.path.dirname(ok_file) + pkg_resources.py31compat.makedirs(dirname, exist_ok=True) + f = open(pth_file, 'w') + except (OSError, IOError): + self.cant_write_to_target() + else: + try: + f.write(tmpl.format(**locals())) + f.close() + f = None + executable = sys.executable + if os.name == 'nt': + dirname, basename = os.path.split(executable) + alt = os.path.join(dirname, 'pythonw.exe') + use_alt = ( + basename.lower() == 'python.exe' and + os.path.exists(alt) + ) + if use_alt: + # use pythonw.exe to avoid opening a console window + executable = alt + + from distutils.spawn import spawn + + spawn([executable, '-E', '-c', 'pass'], 0) + + if os.path.exists(ok_file): + log.info( + "TEST PASSED: %s appears to support .pth files", + instdir + ) + return True + finally: + if f: + f.close() + if os.path.exists(ok_file): + os.unlink(ok_file) + if os.path.exists(pth_file): + os.unlink(pth_file) + if not self.multi_version: + log.warn("TEST FAILED: %s does NOT support .pth files", instdir) + return False + + def install_egg_scripts(self, dist): + """Write all the scripts for `dist`, unless scripts are excluded""" + if not self.exclude_scripts and dist.metadata_isdir('scripts'): + for script_name in dist.metadata_listdir('scripts'): + if dist.metadata_isdir('scripts/' + script_name): + # The "script" is a directory, likely a Python 3 + # __pycache__ directory, so skip it. + continue + self.install_script( + dist, script_name, + dist.get_metadata('scripts/' + script_name) + ) + self.install_wrapper_scripts(dist) + + def add_output(self, path): + if os.path.isdir(path): + for base, dirs, files in os.walk(path): + for filename in files: + self.outputs.append(os.path.join(base, filename)) + else: + self.outputs.append(path) + + def not_editable(self, spec): + if self.editable: + raise DistutilsArgError( + "Invalid argument %r: you can't use filenames or URLs " + "with --editable (except via the --find-links option)." + % (spec,) + ) + + def check_editable(self, spec): + if not self.editable: + return + + if os.path.exists(os.path.join(self.build_directory, spec.key)): + raise DistutilsArgError( + "%r already exists in %s; can't do a checkout there" % + (spec.key, self.build_directory) + ) + + @contextlib.contextmanager + def _tmpdir(self): + tmpdir = tempfile.mkdtemp(prefix=u"easy_install-") + try: + # cast to str as workaround for #709 and #710 and #712 + yield str(tmpdir) + finally: + os.path.exists(tmpdir) and rmtree(rmtree_safe(tmpdir)) + + def easy_install(self, spec, deps=False): + if not self.editable: + self.install_site_py() + + with self._tmpdir() as tmpdir: + if not isinstance(spec, Requirement): + if URL_SCHEME(spec): + # It's a url, download it to tmpdir and process + self.not_editable(spec) + dl = self.package_index.download(spec, tmpdir) + return self.install_item(None, dl, tmpdir, deps, True) + + elif os.path.exists(spec): + # Existing file or directory, just process it directly + self.not_editable(spec) + return self.install_item(None, spec, tmpdir, deps, True) + else: + spec = parse_requirement_arg(spec) + + self.check_editable(spec) + dist = self.package_index.fetch_distribution( + spec, tmpdir, self.upgrade, self.editable, + not self.always_copy, self.local_index + ) + if dist is None: + msg = "Could not find suitable distribution for %r" % spec + if self.always_copy: + msg += " (--always-copy skips system and development eggs)" + raise DistutilsError(msg) + elif dist.precedence == DEVELOP_DIST: + # .egg-info dists don't need installing, just process deps + self.process_distribution(spec, dist, deps, "Using") + return dist + else: + return self.install_item(spec, dist.location, tmpdir, deps) + + def install_item(self, spec, download, tmpdir, deps, install_needed=False): + + # Installation is also needed if file in tmpdir or is not an egg + install_needed = install_needed or self.always_copy + install_needed = install_needed or os.path.dirname(download) == tmpdir + install_needed = install_needed or not download.endswith('.egg') + install_needed = install_needed or ( + self.always_copy_from is not None and + os.path.dirname(normalize_path(download)) == + normalize_path(self.always_copy_from) + ) + + if spec and not install_needed: + # at this point, we know it's a local .egg, we just don't know if + # it's already installed. + for dist in self.local_index[spec.project_name]: + if dist.location == download: + break + else: + install_needed = True # it's not in the local index + + log.info("Processing %s", os.path.basename(download)) + + if install_needed: + dists = self.install_eggs(spec, download, tmpdir) + for dist in dists: + self.process_distribution(spec, dist, deps) + else: + dists = [self.egg_distribution(download)] + self.process_distribution(spec, dists[0], deps, "Using") + + if spec is not None: + for dist in dists: + if dist in spec: + return dist + + def select_scheme(self, name): + """Sets the install directories by applying the install schemes.""" + # it's the caller's problem if they supply a bad name! + scheme = INSTALL_SCHEMES[name] + for key in SCHEME_KEYS: + attrname = 'install_' + key + if getattr(self, attrname) is None: + setattr(self, attrname, scheme[key]) + + def process_distribution(self, requirement, dist, deps=True, *info): + self.update_pth(dist) + self.package_index.add(dist) + if dist in self.local_index[dist.key]: + self.local_index.remove(dist) + self.local_index.add(dist) + self.install_egg_scripts(dist) + self.installed_projects[dist.key] = dist + log.info(self.installation_report(requirement, dist, *info)) + if (dist.has_metadata('dependency_links.txt') and + not self.no_find_links): + self.package_index.add_find_links( + dist.get_metadata_lines('dependency_links.txt') + ) + if not deps and not self.always_copy: + return + elif requirement is not None and dist.key != requirement.key: + log.warn("Skipping dependencies for %s", dist) + return # XXX this is not the distribution we were looking for + elif requirement is None or dist not in requirement: + # if we wound up with a different version, resolve what we've got + distreq = dist.as_requirement() + requirement = Requirement(str(distreq)) + log.info("Processing dependencies for %s", requirement) + try: + distros = WorkingSet([]).resolve( + [requirement], self.local_index, self.easy_install + ) + except DistributionNotFound as e: + raise DistutilsError(str(e)) + except VersionConflict as e: + raise DistutilsError(e.report()) + if self.always_copy or self.always_copy_from: + # Force all the relevant distros to be copied or activated + for dist in distros: + if dist.key not in self.installed_projects: + self.easy_install(dist.as_requirement()) + log.info("Finished processing dependencies for %s", requirement) + + def should_unzip(self, dist): + if self.zip_ok is not None: + return not self.zip_ok + if dist.has_metadata('not-zip-safe'): + return True + if not dist.has_metadata('zip-safe'): + return True + return False + + def maybe_move(self, spec, dist_filename, setup_base): + dst = os.path.join(self.build_directory, spec.key) + if os.path.exists(dst): + msg = ( + "%r already exists in %s; build directory %s will not be kept" + ) + log.warn(msg, spec.key, self.build_directory, setup_base) + return setup_base + if os.path.isdir(dist_filename): + setup_base = dist_filename + else: + if os.path.dirname(dist_filename) == setup_base: + os.unlink(dist_filename) # get it out of the tmp dir + contents = os.listdir(setup_base) + if len(contents) == 1: + dist_filename = os.path.join(setup_base, contents[0]) + if os.path.isdir(dist_filename): + # if the only thing there is a directory, move it instead + setup_base = dist_filename + ensure_directory(dst) + shutil.move(setup_base, dst) + return dst + + def install_wrapper_scripts(self, dist): + if self.exclude_scripts: + return + for args in ScriptWriter.best().get_args(dist): + self.write_script(*args) + + def install_script(self, dist, script_name, script_text, dev_path=None): + """Generate a legacy script wrapper and install it""" + spec = str(dist.as_requirement()) + is_script = is_python_script(script_text, script_name) + + if is_script: + body = self._load_template(dev_path) % locals() + script_text = ScriptWriter.get_header(script_text) + body + self.write_script(script_name, _to_bytes(script_text), 'b') + + @staticmethod + def _load_template(dev_path): + """ + There are a couple of template scripts in the package. This + function loads one of them and prepares it for use. + """ + # See https://github.com/pypa/setuptools/issues/134 for info + # on script file naming and downstream issues with SVR4 + name = 'script.tmpl' + if dev_path: + name = name.replace('.tmpl', ' (dev).tmpl') + + raw_bytes = resource_string('setuptools', name) + return raw_bytes.decode('utf-8') + + def write_script(self, script_name, contents, mode="t", blockers=()): + """Write an executable file to the scripts directory""" + self.delete_blockers( # clean up old .py/.pyw w/o a script + [os.path.join(self.script_dir, x) for x in blockers] + ) + log.info("Installing %s script to %s", script_name, self.script_dir) + target = os.path.join(self.script_dir, script_name) + self.add_output(target) + + if self.dry_run: + return + + mask = current_umask() + ensure_directory(target) + if os.path.exists(target): + os.unlink(target) + with open(target, "w" + mode) as f: + f.write(contents) + chmod(target, 0o777 - mask) + + def install_eggs(self, spec, dist_filename, tmpdir): + # .egg dirs or files are already built, so just return them + if dist_filename.lower().endswith('.egg'): + return [self.install_egg(dist_filename, tmpdir)] + elif dist_filename.lower().endswith('.exe'): + return [self.install_exe(dist_filename, tmpdir)] + elif dist_filename.lower().endswith('.whl'): + return [self.install_wheel(dist_filename, tmpdir)] + + # Anything else, try to extract and build + setup_base = tmpdir + if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'): + unpack_archive(dist_filename, tmpdir, self.unpack_progress) + elif os.path.isdir(dist_filename): + setup_base = os.path.abspath(dist_filename) + + if (setup_base.startswith(tmpdir) # something we downloaded + and self.build_directory and spec is not None): + setup_base = self.maybe_move(spec, dist_filename, setup_base) + + # Find the setup.py file + setup_script = os.path.join(setup_base, 'setup.py') + + if not os.path.exists(setup_script): + setups = glob(os.path.join(setup_base, '*', 'setup.py')) + if not setups: + raise DistutilsError( + "Couldn't find a setup script in %s" % + os.path.abspath(dist_filename) + ) + if len(setups) > 1: + raise DistutilsError( + "Multiple setup scripts in %s" % + os.path.abspath(dist_filename) + ) + setup_script = setups[0] + + # Now run it, and return the result + if self.editable: + log.info(self.report_editable(spec, setup_script)) + return [] + else: + return self.build_and_install(setup_script, setup_base) + + def egg_distribution(self, egg_path): + if os.path.isdir(egg_path): + metadata = PathMetadata(egg_path, os.path.join(egg_path, + 'EGG-INFO')) + else: + metadata = EggMetadata(zipimport.zipimporter(egg_path)) + return Distribution.from_filename(egg_path, metadata=metadata) + + def install_egg(self, egg_path, tmpdir): + destination = os.path.join( + self.install_dir, + os.path.basename(egg_path), + ) + destination = os.path.abspath(destination) + if not self.dry_run: + ensure_directory(destination) + + dist = self.egg_distribution(egg_path) + if not samefile(egg_path, destination): + if os.path.isdir(destination) and not os.path.islink(destination): + dir_util.remove_tree(destination, dry_run=self.dry_run) + elif os.path.exists(destination): + self.execute( + os.unlink, + (destination,), + "Removing " + destination, + ) + try: + new_dist_is_zipped = False + if os.path.isdir(egg_path): + if egg_path.startswith(tmpdir): + f, m = shutil.move, "Moving" + else: + f, m = shutil.copytree, "Copying" + elif self.should_unzip(dist): + self.mkpath(destination) + f, m = self.unpack_and_compile, "Extracting" + else: + new_dist_is_zipped = True + if egg_path.startswith(tmpdir): + f, m = shutil.move, "Moving" + else: + f, m = shutil.copy2, "Copying" + self.execute( + f, + (egg_path, destination), + (m + " %s to %s") % ( + os.path.basename(egg_path), + os.path.dirname(destination) + ), + ) + update_dist_caches( + destination, + fix_zipimporter_caches=new_dist_is_zipped, + ) + except Exception: + update_dist_caches(destination, fix_zipimporter_caches=False) + raise + + self.add_output(destination) + return self.egg_distribution(destination) + + def install_exe(self, dist_filename, tmpdir): + # See if it's valid, get data + cfg = extract_wininst_cfg(dist_filename) + if cfg is None: + raise DistutilsError( + "%s is not a valid distutils Windows .exe" % dist_filename + ) + # Create a dummy distribution object until we build the real distro + dist = Distribution( + None, + project_name=cfg.get('metadata', 'name'), + version=cfg.get('metadata', 'version'), platform=get_platform(), + ) + + # Convert the .exe to an unpacked egg + egg_path = os.path.join(tmpdir, dist.egg_name() + '.egg') + dist.location = egg_path + egg_tmp = egg_path + '.tmp' + _egg_info = os.path.join(egg_tmp, 'EGG-INFO') + pkg_inf = os.path.join(_egg_info, 'PKG-INFO') + ensure_directory(pkg_inf) # make sure EGG-INFO dir exists + dist._provider = PathMetadata(egg_tmp, _egg_info) # XXX + self.exe_to_egg(dist_filename, egg_tmp) + + # Write EGG-INFO/PKG-INFO + if not os.path.exists(pkg_inf): + f = open(pkg_inf, 'w') + f.write('Metadata-Version: 1.0\n') + for k, v in cfg.items('metadata'): + if k != 'target_version': + f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) + f.close() + script_dir = os.path.join(_egg_info, 'scripts') + # delete entry-point scripts to avoid duping + self.delete_blockers([ + os.path.join(script_dir, args[0]) + for args in ScriptWriter.get_args(dist) + ]) + # Build .egg file from tmpdir + bdist_egg.make_zipfile( + egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run, + ) + # install the .egg + return self.install_egg(egg_path, tmpdir) + + def exe_to_egg(self, dist_filename, egg_tmp): + """Extract a bdist_wininst to the directories an egg would use""" + # Check for .pth file and set up prefix translations + prefixes = get_exe_prefixes(dist_filename) + to_compile = [] + native_libs = [] + top_level = {} + + def process(src, dst): + s = src.lower() + for old, new in prefixes: + if s.startswith(old): + src = new + src[len(old):] + parts = src.split('/') + dst = os.path.join(egg_tmp, *parts) + dl = dst.lower() + if dl.endswith('.pyd') or dl.endswith('.dll'): + parts[-1] = bdist_egg.strip_module(parts[-1]) + top_level[os.path.splitext(parts[0])[0]] = 1 + native_libs.append(src) + elif dl.endswith('.py') and old != 'SCRIPTS/': + top_level[os.path.splitext(parts[0])[0]] = 1 + to_compile.append(dst) + return dst + if not src.endswith('.pth'): + log.warn("WARNING: can't process %s", src) + return None + + # extract, tracking .pyd/.dll->native_libs and .py -> to_compile + unpack_archive(dist_filename, egg_tmp, process) + stubs = [] + for res in native_libs: + if res.lower().endswith('.pyd'): # create stubs for .pyd's + parts = res.split('/') + resource = parts[-1] + parts[-1] = bdist_egg.strip_module(parts[-1]) + '.py' + pyfile = os.path.join(egg_tmp, *parts) + to_compile.append(pyfile) + stubs.append(pyfile) + bdist_egg.write_stub(resource, pyfile) + self.byte_compile(to_compile) # compile .py's + bdist_egg.write_safety_flag( + os.path.join(egg_tmp, 'EGG-INFO'), + bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag + + for name in 'top_level', 'native_libs': + if locals()[name]: + txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt') + if not os.path.exists(txt): + f = open(txt, 'w') + f.write('\n'.join(locals()[name]) + '\n') + f.close() + + def install_wheel(self, wheel_path, tmpdir): + wheel = Wheel(wheel_path) + assert wheel.is_compatible() + destination = os.path.join(self.install_dir, wheel.egg_name()) + destination = os.path.abspath(destination) + if not self.dry_run: + ensure_directory(destination) + if os.path.isdir(destination) and not os.path.islink(destination): + dir_util.remove_tree(destination, dry_run=self.dry_run) + elif os.path.exists(destination): + self.execute( + os.unlink, + (destination,), + "Removing " + destination, + ) + try: + self.execute( + wheel.install_as_egg, + (destination,), + ("Installing %s to %s") % ( + os.path.basename(wheel_path), + os.path.dirname(destination) + ), + ) + finally: + update_dist_caches(destination, fix_zipimporter_caches=False) + self.add_output(destination) + return self.egg_distribution(destination) + + __mv_warning = textwrap.dedent(""" + Because this distribution was installed --multi-version, before you can + import modules from this package in an application, you will need to + 'import pkg_resources' and then use a 'require()' call similar to one of + these examples, in order to select the desired version: + + pkg_resources.require("%(name)s") # latest installed version + pkg_resources.require("%(name)s==%(version)s") # this exact version + pkg_resources.require("%(name)s>=%(version)s") # this version or higher + """).lstrip() + + __id_warning = textwrap.dedent(""" + Note also that the installation directory must be on sys.path at runtime for + this to work. (e.g. by being the application's script directory, by being on + PYTHONPATH, or by being added to sys.path by your code.) + """) + + def installation_report(self, req, dist, what="Installed"): + """Helpful installation message for display to package users""" + msg = "\n%(what)s %(eggloc)s%(extras)s" + if self.multi_version and not self.no_report: + msg += '\n' + self.__mv_warning + if self.install_dir not in map(normalize_path, sys.path): + msg += '\n' + self.__id_warning + + eggloc = dist.location + name = dist.project_name + version = dist.version + extras = '' # TODO: self.report_extras(req, dist) + return msg % locals() + + __editable_msg = textwrap.dedent(""" + Extracted editable version of %(spec)s to %(dirname)s + + If it uses setuptools in its setup script, you can activate it in + "development" mode by going to that directory and running:: + + %(python)s setup.py develop + + See the setuptools documentation for the "develop" command for more info. + """).lstrip() + + def report_editable(self, spec, setup_script): + dirname = os.path.dirname(setup_script) + python = sys.executable + return '\n' + self.__editable_msg % locals() + + def run_setup(self, setup_script, setup_base, args): + sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) + sys.modules.setdefault('distutils.command.egg_info', egg_info) + + args = list(args) + if self.verbose > 2: + v = 'v' * (self.verbose - 1) + args.insert(0, '-' + v) + elif self.verbose < 2: + args.insert(0, '-q') + if self.dry_run: + args.insert(0, '-n') + log.info( + "Running %s %s", setup_script[len(setup_base) + 1:], ' '.join(args) + ) + try: + run_setup(setup_script, args) + except SystemExit as v: + raise DistutilsError("Setup script exited with %s" % (v.args[0],)) + + def build_and_install(self, setup_script, setup_base): + args = ['bdist_egg', '--dist-dir'] + + dist_dir = tempfile.mkdtemp( + prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) + ) + try: + self._set_fetcher_options(os.path.dirname(setup_script)) + args.append(dist_dir) + + self.run_setup(setup_script, setup_base, args) + all_eggs = Environment([dist_dir]) + eggs = [] + for key in all_eggs: + for dist in all_eggs[key]: + eggs.append(self.install_egg(dist.location, setup_base)) + if not eggs and not self.dry_run: + log.warn("No eggs found in %s (setup script problem?)", + dist_dir) + return eggs + finally: + rmtree(dist_dir) + log.set_verbosity(self.verbose) # restore our log verbosity + + def _set_fetcher_options(self, base): + """ + When easy_install is about to run bdist_egg on a source dist, that + source dist might have 'setup_requires' directives, requiring + additional fetching. Ensure the fetcher options given to easy_install + are available to that command as well. + """ + # find the fetch options from easy_install and write them out + # to the setup.cfg file. + ei_opts = self.distribution.get_option_dict('easy_install').copy() + fetch_directives = ( + 'find_links', 'site_dirs', 'index_url', 'optimize', + 'site_dirs', 'allow_hosts', + ) + fetch_options = {} + for key, val in ei_opts.items(): + if key not in fetch_directives: + continue + fetch_options[key.replace('_', '-')] = val[1] + # create a settings dictionary suitable for `edit_config` + settings = dict(easy_install=fetch_options) + cfg_filename = os.path.join(base, 'setup.cfg') + setopt.edit_config(cfg_filename, settings) + + def update_pth(self, dist): + if self.pth_file is None: + return + + for d in self.pth_file[dist.key]: # drop old entries + if self.multi_version or d.location != dist.location: + log.info("Removing %s from easy-install.pth file", d) + self.pth_file.remove(d) + if d.location in self.shadow_path: + self.shadow_path.remove(d.location) + + if not self.multi_version: + if dist.location in self.pth_file.paths: + log.info( + "%s is already the active version in easy-install.pth", + dist, + ) + else: + log.info("Adding %s to easy-install.pth file", dist) + self.pth_file.add(dist) # add new entry + if dist.location not in self.shadow_path: + self.shadow_path.append(dist.location) + + if not self.dry_run: + + self.pth_file.save() + + if dist.key == 'setuptools': + # Ensure that setuptools itself never becomes unavailable! + # XXX should this check for latest version? + filename = os.path.join(self.install_dir, 'setuptools.pth') + if os.path.islink(filename): + os.unlink(filename) + f = open(filename, 'wt') + f.write(self.pth_file.make_relative(dist.location) + '\n') + f.close() + + def unpack_progress(self, src, dst): + # Progress filter for unpacking + log.debug("Unpacking %s to %s", src, dst) + return dst # only unpack-and-compile skips files for dry run + + def unpack_and_compile(self, egg_path, destination): + to_compile = [] + to_chmod = [] + + def pf(src, dst): + if dst.endswith('.py') and not src.startswith('EGG-INFO/'): + to_compile.append(dst) + elif dst.endswith('.dll') or dst.endswith('.so'): + to_chmod.append(dst) + self.unpack_progress(src, dst) + return not self.dry_run and dst or None + + unpack_archive(egg_path, destination, pf) + self.byte_compile(to_compile) + if not self.dry_run: + for f in to_chmod: + mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755 + chmod(f, mode) + + def byte_compile(self, to_compile): + if sys.dont_write_bytecode: + return + + from distutils.util import byte_compile + + try: + # try to make the byte compile messages quieter + log.set_verbosity(self.verbose - 1) + + byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) + if self.optimize: + byte_compile( + to_compile, optimize=self.optimize, force=1, + dry_run=self.dry_run, + ) + finally: + log.set_verbosity(self.verbose) # restore original verbosity + + __no_default_msg = textwrap.dedent(""" + bad install directory or PYTHONPATH + + You are attempting to install a package to a directory that is not + on PYTHONPATH and which Python does not read ".pth" files from. The + installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: + + %s + + and your PYTHONPATH environment variable currently contains: + + %r + + Here are some of your options for correcting the problem: + + * You can choose a different installation directory, i.e., one that is + on PYTHONPATH or supports .pth files + + * You can add the installation directory to the PYTHONPATH environment + variable. (It must then also be on PYTHONPATH whenever you run + Python and want to use the package(s) you are installing.) + + * You can set up the installation directory to support ".pth" files by + using one of the approaches described here: + + https://setuptools.readthedocs.io/en/latest/easy_install.html#custom-installation-locations + + + Please make the appropriate changes for your system and try again.""").lstrip() + + def no_default_version_msg(self): + template = self.__no_default_msg + return template % (self.install_dir, os.environ.get('PYTHONPATH', '')) + + def install_site_py(self): + """Make sure there's a site.py in the target dir, if needed""" + + if self.sitepy_installed: + return # already did it, or don't need to + + sitepy = os.path.join(self.install_dir, "site.py") + source = resource_string("setuptools", "site-patch.py") + source = source.decode('utf-8') + current = "" + + if os.path.exists(sitepy): + log.debug("Checking existing site.py in %s", self.install_dir) + with io.open(sitepy) as strm: + current = strm.read() + + if not current.startswith('def __boot():'): + raise DistutilsError( + "%s is not a setuptools-generated site.py; please" + " remove it." % sitepy + ) + + if current != source: + log.info("Creating %s", sitepy) + if not self.dry_run: + ensure_directory(sitepy) + with io.open(sitepy, 'w', encoding='utf-8') as strm: + strm.write(source) + self.byte_compile([sitepy]) + + self.sitepy_installed = True + + def create_home_path(self): + """Create directories under ~.""" + if not self.user: + return + home = convert_path(os.path.expanduser("~")) + for name, path in six.iteritems(self.config_vars): + if path.startswith(home) and not os.path.isdir(path): + self.debug_print("os.makedirs('%s', 0o700)" % path) + os.makedirs(path, 0o700) + + INSTALL_SCHEMES = dict( + posix=dict( + install_dir='$base/lib/python$py_version_short/site-packages', + script_dir='$base/bin', + ), + ) + + DEFAULT_SCHEME = dict( + install_dir='$base/Lib/site-packages', + script_dir='$base/Scripts', + ) + + def _expand(self, *attrs): + config_vars = self.get_finalized_command('install').config_vars + + if self.prefix: + # Set default install_dir/scripts from --prefix + config_vars = config_vars.copy() + config_vars['base'] = self.prefix + scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME) + for attr, val in scheme.items(): + if getattr(self, attr, None) is None: + setattr(self, attr, val) + + from distutils.util import subst_vars + + for attr in attrs: + val = getattr(self, attr) + if val is not None: + val = subst_vars(val, config_vars) + if os.name == 'posix': + val = os.path.expanduser(val) + setattr(self, attr, val) + + +def _pythonpath(): + items = os.environ.get('PYTHONPATH', '').split(os.pathsep) + return filter(None, items) + + +def get_site_dirs(): + """ + Return a list of 'site' dirs + """ + + sitedirs = [] + + # start with PYTHONPATH + sitedirs.extend(_pythonpath()) + + prefixes = [sys.prefix] + if sys.exec_prefix != sys.prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos'): + sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) + elif os.sep == '/': + sitedirs.extend([ + os.path.join( + prefix, + "lib", + "python" + sys.version[:3], + "site-packages", + ), + os.path.join(prefix, "lib", "site-python"), + ]) + else: + sitedirs.extend([ + prefix, + os.path.join(prefix, "lib", "site-packages"), + ]) + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + home_sp = os.path.join( + home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages', + ) + sitedirs.append(home_sp) + lib_paths = get_path('purelib'), get_path('platlib') + for site_lib in lib_paths: + if site_lib not in sitedirs: + sitedirs.append(site_lib) + + if site.ENABLE_USER_SITE: + sitedirs.append(site.USER_SITE) + + try: + sitedirs.extend(site.getsitepackages()) + except AttributeError: + pass + + sitedirs = list(map(normalize_path, sitedirs)) + + return sitedirs + + +def expand_paths(inputs): + """Yield sys.path directories that might contain "old-style" packages""" + + seen = {} + + for dirname in inputs: + dirname = normalize_path(dirname) + if dirname in seen: + continue + + seen[dirname] = 1 + if not os.path.isdir(dirname): + continue + + files = os.listdir(dirname) + yield dirname, files + + for name in files: + if not name.endswith('.pth'): + # We only care about the .pth files + continue + if name in ('easy-install.pth', 'setuptools.pth'): + # Ignore .pth files that we control + continue + + # Read the .pth file + f = open(os.path.join(dirname, name)) + lines = list(yield_lines(f)) + f.close() + + # Yield existing non-dupe, non-import directory lines from it + for line in lines: + if not line.startswith("import"): + line = normalize_path(line.rstrip()) + if line not in seen: + seen[line] = 1 + if not os.path.isdir(line): + continue + yield line, os.listdir(line) + + +def extract_wininst_cfg(dist_filename): + """Extract configuration data from a bdist_wininst .exe + + Returns a configparser.RawConfigParser, or None + """ + f = open(dist_filename, 'rb') + try: + endrec = zipfile._EndRecData(f) + if endrec is None: + return None + + prepended = (endrec[9] - endrec[5]) - endrec[6] + if prepended < 12: # no wininst data here + return None + f.seek(prepended - 12) + + tag, cfglen, bmlen = struct.unpack("<iii", f.read(12)) + if tag not in (0x1234567A, 0x1234567B): + return None # not a valid tag + + f.seek(prepended - (12 + cfglen)) + init = {'version': '', 'target_version': ''} + cfg = configparser.RawConfigParser(init) + try: + part = f.read(cfglen) + # Read up to the first null byte. + config = part.split(b'\0', 1)[0] + # Now the config is in bytes, but for RawConfigParser, it should + # be text, so decode it. + config = config.decode(sys.getfilesystemencoding()) + cfg.readfp(six.StringIO(config)) + except configparser.Error: + return None + if not cfg.has_section('metadata') or not cfg.has_section('Setup'): + return None + return cfg + + finally: + f.close() + + +def get_exe_prefixes(exe_filename): + """Get exe->egg path translations for a given .exe file""" + + prefixes = [ + ('PURELIB/', ''), + ('PLATLIB/pywin32_system32', ''), + ('PLATLIB/', ''), + ('SCRIPTS/', 'EGG-INFO/scripts/'), + ('DATA/lib/site-packages', ''), + ] + z = zipfile.ZipFile(exe_filename) + try: + for info in z.infolist(): + name = info.filename + parts = name.split('/') + if len(parts) == 3 and parts[2] == 'PKG-INFO': + if parts[1].endswith('.egg-info'): + prefixes.insert(0, ('/'.join(parts[:2]), 'EGG-INFO/')) + break + if len(parts) != 2 or not name.endswith('.pth'): + continue + if name.endswith('-nspkg.pth'): + continue + if parts[0].upper() in ('PURELIB', 'PLATLIB'): + contents = z.read(name) + if six.PY3: + contents = contents.decode() + for pth in yield_lines(contents): + pth = pth.strip().replace('\\', '/') + if not pth.startswith('import'): + prefixes.append((('%s/%s/' % (parts[0], pth)), '')) + finally: + z.close() + prefixes = [(x.lower(), y) for x, y in prefixes] + prefixes.sort() + prefixes.reverse() + return prefixes + + +class PthDistributions(Environment): + """A .pth file with Distribution paths in it""" + + dirty = False + + def __init__(self, filename, sitedirs=()): + self.filename = filename + self.sitedirs = list(map(normalize_path, sitedirs)) + self.basedir = normalize_path(os.path.dirname(self.filename)) + self._load() + Environment.__init__(self, [], None, None) + for path in yield_lines(self.paths): + list(map(self.add, find_distributions(path, True))) + + def _load(self): + self.paths = [] + saw_import = False + seen = dict.fromkeys(self.sitedirs) + if os.path.isfile(self.filename): + f = open(self.filename, 'rt') + for line in f: + if line.startswith('import'): + saw_import = True + continue + path = line.rstrip() + self.paths.append(path) + if not path.strip() or path.strip().startswith('#'): + continue + # skip non-existent paths, in case somebody deleted a package + # manually, and duplicate paths as well + path = self.paths[-1] = normalize_path( + os.path.join(self.basedir, path) + ) + if not os.path.exists(path) or path in seen: + self.paths.pop() # skip it + self.dirty = True # we cleaned up, so we're dirty now :) + continue + seen[path] = 1 + f.close() + + if self.paths and not saw_import: + self.dirty = True # ensure anything we touch has import wrappers + while self.paths and not self.paths[-1].strip(): + self.paths.pop() + + def save(self): + """Write changed .pth file back to disk""" + if not self.dirty: + return + + rel_paths = list(map(self.make_relative, self.paths)) + if rel_paths: + log.debug("Saving %s", self.filename) + lines = self._wrap_lines(rel_paths) + data = '\n'.join(lines) + '\n' + + if os.path.islink(self.filename): + os.unlink(self.filename) + with open(self.filename, 'wt') as f: + f.write(data) + + elif os.path.exists(self.filename): + log.debug("Deleting empty %s", self.filename) + os.unlink(self.filename) + + self.dirty = False + + @staticmethod + def _wrap_lines(lines): + return lines + + def add(self, dist): + """Add `dist` to the distribution map""" + new_path = ( + dist.location not in self.paths and ( + dist.location not in self.sitedirs or + # account for '.' being in PYTHONPATH + dist.location == os.getcwd() + ) + ) + if new_path: + self.paths.append(dist.location) + self.dirty = True + Environment.add(self, dist) + + def remove(self, dist): + """Remove `dist` from the distribution map""" + while dist.location in self.paths: + self.paths.remove(dist.location) + self.dirty = True + Environment.remove(self, dist) + + def make_relative(self, path): + npath, last = os.path.split(normalize_path(path)) + baselen = len(self.basedir) + parts = [last] + sep = os.altsep == '/' and '/' or os.sep + while len(npath) >= baselen: + if npath == self.basedir: + parts.append(os.curdir) + parts.reverse() + return sep.join(parts) + npath, last = os.path.split(npath) + parts.append(last) + else: + return path + + +class RewritePthDistributions(PthDistributions): + @classmethod + def _wrap_lines(cls, lines): + yield cls.prelude + for line in lines: + yield line + yield cls.postlude + + prelude = _one_liner(""" + import sys + sys.__plen = len(sys.path) + """) + postlude = _one_liner(""" + import sys + new = sys.path[sys.__plen:] + del sys.path[sys.__plen:] + p = getattr(sys, '__egginsert', 0) + sys.path[p:p] = new + sys.__egginsert = p + len(new) + """) + + +if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite': + PthDistributions = RewritePthDistributions + + +def _first_line_re(): + """ + Return a regular expression based on first_line_re suitable for matching + strings. + """ + if isinstance(first_line_re.pattern, str): + return first_line_re + + # first_line_re in Python >=3.1.4 and >=3.2.1 is a bytes pattern. + return re.compile(first_line_re.pattern.decode()) + + +def auto_chmod(func, arg, exc): + if func in [os.unlink, os.remove] and os.name == 'nt': + chmod(arg, stat.S_IWRITE) + return func(arg) + et, ev, _ = sys.exc_info() + six.reraise(et, (ev[0], ev[1] + (" %s %s" % (func, arg)))) + + +def update_dist_caches(dist_path, fix_zipimporter_caches): + """ + Fix any globally cached `dist_path` related data + + `dist_path` should be a path of a newly installed egg distribution (zipped + or unzipped). + + sys.path_importer_cache contains finder objects that have been cached when + importing data from the original distribution. Any such finders need to be + cleared since the replacement distribution might be packaged differently, + e.g. a zipped egg distribution might get replaced with an unzipped egg + folder or vice versa. Having the old finders cached may then cause Python + to attempt loading modules from the replacement distribution using an + incorrect loader. + + zipimport.zipimporter objects are Python loaders charged with importing + data packaged inside zip archives. If stale loaders referencing the + original distribution, are left behind, they can fail to load modules from + the replacement distribution. E.g. if an old zipimport.zipimporter instance + is used to load data from a new zipped egg archive, it may cause the + operation to attempt to locate the requested data in the wrong location - + one indicated by the original distribution's zip archive directory + information. Such an operation may then fail outright, e.g. report having + read a 'bad local file header', or even worse, it may fail silently & + return invalid data. + + zipimport._zip_directory_cache contains cached zip archive directory + information for all existing zipimport.zipimporter instances and all such + instances connected to the same archive share the same cached directory + information. + + If asked, and the underlying Python implementation allows it, we can fix + all existing zipimport.zipimporter instances instead of having to track + them down and remove them one by one, by updating their shared cached zip + archive directory information. This, of course, assumes that the + replacement distribution is packaged as a zipped egg. + + If not asked to fix existing zipimport.zipimporter instances, we still do + our best to clear any remaining zipimport.zipimporter related cached data + that might somehow later get used when attempting to load data from the new + distribution and thus cause such load operations to fail. Note that when + tracking down such remaining stale data, we can not catch every conceivable + usage from here, and we clear only those that we know of and have found to + cause problems if left alive. Any remaining caches should be updated by + whomever is in charge of maintaining them, i.e. they should be ready to + handle us replacing their zip archives with new distributions at runtime. + + """ + # There are several other known sources of stale zipimport.zipimporter + # instances that we do not clear here, but might if ever given a reason to + # do so: + # * Global setuptools pkg_resources.working_set (a.k.a. 'master working + # set') may contain distributions which may in turn contain their + # zipimport.zipimporter loaders. + # * Several zipimport.zipimporter loaders held by local variables further + # up the function call stack when running the setuptools installation. + # * Already loaded modules may have their __loader__ attribute set to the + # exact loader instance used when importing them. Python 3.4 docs state + # that this information is intended mostly for introspection and so is + # not expected to cause us problems. + normalized_path = normalize_path(dist_path) + _uncache(normalized_path, sys.path_importer_cache) + if fix_zipimporter_caches: + _replace_zip_directory_cache_data(normalized_path) + else: + # Here, even though we do not want to fix existing and now stale + # zipimporter cache information, we still want to remove it. Related to + # Python's zip archive directory information cache, we clear each of + # its stale entries in two phases: + # 1. Clear the entry so attempting to access zip archive information + # via any existing stale zipimport.zipimporter instances fails. + # 2. Remove the entry from the cache so any newly constructed + # zipimport.zipimporter instances do not end up using old stale + # zip archive directory information. + # This whole stale data removal step does not seem strictly necessary, + # but has been left in because it was done before we started replacing + # the zip archive directory information cache content if possible, and + # there are no relevant unit tests that we can depend on to tell us if + # this is really needed. + _remove_and_clear_zip_directory_cache_data(normalized_path) + + +def _collect_zipimporter_cache_entries(normalized_path, cache): + """ + Return zipimporter cache entry keys related to a given normalized path. + + Alternative path spellings (e.g. those using different character case or + those using alternative path separators) related to the same path are + included. Any sub-path entries are included as well, i.e. those + corresponding to zip archives embedded in other zip archives. + + """ + result = [] + prefix_len = len(normalized_path) + for p in cache: + np = normalize_path(p) + if (np.startswith(normalized_path) and + np[prefix_len:prefix_len + 1] in (os.sep, '')): + result.append(p) + return result + + +def _update_zipimporter_cache(normalized_path, cache, updater=None): + """ + Update zipimporter cache data for a given normalized path. + + Any sub-path entries are processed as well, i.e. those corresponding to zip + archives embedded in other zip archives. + + Given updater is a callable taking a cache entry key and the original entry + (after already removing the entry from the cache), and expected to update + the entry and possibly return a new one to be inserted in its place. + Returning None indicates that the entry should not be replaced with a new + one. If no updater is given, the cache entries are simply removed without + any additional processing, the same as if the updater simply returned None. + + """ + for p in _collect_zipimporter_cache_entries(normalized_path, cache): + # N.B. pypy's custom zipimport._zip_directory_cache implementation does + # not support the complete dict interface: + # * Does not support item assignment, thus not allowing this function + # to be used only for removing existing cache entries. + # * Does not support the dict.pop() method, forcing us to use the + # get/del patterns instead. For more detailed information see the + # following links: + # https://github.com/pypa/setuptools/issues/202#issuecomment-202913420 + # http://bit.ly/2h9itJX + old_entry = cache[p] + del cache[p] + new_entry = updater and updater(p, old_entry) + if new_entry is not None: + cache[p] = new_entry + + +def _uncache(normalized_path, cache): + _update_zipimporter_cache(normalized_path, cache) + + +def _remove_and_clear_zip_directory_cache_data(normalized_path): + def clear_and_remove_cached_zip_archive_directory_data(path, old_entry): + old_entry.clear() + + _update_zipimporter_cache( + normalized_path, zipimport._zip_directory_cache, + updater=clear_and_remove_cached_zip_archive_directory_data) + + +# PyPy Python implementation does not allow directly writing to the +# zipimport._zip_directory_cache and so prevents us from attempting to correct +# its content. The best we can do there is clear the problematic cache content +# and have PyPy repopulate it as needed. The downside is that if there are any +# stale zipimport.zipimporter instances laying around, attempting to use them +# will fail due to not having its zip archive directory information available +# instead of being automatically corrected to use the new correct zip archive +# directory information. +if '__pypy__' in sys.builtin_module_names: + _replace_zip_directory_cache_data = \ + _remove_and_clear_zip_directory_cache_data +else: + + def _replace_zip_directory_cache_data(normalized_path): + def replace_cached_zip_archive_directory_data(path, old_entry): + # N.B. In theory, we could load the zip directory information just + # once for all updated path spellings, and then copy it locally and + # update its contained path strings to contain the correct + # spelling, but that seems like a way too invasive move (this cache + # structure is not officially documented anywhere and could in + # theory change with new Python releases) for no significant + # benefit. + old_entry.clear() + zipimport.zipimporter(path) + old_entry.update(zipimport._zip_directory_cache[path]) + return old_entry + + _update_zipimporter_cache( + normalized_path, zipimport._zip_directory_cache, + updater=replace_cached_zip_archive_directory_data) + + +def is_python(text, filename='<string>'): + "Is this string a valid Python script?" + try: + compile(text, filename, 'exec') + except (SyntaxError, TypeError): + return False + else: + return True + + +def is_sh(executable): + """Determine if the specified executable is a .sh (contains a #! line)""" + try: + with io.open(executable, encoding='latin-1') as fp: + magic = fp.read(2) + except (OSError, IOError): + return executable + return magic == '#!' + + +def nt_quote_arg(arg): + """Quote a command line argument according to Windows parsing rules""" + return subprocess.list2cmdline([arg]) + + +def is_python_script(script_text, filename): + """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc. + """ + if filename.endswith('.py') or filename.endswith('.pyw'): + return True # extension says it's Python + if is_python(script_text, filename): + return True # it's syntactically valid Python + if script_text.startswith('#!'): + # It begins with a '#!' line, so check if 'python' is in it somewhere + return 'python' in script_text.splitlines()[0].lower() + + return False # Not any Python I can recognize + + +try: + from os import chmod as _chmod +except ImportError: + # Jython compatibility + def _chmod(*args): + pass + + +def chmod(path, mode): + log.debug("changing mode of %s to %o", path, mode) + try: + _chmod(path, mode) + except os.error as e: + log.debug("chmod failed: %s", e) + + +class CommandSpec(list): + """ + A command spec for a #! header, specified as a list of arguments akin to + those passed to Popen. + """ + + options = [] + split_args = dict() + + @classmethod + def best(cls): + """ + Choose the best CommandSpec class based on environmental conditions. + """ + return cls + + @classmethod + def _sys_executable(cls): + _default = os.path.normpath(sys.executable) + return os.environ.get('__PYVENV_LAUNCHER__', _default) + + @classmethod + def from_param(cls, param): + """ + Construct a CommandSpec from a parameter to build_scripts, which may + be None. + """ + if isinstance(param, cls): + return param + if isinstance(param, list): + return cls(param) + if param is None: + return cls.from_environment() + # otherwise, assume it's a string. + return cls.from_string(param) + + @classmethod + def from_environment(cls): + return cls([cls._sys_executable()]) + + @classmethod + def from_string(cls, string): + """ + Construct a command spec from a simple string representing a command + line parseable by shlex.split. + """ + items = shlex.split(string, **cls.split_args) + return cls(items) + + def install_options(self, script_text): + self.options = shlex.split(self._extract_options(script_text)) + cmdline = subprocess.list2cmdline(self) + if not isascii(cmdline): + self.options[:0] = ['-x'] + + @staticmethod + def _extract_options(orig_script): + """ + Extract any options from the first line of the script. + """ + first = (orig_script + '\n').splitlines()[0] + match = _first_line_re().match(first) + options = match.group(1) or '' if match else '' + return options.strip() + + def as_header(self): + return self._render(self + list(self.options)) + + @staticmethod + def _strip_quotes(item): + _QUOTES = '"\'' + for q in _QUOTES: + if item.startswith(q) and item.endswith(q): + return item[1:-1] + return item + + @staticmethod + def _render(items): + cmdline = subprocess.list2cmdline( + CommandSpec._strip_quotes(item.strip()) for item in items) + return '#!' + cmdline + '\n' + + +# For pbr compat; will be removed in a future version. +sys_executable = CommandSpec._sys_executable() + + +class WindowsCommandSpec(CommandSpec): + split_args = dict(posix=False) + + +class ScriptWriter: + """ + Encapsulates behavior around writing entry point scripts for console and + gui apps. + """ + + template = textwrap.dedent(r""" + # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r + __requires__ = %(spec)r + import re + import sys + from pkg_resources import load_entry_point + + if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit( + load_entry_point(%(spec)r, %(group)r, %(name)r)() + ) + """).lstrip() + + command_spec_class = CommandSpec + + @classmethod + def get_script_args(cls, dist, executable=None, wininst=False): + # for backward compatibility + warnings.warn("Use get_args", EasyInstallDeprecationWarning) + writer = (WindowsScriptWriter if wininst else ScriptWriter).best() + header = cls.get_script_header("", executable, wininst) + return writer.get_args(dist, header) + + @classmethod + def get_script_header(cls, script_text, executable=None, wininst=False): + # for backward compatibility + warnings.warn("Use get_header", EasyInstallDeprecationWarning, stacklevel=2) + if wininst: + executable = "python.exe" + return cls.get_header(script_text, executable) + + @classmethod + def get_args(cls, dist, header=None): + """ + Yield write_script() argument tuples for a distribution's + console_scripts and gui_scripts entry points. + """ + if header is None: + header = cls.get_header() + spec = str(dist.as_requirement()) + for type_ in 'console', 'gui': + group = type_ + '_scripts' + for name, ep in dist.get_entry_map(group).items(): + cls._ensure_safe_name(name) + script_text = cls.template % locals() + args = cls._get_script_args(type_, name, header, script_text) + for res in args: + yield res + + @staticmethod + def _ensure_safe_name(name): + """ + Prevent paths in *_scripts entry point names. + """ + has_path_sep = re.search(r'[\\/]', name) + if has_path_sep: + raise ValueError("Path separators not allowed in script names") + + @classmethod + def get_writer(cls, force_windows): + # for backward compatibility + warnings.warn("Use best", EasyInstallDeprecationWarning) + return WindowsScriptWriter.best() if force_windows else cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter for this environment. + """ + if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'): + return WindowsScriptWriter.best() + else: + return cls + + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + # Simply write the stub with no extension. + yield (name, header + script_text) + + @classmethod + def get_header(cls, script_text="", executable=None): + """Create a #! line, getting options (if any) from script_text""" + cmd = cls.command_spec_class.best().from_param(executable) + cmd.install_options(script_text) + return cmd.as_header() + + +class WindowsScriptWriter(ScriptWriter): + command_spec_class = WindowsCommandSpec + + @classmethod + def get_writer(cls): + # for backward compatibility + warnings.warn("Use best", EasyInstallDeprecationWarning) + return cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter suitable for Windows + """ + writer_lookup = dict( + executable=WindowsExecutableLauncherWriter, + natural=cls, + ) + # for compatibility, use the executable launcher by default + launcher = os.environ.get('SETUPTOOLS_LAUNCHER', 'executable') + return writer_lookup[launcher] + + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + "For Windows, add a .py extension" + ext = dict(console='.pya', gui='.pyw')[type_] + if ext not in os.environ['PATHEXT'].lower().split(';'): + msg = ( + "{ext} not listed in PATHEXT; scripts will not be " + "recognized as executables." + ).format(**locals()) + warnings.warn(msg, UserWarning) + old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe'] + old.remove(ext) + header = cls._adjust_header(type_, header) + blockers = [name + x for x in old] + yield name + ext, header + script_text, 't', blockers + + @classmethod + def _adjust_header(cls, type_, orig_header): + """ + Make sure 'pythonw' is used for gui and and 'python' is used for + console (regardless of what sys.executable is). + """ + pattern = 'pythonw.exe' + repl = 'python.exe' + if type_ == 'gui': + pattern, repl = repl, pattern + pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) + new_header = pattern_ob.sub(string=orig_header, repl=repl) + return new_header if cls._use_header(new_header) else orig_header + + @staticmethod + def _use_header(new_header): + """ + Should _adjust_header use the replaced header? + + On non-windows systems, always use. On + Windows systems, only use the replaced header if it resolves + to an executable on the system. + """ + clean_header = new_header[2:-1].strip('"') + return sys.platform != 'win32' or find_executable(clean_header) + + +class WindowsExecutableLauncherWriter(WindowsScriptWriter): + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + """ + For Windows, add a .py extension and an .exe launcher + """ + if type_ == 'gui': + launcher_type = 'gui' + ext = '-script.pyw' + old = ['.pyw'] + else: + launcher_type = 'cli' + ext = '-script.py' + old = ['.py', '.pyc', '.pyo'] + hdr = cls._adjust_header(type_, header) + blockers = [name + x for x in old] + yield (name + ext, hdr + script_text, 't', blockers) + yield ( + name + '.exe', get_win_launcher(launcher_type), + 'b' # write in binary mode + ) + if not is_64bit(): + # install a manifest for the launcher to prevent Windows + # from detecting it as an installer (which it will for + # launchers like easy_install.exe). Consider only + # adding a manifest for launchers detected as installers. + # See Distribute #143 for details. + m_name = name + '.exe.manifest' + yield (m_name, load_launcher_manifest(name), 't') + + +# for backward-compatibility +get_script_args = ScriptWriter.get_script_args +get_script_header = ScriptWriter.get_script_header + + +def get_win_launcher(type): + """ + Load the Windows launcher (executable) suitable for launching a script. + + `type` should be either 'cli' or 'gui' + + Returns the executable as a byte string. + """ + launcher_fn = '%s.exe' % type + if is_64bit(): + launcher_fn = launcher_fn.replace(".", "-64.") + else: + launcher_fn = launcher_fn.replace(".", "-32.") + return resource_string('setuptools', launcher_fn) + + +def load_launcher_manifest(name): + manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml') + if six.PY2: + return manifest % vars() + else: + return manifest.decode('utf-8') % vars() + + +def rmtree(path, ignore_errors=False, onerror=auto_chmod): + return shutil.rmtree(path, ignore_errors, onerror) + + +def current_umask(): + tmp = os.umask(0o022) + os.umask(tmp) + return tmp + + +def bootstrap(): + # This function is called when setuptools*.egg is run using /bin/sh + import setuptools + + argv0 = os.path.dirname(setuptools.__path__[0]) + sys.argv[0] = argv0 + sys.argv.append(argv0) + main() + + +def main(argv=None, **kw): + from setuptools import setup + from setuptools.dist import Distribution + + class DistributionWithoutHelpCommands(Distribution): + common_usage = "" + + def _show_help(self, *args, **kw): + with _patch_usage(): + Distribution._show_help(self, *args, **kw) + + if argv is None: + argv = sys.argv[1:] + + with _patch_usage(): + setup( + script_args=['-q', 'easy_install', '-v'] + argv, + script_name=sys.argv[0] or 'easy_install', + distclass=DistributionWithoutHelpCommands, + **kw + ) + + +@contextlib.contextmanager +def _patch_usage(): + import distutils.core + USAGE = textwrap.dedent(""" + usage: %(script)s [options] requirement_or_url ... + or: %(script)s --help + """).lstrip() + + def gen_usage(script_name): + return USAGE % dict( + script=os.path.basename(script_name), + ) + + saved = distutils.core.gen_usage + distutils.core.gen_usage = gen_usage + try: + yield + finally: + distutils.core.gen_usage = saved + +class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in EasyInstall in SetupTools. Not ignored by default, unlike DeprecationWarning.""" + diff --git a/venv/lib/python3.7/site-packages/setuptools/command/egg_info.py b/venv/lib/python3.7/site-packages/setuptools/command/egg_info.py new file mode 100644 index 0000000..d9fe3da --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/egg_info.py @@ -0,0 +1,716 @@ +"""setuptools.command.egg_info + +Create a distribution's .egg-info directory and contents""" + +from distutils.filelist import FileList as _FileList +from distutils.errors import DistutilsInternalError +from distutils.util import convert_path +from distutils import log +import distutils.errors +import distutils.filelist +import os +import re +import sys +import io +import warnings +import time +import collections + +from setuptools.extern import six +from setuptools.extern.six.moves import map + +from setuptools import Command +from setuptools.command.sdist import sdist +from setuptools.command.sdist import walk_revctrl +from setuptools.command.setopt import edit_config +from setuptools.command import bdist_egg +from pkg_resources import ( + parse_requirements, safe_name, parse_version, + safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename) +import setuptools.unicode_utils as unicode_utils +from setuptools.glob import glob + +from setuptools.extern import packaging +from setuptools import SetuptoolsDeprecationWarning + +def translate_pattern(glob): + """ + Translate a file path glob like '*.txt' in to a regular expression. + This differs from fnmatch.translate which allows wildcards to match + directory separators. It also knows about '**/' which matches any number of + directories. + """ + pat = '' + + # This will split on '/' within [character classes]. This is deliberate. + chunks = glob.split(os.path.sep) + + sep = re.escape(os.sep) + valid_char = '[^%s]' % (sep,) + + for c, chunk in enumerate(chunks): + last_chunk = c == len(chunks) - 1 + + # Chunks that are a literal ** are globstars. They match anything. + if chunk == '**': + if last_chunk: + # Match anything if this is the last component + pat += '.*' + else: + # Match '(name/)*' + pat += '(?:%s+%s)*' % (valid_char, sep) + continue # Break here as the whole path component has been handled + + # Find any special characters in the remainder + i = 0 + chunk_len = len(chunk) + while i < chunk_len: + char = chunk[i] + if char == '*': + # Match any number of name characters + pat += valid_char + '*' + elif char == '?': + # Match a name character + pat += valid_char + elif char == '[': + # Character class + inner_i = i + 1 + # Skip initial !/] chars + if inner_i < chunk_len and chunk[inner_i] == '!': + inner_i = inner_i + 1 + if inner_i < chunk_len and chunk[inner_i] == ']': + inner_i = inner_i + 1 + + # Loop till the closing ] is found + while inner_i < chunk_len and chunk[inner_i] != ']': + inner_i = inner_i + 1 + + if inner_i >= chunk_len: + # Got to the end of the string without finding a closing ] + # Do not treat this as a matching group, but as a literal [ + pat += re.escape(char) + else: + # Grab the insides of the [brackets] + inner = chunk[i + 1:inner_i] + char_class = '' + + # Class negation + if inner[0] == '!': + char_class = '^' + inner = inner[1:] + + char_class += re.escape(inner) + pat += '[%s]' % (char_class,) + + # Skip to the end ] + i = inner_i + else: + pat += re.escape(char) + i += 1 + + # Join each chunk with the dir separator + if not last_chunk: + pat += sep + + pat += r'\Z' + return re.compile(pat, flags=re.MULTILINE|re.DOTALL) + + +class InfoCommon: + tag_build = None + tag_date = None + + @property + def name(self): + return safe_name(self.distribution.get_name()) + + def tagged_version(self): + version = self.distribution.get_version() + # egg_info may be called more than once for a distribution, + # in which case the version string already contains all tags. + if self.vtags and version.endswith(self.vtags): + return safe_version(version) + return safe_version(version + self.vtags) + + def tags(self): + version = '' + if self.tag_build: + version += self.tag_build + if self.tag_date: + version += time.strftime("-%Y%m%d") + return version + vtags = property(tags) + + +class egg_info(InfoCommon, Command): + description = "create a distribution's .egg-info directory" + + user_options = [ + ('egg-base=', 'e', "directory containing .egg-info directories" + " (default: top of the source tree)"), + ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), + ('tag-build=', 'b', "Specify explicit tag to add to version number"), + ('no-date', 'D', "Don't include date stamp [default]"), + ] + + boolean_options = ['tag-date'] + negative_opt = { + 'no-date': 'tag-date', + } + + def initialize_options(self): + self.egg_base = None + self.egg_name = None + self.egg_info = None + self.egg_version = None + self.broken_egg_info = False + + #################################### + # allow the 'tag_svn_revision' to be detected and + # set, supporting sdists built on older Setuptools. + @property + def tag_svn_revision(self): + pass + + @tag_svn_revision.setter + def tag_svn_revision(self, value): + pass + #################################### + + def save_version_info(self, filename): + """ + Materialize the value of date into the + build tag. Install build keys in a deterministic order + to avoid arbitrary reordering on subsequent builds. + """ + egg_info = collections.OrderedDict() + # follow the order these keys would have been added + # when PYTHONHASHSEED=0 + egg_info['tag_build'] = self.tags() + egg_info['tag_date'] = 0 + edit_config(filename, dict(egg_info=egg_info)) + + def finalize_options(self): + # Note: we need to capture the current value returned + # by `self.tagged_version()`, so we can later update + # `self.distribution.metadata.version` without + # repercussions. + self.egg_name = self.name + self.egg_version = self.tagged_version() + parsed_version = parse_version(self.egg_version) + + try: + is_version = isinstance(parsed_version, packaging.version.Version) + spec = ( + "%s==%s" if is_version else "%s===%s" + ) + list( + parse_requirements(spec % (self.egg_name, self.egg_version)) + ) + except ValueError: + raise distutils.errors.DistutilsOptionError( + "Invalid distribution name or version syntax: %s-%s" % + (self.egg_name, self.egg_version) + ) + + if self.egg_base is None: + dirs = self.distribution.package_dir + self.egg_base = (dirs or {}).get('', os.curdir) + + self.ensure_dirname('egg_base') + self.egg_info = to_filename(self.egg_name) + '.egg-info' + if self.egg_base != os.curdir: + self.egg_info = os.path.join(self.egg_base, self.egg_info) + if '-' in self.egg_name: + self.check_broken_egg_info() + + # Set package version for the benefit of dumber commands + # (e.g. sdist, bdist_wininst, etc.) + # + self.distribution.metadata.version = self.egg_version + + # If we bootstrapped around the lack of a PKG-INFO, as might be the + # case in a fresh checkout, make sure that any special tags get added + # to the version info + # + pd = self.distribution._patched_dist + if pd is not None and pd.key == self.egg_name.lower(): + pd._version = self.egg_version + pd._parsed_version = parse_version(self.egg_version) + self.distribution._patched_dist = None + + def write_or_delete_file(self, what, filename, data, force=False): + """Write `data` to `filename` or delete if empty + + If `data` is non-empty, this routine is the same as ``write_file()``. + If `data` is empty but not ``None``, this is the same as calling + ``delete_file(filename)`. If `data` is ``None``, then this is a no-op + unless `filename` exists, in which case a warning is issued about the + orphaned file (if `force` is false), or deleted (if `force` is true). + """ + if data: + self.write_file(what, filename, data) + elif os.path.exists(filename): + if data is None and not force: + log.warn( + "%s not set in setup(), but %s exists", what, filename + ) + return + else: + self.delete_file(filename) + + def write_file(self, what, filename, data): + """Write `data` to `filename` (if not a dry run) after announcing it + + `what` is used in a log message to identify what is being written + to the file. + """ + log.info("writing %s to %s", what, filename) + if six.PY3: + data = data.encode("utf-8") + if not self.dry_run: + f = open(filename, 'wb') + f.write(data) + f.close() + + def delete_file(self, filename): + """Delete `filename` (if not a dry run) after announcing it""" + log.info("deleting %s", filename) + if not self.dry_run: + os.unlink(filename) + + def run(self): + self.mkpath(self.egg_info) + os.utime(self.egg_info, None) + installer = self.distribution.fetch_build_egg + for ep in iter_entry_points('egg_info.writers'): + ep.require(installer=installer) + writer = ep.resolve() + writer(self, ep.name, os.path.join(self.egg_info, ep.name)) + + # Get rid of native_libs.txt if it was put there by older bdist_egg + nl = os.path.join(self.egg_info, "native_libs.txt") + if os.path.exists(nl): + self.delete_file(nl) + + self.find_sources() + + def find_sources(self): + """Generate SOURCES.txt manifest file""" + manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") + mm = manifest_maker(self.distribution) + mm.manifest = manifest_filename + mm.run() + self.filelist = mm.filelist + + def check_broken_egg_info(self): + bei = self.egg_name + '.egg-info' + if self.egg_base != os.curdir: + bei = os.path.join(self.egg_base, bei) + if os.path.exists(bei): + log.warn( + "-" * 78 + '\n' + "Note: Your current .egg-info directory has a '-' in its name;" + '\nthis will not work correctly with "setup.py develop".\n\n' + 'Please rename %s to %s to correct this problem.\n' + '-' * 78, + bei, self.egg_info + ) + self.broken_egg_info = self.egg_info + self.egg_info = bei # make it work for now + + +class FileList(_FileList): + # Implementations of the various MANIFEST.in commands + + def process_template_line(self, line): + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dir_pattern). + (action, patterns, dir, dir_pattern) = self._parse_template_line(line) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + self.debug_print("include " + ' '.join(patterns)) + for pattern in patterns: + if not self.include(pattern): + log.warn("warning: no files found matching '%s'", pattern) + + elif action == 'exclude': + self.debug_print("exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.exclude(pattern): + log.warn(("warning: no previously-included files " + "found matching '%s'"), pattern) + + elif action == 'global-include': + self.debug_print("global-include " + ' '.join(patterns)) + for pattern in patterns: + if not self.global_include(pattern): + log.warn(("warning: no files found matching '%s' " + "anywhere in distribution"), pattern) + + elif action == 'global-exclude': + self.debug_print("global-exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.global_exclude(pattern): + log.warn(("warning: no previously-included files matching " + "'%s' found anywhere in distribution"), + pattern) + + elif action == 'recursive-include': + self.debug_print("recursive-include %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.recursive_include(dir, pattern): + log.warn(("warning: no files found matching '%s' " + "under directory '%s'"), + pattern, dir) + + elif action == 'recursive-exclude': + self.debug_print("recursive-exclude %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.recursive_exclude(dir, pattern): + log.warn(("warning: no previously-included files matching " + "'%s' found under directory '%s'"), + pattern, dir) + + elif action == 'graft': + self.debug_print("graft " + dir_pattern) + if not self.graft(dir_pattern): + log.warn("warning: no directories found matching '%s'", + dir_pattern) + + elif action == 'prune': + self.debug_print("prune " + dir_pattern) + if not self.prune(dir_pattern): + log.warn(("no previously-included directories found " + "matching '%s'"), dir_pattern) + + else: + raise DistutilsInternalError( + "this cannot happen: invalid action '%s'" % action) + + def _remove_files(self, predicate): + """ + Remove all files from the file list that match the predicate. + Return True if any matching files were removed + """ + found = False + for i in range(len(self.files) - 1, -1, -1): + if predicate(self.files[i]): + self.debug_print(" removing " + self.files[i]) + del self.files[i] + found = True + return found + + def include(self, pattern): + """Include files that match 'pattern'.""" + found = [f for f in glob(pattern) if not os.path.isdir(f)] + self.extend(found) + return bool(found) + + def exclude(self, pattern): + """Exclude files that match 'pattern'.""" + match = translate_pattern(pattern) + return self._remove_files(match.match) + + def recursive_include(self, dir, pattern): + """ + Include all files anywhere in 'dir/' that match the pattern. + """ + full_pattern = os.path.join(dir, '**', pattern) + found = [f for f in glob(full_pattern, recursive=True) + if not os.path.isdir(f)] + self.extend(found) + return bool(found) + + def recursive_exclude(self, dir, pattern): + """ + Exclude any file anywhere in 'dir/' that match the pattern. + """ + match = translate_pattern(os.path.join(dir, '**', pattern)) + return self._remove_files(match.match) + + def graft(self, dir): + """Include all files from 'dir/'.""" + found = [ + item + for match_dir in glob(dir) + for item in distutils.filelist.findall(match_dir) + ] + self.extend(found) + return bool(found) + + def prune(self, dir): + """Filter out files from 'dir/'.""" + match = translate_pattern(os.path.join(dir, '**')) + return self._remove_files(match.match) + + def global_include(self, pattern): + """ + Include all files anywhere in the current directory that match the + pattern. This is very inefficient on large file trees. + """ + if self.allfiles is None: + self.findall() + match = translate_pattern(os.path.join('**', pattern)) + found = [f for f in self.allfiles if match.match(f)] + self.extend(found) + return bool(found) + + def global_exclude(self, pattern): + """ + Exclude all files anywhere that match the pattern. + """ + match = translate_pattern(os.path.join('**', pattern)) + return self._remove_files(match.match) + + def append(self, item): + if item.endswith('\r'): # Fix older sdists built on Windows + item = item[:-1] + path = convert_path(item) + + if self._safe_path(path): + self.files.append(path) + + def extend(self, paths): + self.files.extend(filter(self._safe_path, paths)) + + def _repair(self): + """ + Replace self.files with only safe paths + + Because some owners of FileList manipulate the underlying + ``files`` attribute directly, this method must be called to + repair those paths. + """ + self.files = list(filter(self._safe_path, self.files)) + + def _safe_path(self, path): + enc_warn = "'%s' not %s encodable -- skipping" + + # To avoid accidental trans-codings errors, first to unicode + u_path = unicode_utils.filesys_decode(path) + if u_path is None: + log.warn("'%s' in unexpected encoding -- skipping" % path) + return False + + # Must ensure utf-8 encodability + utf8_path = unicode_utils.try_encode(u_path, "utf-8") + if utf8_path is None: + log.warn(enc_warn, path, 'utf-8') + return False + + try: + # accept is either way checks out + if os.path.exists(u_path) or os.path.exists(utf8_path): + return True + # this will catch any encode errors decoding u_path + except UnicodeEncodeError: + log.warn(enc_warn, path, sys.getfilesystemencoding()) + + +class manifest_maker(sdist): + template = "MANIFEST.in" + + def initialize_options(self): + self.use_defaults = 1 + self.prune = 1 + self.manifest_only = 1 + self.force_manifest = 1 + + def finalize_options(self): + pass + + def run(self): + self.filelist = FileList() + if not os.path.exists(self.manifest): + self.write_manifest() # it must exist so it'll get in the list + self.add_defaults() + if os.path.exists(self.template): + self.read_template() + self.prune_file_list() + self.filelist.sort() + self.filelist.remove_duplicates() + self.write_manifest() + + def _manifest_normalize(self, path): + path = unicode_utils.filesys_decode(path) + return path.replace(os.sep, '/') + + def write_manifest(self): + """ + Write the file list in 'self.filelist' to the manifest file + named by 'self.manifest'. + """ + self.filelist._repair() + + # Now _repairs should encodability, but not unicode + files = [self._manifest_normalize(f) for f in self.filelist.files] + msg = "writing manifest file '%s'" % self.manifest + self.execute(write_file, (self.manifest, files), msg) + + def warn(self, msg): + if not self._should_suppress_warning(msg): + sdist.warn(self, msg) + + @staticmethod + def _should_suppress_warning(msg): + """ + suppress missing-file warnings from sdist + """ + return re.match(r"standard file .*not found", msg) + + def add_defaults(self): + sdist.add_defaults(self) + self.filelist.append(self.template) + self.filelist.append(self.manifest) + rcfiles = list(walk_revctrl()) + if rcfiles: + self.filelist.extend(rcfiles) + elif os.path.exists(self.manifest): + self.read_manifest() + + if os.path.exists("setup.py"): + # setup.py should be included by default, even if it's not + # the script called to create the sdist + self.filelist.append("setup.py") + + ei_cmd = self.get_finalized_command('egg_info') + self.filelist.graft(ei_cmd.egg_info) + + def prune_file_list(self): + build = self.get_finalized_command('build') + base_dir = self.distribution.get_fullname() + self.filelist.prune(build.build_base) + self.filelist.prune(base_dir) + sep = re.escape(os.sep) + self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, + is_regex=1) + + +def write_file(filename, contents): + """Create a file with the specified name and write 'contents' (a + sequence of strings without line terminators) to it. + """ + contents = "\n".join(contents) + + # assuming the contents has been vetted for utf-8 encoding + contents = contents.encode("utf-8") + + with open(filename, "wb") as f: # always write POSIX-style manifest + f.write(contents) + + +def write_pkg_info(cmd, basename, filename): + log.info("writing %s", filename) + if not cmd.dry_run: + metadata = cmd.distribution.metadata + metadata.version, oldver = cmd.egg_version, metadata.version + metadata.name, oldname = cmd.egg_name, metadata.name + + try: + # write unescaped data to PKG-INFO, so older pkg_resources + # can still parse it + metadata.write_pkg_info(cmd.egg_info) + finally: + metadata.name, metadata.version = oldname, oldver + + safe = getattr(cmd.distribution, 'zip_safe', None) + + bdist_egg.write_safety_flag(cmd.egg_info, safe) + + +def warn_depends_obsolete(cmd, basename, filename): + if os.path.exists(filename): + log.warn( + "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" + "Use the install_requires/extras_require setup() args instead." + ) + + +def _write_requirements(stream, reqs): + lines = yield_lines(reqs or ()) + append_cr = lambda line: line + '\n' + lines = map(append_cr, lines) + stream.writelines(lines) + + +def write_requirements(cmd, basename, filename): + dist = cmd.distribution + data = six.StringIO() + _write_requirements(data, dist.install_requires) + extras_require = dist.extras_require or {} + for extra in sorted(extras_require): + data.write('\n[{extra}]\n'.format(**vars())) + _write_requirements(data, extras_require[extra]) + cmd.write_or_delete_file("requirements", filename, data.getvalue()) + + +def write_setup_requirements(cmd, basename, filename): + data = io.StringIO() + _write_requirements(data, cmd.distribution.setup_requires) + cmd.write_or_delete_file("setup-requirements", filename, data.getvalue()) + + +def write_toplevel_names(cmd, basename, filename): + pkgs = dict.fromkeys( + [ + k.split('.', 1)[0] + for k in cmd.distribution.iter_distribution_names() + ] + ) + cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') + + +def overwrite_arg(cmd, basename, filename): + write_arg(cmd, basename, filename, True) + + +def write_arg(cmd, basename, filename, force=False): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = '\n'.join(value) + '\n' + cmd.write_or_delete_file(argname, filename, value, force) + + +def write_entries(cmd, basename, filename): + ep = cmd.distribution.entry_points + + if isinstance(ep, six.string_types) or ep is None: + data = ep + elif ep is not None: + data = [] + for section, contents in sorted(ep.items()): + if not isinstance(contents, six.string_types): + contents = EntryPoint.parse_group(section, contents) + contents = '\n'.join(sorted(map(str, contents.values()))) + data.append('[%s]\n%s\n\n' % (section, contents)) + data = ''.join(data) + + cmd.write_or_delete_file('entry points', filename, data, True) + + +def get_pkg_info_revision(): + """ + Get a -r### off of PKG-INFO Version in case this is an sdist of + a subversion revision. + """ + warnings.warn("get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning) + if os.path.exists('PKG-INFO'): + with io.open('PKG-INFO') as f: + for line in f: + match = re.match(r"Version:.*-r(\d+)\s*$", line) + if match: + return int(match.group(1)) + return 0 + + +class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in eggInfo in setupTools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/venv/lib/python3.7/site-packages/setuptools/command/install.py b/venv/lib/python3.7/site-packages/setuptools/command/install.py new file mode 100644 index 0000000..31a5ddb --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/install.py @@ -0,0 +1,125 @@ +from distutils.errors import DistutilsArgError +import inspect +import glob +import warnings +import platform +import distutils.command.install as orig + +import setuptools + +# Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for +# now. See https://github.com/pypa/setuptools/issues/199/ +_install = orig.install + + +class install(orig.install): + """Use easy_install to install the package, w/dependencies""" + + user_options = orig.install.user_options + [ + ('old-and-unmanageable', None, "Try not to use this!"), + ('single-version-externally-managed', None, + "used by system package builders to create 'flat' eggs"), + ] + boolean_options = orig.install.boolean_options + [ + 'old-and-unmanageable', 'single-version-externally-managed', + ] + new_commands = [ + ('install_egg_info', lambda self: True), + ('install_scripts', lambda self: True), + ] + _nc = dict(new_commands) + + def initialize_options(self): + orig.install.initialize_options(self) + self.old_and_unmanageable = None + self.single_version_externally_managed = None + + def finalize_options(self): + orig.install.finalize_options(self) + if self.root: + self.single_version_externally_managed = True + elif self.single_version_externally_managed: + if not self.root and not self.record: + raise DistutilsArgError( + "You must specify --record or --root when building system" + " packages" + ) + + def handle_extra_path(self): + if self.root or self.single_version_externally_managed: + # explicit backward-compatibility mode, allow extra_path to work + return orig.install.handle_extra_path(self) + + # Ignore extra_path when installing an egg (or being run by another + # command without --root or --single-version-externally-managed + self.path_file = None + self.extra_dirs = '' + + def run(self): + # Explicit request for old-style install? Just do it + if self.old_and_unmanageable or self.single_version_externally_managed: + return orig.install.run(self) + + if not self._called_from_setup(inspect.currentframe()): + # Run in backward-compatibility mode to support bdist_* commands. + orig.install.run(self) + else: + self.do_egg_install() + + @staticmethod + def _called_from_setup(run_frame): + """ + Attempt to detect whether run() was called from setup() or by another + command. If called by setup(), the parent caller will be the + 'run_command' method in 'distutils.dist', and *its* caller will be + the 'run_commands' method. If called any other way, the + immediate caller *might* be 'run_command', but it won't have been + called by 'run_commands'. Return True in that case or if a call stack + is unavailable. Return False otherwise. + """ + if run_frame is None: + msg = "Call stack not available. bdist_* commands may fail." + warnings.warn(msg) + if platform.python_implementation() == 'IronPython': + msg = "For best results, pass -X:Frames to enable call stack." + warnings.warn(msg) + return True + res = inspect.getouterframes(run_frame)[2] + caller, = res[:1] + info = inspect.getframeinfo(caller) + caller_module = caller.f_globals.get('__name__', '') + return ( + caller_module == 'distutils.dist' + and info.function == 'run_commands' + ) + + def do_egg_install(self): + + easy_install = self.distribution.get_command_class('easy_install') + + cmd = easy_install( + self.distribution, args="x", root=self.root, record=self.record, + ) + cmd.ensure_finalized() # finalize before bdist_egg munges install cmd + cmd.always_copy_from = '.' # make sure local-dir eggs get installed + + # pick up setup-dir .egg files only: no .egg-info + cmd.package_index.scan(glob.glob('*.egg')) + + self.run_command('bdist_egg') + args = [self.distribution.get_command_obj('bdist_egg').egg_output] + + if setuptools.bootstrap_install_from: + # Bootstrap self-installation of setuptools + args.insert(0, setuptools.bootstrap_install_from) + + cmd.args = args + cmd.run() + setuptools.bootstrap_install_from = None + + +# XXX Python 3.1 doesn't see _nc if this is inside the class +install.sub_commands = ( + [cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc] + + install.new_commands +) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/install_egg_info.py b/venv/lib/python3.7/site-packages/setuptools/command/install_egg_info.py new file mode 100644 index 0000000..edc4718 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/install_egg_info.py @@ -0,0 +1,62 @@ +from distutils import log, dir_util +import os + +from setuptools import Command +from setuptools import namespaces +from setuptools.archive_util import unpack_archive +import pkg_resources + + +class install_egg_info(namespaces.Installer, Command): + """Install an .egg-info directory for the package""" + + description = "Install an .egg-info directory for the package" + + user_options = [ + ('install-dir=', 'd', "directory to install to"), + ] + + def initialize_options(self): + self.install_dir = None + + def finalize_options(self): + self.set_undefined_options('install_lib', + ('install_dir', 'install_dir')) + ei_cmd = self.get_finalized_command("egg_info") + basename = pkg_resources.Distribution( + None, None, ei_cmd.egg_name, ei_cmd.egg_version + ).egg_name() + '.egg-info' + self.source = ei_cmd.egg_info + self.target = os.path.join(self.install_dir, basename) + self.outputs = [] + + def run(self): + self.run_command('egg_info') + if os.path.isdir(self.target) and not os.path.islink(self.target): + dir_util.remove_tree(self.target, dry_run=self.dry_run) + elif os.path.exists(self.target): + self.execute(os.unlink, (self.target,), "Removing " + self.target) + if not self.dry_run: + pkg_resources.ensure_directory(self.target) + self.execute( + self.copytree, (), "Copying %s to %s" % (self.source, self.target) + ) + self.install_namespaces() + + def get_outputs(self): + return self.outputs + + def copytree(self): + # Copy the .egg-info tree to site-packages + def skimmer(src, dst): + # filter out source-control directories; note that 'src' is always + # a '/'-separated path, regardless of platform. 'dst' is a + # platform-specific path. + for skip in '.svn/', 'CVS/': + if src.startswith(skip) or '/' + skip in src: + return None + self.outputs.append(dst) + log.debug("Copying %s to %s", src, dst) + return dst + + unpack_archive(self.source, self.target, skimmer) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/install_lib.py b/venv/lib/python3.7/site-packages/setuptools/command/install_lib.py new file mode 100644 index 0000000..2b31c3e --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/install_lib.py @@ -0,0 +1,121 @@ +import os +import imp +from itertools import product, starmap +import distutils.command.install_lib as orig + + +class install_lib(orig.install_lib): + """Don't add compiled flags to filenames of non-Python files""" + + def run(self): + self.build() + outfiles = self.install() + if outfiles is not None: + # always compile, in case we have any extension stubs to deal with + self.byte_compile(outfiles) + + def get_exclusions(self): + """ + Return a collections.Sized collections.Container of paths to be + excluded for single_version_externally_managed installations. + """ + all_packages = ( + pkg + for ns_pkg in self._get_SVEM_NSPs() + for pkg in self._all_packages(ns_pkg) + ) + + excl_specs = product(all_packages, self._gen_exclusion_paths()) + return set(starmap(self._exclude_pkg_path, excl_specs)) + + def _exclude_pkg_path(self, pkg, exclusion_path): + """ + Given a package name and exclusion path within that package, + compute the full exclusion path. + """ + parts = pkg.split('.') + [exclusion_path] + return os.path.join(self.install_dir, *parts) + + @staticmethod + def _all_packages(pkg_name): + """ + >>> list(install_lib._all_packages('foo.bar.baz')) + ['foo.bar.baz', 'foo.bar', 'foo'] + """ + while pkg_name: + yield pkg_name + pkg_name, sep, child = pkg_name.rpartition('.') + + def _get_SVEM_NSPs(self): + """ + Get namespace packages (list) but only for + single_version_externally_managed installations and empty otherwise. + """ + # TODO: is it necessary to short-circuit here? i.e. what's the cost + # if get_finalized_command is called even when namespace_packages is + # False? + if not self.distribution.namespace_packages: + return [] + + install_cmd = self.get_finalized_command('install') + svem = install_cmd.single_version_externally_managed + + return self.distribution.namespace_packages if svem else [] + + @staticmethod + def _gen_exclusion_paths(): + """ + Generate file paths to be excluded for namespace packages (bytecode + cache files). + """ + # always exclude the package module itself + yield '__init__.py' + + yield '__init__.pyc' + yield '__init__.pyo' + + if not hasattr(imp, 'get_tag'): + return + + base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) + yield base + '.pyc' + yield base + '.pyo' + yield base + '.opt-1.pyc' + yield base + '.opt-2.pyc' + + def copy_tree( + self, infile, outfile, + preserve_mode=1, preserve_times=1, preserve_symlinks=0, level=1 + ): + assert preserve_mode and preserve_times and not preserve_symlinks + exclude = self.get_exclusions() + + if not exclude: + return orig.install_lib.copy_tree(self, infile, outfile) + + # Exclude namespace package __init__.py* files from the output + + from setuptools.archive_util import unpack_directory + from distutils import log + + outfiles = [] + + def pf(src, dst): + if dst in exclude: + log.warn("Skipping installation of %s (namespace package)", + dst) + return False + + log.info("copying %s -> %s", src, os.path.dirname(dst)) + outfiles.append(dst) + return dst + + unpack_directory(infile, outfile, pf) + return outfiles + + def get_outputs(self): + outputs = orig.install_lib.get_outputs(self) + exclude = self.get_exclusions() + if exclude: + return [f for f in outputs if f not in exclude] + return outputs diff --git a/venv/lib/python3.7/site-packages/setuptools/command/install_scripts.py b/venv/lib/python3.7/site-packages/setuptools/command/install_scripts.py new file mode 100644 index 0000000..1623427 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/install_scripts.py @@ -0,0 +1,65 @@ +from distutils import log +import distutils.command.install_scripts as orig +import os +import sys + +from pkg_resources import Distribution, PathMetadata, ensure_directory + + +class install_scripts(orig.install_scripts): + """Do normal script install, plus any egg_info wrapper scripts""" + + def initialize_options(self): + orig.install_scripts.initialize_options(self) + self.no_ep = False + + def run(self): + import setuptools.command.easy_install as ei + + self.run_command("egg_info") + if self.distribution.scripts: + orig.install_scripts.run(self) # run first to set up self.outfiles + else: + self.outfiles = [] + if self.no_ep: + # don't install entry point scripts into .egg file! + return + + ei_cmd = self.get_finalized_command("egg_info") + dist = Distribution( + ei_cmd.egg_base, PathMetadata(ei_cmd.egg_base, ei_cmd.egg_info), + ei_cmd.egg_name, ei_cmd.egg_version, + ) + bs_cmd = self.get_finalized_command('build_scripts') + exec_param = getattr(bs_cmd, 'executable', None) + bw_cmd = self.get_finalized_command("bdist_wininst") + is_wininst = getattr(bw_cmd, '_is_running', False) + writer = ei.ScriptWriter + if is_wininst: + exec_param = "python.exe" + writer = ei.WindowsScriptWriter + if exec_param == sys.executable: + # In case the path to the Python executable contains a space, wrap + # it so it's not split up. + exec_param = [exec_param] + # resolve the writer to the environment + writer = writer.best() + cmd = writer.command_spec_class.best().from_param(exec_param) + for args in writer.get_args(dist, cmd.as_header()): + self.write_script(*args) + + def write_script(self, script_name, contents, mode="t", *ignored): + """Write an executable file to the scripts directory""" + from setuptools.command.easy_install import chmod, current_umask + + log.info("Installing %s script to %s", script_name, self.install_dir) + target = os.path.join(self.install_dir, script_name) + self.outfiles.append(target) + + mask = current_umask() + if not self.dry_run: + ensure_directory(target) + f = open(target, "w" + mode) + f.write(contents) + f.close() + chmod(target, 0o777 - mask) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/launcher manifest.xml b/venv/lib/python3.7/site-packages/setuptools/command/launcher manifest.xml new file mode 100644 index 0000000..5972a96 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/launcher manifest.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" + processorArchitecture="X86" + name="%(name)s" + type="win32"/> + <!-- Identify the application security requirements. --> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly> diff --git a/venv/lib/python3.7/site-packages/setuptools/command/py36compat.py b/venv/lib/python3.7/site-packages/setuptools/command/py36compat.py new file mode 100644 index 0000000..61063e7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/py36compat.py @@ -0,0 +1,136 @@ +import os +from glob import glob +from distutils.util import convert_path +from distutils.command import sdist + +from setuptools.extern.six.moves import filter + + +class sdist_add_defaults: + """ + Mix-in providing forward-compatibility for functionality as found in + distutils on Python 3.7. + + Do not edit the code in this class except to update functionality + as implemented in distutils. Instead, override in the subclass. + """ + + def add_defaults(self): + """Add all the default files to self.filelist: + - README or README.txt + - setup.py + - test/test*.py + - all pure Python modules mentioned in setup script + - all files pointed by package_data (build_py) + - all files defined in data_files. + - all files defined as scripts. + - all C sources listed as part of extensions or C libraries + in the setup script (doesn't catch C headers!) + Warns if (README or README.txt) or setup.py are missing; everything + else is optional. + """ + self._add_defaults_standards() + self._add_defaults_optional() + self._add_defaults_python() + self._add_defaults_data_files() + self._add_defaults_ext() + self._add_defaults_c_libs() + self._add_defaults_scripts() + + @staticmethod + def _cs_path_exists(fspath): + """ + Case-sensitive path existence check + + >>> sdist_add_defaults._cs_path_exists(__file__) + True + >>> sdist_add_defaults._cs_path_exists(__file__.upper()) + False + """ + if not os.path.exists(fspath): + return False + # make absolute so we always have a directory + abspath = os.path.abspath(fspath) + directory, filename = os.path.split(abspath) + return filename in os.listdir(directory) + + def _add_defaults_standards(self): + standards = [self.READMES, self.distribution.script_name] + for fn in standards: + if isinstance(fn, tuple): + alts = fn + got_it = False + for fn in alts: + if self._cs_path_exists(fn): + got_it = True + self.filelist.append(fn) + break + + if not got_it: + self.warn("standard file not found: should have one of " + + ', '.join(alts)) + else: + if self._cs_path_exists(fn): + self.filelist.append(fn) + else: + self.warn("standard file '%s' not found" % fn) + + def _add_defaults_optional(self): + optional = ['test/test*.py', 'setup.cfg'] + for pattern in optional: + files = filter(os.path.isfile, glob(pattern)) + self.filelist.extend(files) + + def _add_defaults_python(self): + # build_py is used to get: + # - python modules + # - files defined in package_data + build_py = self.get_finalized_command('build_py') + + # getting python files + if self.distribution.has_pure_modules(): + self.filelist.extend(build_py.get_source_files()) + + # getting package_data files + # (computed in build_py.data_files by build_py.finalize_options) + for pkg, src_dir, build_dir, filenames in build_py.data_files: + for filename in filenames: + self.filelist.append(os.path.join(src_dir, filename)) + + def _add_defaults_data_files(self): + # getting distribution.data_files + if self.distribution.has_data_files(): + for item in self.distribution.data_files: + if isinstance(item, str): + # plain file + item = convert_path(item) + if os.path.isfile(item): + self.filelist.append(item) + else: + # a (dirname, filenames) tuple + dirname, filenames = item + for f in filenames: + f = convert_path(f) + if os.path.isfile(f): + self.filelist.append(f) + + def _add_defaults_ext(self): + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + self.filelist.extend(build_ext.get_source_files()) + + def _add_defaults_c_libs(self): + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.filelist.extend(build_clib.get_source_files()) + + def _add_defaults_scripts(self): + if self.distribution.has_scripts(): + build_scripts = self.get_finalized_command('build_scripts') + self.filelist.extend(build_scripts.get_source_files()) + + +if hasattr(sdist.sdist, '_add_defaults_standards'): + # disable the functionality already available upstream + class sdist_add_defaults: + pass diff --git a/venv/lib/python3.7/site-packages/setuptools/command/register.py b/venv/lib/python3.7/site-packages/setuptools/command/register.py new file mode 100644 index 0000000..98bc015 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/register.py @@ -0,0 +1,18 @@ +from distutils import log +import distutils.command.register as orig + + +class register(orig.register): + __doc__ = orig.register.__doc__ + + def run(self): + try: + # Make sure that we are using valid current name/version info + self.run_command('egg_info') + orig.register.run(self) + finally: + self.announce( + "WARNING: Registering is deprecated, use twine to " + "upload instead (https://pypi.org/p/twine/)", + log.WARN + ) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/rotate.py b/venv/lib/python3.7/site-packages/setuptools/command/rotate.py new file mode 100644 index 0000000..b89353f --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/rotate.py @@ -0,0 +1,66 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsOptionError +import os +import shutil + +from setuptools.extern import six + +from setuptools import Command + + +class rotate(Command): + """Delete older distributions""" + + description = "delete older distributions, keeping N newest files" + user_options = [ + ('match=', 'm', "patterns to match (required)"), + ('dist-dir=', 'd', "directory where the distributions are"), + ('keep=', 'k', "number of matching distributions to keep"), + ] + + boolean_options = [] + + def initialize_options(self): + self.match = None + self.dist_dir = None + self.keep = None + + def finalize_options(self): + if self.match is None: + raise DistutilsOptionError( + "Must specify one or more (comma-separated) match patterns " + "(e.g. '.zip' or '.egg')" + ) + if self.keep is None: + raise DistutilsOptionError("Must specify number of files to keep") + try: + self.keep = int(self.keep) + except ValueError: + raise DistutilsOptionError("--keep must be an integer") + if isinstance(self.match, six.string_types): + self.match = [ + convert_path(p.strip()) for p in self.match.split(',') + ] + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + + def run(self): + self.run_command("egg_info") + from glob import glob + + for pattern in self.match: + pattern = self.distribution.get_name() + '*' + pattern + files = glob(os.path.join(self.dist_dir, pattern)) + files = [(os.path.getmtime(f), f) for f in files] + files.sort() + files.reverse() + + log.info("%d file(s) matching %s", len(files), pattern) + files = files[self.keep:] + for (t, f) in files: + log.info("Deleting %s", f) + if not self.dry_run: + if os.path.isdir(f): + shutil.rmtree(f) + else: + os.unlink(f) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/saveopts.py b/venv/lib/python3.7/site-packages/setuptools/command/saveopts.py new file mode 100644 index 0000000..611cec5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/saveopts.py @@ -0,0 +1,22 @@ +from setuptools.command.setopt import edit_config, option_base + + +class saveopts(option_base): + """Save command-line options to a file""" + + description = "save supplied options to setup.cfg or other config file" + + def run(self): + dist = self.distribution + settings = {} + + for cmd in dist.command_options: + + if cmd == 'saveopts': + continue # don't save our own options! + + for opt, (src, val) in dist.get_option_dict(cmd).items(): + if src == "command line": + settings.setdefault(cmd, {})[opt] = val + + edit_config(self.filename, settings, self.dry_run) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/sdist.py b/venv/lib/python3.7/site-packages/setuptools/command/sdist.py new file mode 100644 index 0000000..bcfae4d --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/sdist.py @@ -0,0 +1,200 @@ +from distutils import log +import distutils.command.sdist as orig +import os +import sys +import io +import contextlib + +from setuptools.extern import six + +from .py36compat import sdist_add_defaults + +import pkg_resources + +_default_revctrl = list + + +def walk_revctrl(dirname=''): + """Find all files under revision control""" + for ep in pkg_resources.iter_entry_points('setuptools.file_finders'): + for item in ep.load()(dirname): + yield item + + +class sdist(sdist_add_defaults, orig.sdist): + """Smart sdist that finds anything supported by revision control""" + + user_options = [ + ('formats=', None, + "formats for source distribution (comma-separated list)"), + ('keep-temp', 'k', + "keep the distribution tree around after creating " + + "archive file(s)"), + ('dist-dir=', 'd', + "directory to put the source distribution archive(s) in " + "[default: dist]"), + ] + + negative_opt = {} + + README_EXTENSIONS = ['', '.rst', '.txt', '.md'] + READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS) + + def run(self): + self.run_command('egg_info') + ei_cmd = self.get_finalized_command('egg_info') + self.filelist = ei_cmd.filelist + self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt')) + self.check_readme() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + self.make_distribution() + + dist_files = getattr(self.distribution, 'dist_files', []) + for file in self.archive_files: + data = ('sdist', '', file) + if data not in dist_files: + dist_files.append(data) + + def initialize_options(self): + orig.sdist.initialize_options(self) + + self._default_to_gztar() + + def _default_to_gztar(self): + # only needed on Python prior to 3.6. + if sys.version_info >= (3, 6, 0, 'beta', 1): + return + self.formats = ['gztar'] + + def make_distribution(self): + """ + Workaround for #516 + """ + with self._remove_os_link(): + orig.sdist.make_distribution(self) + + @staticmethod + @contextlib.contextmanager + def _remove_os_link(): + """ + In a context, remove and restore os.link if it exists + """ + + class NoValue: + pass + + orig_val = getattr(os, 'link', NoValue) + try: + del os.link + except Exception: + pass + try: + yield + finally: + if orig_val is not NoValue: + setattr(os, 'link', orig_val) + + def __read_template_hack(self): + # This grody hack closes the template file (MANIFEST.in) if an + # exception occurs during read_template. + # Doing so prevents an error when easy_install attempts to delete the + # file. + try: + orig.sdist.read_template(self) + except Exception: + _, _, tb = sys.exc_info() + tb.tb_next.tb_frame.f_locals['template'].close() + raise + + # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle + # has been fixed, so only override the method if we're using an earlier + # Python. + has_leaky_handle = ( + sys.version_info < (2, 7, 2) + or (3, 0) <= sys.version_info < (3, 1, 4) + or (3, 2) <= sys.version_info < (3, 2, 1) + ) + if has_leaky_handle: + read_template = __read_template_hack + + def _add_defaults_python(self): + """getting python files""" + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + self.filelist.extend(build_py.get_source_files()) + # This functionality is incompatible with include_package_data, and + # will in fact create an infinite recursion if include_package_data + # is True. Use of include_package_data will imply that + # distutils-style automatic handling of package_data is disabled + if not self.distribution.include_package_data: + for _, src_dir, _, filenames in build_py.data_files: + self.filelist.extend([os.path.join(src_dir, filename) + for filename in filenames]) + + def _add_defaults_data_files(self): + try: + if six.PY2: + sdist_add_defaults._add_defaults_data_files(self) + else: + super()._add_defaults_data_files() + except TypeError: + log.warn("data_files contains unexpected objects") + + def check_readme(self): + for f in self.READMES: + if os.path.exists(f): + return + else: + self.warn( + "standard file not found: should have one of " + + ', '.join(self.READMES) + ) + + def make_release_tree(self, base_dir, files): + orig.sdist.make_release_tree(self, base_dir, files) + + # Save any egg_info command line options used to create this sdist + dest = os.path.join(base_dir, 'setup.cfg') + if hasattr(os, 'link') and os.path.exists(dest): + # unlink and re-copy, since it might be hard-linked, and + # we don't want to change the source version + os.unlink(dest) + self.copy_file('setup.cfg', dest) + + self.get_finalized_command('egg_info').save_version_info(dest) + + def _manifest_is_not_generated(self): + # check for special comment used in 2.7.1 and higher + if not os.path.isfile(self.manifest): + return False + + with io.open(self.manifest, 'rb') as fp: + first_line = fp.readline() + return (first_line != + '# file GENERATED by distutils, do NOT edit\n'.encode()) + + def read_manifest(self): + """Read the manifest file (named by 'self.manifest') and use it to + fill in 'self.filelist', the list of files to include in the source + distribution. + """ + log.info("reading manifest file '%s'", self.manifest) + manifest = open(self.manifest, 'rb') + for line in manifest: + # The manifest must contain UTF-8. See #303. + if six.PY3: + try: + line = line.decode('UTF-8') + except UnicodeDecodeError: + log.warn("%r not UTF-8 decodable -- skipping" % line) + continue + # ignore comments and blank lines + line = line.strip() + if line.startswith('#') or not line: + continue + self.filelist.append(line) + manifest.close() diff --git a/venv/lib/python3.7/site-packages/setuptools/command/setopt.py b/venv/lib/python3.7/site-packages/setuptools/command/setopt.py new file mode 100644 index 0000000..7e57cc0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/setopt.py @@ -0,0 +1,149 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsOptionError +import distutils +import os + +from setuptools.extern.six.moves import configparser + +from setuptools import Command + +__all__ = ['config_file', 'edit_config', 'option_base', 'setopt'] + + +def config_file(kind="local"): + """Get the filename of the distutils, local, global, or per-user config + + `kind` must be one of "local", "global", or "user" + """ + if kind == 'local': + return 'setup.cfg' + if kind == 'global': + return os.path.join( + os.path.dirname(distutils.__file__), 'distutils.cfg' + ) + if kind == 'user': + dot = os.name == 'posix' and '.' or '' + return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot)) + raise ValueError( + "config_file() type must be 'local', 'global', or 'user'", kind + ) + + +def edit_config(filename, settings, dry_run=False): + """Edit a configuration file to include `settings` + + `settings` is a dictionary of dictionaries or ``None`` values, keyed by + command/section name. A ``None`` value means to delete the entire section, + while a dictionary lists settings to be changed or deleted in that section. + A setting of ``None`` means to delete that setting. + """ + log.debug("Reading configuration from %s", filename) + opts = configparser.RawConfigParser() + opts.read([filename]) + for section, options in settings.items(): + if options is None: + log.info("Deleting section [%s] from %s", section, filename) + opts.remove_section(section) + else: + if not opts.has_section(section): + log.debug("Adding new section [%s] to %s", section, filename) + opts.add_section(section) + for option, value in options.items(): + if value is None: + log.debug( + "Deleting %s.%s from %s", + section, option, filename + ) + opts.remove_option(section, option) + if not opts.options(section): + log.info("Deleting empty [%s] section from %s", + section, filename) + opts.remove_section(section) + else: + log.debug( + "Setting %s.%s to %r in %s", + section, option, value, filename + ) + opts.set(section, option, value) + + log.info("Writing %s", filename) + if not dry_run: + with open(filename, 'w') as f: + opts.write(f) + + +class option_base(Command): + """Abstract base class for commands that mess with config files""" + + user_options = [ + ('global-config', 'g', + "save options to the site-wide distutils.cfg file"), + ('user-config', 'u', + "save options to the current user's pydistutils.cfg file"), + ('filename=', 'f', + "configuration file to use (default=setup.cfg)"), + ] + + boolean_options = [ + 'global-config', 'user-config', + ] + + def initialize_options(self): + self.global_config = None + self.user_config = None + self.filename = None + + def finalize_options(self): + filenames = [] + if self.global_config: + filenames.append(config_file('global')) + if self.user_config: + filenames.append(config_file('user')) + if self.filename is not None: + filenames.append(self.filename) + if not filenames: + filenames.append(config_file('local')) + if len(filenames) > 1: + raise DistutilsOptionError( + "Must specify only one configuration file option", + filenames + ) + self.filename, = filenames + + +class setopt(option_base): + """Save command-line options to a file""" + + description = "set an option in setup.cfg or another config file" + + user_options = [ + ('command=', 'c', 'command to set an option for'), + ('option=', 'o', 'option to set'), + ('set-value=', 's', 'value of the option'), + ('remove', 'r', 'remove (unset) the value'), + ] + option_base.user_options + + boolean_options = option_base.boolean_options + ['remove'] + + def initialize_options(self): + option_base.initialize_options(self) + self.command = None + self.option = None + self.set_value = None + self.remove = None + + def finalize_options(self): + option_base.finalize_options(self) + if self.command is None or self.option is None: + raise DistutilsOptionError("Must specify --command *and* --option") + if self.set_value is None and not self.remove: + raise DistutilsOptionError("Must specify --set-value or --remove") + + def run(self): + edit_config( + self.filename, { + self.command: {self.option.replace('-', '_'): self.set_value} + }, + self.dry_run + ) diff --git a/venv/lib/python3.7/site-packages/setuptools/command/test.py b/venv/lib/python3.7/site-packages/setuptools/command/test.py new file mode 100644 index 0000000..dde0118 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/test.py @@ -0,0 +1,270 @@ +import os +import operator +import sys +import contextlib +import itertools +import unittest +from distutils.errors import DistutilsError, DistutilsOptionError +from distutils import log +from unittest import TestLoader + +from setuptools.extern import six +from setuptools.extern.six.moves import map, filter + +from pkg_resources import (resource_listdir, resource_exists, normalize_path, + working_set, _namespace_packages, evaluate_marker, + add_activation_listener, require, EntryPoint) +from setuptools import Command + +__metaclass__ = type + + +class ScanningLoader(TestLoader): + + def __init__(self): + TestLoader.__init__(self) + self._visited = set() + + def loadTestsFromModule(self, module, pattern=None): + """Return a suite of all tests cases contained in the given module + + If the module is a package, load tests from all the modules in it. + If the module has an ``additional_tests`` function, call it and add + the return value to the tests. + """ + if module in self._visited: + return None + self._visited.add(module) + + tests = [] + tests.append(TestLoader.loadTestsFromModule(self, module)) + + if hasattr(module, "additional_tests"): + tests.append(module.additional_tests()) + + if hasattr(module, '__path__'): + for file in resource_listdir(module.__name__, ''): + if file.endswith('.py') and file != '__init__.py': + submodule = module.__name__ + '.' + file[:-3] + else: + if resource_exists(module.__name__, file + '/__init__.py'): + submodule = module.__name__ + '.' + file + else: + continue + tests.append(self.loadTestsFromName(submodule)) + + if len(tests) != 1: + return self.suiteClass(tests) + else: + return tests[0] # don't create a nested suite for only one return + + +# adapted from jaraco.classes.properties:NonDataProperty +class NonDataProperty: + def __init__(self, fget): + self.fget = fget + + def __get__(self, obj, objtype=None): + if obj is None: + return self + return self.fget(obj) + + +class test(Command): + """Command to run unit tests after in-place build""" + + description = "run unit tests after in-place build" + + user_options = [ + ('test-module=', 'm', "Run 'test_suite' in specified module"), + ('test-suite=', 's', + "Run single test, case or suite (e.g. 'module.test_suite')"), + ('test-runner=', 'r', "Test runner to use"), + ] + + def initialize_options(self): + self.test_suite = None + self.test_module = None + self.test_loader = None + self.test_runner = None + + def finalize_options(self): + + if self.test_suite and self.test_module: + msg = "You may specify a module or a suite, but not both" + raise DistutilsOptionError(msg) + + if self.test_suite is None: + if self.test_module is None: + self.test_suite = self.distribution.test_suite + else: + self.test_suite = self.test_module + ".test_suite" + + if self.test_loader is None: + self.test_loader = getattr(self.distribution, 'test_loader', None) + if self.test_loader is None: + self.test_loader = "setuptools.command.test:ScanningLoader" + if self.test_runner is None: + self.test_runner = getattr(self.distribution, 'test_runner', None) + + @NonDataProperty + def test_args(self): + return list(self._test_args()) + + def _test_args(self): + if not self.test_suite and sys.version_info >= (2, 7): + yield 'discover' + if self.verbose: + yield '--verbose' + if self.test_suite: + yield self.test_suite + + def with_project_on_sys_path(self, func): + """ + Backward compatibility for project_on_sys_path context. + """ + with self.project_on_sys_path(): + func() + + @contextlib.contextmanager + def project_on_sys_path(self, include_dists=[]): + with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False) + + if with_2to3: + # If we run 2to3 we can not do this inplace: + + # Ensure metadata is up-to-date + self.reinitialize_command('build_py', inplace=0) + self.run_command('build_py') + bpy_cmd = self.get_finalized_command("build_py") + build_path = normalize_path(bpy_cmd.build_lib) + + # Build extensions + self.reinitialize_command('egg_info', egg_base=build_path) + self.run_command('egg_info') + + self.reinitialize_command('build_ext', inplace=0) + self.run_command('build_ext') + else: + # Without 2to3 inplace works fine: + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + + ei_cmd = self.get_finalized_command("egg_info") + + old_path = sys.path[:] + old_modules = sys.modules.copy() + + try: + project_path = normalize_path(ei_cmd.egg_base) + sys.path.insert(0, project_path) + working_set.__init__() + add_activation_listener(lambda dist: dist.activate()) + require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version)) + with self.paths_on_pythonpath([project_path]): + yield + finally: + sys.path[:] = old_path + sys.modules.clear() + sys.modules.update(old_modules) + working_set.__init__() + + @staticmethod + @contextlib.contextmanager + def paths_on_pythonpath(paths): + """ + Add the indicated paths to the head of the PYTHONPATH environment + variable so that subprocesses will also see the packages at + these paths. + + Do this in a context that restores the value on exit. + """ + nothing = object() + orig_pythonpath = os.environ.get('PYTHONPATH', nothing) + current_pythonpath = os.environ.get('PYTHONPATH', '') + try: + prefix = os.pathsep.join(paths) + to_join = filter(None, [prefix, current_pythonpath]) + new_path = os.pathsep.join(to_join) + if new_path: + os.environ['PYTHONPATH'] = new_path + yield + finally: + if orig_pythonpath is nothing: + os.environ.pop('PYTHONPATH', None) + else: + os.environ['PYTHONPATH'] = orig_pythonpath + + @staticmethod + def install_dists(dist): + """ + Install the requirements indicated by self.distribution and + return an iterable of the dists that were built. + """ + ir_d = dist.fetch_build_eggs(dist.install_requires) + tr_d = dist.fetch_build_eggs(dist.tests_require or []) + er_d = dist.fetch_build_eggs( + v for k, v in dist.extras_require.items() + if k.startswith(':') and evaluate_marker(k[1:]) + ) + return itertools.chain(ir_d, tr_d, er_d) + + def run(self): + installed_dists = self.install_dists(self.distribution) + + cmd = ' '.join(self._argv) + if self.dry_run: + self.announce('skipping "%s" (dry run)' % cmd) + return + + self.announce('running "%s"' % cmd) + + paths = map(operator.attrgetter('location'), installed_dists) + with self.paths_on_pythonpath(paths): + with self.project_on_sys_path(): + self.run_tests() + + def run_tests(self): + # Purge modules under test from sys.modules. The test loader will + # re-import them from the build location. Required when 2to3 is used + # with namespace packages. + if six.PY3 and getattr(self.distribution, 'use_2to3', False): + module = self.test_suite.split('.')[0] + if module in _namespace_packages: + del_modules = [] + if module in sys.modules: + del_modules.append(module) + module += '.' + for name in sys.modules: + if name.startswith(module): + del_modules.append(name) + list(map(sys.modules.__delitem__, del_modules)) + + test = unittest.main( + None, None, self._argv, + testLoader=self._resolve_as_ep(self.test_loader), + testRunner=self._resolve_as_ep(self.test_runner), + exit=False, + ) + if not test.result.wasSuccessful(): + msg = 'Test failed: %s' % test.result + self.announce(msg, log.ERROR) + raise DistutilsError(msg) + + @property + def _argv(self): + return ['unittest'] + self.test_args + + @staticmethod + def _resolve_as_ep(val): + """ + Load the indicated attribute value, called, as a as if it were + specified as an entry point. + """ + if val is None: + return + parsed = EntryPoint.parse("x=" + val) + return parsed.resolve()() diff --git a/venv/lib/python3.7/site-packages/setuptools/command/upload.py b/venv/lib/python3.7/site-packages/setuptools/command/upload.py new file mode 100644 index 0000000..dd17f7a --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/upload.py @@ -0,0 +1,196 @@ +import io +import os +import hashlib +import getpass +import platform + +from base64 import standard_b64encode + +from distutils import log +from distutils.command import upload as orig +from distutils.spawn import spawn + +from distutils.errors import DistutilsError + +from setuptools.extern.six.moves.urllib.request import urlopen, Request +from setuptools.extern.six.moves.urllib.error import HTTPError +from setuptools.extern.six.moves.urllib.parse import urlparse + +class upload(orig.upload): + """ + Override default upload behavior to obtain password + in a variety of different ways. + """ + def run(self): + try: + orig.upload.run(self) + finally: + self.announce( + "WARNING: Uploading via this command is deprecated, use twine " + "to upload instead (https://pypi.org/p/twine/)", + log.WARN + ) + + def finalize_options(self): + orig.upload.finalize_options(self) + self.username = ( + self.username or + getpass.getuser() + ) + # Attempt to obtain password. Short circuit evaluation at the first + # sign of success. + self.password = ( + self.password or + self._load_password_from_keyring() or + self._prompt_for_password() + ) + + def upload_file(self, command, pyversion, filename): + # Makes sure the repository URL is compliant + schema, netloc, url, params, query, fragments = \ + urlparse(self.repository) + if params or query or fragments: + raise AssertionError("Incompatible url %s" % self.repository) + + if schema not in ('http', 'https'): + raise AssertionError("unsupported schema " + schema) + + # Sign if requested + if self.sign: + gpg_args = ["gpg", "--detach-sign", "-a", filename] + if self.identity: + gpg_args[2:2] = ["--local-user", self.identity] + spawn(gpg_args, + dry_run=self.dry_run) + + # Fill in the data - send all the meta-data in case we need to + # register a new release + with open(filename, 'rb') as f: + content = f.read() + + meta = self.distribution.metadata + + data = { + # action + ':action': 'file_upload', + 'protocol_version': '1', + + # identify release + 'name': meta.get_name(), + 'version': meta.get_version(), + + # file content + 'content': (os.path.basename(filename),content), + 'filetype': command, + 'pyversion': pyversion, + 'md5_digest': hashlib.md5(content).hexdigest(), + + # additional meta-data + 'metadata_version': str(meta.get_metadata_version()), + 'summary': meta.get_description(), + 'home_page': meta.get_url(), + 'author': meta.get_contact(), + 'author_email': meta.get_contact_email(), + 'license': meta.get_licence(), + 'description': meta.get_long_description(), + 'keywords': meta.get_keywords(), + 'platform': meta.get_platforms(), + 'classifiers': meta.get_classifiers(), + 'download_url': meta.get_download_url(), + # PEP 314 + 'provides': meta.get_provides(), + 'requires': meta.get_requires(), + 'obsoletes': meta.get_obsoletes(), + } + + data['comment'] = '' + + if self.sign: + data['gpg_signature'] = (os.path.basename(filename) + ".asc", + open(filename+".asc", "rb").read()) + + # set up the authentication + user_pass = (self.username + ":" + self.password).encode('ascii') + # The exact encoding of the authentication string is debated. + # Anyway PyPI only accepts ascii for both username or password. + auth = "Basic " + standard_b64encode(user_pass).decode('ascii') + + # Build up the MIME payload for the POST data + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = b'\r\n--' + boundary.encode('ascii') + end_boundary = sep_boundary + b'--\r\n' + body = io.BytesIO() + for key, value in data.items(): + title = '\r\nContent-Disposition: form-data; name="%s"' % key + # handle multiple entries for the same name + if not isinstance(value, list): + value = [value] + for value in value: + if type(value) is tuple: + title += '; filename="%s"' % value[0] + value = value[1] + else: + value = str(value).encode('utf-8') + body.write(sep_boundary) + body.write(title.encode('utf-8')) + body.write(b"\r\n\r\n") + body.write(value) + body.write(end_boundary) + body = body.getvalue() + + msg = "Submitting %s to %s" % (filename, self.repository) + self.announce(msg, log.INFO) + + # build the Request + headers = { + 'Content-type': 'multipart/form-data; boundary=%s' % boundary, + 'Content-length': str(len(body)), + 'Authorization': auth, + } + + request = Request(self.repository, data=body, + headers=headers) + # send the data + try: + result = urlopen(request) + status = result.getcode() + reason = result.msg + except HTTPError as e: + status = e.code + reason = e.msg + except OSError as e: + self.announce(str(e), log.ERROR) + raise + + if status == 200: + self.announce('Server response (%s): %s' % (status, reason), + log.INFO) + if self.show_response: + text = getattr(self, '_read_pypi_response', + lambda x: None)(result) + if text is not None: + msg = '\n'.join(('-' * 75, text, '-' * 75)) + self.announce(msg, log.INFO) + else: + msg = 'Upload failed (%s): %s' % (status, reason) + self.announce(msg, log.ERROR) + raise DistutilsError(msg) + + def _load_password_from_keyring(self): + """ + Attempt to load password from keyring. Suppress Exceptions. + """ + try: + keyring = __import__('keyring') + return keyring.get_password(self.repository, self.username) + except Exception: + pass + + def _prompt_for_password(self): + """ + Prompt for a password on the tty. Suppress Exceptions. + """ + try: + return getpass.getpass() + except (Exception, KeyboardInterrupt): + pass diff --git a/venv/lib/python3.7/site-packages/setuptools/command/upload_docs.py b/venv/lib/python3.7/site-packages/setuptools/command/upload_docs.py new file mode 100644 index 0000000..07aa564 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/command/upload_docs.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +"""upload_docs + +Implements a Distutils 'upload_docs' subcommand (upload documentation to +PyPI's pythonhosted.org). +""" + +from base64 import standard_b64encode +from distutils import log +from distutils.errors import DistutilsOptionError +import os +import socket +import zipfile +import tempfile +import shutil +import itertools +import functools + +from setuptools.extern import six +from setuptools.extern.six.moves import http_client, urllib + +from pkg_resources import iter_entry_points +from .upload import upload + + +def _encode(s): + errors = 'surrogateescape' if six.PY3 else 'strict' + return s.encode('utf-8', errors) + + +class upload_docs(upload): + # override the default repository as upload_docs isn't + # supported by Warehouse (and won't be). + DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi/' + + description = 'Upload documentation to PyPI' + + user_options = [ + ('repository=', 'r', + "url of repository [default: %s]" % upload.DEFAULT_REPOSITORY), + ('show-response', None, + 'display full response text from server'), + ('upload-dir=', None, 'directory to upload'), + ] + boolean_options = upload.boolean_options + + def has_sphinx(self): + if self.upload_dir is None: + for ep in iter_entry_points('distutils.commands', 'build_sphinx'): + return True + + sub_commands = [('build_sphinx', has_sphinx)] + + def initialize_options(self): + upload.initialize_options(self) + self.upload_dir = None + self.target_dir = None + + def finalize_options(self): + upload.finalize_options(self) + if self.upload_dir is None: + if self.has_sphinx(): + build_sphinx = self.get_finalized_command('build_sphinx') + self.target_dir = build_sphinx.builder_target_dir + else: + build = self.get_finalized_command('build') + self.target_dir = os.path.join(build.build_base, 'docs') + else: + self.ensure_dirname('upload_dir') + self.target_dir = self.upload_dir + if 'pypi.python.org' in self.repository: + log.warn("Upload_docs command is deprecated. Use RTD instead.") + self.announce('Using upload directory %s' % self.target_dir) + + def create_zipfile(self, filename): + zip_file = zipfile.ZipFile(filename, "w") + try: + self.mkpath(self.target_dir) # just in case + for root, dirs, files in os.walk(self.target_dir): + if root == self.target_dir and not files: + tmpl = "no files found in upload directory '%s'" + raise DistutilsOptionError(tmpl % self.target_dir) + for name in files: + full = os.path.join(root, name) + relative = root[len(self.target_dir):].lstrip(os.path.sep) + dest = os.path.join(relative, name) + zip_file.write(full, dest) + finally: + zip_file.close() + + def run(self): + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + tmp_dir = tempfile.mkdtemp() + name = self.distribution.metadata.get_name() + zip_file = os.path.join(tmp_dir, "%s.zip" % name) + try: + self.create_zipfile(zip_file) + self.upload_file(zip_file) + finally: + shutil.rmtree(tmp_dir) + + @staticmethod + def _build_part(item, sep_boundary): + key, values = item + title = '\nContent-Disposition: form-data; name="%s"' % key + # handle multiple entries for the same name + if not isinstance(values, list): + values = [values] + for value in values: + if isinstance(value, tuple): + title += '; filename="%s"' % value[0] + value = value[1] + else: + value = _encode(value) + yield sep_boundary + yield _encode(title) + yield b"\n\n" + yield value + if value and value[-1:] == b'\r': + yield b'\n' # write an extra newline (lurve Macs) + + @classmethod + def _build_multipart(cls, data): + """ + Build up the MIME payload for the POST data + """ + boundary = b'--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = b'\n--' + boundary + end_boundary = sep_boundary + b'--' + end_items = end_boundary, b"\n", + builder = functools.partial( + cls._build_part, + sep_boundary=sep_boundary, + ) + part_groups = map(builder, data.items()) + parts = itertools.chain.from_iterable(part_groups) + body_items = itertools.chain(parts, end_items) + content_type = 'multipart/form-data; boundary=%s' % boundary.decode('ascii') + return b''.join(body_items), content_type + + def upload_file(self, filename): + with open(filename, 'rb') as f: + content = f.read() + meta = self.distribution.metadata + data = { + ':action': 'doc_upload', + 'name': meta.get_name(), + 'content': (os.path.basename(filename), content), + } + # set up the authentication + credentials = _encode(self.username + ':' + self.password) + credentials = standard_b64encode(credentials) + if six.PY3: + credentials = credentials.decode('ascii') + auth = "Basic " + credentials + + body, ct = self._build_multipart(data) + + msg = "Submitting documentation to %s" % (self.repository) + self.announce(msg, log.INFO) + + # build the Request + # We can't use urllib2 since we need to send the Basic + # auth right with the first request + schema, netloc, url, params, query, fragments = \ + urllib.parse.urlparse(self.repository) + assert not params and not query and not fragments + if schema == 'http': + conn = http_client.HTTPConnection(netloc) + elif schema == 'https': + conn = http_client.HTTPSConnection(netloc) + else: + raise AssertionError("unsupported schema " + schema) + + data = '' + try: + conn.connect() + conn.putrequest("POST", url) + content_type = ct + conn.putheader('Content-type', content_type) + conn.putheader('Content-length', str(len(body))) + conn.putheader('Authorization', auth) + conn.endheaders() + conn.send(body) + except socket.error as e: + self.announce(str(e), log.ERROR) + return + + r = conn.getresponse() + if r.status == 200: + msg = 'Server response (%s): %s' % (r.status, r.reason) + self.announce(msg, log.INFO) + elif r.status == 301: + location = r.getheader('Location') + if location is None: + location = 'https://pythonhosted.org/%s/' % meta.get_name() + msg = 'Upload successful. Visit %s' % location + self.announce(msg, log.INFO) + else: + msg = 'Upload failed (%s): %s' % (r.status, r.reason) + self.announce(msg, log.ERROR) + if self.show_response: + print('-' * 75, r.read(), '-' * 75) diff --git a/venv/lib/python3.7/site-packages/setuptools/config.py b/venv/lib/python3.7/site-packages/setuptools/config.py new file mode 100644 index 0000000..d1ac673 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/config.py @@ -0,0 +1,635 @@ +from __future__ import absolute_import, unicode_literals +import io +import os +import sys + +import warnings +import functools +from collections import defaultdict +from functools import partial +from functools import wraps +from importlib import import_module + +from distutils.errors import DistutilsOptionError, DistutilsFileError +from setuptools.extern.packaging.version import LegacyVersion, parse +from setuptools.extern.six import string_types, PY3 + + +__metaclass__ = type + + +def read_configuration( + filepath, find_others=False, ignore_option_errors=False): + """Read given configuration file and returns options from it as a dict. + + :param str|unicode filepath: Path to configuration file + to get options from. + + :param bool find_others: Whether to search for other configuration files + which could be on in various places. + + :param bool ignore_option_errors: Whether to silently ignore + options, values of which could not be resolved (e.g. due to exceptions + in directives such as file:, attr:, etc.). + If False exceptions are propagated as expected. + + :rtype: dict + """ + from setuptools.dist import Distribution, _Distribution + + filepath = os.path.abspath(filepath) + + if not os.path.isfile(filepath): + raise DistutilsFileError( + 'Configuration file %s does not exist.' % filepath) + + current_directory = os.getcwd() + os.chdir(os.path.dirname(filepath)) + + try: + dist = Distribution() + + filenames = dist.find_config_files() if find_others else [] + if filepath not in filenames: + filenames.append(filepath) + + _Distribution.parse_config_files(dist, filenames=filenames) + + handlers = parse_configuration( + dist, dist.command_options, + ignore_option_errors=ignore_option_errors) + + finally: + os.chdir(current_directory) + + return configuration_to_dict(handlers) + + +def _get_option(target_obj, key): + """ + Given a target object and option key, get that option from + the target object, either through a get_{key} method or + from an attribute directly. + """ + getter_name = 'get_{key}'.format(**locals()) + by_attribute = functools.partial(getattr, target_obj, key) + getter = getattr(target_obj, getter_name, by_attribute) + return getter() + + +def configuration_to_dict(handlers): + """Returns configuration data gathered by given handlers as a dict. + + :param list[ConfigHandler] handlers: Handlers list, + usually from parse_configuration() + + :rtype: dict + """ + config_dict = defaultdict(dict) + + for handler in handlers: + for option in handler.set_options: + value = _get_option(handler.target_obj, option) + config_dict[handler.section_prefix][option] = value + + return config_dict + + +def parse_configuration( + distribution, command_options, ignore_option_errors=False): + """Performs additional parsing of configuration options + for a distribution. + + Returns a list of used option handlers. + + :param Distribution distribution: + :param dict command_options: + :param bool ignore_option_errors: Whether to silently ignore + options, values of which could not be resolved (e.g. due to exceptions + in directives such as file:, attr:, etc.). + If False exceptions are propagated as expected. + :rtype: list + """ + options = ConfigOptionsHandler( + distribution, command_options, ignore_option_errors) + options.parse() + + meta = ConfigMetadataHandler( + distribution.metadata, command_options, ignore_option_errors, + distribution.package_dir) + meta.parse() + + return meta, options + + +class ConfigHandler: + """Handles metadata supplied in configuration files.""" + + section_prefix = None + """Prefix for config sections handled by this handler. + Must be provided by class heirs. + + """ + + aliases = {} + """Options aliases. + For compatibility with various packages. E.g.: d2to1 and pbr. + Note: `-` in keys is replaced with `_` by config parser. + + """ + + def __init__(self, target_obj, options, ignore_option_errors=False): + sections = {} + + section_prefix = self.section_prefix + for section_name, section_options in options.items(): + if not section_name.startswith(section_prefix): + continue + + section_name = section_name.replace(section_prefix, '').strip('.') + sections[section_name] = section_options + + self.ignore_option_errors = ignore_option_errors + self.target_obj = target_obj + self.sections = sections + self.set_options = [] + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + raise NotImplementedError( + '%s must provide .parsers property' % self.__class__.__name__) + + def __setitem__(self, option_name, value): + unknown = tuple() + target_obj = self.target_obj + + # Translate alias into real name. + option_name = self.aliases.get(option_name, option_name) + + current_value = getattr(target_obj, option_name, unknown) + + if current_value is unknown: + raise KeyError(option_name) + + if current_value: + # Already inhabited. Skipping. + return + + skip_option = False + parser = self.parsers.get(option_name) + if parser: + try: + value = parser(value) + + except Exception: + skip_option = True + if not self.ignore_option_errors: + raise + + if skip_option: + return + + setter = getattr(target_obj, 'set_%s' % option_name, None) + if setter is None: + setattr(target_obj, option_name, value) + else: + setter(value) + + self.set_options.append(option_name) + + @classmethod + def _parse_list(cls, value, separator=','): + """Represents value as a list. + + Value is split either by separator (defaults to comma) or by lines. + + :param value: + :param separator: List items separator character. + :rtype: list + """ + if isinstance(value, list): # _get_parser_compound case + return value + + if '\n' in value: + value = value.splitlines() + else: + value = value.split(separator) + + return [chunk.strip() for chunk in value if chunk.strip()] + + @classmethod + def _parse_dict(cls, value): + """Represents value as a dict. + + :param value: + :rtype: dict + """ + separator = '=' + result = {} + for line in cls._parse_list(value): + key, sep, val = line.partition(separator) + if sep != separator: + raise DistutilsOptionError( + 'Unable to parse option value to dict: %s' % value) + result[key.strip()] = val.strip() + + return result + + @classmethod + def _parse_bool(cls, value): + """Represents value as boolean. + + :param value: + :rtype: bool + """ + value = value.lower() + return value in ('1', 'true', 'yes') + + @classmethod + def _parse_file(cls, value): + """Represents value as a string, allowing including text + from nearest files using `file:` directive. + + Directive is sandboxed and won't reach anything outside + directory with setup.py. + + Examples: + file: LICENSE + file: README.rst, CHANGELOG.md, src/file.txt + + :param str value: + :rtype: str + """ + include_directive = 'file:' + + if not isinstance(value, string_types): + return value + + if not value.startswith(include_directive): + return value + + spec = value[len(include_directive):] + filepaths = (os.path.abspath(path.strip()) for path in spec.split(',')) + return '\n'.join( + cls._read_file(path) + for path in filepaths + if (cls._assert_local(path) or True) + and os.path.isfile(path) + ) + + @staticmethod + def _assert_local(filepath): + if not filepath.startswith(os.getcwd()): + raise DistutilsOptionError( + '`file:` directive can not access %s' % filepath) + + @staticmethod + def _read_file(filepath): + with io.open(filepath, encoding='utf-8') as f: + return f.read() + + @classmethod + def _parse_attr(cls, value, package_dir=None): + """Represents value as a module attribute. + + Examples: + attr: package.attr + attr: package.module.attr + + :param str value: + :rtype: str + """ + attr_directive = 'attr:' + if not value.startswith(attr_directive): + return value + + attrs_path = value.replace(attr_directive, '').strip().split('.') + attr_name = attrs_path.pop() + + module_name = '.'.join(attrs_path) + module_name = module_name or '__init__' + + parent_path = os.getcwd() + if package_dir: + if attrs_path[0] in package_dir: + # A custom path was specified for the module we want to import + custom_path = package_dir[attrs_path[0]] + parts = custom_path.rsplit('/', 1) + if len(parts) > 1: + parent_path = os.path.join(os.getcwd(), parts[0]) + module_name = parts[1] + else: + module_name = custom_path + elif '' in package_dir: + # A custom parent directory was specified for all root modules + parent_path = os.path.join(os.getcwd(), package_dir['']) + sys.path.insert(0, parent_path) + try: + module = import_module(module_name) + value = getattr(module, attr_name) + + finally: + sys.path = sys.path[1:] + + return value + + @classmethod + def _get_parser_compound(cls, *parse_methods): + """Returns parser function to represents value as a list. + + Parses a value applying given methods one after another. + + :param parse_methods: + :rtype: callable + """ + def parse(value): + parsed = value + + for method in parse_methods: + parsed = method(parsed) + + return parsed + + return parse + + @classmethod + def _parse_section_to_dict(cls, section_options, values_parser=None): + """Parses section options into a dictionary. + + Optionally applies a given parser to values. + + :param dict section_options: + :param callable values_parser: + :rtype: dict + """ + value = {} + values_parser = values_parser or (lambda val: val) + for key, (_, val) in section_options.items(): + value[key] = values_parser(val) + return value + + def parse_section(self, section_options): + """Parses configuration file section. + + :param dict section_options: + """ + for (name, (_, value)) in section_options.items(): + try: + self[name] = value + + except KeyError: + pass # Keep silent for a new option may appear anytime. + + def parse(self): + """Parses configuration file items from one + or more related sections. + + """ + for section_name, section_options in self.sections.items(): + + method_postfix = '' + if section_name: # [section.option] variant + method_postfix = '_%s' % section_name + + section_parser_method = getattr( + self, + # Dots in section names are tranlsated into dunderscores. + ('parse_section%s' % method_postfix).replace('.', '__'), + None) + + if section_parser_method is None: + raise DistutilsOptionError( + 'Unsupported distribution option section: [%s.%s]' % ( + self.section_prefix, section_name)) + + section_parser_method(section_options) + + def _deprecated_config_handler(self, func, msg, warning_class): + """ this function will wrap around parameters that are deprecated + + :param msg: deprecation message + :param warning_class: class of warning exception to be raised + :param func: function to be wrapped around + """ + @wraps(func) + def config_handler(*args, **kwargs): + warnings.warn(msg, warning_class) + return func(*args, **kwargs) + + return config_handler + + +class ConfigMetadataHandler(ConfigHandler): + + section_prefix = 'metadata' + + aliases = { + 'home_page': 'url', + 'summary': 'description', + 'classifier': 'classifiers', + 'platform': 'platforms', + } + + strict_mode = False + """We need to keep it loose, to be partially compatible with + `pbr` and `d2to1` packages which also uses `metadata` section. + + """ + + def __init__(self, target_obj, options, ignore_option_errors=False, + package_dir=None): + super(ConfigMetadataHandler, self).__init__(target_obj, options, + ignore_option_errors) + self.package_dir = package_dir + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + parse_list = self._parse_list + parse_file = self._parse_file + parse_dict = self._parse_dict + + return { + 'platforms': parse_list, + 'keywords': parse_list, + 'provides': parse_list, + 'requires': self._deprecated_config_handler(parse_list, + "The requires parameter is deprecated, please use " + + "install_requires for runtime dependencies.", + DeprecationWarning), + 'obsoletes': parse_list, + 'classifiers': self._get_parser_compound(parse_file, parse_list), + 'license': parse_file, + 'description': parse_file, + 'long_description': parse_file, + 'version': self._parse_version, + 'project_urls': parse_dict, + } + + def _parse_version(self, value): + """Parses `version` option value. + + :param value: + :rtype: str + + """ + version = self._parse_file(value) + + if version != value: + version = version.strip() + # Be strict about versions loaded from file because it's easy to + # accidentally include newlines and other unintended content + if isinstance(parse(version), LegacyVersion): + tmpl = ( + 'Version loaded from {value} does not ' + 'comply with PEP 440: {version}' + ) + raise DistutilsOptionError(tmpl.format(**locals())) + + return version + + version = self._parse_attr(value, self.package_dir) + + if callable(version): + version = version() + + if not isinstance(version, string_types): + if hasattr(version, '__iter__'): + version = '.'.join(map(str, version)) + else: + version = '%s' % version + + return version + + +class ConfigOptionsHandler(ConfigHandler): + + section_prefix = 'options' + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + parse_list = self._parse_list + parse_list_semicolon = partial(self._parse_list, separator=';') + parse_bool = self._parse_bool + parse_dict = self._parse_dict + + return { + 'zip_safe': parse_bool, + 'use_2to3': parse_bool, + 'include_package_data': parse_bool, + 'package_dir': parse_dict, + 'use_2to3_fixers': parse_list, + 'use_2to3_exclude_fixers': parse_list, + 'convert_2to3_doctests': parse_list, + 'scripts': parse_list, + 'eager_resources': parse_list, + 'dependency_links': parse_list, + 'namespace_packages': parse_list, + 'install_requires': parse_list_semicolon, + 'setup_requires': parse_list_semicolon, + 'tests_require': parse_list_semicolon, + 'packages': self._parse_packages, + 'entry_points': self._parse_file, + 'py_modules': parse_list, + } + + def _parse_packages(self, value): + """Parses `packages` option value. + + :param value: + :rtype: list + """ + find_directives = ['find:', 'find_namespace:'] + trimmed_value = value.strip() + + if trimmed_value not in find_directives: + return self._parse_list(value) + + findns = trimmed_value == find_directives[1] + if findns and not PY3: + raise DistutilsOptionError( + 'find_namespace: directive is unsupported on Python < 3.3') + + # Read function arguments from a dedicated section. + find_kwargs = self.parse_section_packages__find( + self.sections.get('packages.find', {})) + + if findns: + from setuptools import find_namespace_packages as find_packages + else: + from setuptools import find_packages + + return find_packages(**find_kwargs) + + def parse_section_packages__find(self, section_options): + """Parses `packages.find` configuration file section. + + To be used in conjunction with _parse_packages(). + + :param dict section_options: + """ + section_data = self._parse_section_to_dict( + section_options, self._parse_list) + + valid_keys = ['where', 'include', 'exclude'] + + find_kwargs = dict( + [(k, v) for k, v in section_data.items() if k in valid_keys and v]) + + where = find_kwargs.get('where') + if where is not None: + find_kwargs['where'] = where[0] # cast list to single val + + return find_kwargs + + def parse_section_entry_points(self, section_options): + """Parses `entry_points` configuration file section. + + :param dict section_options: + """ + parsed = self._parse_section_to_dict(section_options, self._parse_list) + self['entry_points'] = parsed + + def _parse_package_data(self, section_options): + parsed = self._parse_section_to_dict(section_options, self._parse_list) + + root = parsed.get('*') + if root: + parsed[''] = root + del parsed['*'] + + return parsed + + def parse_section_package_data(self, section_options): + """Parses `package_data` configuration file section. + + :param dict section_options: + """ + self['package_data'] = self._parse_package_data(section_options) + + def parse_section_exclude_package_data(self, section_options): + """Parses `exclude_package_data` configuration file section. + + :param dict section_options: + """ + self['exclude_package_data'] = self._parse_package_data( + section_options) + + def parse_section_extras_require(self, section_options): + """Parses `extras_require` configuration file section. + + :param dict section_options: + """ + parse_list = partial(self._parse_list, separator=';') + self['extras_require'] = self._parse_section_to_dict( + section_options, parse_list) + + def parse_section_data_files(self, section_options): + """Parses `data_files` configuration file section. + + :param dict section_options: + """ + parsed = self._parse_section_to_dict(section_options, self._parse_list) + self['data_files'] = [(k, v) for k, v in parsed.items()] diff --git a/venv/lib/python3.7/site-packages/setuptools/dep_util.py b/venv/lib/python3.7/site-packages/setuptools/dep_util.py new file mode 100644 index 0000000..2931c13 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/dep_util.py @@ -0,0 +1,23 @@ +from distutils.dep_util import newer_group + +# yes, this is was almost entirely copy-pasted from +# 'newer_pairwise()', this is just another convenience +# function. +def newer_pairwise_group(sources_groups, targets): + """Walk both arguments in parallel, testing if each source group is newer + than its corresponding target. Returns a pair of lists (sources_groups, + targets) where sources is newer than target, according to the semantics + of 'newer_group()'. + """ + if len(sources_groups) != len(targets): + raise ValueError("'sources_group' and 'targets' must be the same length") + + # build a pair of lists (sources_groups, targets) where source is newer + n_sources = [] + n_targets = [] + for i in range(len(sources_groups)): + if newer_group(sources_groups[i], targets[i]): + n_sources.append(sources_groups[i]) + n_targets.append(targets[i]) + + return n_sources, n_targets diff --git a/venv/lib/python3.7/site-packages/setuptools/depends.py b/venv/lib/python3.7/site-packages/setuptools/depends.py new file mode 100644 index 0000000..45e7052 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/depends.py @@ -0,0 +1,186 @@ +import sys +import imp +import marshal +from distutils.version import StrictVersion +from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN + +from .py33compat import Bytecode + + +__all__ = [ + 'Require', 'find_module', 'get_module_constant', 'extract_constant' +] + + +class Require: + """A prerequisite to building or installing a distribution""" + + def __init__(self, name, requested_version, module, homepage='', + attribute=None, format=None): + + if format is None and requested_version is not None: + format = StrictVersion + + if format is not None: + requested_version = format(requested_version) + if attribute is None: + attribute = '__version__' + + self.__dict__.update(locals()) + del self.self + + def full_name(self): + """Return full package/distribution name, w/version""" + if self.requested_version is not None: + return '%s-%s' % (self.name, self.requested_version) + return self.name + + def version_ok(self, version): + """Is 'version' sufficiently up-to-date?""" + return self.attribute is None or self.format is None or \ + str(version) != "unknown" and version >= self.requested_version + + def get_version(self, paths=None, default="unknown"): + """Get version number of installed module, 'None', or 'default' + + Search 'paths' for module. If not found, return 'None'. If found, + return the extracted version attribute, or 'default' if no version + attribute was specified, or the value cannot be determined without + importing the module. The version is formatted according to the + requirement's version format (if any), unless it is 'None' or the + supplied 'default'. + """ + + if self.attribute is None: + try: + f, p, i = find_module(self.module, paths) + if f: + f.close() + return default + except ImportError: + return None + + v = get_module_constant(self.module, self.attribute, default, paths) + + if v is not None and v is not default and self.format is not None: + return self.format(v) + + return v + + def is_present(self, paths=None): + """Return true if dependency is present on 'paths'""" + return self.get_version(paths) is not None + + def is_current(self, paths=None): + """Return true if dependency is present and up-to-date on 'paths'""" + version = self.get_version(paths) + if version is None: + return False + return self.version_ok(version) + + +def find_module(module, paths=None): + """Just like 'imp.find_module()', but with package support""" + + parts = module.split('.') + + while parts: + part = parts.pop(0) + f, path, (suffix, mode, kind) = info = imp.find_module(part, paths) + + if kind == PKG_DIRECTORY: + parts = parts or ['__init__'] + paths = [path] + + elif parts: + raise ImportError("Can't find %r in %s" % (parts, module)) + + return info + + +def get_module_constant(module, symbol, default=-1, paths=None): + """Find 'module' by searching 'paths', and extract 'symbol' + + Return 'None' if 'module' does not exist on 'paths', or it does not define + 'symbol'. If the module defines 'symbol' as a constant, return the + constant. Otherwise, return 'default'.""" + + try: + f, path, (suffix, mode, kind) = find_module(module, paths) + except ImportError: + # Module doesn't exist + return None + + try: + if kind == PY_COMPILED: + f.read(8) # skip magic & date + code = marshal.load(f) + elif kind == PY_FROZEN: + code = imp.get_frozen_object(module) + elif kind == PY_SOURCE: + code = compile(f.read(), path, 'exec') + else: + # Not something we can parse; we'll have to import it. :( + if module not in sys.modules: + imp.load_module(module, f, path, (suffix, mode, kind)) + return getattr(sys.modules[module], symbol, None) + + finally: + if f: + f.close() + + return extract_constant(code, symbol, default) + + +def extract_constant(code, symbol, default=-1): + """Extract the constant value of 'symbol' from 'code' + + If the name 'symbol' is bound to a constant value by the Python code + object 'code', return that value. If 'symbol' is bound to an expression, + return 'default'. Otherwise, return 'None'. + + Return value is based on the first assignment to 'symbol'. 'symbol' must + be a global, or at least a non-"fast" local in the code block. That is, + only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' + must be present in 'code.co_names'. + """ + if symbol not in code.co_names: + # name's not there, can't possibly be an assignment + return None + + name_idx = list(code.co_names).index(symbol) + + STORE_NAME = 90 + STORE_GLOBAL = 97 + LOAD_CONST = 100 + + const = default + + for byte_code in Bytecode(code): + op = byte_code.opcode + arg = byte_code.arg + + if op == LOAD_CONST: + const = code.co_consts[arg] + elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): + return const + else: + const = default + + +def _update_globals(): + """ + Patch the globals to remove the objects not available on some platforms. + + XXX it'd be better to test assertions about bytecode instead. + """ + + if not sys.platform.startswith('java') and sys.platform != 'cli': + return + incompatible = 'extract_constant', 'get_module_constant' + for name in incompatible: + del globals()[name] + __all__.remove(name) + + +_update_globals() diff --git a/venv/lib/python3.7/site-packages/setuptools/dist.py b/venv/lib/python3.7/site-packages/setuptools/dist.py new file mode 100644 index 0000000..7062ae8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/dist.py @@ -0,0 +1,1147 @@ +# -*- coding: utf-8 -*- +__all__ = ['Distribution'] + +import re +import os +import warnings +import numbers +import distutils.log +import distutils.core +import distutils.cmd +import distutils.dist +import itertools + + +from collections import defaultdict +from email import message_from_file + +from distutils.errors import ( + DistutilsOptionError, DistutilsPlatformError, DistutilsSetupError, +) +from distutils.util import rfc822_escape +from distutils.version import StrictVersion + +from setuptools.extern import six +from setuptools.extern import packaging +from setuptools.extern.six.moves import map, filter, filterfalse + +from . import SetuptoolsDeprecationWarning + +from setuptools.depends import Require +from setuptools import windows_support +from setuptools.monkey import get_unpatched +from setuptools.config import parse_configuration +import pkg_resources +from .py36compat import Distribution_parse_config_files + +__import__('setuptools.extern.packaging.specifiers') +__import__('setuptools.extern.packaging.version') + + +def _get_unpatched(cls): + warnings.warn("Do not call this function", DistDeprecationWarning) + return get_unpatched(cls) + + +def get_metadata_version(self): + mv = getattr(self, 'metadata_version', None) + + if mv is None: + if self.long_description_content_type or self.provides_extras: + mv = StrictVersion('2.1') + elif (self.maintainer is not None or + self.maintainer_email is not None or + getattr(self, 'python_requires', None) is not None): + mv = StrictVersion('1.2') + elif (self.provides or self.requires or self.obsoletes or + self.classifiers or self.download_url): + mv = StrictVersion('1.1') + else: + mv = StrictVersion('1.0') + + self.metadata_version = mv + + return mv + + +def read_pkg_file(self, file): + """Reads the metadata values from a file object.""" + msg = message_from_file(file) + + def _read_field(name): + value = msg[name] + if value == 'UNKNOWN': + return None + return value + + def _read_list(name): + values = msg.get_all(name, None) + if values == []: + return None + return values + + self.metadata_version = StrictVersion(msg['metadata-version']) + self.name = _read_field('name') + self.version = _read_field('version') + self.description = _read_field('summary') + # we are filling author only. + self.author = _read_field('author') + self.maintainer = None + self.author_email = _read_field('author-email') + self.maintainer_email = None + self.url = _read_field('home-page') + self.license = _read_field('license') + + if 'download-url' in msg: + self.download_url = _read_field('download-url') + else: + self.download_url = None + + self.long_description = _read_field('description') + self.description = _read_field('summary') + + if 'keywords' in msg: + self.keywords = _read_field('keywords').split(',') + + self.platforms = _read_list('platform') + self.classifiers = _read_list('classifier') + + # PEP 314 - these fields only exist in 1.1 + if self.metadata_version == StrictVersion('1.1'): + self.requires = _read_list('requires') + self.provides = _read_list('provides') + self.obsoletes = _read_list('obsoletes') + else: + self.requires = None + self.provides = None + self.obsoletes = None + + +# Based on Python 3.5 version +def write_pkg_file(self, file): + """Write the PKG-INFO format data to a file object. + """ + version = self.get_metadata_version() + + if six.PY2: + def write_field(key, value): + file.write("%s: %s\n" % (key, self._encode_field(value))) + else: + def write_field(key, value): + file.write("%s: %s\n" % (key, value)) + + + write_field('Metadata-Version', str(version)) + write_field('Name', self.get_name()) + write_field('Version', self.get_version()) + write_field('Summary', self.get_description()) + write_field('Home-page', self.get_url()) + + if version < StrictVersion('1.2'): + write_field('Author', self.get_contact()) + write_field('Author-email', self.get_contact_email()) + else: + optional_fields = ( + ('Author', 'author'), + ('Author-email', 'author_email'), + ('Maintainer', 'maintainer'), + ('Maintainer-email', 'maintainer_email'), + ) + + for field, attr in optional_fields: + attr_val = getattr(self, attr) + + if attr_val is not None: + write_field(field, attr_val) + + write_field('License', self.get_license()) + if self.download_url: + write_field('Download-URL', self.download_url) + for project_url in self.project_urls.items(): + write_field('Project-URL', '%s, %s' % project_url) + + long_desc = rfc822_escape(self.get_long_description()) + write_field('Description', long_desc) + + keywords = ','.join(self.get_keywords()) + if keywords: + write_field('Keywords', keywords) + + if version >= StrictVersion('1.2'): + for platform in self.get_platforms(): + write_field('Platform', platform) + else: + self._write_list(file, 'Platform', self.get_platforms()) + + self._write_list(file, 'Classifier', self.get_classifiers()) + + # PEP 314 + self._write_list(file, 'Requires', self.get_requires()) + self._write_list(file, 'Provides', self.get_provides()) + self._write_list(file, 'Obsoletes', self.get_obsoletes()) + + # Setuptools specific for PEP 345 + if hasattr(self, 'python_requires'): + write_field('Requires-Python', self.python_requires) + + # PEP 566 + if self.long_description_content_type: + write_field( + 'Description-Content-Type', + self.long_description_content_type + ) + if self.provides_extras: + for extra in self.provides_extras: + write_field('Provides-Extra', extra) + + +sequence = tuple, list + + +def check_importable(dist, attr, value): + try: + ep = pkg_resources.EntryPoint.parse('x=' + value) + assert not ep.extras + except (TypeError, ValueError, AttributeError, AssertionError): + raise DistutilsSetupError( + "%r must be importable 'module:attrs' string (got %r)" + % (attr, value) + ) + + +def assert_string_list(dist, attr, value): + """Verify that value is a string list or None""" + try: + assert ''.join(value) != value + except (TypeError, ValueError, AttributeError, AssertionError): + raise DistutilsSetupError( + "%r must be a list of strings (got %r)" % (attr, value) + ) + + +def check_nsp(dist, attr, value): + """Verify that namespace packages are valid""" + ns_packages = value + assert_string_list(dist, attr, ns_packages) + for nsp in ns_packages: + if not dist.has_contents_for(nsp): + raise DistutilsSetupError( + "Distribution contains no modules or packages for " + + "namespace package %r" % nsp + ) + parent, sep, child = nsp.rpartition('.') + if parent and parent not in ns_packages: + distutils.log.warn( + "WARNING: %r is declared as a package namespace, but %r" + " is not: please correct this in setup.py", nsp, parent + ) + + +def check_extras(dist, attr, value): + """Verify that extras_require mapping is valid""" + try: + list(itertools.starmap(_check_extra, value.items())) + except (TypeError, ValueError, AttributeError): + raise DistutilsSetupError( + "'extras_require' must be a dictionary whose values are " + "strings or lists of strings containing valid project/version " + "requirement specifiers." + ) + + +def _check_extra(extra, reqs): + name, sep, marker = extra.partition(':') + if marker and pkg_resources.invalid_marker(marker): + raise DistutilsSetupError("Invalid environment marker: " + marker) + list(pkg_resources.parse_requirements(reqs)) + + +def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + tmpl = "{attr!r} must be a boolean value (got {value!r})" + raise DistutilsSetupError(tmpl.format(attr=attr, value=value)) + + +def check_requirements(dist, attr, value): + """Verify that install_requires is a valid requirements list""" + try: + list(pkg_resources.parse_requirements(value)) + if isinstance(value, (dict, set)): + raise TypeError("Unordered types are not allowed") + except (TypeError, ValueError) as error: + tmpl = ( + "{attr!r} must be a string or list of strings " + "containing valid project/version requirement specifiers; {error}" + ) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) + + +def check_specifier(dist, attr, value): + """Verify that value is a valid version specifier""" + try: + packaging.specifiers.SpecifierSet(value) + except packaging.specifiers.InvalidSpecifier as error: + tmpl = ( + "{attr!r} must be a string " + "containing valid version specifiers; {error}" + ) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) + + +def check_entry_points(dist, attr, value): + """Verify that entry_points map is parseable""" + try: + pkg_resources.EntryPoint.parse_map(value) + except ValueError as e: + raise DistutilsSetupError(e) + + +def check_test_suite(dist, attr, value): + if not isinstance(value, six.string_types): + raise DistutilsSetupError("test_suite must be a string") + + +def check_package_data(dist, attr, value): + """Verify that value is a dictionary of package names to glob lists""" + if isinstance(value, dict): + for k, v in value.items(): + if not isinstance(k, str): + break + try: + iter(v) + except TypeError: + break + else: + return + raise DistutilsSetupError( + attr + " must be a dictionary mapping package names to lists of " + "wildcard patterns" + ) + + +def check_packages(dist, attr, value): + for pkgname in value: + if not re.match(r'\w+(\.\w+)*', pkgname): + distutils.log.warn( + "WARNING: %r not a valid package name; please use only " + ".-separated package names in setup.py", pkgname + ) + + +_Distribution = get_unpatched(distutils.core.Distribution) + + +class Distribution(Distribution_parse_config_files, _Distribution): + """Distribution with support for features, tests, and package data + + This is an enhanced version of 'distutils.dist.Distribution' that + effectively adds the following new optional keyword arguments to 'setup()': + + 'install_requires' -- a string or sequence of strings specifying project + versions that the distribution requires when installed, in the format + used by 'pkg_resources.require()'. They will be installed + automatically when the package is installed. If you wish to use + packages that are not available in PyPI, or want to give your users an + alternate download location, you can add a 'find_links' option to the + '[easy_install]' section of your project's 'setup.cfg' file, and then + setuptools will scan the listed web pages for links that satisfy the + requirements. + + 'extras_require' -- a dictionary mapping names of optional "extras" to the + additional requirement(s) that using those extras incurs. For example, + this:: + + extras_require = dict(reST = ["docutils>=0.3", "reSTedit"]) + + indicates that the distribution can optionally provide an extra + capability called "reST", but it can only be used if docutils and + reSTedit are installed. If the user installs your package using + EasyInstall and requests one of your extras, the corresponding + additional requirements will be installed if needed. + + 'features' **deprecated** -- a dictionary mapping option names to + 'setuptools.Feature' + objects. Features are a portion of the distribution that can be + included or excluded based on user options, inter-feature dependencies, + and availability on the current system. Excluded features are omitted + from all setup commands, including source and binary distributions, so + you can create multiple distributions from the same source tree. + Feature names should be valid Python identifiers, except that they may + contain the '-' (minus) sign. Features can be included or excluded + via the command line options '--with-X' and '--without-X', where 'X' is + the name of the feature. Whether a feature is included by default, and + whether you are allowed to control this from the command line, is + determined by the Feature object. See the 'Feature' class for more + information. + + 'test_suite' -- the name of a test suite to run for the 'test' command. + If the user runs 'python setup.py test', the package will be installed, + and the named test suite will be run. The format is the same as + would be used on a 'unittest.py' command line. That is, it is the + dotted name of an object to import and call to generate a test suite. + + 'package_data' -- a dictionary mapping package names to lists of filenames + or globs to use to find data files contained in the named packages. + If the dictionary has filenames or globs listed under '""' (the empty + string), those names will be searched for in every package, in addition + to any names for the specific package. Data files found using these + names/globs will be installed along with the package, in the same + location as the package. Note that globs are allowed to reference + the contents of non-package subdirectories, as long as you use '/' as + a path separator. (Globs are automatically converted to + platform-specific paths at runtime.) + + In addition to these new keywords, this class also has several new methods + for manipulating the distribution's contents. For example, the 'include()' + and 'exclude()' methods can be thought of as in-place add and subtract + commands that add or remove packages, modules, extensions, and so on from + the distribution. They are used by the feature subsystem to configure the + distribution for the included and excluded features. + """ + + _DISTUTILS_UNSUPPORTED_METADATA = { + 'long_description_content_type': None, + 'project_urls': dict, + 'provides_extras': set, + } + + _patched_dist = None + + def patch_missing_pkg_info(self, attrs): + # Fake up a replacement for the data that would normally come from + # PKG-INFO, but which might not yet be built if this is a fresh + # checkout. + # + if not attrs or 'name' not in attrs or 'version' not in attrs: + return + key = pkg_resources.safe_name(str(attrs['name'])).lower() + dist = pkg_resources.working_set.by_key.get(key) + if dist is not None and not dist.has_metadata('PKG-INFO'): + dist._version = pkg_resources.safe_version(str(attrs['version'])) + self._patched_dist = dist + + def __init__(self, attrs=None): + have_package_data = hasattr(self, "package_data") + if not have_package_data: + self.package_data = {} + attrs = attrs or {} + if 'features' in attrs or 'require_features' in attrs: + Feature.warn_deprecated() + self.require_features = [] + self.features = {} + self.dist_files = [] + # Filter-out setuptools' specific options. + self.src_root = attrs.pop("src_root", None) + self.patch_missing_pkg_info(attrs) + self.dependency_links = attrs.pop('dependency_links', []) + self.setup_requires = attrs.pop('setup_requires', []) + for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): + vars(self).setdefault(ep.name, None) + _Distribution.__init__(self, { + k: v for k, v in attrs.items() + if k not in self._DISTUTILS_UNSUPPORTED_METADATA + }) + + # Fill-in missing metadata fields not supported by distutils. + # Note some fields may have been set by other tools (e.g. pbr) + # above; they are taken preferrentially to setup() arguments + for option, default in self._DISTUTILS_UNSUPPORTED_METADATA.items(): + for source in self.metadata.__dict__, attrs: + if option in source: + value = source[option] + break + else: + value = default() if default else None + setattr(self.metadata, option, value) + + if isinstance(self.metadata.version, numbers.Number): + # Some people apparently take "version number" too literally :) + self.metadata.version = str(self.metadata.version) + + if self.metadata.version is not None: + try: + ver = packaging.version.Version(self.metadata.version) + normalized_version = str(ver) + if self.metadata.version != normalized_version: + warnings.warn( + "Normalizing '%s' to '%s'" % ( + self.metadata.version, + normalized_version, + ) + ) + self.metadata.version = normalized_version + except (packaging.version.InvalidVersion, TypeError): + warnings.warn( + "The version specified (%r) is an invalid version, this " + "may not work as expected with newer versions of " + "setuptools, pip, and PyPI. Please see PEP 440 for more " + "details." % self.metadata.version + ) + self._finalize_requires() + + def _finalize_requires(self): + """ + Set `metadata.python_requires` and fix environment markers + in `install_requires` and `extras_require`. + """ + if getattr(self, 'python_requires', None): + self.metadata.python_requires = self.python_requires + + if getattr(self, 'extras_require', None): + for extra in self.extras_require.keys(): + # Since this gets called multiple times at points where the + # keys have become 'converted' extras, ensure that we are only + # truly adding extras we haven't seen before here. + extra = extra.split(':')[0] + if extra: + self.metadata.provides_extras.add(extra) + + self._convert_extras_requirements() + self._move_install_requirements_markers() + + def _convert_extras_requirements(self): + """ + Convert requirements in `extras_require` of the form + `"extra": ["barbazquux; {marker}"]` to + `"extra:{marker}": ["barbazquux"]`. + """ + spec_ext_reqs = getattr(self, 'extras_require', None) or {} + self._tmp_extras_require = defaultdict(list) + for section, v in spec_ext_reqs.items(): + # Do not strip empty sections. + self._tmp_extras_require[section] + for r in pkg_resources.parse_requirements(v): + suffix = self._suffix_for(r) + self._tmp_extras_require[section + suffix].append(r) + + @staticmethod + def _suffix_for(req): + """ + For a requirement, return the 'extras_require' suffix for + that requirement. + """ + return ':' + str(req.marker) if req.marker else '' + + def _move_install_requirements_markers(self): + """ + Move requirements in `install_requires` that are using environment + markers `extras_require`. + """ + + # divide the install_requires into two sets, simple ones still + # handled by install_requires and more complex ones handled + # by extras_require. + + def is_simple_req(req): + return not req.marker + + spec_inst_reqs = getattr(self, 'install_requires', None) or () + inst_reqs = list(pkg_resources.parse_requirements(spec_inst_reqs)) + simple_reqs = filter(is_simple_req, inst_reqs) + complex_reqs = filterfalse(is_simple_req, inst_reqs) + self.install_requires = list(map(str, simple_reqs)) + + for r in complex_reqs: + self._tmp_extras_require[':' + str(r.marker)].append(r) + self.extras_require = dict( + (k, [str(r) for r in map(self._clean_req, v)]) + for k, v in self._tmp_extras_require.items() + ) + + def _clean_req(self, req): + """ + Given a Requirement, remove environment markers and return it. + """ + req.marker = None + return req + + def parse_config_files(self, filenames=None, ignore_option_errors=False): + """Parses configuration files from various levels + and loads configuration. + + """ + _Distribution.parse_config_files(self, filenames=filenames) + + parse_configuration(self, self.command_options, + ignore_option_errors=ignore_option_errors) + self._finalize_requires() + + def parse_command_line(self): + """Process features after parsing command line options""" + result = _Distribution.parse_command_line(self) + if self.features: + self._finalize_features() + return result + + def _feature_attrname(self, name): + """Convert feature name to corresponding option attribute name""" + return 'with_' + name.replace('-', '_') + + def fetch_build_eggs(self, requires): + """Resolve pre-setup requirements""" + resolved_dists = pkg_resources.working_set.resolve( + pkg_resources.parse_requirements(requires), + installer=self.fetch_build_egg, + replace_conflicting=True, + ) + for dist in resolved_dists: + pkg_resources.working_set.add(dist, replace=True) + return resolved_dists + + def finalize_options(self): + _Distribution.finalize_options(self) + if self.features: + self._set_global_opts_from_features() + + for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): + value = getattr(self, ep.name, None) + if value is not None: + ep.require(installer=self.fetch_build_egg) + ep.load()(self, ep.name, value) + if getattr(self, 'convert_2to3_doctests', None): + # XXX may convert to set here when we can rely on set being builtin + self.convert_2to3_doctests = [ + os.path.abspath(p) + for p in self.convert_2to3_doctests + ] + else: + self.convert_2to3_doctests = [] + + def get_egg_cache_dir(self): + egg_cache_dir = os.path.join(os.curdir, '.eggs') + if not os.path.exists(egg_cache_dir): + os.mkdir(egg_cache_dir) + windows_support.hide_file(egg_cache_dir) + readme_txt_filename = os.path.join(egg_cache_dir, 'README.txt') + with open(readme_txt_filename, 'w') as f: + f.write('This directory contains eggs that were downloaded ' + 'by setuptools to build, test, and run plug-ins.\n\n') + f.write('This directory caches those eggs to prevent ' + 'repeated downloads.\n\n') + f.write('However, it is safe to delete this directory.\n\n') + + return egg_cache_dir + + def fetch_build_egg(self, req): + """Fetch an egg needed for building""" + from setuptools.command.easy_install import easy_install + dist = self.__class__({'script_args': ['easy_install']}) + opts = dist.get_option_dict('easy_install') + opts.clear() + opts.update( + (k, v) + for k, v in self.get_option_dict('easy_install').items() + if k in ( + # don't use any other settings + 'find_links', 'site_dirs', 'index_url', + 'optimize', 'site_dirs', 'allow_hosts', + )) + if self.dependency_links: + links = self.dependency_links[:] + if 'find_links' in opts: + links = opts['find_links'][1] + links + opts['find_links'] = ('setup', links) + install_dir = self.get_egg_cache_dir() + cmd = easy_install( + dist, args=["x"], install_dir=install_dir, + exclude_scripts=True, + always_copy=False, build_directory=None, editable=False, + upgrade=False, multi_version=True, no_report=True, user=False + ) + cmd.ensure_finalized() + return cmd.easy_install(req) + + def _set_global_opts_from_features(self): + """Add --with-X/--without-X options based on optional features""" + + go = [] + no = self.negative_opt.copy() + + for name, feature in self.features.items(): + self._set_feature(name, None) + feature.validate(self) + + if feature.optional: + descr = feature.description + incdef = ' (default)' + excdef = '' + if not feature.include_by_default(): + excdef, incdef = incdef, excdef + + new = ( + ('with-' + name, None, 'include ' + descr + incdef), + ('without-' + name, None, 'exclude ' + descr + excdef), + ) + go.extend(new) + no['without-' + name] = 'with-' + name + + self.global_options = self.feature_options = go + self.global_options + self.negative_opt = self.feature_negopt = no + + def _finalize_features(self): + """Add/remove features and resolve dependencies between them""" + + # First, flag all the enabled items (and thus their dependencies) + for name, feature in self.features.items(): + enabled = self.feature_is_included(name) + if enabled or (enabled is None and feature.include_by_default()): + feature.include_in(self) + self._set_feature(name, 1) + + # Then disable the rest, so that off-by-default features don't + # get flagged as errors when they're required by an enabled feature + for name, feature in self.features.items(): + if not self.feature_is_included(name): + feature.exclude_from(self) + self._set_feature(name, 0) + + def get_command_class(self, command): + """Pluggable version of get_command_class()""" + if command in self.cmdclass: + return self.cmdclass[command] + + eps = pkg_resources.iter_entry_points('distutils.commands', command) + for ep in eps: + ep.require(installer=self.fetch_build_egg) + self.cmdclass[command] = cmdclass = ep.load() + return cmdclass + else: + return _Distribution.get_command_class(self, command) + + def print_commands(self): + for ep in pkg_resources.iter_entry_points('distutils.commands'): + if ep.name not in self.cmdclass: + # don't require extras as the commands won't be invoked + cmdclass = ep.resolve() + self.cmdclass[ep.name] = cmdclass + return _Distribution.print_commands(self) + + def get_command_list(self): + for ep in pkg_resources.iter_entry_points('distutils.commands'): + if ep.name not in self.cmdclass: + # don't require extras as the commands won't be invoked + cmdclass = ep.resolve() + self.cmdclass[ep.name] = cmdclass + return _Distribution.get_command_list(self) + + def _set_feature(self, name, status): + """Set feature's inclusion status""" + setattr(self, self._feature_attrname(name), status) + + def feature_is_included(self, name): + """Return 1 if feature is included, 0 if excluded, 'None' if unknown""" + return getattr(self, self._feature_attrname(name)) + + def include_feature(self, name): + """Request inclusion of feature named 'name'""" + + if self.feature_is_included(name) == 0: + descr = self.features[name].description + raise DistutilsOptionError( + descr + " is required, but was excluded or is not available" + ) + self.features[name].include_in(self) + self._set_feature(name, 1) + + def include(self, **attrs): + """Add items to distribution that are named in keyword arguments + + For example, 'dist.exclude(py_modules=["x"])' would add 'x' to + the distribution's 'py_modules' attribute, if it was not already + there. + + Currently, this method only supports inclusion for attributes that are + lists or tuples. If you need to add support for adding to other + attributes in this or a subclass, you can add an '_include_X' method, + where 'X' is the name of the attribute. The method will be called with + the value passed to 'include()'. So, 'dist.include(foo={"bar":"baz"})' + will try to call 'dist._include_foo({"bar":"baz"})', which can then + handle whatever special inclusion logic is needed. + """ + for k, v in attrs.items(): + include = getattr(self, '_include_' + k, None) + if include: + include(v) + else: + self._include_misc(k, v) + + def exclude_package(self, package): + """Remove packages, modules, and extensions in named package""" + + pfx = package + '.' + if self.packages: + self.packages = [ + p for p in self.packages + if p != package and not p.startswith(pfx) + ] + + if self.py_modules: + self.py_modules = [ + p for p in self.py_modules + if p != package and not p.startswith(pfx) + ] + + if self.ext_modules: + self.ext_modules = [ + p for p in self.ext_modules + if p.name != package and not p.name.startswith(pfx) + ] + + def has_contents_for(self, package): + """Return true if 'exclude_package(package)' would do something""" + + pfx = package + '.' + + for p in self.iter_distribution_names(): + if p == package or p.startswith(pfx): + return True + + def _exclude_misc(self, name, value): + """Handle 'exclude()' for list/tuple attrs without a special handler""" + if not isinstance(value, sequence): + raise DistutilsSetupError( + "%s: setting must be a list or tuple (%r)" % (name, value) + ) + try: + old = getattr(self, name) + except AttributeError: + raise DistutilsSetupError( + "%s: No such distribution setting" % name + ) + if old is not None and not isinstance(old, sequence): + raise DistutilsSetupError( + name + ": this setting cannot be changed via include/exclude" + ) + elif old: + setattr(self, name, [item for item in old if item not in value]) + + def _include_misc(self, name, value): + """Handle 'include()' for list/tuple attrs without a special handler""" + + if not isinstance(value, sequence): + raise DistutilsSetupError( + "%s: setting must be a list (%r)" % (name, value) + ) + try: + old = getattr(self, name) + except AttributeError: + raise DistutilsSetupError( + "%s: No such distribution setting" % name + ) + if old is None: + setattr(self, name, value) + elif not isinstance(old, sequence): + raise DistutilsSetupError( + name + ": this setting cannot be changed via include/exclude" + ) + else: + new = [item for item in value if item not in old] + setattr(self, name, old + new) + + def exclude(self, **attrs): + """Remove items from distribution that are named in keyword arguments + + For example, 'dist.exclude(py_modules=["x"])' would remove 'x' from + the distribution's 'py_modules' attribute. Excluding packages uses + the 'exclude_package()' method, so all of the package's contained + packages, modules, and extensions are also excluded. + + Currently, this method only supports exclusion from attributes that are + lists or tuples. If you need to add support for excluding from other + attributes in this or a subclass, you can add an '_exclude_X' method, + where 'X' is the name of the attribute. The method will be called with + the value passed to 'exclude()'. So, 'dist.exclude(foo={"bar":"baz"})' + will try to call 'dist._exclude_foo({"bar":"baz"})', which can then + handle whatever special exclusion logic is needed. + """ + for k, v in attrs.items(): + exclude = getattr(self, '_exclude_' + k, None) + if exclude: + exclude(v) + else: + self._exclude_misc(k, v) + + def _exclude_packages(self, packages): + if not isinstance(packages, sequence): + raise DistutilsSetupError( + "packages: setting must be a list or tuple (%r)" % (packages,) + ) + list(map(self.exclude_package, packages)) + + def _parse_command_opts(self, parser, args): + # Remove --with-X/--without-X options when processing command args + self.global_options = self.__class__.global_options + self.negative_opt = self.__class__.negative_opt + + # First, expand any aliases + command = args[0] + aliases = self.get_option_dict('aliases') + while command in aliases: + src, alias = aliases[command] + del aliases[command] # ensure each alias can expand only once! + import shlex + args[:1] = shlex.split(alias, True) + command = args[0] + + nargs = _Distribution._parse_command_opts(self, parser, args) + + # Handle commands that want to consume all remaining arguments + cmd_class = self.get_command_class(command) + if getattr(cmd_class, 'command_consumes_arguments', None): + self.get_option_dict(command)['args'] = ("command line", nargs) + if nargs is not None: + return [] + + return nargs + + def get_cmdline_options(self): + """Return a '{cmd: {opt:val}}' map of all command-line options + + Option names are all long, but do not include the leading '--', and + contain dashes rather than underscores. If the option doesn't take + an argument (e.g. '--quiet'), the 'val' is 'None'. + + Note that options provided by config files are intentionally excluded. + """ + + d = {} + + for cmd, opts in self.command_options.items(): + + for opt, (src, val) in opts.items(): + + if src != "command line": + continue + + opt = opt.replace('_', '-') + + if val == 0: + cmdobj = self.get_command_obj(cmd) + neg_opt = self.negative_opt.copy() + neg_opt.update(getattr(cmdobj, 'negative_opt', {})) + for neg, pos in neg_opt.items(): + if pos == opt: + opt = neg + val = None + break + else: + raise AssertionError("Shouldn't be able to get here") + + elif val == 1: + val = None + + d.setdefault(cmd, {})[opt] = val + + return d + + def iter_distribution_names(self): + """Yield all packages, modules, and extension names in distribution""" + + for pkg in self.packages or (): + yield pkg + + for module in self.py_modules or (): + yield module + + for ext in self.ext_modules or (): + if isinstance(ext, tuple): + name, buildinfo = ext + else: + name = ext.name + if name.endswith('module'): + name = name[:-6] + yield name + + def handle_display_options(self, option_order): + """If there were any non-global "display-only" options + (--help-commands or the metadata display options) on the command + line, display the requested info and return true; else return + false. + """ + import sys + + if six.PY2 or self.help_commands: + return _Distribution.handle_display_options(self, option_order) + + # Stdout may be StringIO (e.g. in tests) + import io + if not isinstance(sys.stdout, io.TextIOWrapper): + return _Distribution.handle_display_options(self, option_order) + + # Don't wrap stdout if utf-8 is already the encoding. Provides + # workaround for #334. + if sys.stdout.encoding.lower() in ('utf-8', 'utf8'): + return _Distribution.handle_display_options(self, option_order) + + # Print metadata in UTF-8 no matter the platform + encoding = sys.stdout.encoding + errors = sys.stdout.errors + newline = sys.platform != 'win32' and '\n' or None + line_buffering = sys.stdout.line_buffering + + sys.stdout = io.TextIOWrapper( + sys.stdout.detach(), 'utf-8', errors, newline, line_buffering) + try: + return _Distribution.handle_display_options(self, option_order) + finally: + sys.stdout = io.TextIOWrapper( + sys.stdout.detach(), encoding, errors, newline, line_buffering) + + +class Feature: + """ + **deprecated** -- The `Feature` facility was never completely implemented + or supported, `has reported issues + <https://github.com/pypa/setuptools/issues/58>`_ and will be removed in + a future version. + + A subset of the distribution that can be excluded if unneeded/wanted + + Features are created using these keyword arguments: + + 'description' -- a short, human readable description of the feature, to + be used in error messages, and option help messages. + + 'standard' -- if true, the feature is included by default if it is + available on the current system. Otherwise, the feature is only + included if requested via a command line '--with-X' option, or if + another included feature requires it. The default setting is 'False'. + + 'available' -- if true, the feature is available for installation on the + current system. The default setting is 'True'. + + 'optional' -- if true, the feature's inclusion can be controlled from the + command line, using the '--with-X' or '--without-X' options. If + false, the feature's inclusion status is determined automatically, + based on 'availabile', 'standard', and whether any other feature + requires it. The default setting is 'True'. + + 'require_features' -- a string or sequence of strings naming features + that should also be included if this feature is included. Defaults to + empty list. May also contain 'Require' objects that should be + added/removed from the distribution. + + 'remove' -- a string or list of strings naming packages to be removed + from the distribution if this feature is *not* included. If the + feature *is* included, this argument is ignored. This argument exists + to support removing features that "crosscut" a distribution, such as + defining a 'tests' feature that removes all the 'tests' subpackages + provided by other features. The default for this argument is an empty + list. (Note: the named package(s) or modules must exist in the base + distribution when the 'setup()' function is initially called.) + + other keywords -- any other keyword arguments are saved, and passed to + the distribution's 'include()' and 'exclude()' methods when the + feature is included or excluded, respectively. So, for example, you + could pass 'packages=["a","b"]' to cause packages 'a' and 'b' to be + added or removed from the distribution as appropriate. + + A feature must include at least one 'requires', 'remove', or other + keyword argument. Otherwise, it can't affect the distribution in any way. + Note also that you can subclass 'Feature' to create your own specialized + feature types that modify the distribution in other ways when included or + excluded. See the docstrings for the various methods here for more detail. + Aside from the methods, the only feature attributes that distributions look + at are 'description' and 'optional'. + """ + + @staticmethod + def warn_deprecated(): + msg = ( + "Features are deprecated and will be removed in a future " + "version. See https://github.com/pypa/setuptools/issues/65." + ) + warnings.warn(msg, DistDeprecationWarning, stacklevel=3) + + def __init__( + self, description, standard=False, available=True, + optional=True, require_features=(), remove=(), **extras): + self.warn_deprecated() + + self.description = description + self.standard = standard + self.available = available + self.optional = optional + if isinstance(require_features, (str, Require)): + require_features = require_features, + + self.require_features = [ + r for r in require_features if isinstance(r, str) + ] + er = [r for r in require_features if not isinstance(r, str)] + if er: + extras['require_features'] = er + + if isinstance(remove, str): + remove = remove, + self.remove = remove + self.extras = extras + + if not remove and not require_features and not extras: + raise DistutilsSetupError( + "Feature %s: must define 'require_features', 'remove', or " + "at least one of 'packages', 'py_modules', etc." + ) + + def include_by_default(self): + """Should this feature be included by default?""" + return self.available and self.standard + + def include_in(self, dist): + """Ensure feature and its requirements are included in distribution + + You may override this in a subclass to perform additional operations on + the distribution. Note that this method may be called more than once + per feature, and so should be idempotent. + + """ + + if not self.available: + raise DistutilsPlatformError( + self.description + " is required, " + "but is not available on this platform" + ) + + dist.include(**self.extras) + + for f in self.require_features: + dist.include_feature(f) + + def exclude_from(self, dist): + """Ensure feature is excluded from distribution + + You may override this in a subclass to perform additional operations on + the distribution. This method will be called at most once per + feature, and only after all included features have been asked to + include themselves. + """ + + dist.exclude(**self.extras) + + if self.remove: + for item in self.remove: + dist.exclude_package(item) + + def validate(self, dist): + """Verify that feature makes sense in context of distribution + + This method is called by the distribution just before it parses its + command line. It checks to ensure that the 'remove' attribute, if any, + contains only valid package/module names that are present in the base + distribution when 'setup()' is called. You may override it in a + subclass to perform any other required validation of the feature + against a target distribution. + """ + + for item in self.remove: + if not dist.has_contents_for(item): + raise DistutilsSetupError( + "%s wants to be able to remove %s, but the distribution" + " doesn't contain any packages or modules under %s" + % (self.description, item, item) + ) + + +class DistDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in dist in setuptools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/venv/lib/python3.7/site-packages/setuptools/extension.py b/venv/lib/python3.7/site-packages/setuptools/extension.py new file mode 100644 index 0000000..2946889 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/extension.py @@ -0,0 +1,57 @@ +import re +import functools +import distutils.core +import distutils.errors +import distutils.extension + +from setuptools.extern.six.moves import map + +from .monkey import get_unpatched + + +def _have_cython(): + """ + Return True if Cython can be imported. + """ + cython_impl = 'Cython.Distutils.build_ext' + try: + # from (cython_impl) import build_ext + __import__(cython_impl, fromlist=['build_ext']).build_ext + return True + except Exception: + pass + return False + + +# for compatibility +have_pyrex = _have_cython + +_Extension = get_unpatched(distutils.core.Extension) + + +class Extension(_Extension): + """Extension that uses '.c' files in place of '.pyx' files""" + + def __init__(self, name, sources, *args, **kw): + # The *args is needed for compatibility as calls may use positional + # arguments. py_limited_api may be set only via keyword. + self.py_limited_api = kw.pop("py_limited_api", False) + _Extension.__init__(self, name, sources, *args, **kw) + + def _convert_pyx_sources_to_lang(self): + """ + Replace sources with .pyx extensions to sources with the target + language extension. This mechanism allows language authors to supply + pre-converted sources but to prefer the .pyx sources. + """ + if _have_cython(): + # the build has Cython, so allow it to compile the .pyx files + return + lang = self.language or '' + target_ext = '.cpp' if lang.lower() == 'c++' else '.c' + sub = functools.partial(re.sub, '.pyx$', target_ext) + self.sources = list(map(sub, self.sources)) + + +class Library(Extension): + """Just like a regular Extension, but built as a library instead""" diff --git a/venv/lib/python3.7/site-packages/setuptools/extern/__init__.py b/venv/lib/python3.7/site-packages/setuptools/extern/__init__.py new file mode 100644 index 0000000..cb2fa32 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/extern/__init__.py @@ -0,0 +1,73 @@ +import sys + + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from root_name. + """ + + def __init__(self, root_name, vendored_names=(), vendor_pkg=None): + self.root_name = root_name + self.vendored_names = set(vendored_names) + self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') + + @property + def search_path(self): + """ + Search first the vendor package then as a natural package. + """ + yield self.vendor_pkg + '.' + yield '' + + def find_module(self, fullname, path=None): + """ + Return self when fullname starts with root_name and the + target module is one vendored through this importer. + """ + root, base, target = fullname.partition(self.root_name + '.') + if root: + return + if not any(map(target.startswith, self.vendored_names)): + return + return self + + def load_module(self, fullname): + """ + Iterate over the search path to locate and load fullname. + """ + root, base, target = fullname.partition(self.root_name + '.') + for prefix in self.search_path: + try: + extant = prefix + target + __import__(extant) + mod = sys.modules[extant] + sys.modules[fullname] = mod + # mysterious hack: + # Remove the reference to the extant package/module + # on later Python versions to cause relative imports + # in the vendor package to resolve the same modules + # as those going through this importer. + if sys.version_info >= (3, ): + del sys.modules[extant] + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + def install(self): + """ + Install this importer into sys.meta_path if not already present. + """ + if self not in sys.meta_path: + sys.meta_path.append(self) + + +names = 'six', 'packaging', 'pyparsing', +VendorImporter(__name__, names, 'setuptools._vendor').install() diff --git a/venv/lib/python3.7/site-packages/setuptools/glibc.py b/venv/lib/python3.7/site-packages/setuptools/glibc.py new file mode 100644 index 0000000..a134591 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/glibc.py @@ -0,0 +1,86 @@ +# This file originally from pip: +# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py +from __future__ import absolute_import + +import ctypes +import re +import warnings + + +def glibc_version_string(): + "Returns glibc version string, or None if not using glibc." + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# Separated out from have_compatible_glibc for easier unit testing +def check_glibc_version(version_str, required_major, minimum_minor): + # Parse string and check against requested version. + # + # We use a regexp instead of str.split because we want to discard any + # random junk that might come after the minor version -- this might happen + # in patched/forked versions of glibc (e.g. Linaro's version of glibc + # uses version strings like "2.20-2014.11"). See gh-3588. + m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str) + if not m: + warnings.warn("Expected glibc version with 2 components major.minor," + " got: %s" % version_str, RuntimeWarning) + return False + return (int(m.group("major")) == required_major and + int(m.group("minor")) >= minimum_minor) + + +def have_compatible_glibc(required_major, minimum_minor): + version_str = glibc_version_string() + if version_str is None: + return False + return check_glibc_version(version_str, required_major, minimum_minor) + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver(): + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/venv/lib/python3.7/site-packages/setuptools/glob.py b/venv/lib/python3.7/site-packages/setuptools/glob.py new file mode 100644 index 0000000..9d7cbc5 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/glob.py @@ -0,0 +1,174 @@ +""" +Filename globbing utility. Mostly a copy of `glob` from Python 3.5. + +Changes include: + * `yield from` and PEP3102 `*` removed. + * Hidden files are not ignored. +""" + +import os +import re +import fnmatch + +__all__ = ["glob", "iglob", "escape"] + + +def glob(pathname, recursive=False): + """Return a list of paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + If recursive is true, the pattern '**' will match any files and + zero or more directories and subdirectories. + """ + return list(iglob(pathname, recursive=recursive)) + + +def iglob(pathname, recursive=False): + """Return an iterator which yields the paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + If recursive is true, the pattern '**' will match any files and + zero or more directories and subdirectories. + """ + it = _iglob(pathname, recursive) + if recursive and _isrecursive(pathname): + s = next(it) # skip empty string + assert not s + return it + + +def _iglob(pathname, recursive): + dirname, basename = os.path.split(pathname) + if not has_magic(pathname): + if basename: + if os.path.lexists(pathname): + yield pathname + else: + # Patterns ending with a slash should match only directories + if os.path.isdir(dirname): + yield pathname + return + if not dirname: + if recursive and _isrecursive(basename): + for x in glob2(dirname, basename): + yield x + else: + for x in glob1(dirname, basename): + yield x + return + # `os.path.split()` returns the argument itself as a dirname if it is a + # drive or UNC path. Prevent an infinite recursion if a drive or UNC path + # contains magic characters (i.e. r'\\?\C:'). + if dirname != pathname and has_magic(dirname): + dirs = _iglob(dirname, recursive) + else: + dirs = [dirname] + if has_magic(basename): + if recursive and _isrecursive(basename): + glob_in_dir = glob2 + else: + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) + + +# These 2 helper functions non-recursively glob inside a literal directory. +# They return a list of basenames. `glob1` accepts a pattern while `glob0` +# takes a literal basename (so it only has to check for its existence). + + +def glob1(dirname, pattern): + if not dirname: + if isinstance(pattern, bytes): + dirname = os.curdir.encode('ASCII') + else: + dirname = os.curdir + try: + names = os.listdir(dirname) + except OSError: + return [] + return fnmatch.filter(names, pattern) + + +def glob0(dirname, basename): + if not basename: + # `os.path.split()` returns an empty basename for paths ending with a + # directory separator. 'q*x/' should match only directories. + if os.path.isdir(dirname): + return [basename] + else: + if os.path.lexists(os.path.join(dirname, basename)): + return [basename] + return [] + + +# This helper function recursively yields relative pathnames inside a literal +# directory. + + +def glob2(dirname, pattern): + assert _isrecursive(pattern) + yield pattern[:0] + for x in _rlistdir(dirname): + yield x + + +# Recursively yields relative pathnames inside a literal directory. +def _rlistdir(dirname): + if not dirname: + if isinstance(dirname, bytes): + dirname = os.curdir.encode('ASCII') + else: + dirname = os.curdir + try: + names = os.listdir(dirname) + except os.error: + return + for x in names: + yield x + path = os.path.join(dirname, x) if dirname else x + for y in _rlistdir(path): + yield os.path.join(x, y) + + +magic_check = re.compile('([*?[])') +magic_check_bytes = re.compile(b'([*?[])') + + +def has_magic(s): + if isinstance(s, bytes): + match = magic_check_bytes.search(s) + else: + match = magic_check.search(s) + return match is not None + + +def _isrecursive(pattern): + if isinstance(pattern, bytes): + return pattern == b'**' + else: + return pattern == '**' + + +def escape(pathname): + """Escape all special characters. + """ + # Escaping is done by wrapping any of "*?[" between square brackets. + # Metacharacters do not work in the drive part and shouldn't be escaped. + drive, pathname = os.path.splitdrive(pathname) + if isinstance(pathname, bytes): + pathname = magic_check_bytes.sub(br'[\1]', pathname) + else: + pathname = magic_check.sub(r'[\1]', pathname) + return drive + pathname diff --git a/venv/lib/python3.7/site-packages/setuptools/gui-32.exe b/venv/lib/python3.7/site-packages/setuptools/gui-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..f8d3509653ba8f80ca7f3aa7f95616142ba83a94 GIT binary patch literal 65536 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/setuptools/gui-64.exe b/venv/lib/python3.7/site-packages/setuptools/gui-64.exe new file mode 100644 index 0000000000000000000000000000000000000000..330c51a5dde15a0bb610a48cd0ca11770c914dae GIT binary patch literal 75264 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/setuptools/gui.exe b/venv/lib/python3.7/site-packages/setuptools/gui.exe new file mode 100644 index 0000000000000000000000000000000000000000..f8d3509653ba8f80ca7f3aa7f95616142ba83a94 GIT binary patch literal 65536 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/setuptools/launch.py b/venv/lib/python3.7/site-packages/setuptools/launch.py new file mode 100644 index 0000000..308283e --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/launch.py @@ -0,0 +1,35 @@ +""" +Launch the Python script on the command line after +setuptools is bootstrapped via import. +""" + +# Note that setuptools gets imported implicitly by the +# invocation of this script using python -m setuptools.launch + +import tokenize +import sys + + +def run(): + """ + Run the script in sys.argv[1] as if it had + been invoked naturally. + """ + __builtins__ + script_name = sys.argv[1] + namespace = dict( + __file__=script_name, + __name__='__main__', + __doc__=None, + ) + sys.argv[:] = sys.argv[1:] + + open_ = getattr(tokenize, 'open', open) + script = open_(script_name).read() + norm_script = script.replace('\\r\\n', '\\n') + code = compile(norm_script, script_name, 'exec') + exec(code, namespace) + + +if __name__ == '__main__': + run() diff --git a/venv/lib/python3.7/site-packages/setuptools/lib2to3_ex.py b/venv/lib/python3.7/site-packages/setuptools/lib2to3_ex.py new file mode 100644 index 0000000..4b1a73f --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/lib2to3_ex.py @@ -0,0 +1,62 @@ +""" +Customized Mixin2to3 support: + + - adds support for converting doctests + + +This module raises an ImportError on Python 2. +""" + +from distutils.util import Mixin2to3 as _Mixin2to3 +from distutils import log +from lib2to3.refactor import RefactoringTool, get_fixers_from_package + +import setuptools + + +class DistutilsRefactoringTool(RefactoringTool): + def log_error(self, msg, *args, **kw): + log.error(msg, *args) + + def log_message(self, msg, *args): + log.info(msg, *args) + + def log_debug(self, msg, *args): + log.debug(msg, *args) + + +class Mixin2to3(_Mixin2to3): + def run_2to3(self, files, doctests=False): + # See of the distribution option has been set, otherwise check the + # setuptools default. + if self.distribution.use_2to3 is not True: + return + if not files: + return + log.info("Fixing " + " ".join(files)) + self.__build_fixer_names() + self.__exclude_fixers() + if doctests: + if setuptools.run_2to3_on_doctests: + r = DistutilsRefactoringTool(self.fixer_names) + r.refactor(files, write=True, doctests_only=True) + else: + _Mixin2to3.run_2to3(self, files) + + def __build_fixer_names(self): + if self.fixer_names: + return + self.fixer_names = [] + for p in setuptools.lib2to3_fixer_packages: + self.fixer_names.extend(get_fixers_from_package(p)) + if self.distribution.use_2to3_fixers is not None: + for p in self.distribution.use_2to3_fixers: + self.fixer_names.extend(get_fixers_from_package(p)) + + def __exclude_fixers(self): + excluded_fixers = getattr(self, 'exclude_fixers', []) + if self.distribution.use_2to3_exclude_fixers is not None: + excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers) + for fixer_name in excluded_fixers: + if fixer_name in self.fixer_names: + self.fixer_names.remove(fixer_name) diff --git a/venv/lib/python3.7/site-packages/setuptools/monkey.py b/venv/lib/python3.7/site-packages/setuptools/monkey.py new file mode 100644 index 0000000..3c77f8c --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/monkey.py @@ -0,0 +1,179 @@ +""" +Monkey patching of distutils. +""" + +import sys +import distutils.filelist +import platform +import types +import functools +from importlib import import_module +import inspect + +from setuptools.extern import six + +import setuptools + +__all__ = [] +""" +Everything is private. Contact the project team +if you think you need this functionality. +""" + + +def _get_mro(cls): + """ + Returns the bases classes for cls sorted by the MRO. + + Works around an issue on Jython where inspect.getmro will not return all + base classes if multiple classes share the same name. Instead, this + function will return a tuple containing the class itself, and the contents + of cls.__bases__. See https://github.com/pypa/setuptools/issues/1024. + """ + if platform.python_implementation() == "Jython": + return (cls,) + cls.__bases__ + return inspect.getmro(cls) + + +def get_unpatched(item): + lookup = ( + get_unpatched_class if isinstance(item, six.class_types) else + get_unpatched_function if isinstance(item, types.FunctionType) else + lambda item: None + ) + return lookup(item) + + +def get_unpatched_class(cls): + """Protect against re-patching the distutils if reloaded + + Also ensures that no other distutils extension monkeypatched the distutils + first. + """ + external_bases = ( + cls + for cls in _get_mro(cls) + if not cls.__module__.startswith('setuptools') + ) + base = next(external_bases) + if not base.__module__.startswith('distutils'): + msg = "distutils has already been patched by %r" % cls + raise AssertionError(msg) + return base + + +def patch_all(): + # we can't patch distutils.cmd, alas + distutils.core.Command = setuptools.Command + + has_issue_12885 = sys.version_info <= (3, 5, 3) + + if has_issue_12885: + # fix findall bug in distutils (http://bugs.python.org/issue12885) + distutils.filelist.findall = setuptools.findall + + needs_warehouse = ( + sys.version_info < (2, 7, 13) + or + (3, 4) < sys.version_info < (3, 4, 6) + or + (3, 5) < sys.version_info <= (3, 5, 3) + ) + + if needs_warehouse: + warehouse = 'https://upload.pypi.org/legacy/' + distutils.config.PyPIRCCommand.DEFAULT_REPOSITORY = warehouse + + _patch_distribution_metadata() + + # Install Distribution throughout the distutils + for module in distutils.dist, distutils.core, distutils.cmd: + module.Distribution = setuptools.dist.Distribution + + # Install the patched Extension + distutils.core.Extension = setuptools.extension.Extension + distutils.extension.Extension = setuptools.extension.Extension + if 'distutils.command.build_ext' in sys.modules: + sys.modules['distutils.command.build_ext'].Extension = ( + setuptools.extension.Extension + ) + + patch_for_msvc_specialized_compiler() + + +def _patch_distribution_metadata(): + """Patch write_pkg_file and read_pkg_file for higher metadata standards""" + for attr in ('write_pkg_file', 'read_pkg_file', 'get_metadata_version'): + new_val = getattr(setuptools.dist, attr) + setattr(distutils.dist.DistributionMetadata, attr, new_val) + + +def patch_func(replacement, target_mod, func_name): + """ + Patch func_name in target_mod with replacement + + Important - original must be resolved by name to avoid + patching an already patched function. + """ + original = getattr(target_mod, func_name) + + # set the 'unpatched' attribute on the replacement to + # point to the original. + vars(replacement).setdefault('unpatched', original) + + # replace the function in the original module + setattr(target_mod, func_name, replacement) + + +def get_unpatched_function(candidate): + return getattr(candidate, 'unpatched') + + +def patch_for_msvc_specialized_compiler(): + """ + Patch functions in distutils to use standalone Microsoft Visual C++ + compilers. + """ + # import late to avoid circular imports on Python < 3.5 + msvc = import_module('setuptools.msvc') + + if platform.system() != 'Windows': + # Compilers only availables on Microsoft Windows + return + + def patch_params(mod_name, func_name): + """ + Prepare the parameters for patch_func to patch indicated function. + """ + repl_prefix = 'msvc9_' if 'msvc9' in mod_name else 'msvc14_' + repl_name = repl_prefix + func_name.lstrip('_') + repl = getattr(msvc, repl_name) + mod = import_module(mod_name) + if not hasattr(mod, func_name): + raise ImportError(func_name) + return repl, mod, func_name + + # Python 2.7 to 3.4 + msvc9 = functools.partial(patch_params, 'distutils.msvc9compiler') + + # Python 3.5+ + msvc14 = functools.partial(patch_params, 'distutils._msvccompiler') + + try: + # Patch distutils.msvc9compiler + patch_func(*msvc9('find_vcvarsall')) + patch_func(*msvc9('query_vcvarsall')) + except ImportError: + pass + + try: + # Patch distutils._msvccompiler._get_vc_env + patch_func(*msvc14('_get_vc_env')) + except ImportError: + pass + + try: + # Patch distutils._msvccompiler.gen_lib_options for Numpy + patch_func(*msvc14('gen_lib_options')) + except ImportError: + pass diff --git a/venv/lib/python3.7/site-packages/setuptools/msvc.py b/venv/lib/python3.7/site-packages/setuptools/msvc.py new file mode 100644 index 0000000..b9c472f --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/msvc.py @@ -0,0 +1,1301 @@ +""" +Improved support for Microsoft Visual C++ compilers. + +Known supported compilers: +-------------------------- +Microsoft Visual C++ 9.0: + Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) + Microsoft Windows SDK 6.1 (x86, x64, ia64) + Microsoft Windows SDK 7.0 (x86, x64, ia64) + +Microsoft Visual C++ 10.0: + Microsoft Windows SDK 7.1 (x86, x64, ia64) + +Microsoft Visual C++ 14.0: + Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) + Microsoft Visual Studio 2017 (x86, x64, arm, arm64) + Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) +""" + +import os +import sys +import platform +import itertools +import distutils.errors +from setuptools.extern.packaging.version import LegacyVersion + +from setuptools.extern.six.moves import filterfalse + +from .monkey import get_unpatched + +if platform.system() == 'Windows': + from setuptools.extern.six.moves import winreg + safe_env = os.environ +else: + """ + Mock winreg and environ so the module can be imported + on this platform. + """ + + class winreg: + HKEY_USERS = None + HKEY_CURRENT_USER = None + HKEY_LOCAL_MACHINE = None + HKEY_CLASSES_ROOT = None + + safe_env = dict() + +_msvc9_suppress_errors = ( + # msvc9compiler isn't available on some platforms + ImportError, + + # msvc9compiler raises DistutilsPlatformError in some + # environments. See #1118. + distutils.errors.DistutilsPlatformError, +) + +try: + from distutils.msvc9compiler import Reg +except _msvc9_suppress_errors: + pass + + +def msvc9_find_vcvarsall(version): + """ + Patched "distutils.msvc9compiler.find_vcvarsall" to use the standalone + compiler build for Python (VCForPython). Fall back to original behavior + when the standalone compiler is not available. + + Redirect the path of "vcvarsall.bat". + + Known supported compilers + ------------------------- + Microsoft Visual C++ 9.0: + Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) + + Parameters + ---------- + version: float + Required Microsoft Visual C++ version. + + Return + ------ + vcvarsall.bat path: str + """ + VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f' + key = VC_BASE % ('', version) + try: + # Per-user installs register the compiler path here + productdir = Reg.get_value(key, "installdir") + except KeyError: + try: + # All-user installs on a 64-bit system register here + key = VC_BASE % ('Wow6432Node\\', version) + productdir = Reg.get_value(key, "installdir") + except KeyError: + productdir = None + + if productdir: + vcvarsall = os.path.os.path.join(productdir, "vcvarsall.bat") + if os.path.isfile(vcvarsall): + return vcvarsall + + return get_unpatched(msvc9_find_vcvarsall)(version) + + +def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs): + """ + Patched "distutils.msvc9compiler.query_vcvarsall" for support extra + compilers. + + Set environment without use of "vcvarsall.bat". + + Known supported compilers + ------------------------- + Microsoft Visual C++ 9.0: + Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) + Microsoft Windows SDK 6.1 (x86, x64, ia64) + Microsoft Windows SDK 7.0 (x86, x64, ia64) + + Microsoft Visual C++ 10.0: + Microsoft Windows SDK 7.1 (x86, x64, ia64) + + Parameters + ---------- + ver: float + Required Microsoft Visual C++ version. + arch: str + Target architecture. + + Return + ------ + environment: dict + """ + # Try to get environement from vcvarsall.bat (Classical way) + try: + orig = get_unpatched(msvc9_query_vcvarsall) + return orig(ver, arch, *args, **kwargs) + except distutils.errors.DistutilsPlatformError: + # Pass error if Vcvarsall.bat is missing + pass + except ValueError: + # Pass error if environment not set after executing vcvarsall.bat + pass + + # If error, try to set environment directly + try: + return EnvironmentInfo(arch, ver).return_env() + except distutils.errors.DistutilsPlatformError as exc: + _augment_exception(exc, ver, arch) + raise + + +def msvc14_get_vc_env(plat_spec): + """ + Patched "distutils._msvccompiler._get_vc_env" for support extra + compilers. + + Set environment without use of "vcvarsall.bat". + + Known supported compilers + ------------------------- + Microsoft Visual C++ 14.0: + Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) + Microsoft Visual Studio 2017 (x86, x64, arm, arm64) + Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) + + Parameters + ---------- + plat_spec: str + Target architecture. + + Return + ------ + environment: dict + """ + # Try to get environment from vcvarsall.bat (Classical way) + try: + return get_unpatched(msvc14_get_vc_env)(plat_spec) + except distutils.errors.DistutilsPlatformError: + # Pass error Vcvarsall.bat is missing + pass + + # If error, try to set environment directly + try: + return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env() + except distutils.errors.DistutilsPlatformError as exc: + _augment_exception(exc, 14.0) + raise + + +def msvc14_gen_lib_options(*args, **kwargs): + """ + Patched "distutils._msvccompiler.gen_lib_options" for fix + compatibility between "numpy.distutils" and "distutils._msvccompiler" + (for Numpy < 1.11.2) + """ + if "numpy.distutils" in sys.modules: + import numpy as np + if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'): + return np.distutils.ccompiler.gen_lib_options(*args, **kwargs) + return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs) + + +def _augment_exception(exc, version, arch=''): + """ + Add details to the exception message to help guide the user + as to what action will resolve it. + """ + # Error if MSVC++ directory not found or environment not set + message = exc.args[0] + + if "vcvarsall" in message.lower() or "visual c" in message.lower(): + # Special error message if MSVC++ not installed + tmpl = 'Microsoft Visual C++ {version:0.1f} is required.' + message = tmpl.format(**locals()) + msdownload = 'www.microsoft.com/download/details.aspx?id=%d' + if version == 9.0: + if arch.lower().find('ia64') > -1: + # For VC++ 9.0, if IA64 support is needed, redirect user + # to Windows SDK 7.0 + message += ' Get it with "Microsoft Windows SDK 7.0": ' + message += msdownload % 3138 + else: + # For VC++ 9.0 redirect user to Vc++ for Python 2.7 : + # This redirection link is maintained by Microsoft. + # Contact vspython@microsoft.com if it needs updating. + message += ' Get it from http://aka.ms/vcpython27' + elif version == 10.0: + # For VC++ 10.0 Redirect user to Windows SDK 7.1 + message += ' Get it with "Microsoft Windows SDK 7.1": ' + message += msdownload % 8279 + elif version >= 14.0: + # For VC++ 14.0 Redirect user to Visual C++ Build Tools + message += (' Get it with "Microsoft Visual C++ Build Tools": ' + r'https://visualstudio.microsoft.com/downloads/') + + exc.args = (message, ) + + +class PlatformInfo: + """ + Current and Target Architectures informations. + + Parameters + ---------- + arch: str + Target architecture. + """ + current_cpu = safe_env.get('processor_architecture', '').lower() + + def __init__(self, arch): + self.arch = arch.lower().replace('x64', 'amd64') + + @property + def target_cpu(self): + return self.arch[self.arch.find('_') + 1:] + + def target_is_x86(self): + return self.target_cpu == 'x86' + + def current_is_x86(self): + return self.current_cpu == 'x86' + + def current_dir(self, hidex86=False, x64=False): + """ + Current platform specific subfolder. + + Parameters + ---------- + hidex86: bool + return '' and not '\x86' if architecture is x86. + x64: bool + return '\x64' and not '\amd64' if architecture is amd64. + + Return + ------ + subfolder: str + '\target', or '' (see hidex86 parameter) + """ + return ( + '' if (self.current_cpu == 'x86' and hidex86) else + r'\x64' if (self.current_cpu == 'amd64' and x64) else + r'\%s' % self.current_cpu + ) + + def target_dir(self, hidex86=False, x64=False): + r""" + Target platform specific subfolder. + + Parameters + ---------- + hidex86: bool + return '' and not '\x86' if architecture is x86. + x64: bool + return '\x64' and not '\amd64' if architecture is amd64. + + Return + ------ + subfolder: str + '\current', or '' (see hidex86 parameter) + """ + return ( + '' if (self.target_cpu == 'x86' and hidex86) else + r'\x64' if (self.target_cpu == 'amd64' and x64) else + r'\%s' % self.target_cpu + ) + + def cross_dir(self, forcex86=False): + r""" + Cross platform specific subfolder. + + Parameters + ---------- + forcex86: bool + Use 'x86' as current architecture even if current acritecture is + not x86. + + Return + ------ + subfolder: str + '' if target architecture is current architecture, + '\current_target' if not. + """ + current = 'x86' if forcex86 else self.current_cpu + return ( + '' if self.target_cpu == current else + self.target_dir().replace('\\', '\\%s_' % current) + ) + + +class RegistryInfo: + """ + Microsoft Visual Studio related registry informations. + + Parameters + ---------- + platform_info: PlatformInfo + "PlatformInfo" instance. + """ + HKEYS = (winreg.HKEY_USERS, + winreg.HKEY_CURRENT_USER, + winreg.HKEY_LOCAL_MACHINE, + winreg.HKEY_CLASSES_ROOT) + + def __init__(self, platform_info): + self.pi = platform_info + + @property + def visualstudio(self): + """ + Microsoft Visual Studio root registry key. + """ + return 'VisualStudio' + + @property + def sxs(self): + """ + Microsoft Visual Studio SxS registry key. + """ + return os.path.join(self.visualstudio, 'SxS') + + @property + def vc(self): + """ + Microsoft Visual C++ VC7 registry key. + """ + return os.path.join(self.sxs, 'VC7') + + @property + def vs(self): + """ + Microsoft Visual Studio VS7 registry key. + """ + return os.path.join(self.sxs, 'VS7') + + @property + def vc_for_python(self): + """ + Microsoft Visual C++ for Python registry key. + """ + return r'DevDiv\VCForPython' + + @property + def microsoft_sdk(self): + """ + Microsoft SDK registry key. + """ + return 'Microsoft SDKs' + + @property + def windows_sdk(self): + """ + Microsoft Windows/Platform SDK registry key. + """ + return os.path.join(self.microsoft_sdk, 'Windows') + + @property + def netfx_sdk(self): + """ + Microsoft .NET Framework SDK registry key. + """ + return os.path.join(self.microsoft_sdk, 'NETFXSDK') + + @property + def windows_kits_roots(self): + """ + Microsoft Windows Kits Roots registry key. + """ + return r'Windows Kits\Installed Roots' + + def microsoft(self, key, x86=False): + """ + Return key in Microsoft software registry. + + Parameters + ---------- + key: str + Registry key path where look. + x86: str + Force x86 software registry. + + Return + ------ + str: value + """ + node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node' + return os.path.join('Software', node64, 'Microsoft', key) + + def lookup(self, key, name): + """ + Look for values in registry in Microsoft software registry. + + Parameters + ---------- + key: str + Registry key path where look. + name: str + Value name to find. + + Return + ------ + str: value + """ + KEY_READ = winreg.KEY_READ + openkey = winreg.OpenKey + ms = self.microsoft + for hkey in self.HKEYS: + try: + bkey = openkey(hkey, ms(key), 0, KEY_READ) + except (OSError, IOError): + if not self.pi.current_is_x86(): + try: + bkey = openkey(hkey, ms(key, True), 0, KEY_READ) + except (OSError, IOError): + continue + else: + continue + try: + return winreg.QueryValueEx(bkey, name)[0] + except (OSError, IOError): + pass + + +class SystemInfo: + """ + Microsoft Windows and Visual Studio related system inormations. + + Parameters + ---------- + registry_info: RegistryInfo + "RegistryInfo" instance. + vc_ver: float + Required Microsoft Visual C++ version. + """ + + # Variables and properties in this class use originals CamelCase variables + # names from Microsoft source files for more easy comparaison. + WinDir = safe_env.get('WinDir', '') + ProgramFiles = safe_env.get('ProgramFiles', '') + ProgramFilesx86 = safe_env.get('ProgramFiles(x86)', ProgramFiles) + + def __init__(self, registry_info, vc_ver=None): + self.ri = registry_info + self.pi = self.ri.pi + self.vc_ver = vc_ver or self._find_latest_available_vc_ver() + + def _find_latest_available_vc_ver(self): + try: + return self.find_available_vc_vers()[-1] + except IndexError: + err = 'No Microsoft Visual C++ version found' + raise distutils.errors.DistutilsPlatformError(err) + + def find_available_vc_vers(self): + """ + Find all available Microsoft Visual C++ versions. + """ + ms = self.ri.microsoft + vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs) + vc_vers = [] + for hkey in self.ri.HKEYS: + for key in vckeys: + try: + bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ) + except (OSError, IOError): + continue + subkeys, values, _ = winreg.QueryInfoKey(bkey) + for i in range(values): + try: + ver = float(winreg.EnumValue(bkey, i)[0]) + if ver not in vc_vers: + vc_vers.append(ver) + except ValueError: + pass + for i in range(subkeys): + try: + ver = float(winreg.EnumKey(bkey, i)) + if ver not in vc_vers: + vc_vers.append(ver) + except ValueError: + pass + return sorted(vc_vers) + + @property + def VSInstallDir(self): + """ + Microsoft Visual Studio directory. + """ + # Default path + name = 'Microsoft Visual Studio %0.1f' % self.vc_ver + default = os.path.join(self.ProgramFilesx86, name) + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vs, '%0.1f' % self.vc_ver) or default + + @property + def VCInstallDir(self): + """ + Microsoft Visual C++ directory. + """ + self.VSInstallDir + + guess_vc = self._guess_vc() or self._guess_vc_legacy() + + # Try to get "VC++ for Python" path from registry as default path + reg_path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) + python_vc = self.ri.lookup(reg_path, 'installdir') + default_vc = os.path.join(python_vc, 'VC') if python_vc else guess_vc + + # Try to get path from registry, if fail use default path + path = self.ri.lookup(self.ri.vc, '%0.1f' % self.vc_ver) or default_vc + + if not os.path.isdir(path): + msg = 'Microsoft Visual C++ directory not found' + raise distutils.errors.DistutilsPlatformError(msg) + + return path + + def _guess_vc(self): + """ + Locate Visual C for 2017 + """ + if self.vc_ver <= 14.0: + return + + default = r'VC\Tools\MSVC' + guess_vc = os.path.join(self.VSInstallDir, default) + # Subdir with VC exact version as name + try: + vc_exact_ver = os.listdir(guess_vc)[-1] + return os.path.join(guess_vc, vc_exact_ver) + except (OSError, IOError, IndexError): + pass + + def _guess_vc_legacy(self): + """ + Locate Visual C for versions prior to 2017 + """ + default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver + return os.path.join(self.ProgramFilesx86, default) + + @property + def WindowsSdkVersion(self): + """ + Microsoft Windows SDK versions for specified MSVC++ version. + """ + if self.vc_ver <= 9.0: + return ('7.0', '6.1', '6.0a') + elif self.vc_ver == 10.0: + return ('7.1', '7.0a') + elif self.vc_ver == 11.0: + return ('8.0', '8.0a') + elif self.vc_ver == 12.0: + return ('8.1', '8.1a') + elif self.vc_ver >= 14.0: + return ('10.0', '8.1') + + @property + def WindowsSdkLastVersion(self): + """ + Microsoft Windows SDK last version + """ + return self._use_last_dir_name(os.path.join( + self.WindowsSdkDir, 'lib')) + + @property + def WindowsSdkDir(self): + """ + Microsoft Windows SDK directory. + """ + sdkdir = '' + for ver in self.WindowsSdkVersion: + # Try to get it from registry + loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver) + sdkdir = self.ri.lookup(loc, 'installationfolder') + if sdkdir: + break + if not sdkdir or not os.path.isdir(sdkdir): + # Try to get "VC++ for Python" version from registry + path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) + install_base = self.ri.lookup(path, 'installdir') + if install_base: + sdkdir = os.path.join(install_base, 'WinSDK') + if not sdkdir or not os.path.isdir(sdkdir): + # If fail, use default new path + for ver in self.WindowsSdkVersion: + intver = ver[:ver.rfind('.')] + path = r'Microsoft SDKs\Windows Kits\%s' % (intver) + d = os.path.join(self.ProgramFiles, path) + if os.path.isdir(d): + sdkdir = d + if not sdkdir or not os.path.isdir(sdkdir): + # If fail, use default old path + for ver in self.WindowsSdkVersion: + path = r'Microsoft SDKs\Windows\v%s' % ver + d = os.path.join(self.ProgramFiles, path) + if os.path.isdir(d): + sdkdir = d + if not sdkdir: + # If fail, use Platform SDK + sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK') + return sdkdir + + @property + def WindowsSDKExecutablePath(self): + """ + Microsoft Windows SDK executable directory. + """ + # Find WinSDK NetFx Tools registry dir name + if self.vc_ver <= 11.0: + netfxver = 35 + arch = '' + else: + netfxver = 40 + hidex86 = True if self.vc_ver <= 12.0 else False + arch = self.pi.current_dir(x64=True, hidex86=hidex86) + fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-')) + + # liste all possibles registry paths + regpaths = [] + if self.vc_ver >= 14.0: + for ver in self.NetFxSdkVersion: + regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)] + + for ver in self.WindowsSdkVersion: + regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)] + + # Return installation folder from the more recent path + for path in regpaths: + execpath = self.ri.lookup(path, 'installationfolder') + if execpath: + break + return execpath + + @property + def FSharpInstallDir(self): + """ + Microsoft Visual F# directory. + """ + path = r'%0.1f\Setup\F#' % self.vc_ver + path = os.path.join(self.ri.visualstudio, path) + return self.ri.lookup(path, 'productdir') or '' + + @property + def UniversalCRTSdkDir(self): + """ + Microsoft Universal CRT SDK directory. + """ + # Set Kit Roots versions for specified MSVC++ version + if self.vc_ver >= 14.0: + vers = ('10', '81') + else: + vers = () + + # Find path of the more recent Kit + for ver in vers: + sdkdir = self.ri.lookup(self.ri.windows_kits_roots, + 'kitsroot%s' % ver) + if sdkdir: + break + return sdkdir or '' + + @property + def UniversalCRTSdkLastVersion(self): + """ + Microsoft Universal C Runtime SDK last version + """ + return self._use_last_dir_name(os.path.join( + self.UniversalCRTSdkDir, 'lib')) + + @property + def NetFxSdkVersion(self): + """ + Microsoft .NET Framework SDK versions. + """ + # Set FxSdk versions for specified MSVC++ version + if self.vc_ver >= 14.0: + return ('4.6.1', '4.6') + else: + return () + + @property + def NetFxSdkDir(self): + """ + Microsoft .NET Framework SDK directory. + """ + for ver in self.NetFxSdkVersion: + loc = os.path.join(self.ri.netfx_sdk, ver) + sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder') + if sdkdir: + break + return sdkdir or '' + + @property + def FrameworkDir32(self): + """ + Microsoft .NET Framework 32bit directory. + """ + # Default path + guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework') + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw + + @property + def FrameworkDir64(self): + """ + Microsoft .NET Framework 64bit directory. + """ + # Default path + guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64') + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw + + @property + def FrameworkVersion32(self): + """ + Microsoft .NET Framework 32bit versions. + """ + return self._find_dot_net_versions(32) + + @property + def FrameworkVersion64(self): + """ + Microsoft .NET Framework 64bit versions. + """ + return self._find_dot_net_versions(64) + + def _find_dot_net_versions(self, bits): + """ + Find Microsoft .NET Framework versions. + + Parameters + ---------- + bits: int + Platform number of bits: 32 or 64. + """ + # Find actual .NET version in registry + reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) + dot_net_dir = getattr(self, 'FrameworkDir%d' % bits) + ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or '' + + # Set .NET versions for specified MSVC++ version + if self.vc_ver >= 12.0: + frameworkver = (ver, 'v4.0') + elif self.vc_ver >= 10.0: + frameworkver = ('v4.0.30319' if ver.lower()[:2] != 'v4' else ver, + 'v3.5') + elif self.vc_ver == 9.0: + frameworkver = ('v3.5', 'v2.0.50727') + if self.vc_ver == 8.0: + frameworkver = ('v3.0', 'v2.0.50727') + return frameworkver + + def _use_last_dir_name(self, path, prefix=''): + """ + Return name of the last dir in path or '' if no dir found. + + Parameters + ---------- + path: str + Use dirs in this path + prefix: str + Use only dirs startings by this prefix + """ + matching_dirs = ( + dir_name + for dir_name in reversed(os.listdir(path)) + if os.path.isdir(os.path.join(path, dir_name)) and + dir_name.startswith(prefix) + ) + return next(matching_dirs, None) or '' + + +class EnvironmentInfo: + """ + Return environment variables for specified Microsoft Visual C++ version + and platform : Lib, Include, Path and libpath. + + This function is compatible with Microsoft Visual C++ 9.0 to 14.0. + + Script created by analysing Microsoft environment configuration files like + "vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ... + + Parameters + ---------- + arch: str + Target architecture. + vc_ver: float + Required Microsoft Visual C++ version. If not set, autodetect the last + version. + vc_min_ver: float + Minimum Microsoft Visual C++ version. + """ + + # Variables and properties in this class use originals CamelCase variables + # names from Microsoft source files for more easy comparaison. + + def __init__(self, arch, vc_ver=None, vc_min_ver=0): + self.pi = PlatformInfo(arch) + self.ri = RegistryInfo(self.pi) + self.si = SystemInfo(self.ri, vc_ver) + + if self.vc_ver < vc_min_ver: + err = 'No suitable Microsoft Visual C++ version found' + raise distutils.errors.DistutilsPlatformError(err) + + @property + def vc_ver(self): + """ + Microsoft Visual C++ version. + """ + return self.si.vc_ver + + @property + def VSTools(self): + """ + Microsoft Visual Studio Tools + """ + paths = [r'Common7\IDE', r'Common7\Tools'] + + if self.vc_ver >= 14.0: + arch_subdir = self.pi.current_dir(hidex86=True, x64=True) + paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow'] + paths += [r'Team Tools\Performance Tools'] + paths += [r'Team Tools\Performance Tools%s' % arch_subdir] + + return [os.path.join(self.si.VSInstallDir, path) for path in paths] + + @property + def VCIncludes(self): + """ + Microsoft Visual C++ & Microsoft Foundation Class Includes + """ + return [os.path.join(self.si.VCInstallDir, 'Include'), + os.path.join(self.si.VCInstallDir, r'ATLMFC\Include')] + + @property + def VCLibraries(self): + """ + Microsoft Visual C++ & Microsoft Foundation Class Libraries + """ + if self.vc_ver >= 15.0: + arch_subdir = self.pi.target_dir(x64=True) + else: + arch_subdir = self.pi.target_dir(hidex86=True) + paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir] + + if self.vc_ver >= 14.0: + paths += [r'Lib\store%s' % arch_subdir] + + return [os.path.join(self.si.VCInstallDir, path) for path in paths] + + @property + def VCStoreRefs(self): + """ + Microsoft Visual C++ store references Libraries + """ + if self.vc_ver < 14.0: + return [] + return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')] + + @property + def VCTools(self): + """ + Microsoft Visual C++ Tools + """ + si = self.si + tools = [os.path.join(si.VCInstallDir, 'VCPackages')] + + forcex86 = True if self.vc_ver <= 10.0 else False + arch_subdir = self.pi.cross_dir(forcex86) + if arch_subdir: + tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)] + + if self.vc_ver == 14.0: + path = 'Bin%s' % self.pi.current_dir(hidex86=True) + tools += [os.path.join(si.VCInstallDir, path)] + + elif self.vc_ver >= 15.0: + host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else + r'bin\HostX64%s') + tools += [os.path.join( + si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))] + + if self.pi.current_cpu != self.pi.target_cpu: + tools += [os.path.join( + si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))] + + else: + tools += [os.path.join(si.VCInstallDir, 'Bin')] + + return tools + + @property + def OSLibraries(self): + """ + Microsoft Windows SDK Libraries + """ + if self.vc_ver <= 10.0: + arch_subdir = self.pi.target_dir(hidex86=True, x64=True) + return [os.path.join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)] + + else: + arch_subdir = self.pi.target_dir(x64=True) + lib = os.path.join(self.si.WindowsSdkDir, 'lib') + libver = self._sdk_subdir + return [os.path.join(lib, '%sum%s' % (libver , arch_subdir))] + + @property + def OSIncludes(self): + """ + Microsoft Windows SDK Include + """ + include = os.path.join(self.si.WindowsSdkDir, 'include') + + if self.vc_ver <= 10.0: + return [include, os.path.join(include, 'gl')] + + else: + if self.vc_ver >= 14.0: + sdkver = self._sdk_subdir + else: + sdkver = '' + return [os.path.join(include, '%sshared' % sdkver), + os.path.join(include, '%sum' % sdkver), + os.path.join(include, '%swinrt' % sdkver)] + + @property + def OSLibpath(self): + """ + Microsoft Windows SDK Libraries Paths + """ + ref = os.path.join(self.si.WindowsSdkDir, 'References') + libpath = [] + + if self.vc_ver <= 9.0: + libpath += self.OSLibraries + + if self.vc_ver >= 11.0: + libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')] + + if self.vc_ver >= 14.0: + libpath += [ + ref, + os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'), + os.path.join( + ref, + 'Windows.Foundation.UniversalApiContract', + '1.0.0.0', + ), + os.path.join( + ref, + 'Windows.Foundation.FoundationContract', + '1.0.0.0', + ), + os.path.join( + ref, + 'Windows.Networking.Connectivity.WwanContract', + '1.0.0.0', + ), + os.path.join( + self.si.WindowsSdkDir, + 'ExtensionSDKs', + 'Microsoft.VCLibs', + '%0.1f' % self.vc_ver, + 'References', + 'CommonConfiguration', + 'neutral', + ), + ] + return libpath + + @property + def SdkTools(self): + """ + Microsoft Windows SDK Tools + """ + return list(self._sdk_tools()) + + def _sdk_tools(self): + """ + Microsoft Windows SDK Tools paths generator + """ + if self.vc_ver < 15.0: + bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86' + yield os.path.join(self.si.WindowsSdkDir, bin_dir) + + if not self.pi.current_is_x86(): + arch_subdir = self.pi.current_dir(x64=True) + path = 'Bin%s' % arch_subdir + yield os.path.join(self.si.WindowsSdkDir, path) + + if self.vc_ver == 10.0 or self.vc_ver == 11.0: + if self.pi.target_is_x86(): + arch_subdir = '' + else: + arch_subdir = self.pi.current_dir(hidex86=True, x64=True) + path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir + yield os.path.join(self.si.WindowsSdkDir, path) + + elif self.vc_ver >= 15.0: + path = os.path.join(self.si.WindowsSdkDir, 'Bin') + arch_subdir = self.pi.current_dir(x64=True) + sdkver = self.si.WindowsSdkLastVersion + yield os.path.join(path, '%s%s' % (sdkver, arch_subdir)) + + if self.si.WindowsSDKExecutablePath: + yield self.si.WindowsSDKExecutablePath + + @property + def _sdk_subdir(self): + """ + Microsoft Windows SDK version subdir + """ + ucrtver = self.si.WindowsSdkLastVersion + return ('%s\\' % ucrtver) if ucrtver else '' + + @property + def SdkSetup(self): + """ + Microsoft Windows SDK Setup + """ + if self.vc_ver > 9.0: + return [] + + return [os.path.join(self.si.WindowsSdkDir, 'Setup')] + + @property + def FxTools(self): + """ + Microsoft .NET Framework Tools + """ + pi = self.pi + si = self.si + + if self.vc_ver <= 10.0: + include32 = True + include64 = not pi.target_is_x86() and not pi.current_is_x86() + else: + include32 = pi.target_is_x86() or pi.current_is_x86() + include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64' + + tools = [] + if include32: + tools += [os.path.join(si.FrameworkDir32, ver) + for ver in si.FrameworkVersion32] + if include64: + tools += [os.path.join(si.FrameworkDir64, ver) + for ver in si.FrameworkVersion64] + return tools + + @property + def NetFxSDKLibraries(self): + """ + Microsoft .Net Framework SDK Libraries + """ + if self.vc_ver < 14.0 or not self.si.NetFxSdkDir: + return [] + + arch_subdir = self.pi.target_dir(x64=True) + return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)] + + @property + def NetFxSDKIncludes(self): + """ + Microsoft .Net Framework SDK Includes + """ + if self.vc_ver < 14.0 or not self.si.NetFxSdkDir: + return [] + + return [os.path.join(self.si.NetFxSdkDir, r'include\um')] + + @property + def VsTDb(self): + """ + Microsoft Visual Studio Team System Database + """ + return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')] + + @property + def MSBuild(self): + """ + Microsoft Build Engine + """ + if self.vc_ver < 12.0: + return [] + elif self.vc_ver < 15.0: + base_path = self.si.ProgramFilesx86 + arch_subdir = self.pi.current_dir(hidex86=True) + else: + base_path = self.si.VSInstallDir + arch_subdir = '' + + path = r'MSBuild\%0.1f\bin%s' % (self.vc_ver, arch_subdir) + build = [os.path.join(base_path, path)] + + if self.vc_ver >= 15.0: + # Add Roslyn C# & Visual Basic Compiler + build += [os.path.join(base_path, path, 'Roslyn')] + + return build + + @property + def HTMLHelpWorkshop(self): + """ + Microsoft HTML Help Workshop + """ + if self.vc_ver < 11.0: + return [] + + return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')] + + @property + def UCRTLibraries(self): + """ + Microsoft Universal C Runtime SDK Libraries + """ + if self.vc_ver < 14.0: + return [] + + arch_subdir = self.pi.target_dir(x64=True) + lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib') + ucrtver = self._ucrt_subdir + return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))] + + @property + def UCRTIncludes(self): + """ + Microsoft Universal C Runtime SDK Include + """ + if self.vc_ver < 14.0: + return [] + + include = os.path.join(self.si.UniversalCRTSdkDir, 'include') + return [os.path.join(include, '%sucrt' % self._ucrt_subdir)] + + @property + def _ucrt_subdir(self): + """ + Microsoft Universal C Runtime SDK version subdir + """ + ucrtver = self.si.UniversalCRTSdkLastVersion + return ('%s\\' % ucrtver) if ucrtver else '' + + @property + def FSharp(self): + """ + Microsoft Visual F# + """ + if self.vc_ver < 11.0 and self.vc_ver > 12.0: + return [] + + return self.si.FSharpInstallDir + + @property + def VCRuntimeRedist(self): + """ + Microsoft Visual C++ runtime redistribuable dll + """ + arch_subdir = self.pi.target_dir(x64=True) + if self.vc_ver < 15: + redist_path = self.si.VCInstallDir + vcruntime = 'redist%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll' + else: + redist_path = self.si.VCInstallDir.replace('\\Tools', '\\Redist') + vcruntime = 'onecore%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll' + + # Visual Studio 2017 is still Visual C++ 14.0 + dll_ver = 14.0 if self.vc_ver == 15 else self.vc_ver + + vcruntime = vcruntime % (arch_subdir, self.vc_ver, dll_ver) + return os.path.join(redist_path, vcruntime) + + def return_env(self, exists=True): + """ + Return environment dict. + + Parameters + ---------- + exists: bool + It True, only return existing paths. + """ + env = dict( + include=self._build_paths('include', + [self.VCIncludes, + self.OSIncludes, + self.UCRTIncludes, + self.NetFxSDKIncludes], + exists), + lib=self._build_paths('lib', + [self.VCLibraries, + self.OSLibraries, + self.FxTools, + self.UCRTLibraries, + self.NetFxSDKLibraries], + exists), + libpath=self._build_paths('libpath', + [self.VCLibraries, + self.FxTools, + self.VCStoreRefs, + self.OSLibpath], + exists), + path=self._build_paths('path', + [self.VCTools, + self.VSTools, + self.VsTDb, + self.SdkTools, + self.SdkSetup, + self.FxTools, + self.MSBuild, + self.HTMLHelpWorkshop, + self.FSharp], + exists), + ) + if self.vc_ver >= 14 and os.path.isfile(self.VCRuntimeRedist): + env['py_vcruntime_redist'] = self.VCRuntimeRedist + return env + + def _build_paths(self, name, spec_path_lists, exists): + """ + Given an environment variable name and specified paths, + return a pathsep-separated string of paths containing + unique, extant, directories from those paths and from + the environment variable. Raise an error if no paths + are resolved. + """ + # flatten spec_path_lists + spec_paths = itertools.chain.from_iterable(spec_path_lists) + env_paths = safe_env.get(name, '').split(os.pathsep) + paths = itertools.chain(spec_paths, env_paths) + extant_paths = list(filter(os.path.isdir, paths)) if exists else paths + if not extant_paths: + msg = "%s environment variable is empty" % name.upper() + raise distutils.errors.DistutilsPlatformError(msg) + unique_paths = self._unique_everseen(extant_paths) + return os.pathsep.join(unique_paths) + + # from Python docs + def _unique_everseen(self, iterable, key=None): + """ + List unique elements, preserving order. + Remember all elements ever seen. + + _unique_everseen('AAAABBBCCDAABBB') --> A B C D + + _unique_everseen('ABBCcAD', str.lower) --> A B C D + """ + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element diff --git a/venv/lib/python3.7/site-packages/setuptools/namespaces.py b/venv/lib/python3.7/site-packages/setuptools/namespaces.py new file mode 100644 index 0000000..dc16106 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/namespaces.py @@ -0,0 +1,107 @@ +import os +from distutils import log +import itertools + +from setuptools.extern.six.moves import map + + +flatten = itertools.chain.from_iterable + + +class Installer: + + nspkg_ext = '-nspkg.pth' + + def install_namespaces(self): + nsp = self._get_all_ns_packages() + if not nsp: + return + filename, ext = os.path.splitext(self._get_target()) + filename += self.nspkg_ext + self.outputs.append(filename) + log.info("Installing %s", filename) + lines = map(self._gen_nspkg_line, nsp) + + if self.dry_run: + # always generate the lines, even in dry run + list(lines) + return + + with open(filename, 'wt') as f: + f.writelines(lines) + + def uninstall_namespaces(self): + filename, ext = os.path.splitext(self._get_target()) + filename += self.nspkg_ext + if not os.path.exists(filename): + return + log.info("Removing %s", filename) + os.remove(filename) + + def _get_target(self): + return self.target + + _nspkg_tmpl = ( + "import sys, types, os", + "has_mfs = sys.version_info > (3, 5)", + "p = os.path.join(%(root)s, *%(pth)r)", + "importlib = has_mfs and __import__('importlib.util')", + "has_mfs and __import__('importlib.machinery')", + "m = has_mfs and " + "sys.modules.setdefault(%(pkg)r, " + "importlib.util.module_from_spec(" + "importlib.machinery.PathFinder.find_spec(%(pkg)r, " + "[os.path.dirname(p)])))", + "m = m or " + "sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))", + "mp = (m or []) and m.__dict__.setdefault('__path__',[])", + "(p not in mp) and mp.append(p)", + ) + "lines for the namespace installer" + + _nspkg_tmpl_multi = ( + 'm and setattr(sys.modules[%(parent)r], %(child)r, m)', + ) + "additional line(s) when a parent package is indicated" + + def _get_root(self): + return "sys._getframe(1).f_locals['sitedir']" + + def _gen_nspkg_line(self, pkg): + # ensure pkg is not a unicode string under Python 2.7 + pkg = str(pkg) + pth = tuple(pkg.split('.')) + root = self._get_root() + tmpl_lines = self._nspkg_tmpl + parent, sep, child = pkg.rpartition('.') + if parent: + tmpl_lines += self._nspkg_tmpl_multi + return ';'.join(tmpl_lines) % locals() + '\n' + + def _get_all_ns_packages(self): + """Return sorted list of all package namespaces""" + pkgs = self.distribution.namespace_packages or [] + return sorted(flatten(map(self._pkg_names, pkgs))) + + @staticmethod + def _pkg_names(pkg): + """ + Given a namespace package, yield the components of that + package. + + >>> names = Installer._pkg_names('a.b.c') + >>> set(names) == set(['a', 'a.b', 'a.b.c']) + True + """ + parts = pkg.split('.') + while parts: + yield '.'.join(parts) + parts.pop() + + +class DevelopInstaller(Installer): + def _get_root(self): + return repr(str(self.egg_path)) + + def _get_target(self): + return self.egg_link diff --git a/venv/lib/python3.7/site-packages/setuptools/package_index.py b/venv/lib/python3.7/site-packages/setuptools/package_index.py new file mode 100644 index 0000000..1608b91 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/package_index.py @@ -0,0 +1,1128 @@ +"""PyPI and direct package downloading""" +import sys +import os +import re +import shutil +import socket +import base64 +import hashlib +import itertools +import warnings +from functools import wraps + +from setuptools.extern import six +from setuptools.extern.six.moves import urllib, http_client, configparser, map + +import setuptools +from pkg_resources import ( + CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST, + Environment, find_distributions, safe_name, safe_version, + to_filename, Requirement, DEVELOP_DIST, EGG_DIST, +) +from setuptools import ssl_support +from distutils import log +from distutils.errors import DistutilsError +from fnmatch import translate +from setuptools.py27compat import get_all_headers +from setuptools.py33compat import unescape +from setuptools.wheel import Wheel + +__metaclass__ = type + +EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$') +HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) +PYPI_MD5 = re.compile( + r'<a href="([^"#]+)">([^<]+)</a>\n\s+\(<a (?:title="MD5 hash"\n\s+)' + r'href="[^?]+\?:action=show_md5&digest=([0-9a-f]{32})">md5</a>\)' +) +URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match +EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() + +__all__ = [ + 'PackageIndex', 'distros_for_url', 'parse_bdist_wininst', + 'interpret_distro_name', +] + +_SOCKET_TIMEOUT = 15 + +_tmpl = "setuptools/{setuptools.__version__} Python-urllib/{py_major}" +user_agent = _tmpl.format(py_major=sys.version[:3], setuptools=setuptools) + + +def parse_requirement_arg(spec): + try: + return Requirement.parse(spec) + except ValueError: + raise DistutilsError( + "Not a URL, existing file, or requirement spec: %r" % (spec,) + ) + + +def parse_bdist_wininst(name): + """Return (base,pyversion) or (None,None) for possible .exe name""" + + lower = name.lower() + base, py_ver, plat = None, None, None + + if lower.endswith('.exe'): + if lower.endswith('.win32.exe'): + base = name[:-10] + plat = 'win32' + elif lower.startswith('.win32-py', -16): + py_ver = name[-7:-4] + base = name[:-16] + plat = 'win32' + elif lower.endswith('.win-amd64.exe'): + base = name[:-14] + plat = 'win-amd64' + elif lower.startswith('.win-amd64-py', -20): + py_ver = name[-7:-4] + base = name[:-20] + plat = 'win-amd64' + return base, py_ver, plat + + +def egg_info_for_url(url): + parts = urllib.parse.urlparse(url) + scheme, server, path, parameters, query, fragment = parts + base = urllib.parse.unquote(path.split('/')[-1]) + if server == 'sourceforge.net' and base == 'download': # XXX Yuck + base = urllib.parse.unquote(path.split('/')[-2]) + if '#' in base: + base, fragment = base.split('#', 1) + return base, fragment + + +def distros_for_url(url, metadata=None): + """Yield egg or source distribution objects that might be found at a URL""" + base, fragment = egg_info_for_url(url) + for dist in distros_for_location(url, base, metadata): + yield dist + if fragment: + match = EGG_FRAGMENT.match(fragment) + if match: + for dist in interpret_distro_name( + url, match.group(1), metadata, precedence=CHECKOUT_DIST + ): + yield dist + + +def distros_for_location(location, basename, metadata=None): + """Yield egg or source distribution objects based on basename""" + if basename.endswith('.egg.zip'): + basename = basename[:-4] # strip the .zip + if basename.endswith('.egg') and '-' in basename: + # only one, unambiguous interpretation + return [Distribution.from_location(location, basename, metadata)] + if basename.endswith('.whl') and '-' in basename: + wheel = Wheel(basename) + if not wheel.is_compatible(): + return [] + return [Distribution( + location=location, + project_name=wheel.project_name, + version=wheel.version, + # Increase priority over eggs. + precedence=EGG_DIST + 1, + )] + if basename.endswith('.exe'): + win_base, py_ver, platform = parse_bdist_wininst(basename) + if win_base is not None: + return interpret_distro_name( + location, win_base, metadata, py_ver, BINARY_DIST, platform + ) + # Try source distro extensions (.zip, .tgz, etc.) + # + for ext in EXTENSIONS: + if basename.endswith(ext): + basename = basename[:-len(ext)] + return interpret_distro_name(location, basename, metadata) + return [] # no extension matched + + +def distros_for_filename(filename, metadata=None): + """Yield possible egg or source distribution objects based on a filename""" + return distros_for_location( + normalize_path(filename), os.path.basename(filename), metadata + ) + + +def interpret_distro_name( + location, basename, metadata, py_version=None, precedence=SOURCE_DIST, + platform=None +): + """Generate alternative interpretations of a source distro name + + Note: if `location` is a filesystem filename, you should call + ``pkg_resources.normalize_path()`` on it before passing it to this + routine! + """ + # Generate alternative interpretations of a source distro name + # Because some packages are ambiguous as to name/versions split + # e.g. "adns-python-1.1.0", "egenix-mx-commercial", etc. + # So, we generate each possible interepretation (e.g. "adns, python-1.1.0" + # "adns-python, 1.1.0", and "adns-python-1.1.0, no version"). In practice, + # the spurious interpretations should be ignored, because in the event + # there's also an "adns" package, the spurious "python-1.1.0" version will + # compare lower than any numeric version number, and is therefore unlikely + # to match a request for it. It's still a potential problem, though, and + # in the long run PyPI and the distutils should go for "safe" names and + # versions in distribution archive names (sdist and bdist). + + parts = basename.split('-') + if not py_version and any(re.match(r'py\d\.\d$', p) for p in parts[2:]): + # it is a bdist_dumb, not an sdist -- bail out + return + + for p in range(1, len(parts) + 1): + yield Distribution( + location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), + py_version=py_version, precedence=precedence, + platform=platform + ) + + +# From Python 2.7 docs +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in six.moves.filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +def unique_values(func): + """ + Wrap a function returning an iterable such that the resulting iterable + only ever yields unique items. + """ + + @wraps(func) + def wrapper(*args, **kwargs): + return unique_everseen(func(*args, **kwargs)) + + return wrapper + + +REL = re.compile(r"""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) +# this line is here to fix emacs' cruddy broken syntax highlighting + + +@unique_values +def find_external_links(url, page): + """Find rel="homepage" and rel="download" links in `page`, yielding URLs""" + + for match in REL.finditer(page): + tag, rel = match.groups() + rels = set(map(str.strip, rel.lower().split(','))) + if 'homepage' in rels or 'download' in rels: + for match in HREF.finditer(tag): + yield urllib.parse.urljoin(url, htmldecode(match.group(1))) + + for tag in ("<th>Home Page", "<th>Download URL"): + pos = page.find(tag) + if pos != -1: + match = HREF.search(page, pos) + if match: + yield urllib.parse.urljoin(url, htmldecode(match.group(1))) + + +class ContentChecker: + """ + A null content checker that defines the interface for checking content + """ + + def feed(self, block): + """ + Feed a block of data to the hash. + """ + return + + def is_valid(self): + """ + Check the hash. Return False if validation fails. + """ + return True + + def report(self, reporter, template): + """ + Call reporter with information about the checker (hash name) + substituted into the template. + """ + return + + +class HashChecker(ContentChecker): + pattern = re.compile( + r'(?P<hash_name>sha1|sha224|sha384|sha256|sha512|md5)=' + r'(?P<expected>[a-f0-9]+)' + ) + + def __init__(self, hash_name, expected): + self.hash_name = hash_name + self.hash = hashlib.new(hash_name) + self.expected = expected + + @classmethod + def from_url(cls, url): + "Construct a (possibly null) ContentChecker from a URL" + fragment = urllib.parse.urlparse(url)[-1] + if not fragment: + return ContentChecker() + match = cls.pattern.search(fragment) + if not match: + return ContentChecker() + return cls(**match.groupdict()) + + def feed(self, block): + self.hash.update(block) + + def is_valid(self): + return self.hash.hexdigest() == self.expected + + def report(self, reporter, template): + msg = template % self.hash_name + return reporter(msg) + + +class PackageIndex(Environment): + """A distribution index that scans web pages for download URLs""" + + def __init__( + self, index_url="https://pypi.org/simple/", hosts=('*',), + ca_bundle=None, verify_ssl=True, *args, **kw + ): + Environment.__init__(self, *args, **kw) + self.index_url = index_url + "/" [:not index_url.endswith('/')] + self.scanned_urls = {} + self.fetched_urls = {} + self.package_pages = {} + self.allows = re.compile('|'.join(map(translate, hosts))).match + self.to_scan = [] + use_ssl = ( + verify_ssl + and ssl_support.is_available + and (ca_bundle or ssl_support.find_ca_bundle()) + ) + if use_ssl: + self.opener = ssl_support.opener_for(ca_bundle) + else: + self.opener = urllib.request.urlopen + + def process_url(self, url, retrieve=False): + """Evaluate a URL as a possible download, and maybe retrieve it""" + if url in self.scanned_urls and not retrieve: + return + self.scanned_urls[url] = True + if not URL_SCHEME(url): + self.process_filename(url) + return + else: + dists = list(distros_for_url(url)) + if dists: + if not self.url_ok(url): + return + self.debug("Found link: %s", url) + + if dists or not retrieve or url in self.fetched_urls: + list(map(self.add, dists)) + return # don't need the actual page + + if not self.url_ok(url): + self.fetched_urls[url] = True + return + + self.info("Reading %s", url) + self.fetched_urls[url] = True # prevent multiple fetch attempts + tmpl = "Download error on %s: %%s -- Some packages may not be found!" + f = self.open_url(url, tmpl % url) + if f is None: + return + self.fetched_urls[f.url] = True + if 'html' not in f.headers.get('content-type', '').lower(): + f.close() # not html, we can't process it + return + + base = f.url # handle redirects + page = f.read() + if not isinstance(page, str): + # In Python 3 and got bytes but want str. + if isinstance(f, urllib.error.HTTPError): + # Errors have no charset, assume latin1: + charset = 'latin-1' + else: + charset = f.headers.get_param('charset') or 'latin-1' + page = page.decode(charset, "ignore") + f.close() + for match in HREF.finditer(page): + link = urllib.parse.urljoin(base, htmldecode(match.group(1))) + self.process_url(link) + if url.startswith(self.index_url) and getattr(f, 'code', None) != 404: + page = self.process_index(url, page) + + def process_filename(self, fn, nested=False): + # process filenames or directories + if not os.path.exists(fn): + self.warn("Not found: %s", fn) + return + + if os.path.isdir(fn) and not nested: + path = os.path.realpath(fn) + for item in os.listdir(path): + self.process_filename(os.path.join(path, item), True) + + dists = distros_for_filename(fn) + if dists: + self.debug("Found: %s", fn) + list(map(self.add, dists)) + + def url_ok(self, url, fatal=False): + s = URL_SCHEME(url) + is_file = s and s.group(1).lower() == 'file' + if is_file or self.allows(urllib.parse.urlparse(url)[1]): + return True + msg = ( + "\nNote: Bypassing %s (disallowed host; see " + "http://bit.ly/2hrImnY for details).\n") + if fatal: + raise DistutilsError(msg % url) + else: + self.warn(msg, url) + + def scan_egg_links(self, search_path): + dirs = filter(os.path.isdir, search_path) + egg_links = ( + (path, entry) + for path in dirs + for entry in os.listdir(path) + if entry.endswith('.egg-link') + ) + list(itertools.starmap(self.scan_egg_link, egg_links)) + + def scan_egg_link(self, path, entry): + with open(os.path.join(path, entry)) as raw_lines: + # filter non-empty lines + lines = list(filter(None, map(str.strip, raw_lines))) + + if len(lines) != 2: + # format is not recognized; punt + return + + egg_path, setup_path = lines + + for dist in find_distributions(os.path.join(path, egg_path)): + dist.location = os.path.join(path, *lines) + dist.precedence = SOURCE_DIST + self.add(dist) + + def process_index(self, url, page): + """Process the contents of a PyPI page""" + + def scan(link): + # Process a URL to see if it's for a package page + if link.startswith(self.index_url): + parts = list(map( + urllib.parse.unquote, link[len(self.index_url):].split('/') + )) + if len(parts) == 2 and '#' not in parts[1]: + # it's a package page, sanitize and index it + pkg = safe_name(parts[0]) + ver = safe_version(parts[1]) + self.package_pages.setdefault(pkg.lower(), {})[link] = True + return to_filename(pkg), to_filename(ver) + return None, None + + # process an index page into the package-page index + for match in HREF.finditer(page): + try: + scan(urllib.parse.urljoin(url, htmldecode(match.group(1)))) + except ValueError: + pass + + pkg, ver = scan(url) # ensure this page is in the page index + if pkg: + # process individual package page + for new_url in find_external_links(url, page): + # Process the found URL + base, frag = egg_info_for_url(new_url) + if base.endswith('.py') and not frag: + if ver: + new_url += '#egg=%s-%s' % (pkg, ver) + else: + self.need_version_info(url) + self.scan_url(new_url) + + return PYPI_MD5.sub( + lambda m: '<a href="%s#md5=%s">%s</a>' % m.group(1, 3, 2), page + ) + else: + return "" # no sense double-scanning non-package pages + + def need_version_info(self, url): + self.scan_all( + "Page at %s links to .py file(s) without version info; an index " + "scan is required.", url + ) + + def scan_all(self, msg=None, *args): + if self.index_url not in self.fetched_urls: + if msg: + self.warn(msg, *args) + self.info( + "Scanning index of all packages (this may take a while)" + ) + self.scan_url(self.index_url) + + def find_packages(self, requirement): + self.scan_url(self.index_url + requirement.unsafe_name + '/') + + if not self.package_pages.get(requirement.key): + # Fall back to safe version of the name + self.scan_url(self.index_url + requirement.project_name + '/') + + if not self.package_pages.get(requirement.key): + # We couldn't find the target package, so search the index page too + self.not_found_in_index(requirement) + + for url in list(self.package_pages.get(requirement.key, ())): + # scan each page that might be related to the desired package + self.scan_url(url) + + def obtain(self, requirement, installer=None): + self.prescan() + self.find_packages(requirement) + for dist in self[requirement.key]: + if dist in requirement: + return dist + self.debug("%s does not match %s", requirement, dist) + return super(PackageIndex, self).obtain(requirement, installer) + + def check_hash(self, checker, filename, tfp): + """ + checker is a ContentChecker + """ + checker.report( + self.debug, + "Validating %%s checksum for %s" % filename) + if not checker.is_valid(): + tfp.close() + os.unlink(filename) + raise DistutilsError( + "%s validation failed for %s; " + "possible download problem?" + % (checker.hash.name, os.path.basename(filename)) + ) + + def add_find_links(self, urls): + """Add `urls` to the list that will be prescanned for searches""" + for url in urls: + if ( + self.to_scan is None # if we have already "gone online" + or not URL_SCHEME(url) # or it's a local file/directory + or url.startswith('file:') + or list(distros_for_url(url)) # or a direct package link + ): + # then go ahead and process it now + self.scan_url(url) + else: + # otherwise, defer retrieval till later + self.to_scan.append(url) + + def prescan(self): + """Scan urls scheduled for prescanning (e.g. --find-links)""" + if self.to_scan: + list(map(self.scan_url, self.to_scan)) + self.to_scan = None # from now on, go ahead and process immediately + + def not_found_in_index(self, requirement): + if self[requirement.key]: # we've seen at least one distro + meth, msg = self.info, "Couldn't retrieve index page for %r" + else: # no distros seen for this name, might be misspelled + meth, msg = ( + self.warn, + "Couldn't find index page for %r (maybe misspelled?)") + meth(msg, requirement.unsafe_name) + self.scan_all() + + def download(self, spec, tmpdir): + """Locate and/or download `spec` to `tmpdir`, returning a local path + + `spec` may be a ``Requirement`` object, or a string containing a URL, + an existing local filename, or a project/version requirement spec + (i.e. the string form of a ``Requirement`` object). If it is the URL + of a .py file with an unambiguous ``#egg=name-version`` tag (i.e., one + that escapes ``-`` as ``_`` throughout), a trivial ``setup.py`` is + automatically created alongside the downloaded file. + + If `spec` is a ``Requirement`` object or a string containing a + project/version requirement spec, this method returns the location of + a matching distribution (possibly after downloading it to `tmpdir`). + If `spec` is a locally existing file or directory name, it is simply + returned unchanged. If `spec` is a URL, it is downloaded to a subpath + of `tmpdir`, and the local filename is returned. Various errors may be + raised if a problem occurs during downloading. + """ + if not isinstance(spec, Requirement): + scheme = URL_SCHEME(spec) + if scheme: + # It's a url, download it to tmpdir + found = self._download_url(scheme.group(1), spec, tmpdir) + base, fragment = egg_info_for_url(spec) + if base.endswith('.py'): + found = self.gen_setup(found, fragment, tmpdir) + return found + elif os.path.exists(spec): + # Existing file or directory, just return it + return spec + else: + spec = parse_requirement_arg(spec) + return getattr(self.fetch_distribution(spec, tmpdir), 'location', None) + + def fetch_distribution( + self, requirement, tmpdir, force_scan=False, source=False, + develop_ok=False, local_index=None): + """Obtain a distribution suitable for fulfilling `requirement` + + `requirement` must be a ``pkg_resources.Requirement`` instance. + If necessary, or if the `force_scan` flag is set, the requirement is + searched for in the (online) package index as well as the locally + installed packages. If a distribution matching `requirement` is found, + the returned distribution's ``location`` is the value you would have + gotten from calling the ``download()`` method with the matching + distribution's URL or filename. If no matching distribution is found, + ``None`` is returned. + + If the `source` flag is set, only source distributions and source + checkout links will be considered. Unless the `develop_ok` flag is + set, development and system eggs (i.e., those using the ``.egg-info`` + format) will be ignored. + """ + # process a Requirement + self.info("Searching for %s", requirement) + skipped = {} + dist = None + + def find(req, env=None): + if env is None: + env = self + # Find a matching distribution; may be called more than once + + for dist in env[req.key]: + + if dist.precedence == DEVELOP_DIST and not develop_ok: + if dist not in skipped: + self.warn( + "Skipping development or system egg: %s", dist, + ) + skipped[dist] = 1 + continue + + test = ( + dist in req + and (dist.precedence <= SOURCE_DIST or not source) + ) + if test: + loc = self.download(dist.location, tmpdir) + dist.download_location = loc + if os.path.exists(dist.download_location): + return dist + + if force_scan: + self.prescan() + self.find_packages(requirement) + dist = find(requirement) + + if not dist and local_index is not None: + dist = find(requirement, local_index) + + if dist is None: + if self.to_scan is not None: + self.prescan() + dist = find(requirement) + + if dist is None and not force_scan: + self.find_packages(requirement) + dist = find(requirement) + + if dist is None: + self.warn( + "No local packages or working download links found for %s%s", + (source and "a source distribution of " or ""), + requirement, + ) + else: + self.info("Best match: %s", dist) + return dist.clone(location=dist.download_location) + + def fetch(self, requirement, tmpdir, force_scan=False, source=False): + """Obtain a file suitable for fulfilling `requirement` + + DEPRECATED; use the ``fetch_distribution()`` method now instead. For + backward compatibility, this routine is identical but returns the + ``location`` of the downloaded distribution instead of a distribution + object. + """ + dist = self.fetch_distribution(requirement, tmpdir, force_scan, source) + if dist is not None: + return dist.location + return None + + def gen_setup(self, filename, fragment, tmpdir): + match = EGG_FRAGMENT.match(fragment) + dists = match and [ + d for d in + interpret_distro_name(filename, match.group(1), None) if d.version + ] or [] + + if len(dists) == 1: # unambiguous ``#egg`` fragment + basename = os.path.basename(filename) + + # Make sure the file has been downloaded to the temp dir. + if os.path.dirname(filename) != tmpdir: + dst = os.path.join(tmpdir, basename) + from setuptools.command.easy_install import samefile + if not samefile(filename, dst): + shutil.copy2(filename, dst) + filename = dst + + with open(os.path.join(tmpdir, 'setup.py'), 'w') as file: + file.write( + "from setuptools import setup\n" + "setup(name=%r, version=%r, py_modules=[%r])\n" + % ( + dists[0].project_name, dists[0].version, + os.path.splitext(basename)[0] + ) + ) + return filename + + elif match: + raise DistutilsError( + "Can't unambiguously interpret project/version identifier %r; " + "any dashes in the name or version should be escaped using " + "underscores. %r" % (fragment, dists) + ) + else: + raise DistutilsError( + "Can't process plain .py files without an '#egg=name-version'" + " suffix to enable automatic setup script generation." + ) + + dl_blocksize = 8192 + + def _download_to(self, url, filename): + self.info("Downloading %s", url) + # Download the file + fp = None + try: + checker = HashChecker.from_url(url) + fp = self.open_url(url) + if isinstance(fp, urllib.error.HTTPError): + raise DistutilsError( + "Can't download %s: %s %s" % (url, fp.code, fp.msg) + ) + headers = fp.info() + blocknum = 0 + bs = self.dl_blocksize + size = -1 + if "content-length" in headers: + # Some servers return multiple Content-Length headers :( + sizes = get_all_headers(headers, 'Content-Length') + size = max(map(int, sizes)) + self.reporthook(url, filename, blocknum, bs, size) + with open(filename, 'wb') as tfp: + while True: + block = fp.read(bs) + if block: + checker.feed(block) + tfp.write(block) + blocknum += 1 + self.reporthook(url, filename, blocknum, bs, size) + else: + break + self.check_hash(checker, filename, tfp) + return headers + finally: + if fp: + fp.close() + + def reporthook(self, url, filename, blocknum, blksize, size): + pass # no-op + + def open_url(self, url, warning=None): + if url.startswith('file:'): + return local_open(url) + try: + return open_with_auth(url, self.opener) + except (ValueError, http_client.InvalidURL) as v: + msg = ' '.join([str(arg) for arg in v.args]) + if warning: + self.warn(warning, msg) + else: + raise DistutilsError('%s %s' % (url, msg)) + except urllib.error.HTTPError as v: + return v + except urllib.error.URLError as v: + if warning: + self.warn(warning, v.reason) + else: + raise DistutilsError("Download error for %s: %s" + % (url, v.reason)) + except http_client.BadStatusLine as v: + if warning: + self.warn(warning, v.line) + else: + raise DistutilsError( + '%s returned a bad status line. The server might be ' + 'down, %s' % + (url, v.line) + ) + except (http_client.HTTPException, socket.error) as v: + if warning: + self.warn(warning, v) + else: + raise DistutilsError("Download error for %s: %s" + % (url, v)) + + def _download_url(self, scheme, url, tmpdir): + # Determine download filename + # + name, fragment = egg_info_for_url(url) + if name: + while '..' in name: + name = name.replace('..', '.').replace('\\', '_') + else: + name = "__downloaded__" # default if URL has no path contents + + if name.endswith('.egg.zip'): + name = name[:-4] # strip the extra .zip before download + + filename = os.path.join(tmpdir, name) + + # Download the file + # + if scheme == 'svn' or scheme.startswith('svn+'): + return self._download_svn(url, filename) + elif scheme == 'git' or scheme.startswith('git+'): + return self._download_git(url, filename) + elif scheme.startswith('hg+'): + return self._download_hg(url, filename) + elif scheme == 'file': + return urllib.request.url2pathname(urllib.parse.urlparse(url)[2]) + else: + self.url_ok(url, True) # raises error if not allowed + return self._attempt_download(url, filename) + + def scan_url(self, url): + self.process_url(url, True) + + def _attempt_download(self, url, filename): + headers = self._download_to(url, filename) + if 'html' in headers.get('content-type', '').lower(): + return self._download_html(url, headers, filename) + else: + return filename + + def _download_html(self, url, headers, filename): + file = open(filename) + for line in file: + if line.strip(): + # Check for a subversion index page + if re.search(r'<title>([^- ]+ - )?Revision \d+:', line): + # it's a subversion index page: + file.close() + os.unlink(filename) + return self._download_svn(url, filename) + break # not an index page + file.close() + os.unlink(filename) + raise DistutilsError("Unexpected HTML page found at " + url) + + def _download_svn(self, url, filename): + warnings.warn("SVN download support is deprecated", UserWarning) + url = url.split('#', 1)[0] # remove any fragment for svn's sake + creds = '' + if url.lower().startswith('svn:') and '@' in url: + scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) + if not netloc and path.startswith('//') and '/' in path[2:]: + netloc, path = path[2:].split('/', 1) + auth, host = urllib.parse.splituser(netloc) + if auth: + if ':' in auth: + user, pw = auth.split(':', 1) + creds = " --username=%s --password=%s" % (user, pw) + else: + creds = " --username=" + auth + netloc = host + parts = scheme, netloc, url, p, q, f + url = urllib.parse.urlunparse(parts) + self.info("Doing subversion checkout from %s to %s", url, filename) + os.system("svn checkout%s -q %s %s" % (creds, url, filename)) + return filename + + @staticmethod + def _vcs_split_rev_from_url(url, pop_prefix=False): + scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) + + scheme = scheme.split('+', 1)[-1] + + # Some fragment identification fails + path = path.split('#', 1)[0] + + rev = None + if '@' in path: + path, rev = path.rsplit('@', 1) + + # Also, discard fragment + url = urllib.parse.urlunsplit((scheme, netloc, path, query, '')) + + return url, rev + + def _download_git(self, url, filename): + filename = filename.split('#', 1)[0] + url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) + + self.info("Doing git clone from %s to %s", url, filename) + os.system("git clone --quiet %s %s" % (url, filename)) + + if rev is not None: + self.info("Checking out %s", rev) + os.system("(cd %s && git checkout --quiet %s)" % ( + filename, + rev, + )) + + return filename + + def _download_hg(self, url, filename): + filename = filename.split('#', 1)[0] + url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) + + self.info("Doing hg clone from %s to %s", url, filename) + os.system("hg clone --quiet %s %s" % (url, filename)) + + if rev is not None: + self.info("Updating to %s", rev) + os.system("(cd %s && hg up -C -r %s -q)" % ( + filename, + rev, + )) + + return filename + + def debug(self, msg, *args): + log.debug(msg, *args) + + def info(self, msg, *args): + log.info(msg, *args) + + def warn(self, msg, *args): + log.warn(msg, *args) + + +# This pattern matches a character entity reference (a decimal numeric +# references, a hexadecimal numeric reference, or a named reference). +entity_sub = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub + + +def decode_entity(match): + what = match.group(0) + return unescape(what) + + +def htmldecode(text): + """ + Decode HTML entities in the given text. + + >>> htmldecode( + ... 'https://../package_name-0.1.2.tar.gz' + ... '?tokena=A&tokenb=B">package_name-0.1.2.tar.gz') + 'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz' + """ + return entity_sub(decode_entity, text) + + +def socket_timeout(timeout=15): + def _socket_timeout(func): + def _socket_timeout(*args, **kwargs): + old_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(timeout) + try: + return func(*args, **kwargs) + finally: + socket.setdefaulttimeout(old_timeout) + + return _socket_timeout + + return _socket_timeout + + +def _encode_auth(auth): + """ + A function compatible with Python 2.3-3.3 that will encode + auth from a URL suitable for an HTTP header. + >>> str(_encode_auth('username%3Apassword')) + 'dXNlcm5hbWU6cGFzc3dvcmQ=' + + Long auth strings should not cause a newline to be inserted. + >>> long_auth = 'username:' + 'password'*10 + >>> chr(10) in str(_encode_auth(long_auth)) + False + """ + auth_s = urllib.parse.unquote(auth) + # convert to bytes + auth_bytes = auth_s.encode() + encoded_bytes = base64.b64encode(auth_bytes) + # convert back to a string + encoded = encoded_bytes.decode() + # strip the trailing carriage return + return encoded.replace('\n', '') + + +class Credential: + """ + A username/password pair. Use like a namedtuple. + """ + + def __init__(self, username, password): + self.username = username + self.password = password + + def __iter__(self): + yield self.username + yield self.password + + def __str__(self): + return '%(username)s:%(password)s' % vars(self) + + +class PyPIConfig(configparser.RawConfigParser): + def __init__(self): + """ + Load from ~/.pypirc + """ + defaults = dict.fromkeys(['username', 'password', 'repository'], '') + configparser.RawConfigParser.__init__(self, defaults) + + rc = os.path.join(os.path.expanduser('~'), '.pypirc') + if os.path.exists(rc): + self.read(rc) + + @property + def creds_by_repository(self): + sections_with_repositories = [ + section for section in self.sections() + if self.get(section, 'repository').strip() + ] + + return dict(map(self._get_repo_cred, sections_with_repositories)) + + def _get_repo_cred(self, section): + repo = self.get(section, 'repository').strip() + return repo, Credential( + self.get(section, 'username').strip(), + self.get(section, 'password').strip(), + ) + + def find_credential(self, url): + """ + If the URL indicated appears to be a repository defined in this + config, return the credential for that repository. + """ + for repository, cred in self.creds_by_repository.items(): + if url.startswith(repository): + return cred + + +def open_with_auth(url, opener=urllib.request.urlopen): + """Open a urllib2 request, handling HTTP authentication""" + + scheme, netloc, path, params, query, frag = urllib.parse.urlparse(url) + + # Double scheme does not raise on Mac OS X as revealed by a + # failing test. We would expect "nonnumeric port". Refs #20. + if netloc.endswith(':'): + raise http_client.InvalidURL("nonnumeric port: ''") + + if scheme in ('http', 'https'): + auth, host = urllib.parse.splituser(netloc) + else: + auth = None + + if not auth: + cred = PyPIConfig().find_credential(url) + if cred: + auth = str(cred) + info = cred.username, url + log.info('Authenticating as %s for %s (from .pypirc)', *info) + + if auth: + auth = "Basic " + _encode_auth(auth) + parts = scheme, host, path, params, query, frag + new_url = urllib.parse.urlunparse(parts) + request = urllib.request.Request(new_url) + request.add_header("Authorization", auth) + else: + request = urllib.request.Request(url) + + request.add_header('User-Agent', user_agent) + fp = opener(request) + + if auth: + # Put authentication info back into request URL if same host, + # so that links found on the page will work + s2, h2, path2, param2, query2, frag2 = urllib.parse.urlparse(fp.url) + if s2 == scheme and h2 == host: + parts = s2, netloc, path2, param2, query2, frag2 + fp.url = urllib.parse.urlunparse(parts) + + return fp + + +# adding a timeout to avoid freezing package_index +open_with_auth = socket_timeout(_SOCKET_TIMEOUT)(open_with_auth) + + +def fix_sf_url(url): + return url # backward compatibility + + +def local_open(url): + """Read a local path, with special support for directories""" + scheme, server, path, param, query, frag = urllib.parse.urlparse(url) + filename = urllib.request.url2pathname(path) + if os.path.isfile(filename): + return urllib.request.urlopen(url) + elif path.endswith('/') and os.path.isdir(filename): + files = [] + for f in os.listdir(filename): + filepath = os.path.join(filename, f) + if f == 'index.html': + with open(filepath, 'r') as fp: + body = fp.read() + break + elif os.path.isdir(filepath): + f += '/' + files.append('<a href="{name}">{name}</a>'.format(name=f)) + else: + tmpl = ( + "<html><head><title>{url}" + "{files}") + body = tmpl.format(url=url, files='\n'.join(files)) + status, message = 200, "OK" + else: + status, message, body = 404, "Path not found", "Not found" + + headers = {'content-type': 'text/html'} + body_stream = six.StringIO(body) + return urllib.error.HTTPError(url, status, message, headers, body_stream) diff --git a/venv/lib/python3.7/site-packages/setuptools/pep425tags.py b/venv/lib/python3.7/site-packages/setuptools/pep425tags.py new file mode 100644 index 0000000..8bf4277 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/pep425tags.py @@ -0,0 +1,319 @@ +# This file originally from pip: +# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/pep425tags.py +"""Generate and work with PEP 425 Compatibility Tags.""" +from __future__ import absolute_import + +import distutils.util +from distutils import log +import platform +import re +import sys +import sysconfig +import warnings +from collections import OrderedDict + +from .extern import six + +from . import glibc + +_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') + + +def get_config_var(var): + try: + return sysconfig.get_config_var(var) + except IOError as e: # Issue #1074 + warnings.warn("{}".format(e), RuntimeWarning) + return None + + +def get_abbr_impl(): + """Return abbreviated implementation name.""" + if hasattr(sys, 'pypy_version_info'): + pyimpl = 'pp' + elif sys.platform.startswith('java'): + pyimpl = 'jy' + elif sys.platform == 'cli': + pyimpl = 'ip' + else: + pyimpl = 'cp' + return pyimpl + + +def get_impl_ver(): + """Return implementation version.""" + impl_ver = get_config_var("py_version_nodot") + if not impl_ver or get_abbr_impl() == 'pp': + impl_ver = ''.join(map(str, get_impl_version_info())) + return impl_ver + + +def get_impl_version_info(): + """Return sys.version_info-like tuple for use in decrementing the minor + version.""" + if get_abbr_impl() == 'pp': + # as per https://github.com/pypa/pip/issues/2882 + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return sys.version_info[0], sys.version_info[1] + + +def get_impl_tag(): + """ + Returns the Tag for this specific implementation. + """ + return "{}{}".format(get_abbr_impl(), get_impl_ver()) + + +def get_flag(var, fallback, expected=True, warn=True): + """Use a fallback method for determining SOABI flags if the needed config + var is unset or unavailable.""" + val = get_config_var(var) + if val is None: + if warn: + log.debug("Config variable '%s' is unset, Python ABI tag may " + "be incorrect", var) + return fallback() + return val == expected + + +def get_abi_tag(): + """Return the ABI tag based on SOABI (if available) or emulate SOABI + (CPython 2, PyPy).""" + soabi = get_config_var('SOABI') + impl = get_abbr_impl() + if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): + d = '' + m = '' + u = '' + if get_flag('Py_DEBUG', + lambda: hasattr(sys, 'gettotalrefcount'), + warn=(impl == 'cp')): + d = 'd' + if get_flag('WITH_PYMALLOC', + lambda: impl == 'cp', + warn=(impl == 'cp')): + m = 'm' + if get_flag('Py_UNICODE_SIZE', + lambda: sys.maxunicode == 0x10ffff, + expected=4, + warn=(impl == 'cp' and + six.PY2)) \ + and six.PY2: + u = 'u' + abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) + elif soabi and soabi.startswith('cpython-'): + abi = 'cp' + soabi.split('-')[1] + elif soabi: + abi = soabi.replace('.', '_').replace('-', '_') + else: + abi = None + return abi + + +def _is_running_32bit(): + return sys.maxsize == 2147483647 + + +def get_platform(): + """Return our platform name 'win32', 'linux_x86_64'""" + if sys.platform == 'darwin': + # distutils.util.get_platform() returns the release based on the value + # of MACOSX_DEPLOYMENT_TARGET on which Python was built, which may + # be significantly older than the user's current machine. + release, _, machine = platform.mac_ver() + split_ver = release.split('.') + + if machine == "x86_64" and _is_running_32bit(): + machine = "i386" + elif machine == "ppc64" and _is_running_32bit(): + machine = "ppc" + + return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) + + # XXX remove distutils dependency + result = distutils.util.get_platform().replace('.', '_').replace('-', '_') + if result == "linux_x86_64" and _is_running_32bit(): + # 32 bit Python program (running on a 64 bit Linux): pip should only + # install and run 32 bit compiled extensions in that case. + result = "linux_i686" + + return result + + +def is_manylinux1_compatible(): + # Only Linux, and only x86-64 / i686 + if get_platform() not in {"linux_x86_64", "linux_i686"}: + return False + + # Check for presence of _manylinux module + try: + import _manylinux + return bool(_manylinux.manylinux1_compatible) + except (ImportError, AttributeError): + # Fall through to heuristic check below + pass + + # Check glibc version. CentOS 5 uses glibc 2.5. + return glibc.have_compatible_glibc(2, 5) + + +def get_darwin_arches(major, minor, machine): + """Return a list of supported arches (including group arches) for + the given major, minor and machine architecture of an macOS machine. + """ + arches = [] + + def _supports_arch(major, minor, arch): + # Looking at the application support for macOS versions in the chart + # provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears + # our timeline looks roughly like: + # + # 10.0 - Introduces ppc support. + # 10.4 - Introduces ppc64, i386, and x86_64 support, however the ppc64 + # and x86_64 support is CLI only, and cannot be used for GUI + # applications. + # 10.5 - Extends ppc64 and x86_64 support to cover GUI applications. + # 10.6 - Drops support for ppc64 + # 10.7 - Drops support for ppc + # + # Given that we do not know if we're installing a CLI or a GUI + # application, we must be conservative and assume it might be a GUI + # application and behave as if ppc64 and x86_64 support did not occur + # until 10.5. + # + # Note: The above information is taken from the "Application support" + # column in the chart not the "Processor support" since I believe + # that we care about what instruction sets an application can use + # not which processors the OS supports. + if arch == 'ppc': + return (major, minor) <= (10, 5) + if arch == 'ppc64': + return (major, minor) == (10, 5) + if arch == 'i386': + return (major, minor) >= (10, 4) + if arch == 'x86_64': + return (major, minor) >= (10, 5) + if arch in groups: + for garch in groups[arch]: + if _supports_arch(major, minor, garch): + return True + return False + + groups = OrderedDict([ + ("fat", ("i386", "ppc")), + ("intel", ("x86_64", "i386")), + ("fat64", ("x86_64", "ppc64")), + ("fat32", ("x86_64", "i386", "ppc")), + ]) + + if _supports_arch(major, minor, machine): + arches.append(machine) + + for garch in groups: + if machine in groups[garch] and _supports_arch(major, minor, garch): + arches.append(garch) + + arches.append('universal') + + return arches + + +def get_supported(versions=None, noarch=False, platform=None, + impl=None, abi=None): + """Return a list of supported tags for each version specified in + `versions`. + + :param versions: a list of string versions, of the form ["33", "32"], + or None. The first version will be assumed to support our ABI. + :param platform: specify the exact platform you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abi: specify the exact abi you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported = [] + + # Versions must be given with respect to the preference + if versions is None: + versions = [] + version_info = get_impl_version_info() + major = version_info[:-1] + # Support all previous minor Python versions. + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = impl or get_abbr_impl() + + abis = [] + + abi = abi or get_abi_tag() + if abi: + abis[0:0] = [abi] + + abi3s = set() + import imp + for suffix in imp.get_suffixes(): + if suffix[0].startswith('.abi'): + abi3s.add(suffix[0].split('.', 2)[1]) + + abis.extend(sorted(list(abi3s))) + + abis.append('none') + + if not noarch: + arch = platform or get_platform() + if arch.startswith('macosx'): + # support macosx-10.6-intel on macosx-10.9-x86_64 + match = _osx_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + tpl = '{}_{}_%i_%s'.format(name, major) + arches = [] + for m in reversed(range(int(minor) + 1)): + for a in get_darwin_arches(int(major), m, actual_arch): + arches.append(tpl % (m, a)) + else: + # arch pattern didn't match (?!) + arches = [arch] + elif platform is None and is_manylinux1_compatible(): + arches = [arch.replace('linux', 'manylinux1'), arch] + else: + arches = [arch] + + # Current version, current API (built specifically for our Python): + for abi in abis: + for arch in arches: + supported.append(('%s%s' % (impl, versions[0]), abi, arch)) + + # abi3 modules compatible with older version of Python + for version in versions[1:]: + # abi3 was introduced in Python 3.2 + if version in {'31', '30'}: + break + for abi in abi3s: # empty set if not Python 3 + for arch in arches: + supported.append(("%s%s" % (impl, version), abi, arch)) + + # Has binaries, does not use the Python API: + for arch in arches: + supported.append(('py%s' % (versions[0][0]), 'none', arch)) + + # No abi / arch, but requires our implementation: + supported.append(('%s%s' % (impl, versions[0]), 'none', 'any')) + # Tagged specifically as being cross-version compatible + # (with just the major version specified) + supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + # No abi / arch, generic Python + for i, version in enumerate(versions): + supported.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + supported.append(('py%s' % (version[0]), 'none', 'any')) + + return supported + + +implementation_tag = get_impl_tag() diff --git a/venv/lib/python3.7/site-packages/setuptools/py27compat.py b/venv/lib/python3.7/site-packages/setuptools/py27compat.py new file mode 100644 index 0000000..2985011 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/py27compat.py @@ -0,0 +1,28 @@ +""" +Compatibility Support for Python 2.7 and earlier +""" + +import platform + +from setuptools.extern import six + + +def get_all_headers(message, key): + """ + Given an HTTPMessage, return all headers matching a given key. + """ + return message.get_all(key) + + +if six.PY2: + def get_all_headers(message, key): + return message.getheaders(key) + + +linux_py2_ascii = ( + platform.system() == 'Linux' and + six.PY2 +) + +rmtree_safe = str if linux_py2_ascii else lambda x: x +"""Workaround for http://bugs.python.org/issue24672""" diff --git a/venv/lib/python3.7/site-packages/setuptools/py31compat.py b/venv/lib/python3.7/site-packages/setuptools/py31compat.py new file mode 100644 index 0000000..1a0705e --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/py31compat.py @@ -0,0 +1,32 @@ +__all__ = [] + +__metaclass__ = type + + +try: + # Python >=3.2 + from tempfile import TemporaryDirectory +except ImportError: + import shutil + import tempfile + + class TemporaryDirectory: + """ + Very simple temporary directory context manager. + Will try to delete afterward, but will also ignore OS and similar + errors on deletion. + """ + + def __init__(self): + self.name = None # Handle mkdtemp raising an exception + self.name = tempfile.mkdtemp() + + def __enter__(self): + return self.name + + def __exit__(self, exctype, excvalue, exctrace): + try: + shutil.rmtree(self.name, True) + except OSError: # removal errors are not the only possible + pass + self.name = None diff --git a/venv/lib/python3.7/site-packages/setuptools/py33compat.py b/venv/lib/python3.7/site-packages/setuptools/py33compat.py new file mode 100644 index 0000000..87cf539 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/py33compat.py @@ -0,0 +1,55 @@ +import dis +import array +import collections + +try: + import html +except ImportError: + html = None + +from setuptools.extern import six +from setuptools.extern.six.moves import html_parser + +__metaclass__ = type + +OpArg = collections.namedtuple('OpArg', 'opcode arg') + + +class Bytecode_compat: + def __init__(self, code): + self.code = code + + def __iter__(self): + """Yield '(op,arg)' pair for each operation in code object 'code'""" + + bytes = array.array('b', self.code.co_code) + eof = len(self.code.co_code) + + ptr = 0 + extended_arg = 0 + + while ptr < eof: + + op = bytes[ptr] + + if op >= dis.HAVE_ARGUMENT: + + arg = bytes[ptr + 1] + bytes[ptr + 2] * 256 + extended_arg + ptr += 3 + + if op == dis.EXTENDED_ARG: + long_type = six.integer_types[-1] + extended_arg = arg * long_type(65536) + continue + + else: + arg = None + ptr += 1 + + yield OpArg(op, arg) + + +Bytecode = getattr(dis, 'Bytecode', Bytecode_compat) + + +unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape) diff --git a/venv/lib/python3.7/site-packages/setuptools/py36compat.py b/venv/lib/python3.7/site-packages/setuptools/py36compat.py new file mode 100644 index 0000000..f527969 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/py36compat.py @@ -0,0 +1,82 @@ +import sys +from distutils.errors import DistutilsOptionError +from distutils.util import strtobool +from distutils.debug import DEBUG + + +class Distribution_parse_config_files: + """ + Mix-in providing forward-compatibility for functionality to be + included by default on Python 3.7. + + Do not edit the code in this class except to update functionality + as implemented in distutils. + """ + def parse_config_files(self, filenames=None): + from configparser import ConfigParser + + # Ignore install directory options if we have a venv + if sys.prefix != sys.base_prefix: + ignore_options = [ + 'install-base', 'install-platbase', 'install-lib', + 'install-platlib', 'install-purelib', 'install-headers', + 'install-scripts', 'install-data', 'prefix', 'exec-prefix', + 'home', 'user', 'root'] + else: + ignore_options = [] + + ignore_options = frozenset(ignore_options) + + if filenames is None: + filenames = self.find_config_files() + + if DEBUG: + self.announce("Distribution.parse_config_files():") + + parser = ConfigParser(interpolation=None) + for filename in filenames: + if DEBUG: + self.announce(" reading %s" % filename) + parser.read(filename) + for section in parser.sections(): + options = parser.options(section) + opt_dict = self.get_option_dict(section) + + for opt in options: + if opt != '__name__' and opt not in ignore_options: + val = parser.get(section,opt) + opt = opt.replace('-', '_') + opt_dict[opt] = (filename, val) + + # Make the ConfigParser forget everything (so we retain + # the original filenames that options come from) + parser.__init__() + + # If there was a "global" section in the config file, use it + # to set Distribution options. + + if 'global' in self.command_options: + for (opt, (src, val)) in self.command_options['global'].items(): + alias = self.negative_opt.get(opt) + try: + if alias: + setattr(self, alias, not strtobool(val)) + elif opt in ('verbose', 'dry_run'): # ugh! + setattr(self, opt, strtobool(val)) + else: + setattr(self, opt, val) + except ValueError as msg: + raise DistutilsOptionError(msg) + + +if sys.version_info < (3,): + # Python 2 behavior is sufficient + class Distribution_parse_config_files: + pass + + +if False: + # When updated behavior is available upstream, + # disable override here. + class Distribution_parse_config_files: + pass diff --git a/venv/lib/python3.7/site-packages/setuptools/sandbox.py b/venv/lib/python3.7/site-packages/setuptools/sandbox.py new file mode 100644 index 0000000..685f3f7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/sandbox.py @@ -0,0 +1,491 @@ +import os +import sys +import tempfile +import operator +import functools +import itertools +import re +import contextlib +import pickle +import textwrap + +from setuptools.extern import six +from setuptools.extern.six.moves import builtins, map + +import pkg_resources.py31compat + +if sys.platform.startswith('java'): + import org.python.modules.posix.PosixModule as _os +else: + _os = sys.modules[os.name] +try: + _file = file +except NameError: + _file = None +_open = open +from distutils.errors import DistutilsError +from pkg_resources import working_set + + +__all__ = [ + "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", +] + + +def _execfile(filename, globals, locals=None): + """ + Python 3 implementation of execfile. + """ + mode = 'rb' + with open(filename, mode) as stream: + script = stream.read() + if locals is None: + locals = globals + code = compile(script, filename, 'exec') + exec(code, globals, locals) + + +@contextlib.contextmanager +def save_argv(repl=None): + saved = sys.argv[:] + if repl is not None: + sys.argv[:] = repl + try: + yield saved + finally: + sys.argv[:] = saved + + +@contextlib.contextmanager +def save_path(): + saved = sys.path[:] + try: + yield saved + finally: + sys.path[:] = saved + + +@contextlib.contextmanager +def override_temp(replacement): + """ + Monkey-patch tempfile.tempdir with replacement, ensuring it exists + """ + pkg_resources.py31compat.makedirs(replacement, exist_ok=True) + + saved = tempfile.tempdir + + tempfile.tempdir = replacement + + try: + yield + finally: + tempfile.tempdir = saved + + +@contextlib.contextmanager +def pushd(target): + saved = os.getcwd() + os.chdir(target) + try: + yield saved + finally: + os.chdir(saved) + + +class UnpickleableException(Exception): + """ + An exception representing another Exception that could not be pickled. + """ + + @staticmethod + def dump(type, exc): + """ + Always return a dumped (pickled) type and exc. If exc can't be pickled, + wrap it in UnpickleableException first. + """ + try: + return pickle.dumps(type), pickle.dumps(exc) + except Exception: + # get UnpickleableException inside the sandbox + from setuptools.sandbox import UnpickleableException as cls + return cls.dump(cls, cls(repr(exc))) + + +class ExceptionSaver: + """ + A Context Manager that will save an exception, serialized, and restore it + later. + """ + + def __enter__(self): + return self + + def __exit__(self, type, exc, tb): + if not exc: + return + + # dump the exception + self._saved = UnpickleableException.dump(type, exc) + self._tb = tb + + # suppress the exception + return True + + def resume(self): + "restore and re-raise any exception" + + if '_saved' not in vars(self): + return + + type, exc = map(pickle.loads, self._saved) + six.reraise(type, exc, self._tb) + + +@contextlib.contextmanager +def save_modules(): + """ + Context in which imported modules are saved. + + Translates exceptions internal to the context into the equivalent exception + outside the context. + """ + saved = sys.modules.copy() + with ExceptionSaver() as saved_exc: + yield saved + + sys.modules.update(saved) + # remove any modules imported since + del_modules = ( + mod_name for mod_name in sys.modules + if mod_name not in saved + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ) + _clear_modules(del_modules) + + saved_exc.resume() + + +def _clear_modules(module_names): + for mod_name in list(module_names): + del sys.modules[mod_name] + + +@contextlib.contextmanager +def save_pkg_resources_state(): + saved = pkg_resources.__getstate__() + try: + yield saved + finally: + pkg_resources.__setstate__(saved) + + +@contextlib.contextmanager +def setup_context(setup_dir): + temp_dir = os.path.join(setup_dir, 'temp') + with save_pkg_resources_state(): + with save_modules(): + hide_setuptools() + with save_path(): + with save_argv(): + with override_temp(temp_dir): + with pushd(setup_dir): + # ensure setuptools commands are available + __import__('setuptools') + yield + + +def _needs_hiding(mod_name): + """ + >>> _needs_hiding('setuptools') + True + >>> _needs_hiding('pkg_resources') + True + >>> _needs_hiding('setuptools_plugin') + False + >>> _needs_hiding('setuptools.__init__') + True + >>> _needs_hiding('distutils') + True + >>> _needs_hiding('os') + False + >>> _needs_hiding('Cython') + True + """ + pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)') + return bool(pattern.match(mod_name)) + + +def hide_setuptools(): + """ + Remove references to setuptools' modules from sys.modules to allow the + invocation to import the most appropriate setuptools. This technique is + necessary to avoid issues such as #315 where setuptools upgrading itself + would fail to find a function declared in the metadata. + """ + modules = filter(_needs_hiding, sys.modules) + _clear_modules(modules) + + +def run_setup(setup_script, args): + """Run a distutils setup script, sandboxed in its directory""" + setup_dir = os.path.abspath(os.path.dirname(setup_script)) + with setup_context(setup_dir): + try: + sys.argv[:] = [setup_script] + list(args) + sys.path.insert(0, setup_dir) + # reset to include setup dir, w/clean callback list + working_set.__init__() + working_set.callbacks.append(lambda dist: dist.activate()) + + # __file__ should be a byte string on Python 2 (#712) + dunder_file = ( + setup_script + if isinstance(setup_script, str) else + setup_script.encode(sys.getfilesystemencoding()) + ) + + with DirectorySandbox(setup_dir): + ns = dict(__file__=dunder_file, __name__='__main__') + _execfile(setup_script, ns) + except SystemExit as v: + if v.args and v.args[0]: + raise + # Normal exit, just return + + +class AbstractSandbox: + """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" + + _active = False + + def __init__(self): + self._attrs = [ + name for name in dir(_os) + if not name.startswith('_') and hasattr(self, name) + ] + + def _copy(self, source): + for name in self._attrs: + setattr(os, name, getattr(source, name)) + + def __enter__(self): + self._copy(self) + if _file: + builtins.file = self._file + builtins.open = self._open + self._active = True + + def __exit__(self, exc_type, exc_value, traceback): + self._active = False + if _file: + builtins.file = _file + builtins.open = _open + self._copy(_os) + + def run(self, func): + """Run 'func' under os sandboxing""" + with self: + return func() + + def _mk_dual_path_wrapper(name): + original = getattr(_os, name) + + def wrap(self, src, dst, *args, **kw): + if self._active: + src, dst = self._remap_pair(name, src, dst, *args, **kw) + return original(src, dst, *args, **kw) + + return wrap + + for name in ["rename", "link", "symlink"]: + if hasattr(_os, name): + locals()[name] = _mk_dual_path_wrapper(name) + + def _mk_single_path_wrapper(name, original=None): + original = original or getattr(_os, name) + + def wrap(self, path, *args, **kw): + if self._active: + path = self._remap_input(name, path, *args, **kw) + return original(path, *args, **kw) + + return wrap + + if _file: + _file = _mk_single_path_wrapper('file', _file) + _open = _mk_single_path_wrapper('open', _open) + for name in [ + "stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir", + "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", + "startfile", "mkfifo", "mknod", "pathconf", "access" + ]: + if hasattr(_os, name): + locals()[name] = _mk_single_path_wrapper(name) + + def _mk_single_with_return(name): + original = getattr(_os, name) + + def wrap(self, path, *args, **kw): + if self._active: + path = self._remap_input(name, path, *args, **kw) + return self._remap_output(name, original(path, *args, **kw)) + return original(path, *args, **kw) + + return wrap + + for name in ['readlink', 'tempnam']: + if hasattr(_os, name): + locals()[name] = _mk_single_with_return(name) + + def _mk_query(name): + original = getattr(_os, name) + + def wrap(self, *args, **kw): + retval = original(*args, **kw) + if self._active: + return self._remap_output(name, retval) + return retval + + return wrap + + for name in ['getcwd', 'tmpnam']: + if hasattr(_os, name): + locals()[name] = _mk_query(name) + + def _validate_path(self, path): + """Called to remap or validate any path, whether input or output""" + return path + + def _remap_input(self, operation, path, *args, **kw): + """Called for path inputs""" + return self._validate_path(path) + + def _remap_output(self, operation, path): + """Called for path outputs""" + return self._validate_path(path) + + def _remap_pair(self, operation, src, dst, *args, **kw): + """Called for path pairs like rename, link, and symlink operations""" + return ( + self._remap_input(operation + '-from', src, *args, **kw), + self._remap_input(operation + '-to', dst, *args, **kw) + ) + + +if hasattr(os, 'devnull'): + _EXCEPTIONS = [os.devnull,] +else: + _EXCEPTIONS = [] + + +class DirectorySandbox(AbstractSandbox): + """Restrict operations to a single subdirectory - pseudo-chroot""" + + write_ops = dict.fromkeys([ + "open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir", + "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", + ]) + + _exception_patterns = [ + # Allow lib2to3 to attempt to save a pickled grammar object (#121) + r'.*lib2to3.*\.pickle$', + ] + "exempt writing to paths that match the pattern" + + def __init__(self, sandbox, exceptions=_EXCEPTIONS): + self._sandbox = os.path.normcase(os.path.realpath(sandbox)) + self._prefix = os.path.join(self._sandbox, '') + self._exceptions = [ + os.path.normcase(os.path.realpath(path)) + for path in exceptions + ] + AbstractSandbox.__init__(self) + + def _violation(self, operation, *args, **kw): + from setuptools.sandbox import SandboxViolation + raise SandboxViolation(operation, args, kw) + + if _file: + + def _file(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("file", path, mode, *args, **kw) + return _file(path, mode, *args, **kw) + + def _open(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("open", path, mode, *args, **kw) + return _open(path, mode, *args, **kw) + + def tmpnam(self): + self._violation("tmpnam") + + def _ok(self, path): + active = self._active + try: + self._active = False + realpath = os.path.normcase(os.path.realpath(path)) + return ( + self._exempted(realpath) + or realpath == self._sandbox + or realpath.startswith(self._prefix) + ) + finally: + self._active = active + + def _exempted(self, filepath): + start_matches = ( + filepath.startswith(exception) + for exception in self._exceptions + ) + pattern_matches = ( + re.match(pattern, filepath) + for pattern in self._exception_patterns + ) + candidates = itertools.chain(start_matches, pattern_matches) + return any(candidates) + + def _remap_input(self, operation, path, *args, **kw): + """Called for path inputs""" + if operation in self.write_ops and not self._ok(path): + self._violation(operation, os.path.realpath(path), *args, **kw) + return path + + def _remap_pair(self, operation, src, dst, *args, **kw): + """Called for path pairs like rename, link, and symlink operations""" + if not self._ok(src) or not self._ok(dst): + self._violation(operation, src, dst, *args, **kw) + return (src, dst) + + def open(self, file, flags, mode=0o777, *args, **kw): + """Called for low-level os.open()""" + if flags & WRITE_FLAGS and not self._ok(file): + self._violation("os.open", file, flags, mode, *args, **kw) + return _os.open(file, flags, mode, *args, **kw) + + +WRITE_FLAGS = functools.reduce( + operator.or_, [getattr(_os, a, 0) for a in + "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()] +) + + +class SandboxViolation(DistutilsError): + """A setup script attempted to modify the filesystem outside the sandbox""" + + tmpl = textwrap.dedent(""" + SandboxViolation: {cmd}{args!r} {kwargs} + + The package setup script has attempted to modify files on your system + that are not within the EasyInstall build area, and has been aborted. + + This package cannot be safely installed by EasyInstall, and may not + support alternate installation locations even if you run its setup + script by hand. Please inform the package's author and the EasyInstall + maintainers to find out if a fix or workaround is available. + """).lstrip() + + def __str__(self): + cmd, args, kwargs = self.args + return self.tmpl.format(**locals()) diff --git a/venv/lib/python3.7/site-packages/setuptools/script (dev).tmpl b/venv/lib/python3.7/site-packages/setuptools/script (dev).tmpl new file mode 100644 index 0000000..39a24b0 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/script (dev).tmpl @@ -0,0 +1,6 @@ +# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r +__requires__ = %(spec)r +__import__('pkg_resources').require(%(spec)r) +__file__ = %(dev_path)r +with open(__file__) as f: + exec(compile(f.read(), __file__, 'exec')) diff --git a/venv/lib/python3.7/site-packages/setuptools/script.tmpl b/venv/lib/python3.7/site-packages/setuptools/script.tmpl new file mode 100644 index 0000000..ff5efbc --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/script.tmpl @@ -0,0 +1,3 @@ +# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r +__requires__ = %(spec)r +__import__('pkg_resources').run_script(%(spec)r, %(script_name)r) diff --git a/venv/lib/python3.7/site-packages/setuptools/site-patch.py b/venv/lib/python3.7/site-packages/setuptools/site-patch.py new file mode 100644 index 0000000..40b00de --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/site-patch.py @@ -0,0 +1,74 @@ +def __boot(): + import sys + import os + PYTHONPATH = os.environ.get('PYTHONPATH') + if PYTHONPATH is None or (sys.platform == 'win32' and not PYTHONPATH): + PYTHONPATH = [] + else: + PYTHONPATH = PYTHONPATH.split(os.pathsep) + + pic = getattr(sys, 'path_importer_cache', {}) + stdpath = sys.path[len(PYTHONPATH):] + mydir = os.path.dirname(__file__) + + for item in stdpath: + if item == mydir or not item: + continue # skip if current dir. on Windows, or my own directory + importer = pic.get(item) + if importer is not None: + loader = importer.find_module('site') + if loader is not None: + # This should actually reload the current module + loader.load_module('site') + break + else: + try: + import imp # Avoid import loop in Python 3 + stream, path, descr = imp.find_module('site', [item]) + except ImportError: + continue + if stream is None: + continue + try: + # This should actually reload the current module + imp.load_module('site', stream, path, descr) + finally: + stream.close() + break + else: + raise ImportError("Couldn't find the real 'site' module") + + known_paths = dict([(makepath(item)[1], 1) for item in sys.path]) # 2.2 comp + + oldpos = getattr(sys, '__egginsert', 0) # save old insertion position + sys.__egginsert = 0 # and reset the current one + + for item in PYTHONPATH: + addsitedir(item) + + sys.__egginsert += oldpos # restore effective old position + + d, nd = makepath(stdpath[0]) + insert_at = None + new_path = [] + + for item in sys.path: + p, np = makepath(item) + + if np == nd and insert_at is None: + # We've hit the first 'system' path entry, so added entries go here + insert_at = len(new_path) + + if np in known_paths or insert_at is None: + new_path.append(item) + else: + # new path after the insert point, back-insert it + new_path.insert(insert_at, item) + insert_at += 1 + + sys.path[:] = new_path + + +if __name__ == 'site': + __boot() + del __boot diff --git a/venv/lib/python3.7/site-packages/setuptools/ssl_support.py b/venv/lib/python3.7/site-packages/setuptools/ssl_support.py new file mode 100644 index 0000000..6362f1f --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/ssl_support.py @@ -0,0 +1,260 @@ +import os +import socket +import atexit +import re +import functools + +from setuptools.extern.six.moves import urllib, http_client, map, filter + +from pkg_resources import ResolutionError, ExtractionError + +try: + import ssl +except ImportError: + ssl = None + +__all__ = [ + 'VerifyingHTTPSHandler', 'find_ca_bundle', 'is_available', 'cert_paths', + 'opener_for' +] + +cert_paths = """ +/etc/pki/tls/certs/ca-bundle.crt +/etc/ssl/certs/ca-certificates.crt +/usr/share/ssl/certs/ca-bundle.crt +/usr/local/share/certs/ca-root.crt +/etc/ssl/cert.pem +/System/Library/OpenSSL/certs/cert.pem +/usr/local/share/certs/ca-root-nss.crt +/etc/ssl/ca-bundle.pem +""".strip().split() + +try: + HTTPSHandler = urllib.request.HTTPSHandler + HTTPSConnection = http_client.HTTPSConnection +except AttributeError: + HTTPSHandler = HTTPSConnection = object + +is_available = ssl is not None and object not in (HTTPSHandler, HTTPSConnection) + + +try: + from ssl import CertificateError, match_hostname +except ImportError: + try: + from backports.ssl_match_hostname import CertificateError + from backports.ssl_match_hostname import match_hostname + except ImportError: + CertificateError = None + match_hostname = None + +if not CertificateError: + + class CertificateError(ValueError): + pass + + +if not match_hostname: + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r'.') + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +class VerifyingHTTPSHandler(HTTPSHandler): + """Simple verifying handler: no auth, subclasses, timeouts, etc.""" + + def __init__(self, ca_bundle): + self.ca_bundle = ca_bundle + HTTPSHandler.__init__(self) + + def https_open(self, req): + return self.do_open( + lambda host, **kw: VerifyingHTTPSConn(host, self.ca_bundle, **kw), req + ) + + +class VerifyingHTTPSConn(HTTPSConnection): + """Simple verifying connection: no auth, subclasses, timeouts, etc.""" + + def __init__(self, host, ca_bundle, **kw): + HTTPSConnection.__init__(self, host, **kw) + self.ca_bundle = ca_bundle + + def connect(self): + sock = socket.create_connection( + (self.host, self.port), getattr(self, 'source_address', None) + ) + + # Handle the socket if a (proxy) tunnel is present + if hasattr(self, '_tunnel') and getattr(self, '_tunnel_host', None): + self.sock = sock + self._tunnel() + # http://bugs.python.org/issue7776: Python>=3.4.1 and >=2.7.7 + # change self.host to mean the proxy server host when tunneling is + # being used. Adapt, since we are interested in the destination + # host for the match_hostname() comparison. + actual_host = self._tunnel_host + else: + actual_host = self.host + + if hasattr(ssl, 'create_default_context'): + ctx = ssl.create_default_context(cafile=self.ca_bundle) + self.sock = ctx.wrap_socket(sock, server_hostname=actual_host) + else: + # This is for python < 2.7.9 and < 3.4? + self.sock = ssl.wrap_socket( + sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle + ) + try: + match_hostname(self.sock.getpeercert(), actual_host) + except CertificateError: + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + +def opener_for(ca_bundle=None): + """Get a urlopen() replacement that uses ca_bundle for verification""" + return urllib.request.build_opener( + VerifyingHTTPSHandler(ca_bundle or find_ca_bundle()) + ).open + + +# from jaraco.functools +def once(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + if not hasattr(func, 'always_returns'): + func.always_returns = func(*args, **kwargs) + return func.always_returns + return wrapper + + +@once +def get_win_certfile(): + try: + import wincertstore + except ImportError: + return None + + class CertFile(wincertstore.CertFile): + def __init__(self): + super(CertFile, self).__init__() + atexit.register(self.close) + + def close(self): + try: + super(CertFile, self).close() + except OSError: + pass + + _wincerts = CertFile() + _wincerts.addstore('CA') + _wincerts.addstore('ROOT') + return _wincerts.name + + +def find_ca_bundle(): + """Return an existing CA bundle path, or None""" + extant_cert_paths = filter(os.path.isfile, cert_paths) + return ( + get_win_certfile() + or next(extant_cert_paths, None) + or _certifi_where() + ) + + +def _certifi_where(): + try: + return __import__('certifi').where() + except (ImportError, ResolutionError, ExtractionError): + pass diff --git a/venv/lib/python3.7/site-packages/setuptools/unicode_utils.py b/venv/lib/python3.7/site-packages/setuptools/unicode_utils.py new file mode 100644 index 0000000..7c63efd --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/unicode_utils.py @@ -0,0 +1,44 @@ +import unicodedata +import sys + +from setuptools.extern import six + + +# HFS Plus uses decomposed UTF-8 +def decompose(path): + if isinstance(path, six.text_type): + return unicodedata.normalize('NFD', path) + try: + path = path.decode('utf-8') + path = unicodedata.normalize('NFD', path) + path = path.encode('utf-8') + except UnicodeError: + pass # Not UTF-8 + return path + + +def filesys_decode(path): + """ + Ensure that the given path is decoded, + NONE when no expected encoding works + """ + + if isinstance(path, six.text_type): + return path + + fs_enc = sys.getfilesystemencoding() or 'utf-8' + candidates = fs_enc, 'utf-8' + + for enc in candidates: + try: + return path.decode(enc) + except UnicodeDecodeError: + continue + + +def try_encode(string, enc): + "turn unicode encoding into a functional routine" + try: + return string.encode(enc) + except UnicodeEncodeError: + return None diff --git a/venv/lib/python3.7/site-packages/setuptools/version.py b/venv/lib/python3.7/site-packages/setuptools/version.py new file mode 100644 index 0000000..95e1869 --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/version.py @@ -0,0 +1,6 @@ +import pkg_resources + +try: + __version__ = pkg_resources.get_distribution('setuptools').version +except Exception: + __version__ = 'unknown' diff --git a/venv/lib/python3.7/site-packages/setuptools/wheel.py b/venv/lib/python3.7/site-packages/setuptools/wheel.py new file mode 100644 index 0000000..95a794a --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/wheel.py @@ -0,0 +1,210 @@ +"""Wheels support.""" + +from distutils.util import get_platform +import email +import itertools +import os +import posixpath +import re +import zipfile + +from pkg_resources import Distribution, PathMetadata, parse_version +from setuptools.extern.packaging.utils import canonicalize_name +from setuptools.extern.six import PY3 +from setuptools import Distribution as SetuptoolsDistribution +from setuptools import pep425tags +from setuptools.command.egg_info import write_requirements + + +__metaclass__ = type + + +WHEEL_NAME = re.compile( + r"""^(?P.+?)-(?P\d.*?) + ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) + )\.whl$""", + re.VERBOSE).match + +NAMESPACE_PACKAGE_INIT = '''\ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) +''' + + +def unpack(src_dir, dst_dir): + '''Move everything under `src_dir` to `dst_dir`, and delete the former.''' + for dirpath, dirnames, filenames in os.walk(src_dir): + subdir = os.path.relpath(dirpath, src_dir) + for f in filenames: + src = os.path.join(dirpath, f) + dst = os.path.join(dst_dir, subdir, f) + os.renames(src, dst) + for n, d in reversed(list(enumerate(dirnames))): + src = os.path.join(dirpath, d) + dst = os.path.join(dst_dir, subdir, d) + if not os.path.exists(dst): + # Directory does not exist in destination, + # rename it and prune it from os.walk list. + os.renames(src, dst) + del dirnames[n] + # Cleanup. + for dirpath, dirnames, filenames in os.walk(src_dir, topdown=True): + assert not filenames + os.rmdir(dirpath) + + +class Wheel: + + def __init__(self, filename): + match = WHEEL_NAME(os.path.basename(filename)) + if match is None: + raise ValueError('invalid wheel name: %r' % filename) + self.filename = filename + for k, v in match.groupdict().items(): + setattr(self, k, v) + + def tags(self): + '''List tags (py_version, abi, platform) supported by this wheel.''' + return itertools.product( + self.py_version.split('.'), + self.abi.split('.'), + self.platform.split('.'), + ) + + def is_compatible(self): + '''Is the wheel is compatible with the current platform?''' + supported_tags = pep425tags.get_supported() + return next((True for t in self.tags() if t in supported_tags), False) + + def egg_name(self): + return Distribution( + project_name=self.project_name, version=self.version, + platform=(None if self.platform == 'any' else get_platform()), + ).egg_name() + '.egg' + + def get_dist_info(self, zf): + # find the correct name of the .dist-info dir in the wheel file + for member in zf.namelist(): + dirname = posixpath.dirname(member) + if (dirname.endswith('.dist-info') and + canonicalize_name(dirname).startswith( + canonicalize_name(self.project_name))): + return dirname + raise ValueError("unsupported wheel format. .dist-info not found") + + def install_as_egg(self, destination_eggdir): + '''Install wheel as an egg directory.''' + with zipfile.ZipFile(self.filename) as zf: + self._install_as_egg(destination_eggdir, zf) + + def _install_as_egg(self, destination_eggdir, zf): + dist_basename = '%s-%s' % (self.project_name, self.version) + dist_info = self.get_dist_info(zf) + dist_data = '%s.data' % dist_basename + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + + self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) + self._move_data_entries(destination_eggdir, dist_data) + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): + def get_metadata(name): + with zf.open(posixpath.join(dist_info, name)) as fp: + value = fp.read().decode('utf-8') if PY3 else fp.read() + return email.parser.Parser().parsestr(value) + + wheel_metadata = get_metadata('WHEEL') + # Check wheel format version is supported. + wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) + wheel_v1 = ( + parse_version('1.0') <= wheel_version < parse_version('2.0dev0') + ) + if not wheel_v1: + raise ValueError( + 'unsupported wheel format version: %s' % wheel_version) + # Extract to target directory. + os.mkdir(destination_eggdir) + zf.extractall(destination_eggdir) + # Convert metadata. + dist_info = os.path.join(destination_eggdir, dist_info) + dist = Distribution.from_location( + destination_eggdir, dist_info, + metadata=PathMetadata(destination_eggdir, dist_info), + ) + + # Note: Evaluate and strip markers now, + # as it's difficult to convert back from the syntax: + # foobar; "linux" in sys_platform and extra == 'test' + def raw_req(req): + req.marker = None + return str(req) + install_requires = list(sorted(map(raw_req, dist.requires()))) + extras_require = { + extra: sorted( + req + for req in map(raw_req, dist.requires((extra,))) + if req not in install_requires + ) + for extra in dist.extras + } + os.rename(dist_info, egg_info) + os.rename( + os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO'), + ) + setup_dist = SetuptoolsDistribution( + attrs=dict( + install_requires=install_requires, + extras_require=extras_require, + ), + ) + write_requirements( + setup_dist.get_command_obj('egg_info'), + None, + os.path.join(egg_info, 'requires.txt'), + ) + + @staticmethod + def _move_data_entries(destination_eggdir, dist_data): + """Move data entries to their correct location.""" + dist_data = os.path.join(destination_eggdir, dist_data) + dist_data_scripts = os.path.join(dist_data, 'scripts') + if os.path.exists(dist_data_scripts): + egg_info_scripts = os.path.join( + destination_eggdir, 'EGG-INFO', 'scripts') + os.mkdir(egg_info_scripts) + for entry in os.listdir(dist_data_scripts): + # Remove bytecode, as it's not properly handled + # during easy_install scripts install phase. + if entry.endswith('.pyc'): + os.unlink(os.path.join(dist_data_scripts, entry)) + else: + os.rename( + os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry), + ) + os.rmdir(dist_data_scripts) + for subdir in filter(os.path.exists, ( + os.path.join(dist_data, d) + for d in ('data', 'headers', 'purelib', 'platlib') + )): + unpack(subdir, destination_eggdir) + if os.path.exists(dist_data): + os.rmdir(dist_data) + + @staticmethod + def _fix_namespace_packages(egg_info, destination_eggdir): + namespace_packages = os.path.join( + egg_info, 'namespace_packages.txt') + if os.path.exists(namespace_packages): + with open(namespace_packages) as fp: + namespace_packages = fp.read().split() + for mod in namespace_packages: + mod_dir = os.path.join(destination_eggdir, *mod.split('.')) + mod_init = os.path.join(mod_dir, '__init__.py') + if os.path.exists(mod_dir) and not os.path.exists(mod_init): + with open(mod_init, 'w') as fp: + fp.write(NAMESPACE_PACKAGE_INIT) diff --git a/venv/lib/python3.7/site-packages/setuptools/windows_support.py b/venv/lib/python3.7/site-packages/setuptools/windows_support.py new file mode 100644 index 0000000..cb977cf --- /dev/null +++ b/venv/lib/python3.7/site-packages/setuptools/windows_support.py @@ -0,0 +1,29 @@ +import platform +import ctypes + + +def windows_only(func): + if platform.system() != 'Windows': + return lambda *args, **kwargs: None + return func + + +@windows_only +def hide_file(path): + """ + Set the hidden attribute on a file or directory. + + From http://stackoverflow.com/questions/19622133/ + + `path` must be text. + """ + __import__('ctypes.wintypes') + SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW + SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD + SetFileAttributes.restype = ctypes.wintypes.BOOL + + FILE_ATTRIBUTE_HIDDEN = 0x02 + + ret = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) + if not ret: + raise ctypes.WinError() diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..09c2c99 --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst @@ -0,0 +1,27 @@ +.. image:: http://img.shields.io/pypi/v/six.svg + :target: https://pypi.python.org/pypi/six + +.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master + :target: https://travis-ci.org/benjaminp/six + +.. image:: http://img.shields.io/badge/license-MIT-green.svg + :target: https://github.com/benjaminp/six/blob/master/LICENSE + +Six is a Python 2 and 3 compatibility library. It provides utility functions +for smoothing over the differences between the Python versions with the goal of +writing Python code that is compatible on both Python versions. See the +documentation for more information on what is provided. + +Six supports every Python version since 2.6. It is contained in only one Python +file, so it can be easily copied into your project. (The copyright and license +notice must be retained.) + +Online documentation is at http://six.rtfd.org. + +Bugs can be reported to https://github.com/benjaminp/six. The code can also +be found there. + +For questions about six or porting in general, email the python-porting mailing +list: https://mail.python.org/mailman/listinfo/python-porting + + diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/INSTALLER b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/METADATA b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/METADATA new file mode 100644 index 0000000..04e93dc --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/METADATA @@ -0,0 +1,43 @@ +Metadata-Version: 2.0 +Name: six +Version: 1.11.0 +Summary: Python 2 and 3 compatibility utilities +Home-page: http://pypi.python.org/pypi/six/ +Author: Benjamin Peterson +Author-email: benjamin@python.org +License: MIT +Platform: UNKNOWN +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Utilities + +.. image:: http://img.shields.io/pypi/v/six.svg + :target: https://pypi.python.org/pypi/six + +.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master + :target: https://travis-ci.org/benjaminp/six + +.. image:: http://img.shields.io/badge/license-MIT-green.svg + :target: https://github.com/benjaminp/six/blob/master/LICENSE + +Six is a Python 2 and 3 compatibility library. It provides utility functions +for smoothing over the differences between the Python versions with the goal of +writing Python code that is compatible on both Python versions. See the +documentation for more information on what is provided. + +Six supports every Python version since 2.6. It is contained in only one Python +file, so it can be easily copied into your project. (The copyright and license +notice must be retained.) + +Online documentation is at http://six.rtfd.org. + +Bugs can be reported to https://github.com/benjaminp/six. The code can also +be found there. + +For questions about six or porting in general, email the python-porting mailing +list: https://mail.python.org/mailman/listinfo/python-porting + + diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/RECORD b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/RECORD new file mode 100644 index 0000000..5ab3c76 --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/RECORD @@ -0,0 +1,9 @@ +__pycache__/six.cpython-37.pyc,, +six-1.11.0.dist-info/DESCRIPTION.rst,sha256=gPBoq1Ruc1QDWyLeXPlieL3F-XZz1_WXB-5gctCfg-A,1098 +six-1.11.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +six-1.11.0.dist-info/METADATA,sha256=06nZXaDYN3vnC-pmUjhkECYFH_a--ywvcPIpUdNeH1o,1607 +six-1.11.0.dist-info/RECORD,, +six-1.11.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +six-1.11.0.dist-info/metadata.json,sha256=ac3f4f7MpSHSnZ1SqhHCwsL7FGWMG0gBEb0hhS2eSSM,703 +six-1.11.0.dist-info/top_level.txt,sha256=_iVH_iYEtEXnD8nYGQYpYFUvkUW9sEO1GYbkeKSAais,4 +six.py,sha256=A08MPb-Gi9FfInI3IW7HimXFmEH2T2IPzHgDvdhZPRA,30888 diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/WHEEL b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/WHEEL new file mode 100644 index 0000000..8b6dd1b --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/metadata.json b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/metadata.json new file mode 100644 index 0000000..2c7fcea --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Libraries", "Topic :: Utilities"], "extensions": {"python.details": {"contacts": [{"email": "benjamin@python.org", "name": "Benjamin Peterson", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://pypi.python.org/pypi/six/"}}}, "generator": "bdist_wheel (0.29.0)", "license": "MIT", "metadata_version": "2.0", "name": "six", "summary": "Python 2 and 3 compatibility utilities", "test_requires": [{"requires": ["pytest"]}], "version": "1.11.0"} \ No newline at end of file diff --git a/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/top_level.txt b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/top_level.txt new file mode 100644 index 0000000..ffe2fce --- /dev/null +++ b/venv/lib/python3.7/site-packages/six-1.11.0.dist-info/top_level.txt @@ -0,0 +1 @@ +six diff --git a/venv/lib/python3.7/site-packages/six.py b/venv/lib/python3.7/site-packages/six.py new file mode 100644 index 0000000..6bf4fd3 --- /dev/null +++ b/venv/lib/python3.7/site-packages/six.py @@ -0,0 +1,891 @@ +# Copyright (c) 2010-2017 Benjamin Peterson +# +# 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. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.11.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + try: + if from_value is None: + raise value + raise value from from_value + finally: + value = None +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/INSTALLER b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/LICENSE.txt b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/LICENSE.txt new file mode 100644 index 0000000..c3441e6 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/LICENSE.txt @@ -0,0 +1,22 @@ +"wheel" copyright (c) 2012-2014 Daniel Holth and +contributors. + +The MIT License + +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/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/METADATA b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/METADATA new file mode 100644 index 0000000..cef8071 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.1 +Name: wheel +Version: 0.32.3 +Summary: A built-package format for Python. +Home-page: https://github.com/pypa/wheel +Author: Daniel Holth +Author-email: dholth@fastmail.fm +Maintainer: Alex Grönholm +Maintainer-email: alex.gronholm@nextday.fi +License: MIT +Project-URL: Issue Tracker, https://github.com/pypa/wheel/issues +Project-URL: Documentation, https://wheel.readthedocs.io/ +Project-URL: Changelog, https://wheel.readthedocs.io/en/stable/news.html +Keywords: wheel,packaging +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Topic :: System :: Archiving :: Packaging +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +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 +Classifier: Programming Language :: Python :: 3.7 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Provides-Extra: test +Requires-Dist: pytest (>=3.0.0) ; extra == 'test' +Requires-Dist: pytest-cov ; extra == 'test' + +wheel +===== + +This library is the reference implementation of the Python wheel packaging +standard, as defined in `PEP 427`_. + +It has two different roles: + +#. A setuptools_ extension for building wheels that provides the + ``bdist_wheel`` setuptools command +#. A command line tool for working with wheel files + +It should be noted that wheel is **not** intended to be used as a library, and +as such there is no stable, public API. + +.. _PEP 427: https://www.python.org/dev/peps/pep-0427/ +.. _setuptools: https://pypi.org/project/setuptools/ + + +Code of Conduct +--------------- + +Everyone interacting in the wheel project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_. + +.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ + + diff --git a/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/RECORD b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/RECORD new file mode 100644 index 0000000..36dfe9c --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/RECORD @@ -0,0 +1,34 @@ +wheel/__init__.py,sha256=AgAP7YAmbZj84_nCH9za8R0UXHylXdfKNSyg5g1xLZ4,96 +wheel/__main__.py,sha256=lF-YLO4hdQmoWuh4eWZd8YL1U95RSdm76sNLBXa0vjE,417 +wheel/bdist_wheel.py,sha256=0hM63ZD01ATEMRAr6t0mbmhf2y8pbRkMnWGioed9n-o,14627 +wheel/metadata.py,sha256=a3QgT8C4QOvrS-8RFdNCn7XWUUqEZpcHelmI8XLTDnY,4691 +wheel/pep425tags.py,sha256=Jdjbnq17kqwPRKJCMb2E1VccNgnC3H6iQL7VGaxkPao,5908 +wheel/pkginfo.py,sha256=GR76kupQzn1x9sKDaXuE6B6FsZ4OkfRtG7pndlXPvQ4,1257 +wheel/util.py,sha256=bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI,859 +wheel/wheelfile.py,sha256=mxv8kcRvXMME4xQstpiiQv59bHc42edS6z8kDAco6iw,6990 +wheel/cli/__init__.py,sha256=DsCXkrL_jsTHoR0nhmcwkrlNdkaXw0uV0NL-yYoYQuU,2461 +wheel/cli/convert.py,sha256=me0l6G4gSw-EBVhzjSr7yWYWBp9spMz7mnXlyJTiXso,9497 +wheel/cli/install.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +wheel/cli/pack.py,sha256=RViq4mnUk8s7R5kcrgX0XntX2zalDTeoTSBzLk31SaI,2145 +wheel/cli/unpack.py,sha256=0VWzT7U_xyenTPwEVavxqvdee93GPvAFHnR3Uu91aRc,673 +wheel-0.32.3.dist-info/LICENSE.txt,sha256=zKniDGrx_Pv2lAjzd3aShsvuvN7TNhAMm0o_NfvmNeQ,1125 +wheel-0.32.3.dist-info/METADATA,sha256=1gweIMsoaCjJWccLOuQJCZqj_cWYVM80LkUQosJ4wC8,2082 +wheel-0.32.3.dist-info/WHEEL,sha256=_wJFdOYk7i3xxT8ElOkUJvOdOvfNGbR9g-bf6UQT6sU,110 +wheel-0.32.3.dist-info/entry_points.txt,sha256=N8HbYFST3yrNQYeB2wXWBEPUhFsEtKNRPaCFGJPyqyc,108 +wheel-0.32.3.dist-info/top_level.txt,sha256=HxSBIbgEstMPe4eFawhA66Mq-QYHMopXVoAncfjb_1c,6 +wheel-0.32.3.dist-info/RECORD,, +../../../bin/wheel,sha256=6Tka3odcOULCNeygtCaH_ajc8brYzXiDJIsK18JzTAQ,254 +wheel-0.32.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +wheel/__pycache__/wheelfile.cpython-37.pyc,, +wheel/__pycache__/util.cpython-37.pyc,, +wheel/__pycache__/bdist_wheel.cpython-37.pyc,, +wheel/__pycache__/__main__.cpython-37.pyc,, +wheel/__pycache__/pep425tags.cpython-37.pyc,, +wheel/__pycache__/pkginfo.cpython-37.pyc,, +wheel/__pycache__/metadata.cpython-37.pyc,, +wheel/__pycache__/__init__.cpython-37.pyc,, +wheel/cli/__pycache__/convert.cpython-37.pyc,, +wheel/cli/__pycache__/pack.cpython-37.pyc,, +wheel/cli/__pycache__/install.cpython-37.pyc,, +wheel/cli/__pycache__/unpack.cpython-37.pyc,, +wheel/cli/__pycache__/__init__.cpython-37.pyc,, diff --git a/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/WHEEL b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/WHEEL new file mode 100644 index 0000000..c4bde30 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.3) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/entry_points.txt b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/entry_points.txt new file mode 100644 index 0000000..b27acad --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/entry_points.txt @@ -0,0 +1,6 @@ +[console_scripts] +wheel = wheel.cli:main + +[distutils.commands] +bdist_wheel = wheel.bdist_wheel:bdist_wheel + diff --git a/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/top_level.txt b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/top_level.txt new file mode 100644 index 0000000..2309722 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel-0.32.3.dist-info/top_level.txt @@ -0,0 +1 @@ +wheel diff --git a/venv/lib/python3.7/site-packages/wheel/__init__.py b/venv/lib/python3.7/site-packages/wheel/__init__.py new file mode 100644 index 0000000..6938633 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/__init__.py @@ -0,0 +1,2 @@ +# __variables__ with double-quoted values will be available in setup.py: +__version__ = "0.32.3" diff --git a/venv/lib/python3.7/site-packages/wheel/__main__.py b/venv/lib/python3.7/site-packages/wheel/__main__.py new file mode 100644 index 0000000..b3773a2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/__main__.py @@ -0,0 +1,19 @@ +""" +Wheel command line tool (enable python -m wheel syntax) +""" + +import sys + + +def main(): # needed for console script + if __package__ == '': + # To be able to run 'python wheel-0.9.whl/wheel': + import os.path + path = os.path.dirname(os.path.dirname(__file__)) + sys.path[0:0] = [path] + import wheel.cli + sys.exit(wheel.cli.main()) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py b/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py new file mode 100644 index 0000000..5796970 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/bdist_wheel.py @@ -0,0 +1,368 @@ +""" +Create a wheel (.whl) distribution. + +A wheel is a built archive format. +""" + +import os +import shutil +import sys +import re +from email.generator import Generator +from distutils.core import Command +from distutils.sysconfig import get_python_version +from distutils import log as logger +from glob import iglob +from shutil import rmtree +from warnings import warn + +import pkg_resources + +from .pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag, get_platform +from .pkginfo import write_pkg_info +from .metadata import pkginfo_to_metadata +from .wheelfile import WheelFile +from . import pep425tags +from . import __version__ as wheel_version + + +safe_name = pkg_resources.safe_name +safe_version = pkg_resources.safe_version + +PY_LIMITED_API_PATTERN = r'cp3\d' + + +def safer_name(name): + return safe_name(name).replace('-', '_') + + +def safer_version(version): + return safe_version(version).replace('-', '_') + + +class bdist_wheel(Command): + + description = 'create a wheel distribution' + + user_options = [('bdist-dir=', 'b', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('relative', None, + "build the archive using relative paths" + "(default: false)"), + ('owner=', 'u', + "Owner name used when creating a tar file" + " [default: current user]"), + ('group=', 'g', + "Group name used when creating a tar file" + " [default: current group]"), + ('universal', None, + "make a universal wheel" + " (default: false)"), + ('python-tag=', None, + "Python implementation compatibility tag" + " (default: py%s)" % get_impl_ver()[0]), + ('build-number=', None, + "Build number for this particular version. " + "As specified in PEP-0427, this must start with a digit. " + "[default: None]"), + ('py-limited-api=', None, + "Python tag (cp32|cp33|cpNN) for abi3 wheel tag" + " (default: false)"), + ] + + boolean_options = ['keep-temp', 'skip-build', 'relative', 'universal'] + + def initialize_options(self): + self.bdist_dir = None + self.data_dir = None + self.plat_name = None + self.plat_tag = None + self.format = 'zip' + self.keep_temp = False + self.dist_dir = None + self.egginfo_dir = None + self.root_is_pure = None + self.skip_build = None + self.relative = False + self.owner = None + self.group = None + self.universal = False + self.python_tag = 'py' + get_impl_ver()[0] + self.build_number = None + self.py_limited_api = False + self.plat_name_supplied = False + + def finalize_options(self): + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'wheel') + + self.data_dir = self.wheel_dist_name + '.data' + self.plat_name_supplied = self.plat_name is not None + + need_options = ('dist_dir', 'plat_name', 'skip_build') + + self.set_undefined_options('bdist', + *zip(need_options, need_options)) + + self.root_is_pure = not (self.distribution.has_ext_modules() + or self.distribution.has_c_libraries()) + + if self.py_limited_api and not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api): + raise ValueError("py-limited-api must match '%s'" % PY_LIMITED_API_PATTERN) + + # Support legacy [wheel] section for setting universal + wheel = self.distribution.get_option_dict('wheel') + if 'universal' in wheel: + # please don't define this in your global configs + logger.warn('The [wheel] section is deprecated. Use [bdist_wheel] instead.') + val = wheel['universal'][1].strip() + if val.lower() in ('1', 'true', 'yes'): + self.universal = True + + if self.build_number is not None and not self.build_number[:1].isdigit(): + raise ValueError("Build tag (build-number) must start with a digit.") + + @property + def wheel_dist_name(self): + """Return distribution full name with - replaced with _""" + components = (safer_name(self.distribution.get_name()), + safer_version(self.distribution.get_version())) + if self.build_number: + components += (self.build_number,) + return '-'.join(components) + + def get_tag(self): + # bdist sets self.plat_name if unset, we should only use it for purepy + # wheels if the user supplied it. + if self.plat_name_supplied: + plat_name = self.plat_name + elif self.root_is_pure: + plat_name = 'any' + else: + plat_name = self.plat_name or get_platform() + if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: + plat_name = 'linux_i686' + plat_name = plat_name.replace('-', '_').replace('.', '_') + + if self.root_is_pure: + if self.universal: + impl = 'py2.py3' + else: + impl = self.python_tag + tag = (impl, 'none', plat_name) + else: + impl_name = get_abbr_impl() + impl_ver = get_impl_ver() + impl = impl_name + impl_ver + # We don't work on CPython 3.1, 3.0. + if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): + impl = self.py_limited_api + abi_tag = 'abi3' + else: + abi_tag = str(get_abi_tag()).lower() + tag = (impl, abi_tag, plat_name) + supported_tags = pep425tags.get_supported( + supplied_platform=plat_name if self.plat_name_supplied else None) + # XXX switch to this alternate implementation for non-pure: + if not self.py_limited_api: + assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0]) + assert tag in supported_tags, "would build wheel with unsupported tag {}".format(tag) + return tag + + def run(self): + build_scripts = self.reinitialize_command('build_scripts') + build_scripts.executable = 'python' + + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', + reinit_subcommands=True) + install.root = self.bdist_dir + install.compile = False + install.skip_build = self.skip_build + install.warn_dir = False + + # A wheel without setuptools scripts is more cross-platform. + # Use the (undocumented) `no_ep` option to setuptools' + # install_scripts command to avoid creating entry point scripts. + install_scripts = self.reinitialize_command('install_scripts') + install_scripts.no_ep = True + + # Use a custom scheme for the archive, because we have to decide + # at installation time which scheme to use. + for key in ('headers', 'scripts', 'data', 'purelib', 'platlib'): + setattr(install, + 'install_' + key, + os.path.join(self.data_dir, key)) + + basedir_observed = '' + + if os.name == 'nt': + # win32 barfs if any of these are ''; could be '.'? + # (distutils.command.install:change_roots bug) + basedir_observed = os.path.normpath(os.path.join(self.data_dir, '..')) + self.install_libbase = self.install_lib = basedir_observed + + setattr(install, + 'install_purelib' if self.root_is_pure else 'install_platlib', + basedir_observed) + + logger.info("installing to %s", self.bdist_dir) + + self.run_command('install') + + impl_tag, abi_tag, plat_tag = self.get_tag() + archive_basename = "{}-{}-{}-{}".format(self.wheel_dist_name, impl_tag, abi_tag, plat_tag) + if not self.relative: + archive_root = self.bdist_dir + else: + archive_root = os.path.join( + self.bdist_dir, + self._ensure_relative(install.install_base)) + + self.set_undefined_options('install_egg_info', ('target', 'egginfo_dir')) + distinfo_dirname = '{}-{}.dist-info'.format( + safer_name(self.distribution.get_name()), + safer_version(self.distribution.get_version())) + distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) + self.egg2dist(self.egginfo_dir, distinfo_dir) + + self.write_wheelfile(distinfo_dir) + + # Make the archive + if not os.path.exists(self.dist_dir): + os.makedirs(self.dist_dir) + + wheel_path = os.path.join(self.dist_dir, archive_basename + '.whl') + with WheelFile(wheel_path, 'w') as wf: + wf.write_files(archive_root) + + # Add to 'Distribution.dist_files' so that the "upload" command works + getattr(self.distribution, 'dist_files', []).append( + ('bdist_wheel', get_python_version(), wheel_path)) + + if not self.keep_temp: + logger.info('removing %s', self.bdist_dir) + if not self.dry_run: + rmtree(self.bdist_dir) + + def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): + from email.message import Message + msg = Message() + msg['Wheel-Version'] = '1.0' # of the spec + msg['Generator'] = generator + msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() + if self.build_number is not None: + msg['Build'] = self.build_number + + # Doesn't work for bdist_wininst + impl_tag, abi_tag, plat_tag = self.get_tag() + for impl in impl_tag.split('.'): + for abi in abi_tag.split('.'): + for plat in plat_tag.split('.'): + msg['Tag'] = '-'.join((impl, abi, plat)) + + wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') + logger.info('creating %s', wheelfile_path) + with open(wheelfile_path, 'w') as f: + Generator(f, maxheaderlen=0).flatten(msg) + + def _ensure_relative(self, path): + # copied from dir_util, deleted + drive, path = os.path.splitdrive(path) + if path[0:1] == os.sep: + path = drive + path[1:] + return path + + @property + def license_paths(self): + metadata = self.distribution.get_option_dict('metadata') + files = set() + patterns = sorted({ + option for option in metadata.get('license_files', ('', ''))[1].split() + }) + + if 'license_file' in metadata: + warn('The "license_file" option is deprecated. Use "license_files" instead.', + DeprecationWarning) + files.add(metadata['license_file'][1]) + + if 'license_file' not in metadata and 'license_files' not in metadata: + patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') + + for pattern in patterns: + for path in iglob(pattern): + if path not in files and os.path.isfile(path): + logger.info('adding license file "%s" (matched pattern "%s")', path, pattern) + files.add(path) + + return files + + def egg2dist(self, egginfo_path, distinfo_path): + """Convert an .egg-info directory into a .dist-info directory""" + def adios(p): + """Appropriately delete directory, file or link.""" + if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): + shutil.rmtree(p) + elif os.path.exists(p): + os.unlink(p) + + adios(distinfo_path) + + if not os.path.exists(egginfo_path): + # There is no egg-info. This is probably because the egg-info + # file/directory is not named matching the distribution name used + # to name the archive file. Check for this case and report + # accordingly. + import glob + pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') + possible = glob.glob(pat) + err = "Egg metadata expected at %s but not found" % (egginfo_path,) + if possible: + alt = os.path.basename(possible[0]) + err += " (%s found - possible misnamed archive file?)" % (alt,) + + raise ValueError(err) + + if os.path.isfile(egginfo_path): + # .egg-info is a single file + pkginfo_path = egginfo_path + pkg_info = pkginfo_to_metadata(egginfo_path, egginfo_path) + os.mkdir(distinfo_path) + else: + # .egg-info is a directory + pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') + pkg_info = pkginfo_to_metadata(egginfo_path, pkginfo_path) + + # ignore common egg metadata that is useless to wheel + shutil.copytree(egginfo_path, distinfo_path, + ignore=lambda x, y: {'PKG-INFO', 'requires.txt', 'SOURCES.txt', + 'not-zip-safe'} + ) + + # delete dependency_links if it is only whitespace + dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') + with open(dependency_links_path, 'r') as dependency_links_file: + dependency_links = dependency_links_file.read().strip() + if not dependency_links: + adios(dependency_links_path) + + write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) + + for license_path in self.license_paths: + filename = os.path.basename(license_path) + shutil.copy(license_path, os.path.join(distinfo_path, filename)) + + adios(egginfo_path) diff --git a/venv/lib/python3.7/site-packages/wheel/cli/__init__.py b/venv/lib/python3.7/site-packages/wheel/cli/__init__.py new file mode 100644 index 0000000..635f40f --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/cli/__init__.py @@ -0,0 +1,87 @@ +""" +Wheel command-line utility. +""" + +from __future__ import print_function + +import argparse +import os +import sys + + +def require_pkgresources(name): + try: + import pkg_resources # noqa: F401 + except ImportError: + raise RuntimeError("'{0}' needs pkg_resources (part of setuptools).".format(name)) + + +class WheelError(Exception): + pass + + +def unpack_f(args): + from .unpack import unpack + unpack(args.wheelfile, args.dest) + + +def pack_f(args): + from .pack import pack + pack(args.directory, args.dest_dir) + + +def convert_f(args): + from .convert import convert + convert(args.files, args.dest_dir, args.verbose) + + +def version_f(args): + from .. import __version__ + print("wheel %s" % __version__) + + +def parser(): + p = argparse.ArgumentParser() + s = p.add_subparsers(help="commands") + + unpack_parser = s.add_parser('unpack', help='Unpack wheel') + unpack_parser.add_argument('--dest', '-d', help='Destination directory', + default='.') + unpack_parser.add_argument('wheelfile', help='Wheel file') + unpack_parser.set_defaults(func=unpack_f) + + repack_parser = s.add_parser('pack', help='Repack wheel') + repack_parser.add_argument('directory', help='Root directory of the unpacked wheel') + repack_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, + help="Directory to store the wheel (default %(default)s)") + repack_parser.set_defaults(func=pack_f) + + convert_parser = s.add_parser('convert', help='Convert egg or wininst to wheel') + convert_parser.add_argument('files', nargs='*', help='Files to convert') + convert_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, + help="Directory to store wheels (default %(default)s)") + convert_parser.add_argument('--verbose', '-v', action='store_true') + convert_parser.set_defaults(func=convert_f) + + version_parser = s.add_parser('version', help='Print version and exit') + version_parser.set_defaults(func=version_f) + + help_parser = s.add_parser('help', help='Show this help') + help_parser.set_defaults(func=lambda args: p.print_help()) + + return p + + +def main(): + p = parser() + args = p.parse_args() + if not hasattr(args, 'func'): + p.print_help() + else: + try: + args.func(args) + return 0 + except WheelError as e: + print(e, file=sys.stderr) + + return 1 diff --git a/venv/lib/python3.7/site-packages/wheel/cli/convert.py b/venv/lib/python3.7/site-packages/wheel/cli/convert.py new file mode 100644 index 0000000..f1a793a --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/cli/convert.py @@ -0,0 +1,269 @@ +import os.path +import re +import shutil +import sys +import tempfile +import zipfile +from distutils import dist +from glob import iglob + +from ..bdist_wheel import bdist_wheel +from ..wheelfile import WheelFile +from . import WheelError, require_pkgresources + +egg_info_re = re.compile(r''' + (?P.+?)-(?P.+?) + (-(?Ppy\d\.\d) + (-(?P.+?))? + )?.egg$''', re.VERBOSE) + + +class _bdist_wheel_tag(bdist_wheel): + # allow the client to override the default generated wheel tag + # The default bdist_wheel implementation uses python and abi tags + # of the running python process. This is not suitable for + # generating/repackaging prebuild binaries. + + full_tag_supplied = False + full_tag = None # None or a (pytag, soabitag, plattag) triple + + def get_tag(self): + if self.full_tag_supplied and self.full_tag is not None: + return self.full_tag + else: + return bdist_wheel.get_tag(self) + + +def egg2wheel(egg_path, dest_dir): + filename = os.path.basename(egg_path) + match = egg_info_re.match(filename) + if not match: + raise WheelError('Invalid egg file name: {}'.format(filename)) + + egg_info = match.groupdict() + dir = tempfile.mkdtemp(suffix="_e2w") + if os.path.isfile(egg_path): + # assume we have a bdist_egg otherwise + with zipfile.ZipFile(egg_path) as egg: + egg.extractall(dir) + else: + # support buildout-style installed eggs directories + for pth in os.listdir(egg_path): + src = os.path.join(egg_path, pth) + if os.path.isfile(src): + shutil.copy2(src, dir) + else: + shutil.copytree(src, os.path.join(dir, pth)) + + pyver = egg_info['pyver'] + if pyver: + pyver = egg_info['pyver'] = pyver.replace('.', '') + + arch = (egg_info['arch'] or 'any').replace('.', '_').replace('-', '_') + + # assume all binary eggs are for CPython + abi = 'cp' + pyver[2:] if arch != 'any' else 'none' + + root_is_purelib = egg_info['arch'] is None + if root_is_purelib: + bw = bdist_wheel(dist.Distribution()) + else: + bw = _bdist_wheel_tag(dist.Distribution()) + + bw.root_is_pure = root_is_purelib + bw.python_tag = pyver + bw.plat_name_supplied = True + bw.plat_name = egg_info['arch'] or 'any' + if not root_is_purelib: + bw.full_tag_supplied = True + bw.full_tag = (pyver, abi, arch) + + dist_info_dir = os.path.join(dir, '{name}-{ver}.dist-info'.format(**egg_info)) + bw.egg2dist(os.path.join(dir, 'EGG-INFO'), dist_info_dir) + bw.write_wheelfile(dist_info_dir, generator='egg2wheel') + wheel_name = '{name}-{ver}-{pyver}-{}-{}.whl'.format(abi, arch, **egg_info) + with WheelFile(os.path.join(dest_dir, wheel_name), 'w') as wf: + wf.write_files(dir) + + shutil.rmtree(dir) + + +def parse_wininst_info(wininfo_name, egginfo_name): + """Extract metadata from filenames. + + Extracts the 4 metadataitems needed (name, version, pyversion, arch) from + the installer filename and the name of the egg-info directory embedded in + the zipfile (if any). + + The egginfo filename has the format:: + + name-ver(-pyver)(-arch).egg-info + + The installer filename has the format:: + + name-ver.arch(-pyver).exe + + Some things to note: + + 1. The installer filename is not definitive. An installer can be renamed + and work perfectly well as an installer. So more reliable data should + be used whenever possible. + 2. The egg-info data should be preferred for the name and version, because + these come straight from the distutils metadata, and are mandatory. + 3. The pyver from the egg-info data should be ignored, as it is + constructed from the version of Python used to build the installer, + which is irrelevant - the installer filename is correct here (even to + the point that when it's not there, any version is implied). + 4. The architecture must be taken from the installer filename, as it is + not included in the egg-info data. + 5. Architecture-neutral installers still have an architecture because the + installer format itself (being executable) is architecture-specific. We + should therefore ignore the architecture if the content is pure-python. + """ + + egginfo = None + if egginfo_name: + egginfo = egg_info_re.search(egginfo_name) + if not egginfo: + raise ValueError("Egg info filename %s is not valid" % (egginfo_name,)) + + # Parse the wininst filename + # 1. Distribution name (up to the first '-') + w_name, sep, rest = wininfo_name.partition('-') + if not sep: + raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) + + # Strip '.exe' + rest = rest[:-4] + # 2. Python version (from the last '-', must start with 'py') + rest2, sep, w_pyver = rest.rpartition('-') + if sep and w_pyver.startswith('py'): + rest = rest2 + w_pyver = w_pyver.replace('.', '') + else: + # Not version specific - use py2.py3. While it is possible that + # pure-Python code is not compatible with both Python 2 and 3, there + # is no way of knowing from the wininst format, so we assume the best + # here (the user can always manually rename the wheel to be more + # restrictive if needed). + w_pyver = 'py2.py3' + # 3. Version and architecture + w_ver, sep, w_arch = rest.rpartition('.') + if not sep: + raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) + + if egginfo: + w_name = egginfo.group('name') + w_ver = egginfo.group('ver') + + return {'name': w_name, 'ver': w_ver, 'arch': w_arch, 'pyver': w_pyver} + + +def wininst2wheel(path, dest_dir): + with zipfile.ZipFile(path) as bdw: + # Search for egg-info in the archive + egginfo_name = None + for filename in bdw.namelist(): + if '.egg-info' in filename: + egginfo_name = filename + break + + info = parse_wininst_info(os.path.basename(path), egginfo_name) + + root_is_purelib = True + for zipinfo in bdw.infolist(): + if zipinfo.filename.startswith('PLATLIB'): + root_is_purelib = False + break + if root_is_purelib: + paths = {'purelib': ''} + else: + paths = {'platlib': ''} + + dist_info = "%(name)s-%(ver)s" % info + datadir = "%s.data/" % dist_info + + # rewrite paths to trick ZipFile into extracting an egg + # XXX grab wininst .ini - between .exe, padding, and first zip file. + members = [] + egginfo_name = '' + for zipinfo in bdw.infolist(): + key, basename = zipinfo.filename.split('/', 1) + key = key.lower() + basepath = paths.get(key, None) + if basepath is None: + basepath = datadir + key.lower() + '/' + oldname = zipinfo.filename + newname = basepath + basename + zipinfo.filename = newname + del bdw.NameToInfo[oldname] + bdw.NameToInfo[newname] = zipinfo + # Collect member names, but omit '' (from an entry like "PLATLIB/" + if newname: + members.append(newname) + # Remember egg-info name for the egg2dist call below + if not egginfo_name: + if newname.endswith('.egg-info'): + egginfo_name = newname + elif '.egg-info/' in newname: + egginfo_name, sep, _ = newname.rpartition('/') + dir = tempfile.mkdtemp(suffix="_b2w") + bdw.extractall(dir, members) + + # egg2wheel + abi = 'none' + pyver = info['pyver'] + arch = (info['arch'] or 'any').replace('.', '_').replace('-', '_') + # Wininst installers always have arch even if they are not + # architecture-specific (because the format itself is). + # So, assume the content is architecture-neutral if root is purelib. + if root_is_purelib: + arch = 'any' + # If the installer is architecture-specific, it's almost certainly also + # CPython-specific. + if arch != 'any': + pyver = pyver.replace('py', 'cp') + wheel_name = '-'.join((dist_info, pyver, abi, arch)) + if root_is_purelib: + bw = bdist_wheel(dist.Distribution()) + else: + bw = _bdist_wheel_tag(dist.Distribution()) + + bw.root_is_pure = root_is_purelib + bw.python_tag = pyver + bw.plat_name_supplied = True + bw.plat_name = info['arch'] or 'any' + + if not root_is_purelib: + bw.full_tag_supplied = True + bw.full_tag = (pyver, abi, arch) + + dist_info_dir = os.path.join(dir, '%s.dist-info' % dist_info) + bw.egg2dist(os.path.join(dir, egginfo_name), dist_info_dir) + bw.write_wheelfile(dist_info_dir, generator='wininst2wheel') + + wheel_path = os.path.join(dest_dir, wheel_name) + with WheelFile(wheel_path, 'w') as wf: + wf.write_files(dir) + + shutil.rmtree(dir) + + +def convert(files, dest_dir, verbose): + # Only support wheel convert if pkg_resources is present + require_pkgresources('wheel convert') + + for pat in files: + for installer in iglob(pat): + if os.path.splitext(installer)[1] == '.egg': + conv = egg2wheel + else: + conv = wininst2wheel + + if verbose: + print("{}... ".format(installer)) + sys.stdout.flush() + + conv(installer, dest_dir) + if verbose: + print("OK") diff --git a/venv/lib/python3.7/site-packages/wheel/cli/install.py b/venv/lib/python3.7/site-packages/wheel/cli/install.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/wheel/cli/pack.py b/venv/lib/python3.7/site-packages/wheel/cli/pack.py new file mode 100644 index 0000000..45c70f2 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/cli/pack.py @@ -0,0 +1,54 @@ +from __future__ import print_function + +import os.path +import re +import sys + +from wheel.cli import WheelError +from wheel.wheelfile import WheelFile + +DIST_INFO_RE = re.compile(r"^(?P(?P.+?)-(?P\d.*?))\.dist-info$") + + +def pack(directory, dest_dir): + """Repack a previously unpacked wheel directory into a new wheel file. + + The .dist-info/WHEEL file must contain one or more tags so that the target + wheel file name can be determined. + + :param directory: The unpacked wheel directory + :param dest_dir: Destination directory (defaults to the current directory) + """ + # Find the .dist-info directory + dist_info_dirs = [fn for fn in os.listdir(directory) + if os.path.isdir(os.path.join(directory, fn)) and DIST_INFO_RE.match(fn)] + if len(dist_info_dirs) > 1: + raise WheelError('Multiple .dist-info directories found in {}'.format(directory)) + elif not dist_info_dirs: + raise WheelError('No .dist-info directories found in {}'.format(directory)) + + # Determine the target wheel filename + dist_info_dir = dist_info_dirs[0] + name_version = DIST_INFO_RE.match(dist_info_dir).group('namever') + + # Read the tags from .dist-info/WHEEL + with open(os.path.join(directory, dist_info_dir, 'WHEEL')) as f: + tags = [line.split(' ')[1].rstrip() for line in f if line.startswith('Tag: ')] + if not tags: + raise WheelError('No tags present in {}/WHEEL; cannot determine target wheel filename' + .format(dist_info_dir)) + + # Reassemble the tags for the wheel file + impls = sorted({tag.split('-')[0] for tag in tags}) + abivers = sorted({tag.split('-')[1] for tag in tags}) + platforms = sorted({tag.split('-')[2] for tag in tags}) + tagline = '-'.join(['.'.join(impls), '.'.join(abivers), '.'.join(platforms)]) + + # Repack the wheel + wheel_path = os.path.join(dest_dir, '{}-{}.whl'.format(name_version, tagline)) + with WheelFile(wheel_path, 'w') as wf: + print("Repacking wheel as {}...".format(wheel_path), end='') + sys.stdout.flush() + wf.write_files(directory) + + print('OK') diff --git a/venv/lib/python3.7/site-packages/wheel/cli/unpack.py b/venv/lib/python3.7/site-packages/wheel/cli/unpack.py new file mode 100644 index 0000000..2e9857a --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/cli/unpack.py @@ -0,0 +1,25 @@ +from __future__ import print_function + +import os.path +import sys + +from ..wheelfile import WheelFile + + +def unpack(path, dest='.'): + """Unpack a wheel. + + Wheel content will be unpacked to {dest}/{name}-{ver}, where {name} + is the package name and {ver} its version. + + :param path: The path to the wheel. + :param dest: Destination directory (default to current directory). + """ + with WheelFile(path) as wf: + namever = wf.parsed_filename.group('namever') + destination = os.path.join(dest, namever) + print("Unpacking to: {}...".format(destination), end='') + sys.stdout.flush() + wf.extractall(destination) + + print('OK') diff --git a/venv/lib/python3.7/site-packages/wheel/metadata.py b/venv/lib/python3.7/site-packages/wheel/metadata.py new file mode 100644 index 0000000..3edf6ae --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/metadata.py @@ -0,0 +1,141 @@ +""" +Tools for converting old- to new-style metadata. +""" + +import os.path +import re +import textwrap + +import pkg_resources + +from .pkginfo import read_pkg_info + +# Wheel itself is probably the only program that uses non-extras markers +# in METADATA/PKG-INFO. Support its syntax with the extra at the end only. +EXTRA_RE = re.compile( + r"""^(?P.*?)(;\s*(?P.*?)(extra == '(?P.*?)')?)$""") + + +def requires_to_requires_dist(requirement): + """Return the version specifier for a requirement in PEP 345/566 fashion.""" + if getattr(requirement, 'url', None): + return " @ " + requirement.url + + requires_dist = [] + for op, ver in requirement.specs: + requires_dist.append(op + ver) + if not requires_dist: + return '' + return " (%s)" % ','.join(sorted(requires_dist)) + + +def convert_requirements(requirements): + """Yield Requires-Dist: strings for parsed requirements strings.""" + for req in requirements: + parsed_requirement = pkg_resources.Requirement.parse(req) + spec = requires_to_requires_dist(parsed_requirement) + extras = ",".join(parsed_requirement.extras) + if extras: + extras = "[%s]" % extras + yield (parsed_requirement.project_name + extras + spec) + + +def generate_requirements(extras_require): + """ + Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement') + and ('Provides-Extra', 'extra') tuples. + + extras_require is a dictionary of {extra: [requirements]} as passed to setup(), + using the empty extra {'': [requirements]} to hold install_requires. + """ + for extra, depends in extras_require.items(): + condition = '' + extra = extra or '' + if ':' in extra: # setuptools extra:condition syntax + extra, condition = extra.split(':', 1) + + extra = pkg_resources.safe_extra(extra) + if extra: + yield 'Provides-Extra', extra + if condition: + condition = "(" + condition + ") and " + condition += "extra == '%s'" % extra + + if condition: + condition = ' ; ' + condition + + for new_req in convert_requirements(depends): + yield 'Requires-Dist', new_req + condition + + +def pkginfo_to_metadata(egg_info_path, pkginfo_path): + """ + Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format + """ + pkg_info = read_pkg_info(pkginfo_path) + pkg_info.replace_header('Metadata-Version', '2.1') + # Those will be regenerated from `requires.txt`. + del pkg_info['Provides-Extra'] + del pkg_info['Requires-Dist'] + requires_path = os.path.join(egg_info_path, 'requires.txt') + if os.path.exists(requires_path): + with open(requires_path) as requires_file: + requires = requires_file.read() + + parsed_requirements = sorted(pkg_resources.split_sections(requires), + key=lambda x: x[0] or '') + for extra, reqs in parsed_requirements: + for key, value in generate_requirements({extra: reqs}): + if (key, value) not in pkg_info.items(): + pkg_info[key] = value + + description = pkg_info['Description'] + if description: + pkg_info.set_payload(dedent_description(pkg_info)) + del pkg_info['Description'] + + return pkg_info + + +def pkginfo_unicode(pkg_info, field): + """Hack to coax Unicode out of an email Message() - Python 3.3+""" + text = pkg_info[field] + field = field.lower() + if not isinstance(text, str): + if not hasattr(pkg_info, 'raw_items'): # Python 3.2 + return str(text) + for item in pkg_info.raw_items(): + if item[0].lower() == field: + text = item[1].encode('ascii', 'surrogateescape') \ + .decode('utf-8') + break + + return text + + +def dedent_description(pkg_info): + """ + Dedent and convert pkg_info['Description'] to Unicode. + """ + description = pkg_info['Description'] + + # Python 3 Unicode handling, sorta. + surrogates = False + if not isinstance(description, str): + surrogates = True + description = pkginfo_unicode(pkg_info, 'Description') + + description_lines = description.splitlines() + description_dedent = '\n'.join( + # if the first line of long_description is blank, + # the first line here will be indented. + (description_lines[0].lstrip(), + textwrap.dedent('\n'.join(description_lines[1:])), + '\n')) + + if surrogates: + description_dedent = description_dedent \ + .encode("utf8") \ + .decode("ascii", "surrogateescape") + + return description_dedent diff --git a/venv/lib/python3.7/site-packages/wheel/pep425tags.py b/venv/lib/python3.7/site-packages/wheel/pep425tags.py new file mode 100644 index 0000000..13b5073 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/pep425tags.py @@ -0,0 +1,185 @@ +"""Generate and work with PEP 425 Compatibility Tags.""" + +import distutils.util +import platform +import sys +import sysconfig +import warnings + +try: + from importlib.machinery import get_all_suffixes +except ImportError: + from imp import get_suffixes as get_all_suffixes + + +def get_config_var(var): + try: + return sysconfig.get_config_var(var) + except IOError as e: # pip Issue #1074 + warnings.warn("{0}".format(e), RuntimeWarning) + return None + + +def get_abbr_impl(): + """Return abbreviated implementation name.""" + impl = platform.python_implementation() + if impl == 'PyPy': + return 'pp' + elif impl == 'Jython': + return 'jy' + elif impl == 'IronPython': + return 'ip' + elif impl == 'CPython': + return 'cp' + + raise LookupError('Unknown Python implementation: ' + impl) + + +def get_impl_ver(): + """Return implementation version.""" + impl_ver = get_config_var("py_version_nodot") + if not impl_ver or get_abbr_impl() == 'pp': + impl_ver = ''.join(map(str, get_impl_version_info())) + return impl_ver + + +def get_impl_version_info(): + """Return sys.version_info-like tuple for use in decrementing the minor + version.""" + if get_abbr_impl() == 'pp': + # as per https://github.com/pypa/pip/issues/2882 + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return sys.version_info[0], sys.version_info[1] + + +def get_flag(var, fallback, expected=True, warn=True): + """Use a fallback method for determining SOABI flags if the needed config + var is unset or unavailable.""" + val = get_config_var(var) + if val is None: + if warn: + warnings.warn("Config variable '{0}' is unset, Python ABI tag may " + "be incorrect".format(var), RuntimeWarning, 2) + return fallback() + return val == expected + + +def get_abi_tag(): + """Return the ABI tag based on SOABI (if available) or emulate SOABI + (CPython 2, PyPy).""" + soabi = get_config_var('SOABI') + impl = get_abbr_impl() + if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'): + d = '' + m = '' + u = '' + if get_flag('Py_DEBUG', + lambda: hasattr(sys, 'gettotalrefcount'), + warn=(impl == 'cp')): + d = 'd' + if get_flag('WITH_PYMALLOC', + lambda: impl == 'cp', + warn=(impl == 'cp')): + m = 'm' + if get_flag('Py_UNICODE_SIZE', + lambda: sys.maxunicode == 0x10ffff, + expected=4, + warn=(impl == 'cp' and + sys.version_info < (3, 3))) \ + and sys.version_info < (3, 3): + u = 'u' + abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) + elif soabi and soabi.startswith('cpython-'): + abi = 'cp' + soabi.split('-')[1] + elif soabi: + abi = soabi.replace('.', '_').replace('-', '_') + else: + abi = None + return abi + + +def get_platform(): + """Return our platform name 'win32', 'linux_x86_64'""" + # XXX remove distutils dependency + result = distutils.util.get_platform().replace('.', '_').replace('-', '_') + if result == "linux_x86_64" and sys.maxsize == 2147483647: + # pip pull request #3497 + result = "linux_i686" + return result + + +def get_supported(versions=None, supplied_platform=None): + """Return a list of supported tags for each version specified in + `versions`. + + :param versions: a list of string versions, of the form ["33", "32"], + or None. The first version will be assumed to support our ABI. + """ + supported = [] + + # Versions must be given with respect to the preference + if versions is None: + versions = [] + version_info = get_impl_version_info() + major = version_info[:-1] + # Support all previous minor Python versions. + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = get_abbr_impl() + + abis = [] + + abi = get_abi_tag() + if abi: + abis[0:0] = [abi] + + abi3s = set() + for suffix in get_all_suffixes(): + if suffix[0].startswith('.abi'): + abi3s.add(suffix[0].split('.', 2)[1]) + + abis.extend(sorted(list(abi3s))) + + abis.append('none') + + platforms = [] + if supplied_platform: + platforms.append(supplied_platform) + platforms.append(get_platform()) + + # Current version, current API (built specifically for our Python): + for abi in abis: + for arch in platforms: + supported.append(('%s%s' % (impl, versions[0]), abi, arch)) + + # abi3 modules compatible with older version of Python + for version in versions[1:]: + # abi3 was introduced in Python 3.2 + if version in ('31', '30'): + break + for abi in abi3s: # empty set if not Python 3 + for arch in platforms: + supported.append(("%s%s" % (impl, version), abi, arch)) + + # No abi / arch, but requires our implementation: + for i, version in enumerate(versions): + supported.append(('%s%s' % (impl, version), 'none', 'any')) + if i == 0: + # Tagged specifically as being cross-version compatible + # (with just the major version specified) + supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + # Major Python version + platform; e.g. binaries not using the Python API + for arch in platforms: + supported.append(('py%s' % (versions[0][0]), 'none', arch)) + + # No abi / arch, generic Python + for i, version in enumerate(versions): + supported.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + supported.append(('py%s' % (version[0]), 'none', 'any')) + + return supported diff --git a/venv/lib/python3.7/site-packages/wheel/pkginfo.py b/venv/lib/python3.7/site-packages/wheel/pkginfo.py new file mode 100644 index 0000000..115be45 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/pkginfo.py @@ -0,0 +1,43 @@ +"""Tools for reading and writing PKG-INFO / METADATA without caring +about the encoding.""" + +from email.parser import Parser + +try: + unicode + _PY3 = False +except NameError: + _PY3 = True + +if not _PY3: + from email.generator import Generator + + def read_pkg_info_bytes(bytestr): + return Parser().parsestr(bytestr) + + def read_pkg_info(path): + with open(path, "r") as headers: + message = Parser().parse(headers) + return message + + def write_pkg_info(path, message): + with open(path, 'w') as metadata: + Generator(metadata, mangle_from_=False, maxheaderlen=0).flatten(message) +else: + from email.generator import BytesGenerator + + def read_pkg_info_bytes(bytestr): + headers = bytestr.decode(encoding="ascii", errors="surrogateescape") + message = Parser().parsestr(headers) + return message + + def read_pkg_info(path): + with open(path, "r", + encoding="ascii", + errors="surrogateescape") as headers: + message = Parser().parse(headers) + return message + + def write_pkg_info(path, message): + with open(path, "wb") as out: + BytesGenerator(out, mangle_from_=False, maxheaderlen=0).flatten(message) diff --git a/venv/lib/python3.7/site-packages/wheel/util.py b/venv/lib/python3.7/site-packages/wheel/util.py new file mode 100644 index 0000000..be0aa9b --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/util.py @@ -0,0 +1,41 @@ +import base64 +import sys + + +if sys.version_info[0] < 3: + text_type = unicode # noqa: F821 + + def native(s, encoding='utf-8'): + if isinstance(s, unicode): + return s.encode(encoding) + return s +else: + text_type = str + + def native(s, encoding='utf-8'): + if isinstance(s, bytes): + return s.decode(encoding) + return s + + +def urlsafe_b64encode(data): + """urlsafe_b64encode without padding""" + return base64.urlsafe_b64encode(data).rstrip(b'=') + + +def urlsafe_b64decode(data): + """urlsafe_b64decode without padding""" + pad = b'=' * (4 - (len(data) & 3)) + return base64.urlsafe_b64decode(data + pad) + + +def as_unicode(s): + if isinstance(s, bytes): + return s.decode('utf-8') + return s + + +def as_bytes(s): + if isinstance(s, text_type): + return s.encode('utf-8') + return s diff --git a/venv/lib/python3.7/site-packages/wheel/wheelfile.py b/venv/lib/python3.7/site-packages/wheel/wheelfile.py new file mode 100644 index 0000000..635aa77 --- /dev/null +++ b/venv/lib/python3.7/site-packages/wheel/wheelfile.py @@ -0,0 +1,160 @@ +from __future__ import print_function + +import hashlib +import os.path +import re +import time +from collections import OrderedDict +from distutils import log as logger +from zipfile import ZIP_DEFLATED, ZipInfo, ZipFile + +from wheel.cli import WheelError +from wheel.util import urlsafe_b64decode, as_unicode, native, urlsafe_b64encode, as_bytes + +# Non-greedy matching of an optional build number may be too clever (more +# invalid wheel filenames will match). Separate regex for .dist-info? +WHEEL_INFO_RE = re.compile( + r"""^(?P(?P.+?)-(?P.+?))(-(?P\d[^-]*))? + -(?P.+?)-(?P.+?)-(?P.+?)\.whl$""", + re.VERBOSE) + + +def get_zipinfo_datetime(timestamp=None): + # Some applications need reproducible .whl files, but they can't do this without forcing + # the timestamp of the individual ZipInfo objects. See issue #143. + timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', timestamp or time.time())) + return time.gmtime(timestamp)[0:6] + + +class WheelFile(ZipFile): + """A ZipFile derivative class that also reads SHA-256 hashes from + .dist-info/RECORD and checks any read files against those. + """ + + _default_algorithm = hashlib.sha256 + + def __init__(self, file, mode='r'): + basename = os.path.basename(file) + self.parsed_filename = WHEEL_INFO_RE.match(basename) + if not basename.endswith('.whl') or self.parsed_filename is None: + raise WheelError("Bad wheel filename {!r}".format(basename)) + + ZipFile.__init__(self, file, mode, compression=ZIP_DEFLATED, allowZip64=True) + + self.dist_info_path = '{}.dist-info'.format(self.parsed_filename.group('namever')) + self.record_path = self.dist_info_path + '/RECORD' + self._file_hashes = OrderedDict() + self._file_sizes = {} + if mode == 'r': + # Ignore RECORD and any embedded wheel signatures + self._file_hashes[self.record_path] = None, None + self._file_hashes[self.record_path + '.jws'] = None, None + self._file_hashes[self.record_path + '.p7s'] = None, None + + # Fill in the expected hashes by reading them from RECORD + try: + record = self.open(self.record_path) + except KeyError: + raise WheelError('Missing {} file'.format(self.record_path)) + + with record: + for line in record: + line = line.decode('utf-8') + path, hash_sum, size = line.rsplit(u',', 2) + if hash_sum: + algorithm, hash_sum = hash_sum.split(u'=') + try: + hashlib.new(algorithm) + except ValueError: + raise WheelError('Unsupported hash algorithm: {}'.format(algorithm)) + + if algorithm.lower() in {'md5', 'sha1'}: + raise WheelError( + 'Weak hash algorithm ({}) is not permitted by PEP 427' + .format(algorithm)) + + self._file_hashes[path] = ( + algorithm, urlsafe_b64decode(hash_sum.encode('ascii'))) + + def open(self, name_or_info, mode="r", pwd=None): + def _update_crc(newdata, eof=None): + if eof is None: + eof = ef._eof + update_crc_orig(newdata) + else: # Python 2 + update_crc_orig(newdata, eof) + + running_hash.update(newdata) + if eof and running_hash.digest() != expected_hash: + raise WheelError("Hash mismatch for file '{}'".format(native(ef_name))) + + ef = ZipFile.open(self, name_or_info, mode, pwd) + ef_name = as_unicode(name_or_info.filename if isinstance(name_or_info, ZipInfo) + else name_or_info) + if mode == 'r' and not ef_name.endswith('/'): + if ef_name not in self._file_hashes: + raise WheelError("No hash found for file '{}'".format(native(ef_name))) + + algorithm, expected_hash = self._file_hashes[ef_name] + if expected_hash is not None: + # Monkey patch the _update_crc method to also check for the hash from RECORD + running_hash = hashlib.new(algorithm) + update_crc_orig, ef._update_crc = ef._update_crc, _update_crc + + return ef + + def write_files(self, base_dir): + logger.info("creating '%s' and adding '%s' to it", self.filename, base_dir) + deferred = [] + for root, dirnames, filenames in os.walk(base_dir): + # Sort the directory names so that `os.walk` will walk them in a + # defined order on the next iteration. + dirnames.sort() + for name in sorted(filenames): + path = os.path.normpath(os.path.join(root, name)) + if os.path.isfile(path): + arcname = os.path.relpath(path, base_dir) + if arcname == self.record_path: + pass + elif root.endswith('.dist-info'): + deferred.append((path, arcname)) + else: + self.write(path, arcname) + + deferred.sort() + for path, arcname in deferred: + self.write(path, arcname) + + def write(self, filename, arcname=None, compress_type=None): + with open(filename, 'rb') as f: + st = os.fstat(f.fileno()) + data = f.read() + + zinfo = ZipInfo(arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime)) + zinfo.external_attr = st.st_mode << 16 + zinfo.compress_type = ZIP_DEFLATED + self.writestr(zinfo, data, compress_type) + + def writestr(self, zinfo_or_arcname, bytes, compress_type=None): + ZipFile.writestr(self, zinfo_or_arcname, bytes, compress_type) + fname = (zinfo_or_arcname.filename if isinstance(zinfo_or_arcname, ZipInfo) + else zinfo_or_arcname) + logger.info("adding '%s'", fname) + if fname != self.record_path: + hash_ = self._default_algorithm(bytes) + self._file_hashes[fname] = hash_.name, native(urlsafe_b64encode(hash_.digest())) + self._file_sizes[fname] = len(bytes) + + def close(self): + # Write RECORD + if self.fp is not None and self.mode == 'w' and self._file_hashes: + content = '\n'.join('{},{}={},{}'.format(fname, algorithm, hash_, + self._file_sizes[fname]) + for fname, (algorithm, hash_) in self._file_hashes.items()) + content += '\n{},,\n'.format(self.record_path) + zinfo = ZipInfo(native(self.record_path), date_time=get_zipinfo_datetime()) + zinfo.compress_type = ZIP_DEFLATED + zinfo.external_attr = 0o664 << 16 + self.writestr(zinfo, as_bytes(content)) + + ZipFile.close(self) diff --git a/venv/lib/python3.7/site.py b/venv/lib/python3.7/site.py new file mode 100644 index 0000000..7969769 --- /dev/null +++ b/venv/lib/python3.7/site.py @@ -0,0 +1,758 @@ +"""Append module search paths for third-party packages to sys.path. + +**************************************************************** +* This module is automatically imported during initialization. * +**************************************************************** + +In earlier versions of Python (up to 1.5a3), scripts or modules that +needed to use site-specific modules would place ``import site'' +somewhere near the top of their code. Because of the automatic +import, this is no longer necessary (but code that does it still +works). + +This will append site-specific paths to the module search path. On +Unix, it starts with sys.prefix and sys.exec_prefix (if different) and +appends lib/python/site-packages as well as lib/site-python. +It also supports the Debian convention of +lib/python/dist-packages. On other platforms (mainly Mac and +Windows), it uses just sys.prefix (and sys.exec_prefix, if different, +but this is unlikely). The resulting directories, if they exist, are +appended to sys.path, and also inspected for path configuration files. + +FOR DEBIAN, this sys.path is augmented with directories in /usr/local. +Local addons go into /usr/local/lib/python/site-packages +(resp. /usr/local/lib/site-python), Debian addons install into +/usr/{lib,share}/python/dist-packages. + +A path configuration file is a file whose name has the form +.pth; its contents are additional directories (one per line) +to be added to sys.path. Non-existing directories (or +non-directories) are never added to sys.path; no directory is added to +sys.path more than once. Blank lines and lines beginning with +'#' are skipped. Lines starting with 'import' are executed. + +For example, suppose sys.prefix and sys.exec_prefix are set to +/usr/local and there is a directory /usr/local/lib/python2.X/site-packages +with three subdirectories, foo, bar and spam, and two path +configuration files, foo.pth and bar.pth. Assume foo.pth contains the +following: + + # foo package configuration + foo + bar + bletch + +and bar.pth contains: + + # bar package configuration + bar + +Then the following directories are added to sys.path, in this order: + + /usr/local/lib/python2.X/site-packages/bar + /usr/local/lib/python2.X/site-packages/foo + +Note that bletch is omitted because it doesn't exist; bar precedes foo +because bar.pth comes alphabetically before foo.pth; and spam is +omitted because it is not mentioned in either path configuration file. + +After these path manipulations, an attempt is made to import a module +named sitecustomize, which can perform arbitrary additional +site-specific customizations. If this import fails with an +ImportError exception, it is silently ignored. + +""" + +import sys +import os +try: + import __builtin__ as builtins +except ImportError: + import builtins +try: + set +except NameError: + from sets import Set as set + +# Prefixes for site-packages; add additional prefixes like /usr/local here +PREFIXES = [sys.prefix, sys.exec_prefix] +# Enable per user site-packages directory +# set it to False to disable the feature or True to force the feature +ENABLE_USER_SITE = None +# for distutils.commands.install +USER_SITE = None +USER_BASE = None + +_is_64bit = (getattr(sys, 'maxsize', None) or getattr(sys, 'maxint')) > 2**32 +_is_pypy = hasattr(sys, 'pypy_version_info') +_is_jython = sys.platform[:4] == 'java' +if _is_jython: + ModuleType = type(os) + +def makepath(*paths): + dir = os.path.join(*paths) + if _is_jython and (dir == '__classpath__' or + dir.startswith('__pyclasspath__')): + return dir, dir + dir = os.path.abspath(dir) + return dir, os.path.normcase(dir) + +def abs__file__(): + """Set all module' __file__ attribute to an absolute path""" + for m in sys.modules.values(): + if ((_is_jython and not isinstance(m, ModuleType)) or + hasattr(m, '__loader__')): + # only modules need the abspath in Jython. and don't mess + # with a PEP 302-supplied __file__ + continue + f = getattr(m, '__file__', None) + if f is None: + continue + m.__file__ = os.path.abspath(f) + +def removeduppaths(): + """ Remove duplicate entries from sys.path along with making them + absolute""" + # This ensures that the initial path provided by the interpreter contains + # only absolute pathnames, even if we're running from the build directory. + L = [] + known_paths = set() + for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in known_paths: + L.append(dir) + known_paths.add(dircase) + sys.path[:] = L + return known_paths + +# XXX This should not be part of site.py, since it is needed even when +# using the -S option for Python. See http://www.python.org/sf/586680 +def addbuilddir(): + """Append ./build/lib. in case we're running in the build dir + (especially for Guido :-)""" + from distutils.util import get_platform + s = "build/lib.%s-%.3s" % (get_platform(), sys.version) + if hasattr(sys, 'gettotalrefcount'): + s += '-pydebug' + s = os.path.join(os.path.dirname(sys.path[-1]), s) + sys.path.append(s) + +def _init_pathinfo(): + """Return a set containing all existing directory entries from sys.path""" + d = set() + for dir in sys.path: + try: + if os.path.isdir(dir): + dir, dircase = makepath(dir) + d.add(dircase) + except TypeError: + continue + return d + +def addpackage(sitedir, name, known_paths): + """Add a new path to known_paths by combining sitedir and 'name' or execute + sitedir if it starts with 'import'""" + if known_paths is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname, "rU") + except IOError: + return + try: + for line in f: + if line.startswith("#"): + continue + if line.startswith("import"): + exec(line) + continue + line = line.rstrip() + dir, dircase = makepath(sitedir, line) + if not dircase in known_paths and os.path.exists(dir): + sys.path.append(dir) + known_paths.add(dircase) + finally: + f.close() + if reset: + known_paths = None + return known_paths + +def addsitedir(sitedir, known_paths=None): + """Add 'sitedir' argument to sys.path if missing and handle .pth files in + 'sitedir'""" + if known_paths is None: + known_paths = _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in known_paths: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name.endswith(os.extsep + "pth"): + addpackage(sitedir, name, known_paths) + if reset: + known_paths = None + return known_paths + +def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): + """Add site-packages (and possibly site-python) to sys.path""" + prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] + if exec_prefix != sys_prefix: + prefixes.append(os.path.join(exec_prefix, "local")) + + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos') or _is_jython: + sitedirs = [os.path.join(prefix, "Lib", "site-packages")] + elif _is_pypy: + sitedirs = [os.path.join(prefix, 'site-packages')] + elif sys.platform == 'darwin' and prefix == sys_prefix: + + if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python + + sitedirs = [os.path.join("/Library/Python", sys.version[:3], "site-packages"), + os.path.join(prefix, "Extras", "lib", "python")] + + else: # any other Python distros on OSX work this way + sitedirs = [os.path.join(prefix, "lib", + "python" + sys.version[:3], "site-packages")] + + elif os.sep == '/': + sitedirs = [os.path.join(prefix, + "lib", + "python" + sys.version[:3], + "site-packages"), + os.path.join(prefix, "lib", "site-python"), + os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")] + lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages") + if (os.path.exists(lib64_dir) and + os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]): + if _is_64bit: + sitedirs.insert(0, lib64_dir) + else: + sitedirs.append(lib64_dir) + try: + # sys.getobjects only available in --with-pydebug build + sys.getobjects + sitedirs.insert(0, os.path.join(sitedirs[0], 'debug')) + except AttributeError: + pass + # Debian-specific dist-packages directories: + sitedirs.append(os.path.join(prefix, "local/lib", + "python" + sys.version[:3], + "dist-packages")) + if sys.version[0] == '2': + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[:3], + "dist-packages")) + else: + sitedirs.append(os.path.join(prefix, "lib", + "python" + sys.version[0], + "dist-packages")) + sitedirs.append(os.path.join(prefix, "lib", "dist-python")) + else: + sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + sitedirs.append( + os.path.join(home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages')) + for sitedir in sitedirs: + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + return None + +def check_enableusersite(): + """Check if user site directory is safe for inclusion + + The function tests for the command line flag (including environment var), + process uid/gid equal to effective uid/gid. + + None: Disabled for security reasons + False: Disabled by user (command line option) + True: Safe and enabled + """ + if hasattr(sys, 'flags') and getattr(sys.flags, 'no_user_site', False): + return False + + if hasattr(os, "getuid") and hasattr(os, "geteuid"): + # check process uid == effective uid + if os.geteuid() != os.getuid(): + return None + if hasattr(os, "getgid") and hasattr(os, "getegid"): + # check process gid == effective gid + if os.getegid() != os.getgid(): + return None + + return True + +def addusersitepackages(known_paths): + """Add a per user site-package to sys.path + + Each user has its own python directory with site-packages in the + home directory. + + USER_BASE is the root directory for all Python versions + + USER_SITE is the user specific site-packages directory + + USER_SITE/.. can be used for data. + """ + global USER_BASE, USER_SITE, ENABLE_USER_SITE + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + #if sys.platform in ('os2emx', 'riscos'): + # # Don't know what to put here + # USER_BASE = '' + # USER_SITE = '' + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser(base, "Python") + USER_SITE = os.path.join(USER_BASE, + "Python" + sys.version[0] + sys.version[2], + "site-packages") + else: + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser("~", ".local") + USER_SITE = os.path.join(USER_BASE, "lib", + "python" + sys.version[:3], + "site-packages") + + if ENABLE_USER_SITE and os.path.isdir(USER_SITE): + addsitedir(USER_SITE, known_paths) + if ENABLE_USER_SITE: + for dist_libdir in ("lib", "local/lib"): + user_site = os.path.join(USER_BASE, dist_libdir, + "python" + sys.version[:3], + "dist-packages") + if os.path.isdir(user_site): + addsitedir(user_site, known_paths) + return known_paths + + + +def setBEGINLIBPATH(): + """The OS/2 EMX port has optional extension modules that do double duty + as DLLs (and must use the .DLL file extension) for other extensions. + The library search path needs to be amended so these will be found + during module import. Use BEGINLIBPATH so that these are at the start + of the library search path. + + """ + dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") + libpath = os.environ['BEGINLIBPATH'].split(';') + if libpath[-1]: + libpath.append(dllpath) + else: + libpath[-1] = dllpath + os.environ['BEGINLIBPATH'] = ';'.join(libpath) + + +def setquit(): + """Define new built-ins 'quit' and 'exit'. + These are simply strings that display a hint on how to exit. + + """ + if os.sep == ':': + eof = 'Cmd-Q' + elif os.sep == '\\': + eof = 'Ctrl-Z plus Return' + else: + eof = 'Ctrl-D (i.e. EOF)' + + class Quitter(object): + def __init__(self, name): + self.name = name + def __repr__(self): + return 'Use %s() or %s to exit' % (self.name, eof) + def __call__(self, code=None): + # Shells like IDLE catch the SystemExit, but listen when their + # stdin wrapper is closed. + try: + sys.stdin.close() + except: + pass + raise SystemExit(code) + builtins.quit = Quitter('quit') + builtins.exit = Quitter('exit') + + +class _Printer(object): + """interactive prompt objects for printing the license text, a list of + contributors and the copyright notice.""" + + MAXLINES = 23 + + def __init__(self, name, data, files=(), dirs=()): + self.__name = name + self.__data = data + self.__files = files + self.__dirs = dirs + self.__lines = None + + def __setup(self): + if self.__lines: + return + data = None + for dir in self.__dirs: + for filename in self.__files: + filename = os.path.join(dir, filename) + try: + fp = open(filename, "rU") + data = fp.read() + fp.close() + break + except IOError: + pass + if data: + break + if not data: + data = self.__data + self.__lines = data.split('\n') + self.__linecnt = len(self.__lines) + + def __repr__(self): + self.__setup() + if len(self.__lines) <= self.MAXLINES: + return "\n".join(self.__lines) + else: + return "Type %s() to see the full %s text" % ((self.__name,)*2) + + def __call__(self): + self.__setup() + prompt = 'Hit Return for more, or q (and Return) to quit: ' + lineno = 0 + while 1: + try: + for i in range(lineno, lineno + self.MAXLINES): + print(self.__lines[i]) + except IndexError: + break + else: + lineno += self.MAXLINES + key = None + while key is None: + try: + key = raw_input(prompt) + except NameError: + key = input(prompt) + if key not in ('', 'q'): + key = None + if key == 'q': + break + +def setcopyright(): + """Set 'copyright' and 'credits' in __builtin__""" + builtins.copyright = _Printer("copyright", sys.copyright) + if _is_jython: + builtins.credits = _Printer( + "credits", + "Jython is maintained by the Jython developers (www.jython.org).") + elif _is_pypy: + builtins.credits = _Printer( + "credits", + "PyPy is maintained by the PyPy developers: http://pypy.org/") + else: + builtins.credits = _Printer("credits", """\ + Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands + for supporting Python development. See www.python.org for more information.""") + here = os.path.dirname(os.__file__) + builtins.license = _Printer( + "license", "See http://www.python.org/%.3s/license.html" % sys.version, + ["LICENSE.txt", "LICENSE"], + [os.path.join(here, os.pardir), here, os.curdir]) + + +class _Helper(object): + """Define the built-in 'help'. + This is a wrapper around pydoc.help (with a twist). + + """ + + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + +def sethelper(): + builtins.help = _Helper() + +def aliasmbcs(): + """On Windows, some default encodings are not provided by Python, + while they are always available as "mbcs" in each locale. Make + them usable by aliasing to "mbcs" in such a case.""" + if sys.platform == 'win32': + import locale, codecs + enc = locale.getdefaultlocale()[1] + if enc.startswith('cp'): # "cp***" ? + try: + codecs.lookup(enc) + except LookupError: + import encodings + encodings._cache[enc] = encodings._unknown + encodings.aliases.aliases[enc] = 'mbcs' + +def setencoding(): + """Set the string encoding used by the Unicode implementation. The + default is 'ascii', but if you're willing to experiment, you can + change this.""" + encoding = "ascii" # Default value set by _PyUnicode_Init() + if 0: + # Enable to support locale aware default string encodings. + import locale + loc = locale.getdefaultlocale() + if loc[1]: + encoding = loc[1] + if 0: + # Enable to switch off string to Unicode coercion and implicit + # Unicode to string conversion. + encoding = "undefined" + if encoding != "ascii": + # On Non-Unicode builds this will raise an AttributeError... + sys.setdefaultencoding(encoding) # Needs Python Unicode build ! + + +def execsitecustomize(): + """Run custom site specific code, if available.""" + try: + import sitecustomize + except ImportError: + pass + +def virtual_install_main_packages(): + f = open(os.path.join(os.path.dirname(__file__), 'orig-prefix.txt')) + sys.real_prefix = f.read().strip() + f.close() + pos = 2 + hardcoded_relative_dirs = [] + if sys.path[0] == '': + pos += 1 + if _is_jython: + paths = [os.path.join(sys.real_prefix, 'Lib')] + elif _is_pypy: + if sys.version_info > (3, 2): + cpyver = '%d' % sys.version_info[0] + elif sys.pypy_version_info >= (1, 5): + cpyver = '%d.%d' % sys.version_info[:2] + else: + cpyver = '%d.%d.%d' % sys.version_info[:3] + paths = [os.path.join(sys.real_prefix, 'lib_pypy'), + os.path.join(sys.real_prefix, 'lib-python', cpyver)] + if sys.pypy_version_info < (1, 9): + paths.insert(1, os.path.join(sys.real_prefix, + 'lib-python', 'modified-%s' % cpyver)) + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + # + # This is hardcoded in the Python executable, but relative to sys.prefix: + for path in paths[:]: + plat_path = os.path.join(path, 'plat-%s' % sys.platform) + if os.path.exists(plat_path): + paths.append(plat_path) + elif sys.platform == 'win32': + paths = [os.path.join(sys.real_prefix, 'Lib'), os.path.join(sys.real_prefix, 'DLLs')] + else: + paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])] + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3]) + if os.path.exists(lib64_path): + if _is_64bit: + paths.insert(0, lib64_path) + else: + paths.append(lib64_path) + # This is hardcoded in the Python executable, but relative to + # sys.prefix. Debian change: we need to add the multiarch triplet + # here, which is where the real stuff lives. As per PEP 421, in + # Python 3.3+, this lives in sys.implementation, while in Python 2.7 + # it lives in sys. + try: + arch = getattr(sys, 'implementation', sys)._multiarch + except AttributeError: + # This is a non-multiarch aware Python. Fallback to the old way. + arch = sys.platform + plat_path = os.path.join(sys.real_prefix, 'lib', + 'python'+sys.version[:3], + 'plat-%s' % arch) + if os.path.exists(plat_path): + paths.append(plat_path) + # This is hardcoded in the Python executable, but + # relative to sys.prefix, so we have to fix up: + for path in list(paths): + tk_dir = os.path.join(path, 'lib-tk') + if os.path.exists(tk_dir): + paths.append(tk_dir) + + # These are hardcoded in the Apple's Python executable, + # but relative to sys.prefix, so we have to fix them up: + if sys.platform == 'darwin': + hardcoded_paths = [os.path.join(relative_dir, module) + for relative_dir in hardcoded_relative_dirs + for module in ('plat-darwin', 'plat-mac', 'plat-mac/lib-scriptpackages')] + + for path in hardcoded_paths: + if os.path.exists(path): + paths.append(path) + + sys.path.extend(paths) + +def force_global_eggs_after_local_site_packages(): + """ + Force easy_installed eggs in the global environment to get placed + in sys.path after all packages inside the virtualenv. This + maintains the "least surprise" result that packages in the + virtualenv always mask global packages, never the other way + around. + + """ + egginsert = getattr(sys, '__egginsert', 0) + for i, path in enumerate(sys.path): + if i > egginsert and path.startswith(sys.prefix): + egginsert = i + sys.__egginsert = egginsert + 1 + +def virtual_addsitepackages(known_paths): + force_global_eggs_after_local_site_packages() + return addsitepackages(known_paths, sys_prefix=sys.real_prefix) + +def fixclasspath(): + """Adjust the special classpath sys.path entries for Jython. These + entries should follow the base virtualenv lib directories. + """ + paths = [] + classpaths = [] + for path in sys.path: + if path == '__classpath__' or path.startswith('__pyclasspath__'): + classpaths.append(path) + else: + paths.append(path) + sys.path = paths + sys.path.extend(classpaths) + +def execusercustomize(): + """Run custom user specific code, if available.""" + try: + import usercustomize + except ImportError: + pass + + +def main(): + global ENABLE_USER_SITE + virtual_install_main_packages() + abs__file__() + paths_in_sys = removeduppaths() + if (os.name == "posix" and sys.path and + os.path.basename(sys.path[-1]) == "Modules"): + addbuilddir() + if _is_jython: + fixclasspath() + GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), 'no-global-site-packages.txt')) + if not GLOBAL_SITE_PACKAGES: + ENABLE_USER_SITE = False + if ENABLE_USER_SITE is None: + ENABLE_USER_SITE = check_enableusersite() + paths_in_sys = addsitepackages(paths_in_sys) + paths_in_sys = addusersitepackages(paths_in_sys) + if GLOBAL_SITE_PACKAGES: + paths_in_sys = virtual_addsitepackages(paths_in_sys) + if sys.platform == 'os2emx': + setBEGINLIBPATH() + setquit() + setcopyright() + sethelper() + aliasmbcs() + setencoding() + execsitecustomize() + if ENABLE_USER_SITE: + execusercustomize() + # Remove sys.setdefaultencoding() so that users cannot change the + # encoding after initialization. The test for presence is needed when + # this module is run as a script, because this code is executed twice. + if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding + +main() + +def _script(): + help = """\ + %s [--user-base] [--user-site] + + Without arguments print some useful information + With arguments print the value of USER_BASE and/or USER_SITE separated + by '%s'. + + Exit codes with --user-base or --user-site: + 0 - user site directory is enabled + 1 - user site directory is disabled by user + 2 - uses site directory is disabled by super user + or for security reasons + >2 - unknown error + """ + args = sys.argv[1:] + if not args: + print("sys.path = [") + for dir in sys.path: + print(" %r," % (dir,)) + print("]") + def exists(path): + if os.path.isdir(path): + return "exists" + else: + return "doesn't exist" + print("USER_BASE: %r (%s)" % (USER_BASE, exists(USER_BASE))) + print("USER_SITE: %r (%s)" % (USER_SITE, exists(USER_BASE))) + print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) + sys.exit(0) + + buffer = [] + if '--user-base' in args: + buffer.append(USER_BASE) + if '--user-site' in args: + buffer.append(USER_SITE) + + if buffer: + print(os.pathsep.join(buffer)) + if ENABLE_USER_SITE: + sys.exit(0) + elif ENABLE_USER_SITE is False: + sys.exit(1) + elif ENABLE_USER_SITE is None: + sys.exit(2) + else: + sys.exit(3) + else: + import textwrap + print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) + sys.exit(10) + +if __name__ == '__main__': + _script() diff --git a/venv/lib/python3.7/sre_compile.py b/venv/lib/python3.7/sre_compile.py new file mode 120000 index 0000000..7116370 --- /dev/null +++ b/venv/lib/python3.7/sre_compile.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/sre_compile.py \ No newline at end of file diff --git a/venv/lib/python3.7/sre_constants.py b/venv/lib/python3.7/sre_constants.py new file mode 120000 index 0000000..d30f950 --- /dev/null +++ b/venv/lib/python3.7/sre_constants.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/sre_constants.py \ No newline at end of file diff --git a/venv/lib/python3.7/sre_parse.py b/venv/lib/python3.7/sre_parse.py new file mode 120000 index 0000000..1bc34a9 --- /dev/null +++ b/venv/lib/python3.7/sre_parse.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/sre_parse.py \ No newline at end of file diff --git a/venv/lib/python3.7/stat.py b/venv/lib/python3.7/stat.py new file mode 120000 index 0000000..3c3c328 --- /dev/null +++ b/venv/lib/python3.7/stat.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/stat.py \ No newline at end of file diff --git a/venv/lib/python3.7/struct.py b/venv/lib/python3.7/struct.py new file mode 120000 index 0000000..9a8e659 --- /dev/null +++ b/venv/lib/python3.7/struct.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/struct.py \ No newline at end of file diff --git a/venv/lib/python3.7/tarfile.py b/venv/lib/python3.7/tarfile.py new file mode 120000 index 0000000..3bd1674 --- /dev/null +++ b/venv/lib/python3.7/tarfile.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tarfile.py \ No newline at end of file diff --git a/venv/lib/python3.7/tempfile.py b/venv/lib/python3.7/tempfile.py new file mode 120000 index 0000000..ba621ac --- /dev/null +++ b/venv/lib/python3.7/tempfile.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tempfile.py \ No newline at end of file diff --git a/venv/lib/python3.7/token.py b/venv/lib/python3.7/token.py new file mode 120000 index 0000000..a252819 --- /dev/null +++ b/venv/lib/python3.7/token.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/token.py \ No newline at end of file diff --git a/venv/lib/python3.7/tokenize.py b/venv/lib/python3.7/tokenize.py new file mode 120000 index 0000000..005222d --- /dev/null +++ b/venv/lib/python3.7/tokenize.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tokenize.py \ No newline at end of file diff --git a/venv/lib/python3.7/types.py b/venv/lib/python3.7/types.py new file mode 120000 index 0000000..dd77f9c --- /dev/null +++ b/venv/lib/python3.7/types.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/types.py \ No newline at end of file diff --git a/venv/lib/python3.7/warnings.py b/venv/lib/python3.7/warnings.py new file mode 120000 index 0000000..c5e80d5 --- /dev/null +++ b/venv/lib/python3.7/warnings.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/warnings.py \ No newline at end of file diff --git a/venv/lib/python3.7/weakref.py b/venv/lib/python3.7/weakref.py new file mode 120000 index 0000000..e947c30 --- /dev/null +++ b/venv/lib/python3.7/weakref.py @@ -0,0 +1 @@ +/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/weakref.py \ No newline at end of file diff --git a/venv/pip-selfcheck.json b/venv/pip-selfcheck.json new file mode 100644 index 0000000..0826a34 --- /dev/null +++ b/venv/pip-selfcheck.json @@ -0,0 +1 @@ +{"last_check":"2018-11-26T10:44:25Z","pypi_version":"18.1"} \ No newline at end of file From ba582096c2eca475a48dfd6da14350dd5c2d326e Mon Sep 17 00:00:00 2001 From: unixtreme Date: Mon, 26 Nov 2018 12:20:12 +0000 Subject: [PATCH 036/115] Adds Windows venv with dependencies --- D3Edit.bat | 2 + D3Edit.py | 11 +- winvenv/Include/Python-ast.h | 637 ++ winvenv/Include/Python.h | 140 + winvenv/Include/abstract.h | 1109 +++ winvenv/Include/accu.h | 37 + winvenv/Include/asdl.h | 46 + winvenv/Include/ast.h | 29 + winvenv/Include/bitset.h | 32 + winvenv/Include/bltinmodule.h | 14 + winvenv/Include/boolobject.h | 34 + winvenv/Include/bytearrayobject.h | 62 + winvenv/Include/bytes_methods.h | 69 + winvenv/Include/bytesobject.h | 224 + winvenv/Include/cellobject.h | 29 + winvenv/Include/ceval.h | 237 + winvenv/Include/classobject.h | 58 + winvenv/Include/code.h | 157 + winvenv/Include/codecs.h | 240 + winvenv/Include/compile.h | 93 + winvenv/Include/complexobject.h | 69 + winvenv/Include/context.h | 84 + winvenv/Include/datetime.h | 273 + winvenv/Include/descrobject.h | 110 + winvenv/Include/dictobject.h | 179 + winvenv/Include/dtoa.h | 19 + winvenv/Include/dynamic_annotations.h | 499 + winvenv/Include/enumobject.h | 17 + winvenv/Include/errcode.h | 38 + winvenv/Include/eval.h | 37 + winvenv/Include/fileobject.h | 55 + winvenv/Include/fileutils.h | 177 + winvenv/Include/floatobject.h | 130 + winvenv/Include/frameobject.h | 93 + winvenv/Include/funcobject.h | 103 + winvenv/Include/genobject.h | 105 + winvenv/Include/graminit.h | 89 + winvenv/Include/grammar.h | 94 + winvenv/Include/import.h | 151 + winvenv/Include/intrcheck.h | 33 + winvenv/Include/iterobject.h | 25 + winvenv/Include/listobject.h | 81 + winvenv/Include/longintrepr.h | 99 + winvenv/Include/longobject.h | 220 + winvenv/Include/marshal.h | 28 + winvenv/Include/memoryobject.h | 72 + winvenv/Include/metagrammar.h | 18 + winvenv/Include/methodobject.h | 135 + winvenv/Include/modsupport.h | 229 + winvenv/Include/moduleobject.h | 89 + winvenv/Include/namespaceobject.h | 19 + winvenv/Include/node.h | 44 + winvenv/Include/object.h | 1104 +++ winvenv/Include/objimpl.h | 370 + winvenv/Include/odictobject.h | 43 + winvenv/Include/opcode.h | 147 + winvenv/Include/osdefs.h | 47 + winvenv/Include/osmodule.h | 17 + winvenv/Include/parsetok.h | 108 + winvenv/Include/patchlevel.h | 35 + winvenv/Include/pgen.h | 18 + winvenv/Include/pgenheaders.h | 43 + winvenv/Include/py_curses.h | 159 + winvenv/Include/pyarena.h | 64 + winvenv/Include/pyatomic.h | 535 ++ winvenv/Include/pycapsule.h | 59 + winvenv/Include/pyconfig.h | 693 ++ winvenv/Include/pyctype.h | 33 + winvenv/Include/pydebug.h | 40 + winvenv/Include/pydtrace.h | 57 + winvenv/Include/pyerrors.h | 504 + winvenv/Include/pyexpat.h | 55 + winvenv/Include/pyfpe.h | 12 + winvenv/Include/pyhash.h | 145 + winvenv/Include/pylifecycle.h | 226 + winvenv/Include/pymacconfig.h | 102 + winvenv/Include/pymacro.h | 100 + winvenv/Include/pymath.h | 230 + winvenv/Include/pymem.h | 244 + winvenv/Include/pyport.h | 793 ++ winvenv/Include/pystate.h | 455 + winvenv/Include/pystrcmp.h | 23 + winvenv/Include/pystrhex.h | 19 + winvenv/Include/pystrtod.h | 45 + winvenv/Include/pythonrun.h | 181 + winvenv/Include/pythread.h | 155 + winvenv/Include/pytime.h | 246 + winvenv/Include/rangeobject.h | 27 + winvenv/Include/setobject.h | 108 + winvenv/Include/sliceobject.h | 63 + winvenv/Include/structmember.h | 74 + winvenv/Include/structseq.h | 49 + winvenv/Include/symtable.h | 118 + winvenv/Include/sysmodule.h | 48 + winvenv/Include/token.h | 92 + winvenv/Include/traceback.h | 119 + winvenv/Include/tupleobject.h | 73 + winvenv/Include/typeslots.h | 85 + winvenv/Include/ucnhash.h | 36 + winvenv/Include/unicodeobject.h | 2334 +++++ winvenv/Include/warnings.h | 67 + winvenv/Include/weakrefobject.h | 86 + winvenv/Lib/__future__.py | 146 + winvenv/Lib/_bootlocale.py | 46 + winvenv/Lib/_collections_abc.py | 1011 ++ winvenv/Lib/_dummy_thread.py | 163 + winvenv/Lib/_weakrefset.py | 196 + winvenv/Lib/abc.py | 170 + winvenv/Lib/base64.py | 595 ++ winvenv/Lib/bisect.py | 92 + winvenv/Lib/codecs.py | 1114 +++ winvenv/Lib/collections/__init__.py | 1279 +++ winvenv/Lib/collections/abc.py | 2 + winvenv/Lib/copy.py | 313 + winvenv/Lib/copyreg.py | 206 + winvenv/Lib/distutils/__init__.py | 116 + winvenv/Lib/distutils/distutils.cfg | 6 + winvenv/Lib/encodings/__init__.py | 170 + winvenv/Lib/encodings/aliases.py | 550 ++ winvenv/Lib/encodings/ascii.py | 50 + winvenv/Lib/encodings/base64_codec.py | 55 + winvenv/Lib/encodings/big5.py | 39 + winvenv/Lib/encodings/big5hkscs.py | 39 + winvenv/Lib/encodings/bz2_codec.py | 78 + winvenv/Lib/encodings/charmap.py | 69 + winvenv/Lib/encodings/cp037.py | 307 + winvenv/Lib/encodings/cp1006.py | 307 + winvenv/Lib/encodings/cp1026.py | 307 + winvenv/Lib/encodings/cp1125.py | 698 ++ winvenv/Lib/encodings/cp1140.py | 307 + winvenv/Lib/encodings/cp1250.py | 307 + winvenv/Lib/encodings/cp1251.py | 307 + winvenv/Lib/encodings/cp1252.py | 307 + winvenv/Lib/encodings/cp1253.py | 307 + winvenv/Lib/encodings/cp1254.py | 307 + winvenv/Lib/encodings/cp1255.py | 307 + winvenv/Lib/encodings/cp1256.py | 307 + winvenv/Lib/encodings/cp1257.py | 307 + winvenv/Lib/encodings/cp1258.py | 307 + winvenv/Lib/encodings/cp273.py | 307 + winvenv/Lib/encodings/cp424.py | 307 + winvenv/Lib/encodings/cp437.py | 698 ++ winvenv/Lib/encodings/cp500.py | 307 + winvenv/Lib/encodings/cp65001.py | 43 + winvenv/Lib/encodings/cp720.py | 309 + winvenv/Lib/encodings/cp737.py | 698 ++ winvenv/Lib/encodings/cp775.py | 697 ++ winvenv/Lib/encodings/cp850.py | 698 ++ winvenv/Lib/encodings/cp852.py | 698 ++ winvenv/Lib/encodings/cp855.py | 698 ++ winvenv/Lib/encodings/cp856.py | 307 + winvenv/Lib/encodings/cp857.py | 694 ++ winvenv/Lib/encodings/cp858.py | 698 ++ winvenv/Lib/encodings/cp860.py | 698 ++ winvenv/Lib/encodings/cp861.py | 698 ++ winvenv/Lib/encodings/cp862.py | 698 ++ winvenv/Lib/encodings/cp863.py | 698 ++ winvenv/Lib/encodings/cp864.py | 690 ++ winvenv/Lib/encodings/cp865.py | 698 ++ winvenv/Lib/encodings/cp866.py | 698 ++ winvenv/Lib/encodings/cp869.py | 689 ++ winvenv/Lib/encodings/cp874.py | 307 + winvenv/Lib/encodings/cp875.py | 307 + winvenv/Lib/encodings/cp932.py | 39 + winvenv/Lib/encodings/cp949.py | 39 + winvenv/Lib/encodings/cp950.py | 39 + winvenv/Lib/encodings/euc_jis_2004.py | 39 + winvenv/Lib/encodings/euc_jisx0213.py | 39 + winvenv/Lib/encodings/euc_jp.py | 39 + winvenv/Lib/encodings/euc_kr.py | 39 + winvenv/Lib/encodings/gb18030.py | 39 + winvenv/Lib/encodings/gb2312.py | 39 + winvenv/Lib/encodings/gbk.py | 39 + winvenv/Lib/encodings/hex_codec.py | 55 + winvenv/Lib/encodings/hp_roman8.py | 314 + winvenv/Lib/encodings/hz.py | 39 + winvenv/Lib/encodings/idna.py | 309 + winvenv/Lib/encodings/iso2022_jp.py | 39 + winvenv/Lib/encodings/iso2022_jp_1.py | 39 + winvenv/Lib/encodings/iso2022_jp_2.py | 39 + winvenv/Lib/encodings/iso2022_jp_2004.py | 39 + winvenv/Lib/encodings/iso2022_jp_3.py | 39 + winvenv/Lib/encodings/iso2022_jp_ext.py | 39 + winvenv/Lib/encodings/iso2022_kr.py | 39 + winvenv/Lib/encodings/iso8859_1.py | 307 + winvenv/Lib/encodings/iso8859_10.py | 307 + winvenv/Lib/encodings/iso8859_11.py | 307 + winvenv/Lib/encodings/iso8859_13.py | 307 + winvenv/Lib/encodings/iso8859_14.py | 307 + winvenv/Lib/encodings/iso8859_15.py | 307 + winvenv/Lib/encodings/iso8859_16.py | 307 + winvenv/Lib/encodings/iso8859_2.py | 307 + winvenv/Lib/encodings/iso8859_3.py | 307 + winvenv/Lib/encodings/iso8859_4.py | 307 + winvenv/Lib/encodings/iso8859_5.py | 307 + winvenv/Lib/encodings/iso8859_6.py | 307 + winvenv/Lib/encodings/iso8859_7.py | 307 + winvenv/Lib/encodings/iso8859_8.py | 307 + winvenv/Lib/encodings/iso8859_9.py | 307 + winvenv/Lib/encodings/johab.py | 39 + winvenv/Lib/encodings/koi8_r.py | 307 + winvenv/Lib/encodings/koi8_t.py | 308 + winvenv/Lib/encodings/koi8_u.py | 307 + winvenv/Lib/encodings/kz1048.py | 307 + winvenv/Lib/encodings/latin_1.py | 50 + winvenv/Lib/encodings/mac_arabic.py | 698 ++ winvenv/Lib/encodings/mac_centeuro.py | 307 + winvenv/Lib/encodings/mac_croatian.py | 307 + winvenv/Lib/encodings/mac_cyrillic.py | 307 + winvenv/Lib/encodings/mac_farsi.py | 307 + winvenv/Lib/encodings/mac_greek.py | 307 + winvenv/Lib/encodings/mac_iceland.py | 307 + winvenv/Lib/encodings/mac_latin2.py | 312 + winvenv/Lib/encodings/mac_roman.py | 307 + winvenv/Lib/encodings/mac_romanian.py | 307 + winvenv/Lib/encodings/mac_turkish.py | 307 + winvenv/Lib/encodings/mbcs.py | 47 + winvenv/Lib/encodings/oem.py | 41 + winvenv/Lib/encodings/palmos.py | 308 + winvenv/Lib/encodings/ptcp154.py | 312 + winvenv/Lib/encodings/punycode.py | 237 + winvenv/Lib/encodings/quopri_codec.py | 56 + winvenv/Lib/encodings/raw_unicode_escape.py | 45 + winvenv/Lib/encodings/rot_13.py | 113 + winvenv/Lib/encodings/shift_jis.py | 39 + winvenv/Lib/encodings/shift_jis_2004.py | 39 + winvenv/Lib/encodings/shift_jisx0213.py | 39 + winvenv/Lib/encodings/tis_620.py | 307 + winvenv/Lib/encodings/undefined.py | 49 + winvenv/Lib/encodings/unicode_escape.py | 45 + winvenv/Lib/encodings/unicode_internal.py | 45 + winvenv/Lib/encodings/utf_16.py | 155 + winvenv/Lib/encodings/utf_16_be.py | 42 + winvenv/Lib/encodings/utf_16_le.py | 42 + winvenv/Lib/encodings/utf_32.py | 150 + winvenv/Lib/encodings/utf_32_be.py | 37 + winvenv/Lib/encodings/utf_32_le.py | 37 + winvenv/Lib/encodings/utf_7.py | 38 + winvenv/Lib/encodings/utf_8.py | 42 + winvenv/Lib/encodings/utf_8_sig.py | 130 + winvenv/Lib/encodings/uu_codec.py | 99 + winvenv/Lib/encodings/zlib_codec.py | 77 + winvenv/Lib/enum.py | 889 ++ winvenv/Lib/fnmatch.py | 128 + winvenv/Lib/functools.py | 833 ++ winvenv/Lib/genericpath.py | 151 + winvenv/Lib/hashlib.py | 252 + winvenv/Lib/heapq.py | 607 ++ winvenv/Lib/hmac.py | 188 + winvenv/Lib/imp.py | 345 + winvenv/Lib/importlib/__init__.py | 176 + winvenv/Lib/importlib/_bootstrap.py | 1164 +++ winvenv/Lib/importlib/_bootstrap_external.py | 1562 ++++ winvenv/Lib/importlib/abc.py | 388 + winvenv/Lib/importlib/machinery.py | 21 + winvenv/Lib/importlib/resources.py | 343 + winvenv/Lib/importlib/util.py | 300 + winvenv/Lib/io.py | 99 + winvenv/Lib/keyword.py | 96 + winvenv/Lib/linecache.py | 177 + winvenv/Lib/locale.py | 1749 ++++ winvenv/Lib/no-global-site-packages.txt | 0 winvenv/Lib/ntpath.py | 669 ++ winvenv/Lib/operator.py | 464 + winvenv/Lib/orig-prefix.txt | 1 + winvenv/Lib/os.py | 1078 +++ winvenv/Lib/posixpath.py | 522 ++ winvenv/Lib/random.py | 777 ++ winvenv/Lib/re.py | 366 + winvenv/Lib/reprlib.py | 161 + winvenv/Lib/rlcompleter.py | 205 + winvenv/Lib/shutil.py | 1169 +++ winvenv/Lib/site-packages/easy_install.py | 5 + .../site-packages/google/protobuf/__init__.py | 39 + .../site-packages/google/protobuf/any_pb2.py | 77 + .../google/protobuf/any_test_pb2.py | 87 + .../site-packages/google/protobuf/api_pb2.py | 249 + .../google/protobuf/compiler/__init__.py | 0 .../google/protobuf/compiler/plugin_pb2.py | 255 + .../google/protobuf/descriptor.py | 1076 +++ .../google/protobuf/descriptor_database.py | 162 + .../google/protobuf/descriptor_pb2.py | 2033 ++++ .../google/protobuf/descriptor_pool.py | 1057 +++ .../google/protobuf/duration_pb2.py | 77 + .../google/protobuf/empty_pb2.py | 63 + .../google/protobuf/field_mask_pb2.py | 70 + .../google/protobuf/internal/__init__.py | 0 .../protobuf/internal/_parameterized.py | 443 + .../google/protobuf/internal/any_test_pb2.py | 182 + .../protobuf/internal/api_implementation.py | 173 + .../google/protobuf/internal/containers.py | 630 ++ .../google/protobuf/internal/decoder.py | 854 ++ .../internal/descriptor_database_test.py | 124 + .../protobuf/internal/descriptor_pool_test.py | 1055 +++ .../internal/descriptor_pool_test1_pb2.py | 474 + .../internal/descriptor_pool_test2_pb2.py | 266 + .../protobuf/internal/descriptor_test.py | 1036 +++ .../google/protobuf/internal/encoder.py | 828 ++ .../protobuf/internal/enum_type_wrapper.py | 89 + .../protobuf/internal/factory_test1_pb2.py | 190 + .../protobuf/internal/factory_test2_pb2.py | 517 ++ .../internal/file_options_test_pb2.py | 82 + .../protobuf/internal/generator_test.py | 349 + .../internal/import_test_package/__init__.py | 33 + .../internal/import_test_package/inner_pb2.py | 69 + .../internal/import_test_package/outer_pb2.py | 72 + .../protobuf/internal/json_format_test.py | 1038 +++ .../protobuf/internal/message_factory_test.py | 222 + .../protobuf/internal/message_listener.py | 78 + .../internal/message_set_extensions_pb2.py | 209 + .../google/protobuf/internal/message_test.py | 2203 +++++ .../internal/missing_enum_values_pb2.py | 227 + .../internal/more_extensions_dynamic_pb2.py | 103 + .../protobuf/internal/more_extensions_pb2.py | 183 + .../protobuf/internal/more_messages_pb2.py | 103 + .../protobuf/internal/no_package_pb2.py | 97 + .../internal/packed_field_test_pb2.py | 334 + .../protobuf/internal/proto_builder_test.py | 96 + .../protobuf/internal/python_message.py | 1559 ++++ .../protobuf/internal/reflection_test.py | 3106 +++++++ .../internal/service_reflection_test.py | 144 + .../protobuf/internal/symbol_database_test.py | 138 + .../internal/test_bad_identifiers_pb2.py | 163 + .../google/protobuf/internal/test_util.py | 868 ++ .../protobuf/internal/testing_refleaks.py | 126 + .../protobuf/internal/text_encoding_test.py | 72 + .../protobuf/internal/text_format_test.py | 1656 ++++ .../google/protobuf/internal/type_checkers.py | 353 + .../protobuf/internal/unknown_fields_test.py | 336 + .../protobuf/internal/well_known_types.py | 839 ++ .../internal/well_known_types_test.py | 927 ++ .../google/protobuf/internal/wire_format.py | 268 + .../protobuf/internal/wire_format_test.py | 257 + .../google/protobuf/json_format.py | 785 ++ .../protobuf/map_proto2_unittest_pb2.py | 1312 +++ .../google/protobuf/map_unittest_pb2.py | 2813 ++++++ .../site-packages/google/protobuf/message.py | 308 + .../google/protobuf/message_factory.py | 151 + .../google/protobuf/proto_builder.py | 130 + .../google/protobuf/pyext/__init__.py | 4 + .../google/protobuf/pyext/cpp_message.py | 65 + .../google/protobuf/pyext/python_pb2.py | 233 + .../google/protobuf/reflection.py | 121 + .../site-packages/google/protobuf/service.py | 226 + .../google/protobuf/service_reflection.py | 284 + .../google/protobuf/source_context_pb2.py | 70 + .../google/protobuf/struct_pb2.py | 279 + .../google/protobuf/symbol_database.py | 189 + .../protobuf/test_messages_proto2_pb2.py | 1990 ++++ .../protobuf/test_messages_proto3_pb2.py | 2044 ++++ .../google/protobuf/text_encoding.py | 107 + .../google/protobuf/text_format.py | 1593 ++++ .../google/protobuf/timestamp_pb2.py | 77 + .../site-packages/google/protobuf/type_pb2.py | 540 ++ .../google/protobuf/unittest_arena_pb2.py | 120 + .../protobuf/unittest_custom_options_pb2.py | 1845 ++++ .../google/protobuf/unittest_import_pb2.py | 137 + .../protobuf/unittest_import_public_pb2.py | 70 + .../google/protobuf/unittest_mset_pb2.py | 255 + .../protobuf/unittest_mset_wire_format_pb2.py | 104 + .../protobuf/unittest_no_arena_import_pb2.py | 69 + .../google/protobuf/unittest_no_arena_pb2.py | 911 ++ .../unittest_no_generic_services_pb2.py | 125 + .../google/protobuf/unittest_pb2.py | 7082 ++++++++++++++ .../protobuf/unittest_proto3_arena_pb2.py | 999 ++ .../google/protobuf/util/__init__.py | 0 .../protobuf/util/json_format_proto3_pb2.py | 1895 ++++ .../google/protobuf/wrappers_pb2.py | 382 + .../pip-18.1.dist-info/INSTALLER | 1 + .../pip-18.1.dist-info/LICENSE.txt | 20 + .../site-packages/pip-18.1.dist-info/METADATA | 70 + .../site-packages/pip-18.1.dist-info/RECORD | 614 ++ .../site-packages/pip-18.1.dist-info/WHEEL | 6 + .../pip-18.1.dist-info/entry_points.txt | 5 + .../pip-18.1.dist-info/top_level.txt | 1 + winvenv/Lib/site-packages/pip/__init__.py | 1 + winvenv/Lib/site-packages/pip/__main__.py | 19 + .../site-packages/pip/_internal/__init__.py | 78 + .../site-packages/pip/_internal/build_env.py | 142 + .../Lib/site-packages/pip/_internal/cache.py | 202 + .../pip/_internal/cli/__init__.py | 4 + .../pip/_internal/cli/autocompletion.py | 152 + .../pip/_internal/cli/base_command.py | 278 + .../pip/_internal/cli/cmdoptions.py | 714 ++ .../pip/_internal/cli/main_parser.py | 96 + .../site-packages/pip/_internal/cli/parser.py | 261 + .../pip/_internal/cli/status_codes.py | 8 + .../pip/_internal/commands/__init__.py | 79 + .../pip/_internal/commands/check.py | 41 + .../pip/_internal/commands/completion.py | 94 + .../pip/_internal/commands/configuration.py | 227 + .../pip/_internal/commands/download.py | 174 + .../pip/_internal/commands/freeze.py | 96 + .../pip/_internal/commands/hash.py | 57 + .../pip/_internal/commands/help.py | 37 + .../pip/_internal/commands/install.py | 535 ++ .../pip/_internal/commands/list.py | 306 + .../pip/_internal/commands/search.py | 135 + .../pip/_internal/commands/show.py | 168 + .../pip/_internal/commands/uninstall.py | 78 + .../pip/_internal/commands/wheel.py | 183 + .../pip/_internal/configuration.py | 387 + .../site-packages/pip/_internal/download.py | 921 ++ .../site-packages/pip/_internal/exceptions.py | 268 + .../Lib/site-packages/pip/_internal/index.py | 899 ++ .../site-packages/pip/_internal/locations.py | 194 + .../pip/_internal/models/__init__.py | 2 + .../pip/_internal/models/candidate.py | 23 + .../pip/_internal/models/format_control.py | 62 + .../pip/_internal/models/index.py | 29 + .../pip/_internal/models/link.py | 141 + .../pip/_internal/operations/__init__.py | 0 .../pip/_internal/operations/check.py | 148 + .../pip/_internal/operations/freeze.py | 264 + .../pip/_internal/operations/prepare.py | 355 + .../site-packages/pip/_internal/pep425tags.py | 317 + .../site-packages/pip/_internal/pyproject.py | 144 + .../pip/_internal/req/__init__.py | 69 + .../pip/_internal/req/constructors.py | 298 + .../pip/_internal/req/req_file.py | 340 + .../pip/_internal/req/req_install.py | 860 ++ .../pip/_internal/req/req_set.py | 181 + .../pip/_internal/req/req_tracker.py | 76 + .../pip/_internal/req/req_uninstall.py | 460 + .../site-packages/pip/_internal/resolve.py | 353 + .../pip/_internal/utils/__init__.py | 0 .../pip/_internal/utils/appdirs.py | 258 + .../pip/_internal/utils/compat.py | 248 + .../pip/_internal/utils/deprecation.py | 89 + .../pip/_internal/utils/encoding.py | 33 + .../pip/_internal/utils/filesystem.py | 28 + .../pip/_internal/utils/glibc.py | 84 + .../pip/_internal/utils/hashes.py | 94 + .../pip/_internal/utils/logging.py | 225 + .../site-packages/pip/_internal/utils/misc.py | 940 ++ .../pip/_internal/utils/models.py | 40 + .../pip/_internal/utils/outdated.py | 154 + .../pip/_internal/utils/packaging.py | 75 + .../pip/_internal/utils/setuptools_build.py | 8 + .../pip/_internal/utils/temp_dir.py | 82 + .../pip/_internal/utils/typing.py | 29 + .../site-packages/pip/_internal/utils/ui.py | 421 + .../pip/_internal/vcs/__init__.py | 509 + .../site-packages/pip/_internal/vcs/bazaar.py | 112 + .../site-packages/pip/_internal/vcs/git.py | 346 + .../pip/_internal/vcs/mercurial.py | 101 + .../pip/_internal/vcs/subversion.py | 213 + .../Lib/site-packages/pip/_internal/wheel.py | 831 ++ .../Lib/site-packages/pip/_vendor/__init__.py | 110 + .../Lib/site-packages/pip/_vendor/appdirs.py | 604 ++ .../pip/_vendor/cachecontrol/__init__.py | 11 + .../pip/_vendor/cachecontrol/_cmd.py | 57 + .../pip/_vendor/cachecontrol/adapter.py | 133 + .../pip/_vendor/cachecontrol/cache.py | 39 + .../_vendor/cachecontrol/caches/__init__.py | 2 + .../_vendor/cachecontrol/caches/file_cache.py | 146 + .../cachecontrol/caches/redis_cache.py | 33 + .../pip/_vendor/cachecontrol/compat.py | 29 + .../pip/_vendor/cachecontrol/controller.py | 367 + .../pip/_vendor/cachecontrol/filewrapper.py | 80 + .../pip/_vendor/cachecontrol/heuristics.py | 135 + .../pip/_vendor/cachecontrol/serialize.py | 186 + .../pip/_vendor/cachecontrol/wrapper.py | 29 + .../pip/_vendor/certifi/__init__.py | 3 + .../pip/_vendor/certifi/__main__.py | 2 + .../pip/_vendor/certifi/cacert.pem | 4300 +++++++++ .../site-packages/pip/_vendor/certifi/core.py | 37 + .../pip/_vendor/chardet/__init__.py | 39 + .../pip/_vendor/chardet/big5freq.py | 386 + .../pip/_vendor/chardet/big5prober.py | 47 + .../pip/_vendor/chardet/chardistribution.py | 233 + .../pip/_vendor/chardet/charsetgroupprober.py | 106 + .../pip/_vendor/chardet/charsetprober.py | 145 + .../pip/_vendor/chardet/cli/__init__.py | 1 + .../pip/_vendor/chardet/cli/chardetect.py | 85 + .../pip/_vendor/chardet/codingstatemachine.py | 88 + .../pip/_vendor/chardet/compat.py | 34 + .../pip/_vendor/chardet/cp949prober.py | 49 + .../pip/_vendor/chardet/enums.py | 76 + .../pip/_vendor/chardet/escprober.py | 101 + .../pip/_vendor/chardet/escsm.py | 246 + .../pip/_vendor/chardet/eucjpprober.py | 92 + .../pip/_vendor/chardet/euckrfreq.py | 195 + .../pip/_vendor/chardet/euckrprober.py | 47 + .../pip/_vendor/chardet/euctwfreq.py | 387 + .../pip/_vendor/chardet/euctwprober.py | 46 + .../pip/_vendor/chardet/gb2312freq.py | 283 + .../pip/_vendor/chardet/gb2312prober.py | 46 + .../pip/_vendor/chardet/hebrewprober.py | 292 + .../pip/_vendor/chardet/jisfreq.py | 325 + .../pip/_vendor/chardet/jpcntx.py | 233 + .../pip/_vendor/chardet/langbulgarianmodel.py | 228 + .../pip/_vendor/chardet/langcyrillicmodel.py | 333 + .../pip/_vendor/chardet/langgreekmodel.py | 225 + .../pip/_vendor/chardet/langhebrewmodel.py | 200 + .../pip/_vendor/chardet/langhungarianmodel.py | 225 + .../pip/_vendor/chardet/langthaimodel.py | 199 + .../pip/_vendor/chardet/langturkishmodel.py | 193 + .../pip/_vendor/chardet/latin1prober.py | 145 + .../pip/_vendor/chardet/mbcharsetprober.py | 91 + .../pip/_vendor/chardet/mbcsgroupprober.py | 54 + .../pip/_vendor/chardet/mbcssm.py | 572 ++ .../pip/_vendor/chardet/sbcharsetprober.py | 132 + .../pip/_vendor/chardet/sbcsgroupprober.py | 73 + .../pip/_vendor/chardet/sjisprober.py | 92 + .../pip/_vendor/chardet/universaldetector.py | 286 + .../pip/_vendor/chardet/utf8prober.py | 82 + .../pip/_vendor/chardet/version.py | 9 + .../pip/_vendor/colorama/__init__.py | 7 + .../pip/_vendor/colorama/ansi.py | 102 + .../pip/_vendor/colorama/ansitowin32.py | 236 + .../pip/_vendor/colorama/initialise.py | 82 + .../pip/_vendor/colorama/win32.py | 156 + .../pip/_vendor/colorama/winterm.py | 162 + .../pip/_vendor/distlib/__init__.py | 23 + .../pip/_vendor/distlib/_backport/__init__.py | 6 + .../pip/_vendor/distlib/_backport/misc.py | 41 + .../pip/_vendor/distlib/_backport/shutil.py | 761 ++ .../_vendor/distlib/_backport/sysconfig.cfg | 84 + .../_vendor/distlib/_backport/sysconfig.py | 788 ++ .../pip/_vendor/distlib/_backport/tarfile.py | 2607 ++++++ .../pip/_vendor/distlib/compat.py | 1120 +++ .../pip/_vendor/distlib/database.py | 1336 +++ .../pip/_vendor/distlib/index.py | 516 ++ .../pip/_vendor/distlib/locators.py | 1292 +++ .../pip/_vendor/distlib/manifest.py | 393 + .../pip/_vendor/distlib/markers.py | 131 + .../pip/_vendor/distlib/metadata.py | 1091 +++ .../pip/_vendor/distlib/resources.py | 355 + .../pip/_vendor/distlib/scripts.py | 415 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 92672 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 102400 bytes .../site-packages/pip/_vendor/distlib/util.py | 1755 ++++ .../pip/_vendor/distlib/version.py | 736 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 89088 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 99328 bytes .../pip/_vendor/distlib/wheel.py | 984 ++ .../Lib/site-packages/pip/_vendor/distro.py | 1197 +++ .../pip/_vendor/html5lib/__init__.py | 35 + .../pip/_vendor/html5lib/_ihatexml.py | 288 + .../pip/_vendor/html5lib/_inputstream.py | 923 ++ .../pip/_vendor/html5lib/_tokenizer.py | 1721 ++++ .../pip/_vendor/html5lib/_trie/__init__.py | 14 + .../pip/_vendor/html5lib/_trie/_base.py | 37 + .../pip/_vendor/html5lib/_trie/datrie.py | 44 + .../pip/_vendor/html5lib/_trie/py.py | 67 + .../pip/_vendor/html5lib/_utils.py | 124 + .../pip/_vendor/html5lib/constants.py | 2947 ++++++ .../pip/_vendor/html5lib/filters/__init__.py | 0 .../filters/alphabeticalattributes.py | 29 + .../pip/_vendor/html5lib/filters/base.py | 12 + .../html5lib/filters/inject_meta_charset.py | 73 + .../pip/_vendor/html5lib/filters/lint.py | 93 + .../_vendor/html5lib/filters/optionaltags.py | 207 + .../pip/_vendor/html5lib/filters/sanitizer.py | 896 ++ .../_vendor/html5lib/filters/whitespace.py | 38 + .../pip/_vendor/html5lib/html5parser.py | 2791 ++++++ .../pip/_vendor/html5lib/serializer.py | 409 + .../_vendor/html5lib/treeadapters/__init__.py | 30 + .../_vendor/html5lib/treeadapters/genshi.py | 54 + .../pip/_vendor/html5lib/treeadapters/sax.py | 50 + .../_vendor/html5lib/treebuilders/__init__.py | 88 + .../pip/_vendor/html5lib/treebuilders/base.py | 417 + .../pip/_vendor/html5lib/treebuilders/dom.py | 236 + .../_vendor/html5lib/treebuilders/etree.py | 340 + .../html5lib/treebuilders/etree_lxml.py | 366 + .../_vendor/html5lib/treewalkers/__init__.py | 154 + .../pip/_vendor/html5lib/treewalkers/base.py | 252 + .../pip/_vendor/html5lib/treewalkers/dom.py | 43 + .../pip/_vendor/html5lib/treewalkers/etree.py | 130 + .../html5lib/treewalkers/etree_lxml.py | 213 + .../_vendor/html5lib/treewalkers/genshi.py | 69 + .../pip/_vendor/idna/__init__.py | 2 + .../site-packages/pip/_vendor/idna/codec.py | 118 + .../site-packages/pip/_vendor/idna/compat.py | 12 + .../site-packages/pip/_vendor/idna/core.py | 399 + .../pip/_vendor/idna/idnadata.py | 1893 ++++ .../pip/_vendor/idna/intranges.py | 53 + .../pip/_vendor/idna/package_data.py | 2 + .../pip/_vendor/idna/uts46data.py | 8179 +++++++++++++++++ .../site-packages/pip/_vendor/ipaddress.py | 2419 +++++ .../pip/_vendor/lockfile/__init__.py | 347 + .../pip/_vendor/lockfile/linklockfile.py | 73 + .../pip/_vendor/lockfile/mkdirlockfile.py | 84 + .../pip/_vendor/lockfile/pidlockfile.py | 190 + .../pip/_vendor/lockfile/sqlitelockfile.py | 156 + .../pip/_vendor/lockfile/symlinklockfile.py | 70 + .../pip/_vendor/msgpack/__init__.py | 66 + .../pip/_vendor/msgpack/_version.py | 1 + .../pip/_vendor/msgpack/exceptions.py | 41 + .../pip/_vendor/msgpack/fallback.py | 977 ++ .../pip/_vendor/packaging/__about__.py | 21 + .../pip/_vendor/packaging/__init__.py | 14 + .../pip/_vendor/packaging/_compat.py | 30 + .../pip/_vendor/packaging/_structures.py | 70 + .../pip/_vendor/packaging/markers.py | 301 + .../pip/_vendor/packaging/requirements.py | 130 + .../pip/_vendor/packaging/specifiers.py | 774 ++ .../pip/_vendor/packaging/utils.py | 63 + .../pip/_vendor/packaging/version.py | 441 + .../pip/_vendor/pep517/__init__.py | 4 + .../pip/_vendor/pep517/_in_process.py | 182 + .../site-packages/pip/_vendor/pep517/check.py | 194 + .../pip/_vendor/pep517/colorlog.py | 110 + .../pip/_vendor/pep517/compat.py | 23 + .../pip/_vendor/pep517/envbuild.py | 150 + .../pip/_vendor/pep517/wrappers.py | 134 + .../pip/_vendor/pkg_resources/__init__.py | 3149 +++++++ .../pip/_vendor/pkg_resources/py31compat.py | 23 + .../pip/_vendor/progress/__init__.py | 127 + .../site-packages/pip/_vendor/progress/bar.py | 94 + .../pip/_vendor/progress/counter.py | 48 + .../pip/_vendor/progress/helpers.py | 91 + .../pip/_vendor/progress/spinner.py | 44 + .../site-packages/pip/_vendor/pyparsing.py | 5742 ++++++++++++ .../pip/_vendor/pytoml/__init__.py | 3 + .../site-packages/pip/_vendor/pytoml/core.py | 13 + .../pip/_vendor/pytoml/parser.py | 374 + .../pip/_vendor/pytoml/writer.py | 127 + .../pip/_vendor/requests/__init__.py | 138 + .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 42 + .../pip/_vendor/requests/adapters.py | 530 ++ .../site-packages/pip/_vendor/requests/api.py | 152 + .../pip/_vendor/requests/auth.py | 305 + .../pip/_vendor/requests/certs.py | 18 + .../pip/_vendor/requests/compat.py | 75 + .../pip/_vendor/requests/cookies.py | 546 ++ .../pip/_vendor/requests/exceptions.py | 126 + .../pip/_vendor/requests/help.py | 120 + .../pip/_vendor/requests/hooks.py | 34 + .../pip/_vendor/requests/models.py | 952 ++ .../pip/_vendor/requests/packages.py | 16 + .../pip/_vendor/requests/sessions.py | 741 ++ .../pip/_vendor/requests/status_codes.py | 120 + .../pip/_vendor/requests/structures.py | 103 + .../pip/_vendor/requests/utils.py | 976 ++ .../Lib/site-packages/pip/_vendor/retrying.py | 267 + winvenv/Lib/site-packages/pip/_vendor/six.py | 891 ++ .../pip/_vendor/urllib3/__init__.py | 97 + .../pip/_vendor/urllib3/_collections.py | 332 + .../pip/_vendor/urllib3/connection.py | 403 + .../pip/_vendor/urllib3/connectionpool.py | 906 ++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 593 ++ .../contrib/_securetransport/low_level.py | 346 + .../pip/_vendor/urllib3/contrib/appengine.py | 305 + .../pip/_vendor/urllib3/contrib/ntlmpool.py | 112 + .../pip/_vendor/urllib3/contrib/pyopenssl.py | 457 + .../urllib3/contrib/securetransport.py | 804 ++ .../pip/_vendor/urllib3/contrib/socks.py | 192 + .../pip/_vendor/urllib3/exceptions.py | 246 + .../pip/_vendor/urllib3/fields.py | 178 + .../pip/_vendor/urllib3/filepost.py | 98 + .../pip/_vendor/urllib3/packages/__init__.py | 5 + .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 53 + .../_vendor/urllib3/packages/ordered_dict.py | 259 + .../pip/_vendor/urllib3/packages/six.py | 868 ++ .../packages/ssl_match_hostname/__init__.py | 19 + .../ssl_match_hostname/_implementation.py | 157 + .../pip/_vendor/urllib3/poolmanager.py | 449 + .../pip/_vendor/urllib3/request.py | 150 + .../pip/_vendor/urllib3/response.py | 676 ++ .../pip/_vendor/urllib3/util/__init__.py | 54 + .../pip/_vendor/urllib3/util/connection.py | 126 + .../pip/_vendor/urllib3/util/queue.py | 21 + .../pip/_vendor/urllib3/util/request.py | 118 + .../pip/_vendor/urllib3/util/response.py | 81 + .../pip/_vendor/urllib3/util/retry.py | 411 + .../pip/_vendor/urllib3/util/ssl_.py | 396 + .../pip/_vendor/urllib3/util/timeout.py | 242 + .../pip/_vendor/urllib3/util/url.py | 230 + .../pip/_vendor/urllib3/util/wait.py | 153 + .../pip/_vendor/webencodings/__init__.py | 342 + .../pip/_vendor/webencodings/labels.py | 231 + .../pip/_vendor/webencodings/mklabels.py | 59 + .../pip/_vendor/webencodings/tests.py | 153 + .../_vendor/webencodings/x_user_defined.py | 325 + .../site-packages/pkg_resources/__init__.py | 3171 +++++++ .../pkg_resources/_vendor/__init__.py | 0 .../pkg_resources/_vendor/appdirs.py | 608 ++ .../_vendor/packaging/__about__.py | 21 + .../_vendor/packaging/__init__.py | 14 + .../_vendor/packaging/_compat.py | 30 + .../_vendor/packaging/_structures.py | 68 + .../_vendor/packaging/markers.py | 301 + .../_vendor/packaging/requirements.py | 127 + .../_vendor/packaging/specifiers.py | 774 ++ .../pkg_resources/_vendor/packaging/utils.py | 14 + .../_vendor/packaging/version.py | 393 + .../pkg_resources/_vendor/pyparsing.py | 5742 ++++++++++++ .../pkg_resources/_vendor/six.py | 868 ++ .../pkg_resources/extern/__init__.py | 73 + .../site-packages/pkg_resources/py31compat.py | 23 + .../site-packages/protobuf-3.6.1-nspkg.pth | 1 + .../protobuf-3.6.1.dist-info/DESCRIPTION.rst | 3 + .../protobuf-3.6.1.dist-info/INSTALLER | 1 + .../protobuf-3.6.1.dist-info/METADATA | 22 + .../protobuf-3.6.1.dist-info/RECORD | 199 + .../protobuf-3.6.1.dist-info/WHEEL | 6 + .../protobuf-3.6.1.dist-info/metadata.json | 1 + .../namespace_packages.txt | 1 + .../protobuf-3.6.1.dist-info/top_level.txt | 1 + .../setuptools-40.6.2.dist-info/INSTALLER | 1 + .../setuptools-40.6.2.dist-info/LICENSE | 19 + .../setuptools-40.6.2.dist-info/METADATA | 73 + .../setuptools-40.6.2.dist-info/RECORD | 188 + .../setuptools-40.6.2.dist-info/WHEEL | 6 + .../dependency_links.txt | 2 + .../entry_points.txt | 65 + .../setuptools-40.6.2.dist-info/top_level.txt | 3 + .../setuptools-40.6.2.dist-info/zip-safe | 1 + .../Lib/site-packages/setuptools/__init__.py | 195 + .../setuptools/_deprecation_warning.py | 7 + .../setuptools/_vendor/__init__.py | 0 .../setuptools/_vendor/packaging/__about__.py | 21 + .../setuptools/_vendor/packaging/__init__.py | 14 + .../setuptools/_vendor/packaging/_compat.py | 30 + .../_vendor/packaging/_structures.py | 68 + .../setuptools/_vendor/packaging/markers.py | 301 + .../_vendor/packaging/requirements.py | 127 + .../_vendor/packaging/specifiers.py | 774 ++ .../setuptools/_vendor/packaging/utils.py | 14 + .../setuptools/_vendor/packaging/version.py | 393 + .../setuptools/_vendor/pyparsing.py | 5742 ++++++++++++ .../site-packages/setuptools/_vendor/six.py | 868 ++ .../site-packages/setuptools/archive_util.py | 173 + .../site-packages/setuptools/build_meta.py | 182 + .../Lib/site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes winvenv/Lib/site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 18 + .../site-packages/setuptools/command/alias.py | 80 + .../setuptools/command/bdist_egg.py | 502 + .../setuptools/command/bdist_rpm.py | 43 + .../setuptools/command/bdist_wininst.py | 21 + .../setuptools/command/build_clib.py | 98 + .../setuptools/command/build_ext.py | 321 + .../setuptools/command/build_py.py | 270 + .../setuptools/command/develop.py | 218 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2342 +++++ .../setuptools/command/egg_info.py | 716 ++ .../setuptools/command/install.py | 125 + .../setuptools/command/install_egg_info.py | 62 + .../setuptools/command/install_lib.py | 121 + .../setuptools/command/install_scripts.py | 65 + .../setuptools/command/launcher manifest.xml | 15 + .../setuptools/command/py36compat.py | 136 + .../setuptools/command/register.py | 18 + .../setuptools/command/rotate.py | 66 + .../setuptools/command/saveopts.py | 22 + .../site-packages/setuptools/command/sdist.py | 200 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 270 + .../setuptools/command/upload.py | 196 + .../setuptools/command/upload_docs.py | 206 + .../Lib/site-packages/setuptools/config.py | 635 ++ .../Lib/site-packages/setuptools/dep_util.py | 23 + .../Lib/site-packages/setuptools/depends.py | 186 + winvenv/Lib/site-packages/setuptools/dist.py | 1147 +++ .../Lib/site-packages/setuptools/extension.py | 57 + .../setuptools/extern/__init__.py | 73 + winvenv/Lib/site-packages/setuptools/glibc.py | 86 + winvenv/Lib/site-packages/setuptools/glob.py | 174 + .../Lib/site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes winvenv/Lib/site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/launch.py | 35 + .../site-packages/setuptools/lib2to3_ex.py | 62 + .../Lib/site-packages/setuptools/monkey.py | 179 + winvenv/Lib/site-packages/setuptools/msvc.py | 1301 +++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1128 +++ .../site-packages/setuptools/pep425tags.py | 319 + .../site-packages/setuptools/py27compat.py | 28 + .../site-packages/setuptools/py31compat.py | 32 + .../site-packages/setuptools/py33compat.py | 55 + .../site-packages/setuptools/py36compat.py | 82 + .../Lib/site-packages/setuptools/sandbox.py | 491 + .../setuptools/script (dev).tmpl | 6 + .../Lib/site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/site-patch.py | 74 + .../site-packages/setuptools/ssl_support.py | 260 + .../site-packages/setuptools/unicode_utils.py | 44 + .../Lib/site-packages/setuptools/version.py | 6 + winvenv/Lib/site-packages/setuptools/wheel.py | 210 + .../setuptools/windows_support.py | 29 + .../six-1.11.0.dist-info/DESCRIPTION.rst | 27 + .../six-1.11.0.dist-info/INSTALLER | 1 + .../six-1.11.0.dist-info/METADATA | 43 + .../site-packages/six-1.11.0.dist-info/RECORD | 9 + .../site-packages/six-1.11.0.dist-info/WHEEL | 6 + .../six-1.11.0.dist-info/metadata.json | 1 + .../six-1.11.0.dist-info/top_level.txt | 1 + winvenv/Lib/site-packages/six.py | 891 ++ .../wheel-0.32.3.dist-info/INSTALLER | 1 + .../wheel-0.32.3.dist-info/LICENSE.txt | 22 + .../wheel-0.32.3.dist-info/METADATA | 60 + .../wheel-0.32.3.dist-info/RECORD | 34 + .../wheel-0.32.3.dist-info/WHEEL | 6 + .../wheel-0.32.3.dist-info/entry_points.txt | 6 + .../wheel-0.32.3.dist-info/top_level.txt | 1 + winvenv/Lib/site-packages/wheel/__init__.py | 2 + winvenv/Lib/site-packages/wheel/__main__.py | 19 + .../Lib/site-packages/wheel/bdist_wheel.py | 368 + .../Lib/site-packages/wheel/cli/__init__.py | 87 + .../Lib/site-packages/wheel/cli/convert.py | 269 + .../Lib/site-packages/wheel/cli/install.py | 0 winvenv/Lib/site-packages/wheel/cli/pack.py | 54 + winvenv/Lib/site-packages/wheel/cli/unpack.py | 25 + winvenv/Lib/site-packages/wheel/metadata.py | 141 + winvenv/Lib/site-packages/wheel/pep425tags.py | 185 + winvenv/Lib/site-packages/wheel/pkginfo.py | 43 + winvenv/Lib/site-packages/wheel/util.py | 41 + winvenv/Lib/site-packages/wheel/wheelfile.py | 160 + winvenv/Lib/site.py | 833 ++ winvenv/Lib/sre_compile.py | 784 ++ winvenv/Lib/sre_constants.py | 261 + winvenv/Lib/sre_parse.py | 1046 +++ winvenv/Lib/stat.py | 178 + winvenv/Lib/struct.py | 15 + winvenv/Lib/tarfile.py | 2539 +++++ winvenv/Lib/tempfile.py | 809 ++ winvenv/Lib/token.py | 160 + winvenv/Lib/tokenize.py | 736 ++ winvenv/Lib/types.py | 295 + winvenv/Lib/warnings.py | 554 ++ winvenv/Lib/weakref.py | 632 ++ winvenv/Scripts/activate | 78 + winvenv/Scripts/activate.bat | 30 + winvenv/Scripts/activate.ps1 | 150 + winvenv/Scripts/activate_this.py | 36 + winvenv/Scripts/deactivate.bat | 20 + winvenv/Scripts/easy_install-3.7.exe | Bin 0 -> 102809 bytes winvenv/Scripts/easy_install.exe | Bin 0 -> 102809 bytes winvenv/Scripts/pip.exe | Bin 0 -> 102791 bytes winvenv/Scripts/pip3.7.exe | Bin 0 -> 102791 bytes winvenv/Scripts/pip3.exe | Bin 0 -> 102791 bytes winvenv/Scripts/python.exe | Bin 0 -> 99992 bytes winvenv/Scripts/python3.dll | Bin 0 -> 59032 bytes winvenv/Scripts/python37.dll | Bin 0 -> 3771032 bytes winvenv/Scripts/pythonw.exe | Bin 0 -> 98456 bytes winvenv/Scripts/wheel.exe | Bin 0 -> 102787 bytes winvenv/tcl/tcl8.6/auto.tcl | 646 ++ winvenv/tcl/tcl8.6/clock.tcl | 4547 +++++++++ winvenv/tcl/tcl8.6/encoding/ascii.enc | 20 + winvenv/tcl/tcl8.6/encoding/big5.enc | 1516 +++ winvenv/tcl/tcl8.6/encoding/cp1250.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1251.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1252.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1253.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1254.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1255.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1256.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1257.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp1258.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp437.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp737.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp775.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp850.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp852.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp855.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp857.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp860.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp861.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp862.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp863.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp864.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp865.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp866.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp869.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp874.enc | 20 + winvenv/tcl/tcl8.6/encoding/cp932.enc | 801 ++ winvenv/tcl/tcl8.6/encoding/cp936.enc | 2162 +++++ winvenv/tcl/tcl8.6/encoding/cp949.enc | 2128 +++++ winvenv/tcl/tcl8.6/encoding/cp950.enc | 1499 +++ winvenv/tcl/tcl8.6/encoding/dingbats.enc | 20 + winvenv/tcl/tcl8.6/encoding/ebcdic.enc | 19 + winvenv/tcl/tcl8.6/encoding/euc-cn.enc | 1397 +++ winvenv/tcl/tcl8.6/encoding/euc-jp.enc | 1353 +++ winvenv/tcl/tcl8.6/encoding/euc-kr.enc | 1533 +++ winvenv/tcl/tcl8.6/encoding/gb12345.enc | 1414 +++ winvenv/tcl/tcl8.6/encoding/gb1988.enc | 20 + winvenv/tcl/tcl8.6/encoding/gb2312-raw.enc | 1380 +++ winvenv/tcl/tcl8.6/encoding/gb2312.enc | 1397 +++ winvenv/tcl/tcl8.6/encoding/iso2022-jp.enc | 12 + winvenv/tcl/tcl8.6/encoding/iso2022-kr.enc | 7 + winvenv/tcl/tcl8.6/encoding/iso2022.enc | 14 + winvenv/tcl/tcl8.6/encoding/iso8859-1.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-10.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-13.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-14.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-15.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-16.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-2.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-3.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-4.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-5.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-6.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-7.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-8.enc | 20 + winvenv/tcl/tcl8.6/encoding/iso8859-9.enc | 20 + winvenv/tcl/tcl8.6/encoding/jis0201.enc | 20 + winvenv/tcl/tcl8.6/encoding/jis0208.enc | 1319 +++ winvenv/tcl/tcl8.6/encoding/jis0212.enc | 1159 +++ winvenv/tcl/tcl8.6/encoding/koi8-r.enc | 20 + winvenv/tcl/tcl8.6/encoding/koi8-u.enc | 20 + winvenv/tcl/tcl8.6/encoding/ksc5601.enc | 1516 +++ winvenv/tcl/tcl8.6/encoding/macCentEuro.enc | 20 + winvenv/tcl/tcl8.6/encoding/macCroatian.enc | 20 + winvenv/tcl/tcl8.6/encoding/macCyrillic.enc | 20 + winvenv/tcl/tcl8.6/encoding/macDingbats.enc | 20 + winvenv/tcl/tcl8.6/encoding/macGreek.enc | 20 + winvenv/tcl/tcl8.6/encoding/macIceland.enc | 20 + winvenv/tcl/tcl8.6/encoding/macJapan.enc | 785 ++ winvenv/tcl/tcl8.6/encoding/macRoman.enc | 20 + winvenv/tcl/tcl8.6/encoding/macRomania.enc | 20 + winvenv/tcl/tcl8.6/encoding/macThai.enc | 20 + winvenv/tcl/tcl8.6/encoding/macTurkish.enc | 20 + winvenv/tcl/tcl8.6/encoding/macUkraine.enc | 20 + winvenv/tcl/tcl8.6/encoding/shiftjis.enc | 690 ++ winvenv/tcl/tcl8.6/encoding/symbol.enc | 20 + winvenv/tcl/tcl8.6/encoding/tis-620.enc | 20 + winvenv/tcl/tcl8.6/history.tcl | 335 + winvenv/tcl/tcl8.6/http1.0/http.tcl | 377 + winvenv/tcl/tcl8.6/http1.0/pkgIndex.tcl | 11 + winvenv/tcl/tcl8.6/init.tcl | 819 ++ winvenv/tcl/tcl8.6/msgs/af.msg | 49 + winvenv/tcl/tcl8.6/msgs/af_za.msg | 6 + winvenv/tcl/tcl8.6/msgs/ar.msg | 54 + winvenv/tcl/tcl8.6/msgs/ar_in.msg | 6 + winvenv/tcl/tcl8.6/msgs/ar_jo.msg | 39 + winvenv/tcl/tcl8.6/msgs/ar_lb.msg | 39 + winvenv/tcl/tcl8.6/msgs/ar_sy.msg | 39 + winvenv/tcl/tcl8.6/msgs/be.msg | 52 + winvenv/tcl/tcl8.6/msgs/bg.msg | 52 + winvenv/tcl/tcl8.6/msgs/bn.msg | 49 + winvenv/tcl/tcl8.6/msgs/bn_in.msg | 6 + winvenv/tcl/tcl8.6/msgs/ca.msg | 50 + winvenv/tcl/tcl8.6/msgs/cs.msg | 54 + winvenv/tcl/tcl8.6/msgs/da.msg | 52 + winvenv/tcl/tcl8.6/msgs/de.msg | 54 + winvenv/tcl/tcl8.6/msgs/de_at.msg | 35 + winvenv/tcl/tcl8.6/msgs/de_be.msg | 53 + winvenv/tcl/tcl8.6/msgs/el.msg | 52 + winvenv/tcl/tcl8.6/msgs/en_au.msg | 7 + winvenv/tcl/tcl8.6/msgs/en_be.msg | 7 + winvenv/tcl/tcl8.6/msgs/en_bw.msg | 6 + winvenv/tcl/tcl8.6/msgs/en_ca.msg | 7 + winvenv/tcl/tcl8.6/msgs/en_gb.msg | 7 + winvenv/tcl/tcl8.6/msgs/en_hk.msg | 8 + winvenv/tcl/tcl8.6/msgs/en_ie.msg | 7 + winvenv/tcl/tcl8.6/msgs/en_in.msg | 8 + winvenv/tcl/tcl8.6/msgs/en_nz.msg | 7 + winvenv/tcl/tcl8.6/msgs/en_ph.msg | 8 + winvenv/tcl/tcl8.6/msgs/en_sg.msg | 6 + winvenv/tcl/tcl8.6/msgs/en_za.msg | 6 + winvenv/tcl/tcl8.6/msgs/en_zw.msg | 6 + winvenv/tcl/tcl8.6/msgs/eo.msg | 54 + winvenv/tcl/tcl8.6/msgs/es.msg | 52 + winvenv/tcl/tcl8.6/msgs/es_ar.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_bo.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_cl.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_co.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_cr.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_do.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_ec.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_gt.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_hn.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_mx.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_ni.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_pa.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_pe.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_pr.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_py.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_sv.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_uy.msg | 6 + winvenv/tcl/tcl8.6/msgs/es_ve.msg | 6 + winvenv/tcl/tcl8.6/msgs/et.msg | 52 + winvenv/tcl/tcl8.6/msgs/eu.msg | 47 + winvenv/tcl/tcl8.6/msgs/eu_es.msg | 7 + winvenv/tcl/tcl8.6/msgs/fa.msg | 47 + winvenv/tcl/tcl8.6/msgs/fa_in.msg | 52 + winvenv/tcl/tcl8.6/msgs/fa_ir.msg | 9 + winvenv/tcl/tcl8.6/msgs/fi.msg | 50 + winvenv/tcl/tcl8.6/msgs/fo.msg | 47 + winvenv/tcl/tcl8.6/msgs/fo_fo.msg | 7 + winvenv/tcl/tcl8.6/msgs/fr.msg | 52 + winvenv/tcl/tcl8.6/msgs/fr_be.msg | 7 + winvenv/tcl/tcl8.6/msgs/fr_ca.msg | 7 + winvenv/tcl/tcl8.6/msgs/fr_ch.msg | 7 + winvenv/tcl/tcl8.6/msgs/ga.msg | 47 + winvenv/tcl/tcl8.6/msgs/ga_ie.msg | 7 + winvenv/tcl/tcl8.6/msgs/gl.msg | 47 + winvenv/tcl/tcl8.6/msgs/gl_es.msg | 6 + winvenv/tcl/tcl8.6/msgs/gv.msg | 47 + winvenv/tcl/tcl8.6/msgs/gv_gb.msg | 6 + winvenv/tcl/tcl8.6/msgs/he.msg | 52 + winvenv/tcl/tcl8.6/msgs/hi.msg | 39 + winvenv/tcl/tcl8.6/msgs/hi_in.msg | 6 + winvenv/tcl/tcl8.6/msgs/hr.msg | 50 + winvenv/tcl/tcl8.6/msgs/hu.msg | 54 + winvenv/tcl/tcl8.6/msgs/id.msg | 47 + winvenv/tcl/tcl8.6/msgs/id_id.msg | 6 + winvenv/tcl/tcl8.6/msgs/is.msg | 50 + winvenv/tcl/tcl8.6/msgs/it.msg | 54 + winvenv/tcl/tcl8.6/msgs/it_ch.msg | 6 + winvenv/tcl/tcl8.6/msgs/ja.msg | 44 + winvenv/tcl/tcl8.6/msgs/kl.msg | 47 + winvenv/tcl/tcl8.6/msgs/kl_gl.msg | 7 + winvenv/tcl/tcl8.6/msgs/ko.msg | 55 + winvenv/tcl/tcl8.6/msgs/ko_kr.msg | 8 + winvenv/tcl/tcl8.6/msgs/kok.msg | 39 + winvenv/tcl/tcl8.6/msgs/kok_in.msg | 6 + winvenv/tcl/tcl8.6/msgs/kw.msg | 47 + winvenv/tcl/tcl8.6/msgs/kw_gb.msg | 6 + winvenv/tcl/tcl8.6/msgs/lt.msg | 52 + winvenv/tcl/tcl8.6/msgs/lv.msg | 52 + winvenv/tcl/tcl8.6/msgs/mk.msg | 52 + winvenv/tcl/tcl8.6/msgs/mr.msg | 39 + winvenv/tcl/tcl8.6/msgs/mr_in.msg | 6 + winvenv/tcl/tcl8.6/msgs/ms.msg | 47 + winvenv/tcl/tcl8.6/msgs/ms_my.msg | 6 + winvenv/tcl/tcl8.6/msgs/mt.msg | 27 + winvenv/tcl/tcl8.6/msgs/nb.msg | 52 + winvenv/tcl/tcl8.6/msgs/nl.msg | 50 + winvenv/tcl/tcl8.6/msgs/nl_be.msg | 7 + winvenv/tcl/tcl8.6/msgs/nn.msg | 52 + winvenv/tcl/tcl8.6/msgs/pl.msg | 52 + winvenv/tcl/tcl8.6/msgs/pt.msg | 50 + winvenv/tcl/tcl8.6/msgs/pt_br.msg | 7 + winvenv/tcl/tcl8.6/msgs/ro.msg | 52 + winvenv/tcl/tcl8.6/msgs/ru.msg | 52 + winvenv/tcl/tcl8.6/msgs/ru_ua.msg | 6 + winvenv/tcl/tcl8.6/msgs/sh.msg | 52 + winvenv/tcl/tcl8.6/msgs/sk.msg | 52 + winvenv/tcl/tcl8.6/msgs/sl.msg | 52 + winvenv/tcl/tcl8.6/msgs/sq.msg | 54 + winvenv/tcl/tcl8.6/msgs/sr.msg | 52 + winvenv/tcl/tcl8.6/msgs/sv.msg | 52 + winvenv/tcl/tcl8.6/msgs/sw.msg | 49 + winvenv/tcl/tcl8.6/msgs/ta.msg | 39 + winvenv/tcl/tcl8.6/msgs/ta_in.msg | 6 + winvenv/tcl/tcl8.6/msgs/te.msg | 47 + winvenv/tcl/tcl8.6/msgs/te_in.msg | 8 + winvenv/tcl/tcl8.6/msgs/th.msg | 54 + winvenv/tcl/tcl8.6/msgs/tr.msg | 50 + winvenv/tcl/tcl8.6/msgs/uk.msg | 52 + winvenv/tcl/tcl8.6/msgs/vi.msg | 50 + winvenv/tcl/tcl8.6/msgs/zh.msg | 55 + winvenv/tcl/tcl8.6/msgs/zh_cn.msg | 7 + winvenv/tcl/tcl8.6/msgs/zh_hk.msg | 28 + winvenv/tcl/tcl8.6/msgs/zh_sg.msg | 8 + winvenv/tcl/tcl8.6/msgs/zh_tw.msg | 8 + winvenv/tcl/tcl8.6/opt0.4/optparse.tcl | 1072 +++ winvenv/tcl/tcl8.6/opt0.4/pkgIndex.tcl | 12 + winvenv/tcl/tcl8.6/package.tcl | 747 ++ winvenv/tcl/tcl8.6/parray.tcl | 28 + winvenv/tcl/tcl8.6/safe.tcl | 1133 +++ winvenv/tcl/tcl8.6/tclIndex | 75 + winvenv/tcl/tcl8.6/tm.tcl | 375 + winvenv/tcl/tcl8.6/tzdata/Africa/Abidjan | 6 + winvenv/tcl/tcl8.6/tzdata/Africa/Accra | 52 + winvenv/tcl/tcl8.6/tzdata/Africa/Addis_Ababa | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Algiers | 39 + winvenv/tcl/tcl8.6/tzdata/Africa/Asmara | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Asmera | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Bamako | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Bangui | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Banjul | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Bissau | 7 + winvenv/tcl/tcl8.6/tzdata/Africa/Blantyre | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Brazzaville | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Bujumbura | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Cairo | 132 + winvenv/tcl/tcl8.6/tzdata/Africa/Casablanca | 230 + winvenv/tcl/tcl8.6/tzdata/Africa/Ceuta | 258 + winvenv/tcl/tcl8.6/tzdata/Africa/Conakry | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Dakar | 5 + .../tcl/tcl8.6/tzdata/Africa/Dar_es_Salaam | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Djibouti | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Douala | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/El_Aaiun | 219 + winvenv/tcl/tcl8.6/tzdata/Africa/Freetown | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Gaborone | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Harare | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Johannesburg | 11 + winvenv/tcl/tcl8.6/tzdata/Africa/Juba | 39 + winvenv/tcl/tcl8.6/tzdata/Africa/Kampala | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Khartoum | 40 + winvenv/tcl/tcl8.6/tzdata/Africa/Kigali | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Kinshasa | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Lagos | 6 + winvenv/tcl/tcl8.6/tzdata/Africa/Libreville | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Lome | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Luanda | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Lubumbashi | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Lusaka | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Malabo | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Maputo | 6 + winvenv/tcl/tcl8.6/tzdata/Africa/Maseru | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Mbabane | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Mogadishu | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Monrovia | 8 + winvenv/tcl/tcl8.6/tzdata/Africa/Nairobi | 9 + winvenv/tcl/tcl8.6/tzdata/Africa/Ndjamena | 8 + winvenv/tcl/tcl8.6/tzdata/Africa/Niamey | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Nouakchott | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Ouagadougou | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Porto-Novo | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Sao_Tome | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Timbuktu | 5 + winvenv/tcl/tcl8.6/tzdata/Africa/Tripoli | 34 + winvenv/tcl/tcl8.6/tzdata/Africa/Tunis | 39 + winvenv/tcl/tcl8.6/tzdata/Africa/Windhoek | 59 + winvenv/tcl/tcl8.6/tzdata/America/Adak | 276 + winvenv/tcl/tcl8.6/tzdata/America/Anchorage | 275 + winvenv/tcl/tcl8.6/tzdata/America/Anguilla | 5 + winvenv/tcl/tcl8.6/tzdata/America/Antigua | 5 + winvenv/tcl/tcl8.6/tzdata/America/Araguaina | 60 + .../tzdata/America/Argentina/Buenos_Aires | 67 + .../tcl8.6/tzdata/America/Argentina/Catamarca | 68 + .../tzdata/America/Argentina/ComodRivadavia | 5 + .../tcl8.6/tzdata/America/Argentina/Cordoba | 67 + .../tcl/tcl8.6/tzdata/America/Argentina/Jujuy | 67 + .../tcl8.6/tzdata/America/Argentina/La_Rioja | 69 + .../tcl8.6/tzdata/America/Argentina/Mendoza | 68 + .../tzdata/America/Argentina/Rio_Gallegos | 68 + .../tcl/tcl8.6/tzdata/America/Argentina/Salta | 66 + .../tcl8.6/tzdata/America/Argentina/San_Juan | 69 + .../tcl8.6/tzdata/America/Argentina/San_Luis | 68 + .../tcl8.6/tzdata/America/Argentina/Tucuman | 69 + .../tcl8.6/tzdata/America/Argentina/Ushuaia | 68 + winvenv/tcl/tcl8.6/tzdata/America/Aruba | 5 + winvenv/tcl/tcl8.6/tzdata/America/Asuncion | 259 + winvenv/tcl/tcl8.6/tzdata/America/Atikokan | 12 + winvenv/tcl/tcl8.6/tzdata/America/Atka | 5 + winvenv/tcl/tcl8.6/tzdata/America/Bahia | 68 + .../tcl/tcl8.6/tzdata/America/Bahia_Banderas | 222 + winvenv/tcl/tcl8.6/tzdata/America/Barbados | 15 + winvenv/tcl/tcl8.6/tzdata/America/Belem | 35 + winvenv/tcl/tcl8.6/tzdata/America/Belize | 60 + .../tcl/tcl8.6/tzdata/America/Blanc-Sablon | 12 + winvenv/tcl/tcl8.6/tzdata/America/Boa_Vista | 40 + winvenv/tcl/tcl8.6/tzdata/America/Bogota | 9 + winvenv/tcl/tcl8.6/tzdata/America/Boise | 281 + .../tcl/tcl8.6/tzdata/America/Buenos_Aires | 5 + .../tcl/tcl8.6/tzdata/America/Cambridge_Bay | 252 + .../tcl/tcl8.6/tzdata/America/Campo_Grande | 257 + winvenv/tcl/tcl8.6/tzdata/America/Cancun | 47 + winvenv/tcl/tcl8.6/tzdata/America/Caracas | 10 + winvenv/tcl/tcl8.6/tzdata/America/Catamarca | 5 + winvenv/tcl/tcl8.6/tzdata/America/Cayenne | 7 + winvenv/tcl/tcl8.6/tzdata/America/Cayman | 5 + winvenv/tcl/tcl8.6/tzdata/America/Chicago | 369 + winvenv/tcl/tcl8.6/tzdata/America/Chihuahua | 221 + .../tcl/tcl8.6/tzdata/America/Coral_Harbour | 5 + winvenv/tcl/tcl8.6/tzdata/America/Cordoba | 5 + winvenv/tcl/tcl8.6/tzdata/America/Costa_Rica | 15 + winvenv/tcl/tcl8.6/tzdata/America/Creston | 8 + winvenv/tcl/tcl8.6/tzdata/America/Cuiaba | 257 + winvenv/tcl/tcl8.6/tzdata/America/Curacao | 7 + .../tcl/tcl8.6/tzdata/America/Danmarkshavn | 39 + winvenv/tcl/tcl8.6/tzdata/America/Dawson | 256 + .../tcl/tcl8.6/tzdata/America/Dawson_Creek | 64 + winvenv/tcl/tcl8.6/tzdata/America/Denver | 291 + winvenv/tcl/tcl8.6/tzdata/America/Detroit | 270 + winvenv/tcl/tcl8.6/tzdata/America/Dominica | 5 + winvenv/tcl/tcl8.6/tzdata/America/Edmonton | 284 + winvenv/tcl/tcl8.6/tzdata/America/Eirunepe | 41 + winvenv/tcl/tcl8.6/tzdata/America/El_Salvador | 10 + winvenv/tcl/tcl8.6/tzdata/America/Ensenada | 5 + winvenv/tcl/tcl8.6/tzdata/America/Fort_Nelson | 151 + winvenv/tcl/tcl8.6/tzdata/America/Fort_Wayne | 5 + winvenv/tcl/tcl8.6/tzdata/America/Fortaleza | 48 + winvenv/tcl/tcl8.6/tzdata/America/Glace_Bay | 273 + winvenv/tcl/tcl8.6/tzdata/America/Godthab | 246 + winvenv/tcl/tcl8.6/tzdata/America/Goose_Bay | 338 + winvenv/tcl/tcl8.6/tzdata/America/Grand_Turk | 246 + winvenv/tcl/tcl8.6/tzdata/America/Grenada | 5 + winvenv/tcl/tcl8.6/tzdata/America/Guadeloupe | 5 + winvenv/tcl/tcl8.6/tzdata/America/Guatemala | 14 + winvenv/tcl/tcl8.6/tzdata/America/Guayaquil | 9 + winvenv/tcl/tcl8.6/tzdata/America/Guyana | 8 + winvenv/tcl/tcl8.6/tzdata/America/Halifax | 361 + winvenv/tcl/tcl8.6/tzdata/America/Havana | 285 + winvenv/tcl/tcl8.6/tzdata/America/Hermosillo | 21 + .../tzdata/America/Indiana/Indianapolis | 234 + .../tcl/tcl8.6/tzdata/America/Indiana/Knox | 285 + .../tcl/tcl8.6/tzdata/America/Indiana/Marengo | 236 + .../tcl8.6/tzdata/America/Indiana/Petersburg | 247 + .../tcl8.6/tzdata/America/Indiana/Tell_City | 234 + .../tcl/tcl8.6/tzdata/America/Indiana/Vevay | 213 + .../tcl8.6/tzdata/America/Indiana/Vincennes | 234 + .../tcl/tcl8.6/tzdata/America/Indiana/Winamac | 240 + .../tcl/tcl8.6/tzdata/America/Indianapolis | 5 + winvenv/tcl/tcl8.6/tzdata/America/Inuvik | 249 + winvenv/tcl/tcl8.6/tzdata/America/Iqaluit | 250 + winvenv/tcl/tcl8.6/tzdata/America/Jamaica | 29 + winvenv/tcl/tcl8.6/tzdata/America/Jujuy | 5 + winvenv/tcl/tcl8.6/tzdata/America/Juneau | 276 + .../tcl8.6/tzdata/America/Kentucky/Louisville | 314 + .../tcl8.6/tzdata/America/Kentucky/Monticello | 279 + winvenv/tcl/tcl8.6/tzdata/America/Knox_IN | 5 + winvenv/tcl/tcl8.6/tzdata/America/Kralendijk | 5 + winvenv/tcl/tcl8.6/tzdata/America/La_Paz | 8 + winvenv/tcl/tcl8.6/tzdata/America/Lima | 16 + winvenv/tcl/tcl8.6/tzdata/America/Los_Angeles | 317 + winvenv/tcl/tcl8.6/tzdata/America/Louisville | 5 + .../tcl/tcl8.6/tzdata/America/Lower_Princes | 5 + winvenv/tcl/tcl8.6/tzdata/America/Maceio | 52 + winvenv/tcl/tcl8.6/tzdata/America/Managua | 21 + winvenv/tcl/tcl8.6/tzdata/America/Manaus | 39 + winvenv/tcl/tcl8.6/tzdata/America/Marigot | 5 + winvenv/tcl/tcl8.6/tzdata/America/Martinique | 9 + winvenv/tcl/tcl8.6/tzdata/America/Matamoros | 219 + winvenv/tcl/tcl8.6/tzdata/America/Mazatlan | 222 + winvenv/tcl/tcl8.6/tzdata/America/Mendoza | 5 + winvenv/tcl/tcl8.6/tzdata/America/Menominee | 274 + winvenv/tcl/tcl8.6/tzdata/America/Merida | 216 + winvenv/tcl/tcl8.6/tzdata/America/Metlakatla | 212 + winvenv/tcl/tcl8.6/tzdata/America/Mexico_City | 228 + winvenv/tcl/tcl8.6/tzdata/America/Miquelon | 234 + winvenv/tcl/tcl8.6/tzdata/America/Moncton | 342 + winvenv/tcl/tcl8.6/tzdata/America/Monterrey | 218 + winvenv/tcl/tcl8.6/tzdata/America/Montevideo | 96 + winvenv/tcl/tcl8.6/tzdata/America/Montreal | 5 + winvenv/tcl/tcl8.6/tzdata/America/Montserrat | 5 + winvenv/tcl/tcl8.6/tzdata/America/Nassau | 279 + winvenv/tcl/tcl8.6/tzdata/America/New_York | 369 + winvenv/tcl/tcl8.6/tzdata/America/Nipigon | 264 + winvenv/tcl/tcl8.6/tzdata/America/Nome | 276 + winvenv/tcl/tcl8.6/tzdata/America/Noronha | 48 + .../tcl8.6/tzdata/America/North_Dakota/Beulah | 279 + .../tcl8.6/tzdata/America/North_Dakota/Center | 279 + .../tzdata/America/North_Dakota/New_Salem | 279 + winvenv/tcl/tcl8.6/tzdata/America/Ojinaga | 222 + winvenv/tcl/tcl8.6/tzdata/America/Panama | 7 + winvenv/tcl/tcl8.6/tzdata/America/Pangnirtung | 252 + winvenv/tcl/tcl8.6/tzdata/America/Paramaribo | 9 + winvenv/tcl/tcl8.6/tzdata/America/Phoenix | 17 + .../tcl/tcl8.6/tzdata/America/Port-au-Prince | 215 + .../tcl/tcl8.6/tzdata/America/Port_of_Spain | 6 + winvenv/tcl/tcl8.6/tzdata/America/Porto_Acre | 5 + winvenv/tcl/tcl8.6/tzdata/America/Porto_Velho | 35 + winvenv/tcl/tcl8.6/tzdata/America/Puerto_Rico | 10 + .../tcl/tcl8.6/tzdata/America/Punta_Arenas | 122 + winvenv/tcl/tcl8.6/tzdata/America/Rainy_River | 264 + .../tcl/tcl8.6/tzdata/America/Rankin_Inlet | 248 + winvenv/tcl/tcl8.6/tzdata/America/Recife | 48 + winvenv/tcl/tcl8.6/tzdata/America/Regina | 58 + winvenv/tcl/tcl8.6/tzdata/America/Resolute | 248 + winvenv/tcl/tcl8.6/tzdata/America/Rio_Branco | 37 + winvenv/tcl/tcl8.6/tzdata/America/Rosario | 5 + .../tcl/tcl8.6/tzdata/America/Santa_Isabel | 5 + winvenv/tcl/tcl8.6/tzdata/America/Santarem | 36 + winvenv/tcl/tcl8.6/tzdata/America/Santiago | 289 + .../tcl/tcl8.6/tzdata/America/Santo_Domingo | 21 + winvenv/tcl/tcl8.6/tzdata/America/Sao_Paulo | 258 + .../tcl/tcl8.6/tzdata/America/Scoresbysund | 246 + winvenv/tcl/tcl8.6/tzdata/America/Shiprock | 5 + winvenv/tcl/tcl8.6/tzdata/America/Sitka | 275 + .../tcl/tcl8.6/tzdata/America/St_Barthelemy | 5 + winvenv/tcl/tcl8.6/tzdata/America/St_Johns | 372 + winvenv/tcl/tcl8.6/tzdata/America/St_Kitts | 5 + winvenv/tcl/tcl8.6/tzdata/America/St_Lucia | 5 + winvenv/tcl/tcl8.6/tzdata/America/St_Thomas | 5 + winvenv/tcl/tcl8.6/tzdata/America/St_Vincent | 5 + .../tcl/tcl8.6/tzdata/America/Swift_Current | 29 + winvenv/tcl/tcl8.6/tzdata/America/Tegucigalpa | 12 + winvenv/tcl/tcl8.6/tzdata/America/Thule | 224 + winvenv/tcl/tcl8.6/tzdata/America/Thunder_Bay | 272 + winvenv/tcl/tcl8.6/tzdata/America/Tijuana | 285 + winvenv/tcl/tcl8.6/tzdata/America/Toronto | 365 + winvenv/tcl/tcl8.6/tzdata/America/Tortola | 5 + winvenv/tcl/tcl8.6/tzdata/America/Vancouver | 320 + winvenv/tcl/tcl8.6/tzdata/America/Virgin | 5 + winvenv/tcl/tcl8.6/tzdata/America/Whitehorse | 256 + winvenv/tcl/tcl8.6/tzdata/America/Winnipeg | 316 + winvenv/tcl/tcl8.6/tzdata/America/Yakutat | 276 + winvenv/tcl/tcl8.6/tzdata/America/Yellowknife | 252 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Casey | 11 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Davis | 12 + .../tcl8.6/tzdata/Antarctica/DumontDUrville | 8 + .../tcl/tcl8.6/tzdata/Antarctica/Macquarie | 97 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Mawson | 7 + winvenv/tcl/tcl8.6/tzdata/Antarctica/McMurdo | 5 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Palmer | 87 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Rothera | 6 + .../tcl/tcl8.6/tzdata/Antarctica/South_Pole | 5 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Syowa | 6 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Troll | 196 + winvenv/tcl/tcl8.6/tzdata/Antarctica/Vostok | 6 + winvenv/tcl/tcl8.6/tzdata/Arctic/Longyearbyen | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Aden | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Almaty | 57 + winvenv/tcl/tcl8.6/tzdata/Asia/Amman | 246 + winvenv/tcl/tcl8.6/tzdata/Asia/Anadyr | 72 + winvenv/tcl/tcl8.6/tzdata/Asia/Aqtau | 58 + winvenv/tcl/tcl8.6/tzdata/Asia/Aqtobe | 58 + winvenv/tcl/tcl8.6/tzdata/Asia/Ashgabat | 31 + winvenv/tcl/tcl8.6/tzdata/Asia/Ashkhabad | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Atyrau | 58 + winvenv/tcl/tcl8.6/tzdata/Asia/Baghdad | 59 + winvenv/tcl/tcl8.6/tzdata/Asia/Bahrain | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Baku | 74 + winvenv/tcl/tcl8.6/tzdata/Asia/Bangkok | 7 + winvenv/tcl/tcl8.6/tzdata/Asia/Barnaul | 73 + winvenv/tcl/tcl8.6/tzdata/Asia/Beirut | 270 + winvenv/tcl/tcl8.6/tzdata/Asia/Bishkek | 58 + winvenv/tcl/tcl8.6/tzdata/Asia/Brunei | 7 + winvenv/tcl/tcl8.6/tzdata/Asia/Calcutta | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Chita | 72 + winvenv/tcl/tcl8.6/tzdata/Asia/Choibalsan | 56 + winvenv/tcl/tcl8.6/tzdata/Asia/Chongqing | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Chungking | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Colombo | 13 + winvenv/tcl/tcl8.6/tzdata/Asia/Dacca | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Damascus | 280 + winvenv/tcl/tcl8.6/tzdata/Asia/Dhaka | 13 + winvenv/tcl/tcl8.6/tzdata/Asia/Dili | 9 + winvenv/tcl/tcl8.6/tzdata/Asia/Dubai | 6 + winvenv/tcl/tcl8.6/tzdata/Asia/Dushanbe | 29 + winvenv/tcl/tcl8.6/tzdata/Asia/Famagusta | 256 + winvenv/tcl/tcl8.6/tzdata/Asia/Gaza | 278 + winvenv/tcl/tcl8.6/tzdata/Asia/Harbin | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Hebron | 277 + winvenv/tcl/tcl8.6/tzdata/Asia/Ho_Chi_Minh | 14 + winvenv/tcl/tcl8.6/tzdata/Asia/Hong_Kong | 75 + winvenv/tcl/tcl8.6/tzdata/Asia/Hovd | 55 + winvenv/tcl/tcl8.6/tzdata/Asia/Irkutsk | 72 + winvenv/tcl/tcl8.6/tzdata/Asia/Istanbul | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Jakarta | 13 + winvenv/tcl/tcl8.6/tzdata/Asia/Jayapura | 8 + winvenv/tcl/tcl8.6/tzdata/Asia/Jerusalem | 272 + winvenv/tcl/tcl8.6/tzdata/Asia/Kabul | 7 + winvenv/tcl/tcl8.6/tzdata/Asia/Kamchatka | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Karachi | 16 + winvenv/tcl/tcl8.6/tzdata/Asia/Kashgar | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Kathmandu | 7 + winvenv/tcl/tcl8.6/tzdata/Asia/Katmandu | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Khandyga | 73 + winvenv/tcl/tcl8.6/tzdata/Asia/Kolkata | 12 + winvenv/tcl/tcl8.6/tzdata/Asia/Krasnoyarsk | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Kuala_Lumpur | 13 + winvenv/tcl/tcl8.6/tzdata/Asia/Kuching | 23 + winvenv/tcl/tcl8.6/tzdata/Asia/Kuwait | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Macao | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Macau | 46 + winvenv/tcl/tcl8.6/tzdata/Asia/Magadan | 72 + winvenv/tcl/tcl8.6/tzdata/Asia/Makassar | 9 + winvenv/tcl/tcl8.6/tzdata/Asia/Manila | 15 + winvenv/tcl/tcl8.6/tzdata/Asia/Muscat | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Nicosia | 257 + winvenv/tcl/tcl8.6/tzdata/Asia/Novokuznetsk | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Novosibirsk | 73 + winvenv/tcl/tcl8.6/tzdata/Asia/Omsk | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Oral | 58 + winvenv/tcl/tcl8.6/tzdata/Asia/Phnom_Penh | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Pontianak | 13 + winvenv/tcl/tcl8.6/tzdata/Asia/Pyongyang | 9 + winvenv/tcl/tcl8.6/tzdata/Asia/Qatar | 7 + winvenv/tcl/tcl8.6/tzdata/Asia/Qyzylorda | 57 + winvenv/tcl/tcl8.6/tzdata/Asia/Rangoon | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Riyadh | 6 + winvenv/tcl/tcl8.6/tzdata/Asia/Saigon | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Sakhalin | 73 + winvenv/tcl/tcl8.6/tzdata/Asia/Samarkand | 31 + winvenv/tcl/tcl8.6/tzdata/Asia/Seoul | 26 + winvenv/tcl/tcl8.6/tzdata/Asia/Shanghai | 23 + winvenv/tcl/tcl8.6/tzdata/Asia/Singapore | 13 + winvenv/tcl/tcl8.6/tzdata/Asia/Srednekolymsk | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Taipei | 46 + winvenv/tcl/tcl8.6/tzdata/Asia/Tashkent | 31 + winvenv/tcl/tcl8.6/tzdata/Asia/Tbilisi | 60 + winvenv/tcl/tcl8.6/tzdata/Asia/Tehran | 229 + winvenv/tcl/tcl8.6/tzdata/Asia/Tel_Aviv | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Thimbu | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Thimphu | 7 + winvenv/tcl/tcl8.6/tzdata/Asia/Tokyo | 14 + winvenv/tcl/tcl8.6/tzdata/Asia/Tomsk | 73 + winvenv/tcl/tcl8.6/tzdata/Asia/Ujung_Pandang | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Ulaanbaatar | 55 + winvenv/tcl/tcl8.6/tzdata/Asia/Ulan_Bator | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Urumqi | 6 + winvenv/tcl/tcl8.6/tzdata/Asia/Ust-Nera | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Vientiane | 5 + winvenv/tcl/tcl8.6/tzdata/Asia/Vladivostok | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Yakutsk | 71 + winvenv/tcl/tcl8.6/tzdata/Asia/Yangon | 9 + winvenv/tcl/tcl8.6/tzdata/Asia/Yekaterinburg | 72 + winvenv/tcl/tcl8.6/tzdata/Asia/Yerevan | 70 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Azores | 345 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Bermuda | 259 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Canary | 247 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Cape_Verde | 9 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Faeroe | 5 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Faroe | 245 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Jan_Mayen | 5 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Madeira | 346 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Reykjavik | 73 + .../tcl/tcl8.6/tzdata/Atlantic/South_Georgia | 6 + winvenv/tcl/tcl8.6/tzdata/Atlantic/St_Helena | 5 + winvenv/tcl/tcl8.6/tzdata/Atlantic/Stanley | 75 + winvenv/tcl/tcl8.6/tzdata/Australia/ACT | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/Adelaide | 273 + winvenv/tcl/tcl8.6/tzdata/Australia/Brisbane | 23 + .../tcl/tcl8.6/tzdata/Australia/Broken_Hill | 275 + winvenv/tcl/tcl8.6/tzdata/Australia/Canberra | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/Currie | 273 + winvenv/tcl/tcl8.6/tzdata/Australia/Darwin | 15 + winvenv/tcl/tcl8.6/tzdata/Australia/Eucla | 25 + winvenv/tcl/tcl8.6/tzdata/Australia/Hobart | 281 + winvenv/tcl/tcl8.6/tzdata/Australia/LHI | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/Lindeman | 28 + winvenv/tcl/tcl8.6/tzdata/Australia/Lord_Howe | 245 + winvenv/tcl/tcl8.6/tzdata/Australia/Melbourne | 272 + winvenv/tcl/tcl8.6/tzdata/Australia/NSW | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/North | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/Perth | 25 + .../tcl/tcl8.6/tzdata/Australia/Queensland | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/South | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/Sydney | 272 + winvenv/tcl/tcl8.6/tzdata/Australia/Tasmania | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/Victoria | 5 + winvenv/tcl/tcl8.6/tzdata/Australia/West | 5 + .../tcl/tcl8.6/tzdata/Australia/Yancowinna | 5 + winvenv/tcl/tcl8.6/tzdata/Brazil/Acre | 5 + winvenv/tcl/tcl8.6/tzdata/Brazil/DeNoronha | 5 + winvenv/tcl/tcl8.6/tzdata/Brazil/East | 5 + winvenv/tcl/tcl8.6/tzdata/Brazil/West | 5 + winvenv/tcl/tcl8.6/tzdata/CET | 265 + winvenv/tcl/tcl8.6/tzdata/CST6CDT | 278 + winvenv/tcl/tcl8.6/tzdata/Canada/Atlantic | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Central | 5 + .../tcl8.6/tzdata/Canada/East-Saskatchewan | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Eastern | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Mountain | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Newfoundland | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Pacific | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Saskatchewan | 5 + winvenv/tcl/tcl8.6/tzdata/Canada/Yukon | 5 + winvenv/tcl/tcl8.6/tzdata/Chile/Continental | 5 + winvenv/tcl/tcl8.6/tzdata/Chile/EasterIsland | 5 + winvenv/tcl/tcl8.6/tzdata/Cuba | 5 + winvenv/tcl/tcl8.6/tzdata/EET | 251 + winvenv/tcl/tcl8.6/tzdata/EST | 5 + winvenv/tcl/tcl8.6/tzdata/EST5EDT | 278 + winvenv/tcl/tcl8.6/tzdata/Egypt | 5 + winvenv/tcl/tcl8.6/tzdata/Eire | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+0 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+1 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+10 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+11 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+12 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+2 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+3 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+4 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+5 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+6 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+7 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+8 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT+9 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-0 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-1 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-10 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-11 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-12 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-13 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-14 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-2 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-3 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-4 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-5 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-6 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-7 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-8 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT-9 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/GMT0 | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/Greenwich | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/UCT | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/UTC | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/Universal | 5 + winvenv/tcl/tcl8.6/tzdata/Etc/Zulu | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Amsterdam | 310 + winvenv/tcl/tcl8.6/tzdata/Europe/Andorra | 237 + winvenv/tcl/tcl8.6/tzdata/Europe/Astrakhan | 71 + winvenv/tcl/tcl8.6/tzdata/Europe/Athens | 268 + winvenv/tcl/tcl8.6/tzdata/Europe/Belfast | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Belgrade | 250 + winvenv/tcl/tcl8.6/tzdata/Europe/Berlin | 274 + winvenv/tcl/tcl8.6/tzdata/Europe/Bratislava | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Brussels | 316 + winvenv/tcl/tcl8.6/tzdata/Europe/Bucharest | 268 + winvenv/tcl/tcl8.6/tzdata/Europe/Budapest | 282 + winvenv/tcl/tcl8.6/tzdata/Europe/Busingen | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Chisinau | 272 + winvenv/tcl/tcl8.6/tzdata/Europe/Copenhagen | 264 + winvenv/tcl/tcl8.6/tzdata/Europe/Dublin | 359 + winvenv/tcl/tcl8.6/tzdata/Europe/Gibraltar | 328 + winvenv/tcl/tcl8.6/tzdata/Europe/Guernsey | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Helsinki | 248 + winvenv/tcl/tcl8.6/tzdata/Europe/Isle_of_Man | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Istanbul | 140 + winvenv/tcl/tcl8.6/tzdata/Europe/Jersey | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Kaliningrad | 85 + winvenv/tcl/tcl8.6/tzdata/Europe/Kiev | 251 + winvenv/tcl/tcl8.6/tzdata/Europe/Kirov | 70 + winvenv/tcl/tcl8.6/tzdata/Europe/Lisbon | 351 + winvenv/tcl/tcl8.6/tzdata/Europe/Ljubljana | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/London | 372 + winvenv/tcl/tcl8.6/tzdata/Europe/Luxembourg | 313 + winvenv/tcl/tcl8.6/tzdata/Europe/Madrid | 292 + winvenv/tcl/tcl8.6/tzdata/Europe/Malta | 299 + winvenv/tcl/tcl8.6/tzdata/Europe/Mariehamn | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Minsk | 75 + winvenv/tcl/tcl8.6/tzdata/Europe/Monaco | 315 + winvenv/tcl/tcl8.6/tzdata/Europe/Moscow | 83 + winvenv/tcl/tcl8.6/tzdata/Europe/Nicosia | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Oslo | 271 + winvenv/tcl/tcl8.6/tzdata/Europe/Paris | 314 + winvenv/tcl/tcl8.6/tzdata/Europe/Podgorica | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Prague | 272 + winvenv/tcl/tcl8.6/tzdata/Europe/Riga | 258 + winvenv/tcl/tcl8.6/tzdata/Europe/Rome | 302 + winvenv/tcl/tcl8.6/tzdata/Europe/Samara | 73 + winvenv/tcl/tcl8.6/tzdata/Europe/San_Marino | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Sarajevo | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Saratov | 71 + winvenv/tcl/tcl8.6/tzdata/Europe/Simferopol | 82 + winvenv/tcl/tcl8.6/tzdata/Europe/Skopje | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Sofia | 258 + winvenv/tcl/tcl8.6/tzdata/Europe/Stockholm | 250 + winvenv/tcl/tcl8.6/tzdata/Europe/Tallinn | 254 + winvenv/tcl/tcl8.6/tzdata/Europe/Tirane | 263 + winvenv/tcl/tcl8.6/tzdata/Europe/Tiraspol | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Ulyanovsk | 73 + winvenv/tcl/tcl8.6/tzdata/Europe/Uzhgorod | 254 + winvenv/tcl/tcl8.6/tzdata/Europe/Vaduz | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Vatican | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Vienna | 271 + winvenv/tcl/tcl8.6/tzdata/Europe/Vilnius | 252 + winvenv/tcl/tcl8.6/tzdata/Europe/Volgograd | 71 + winvenv/tcl/tcl8.6/tzdata/Europe/Warsaw | 296 + winvenv/tcl/tcl8.6/tzdata/Europe/Zagreb | 5 + winvenv/tcl/tcl8.6/tzdata/Europe/Zaporozhye | 252 + winvenv/tcl/tcl8.6/tzdata/Europe/Zurich | 250 + winvenv/tcl/tcl8.6/tzdata/GB | 5 + winvenv/tcl/tcl8.6/tzdata/GB-Eire | 5 + winvenv/tcl/tcl8.6/tzdata/GMT | 5 + winvenv/tcl/tcl8.6/tzdata/GMT+0 | 5 + winvenv/tcl/tcl8.6/tzdata/GMT-0 | 5 + winvenv/tcl/tcl8.6/tzdata/GMT0 | 5 + winvenv/tcl/tcl8.6/tzdata/Greenwich | 5 + winvenv/tcl/tcl8.6/tzdata/HST | 5 + winvenv/tcl/tcl8.6/tzdata/Hongkong | 5 + winvenv/tcl/tcl8.6/tzdata/Iceland | 5 + winvenv/tcl/tcl8.6/tzdata/Indian/Antananarivo | 5 + winvenv/tcl/tcl8.6/tzdata/Indian/Chagos | 7 + winvenv/tcl/tcl8.6/tzdata/Indian/Christmas | 6 + winvenv/tcl/tcl8.6/tzdata/Indian/Cocos | 6 + winvenv/tcl/tcl8.6/tzdata/Indian/Comoro | 5 + winvenv/tcl/tcl8.6/tzdata/Indian/Kerguelen | 6 + winvenv/tcl/tcl8.6/tzdata/Indian/Mahe | 6 + winvenv/tcl/tcl8.6/tzdata/Indian/Maldives | 7 + winvenv/tcl/tcl8.6/tzdata/Indian/Mauritius | 10 + winvenv/tcl/tcl8.6/tzdata/Indian/Mayotte | 5 + winvenv/tcl/tcl8.6/tzdata/Indian/Reunion | 6 + winvenv/tcl/tcl8.6/tzdata/Iran | 5 + winvenv/tcl/tcl8.6/tzdata/Israel | 5 + winvenv/tcl/tcl8.6/tzdata/Jamaica | 5 + winvenv/tcl/tcl8.6/tzdata/Japan | 5 + winvenv/tcl/tcl8.6/tzdata/Kwajalein | 5 + winvenv/tcl/tcl8.6/tzdata/Libya | 5 + winvenv/tcl/tcl8.6/tzdata/MET | 265 + winvenv/tcl/tcl8.6/tzdata/MST | 5 + winvenv/tcl/tcl8.6/tzdata/MST7MDT | 278 + winvenv/tcl/tcl8.6/tzdata/Mexico/BajaNorte | 5 + winvenv/tcl/tcl8.6/tzdata/Mexico/BajaSur | 5 + winvenv/tcl/tcl8.6/tzdata/Mexico/General | 5 + winvenv/tcl/tcl8.6/tzdata/NZ | 5 + winvenv/tcl/tcl8.6/tzdata/NZ-CHAT | 5 + winvenv/tcl/tcl8.6/tzdata/Navajo | 5 + winvenv/tcl/tcl8.6/tzdata/PRC | 5 + winvenv/tcl/tcl8.6/tzdata/PST8PDT | 278 + winvenv/tcl/tcl8.6/tzdata/Pacific/Apia | 188 + winvenv/tcl/tcl8.6/tzdata/Pacific/Auckland | 285 + .../tcl/tcl8.6/tzdata/Pacific/Bougainville | 10 + winvenv/tcl/tcl8.6/tzdata/Pacific/Chatham | 258 + winvenv/tcl/tcl8.6/tzdata/Pacific/Chuuk | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Easter | 268 + winvenv/tcl/tcl8.6/tzdata/Pacific/Efate | 26 + winvenv/tcl/tcl8.6/tzdata/Pacific/Enderbury | 8 + winvenv/tcl/tcl8.6/tzdata/Pacific/Fakaofo | 7 + winvenv/tcl/tcl8.6/tzdata/Pacific/Fiji | 191 + winvenv/tcl/tcl8.6/tzdata/Pacific/Funafuti | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Galapagos | 9 + winvenv/tcl/tcl8.6/tzdata/Pacific/Gambier | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Guadalcanal | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Guam | 8 + winvenv/tcl/tcl8.6/tzdata/Pacific/Honolulu | 11 + winvenv/tcl/tcl8.6/tzdata/Pacific/Johnston | 5 + winvenv/tcl/tcl8.6/tzdata/Pacific/Kiritimati | 8 + winvenv/tcl/tcl8.6/tzdata/Pacific/Kosrae | 8 + winvenv/tcl/tcl8.6/tzdata/Pacific/Kwajalein | 8 + winvenv/tcl/tcl8.6/tzdata/Pacific/Majuro | 7 + winvenv/tcl/tcl8.6/tzdata/Pacific/Marquesas | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Midway | 5 + winvenv/tcl/tcl8.6/tzdata/Pacific/Nauru | 9 + winvenv/tcl/tcl8.6/tzdata/Pacific/Niue | 8 + winvenv/tcl/tcl8.6/tzdata/Pacific/Norfolk | 10 + winvenv/tcl/tcl8.6/tzdata/Pacific/Noumea | 12 + winvenv/tcl/tcl8.6/tzdata/Pacific/Pago_Pago | 7 + winvenv/tcl/tcl8.6/tzdata/Pacific/Palau | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Pitcairn | 7 + winvenv/tcl/tcl8.6/tzdata/Pacific/Pohnpei | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Ponape | 5 + .../tcl/tcl8.6/tzdata/Pacific/Port_Moresby | 7 + winvenv/tcl/tcl8.6/tzdata/Pacific/Rarotonga | 32 + winvenv/tcl/tcl8.6/tzdata/Pacific/Saipan | 5 + winvenv/tcl/tcl8.6/tzdata/Pacific/Samoa | 5 + winvenv/tcl/tcl8.6/tzdata/Pacific/Tahiti | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Tarawa | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Tongatapu | 16 + winvenv/tcl/tcl8.6/tzdata/Pacific/Truk | 5 + winvenv/tcl/tcl8.6/tzdata/Pacific/Wake | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Wallis | 6 + winvenv/tcl/tcl8.6/tzdata/Pacific/Yap | 5 + winvenv/tcl/tcl8.6/tzdata/Poland | 5 + winvenv/tcl/tcl8.6/tzdata/Portugal | 5 + winvenv/tcl/tcl8.6/tzdata/ROC | 5 + winvenv/tcl/tcl8.6/tzdata/ROK | 5 + winvenv/tcl/tcl8.6/tzdata/Singapore | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/AST4 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/AST4ADT | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/CST6 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/CST6CDT | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/EST5 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/EST5EDT | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/HST10 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/MST7 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/MST7MDT | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/PST8 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/PST8PDT | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/YST9 | 5 + winvenv/tcl/tcl8.6/tzdata/SystemV/YST9YDT | 5 + winvenv/tcl/tcl8.6/tzdata/Turkey | 5 + winvenv/tcl/tcl8.6/tzdata/UCT | 5 + winvenv/tcl/tcl8.6/tzdata/US/Alaska | 5 + winvenv/tcl/tcl8.6/tzdata/US/Aleutian | 5 + winvenv/tcl/tcl8.6/tzdata/US/Arizona | 5 + winvenv/tcl/tcl8.6/tzdata/US/Central | 5 + winvenv/tcl/tcl8.6/tzdata/US/East-Indiana | 5 + winvenv/tcl/tcl8.6/tzdata/US/Eastern | 5 + winvenv/tcl/tcl8.6/tzdata/US/Hawaii | 5 + winvenv/tcl/tcl8.6/tzdata/US/Indiana-Starke | 5 + winvenv/tcl/tcl8.6/tzdata/US/Michigan | 5 + winvenv/tcl/tcl8.6/tzdata/US/Mountain | 5 + winvenv/tcl/tcl8.6/tzdata/US/Pacific | 5 + winvenv/tcl/tcl8.6/tzdata/US/Pacific-New | 5 + winvenv/tcl/tcl8.6/tzdata/US/Samoa | 5 + winvenv/tcl/tcl8.6/tzdata/UTC | 5 + winvenv/tcl/tcl8.6/tzdata/Universal | 5 + winvenv/tcl/tcl8.6/tzdata/W-SU | 5 + winvenv/tcl/tcl8.6/tzdata/WET | 251 + winvenv/tcl/tcl8.6/tzdata/Zulu | 5 + winvenv/tcl/tcl8.6/word.tcl | 152 + winvenv/tcl/tk8.6/bgerror.tcl | 265 + winvenv/tcl/tk8.6/button.tcl | 778 ++ winvenv/tcl/tk8.6/choosedir.tcl | 308 + winvenv/tcl/tk8.6/clrpick.tcl | 695 ++ winvenv/tcl/tk8.6/comdlg.tcl | 319 + winvenv/tcl/tk8.6/console.tcl | 1150 +++ winvenv/tcl/tk8.6/demos/README | 44 + winvenv/tcl/tk8.6/demos/anilabel.tcl | 160 + winvenv/tcl/tk8.6/demos/aniwave.tcl | 104 + winvenv/tcl/tk8.6/demos/arrow.tcl | 237 + winvenv/tcl/tk8.6/demos/bind.tcl | 78 + winvenv/tcl/tk8.6/demos/bitmap.tcl | 52 + winvenv/tcl/tk8.6/demos/browse | 66 + winvenv/tcl/tk8.6/demos/button.tcl | 47 + winvenv/tcl/tk8.6/demos/check.tcl | 71 + winvenv/tcl/tk8.6/demos/clrpick.tcl | 54 + winvenv/tcl/tk8.6/demos/colors.tcl | 99 + winvenv/tcl/tk8.6/demos/combo.tcl | 61 + winvenv/tcl/tk8.6/demos/cscroll.tcl | 108 + winvenv/tcl/tk8.6/demos/ctext.tcl | 172 + winvenv/tcl/tk8.6/demos/dialog1.tcl | 13 + winvenv/tcl/tk8.6/demos/dialog2.tcl | 17 + winvenv/tcl/tk8.6/demos/en.msg | 97 + winvenv/tcl/tk8.6/demos/entry1.tcl | 34 + winvenv/tcl/tk8.6/demos/entry2.tcl | 46 + winvenv/tcl/tk8.6/demos/entry3.tcl | 185 + winvenv/tcl/tk8.6/demos/filebox.tcl | 81 + winvenv/tcl/tk8.6/demos/floor.tcl | 1366 +++ winvenv/tcl/tk8.6/demos/fontchoose.tcl | 69 + winvenv/tcl/tk8.6/demos/form.tcl | 38 + winvenv/tcl/tk8.6/demos/goldberg.tcl | 1833 ++++ winvenv/tcl/tk8.6/demos/hello | 22 + winvenv/tcl/tk8.6/demos/hscale.tcl | 45 + winvenv/tcl/tk8.6/demos/icon.tcl | 51 + winvenv/tcl/tk8.6/demos/image1.tcl | 35 + winvenv/tcl/tk8.6/demos/image2.tcl | 108 + winvenv/tcl/tk8.6/demos/images/earth.gif | Bin 0 -> 51712 bytes winvenv/tcl/tk8.6/demos/images/earthmenu.png | Bin 0 -> 8157 bytes winvenv/tcl/tk8.6/demos/images/earthris.gif | Bin 0 -> 6343 bytes winvenv/tcl/tk8.6/demos/images/flagdown.xbm | 27 + winvenv/tcl/tk8.6/demos/images/flagup.xbm | 27 + winvenv/tcl/tk8.6/demos/images/gray25.xbm | 6 + winvenv/tcl/tk8.6/demos/images/letters.xbm | 27 + winvenv/tcl/tk8.6/demos/images/noletter.xbm | 27 + winvenv/tcl/tk8.6/demos/images/ouster.png | Bin 0 -> 54257 bytes winvenv/tcl/tk8.6/demos/images/pattern.xbm | 6 + winvenv/tcl/tk8.6/demos/images/tcllogo.gif | Bin 0 -> 2341 bytes winvenv/tcl/tk8.6/demos/images/teapot.ppm | 31 + winvenv/tcl/tk8.6/demos/items.tcl | 291 + winvenv/tcl/tk8.6/demos/ixset | 328 + winvenv/tcl/tk8.6/demos/knightstour.tcl | 268 + winvenv/tcl/tk8.6/demos/label.tcl | 40 + winvenv/tcl/tk8.6/demos/labelframe.tcl | 76 + winvenv/tcl/tk8.6/demos/license.terms | 40 + winvenv/tcl/tk8.6/demos/mclist.tcl | 119 + winvenv/tcl/tk8.6/demos/menu.tcl | 163 + winvenv/tcl/tk8.6/demos/menubu.tcl | 90 + winvenv/tcl/tk8.6/demos/msgbox.tcl | 62 + winvenv/tcl/tk8.6/demos/nl.msg | 125 + winvenv/tcl/tk8.6/demos/paned1.tcl | 32 + winvenv/tcl/tk8.6/demos/paned2.tcl | 74 + winvenv/tcl/tk8.6/demos/pendulum.tcl | 197 + winvenv/tcl/tk8.6/demos/plot.tcl | 97 + winvenv/tcl/tk8.6/demos/puzzle.tcl | 82 + winvenv/tcl/tk8.6/demos/radio.tcl | 66 + winvenv/tcl/tk8.6/demos/rmt | 210 + winvenv/tcl/tk8.6/demos/rolodex | 204 + winvenv/tcl/tk8.6/demos/ruler.tcl | 171 + winvenv/tcl/tk8.6/demos/sayings.tcl | 44 + winvenv/tcl/tk8.6/demos/search.tcl | 139 + winvenv/tcl/tk8.6/demos/spin.tcl | 53 + winvenv/tcl/tk8.6/demos/square | 60 + winvenv/tcl/tk8.6/demos/states.tcl | 54 + winvenv/tcl/tk8.6/demos/style.tcl | 155 + winvenv/tcl/tk8.6/demos/tclIndex | 67 + winvenv/tcl/tk8.6/demos/tcolor | 358 + winvenv/tcl/tk8.6/demos/text.tcl | 111 + winvenv/tcl/tk8.6/demos/textpeer.tcl | 62 + winvenv/tcl/tk8.6/demos/timer | 47 + winvenv/tcl/tk8.6/demos/toolbar.tcl | 92 + winvenv/tcl/tk8.6/demos/tree.tcl | 88 + winvenv/tcl/tk8.6/demos/ttkbut.tcl | 84 + winvenv/tcl/tk8.6/demos/ttkmenu.tcl | 53 + winvenv/tcl/tk8.6/demos/ttknote.tcl | 57 + winvenv/tcl/tk8.6/demos/ttkpane.tcl | 112 + winvenv/tcl/tk8.6/demos/ttkprogress.tcl | 46 + winvenv/tcl/tk8.6/demos/ttkscale.tcl | 39 + winvenv/tcl/tk8.6/demos/twind.tcl | 327 + winvenv/tcl/tk8.6/demos/unicodeout.tcl | 137 + winvenv/tcl/tk8.6/demos/vscale.tcl | 46 + winvenv/tcl/tk8.6/demos/widget | 721 ++ winvenv/tcl/tk8.6/dialog.tcl | 180 + winvenv/tcl/tk8.6/entry.tcl | 654 ++ winvenv/tcl/tk8.6/focus.tcl | 178 + winvenv/tcl/tk8.6/fontchooser.tcl | 452 + winvenv/tcl/tk8.6/iconlist.tcl | 696 ++ winvenv/tcl/tk8.6/icons.tcl | 153 + winvenv/tcl/tk8.6/images/README | 7 + winvenv/tcl/tk8.6/images/logo.eps | 2091 +++++ winvenv/tcl/tk8.6/images/logo100.gif | Bin 0 -> 2341 bytes winvenv/tcl/tk8.6/images/logo64.gif | Bin 0 -> 1670 bytes winvenv/tcl/tk8.6/images/logoLarge.gif | Bin 0 -> 11000 bytes winvenv/tcl/tk8.6/images/logoMed.gif | Bin 0 -> 3889 bytes winvenv/tcl/tk8.6/images/pwrdLogo.eps | 1897 ++++ winvenv/tcl/tk8.6/images/pwrdLogo100.gif | Bin 0 -> 1615 bytes winvenv/tcl/tk8.6/images/pwrdLogo150.gif | Bin 0 -> 2489 bytes winvenv/tcl/tk8.6/images/pwrdLogo175.gif | Bin 0 -> 2981 bytes winvenv/tcl/tk8.6/images/pwrdLogo200.gif | Bin 0 -> 3491 bytes winvenv/tcl/tk8.6/images/pwrdLogo75.gif | Bin 0 -> 1171 bytes winvenv/tcl/tk8.6/images/tai-ku.gif | Bin 0 -> 5473 bytes winvenv/tcl/tk8.6/license.terms | 40 + winvenv/tcl/tk8.6/listbox.tcl | 552 ++ winvenv/tcl/tk8.6/megawidget.tcl | 297 + winvenv/tcl/tk8.6/menu.tcl | 1354 +++ winvenv/tcl/tk8.6/mkpsenc.tcl | 1488 +++ winvenv/tcl/tk8.6/msgbox.tcl | 429 + winvenv/tcl/tk8.6/msgs/cs.msg | 77 + winvenv/tcl/tk8.6/msgs/da.msg | 78 + winvenv/tcl/tk8.6/msgs/de.msg | 91 + winvenv/tcl/tk8.6/msgs/el.msg | 86 + winvenv/tcl/tk8.6/msgs/en.msg | 91 + winvenv/tcl/tk8.6/msgs/en_gb.msg | 3 + winvenv/tcl/tk8.6/msgs/eo.msg | 75 + winvenv/tcl/tk8.6/msgs/es.msg | 76 + winvenv/tcl/tk8.6/msgs/fr.msg | 72 + winvenv/tcl/tk8.6/msgs/hu.msg | 78 + winvenv/tcl/tk8.6/msgs/it.msg | 73 + winvenv/tcl/tk8.6/msgs/nl.msg | 91 + winvenv/tcl/tk8.6/msgs/pl.msg | 91 + winvenv/tcl/tk8.6/msgs/pt.msg | 74 + winvenv/tcl/tk8.6/msgs/ru.msg | 75 + winvenv/tcl/tk8.6/msgs/sv.msg | 76 + winvenv/tcl/tk8.6/obsolete.tcl | 178 + winvenv/tcl/tk8.6/optMenu.tcl | 43 + winvenv/tcl/tk8.6/palette.tcl | 244 + winvenv/tcl/tk8.6/panedwindow.tcl | 194 + winvenv/tcl/tk8.6/pkgIndex.tcl | 7 + winvenv/tcl/tk8.6/safetk.tcl | 262 + winvenv/tcl/tk8.6/scale.tcl | 290 + winvenv/tcl/tk8.6/scrlbar.tcl | 454 + winvenv/tcl/tk8.6/spinbox.tcl | 580 ++ winvenv/tcl/tk8.6/tclIndex | 253 + winvenv/tcl/tk8.6/tearoff.tcl | 180 + winvenv/tcl/tk8.6/text.tcl | 1207 +++ winvenv/tcl/tk8.6/tk.tcl | 695 ++ winvenv/tcl/tk8.6/tkfbox.tcl | 1240 +++ winvenv/tcl/tk8.6/ttk/altTheme.tcl | 107 + winvenv/tcl/tk8.6/ttk/aquaTheme.tcl | 59 + winvenv/tcl/tk8.6/ttk/button.tcl | 83 + winvenv/tcl/tk8.6/ttk/clamTheme.tcl | 145 + winvenv/tcl/tk8.6/ttk/classicTheme.tcl | 113 + winvenv/tcl/tk8.6/ttk/combobox.tcl | 457 + winvenv/tcl/tk8.6/ttk/cursors.tcl | 186 + winvenv/tcl/tk8.6/ttk/defaults.tcl | 141 + winvenv/tcl/tk8.6/ttk/entry.tcl | 607 ++ winvenv/tcl/tk8.6/ttk/fonts.tcl | 157 + winvenv/tcl/tk8.6/ttk/menubutton.tcl | 169 + winvenv/tcl/tk8.6/ttk/notebook.tcl | 197 + winvenv/tcl/tk8.6/ttk/panedwindow.tcl | 82 + winvenv/tcl/tk8.6/ttk/progress.tcl | 49 + winvenv/tcl/tk8.6/ttk/scale.tcl | 94 + winvenv/tcl/tk8.6/ttk/scrollbar.tcl | 123 + winvenv/tcl/tk8.6/ttk/sizegrip.tcl | 102 + winvenv/tcl/tk8.6/ttk/spinbox.tcl | 173 + winvenv/tcl/tk8.6/ttk/treeview.tcl | 363 + winvenv/tcl/tk8.6/ttk/ttk.tcl | 176 + winvenv/tcl/tk8.6/ttk/utils.tcl | 350 + winvenv/tcl/tk8.6/ttk/vistaTheme.tcl | 224 + winvenv/tcl/tk8.6/ttk/winTheme.tcl | 80 + winvenv/tcl/tk8.6/ttk/xpTheme.tcl | 65 + winvenv/tcl/tk8.6/unsupported.tcl | 269 + winvenv/tcl/tk8.6/xmfbox.tcl | 989 ++ 1843 files changed, 398325 insertions(+), 3 deletions(-) create mode 100644 D3Edit.bat mode change 100755 => 100644 D3Edit.py create mode 100644 winvenv/Include/Python-ast.h create mode 100644 winvenv/Include/Python.h create mode 100644 winvenv/Include/abstract.h create mode 100644 winvenv/Include/accu.h create mode 100644 winvenv/Include/asdl.h create mode 100644 winvenv/Include/ast.h create mode 100644 winvenv/Include/bitset.h create mode 100644 winvenv/Include/bltinmodule.h create mode 100644 winvenv/Include/boolobject.h create mode 100644 winvenv/Include/bytearrayobject.h create mode 100644 winvenv/Include/bytes_methods.h create mode 100644 winvenv/Include/bytesobject.h create mode 100644 winvenv/Include/cellobject.h create mode 100644 winvenv/Include/ceval.h create mode 100644 winvenv/Include/classobject.h create mode 100644 winvenv/Include/code.h create mode 100644 winvenv/Include/codecs.h create mode 100644 winvenv/Include/compile.h create mode 100644 winvenv/Include/complexobject.h create mode 100644 winvenv/Include/context.h create mode 100644 winvenv/Include/datetime.h create mode 100644 winvenv/Include/descrobject.h create mode 100644 winvenv/Include/dictobject.h create mode 100644 winvenv/Include/dtoa.h create mode 100644 winvenv/Include/dynamic_annotations.h create mode 100644 winvenv/Include/enumobject.h create mode 100644 winvenv/Include/errcode.h create mode 100644 winvenv/Include/eval.h create mode 100644 winvenv/Include/fileobject.h create mode 100644 winvenv/Include/fileutils.h create mode 100644 winvenv/Include/floatobject.h create mode 100644 winvenv/Include/frameobject.h create mode 100644 winvenv/Include/funcobject.h create mode 100644 winvenv/Include/genobject.h create mode 100644 winvenv/Include/graminit.h create mode 100644 winvenv/Include/grammar.h create mode 100644 winvenv/Include/import.h create mode 100644 winvenv/Include/intrcheck.h create mode 100644 winvenv/Include/iterobject.h create mode 100644 winvenv/Include/listobject.h create mode 100644 winvenv/Include/longintrepr.h create mode 100644 winvenv/Include/longobject.h create mode 100644 winvenv/Include/marshal.h create mode 100644 winvenv/Include/memoryobject.h create mode 100644 winvenv/Include/metagrammar.h create mode 100644 winvenv/Include/methodobject.h create mode 100644 winvenv/Include/modsupport.h create mode 100644 winvenv/Include/moduleobject.h create mode 100644 winvenv/Include/namespaceobject.h create mode 100644 winvenv/Include/node.h create mode 100644 winvenv/Include/object.h create mode 100644 winvenv/Include/objimpl.h create mode 100644 winvenv/Include/odictobject.h create mode 100644 winvenv/Include/opcode.h create mode 100644 winvenv/Include/osdefs.h create mode 100644 winvenv/Include/osmodule.h create mode 100644 winvenv/Include/parsetok.h create mode 100644 winvenv/Include/patchlevel.h create mode 100644 winvenv/Include/pgen.h create mode 100644 winvenv/Include/pgenheaders.h create mode 100644 winvenv/Include/py_curses.h create mode 100644 winvenv/Include/pyarena.h create mode 100644 winvenv/Include/pyatomic.h create mode 100644 winvenv/Include/pycapsule.h create mode 100644 winvenv/Include/pyconfig.h create mode 100644 winvenv/Include/pyctype.h create mode 100644 winvenv/Include/pydebug.h create mode 100644 winvenv/Include/pydtrace.h create mode 100644 winvenv/Include/pyerrors.h create mode 100644 winvenv/Include/pyexpat.h create mode 100644 winvenv/Include/pyfpe.h create mode 100644 winvenv/Include/pyhash.h create mode 100644 winvenv/Include/pylifecycle.h create mode 100644 winvenv/Include/pymacconfig.h create mode 100644 winvenv/Include/pymacro.h create mode 100644 winvenv/Include/pymath.h create mode 100644 winvenv/Include/pymem.h create mode 100644 winvenv/Include/pyport.h create mode 100644 winvenv/Include/pystate.h create mode 100644 winvenv/Include/pystrcmp.h create mode 100644 winvenv/Include/pystrhex.h create mode 100644 winvenv/Include/pystrtod.h create mode 100644 winvenv/Include/pythonrun.h create mode 100644 winvenv/Include/pythread.h create mode 100644 winvenv/Include/pytime.h create mode 100644 winvenv/Include/rangeobject.h create mode 100644 winvenv/Include/setobject.h create mode 100644 winvenv/Include/sliceobject.h create mode 100644 winvenv/Include/structmember.h create mode 100644 winvenv/Include/structseq.h create mode 100644 winvenv/Include/symtable.h create mode 100644 winvenv/Include/sysmodule.h create mode 100644 winvenv/Include/token.h create mode 100644 winvenv/Include/traceback.h create mode 100644 winvenv/Include/tupleobject.h create mode 100644 winvenv/Include/typeslots.h create mode 100644 winvenv/Include/ucnhash.h create mode 100644 winvenv/Include/unicodeobject.h create mode 100644 winvenv/Include/warnings.h create mode 100644 winvenv/Include/weakrefobject.h create mode 100644 winvenv/Lib/__future__.py create mode 100644 winvenv/Lib/_bootlocale.py create mode 100644 winvenv/Lib/_collections_abc.py create mode 100644 winvenv/Lib/_dummy_thread.py create mode 100644 winvenv/Lib/_weakrefset.py create mode 100644 winvenv/Lib/abc.py create mode 100644 winvenv/Lib/base64.py create mode 100644 winvenv/Lib/bisect.py create mode 100644 winvenv/Lib/codecs.py create mode 100644 winvenv/Lib/collections/__init__.py create mode 100644 winvenv/Lib/collections/abc.py create mode 100644 winvenv/Lib/copy.py create mode 100644 winvenv/Lib/copyreg.py create mode 100644 winvenv/Lib/distutils/__init__.py create mode 100644 winvenv/Lib/distutils/distutils.cfg create mode 100644 winvenv/Lib/encodings/__init__.py create mode 100644 winvenv/Lib/encodings/aliases.py create mode 100644 winvenv/Lib/encodings/ascii.py create mode 100644 winvenv/Lib/encodings/base64_codec.py create mode 100644 winvenv/Lib/encodings/big5.py create mode 100644 winvenv/Lib/encodings/big5hkscs.py create mode 100644 winvenv/Lib/encodings/bz2_codec.py create mode 100644 winvenv/Lib/encodings/charmap.py create mode 100644 winvenv/Lib/encodings/cp037.py create mode 100644 winvenv/Lib/encodings/cp1006.py create mode 100644 winvenv/Lib/encodings/cp1026.py create mode 100644 winvenv/Lib/encodings/cp1125.py create mode 100644 winvenv/Lib/encodings/cp1140.py create mode 100644 winvenv/Lib/encodings/cp1250.py create mode 100644 winvenv/Lib/encodings/cp1251.py create mode 100644 winvenv/Lib/encodings/cp1252.py create mode 100644 winvenv/Lib/encodings/cp1253.py create mode 100644 winvenv/Lib/encodings/cp1254.py create mode 100644 winvenv/Lib/encodings/cp1255.py create mode 100644 winvenv/Lib/encodings/cp1256.py create mode 100644 winvenv/Lib/encodings/cp1257.py create mode 100644 winvenv/Lib/encodings/cp1258.py create mode 100644 winvenv/Lib/encodings/cp273.py create mode 100644 winvenv/Lib/encodings/cp424.py create mode 100644 winvenv/Lib/encodings/cp437.py create mode 100644 winvenv/Lib/encodings/cp500.py create mode 100644 winvenv/Lib/encodings/cp65001.py create mode 100644 winvenv/Lib/encodings/cp720.py create mode 100644 winvenv/Lib/encodings/cp737.py create mode 100644 winvenv/Lib/encodings/cp775.py create mode 100644 winvenv/Lib/encodings/cp850.py create mode 100644 winvenv/Lib/encodings/cp852.py create mode 100644 winvenv/Lib/encodings/cp855.py create mode 100644 winvenv/Lib/encodings/cp856.py create mode 100644 winvenv/Lib/encodings/cp857.py create mode 100644 winvenv/Lib/encodings/cp858.py create mode 100644 winvenv/Lib/encodings/cp860.py create mode 100644 winvenv/Lib/encodings/cp861.py create mode 100644 winvenv/Lib/encodings/cp862.py create mode 100644 winvenv/Lib/encodings/cp863.py create mode 100644 winvenv/Lib/encodings/cp864.py create mode 100644 winvenv/Lib/encodings/cp865.py create mode 100644 winvenv/Lib/encodings/cp866.py create mode 100644 winvenv/Lib/encodings/cp869.py create mode 100644 winvenv/Lib/encodings/cp874.py create mode 100644 winvenv/Lib/encodings/cp875.py create mode 100644 winvenv/Lib/encodings/cp932.py create mode 100644 winvenv/Lib/encodings/cp949.py create mode 100644 winvenv/Lib/encodings/cp950.py create mode 100644 winvenv/Lib/encodings/euc_jis_2004.py create mode 100644 winvenv/Lib/encodings/euc_jisx0213.py create mode 100644 winvenv/Lib/encodings/euc_jp.py create mode 100644 winvenv/Lib/encodings/euc_kr.py create mode 100644 winvenv/Lib/encodings/gb18030.py create mode 100644 winvenv/Lib/encodings/gb2312.py create mode 100644 winvenv/Lib/encodings/gbk.py create mode 100644 winvenv/Lib/encodings/hex_codec.py create mode 100644 winvenv/Lib/encodings/hp_roman8.py create mode 100644 winvenv/Lib/encodings/hz.py create mode 100644 winvenv/Lib/encodings/idna.py create mode 100644 winvenv/Lib/encodings/iso2022_jp.py create mode 100644 winvenv/Lib/encodings/iso2022_jp_1.py create mode 100644 winvenv/Lib/encodings/iso2022_jp_2.py create mode 100644 winvenv/Lib/encodings/iso2022_jp_2004.py create mode 100644 winvenv/Lib/encodings/iso2022_jp_3.py create mode 100644 winvenv/Lib/encodings/iso2022_jp_ext.py create mode 100644 winvenv/Lib/encodings/iso2022_kr.py create mode 100644 winvenv/Lib/encodings/iso8859_1.py create mode 100644 winvenv/Lib/encodings/iso8859_10.py create mode 100644 winvenv/Lib/encodings/iso8859_11.py create mode 100644 winvenv/Lib/encodings/iso8859_13.py create mode 100644 winvenv/Lib/encodings/iso8859_14.py create mode 100644 winvenv/Lib/encodings/iso8859_15.py create mode 100644 winvenv/Lib/encodings/iso8859_16.py create mode 100644 winvenv/Lib/encodings/iso8859_2.py create mode 100644 winvenv/Lib/encodings/iso8859_3.py create mode 100644 winvenv/Lib/encodings/iso8859_4.py create mode 100644 winvenv/Lib/encodings/iso8859_5.py create mode 100644 winvenv/Lib/encodings/iso8859_6.py create mode 100644 winvenv/Lib/encodings/iso8859_7.py create mode 100644 winvenv/Lib/encodings/iso8859_8.py create mode 100644 winvenv/Lib/encodings/iso8859_9.py create mode 100644 winvenv/Lib/encodings/johab.py create mode 100644 winvenv/Lib/encodings/koi8_r.py create mode 100644 winvenv/Lib/encodings/koi8_t.py create mode 100644 winvenv/Lib/encodings/koi8_u.py create mode 100644 winvenv/Lib/encodings/kz1048.py create mode 100644 winvenv/Lib/encodings/latin_1.py create mode 100644 winvenv/Lib/encodings/mac_arabic.py create mode 100644 winvenv/Lib/encodings/mac_centeuro.py create mode 100644 winvenv/Lib/encodings/mac_croatian.py create mode 100644 winvenv/Lib/encodings/mac_cyrillic.py create mode 100644 winvenv/Lib/encodings/mac_farsi.py create mode 100644 winvenv/Lib/encodings/mac_greek.py create mode 100644 winvenv/Lib/encodings/mac_iceland.py create mode 100644 winvenv/Lib/encodings/mac_latin2.py create mode 100644 winvenv/Lib/encodings/mac_roman.py create mode 100644 winvenv/Lib/encodings/mac_romanian.py create mode 100644 winvenv/Lib/encodings/mac_turkish.py create mode 100644 winvenv/Lib/encodings/mbcs.py create mode 100644 winvenv/Lib/encodings/oem.py create mode 100644 winvenv/Lib/encodings/palmos.py create mode 100644 winvenv/Lib/encodings/ptcp154.py create mode 100644 winvenv/Lib/encodings/punycode.py create mode 100644 winvenv/Lib/encodings/quopri_codec.py create mode 100644 winvenv/Lib/encodings/raw_unicode_escape.py create mode 100644 winvenv/Lib/encodings/rot_13.py create mode 100644 winvenv/Lib/encodings/shift_jis.py create mode 100644 winvenv/Lib/encodings/shift_jis_2004.py create mode 100644 winvenv/Lib/encodings/shift_jisx0213.py create mode 100644 winvenv/Lib/encodings/tis_620.py create mode 100644 winvenv/Lib/encodings/undefined.py create mode 100644 winvenv/Lib/encodings/unicode_escape.py create mode 100644 winvenv/Lib/encodings/unicode_internal.py create mode 100644 winvenv/Lib/encodings/utf_16.py create mode 100644 winvenv/Lib/encodings/utf_16_be.py create mode 100644 winvenv/Lib/encodings/utf_16_le.py create mode 100644 winvenv/Lib/encodings/utf_32.py create mode 100644 winvenv/Lib/encodings/utf_32_be.py create mode 100644 winvenv/Lib/encodings/utf_32_le.py create mode 100644 winvenv/Lib/encodings/utf_7.py create mode 100644 winvenv/Lib/encodings/utf_8.py create mode 100644 winvenv/Lib/encodings/utf_8_sig.py create mode 100644 winvenv/Lib/encodings/uu_codec.py create mode 100644 winvenv/Lib/encodings/zlib_codec.py create mode 100644 winvenv/Lib/enum.py create mode 100644 winvenv/Lib/fnmatch.py create mode 100644 winvenv/Lib/functools.py create mode 100644 winvenv/Lib/genericpath.py create mode 100644 winvenv/Lib/hashlib.py create mode 100644 winvenv/Lib/heapq.py create mode 100644 winvenv/Lib/hmac.py create mode 100644 winvenv/Lib/imp.py create mode 100644 winvenv/Lib/importlib/__init__.py create mode 100644 winvenv/Lib/importlib/_bootstrap.py create mode 100644 winvenv/Lib/importlib/_bootstrap_external.py create mode 100644 winvenv/Lib/importlib/abc.py create mode 100644 winvenv/Lib/importlib/machinery.py create mode 100644 winvenv/Lib/importlib/resources.py create mode 100644 winvenv/Lib/importlib/util.py create mode 100644 winvenv/Lib/io.py create mode 100644 winvenv/Lib/keyword.py create mode 100644 winvenv/Lib/linecache.py create mode 100644 winvenv/Lib/locale.py create mode 100644 winvenv/Lib/no-global-site-packages.txt create mode 100644 winvenv/Lib/ntpath.py create mode 100644 winvenv/Lib/operator.py create mode 100644 winvenv/Lib/orig-prefix.txt create mode 100644 winvenv/Lib/os.py create mode 100644 winvenv/Lib/posixpath.py create mode 100644 winvenv/Lib/random.py create mode 100644 winvenv/Lib/re.py create mode 100644 winvenv/Lib/reprlib.py create mode 100644 winvenv/Lib/rlcompleter.py create mode 100644 winvenv/Lib/shutil.py create mode 100644 winvenv/Lib/site-packages/easy_install.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/__init__.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/any_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/any_test_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/api_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/compiler/__init__.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/descriptor.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/descriptor_database.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/descriptor_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/descriptor_pool.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/duration_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/empty_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/field_mask_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/__init__.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/_parameterized.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/any_test_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/api_implementation.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/containers.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/decoder.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/descriptor_database_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/descriptor_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/encoder.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/enum_type_wrapper.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/factory_test1_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/factory_test2_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/file_options_test_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/generator_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/__init__.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/json_format_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/message_factory_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/message_listener.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/message_set_extensions_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/message_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/missing_enum_values_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/more_messages_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/no_package_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/packed_field_test_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/proto_builder_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/python_message.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/reflection_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/service_reflection_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/symbol_database_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/test_bad_identifiers_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/test_util.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/testing_refleaks.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/text_encoding_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/text_format_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/type_checkers.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/unknown_fields_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/well_known_types.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/well_known_types_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/wire_format.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/internal/wire_format_test.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/json_format.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/map_proto2_unittest_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/map_unittest_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/message.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/message_factory.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/proto_builder.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/pyext/__init__.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/pyext/cpp_message.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/pyext/python_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/reflection.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/service.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/service_reflection.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/source_context_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/struct_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/symbol_database.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/test_messages_proto2_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/test_messages_proto3_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/text_encoding.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/text_format.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/timestamp_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/type_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_arena_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_custom_options_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_import_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_import_public_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_mset_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_import_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_no_generic_services_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/unittest_proto3_arena_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/util/__init__.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/util/json_format_proto3_pb2.py create mode 100644 winvenv/Lib/site-packages/google/protobuf/wrappers_pb2.py create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/INSTALLER create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/LICENSE.txt create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/METADATA create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/RECORD create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/WHEEL create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/entry_points.txt create mode 100644 winvenv/Lib/site-packages/pip-18.1.dist-info/top_level.txt create mode 100644 winvenv/Lib/site-packages/pip/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/__main__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/build_env.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cache.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/base_command.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/main_parser.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/parser.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/cli/status_codes.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/check.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/completion.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/configuration.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/download.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/freeze.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/hash.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/help.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/install.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/list.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/search.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/show.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/uninstall.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/commands/wheel.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/configuration.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/download.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/exceptions.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/index.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/locations.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/models/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/models/candidate.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/models/format_control.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/models/index.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/models/link.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/operations/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/operations/check.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/operations/freeze.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/operations/prepare.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/pep425tags.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/pyproject.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/constructors.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/req_file.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/req_install.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/req_set.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/req_tracker.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/resolve.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/appdirs.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/deprecation.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/encoding.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/filesystem.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/glibc.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/hashes.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/logging.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/misc.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/models.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/outdated.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/packaging.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/typing.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/utils/ui.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/vcs/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/vcs/git.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/vcs/subversion.py create mode 100644 winvenv/Lib/site-packages/pip/_internal/wheel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/appdirs.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 winvenv/Lib/site-packages/pip/_vendor/certifi/core.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/big5freq.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/big5prober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/enums.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/escprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/escsm.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langcyrillicmodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/chardet/version.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/colorama/win32.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/database.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/index.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/locators.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/markers.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/resources.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/util.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/version.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/distro.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_ihatexml.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/datrie.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/_utils.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/constants.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/serializer.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/base.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/base.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/codec.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/core.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/intranges.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/package_data.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/ipaddress.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/lockfile/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/lockfile/linklockfile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/lockfile/mkdirlockfile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/lockfile/pidlockfile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/lockfile/sqlitelockfile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/lockfile/symlinklockfile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/msgpack/_version.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/__about__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/_compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/markers.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/utils.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/packaging/version.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/_in_process.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/check.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/colorlog.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/envbuild.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pep517/wrappers.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/progress/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/progress/bar.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/progress/counter.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/progress/helpers.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/progress/spinner.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pyparsing.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pytoml/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pytoml/core.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pytoml/parser.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/pytoml/writer.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/__version__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/api.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/help.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/models.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/packages.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/requests/utils.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/retrying.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/six.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/request.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/response.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/webencodings/__init__.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/webencodings/labels.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/webencodings/tests.py create mode 100644 winvenv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/__init__.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_compat.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/_vendor/six.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/extern/__init__.py create mode 100644 winvenv/Lib/site-packages/pkg_resources/py31compat.py create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1-nspkg.pth create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/DESCRIPTION.rst create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/INSTALLER create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/METADATA create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/RECORD create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/WHEEL create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/metadata.json create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt create mode 100644 winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/top_level.txt create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/INSTALLER create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/LICENSE create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/METADATA create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/RECORD create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/WHEEL create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/entry_points.txt create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/top_level.txt create mode 100644 winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/zip-safe create mode 100644 winvenv/Lib/site-packages/setuptools/__init__.py create mode 100644 winvenv/Lib/site-packages/setuptools/_deprecation_warning.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/__init__.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/_compat.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 winvenv/Lib/site-packages/setuptools/_vendor/six.py create mode 100644 winvenv/Lib/site-packages/setuptools/archive_util.py create mode 100644 winvenv/Lib/site-packages/setuptools/build_meta.py create mode 100644 winvenv/Lib/site-packages/setuptools/cli-32.exe create mode 100644 winvenv/Lib/site-packages/setuptools/cli-64.exe create mode 100644 winvenv/Lib/site-packages/setuptools/cli.exe create mode 100644 winvenv/Lib/site-packages/setuptools/command/__init__.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/alias.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/bdist_egg.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/bdist_rpm.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/bdist_wininst.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/build_clib.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/build_ext.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/build_py.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/develop.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/dist_info.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/easy_install.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/egg_info.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/install.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/install_egg_info.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/install_lib.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/install_scripts.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/launcher manifest.xml create mode 100644 winvenv/Lib/site-packages/setuptools/command/py36compat.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/register.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/rotate.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/saveopts.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/sdist.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/setopt.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/test.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/upload.py create mode 100644 winvenv/Lib/site-packages/setuptools/command/upload_docs.py create mode 100644 winvenv/Lib/site-packages/setuptools/config.py create mode 100644 winvenv/Lib/site-packages/setuptools/dep_util.py create mode 100644 winvenv/Lib/site-packages/setuptools/depends.py create mode 100644 winvenv/Lib/site-packages/setuptools/dist.py create mode 100644 winvenv/Lib/site-packages/setuptools/extension.py create mode 100644 winvenv/Lib/site-packages/setuptools/extern/__init__.py create mode 100644 winvenv/Lib/site-packages/setuptools/glibc.py create mode 100644 winvenv/Lib/site-packages/setuptools/glob.py create mode 100644 winvenv/Lib/site-packages/setuptools/gui-32.exe create mode 100644 winvenv/Lib/site-packages/setuptools/gui-64.exe create mode 100644 winvenv/Lib/site-packages/setuptools/gui.exe create mode 100644 winvenv/Lib/site-packages/setuptools/launch.py create mode 100644 winvenv/Lib/site-packages/setuptools/lib2to3_ex.py create mode 100644 winvenv/Lib/site-packages/setuptools/monkey.py create mode 100644 winvenv/Lib/site-packages/setuptools/msvc.py create mode 100644 winvenv/Lib/site-packages/setuptools/namespaces.py create mode 100644 winvenv/Lib/site-packages/setuptools/package_index.py create mode 100644 winvenv/Lib/site-packages/setuptools/pep425tags.py create mode 100644 winvenv/Lib/site-packages/setuptools/py27compat.py create mode 100644 winvenv/Lib/site-packages/setuptools/py31compat.py create mode 100644 winvenv/Lib/site-packages/setuptools/py33compat.py create mode 100644 winvenv/Lib/site-packages/setuptools/py36compat.py create mode 100644 winvenv/Lib/site-packages/setuptools/sandbox.py create mode 100644 winvenv/Lib/site-packages/setuptools/script (dev).tmpl create mode 100644 winvenv/Lib/site-packages/setuptools/script.tmpl create mode 100644 winvenv/Lib/site-packages/setuptools/site-patch.py create mode 100644 winvenv/Lib/site-packages/setuptools/ssl_support.py create mode 100644 winvenv/Lib/site-packages/setuptools/unicode_utils.py create mode 100644 winvenv/Lib/site-packages/setuptools/version.py create mode 100644 winvenv/Lib/site-packages/setuptools/wheel.py create mode 100644 winvenv/Lib/site-packages/setuptools/windows_support.py create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/INSTALLER create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/METADATA create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/RECORD create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/WHEEL create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/metadata.json create mode 100644 winvenv/Lib/site-packages/six-1.11.0.dist-info/top_level.txt create mode 100644 winvenv/Lib/site-packages/six.py create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/INSTALLER create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/LICENSE.txt create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/METADATA create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/RECORD create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/WHEEL create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/entry_points.txt create mode 100644 winvenv/Lib/site-packages/wheel-0.32.3.dist-info/top_level.txt create mode 100644 winvenv/Lib/site-packages/wheel/__init__.py create mode 100644 winvenv/Lib/site-packages/wheel/__main__.py create mode 100644 winvenv/Lib/site-packages/wheel/bdist_wheel.py create mode 100644 winvenv/Lib/site-packages/wheel/cli/__init__.py create mode 100644 winvenv/Lib/site-packages/wheel/cli/convert.py create mode 100644 winvenv/Lib/site-packages/wheel/cli/install.py create mode 100644 winvenv/Lib/site-packages/wheel/cli/pack.py create mode 100644 winvenv/Lib/site-packages/wheel/cli/unpack.py create mode 100644 winvenv/Lib/site-packages/wheel/metadata.py create mode 100644 winvenv/Lib/site-packages/wheel/pep425tags.py create mode 100644 winvenv/Lib/site-packages/wheel/pkginfo.py create mode 100644 winvenv/Lib/site-packages/wheel/util.py create mode 100644 winvenv/Lib/site-packages/wheel/wheelfile.py create mode 100644 winvenv/Lib/site.py create mode 100644 winvenv/Lib/sre_compile.py create mode 100644 winvenv/Lib/sre_constants.py create mode 100644 winvenv/Lib/sre_parse.py create mode 100644 winvenv/Lib/stat.py create mode 100644 winvenv/Lib/struct.py create mode 100644 winvenv/Lib/tarfile.py create mode 100644 winvenv/Lib/tempfile.py create mode 100644 winvenv/Lib/token.py create mode 100644 winvenv/Lib/tokenize.py create mode 100644 winvenv/Lib/types.py create mode 100644 winvenv/Lib/warnings.py create mode 100644 winvenv/Lib/weakref.py create mode 100644 winvenv/Scripts/activate create mode 100644 winvenv/Scripts/activate.bat create mode 100644 winvenv/Scripts/activate.ps1 create mode 100644 winvenv/Scripts/activate_this.py create mode 100644 winvenv/Scripts/deactivate.bat create mode 100644 winvenv/Scripts/easy_install-3.7.exe create mode 100644 winvenv/Scripts/easy_install.exe create mode 100644 winvenv/Scripts/pip.exe create mode 100644 winvenv/Scripts/pip3.7.exe create mode 100644 winvenv/Scripts/pip3.exe create mode 100644 winvenv/Scripts/python.exe create mode 100644 winvenv/Scripts/python3.dll create mode 100644 winvenv/Scripts/python37.dll create mode 100644 winvenv/Scripts/pythonw.exe create mode 100644 winvenv/Scripts/wheel.exe create mode 100644 winvenv/tcl/tcl8.6/auto.tcl create mode 100644 winvenv/tcl/tcl8.6/clock.tcl create mode 100644 winvenv/tcl/tcl8.6/encoding/ascii.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/big5.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1250.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1251.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1252.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1253.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1254.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1255.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1256.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1257.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp1258.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp437.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp737.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp775.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp850.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp852.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp855.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp857.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp860.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp861.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp862.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp863.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp864.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp865.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp866.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp869.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp874.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp932.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp936.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp949.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/cp950.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/dingbats.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/ebcdic.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/euc-cn.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/euc-jp.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/euc-kr.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/gb12345.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/gb1988.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/gb2312-raw.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/gb2312.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso2022-jp.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso2022-kr.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso2022.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-1.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-10.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-13.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-14.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-15.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-16.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-2.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-3.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-4.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-5.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-6.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-7.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-8.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/iso8859-9.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/jis0201.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/jis0208.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/jis0212.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/koi8-r.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/koi8-u.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/ksc5601.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macCentEuro.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macCroatian.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macCyrillic.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macDingbats.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macGreek.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macIceland.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macJapan.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macRoman.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macRomania.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macThai.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macTurkish.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/macUkraine.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/shiftjis.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/symbol.enc create mode 100644 winvenv/tcl/tcl8.6/encoding/tis-620.enc create mode 100644 winvenv/tcl/tcl8.6/history.tcl create mode 100644 winvenv/tcl/tcl8.6/http1.0/http.tcl create mode 100644 winvenv/tcl/tcl8.6/http1.0/pkgIndex.tcl create mode 100644 winvenv/tcl/tcl8.6/init.tcl create mode 100644 winvenv/tcl/tcl8.6/msgs/af.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/af_za.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ar.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ar_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ar_jo.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ar_lb.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ar_sy.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/be.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/bg.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/bn.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/bn_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ca.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/cs.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/da.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/de.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/de_at.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/de_be.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/el.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_au.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_be.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_bw.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_ca.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_gb.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_hk.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_ie.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_nz.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_ph.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_sg.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_za.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/en_zw.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/eo.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_ar.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_bo.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_cl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_co.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_cr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_do.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_ec.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_gt.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_hn.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_mx.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_ni.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_pa.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_pe.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_pr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_py.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_sv.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_uy.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/es_ve.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/et.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/eu.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/eu_es.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fa.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fa_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fa_ir.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fi.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fo.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fo_fo.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fr_be.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fr_ca.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/fr_ch.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ga.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ga_ie.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/gl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/gl_es.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/gv.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/gv_gb.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/he.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/hi.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/hi_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/hr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/hu.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/id.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/id_id.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/is.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/it.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/it_ch.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ja.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/kl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/kl_gl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ko.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ko_kr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/kok.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/kok_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/kw.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/kw_gb.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/lt.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/lv.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/mk.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/mr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/mr_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ms.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ms_my.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/mt.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/nb.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/nl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/nl_be.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/nn.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/pl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/pt.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/pt_br.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ro.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ru.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ru_ua.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sh.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sk.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sl.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sq.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sv.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/sw.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ta.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/ta_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/te.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/te_in.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/th.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/tr.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/uk.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/vi.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/zh.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/zh_cn.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/zh_hk.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/zh_sg.msg create mode 100644 winvenv/tcl/tcl8.6/msgs/zh_tw.msg create mode 100644 winvenv/tcl/tcl8.6/opt0.4/optparse.tcl create mode 100644 winvenv/tcl/tcl8.6/opt0.4/pkgIndex.tcl create mode 100644 winvenv/tcl/tcl8.6/package.tcl create mode 100644 winvenv/tcl/tcl8.6/parray.tcl create mode 100644 winvenv/tcl/tcl8.6/safe.tcl create mode 100644 winvenv/tcl/tcl8.6/tclIndex create mode 100644 winvenv/tcl/tcl8.6/tm.tcl create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Abidjan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Accra create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Addis_Ababa create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Algiers create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Asmara create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Asmera create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Bamako create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Bangui create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Banjul create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Bissau create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Blantyre create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Brazzaville create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Bujumbura create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Cairo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Casablanca create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Ceuta create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Conakry create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Dakar create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Dar_es_Salaam create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Djibouti create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Douala create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/El_Aaiun create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Freetown create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Gaborone create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Harare create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Johannesburg create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Juba create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Kampala create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Khartoum create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Kigali create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Kinshasa create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Lagos create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Libreville create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Lome create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Luanda create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Lubumbashi create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Lusaka create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Malabo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Maputo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Maseru create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Mbabane create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Mogadishu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Monrovia create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Nairobi create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Ndjamena create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Niamey create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Nouakchott create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Ouagadougou create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Porto-Novo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Sao_Tome create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Timbuktu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Tripoli create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Tunis create mode 100644 winvenv/tcl/tcl8.6/tzdata/Africa/Windhoek create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Adak create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Anchorage create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Anguilla create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Antigua create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Araguaina create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Buenos_Aires create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Catamarca create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/ComodRivadavia create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Cordoba create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Jujuy create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/La_Rioja create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Mendoza create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Rio_Gallegos create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Salta create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/San_Juan create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/San_Luis create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Tucuman create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Argentina/Ushuaia create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Aruba create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Asuncion create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Atikokan create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Atka create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Bahia create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Bahia_Banderas create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Barbados create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Belem create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Belize create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Blanc-Sablon create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Boa_Vista create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Bogota create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Boise create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Buenos_Aires create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Cambridge_Bay create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Campo_Grande create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Cancun create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Caracas create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Catamarca create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Cayenne create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Cayman create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Chicago create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Chihuahua create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Coral_Harbour create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Cordoba create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Costa_Rica create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Creston create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Cuiaba create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Curacao create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Danmarkshavn create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Dawson create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Dawson_Creek create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Denver create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Detroit create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Dominica create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Edmonton create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Eirunepe create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/El_Salvador create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Ensenada create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Fort_Nelson create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Fort_Wayne create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Fortaleza create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Glace_Bay create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Godthab create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Goose_Bay create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Grand_Turk create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Grenada create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Guadeloupe create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Guatemala create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Guayaquil create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Guyana create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Halifax create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Havana create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Hermosillo create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Indianapolis create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Knox create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Marengo create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Petersburg create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Tell_City create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Vevay create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Vincennes create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indiana/Winamac create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Indianapolis create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Inuvik create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Iqaluit create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Jamaica create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Jujuy create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Juneau create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Kentucky/Louisville create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Kentucky/Monticello create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Knox_IN create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Kralendijk create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/La_Paz create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Lima create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Los_Angeles create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Louisville create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Lower_Princes create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Maceio create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Managua create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Manaus create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Marigot create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Martinique create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Matamoros create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Mazatlan create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Mendoza create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Menominee create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Merida create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Metlakatla create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Mexico_City create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Miquelon create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Moncton create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Monterrey create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Montevideo create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Montreal create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Montserrat create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Nassau create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/New_York create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Nipigon create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Nome create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Noronha create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/North_Dakota/Beulah create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/North_Dakota/Center create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/North_Dakota/New_Salem create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Ojinaga create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Panama create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Pangnirtung create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Paramaribo create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Phoenix create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Port-au-Prince create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Port_of_Spain create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Porto_Acre create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Porto_Velho create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Puerto_Rico create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Punta_Arenas create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Rainy_River create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Rankin_Inlet create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Recife create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Regina create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Resolute create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Rio_Branco create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Rosario create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Santa_Isabel create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Santarem create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Santiago create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Santo_Domingo create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Sao_Paulo create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Scoresbysund create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Shiprock create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Sitka create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/St_Barthelemy create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/St_Johns create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/St_Kitts create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/St_Lucia create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/St_Thomas create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/St_Vincent create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Swift_Current create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Tegucigalpa create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Thule create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Thunder_Bay create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Tijuana create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Toronto create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Tortola create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Vancouver create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Virgin create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Whitehorse create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Winnipeg create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Yakutat create mode 100644 winvenv/tcl/tcl8.6/tzdata/America/Yellowknife create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Casey create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Davis create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/DumontDUrville create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Macquarie create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Mawson create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/McMurdo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Palmer create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Rothera create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/South_Pole create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Syowa create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Troll create mode 100644 winvenv/tcl/tcl8.6/tzdata/Antarctica/Vostok create mode 100644 winvenv/tcl/tcl8.6/tzdata/Arctic/Longyearbyen create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Aden create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Almaty create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Amman create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Anadyr create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Aqtau create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Aqtobe create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ashgabat create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ashkhabad create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Atyrau create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Baghdad create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Bahrain create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Baku create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Bangkok create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Barnaul create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Beirut create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Bishkek create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Brunei create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Calcutta create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Chita create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Choibalsan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Chongqing create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Chungking create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Colombo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Dacca create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Damascus create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Dhaka create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Dili create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Dubai create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Dushanbe create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Famagusta create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Gaza create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Harbin create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Hebron create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ho_Chi_Minh create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Hong_Kong create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Hovd create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Irkutsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Istanbul create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Jakarta create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Jayapura create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Jerusalem create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kabul create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kamchatka create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Karachi create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kashgar create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kathmandu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Katmandu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Khandyga create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kolkata create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Krasnoyarsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kuala_Lumpur create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kuching create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Kuwait create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Macao create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Macau create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Magadan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Makassar create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Manila create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Muscat create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Nicosia create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Novokuznetsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Novosibirsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Omsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Oral create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Phnom_Penh create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Pontianak create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Pyongyang create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Qatar create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Qyzylorda create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Rangoon create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Riyadh create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Saigon create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Sakhalin create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Samarkand create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Seoul create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Shanghai create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Singapore create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Srednekolymsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Taipei create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Tashkent create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Tbilisi create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Tehran create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Tel_Aviv create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Thimbu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Thimphu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Tokyo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Tomsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ujung_Pandang create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ulaanbaatar create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ulan_Bator create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Urumqi create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Ust-Nera create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Vientiane create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Vladivostok create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Yakutsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Yangon create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Yekaterinburg create mode 100644 winvenv/tcl/tcl8.6/tzdata/Asia/Yerevan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Azores create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Bermuda create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Canary create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Cape_Verde create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Faeroe create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Faroe create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Jan_Mayen create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Madeira create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Reykjavik create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/South_Georgia create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/St_Helena create mode 100644 winvenv/tcl/tcl8.6/tzdata/Atlantic/Stanley create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/ACT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Adelaide create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Brisbane create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Broken_Hill create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Canberra create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Currie create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Darwin create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Eucla create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Hobart create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/LHI create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Lindeman create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Lord_Howe create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Melbourne create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/NSW create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/North create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Perth create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Queensland create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/South create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Sydney create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Tasmania create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Victoria create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/West create mode 100644 winvenv/tcl/tcl8.6/tzdata/Australia/Yancowinna create mode 100644 winvenv/tcl/tcl8.6/tzdata/Brazil/Acre create mode 100644 winvenv/tcl/tcl8.6/tzdata/Brazil/DeNoronha create mode 100644 winvenv/tcl/tcl8.6/tzdata/Brazil/East create mode 100644 winvenv/tcl/tcl8.6/tzdata/Brazil/West create mode 100644 winvenv/tcl/tcl8.6/tzdata/CET create mode 100644 winvenv/tcl/tcl8.6/tzdata/CST6CDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Atlantic create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Central create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/East-Saskatchewan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Eastern create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Mountain create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Newfoundland create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Pacific create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Saskatchewan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Canada/Yukon create mode 100644 winvenv/tcl/tcl8.6/tzdata/Chile/Continental create mode 100644 winvenv/tcl/tcl8.6/tzdata/Chile/EasterIsland create mode 100644 winvenv/tcl/tcl8.6/tzdata/Cuba create mode 100644 winvenv/tcl/tcl8.6/tzdata/EET create mode 100644 winvenv/tcl/tcl8.6/tzdata/EST create mode 100644 winvenv/tcl/tcl8.6/tzdata/EST5EDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Egypt create mode 100644 winvenv/tcl/tcl8.6/tzdata/Eire create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+0 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+1 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+10 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+11 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+12 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+2 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+3 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+4 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+5 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+6 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+7 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+8 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT+9 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-0 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-1 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-10 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-11 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-12 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-13 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-14 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-2 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-3 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-4 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-5 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-6 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-7 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-8 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT-9 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/GMT0 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/Greenwich create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/UCT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/UTC create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/Universal create mode 100644 winvenv/tcl/tcl8.6/tzdata/Etc/Zulu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Amsterdam create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Andorra create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Astrakhan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Athens create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Belfast create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Belgrade create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Berlin create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Bratislava create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Brussels create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Bucharest create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Budapest create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Busingen create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Chisinau create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Copenhagen create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Dublin create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Gibraltar create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Guernsey create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Helsinki create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Isle_of_Man create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Istanbul create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Jersey create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Kaliningrad create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Kiev create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Kirov create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Lisbon create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Ljubljana create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/London create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Luxembourg create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Madrid create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Malta create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Mariehamn create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Minsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Monaco create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Moscow create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Nicosia create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Oslo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Paris create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Podgorica create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Prague create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Riga create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Rome create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Samara create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/San_Marino create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Sarajevo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Saratov create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Simferopol create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Skopje create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Sofia create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Stockholm create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Tallinn create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Tirane create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Tiraspol create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Ulyanovsk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Uzhgorod create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Vaduz create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Vatican create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Vienna create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Vilnius create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Volgograd create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Warsaw create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Zagreb create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Zaporozhye create mode 100644 winvenv/tcl/tcl8.6/tzdata/Europe/Zurich create mode 100644 winvenv/tcl/tcl8.6/tzdata/GB create mode 100644 winvenv/tcl/tcl8.6/tzdata/GB-Eire create mode 100644 winvenv/tcl/tcl8.6/tzdata/GMT create mode 100644 winvenv/tcl/tcl8.6/tzdata/GMT+0 create mode 100644 winvenv/tcl/tcl8.6/tzdata/GMT-0 create mode 100644 winvenv/tcl/tcl8.6/tzdata/GMT0 create mode 100644 winvenv/tcl/tcl8.6/tzdata/Greenwich create mode 100644 winvenv/tcl/tcl8.6/tzdata/HST create mode 100644 winvenv/tcl/tcl8.6/tzdata/Hongkong create mode 100644 winvenv/tcl/tcl8.6/tzdata/Iceland create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Antananarivo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Chagos create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Christmas create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Cocos create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Comoro create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Kerguelen create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Mahe create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Maldives create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Mauritius create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Mayotte create mode 100644 winvenv/tcl/tcl8.6/tzdata/Indian/Reunion create mode 100644 winvenv/tcl/tcl8.6/tzdata/Iran create mode 100644 winvenv/tcl/tcl8.6/tzdata/Israel create mode 100644 winvenv/tcl/tcl8.6/tzdata/Jamaica create mode 100644 winvenv/tcl/tcl8.6/tzdata/Japan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Kwajalein create mode 100644 winvenv/tcl/tcl8.6/tzdata/Libya create mode 100644 winvenv/tcl/tcl8.6/tzdata/MET create mode 100644 winvenv/tcl/tcl8.6/tzdata/MST create mode 100644 winvenv/tcl/tcl8.6/tzdata/MST7MDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Mexico/BajaNorte create mode 100644 winvenv/tcl/tcl8.6/tzdata/Mexico/BajaSur create mode 100644 winvenv/tcl/tcl8.6/tzdata/Mexico/General create mode 100644 winvenv/tcl/tcl8.6/tzdata/NZ create mode 100644 winvenv/tcl/tcl8.6/tzdata/NZ-CHAT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Navajo create mode 100644 winvenv/tcl/tcl8.6/tzdata/PRC create mode 100644 winvenv/tcl/tcl8.6/tzdata/PST8PDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Apia create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Auckland create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Bougainville create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Chatham create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Chuuk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Easter create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Efate create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Enderbury create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Fakaofo create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Fiji create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Funafuti create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Galapagos create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Gambier create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Guadalcanal create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Guam create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Honolulu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Johnston create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Kiritimati create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Kosrae create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Kwajalein create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Majuro create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Marquesas create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Midway create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Nauru create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Niue create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Norfolk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Noumea create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Pago_Pago create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Palau create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Pitcairn create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Pohnpei create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Ponape create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Port_Moresby create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Rarotonga create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Saipan create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Samoa create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Tahiti create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Tarawa create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Tongatapu create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Truk create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Wake create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Wallis create mode 100644 winvenv/tcl/tcl8.6/tzdata/Pacific/Yap create mode 100644 winvenv/tcl/tcl8.6/tzdata/Poland create mode 100644 winvenv/tcl/tcl8.6/tzdata/Portugal create mode 100644 winvenv/tcl/tcl8.6/tzdata/ROC create mode 100644 winvenv/tcl/tcl8.6/tzdata/ROK create mode 100644 winvenv/tcl/tcl8.6/tzdata/Singapore create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/AST4 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/AST4ADT create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/CST6 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/CST6CDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/EST5 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/EST5EDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/HST10 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/MST7 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/MST7MDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/PST8 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/PST8PDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/YST9 create mode 100644 winvenv/tcl/tcl8.6/tzdata/SystemV/YST9YDT create mode 100644 winvenv/tcl/tcl8.6/tzdata/Turkey create mode 100644 winvenv/tcl/tcl8.6/tzdata/UCT create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Alaska create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Aleutian create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Arizona create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Central create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/East-Indiana create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Eastern create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Hawaii create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Indiana-Starke create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Michigan create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Mountain create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Pacific create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Pacific-New create mode 100644 winvenv/tcl/tcl8.6/tzdata/US/Samoa create mode 100644 winvenv/tcl/tcl8.6/tzdata/UTC create mode 100644 winvenv/tcl/tcl8.6/tzdata/Universal create mode 100644 winvenv/tcl/tcl8.6/tzdata/W-SU create mode 100644 winvenv/tcl/tcl8.6/tzdata/WET create mode 100644 winvenv/tcl/tcl8.6/tzdata/Zulu create mode 100644 winvenv/tcl/tcl8.6/word.tcl create mode 100644 winvenv/tcl/tk8.6/bgerror.tcl create mode 100644 winvenv/tcl/tk8.6/button.tcl create mode 100644 winvenv/tcl/tk8.6/choosedir.tcl create mode 100644 winvenv/tcl/tk8.6/clrpick.tcl create mode 100644 winvenv/tcl/tk8.6/comdlg.tcl create mode 100644 winvenv/tcl/tk8.6/console.tcl create mode 100644 winvenv/tcl/tk8.6/demos/README create mode 100644 winvenv/tcl/tk8.6/demos/anilabel.tcl create mode 100644 winvenv/tcl/tk8.6/demos/aniwave.tcl create mode 100644 winvenv/tcl/tk8.6/demos/arrow.tcl create mode 100644 winvenv/tcl/tk8.6/demos/bind.tcl create mode 100644 winvenv/tcl/tk8.6/demos/bitmap.tcl create mode 100644 winvenv/tcl/tk8.6/demos/browse create mode 100644 winvenv/tcl/tk8.6/demos/button.tcl create mode 100644 winvenv/tcl/tk8.6/demos/check.tcl create mode 100644 winvenv/tcl/tk8.6/demos/clrpick.tcl create mode 100644 winvenv/tcl/tk8.6/demos/colors.tcl create mode 100644 winvenv/tcl/tk8.6/demos/combo.tcl create mode 100644 winvenv/tcl/tk8.6/demos/cscroll.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ctext.tcl create mode 100644 winvenv/tcl/tk8.6/demos/dialog1.tcl create mode 100644 winvenv/tcl/tk8.6/demos/dialog2.tcl create mode 100644 winvenv/tcl/tk8.6/demos/en.msg create mode 100644 winvenv/tcl/tk8.6/demos/entry1.tcl create mode 100644 winvenv/tcl/tk8.6/demos/entry2.tcl create mode 100644 winvenv/tcl/tk8.6/demos/entry3.tcl create mode 100644 winvenv/tcl/tk8.6/demos/filebox.tcl create mode 100644 winvenv/tcl/tk8.6/demos/floor.tcl create mode 100644 winvenv/tcl/tk8.6/demos/fontchoose.tcl create mode 100644 winvenv/tcl/tk8.6/demos/form.tcl create mode 100644 winvenv/tcl/tk8.6/demos/goldberg.tcl create mode 100644 winvenv/tcl/tk8.6/demos/hello create mode 100644 winvenv/tcl/tk8.6/demos/hscale.tcl create mode 100644 winvenv/tcl/tk8.6/demos/icon.tcl create mode 100644 winvenv/tcl/tk8.6/demos/image1.tcl create mode 100644 winvenv/tcl/tk8.6/demos/image2.tcl create mode 100644 winvenv/tcl/tk8.6/demos/images/earth.gif create mode 100644 winvenv/tcl/tk8.6/demos/images/earthmenu.png create mode 100644 winvenv/tcl/tk8.6/demos/images/earthris.gif create mode 100644 winvenv/tcl/tk8.6/demos/images/flagdown.xbm create mode 100644 winvenv/tcl/tk8.6/demos/images/flagup.xbm create mode 100644 winvenv/tcl/tk8.6/demos/images/gray25.xbm create mode 100644 winvenv/tcl/tk8.6/demos/images/letters.xbm create mode 100644 winvenv/tcl/tk8.6/demos/images/noletter.xbm create mode 100644 winvenv/tcl/tk8.6/demos/images/ouster.png create mode 100644 winvenv/tcl/tk8.6/demos/images/pattern.xbm create mode 100644 winvenv/tcl/tk8.6/demos/images/tcllogo.gif create mode 100644 winvenv/tcl/tk8.6/demos/images/teapot.ppm create mode 100644 winvenv/tcl/tk8.6/demos/items.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ixset create mode 100644 winvenv/tcl/tk8.6/demos/knightstour.tcl create mode 100644 winvenv/tcl/tk8.6/demos/label.tcl create mode 100644 winvenv/tcl/tk8.6/demos/labelframe.tcl create mode 100644 winvenv/tcl/tk8.6/demos/license.terms create mode 100644 winvenv/tcl/tk8.6/demos/mclist.tcl create mode 100644 winvenv/tcl/tk8.6/demos/menu.tcl create mode 100644 winvenv/tcl/tk8.6/demos/menubu.tcl create mode 100644 winvenv/tcl/tk8.6/demos/msgbox.tcl create mode 100644 winvenv/tcl/tk8.6/demos/nl.msg create mode 100644 winvenv/tcl/tk8.6/demos/paned1.tcl create mode 100644 winvenv/tcl/tk8.6/demos/paned2.tcl create mode 100644 winvenv/tcl/tk8.6/demos/pendulum.tcl create mode 100644 winvenv/tcl/tk8.6/demos/plot.tcl create mode 100644 winvenv/tcl/tk8.6/demos/puzzle.tcl create mode 100644 winvenv/tcl/tk8.6/demos/radio.tcl create mode 100644 winvenv/tcl/tk8.6/demos/rmt create mode 100644 winvenv/tcl/tk8.6/demos/rolodex create mode 100644 winvenv/tcl/tk8.6/demos/ruler.tcl create mode 100644 winvenv/tcl/tk8.6/demos/sayings.tcl create mode 100644 winvenv/tcl/tk8.6/demos/search.tcl create mode 100644 winvenv/tcl/tk8.6/demos/spin.tcl create mode 100644 winvenv/tcl/tk8.6/demos/square create mode 100644 winvenv/tcl/tk8.6/demos/states.tcl create mode 100644 winvenv/tcl/tk8.6/demos/style.tcl create mode 100644 winvenv/tcl/tk8.6/demos/tclIndex create mode 100644 winvenv/tcl/tk8.6/demos/tcolor create mode 100644 winvenv/tcl/tk8.6/demos/text.tcl create mode 100644 winvenv/tcl/tk8.6/demos/textpeer.tcl create mode 100644 winvenv/tcl/tk8.6/demos/timer create mode 100644 winvenv/tcl/tk8.6/demos/toolbar.tcl create mode 100644 winvenv/tcl/tk8.6/demos/tree.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ttkbut.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ttkmenu.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ttknote.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ttkpane.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ttkprogress.tcl create mode 100644 winvenv/tcl/tk8.6/demos/ttkscale.tcl create mode 100644 winvenv/tcl/tk8.6/demos/twind.tcl create mode 100644 winvenv/tcl/tk8.6/demos/unicodeout.tcl create mode 100644 winvenv/tcl/tk8.6/demos/vscale.tcl create mode 100644 winvenv/tcl/tk8.6/demos/widget create mode 100644 winvenv/tcl/tk8.6/dialog.tcl create mode 100644 winvenv/tcl/tk8.6/entry.tcl create mode 100644 winvenv/tcl/tk8.6/focus.tcl create mode 100644 winvenv/tcl/tk8.6/fontchooser.tcl create mode 100644 winvenv/tcl/tk8.6/iconlist.tcl create mode 100644 winvenv/tcl/tk8.6/icons.tcl create mode 100644 winvenv/tcl/tk8.6/images/README create mode 100644 winvenv/tcl/tk8.6/images/logo.eps create mode 100644 winvenv/tcl/tk8.6/images/logo100.gif create mode 100644 winvenv/tcl/tk8.6/images/logo64.gif create mode 100644 winvenv/tcl/tk8.6/images/logoLarge.gif create mode 100644 winvenv/tcl/tk8.6/images/logoMed.gif create mode 100644 winvenv/tcl/tk8.6/images/pwrdLogo.eps create mode 100644 winvenv/tcl/tk8.6/images/pwrdLogo100.gif create mode 100644 winvenv/tcl/tk8.6/images/pwrdLogo150.gif create mode 100644 winvenv/tcl/tk8.6/images/pwrdLogo175.gif create mode 100644 winvenv/tcl/tk8.6/images/pwrdLogo200.gif create mode 100644 winvenv/tcl/tk8.6/images/pwrdLogo75.gif create mode 100644 winvenv/tcl/tk8.6/images/tai-ku.gif create mode 100644 winvenv/tcl/tk8.6/license.terms create mode 100644 winvenv/tcl/tk8.6/listbox.tcl create mode 100644 winvenv/tcl/tk8.6/megawidget.tcl create mode 100644 winvenv/tcl/tk8.6/menu.tcl create mode 100644 winvenv/tcl/tk8.6/mkpsenc.tcl create mode 100644 winvenv/tcl/tk8.6/msgbox.tcl create mode 100644 winvenv/tcl/tk8.6/msgs/cs.msg create mode 100644 winvenv/tcl/tk8.6/msgs/da.msg create mode 100644 winvenv/tcl/tk8.6/msgs/de.msg create mode 100644 winvenv/tcl/tk8.6/msgs/el.msg create mode 100644 winvenv/tcl/tk8.6/msgs/en.msg create mode 100644 winvenv/tcl/tk8.6/msgs/en_gb.msg create mode 100644 winvenv/tcl/tk8.6/msgs/eo.msg create mode 100644 winvenv/tcl/tk8.6/msgs/es.msg create mode 100644 winvenv/tcl/tk8.6/msgs/fr.msg create mode 100644 winvenv/tcl/tk8.6/msgs/hu.msg create mode 100644 winvenv/tcl/tk8.6/msgs/it.msg create mode 100644 winvenv/tcl/tk8.6/msgs/nl.msg create mode 100644 winvenv/tcl/tk8.6/msgs/pl.msg create mode 100644 winvenv/tcl/tk8.6/msgs/pt.msg create mode 100644 winvenv/tcl/tk8.6/msgs/ru.msg create mode 100644 winvenv/tcl/tk8.6/msgs/sv.msg create mode 100644 winvenv/tcl/tk8.6/obsolete.tcl create mode 100644 winvenv/tcl/tk8.6/optMenu.tcl create mode 100644 winvenv/tcl/tk8.6/palette.tcl create mode 100644 winvenv/tcl/tk8.6/panedwindow.tcl create mode 100644 winvenv/tcl/tk8.6/pkgIndex.tcl create mode 100644 winvenv/tcl/tk8.6/safetk.tcl create mode 100644 winvenv/tcl/tk8.6/scale.tcl create mode 100644 winvenv/tcl/tk8.6/scrlbar.tcl create mode 100644 winvenv/tcl/tk8.6/spinbox.tcl create mode 100644 winvenv/tcl/tk8.6/tclIndex create mode 100644 winvenv/tcl/tk8.6/tearoff.tcl create mode 100644 winvenv/tcl/tk8.6/text.tcl create mode 100644 winvenv/tcl/tk8.6/tk.tcl create mode 100644 winvenv/tcl/tk8.6/tkfbox.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/altTheme.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/aquaTheme.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/button.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/clamTheme.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/classicTheme.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/combobox.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/cursors.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/defaults.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/entry.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/fonts.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/menubutton.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/notebook.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/panedwindow.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/progress.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/scale.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/scrollbar.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/sizegrip.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/spinbox.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/treeview.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/ttk.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/utils.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/vistaTheme.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/winTheme.tcl create mode 100644 winvenv/tcl/tk8.6/ttk/xpTheme.tcl create mode 100644 winvenv/tcl/tk8.6/unsupported.tcl create mode 100644 winvenv/tcl/tk8.6/xmfbox.tcl diff --git a/D3Edit.bat b/D3Edit.bat new file mode 100644 index 0000000..2b622b3 --- /dev/null +++ b/D3Edit.bat @@ -0,0 +1,2 @@ +@echo off +START %cd%\winvenv\Scripts\python D3Edit.py \ No newline at end of file diff --git a/D3Edit.py b/D3Edit.py old mode 100755 new mode 100644 index 15cc841..2ef7175 --- a/D3Edit.py +++ b/D3Edit.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 -import gui import platform -import save_manager from os import getcwd from argparse import ArgumentParser from settings import currency_list def main(): + import gui + import save_manager # parse arguments parser = ArgumentParser(description="A script to encrypt/decrypt and modify Diablo III saves") parser.add_argument("-i", "--in-file", type=str, help="The save file you want to work with") @@ -54,9 +54,14 @@ def main(): if __name__ == "__main__": venv_platforms = ['Linux', 'Darwin'] + running_os = platform.system() # activate Linux/Darwin venvs: - if any(p in platform.system() for p in venv_platforms): + if any(p in running_os for p in venv_platforms): print("activated linux venv") activate_this_file = "{}/venv/bin/activate_this.py".format(getcwd()) exec(open(activate_this_file).read(), dict(__file__=activate_this_file)) + elif running_os == 'Windows': + print("Activating Windows venv") + activate_this_file = "{}\\winvenv\\Scripts\\activate_this.py".format(getcwd()) + exec(open(activate_this_file).read(), dict(__file__=activate_this_file)) main() diff --git a/winvenv/Include/Python-ast.h b/winvenv/Include/Python-ast.h new file mode 100644 index 0000000..8e0f750 --- /dev/null +++ b/winvenv/Include/Python-ast.h @@ -0,0 +1,637 @@ +/* File automatically generated by Parser/asdl_c.py. */ + +#include "asdl.h" + +typedef struct _mod *mod_ty; + +typedef struct _stmt *stmt_ty; + +typedef struct _expr *expr_ty; + +typedef enum _expr_context { Load=1, Store=2, Del=3, AugLoad=4, AugStore=5, + Param=6 } expr_context_ty; + +typedef struct _slice *slice_ty; + +typedef enum _boolop { And=1, Or=2 } boolop_ty; + +typedef enum _operator { Add=1, Sub=2, Mult=3, MatMult=4, Div=5, Mod=6, Pow=7, + LShift=8, RShift=9, BitOr=10, BitXor=11, BitAnd=12, + FloorDiv=13 } operator_ty; + +typedef enum _unaryop { Invert=1, Not=2, UAdd=3, USub=4 } unaryop_ty; + +typedef enum _cmpop { Eq=1, NotEq=2, Lt=3, LtE=4, Gt=5, GtE=6, Is=7, IsNot=8, + In=9, NotIn=10 } cmpop_ty; + +typedef struct _comprehension *comprehension_ty; + +typedef struct _excepthandler *excepthandler_ty; + +typedef struct _arguments *arguments_ty; + +typedef struct _arg *arg_ty; + +typedef struct _keyword *keyword_ty; + +typedef struct _alias *alias_ty; + +typedef struct _withitem *withitem_ty; + + +enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3, + Suite_kind=4}; +struct _mod { + enum _mod_kind kind; + union { + struct { + asdl_seq *body; + } Module; + + struct { + asdl_seq *body; + } Interactive; + + struct { + expr_ty body; + } Expression; + + struct { + asdl_seq *body; + } Suite; + + } v; +}; + +enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3, + Return_kind=4, Delete_kind=5, Assign_kind=6, + AugAssign_kind=7, AnnAssign_kind=8, For_kind=9, + AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13, + AsyncWith_kind=14, Raise_kind=15, Try_kind=16, + Assert_kind=17, Import_kind=18, ImportFrom_kind=19, + Global_kind=20, Nonlocal_kind=21, Expr_kind=22, Pass_kind=23, + Break_kind=24, Continue_kind=25}; +struct _stmt { + enum _stmt_kind kind; + union { + struct { + identifier name; + arguments_ty args; + asdl_seq *body; + asdl_seq *decorator_list; + expr_ty returns; + } FunctionDef; + + struct { + identifier name; + arguments_ty args; + asdl_seq *body; + asdl_seq *decorator_list; + expr_ty returns; + } AsyncFunctionDef; + + struct { + identifier name; + asdl_seq *bases; + asdl_seq *keywords; + asdl_seq *body; + asdl_seq *decorator_list; + } ClassDef; + + struct { + expr_ty value; + } Return; + + struct { + asdl_seq *targets; + } Delete; + + struct { + asdl_seq *targets; + expr_ty value; + } Assign; + + struct { + expr_ty target; + operator_ty op; + expr_ty value; + } AugAssign; + + struct { + expr_ty target; + expr_ty annotation; + expr_ty value; + int simple; + } AnnAssign; + + struct { + expr_ty target; + expr_ty iter; + asdl_seq *body; + asdl_seq *orelse; + } For; + + struct { + expr_ty target; + expr_ty iter; + asdl_seq *body; + asdl_seq *orelse; + } AsyncFor; + + struct { + expr_ty test; + asdl_seq *body; + asdl_seq *orelse; + } While; + + struct { + expr_ty test; + asdl_seq *body; + asdl_seq *orelse; + } If; + + struct { + asdl_seq *items; + asdl_seq *body; + } With; + + struct { + asdl_seq *items; + asdl_seq *body; + } AsyncWith; + + struct { + expr_ty exc; + expr_ty cause; + } Raise; + + struct { + asdl_seq *body; + asdl_seq *handlers; + asdl_seq *orelse; + asdl_seq *finalbody; + } Try; + + struct { + expr_ty test; + expr_ty msg; + } Assert; + + struct { + asdl_seq *names; + } Import; + + struct { + identifier module; + asdl_seq *names; + int level; + } ImportFrom; + + struct { + asdl_seq *names; + } Global; + + struct { + asdl_seq *names; + } Nonlocal; + + struct { + expr_ty value; + } Expr; + + } v; + int lineno; + int col_offset; +}; + +enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4, + IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8, + SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11, + Await_kind=12, Yield_kind=13, YieldFrom_kind=14, + Compare_kind=15, Call_kind=16, Num_kind=17, Str_kind=18, + FormattedValue_kind=19, JoinedStr_kind=20, Bytes_kind=21, + NameConstant_kind=22, Ellipsis_kind=23, Constant_kind=24, + Attribute_kind=25, Subscript_kind=26, Starred_kind=27, + Name_kind=28, List_kind=29, Tuple_kind=30}; +struct _expr { + enum _expr_kind kind; + union { + struct { + boolop_ty op; + asdl_seq *values; + } BoolOp; + + struct { + expr_ty left; + operator_ty op; + expr_ty right; + } BinOp; + + struct { + unaryop_ty op; + expr_ty operand; + } UnaryOp; + + struct { + arguments_ty args; + expr_ty body; + } Lambda; + + struct { + expr_ty test; + expr_ty body; + expr_ty orelse; + } IfExp; + + struct { + asdl_seq *keys; + asdl_seq *values; + } Dict; + + struct { + asdl_seq *elts; + } Set; + + struct { + expr_ty elt; + asdl_seq *generators; + } ListComp; + + struct { + expr_ty elt; + asdl_seq *generators; + } SetComp; + + struct { + expr_ty key; + expr_ty value; + asdl_seq *generators; + } DictComp; + + struct { + expr_ty elt; + asdl_seq *generators; + } GeneratorExp; + + struct { + expr_ty value; + } Await; + + struct { + expr_ty value; + } Yield; + + struct { + expr_ty value; + } YieldFrom; + + struct { + expr_ty left; + asdl_int_seq *ops; + asdl_seq *comparators; + } Compare; + + struct { + expr_ty func; + asdl_seq *args; + asdl_seq *keywords; + } Call; + + struct { + object n; + } Num; + + struct { + string s; + } Str; + + struct { + expr_ty value; + int conversion; + expr_ty format_spec; + } FormattedValue; + + struct { + asdl_seq *values; + } JoinedStr; + + struct { + bytes s; + } Bytes; + + struct { + singleton value; + } NameConstant; + + struct { + constant value; + } Constant; + + struct { + expr_ty value; + identifier attr; + expr_context_ty ctx; + } Attribute; + + struct { + expr_ty value; + slice_ty slice; + expr_context_ty ctx; + } Subscript; + + struct { + expr_ty value; + expr_context_ty ctx; + } Starred; + + struct { + identifier id; + expr_context_ty ctx; + } Name; + + struct { + asdl_seq *elts; + expr_context_ty ctx; + } List; + + struct { + asdl_seq *elts; + expr_context_ty ctx; + } Tuple; + + } v; + int lineno; + int col_offset; +}; + +enum _slice_kind {Slice_kind=1, ExtSlice_kind=2, Index_kind=3}; +struct _slice { + enum _slice_kind kind; + union { + struct { + expr_ty lower; + expr_ty upper; + expr_ty step; + } Slice; + + struct { + asdl_seq *dims; + } ExtSlice; + + struct { + expr_ty value; + } Index; + + } v; +}; + +struct _comprehension { + expr_ty target; + expr_ty iter; + asdl_seq *ifs; + int is_async; +}; + +enum _excepthandler_kind {ExceptHandler_kind=1}; +struct _excepthandler { + enum _excepthandler_kind kind; + union { + struct { + expr_ty type; + identifier name; + asdl_seq *body; + } ExceptHandler; + + } v; + int lineno; + int col_offset; +}; + +struct _arguments { + asdl_seq *args; + arg_ty vararg; + asdl_seq *kwonlyargs; + asdl_seq *kw_defaults; + arg_ty kwarg; + asdl_seq *defaults; +}; + +struct _arg { + identifier arg; + expr_ty annotation; + int lineno; + int col_offset; +}; + +struct _keyword { + identifier arg; + expr_ty value; +}; + +struct _alias { + identifier name; + identifier asname; +}; + +struct _withitem { + expr_ty context_expr; + expr_ty optional_vars; +}; + + +#define Module(a0, a1) _Py_Module(a0, a1) +mod_ty _Py_Module(asdl_seq * body, PyArena *arena); +#define Interactive(a0, a1) _Py_Interactive(a0, a1) +mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena); +#define Expression(a0, a1) _Py_Expression(a0, a1) +mod_ty _Py_Expression(expr_ty body, PyArena *arena); +#define Suite(a0, a1) _Py_Suite(a0, a1) +mod_ty _Py_Suite(asdl_seq * body, PyArena *arena); +#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) +stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, + asdl_seq * decorator_list, expr_ty returns, int lineno, + int col_offset, PyArena *arena); +#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) +stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * + body, asdl_seq * decorator_list, expr_ty returns, + int lineno, int col_offset, PyArena *arena); +#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) +stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, + asdl_seq * body, asdl_seq * decorator_list, int lineno, + int col_offset, PyArena *arena); +#define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3) +stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena); +#define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3) +stmt_ty _Py_Delete(asdl_seq * targets, int lineno, int col_offset, PyArena + *arena); +#define Assign(a0, a1, a2, a3, a4) _Py_Assign(a0, a1, a2, a3, a4) +stmt_ty _Py_Assign(asdl_seq * targets, expr_ty value, int lineno, int + col_offset, PyArena *arena); +#define AugAssign(a0, a1, a2, a3, a4, a5) _Py_AugAssign(a0, a1, a2, a3, a4, a5) +stmt_ty _Py_AugAssign(expr_ty target, operator_ty op, expr_ty value, int + lineno, int col_offset, PyArena *arena); +#define AnnAssign(a0, a1, a2, a3, a4, a5, a6) _Py_AnnAssign(a0, a1, a2, a3, a4, a5, a6) +stmt_ty _Py_AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int + simple, int lineno, int col_offset, PyArena *arena); +#define For(a0, a1, a2, a3, a4, a5, a6) _Py_For(a0, a1, a2, a3, a4, a5, a6) +stmt_ty _Py_For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * + orelse, int lineno, int col_offset, PyArena *arena); +#define AsyncFor(a0, a1, a2, a3, a4, a5, a6) _Py_AsyncFor(a0, a1, a2, a3, a4, a5, a6) +stmt_ty _Py_AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * + orelse, int lineno, int col_offset, PyArena *arena); +#define While(a0, a1, a2, a3, a4, a5) _Py_While(a0, a1, a2, a3, a4, a5) +stmt_ty _Py_While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, + int col_offset, PyArena *arena); +#define If(a0, a1, a2, a3, a4, a5) _Py_If(a0, a1, a2, a3, a4, a5) +stmt_ty _Py_If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, + int col_offset, PyArena *arena); +#define With(a0, a1, a2, a3, a4) _Py_With(a0, a1, a2, a3, a4) +stmt_ty _Py_With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, + PyArena *arena); +#define AsyncWith(a0, a1, a2, a3, a4) _Py_AsyncWith(a0, a1, a2, a3, a4) +stmt_ty _Py_AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int + col_offset, PyArena *arena); +#define Raise(a0, a1, a2, a3, a4) _Py_Raise(a0, a1, a2, a3, a4) +stmt_ty _Py_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, + PyArena *arena); +#define Try(a0, a1, a2, a3, a4, a5, a6) _Py_Try(a0, a1, a2, a3, a4, a5, a6) +stmt_ty _Py_Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, + asdl_seq * finalbody, int lineno, int col_offset, PyArena + *arena); +#define Assert(a0, a1, a2, a3, a4) _Py_Assert(a0, a1, a2, a3, a4) +stmt_ty _Py_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, + PyArena *arena); +#define Import(a0, a1, a2, a3) _Py_Import(a0, a1, a2, a3) +stmt_ty _Py_Import(asdl_seq * names, int lineno, int col_offset, PyArena + *arena); +#define ImportFrom(a0, a1, a2, a3, a4, a5) _Py_ImportFrom(a0, a1, a2, a3, a4, a5) +stmt_ty _Py_ImportFrom(identifier module, asdl_seq * names, int level, int + lineno, int col_offset, PyArena *arena); +#define Global(a0, a1, a2, a3) _Py_Global(a0, a1, a2, a3) +stmt_ty _Py_Global(asdl_seq * names, int lineno, int col_offset, PyArena + *arena); +#define Nonlocal(a0, a1, a2, a3) _Py_Nonlocal(a0, a1, a2, a3) +stmt_ty _Py_Nonlocal(asdl_seq * names, int lineno, int col_offset, PyArena + *arena); +#define Expr(a0, a1, a2, a3) _Py_Expr(a0, a1, a2, a3) +stmt_ty _Py_Expr(expr_ty value, int lineno, int col_offset, PyArena *arena); +#define Pass(a0, a1, a2) _Py_Pass(a0, a1, a2) +stmt_ty _Py_Pass(int lineno, int col_offset, PyArena *arena); +#define Break(a0, a1, a2) _Py_Break(a0, a1, a2) +stmt_ty _Py_Break(int lineno, int col_offset, PyArena *arena); +#define Continue(a0, a1, a2) _Py_Continue(a0, a1, a2) +stmt_ty _Py_Continue(int lineno, int col_offset, PyArena *arena); +#define BoolOp(a0, a1, a2, a3, a4) _Py_BoolOp(a0, a1, a2, a3, a4) +expr_ty _Py_BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, + PyArena *arena); +#define BinOp(a0, a1, a2, a3, a4, a5) _Py_BinOp(a0, a1, a2, a3, a4, a5) +expr_ty _Py_BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int + col_offset, PyArena *arena); +#define UnaryOp(a0, a1, a2, a3, a4) _Py_UnaryOp(a0, a1, a2, a3, a4) +expr_ty _Py_UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, + PyArena *arena); +#define Lambda(a0, a1, a2, a3, a4) _Py_Lambda(a0, a1, a2, a3, a4) +expr_ty _Py_Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, + PyArena *arena); +#define IfExp(a0, a1, a2, a3, a4, a5) _Py_IfExp(a0, a1, a2, a3, a4, a5) +expr_ty _Py_IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int + col_offset, PyArena *arena); +#define Dict(a0, a1, a2, a3, a4) _Py_Dict(a0, a1, a2, a3, a4) +expr_ty _Py_Dict(asdl_seq * keys, asdl_seq * values, int lineno, int + col_offset, PyArena *arena); +#define Set(a0, a1, a2, a3) _Py_Set(a0, a1, a2, a3) +expr_ty _Py_Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena); +#define ListComp(a0, a1, a2, a3, a4) _Py_ListComp(a0, a1, a2, a3, a4) +expr_ty _Py_ListComp(expr_ty elt, asdl_seq * generators, int lineno, int + col_offset, PyArena *arena); +#define SetComp(a0, a1, a2, a3, a4) _Py_SetComp(a0, a1, a2, a3, a4) +expr_ty _Py_SetComp(expr_ty elt, asdl_seq * generators, int lineno, int + col_offset, PyArena *arena); +#define DictComp(a0, a1, a2, a3, a4, a5) _Py_DictComp(a0, a1, a2, a3, a4, a5) +expr_ty _Py_DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int + lineno, int col_offset, PyArena *arena); +#define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4) +expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int + col_offset, PyArena *arena); +#define Await(a0, a1, a2, a3) _Py_Await(a0, a1, a2, a3) +expr_ty _Py_Await(expr_ty value, int lineno, int col_offset, PyArena *arena); +#define Yield(a0, a1, a2, a3) _Py_Yield(a0, a1, a2, a3) +expr_ty _Py_Yield(expr_ty value, int lineno, int col_offset, PyArena *arena); +#define YieldFrom(a0, a1, a2, a3) _Py_YieldFrom(a0, a1, a2, a3) +expr_ty _Py_YieldFrom(expr_ty value, int lineno, int col_offset, PyArena + *arena); +#define Compare(a0, a1, a2, a3, a4, a5) _Py_Compare(a0, a1, a2, a3, a4, a5) +expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, + int lineno, int col_offset, PyArena *arena); +#define Call(a0, a1, a2, a3, a4, a5) _Py_Call(a0, a1, a2, a3, a4, a5) +expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int + lineno, int col_offset, PyArena *arena); +#define Num(a0, a1, a2, a3) _Py_Num(a0, a1, a2, a3) +expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena); +#define Str(a0, a1, a2, a3) _Py_Str(a0, a1, a2, a3) +expr_ty _Py_Str(string s, int lineno, int col_offset, PyArena *arena); +#define FormattedValue(a0, a1, a2, a3, a4, a5) _Py_FormattedValue(a0, a1, a2, a3, a4, a5) +expr_ty _Py_FormattedValue(expr_ty value, int conversion, expr_ty format_spec, + int lineno, int col_offset, PyArena *arena); +#define JoinedStr(a0, a1, a2, a3) _Py_JoinedStr(a0, a1, a2, a3) +expr_ty _Py_JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena + *arena); +#define Bytes(a0, a1, a2, a3) _Py_Bytes(a0, a1, a2, a3) +expr_ty _Py_Bytes(bytes s, int lineno, int col_offset, PyArena *arena); +#define NameConstant(a0, a1, a2, a3) _Py_NameConstant(a0, a1, a2, a3) +expr_ty _Py_NameConstant(singleton value, int lineno, int col_offset, PyArena + *arena); +#define Ellipsis(a0, a1, a2) _Py_Ellipsis(a0, a1, a2) +expr_ty _Py_Ellipsis(int lineno, int col_offset, PyArena *arena); +#define Constant(a0, a1, a2, a3) _Py_Constant(a0, a1, a2, a3) +expr_ty _Py_Constant(constant value, int lineno, int col_offset, PyArena + *arena); +#define Attribute(a0, a1, a2, a3, a4, a5) _Py_Attribute(a0, a1, a2, a3, a4, a5) +expr_ty _Py_Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int + lineno, int col_offset, PyArena *arena); +#define Subscript(a0, a1, a2, a3, a4, a5) _Py_Subscript(a0, a1, a2, a3, a4, a5) +expr_ty _Py_Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int + lineno, int col_offset, PyArena *arena); +#define Starred(a0, a1, a2, a3, a4) _Py_Starred(a0, a1, a2, a3, a4) +expr_ty _Py_Starred(expr_ty value, expr_context_ty ctx, int lineno, int + col_offset, PyArena *arena); +#define Name(a0, a1, a2, a3, a4) _Py_Name(a0, a1, a2, a3, a4) +expr_ty _Py_Name(identifier id, expr_context_ty ctx, int lineno, int + col_offset, PyArena *arena); +#define List(a0, a1, a2, a3, a4) _Py_List(a0, a1, a2, a3, a4) +expr_ty _Py_List(asdl_seq * elts, expr_context_ty ctx, int lineno, int + col_offset, PyArena *arena); +#define Tuple(a0, a1, a2, a3, a4) _Py_Tuple(a0, a1, a2, a3, a4) +expr_ty _Py_Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int + col_offset, PyArena *arena); +#define Slice(a0, a1, a2, a3) _Py_Slice(a0, a1, a2, a3) +slice_ty _Py_Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena *arena); +#define ExtSlice(a0, a1) _Py_ExtSlice(a0, a1) +slice_ty _Py_ExtSlice(asdl_seq * dims, PyArena *arena); +#define Index(a0, a1) _Py_Index(a0, a1) +slice_ty _Py_Index(expr_ty value, PyArena *arena); +#define comprehension(a0, a1, a2, a3, a4) _Py_comprehension(a0, a1, a2, a3, a4) +comprehension_ty _Py_comprehension(expr_ty target, expr_ty iter, asdl_seq * + ifs, int is_async, PyArena *arena); +#define ExceptHandler(a0, a1, a2, a3, a4, a5) _Py_ExceptHandler(a0, a1, a2, a3, a4, a5) +excepthandler_ty _Py_ExceptHandler(expr_ty type, identifier name, asdl_seq * + body, int lineno, int col_offset, PyArena + *arena); +#define arguments(a0, a1, a2, a3, a4, a5, a6) _Py_arguments(a0, a1, a2, a3, a4, a5, a6) +arguments_ty _Py_arguments(asdl_seq * args, arg_ty vararg, asdl_seq * + kwonlyargs, asdl_seq * kw_defaults, arg_ty kwarg, + asdl_seq * defaults, PyArena *arena); +#define arg(a0, a1, a2, a3, a4) _Py_arg(a0, a1, a2, a3, a4) +arg_ty _Py_arg(identifier arg, expr_ty annotation, int lineno, int col_offset, + PyArena *arena); +#define keyword(a0, a1, a2) _Py_keyword(a0, a1, a2) +keyword_ty _Py_keyword(identifier arg, expr_ty value, PyArena *arena); +#define alias(a0, a1, a2) _Py_alias(a0, a1, a2) +alias_ty _Py_alias(identifier name, identifier asname, PyArena *arena); +#define withitem(a0, a1, a2) _Py_withitem(a0, a1, a2) +withitem_ty _Py_withitem(expr_ty context_expr, expr_ty optional_vars, PyArena + *arena); + +PyObject* PyAST_mod2obj(mod_ty t); +mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode); +int PyAST_Check(PyObject* obj); diff --git a/winvenv/Include/Python.h b/winvenv/Include/Python.h new file mode 100644 index 0000000..1feb153 --- /dev/null +++ b/winvenv/Include/Python.h @@ -0,0 +1,140 @@ +#ifndef Py_PYTHON_H +#define Py_PYTHON_H +/* Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { */ + +/* Include nearly all Python header files */ + +#include "patchlevel.h" +#include "pyconfig.h" +#include "pymacconfig.h" + +#include + +#ifndef UCHAR_MAX +#error "Something's broken. UCHAR_MAX should be defined in limits.h." +#endif + +#if UCHAR_MAX != 255 +#error "Python's source code assumes C's unsigned char is an 8-bit type." +#endif + +#if defined(__sgi) && !defined(_SGI_MP_SOURCE) +#define _SGI_MP_SOURCE +#endif + +#include +#ifndef NULL +# error "Python.h requires that stdio.h define NULL." +#endif + +#include +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_CRYPT_H +#include +#endif + +/* For size_t? */ +#ifdef HAVE_STDDEF_H +#include +#endif + +/* CAUTION: Build setups should ensure that NDEBUG is defined on the + * compiler command line when building Python in release mode; else + * assert() calls won't be removed. + */ +#include + +#include "pyport.h" +#include "pymacro.h" + +#include "pyatomic.h" + +/* Debug-mode build with pymalloc implies PYMALLOC_DEBUG. + * PYMALLOC_DEBUG is in error if pymalloc is not in use. + */ +#if defined(Py_DEBUG) && defined(WITH_PYMALLOC) && !defined(PYMALLOC_DEBUG) +#define PYMALLOC_DEBUG +#endif +#if defined(PYMALLOC_DEBUG) && !defined(WITH_PYMALLOC) +#error "PYMALLOC_DEBUG requires WITH_PYMALLOC" +#endif +#include "pymath.h" +#include "pytime.h" +#include "pymem.h" + +#include "object.h" +#include "objimpl.h" +#include "typeslots.h" +#include "pyhash.h" + +#include "pydebug.h" + +#include "bytearrayobject.h" +#include "bytesobject.h" +#include "unicodeobject.h" +#include "longobject.h" +#include "longintrepr.h" +#include "boolobject.h" +#include "floatobject.h" +#include "complexobject.h" +#include "rangeobject.h" +#include "memoryobject.h" +#include "tupleobject.h" +#include "listobject.h" +#include "dictobject.h" +#include "odictobject.h" +#include "enumobject.h" +#include "setobject.h" +#include "methodobject.h" +#include "moduleobject.h" +#include "funcobject.h" +#include "classobject.h" +#include "fileobject.h" +#include "pycapsule.h" +#include "traceback.h" +#include "sliceobject.h" +#include "cellobject.h" +#include "iterobject.h" +#include "genobject.h" +#include "descrobject.h" +#include "warnings.h" +#include "weakrefobject.h" +#include "structseq.h" +#include "namespaceobject.h" + +#include "codecs.h" +#include "pyerrors.h" + +#include "pystate.h" +#include "context.h" + +#include "pyarena.h" +#include "modsupport.h" +#include "compile.h" +#include "pythonrun.h" +#include "pylifecycle.h" +#include "ceval.h" +#include "sysmodule.h" +#include "osmodule.h" +#include "intrcheck.h" +#include "import.h" + +#include "abstract.h" +#include "bltinmodule.h" + +#include "eval.h" + +#include "pyctype.h" +#include "pystrtod.h" +#include "pystrcmp.h" +#include "dtoa.h" +#include "fileutils.h" +#include "pyfpe.h" + +#endif /* !Py_PYTHON_H */ diff --git a/winvenv/Include/abstract.h b/winvenv/Include/abstract.h new file mode 100644 index 0000000..4088f75 --- /dev/null +++ b/winvenv/Include/abstract.h @@ -0,0 +1,1109 @@ +/* Abstract Object Interface (many thanks to Jim Fulton) */ + +#ifndef Py_ABSTRACTOBJECT_H +#define Py_ABSTRACTOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* === Object Protocol ================================================== */ + +/* Implemented elsewhere: + + int PyObject_Print(PyObject *o, FILE *fp, int flags); + + Print an object 'o' on file 'fp'. Returns -1 on error. The flags argument + is used to enable certain printing options. The only option currently + supported is Py_Print_RAW. + + (What should be said about Py_Print_RAW?). */ + + +/* Implemented elsewhere: + + int PyObject_HasAttrString(PyObject *o, const char *attr_name); + + Returns 1 if object 'o' has the attribute attr_name, and 0 otherwise. + + This is equivalent to the Python expression: hasattr(o,attr_name). + + This function always succeeds. */ + + +/* Implemented elsewhere: + + PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name); + + Retrieve an attributed named attr_name form object o. + Returns the attribute value on success, or NULL on failure. + + This is the equivalent of the Python expression: o.attr_name. */ + + +/* Implemented elsewhere: + + int PyObject_HasAttr(PyObject *o, PyObject *attr_name); + + Returns 1 if o has the attribute attr_name, and 0 otherwise. + + This is equivalent to the Python expression: hasattr(o,attr_name). + + This function always succeeds. */ + +/* Implemented elsewhere: + + PyObject* PyObject_GetAttr(PyObject *o, PyObject *attr_name); + + Retrieve an attributed named 'attr_name' form object 'o'. + Returns the attribute value on success, or NULL on failure. + + This is the equivalent of the Python expression: o.attr_name. */ + + +/* Implemented elsewhere: + + int PyObject_SetAttrString(PyObject *o, const char *attr_name, PyObject *v); + + Set the value of the attribute named attr_name, for object 'o', + to the value 'v'. Raise an exception and return -1 on failure; return 0 on + success. + + This is the equivalent of the Python statement o.attr_name=v. */ + + +/* Implemented elsewhere: + + int PyObject_SetAttr(PyObject *o, PyObject *attr_name, PyObject *v); + + Set the value of the attribute named attr_name, for object 'o', to the value + 'v'. an exception and return -1 on failure; return 0 on success. + + This is the equivalent of the Python statement o.attr_name=v. */ + +/* Implemented as a macro: + + int PyObject_DelAttrString(PyObject *o, const char *attr_name); + + Delete attribute named attr_name, for object o. Returns + -1 on failure. + + This is the equivalent of the Python statement: del o.attr_name. */ +#define PyObject_DelAttrString(O,A) PyObject_SetAttrString((O),(A), NULL) + + +/* Implemented as a macro: + + int PyObject_DelAttr(PyObject *o, PyObject *attr_name); + + Delete attribute named attr_name, for object o. Returns -1 + on failure. This is the equivalent of the Python + statement: del o.attr_name. */ +#define PyObject_DelAttr(O,A) PyObject_SetAttr((O),(A), NULL) + + +/* Implemented elsewhere: + + PyObject *PyObject_Repr(PyObject *o); + + Compute the string representation of object 'o'. Returns the + string representation on success, NULL on failure. + + This is the equivalent of the Python expression: repr(o). + + Called by the repr() built-in function. */ + + +/* Implemented elsewhere: + + PyObject *PyObject_Str(PyObject *o); + + Compute the string representation of object, o. Returns the + string representation on success, NULL on failure. + + This is the equivalent of the Python expression: str(o). + + Called by the str() and print() built-in functions. */ + + +/* Declared elsewhere + + PyAPI_FUNC(int) PyCallable_Check(PyObject *o); + + Determine if the object, o, is callable. Return 1 if the object is callable + and 0 otherwise. + + This function always succeeds. */ + + +#ifdef PY_SSIZE_T_CLEAN +# define PyObject_CallFunction _PyObject_CallFunction_SizeT +# define PyObject_CallMethod _PyObject_CallMethod_SizeT +# ifndef Py_LIMITED_API +# define _PyObject_CallMethodId _PyObject_CallMethodId_SizeT +# endif /* !Py_LIMITED_API */ +#endif + + +/* Call a callable Python object 'callable' with arguments given by the + tuple 'args' and keywords arguments given by the dictionary 'kwargs'. + + 'args' must not be *NULL*, use an empty tuple if no arguments are + needed. If no named arguments are needed, 'kwargs' can be NULL. + + This is the equivalent of the Python expression: + callable(*args, **kwargs). */ +PyAPI_FUNC(PyObject *) PyObject_Call(PyObject *callable, + PyObject *args, PyObject *kwargs); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) _PyStack_AsTuple( + PyObject *const *stack, + Py_ssize_t nargs); + +PyAPI_FUNC(PyObject*) _PyStack_AsTupleSlice( + PyObject *const *stack, + Py_ssize_t nargs, + Py_ssize_t start, + Py_ssize_t end); + +/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple) + format to a Python dictionary ("kwargs" dict). + + The type of kwnames keys is not checked. The final function getting + arguments is responsible to check if all keys are strings, for example using + PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments(). + + Duplicate keys are merged using the last value. If duplicate keys must raise + an exception, the caller is responsible to implement an explicit keys on + kwnames. */ +PyAPI_FUNC(PyObject *) _PyStack_AsDict( + PyObject *const *values, + PyObject *kwnames); + +/* Convert (args, nargs, kwargs: dict) into a (stack, nargs, kwnames: tuple). + + Return 0 on success, raise an exception and return -1 on error. + + Write the new stack into *p_stack. If *p_stack is differen than args, it + must be released by PyMem_Free(). + + The stack uses borrowed references. + + The type of keyword keys is not checked, these checks should be done + later (ex: _PyArg_ParseStackAndKeywords). */ +PyAPI_FUNC(int) _PyStack_UnpackDict( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwargs, + PyObject *const **p_stack, + PyObject **p_kwnames); + +/* Suggested size (number of positional arguments) for arrays of PyObject* + allocated on a C stack to avoid allocating memory on the heap memory. Such + array is used to pass positional arguments to call functions of the + _PyObject_FastCall() family. + + The size is chosen to not abuse the C stack and so limit the risk of stack + overflow. The size is also chosen to allow using the small stack for most + function calls of the Python standard library. On 64-bit CPU, it allocates + 40 bytes on the stack. */ +#define _PY_FASTCALL_SMALL_STACK 5 + +/* Return 1 if callable supports FASTCALL calling convention for positional + arguments: see _PyObject_FastCallDict() and _PyObject_FastCallKeywords() */ +PyAPI_FUNC(int) _PyObject_HasFastCall(PyObject *callable); + +/* Call the callable object 'callable' with the "fast call" calling convention: + args is a C array for positional arguments (nargs is the number of + positional arguments), kwargs is a dictionary for keyword arguments. + + If nargs is equal to zero, args can be NULL. kwargs can be NULL. + nargs must be greater or equal to zero. + + Return the result on success. Raise an exception on return NULL on + error. */ +PyAPI_FUNC(PyObject *) _PyObject_FastCallDict( + PyObject *callable, + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwargs); + +/* Call the callable object 'callable' with the "fast call" calling convention: + args is a C array for positional arguments followed by values of + keyword arguments. Keys of keyword arguments are stored as a tuple + of strings in kwnames. nargs is the number of positional parameters at + the beginning of stack. The size of kwnames gives the number of keyword + values in the stack after positional arguments. + + kwnames must only contains str strings, no subclass, and all keys must + be unique. + + If nargs is equal to zero and there is no keyword argument (kwnames is + NULL or its size is zero), args can be NULL. + + Return the result on success. Raise an exception and return NULL on + error. */ +PyAPI_FUNC(PyObject *) _PyObject_FastCallKeywords( + PyObject *callable, + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames); + +#define _PyObject_FastCall(func, args, nargs) \ + _PyObject_FastCallDict((func), (args), (nargs), NULL) + +#define _PyObject_CallNoArg(func) \ + _PyObject_FastCallDict((func), NULL, 0, NULL) + +PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend( + PyObject *callable, + PyObject *obj, + PyObject *args, + PyObject *kwargs); + +PyAPI_FUNC(PyObject *) _PyObject_FastCall_Prepend( + PyObject *callable, + PyObject *obj, + PyObject *const *args, + Py_ssize_t nargs); + +PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *callable, + PyObject *result, + const char *where); +#endif /* Py_LIMITED_API */ + + +/* Call a callable Python object 'callable', with arguments given by the + tuple 'args'. If no arguments are needed, then 'args' can be *NULL*. + + Returns the result of the call on success, or *NULL* on failure. + + This is the equivalent of the Python expression: + callable(*args). */ +PyAPI_FUNC(PyObject *) PyObject_CallObject(PyObject *callable, + PyObject *args); + +/* Call a callable Python object, callable, with a variable number of C + arguments. The C arguments are described using a mkvalue-style format + string. + + The format may be NULL, indicating that no arguments are provided. + + Returns the result of the call on success, or NULL on failure. + + This is the equivalent of the Python expression: + callable(arg1, arg2, ...). */ +PyAPI_FUNC(PyObject *) PyObject_CallFunction(PyObject *callable, + const char *format, ...); + +/* Call the method named 'name' of object 'obj' with a variable number of + C arguments. The C arguments are described by a mkvalue format string. + + The format can be NULL, indicating that no arguments are provided. + + Returns the result of the call on success, or NULL on failure. + + This is the equivalent of the Python expression: + obj.name(arg1, arg2, ...). */ +PyAPI_FUNC(PyObject *) PyObject_CallMethod(PyObject *obj, + const char *name, + const char *format, ...); + +#ifndef Py_LIMITED_API +/* Like PyObject_CallMethod(), but expect a _Py_Identifier* + as the method name. */ +PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj, + _Py_Identifier *name, + const char *format, ...); +#endif /* !Py_LIMITED_API */ + +PyAPI_FUNC(PyObject *) _PyObject_CallFunction_SizeT(PyObject *callable, + const char *format, + ...); + +PyAPI_FUNC(PyObject *) _PyObject_CallMethod_SizeT(PyObject *obj, + const char *name, + const char *format, + ...); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyObject_CallMethodId_SizeT(PyObject *obj, + _Py_Identifier *name, + const char *format, + ...); +#endif /* !Py_LIMITED_API */ + +/* Call a callable Python object 'callable' with a variable number of C + arguments. The C arguments are provided as PyObject* values, terminated + by a NULL. + + Returns the result of the call on success, or NULL on failure. + + This is the equivalent of the Python expression: + callable(arg1, arg2, ...). */ +PyAPI_FUNC(PyObject *) PyObject_CallFunctionObjArgs(PyObject *callable, + ...); + +/* Call the method named 'name' of object 'obj' with a variable number of + C arguments. The C arguments are provided as PyObject* values, terminated + by NULL. + + Returns the result of the call on success, or NULL on failure. + + This is the equivalent of the Python expression: obj.name(*args). */ + +PyAPI_FUNC(PyObject *) PyObject_CallMethodObjArgs( + PyObject *obj, + PyObject *name, + ...); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyObject_CallMethodIdObjArgs( + PyObject *obj, + struct _Py_Identifier *name, + ...); +#endif /* !Py_LIMITED_API */ + + +/* Implemented elsewhere: + + Py_hash_t PyObject_Hash(PyObject *o); + + Compute and return the hash, hash_value, of an object, o. On + failure, return -1. + + This is the equivalent of the Python expression: hash(o). */ + + +/* Implemented elsewhere: + + int PyObject_IsTrue(PyObject *o); + + Returns 1 if the object, o, is considered to be true, 0 if o is + considered to be false and -1 on failure. + + This is equivalent to the Python expression: not not o. */ + + +/* Implemented elsewhere: + + int PyObject_Not(PyObject *o); + + Returns 0 if the object, o, is considered to be true, 1 if o is + considered to be false and -1 on failure. + + This is equivalent to the Python expression: not o. */ + + +/* Get the type of an object. + + On success, returns a type object corresponding to the object type of object + 'o'. On failure, returns NULL. + + This is equivalent to the Python expression: type(o) */ +PyAPI_FUNC(PyObject *) PyObject_Type(PyObject *o); + + +/* Return the size of object 'o'. If the object 'o' provides both sequence and + mapping protocols, the sequence size is returned. + + On error, -1 is returned. + + This is the equivalent to the Python expression: len(o) */ +PyAPI_FUNC(Py_ssize_t) PyObject_Size(PyObject *o); + + +/* For DLL compatibility */ +#undef PyObject_Length +PyAPI_FUNC(Py_ssize_t) PyObject_Length(PyObject *o); +#define PyObject_Length PyObject_Size + + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o); + +/* Guess the size of object 'o' using len(o) or o.__length_hint__(). + If neither of those return a non-negative value, then return the default + value. If one of the calls fails, this function returns -1. */ +PyAPI_FUNC(Py_ssize_t) PyObject_LengthHint(PyObject *o, Py_ssize_t); +#endif + +/* Return element of 'o' corresponding to the object 'key'. Return NULL + on failure. + + This is the equivalent of the Python expression: o[key] */ +PyAPI_FUNC(PyObject *) PyObject_GetItem(PyObject *o, PyObject *key); + + +/* Map the object 'key' to the value 'v' into 'o'. + + Raise an exception and return -1 on failure; return 0 on success. + + This is the equivalent of the Python statement: o[key]=v. */ +PyAPI_FUNC(int) PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v); + +/* Remove the mapping for the string 'key' from the object 'o'. + Returns -1 on failure. + + This is equivalent to the Python statement: del o[key]. */ +PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *key); + +/* Delete the mapping for the object 'key' from the object 'o'. + Returns -1 on failure. + + This is the equivalent of the Python statement: del o[key]. */ +PyAPI_FUNC(int) PyObject_DelItem(PyObject *o, PyObject *key); + + +/* === Old Buffer API ============================================ */ + +/* FIXME: usage of these should all be replaced in Python itself + but for backwards compatibility we will implement them. + Their usage without a corresponding "unlock" mechanism + may create issues (but they would already be there). */ + +/* Takes an arbitrary object which must support the (character, single segment) + buffer interface and returns a pointer to a read-only memory location + useable as character based input for subsequent processing. + + Return 0 on success. buffer and buffer_len are only set in case no error + occurs. Otherwise, -1 is returned and an exception set. */ +PyAPI_FUNC(int) PyObject_AsCharBuffer(PyObject *obj, + const char **buffer, + Py_ssize_t *buffer_len) + Py_DEPRECATED(3.0); + +/* Checks whether an arbitrary object supports the (character, single segment) + buffer interface. + + Returns 1 on success, 0 on failure. */ +PyAPI_FUNC(int) PyObject_CheckReadBuffer(PyObject *obj) + Py_DEPRECATED(3.0); + +/* Same as PyObject_AsCharBuffer() except that this API expects (readable, + single segment) buffer interface and returns a pointer to a read-only memory + location which can contain arbitrary data. + + 0 is returned on success. buffer and buffer_len are only set in case no + error occurs. Otherwise, -1 is returned and an exception set. */ +PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *obj, + const void **buffer, + Py_ssize_t *buffer_len) + Py_DEPRECATED(3.0); + +/* Takes an arbitrary object which must support the (writable, single segment) + buffer interface and returns a pointer to a writable memory location in + buffer of size 'buffer_len'. + + Return 0 on success. buffer and buffer_len are only set in case no error + occurs. Otherwise, -1 is returned and an exception set. */ +PyAPI_FUNC(int) PyObject_AsWriteBuffer(PyObject *obj, + void **buffer, + Py_ssize_t *buffer_len) + Py_DEPRECATED(3.0); + + +/* === New Buffer API ============================================ */ + +#ifndef Py_LIMITED_API + +/* Return 1 if the getbuffer function is available, otherwise return 0. */ +#define PyObject_CheckBuffer(obj) \ + (((obj)->ob_type->tp_as_buffer != NULL) && \ + ((obj)->ob_type->tp_as_buffer->bf_getbuffer != NULL)) + +/* This is a C-API version of the getbuffer function call. It checks + to make sure object has the required function pointer and issues the + call. + + Returns -1 and raises an error on failure and returns 0 on success. */ +PyAPI_FUNC(int) PyObject_GetBuffer(PyObject *obj, Py_buffer *view, + int flags); + +/* Get the memory area pointed to by the indices for the buffer given. + Note that view->ndim is the assumed size of indices. */ +PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); + +/* Return the implied itemsize of the data-format area from a + struct-style description. */ +PyAPI_FUNC(int) PyBuffer_SizeFromFormat(const char *); + +/* Implementation in memoryobject.c */ +PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, + Py_ssize_t len, char order); + +PyAPI_FUNC(int) PyBuffer_FromContiguous(Py_buffer *view, void *buf, + Py_ssize_t len, char order); + +/* Copy len bytes of data from the contiguous chunk of memory + pointed to by buf into the buffer exported by obj. Return + 0 on success and return -1 and raise a PyBuffer_Error on + error (i.e. the object does not have a buffer interface or + it is not working). + + If fort is 'F', then if the object is multi-dimensional, + then the data will be copied into the array in + Fortran-style (first dimension varies the fastest). If + fort is 'C', then the data will be copied into the array + in C-style (last dimension varies the fastest). If fort + is 'A', then it does not matter and the copy will be made + in whatever way is more efficient. */ +PyAPI_FUNC(int) PyObject_CopyData(PyObject *dest, PyObject *src); + +/* Copy the data from the src buffer to the buffer of destination. */ +PyAPI_FUNC(int) PyBuffer_IsContiguous(const Py_buffer *view, char fort); + +/*Fill the strides array with byte-strides of a contiguous + (Fortran-style if fort is 'F' or C-style otherwise) + array of the given shape with the given number of bytes + per element. */ +PyAPI_FUNC(void) PyBuffer_FillContiguousStrides(int ndims, + Py_ssize_t *shape, + Py_ssize_t *strides, + int itemsize, + char fort); + +/* Fills in a buffer-info structure correctly for an exporter + that can only share a contiguous chunk of memory of + "unsigned bytes" of the given length. + + Returns 0 on success and -1 (with raising an error) on error. */ +PyAPI_FUNC(int) PyBuffer_FillInfo(Py_buffer *view, PyObject *o, void *buf, + Py_ssize_t len, int readonly, + int flags); + +/* Releases a Py_buffer obtained from getbuffer ParseTuple's "s*". */ +PyAPI_FUNC(void) PyBuffer_Release(Py_buffer *view); + +#endif /* Py_LIMITED_API */ + +/* Takes an arbitrary object and returns the result of calling + obj.__format__(format_spec). */ +PyAPI_FUNC(PyObject *) PyObject_Format(PyObject *obj, + PyObject *format_spec); + + +/* ==== Iterators ================================================ */ + +/* Takes an object and returns an iterator for it. + This is typically a new iterator but if the argument is an iterator, this + returns itself. */ +PyAPI_FUNC(PyObject *) PyObject_GetIter(PyObject *); + +#define PyIter_Check(obj) \ + ((obj)->ob_type->tp_iternext != NULL && \ + (obj)->ob_type->tp_iternext != &_PyObject_NextNotImplemented) + +/* Takes an iterator object and calls its tp_iternext slot, + returning the next value. + + If the iterator is exhausted, this returns NULL without setting an + exception. + + NULL with an exception means an error occurred. */ +PyAPI_FUNC(PyObject *) PyIter_Next(PyObject *); + + +/* === Number Protocol ================================================== */ + +/* Returns 1 if the object 'o' provides numeric protocols, and 0 otherwise. + + This function always succeeds. */ +PyAPI_FUNC(int) PyNumber_Check(PyObject *o); + +/* Returns the result of adding o1 and o2, or NULL on failure. + + This is the equivalent of the Python expression: o1 + o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Add(PyObject *o1, PyObject *o2); + +/* Returns the result of subtracting o2 from o1, or NULL on failure. + + This is the equivalent of the Python expression: o1 - o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Subtract(PyObject *o1, PyObject *o2); + +/* Returns the result of multiplying o1 and o2, or NULL on failure. + + This is the equivalent of the Python expression: o1 * o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Multiply(PyObject *o1, PyObject *o2); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* This is the equivalent of the Python expression: o1 @ o2. */ +PyAPI_FUNC(PyObject *) PyNumber_MatrixMultiply(PyObject *o1, PyObject *o2); +#endif + +/* Returns the result of dividing o1 by o2 giving an integral result, + or NULL on failure. + + This is the equivalent of the Python expression: o1 // o2. */ +PyAPI_FUNC(PyObject *) PyNumber_FloorDivide(PyObject *o1, PyObject *o2); + +/* Returns the result of dividing o1 by o2 giving a float result, or NULL on + failure. + + This is the equivalent of the Python expression: o1 / o2. */ +PyAPI_FUNC(PyObject *) PyNumber_TrueDivide(PyObject *o1, PyObject *o2); + +/* Returns the remainder of dividing o1 by o2, or NULL on failure. + + This is the equivalent of the Python expression: o1 % o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Remainder(PyObject *o1, PyObject *o2); + +/* See the built-in function divmod. + + Returns NULL on failure. + + This is the equivalent of the Python expression: divmod(o1, o2). */ +PyAPI_FUNC(PyObject *) PyNumber_Divmod(PyObject *o1, PyObject *o2); + +/* See the built-in function pow. Returns NULL on failure. + + This is the equivalent of the Python expression: pow(o1, o2, o3), + where o3 is optional. */ +PyAPI_FUNC(PyObject *) PyNumber_Power(PyObject *o1, PyObject *o2, + PyObject *o3); + +/* Returns the negation of o on success, or NULL on failure. + + This is the equivalent of the Python expression: -o. */ +PyAPI_FUNC(PyObject *) PyNumber_Negative(PyObject *o); + +/* Returns the positive of o on success, or NULL on failure. + + This is the equivalent of the Python expression: +o. */ +PyAPI_FUNC(PyObject *) PyNumber_Positive(PyObject *o); + +/* Returns the absolute value of 'o', or NULL on failure. + + This is the equivalent of the Python expression: abs(o). */ +PyAPI_FUNC(PyObject *) PyNumber_Absolute(PyObject *o); + +/* Returns the bitwise negation of 'o' on success, or NULL on failure. + + This is the equivalent of the Python expression: ~o. */ +PyAPI_FUNC(PyObject *) PyNumber_Invert(PyObject *o); + +/* Returns the result of left shifting o1 by o2 on success, or NULL on failure. + + This is the equivalent of the Python expression: o1 << o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Lshift(PyObject *o1, PyObject *o2); + +/* Returns the result of right shifting o1 by o2 on success, or NULL on + failure. + + This is the equivalent of the Python expression: o1 >> o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Rshift(PyObject *o1, PyObject *o2); + +/* Returns the result of bitwise and of o1 and o2 on success, or NULL on + failure. + + This is the equivalent of the Python expression: o1 & o2. */ +PyAPI_FUNC(PyObject *) PyNumber_And(PyObject *o1, PyObject *o2); + +/* Returns the bitwise exclusive or of o1 by o2 on success, or NULL on failure. + + This is the equivalent of the Python expression: o1 ^ o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Xor(PyObject *o1, PyObject *o2); + +/* Returns the result of bitwise or on o1 and o2 on success, or NULL on + failure. + + This is the equivalent of the Python expression: o1 | o2. */ +PyAPI_FUNC(PyObject *) PyNumber_Or(PyObject *o1, PyObject *o2); + +#define PyIndex_Check(obj) \ + ((obj)->ob_type->tp_as_number != NULL && \ + (obj)->ob_type->tp_as_number->nb_index != NULL) + +/* Returns the object 'o' converted to a Python int, or NULL with an exception + raised on failure. */ +PyAPI_FUNC(PyObject *) PyNumber_Index(PyObject *o); + +/* Returns the object 'o' converted to Py_ssize_t by going through + PyNumber_Index() first. + + If an overflow error occurs while converting the int to Py_ssize_t, then the + second argument 'exc' is the error-type to return. If it is NULL, then the + overflow error is cleared and the value is clipped. */ +PyAPI_FUNC(Py_ssize_t) PyNumber_AsSsize_t(PyObject *o, PyObject *exc); + +/* Returns the object 'o' converted to an integer object on success, or NULL + on failure. + + This is the equivalent of the Python expression: int(o). */ +PyAPI_FUNC(PyObject *) PyNumber_Long(PyObject *o); + +/* Returns the object 'o' converted to a float object on success, or NULL + on failure. + + This is the equivalent of the Python expression: float(o). */ +PyAPI_FUNC(PyObject *) PyNumber_Float(PyObject *o); + + +/* --- In-place variants of (some of) the above number protocol functions -- */ + +/* Returns the result of adding o2 to o1, possibly in-place, or NULL + on failure. + + This is the equivalent of the Python expression: o1 += o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceAdd(PyObject *o1, PyObject *o2); + +/* Returns the result of subtracting o2 from o1, possibly in-place or + NULL on failure. + + This is the equivalent of the Python expression: o1 -= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceSubtract(PyObject *o1, PyObject *o2); + +/* Returns the result of multiplying o1 by o2, possibly in-place, or NULL on + failure. + + This is the equivalent of the Python expression: o1 *= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceMultiply(PyObject *o1, PyObject *o2); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* This is the equivalent of the Python expression: o1 @= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceMatrixMultiply(PyObject *o1, PyObject *o2); +#endif + +/* Returns the result of dividing o1 by o2 giving an integral result, possibly + in-place, or NULL on failure. + + This is the equivalent of the Python expression: o1 /= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceFloorDivide(PyObject *o1, + PyObject *o2); + +/* Returns the result of dividing o1 by o2 giving a float result, possibly + in-place, or null on failure. + + This is the equivalent of the Python expression: o1 /= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceTrueDivide(PyObject *o1, + PyObject *o2); + +/* Returns the remainder of dividing o1 by o2, possibly in-place, or NULL on + failure. + + This is the equivalent of the Python expression: o1 %= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceRemainder(PyObject *o1, PyObject *o2); + +/* Returns the result of raising o1 to the power of o2, possibly in-place, + or NULL on failure. + + This is the equivalent of the Python expression: o1 **= o2, + or o1 = pow(o1, o2, o3) if o3 is present. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlacePower(PyObject *o1, PyObject *o2, + PyObject *o3); + +/* Returns the result of left shifting o1 by o2, possibly in-place, or NULL + on failure. + + This is the equivalent of the Python expression: o1 <<= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceLshift(PyObject *o1, PyObject *o2); + +/* Returns the result of right shifting o1 by o2, possibly in-place or NULL + on failure. + + This is the equivalent of the Python expression: o1 >>= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceRshift(PyObject *o1, PyObject *o2); + +/* Returns the result of bitwise and of o1 and o2, possibly in-place, or NULL + on failure. + + This is the equivalent of the Python expression: o1 &= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceAnd(PyObject *o1, PyObject *o2); + +/* Returns the bitwise exclusive or of o1 by o2, possibly in-place, or NULL + on failure. + + This is the equivalent of the Python expression: o1 ^= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceXor(PyObject *o1, PyObject *o2); + +/* Returns the result of bitwise or of o1 and o2, possibly in-place, + or NULL on failure. + + This is the equivalent of the Python expression: o1 |= o2. */ +PyAPI_FUNC(PyObject *) PyNumber_InPlaceOr(PyObject *o1, PyObject *o2); + +/* Returns the integer n converted to a string with a base, with a base + marker of 0b, 0o or 0x prefixed if applicable. + + If n is not an int object, it is converted with PyNumber_Index first. */ +PyAPI_FUNC(PyObject *) PyNumber_ToBase(PyObject *n, int base); + + +/* === Sequence protocol ================================================ */ + +/* Return 1 if the object provides sequence protocol, and zero + otherwise. + + This function always succeeds. */ +PyAPI_FUNC(int) PySequence_Check(PyObject *o); + +/* Return the size of sequence object o, or -1 on failure. */ +PyAPI_FUNC(Py_ssize_t) PySequence_Size(PyObject *o); + +/* For DLL compatibility */ +#undef PySequence_Length +PyAPI_FUNC(Py_ssize_t) PySequence_Length(PyObject *o); +#define PySequence_Length PySequence_Size + + +/* Return the concatenation of o1 and o2 on success, and NULL on failure. + + This is the equivalent of the Python expression: o1 + o2. */ +PyAPI_FUNC(PyObject *) PySequence_Concat(PyObject *o1, PyObject *o2); + +/* Return the result of repeating sequence object 'o' 'count' times, + or NULL on failure. + + This is the equivalent of the Python expression: o * count. */ +PyAPI_FUNC(PyObject *) PySequence_Repeat(PyObject *o, Py_ssize_t count); + +/* Return the ith element of o, or NULL on failure. + + This is the equivalent of the Python expression: o[i]. */ +PyAPI_FUNC(PyObject *) PySequence_GetItem(PyObject *o, Py_ssize_t i); + +/* Return the slice of sequence object o between i1 and i2, or NULL on failure. + + This is the equivalent of the Python expression: o[i1:i2]. */ +PyAPI_FUNC(PyObject *) PySequence_GetSlice(PyObject *o, Py_ssize_t i1, Py_ssize_t i2); + +/* Assign object 'v' to the ith element of the sequence 'o'. Raise an exception + and return -1 on failure; return 0 on success. + + This is the equivalent of the Python statement o[i] = v. */ +PyAPI_FUNC(int) PySequence_SetItem(PyObject *o, Py_ssize_t i, PyObject *v); + +/* Delete the 'i'-th element of the sequence 'v'. Returns -1 on failure. + + This is the equivalent of the Python statement: del o[i]. */ +PyAPI_FUNC(int) PySequence_DelItem(PyObject *o, Py_ssize_t i); + +/* Assign the sequence object 'v' to the slice in sequence object 'o', + from 'i1' to 'i2'. Returns -1 on failure. + + This is the equivalent of the Python statement: o[i1:i2] = v. */ +PyAPI_FUNC(int) PySequence_SetSlice(PyObject *o, Py_ssize_t i1, Py_ssize_t i2, + PyObject *v); + +/* Delete the slice in sequence object 'o' from 'i1' to 'i2'. + Returns -1 on failure. + + This is the equivalent of the Python statement: del o[i1:i2]. */ +PyAPI_FUNC(int) PySequence_DelSlice(PyObject *o, Py_ssize_t i1, Py_ssize_t i2); + +/* Returns the sequence 'o' as a tuple on success, and NULL on failure. + + This is equivalent to the Python expression: tuple(o). */ +PyAPI_FUNC(PyObject *) PySequence_Tuple(PyObject *o); + +/* Returns the sequence 'o' as a list on success, and NULL on failure. + This is equivalent to the Python expression: list(o) */ +PyAPI_FUNC(PyObject *) PySequence_List(PyObject *o); + +/* Return the sequence 'o' as a list, unless it's already a tuple or list. + + Use PySequence_Fast_GET_ITEM to access the members of this list, and + PySequence_Fast_GET_SIZE to get its length. + + Returns NULL on failure. If the object does not support iteration, raises a + TypeError exception with 'm' as the message text. */ +PyAPI_FUNC(PyObject *) PySequence_Fast(PyObject *o, const char* m); + +/* Return the size of the sequence 'o', assuming that 'o' was returned by + PySequence_Fast and is not NULL. */ +#define PySequence_Fast_GET_SIZE(o) \ + (PyList_Check(o) ? PyList_GET_SIZE(o) : PyTuple_GET_SIZE(o)) + +/* Return the 'i'-th element of the sequence 'o', assuming that o was returned + by PySequence_Fast, and that i is within bounds. */ +#define PySequence_Fast_GET_ITEM(o, i)\ + (PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i)) + +/* Assume tp_as_sequence and sq_item exist and that 'i' does not + need to be corrected for a negative index. */ +#define PySequence_ITEM(o, i)\ + ( Py_TYPE(o)->tp_as_sequence->sq_item(o, i) ) + +/* Return a pointer to the underlying item array for + an object retured by PySequence_Fast */ +#define PySequence_Fast_ITEMS(sf) \ + (PyList_Check(sf) ? ((PyListObject *)(sf))->ob_item \ + : ((PyTupleObject *)(sf))->ob_item) + +/* Return the number of occurrences on value on 'o', that is, return + the number of keys for which o[key] == value. + + On failure, return -1. This is equivalent to the Python expression: + o.count(value). */ +PyAPI_FUNC(Py_ssize_t) PySequence_Count(PyObject *o, PyObject *value); + +/* Return 1 if 'ob' is in the sequence 'seq'; 0 if 'ob' is not in the sequence + 'seq'; -1 on error. + + Use __contains__ if possible, else _PySequence_IterSearch(). */ +PyAPI_FUNC(int) PySequence_Contains(PyObject *seq, PyObject *ob); + +#ifndef Py_LIMITED_API +#define PY_ITERSEARCH_COUNT 1 +#define PY_ITERSEARCH_INDEX 2 +#define PY_ITERSEARCH_CONTAINS 3 + +/* Iterate over seq. + + Result depends on the operation: + + PY_ITERSEARCH_COUNT: return # of times obj appears in seq; -1 if + error. + PY_ITERSEARCH_INDEX: return 0-based index of first occurrence of + obj in seq; set ValueError and return -1 if none found; + also return -1 on error. + PY_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on + error. */ +PyAPI_FUNC(Py_ssize_t) _PySequence_IterSearch(PyObject *seq, + PyObject *obj, int operation); +#endif + + +/* For DLL-level backwards compatibility */ +#undef PySequence_In +/* Determine if the sequence 'o' contains 'value'. If an item in 'o' is equal + to 'value', return 1, otherwise return 0. On error, return -1. + + This is equivalent to the Python expression: value in o. */ +PyAPI_FUNC(int) PySequence_In(PyObject *o, PyObject *value); + +/* For source-level backwards compatibility */ +#define PySequence_In PySequence_Contains + + +/* Return the first index for which o[i] == value. + On error, return -1. + + This is equivalent to the Python expression: o.index(value). */ +PyAPI_FUNC(Py_ssize_t) PySequence_Index(PyObject *o, PyObject *value); + + +/* --- In-place versions of some of the above Sequence functions --- */ + +/* Append sequence 'o2' to sequence 'o1', in-place when possible. Return the + resulting object, which could be 'o1', or NULL on failure. + + This is the equivalent of the Python expression: o1 += o2. */ +PyAPI_FUNC(PyObject *) PySequence_InPlaceConcat(PyObject *o1, PyObject *o2); + +/* Repeat sequence 'o' by 'count', in-place when possible. Return the resulting + object, which could be 'o', or NULL on failure. + + This is the equivalent of the Python expression: o1 *= count. */ +PyAPI_FUNC(PyObject *) PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count); + + +/* === Mapping protocol ================================================= */ + +/* Return 1 if the object provides mapping protocol, and 0 otherwise. + + This function always succeeds. */ +PyAPI_FUNC(int) PyMapping_Check(PyObject *o); + +/* Returns the number of keys in mapping object 'o' on success, and -1 on + failure. This is equivalent to the Python expression: len(o). */ +PyAPI_FUNC(Py_ssize_t) PyMapping_Size(PyObject *o); + +/* For DLL compatibility */ +#undef PyMapping_Length +PyAPI_FUNC(Py_ssize_t) PyMapping_Length(PyObject *o); +#define PyMapping_Length PyMapping_Size + + +/* Implemented as a macro: + + int PyMapping_DelItemString(PyObject *o, const char *key); + + Remove the mapping for the string 'key' from the mapping 'o'. Returns -1 on + failure. + + This is equivalent to the Python statement: del o[key]. */ +#define PyMapping_DelItemString(O,K) PyObject_DelItemString((O),(K)) + +/* Implemented as a macro: + + int PyMapping_DelItem(PyObject *o, PyObject *key); + + Remove the mapping for the object 'key' from the mapping object 'o'. + Returns -1 on failure. + + This is equivalent to the Python statement: del o[key]. */ +#define PyMapping_DelItem(O,K) PyObject_DelItem((O),(K)) + +/* On success, return 1 if the mapping object 'o' has the key 'key', + and 0 otherwise. + + This is equivalent to the Python expression: key in o. + + This function always succeeds. */ +PyAPI_FUNC(int) PyMapping_HasKeyString(PyObject *o, const char *key); + +/* Return 1 if the mapping object has the key 'key', and 0 otherwise. + + This is equivalent to the Python expression: key in o. + + This function always succeeds. */ +PyAPI_FUNC(int) PyMapping_HasKey(PyObject *o, PyObject *key); + +/* On success, return a list or tuple of the keys in mapping object 'o'. + On failure, return NULL. */ +PyAPI_FUNC(PyObject *) PyMapping_Keys(PyObject *o); + +/* On success, return a list or tuple of the values in mapping object 'o'. + On failure, return NULL. */ +PyAPI_FUNC(PyObject *) PyMapping_Values(PyObject *o); + +/* On success, return a list or tuple of the items in mapping object 'o', + where each item is a tuple containing a key-value pair. On failure, return + NULL. */ +PyAPI_FUNC(PyObject *) PyMapping_Items(PyObject *o); + +/* Return element of 'o' corresponding to the string 'key' or NULL on failure. + + This is the equivalent of the Python expression: o[key]. */ +PyAPI_FUNC(PyObject *) PyMapping_GetItemString(PyObject *o, + const char *key); + +/* Map the string 'key' to the value 'v' in the mapping 'o'. + Returns -1 on failure. + + This is the equivalent of the Python statement: o[key]=v. */ +PyAPI_FUNC(int) PyMapping_SetItemString(PyObject *o, const char *key, + PyObject *value); + +/* isinstance(object, typeorclass) */ +PyAPI_FUNC(int) PyObject_IsInstance(PyObject *object, PyObject *typeorclass); + +/* issubclass(object, typeorclass) */ +PyAPI_FUNC(int) PyObject_IsSubclass(PyObject *object, PyObject *typeorclass); + + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyObject_RealIsInstance(PyObject *inst, PyObject *cls); + +PyAPI_FUNC(int) _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls); + +PyAPI_FUNC(char *const *) _PySequence_BytesToCharpArray(PyObject* self); + +PyAPI_FUNC(void) _Py_FreeCharPArray(char *const array[]); + +/* For internal use by buffer API functions */ +PyAPI_FUNC(void) _Py_add_one_to_index_F(int nd, Py_ssize_t *index, + const Py_ssize_t *shape); +PyAPI_FUNC(void) _Py_add_one_to_index_C(int nd, Py_ssize_t *index, + const Py_ssize_t *shape); + +/* Convert Python int to Py_ssize_t. Do nothing if the argument is None. */ +PyAPI_FUNC(int) _Py_convert_optional_to_ssize_t(PyObject *, void *); +#endif /* !Py_LIMITED_API */ + + +#ifdef __cplusplus +} +#endif +#endif /* Py_ABSTRACTOBJECT_H */ diff --git a/winvenv/Include/accu.h b/winvenv/Include/accu.h new file mode 100644 index 0000000..3636ea6 --- /dev/null +++ b/winvenv/Include/accu.h @@ -0,0 +1,37 @@ +#ifndef Py_LIMITED_API +#ifndef Py_ACCU_H +#define Py_ACCU_H + +/*** This is a private API for use by the interpreter and the stdlib. + *** Its definition may be changed or removed at any moment. + ***/ + +/* + * A two-level accumulator of unicode objects that avoids both the overhead + * of keeping a huge number of small separate objects, and the quadratic + * behaviour of using a naive repeated concatenation scheme. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#undef small /* defined by some Windows headers */ + +typedef struct { + PyObject *large; /* A list of previously accumulated large strings */ + PyObject *small; /* Pending small strings */ +} _PyAccu; + +PyAPI_FUNC(int) _PyAccu_Init(_PyAccu *acc); +PyAPI_FUNC(int) _PyAccu_Accumulate(_PyAccu *acc, PyObject *unicode); +PyAPI_FUNC(PyObject *) _PyAccu_FinishAsList(_PyAccu *acc); +PyAPI_FUNC(PyObject *) _PyAccu_Finish(_PyAccu *acc); +PyAPI_FUNC(void) _PyAccu_Destroy(_PyAccu *acc); + +#ifdef __cplusplus +} +#endif + +#endif /* Py_ACCU_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/asdl.h b/winvenv/Include/asdl.h new file mode 100644 index 0000000..35e9fa1 --- /dev/null +++ b/winvenv/Include/asdl.h @@ -0,0 +1,46 @@ +#ifndef Py_ASDL_H +#define Py_ASDL_H + +typedef PyObject * identifier; +typedef PyObject * string; +typedef PyObject * bytes; +typedef PyObject * object; +typedef PyObject * singleton; +typedef PyObject * constant; + +/* It would be nice if the code generated by asdl_c.py was completely + independent of Python, but it is a goal the requires too much work + at this stage. So, for example, I'll represent identifiers as + interned Python strings. +*/ + +/* XXX A sequence should be typed so that its use can be typechecked. */ + +typedef struct { + Py_ssize_t size; + void *elements[1]; +} asdl_seq; + +typedef struct { + Py_ssize_t size; + int elements[1]; +} asdl_int_seq; + +asdl_seq *_Py_asdl_seq_new(Py_ssize_t size, PyArena *arena); +asdl_int_seq *_Py_asdl_int_seq_new(Py_ssize_t size, PyArena *arena); + +#define asdl_seq_GET(S, I) (S)->elements[(I)] +#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size) +#ifdef Py_DEBUG +#define asdl_seq_SET(S, I, V) \ + do { \ + Py_ssize_t _asdl_i = (I); \ + assert((S) != NULL); \ + assert(_asdl_i < (S)->size); \ + (S)->elements[_asdl_i] = (V); \ + } while (0) +#else +#define asdl_seq_SET(S, I, V) (S)->elements[I] = (V) +#endif + +#endif /* !Py_ASDL_H */ diff --git a/winvenv/Include/ast.h b/winvenv/Include/ast.h new file mode 100644 index 0000000..5bc2b05 --- /dev/null +++ b/winvenv/Include/ast.h @@ -0,0 +1,29 @@ +#ifndef Py_AST_H +#define Py_AST_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(int) PyAST_Validate(mod_ty); +PyAPI_FUNC(mod_ty) PyAST_FromNode( + const node *n, + PyCompilerFlags *flags, + const char *filename, /* decoded from the filesystem encoding */ + PyArena *arena); +PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( + const node *n, + PyCompilerFlags *flags, + PyObject *filename, + PyArena *arena); + +#ifndef Py_LIMITED_API + +/* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ +PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty); + +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_AST_H */ diff --git a/winvenv/Include/bitset.h b/winvenv/Include/bitset.h new file mode 100644 index 0000000..b22fa77 --- /dev/null +++ b/winvenv/Include/bitset.h @@ -0,0 +1,32 @@ + +#ifndef Py_BITSET_H +#define Py_BITSET_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Bitset interface */ + +#define BYTE char + +typedef BYTE *bitset; + +bitset newbitset(int nbits); +void delbitset(bitset bs); +#define testbit(ss, ibit) (((ss)[BIT2BYTE(ibit)] & BIT2MASK(ibit)) != 0) +int addbit(bitset bs, int ibit); /* Returns 0 if already set */ +int samebitset(bitset bs1, bitset bs2, int nbits); +void mergebitset(bitset bs1, bitset bs2, int nbits); + +#define BITSPERBYTE (8*sizeof(BYTE)) +#define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE) + +#define BIT2BYTE(ibit) ((ibit) / BITSPERBYTE) +#define BIT2SHIFT(ibit) ((ibit) % BITSPERBYTE) +#define BIT2MASK(ibit) (1 << BIT2SHIFT(ibit)) +#define BYTE2BIT(ibyte) ((ibyte) * BITSPERBYTE) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_BITSET_H */ diff --git a/winvenv/Include/bltinmodule.h b/winvenv/Include/bltinmodule.h new file mode 100644 index 0000000..868c9e6 --- /dev/null +++ b/winvenv/Include/bltinmodule.h @@ -0,0 +1,14 @@ +#ifndef Py_BLTINMODULE_H +#define Py_BLTINMODULE_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_DATA(PyTypeObject) PyFilter_Type; +PyAPI_DATA(PyTypeObject) PyMap_Type; +PyAPI_DATA(PyTypeObject) PyZip_Type; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_BLTINMODULE_H */ diff --git a/winvenv/Include/boolobject.h b/winvenv/Include/boolobject.h new file mode 100644 index 0000000..7cc2f1f --- /dev/null +++ b/winvenv/Include/boolobject.h @@ -0,0 +1,34 @@ +/* Boolean object interface */ + +#ifndef Py_BOOLOBJECT_H +#define Py_BOOLOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +PyAPI_DATA(PyTypeObject) PyBool_Type; + +#define PyBool_Check(x) (Py_TYPE(x) == &PyBool_Type) + +/* Py_False and Py_True are the only two bools in existence. +Don't forget to apply Py_INCREF() when returning either!!! */ + +/* Don't use these directly */ +PyAPI_DATA(struct _longobject) _Py_FalseStruct, _Py_TrueStruct; + +/* Use these macros */ +#define Py_False ((PyObject *) &_Py_FalseStruct) +#define Py_True ((PyObject *) &_Py_TrueStruct) + +/* Macros for returning Py_True or Py_False, respectively */ +#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True +#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False + +/* Function to return a bool from a C long */ +PyAPI_FUNC(PyObject *) PyBool_FromLong(long); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_BOOLOBJECT_H */ diff --git a/winvenv/Include/bytearrayobject.h b/winvenv/Include/bytearrayobject.h new file mode 100644 index 0000000..a757b88 --- /dev/null +++ b/winvenv/Include/bytearrayobject.h @@ -0,0 +1,62 @@ +/* ByteArray object interface */ + +#ifndef Py_BYTEARRAYOBJECT_H +#define Py_BYTEARRAYOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Type PyByteArrayObject represents a mutable array of bytes. + * The Python API is that of a sequence; + * the bytes are mapped to ints in [0, 256). + * Bytes are not characters; they may be used to encode characters. + * The only way to go between bytes and str/unicode is via encoding + * and decoding. + * For the convenience of C programmers, the bytes type is considered + * to contain a char pointer, not an unsigned char pointer. + */ + +/* Object layout */ +#ifndef Py_LIMITED_API +typedef struct { + PyObject_VAR_HEAD + Py_ssize_t ob_alloc; /* How many bytes allocated in ob_bytes */ + char *ob_bytes; /* Physical backing buffer */ + char *ob_start; /* Logical start inside ob_bytes */ + /* XXX(nnorwitz): should ob_exports be Py_ssize_t? */ + int ob_exports; /* How many buffer exports */ +} PyByteArrayObject; +#endif + +/* Type object */ +PyAPI_DATA(PyTypeObject) PyByteArray_Type; +PyAPI_DATA(PyTypeObject) PyByteArrayIter_Type; + +/* Type check macros */ +#define PyByteArray_Check(self) PyObject_TypeCheck(self, &PyByteArray_Type) +#define PyByteArray_CheckExact(self) (Py_TYPE(self) == &PyByteArray_Type) + +/* Direct API functions */ +PyAPI_FUNC(PyObject *) PyByteArray_FromObject(PyObject *); +PyAPI_FUNC(PyObject *) PyByteArray_Concat(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyByteArray_FromStringAndSize(const char *, Py_ssize_t); +PyAPI_FUNC(Py_ssize_t) PyByteArray_Size(PyObject *); +PyAPI_FUNC(char *) PyByteArray_AsString(PyObject *); +PyAPI_FUNC(int) PyByteArray_Resize(PyObject *, Py_ssize_t); + +/* Macros, trading safety for speed */ +#ifndef Py_LIMITED_API +#define PyByteArray_AS_STRING(self) \ + (assert(PyByteArray_Check(self)), \ + Py_SIZE(self) ? ((PyByteArrayObject *)(self))->ob_start : _PyByteArray_empty_string) +#define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)), Py_SIZE(self)) + +PyAPI_DATA(char) _PyByteArray_empty_string[]; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_BYTEARRAYOBJECT_H */ diff --git a/winvenv/Include/bytes_methods.h b/winvenv/Include/bytes_methods.h new file mode 100644 index 0000000..8434a50 --- /dev/null +++ b/winvenv/Include/bytes_methods.h @@ -0,0 +1,69 @@ +#ifndef Py_LIMITED_API +#ifndef Py_BYTES_CTYPE_H +#define Py_BYTES_CTYPE_H + +/* + * The internal implementation behind PyBytes (bytes) and PyByteArray (bytearray) + * methods of the given names, they operate on ASCII byte strings. + */ +extern PyObject* _Py_bytes_isspace(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_isalpha(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_isalnum(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_isascii(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_isdigit(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_islower(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_isupper(const char *cptr, Py_ssize_t len); +extern PyObject* _Py_bytes_istitle(const char *cptr, Py_ssize_t len); + +/* These store their len sized answer in the given preallocated *result arg. */ +extern void _Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len); +extern void _Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len); +extern void _Py_bytes_title(char *result, const char *s, Py_ssize_t len); +extern void _Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len); +extern void _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len); + +extern PyObject *_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args); +extern int _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg); +extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args); +extern PyObject *_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args); + +/* The maketrans() static method. */ +extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to); + +/* Shared __doc__ strings. */ +extern const char _Py_isspace__doc__[]; +extern const char _Py_isalpha__doc__[]; +extern const char _Py_isalnum__doc__[]; +extern const char _Py_isascii__doc__[]; +extern const char _Py_isdigit__doc__[]; +extern const char _Py_islower__doc__[]; +extern const char _Py_isupper__doc__[]; +extern const char _Py_istitle__doc__[]; +extern const char _Py_lower__doc__[]; +extern const char _Py_upper__doc__[]; +extern const char _Py_title__doc__[]; +extern const char _Py_capitalize__doc__[]; +extern const char _Py_swapcase__doc__[]; +extern const char _Py_count__doc__[]; +extern const char _Py_find__doc__[]; +extern const char _Py_index__doc__[]; +extern const char _Py_rfind__doc__[]; +extern const char _Py_rindex__doc__[]; +extern const char _Py_startswith__doc__[]; +extern const char _Py_endswith__doc__[]; +extern const char _Py_maketrans__doc__[]; +extern const char _Py_expandtabs__doc__[]; +extern const char _Py_ljust__doc__[]; +extern const char _Py_rjust__doc__[]; +extern const char _Py_center__doc__[]; +extern const char _Py_zfill__doc__[]; + +/* this is needed because some docs are shared from the .o, not static */ +#define PyDoc_STRVAR_shared(name,str) const char name[] = PyDoc_STR(str) + +#endif /* !Py_BYTES_CTYPE_H */ +#endif /* !Py_LIMITED_API */ diff --git a/winvenv/Include/bytesobject.h b/winvenv/Include/bytesobject.h new file mode 100644 index 0000000..3fde4a2 --- /dev/null +++ b/winvenv/Include/bytesobject.h @@ -0,0 +1,224 @@ + +/* Bytes (String) object interface */ + +#ifndef Py_BYTESOBJECT_H +#define Py_BYTESOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* +Type PyBytesObject represents a character string. An extra zero byte is +reserved at the end to ensure it is zero-terminated, but a size is +present so strings with null bytes in them can be represented. This +is an immutable object type. + +There are functions to create new string objects, to test +an object for string-ness, and to get the +string value. The latter function returns a null pointer +if the object is not of the proper type. +There is a variant that takes an explicit size as well as a +variant that assumes a zero-terminated string. Note that none of the +functions should be applied to nil objects. +*/ + +/* Caching the hash (ob_shash) saves recalculation of a string's hash value. + This significantly speeds up dict lookups. */ + +#ifndef Py_LIMITED_API +typedef struct { + PyObject_VAR_HEAD + Py_hash_t ob_shash; + char ob_sval[1]; + + /* Invariants: + * ob_sval contains space for 'ob_size+1' elements. + * ob_sval[ob_size] == 0. + * ob_shash is the hash of the string or -1 if not computed yet. + */ +} PyBytesObject; +#endif + +PyAPI_DATA(PyTypeObject) PyBytes_Type; +PyAPI_DATA(PyTypeObject) PyBytesIter_Type; + +#define PyBytes_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_BYTES_SUBCLASS) +#define PyBytes_CheckExact(op) (Py_TYPE(op) == &PyBytes_Type) + +PyAPI_FUNC(PyObject *) PyBytes_FromStringAndSize(const char *, Py_ssize_t); +PyAPI_FUNC(PyObject *) PyBytes_FromString(const char *); +PyAPI_FUNC(PyObject *) PyBytes_FromObject(PyObject *); +PyAPI_FUNC(PyObject *) PyBytes_FromFormatV(const char*, va_list) + Py_GCC_ATTRIBUTE((format(printf, 1, 0))); +PyAPI_FUNC(PyObject *) PyBytes_FromFormat(const char*, ...) + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); +PyAPI_FUNC(Py_ssize_t) PyBytes_Size(PyObject *); +PyAPI_FUNC(char *) PyBytes_AsString(PyObject *); +PyAPI_FUNC(PyObject *) PyBytes_Repr(PyObject *, int); +PyAPI_FUNC(void) PyBytes_Concat(PyObject **, PyObject *); +PyAPI_FUNC(void) PyBytes_ConcatAndDel(PyObject **, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyBytes_Resize(PyObject **, Py_ssize_t); +PyAPI_FUNC(PyObject*) _PyBytes_FormatEx( + const char *format, + Py_ssize_t format_len, + PyObject *args, + int use_bytearray); +PyAPI_FUNC(PyObject*) _PyBytes_FromHex( + PyObject *string, + int use_bytearray); +#endif +PyAPI_FUNC(PyObject *) PyBytes_DecodeEscape(const char *, Py_ssize_t, + const char *, Py_ssize_t, + const char *); +#ifndef Py_LIMITED_API +/* Helper for PyBytes_DecodeEscape that detects invalid escape chars. */ +PyAPI_FUNC(PyObject *) _PyBytes_DecodeEscape(const char *, Py_ssize_t, + const char *, Py_ssize_t, + const char *, + const char **); +#endif + +/* Macro, trading safety for speed */ +#ifndef Py_LIMITED_API +#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \ + (((PyBytesObject *)(op))->ob_sval)) +#define PyBytes_GET_SIZE(op) (assert(PyBytes_Check(op)),Py_SIZE(op)) +#endif + +/* _PyBytes_Join(sep, x) is like sep.join(x). sep must be PyBytesObject*, + x must be an iterable object. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyBytes_Join(PyObject *sep, PyObject *x); +#endif + +/* Provides access to the internal data buffer and size of a string + object or the default encoded version of a Unicode object. Passing + NULL as *len parameter will force the string buffer to be + 0-terminated (passing a string with embedded NULL characters will + cause an exception). */ +PyAPI_FUNC(int) PyBytes_AsStringAndSize( + PyObject *obj, /* string or Unicode object */ + char **s, /* pointer to buffer variable */ + Py_ssize_t *len /* pointer to length variable or NULL + (only possible for 0-terminated + strings) */ + ); + +/* Using the current locale, insert the thousands grouping + into the string pointed to by buffer. For the argument descriptions, + see Objects/stringlib/localeutil.h */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) _PyBytes_InsertThousandsGroupingLocale(char *buffer, + Py_ssize_t n_buffer, + char *digits, + Py_ssize_t n_digits, + Py_ssize_t min_width); + +/* Using explicit passed-in values, insert the thousands grouping + into the string pointed to by buffer. For the argument descriptions, + see Objects/stringlib/localeutil.h */ +PyAPI_FUNC(Py_ssize_t) _PyBytes_InsertThousandsGrouping(char *buffer, + Py_ssize_t n_buffer, + char *digits, + Py_ssize_t n_digits, + Py_ssize_t min_width, + const char *grouping, + const char *thousands_sep); +#endif + +/* Flags used by string formatting */ +#define F_LJUST (1<<0) +#define F_SIGN (1<<1) +#define F_BLANK (1<<2) +#define F_ALT (1<<3) +#define F_ZERO (1<<4) + +#ifndef Py_LIMITED_API +/* The _PyBytesWriter structure is big: it contains an embedded "stack buffer". + A _PyBytesWriter variable must be declared at the end of variables in a + function to optimize the memory allocation on the stack. */ +typedef struct { + /* bytes, bytearray or NULL (when the small buffer is used) */ + PyObject *buffer; + + /* Number of allocated size. */ + Py_ssize_t allocated; + + /* Minimum number of allocated bytes, + incremented by _PyBytesWriter_Prepare() */ + Py_ssize_t min_size; + + /* If non-zero, use a bytearray instead of a bytes object for buffer. */ + int use_bytearray; + + /* If non-zero, overallocate the buffer (default: 0). + This flag must be zero if use_bytearray is non-zero. */ + int overallocate; + + /* Stack buffer */ + int use_small_buffer; + char small_buffer[512]; +} _PyBytesWriter; + +/* Initialize a bytes writer + + By default, the overallocation is disabled. Set the overallocate attribute + to control the allocation of the buffer. */ +PyAPI_FUNC(void) _PyBytesWriter_Init(_PyBytesWriter *writer); + +/* Get the buffer content and reset the writer. + Return a bytes object, or a bytearray object if use_bytearray is non-zero. + Raise an exception and return NULL on error. */ +PyAPI_FUNC(PyObject *) _PyBytesWriter_Finish(_PyBytesWriter *writer, + void *str); + +/* Deallocate memory of a writer (clear its internal buffer). */ +PyAPI_FUNC(void) _PyBytesWriter_Dealloc(_PyBytesWriter *writer); + +/* Allocate the buffer to write size bytes. + Return the pointer to the beginning of buffer data. + Raise an exception and return NULL on error. */ +PyAPI_FUNC(void*) _PyBytesWriter_Alloc(_PyBytesWriter *writer, + Py_ssize_t size); + +/* Ensure that the buffer is large enough to write *size* bytes. + Add size to the writer minimum size (min_size attribute). + + str is the current pointer inside the buffer. + Return the updated current pointer inside the buffer. + Raise an exception and return NULL on error. */ +PyAPI_FUNC(void*) _PyBytesWriter_Prepare(_PyBytesWriter *writer, + void *str, + Py_ssize_t size); + +/* Resize the buffer to make it larger. + The new buffer may be larger than size bytes because of overallocation. + Return the updated current pointer inside the buffer. + Raise an exception and return NULL on error. + + Note: size must be greater than the number of allocated bytes in the writer. + + This function doesn't use the writer minimum size (min_size attribute). + + See also _PyBytesWriter_Prepare(). + */ +PyAPI_FUNC(void*) _PyBytesWriter_Resize(_PyBytesWriter *writer, + void *str, + Py_ssize_t size); + +/* Write bytes. + Raise an exception and return NULL on error. */ +PyAPI_FUNC(void*) _PyBytesWriter_WriteBytes(_PyBytesWriter *writer, + void *str, + const void *bytes, + Py_ssize_t size); +#endif /* Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_BYTESOBJECT_H */ diff --git a/winvenv/Include/cellobject.h b/winvenv/Include/cellobject.h new file mode 100644 index 0000000..2f9b5b7 --- /dev/null +++ b/winvenv/Include/cellobject.h @@ -0,0 +1,29 @@ +/* Cell object interface */ +#ifndef Py_LIMITED_API +#ifndef Py_CELLOBJECT_H +#define Py_CELLOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + PyObject_HEAD + PyObject *ob_ref; /* Content of the cell or NULL when empty */ +} PyCellObject; + +PyAPI_DATA(PyTypeObject) PyCell_Type; + +#define PyCell_Check(op) (Py_TYPE(op) == &PyCell_Type) + +PyAPI_FUNC(PyObject *) PyCell_New(PyObject *); +PyAPI_FUNC(PyObject *) PyCell_Get(PyObject *); +PyAPI_FUNC(int) PyCell_Set(PyObject *, PyObject *); + +#define PyCell_GET(op) (((PyCellObject *)(op))->ob_ref) +#define PyCell_SET(op, v) (((PyCellObject *)(op))->ob_ref = v) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_TUPLEOBJECT_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/ceval.h b/winvenv/Include/ceval.h new file mode 100644 index 0000000..bce8a0b --- /dev/null +++ b/winvenv/Include/ceval.h @@ -0,0 +1,237 @@ +#ifndef Py_CEVAL_H +#define Py_CEVAL_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Interface to random parts in ceval.c */ + +/* PyEval_CallObjectWithKeywords(), PyEval_CallObject(), PyEval_CallFunction + * and PyEval_CallMethod are kept for backward compatibility: PyObject_Call(), + * PyObject_CallFunction() and PyObject_CallMethod() are recommended to call + * a callable object. + */ + +PyAPI_FUNC(PyObject *) PyEval_CallObjectWithKeywords( + PyObject *callable, + PyObject *args, + PyObject *kwargs); + +/* Inline this */ +#define PyEval_CallObject(callable, arg) \ + PyEval_CallObjectWithKeywords(callable, arg, (PyObject *)NULL) + +PyAPI_FUNC(PyObject *) PyEval_CallFunction(PyObject *callable, + const char *format, ...); +PyAPI_FUNC(PyObject *) PyEval_CallMethod(PyObject *obj, + const char *name, + const char *format, ...); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); +PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *); +PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(int new_depth); +PyAPI_FUNC(int) _PyEval_GetCoroutineOriginTrackingDepth(void); +PyAPI_FUNC(void) _PyEval_SetCoroutineWrapper(PyObject *); +PyAPI_FUNC(PyObject *) _PyEval_GetCoroutineWrapper(void); +PyAPI_FUNC(void) _PyEval_SetAsyncGenFirstiter(PyObject *); +PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFirstiter(void); +PyAPI_FUNC(void) _PyEval_SetAsyncGenFinalizer(PyObject *); +PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFinalizer(void); +#endif + +struct _frame; /* Avoid including frameobject.h */ + +PyAPI_FUNC(PyObject *) PyEval_GetBuiltins(void); +PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void); +PyAPI_FUNC(PyObject *) PyEval_GetLocals(void); +PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void); + +/* Look at the current frame's (if any) code's co_flags, and turn on + the corresponding compiler flags in cf->cf_flags. Return 1 if any + flag was set, else return 0. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf); +#endif + +PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg); +PyAPI_FUNC(void) _PyEval_SignalReceived(void); +PyAPI_FUNC(int) Py_MakePendingCalls(void); + +/* Protection against deeply nested recursive calls + + In Python 3.0, this protection has two levels: + * normal anti-recursion protection is triggered when the recursion level + exceeds the current recursion limit. It raises a RecursionError, and sets + the "overflowed" flag in the thread state structure. This flag + temporarily *disables* the normal protection; this allows cleanup code + to potentially outgrow the recursion limit while processing the + RecursionError. + * "last chance" anti-recursion protection is triggered when the recursion + level exceeds "current recursion limit + 50". By construction, this + protection can only be triggered when the "overflowed" flag is set. It + means the cleanup code has itself gone into an infinite loop, or the + RecursionError has been mistakingly ignored. When this protection is + triggered, the interpreter aborts with a Fatal Error. + + In addition, the "overflowed" flag is automatically reset when the + recursion level drops below "current recursion limit - 50". This heuristic + is meant to ensure that the normal anti-recursion protection doesn't get + disabled too long. + + Please note: this scheme has its own limitations. See: + http://mail.python.org/pipermail/python-dev/2008-August/082106.html + for some observations. +*/ +PyAPI_FUNC(void) Py_SetRecursionLimit(int); +PyAPI_FUNC(int) Py_GetRecursionLimit(void); + +#define Py_EnterRecursiveCall(where) \ + (_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \ + _Py_CheckRecursiveCall(where)) +#define Py_LeaveRecursiveCall() \ + do{ if(_Py_MakeEndRecCheck(PyThreadState_GET()->recursion_depth)) \ + PyThreadState_GET()->overflowed = 0; \ + } while(0) +PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where); + +/* Due to the macros in which it's used, _Py_CheckRecursionLimit is in + the stable ABI. It should be removed therefrom when possible. +*/ +PyAPI_DATA(int) _Py_CheckRecursionLimit; + +#ifdef USE_STACKCHECK +/* With USE_STACKCHECK, trigger stack checks in _Py_CheckRecursiveCall() + on every 64th call to Py_EnterRecursiveCall. +*/ +# define _Py_MakeRecCheck(x) \ + (++(x) > _Py_CheckRecursionLimit || \ + ++(PyThreadState_GET()->stackcheck_counter) > 64) +#else +# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit) +#endif + +/* Compute the "lower-water mark" for a recursion limit. When + * Py_LeaveRecursiveCall() is called with a recursion depth below this mark, + * the overflowed flag is reset to 0. */ +#define _Py_RecursionLimitLowerWaterMark(limit) \ + (((limit) > 200) \ + ? ((limit) - 50) \ + : (3 * ((limit) >> 2))) + +#define _Py_MakeEndRecCheck(x) \ + (--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit)) + +#define Py_ALLOW_RECURSION \ + do { unsigned char _old = PyThreadState_GET()->recursion_critical;\ + PyThreadState_GET()->recursion_critical = 1; + +#define Py_END_ALLOW_RECURSION \ + PyThreadState_GET()->recursion_critical = _old; \ + } while(0); + +PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *); +PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *); + +PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *); +PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(struct _frame *f, int exc); +#endif + +/* Interface for threads. + + A module that plans to do a blocking system call (or something else + that lasts a long time and doesn't touch Python data) can allow other + threads to run as follows: + + ...preparations here... + Py_BEGIN_ALLOW_THREADS + ...blocking system call here... + Py_END_ALLOW_THREADS + ...interpret result here... + + The Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS pair expands to a + {}-surrounded block. + To leave the block in the middle (e.g., with return), you must insert + a line containing Py_BLOCK_THREADS before the return, e.g. + + if (...premature_exit...) { + Py_BLOCK_THREADS + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + An alternative is: + + Py_BLOCK_THREADS + if (...premature_exit...) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_UNBLOCK_THREADS + + For convenience, that the value of 'errno' is restored across + Py_END_ALLOW_THREADS and Py_BLOCK_THREADS. + + WARNING: NEVER NEST CALLS TO Py_BEGIN_ALLOW_THREADS AND + Py_END_ALLOW_THREADS!!! + + The function PyEval_InitThreads() should be called only from + init_thread() in "_threadmodule.c". + + Note that not yet all candidates have been converted to use this + mechanism! +*/ + +PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void); +PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); + +PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); +PyAPI_FUNC(void) PyEval_InitThreads(void); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyEval_FiniThreads(void); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(void) PyEval_AcquireLock(void) Py_DEPRECATED(3.2); +PyAPI_FUNC(void) PyEval_ReleaseLock(void) /* Py_DEPRECATED(3.2) */; +PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); +PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate); +PyAPI_FUNC(void) PyEval_ReInitThreads(void); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds); +PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void); +#endif + +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc); +#endif + +#define Py_BEGIN_ALLOW_THREADS { \ + PyThreadState *_save; \ + _save = PyEval_SaveThread(); +#define Py_BLOCK_THREADS PyEval_RestoreThread(_save); +#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread(); +#define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \ + } + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *); +PyAPI_FUNC(void) _PyEval_SignalAsyncExc(void); +#endif + +/* Masks and values used by FORMAT_VALUE opcode. */ +#define FVC_MASK 0x3 +#define FVC_NONE 0x0 +#define FVC_STR 0x1 +#define FVC_REPR 0x2 +#define FVC_ASCII 0x3 +#define FVS_MASK 0x4 +#define FVS_HAVE_SPEC 0x4 + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CEVAL_H */ diff --git a/winvenv/Include/classobject.h b/winvenv/Include/classobject.h new file mode 100644 index 0000000..209f0f4 --- /dev/null +++ b/winvenv/Include/classobject.h @@ -0,0 +1,58 @@ +/* Former class object interface -- now only bound methods are here */ + +/* Revealing some structures (not for general use) */ + +#ifndef Py_LIMITED_API +#ifndef Py_CLASSOBJECT_H +#define Py_CLASSOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + PyObject_HEAD + PyObject *im_func; /* The callable object implementing the method */ + PyObject *im_self; /* The instance it is bound to */ + PyObject *im_weakreflist; /* List of weak references */ +} PyMethodObject; + +PyAPI_DATA(PyTypeObject) PyMethod_Type; + +#define PyMethod_Check(op) ((op)->ob_type == &PyMethod_Type) + +PyAPI_FUNC(PyObject *) PyMethod_New(PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) PyMethod_Function(PyObject *); +PyAPI_FUNC(PyObject *) PyMethod_Self(PyObject *); + +/* Macros for direct access to these values. Type checks are *not* + done, so use with care. */ +#define PyMethod_GET_FUNCTION(meth) \ + (((PyMethodObject *)meth) -> im_func) +#define PyMethod_GET_SELF(meth) \ + (((PyMethodObject *)meth) -> im_self) + +PyAPI_FUNC(int) PyMethod_ClearFreeList(void); + +typedef struct { + PyObject_HEAD + PyObject *func; +} PyInstanceMethodObject; + +PyAPI_DATA(PyTypeObject) PyInstanceMethod_Type; + +#define PyInstanceMethod_Check(op) ((op)->ob_type == &PyInstanceMethod_Type) + +PyAPI_FUNC(PyObject *) PyInstanceMethod_New(PyObject *); +PyAPI_FUNC(PyObject *) PyInstanceMethod_Function(PyObject *); + +/* Macros for direct access to these values. Type checks are *not* + done, so use with care. */ +#define PyInstanceMethod_GET_FUNCTION(meth) \ + (((PyInstanceMethodObject *)meth) -> func) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CLASSOBJECT_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/code.h b/winvenv/Include/code.h new file mode 100644 index 0000000..2e661e8 --- /dev/null +++ b/winvenv/Include/code.h @@ -0,0 +1,157 @@ +/* Definitions for bytecode */ + +#ifndef Py_LIMITED_API +#ifndef Py_CODE_H +#define Py_CODE_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint16_t _Py_CODEUNIT; + +#ifdef WORDS_BIGENDIAN +# define _Py_OPCODE(word) ((word) >> 8) +# define _Py_OPARG(word) ((word) & 255) +#else +# define _Py_OPCODE(word) ((word) & 255) +# define _Py_OPARG(word) ((word) >> 8) +#endif + +/* Bytecode object */ +typedef struct { + PyObject_HEAD + int co_argcount; /* #arguments, except *args */ + int co_kwonlyargcount; /* #keyword only arguments */ + int co_nlocals; /* #local variables */ + int co_stacksize; /* #entries needed for evaluation stack */ + int co_flags; /* CO_..., see below */ + int co_firstlineno; /* first source line number */ + PyObject *co_code; /* instruction opcodes */ + PyObject *co_consts; /* list (constants used) */ + PyObject *co_names; /* list of strings (names used) */ + PyObject *co_varnames; /* tuple of strings (local variable names) */ + PyObject *co_freevars; /* tuple of strings (free variable names) */ + PyObject *co_cellvars; /* tuple of strings (cell variable names) */ + /* The rest aren't used in either hash or comparisons, except for co_name, + used in both. This is done to preserve the name and line number + for tracebacks and debuggers; otherwise, constant de-duplication + would collapse identical functions/lambdas defined on different lines. + */ + Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */ + PyObject *co_filename; /* unicode (where it was loaded from) */ + PyObject *co_name; /* unicode (name, for reference) */ + PyObject *co_lnotab; /* string (encoding addr<->lineno mapping) See + Objects/lnotab_notes.txt for details. */ + void *co_zombieframe; /* for optimization only (see frameobject.c) */ + PyObject *co_weakreflist; /* to support weakrefs to code objects */ + /* Scratch space for extra data relating to the code object. + Type is a void* to keep the format private in codeobject.c to force + people to go through the proper APIs. */ + void *co_extra; +} PyCodeObject; + +/* Masks for co_flags above */ +#define CO_OPTIMIZED 0x0001 +#define CO_NEWLOCALS 0x0002 +#define CO_VARARGS 0x0004 +#define CO_VARKEYWORDS 0x0008 +#define CO_NESTED 0x0010 +#define CO_GENERATOR 0x0020 +/* The CO_NOFREE flag is set if there are no free or cell variables. + This information is redundant, but it allows a single flag test + to determine whether there is any extra work to be done when the + call frame it setup. +*/ +#define CO_NOFREE 0x0040 + +/* The CO_COROUTINE flag is set for coroutine functions (defined with + ``async def`` keywords) */ +#define CO_COROUTINE 0x0080 +#define CO_ITERABLE_COROUTINE 0x0100 +#define CO_ASYNC_GENERATOR 0x0200 + +/* These are no longer used. */ +#if 0 +#define CO_GENERATOR_ALLOWED 0x1000 +#endif +#define CO_FUTURE_DIVISION 0x2000 +#define CO_FUTURE_ABSOLUTE_IMPORT 0x4000 /* do absolute imports by default */ +#define CO_FUTURE_WITH_STATEMENT 0x8000 +#define CO_FUTURE_PRINT_FUNCTION 0x10000 +#define CO_FUTURE_UNICODE_LITERALS 0x20000 + +#define CO_FUTURE_BARRY_AS_BDFL 0x40000 +#define CO_FUTURE_GENERATOR_STOP 0x80000 +#define CO_FUTURE_ANNOTATIONS 0x100000 + +/* This value is found in the co_cell2arg array when the associated cell + variable does not correspond to an argument. */ +#define CO_CELL_NOT_AN_ARG (-1) + +/* This should be defined if a future statement modifies the syntax. + For example, when a keyword is added. +*/ +#define PY_PARSER_REQUIRES_FUTURE_KEYWORD + +#define CO_MAXBLOCKS 20 /* Max static block nesting within a function */ + +PyAPI_DATA(PyTypeObject) PyCode_Type; + +#define PyCode_Check(op) (Py_TYPE(op) == &PyCode_Type) +#define PyCode_GetNumFree(op) (PyTuple_GET_SIZE((op)->co_freevars)) + +/* Public interface */ +PyAPI_FUNC(PyCodeObject *) PyCode_New( + int, int, int, int, int, PyObject *, PyObject *, + PyObject *, PyObject *, PyObject *, PyObject *, + PyObject *, PyObject *, int, PyObject *); + /* same as struct above */ + +/* Creates a new empty code object with the specified source location. */ +PyAPI_FUNC(PyCodeObject *) +PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno); + +/* Return the line number associated with the specified bytecode index + in this code object. If you just need the line number of a frame, + use PyFrame_GetLineNumber() instead. */ +PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int); + +/* for internal use only */ +typedef struct _addr_pair { + int ap_lower; + int ap_upper; +} PyAddrPair; + +#ifndef Py_LIMITED_API +/* Update *bounds to describe the first and one-past-the-last instructions in the + same line as lasti. Return the number of that line. +*/ +PyAPI_FUNC(int) _PyCode_CheckLineNumber(PyCodeObject* co, + int lasti, PyAddrPair *bounds); + +/* Create a comparable key used to compare constants taking in account the + * object type. It is used to make sure types are not coerced (e.g., float and + * complex) _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms + * + * Return (type(obj), obj, ...): a tuple with variable size (at least 2 items) + * depending on the type and the value. The type is the first item to not + * compare bytes and str which can raise a BytesWarning exception. */ +PyAPI_FUNC(PyObject*) _PyCode_ConstantKey(PyObject *obj); +#endif + +PyAPI_FUNC(PyObject*) PyCode_Optimize(PyObject *code, PyObject* consts, + PyObject *names, PyObject *lnotab); + + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyCode_GetExtra(PyObject *code, Py_ssize_t index, + void **extra); +PyAPI_FUNC(int) _PyCode_SetExtra(PyObject *code, Py_ssize_t index, + void *extra); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CODE_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/codecs.h b/winvenv/Include/codecs.h new file mode 100644 index 0000000..3ad0f2b --- /dev/null +++ b/winvenv/Include/codecs.h @@ -0,0 +1,240 @@ +#ifndef Py_CODECREGISTRY_H +#define Py_CODECREGISTRY_H +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------------ + + Python Codec Registry and support functions + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +Copyright (c) Corporation for National Research Initiatives. + + ------------------------------------------------------------------------ */ + +/* Register a new codec search function. + + As side effect, this tries to load the encodings package, if not + yet done, to make sure that it is always first in the list of + search functions. + + The search_function's refcount is incremented by this function. */ + +PyAPI_FUNC(int) PyCodec_Register( + PyObject *search_function + ); + +/* Codec registry lookup API. + + Looks up the given encoding and returns a CodecInfo object with + function attributes which implement the different aspects of + processing the encoding. + + The encoding string is looked up converted to all lower-case + characters. This makes encodings looked up through this mechanism + effectively case-insensitive. + + If no codec is found, a KeyError is set and NULL returned. + + As side effect, this tries to load the encodings package, if not + yet done. This is part of the lazy load strategy for the encodings + package. + + */ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyCodec_Lookup( + const char *encoding + ); + +PyAPI_FUNC(int) _PyCodec_Forget( + const char *encoding + ); +#endif + +/* Codec registry encoding check API. + + Returns 1/0 depending on whether there is a registered codec for + the given encoding. + +*/ + +PyAPI_FUNC(int) PyCodec_KnownEncoding( + const char *encoding + ); + +/* Generic codec based encoding API. + + object is passed through the encoder function found for the given + encoding using the error handling method defined by errors. errors + may be NULL to use the default method defined for the codec. + + Raises a LookupError in case no encoder can be found. + + */ + +PyAPI_FUNC(PyObject *) PyCodec_Encode( + PyObject *object, + const char *encoding, + const char *errors + ); + +/* Generic codec based decoding API. + + object is passed through the decoder function found for the given + encoding using the error handling method defined by errors. errors + may be NULL to use the default method defined for the codec. + + Raises a LookupError in case no encoder can be found. + + */ + +PyAPI_FUNC(PyObject *) PyCodec_Decode( + PyObject *object, + const char *encoding, + const char *errors + ); + +#ifndef Py_LIMITED_API +/* Text codec specific encoding and decoding API. + + Checks the encoding against a list of codecs which do not + implement a str<->bytes encoding before attempting the + operation. + + Please note that these APIs are internal and should not + be used in Python C extensions. + + XXX (ncoghlan): should we make these, or something like them, public + in Python 3.5+? + + */ +PyAPI_FUNC(PyObject *) _PyCodec_LookupTextEncoding( + const char *encoding, + const char *alternate_command + ); + +PyAPI_FUNC(PyObject *) _PyCodec_EncodeText( + PyObject *object, + const char *encoding, + const char *errors + ); + +PyAPI_FUNC(PyObject *) _PyCodec_DecodeText( + PyObject *object, + const char *encoding, + const char *errors + ); + +/* These two aren't actually text encoding specific, but _io.TextIOWrapper + * is the only current API consumer. + */ +PyAPI_FUNC(PyObject *) _PyCodecInfo_GetIncrementalDecoder( + PyObject *codec_info, + const char *errors + ); + +PyAPI_FUNC(PyObject *) _PyCodecInfo_GetIncrementalEncoder( + PyObject *codec_info, + const char *errors + ); +#endif + + + +/* --- Codec Lookup APIs -------------------------------------------------- + + All APIs return a codec object with incremented refcount and are + based on _PyCodec_Lookup(). The same comments w/r to the encoding + name also apply to these APIs. + +*/ + +/* Get an encoder function for the given encoding. */ + +PyAPI_FUNC(PyObject *) PyCodec_Encoder( + const char *encoding + ); + +/* Get a decoder function for the given encoding. */ + +PyAPI_FUNC(PyObject *) PyCodec_Decoder( + const char *encoding + ); + +/* Get an IncrementalEncoder object for the given encoding. */ + +PyAPI_FUNC(PyObject *) PyCodec_IncrementalEncoder( + const char *encoding, + const char *errors + ); + +/* Get an IncrementalDecoder object function for the given encoding. */ + +PyAPI_FUNC(PyObject *) PyCodec_IncrementalDecoder( + const char *encoding, + const char *errors + ); + +/* Get a StreamReader factory function for the given encoding. */ + +PyAPI_FUNC(PyObject *) PyCodec_StreamReader( + const char *encoding, + PyObject *stream, + const char *errors + ); + +/* Get a StreamWriter factory function for the given encoding. */ + +PyAPI_FUNC(PyObject *) PyCodec_StreamWriter( + const char *encoding, + PyObject *stream, + const char *errors + ); + +/* Unicode encoding error handling callback registry API */ + +/* Register the error handling callback function error under the given + name. This function will be called by the codec when it encounters + unencodable characters/undecodable bytes and doesn't know the + callback name, when name is specified as the error parameter + in the call to the encode/decode function. + Return 0 on success, -1 on error */ +PyAPI_FUNC(int) PyCodec_RegisterError(const char *name, PyObject *error); + +/* Lookup the error handling callback function registered under the given + name. As a special case NULL can be passed, in which case + the error handling callback for "strict" will be returned. */ +PyAPI_FUNC(PyObject *) PyCodec_LookupError(const char *name); + +/* raise exc as an exception */ +PyAPI_FUNC(PyObject *) PyCodec_StrictErrors(PyObject *exc); + +/* ignore the unicode error, skipping the faulty input */ +PyAPI_FUNC(PyObject *) PyCodec_IgnoreErrors(PyObject *exc); + +/* replace the unicode encode error with ? or U+FFFD */ +PyAPI_FUNC(PyObject *) PyCodec_ReplaceErrors(PyObject *exc); + +/* replace the unicode encode error with XML character references */ +PyAPI_FUNC(PyObject *) PyCodec_XMLCharRefReplaceErrors(PyObject *exc); + +/* replace the unicode encode error with backslash escapes (\x, \u and \U) */ +PyAPI_FUNC(PyObject *) PyCodec_BackslashReplaceErrors(PyObject *exc); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* replace the unicode encode error with backslash escapes (\N, \x, \u and \U) */ +PyAPI_FUNC(PyObject *) PyCodec_NameReplaceErrors(PyObject *exc); +#endif + +#ifndef Py_LIMITED_API +PyAPI_DATA(const char *) Py_hexdigits; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CODECREGISTRY_H */ diff --git a/winvenv/Include/compile.h b/winvenv/Include/compile.h new file mode 100644 index 0000000..edb961f --- /dev/null +++ b/winvenv/Include/compile.h @@ -0,0 +1,93 @@ +#ifndef Py_COMPILE_H +#define Py_COMPILE_H + +#ifndef Py_LIMITED_API +#include "code.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Public interface */ +struct _node; /* Declare the existence of this type */ +PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *); +/* XXX (ncoghlan): Unprefixed type name in a public API! */ + +#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \ + CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \ + CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \ + CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS) +#define PyCF_MASK_OBSOLETE (CO_NESTED) +#define PyCF_SOURCE_IS_UTF8 0x0100 +#define PyCF_DONT_IMPLY_DEDENT 0x0200 +#define PyCF_ONLY_AST 0x0400 +#define PyCF_IGNORE_COOKIE 0x0800 + +#ifndef Py_LIMITED_API +typedef struct { + int cf_flags; /* bitmask of CO_xxx flags relevant to future */ +} PyCompilerFlags; +#endif + +/* Future feature support */ + +typedef struct { + int ff_features; /* flags set by future statements */ + int ff_lineno; /* line number of last future statement */ +} PyFutureFeatures; + +#define FUTURE_NESTED_SCOPES "nested_scopes" +#define FUTURE_GENERATORS "generators" +#define FUTURE_DIVISION "division" +#define FUTURE_ABSOLUTE_IMPORT "absolute_import" +#define FUTURE_WITH_STATEMENT "with_statement" +#define FUTURE_PRINT_FUNCTION "print_function" +#define FUTURE_UNICODE_LITERALS "unicode_literals" +#define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL" +#define FUTURE_GENERATOR_STOP "generator_stop" +#define FUTURE_ANNOTATIONS "annotations" + +struct _mod; /* Declare the existence of this type */ +#define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar) +PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx( + struct _mod *mod, + const char *filename, /* decoded from the filesystem encoding */ + PyCompilerFlags *flags, + int optimize, + PyArena *arena); +PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject( + struct _mod *mod, + PyObject *filename, + PyCompilerFlags *flags, + int optimize, + PyArena *arena); +PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST( + struct _mod * mod, + const char *filename /* decoded from the filesystem encoding */ + ); +PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject( + struct _mod * mod, + PyObject *filename + ); + +/* _Py_Mangle is defined in compile.c */ +PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name); + +#define PY_INVALID_STACK_EFFECT INT_MAX +PyAPI_FUNC(int) PyCompile_OpcodeStackEffect(int opcode, int oparg); + +PyAPI_FUNC(int) _PyAST_Optimize(struct _mod *, PyArena *arena, int optimize); + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_LIMITED_API */ + +/* These definitions must match corresponding definitions in graminit.h. + There's code in compile.c that checks that they are the same. */ +#define Py_single_input 256 +#define Py_file_input 257 +#define Py_eval_input 258 + +#endif /* !Py_COMPILE_H */ diff --git a/winvenv/Include/complexobject.h b/winvenv/Include/complexobject.h new file mode 100644 index 0000000..cb8c52c --- /dev/null +++ b/winvenv/Include/complexobject.h @@ -0,0 +1,69 @@ +/* Complex number structure */ + +#ifndef Py_COMPLEXOBJECT_H +#define Py_COMPLEXOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +typedef struct { + double real; + double imag; +} Py_complex; + +/* Operations on complex numbers from complexmodule.c */ + +PyAPI_FUNC(Py_complex) _Py_c_sum(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_diff(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_neg(Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_prod(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_quot(Py_complex, Py_complex); +PyAPI_FUNC(Py_complex) _Py_c_pow(Py_complex, Py_complex); +PyAPI_FUNC(double) _Py_c_abs(Py_complex); +#endif + +/* Complex object interface */ + +/* +PyComplexObject represents a complex number with double-precision +real and imaginary parts. +*/ +#ifndef Py_LIMITED_API +typedef struct { + PyObject_HEAD + Py_complex cval; +} PyComplexObject; +#endif + +PyAPI_DATA(PyTypeObject) PyComplex_Type; + +#define PyComplex_Check(op) PyObject_TypeCheck(op, &PyComplex_Type) +#define PyComplex_CheckExact(op) (Py_TYPE(op) == &PyComplex_Type) + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyComplex_FromCComplex(Py_complex); +#endif +PyAPI_FUNC(PyObject *) PyComplex_FromDoubles(double real, double imag); + +PyAPI_FUNC(double) PyComplex_RealAsDouble(PyObject *op); +PyAPI_FUNC(double) PyComplex_ImagAsDouble(PyObject *op); +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_complex) PyComplex_AsCComplex(PyObject *op); +#endif + +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyComplex_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_COMPLEXOBJECT_H */ diff --git a/winvenv/Include/context.h b/winvenv/Include/context.h new file mode 100644 index 0000000..9581285 --- /dev/null +++ b/winvenv/Include/context.h @@ -0,0 +1,84 @@ +#ifndef Py_CONTEXT_H +#define Py_CONTEXT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API + + +PyAPI_DATA(PyTypeObject) PyContext_Type; +typedef struct _pycontextobject PyContext; + +PyAPI_DATA(PyTypeObject) PyContextVar_Type; +typedef struct _pycontextvarobject PyContextVar; + +PyAPI_DATA(PyTypeObject) PyContextToken_Type; +typedef struct _pycontexttokenobject PyContextToken; + + +#define PyContext_CheckExact(o) (Py_TYPE(o) == &PyContext_Type) +#define PyContextVar_CheckExact(o) (Py_TYPE(o) == &PyContextVar_Type) +#define PyContextToken_CheckExact(o) (Py_TYPE(o) == &PyContextToken_Type) + + +PyAPI_FUNC(PyObject *) PyContext_New(void); +PyAPI_FUNC(PyObject *) PyContext_Copy(PyObject *); +PyAPI_FUNC(PyObject *) PyContext_CopyCurrent(void); + +PyAPI_FUNC(int) PyContext_Enter(PyObject *); +PyAPI_FUNC(int) PyContext_Exit(PyObject *); + + +/* Create a new context variable. + + default_value can be NULL. +*/ +PyAPI_FUNC(PyObject *) PyContextVar_New( + const char *name, PyObject *default_value); + + +/* Get a value for the variable. + + Returns -1 if an error occurred during lookup. + + Returns 0 if value either was or was not found. + + If value was found, *value will point to it. + If not, it will point to: + + - default_value, if not NULL; + - the default value of "var", if not NULL; + - NULL. + + '*value' will be a new ref, if not NULL. +*/ +PyAPI_FUNC(int) PyContextVar_Get( + PyObject *var, PyObject *default_value, PyObject **value); + + +/* Set a new value for the variable. + Returns NULL if an error occurs. +*/ +PyAPI_FUNC(PyObject *) PyContextVar_Set(PyObject *var, PyObject *value); + + +/* Reset a variable to its previous value. + Returns 0 on success, -1 on error. +*/ +PyAPI_FUNC(int) PyContextVar_Reset(PyObject *var, PyObject *token); + + +/* This method is exposed only for CPython tests. Don not use it. */ +PyAPI_FUNC(PyObject *) _PyContext_NewHamtForTests(void); + + +PyAPI_FUNC(int) PyContext_ClearFreeList(void); + + +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CONTEXT_H */ diff --git a/winvenv/Include/datetime.h b/winvenv/Include/datetime.h new file mode 100644 index 0000000..059d5ec --- /dev/null +++ b/winvenv/Include/datetime.h @@ -0,0 +1,273 @@ +/* datetime.h + */ +#ifndef Py_LIMITED_API +#ifndef DATETIME_H +#define DATETIME_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Fields are packed into successive bytes, each viewed as unsigned and + * big-endian, unless otherwise noted: + * + * byte offset + * 0 year 2 bytes, 1-9999 + * 2 month 1 byte, 1-12 + * 3 day 1 byte, 1-31 + * 4 hour 1 byte, 0-23 + * 5 minute 1 byte, 0-59 + * 6 second 1 byte, 0-59 + * 7 usecond 3 bytes, 0-999999 + * 10 + */ + +/* # of bytes for year, month, and day. */ +#define _PyDateTime_DATE_DATASIZE 4 + +/* # of bytes for hour, minute, second, and usecond. */ +#define _PyDateTime_TIME_DATASIZE 6 + +/* # of bytes for year, month, day, hour, minute, second, and usecond. */ +#define _PyDateTime_DATETIME_DATASIZE 10 + + +typedef struct +{ + PyObject_HEAD + Py_hash_t hashcode; /* -1 when unknown */ + int days; /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */ + int seconds; /* 0 <= seconds < 24*3600 is invariant */ + int microseconds; /* 0 <= microseconds < 1000000 is invariant */ +} PyDateTime_Delta; + +typedef struct +{ + PyObject_HEAD /* a pure abstract base class */ +} PyDateTime_TZInfo; + + +/* The datetime and time types have hashcodes, and an optional tzinfo member, + * present if and only if hastzinfo is true. + */ +#define _PyTZINFO_HEAD \ + PyObject_HEAD \ + Py_hash_t hashcode; \ + char hastzinfo; /* boolean flag */ + +/* No _PyDateTime_BaseTZInfo is allocated; it's just to have something + * convenient to cast to, when getting at the hastzinfo member of objects + * starting with _PyTZINFO_HEAD. + */ +typedef struct +{ + _PyTZINFO_HEAD +} _PyDateTime_BaseTZInfo; + +/* All time objects are of PyDateTime_TimeType, but that can be allocated + * in two ways, with or without a tzinfo member. Without is the same as + * tzinfo == None, but consumes less memory. _PyDateTime_BaseTime is an + * internal struct used to allocate the right amount of space for the + * "without" case. + */ +#define _PyDateTime_TIMEHEAD \ + _PyTZINFO_HEAD \ + unsigned char data[_PyDateTime_TIME_DATASIZE]; + +typedef struct +{ + _PyDateTime_TIMEHEAD +} _PyDateTime_BaseTime; /* hastzinfo false */ + +typedef struct +{ + _PyDateTime_TIMEHEAD + unsigned char fold; + PyObject *tzinfo; +} PyDateTime_Time; /* hastzinfo true */ + + +/* All datetime objects are of PyDateTime_DateTimeType, but that can be + * allocated in two ways too, just like for time objects above. In addition, + * the plain date type is a base class for datetime, so it must also have + * a hastzinfo member (although it's unused there). + */ +typedef struct +{ + _PyTZINFO_HEAD + unsigned char data[_PyDateTime_DATE_DATASIZE]; +} PyDateTime_Date; + +#define _PyDateTime_DATETIMEHEAD \ + _PyTZINFO_HEAD \ + unsigned char data[_PyDateTime_DATETIME_DATASIZE]; + +typedef struct +{ + _PyDateTime_DATETIMEHEAD +} _PyDateTime_BaseDateTime; /* hastzinfo false */ + +typedef struct +{ + _PyDateTime_DATETIMEHEAD + unsigned char fold; + PyObject *tzinfo; +} PyDateTime_DateTime; /* hastzinfo true */ + + +/* Apply for date and datetime instances. */ +#define PyDateTime_GET_YEAR(o) ((((PyDateTime_Date*)o)->data[0] << 8) | \ + ((PyDateTime_Date*)o)->data[1]) +#define PyDateTime_GET_MONTH(o) (((PyDateTime_Date*)o)->data[2]) +#define PyDateTime_GET_DAY(o) (((PyDateTime_Date*)o)->data[3]) + +#define PyDateTime_DATE_GET_HOUR(o) (((PyDateTime_DateTime*)o)->data[4]) +#define PyDateTime_DATE_GET_MINUTE(o) (((PyDateTime_DateTime*)o)->data[5]) +#define PyDateTime_DATE_GET_SECOND(o) (((PyDateTime_DateTime*)o)->data[6]) +#define PyDateTime_DATE_GET_MICROSECOND(o) \ + ((((PyDateTime_DateTime*)o)->data[7] << 16) | \ + (((PyDateTime_DateTime*)o)->data[8] << 8) | \ + ((PyDateTime_DateTime*)o)->data[9]) +#define PyDateTime_DATE_GET_FOLD(o) (((PyDateTime_DateTime*)o)->fold) + +/* Apply for time instances. */ +#define PyDateTime_TIME_GET_HOUR(o) (((PyDateTime_Time*)o)->data[0]) +#define PyDateTime_TIME_GET_MINUTE(o) (((PyDateTime_Time*)o)->data[1]) +#define PyDateTime_TIME_GET_SECOND(o) (((PyDateTime_Time*)o)->data[2]) +#define PyDateTime_TIME_GET_MICROSECOND(o) \ + ((((PyDateTime_Time*)o)->data[3] << 16) | \ + (((PyDateTime_Time*)o)->data[4] << 8) | \ + ((PyDateTime_Time*)o)->data[5]) +#define PyDateTime_TIME_GET_FOLD(o) (((PyDateTime_Time*)o)->fold) + +/* Apply for time delta instances */ +#define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) +#define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) +#define PyDateTime_DELTA_GET_MICROSECONDS(o) \ + (((PyDateTime_Delta*)o)->microseconds) + + +/* Define structure for C API. */ +typedef struct { + /* type objects */ + PyTypeObject *DateType; + PyTypeObject *DateTimeType; + PyTypeObject *TimeType; + PyTypeObject *DeltaType; + PyTypeObject *TZInfoType; + + /* singletons */ + PyObject *TimeZone_UTC; + + /* constructors */ + PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*); + PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, + PyObject*, PyTypeObject*); + PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*); + PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*); + PyObject *(*TimeZone_FromTimeZone)(PyObject *offset, PyObject *name); + + /* constructors for the DB API */ + PyObject *(*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*); + PyObject *(*Date_FromTimestamp)(PyObject*, PyObject*); + + /* PEP 495 constructors */ + PyObject *(*DateTime_FromDateAndTimeAndFold)(int, int, int, int, int, int, int, + PyObject*, int, PyTypeObject*); + PyObject *(*Time_FromTimeAndFold)(int, int, int, int, PyObject*, int, PyTypeObject*); + +} PyDateTime_CAPI; + +#define PyDateTime_CAPSULE_NAME "datetime.datetime_CAPI" + + +#ifdef Py_BUILD_CORE + +/* Macros for type checking when building the Python core. */ +#define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType) +#define PyDate_CheckExact(op) (Py_TYPE(op) == &PyDateTime_DateType) + +#define PyDateTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateTimeType) +#define PyDateTime_CheckExact(op) (Py_TYPE(op) == &PyDateTime_DateTimeType) + +#define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType) +#define PyTime_CheckExact(op) (Py_TYPE(op) == &PyDateTime_TimeType) + +#define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType) +#define PyDelta_CheckExact(op) (Py_TYPE(op) == &PyDateTime_DeltaType) + +#define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType) +#define PyTZInfo_CheckExact(op) (Py_TYPE(op) == &PyDateTime_TZInfoType) + +#else + +/* Define global variable for the C API and a macro for setting it. */ +static PyDateTime_CAPI *PyDateTimeAPI = NULL; + +#define PyDateTime_IMPORT \ + PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0) + +/* Macro for access to the UTC singleton */ +#define PyDateTime_TimeZone_UTC PyDateTimeAPI->TimeZone_UTC + +/* Macros for type checking when not building the Python core. */ +#define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType) +#define PyDate_CheckExact(op) (Py_TYPE(op) == PyDateTimeAPI->DateType) + +#define PyDateTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateTimeType) +#define PyDateTime_CheckExact(op) (Py_TYPE(op) == PyDateTimeAPI->DateTimeType) + +#define PyTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TimeType) +#define PyTime_CheckExact(op) (Py_TYPE(op) == PyDateTimeAPI->TimeType) + +#define PyDelta_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DeltaType) +#define PyDelta_CheckExact(op) (Py_TYPE(op) == PyDateTimeAPI->DeltaType) + +#define PyTZInfo_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TZInfoType) +#define PyTZInfo_CheckExact(op) (Py_TYPE(op) == PyDateTimeAPI->TZInfoType) + +/* Macros for accessing constructors in a simplified fashion. */ +#define PyDate_FromDate(year, month, day) \ + PyDateTimeAPI->Date_FromDate(year, month, day, PyDateTimeAPI->DateType) + +#define PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, usec) \ + PyDateTimeAPI->DateTime_FromDateAndTime(year, month, day, hour, \ + min, sec, usec, Py_None, PyDateTimeAPI->DateTimeType) + +#define PyDateTime_FromDateAndTimeAndFold(year, month, day, hour, min, sec, usec, fold) \ + PyDateTimeAPI->DateTime_FromDateAndTimeAndFold(year, month, day, hour, \ + min, sec, usec, Py_None, fold, PyDateTimeAPI->DateTimeType) + +#define PyTime_FromTime(hour, minute, second, usecond) \ + PyDateTimeAPI->Time_FromTime(hour, minute, second, usecond, \ + Py_None, PyDateTimeAPI->TimeType) + +#define PyTime_FromTimeAndFold(hour, minute, second, usecond, fold) \ + PyDateTimeAPI->Time_FromTimeAndFold(hour, minute, second, usecond, \ + Py_None, fold, PyDateTimeAPI->TimeType) + +#define PyDelta_FromDSU(days, seconds, useconds) \ + PyDateTimeAPI->Delta_FromDelta(days, seconds, useconds, 1, \ + PyDateTimeAPI->DeltaType) + +#define PyTimeZone_FromOffset(offset) \ + PyDateTimeAPI->TimeZone_FromTimeZone(offset, NULL) + +#define PyTimeZone_FromOffsetAndName(offset, name) \ + PyDateTimeAPI->TimeZone_FromTimeZone(offset, name) + +/* Macros supporting the DB API. */ +#define PyDateTime_FromTimestamp(args) \ + PyDateTimeAPI->DateTime_FromTimestamp( \ + (PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL) + +#define PyDate_FromTimestamp(args) \ + PyDateTimeAPI->Date_FromTimestamp( \ + (PyObject*) (PyDateTimeAPI->DateType), args) + +#endif /* Py_BUILD_CORE */ + +#ifdef __cplusplus +} +#endif +#endif +#endif /* !Py_LIMITED_API */ diff --git a/winvenv/Include/descrobject.h b/winvenv/Include/descrobject.h new file mode 100644 index 0000000..73bbb3f --- /dev/null +++ b/winvenv/Include/descrobject.h @@ -0,0 +1,110 @@ +/* Descriptors */ +#ifndef Py_DESCROBJECT_H +#define Py_DESCROBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef PyObject *(*getter)(PyObject *, void *); +typedef int (*setter)(PyObject *, PyObject *, void *); + +typedef struct PyGetSetDef { + const char *name; + getter get; + setter set; + const char *doc; + void *closure; +} PyGetSetDef; + +#ifndef Py_LIMITED_API +typedef PyObject *(*wrapperfunc)(PyObject *self, PyObject *args, + void *wrapped); + +typedef PyObject *(*wrapperfunc_kwds)(PyObject *self, PyObject *args, + void *wrapped, PyObject *kwds); + +struct wrapperbase { + const char *name; + int offset; + void *function; + wrapperfunc wrapper; + const char *doc; + int flags; + PyObject *name_strobj; +}; + +/* Flags for above struct */ +#define PyWrapperFlag_KEYWORDS 1 /* wrapper function takes keyword args */ + +/* Various kinds of descriptor objects */ + +typedef struct { + PyObject_HEAD + PyTypeObject *d_type; + PyObject *d_name; + PyObject *d_qualname; +} PyDescrObject; + +#define PyDescr_COMMON PyDescrObject d_common + +#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) +#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) + +typedef struct { + PyDescr_COMMON; + PyMethodDef *d_method; +} PyMethodDescrObject; + +typedef struct { + PyDescr_COMMON; + struct PyMemberDef *d_member; +} PyMemberDescrObject; + +typedef struct { + PyDescr_COMMON; + PyGetSetDef *d_getset; +} PyGetSetDescrObject; + +typedef struct { + PyDescr_COMMON; + struct wrapperbase *d_base; + void *d_wrapped; /* This can be any function pointer */ +} PyWrapperDescrObject; +#endif /* Py_LIMITED_API */ + +PyAPI_DATA(PyTypeObject) PyClassMethodDescr_Type; +PyAPI_DATA(PyTypeObject) PyGetSetDescr_Type; +PyAPI_DATA(PyTypeObject) PyMemberDescr_Type; +PyAPI_DATA(PyTypeObject) PyMethodDescr_Type; +PyAPI_DATA(PyTypeObject) PyWrapperDescr_Type; +PyAPI_DATA(PyTypeObject) PyDictProxy_Type; +#ifndef Py_LIMITED_API +PyAPI_DATA(PyTypeObject) _PyMethodWrapper_Type; +#endif /* Py_LIMITED_API */ + +PyAPI_FUNC(PyObject *) PyDescr_NewMethod(PyTypeObject *, PyMethodDef *); +PyAPI_FUNC(PyObject *) PyDescr_NewClassMethod(PyTypeObject *, PyMethodDef *); +struct PyMemberDef; /* forward declaration for following prototype */ +PyAPI_FUNC(PyObject *) PyDescr_NewMember(PyTypeObject *, + struct PyMemberDef *); +PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, + struct PyGetSetDef *); +#ifndef Py_LIMITED_API + +PyAPI_FUNC(PyObject *) _PyMethodDescr_FastCallKeywords( + PyObject *descrobj, PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames); +PyAPI_FUNC(PyObject *) PyDescr_NewWrapper(PyTypeObject *, + struct wrapperbase *, void *); +#define PyDescr_IsData(d) (Py_TYPE(d)->tp_descr_set != NULL) +#endif + +PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *); +PyAPI_FUNC(PyObject *) PyWrapper_New(PyObject *, PyObject *); + + +PyAPI_DATA(PyTypeObject) PyProperty_Type; +#ifdef __cplusplus +} +#endif +#endif /* !Py_DESCROBJECT_H */ + diff --git a/winvenv/Include/dictobject.h b/winvenv/Include/dictobject.h new file mode 100644 index 0000000..28930f4 --- /dev/null +++ b/winvenv/Include/dictobject.h @@ -0,0 +1,179 @@ +#ifndef Py_DICTOBJECT_H +#define Py_DICTOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Dictionary object type -- mapping from hashable object to object */ + +/* The distribution includes a separate file, Objects/dictnotes.txt, + describing explorations into dictionary design and optimization. + It covers typical dictionary use patterns, the parameters for + tuning dictionaries, and several ideas for possible optimizations. +*/ + +#ifndef Py_LIMITED_API + +typedef struct _dictkeysobject PyDictKeysObject; + +/* The ma_values pointer is NULL for a combined table + * or points to an array of PyObject* for a split table + */ +typedef struct { + PyObject_HEAD + + /* Number of items in the dictionary */ + Py_ssize_t ma_used; + + /* Dictionary version: globally unique, value change each time + the dictionary is modified */ + uint64_t ma_version_tag; + + PyDictKeysObject *ma_keys; + + /* If ma_values is NULL, the table is "combined": keys and values + are stored in ma_keys. + + If ma_values is not NULL, the table is splitted: + keys are stored in ma_keys and values are stored in ma_values */ + PyObject **ma_values; +} PyDictObject; + +typedef struct { + PyObject_HEAD + PyDictObject *dv_dict; +} _PyDictViewObject; + +#endif /* Py_LIMITED_API */ + +PyAPI_DATA(PyTypeObject) PyDict_Type; +PyAPI_DATA(PyTypeObject) PyDictIterKey_Type; +PyAPI_DATA(PyTypeObject) PyDictIterValue_Type; +PyAPI_DATA(PyTypeObject) PyDictIterItem_Type; +PyAPI_DATA(PyTypeObject) PyDictKeys_Type; +PyAPI_DATA(PyTypeObject) PyDictItems_Type; +PyAPI_DATA(PyTypeObject) PyDictValues_Type; + +#define PyDict_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) +#define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) +#define PyDictKeys_Check(op) PyObject_TypeCheck(op, &PyDictKeys_Type) +#define PyDictItems_Check(op) PyObject_TypeCheck(op, &PyDictItems_Type) +#define PyDictValues_Check(op) PyObject_TypeCheck(op, &PyDictValues_Type) +/* This excludes Values, since they are not sets. */ +# define PyDictViewSet_Check(op) \ + (PyDictKeys_Check(op) || PyDictItems_Check(op)) + + +PyAPI_FUNC(PyObject *) PyDict_New(void); +PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key, + Py_hash_t hash); +#endif +PyAPI_FUNC(PyObject *) PyDict_GetItemWithError(PyObject *mp, PyObject *key); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp, + struct _Py_Identifier *key); +PyAPI_FUNC(PyObject *) PyDict_SetDefault( + PyObject *mp, PyObject *key, PyObject *defaultobj); +#endif +PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key, + PyObject *item, Py_hash_t hash); +#endif +PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key, + Py_hash_t hash); +PyAPI_FUNC(int) _PyDict_DelItemIf(PyObject *mp, PyObject *key, + int (*predicate)(PyObject *value)); +#endif +PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); +PyAPI_FUNC(int) PyDict_Next( + PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value); +#ifndef Py_LIMITED_API +PyDictKeysObject *_PyDict_NewKeysForClass(void); +PyAPI_FUNC(PyObject *) PyObject_GenericGetDict(PyObject *, void *); +PyAPI_FUNC(int) _PyDict_Next( + PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash); +PyObject *_PyDictView_New(PyObject *, PyTypeObject *); +#endif +PyAPI_FUNC(PyObject *) PyDict_Keys(PyObject *mp); +PyAPI_FUNC(PyObject *) PyDict_Values(PyObject *mp); +PyAPI_FUNC(PyObject *) PyDict_Items(PyObject *mp); +PyAPI_FUNC(Py_ssize_t) PyDict_Size(PyObject *mp); +PyAPI_FUNC(PyObject *) PyDict_Copy(PyObject *mp); +PyAPI_FUNC(int) PyDict_Contains(PyObject *mp, PyObject *key); +#ifndef Py_LIMITED_API +/* Get the number of items of a dictionary. */ +#define PyDict_GET_SIZE(mp) (assert(PyDict_Check(mp)),((PyDictObject *)mp)->ma_used) +PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, Py_hash_t hash); +PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused); +PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp); +PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp); +Py_ssize_t _PyDict_KeysSize(PyDictKeysObject *keys); +PyAPI_FUNC(Py_ssize_t) _PyDict_SizeOf(PyDictObject *); +PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *, PyObject *, PyObject *); +PyObject *_PyDict_Pop_KnownHash(PyObject *, PyObject *, Py_hash_t, PyObject *); +PyObject *_PyDict_FromKeys(PyObject *, PyObject *, PyObject *); +#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL) + +PyAPI_FUNC(int) PyDict_ClearFreeList(void); +#endif + +/* PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */ +PyAPI_FUNC(int) PyDict_Update(PyObject *mp, PyObject *other); + +/* PyDict_Merge updates/merges from a mapping object (an object that + supports PyMapping_Keys() and PyObject_GetItem()). If override is true, + the last occurrence of a key wins, else the first. The Python + dict.update(other) is equivalent to PyDict_Merge(dict, other, 1). +*/ +PyAPI_FUNC(int) PyDict_Merge(PyObject *mp, + PyObject *other, + int override); + +#ifndef Py_LIMITED_API +/* Like PyDict_Merge, but override can be 0, 1 or 2. If override is 0, + the first occurrence of a key wins, if override is 1, the last occurrence + of a key wins, if override is 2, a KeyError with conflicting key as + argument is raised. +*/ +PyAPI_FUNC(int) _PyDict_MergeEx(PyObject *mp, PyObject *other, int override); +PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other); +#endif + +/* PyDict_MergeFromSeq2 updates/merges from an iterable object producing + iterable objects of length 2. If override is true, the last occurrence + of a key wins, else the first. The Python dict constructor dict(seq2) + is equivalent to dict={}; PyDict_MergeFromSeq(dict, seq2, 1). +*/ +PyAPI_FUNC(int) PyDict_MergeFromSeq2(PyObject *d, + PyObject *seq2, + int override); + +PyAPI_FUNC(PyObject *) PyDict_GetItemString(PyObject *dp, const char *key); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyDict_GetItemId(PyObject *dp, struct _Py_Identifier *key); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyDict_SetItemId(PyObject *dp, struct _Py_Identifier *key, PyObject *item); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyDict_DelItemId(PyObject *mp, struct _Py_Identifier *key); +PyAPI_FUNC(void) _PyDict_DebugMallocStats(FILE *out); + +int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value); +PyObject *_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_DICTOBJECT_H */ diff --git a/winvenv/Include/dtoa.h b/winvenv/Include/dtoa.h new file mode 100644 index 0000000..9bfb625 --- /dev/null +++ b/winvenv/Include/dtoa.h @@ -0,0 +1,19 @@ +#ifndef Py_LIMITED_API +#ifndef PY_NO_SHORT_FLOAT_REPR +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr); +PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits, + int *decpt, int *sign, char **rve); +PyAPI_FUNC(void) _Py_dg_freedtoa(char *s); +PyAPI_FUNC(double) _Py_dg_stdnan(int sign); +PyAPI_FUNC(double) _Py_dg_infinity(int sign); + + +#ifdef __cplusplus +} +#endif +#endif +#endif diff --git a/winvenv/Include/dynamic_annotations.h b/winvenv/Include/dynamic_annotations.h new file mode 100644 index 0000000..0bd1a83 --- /dev/null +++ b/winvenv/Include/dynamic_annotations.h @@ -0,0 +1,499 @@ +/* Copyright (c) 2008-2009, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Neither the name of Google Inc. 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 + * OWNER 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. + * + * --- + * Author: Kostya Serebryany + * Copied to CPython by Jeffrey Yasskin, with all macros renamed to + * start with _Py_ to avoid colliding with users embedding Python, and + * with deprecated macros removed. + */ + +/* This file defines dynamic annotations for use with dynamic analysis + tool such as valgrind, PIN, etc. + + Dynamic annotation is a source code annotation that affects + the generated code (that is, the annotation is not a comment). + Each such annotation is attached to a particular + instruction and/or to a particular object (address) in the program. + + The annotations that should be used by users are macros in all upper-case + (e.g., _Py_ANNOTATE_NEW_MEMORY). + + Actual implementation of these macros may differ depending on the + dynamic analysis tool being used. + + See http://code.google.com/p/data-race-test/ for more information. + + This file supports the following dynamic analysis tools: + - None (DYNAMIC_ANNOTATIONS_ENABLED is not defined or zero). + Macros are defined empty. + - ThreadSanitizer, Helgrind, DRD (DYNAMIC_ANNOTATIONS_ENABLED is 1). + Macros are defined as calls to non-inlinable empty functions + that are intercepted by Valgrind. */ + +#ifndef __DYNAMIC_ANNOTATIONS_H__ +#define __DYNAMIC_ANNOTATIONS_H__ + +#ifndef DYNAMIC_ANNOTATIONS_ENABLED +# define DYNAMIC_ANNOTATIONS_ENABLED 0 +#endif + +#if DYNAMIC_ANNOTATIONS_ENABLED != 0 + + /* ------------------------------------------------------------- + Annotations useful when implementing condition variables such as CondVar, + using conditional critical sections (Await/LockWhen) and when constructing + user-defined synchronization mechanisms. + + The annotations _Py_ANNOTATE_HAPPENS_BEFORE() and + _Py_ANNOTATE_HAPPENS_AFTER() can be used to define happens-before arcs in + user-defined synchronization mechanisms: the race detector will infer an + arc from the former to the latter when they share the same argument + pointer. + + Example 1 (reference counting): + + void Unref() { + _Py_ANNOTATE_HAPPENS_BEFORE(&refcount_); + if (AtomicDecrementByOne(&refcount_) == 0) { + _Py_ANNOTATE_HAPPENS_AFTER(&refcount_); + delete this; + } + } + + Example 2 (message queue): + + void MyQueue::Put(Type *e) { + MutexLock lock(&mu_); + _Py_ANNOTATE_HAPPENS_BEFORE(e); + PutElementIntoMyQueue(e); + } + + Type *MyQueue::Get() { + MutexLock lock(&mu_); + Type *e = GetElementFromMyQueue(); + _Py_ANNOTATE_HAPPENS_AFTER(e); + return e; + } + + Note: when possible, please use the existing reference counting and message + queue implementations instead of inventing new ones. */ + + /* Report that wait on the condition variable at address "cv" has succeeded + and the lock at address "lock" is held. */ +#define _Py_ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \ + AnnotateCondVarWait(__FILE__, __LINE__, cv, lock) + + /* Report that wait on the condition variable at "cv" has succeeded. Variant + w/o lock. */ +#define _Py_ANNOTATE_CONDVAR_WAIT(cv) \ + AnnotateCondVarWait(__FILE__, __LINE__, cv, NULL) + + /* Report that we are about to signal on the condition variable at address + "cv". */ +#define _Py_ANNOTATE_CONDVAR_SIGNAL(cv) \ + AnnotateCondVarSignal(__FILE__, __LINE__, cv) + + /* Report that we are about to signal_all on the condition variable at "cv". */ +#define _Py_ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \ + AnnotateCondVarSignalAll(__FILE__, __LINE__, cv) + + /* Annotations for user-defined synchronization mechanisms. */ +#define _Py_ANNOTATE_HAPPENS_BEFORE(obj) _Py_ANNOTATE_CONDVAR_SIGNAL(obj) +#define _Py_ANNOTATE_HAPPENS_AFTER(obj) _Py_ANNOTATE_CONDVAR_WAIT(obj) + + /* Report that the bytes in the range [pointer, pointer+size) are about + to be published safely. The race checker will create a happens-before + arc from the call _Py_ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to + subsequent accesses to this memory. + Note: this annotation may not work properly if the race detector uses + sampling, i.e. does not observe all memory accesses. + */ +#define _Py_ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \ + AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size) + + /* Instruct the tool to create a happens-before arc between mu->Unlock() and + mu->Lock(). This annotation may slow down the race detector and hide real + races. Normally it is used only when it would be difficult to annotate each + of the mutex's critical sections individually using the annotations above. + This annotation makes sense only for hybrid race detectors. For pure + happens-before detectors this is a no-op. For more details see + http://code.google.com/p/data-race-test/wiki/PureHappensBeforeVsHybrid . */ +#define _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) \ + AnnotateMutexIsUsedAsCondVar(__FILE__, __LINE__, mu) + + /* ------------------------------------------------------------- + Annotations useful when defining memory allocators, or when memory that + was protected in one way starts to be protected in another. */ + + /* Report that a new memory at "address" of size "size" has been allocated. + This might be used when the memory has been retrieved from a free list and + is about to be reused, or when the locking discipline for a variable + changes. */ +#define _Py_ANNOTATE_NEW_MEMORY(address, size) \ + AnnotateNewMemory(__FILE__, __LINE__, address, size) + + /* ------------------------------------------------------------- + Annotations useful when defining FIFO queues that transfer data between + threads. */ + + /* Report that the producer-consumer queue (such as ProducerConsumerQueue) at + address "pcq" has been created. The _Py_ANNOTATE_PCQ_* annotations should + be used only for FIFO queues. For non-FIFO queues use + _Py_ANNOTATE_HAPPENS_BEFORE (for put) and _Py_ANNOTATE_HAPPENS_AFTER (for + get). */ +#define _Py_ANNOTATE_PCQ_CREATE(pcq) \ + AnnotatePCQCreate(__FILE__, __LINE__, pcq) + + /* Report that the queue at address "pcq" is about to be destroyed. */ +#define _Py_ANNOTATE_PCQ_DESTROY(pcq) \ + AnnotatePCQDestroy(__FILE__, __LINE__, pcq) + + /* Report that we are about to put an element into a FIFO queue at address + "pcq". */ +#define _Py_ANNOTATE_PCQ_PUT(pcq) \ + AnnotatePCQPut(__FILE__, __LINE__, pcq) + + /* Report that we've just got an element from a FIFO queue at address "pcq". */ +#define _Py_ANNOTATE_PCQ_GET(pcq) \ + AnnotatePCQGet(__FILE__, __LINE__, pcq) + + /* ------------------------------------------------------------- + Annotations that suppress errors. It is usually better to express the + program's synchronization using the other annotations, but these can + be used when all else fails. */ + + /* Report that we may have a benign race at "pointer", with size + "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the + point where "pointer" has been allocated, preferably close to the point + where the race happens. See also _Py_ANNOTATE_BENIGN_RACE_STATIC. */ +#define _Py_ANNOTATE_BENIGN_RACE(pointer, description) \ + AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \ + sizeof(*(pointer)), description) + + /* Same as _Py_ANNOTATE_BENIGN_RACE(address, description), but applies to + the memory range [address, address+size). */ +#define _Py_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \ + AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description) + + /* Request the analysis tool to ignore all reads in the current thread + until _Py_ANNOTATE_IGNORE_READS_END is called. + Useful to ignore intentional racey reads, while still checking + other reads and all writes. + See also _Py_ANNOTATE_UNPROTECTED_READ. */ +#define _Py_ANNOTATE_IGNORE_READS_BEGIN() \ + AnnotateIgnoreReadsBegin(__FILE__, __LINE__) + + /* Stop ignoring reads. */ +#define _Py_ANNOTATE_IGNORE_READS_END() \ + AnnotateIgnoreReadsEnd(__FILE__, __LINE__) + + /* Similar to _Py_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */ +#define _Py_ANNOTATE_IGNORE_WRITES_BEGIN() \ + AnnotateIgnoreWritesBegin(__FILE__, __LINE__) + + /* Stop ignoring writes. */ +#define _Py_ANNOTATE_IGNORE_WRITES_END() \ + AnnotateIgnoreWritesEnd(__FILE__, __LINE__) + + /* Start ignoring all memory accesses (reads and writes). */ +#define _Py_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \ + do {\ + _Py_ANNOTATE_IGNORE_READS_BEGIN();\ + _Py_ANNOTATE_IGNORE_WRITES_BEGIN();\ + }while(0)\ + + /* Stop ignoring all memory accesses. */ +#define _Py_ANNOTATE_IGNORE_READS_AND_WRITES_END() \ + do {\ + _Py_ANNOTATE_IGNORE_WRITES_END();\ + _Py_ANNOTATE_IGNORE_READS_END();\ + }while(0)\ + + /* Similar to _Py_ANNOTATE_IGNORE_READS_BEGIN, but ignore synchronization events: + RWLOCK* and CONDVAR*. */ +#define _Py_ANNOTATE_IGNORE_SYNC_BEGIN() \ + AnnotateIgnoreSyncBegin(__FILE__, __LINE__) + + /* Stop ignoring sync events. */ +#define _Py_ANNOTATE_IGNORE_SYNC_END() \ + AnnotateIgnoreSyncEnd(__FILE__, __LINE__) + + + /* Enable (enable!=0) or disable (enable==0) race detection for all threads. + This annotation could be useful if you want to skip expensive race analysis + during some period of program execution, e.g. during initialization. */ +#define _Py_ANNOTATE_ENABLE_RACE_DETECTION(enable) \ + AnnotateEnableRaceDetection(__FILE__, __LINE__, enable) + + /* ------------------------------------------------------------- + Annotations useful for debugging. */ + + /* Request to trace every access to "address". */ +#define _Py_ANNOTATE_TRACE_MEMORY(address) \ + AnnotateTraceMemory(__FILE__, __LINE__, address) + + /* Report the current thread name to a race detector. */ +#define _Py_ANNOTATE_THREAD_NAME(name) \ + AnnotateThreadName(__FILE__, __LINE__, name) + + /* ------------------------------------------------------------- + Annotations useful when implementing locks. They are not + normally needed by modules that merely use locks. + The "lock" argument is a pointer to the lock object. */ + + /* Report that a lock has been created at address "lock". */ +#define _Py_ANNOTATE_RWLOCK_CREATE(lock) \ + AnnotateRWLockCreate(__FILE__, __LINE__, lock) + + /* Report that the lock at address "lock" is about to be destroyed. */ +#define _Py_ANNOTATE_RWLOCK_DESTROY(lock) \ + AnnotateRWLockDestroy(__FILE__, __LINE__, lock) + + /* Report that the lock at address "lock" has been acquired. + is_w=1 for writer lock, is_w=0 for reader lock. */ +#define _Py_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \ + AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w) + + /* Report that the lock at address "lock" is about to be released. */ +#define _Py_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \ + AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w) + + /* ------------------------------------------------------------- + Annotations useful when implementing barriers. They are not + normally needed by modules that merely use barriers. + The "barrier" argument is a pointer to the barrier object. */ + + /* Report that the "barrier" has been initialized with initial "count". + If 'reinitialization_allowed' is true, initialization is allowed to happen + multiple times w/o calling barrier_destroy() */ +#define _Py_ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) \ + AnnotateBarrierInit(__FILE__, __LINE__, barrier, count, \ + reinitialization_allowed) + + /* Report that we are about to enter barrier_wait("barrier"). */ +#define _Py_ANNOTATE_BARRIER_WAIT_BEFORE(barrier) \ + AnnotateBarrierWaitBefore(__FILE__, __LINE__, barrier) + + /* Report that we just exited barrier_wait("barrier"). */ +#define _Py_ANNOTATE_BARRIER_WAIT_AFTER(barrier) \ + AnnotateBarrierWaitAfter(__FILE__, __LINE__, barrier) + + /* Report that the "barrier" has been destroyed. */ +#define _Py_ANNOTATE_BARRIER_DESTROY(barrier) \ + AnnotateBarrierDestroy(__FILE__, __LINE__, barrier) + + /* ------------------------------------------------------------- + Annotations useful for testing race detectors. */ + + /* Report that we expect a race on the variable at "address". + Use only in unit tests for a race detector. */ +#define _Py_ANNOTATE_EXPECT_RACE(address, description) \ + AnnotateExpectRace(__FILE__, __LINE__, address, description) + + /* A no-op. Insert where you like to test the interceptors. */ +#define _Py_ANNOTATE_NO_OP(arg) \ + AnnotateNoOp(__FILE__, __LINE__, arg) + + /* Force the race detector to flush its state. The actual effect depends on + * the implementation of the detector. */ +#define _Py_ANNOTATE_FLUSH_STATE() \ + AnnotateFlushState(__FILE__, __LINE__) + + +#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */ + +#define _Py_ANNOTATE_RWLOCK_CREATE(lock) /* empty */ +#define _Py_ANNOTATE_RWLOCK_DESTROY(lock) /* empty */ +#define _Py_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */ +#define _Py_ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */ +#define _Py_ANNOTATE_BARRIER_INIT(barrier, count, reinitialization_allowed) /* */ +#define _Py_ANNOTATE_BARRIER_WAIT_BEFORE(barrier) /* empty */ +#define _Py_ANNOTATE_BARRIER_WAIT_AFTER(barrier) /* empty */ +#define _Py_ANNOTATE_BARRIER_DESTROY(barrier) /* empty */ +#define _Py_ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) /* empty */ +#define _Py_ANNOTATE_CONDVAR_WAIT(cv) /* empty */ +#define _Py_ANNOTATE_CONDVAR_SIGNAL(cv) /* empty */ +#define _Py_ANNOTATE_CONDVAR_SIGNAL_ALL(cv) /* empty */ +#define _Py_ANNOTATE_HAPPENS_BEFORE(obj) /* empty */ +#define _Py_ANNOTATE_HAPPENS_AFTER(obj) /* empty */ +#define _Py_ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) /* empty */ +#define _Py_ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) /* empty */ +#define _Py_ANNOTATE_SWAP_MEMORY_RANGE(address, size) /* empty */ +#define _Py_ANNOTATE_PCQ_CREATE(pcq) /* empty */ +#define _Py_ANNOTATE_PCQ_DESTROY(pcq) /* empty */ +#define _Py_ANNOTATE_PCQ_PUT(pcq) /* empty */ +#define _Py_ANNOTATE_PCQ_GET(pcq) /* empty */ +#define _Py_ANNOTATE_NEW_MEMORY(address, size) /* empty */ +#define _Py_ANNOTATE_EXPECT_RACE(address, description) /* empty */ +#define _Py_ANNOTATE_BENIGN_RACE(address, description) /* empty */ +#define _Py_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */ +#define _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(mu) /* empty */ +#define _Py_ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) /* empty */ +#define _Py_ANNOTATE_TRACE_MEMORY(arg) /* empty */ +#define _Py_ANNOTATE_THREAD_NAME(name) /* empty */ +#define _Py_ANNOTATE_IGNORE_READS_BEGIN() /* empty */ +#define _Py_ANNOTATE_IGNORE_READS_END() /* empty */ +#define _Py_ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */ +#define _Py_ANNOTATE_IGNORE_WRITES_END() /* empty */ +#define _Py_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */ +#define _Py_ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */ +#define _Py_ANNOTATE_IGNORE_SYNC_BEGIN() /* empty */ +#define _Py_ANNOTATE_IGNORE_SYNC_END() /* empty */ +#define _Py_ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */ +#define _Py_ANNOTATE_NO_OP(arg) /* empty */ +#define _Py_ANNOTATE_FLUSH_STATE() /* empty */ + +#endif /* DYNAMIC_ANNOTATIONS_ENABLED */ + +/* Use the macros above rather than using these functions directly. */ +#ifdef __cplusplus +extern "C" { +#endif +void AnnotateRWLockCreate(const char *file, int line, + const volatile void *lock); +void AnnotateRWLockDestroy(const char *file, int line, + const volatile void *lock); +void AnnotateRWLockAcquired(const char *file, int line, + const volatile void *lock, long is_w); +void AnnotateRWLockReleased(const char *file, int line, + const volatile void *lock, long is_w); +void AnnotateBarrierInit(const char *file, int line, + const volatile void *barrier, long count, + long reinitialization_allowed); +void AnnotateBarrierWaitBefore(const char *file, int line, + const volatile void *barrier); +void AnnotateBarrierWaitAfter(const char *file, int line, + const volatile void *barrier); +void AnnotateBarrierDestroy(const char *file, int line, + const volatile void *barrier); +void AnnotateCondVarWait(const char *file, int line, + const volatile void *cv, + const volatile void *lock); +void AnnotateCondVarSignal(const char *file, int line, + const volatile void *cv); +void AnnotateCondVarSignalAll(const char *file, int line, + const volatile void *cv); +void AnnotatePublishMemoryRange(const char *file, int line, + const volatile void *address, + long size); +void AnnotateUnpublishMemoryRange(const char *file, int line, + const volatile void *address, + long size); +void AnnotatePCQCreate(const char *file, int line, + const volatile void *pcq); +void AnnotatePCQDestroy(const char *file, int line, + const volatile void *pcq); +void AnnotatePCQPut(const char *file, int line, + const volatile void *pcq); +void AnnotatePCQGet(const char *file, int line, + const volatile void *pcq); +void AnnotateNewMemory(const char *file, int line, + const volatile void *address, + long size); +void AnnotateExpectRace(const char *file, int line, + const volatile void *address, + const char *description); +void AnnotateBenignRace(const char *file, int line, + const volatile void *address, + const char *description); +void AnnotateBenignRaceSized(const char *file, int line, + const volatile void *address, + long size, + const char *description); +void AnnotateMutexIsUsedAsCondVar(const char *file, int line, + const volatile void *mu); +void AnnotateTraceMemory(const char *file, int line, + const volatile void *arg); +void AnnotateThreadName(const char *file, int line, + const char *name); +void AnnotateIgnoreReadsBegin(const char *file, int line); +void AnnotateIgnoreReadsEnd(const char *file, int line); +void AnnotateIgnoreWritesBegin(const char *file, int line); +void AnnotateIgnoreWritesEnd(const char *file, int line); +void AnnotateEnableRaceDetection(const char *file, int line, int enable); +void AnnotateNoOp(const char *file, int line, + const volatile void *arg); +void AnnotateFlushState(const char *file, int line); + +/* Return non-zero value if running under valgrind. + + If "valgrind.h" is included into dynamic_annotations.c, + the regular valgrind mechanism will be used. + See http://valgrind.org/docs/manual/manual-core-adv.html about + RUNNING_ON_VALGRIND and other valgrind "client requests". + The file "valgrind.h" may be obtained by doing + svn co svn://svn.valgrind.org/valgrind/trunk/include + + If for some reason you can't use "valgrind.h" or want to fake valgrind, + there are two ways to make this function return non-zero: + - Use environment variable: export RUNNING_ON_VALGRIND=1 + - Make your tool intercept the function RunningOnValgrind() and + change its return value. + */ +int RunningOnValgrind(void); + +#ifdef __cplusplus +} +#endif + +#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus) + + /* _Py_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads. + + Instead of doing + _Py_ANNOTATE_IGNORE_READS_BEGIN(); + ... = x; + _Py_ANNOTATE_IGNORE_READS_END(); + one can use + ... = _Py_ANNOTATE_UNPROTECTED_READ(x); */ + template + inline T _Py_ANNOTATE_UNPROTECTED_READ(const volatile T &x) { + _Py_ANNOTATE_IGNORE_READS_BEGIN(); + T res = x; + _Py_ANNOTATE_IGNORE_READS_END(); + return res; + } + /* Apply _Py_ANNOTATE_BENIGN_RACE_SIZED to a static variable. */ +#define _Py_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \ + namespace { \ + class static_var ## _annotator { \ + public: \ + static_var ## _annotator() { \ + _Py_ANNOTATE_BENIGN_RACE_SIZED(&static_var, \ + sizeof(static_var), \ + # static_var ": " description); \ + } \ + }; \ + static static_var ## _annotator the ## static_var ## _annotator;\ + } +#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */ + +#define _Py_ANNOTATE_UNPROTECTED_READ(x) (x) +#define _Py_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */ + +#endif /* DYNAMIC_ANNOTATIONS_ENABLED */ + +#endif /* __DYNAMIC_ANNOTATIONS_H__ */ diff --git a/winvenv/Include/enumobject.h b/winvenv/Include/enumobject.h new file mode 100644 index 0000000..c14dbfc --- /dev/null +++ b/winvenv/Include/enumobject.h @@ -0,0 +1,17 @@ +#ifndef Py_ENUMOBJECT_H +#define Py_ENUMOBJECT_H + +/* Enumerate Object */ + +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_DATA(PyTypeObject) PyEnum_Type; +PyAPI_DATA(PyTypeObject) PyReversed_Type; + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_ENUMOBJECT_H */ diff --git a/winvenv/Include/errcode.h b/winvenv/Include/errcode.h new file mode 100644 index 0000000..b37cd26 --- /dev/null +++ b/winvenv/Include/errcode.h @@ -0,0 +1,38 @@ +#ifndef Py_ERRCODE_H +#define Py_ERRCODE_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Error codes passed around between file input, tokenizer, parser and + interpreter. This is necessary so we can turn them into Python + exceptions at a higher level. Note that some errors have a + slightly different meaning when passed from the tokenizer to the + parser than when passed from the parser to the interpreter; e.g. + the parser only returns E_EOF when it hits EOF immediately, and it + never returns E_OK. */ + +#define E_OK 10 /* No error */ +#define E_EOF 11 /* End Of File */ +#define E_INTR 12 /* Interrupted */ +#define E_TOKEN 13 /* Bad token */ +#define E_SYNTAX 14 /* Syntax error */ +#define E_NOMEM 15 /* Ran out of memory */ +#define E_DONE 16 /* Parsing complete */ +#define E_ERROR 17 /* Execution error */ +#define E_TABSPACE 18 /* Inconsistent mixing of tabs and spaces */ +#define E_OVERFLOW 19 /* Node had too many children */ +#define E_TOODEEP 20 /* Too many indentation levels */ +#define E_DEDENT 21 /* No matching outer block for dedent */ +#define E_DECODE 22 /* Error in decoding into Unicode */ +#define E_EOFS 23 /* EOF in triple-quoted string */ +#define E_EOLS 24 /* EOL in single-quoted string */ +#define E_LINECONT 25 /* Unexpected characters after a line continuation */ +#define E_IDENTIFIER 26 /* Invalid characters in identifier */ +#define E_BADSINGLE 27 /* Ill-formed single statement input */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ERRCODE_H */ diff --git a/winvenv/Include/eval.h b/winvenv/Include/eval.h new file mode 100644 index 0000000..2c1c2d0 --- /dev/null +++ b/winvenv/Include/eval.h @@ -0,0 +1,37 @@ + +/* Interface to execute compiled code */ + +#ifndef Py_EVAL_H +#define Py_EVAL_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(PyObject *) PyEval_EvalCode(PyObject *, PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyObject *co, + PyObject *globals, + PyObject *locals, + PyObject *const *args, int argc, + PyObject *const *kwds, int kwdc, + PyObject *const *defs, int defc, + PyObject *kwdefs, PyObject *closure); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyEval_EvalCodeWithName( + PyObject *co, + PyObject *globals, PyObject *locals, + PyObject *const *args, Py_ssize_t argcount, + PyObject *const *kwnames, PyObject *const *kwargs, + Py_ssize_t kwcount, int kwstep, + PyObject *const *defs, Py_ssize_t defcount, + PyObject *kwdefs, PyObject *closure, + PyObject *name, PyObject *qualname); + +PyAPI_FUNC(PyObject *) _PyEval_CallTracing(PyObject *func, PyObject *args); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_EVAL_H */ diff --git a/winvenv/Include/fileobject.h b/winvenv/Include/fileobject.h new file mode 100644 index 0000000..89e8dd6 --- /dev/null +++ b/winvenv/Include/fileobject.h @@ -0,0 +1,55 @@ +/* File object interface (what's left of it -- see io.py) */ + +#ifndef Py_FILEOBJECT_H +#define Py_FILEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#define PY_STDIOTEXTMODE "b" + +PyAPI_FUNC(PyObject *) PyFile_FromFd(int, const char *, const char *, int, + const char *, const char *, + const char *, int); +PyAPI_FUNC(PyObject *) PyFile_GetLine(PyObject *, int); +PyAPI_FUNC(int) PyFile_WriteObject(PyObject *, PyObject *, int); +PyAPI_FUNC(int) PyFile_WriteString(const char *, PyObject *); +PyAPI_FUNC(int) PyObject_AsFileDescriptor(PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); +#endif + +/* The default encoding used by the platform file system APIs + If non-NULL, this is different than the default encoding for strings +*/ +PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 +PyAPI_DATA(const char *) Py_FileSystemDefaultEncodeErrors; +#endif +PyAPI_DATA(int) Py_HasFileSystemDefaultEncoding; + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 +PyAPI_DATA(int) Py_UTF8Mode; +#endif + +/* Internal API + + The std printer acts as a preliminary sys.stderr until the new io + infrastructure is in place. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyFile_NewStdPrinter(int); +PyAPI_DATA(PyTypeObject) PyStdPrinter_Type; +#endif /* Py_LIMITED_API */ + +/* A routine to check if a file descriptor can be select()-ed. */ +#ifdef _MSC_VER + /* On Windows, any socket fd can be select()-ed, no matter how high */ + #define _PyIsSelectable_fd(FD) (1) +#else + #define _PyIsSelectable_fd(FD) ((unsigned int)(FD) < (unsigned int)FD_SETSIZE) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_FILEOBJECT_H */ diff --git a/winvenv/Include/fileutils.h b/winvenv/Include/fileutils.h new file mode 100644 index 0000000..e4bf6d4 --- /dev/null +++ b/winvenv/Include/fileutils.h @@ -0,0 +1,177 @@ +#ifndef Py_FILEUTILS_H +#define Py_FILEUTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_FUNC(wchar_t *) Py_DecodeLocale( + const char *arg, + size_t *size); + +PyAPI_FUNC(char*) Py_EncodeLocale( + const wchar_t *text, + size_t *error_pos); + +PyAPI_FUNC(char*) _Py_EncodeLocaleRaw( + const wchar_t *text, + size_t *error_pos); +#endif + +#ifdef Py_BUILD_CORE +PyAPI_FUNC(int) _Py_DecodeUTF8Ex( + const char *arg, + Py_ssize_t arglen, + wchar_t **wstr, + size_t *wlen, + const char **reason, + int surrogateescape); + +PyAPI_FUNC(int) _Py_EncodeUTF8Ex( + const wchar_t *text, + char **str, + size_t *error_pos, + const char **reason, + int raw_malloc, + int surrogateescape); + +PyAPI_FUNC(wchar_t*) _Py_DecodeUTF8_surrogateescape( + const char *arg, + Py_ssize_t arglen); + +PyAPI_FUNC(int) _Py_DecodeLocaleEx( + const char *arg, + wchar_t **wstr, + size_t *wlen, + const char **reason, + int current_locale, + int surrogateescape); + +PyAPI_FUNC(int) _Py_EncodeLocaleEx( + const wchar_t *text, + char **str, + size_t *error_pos, + const char **reason, + int current_locale, + int surrogateescape); +#endif + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _Py_device_encoding(int); + +#ifdef MS_WINDOWS +struct _Py_stat_struct { + unsigned long st_dev; + uint64_t st_ino; + unsigned short st_mode; + int st_nlink; + int st_uid; + int st_gid; + unsigned long st_rdev; + __int64 st_size; + time_t st_atime; + int st_atime_nsec; + time_t st_mtime; + int st_mtime_nsec; + time_t st_ctime; + int st_ctime_nsec; + unsigned long st_file_attributes; +}; +#else +# define _Py_stat_struct stat +#endif + +PyAPI_FUNC(int) _Py_fstat( + int fd, + struct _Py_stat_struct *status); + +PyAPI_FUNC(int) _Py_fstat_noraise( + int fd, + struct _Py_stat_struct *status); + +PyAPI_FUNC(int) _Py_stat( + PyObject *path, + struct stat *status); + +PyAPI_FUNC(int) _Py_open( + const char *pathname, + int flags); + +PyAPI_FUNC(int) _Py_open_noraise( + const char *pathname, + int flags); + +PyAPI_FUNC(FILE *) _Py_wfopen( + const wchar_t *path, + const wchar_t *mode); + +PyAPI_FUNC(FILE*) _Py_fopen( + const char *pathname, + const char *mode); + +PyAPI_FUNC(FILE*) _Py_fopen_obj( + PyObject *path, + const char *mode); + +PyAPI_FUNC(Py_ssize_t) _Py_read( + int fd, + void *buf, + size_t count); + +PyAPI_FUNC(Py_ssize_t) _Py_write( + int fd, + const void *buf, + size_t count); + +PyAPI_FUNC(Py_ssize_t) _Py_write_noraise( + int fd, + const void *buf, + size_t count); + +#ifdef HAVE_READLINK +PyAPI_FUNC(int) _Py_wreadlink( + const wchar_t *path, + wchar_t *buf, + size_t bufsiz); +#endif + +#ifdef HAVE_REALPATH +PyAPI_FUNC(wchar_t*) _Py_wrealpath( + const wchar_t *path, + wchar_t *resolved_path, + size_t resolved_path_size); +#endif + +PyAPI_FUNC(wchar_t*) _Py_wgetcwd( + wchar_t *buf, + size_t size); + +PyAPI_FUNC(int) _Py_get_inheritable(int fd); + +PyAPI_FUNC(int) _Py_set_inheritable(int fd, int inheritable, + int *atomic_flag_works); + +PyAPI_FUNC(int) _Py_set_inheritable_async_safe(int fd, int inheritable, + int *atomic_flag_works); + +PyAPI_FUNC(int) _Py_dup(int fd); + +#ifndef MS_WINDOWS +PyAPI_FUNC(int) _Py_get_blocking(int fd); + +PyAPI_FUNC(int) _Py_set_blocking(int fd, int blocking); +#endif /* !MS_WINDOWS */ + +PyAPI_FUNC(int) _Py_GetLocaleconvNumeric( + PyObject **decimal_point, + PyObject **thousands_sep, + const char **grouping); + +#endif /* Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_FILEUTILS_H */ diff --git a/winvenv/Include/floatobject.h b/winvenv/Include/floatobject.h new file mode 100644 index 0000000..f1044d6 --- /dev/null +++ b/winvenv/Include/floatobject.h @@ -0,0 +1,130 @@ + +/* Float object interface */ + +/* +PyFloatObject represents a (double precision) floating point number. +*/ + +#ifndef Py_FLOATOBJECT_H +#define Py_FLOATOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +typedef struct { + PyObject_HEAD + double ob_fval; +} PyFloatObject; +#endif + +PyAPI_DATA(PyTypeObject) PyFloat_Type; + +#define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type) +#define PyFloat_CheckExact(op) (Py_TYPE(op) == &PyFloat_Type) + +#ifdef Py_NAN +#define Py_RETURN_NAN return PyFloat_FromDouble(Py_NAN) +#endif + +#define Py_RETURN_INF(sign) do \ + if (copysign(1., sign) == 1.) { \ + return PyFloat_FromDouble(Py_HUGE_VAL); \ + } else { \ + return PyFloat_FromDouble(-Py_HUGE_VAL); \ + } while(0) + +PyAPI_FUNC(double) PyFloat_GetMax(void); +PyAPI_FUNC(double) PyFloat_GetMin(void); +PyAPI_FUNC(PyObject *) PyFloat_GetInfo(void); + +/* Return Python float from string PyObject. */ +PyAPI_FUNC(PyObject *) PyFloat_FromString(PyObject*); + +/* Return Python float from C double. */ +PyAPI_FUNC(PyObject *) PyFloat_FromDouble(double); + +/* Extract C double from Python float. The macro version trades safety for + speed. */ +PyAPI_FUNC(double) PyFloat_AsDouble(PyObject *); +#ifndef Py_LIMITED_API +#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval) +#endif + +#ifndef Py_LIMITED_API +/* _PyFloat_{Pack,Unpack}{4,8} + * + * The struct and pickle (at least) modules need an efficient platform- + * independent way to store floating-point values as byte strings. + * The Pack routines produce a string from a C double, and the Unpack + * routines produce a C double from such a string. The suffix (4 or 8) + * specifies the number of bytes in the string. + * + * On platforms that appear to use (see _PyFloat_Init()) IEEE-754 formats + * these functions work by copying bits. On other platforms, the formats the + * 4- byte format is identical to the IEEE-754 single precision format, and + * the 8-byte format to the IEEE-754 double precision format, although the + * packing of INFs and NaNs (if such things exist on the platform) isn't + * handled correctly, and attempting to unpack a string containing an IEEE + * INF or NaN will raise an exception. + * + * On non-IEEE platforms with more precision, or larger dynamic range, than + * 754 supports, not all values can be packed; on non-IEEE platforms with less + * precision, or smaller dynamic range, not all values can be unpacked. What + * happens in such cases is partly accidental (alas). + */ + +/* The pack routines write 2, 4 or 8 bytes, starting at p. le is a bool + * argument, true if you want the string in little-endian format (exponent + * last, at p+1, p+3 or p+7), false if you want big-endian format (exponent + * first, at p). + * Return value: 0 if all is OK, -1 if error (and an exception is + * set, most likely OverflowError). + * There are two problems on non-IEEE platforms: + * 1): What this does is undefined if x is a NaN or infinity. + * 2): -0.0 and +0.0 produce the same string. + */ +PyAPI_FUNC(int) _PyFloat_Pack2(double x, unsigned char *p, int le); +PyAPI_FUNC(int) _PyFloat_Pack4(double x, unsigned char *p, int le); +PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le); + +/* Needed for the old way for marshal to store a floating point number. + Returns the string length copied into p, -1 on error. + */ +PyAPI_FUNC(int) _PyFloat_Repr(double x, char *p, size_t len); + +/* Used to get the important decimal digits of a double */ +PyAPI_FUNC(int) _PyFloat_Digits(char *buf, double v, int *signum); +PyAPI_FUNC(void) _PyFloat_DigitsInit(void); + +/* The unpack routines read 2, 4 or 8 bytes, starting at p. le is a bool + * argument, true if the string is in little-endian format (exponent + * last, at p+1, p+3 or p+7), false if big-endian (exponent first, at p). + * Return value: The unpacked double. On error, this is -1.0 and + * PyErr_Occurred() is true (and an exception is set, most likely + * OverflowError). Note that on a non-IEEE platform this will refuse + * to unpack a string that represents a NaN or infinity. + */ +PyAPI_FUNC(double) _PyFloat_Unpack2(const unsigned char *p, int le); +PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le); +PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le); + +/* free list api */ +PyAPI_FUNC(int) PyFloat_ClearFreeList(void); + +PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out); + +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +PyAPI_FUNC(int) _PyFloat_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); +#endif /* Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_FLOATOBJECT_H */ diff --git a/winvenv/Include/frameobject.h b/winvenv/Include/frameobject.h new file mode 100644 index 0000000..a95baf8 --- /dev/null +++ b/winvenv/Include/frameobject.h @@ -0,0 +1,93 @@ + +/* Frame object interface */ + +#ifndef Py_LIMITED_API +#ifndef Py_FRAMEOBJECT_H +#define Py_FRAMEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int b_type; /* what kind of block this is */ + int b_handler; /* where to jump to find handler */ + int b_level; /* value stack level to pop to */ +} PyTryBlock; + +typedef struct _frame { + PyObject_VAR_HEAD + struct _frame *f_back; /* previous frame, or NULL */ + PyCodeObject *f_code; /* code segment */ + PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ + PyObject *f_globals; /* global symbol table (PyDictObject) */ + PyObject *f_locals; /* local symbol table (any mapping) */ + PyObject **f_valuestack; /* points after the last local */ + /* Next free slot in f_valuestack. Frame creation sets to f_valuestack. + Frame evaluation usually NULLs it, but a frame that yields sets it + to the current stack top. */ + PyObject **f_stacktop; + PyObject *f_trace; /* Trace function */ + char f_trace_lines; /* Emit per-line trace events? */ + char f_trace_opcodes; /* Emit per-opcode trace events? */ + + /* Borrowed reference to a generator, or NULL */ + PyObject *f_gen; + + int f_lasti; /* Last instruction if called */ + /* Call PyFrame_GetLineNumber() instead of reading this field + directly. As of 2.3 f_lineno is only valid when tracing is + active (i.e. when f_trace is set). At other times we use + PyCode_Addr2Line to calculate the line from the current + bytecode index. */ + int f_lineno; /* Current line number */ + int f_iblock; /* index in f_blockstack */ + char f_executing; /* whether the frame is still executing */ + PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ + PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ +} PyFrameObject; + + +/* Standard object interface */ + +PyAPI_DATA(PyTypeObject) PyFrame_Type; + +#define PyFrame_Check(op) (Py_TYPE(op) == &PyFrame_Type) + +PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *, + PyObject *, PyObject *); + +/* only internal use */ +PyFrameObject* _PyFrame_New_NoTrack(PyThreadState *, PyCodeObject *, + PyObject *, PyObject *); + + +/* The rest of the interface is specific for frame objects */ + +/* Block management functions */ + +PyAPI_FUNC(void) PyFrame_BlockSetup(PyFrameObject *, int, int, int); +PyAPI_FUNC(PyTryBlock *) PyFrame_BlockPop(PyFrameObject *); + +/* Extend the value stack */ + +PyAPI_FUNC(PyObject **) PyFrame_ExtendStack(PyFrameObject *, int, int); + +/* Conversions between "fast locals" and locals in dictionary */ + +PyAPI_FUNC(void) PyFrame_LocalsToFast(PyFrameObject *, int); + +PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f); +PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *); + +PyAPI_FUNC(int) PyFrame_ClearFreeList(void); + +PyAPI_FUNC(void) _PyFrame_DebugMallocStats(FILE *out); + +/* Return the line of code the frame is currently executing. */ +PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_FRAMEOBJECT_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/funcobject.h b/winvenv/Include/funcobject.h new file mode 100644 index 0000000..86674ac --- /dev/null +++ b/winvenv/Include/funcobject.h @@ -0,0 +1,103 @@ + +/* Function object interface */ +#ifndef Py_LIMITED_API +#ifndef Py_FUNCOBJECT_H +#define Py_FUNCOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Function objects and code objects should not be confused with each other: + * + * Function objects are created by the execution of the 'def' statement. + * They reference a code object in their __code__ attribute, which is a + * purely syntactic object, i.e. nothing more than a compiled version of some + * source code lines. There is one code object per source code "fragment", + * but each code object can be referenced by zero or many function objects + * depending only on how many times the 'def' statement in the source was + * executed so far. + */ + +typedef struct { + PyObject_HEAD + PyObject *func_code; /* A code object, the __code__ attribute */ + PyObject *func_globals; /* A dictionary (other mappings won't do) */ + PyObject *func_defaults; /* NULL or a tuple */ + PyObject *func_kwdefaults; /* NULL or a dict */ + PyObject *func_closure; /* NULL or a tuple of cell objects */ + PyObject *func_doc; /* The __doc__ attribute, can be anything */ + PyObject *func_name; /* The __name__ attribute, a string object */ + PyObject *func_dict; /* The __dict__ attribute, a dict or NULL */ + PyObject *func_weakreflist; /* List of weak references */ + PyObject *func_module; /* The __module__ attribute, can be anything */ + PyObject *func_annotations; /* Annotations, a dict or NULL */ + PyObject *func_qualname; /* The qualified name */ + + /* Invariant: + * func_closure contains the bindings for func_code->co_freevars, so + * PyTuple_Size(func_closure) == PyCode_GetNumFree(func_code) + * (func_closure may be NULL if PyCode_GetNumFree(func_code) == 0). + */ +} PyFunctionObject; + +PyAPI_DATA(PyTypeObject) PyFunction_Type; + +#define PyFunction_Check(op) (Py_TYPE(op) == &PyFunction_Type) + +PyAPI_FUNC(PyObject *) PyFunction_New(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_NewWithQualName(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetCode(PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetGlobals(PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetDefaults(PyObject *); +PyAPI_FUNC(int) PyFunction_SetDefaults(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetKwDefaults(PyObject *); +PyAPI_FUNC(int) PyFunction_SetKwDefaults(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetClosure(PyObject *); +PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyFunction_GetAnnotations(PyObject *); +PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyFunction_FastCallDict( + PyObject *func, + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwargs); + +PyAPI_FUNC(PyObject *) _PyFunction_FastCallKeywords( + PyObject *func, + PyObject *const *stack, + Py_ssize_t nargs, + PyObject *kwnames); +#endif + +/* Macros for direct access to these values. Type checks are *not* + done, so use with care. */ +#define PyFunction_GET_CODE(func) \ + (((PyFunctionObject *)func) -> func_code) +#define PyFunction_GET_GLOBALS(func) \ + (((PyFunctionObject *)func) -> func_globals) +#define PyFunction_GET_MODULE(func) \ + (((PyFunctionObject *)func) -> func_module) +#define PyFunction_GET_DEFAULTS(func) \ + (((PyFunctionObject *)func) -> func_defaults) +#define PyFunction_GET_KW_DEFAULTS(func) \ + (((PyFunctionObject *)func) -> func_kwdefaults) +#define PyFunction_GET_CLOSURE(func) \ + (((PyFunctionObject *)func) -> func_closure) +#define PyFunction_GET_ANNOTATIONS(func) \ + (((PyFunctionObject *)func) -> func_annotations) + +/* The classmethod and staticmethod types lives here, too */ +PyAPI_DATA(PyTypeObject) PyClassMethod_Type; +PyAPI_DATA(PyTypeObject) PyStaticMethod_Type; + +PyAPI_FUNC(PyObject *) PyClassMethod_New(PyObject *); +PyAPI_FUNC(PyObject *) PyStaticMethod_New(PyObject *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_FUNCOBJECT_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/genobject.h b/winvenv/Include/genobject.h new file mode 100644 index 0000000..16b9833 --- /dev/null +++ b/winvenv/Include/genobject.h @@ -0,0 +1,105 @@ + +/* Generator object interface */ + +#ifndef Py_LIMITED_API +#ifndef Py_GENOBJECT_H +#define Py_GENOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +struct _frame; /* Avoid including frameobject.h */ + +/* _PyGenObject_HEAD defines the initial segment of generator + and coroutine objects. */ +#define _PyGenObject_HEAD(prefix) \ + PyObject_HEAD \ + /* Note: gi_frame can be NULL if the generator is "finished" */ \ + struct _frame *prefix##_frame; \ + /* True if generator is being executed. */ \ + char prefix##_running; \ + /* The code object backing the generator */ \ + PyObject *prefix##_code; \ + /* List of weak reference. */ \ + PyObject *prefix##_weakreflist; \ + /* Name of the generator. */ \ + PyObject *prefix##_name; \ + /* Qualified name of the generator. */ \ + PyObject *prefix##_qualname; \ + _PyErr_StackItem prefix##_exc_state; + +typedef struct { + /* The gi_ prefix is intended to remind of generator-iterator. */ + _PyGenObject_HEAD(gi) +} PyGenObject; + +PyAPI_DATA(PyTypeObject) PyGen_Type; + +#define PyGen_Check(op) PyObject_TypeCheck(op, &PyGen_Type) +#define PyGen_CheckExact(op) (Py_TYPE(op) == &PyGen_Type) + +PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *); +PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(struct _frame *, + PyObject *name, PyObject *qualname); +PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *); +PyAPI_FUNC(int) _PyGen_SetStopIterationValue(PyObject *); +PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); +PyAPI_FUNC(PyObject *) _PyGen_Send(PyGenObject *, PyObject *); +PyObject *_PyGen_yf(PyGenObject *); +PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); + +#ifndef Py_LIMITED_API +typedef struct { + _PyGenObject_HEAD(cr) + PyObject *cr_origin; +} PyCoroObject; + +PyAPI_DATA(PyTypeObject) PyCoro_Type; +PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type; + +PyAPI_DATA(PyTypeObject) _PyAIterWrapper_Type; + +#define PyCoro_CheckExact(op) (Py_TYPE(op) == &PyCoro_Type) +PyObject *_PyCoro_GetAwaitableIter(PyObject *o); +PyAPI_FUNC(PyObject *) PyCoro_New(struct _frame *, + PyObject *name, PyObject *qualname); + +/* Asynchronous Generators */ + +typedef struct { + _PyGenObject_HEAD(ag) + PyObject *ag_finalizer; + + /* Flag is set to 1 when hooks set up by sys.set_asyncgen_hooks + were called on the generator, to avoid calling them more + than once. */ + int ag_hooks_inited; + + /* Flag is set to 1 when aclose() is called for the first time, or + when a StopAsyncIteration exception is raised. */ + int ag_closed; +} PyAsyncGenObject; + +PyAPI_DATA(PyTypeObject) PyAsyncGen_Type; +PyAPI_DATA(PyTypeObject) _PyAsyncGenASend_Type; +PyAPI_DATA(PyTypeObject) _PyAsyncGenWrappedValue_Type; +PyAPI_DATA(PyTypeObject) _PyAsyncGenAThrow_Type; + +PyAPI_FUNC(PyObject *) PyAsyncGen_New(struct _frame *, + PyObject *name, PyObject *qualname); + +#define PyAsyncGen_CheckExact(op) (Py_TYPE(op) == &PyAsyncGen_Type) + +PyObject *_PyAsyncGenValueWrapperNew(PyObject *); + +int PyAsyncGen_ClearFreeLists(void); + +#endif + +#undef _PyGenObject_HEAD + +#ifdef __cplusplus +} +#endif +#endif /* !Py_GENOBJECT_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/graminit.h b/winvenv/Include/graminit.h new file mode 100644 index 0000000..bdfe821 --- /dev/null +++ b/winvenv/Include/graminit.h @@ -0,0 +1,89 @@ +/* Generated by Parser/pgen */ + +#define single_input 256 +#define file_input 257 +#define eval_input 258 +#define decorator 259 +#define decorators 260 +#define decorated 261 +#define async_funcdef 262 +#define funcdef 263 +#define parameters 264 +#define typedargslist 265 +#define tfpdef 266 +#define varargslist 267 +#define vfpdef 268 +#define stmt 269 +#define simple_stmt 270 +#define small_stmt 271 +#define expr_stmt 272 +#define annassign 273 +#define testlist_star_expr 274 +#define augassign 275 +#define del_stmt 276 +#define pass_stmt 277 +#define flow_stmt 278 +#define break_stmt 279 +#define continue_stmt 280 +#define return_stmt 281 +#define yield_stmt 282 +#define raise_stmt 283 +#define import_stmt 284 +#define import_name 285 +#define import_from 286 +#define import_as_name 287 +#define dotted_as_name 288 +#define import_as_names 289 +#define dotted_as_names 290 +#define dotted_name 291 +#define global_stmt 292 +#define nonlocal_stmt 293 +#define assert_stmt 294 +#define compound_stmt 295 +#define async_stmt 296 +#define if_stmt 297 +#define while_stmt 298 +#define for_stmt 299 +#define try_stmt 300 +#define with_stmt 301 +#define with_item 302 +#define except_clause 303 +#define suite 304 +#define test 305 +#define test_nocond 306 +#define lambdef 307 +#define lambdef_nocond 308 +#define or_test 309 +#define and_test 310 +#define not_test 311 +#define comparison 312 +#define comp_op 313 +#define star_expr 314 +#define expr 315 +#define xor_expr 316 +#define and_expr 317 +#define shift_expr 318 +#define arith_expr 319 +#define term 320 +#define factor 321 +#define power 322 +#define atom_expr 323 +#define atom 324 +#define testlist_comp 325 +#define trailer 326 +#define subscriptlist 327 +#define subscript 328 +#define sliceop 329 +#define exprlist 330 +#define testlist 331 +#define dictorsetmaker 332 +#define classdef 333 +#define arglist 334 +#define argument 335 +#define comp_iter 336 +#define sync_comp_for 337 +#define comp_for 338 +#define comp_if 339 +#define encoding_decl 340 +#define yield_expr 341 +#define yield_arg 342 diff --git a/winvenv/Include/grammar.h b/winvenv/Include/grammar.h new file mode 100644 index 0000000..e1703f4 --- /dev/null +++ b/winvenv/Include/grammar.h @@ -0,0 +1,94 @@ + +/* Grammar interface */ + +#ifndef Py_GRAMMAR_H +#define Py_GRAMMAR_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "bitset.h" /* Sigh... */ + +/* A label of an arc */ + +typedef struct { + int lb_type; + char *lb_str; +} label; + +#define EMPTY 0 /* Label number 0 is by definition the empty label */ + +/* A list of labels */ + +typedef struct { + int ll_nlabels; + label *ll_label; +} labellist; + +/* An arc from one state to another */ + +typedef struct { + short a_lbl; /* Label of this arc */ + short a_arrow; /* State where this arc goes to */ +} arc; + +/* A state in a DFA */ + +typedef struct { + int s_narcs; + arc *s_arc; /* Array of arcs */ + + /* Optional accelerators */ + int s_lower; /* Lowest label index */ + int s_upper; /* Highest label index */ + int *s_accel; /* Accelerator */ + int s_accept; /* Nonzero for accepting state */ +} state; + +/* A DFA */ + +typedef struct { + int d_type; /* Non-terminal this represents */ + char *d_name; /* For printing */ + int d_initial; /* Initial state */ + int d_nstates; + state *d_state; /* Array of states */ + bitset d_first; +} dfa; + +/* A grammar */ + +typedef struct { + int g_ndfas; + dfa *g_dfa; /* Array of DFAs */ + labellist g_ll; + int g_start; /* Start symbol of the grammar */ + int g_accel; /* Set if accelerators present */ +} grammar; + +/* FUNCTIONS */ + +grammar *newgrammar(int start); +void freegrammar(grammar *g); +dfa *adddfa(grammar *g, int type, const char *name); +int addstate(dfa *d); +void addarc(dfa *d, int from, int to, int lbl); +dfa *PyGrammar_FindDFA(grammar *g, int type); + +int addlabel(labellist *ll, int type, const char *str); +int findlabel(labellist *ll, int type, const char *str); +const char *PyGrammar_LabelRepr(label *lb); +void translatelabels(grammar *g); + +void addfirstsets(grammar *g); + +void PyGrammar_AddAccelerators(grammar *g); +void PyGrammar_RemoveAccelerators(grammar *); + +void printgrammar(grammar *g, FILE *fp); +void printnonterminals(grammar *g, FILE *fp); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_GRAMMAR_H */ diff --git a/winvenv/Include/import.h b/winvenv/Include/import.h new file mode 100644 index 0000000..c664803 --- /dev/null +++ b/winvenv/Include/import.h @@ -0,0 +1,151 @@ + +/* Module definition and import interface */ + +#ifndef Py_IMPORT_H +#define Py_IMPORT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +PyAPI_FUNC(_PyInitError) _PyImportZip_Init(void); + +PyMODINIT_FUNC PyInit__imp(void); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(long) PyImport_GetMagicNumber(void); +PyAPI_FUNC(const char *) PyImport_GetMagicTag(void); +PyAPI_FUNC(PyObject *) PyImport_ExecCodeModule( + const char *name, /* UTF-8 encoded string */ + PyObject *co + ); +PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleEx( + const char *name, /* UTF-8 encoded string */ + PyObject *co, + const char *pathname /* decoded from the filesystem encoding */ + ); +PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleWithPathnames( + const char *name, /* UTF-8 encoded string */ + PyObject *co, + const char *pathname, /* decoded from the filesystem encoding */ + const char *cpathname /* decoded from the filesystem encoding */ + ); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject( + PyObject *name, + PyObject *co, + PyObject *pathname, + PyObject *cpathname + ); +#endif +PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 +PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name); +#endif +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); +PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); +PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *name, + PyObject *modules); +PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module); +PyAPI_FUNC(int) _PyImport_SetModuleString(const char *name, PyObject* module); +#endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject *) PyImport_AddModuleObject( + PyObject *name + ); +#endif +PyAPI_FUNC(PyObject *) PyImport_AddModule( + const char *name /* UTF-8 encoded string */ + ); +PyAPI_FUNC(PyObject *) PyImport_ImportModule( + const char *name /* UTF-8 encoded string */ + ); +PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock( + const char *name /* UTF-8 encoded string */ + ); +PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel( + const char *name, /* UTF-8 encoded string */ + PyObject *globals, + PyObject *locals, + PyObject *fromlist, + int level + ); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevelObject( + PyObject *name, + PyObject *globals, + PyObject *locals, + PyObject *fromlist, + int level + ); +#endif + +#define PyImport_ImportModuleEx(n, g, l, f) \ + PyImport_ImportModuleLevel(n, g, l, f, 0) + +PyAPI_FUNC(PyObject *) PyImport_GetImporter(PyObject *path); +PyAPI_FUNC(PyObject *) PyImport_Import(PyObject *name); +PyAPI_FUNC(PyObject *) PyImport_ReloadModule(PyObject *m); +PyAPI_FUNC(void) PyImport_Cleanup(void); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(int) PyImport_ImportFrozenModuleObject( + PyObject *name + ); +#endif +PyAPI_FUNC(int) PyImport_ImportFrozenModule( + const char *name /* UTF-8 encoded string */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyImport_AcquireLock(void); +PyAPI_FUNC(int) _PyImport_ReleaseLock(void); + +PyAPI_FUNC(void) _PyImport_ReInitLock(void); + +PyAPI_FUNC(PyObject *) _PyImport_FindBuiltin( + const char *name, /* UTF-8 encoded string */ + PyObject *modules + ); +PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObject(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObjectEx(PyObject *, PyObject *, + PyObject *); +PyAPI_FUNC(int) _PyImport_FixupBuiltin( + PyObject *mod, + const char *name, /* UTF-8 encoded string */ + PyObject *modules + ); +PyAPI_FUNC(int) _PyImport_FixupExtensionObject(PyObject*, PyObject *, + PyObject *, PyObject *); + +struct _inittab { + const char *name; /* ASCII encoded string */ + PyObject* (*initfunc)(void); +}; +PyAPI_DATA(struct _inittab *) PyImport_Inittab; +PyAPI_FUNC(int) PyImport_ExtendInittab(struct _inittab *newtab); +#endif /* Py_LIMITED_API */ + +PyAPI_DATA(PyTypeObject) PyNullImporter_Type; + +PyAPI_FUNC(int) PyImport_AppendInittab( + const char *name, /* ASCII encoded string */ + PyObject* (*initfunc)(void) + ); + +#ifndef Py_LIMITED_API +struct _frozen { + const char *name; /* ASCII encoded string */ + const unsigned char *code; + int size; +}; + +/* Embedding apps may change this pointer to point to their favorite + collection of frozen modules: */ + +PyAPI_DATA(const struct _frozen *) PyImport_FrozenModules; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_IMPORT_H */ diff --git a/winvenv/Include/intrcheck.h b/winvenv/Include/intrcheck.h new file mode 100644 index 0000000..2e17336 --- /dev/null +++ b/winvenv/Include/intrcheck.h @@ -0,0 +1,33 @@ + +#ifndef Py_INTRCHECK_H +#define Py_INTRCHECK_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(int) PyOS_InterruptOccurred(void); +PyAPI_FUNC(void) PyOS_InitInterrupts(void); +#ifdef HAVE_FORK +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 +PyAPI_FUNC(void) PyOS_BeforeFork(void); +PyAPI_FUNC(void) PyOS_AfterFork_Parent(void); +PyAPI_FUNC(void) PyOS_AfterFork_Child(void); +#endif +#endif +/* Deprecated, please use PyOS_AfterFork_Child() instead */ +PyAPI_FUNC(void) PyOS_AfterFork(void) Py_DEPRECATED(3.7); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyOS_IsMainThread(void); +PyAPI_FUNC(void) _PySignal_AfterFork(void); + +#ifdef MS_WINDOWS +/* windows.h is not included by Python.h so use void* instead of HANDLE */ +PyAPI_FUNC(void*) _PyOS_SigintEvent(void); +#endif +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTRCHECK_H */ diff --git a/winvenv/Include/iterobject.h b/winvenv/Include/iterobject.h new file mode 100644 index 0000000..f61726f --- /dev/null +++ b/winvenv/Include/iterobject.h @@ -0,0 +1,25 @@ +#ifndef Py_ITEROBJECT_H +#define Py_ITEROBJECT_H +/* Iterators (the basic kind, over a sequence) */ +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_DATA(PyTypeObject) PySeqIter_Type; +PyAPI_DATA(PyTypeObject) PyCallIter_Type; +PyAPI_DATA(PyTypeObject) PyCmpWrapper_Type; + +#define PySeqIter_Check(op) (Py_TYPE(op) == &PySeqIter_Type) + +PyAPI_FUNC(PyObject *) PySeqIter_New(PyObject *); + + +#define PyCallIter_Check(op) (Py_TYPE(op) == &PyCallIter_Type) + +PyAPI_FUNC(PyObject *) PyCallIter_New(PyObject *, PyObject *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ITEROBJECT_H */ + diff --git a/winvenv/Include/listobject.h b/winvenv/Include/listobject.h new file mode 100644 index 0000000..6057279 --- /dev/null +++ b/winvenv/Include/listobject.h @@ -0,0 +1,81 @@ + +/* List object interface */ + +/* +Another generally useful object type is a list of object pointers. +This is a mutable type: the list items can be changed, and items can be +added or removed. Out-of-range indices or non-list objects are ignored. + +*** WARNING *** PyList_SetItem does not increment the new item's reference +count, but does decrement the reference count of the item it replaces, +if not nil. It does *decrement* the reference count if it is *not* +inserted in the list. Similarly, PyList_GetItem does not increment the +returned item's reference count. +*/ + +#ifndef Py_LISTOBJECT_H +#define Py_LISTOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +typedef struct { + PyObject_VAR_HEAD + /* Vector of pointers to list elements. list[0] is ob_item[0], etc. */ + PyObject **ob_item; + + /* ob_item contains space for 'allocated' elements. The number + * currently in use is ob_size. + * Invariants: + * 0 <= ob_size <= allocated + * len(list) == ob_size + * ob_item == NULL implies ob_size == allocated == 0 + * list.sort() temporarily sets allocated to -1 to detect mutations. + * + * Items must normally not be NULL, except during construction when + * the list is not yet visible outside the function that builds it. + */ + Py_ssize_t allocated; +} PyListObject; +#endif + +PyAPI_DATA(PyTypeObject) PyList_Type; +PyAPI_DATA(PyTypeObject) PyListIter_Type; +PyAPI_DATA(PyTypeObject) PyListRevIter_Type; +PyAPI_DATA(PyTypeObject) PySortWrapper_Type; + +#define PyList_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS) +#define PyList_CheckExact(op) (Py_TYPE(op) == &PyList_Type) + +PyAPI_FUNC(PyObject *) PyList_New(Py_ssize_t size); +PyAPI_FUNC(Py_ssize_t) PyList_Size(PyObject *); +PyAPI_FUNC(PyObject *) PyList_GetItem(PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyList_SetItem(PyObject *, Py_ssize_t, PyObject *); +PyAPI_FUNC(int) PyList_Insert(PyObject *, Py_ssize_t, PyObject *); +PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyList_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t); +PyAPI_FUNC(int) PyList_SetSlice(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); +PyAPI_FUNC(int) PyList_Sort(PyObject *); +PyAPI_FUNC(int) PyList_Reverse(PyObject *); +PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *); + +PyAPI_FUNC(int) PyList_ClearFreeList(void); +PyAPI_FUNC(void) _PyList_DebugMallocStats(FILE *out); +#endif + +/* Macro, trading safety for speed */ +#ifndef Py_LIMITED_API +#define PyList_GET_ITEM(op, i) (((PyListObject *)(op))->ob_item[i]) +#define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v)) +#define PyList_GET_SIZE(op) (assert(PyList_Check(op)),Py_SIZE(op)) +#define _PyList_ITEMS(op) (((PyListObject *)(op))->ob_item) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_LISTOBJECT_H */ diff --git a/winvenv/Include/longintrepr.h b/winvenv/Include/longintrepr.h new file mode 100644 index 0000000..ff4155f --- /dev/null +++ b/winvenv/Include/longintrepr.h @@ -0,0 +1,99 @@ +#ifndef Py_LIMITED_API +#ifndef Py_LONGINTREPR_H +#define Py_LONGINTREPR_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* This is published for the benefit of "friends" marshal.c and _decimal.c. */ + +/* Parameters of the integer representation. There are two different + sets of parameters: one set for 30-bit digits, stored in an unsigned 32-bit + integer type, and one set for 15-bit digits with each digit stored in an + unsigned short. The value of PYLONG_BITS_IN_DIGIT, defined either at + configure time or in pyport.h, is used to decide which digit size to use. + + Type 'digit' should be able to hold 2*PyLong_BASE-1, and type 'twodigits' + should be an unsigned integer type able to hold all integers up to + PyLong_BASE*PyLong_BASE-1. x_sub assumes that 'digit' is an unsigned type, + and that overflow is handled by taking the result modulo 2**N for some N > + PyLong_SHIFT. The majority of the code doesn't care about the precise + value of PyLong_SHIFT, but there are some notable exceptions: + + - long_pow() requires that PyLong_SHIFT be divisible by 5 + + - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8 + + - long_hash() requires that PyLong_SHIFT is *strictly* less than the number + of bits in an unsigned long, as do the PyLong <-> long (or unsigned long) + conversion functions + + - the Python int <-> size_t/Py_ssize_t conversion functions expect that + PyLong_SHIFT is strictly less than the number of bits in a size_t + + - the marshal code currently expects that PyLong_SHIFT is a multiple of 15 + + - NSMALLNEGINTS and NSMALLPOSINTS should be small enough to fit in a single + digit; with the current values this forces PyLong_SHIFT >= 9 + + The values 15 and 30 should fit all of the above requirements, on any + platform. +*/ + +#if PYLONG_BITS_IN_DIGIT == 30 +typedef uint32_t digit; +typedef int32_t sdigit; /* signed variant of digit */ +typedef uint64_t twodigits; +typedef int64_t stwodigits; /* signed variant of twodigits */ +#define PyLong_SHIFT 30 +#define _PyLong_DECIMAL_SHIFT 9 /* max(e such that 10**e fits in a digit) */ +#define _PyLong_DECIMAL_BASE ((digit)1000000000) /* 10 ** DECIMAL_SHIFT */ +#elif PYLONG_BITS_IN_DIGIT == 15 +typedef unsigned short digit; +typedef short sdigit; /* signed variant of digit */ +typedef unsigned long twodigits; +typedef long stwodigits; /* signed variant of twodigits */ +#define PyLong_SHIFT 15 +#define _PyLong_DECIMAL_SHIFT 4 /* max(e such that 10**e fits in a digit) */ +#define _PyLong_DECIMAL_BASE ((digit)10000) /* 10 ** DECIMAL_SHIFT */ +#else +#error "PYLONG_BITS_IN_DIGIT should be 15 or 30" +#endif +#define PyLong_BASE ((digit)1 << PyLong_SHIFT) +#define PyLong_MASK ((digit)(PyLong_BASE - 1)) + +#if PyLong_SHIFT % 5 != 0 +#error "longobject.c requires that PyLong_SHIFT be divisible by 5" +#endif + +/* Long integer representation. + The absolute value of a number is equal to + SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i) + Negative numbers are represented with ob_size < 0; + zero is represented by ob_size == 0. + In a normalized number, ob_digit[abs(ob_size)-1] (the most significant + digit) is never zero. Also, in all cases, for all valid i, + 0 <= ob_digit[i] <= MASK. + The allocation function takes care of allocating extra memory + so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available. + + CAUTION: Generic code manipulating subtypes of PyVarObject has to + aware that ints abuse ob_size's sign bit. +*/ + +struct _longobject { + PyObject_VAR_HEAD + digit ob_digit[1]; +}; + +PyAPI_FUNC(PyLongObject *) _PyLong_New(Py_ssize_t); + +/* Return a copy of src. */ +PyAPI_FUNC(PyObject *) _PyLong_Copy(PyLongObject *src); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_LONGINTREPR_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/longobject.h b/winvenv/Include/longobject.h new file mode 100644 index 0000000..7bdd047 --- /dev/null +++ b/winvenv/Include/longobject.h @@ -0,0 +1,220 @@ +#ifndef Py_LONGOBJECT_H +#define Py_LONGOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Long (arbitrary precision) integer object interface */ + +typedef struct _longobject PyLongObject; /* Revealed in longintrepr.h */ + +PyAPI_DATA(PyTypeObject) PyLong_Type; + +#define PyLong_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS) +#define PyLong_CheckExact(op) (Py_TYPE(op) == &PyLong_Type) + +PyAPI_FUNC(PyObject *) PyLong_FromLong(long); +PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLong(unsigned long); +PyAPI_FUNC(PyObject *) PyLong_FromSize_t(size_t); +PyAPI_FUNC(PyObject *) PyLong_FromSsize_t(Py_ssize_t); +PyAPI_FUNC(PyObject *) PyLong_FromDouble(double); +PyAPI_FUNC(long) PyLong_AsLong(PyObject *); +PyAPI_FUNC(long) PyLong_AsLongAndOverflow(PyObject *, int *); +PyAPI_FUNC(Py_ssize_t) PyLong_AsSsize_t(PyObject *); +PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *); +PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *); +PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyLong_AsInt(PyObject *); +#endif +PyAPI_FUNC(PyObject *) PyLong_GetInfo(void); + +/* It may be useful in the future. I've added it in the PyInt -> PyLong + cleanup to keep the extra information. [CH] */ +#define PyLong_AS_LONG(op) PyLong_AsLong(op) + +/* Issue #1983: pid_t can be longer than a C long on some systems */ +#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT +#define _Py_PARSE_PID "i" +#define PyLong_FromPid PyLong_FromLong +#define PyLong_AsPid PyLong_AsLong +#elif SIZEOF_PID_T == SIZEOF_LONG +#define _Py_PARSE_PID "l" +#define PyLong_FromPid PyLong_FromLong +#define PyLong_AsPid PyLong_AsLong +#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG +#define _Py_PARSE_PID "L" +#define PyLong_FromPid PyLong_FromLongLong +#define PyLong_AsPid PyLong_AsLongLong +#else +#error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)" +#endif /* SIZEOF_PID_T */ + +#if SIZEOF_VOID_P == SIZEOF_INT +# define _Py_PARSE_INTPTR "i" +# define _Py_PARSE_UINTPTR "I" +#elif SIZEOF_VOID_P == SIZEOF_LONG +# define _Py_PARSE_INTPTR "l" +# define _Py_PARSE_UINTPTR "k" +#elif defined(SIZEOF_LONG_LONG) && SIZEOF_VOID_P == SIZEOF_LONG_LONG +# define _Py_PARSE_INTPTR "L" +# define _Py_PARSE_UINTPTR "K" +#else +# error "void* different in size from int, long and long long" +#endif /* SIZEOF_VOID_P */ + +/* Used by Python/mystrtoul.c, _PyBytes_FromHex(), + _PyBytes_DecodeEscapeRecode(), etc. */ +#ifndef Py_LIMITED_API +PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; +#endif + +/* _PyLong_Frexp returns a double x and an exponent e such that the + true value is approximately equal to x * 2**e. e is >= 0. x is + 0.0 if and only if the input is 0 (in which case, e and x are both + zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is + possible if the number of bits doesn't fit into a Py_ssize_t, sets + OverflowError and returns -1.0 for x, 0 for e. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); +#endif + +PyAPI_FUNC(double) PyLong_AsDouble(PyObject *); +PyAPI_FUNC(PyObject *) PyLong_FromVoidPtr(void *); +PyAPI_FUNC(void *) PyLong_AsVoidPtr(PyObject *); + +PyAPI_FUNC(PyObject *) PyLong_FromLongLong(long long); +PyAPI_FUNC(PyObject *) PyLong_FromUnsignedLongLong(unsigned long long); +PyAPI_FUNC(long long) PyLong_AsLongLong(PyObject *); +PyAPI_FUNC(unsigned long long) PyLong_AsUnsignedLongLong(PyObject *); +PyAPI_FUNC(unsigned long long) PyLong_AsUnsignedLongLongMask(PyObject *); +PyAPI_FUNC(long long) PyLong_AsLongLongAndOverflow(PyObject *, int *); + +PyAPI_FUNC(PyObject *) PyLong_FromString(const char *, char **, int); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyLong_FromUnicode(Py_UNICODE*, Py_ssize_t, int) Py_DEPRECATED(3.3); +PyAPI_FUNC(PyObject *) PyLong_FromUnicodeObject(PyObject *u, int base); +PyAPI_FUNC(PyObject *) _PyLong_FromBytes(const char *, Py_ssize_t, int); +#endif + +#ifndef Py_LIMITED_API +/* _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0. + v must not be NULL, and must be a normalized long. + There are no error cases. +*/ +PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); + + +/* _PyLong_NumBits. Return the number of bits needed to represent the + absolute value of a long. For example, this returns 1 for 1 and -1, 2 + for 2 and -2, and 2 for 3 and -3. It returns 0 for 0. + v must not be NULL, and must be a normalized long. + (size_t)-1 is returned and OverflowError set if the true result doesn't + fit in a size_t. +*/ +PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); + +/* _PyLong_DivmodNear. Given integers a and b, compute the nearest + integer q to the exact quotient a / b, rounding to the nearest even integer + in the case of a tie. Return (q, r), where r = a - q*b. The remainder r + will satisfy abs(r) <= abs(b)/2, with equality possible only if q is + even. +*/ +PyAPI_FUNC(PyObject *) _PyLong_DivmodNear(PyObject *, PyObject *); + +/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in + base 256, and return a Python int with the same numeric value. + If n is 0, the integer is 0. Else: + If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; + else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the + LSB. + If is_signed is 0/false, view the bytes as a non-negative integer. + If is_signed is 1/true, view the bytes as a 2's-complement integer, + non-negative if bit 0x80 of the MSB is clear, negative if set. + Error returns: + + Return NULL with the appropriate exception set if there's not + enough memory to create the Python int. +*/ +PyAPI_FUNC(PyObject *) _PyLong_FromByteArray( + const unsigned char* bytes, size_t n, + int little_endian, int is_signed); + +/* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long + v to a base-256 integer, stored in array bytes. Normally return 0, + return -1 on error. + If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at + bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and + the LSB at bytes[n-1]. + If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes + are filled and there's nothing special about bit 0x80 of the MSB. + If is_signed is 1/true, bytes is filled with the 2's-complement + representation of v's value. Bit 0x80 of the MSB is the sign bit. + Error returns (-1): + + is_signed is 0 and v < 0. TypeError is set in this case, and bytes + isn't altered. + + n isn't big enough to hold the full mathematical value of v. For + example, if is_signed is 0 and there are more digits in the v than + fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of + being large enough to hold a sign bit. OverflowError is set in this + case, but bytes holds the least-significant n bytes of the true value. +*/ +PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v, + unsigned char* bytes, size_t n, + int little_endian, int is_signed); + +/* _PyLong_FromNbInt: Convert the given object to a PyLongObject + using the nb_int slot, if available. Raise TypeError if either the + nb_int slot is not available or the result of the call to nb_int + returns something not of type int. +*/ +PyAPI_FUNC(PyLongObject *)_PyLong_FromNbInt(PyObject *); + +/* _PyLong_Format: Convert the long to a string object with given base, + appending a base prefix of 0[box] if base is 2, 8 or 16. */ +PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *obj, int base); + +PyAPI_FUNC(int) _PyLong_FormatWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + int base, + int alternate); + +PyAPI_FUNC(char*) _PyLong_FormatBytesWriter( + _PyBytesWriter *writer, + char *str, + PyObject *obj, + int base, + int alternate); + +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +PyAPI_FUNC(int) _PyLong_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); +#endif /* Py_LIMITED_API */ + +/* These aren't really part of the int object, but they're handy. The + functions are in Python/mystrtoul.c. + */ +PyAPI_FUNC(unsigned long) PyOS_strtoul(const char *, char **, int); +PyAPI_FUNC(long) PyOS_strtol(const char *, char **, int); + +#ifndef Py_LIMITED_API +/* For use by the gcd function in mathmodule.c */ +PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); +#endif /* !Py_LIMITED_API */ + +#ifndef Py_LIMITED_API +PyAPI_DATA(PyObject *) _PyLong_Zero; +PyAPI_DATA(PyObject *) _PyLong_One; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_LONGOBJECT_H */ diff --git a/winvenv/Include/marshal.h b/winvenv/Include/marshal.h new file mode 100644 index 0000000..09d9337 --- /dev/null +++ b/winvenv/Include/marshal.h @@ -0,0 +1,28 @@ + +/* Interface for marshal.c */ + +#ifndef Py_MARSHAL_H +#define Py_MARSHAL_H +#ifdef __cplusplus +extern "C" { +#endif + +#define Py_MARSHAL_VERSION 4 + +PyAPI_FUNC(void) PyMarshal_WriteLongToFile(long, FILE *, int); +PyAPI_FUNC(void) PyMarshal_WriteObjectToFile(PyObject *, FILE *, int); +PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(long) PyMarshal_ReadLongFromFile(FILE *); +PyAPI_FUNC(int) PyMarshal_ReadShortFromFile(FILE *); +PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromFile(FILE *); +PyAPI_FUNC(PyObject *) PyMarshal_ReadLastObjectFromFile(FILE *); +#endif +PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(const char *, + Py_ssize_t); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MARSHAL_H */ diff --git a/winvenv/Include/memoryobject.h b/winvenv/Include/memoryobject.h new file mode 100644 index 0000000..990a716 --- /dev/null +++ b/winvenv/Include/memoryobject.h @@ -0,0 +1,72 @@ +/* Memory view object. In Python this is available as "memoryview". */ + +#ifndef Py_MEMORYOBJECT_H +#define Py_MEMORYOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +PyAPI_DATA(PyTypeObject) _PyManagedBuffer_Type; +#endif +PyAPI_DATA(PyTypeObject) PyMemoryView_Type; + +#define PyMemoryView_Check(op) (Py_TYPE(op) == &PyMemoryView_Type) + +#ifndef Py_LIMITED_API +/* Get a pointer to the memoryview's private copy of the exporter's buffer. */ +#define PyMemoryView_GET_BUFFER(op) (&((PyMemoryViewObject *)(op))->view) +/* Get a pointer to the exporting object (this may be NULL!). */ +#define PyMemoryView_GET_BASE(op) (((PyMemoryViewObject *)(op))->view.obj) +#endif + +PyAPI_FUNC(PyObject *) PyMemoryView_FromObject(PyObject *base); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject *) PyMemoryView_FromMemory(char *mem, Py_ssize_t size, + int flags); +#endif +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyMemoryView_FromBuffer(Py_buffer *info); +#endif +PyAPI_FUNC(PyObject *) PyMemoryView_GetContiguous(PyObject *base, + int buffertype, + char order); + + +/* The structs are declared here so that macros can work, but they shouldn't + be considered public. Don't access their fields directly, use the macros + and functions instead! */ +#ifndef Py_LIMITED_API +#define _Py_MANAGED_BUFFER_RELEASED 0x001 /* access to exporter blocked */ +#define _Py_MANAGED_BUFFER_FREE_FORMAT 0x002 /* free format */ +typedef struct { + PyObject_HEAD + int flags; /* state flags */ + Py_ssize_t exports; /* number of direct memoryview exports */ + Py_buffer master; /* snapshot buffer obtained from the original exporter */ +} _PyManagedBufferObject; + + +/* memoryview state flags */ +#define _Py_MEMORYVIEW_RELEASED 0x001 /* access to master buffer blocked */ +#define _Py_MEMORYVIEW_C 0x002 /* C-contiguous layout */ +#define _Py_MEMORYVIEW_FORTRAN 0x004 /* Fortran contiguous layout */ +#define _Py_MEMORYVIEW_SCALAR 0x008 /* scalar: ndim = 0 */ +#define _Py_MEMORYVIEW_PIL 0x010 /* PIL-style layout */ + +typedef struct { + PyObject_VAR_HEAD + _PyManagedBufferObject *mbuf; /* managed buffer */ + Py_hash_t hash; /* hash value for read-only views */ + int flags; /* state flags */ + Py_ssize_t exports; /* number of buffer re-exports */ + Py_buffer view; /* private copy of the exporter's view */ + PyObject *weakreflist; + Py_ssize_t ob_array[1]; /* shape, strides, suboffsets */ +} PyMemoryViewObject; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MEMORYOBJECT_H */ diff --git a/winvenv/Include/metagrammar.h b/winvenv/Include/metagrammar.h new file mode 100644 index 0000000..15c8ef8 --- /dev/null +++ b/winvenv/Include/metagrammar.h @@ -0,0 +1,18 @@ +#ifndef Py_METAGRAMMAR_H +#define Py_METAGRAMMAR_H +#ifdef __cplusplus +extern "C" { +#endif + + +#define MSTART 256 +#define RULE 257 +#define RHS 258 +#define ALT 259 +#define ITEM 260 +#define ATOM 261 + +#ifdef __cplusplus +} +#endif +#endif /* !Py_METAGRAMMAR_H */ diff --git a/winvenv/Include/methodobject.h b/winvenv/Include/methodobject.h new file mode 100644 index 0000000..ea35d86 --- /dev/null +++ b/winvenv/Include/methodobject.h @@ -0,0 +1,135 @@ + +/* Method object interface */ + +#ifndef Py_METHODOBJECT_H +#define Py_METHODOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* This is about the type 'builtin_function_or_method', + not Python methods in user-defined classes. See classobject.h + for the latter. */ + +PyAPI_DATA(PyTypeObject) PyCFunction_Type; + +#define PyCFunction_Check(op) (Py_TYPE(op) == &PyCFunction_Type) + +typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); +typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t); +typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *, + PyObject *); +typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *, + PyObject *const *, Py_ssize_t, + PyObject *); +typedef PyObject *(*PyNoArgsFunction)(PyObject *); + +PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *); +PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *); +PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *); + +/* Macros for direct access to these values. Type checks are *not* + done, so use with care. */ +#ifndef Py_LIMITED_API +#define PyCFunction_GET_FUNCTION(func) \ + (((PyCFunctionObject *)func) -> m_ml -> ml_meth) +#define PyCFunction_GET_SELF(func) \ + (((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \ + NULL : ((PyCFunctionObject *)func) -> m_self) +#define PyCFunction_GET_FLAGS(func) \ + (((PyCFunctionObject *)func) -> m_ml -> ml_flags) +#endif +PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyCFunction_FastCallDict(PyObject *func, + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwargs); + +PyAPI_FUNC(PyObject *) _PyCFunction_FastCallKeywords(PyObject *func, + PyObject *const *stack, + Py_ssize_t nargs, + PyObject *kwnames); +#endif + +struct PyMethodDef { + const char *ml_name; /* The name of the built-in function/method */ + PyCFunction ml_meth; /* The C function that implements it */ + int ml_flags; /* Combination of METH_xxx flags, which mostly + describe the args expected by the C func */ + const char *ml_doc; /* The __doc__ attribute, or NULL */ +}; +typedef struct PyMethodDef PyMethodDef; + +#define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL) +PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *, + PyObject *); + +/* Flag passed to newmethodobject */ +/* #define METH_OLDARGS 0x0000 -- unsupported now */ +#define METH_VARARGS 0x0001 +#define METH_KEYWORDS 0x0002 +/* METH_NOARGS and METH_O must not be combined with the flags above. */ +#define METH_NOARGS 0x0004 +#define METH_O 0x0008 + +/* METH_CLASS and METH_STATIC are a little different; these control + the construction of methods for a class. These cannot be used for + functions in modules. */ +#define METH_CLASS 0x0010 +#define METH_STATIC 0x0020 + +/* METH_COEXIST allows a method to be entered even though a slot has + already filled the entry. When defined, the flag allows a separate + method, "__contains__" for example, to coexist with a defined + slot like sq_contains. */ + +#define METH_COEXIST 0x0040 + +#ifndef Py_LIMITED_API +#define METH_FASTCALL 0x0080 +#endif + +/* This bit is preserved for Stackless Python */ +#ifdef STACKLESS +#define METH_STACKLESS 0x0100 +#else +#define METH_STACKLESS 0x0000 +#endif + +#ifndef Py_LIMITED_API +typedef struct { + PyObject_HEAD + PyMethodDef *m_ml; /* Description of the C function to call */ + PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ + PyObject *m_module; /* The __module__ attribute, can be anything */ + PyObject *m_weakreflist; /* List of weak references */ +} PyCFunctionObject; + +PyAPI_FUNC(PyObject *) _PyMethodDef_RawFastCallDict( + PyMethodDef *method, + PyObject *self, + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwargs); + +PyAPI_FUNC(PyObject *) _PyMethodDef_RawFastCallKeywords( + PyMethodDef *method, + PyObject *self, + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames); +#endif + +PyAPI_FUNC(int) PyCFunction_ClearFreeList(void); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyCFunction_DebugMallocStats(FILE *out); +PyAPI_FUNC(void) _PyMethod_DebugMallocStats(FILE *out); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_METHODOBJECT_H */ diff --git a/winvenv/Include/modsupport.h b/winvenv/Include/modsupport.h new file mode 100644 index 0000000..a238bef --- /dev/null +++ b/winvenv/Include/modsupport.h @@ -0,0 +1,229 @@ + +#ifndef Py_MODSUPPORT_H +#define Py_MODSUPPORT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Module support interface */ + +#include + +/* If PY_SSIZE_T_CLEAN is defined, each functions treats #-specifier + to mean Py_ssize_t */ +#ifdef PY_SSIZE_T_CLEAN +#define PyArg_Parse _PyArg_Parse_SizeT +#define PyArg_ParseTuple _PyArg_ParseTuple_SizeT +#define PyArg_ParseTupleAndKeywords _PyArg_ParseTupleAndKeywords_SizeT +#define PyArg_VaParse _PyArg_VaParse_SizeT +#define PyArg_VaParseTupleAndKeywords _PyArg_VaParseTupleAndKeywords_SizeT +#define Py_BuildValue _Py_BuildValue_SizeT +#define Py_VaBuildValue _Py_VaBuildValue_SizeT +#ifndef Py_LIMITED_API +#define _Py_VaBuildStack _Py_VaBuildStack_SizeT +#endif +#else +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _Py_VaBuildValue_SizeT(const char *, va_list); +PyAPI_FUNC(PyObject **) _Py_VaBuildStack_SizeT( + PyObject **small_stack, + Py_ssize_t small_stack_len, + const char *format, + va_list va, + Py_ssize_t *p_nargs); +#endif /* !Py_LIMITED_API */ +#endif + +/* Due to a glitch in 3.2, the _SizeT versions weren't exported from the DLL. */ +#if !defined(PY_SSIZE_T_CLEAN) || !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(int) PyArg_Parse(PyObject *, const char *, ...); +PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...); +PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, ...); +PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list); +PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, va_list); +#endif +PyAPI_FUNC(int) PyArg_ValidateKeywordArguments(PyObject *); +PyAPI_FUNC(int) PyArg_UnpackTuple(PyObject *, const char *, Py_ssize_t, Py_ssize_t, ...); +PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); +PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); + + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyArg_UnpackStack( + PyObject *const *args, + Py_ssize_t nargs, + const char *name, + Py_ssize_t min, + Py_ssize_t max, + ...); + +PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kwargs); +PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); +#define _PyArg_NoKeywords(funcname, kwargs) \ + ((kwargs) == NULL || _PyArg_NoKeywords((funcname), (kwargs))) +#define _PyArg_NoPositional(funcname, args) \ + ((args) == NULL || _PyArg_NoPositional((funcname), (args))) + +#endif + +PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject **) _Py_VaBuildStack( + PyObject **small_stack, + Py_ssize_t small_stack_len, + const char *format, + va_list va, + Py_ssize_t *p_nargs); +#endif + +#ifndef Py_LIMITED_API +typedef struct _PyArg_Parser { + const char *format; + const char * const *keywords; + const char *fname; + const char *custom_msg; + int pos; /* number of positional-only arguments */ + int min; /* minimal number of arguments */ + int max; /* maximal number of positional arguments */ + PyObject *kwtuple; /* tuple of keyword parameter names */ + struct _PyArg_Parser *next; +} _PyArg_Parser; +#ifdef PY_SSIZE_T_CLEAN +#define _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT +#define _PyArg_ParseStack _PyArg_ParseStack_SizeT +#define _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT +#define _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT +#endif +PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, ...); +PyAPI_FUNC(int) _PyArg_ParseStack( + PyObject *const *args, + Py_ssize_t nargs, + const char *format, + ...); +PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords( + PyObject *const *args, + Py_ssize_t nargs, + PyObject *kwnames, + struct _PyArg_Parser *, + ...); +PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, va_list); +void _PyArg_Fini(void); +#endif /* Py_LIMITED_API */ + +PyAPI_FUNC(int) PyModule_AddObject(PyObject *, const char *, PyObject *); +PyAPI_FUNC(int) PyModule_AddIntConstant(PyObject *, const char *, long); +PyAPI_FUNC(int) PyModule_AddStringConstant(PyObject *, const char *, const char *); +#define PyModule_AddIntMacro(m, c) PyModule_AddIntConstant(m, #c, c) +#define PyModule_AddStringMacro(m, c) PyModule_AddStringConstant(m, #c, c) + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* New in 3.5 */ +PyAPI_FUNC(int) PyModule_SetDocString(PyObject *, const char *); +PyAPI_FUNC(int) PyModule_AddFunctions(PyObject *, PyMethodDef *); +PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def); +#endif + +#define Py_CLEANUP_SUPPORTED 0x20000 + +#define PYTHON_API_VERSION 1013 +#define PYTHON_API_STRING "1013" +/* The API version is maintained (independently from the Python version) + so we can detect mismatches between the interpreter and dynamically + loaded modules. These are diagnosed by an error message but + the module is still loaded (because the mismatch can only be tested + after loading the module). The error message is intended to + explain the core dump a few seconds later. + + The symbol PYTHON_API_STRING defines the same value as a string + literal. *** PLEASE MAKE SURE THE DEFINITIONS MATCH. *** + + Please add a line or two to the top of this log for each API + version change: + + 22-Feb-2006 MvL 1013 PEP 353 - long indices for sequence lengths + + 19-Aug-2002 GvR 1012 Changes to string object struct for + interning changes, saving 3 bytes. + + 17-Jul-2001 GvR 1011 Descr-branch, just to be on the safe side + + 25-Jan-2001 FLD 1010 Parameters added to PyCode_New() and + PyFrame_New(); Python 2.1a2 + + 14-Mar-2000 GvR 1009 Unicode API added + + 3-Jan-1999 GvR 1007 Decided to change back! (Don't reuse 1008!) + + 3-Dec-1998 GvR 1008 Python 1.5.2b1 + + 18-Jan-1997 GvR 1007 string interning and other speedups + + 11-Oct-1996 GvR renamed Py_Ellipses to Py_Ellipsis :-( + + 30-Jul-1996 GvR Slice and ellipses syntax added + + 23-Jul-1996 GvR For 1.4 -- better safe than sorry this time :-) + + 7-Nov-1995 GvR Keyword arguments (should've been done at 1.3 :-( ) + + 10-Jan-1995 GvR Renamed globals to new naming scheme + + 9-Jan-1995 GvR Initial version (incompatible with older API) +*/ + +/* The PYTHON_ABI_VERSION is introduced in PEP 384. For the lifetime of + Python 3, it will stay at the value of 3; changes to the limited API + must be performed in a strictly backwards-compatible manner. */ +#define PYTHON_ABI_VERSION 3 +#define PYTHON_ABI_STRING "3" + +#ifdef Py_TRACE_REFS + /* When we are tracing reference counts, rename module creation functions so + modules compiled with incompatible settings will generate a + link-time error. */ + #define PyModule_Create2 PyModule_Create2TraceRefs + #define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs +#endif + +PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*, + int apiver); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(struct PyModuleDef*, + int apiver); +#endif + +#ifdef Py_LIMITED_API +#define PyModule_Create(module) \ + PyModule_Create2(module, PYTHON_ABI_VERSION) +#else +#define PyModule_Create(module) \ + PyModule_Create2(module, PYTHON_API_VERSION) +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* New in 3.5 */ +PyAPI_FUNC(PyObject *) PyModule_FromDefAndSpec2(PyModuleDef *def, + PyObject *spec, + int module_api_version); + +#ifdef Py_LIMITED_API +#define PyModule_FromDefAndSpec(module, spec) \ + PyModule_FromDefAndSpec2(module, spec, PYTHON_ABI_VERSION) +#else +#define PyModule_FromDefAndSpec(module, spec) \ + PyModule_FromDefAndSpec2(module, spec, PYTHON_API_VERSION) +#endif /* Py_LIMITED_API */ +#endif /* New in 3.5 */ + +#ifndef Py_LIMITED_API +PyAPI_DATA(const char *) _Py_PackageContext; +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MODSUPPORT_H */ diff --git a/winvenv/Include/moduleobject.h b/winvenv/Include/moduleobject.h new file mode 100644 index 0000000..1d8fe46 --- /dev/null +++ b/winvenv/Include/moduleobject.h @@ -0,0 +1,89 @@ + +/* Module object interface */ + +#ifndef Py_MODULEOBJECT_H +#define Py_MODULEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_DATA(PyTypeObject) PyModule_Type; + +#define PyModule_Check(op) PyObject_TypeCheck(op, &PyModule_Type) +#define PyModule_CheckExact(op) (Py_TYPE(op) == &PyModule_Type) + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject *) PyModule_NewObject( + PyObject *name + ); +#endif +PyAPI_FUNC(PyObject *) PyModule_New( + const char *name /* UTF-8 encoded string */ + ); +PyAPI_FUNC(PyObject *) PyModule_GetDict(PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject *) PyModule_GetNameObject(PyObject *); +#endif +PyAPI_FUNC(const char *) PyModule_GetName(PyObject *); +PyAPI_FUNC(const char *) PyModule_GetFilename(PyObject *) Py_DEPRECATED(3.2); +PyAPI_FUNC(PyObject *) PyModule_GetFilenameObject(PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyModule_Clear(PyObject *); +PyAPI_FUNC(void) _PyModule_ClearDict(PyObject *); +#endif +PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*); +PyAPI_FUNC(void*) PyModule_GetState(PyObject*); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* New in 3.5 */ +PyAPI_FUNC(PyObject *) PyModuleDef_Init(struct PyModuleDef*); +PyAPI_DATA(PyTypeObject) PyModuleDef_Type; +#endif + +typedef struct PyModuleDef_Base { + PyObject_HEAD + PyObject* (*m_init)(void); + Py_ssize_t m_index; + PyObject* m_copy; +} PyModuleDef_Base; + +#define PyModuleDef_HEAD_INIT { \ + PyObject_HEAD_INIT(NULL) \ + NULL, /* m_init */ \ + 0, /* m_index */ \ + NULL, /* m_copy */ \ + } + +struct PyModuleDef_Slot; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* New in 3.5 */ +typedef struct PyModuleDef_Slot{ + int slot; + void *value; +} PyModuleDef_Slot; + +#define Py_mod_create 1 +#define Py_mod_exec 2 + +#ifndef Py_LIMITED_API +#define _Py_mod_LAST_SLOT 2 +#endif + +#endif /* New in 3.5 */ + +typedef struct PyModuleDef{ + PyModuleDef_Base m_base; + const char* m_name; + const char* m_doc; + Py_ssize_t m_size; + PyMethodDef *m_methods; + struct PyModuleDef_Slot* m_slots; + traverseproc m_traverse; + inquiry m_clear; + freefunc m_free; +} PyModuleDef; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_MODULEOBJECT_H */ diff --git a/winvenv/Include/namespaceobject.h b/winvenv/Include/namespaceobject.h new file mode 100644 index 0000000..0c8d95c --- /dev/null +++ b/winvenv/Include/namespaceobject.h @@ -0,0 +1,19 @@ + +/* simple namespace object interface */ + +#ifndef NAMESPACEOBJECT_H +#define NAMESPACEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +PyAPI_DATA(PyTypeObject) _PyNamespace_Type; + +PyAPI_FUNC(PyObject *) _PyNamespace_New(PyObject *kwds); +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !NAMESPACEOBJECT_H */ diff --git a/winvenv/Include/node.h b/winvenv/Include/node.h new file mode 100644 index 0000000..40596df --- /dev/null +++ b/winvenv/Include/node.h @@ -0,0 +1,44 @@ + +/* Parse tree node interface */ + +#ifndef Py_NODE_H +#define Py_NODE_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _node { + short n_type; + char *n_str; + int n_lineno; + int n_col_offset; + int n_nchildren; + struct _node *n_child; +} node; + +PyAPI_FUNC(node *) PyNode_New(int type); +PyAPI_FUNC(int) PyNode_AddChild(node *n, int type, + char *str, int lineno, int col_offset); +PyAPI_FUNC(void) PyNode_Free(node *n); +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) _PyNode_SizeOf(node *n); +#endif + +/* Node access functions */ +#define NCH(n) ((n)->n_nchildren) + +#define CHILD(n, i) (&(n)->n_child[i]) +#define RCHILD(n, i) (CHILD(n, NCH(n) + i)) +#define TYPE(n) ((n)->n_type) +#define STR(n) ((n)->n_str) +#define LINENO(n) ((n)->n_lineno) + +/* Assert that the type of a node is what we expect */ +#define REQ(n, type) assert(TYPE(n) == (type)) + +PyAPI_FUNC(void) PyNode_ListTree(node *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_NODE_H */ diff --git a/winvenv/Include/object.h b/winvenv/Include/object.h new file mode 100644 index 0000000..c772dea --- /dev/null +++ b/winvenv/Include/object.h @@ -0,0 +1,1104 @@ +#ifndef Py_OBJECT_H +#define Py_OBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Object and type object interface */ + +/* +Objects are structures allocated on the heap. Special rules apply to +the use of objects to ensure they are properly garbage-collected. +Objects are never allocated statically or on the stack; they must be +accessed through special macros and functions only. (Type objects are +exceptions to the first rule; the standard types are represented by +statically initialized type objects, although work on type/class unification +for Python 2.2 made it possible to have heap-allocated type objects too). + +An object has a 'reference count' that is increased or decreased when a +pointer to the object is copied or deleted; when the reference count +reaches zero there are no references to the object left and it can be +removed from the heap. + +An object has a 'type' that determines what it represents and what kind +of data it contains. An object's type is fixed when it is created. +Types themselves are represented as objects; an object contains a +pointer to the corresponding type object. The type itself has a type +pointer pointing to the object representing the type 'type', which +contains a pointer to itself!). + +Objects do not float around in memory; once allocated an object keeps +the same size and address. Objects that must hold variable-size data +can contain pointers to variable-size parts of the object. Not all +objects of the same type have the same size; but the size cannot change +after allocation. (These restrictions are made so a reference to an +object can be simply a pointer -- moving an object would require +updating all the pointers, and changing an object's size would require +moving it if there was another object right next to it.) + +Objects are always accessed through pointers of the type 'PyObject *'. +The type 'PyObject' is a structure that only contains the reference count +and the type pointer. The actual memory allocated for an object +contains other data that can only be accessed after casting the pointer +to a pointer to a longer structure type. This longer type must start +with the reference count and type fields; the macro PyObject_HEAD should be +used for this (to accommodate for future changes). The implementation +of a particular object type can cast the object pointer to the proper +type and back. + +A standard interface exists for objects that contain an array of items +whose size is determined when the object is allocated. +*/ + +/* Py_DEBUG implies Py_TRACE_REFS. */ +#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) +#define Py_TRACE_REFS +#endif + +/* Py_TRACE_REFS implies Py_REF_DEBUG. */ +#if defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) +#define Py_REF_DEBUG +#endif + +#if defined(Py_LIMITED_API) && defined(Py_REF_DEBUG) +#error Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG +#endif + + +#ifdef Py_TRACE_REFS +/* Define pointers to support a doubly-linked list of all live heap objects. */ +#define _PyObject_HEAD_EXTRA \ + struct _object *_ob_next; \ + struct _object *_ob_prev; + +#define _PyObject_EXTRA_INIT 0, 0, + +#else +#define _PyObject_HEAD_EXTRA +#define _PyObject_EXTRA_INIT +#endif + +/* PyObject_HEAD defines the initial segment of every PyObject. */ +#define PyObject_HEAD PyObject ob_base; + +#define PyObject_HEAD_INIT(type) \ + { _PyObject_EXTRA_INIT \ + 1, type }, + +#define PyVarObject_HEAD_INIT(type, size) \ + { PyObject_HEAD_INIT(type) size }, + +/* PyObject_VAR_HEAD defines the initial segment of all variable-size + * container objects. These end with a declaration of an array with 1 + * element, but enough space is malloc'ed so that the array actually + * has room for ob_size elements. Note that ob_size is an element count, + * not necessarily a byte count. + */ +#define PyObject_VAR_HEAD PyVarObject ob_base; +#define Py_INVALID_SIZE (Py_ssize_t)-1 + +/* Nothing is actually declared to be a PyObject, but every pointer to + * a Python object can be cast to a PyObject*. This is inheritance built + * by hand. Similarly every pointer to a variable-size Python object can, + * in addition, be cast to PyVarObject*. + */ +typedef struct _object { + _PyObject_HEAD_EXTRA + Py_ssize_t ob_refcnt; + struct _typeobject *ob_type; +} PyObject; + +typedef struct { + PyObject ob_base; + Py_ssize_t ob_size; /* Number of items in variable part */ +} PyVarObject; + +#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) + +#ifndef Py_LIMITED_API +/********************* String Literals ****************************************/ +/* This structure helps managing static strings. The basic usage goes like this: + Instead of doing + + r = PyObject_CallMethod(o, "foo", "args", ...); + + do + + _Py_IDENTIFIER(foo); + ... + r = _PyObject_CallMethodId(o, &PyId_foo, "args", ...); + + PyId_foo is a static variable, either on block level or file level. On first + usage, the string "foo" is interned, and the structures are linked. On interpreter + shutdown, all strings are released (through _PyUnicode_ClearStaticStrings). + + Alternatively, _Py_static_string allows choosing the variable name. + _PyUnicode_FromId returns a borrowed reference to the interned string. + _PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*. +*/ +typedef struct _Py_Identifier { + struct _Py_Identifier *next; + const char* string; + PyObject *object; +} _Py_Identifier; + +#define _Py_static_string_init(value) { .next = NULL, .string = value, .object = NULL } +#define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value) +#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname) + +#endif /* !Py_LIMITED_API */ + +/* +Type objects contain a string containing the type name (to help somewhat +in debugging), the allocation parameters (see PyObject_New() and +PyObject_NewVar()), +and methods for accessing objects of the type. Methods are optional, a +nil pointer meaning that particular kind of access is not available for +this type. The Py_DECREF() macro uses the tp_dealloc method without +checking for a nil pointer; it should always be implemented except if +the implementation can guarantee that the reference count will never +reach zero (e.g., for statically allocated type objects). + +NB: the methods for certain type groups are now contained in separate +method blocks. +*/ + +typedef PyObject * (*unaryfunc)(PyObject *); +typedef PyObject * (*binaryfunc)(PyObject *, PyObject *); +typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); +typedef int (*inquiry)(PyObject *); +typedef Py_ssize_t (*lenfunc)(PyObject *); +typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t); +typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t); +typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); +typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); +typedef int(*objobjargproc)(PyObject *, PyObject *, PyObject *); + +#ifndef Py_LIMITED_API +/* buffer interface */ +typedef struct bufferinfo { + void *buf; + PyObject *obj; /* owned reference */ + Py_ssize_t len; + Py_ssize_t itemsize; /* This is Py_ssize_t so it can be + pointed to by strides in simple case.*/ + int readonly; + int ndim; + char *format; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + void *internal; +} Py_buffer; + +typedef int (*getbufferproc)(PyObject *, Py_buffer *, int); +typedef void (*releasebufferproc)(PyObject *, Py_buffer *); + +/* Maximum number of dimensions */ +#define PyBUF_MAX_NDIM 64 + +/* Flags for getting buffers */ +#define PyBUF_SIMPLE 0 +#define PyBUF_WRITABLE 0x0001 +/* we used to include an E, backwards compatible alias */ +#define PyBUF_WRITEABLE PyBUF_WRITABLE +#define PyBUF_FORMAT 0x0004 +#define PyBUF_ND 0x0008 +#define PyBUF_STRIDES (0x0010 | PyBUF_ND) +#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) +#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) +#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) +#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) + +#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE) +#define PyBUF_CONTIG_RO (PyBUF_ND) + +#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE) +#define PyBUF_STRIDED_RO (PyBUF_STRIDES) + +#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT) +#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT) + +#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT) +#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT) + + +#define PyBUF_READ 0x100 +#define PyBUF_WRITE 0x200 + +/* End buffer interface */ +#endif /* Py_LIMITED_API */ + +typedef int (*objobjproc)(PyObject *, PyObject *); +typedef int (*visitproc)(PyObject *, void *); +typedef int (*traverseproc)(PyObject *, visitproc, void *); + +#ifndef Py_LIMITED_API +typedef struct { + /* Number implementations must check *both* + arguments for proper type and implement the necessary conversions + in the slot functions themselves. */ + + binaryfunc nb_add; + binaryfunc nb_subtract; + binaryfunc nb_multiply; + binaryfunc nb_remainder; + binaryfunc nb_divmod; + ternaryfunc nb_power; + unaryfunc nb_negative; + unaryfunc nb_positive; + unaryfunc nb_absolute; + inquiry nb_bool; + unaryfunc nb_invert; + binaryfunc nb_lshift; + binaryfunc nb_rshift; + binaryfunc nb_and; + binaryfunc nb_xor; + binaryfunc nb_or; + unaryfunc nb_int; + void *nb_reserved; /* the slot formerly known as nb_long */ + unaryfunc nb_float; + + binaryfunc nb_inplace_add; + binaryfunc nb_inplace_subtract; + binaryfunc nb_inplace_multiply; + binaryfunc nb_inplace_remainder; + ternaryfunc nb_inplace_power; + binaryfunc nb_inplace_lshift; + binaryfunc nb_inplace_rshift; + binaryfunc nb_inplace_and; + binaryfunc nb_inplace_xor; + binaryfunc nb_inplace_or; + + binaryfunc nb_floor_divide; + binaryfunc nb_true_divide; + binaryfunc nb_inplace_floor_divide; + binaryfunc nb_inplace_true_divide; + + unaryfunc nb_index; + + binaryfunc nb_matrix_multiply; + binaryfunc nb_inplace_matrix_multiply; +} PyNumberMethods; + +typedef struct { + lenfunc sq_length; + binaryfunc sq_concat; + ssizeargfunc sq_repeat; + ssizeargfunc sq_item; + void *was_sq_slice; + ssizeobjargproc sq_ass_item; + void *was_sq_ass_slice; + objobjproc sq_contains; + + binaryfunc sq_inplace_concat; + ssizeargfunc sq_inplace_repeat; +} PySequenceMethods; + +typedef struct { + lenfunc mp_length; + binaryfunc mp_subscript; + objobjargproc mp_ass_subscript; +} PyMappingMethods; + +typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; +} PyAsyncMethods; + +typedef struct { + getbufferproc bf_getbuffer; + releasebufferproc bf_releasebuffer; +} PyBufferProcs; +#endif /* Py_LIMITED_API */ + +typedef void (*freefunc)(void *); +typedef void (*destructor)(PyObject *); +#ifndef Py_LIMITED_API +/* We can't provide a full compile-time check that limited-API + users won't implement tp_print. However, not defining printfunc + and making tp_print of a different function pointer type + should at least cause a warning in most cases. */ +typedef int (*printfunc)(PyObject *, FILE *, int); +#endif +typedef PyObject *(*getattrfunc)(PyObject *, char *); +typedef PyObject *(*getattrofunc)(PyObject *, PyObject *); +typedef int (*setattrfunc)(PyObject *, char *, PyObject *); +typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *); +typedef PyObject *(*reprfunc)(PyObject *); +typedef Py_hash_t (*hashfunc)(PyObject *); +typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); +typedef PyObject *(*getiterfunc) (PyObject *); +typedef PyObject *(*iternextfunc) (PyObject *); +typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *); +typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); +typedef int (*initproc)(PyObject *, PyObject *, PyObject *); +typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *); +typedef PyObject *(*allocfunc)(struct _typeobject *, Py_ssize_t); + +#ifdef Py_LIMITED_API +typedef struct _typeobject PyTypeObject; /* opaque */ +#else +typedef struct _typeobject { + PyObject_VAR_HEAD + const char *tp_name; /* For printing, in format "." */ + Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */ + + /* Methods to implement standard operations */ + + destructor tp_dealloc; + printfunc tp_print; + getattrfunc tp_getattr; + setattrfunc tp_setattr; + PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2) + or tp_reserved (Python 3) */ + reprfunc tp_repr; + + /* Method suites for standard classes */ + + PyNumberMethods *tp_as_number; + PySequenceMethods *tp_as_sequence; + PyMappingMethods *tp_as_mapping; + + /* More standard operations (here for binary compatibility) */ + + hashfunc tp_hash; + ternaryfunc tp_call; + reprfunc tp_str; + getattrofunc tp_getattro; + setattrofunc tp_setattro; + + /* Functions to access object as input/output buffer */ + PyBufferProcs *tp_as_buffer; + + /* Flags to define presence of optional/expanded features */ + unsigned long tp_flags; + + const char *tp_doc; /* Documentation string */ + + /* Assigned meaning in release 2.0 */ + /* call function for all accessible objects */ + traverseproc tp_traverse; + + /* delete references to contained objects */ + inquiry tp_clear; + + /* Assigned meaning in release 2.1 */ + /* rich comparisons */ + richcmpfunc tp_richcompare; + + /* weak reference enabler */ + Py_ssize_t tp_weaklistoffset; + + /* Iterators */ + getiterfunc tp_iter; + iternextfunc tp_iternext; + + /* Attribute descriptor and subclassing stuff */ + struct PyMethodDef *tp_methods; + struct PyMemberDef *tp_members; + struct PyGetSetDef *tp_getset; + struct _typeobject *tp_base; + PyObject *tp_dict; + descrgetfunc tp_descr_get; + descrsetfunc tp_descr_set; + Py_ssize_t tp_dictoffset; + initproc tp_init; + allocfunc tp_alloc; + newfunc tp_new; + freefunc tp_free; /* Low-level free-memory routine */ + inquiry tp_is_gc; /* For PyObject_IS_GC */ + PyObject *tp_bases; + PyObject *tp_mro; /* method resolution order */ + PyObject *tp_cache; + PyObject *tp_subclasses; + PyObject *tp_weaklist; + destructor tp_del; + + /* Type attribute cache version tag. Added in version 2.6 */ + unsigned int tp_version_tag; + + destructor tp_finalize; + +#ifdef COUNT_ALLOCS + /* these must be last and never explicitly initialized */ + Py_ssize_t tp_allocs; + Py_ssize_t tp_frees; + Py_ssize_t tp_maxalloc; + struct _typeobject *tp_prev; + struct _typeobject *tp_next; +#endif +} PyTypeObject; +#endif + +typedef struct{ + int slot; /* slot id, see below */ + void *pfunc; /* function pointer */ +} PyType_Slot; + +typedef struct{ + const char* name; + int basicsize; + int itemsize; + unsigned int flags; + PyType_Slot *slots; /* terminated by slot==0. */ +} PyType_Spec; + +PyAPI_FUNC(PyObject*) PyType_FromSpec(PyType_Spec*); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject*) PyType_FromSpecWithBases(PyType_Spec*, PyObject*); +#endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 +PyAPI_FUNC(void*) PyType_GetSlot(PyTypeObject*, int); +#endif + +#ifndef Py_LIMITED_API +/* The *real* layout of a type object when allocated on the heap */ +typedef struct _heaptypeobject { + /* Note: there's a dependency on the order of these members + in slotptr() in typeobject.c . */ + PyTypeObject ht_type; + PyAsyncMethods as_async; + PyNumberMethods as_number; + PyMappingMethods as_mapping; + PySequenceMethods as_sequence; /* as_sequence comes after as_mapping, + so that the mapping wins when both + the mapping and the sequence define + a given operator (e.g. __getitem__). + see add_operators() in typeobject.c . */ + PyBufferProcs as_buffer; + PyObject *ht_name, *ht_slots, *ht_qualname; + struct _dictkeysobject *ht_cached_keys; + /* here are optional user slots, followed by the members. */ +} PyHeapTypeObject; + +/* access macro to the members which are floating "behind" the object */ +#define PyHeapType_GET_MEMBERS(etype) \ + ((PyMemberDef *)(((char *)etype) + Py_TYPE(etype)->tp_basicsize)) +#endif + +/* Generic type check */ +PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *); +#define PyObject_TypeCheck(ob, tp) \ + (Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp))) + +PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */ +PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */ +PyAPI_DATA(PyTypeObject) PySuper_Type; /* built-in 'super' */ + +PyAPI_FUNC(unsigned long) PyType_GetFlags(PyTypeObject*); + +#define PyType_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS) +#define PyType_CheckExact(op) (Py_TYPE(op) == &PyType_Type) + +PyAPI_FUNC(int) PyType_Ready(PyTypeObject *); +PyAPI_FUNC(PyObject *) PyType_GenericAlloc(PyTypeObject *, Py_ssize_t); +PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *, + PyObject *, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(const char *) _PyType_Name(PyTypeObject *); +PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyType_LookupId(PyTypeObject *, _Py_Identifier *); +PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *); +PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *); +#endif +PyAPI_FUNC(unsigned int) PyType_ClearCache(void); +PyAPI_FUNC(void) PyType_Modified(PyTypeObject *); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *); +PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *, const char *); +#endif + +/* Generic operations on objects */ +#ifndef Py_LIMITED_API +struct _Py_Identifier; +PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int); +PyAPI_FUNC(void) _Py_BreakPoint(void); +PyAPI_FUNC(void) _PyObject_Dump(PyObject *); +#endif +PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_Str(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_ASCII(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_Bytes(PyObject *); +PyAPI_FUNC(PyObject *) PyObject_RichCompare(PyObject *, PyObject *, int); +PyAPI_FUNC(int) PyObject_RichCompareBool(PyObject *, PyObject *, int); +PyAPI_FUNC(PyObject *) PyObject_GetAttrString(PyObject *, const char *); +PyAPI_FUNC(int) PyObject_SetAttrString(PyObject *, const char *, PyObject *); +PyAPI_FUNC(int) PyObject_HasAttrString(PyObject *, const char *); +PyAPI_FUNC(PyObject *) PyObject_GetAttr(PyObject *, PyObject *); +PyAPI_FUNC(int) PyObject_SetAttr(PyObject *, PyObject *, PyObject *); +PyAPI_FUNC(int) PyObject_HasAttr(PyObject *, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyObject_IsAbstract(PyObject *); +PyAPI_FUNC(PyObject *) _PyObject_GetAttrId(PyObject *, struct _Py_Identifier *); +PyAPI_FUNC(int) _PyObject_SetAttrId(PyObject *, struct _Py_Identifier *, PyObject *); +PyAPI_FUNC(int) _PyObject_HasAttrId(PyObject *, struct _Py_Identifier *); +/* Replacements of PyObject_GetAttr() and _PyObject_GetAttrId() which + don't raise AttributeError. + + Return 1 and set *result != NULL if an attribute is found. + Return 0 and set *result == NULL if an attribute is not found; + an AttributeError is silenced. + Return -1 and set *result == NULL if an error other than AttributeError + is raised. +*/ +PyAPI_FUNC(int) _PyObject_LookupAttr(PyObject *, PyObject *, PyObject **); +PyAPI_FUNC(int) _PyObject_LookupAttrId(PyObject *, struct _Py_Identifier *, PyObject **); +PyAPI_FUNC(PyObject **) _PyObject_GetDictPtr(PyObject *); +#endif +PyAPI_FUNC(PyObject *) PyObject_SelfIter(PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyObject_NextNotImplemented(PyObject *); +#endif +PyAPI_FUNC(PyObject *) PyObject_GenericGetAttr(PyObject *, PyObject *); +PyAPI_FUNC(int) PyObject_GenericSetAttr(PyObject *, + PyObject *, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(int) PyObject_GenericSetDict(PyObject *, PyObject *, void *); +#endif +PyAPI_FUNC(Py_hash_t) PyObject_Hash(PyObject *); +PyAPI_FUNC(Py_hash_t) PyObject_HashNotImplemented(PyObject *); +PyAPI_FUNC(int) PyObject_IsTrue(PyObject *); +PyAPI_FUNC(int) PyObject_Not(PyObject *); +PyAPI_FUNC(int) PyCallable_Check(PyObject *); + +PyAPI_FUNC(void) PyObject_ClearWeakRefs(PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) PyObject_CallFinalizer(PyObject *); +PyAPI_FUNC(int) PyObject_CallFinalizerFromDealloc(PyObject *); +#endif + +#ifndef Py_LIMITED_API +/* Same as PyObject_Generic{Get,Set}Attr, but passing the attributes + dict as the last parameter. */ +PyAPI_FUNC(PyObject *) +_PyObject_GenericGetAttrWithDict(PyObject *, PyObject *, PyObject *, int); +PyAPI_FUNC(int) +_PyObject_GenericSetAttrWithDict(PyObject *, PyObject *, + PyObject *, PyObject *); +#endif /* !Py_LIMITED_API */ + +/* Helper to look up a builtin object */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) +_PyObject_GetBuiltin(const char *name); +#endif + +/* PyObject_Dir(obj) acts like Python builtins.dir(obj), returning a + list of strings. PyObject_Dir(NULL) is like builtins.dir(), + returning the names of the current locals. In this case, if there are + no current locals, NULL is returned, and PyErr_Occurred() is false. +*/ +PyAPI_FUNC(PyObject *) PyObject_Dir(PyObject *); + + +/* Helpers for printing recursive container types */ +PyAPI_FUNC(int) Py_ReprEnter(PyObject *); +PyAPI_FUNC(void) Py_ReprLeave(PyObject *); + +/* Flag bits for printing: */ +#define Py_PRINT_RAW 1 /* No string quotes etc. */ + +/* +`Type flags (tp_flags) + +These flags are used to extend the type structure in a backwards-compatible +fashion. Extensions can use the flags to indicate (and test) when a given +type structure contains a new feature. The Python core will use these when +introducing new functionality between major revisions (to avoid mid-version +changes in the PYTHON_API_VERSION). + +Arbitration of the flag bit positions will need to be coordinated among +all extension writers who publicly release their extensions (this will +be fewer than you might expect!).. + +Most flags were removed as of Python 3.0 to make room for new flags. (Some +flags are not for backwards compatibility but to indicate the presence of an +optional feature; these flags remain of course.) + +Type definitions should use Py_TPFLAGS_DEFAULT for their tp_flags value. + +Code can use PyType_HasFeature(type_ob, flag_value) to test whether the +given type object has a specified feature. +*/ + +/* Set if the type object is dynamically allocated */ +#define Py_TPFLAGS_HEAPTYPE (1UL << 9) + +/* Set if the type allows subclassing */ +#define Py_TPFLAGS_BASETYPE (1UL << 10) + +/* Set if the type is 'ready' -- fully initialized */ +#define Py_TPFLAGS_READY (1UL << 12) + +/* Set while the type is being 'readied', to prevent recursive ready calls */ +#define Py_TPFLAGS_READYING (1UL << 13) + +/* Objects support garbage collection (see objimp.h) */ +#define Py_TPFLAGS_HAVE_GC (1UL << 14) + +/* These two bits are preserved for Stackless Python, next after this is 17 */ +#ifdef STACKLESS +#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION (3UL << 15) +#else +#define Py_TPFLAGS_HAVE_STACKLESS_EXTENSION 0 +#endif + +/* Objects support type attribute cache */ +#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18) +#define Py_TPFLAGS_VALID_VERSION_TAG (1UL << 19) + +/* Type is abstract and cannot be instantiated */ +#define Py_TPFLAGS_IS_ABSTRACT (1UL << 20) + +/* These flags are used to determine if a type is a subclass. */ +#define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24) +#define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25) +#define Py_TPFLAGS_TUPLE_SUBCLASS (1UL << 26) +#define Py_TPFLAGS_BYTES_SUBCLASS (1UL << 27) +#define Py_TPFLAGS_UNICODE_SUBCLASS (1UL << 28) +#define Py_TPFLAGS_DICT_SUBCLASS (1UL << 29) +#define Py_TPFLAGS_BASE_EXC_SUBCLASS (1UL << 30) +#define Py_TPFLAGS_TYPE_SUBCLASS (1UL << 31) + +#define Py_TPFLAGS_DEFAULT ( \ + Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | \ + Py_TPFLAGS_HAVE_VERSION_TAG | \ + 0) + +/* NOTE: The following flags reuse lower bits (removed as part of the + * Python 3.0 transition). */ + +/* Type structure has tp_finalize member (3.4) */ +#define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0) + +#ifdef Py_LIMITED_API +#define PyType_HasFeature(t,f) ((PyType_GetFlags(t) & (f)) != 0) +#else +#define PyType_HasFeature(t,f) (((t)->tp_flags & (f)) != 0) +#endif +#define PyType_FastSubclass(t,f) PyType_HasFeature(t,f) + + +/* +The macros Py_INCREF(op) and Py_DECREF(op) are used to increment or decrement +reference counts. Py_DECREF calls the object's deallocator function when +the refcount falls to 0; for +objects that don't contain references to other objects or heap memory +this can be the standard function free(). Both macros can be used +wherever a void expression is allowed. The argument must not be a +NULL pointer. If it may be NULL, use Py_XINCREF/Py_XDECREF instead. +The macro _Py_NewReference(op) initialize reference counts to 1, and +in special builds (Py_REF_DEBUG, Py_TRACE_REFS) performs additional +bookkeeping appropriate to the special build. + +We assume that the reference count field can never overflow; this can +be proven when the size of the field is the same as the pointer size, so +we ignore the possibility. Provided a C int is at least 32 bits (which +is implicitly assumed in many parts of this code), that's enough for +about 2**31 references to an object. + +XXX The following became out of date in Python 2.2, but I'm not sure +XXX what the full truth is now. Certainly, heap-allocated type objects +XXX can and should be deallocated. +Type objects should never be deallocated; the type pointer in an object +is not considered to be a reference to the type object, to save +complications in the deallocation function. (This is actually a +decision that's up to the implementer of each new type so if you want, +you can count such references to the type object.) +*/ + +/* First define a pile of simple helper macros, one set per special + * build symbol. These either expand to the obvious things, or to + * nothing at all when the special mode isn't in effect. The main + * macros can later be defined just once then, yet expand to different + * things depending on which special build options are and aren't in effect. + * Trust me : while painful, this is 20x easier to understand than, + * e.g, defining _Py_NewReference five different times in a maze of nested + * #ifdefs (we used to do that -- it was impenetrable). + */ +#ifdef Py_REF_DEBUG +PyAPI_DATA(Py_ssize_t) _Py_RefTotal; +PyAPI_FUNC(void) _Py_NegativeRefcount(const char *fname, + int lineno, PyObject *op); +PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void); +#define _Py_INC_REFTOTAL _Py_RefTotal++ +#define _Py_DEC_REFTOTAL _Py_RefTotal-- +#define _Py_REF_DEBUG_COMMA , +#define _Py_CHECK_REFCNT(OP) \ +{ if (((PyObject*)OP)->ob_refcnt < 0) \ + _Py_NegativeRefcount(__FILE__, __LINE__, \ + (PyObject *)(OP)); \ +} +/* Py_REF_DEBUG also controls the display of refcounts and memory block + * allocations at the interactive prompt and at interpreter shutdown + */ +PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void); +#else +#define _Py_INC_REFTOTAL +#define _Py_DEC_REFTOTAL +#define _Py_REF_DEBUG_COMMA +#define _Py_CHECK_REFCNT(OP) /* a semicolon */; +#endif /* Py_REF_DEBUG */ + +#ifdef COUNT_ALLOCS +PyAPI_FUNC(void) inc_count(PyTypeObject *); +PyAPI_FUNC(void) dec_count(PyTypeObject *); +#define _Py_INC_TPALLOCS(OP) inc_count(Py_TYPE(OP)) +#define _Py_INC_TPFREES(OP) dec_count(Py_TYPE(OP)) +#define _Py_DEC_TPFREES(OP) Py_TYPE(OP)->tp_frees-- +#define _Py_COUNT_ALLOCS_COMMA , +#else +#define _Py_INC_TPALLOCS(OP) +#define _Py_INC_TPFREES(OP) +#define _Py_DEC_TPFREES(OP) +#define _Py_COUNT_ALLOCS_COMMA +#endif /* COUNT_ALLOCS */ + +#ifdef Py_TRACE_REFS +/* Py_TRACE_REFS is such major surgery that we call external routines. */ +PyAPI_FUNC(void) _Py_NewReference(PyObject *); +PyAPI_FUNC(void) _Py_ForgetReference(PyObject *); +PyAPI_FUNC(void) _Py_Dealloc(PyObject *); +PyAPI_FUNC(void) _Py_PrintReferences(FILE *); +PyAPI_FUNC(void) _Py_PrintReferenceAddresses(FILE *); +PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force); + +#else +/* Without Py_TRACE_REFS, there's little enough to do that we expand code + * inline. + */ +#define _Py_NewReference(op) ( \ + _Py_INC_TPALLOCS(op) _Py_COUNT_ALLOCS_COMMA \ + _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ + Py_REFCNT(op) = 1) + +#define _Py_ForgetReference(op) _Py_INC_TPFREES(op) + +#ifdef Py_LIMITED_API +PyAPI_FUNC(void) _Py_Dealloc(PyObject *); +#else +#define _Py_Dealloc(op) ( \ + _Py_INC_TPFREES(op) _Py_COUNT_ALLOCS_COMMA \ + (*Py_TYPE(op)->tp_dealloc)((PyObject *)(op))) +#endif +#endif /* !Py_TRACE_REFS */ + +#define Py_INCREF(op) ( \ + _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA \ + ((PyObject *)(op))->ob_refcnt++) + +#define Py_DECREF(op) \ + do { \ + PyObject *_py_decref_tmp = (PyObject *)(op); \ + if (_Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA \ + --(_py_decref_tmp)->ob_refcnt != 0) \ + _Py_CHECK_REFCNT(_py_decref_tmp) \ + else \ + _Py_Dealloc(_py_decref_tmp); \ + } while (0) + +/* Safely decref `op` and set `op` to NULL, especially useful in tp_clear + * and tp_dealloc implementations. + * + * Note that "the obvious" code can be deadly: + * + * Py_XDECREF(op); + * op = NULL; + * + * Typically, `op` is something like self->containee, and `self` is done + * using its `containee` member. In the code sequence above, suppose + * `containee` is non-NULL with a refcount of 1. Its refcount falls to + * 0 on the first line, which can trigger an arbitrary amount of code, + * possibly including finalizers (like __del__ methods or weakref callbacks) + * coded in Python, which in turn can release the GIL and allow other threads + * to run, etc. Such code may even invoke methods of `self` again, or cause + * cyclic gc to trigger, but-- oops! --self->containee still points to the + * object being torn down, and it may be in an insane state while being torn + * down. This has in fact been a rich historic source of miserable (rare & + * hard-to-diagnose) segfaulting (and other) bugs. + * + * The safe way is: + * + * Py_CLEAR(op); + * + * That arranges to set `op` to NULL _before_ decref'ing, so that any code + * triggered as a side-effect of `op` getting torn down no longer believes + * `op` points to a valid object. + * + * There are cases where it's safe to use the naive code, but they're brittle. + * For example, if `op` points to a Python integer, you know that destroying + * one of those can't cause problems -- but in part that relies on that + * Python integers aren't currently weakly referencable. Best practice is + * to use Py_CLEAR() even if you can't think of a reason for why you need to. + */ +#define Py_CLEAR(op) \ + do { \ + PyObject *_py_tmp = (PyObject *)(op); \ + if (_py_tmp != NULL) { \ + (op) = NULL; \ + Py_DECREF(_py_tmp); \ + } \ + } while (0) + +/* Macros to use in case the object pointer may be NULL: */ +#define Py_XINCREF(op) \ + do { \ + PyObject *_py_xincref_tmp = (PyObject *)(op); \ + if (_py_xincref_tmp != NULL) \ + Py_INCREF(_py_xincref_tmp); \ + } while (0) + +#define Py_XDECREF(op) \ + do { \ + PyObject *_py_xdecref_tmp = (PyObject *)(op); \ + if (_py_xdecref_tmp != NULL) \ + Py_DECREF(_py_xdecref_tmp); \ + } while (0) + +#ifndef Py_LIMITED_API +/* Safely decref `op` and set `op` to `op2`. + * + * As in case of Py_CLEAR "the obvious" code can be deadly: + * + * Py_DECREF(op); + * op = op2; + * + * The safe way is: + * + * Py_SETREF(op, op2); + * + * That arranges to set `op` to `op2` _before_ decref'ing, so that any code + * triggered as a side-effect of `op` getting torn down no longer believes + * `op` points to a valid object. + * + * Py_XSETREF is a variant of Py_SETREF that uses Py_XDECREF instead of + * Py_DECREF. + */ + +#define Py_SETREF(op, op2) \ + do { \ + PyObject *_py_tmp = (PyObject *)(op); \ + (op) = (op2); \ + Py_DECREF(_py_tmp); \ + } while (0) + +#define Py_XSETREF(op, op2) \ + do { \ + PyObject *_py_tmp = (PyObject *)(op); \ + (op) = (op2); \ + Py_XDECREF(_py_tmp); \ + } while (0) + +#endif /* ifndef Py_LIMITED_API */ + +/* +These are provided as conveniences to Python runtime embedders, so that +they can have object code that is not dependent on Python compilation flags. +*/ +PyAPI_FUNC(void) Py_IncRef(PyObject *); +PyAPI_FUNC(void) Py_DecRef(PyObject *); + +#ifndef Py_LIMITED_API +PyAPI_DATA(PyTypeObject) _PyNone_Type; +PyAPI_DATA(PyTypeObject) _PyNotImplemented_Type; +#endif /* !Py_LIMITED_API */ + +/* +_Py_NoneStruct is an object of undefined type which can be used in contexts +where NULL (nil) is not suitable (since NULL often means 'error'). + +Don't forget to apply Py_INCREF() when returning this value!!! +*/ +PyAPI_DATA(PyObject) _Py_NoneStruct; /* Don't use this directly */ +#define Py_None (&_Py_NoneStruct) + +/* Macro for returning Py_None from a function */ +#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None + +/* +Py_NotImplemented is a singleton used to signal that an operation is +not implemented for a given type combination. +*/ +PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */ +#define Py_NotImplemented (&_Py_NotImplementedStruct) + +/* Macro for returning Py_NotImplemented from a function */ +#define Py_RETURN_NOTIMPLEMENTED \ + return Py_INCREF(Py_NotImplemented), Py_NotImplemented + +/* Rich comparison opcodes */ +#define Py_LT 0 +#define Py_LE 1 +#define Py_EQ 2 +#define Py_NE 3 +#define Py_GT 4 +#define Py_GE 5 + +/* + * Macro for implementing rich comparisons + * + * Needs to be a macro because any C-comparable type can be used. + */ +#define Py_RETURN_RICHCOMPARE(val1, val2, op) \ + do { \ + switch (op) { \ + case Py_EQ: if ((val1) == (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \ + case Py_NE: if ((val1) != (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \ + case Py_LT: if ((val1) < (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \ + case Py_GT: if ((val1) > (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \ + case Py_LE: if ((val1) <= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \ + case Py_GE: if ((val1) >= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \ + default: \ + Py_UNREACHABLE(); \ + } \ + } while (0) + +#ifndef Py_LIMITED_API +/* Maps Py_LT to Py_GT, ..., Py_GE to Py_LE. + * Defined in object.c. + */ +PyAPI_DATA(int) _Py_SwappedOp[]; +#endif /* !Py_LIMITED_API */ + + +/* +More conventions +================ + +Argument Checking +----------------- + +Functions that take objects as arguments normally don't check for nil +arguments, but they do check the type of the argument, and return an +error if the function doesn't apply to the type. + +Failure Modes +------------- + +Functions may fail for a variety of reasons, including running out of +memory. This is communicated to the caller in two ways: an error string +is set (see errors.h), and the function result differs: functions that +normally return a pointer return NULL for failure, functions returning +an integer return -1 (which could be a legal return value too!), and +other functions return 0 for success and -1 for failure. +Callers should always check for errors before using the result. If +an error was set, the caller must either explicitly clear it, or pass +the error on to its caller. + +Reference Counts +---------------- + +It takes a while to get used to the proper usage of reference counts. + +Functions that create an object set the reference count to 1; such new +objects must be stored somewhere or destroyed again with Py_DECREF(). +Some functions that 'store' objects, such as PyTuple_SetItem() and +PyList_SetItem(), +don't increment the reference count of the object, since the most +frequent use is to store a fresh object. Functions that 'retrieve' +objects, such as PyTuple_GetItem() and PyDict_GetItemString(), also +don't increment +the reference count, since most frequently the object is only looked at +quickly. Thus, to retrieve an object and store it again, the caller +must call Py_INCREF() explicitly. + +NOTE: functions that 'consume' a reference count, like +PyList_SetItem(), consume the reference even if the object wasn't +successfully stored, to simplify error handling. + +It seems attractive to make other functions that take an object as +argument consume a reference count; however, this may quickly get +confusing (even the current practice is already confusing). Consider +it carefully, it may save lots of calls to Py_INCREF() and Py_DECREF() at +times. +*/ + + +/* Trashcan mechanism, thanks to Christian Tismer. + +When deallocating a container object, it's possible to trigger an unbounded +chain of deallocations, as each Py_DECREF in turn drops the refcount on "the +next" object in the chain to 0. This can easily lead to stack faults, and +especially in threads (which typically have less stack space to work with). + +A container object that participates in cyclic gc can avoid this by +bracketing the body of its tp_dealloc function with a pair of macros: + +static void +mytype_dealloc(mytype *p) +{ + ... declarations go here ... + + PyObject_GC_UnTrack(p); // must untrack first + Py_TRASHCAN_SAFE_BEGIN(p) + ... The body of the deallocator goes here, including all calls ... + ... to Py_DECREF on contained objects. ... + Py_TRASHCAN_SAFE_END(p) +} + +CAUTION: Never return from the middle of the body! If the body needs to +"get out early", put a label immediately before the Py_TRASHCAN_SAFE_END +call, and goto it. Else the call-depth counter (see below) will stay +above 0 forever, and the trashcan will never get emptied. + +How it works: The BEGIN macro increments a call-depth counter. So long +as this counter is small, the body of the deallocator is run directly without +further ado. But if the counter gets large, it instead adds p to a list of +objects to be deallocated later, skips the body of the deallocator, and +resumes execution after the END macro. The tp_dealloc routine then returns +without deallocating anything (and so unbounded call-stack depth is avoided). + +When the call stack finishes unwinding again, code generated by the END macro +notices this, and calls another routine to deallocate all the objects that +may have been added to the list of deferred deallocations. In effect, a +chain of N deallocations is broken into (N-1)/(PyTrash_UNWIND_LEVEL-1) pieces, +with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL. +*/ + +#ifndef Py_LIMITED_API +/* This is the old private API, invoked by the macros before 3.2.4. + Kept for binary compatibility of extensions using the stable ABI. */ +PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*); +PyAPI_FUNC(void) _PyTrash_destroy_chain(void); +#endif /* !Py_LIMITED_API */ + +/* The new thread-safe private API, invoked by the macros below. */ +PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*); +PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void); + +#define PyTrash_UNWIND_LEVEL 50 + +#define Py_TRASHCAN_SAFE_BEGIN(op) \ + do { \ + PyThreadState *_tstate = PyThreadState_GET(); \ + if (_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ + ++_tstate->trash_delete_nesting; + /* The body of the deallocator is here. */ +#define Py_TRASHCAN_SAFE_END(op) \ + --_tstate->trash_delete_nesting; \ + if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ + _PyTrash_thread_destroy_chain(); \ + } \ + else \ + _PyTrash_thread_deposit_object((PyObject*)op); \ + } while (0); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) +_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks, + size_t sizeof_block); +PyAPI_FUNC(void) +_PyObject_DebugTypeStats(FILE *out); +#endif /* ifndef Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_OBJECT_H */ diff --git a/winvenv/Include/objimpl.h b/winvenv/Include/objimpl.h new file mode 100644 index 0000000..057bb50 --- /dev/null +++ b/winvenv/Include/objimpl.h @@ -0,0 +1,370 @@ +/* The PyObject_ memory family: high-level object memory interfaces. + See pymem.h for the low-level PyMem_ family. +*/ + +#ifndef Py_OBJIMPL_H +#define Py_OBJIMPL_H + +#include "pymem.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* BEWARE: + + Each interface exports both functions and macros. Extension modules should + use the functions, to ensure binary compatibility across Python versions. + Because the Python implementation is free to change internal details, and + the macros may (or may not) expose details for speed, if you do use the + macros you must recompile your extensions with each Python release. + + Never mix calls to PyObject_ memory functions with calls to the platform + malloc/realloc/ calloc/free, or with calls to PyMem_. +*/ + +/* +Functions and macros for modules that implement new object types. + + - PyObject_New(type, typeobj) allocates memory for a new object of the given + type, and initializes part of it. 'type' must be the C structure type used + to represent the object, and 'typeobj' the address of the corresponding + type object. Reference count and type pointer are filled in; the rest of + the bytes of the object are *undefined*! The resulting expression type is + 'type *'. The size of the object is determined by the tp_basicsize field + of the type object. + + - PyObject_NewVar(type, typeobj, n) is similar but allocates a variable-size + object with room for n items. In addition to the refcount and type pointer + fields, this also fills in the ob_size field. + + - PyObject_Del(op) releases the memory allocated for an object. It does not + run a destructor -- it only frees the memory. PyObject_Free is identical. + + - PyObject_Init(op, typeobj) and PyObject_InitVar(op, typeobj, n) don't + allocate memory. Instead of a 'type' parameter, they take a pointer to a + new object (allocated by an arbitrary allocator), and initialize its object + header fields. + +Note that objects created with PyObject_{New, NewVar} are allocated using the +specialized Python allocator (implemented in obmalloc.c), if WITH_PYMALLOC is +enabled. In addition, a special debugging allocator is used if PYMALLOC_DEBUG +is also #defined. + +In case a specific form of memory management is needed (for example, if you +must use the platform malloc heap(s), or shared memory, or C++ local storage or +operator new), you must first allocate the object with your custom allocator, +then pass its pointer to PyObject_{Init, InitVar} for filling in its Python- +specific fields: reference count, type pointer, possibly others. You should +be aware that Python has no control over these objects because they don't +cooperate with the Python memory manager. Such objects may not be eligible +for automatic garbage collection and you have to make sure that they are +released accordingly whenever their destructor gets called (cf. the specific +form of memory management you're using). + +Unless you have specific memory management requirements, use +PyObject_{New, NewVar, Del}. +*/ + +/* + * Raw object memory interface + * =========================== + */ + +/* Functions to call the same malloc/realloc/free as used by Python's + object allocator. If WITH_PYMALLOC is enabled, these may differ from + the platform malloc/realloc/free. The Python object allocator is + designed for fast, cache-conscious allocation of many "small" objects, + and with low hidden memory overhead. + + PyObject_Malloc(0) returns a unique non-NULL pointer if possible. + + PyObject_Realloc(NULL, n) acts like PyObject_Malloc(n). + PyObject_Realloc(p != NULL, 0) does not return NULL, or free the memory + at p. + + Returned pointers must be checked for NULL explicitly; no action is + performed on failure other than to return NULL (no warning it printed, no + exception is set, etc). + + For allocating objects, use PyObject_{New, NewVar} instead whenever + possible. The PyObject_{Malloc, Realloc, Free} family is exposed + so that you can exploit Python's small-block allocator for non-object + uses. If you must use these routines to allocate object memory, make sure + the object gets initialized via PyObject_{Init, InitVar} after obtaining + the raw memory. +*/ +PyAPI_FUNC(void *) PyObject_Malloc(size_t size); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_FUNC(void *) PyObject_Calloc(size_t nelem, size_t elsize); +#endif +PyAPI_FUNC(void *) PyObject_Realloc(void *ptr, size_t new_size); +PyAPI_FUNC(void) PyObject_Free(void *ptr); + +#ifndef Py_LIMITED_API +/* This function returns the number of allocated memory blocks, regardless of size */ +PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void); +#endif /* !Py_LIMITED_API */ + +/* Macros */ +#ifdef WITH_PYMALLOC +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out); +#endif /* #ifndef Py_LIMITED_API */ +#endif + +/* Macros */ +#define PyObject_MALLOC PyObject_Malloc +#define PyObject_REALLOC PyObject_Realloc +#define PyObject_FREE PyObject_Free +#define PyObject_Del PyObject_Free +#define PyObject_DEL PyObject_Free + + +/* + * Generic object allocator interface + * ================================== + */ + +/* Functions */ +PyAPI_FUNC(PyObject *) PyObject_Init(PyObject *, PyTypeObject *); +PyAPI_FUNC(PyVarObject *) PyObject_InitVar(PyVarObject *, + PyTypeObject *, Py_ssize_t); +PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *); +PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t); + +#define PyObject_New(type, typeobj) \ + ( (type *) _PyObject_New(typeobj) ) +#define PyObject_NewVar(type, typeobj, n) \ + ( (type *) _PyObject_NewVar((typeobj), (n)) ) + +/* Macros trading binary compatibility for speed. See also pymem.h. + Note that these macros expect non-NULL object pointers.*/ +#define PyObject_INIT(op, typeobj) \ + ( Py_TYPE(op) = (typeobj), _Py_NewReference((PyObject *)(op)), (op) ) +#define PyObject_INIT_VAR(op, typeobj, size) \ + ( Py_SIZE(op) = (size), PyObject_INIT((op), (typeobj)) ) + +#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize ) + +/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a + vrbl-size object with nitems items, exclusive of gc overhead (if any). The + value is rounded up to the closest multiple of sizeof(void *), in order to + ensure that pointer fields at the end of the object are correctly aligned + for the platform (this is of special importance for subclasses of, e.g., + str or int, so that pointers can be stored after the embedded data). + + Note that there's no memory wastage in doing this, as malloc has to + return (at worst) pointer-aligned memory anyway. +*/ +#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0 +# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2" +#endif + +#define _PyObject_VAR_SIZE(typeobj, nitems) \ + _Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \ + (nitems)*(typeobj)->tp_itemsize, \ + SIZEOF_VOID_P) + +#define PyObject_NEW(type, typeobj) \ +( (type *) PyObject_Init( \ + (PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) ) + +#define PyObject_NEW_VAR(type, typeobj, n) \ +( (type *) PyObject_InitVar( \ + (PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE((typeobj),(n)) ),\ + (typeobj), (n)) ) + +/* This example code implements an object constructor with a custom + allocator, where PyObject_New is inlined, and shows the important + distinction between two steps (at least): + 1) the actual allocation of the object storage; + 2) the initialization of the Python specific fields + in this storage with PyObject_{Init, InitVar}. + + PyObject * + YourObject_New(...) + { + PyObject *op; + + op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct)); + if (op == NULL) + return PyErr_NoMemory(); + + PyObject_Init(op, &YourTypeStruct); + + op->ob_field = value; + ... + return op; + } + + Note that in C++, the use of the new operator usually implies that + the 1st step is performed automatically for you, so in a C++ class + constructor you would start directly with PyObject_Init/InitVar +*/ + +#ifndef Py_LIMITED_API +typedef struct { + /* user context passed as the first argument to the 2 functions */ + void *ctx; + + /* allocate an arena of size bytes */ + void* (*alloc) (void *ctx, size_t size); + + /* free an arena */ + void (*free) (void *ctx, void *ptr, size_t size); +} PyObjectArenaAllocator; + +/* Get the arena allocator. */ +PyAPI_FUNC(void) PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator); + +/* Set the arena allocator. */ +PyAPI_FUNC(void) PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator); +#endif + + +/* + * Garbage Collection Support + * ========================== + */ + +/* C equivalent of gc.collect() which ignores the state of gc.enabled. */ +PyAPI_FUNC(Py_ssize_t) PyGC_Collect(void); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) _PyGC_CollectNoFail(void); +PyAPI_FUNC(Py_ssize_t) _PyGC_CollectIfEnabled(void); +#endif + +/* Test if a type has a GC head */ +#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC) + +/* Test if an object has a GC head */ +#define PyObject_IS_GC(o) (PyType_IS_GC(Py_TYPE(o)) && \ + (Py_TYPE(o)->tp_is_gc == NULL || Py_TYPE(o)->tp_is_gc(o))) + +PyAPI_FUNC(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, Py_ssize_t); +#define PyObject_GC_Resize(type, op, n) \ + ( (type *) _PyObject_GC_Resize((PyVarObject *)(op), (n)) ) + +/* GC information is stored BEFORE the object structure. */ +#ifndef Py_LIMITED_API +typedef union _gc_head { + struct { + union _gc_head *gc_next; + union _gc_head *gc_prev; + Py_ssize_t gc_refs; + } gc; + double dummy; /* force worst-case alignment */ +} PyGC_Head; + +extern PyGC_Head *_PyGC_generation0; + +#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1) + +/* Bit 0 is set when tp_finalize is called */ +#define _PyGC_REFS_MASK_FINALIZED (1 << 0) +/* The (N-1) most significant bits contain the gc state / refcount */ +#define _PyGC_REFS_SHIFT (1) +#define _PyGC_REFS_MASK (((size_t) -1) << _PyGC_REFS_SHIFT) + +#define _PyGCHead_REFS(g) ((g)->gc.gc_refs >> _PyGC_REFS_SHIFT) +#define _PyGCHead_SET_REFS(g, v) do { \ + (g)->gc.gc_refs = ((g)->gc.gc_refs & ~_PyGC_REFS_MASK) \ + | (((size_t)(v)) << _PyGC_REFS_SHIFT); \ + } while (0) +#define _PyGCHead_DECREF(g) ((g)->gc.gc_refs -= 1 << _PyGC_REFS_SHIFT) + +#define _PyGCHead_FINALIZED(g) (((g)->gc.gc_refs & _PyGC_REFS_MASK_FINALIZED) != 0) +#define _PyGCHead_SET_FINALIZED(g, v) do { \ + (g)->gc.gc_refs = ((g)->gc.gc_refs & ~_PyGC_REFS_MASK_FINALIZED) \ + | (v != 0); \ + } while (0) + +#define _PyGC_FINALIZED(o) _PyGCHead_FINALIZED(_Py_AS_GC(o)) +#define _PyGC_SET_FINALIZED(o, v) _PyGCHead_SET_FINALIZED(_Py_AS_GC(o), v) + +#define _PyGC_REFS(o) _PyGCHead_REFS(_Py_AS_GC(o)) + +#define _PyGC_REFS_UNTRACKED (-2) +#define _PyGC_REFS_REACHABLE (-3) +#define _PyGC_REFS_TENTATIVELY_UNREACHABLE (-4) + +/* Tell the GC to track this object. NB: While the object is tracked the + * collector it must be safe to call the ob_traverse method. */ +#define _PyObject_GC_TRACK(o) do { \ + PyGC_Head *g = _Py_AS_GC(o); \ + if (_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED) \ + Py_FatalError("GC object already tracked"); \ + _PyGCHead_SET_REFS(g, _PyGC_REFS_REACHABLE); \ + g->gc.gc_next = _PyGC_generation0; \ + g->gc.gc_prev = _PyGC_generation0->gc.gc_prev; \ + g->gc.gc_prev->gc.gc_next = g; \ + _PyGC_generation0->gc.gc_prev = g; \ + } while (0); + +/* Tell the GC to stop tracking this object. + * gc_next doesn't need to be set to NULL, but doing so is a good + * way to provoke memory errors if calling code is confused. + */ +#define _PyObject_GC_UNTRACK(o) do { \ + PyGC_Head *g = _Py_AS_GC(o); \ + assert(_PyGCHead_REFS(g) != _PyGC_REFS_UNTRACKED); \ + _PyGCHead_SET_REFS(g, _PyGC_REFS_UNTRACKED); \ + g->gc.gc_prev->gc.gc_next = g->gc.gc_next; \ + g->gc.gc_next->gc.gc_prev = g->gc.gc_prev; \ + g->gc.gc_next = NULL; \ + } while (0); + +/* True if the object is currently tracked by the GC. */ +#define _PyObject_GC_IS_TRACKED(o) \ + (_PyGC_REFS(o) != _PyGC_REFS_UNTRACKED) + +/* True if the object may be tracked by the GC in the future, or already is. + This can be useful to implement some optimizations. */ +#define _PyObject_GC_MAY_BE_TRACKED(obj) \ + (PyObject_IS_GC(obj) && \ + (!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj))) +#endif /* Py_LIMITED_API */ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t size); +PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t size); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *); +PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t); +PyAPI_FUNC(void) PyObject_GC_Track(void *); +PyAPI_FUNC(void) PyObject_GC_UnTrack(void *); +PyAPI_FUNC(void) PyObject_GC_Del(void *); + +#define PyObject_GC_New(type, typeobj) \ + ( (type *) _PyObject_GC_New(typeobj) ) +#define PyObject_GC_NewVar(type, typeobj, n) \ + ( (type *) _PyObject_GC_NewVar((typeobj), (n)) ) + + +/* Utility macro to help write tp_traverse functions. + * To use this macro, the tp_traverse function must name its arguments + * "visit" and "arg". This is intended to keep tp_traverse functions + * looking as much alike as possible. + */ +#define Py_VISIT(op) \ + do { \ + if (op) { \ + int vret = visit((PyObject *)(op), arg); \ + if (vret) \ + return vret; \ + } \ + } while (0) + + +/* Test if a type supports weak references */ +#define PyType_SUPPORTS_WEAKREFS(t) ((t)->tp_weaklistoffset > 0) + +#define PyObject_GET_WEAKREFS_LISTPTR(o) \ + ((PyObject **) (((char *) (o)) + Py_TYPE(o)->tp_weaklistoffset)) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_OBJIMPL_H */ diff --git a/winvenv/Include/odictobject.h b/winvenv/Include/odictobject.h new file mode 100644 index 0000000..8378dc4 --- /dev/null +++ b/winvenv/Include/odictobject.h @@ -0,0 +1,43 @@ +#ifndef Py_ODICTOBJECT_H +#define Py_ODICTOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* OrderedDict */ +/* This API is optional and mostly redundant. */ + +#ifndef Py_LIMITED_API + +typedef struct _odictobject PyODictObject; + +PyAPI_DATA(PyTypeObject) PyODict_Type; +PyAPI_DATA(PyTypeObject) PyODictIter_Type; +PyAPI_DATA(PyTypeObject) PyODictKeys_Type; +PyAPI_DATA(PyTypeObject) PyODictItems_Type; +PyAPI_DATA(PyTypeObject) PyODictValues_Type; + +#define PyODict_Check(op) PyObject_TypeCheck(op, &PyODict_Type) +#define PyODict_CheckExact(op) (Py_TYPE(op) == &PyODict_Type) +#define PyODict_SIZE(op) PyDict_GET_SIZE((op)) + +PyAPI_FUNC(PyObject *) PyODict_New(void); +PyAPI_FUNC(int) PyODict_SetItem(PyObject *od, PyObject *key, PyObject *item); +PyAPI_FUNC(int) PyODict_DelItem(PyObject *od, PyObject *key); + +/* wrappers around PyDict* functions */ +#define PyODict_GetItem(od, key) PyDict_GetItem((PyObject *)od, key) +#define PyODict_GetItemWithError(od, key) \ + PyDict_GetItemWithError((PyObject *)od, key) +#define PyODict_Contains(od, key) PyDict_Contains((PyObject *)od, key) +#define PyODict_Size(od) PyDict_Size((PyObject *)od) +#define PyODict_GetItemString(od, key) \ + PyDict_GetItemString((PyObject *)od, key) + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ODICTOBJECT_H */ diff --git a/winvenv/Include/opcode.h b/winvenv/Include/opcode.h new file mode 100644 index 0000000..fc6cbf3 --- /dev/null +++ b/winvenv/Include/opcode.h @@ -0,0 +1,147 @@ +/* Auto-generated by Tools/scripts/generate_opcode_h.py */ +#ifndef Py_OPCODE_H +#define Py_OPCODE_H +#ifdef __cplusplus +extern "C" { +#endif + + + /* Instruction opcodes for compiled code */ +#define POP_TOP 1 +#define ROT_TWO 2 +#define ROT_THREE 3 +#define DUP_TOP 4 +#define DUP_TOP_TWO 5 +#define NOP 9 +#define UNARY_POSITIVE 10 +#define UNARY_NEGATIVE 11 +#define UNARY_NOT 12 +#define UNARY_INVERT 15 +#define BINARY_MATRIX_MULTIPLY 16 +#define INPLACE_MATRIX_MULTIPLY 17 +#define BINARY_POWER 19 +#define BINARY_MULTIPLY 20 +#define BINARY_MODULO 22 +#define BINARY_ADD 23 +#define BINARY_SUBTRACT 24 +#define BINARY_SUBSCR 25 +#define BINARY_FLOOR_DIVIDE 26 +#define BINARY_TRUE_DIVIDE 27 +#define INPLACE_FLOOR_DIVIDE 28 +#define INPLACE_TRUE_DIVIDE 29 +#define GET_AITER 50 +#define GET_ANEXT 51 +#define BEFORE_ASYNC_WITH 52 +#define INPLACE_ADD 55 +#define INPLACE_SUBTRACT 56 +#define INPLACE_MULTIPLY 57 +#define INPLACE_MODULO 59 +#define STORE_SUBSCR 60 +#define DELETE_SUBSCR 61 +#define BINARY_LSHIFT 62 +#define BINARY_RSHIFT 63 +#define BINARY_AND 64 +#define BINARY_XOR 65 +#define BINARY_OR 66 +#define INPLACE_POWER 67 +#define GET_ITER 68 +#define GET_YIELD_FROM_ITER 69 +#define PRINT_EXPR 70 +#define LOAD_BUILD_CLASS 71 +#define YIELD_FROM 72 +#define GET_AWAITABLE 73 +#define INPLACE_LSHIFT 75 +#define INPLACE_RSHIFT 76 +#define INPLACE_AND 77 +#define INPLACE_XOR 78 +#define INPLACE_OR 79 +#define BREAK_LOOP 80 +#define WITH_CLEANUP_START 81 +#define WITH_CLEANUP_FINISH 82 +#define RETURN_VALUE 83 +#define IMPORT_STAR 84 +#define SETUP_ANNOTATIONS 85 +#define YIELD_VALUE 86 +#define POP_BLOCK 87 +#define END_FINALLY 88 +#define POP_EXCEPT 89 +#define HAVE_ARGUMENT 90 +#define STORE_NAME 90 +#define DELETE_NAME 91 +#define UNPACK_SEQUENCE 92 +#define FOR_ITER 93 +#define UNPACK_EX 94 +#define STORE_ATTR 95 +#define DELETE_ATTR 96 +#define STORE_GLOBAL 97 +#define DELETE_GLOBAL 98 +#define LOAD_CONST 100 +#define LOAD_NAME 101 +#define BUILD_TUPLE 102 +#define BUILD_LIST 103 +#define BUILD_SET 104 +#define BUILD_MAP 105 +#define LOAD_ATTR 106 +#define COMPARE_OP 107 +#define IMPORT_NAME 108 +#define IMPORT_FROM 109 +#define JUMP_FORWARD 110 +#define JUMP_IF_FALSE_OR_POP 111 +#define JUMP_IF_TRUE_OR_POP 112 +#define JUMP_ABSOLUTE 113 +#define POP_JUMP_IF_FALSE 114 +#define POP_JUMP_IF_TRUE 115 +#define LOAD_GLOBAL 116 +#define CONTINUE_LOOP 119 +#define SETUP_LOOP 120 +#define SETUP_EXCEPT 121 +#define SETUP_FINALLY 122 +#define LOAD_FAST 124 +#define STORE_FAST 125 +#define DELETE_FAST 126 +#define RAISE_VARARGS 130 +#define CALL_FUNCTION 131 +#define MAKE_FUNCTION 132 +#define BUILD_SLICE 133 +#define LOAD_CLOSURE 135 +#define LOAD_DEREF 136 +#define STORE_DEREF 137 +#define DELETE_DEREF 138 +#define CALL_FUNCTION_KW 141 +#define CALL_FUNCTION_EX 142 +#define SETUP_WITH 143 +#define EXTENDED_ARG 144 +#define LIST_APPEND 145 +#define SET_ADD 146 +#define MAP_ADD 147 +#define LOAD_CLASSDEREF 148 +#define BUILD_LIST_UNPACK 149 +#define BUILD_MAP_UNPACK 150 +#define BUILD_MAP_UNPACK_WITH_CALL 151 +#define BUILD_TUPLE_UNPACK 152 +#define BUILD_SET_UNPACK 153 +#define SETUP_ASYNC_WITH 154 +#define FORMAT_VALUE 155 +#define BUILD_CONST_KEY_MAP 156 +#define BUILD_STRING 157 +#define BUILD_TUPLE_UNPACK_WITH_CALL 158 +#define LOAD_METHOD 160 +#define CALL_METHOD 161 + +/* EXCEPT_HANDLER is a special, implicit block type which is created when + entering an except handler. It is not an opcode but we define it here + as we want it to be available to both frameobject.c and ceval.c, while + remaining private.*/ +#define EXCEPT_HANDLER 257 + + +enum cmp_op {PyCmp_LT=Py_LT, PyCmp_LE=Py_LE, PyCmp_EQ=Py_EQ, PyCmp_NE=Py_NE, + PyCmp_GT=Py_GT, PyCmp_GE=Py_GE, PyCmp_IN, PyCmp_NOT_IN, + PyCmp_IS, PyCmp_IS_NOT, PyCmp_EXC_MATCH, PyCmp_BAD}; + +#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_OPCODE_H */ diff --git a/winvenv/Include/osdefs.h b/winvenv/Include/osdefs.h new file mode 100644 index 0000000..bd84c1c --- /dev/null +++ b/winvenv/Include/osdefs.h @@ -0,0 +1,47 @@ +#ifndef Py_OSDEFS_H +#define Py_OSDEFS_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Operating system dependencies */ + +#ifdef MS_WINDOWS +#define SEP L'\\' +#define ALTSEP L'/' +#define MAXPATHLEN 256 +#define DELIM L';' +#endif + +/* Filename separator */ +#ifndef SEP +#define SEP L'/' +#endif + +/* Max pathname length */ +#ifdef __hpux +#include +#include +#ifndef PATH_MAX +#define PATH_MAX MAXPATHLEN +#endif +#endif + +#ifndef MAXPATHLEN +#if defined(PATH_MAX) && PATH_MAX > 1024 +#define MAXPATHLEN PATH_MAX +#else +#define MAXPATHLEN 1024 +#endif +#endif + +/* Search path entry delimiter */ +#ifndef DELIM +#define DELIM L':' +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_OSDEFS_H */ diff --git a/winvenv/Include/osmodule.h b/winvenv/Include/osmodule.h new file mode 100644 index 0000000..9095c2f --- /dev/null +++ b/winvenv/Include/osmodule.h @@ -0,0 +1,17 @@ + +/* os module interface */ + +#ifndef Py_OSMODULE_H +#define Py_OSMODULE_H +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 +PyAPI_FUNC(PyObject *) PyOS_FSPath(PyObject *path); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_OSMODULE_H */ diff --git a/winvenv/Include/parsetok.h b/winvenv/Include/parsetok.h new file mode 100644 index 0000000..c9407a3 --- /dev/null +++ b/winvenv/Include/parsetok.h @@ -0,0 +1,108 @@ + +/* Parser-tokenizer link interface */ +#ifndef Py_LIMITED_API +#ifndef Py_PARSETOK_H +#define Py_PARSETOK_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int error; +#ifndef PGEN + /* The filename is useless for pgen, see comment in tok_state structure */ + PyObject *filename; +#endif + int lineno; + int offset; + char *text; /* UTF-8-encoded string */ + int token; + int expected; +} perrdetail; + +#if 0 +#define PyPARSE_YIELD_IS_KEYWORD 0x0001 +#endif + +#define PyPARSE_DONT_IMPLY_DEDENT 0x0002 + +#if 0 +#define PyPARSE_WITH_IS_KEYWORD 0x0003 +#define PyPARSE_PRINT_IS_FUNCTION 0x0004 +#define PyPARSE_UNICODE_LITERALS 0x0008 +#endif + +#define PyPARSE_IGNORE_COOKIE 0x0010 +#define PyPARSE_BARRY_AS_BDFL 0x0020 + +PyAPI_FUNC(node *) PyParser_ParseString(const char *, grammar *, int, + perrdetail *); +PyAPI_FUNC(node *) PyParser_ParseFile (FILE *, const char *, grammar *, int, + const char *, const char *, + perrdetail *); + +PyAPI_FUNC(node *) PyParser_ParseStringFlags(const char *, grammar *, int, + perrdetail *, int); +PyAPI_FUNC(node *) PyParser_ParseFileFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + const char *enc, + grammar *g, + int start, + const char *ps1, + const char *ps2, + perrdetail *err_ret, + int flags); +PyAPI_FUNC(node *) PyParser_ParseFileFlagsEx( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + const char *enc, + grammar *g, + int start, + const char *ps1, + const char *ps2, + perrdetail *err_ret, + int *flags); +PyAPI_FUNC(node *) PyParser_ParseFileObject( + FILE *fp, + PyObject *filename, + const char *enc, + grammar *g, + int start, + const char *ps1, + const char *ps2, + perrdetail *err_ret, + int *flags); + +PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilename( + const char *s, + const char *filename, /* decoded from the filesystem encoding */ + grammar *g, + int start, + perrdetail *err_ret, + int flags); +PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilenameEx( + const char *s, + const char *filename, /* decoded from the filesystem encoding */ + grammar *g, + int start, + perrdetail *err_ret, + int *flags); +PyAPI_FUNC(node *) PyParser_ParseStringObject( + const char *s, + PyObject *filename, + grammar *g, + int start, + perrdetail *err_ret, + int *flags); + +/* Note that the following functions are defined in pythonrun.c, + not in parsetok.c */ +PyAPI_FUNC(void) PyParser_SetError(perrdetail *); +PyAPI_FUNC(void) PyParser_ClearError(perrdetail *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PARSETOK_H */ +#endif /* !Py_LIMITED_API */ diff --git a/winvenv/Include/patchlevel.h b/winvenv/Include/patchlevel.h new file mode 100644 index 0000000..667facb --- /dev/null +++ b/winvenv/Include/patchlevel.h @@ -0,0 +1,35 @@ + +/* Python version identification scheme. + + When the major or minor version changes, the VERSION variable in + configure.ac must also be changed. + + There is also (independent) API version information in modsupport.h. +*/ + +/* Values for PY_RELEASE_LEVEL */ +#define PY_RELEASE_LEVEL_ALPHA 0xA +#define PY_RELEASE_LEVEL_BETA 0xB +#define PY_RELEASE_LEVEL_GAMMA 0xC /* For release candidates */ +#define PY_RELEASE_LEVEL_FINAL 0xF /* Serial should be 0 here */ + /* Higher for patch releases */ + +/* Version parsed out into numeric values */ +/*--start constants--*/ +#define PY_MAJOR_VERSION 3 +#define PY_MINOR_VERSION 7 +#define PY_MICRO_VERSION 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 + +/* Version as a string */ +#define PY_VERSION "3.7.1" +/*--end constants--*/ + +/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. + Use this for numeric comparisons, e.g. #if PY_VERSION_HEX >= ... */ +#define PY_VERSION_HEX ((PY_MAJOR_VERSION << 24) | \ + (PY_MINOR_VERSION << 16) | \ + (PY_MICRO_VERSION << 8) | \ + (PY_RELEASE_LEVEL << 4) | \ + (PY_RELEASE_SERIAL << 0)) diff --git a/winvenv/Include/pgen.h b/winvenv/Include/pgen.h new file mode 100644 index 0000000..8a325ed --- /dev/null +++ b/winvenv/Include/pgen.h @@ -0,0 +1,18 @@ +#ifndef Py_PGEN_H +#define Py_PGEN_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Parser generator interface */ + +extern grammar *meta_grammar(void); + +struct _node; +extern grammar *pgen(struct _node *); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PGEN_H */ diff --git a/winvenv/Include/pgenheaders.h b/winvenv/Include/pgenheaders.h new file mode 100644 index 0000000..dbc5e0a --- /dev/null +++ b/winvenv/Include/pgenheaders.h @@ -0,0 +1,43 @@ +#ifndef Py_PGENHEADERS_H +#define Py_PGENHEADERS_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Include files and extern declarations used by most of the parser. */ + +#include "Python.h" + +PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); +PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); + +#define addarc _Py_addarc +#define addbit _Py_addbit +#define adddfa _Py_adddfa +#define addfirstsets _Py_addfirstsets +#define addlabel _Py_addlabel +#define addstate _Py_addstate +#define delbitset _Py_delbitset +#define dumptree _Py_dumptree +#define findlabel _Py_findlabel +#define freegrammar _Py_freegrammar +#define mergebitset _Py_mergebitset +#define meta_grammar _Py_meta_grammar +#define newbitset _Py_newbitset +#define newgrammar _Py_newgrammar +#define pgen _Py_pgen +#define printgrammar _Py_printgrammar +#define printnonterminals _Py_printnonterminals +#define printtree _Py_printtree +#define samebitset _Py_samebitset +#define showtree _Py_showtree +#define tok_dump _Py_tok_dump +#define translatelabels _Py_translatelabels + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PGENHEADERS_H */ diff --git a/winvenv/Include/py_curses.h b/winvenv/Include/py_curses.h new file mode 100644 index 0000000..0eebc36 --- /dev/null +++ b/winvenv/Include/py_curses.h @@ -0,0 +1,159 @@ + +#ifndef Py_CURSES_H +#define Py_CURSES_H + +#ifdef __APPLE__ +/* +** On Mac OS X 10.2 [n]curses.h and stdlib.h use different guards +** against multiple definition of wchar_t. +*/ +#ifdef _BSD_WCHAR_T_DEFINED_ +#define _WCHAR_T +#endif +#endif /* __APPLE__ */ + +/* On FreeBSD, [n]curses.h and stdlib.h/wchar.h use different guards + against multiple definition of wchar_t and wint_t. */ +#if defined(__FreeBSD__) && defined(_XOPEN_SOURCE_EXTENDED) +# ifndef __wchar_t +# define __wchar_t +# endif +# ifndef __wint_t +# define __wint_t +# endif +#endif + +#if !defined(HAVE_CURSES_IS_PAD) && defined(WINDOW_HAS_FLAGS) +/* The following definition is necessary for ncurses 5.7; without it, + some of [n]curses.h set NCURSES_OPAQUE to 1, and then Python + can't get at the WINDOW flags field. */ +#define NCURSES_OPAQUE 0 +#endif + +#ifdef HAVE_NCURSES_H +#include +#else +#include +#endif + +#ifdef HAVE_NCURSES_H +/* configure was checking , but we will + use , which has some or all these features. */ +#if !defined(WINDOW_HAS_FLAGS) && !(NCURSES_OPAQUE+0) +#define WINDOW_HAS_FLAGS 1 +#endif +#if !defined(HAVE_CURSES_IS_PAD) && NCURSES_VERSION_PATCH+0 >= 20090906 +#define HAVE_CURSES_IS_PAD 1 +#endif +#ifndef MVWDELCH_IS_EXPRESSION +#define MVWDELCH_IS_EXPRESSION 1 +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define PyCurses_API_pointers 4 + +/* Type declarations */ + +typedef struct { + PyObject_HEAD + WINDOW *win; + char *encoding; +} PyCursesWindowObject; + +#define PyCursesWindow_Check(v) (Py_TYPE(v) == &PyCursesWindow_Type) + +#define PyCurses_CAPSULE_NAME "_curses._C_API" + + +#ifdef CURSES_MODULE +/* This section is used when compiling _cursesmodule.c */ + +#else +/* This section is used in modules that use the _cursesmodule API */ + +static void **PyCurses_API; + +#define PyCursesWindow_Type (*(PyTypeObject *) PyCurses_API[0]) +#define PyCursesSetupTermCalled {if (! ((int (*)(void))PyCurses_API[1]) () ) return NULL;} +#define PyCursesInitialised {if (! ((int (*)(void))PyCurses_API[2]) () ) return NULL;} +#define PyCursesInitialisedColor {if (! ((int (*)(void))PyCurses_API[3]) () ) return NULL;} + +#define import_curses() \ + PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1); + +#endif + +/* general error messages */ +static const char catchall_ERR[] = "curses function returned ERR"; +static const char catchall_NULL[] = "curses function returned NULL"; + +/* Function Prototype Macros - They are ugly but very, very useful. ;-) + + X - function name + TYPE - parameter Type + ERGSTR - format string for construction of the return value + PARSESTR - format string for argument parsing + */ + +#define NoArgNoReturnFunction(X) \ +static PyObject *PyCurses_ ## X (PyObject *self) \ +{ \ + PyCursesInitialised \ + return PyCursesCheckERR(X(), # X); } + +#define NoArgOrFlagNoReturnFunction(X) \ +static PyObject *PyCurses_ ## X (PyObject *self, PyObject *args) \ +{ \ + int flag = 0; \ + PyCursesInitialised \ + switch(PyTuple_Size(args)) { \ + case 0: \ + return PyCursesCheckERR(X(), # X); \ + case 1: \ + if (!PyArg_ParseTuple(args, "i;True(1) or False(0)", &flag)) return NULL; \ + if (flag) return PyCursesCheckERR(X(), # X); \ + else return PyCursesCheckERR(no ## X (), # X); \ + default: \ + PyErr_SetString(PyExc_TypeError, # X " requires 0 or 1 arguments"); \ + return NULL; } } + +#define NoArgReturnIntFunction(X) \ +static PyObject *PyCurses_ ## X (PyObject *self) \ +{ \ + PyCursesInitialised \ + return PyLong_FromLong((long) X()); } + + +#define NoArgReturnStringFunction(X) \ +static PyObject *PyCurses_ ## X (PyObject *self) \ +{ \ + PyCursesInitialised \ + return PyBytes_FromString(X()); } + +#define NoArgTrueFalseFunction(X) \ +static PyObject *PyCurses_ ## X (PyObject *self) \ +{ \ + PyCursesInitialised \ + if (X () == FALSE) { \ + Py_RETURN_FALSE; \ + } \ + Py_RETURN_TRUE; } + +#define NoArgNoReturnVoidFunction(X) \ +static PyObject *PyCurses_ ## X (PyObject *self) \ +{ \ + PyCursesInitialised \ + X(); \ + Py_RETURN_NONE; } + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(Py_CURSES_H) */ + + diff --git a/winvenv/Include/pyarena.h b/winvenv/Include/pyarena.h new file mode 100644 index 0000000..db3ad01 --- /dev/null +++ b/winvenv/Include/pyarena.h @@ -0,0 +1,64 @@ +/* An arena-like memory interface for the compiler. + */ + +#ifndef Py_LIMITED_API +#ifndef Py_PYARENA_H +#define Py_PYARENA_H + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _arena PyArena; + + /* PyArena_New() and PyArena_Free() create a new arena and free it, + respectively. Once an arena has been created, it can be used + to allocate memory via PyArena_Malloc(). Pointers to PyObject can + also be registered with the arena via PyArena_AddPyObject(), and the + arena will ensure that the PyObjects stay alive at least until + PyArena_Free() is called. When an arena is freed, all the memory it + allocated is freed, the arena releases internal references to registered + PyObject*, and none of its pointers are valid. + XXX (tim) What does "none of its pointers are valid" mean? Does it + XXX mean that pointers previously obtained via PyArena_Malloc() are + XXX no longer valid? (That's clearly true, but not sure that's what + XXX the text is trying to say.) + + PyArena_New() returns an arena pointer. On error, it + returns a negative number and sets an exception. + XXX (tim): Not true. On error, PyArena_New() actually returns NULL, + XXX and looks like it may or may not set an exception (e.g., if the + XXX internal PyList_New(0) returns NULL, PyArena_New() passes that on + XXX and an exception is set; OTOH, if the internal + XXX block_new(DEFAULT_BLOCK_SIZE) returns NULL, that's passed on but + XXX an exception is not set in that case). + */ + PyAPI_FUNC(PyArena *) PyArena_New(void); + PyAPI_FUNC(void) PyArena_Free(PyArena *); + + /* Mostly like malloc(), return the address of a block of memory spanning + * `size` bytes, or return NULL (without setting an exception) if enough + * new memory can't be obtained. Unlike malloc(0), PyArena_Malloc() with + * size=0 does not guarantee to return a unique pointer (the pointer + * returned may equal one or more other pointers obtained from + * PyArena_Malloc()). + * Note that pointers obtained via PyArena_Malloc() must never be passed to + * the system free() or realloc(), or to any of Python's similar memory- + * management functions. PyArena_Malloc()-obtained pointers remain valid + * until PyArena_Free(ar) is called, at which point all pointers obtained + * from the arena `ar` become invalid simultaneously. + */ + PyAPI_FUNC(void *) PyArena_Malloc(PyArena *, size_t size); + + /* This routine isn't a proper arena allocation routine. It takes + * a PyObject* and records it so that it can be DECREFed when the + * arena is freed. + */ + PyAPI_FUNC(int) PyArena_AddPyObject(PyArena *, PyObject *); + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_PYARENA_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/pyatomic.h b/winvenv/Include/pyatomic.h new file mode 100644 index 0000000..9a497a6 --- /dev/null +++ b/winvenv/Include/pyatomic.h @@ -0,0 +1,535 @@ +#ifndef Py_ATOMIC_H +#define Py_ATOMIC_H +#ifdef Py_BUILD_CORE + +#include "dynamic_annotations.h" + +#include "pyconfig.h" + +#if defined(HAVE_STD_ATOMIC) +#include +#endif + + +#if defined(_MSC_VER) +#include +#include +#endif + +/* This is modeled after the atomics interface from C1x, according to + * the draft at + * http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1425.pdf. + * Operations and types are named the same except with a _Py_ prefix + * and have the same semantics. + * + * Beware, the implementations here are deep magic. + */ + +#if defined(HAVE_STD_ATOMIC) + +typedef enum _Py_memory_order { + _Py_memory_order_relaxed = memory_order_relaxed, + _Py_memory_order_acquire = memory_order_acquire, + _Py_memory_order_release = memory_order_release, + _Py_memory_order_acq_rel = memory_order_acq_rel, + _Py_memory_order_seq_cst = memory_order_seq_cst +} _Py_memory_order; + +typedef struct _Py_atomic_address { + atomic_uintptr_t _value; +} _Py_atomic_address; + +typedef struct _Py_atomic_int { + atomic_int _value; +} _Py_atomic_int; + +#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \ + atomic_signal_fence(ORDER) + +#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \ + atomic_thread_fence(ORDER) + +#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ + atomic_store_explicit(&(ATOMIC_VAL)->_value, NEW_VAL, ORDER) + +#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ + atomic_load_explicit(&(ATOMIC_VAL)->_value, ORDER) + +/* Use builtin atomic operations in GCC >= 4.7 */ +#elif defined(HAVE_BUILTIN_ATOMIC) + +typedef enum _Py_memory_order { + _Py_memory_order_relaxed = __ATOMIC_RELAXED, + _Py_memory_order_acquire = __ATOMIC_ACQUIRE, + _Py_memory_order_release = __ATOMIC_RELEASE, + _Py_memory_order_acq_rel = __ATOMIC_ACQ_REL, + _Py_memory_order_seq_cst = __ATOMIC_SEQ_CST +} _Py_memory_order; + +typedef struct _Py_atomic_address { + uintptr_t _value; +} _Py_atomic_address; + +typedef struct _Py_atomic_int { + int _value; +} _Py_atomic_int; + +#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \ + __atomic_signal_fence(ORDER) + +#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \ + __atomic_thread_fence(ORDER) + +#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ + (assert((ORDER) == __ATOMIC_RELAXED \ + || (ORDER) == __ATOMIC_SEQ_CST \ + || (ORDER) == __ATOMIC_RELEASE), \ + __atomic_store_n(&(ATOMIC_VAL)->_value, NEW_VAL, ORDER)) + +#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ + (assert((ORDER) == __ATOMIC_RELAXED \ + || (ORDER) == __ATOMIC_SEQ_CST \ + || (ORDER) == __ATOMIC_ACQUIRE \ + || (ORDER) == __ATOMIC_CONSUME), \ + __atomic_load_n(&(ATOMIC_VAL)->_value, ORDER)) + +/* Only support GCC (for expression statements) and x86 (for simple + * atomic semantics) and MSVC x86/x64/ARM */ +#elif defined(__GNUC__) && (defined(__i386__) || defined(__amd64)) +typedef enum _Py_memory_order { + _Py_memory_order_relaxed, + _Py_memory_order_acquire, + _Py_memory_order_release, + _Py_memory_order_acq_rel, + _Py_memory_order_seq_cst +} _Py_memory_order; + +typedef struct _Py_atomic_address { + uintptr_t _value; +} _Py_atomic_address; + +typedef struct _Py_atomic_int { + int _value; +} _Py_atomic_int; + + +static __inline__ void +_Py_atomic_signal_fence(_Py_memory_order order) +{ + if (order != _Py_memory_order_relaxed) + __asm__ volatile("":::"memory"); +} + +static __inline__ void +_Py_atomic_thread_fence(_Py_memory_order order) +{ + if (order != _Py_memory_order_relaxed) + __asm__ volatile("mfence":::"memory"); +} + +/* Tell the race checker about this operation's effects. */ +static __inline__ void +_Py_ANNOTATE_MEMORY_ORDER(const volatile void *address, _Py_memory_order order) +{ + (void)address; /* shut up -Wunused-parameter */ + switch(order) { + case _Py_memory_order_release: + case _Py_memory_order_acq_rel: + case _Py_memory_order_seq_cst: + _Py_ANNOTATE_HAPPENS_BEFORE(address); + break; + case _Py_memory_order_relaxed: + case _Py_memory_order_acquire: + break; + } + switch(order) { + case _Py_memory_order_acquire: + case _Py_memory_order_acq_rel: + case _Py_memory_order_seq_cst: + _Py_ANNOTATE_HAPPENS_AFTER(address); + break; + case _Py_memory_order_relaxed: + case _Py_memory_order_release: + break; + } +} + +#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ + __extension__ ({ \ + __typeof__(ATOMIC_VAL) atomic_val = ATOMIC_VAL; \ + __typeof__(atomic_val->_value) new_val = NEW_VAL;\ + volatile __typeof__(new_val) *volatile_data = &atomic_val->_value; \ + _Py_memory_order order = ORDER; \ + _Py_ANNOTATE_MEMORY_ORDER(atomic_val, order); \ + \ + /* Perform the operation. */ \ + _Py_ANNOTATE_IGNORE_WRITES_BEGIN(); \ + switch(order) { \ + case _Py_memory_order_release: \ + _Py_atomic_signal_fence(_Py_memory_order_release); \ + /* fallthrough */ \ + case _Py_memory_order_relaxed: \ + *volatile_data = new_val; \ + break; \ + \ + case _Py_memory_order_acquire: \ + case _Py_memory_order_acq_rel: \ + case _Py_memory_order_seq_cst: \ + __asm__ volatile("xchg %0, %1" \ + : "+r"(new_val) \ + : "m"(atomic_val->_value) \ + : "memory"); \ + break; \ + } \ + _Py_ANNOTATE_IGNORE_WRITES_END(); \ + }) + +#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ + __extension__ ({ \ + __typeof__(ATOMIC_VAL) atomic_val = ATOMIC_VAL; \ + __typeof__(atomic_val->_value) result; \ + volatile __typeof__(result) *volatile_data = &atomic_val->_value; \ + _Py_memory_order order = ORDER; \ + _Py_ANNOTATE_MEMORY_ORDER(atomic_val, order); \ + \ + /* Perform the operation. */ \ + _Py_ANNOTATE_IGNORE_READS_BEGIN(); \ + switch(order) { \ + case _Py_memory_order_release: \ + case _Py_memory_order_acq_rel: \ + case _Py_memory_order_seq_cst: \ + /* Loads on x86 are not releases by default, so need a */ \ + /* thread fence. */ \ + _Py_atomic_thread_fence(_Py_memory_order_release); \ + break; \ + default: \ + /* No fence */ \ + break; \ + } \ + result = *volatile_data; \ + switch(order) { \ + case _Py_memory_order_acquire: \ + case _Py_memory_order_acq_rel: \ + case _Py_memory_order_seq_cst: \ + /* Loads on x86 are automatically acquire operations so */ \ + /* can get by with just a compiler fence. */ \ + _Py_atomic_signal_fence(_Py_memory_order_acquire); \ + break; \ + default: \ + /* No fence */ \ + break; \ + } \ + _Py_ANNOTATE_IGNORE_READS_END(); \ + result; \ + }) + +#elif defined(_MSC_VER) +/* _Interlocked* functions provide a full memory barrier and are therefore + enough for acq_rel and seq_cst. If the HLE variants aren't available + in hardware they will fall back to a full memory barrier as well. + + This might affect performance but likely only in some very specific and + hard to meassure scenario. +*/ +#if defined(_M_IX86) || defined(_M_X64) +typedef enum _Py_memory_order { + _Py_memory_order_relaxed, + _Py_memory_order_acquire, + _Py_memory_order_release, + _Py_memory_order_acq_rel, + _Py_memory_order_seq_cst +} _Py_memory_order; + +typedef struct _Py_atomic_address { + volatile uintptr_t _value; +} _Py_atomic_address; + +typedef struct _Py_atomic_int { + volatile int _value; +} _Py_atomic_int; + + +#if defined(_M_X64) +#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \ + switch (ORDER) { \ + case _Py_memory_order_acquire: \ + _InterlockedExchange64_HLEAcquire((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + break; \ + case _Py_memory_order_release: \ + _InterlockedExchange64_HLERelease((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + break; \ + default: \ + _InterlockedExchange64((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + break; \ + } +#else +#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) ((void)0); +#endif + +#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \ + switch (ORDER) { \ + case _Py_memory_order_acquire: \ + _InterlockedExchange_HLEAcquire((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + break; \ + case _Py_memory_order_release: \ + _InterlockedExchange_HLERelease((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + break; \ + default: \ + _InterlockedExchange((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + break; \ + } + +#if defined(_M_X64) +/* This has to be an intptr_t for now. + gil_created() uses -1 as a sentinel value, if this returns + a uintptr_t it will do an unsigned compare and crash +*/ +inline intptr_t _Py_atomic_load_64bit(volatile uintptr_t* value, int order) { + __int64 old; + switch (order) { + case _Py_memory_order_acquire: + { + do { + old = *value; + } while(_InterlockedCompareExchange64_HLEAcquire((volatile __int64*)value, old, old) != old); + break; + } + case _Py_memory_order_release: + { + do { + old = *value; + } while(_InterlockedCompareExchange64_HLERelease((volatile __int64*)value, old, old) != old); + break; + } + case _Py_memory_order_relaxed: + old = *value; + break; + default: + { + do { + old = *value; + } while(_InterlockedCompareExchange64((volatile __int64*)value, old, old) != old); + break; + } + } + return old; +} + +#else +#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) *ATOMIC_VAL +#endif + +inline int _Py_atomic_load_32bit(volatile int* value, int order) { + long old; + switch (order) { + case _Py_memory_order_acquire: + { + do { + old = *value; + } while(_InterlockedCompareExchange_HLEAcquire((volatile long*)value, old, old) != old); + break; + } + case _Py_memory_order_release: + { + do { + old = *value; + } while(_InterlockedCompareExchange_HLERelease((volatile long*)value, old, old) != old); + break; + } + case _Py_memory_order_relaxed: + old = *value; + break; + default: + { + do { + old = *value; + } while(_InterlockedCompareExchange((volatile long*)value, old, old) != old); + break; + } + } + return old; +} + +#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ + if (sizeof(*ATOMIC_VAL._value) == 8) { \ + _Py_atomic_store_64bit((volatile long long*)ATOMIC_VAL._value, NEW_VAL, ORDER) } else { \ + _Py_atomic_store_32bit((volatile long*)ATOMIC_VAL._value, NEW_VAL, ORDER) } + +#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ + ( \ + sizeof(*(ATOMIC_VAL._value)) == 8 ? \ + _Py_atomic_load_64bit((volatile long long*)ATOMIC_VAL._value, ORDER) : \ + _Py_atomic_load_32bit((volatile long*)ATOMIC_VAL._value, ORDER) \ + ) +#elif defined(_M_ARM) || defined(_M_ARM64) +typedef enum _Py_memory_order { + _Py_memory_order_relaxed, + _Py_memory_order_acquire, + _Py_memory_order_release, + _Py_memory_order_acq_rel, + _Py_memory_order_seq_cst +} _Py_memory_order; + +typedef struct _Py_atomic_address { + volatile uintptr_t _value; +} _Py_atomic_address; + +typedef struct _Py_atomic_int { + volatile int _value; +} _Py_atomic_int; + + +#if defined(_M_ARM64) +#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \ + switch (ORDER) { \ + case _Py_memory_order_acquire: \ + _InterlockedExchange64_acq((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + break; \ + case _Py_memory_order_release: \ + _InterlockedExchange64_rel((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + break; \ + default: \ + _InterlockedExchange64((__int64 volatile*)ATOMIC_VAL, (__int64)NEW_VAL); \ + break; \ + } +#else +#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) ((void)0); +#endif + +#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \ + switch (ORDER) { \ + case _Py_memory_order_acquire: \ + _InterlockedExchange_acq((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + break; \ + case _Py_memory_order_release: \ + _InterlockedExchange_rel((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + break; \ + default: \ + _InterlockedExchange((volatile long*)ATOMIC_VAL, (int)NEW_VAL); \ + break; \ + } + +#if defined(_M_ARM64) +/* This has to be an intptr_t for now. + gil_created() uses -1 as a sentinel value, if this returns + a uintptr_t it will do an unsigned compare and crash +*/ +inline intptr_t _Py_atomic_load_64bit(volatile uintptr_t* value, int order) { + uintptr_t old; + switch (order) { + case _Py_memory_order_acquire: + { + do { + old = *value; + } while(_InterlockedCompareExchange64_acq(value, old, old) != old); + break; + } + case _Py_memory_order_release: + { + do { + old = *value; + } while(_InterlockedCompareExchange64_rel(value, old, old) != old); + break; + } + case _Py_memory_order_relaxed: + old = *value; + break; + default: + { + do { + old = *value; + } while(_InterlockedCompareExchange64(value, old, old) != old); + break; + } + } + return old; +} + +#else +#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) *ATOMIC_VAL +#endif + +inline int _Py_atomic_load_32bit(volatile int* value, int order) { + int old; + switch (order) { + case _Py_memory_order_acquire: + { + do { + old = *value; + } while(_InterlockedCompareExchange_acq(value, old, old) != old); + break; + } + case _Py_memory_order_release: + { + do { + old = *value; + } while(_InterlockedCompareExchange_rel(value, old, old) != old); + break; + } + case _Py_memory_order_relaxed: + old = *value; + break; + default: + { + do { + old = *value; + } while(_InterlockedCompareExchange(value, old, old) != old); + break; + } + } + return old; +} + +#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ + if (sizeof(*ATOMIC_VAL._value) == 8) { \ + _Py_atomic_store_64bit(ATOMIC_VAL._value, NEW_VAL, ORDER) } else { \ + _Py_atomic_store_32bit(ATOMIC_VAL._value, NEW_VAL, ORDER) } + +#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ + ( \ + sizeof(*(ATOMIC_VAL._value)) == 8 ? \ + _Py_atomic_load_64bit(ATOMIC_VAL._value, ORDER) : \ + _Py_atomic_load_32bit(ATOMIC_VAL._value, ORDER) \ + ) +#endif +#else /* !gcc x86 !_msc_ver */ +typedef enum _Py_memory_order { + _Py_memory_order_relaxed, + _Py_memory_order_acquire, + _Py_memory_order_release, + _Py_memory_order_acq_rel, + _Py_memory_order_seq_cst +} _Py_memory_order; + +typedef struct _Py_atomic_address { + uintptr_t _value; +} _Py_atomic_address; + +typedef struct _Py_atomic_int { + int _value; +} _Py_atomic_int; +/* Fall back to other compilers and processors by assuming that simple + volatile accesses are atomic. This is false, so people should port + this. */ +#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) ((void)0) +#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) ((void)0) +#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \ + ((ATOMIC_VAL)->_value = NEW_VAL) +#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \ + ((ATOMIC_VAL)->_value) +#endif + +/* Standardized shortcuts. */ +#define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \ + _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, _Py_memory_order_seq_cst) +#define _Py_atomic_load(ATOMIC_VAL) \ + _Py_atomic_load_explicit(ATOMIC_VAL, _Py_memory_order_seq_cst) + +/* Python-local extensions */ + +#define _Py_atomic_store_relaxed(ATOMIC_VAL, NEW_VAL) \ + _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, _Py_memory_order_relaxed) +#define _Py_atomic_load_relaxed(ATOMIC_VAL) \ + _Py_atomic_load_explicit(ATOMIC_VAL, _Py_memory_order_relaxed) +#endif /* Py_BUILD_CORE */ +#endif /* Py_ATOMIC_H */ diff --git a/winvenv/Include/pycapsule.h b/winvenv/Include/pycapsule.h new file mode 100644 index 0000000..d9ecda7 --- /dev/null +++ b/winvenv/Include/pycapsule.h @@ -0,0 +1,59 @@ + +/* Capsule objects let you wrap a C "void *" pointer in a Python + object. They're a way of passing data through the Python interpreter + without creating your own custom type. + + Capsules are used for communication between extension modules. + They provide a way for an extension module to export a C interface + to other extension modules, so that extension modules can use the + Python import mechanism to link to one another. + + For more information, please see "c-api/capsule.html" in the + documentation. +*/ + +#ifndef Py_CAPSULE_H +#define Py_CAPSULE_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_DATA(PyTypeObject) PyCapsule_Type; + +typedef void (*PyCapsule_Destructor)(PyObject *); + +#define PyCapsule_CheckExact(op) (Py_TYPE(op) == &PyCapsule_Type) + + +PyAPI_FUNC(PyObject *) PyCapsule_New( + void *pointer, + const char *name, + PyCapsule_Destructor destructor); + +PyAPI_FUNC(void *) PyCapsule_GetPointer(PyObject *capsule, const char *name); + +PyAPI_FUNC(PyCapsule_Destructor) PyCapsule_GetDestructor(PyObject *capsule); + +PyAPI_FUNC(const char *) PyCapsule_GetName(PyObject *capsule); + +PyAPI_FUNC(void *) PyCapsule_GetContext(PyObject *capsule); + +PyAPI_FUNC(int) PyCapsule_IsValid(PyObject *capsule, const char *name); + +PyAPI_FUNC(int) PyCapsule_SetPointer(PyObject *capsule, void *pointer); + +PyAPI_FUNC(int) PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor); + +PyAPI_FUNC(int) PyCapsule_SetName(PyObject *capsule, const char *name); + +PyAPI_FUNC(int) PyCapsule_SetContext(PyObject *capsule, void *context); + +PyAPI_FUNC(void *) PyCapsule_Import( + const char *name, /* UTF-8 encoded string */ + int no_block); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_CAPSULE_H */ diff --git a/winvenv/Include/pyconfig.h b/winvenv/Include/pyconfig.h new file mode 100644 index 0000000..d2a3f5d --- /dev/null +++ b/winvenv/Include/pyconfig.h @@ -0,0 +1,693 @@ +#ifndef Py_CONFIG_H +#define Py_CONFIG_H + +/* pyconfig.h. NOT Generated automatically by configure. + +This is a manually maintained version used for the Watcom, +Borland and Microsoft Visual C++ compilers. It is a +standard part of the Python distribution. + +WINDOWS DEFINES: +The code specific to Windows should be wrapped around one of +the following #defines + +MS_WIN64 - Code specific to the MS Win64 API +MS_WIN32 - Code specific to the MS Win32 (and Win64) API (obsolete, this covers all supported APIs) +MS_WINDOWS - Code specific to Windows, but all versions. +Py_ENABLE_SHARED - Code if the Python core is built as a DLL. + +Also note that neither "_M_IX86" or "_MSC_VER" should be used for +any purpose other than "Windows Intel x86 specific" and "Microsoft +compiler specific". Therefore, these should be very rare. + + +NOTE: The following symbols are deprecated: +NT, USE_DL_EXPORT, USE_DL_IMPORT, DL_EXPORT, DL_IMPORT +MS_CORE_DLL. + +WIN32 is still required for the locale module. + +*/ + +/* Deprecated USE_DL_EXPORT macro - please use Py_BUILD_CORE */ +#ifdef USE_DL_EXPORT +# define Py_BUILD_CORE +#endif /* USE_DL_EXPORT */ + +/* Visual Studio 2005 introduces deprecation warnings for + "insecure" and POSIX functions. The insecure functions should + be replaced by *_s versions (according to Microsoft); the + POSIX functions by _* versions (which, according to Microsoft, + would be ISO C conforming). Neither renaming is feasible, so + we just silence the warnings. */ + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +#define HAVE_IO_H +#define HAVE_SYS_UTIME_H +#define HAVE_TEMPNAM +#define HAVE_TMPFILE +#define HAVE_TMPNAM +#define HAVE_CLOCK +#define HAVE_STRERROR + +#include + +#define HAVE_HYPOT +#define HAVE_STRFTIME +#define DONT_HAVE_SIG_ALARM +#define DONT_HAVE_SIG_PAUSE +#define LONG_BIT 32 +#define WORD_BIT 32 + +#define MS_WIN32 /* only support win32 and greater. */ +#define MS_WINDOWS +#ifndef PYTHONPATH +# define PYTHONPATH L".\\DLLs;.\\lib" +#endif +#define NT_THREADS +#define WITH_THREAD +#ifndef NETSCAPE_PI +#define USE_SOCKET +#endif + + +/* Compiler specific defines */ + +/* ------------------------------------------------------------------------*/ +/* Microsoft C defines _MSC_VER */ +#ifdef _MSC_VER + +/* We want COMPILER to expand to a string containing _MSC_VER's *value*. + * This is horridly tricky, because the stringization operator only works + * on macro arguments, and doesn't evaluate macros passed *as* arguments. + * Attempts simpler than the following appear doomed to produce "_MSC_VER" + * literally in the string. + */ +#define _Py_PASTE_VERSION(SUFFIX) \ + ("[MSC v." _Py_STRINGIZE(_MSC_VER) " " SUFFIX "]") +/* e.g., this produces, after compile-time string catenation, + * ("[MSC v.1200 32 bit (Intel)]") + * + * _Py_STRINGIZE(_MSC_VER) expands to + * _Py_STRINGIZE1((_MSC_VER)) expands to + * _Py_STRINGIZE2(_MSC_VER) but as this call is the result of token-pasting + * it's scanned again for macros and so further expands to (under MSVC 6) + * _Py_STRINGIZE2(1200) which then expands to + * "1200" + */ +#define _Py_STRINGIZE(X) _Py_STRINGIZE1((X)) +#define _Py_STRINGIZE1(X) _Py_STRINGIZE2 ## X +#define _Py_STRINGIZE2(X) #X + +/* MSVC defines _WINxx to differentiate the windows platform types + + Note that for compatibility reasons _WIN32 is defined on Win32 + *and* on Win64. For the same reasons, in Python, MS_WIN32 is + defined on Win32 *and* Win64. Win32 only code must therefore be + guarded as follows: + #if defined(MS_WIN32) && !defined(MS_WIN64) +*/ +#ifdef _WIN64 +#define MS_WIN64 +#endif + +/* set the COMPILER */ +#ifdef MS_WIN64 +#if defined(_M_X64) || defined(_M_AMD64) +#if defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 64 bit (amd64) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else +#define COMPILER _Py_PASTE_VERSION("64 bit (AMD64)") +#endif /* __INTEL_COMPILER */ +#define PYD_PLATFORM_TAG "win_amd64" +#else +#define COMPILER _Py_PASTE_VERSION("64 bit (Unknown)") +#endif +#endif /* MS_WIN64 */ + +/* set the version macros for the windows headers */ +/* Python 3.5+ requires Windows Vista or greater */ +#define Py_WINVER 0x0600 /* _WIN32_WINNT_VISTA */ +#define Py_NTDDI NTDDI_VISTA + +/* We only set these values when building Python - we don't want to force + these values on extensions, as that will affect the prototypes and + structures exposed in the Windows headers. Even when building Python, we + allow a single source file to override this - they may need access to + structures etc so it can optionally use new Windows features if it + determines at runtime they are available. +*/ +#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) || defined(Py_BUILD_CORE_MODULE) +#ifndef NTDDI_VERSION +#define NTDDI_VERSION Py_NTDDI +#endif +#ifndef WINVER +#define WINVER Py_WINVER +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT Py_WINVER +#endif +#endif + +/* _W64 is not defined for VC6 or eVC4 */ +#ifndef _W64 +#define _W64 +#endif + +/* Define like size_t, omitting the "unsigned" */ +#ifdef MS_WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif +#define HAVE_SSIZE_T 1 + +#if defined(MS_WIN32) && !defined(MS_WIN64) +#if defined(_M_IX86) +#if defined(__INTEL_COMPILER) +#define COMPILER ("[ICC v." _Py_STRINGIZE(__INTEL_COMPILER) " 32 bit (Intel) with MSC v." _Py_STRINGIZE(_MSC_VER) " CRT]") +#else +#define COMPILER _Py_PASTE_VERSION("32 bit (Intel)") +#endif /* __INTEL_COMPILER */ +#define PYD_PLATFORM_TAG "win32" +#elif defined(_M_ARM) +#define COMPILER _Py_PASTE_VERSION("32 bit (ARM)") +#define PYD_PLATFORM_TAG "win_arm" +#else +#define COMPILER _Py_PASTE_VERSION("32 bit (Unknown)") +#endif +#endif /* MS_WIN32 && !MS_WIN64 */ + +typedef int pid_t; + +#include +#define Py_IS_NAN _isnan +#define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X)) +#define Py_IS_FINITE(X) _finite(X) +#define copysign _copysign + +/* VS 2010 and above already defines hypot as _hypot */ +#if _MSC_VER < 1600 +#define hypot _hypot +#endif + +/* VS 2015 defines these names with a leading underscore */ +#if _MSC_VER >= 1900 +#define timezone _timezone +#define daylight _daylight +#define tzname _tzname +#endif + +/* Side by Side assemblies supported in VS 2005 and VS 2008 but not 2010*/ +#if _MSC_VER >= 1400 && _MSC_VER < 1600 +#define HAVE_SXS 1 +#endif + +/* define some ANSI types that are not defined in earlier Win headers */ +#if _MSC_VER >= 1200 +/* This file only exists in VC 6.0 or higher */ +#include +#endif + +#endif /* _MSC_VER */ + +/* ------------------------------------------------------------------------*/ +/* egcs/gnu-win32 defines __GNUC__ and _WIN32 */ +#if defined(__GNUC__) && defined(_WIN32) +/* XXX These defines are likely incomplete, but should be easy to fix. + They should be complete enough to build extension modules. */ +/* Suggested by Rene Liebscher to avoid a GCC 2.91.* + bug that requires structure imports. More recent versions of the + compiler don't exhibit this bug. +*/ +#if (__GNUC__==2) && (__GNUC_MINOR__<=91) +#warning "Please use an up-to-date version of gcc! (>2.91 recommended)" +#endif + +#define COMPILER "[gcc]" +#define hypot _hypot +#define PY_LONG_LONG long long +#define PY_LLONG_MIN LLONG_MIN +#define PY_LLONG_MAX LLONG_MAX +#define PY_ULLONG_MAX ULLONG_MAX +#endif /* GNUC */ + +/* ------------------------------------------------------------------------*/ +/* lcc-win32 defines __LCC__ */ +#if defined(__LCC__) +/* XXX These defines are likely incomplete, but should be easy to fix. + They should be complete enough to build extension modules. */ + +#define COMPILER "[lcc-win32]" +typedef int pid_t; +/* __declspec() is supported here too - do nothing to get the defaults */ + +#endif /* LCC */ + +/* ------------------------------------------------------------------------*/ +/* End of compilers - finish up */ + +#ifndef NO_STDIO_H +# include +#endif + +/* 64 bit ints are usually spelt __int64 unless compiler has overridden */ +#ifndef PY_LONG_LONG +# define PY_LONG_LONG __int64 +# define PY_LLONG_MAX _I64_MAX +# define PY_LLONG_MIN _I64_MIN +# define PY_ULLONG_MAX _UI64_MAX +#endif + +/* For Windows the Python core is in a DLL by default. Test +Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ +#if !defined(MS_NO_COREDLL) && !defined(Py_NO_ENABLE_SHARED) +# define Py_ENABLE_SHARED 1 /* standard symbol for shared library */ +# define MS_COREDLL /* deprecated old symbol */ +#endif /* !MS_NO_COREDLL && ... */ + +/* All windows compilers that use this header support __declspec */ +#define HAVE_DECLSPEC_DLL + +/* For an MSVC DLL, we can nominate the .lib files used by extensions */ +#ifdef MS_COREDLL +# if !defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_BUILTIN) + /* not building the core - must be an ext */ +# if defined(_MSC_VER) + /* So MSVC users need not specify the .lib + file in their Makefile (other compilers are + generally taken care of by distutils.) */ +# if defined(_DEBUG) +# pragma comment(lib,"python37_d.lib") +# elif defined(Py_LIMITED_API) +# pragma comment(lib,"python3.lib") +# else +# pragma comment(lib,"python37.lib") +# endif /* _DEBUG */ +# endif /* _MSC_VER */ +# endif /* Py_BUILD_CORE */ +#endif /* MS_COREDLL */ + +#if defined(MS_WIN64) +/* maintain "win32" sys.platform for backward compatibility of Python code, + the Win64 API should be close enough to the Win32 API to make this + preferable */ +# define PLATFORM "win32" +# define SIZEOF_VOID_P 8 +# define SIZEOF_TIME_T 8 +# define SIZEOF_OFF_T 4 +# define SIZEOF_FPOS_T 8 +# define SIZEOF_HKEY 8 +# define SIZEOF_SIZE_T 8 +/* configure.ac defines HAVE_LARGEFILE_SUPPORT iff HAVE_LONG_LONG, + sizeof(off_t) > sizeof(long), and sizeof(PY_LONG_LONG) >= sizeof(off_t). + On Win64 the second condition is not true, but if fpos_t replaces off_t + then this is true. The uses of HAVE_LARGEFILE_SUPPORT imply that Win64 + should define this. */ +# define HAVE_LARGEFILE_SUPPORT +#elif defined(MS_WIN32) +# define PLATFORM "win32" +# define HAVE_LARGEFILE_SUPPORT +# define SIZEOF_VOID_P 4 +# define SIZEOF_OFF_T 4 +# define SIZEOF_FPOS_T 8 +# define SIZEOF_HKEY 4 +# define SIZEOF_SIZE_T 4 + /* MS VS2005 changes time_t to a 64-bit type on all platforms */ +# if defined(_MSC_VER) && _MSC_VER >= 1400 +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +#ifdef _DEBUG +# define Py_DEBUG +#endif + + +#ifdef MS_WIN32 + +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_LONG_LONG 8 +#define SIZEOF_DOUBLE 8 +#define SIZEOF_FLOAT 4 + +/* VC 7.1 has them and VC 6.0 does not. VC 6.0 has a version number of 1200. + Microsoft eMbedded Visual C++ 4.0 has a version number of 1201 and doesn't + define these. + If some compiler does not provide them, modify the #if appropriately. */ +#if defined(_MSC_VER) +#if _MSC_VER > 1300 +#define HAVE_UINTPTR_T 1 +#define HAVE_INTPTR_T 1 +#else +/* VC6, VS 2002 and eVC4 don't support the C99 LL suffix for 64-bit integer literals */ +#define Py_LL(x) x##I64 +#endif /* _MSC_VER > 1300 */ +#endif /* _MSC_VER */ + +#endif + +/* define signed and unsigned exact-width 32-bit and 64-bit types, used in the + implementation of Python integers. */ +#define PY_UINT32_T uint32_t +#define PY_UINT64_T uint64_t +#define PY_INT32_T int32_t +#define PY_INT64_T int64_t + +/* Fairly standard from here! */ + +/* Define to 1 if you have the `copysign' function. */ +#define HAVE_COPYSIGN 1 + +/* Define to 1 if you have the `round' function. */ +#if _MSC_VER >= 1800 +#define HAVE_ROUND 1 +#endif + +/* Define to 1 if you have the `isinf' macro. */ +#define HAVE_DECL_ISINF 1 + +/* Define to 1 if you have the `isnan' function. */ +#define HAVE_DECL_ISNAN 1 + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* #undef _ALL_SOURCE */ +#endif + +/* Define to empty if the keyword does not work. */ +/* #define const */ + +/* Define to 1 if you have the header file. */ +#define HAVE_CONIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DIRECT_H 1 + +/* Define if you have dirent.h. */ +/* #define DIRENT 1 */ + +/* Define to the type of elements in the array set by `getgroups'. + Usually this is either `int' or `gid_t'. */ +/* #undef GETGROUPS_T */ + +/* Define to `int' if doesn't define. */ +/* #undef gid_t */ + +/* Define if your struct tm has tm_zone. */ +/* #undef HAVE_TM_ZONE */ + +/* Define if you don't have tm_zone but do have the external array + tzname. */ +#define HAVE_TZNAME + +/* Define to `int' if doesn't define. */ +/* #undef mode_t */ + +/* Define if you don't have dirent.h, but have ndir.h. */ +/* #undef NDIR */ + +/* Define to `long' if doesn't define. */ +/* #undef off_t */ + +/* Define to `int' if doesn't define. */ +/* #undef pid_t */ + +/* Define if the system does not provide POSIX.1 features except + with this defined. */ +/* #undef _POSIX_1_SOURCE */ + +/* Define if you need to in order for stat and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you don't have dirent.h, but have sys/dir.h. */ +/* #undef SYSDIR */ + +/* Define if you don't have dirent.h, but have sys/ndir.h. */ +/* #undef SYSNDIR */ + +/* Define if you can safely include both and . */ +/* #undef TIME_WITH_SYS_TIME */ + +/* Define if your declares struct tm. */ +/* #define TM_IN_SYS_TIME 1 */ + +/* Define to `int' if doesn't define. */ +/* #undef uid_t */ + +/* Define if the closedir function returns void instead of int. */ +/* #undef VOID_CLOSEDIR */ + +/* Define if getpgrp() must be called as getpgrp(0) + and (consequently) setpgrp() as setpgrp(0, 0). */ +/* #undef GETPGRP_HAVE_ARGS */ + +/* Define this if your time.h defines altzone */ +/* #define HAVE_ALTZONE */ + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV + +/* Define if your compiler supports function prototypes */ +#define HAVE_PROTOTYPES + +/* Define if you can safely include both and + (which you can't on SCO ODT 3.0). */ +/* #undef SYS_SELECT_WITH_SYS_TIME */ + +/* Define if you want documentation strings in extension modules */ +#define WITH_DOC_STRINGS 1 + +/* Define if you want to compile in rudimentary thread support */ +/* #undef WITH_THREAD */ + +/* Define if you want to use the GNU readline library */ +/* #define WITH_READLINE 1 */ + +/* Use Python's own small-block memory-allocator. */ +#define WITH_PYMALLOC 1 + +/* Define if you have clock. */ +/* #define HAVE_CLOCK */ + +/* Define when any dynamic module loading is enabled */ +#define HAVE_DYNAMIC_LOADING + +/* Define if you have ftime. */ +#define HAVE_FTIME + +/* Define if you have getpeername. */ +#define HAVE_GETPEERNAME + +/* Define if you have getpgrp. */ +/* #undef HAVE_GETPGRP */ + +/* Define if you have getpid. */ +#define HAVE_GETPID + +/* Define if you have gettimeofday. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define if you have getwd. */ +/* #undef HAVE_GETWD */ + +/* Define if you have lstat. */ +/* #undef HAVE_LSTAT */ + +/* Define if you have the mktime function. */ +#define HAVE_MKTIME + +/* Define if you have nice. */ +/* #undef HAVE_NICE */ + +/* Define if you have readlink. */ +/* #undef HAVE_READLINK */ + +/* Define if you have setpgid. */ +/* #undef HAVE_SETPGID */ + +/* Define if you have setpgrp. */ +/* #undef HAVE_SETPGRP */ + +/* Define if you have setsid. */ +/* #undef HAVE_SETSID */ + +/* Define if you have setvbuf. */ +#define HAVE_SETVBUF + +/* Define if you have siginterrupt. */ +/* #undef HAVE_SIGINTERRUPT */ + +/* Define if you have symlink. */ +/* #undef HAVE_SYMLINK */ + +/* Define if you have tcgetpgrp. */ +/* #undef HAVE_TCGETPGRP */ + +/* Define if you have tcsetpgrp. */ +/* #undef HAVE_TCSETPGRP */ + +/* Define if you have times. */ +/* #undef HAVE_TIMES */ + +/* Define if you have uname. */ +/* #undef HAVE_UNAME */ + +/* Define if you have waitpid. */ +/* #undef HAVE_WAITPID */ + +/* Define to 1 if you have the `wcsftime' function. */ +#if defined(_MSC_VER) && _MSC_VER >= 1310 +#define HAVE_WCSFTIME 1 +#endif + +/* Define to 1 if you have the `wcscoll' function. */ +#define HAVE_WCSCOLL 1 + +/* Define to 1 if you have the `wcsxfrm' function. */ +#define HAVE_WCSXFRM 1 + +/* Define if the zlib library has inflateCopy */ +#define HAVE_ZLIB_COPY 1 + +/* Define if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PROCESS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the prototypes. */ +#define HAVE_STDARG_PROTOTYPES + +/* Define if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define if you have the header file. */ +/* #undef HAVE_SYS_AUDIOIO_H */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIMES_H 1 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_UN_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_UTIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_UTSNAME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_UNISTD_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_UTIME_H 1 */ + +/* Define if the compiler provides a wchar.h header file. */ +#define HAVE_WCHAR_H 1 + +/* The size of `wchar_t', as computed by sizeof. */ +#define SIZEOF_WCHAR_T 2 + +/* The size of `_Bool', as computed by sizeof. */ +#define SIZEOF__BOOL 1 + +/* The size of `pid_t', as computed by sizeof. */ +#define SIZEOF_PID_T SIZEOF_INT + +/* Define if you have the dl library (-ldl). */ +/* #undef HAVE_LIBDL */ + +/* Define if you have the mpc library (-lmpc). */ +/* #undef HAVE_LIBMPC */ + +/* Define if you have the nsl library (-lnsl). */ +#define HAVE_LIBNSL 1 + +/* Define if you have the seq library (-lseq). */ +/* #undef HAVE_LIBSEQ */ + +/* Define if you have the socket library (-lsocket). */ +#define HAVE_LIBSOCKET 1 + +/* Define if you have the sun library (-lsun). */ +/* #undef HAVE_LIBSUN */ + +/* Define if you have the termcap library (-ltermcap). */ +/* #undef HAVE_LIBTERMCAP */ + +/* Define if you have the termlib library (-ltermlib). */ +/* #undef HAVE_LIBTERMLIB */ + +/* Define if you have the thread library (-lthread). */ +/* #undef HAVE_LIBTHREAD */ + +/* WinSock does not use a bitmask in select, and uses + socket handles greater than FD_SETSIZE */ +#define Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE + +/* Define if C doubles are 64-bit IEEE 754 binary format, stored with the + least significant byte first */ +#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 1 + +/* Define to 1 if you have the `erf' function. */ +#define HAVE_ERF 1 + +/* Define to 1 if you have the `erfc' function. */ +#define HAVE_ERFC 1 + +/* Define if you have the 'inet_pton' function. */ +#define HAVE_INET_PTON 1 + +/* framework name */ +#define _PYTHONFRAMEWORK "" + +/* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */ +#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 + +#endif /* !Py_CONFIG_H */ diff --git a/winvenv/Include/pyctype.h b/winvenv/Include/pyctype.h new file mode 100644 index 0000000..6bce63e --- /dev/null +++ b/winvenv/Include/pyctype.h @@ -0,0 +1,33 @@ +#ifndef Py_LIMITED_API +#ifndef PYCTYPE_H +#define PYCTYPE_H + +#define PY_CTF_LOWER 0x01 +#define PY_CTF_UPPER 0x02 +#define PY_CTF_ALPHA (PY_CTF_LOWER|PY_CTF_UPPER) +#define PY_CTF_DIGIT 0x04 +#define PY_CTF_ALNUM (PY_CTF_ALPHA|PY_CTF_DIGIT) +#define PY_CTF_SPACE 0x08 +#define PY_CTF_XDIGIT 0x10 + +PyAPI_DATA(const unsigned int) _Py_ctype_table[256]; + +/* Unlike their C counterparts, the following macros are not meant to + * handle an int with any of the values [EOF, 0-UCHAR_MAX]. The argument + * must be a signed/unsigned char. */ +#define Py_ISLOWER(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_LOWER) +#define Py_ISUPPER(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_UPPER) +#define Py_ISALPHA(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_ALPHA) +#define Py_ISDIGIT(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_DIGIT) +#define Py_ISXDIGIT(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_XDIGIT) +#define Py_ISALNUM(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_ALNUM) +#define Py_ISSPACE(c) (_Py_ctype_table[Py_CHARMASK(c)] & PY_CTF_SPACE) + +PyAPI_DATA(const unsigned char) _Py_ctype_tolower[256]; +PyAPI_DATA(const unsigned char) _Py_ctype_toupper[256]; + +#define Py_TOLOWER(c) (_Py_ctype_tolower[Py_CHARMASK(c)]) +#define Py_TOUPPER(c) (_Py_ctype_toupper[Py_CHARMASK(c)]) + +#endif /* !PYCTYPE_H */ +#endif /* !Py_LIMITED_API */ diff --git a/winvenv/Include/pydebug.h b/winvenv/Include/pydebug.h new file mode 100644 index 0000000..bd4aafe --- /dev/null +++ b/winvenv/Include/pydebug.h @@ -0,0 +1,40 @@ +#ifndef Py_LIMITED_API +#ifndef Py_PYDEBUG_H +#define Py_PYDEBUG_H +#ifdef __cplusplus +extern "C" { +#endif + +/* These global variable are defined in pylifecycle.c */ +/* XXX (ncoghlan): move these declarations to pylifecycle.h? */ +PyAPI_DATA(int) Py_DebugFlag; +PyAPI_DATA(int) Py_VerboseFlag; +PyAPI_DATA(int) Py_QuietFlag; +PyAPI_DATA(int) Py_InteractiveFlag; +PyAPI_DATA(int) Py_InspectFlag; +PyAPI_DATA(int) Py_OptimizeFlag; +PyAPI_DATA(int) Py_NoSiteFlag; +PyAPI_DATA(int) Py_BytesWarningFlag; +PyAPI_DATA(int) Py_FrozenFlag; +PyAPI_DATA(int) Py_IgnoreEnvironmentFlag; +PyAPI_DATA(int) Py_DontWriteBytecodeFlag; +PyAPI_DATA(int) Py_NoUserSiteDirectory; +PyAPI_DATA(int) Py_UnbufferedStdioFlag; +PyAPI_DATA(int) Py_HashRandomizationFlag; +PyAPI_DATA(int) Py_IsolatedFlag; + +#ifdef MS_WINDOWS +PyAPI_DATA(int) Py_LegacyWindowsFSEncodingFlag; +PyAPI_DATA(int) Py_LegacyWindowsStdioFlag; +#endif + +/* this is a wrapper around getenv() that pays attention to + Py_IgnoreEnvironmentFlag. It should be used for getting variables like + PYTHONPATH and PYTHONHOME from the environment */ +#define Py_GETENV(s) (Py_IgnoreEnvironmentFlag ? NULL : getenv(s)) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PYDEBUG_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/pydtrace.h b/winvenv/Include/pydtrace.h new file mode 100644 index 0000000..037961d --- /dev/null +++ b/winvenv/Include/pydtrace.h @@ -0,0 +1,57 @@ +/* Static DTrace probes interface */ + +#ifndef Py_DTRACE_H +#define Py_DTRACE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WITH_DTRACE + +#include "pydtrace_probes.h" + +/* pydtrace_probes.h, on systems with DTrace, is auto-generated to include + `PyDTrace_{PROBE}` and `PyDTrace_{PROBE}_ENABLED()` macros for every probe + defined in pydtrace_provider.d. + + Calling these functions must be guarded by a `PyDTrace_{PROBE}_ENABLED()` + check to minimize performance impact when probing is off. For example: + + if (PyDTrace_FUNCTION_ENTRY_ENABLED()) + PyDTrace_FUNCTION_ENTRY(f); +*/ + +#else + +/* Without DTrace, compile to nothing. */ + +static inline void PyDTrace_LINE(const char *arg0, const char *arg1, int arg2) {} +static inline void PyDTrace_FUNCTION_ENTRY(const char *arg0, const char *arg1, int arg2) {} +static inline void PyDTrace_FUNCTION_RETURN(const char *arg0, const char *arg1, int arg2) {} +static inline void PyDTrace_GC_START(int arg0) {} +static inline void PyDTrace_GC_DONE(int arg0) {} +static inline void PyDTrace_INSTANCE_NEW_START(int arg0) {} +static inline void PyDTrace_INSTANCE_NEW_DONE(int arg0) {} +static inline void PyDTrace_INSTANCE_DELETE_START(int arg0) {} +static inline void PyDTrace_INSTANCE_DELETE_DONE(int arg0) {} +static inline void PyDTrace_IMPORT_FIND_LOAD_START(const char *arg0) {} +static inline void PyDTrace_IMPORT_FIND_LOAD_DONE(const char *arg0, int arg1) {} + +static inline int PyDTrace_LINE_ENABLED(void) { return 0; } +static inline int PyDTrace_FUNCTION_ENTRY_ENABLED(void) { return 0; } +static inline int PyDTrace_FUNCTION_RETURN_ENABLED(void) { return 0; } +static inline int PyDTrace_GC_START_ENABLED(void) { return 0; } +static inline int PyDTrace_GC_DONE_ENABLED(void) { return 0; } +static inline int PyDTrace_INSTANCE_NEW_START_ENABLED(void) { return 0; } +static inline int PyDTrace_INSTANCE_NEW_DONE_ENABLED(void) { return 0; } +static inline int PyDTrace_INSTANCE_DELETE_START_ENABLED(void) { return 0; } +static inline int PyDTrace_INSTANCE_DELETE_DONE_ENABLED(void) { return 0; } +static inline int PyDTrace_IMPORT_FIND_LOAD_START_ENABLED(void) { return 0; } +static inline int PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED(void) { return 0; } + +#endif /* !WITH_DTRACE */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_DTRACE_H */ diff --git a/winvenv/Include/pyerrors.h b/winvenv/Include/pyerrors.h new file mode 100644 index 0000000..f289471 --- /dev/null +++ b/winvenv/Include/pyerrors.h @@ -0,0 +1,504 @@ +#ifndef Py_ERRORS_H +#define Py_ERRORS_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Error objects */ + +#ifndef Py_LIMITED_API +/* PyException_HEAD defines the initial segment of every exception class. */ +#define PyException_HEAD PyObject_HEAD PyObject *dict;\ + PyObject *args; PyObject *traceback;\ + PyObject *context; PyObject *cause;\ + char suppress_context; + +typedef struct { + PyException_HEAD +} PyBaseExceptionObject; + +typedef struct { + PyException_HEAD + PyObject *msg; + PyObject *filename; + PyObject *lineno; + PyObject *offset; + PyObject *text; + PyObject *print_file_and_line; +} PySyntaxErrorObject; + +typedef struct { + PyException_HEAD + PyObject *msg; + PyObject *name; + PyObject *path; +} PyImportErrorObject; + +typedef struct { + PyException_HEAD + PyObject *encoding; + PyObject *object; + Py_ssize_t start; + Py_ssize_t end; + PyObject *reason; +} PyUnicodeErrorObject; + +typedef struct { + PyException_HEAD + PyObject *code; +} PySystemExitObject; + +typedef struct { + PyException_HEAD + PyObject *myerrno; + PyObject *strerror; + PyObject *filename; + PyObject *filename2; +#ifdef MS_WINDOWS + PyObject *winerror; +#endif + Py_ssize_t written; /* only for BlockingIOError, -1 otherwise */ +} PyOSErrorObject; + +typedef struct { + PyException_HEAD + PyObject *value; +} PyStopIterationObject; + +/* Compatibility typedefs */ +typedef PyOSErrorObject PyEnvironmentErrorObject; +#ifdef MS_WINDOWS +typedef PyOSErrorObject PyWindowsErrorObject; +#endif +#endif /* !Py_LIMITED_API */ + +/* Error handling definitions */ + +PyAPI_FUNC(void) PyErr_SetNone(PyObject *); +PyAPI_FUNC(void) PyErr_SetObject(PyObject *, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); +_PyErr_StackItem *_PyErr_GetTopmostException(PyThreadState *tstate); +#endif +PyAPI_FUNC(void) PyErr_SetString( + PyObject *exception, + const char *string /* decoded from utf-8 */ + ); +PyAPI_FUNC(PyObject *) PyErr_Occurred(void); +PyAPI_FUNC(void) PyErr_Clear(void); +PyAPI_FUNC(void) PyErr_Fetch(PyObject **, PyObject **, PyObject **); +PyAPI_FUNC(void) PyErr_Restore(PyObject *, PyObject *, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **); +PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); +#endif + +#if defined(__clang__) || \ + (defined(__GNUC_MAJOR__) && \ + ((__GNUC_MAJOR__ >= 3) || \ + (__GNUC_MAJOR__ == 2) && (__GNUC_MINOR__ >= 5))) +#define _Py_NO_RETURN __attribute__((__noreturn__)) +#else +#define _Py_NO_RETURN +#endif + +/* Defined in Python/pylifecycle.c */ +PyAPI_FUNC(void) Py_FatalError(const char *message) _Py_NO_RETURN; + +#if defined(Py_DEBUG) || defined(Py_LIMITED_API) +#define _PyErr_OCCURRED() PyErr_Occurred() +#else +#define _PyErr_OCCURRED() (PyThreadState_GET()->curexc_type) +#endif + +/* Error testing and normalization */ +PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *); +PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *); +PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**); + +/* Traceback manipulation (PEP 3134) */ +PyAPI_FUNC(int) PyException_SetTraceback(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyException_GetTraceback(PyObject *); + +/* Cause manipulation (PEP 3134) */ +PyAPI_FUNC(PyObject *) PyException_GetCause(PyObject *); +PyAPI_FUNC(void) PyException_SetCause(PyObject *, PyObject *); + +/* Context manipulation (PEP 3134) */ +PyAPI_FUNC(PyObject *) PyException_GetContext(PyObject *); +PyAPI_FUNC(void) PyException_SetContext(PyObject *, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *); +#endif + +/* */ + +#define PyExceptionClass_Check(x) \ + (PyType_Check((x)) && \ + PyType_FastSubclass((PyTypeObject*)(x), Py_TPFLAGS_BASE_EXC_SUBCLASS)) + +#define PyExceptionInstance_Check(x) \ + PyType_FastSubclass((x)->ob_type, Py_TPFLAGS_BASE_EXC_SUBCLASS) + +#define PyExceptionClass_Name(x) \ + ((char *)(((PyTypeObject*)(x))->tp_name)) + +#define PyExceptionInstance_Class(x) ((PyObject*)((x)->ob_type)) + + +/* Predefined exceptions */ + +PyAPI_DATA(PyObject *) PyExc_BaseException; +PyAPI_DATA(PyObject *) PyExc_Exception; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_DATA(PyObject *) PyExc_StopAsyncIteration; +#endif +PyAPI_DATA(PyObject *) PyExc_StopIteration; +PyAPI_DATA(PyObject *) PyExc_GeneratorExit; +PyAPI_DATA(PyObject *) PyExc_ArithmeticError; +PyAPI_DATA(PyObject *) PyExc_LookupError; + +PyAPI_DATA(PyObject *) PyExc_AssertionError; +PyAPI_DATA(PyObject *) PyExc_AttributeError; +PyAPI_DATA(PyObject *) PyExc_BufferError; +PyAPI_DATA(PyObject *) PyExc_EOFError; +PyAPI_DATA(PyObject *) PyExc_FloatingPointError; +PyAPI_DATA(PyObject *) PyExc_OSError; +PyAPI_DATA(PyObject *) PyExc_ImportError; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 +PyAPI_DATA(PyObject *) PyExc_ModuleNotFoundError; +#endif +PyAPI_DATA(PyObject *) PyExc_IndexError; +PyAPI_DATA(PyObject *) PyExc_KeyError; +PyAPI_DATA(PyObject *) PyExc_KeyboardInterrupt; +PyAPI_DATA(PyObject *) PyExc_MemoryError; +PyAPI_DATA(PyObject *) PyExc_NameError; +PyAPI_DATA(PyObject *) PyExc_OverflowError; +PyAPI_DATA(PyObject *) PyExc_RuntimeError; +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_DATA(PyObject *) PyExc_RecursionError; +#endif +PyAPI_DATA(PyObject *) PyExc_NotImplementedError; +PyAPI_DATA(PyObject *) PyExc_SyntaxError; +PyAPI_DATA(PyObject *) PyExc_IndentationError; +PyAPI_DATA(PyObject *) PyExc_TabError; +PyAPI_DATA(PyObject *) PyExc_ReferenceError; +PyAPI_DATA(PyObject *) PyExc_SystemError; +PyAPI_DATA(PyObject *) PyExc_SystemExit; +PyAPI_DATA(PyObject *) PyExc_TypeError; +PyAPI_DATA(PyObject *) PyExc_UnboundLocalError; +PyAPI_DATA(PyObject *) PyExc_UnicodeError; +PyAPI_DATA(PyObject *) PyExc_UnicodeEncodeError; +PyAPI_DATA(PyObject *) PyExc_UnicodeDecodeError; +PyAPI_DATA(PyObject *) PyExc_UnicodeTranslateError; +PyAPI_DATA(PyObject *) PyExc_ValueError; +PyAPI_DATA(PyObject *) PyExc_ZeroDivisionError; + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_DATA(PyObject *) PyExc_BlockingIOError; +PyAPI_DATA(PyObject *) PyExc_BrokenPipeError; +PyAPI_DATA(PyObject *) PyExc_ChildProcessError; +PyAPI_DATA(PyObject *) PyExc_ConnectionError; +PyAPI_DATA(PyObject *) PyExc_ConnectionAbortedError; +PyAPI_DATA(PyObject *) PyExc_ConnectionRefusedError; +PyAPI_DATA(PyObject *) PyExc_ConnectionResetError; +PyAPI_DATA(PyObject *) PyExc_FileExistsError; +PyAPI_DATA(PyObject *) PyExc_FileNotFoundError; +PyAPI_DATA(PyObject *) PyExc_InterruptedError; +PyAPI_DATA(PyObject *) PyExc_IsADirectoryError; +PyAPI_DATA(PyObject *) PyExc_NotADirectoryError; +PyAPI_DATA(PyObject *) PyExc_PermissionError; +PyAPI_DATA(PyObject *) PyExc_ProcessLookupError; +PyAPI_DATA(PyObject *) PyExc_TimeoutError; +#endif + + +/* Compatibility aliases */ +PyAPI_DATA(PyObject *) PyExc_EnvironmentError; +PyAPI_DATA(PyObject *) PyExc_IOError; +#ifdef MS_WINDOWS +PyAPI_DATA(PyObject *) PyExc_WindowsError; +#endif + +/* Predefined warning categories */ +PyAPI_DATA(PyObject *) PyExc_Warning; +PyAPI_DATA(PyObject *) PyExc_UserWarning; +PyAPI_DATA(PyObject *) PyExc_DeprecationWarning; +PyAPI_DATA(PyObject *) PyExc_PendingDeprecationWarning; +PyAPI_DATA(PyObject *) PyExc_SyntaxWarning; +PyAPI_DATA(PyObject *) PyExc_RuntimeWarning; +PyAPI_DATA(PyObject *) PyExc_FutureWarning; +PyAPI_DATA(PyObject *) PyExc_ImportWarning; +PyAPI_DATA(PyObject *) PyExc_UnicodeWarning; +PyAPI_DATA(PyObject *) PyExc_BytesWarning; +PyAPI_DATA(PyObject *) PyExc_ResourceWarning; + + +/* Convenience functions */ + +PyAPI_FUNC(int) PyErr_BadArgument(void); +PyAPI_FUNC(PyObject *) PyErr_NoMemory(void); +PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObject( + PyObject *, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObjects( + PyObject *, PyObject *, PyObject *); +#endif +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename( + PyObject *exc, + const char *filename /* decoded from the filesystem encoding */ + ); +#if defined(MS_WINDOWS) && !defined(Py_LIMITED_API) +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename( + PyObject *, const Py_UNICODE *) Py_DEPRECATED(3.3); +#endif /* MS_WINDOWS */ + +PyAPI_FUNC(PyObject *) PyErr_Format( + PyObject *exception, + const char *format, /* ASCII-encoded string */ + ... + ); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_FUNC(PyObject *) PyErr_FormatV( + PyObject *exception, + const char *format, + va_list vargs); +#endif + +#ifndef Py_LIMITED_API +/* Like PyErr_Format(), but saves current exception as __context__ and + __cause__. + */ +PyAPI_FUNC(PyObject *) _PyErr_FormatFromCause( + PyObject *exception, + const char *format, /* ASCII-encoded string */ + ... + ); +#endif + +#ifdef MS_WINDOWS +PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename( + int ierr, + const char *filename /* decoded from the filesystem encoding */ + ); +#ifndef Py_LIMITED_API +/* XXX redeclare to use WSTRING */ +PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename( + int, const Py_UNICODE *) Py_DEPRECATED(3.3); +#endif +PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject( + PyObject *,int, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyObject *,int, PyObject *, PyObject *); +#endif +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( + PyObject *exc, + int ierr, + const char *filename /* decoded from the filesystem encoding */ + ); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename( + PyObject *,int, const Py_UNICODE *) Py_DEPRECATED(3.3); +#endif +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); +#endif /* MS_WINDOWS */ + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 +PyAPI_FUNC(PyObject *) PyErr_SetImportErrorSubclass(PyObject *, PyObject *, + PyObject *, PyObject *); +#endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject *) PyErr_SetImportError(PyObject *, PyObject *, + PyObject *); +#endif + +/* Export the old function so that the existing API remains available: */ +PyAPI_FUNC(void) PyErr_BadInternalCall(void); +PyAPI_FUNC(void) _PyErr_BadInternalCall(const char *filename, int lineno); +/* Mask the old API with a call to the new API for code compiled under + Python 2.0: */ +#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__) + +/* Function to create a new exception */ +PyAPI_FUNC(PyObject *) PyErr_NewException( + const char *name, PyObject *base, PyObject *dict); +PyAPI_FUNC(PyObject *) PyErr_NewExceptionWithDoc( + const char *name, const char *doc, PyObject *base, PyObject *dict); +PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *); + +/* In exceptions.c */ +#ifndef Py_LIMITED_API +/* Helper that attempts to replace the current exception with one of the + * same type but with a prefix added to the exception text. The resulting + * exception description looks like: + * + * prefix (exc_type: original_exc_str) + * + * Only some exceptions can be safely replaced. If the function determines + * it isn't safe to perform the replacement, it will leave the original + * unmodified exception in place. + * + * Returns a borrowed reference to the new exception (if any), NULL if the + * existing exception was left in place. + */ +PyAPI_FUNC(PyObject *) _PyErr_TrySetFromCause( + const char *prefix_format, /* ASCII-encoded string */ + ... + ); +#endif + + +/* In signalmodule.c */ +PyAPI_FUNC(int) PyErr_CheckSignals(void); +PyAPI_FUNC(void) PyErr_SetInterrupt(void); + +/* In signalmodule.c */ +#ifndef Py_LIMITED_API +int PySignal_SetWakeupFd(int fd); +#endif + +/* Support for adding program text to SyntaxErrors */ +PyAPI_FUNC(void) PyErr_SyntaxLocation( + const char *filename, /* decoded from the filesystem encoding */ + int lineno); +PyAPI_FUNC(void) PyErr_SyntaxLocationEx( + const char *filename, /* decoded from the filesystem encoding */ + int lineno, + int col_offset); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) PyErr_SyntaxLocationObject( + PyObject *filename, + int lineno, + int col_offset); +#endif +PyAPI_FUNC(PyObject *) PyErr_ProgramText( + const char *filename, /* decoded from the filesystem encoding */ + int lineno); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject( + PyObject *filename, + int lineno); +#endif + +/* The following functions are used to create and modify unicode + exceptions from C */ + +/* create a UnicodeDecodeError object */ +PyAPI_FUNC(PyObject *) PyUnicodeDecodeError_Create( + const char *encoding, /* UTF-8 encoded string */ + const char *object, + Py_ssize_t length, + Py_ssize_t start, + Py_ssize_t end, + const char *reason /* UTF-8 encoded string */ + ); + +/* create a UnicodeEncodeError object */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyUnicodeEncodeError_Create( + const char *encoding, /* UTF-8 encoded string */ + const Py_UNICODE *object, + Py_ssize_t length, + Py_ssize_t start, + Py_ssize_t end, + const char *reason /* UTF-8 encoded string */ + ) Py_DEPRECATED(3.3); +#endif + +/* create a UnicodeTranslateError object */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyUnicodeTranslateError_Create( + const Py_UNICODE *object, + Py_ssize_t length, + Py_ssize_t start, + Py_ssize_t end, + const char *reason /* UTF-8 encoded string */ + ) Py_DEPRECATED(3.3); +PyAPI_FUNC(PyObject *) _PyUnicodeTranslateError_Create( + PyObject *object, + Py_ssize_t start, + Py_ssize_t end, + const char *reason /* UTF-8 encoded string */ + ); +#endif + +/* get the encoding attribute */ +PyAPI_FUNC(PyObject *) PyUnicodeEncodeError_GetEncoding(PyObject *); +PyAPI_FUNC(PyObject *) PyUnicodeDecodeError_GetEncoding(PyObject *); + +/* get the object attribute */ +PyAPI_FUNC(PyObject *) PyUnicodeEncodeError_GetObject(PyObject *); +PyAPI_FUNC(PyObject *) PyUnicodeDecodeError_GetObject(PyObject *); +PyAPI_FUNC(PyObject *) PyUnicodeTranslateError_GetObject(PyObject *); + +/* get the value of the start attribute (the int * may not be NULL) + return 0 on success, -1 on failure */ +PyAPI_FUNC(int) PyUnicodeEncodeError_GetStart(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) PyUnicodeDecodeError_GetStart(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) PyUnicodeTranslateError_GetStart(PyObject *, Py_ssize_t *); + +/* assign a new value to the start attribute + return 0 on success, -1 on failure */ +PyAPI_FUNC(int) PyUnicodeEncodeError_SetStart(PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyUnicodeDecodeError_SetStart(PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyUnicodeTranslateError_SetStart(PyObject *, Py_ssize_t); + +/* get the value of the end attribute (the int *may not be NULL) + return 0 on success, -1 on failure */ +PyAPI_FUNC(int) PyUnicodeEncodeError_GetEnd(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) PyUnicodeDecodeError_GetEnd(PyObject *, Py_ssize_t *); +PyAPI_FUNC(int) PyUnicodeTranslateError_GetEnd(PyObject *, Py_ssize_t *); + +/* assign a new value to the end attribute + return 0 on success, -1 on failure */ +PyAPI_FUNC(int) PyUnicodeEncodeError_SetEnd(PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyUnicodeDecodeError_SetEnd(PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyUnicodeTranslateError_SetEnd(PyObject *, Py_ssize_t); + +/* get the value of the reason attribute */ +PyAPI_FUNC(PyObject *) PyUnicodeEncodeError_GetReason(PyObject *); +PyAPI_FUNC(PyObject *) PyUnicodeDecodeError_GetReason(PyObject *); +PyAPI_FUNC(PyObject *) PyUnicodeTranslateError_GetReason(PyObject *); + +/* assign a new value to the reason attribute + return 0 on success, -1 on failure */ +PyAPI_FUNC(int) PyUnicodeEncodeError_SetReason( + PyObject *exc, + const char *reason /* UTF-8 encoded string */ + ); +PyAPI_FUNC(int) PyUnicodeDecodeError_SetReason( + PyObject *exc, + const char *reason /* UTF-8 encoded string */ + ); +PyAPI_FUNC(int) PyUnicodeTranslateError_SetReason( + PyObject *exc, + const char *reason /* UTF-8 encoded string */ + ); + +/* These APIs aren't really part of the error implementation, but + often needed to format error messages; the native C lib APIs are + not available on all platforms, which is why we provide emulations + for those platforms in Python/mysnprintf.c, + WARNING: The return value of snprintf varies across platforms; do + not rely on any particular behavior; eventually the C99 defn may + be reliable. +*/ +#if defined(MS_WIN32) && !defined(HAVE_SNPRINTF) +# define HAVE_SNPRINTF +# define snprintf _snprintf +# define vsnprintf _vsnprintf +#endif + +#include +PyAPI_FUNC(int) PyOS_snprintf(char *str, size_t size, const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 3, 4))); +PyAPI_FUNC(int) PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) + Py_GCC_ATTRIBUTE((format(printf, 3, 0))); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_ERRORS_H */ diff --git a/winvenv/Include/pyexpat.h b/winvenv/Include/pyexpat.h new file mode 100644 index 0000000..07020b5 --- /dev/null +++ b/winvenv/Include/pyexpat.h @@ -0,0 +1,55 @@ +/* Stuff to export relevant 'expat' entry points from pyexpat to other + * parser modules, such as cElementTree. */ + +/* note: you must import expat.h before importing this module! */ + +#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.1" +#define PyExpat_CAPSULE_NAME "pyexpat.expat_CAPI" + +struct PyExpat_CAPI +{ + char* magic; /* set to PyExpat_CAPI_MAGIC */ + int size; /* set to sizeof(struct PyExpat_CAPI) */ + int MAJOR_VERSION; + int MINOR_VERSION; + int MICRO_VERSION; + /* pointers to selected expat functions. add new functions at + the end, if needed */ + const XML_LChar * (*ErrorString)(enum XML_Error code); + enum XML_Error (*GetErrorCode)(XML_Parser parser); + XML_Size (*GetErrorColumnNumber)(XML_Parser parser); + XML_Size (*GetErrorLineNumber)(XML_Parser parser); + enum XML_Status (*Parse)( + XML_Parser parser, const char *s, int len, int isFinal); + XML_Parser (*ParserCreate_MM)( + const XML_Char *encoding, const XML_Memory_Handling_Suite *memsuite, + const XML_Char *namespaceSeparator); + void (*ParserFree)(XML_Parser parser); + void (*SetCharacterDataHandler)( + XML_Parser parser, XML_CharacterDataHandler handler); + void (*SetCommentHandler)( + XML_Parser parser, XML_CommentHandler handler); + void (*SetDefaultHandlerExpand)( + XML_Parser parser, XML_DefaultHandler handler); + void (*SetElementHandler)( + XML_Parser parser, XML_StartElementHandler start, + XML_EndElementHandler end); + void (*SetNamespaceDeclHandler)( + XML_Parser parser, XML_StartNamespaceDeclHandler start, + XML_EndNamespaceDeclHandler end); + void (*SetProcessingInstructionHandler)( + XML_Parser parser, XML_ProcessingInstructionHandler handler); + void (*SetUnknownEncodingHandler)( + XML_Parser parser, XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + void (*SetUserData)(XML_Parser parser, void *userData); + void (*SetStartDoctypeDeclHandler)(XML_Parser parser, + XML_StartDoctypeDeclHandler start); + enum XML_Status (*SetEncoding)(XML_Parser parser, const XML_Char *encoding); + int (*DefaultUnknownEncodingHandler)( + void *encodingHandlerData, const XML_Char *name, XML_Encoding *info); + /* might be none for expat < 2.1.0 */ + int (*SetHashSalt)(XML_Parser parser, unsigned long hash_salt); + /* always add new stuff to the end! */ +}; + diff --git a/winvenv/Include/pyfpe.h b/winvenv/Include/pyfpe.h new file mode 100644 index 0000000..5a99e39 --- /dev/null +++ b/winvenv/Include/pyfpe.h @@ -0,0 +1,12 @@ +#ifndef Py_PYFPE_H +#define Py_PYFPE_H + +/* These macros used to do something when Python was built with --with-fpectl, + * but support for that was dropped in 3.7. We continue to define them though, + * to avoid breaking API users. + */ + +#define PyFPE_START_PROTECT(err_string, leave_stmt) +#define PyFPE_END_PROTECT(v) + +#endif /* !Py_PYFPE_H */ diff --git a/winvenv/Include/pyhash.h b/winvenv/Include/pyhash.h new file mode 100644 index 0000000..9cfd071 --- /dev/null +++ b/winvenv/Include/pyhash.h @@ -0,0 +1,145 @@ +#ifndef Py_HASH_H + +#define Py_HASH_H +#ifdef __cplusplus +extern "C" { +#endif + +/* Helpers for hash functions */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_hash_t) _Py_HashDouble(double); +PyAPI_FUNC(Py_hash_t) _Py_HashPointer(void*); +PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void*, Py_ssize_t); +#endif + +/* Prime multiplier used in string and various other hashes. */ +#define _PyHASH_MULTIPLIER 1000003UL /* 0xf4243 */ + +/* Parameters used for the numeric hash implementation. See notes for + _Py_HashDouble in Python/pyhash.c. Numeric hashes are based on + reduction modulo the prime 2**_PyHASH_BITS - 1. */ + +#if SIZEOF_VOID_P >= 8 +# define _PyHASH_BITS 61 +#else +# define _PyHASH_BITS 31 +#endif + +#define _PyHASH_MODULUS (((size_t)1 << _PyHASH_BITS) - 1) +#define _PyHASH_INF 314159 +#define _PyHASH_NAN 0 +#define _PyHASH_IMAG _PyHASH_MULTIPLIER + + +/* hash secret + * + * memory layout on 64 bit systems + * cccccccc cccccccc cccccccc uc -- unsigned char[24] + * pppppppp ssssssss ........ fnv -- two Py_hash_t + * k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t + * ........ ........ ssssssss djbx33a -- 16 bytes padding + one Py_hash_t + * ........ ........ eeeeeeee pyexpat XML hash salt + * + * memory layout on 32 bit systems + * cccccccc cccccccc cccccccc uc + * ppppssss ........ ........ fnv -- two Py_hash_t + * k0k0k0k0 k1k1k1k1 ........ siphash -- two uint64_t (*) + * ........ ........ ssss.... djbx33a -- 16 bytes padding + one Py_hash_t + * ........ ........ eeee.... pyexpat XML hash salt + * + * (*) The siphash member may not be available on 32 bit platforms without + * an unsigned int64 data type. + */ +#ifndef Py_LIMITED_API +typedef union { + /* ensure 24 bytes */ + unsigned char uc[24]; + /* two Py_hash_t for FNV */ + struct { + Py_hash_t prefix; + Py_hash_t suffix; + } fnv; + /* two uint64 for SipHash24 */ + struct { + uint64_t k0; + uint64_t k1; + } siphash; + /* a different (!) Py_hash_t for small string optimization */ + struct { + unsigned char padding[16]; + Py_hash_t suffix; + } djbx33a; + struct { + unsigned char padding[16]; + Py_hash_t hashsalt; + } expat; +} _Py_HashSecret_t; +PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret; +#endif + +#ifdef Py_DEBUG +PyAPI_DATA(int) _Py_HashSecret_Initialized; +#endif + + +/* hash function definition */ +#ifndef Py_LIMITED_API +typedef struct { + Py_hash_t (*const hash)(const void *, Py_ssize_t); + const char *name; + const int hash_bits; + const int seed_bits; +} PyHash_FuncDef; + +PyAPI_FUNC(PyHash_FuncDef*) PyHash_GetFuncDef(void); +#endif + + +/* cutoff for small string DJBX33A optimization in range [1, cutoff). + * + * About 50% of the strings in a typical Python application are smaller than + * 6 to 7 chars. However DJBX33A is vulnerable to hash collision attacks. + * NEVER use DJBX33A for long strings! + * + * A Py_HASH_CUTOFF of 0 disables small string optimization. 32 bit platforms + * should use a smaller cutoff because it is easier to create colliding + * strings. A cutoff of 7 on 64bit platforms and 5 on 32bit platforms should + * provide a decent safety margin. + */ +#ifndef Py_HASH_CUTOFF +# define Py_HASH_CUTOFF 0 +#elif (Py_HASH_CUTOFF > 7 || Py_HASH_CUTOFF < 0) +# error Py_HASH_CUTOFF must in range 0...7. +#endif /* Py_HASH_CUTOFF */ + + +/* hash algorithm selection + * + * The values for Py_HASH_SIPHASH24 and Py_HASH_FNV are hard-coded in the + * configure script. + * + * - FNV is available on all platforms and architectures. + * - SIPHASH24 only works on plaforms that don't require aligned memory for integers. + * - With EXTERNAL embedders can provide an alternative implementation with:: + * + * PyHash_FuncDef PyHash_Func = {...}; + * + * XXX: Figure out __declspec() for extern PyHash_FuncDef. + */ +#define Py_HASH_EXTERNAL 0 +#define Py_HASH_SIPHASH24 1 +#define Py_HASH_FNV 2 + +#ifndef Py_HASH_ALGORITHM +# ifndef HAVE_ALIGNED_REQUIRED +# define Py_HASH_ALGORITHM Py_HASH_SIPHASH24 +# else +# define Py_HASH_ALGORITHM Py_HASH_FNV +# endif /* uint64_t && uint32_t && aligned */ +#endif /* Py_HASH_ALGORITHM */ + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_HASH_H */ diff --git a/winvenv/Include/pylifecycle.h b/winvenv/Include/pylifecycle.h new file mode 100644 index 0000000..1192961 --- /dev/null +++ b/winvenv/Include/pylifecycle.h @@ -0,0 +1,226 @@ + +/* Interfaces to configure, query, create & destroy the Python runtime */ + +#ifndef Py_PYLIFECYCLE_H +#define Py_PYLIFECYCLE_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +typedef struct { + const char *prefix; + const char *msg; + int user_err; +} _PyInitError; + +/* Almost all errors causing Python initialization to fail */ +#ifdef _MSC_VER + /* Visual Studio 2015 doesn't implement C99 __func__ in C */ +# define _Py_INIT_GET_FUNC() __FUNCTION__ +#else +# define _Py_INIT_GET_FUNC() __func__ +#endif + +#define _Py_INIT_OK() \ + (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0} +#define _Py_INIT_ERR(MSG) \ + (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0} +/* Error that can be fixed by the user like invalid input parameter. + Don't abort() the process on such error. */ +#define _Py_INIT_USER_ERR(MSG) \ + (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1} +#define _Py_INIT_NO_MEMORY() _Py_INIT_USER_ERR("memory allocation failed") +#define _Py_INIT_FAILED(err) \ + (err.msg != NULL) + +#endif + + +PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); +PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); + +PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *); +PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); + +#ifndef Py_LIMITED_API +/* Only used by applications that embed the interpreter and need to + * override the standard encoding determination mechanism + */ +PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, + const char *errors); + +/* PEP 432 Multi-phase initialization API (Private while provisional!) */ +PyAPI_FUNC(_PyInitError) _Py_InitializeCore( + PyInterpreterState **interp_p, + const _PyCoreConfig *config); +PyAPI_FUNC(int) _Py_IsCoreInitialized(void); +PyAPI_FUNC(_PyInitError) _Py_InitializeFromConfig( + const _PyCoreConfig *config); +#ifdef Py_BUILD_CORE +PyAPI_FUNC(void) _Py_Initialize_ReadEnvVarsNoAlloc(void); +#endif + +PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *); +PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); +PyAPI_FUNC(int) _PyCoreConfig_Copy( + _PyCoreConfig *config, + const _PyCoreConfig *config2); +PyAPI_FUNC(void) _PyCoreConfig_SetGlobalConfig( + const _PyCoreConfig *config); + + +PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read( + _PyMainInterpreterConfig *config, + const _PyCoreConfig *core_config); +PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *); +PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy( + _PyMainInterpreterConfig *config, + const _PyMainInterpreterConfig *config2); + +PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter( + PyInterpreterState *interp, + const _PyMainInterpreterConfig *config); +#endif /* !defined(Py_LIMITED_API) */ + + +/* Initialization and finalization */ +PyAPI_FUNC(void) Py_Initialize(void); +PyAPI_FUNC(void) Py_InitializeEx(int); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _Py_FatalInitError(_PyInitError err) _Py_NO_RETURN; +#endif +PyAPI_FUNC(void) Py_Finalize(void); +PyAPI_FUNC(int) Py_FinalizeEx(void); +PyAPI_FUNC(int) Py_IsInitialized(void); + +/* Subinterpreter support */ +PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void); +PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *); + + +/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level + * exit functions. + */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(PyObject *), PyObject *); +#endif +PyAPI_FUNC(int) Py_AtExit(void (*func)(void)); + +PyAPI_FUNC(void) Py_Exit(int) _Py_NO_RETURN; + +/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _Py_RestoreSignals(void); + +PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *); +#endif + +/* Bootstrap __main__ (defined in Modules/main.c) */ +PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); +#ifdef Py_BUILD_CORE +PyAPI_FUNC(int) _Py_UnixMain(int argc, char **argv); +#endif + +/* In getpath.c */ +PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); +PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); +PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); +PyAPI_FUNC(wchar_t *) Py_GetPath(void); +#ifdef Py_BUILD_CORE +PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(const _PyCoreConfig *core_config); +PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv); +PyAPI_FUNC(int) _Py_FindEnvConfigValue( + FILE *env_file, + const wchar_t *key, + wchar_t *value, + size_t value_size); +#endif +PyAPI_FUNC(void) Py_SetPath(const wchar_t *); +#ifdef MS_WINDOWS +int _Py_CheckPython3(void); +#endif + +/* In their own files */ +PyAPI_FUNC(const char *) Py_GetVersion(void); +PyAPI_FUNC(const char *) Py_GetPlatform(void); +PyAPI_FUNC(const char *) Py_GetCopyright(void); +PyAPI_FUNC(const char *) Py_GetCompiler(void); +PyAPI_FUNC(const char *) Py_GetBuildInfo(void); +#ifndef Py_LIMITED_API +PyAPI_FUNC(const char *) _Py_gitidentifier(void); +PyAPI_FUNC(const char *) _Py_gitversion(void); +#endif + +/* Internal -- various one-time initializations */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void); +PyAPI_FUNC(_PyInitError) _PySys_BeginInit(PyObject **sysmod); +PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict, _PyMainInterpreterConfig *config); +PyAPI_FUNC(_PyInitError) _PyImport_Init(PyInterpreterState *interp); +PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod); +PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void); +PyAPI_FUNC(int) _PyFrame_Init(void); +PyAPI_FUNC(int) _PyFloat_Init(void); +PyAPI_FUNC(int) PyByteArray_Init(void); +PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(const _PyCoreConfig *); +#endif +#ifdef Py_BUILD_CORE +PyAPI_FUNC(int) _Py_ReadHashSeed( + const char *seed_text, + int *use_hash_seed, + unsigned long *hash_seed); +#endif + +/* Various internal finalizers */ + +#ifdef Py_BUILD_CORE +PyAPI_FUNC(void) _PyExc_Fini(void); +PyAPI_FUNC(void) _PyImport_Fini(void); +PyAPI_FUNC(void) _PyImport_Fini2(void); +PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void); +PyAPI_FUNC(void) _PyGC_Fini(void); +PyAPI_FUNC(void) _PyType_Fini(void); +PyAPI_FUNC(void) _Py_HashRandomization_Fini(void); +#endif /* Py_BUILD_CORE */ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) PyMethod_Fini(void); +PyAPI_FUNC(void) PyFrame_Fini(void); +PyAPI_FUNC(void) PyCFunction_Fini(void); +PyAPI_FUNC(void) PyDict_Fini(void); +PyAPI_FUNC(void) PyTuple_Fini(void); +PyAPI_FUNC(void) PyList_Fini(void); +PyAPI_FUNC(void) PySet_Fini(void); +PyAPI_FUNC(void) PyBytes_Fini(void); +PyAPI_FUNC(void) PyByteArray_Fini(void); +PyAPI_FUNC(void) PyFloat_Fini(void); +PyAPI_FUNC(void) PyOS_FiniInterrupts(void); +PyAPI_FUNC(void) PySlice_Fini(void); +PyAPI_FUNC(void) PyAsyncGen_Fini(void); + +PyAPI_FUNC(int) _Py_IsFinalizing(void); +#endif /* !Py_LIMITED_API */ + +/* Signals */ +typedef void (*PyOS_sighandler_t)(int); +PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int); +PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t); + +#ifndef Py_LIMITED_API +/* Random */ +PyAPI_FUNC(int) _PyOS_URandom(void *buffer, Py_ssize_t size); +PyAPI_FUNC(int) _PyOS_URandomNonblock(void *buffer, Py_ssize_t size); +#endif /* !Py_LIMITED_API */ + +/* Legacy locale support */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _Py_CoerceLegacyLocale(const _PyCoreConfig *config); +PyAPI_FUNC(int) _Py_LegacyLocaleDetected(void); +PyAPI_FUNC(char *) _Py_SetLocaleFromEnv(int category); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PYLIFECYCLE_H */ diff --git a/winvenv/Include/pymacconfig.h b/winvenv/Include/pymacconfig.h new file mode 100644 index 0000000..9dde11b --- /dev/null +++ b/winvenv/Include/pymacconfig.h @@ -0,0 +1,102 @@ +#ifndef PYMACCONFIG_H +#define PYMACCONFIG_H + /* + * This file moves some of the autoconf magic to compile-time + * when building on MacOSX. This is needed for building 4-way + * universal binaries and for 64-bit universal binaries because + * the values redefined below aren't configure-time constant but + * only compile-time constant in these scenarios. + */ + +#if defined(__APPLE__) + +# undef SIZEOF_LONG +# undef SIZEOF_PTHREAD_T +# undef SIZEOF_SIZE_T +# undef SIZEOF_TIME_T +# undef SIZEOF_VOID_P +# undef SIZEOF__BOOL +# undef SIZEOF_UINTPTR_T +# undef SIZEOF_PTHREAD_T +# undef WORDS_BIGENDIAN +# undef DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 +# undef DOUBLE_IS_BIG_ENDIAN_IEEE754 +# undef DOUBLE_IS_LITTLE_ENDIAN_IEEE754 +# undef HAVE_GCC_ASM_FOR_X87 + +# undef VA_LIST_IS_ARRAY +# if defined(__LP64__) && defined(__x86_64__) +# define VA_LIST_IS_ARRAY 1 +# endif + +# undef HAVE_LARGEFILE_SUPPORT +# ifndef __LP64__ +# define HAVE_LARGEFILE_SUPPORT 1 +# endif + +# undef SIZEOF_LONG +# ifdef __LP64__ +# define SIZEOF__BOOL 1 +# define SIZEOF__BOOL 1 +# define SIZEOF_LONG 8 +# define SIZEOF_PTHREAD_T 8 +# define SIZEOF_SIZE_T 8 +# define SIZEOF_TIME_T 8 +# define SIZEOF_VOID_P 8 +# define SIZEOF_UINTPTR_T 8 +# define SIZEOF_PTHREAD_T 8 +# else +# ifdef __ppc__ +# define SIZEOF__BOOL 4 +# else +# define SIZEOF__BOOL 1 +# endif +# define SIZEOF_LONG 4 +# define SIZEOF_PTHREAD_T 4 +# define SIZEOF_SIZE_T 4 +# define SIZEOF_TIME_T 4 +# define SIZEOF_VOID_P 4 +# define SIZEOF_UINTPTR_T 4 +# define SIZEOF_PTHREAD_T 4 +# endif + +# if defined(__LP64__) + /* MacOSX 10.4 (the first release to support 64-bit code + * at all) only supports 64-bit in the UNIX layer. + * Therefore suppress the toolbox-glue in 64-bit mode. + */ + + /* In 64-bit mode setpgrp always has no arguments, in 32-bit + * mode that depends on the compilation environment + */ +# undef SETPGRP_HAVE_ARG + +# endif + +#ifdef __BIG_ENDIAN__ +#define WORDS_BIGENDIAN 1 +#define DOUBLE_IS_BIG_ENDIAN_IEEE754 +#else +#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754 +#endif /* __BIG_ENDIAN */ + +#ifdef __i386__ +# define HAVE_GCC_ASM_FOR_X87 +#endif + + /* + * The definition in pyconfig.h is only valid on the OS release + * where configure ran on and not necessarily for all systems where + * the executable can be used on. + * + * Specifically: OSX 10.4 has limited supported for '%zd', while + * 10.5 has full support for '%zd'. A binary built on 10.5 won't + * work properly on 10.4 unless we suppress the definition + * of PY_FORMAT_SIZE_T + */ +#undef PY_FORMAT_SIZE_T + + +#endif /* defined(_APPLE__) */ + +#endif /* PYMACCONFIG_H */ diff --git a/winvenv/Include/pymacro.h b/winvenv/Include/pymacro.h new file mode 100644 index 0000000..3f6ddbe --- /dev/null +++ b/winvenv/Include/pymacro.h @@ -0,0 +1,100 @@ +#ifndef Py_PYMACRO_H +#define Py_PYMACRO_H + +/* Minimum value between x and y */ +#define Py_MIN(x, y) (((x) > (y)) ? (y) : (x)) + +/* Maximum value between x and y */ +#define Py_MAX(x, y) (((x) > (y)) ? (x) : (y)) + +/* Absolute value of the number x */ +#define Py_ABS(x) ((x) < 0 ? -(x) : (x)) + +#define _Py_XSTRINGIFY(x) #x + +/* Convert the argument to a string. For example, Py_STRINGIFY(123) is replaced + with "123" by the preprocessor. Defines are also replaced by their value. + For example Py_STRINGIFY(__LINE__) is replaced by the line number, not + by "__LINE__". */ +#define Py_STRINGIFY(x) _Py_XSTRINGIFY(x) + +/* Get the size of a structure member in bytes */ +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +/* Argument must be a char or an int in [-128, 127] or [0, 255]. */ +#define Py_CHARMASK(c) ((unsigned char)((c) & 0xff)) + +/* Assert a build-time dependency, as an expression. + + Your compile will fail if the condition isn't true, or can't be evaluated + by the compiler. This can be used in an expression: its value is 0. + + Example: + + #define foo_to_char(foo) \ + ((char *)(foo) \ + + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0)) + + Written by Rusty Russell, public domain, http://ccodearchive.net/ */ +#define Py_BUILD_ASSERT_EXPR(cond) \ + (sizeof(char [1 - 2*!(cond)]) - 1) + +#define Py_BUILD_ASSERT(cond) do { \ + (void)Py_BUILD_ASSERT_EXPR(cond); \ + } while(0) + +/* Get the number of elements in a visible array + + This does not work on pointers, or arrays declared as [], or function + parameters. With correct compiler support, such usage will cause a build + error (see Py_BUILD_ASSERT_EXPR). + + Written by Rusty Russell, public domain, http://ccodearchive.net/ + + Requires at GCC 3.1+ */ +#if (defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ + (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ >= 4))) +/* Two gcc extensions. + &a[0] degrades to a pointer: a different type from an array */ +#define Py_ARRAY_LENGTH(array) \ + (sizeof(array) / sizeof((array)[0]) \ + + Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(array), \ + typeof(&(array)[0])))) +#else +#define Py_ARRAY_LENGTH(array) \ + (sizeof(array) / sizeof((array)[0])) +#endif + + +/* Define macros for inline documentation. */ +#define PyDoc_VAR(name) static char name[] +#define PyDoc_STRVAR(name,str) PyDoc_VAR(name) = PyDoc_STR(str) +#ifdef WITH_DOC_STRINGS +#define PyDoc_STR(str) str +#else +#define PyDoc_STR(str) "" +#endif + +/* Below "a" is a power of 2. */ +/* Round down size "n" to be a multiple of "a". */ +#define _Py_SIZE_ROUND_DOWN(n, a) ((size_t)(n) & ~(size_t)((a) - 1)) +/* Round up size "n" to be a multiple of "a". */ +#define _Py_SIZE_ROUND_UP(n, a) (((size_t)(n) + \ + (size_t)((a) - 1)) & ~(size_t)((a) - 1)) +/* Round pointer "p" down to the closest "a"-aligned address <= "p". */ +#define _Py_ALIGN_DOWN(p, a) ((void *)((uintptr_t)(p) & ~(uintptr_t)((a) - 1))) +/* Round pointer "p" up to the closest "a"-aligned address >= "p". */ +#define _Py_ALIGN_UP(p, a) ((void *)(((uintptr_t)(p) + \ + (uintptr_t)((a) - 1)) & ~(uintptr_t)((a) - 1))) +/* Check if pointer "p" is aligned to "a"-bytes boundary. */ +#define _Py_IS_ALIGNED(p, a) (!((uintptr_t)(p) & (uintptr_t)((a) - 1))) + +#ifdef __GNUC__ +#define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) +#else +#define Py_UNUSED(name) _unused_ ## name +#endif + +#define Py_UNREACHABLE() abort() + +#endif /* Py_PYMACRO_H */ diff --git a/winvenv/Include/pymath.h b/winvenv/Include/pymath.h new file mode 100644 index 0000000..6cf69f9 --- /dev/null +++ b/winvenv/Include/pymath.h @@ -0,0 +1,230 @@ +#ifndef Py_PYMATH_H +#define Py_PYMATH_H + +#include "pyconfig.h" /* include for defines */ + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to mathematical +functions and constants +**************************************************************************/ + +/* Python provides implementations for copysign, round and hypot in + * Python/pymath.c just in case your math library doesn't provide the + * functions. + * + *Note: PC/pyconfig.h defines copysign as _copysign + */ +#ifndef HAVE_COPYSIGN +extern double copysign(double, double); +#endif + +#ifndef HAVE_ROUND +extern double round(double); +#endif + +#ifndef HAVE_HYPOT +extern double hypot(double, double); +#endif + +/* extra declarations */ +#ifndef _MSC_VER +#ifndef __STDC__ +extern double fmod (double, double); +extern double frexp (double, int *); +extern double ldexp (double, int); +extern double modf (double, double *); +extern double pow(double, double); +#endif /* __STDC__ */ +#endif /* _MSC_VER */ + +/* High precision definition of pi and e (Euler) + * The values are taken from libc6's math.h. + */ +#ifndef Py_MATH_PIl +#define Py_MATH_PIl 3.1415926535897932384626433832795029L +#endif +#ifndef Py_MATH_PI +#define Py_MATH_PI 3.14159265358979323846 +#endif + +#ifndef Py_MATH_El +#define Py_MATH_El 2.7182818284590452353602874713526625L +#endif + +#ifndef Py_MATH_E +#define Py_MATH_E 2.7182818284590452354 +#endif + +/* Tau (2pi) to 40 digits, taken from tauday.com/tau-digits. */ +#ifndef Py_MATH_TAU +#define Py_MATH_TAU 6.2831853071795864769252867665590057683943L +#endif + + +/* On x86, Py_FORCE_DOUBLE forces a floating-point number out of an x87 FPU + register and into a 64-bit memory location, rounding from extended + precision to double precision in the process. On other platforms it does + nothing. */ + +/* we take double rounding as evidence of x87 usage */ +#ifndef Py_LIMITED_API +#ifndef Py_FORCE_DOUBLE +# ifdef X87_DOUBLE_ROUNDING +PyAPI_FUNC(double) _Py_force_double(double); +# define Py_FORCE_DOUBLE(X) (_Py_force_double(X)) +# else +# define Py_FORCE_DOUBLE(X) (X) +# endif +#endif +#endif + +#ifndef Py_LIMITED_API +#ifdef HAVE_GCC_ASM_FOR_X87 +PyAPI_FUNC(unsigned short) _Py_get_387controlword(void); +PyAPI_FUNC(void) _Py_set_387controlword(unsigned short); +#endif +#endif + +/* Py_IS_NAN(X) + * Return 1 if float or double arg is a NaN, else 0. + * Caution: + * X is evaluated more than once. + * This may not work on all platforms. Each platform has *some* + * way to spell this, though -- override in pyconfig.h if you have + * a platform where it doesn't work. + * Note: PC/pyconfig.h defines Py_IS_NAN as _isnan + */ +#ifndef Py_IS_NAN +#if defined HAVE_DECL_ISNAN && HAVE_DECL_ISNAN == 1 +#define Py_IS_NAN(X) isnan(X) +#else +#define Py_IS_NAN(X) ((X) != (X)) +#endif +#endif + +/* Py_IS_INFINITY(X) + * Return 1 if float or double arg is an infinity, else 0. + * Caution: + * X is evaluated more than once. + * This implementation may set the underflow flag if |X| is very small; + * it really can't be implemented correctly (& easily) before C99. + * Override in pyconfig.h if you have a better spelling on your platform. + * Py_FORCE_DOUBLE is used to avoid getting false negatives from a + * non-infinite value v sitting in an 80-bit x87 register such that + * v becomes infinite when spilled from the register to 64-bit memory. + * Note: PC/pyconfig.h defines Py_IS_INFINITY as _isinf + */ +#ifndef Py_IS_INFINITY +# if defined HAVE_DECL_ISINF && HAVE_DECL_ISINF == 1 +# define Py_IS_INFINITY(X) isinf(X) +# else +# define Py_IS_INFINITY(X) ((X) && \ + (Py_FORCE_DOUBLE(X)*0.5 == Py_FORCE_DOUBLE(X))) +# endif +#endif + +/* Py_IS_FINITE(X) + * Return 1 if float or double arg is neither infinite nor NAN, else 0. + * Some compilers (e.g. VisualStudio) have intrisics for this, so a special + * macro for this particular test is useful + * Note: PC/pyconfig.h defines Py_IS_FINITE as _finite + */ +#ifndef Py_IS_FINITE +#if defined HAVE_DECL_ISFINITE && HAVE_DECL_ISFINITE == 1 +#define Py_IS_FINITE(X) isfinite(X) +#elif defined HAVE_FINITE +#define Py_IS_FINITE(X) finite(X) +#else +#define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X)) +#endif +#endif + +/* HUGE_VAL is supposed to expand to a positive double infinity. Python + * uses Py_HUGE_VAL instead because some platforms are broken in this + * respect. We used to embed code in pyport.h to try to worm around that, + * but different platforms are broken in conflicting ways. If you're on + * a platform where HUGE_VAL is defined incorrectly, fiddle your Python + * config to #define Py_HUGE_VAL to something that works on your platform. + */ +#ifndef Py_HUGE_VAL +#define Py_HUGE_VAL HUGE_VAL +#endif + +/* Py_NAN + * A value that evaluates to a NaN. On IEEE 754 platforms INF*0 or + * INF/INF works. Define Py_NO_NAN in pyconfig.h if your platform + * doesn't support NaNs. + */ +#if !defined(Py_NAN) && !defined(Py_NO_NAN) +#if !defined(__INTEL_COMPILER) + #define Py_NAN (Py_HUGE_VAL * 0.) +#else /* __INTEL_COMPILER */ + #if defined(ICC_NAN_STRICT) + #pragma float_control(push) + #pragma float_control(precise, on) + #pragma float_control(except, on) + #if defined(_MSC_VER) + __declspec(noinline) + #else /* Linux */ + __attribute__((noinline)) + #endif /* _MSC_VER */ + static double __icc_nan() + { + return sqrt(-1.0); + } + #pragma float_control (pop) + #define Py_NAN __icc_nan() + #else /* ICC_NAN_RELAXED as default for Intel Compiler */ + static const union { unsigned char buf[8]; double __icc_nan; } __nan_store = {0,0,0,0,0,0,0xf8,0x7f}; + #define Py_NAN (__nan_store.__icc_nan) + #endif /* ICC_NAN_STRICT */ +#endif /* __INTEL_COMPILER */ +#endif + +/* Py_OVERFLOWED(X) + * Return 1 iff a libm function overflowed. Set errno to 0 before calling + * a libm function, and invoke this macro after, passing the function + * result. + * Caution: + * This isn't reliable. C99 no longer requires libm to set errno under + * any exceptional condition, but does require +- HUGE_VAL return + * values on overflow. A 754 box *probably* maps HUGE_VAL to a + * double infinity, and we're cool if that's so, unless the input + * was an infinity and an infinity is the expected result. A C89 + * system sets errno to ERANGE, so we check for that too. We're + * out of luck if a C99 754 box doesn't map HUGE_VAL to +Inf, or + * if the returned result is a NaN, or if a C89 box returns HUGE_VAL + * in non-overflow cases. + * X is evaluated more than once. + * Some platforms have better way to spell this, so expect some #ifdef'ery. + * + * OpenBSD uses 'isinf()' because a compiler bug on that platform causes + * the longer macro version to be mis-compiled. This isn't optimal, and + * should be removed once a newer compiler is available on that platform. + * The system that had the failure was running OpenBSD 3.2 on Intel, with + * gcc 2.95.3. + * + * According to Tim's checkin, the FreeBSD systems use isinf() to work + * around a FPE bug on that platform. + */ +#if defined(__FreeBSD__) || defined(__OpenBSD__) +#define Py_OVERFLOWED(X) isinf(X) +#else +#define Py_OVERFLOWED(X) ((X) != 0.0 && (errno == ERANGE || \ + (X) == Py_HUGE_VAL || \ + (X) == -Py_HUGE_VAL)) +#endif + +/* Return whether integral type *type* is signed or not. */ +#define _Py_IntegralTypeSigned(type) ((type)(-1) < 0) +/* Return the maximum value of integral type *type*. */ +#define _Py_IntegralTypeMax(type) ((_Py_IntegralTypeSigned(type)) ? (((((type)1 << (sizeof(type)*CHAR_BIT - 2)) - 1) << 1) + 1) : ~(type)0) +/* Return the minimum value of integral type *type*. */ +#define _Py_IntegralTypeMin(type) ((_Py_IntegralTypeSigned(type)) ? -_Py_IntegralTypeMax(type) - 1 : 0) +/* Check whether *v* is in the range of integral type *type*. This is most + * useful if *v* is floating-point, since demoting a floating-point *v* to an + * integral type that cannot represent *v*'s integral part is undefined + * behavior. */ +#define _Py_InIntegralTypeRange(type, v) (_Py_IntegralTypeMin(type) <= v && v <= _Py_IntegralTypeMax(type)) + +#endif /* Py_PYMATH_H */ diff --git a/winvenv/Include/pymem.h b/winvenv/Include/pymem.h new file mode 100644 index 0000000..8ee0efd --- /dev/null +++ b/winvenv/Include/pymem.h @@ -0,0 +1,244 @@ +/* The PyMem_ family: low-level memory allocation interfaces. + See objimpl.h for the PyObject_ memory family. +*/ + +#ifndef Py_PYMEM_H +#define Py_PYMEM_H + +#include "pyport.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size); +PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize); +PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size); +PyAPI_FUNC(void) PyMem_RawFree(void *ptr); + +/* Configure the Python memory allocators. Pass NULL to use default + allocators. */ +PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt); + +/* Try to get the allocators name set by _PyMem_SetupAllocators(). */ +PyAPI_FUNC(const char*) _PyMem_GetAllocatorsName(void); + +/* Track an allocated memory block in the tracemalloc module. + Return 0 on success, return -1 on error (failed to allocate memory to store + the trace). + + Return -2 if tracemalloc is disabled. + + If memory block is already tracked, update the existing trace. */ +PyAPI_FUNC(int) PyTraceMalloc_Track( + unsigned int domain, + uintptr_t ptr, + size_t size); + +/* Untrack an allocated memory block in the tracemalloc module. + Do nothing if the block was not tracked. + + Return -2 if tracemalloc is disabled, otherwise return 0. */ +PyAPI_FUNC(int) PyTraceMalloc_Untrack( + unsigned int domain, + uintptr_t ptr); + +/* Get the traceback where a memory block was allocated. + + Return a tuple of (filename: str, lineno: int) tuples. + + Return None if the tracemalloc module is disabled or if the memory block + is not tracked by tracemalloc. + + Raise an exception and return NULL on error. */ +PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback( + unsigned int domain, + uintptr_t ptr); +#endif /* !Py_LIMITED_API */ + + +/* BEWARE: + + Each interface exports both functions and macros. Extension modules should + use the functions, to ensure binary compatibility across Python versions. + Because the Python implementation is free to change internal details, and + the macros may (or may not) expose details for speed, if you do use the + macros you must recompile your extensions with each Python release. + + Never mix calls to PyMem_ with calls to the platform malloc/realloc/ + calloc/free. For example, on Windows different DLLs may end up using + different heaps, and if you use PyMem_Malloc you'll get the memory from the + heap used by the Python DLL; it could be a disaster if you free()'ed that + directly in your own extension. Using PyMem_Free instead ensures Python + can return the memory to the proper heap. As another example, in + PYMALLOC_DEBUG mode, Python wraps all calls to all PyMem_ and PyObject_ + memory functions in special debugging wrappers that add additional + debugging info to dynamic memory blocks. The system routines have no idea + what to do with that stuff, and the Python wrappers have no idea what to do + with raw blocks obtained directly by the system routines then. + + The GIL must be held when using these APIs. +*/ + +/* + * Raw memory interface + * ==================== + */ + +/* Functions + + Functions supplying platform-independent semantics for malloc/realloc/ + free. These functions make sure that allocating 0 bytes returns a distinct + non-NULL pointer (whenever possible -- if we're flat out of memory, NULL + may be returned), even if the platform malloc and realloc don't. + Returned pointers must be checked for NULL explicitly. No action is + performed on failure (no exception is set, no warning is printed, etc). +*/ + +PyAPI_FUNC(void *) PyMem_Malloc(size_t size); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize); +#endif +PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size); +PyAPI_FUNC(void) PyMem_Free(void *ptr); + +#ifndef Py_LIMITED_API +/* strdup() using PyMem_RawMalloc() */ +PyAPI_FUNC(char *) _PyMem_RawStrdup(const char *str); + +/* strdup() using PyMem_Malloc() */ +PyAPI_FUNC(char *) _PyMem_Strdup(const char *str); + +/* wcsdup() using PyMem_RawMalloc() */ +PyAPI_FUNC(wchar_t*) _PyMem_RawWcsdup(const wchar_t *str); +#endif + +/* Macros. */ + +/* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL + for malloc(0), which would be treated as an error. Some platforms + would return a pointer with no memory behind it, which would break + pymalloc. To solve these problems, allocate an extra byte. */ +/* Returns NULL to indicate error if a negative size or size larger than + Py_ssize_t can represent is supplied. Helps prevents security holes. */ +#define PyMem_MALLOC(n) PyMem_Malloc(n) +#define PyMem_REALLOC(p, n) PyMem_Realloc(p, n) +#define PyMem_FREE(p) PyMem_Free(p) + +/* + * Type-oriented memory interface + * ============================== + * + * Allocate memory for n objects of the given type. Returns a new pointer + * or NULL if the request was too large or memory allocation failed. Use + * these macros rather than doing the multiplication yourself so that proper + * overflow checking is always done. + */ + +#define PyMem_New(type, n) \ + ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ + ( (type *) PyMem_Malloc((n) * sizeof(type)) ) ) +#define PyMem_NEW(type, n) \ + ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ + ( (type *) PyMem_MALLOC((n) * sizeof(type)) ) ) + +/* + * The value of (p) is always clobbered by this macro regardless of success. + * The caller MUST check if (p) is NULL afterwards and deal with the memory + * error if so. This means the original value of (p) MUST be saved for the + * caller's memory error handler to not lose track of it. + */ +#define PyMem_Resize(p, type, n) \ + ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ + (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) +#define PyMem_RESIZE(p, type, n) \ + ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ + (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) + +/* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used + * anymore. They're just confusing aliases for PyMem_{Free,FREE} now. + */ +#define PyMem_Del PyMem_Free +#define PyMem_DEL PyMem_FREE + +#ifndef Py_LIMITED_API +typedef enum { + /* PyMem_RawMalloc(), PyMem_RawRealloc() and PyMem_RawFree() */ + PYMEM_DOMAIN_RAW, + + /* PyMem_Malloc(), PyMem_Realloc() and PyMem_Free() */ + PYMEM_DOMAIN_MEM, + + /* PyObject_Malloc(), PyObject_Realloc() and PyObject_Free() */ + PYMEM_DOMAIN_OBJ +} PyMemAllocatorDomain; + +typedef struct { + /* user context passed as the first argument to the 4 functions */ + void *ctx; + + /* allocate a memory block */ + void* (*malloc) (void *ctx, size_t size); + + /* allocate a memory block initialized by zeros */ + void* (*calloc) (void *ctx, size_t nelem, size_t elsize); + + /* allocate or resize a memory block */ + void* (*realloc) (void *ctx, void *ptr, size_t new_size); + + /* release a memory block */ + void (*free) (void *ctx, void *ptr); +} PyMemAllocatorEx; + +/* Get the memory block allocator of the specified domain. */ +PyAPI_FUNC(void) PyMem_GetAllocator(PyMemAllocatorDomain domain, + PyMemAllocatorEx *allocator); + +/* Set the memory block allocator of the specified domain. + + The new allocator must return a distinct non-NULL pointer when requesting + zero bytes. + + For the PYMEM_DOMAIN_RAW domain, the allocator must be thread-safe: the GIL + is not held when the allocator is called. + + If the new allocator is not a hook (don't call the previous allocator), the + PyMem_SetupDebugHooks() function must be called to reinstall the debug hooks + on top on the new allocator. */ +PyAPI_FUNC(void) PyMem_SetAllocator(PyMemAllocatorDomain domain, + PyMemAllocatorEx *allocator); + +/* Setup hooks to detect bugs in the following Python memory allocator + functions: + + - PyMem_RawMalloc(), PyMem_RawRealloc(), PyMem_RawFree() + - PyMem_Malloc(), PyMem_Realloc(), PyMem_Free() + - PyObject_Malloc(), PyObject_Realloc() and PyObject_Free() + + Newly allocated memory is filled with the byte 0xCB, freed memory is filled + with the byte 0xDB. Additional checks: + + - detect API violations, ex: PyObject_Free() called on a buffer allocated + by PyMem_Malloc() + - detect write before the start of the buffer (buffer underflow) + - detect write after the end of the buffer (buffer overflow) + + The function does nothing if Python is not compiled is debug mode. */ +PyAPI_FUNC(void) PyMem_SetupDebugHooks(void); +#endif + +#ifdef Py_BUILD_CORE +/* Set the memory allocator of the specified domain to the default. + Save the old allocator into *old_alloc if it's non-NULL. + Return on success, or return -1 if the domain is unknown. */ +PyAPI_FUNC(int) _PyMem_SetDefaultAllocator( + PyMemAllocatorDomain domain, + PyMemAllocatorEx *old_alloc); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_PYMEM_H */ diff --git a/winvenv/Include/pyport.h b/winvenv/Include/pyport.h new file mode 100644 index 0000000..c1f4c7f --- /dev/null +++ b/winvenv/Include/pyport.h @@ -0,0 +1,793 @@ +#ifndef Py_PYPORT_H +#define Py_PYPORT_H + +#include "pyconfig.h" /* include for defines */ + +#include + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to basic +C language & library operations whose spellings vary across platforms. + +Please try to make documentation here as clear as possible: by definition, +the stuff here is trying to illuminate C's darkest corners. + +Config #defines referenced here: + +SIGNED_RIGHT_SHIFT_ZERO_FILLS +Meaning: To be defined iff i>>j does not extend the sign bit when i is a + signed integral type and i < 0. +Used in: Py_ARITHMETIC_RIGHT_SHIFT + +Py_DEBUG +Meaning: Extra checks compiled in for debug mode. +Used in: Py_SAFE_DOWNCAST + +**************************************************************************/ + +/* typedefs for some C9X-defined synonyms for integral types. + * + * The names in Python are exactly the same as the C9X names, except with a + * Py_ prefix. Until C9X is universally implemented, this is the only way + * to ensure that Python gets reliable names that don't conflict with names + * in non-Python code that are playing their own tricks to define the C9X + * names. + * + * NOTE: don't go nuts here! Python has no use for *most* of the C9X + * integral synonyms. Only define the ones we actually need. + */ + +/* long long is required. Ensure HAVE_LONG_LONG is defined for compatibility. */ +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG 1 +#endif +#ifndef PY_LONG_LONG +#define PY_LONG_LONG long long +/* If LLONG_MAX is defined in limits.h, use that. */ +#define PY_LLONG_MIN LLONG_MIN +#define PY_LLONG_MAX LLONG_MAX +#define PY_ULLONG_MAX ULLONG_MAX +#endif + +#define PY_UINT32_T uint32_t +#define PY_UINT64_T uint64_t + +/* Signed variants of the above */ +#define PY_INT32_T int32_t +#define PY_INT64_T int64_t + +/* If PYLONG_BITS_IN_DIGIT is not defined then we'll use 30-bit digits if all + the necessary integer types are available, and we're on a 64-bit platform + (as determined by SIZEOF_VOID_P); otherwise we use 15-bit digits. */ + +#ifndef PYLONG_BITS_IN_DIGIT +#if SIZEOF_VOID_P >= 8 +#define PYLONG_BITS_IN_DIGIT 30 +#else +#define PYLONG_BITS_IN_DIGIT 15 +#endif +#endif + +/* uintptr_t is the C9X name for an unsigned integral type such that a + * legitimate void* can be cast to uintptr_t and then back to void* again + * without loss of information. Similarly for intptr_t, wrt a signed + * integral type. + */ +typedef uintptr_t Py_uintptr_t; +typedef intptr_t Py_intptr_t; + +/* Py_ssize_t is a signed integral type such that sizeof(Py_ssize_t) == + * sizeof(size_t). C99 doesn't define such a thing directly (size_t is an + * unsigned integral type). See PEP 353 for details. + */ +#ifdef HAVE_SSIZE_T +typedef ssize_t Py_ssize_t; +#elif SIZEOF_VOID_P == SIZEOF_SIZE_T +typedef Py_intptr_t Py_ssize_t; +#else +# error "Python needs a typedef for Py_ssize_t in pyport.h." +#endif + +/* Py_hash_t is the same size as a pointer. */ +#define SIZEOF_PY_HASH_T SIZEOF_SIZE_T +typedef Py_ssize_t Py_hash_t; +/* Py_uhash_t is the unsigned equivalent needed to calculate numeric hash. */ +#define SIZEOF_PY_UHASH_T SIZEOF_SIZE_T +typedef size_t Py_uhash_t; + +/* Only used for compatibility with code that may not be PY_SSIZE_T_CLEAN. */ +#ifdef PY_SSIZE_T_CLEAN +typedef Py_ssize_t Py_ssize_clean_t; +#else +typedef int Py_ssize_clean_t; +#endif + +/* Largest possible value of size_t. */ +#define PY_SIZE_MAX SIZE_MAX + +/* Largest positive value of type Py_ssize_t. */ +#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) +/* Smallest negative value of type Py_ssize_t. */ +#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) + +/* PY_FORMAT_SIZE_T is a platform-specific modifier for use in a printf + * format to convert an argument with the width of a size_t or Py_ssize_t. + * C99 introduced "z" for this purpose, but not all platforms support that; + * e.g., MS compilers use "I" instead. + * + * These "high level" Python format functions interpret "z" correctly on + * all platforms (Python interprets the format string itself, and does whatever + * the platform C requires to convert a size_t/Py_ssize_t argument): + * + * PyBytes_FromFormat + * PyErr_Format + * PyBytes_FromFormatV + * PyUnicode_FromFormatV + * + * Lower-level uses require that you interpolate the correct format modifier + * yourself (e.g., calling printf, fprintf, sprintf, PyOS_snprintf); for + * example, + * + * Py_ssize_t index; + * fprintf(stderr, "index %" PY_FORMAT_SIZE_T "d sucks\n", index); + * + * That will expand to %ld, or %Id, or to something else correct for a + * Py_ssize_t on the platform. + */ +#ifndef PY_FORMAT_SIZE_T +# if SIZEOF_SIZE_T == SIZEOF_INT && !defined(__APPLE__) +# define PY_FORMAT_SIZE_T "" +# elif SIZEOF_SIZE_T == SIZEOF_LONG +# define PY_FORMAT_SIZE_T "l" +# elif defined(MS_WINDOWS) +# define PY_FORMAT_SIZE_T "I" +# else +# error "This platform's pyconfig.h needs to define PY_FORMAT_SIZE_T" +# endif +#endif + +/* Py_LOCAL can be used instead of static to get the fastest possible calling + * convention for functions that are local to a given module. + * + * Py_LOCAL_INLINE does the same thing, and also explicitly requests inlining, + * for platforms that support that. + * + * If PY_LOCAL_AGGRESSIVE is defined before python.h is included, more + * "aggressive" inlining/optimization is enabled for the entire module. This + * may lead to code bloat, and may slow things down for those reasons. It may + * also lead to errors, if the code relies on pointer aliasing. Use with + * care. + * + * NOTE: You can only use this for functions that are entirely local to a + * module; functions that are exported via method tables, callbacks, etc, + * should keep using static. + */ + +#if defined(_MSC_VER) +#if defined(PY_LOCAL_AGGRESSIVE) +/* enable more aggressive optimization for visual studio */ +#pragma optimize("agtw", on) +#endif +/* ignore warnings if the compiler decides not to inline a function */ +#pragma warning(disable: 4710) +/* fastest possible local call under MSVC */ +#define Py_LOCAL(type) static type __fastcall +#define Py_LOCAL_INLINE(type) static __inline type __fastcall +#else +#define Py_LOCAL(type) static type +#define Py_LOCAL_INLINE(type) static inline type +#endif + +/* Py_MEMCPY is kept for backwards compatibility, + * see https://bugs.python.org/issue28126 */ +#define Py_MEMCPY memcpy + +#include + +#ifdef HAVE_IEEEFP_H +#include /* needed for 'finite' declaration on some platforms */ +#endif + +#include /* Moved here from the math section, before extern "C" */ + +/******************************************** + * WRAPPER FOR and/or * + ********************************************/ + +#ifdef TIME_WITH_SYS_TIME +#include +#include +#else /* !TIME_WITH_SYS_TIME */ +#ifdef HAVE_SYS_TIME_H +#include +#else /* !HAVE_SYS_TIME_H */ +#include +#endif /* !HAVE_SYS_TIME_H */ +#endif /* !TIME_WITH_SYS_TIME */ + + +/****************************** + * WRAPPER FOR * + ******************************/ + +/* NB caller must include */ + +#ifdef HAVE_SYS_SELECT_H +#include +#endif /* !HAVE_SYS_SELECT_H */ + +/******************************* + * stat() and fstat() fiddling * + *******************************/ + +#ifdef HAVE_SYS_STAT_H +#include +#elif defined(HAVE_STAT_H) +#include +#endif + +#ifndef S_IFMT +/* VisualAge C/C++ Failed to Define MountType Field in sys/stat.h */ +#define S_IFMT 0170000 +#endif + +#ifndef S_IFLNK +/* Windows doesn't define S_IFLNK but posixmodule.c maps + * IO_REPARSE_TAG_SYMLINK to S_IFLNK */ +# define S_IFLNK 0120000 +#endif + +#ifndef S_ISREG +#define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) +#endif + +#ifndef S_ISDIR +#define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISCHR +#define S_ISCHR(x) (((x) & S_IFMT) == S_IFCHR) +#endif + +#ifdef __cplusplus +/* Move this down here since some C++ #include's don't like to be included + inside an extern "C" */ +extern "C" { +#endif + + +/* Py_ARITHMETIC_RIGHT_SHIFT + * C doesn't define whether a right-shift of a signed integer sign-extends + * or zero-fills. Here a macro to force sign extension: + * Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) + * Return I >> J, forcing sign extension. Arithmetically, return the + * floor of I/2**J. + * Requirements: + * I should have signed integer type. In the terminology of C99, this can + * be either one of the five standard signed integer types (signed char, + * short, int, long, long long) or an extended signed integer type. + * J is an integer >= 0 and strictly less than the number of bits in the + * type of I (because C doesn't define what happens for J outside that + * range either). + * TYPE used to specify the type of I, but is now ignored. It's been left + * in for backwards compatibility with versions <= 2.6 or 3.0. + * Caution: + * I may be evaluated more than once. + */ +#ifdef SIGNED_RIGHT_SHIFT_ZERO_FILLS +#define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) \ + ((I) < 0 ? -1-((-1-(I)) >> (J)) : (I) >> (J)) +#else +#define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) ((I) >> (J)) +#endif + +/* Py_FORCE_EXPANSION(X) + * "Simply" returns its argument. However, macro expansions within the + * argument are evaluated. This unfortunate trickery is needed to get + * token-pasting to work as desired in some cases. + */ +#define Py_FORCE_EXPANSION(X) X + +/* Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) + * Cast VALUE to type NARROW from type WIDE. In Py_DEBUG mode, this + * assert-fails if any information is lost. + * Caution: + * VALUE may be evaluated more than once. + */ +#ifdef Py_DEBUG +#define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) \ + (assert((WIDE)(NARROW)(VALUE) == (VALUE)), (NARROW)(VALUE)) +#else +#define Py_SAFE_DOWNCAST(VALUE, WIDE, NARROW) (NARROW)(VALUE) +#endif + +/* Py_SET_ERRNO_ON_MATH_ERROR(x) + * If a libm function did not set errno, but it looks like the result + * overflowed or not-a-number, set errno to ERANGE or EDOM. Set errno + * to 0 before calling a libm function, and invoke this macro after, + * passing the function result. + * Caution: + * This isn't reliable. See Py_OVERFLOWED comments. + * X is evaluated more than once. + */ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__hpux) && defined(__ia64)) +#define _Py_SET_EDOM_FOR_NAN(X) if (isnan(X)) errno = EDOM; +#else +#define _Py_SET_EDOM_FOR_NAN(X) ; +#endif +#define Py_SET_ERRNO_ON_MATH_ERROR(X) \ + do { \ + if (errno == 0) { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL) \ + errno = ERANGE; \ + else _Py_SET_EDOM_FOR_NAN(X) \ + } \ + } while(0) + +/* Py_SET_ERANGE_ON_OVERFLOW(x) + * An alias of Py_SET_ERRNO_ON_MATH_ERROR for backward-compatibility. + */ +#define Py_SET_ERANGE_IF_OVERFLOW(X) Py_SET_ERRNO_ON_MATH_ERROR(X) + +/* Py_ADJUST_ERANGE1(x) + * Py_ADJUST_ERANGE2(x, y) + * Set errno to 0 before calling a libm function, and invoke one of these + * macros after, passing the function result(s) (Py_ADJUST_ERANGE2 is useful + * for functions returning complex results). This makes two kinds of + * adjustments to errno: (A) If it looks like the platform libm set + * errno=ERANGE due to underflow, clear errno. (B) If it looks like the + * platform libm overflowed but didn't set errno, force errno to ERANGE. In + * effect, we're trying to force a useful implementation of C89 errno + * behavior. + * Caution: + * This isn't reliable. See Py_OVERFLOWED comments. + * X and Y may be evaluated more than once. + */ +#define Py_ADJUST_ERANGE1(X) \ + do { \ + if (errno == 0) { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL) \ + errno = ERANGE; \ + } \ + else if (errno == ERANGE && (X) == 0.0) \ + errno = 0; \ + } while(0) + +#define Py_ADJUST_ERANGE2(X, Y) \ + do { \ + if ((X) == Py_HUGE_VAL || (X) == -Py_HUGE_VAL || \ + (Y) == Py_HUGE_VAL || (Y) == -Py_HUGE_VAL) { \ + if (errno == 0) \ + errno = ERANGE; \ + } \ + else if (errno == ERANGE) \ + errno = 0; \ + } while(0) + +/* The functions _Py_dg_strtod and _Py_dg_dtoa in Python/dtoa.c (which are + * required to support the short float repr introduced in Python 3.1) require + * that the floating-point unit that's being used for arithmetic operations + * on C doubles is set to use 53-bit precision. It also requires that the + * FPU rounding mode is round-half-to-even, but that's less often an issue. + * + * If your FPU isn't already set to 53-bit precision/round-half-to-even, and + * you want to make use of _Py_dg_strtod and _Py_dg_dtoa, then you should + * + * #define HAVE_PY_SET_53BIT_PRECISION 1 + * + * and also give appropriate definitions for the following three macros: + * + * _PY_SET_53BIT_PRECISION_START : store original FPU settings, and + * set FPU to 53-bit precision/round-half-to-even + * _PY_SET_53BIT_PRECISION_END : restore original FPU settings + * _PY_SET_53BIT_PRECISION_HEADER : any variable declarations needed to + * use the two macros above. + * + * The macros are designed to be used within a single C function: see + * Python/pystrtod.c for an example of their use. + */ + +/* get and set x87 control word for gcc/x86 */ +#ifdef HAVE_GCC_ASM_FOR_X87 +#define HAVE_PY_SET_53BIT_PRECISION 1 +/* _Py_get/set_387controlword functions are defined in Python/pymath.c */ +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned short old_387controlword, new_387controlword +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + old_387controlword = _Py_get_387controlword(); \ + new_387controlword = (old_387controlword & ~0x0f00) | 0x0200; \ + if (new_387controlword != old_387controlword) \ + _Py_set_387controlword(new_387controlword); \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + if (new_387controlword != old_387controlword) \ + _Py_set_387controlword(old_387controlword) +#endif + +/* get and set x87 control word for VisualStudio/x86 */ +#if defined(_MSC_VER) && !defined(_WIN64) /* x87 not supported in 64-bit */ +#define HAVE_PY_SET_53BIT_PRECISION 1 +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_387controlword, new_387controlword, out_387controlword +/* We use the __control87_2 function to set only the x87 control word. + The SSE control word is unaffected. */ +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __control87_2(0, 0, &old_387controlword, NULL); \ + new_387controlword = \ + (old_387controlword & ~(_MCW_PC | _MCW_RC)) | (_PC_53 | _RC_NEAR); \ + if (new_387controlword != old_387controlword) \ + __control87_2(new_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_387controlword != old_387controlword) \ + __control87_2(old_387controlword, _MCW_PC | _MCW_RC, \ + &out_387controlword, NULL); \ + } while (0) +#endif + +#ifdef HAVE_GCC_ASM_FOR_MC68881 +#define HAVE_PY_SET_53BIT_PRECISION 1 +#define _Py_SET_53BIT_PRECISION_HEADER \ + unsigned int old_fpcr, new_fpcr +#define _Py_SET_53BIT_PRECISION_START \ + do { \ + __asm__ ("fmove.l %%fpcr,%0" : "=g" (old_fpcr)); \ + /* Set double precision / round to nearest. */ \ + new_fpcr = (old_fpcr & ~0xf0) | 0x80; \ + if (new_fpcr != old_fpcr) \ + __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (new_fpcr)); \ + } while (0) +#define _Py_SET_53BIT_PRECISION_END \ + do { \ + if (new_fpcr != old_fpcr) \ + __asm__ volatile ("fmove.l %0,%%fpcr" : : "g" (old_fpcr)); \ + } while (0) +#endif + +/* default definitions are empty */ +#ifndef HAVE_PY_SET_53BIT_PRECISION +#define _Py_SET_53BIT_PRECISION_HEADER +#define _Py_SET_53BIT_PRECISION_START +#define _Py_SET_53BIT_PRECISION_END +#endif + +/* If we can't guarantee 53-bit precision, don't use the code + in Python/dtoa.c, but fall back to standard code. This + means that repr of a float will be long (17 sig digits). + + Realistically, there are two things that could go wrong: + + (1) doubles aren't IEEE 754 doubles, or + (2) we're on x86 with the rounding precision set to 64-bits + (extended precision), and we don't know how to change + the rounding precision. + */ + +#if !defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) && \ + !defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) && \ + !defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754) +#define PY_NO_SHORT_FLOAT_REPR +#endif + +/* double rounding is symptomatic of use of extended precision on x86. If + we're seeing double rounding, and we don't have any mechanism available for + changing the FPU rounding precision, then don't use Python/dtoa.c. */ +#if defined(X87_DOUBLE_ROUNDING) && !defined(HAVE_PY_SET_53BIT_PRECISION) +#define PY_NO_SHORT_FLOAT_REPR +#endif + + +/* Py_DEPRECATED(version) + * Declare a variable, type, or function deprecated. + * Usage: + * extern int old_var Py_DEPRECATED(2.3); + * typedef int T1 Py_DEPRECATED(2.4); + * extern int x() Py_DEPRECATED(2.5); + */ +#if defined(__GNUC__) \ + && ((__GNUC__ >= 4) || (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) +#define Py_DEPRECATED(VERSION_UNUSED) __attribute__((__deprecated__)) +#else +#define Py_DEPRECATED(VERSION_UNUSED) +#endif + + +/* _Py_HOT_FUNCTION + * The hot attribute on a function is used to inform the compiler that the + * function is a hot spot of the compiled program. The function is optimized + * more aggressively and on many target it is placed into special subsection of + * the text section so all hot functions appears close together improving + * locality. + * + * Usage: + * int _Py_HOT_FUNCTION x(void) { return 3; } + * + * Issue #28618: This attribute must not be abused, otherwise it can have a + * negative effect on performance. Only the functions were Python spend most of + * its time must use it. Use a profiler when running performance benchmark + * suite to find these functions. + */ +#if defined(__GNUC__) \ + && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) +#define _Py_HOT_FUNCTION __attribute__((hot)) +#else +#define _Py_HOT_FUNCTION +#endif + +/* _Py_NO_INLINE + * Disable inlining on a function. For example, it helps to reduce the C stack + * consumption. + * + * Usage: + * int _Py_NO_INLINE x(void) { return 3; } + */ +#if defined(__GNUC__) || defined(__clang__) +# define _Py_NO_INLINE __attribute__((noinline)) +#else +# define _Py_NO_INLINE +#endif + +/************************************************************************** +Prototypes that are missing from the standard include files on some systems +(and possibly only some versions of such systems.) + +Please be conservative with adding new ones, document them and enclose them +in platform-specific #ifdefs. +**************************************************************************/ + +#ifdef SOLARIS +/* Unchecked */ +extern int gethostname(char *, int); +#endif + +#ifdef HAVE__GETPTY +#include /* we need to import mode_t */ +extern char * _getpty(int *, int, mode_t, int); +#endif + +/* On QNX 6, struct termio must be declared by including sys/termio.h + if TCGETA, TCSETA, TCSETAW, or TCSETAF are used. sys/termio.h must + be included before termios.h or it will generate an error. */ +#if defined(HAVE_SYS_TERMIO_H) && !defined(__hpux) +#include +#endif + + +/* On 4.4BSD-descendants, ctype functions serves the whole range of + * wchar_t character set rather than single byte code points only. + * This characteristic can break some operations of string object + * including str.upper() and str.split() on UTF-8 locales. This + * workaround was provided by Tim Robbins of FreeBSD project. + */ + +#if defined(__APPLE__) +# define _PY_PORT_CTYPE_UTF8_ISSUE +#endif + +#ifdef _PY_PORT_CTYPE_UTF8_ISSUE +#ifndef __cplusplus + /* The workaround below is unsafe in C++ because + * the defines these symbols as real functions, + * with a slightly different signature. + * See issue #10910 + */ +#include +#include +#undef isalnum +#define isalnum(c) iswalnum(btowc(c)) +#undef isalpha +#define isalpha(c) iswalpha(btowc(c)) +#undef islower +#define islower(c) iswlower(btowc(c)) +#undef isspace +#define isspace(c) iswspace(btowc(c)) +#undef isupper +#define isupper(c) iswupper(btowc(c)) +#undef tolower +#define tolower(c) towlower(btowc(c)) +#undef toupper +#define toupper(c) towupper(btowc(c)) +#endif +#endif + + +/* Declarations for symbol visibility. + + PyAPI_FUNC(type): Declares a public Python API function and return type + PyAPI_DATA(type): Declares public Python data and its type + PyMODINIT_FUNC: A Python module init function. If these functions are + inside the Python core, they are private to the core. + If in an extension module, it may be declared with + external linkage depending on the platform. + + As a number of platforms support/require "__declspec(dllimport/dllexport)", + we support a HAVE_DECLSPEC_DLL macro to save duplication. +*/ + +/* + All windows ports, except cygwin, are handled in PC/pyconfig.h. + + Cygwin is the only other autoconf platform requiring special + linkage handling and it uses __declspec(). +*/ +#if defined(__CYGWIN__) +# define HAVE_DECLSPEC_DLL +#endif + +/* only get special linkage if built as shared or platform is Cygwin */ +#if defined(Py_ENABLE_SHARED) || defined(__CYGWIN__) +# if defined(HAVE_DECLSPEC_DLL) +# if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) +# define PyAPI_FUNC(RTYPE) __declspec(dllexport) RTYPE +# define PyAPI_DATA(RTYPE) extern __declspec(dllexport) RTYPE + /* module init functions inside the core need no external linkage */ + /* except for Cygwin to handle embedding */ +# if defined(__CYGWIN__) +# define PyMODINIT_FUNC __declspec(dllexport) PyObject* +# else /* __CYGWIN__ */ +# define PyMODINIT_FUNC PyObject* +# endif /* __CYGWIN__ */ +# else /* Py_BUILD_CORE */ + /* Building an extension module, or an embedded situation */ + /* public Python functions and data are imported */ + /* Under Cygwin, auto-import functions to prevent compilation */ + /* failures similar to those described at the bottom of 4.1: */ + /* http://docs.python.org/extending/windows.html#a-cookbook-approach */ +# if !defined(__CYGWIN__) +# define PyAPI_FUNC(RTYPE) __declspec(dllimport) RTYPE +# endif /* !__CYGWIN__ */ +# define PyAPI_DATA(RTYPE) extern __declspec(dllimport) RTYPE + /* module init functions outside the core must be exported */ +# if defined(__cplusplus) +# define PyMODINIT_FUNC extern "C" __declspec(dllexport) PyObject* +# else /* __cplusplus */ +# define PyMODINIT_FUNC __declspec(dllexport) PyObject* +# endif /* __cplusplus */ +# endif /* Py_BUILD_CORE */ +# endif /* HAVE_DECLSPEC_DLL */ +#endif /* Py_ENABLE_SHARED */ + +/* If no external linkage macros defined by now, create defaults */ +#ifndef PyAPI_FUNC +# define PyAPI_FUNC(RTYPE) RTYPE +#endif +#ifndef PyAPI_DATA +# define PyAPI_DATA(RTYPE) extern RTYPE +#endif +#ifndef PyMODINIT_FUNC +# if defined(__cplusplus) +# define PyMODINIT_FUNC extern "C" PyObject* +# else /* __cplusplus */ +# define PyMODINIT_FUNC PyObject* +# endif /* __cplusplus */ +#endif + +/* limits.h constants that may be missing */ + +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif + +#ifndef LONG_MAX +#if SIZEOF_LONG == 4 +#define LONG_MAX 0X7FFFFFFFL +#elif SIZEOF_LONG == 8 +#define LONG_MAX 0X7FFFFFFFFFFFFFFFL +#else +#error "could not set LONG_MAX in pyport.h" +#endif +#endif + +#ifndef LONG_MIN +#define LONG_MIN (-LONG_MAX-1) +#endif + +#ifndef LONG_BIT +#define LONG_BIT (8 * SIZEOF_LONG) +#endif + +#if LONG_BIT != 8 * SIZEOF_LONG +/* 04-Oct-2000 LONG_BIT is apparently (mis)defined as 64 on some recent + * 32-bit platforms using gcc. We try to catch that here at compile-time + * rather than waiting for integer multiplication to trigger bogus + * overflows. + */ +#error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)." +#endif + +#ifdef __cplusplus +} +#endif + +/* + * Hide GCC attributes from compilers that don't support them. + */ +#if (!defined(__GNUC__) || __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ) +#define Py_GCC_ATTRIBUTE(x) +#else +#define Py_GCC_ATTRIBUTE(x) __attribute__(x) +#endif + +/* + * Specify alignment on compilers that support it. + */ +#if defined(__GNUC__) && __GNUC__ >= 3 +#define Py_ALIGNED(x) __attribute__((aligned(x))) +#else +#define Py_ALIGNED(x) +#endif + +/* Eliminate end-of-loop code not reached warnings from SunPro C + * when using do{...}while(0) macros + */ +#ifdef __SUNPRO_C +#pragma error_messages (off,E_END_OF_LOOP_CODE_NOT_REACHED) +#endif + +#ifndef Py_LL +#define Py_LL(x) x##LL +#endif + +#ifndef Py_ULL +#define Py_ULL(x) Py_LL(x##U) +#endif + +#define Py_VA_COPY va_copy + +/* + * Convenient macros to deal with endianness of the platform. WORDS_BIGENDIAN is + * detected by configure and defined in pyconfig.h. The code in pyconfig.h + * also takes care of Apple's universal builds. + */ + +#ifdef WORDS_BIGENDIAN +#define PY_BIG_ENDIAN 1 +#define PY_LITTLE_ENDIAN 0 +#else +#define PY_BIG_ENDIAN 0 +#define PY_LITTLE_ENDIAN 1 +#endif + +#if defined(Py_BUILD_CORE) || defined(Py_BUILD_CORE_BUILTIN) +/* + * Macros to protect CRT calls against instant termination when passed an + * invalid parameter (issue23524). + */ +#if defined _MSC_VER && _MSC_VER >= 1900 + +extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler; +#define _Py_BEGIN_SUPPRESS_IPH { _invalid_parameter_handler _Py_old_handler = \ + _set_thread_local_invalid_parameter_handler(_Py_silent_invalid_parameter_handler); +#define _Py_END_SUPPRESS_IPH _set_thread_local_invalid_parameter_handler(_Py_old_handler); } + +#else + +#define _Py_BEGIN_SUPPRESS_IPH +#define _Py_END_SUPPRESS_IPH + +#endif /* _MSC_VER >= 1900 */ +#endif /* Py_BUILD_CORE */ + +#ifdef __ANDROID__ +/* The Android langinfo.h header is not used. */ +#undef HAVE_LANGINFO_H +#undef CODESET +#endif + +/* Maximum value of the Windows DWORD type */ +#define PY_DWORD_MAX 4294967295U + +/* This macro used to tell whether Python was built with multithreading + * enabled. Now multithreading is always enabled, but keep the macro + * for compatibility. + */ +#ifndef WITH_THREAD +#define WITH_THREAD +#endif + +#endif /* Py_PYPORT_H */ diff --git a/winvenv/Include/pystate.h b/winvenv/Include/pystate.h new file mode 100644 index 0000000..f16ffb8 --- /dev/null +++ b/winvenv/Include/pystate.h @@ -0,0 +1,455 @@ + +/* Thread and interpreter state structures and their interfaces */ + + +#ifndef Py_PYSTATE_H +#define Py_PYSTATE_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "pythread.h" + +/* This limitation is for performance and simplicity. If needed it can be +removed (with effort). */ +#define MAX_CO_EXTRA_USERS 255 + +/* State shared between threads */ + +struct _ts; /* Forward */ +struct _is; /* Forward */ +struct _frame; /* Forward declaration for PyFrameObject. */ + +#ifdef Py_LIMITED_API +typedef struct _is PyInterpreterState; +#else +typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int); + + +typedef struct { + int install_signal_handlers; /* Install signal handlers? -1 means unset */ + + int ignore_environment; /* -E, Py_IgnoreEnvironmentFlag */ + int use_hash_seed; /* PYTHONHASHSEED=x */ + unsigned long hash_seed; + const char *allocator; /* Memory allocator: _PyMem_SetupAllocators() */ + int dev_mode; /* PYTHONDEVMODE, -X dev */ + int faulthandler; /* PYTHONFAULTHANDLER, -X faulthandler */ + int tracemalloc; /* PYTHONTRACEMALLOC, -X tracemalloc=N */ + int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */ + int show_ref_count; /* -X showrefcount */ + int show_alloc_count; /* -X showalloccount */ + int dump_refs; /* PYTHONDUMPREFS */ + int malloc_stats; /* PYTHONMALLOCSTATS */ + int coerce_c_locale; /* PYTHONCOERCECLOCALE, -1 means unknown */ + int coerce_c_locale_warn; /* PYTHONCOERCECLOCALE=warn */ + int utf8_mode; /* PYTHONUTF8, -X utf8; -1 means unknown */ + + wchar_t *program_name; /* Program name, see also Py_GetProgramName() */ + int argc; /* Number of command line arguments, + -1 means unset */ + wchar_t **argv; /* Command line arguments */ + wchar_t *program; /* argv[0] or "" */ + + int nxoption; /* Number of -X options */ + wchar_t **xoptions; /* -X options */ + + int nwarnoption; /* Number of warnings options */ + wchar_t **warnoptions; /* Warnings options */ + + /* Path configuration inputs */ + wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ + wchar_t *home; /* PYTHONHOME environment variable, + see also Py_SetPythonHome(). */ + + /* Path configuration outputs */ + int nmodule_search_path; /* Number of sys.path paths, + -1 means unset */ + wchar_t **module_search_paths; /* sys.path paths */ + wchar_t *executable; /* sys.executable */ + wchar_t *prefix; /* sys.prefix */ + wchar_t *base_prefix; /* sys.base_prefix */ + wchar_t *exec_prefix; /* sys.exec_prefix */ + wchar_t *base_exec_prefix; /* sys.base_exec_prefix */ + + /* Private fields */ + int _disable_importlib; /* Needed by freeze_importlib */ +} _PyCoreConfig; + +#define _PyCoreConfig_INIT \ + (_PyCoreConfig){ \ + .install_signal_handlers = -1, \ + .ignore_environment = -1, \ + .use_hash_seed = -1, \ + .coerce_c_locale = -1, \ + .faulthandler = -1, \ + .tracemalloc = -1, \ + .utf8_mode = -1, \ + .argc = -1, \ + .nmodule_search_path = -1} +/* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ + +/* Placeholders while working on the new configuration API + * + * See PEP 432 for final anticipated contents + */ +typedef struct { + int install_signal_handlers; /* Install signal handlers? -1 means unset */ + PyObject *argv; /* sys.argv list, can be NULL */ + PyObject *executable; /* sys.executable str */ + PyObject *prefix; /* sys.prefix str */ + PyObject *base_prefix; /* sys.base_prefix str, can be NULL */ + PyObject *exec_prefix; /* sys.exec_prefix str */ + PyObject *base_exec_prefix; /* sys.base_exec_prefix str, can be NULL */ + PyObject *warnoptions; /* sys.warnoptions list, can be NULL */ + PyObject *xoptions; /* sys._xoptions dict, can be NULL */ + PyObject *module_search_path; /* sys.path list */ +} _PyMainInterpreterConfig; + +#define _PyMainInterpreterConfig_INIT \ + (_PyMainInterpreterConfig){.install_signal_handlers = -1} +/* Note: _PyMainInterpreterConfig_INIT sets other fields to 0/NULL */ + +typedef struct _is { + + struct _is *next; + struct _ts *tstate_head; + + int64_t id; + int64_t id_refcount; + PyThread_type_lock id_mutex; + + PyObject *modules; + PyObject *modules_by_index; + PyObject *sysdict; + PyObject *builtins; + PyObject *importlib; + + /* Used in Python/sysmodule.c. */ + int check_interval; + + /* Used in Modules/_threadmodule.c. */ + long num_threads; + /* Support for runtime thread stack size tuning. + A value of 0 means using the platform's default stack size + or the size specified by the THREAD_STACK_SIZE macro. */ + /* Used in Python/thread.c. */ + size_t pythread_stacksize; + + PyObject *codec_search_path; + PyObject *codec_search_cache; + PyObject *codec_error_registry; + int codecs_initialized; + int fscodec_initialized; + + _PyCoreConfig core_config; + _PyMainInterpreterConfig config; +#ifdef HAVE_DLOPEN + int dlopenflags; +#endif + + PyObject *builtins_copy; + PyObject *import_func; + /* Initialized to PyEval_EvalFrameDefault(). */ + _PyFrameEvalFunction eval_frame; + + Py_ssize_t co_extra_user_count; + freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS]; + +#ifdef HAVE_FORK + PyObject *before_forkers; + PyObject *after_forkers_parent; + PyObject *after_forkers_child; +#endif + /* AtExit module */ + void (*pyexitfunc)(PyObject *); + PyObject *pyexitmodule; + + uint64_t tstate_next_unique_id; +} PyInterpreterState; +#endif /* !Py_LIMITED_API */ + + +/* State unique per thread */ + +#ifndef Py_LIMITED_API +/* Py_tracefunc return -1 when raising an exception, or 0 for success. */ +typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *); + +/* The following values are used for 'what' for tracefunc functions + * + * To add a new kind of trace event, also update "trace_init" in + * Python/sysmodule.c to define the Python level event name + */ +#define PyTrace_CALL 0 +#define PyTrace_EXCEPTION 1 +#define PyTrace_LINE 2 +#define PyTrace_RETURN 3 +#define PyTrace_C_CALL 4 +#define PyTrace_C_EXCEPTION 5 +#define PyTrace_C_RETURN 6 +#define PyTrace_OPCODE 7 +#endif /* Py_LIMITED_API */ + +#ifdef Py_LIMITED_API +typedef struct _ts PyThreadState; +#else + +typedef struct _err_stackitem { + /* This struct represents an entry on the exception stack, which is a + * per-coroutine state. (Coroutine in the computer science sense, + * including the thread and generators). + * This ensures that the exception state is not impacted by "yields" + * from an except handler. + */ + PyObject *exc_type, *exc_value, *exc_traceback; + + struct _err_stackitem *previous_item; + +} _PyErr_StackItem; + + +typedef struct _ts { + /* See Python/ceval.c for comments explaining most fields */ + + struct _ts *prev; + struct _ts *next; + PyInterpreterState *interp; + + struct _frame *frame; + int recursion_depth; + char overflowed; /* The stack has overflowed. Allow 50 more calls + to handle the runtime error. */ + char recursion_critical; /* The current calls must not cause + a stack overflow. */ + int stackcheck_counter; + + /* 'tracing' keeps track of the execution depth when tracing/profiling. + This is to prevent the actual trace/profile code from being recorded in + the trace/profile. */ + int tracing; + int use_tracing; + + Py_tracefunc c_profilefunc; + Py_tracefunc c_tracefunc; + PyObject *c_profileobj; + PyObject *c_traceobj; + + /* The exception currently being raised */ + PyObject *curexc_type; + PyObject *curexc_value; + PyObject *curexc_traceback; + + /* The exception currently being handled, if no coroutines/generators + * are present. Always last element on the stack referred to be exc_info. + */ + _PyErr_StackItem exc_state; + + /* Pointer to the top of the stack of the exceptions currently + * being handled */ + _PyErr_StackItem *exc_info; + + PyObject *dict; /* Stores per-thread state */ + + int gilstate_counter; + + PyObject *async_exc; /* Asynchronous exception to raise */ + unsigned long thread_id; /* Thread id where this tstate was created */ + + int trash_delete_nesting; + PyObject *trash_delete_later; + + /* Called when a thread state is deleted normally, but not when it + * is destroyed after fork(). + * Pain: to prevent rare but fatal shutdown errors (issue 18808), + * Thread.join() must wait for the join'ed thread's tstate to be unlinked + * from the tstate chain. That happens at the end of a thread's life, + * in pystate.c. + * The obvious way doesn't quite work: create a lock which the tstate + * unlinking code releases, and have Thread.join() wait to acquire that + * lock. The problem is that we _are_ at the end of the thread's life: + * if the thread holds the last reference to the lock, decref'ing the + * lock will delete the lock, and that may trigger arbitrary Python code + * if there's a weakref, with a callback, to the lock. But by this time + * _PyThreadState_Current is already NULL, so only the simplest of C code + * can be allowed to run (in particular it must not be possible to + * release the GIL). + * So instead of holding the lock directly, the tstate holds a weakref to + * the lock: that's the value of on_delete_data below. Decref'ing a + * weakref is harmless. + * on_delete points to _threadmodule.c's static release_sentinel() function. + * After the tstate is unlinked, release_sentinel is called with the + * weakref-to-lock (on_delete_data) argument, and release_sentinel releases + * the indirectly held lock. + */ + void (*on_delete)(void *); + void *on_delete_data; + + int coroutine_origin_tracking_depth; + + PyObject *coroutine_wrapper; + int in_coroutine_wrapper; + + PyObject *async_gen_firstiter; + PyObject *async_gen_finalizer; + + PyObject *context; + uint64_t context_ver; + + /* Unique thread state id. */ + uint64_t id; + + /* XXX signal handlers should also be here */ + +} PyThreadState; +#endif /* !Py_LIMITED_API */ + + +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); +PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *); +PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 +/* New in 3.7 */ +PyAPI_FUNC(int64_t) PyInterpreterState_GetID(PyInterpreterState *); +#endif +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); +#endif /* !Py_LIMITED_API */ +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* New in 3.3 */ +PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*); +PyAPI_FUNC(int) PyState_RemoveModule(struct PyModuleDef*); +#endif +PyAPI_FUNC(PyObject*) PyState_FindModule(struct PyModuleDef*); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyState_ClearModules(void); +#endif + +PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); +PyAPI_FUNC(void) _PyThreadState_Init(PyThreadState *); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(void) PyThreadState_Clear(PyThreadState *); +PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate); +#endif /* !Py_LIMITED_API */ +PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyGILState_Reinit(void); +#endif /* !Py_LIMITED_API */ + +/* Return the current thread state. The global interpreter lock must be held. + * When the current thread state is NULL, this issues a fatal error (so that + * the caller needn't check for NULL). */ +PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void); + +#ifndef Py_LIMITED_API +/* Similar to PyThreadState_Get(), but don't issue a fatal error + * if it is NULL. */ +PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void); +#endif /* !Py_LIMITED_API */ + +PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *); +PyAPI_FUNC(PyObject *) PyThreadState_GetDict(void); +PyAPI_FUNC(int) PyThreadState_SetAsyncExc(unsigned long, PyObject *); + + +/* Variable and macro for in-line access to current thread state */ + +/* Assuming the current thread holds the GIL, this is the + PyThreadState for the current thread. */ +#ifdef Py_BUILD_CORE +# define _PyThreadState_Current _PyRuntime.gilstate.tstate_current +# define PyThreadState_GET() \ + ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) +#else +# define PyThreadState_GET() PyThreadState_Get() +#endif + +typedef + enum {PyGILState_LOCKED, PyGILState_UNLOCKED} + PyGILState_STATE; + + +/* Ensure that the current thread is ready to call the Python + C API, regardless of the current state of Python, or of its + thread lock. This may be called as many times as desired + by a thread so long as each call is matched with a call to + PyGILState_Release(). In general, other thread-state APIs may + be used between _Ensure() and _Release() calls, so long as the + thread-state is restored to its previous state before the Release(). + For example, normal use of the Py_BEGIN_ALLOW_THREADS/ + Py_END_ALLOW_THREADS macros are acceptable. + + The return value is an opaque "handle" to the thread state when + PyGILState_Ensure() was called, and must be passed to + PyGILState_Release() to ensure Python is left in the same state. Even + though recursive calls are allowed, these handles can *not* be shared - + each unique call to PyGILState_Ensure must save the handle for its + call to PyGILState_Release. + + When the function returns, the current thread will hold the GIL. + + Failure is a fatal error. +*/ +PyAPI_FUNC(PyGILState_STATE) PyGILState_Ensure(void); + +/* Release any resources previously acquired. After this call, Python's + state will be the same as it was prior to the corresponding + PyGILState_Ensure() call (but generally this state will be unknown to + the caller, hence the use of the GILState API.) + + Every call to PyGILState_Ensure must be matched by a call to + PyGILState_Release on the same thread. +*/ +PyAPI_FUNC(void) PyGILState_Release(PyGILState_STATE); + +/* Helper/diagnostic function - get the current thread state for + this thread. May return NULL if no GILState API has been used + on the current thread. Note that the main thread always has such a + thread-state, even if no auto-thread-state call has been made + on the main thread. +*/ +PyAPI_FUNC(PyThreadState *) PyGILState_GetThisThreadState(void); + +#ifndef Py_LIMITED_API +/* Helper/diagnostic function - return 1 if the current thread + currently holds the GIL, 0 otherwise. + + The function returns 1 if _PyGILState_check_enabled is non-zero. */ +PyAPI_FUNC(int) PyGILState_Check(void); + +/* Unsafe function to get the single PyInterpreterState used by this process' + GILState implementation. + + Return NULL before _PyGILState_Init() is called and after _PyGILState_Fini() + is called. */ +PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void); +#endif /* !Py_LIMITED_API */ + + +/* The implementation of sys._current_frames() Returns a dict mapping + thread id to that thread's current frame. +*/ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyThread_CurrentFrames(void); +#endif + +/* Routines for advanced debuggers, requested by David Beazley. + Don't use unless you know what you are doing! */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Main(void); +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Head(void); +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Next(PyInterpreterState *); +PyAPI_FUNC(PyThreadState *) PyInterpreterState_ThreadHead(PyInterpreterState *); +PyAPI_FUNC(PyThreadState *) PyThreadState_Next(PyThreadState *); + +typedef struct _frame *(*PyThreadFrameGetter)(PyThreadState *self_); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PYSTATE_H */ diff --git a/winvenv/Include/pystrcmp.h b/winvenv/Include/pystrcmp.h new file mode 100644 index 0000000..edb1239 --- /dev/null +++ b/winvenv/Include/pystrcmp.h @@ -0,0 +1,23 @@ +#ifndef Py_STRCMP_H +#define Py_STRCMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(int) PyOS_mystrnicmp(const char *, const char *, Py_ssize_t); +PyAPI_FUNC(int) PyOS_mystricmp(const char *, const char *); + +#ifdef MS_WINDOWS +#define PyOS_strnicmp strnicmp +#define PyOS_stricmp stricmp +#else +#define PyOS_strnicmp PyOS_mystrnicmp +#define PyOS_stricmp PyOS_mystricmp +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_STRCMP_H */ diff --git a/winvenv/Include/pystrhex.h b/winvenv/Include/pystrhex.h new file mode 100644 index 0000000..66a30e2 --- /dev/null +++ b/winvenv/Include/pystrhex.h @@ -0,0 +1,19 @@ +#ifndef Py_STRHEX_H +#define Py_STRHEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +/* Returns a str() containing the hex representation of argbuf. */ +PyAPI_FUNC(PyObject*) _Py_strhex(const char* argbuf, const Py_ssize_t arglen); +/* Returns a bytes() containing the ASCII hex representation of argbuf. */ +PyAPI_FUNC(PyObject*) _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen); +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_STRHEX_H */ diff --git a/winvenv/Include/pystrtod.h b/winvenv/Include/pystrtod.h new file mode 100644 index 0000000..c1e84de --- /dev/null +++ b/winvenv/Include/pystrtod.h @@ -0,0 +1,45 @@ +#ifndef Py_STRTOD_H +#define Py_STRTOD_H + +#ifdef __cplusplus +extern "C" { +#endif + + +PyAPI_FUNC(double) PyOS_string_to_double(const char *str, + char **endptr, + PyObject *overflow_exception); + +/* The caller is responsible for calling PyMem_Free to free the buffer + that's is returned. */ +PyAPI_FUNC(char *) PyOS_double_to_string(double val, + char format_code, + int precision, + int flags, + int *type); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _Py_string_to_number_with_underscores( + const char *str, Py_ssize_t len, const char *what, PyObject *obj, void *arg, + PyObject *(*innerfunc)(const char *, Py_ssize_t, void *)); + +PyAPI_FUNC(double) _Py_parse_inf_or_nan(const char *p, char **endptr); +#endif + + +/* PyOS_double_to_string's "flags" parameter can be set to 0 or more of: */ +#define Py_DTSF_SIGN 0x01 /* always add the sign */ +#define Py_DTSF_ADD_DOT_0 0x02 /* if the result is an integer add ".0" */ +#define Py_DTSF_ALT 0x04 /* "alternate" formatting. it's format_code + specific */ + +/* PyOS_double_to_string's "type", if non-NULL, will be set to one of: */ +#define Py_DTST_FINITE 0 +#define Py_DTST_INFINITE 1 +#define Py_DTST_NAN 2 + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_STRTOD_H */ diff --git a/winvenv/Include/pythonrun.h b/winvenv/Include/pythonrun.h new file mode 100644 index 0000000..6f0c6fc --- /dev/null +++ b/winvenv/Include/pythonrun.h @@ -0,0 +1,181 @@ + +/* Interfaces to parse and execute pieces of python code */ + +#ifndef Py_PYTHONRUN_H +#define Py_PYTHONRUN_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *); +PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *); +PyAPI_FUNC(int) PyRun_AnyFileExFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + int closeit, + PyCompilerFlags *flags); +PyAPI_FUNC(int) PyRun_SimpleFileExFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + int closeit, + PyCompilerFlags *flags); +PyAPI_FUNC(int) PyRun_InteractiveOneFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + PyCompilerFlags *flags); +PyAPI_FUNC(int) PyRun_InteractiveOneObject( + FILE *fp, + PyObject *filename, + PyCompilerFlags *flags); +PyAPI_FUNC(int) PyRun_InteractiveLoopFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + PyCompilerFlags *flags); + +PyAPI_FUNC(struct _mod *) PyParser_ASTFromString( + const char *s, + const char *filename, /* decoded from the filesystem encoding */ + int start, + PyCompilerFlags *flags, + PyArena *arena); +PyAPI_FUNC(struct _mod *) PyParser_ASTFromStringObject( + const char *s, + PyObject *filename, + int start, + PyCompilerFlags *flags, + PyArena *arena); +PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + const char* enc, + int start, + const char *ps1, + const char *ps2, + PyCompilerFlags *flags, + int *errcode, + PyArena *arena); +PyAPI_FUNC(struct _mod *) PyParser_ASTFromFileObject( + FILE *fp, + PyObject *filename, + const char* enc, + int start, + const char *ps1, + const char *ps2, + PyCompilerFlags *flags, + int *errcode, + PyArena *arena); +#endif + +#ifndef PyParser_SimpleParseString +#define PyParser_SimpleParseString(S, B) \ + PyParser_SimpleParseStringFlags(S, B, 0) +#define PyParser_SimpleParseFile(FP, S, B) \ + PyParser_SimpleParseFileFlags(FP, S, B, 0) +#endif +PyAPI_FUNC(struct _node *) PyParser_SimpleParseStringFlags(const char *, int, + int); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(struct _node *) PyParser_SimpleParseStringFlagsFilename(const char *, + const char *, + int, int); +#endif +PyAPI_FUNC(struct _node *) PyParser_SimpleParseFileFlags(FILE *, const char *, + int, int); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyRun_StringFlags(const char *, int, PyObject *, + PyObject *, PyCompilerFlags *); + +PyAPI_FUNC(PyObject *) PyRun_FileExFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + int start, + PyObject *globals, + PyObject *locals, + int closeit, + PyCompilerFlags *flags); +#endif + +#ifdef Py_LIMITED_API +PyAPI_FUNC(PyObject *) Py_CompileString(const char *, const char *, int); +#else +#define Py_CompileString(str, p, s) Py_CompileStringExFlags(str, p, s, NULL, -1) +#define Py_CompileStringFlags(str, p, s, f) Py_CompileStringExFlags(str, p, s, f, -1) +PyAPI_FUNC(PyObject *) Py_CompileStringExFlags( + const char *str, + const char *filename, /* decoded from the filesystem encoding */ + int start, + PyCompilerFlags *flags, + int optimize); +PyAPI_FUNC(PyObject *) Py_CompileStringObject( + const char *str, + PyObject *filename, int start, + PyCompilerFlags *flags, + int optimize); +#endif +PyAPI_FUNC(struct symtable *) Py_SymtableString( + const char *str, + const char *filename, /* decoded from the filesystem encoding */ + int start); +#ifndef Py_LIMITED_API +PyAPI_FUNC(struct symtable *) Py_SymtableStringObject( + const char *str, + PyObject *filename, + int start); +#endif + +PyAPI_FUNC(void) PyErr_Print(void); +PyAPI_FUNC(void) PyErr_PrintEx(int); +PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *); + +#ifndef Py_LIMITED_API +/* Use macros for a bunch of old variants */ +#define PyRun_String(str, s, g, l) PyRun_StringFlags(str, s, g, l, NULL) +#define PyRun_AnyFile(fp, name) PyRun_AnyFileExFlags(fp, name, 0, NULL) +#define PyRun_AnyFileEx(fp, name, closeit) \ + PyRun_AnyFileExFlags(fp, name, closeit, NULL) +#define PyRun_AnyFileFlags(fp, name, flags) \ + PyRun_AnyFileExFlags(fp, name, 0, flags) +#define PyRun_SimpleString(s) PyRun_SimpleStringFlags(s, NULL) +#define PyRun_SimpleFile(f, p) PyRun_SimpleFileExFlags(f, p, 0, NULL) +#define PyRun_SimpleFileEx(f, p, c) PyRun_SimpleFileExFlags(f, p, c, NULL) +#define PyRun_InteractiveOne(f, p) PyRun_InteractiveOneFlags(f, p, NULL) +#define PyRun_InteractiveLoop(f, p) PyRun_InteractiveLoopFlags(f, p, NULL) +#define PyRun_File(fp, p, s, g, l) \ + PyRun_FileExFlags(fp, p, s, g, l, 0, NULL) +#define PyRun_FileEx(fp, p, s, g, l, c) \ + PyRun_FileExFlags(fp, p, s, g, l, c, NULL) +#define PyRun_FileFlags(fp, p, s, g, l, flags) \ + PyRun_FileExFlags(fp, p, s, g, l, 0, flags) +#endif + +/* Stuff with no proper home (yet) */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, const char *); +#endif +PyAPI_DATA(int) (*PyOS_InputHook)(void); +PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, const char *); +#ifndef Py_LIMITED_API +PyAPI_DATA(PyThreadState*) _PyOS_ReadlineTState; +#endif + +/* Stack size, in "pointers" (so we get extra safety margins + on 64-bit platforms). On a 32-bit platform, this translates + to an 8k margin. */ +#define PYOS_STACK_MARGIN 2048 + +#if defined(WIN32) && !defined(MS_WIN64) && defined(_MSC_VER) && _MSC_VER >= 1300 +/* Enable stack checking under Microsoft C */ +#define USE_STACKCHECK +#endif + +#ifdef USE_STACKCHECK +/* Check that we aren't overflowing our stack */ +PyAPI_FUNC(int) PyOS_CheckStack(void); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_PYTHONRUN_H */ diff --git a/winvenv/Include/pythread.h b/winvenv/Include/pythread.h new file mode 100644 index 0000000..eb61033 --- /dev/null +++ b/winvenv/Include/pythread.h @@ -0,0 +1,155 @@ + +#ifndef Py_PYTHREAD_H +#define Py_PYTHREAD_H + +typedef void *PyThread_type_lock; +typedef void *PyThread_type_sema; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return status codes for Python lock acquisition. Chosen for maximum + * backwards compatibility, ie failure -> 0, success -> 1. */ +typedef enum PyLockStatus { + PY_LOCK_FAILURE = 0, + PY_LOCK_ACQUIRED = 1, + PY_LOCK_INTR +} PyLockStatus; + +#ifndef Py_LIMITED_API +#define PYTHREAD_INVALID_THREAD_ID ((unsigned long)-1) +#endif + +PyAPI_FUNC(void) PyThread_init_thread(void); +PyAPI_FUNC(unsigned long) PyThread_start_new_thread(void (*)(void *), void *); +PyAPI_FUNC(void) PyThread_exit_thread(void); +PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void); + +PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void); +PyAPI_FUNC(void) PyThread_free_lock(PyThread_type_lock); +PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int); +#define WAIT_LOCK 1 +#define NOWAIT_LOCK 0 + +/* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting + on a lock (see PyThread_acquire_lock_timed() below). + PY_TIMEOUT_MAX is the highest usable value (in microseconds) of that + type, and depends on the system threading API. + + NOTE: this isn't the same value as `_thread.TIMEOUT_MAX`. The _thread + module exposes a higher-level API, with timeouts expressed in seconds + and floating-point numbers allowed. +*/ +#define PY_TIMEOUT_T long long + +#if defined(_POSIX_THREADS) + /* PyThread_acquire_lock_timed() uses _PyTime_FromNanoseconds(us * 1000), + convert microseconds to nanoseconds. */ +# define PY_TIMEOUT_MAX (PY_LLONG_MAX / 1000) +#elif defined (NT_THREADS) + /* In the NT API, the timeout is a DWORD and is expressed in milliseconds */ +# if 0xFFFFFFFFLL * 1000 < PY_LLONG_MAX +# define PY_TIMEOUT_MAX (0xFFFFFFFFLL * 1000) +# else +# define PY_TIMEOUT_MAX PY_LLONG_MAX +# endif +#else +# define PY_TIMEOUT_MAX PY_LLONG_MAX +#endif + + +/* If microseconds == 0, the call is non-blocking: it returns immediately + even when the lock can't be acquired. + If microseconds > 0, the call waits up to the specified duration. + If microseconds < 0, the call waits until success (or abnormal failure) + + microseconds must be less than PY_TIMEOUT_MAX. Behaviour otherwise is + undefined. + + If intr_flag is true and the acquire is interrupted by a signal, then the + call will return PY_LOCK_INTR. The caller may reattempt to acquire the + lock. +*/ +PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed(PyThread_type_lock, + PY_TIMEOUT_T microseconds, + int intr_flag); + +PyAPI_FUNC(void) PyThread_release_lock(PyThread_type_lock); + +PyAPI_FUNC(size_t) PyThread_get_stacksize(void); +PyAPI_FUNC(int) PyThread_set_stacksize(size_t); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject*) PyThread_GetInfo(void); +#endif + + +/* Thread Local Storage (TLS) API + TLS API is DEPRECATED. Use Thread Specific Storage (TSS) API. + + The existing TLS API has used int to represent TLS keys across all + platforms, but it is not POSIX-compliant. Therefore, the new TSS API uses + opaque data type to represent TSS keys to be compatible (see PEP 539). +*/ +PyAPI_FUNC(int) PyThread_create_key(void) Py_DEPRECATED(3.7); +PyAPI_FUNC(void) PyThread_delete_key(int key) Py_DEPRECATED(3.7); +PyAPI_FUNC(int) PyThread_set_key_value(int key, void *value) Py_DEPRECATED(3.7); +PyAPI_FUNC(void *) PyThread_get_key_value(int key) Py_DEPRECATED(3.7); +PyAPI_FUNC(void) PyThread_delete_key_value(int key) Py_DEPRECATED(3.7); + +/* Cleanup after a fork */ +PyAPI_FUNC(void) PyThread_ReInitTLS(void) Py_DEPRECATED(3.7); + + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 +/* New in 3.7 */ +/* Thread Specific Storage (TSS) API */ + +typedef struct _Py_tss_t Py_tss_t; /* opaque */ + +#ifndef Py_LIMITED_API +#if defined(_POSIX_THREADS) + /* Darwin needs pthread.h to know type name the pthread_key_t. */ +# include +# define NATIVE_TSS_KEY_T pthread_key_t +#elif defined(NT_THREADS) + /* In Windows, native TSS key type is DWORD, + but hardcode the unsigned long to avoid errors for include directive. + */ +# define NATIVE_TSS_KEY_T unsigned long +#else +# error "Require native threads. See https://bugs.python.org/issue31370" +#endif + +/* When Py_LIMITED_API is not defined, the type layout of Py_tss_t is + exposed to allow static allocation in the API clients. Even in this case, + you must handle TSS keys through API functions due to compatibility. +*/ +struct _Py_tss_t { + int _is_initialized; + NATIVE_TSS_KEY_T _key; +}; + +#undef NATIVE_TSS_KEY_T + +/* When static allocation, you must initialize with Py_tss_NEEDS_INIT. */ +#define Py_tss_NEEDS_INIT {0} +#endif /* !Py_LIMITED_API */ + +PyAPI_FUNC(Py_tss_t *) PyThread_tss_alloc(void); +PyAPI_FUNC(void) PyThread_tss_free(Py_tss_t *key); + +/* The parameter key must not be NULL. */ +PyAPI_FUNC(int) PyThread_tss_is_created(Py_tss_t *key); +PyAPI_FUNC(int) PyThread_tss_create(Py_tss_t *key); +PyAPI_FUNC(void) PyThread_tss_delete(Py_tss_t *key); +PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t *key, void *value); +PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t *key); +#endif /* New in 3.7 */ + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_PYTHREAD_H */ diff --git a/winvenv/Include/pytime.h b/winvenv/Include/pytime.h new file mode 100644 index 0000000..4870a9d --- /dev/null +++ b/winvenv/Include/pytime.h @@ -0,0 +1,246 @@ +#ifndef Py_LIMITED_API +#ifndef Py_PYTIME_H +#define Py_PYTIME_H + +#include "pyconfig.h" /* include for defines */ +#include "object.h" + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to time related +functions and constants +**************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/* _PyTime_t: Python timestamp with subsecond precision. It can be used to + store a duration, and so indirectly a date (related to another date, like + UNIX epoch). */ +typedef int64_t _PyTime_t; +#define _PyTime_MIN PY_LLONG_MIN +#define _PyTime_MAX PY_LLONG_MAX + +typedef enum { + /* Round towards minus infinity (-inf). + For example, used to read a clock. */ + _PyTime_ROUND_FLOOR=0, + /* Round towards infinity (+inf). + For example, used for timeout to wait "at least" N seconds. */ + _PyTime_ROUND_CEILING=1, + /* Round to nearest with ties going to nearest even integer. + For example, used to round from a Python float. */ + _PyTime_ROUND_HALF_EVEN=2, + /* Round away from zero + For example, used for timeout. _PyTime_ROUND_CEILING rounds + -1e-9 to 0 milliseconds which causes bpo-31786 issue. + _PyTime_ROUND_UP rounds -1e-9 to -1 millisecond which keeps + the timeout sign as expected. select.poll(timeout) must block + for negative values." */ + _PyTime_ROUND_UP=3, + /* _PyTime_ROUND_TIMEOUT (an alias for _PyTime_ROUND_UP) should be + used for timeouts. */ + _PyTime_ROUND_TIMEOUT = _PyTime_ROUND_UP +} _PyTime_round_t; + + +/* Convert a time_t to a PyLong. */ +PyAPI_FUNC(PyObject *) _PyLong_FromTime_t( + time_t sec); + +/* Convert a PyLong to a time_t. */ +PyAPI_FUNC(time_t) _PyLong_AsTime_t( + PyObject *obj); + +/* Convert a number of seconds, int or float, to time_t. */ +PyAPI_FUNC(int) _PyTime_ObjectToTime_t( + PyObject *obj, + time_t *sec, + _PyTime_round_t); + +/* Convert a number of seconds, int or float, to a timeval structure. + usec is in the range [0; 999999] and rounded towards zero. + For example, -1.2 is converted to (-2, 800000). */ +PyAPI_FUNC(int) _PyTime_ObjectToTimeval( + PyObject *obj, + time_t *sec, + long *usec, + _PyTime_round_t); + +/* Convert a number of seconds, int or float, to a timespec structure. + nsec is in the range [0; 999999999] and rounded towards zero. + For example, -1.2 is converted to (-2, 800000000). */ +PyAPI_FUNC(int) _PyTime_ObjectToTimespec( + PyObject *obj, + time_t *sec, + long *nsec, + _PyTime_round_t); + + +/* Create a timestamp from a number of seconds. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds); + +/* Macro to create a timestamp from a number of seconds, no integer overflow. + Only use the macro for small values, prefer _PyTime_FromSeconds(). */ +#define _PYTIME_FROMSECONDS(seconds) \ + ((_PyTime_t)(seconds) * (1000 * 1000 * 1000)) + +/* Create a timestamp from a number of nanoseconds. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns); + +/* Create a timestamp from nanoseconds (Python int). */ +PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t, + PyObject *obj); + +/* Convert a number of seconds (Python float or int) to a timetamp. + Raise an exception and return -1 on error, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromSecondsObject(_PyTime_t *t, + PyObject *obj, + _PyTime_round_t round); + +/* Convert a number of milliseconds (Python float or int, 10^-3) to a timetamp. + Raise an exception and return -1 on error, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromMillisecondsObject(_PyTime_t *t, + PyObject *obj, + _PyTime_round_t round); + +/* Convert a timestamp to a number of seconds as a C double. */ +PyAPI_FUNC(double) _PyTime_AsSecondsDouble(_PyTime_t t); + +/* Convert timestamp to a number of milliseconds (10^-3 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t, + _PyTime_round_t round); + +/* Convert timestamp to a number of microseconds (10^-6 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, + _PyTime_round_t round); + +/* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int + object. */ +PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t); + +/* Create a timestamp from a timeval structure. + Raise an exception and return -1 on overflow, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv); + +/* Convert a timestamp to a timeval structure (microsecond resolution). + tv_usec is always positive. + Raise an exception and return -1 if the conversion overflowed, + return 0 on success. */ +PyAPI_FUNC(int) _PyTime_AsTimeval(_PyTime_t t, + struct timeval *tv, + _PyTime_round_t round); + +/* Similar to _PyTime_AsTimeval(), but don't raise an exception on error. */ +PyAPI_FUNC(int) _PyTime_AsTimeval_noraise(_PyTime_t t, + struct timeval *tv, + _PyTime_round_t round); + +/* Convert a timestamp to a number of seconds (secs) and microseconds (us). + us is always positive. This function is similar to _PyTime_AsTimeval() + except that secs is always a time_t type, whereas the timeval structure + uses a C long for tv_sec on Windows. + Raise an exception and return -1 if the conversion overflowed, + return 0 on success. */ +PyAPI_FUNC(int) _PyTime_AsTimevalTime_t( + _PyTime_t t, + time_t *secs, + int *us, + _PyTime_round_t round); + +#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) +/* Create a timestamp from a timespec structure. + Raise an exception and return -1 on overflow, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts); + +/* Convert a timestamp to a timespec structure (nanosecond resolution). + tv_nsec is always positive. + Raise an exception and return -1 on error, return 0 on success. */ +PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts); +#endif + +/* Compute ticks * mul / div. + The caller must ensure that ((div - 1) * mul) cannot overflow. */ +PyAPI_FUNC(_PyTime_t) _PyTime_MulDiv(_PyTime_t ticks, + _PyTime_t mul, + _PyTime_t div); + +/* Get the current time from the system clock. + + The function cannot fail. _PyTime_Init() ensures that the system clock + works. */ +PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void); + +/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards. + The clock is not affected by system clock updates. The reference point of + the returned value is undefined, so that only the difference between the + results of consecutive calls is valid. + + The function cannot fail. _PyTime_Init() ensures that a monotonic clock + is available and works. */ +PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void); + + +/* Structure used by time.get_clock_info() */ +typedef struct { + const char *implementation; + int monotonic; + int adjustable; + double resolution; +} _Py_clock_info_t; + +/* Get the current time from the system clock. + * Fill clock information if info is not NULL. + * Raise an exception and return -1 on error, return 0 on success. + */ +PyAPI_FUNC(int) _PyTime_GetSystemClockWithInfo( + _PyTime_t *t, + _Py_clock_info_t *info); + +/* Get the time of a monotonic clock, i.e. a clock that cannot go backwards. + The clock is not affected by system clock updates. The reference point of + the returned value is undefined, so that only the difference between the + results of consecutive calls is valid. + + Fill info (if set) with information of the function used to get the time. + + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_GetMonotonicClockWithInfo( + _PyTime_t *t, + _Py_clock_info_t *info); + + +/* Initialize time. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_Init(void); + +/* Converts a timestamp to the Gregorian time, using the local time zone. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_localtime(time_t t, struct tm *tm); + +/* Converts a timestamp to the Gregorian time, assuming UTC. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm); + +/* Get the performance counter: clock with the highest available resolution to + measure a short duration. + + The function cannot fail. _PyTime_Init() ensures that the system clock + works. */ +PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void); + +/* Get the performance counter: clock with the highest available resolution to + measure a short duration. + + Fill info (if set) with information of the function used to get the time. + + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) _PyTime_GetPerfCounterWithInfo( + _PyTime_t *t, + _Py_clock_info_t *info); + +#ifdef __cplusplus +} +#endif + +#endif /* Py_PYTIME_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/rangeobject.h b/winvenv/Include/rangeobject.h new file mode 100644 index 0000000..7e4dc28 --- /dev/null +++ b/winvenv/Include/rangeobject.h @@ -0,0 +1,27 @@ + +/* Range object interface */ + +#ifndef Py_RANGEOBJECT_H +#define Py_RANGEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* +A range object represents an integer range. This is an immutable object; +a range cannot change its value after creation. + +Range objects behave like the corresponding tuple objects except that +they are represented by a start, stop, and step datamembers. +*/ + +PyAPI_DATA(PyTypeObject) PyRange_Type; +PyAPI_DATA(PyTypeObject) PyRangeIter_Type; +PyAPI_DATA(PyTypeObject) PyLongRangeIter_Type; + +#define PyRange_Check(op) (Py_TYPE(op) == &PyRange_Type) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_RANGEOBJECT_H */ diff --git a/winvenv/Include/setobject.h b/winvenv/Include/setobject.h new file mode 100644 index 0000000..fc0ea83 --- /dev/null +++ b/winvenv/Include/setobject.h @@ -0,0 +1,108 @@ +/* Set object interface */ + +#ifndef Py_SETOBJECT_H +#define Py_SETOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API + +/* There are three kinds of entries in the table: + +1. Unused: key == NULL and hash == 0 +2. Dummy: key == dummy and hash == -1 +3. Active: key != NULL and key != dummy and hash != -1 + +The hash field of Unused slots is always zero. + +The hash field of Dummy slots are set to -1 +meaning that dummy entries can be detected by +either entry->key==dummy or by entry->hash==-1. +*/ + +#define PySet_MINSIZE 8 + +typedef struct { + PyObject *key; + Py_hash_t hash; /* Cached hash code of the key */ +} setentry; + +/* The SetObject data structure is shared by set and frozenset objects. + +Invariant for sets: + - hash is -1 + +Invariants for frozensets: + - data is immutable. + - hash is the hash of the frozenset or -1 if not computed yet. + +*/ + +typedef struct { + PyObject_HEAD + + Py_ssize_t fill; /* Number active and dummy entries*/ + Py_ssize_t used; /* Number active entries */ + + /* The table contains mask + 1 slots, and that's a power of 2. + * We store the mask instead of the size because the mask is more + * frequently needed. + */ + Py_ssize_t mask; + + /* The table points to a fixed-size smalltable for small tables + * or to additional malloc'ed memory for bigger tables. + * The table pointer is never NULL which saves us from repeated + * runtime null-tests. + */ + setentry *table; + Py_hash_t hash; /* Only used by frozenset objects */ + Py_ssize_t finger; /* Search finger for pop() */ + + setentry smalltable[PySet_MINSIZE]; + PyObject *weakreflist; /* List of weak references */ +} PySetObject; + +#define PySet_GET_SIZE(so) (assert(PyAnySet_Check(so)),(((PySetObject *)(so))->used)) + +PyAPI_DATA(PyObject *) _PySet_Dummy; + +PyAPI_FUNC(int) _PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash); +PyAPI_FUNC(int) _PySet_Update(PyObject *set, PyObject *iterable); +PyAPI_FUNC(int) PySet_ClearFreeList(void); + +#endif /* Section excluded by Py_LIMITED_API */ + +PyAPI_DATA(PyTypeObject) PySet_Type; +PyAPI_DATA(PyTypeObject) PyFrozenSet_Type; +PyAPI_DATA(PyTypeObject) PySetIter_Type; + +PyAPI_FUNC(PyObject *) PySet_New(PyObject *); +PyAPI_FUNC(PyObject *) PyFrozenSet_New(PyObject *); + +PyAPI_FUNC(int) PySet_Add(PyObject *set, PyObject *key); +PyAPI_FUNC(int) PySet_Clear(PyObject *set); +PyAPI_FUNC(int) PySet_Contains(PyObject *anyset, PyObject *key); +PyAPI_FUNC(int) PySet_Discard(PyObject *set, PyObject *key); +PyAPI_FUNC(PyObject *) PySet_Pop(PyObject *set); +PyAPI_FUNC(Py_ssize_t) PySet_Size(PyObject *anyset); + +#define PyFrozenSet_CheckExact(ob) (Py_TYPE(ob) == &PyFrozenSet_Type) +#define PyAnySet_CheckExact(ob) \ + (Py_TYPE(ob) == &PySet_Type || Py_TYPE(ob) == &PyFrozenSet_Type) +#define PyAnySet_Check(ob) \ + (Py_TYPE(ob) == &PySet_Type || Py_TYPE(ob) == &PyFrozenSet_Type || \ + PyType_IsSubtype(Py_TYPE(ob), &PySet_Type) || \ + PyType_IsSubtype(Py_TYPE(ob), &PyFrozenSet_Type)) +#define PySet_Check(ob) \ + (Py_TYPE(ob) == &PySet_Type || \ + PyType_IsSubtype(Py_TYPE(ob), &PySet_Type)) +#define PyFrozenSet_Check(ob) \ + (Py_TYPE(ob) == &PyFrozenSet_Type || \ + PyType_IsSubtype(Py_TYPE(ob), &PyFrozenSet_Type)) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_SETOBJECT_H */ diff --git a/winvenv/Include/sliceobject.h b/winvenv/Include/sliceobject.h new file mode 100644 index 0000000..c238b09 --- /dev/null +++ b/winvenv/Include/sliceobject.h @@ -0,0 +1,63 @@ +#ifndef Py_SLICEOBJECT_H +#define Py_SLICEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* The unique ellipsis object "..." */ + +PyAPI_DATA(PyObject) _Py_EllipsisObject; /* Don't use this directly */ + +#define Py_Ellipsis (&_Py_EllipsisObject) + +/* Slice object interface */ + +/* + +A slice object containing start, stop, and step data members (the +names are from range). After much talk with Guido, it was decided to +let these be any arbitrary python type. Py_None stands for omitted values. +*/ +#ifndef Py_LIMITED_API +typedef struct { + PyObject_HEAD + PyObject *start, *stop, *step; /* not NULL */ +} PySliceObject; +#endif + +PyAPI_DATA(PyTypeObject) PySlice_Type; +PyAPI_DATA(PyTypeObject) PyEllipsis_Type; + +#define PySlice_Check(op) (Py_TYPE(op) == &PySlice_Type) + +PyAPI_FUNC(PyObject *) PySlice_New(PyObject* start, PyObject* stop, + PyObject* step); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PySlice_FromIndices(Py_ssize_t start, Py_ssize_t stop); +PyAPI_FUNC(int) _PySlice_GetLongIndices(PySliceObject *self, PyObject *length, + PyObject **start_ptr, PyObject **stop_ptr, + PyObject **step_ptr); +#endif +PyAPI_FUNC(int) PySlice_GetIndices(PyObject *r, Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step); +PyAPI_FUNC(int) PySlice_GetIndicesEx(PyObject *r, Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, + Py_ssize_t *step, Py_ssize_t *slicelength) Py_DEPRECATED(3.7); + +#if !defined(Py_LIMITED_API) || (Py_LIMITED_API+0 >= 0x03050400 && Py_LIMITED_API+0 < 0x03060000) || Py_LIMITED_API+0 >= 0x03060100 +#define PySlice_GetIndicesEx(slice, length, start, stop, step, slicelen) ( \ + PySlice_Unpack((slice), (start), (stop), (step)) < 0 ? \ + ((*(slicelen) = 0), -1) : \ + ((*(slicelen) = PySlice_AdjustIndices((length), (start), (stop), *(step))), \ + 0)) +PyAPI_FUNC(int) PySlice_Unpack(PyObject *slice, + Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step); +PyAPI_FUNC(Py_ssize_t) PySlice_AdjustIndices(Py_ssize_t length, + Py_ssize_t *start, Py_ssize_t *stop, + Py_ssize_t step); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_SLICEOBJECT_H */ diff --git a/winvenv/Include/structmember.h b/winvenv/Include/structmember.h new file mode 100644 index 0000000..b54f708 --- /dev/null +++ b/winvenv/Include/structmember.h @@ -0,0 +1,74 @@ +#ifndef Py_STRUCTMEMBER_H +#define Py_STRUCTMEMBER_H +#ifdef __cplusplus +extern "C" { +#endif + + +/* Interface to map C struct members to Python object attributes */ + +#include /* For offsetof */ + +/* An array of PyMemberDef structures defines the name, type and offset + of selected members of a C structure. These can be read by + PyMember_GetOne() and set by PyMember_SetOne() (except if their READONLY + flag is set). The array must be terminated with an entry whose name + pointer is NULL. */ + +typedef struct PyMemberDef { + const char *name; + int type; + Py_ssize_t offset; + int flags; + const char *doc; +} PyMemberDef; + +/* Types */ +#define T_SHORT 0 +#define T_INT 1 +#define T_LONG 2 +#define T_FLOAT 3 +#define T_DOUBLE 4 +#define T_STRING 5 +#define T_OBJECT 6 +/* XXX the ordering here is weird for binary compatibility */ +#define T_CHAR 7 /* 1-character string */ +#define T_BYTE 8 /* 8-bit signed int */ +/* unsigned variants: */ +#define T_UBYTE 9 +#define T_USHORT 10 +#define T_UINT 11 +#define T_ULONG 12 + +/* Added by Jack: strings contained in the structure */ +#define T_STRING_INPLACE 13 + +/* Added by Lillo: bools contained in the structure (assumed char) */ +#define T_BOOL 14 + +#define T_OBJECT_EX 16 /* Like T_OBJECT, but raises AttributeError + when the value is NULL, instead of + converting to None. */ +#define T_LONGLONG 17 +#define T_ULONGLONG 18 + +#define T_PYSSIZET 19 /* Py_ssize_t */ +#define T_NONE 20 /* Value is always None */ + + +/* Flags */ +#define READONLY 1 +#define READ_RESTRICTED 2 +#define PY_WRITE_RESTRICTED 4 +#define RESTRICTED (READ_RESTRICTED | PY_WRITE_RESTRICTED) + + +/* Current API, use this */ +PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, struct PyMemberDef *); +PyAPI_FUNC(int) PyMember_SetOne(char *, struct PyMemberDef *, PyObject *); + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_STRUCTMEMBER_H */ diff --git a/winvenv/Include/structseq.h b/winvenv/Include/structseq.h new file mode 100644 index 0000000..e5e5d5c --- /dev/null +++ b/winvenv/Include/structseq.h @@ -0,0 +1,49 @@ + +/* Named tuple object interface */ + +#ifndef Py_STRUCTSEQ_H +#define Py_STRUCTSEQ_H +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct PyStructSequence_Field { + const char *name; + const char *doc; +} PyStructSequence_Field; + +typedef struct PyStructSequence_Desc { + const char *name; + const char *doc; + struct PyStructSequence_Field *fields; + int n_in_sequence; +} PyStructSequence_Desc; + +extern char* PyStructSequence_UnnamedField; + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) PyStructSequence_InitType(PyTypeObject *type, + PyStructSequence_Desc *desc); +PyAPI_FUNC(int) PyStructSequence_InitType2(PyTypeObject *type, + PyStructSequence_Desc *desc); +#endif +PyAPI_FUNC(PyTypeObject*) PyStructSequence_NewType(PyStructSequence_Desc *desc); + +PyAPI_FUNC(PyObject *) PyStructSequence_New(PyTypeObject* type); + +#ifndef Py_LIMITED_API +typedef PyTupleObject PyStructSequence; + +/* Macro, *only* to be used to fill in brand new objects */ +#define PyStructSequence_SET_ITEM(op, i, v) PyTuple_SET_ITEM(op, i, v) + +#define PyStructSequence_GET_ITEM(op, i) PyTuple_GET_ITEM(op, i) +#endif + +PyAPI_FUNC(void) PyStructSequence_SetItem(PyObject*, Py_ssize_t, PyObject*); +PyAPI_FUNC(PyObject*) PyStructSequence_GetItem(PyObject*, Py_ssize_t); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_STRUCTSEQ_H */ diff --git a/winvenv/Include/symtable.h b/winvenv/Include/symtable.h new file mode 100644 index 0000000..007f88d --- /dev/null +++ b/winvenv/Include/symtable.h @@ -0,0 +1,118 @@ +#ifndef Py_LIMITED_API +#ifndef Py_SYMTABLE_H +#define Py_SYMTABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* XXX(ncoghlan): This is a weird mix of public names and interpreter internal + * names. + */ + +typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock } + _Py_block_ty; + +struct _symtable_entry; + +struct symtable { + PyObject *st_filename; /* name of file being compiled, + decoded from the filesystem encoding */ + struct _symtable_entry *st_cur; /* current symbol table entry */ + struct _symtable_entry *st_top; /* symbol table entry for module */ + PyObject *st_blocks; /* dict: map AST node addresses + * to symbol table entries */ + PyObject *st_stack; /* list: stack of namespace info */ + PyObject *st_global; /* borrowed ref to st_top->ste_symbols */ + int st_nblocks; /* number of blocks used. kept for + consistency with the corresponding + compiler structure */ + PyObject *st_private; /* name of current class or NULL */ + PyFutureFeatures *st_future; /* module's future features that affect + the symbol table */ + int recursion_depth; /* current recursion depth */ + int recursion_limit; /* recursion limit */ +}; + +typedef struct _symtable_entry { + PyObject_HEAD + PyObject *ste_id; /* int: key in ste_table->st_blocks */ + PyObject *ste_symbols; /* dict: variable names to flags */ + PyObject *ste_name; /* string: name of current block */ + PyObject *ste_varnames; /* list of function parameters */ + PyObject *ste_children; /* list of child blocks */ + PyObject *ste_directives;/* locations of global and nonlocal statements */ + _Py_block_ty ste_type; /* module, class, or function */ + int ste_nested; /* true if block is nested */ + unsigned ste_free : 1; /* true if block has free variables */ + unsigned ste_child_free : 1; /* true if a child block has free vars, + including free refs to globals */ + unsigned ste_generator : 1; /* true if namespace is a generator */ + unsigned ste_coroutine : 1; /* true if namespace is a coroutine */ + unsigned ste_varargs : 1; /* true if block has varargs */ + unsigned ste_varkeywords : 1; /* true if block has varkeywords */ + unsigned ste_returns_value : 1; /* true if namespace uses return with + an argument */ + unsigned ste_needs_class_closure : 1; /* for class scopes, true if a + closure over __class__ + should be created */ + int ste_lineno; /* first line of block */ + int ste_col_offset; /* offset of first line of block */ + int ste_opt_lineno; /* lineno of last exec or import * */ + int ste_opt_col_offset; /* offset of last exec or import * */ + struct symtable *ste_table; +} PySTEntryObject; + +PyAPI_DATA(PyTypeObject) PySTEntry_Type; + +#define PySTEntry_Check(op) (Py_TYPE(op) == &PySTEntry_Type) + +PyAPI_FUNC(int) PyST_GetScope(PySTEntryObject *, PyObject *); + +PyAPI_FUNC(struct symtable *) PySymtable_Build( + mod_ty mod, + const char *filename, /* decoded from the filesystem encoding */ + PyFutureFeatures *future); +PyAPI_FUNC(struct symtable *) PySymtable_BuildObject( + mod_ty mod, + PyObject *filename, + PyFutureFeatures *future); +PyAPI_FUNC(PySTEntryObject *) PySymtable_Lookup(struct symtable *, void *); + +PyAPI_FUNC(void) PySymtable_Free(struct symtable *); + +/* Flags for def-use information */ + +#define DEF_GLOBAL 1 /* global stmt */ +#define DEF_LOCAL 2 /* assignment in code block */ +#define DEF_PARAM 2<<1 /* formal parameter */ +#define DEF_NONLOCAL 2<<2 /* nonlocal stmt */ +#define USE 2<<3 /* name is used */ +#define DEF_FREE 2<<4 /* name used but not defined in nested block */ +#define DEF_FREE_CLASS 2<<5 /* free variable from class's method */ +#define DEF_IMPORT 2<<6 /* assignment occurred via import */ +#define DEF_ANNOT 2<<7 /* this name is annotated */ + +#define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT) + +/* GLOBAL_EXPLICIT and GLOBAL_IMPLICIT are used internally by the symbol + table. GLOBAL is returned from PyST_GetScope() for either of them. + It is stored in ste_symbols at bits 12-15. +*/ +#define SCOPE_OFFSET 11 +#define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL) + +#define LOCAL 1 +#define GLOBAL_EXPLICIT 2 +#define GLOBAL_IMPLICIT 3 +#define FREE 4 +#define CELL 5 + +#define GENERATOR 1 +#define GENERATOR_EXPRESSION 2 + +#ifdef __cplusplus +} +#endif +#endif /* !Py_SYMTABLE_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/sysmodule.h b/winvenv/Include/sysmodule.h new file mode 100644 index 0000000..719ecfc --- /dev/null +++ b/winvenv/Include/sysmodule.h @@ -0,0 +1,48 @@ + +/* System module interface */ + +#ifndef Py_SYSMODULE_H +#define Py_SYSMODULE_H +#ifdef __cplusplus +extern "C" { +#endif + +PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); +PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PySys_GetObjectId(_Py_Identifier *key); +PyAPI_FUNC(int) _PySys_SetObjectId(_Py_Identifier *key, PyObject *); +#endif + +PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **); +PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int); +PyAPI_FUNC(void) PySys_SetPath(const wchar_t *); + +PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); +PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) + Py_GCC_ATTRIBUTE((format(printf, 1, 2))); +PyAPI_FUNC(void) PySys_FormatStdout(const char *format, ...); +PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...); + +PyAPI_FUNC(void) PySys_ResetWarnOptions(void); +PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *); +PyAPI_FUNC(void) PySys_AddWarnOptionUnicode(PyObject *); +PyAPI_FUNC(int) PySys_HasWarnOptions(void); + +PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *); +PyAPI_FUNC(PyObject *) PySys_GetXOptions(void); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *); +#endif + +#ifdef Py_BUILD_CORE +PyAPI_FUNC(int) _PySys_AddXOptionWithError(const wchar_t *s); +PyAPI_FUNC(int) _PySys_AddWarnOptionWithError(PyObject *option); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_SYSMODULE_H */ diff --git a/winvenv/Include/token.h b/winvenv/Include/token.h new file mode 100644 index 0000000..cd1cd00 --- /dev/null +++ b/winvenv/Include/token.h @@ -0,0 +1,92 @@ + +/* Token types */ +#ifndef Py_LIMITED_API +#ifndef Py_TOKEN_H +#define Py_TOKEN_H +#ifdef __cplusplus +extern "C" { +#endif + +#undef TILDE /* Prevent clash of our definition with system macro. Ex AIX, ioctl.h */ + +#define ENDMARKER 0 +#define NAME 1 +#define NUMBER 2 +#define STRING 3 +#define NEWLINE 4 +#define INDENT 5 +#define DEDENT 6 +#define LPAR 7 +#define RPAR 8 +#define LSQB 9 +#define RSQB 10 +#define COLON 11 +#define COMMA 12 +#define SEMI 13 +#define PLUS 14 +#define MINUS 15 +#define STAR 16 +#define SLASH 17 +#define VBAR 18 +#define AMPER 19 +#define LESS 20 +#define GREATER 21 +#define EQUAL 22 +#define DOT 23 +#define PERCENT 24 +#define LBRACE 25 +#define RBRACE 26 +#define EQEQUAL 27 +#define NOTEQUAL 28 +#define LESSEQUAL 29 +#define GREATEREQUAL 30 +#define TILDE 31 +#define CIRCUMFLEX 32 +#define LEFTSHIFT 33 +#define RIGHTSHIFT 34 +#define DOUBLESTAR 35 +#define PLUSEQUAL 36 +#define MINEQUAL 37 +#define STAREQUAL 38 +#define SLASHEQUAL 39 +#define PERCENTEQUAL 40 +#define AMPEREQUAL 41 +#define VBAREQUAL 42 +#define CIRCUMFLEXEQUAL 43 +#define LEFTSHIFTEQUAL 44 +#define RIGHTSHIFTEQUAL 45 +#define DOUBLESTAREQUAL 46 +#define DOUBLESLASH 47 +#define DOUBLESLASHEQUAL 48 +#define AT 49 +#define ATEQUAL 50 +#define RARROW 51 +#define ELLIPSIS 52 +/* Don't forget to update the table _PyParser_TokenNames in tokenizer.c! */ +#define OP 53 +#define ERRORTOKEN 54 +/* These aren't used by the C tokenizer but are needed for tokenize.py */ +#define COMMENT 55 +#define NL 56 +#define ENCODING 57 +#define N_TOKENS 58 + +/* Special definitions for cooperation with parser */ + +#define NT_OFFSET 256 + +#define ISTERMINAL(x) ((x) < NT_OFFSET) +#define ISNONTERMINAL(x) ((x) >= NT_OFFSET) +#define ISEOF(x) ((x) == ENDMARKER) + + +PyAPI_DATA(const char *) _PyParser_TokenNames[]; /* Token names */ +PyAPI_FUNC(int) PyToken_OneChar(int); +PyAPI_FUNC(int) PyToken_TwoChars(int, int); +PyAPI_FUNC(int) PyToken_ThreeChars(int, int, int); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_TOKEN_H */ +#endif /* Py_LIMITED_API */ diff --git a/winvenv/Include/traceback.h b/winvenv/Include/traceback.h new file mode 100644 index 0000000..b587410 --- /dev/null +++ b/winvenv/Include/traceback.h @@ -0,0 +1,119 @@ + +#ifndef Py_TRACEBACK_H +#define Py_TRACEBACK_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "pystate.h" + +struct _frame; + +/* Traceback interface */ +#ifndef Py_LIMITED_API +typedef struct _traceback { + PyObject_HEAD + struct _traceback *tb_next; + struct _frame *tb_frame; + int tb_lasti; + int tb_lineno; +} PyTracebackObject; +#endif + +PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *); +PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, PyObject *, int, int); +PyAPI_FUNC(void) _PyTraceback_Add(const char *, const char *, int); +#endif + +/* Reveal traceback type so we can typecheck traceback objects */ +PyAPI_DATA(PyTypeObject) PyTraceBack_Type; +#define PyTraceBack_Check(v) (Py_TYPE(v) == &PyTraceBack_Type) + +#ifndef Py_LIMITED_API +/* Write the Python traceback into the file 'fd'. For example: + + Traceback (most recent call first): + File "xxx", line xxx in + File "xxx", line xxx in + ... + File "xxx", line xxx in + + This function is written for debug purpose only, to dump the traceback in + the worst case: after a segmentation fault, at fatal error, etc. That's why, + it is very limited. Strings are truncated to 100 characters and encoded to + ASCII with backslashreplace. It doesn't write the source code, only the + function name, filename and line number of each frame. Write only the first + 100 frames: if the traceback is truncated, write the line " ...". + + This function is signal safe. */ + +PyAPI_FUNC(void) _Py_DumpTraceback( + int fd, + PyThreadState *tstate); + +/* Write the traceback of all threads into the file 'fd'. current_thread can be + NULL. + + Return NULL on success, or an error message on error. + + This function is written for debug purpose only. It calls + _Py_DumpTraceback() for each thread, and so has the same limitations. It + only write the traceback of the first 100 threads: write "..." if there are + more threads. + + If current_tstate is NULL, the function tries to get the Python thread state + of the current thread. It is not an error if the function is unable to get + the current Python thread state. + + If interp is NULL, the function tries to get the interpreter state from + the current Python thread state, or from + _PyGILState_GetInterpreterStateUnsafe() in last resort. + + It is better to pass NULL to interp and current_tstate, the function tries + different options to retrieve these informations. + + This function is signal safe. */ + +PyAPI_FUNC(const char*) _Py_DumpTracebackThreads( + int fd, + PyInterpreterState *interp, + PyThreadState *current_tstate); +#endif /* !Py_LIMITED_API */ + +#ifndef Py_LIMITED_API + +/* Write a Unicode object into the file descriptor fd. Encode the string to + ASCII using the backslashreplace error handler. + + Do nothing if text is not a Unicode object. The function accepts Unicode + string which is not ready (PyUnicode_WCHAR_KIND). + + This function is signal safe. */ +PyAPI_FUNC(void) _Py_DumpASCII(int fd, PyObject *text); + +/* Format an integer as decimal into the file descriptor fd. + + This function is signal safe. */ +PyAPI_FUNC(void) _Py_DumpDecimal( + int fd, + unsigned long value); + +/* Format an integer as hexadecimal into the file descriptor fd with at least + width digits. + + The maximum width is sizeof(unsigned long)*2 digits. + + This function is signal safe. */ +PyAPI_FUNC(void) _Py_DumpHexadecimal( + int fd, + unsigned long value, + Py_ssize_t width); + +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_TRACEBACK_H */ diff --git a/winvenv/Include/tupleobject.h b/winvenv/Include/tupleobject.h new file mode 100644 index 0000000..72a7d8d --- /dev/null +++ b/winvenv/Include/tupleobject.h @@ -0,0 +1,73 @@ + +/* Tuple object interface */ + +#ifndef Py_TUPLEOBJECT_H +#define Py_TUPLEOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* +Another generally useful object type is a tuple of object pointers. +For Python, this is an immutable type. C code can change the tuple items +(but not their number), and even use tuples as general-purpose arrays of +object references, but in general only brand new tuples should be mutated, +not ones that might already have been exposed to Python code. + +*** WARNING *** PyTuple_SetItem does not increment the new item's reference +count, but does decrement the reference count of the item it replaces, +if not nil. It does *decrement* the reference count if it is *not* +inserted in the tuple. Similarly, PyTuple_GetItem does not increment the +returned item's reference count. +*/ + +#ifndef Py_LIMITED_API +typedef struct { + PyObject_VAR_HEAD + PyObject *ob_item[1]; + + /* ob_item contains space for 'ob_size' elements. + * Items must normally not be NULL, except during construction when + * the tuple is not yet visible outside the function that builds it. + */ +} PyTupleObject; +#endif + +PyAPI_DATA(PyTypeObject) PyTuple_Type; +PyAPI_DATA(PyTypeObject) PyTupleIter_Type; + +#define PyTuple_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TUPLE_SUBCLASS) +#define PyTuple_CheckExact(op) (Py_TYPE(op) == &PyTuple_Type) + +PyAPI_FUNC(PyObject *) PyTuple_New(Py_ssize_t size); +PyAPI_FUNC(Py_ssize_t) PyTuple_Size(PyObject *); +PyAPI_FUNC(PyObject *) PyTuple_GetItem(PyObject *, Py_ssize_t); +PyAPI_FUNC(int) PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *); +PyAPI_FUNC(PyObject *) PyTuple_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t); +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyTuple_Resize(PyObject **, Py_ssize_t); +#endif +PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyTuple_MaybeUntrack(PyObject *); +#endif + +/* Macro, trading safety for speed */ +#ifndef Py_LIMITED_API +#define PyTuple_GET_ITEM(op, i) (((PyTupleObject *)(op))->ob_item[i]) +#define PyTuple_GET_SIZE(op) (assert(PyTuple_Check(op)),Py_SIZE(op)) + +/* Macro, *only* to be used to fill in brand new tuples */ +#define PyTuple_SET_ITEM(op, i, v) (((PyTupleObject *)(op))->ob_item[i] = v) +#endif + +PyAPI_FUNC(int) PyTuple_ClearFreeList(void); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out); +#endif /* Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_TUPLEOBJECT_H */ diff --git a/winvenv/Include/typeslots.h b/winvenv/Include/typeslots.h new file mode 100644 index 0000000..0ce6a37 --- /dev/null +++ b/winvenv/Include/typeslots.h @@ -0,0 +1,85 @@ +/* Do not renumber the file; these numbers are part of the stable ABI. */ +/* Disabled, see #10181 */ +#undef Py_bf_getbuffer +#undef Py_bf_releasebuffer +#define Py_mp_ass_subscript 3 +#define Py_mp_length 4 +#define Py_mp_subscript 5 +#define Py_nb_absolute 6 +#define Py_nb_add 7 +#define Py_nb_and 8 +#define Py_nb_bool 9 +#define Py_nb_divmod 10 +#define Py_nb_float 11 +#define Py_nb_floor_divide 12 +#define Py_nb_index 13 +#define Py_nb_inplace_add 14 +#define Py_nb_inplace_and 15 +#define Py_nb_inplace_floor_divide 16 +#define Py_nb_inplace_lshift 17 +#define Py_nb_inplace_multiply 18 +#define Py_nb_inplace_or 19 +#define Py_nb_inplace_power 20 +#define Py_nb_inplace_remainder 21 +#define Py_nb_inplace_rshift 22 +#define Py_nb_inplace_subtract 23 +#define Py_nb_inplace_true_divide 24 +#define Py_nb_inplace_xor 25 +#define Py_nb_int 26 +#define Py_nb_invert 27 +#define Py_nb_lshift 28 +#define Py_nb_multiply 29 +#define Py_nb_negative 30 +#define Py_nb_or 31 +#define Py_nb_positive 32 +#define Py_nb_power 33 +#define Py_nb_remainder 34 +#define Py_nb_rshift 35 +#define Py_nb_subtract 36 +#define Py_nb_true_divide 37 +#define Py_nb_xor 38 +#define Py_sq_ass_item 39 +#define Py_sq_concat 40 +#define Py_sq_contains 41 +#define Py_sq_inplace_concat 42 +#define Py_sq_inplace_repeat 43 +#define Py_sq_item 44 +#define Py_sq_length 45 +#define Py_sq_repeat 46 +#define Py_tp_alloc 47 +#define Py_tp_base 48 +#define Py_tp_bases 49 +#define Py_tp_call 50 +#define Py_tp_clear 51 +#define Py_tp_dealloc 52 +#define Py_tp_del 53 +#define Py_tp_descr_get 54 +#define Py_tp_descr_set 55 +#define Py_tp_doc 56 +#define Py_tp_getattr 57 +#define Py_tp_getattro 58 +#define Py_tp_hash 59 +#define Py_tp_init 60 +#define Py_tp_is_gc 61 +#define Py_tp_iter 62 +#define Py_tp_iternext 63 +#define Py_tp_methods 64 +#define Py_tp_new 65 +#define Py_tp_repr 66 +#define Py_tp_richcompare 67 +#define Py_tp_setattr 68 +#define Py_tp_setattro 69 +#define Py_tp_str 70 +#define Py_tp_traverse 71 +#define Py_tp_members 72 +#define Py_tp_getset 73 +#define Py_tp_free 74 +#define Py_nb_matrix_multiply 75 +#define Py_nb_inplace_matrix_multiply 76 +#define Py_am_await 77 +#define Py_am_aiter 78 +#define Py_am_anext 79 +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000 +/* New in 3.5 */ +#define Py_tp_finalize 80 +#endif diff --git a/winvenv/Include/ucnhash.h b/winvenv/Include/ucnhash.h new file mode 100644 index 0000000..45362e9 --- /dev/null +++ b/winvenv/Include/ucnhash.h @@ -0,0 +1,36 @@ +/* Unicode name database interface */ +#ifndef Py_LIMITED_API +#ifndef Py_UCNHASH_H +#define Py_UCNHASH_H +#ifdef __cplusplus +extern "C" { +#endif + +/* revised ucnhash CAPI interface (exported through a "wrapper") */ + +#define PyUnicodeData_CAPSULE_NAME "unicodedata.ucnhash_CAPI" + +typedef struct { + + /* Size of this struct */ + int size; + + /* Get name for a given character code. Returns non-zero if + success, zero if not. Does not set Python exceptions. + If self is NULL, data come from the default version of the database. + If it is not NULL, it should be a unicodedata.ucd_X_Y_Z object */ + int (*getname)(PyObject *self, Py_UCS4 code, char* buffer, int buflen, + int with_alias_and_seq); + + /* Get character code for a given name. Same error handling + as for getname. */ + int (*getcode)(PyObject *self, const char* name, int namelen, Py_UCS4* code, + int with_named_seq); + +} _PyUnicode_Name_CAPI; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_UCNHASH_H */ +#endif /* !Py_LIMITED_API */ diff --git a/winvenv/Include/unicodeobject.h b/winvenv/Include/unicodeobject.h new file mode 100644 index 0000000..0274de6 --- /dev/null +++ b/winvenv/Include/unicodeobject.h @@ -0,0 +1,2334 @@ +#ifndef Py_UNICODEOBJECT_H +#define Py_UNICODEOBJECT_H + +#include + +/* + +Unicode implementation based on original code by Fredrik Lundh, +modified by Marc-Andre Lemburg (mal@lemburg.com) according to the +Unicode Integration Proposal. (See +http://www.egenix.com/files/python/unicode-proposal.txt). + +Copyright (c) Corporation for National Research Initiatives. + + + Original header: + -------------------------------------------------------------------- + + * Yet another Unicode string type for Python. This type supports the + * 16-bit Basic Multilingual Plane (BMP) only. + * + * Written by Fredrik Lundh, January 1999. + * + * Copyright (c) 1999 by Secret Labs AB. + * Copyright (c) 1999 by Fredrik Lundh. + * + * fredrik@pythonware.com + * http://www.pythonware.com + * + * -------------------------------------------------------------------- + * This Unicode String Type is + * + * Copyright (c) 1999 by Secret Labs AB + * Copyright (c) 1999 by Fredrik Lundh + * + * By obtaining, using, and/or copying this software and/or its + * associated documentation, you agree that you have read, understood, + * and will comply with the following terms and conditions: + * + * Permission to use, copy, modify, and distribute this software and its + * associated documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appears in all + * copies, and that both that copyright notice and this permission notice + * appear in supporting documentation, and that the name of Secret Labs + * AB or the author not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * -------------------------------------------------------------------- */ + +#include + +/* === Internal API ======================================================= */ + +/* --- Internal Unicode Format -------------------------------------------- */ + +/* Python 3.x requires unicode */ +#define Py_USING_UNICODE + +#ifndef SIZEOF_WCHAR_T +#error Must define SIZEOF_WCHAR_T +#endif + +#define Py_UNICODE_SIZE SIZEOF_WCHAR_T + +/* If wchar_t can be used for UCS-4 storage, set Py_UNICODE_WIDE. + Otherwise, Unicode strings are stored as UCS-2 (with limited support + for UTF-16) */ + +#if Py_UNICODE_SIZE >= 4 +#define Py_UNICODE_WIDE +#endif + +/* Set these flags if the platform has "wchar.h" and the + wchar_t type is a 16-bit unsigned type */ +/* #define HAVE_WCHAR_H */ +/* #define HAVE_USABLE_WCHAR_T */ + +/* Py_UNICODE was the native Unicode storage format (code unit) used by + Python and represents a single Unicode element in the Unicode type. + With PEP 393, Py_UNICODE is deprecated and replaced with a + typedef to wchar_t. */ + +#ifndef Py_LIMITED_API +#define PY_UNICODE_TYPE wchar_t +typedef wchar_t Py_UNICODE /* Py_DEPRECATED(3.3) */; +#endif + +/* If the compiler provides a wchar_t type we try to support it + through the interface functions PyUnicode_FromWideChar(), + PyUnicode_AsWideChar() and PyUnicode_AsWideCharString(). */ + +#ifdef HAVE_USABLE_WCHAR_T +# ifndef HAVE_WCHAR_H +# define HAVE_WCHAR_H +# endif +#endif + +#ifdef HAVE_WCHAR_H +# include +#endif + +/* Py_UCS4 and Py_UCS2 are typedefs for the respective + unicode representations. */ +typedef uint32_t Py_UCS4; +typedef uint16_t Py_UCS2; +typedef uint8_t Py_UCS1; + +/* --- Internal Unicode Operations ---------------------------------------- */ + +/* Since splitting on whitespace is an important use case, and + whitespace in most situations is solely ASCII whitespace, we + optimize for the common case by using a quick look-up table + _Py_ascii_whitespace (see below) with an inlined check. + + */ +#ifndef Py_LIMITED_API +#define Py_UNICODE_ISSPACE(ch) \ + ((ch) < 128U ? _Py_ascii_whitespace[(ch)] : _PyUnicode_IsWhitespace(ch)) + +#define Py_UNICODE_ISLOWER(ch) _PyUnicode_IsLowercase(ch) +#define Py_UNICODE_ISUPPER(ch) _PyUnicode_IsUppercase(ch) +#define Py_UNICODE_ISTITLE(ch) _PyUnicode_IsTitlecase(ch) +#define Py_UNICODE_ISLINEBREAK(ch) _PyUnicode_IsLinebreak(ch) + +#define Py_UNICODE_TOLOWER(ch) _PyUnicode_ToLowercase(ch) +#define Py_UNICODE_TOUPPER(ch) _PyUnicode_ToUppercase(ch) +#define Py_UNICODE_TOTITLE(ch) _PyUnicode_ToTitlecase(ch) + +#define Py_UNICODE_ISDECIMAL(ch) _PyUnicode_IsDecimalDigit(ch) +#define Py_UNICODE_ISDIGIT(ch) _PyUnicode_IsDigit(ch) +#define Py_UNICODE_ISNUMERIC(ch) _PyUnicode_IsNumeric(ch) +#define Py_UNICODE_ISPRINTABLE(ch) _PyUnicode_IsPrintable(ch) + +#define Py_UNICODE_TODECIMAL(ch) _PyUnicode_ToDecimalDigit(ch) +#define Py_UNICODE_TODIGIT(ch) _PyUnicode_ToDigit(ch) +#define Py_UNICODE_TONUMERIC(ch) _PyUnicode_ToNumeric(ch) + +#define Py_UNICODE_ISALPHA(ch) _PyUnicode_IsAlpha(ch) + +#define Py_UNICODE_ISALNUM(ch) \ + (Py_UNICODE_ISALPHA(ch) || \ + Py_UNICODE_ISDECIMAL(ch) || \ + Py_UNICODE_ISDIGIT(ch) || \ + Py_UNICODE_ISNUMERIC(ch)) + +#define Py_UNICODE_COPY(target, source, length) \ + memcpy((target), (source), (length)*sizeof(Py_UNICODE)) + +#define Py_UNICODE_FILL(target, value, length) \ + do {Py_ssize_t i_; Py_UNICODE *t_ = (target); Py_UNICODE v_ = (value);\ + for (i_ = 0; i_ < (length); i_++) t_[i_] = v_;\ + } while (0) + +/* macros to work with surrogates */ +#define Py_UNICODE_IS_SURROGATE(ch) (0xD800 <= (ch) && (ch) <= 0xDFFF) +#define Py_UNICODE_IS_HIGH_SURROGATE(ch) (0xD800 <= (ch) && (ch) <= 0xDBFF) +#define Py_UNICODE_IS_LOW_SURROGATE(ch) (0xDC00 <= (ch) && (ch) <= 0xDFFF) +/* Join two surrogate characters and return a single Py_UCS4 value. */ +#define Py_UNICODE_JOIN_SURROGATES(high, low) \ + (((((Py_UCS4)(high) & 0x03FF) << 10) | \ + ((Py_UCS4)(low) & 0x03FF)) + 0x10000) +/* high surrogate = top 10 bits added to D800 */ +#define Py_UNICODE_HIGH_SURROGATE(ch) (0xD800 - (0x10000 >> 10) + ((ch) >> 10)) +/* low surrogate = bottom 10 bits added to DC00 */ +#define Py_UNICODE_LOW_SURROGATE(ch) (0xDC00 + ((ch) & 0x3FF)) + +/* Check if substring matches at given offset. The offset must be + valid, and the substring must not be empty. */ + +#define Py_UNICODE_MATCH(string, offset, substring) \ + ((*((string)->wstr + (offset)) == *((substring)->wstr)) && \ + ((*((string)->wstr + (offset) + (substring)->wstr_length-1) == *((substring)->wstr + (substring)->wstr_length-1))) && \ + !memcmp((string)->wstr + (offset), (substring)->wstr, (substring)->wstr_length*sizeof(Py_UNICODE))) + +#endif /* Py_LIMITED_API */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* --- Unicode Type ------------------------------------------------------- */ + +#ifndef Py_LIMITED_API + +/* ASCII-only strings created through PyUnicode_New use the PyASCIIObject + structure. state.ascii and state.compact are set, and the data + immediately follow the structure. utf8_length and wstr_length can be found + in the length field; the utf8 pointer is equal to the data pointer. */ +typedef struct { + /* There are 4 forms of Unicode strings: + + - compact ascii: + + * structure = PyASCIIObject + * test: PyUnicode_IS_COMPACT_ASCII(op) + * kind = PyUnicode_1BYTE_KIND + * compact = 1 + * ascii = 1 + * ready = 1 + * (length is the length of the utf8 and wstr strings) + * (data starts just after the structure) + * (since ASCII is decoded from UTF-8, the utf8 string are the data) + + - compact: + + * structure = PyCompactUnicodeObject + * test: PyUnicode_IS_COMPACT(op) && !PyUnicode_IS_ASCII(op) + * kind = PyUnicode_1BYTE_KIND, PyUnicode_2BYTE_KIND or + PyUnicode_4BYTE_KIND + * compact = 1 + * ready = 1 + * ascii = 0 + * utf8 is not shared with data + * utf8_length = 0 if utf8 is NULL + * wstr is shared with data and wstr_length=length + if kind=PyUnicode_2BYTE_KIND and sizeof(wchar_t)=2 + or if kind=PyUnicode_4BYTE_KIND and sizeof(wchar_t)=4 + * wstr_length = 0 if wstr is NULL + * (data starts just after the structure) + + - legacy string, not ready: + + * structure = PyUnicodeObject + * test: kind == PyUnicode_WCHAR_KIND + * length = 0 (use wstr_length) + * hash = -1 + * kind = PyUnicode_WCHAR_KIND + * compact = 0 + * ascii = 0 + * ready = 0 + * interned = SSTATE_NOT_INTERNED + * wstr is not NULL + * data.any is NULL + * utf8 is NULL + * utf8_length = 0 + + - legacy string, ready: + + * structure = PyUnicodeObject structure + * test: !PyUnicode_IS_COMPACT(op) && kind != PyUnicode_WCHAR_KIND + * kind = PyUnicode_1BYTE_KIND, PyUnicode_2BYTE_KIND or + PyUnicode_4BYTE_KIND + * compact = 0 + * ready = 1 + * data.any is not NULL + * utf8 is shared and utf8_length = length with data.any if ascii = 1 + * utf8_length = 0 if utf8 is NULL + * wstr is shared with data.any and wstr_length = length + if kind=PyUnicode_2BYTE_KIND and sizeof(wchar_t)=2 + or if kind=PyUnicode_4BYTE_KIND and sizeof(wchar_4)=4 + * wstr_length = 0 if wstr is NULL + + Compact strings use only one memory block (structure + characters), + whereas legacy strings use one block for the structure and one block + for characters. + + Legacy strings are created by PyUnicode_FromUnicode() and + PyUnicode_FromStringAndSize(NULL, size) functions. They become ready + when PyUnicode_READY() is called. + + See also _PyUnicode_CheckConsistency(). + */ + PyObject_HEAD + Py_ssize_t length; /* Number of code points in the string */ + Py_hash_t hash; /* Hash value; -1 if not set */ + struct { + /* + SSTATE_NOT_INTERNED (0) + SSTATE_INTERNED_MORTAL (1) + SSTATE_INTERNED_IMMORTAL (2) + + If interned != SSTATE_NOT_INTERNED, the two references from the + dictionary to this object are *not* counted in ob_refcnt. + */ + unsigned int interned:2; + /* Character size: + + - PyUnicode_WCHAR_KIND (0): + + * character type = wchar_t (16 or 32 bits, depending on the + platform) + + - PyUnicode_1BYTE_KIND (1): + + * character type = Py_UCS1 (8 bits, unsigned) + * all characters are in the range U+0000-U+00FF (latin1) + * if ascii is set, all characters are in the range U+0000-U+007F + (ASCII), otherwise at least one character is in the range + U+0080-U+00FF + + - PyUnicode_2BYTE_KIND (2): + + * character type = Py_UCS2 (16 bits, unsigned) + * all characters are in the range U+0000-U+FFFF (BMP) + * at least one character is in the range U+0100-U+FFFF + + - PyUnicode_4BYTE_KIND (4): + + * character type = Py_UCS4 (32 bits, unsigned) + * all characters are in the range U+0000-U+10FFFF + * at least one character is in the range U+10000-U+10FFFF + */ + unsigned int kind:3; + /* Compact is with respect to the allocation scheme. Compact unicode + objects only require one memory block while non-compact objects use + one block for the PyUnicodeObject struct and another for its data + buffer. */ + unsigned int compact:1; + /* The string only contains characters in the range U+0000-U+007F (ASCII) + and the kind is PyUnicode_1BYTE_KIND. If ascii is set and compact is + set, use the PyASCIIObject structure. */ + unsigned int ascii:1; + /* The ready flag indicates whether the object layout is initialized + completely. This means that this is either a compact object, or + the data pointer is filled out. The bit is redundant, and helps + to minimize the test in PyUnicode_IS_READY(). */ + unsigned int ready:1; + /* Padding to ensure that PyUnicode_DATA() is always aligned to + 4 bytes (see issue #19537 on m68k). */ + unsigned int :24; + } state; + wchar_t *wstr; /* wchar_t representation (null-terminated) */ +} PyASCIIObject; + +/* Non-ASCII strings allocated through PyUnicode_New use the + PyCompactUnicodeObject structure. state.compact is set, and the data + immediately follow the structure. */ +typedef struct { + PyASCIIObject _base; + Py_ssize_t utf8_length; /* Number of bytes in utf8, excluding the + * terminating \0. */ + char *utf8; /* UTF-8 representation (null-terminated) */ + Py_ssize_t wstr_length; /* Number of code points in wstr, possible + * surrogates count as two code points. */ +} PyCompactUnicodeObject; + +/* Strings allocated through PyUnicode_FromUnicode(NULL, len) use the + PyUnicodeObject structure. The actual string data is initially in the wstr + block, and copied into the data block using _PyUnicode_Ready. */ +typedef struct { + PyCompactUnicodeObject _base; + union { + void *any; + Py_UCS1 *latin1; + Py_UCS2 *ucs2; + Py_UCS4 *ucs4; + } data; /* Canonical, smallest-form Unicode buffer */ +} PyUnicodeObject; +#endif + +PyAPI_DATA(PyTypeObject) PyUnicode_Type; +PyAPI_DATA(PyTypeObject) PyUnicodeIter_Type; + +#define PyUnicode_Check(op) \ + PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) +#define PyUnicode_CheckExact(op) (Py_TYPE(op) == &PyUnicode_Type) + +/* Fast access macros */ +#ifndef Py_LIMITED_API + +#define PyUnicode_WSTR_LENGTH(op) \ + (PyUnicode_IS_COMPACT_ASCII(op) ? \ + ((PyASCIIObject*)op)->length : \ + ((PyCompactUnicodeObject*)op)->wstr_length) + +/* Returns the deprecated Py_UNICODE representation's size in code units + (this includes surrogate pairs as 2 units). + If the Py_UNICODE representation is not available, it will be computed + on request. Use PyUnicode_GET_LENGTH() for the length in code points. */ + +#define PyUnicode_GET_SIZE(op) \ + (assert(PyUnicode_Check(op)), \ + (((PyASCIIObject *)(op))->wstr) ? \ + PyUnicode_WSTR_LENGTH(op) : \ + ((void)PyUnicode_AsUnicode((PyObject *)(op)), \ + assert(((PyASCIIObject *)(op))->wstr), \ + PyUnicode_WSTR_LENGTH(op))) + /* Py_DEPRECATED(3.3) */ + +#define PyUnicode_GET_DATA_SIZE(op) \ + (PyUnicode_GET_SIZE(op) * Py_UNICODE_SIZE) + /* Py_DEPRECATED(3.3) */ + +/* Alias for PyUnicode_AsUnicode(). This will create a wchar_t/Py_UNICODE + representation on demand. Using this macro is very inefficient now, + try to port your code to use the new PyUnicode_*BYTE_DATA() macros or + use PyUnicode_WRITE() and PyUnicode_READ(). */ + +#define PyUnicode_AS_UNICODE(op) \ + (assert(PyUnicode_Check(op)), \ + (((PyASCIIObject *)(op))->wstr) ? (((PyASCIIObject *)(op))->wstr) : \ + PyUnicode_AsUnicode((PyObject *)(op))) + /* Py_DEPRECATED(3.3) */ + +#define PyUnicode_AS_DATA(op) \ + ((const char *)(PyUnicode_AS_UNICODE(op))) + /* Py_DEPRECATED(3.3) */ + + +/* --- Flexible String Representation Helper Macros (PEP 393) -------------- */ + +/* Values for PyASCIIObject.state: */ + +/* Interning state. */ +#define SSTATE_NOT_INTERNED 0 +#define SSTATE_INTERNED_MORTAL 1 +#define SSTATE_INTERNED_IMMORTAL 2 + +/* Return true if the string contains only ASCII characters, or 0 if not. The + string may be compact (PyUnicode_IS_COMPACT_ASCII) or not, but must be + ready. */ +#define PyUnicode_IS_ASCII(op) \ + (assert(PyUnicode_Check(op)), \ + assert(PyUnicode_IS_READY(op)), \ + ((PyASCIIObject*)op)->state.ascii) + +/* Return true if the string is compact or 0 if not. + No type checks or Ready calls are performed. */ +#define PyUnicode_IS_COMPACT(op) \ + (((PyASCIIObject*)(op))->state.compact) + +/* Return true if the string is a compact ASCII string (use PyASCIIObject + structure), or 0 if not. No type checks or Ready calls are performed. */ +#define PyUnicode_IS_COMPACT_ASCII(op) \ + (((PyASCIIObject*)op)->state.ascii && PyUnicode_IS_COMPACT(op)) + +enum PyUnicode_Kind { +/* String contains only wstr byte characters. This is only possible + when the string was created with a legacy API and _PyUnicode_Ready() + has not been called yet. */ + PyUnicode_WCHAR_KIND = 0, +/* Return values of the PyUnicode_KIND() macro: */ + PyUnicode_1BYTE_KIND = 1, + PyUnicode_2BYTE_KIND = 2, + PyUnicode_4BYTE_KIND = 4 +}; + +/* Return pointers to the canonical representation cast to unsigned char, + Py_UCS2, or Py_UCS4 for direct character access. + No checks are performed, use PyUnicode_KIND() before to ensure + these will work correctly. */ + +#define PyUnicode_1BYTE_DATA(op) ((Py_UCS1*)PyUnicode_DATA(op)) +#define PyUnicode_2BYTE_DATA(op) ((Py_UCS2*)PyUnicode_DATA(op)) +#define PyUnicode_4BYTE_DATA(op) ((Py_UCS4*)PyUnicode_DATA(op)) + +/* Return one of the PyUnicode_*_KIND values defined above. */ +#define PyUnicode_KIND(op) \ + (assert(PyUnicode_Check(op)), \ + assert(PyUnicode_IS_READY(op)), \ + ((PyASCIIObject *)(op))->state.kind) + +/* Return a void pointer to the raw unicode buffer. */ +#define _PyUnicode_COMPACT_DATA(op) \ + (PyUnicode_IS_ASCII(op) ? \ + ((void*)((PyASCIIObject*)(op) + 1)) : \ + ((void*)((PyCompactUnicodeObject*)(op) + 1))) + +#define _PyUnicode_NONCOMPACT_DATA(op) \ + (assert(((PyUnicodeObject*)(op))->data.any), \ + ((((PyUnicodeObject *)(op))->data.any))) + +#define PyUnicode_DATA(op) \ + (assert(PyUnicode_Check(op)), \ + PyUnicode_IS_COMPACT(op) ? _PyUnicode_COMPACT_DATA(op) : \ + _PyUnicode_NONCOMPACT_DATA(op)) + +/* In the access macros below, "kind" may be evaluated more than once. + All other macro parameters are evaluated exactly once, so it is safe + to put side effects into them (such as increasing the index). */ + +/* Write into the canonical representation, this macro does not do any sanity + checks and is intended for usage in loops. The caller should cache the + kind and data pointers obtained from other macro calls. + index is the index in the string (starts at 0) and value is the new + code point value which should be written to that location. */ +#define PyUnicode_WRITE(kind, data, index, value) \ + do { \ + switch ((kind)) { \ + case PyUnicode_1BYTE_KIND: { \ + ((Py_UCS1 *)(data))[(index)] = (Py_UCS1)(value); \ + break; \ + } \ + case PyUnicode_2BYTE_KIND: { \ + ((Py_UCS2 *)(data))[(index)] = (Py_UCS2)(value); \ + break; \ + } \ + default: { \ + assert((kind) == PyUnicode_4BYTE_KIND); \ + ((Py_UCS4 *)(data))[(index)] = (Py_UCS4)(value); \ + } \ + } \ + } while (0) + +/* Read a code point from the string's canonical representation. No checks + or ready calls are performed. */ +#define PyUnicode_READ(kind, data, index) \ + ((Py_UCS4) \ + ((kind) == PyUnicode_1BYTE_KIND ? \ + ((const Py_UCS1 *)(data))[(index)] : \ + ((kind) == PyUnicode_2BYTE_KIND ? \ + ((const Py_UCS2 *)(data))[(index)] : \ + ((const Py_UCS4 *)(data))[(index)] \ + ) \ + )) + +/* PyUnicode_READ_CHAR() is less efficient than PyUnicode_READ() because it + calls PyUnicode_KIND() and might call it twice. For single reads, use + PyUnicode_READ_CHAR, for multiple consecutive reads callers should + cache kind and use PyUnicode_READ instead. */ +#define PyUnicode_READ_CHAR(unicode, index) \ + (assert(PyUnicode_Check(unicode)), \ + assert(PyUnicode_IS_READY(unicode)), \ + (Py_UCS4) \ + (PyUnicode_KIND((unicode)) == PyUnicode_1BYTE_KIND ? \ + ((const Py_UCS1 *)(PyUnicode_DATA((unicode))))[(index)] : \ + (PyUnicode_KIND((unicode)) == PyUnicode_2BYTE_KIND ? \ + ((const Py_UCS2 *)(PyUnicode_DATA((unicode))))[(index)] : \ + ((const Py_UCS4 *)(PyUnicode_DATA((unicode))))[(index)] \ + ) \ + )) + +/* Returns the length of the unicode string. The caller has to make sure that + the string has it's canonical representation set before calling + this macro. Call PyUnicode_(FAST_)Ready to ensure that. */ +#define PyUnicode_GET_LENGTH(op) \ + (assert(PyUnicode_Check(op)), \ + assert(PyUnicode_IS_READY(op)), \ + ((PyASCIIObject *)(op))->length) + + +/* Fast check to determine whether an object is ready. Equivalent to + PyUnicode_IS_COMPACT(op) || ((PyUnicodeObject*)(op))->data.any) */ + +#define PyUnicode_IS_READY(op) (((PyASCIIObject*)op)->state.ready) + +/* PyUnicode_READY() does less work than _PyUnicode_Ready() in the best + case. If the canonical representation is not yet set, it will still call + _PyUnicode_Ready(). + Returns 0 on success and -1 on errors. */ +#define PyUnicode_READY(op) \ + (assert(PyUnicode_Check(op)), \ + (PyUnicode_IS_READY(op) ? \ + 0 : _PyUnicode_Ready((PyObject *)(op)))) + +/* Return a maximum character value which is suitable for creating another + string based on op. This is always an approximation but more efficient + than iterating over the string. */ +#define PyUnicode_MAX_CHAR_VALUE(op) \ + (assert(PyUnicode_IS_READY(op)), \ + (PyUnicode_IS_ASCII(op) ? \ + (0x7f) : \ + (PyUnicode_KIND(op) == PyUnicode_1BYTE_KIND ? \ + (0xffU) : \ + (PyUnicode_KIND(op) == PyUnicode_2BYTE_KIND ? \ + (0xffffU) : \ + (0x10ffffU))))) + +#endif + +/* --- Constants ---------------------------------------------------------- */ + +/* This Unicode character will be used as replacement character during + decoding if the errors argument is set to "replace". Note: the + Unicode character U+FFFD is the official REPLACEMENT CHARACTER in + Unicode 3.0. */ + +#define Py_UNICODE_REPLACEMENT_CHARACTER ((Py_UCS4) 0xFFFD) + +/* === Public API ========================================================= */ + +/* --- Plain Py_UNICODE --------------------------------------------------- */ + +/* With PEP 393, this is the recommended way to allocate a new unicode object. + This function will allocate the object and its buffer in a single memory + block. Objects created using this function are not resizable. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_New( + Py_ssize_t size, /* Number of code points in the new string */ + Py_UCS4 maxchar /* maximum code point value in the string */ + ); +#endif + +/* Initializes the canonical string representation from the deprecated + wstr/Py_UNICODE representation. This function is used to convert Unicode + objects which were created using the old API to the new flexible format + introduced with PEP 393. + + Don't call this function directly, use the public PyUnicode_READY() macro + instead. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyUnicode_Ready( + PyObject *unicode /* Unicode object */ + ); +#endif + +/* Get a copy of a Unicode string. */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) _PyUnicode_Copy( + PyObject *unicode + ); +#endif + +/* Copy character from one unicode object into another, this function performs + character conversion when necessary and falls back to memcpy() if possible. + + Fail if to is too small (smaller than *how_many* or smaller than + len(from)-from_start), or if kind(from[from_start:from_start+how_many]) > + kind(to), or if *to* has more than 1 reference. + + Return the number of written character, or return -1 and raise an exception + on error. + + Pseudo-code: + + how_many = min(how_many, len(from) - from_start) + to[to_start:to_start+how_many] = from[from_start:from_start+how_many] + return how_many + + Note: The function doesn't write a terminating null character. + */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) PyUnicode_CopyCharacters( + PyObject *to, + Py_ssize_t to_start, + PyObject *from, + Py_ssize_t from_start, + Py_ssize_t how_many + ); + +/* Unsafe version of PyUnicode_CopyCharacters(): don't check arguments and so + may crash if parameters are invalid (e.g. if the output string + is too short). */ +PyAPI_FUNC(void) _PyUnicode_FastCopyCharacters( + PyObject *to, + Py_ssize_t to_start, + PyObject *from, + Py_ssize_t from_start, + Py_ssize_t how_many + ); +#endif + +#ifndef Py_LIMITED_API +/* Fill a string with a character: write fill_char into + unicode[start:start+length]. + + Fail if fill_char is bigger than the string maximum character, or if the + string has more than 1 reference. + + Return the number of written character, or return -1 and raise an exception + on error. */ +PyAPI_FUNC(Py_ssize_t) PyUnicode_Fill( + PyObject *unicode, + Py_ssize_t start, + Py_ssize_t length, + Py_UCS4 fill_char + ); + +/* Unsafe version of PyUnicode_Fill(): don't check arguments and so may crash + if parameters are invalid (e.g. if length is longer than the string). */ +PyAPI_FUNC(void) _PyUnicode_FastFill( + PyObject *unicode, + Py_ssize_t start, + Py_ssize_t length, + Py_UCS4 fill_char + ); +#endif + +/* Create a Unicode Object from the Py_UNICODE buffer u of the given + size. + + u may be NULL which causes the contents to be undefined. It is the + user's responsibility to fill in the needed data afterwards. Note + that modifying the Unicode object contents after construction is + only allowed if u was set to NULL. + + The buffer is copied into the new object. */ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_FromUnicode( + const Py_UNICODE *u, /* Unicode buffer */ + Py_ssize_t size /* size of buffer */ + ) /* Py_DEPRECATED(3.3) */; +#endif + +/* Similar to PyUnicode_FromUnicode(), but u points to UTF-8 encoded bytes */ +PyAPI_FUNC(PyObject*) PyUnicode_FromStringAndSize( + const char *u, /* UTF-8 encoded string */ + Py_ssize_t size /* size of buffer */ + ); + +/* Similar to PyUnicode_FromUnicode(), but u points to null-terminated + UTF-8 encoded bytes. The size is determined with strlen(). */ +PyAPI_FUNC(PyObject*) PyUnicode_FromString( + const char *u /* UTF-8 encoded string */ + ); + +#ifndef Py_LIMITED_API +/* Create a new string from a buffer of Py_UCS1, Py_UCS2 or Py_UCS4 characters. + Scan the string to find the maximum character. */ +PyAPI_FUNC(PyObject*) PyUnicode_FromKindAndData( + int kind, + const void *buffer, + Py_ssize_t size); + +/* Create a new string from a buffer of ASCII characters. + WARNING: Don't check if the string contains any non-ASCII character. */ +PyAPI_FUNC(PyObject*) _PyUnicode_FromASCII( + const char *buffer, + Py_ssize_t size); +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject*) PyUnicode_Substring( + PyObject *str, + Py_ssize_t start, + Py_ssize_t end); +#endif + +#ifndef Py_LIMITED_API +/* Compute the maximum character of the substring unicode[start:end]. + Return 127 for an empty string. */ +PyAPI_FUNC(Py_UCS4) _PyUnicode_FindMaxChar ( + PyObject *unicode, + Py_ssize_t start, + Py_ssize_t end); +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* Copy the string into a UCS4 buffer including the null character if copy_null + is set. Return NULL and raise an exception on error. Raise a SystemError if + the buffer is smaller than the string. Return buffer on success. + + buflen is the length of the buffer in (Py_UCS4) characters. */ +PyAPI_FUNC(Py_UCS4*) PyUnicode_AsUCS4( + PyObject *unicode, + Py_UCS4* buffer, + Py_ssize_t buflen, + int copy_null); + +/* Copy the string into a UCS4 buffer. A new buffer is allocated using + * PyMem_Malloc; if this fails, NULL is returned with a memory error + exception set. */ +PyAPI_FUNC(Py_UCS4*) PyUnicode_AsUCS4Copy(PyObject *unicode); +#endif + +#ifndef Py_LIMITED_API +/* Return a read-only pointer to the Unicode object's internal + Py_UNICODE buffer. + If the wchar_t/Py_UNICODE representation is not yet available, this + function will calculate it. */ + +PyAPI_FUNC(Py_UNICODE *) PyUnicode_AsUnicode( + PyObject *unicode /* Unicode object */ + ) /* Py_DEPRECATED(3.3) */; + +/* Similar to PyUnicode_AsUnicode(), but raises a ValueError if the string + contains null characters. */ +PyAPI_FUNC(const Py_UNICODE *) _PyUnicode_AsUnicode( + PyObject *unicode /* Unicode object */ + ); + +/* Return a read-only pointer to the Unicode object's internal + Py_UNICODE buffer and save the length at size. + If the wchar_t/Py_UNICODE representation is not yet available, this + function will calculate it. */ + +PyAPI_FUNC(Py_UNICODE *) PyUnicode_AsUnicodeAndSize( + PyObject *unicode, /* Unicode object */ + Py_ssize_t *size /* location where to save the length */ + ) /* Py_DEPRECATED(3.3) */; +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* Get the length of the Unicode object. */ + +PyAPI_FUNC(Py_ssize_t) PyUnicode_GetLength( + PyObject *unicode +); +#endif + +/* Get the number of Py_UNICODE units in the + string representation. */ + +PyAPI_FUNC(Py_ssize_t) PyUnicode_GetSize( + PyObject *unicode /* Unicode object */ + ) Py_DEPRECATED(3.3); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* Read a character from the string. */ + +PyAPI_FUNC(Py_UCS4) PyUnicode_ReadChar( + PyObject *unicode, + Py_ssize_t index + ); + +/* Write a character to the string. The string must have been created through + PyUnicode_New, must not be shared, and must not have been hashed yet. + + Return 0 on success, -1 on error. */ + +PyAPI_FUNC(int) PyUnicode_WriteChar( + PyObject *unicode, + Py_ssize_t index, + Py_UCS4 character + ); +#endif + +#ifndef Py_LIMITED_API +/* Get the maximum ordinal for a Unicode character. */ +PyAPI_FUNC(Py_UNICODE) PyUnicode_GetMax(void) Py_DEPRECATED(3.3); +#endif + +/* Resize a Unicode object. The length is the number of characters, except + if the kind of the string is PyUnicode_WCHAR_KIND: in this case, the length + is the number of Py_UNICODE characters. + + *unicode is modified to point to the new (resized) object and 0 + returned on success. + + Try to resize the string in place (which is usually faster than allocating + a new string and copy characters), or create a new string. + + Error handling is implemented as follows: an exception is set, -1 + is returned and *unicode left untouched. + + WARNING: The function doesn't check string content, the result may not be a + string in canonical representation. */ + +PyAPI_FUNC(int) PyUnicode_Resize( + PyObject **unicode, /* Pointer to the Unicode object */ + Py_ssize_t length /* New length */ + ); + +/* Decode obj to a Unicode object. + + bytes, bytearray and other bytes-like objects are decoded according to the + given encoding and error handler. The encoding and error handler can be + NULL to have the interface use UTF-8 and "strict". + + All other objects (including Unicode objects) raise an exception. + + The API returns NULL in case of an error. The caller is responsible + for decref'ing the returned objects. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_FromEncodedObject( + PyObject *obj, /* Object */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ); + +/* Copy an instance of a Unicode subtype to a new true Unicode object if + necessary. If obj is already a true Unicode object (not a subtype), return + the reference with *incremented* refcount. + + The API returns NULL in case of an error. The caller is responsible + for decref'ing the returned objects. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_FromObject( + PyObject *obj /* Object */ + ); + +PyAPI_FUNC(PyObject *) PyUnicode_FromFormatV( + const char *format, /* ASCII-encoded string */ + va_list vargs + ); +PyAPI_FUNC(PyObject *) PyUnicode_FromFormat( + const char *format, /* ASCII-encoded string */ + ... + ); + +#ifndef Py_LIMITED_API +typedef struct { + PyObject *buffer; + void *data; + enum PyUnicode_Kind kind; + Py_UCS4 maxchar; + Py_ssize_t size; + Py_ssize_t pos; + + /* minimum number of allocated characters (default: 0) */ + Py_ssize_t min_length; + + /* minimum character (default: 127, ASCII) */ + Py_UCS4 min_char; + + /* If non-zero, overallocate the buffer (default: 0). */ + unsigned char overallocate; + + /* If readonly is 1, buffer is a shared string (cannot be modified) + and size is set to 0. */ + unsigned char readonly; +} _PyUnicodeWriter ; + +/* Initialize a Unicode writer. + * + * By default, the minimum buffer size is 0 character and overallocation is + * disabled. Set min_length, min_char and overallocate attributes to control + * the allocation of the buffer. */ +PyAPI_FUNC(void) +_PyUnicodeWriter_Init(_PyUnicodeWriter *writer); + +/* Prepare the buffer to write 'length' characters + with the specified maximum character. + + Return 0 on success, raise an exception and return -1 on error. */ +#define _PyUnicodeWriter_Prepare(WRITER, LENGTH, MAXCHAR) \ + (((MAXCHAR) <= (WRITER)->maxchar \ + && (LENGTH) <= (WRITER)->size - (WRITER)->pos) \ + ? 0 \ + : (((LENGTH) == 0) \ + ? 0 \ + : _PyUnicodeWriter_PrepareInternal((WRITER), (LENGTH), (MAXCHAR)))) + +/* Don't call this function directly, use the _PyUnicodeWriter_Prepare() macro + instead. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer, + Py_ssize_t length, Py_UCS4 maxchar); + +/* Prepare the buffer to have at least the kind KIND. + For example, kind=PyUnicode_2BYTE_KIND ensures that the writer will + support characters in range U+000-U+FFFF. + + Return 0 on success, raise an exception and return -1 on error. */ +#define _PyUnicodeWriter_PrepareKind(WRITER, KIND) \ + (assert((KIND) != PyUnicode_WCHAR_KIND), \ + (KIND) <= (WRITER)->kind \ + ? 0 \ + : _PyUnicodeWriter_PrepareKindInternal((WRITER), (KIND))) + +/* Don't call this function directly, use the _PyUnicodeWriter_PrepareKind() + macro instead. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer, + enum PyUnicode_Kind kind); + +/* Append a Unicode character. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, + Py_UCS4 ch + ); + +/* Append a Unicode string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, + PyObject *str /* Unicode string */ + ); + +/* Append a substring of a Unicode string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, + PyObject *str, /* Unicode string */ + Py_ssize_t start, + Py_ssize_t end + ); + +/* Append an ASCII-encoded byte string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer, + const char *str, /* ASCII-encoded byte string */ + Py_ssize_t len /* number of bytes, or -1 if unknown */ + ); + +/* Append a latin1-encoded byte string. + Return 0 on success, raise an exception and return -1 on error. */ +PyAPI_FUNC(int) +_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer, + const char *str, /* latin1-encoded byte string */ + Py_ssize_t len /* length in bytes */ + ); + +/* Get the value of the writer as a Unicode string. Clear the + buffer of the writer. Raise an exception and return NULL + on error. */ +PyAPI_FUNC(PyObject *) +_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer); + +/* Deallocate memory of a writer (clear its internal buffer). */ +PyAPI_FUNC(void) +_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer); +#endif + +#ifndef Py_LIMITED_API +/* Format the object based on the format_spec, as defined in PEP 3101 + (Advanced String Formatting). */ +PyAPI_FUNC(int) _PyUnicode_FormatAdvancedWriter( + _PyUnicodeWriter *writer, + PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, + Py_ssize_t end); +#endif + +PyAPI_FUNC(void) PyUnicode_InternInPlace(PyObject **); +PyAPI_FUNC(void) PyUnicode_InternImmortal(PyObject **); +PyAPI_FUNC(PyObject *) PyUnicode_InternFromString( + const char *u /* UTF-8 encoded string */ + ); +#ifndef Py_LIMITED_API +PyAPI_FUNC(void) _Py_ReleaseInternedUnicodeStrings(void); +#endif + +/* Use only if you know it's a string */ +#define PyUnicode_CHECK_INTERNED(op) \ + (((PyASCIIObject *)(op))->state.interned) + +/* --- wchar_t support for platforms which support it --------------------- */ + +#ifdef HAVE_WCHAR_H + +/* Create a Unicode Object from the wchar_t buffer w of the given + size. + + The buffer is copied into the new object. */ + +PyAPI_FUNC(PyObject*) PyUnicode_FromWideChar( + const wchar_t *w, /* wchar_t buffer */ + Py_ssize_t size /* size of buffer */ + ); + +/* Copies the Unicode Object contents into the wchar_t buffer w. At + most size wchar_t characters are copied. + + Note that the resulting wchar_t string may or may not be + 0-terminated. It is the responsibility of the caller to make sure + that the wchar_t string is 0-terminated in case this is required by + the application. + + Returns the number of wchar_t characters copied (excluding a + possibly trailing 0-termination character) or -1 in case of an + error. */ + +PyAPI_FUNC(Py_ssize_t) PyUnicode_AsWideChar( + PyObject *unicode, /* Unicode object */ + wchar_t *w, /* wchar_t buffer */ + Py_ssize_t size /* size of buffer */ + ); + +/* Convert the Unicode object to a wide character string. The output string + always ends with a nul character. If size is not NULL, write the number of + wide characters (excluding the null character) into *size. + + Returns a buffer allocated by PyMem_Malloc() (use PyMem_Free() to free it) + on success. On error, returns NULL, *size is undefined and raises a + MemoryError. */ + +PyAPI_FUNC(wchar_t*) PyUnicode_AsWideCharString( + PyObject *unicode, /* Unicode object */ + Py_ssize_t *size /* number of characters of the result */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(void*) _PyUnicode_AsKind(PyObject *s, unsigned int kind); +#endif + +#endif + +/* --- Unicode ordinals --------------------------------------------------- */ + +/* Create a Unicode Object from the given Unicode code point ordinal. + + The ordinal must be in range(0x110000). A ValueError is + raised in case it is not. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_FromOrdinal(int ordinal); + +/* --- Free-list management ----------------------------------------------- */ + +/* Clear the free list used by the Unicode implementation. + + This can be used to release memory used for objects on the free + list back to the Python memory allocator. + +*/ + +PyAPI_FUNC(int) PyUnicode_ClearFreeList(void); + +/* === Builtin Codecs ===================================================== + + Many of these APIs take two arguments encoding and errors. These + parameters encoding and errors have the same semantics as the ones + of the builtin str() API. + + Setting encoding to NULL causes the default encoding (UTF-8) to be used. + + Error handling is set by errors which may also be set to NULL + meaning to use the default handling defined for the codec. Default + error handling for all builtin codecs is "strict" (ValueErrors are + raised). + + The codecs all use a similar interface. Only deviation from the + generic ones are documented. + +*/ + +/* --- Manage the default encoding ---------------------------------------- */ + +/* Returns a pointer to the default encoding (UTF-8) of the + Unicode object unicode and the size of the encoded representation + in bytes stored in *size. + + In case of an error, no *size is set. + + This function caches the UTF-8 encoded string in the unicodeobject + and subsequent calls will return the same string. The memory is released + when the unicodeobject is deallocated. + + _PyUnicode_AsStringAndSize is a #define for PyUnicode_AsUTF8AndSize to + support the previous internal function with the same behaviour. + + *** This API is for interpreter INTERNAL USE ONLY and will likely + *** be removed or changed in the future. + + *** If you need to access the Unicode object as UTF-8 bytes string, + *** please use PyUnicode_AsUTF8String() instead. +*/ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize( + PyObject *unicode, + Py_ssize_t *size); +#define _PyUnicode_AsStringAndSize PyUnicode_AsUTF8AndSize +#endif + +/* Returns a pointer to the default encoding (UTF-8) of the + Unicode object unicode. + + Like PyUnicode_AsUTF8AndSize(), this also caches the UTF-8 representation + in the unicodeobject. + + _PyUnicode_AsString is a #define for PyUnicode_AsUTF8 to + support the previous internal function with the same behaviour. + + Use of this API is DEPRECATED since no size information can be + extracted from the returned data. + + *** This API is for interpreter INTERNAL USE ONLY and will likely + *** be removed or changed for Python 3.1. + + *** If you need to access the Unicode object as UTF-8 bytes string, + *** please use PyUnicode_AsUTF8String() instead. + +*/ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(const char *) PyUnicode_AsUTF8(PyObject *unicode); +#define _PyUnicode_AsString PyUnicode_AsUTF8 +#endif + +/* Returns "utf-8". */ + +PyAPI_FUNC(const char*) PyUnicode_GetDefaultEncoding(void); + +/* --- Generic Codecs ----------------------------------------------------- */ + +/* Create a Unicode object by decoding the encoded string s of the + given size. */ + +PyAPI_FUNC(PyObject*) PyUnicode_Decode( + const char *s, /* encoded string */ + Py_ssize_t size, /* size of buffer */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ); + +/* Decode a Unicode object unicode and return the result as Python + object. + + This API is DEPRECATED. The only supported standard encoding is rot13. + Use PyCodec_Decode() to decode with rot13 and non-standard codecs + that decode from str. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsDecodedObject( + PyObject *unicode, /* Unicode object */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.6); + +/* Decode a Unicode object unicode and return the result as Unicode + object. + + This API is DEPRECATED. The only supported standard encoding is rot13. + Use PyCodec_Decode() to decode with rot13 and non-standard codecs + that decode from str to str. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsDecodedUnicode( + PyObject *unicode, /* Unicode object */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.6); + +/* Encodes a Py_UNICODE buffer of the given size and returns a + Python string object. */ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_Encode( + const Py_UNICODE *s, /* Unicode char buffer */ + Py_ssize_t size, /* number of Py_UNICODE chars to encode */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +#endif + +/* Encodes a Unicode object and returns the result as Python + object. + + This API is DEPRECATED. It is superseded by PyUnicode_AsEncodedString() + since all standard encodings (except rot13) encode str to bytes. + Use PyCodec_Encode() for encoding with rot13 and non-standard codecs + that encode form str to non-bytes. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsEncodedObject( + PyObject *unicode, /* Unicode object */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.6); + +/* Encodes a Unicode object and returns the result as Python string + object. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsEncodedString( + PyObject *unicode, /* Unicode object */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ); + +/* Encodes a Unicode object and returns the result as Unicode + object. + + This API is DEPRECATED. The only supported standard encodings is rot13. + Use PyCodec_Encode() to encode with rot13 and non-standard codecs + that encode from str to str. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsEncodedUnicode( + PyObject *unicode, /* Unicode object */ + const char *encoding, /* encoding */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.6); + +/* Build an encoding map. */ + +PyAPI_FUNC(PyObject*) PyUnicode_BuildEncodingMap( + PyObject* string /* 256 character map */ + ); + +/* --- UTF-7 Codecs ------------------------------------------------------- */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF7( + const char *string, /* UTF-7 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF7Stateful( + const char *string, /* UTF-7 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + Py_ssize_t *consumed /* bytes consumed */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF7( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* number of Py_UNICODE chars to encode */ + int base64SetO, /* Encode RFC2152 Set O characters in base64 */ + int base64WhiteSpace, /* Encode whitespace (sp, ht, nl, cr) in base64 */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF7( + PyObject *unicode, /* Unicode object */ + int base64SetO, /* Encode RFC2152 Set O characters in base64 */ + int base64WhiteSpace, /* Encode whitespace (sp, ht, nl, cr) in base64 */ + const char *errors /* error handling */ + ); +#endif + +/* --- UTF-8 Codecs ------------------------------------------------------- */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF8( + const char *string, /* UTF-8 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF8Stateful( + const char *string, /* UTF-8 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + Py_ssize_t *consumed /* bytes consumed */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_AsUTF8String( + PyObject *unicode /* Unicode object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) _PyUnicode_AsUTF8String( + PyObject *unicode, + const char *errors); + +PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF8( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* number of Py_UNICODE chars to encode */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +#endif + +/* --- UTF-32 Codecs ------------------------------------------------------ */ + +/* Decodes length bytes from a UTF-32 encoded buffer string and returns + the corresponding Unicode object. + + errors (if non-NULL) defines the error handling. It defaults + to "strict". + + If byteorder is non-NULL, the decoder starts decoding using the + given byte order: + + *byteorder == -1: little endian + *byteorder == 0: native order + *byteorder == 1: big endian + + In native mode, the first four bytes of the stream are checked for a + BOM mark. If found, the BOM mark is analysed, the byte order + adjusted and the BOM skipped. In the other modes, no BOM mark + interpretation is done. After completion, *byteorder is set to the + current byte order at the end of input data. + + If byteorder is NULL, the codec starts in native order mode. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF32( + const char *string, /* UTF-32 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + int *byteorder /* pointer to byteorder to use + 0=native;-1=LE,1=BE; updated on + exit */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF32Stateful( + const char *string, /* UTF-32 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + int *byteorder, /* pointer to byteorder to use + 0=native;-1=LE,1=BE; updated on + exit */ + Py_ssize_t *consumed /* bytes consumed */ + ); + +/* Returns a Python string using the UTF-32 encoding in native byte + order. The string always starts with a BOM mark. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsUTF32String( + PyObject *unicode /* Unicode object */ + ); + +/* Returns a Python string object holding the UTF-32 encoded value of + the Unicode data. + + If byteorder is not 0, output is written according to the following + byte order: + + byteorder == -1: little endian + byteorder == 0: native byte order (writes a BOM mark) + byteorder == 1: big endian + + If byteorder is 0, the output string will always start with the + Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is + prepended. + +*/ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF32( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* number of Py_UNICODE chars to encode */ + const char *errors, /* error handling */ + int byteorder /* byteorder to use 0=BOM+native;-1=LE,1=BE */ + ) Py_DEPRECATED(3.3); +PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF32( + PyObject *object, /* Unicode object */ + const char *errors, /* error handling */ + int byteorder /* byteorder to use 0=BOM+native;-1=LE,1=BE */ + ); +#endif + +/* --- UTF-16 Codecs ------------------------------------------------------ */ + +/* Decodes length bytes from a UTF-16 encoded buffer string and returns + the corresponding Unicode object. + + errors (if non-NULL) defines the error handling. It defaults + to "strict". + + If byteorder is non-NULL, the decoder starts decoding using the + given byte order: + + *byteorder == -1: little endian + *byteorder == 0: native order + *byteorder == 1: big endian + + In native mode, the first two bytes of the stream are checked for a + BOM mark. If found, the BOM mark is analysed, the byte order + adjusted and the BOM skipped. In the other modes, no BOM mark + interpretation is done. After completion, *byteorder is set to the + current byte order at the end of input data. + + If byteorder is NULL, the codec starts in native order mode. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF16( + const char *string, /* UTF-16 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + int *byteorder /* pointer to byteorder to use + 0=native;-1=LE,1=BE; updated on + exit */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUTF16Stateful( + const char *string, /* UTF-16 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + int *byteorder, /* pointer to byteorder to use + 0=native;-1=LE,1=BE; updated on + exit */ + Py_ssize_t *consumed /* bytes consumed */ + ); + +/* Returns a Python string using the UTF-16 encoding in native byte + order. The string always starts with a BOM mark. */ + +PyAPI_FUNC(PyObject*) PyUnicode_AsUTF16String( + PyObject *unicode /* Unicode object */ + ); + +/* Returns a Python string object holding the UTF-16 encoded value of + the Unicode data. + + If byteorder is not 0, output is written according to the following + byte order: + + byteorder == -1: little endian + byteorder == 0: native byte order (writes a BOM mark) + byteorder == 1: big endian + + If byteorder is 0, the output string will always start with the + Unicode BOM mark (U+FEFF). In the other two modes, no BOM mark is + prepended. + + Note that Py_UNICODE data is being interpreted as UTF-16 reduced to + UCS-2. This trick makes it possible to add full UTF-16 capabilities + at a later point without compromising the APIs. + +*/ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeUTF16( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* number of Py_UNICODE chars to encode */ + const char *errors, /* error handling */ + int byteorder /* byteorder to use 0=BOM+native;-1=LE,1=BE */ + ) Py_DEPRECATED(3.3); +PyAPI_FUNC(PyObject*) _PyUnicode_EncodeUTF16( + PyObject* unicode, /* Unicode object */ + const char *errors, /* error handling */ + int byteorder /* byteorder to use 0=BOM+native;-1=LE,1=BE */ + ); +#endif + +/* --- Unicode-Escape Codecs ---------------------------------------------- */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeUnicodeEscape( + const char *string, /* Unicode-Escape encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +#ifndef Py_LIMITED_API +/* Helper for PyUnicode_DecodeUnicodeEscape that detects invalid escape + chars. */ +PyAPI_FUNC(PyObject*) _PyUnicode_DecodeUnicodeEscape( + const char *string, /* Unicode-Escape encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + const char **first_invalid_escape /* on return, points to first + invalid escaped char in + string. */ +); +#endif + +PyAPI_FUNC(PyObject*) PyUnicode_AsUnicodeEscapeString( + PyObject *unicode /* Unicode object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeUnicodeEscape( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length /* Number of Py_UNICODE chars to encode */ + ) Py_DEPRECATED(3.3); +#endif + +/* --- Raw-Unicode-Escape Codecs ------------------------------------------ */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeRawUnicodeEscape( + const char *string, /* Raw-Unicode-Escape encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_AsRawUnicodeEscapeString( + PyObject *unicode /* Unicode object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeRawUnicodeEscape( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length /* Number of Py_UNICODE chars to encode */ + ) Py_DEPRECATED(3.3); +#endif + +/* --- Unicode Internal Codec --------------------------------------------- + + Only for internal use in _codecsmodule.c */ + +#ifndef Py_LIMITED_API +PyObject *_PyUnicode_DecodeUnicodeInternal( + const char *string, + Py_ssize_t length, + const char *errors + ); +#endif + +/* --- Latin-1 Codecs ----------------------------------------------------- + + Note: Latin-1 corresponds to the first 256 Unicode ordinals. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeLatin1( + const char *string, /* Latin-1 encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_AsLatin1String( + PyObject *unicode /* Unicode object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) _PyUnicode_AsLatin1String( + PyObject* unicode, + const char* errors); + +PyAPI_FUNC(PyObject*) PyUnicode_EncodeLatin1( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +#endif + +/* --- ASCII Codecs ------------------------------------------------------- + + Only 7-bit ASCII data is excepted. All other codes generate errors. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeASCII( + const char *string, /* ASCII encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_AsASCIIString( + PyObject *unicode /* Unicode object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) _PyUnicode_AsASCIIString( + PyObject* unicode, + const char* errors); + +PyAPI_FUNC(PyObject*) PyUnicode_EncodeASCII( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +#endif + +/* --- Character Map Codecs ----------------------------------------------- + + This codec uses mappings to encode and decode characters. + + Decoding mappings must map byte ordinals (integers in the range from 0 to + 255) to Unicode strings, integers (which are then interpreted as Unicode + ordinals) or None. Unmapped data bytes (ones which cause a LookupError) + as well as mapped to None, 0xFFFE or '\ufffe' are treated as "undefined + mapping" and cause an error. + + Encoding mappings must map Unicode ordinal integers to bytes objects, + integers in the range from 0 to 255 or None. Unmapped character + ordinals (ones which cause a LookupError) as well as mapped to + None are treated as "undefined mapping" and cause an error. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeCharmap( + const char *string, /* Encoded string */ + Py_ssize_t length, /* size of string */ + PyObject *mapping, /* decoding mapping */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_AsCharmapString( + PyObject *unicode, /* Unicode object */ + PyObject *mapping /* encoding mapping */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeCharmap( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ + PyObject *mapping, /* encoding mapping */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +PyAPI_FUNC(PyObject*) _PyUnicode_EncodeCharmap( + PyObject *unicode, /* Unicode object */ + PyObject *mapping, /* encoding mapping */ + const char *errors /* error handling */ + ); +#endif + +/* Translate a Py_UNICODE buffer of the given length by applying a + character mapping table to it and return the resulting Unicode + object. + + The mapping table must map Unicode ordinal integers to Unicode strings, + Unicode ordinal integers or None (causing deletion of the character). + + Mapping tables may be dictionaries or sequences. Unmapped character + ordinals (ones which cause a LookupError) are left untouched and + are copied as-is. + +*/ + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) PyUnicode_TranslateCharmap( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ + PyObject *table, /* Translate table */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +#endif + +#ifdef MS_WINDOWS + +/* --- MBCS codecs for Windows -------------------------------------------- */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeMBCS( + const char *string, /* MBCS encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors /* error handling */ + ); + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeMBCSStateful( + const char *string, /* MBCS encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + Py_ssize_t *consumed /* bytes consumed */ + ); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject*) PyUnicode_DecodeCodePageStateful( + int code_page, /* code page number */ + const char *string, /* encoded string */ + Py_ssize_t length, /* size of string */ + const char *errors, /* error handling */ + Py_ssize_t *consumed /* bytes consumed */ + ); +#endif + +PyAPI_FUNC(PyObject*) PyUnicode_AsMBCSString( + PyObject *unicode /* Unicode object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) PyUnicode_EncodeMBCS( + const Py_UNICODE *data, /* Unicode char buffer */ + Py_ssize_t length, /* number of Py_UNICODE chars to encode */ + const char *errors /* error handling */ + ) Py_DEPRECATED(3.3); +#endif + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +PyAPI_FUNC(PyObject*) PyUnicode_EncodeCodePage( + int code_page, /* code page number */ + PyObject *unicode, /* Unicode object */ + const char *errors /* error handling */ + ); +#endif + +#endif /* MS_WINDOWS */ + +#ifndef Py_LIMITED_API +/* --- Decimal Encoder ---------------------------------------------------- */ + +/* Takes a Unicode string holding a decimal value and writes it into + an output buffer using standard ASCII digit codes. + + The output buffer has to provide at least length+1 bytes of storage + area. The output string is 0-terminated. + + The encoder converts whitespace to ' ', decimal characters to their + corresponding ASCII digit and all other Latin-1 characters except + \0 as-is. Characters outside this range (Unicode ordinals 1-256) + are treated as errors. This includes embedded NULL bytes. + + Error handling is defined by the errors argument: + + NULL or "strict": raise a ValueError + "ignore": ignore the wrong characters (these are not copied to the + output buffer) + "replace": replaces illegal characters with '?' + + Returns 0 on success, -1 on failure. + +*/ + +PyAPI_FUNC(int) PyUnicode_EncodeDecimal( + Py_UNICODE *s, /* Unicode buffer */ + Py_ssize_t length, /* Number of Py_UNICODE chars to encode */ + char *output, /* Output buffer; must have size >= length */ + const char *errors /* error handling */ + ) /* Py_DEPRECATED(3.3) */; + +/* Transforms code points that have decimal digit property to the + corresponding ASCII digit code points. + + Returns a new Unicode string on success, NULL on failure. +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_TransformDecimalToASCII( + Py_UNICODE *s, /* Unicode buffer */ + Py_ssize_t length /* Number of Py_UNICODE chars to transform */ + ) /* Py_DEPRECATED(3.3) */; + +/* Coverts a Unicode object holding a decimal value to an ASCII string + for using in int, float and complex parsers. + Transforms code points that have decimal digit property to the + corresponding ASCII digit code points. Transforms spaces to ASCII. + Transforms code points starting from the first non-ASCII code point that + is neither a decimal digit nor a space to the end into '?'. */ + +PyAPI_FUNC(PyObject*) _PyUnicode_TransformDecimalAndSpaceToASCII( + PyObject *unicode /* Unicode object */ + ); +#endif + +/* --- Locale encoding --------------------------------------------------- */ + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* Decode a string from the current locale encoding. The decoder is strict if + *surrogateescape* is equal to zero, otherwise it uses the 'surrogateescape' + error handler (PEP 383) to escape undecodable bytes. If a byte sequence can + be decoded as a surrogate character and *surrogateescape* is not equal to + zero, the byte sequence is escaped using the 'surrogateescape' error handler + instead of being decoded. *str* must end with a null character but cannot + contain embedded null characters. */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeLocaleAndSize( + const char *str, + Py_ssize_t len, + const char *errors); + +/* Similar to PyUnicode_DecodeLocaleAndSize(), but compute the string + length using strlen(). */ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeLocale( + const char *str, + const char *errors); + +/* Encode a Unicode object to the current locale encoding. The encoder is + strict is *surrogateescape* is equal to zero, otherwise the + "surrogateescape" error handler is used. Return a bytes object. The string + cannot contain embedded null characters. */ + +PyAPI_FUNC(PyObject*) PyUnicode_EncodeLocale( + PyObject *unicode, + const char *errors + ); +#endif + +/* --- File system encoding ---------------------------------------------- */ + +/* ParseTuple converter: encode str objects to bytes using + PyUnicode_EncodeFSDefault(); bytes objects are output as-is. */ + +PyAPI_FUNC(int) PyUnicode_FSConverter(PyObject*, void*); + +/* ParseTuple converter: decode bytes objects to unicode using + PyUnicode_DecodeFSDefaultAndSize(); str objects are output as-is. */ + +PyAPI_FUNC(int) PyUnicode_FSDecoder(PyObject*, void*); + +/* Decode a null-terminated string using Py_FileSystemDefaultEncoding + and the "surrogateescape" error handler. + + If Py_FileSystemDefaultEncoding is not set, fall back to the locale + encoding. + + Use PyUnicode_DecodeFSDefaultAndSize() if the string length is known. +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeFSDefault( + const char *s /* encoded string */ + ); + +/* Decode a string using Py_FileSystemDefaultEncoding + and the "surrogateescape" error handler. + + If Py_FileSystemDefaultEncoding is not set, fall back to the locale + encoding. +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_DecodeFSDefaultAndSize( + const char *s, /* encoded string */ + Py_ssize_t size /* size */ + ); + +/* Encode a Unicode object to Py_FileSystemDefaultEncoding with the + "surrogateescape" error handler, and return bytes. + + If Py_FileSystemDefaultEncoding is not set, fall back to the locale + encoding. +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_EncodeFSDefault( + PyObject *unicode + ); + +/* --- Methods & Slots ---------------------------------------------------- + + These are capable of handling Unicode objects and strings on input + (we refer to them as strings in the descriptions) and return + Unicode objects or integers as appropriate. */ + +/* Concat two strings giving a new Unicode string. */ + +PyAPI_FUNC(PyObject*) PyUnicode_Concat( + PyObject *left, /* Left string */ + PyObject *right /* Right string */ + ); + +/* Concat two strings and put the result in *pleft + (sets *pleft to NULL on error) */ + +PyAPI_FUNC(void) PyUnicode_Append( + PyObject **pleft, /* Pointer to left string */ + PyObject *right /* Right string */ + ); + +/* Concat two strings, put the result in *pleft and drop the right object + (sets *pleft to NULL on error) */ + +PyAPI_FUNC(void) PyUnicode_AppendAndDel( + PyObject **pleft, /* Pointer to left string */ + PyObject *right /* Right string */ + ); + +/* Split a string giving a list of Unicode strings. + + If sep is NULL, splitting will be done at all whitespace + substrings. Otherwise, splits occur at the given separator. + + At most maxsplit splits will be done. If negative, no limit is set. + + Separators are not included in the resulting list. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_Split( + PyObject *s, /* String to split */ + PyObject *sep, /* String separator */ + Py_ssize_t maxsplit /* Maxsplit count */ + ); + +/* Dito, but split at line breaks. + + CRLF is considered to be one line break. Line breaks are not + included in the resulting list. */ + +PyAPI_FUNC(PyObject*) PyUnicode_Splitlines( + PyObject *s, /* String to split */ + int keepends /* If true, line end markers are included */ + ); + +/* Partition a string using a given separator. */ + +PyAPI_FUNC(PyObject*) PyUnicode_Partition( + PyObject *s, /* String to partition */ + PyObject *sep /* String separator */ + ); + +/* Partition a string using a given separator, searching from the end of the + string. */ + +PyAPI_FUNC(PyObject*) PyUnicode_RPartition( + PyObject *s, /* String to partition */ + PyObject *sep /* String separator */ + ); + +/* Split a string giving a list of Unicode strings. + + If sep is NULL, splitting will be done at all whitespace + substrings. Otherwise, splits occur at the given separator. + + At most maxsplit splits will be done. But unlike PyUnicode_Split + PyUnicode_RSplit splits from the end of the string. If negative, + no limit is set. + + Separators are not included in the resulting list. + +*/ + +PyAPI_FUNC(PyObject*) PyUnicode_RSplit( + PyObject *s, /* String to split */ + PyObject *sep, /* String separator */ + Py_ssize_t maxsplit /* Maxsplit count */ + ); + +/* Translate a string by applying a character mapping table to it and + return the resulting Unicode object. + + The mapping table must map Unicode ordinal integers to Unicode strings, + Unicode ordinal integers or None (causing deletion of the character). + + Mapping tables may be dictionaries or sequences. Unmapped character + ordinals (ones which cause a LookupError) are left untouched and + are copied as-is. + +*/ + +PyAPI_FUNC(PyObject *) PyUnicode_Translate( + PyObject *str, /* String */ + PyObject *table, /* Translate table */ + const char *errors /* error handling */ + ); + +/* Join a sequence of strings using the given separator and return + the resulting Unicode string. */ + +PyAPI_FUNC(PyObject*) PyUnicode_Join( + PyObject *separator, /* Separator string */ + PyObject *seq /* Sequence object */ + ); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyUnicode_JoinArray( + PyObject *separator, + PyObject *const *items, + Py_ssize_t seqlen + ); +#endif /* Py_LIMITED_API */ + +/* Return 1 if substr matches str[start:end] at the given tail end, 0 + otherwise. */ + +PyAPI_FUNC(Py_ssize_t) PyUnicode_Tailmatch( + PyObject *str, /* String */ + PyObject *substr, /* Prefix or Suffix string */ + Py_ssize_t start, /* Start index */ + Py_ssize_t end, /* Stop index */ + int direction /* Tail end: -1 prefix, +1 suffix */ + ); + +/* Return the first position of substr in str[start:end] using the + given search direction or -1 if not found. -2 is returned in case + an error occurred and an exception is set. */ + +PyAPI_FUNC(Py_ssize_t) PyUnicode_Find( + PyObject *str, /* String */ + PyObject *substr, /* Substring to find */ + Py_ssize_t start, /* Start index */ + Py_ssize_t end, /* Stop index */ + int direction /* Find direction: +1 forward, -1 backward */ + ); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 +/* Like PyUnicode_Find, but search for single character only. */ +PyAPI_FUNC(Py_ssize_t) PyUnicode_FindChar( + PyObject *str, + Py_UCS4 ch, + Py_ssize_t start, + Py_ssize_t end, + int direction + ); +#endif + +/* Count the number of occurrences of substr in str[start:end]. */ + +PyAPI_FUNC(Py_ssize_t) PyUnicode_Count( + PyObject *str, /* String */ + PyObject *substr, /* Substring to count */ + Py_ssize_t start, /* Start index */ + Py_ssize_t end /* Stop index */ + ); + +/* Replace at most maxcount occurrences of substr in str with replstr + and return the resulting Unicode object. */ + +PyAPI_FUNC(PyObject *) PyUnicode_Replace( + PyObject *str, /* String */ + PyObject *substr, /* Substring to find */ + PyObject *replstr, /* Substring to replace */ + Py_ssize_t maxcount /* Max. number of replacements to apply; + -1 = all */ + ); + +/* Compare two strings and return -1, 0, 1 for less than, equal, + greater than resp. + Raise an exception and return -1 on error. */ + +PyAPI_FUNC(int) PyUnicode_Compare( + PyObject *left, /* Left string */ + PyObject *right /* Right string */ + ); + +#ifndef Py_LIMITED_API +/* Test whether a unicode is equal to ASCII identifier. Return 1 if true, + 0 otherwise. The right argument must be ASCII identifier. + Any error occurs inside will be cleared before return. */ + +PyAPI_FUNC(int) _PyUnicode_EqualToASCIIId( + PyObject *left, /* Left string */ + _Py_Identifier *right /* Right identifier */ + ); +#endif + +/* Compare a Unicode object with C string and return -1, 0, 1 for less than, + equal, and greater than, respectively. It is best to pass only + ASCII-encoded strings, but the function interprets the input string as + ISO-8859-1 if it contains non-ASCII characters. + This function does not raise exceptions. */ + +PyAPI_FUNC(int) PyUnicode_CompareWithASCIIString( + PyObject *left, + const char *right /* ASCII-encoded string */ + ); + +#ifndef Py_LIMITED_API +/* Test whether a unicode is equal to ASCII string. Return 1 if true, + 0 otherwise. The right argument must be ASCII-encoded string. + Any error occurs inside will be cleared before return. */ + +PyAPI_FUNC(int) _PyUnicode_EqualToASCIIString( + PyObject *left, + const char *right /* ASCII-encoded string */ + ); +#endif + +/* Rich compare two strings and return one of the following: + + - NULL in case an exception was raised + - Py_True or Py_False for successful comparisons + - Py_NotImplemented in case the type combination is unknown + + Possible values for op: + + Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE + +*/ + +PyAPI_FUNC(PyObject *) PyUnicode_RichCompare( + PyObject *left, /* Left string */ + PyObject *right, /* Right string */ + int op /* Operation: Py_EQ, Py_NE, Py_GT, etc. */ + ); + +/* Apply an argument tuple or dictionary to a format string and return + the resulting Unicode string. */ + +PyAPI_FUNC(PyObject *) PyUnicode_Format( + PyObject *format, /* Format string */ + PyObject *args /* Argument tuple or dictionary */ + ); + +/* Checks whether element is contained in container and return 1/0 + accordingly. + + element has to coerce to a one element Unicode string. -1 is + returned in case of an error. */ + +PyAPI_FUNC(int) PyUnicode_Contains( + PyObject *container, /* Container string */ + PyObject *element /* Element string */ + ); + +/* Checks whether argument is a valid identifier. */ + +PyAPI_FUNC(int) PyUnicode_IsIdentifier(PyObject *s); + +#ifndef Py_LIMITED_API +/* Externally visible for str.strip(unicode) */ +PyAPI_FUNC(PyObject *) _PyUnicode_XStrip( + PyObject *self, + int striptype, + PyObject *sepobj + ); +#endif + +/* Using explicit passed-in values, insert the thousands grouping + into the string pointed to by buffer. For the argument descriptions, + see Objects/stringlib/localeutil.h */ +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) _PyUnicode_InsertThousandsGrouping( + PyObject *unicode, + Py_ssize_t index, + Py_ssize_t n_buffer, + void *digits, + Py_ssize_t n_digits, + Py_ssize_t min_width, + const char *grouping, + PyObject *thousands_sep, + Py_UCS4 *maxchar); +#endif +/* === Characters Type APIs =============================================== */ + +/* Helper array used by Py_UNICODE_ISSPACE(). */ + +#ifndef Py_LIMITED_API +PyAPI_DATA(const unsigned char) _Py_ascii_whitespace[]; + +/* These should not be used directly. Use the Py_UNICODE_IS* and + Py_UNICODE_TO* macros instead. + + These APIs are implemented in Objects/unicodectype.c. + +*/ + +PyAPI_FUNC(int) _PyUnicode_IsLowercase( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsUppercase( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsTitlecase( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsXidStart( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsXidContinue( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsWhitespace( + const Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsLinebreak( + const Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(Py_UCS4) _PyUnicode_ToLowercase( + Py_UCS4 ch /* Unicode character */ + ) /* Py_DEPRECATED(3.3) */; + +PyAPI_FUNC(Py_UCS4) _PyUnicode_ToUppercase( + Py_UCS4 ch /* Unicode character */ + ) /* Py_DEPRECATED(3.3) */; + +PyAPI_FUNC(Py_UCS4) _PyUnicode_ToTitlecase( + Py_UCS4 ch /* Unicode character */ + ) Py_DEPRECATED(3.3); + +PyAPI_FUNC(int) _PyUnicode_ToLowerFull( + Py_UCS4 ch, /* Unicode character */ + Py_UCS4 *res + ); + +PyAPI_FUNC(int) _PyUnicode_ToTitleFull( + Py_UCS4 ch, /* Unicode character */ + Py_UCS4 *res + ); + +PyAPI_FUNC(int) _PyUnicode_ToUpperFull( + Py_UCS4 ch, /* Unicode character */ + Py_UCS4 *res + ); + +PyAPI_FUNC(int) _PyUnicode_ToFoldedFull( + Py_UCS4 ch, /* Unicode character */ + Py_UCS4 *res + ); + +PyAPI_FUNC(int) _PyUnicode_IsCaseIgnorable( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsCased( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_ToDecimalDigit( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_ToDigit( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(double) _PyUnicode_ToNumeric( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsDecimalDigit( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsDigit( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsNumeric( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsPrintable( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(int) _PyUnicode_IsAlpha( + Py_UCS4 ch /* Unicode character */ + ); + +PyAPI_FUNC(size_t) Py_UNICODE_strlen( + const Py_UNICODE *u + ) Py_DEPRECATED(3.3); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strcpy( + Py_UNICODE *s1, + const Py_UNICODE *s2) Py_DEPRECATED(3.3); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strcat( + Py_UNICODE *s1, const Py_UNICODE *s2) Py_DEPRECATED(3.3); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strncpy( + Py_UNICODE *s1, + const Py_UNICODE *s2, + size_t n) Py_DEPRECATED(3.3); + +PyAPI_FUNC(int) Py_UNICODE_strcmp( + const Py_UNICODE *s1, + const Py_UNICODE *s2 + ) Py_DEPRECATED(3.3); + +PyAPI_FUNC(int) Py_UNICODE_strncmp( + const Py_UNICODE *s1, + const Py_UNICODE *s2, + size_t n + ) Py_DEPRECATED(3.3); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strchr( + const Py_UNICODE *s, + Py_UNICODE c + ) Py_DEPRECATED(3.3); + +PyAPI_FUNC(Py_UNICODE*) Py_UNICODE_strrchr( + const Py_UNICODE *s, + Py_UNICODE c + ) Py_DEPRECATED(3.3); + +PyAPI_FUNC(PyObject*) _PyUnicode_FormatLong(PyObject *, int, int, int); + +/* Create a copy of a unicode string ending with a nul character. Return NULL + and raise a MemoryError exception on memory allocation failure, otherwise + return a new allocated buffer (use PyMem_Free() to free the buffer). */ + +PyAPI_FUNC(Py_UNICODE*) PyUnicode_AsUnicodeCopy( + PyObject *unicode + ) Py_DEPRECATED(3.3); +#endif /* Py_LIMITED_API */ + +#if defined(Py_DEBUG) && !defined(Py_LIMITED_API) +PyAPI_FUNC(int) _PyUnicode_CheckConsistency( + PyObject *op, + int check_content); +#elif !defined(NDEBUG) +/* For asserts that call _PyUnicode_CheckConsistency(), which would + * otherwise be a problem when building with asserts but without Py_DEBUG. */ +#define _PyUnicode_CheckConsistency(op, check_content) PyUnicode_Check(op) +#endif + +#ifndef Py_LIMITED_API +/* Return an interned Unicode object for an Identifier; may fail if there is no memory.*/ +PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); +/* Clear all static strings. */ +PyAPI_FUNC(void) _PyUnicode_ClearStaticStrings(void); + +/* Fast equality check when the inputs are known to be exact unicode types + and where the hash values are equal (i.e. a very probable match) */ +PyAPI_FUNC(int) _PyUnicode_EQ(PyObject *, PyObject *); +#endif /* !Py_LIMITED_API */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_UNICODEOBJECT_H */ diff --git a/winvenv/Include/warnings.h b/winvenv/Include/warnings.h new file mode 100644 index 0000000..a675bb5 --- /dev/null +++ b/winvenv/Include/warnings.h @@ -0,0 +1,67 @@ +#ifndef Py_WARNINGS_H +#define Py_WARNINGS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject*) _PyWarnings_Init(void); +#endif + +PyAPI_FUNC(int) PyErr_WarnEx( + PyObject *category, + const char *message, /* UTF-8 encoded string */ + Py_ssize_t stack_level); +PyAPI_FUNC(int) PyErr_WarnFormat( + PyObject *category, + Py_ssize_t stack_level, + const char *format, /* ASCII-encoded string */ + ...); + +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 +/* Emit a ResourceWarning warning */ +PyAPI_FUNC(int) PyErr_ResourceWarning( + PyObject *source, + Py_ssize_t stack_level, + const char *format, /* ASCII-encoded string */ + ...); +#endif +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) PyErr_WarnExplicitObject( + PyObject *category, + PyObject *message, + PyObject *filename, + int lineno, + PyObject *module, + PyObject *registry); +#endif +PyAPI_FUNC(int) PyErr_WarnExplicit( + PyObject *category, + const char *message, /* UTF-8 encoded string */ + const char *filename, /* decoded from the filesystem encoding */ + int lineno, + const char *module, /* UTF-8 encoded string */ + PyObject *registry); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(int) +PyErr_WarnExplicitFormat(PyObject *category, + const char *filename, int lineno, + const char *module, PyObject *registry, + const char *format, ...); +#endif + +/* DEPRECATED: Use PyErr_WarnEx() instead. */ +#ifndef Py_LIMITED_API +#define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1) +#endif + +#ifndef Py_LIMITED_API +void _PyErr_WarnUnawaitedCoroutine(PyObject *coro); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* !Py_WARNINGS_H */ + diff --git a/winvenv/Include/weakrefobject.h b/winvenv/Include/weakrefobject.h new file mode 100644 index 0000000..1705156 --- /dev/null +++ b/winvenv/Include/weakrefobject.h @@ -0,0 +1,86 @@ +/* Weak references objects for Python. */ + +#ifndef Py_WEAKREFOBJECT_H +#define Py_WEAKREFOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct _PyWeakReference PyWeakReference; + +/* PyWeakReference is the base struct for the Python ReferenceType, ProxyType, + * and CallableProxyType. + */ +#ifndef Py_LIMITED_API +struct _PyWeakReference { + PyObject_HEAD + + /* The object to which this is a weak reference, or Py_None if none. + * Note that this is a stealth reference: wr_object's refcount is + * not incremented to reflect this pointer. + */ + PyObject *wr_object; + + /* A callable to invoke when wr_object dies, or NULL if none. */ + PyObject *wr_callback; + + /* A cache for wr_object's hash code. As usual for hashes, this is -1 + * if the hash code isn't known yet. + */ + Py_hash_t hash; + + /* If wr_object is weakly referenced, wr_object has a doubly-linked NULL- + * terminated list of weak references to it. These are the list pointers. + * If wr_object goes away, wr_object is set to Py_None, and these pointers + * have no meaning then. + */ + PyWeakReference *wr_prev; + PyWeakReference *wr_next; +}; +#endif + +PyAPI_DATA(PyTypeObject) _PyWeakref_RefType; +PyAPI_DATA(PyTypeObject) _PyWeakref_ProxyType; +PyAPI_DATA(PyTypeObject) _PyWeakref_CallableProxyType; + +#define PyWeakref_CheckRef(op) PyObject_TypeCheck(op, &_PyWeakref_RefType) +#define PyWeakref_CheckRefExact(op) \ + (Py_TYPE(op) == &_PyWeakref_RefType) +#define PyWeakref_CheckProxy(op) \ + ((Py_TYPE(op) == &_PyWeakref_ProxyType) || \ + (Py_TYPE(op) == &_PyWeakref_CallableProxyType)) + +#define PyWeakref_Check(op) \ + (PyWeakref_CheckRef(op) || PyWeakref_CheckProxy(op)) + + +PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob, + PyObject *callback); +PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob, + PyObject *callback); +PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref); + +#ifndef Py_LIMITED_API +PyAPI_FUNC(Py_ssize_t) _PyWeakref_GetWeakrefCount(PyWeakReference *head); + +PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); +#endif + +/* Explanation for the Py_REFCNT() check: when a weakref's target is part + of a long chain of deallocations which triggers the trashcan mechanism, + clearing the weakrefs can be delayed long after the target's refcount + has dropped to zero. In the meantime, code accessing the weakref will + be able to "see" the target object even though it is supposed to be + unreachable. See issue #16602. */ + +#define PyWeakref_GET_OBJECT(ref) \ + (Py_REFCNT(((PyWeakReference *)(ref))->wr_object) > 0 \ + ? ((PyWeakReference *)(ref))->wr_object \ + : Py_None) + + +#ifdef __cplusplus +} +#endif +#endif /* !Py_WEAKREFOBJECT_H */ diff --git a/winvenv/Lib/__future__.py b/winvenv/Lib/__future__.py new file mode 100644 index 0000000..ce8bed7 --- /dev/null +++ b/winvenv/Lib/__future__.py @@ -0,0 +1,146 @@ +"""Record of phased-in incompatible language changes. + +Each line is of the form: + + FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease "," + CompilerFlag ")" + +where, normally, OptionalRelease < MandatoryRelease, and both are 5-tuples +of the same form as sys.version_info: + + (PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int + PY_MINOR_VERSION, # the 1; an int + PY_MICRO_VERSION, # the 0; an int + PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string + PY_RELEASE_SERIAL # the 3; an int + ) + +OptionalRelease records the first release in which + + from __future__ import FeatureName + +was accepted. + +In the case of MandatoryReleases that have not yet occurred, +MandatoryRelease predicts the release in which the feature will become part +of the language. + +Else MandatoryRelease records when the feature became part of the language; +in releases at or after that, modules no longer need + + from __future__ import FeatureName + +to use the feature in question, but may continue to use such imports. + +MandatoryRelease may also be None, meaning that a planned feature got +dropped. + +Instances of class _Feature have two corresponding methods, +.getOptionalRelease() and .getMandatoryRelease(). + +CompilerFlag is the (bitfield) flag that should be passed in the fourth +argument to the builtin function compile() to enable the feature in +dynamically compiled code. This flag is stored in the .compiler_flag +attribute on _Future instances. These values must match the appropriate +#defines of CO_xxx flags in Include/compile.h. + +No feature line is ever to be deleted from this file. +""" + +all_feature_names = [ + "nested_scopes", + "generators", + "division", + "absolute_import", + "with_statement", + "print_function", + "unicode_literals", + "barry_as_FLUFL", + "generator_stop", + "annotations", +] + +__all__ = ["all_feature_names"] + all_feature_names + +# The CO_xxx symbols are defined here under the same names defined in +# code.h and used by compile.h, so that an editor search will find them here. +# However, they're not exported in __all__, because they don't really belong to +# this module. +CO_NESTED = 0x0010 # nested_scopes +CO_GENERATOR_ALLOWED = 0 # generators (obsolete, was 0x1000) +CO_FUTURE_DIVISION = 0x2000 # division +CO_FUTURE_ABSOLUTE_IMPORT = 0x4000 # perform absolute imports by default +CO_FUTURE_WITH_STATEMENT = 0x8000 # with statement +CO_FUTURE_PRINT_FUNCTION = 0x10000 # print function +CO_FUTURE_UNICODE_LITERALS = 0x20000 # unicode string literals +CO_FUTURE_BARRY_AS_BDFL = 0x40000 +CO_FUTURE_GENERATOR_STOP = 0x80000 # StopIteration becomes RuntimeError in generators +CO_FUTURE_ANNOTATIONS = 0x100000 # annotations become strings at runtime + +class _Feature: + def __init__(self, optionalRelease, mandatoryRelease, compiler_flag): + self.optional = optionalRelease + self.mandatory = mandatoryRelease + self.compiler_flag = compiler_flag + + def getOptionalRelease(self): + """Return first release in which this feature was recognized. + + This is a 5-tuple, of the same form as sys.version_info. + """ + + return self.optional + + def getMandatoryRelease(self): + """Return release in which this feature will become mandatory. + + This is a 5-tuple, of the same form as sys.version_info, or, if + the feature was dropped, is None. + """ + + return self.mandatory + + def __repr__(self): + return "_Feature" + repr((self.optional, + self.mandatory, + self.compiler_flag)) + +nested_scopes = _Feature((2, 1, 0, "beta", 1), + (2, 2, 0, "alpha", 0), + CO_NESTED) + +generators = _Feature((2, 2, 0, "alpha", 1), + (2, 3, 0, "final", 0), + CO_GENERATOR_ALLOWED) + +division = _Feature((2, 2, 0, "alpha", 2), + (3, 0, 0, "alpha", 0), + CO_FUTURE_DIVISION) + +absolute_import = _Feature((2, 5, 0, "alpha", 1), + (3, 0, 0, "alpha", 0), + CO_FUTURE_ABSOLUTE_IMPORT) + +with_statement = _Feature((2, 5, 0, "alpha", 1), + (2, 6, 0, "alpha", 0), + CO_FUTURE_WITH_STATEMENT) + +print_function = _Feature((2, 6, 0, "alpha", 2), + (3, 0, 0, "alpha", 0), + CO_FUTURE_PRINT_FUNCTION) + +unicode_literals = _Feature((2, 6, 0, "alpha", 2), + (3, 0, 0, "alpha", 0), + CO_FUTURE_UNICODE_LITERALS) + +barry_as_FLUFL = _Feature((3, 1, 0, "alpha", 2), + (3, 9, 0, "alpha", 0), + CO_FUTURE_BARRY_AS_BDFL) + +generator_stop = _Feature((3, 5, 0, "beta", 1), + (3, 7, 0, "alpha", 0), + CO_FUTURE_GENERATOR_STOP) + +annotations = _Feature((3, 7, 0, "beta", 1), + (4, 0, 0, "alpha", 0), + CO_FUTURE_ANNOTATIONS) diff --git a/winvenv/Lib/_bootlocale.py b/winvenv/Lib/_bootlocale.py new file mode 100644 index 0000000..3273a3b --- /dev/null +++ b/winvenv/Lib/_bootlocale.py @@ -0,0 +1,46 @@ +"""A minimal subset of the locale module used at interpreter startup +(imported by the _io module), in order to reduce startup time. + +Don't import directly from third-party code; use the `locale` module instead! +""" + +import sys +import _locale + +if sys.platform.startswith("win"): + def getpreferredencoding(do_setlocale=True): + if sys.flags.utf8_mode: + return 'UTF-8' + return _locale._getdefaultlocale()[1] +else: + try: + _locale.CODESET + except AttributeError: + if hasattr(sys, 'getandroidapilevel'): + # On Android langinfo.h and CODESET are missing, and UTF-8 is + # always used in mbstowcs() and wcstombs(). + def getpreferredencoding(do_setlocale=True): + return 'UTF-8' + else: + def getpreferredencoding(do_setlocale=True): + if sys.flags.utf8_mode: + return 'UTF-8' + # This path for legacy systems needs the more complex + # getdefaultlocale() function, import the full locale module. + import locale + return locale.getpreferredencoding(do_setlocale) + else: + def getpreferredencoding(do_setlocale=True): + assert not do_setlocale + if sys.flags.utf8_mode: + return 'UTF-8' + result = _locale.nl_langinfo(_locale.CODESET) + if not result and sys.platform == 'darwin': + # nl_langinfo can return an empty string + # when the setting has an invalid value. + # Default to UTF-8 in that case because + # UTF-8 is the default charset on OSX and + # returning nothing will crash the + # interpreter. + result = 'UTF-8' + return result diff --git a/winvenv/Lib/_collections_abc.py b/winvenv/Lib/_collections_abc.py new file mode 100644 index 0000000..dbe30df --- /dev/null +++ b/winvenv/Lib/_collections_abc.py @@ -0,0 +1,1011 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Abstract Base Classes (ABCs) for collections, according to PEP 3119. + +Unit tests are in test_collections. +""" + +from abc import ABCMeta, abstractmethod +import sys + +__all__ = ["Awaitable", "Coroutine", + "AsyncIterable", "AsyncIterator", "AsyncGenerator", + "Hashable", "Iterable", "Iterator", "Generator", "Reversible", + "Sized", "Container", "Callable", "Collection", + "Set", "MutableSet", + "Mapping", "MutableMapping", + "MappingView", "KeysView", "ItemsView", "ValuesView", + "Sequence", "MutableSequence", + "ByteString", + ] + +# This module has been renamed from collections.abc to _collections_abc to +# speed up interpreter startup. Some of the types such as MutableMapping are +# required early but collections module imports a lot of other modules. +# See issue #19218 +__name__ = "collections.abc" + +# Private list of types that we want to register with the various ABCs +# so that they will pass tests like: +# it = iter(somebytearray) +# assert isinstance(it, Iterable) +# Note: in other implementations, these types might not be distinct +# and they may have their own implementation specific types that +# are not included on this list. +bytes_iterator = type(iter(b'')) +bytearray_iterator = type(iter(bytearray())) +#callable_iterator = ??? +dict_keyiterator = type(iter({}.keys())) +dict_valueiterator = type(iter({}.values())) +dict_itemiterator = type(iter({}.items())) +list_iterator = type(iter([])) +list_reverseiterator = type(iter(reversed([]))) +range_iterator = type(iter(range(0))) +longrange_iterator = type(iter(range(1 << 1000))) +set_iterator = type(iter(set())) +str_iterator = type(iter("")) +tuple_iterator = type(iter(())) +zip_iterator = type(iter(zip())) +## views ## +dict_keys = type({}.keys()) +dict_values = type({}.values()) +dict_items = type({}.items()) +## misc ## +mappingproxy = type(type.__dict__) +generator = type((lambda: (yield))()) +## coroutine ## +async def _coro(): pass +_coro = _coro() +coroutine = type(_coro) +_coro.close() # Prevent ResourceWarning +del _coro +## asynchronous generator ## +async def _ag(): yield +_ag = _ag() +async_generator = type(_ag) +del _ag + + +### ONE-TRICK PONIES ### + +def _check_methods(C, *methods): + mro = C.__mro__ + for method in methods: + for B in mro: + if method in B.__dict__: + if B.__dict__[method] is None: + return NotImplemented + break + else: + return NotImplemented + return True + +class Hashable(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __hash__(self): + return 0 + + @classmethod + def __subclasshook__(cls, C): + if cls is Hashable: + return _check_methods(C, "__hash__") + return NotImplemented + + +class Awaitable(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __await__(self): + yield + + @classmethod + def __subclasshook__(cls, C): + if cls is Awaitable: + return _check_methods(C, "__await__") + return NotImplemented + + +class Coroutine(Awaitable): + + __slots__ = () + + @abstractmethod + def send(self, value): + """Send a value into the coroutine. + Return next yielded value or raise StopIteration. + """ + raise StopIteration + + @abstractmethod + def throw(self, typ, val=None, tb=None): + """Raise an exception in the coroutine. + Return next yielded value or raise StopIteration. + """ + if val is None: + if tb is None: + raise typ + val = typ() + if tb is not None: + val = val.with_traceback(tb) + raise val + + def close(self): + """Raise GeneratorExit inside coroutine. + """ + try: + self.throw(GeneratorExit) + except (GeneratorExit, StopIteration): + pass + else: + raise RuntimeError("coroutine ignored GeneratorExit") + + @classmethod + def __subclasshook__(cls, C): + if cls is Coroutine: + return _check_methods(C, '__await__', 'send', 'throw', 'close') + return NotImplemented + + +Coroutine.register(coroutine) + + +class AsyncIterable(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __aiter__(self): + return AsyncIterator() + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncIterable: + return _check_methods(C, "__aiter__") + return NotImplemented + + +class AsyncIterator(AsyncIterable): + + __slots__ = () + + @abstractmethod + async def __anext__(self): + """Return the next item or raise StopAsyncIteration when exhausted.""" + raise StopAsyncIteration + + def __aiter__(self): + return self + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncIterator: + return _check_methods(C, "__anext__", "__aiter__") + return NotImplemented + + +class AsyncGenerator(AsyncIterator): + + __slots__ = () + + async def __anext__(self): + """Return the next item from the asynchronous generator. + When exhausted, raise StopAsyncIteration. + """ + return await self.asend(None) + + @abstractmethod + async def asend(self, value): + """Send a value into the asynchronous generator. + Return next yielded value or raise StopAsyncIteration. + """ + raise StopAsyncIteration + + @abstractmethod + async def athrow(self, typ, val=None, tb=None): + """Raise an exception in the asynchronous generator. + Return next yielded value or raise StopAsyncIteration. + """ + if val is None: + if tb is None: + raise typ + val = typ() + if tb is not None: + val = val.with_traceback(tb) + raise val + + async def aclose(self): + """Raise GeneratorExit inside coroutine. + """ + try: + await self.athrow(GeneratorExit) + except (GeneratorExit, StopAsyncIteration): + pass + else: + raise RuntimeError("asynchronous generator ignored GeneratorExit") + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncGenerator: + return _check_methods(C, '__aiter__', '__anext__', + 'asend', 'athrow', 'aclose') + return NotImplemented + + +AsyncGenerator.register(async_generator) + + +class Iterable(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __iter__(self): + while False: + yield None + + @classmethod + def __subclasshook__(cls, C): + if cls is Iterable: + return _check_methods(C, "__iter__") + return NotImplemented + + +class Iterator(Iterable): + + __slots__ = () + + @abstractmethod + def __next__(self): + 'Return the next item from the iterator. When exhausted, raise StopIteration' + raise StopIteration + + def __iter__(self): + return self + + @classmethod + def __subclasshook__(cls, C): + if cls is Iterator: + return _check_methods(C, '__iter__', '__next__') + return NotImplemented + +Iterator.register(bytes_iterator) +Iterator.register(bytearray_iterator) +#Iterator.register(callable_iterator) +Iterator.register(dict_keyiterator) +Iterator.register(dict_valueiterator) +Iterator.register(dict_itemiterator) +Iterator.register(list_iterator) +Iterator.register(list_reverseiterator) +Iterator.register(range_iterator) +Iterator.register(longrange_iterator) +Iterator.register(set_iterator) +Iterator.register(str_iterator) +Iterator.register(tuple_iterator) +Iterator.register(zip_iterator) + + +class Reversible(Iterable): + + __slots__ = () + + @abstractmethod + def __reversed__(self): + while False: + yield None + + @classmethod + def __subclasshook__(cls, C): + if cls is Reversible: + return _check_methods(C, "__reversed__", "__iter__") + return NotImplemented + + +class Generator(Iterator): + + __slots__ = () + + def __next__(self): + """Return the next item from the generator. + When exhausted, raise StopIteration. + """ + return self.send(None) + + @abstractmethod + def send(self, value): + """Send a value into the generator. + Return next yielded value or raise StopIteration. + """ + raise StopIteration + + @abstractmethod + def throw(self, typ, val=None, tb=None): + """Raise an exception in the generator. + Return next yielded value or raise StopIteration. + """ + if val is None: + if tb is None: + raise typ + val = typ() + if tb is not None: + val = val.with_traceback(tb) + raise val + + def close(self): + """Raise GeneratorExit inside generator. + """ + try: + self.throw(GeneratorExit) + except (GeneratorExit, StopIteration): + pass + else: + raise RuntimeError("generator ignored GeneratorExit") + + @classmethod + def __subclasshook__(cls, C): + if cls is Generator: + return _check_methods(C, '__iter__', '__next__', + 'send', 'throw', 'close') + return NotImplemented + +Generator.register(generator) + + +class Sized(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __len__(self): + return 0 + + @classmethod + def __subclasshook__(cls, C): + if cls is Sized: + return _check_methods(C, "__len__") + return NotImplemented + + +class Container(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __contains__(self, x): + return False + + @classmethod + def __subclasshook__(cls, C): + if cls is Container: + return _check_methods(C, "__contains__") + return NotImplemented + +class Collection(Sized, Iterable, Container): + + __slots__ = () + + @classmethod + def __subclasshook__(cls, C): + if cls is Collection: + return _check_methods(C, "__len__", "__iter__", "__contains__") + return NotImplemented + +class Callable(metaclass=ABCMeta): + + __slots__ = () + + @abstractmethod + def __call__(self, *args, **kwds): + return False + + @classmethod + def __subclasshook__(cls, C): + if cls is Callable: + return _check_methods(C, "__call__") + return NotImplemented + + +### SETS ### + + +class Set(Collection): + + """A set is a finite, iterable container. + + This class provides concrete generic implementations of all + methods except for __contains__, __iter__ and __len__. + + To override the comparisons (presumably for speed, as the + semantics are fixed), redefine __le__ and __ge__, + then the other operations will automatically follow suit. + """ + + __slots__ = () + + def __le__(self, other): + if not isinstance(other, Set): + return NotImplemented + if len(self) > len(other): + return False + for elem in self: + if elem not in other: + return False + return True + + def __lt__(self, other): + if not isinstance(other, Set): + return NotImplemented + return len(self) < len(other) and self.__le__(other) + + def __gt__(self, other): + if not isinstance(other, Set): + return NotImplemented + return len(self) > len(other) and self.__ge__(other) + + def __ge__(self, other): + if not isinstance(other, Set): + return NotImplemented + if len(self) < len(other): + return False + for elem in other: + if elem not in self: + return False + return True + + def __eq__(self, other): + if not isinstance(other, Set): + return NotImplemented + return len(self) == len(other) and self.__le__(other) + + @classmethod + def _from_iterable(cls, it): + '''Construct an instance of the class from any iterable input. + + Must override this method if the class constructor signature + does not accept an iterable for an input. + ''' + return cls(it) + + def __and__(self, other): + if not isinstance(other, Iterable): + return NotImplemented + return self._from_iterable(value for value in other if value in self) + + __rand__ = __and__ + + def isdisjoint(self, other): + 'Return True if two sets have a null intersection.' + for value in other: + if value in self: + return False + return True + + def __or__(self, other): + if not isinstance(other, Iterable): + return NotImplemented + chain = (e for s in (self, other) for e in s) + return self._from_iterable(chain) + + __ror__ = __or__ + + def __sub__(self, other): + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self._from_iterable(other) + return self._from_iterable(value for value in self + if value not in other) + + def __rsub__(self, other): + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self._from_iterable(other) + return self._from_iterable(value for value in other + if value not in self) + + def __xor__(self, other): + if not isinstance(other, Set): + if not isinstance(other, Iterable): + return NotImplemented + other = self._from_iterable(other) + return (self - other) | (other - self) + + __rxor__ = __xor__ + + def _hash(self): + """Compute the hash value of a set. + + Note that we don't define __hash__: not all sets are hashable. + But if you define a hashable set type, its __hash__ should + call this function. + + This must be compatible __eq__. + + All sets ought to compare equal if they contain the same + elements, regardless of how they are implemented, and + regardless of the order of the elements; so there's not much + freedom for __eq__ or __hash__. We match the algorithm used + by the built-in frozenset type. + """ + MAX = sys.maxsize + MASK = 2 * MAX + 1 + n = len(self) + h = 1927868237 * (n + 1) + h &= MASK + for x in self: + hx = hash(x) + h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 + h &= MASK + h = h * 69069 + 907133923 + h &= MASK + if h > MAX: + h -= MASK + 1 + if h == -1: + h = 590923713 + return h + +Set.register(frozenset) + + +class MutableSet(Set): + """A mutable set is a finite, iterable container. + + This class provides concrete generic implementations of all + methods except for __contains__, __iter__, __len__, + add(), and discard(). + + To override the comparisons (presumably for speed, as the + semantics are fixed), all you have to do is redefine __le__ and + then the other operations will automatically follow suit. + """ + + __slots__ = () + + @abstractmethod + def add(self, value): + """Add an element.""" + raise NotImplementedError + + @abstractmethod + def discard(self, value): + """Remove an element. Do not raise an exception if absent.""" + raise NotImplementedError + + def remove(self, value): + """Remove an element. If not a member, raise a KeyError.""" + if value not in self: + raise KeyError(value) + self.discard(value) + + def pop(self): + """Return the popped value. Raise KeyError if empty.""" + it = iter(self) + try: + value = next(it) + except StopIteration: + raise KeyError from None + self.discard(value) + return value + + def clear(self): + """This is slow (creates N new iterators!) but effective.""" + try: + while True: + self.pop() + except KeyError: + pass + + def __ior__(self, it): + for value in it: + self.add(value) + return self + + def __iand__(self, it): + for value in (self - it): + self.discard(value) + return self + + def __ixor__(self, it): + if it is self: + self.clear() + else: + if not isinstance(it, Set): + it = self._from_iterable(it) + for value in it: + if value in self: + self.discard(value) + else: + self.add(value) + return self + + def __isub__(self, it): + if it is self: + self.clear() + else: + for value in it: + self.discard(value) + return self + +MutableSet.register(set) + + +### MAPPINGS ### + + +class Mapping(Collection): + + __slots__ = () + + """A Mapping is a generic container for associating key/value + pairs. + + This class provides concrete generic implementations of all + methods except for __getitem__, __iter__, and __len__. + + """ + + @abstractmethod + def __getitem__(self, key): + raise KeyError + + def get(self, key, default=None): + 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' + try: + return self[key] + except KeyError: + return default + + def __contains__(self, key): + try: + self[key] + except KeyError: + return False + else: + return True + + def keys(self): + "D.keys() -> a set-like object providing a view on D's keys" + return KeysView(self) + + def items(self): + "D.items() -> a set-like object providing a view on D's items" + return ItemsView(self) + + def values(self): + "D.values() -> an object providing a view on D's values" + return ValuesView(self) + + def __eq__(self, other): + if not isinstance(other, Mapping): + return NotImplemented + return dict(self.items()) == dict(other.items()) + + __reversed__ = None + +Mapping.register(mappingproxy) + + +class MappingView(Sized): + + __slots__ = '_mapping', + + def __init__(self, mapping): + self._mapping = mapping + + def __len__(self): + return len(self._mapping) + + def __repr__(self): + return '{0.__class__.__name__}({0._mapping!r})'.format(self) + + +class KeysView(MappingView, Set): + + __slots__ = () + + @classmethod + def _from_iterable(self, it): + return set(it) + + def __contains__(self, key): + return key in self._mapping + + def __iter__(self): + yield from self._mapping + +KeysView.register(dict_keys) + + +class ItemsView(MappingView, Set): + + __slots__ = () + + @classmethod + def _from_iterable(self, it): + return set(it) + + def __contains__(self, item): + key, value = item + try: + v = self._mapping[key] + except KeyError: + return False + else: + return v is value or v == value + + def __iter__(self): + for key in self._mapping: + yield (key, self._mapping[key]) + +ItemsView.register(dict_items) + + +class ValuesView(MappingView, Collection): + + __slots__ = () + + def __contains__(self, value): + for key in self._mapping: + v = self._mapping[key] + if v is value or v == value: + return True + return False + + def __iter__(self): + for key in self._mapping: + yield self._mapping[key] + +ValuesView.register(dict_values) + + +class MutableMapping(Mapping): + + __slots__ = () + + """A MutableMapping is a generic container for associating + key/value pairs. + + This class provides concrete generic implementations of all + methods except for __getitem__, __setitem__, __delitem__, + __iter__, and __len__. + + """ + + @abstractmethod + def __setitem__(self, key, value): + raise KeyError + + @abstractmethod + def __delitem__(self, key): + raise KeyError + + __marker = object() + + def pop(self, key, default=__marker): + '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + ''' + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def popitem(self): + '''D.popitem() -> (k, v), remove and return some (key, value) pair + as a 2-tuple; but raise KeyError if D is empty. + ''' + try: + key = next(iter(self)) + except StopIteration: + raise KeyError from None + value = self[key] + del self[key] + return key, value + + def clear(self): + 'D.clear() -> None. Remove all items from D.' + try: + while True: + self.popitem() + except KeyError: + pass + + def update(*args, **kwds): + ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. + If E present and has a .keys() method, does: for k in E: D[k] = E[k] + If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v + In either case, this is followed by: for k, v in F.items(): D[k] = v + ''' + if not args: + raise TypeError("descriptor 'update' of 'MutableMapping' object " + "needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('update expected at most 1 arguments, got %d' % + len(args)) + if args: + other = args[0] + if isinstance(other, Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + def setdefault(self, key, default=None): + 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' + try: + return self[key] + except KeyError: + self[key] = default + return default + +MutableMapping.register(dict) + + +### SEQUENCES ### + + +class Sequence(Reversible, Collection): + + """All the operations on a read-only sequence. + + Concrete subclasses must override __new__ or __init__, + __getitem__, and __len__. + """ + + __slots__ = () + + @abstractmethod + def __getitem__(self, index): + raise IndexError + + def __iter__(self): + i = 0 + try: + while True: + v = self[i] + yield v + i += 1 + except IndexError: + return + + def __contains__(self, value): + for v in self: + if v is value or v == value: + return True + return False + + def __reversed__(self): + for i in reversed(range(len(self))): + yield self[i] + + def index(self, value, start=0, stop=None): + '''S.index(value, [start, [stop]]) -> integer -- return first index of value. + Raises ValueError if the value is not present. + + Supporting start and stop arguments is optional, but + recommended. + ''' + if start is not None and start < 0: + start = max(len(self) + start, 0) + if stop is not None and stop < 0: + stop += len(self) + + i = start + while stop is None or i < stop: + try: + v = self[i] + if v is value or v == value: + return i + except IndexError: + break + i += 1 + raise ValueError + + def count(self, value): + 'S.count(value) -> integer -- return number of occurrences of value' + return sum(1 for v in self if v is value or v == value) + +Sequence.register(tuple) +Sequence.register(str) +Sequence.register(range) +Sequence.register(memoryview) + + +class ByteString(Sequence): + + """This unifies bytes and bytearray. + + XXX Should add all their methods. + """ + + __slots__ = () + +ByteString.register(bytes) +ByteString.register(bytearray) + + +class MutableSequence(Sequence): + + __slots__ = () + + """All the operations on a read-write sequence. + + Concrete subclasses must provide __new__ or __init__, + __getitem__, __setitem__, __delitem__, __len__, and insert(). + + """ + + @abstractmethod + def __setitem__(self, index, value): + raise IndexError + + @abstractmethod + def __delitem__(self, index): + raise IndexError + + @abstractmethod + def insert(self, index, value): + 'S.insert(index, value) -- insert value before index' + raise IndexError + + def append(self, value): + 'S.append(value) -- append value to the end of the sequence' + self.insert(len(self), value) + + def clear(self): + 'S.clear() -> None -- remove all items from S' + try: + while True: + self.pop() + except IndexError: + pass + + def reverse(self): + 'S.reverse() -- reverse *IN PLACE*' + n = len(self) + for i in range(n//2): + self[i], self[n-i-1] = self[n-i-1], self[i] + + def extend(self, values): + 'S.extend(iterable) -- extend sequence by appending elements from the iterable' + for v in values: + self.append(v) + + def pop(self, index=-1): + '''S.pop([index]) -> item -- remove and return item at index (default last). + Raise IndexError if list is empty or index is out of range. + ''' + v = self[index] + del self[index] + return v + + def remove(self, value): + '''S.remove(value) -- remove first occurrence of value. + Raise ValueError if the value is not present. + ''' + del self[self.index(value)] + + def __iadd__(self, values): + self.extend(values) + return self + +MutableSequence.register(list) +MutableSequence.register(bytearray) # Multiply inheriting, see ByteString diff --git a/winvenv/Lib/_dummy_thread.py b/winvenv/Lib/_dummy_thread.py new file mode 100644 index 0000000..a2cae54 --- /dev/null +++ b/winvenv/Lib/_dummy_thread.py @@ -0,0 +1,163 @@ +"""Drop-in replacement for the thread module. + +Meant to be used as a brain-dead substitute so that threaded code does +not need to be rewritten for when the thread module is not present. + +Suggested usage is:: + + try: + import _thread + except ImportError: + import _dummy_thread as _thread + +""" +# Exports only things specified by thread documentation; +# skipping obsolete synonyms allocate(), start_new(), exit_thread(). +__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock', + 'interrupt_main', 'LockType'] + +# A dummy value +TIMEOUT_MAX = 2**31 + +# NOTE: this module can be imported early in the extension building process, +# and so top level imports of other modules should be avoided. Instead, all +# imports are done when needed on a function-by-function basis. Since threads +# are disabled, the import lock should not be an issue anyway (??). + +error = RuntimeError + +def start_new_thread(function, args, kwargs={}): + """Dummy implementation of _thread.start_new_thread(). + + Compatibility is maintained by making sure that ``args`` is a + tuple and ``kwargs`` is a dictionary. If an exception is raised + and it is SystemExit (which can be done by _thread.exit()) it is + caught and nothing is done; all other exceptions are printed out + by using traceback.print_exc(). + + If the executed function calls interrupt_main the KeyboardInterrupt will be + raised when the function returns. + + """ + if type(args) != type(tuple()): + raise TypeError("2nd arg must be a tuple") + if type(kwargs) != type(dict()): + raise TypeError("3rd arg must be a dict") + global _main + _main = False + try: + function(*args, **kwargs) + except SystemExit: + pass + except: + import traceback + traceback.print_exc() + _main = True + global _interrupt + if _interrupt: + _interrupt = False + raise KeyboardInterrupt + +def exit(): + """Dummy implementation of _thread.exit().""" + raise SystemExit + +def get_ident(): + """Dummy implementation of _thread.get_ident(). + + Since this module should only be used when _threadmodule is not + available, it is safe to assume that the current process is the + only thread. Thus a constant can be safely returned. + """ + return 1 + +def allocate_lock(): + """Dummy implementation of _thread.allocate_lock().""" + return LockType() + +def stack_size(size=None): + """Dummy implementation of _thread.stack_size().""" + if size is not None: + raise error("setting thread stack size not supported") + return 0 + +def _set_sentinel(): + """Dummy implementation of _thread._set_sentinel().""" + return LockType() + +class LockType(object): + """Class implementing dummy implementation of _thread.LockType. + + Compatibility is maintained by maintaining self.locked_status + which is a boolean that stores the state of the lock. Pickling of + the lock, though, should not be done since if the _thread module is + then used with an unpickled ``lock()`` from here problems could + occur from this class not having atomic methods. + + """ + + def __init__(self): + self.locked_status = False + + def acquire(self, waitflag=None, timeout=-1): + """Dummy implementation of acquire(). + + For blocking calls, self.locked_status is automatically set to + True and returned appropriately based on value of + ``waitflag``. If it is non-blocking, then the value is + actually checked and not set if it is already acquired. This + is all done so that threading.Condition's assert statements + aren't triggered and throw a little fit. + + """ + if waitflag is None or waitflag: + self.locked_status = True + return True + else: + if not self.locked_status: + self.locked_status = True + return True + else: + if timeout > 0: + import time + time.sleep(timeout) + return False + + __enter__ = acquire + + def __exit__(self, typ, val, tb): + self.release() + + def release(self): + """Release the dummy lock.""" + # XXX Perhaps shouldn't actually bother to test? Could lead + # to problems for complex, threaded code. + if not self.locked_status: + raise error + self.locked_status = False + return True + + def locked(self): + return self.locked_status + + def __repr__(self): + return "<%s %s.%s object at %s>" % ( + "locked" if self.locked_status else "unlocked", + self.__class__.__module__, + self.__class__.__qualname__, + hex(id(self)) + ) + +# Used to signal that interrupt_main was called in a "thread" +_interrupt = False +# True when not executing in a "thread" +_main = True + +def interrupt_main(): + """Set _interrupt flag to True to have start_new_thread raise + KeyboardInterrupt upon exiting.""" + if _main: + raise KeyboardInterrupt + else: + global _interrupt + _interrupt = True diff --git a/winvenv/Lib/_weakrefset.py b/winvenv/Lib/_weakrefset.py new file mode 100644 index 0000000..304c66f --- /dev/null +++ b/winvenv/Lib/_weakrefset.py @@ -0,0 +1,196 @@ +# Access WeakSet through the weakref module. +# This code is separated-out because it is needed +# by abc.py to load everything else at startup. + +from _weakref import ref + +__all__ = ['WeakSet'] + + +class _IterationGuard: + # This context manager registers itself in the current iterators of the + # weak container, such as to delay all removals until the context manager + # exits. + # This technique should be relatively thread-safe (since sets are). + + def __init__(self, weakcontainer): + # Don't create cycles + self.weakcontainer = ref(weakcontainer) + + def __enter__(self): + w = self.weakcontainer() + if w is not None: + w._iterating.add(self) + return self + + def __exit__(self, e, t, b): + w = self.weakcontainer() + if w is not None: + s = w._iterating + s.remove(self) + if not s: + w._commit_removals() + + +class WeakSet: + def __init__(self, data=None): + self.data = set() + def _remove(item, selfref=ref(self)): + self = selfref() + if self is not None: + if self._iterating: + self._pending_removals.append(item) + else: + self.data.discard(item) + self._remove = _remove + # A list of keys to be removed + self._pending_removals = [] + self._iterating = set() + if data is not None: + self.update(data) + + def _commit_removals(self): + l = self._pending_removals + discard = self.data.discard + while l: + discard(l.pop()) + + def __iter__(self): + with _IterationGuard(self): + for itemref in self.data: + item = itemref() + if item is not None: + # Caveat: the iterator will keep a strong reference to + # `item` until it is resumed or closed. + yield item + + def __len__(self): + return len(self.data) - len(self._pending_removals) + + def __contains__(self, item): + try: + wr = ref(item) + except TypeError: + return False + return wr in self.data + + def __reduce__(self): + return (self.__class__, (list(self),), + getattr(self, '__dict__', None)) + + def add(self, item): + if self._pending_removals: + self._commit_removals() + self.data.add(ref(item, self._remove)) + + def clear(self): + if self._pending_removals: + self._commit_removals() + self.data.clear() + + def copy(self): + return self.__class__(self) + + def pop(self): + if self._pending_removals: + self._commit_removals() + while True: + try: + itemref = self.data.pop() + except KeyError: + raise KeyError('pop from empty WeakSet') from None + item = itemref() + if item is not None: + return item + + def remove(self, item): + if self._pending_removals: + self._commit_removals() + self.data.remove(ref(item)) + + def discard(self, item): + if self._pending_removals: + self._commit_removals() + self.data.discard(ref(item)) + + def update(self, other): + if self._pending_removals: + self._commit_removals() + for element in other: + self.add(element) + + def __ior__(self, other): + self.update(other) + return self + + def difference(self, other): + newset = self.copy() + newset.difference_update(other) + return newset + __sub__ = difference + + def difference_update(self, other): + self.__isub__(other) + def __isub__(self, other): + if self._pending_removals: + self._commit_removals() + if self is other: + self.data.clear() + else: + self.data.difference_update(ref(item) for item in other) + return self + + def intersection(self, other): + return self.__class__(item for item in other if item in self) + __and__ = intersection + + def intersection_update(self, other): + self.__iand__(other) + def __iand__(self, other): + if self._pending_removals: + self._commit_removals() + self.data.intersection_update(ref(item) for item in other) + return self + + def issubset(self, other): + return self.data.issubset(ref(item) for item in other) + __le__ = issubset + + def __lt__(self, other): + return self.data < set(map(ref, other)) + + def issuperset(self, other): + return self.data.issuperset(ref(item) for item in other) + __ge__ = issuperset + + def __gt__(self, other): + return self.data > set(map(ref, other)) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.data == set(map(ref, other)) + + def symmetric_difference(self, other): + newset = self.copy() + newset.symmetric_difference_update(other) + return newset + __xor__ = symmetric_difference + + def symmetric_difference_update(self, other): + self.__ixor__(other) + def __ixor__(self, other): + if self._pending_removals: + self._commit_removals() + if self is other: + self.data.clear() + else: + self.data.symmetric_difference_update(ref(item, self._remove) for item in other) + return self + + def union(self, other): + return self.__class__(e for s in (self, other) for e in s) + __or__ = union + + def isdisjoint(self, other): + return len(self.intersection(other)) == 0 diff --git a/winvenv/Lib/abc.py b/winvenv/Lib/abc.py new file mode 100644 index 0000000..7094141 --- /dev/null +++ b/winvenv/Lib/abc.py @@ -0,0 +1,170 @@ +# Copyright 2007 Google, Inc. All Rights Reserved. +# Licensed to PSF under a Contributor Agreement. + +"""Abstract Base Classes (ABCs) according to PEP 3119.""" + + +def abstractmethod(funcobj): + """A decorator indicating abstract methods. + + Requires that the metaclass is ABCMeta or derived from it. A + class that has a metaclass derived from ABCMeta cannot be + instantiated unless all of its abstract methods are overridden. + The abstract methods can be called using any of the normal + 'super' call mechanisms. + + Usage: + + class C(metaclass=ABCMeta): + @abstractmethod + def my_abstract_method(self, ...): + ... + """ + funcobj.__isabstractmethod__ = True + return funcobj + + +class abstractclassmethod(classmethod): + """A decorator indicating abstract classmethods. + + Similar to abstractmethod. + + Usage: + + class C(metaclass=ABCMeta): + @abstractclassmethod + def my_abstract_classmethod(cls, ...): + ... + + 'abstractclassmethod' is deprecated. Use 'classmethod' with + 'abstractmethod' instead. + """ + + __isabstractmethod__ = True + + def __init__(self, callable): + callable.__isabstractmethod__ = True + super().__init__(callable) + + +class abstractstaticmethod(staticmethod): + """A decorator indicating abstract staticmethods. + + Similar to abstractmethod. + + Usage: + + class C(metaclass=ABCMeta): + @abstractstaticmethod + def my_abstract_staticmethod(...): + ... + + 'abstractstaticmethod' is deprecated. Use 'staticmethod' with + 'abstractmethod' instead. + """ + + __isabstractmethod__ = True + + def __init__(self, callable): + callable.__isabstractmethod__ = True + super().__init__(callable) + + +class abstractproperty(property): + """A decorator indicating abstract properties. + + Requires that the metaclass is ABCMeta or derived from it. A + class that has a metaclass derived from ABCMeta cannot be + instantiated unless all of its abstract properties are overridden. + The abstract properties can be called using any of the normal + 'super' call mechanisms. + + Usage: + + class C(metaclass=ABCMeta): + @abstractproperty + def my_abstract_property(self): + ... + + This defines a read-only property; you can also define a read-write + abstract property using the 'long' form of property declaration: + + class C(metaclass=ABCMeta): + def getx(self): ... + def setx(self, value): ... + x = abstractproperty(getx, setx) + + 'abstractproperty' is deprecated. Use 'property' with 'abstractmethod' + instead. + """ + + __isabstractmethod__ = True + + +try: + from _abc import (get_cache_token, _abc_init, _abc_register, + _abc_instancecheck, _abc_subclasscheck, _get_dump, + _reset_registry, _reset_caches) +except ImportError: + from _py_abc import ABCMeta, get_cache_token + ABCMeta.__module__ = 'abc' +else: + class ABCMeta(type): + """Metaclass for defining Abstract Base Classes (ABCs). + + Use this metaclass to create an ABC. An ABC can be subclassed + directly, and then acts as a mix-in class. You can also register + unrelated concrete classes (even built-in classes) and unrelated + ABCs as 'virtual subclasses' -- these and their descendants will + be considered subclasses of the registering ABC by the built-in + issubclass() function, but the registering ABC won't show up in + their MRO (Method Resolution Order) nor will method + implementations defined by the registering ABC be callable (not + even via super()). + """ + def __new__(mcls, name, bases, namespace, **kwargs): + cls = super().__new__(mcls, name, bases, namespace, **kwargs) + _abc_init(cls) + return cls + + def register(cls, subclass): + """Register a virtual subclass of an ABC. + + Returns the subclass, to allow usage as a class decorator. + """ + return _abc_register(cls, subclass) + + def __instancecheck__(cls, instance): + """Override for isinstance(instance, cls).""" + return _abc_instancecheck(cls, instance) + + def __subclasscheck__(cls, subclass): + """Override for issubclass(subclass, cls).""" + return _abc_subclasscheck(cls, subclass) + + def _dump_registry(cls, file=None): + """Debug helper to print the ABC registry.""" + print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) + print(f"Inv. counter: {get_cache_token()}", file=file) + (_abc_registry, _abc_cache, _abc_negative_cache, + _abc_negative_cache_version) = _get_dump(cls) + print(f"_abc_registry: {_abc_registry!r}", file=file) + print(f"_abc_cache: {_abc_cache!r}", file=file) + print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file) + print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}", + file=file) + + def _abc_registry_clear(cls): + """Clear the registry (for debugging or testing).""" + _reset_registry(cls) + + def _abc_caches_clear(cls): + """Clear the caches (for debugging or testing).""" + _reset_caches(cls) + + +class ABC(metaclass=ABCMeta): + """Helper class that provides a standard way to create an ABC using + inheritance. + """ + __slots__ = () diff --git a/winvenv/Lib/base64.py b/winvenv/Lib/base64.py new file mode 100644 index 0000000..2be9c39 --- /dev/null +++ b/winvenv/Lib/base64.py @@ -0,0 +1,595 @@ +#! /usr/bin/env python3 + +"""Base16, Base32, Base64 (RFC 3548), Base85 and Ascii85 data encodings""" + +# Modified 04-Oct-1995 by Jack Jansen to use binascii module +# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support +# Modified 22-May-2007 by Guido van Rossum to use bytes everywhere + +import re +import struct +import binascii + + +__all__ = [ + # Legacy interface exports traditional RFC 2045 Base64 encodings + 'encode', 'decode', 'encodebytes', 'decodebytes', + # Generalized interface for other encodings + 'b64encode', 'b64decode', 'b32encode', 'b32decode', + 'b16encode', 'b16decode', + # Base85 and Ascii85 encodings + 'b85encode', 'b85decode', 'a85encode', 'a85decode', + # Standard Base64 encoding + 'standard_b64encode', 'standard_b64decode', + # Some common Base64 alternatives. As referenced by RFC 3458, see thread + # starting at: + # + # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html + 'urlsafe_b64encode', 'urlsafe_b64decode', + ] + + +bytes_types = (bytes, bytearray) # Types acceptable as binary data + +def _bytes_from_decode_data(s): + if isinstance(s, str): + try: + return s.encode('ascii') + except UnicodeEncodeError: + raise ValueError('string argument should contain only ASCII characters') + if isinstance(s, bytes_types): + return s + try: + return memoryview(s).tobytes() + except TypeError: + raise TypeError("argument should be a bytes-like object or ASCII " + "string, not %r" % s.__class__.__name__) from None + + +# Base64 encoding/decoding uses binascii + +def b64encode(s, altchars=None): + """Encode the bytes-like object s using Base64 and return a bytes object. + + Optional altchars should be a byte string of length 2 which specifies an + alternative alphabet for the '+' and '/' characters. This allows an + application to e.g. generate url or filesystem safe Base64 strings. + """ + encoded = binascii.b2a_base64(s, newline=False) + if altchars is not None: + assert len(altchars) == 2, repr(altchars) + return encoded.translate(bytes.maketrans(b'+/', altchars)) + return encoded + + +def b64decode(s, altchars=None, validate=False): + """Decode the Base64 encoded bytes-like object or ASCII string s. + + Optional altchars must be a bytes-like object or ASCII string of length 2 + which specifies the alternative alphabet used instead of the '+' and '/' + characters. + + The result is returned as a bytes object. A binascii.Error is raised if + s is incorrectly padded. + + If validate is False (the default), characters that are neither in the + normal base-64 alphabet nor the alternative alphabet are discarded prior + to the padding check. If validate is True, these non-alphabet characters + in the input result in a binascii.Error. + """ + s = _bytes_from_decode_data(s) + if altchars is not None: + altchars = _bytes_from_decode_data(altchars) + assert len(altchars) == 2, repr(altchars) + s = s.translate(bytes.maketrans(altchars, b'+/')) + if validate and not re.match(b'^[A-Za-z0-9+/]*={0,2}$', s): + raise binascii.Error('Non-base64 digit found') + return binascii.a2b_base64(s) + + +def standard_b64encode(s): + """Encode bytes-like object s using the standard Base64 alphabet. + + The result is returned as a bytes object. + """ + return b64encode(s) + +def standard_b64decode(s): + """Decode bytes encoded with the standard Base64 alphabet. + + Argument s is a bytes-like object or ASCII string to decode. The result + is returned as a bytes object. A binascii.Error is raised if the input + is incorrectly padded. Characters that are not in the standard alphabet + are discarded prior to the padding check. + """ + return b64decode(s) + + +_urlsafe_encode_translation = bytes.maketrans(b'+/', b'-_') +_urlsafe_decode_translation = bytes.maketrans(b'-_', b'+/') + +def urlsafe_b64encode(s): + """Encode bytes using the URL- and filesystem-safe Base64 alphabet. + + Argument s is a bytes-like object to encode. The result is returned as a + bytes object. The alphabet uses '-' instead of '+' and '_' instead of + '/'. + """ + return b64encode(s).translate(_urlsafe_encode_translation) + +def urlsafe_b64decode(s): + """Decode bytes using the URL- and filesystem-safe Base64 alphabet. + + Argument s is a bytes-like object or ASCII string to decode. The result + is returned as a bytes object. A binascii.Error is raised if the input + is incorrectly padded. Characters that are not in the URL-safe base-64 + alphabet, and are not a plus '+' or slash '/', are discarded prior to the + padding check. + + The alphabet uses '-' instead of '+' and '_' instead of '/'. + """ + s = _bytes_from_decode_data(s) + s = s.translate(_urlsafe_decode_translation) + return b64decode(s) + + + +# Base32 encoding/decoding must be done in Python +_b32alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567' +_b32tab2 = None +_b32rev = None + +def b32encode(s): + """Encode the bytes-like object s using Base32 and return a bytes object. + """ + global _b32tab2 + # Delay the initialization of the table to not waste memory + # if the function is never called + if _b32tab2 is None: + b32tab = [bytes((i,)) for i in _b32alphabet] + _b32tab2 = [a + b for a in b32tab for b in b32tab] + b32tab = None + + if not isinstance(s, bytes_types): + s = memoryview(s).tobytes() + leftover = len(s) % 5 + # Pad the last quantum with zero bits if necessary + if leftover: + s = s + b'\0' * (5 - leftover) # Don't use += ! + encoded = bytearray() + from_bytes = int.from_bytes + b32tab2 = _b32tab2 + for i in range(0, len(s), 5): + c = from_bytes(s[i: i + 5], 'big') + encoded += (b32tab2[c >> 30] + # bits 1 - 10 + b32tab2[(c >> 20) & 0x3ff] + # bits 11 - 20 + b32tab2[(c >> 10) & 0x3ff] + # bits 21 - 30 + b32tab2[c & 0x3ff] # bits 31 - 40 + ) + # Adjust for any leftover partial quanta + if leftover == 1: + encoded[-6:] = b'======' + elif leftover == 2: + encoded[-4:] = b'====' + elif leftover == 3: + encoded[-3:] = b'===' + elif leftover == 4: + encoded[-1:] = b'=' + return bytes(encoded) + +def b32decode(s, casefold=False, map01=None): + """Decode the Base32 encoded bytes-like object or ASCII string s. + + Optional casefold is a flag specifying whether a lowercase alphabet is + acceptable as input. For security purposes, the default is False. + + RFC 3548 allows for optional mapping of the digit 0 (zero) to the + letter O (oh), and for optional mapping of the digit 1 (one) to + either the letter I (eye) or letter L (el). The optional argument + map01 when not None, specifies which letter the digit 1 should be + mapped to (when map01 is not None, the digit 0 is always mapped to + the letter O). For security purposes the default is None, so that + 0 and 1 are not allowed in the input. + + The result is returned as a bytes object. A binascii.Error is raised if + the input is incorrectly padded or if there are non-alphabet + characters present in the input. + """ + global _b32rev + # Delay the initialization of the table to not waste memory + # if the function is never called + if _b32rev is None: + _b32rev = {v: k for k, v in enumerate(_b32alphabet)} + s = _bytes_from_decode_data(s) + if len(s) % 8: + raise binascii.Error('Incorrect padding') + # Handle section 2.4 zero and one mapping. The flag map01 will be either + # False, or the character to map the digit 1 (one) to. It should be + # either L (el) or I (eye). + if map01 is not None: + map01 = _bytes_from_decode_data(map01) + assert len(map01) == 1, repr(map01) + s = s.translate(bytes.maketrans(b'01', b'O' + map01)) + if casefold: + s = s.upper() + # Strip off pad characters from the right. We need to count the pad + # characters because this will tell us how many null bytes to remove from + # the end of the decoded string. + l = len(s) + s = s.rstrip(b'=') + padchars = l - len(s) + # Now decode the full quanta + decoded = bytearray() + b32rev = _b32rev + for i in range(0, len(s), 8): + quanta = s[i: i + 8] + acc = 0 + try: + for c in quanta: + acc = (acc << 5) + b32rev[c] + except KeyError: + raise binascii.Error('Non-base32 digit found') from None + decoded += acc.to_bytes(5, 'big') + # Process the last, partial quanta + if l % 8 or padchars not in {0, 1, 3, 4, 6}: + raise binascii.Error('Incorrect padding') + if padchars and decoded: + acc <<= 5 * padchars + last = acc.to_bytes(5, 'big') + leftover = (43 - 5 * padchars) // 8 # 1: 4, 3: 3, 4: 2, 6: 1 + decoded[-5:] = last[:leftover] + return bytes(decoded) + + +# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns +# lowercase. The RFC also recommends against accepting input case +# insensitively. +def b16encode(s): + """Encode the bytes-like object s using Base16 and return a bytes object. + """ + return binascii.hexlify(s).upper() + + +def b16decode(s, casefold=False): + """Decode the Base16 encoded bytes-like object or ASCII string s. + + Optional casefold is a flag specifying whether a lowercase alphabet is + acceptable as input. For security purposes, the default is False. + + The result is returned as a bytes object. A binascii.Error is raised if + s is incorrectly padded or if there are non-alphabet characters present + in the input. + """ + s = _bytes_from_decode_data(s) + if casefold: + s = s.upper() + if re.search(b'[^0-9A-F]', s): + raise binascii.Error('Non-base16 digit found') + return binascii.unhexlify(s) + +# +# Ascii85 encoding/decoding +# + +_a85chars = None +_a85chars2 = None +_A85START = b"<~" +_A85END = b"~>" + +def _85encode(b, chars, chars2, pad=False, foldnuls=False, foldspaces=False): + # Helper function for a85encode and b85encode + if not isinstance(b, bytes_types): + b = memoryview(b).tobytes() + + padding = (-len(b)) % 4 + if padding: + b = b + b'\0' * padding + words = struct.Struct('!%dI' % (len(b) // 4)).unpack(b) + + chunks = [b'z' if foldnuls and not word else + b'y' if foldspaces and word == 0x20202020 else + (chars2[word // 614125] + + chars2[word // 85 % 7225] + + chars[word % 85]) + for word in words] + + if padding and not pad: + if chunks[-1] == b'z': + chunks[-1] = chars[0] * 5 + chunks[-1] = chunks[-1][:-padding] + + return b''.join(chunks) + +def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False): + """Encode bytes-like object b using Ascii85 and return a bytes object. + + foldspaces is an optional flag that uses the special short sequence 'y' + instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This + feature is not supported by the "standard" Adobe encoding. + + wrapcol controls whether the output should have newline (b'\\n') characters + added to it. If this is non-zero, each output line will be at most this + many characters long. + + pad controls whether the input is padded to a multiple of 4 before + encoding. Note that the btoa implementation always pads. + + adobe controls whether the encoded byte sequence is framed with <~ and ~>, + which is used by the Adobe implementation. + """ + global _a85chars, _a85chars2 + # Delay the initialization of tables to not waste memory + # if the function is never called + if _a85chars is None: + _a85chars = [bytes((i,)) for i in range(33, 118)] + _a85chars2 = [(a + b) for a in _a85chars for b in _a85chars] + + result = _85encode(b, _a85chars, _a85chars2, pad, True, foldspaces) + + if adobe: + result = _A85START + result + if wrapcol: + wrapcol = max(2 if adobe else 1, wrapcol) + chunks = [result[i: i + wrapcol] + for i in range(0, len(result), wrapcol)] + if adobe: + if len(chunks[-1]) + 2 > wrapcol: + chunks.append(b'') + result = b'\n'.join(chunks) + if adobe: + result += _A85END + + return result + +def a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v'): + """Decode the Ascii85 encoded bytes-like object or ASCII string b. + + foldspaces is a flag that specifies whether the 'y' short sequence should be + accepted as shorthand for 4 consecutive spaces (ASCII 0x20). This feature is + not supported by the "standard" Adobe encoding. + + adobe controls whether the input sequence is in Adobe Ascii85 format (i.e. + is framed with <~ and ~>). + + ignorechars should be a byte string containing characters to ignore from the + input. This should only contain whitespace characters, and by default + contains all whitespace characters in ASCII. + + The result is returned as a bytes object. + """ + b = _bytes_from_decode_data(b) + if adobe: + if not b.endswith(_A85END): + raise ValueError( + "Ascii85 encoded byte sequences must end " + "with {!r}".format(_A85END) + ) + if b.startswith(_A85START): + b = b[2:-2] # Strip off start/end markers + else: + b = b[:-2] + # + # We have to go through this stepwise, so as to ignore spaces and handle + # special short sequences + # + packI = struct.Struct('!I').pack + decoded = [] + decoded_append = decoded.append + curr = [] + curr_append = curr.append + curr_clear = curr.clear + for x in b + b'u' * 4: + if b'!'[0] <= x <= b'u'[0]: + curr_append(x) + if len(curr) == 5: + acc = 0 + for x in curr: + acc = 85 * acc + (x - 33) + try: + decoded_append(packI(acc)) + except struct.error: + raise ValueError('Ascii85 overflow') from None + curr_clear() + elif x == b'z'[0]: + if curr: + raise ValueError('z inside Ascii85 5-tuple') + decoded_append(b'\0\0\0\0') + elif foldspaces and x == b'y'[0]: + if curr: + raise ValueError('y inside Ascii85 5-tuple') + decoded_append(b'\x20\x20\x20\x20') + elif x in ignorechars: + # Skip whitespace + continue + else: + raise ValueError('Non-Ascii85 digit found: %c' % x) + + result = b''.join(decoded) + padding = 4 - len(curr) + if padding: + # Throw away the extra padding + result = result[:-padding] + return result + +# The following code is originally taken (with permission) from Mercurial + +_b85alphabet = (b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + b"abcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~") +_b85chars = None +_b85chars2 = None +_b85dec = None + +def b85encode(b, pad=False): + """Encode bytes-like object b in base85 format and return a bytes object. + + If pad is true, the input is padded with b'\\0' so its length is a multiple of + 4 bytes before encoding. + """ + global _b85chars, _b85chars2 + # Delay the initialization of tables to not waste memory + # if the function is never called + if _b85chars is None: + _b85chars = [bytes((i,)) for i in _b85alphabet] + _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars] + return _85encode(b, _b85chars, _b85chars2, pad) + +def b85decode(b): + """Decode the base85-encoded bytes-like object or ASCII string b + + The result is returned as a bytes object. + """ + global _b85dec + # Delay the initialization of tables to not waste memory + # if the function is never called + if _b85dec is None: + _b85dec = [None] * 256 + for i, c in enumerate(_b85alphabet): + _b85dec[c] = i + + b = _bytes_from_decode_data(b) + padding = (-len(b)) % 5 + b = b + b'~' * padding + out = [] + packI = struct.Struct('!I').pack + for i in range(0, len(b), 5): + chunk = b[i:i + 5] + acc = 0 + try: + for c in chunk: + acc = acc * 85 + _b85dec[c] + except TypeError: + for j, c in enumerate(chunk): + if _b85dec[c] is None: + raise ValueError('bad base85 character at position %d' + % (i + j)) from None + raise + try: + out.append(packI(acc)) + except struct.error: + raise ValueError('base85 overflow in hunk starting at byte %d' + % i) from None + + result = b''.join(out) + if padding: + result = result[:-padding] + return result + +# Legacy interface. This code could be cleaned up since I don't believe +# binascii has any line length limitations. It just doesn't seem worth it +# though. The files should be opened in binary mode. + +MAXLINESIZE = 76 # Excluding the CRLF +MAXBINSIZE = (MAXLINESIZE//4)*3 + +def encode(input, output): + """Encode a file; input and output are binary files.""" + while True: + s = input.read(MAXBINSIZE) + if not s: + break + while len(s) < MAXBINSIZE: + ns = input.read(MAXBINSIZE-len(s)) + if not ns: + break + s += ns + line = binascii.b2a_base64(s) + output.write(line) + + +def decode(input, output): + """Decode a file; input and output are binary files.""" + while True: + line = input.readline() + if not line: + break + s = binascii.a2b_base64(line) + output.write(s) + +def _input_type_check(s): + try: + m = memoryview(s) + except TypeError as err: + msg = "expected bytes-like object, not %s" % s.__class__.__name__ + raise TypeError(msg) from err + if m.format not in ('c', 'b', 'B'): + msg = ("expected single byte elements, not %r from %s" % + (m.format, s.__class__.__name__)) + raise TypeError(msg) + if m.ndim != 1: + msg = ("expected 1-D data, not %d-D data from %s" % + (m.ndim, s.__class__.__name__)) + raise TypeError(msg) + + +def encodebytes(s): + """Encode a bytestring into a bytes object containing multiple lines + of base-64 data.""" + _input_type_check(s) + pieces = [] + for i in range(0, len(s), MAXBINSIZE): + chunk = s[i : i + MAXBINSIZE] + pieces.append(binascii.b2a_base64(chunk)) + return b"".join(pieces) + +def encodestring(s): + """Legacy alias of encodebytes().""" + import warnings + warnings.warn("encodestring() is a deprecated alias since 3.1, " + "use encodebytes()", + DeprecationWarning, 2) + return encodebytes(s) + + +def decodebytes(s): + """Decode a bytestring of base-64 data into a bytes object.""" + _input_type_check(s) + return binascii.a2b_base64(s) + +def decodestring(s): + """Legacy alias of decodebytes().""" + import warnings + warnings.warn("decodestring() is a deprecated alias since Python 3.1, " + "use decodebytes()", + DeprecationWarning, 2) + return decodebytes(s) + + +# Usable as a script... +def main(): + """Small main program""" + import sys, getopt + try: + opts, args = getopt.getopt(sys.argv[1:], 'deut') + except getopt.error as msg: + sys.stdout = sys.stderr + print(msg) + print("""usage: %s [-d|-e|-u|-t] [file|-] + -d, -u: decode + -e: encode (default) + -t: encode and decode string 'Aladdin:open sesame'"""%sys.argv[0]) + sys.exit(2) + func = encode + for o, a in opts: + if o == '-e': func = encode + if o == '-d': func = decode + if o == '-u': func = decode + if o == '-t': test(); return + if args and args[0] != '-': + with open(args[0], 'rb') as f: + func(f, sys.stdout.buffer) + else: + func(sys.stdin.buffer, sys.stdout.buffer) + + +def test(): + s0 = b"Aladdin:open sesame" + print(repr(s0)) + s1 = encodebytes(s0) + print(repr(s1)) + s2 = decodebytes(s1) + print(repr(s2)) + assert s0 == s2 + + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/bisect.py b/winvenv/Lib/bisect.py new file mode 100644 index 0000000..7732c63 --- /dev/null +++ b/winvenv/Lib/bisect.py @@ -0,0 +1,92 @@ +"""Bisection algorithms.""" + +def insort_right(a, x, lo=0, hi=None): + """Insert item x in list a, and keep it sorted assuming a is sorted. + + If x is already in a, insert it to the right of the rightmost x. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if x < a[mid]: hi = mid + else: lo = mid+1 + a.insert(lo, x) + +def bisect_right(a, x, lo=0, hi=None): + """Return the index where to insert item x in list a, assuming a is sorted. + + The return value i is such that all e in a[:i] have e <= x, and all e in + a[i:] have e > x. So if x already appears in the list, a.insert(x) will + insert just after the rightmost x already there. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if x < a[mid]: hi = mid + else: lo = mid+1 + return lo + +def insort_left(a, x, lo=0, hi=None): + """Insert item x in list a, and keep it sorted assuming a is sorted. + + If x is already in a, insert it to the left of the leftmost x. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if a[mid] < x: lo = mid+1 + else: hi = mid + a.insert(lo, x) + + +def bisect_left(a, x, lo=0, hi=None): + """Return the index where to insert item x in list a, assuming a is sorted. + + The return value i is such that all e in a[:i] have e < x, and all e in + a[i:] have e >= x. So if x already appears in the list, a.insert(x) will + insert just before the leftmost x already there. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + """ + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if a[mid] < x: lo = mid+1 + else: hi = mid + return lo + +# Overwrite above definitions with a fast C implementation +try: + from _bisect import * +except ImportError: + pass + +# Create aliases +bisect = bisect_right +insort = insort_right diff --git a/winvenv/Lib/codecs.py b/winvenv/Lib/codecs.py new file mode 100644 index 0000000..a70ed20 --- /dev/null +++ b/winvenv/Lib/codecs.py @@ -0,0 +1,1114 @@ +""" codecs -- Python Codec Registry, API and helpers. + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" + +import builtins +import sys + +### Registry and builtin stateless codec functions + +try: + from _codecs import * +except ImportError as why: + raise SystemError('Failed to load the builtin codecs: %s' % why) + +__all__ = ["register", "lookup", "open", "EncodedFile", "BOM", "BOM_BE", + "BOM_LE", "BOM32_BE", "BOM32_LE", "BOM64_BE", "BOM64_LE", + "BOM_UTF8", "BOM_UTF16", "BOM_UTF16_LE", "BOM_UTF16_BE", + "BOM_UTF32", "BOM_UTF32_LE", "BOM_UTF32_BE", + "CodecInfo", "Codec", "IncrementalEncoder", "IncrementalDecoder", + "StreamReader", "StreamWriter", + "StreamReaderWriter", "StreamRecoder", + "getencoder", "getdecoder", "getincrementalencoder", + "getincrementaldecoder", "getreader", "getwriter", + "encode", "decode", "iterencode", "iterdecode", + "strict_errors", "ignore_errors", "replace_errors", + "xmlcharrefreplace_errors", + "backslashreplace_errors", "namereplace_errors", + "register_error", "lookup_error"] + +### Constants + +# +# Byte Order Mark (BOM = ZERO WIDTH NO-BREAK SPACE = U+FEFF) +# and its possible byte string values +# for UTF8/UTF16/UTF32 output and little/big endian machines +# + +# UTF-8 +BOM_UTF8 = b'\xef\xbb\xbf' + +# UTF-16, little endian +BOM_LE = BOM_UTF16_LE = b'\xff\xfe' + +# UTF-16, big endian +BOM_BE = BOM_UTF16_BE = b'\xfe\xff' + +# UTF-32, little endian +BOM_UTF32_LE = b'\xff\xfe\x00\x00' + +# UTF-32, big endian +BOM_UTF32_BE = b'\x00\x00\xfe\xff' + +if sys.byteorder == 'little': + + # UTF-16, native endianness + BOM = BOM_UTF16 = BOM_UTF16_LE + + # UTF-32, native endianness + BOM_UTF32 = BOM_UTF32_LE + +else: + + # UTF-16, native endianness + BOM = BOM_UTF16 = BOM_UTF16_BE + + # UTF-32, native endianness + BOM_UTF32 = BOM_UTF32_BE + +# Old broken names (don't use in new code) +BOM32_LE = BOM_UTF16_LE +BOM32_BE = BOM_UTF16_BE +BOM64_LE = BOM_UTF32_LE +BOM64_BE = BOM_UTF32_BE + + +### Codec base classes (defining the API) + +class CodecInfo(tuple): + """Codec details when looking up the codec registry""" + + # Private API to allow Python 3.4 to blacklist the known non-Unicode + # codecs in the standard library. A more general mechanism to + # reliably distinguish test encodings from other codecs will hopefully + # be defined for Python 3.5 + # + # See http://bugs.python.org/issue19619 + _is_text_encoding = True # Assume codecs are text encodings by default + + def __new__(cls, encode, decode, streamreader=None, streamwriter=None, + incrementalencoder=None, incrementaldecoder=None, name=None, + *, _is_text_encoding=None): + self = tuple.__new__(cls, (encode, decode, streamreader, streamwriter)) + self.name = name + self.encode = encode + self.decode = decode + self.incrementalencoder = incrementalencoder + self.incrementaldecoder = incrementaldecoder + self.streamwriter = streamwriter + self.streamreader = streamreader + if _is_text_encoding is not None: + self._is_text_encoding = _is_text_encoding + return self + + def __repr__(self): + return "<%s.%s object for encoding %s at %#x>" % \ + (self.__class__.__module__, self.__class__.__qualname__, + self.name, id(self)) + +class Codec: + + """ Defines the interface for stateless encoders/decoders. + + The .encode()/.decode() methods may use different error + handling schemes by providing the errors argument. These + string values are predefined: + + 'strict' - raise a ValueError error (or a subclass) + 'ignore' - ignore the character and continue with the next + 'replace' - replace with a suitable replacement character; + Python will use the official U+FFFD REPLACEMENT + CHARACTER for the builtin Unicode codecs on + decoding and '?' on encoding. + 'surrogateescape' - replace with private code points U+DCnn. + 'xmlcharrefreplace' - Replace with the appropriate XML + character reference (only for encoding). + 'backslashreplace' - Replace with backslashed escape sequences. + 'namereplace' - Replace with \\N{...} escape sequences + (only for encoding). + + The set of allowed values can be extended via register_error. + + """ + def encode(self, input, errors='strict'): + + """ Encodes the object input and returns a tuple (output + object, length consumed). + + errors defines the error handling to apply. It defaults to + 'strict' handling. + + The method may not store state in the Codec instance. Use + StreamWriter for codecs which have to keep state in order to + make encoding efficient. + + The encoder must be able to handle zero length input and + return an empty object of the output object type in this + situation. + + """ + raise NotImplementedError + + def decode(self, input, errors='strict'): + + """ Decodes the object input and returns a tuple (output + object, length consumed). + + input must be an object which provides the bf_getreadbuf + buffer slot. Python strings, buffer objects and memory + mapped files are examples of objects providing this slot. + + errors defines the error handling to apply. It defaults to + 'strict' handling. + + The method may not store state in the Codec instance. Use + StreamReader for codecs which have to keep state in order to + make decoding efficient. + + The decoder must be able to handle zero length input and + return an empty object of the output object type in this + situation. + + """ + raise NotImplementedError + +class IncrementalEncoder(object): + """ + An IncrementalEncoder encodes an input in multiple steps. The input can + be passed piece by piece to the encode() method. The IncrementalEncoder + remembers the state of the encoding process between calls to encode(). + """ + def __init__(self, errors='strict'): + """ + Creates an IncrementalEncoder instance. + + The IncrementalEncoder may use different error handling schemes by + providing the errors keyword argument. See the module docstring + for a list of possible values. + """ + self.errors = errors + self.buffer = "" + + def encode(self, input, final=False): + """ + Encodes input and returns the resulting object. + """ + raise NotImplementedError + + def reset(self): + """ + Resets the encoder to the initial state. + """ + + def getstate(self): + """ + Return the current state of the encoder. + """ + return 0 + + def setstate(self, state): + """ + Set the current state of the encoder. state must have been + returned by getstate(). + """ + +class BufferedIncrementalEncoder(IncrementalEncoder): + """ + This subclass of IncrementalEncoder can be used as the baseclass for an + incremental encoder if the encoder must keep some of the output in a + buffer between calls to encode(). + """ + def __init__(self, errors='strict'): + IncrementalEncoder.__init__(self, errors) + # unencoded input that is kept between calls to encode() + self.buffer = "" + + def _buffer_encode(self, input, errors, final): + # Overwrite this method in subclasses: It must encode input + # and return an (output, length consumed) tuple + raise NotImplementedError + + def encode(self, input, final=False): + # encode input (taking the buffer into account) + data = self.buffer + input + (result, consumed) = self._buffer_encode(data, self.errors, final) + # keep unencoded input until the next call + self.buffer = data[consumed:] + return result + + def reset(self): + IncrementalEncoder.reset(self) + self.buffer = "" + + def getstate(self): + return self.buffer or 0 + + def setstate(self, state): + self.buffer = state or "" + +class IncrementalDecoder(object): + """ + An IncrementalDecoder decodes an input in multiple steps. The input can + be passed piece by piece to the decode() method. The IncrementalDecoder + remembers the state of the decoding process between calls to decode(). + """ + def __init__(self, errors='strict'): + """ + Create an IncrementalDecoder instance. + + The IncrementalDecoder may use different error handling schemes by + providing the errors keyword argument. See the module docstring + for a list of possible values. + """ + self.errors = errors + + def decode(self, input, final=False): + """ + Decode input and returns the resulting object. + """ + raise NotImplementedError + + def reset(self): + """ + Reset the decoder to the initial state. + """ + + def getstate(self): + """ + Return the current state of the decoder. + + This must be a (buffered_input, additional_state_info) tuple. + buffered_input must be a bytes object containing bytes that + were passed to decode() that have not yet been converted. + additional_state_info must be a non-negative integer + representing the state of the decoder WITHOUT yet having + processed the contents of buffered_input. In the initial state + and after reset(), getstate() must return (b"", 0). + """ + return (b"", 0) + + def setstate(self, state): + """ + Set the current state of the decoder. + + state must have been returned by getstate(). The effect of + setstate((b"", 0)) must be equivalent to reset(). + """ + +class BufferedIncrementalDecoder(IncrementalDecoder): + """ + This subclass of IncrementalDecoder can be used as the baseclass for an + incremental decoder if the decoder must be able to handle incomplete + byte sequences. + """ + def __init__(self, errors='strict'): + IncrementalDecoder.__init__(self, errors) + # undecoded input that is kept between calls to decode() + self.buffer = b"" + + def _buffer_decode(self, input, errors, final): + # Overwrite this method in subclasses: It must decode input + # and return an (output, length consumed) tuple + raise NotImplementedError + + def decode(self, input, final=False): + # decode input (taking the buffer into account) + data = self.buffer + input + (result, consumed) = self._buffer_decode(data, self.errors, final) + # keep undecoded input until the next call + self.buffer = data[consumed:] + return result + + def reset(self): + IncrementalDecoder.reset(self) + self.buffer = b"" + + def getstate(self): + # additional state info is always 0 + return (self.buffer, 0) + + def setstate(self, state): + # ignore additional state info + self.buffer = state[0] + +# +# The StreamWriter and StreamReader class provide generic working +# interfaces which can be used to implement new encoding submodules +# very easily. See encodings/utf_8.py for an example on how this is +# done. +# + +class StreamWriter(Codec): + + def __init__(self, stream, errors='strict'): + + """ Creates a StreamWriter instance. + + stream must be a file-like object open for writing. + + The StreamWriter may use different error handling + schemes by providing the errors keyword argument. These + parameters are predefined: + + 'strict' - raise a ValueError (or a subclass) + 'ignore' - ignore the character and continue with the next + 'replace'- replace with a suitable replacement character + 'xmlcharrefreplace' - Replace with the appropriate XML + character reference. + 'backslashreplace' - Replace with backslashed escape + sequences. + 'namereplace' - Replace with \\N{...} escape sequences. + + The set of allowed parameter values can be extended via + register_error. + """ + self.stream = stream + self.errors = errors + + def write(self, object): + + """ Writes the object's contents encoded to self.stream. + """ + data, consumed = self.encode(object, self.errors) + self.stream.write(data) + + def writelines(self, list): + + """ Writes the concatenated list of strings to the stream + using .write(). + """ + self.write(''.join(list)) + + def reset(self): + + """ Flushes and resets the codec buffers used for keeping state. + + Calling this method should ensure that the data on the + output is put into a clean state, that allows appending + of new fresh data without having to rescan the whole + stream to recover state. + + """ + pass + + def seek(self, offset, whence=0): + self.stream.seek(offset, whence) + if whence == 0 and offset == 0: + self.reset() + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### + +class StreamReader(Codec): + + charbuffertype = str + + def __init__(self, stream, errors='strict'): + + """ Creates a StreamReader instance. + + stream must be a file-like object open for reading. + + The StreamReader may use different error handling + schemes by providing the errors keyword argument. These + parameters are predefined: + + 'strict' - raise a ValueError (or a subclass) + 'ignore' - ignore the character and continue with the next + 'replace'- replace with a suitable replacement character + 'backslashreplace' - Replace with backslashed escape sequences; + + The set of allowed parameter values can be extended via + register_error. + """ + self.stream = stream + self.errors = errors + self.bytebuffer = b"" + self._empty_charbuffer = self.charbuffertype() + self.charbuffer = self._empty_charbuffer + self.linebuffer = None + + def decode(self, input, errors='strict'): + raise NotImplementedError + + def read(self, size=-1, chars=-1, firstline=False): + + """ Decodes data from the stream self.stream and returns the + resulting object. + + chars indicates the number of decoded code points or bytes to + return. read() will never return more data than requested, + but it might return less, if there is not enough available. + + size indicates the approximate maximum number of decoded + bytes or code points to read for decoding. The decoder + can modify this setting as appropriate. The default value + -1 indicates to read and decode as much as possible. size + is intended to prevent having to decode huge files in one + step. + + If firstline is true, and a UnicodeDecodeError happens + after the first line terminator in the input only the first line + will be returned, the rest of the input will be kept until the + next call to read(). + + The method should use a greedy read strategy, meaning that + it should read as much data as is allowed within the + definition of the encoding and the given size, e.g. if + optional encoding endings or state markers are available + on the stream, these should be read too. + """ + # If we have lines cached, first merge them back into characters + if self.linebuffer: + self.charbuffer = self._empty_charbuffer.join(self.linebuffer) + self.linebuffer = None + + if chars < 0: + # For compatibility with other read() methods that take a + # single argument + chars = size + + # read until we get the required number of characters (if available) + while True: + # can the request be satisfied from the character buffer? + if chars >= 0: + if len(self.charbuffer) >= chars: + break + # we need more data + if size < 0: + newdata = self.stream.read() + else: + newdata = self.stream.read(size) + # decode bytes (those remaining from the last call included) + data = self.bytebuffer + newdata + if not data: + break + try: + newchars, decodedbytes = self.decode(data, self.errors) + except UnicodeDecodeError as exc: + if firstline: + newchars, decodedbytes = \ + self.decode(data[:exc.start], self.errors) + lines = newchars.splitlines(keepends=True) + if len(lines)<=1: + raise + else: + raise + # keep undecoded bytes until the next call + self.bytebuffer = data[decodedbytes:] + # put new characters in the character buffer + self.charbuffer += newchars + # there was no data available + if not newdata: + break + if chars < 0: + # Return everything we've got + result = self.charbuffer + self.charbuffer = self._empty_charbuffer + else: + # Return the first chars characters + result = self.charbuffer[:chars] + self.charbuffer = self.charbuffer[chars:] + return result + + def readline(self, size=None, keepends=True): + + """ Read one line from the input stream and return the + decoded data. + + size, if given, is passed as size argument to the + read() method. + + """ + # If we have lines cached from an earlier read, return + # them unconditionally + if self.linebuffer: + line = self.linebuffer[0] + del self.linebuffer[0] + if len(self.linebuffer) == 1: + # revert to charbuffer mode; we might need more data + # next time + self.charbuffer = self.linebuffer[0] + self.linebuffer = None + if not keepends: + line = line.splitlines(keepends=False)[0] + return line + + readsize = size or 72 + line = self._empty_charbuffer + # If size is given, we call read() only once + while True: + data = self.read(readsize, firstline=True) + if data: + # If we're at a "\r" read one extra character (which might + # be a "\n") to get a proper line ending. If the stream is + # temporarily exhausted we return the wrong line ending. + if (isinstance(data, str) and data.endswith("\r")) or \ + (isinstance(data, bytes) and data.endswith(b"\r")): + data += self.read(size=1, chars=1) + + line += data + lines = line.splitlines(keepends=True) + if lines: + if len(lines) > 1: + # More than one line result; the first line is a full line + # to return + line = lines[0] + del lines[0] + if len(lines) > 1: + # cache the remaining lines + lines[-1] += self.charbuffer + self.linebuffer = lines + self.charbuffer = None + else: + # only one remaining line, put it back into charbuffer + self.charbuffer = lines[0] + self.charbuffer + if not keepends: + line = line.splitlines(keepends=False)[0] + break + line0withend = lines[0] + line0withoutend = lines[0].splitlines(keepends=False)[0] + if line0withend != line0withoutend: # We really have a line end + # Put the rest back together and keep it until the next call + self.charbuffer = self._empty_charbuffer.join(lines[1:]) + \ + self.charbuffer + if keepends: + line = line0withend + else: + line = line0withoutend + break + # we didn't get anything or this was our only try + if not data or size is not None: + if line and not keepends: + line = line.splitlines(keepends=False)[0] + break + if readsize < 8000: + readsize *= 2 + return line + + def readlines(self, sizehint=None, keepends=True): + + """ Read all lines available on the input stream + and return them as a list. + + Line breaks are implemented using the codec's decoder + method and are included in the list entries. + + sizehint, if given, is ignored since there is no efficient + way to finding the true end-of-line. + + """ + data = self.read() + return data.splitlines(keepends) + + def reset(self): + + """ Resets the codec buffers used for keeping state. + + Note that no stream repositioning should take place. + This method is primarily intended to be able to recover + from decoding errors. + + """ + self.bytebuffer = b"" + self.charbuffer = self._empty_charbuffer + self.linebuffer = None + + def seek(self, offset, whence=0): + """ Set the input stream's current position. + + Resets the codec buffers used for keeping state. + """ + self.stream.seek(offset, whence) + self.reset() + + def __next__(self): + + """ Return the next decoded line from the input stream.""" + line = self.readline() + if line: + return line + raise StopIteration + + def __iter__(self): + return self + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### + +class StreamReaderWriter: + + """ StreamReaderWriter instances allow wrapping streams which + work in both read and write modes. + + The design is such that one can use the factory functions + returned by the codec.lookup() function to construct the + instance. + + """ + # Optional attributes set by the file wrappers below + encoding = 'unknown' + + def __init__(self, stream, Reader, Writer, errors='strict'): + + """ Creates a StreamReaderWriter instance. + + stream must be a Stream-like object. + + Reader, Writer must be factory functions or classes + providing the StreamReader, StreamWriter interface resp. + + Error handling is done in the same way as defined for the + StreamWriter/Readers. + + """ + self.stream = stream + self.reader = Reader(stream, errors) + self.writer = Writer(stream, errors) + self.errors = errors + + def read(self, size=-1): + + return self.reader.read(size) + + def readline(self, size=None): + + return self.reader.readline(size) + + def readlines(self, sizehint=None): + + return self.reader.readlines(sizehint) + + def __next__(self): + + """ Return the next decoded line from the input stream.""" + return next(self.reader) + + def __iter__(self): + return self + + def write(self, data): + + return self.writer.write(data) + + def writelines(self, list): + + return self.writer.writelines(list) + + def reset(self): + + self.reader.reset() + self.writer.reset() + + def seek(self, offset, whence=0): + self.stream.seek(offset, whence) + self.reader.reset() + if whence == 0 and offset == 0: + self.writer.reset() + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + # these are needed to make "with StreamReaderWriter(...)" work properly + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### + +class StreamRecoder: + + """ StreamRecoder instances translate data from one encoding to another. + + They use the complete set of APIs returned by the + codecs.lookup() function to implement their task. + + Data written to the StreamRecoder is first decoded into an + intermediate format (depending on the "decode" codec) and then + written to the underlying stream using an instance of the provided + Writer class. + + In the other direction, data is read from the underlying stream using + a Reader instance and then encoded and returned to the caller. + + """ + # Optional attributes set by the file wrappers below + data_encoding = 'unknown' + file_encoding = 'unknown' + + def __init__(self, stream, encode, decode, Reader, Writer, + errors='strict'): + + """ Creates a StreamRecoder instance which implements a two-way + conversion: encode and decode work on the frontend (the + data visible to .read() and .write()) while Reader and Writer + work on the backend (the data in stream). + + You can use these objects to do transparent + transcodings from e.g. latin-1 to utf-8 and back. + + stream must be a file-like object. + + encode and decode must adhere to the Codec interface; Reader and + Writer must be factory functions or classes providing the + StreamReader and StreamWriter interfaces resp. + + Error handling is done in the same way as defined for the + StreamWriter/Readers. + + """ + self.stream = stream + self.encode = encode + self.decode = decode + self.reader = Reader(stream, errors) + self.writer = Writer(stream, errors) + self.errors = errors + + def read(self, size=-1): + + data = self.reader.read(size) + data, bytesencoded = self.encode(data, self.errors) + return data + + def readline(self, size=None): + + if size is None: + data = self.reader.readline() + else: + data = self.reader.readline(size) + data, bytesencoded = self.encode(data, self.errors) + return data + + def readlines(self, sizehint=None): + + data = self.reader.read() + data, bytesencoded = self.encode(data, self.errors) + return data.splitlines(keepends=True) + + def __next__(self): + + """ Return the next decoded line from the input stream.""" + data = next(self.reader) + data, bytesencoded = self.encode(data, self.errors) + return data + + def __iter__(self): + return self + + def write(self, data): + + data, bytesdecoded = self.decode(data, self.errors) + return self.writer.write(data) + + def writelines(self, list): + + data = ''.join(list) + data, bytesdecoded = self.decode(data, self.errors) + return self.writer.write(data) + + def reset(self): + + self.reader.reset() + self.writer.reset() + + def __getattr__(self, name, + getattr=getattr): + + """ Inherit all other methods from the underlying stream. + """ + return getattr(self.stream, name) + + def __enter__(self): + return self + + def __exit__(self, type, value, tb): + self.stream.close() + +### Shortcuts + +def open(filename, mode='r', encoding=None, errors='strict', buffering=1): + + """ Open an encoded file using the given mode and return + a wrapped version providing transparent encoding/decoding. + + Note: The wrapped version will only accept the object format + defined by the codecs, i.e. Unicode objects for most builtin + codecs. Output is also codec dependent and will usually be + Unicode as well. + + Underlying encoded files are always opened in binary mode. + The default file mode is 'r', meaning to open the file in read mode. + + encoding specifies the encoding which is to be used for the + file. + + errors may be given to define the error handling. It defaults + to 'strict' which causes ValueErrors to be raised in case an + encoding error occurs. + + buffering has the same meaning as for the builtin open() API. + It defaults to line buffered. + + The returned wrapped file object provides an extra attribute + .encoding which allows querying the used encoding. This + attribute is only available if an encoding was specified as + parameter. + + """ + if encoding is not None and \ + 'b' not in mode: + # Force opening of the file in binary mode + mode = mode + 'b' + file = builtins.open(filename, mode, buffering) + if encoding is None: + return file + info = lookup(encoding) + srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) + # Add attributes to simplify introspection + srw.encoding = encoding + return srw + +def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): + + """ Return a wrapped version of file which provides transparent + encoding translation. + + Data written to the wrapped file is decoded according + to the given data_encoding and then encoded to the underlying + file using file_encoding. The intermediate data type + will usually be Unicode but depends on the specified codecs. + + Bytes read from the file are decoded using file_encoding and then + passed back to the caller encoded using data_encoding. + + If file_encoding is not given, it defaults to data_encoding. + + errors may be given to define the error handling. It defaults + to 'strict' which causes ValueErrors to be raised in case an + encoding error occurs. + + The returned wrapped file object provides two extra attributes + .data_encoding and .file_encoding which reflect the given + parameters of the same name. The attributes can be used for + introspection by Python programs. + + """ + if file_encoding is None: + file_encoding = data_encoding + data_info = lookup(data_encoding) + file_info = lookup(file_encoding) + sr = StreamRecoder(file, data_info.encode, data_info.decode, + file_info.streamreader, file_info.streamwriter, errors) + # Add attributes to simplify introspection + sr.data_encoding = data_encoding + sr.file_encoding = file_encoding + return sr + +### Helpers for codec lookup + +def getencoder(encoding): + + """ Lookup up the codec for the given encoding and return + its encoder function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).encode + +def getdecoder(encoding): + + """ Lookup up the codec for the given encoding and return + its decoder function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).decode + +def getincrementalencoder(encoding): + + """ Lookup up the codec for the given encoding and return + its IncrementalEncoder class or factory function. + + Raises a LookupError in case the encoding cannot be found + or the codecs doesn't provide an incremental encoder. + + """ + encoder = lookup(encoding).incrementalencoder + if encoder is None: + raise LookupError(encoding) + return encoder + +def getincrementaldecoder(encoding): + + """ Lookup up the codec for the given encoding and return + its IncrementalDecoder class or factory function. + + Raises a LookupError in case the encoding cannot be found + or the codecs doesn't provide an incremental decoder. + + """ + decoder = lookup(encoding).incrementaldecoder + if decoder is None: + raise LookupError(encoding) + return decoder + +def getreader(encoding): + + """ Lookup up the codec for the given encoding and return + its StreamReader class or factory function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).streamreader + +def getwriter(encoding): + + """ Lookup up the codec for the given encoding and return + its StreamWriter class or factory function. + + Raises a LookupError in case the encoding cannot be found. + + """ + return lookup(encoding).streamwriter + +def iterencode(iterator, encoding, errors='strict', **kwargs): + """ + Encoding iterator. + + Encodes the input strings from the iterator using an IncrementalEncoder. + + errors and kwargs are passed through to the IncrementalEncoder + constructor. + """ + encoder = getincrementalencoder(encoding)(errors, **kwargs) + for input in iterator: + output = encoder.encode(input) + if output: + yield output + output = encoder.encode("", True) + if output: + yield output + +def iterdecode(iterator, encoding, errors='strict', **kwargs): + """ + Decoding iterator. + + Decodes the input strings from the iterator using an IncrementalDecoder. + + errors and kwargs are passed through to the IncrementalDecoder + constructor. + """ + decoder = getincrementaldecoder(encoding)(errors, **kwargs) + for input in iterator: + output = decoder.decode(input) + if output: + yield output + output = decoder.decode(b"", True) + if output: + yield output + +### Helpers for charmap-based codecs + +def make_identity_dict(rng): + + """ make_identity_dict(rng) -> dict + + Return a dictionary where elements of the rng sequence are + mapped to themselves. + + """ + return {i:i for i in rng} + +def make_encoding_map(decoding_map): + + """ Creates an encoding map from a decoding map. + + If a target mapping in the decoding map occurs multiple + times, then that target is mapped to None (undefined mapping), + causing an exception when encountered by the charmap codec + during translation. + + One example where this happens is cp875.py which decodes + multiple character to \\u001a. + + """ + m = {} + for k,v in decoding_map.items(): + if not v in m: + m[v] = k + else: + m[v] = None + return m + +### error handlers + +try: + strict_errors = lookup_error("strict") + ignore_errors = lookup_error("ignore") + replace_errors = lookup_error("replace") + xmlcharrefreplace_errors = lookup_error("xmlcharrefreplace") + backslashreplace_errors = lookup_error("backslashreplace") + namereplace_errors = lookup_error("namereplace") +except LookupError: + # In --disable-unicode builds, these error handler are missing + strict_errors = None + ignore_errors = None + replace_errors = None + xmlcharrefreplace_errors = None + backslashreplace_errors = None + namereplace_errors = None + +# Tell modulefinder that using codecs probably needs the encodings +# package +_false = 0 +if _false: + import encodings + +### Tests + +if __name__ == '__main__': + + # Make stdout translate Latin-1 output into UTF-8 output + sys.stdout = EncodedFile(sys.stdout, 'latin-1', 'utf-8') + + # Have stdin translate Latin-1 input into UTF-8 input + sys.stdin = EncodedFile(sys.stdin, 'utf-8', 'latin-1') diff --git a/winvenv/Lib/collections/__init__.py b/winvenv/Lib/collections/__init__.py new file mode 100644 index 0000000..9a753db --- /dev/null +++ b/winvenv/Lib/collections/__init__.py @@ -0,0 +1,1279 @@ +'''This module implements specialized container datatypes providing +alternatives to Python's general purpose built-in containers, dict, +list, set, and tuple. + +* namedtuple factory function for creating tuple subclasses with named fields +* deque list-like container with fast appends and pops on either end +* ChainMap dict-like class for creating a single view of multiple mappings +* Counter dict subclass for counting hashable objects +* OrderedDict dict subclass that remembers the order entries were added +* defaultdict dict subclass that calls a factory function to supply missing values +* UserDict wrapper around dictionary objects for easier dict subclassing +* UserList wrapper around list objects for easier list subclassing +* UserString wrapper around string objects for easier string subclassing + +''' + +__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', + 'UserString', 'Counter', 'OrderedDict', 'ChainMap'] + +import _collections_abc +from operator import itemgetter as _itemgetter, eq as _eq +from keyword import iskeyword as _iskeyword +import sys as _sys +import heapq as _heapq +from _weakref import proxy as _proxy +from itertools import repeat as _repeat, chain as _chain, starmap as _starmap +from reprlib import recursive_repr as _recursive_repr + +try: + from _collections import deque +except ImportError: + pass +else: + _collections_abc.MutableSequence.register(deque) + +try: + from _collections import defaultdict +except ImportError: + pass + + +def __getattr__(name): + # For backwards compatibility, continue to make the collections ABCs + # through Python 3.6 available through the collections module. + # Note, no new collections ABCs were added in Python 3.7 + if name in _collections_abc.__all__: + obj = getattr(_collections_abc, name) + import warnings + warnings.warn("Using or importing the ABCs from 'collections' instead " + "of from 'collections.abc' is deprecated, " + "and in 3.8 it will stop working", + DeprecationWarning, stacklevel=2) + globals()[name] = obj + return obj + raise AttributeError(f'module {__name__!r} has no attribute {name!r}') + +################################################################################ +### OrderedDict +################################################################################ + +class _OrderedDictKeysView(_collections_abc.KeysView): + + def __reversed__(self): + yield from reversed(self._mapping) + +class _OrderedDictItemsView(_collections_abc.ItemsView): + + def __reversed__(self): + for key in reversed(self._mapping): + yield (key, self._mapping[key]) + +class _OrderedDictValuesView(_collections_abc.ValuesView): + + def __reversed__(self): + for key in reversed(self._mapping): + yield self._mapping[key] + +class _Link(object): + __slots__ = 'prev', 'next', 'key', '__weakref__' + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as regular dictionaries. + + # The internal self.__map dict maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # The sentinel is in self.__hardroot with a weakref proxy in self.__root. + # The prev links are weakref proxies (to prevent circular references). + # Individual links are kept alive by the hard reference in self.__map. + # Those hard references disappear when a key is deleted from an OrderedDict. + + def __init__(*args, **kwds): + '''Initialize an ordered dictionary. The signature is the same as + regular dictionaries. Keyword argument order is preserved. + ''' + if not args: + raise TypeError("descriptor '__init__' of 'OrderedDict' object " + "needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__hardroot = _Link() + self.__root = root = _proxy(self.__hardroot) + root.prev = root.next = root + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, + dict_setitem=dict.__setitem__, proxy=_proxy, Link=_Link): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link at the end of the linked list, + # and the inherited dictionary is updated with the new key/value pair. + if key not in self: + self.__map[key] = link = Link() + root = self.__root + last = root.prev + link.prev, link.next, link.key = last, root, key + last.next = link + root.prev = proxy(link) + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which gets + # removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link = self.__map.pop(key) + link_prev = link.prev + link_next = link.next + link_prev.next = link_next + link_next.prev = link_prev + link.prev = None + link.next = None + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + # Traverse the linked list in order. + root = self.__root + curr = root.next + while curr is not root: + yield curr.key + curr = curr.next + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + # Traverse the linked list in reverse order. + root = self.__root + curr = root.prev + while curr is not root: + yield curr.key + curr = curr.prev + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + root = self.__root + root.prev = root.next = root + self.__map.clear() + dict.clear(self) + + def popitem(self, last=True): + '''Remove and return a (key, value) pair from the dictionary. + + Pairs are returned in LIFO order if last is true or FIFO order if false. + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root.prev + link_prev = link.prev + link_prev.next = root + root.prev = link_prev + else: + link = root.next + link_next = link.next + root.next = link_next + link_next.prev = root + key = link.key + del self.__map[key] + value = dict.pop(self, key) + return key, value + + def move_to_end(self, key, last=True): + '''Move an existing element to the end (or beginning if last is false). + + Raise KeyError if the element does not exist. + ''' + link = self.__map[key] + link_prev = link.prev + link_next = link.next + soft_link = link_next.prev + link_prev.next = link_next + link_next.prev = link_prev + root = self.__root + if last: + last = root.prev + link.prev = last + link.next = root + root.prev = soft_link + last.next = link + else: + first = root.next + link.prev = root + link.next = first + first.prev = soft_link + root.next = link + + def __sizeof__(self): + sizeof = _sys.getsizeof + n = len(self) + 1 # number of links including root + size = sizeof(self.__dict__) # instance dictionary + size += sizeof(self.__map) * 2 # internal dict and inherited dict + size += sizeof(self.__hardroot) * n # link objects + size += sizeof(self.__root) * n # proxy objects + return size + + update = __update = _collections_abc.MutableMapping.update + + def keys(self): + "D.keys() -> a set-like object providing a view on D's keys" + return _OrderedDictKeysView(self) + + def items(self): + "D.items() -> a set-like object providing a view on D's items" + return _OrderedDictItemsView(self) + + def values(self): + "D.values() -> an object providing a view on D's values" + return _OrderedDictValuesView(self) + + __ne__ = _collections_abc.MutableMapping.__ne__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding + value. If key is not found, d is returned if given, otherwise KeyError + is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + '''Insert key with a value of default if key is not in the dictionary. + + Return the value for key if key is in the dictionary, else default. + ''' + if key in self: + return self[key] + self[key] = default + return default + + @_recursive_repr() + def __repr__(self): + 'od.__repr__() <==> repr(od)' + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self.items())) + + def __reduce__(self): + 'Return state information for pickling' + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + return self.__class__, (), inst_dict or None, None, iter(self.items()) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''Create a new ordered dictionary with keys from iterable and values set to value. + ''' + self = cls() + for key in iterable: + self[key] = value + return self + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return dict.__eq__(self, other) and all(map(_eq, self, other)) + return dict.__eq__(self, other) + + +try: + from _collections import OrderedDict +except ImportError: + # Leave the pure Python version in place. + pass + + +################################################################################ +### namedtuple +################################################################################ + +_nt_itemgetters = {} + +def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None): + """Returns a new subclass of tuple with named fields. + + >>> Point = namedtuple('Point', ['x', 'y']) + >>> Point.__doc__ # docstring for the new class + 'Point(x, y)' + >>> p = Point(11, y=22) # instantiate with positional args or keywords + >>> p[0] + p[1] # indexable like a plain tuple + 33 + >>> x, y = p # unpack like a regular tuple + >>> x, y + (11, 22) + >>> p.x + p.y # fields also accessible by name + 33 + >>> d = p._asdict() # convert to a dictionary + >>> d['x'] + 11 + >>> Point(**d) # convert from a dictionary + Point(x=11, y=22) + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + Point(x=100, y=22) + + """ + + # Validate the field names. At the user's option, either generate an error + # message or automatically replace the field name with a valid name. + if isinstance(field_names, str): + field_names = field_names.replace(',', ' ').split() + field_names = list(map(str, field_names)) + typename = _sys.intern(str(typename)) + + if rename: + seen = set() + for index, name in enumerate(field_names): + if (not name.isidentifier() + or _iskeyword(name) + or name.startswith('_') + or name in seen): + field_names[index] = f'_{index}' + seen.add(name) + + for name in [typename] + field_names: + if type(name) is not str: + raise TypeError('Type names and field names must be strings') + if not name.isidentifier(): + raise ValueError('Type names and field names must be valid ' + f'identifiers: {name!r}') + if _iskeyword(name): + raise ValueError('Type names and field names cannot be a ' + f'keyword: {name!r}') + + seen = set() + for name in field_names: + if name.startswith('_') and not rename: + raise ValueError('Field names cannot start with an underscore: ' + f'{name!r}') + if name in seen: + raise ValueError(f'Encountered duplicate field name: {name!r}') + seen.add(name) + + field_defaults = {} + if defaults is not None: + defaults = tuple(defaults) + if len(defaults) > len(field_names): + raise TypeError('Got more default values than field names') + field_defaults = dict(reversed(list(zip(reversed(field_names), + reversed(defaults))))) + + # Variables used in the methods and docstrings + field_names = tuple(map(_sys.intern, field_names)) + num_fields = len(field_names) + arg_list = repr(field_names).replace("'", "")[1:-1] + repr_fmt = '(' + ', '.join(f'{name}=%r' for name in field_names) + ')' + tuple_new = tuple.__new__ + _len = len + + # Create all the named tuple methods to be added to the class namespace + + s = f'def __new__(_cls, {arg_list}): return _tuple_new(_cls, ({arg_list}))' + namespace = {'_tuple_new': tuple_new, '__name__': f'namedtuple_{typename}'} + # Note: exec() has the side-effect of interning the field names + exec(s, namespace) + __new__ = namespace['__new__'] + __new__.__doc__ = f'Create new instance of {typename}({arg_list})' + if defaults is not None: + __new__.__defaults__ = defaults + + @classmethod + def _make(cls, iterable): + result = tuple_new(cls, iterable) + if _len(result) != num_fields: + raise TypeError(f'Expected {num_fields} arguments, got {len(result)}') + return result + + _make.__func__.__doc__ = (f'Make a new {typename} object from a sequence ' + 'or iterable') + + def _replace(_self, **kwds): + result = _self._make(map(kwds.pop, field_names, _self)) + if kwds: + raise ValueError(f'Got unexpected field names: {list(kwds)!r}') + return result + + _replace.__doc__ = (f'Return a new {typename} object replacing specified ' + 'fields with new values') + + def __repr__(self): + 'Return a nicely formatted representation string' + return self.__class__.__name__ + repr_fmt % self + + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values.' + return OrderedDict(zip(self._fields, self)) + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + # Modify function metadata to help with introspection and debugging + + for method in (__new__, _make.__func__, _replace, + __repr__, _asdict, __getnewargs__): + method.__qualname__ = f'{typename}.{method.__name__}' + + # Build-up the class namespace dictionary + # and use type() to build the result class + class_namespace = { + '__doc__': f'{typename}({arg_list})', + '__slots__': (), + '_fields': field_names, + '_fields_defaults': field_defaults, + '__new__': __new__, + '_make': _make, + '_replace': _replace, + '__repr__': __repr__, + '_asdict': _asdict, + '__getnewargs__': __getnewargs__, + } + cache = _nt_itemgetters + for index, name in enumerate(field_names): + try: + itemgetter_object, doc = cache[index] + except KeyError: + itemgetter_object = _itemgetter(index) + doc = f'Alias for field number {index}' + cache[index] = itemgetter_object, doc + class_namespace[name] = property(itemgetter_object, doc=doc) + + result = type(typename, (tuple,), class_namespace) + + # For pickling to work, the __module__ variable needs to be set to the frame + # where the named tuple 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), or where the user has + # specified a particular module. + if module is None: + try: + module = _sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + if module is not None: + result.__module__ = module + + return result + + +######################################################################## +### Counter +######################################################################## + +def _count_elements(mapping, iterable): + 'Tally elements from the iterable.' + mapping_get = mapping.get + for elem in iterable: + mapping[elem] = mapping_get(elem, 0) + 1 + +try: # Load C helper function if available + from _collections import _count_elements +except ImportError: + pass + +class Counter(dict): + '''Dict subclass for counting hashable items. Sometimes called a bag + or multiset. Elements are stored as dictionary keys and their counts + are stored as dictionary values. + + >>> c = Counter('abcdeabcdabcaba') # count elements from a string + + >>> c.most_common(3) # three most common elements + [('a', 5), ('b', 4), ('c', 3)] + >>> sorted(c) # list all unique elements + ['a', 'b', 'c', 'd', 'e'] + >>> ''.join(sorted(c.elements())) # list elements with repetitions + 'aaaaabbbbcccdde' + >>> sum(c.values()) # total of all counts + 15 + + >>> c['a'] # count of letter 'a' + 5 + >>> for elem in 'shazam': # update counts from an iterable + ... c[elem] += 1 # by adding 1 to each element's count + >>> c['a'] # now there are seven 'a' + 7 + >>> del c['b'] # remove all 'b' + >>> c['b'] # now there are zero 'b' + 0 + + >>> d = Counter('simsalabim') # make another counter + >>> c.update(d) # add in the second counter + >>> c['a'] # now there are nine 'a' + 9 + + >>> c.clear() # empty the counter + >>> c + Counter() + + Note: If a count is set to zero or reduced to zero, it will remain + in the counter until the entry is deleted or the counter is cleared: + + >>> c = Counter('aaabbc') + >>> c['b'] -= 2 # reduce the count of 'b' by two + >>> c.most_common() # 'b' is still in, but its count is zero + [('a', 3), ('c', 1), ('b', 0)] + + ''' + # References: + # http://en.wikipedia.org/wiki/Multiset + # http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html + # http://www.demo2s.com/Tutorial/Cpp/0380__set-multiset/Catalog0380__set-multiset.htm + # http://code.activestate.com/recipes/259174/ + # Knuth, TAOCP Vol. II section 4.6.3 + + def __init__(*args, **kwds): + '''Create a new, empty Counter object. And if given, count elements + from an input iterable. Or, initialize the count from another mapping + of elements to their counts. + + >>> c = Counter() # a new, empty counter + >>> c = Counter('gallahad') # a new counter from an iterable + >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping + >>> c = Counter(a=4, b=2) # a new counter from keyword args + + ''' + if not args: + raise TypeError("descriptor '__init__' of 'Counter' object " + "needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + super(Counter, self).__init__() + self.update(*args, **kwds) + + def __missing__(self, key): + 'The count of elements not in the Counter is zero.' + # Needed so that self[missing_item] does not raise KeyError + return 0 + + def most_common(self, n=None): + '''List the n most common elements and their counts from the most + common to the least. If n is None, then list all element counts. + + >>> Counter('abcdeabcdabcaba').most_common(3) + [('a', 5), ('b', 4), ('c', 3)] + + ''' + # Emulate Bag.sortedByCount from Smalltalk + if n is None: + return sorted(self.items(), key=_itemgetter(1), reverse=True) + return _heapq.nlargest(n, self.items(), key=_itemgetter(1)) + + def elements(self): + '''Iterator over elements repeating each as many times as its count. + + >>> c = Counter('ABCABC') + >>> sorted(c.elements()) + ['A', 'A', 'B', 'B', 'C', 'C'] + + # Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1 + >>> prime_factors = Counter({2: 2, 3: 3, 17: 1}) + >>> product = 1 + >>> for factor in prime_factors.elements(): # loop over factors + ... product *= factor # and multiply them + >>> product + 1836 + + Note, if an element's count has been set to zero or is a negative + number, elements() will ignore it. + + ''' + # Emulate Bag.do from Smalltalk and Multiset.begin from C++. + return _chain.from_iterable(_starmap(_repeat, self.items())) + + # Override dict methods where necessary + + @classmethod + def fromkeys(cls, iterable, v=None): + # There is no equivalent method for counters because setting v=1 + # means that no element can have a count greater than one. + raise NotImplementedError( + 'Counter.fromkeys() is undefined. Use Counter(iterable) instead.') + + def update(*args, **kwds): + '''Like dict.update() but add counts instead of replacing them. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.update('witch') # add elements from another iterable + >>> d = Counter('watch') + >>> c.update(d) # add elements from another counter + >>> c['h'] # four 'h' in which, witch, and watch + 4 + + ''' + # The regular dict.update() operation makes no sense here because the + # replace behavior results in the some of original untouched counts + # being mixed-in with all of the other counts for a mismash that + # doesn't have a straight-forward interpretation in most counting + # contexts. Instead, we implement straight-addition. Both the inputs + # and outputs are allowed to contain zero and negative counts. + + if not args: + raise TypeError("descriptor 'update' of 'Counter' object " + "needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + iterable = args[0] if args else None + if iterable is not None: + if isinstance(iterable, _collections_abc.Mapping): + if self: + self_get = self.get + for elem, count in iterable.items(): + self[elem] = count + self_get(elem, 0) + else: + super(Counter, self).update(iterable) # fast path when counter is empty + else: + _count_elements(self, iterable) + if kwds: + self.update(kwds) + + def subtract(*args, **kwds): + '''Like dict.update() but subtracts counts instead of replacing them. + Counts can be reduced below zero. Both the inputs and outputs are + allowed to contain zero and negative counts. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.subtract('witch') # subtract elements from another iterable + >>> c.subtract(Counter('watch')) # subtract elements from another counter + >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch + 0 + >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch + -1 + + ''' + if not args: + raise TypeError("descriptor 'subtract' of 'Counter' object " + "needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + iterable = args[0] if args else None + if iterable is not None: + self_get = self.get + if isinstance(iterable, _collections_abc.Mapping): + for elem, count in iterable.items(): + self[elem] = self_get(elem, 0) - count + else: + for elem in iterable: + self[elem] = self_get(elem, 0) - 1 + if kwds: + self.subtract(kwds) + + def copy(self): + 'Return a shallow copy.' + return self.__class__(self) + + def __reduce__(self): + return self.__class__, (dict(self),) + + def __delitem__(self, elem): + 'Like dict.__delitem__() but does not raise KeyError for missing values.' + if elem in self: + super().__delitem__(elem) + + def __repr__(self): + if not self: + return '%s()' % self.__class__.__name__ + try: + items = ', '.join(map('%r: %r'.__mod__, self.most_common())) + return '%s({%s})' % (self.__class__.__name__, items) + except TypeError: + # handle case where values are not orderable + return '{0}({1!r})'.format(self.__class__.__name__, dict(self)) + + # Multiset-style mathematical operations discussed in: + # Knuth TAOCP Volume II section 4.6.3 exercise 19 + # and at http://en.wikipedia.org/wiki/Multiset + # + # Outputs guaranteed to only include positive counts. + # + # To strip negative and zero counts, add-in an empty counter: + # c += Counter() + + def __add__(self, other): + '''Add counts from two counters. + + >>> Counter('abbb') + Counter('bcc') + Counter({'b': 4, 'c': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + newcount = count + other[elem] + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count + return result + + def __sub__(self, other): + ''' Subtract count, but keep only results with positive counts. + + >>> Counter('abbbc') - Counter('bccd') + Counter({'b': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + newcount = count - other[elem] + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count < 0: + result[elem] = 0 - count + return result + + def __or__(self, other): + '''Union is the maximum of value in either of the input counters. + + >>> Counter('abbb') | Counter('bcc') + Counter({'b': 3, 'c': 2, 'a': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + other_count = other[elem] + newcount = other_count if count < other_count else count + if newcount > 0: + result[elem] = newcount + for elem, count in other.items(): + if elem not in self and count > 0: + result[elem] = count + return result + + def __and__(self, other): + ''' Intersection is the minimum of corresponding counts. + + >>> Counter('abbb') & Counter('bcc') + Counter({'b': 1}) + + ''' + if not isinstance(other, Counter): + return NotImplemented + result = Counter() + for elem, count in self.items(): + other_count = other[elem] + newcount = count if count < other_count else other_count + if newcount > 0: + result[elem] = newcount + return result + + def __pos__(self): + 'Adds an empty counter, effectively stripping negative and zero counts' + result = Counter() + for elem, count in self.items(): + if count > 0: + result[elem] = count + return result + + def __neg__(self): + '''Subtracts from an empty counter. Strips positive and zero counts, + and flips the sign on negative counts. + + ''' + result = Counter() + for elem, count in self.items(): + if count < 0: + result[elem] = 0 - count + return result + + def _keep_positive(self): + '''Internal method to strip elements with a negative or zero count''' + nonpositive = [elem for elem, count in self.items() if not count > 0] + for elem in nonpositive: + del self[elem] + return self + + def __iadd__(self, other): + '''Inplace add from another counter, keeping only positive counts. + + >>> c = Counter('abbb') + >>> c += Counter('bcc') + >>> c + Counter({'b': 4, 'c': 2, 'a': 1}) + + ''' + for elem, count in other.items(): + self[elem] += count + return self._keep_positive() + + def __isub__(self, other): + '''Inplace subtract counter, but keep only results with positive counts. + + >>> c = Counter('abbbc') + >>> c -= Counter('bccd') + >>> c + Counter({'b': 2, 'a': 1}) + + ''' + for elem, count in other.items(): + self[elem] -= count + return self._keep_positive() + + def __ior__(self, other): + '''Inplace union is the maximum of value from either counter. + + >>> c = Counter('abbb') + >>> c |= Counter('bcc') + >>> c + Counter({'b': 3, 'c': 2, 'a': 1}) + + ''' + for elem, other_count in other.items(): + count = self[elem] + if other_count > count: + self[elem] = other_count + return self._keep_positive() + + def __iand__(self, other): + '''Inplace intersection is the minimum of corresponding counts. + + >>> c = Counter('abbb') + >>> c &= Counter('bcc') + >>> c + Counter({'b': 1}) + + ''' + for elem, count in self.items(): + other_count = other[elem] + if other_count < count: + self[elem] = other_count + return self._keep_positive() + + +######################################################################## +### ChainMap +######################################################################## + +class ChainMap(_collections_abc.MutableMapping): + ''' A ChainMap groups multiple dicts (or other mappings) together + to create a single, updateable view. + + The underlying mappings are stored in a list. That list is public and can + be accessed or updated using the *maps* attribute. There is no other + state. + + Lookups search the underlying mappings successively until a key is found. + In contrast, writes, updates, and deletions only operate on the first + mapping. + + ''' + + def __init__(self, *maps): + '''Initialize a ChainMap by setting *maps* to the given mappings. + If no mappings are provided, a single empty dictionary is used. + + ''' + self.maps = list(maps) or [{}] # always at least one map + + def __missing__(self, key): + raise KeyError(key) + + def __getitem__(self, key): + for mapping in self.maps: + try: + return mapping[key] # can't use 'key in mapping' with defaultdict + except KeyError: + pass + return self.__missing__(key) # support subclasses that define __missing__ + + def get(self, key, default=None): + return self[key] if key in self else default + + def __len__(self): + return len(set().union(*self.maps)) # reuses stored hash values if possible + + def __iter__(self): + d = {} + for mapping in reversed(self.maps): + d.update(mapping) # reuses stored hash values if possible + return iter(d) + + def __contains__(self, key): + return any(key in m for m in self.maps) + + def __bool__(self): + return any(self.maps) + + @_recursive_repr() + def __repr__(self): + return '{0.__class__.__name__}({1})'.format( + self, ', '.join(map(repr, self.maps))) + + @classmethod + def fromkeys(cls, iterable, *args): + 'Create a ChainMap with a single dict created from the iterable.' + return cls(dict.fromkeys(iterable, *args)) + + def copy(self): + 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' + return self.__class__(self.maps[0].copy(), *self.maps[1:]) + + __copy__ = copy + + def new_child(self, m=None): # like Django's Context.push() + '''New ChainMap with a new map followed by all previous maps. + If no map is provided, an empty dict is used. + ''' + if m is None: + m = {} + return self.__class__(m, *self.maps) + + @property + def parents(self): # like Django's Context.pop() + 'New ChainMap from maps[1:].' + return self.__class__(*self.maps[1:]) + + def __setitem__(self, key, value): + self.maps[0][key] = value + + def __delitem__(self, key): + try: + del self.maps[0][key] + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def popitem(self): + 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' + try: + return self.maps[0].popitem() + except KeyError: + raise KeyError('No keys found in the first mapping.') + + def pop(self, key, *args): + 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' + try: + return self.maps[0].pop(key, *args) + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def clear(self): + 'Clear maps[0], leaving maps[1:] intact.' + self.maps[0].clear() + + +################################################################################ +### UserDict +################################################################################ + +class UserDict(_collections_abc.MutableMapping): + + # Start by filling-out the abstract methods + def __init__(*args, **kwargs): + if not args: + raise TypeError("descriptor '__init__' of 'UserDict' object " + "needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + if args: + dict = args[0] + elif 'dict' in kwargs: + dict = kwargs.pop('dict') + import warnings + warnings.warn("Passing 'dict' as keyword argument is deprecated", + DeprecationWarning, stacklevel=2) + else: + dict = None + self.data = {} + if dict is not None: + self.update(dict) + if len(kwargs): + self.update(kwargs) + def __len__(self): return len(self.data) + def __getitem__(self, key): + if key in self.data: + return self.data[key] + if hasattr(self.__class__, "__missing__"): + return self.__class__.__missing__(self, key) + raise KeyError(key) + def __setitem__(self, key, item): self.data[key] = item + def __delitem__(self, key): del self.data[key] + def __iter__(self): + return iter(self.data) + + # Modify __contains__ to work correctly when __missing__ is present + def __contains__(self, key): + return key in self.data + + # Now, add the methods in dicts but not in MutableMapping + def __repr__(self): return repr(self.data) + def copy(self): + if self.__class__ is UserDict: + return UserDict(self.data.copy()) + import copy + data = self.data + try: + self.data = {} + c = copy.copy(self) + finally: + self.data = data + c.update(self) + return c + @classmethod + def fromkeys(cls, iterable, value=None): + d = cls() + for key in iterable: + d[key] = value + return d + + + +################################################################################ +### UserList +################################################################################ + +class UserList(_collections_abc.MutableSequence): + """A more or less complete user-defined wrapper around list objects.""" + def __init__(self, initlist=None): + self.data = [] + if initlist is not None: + # XXX should this accept an arbitrary sequence? + if type(initlist) == type(self.data): + self.data[:] = initlist + elif isinstance(initlist, UserList): + self.data[:] = initlist.data[:] + else: + self.data = list(initlist) + def __repr__(self): return repr(self.data) + def __lt__(self, other): return self.data < self.__cast(other) + def __le__(self, other): return self.data <= self.__cast(other) + def __eq__(self, other): return self.data == self.__cast(other) + def __gt__(self, other): return self.data > self.__cast(other) + def __ge__(self, other): return self.data >= self.__cast(other) + def __cast(self, other): + return other.data if isinstance(other, UserList) else other + def __contains__(self, item): return item in self.data + def __len__(self): return len(self.data) + def __getitem__(self, i): return self.data[i] + def __setitem__(self, i, item): self.data[i] = item + def __delitem__(self, i): del self.data[i] + def __add__(self, other): + if isinstance(other, UserList): + return self.__class__(self.data + other.data) + elif isinstance(other, type(self.data)): + return self.__class__(self.data + other) + return self.__class__(self.data + list(other)) + def __radd__(self, other): + if isinstance(other, UserList): + return self.__class__(other.data + self.data) + elif isinstance(other, type(self.data)): + return self.__class__(other + self.data) + return self.__class__(list(other) + self.data) + def __iadd__(self, other): + if isinstance(other, UserList): + self.data += other.data + elif isinstance(other, type(self.data)): + self.data += other + else: + self.data += list(other) + return self + def __mul__(self, n): + return self.__class__(self.data*n) + __rmul__ = __mul__ + def __imul__(self, n): + self.data *= n + return self + def append(self, item): self.data.append(item) + def insert(self, i, item): self.data.insert(i, item) + def pop(self, i=-1): return self.data.pop(i) + def remove(self, item): self.data.remove(item) + def clear(self): self.data.clear() + def copy(self): return self.__class__(self) + def count(self, item): return self.data.count(item) + def index(self, item, *args): return self.data.index(item, *args) + def reverse(self): self.data.reverse() + def sort(self, *args, **kwds): self.data.sort(*args, **kwds) + def extend(self, other): + if isinstance(other, UserList): + self.data.extend(other.data) + else: + self.data.extend(other) + + + +################################################################################ +### UserString +################################################################################ + +class UserString(_collections_abc.Sequence): + def __init__(self, seq): + if isinstance(seq, str): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq) + def __str__(self): return str(self.data) + def __repr__(self): return repr(self.data) + def __int__(self): return int(self.data) + def __float__(self): return float(self.data) + def __complex__(self): return complex(self.data) + def __hash__(self): return hash(self.data) + def __getnewargs__(self): + return (self.data[:],) + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + return self.data == string + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + return self.data < string + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + return self.data <= string + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + return self.data > string + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + return self.data >= string + + def __contains__(self, char): + if isinstance(char, UserString): + char = char.data + return char in self.data + + def __len__(self): return len(self.data) + def __getitem__(self, index): return self.__class__(self.data[index]) + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, str): + return self.__class__(self.data + other) + return self.__class__(self.data + str(other)) + def __radd__(self, other): + if isinstance(other, str): + return self.__class__(other + self.data) + return self.__class__(str(other) + self.data) + def __mul__(self, n): + return self.__class__(self.data*n) + __rmul__ = __mul__ + def __mod__(self, args): + return self.__class__(self.data % args) + def __rmod__(self, format): + return self.__class__(format % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): return self.__class__(self.data.capitalize()) + def casefold(self): + return self.__class__(self.data.casefold()) + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + def count(self, sub, start=0, end=_sys.maxsize): + if isinstance(sub, UserString): + sub = sub.data + return self.data.count(sub, start, end) + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + return self.__class__(self.data.encode(encoding)) + return self.__class__(self.data.encode()) + def endswith(self, suffix, start=0, end=_sys.maxsize): + return self.data.endswith(suffix, start, end) + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + def find(self, sub, start=0, end=_sys.maxsize): + if isinstance(sub, UserString): + sub = sub.data + return self.data.find(sub, start, end) + def format(self, *args, **kwds): + return self.data.format(*args, **kwds) + def format_map(self, mapping): + return self.data.format_map(mapping) + def index(self, sub, start=0, end=_sys.maxsize): + return self.data.index(sub, start, end) + def isalpha(self): return self.data.isalpha() + def isalnum(self): return self.data.isalnum() + def isascii(self): return self.data.isascii() + def isdecimal(self): return self.data.isdecimal() + def isdigit(self): return self.data.isdigit() + def isidentifier(self): return self.data.isidentifier() + def islower(self): return self.data.islower() + def isnumeric(self): return self.data.isnumeric() + def isprintable(self): return self.data.isprintable() + def isspace(self): return self.data.isspace() + def istitle(self): return self.data.istitle() + def isupper(self): return self.data.isupper() + def join(self, seq): return self.data.join(seq) + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + def lower(self): return self.__class__(self.data.lower()) + def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) + maketrans = str.maketrans + def partition(self, sep): + return self.data.partition(sep) + def replace(self, old, new, maxsplit=-1): + if isinstance(old, UserString): + old = old.data + if isinstance(new, UserString): + new = new.data + return self.__class__(self.data.replace(old, new, maxsplit)) + def rfind(self, sub, start=0, end=_sys.maxsize): + if isinstance(sub, UserString): + sub = sub.data + return self.data.rfind(sub, start, end) + def rindex(self, sub, start=0, end=_sys.maxsize): + return self.data.rindex(sub, start, end) + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + def rpartition(self, sep): + return self.data.rpartition(sep) + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + def splitlines(self, keepends=False): return self.data.splitlines(keepends) + def startswith(self, prefix, start=0, end=_sys.maxsize): + return self.data.startswith(prefix, start, end) + def strip(self, chars=None): return self.__class__(self.data.strip(chars)) + def swapcase(self): return self.__class__(self.data.swapcase()) + def title(self): return self.__class__(self.data.title()) + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + def upper(self): return self.__class__(self.data.upper()) + def zfill(self, width): return self.__class__(self.data.zfill(width)) diff --git a/winvenv/Lib/collections/abc.py b/winvenv/Lib/collections/abc.py new file mode 100644 index 0000000..891600d --- /dev/null +++ b/winvenv/Lib/collections/abc.py @@ -0,0 +1,2 @@ +from _collections_abc import * +from _collections_abc import __all__ diff --git a/winvenv/Lib/copy.py b/winvenv/Lib/copy.py new file mode 100644 index 0000000..f86040a --- /dev/null +++ b/winvenv/Lib/copy.py @@ -0,0 +1,313 @@ +"""Generic (shallow and deep) copying operations. + +Interface summary: + + import copy + + x = copy.copy(y) # make a shallow copy of y + x = copy.deepcopy(y) # make a deep copy of y + +For module specific errors, copy.Error is raised. + +The difference between shallow and deep copying is only relevant for +compound objects (objects that contain other objects, like lists or +class instances). + +- A shallow copy constructs a new compound object and then (to the + extent possible) inserts *the same objects* into it that the + original contains. + +- A deep copy constructs a new compound object and then, recursively, + inserts *copies* into it of the objects found in the original. + +Two problems often exist with deep copy operations that don't exist +with shallow copy operations: + + a) recursive objects (compound objects that, directly or indirectly, + contain a reference to themselves) may cause a recursive loop + + b) because deep copy copies *everything* it may copy too much, e.g. + administrative data structures that should be shared even between + copies + +Python's deep copy operation avoids these problems by: + + a) keeping a table of objects already copied during the current + copying pass + + b) letting user-defined classes override the copying operation or the + set of components copied + +This version does not copy types like module, class, function, method, +nor stack trace, stack frame, nor file, socket, window, nor array, nor +any similar types. + +Classes can use the same interfaces to control copying that they use +to control pickling: they can define methods called __getinitargs__(), +__getstate__() and __setstate__(). See the documentation for module +"pickle" for information on these methods. +""" + +import types +import weakref +from copyreg import dispatch_table + +class Error(Exception): + pass +error = Error # backward compatibility + +try: + from org.python.core import PyStringMap +except ImportError: + PyStringMap = None + +__all__ = ["Error", "copy", "deepcopy"] + +def copy(x): + """Shallow copy operation on arbitrary Python objects. + + See the module's __doc__ string for more info. + """ + + cls = type(x) + + copier = _copy_dispatch.get(cls) + if copier: + return copier(x) + + try: + issc = issubclass(cls, type) + except TypeError: # cls is not a class + issc = False + if issc: + # treat it as a regular class: + return _copy_immutable(x) + + copier = getattr(cls, "__copy__", None) + if copier: + return copier(x) + + reductor = dispatch_table.get(cls) + if reductor: + rv = reductor(x) + else: + reductor = getattr(x, "__reduce_ex__", None) + if reductor: + rv = reductor(4) + else: + reductor = getattr(x, "__reduce__", None) + if reductor: + rv = reductor() + else: + raise Error("un(shallow)copyable object of type %s" % cls) + + if isinstance(rv, str): + return x + return _reconstruct(x, None, *rv) + + +_copy_dispatch = d = {} + +def _copy_immutable(x): + return x +for t in (type(None), int, float, bool, complex, str, tuple, + bytes, frozenset, type, range, slice, + types.BuiltinFunctionType, type(Ellipsis), type(NotImplemented), + types.FunctionType, weakref.ref): + d[t] = _copy_immutable +t = getattr(types, "CodeType", None) +if t is not None: + d[t] = _copy_immutable + +d[list] = list.copy +d[dict] = dict.copy +d[set] = set.copy +d[bytearray] = bytearray.copy + +if PyStringMap is not None: + d[PyStringMap] = PyStringMap.copy + +del d, t + +def deepcopy(x, memo=None, _nil=[]): + """Deep copy operation on arbitrary Python objects. + + See the module's __doc__ string for more info. + """ + + if memo is None: + memo = {} + + d = id(x) + y = memo.get(d, _nil) + if y is not _nil: + return y + + cls = type(x) + + copier = _deepcopy_dispatch.get(cls) + if copier: + y = copier(x, memo) + else: + try: + issc = issubclass(cls, type) + except TypeError: # cls is not a class (old Boost; see SF #502085) + issc = 0 + if issc: + y = _deepcopy_atomic(x, memo) + else: + copier = getattr(x, "__deepcopy__", None) + if copier: + y = copier(memo) + else: + reductor = dispatch_table.get(cls) + if reductor: + rv = reductor(x) + else: + reductor = getattr(x, "__reduce_ex__", None) + if reductor: + rv = reductor(4) + else: + reductor = getattr(x, "__reduce__", None) + if reductor: + rv = reductor() + else: + raise Error( + "un(deep)copyable object of type %s" % cls) + if isinstance(rv, str): + y = x + else: + y = _reconstruct(x, memo, *rv) + + # If is its own copy, don't memoize. + if y is not x: + memo[d] = y + _keep_alive(x, memo) # Make sure x lives at least as long as d + return y + +_deepcopy_dispatch = d = {} + +def _deepcopy_atomic(x, memo): + return x +d[type(None)] = _deepcopy_atomic +d[type(Ellipsis)] = _deepcopy_atomic +d[type(NotImplemented)] = _deepcopy_atomic +d[int] = _deepcopy_atomic +d[float] = _deepcopy_atomic +d[bool] = _deepcopy_atomic +d[complex] = _deepcopy_atomic +d[bytes] = _deepcopy_atomic +d[str] = _deepcopy_atomic +try: + d[types.CodeType] = _deepcopy_atomic +except AttributeError: + pass +d[type] = _deepcopy_atomic +d[types.BuiltinFunctionType] = _deepcopy_atomic +d[types.FunctionType] = _deepcopy_atomic +d[weakref.ref] = _deepcopy_atomic + +def _deepcopy_list(x, memo, deepcopy=deepcopy): + y = [] + memo[id(x)] = y + append = y.append + for a in x: + append(deepcopy(a, memo)) + return y +d[list] = _deepcopy_list + +def _deepcopy_tuple(x, memo, deepcopy=deepcopy): + y = [deepcopy(a, memo) for a in x] + # We're not going to put the tuple in the memo, but it's still important we + # check for it, in case the tuple contains recursive mutable structures. + try: + return memo[id(x)] + except KeyError: + pass + for k, j in zip(x, y): + if k is not j: + y = tuple(y) + break + else: + y = x + return y +d[tuple] = _deepcopy_tuple + +def _deepcopy_dict(x, memo, deepcopy=deepcopy): + y = {} + memo[id(x)] = y + for key, value in x.items(): + y[deepcopy(key, memo)] = deepcopy(value, memo) + return y +d[dict] = _deepcopy_dict +if PyStringMap is not None: + d[PyStringMap] = _deepcopy_dict + +def _deepcopy_method(x, memo): # Copy instance methods + return type(x)(x.__func__, deepcopy(x.__self__, memo)) +d[types.MethodType] = _deepcopy_method + +del d + +def _keep_alive(x, memo): + """Keeps a reference to the object x in the memo. + + Because we remember objects by their id, we have + to assure that possibly temporary objects are kept + alive by referencing them. + We store a reference at the id of the memo, which should + normally not be used unless someone tries to deepcopy + the memo itself... + """ + try: + memo[id(memo)].append(x) + except KeyError: + # aha, this is the first one :-) + memo[id(memo)]=[x] + +def _reconstruct(x, memo, func, args, + state=None, listiter=None, dictiter=None, + deepcopy=deepcopy): + deep = memo is not None + if deep and args: + args = (deepcopy(arg, memo) for arg in args) + y = func(*args) + if deep: + memo[id(x)] = y + + if state is not None: + if deep: + state = deepcopy(state, memo) + if hasattr(y, '__setstate__'): + y.__setstate__(state) + else: + if isinstance(state, tuple) and len(state) == 2: + state, slotstate = state + else: + slotstate = None + if state is not None: + y.__dict__.update(state) + if slotstate is not None: + for key, value in slotstate.items(): + setattr(y, key, value) + + if listiter is not None: + if deep: + for item in listiter: + item = deepcopy(item, memo) + y.append(item) + else: + for item in listiter: + y.append(item) + if dictiter is not None: + if deep: + for key, value in dictiter: + key = deepcopy(key, memo) + value = deepcopy(value, memo) + y[key] = value + else: + for key, value in dictiter: + y[key] = value + return y + +del types, weakref, PyStringMap diff --git a/winvenv/Lib/copyreg.py b/winvenv/Lib/copyreg.py new file mode 100644 index 0000000..bbe1af4 --- /dev/null +++ b/winvenv/Lib/copyreg.py @@ -0,0 +1,206 @@ +"""Helper to provide extensibility for pickle. + +This is only useful to add pickle support for extension types defined in +C, not for instances of user-defined classes. +""" + +__all__ = ["pickle", "constructor", + "add_extension", "remove_extension", "clear_extension_cache"] + +dispatch_table = {} + +def pickle(ob_type, pickle_function, constructor_ob=None): + if not callable(pickle_function): + raise TypeError("reduction functions must be callable") + dispatch_table[ob_type] = pickle_function + + # The constructor_ob function is a vestige of safe for unpickling. + # There is no reason for the caller to pass it anymore. + if constructor_ob is not None: + constructor(constructor_ob) + +def constructor(object): + if not callable(object): + raise TypeError("constructors must be callable") + +# Example: provide pickling support for complex numbers. + +try: + complex +except NameError: + pass +else: + + def pickle_complex(c): + return complex, (c.real, c.imag) + + pickle(complex, pickle_complex, complex) + +# Support for pickling new-style objects + +def _reconstructor(cls, base, state): + if base is object: + obj = object.__new__(cls) + else: + obj = base.__new__(cls, state) + if base.__init__ != object.__init__: + base.__init__(obj, state) + return obj + +_HEAPTYPE = 1<<9 + +# Python code for object.__reduce_ex__ for protocols 0 and 1 + +def _reduce_ex(self, proto): + assert proto < 2 + for base in self.__class__.__mro__: + if hasattr(base, '__flags__') and not base.__flags__ & _HEAPTYPE: + break + else: + base = object # not really reachable + if base is object: + state = None + else: + if base is self.__class__: + raise TypeError("can't pickle %s objects" % base.__name__) + state = base(self) + args = (self.__class__, base, state) + try: + getstate = self.__getstate__ + except AttributeError: + if getattr(self, "__slots__", None): + raise TypeError("a class that defines __slots__ without " + "defining __getstate__ cannot be pickled") from None + try: + dict = self.__dict__ + except AttributeError: + dict = None + else: + dict = getstate() + if dict: + return _reconstructor, args, dict + else: + return _reconstructor, args + +# Helper for __reduce_ex__ protocol 2 + +def __newobj__(cls, *args): + return cls.__new__(cls, *args) + +def __newobj_ex__(cls, args, kwargs): + """Used by pickle protocol 4, instead of __newobj__ to allow classes with + keyword-only arguments to be pickled correctly. + """ + return cls.__new__(cls, *args, **kwargs) + +def _slotnames(cls): + """Return a list of slot names for a given class. + + This needs to find slots defined by the class and its bases, so we + can't simply return the __slots__ attribute. We must walk down + the Method Resolution Order and concatenate the __slots__ of each + class found there. (This assumes classes don't modify their + __slots__ attribute to misrepresent their slots after the class is + defined.) + """ + + # Get the value from a cache in the class if possible + names = cls.__dict__.get("__slotnames__") + if names is not None: + return names + + # Not cached -- calculate the value + names = [] + if not hasattr(cls, "__slots__"): + # This class has no slots + pass + else: + # Slots found -- gather slot names from all base classes + for c in cls.__mro__: + if "__slots__" in c.__dict__: + slots = c.__dict__['__slots__'] + # if class has a single slot, it can be given as a string + if isinstance(slots, str): + slots = (slots,) + for name in slots: + # special descriptors + if name in ("__dict__", "__weakref__"): + continue + # mangled names + elif name.startswith('__') and not name.endswith('__'): + stripped = c.__name__.lstrip('_') + if stripped: + names.append('_%s%s' % (stripped, name)) + else: + names.append(name) + else: + names.append(name) + + # Cache the outcome in the class if at all possible + try: + cls.__slotnames__ = names + except: + pass # But don't die if we can't + + return names + +# A registry of extension codes. This is an ad-hoc compression +# mechanism. Whenever a global reference to , is about +# to be pickled, the (, ) tuple is looked up here to see +# if it is a registered extension code for it. Extension codes are +# universal, so that the meaning of a pickle does not depend on +# context. (There are also some codes reserved for local use that +# don't have this restriction.) Codes are positive ints; 0 is +# reserved. + +_extension_registry = {} # key -> code +_inverted_registry = {} # code -> key +_extension_cache = {} # code -> object +# Don't ever rebind those names: pickling grabs a reference to them when +# it's initialized, and won't see a rebinding. + +def add_extension(module, name, code): + """Register an extension code.""" + code = int(code) + if not 1 <= code <= 0x7fffffff: + raise ValueError("code out of range") + key = (module, name) + if (_extension_registry.get(key) == code and + _inverted_registry.get(code) == key): + return # Redundant registrations are benign + if key in _extension_registry: + raise ValueError("key %s is already registered with code %s" % + (key, _extension_registry[key])) + if code in _inverted_registry: + raise ValueError("code %s is already in use for key %s" % + (code, _inverted_registry[code])) + _extension_registry[key] = code + _inverted_registry[code] = key + +def remove_extension(module, name, code): + """Unregister an extension code. For testing only.""" + key = (module, name) + if (_extension_registry.get(key) != code or + _inverted_registry.get(code) != key): + raise ValueError("key %s is not registered with code %s" % + (key, code)) + del _extension_registry[key] + del _inverted_registry[code] + if code in _extension_cache: + del _extension_cache[code] + +def clear_extension_cache(): + _extension_cache.clear() + +# Standard extension code assignments + +# Reserved ranges + +# First Last Count Purpose +# 1 127 127 Reserved for Python standard library +# 128 191 64 Reserved for Zope +# 192 239 48 Reserved for 3rd parties +# 240 255 16 Reserved for private use (will never be assigned) +# 256 Inf Inf Reserved for future assignment + +# Extension codes are assigned by the Python Software Foundation. diff --git a/winvenv/Lib/distutils/__init__.py b/winvenv/Lib/distutils/__init__.py new file mode 100644 index 0000000..59f55f1 --- /dev/null +++ b/winvenv/Lib/distutils/__init__.py @@ -0,0 +1,116 @@ +import imp +import os +import sys +import warnings + +# opcode is not a virtualenv module, so we can use it to find the stdlib +# Important! To work on pypy, this must be a module that resides in the +# lib-python/modified-x.y.z directory +import opcode + +dirname = os.path.dirname + +distutils_path = os.path.join(os.path.dirname(opcode.__file__), "distutils") +if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)): + warnings.warn("The virtualenv distutils package at %s appears to be in the same location as the system distutils?") +else: + __path__.insert(0, distutils_path) # noqa: F821 + real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ("", "", imp.PKG_DIRECTORY)) + # Copy the relevant attributes + try: + __revision__ = real_distutils.__revision__ + except AttributeError: + pass + __version__ = real_distutils.__version__ + +from distutils import dist, sysconfig # isort:skip + +try: + basestring +except NameError: + basestring = str + +# patch build_ext (distutils doesn't know how to get the libs directory +# path on windows - it hardcodes the paths around the patched sys.prefix) + +if sys.platform == "win32": + from distutils.command.build_ext import build_ext as old_build_ext + + class build_ext(old_build_ext): + def finalize_options(self): + if self.library_dirs is None: + self.library_dirs = [] + elif isinstance(self.library_dirs, basestring): + self.library_dirs = self.library_dirs.split(os.pathsep) + + self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs")) + old_build_ext.finalize_options(self) + + from distutils.command import build_ext as build_ext_module + + build_ext_module.build_ext = build_ext + +# distutils.dist patches: + +old_find_config_files = dist.Distribution.find_config_files + + +def find_config_files(self): + found = old_find_config_files(self) + if os.name == "posix": + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + user_filename = os.path.join(sys.prefix, user_filename) + if os.path.isfile(user_filename): + for item in list(found): + if item.endswith("pydistutils.cfg"): + found.remove(item) + found.append(user_filename) + return found + + +dist.Distribution.find_config_files = find_config_files + +# distutils.sysconfig patches: + +old_get_python_inc = sysconfig.get_python_inc + + +def sysconfig_get_python_inc(plat_specific=0, prefix=None): + if prefix is None: + prefix = sys.real_prefix + return old_get_python_inc(plat_specific, prefix) + + +sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__ +sysconfig.get_python_inc = sysconfig_get_python_inc + +old_get_python_lib = sysconfig.get_python_lib + + +def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + if standard_lib and prefix is None: + prefix = sys.real_prefix + return old_get_python_lib(plat_specific, standard_lib, prefix) + + +sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__ +sysconfig.get_python_lib = sysconfig_get_python_lib + +old_get_config_vars = sysconfig.get_config_vars + + +def sysconfig_get_config_vars(*args): + real_vars = old_get_config_vars(*args) + if sys.platform == "win32": + lib_dir = os.path.join(sys.real_prefix, "libs") + if isinstance(real_vars, dict) and "LIBDIR" not in real_vars: + real_vars["LIBDIR"] = lib_dir # asked for all + elif isinstance(real_vars, list) and "LIBDIR" in args: + real_vars = real_vars + [lib_dir] # asked for list + return real_vars + + +sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__ +sysconfig.get_config_vars = sysconfig_get_config_vars diff --git a/winvenv/Lib/distutils/distutils.cfg b/winvenv/Lib/distutils/distutils.cfg new file mode 100644 index 0000000..1af230e --- /dev/null +++ b/winvenv/Lib/distutils/distutils.cfg @@ -0,0 +1,6 @@ +# This is a config file local to this virtualenv installation +# You may include options that will be used by all distutils commands, +# and by easy_install. For instance: +# +# [easy_install] +# find_links = http://mylocalsite diff --git a/winvenv/Lib/encodings/__init__.py b/winvenv/Lib/encodings/__init__.py new file mode 100644 index 0000000..025b7a8 --- /dev/null +++ b/winvenv/Lib/encodings/__init__.py @@ -0,0 +1,170 @@ +""" Standard "encodings" Package + + Standard Python encoding modules are stored in this package + directory. + + Codec modules must have names corresponding to normalized encoding + names as defined in the normalize_encoding() function below, e.g. + 'utf-8' must be implemented by the module 'utf_8.py'. + + Each codec module must export the following interface: + + * getregentry() -> codecs.CodecInfo object + The getregentry() API must return a CodecInfo object with encoder, decoder, + incrementalencoder, incrementaldecoder, streamwriter and streamreader + atttributes which adhere to the Python Codec Interface Standard. + + In addition, a module may optionally also define the following + APIs which are then used by the package's codec search function: + + * getaliases() -> sequence of encoding name strings to use as aliases + + Alias names returned by getaliases() must be normalized encoding + names as defined by normalize_encoding(). + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +"""#" + +import codecs +import sys +from . import aliases + +_cache = {} +_unknown = '--unknown--' +_import_tail = ['*'] +_aliases = aliases.aliases + +class CodecRegistryError(LookupError, SystemError): + pass + +def normalize_encoding(encoding): + + """ Normalize an encoding name. + + Normalization works as follows: all non-alphanumeric + characters except the dot used for Python package names are + collapsed and replaced with a single underscore, e.g. ' -;#' + becomes '_'. Leading and trailing underscores are removed. + + Note that encoding names should be ASCII only; if they do use + non-ASCII characters, these must be Latin-1 compatible. + + """ + if isinstance(encoding, bytes): + encoding = str(encoding, "ascii") + + chars = [] + punct = False + for c in encoding: + if c.isalnum() or c == '.': + if punct and chars: + chars.append('_') + chars.append(c) + punct = False + else: + punct = True + return ''.join(chars) + +def search_function(encoding): + + # Cache lookup + entry = _cache.get(encoding, _unknown) + if entry is not _unknown: + return entry + + # Import the module: + # + # First try to find an alias for the normalized encoding + # name and lookup the module using the aliased name, then try to + # lookup the module using the standard import scheme, i.e. first + # try in the encodings package, then at top-level. + # + norm_encoding = normalize_encoding(encoding) + aliased_encoding = _aliases.get(norm_encoding) or \ + _aliases.get(norm_encoding.replace('.', '_')) + if aliased_encoding is not None: + modnames = [aliased_encoding, + norm_encoding] + else: + modnames = [norm_encoding] + for modname in modnames: + if not modname or '.' in modname: + continue + try: + # Import is absolute to prevent the possibly malicious import of a + # module with side-effects that is not in the 'encodings' package. + mod = __import__('encodings.' + modname, fromlist=_import_tail, + level=0) + except ImportError: + # ImportError may occur because 'encodings.(modname)' does not exist, + # or because it imports a name that does not exist (see mbcs and oem) + pass + else: + break + else: + mod = None + + try: + getregentry = mod.getregentry + except AttributeError: + # Not a codec module + mod = None + + if mod is None: + # Cache misses + _cache[encoding] = None + return None + + # Now ask the module for the registry entry + entry = getregentry() + if not isinstance(entry, codecs.CodecInfo): + if not 4 <= len(entry) <= 7: + raise CodecRegistryError('module "%s" (%s) failed to register' + % (mod.__name__, mod.__file__)) + if not callable(entry[0]) or not callable(entry[1]) or \ + (entry[2] is not None and not callable(entry[2])) or \ + (entry[3] is not None and not callable(entry[3])) or \ + (len(entry) > 4 and entry[4] is not None and not callable(entry[4])) or \ + (len(entry) > 5 and entry[5] is not None and not callable(entry[5])): + raise CodecRegistryError('incompatible codecs in module "%s" (%s)' + % (mod.__name__, mod.__file__)) + if len(entry)<7 or entry[6] is None: + entry += (None,)*(6-len(entry)) + (mod.__name__.split(".", 1)[1],) + entry = codecs.CodecInfo(*entry) + + # Cache the codec registry entry + _cache[encoding] = entry + + # Register its aliases (without overwriting previously registered + # aliases) + try: + codecaliases = mod.getaliases() + except AttributeError: + pass + else: + for alias in codecaliases: + if alias not in _aliases: + _aliases[alias] = modname + + # Return the registry entry + return entry + +# Register the search_function in the Python codec registry +codecs.register(search_function) + +if sys.platform == 'win32': + def _alias_mbcs(encoding): + try: + import _winapi + ansi_code_page = "cp%s" % _winapi.GetACP() + if encoding == ansi_code_page: + import encodings.mbcs + return encodings.mbcs.getregentry() + except ImportError: + # Imports may fail while we are shutting down + pass + + codecs.register(_alias_mbcs) diff --git a/winvenv/Lib/encodings/aliases.py b/winvenv/Lib/encodings/aliases.py new file mode 100644 index 0000000..2e63c2f --- /dev/null +++ b/winvenv/Lib/encodings/aliases.py @@ -0,0 +1,550 @@ +""" Encoding Aliases Support + + This module is used by the encodings package search function to + map encodings names to module names. + + Note that the search function normalizes the encoding names before + doing the lookup, so the mapping will have to map normalized + encoding names to module names. + + Contents: + + The following aliases dictionary contains mappings of all IANA + character set names for which the Python core library provides + codecs. In addition to these, a few Python specific codec + aliases have also been added. + +""" +aliases = { + + # Please keep this list sorted alphabetically by value ! + + # ascii codec + '646' : 'ascii', + 'ansi_x3.4_1968' : 'ascii', + 'ansi_x3_4_1968' : 'ascii', # some email headers use this non-standard name + 'ansi_x3.4_1986' : 'ascii', + 'cp367' : 'ascii', + 'csascii' : 'ascii', + 'ibm367' : 'ascii', + 'iso646_us' : 'ascii', + 'iso_646.irv_1991' : 'ascii', + 'iso_ir_6' : 'ascii', + 'us' : 'ascii', + 'us_ascii' : 'ascii', + + # base64_codec codec + 'base64' : 'base64_codec', + 'base_64' : 'base64_codec', + + # big5 codec + 'big5_tw' : 'big5', + 'csbig5' : 'big5', + + # big5hkscs codec + 'big5_hkscs' : 'big5hkscs', + 'hkscs' : 'big5hkscs', + + # bz2_codec codec + 'bz2' : 'bz2_codec', + + # cp037 codec + '037' : 'cp037', + 'csibm037' : 'cp037', + 'ebcdic_cp_ca' : 'cp037', + 'ebcdic_cp_nl' : 'cp037', + 'ebcdic_cp_us' : 'cp037', + 'ebcdic_cp_wt' : 'cp037', + 'ibm037' : 'cp037', + 'ibm039' : 'cp037', + + # cp1026 codec + '1026' : 'cp1026', + 'csibm1026' : 'cp1026', + 'ibm1026' : 'cp1026', + + # cp1125 codec + '1125' : 'cp1125', + 'ibm1125' : 'cp1125', + 'cp866u' : 'cp1125', + 'ruscii' : 'cp1125', + + # cp1140 codec + '1140' : 'cp1140', + 'ibm1140' : 'cp1140', + + # cp1250 codec + '1250' : 'cp1250', + 'windows_1250' : 'cp1250', + + # cp1251 codec + '1251' : 'cp1251', + 'windows_1251' : 'cp1251', + + # cp1252 codec + '1252' : 'cp1252', + 'windows_1252' : 'cp1252', + + # cp1253 codec + '1253' : 'cp1253', + 'windows_1253' : 'cp1253', + + # cp1254 codec + '1254' : 'cp1254', + 'windows_1254' : 'cp1254', + + # cp1255 codec + '1255' : 'cp1255', + 'windows_1255' : 'cp1255', + + # cp1256 codec + '1256' : 'cp1256', + 'windows_1256' : 'cp1256', + + # cp1257 codec + '1257' : 'cp1257', + 'windows_1257' : 'cp1257', + + # cp1258 codec + '1258' : 'cp1258', + 'windows_1258' : 'cp1258', + + # cp273 codec + '273' : 'cp273', + 'ibm273' : 'cp273', + 'csibm273' : 'cp273', + + # cp424 codec + '424' : 'cp424', + 'csibm424' : 'cp424', + 'ebcdic_cp_he' : 'cp424', + 'ibm424' : 'cp424', + + # cp437 codec + '437' : 'cp437', + 'cspc8codepage437' : 'cp437', + 'ibm437' : 'cp437', + + # cp500 codec + '500' : 'cp500', + 'csibm500' : 'cp500', + 'ebcdic_cp_be' : 'cp500', + 'ebcdic_cp_ch' : 'cp500', + 'ibm500' : 'cp500', + + # cp775 codec + '775' : 'cp775', + 'cspc775baltic' : 'cp775', + 'ibm775' : 'cp775', + + # cp850 codec + '850' : 'cp850', + 'cspc850multilingual' : 'cp850', + 'ibm850' : 'cp850', + + # cp852 codec + '852' : 'cp852', + 'cspcp852' : 'cp852', + 'ibm852' : 'cp852', + + # cp855 codec + '855' : 'cp855', + 'csibm855' : 'cp855', + 'ibm855' : 'cp855', + + # cp857 codec + '857' : 'cp857', + 'csibm857' : 'cp857', + 'ibm857' : 'cp857', + + # cp858 codec + '858' : 'cp858', + 'csibm858' : 'cp858', + 'ibm858' : 'cp858', + + # cp860 codec + '860' : 'cp860', + 'csibm860' : 'cp860', + 'ibm860' : 'cp860', + + # cp861 codec + '861' : 'cp861', + 'cp_is' : 'cp861', + 'csibm861' : 'cp861', + 'ibm861' : 'cp861', + + # cp862 codec + '862' : 'cp862', + 'cspc862latinhebrew' : 'cp862', + 'ibm862' : 'cp862', + + # cp863 codec + '863' : 'cp863', + 'csibm863' : 'cp863', + 'ibm863' : 'cp863', + + # cp864 codec + '864' : 'cp864', + 'csibm864' : 'cp864', + 'ibm864' : 'cp864', + + # cp865 codec + '865' : 'cp865', + 'csibm865' : 'cp865', + 'ibm865' : 'cp865', + + # cp866 codec + '866' : 'cp866', + 'csibm866' : 'cp866', + 'ibm866' : 'cp866', + + # cp869 codec + '869' : 'cp869', + 'cp_gr' : 'cp869', + 'csibm869' : 'cp869', + 'ibm869' : 'cp869', + + # cp932 codec + '932' : 'cp932', + 'ms932' : 'cp932', + 'mskanji' : 'cp932', + 'ms_kanji' : 'cp932', + + # cp949 codec + '949' : 'cp949', + 'ms949' : 'cp949', + 'uhc' : 'cp949', + + # cp950 codec + '950' : 'cp950', + 'ms950' : 'cp950', + + # euc_jis_2004 codec + 'jisx0213' : 'euc_jis_2004', + 'eucjis2004' : 'euc_jis_2004', + 'euc_jis2004' : 'euc_jis_2004', + + # euc_jisx0213 codec + 'eucjisx0213' : 'euc_jisx0213', + + # euc_jp codec + 'eucjp' : 'euc_jp', + 'ujis' : 'euc_jp', + 'u_jis' : 'euc_jp', + + # euc_kr codec + 'euckr' : 'euc_kr', + 'korean' : 'euc_kr', + 'ksc5601' : 'euc_kr', + 'ks_c_5601' : 'euc_kr', + 'ks_c_5601_1987' : 'euc_kr', + 'ksx1001' : 'euc_kr', + 'ks_x_1001' : 'euc_kr', + + # gb18030 codec + 'gb18030_2000' : 'gb18030', + + # gb2312 codec + 'chinese' : 'gb2312', + 'csiso58gb231280' : 'gb2312', + 'euc_cn' : 'gb2312', + 'euccn' : 'gb2312', + 'eucgb2312_cn' : 'gb2312', + 'gb2312_1980' : 'gb2312', + 'gb2312_80' : 'gb2312', + 'iso_ir_58' : 'gb2312', + + # gbk codec + '936' : 'gbk', + 'cp936' : 'gbk', + 'ms936' : 'gbk', + + # hex_codec codec + 'hex' : 'hex_codec', + + # hp_roman8 codec + 'roman8' : 'hp_roman8', + 'r8' : 'hp_roman8', + 'csHPRoman8' : 'hp_roman8', + + # hz codec + 'hzgb' : 'hz', + 'hz_gb' : 'hz', + 'hz_gb_2312' : 'hz', + + # iso2022_jp codec + 'csiso2022jp' : 'iso2022_jp', + 'iso2022jp' : 'iso2022_jp', + 'iso_2022_jp' : 'iso2022_jp', + + # iso2022_jp_1 codec + 'iso2022jp_1' : 'iso2022_jp_1', + 'iso_2022_jp_1' : 'iso2022_jp_1', + + # iso2022_jp_2 codec + 'iso2022jp_2' : 'iso2022_jp_2', + 'iso_2022_jp_2' : 'iso2022_jp_2', + + # iso2022_jp_2004 codec + 'iso_2022_jp_2004' : 'iso2022_jp_2004', + 'iso2022jp_2004' : 'iso2022_jp_2004', + + # iso2022_jp_3 codec + 'iso2022jp_3' : 'iso2022_jp_3', + 'iso_2022_jp_3' : 'iso2022_jp_3', + + # iso2022_jp_ext codec + 'iso2022jp_ext' : 'iso2022_jp_ext', + 'iso_2022_jp_ext' : 'iso2022_jp_ext', + + # iso2022_kr codec + 'csiso2022kr' : 'iso2022_kr', + 'iso2022kr' : 'iso2022_kr', + 'iso_2022_kr' : 'iso2022_kr', + + # iso8859_10 codec + 'csisolatin6' : 'iso8859_10', + 'iso_8859_10' : 'iso8859_10', + 'iso_8859_10_1992' : 'iso8859_10', + 'iso_ir_157' : 'iso8859_10', + 'l6' : 'iso8859_10', + 'latin6' : 'iso8859_10', + + # iso8859_11 codec + 'thai' : 'iso8859_11', + 'iso_8859_11' : 'iso8859_11', + 'iso_8859_11_2001' : 'iso8859_11', + + # iso8859_13 codec + 'iso_8859_13' : 'iso8859_13', + 'l7' : 'iso8859_13', + 'latin7' : 'iso8859_13', + + # iso8859_14 codec + 'iso_8859_14' : 'iso8859_14', + 'iso_8859_14_1998' : 'iso8859_14', + 'iso_celtic' : 'iso8859_14', + 'iso_ir_199' : 'iso8859_14', + 'l8' : 'iso8859_14', + 'latin8' : 'iso8859_14', + + # iso8859_15 codec + 'iso_8859_15' : 'iso8859_15', + 'l9' : 'iso8859_15', + 'latin9' : 'iso8859_15', + + # iso8859_16 codec + 'iso_8859_16' : 'iso8859_16', + 'iso_8859_16_2001' : 'iso8859_16', + 'iso_ir_226' : 'iso8859_16', + 'l10' : 'iso8859_16', + 'latin10' : 'iso8859_16', + + # iso8859_2 codec + 'csisolatin2' : 'iso8859_2', + 'iso_8859_2' : 'iso8859_2', + 'iso_8859_2_1987' : 'iso8859_2', + 'iso_ir_101' : 'iso8859_2', + 'l2' : 'iso8859_2', + 'latin2' : 'iso8859_2', + + # iso8859_3 codec + 'csisolatin3' : 'iso8859_3', + 'iso_8859_3' : 'iso8859_3', + 'iso_8859_3_1988' : 'iso8859_3', + 'iso_ir_109' : 'iso8859_3', + 'l3' : 'iso8859_3', + 'latin3' : 'iso8859_3', + + # iso8859_4 codec + 'csisolatin4' : 'iso8859_4', + 'iso_8859_4' : 'iso8859_4', + 'iso_8859_4_1988' : 'iso8859_4', + 'iso_ir_110' : 'iso8859_4', + 'l4' : 'iso8859_4', + 'latin4' : 'iso8859_4', + + # iso8859_5 codec + 'csisolatincyrillic' : 'iso8859_5', + 'cyrillic' : 'iso8859_5', + 'iso_8859_5' : 'iso8859_5', + 'iso_8859_5_1988' : 'iso8859_5', + 'iso_ir_144' : 'iso8859_5', + + # iso8859_6 codec + 'arabic' : 'iso8859_6', + 'asmo_708' : 'iso8859_6', + 'csisolatinarabic' : 'iso8859_6', + 'ecma_114' : 'iso8859_6', + 'iso_8859_6' : 'iso8859_6', + 'iso_8859_6_1987' : 'iso8859_6', + 'iso_ir_127' : 'iso8859_6', + + # iso8859_7 codec + 'csisolatingreek' : 'iso8859_7', + 'ecma_118' : 'iso8859_7', + 'elot_928' : 'iso8859_7', + 'greek' : 'iso8859_7', + 'greek8' : 'iso8859_7', + 'iso_8859_7' : 'iso8859_7', + 'iso_8859_7_1987' : 'iso8859_7', + 'iso_ir_126' : 'iso8859_7', + + # iso8859_8 codec + 'csisolatinhebrew' : 'iso8859_8', + 'hebrew' : 'iso8859_8', + 'iso_8859_8' : 'iso8859_8', + 'iso_8859_8_1988' : 'iso8859_8', + 'iso_ir_138' : 'iso8859_8', + + # iso8859_9 codec + 'csisolatin5' : 'iso8859_9', + 'iso_8859_9' : 'iso8859_9', + 'iso_8859_9_1989' : 'iso8859_9', + 'iso_ir_148' : 'iso8859_9', + 'l5' : 'iso8859_9', + 'latin5' : 'iso8859_9', + + # johab codec + 'cp1361' : 'johab', + 'ms1361' : 'johab', + + # koi8_r codec + 'cskoi8r' : 'koi8_r', + + # kz1048 codec + 'kz_1048' : 'kz1048', + 'rk1048' : 'kz1048', + 'strk1048_2002' : 'kz1048', + + # latin_1 codec + # + # Note that the latin_1 codec is implemented internally in C and a + # lot faster than the charmap codec iso8859_1 which uses the same + # encoding. This is why we discourage the use of the iso8859_1 + # codec and alias it to latin_1 instead. + # + '8859' : 'latin_1', + 'cp819' : 'latin_1', + 'csisolatin1' : 'latin_1', + 'ibm819' : 'latin_1', + 'iso8859' : 'latin_1', + 'iso8859_1' : 'latin_1', + 'iso_8859_1' : 'latin_1', + 'iso_8859_1_1987' : 'latin_1', + 'iso_ir_100' : 'latin_1', + 'l1' : 'latin_1', + 'latin' : 'latin_1', + 'latin1' : 'latin_1', + + # mac_cyrillic codec + 'maccyrillic' : 'mac_cyrillic', + + # mac_greek codec + 'macgreek' : 'mac_greek', + + # mac_iceland codec + 'maciceland' : 'mac_iceland', + + # mac_latin2 codec + 'maccentraleurope' : 'mac_latin2', + 'maclatin2' : 'mac_latin2', + + # mac_roman codec + 'macintosh' : 'mac_roman', + 'macroman' : 'mac_roman', + + # mac_turkish codec + 'macturkish' : 'mac_turkish', + + # mbcs codec + 'ansi' : 'mbcs', + 'dbcs' : 'mbcs', + + # ptcp154 codec + 'csptcp154' : 'ptcp154', + 'pt154' : 'ptcp154', + 'cp154' : 'ptcp154', + 'cyrillic_asian' : 'ptcp154', + + # quopri_codec codec + 'quopri' : 'quopri_codec', + 'quoted_printable' : 'quopri_codec', + 'quotedprintable' : 'quopri_codec', + + # rot_13 codec + 'rot13' : 'rot_13', + + # shift_jis codec + 'csshiftjis' : 'shift_jis', + 'shiftjis' : 'shift_jis', + 'sjis' : 'shift_jis', + 's_jis' : 'shift_jis', + + # shift_jis_2004 codec + 'shiftjis2004' : 'shift_jis_2004', + 'sjis_2004' : 'shift_jis_2004', + 's_jis_2004' : 'shift_jis_2004', + + # shift_jisx0213 codec + 'shiftjisx0213' : 'shift_jisx0213', + 'sjisx0213' : 'shift_jisx0213', + 's_jisx0213' : 'shift_jisx0213', + + # tactis codec + 'tis260' : 'tactis', + + # tis_620 codec + 'tis620' : 'tis_620', + 'tis_620_0' : 'tis_620', + 'tis_620_2529_0' : 'tis_620', + 'tis_620_2529_1' : 'tis_620', + 'iso_ir_166' : 'tis_620', + + # utf_16 codec + 'u16' : 'utf_16', + 'utf16' : 'utf_16', + + # utf_16_be codec + 'unicodebigunmarked' : 'utf_16_be', + 'utf_16be' : 'utf_16_be', + + # utf_16_le codec + 'unicodelittleunmarked' : 'utf_16_le', + 'utf_16le' : 'utf_16_le', + + # utf_32 codec + 'u32' : 'utf_32', + 'utf32' : 'utf_32', + + # utf_32_be codec + 'utf_32be' : 'utf_32_be', + + # utf_32_le codec + 'utf_32le' : 'utf_32_le', + + # utf_7 codec + 'u7' : 'utf_7', + 'utf7' : 'utf_7', + 'unicode_1_1_utf_7' : 'utf_7', + + # utf_8 codec + 'u8' : 'utf_8', + 'utf' : 'utf_8', + 'utf8' : 'utf_8', + 'utf8_ucs2' : 'utf_8', + 'utf8_ucs4' : 'utf_8', + + # uu_codec codec + 'uu' : 'uu_codec', + + # zlib_codec codec + 'zip' : 'zlib_codec', + 'zlib' : 'zlib_codec', + + # temporary mac CJK aliases, will be replaced by proper codecs in 3.1 + 'x_mac_japanese' : 'shift_jis', + 'x_mac_korean' : 'euc_kr', + 'x_mac_simp_chinese' : 'gb2312', + 'x_mac_trad_chinese' : 'big5', +} diff --git a/winvenv/Lib/encodings/ascii.py b/winvenv/Lib/encodings/ascii.py new file mode 100644 index 0000000..2033cde --- /dev/null +++ b/winvenv/Lib/encodings/ascii.py @@ -0,0 +1,50 @@ +""" Python 'ascii' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.ascii_encode + decode = codecs.ascii_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.ascii_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.ascii_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +class StreamConverter(StreamWriter,StreamReader): + + encode = codecs.ascii_decode + decode = codecs.ascii_encode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='ascii', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/base64_codec.py b/winvenv/Lib/encodings/base64_codec.py new file mode 100644 index 0000000..8e7703b --- /dev/null +++ b/winvenv/Lib/encodings/base64_codec.py @@ -0,0 +1,55 @@ +"""Python 'base64_codec' Codec - base64 content transfer encoding. + +This codec de/encodes from bytes to bytes. + +Written by Marc-Andre Lemburg (mal@lemburg.com). +""" + +import codecs +import base64 + +### Codec APIs + +def base64_encode(input, errors='strict'): + assert errors == 'strict' + return (base64.encodebytes(input), len(input)) + +def base64_decode(input, errors='strict'): + assert errors == 'strict' + return (base64.decodebytes(input), len(input)) + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return base64_encode(input, errors) + def decode(self, input, errors='strict'): + return base64_decode(input, errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + assert self.errors == 'strict' + return base64.encodebytes(input) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + assert self.errors == 'strict' + return base64.decodebytes(input) + +class StreamWriter(Codec, codecs.StreamWriter): + charbuffertype = bytes + +class StreamReader(Codec, codecs.StreamReader): + charbuffertype = bytes + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='base64', + encode=base64_encode, + decode=base64_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + _is_text_encoding=False, + ) diff --git a/winvenv/Lib/encodings/big5.py b/winvenv/Lib/encodings/big5.py new file mode 100644 index 0000000..7adeb0e --- /dev/null +++ b/winvenv/Lib/encodings/big5.py @@ -0,0 +1,39 @@ +# +# big5.py: Python Unicode Codec for BIG5 +# +# Written by Hye-Shik Chang +# + +import _codecs_tw, codecs +import _multibytecodec as mbc + +codec = _codecs_tw.getcodec('big5') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='big5', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/big5hkscs.py b/winvenv/Lib/encodings/big5hkscs.py new file mode 100644 index 0000000..350df37 --- /dev/null +++ b/winvenv/Lib/encodings/big5hkscs.py @@ -0,0 +1,39 @@ +# +# big5hkscs.py: Python Unicode Codec for BIG5HKSCS +# +# Written by Hye-Shik Chang +# + +import _codecs_hk, codecs +import _multibytecodec as mbc + +codec = _codecs_hk.getcodec('big5hkscs') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='big5hkscs', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/bz2_codec.py b/winvenv/Lib/encodings/bz2_codec.py new file mode 100644 index 0000000..fd9495e --- /dev/null +++ b/winvenv/Lib/encodings/bz2_codec.py @@ -0,0 +1,78 @@ +"""Python 'bz2_codec' Codec - bz2 compression encoding. + +This codec de/encodes from bytes to bytes and is therefore usable with +bytes.transform() and bytes.untransform(). + +Adapted by Raymond Hettinger from zlib_codec.py which was written +by Marc-Andre Lemburg (mal@lemburg.com). +""" + +import codecs +import bz2 # this codec needs the optional bz2 module ! + +### Codec APIs + +def bz2_encode(input, errors='strict'): + assert errors == 'strict' + return (bz2.compress(input), len(input)) + +def bz2_decode(input, errors='strict'): + assert errors == 'strict' + return (bz2.decompress(input), len(input)) + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return bz2_encode(input, errors) + def decode(self, input, errors='strict'): + return bz2_decode(input, errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict'): + assert errors == 'strict' + self.errors = errors + self.compressobj = bz2.BZ2Compressor() + + def encode(self, input, final=False): + if final: + c = self.compressobj.compress(input) + return c + self.compressobj.flush() + else: + return self.compressobj.compress(input) + + def reset(self): + self.compressobj = bz2.BZ2Compressor() + +class IncrementalDecoder(codecs.IncrementalDecoder): + def __init__(self, errors='strict'): + assert errors == 'strict' + self.errors = errors + self.decompressobj = bz2.BZ2Decompressor() + + def decode(self, input, final=False): + try: + return self.decompressobj.decompress(input) + except EOFError: + return '' + + def reset(self): + self.decompressobj = bz2.BZ2Decompressor() + +class StreamWriter(Codec, codecs.StreamWriter): + charbuffertype = bytes + +class StreamReader(Codec, codecs.StreamReader): + charbuffertype = bytes + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name="bz2", + encode=bz2_encode, + decode=bz2_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + _is_text_encoding=False, + ) diff --git a/winvenv/Lib/encodings/charmap.py b/winvenv/Lib/encodings/charmap.py new file mode 100644 index 0000000..81189b1 --- /dev/null +++ b/winvenv/Lib/encodings/charmap.py @@ -0,0 +1,69 @@ +""" Generic Python Character Mapping Codec. + + Use this codec directly rather than through the automatic + conversion mechanisms supplied by unicode() and .encode(). + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.charmap_encode + decode = codecs.charmap_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict', mapping=None): + codecs.IncrementalEncoder.__init__(self, errors) + self.mapping = mapping + + def encode(self, input, final=False): + return codecs.charmap_encode(input, self.errors, self.mapping)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def __init__(self, errors='strict', mapping=None): + codecs.IncrementalDecoder.__init__(self, errors) + self.mapping = mapping + + def decode(self, input, final=False): + return codecs.charmap_decode(input, self.errors, self.mapping)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + + def __init__(self,stream,errors='strict',mapping=None): + codecs.StreamWriter.__init__(self,stream,errors) + self.mapping = mapping + + def encode(self,input,errors='strict'): + return Codec.encode(input,errors,self.mapping) + +class StreamReader(Codec,codecs.StreamReader): + + def __init__(self,stream,errors='strict',mapping=None): + codecs.StreamReader.__init__(self,stream,errors) + self.mapping = mapping + + def decode(self,input,errors='strict'): + return Codec.decode(input,errors,self.mapping) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='charmap', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/cp037.py b/winvenv/Lib/encodings/cp037.py new file mode 100644 index 0000000..4edd708 --- /dev/null +++ b/winvenv/Lib/encodings/cp037.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp037 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP037.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp037', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x9c' # 0x04 -> CONTROL + '\t' # 0x05 -> HORIZONTAL TABULATION + '\x86' # 0x06 -> CONTROL + '\x7f' # 0x07 -> DELETE + '\x97' # 0x08 -> CONTROL + '\x8d' # 0x09 -> CONTROL + '\x8e' # 0x0A -> CONTROL + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x9d' # 0x14 -> CONTROL + '\x85' # 0x15 -> CONTROL + '\x08' # 0x16 -> BACKSPACE + '\x87' # 0x17 -> CONTROL + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x92' # 0x1A -> CONTROL + '\x8f' # 0x1B -> CONTROL + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + '\x80' # 0x20 -> CONTROL + '\x81' # 0x21 -> CONTROL + '\x82' # 0x22 -> CONTROL + '\x83' # 0x23 -> CONTROL + '\x84' # 0x24 -> CONTROL + '\n' # 0x25 -> LINE FEED + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK + '\x1b' # 0x27 -> ESCAPE + '\x88' # 0x28 -> CONTROL + '\x89' # 0x29 -> CONTROL + '\x8a' # 0x2A -> CONTROL + '\x8b' # 0x2B -> CONTROL + '\x8c' # 0x2C -> CONTROL + '\x05' # 0x2D -> ENQUIRY + '\x06' # 0x2E -> ACKNOWLEDGE + '\x07' # 0x2F -> BELL + '\x90' # 0x30 -> CONTROL + '\x91' # 0x31 -> CONTROL + '\x16' # 0x32 -> SYNCHRONOUS IDLE + '\x93' # 0x33 -> CONTROL + '\x94' # 0x34 -> CONTROL + '\x95' # 0x35 -> CONTROL + '\x96' # 0x36 -> CONTROL + '\x04' # 0x37 -> END OF TRANSMISSION + '\x98' # 0x38 -> CONTROL + '\x99' # 0x39 -> CONTROL + '\x9a' # 0x3A -> CONTROL + '\x9b' # 0x3B -> CONTROL + '\x14' # 0x3C -> DEVICE CONTROL FOUR + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + '\x9e' # 0x3E -> CONTROL + '\x1a' # 0x3F -> SUBSTITUTE + ' ' # 0x40 -> SPACE + '\xa0' # 0x41 -> NO-BREAK SPACE + '\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + '\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + '\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + '\xa2' # 0x4A -> CENT SIGN + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '|' # 0x4F -> VERTICAL LINE + '&' # 0x50 -> AMPERSAND + '\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + '\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + '\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + '!' # 0x5A -> EXCLAMATION MARK + '$' # 0x5B -> DOLLAR SIGN + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '\xac' # 0x5F -> NOT SIGN + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + '\xa6' # 0x6A -> BROKEN BAR + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + '\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + '`' # 0x79 -> GRAVE ACCENT + ':' # 0x7A -> COLON + '#' # 0x7B -> NUMBER SIGN + '@' # 0x7C -> COMMERCIAL AT + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '"' # 0x7F -> QUOTATION MARK + '\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xf0' # 0x8C -> LATIN SMALL LETTER ETH (ICELANDIC) + '\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0x8E -> LATIN SMALL LETTER THORN (ICELANDIC) + '\xb1' # 0x8F -> PLUS-MINUS SIGN + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + '\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + '\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + '\xb8' # 0x9D -> CEDILLA + '\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + '\xa4' # 0x9F -> CURRENCY SIGN + '\xb5' # 0xA0 -> MICRO SIGN + '~' # 0xA1 -> TILDE + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + '\xbf' # 0xAB -> INVERTED QUESTION MARK + '\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC) + '\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC) + '\xae' # 0xAF -> REGISTERED SIGN + '^' # 0xB0 -> CIRCUMFLEX ACCENT + '\xa3' # 0xB1 -> POUND SIGN + '\xa5' # 0xB2 -> YEN SIGN + '\xb7' # 0xB3 -> MIDDLE DOT + '\xa9' # 0xB4 -> COPYRIGHT SIGN + '\xa7' # 0xB5 -> SECTION SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + '\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + '[' # 0xBA -> LEFT SQUARE BRACKET + ']' # 0xBB -> RIGHT SQUARE BRACKET + '\xaf' # 0xBC -> MACRON + '\xa8' # 0xBD -> DIAERESIS + '\xb4' # 0xBE -> ACUTE ACCENT + '\xd7' # 0xBF -> MULTIPLICATION SIGN + '{' # 0xC0 -> LEFT CURLY BRACKET + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0xCC -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + '\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + '}' # 0xD0 -> RIGHT CURLY BRACKET + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb9' # 0xDA -> SUPERSCRIPT ONE + '\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xDC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + '\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + '\\' # 0xE0 -> REVERSE SOLIDUS + '\xf7' # 0xE1 -> DIVISION SIGN + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd6' # 0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + '\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1006.py b/winvenv/Lib/encodings/cp1006.py new file mode 100644 index 0000000..a1221c3 --- /dev/null +++ b/winvenv/Lib/encodings/cp1006.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1006 generated from 'MAPPINGS/VENDORS/MISC/CP1006.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1006', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u06f0' # 0xA1 -> EXTENDED ARABIC-INDIC DIGIT ZERO + '\u06f1' # 0xA2 -> EXTENDED ARABIC-INDIC DIGIT ONE + '\u06f2' # 0xA3 -> EXTENDED ARABIC-INDIC DIGIT TWO + '\u06f3' # 0xA4 -> EXTENDED ARABIC-INDIC DIGIT THREE + '\u06f4' # 0xA5 -> EXTENDED ARABIC-INDIC DIGIT FOUR + '\u06f5' # 0xA6 -> EXTENDED ARABIC-INDIC DIGIT FIVE + '\u06f6' # 0xA7 -> EXTENDED ARABIC-INDIC DIGIT SIX + '\u06f7' # 0xA8 -> EXTENDED ARABIC-INDIC DIGIT SEVEN + '\u06f8' # 0xA9 -> EXTENDED ARABIC-INDIC DIGIT EIGHT + '\u06f9' # 0xAA -> EXTENDED ARABIC-INDIC DIGIT NINE + '\u060c' # 0xAB -> ARABIC COMMA + '\u061b' # 0xAC -> ARABIC SEMICOLON + '\xad' # 0xAD -> SOFT HYPHEN + '\u061f' # 0xAE -> ARABIC QUESTION MARK + '\ufe81' # 0xAF -> ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + '\ufe8d' # 0xB0 -> ARABIC LETTER ALEF ISOLATED FORM + '\ufe8e' # 0xB1 -> ARABIC LETTER ALEF FINAL FORM + '\ufe8e' # 0xB2 -> ARABIC LETTER ALEF FINAL FORM + '\ufe8f' # 0xB3 -> ARABIC LETTER BEH ISOLATED FORM + '\ufe91' # 0xB4 -> ARABIC LETTER BEH INITIAL FORM + '\ufb56' # 0xB5 -> ARABIC LETTER PEH ISOLATED FORM + '\ufb58' # 0xB6 -> ARABIC LETTER PEH INITIAL FORM + '\ufe93' # 0xB7 -> ARABIC LETTER TEH MARBUTA ISOLATED FORM + '\ufe95' # 0xB8 -> ARABIC LETTER TEH ISOLATED FORM + '\ufe97' # 0xB9 -> ARABIC LETTER TEH INITIAL FORM + '\ufb66' # 0xBA -> ARABIC LETTER TTEH ISOLATED FORM + '\ufb68' # 0xBB -> ARABIC LETTER TTEH INITIAL FORM + '\ufe99' # 0xBC -> ARABIC LETTER THEH ISOLATED FORM + '\ufe9b' # 0xBD -> ARABIC LETTER THEH INITIAL FORM + '\ufe9d' # 0xBE -> ARABIC LETTER JEEM ISOLATED FORM + '\ufe9f' # 0xBF -> ARABIC LETTER JEEM INITIAL FORM + '\ufb7a' # 0xC0 -> ARABIC LETTER TCHEH ISOLATED FORM + '\ufb7c' # 0xC1 -> ARABIC LETTER TCHEH INITIAL FORM + '\ufea1' # 0xC2 -> ARABIC LETTER HAH ISOLATED FORM + '\ufea3' # 0xC3 -> ARABIC LETTER HAH INITIAL FORM + '\ufea5' # 0xC4 -> ARABIC LETTER KHAH ISOLATED FORM + '\ufea7' # 0xC5 -> ARABIC LETTER KHAH INITIAL FORM + '\ufea9' # 0xC6 -> ARABIC LETTER DAL ISOLATED FORM + '\ufb84' # 0xC7 -> ARABIC LETTER DAHAL ISOLATED FORMN + '\ufeab' # 0xC8 -> ARABIC LETTER THAL ISOLATED FORM + '\ufead' # 0xC9 -> ARABIC LETTER REH ISOLATED FORM + '\ufb8c' # 0xCA -> ARABIC LETTER RREH ISOLATED FORM + '\ufeaf' # 0xCB -> ARABIC LETTER ZAIN ISOLATED FORM + '\ufb8a' # 0xCC -> ARABIC LETTER JEH ISOLATED FORM + '\ufeb1' # 0xCD -> ARABIC LETTER SEEN ISOLATED FORM + '\ufeb3' # 0xCE -> ARABIC LETTER SEEN INITIAL FORM + '\ufeb5' # 0xCF -> ARABIC LETTER SHEEN ISOLATED FORM + '\ufeb7' # 0xD0 -> ARABIC LETTER SHEEN INITIAL FORM + '\ufeb9' # 0xD1 -> ARABIC LETTER SAD ISOLATED FORM + '\ufebb' # 0xD2 -> ARABIC LETTER SAD INITIAL FORM + '\ufebd' # 0xD3 -> ARABIC LETTER DAD ISOLATED FORM + '\ufebf' # 0xD4 -> ARABIC LETTER DAD INITIAL FORM + '\ufec1' # 0xD5 -> ARABIC LETTER TAH ISOLATED FORM + '\ufec5' # 0xD6 -> ARABIC LETTER ZAH ISOLATED FORM + '\ufec9' # 0xD7 -> ARABIC LETTER AIN ISOLATED FORM + '\ufeca' # 0xD8 -> ARABIC LETTER AIN FINAL FORM + '\ufecb' # 0xD9 -> ARABIC LETTER AIN INITIAL FORM + '\ufecc' # 0xDA -> ARABIC LETTER AIN MEDIAL FORM + '\ufecd' # 0xDB -> ARABIC LETTER GHAIN ISOLATED FORM + '\ufece' # 0xDC -> ARABIC LETTER GHAIN FINAL FORM + '\ufecf' # 0xDD -> ARABIC LETTER GHAIN INITIAL FORM + '\ufed0' # 0xDE -> ARABIC LETTER GHAIN MEDIAL FORM + '\ufed1' # 0xDF -> ARABIC LETTER FEH ISOLATED FORM + '\ufed3' # 0xE0 -> ARABIC LETTER FEH INITIAL FORM + '\ufed5' # 0xE1 -> ARABIC LETTER QAF ISOLATED FORM + '\ufed7' # 0xE2 -> ARABIC LETTER QAF INITIAL FORM + '\ufed9' # 0xE3 -> ARABIC LETTER KAF ISOLATED FORM + '\ufedb' # 0xE4 -> ARABIC LETTER KAF INITIAL FORM + '\ufb92' # 0xE5 -> ARABIC LETTER GAF ISOLATED FORM + '\ufb94' # 0xE6 -> ARABIC LETTER GAF INITIAL FORM + '\ufedd' # 0xE7 -> ARABIC LETTER LAM ISOLATED FORM + '\ufedf' # 0xE8 -> ARABIC LETTER LAM INITIAL FORM + '\ufee0' # 0xE9 -> ARABIC LETTER LAM MEDIAL FORM + '\ufee1' # 0xEA -> ARABIC LETTER MEEM ISOLATED FORM + '\ufee3' # 0xEB -> ARABIC LETTER MEEM INITIAL FORM + '\ufb9e' # 0xEC -> ARABIC LETTER NOON GHUNNA ISOLATED FORM + '\ufee5' # 0xED -> ARABIC LETTER NOON ISOLATED FORM + '\ufee7' # 0xEE -> ARABIC LETTER NOON INITIAL FORM + '\ufe85' # 0xEF -> ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + '\ufeed' # 0xF0 -> ARABIC LETTER WAW ISOLATED FORM + '\ufba6' # 0xF1 -> ARABIC LETTER HEH GOAL ISOLATED FORM + '\ufba8' # 0xF2 -> ARABIC LETTER HEH GOAL INITIAL FORM + '\ufba9' # 0xF3 -> ARABIC LETTER HEH GOAL MEDIAL FORM + '\ufbaa' # 0xF4 -> ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM + '\ufe80' # 0xF5 -> ARABIC LETTER HAMZA ISOLATED FORM + '\ufe89' # 0xF6 -> ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM + '\ufe8a' # 0xF7 -> ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM + '\ufe8b' # 0xF8 -> ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + '\ufef1' # 0xF9 -> ARABIC LETTER YEH ISOLATED FORM + '\ufef2' # 0xFA -> ARABIC LETTER YEH FINAL FORM + '\ufef3' # 0xFB -> ARABIC LETTER YEH INITIAL FORM + '\ufbb0' # 0xFC -> ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM + '\ufbae' # 0xFD -> ARABIC LETTER YEH BARREE ISOLATED FORM + '\ufe7c' # 0xFE -> ARABIC SHADDA ISOLATED FORM + '\ufe7d' # 0xFF -> ARABIC SHADDA MEDIAL FORM +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1026.py b/winvenv/Lib/encodings/cp1026.py new file mode 100644 index 0000000..46f71f7 --- /dev/null +++ b/winvenv/Lib/encodings/cp1026.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1026 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP1026.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1026', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x9c' # 0x04 -> CONTROL + '\t' # 0x05 -> HORIZONTAL TABULATION + '\x86' # 0x06 -> CONTROL + '\x7f' # 0x07 -> DELETE + '\x97' # 0x08 -> CONTROL + '\x8d' # 0x09 -> CONTROL + '\x8e' # 0x0A -> CONTROL + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x9d' # 0x14 -> CONTROL + '\x85' # 0x15 -> CONTROL + '\x08' # 0x16 -> BACKSPACE + '\x87' # 0x17 -> CONTROL + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x92' # 0x1A -> CONTROL + '\x8f' # 0x1B -> CONTROL + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + '\x80' # 0x20 -> CONTROL + '\x81' # 0x21 -> CONTROL + '\x82' # 0x22 -> CONTROL + '\x83' # 0x23 -> CONTROL + '\x84' # 0x24 -> CONTROL + '\n' # 0x25 -> LINE FEED + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK + '\x1b' # 0x27 -> ESCAPE + '\x88' # 0x28 -> CONTROL + '\x89' # 0x29 -> CONTROL + '\x8a' # 0x2A -> CONTROL + '\x8b' # 0x2B -> CONTROL + '\x8c' # 0x2C -> CONTROL + '\x05' # 0x2D -> ENQUIRY + '\x06' # 0x2E -> ACKNOWLEDGE + '\x07' # 0x2F -> BELL + '\x90' # 0x30 -> CONTROL + '\x91' # 0x31 -> CONTROL + '\x16' # 0x32 -> SYNCHRONOUS IDLE + '\x93' # 0x33 -> CONTROL + '\x94' # 0x34 -> CONTROL + '\x95' # 0x35 -> CONTROL + '\x96' # 0x36 -> CONTROL + '\x04' # 0x37 -> END OF TRANSMISSION + '\x98' # 0x38 -> CONTROL + '\x99' # 0x39 -> CONTROL + '\x9a' # 0x3A -> CONTROL + '\x9b' # 0x3B -> CONTROL + '\x14' # 0x3C -> DEVICE CONTROL FOUR + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + '\x9e' # 0x3E -> CONTROL + '\x1a' # 0x3F -> SUBSTITUTE + ' ' # 0x40 -> SPACE + '\xa0' # 0x41 -> NO-BREAK SPACE + '\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + '\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + '{' # 0x48 -> LEFT CURLY BRACKET + '\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + '\xc7' # 0x4A -> LATIN CAPITAL LETTER C WITH CEDILLA + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '!' # 0x4F -> EXCLAMATION MARK + '&' # 0x50 -> AMPERSAND + '\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + '\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + '\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + '\u011e' # 0x5A -> LATIN CAPITAL LETTER G WITH BREVE + '\u0130' # 0x5B -> LATIN CAPITAL LETTER I WITH DOT ABOVE + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '^' # 0x5F -> CIRCUMFLEX ACCENT + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '[' # 0x68 -> LEFT SQUARE BRACKET + '\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + '\u015f' # 0x6A -> LATIN SMALL LETTER S WITH CEDILLA + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + '\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + '\u0131' # 0x79 -> LATIN SMALL LETTER DOTLESS I + ':' # 0x7A -> COLON + '\xd6' # 0x7B -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\u015e' # 0x7C -> LATIN CAPITAL LETTER S WITH CEDILLA + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '\xdc' # 0x7F -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '}' # 0x8C -> RIGHT CURLY BRACKET + '`' # 0x8D -> GRAVE ACCENT + '\xa6' # 0x8E -> BROKEN BAR + '\xb1' # 0x8F -> PLUS-MINUS SIGN + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + '\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + '\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + '\xb8' # 0x9D -> CEDILLA + '\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + '\xa4' # 0x9F -> CURRENCY SIGN + '\xb5' # 0xA0 -> MICRO SIGN + '\xf6' # 0xA1 -> LATIN SMALL LETTER O WITH DIAERESIS + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + '\xbf' # 0xAB -> INVERTED QUESTION MARK + ']' # 0xAC -> RIGHT SQUARE BRACKET + '$' # 0xAD -> DOLLAR SIGN + '@' # 0xAE -> COMMERCIAL AT + '\xae' # 0xAF -> REGISTERED SIGN + '\xa2' # 0xB0 -> CENT SIGN + '\xa3' # 0xB1 -> POUND SIGN + '\xa5' # 0xB2 -> YEN SIGN + '\xb7' # 0xB3 -> MIDDLE DOT + '\xa9' # 0xB4 -> COPYRIGHT SIGN + '\xa7' # 0xB5 -> SECTION SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + '\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + '\xac' # 0xBA -> NOT SIGN + '|' # 0xBB -> VERTICAL LINE + '\xaf' # 0xBC -> MACRON + '\xa8' # 0xBD -> DIAERESIS + '\xb4' # 0xBE -> ACUTE ACCENT + '\xd7' # 0xBF -> MULTIPLICATION SIGN + '\xe7' # 0xC0 -> LATIN SMALL LETTER C WITH CEDILLA + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '~' # 0xCC -> TILDE + '\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + '\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + '\u011f' # 0xD0 -> LATIN SMALL LETTER G WITH BREVE + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb9' # 0xDA -> SUPERSCRIPT ONE + '\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\\' # 0xDC -> REVERSE SOLIDUS + '\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + '\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xfc' # 0xE0 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xf7' # 0xE1 -> DIVISION SIGN + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '#' # 0xEC -> NUMBER SIGN + '\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '"' # 0xFC -> QUOTATION MARK + '\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + '\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1125.py b/winvenv/Lib/encodings/cp1125.py new file mode 100644 index 0000000..b1fd69d --- /dev/null +++ b/winvenv/Lib/encodings/cp1125.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec for CP1125 + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1125', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x0410, # CYRILLIC CAPITAL LETTER A + 0x0081: 0x0411, # CYRILLIC CAPITAL LETTER BE + 0x0082: 0x0412, # CYRILLIC CAPITAL LETTER VE + 0x0083: 0x0413, # CYRILLIC CAPITAL LETTER GHE + 0x0084: 0x0414, # CYRILLIC CAPITAL LETTER DE + 0x0085: 0x0415, # CYRILLIC CAPITAL LETTER IE + 0x0086: 0x0416, # CYRILLIC CAPITAL LETTER ZHE + 0x0087: 0x0417, # CYRILLIC CAPITAL LETTER ZE + 0x0088: 0x0418, # CYRILLIC CAPITAL LETTER I + 0x0089: 0x0419, # CYRILLIC CAPITAL LETTER SHORT I + 0x008a: 0x041a, # CYRILLIC CAPITAL LETTER KA + 0x008b: 0x041b, # CYRILLIC CAPITAL LETTER EL + 0x008c: 0x041c, # CYRILLIC CAPITAL LETTER EM + 0x008d: 0x041d, # CYRILLIC CAPITAL LETTER EN + 0x008e: 0x041e, # CYRILLIC CAPITAL LETTER O + 0x008f: 0x041f, # CYRILLIC CAPITAL LETTER PE + 0x0090: 0x0420, # CYRILLIC CAPITAL LETTER ER + 0x0091: 0x0421, # CYRILLIC CAPITAL LETTER ES + 0x0092: 0x0422, # CYRILLIC CAPITAL LETTER TE + 0x0093: 0x0423, # CYRILLIC CAPITAL LETTER U + 0x0094: 0x0424, # CYRILLIC CAPITAL LETTER EF + 0x0095: 0x0425, # CYRILLIC CAPITAL LETTER HA + 0x0096: 0x0426, # CYRILLIC CAPITAL LETTER TSE + 0x0097: 0x0427, # CYRILLIC CAPITAL LETTER CHE + 0x0098: 0x0428, # CYRILLIC CAPITAL LETTER SHA + 0x0099: 0x0429, # CYRILLIC CAPITAL LETTER SHCHA + 0x009a: 0x042a, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x009b: 0x042b, # CYRILLIC CAPITAL LETTER YERU + 0x009c: 0x042c, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x009d: 0x042d, # CYRILLIC CAPITAL LETTER E + 0x009e: 0x042e, # CYRILLIC CAPITAL LETTER YU + 0x009f: 0x042f, # CYRILLIC CAPITAL LETTER YA + 0x00a0: 0x0430, # CYRILLIC SMALL LETTER A + 0x00a1: 0x0431, # CYRILLIC SMALL LETTER BE + 0x00a2: 0x0432, # CYRILLIC SMALL LETTER VE + 0x00a3: 0x0433, # CYRILLIC SMALL LETTER GHE + 0x00a4: 0x0434, # CYRILLIC SMALL LETTER DE + 0x00a5: 0x0435, # CYRILLIC SMALL LETTER IE + 0x00a6: 0x0436, # CYRILLIC SMALL LETTER ZHE + 0x00a7: 0x0437, # CYRILLIC SMALL LETTER ZE + 0x00a8: 0x0438, # CYRILLIC SMALL LETTER I + 0x00a9: 0x0439, # CYRILLIC SMALL LETTER SHORT I + 0x00aa: 0x043a, # CYRILLIC SMALL LETTER KA + 0x00ab: 0x043b, # CYRILLIC SMALL LETTER EL + 0x00ac: 0x043c, # CYRILLIC SMALL LETTER EM + 0x00ad: 0x043d, # CYRILLIC SMALL LETTER EN + 0x00ae: 0x043e, # CYRILLIC SMALL LETTER O + 0x00af: 0x043f, # CYRILLIC SMALL LETTER PE + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x0440, # CYRILLIC SMALL LETTER ER + 0x00e1: 0x0441, # CYRILLIC SMALL LETTER ES + 0x00e2: 0x0442, # CYRILLIC SMALL LETTER TE + 0x00e3: 0x0443, # CYRILLIC SMALL LETTER U + 0x00e4: 0x0444, # CYRILLIC SMALL LETTER EF + 0x00e5: 0x0445, # CYRILLIC SMALL LETTER HA + 0x00e6: 0x0446, # CYRILLIC SMALL LETTER TSE + 0x00e7: 0x0447, # CYRILLIC SMALL LETTER CHE + 0x00e8: 0x0448, # CYRILLIC SMALL LETTER SHA + 0x00e9: 0x0449, # CYRILLIC SMALL LETTER SHCHA + 0x00ea: 0x044a, # CYRILLIC SMALL LETTER HARD SIGN + 0x00eb: 0x044b, # CYRILLIC SMALL LETTER YERU + 0x00ec: 0x044c, # CYRILLIC SMALL LETTER SOFT SIGN + 0x00ed: 0x044d, # CYRILLIC SMALL LETTER E + 0x00ee: 0x044e, # CYRILLIC SMALL LETTER YU + 0x00ef: 0x044f, # CYRILLIC SMALL LETTER YA + 0x00f0: 0x0401, # CYRILLIC CAPITAL LETTER IO + 0x00f1: 0x0451, # CYRILLIC SMALL LETTER IO + 0x00f2: 0x0490, # CYRILLIC CAPITAL LETTER GHE WITH UPTURN + 0x00f3: 0x0491, # CYRILLIC SMALL LETTER GHE WITH UPTURN + 0x00f4: 0x0404, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x00f5: 0x0454, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x00f6: 0x0406, # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + 0x00f7: 0x0456, # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + 0x00f8: 0x0407, # CYRILLIC CAPITAL LETTER YI + 0x00f9: 0x0457, # CYRILLIC SMALL LETTER YI + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x2116, # NUMERO SIGN + 0x00fd: 0x00a4, # CURRENCY SIGN + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\u0410' # 0x0080 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0x0081 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0x0082 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0x0083 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0x0084 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0x0085 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0x0086 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0x0087 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0x0088 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0x0089 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0x008a -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0x008b -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0x008c -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0x008d -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0x008e -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0x008f -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0x0090 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0x0091 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0x0092 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0x0093 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0x0094 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0x0095 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0x0096 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0x0097 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0x0098 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0x0099 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0x009a -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0x009b -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0x009c -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0x009d -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0x009e -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0x009f -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0x00a0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0x00a1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0x00a2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0x00a3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0x00a4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0x00a5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0x00a6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0x00a7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0x00a8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0x00a9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0x00aa -> CYRILLIC SMALL LETTER KA + '\u043b' # 0x00ab -> CYRILLIC SMALL LETTER EL + '\u043c' # 0x00ac -> CYRILLIC SMALL LETTER EM + '\u043d' # 0x00ad -> CYRILLIC SMALL LETTER EN + '\u043e' # 0x00ae -> CYRILLIC SMALL LETTER O + '\u043f' # 0x00af -> CYRILLIC SMALL LETTER PE + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u0440' # 0x00e0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0x00e1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0x00e2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0x00e3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0x00e4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0x00e5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0x00e6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0x00e7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0x00e8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0x00e9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0x00ea -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0x00eb -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0x00ec -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0x00ed -> CYRILLIC SMALL LETTER E + '\u044e' # 0x00ee -> CYRILLIC SMALL LETTER YU + '\u044f' # 0x00ef -> CYRILLIC SMALL LETTER YA + '\u0401' # 0x00f0 -> CYRILLIC CAPITAL LETTER IO + '\u0451' # 0x00f1 -> CYRILLIC SMALL LETTER IO + '\u0490' # 0x00f2 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN + '\u0491' # 0x00f3 -> CYRILLIC SMALL LETTER GHE WITH UPTURN + '\u0404' # 0x00f4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\u0454' # 0x00f5 -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\u0406' # 0x00f6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0456' # 0x00f7 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0407' # 0x00f8 -> CYRILLIC CAPITAL LETTER YI + '\u0457' # 0x00f9 -> CYRILLIC SMALL LETTER YI + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u2116' # 0x00fc -> NUMERO SIGN + '\xa4' # 0x00fd -> CURRENCY SIGN + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00fd, # CURRENCY SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x0401: 0x00f0, # CYRILLIC CAPITAL LETTER IO + 0x0404: 0x00f4, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x0406: 0x00f6, # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + 0x0407: 0x00f8, # CYRILLIC CAPITAL LETTER YI + 0x0410: 0x0080, # CYRILLIC CAPITAL LETTER A + 0x0411: 0x0081, # CYRILLIC CAPITAL LETTER BE + 0x0412: 0x0082, # CYRILLIC CAPITAL LETTER VE + 0x0413: 0x0083, # CYRILLIC CAPITAL LETTER GHE + 0x0414: 0x0084, # CYRILLIC CAPITAL LETTER DE + 0x0415: 0x0085, # CYRILLIC CAPITAL LETTER IE + 0x0416: 0x0086, # CYRILLIC CAPITAL LETTER ZHE + 0x0417: 0x0087, # CYRILLIC CAPITAL LETTER ZE + 0x0418: 0x0088, # CYRILLIC CAPITAL LETTER I + 0x0419: 0x0089, # CYRILLIC CAPITAL LETTER SHORT I + 0x041a: 0x008a, # CYRILLIC CAPITAL LETTER KA + 0x041b: 0x008b, # CYRILLIC CAPITAL LETTER EL + 0x041c: 0x008c, # CYRILLIC CAPITAL LETTER EM + 0x041d: 0x008d, # CYRILLIC CAPITAL LETTER EN + 0x041e: 0x008e, # CYRILLIC CAPITAL LETTER O + 0x041f: 0x008f, # CYRILLIC CAPITAL LETTER PE + 0x0420: 0x0090, # CYRILLIC CAPITAL LETTER ER + 0x0421: 0x0091, # CYRILLIC CAPITAL LETTER ES + 0x0422: 0x0092, # CYRILLIC CAPITAL LETTER TE + 0x0423: 0x0093, # CYRILLIC CAPITAL LETTER U + 0x0424: 0x0094, # CYRILLIC CAPITAL LETTER EF + 0x0425: 0x0095, # CYRILLIC CAPITAL LETTER HA + 0x0426: 0x0096, # CYRILLIC CAPITAL LETTER TSE + 0x0427: 0x0097, # CYRILLIC CAPITAL LETTER CHE + 0x0428: 0x0098, # CYRILLIC CAPITAL LETTER SHA + 0x0429: 0x0099, # CYRILLIC CAPITAL LETTER SHCHA + 0x042a: 0x009a, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x042b: 0x009b, # CYRILLIC CAPITAL LETTER YERU + 0x042c: 0x009c, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x042d: 0x009d, # CYRILLIC CAPITAL LETTER E + 0x042e: 0x009e, # CYRILLIC CAPITAL LETTER YU + 0x042f: 0x009f, # CYRILLIC CAPITAL LETTER YA + 0x0430: 0x00a0, # CYRILLIC SMALL LETTER A + 0x0431: 0x00a1, # CYRILLIC SMALL LETTER BE + 0x0432: 0x00a2, # CYRILLIC SMALL LETTER VE + 0x0433: 0x00a3, # CYRILLIC SMALL LETTER GHE + 0x0434: 0x00a4, # CYRILLIC SMALL LETTER DE + 0x0435: 0x00a5, # CYRILLIC SMALL LETTER IE + 0x0436: 0x00a6, # CYRILLIC SMALL LETTER ZHE + 0x0437: 0x00a7, # CYRILLIC SMALL LETTER ZE + 0x0438: 0x00a8, # CYRILLIC SMALL LETTER I + 0x0439: 0x00a9, # CYRILLIC SMALL LETTER SHORT I + 0x043a: 0x00aa, # CYRILLIC SMALL LETTER KA + 0x043b: 0x00ab, # CYRILLIC SMALL LETTER EL + 0x043c: 0x00ac, # CYRILLIC SMALL LETTER EM + 0x043d: 0x00ad, # CYRILLIC SMALL LETTER EN + 0x043e: 0x00ae, # CYRILLIC SMALL LETTER O + 0x043f: 0x00af, # CYRILLIC SMALL LETTER PE + 0x0440: 0x00e0, # CYRILLIC SMALL LETTER ER + 0x0441: 0x00e1, # CYRILLIC SMALL LETTER ES + 0x0442: 0x00e2, # CYRILLIC SMALL LETTER TE + 0x0443: 0x00e3, # CYRILLIC SMALL LETTER U + 0x0444: 0x00e4, # CYRILLIC SMALL LETTER EF + 0x0445: 0x00e5, # CYRILLIC SMALL LETTER HA + 0x0446: 0x00e6, # CYRILLIC SMALL LETTER TSE + 0x0447: 0x00e7, # CYRILLIC SMALL LETTER CHE + 0x0448: 0x00e8, # CYRILLIC SMALL LETTER SHA + 0x0449: 0x00e9, # CYRILLIC SMALL LETTER SHCHA + 0x044a: 0x00ea, # CYRILLIC SMALL LETTER HARD SIGN + 0x044b: 0x00eb, # CYRILLIC SMALL LETTER YERU + 0x044c: 0x00ec, # CYRILLIC SMALL LETTER SOFT SIGN + 0x044d: 0x00ed, # CYRILLIC SMALL LETTER E + 0x044e: 0x00ee, # CYRILLIC SMALL LETTER YU + 0x044f: 0x00ef, # CYRILLIC SMALL LETTER YA + 0x0451: 0x00f1, # CYRILLIC SMALL LETTER IO + 0x0454: 0x00f5, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x0456: 0x00f7, # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + 0x0457: 0x00f9, # CYRILLIC SMALL LETTER YI + 0x0490: 0x00f2, # CYRILLIC CAPITAL LETTER GHE WITH UPTURN + 0x0491: 0x00f3, # CYRILLIC SMALL LETTER GHE WITH UPTURN + 0x2116: 0x00fc, # NUMERO SIGN + 0x221a: 0x00fb, # SQUARE ROOT + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp1140.py b/winvenv/Lib/encodings/cp1140.py new file mode 100644 index 0000000..0a919d8 --- /dev/null +++ b/winvenv/Lib/encodings/cp1140.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1140 generated from 'python-mappings/CP1140.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1140', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x9c' # 0x04 -> CONTROL + '\t' # 0x05 -> HORIZONTAL TABULATION + '\x86' # 0x06 -> CONTROL + '\x7f' # 0x07 -> DELETE + '\x97' # 0x08 -> CONTROL + '\x8d' # 0x09 -> CONTROL + '\x8e' # 0x0A -> CONTROL + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x9d' # 0x14 -> CONTROL + '\x85' # 0x15 -> CONTROL + '\x08' # 0x16 -> BACKSPACE + '\x87' # 0x17 -> CONTROL + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x92' # 0x1A -> CONTROL + '\x8f' # 0x1B -> CONTROL + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + '\x80' # 0x20 -> CONTROL + '\x81' # 0x21 -> CONTROL + '\x82' # 0x22 -> CONTROL + '\x83' # 0x23 -> CONTROL + '\x84' # 0x24 -> CONTROL + '\n' # 0x25 -> LINE FEED + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK + '\x1b' # 0x27 -> ESCAPE + '\x88' # 0x28 -> CONTROL + '\x89' # 0x29 -> CONTROL + '\x8a' # 0x2A -> CONTROL + '\x8b' # 0x2B -> CONTROL + '\x8c' # 0x2C -> CONTROL + '\x05' # 0x2D -> ENQUIRY + '\x06' # 0x2E -> ACKNOWLEDGE + '\x07' # 0x2F -> BELL + '\x90' # 0x30 -> CONTROL + '\x91' # 0x31 -> CONTROL + '\x16' # 0x32 -> SYNCHRONOUS IDLE + '\x93' # 0x33 -> CONTROL + '\x94' # 0x34 -> CONTROL + '\x95' # 0x35 -> CONTROL + '\x96' # 0x36 -> CONTROL + '\x04' # 0x37 -> END OF TRANSMISSION + '\x98' # 0x38 -> CONTROL + '\x99' # 0x39 -> CONTROL + '\x9a' # 0x3A -> CONTROL + '\x9b' # 0x3B -> CONTROL + '\x14' # 0x3C -> DEVICE CONTROL FOUR + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + '\x9e' # 0x3E -> CONTROL + '\x1a' # 0x3F -> SUBSTITUTE + ' ' # 0x40 -> SPACE + '\xa0' # 0x41 -> NO-BREAK SPACE + '\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + '\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + '\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + '\xa2' # 0x4A -> CENT SIGN + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '|' # 0x4F -> VERTICAL LINE + '&' # 0x50 -> AMPERSAND + '\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + '\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + '\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + '!' # 0x5A -> EXCLAMATION MARK + '$' # 0x5B -> DOLLAR SIGN + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '\xac' # 0x5F -> NOT SIGN + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + '\xa6' # 0x6A -> BROKEN BAR + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + '\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + '`' # 0x79 -> GRAVE ACCENT + ':' # 0x7A -> COLON + '#' # 0x7B -> NUMBER SIGN + '@' # 0x7C -> COMMERCIAL AT + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '"' # 0x7F -> QUOTATION MARK + '\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xf0' # 0x8C -> LATIN SMALL LETTER ETH (ICELANDIC) + '\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0x8E -> LATIN SMALL LETTER THORN (ICELANDIC) + '\xb1' # 0x8F -> PLUS-MINUS SIGN + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + '\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + '\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + '\xb8' # 0x9D -> CEDILLA + '\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + '\u20ac' # 0x9F -> EURO SIGN + '\xb5' # 0xA0 -> MICRO SIGN + '~' # 0xA1 -> TILDE + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + '\xbf' # 0xAB -> INVERTED QUESTION MARK + '\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC) + '\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC) + '\xae' # 0xAF -> REGISTERED SIGN + '^' # 0xB0 -> CIRCUMFLEX ACCENT + '\xa3' # 0xB1 -> POUND SIGN + '\xa5' # 0xB2 -> YEN SIGN + '\xb7' # 0xB3 -> MIDDLE DOT + '\xa9' # 0xB4 -> COPYRIGHT SIGN + '\xa7' # 0xB5 -> SECTION SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + '\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + '[' # 0xBA -> LEFT SQUARE BRACKET + ']' # 0xBB -> RIGHT SQUARE BRACKET + '\xaf' # 0xBC -> MACRON + '\xa8' # 0xBD -> DIAERESIS + '\xb4' # 0xBE -> ACUTE ACCENT + '\xd7' # 0xBF -> MULTIPLICATION SIGN + '{' # 0xC0 -> LEFT CURLY BRACKET + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0xCC -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + '\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + '}' # 0xD0 -> RIGHT CURLY BRACKET + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb9' # 0xDA -> SUPERSCRIPT ONE + '\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xDC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + '\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + '\\' # 0xE0 -> REVERSE SOLIDUS + '\xf7' # 0xE1 -> DIVISION SIGN + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd6' # 0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + '\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1250.py b/winvenv/Lib/encodings/cp1250.py new file mode 100644 index 0000000..c2c83aa --- /dev/null +++ b/winvenv/Lib/encodings/cp1250.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1250 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1250', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\ufffe' # 0x83 -> UNDEFINED + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\ufffe' # 0x88 -> UNDEFINED + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u015a' # 0x8C -> LATIN CAPITAL LETTER S WITH ACUTE + '\u0164' # 0x8D -> LATIN CAPITAL LETTER T WITH CARON + '\u017d' # 0x8E -> LATIN CAPITAL LETTER Z WITH CARON + '\u0179' # 0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u015b' # 0x9C -> LATIN SMALL LETTER S WITH ACUTE + '\u0165' # 0x9D -> LATIN SMALL LETTER T WITH CARON + '\u017e' # 0x9E -> LATIN SMALL LETTER Z WITH CARON + '\u017a' # 0x9F -> LATIN SMALL LETTER Z WITH ACUTE + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u02c7' # 0xA1 -> CARON + '\u02d8' # 0xA2 -> BREVE + '\u0141' # 0xA3 -> LATIN CAPITAL LETTER L WITH STROKE + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u0104' # 0xA5 -> LATIN CAPITAL LETTER A WITH OGONEK + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u015e' # 0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u02db' # 0xB2 -> OGONEK + '\u0142' # 0xB3 -> LATIN SMALL LETTER L WITH STROKE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\u0105' # 0xB9 -> LATIN SMALL LETTER A WITH OGONEK + '\u015f' # 0xBA -> LATIN SMALL LETTER S WITH CEDILLA + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u013d' # 0xBC -> LATIN CAPITAL LETTER L WITH CARON + '\u02dd' # 0xBD -> DOUBLE ACUTE ACCENT + '\u013e' # 0xBE -> LATIN SMALL LETTER L WITH CARON + '\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u0154' # 0xC0 -> LATIN CAPITAL LETTER R WITH ACUTE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u0139' # 0xC5 -> LATIN CAPITAL LETTER L WITH ACUTE + '\u0106' # 0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u011a' # 0xCC -> LATIN CAPITAL LETTER E WITH CARON + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\u010e' # 0xCF -> LATIN CAPITAL LETTER D WITH CARON + '\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + '\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\u0147' # 0xD2 -> LATIN CAPITAL LETTER N WITH CARON + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u0150' # 0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\u0158' # 0xD8 -> LATIN CAPITAL LETTER R WITH CARON + '\u016e' # 0xD9 -> LATIN CAPITAL LETTER U WITH RING ABOVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\u0170' # 0xDB -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\u0162' # 0xDE -> LATIN CAPITAL LETTER T WITH CEDILLA + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\u0155' # 0xE0 -> LATIN SMALL LETTER R WITH ACUTE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\u013a' # 0xE5 -> LATIN SMALL LETTER L WITH ACUTE + '\u0107' # 0xE6 -> LATIN SMALL LETTER C WITH ACUTE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\u011b' # 0xEC -> LATIN SMALL LETTER E WITH CARON + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\u010f' # 0xEF -> LATIN SMALL LETTER D WITH CARON + '\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + '\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + '\u0148' # 0xF2 -> LATIN SMALL LETTER N WITH CARON + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\u0151' # 0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\u0159' # 0xF8 -> LATIN SMALL LETTER R WITH CARON + '\u016f' # 0xF9 -> LATIN SMALL LETTER U WITH RING ABOVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\u0171' # 0xFB -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\u0163' # 0xFE -> LATIN SMALL LETTER T WITH CEDILLA + '\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1251.py b/winvenv/Lib/encodings/cp1251.py new file mode 100644 index 0000000..22bc660 --- /dev/null +++ b/winvenv/Lib/encodings/cp1251.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1251 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1251', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u0402' # 0x80 -> CYRILLIC CAPITAL LETTER DJE + '\u0403' # 0x81 -> CYRILLIC CAPITAL LETTER GJE + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0453' # 0x83 -> CYRILLIC SMALL LETTER GJE + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u20ac' # 0x88 -> EURO SIGN + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0409' # 0x8A -> CYRILLIC CAPITAL LETTER LJE + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u040a' # 0x8C -> CYRILLIC CAPITAL LETTER NJE + '\u040c' # 0x8D -> CYRILLIC CAPITAL LETTER KJE + '\u040b' # 0x8E -> CYRILLIC CAPITAL LETTER TSHE + '\u040f' # 0x8F -> CYRILLIC CAPITAL LETTER DZHE + '\u0452' # 0x90 -> CYRILLIC SMALL LETTER DJE + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0459' # 0x9A -> CYRILLIC SMALL LETTER LJE + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u045a' # 0x9C -> CYRILLIC SMALL LETTER NJE + '\u045c' # 0x9D -> CYRILLIC SMALL LETTER KJE + '\u045b' # 0x9E -> CYRILLIC SMALL LETTER TSHE + '\u045f' # 0x9F -> CYRILLIC SMALL LETTER DZHE + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u040e' # 0xA1 -> CYRILLIC CAPITAL LETTER SHORT U + '\u045e' # 0xA2 -> CYRILLIC SMALL LETTER SHORT U + '\u0408' # 0xA3 -> CYRILLIC CAPITAL LETTER JE + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u0490' # 0xA5 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\u0401' # 0xA8 -> CYRILLIC CAPITAL LETTER IO + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u0404' # 0xAA -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\u0407' # 0xAF -> CYRILLIC CAPITAL LETTER YI + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u0406' # 0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0456' # 0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0491' # 0xB4 -> CYRILLIC SMALL LETTER GHE WITH UPTURN + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u0451' # 0xB8 -> CYRILLIC SMALL LETTER IO + '\u2116' # 0xB9 -> NUMERO SIGN + '\u0454' # 0xBA -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u0458' # 0xBC -> CYRILLIC SMALL LETTER JE + '\u0405' # 0xBD -> CYRILLIC CAPITAL LETTER DZE + '\u0455' # 0xBE -> CYRILLIC SMALL LETTER DZE + '\u0457' # 0xBF -> CYRILLIC SMALL LETTER YI + '\u0410' # 0xC0 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xC1 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0xC2 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0xC3 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0xC4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xC5 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0xC6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0xC7 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0xC8 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xC9 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xCA -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xCB -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xCC -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xCD -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xCE -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xCF -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0xD0 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xD1 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xD2 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xD3 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0xD4 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0xD5 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0xD6 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0xD7 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0xD8 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0xD9 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0xDB -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0xDD -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0xDE -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0xDF -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + '\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + '\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + '\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + '\u044f' # 0xFF -> CYRILLIC SMALL LETTER YA +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1252.py b/winvenv/Lib/encodings/cp1252.py new file mode 100644 index 0000000..c0e8088 --- /dev/null +++ b/winvenv/Lib/encodings/cp1252.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1252 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1252', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + '\ufffe' # 0x8D -> UNDEFINED + '\u017d' # 0x8E -> LATIN CAPITAL LETTER Z WITH CARON + '\ufffe' # 0x8F -> UNDEFINED + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u02dc' # 0x98 -> SMALL TILDE + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + '\ufffe' # 0x9D -> UNDEFINED + '\u017e' # 0x9E -> LATIN SMALL LETTER Z WITH CARON + '\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xDE -> LATIN CAPITAL LETTER THORN + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf0' # 0xF0 -> LATIN SMALL LETTER ETH + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0xFE -> LATIN SMALL LETTER THORN + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1253.py b/winvenv/Lib/encodings/cp1253.py new file mode 100644 index 0000000..ec9c097 --- /dev/null +++ b/winvenv/Lib/encodings/cp1253.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1253 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1253.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1253', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\ufffe' # 0x88 -> UNDEFINED + '\u2030' # 0x89 -> PER MILLE SIGN + '\ufffe' # 0x8A -> UNDEFINED + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x8C -> UNDEFINED + '\ufffe' # 0x8D -> UNDEFINED + '\ufffe' # 0x8E -> UNDEFINED + '\ufffe' # 0x8F -> UNDEFINED + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\ufffe' # 0x9A -> UNDEFINED + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x9C -> UNDEFINED + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\ufffe' # 0x9F -> UNDEFINED + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0385' # 0xA1 -> GREEK DIALYTIKA TONOS + '\u0386' # 0xA2 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\ufffe' # 0xAA -> UNDEFINED + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\u2015' # 0xAF -> HORIZONTAL BAR + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\u0384' # 0xB4 -> GREEK TONOS + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u0388' # 0xB8 -> GREEK CAPITAL LETTER EPSILON WITH TONOS + '\u0389' # 0xB9 -> GREEK CAPITAL LETTER ETA WITH TONOS + '\u038a' # 0xBA -> GREEK CAPITAL LETTER IOTA WITH TONOS + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u038c' # 0xBC -> GREEK CAPITAL LETTER OMICRON WITH TONOS + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\u038e' # 0xBE -> GREEK CAPITAL LETTER UPSILON WITH TONOS + '\u038f' # 0xBF -> GREEK CAPITAL LETTER OMEGA WITH TONOS + '\u0390' # 0xC0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + '\u0391' # 0xC1 -> GREEK CAPITAL LETTER ALPHA + '\u0392' # 0xC2 -> GREEK CAPITAL LETTER BETA + '\u0393' # 0xC3 -> GREEK CAPITAL LETTER GAMMA + '\u0394' # 0xC4 -> GREEK CAPITAL LETTER DELTA + '\u0395' # 0xC5 -> GREEK CAPITAL LETTER EPSILON + '\u0396' # 0xC6 -> GREEK CAPITAL LETTER ZETA + '\u0397' # 0xC7 -> GREEK CAPITAL LETTER ETA + '\u0398' # 0xC8 -> GREEK CAPITAL LETTER THETA + '\u0399' # 0xC9 -> GREEK CAPITAL LETTER IOTA + '\u039a' # 0xCA -> GREEK CAPITAL LETTER KAPPA + '\u039b' # 0xCB -> GREEK CAPITAL LETTER LAMDA + '\u039c' # 0xCC -> GREEK CAPITAL LETTER MU + '\u039d' # 0xCD -> GREEK CAPITAL LETTER NU + '\u039e' # 0xCE -> GREEK CAPITAL LETTER XI + '\u039f' # 0xCF -> GREEK CAPITAL LETTER OMICRON + '\u03a0' # 0xD0 -> GREEK CAPITAL LETTER PI + '\u03a1' # 0xD1 -> GREEK CAPITAL LETTER RHO + '\ufffe' # 0xD2 -> UNDEFINED + '\u03a3' # 0xD3 -> GREEK CAPITAL LETTER SIGMA + '\u03a4' # 0xD4 -> GREEK CAPITAL LETTER TAU + '\u03a5' # 0xD5 -> GREEK CAPITAL LETTER UPSILON + '\u03a6' # 0xD6 -> GREEK CAPITAL LETTER PHI + '\u03a7' # 0xD7 -> GREEK CAPITAL LETTER CHI + '\u03a8' # 0xD8 -> GREEK CAPITAL LETTER PSI + '\u03a9' # 0xD9 -> GREEK CAPITAL LETTER OMEGA + '\u03aa' # 0xDA -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + '\u03ab' # 0xDB -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + '\u03ac' # 0xDC -> GREEK SMALL LETTER ALPHA WITH TONOS + '\u03ad' # 0xDD -> GREEK SMALL LETTER EPSILON WITH TONOS + '\u03ae' # 0xDE -> GREEK SMALL LETTER ETA WITH TONOS + '\u03af' # 0xDF -> GREEK SMALL LETTER IOTA WITH TONOS + '\u03b0' # 0xE0 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + '\u03b1' # 0xE1 -> GREEK SMALL LETTER ALPHA + '\u03b2' # 0xE2 -> GREEK SMALL LETTER BETA + '\u03b3' # 0xE3 -> GREEK SMALL LETTER GAMMA + '\u03b4' # 0xE4 -> GREEK SMALL LETTER DELTA + '\u03b5' # 0xE5 -> GREEK SMALL LETTER EPSILON + '\u03b6' # 0xE6 -> GREEK SMALL LETTER ZETA + '\u03b7' # 0xE7 -> GREEK SMALL LETTER ETA + '\u03b8' # 0xE8 -> GREEK SMALL LETTER THETA + '\u03b9' # 0xE9 -> GREEK SMALL LETTER IOTA + '\u03ba' # 0xEA -> GREEK SMALL LETTER KAPPA + '\u03bb' # 0xEB -> GREEK SMALL LETTER LAMDA + '\u03bc' # 0xEC -> GREEK SMALL LETTER MU + '\u03bd' # 0xED -> GREEK SMALL LETTER NU + '\u03be' # 0xEE -> GREEK SMALL LETTER XI + '\u03bf' # 0xEF -> GREEK SMALL LETTER OMICRON + '\u03c0' # 0xF0 -> GREEK SMALL LETTER PI + '\u03c1' # 0xF1 -> GREEK SMALL LETTER RHO + '\u03c2' # 0xF2 -> GREEK SMALL LETTER FINAL SIGMA + '\u03c3' # 0xF3 -> GREEK SMALL LETTER SIGMA + '\u03c4' # 0xF4 -> GREEK SMALL LETTER TAU + '\u03c5' # 0xF5 -> GREEK SMALL LETTER UPSILON + '\u03c6' # 0xF6 -> GREEK SMALL LETTER PHI + '\u03c7' # 0xF7 -> GREEK SMALL LETTER CHI + '\u03c8' # 0xF8 -> GREEK SMALL LETTER PSI + '\u03c9' # 0xF9 -> GREEK SMALL LETTER OMEGA + '\u03ca' # 0xFA -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + '\u03cb' # 0xFB -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + '\u03cc' # 0xFC -> GREEK SMALL LETTER OMICRON WITH TONOS + '\u03cd' # 0xFD -> GREEK SMALL LETTER UPSILON WITH TONOS + '\u03ce' # 0xFE -> GREEK SMALL LETTER OMEGA WITH TONOS + '\ufffe' # 0xFF -> UNDEFINED +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1254.py b/winvenv/Lib/encodings/cp1254.py new file mode 100644 index 0000000..4912327 --- /dev/null +++ b/winvenv/Lib/encodings/cp1254.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1254 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1254.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1254', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + '\ufffe' # 0x8D -> UNDEFINED + '\ufffe' # 0x8E -> UNDEFINED + '\ufffe' # 0x8F -> UNDEFINED + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u02dc' # 0x98 -> SMALL TILDE + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u011e' # 0xD0 -> LATIN CAPITAL LETTER G WITH BREVE + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u0130' # 0xDD -> LATIN CAPITAL LETTER I WITH DOT ABOVE + '\u015e' # 0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\u011f' # 0xF0 -> LATIN SMALL LETTER G WITH BREVE + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u0131' # 0xFD -> LATIN SMALL LETTER DOTLESS I + '\u015f' # 0xFE -> LATIN SMALL LETTER S WITH CEDILLA + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1255.py b/winvenv/Lib/encodings/cp1255.py new file mode 100644 index 0000000..91ce26b --- /dev/null +++ b/winvenv/Lib/encodings/cp1255.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1255 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1255.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1255', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u2030' # 0x89 -> PER MILLE SIGN + '\ufffe' # 0x8A -> UNDEFINED + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x8C -> UNDEFINED + '\ufffe' # 0x8D -> UNDEFINED + '\ufffe' # 0x8E -> UNDEFINED + '\ufffe' # 0x8F -> UNDEFINED + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u02dc' # 0x98 -> SMALL TILDE + '\u2122' # 0x99 -> TRADE MARK SIGN + '\ufffe' # 0x9A -> UNDEFINED + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x9C -> UNDEFINED + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\ufffe' # 0x9F -> UNDEFINED + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\u20aa' # 0xA4 -> NEW SHEQEL SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xd7' # 0xAA -> MULTIPLICATION SIGN + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xf7' # 0xBA -> DIVISION SIGN + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\u05b0' # 0xC0 -> HEBREW POINT SHEVA + '\u05b1' # 0xC1 -> HEBREW POINT HATAF SEGOL + '\u05b2' # 0xC2 -> HEBREW POINT HATAF PATAH + '\u05b3' # 0xC3 -> HEBREW POINT HATAF QAMATS + '\u05b4' # 0xC4 -> HEBREW POINT HIRIQ + '\u05b5' # 0xC5 -> HEBREW POINT TSERE + '\u05b6' # 0xC6 -> HEBREW POINT SEGOL + '\u05b7' # 0xC7 -> HEBREW POINT PATAH + '\u05b8' # 0xC8 -> HEBREW POINT QAMATS + '\u05b9' # 0xC9 -> HEBREW POINT HOLAM + '\ufffe' # 0xCA -> UNDEFINED + '\u05bb' # 0xCB -> HEBREW POINT QUBUTS + '\u05bc' # 0xCC -> HEBREW POINT DAGESH OR MAPIQ + '\u05bd' # 0xCD -> HEBREW POINT METEG + '\u05be' # 0xCE -> HEBREW PUNCTUATION MAQAF + '\u05bf' # 0xCF -> HEBREW POINT RAFE + '\u05c0' # 0xD0 -> HEBREW PUNCTUATION PASEQ + '\u05c1' # 0xD1 -> HEBREW POINT SHIN DOT + '\u05c2' # 0xD2 -> HEBREW POINT SIN DOT + '\u05c3' # 0xD3 -> HEBREW PUNCTUATION SOF PASUQ + '\u05f0' # 0xD4 -> HEBREW LIGATURE YIDDISH DOUBLE VAV + '\u05f1' # 0xD5 -> HEBREW LIGATURE YIDDISH VAV YOD + '\u05f2' # 0xD6 -> HEBREW LIGATURE YIDDISH DOUBLE YOD + '\u05f3' # 0xD7 -> HEBREW PUNCTUATION GERESH + '\u05f4' # 0xD8 -> HEBREW PUNCTUATION GERSHAYIM + '\ufffe' # 0xD9 -> UNDEFINED + '\ufffe' # 0xDA -> UNDEFINED + '\ufffe' # 0xDB -> UNDEFINED + '\ufffe' # 0xDC -> UNDEFINED + '\ufffe' # 0xDD -> UNDEFINED + '\ufffe' # 0xDE -> UNDEFINED + '\ufffe' # 0xDF -> UNDEFINED + '\u05d0' # 0xE0 -> HEBREW LETTER ALEF + '\u05d1' # 0xE1 -> HEBREW LETTER BET + '\u05d2' # 0xE2 -> HEBREW LETTER GIMEL + '\u05d3' # 0xE3 -> HEBREW LETTER DALET + '\u05d4' # 0xE4 -> HEBREW LETTER HE + '\u05d5' # 0xE5 -> HEBREW LETTER VAV + '\u05d6' # 0xE6 -> HEBREW LETTER ZAYIN + '\u05d7' # 0xE7 -> HEBREW LETTER HET + '\u05d8' # 0xE8 -> HEBREW LETTER TET + '\u05d9' # 0xE9 -> HEBREW LETTER YOD + '\u05da' # 0xEA -> HEBREW LETTER FINAL KAF + '\u05db' # 0xEB -> HEBREW LETTER KAF + '\u05dc' # 0xEC -> HEBREW LETTER LAMED + '\u05dd' # 0xED -> HEBREW LETTER FINAL MEM + '\u05de' # 0xEE -> HEBREW LETTER MEM + '\u05df' # 0xEF -> HEBREW LETTER FINAL NUN + '\u05e0' # 0xF0 -> HEBREW LETTER NUN + '\u05e1' # 0xF1 -> HEBREW LETTER SAMEKH + '\u05e2' # 0xF2 -> HEBREW LETTER AYIN + '\u05e3' # 0xF3 -> HEBREW LETTER FINAL PE + '\u05e4' # 0xF4 -> HEBREW LETTER PE + '\u05e5' # 0xF5 -> HEBREW LETTER FINAL TSADI + '\u05e6' # 0xF6 -> HEBREW LETTER TSADI + '\u05e7' # 0xF7 -> HEBREW LETTER QOF + '\u05e8' # 0xF8 -> HEBREW LETTER RESH + '\u05e9' # 0xF9 -> HEBREW LETTER SHIN + '\u05ea' # 0xFA -> HEBREW LETTER TAV + '\ufffe' # 0xFB -> UNDEFINED + '\ufffe' # 0xFC -> UNDEFINED + '\u200e' # 0xFD -> LEFT-TO-RIGHT MARK + '\u200f' # 0xFE -> RIGHT-TO-LEFT MARK + '\ufffe' # 0xFF -> UNDEFINED +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1256.py b/winvenv/Lib/encodings/cp1256.py new file mode 100644 index 0000000..fd6afab --- /dev/null +++ b/winvenv/Lib/encodings/cp1256.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1256 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1256.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1256', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\u067e' # 0x81 -> ARABIC LETTER PEH + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0679' # 0x8A -> ARABIC LETTER TTEH + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + '\u0686' # 0x8D -> ARABIC LETTER TCHEH + '\u0698' # 0x8E -> ARABIC LETTER JEH + '\u0688' # 0x8F -> ARABIC LETTER DDAL + '\u06af' # 0x90 -> ARABIC LETTER GAF + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u06a9' # 0x98 -> ARABIC LETTER KEHEH + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0691' # 0x9A -> ARABIC LETTER RREH + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + '\u200c' # 0x9D -> ZERO WIDTH NON-JOINER + '\u200d' # 0x9E -> ZERO WIDTH JOINER + '\u06ba' # 0x9F -> ARABIC LETTER NOON GHUNNA + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u060c' # 0xA1 -> ARABIC COMMA + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u06be' # 0xAA -> ARABIC LETTER HEH DOACHASHMEE + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\u061b' # 0xBA -> ARABIC SEMICOLON + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\u061f' # 0xBF -> ARABIC QUESTION MARK + '\u06c1' # 0xC0 -> ARABIC LETTER HEH GOAL + '\u0621' # 0xC1 -> ARABIC LETTER HAMZA + '\u0622' # 0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + '\u0623' # 0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + '\u0624' # 0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + '\u0625' # 0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + '\u0626' # 0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + '\u0627' # 0xC7 -> ARABIC LETTER ALEF + '\u0628' # 0xC8 -> ARABIC LETTER BEH + '\u0629' # 0xC9 -> ARABIC LETTER TEH MARBUTA + '\u062a' # 0xCA -> ARABIC LETTER TEH + '\u062b' # 0xCB -> ARABIC LETTER THEH + '\u062c' # 0xCC -> ARABIC LETTER JEEM + '\u062d' # 0xCD -> ARABIC LETTER HAH + '\u062e' # 0xCE -> ARABIC LETTER KHAH + '\u062f' # 0xCF -> ARABIC LETTER DAL + '\u0630' # 0xD0 -> ARABIC LETTER THAL + '\u0631' # 0xD1 -> ARABIC LETTER REH + '\u0632' # 0xD2 -> ARABIC LETTER ZAIN + '\u0633' # 0xD3 -> ARABIC LETTER SEEN + '\u0634' # 0xD4 -> ARABIC LETTER SHEEN + '\u0635' # 0xD5 -> ARABIC LETTER SAD + '\u0636' # 0xD6 -> ARABIC LETTER DAD + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\u0637' # 0xD8 -> ARABIC LETTER TAH + '\u0638' # 0xD9 -> ARABIC LETTER ZAH + '\u0639' # 0xDA -> ARABIC LETTER AIN + '\u063a' # 0xDB -> ARABIC LETTER GHAIN + '\u0640' # 0xDC -> ARABIC TATWEEL + '\u0641' # 0xDD -> ARABIC LETTER FEH + '\u0642' # 0xDE -> ARABIC LETTER QAF + '\u0643' # 0xDF -> ARABIC LETTER KAF + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\u0644' # 0xE1 -> ARABIC LETTER LAM + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\u0645' # 0xE3 -> ARABIC LETTER MEEM + '\u0646' # 0xE4 -> ARABIC LETTER NOON + '\u0647' # 0xE5 -> ARABIC LETTER HEH + '\u0648' # 0xE6 -> ARABIC LETTER WAW + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\u0649' # 0xEC -> ARABIC LETTER ALEF MAKSURA + '\u064a' # 0xED -> ARABIC LETTER YEH + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\u064b' # 0xF0 -> ARABIC FATHATAN + '\u064c' # 0xF1 -> ARABIC DAMMATAN + '\u064d' # 0xF2 -> ARABIC KASRATAN + '\u064e' # 0xF3 -> ARABIC FATHA + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\u064f' # 0xF5 -> ARABIC DAMMA + '\u0650' # 0xF6 -> ARABIC KASRA + '\xf7' # 0xF7 -> DIVISION SIGN + '\u0651' # 0xF8 -> ARABIC SHADDA + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\u0652' # 0xFA -> ARABIC SUKUN + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u200e' # 0xFD -> LEFT-TO-RIGHT MARK + '\u200f' # 0xFE -> RIGHT-TO-LEFT MARK + '\u06d2' # 0xFF -> ARABIC LETTER YEH BARREE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1257.py b/winvenv/Lib/encodings/cp1257.py new file mode 100644 index 0000000..9ebc90d --- /dev/null +++ b/winvenv/Lib/encodings/cp1257.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1257 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1257.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1257', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\ufffe' # 0x83 -> UNDEFINED + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\ufffe' # 0x88 -> UNDEFINED + '\u2030' # 0x89 -> PER MILLE SIGN + '\ufffe' # 0x8A -> UNDEFINED + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x8C -> UNDEFINED + '\xa8' # 0x8D -> DIAERESIS + '\u02c7' # 0x8E -> CARON + '\xb8' # 0x8F -> CEDILLA + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\ufffe' # 0x9A -> UNDEFINED + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x9C -> UNDEFINED + '\xaf' # 0x9D -> MACRON + '\u02db' # 0x9E -> OGONEK + '\ufffe' # 0x9F -> UNDEFINED + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\ufffe' # 0xA1 -> UNDEFINED + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\ufffe' # 0xA5 -> UNDEFINED + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xd8' # 0xA8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u0156' # 0xAA -> LATIN CAPITAL LETTER R WITH CEDILLA + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xc6' # 0xAF -> LATIN CAPITAL LETTER AE + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xf8' # 0xB8 -> LATIN SMALL LETTER O WITH STROKE + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\u0157' # 0xBA -> LATIN SMALL LETTER R WITH CEDILLA + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xe6' # 0xBF -> LATIN SMALL LETTER AE + '\u0104' # 0xC0 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u012e' # 0xC1 -> LATIN CAPITAL LETTER I WITH OGONEK + '\u0100' # 0xC2 -> LATIN CAPITAL LETTER A WITH MACRON + '\u0106' # 0xC3 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\u0118' # 0xC6 -> LATIN CAPITAL LETTER E WITH OGONEK + '\u0112' # 0xC7 -> LATIN CAPITAL LETTER E WITH MACRON + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0179' # 0xCA -> LATIN CAPITAL LETTER Z WITH ACUTE + '\u0116' # 0xCB -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\u0122' # 0xCC -> LATIN CAPITAL LETTER G WITH CEDILLA + '\u0136' # 0xCD -> LATIN CAPITAL LETTER K WITH CEDILLA + '\u012a' # 0xCE -> LATIN CAPITAL LETTER I WITH MACRON + '\u013b' # 0xCF -> LATIN CAPITAL LETTER L WITH CEDILLA + '\u0160' # 0xD0 -> LATIN CAPITAL LETTER S WITH CARON + '\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\u0145' # 0xD2 -> LATIN CAPITAL LETTER N WITH CEDILLA + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\u014c' # 0xD4 -> LATIN CAPITAL LETTER O WITH MACRON + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\u0172' # 0xD8 -> LATIN CAPITAL LETTER U WITH OGONEK + '\u0141' # 0xD9 -> LATIN CAPITAL LETTER L WITH STROKE + '\u015a' # 0xDA -> LATIN CAPITAL LETTER S WITH ACUTE + '\u016a' # 0xDB -> LATIN CAPITAL LETTER U WITH MACRON + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u017b' # 0xDD -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\u017d' # 0xDE -> LATIN CAPITAL LETTER Z WITH CARON + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\u0105' # 0xE0 -> LATIN SMALL LETTER A WITH OGONEK + '\u012f' # 0xE1 -> LATIN SMALL LETTER I WITH OGONEK + '\u0101' # 0xE2 -> LATIN SMALL LETTER A WITH MACRON + '\u0107' # 0xE3 -> LATIN SMALL LETTER C WITH ACUTE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\u0119' # 0xE6 -> LATIN SMALL LETTER E WITH OGONEK + '\u0113' # 0xE7 -> LATIN SMALL LETTER E WITH MACRON + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\u017a' # 0xEA -> LATIN SMALL LETTER Z WITH ACUTE + '\u0117' # 0xEB -> LATIN SMALL LETTER E WITH DOT ABOVE + '\u0123' # 0xEC -> LATIN SMALL LETTER G WITH CEDILLA + '\u0137' # 0xED -> LATIN SMALL LETTER K WITH CEDILLA + '\u012b' # 0xEE -> LATIN SMALL LETTER I WITH MACRON + '\u013c' # 0xEF -> LATIN SMALL LETTER L WITH CEDILLA + '\u0161' # 0xF0 -> LATIN SMALL LETTER S WITH CARON + '\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + '\u0146' # 0xF2 -> LATIN SMALL LETTER N WITH CEDILLA + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\u014d' # 0xF4 -> LATIN SMALL LETTER O WITH MACRON + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\u0173' # 0xF8 -> LATIN SMALL LETTER U WITH OGONEK + '\u0142' # 0xF9 -> LATIN SMALL LETTER L WITH STROKE + '\u015b' # 0xFA -> LATIN SMALL LETTER S WITH ACUTE + '\u016b' # 0xFB -> LATIN SMALL LETTER U WITH MACRON + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u017e' # 0xFE -> LATIN SMALL LETTER Z WITH CARON + '\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp1258.py b/winvenv/Lib/encodings/cp1258.py new file mode 100644 index 0000000..784378a --- /dev/null +++ b/winvenv/Lib/encodings/cp1258.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp1258 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1258.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp1258', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u2030' # 0x89 -> PER MILLE SIGN + '\ufffe' # 0x8A -> UNDEFINED + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + '\ufffe' # 0x8D -> UNDEFINED + '\ufffe' # 0x8E -> UNDEFINED + '\ufffe' # 0x8F -> UNDEFINED + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u02dc' # 0x98 -> SMALL TILDE + '\u2122' # 0x99 -> TRADE MARK SIGN + '\ufffe' # 0x9A -> UNDEFINED + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u0300' # 0xCC -> COMBINING GRAVE ACCENT + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\u0309' # 0xD2 -> COMBINING HOOK ABOVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u01a0' # 0xD5 -> LATIN CAPITAL LETTER O WITH HORN + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u01af' # 0xDD -> LATIN CAPITAL LETTER U WITH HORN + '\u0303' # 0xDE -> COMBINING TILDE + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\u0301' # 0xEC -> COMBINING ACUTE ACCENT + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\u0323' # 0xF2 -> COMBINING DOT BELOW + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\u01a1' # 0xF5 -> LATIN SMALL LETTER O WITH HORN + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u01b0' # 0xFD -> LATIN SMALL LETTER U WITH HORN + '\u20ab' # 0xFE -> DONG SIGN + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp273.py b/winvenv/Lib/encodings/cp273.py new file mode 100644 index 0000000..69c6d77 --- /dev/null +++ b/winvenv/Lib/encodings/cp273.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp273 generated from 'python-mappings/CP273.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp273', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL (NUL) + '\x01' # 0x01 -> START OF HEADING (SOH) + '\x02' # 0x02 -> START OF TEXT (STX) + '\x03' # 0x03 -> END OF TEXT (ETX) + '\x9c' # 0x04 -> STRING TERMINATOR (ST) + '\t' # 0x05 -> CHARACTER TABULATION (HT) + '\x86' # 0x06 -> START OF SELECTED AREA (SSA) + '\x7f' # 0x07 -> DELETE (DEL) + '\x97' # 0x08 -> END OF GUARDED AREA (EPA) + '\x8d' # 0x09 -> REVERSE LINE FEED (RI) + '\x8e' # 0x0A -> SINGLE-SHIFT TWO (SS2) + '\x0b' # 0x0B -> LINE TABULATION (VT) + '\x0c' # 0x0C -> FORM FEED (FF) + '\r' # 0x0D -> CARRIAGE RETURN (CR) + '\x0e' # 0x0E -> SHIFT OUT (SO) + '\x0f' # 0x0F -> SHIFT IN (SI) + '\x10' # 0x10 -> DATALINK ESCAPE (DLE) + '\x11' # 0x11 -> DEVICE CONTROL ONE (DC1) + '\x12' # 0x12 -> DEVICE CONTROL TWO (DC2) + '\x13' # 0x13 -> DEVICE CONTROL THREE (DC3) + '\x9d' # 0x14 -> OPERATING SYSTEM COMMAND (OSC) + '\x85' # 0x15 -> NEXT LINE (NEL) + '\x08' # 0x16 -> BACKSPACE (BS) + '\x87' # 0x17 -> END OF SELECTED AREA (ESA) + '\x18' # 0x18 -> CANCEL (CAN) + '\x19' # 0x19 -> END OF MEDIUM (EM) + '\x92' # 0x1A -> PRIVATE USE TWO (PU2) + '\x8f' # 0x1B -> SINGLE-SHIFT THREE (SS3) + '\x1c' # 0x1C -> FILE SEPARATOR (IS4) + '\x1d' # 0x1D -> GROUP SEPARATOR (IS3) + '\x1e' # 0x1E -> RECORD SEPARATOR (IS2) + '\x1f' # 0x1F -> UNIT SEPARATOR (IS1) + '\x80' # 0x20 -> PADDING CHARACTER (PAD) + '\x81' # 0x21 -> HIGH OCTET PRESET (HOP) + '\x82' # 0x22 -> BREAK PERMITTED HERE (BPH) + '\x83' # 0x23 -> NO BREAK HERE (NBH) + '\x84' # 0x24 -> INDEX (IND) + '\n' # 0x25 -> LINE FEED (LF) + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK (ETB) + '\x1b' # 0x27 -> ESCAPE (ESC) + '\x88' # 0x28 -> CHARACTER TABULATION SET (HTS) + '\x89' # 0x29 -> CHARACTER TABULATION WITH JUSTIFICATION (HTJ) + '\x8a' # 0x2A -> LINE TABULATION SET (VTS) + '\x8b' # 0x2B -> PARTIAL LINE FORWARD (PLD) + '\x8c' # 0x2C -> PARTIAL LINE BACKWARD (PLU) + '\x05' # 0x2D -> ENQUIRY (ENQ) + '\x06' # 0x2E -> ACKNOWLEDGE (ACK) + '\x07' # 0x2F -> BELL (BEL) + '\x90' # 0x30 -> DEVICE CONTROL STRING (DCS) + '\x91' # 0x31 -> PRIVATE USE ONE (PU1) + '\x16' # 0x32 -> SYNCHRONOUS IDLE (SYN) + '\x93' # 0x33 -> SET TRANSMIT STATE (STS) + '\x94' # 0x34 -> CANCEL CHARACTER (CCH) + '\x95' # 0x35 -> MESSAGE WAITING (MW) + '\x96' # 0x36 -> START OF GUARDED AREA (SPA) + '\x04' # 0x37 -> END OF TRANSMISSION (EOT) + '\x98' # 0x38 -> START OF STRING (SOS) + '\x99' # 0x39 -> SINGLE GRAPHIC CHARACTER INTRODUCER (SGCI) + '\x9a' # 0x3A -> SINGLE CHARACTER INTRODUCER (SCI) + '\x9b' # 0x3B -> CONTROL SEQUENCE INTRODUCER (CSI) + '\x14' # 0x3C -> DEVICE CONTROL FOUR (DC4) + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE (NAK) + '\x9e' # 0x3E -> PRIVACY MESSAGE (PM) + '\x1a' # 0x3F -> SUBSTITUTE (SUB) + ' ' # 0x40 -> SPACE + '\xa0' # 0x41 -> NO-BREAK SPACE + '\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '{' # 0x43 -> LEFT CURLY BRACKET + '\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + '\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + '\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + '\xc4' # 0x4A -> LATIN CAPITAL LETTER A WITH DIAERESIS + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '!' # 0x4F -> EXCLAMATION MARK + '&' # 0x50 -> AMPERSAND + '\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + '\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + '~' # 0x59 -> TILDE + '\xdc' # 0x5A -> LATIN CAPITAL LETTER U WITH DIAERESIS + '$' # 0x5B -> DOLLAR SIGN + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '^' # 0x5F -> CIRCUMFLEX ACCENT + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '[' # 0x63 -> LEFT SQUARE BRACKET + '\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + '\xf6' # 0x6A -> LATIN SMALL LETTER O WITH DIAERESIS + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + '\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + '`' # 0x79 -> GRAVE ACCENT + ':' # 0x7A -> COLON + '#' # 0x7B -> NUMBER SIGN + '\xa7' # 0x7C -> SECTION SIGN + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '"' # 0x7F -> QUOTATION MARK + '\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xf0' # 0x8C -> LATIN SMALL LETTER ETH (Icelandic) + '\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0x8E -> LATIN SMALL LETTER THORN (Icelandic) + '\xb1' # 0x8F -> PLUS-MINUS SIGN + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + '\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + '\xe6' # 0x9C -> LATIN SMALL LETTER AE + '\xb8' # 0x9D -> CEDILLA + '\xc6' # 0x9E -> LATIN CAPITAL LETTER AE + '\xa4' # 0x9F -> CURRENCY SIGN + '\xb5' # 0xA0 -> MICRO SIGN + '\xdf' # 0xA1 -> LATIN SMALL LETTER SHARP S (German) + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + '\xbf' # 0xAB -> INVERTED QUESTION MARK + '\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (Icelandic) + '\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (Icelandic) + '\xae' # 0xAF -> REGISTERED SIGN + '\xa2' # 0xB0 -> CENT SIGN + '\xa3' # 0xB1 -> POUND SIGN + '\xa5' # 0xB2 -> YEN SIGN + '\xb7' # 0xB3 -> MIDDLE DOT + '\xa9' # 0xB4 -> COPYRIGHT SIGN + '@' # 0xB5 -> COMMERCIAL AT + '\xb6' # 0xB6 -> PILCROW SIGN + '\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + '\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + '\xac' # 0xBA -> NOT SIGN + '|' # 0xBB -> VERTICAL LINE + '\u203e' # 0xBC -> OVERLINE + '\xa8' # 0xBD -> DIAERESIS + '\xb4' # 0xBE -> ACUTE ACCENT + '\xd7' # 0xBF -> MULTIPLICATION SIGN + '\xe4' # 0xC0 -> LATIN SMALL LETTER A WITH DIAERESIS + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xa6' # 0xCC -> BROKEN BAR + '\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + '\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + '\xfc' # 0xD0 -> LATIN SMALL LETTER U WITH DIAERESIS + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb9' # 0xDA -> SUPERSCRIPT ONE + '\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '}' # 0xDC -> RIGHT CURLY BRACKET + '\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + '\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xd6' # 0xE0 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xf7' # 0xE1 -> DIVISION SIGN + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\\' # 0xEC -> REVERSE SOLIDUS + '\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + ']' # 0xFC -> RIGHT SQUARE BRACKET + '\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + '\x9f' # 0xFF -> APPLICATION PROGRAM COMMAND (APC) +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp424.py b/winvenv/Lib/encodings/cp424.py new file mode 100644 index 0000000..6753daf --- /dev/null +++ b/winvenv/Lib/encodings/cp424.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp424 generated from 'MAPPINGS/VENDORS/MISC/CP424.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp424', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x9c' # 0x04 -> SELECT + '\t' # 0x05 -> HORIZONTAL TABULATION + '\x86' # 0x06 -> REQUIRED NEW LINE + '\x7f' # 0x07 -> DELETE + '\x97' # 0x08 -> GRAPHIC ESCAPE + '\x8d' # 0x09 -> SUPERSCRIPT + '\x8e' # 0x0A -> REPEAT + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x9d' # 0x14 -> RESTORE/ENABLE PRESENTATION + '\x85' # 0x15 -> NEW LINE + '\x08' # 0x16 -> BACKSPACE + '\x87' # 0x17 -> PROGRAM OPERATOR COMMUNICATION + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x92' # 0x1A -> UNIT BACK SPACE + '\x8f' # 0x1B -> CUSTOMER USE ONE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + '\x80' # 0x20 -> DIGIT SELECT + '\x81' # 0x21 -> START OF SIGNIFICANCE + '\x82' # 0x22 -> FIELD SEPARATOR + '\x83' # 0x23 -> WORD UNDERSCORE + '\x84' # 0x24 -> BYPASS OR INHIBIT PRESENTATION + '\n' # 0x25 -> LINE FEED + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK + '\x1b' # 0x27 -> ESCAPE + '\x88' # 0x28 -> SET ATTRIBUTE + '\x89' # 0x29 -> START FIELD EXTENDED + '\x8a' # 0x2A -> SET MODE OR SWITCH + '\x8b' # 0x2B -> CONTROL SEQUENCE PREFIX + '\x8c' # 0x2C -> MODIFY FIELD ATTRIBUTE + '\x05' # 0x2D -> ENQUIRY + '\x06' # 0x2E -> ACKNOWLEDGE + '\x07' # 0x2F -> BELL + '\x90' # 0x30 -> + '\x91' # 0x31 -> + '\x16' # 0x32 -> SYNCHRONOUS IDLE + '\x93' # 0x33 -> INDEX RETURN + '\x94' # 0x34 -> PRESENTATION POSITION + '\x95' # 0x35 -> TRANSPARENT + '\x96' # 0x36 -> NUMERIC BACKSPACE + '\x04' # 0x37 -> END OF TRANSMISSION + '\x98' # 0x38 -> SUBSCRIPT + '\x99' # 0x39 -> INDENT TABULATION + '\x9a' # 0x3A -> REVERSE FORM FEED + '\x9b' # 0x3B -> CUSTOMER USE THREE + '\x14' # 0x3C -> DEVICE CONTROL FOUR + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + '\x9e' # 0x3E -> + '\x1a' # 0x3F -> SUBSTITUTE + ' ' # 0x40 -> SPACE + '\u05d0' # 0x41 -> HEBREW LETTER ALEF + '\u05d1' # 0x42 -> HEBREW LETTER BET + '\u05d2' # 0x43 -> HEBREW LETTER GIMEL + '\u05d3' # 0x44 -> HEBREW LETTER DALET + '\u05d4' # 0x45 -> HEBREW LETTER HE + '\u05d5' # 0x46 -> HEBREW LETTER VAV + '\u05d6' # 0x47 -> HEBREW LETTER ZAYIN + '\u05d7' # 0x48 -> HEBREW LETTER HET + '\u05d8' # 0x49 -> HEBREW LETTER TET + '\xa2' # 0x4A -> CENT SIGN + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '|' # 0x4F -> VERTICAL LINE + '&' # 0x50 -> AMPERSAND + '\u05d9' # 0x51 -> HEBREW LETTER YOD + '\u05da' # 0x52 -> HEBREW LETTER FINAL KAF + '\u05db' # 0x53 -> HEBREW LETTER KAF + '\u05dc' # 0x54 -> HEBREW LETTER LAMED + '\u05dd' # 0x55 -> HEBREW LETTER FINAL MEM + '\u05de' # 0x56 -> HEBREW LETTER MEM + '\u05df' # 0x57 -> HEBREW LETTER FINAL NUN + '\u05e0' # 0x58 -> HEBREW LETTER NUN + '\u05e1' # 0x59 -> HEBREW LETTER SAMEKH + '!' # 0x5A -> EXCLAMATION MARK + '$' # 0x5B -> DOLLAR SIGN + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '\xac' # 0x5F -> NOT SIGN + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\u05e2' # 0x62 -> HEBREW LETTER AYIN + '\u05e3' # 0x63 -> HEBREW LETTER FINAL PE + '\u05e4' # 0x64 -> HEBREW LETTER PE + '\u05e5' # 0x65 -> HEBREW LETTER FINAL TSADI + '\u05e6' # 0x66 -> HEBREW LETTER TSADI + '\u05e7' # 0x67 -> HEBREW LETTER QOF + '\u05e8' # 0x68 -> HEBREW LETTER RESH + '\u05e9' # 0x69 -> HEBREW LETTER SHIN + '\xa6' # 0x6A -> BROKEN BAR + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\ufffe' # 0x70 -> UNDEFINED + '\u05ea' # 0x71 -> HEBREW LETTER TAV + '\ufffe' # 0x72 -> UNDEFINED + '\ufffe' # 0x73 -> UNDEFINED + '\xa0' # 0x74 -> NO-BREAK SPACE + '\ufffe' # 0x75 -> UNDEFINED + '\ufffe' # 0x76 -> UNDEFINED + '\ufffe' # 0x77 -> UNDEFINED + '\u2017' # 0x78 -> DOUBLE LOW LINE + '`' # 0x79 -> GRAVE ACCENT + ':' # 0x7A -> COLON + '#' # 0x7B -> NUMBER SIGN + '@' # 0x7C -> COMMERCIAL AT + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '"' # 0x7F -> QUOTATION MARK + '\ufffe' # 0x80 -> UNDEFINED + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\ufffe' # 0x8C -> UNDEFINED + '\ufffe' # 0x8D -> UNDEFINED + '\ufffe' # 0x8E -> UNDEFINED + '\xb1' # 0x8F -> PLUS-MINUS SIGN + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\ufffe' # 0x9A -> UNDEFINED + '\ufffe' # 0x9B -> UNDEFINED + '\ufffe' # 0x9C -> UNDEFINED + '\xb8' # 0x9D -> CEDILLA + '\ufffe' # 0x9E -> UNDEFINED + '\xa4' # 0x9F -> CURRENCY SIGN + '\xb5' # 0xA0 -> MICRO SIGN + '~' # 0xA1 -> TILDE + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\ufffe' # 0xAA -> UNDEFINED + '\ufffe' # 0xAB -> UNDEFINED + '\ufffe' # 0xAC -> UNDEFINED + '\ufffe' # 0xAD -> UNDEFINED + '\ufffe' # 0xAE -> UNDEFINED + '\xae' # 0xAF -> REGISTERED SIGN + '^' # 0xB0 -> CIRCUMFLEX ACCENT + '\xa3' # 0xB1 -> POUND SIGN + '\xa5' # 0xB2 -> YEN SIGN + '\xb7' # 0xB3 -> MIDDLE DOT + '\xa9' # 0xB4 -> COPYRIGHT SIGN + '\xa7' # 0xB5 -> SECTION SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + '\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + '[' # 0xBA -> LEFT SQUARE BRACKET + ']' # 0xBB -> RIGHT SQUARE BRACKET + '\xaf' # 0xBC -> MACRON + '\xa8' # 0xBD -> DIAERESIS + '\xb4' # 0xBE -> ACUTE ACCENT + '\xd7' # 0xBF -> MULTIPLICATION SIGN + '{' # 0xC0 -> LEFT CURLY BRACKET + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\ufffe' # 0xCB -> UNDEFINED + '\ufffe' # 0xCC -> UNDEFINED + '\ufffe' # 0xCD -> UNDEFINED + '\ufffe' # 0xCE -> UNDEFINED + '\ufffe' # 0xCF -> UNDEFINED + '}' # 0xD0 -> RIGHT CURLY BRACKET + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb9' # 0xDA -> SUPERSCRIPT ONE + '\ufffe' # 0xDB -> UNDEFINED + '\ufffe' # 0xDC -> UNDEFINED + '\ufffe' # 0xDD -> UNDEFINED + '\ufffe' # 0xDE -> UNDEFINED + '\ufffe' # 0xDF -> UNDEFINED + '\\' # 0xE0 -> REVERSE SOLIDUS + '\xf7' # 0xE1 -> DIVISION SIGN + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\ufffe' # 0xEB -> UNDEFINED + '\ufffe' # 0xEC -> UNDEFINED + '\ufffe' # 0xED -> UNDEFINED + '\ufffe' # 0xEE -> UNDEFINED + '\ufffe' # 0xEF -> UNDEFINED + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\ufffe' # 0xFB -> UNDEFINED + '\ufffe' # 0xFC -> UNDEFINED + '\ufffe' # 0xFD -> UNDEFINED + '\ufffe' # 0xFE -> UNDEFINED + '\x9f' # 0xFF -> EIGHT ONES +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp437.py b/winvenv/Lib/encodings/cp437.py new file mode 100644 index 0000000..b6c75e2 --- /dev/null +++ b/winvenv/Lib/encodings/cp437.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec cp437 generated from 'VENDORS/MICSFT/PC/CP437.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp437', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00a2, # CENT SIGN + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00a5, # YEN SIGN + 0x009e: 0x20a7, # PESETA SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x2310, # REVERSED NOT SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xa2' # 0x009b -> CENT SIGN + '\xa3' # 0x009c -> POUND SIGN + '\xa5' # 0x009d -> YEN SIGN + '\u20a7' # 0x009e -> PESETA SIGN + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + '\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\u2310' # 0x00a9 -> REVERSED NOT SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + '\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + '\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + '\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + '\xb5' # 0x00e6 -> MICRO SIGN + '\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + '\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + '\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + '\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + '\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + '\u221e' # 0x00ec -> INFINITY + '\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + '\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + '\u2229' # 0x00ef -> INTERSECTION + '\u2261' # 0x00f0 -> IDENTICAL TO + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u2320' # 0x00f4 -> TOP HALF INTEGRAL + '\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a5: 0x009d, # YEN SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp500.py b/winvenv/Lib/encodings/cp500.py new file mode 100644 index 0000000..5f61535 --- /dev/null +++ b/winvenv/Lib/encodings/cp500.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp500 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP500.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp500', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x9c' # 0x04 -> CONTROL + '\t' # 0x05 -> HORIZONTAL TABULATION + '\x86' # 0x06 -> CONTROL + '\x7f' # 0x07 -> DELETE + '\x97' # 0x08 -> CONTROL + '\x8d' # 0x09 -> CONTROL + '\x8e' # 0x0A -> CONTROL + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x9d' # 0x14 -> CONTROL + '\x85' # 0x15 -> CONTROL + '\x08' # 0x16 -> BACKSPACE + '\x87' # 0x17 -> CONTROL + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x92' # 0x1A -> CONTROL + '\x8f' # 0x1B -> CONTROL + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + '\x80' # 0x20 -> CONTROL + '\x81' # 0x21 -> CONTROL + '\x82' # 0x22 -> CONTROL + '\x83' # 0x23 -> CONTROL + '\x84' # 0x24 -> CONTROL + '\n' # 0x25 -> LINE FEED + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK + '\x1b' # 0x27 -> ESCAPE + '\x88' # 0x28 -> CONTROL + '\x89' # 0x29 -> CONTROL + '\x8a' # 0x2A -> CONTROL + '\x8b' # 0x2B -> CONTROL + '\x8c' # 0x2C -> CONTROL + '\x05' # 0x2D -> ENQUIRY + '\x06' # 0x2E -> ACKNOWLEDGE + '\x07' # 0x2F -> BELL + '\x90' # 0x30 -> CONTROL + '\x91' # 0x31 -> CONTROL + '\x16' # 0x32 -> SYNCHRONOUS IDLE + '\x93' # 0x33 -> CONTROL + '\x94' # 0x34 -> CONTROL + '\x95' # 0x35 -> CONTROL + '\x96' # 0x36 -> CONTROL + '\x04' # 0x37 -> END OF TRANSMISSION + '\x98' # 0x38 -> CONTROL + '\x99' # 0x39 -> CONTROL + '\x9a' # 0x3A -> CONTROL + '\x9b' # 0x3B -> CONTROL + '\x14' # 0x3C -> DEVICE CONTROL FOUR + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + '\x9e' # 0x3E -> CONTROL + '\x1a' # 0x3F -> SUBSTITUTE + ' ' # 0x40 -> SPACE + '\xa0' # 0x41 -> NO-BREAK SPACE + '\xe2' # 0x42 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x43 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x44 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0x45 -> LATIN SMALL LETTER A WITH ACUTE + '\xe3' # 0x46 -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x47 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x48 -> LATIN SMALL LETTER C WITH CEDILLA + '\xf1' # 0x49 -> LATIN SMALL LETTER N WITH TILDE + '[' # 0x4A -> LEFT SQUARE BRACKET + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '!' # 0x4F -> EXCLAMATION MARK + '&' # 0x50 -> AMPERSAND + '\xe9' # 0x51 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0x52 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x53 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x54 -> LATIN SMALL LETTER E WITH GRAVE + '\xed' # 0x55 -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0x56 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x57 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xec' # 0x58 -> LATIN SMALL LETTER I WITH GRAVE + '\xdf' # 0x59 -> LATIN SMALL LETTER SHARP S (GERMAN) + ']' # 0x5A -> RIGHT SQUARE BRACKET + '$' # 0x5B -> DOLLAR SIGN + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '^' # 0x5F -> CIRCUMFLEX ACCENT + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\xc2' # 0x62 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc4' # 0x63 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc0' # 0x64 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0x65 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc3' # 0x66 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc5' # 0x67 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x68 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xd1' # 0x69 -> LATIN CAPITAL LETTER N WITH TILDE + '\xa6' # 0x6A -> BROKEN BAR + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\xf8' # 0x70 -> LATIN SMALL LETTER O WITH STROKE + '\xc9' # 0x71 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0x72 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x73 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x74 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0x75 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x76 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x77 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0x78 -> LATIN CAPITAL LETTER I WITH GRAVE + '`' # 0x79 -> GRAVE ACCENT + ':' # 0x7A -> COLON + '#' # 0x7B -> NUMBER SIGN + '@' # 0x7C -> COMMERCIAL AT + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '"' # 0x7F -> QUOTATION MARK + '\xd8' # 0x80 -> LATIN CAPITAL LETTER O WITH STROKE + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\xab' # 0x8A -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x8B -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xf0' # 0x8C -> LATIN SMALL LETTER ETH (ICELANDIC) + '\xfd' # 0x8D -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0x8E -> LATIN SMALL LETTER THORN (ICELANDIC) + '\xb1' # 0x8F -> PLUS-MINUS SIGN + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\xaa' # 0x9A -> FEMININE ORDINAL INDICATOR + '\xba' # 0x9B -> MASCULINE ORDINAL INDICATOR + '\xe6' # 0x9C -> LATIN SMALL LIGATURE AE + '\xb8' # 0x9D -> CEDILLA + '\xc6' # 0x9E -> LATIN CAPITAL LIGATURE AE + '\xa4' # 0x9F -> CURRENCY SIGN + '\xb5' # 0xA0 -> MICRO SIGN + '~' # 0xA1 -> TILDE + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\xa1' # 0xAA -> INVERTED EXCLAMATION MARK + '\xbf' # 0xAB -> INVERTED QUESTION MARK + '\xd0' # 0xAC -> LATIN CAPITAL LETTER ETH (ICELANDIC) + '\xdd' # 0xAD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xAE -> LATIN CAPITAL LETTER THORN (ICELANDIC) + '\xae' # 0xAF -> REGISTERED SIGN + '\xa2' # 0xB0 -> CENT SIGN + '\xa3' # 0xB1 -> POUND SIGN + '\xa5' # 0xB2 -> YEN SIGN + '\xb7' # 0xB3 -> MIDDLE DOT + '\xa9' # 0xB4 -> COPYRIGHT SIGN + '\xa7' # 0xB5 -> SECTION SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xbc' # 0xB7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xB8 -> VULGAR FRACTION ONE HALF + '\xbe' # 0xB9 -> VULGAR FRACTION THREE QUARTERS + '\xac' # 0xBA -> NOT SIGN + '|' # 0xBB -> VERTICAL LINE + '\xaf' # 0xBC -> MACRON + '\xa8' # 0xBD -> DIAERESIS + '\xb4' # 0xBE -> ACUTE ACCENT + '\xd7' # 0xBF -> MULTIPLICATION SIGN + '{' # 0xC0 -> LEFT CURLY BRACKET + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\xf4' # 0xCB -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0xCC -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0xCD -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xCE -> LATIN SMALL LETTER O WITH ACUTE + '\xf5' # 0xCF -> LATIN SMALL LETTER O WITH TILDE + '}' # 0xD0 -> RIGHT CURLY BRACKET + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb9' # 0xDA -> SUPERSCRIPT ONE + '\xfb' # 0xDB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xDC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xf9' # 0xDD -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xDE -> LATIN SMALL LETTER U WITH ACUTE + '\xff' # 0xDF -> LATIN SMALL LETTER Y WITH DIAERESIS + '\\' # 0xE0 -> REVERSE SOLIDUS + '\xf7' # 0xE1 -> DIVISION SIGN + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\xd4' # 0xEB -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd6' # 0xEC -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd2' # 0xED -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd5' # 0xEF -> LATIN CAPITAL LETTER O WITH TILDE + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\xdb' # 0xFB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xFC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xd9' # 0xFD -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xFE -> LATIN CAPITAL LETTER U WITH ACUTE + '\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp65001.py b/winvenv/Lib/encodings/cp65001.py new file mode 100644 index 0000000..95cb2ae --- /dev/null +++ b/winvenv/Lib/encodings/cp65001.py @@ -0,0 +1,43 @@ +""" +Code page 65001: Windows UTF-8 (CP_UTF8). +""" + +import codecs +import functools + +if not hasattr(codecs, 'code_page_encode'): + raise LookupError("cp65001 encoding is only available on Windows") + +### Codec APIs + +encode = functools.partial(codecs.code_page_encode, 65001) +_decode = functools.partial(codecs.code_page_decode, 65001) + +def decode(input, errors='strict'): + return codecs.code_page_decode(65001, input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = _decode + +class StreamWriter(codecs.StreamWriter): + encode = encode + +class StreamReader(codecs.StreamReader): + decode = _decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp65001', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/cp720.py b/winvenv/Lib/encodings/cp720.py new file mode 100644 index 0000000..96d6096 --- /dev/null +++ b/winvenv/Lib/encodings/cp720.py @@ -0,0 +1,309 @@ +"""Python Character Mapping Codec cp720 generated on Windows: +Vista 6.0.6002 SP2 Multiprocessor Free with the command: + python Tools/unicode/genwincodec.py 720 +"""#" + + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp720', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\x80' + '\x81' + '\xe9' # 0x82 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x83 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\x84' + '\xe0' # 0x85 -> LATIN SMALL LETTER A WITH GRAVE + '\x86' + '\xe7' # 0x87 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x88 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x89 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x8A -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x8B -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x8C -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\x8d' + '\x8e' + '\x8f' + '\x90' + '\u0651' # 0x91 -> ARABIC SHADDA + '\u0652' # 0x92 -> ARABIC SUKUN + '\xf4' # 0x93 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xa4' # 0x94 -> CURRENCY SIGN + '\u0640' # 0x95 -> ARABIC TATWEEL + '\xfb' # 0x96 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x97 -> LATIN SMALL LETTER U WITH GRAVE + '\u0621' # 0x98 -> ARABIC LETTER HAMZA + '\u0622' # 0x99 -> ARABIC LETTER ALEF WITH MADDA ABOVE + '\u0623' # 0x9A -> ARABIC LETTER ALEF WITH HAMZA ABOVE + '\u0624' # 0x9B -> ARABIC LETTER WAW WITH HAMZA ABOVE + '\xa3' # 0x9C -> POUND SIGN + '\u0625' # 0x9D -> ARABIC LETTER ALEF WITH HAMZA BELOW + '\u0626' # 0x9E -> ARABIC LETTER YEH WITH HAMZA ABOVE + '\u0627' # 0x9F -> ARABIC LETTER ALEF + '\u0628' # 0xA0 -> ARABIC LETTER BEH + '\u0629' # 0xA1 -> ARABIC LETTER TEH MARBUTA + '\u062a' # 0xA2 -> ARABIC LETTER TEH + '\u062b' # 0xA3 -> ARABIC LETTER THEH + '\u062c' # 0xA4 -> ARABIC LETTER JEEM + '\u062d' # 0xA5 -> ARABIC LETTER HAH + '\u062e' # 0xA6 -> ARABIC LETTER KHAH + '\u062f' # 0xA7 -> ARABIC LETTER DAL + '\u0630' # 0xA8 -> ARABIC LETTER THAL + '\u0631' # 0xA9 -> ARABIC LETTER REH + '\u0632' # 0xAA -> ARABIC LETTER ZAIN + '\u0633' # 0xAB -> ARABIC LETTER SEEN + '\u0634' # 0xAC -> ARABIC LETTER SHEEN + '\u0635' # 0xAD -> ARABIC LETTER SAD + '\xab' # 0xAE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xAF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0xB0 -> LIGHT SHADE + '\u2592' # 0xB1 -> MEDIUM SHADE + '\u2593' # 0xB2 -> DARK SHADE + '\u2502' # 0xB3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0xB4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0xB5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0xB6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0xB7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0xB8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0xB9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0xBA -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0xBB -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0xBC -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0xBD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0xBE -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0xBF -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0xC0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0xC1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0xC2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0xC3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0xC5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0xC6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0xC7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0xC8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0xC9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0xCA -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0xCB -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0xCC -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0xCD -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0xCE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0xCF -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0xD0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0xD1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0xD2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0xD3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0xD4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0xD5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0xD6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0xD7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0xD8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0xD9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0xDA -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0xDB -> FULL BLOCK + '\u2584' # 0xDC -> LOWER HALF BLOCK + '\u258c' # 0xDD -> LEFT HALF BLOCK + '\u2590' # 0xDE -> RIGHT HALF BLOCK + '\u2580' # 0xDF -> UPPER HALF BLOCK + '\u0636' # 0xE0 -> ARABIC LETTER DAD + '\u0637' # 0xE1 -> ARABIC LETTER TAH + '\u0638' # 0xE2 -> ARABIC LETTER ZAH + '\u0639' # 0xE3 -> ARABIC LETTER AIN + '\u063a' # 0xE4 -> ARABIC LETTER GHAIN + '\u0641' # 0xE5 -> ARABIC LETTER FEH + '\xb5' # 0xE6 -> MICRO SIGN + '\u0642' # 0xE7 -> ARABIC LETTER QAF + '\u0643' # 0xE8 -> ARABIC LETTER KAF + '\u0644' # 0xE9 -> ARABIC LETTER LAM + '\u0645' # 0xEA -> ARABIC LETTER MEEM + '\u0646' # 0xEB -> ARABIC LETTER NOON + '\u0647' # 0xEC -> ARABIC LETTER HEH + '\u0648' # 0xED -> ARABIC LETTER WAW + '\u0649' # 0xEE -> ARABIC LETTER ALEF MAKSURA + '\u064a' # 0xEF -> ARABIC LETTER YEH + '\u2261' # 0xF0 -> IDENTICAL TO + '\u064b' # 0xF1 -> ARABIC FATHATAN + '\u064c' # 0xF2 -> ARABIC DAMMATAN + '\u064d' # 0xF3 -> ARABIC KASRATAN + '\u064e' # 0xF4 -> ARABIC FATHA + '\u064f' # 0xF5 -> ARABIC DAMMA + '\u0650' # 0xF6 -> ARABIC KASRA + '\u2248' # 0xF7 -> ALMOST EQUAL TO + '\xb0' # 0xF8 -> DEGREE SIGN + '\u2219' # 0xF9 -> BULLET OPERATOR + '\xb7' # 0xFA -> MIDDLE DOT + '\u221a' # 0xFB -> SQUARE ROOT + '\u207f' # 0xFC -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0xFD -> SUPERSCRIPT TWO + '\u25a0' # 0xFE -> BLACK SQUARE + '\xa0' # 0xFF -> NO-BREAK SPACE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp737.py b/winvenv/Lib/encodings/cp737.py new file mode 100644 index 0000000..9685bae --- /dev/null +++ b/winvenv/Lib/encodings/cp737.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec cp737 generated from 'VENDORS/MICSFT/PC/CP737.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp737', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x0391, # GREEK CAPITAL LETTER ALPHA + 0x0081: 0x0392, # GREEK CAPITAL LETTER BETA + 0x0082: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x0083: 0x0394, # GREEK CAPITAL LETTER DELTA + 0x0084: 0x0395, # GREEK CAPITAL LETTER EPSILON + 0x0085: 0x0396, # GREEK CAPITAL LETTER ZETA + 0x0086: 0x0397, # GREEK CAPITAL LETTER ETA + 0x0087: 0x0398, # GREEK CAPITAL LETTER THETA + 0x0088: 0x0399, # GREEK CAPITAL LETTER IOTA + 0x0089: 0x039a, # GREEK CAPITAL LETTER KAPPA + 0x008a: 0x039b, # GREEK CAPITAL LETTER LAMDA + 0x008b: 0x039c, # GREEK CAPITAL LETTER MU + 0x008c: 0x039d, # GREEK CAPITAL LETTER NU + 0x008d: 0x039e, # GREEK CAPITAL LETTER XI + 0x008e: 0x039f, # GREEK CAPITAL LETTER OMICRON + 0x008f: 0x03a0, # GREEK CAPITAL LETTER PI + 0x0090: 0x03a1, # GREEK CAPITAL LETTER RHO + 0x0091: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x0092: 0x03a4, # GREEK CAPITAL LETTER TAU + 0x0093: 0x03a5, # GREEK CAPITAL LETTER UPSILON + 0x0094: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x0095: 0x03a7, # GREEK CAPITAL LETTER CHI + 0x0096: 0x03a8, # GREEK CAPITAL LETTER PSI + 0x0097: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x0098: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x0099: 0x03b2, # GREEK SMALL LETTER BETA + 0x009a: 0x03b3, # GREEK SMALL LETTER GAMMA + 0x009b: 0x03b4, # GREEK SMALL LETTER DELTA + 0x009c: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x009d: 0x03b6, # GREEK SMALL LETTER ZETA + 0x009e: 0x03b7, # GREEK SMALL LETTER ETA + 0x009f: 0x03b8, # GREEK SMALL LETTER THETA + 0x00a0: 0x03b9, # GREEK SMALL LETTER IOTA + 0x00a1: 0x03ba, # GREEK SMALL LETTER KAPPA + 0x00a2: 0x03bb, # GREEK SMALL LETTER LAMDA + 0x00a3: 0x03bc, # GREEK SMALL LETTER MU + 0x00a4: 0x03bd, # GREEK SMALL LETTER NU + 0x00a5: 0x03be, # GREEK SMALL LETTER XI + 0x00a6: 0x03bf, # GREEK SMALL LETTER OMICRON + 0x00a7: 0x03c0, # GREEK SMALL LETTER PI + 0x00a8: 0x03c1, # GREEK SMALL LETTER RHO + 0x00a9: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00aa: 0x03c2, # GREEK SMALL LETTER FINAL SIGMA + 0x00ab: 0x03c4, # GREEK SMALL LETTER TAU + 0x00ac: 0x03c5, # GREEK SMALL LETTER UPSILON + 0x00ad: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ae: 0x03c7, # GREEK SMALL LETTER CHI + 0x00af: 0x03c8, # GREEK SMALL LETTER PSI + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03c9, # GREEK SMALL LETTER OMEGA + 0x00e1: 0x03ac, # GREEK SMALL LETTER ALPHA WITH TONOS + 0x00e2: 0x03ad, # GREEK SMALL LETTER EPSILON WITH TONOS + 0x00e3: 0x03ae, # GREEK SMALL LETTER ETA WITH TONOS + 0x00e4: 0x03ca, # GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x00e5: 0x03af, # GREEK SMALL LETTER IOTA WITH TONOS + 0x00e6: 0x03cc, # GREEK SMALL LETTER OMICRON WITH TONOS + 0x00e7: 0x03cd, # GREEK SMALL LETTER UPSILON WITH TONOS + 0x00e8: 0x03cb, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x00e9: 0x03ce, # GREEK SMALL LETTER OMEGA WITH TONOS + 0x00ea: 0x0386, # GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x00eb: 0x0388, # GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x00ec: 0x0389, # GREEK CAPITAL LETTER ETA WITH TONOS + 0x00ed: 0x038a, # GREEK CAPITAL LETTER IOTA WITH TONOS + 0x00ee: 0x038c, # GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x00ef: 0x038e, # GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x00f0: 0x038f, # GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x03aa, # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x00f5: 0x03ab, # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\u0391' # 0x0080 -> GREEK CAPITAL LETTER ALPHA + '\u0392' # 0x0081 -> GREEK CAPITAL LETTER BETA + '\u0393' # 0x0082 -> GREEK CAPITAL LETTER GAMMA + '\u0394' # 0x0083 -> GREEK CAPITAL LETTER DELTA + '\u0395' # 0x0084 -> GREEK CAPITAL LETTER EPSILON + '\u0396' # 0x0085 -> GREEK CAPITAL LETTER ZETA + '\u0397' # 0x0086 -> GREEK CAPITAL LETTER ETA + '\u0398' # 0x0087 -> GREEK CAPITAL LETTER THETA + '\u0399' # 0x0088 -> GREEK CAPITAL LETTER IOTA + '\u039a' # 0x0089 -> GREEK CAPITAL LETTER KAPPA + '\u039b' # 0x008a -> GREEK CAPITAL LETTER LAMDA + '\u039c' # 0x008b -> GREEK CAPITAL LETTER MU + '\u039d' # 0x008c -> GREEK CAPITAL LETTER NU + '\u039e' # 0x008d -> GREEK CAPITAL LETTER XI + '\u039f' # 0x008e -> GREEK CAPITAL LETTER OMICRON + '\u03a0' # 0x008f -> GREEK CAPITAL LETTER PI + '\u03a1' # 0x0090 -> GREEK CAPITAL LETTER RHO + '\u03a3' # 0x0091 -> GREEK CAPITAL LETTER SIGMA + '\u03a4' # 0x0092 -> GREEK CAPITAL LETTER TAU + '\u03a5' # 0x0093 -> GREEK CAPITAL LETTER UPSILON + '\u03a6' # 0x0094 -> GREEK CAPITAL LETTER PHI + '\u03a7' # 0x0095 -> GREEK CAPITAL LETTER CHI + '\u03a8' # 0x0096 -> GREEK CAPITAL LETTER PSI + '\u03a9' # 0x0097 -> GREEK CAPITAL LETTER OMEGA + '\u03b1' # 0x0098 -> GREEK SMALL LETTER ALPHA + '\u03b2' # 0x0099 -> GREEK SMALL LETTER BETA + '\u03b3' # 0x009a -> GREEK SMALL LETTER GAMMA + '\u03b4' # 0x009b -> GREEK SMALL LETTER DELTA + '\u03b5' # 0x009c -> GREEK SMALL LETTER EPSILON + '\u03b6' # 0x009d -> GREEK SMALL LETTER ZETA + '\u03b7' # 0x009e -> GREEK SMALL LETTER ETA + '\u03b8' # 0x009f -> GREEK SMALL LETTER THETA + '\u03b9' # 0x00a0 -> GREEK SMALL LETTER IOTA + '\u03ba' # 0x00a1 -> GREEK SMALL LETTER KAPPA + '\u03bb' # 0x00a2 -> GREEK SMALL LETTER LAMDA + '\u03bc' # 0x00a3 -> GREEK SMALL LETTER MU + '\u03bd' # 0x00a4 -> GREEK SMALL LETTER NU + '\u03be' # 0x00a5 -> GREEK SMALL LETTER XI + '\u03bf' # 0x00a6 -> GREEK SMALL LETTER OMICRON + '\u03c0' # 0x00a7 -> GREEK SMALL LETTER PI + '\u03c1' # 0x00a8 -> GREEK SMALL LETTER RHO + '\u03c3' # 0x00a9 -> GREEK SMALL LETTER SIGMA + '\u03c2' # 0x00aa -> GREEK SMALL LETTER FINAL SIGMA + '\u03c4' # 0x00ab -> GREEK SMALL LETTER TAU + '\u03c5' # 0x00ac -> GREEK SMALL LETTER UPSILON + '\u03c6' # 0x00ad -> GREEK SMALL LETTER PHI + '\u03c7' # 0x00ae -> GREEK SMALL LETTER CHI + '\u03c8' # 0x00af -> GREEK SMALL LETTER PSI + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03c9' # 0x00e0 -> GREEK SMALL LETTER OMEGA + '\u03ac' # 0x00e1 -> GREEK SMALL LETTER ALPHA WITH TONOS + '\u03ad' # 0x00e2 -> GREEK SMALL LETTER EPSILON WITH TONOS + '\u03ae' # 0x00e3 -> GREEK SMALL LETTER ETA WITH TONOS + '\u03ca' # 0x00e4 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + '\u03af' # 0x00e5 -> GREEK SMALL LETTER IOTA WITH TONOS + '\u03cc' # 0x00e6 -> GREEK SMALL LETTER OMICRON WITH TONOS + '\u03cd' # 0x00e7 -> GREEK SMALL LETTER UPSILON WITH TONOS + '\u03cb' # 0x00e8 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + '\u03ce' # 0x00e9 -> GREEK SMALL LETTER OMEGA WITH TONOS + '\u0386' # 0x00ea -> GREEK CAPITAL LETTER ALPHA WITH TONOS + '\u0388' # 0x00eb -> GREEK CAPITAL LETTER EPSILON WITH TONOS + '\u0389' # 0x00ec -> GREEK CAPITAL LETTER ETA WITH TONOS + '\u038a' # 0x00ed -> GREEK CAPITAL LETTER IOTA WITH TONOS + '\u038c' # 0x00ee -> GREEK CAPITAL LETTER OMICRON WITH TONOS + '\u038e' # 0x00ef -> GREEK CAPITAL LETTER UPSILON WITH TONOS + '\u038f' # 0x00f0 -> GREEK CAPITAL LETTER OMEGA WITH TONOS + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u03aa' # 0x00f4 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + '\u03ab' # 0x00f5 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00f7: 0x00f6, # DIVISION SIGN + 0x0386: 0x00ea, # GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x0388: 0x00eb, # GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x0389: 0x00ec, # GREEK CAPITAL LETTER ETA WITH TONOS + 0x038a: 0x00ed, # GREEK CAPITAL LETTER IOTA WITH TONOS + 0x038c: 0x00ee, # GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x038e: 0x00ef, # GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x038f: 0x00f0, # GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x0391: 0x0080, # GREEK CAPITAL LETTER ALPHA + 0x0392: 0x0081, # GREEK CAPITAL LETTER BETA + 0x0393: 0x0082, # GREEK CAPITAL LETTER GAMMA + 0x0394: 0x0083, # GREEK CAPITAL LETTER DELTA + 0x0395: 0x0084, # GREEK CAPITAL LETTER EPSILON + 0x0396: 0x0085, # GREEK CAPITAL LETTER ZETA + 0x0397: 0x0086, # GREEK CAPITAL LETTER ETA + 0x0398: 0x0087, # GREEK CAPITAL LETTER THETA + 0x0399: 0x0088, # GREEK CAPITAL LETTER IOTA + 0x039a: 0x0089, # GREEK CAPITAL LETTER KAPPA + 0x039b: 0x008a, # GREEK CAPITAL LETTER LAMDA + 0x039c: 0x008b, # GREEK CAPITAL LETTER MU + 0x039d: 0x008c, # GREEK CAPITAL LETTER NU + 0x039e: 0x008d, # GREEK CAPITAL LETTER XI + 0x039f: 0x008e, # GREEK CAPITAL LETTER OMICRON + 0x03a0: 0x008f, # GREEK CAPITAL LETTER PI + 0x03a1: 0x0090, # GREEK CAPITAL LETTER RHO + 0x03a3: 0x0091, # GREEK CAPITAL LETTER SIGMA + 0x03a4: 0x0092, # GREEK CAPITAL LETTER TAU + 0x03a5: 0x0093, # GREEK CAPITAL LETTER UPSILON + 0x03a6: 0x0094, # GREEK CAPITAL LETTER PHI + 0x03a7: 0x0095, # GREEK CAPITAL LETTER CHI + 0x03a8: 0x0096, # GREEK CAPITAL LETTER PSI + 0x03a9: 0x0097, # GREEK CAPITAL LETTER OMEGA + 0x03aa: 0x00f4, # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x03ab: 0x00f5, # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x03ac: 0x00e1, # GREEK SMALL LETTER ALPHA WITH TONOS + 0x03ad: 0x00e2, # GREEK SMALL LETTER EPSILON WITH TONOS + 0x03ae: 0x00e3, # GREEK SMALL LETTER ETA WITH TONOS + 0x03af: 0x00e5, # GREEK SMALL LETTER IOTA WITH TONOS + 0x03b1: 0x0098, # GREEK SMALL LETTER ALPHA + 0x03b2: 0x0099, # GREEK SMALL LETTER BETA + 0x03b3: 0x009a, # GREEK SMALL LETTER GAMMA + 0x03b4: 0x009b, # GREEK SMALL LETTER DELTA + 0x03b5: 0x009c, # GREEK SMALL LETTER EPSILON + 0x03b6: 0x009d, # GREEK SMALL LETTER ZETA + 0x03b7: 0x009e, # GREEK SMALL LETTER ETA + 0x03b8: 0x009f, # GREEK SMALL LETTER THETA + 0x03b9: 0x00a0, # GREEK SMALL LETTER IOTA + 0x03ba: 0x00a1, # GREEK SMALL LETTER KAPPA + 0x03bb: 0x00a2, # GREEK SMALL LETTER LAMDA + 0x03bc: 0x00a3, # GREEK SMALL LETTER MU + 0x03bd: 0x00a4, # GREEK SMALL LETTER NU + 0x03be: 0x00a5, # GREEK SMALL LETTER XI + 0x03bf: 0x00a6, # GREEK SMALL LETTER OMICRON + 0x03c0: 0x00a7, # GREEK SMALL LETTER PI + 0x03c1: 0x00a8, # GREEK SMALL LETTER RHO + 0x03c2: 0x00aa, # GREEK SMALL LETTER FINAL SIGMA + 0x03c3: 0x00a9, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00ab, # GREEK SMALL LETTER TAU + 0x03c5: 0x00ac, # GREEK SMALL LETTER UPSILON + 0x03c6: 0x00ad, # GREEK SMALL LETTER PHI + 0x03c7: 0x00ae, # GREEK SMALL LETTER CHI + 0x03c8: 0x00af, # GREEK SMALL LETTER PSI + 0x03c9: 0x00e0, # GREEK SMALL LETTER OMEGA + 0x03ca: 0x00e4, # GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x03cb: 0x00e8, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x03cc: 0x00e6, # GREEK SMALL LETTER OMICRON WITH TONOS + 0x03cd: 0x00e7, # GREEK SMALL LETTER UPSILON WITH TONOS + 0x03ce: 0x00e9, # GREEK SMALL LETTER OMEGA WITH TONOS + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp775.py b/winvenv/Lib/encodings/cp775.py new file mode 100644 index 0000000..fe06e7b --- /dev/null +++ b/winvenv/Lib/encodings/cp775.py @@ -0,0 +1,697 @@ +""" Python Character Mapping Codec cp775 generated from 'VENDORS/MICSFT/PC/CP775.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp775', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x0106, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x0101, # LATIN SMALL LETTER A WITH MACRON + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x0123, # LATIN SMALL LETTER G WITH CEDILLA + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x0107, # LATIN SMALL LETTER C WITH ACUTE + 0x0088: 0x0142, # LATIN SMALL LETTER L WITH STROKE + 0x0089: 0x0113, # LATIN SMALL LETTER E WITH MACRON + 0x008a: 0x0156, # LATIN CAPITAL LETTER R WITH CEDILLA + 0x008b: 0x0157, # LATIN SMALL LETTER R WITH CEDILLA + 0x008c: 0x012b, # LATIN SMALL LETTER I WITH MACRON + 0x008d: 0x0179, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x014d, # LATIN SMALL LETTER O WITH MACRON + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x0122, # LATIN CAPITAL LETTER G WITH CEDILLA + 0x0096: 0x00a2, # CENT SIGN + 0x0097: 0x015a, # LATIN CAPITAL LETTER S WITH ACUTE + 0x0098: 0x015b, # LATIN SMALL LETTER S WITH ACUTE + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x00d7, # MULTIPLICATION SIGN + 0x009f: 0x00a4, # CURRENCY SIGN + 0x00a0: 0x0100, # LATIN CAPITAL LETTER A WITH MACRON + 0x00a1: 0x012a, # LATIN CAPITAL LETTER I WITH MACRON + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x017b, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x00a4: 0x017c, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x00a5: 0x017a, # LATIN SMALL LETTER Z WITH ACUTE + 0x00a6: 0x201d, # RIGHT DOUBLE QUOTATION MARK + 0x00a7: 0x00a6, # BROKEN BAR + 0x00a8: 0x00a9, # COPYRIGHT SIGN + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x0141, # LATIN CAPITAL LETTER L WITH STROKE + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x0104, # LATIN CAPITAL LETTER A WITH OGONEK + 0x00b6: 0x010c, # LATIN CAPITAL LETTER C WITH CARON + 0x00b7: 0x0118, # LATIN CAPITAL LETTER E WITH OGONEK + 0x00b8: 0x0116, # LATIN CAPITAL LETTER E WITH DOT ABOVE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x012e, # LATIN CAPITAL LETTER I WITH OGONEK + 0x00be: 0x0160, # LATIN CAPITAL LETTER S WITH CARON + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x0172, # LATIN CAPITAL LETTER U WITH OGONEK + 0x00c7: 0x016a, # LATIN CAPITAL LETTER U WITH MACRON + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x017d, # LATIN CAPITAL LETTER Z WITH CARON + 0x00d0: 0x0105, # LATIN SMALL LETTER A WITH OGONEK + 0x00d1: 0x010d, # LATIN SMALL LETTER C WITH CARON + 0x00d2: 0x0119, # LATIN SMALL LETTER E WITH OGONEK + 0x00d3: 0x0117, # LATIN SMALL LETTER E WITH DOT ABOVE + 0x00d4: 0x012f, # LATIN SMALL LETTER I WITH OGONEK + 0x00d5: 0x0161, # LATIN SMALL LETTER S WITH CARON + 0x00d6: 0x0173, # LATIN SMALL LETTER U WITH OGONEK + 0x00d7: 0x016b, # LATIN SMALL LETTER U WITH MACRON + 0x00d8: 0x017e, # LATIN SMALL LETTER Z WITH CARON + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e2: 0x014c, # LATIN CAPITAL LETTER O WITH MACRON + 0x00e3: 0x0143, # LATIN CAPITAL LETTER N WITH ACUTE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x0144, # LATIN SMALL LETTER N WITH ACUTE + 0x00e8: 0x0136, # LATIN CAPITAL LETTER K WITH CEDILLA + 0x00e9: 0x0137, # LATIN SMALL LETTER K WITH CEDILLA + 0x00ea: 0x013b, # LATIN CAPITAL LETTER L WITH CEDILLA + 0x00eb: 0x013c, # LATIN SMALL LETTER L WITH CEDILLA + 0x00ec: 0x0146, # LATIN SMALL LETTER N WITH CEDILLA + 0x00ed: 0x0112, # LATIN CAPITAL LETTER E WITH MACRON + 0x00ee: 0x0145, # LATIN CAPITAL LETTER N WITH CEDILLA + 0x00ef: 0x2019, # RIGHT SINGLE QUOTATION MARK + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x201c, # LEFT DOUBLE QUOTATION MARK + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x201e, # DOUBLE LOW-9 QUOTATION MARK + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\u0106' # 0x0080 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\u0101' # 0x0083 -> LATIN SMALL LETTER A WITH MACRON + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\u0123' # 0x0085 -> LATIN SMALL LETTER G WITH CEDILLA + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\u0107' # 0x0087 -> LATIN SMALL LETTER C WITH ACUTE + '\u0142' # 0x0088 -> LATIN SMALL LETTER L WITH STROKE + '\u0113' # 0x0089 -> LATIN SMALL LETTER E WITH MACRON + '\u0156' # 0x008a -> LATIN CAPITAL LETTER R WITH CEDILLA + '\u0157' # 0x008b -> LATIN SMALL LETTER R WITH CEDILLA + '\u012b' # 0x008c -> LATIN SMALL LETTER I WITH MACRON + '\u0179' # 0x008d -> LATIN CAPITAL LETTER Z WITH ACUTE + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\u014d' # 0x0093 -> LATIN SMALL LETTER O WITH MACRON + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\u0122' # 0x0095 -> LATIN CAPITAL LETTER G WITH CEDILLA + '\xa2' # 0x0096 -> CENT SIGN + '\u015a' # 0x0097 -> LATIN CAPITAL LETTER S WITH ACUTE + '\u015b' # 0x0098 -> LATIN SMALL LETTER S WITH ACUTE + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + '\xa3' # 0x009c -> POUND SIGN + '\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + '\xd7' # 0x009e -> MULTIPLICATION SIGN + '\xa4' # 0x009f -> CURRENCY SIGN + '\u0100' # 0x00a0 -> LATIN CAPITAL LETTER A WITH MACRON + '\u012a' # 0x00a1 -> LATIN CAPITAL LETTER I WITH MACRON + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\u017b' # 0x00a3 -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\u017c' # 0x00a4 -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u017a' # 0x00a5 -> LATIN SMALL LETTER Z WITH ACUTE + '\u201d' # 0x00a6 -> RIGHT DOUBLE QUOTATION MARK + '\xa6' # 0x00a7 -> BROKEN BAR + '\xa9' # 0x00a8 -> COPYRIGHT SIGN + '\xae' # 0x00a9 -> REGISTERED SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\u0141' # 0x00ad -> LATIN CAPITAL LETTER L WITH STROKE + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u0104' # 0x00b5 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u010c' # 0x00b6 -> LATIN CAPITAL LETTER C WITH CARON + '\u0118' # 0x00b7 -> LATIN CAPITAL LETTER E WITH OGONEK + '\u0116' # 0x00b8 -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u012e' # 0x00bd -> LATIN CAPITAL LETTER I WITH OGONEK + '\u0160' # 0x00be -> LATIN CAPITAL LETTER S WITH CARON + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u0172' # 0x00c6 -> LATIN CAPITAL LETTER U WITH OGONEK + '\u016a' # 0x00c7 -> LATIN CAPITAL LETTER U WITH MACRON + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u017d' # 0x00cf -> LATIN CAPITAL LETTER Z WITH CARON + '\u0105' # 0x00d0 -> LATIN SMALL LETTER A WITH OGONEK + '\u010d' # 0x00d1 -> LATIN SMALL LETTER C WITH CARON + '\u0119' # 0x00d2 -> LATIN SMALL LETTER E WITH OGONEK + '\u0117' # 0x00d3 -> LATIN SMALL LETTER E WITH DOT ABOVE + '\u012f' # 0x00d4 -> LATIN SMALL LETTER I WITH OGONEK + '\u0161' # 0x00d5 -> LATIN SMALL LETTER S WITH CARON + '\u0173' # 0x00d6 -> LATIN SMALL LETTER U WITH OGONEK + '\u016b' # 0x00d7 -> LATIN SMALL LETTER U WITH MACRON + '\u017e' # 0x00d8 -> LATIN SMALL LETTER Z WITH CARON + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S (GERMAN) + '\u014c' # 0x00e2 -> LATIN CAPITAL LETTER O WITH MACRON + '\u0143' # 0x00e3 -> LATIN CAPITAL LETTER N WITH ACUTE + '\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + '\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xb5' # 0x00e6 -> MICRO SIGN + '\u0144' # 0x00e7 -> LATIN SMALL LETTER N WITH ACUTE + '\u0136' # 0x00e8 -> LATIN CAPITAL LETTER K WITH CEDILLA + '\u0137' # 0x00e9 -> LATIN SMALL LETTER K WITH CEDILLA + '\u013b' # 0x00ea -> LATIN CAPITAL LETTER L WITH CEDILLA + '\u013c' # 0x00eb -> LATIN SMALL LETTER L WITH CEDILLA + '\u0146' # 0x00ec -> LATIN SMALL LETTER N WITH CEDILLA + '\u0112' # 0x00ed -> LATIN CAPITAL LETTER E WITH MACRON + '\u0145' # 0x00ee -> LATIN CAPITAL LETTER N WITH CEDILLA + '\u2019' # 0x00ef -> RIGHT SINGLE QUOTATION MARK + '\xad' # 0x00f0 -> SOFT HYPHEN + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u201c' # 0x00f2 -> LEFT DOUBLE QUOTATION MARK + '\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + '\xb6' # 0x00f4 -> PILCROW SIGN + '\xa7' # 0x00f5 -> SECTION SIGN + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u201e' # 0x00f7 -> DOUBLE LOW-9 QUOTATION MARK + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\xb9' # 0x00fb -> SUPERSCRIPT ONE + '\xb3' # 0x00fc -> SUPERSCRIPT THREE + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a2: 0x0096, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x009f, # CURRENCY SIGN + 0x00a6: 0x00a7, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a9: 0x00a8, # COPYRIGHT SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0100: 0x00a0, # LATIN CAPITAL LETTER A WITH MACRON + 0x0101: 0x0083, # LATIN SMALL LETTER A WITH MACRON + 0x0104: 0x00b5, # LATIN CAPITAL LETTER A WITH OGONEK + 0x0105: 0x00d0, # LATIN SMALL LETTER A WITH OGONEK + 0x0106: 0x0080, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0107: 0x0087, # LATIN SMALL LETTER C WITH ACUTE + 0x010c: 0x00b6, # LATIN CAPITAL LETTER C WITH CARON + 0x010d: 0x00d1, # LATIN SMALL LETTER C WITH CARON + 0x0112: 0x00ed, # LATIN CAPITAL LETTER E WITH MACRON + 0x0113: 0x0089, # LATIN SMALL LETTER E WITH MACRON + 0x0116: 0x00b8, # LATIN CAPITAL LETTER E WITH DOT ABOVE + 0x0117: 0x00d3, # LATIN SMALL LETTER E WITH DOT ABOVE + 0x0118: 0x00b7, # LATIN CAPITAL LETTER E WITH OGONEK + 0x0119: 0x00d2, # LATIN SMALL LETTER E WITH OGONEK + 0x0122: 0x0095, # LATIN CAPITAL LETTER G WITH CEDILLA + 0x0123: 0x0085, # LATIN SMALL LETTER G WITH CEDILLA + 0x012a: 0x00a1, # LATIN CAPITAL LETTER I WITH MACRON + 0x012b: 0x008c, # LATIN SMALL LETTER I WITH MACRON + 0x012e: 0x00bd, # LATIN CAPITAL LETTER I WITH OGONEK + 0x012f: 0x00d4, # LATIN SMALL LETTER I WITH OGONEK + 0x0136: 0x00e8, # LATIN CAPITAL LETTER K WITH CEDILLA + 0x0137: 0x00e9, # LATIN SMALL LETTER K WITH CEDILLA + 0x013b: 0x00ea, # LATIN CAPITAL LETTER L WITH CEDILLA + 0x013c: 0x00eb, # LATIN SMALL LETTER L WITH CEDILLA + 0x0141: 0x00ad, # LATIN CAPITAL LETTER L WITH STROKE + 0x0142: 0x0088, # LATIN SMALL LETTER L WITH STROKE + 0x0143: 0x00e3, # LATIN CAPITAL LETTER N WITH ACUTE + 0x0144: 0x00e7, # LATIN SMALL LETTER N WITH ACUTE + 0x0145: 0x00ee, # LATIN CAPITAL LETTER N WITH CEDILLA + 0x0146: 0x00ec, # LATIN SMALL LETTER N WITH CEDILLA + 0x014c: 0x00e2, # LATIN CAPITAL LETTER O WITH MACRON + 0x014d: 0x0093, # LATIN SMALL LETTER O WITH MACRON + 0x0156: 0x008a, # LATIN CAPITAL LETTER R WITH CEDILLA + 0x0157: 0x008b, # LATIN SMALL LETTER R WITH CEDILLA + 0x015a: 0x0097, # LATIN CAPITAL LETTER S WITH ACUTE + 0x015b: 0x0098, # LATIN SMALL LETTER S WITH ACUTE + 0x0160: 0x00be, # LATIN CAPITAL LETTER S WITH CARON + 0x0161: 0x00d5, # LATIN SMALL LETTER S WITH CARON + 0x016a: 0x00c7, # LATIN CAPITAL LETTER U WITH MACRON + 0x016b: 0x00d7, # LATIN SMALL LETTER U WITH MACRON + 0x0172: 0x00c6, # LATIN CAPITAL LETTER U WITH OGONEK + 0x0173: 0x00d6, # LATIN SMALL LETTER U WITH OGONEK + 0x0179: 0x008d, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x017a: 0x00a5, # LATIN SMALL LETTER Z WITH ACUTE + 0x017b: 0x00a3, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x017c: 0x00a4, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x017d: 0x00cf, # LATIN CAPITAL LETTER Z WITH CARON + 0x017e: 0x00d8, # LATIN SMALL LETTER Z WITH CARON + 0x2019: 0x00ef, # RIGHT SINGLE QUOTATION MARK + 0x201c: 0x00f2, # LEFT DOUBLE QUOTATION MARK + 0x201d: 0x00a6, # RIGHT DOUBLE QUOTATION MARK + 0x201e: 0x00f7, # DOUBLE LOW-9 QUOTATION MARK + 0x2219: 0x00f9, # BULLET OPERATOR + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp850.py b/winvenv/Lib/encodings/cp850.py new file mode 100644 index 0000000..f98aef9 --- /dev/null +++ b/winvenv/Lib/encodings/cp850.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP850.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp850', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x00d7, # MULTIPLICATION SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00b6: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00b7: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00b8: 0x00a9, # COPYRIGHT SIGN + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x00a2, # CENT SIGN + 0x00be: 0x00a5, # YEN SIGN + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x00c7: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x00f0, # LATIN SMALL LETTER ETH + 0x00d1: 0x00d0, # LATIN CAPITAL LETTER ETH + 0x00d2: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00d3: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00d4: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00d5: 0x0131, # LATIN SMALL LETTER DOTLESS I + 0x00d6: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d7: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d8: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x00a6, # BROKEN BAR + 0x00de: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e3: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x00fe, # LATIN SMALL LETTER THORN + 0x00e8: 0x00de, # LATIN CAPITAL LETTER THORN + 0x00e9: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ea: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00eb: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00ec: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x00ed: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00ee: 0x00af, # MACRON + 0x00ef: 0x00b4, # ACUTE ACCENT + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2017, # DOUBLE LOW LINE + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x00b8, # CEDILLA + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + '\xa3' # 0x009c -> POUND SIGN + '\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + '\xd7' # 0x009e -> MULTIPLICATION SIGN + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + '\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\xae' # 0x00a9 -> REGISTERED SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc0' # 0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xa9' # 0x00b8 -> COPYRIGHT SIGN + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\xa2' # 0x00bd -> CENT SIGN + '\xa5' # 0x00be -> YEN SIGN + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\xe3' # 0x00c6 -> LATIN SMALL LETTER A WITH TILDE + '\xc3' # 0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa4' # 0x00cf -> CURRENCY SIGN + '\xf0' # 0x00d0 -> LATIN SMALL LETTER ETH + '\xd0' # 0x00d1 -> LATIN CAPITAL LETTER ETH + '\xca' # 0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE + '\u0131' # 0x00d5 -> LATIN SMALL LETTER DOTLESS I + '\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\xa6' # 0x00dd -> BROKEN BAR + '\xcc' # 0x00de -> LATIN CAPITAL LETTER I WITH GRAVE + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd2' # 0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + '\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xb5' # 0x00e6 -> MICRO SIGN + '\xfe' # 0x00e7 -> LATIN SMALL LETTER THORN + '\xde' # 0x00e8 -> LATIN CAPITAL LETTER THORN + '\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE + '\xfd' # 0x00ec -> LATIN SMALL LETTER Y WITH ACUTE + '\xdd' # 0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xaf' # 0x00ee -> MACRON + '\xb4' # 0x00ef -> ACUTE ACCENT + '\xad' # 0x00f0 -> SOFT HYPHEN + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2017' # 0x00f2 -> DOUBLE LOW LINE + '\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + '\xb6' # 0x00f4 -> PILCROW SIGN + '\xa7' # 0x00f5 -> SECTION SIGN + '\xf7' # 0x00f6 -> DIVISION SIGN + '\xb8' # 0x00f7 -> CEDILLA + '\xb0' # 0x00f8 -> DEGREE SIGN + '\xa8' # 0x00f9 -> DIAERESIS + '\xb7' # 0x00fa -> MIDDLE DOT + '\xb9' # 0x00fb -> SUPERSCRIPT ONE + '\xb3' # 0x00fc -> SUPERSCRIPT THREE + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x00bd, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a5: 0x00be, # YEN SIGN + 0x00a6: 0x00dd, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x00b8, # COPYRIGHT SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00af: 0x00ee, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00f7, # CEDILLA + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x00b7, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00c7, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00d4, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00d2, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00de, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00d8, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d0: 0x00d1, # LATIN CAPITAL LETTER ETH + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00e3, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00eb, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00ea, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00ed, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x00e8, # LATIN CAPITAL LETTER THORN + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00c6, # LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f0: 0x00d0, # LATIN SMALL LETTER ETH + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00ec, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x00e7, # LATIN SMALL LETTER THORN + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0131: 0x00d5, # LATIN SMALL LETTER DOTLESS I + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x2017: 0x00f2, # DOUBLE LOW LINE + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp852.py b/winvenv/Lib/encodings/cp852.py new file mode 100644 index 0000000..34d8a0e --- /dev/null +++ b/winvenv/Lib/encodings/cp852.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP852.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp852', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x016f, # LATIN SMALL LETTER U WITH RING ABOVE + 0x0086: 0x0107, # LATIN SMALL LETTER C WITH ACUTE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x0142, # LATIN SMALL LETTER L WITH STROKE + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x0150, # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + 0x008b: 0x0151, # LATIN SMALL LETTER O WITH DOUBLE ACUTE + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x0179, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x0106, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x0139, # LATIN CAPITAL LETTER L WITH ACUTE + 0x0092: 0x013a, # LATIN SMALL LETTER L WITH ACUTE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x013d, # LATIN CAPITAL LETTER L WITH CARON + 0x0096: 0x013e, # LATIN SMALL LETTER L WITH CARON + 0x0097: 0x015a, # LATIN CAPITAL LETTER S WITH ACUTE + 0x0098: 0x015b, # LATIN SMALL LETTER S WITH ACUTE + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x0164, # LATIN CAPITAL LETTER T WITH CARON + 0x009c: 0x0165, # LATIN SMALL LETTER T WITH CARON + 0x009d: 0x0141, # LATIN CAPITAL LETTER L WITH STROKE + 0x009e: 0x00d7, # MULTIPLICATION SIGN + 0x009f: 0x010d, # LATIN SMALL LETTER C WITH CARON + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x0104, # LATIN CAPITAL LETTER A WITH OGONEK + 0x00a5: 0x0105, # LATIN SMALL LETTER A WITH OGONEK + 0x00a6: 0x017d, # LATIN CAPITAL LETTER Z WITH CARON + 0x00a7: 0x017e, # LATIN SMALL LETTER Z WITH CARON + 0x00a8: 0x0118, # LATIN CAPITAL LETTER E WITH OGONEK + 0x00a9: 0x0119, # LATIN SMALL LETTER E WITH OGONEK + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x017a, # LATIN SMALL LETTER Z WITH ACUTE + 0x00ac: 0x010c, # LATIN CAPITAL LETTER C WITH CARON + 0x00ad: 0x015f, # LATIN SMALL LETTER S WITH CEDILLA + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00b6: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00b7: 0x011a, # LATIN CAPITAL LETTER E WITH CARON + 0x00b8: 0x015e, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x017b, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x00be: 0x017c, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x0102, # LATIN CAPITAL LETTER A WITH BREVE + 0x00c7: 0x0103, # LATIN SMALL LETTER A WITH BREVE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x0111, # LATIN SMALL LETTER D WITH STROKE + 0x00d1: 0x0110, # LATIN CAPITAL LETTER D WITH STROKE + 0x00d2: 0x010e, # LATIN CAPITAL LETTER D WITH CARON + 0x00d3: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00d4: 0x010f, # LATIN SMALL LETTER D WITH CARON + 0x00d5: 0x0147, # LATIN CAPITAL LETTER N WITH CARON + 0x00d6: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d7: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d8: 0x011b, # LATIN SMALL LETTER E WITH CARON + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x0162, # LATIN CAPITAL LETTER T WITH CEDILLA + 0x00de: 0x016e, # LATIN CAPITAL LETTER U WITH RING ABOVE + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e3: 0x0143, # LATIN CAPITAL LETTER N WITH ACUTE + 0x00e4: 0x0144, # LATIN SMALL LETTER N WITH ACUTE + 0x00e5: 0x0148, # LATIN SMALL LETTER N WITH CARON + 0x00e6: 0x0160, # LATIN CAPITAL LETTER S WITH CARON + 0x00e7: 0x0161, # LATIN SMALL LETTER S WITH CARON + 0x00e8: 0x0154, # LATIN CAPITAL LETTER R WITH ACUTE + 0x00e9: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ea: 0x0155, # LATIN SMALL LETTER R WITH ACUTE + 0x00eb: 0x0170, # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + 0x00ec: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x00ed: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00ee: 0x0163, # LATIN SMALL LETTER T WITH CEDILLA + 0x00ef: 0x00b4, # ACUTE ACCENT + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x02dd, # DOUBLE ACUTE ACCENT + 0x00f2: 0x02db, # OGONEK + 0x00f3: 0x02c7, # CARON + 0x00f4: 0x02d8, # BREVE + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x00b8, # CEDILLA + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x02d9, # DOT ABOVE + 0x00fb: 0x0171, # LATIN SMALL LETTER U WITH DOUBLE ACUTE + 0x00fc: 0x0158, # LATIN CAPITAL LETTER R WITH CARON + 0x00fd: 0x0159, # LATIN SMALL LETTER R WITH CARON + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\u016f' # 0x0085 -> LATIN SMALL LETTER U WITH RING ABOVE + '\u0107' # 0x0086 -> LATIN SMALL LETTER C WITH ACUTE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\u0142' # 0x0088 -> LATIN SMALL LETTER L WITH STROKE + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\u0150' # 0x008a -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + '\u0151' # 0x008b -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\u0179' # 0x008d -> LATIN CAPITAL LETTER Z WITH ACUTE + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u0106' # 0x008f -> LATIN CAPITAL LETTER C WITH ACUTE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0139' # 0x0091 -> LATIN CAPITAL LETTER L WITH ACUTE + '\u013a' # 0x0092 -> LATIN SMALL LETTER L WITH ACUTE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\u013d' # 0x0095 -> LATIN CAPITAL LETTER L WITH CARON + '\u013e' # 0x0096 -> LATIN SMALL LETTER L WITH CARON + '\u015a' # 0x0097 -> LATIN CAPITAL LETTER S WITH ACUTE + '\u015b' # 0x0098 -> LATIN SMALL LETTER S WITH ACUTE + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u0164' # 0x009b -> LATIN CAPITAL LETTER T WITH CARON + '\u0165' # 0x009c -> LATIN SMALL LETTER T WITH CARON + '\u0141' # 0x009d -> LATIN CAPITAL LETTER L WITH STROKE + '\xd7' # 0x009e -> MULTIPLICATION SIGN + '\u010d' # 0x009f -> LATIN SMALL LETTER C WITH CARON + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\u0104' # 0x00a4 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u0105' # 0x00a5 -> LATIN SMALL LETTER A WITH OGONEK + '\u017d' # 0x00a6 -> LATIN CAPITAL LETTER Z WITH CARON + '\u017e' # 0x00a7 -> LATIN SMALL LETTER Z WITH CARON + '\u0118' # 0x00a8 -> LATIN CAPITAL LETTER E WITH OGONEK + '\u0119' # 0x00a9 -> LATIN SMALL LETTER E WITH OGONEK + '\xac' # 0x00aa -> NOT SIGN + '\u017a' # 0x00ab -> LATIN SMALL LETTER Z WITH ACUTE + '\u010c' # 0x00ac -> LATIN CAPITAL LETTER C WITH CARON + '\u015f' # 0x00ad -> LATIN SMALL LETTER S WITH CEDILLA + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\u011a' # 0x00b7 -> LATIN CAPITAL LETTER E WITH CARON + '\u015e' # 0x00b8 -> LATIN CAPITAL LETTER S WITH CEDILLA + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u017b' # 0x00bd -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\u017c' # 0x00be -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u0102' # 0x00c6 -> LATIN CAPITAL LETTER A WITH BREVE + '\u0103' # 0x00c7 -> LATIN SMALL LETTER A WITH BREVE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa4' # 0x00cf -> CURRENCY SIGN + '\u0111' # 0x00d0 -> LATIN SMALL LETTER D WITH STROKE + '\u0110' # 0x00d1 -> LATIN CAPITAL LETTER D WITH STROKE + '\u010e' # 0x00d2 -> LATIN CAPITAL LETTER D WITH CARON + '\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u010f' # 0x00d4 -> LATIN SMALL LETTER D WITH CARON + '\u0147' # 0x00d5 -> LATIN CAPITAL LETTER N WITH CARON + '\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\u011b' # 0x00d8 -> LATIN SMALL LETTER E WITH CARON + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u0162' # 0x00dd -> LATIN CAPITAL LETTER T WITH CEDILLA + '\u016e' # 0x00de -> LATIN CAPITAL LETTER U WITH RING ABOVE + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u0143' # 0x00e3 -> LATIN CAPITAL LETTER N WITH ACUTE + '\u0144' # 0x00e4 -> LATIN SMALL LETTER N WITH ACUTE + '\u0148' # 0x00e5 -> LATIN SMALL LETTER N WITH CARON + '\u0160' # 0x00e6 -> LATIN CAPITAL LETTER S WITH CARON + '\u0161' # 0x00e7 -> LATIN SMALL LETTER S WITH CARON + '\u0154' # 0x00e8 -> LATIN CAPITAL LETTER R WITH ACUTE + '\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + '\u0155' # 0x00ea -> LATIN SMALL LETTER R WITH ACUTE + '\u0170' # 0x00eb -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + '\xfd' # 0x00ec -> LATIN SMALL LETTER Y WITH ACUTE + '\xdd' # 0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE + '\u0163' # 0x00ee -> LATIN SMALL LETTER T WITH CEDILLA + '\xb4' # 0x00ef -> ACUTE ACCENT + '\xad' # 0x00f0 -> SOFT HYPHEN + '\u02dd' # 0x00f1 -> DOUBLE ACUTE ACCENT + '\u02db' # 0x00f2 -> OGONEK + '\u02c7' # 0x00f3 -> CARON + '\u02d8' # 0x00f4 -> BREVE + '\xa7' # 0x00f5 -> SECTION SIGN + '\xf7' # 0x00f6 -> DIVISION SIGN + '\xb8' # 0x00f7 -> CEDILLA + '\xb0' # 0x00f8 -> DEGREE SIGN + '\xa8' # 0x00f9 -> DIAERESIS + '\u02d9' # 0x00fa -> DOT ABOVE + '\u0171' # 0x00fb -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + '\u0158' # 0x00fc -> LATIN CAPITAL LETTER R WITH CARON + '\u0159' # 0x00fd -> LATIN SMALL LETTER R WITH CARON + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b8: 0x00f7, # CEDILLA + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00ed, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00ec, # LATIN SMALL LETTER Y WITH ACUTE + 0x0102: 0x00c6, # LATIN CAPITAL LETTER A WITH BREVE + 0x0103: 0x00c7, # LATIN SMALL LETTER A WITH BREVE + 0x0104: 0x00a4, # LATIN CAPITAL LETTER A WITH OGONEK + 0x0105: 0x00a5, # LATIN SMALL LETTER A WITH OGONEK + 0x0106: 0x008f, # LATIN CAPITAL LETTER C WITH ACUTE + 0x0107: 0x0086, # LATIN SMALL LETTER C WITH ACUTE + 0x010c: 0x00ac, # LATIN CAPITAL LETTER C WITH CARON + 0x010d: 0x009f, # LATIN SMALL LETTER C WITH CARON + 0x010e: 0x00d2, # LATIN CAPITAL LETTER D WITH CARON + 0x010f: 0x00d4, # LATIN SMALL LETTER D WITH CARON + 0x0110: 0x00d1, # LATIN CAPITAL LETTER D WITH STROKE + 0x0111: 0x00d0, # LATIN SMALL LETTER D WITH STROKE + 0x0118: 0x00a8, # LATIN CAPITAL LETTER E WITH OGONEK + 0x0119: 0x00a9, # LATIN SMALL LETTER E WITH OGONEK + 0x011a: 0x00b7, # LATIN CAPITAL LETTER E WITH CARON + 0x011b: 0x00d8, # LATIN SMALL LETTER E WITH CARON + 0x0139: 0x0091, # LATIN CAPITAL LETTER L WITH ACUTE + 0x013a: 0x0092, # LATIN SMALL LETTER L WITH ACUTE + 0x013d: 0x0095, # LATIN CAPITAL LETTER L WITH CARON + 0x013e: 0x0096, # LATIN SMALL LETTER L WITH CARON + 0x0141: 0x009d, # LATIN CAPITAL LETTER L WITH STROKE + 0x0142: 0x0088, # LATIN SMALL LETTER L WITH STROKE + 0x0143: 0x00e3, # LATIN CAPITAL LETTER N WITH ACUTE + 0x0144: 0x00e4, # LATIN SMALL LETTER N WITH ACUTE + 0x0147: 0x00d5, # LATIN CAPITAL LETTER N WITH CARON + 0x0148: 0x00e5, # LATIN SMALL LETTER N WITH CARON + 0x0150: 0x008a, # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + 0x0151: 0x008b, # LATIN SMALL LETTER O WITH DOUBLE ACUTE + 0x0154: 0x00e8, # LATIN CAPITAL LETTER R WITH ACUTE + 0x0155: 0x00ea, # LATIN SMALL LETTER R WITH ACUTE + 0x0158: 0x00fc, # LATIN CAPITAL LETTER R WITH CARON + 0x0159: 0x00fd, # LATIN SMALL LETTER R WITH CARON + 0x015a: 0x0097, # LATIN CAPITAL LETTER S WITH ACUTE + 0x015b: 0x0098, # LATIN SMALL LETTER S WITH ACUTE + 0x015e: 0x00b8, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x015f: 0x00ad, # LATIN SMALL LETTER S WITH CEDILLA + 0x0160: 0x00e6, # LATIN CAPITAL LETTER S WITH CARON + 0x0161: 0x00e7, # LATIN SMALL LETTER S WITH CARON + 0x0162: 0x00dd, # LATIN CAPITAL LETTER T WITH CEDILLA + 0x0163: 0x00ee, # LATIN SMALL LETTER T WITH CEDILLA + 0x0164: 0x009b, # LATIN CAPITAL LETTER T WITH CARON + 0x0165: 0x009c, # LATIN SMALL LETTER T WITH CARON + 0x016e: 0x00de, # LATIN CAPITAL LETTER U WITH RING ABOVE + 0x016f: 0x0085, # LATIN SMALL LETTER U WITH RING ABOVE + 0x0170: 0x00eb, # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + 0x0171: 0x00fb, # LATIN SMALL LETTER U WITH DOUBLE ACUTE + 0x0179: 0x008d, # LATIN CAPITAL LETTER Z WITH ACUTE + 0x017a: 0x00ab, # LATIN SMALL LETTER Z WITH ACUTE + 0x017b: 0x00bd, # LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x017c: 0x00be, # LATIN SMALL LETTER Z WITH DOT ABOVE + 0x017d: 0x00a6, # LATIN CAPITAL LETTER Z WITH CARON + 0x017e: 0x00a7, # LATIN SMALL LETTER Z WITH CARON + 0x02c7: 0x00f3, # CARON + 0x02d8: 0x00f4, # BREVE + 0x02d9: 0x00fa, # DOT ABOVE + 0x02db: 0x00f2, # OGONEK + 0x02dd: 0x00f1, # DOUBLE ACUTE ACCENT + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp855.py b/winvenv/Lib/encodings/cp855.py new file mode 100644 index 0000000..4fe9210 --- /dev/null +++ b/winvenv/Lib/encodings/cp855.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP855.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp855', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x0452, # CYRILLIC SMALL LETTER DJE + 0x0081: 0x0402, # CYRILLIC CAPITAL LETTER DJE + 0x0082: 0x0453, # CYRILLIC SMALL LETTER GJE + 0x0083: 0x0403, # CYRILLIC CAPITAL LETTER GJE + 0x0084: 0x0451, # CYRILLIC SMALL LETTER IO + 0x0085: 0x0401, # CYRILLIC CAPITAL LETTER IO + 0x0086: 0x0454, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x0087: 0x0404, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x0088: 0x0455, # CYRILLIC SMALL LETTER DZE + 0x0089: 0x0405, # CYRILLIC CAPITAL LETTER DZE + 0x008a: 0x0456, # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + 0x008b: 0x0406, # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + 0x008c: 0x0457, # CYRILLIC SMALL LETTER YI + 0x008d: 0x0407, # CYRILLIC CAPITAL LETTER YI + 0x008e: 0x0458, # CYRILLIC SMALL LETTER JE + 0x008f: 0x0408, # CYRILLIC CAPITAL LETTER JE + 0x0090: 0x0459, # CYRILLIC SMALL LETTER LJE + 0x0091: 0x0409, # CYRILLIC CAPITAL LETTER LJE + 0x0092: 0x045a, # CYRILLIC SMALL LETTER NJE + 0x0093: 0x040a, # CYRILLIC CAPITAL LETTER NJE + 0x0094: 0x045b, # CYRILLIC SMALL LETTER TSHE + 0x0095: 0x040b, # CYRILLIC CAPITAL LETTER TSHE + 0x0096: 0x045c, # CYRILLIC SMALL LETTER KJE + 0x0097: 0x040c, # CYRILLIC CAPITAL LETTER KJE + 0x0098: 0x045e, # CYRILLIC SMALL LETTER SHORT U + 0x0099: 0x040e, # CYRILLIC CAPITAL LETTER SHORT U + 0x009a: 0x045f, # CYRILLIC SMALL LETTER DZHE + 0x009b: 0x040f, # CYRILLIC CAPITAL LETTER DZHE + 0x009c: 0x044e, # CYRILLIC SMALL LETTER YU + 0x009d: 0x042e, # CYRILLIC CAPITAL LETTER YU + 0x009e: 0x044a, # CYRILLIC SMALL LETTER HARD SIGN + 0x009f: 0x042a, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x00a0: 0x0430, # CYRILLIC SMALL LETTER A + 0x00a1: 0x0410, # CYRILLIC CAPITAL LETTER A + 0x00a2: 0x0431, # CYRILLIC SMALL LETTER BE + 0x00a3: 0x0411, # CYRILLIC CAPITAL LETTER BE + 0x00a4: 0x0446, # CYRILLIC SMALL LETTER TSE + 0x00a5: 0x0426, # CYRILLIC CAPITAL LETTER TSE + 0x00a6: 0x0434, # CYRILLIC SMALL LETTER DE + 0x00a7: 0x0414, # CYRILLIC CAPITAL LETTER DE + 0x00a8: 0x0435, # CYRILLIC SMALL LETTER IE + 0x00a9: 0x0415, # CYRILLIC CAPITAL LETTER IE + 0x00aa: 0x0444, # CYRILLIC SMALL LETTER EF + 0x00ab: 0x0424, # CYRILLIC CAPITAL LETTER EF + 0x00ac: 0x0433, # CYRILLIC SMALL LETTER GHE + 0x00ad: 0x0413, # CYRILLIC CAPITAL LETTER GHE + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x0445, # CYRILLIC SMALL LETTER HA + 0x00b6: 0x0425, # CYRILLIC CAPITAL LETTER HA + 0x00b7: 0x0438, # CYRILLIC SMALL LETTER I + 0x00b8: 0x0418, # CYRILLIC CAPITAL LETTER I + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x0439, # CYRILLIC SMALL LETTER SHORT I + 0x00be: 0x0419, # CYRILLIC CAPITAL LETTER SHORT I + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x043a, # CYRILLIC SMALL LETTER KA + 0x00c7: 0x041a, # CYRILLIC CAPITAL LETTER KA + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x043b, # CYRILLIC SMALL LETTER EL + 0x00d1: 0x041b, # CYRILLIC CAPITAL LETTER EL + 0x00d2: 0x043c, # CYRILLIC SMALL LETTER EM + 0x00d3: 0x041c, # CYRILLIC CAPITAL LETTER EM + 0x00d4: 0x043d, # CYRILLIC SMALL LETTER EN + 0x00d5: 0x041d, # CYRILLIC CAPITAL LETTER EN + 0x00d6: 0x043e, # CYRILLIC SMALL LETTER O + 0x00d7: 0x041e, # CYRILLIC CAPITAL LETTER O + 0x00d8: 0x043f, # CYRILLIC SMALL LETTER PE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x041f, # CYRILLIC CAPITAL LETTER PE + 0x00de: 0x044f, # CYRILLIC SMALL LETTER YA + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x042f, # CYRILLIC CAPITAL LETTER YA + 0x00e1: 0x0440, # CYRILLIC SMALL LETTER ER + 0x00e2: 0x0420, # CYRILLIC CAPITAL LETTER ER + 0x00e3: 0x0441, # CYRILLIC SMALL LETTER ES + 0x00e4: 0x0421, # CYRILLIC CAPITAL LETTER ES + 0x00e5: 0x0442, # CYRILLIC SMALL LETTER TE + 0x00e6: 0x0422, # CYRILLIC CAPITAL LETTER TE + 0x00e7: 0x0443, # CYRILLIC SMALL LETTER U + 0x00e8: 0x0423, # CYRILLIC CAPITAL LETTER U + 0x00e9: 0x0436, # CYRILLIC SMALL LETTER ZHE + 0x00ea: 0x0416, # CYRILLIC CAPITAL LETTER ZHE + 0x00eb: 0x0432, # CYRILLIC SMALL LETTER VE + 0x00ec: 0x0412, # CYRILLIC CAPITAL LETTER VE + 0x00ed: 0x044c, # CYRILLIC SMALL LETTER SOFT SIGN + 0x00ee: 0x042c, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x00ef: 0x2116, # NUMERO SIGN + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x044b, # CYRILLIC SMALL LETTER YERU + 0x00f2: 0x042b, # CYRILLIC CAPITAL LETTER YERU + 0x00f3: 0x0437, # CYRILLIC SMALL LETTER ZE + 0x00f4: 0x0417, # CYRILLIC CAPITAL LETTER ZE + 0x00f5: 0x0448, # CYRILLIC SMALL LETTER SHA + 0x00f6: 0x0428, # CYRILLIC CAPITAL LETTER SHA + 0x00f7: 0x044d, # CYRILLIC SMALL LETTER E + 0x00f8: 0x042d, # CYRILLIC CAPITAL LETTER E + 0x00f9: 0x0449, # CYRILLIC SMALL LETTER SHCHA + 0x00fa: 0x0429, # CYRILLIC CAPITAL LETTER SHCHA + 0x00fb: 0x0447, # CYRILLIC SMALL LETTER CHE + 0x00fc: 0x0427, # CYRILLIC CAPITAL LETTER CHE + 0x00fd: 0x00a7, # SECTION SIGN + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\u0452' # 0x0080 -> CYRILLIC SMALL LETTER DJE + '\u0402' # 0x0081 -> CYRILLIC CAPITAL LETTER DJE + '\u0453' # 0x0082 -> CYRILLIC SMALL LETTER GJE + '\u0403' # 0x0083 -> CYRILLIC CAPITAL LETTER GJE + '\u0451' # 0x0084 -> CYRILLIC SMALL LETTER IO + '\u0401' # 0x0085 -> CYRILLIC CAPITAL LETTER IO + '\u0454' # 0x0086 -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\u0404' # 0x0087 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\u0455' # 0x0088 -> CYRILLIC SMALL LETTER DZE + '\u0405' # 0x0089 -> CYRILLIC CAPITAL LETTER DZE + '\u0456' # 0x008a -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0406' # 0x008b -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0457' # 0x008c -> CYRILLIC SMALL LETTER YI + '\u0407' # 0x008d -> CYRILLIC CAPITAL LETTER YI + '\u0458' # 0x008e -> CYRILLIC SMALL LETTER JE + '\u0408' # 0x008f -> CYRILLIC CAPITAL LETTER JE + '\u0459' # 0x0090 -> CYRILLIC SMALL LETTER LJE + '\u0409' # 0x0091 -> CYRILLIC CAPITAL LETTER LJE + '\u045a' # 0x0092 -> CYRILLIC SMALL LETTER NJE + '\u040a' # 0x0093 -> CYRILLIC CAPITAL LETTER NJE + '\u045b' # 0x0094 -> CYRILLIC SMALL LETTER TSHE + '\u040b' # 0x0095 -> CYRILLIC CAPITAL LETTER TSHE + '\u045c' # 0x0096 -> CYRILLIC SMALL LETTER KJE + '\u040c' # 0x0097 -> CYRILLIC CAPITAL LETTER KJE + '\u045e' # 0x0098 -> CYRILLIC SMALL LETTER SHORT U + '\u040e' # 0x0099 -> CYRILLIC CAPITAL LETTER SHORT U + '\u045f' # 0x009a -> CYRILLIC SMALL LETTER DZHE + '\u040f' # 0x009b -> CYRILLIC CAPITAL LETTER DZHE + '\u044e' # 0x009c -> CYRILLIC SMALL LETTER YU + '\u042e' # 0x009d -> CYRILLIC CAPITAL LETTER YU + '\u044a' # 0x009e -> CYRILLIC SMALL LETTER HARD SIGN + '\u042a' # 0x009f -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u0430' # 0x00a0 -> CYRILLIC SMALL LETTER A + '\u0410' # 0x00a1 -> CYRILLIC CAPITAL LETTER A + '\u0431' # 0x00a2 -> CYRILLIC SMALL LETTER BE + '\u0411' # 0x00a3 -> CYRILLIC CAPITAL LETTER BE + '\u0446' # 0x00a4 -> CYRILLIC SMALL LETTER TSE + '\u0426' # 0x00a5 -> CYRILLIC CAPITAL LETTER TSE + '\u0434' # 0x00a6 -> CYRILLIC SMALL LETTER DE + '\u0414' # 0x00a7 -> CYRILLIC CAPITAL LETTER DE + '\u0435' # 0x00a8 -> CYRILLIC SMALL LETTER IE + '\u0415' # 0x00a9 -> CYRILLIC CAPITAL LETTER IE + '\u0444' # 0x00aa -> CYRILLIC SMALL LETTER EF + '\u0424' # 0x00ab -> CYRILLIC CAPITAL LETTER EF + '\u0433' # 0x00ac -> CYRILLIC SMALL LETTER GHE + '\u0413' # 0x00ad -> CYRILLIC CAPITAL LETTER GHE + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u0445' # 0x00b5 -> CYRILLIC SMALL LETTER HA + '\u0425' # 0x00b6 -> CYRILLIC CAPITAL LETTER HA + '\u0438' # 0x00b7 -> CYRILLIC SMALL LETTER I + '\u0418' # 0x00b8 -> CYRILLIC CAPITAL LETTER I + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u0439' # 0x00bd -> CYRILLIC SMALL LETTER SHORT I + '\u0419' # 0x00be -> CYRILLIC CAPITAL LETTER SHORT I + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u043a' # 0x00c6 -> CYRILLIC SMALL LETTER KA + '\u041a' # 0x00c7 -> CYRILLIC CAPITAL LETTER KA + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa4' # 0x00cf -> CURRENCY SIGN + '\u043b' # 0x00d0 -> CYRILLIC SMALL LETTER EL + '\u041b' # 0x00d1 -> CYRILLIC CAPITAL LETTER EL + '\u043c' # 0x00d2 -> CYRILLIC SMALL LETTER EM + '\u041c' # 0x00d3 -> CYRILLIC CAPITAL LETTER EM + '\u043d' # 0x00d4 -> CYRILLIC SMALL LETTER EN + '\u041d' # 0x00d5 -> CYRILLIC CAPITAL LETTER EN + '\u043e' # 0x00d6 -> CYRILLIC SMALL LETTER O + '\u041e' # 0x00d7 -> CYRILLIC CAPITAL LETTER O + '\u043f' # 0x00d8 -> CYRILLIC SMALL LETTER PE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u041f' # 0x00dd -> CYRILLIC CAPITAL LETTER PE + '\u044f' # 0x00de -> CYRILLIC SMALL LETTER YA + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u042f' # 0x00e0 -> CYRILLIC CAPITAL LETTER YA + '\u0440' # 0x00e1 -> CYRILLIC SMALL LETTER ER + '\u0420' # 0x00e2 -> CYRILLIC CAPITAL LETTER ER + '\u0441' # 0x00e3 -> CYRILLIC SMALL LETTER ES + '\u0421' # 0x00e4 -> CYRILLIC CAPITAL LETTER ES + '\u0442' # 0x00e5 -> CYRILLIC SMALL LETTER TE + '\u0422' # 0x00e6 -> CYRILLIC CAPITAL LETTER TE + '\u0443' # 0x00e7 -> CYRILLIC SMALL LETTER U + '\u0423' # 0x00e8 -> CYRILLIC CAPITAL LETTER U + '\u0436' # 0x00e9 -> CYRILLIC SMALL LETTER ZHE + '\u0416' # 0x00ea -> CYRILLIC CAPITAL LETTER ZHE + '\u0432' # 0x00eb -> CYRILLIC SMALL LETTER VE + '\u0412' # 0x00ec -> CYRILLIC CAPITAL LETTER VE + '\u044c' # 0x00ed -> CYRILLIC SMALL LETTER SOFT SIGN + '\u042c' # 0x00ee -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u2116' # 0x00ef -> NUMERO SIGN + '\xad' # 0x00f0 -> SOFT HYPHEN + '\u044b' # 0x00f1 -> CYRILLIC SMALL LETTER YERU + '\u042b' # 0x00f2 -> CYRILLIC CAPITAL LETTER YERU + '\u0437' # 0x00f3 -> CYRILLIC SMALL LETTER ZE + '\u0417' # 0x00f4 -> CYRILLIC CAPITAL LETTER ZE + '\u0448' # 0x00f5 -> CYRILLIC SMALL LETTER SHA + '\u0428' # 0x00f6 -> CYRILLIC CAPITAL LETTER SHA + '\u044d' # 0x00f7 -> CYRILLIC SMALL LETTER E + '\u042d' # 0x00f8 -> CYRILLIC CAPITAL LETTER E + '\u0449' # 0x00f9 -> CYRILLIC SMALL LETTER SHCHA + '\u0429' # 0x00fa -> CYRILLIC CAPITAL LETTER SHCHA + '\u0447' # 0x00fb -> CYRILLIC SMALL LETTER CHE + '\u0427' # 0x00fc -> CYRILLIC CAPITAL LETTER CHE + '\xa7' # 0x00fd -> SECTION SIGN + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a7: 0x00fd, # SECTION SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x0401: 0x0085, # CYRILLIC CAPITAL LETTER IO + 0x0402: 0x0081, # CYRILLIC CAPITAL LETTER DJE + 0x0403: 0x0083, # CYRILLIC CAPITAL LETTER GJE + 0x0404: 0x0087, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x0405: 0x0089, # CYRILLIC CAPITAL LETTER DZE + 0x0406: 0x008b, # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + 0x0407: 0x008d, # CYRILLIC CAPITAL LETTER YI + 0x0408: 0x008f, # CYRILLIC CAPITAL LETTER JE + 0x0409: 0x0091, # CYRILLIC CAPITAL LETTER LJE + 0x040a: 0x0093, # CYRILLIC CAPITAL LETTER NJE + 0x040b: 0x0095, # CYRILLIC CAPITAL LETTER TSHE + 0x040c: 0x0097, # CYRILLIC CAPITAL LETTER KJE + 0x040e: 0x0099, # CYRILLIC CAPITAL LETTER SHORT U + 0x040f: 0x009b, # CYRILLIC CAPITAL LETTER DZHE + 0x0410: 0x00a1, # CYRILLIC CAPITAL LETTER A + 0x0411: 0x00a3, # CYRILLIC CAPITAL LETTER BE + 0x0412: 0x00ec, # CYRILLIC CAPITAL LETTER VE + 0x0413: 0x00ad, # CYRILLIC CAPITAL LETTER GHE + 0x0414: 0x00a7, # CYRILLIC CAPITAL LETTER DE + 0x0415: 0x00a9, # CYRILLIC CAPITAL LETTER IE + 0x0416: 0x00ea, # CYRILLIC CAPITAL LETTER ZHE + 0x0417: 0x00f4, # CYRILLIC CAPITAL LETTER ZE + 0x0418: 0x00b8, # CYRILLIC CAPITAL LETTER I + 0x0419: 0x00be, # CYRILLIC CAPITAL LETTER SHORT I + 0x041a: 0x00c7, # CYRILLIC CAPITAL LETTER KA + 0x041b: 0x00d1, # CYRILLIC CAPITAL LETTER EL + 0x041c: 0x00d3, # CYRILLIC CAPITAL LETTER EM + 0x041d: 0x00d5, # CYRILLIC CAPITAL LETTER EN + 0x041e: 0x00d7, # CYRILLIC CAPITAL LETTER O + 0x041f: 0x00dd, # CYRILLIC CAPITAL LETTER PE + 0x0420: 0x00e2, # CYRILLIC CAPITAL LETTER ER + 0x0421: 0x00e4, # CYRILLIC CAPITAL LETTER ES + 0x0422: 0x00e6, # CYRILLIC CAPITAL LETTER TE + 0x0423: 0x00e8, # CYRILLIC CAPITAL LETTER U + 0x0424: 0x00ab, # CYRILLIC CAPITAL LETTER EF + 0x0425: 0x00b6, # CYRILLIC CAPITAL LETTER HA + 0x0426: 0x00a5, # CYRILLIC CAPITAL LETTER TSE + 0x0427: 0x00fc, # CYRILLIC CAPITAL LETTER CHE + 0x0428: 0x00f6, # CYRILLIC CAPITAL LETTER SHA + 0x0429: 0x00fa, # CYRILLIC CAPITAL LETTER SHCHA + 0x042a: 0x009f, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x042b: 0x00f2, # CYRILLIC CAPITAL LETTER YERU + 0x042c: 0x00ee, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x042d: 0x00f8, # CYRILLIC CAPITAL LETTER E + 0x042e: 0x009d, # CYRILLIC CAPITAL LETTER YU + 0x042f: 0x00e0, # CYRILLIC CAPITAL LETTER YA + 0x0430: 0x00a0, # CYRILLIC SMALL LETTER A + 0x0431: 0x00a2, # CYRILLIC SMALL LETTER BE + 0x0432: 0x00eb, # CYRILLIC SMALL LETTER VE + 0x0433: 0x00ac, # CYRILLIC SMALL LETTER GHE + 0x0434: 0x00a6, # CYRILLIC SMALL LETTER DE + 0x0435: 0x00a8, # CYRILLIC SMALL LETTER IE + 0x0436: 0x00e9, # CYRILLIC SMALL LETTER ZHE + 0x0437: 0x00f3, # CYRILLIC SMALL LETTER ZE + 0x0438: 0x00b7, # CYRILLIC SMALL LETTER I + 0x0439: 0x00bd, # CYRILLIC SMALL LETTER SHORT I + 0x043a: 0x00c6, # CYRILLIC SMALL LETTER KA + 0x043b: 0x00d0, # CYRILLIC SMALL LETTER EL + 0x043c: 0x00d2, # CYRILLIC SMALL LETTER EM + 0x043d: 0x00d4, # CYRILLIC SMALL LETTER EN + 0x043e: 0x00d6, # CYRILLIC SMALL LETTER O + 0x043f: 0x00d8, # CYRILLIC SMALL LETTER PE + 0x0440: 0x00e1, # CYRILLIC SMALL LETTER ER + 0x0441: 0x00e3, # CYRILLIC SMALL LETTER ES + 0x0442: 0x00e5, # CYRILLIC SMALL LETTER TE + 0x0443: 0x00e7, # CYRILLIC SMALL LETTER U + 0x0444: 0x00aa, # CYRILLIC SMALL LETTER EF + 0x0445: 0x00b5, # CYRILLIC SMALL LETTER HA + 0x0446: 0x00a4, # CYRILLIC SMALL LETTER TSE + 0x0447: 0x00fb, # CYRILLIC SMALL LETTER CHE + 0x0448: 0x00f5, # CYRILLIC SMALL LETTER SHA + 0x0449: 0x00f9, # CYRILLIC SMALL LETTER SHCHA + 0x044a: 0x009e, # CYRILLIC SMALL LETTER HARD SIGN + 0x044b: 0x00f1, # CYRILLIC SMALL LETTER YERU + 0x044c: 0x00ed, # CYRILLIC SMALL LETTER SOFT SIGN + 0x044d: 0x00f7, # CYRILLIC SMALL LETTER E + 0x044e: 0x009c, # CYRILLIC SMALL LETTER YU + 0x044f: 0x00de, # CYRILLIC SMALL LETTER YA + 0x0451: 0x0084, # CYRILLIC SMALL LETTER IO + 0x0452: 0x0080, # CYRILLIC SMALL LETTER DJE + 0x0453: 0x0082, # CYRILLIC SMALL LETTER GJE + 0x0454: 0x0086, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x0455: 0x0088, # CYRILLIC SMALL LETTER DZE + 0x0456: 0x008a, # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + 0x0457: 0x008c, # CYRILLIC SMALL LETTER YI + 0x0458: 0x008e, # CYRILLIC SMALL LETTER JE + 0x0459: 0x0090, # CYRILLIC SMALL LETTER LJE + 0x045a: 0x0092, # CYRILLIC SMALL LETTER NJE + 0x045b: 0x0094, # CYRILLIC SMALL LETTER TSHE + 0x045c: 0x0096, # CYRILLIC SMALL LETTER KJE + 0x045e: 0x0098, # CYRILLIC SMALL LETTER SHORT U + 0x045f: 0x009a, # CYRILLIC SMALL LETTER DZHE + 0x2116: 0x00ef, # NUMERO SIGN + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp856.py b/winvenv/Lib/encodings/cp856.py new file mode 100644 index 0000000..cacbfb2 --- /dev/null +++ b/winvenv/Lib/encodings/cp856.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp856 generated from 'MAPPINGS/VENDORS/MISC/CP856.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp856', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u05d0' # 0x80 -> HEBREW LETTER ALEF + '\u05d1' # 0x81 -> HEBREW LETTER BET + '\u05d2' # 0x82 -> HEBREW LETTER GIMEL + '\u05d3' # 0x83 -> HEBREW LETTER DALET + '\u05d4' # 0x84 -> HEBREW LETTER HE + '\u05d5' # 0x85 -> HEBREW LETTER VAV + '\u05d6' # 0x86 -> HEBREW LETTER ZAYIN + '\u05d7' # 0x87 -> HEBREW LETTER HET + '\u05d8' # 0x88 -> HEBREW LETTER TET + '\u05d9' # 0x89 -> HEBREW LETTER YOD + '\u05da' # 0x8A -> HEBREW LETTER FINAL KAF + '\u05db' # 0x8B -> HEBREW LETTER KAF + '\u05dc' # 0x8C -> HEBREW LETTER LAMED + '\u05dd' # 0x8D -> HEBREW LETTER FINAL MEM + '\u05de' # 0x8E -> HEBREW LETTER MEM + '\u05df' # 0x8F -> HEBREW LETTER FINAL NUN + '\u05e0' # 0x90 -> HEBREW LETTER NUN + '\u05e1' # 0x91 -> HEBREW LETTER SAMEKH + '\u05e2' # 0x92 -> HEBREW LETTER AYIN + '\u05e3' # 0x93 -> HEBREW LETTER FINAL PE + '\u05e4' # 0x94 -> HEBREW LETTER PE + '\u05e5' # 0x95 -> HEBREW LETTER FINAL TSADI + '\u05e6' # 0x96 -> HEBREW LETTER TSADI + '\u05e7' # 0x97 -> HEBREW LETTER QOF + '\u05e8' # 0x98 -> HEBREW LETTER RESH + '\u05e9' # 0x99 -> HEBREW LETTER SHIN + '\u05ea' # 0x9A -> HEBREW LETTER TAV + '\ufffe' # 0x9B -> UNDEFINED + '\xa3' # 0x9C -> POUND SIGN + '\ufffe' # 0x9D -> UNDEFINED + '\xd7' # 0x9E -> MULTIPLICATION SIGN + '\ufffe' # 0x9F -> UNDEFINED + '\ufffe' # 0xA0 -> UNDEFINED + '\ufffe' # 0xA1 -> UNDEFINED + '\ufffe' # 0xA2 -> UNDEFINED + '\ufffe' # 0xA3 -> UNDEFINED + '\ufffe' # 0xA4 -> UNDEFINED + '\ufffe' # 0xA5 -> UNDEFINED + '\ufffe' # 0xA6 -> UNDEFINED + '\ufffe' # 0xA7 -> UNDEFINED + '\ufffe' # 0xA8 -> UNDEFINED + '\xae' # 0xA9 -> REGISTERED SIGN + '\xac' # 0xAA -> NOT SIGN + '\xbd' # 0xAB -> VULGAR FRACTION ONE HALF + '\xbc' # 0xAC -> VULGAR FRACTION ONE QUARTER + '\ufffe' # 0xAD -> UNDEFINED + '\xab' # 0xAE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xAF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0xB0 -> LIGHT SHADE + '\u2592' # 0xB1 -> MEDIUM SHADE + '\u2593' # 0xB2 -> DARK SHADE + '\u2502' # 0xB3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0xB4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\ufffe' # 0xB5 -> UNDEFINED + '\ufffe' # 0xB6 -> UNDEFINED + '\ufffe' # 0xB7 -> UNDEFINED + '\xa9' # 0xB8 -> COPYRIGHT SIGN + '\u2563' # 0xB9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0xBA -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0xBB -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0xBC -> BOX DRAWINGS DOUBLE UP AND LEFT + '\xa2' # 0xBD -> CENT SIGN + '\xa5' # 0xBE -> YEN SIGN + '\u2510' # 0xBF -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0xC0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0xC1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0xC2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0xC3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0xC4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0xC5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\ufffe' # 0xC6 -> UNDEFINED + '\ufffe' # 0xC7 -> UNDEFINED + '\u255a' # 0xC8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0xC9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0xCA -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0xCB -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0xCC -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0xCD -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0xCE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa4' # 0xCF -> CURRENCY SIGN + '\ufffe' # 0xD0 -> UNDEFINED + '\ufffe' # 0xD1 -> UNDEFINED + '\ufffe' # 0xD2 -> UNDEFINED + '\ufffe' # 0xD3 -> UNDEFINEDS + '\ufffe' # 0xD4 -> UNDEFINED + '\ufffe' # 0xD5 -> UNDEFINED + '\ufffe' # 0xD6 -> UNDEFINEDE + '\ufffe' # 0xD7 -> UNDEFINED + '\ufffe' # 0xD8 -> UNDEFINED + '\u2518' # 0xD9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0xDA -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0xDB -> FULL BLOCK + '\u2584' # 0xDC -> LOWER HALF BLOCK + '\xa6' # 0xDD -> BROKEN BAR + '\ufffe' # 0xDE -> UNDEFINED + '\u2580' # 0xDF -> UPPER HALF BLOCK + '\ufffe' # 0xE0 -> UNDEFINED + '\ufffe' # 0xE1 -> UNDEFINED + '\ufffe' # 0xE2 -> UNDEFINED + '\ufffe' # 0xE3 -> UNDEFINED + '\ufffe' # 0xE4 -> UNDEFINED + '\ufffe' # 0xE5 -> UNDEFINED + '\xb5' # 0xE6 -> MICRO SIGN + '\ufffe' # 0xE7 -> UNDEFINED + '\ufffe' # 0xE8 -> UNDEFINED + '\ufffe' # 0xE9 -> UNDEFINED + '\ufffe' # 0xEA -> UNDEFINED + '\ufffe' # 0xEB -> UNDEFINED + '\ufffe' # 0xEC -> UNDEFINED + '\ufffe' # 0xED -> UNDEFINED + '\xaf' # 0xEE -> MACRON + '\xb4' # 0xEF -> ACUTE ACCENT + '\xad' # 0xF0 -> SOFT HYPHEN + '\xb1' # 0xF1 -> PLUS-MINUS SIGN + '\u2017' # 0xF2 -> DOUBLE LOW LINE + '\xbe' # 0xF3 -> VULGAR FRACTION THREE QUARTERS + '\xb6' # 0xF4 -> PILCROW SIGN + '\xa7' # 0xF5 -> SECTION SIGN + '\xf7' # 0xF6 -> DIVISION SIGN + '\xb8' # 0xF7 -> CEDILLA + '\xb0' # 0xF8 -> DEGREE SIGN + '\xa8' # 0xF9 -> DIAERESIS + '\xb7' # 0xFA -> MIDDLE DOT + '\xb9' # 0xFB -> SUPERSCRIPT ONE + '\xb3' # 0xFC -> SUPERSCRIPT THREE + '\xb2' # 0xFD -> SUPERSCRIPT TWO + '\u25a0' # 0xFE -> BLACK SQUARE + '\xa0' # 0xFF -> NO-BREAK SPACE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp857.py b/winvenv/Lib/encodings/cp857.py new file mode 100644 index 0000000..741b059 --- /dev/null +++ b/winvenv/Lib/encodings/cp857.py @@ -0,0 +1,694 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP857.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp857', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x0131, # LATIN SMALL LETTER DOTLESS I + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x0130, # LATIN CAPITAL LETTER I WITH DOT ABOVE + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x015e, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x009f: 0x015f, # LATIN SMALL LETTER S WITH CEDILLA + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x011e, # LATIN CAPITAL LETTER G WITH BREVE + 0x00a7: 0x011f, # LATIN SMALL LETTER G WITH BREVE + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00b6: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00b7: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00b8: 0x00a9, # COPYRIGHT SIGN + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x00a2, # CENT SIGN + 0x00be: 0x00a5, # YEN SIGN + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x00c7: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00d1: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00d2: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00d3: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00d4: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00d5: None, # UNDEFINED + 0x00d6: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d7: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d8: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x00a6, # BROKEN BAR + 0x00de: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e3: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: None, # UNDEFINED + 0x00e8: 0x00d7, # MULTIPLICATION SIGN + 0x00e9: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ea: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00eb: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00ed: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x00ee: 0x00af, # MACRON + 0x00ef: 0x00b4, # ACUTE ACCENT + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: None, # UNDEFINED + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x00b8, # CEDILLA + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\u0131' # 0x008d -> LATIN SMALL LETTER DOTLESS I + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\u0130' # 0x0098 -> LATIN CAPITAL LETTER I WITH DOT ABOVE + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + '\xa3' # 0x009c -> POUND SIGN + '\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + '\u015e' # 0x009e -> LATIN CAPITAL LETTER S WITH CEDILLA + '\u015f' # 0x009f -> LATIN SMALL LETTER S WITH CEDILLA + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\u011e' # 0x00a6 -> LATIN CAPITAL LETTER G WITH BREVE + '\u011f' # 0x00a7 -> LATIN SMALL LETTER G WITH BREVE + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\xae' # 0x00a9 -> REGISTERED SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc0' # 0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xa9' # 0x00b8 -> COPYRIGHT SIGN + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\xa2' # 0x00bd -> CENT SIGN + '\xa5' # 0x00be -> YEN SIGN + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\xe3' # 0x00c6 -> LATIN SMALL LETTER A WITH TILDE + '\xc3' # 0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa4' # 0x00cf -> CURRENCY SIGN + '\xba' # 0x00d0 -> MASCULINE ORDINAL INDICATOR + '\xaa' # 0x00d1 -> FEMININE ORDINAL INDICATOR + '\xca' # 0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE + '\ufffe' # 0x00d5 -> UNDEFINED + '\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\xa6' # 0x00dd -> BROKEN BAR + '\xcc' # 0x00de -> LATIN CAPITAL LETTER I WITH GRAVE + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd2' # 0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + '\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xb5' # 0x00e6 -> MICRO SIGN + '\ufffe' # 0x00e7 -> UNDEFINED + '\xd7' # 0x00e8 -> MULTIPLICATION SIGN + '\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE + '\xec' # 0x00ec -> LATIN SMALL LETTER I WITH GRAVE + '\xff' # 0x00ed -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xaf' # 0x00ee -> MACRON + '\xb4' # 0x00ef -> ACUTE ACCENT + '\xad' # 0x00f0 -> SOFT HYPHEN + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\ufffe' # 0x00f2 -> UNDEFINED + '\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + '\xb6' # 0x00f4 -> PILCROW SIGN + '\xa7' # 0x00f5 -> SECTION SIGN + '\xf7' # 0x00f6 -> DIVISION SIGN + '\xb8' # 0x00f7 -> CEDILLA + '\xb0' # 0x00f8 -> DEGREE SIGN + '\xa8' # 0x00f9 -> DIAERESIS + '\xb7' # 0x00fa -> MIDDLE DOT + '\xb9' # 0x00fb -> SUPERSCRIPT ONE + '\xb3' # 0x00fc -> SUPERSCRIPT THREE + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x00bd, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a5: 0x00be, # YEN SIGN + 0x00a6: 0x00dd, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x00b8, # COPYRIGHT SIGN + 0x00aa: 0x00d1, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00af: 0x00ee, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00f7, # CEDILLA + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00ba: 0x00d0, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x00b7, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00c7, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00d4, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00d2, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00de, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00d8, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00e3, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x00e8, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00eb, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00ea, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00c6, # LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00ff: 0x00ed, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x011e: 0x00a6, # LATIN CAPITAL LETTER G WITH BREVE + 0x011f: 0x00a7, # LATIN SMALL LETTER G WITH BREVE + 0x0130: 0x0098, # LATIN CAPITAL LETTER I WITH DOT ABOVE + 0x0131: 0x008d, # LATIN SMALL LETTER DOTLESS I + 0x015e: 0x009e, # LATIN CAPITAL LETTER S WITH CEDILLA + 0x015f: 0x009f, # LATIN SMALL LETTER S WITH CEDILLA + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp858.py b/winvenv/Lib/encodings/cp858.py new file mode 100644 index 0000000..7579f52 --- /dev/null +++ b/winvenv/Lib/encodings/cp858.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec for CP858, modified from cp850. + +""" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp858', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x00d7, # MULTIPLICATION SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00ae, # REGISTERED SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00b6: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00b7: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00b8: 0x00a9, # COPYRIGHT SIGN + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x00a2, # CENT SIGN + 0x00be: 0x00a5, # YEN SIGN + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x00c7: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x00a4, # CURRENCY SIGN + 0x00d0: 0x00f0, # LATIN SMALL LETTER ETH + 0x00d1: 0x00d0, # LATIN CAPITAL LETTER ETH + 0x00d2: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00d3: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00d4: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00d5: 0x20ac, # EURO SIGN + 0x00d6: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d7: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00d8: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x00a6, # BROKEN BAR + 0x00de: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00e3: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00e4: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x00e5: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x00fe, # LATIN SMALL LETTER THORN + 0x00e8: 0x00de, # LATIN CAPITAL LETTER THORN + 0x00e9: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00ea: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00eb: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00ec: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x00ed: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00ee: 0x00af, # MACRON + 0x00ef: 0x00b4, # ACUTE ACCENT + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2017, # DOUBLE LOW LINE + 0x00f3: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00f4: 0x00b6, # PILCROW SIGN + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x00b8, # CEDILLA + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x00b9, # SUPERSCRIPT ONE + 0x00fc: 0x00b3, # SUPERSCRIPT THREE + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + '\xa3' # 0x009c -> POUND SIGN + '\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + '\xd7' # 0x009e -> MULTIPLICATION SIGN + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + '\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\xae' # 0x00a9 -> REGISTERED SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\xc1' # 0x00b5 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0x00b6 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc0' # 0x00b7 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xa9' # 0x00b8 -> COPYRIGHT SIGN + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\xa2' # 0x00bd -> CENT SIGN + '\xa5' # 0x00be -> YEN SIGN + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\xe3' # 0x00c6 -> LATIN SMALL LETTER A WITH TILDE + '\xc3' # 0x00c7 -> LATIN CAPITAL LETTER A WITH TILDE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa4' # 0x00cf -> CURRENCY SIGN + '\xf0' # 0x00d0 -> LATIN SMALL LETTER ETH + '\xd0' # 0x00d1 -> LATIN CAPITAL LETTER ETH + '\xca' # 0x00d2 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0x00d3 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0x00d4 -> LATIN CAPITAL LETTER E WITH GRAVE + '\u20ac' # 0x00d5 -> EURO SIGN + '\xcd' # 0x00d6 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0x00d7 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0x00d8 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\xa6' # 0x00dd -> BROKEN BAR + '\xcc' # 0x00de -> LATIN CAPITAL LETTER I WITH GRAVE + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\xd3' # 0x00e0 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\xd4' # 0x00e2 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd2' # 0x00e3 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xf5' # 0x00e4 -> LATIN SMALL LETTER O WITH TILDE + '\xd5' # 0x00e5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xb5' # 0x00e6 -> MICRO SIGN + '\xfe' # 0x00e7 -> LATIN SMALL LETTER THORN + '\xde' # 0x00e8 -> LATIN CAPITAL LETTER THORN + '\xda' # 0x00e9 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0x00ea -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0x00eb -> LATIN CAPITAL LETTER U WITH GRAVE + '\xfd' # 0x00ec -> LATIN SMALL LETTER Y WITH ACUTE + '\xdd' # 0x00ed -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xaf' # 0x00ee -> MACRON + '\xb4' # 0x00ef -> ACUTE ACCENT + '\xad' # 0x00f0 -> SOFT HYPHEN + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2017' # 0x00f2 -> DOUBLE LOW LINE + '\xbe' # 0x00f3 -> VULGAR FRACTION THREE QUARTERS + '\xb6' # 0x00f4 -> PILCROW SIGN + '\xa7' # 0x00f5 -> SECTION SIGN + '\xf7' # 0x00f6 -> DIVISION SIGN + '\xb8' # 0x00f7 -> CEDILLA + '\xb0' # 0x00f8 -> DEGREE SIGN + '\xa8' # 0x00f9 -> DIAERESIS + '\xb7' # 0x00fa -> MIDDLE DOT + '\xb9' # 0x00fb -> SUPERSCRIPT ONE + '\xb3' # 0x00fc -> SUPERSCRIPT THREE + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x00bd, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00cf, # CURRENCY SIGN + 0x00a5: 0x00be, # YEN SIGN + 0x00a6: 0x00dd, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x00b8, # COPYRIGHT SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00ae: 0x00a9, # REGISTERED SIGN + 0x00af: 0x00ee, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00fc, # SUPERSCRIPT THREE + 0x00b4: 0x00ef, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x00f4, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00f7, # CEDILLA + 0x00b9: 0x00fb, # SUPERSCRIPT ONE + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00f3, # VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x00b7, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00b5, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00b6, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00c7, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00d4, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00d2, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00d3, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00de, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00d6, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00d7, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00d8, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d0: 0x00d1, # LATIN CAPITAL LETTER ETH + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00e3, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00e0, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00e2, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00e5, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x009e, # MULTIPLICATION SIGN + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00eb, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00e9, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00ea, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00ed, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x00e8, # LATIN CAPITAL LETTER THORN + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00c6, # LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f0: 0x00d0, # LATIN SMALL LETTER ETH + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00e4, # LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00ec, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x00e7, # LATIN SMALL LETTER THORN + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x20ac: 0x00d5, # EURO SIGN + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x2017: 0x00f2, # DOUBLE LOW LINE + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp860.py b/winvenv/Lib/encodings/cp860.py new file mode 100644 index 0000000..65903e7 --- /dev/null +++ b/winvenv/Lib/encodings/cp860.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP860.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp860', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e3, # LATIN SMALL LETTER A WITH TILDE + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x008c: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c3, # LATIN CAPITAL LETTER A WITH TILDE + 0x008f: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x0092: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f5, # LATIN SMALL LETTER O WITH TILDE + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00cc, # LATIN CAPITAL LETTER I WITH GRAVE + 0x0099: 0x00d5, # LATIN CAPITAL LETTER O WITH TILDE + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00a2, # CENT SIGN + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x009e: 0x20a7, # PESETA SIGN + 0x009f: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x00d2, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0x0084 -> LATIN SMALL LETTER A WITH TILDE + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xc1' # 0x0086 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xca' # 0x0089 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xcd' # 0x008b -> LATIN CAPITAL LETTER I WITH ACUTE + '\xd4' # 0x008c -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + '\xc3' # 0x008e -> LATIN CAPITAL LETTER A WITH TILDE + '\xc2' # 0x008f -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xc0' # 0x0091 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc8' # 0x0092 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0x0094 -> LATIN SMALL LETTER O WITH TILDE + '\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + '\xda' # 0x0096 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\xcc' # 0x0098 -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd5' # 0x0099 -> LATIN CAPITAL LETTER O WITH TILDE + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xa2' # 0x009b -> CENT SIGN + '\xa3' # 0x009c -> POUND SIGN + '\xd9' # 0x009d -> LATIN CAPITAL LETTER U WITH GRAVE + '\u20a7' # 0x009e -> PESETA SIGN + '\xd3' # 0x009f -> LATIN CAPITAL LETTER O WITH ACUTE + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + '\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\xd2' # 0x00a9 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + '\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + '\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + '\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + '\xb5' # 0x00e6 -> MICRO SIGN + '\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + '\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + '\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + '\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + '\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + '\u221e' # 0x00ec -> INFINITY + '\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + '\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + '\u2229' # 0x00ef -> INTERSECTION + '\u2261' # 0x00f0 -> IDENTICAL TO + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u2320' # 0x00f4 -> TOP HALF INTEGRAL + '\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c0: 0x0091, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x0086, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x008f, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x008e, # LATIN CAPITAL LETTER A WITH TILDE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x0092, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x0089, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cc: 0x0098, # LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x008b, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00a9, # LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x009f, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x008c, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x0099, # LATIN CAPITAL LETTER O WITH TILDE + 0x00d9: 0x009d, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x0096, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x0084, # LATIN SMALL LETTER A WITH TILDE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x0094, # LATIN SMALL LETTER O WITH TILDE + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp861.py b/winvenv/Lib/encodings/cp861.py new file mode 100644 index 0000000..860a05f --- /dev/null +++ b/winvenv/Lib/encodings/cp861.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP861.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp861', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00d0, # LATIN CAPITAL LETTER ETH + 0x008c: 0x00f0, # LATIN SMALL LETTER ETH + 0x008d: 0x00de, # LATIN CAPITAL LETTER THORN + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00fe, # LATIN SMALL LETTER THORN + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00dd, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x0098: 0x00fd, # LATIN SMALL LETTER Y WITH ACUTE + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x20a7, # PESETA SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00c1, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00a5: 0x00cd, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00a6: 0x00d3, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00a7: 0x00da, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x2310, # REVERSED NOT SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xd0' # 0x008b -> LATIN CAPITAL LETTER ETH + '\xf0' # 0x008c -> LATIN SMALL LETTER ETH + '\xde' # 0x008d -> LATIN CAPITAL LETTER THORN + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xfe' # 0x0095 -> LATIN SMALL LETTER THORN + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xdd' # 0x0097 -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xfd' # 0x0098 -> LATIN SMALL LETTER Y WITH ACUTE + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + '\xa3' # 0x009c -> POUND SIGN + '\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + '\u20a7' # 0x009e -> PESETA SIGN + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xc1' # 0x00a4 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xcd' # 0x00a5 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xd3' # 0x00a6 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xda' # 0x00a7 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\u2310' # 0x00a9 -> REVERSED NOT SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + '\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + '\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + '\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + '\xb5' # 0x00e6 -> MICRO SIGN + '\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + '\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + '\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + '\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + '\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + '\u221e' # 0x00ec -> INFINITY + '\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + '\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + '\u2229' # 0x00ef -> INTERSECTION + '\u2261' # 0x00f0 -> IDENTICAL TO + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u2320' # 0x00f4 -> TOP HALF INTEGRAL + '\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a3: 0x009c, # POUND SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c1: 0x00a4, # LATIN CAPITAL LETTER A WITH ACUTE + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00cd: 0x00a5, # LATIN CAPITAL LETTER I WITH ACUTE + 0x00d0: 0x008b, # LATIN CAPITAL LETTER ETH + 0x00d3: 0x00a6, # LATIN CAPITAL LETTER O WITH ACUTE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00da: 0x00a7, # LATIN CAPITAL LETTER U WITH ACUTE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x0097, # LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x008d, # LATIN CAPITAL LETTER THORN + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00f0: 0x008c, # LATIN SMALL LETTER ETH + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x0098, # LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x0095, # LATIN SMALL LETTER THORN + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp862.py b/winvenv/Lib/encodings/cp862.py new file mode 100644 index 0000000..3df22f9 --- /dev/null +++ b/winvenv/Lib/encodings/cp862.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP862.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp862', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x05d0, # HEBREW LETTER ALEF + 0x0081: 0x05d1, # HEBREW LETTER BET + 0x0082: 0x05d2, # HEBREW LETTER GIMEL + 0x0083: 0x05d3, # HEBREW LETTER DALET + 0x0084: 0x05d4, # HEBREW LETTER HE + 0x0085: 0x05d5, # HEBREW LETTER VAV + 0x0086: 0x05d6, # HEBREW LETTER ZAYIN + 0x0087: 0x05d7, # HEBREW LETTER HET + 0x0088: 0x05d8, # HEBREW LETTER TET + 0x0089: 0x05d9, # HEBREW LETTER YOD + 0x008a: 0x05da, # HEBREW LETTER FINAL KAF + 0x008b: 0x05db, # HEBREW LETTER KAF + 0x008c: 0x05dc, # HEBREW LETTER LAMED + 0x008d: 0x05dd, # HEBREW LETTER FINAL MEM + 0x008e: 0x05de, # HEBREW LETTER MEM + 0x008f: 0x05df, # HEBREW LETTER FINAL NUN + 0x0090: 0x05e0, # HEBREW LETTER NUN + 0x0091: 0x05e1, # HEBREW LETTER SAMEKH + 0x0092: 0x05e2, # HEBREW LETTER AYIN + 0x0093: 0x05e3, # HEBREW LETTER FINAL PE + 0x0094: 0x05e4, # HEBREW LETTER PE + 0x0095: 0x05e5, # HEBREW LETTER FINAL TSADI + 0x0096: 0x05e6, # HEBREW LETTER TSADI + 0x0097: 0x05e7, # HEBREW LETTER QOF + 0x0098: 0x05e8, # HEBREW LETTER RESH + 0x0099: 0x05e9, # HEBREW LETTER SHIN + 0x009a: 0x05ea, # HEBREW LETTER TAV + 0x009b: 0x00a2, # CENT SIGN + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00a5, # YEN SIGN + 0x009e: 0x20a7, # PESETA SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x2310, # REVERSED NOT SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\u05d0' # 0x0080 -> HEBREW LETTER ALEF + '\u05d1' # 0x0081 -> HEBREW LETTER BET + '\u05d2' # 0x0082 -> HEBREW LETTER GIMEL + '\u05d3' # 0x0083 -> HEBREW LETTER DALET + '\u05d4' # 0x0084 -> HEBREW LETTER HE + '\u05d5' # 0x0085 -> HEBREW LETTER VAV + '\u05d6' # 0x0086 -> HEBREW LETTER ZAYIN + '\u05d7' # 0x0087 -> HEBREW LETTER HET + '\u05d8' # 0x0088 -> HEBREW LETTER TET + '\u05d9' # 0x0089 -> HEBREW LETTER YOD + '\u05da' # 0x008a -> HEBREW LETTER FINAL KAF + '\u05db' # 0x008b -> HEBREW LETTER KAF + '\u05dc' # 0x008c -> HEBREW LETTER LAMED + '\u05dd' # 0x008d -> HEBREW LETTER FINAL MEM + '\u05de' # 0x008e -> HEBREW LETTER MEM + '\u05df' # 0x008f -> HEBREW LETTER FINAL NUN + '\u05e0' # 0x0090 -> HEBREW LETTER NUN + '\u05e1' # 0x0091 -> HEBREW LETTER SAMEKH + '\u05e2' # 0x0092 -> HEBREW LETTER AYIN + '\u05e3' # 0x0093 -> HEBREW LETTER FINAL PE + '\u05e4' # 0x0094 -> HEBREW LETTER PE + '\u05e5' # 0x0095 -> HEBREW LETTER FINAL TSADI + '\u05e6' # 0x0096 -> HEBREW LETTER TSADI + '\u05e7' # 0x0097 -> HEBREW LETTER QOF + '\u05e8' # 0x0098 -> HEBREW LETTER RESH + '\u05e9' # 0x0099 -> HEBREW LETTER SHIN + '\u05ea' # 0x009a -> HEBREW LETTER TAV + '\xa2' # 0x009b -> CENT SIGN + '\xa3' # 0x009c -> POUND SIGN + '\xa5' # 0x009d -> YEN SIGN + '\u20a7' # 0x009e -> PESETA SIGN + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + '\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\u2310' # 0x00a9 -> REVERSED NOT SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S (GERMAN) + '\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + '\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + '\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + '\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + '\xb5' # 0x00e6 -> MICRO SIGN + '\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + '\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + '\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + '\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + '\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + '\u221e' # 0x00ec -> INFINITY + '\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + '\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + '\u2229' # 0x00ef -> INTERSECTION + '\u2261' # 0x00f0 -> IDENTICAL TO + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u2320' # 0x00f4 -> TOP HALF INTEGRAL + '\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a5: 0x009d, # YEN SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S (GERMAN) + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x05d0: 0x0080, # HEBREW LETTER ALEF + 0x05d1: 0x0081, # HEBREW LETTER BET + 0x05d2: 0x0082, # HEBREW LETTER GIMEL + 0x05d3: 0x0083, # HEBREW LETTER DALET + 0x05d4: 0x0084, # HEBREW LETTER HE + 0x05d5: 0x0085, # HEBREW LETTER VAV + 0x05d6: 0x0086, # HEBREW LETTER ZAYIN + 0x05d7: 0x0087, # HEBREW LETTER HET + 0x05d8: 0x0088, # HEBREW LETTER TET + 0x05d9: 0x0089, # HEBREW LETTER YOD + 0x05da: 0x008a, # HEBREW LETTER FINAL KAF + 0x05db: 0x008b, # HEBREW LETTER KAF + 0x05dc: 0x008c, # HEBREW LETTER LAMED + 0x05dd: 0x008d, # HEBREW LETTER FINAL MEM + 0x05de: 0x008e, # HEBREW LETTER MEM + 0x05df: 0x008f, # HEBREW LETTER FINAL NUN + 0x05e0: 0x0090, # HEBREW LETTER NUN + 0x05e1: 0x0091, # HEBREW LETTER SAMEKH + 0x05e2: 0x0092, # HEBREW LETTER AYIN + 0x05e3: 0x0093, # HEBREW LETTER FINAL PE + 0x05e4: 0x0094, # HEBREW LETTER PE + 0x05e5: 0x0095, # HEBREW LETTER FINAL TSADI + 0x05e6: 0x0096, # HEBREW LETTER TSADI + 0x05e7: 0x0097, # HEBREW LETTER QOF + 0x05e8: 0x0098, # HEBREW LETTER RESH + 0x05e9: 0x0099, # HEBREW LETTER SHIN + 0x05ea: 0x009a, # HEBREW LETTER TAV + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp863.py b/winvenv/Lib/encodings/cp863.py new file mode 100644 index 0000000..764180b --- /dev/null +++ b/winvenv/Lib/encodings/cp863.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP863.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp863', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00c2, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00b6, # PILCROW SIGN + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x2017, # DOUBLE LOW LINE + 0x008e: 0x00c0, # LATIN CAPITAL LETTER A WITH GRAVE + 0x008f: 0x00a7, # SECTION SIGN + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00c8, # LATIN CAPITAL LETTER E WITH GRAVE + 0x0092: 0x00ca, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00cb, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x0095: 0x00cf, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00a4, # CURRENCY SIGN + 0x0099: 0x00d4, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00a2, # CENT SIGN + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d9, # LATIN CAPITAL LETTER U WITH GRAVE + 0x009e: 0x00db, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00a6, # BROKEN BAR + 0x00a1: 0x00b4, # ACUTE ACCENT + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00a8, # DIAERESIS + 0x00a5: 0x00b8, # CEDILLA + 0x00a6: 0x00b3, # SUPERSCRIPT THREE + 0x00a7: 0x00af, # MACRON + 0x00a8: 0x00ce, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00a9: 0x2310, # REVERSED NOT SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00be, # VULGAR FRACTION THREE QUARTERS + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xc2' # 0x0084 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xb6' # 0x0086 -> PILCROW SIGN + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\u2017' # 0x008d -> DOUBLE LOW LINE + '\xc0' # 0x008e -> LATIN CAPITAL LETTER A WITH GRAVE + '\xa7' # 0x008f -> SECTION SIGN + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xc8' # 0x0091 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xca' # 0x0092 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xcb' # 0x0094 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcf' # 0x0095 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\xa4' # 0x0098 -> CURRENCY SIGN + '\xd4' # 0x0099 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xa2' # 0x009b -> CENT SIGN + '\xa3' # 0x009c -> POUND SIGN + '\xd9' # 0x009d -> LATIN CAPITAL LETTER U WITH GRAVE + '\xdb' # 0x009e -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xa6' # 0x00a0 -> BROKEN BAR + '\xb4' # 0x00a1 -> ACUTE ACCENT + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xa8' # 0x00a4 -> DIAERESIS + '\xb8' # 0x00a5 -> CEDILLA + '\xb3' # 0x00a6 -> SUPERSCRIPT THREE + '\xaf' # 0x00a7 -> MACRON + '\xce' # 0x00a8 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\u2310' # 0x00a9 -> REVERSED NOT SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xbe' # 0x00ad -> VULGAR FRACTION THREE QUARTERS + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + '\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + '\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + '\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + '\xb5' # 0x00e6 -> MICRO SIGN + '\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + '\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + '\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + '\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + '\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + '\u221e' # 0x00ec -> INFINITY + '\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + '\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + '\u2229' # 0x00ef -> INTERSECTION + '\u2261' # 0x00f0 -> IDENTICAL TO + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u2320' # 0x00f4 -> TOP HALF INTEGRAL + '\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a2: 0x009b, # CENT SIGN + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x0098, # CURRENCY SIGN + 0x00a6: 0x00a0, # BROKEN BAR + 0x00a7: 0x008f, # SECTION SIGN + 0x00a8: 0x00a4, # DIAERESIS + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00af: 0x00a7, # MACRON + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b3: 0x00a6, # SUPERSCRIPT THREE + 0x00b4: 0x00a1, # ACUTE ACCENT + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b6: 0x0086, # PILCROW SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00b8: 0x00a5, # CEDILLA + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00be: 0x00ad, # VULGAR FRACTION THREE QUARTERS + 0x00c0: 0x008e, # LATIN CAPITAL LETTER A WITH GRAVE + 0x00c2: 0x0084, # LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x0091, # LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x0092, # LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x0094, # LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00ce: 0x00a8, # LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x0095, # LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d4: 0x0099, # LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d9: 0x009d, # LATIN CAPITAL LETTER U WITH GRAVE + 0x00db: 0x009e, # LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x2017: 0x008d, # DOUBLE LOW LINE + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp864.py b/winvenv/Lib/encodings/cp864.py new file mode 100644 index 0000000..53df482 --- /dev/null +++ b/winvenv/Lib/encodings/cp864.py @@ -0,0 +1,690 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP864.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp864', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0025: 0x066a, # ARABIC PERCENT SIGN + 0x0080: 0x00b0, # DEGREE SIGN + 0x0081: 0x00b7, # MIDDLE DOT + 0x0082: 0x2219, # BULLET OPERATOR + 0x0083: 0x221a, # SQUARE ROOT + 0x0084: 0x2592, # MEDIUM SHADE + 0x0085: 0x2500, # FORMS LIGHT HORIZONTAL + 0x0086: 0x2502, # FORMS LIGHT VERTICAL + 0x0087: 0x253c, # FORMS LIGHT VERTICAL AND HORIZONTAL + 0x0088: 0x2524, # FORMS LIGHT VERTICAL AND LEFT + 0x0089: 0x252c, # FORMS LIGHT DOWN AND HORIZONTAL + 0x008a: 0x251c, # FORMS LIGHT VERTICAL AND RIGHT + 0x008b: 0x2534, # FORMS LIGHT UP AND HORIZONTAL + 0x008c: 0x2510, # FORMS LIGHT DOWN AND LEFT + 0x008d: 0x250c, # FORMS LIGHT DOWN AND RIGHT + 0x008e: 0x2514, # FORMS LIGHT UP AND RIGHT + 0x008f: 0x2518, # FORMS LIGHT UP AND LEFT + 0x0090: 0x03b2, # GREEK SMALL BETA + 0x0091: 0x221e, # INFINITY + 0x0092: 0x03c6, # GREEK SMALL PHI + 0x0093: 0x00b1, # PLUS-OR-MINUS SIGN + 0x0094: 0x00bd, # FRACTION 1/2 + 0x0095: 0x00bc, # FRACTION 1/4 + 0x0096: 0x2248, # ALMOST EQUAL TO + 0x0097: 0x00ab, # LEFT POINTING GUILLEMET + 0x0098: 0x00bb, # RIGHT POINTING GUILLEMET + 0x0099: 0xfef7, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + 0x009a: 0xfef8, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM + 0x009b: None, # UNDEFINED + 0x009c: None, # UNDEFINED + 0x009d: 0xfefb, # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + 0x009e: 0xfefc, # ARABIC LIGATURE LAM WITH ALEF FINAL FORM + 0x009f: None, # UNDEFINED + 0x00a1: 0x00ad, # SOFT HYPHEN + 0x00a2: 0xfe82, # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM + 0x00a5: 0xfe84, # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM + 0x00a6: None, # UNDEFINED + 0x00a7: None, # UNDEFINED + 0x00a8: 0xfe8e, # ARABIC LETTER ALEF FINAL FORM + 0x00a9: 0xfe8f, # ARABIC LETTER BEH ISOLATED FORM + 0x00aa: 0xfe95, # ARABIC LETTER TEH ISOLATED FORM + 0x00ab: 0xfe99, # ARABIC LETTER THEH ISOLATED FORM + 0x00ac: 0x060c, # ARABIC COMMA + 0x00ad: 0xfe9d, # ARABIC LETTER JEEM ISOLATED FORM + 0x00ae: 0xfea1, # ARABIC LETTER HAH ISOLATED FORM + 0x00af: 0xfea5, # ARABIC LETTER KHAH ISOLATED FORM + 0x00b0: 0x0660, # ARABIC-INDIC DIGIT ZERO + 0x00b1: 0x0661, # ARABIC-INDIC DIGIT ONE + 0x00b2: 0x0662, # ARABIC-INDIC DIGIT TWO + 0x00b3: 0x0663, # ARABIC-INDIC DIGIT THREE + 0x00b4: 0x0664, # ARABIC-INDIC DIGIT FOUR + 0x00b5: 0x0665, # ARABIC-INDIC DIGIT FIVE + 0x00b6: 0x0666, # ARABIC-INDIC DIGIT SIX + 0x00b7: 0x0667, # ARABIC-INDIC DIGIT SEVEN + 0x00b8: 0x0668, # ARABIC-INDIC DIGIT EIGHT + 0x00b9: 0x0669, # ARABIC-INDIC DIGIT NINE + 0x00ba: 0xfed1, # ARABIC LETTER FEH ISOLATED FORM + 0x00bb: 0x061b, # ARABIC SEMICOLON + 0x00bc: 0xfeb1, # ARABIC LETTER SEEN ISOLATED FORM + 0x00bd: 0xfeb5, # ARABIC LETTER SHEEN ISOLATED FORM + 0x00be: 0xfeb9, # ARABIC LETTER SAD ISOLATED FORM + 0x00bf: 0x061f, # ARABIC QUESTION MARK + 0x00c0: 0x00a2, # CENT SIGN + 0x00c1: 0xfe80, # ARABIC LETTER HAMZA ISOLATED FORM + 0x00c2: 0xfe81, # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + 0x00c3: 0xfe83, # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM + 0x00c4: 0xfe85, # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + 0x00c5: 0xfeca, # ARABIC LETTER AIN FINAL FORM + 0x00c6: 0xfe8b, # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + 0x00c7: 0xfe8d, # ARABIC LETTER ALEF ISOLATED FORM + 0x00c8: 0xfe91, # ARABIC LETTER BEH INITIAL FORM + 0x00c9: 0xfe93, # ARABIC LETTER TEH MARBUTA ISOLATED FORM + 0x00ca: 0xfe97, # ARABIC LETTER TEH INITIAL FORM + 0x00cb: 0xfe9b, # ARABIC LETTER THEH INITIAL FORM + 0x00cc: 0xfe9f, # ARABIC LETTER JEEM INITIAL FORM + 0x00cd: 0xfea3, # ARABIC LETTER HAH INITIAL FORM + 0x00ce: 0xfea7, # ARABIC LETTER KHAH INITIAL FORM + 0x00cf: 0xfea9, # ARABIC LETTER DAL ISOLATED FORM + 0x00d0: 0xfeab, # ARABIC LETTER THAL ISOLATED FORM + 0x00d1: 0xfead, # ARABIC LETTER REH ISOLATED FORM + 0x00d2: 0xfeaf, # ARABIC LETTER ZAIN ISOLATED FORM + 0x00d3: 0xfeb3, # ARABIC LETTER SEEN INITIAL FORM + 0x00d4: 0xfeb7, # ARABIC LETTER SHEEN INITIAL FORM + 0x00d5: 0xfebb, # ARABIC LETTER SAD INITIAL FORM + 0x00d6: 0xfebf, # ARABIC LETTER DAD INITIAL FORM + 0x00d7: 0xfec1, # ARABIC LETTER TAH ISOLATED FORM + 0x00d8: 0xfec5, # ARABIC LETTER ZAH ISOLATED FORM + 0x00d9: 0xfecb, # ARABIC LETTER AIN INITIAL FORM + 0x00da: 0xfecf, # ARABIC LETTER GHAIN INITIAL FORM + 0x00db: 0x00a6, # BROKEN VERTICAL BAR + 0x00dc: 0x00ac, # NOT SIGN + 0x00dd: 0x00f7, # DIVISION SIGN + 0x00de: 0x00d7, # MULTIPLICATION SIGN + 0x00df: 0xfec9, # ARABIC LETTER AIN ISOLATED FORM + 0x00e0: 0x0640, # ARABIC TATWEEL + 0x00e1: 0xfed3, # ARABIC LETTER FEH INITIAL FORM + 0x00e2: 0xfed7, # ARABIC LETTER QAF INITIAL FORM + 0x00e3: 0xfedb, # ARABIC LETTER KAF INITIAL FORM + 0x00e4: 0xfedf, # ARABIC LETTER LAM INITIAL FORM + 0x00e5: 0xfee3, # ARABIC LETTER MEEM INITIAL FORM + 0x00e6: 0xfee7, # ARABIC LETTER NOON INITIAL FORM + 0x00e7: 0xfeeb, # ARABIC LETTER HEH INITIAL FORM + 0x00e8: 0xfeed, # ARABIC LETTER WAW ISOLATED FORM + 0x00e9: 0xfeef, # ARABIC LETTER ALEF MAKSURA ISOLATED FORM + 0x00ea: 0xfef3, # ARABIC LETTER YEH INITIAL FORM + 0x00eb: 0xfebd, # ARABIC LETTER DAD ISOLATED FORM + 0x00ec: 0xfecc, # ARABIC LETTER AIN MEDIAL FORM + 0x00ed: 0xfece, # ARABIC LETTER GHAIN FINAL FORM + 0x00ee: 0xfecd, # ARABIC LETTER GHAIN ISOLATED FORM + 0x00ef: 0xfee1, # ARABIC LETTER MEEM ISOLATED FORM + 0x00f0: 0xfe7d, # ARABIC SHADDA MEDIAL FORM + 0x00f1: 0x0651, # ARABIC SHADDAH + 0x00f2: 0xfee5, # ARABIC LETTER NOON ISOLATED FORM + 0x00f3: 0xfee9, # ARABIC LETTER HEH ISOLATED FORM + 0x00f4: 0xfeec, # ARABIC LETTER HEH MEDIAL FORM + 0x00f5: 0xfef0, # ARABIC LETTER ALEF MAKSURA FINAL FORM + 0x00f6: 0xfef2, # ARABIC LETTER YEH FINAL FORM + 0x00f7: 0xfed0, # ARABIC LETTER GHAIN MEDIAL FORM + 0x00f8: 0xfed5, # ARABIC LETTER QAF ISOLATED FORM + 0x00f9: 0xfef5, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + 0x00fa: 0xfef6, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM + 0x00fb: 0xfedd, # ARABIC LETTER LAM ISOLATED FORM + 0x00fc: 0xfed9, # ARABIC LETTER KAF ISOLATED FORM + 0x00fd: 0xfef1, # ARABIC LETTER YEH ISOLATED FORM + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: None, # UNDEFINED +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '\u066a' # 0x0025 -> ARABIC PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xb0' # 0x0080 -> DEGREE SIGN + '\xb7' # 0x0081 -> MIDDLE DOT + '\u2219' # 0x0082 -> BULLET OPERATOR + '\u221a' # 0x0083 -> SQUARE ROOT + '\u2592' # 0x0084 -> MEDIUM SHADE + '\u2500' # 0x0085 -> FORMS LIGHT HORIZONTAL + '\u2502' # 0x0086 -> FORMS LIGHT VERTICAL + '\u253c' # 0x0087 -> FORMS LIGHT VERTICAL AND HORIZONTAL + '\u2524' # 0x0088 -> FORMS LIGHT VERTICAL AND LEFT + '\u252c' # 0x0089 -> FORMS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x008a -> FORMS LIGHT VERTICAL AND RIGHT + '\u2534' # 0x008b -> FORMS LIGHT UP AND HORIZONTAL + '\u2510' # 0x008c -> FORMS LIGHT DOWN AND LEFT + '\u250c' # 0x008d -> FORMS LIGHT DOWN AND RIGHT + '\u2514' # 0x008e -> FORMS LIGHT UP AND RIGHT + '\u2518' # 0x008f -> FORMS LIGHT UP AND LEFT + '\u03b2' # 0x0090 -> GREEK SMALL BETA + '\u221e' # 0x0091 -> INFINITY + '\u03c6' # 0x0092 -> GREEK SMALL PHI + '\xb1' # 0x0093 -> PLUS-OR-MINUS SIGN + '\xbd' # 0x0094 -> FRACTION 1/2 + '\xbc' # 0x0095 -> FRACTION 1/4 + '\u2248' # 0x0096 -> ALMOST EQUAL TO + '\xab' # 0x0097 -> LEFT POINTING GUILLEMET + '\xbb' # 0x0098 -> RIGHT POINTING GUILLEMET + '\ufef7' # 0x0099 -> ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + '\ufef8' # 0x009a -> ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM + '\ufffe' # 0x009b -> UNDEFINED + '\ufffe' # 0x009c -> UNDEFINED + '\ufefb' # 0x009d -> ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + '\ufefc' # 0x009e -> ARABIC LIGATURE LAM WITH ALEF FINAL FORM + '\ufffe' # 0x009f -> UNDEFINED + '\xa0' # 0x00a0 -> NON-BREAKING SPACE + '\xad' # 0x00a1 -> SOFT HYPHEN + '\ufe82' # 0x00a2 -> ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM + '\xa3' # 0x00a3 -> POUND SIGN + '\xa4' # 0x00a4 -> CURRENCY SIGN + '\ufe84' # 0x00a5 -> ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM + '\ufffe' # 0x00a6 -> UNDEFINED + '\ufffe' # 0x00a7 -> UNDEFINED + '\ufe8e' # 0x00a8 -> ARABIC LETTER ALEF FINAL FORM + '\ufe8f' # 0x00a9 -> ARABIC LETTER BEH ISOLATED FORM + '\ufe95' # 0x00aa -> ARABIC LETTER TEH ISOLATED FORM + '\ufe99' # 0x00ab -> ARABIC LETTER THEH ISOLATED FORM + '\u060c' # 0x00ac -> ARABIC COMMA + '\ufe9d' # 0x00ad -> ARABIC LETTER JEEM ISOLATED FORM + '\ufea1' # 0x00ae -> ARABIC LETTER HAH ISOLATED FORM + '\ufea5' # 0x00af -> ARABIC LETTER KHAH ISOLATED FORM + '\u0660' # 0x00b0 -> ARABIC-INDIC DIGIT ZERO + '\u0661' # 0x00b1 -> ARABIC-INDIC DIGIT ONE + '\u0662' # 0x00b2 -> ARABIC-INDIC DIGIT TWO + '\u0663' # 0x00b3 -> ARABIC-INDIC DIGIT THREE + '\u0664' # 0x00b4 -> ARABIC-INDIC DIGIT FOUR + '\u0665' # 0x00b5 -> ARABIC-INDIC DIGIT FIVE + '\u0666' # 0x00b6 -> ARABIC-INDIC DIGIT SIX + '\u0667' # 0x00b7 -> ARABIC-INDIC DIGIT SEVEN + '\u0668' # 0x00b8 -> ARABIC-INDIC DIGIT EIGHT + '\u0669' # 0x00b9 -> ARABIC-INDIC DIGIT NINE + '\ufed1' # 0x00ba -> ARABIC LETTER FEH ISOLATED FORM + '\u061b' # 0x00bb -> ARABIC SEMICOLON + '\ufeb1' # 0x00bc -> ARABIC LETTER SEEN ISOLATED FORM + '\ufeb5' # 0x00bd -> ARABIC LETTER SHEEN ISOLATED FORM + '\ufeb9' # 0x00be -> ARABIC LETTER SAD ISOLATED FORM + '\u061f' # 0x00bf -> ARABIC QUESTION MARK + '\xa2' # 0x00c0 -> CENT SIGN + '\ufe80' # 0x00c1 -> ARABIC LETTER HAMZA ISOLATED FORM + '\ufe81' # 0x00c2 -> ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + '\ufe83' # 0x00c3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM + '\ufe85' # 0x00c4 -> ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + '\ufeca' # 0x00c5 -> ARABIC LETTER AIN FINAL FORM + '\ufe8b' # 0x00c6 -> ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + '\ufe8d' # 0x00c7 -> ARABIC LETTER ALEF ISOLATED FORM + '\ufe91' # 0x00c8 -> ARABIC LETTER BEH INITIAL FORM + '\ufe93' # 0x00c9 -> ARABIC LETTER TEH MARBUTA ISOLATED FORM + '\ufe97' # 0x00ca -> ARABIC LETTER TEH INITIAL FORM + '\ufe9b' # 0x00cb -> ARABIC LETTER THEH INITIAL FORM + '\ufe9f' # 0x00cc -> ARABIC LETTER JEEM INITIAL FORM + '\ufea3' # 0x00cd -> ARABIC LETTER HAH INITIAL FORM + '\ufea7' # 0x00ce -> ARABIC LETTER KHAH INITIAL FORM + '\ufea9' # 0x00cf -> ARABIC LETTER DAL ISOLATED FORM + '\ufeab' # 0x00d0 -> ARABIC LETTER THAL ISOLATED FORM + '\ufead' # 0x00d1 -> ARABIC LETTER REH ISOLATED FORM + '\ufeaf' # 0x00d2 -> ARABIC LETTER ZAIN ISOLATED FORM + '\ufeb3' # 0x00d3 -> ARABIC LETTER SEEN INITIAL FORM + '\ufeb7' # 0x00d4 -> ARABIC LETTER SHEEN INITIAL FORM + '\ufebb' # 0x00d5 -> ARABIC LETTER SAD INITIAL FORM + '\ufebf' # 0x00d6 -> ARABIC LETTER DAD INITIAL FORM + '\ufec1' # 0x00d7 -> ARABIC LETTER TAH ISOLATED FORM + '\ufec5' # 0x00d8 -> ARABIC LETTER ZAH ISOLATED FORM + '\ufecb' # 0x00d9 -> ARABIC LETTER AIN INITIAL FORM + '\ufecf' # 0x00da -> ARABIC LETTER GHAIN INITIAL FORM + '\xa6' # 0x00db -> BROKEN VERTICAL BAR + '\xac' # 0x00dc -> NOT SIGN + '\xf7' # 0x00dd -> DIVISION SIGN + '\xd7' # 0x00de -> MULTIPLICATION SIGN + '\ufec9' # 0x00df -> ARABIC LETTER AIN ISOLATED FORM + '\u0640' # 0x00e0 -> ARABIC TATWEEL + '\ufed3' # 0x00e1 -> ARABIC LETTER FEH INITIAL FORM + '\ufed7' # 0x00e2 -> ARABIC LETTER QAF INITIAL FORM + '\ufedb' # 0x00e3 -> ARABIC LETTER KAF INITIAL FORM + '\ufedf' # 0x00e4 -> ARABIC LETTER LAM INITIAL FORM + '\ufee3' # 0x00e5 -> ARABIC LETTER MEEM INITIAL FORM + '\ufee7' # 0x00e6 -> ARABIC LETTER NOON INITIAL FORM + '\ufeeb' # 0x00e7 -> ARABIC LETTER HEH INITIAL FORM + '\ufeed' # 0x00e8 -> ARABIC LETTER WAW ISOLATED FORM + '\ufeef' # 0x00e9 -> ARABIC LETTER ALEF MAKSURA ISOLATED FORM + '\ufef3' # 0x00ea -> ARABIC LETTER YEH INITIAL FORM + '\ufebd' # 0x00eb -> ARABIC LETTER DAD ISOLATED FORM + '\ufecc' # 0x00ec -> ARABIC LETTER AIN MEDIAL FORM + '\ufece' # 0x00ed -> ARABIC LETTER GHAIN FINAL FORM + '\ufecd' # 0x00ee -> ARABIC LETTER GHAIN ISOLATED FORM + '\ufee1' # 0x00ef -> ARABIC LETTER MEEM ISOLATED FORM + '\ufe7d' # 0x00f0 -> ARABIC SHADDA MEDIAL FORM + '\u0651' # 0x00f1 -> ARABIC SHADDAH + '\ufee5' # 0x00f2 -> ARABIC LETTER NOON ISOLATED FORM + '\ufee9' # 0x00f3 -> ARABIC LETTER HEH ISOLATED FORM + '\ufeec' # 0x00f4 -> ARABIC LETTER HEH MEDIAL FORM + '\ufef0' # 0x00f5 -> ARABIC LETTER ALEF MAKSURA FINAL FORM + '\ufef2' # 0x00f6 -> ARABIC LETTER YEH FINAL FORM + '\ufed0' # 0x00f7 -> ARABIC LETTER GHAIN MEDIAL FORM + '\ufed5' # 0x00f8 -> ARABIC LETTER QAF ISOLATED FORM + '\ufef5' # 0x00f9 -> ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + '\ufef6' # 0x00fa -> ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM + '\ufedd' # 0x00fb -> ARABIC LETTER LAM ISOLATED FORM + '\ufed9' # 0x00fc -> ARABIC LETTER KAF ISOLATED FORM + '\ufef1' # 0x00fd -> ARABIC LETTER YEH ISOLATED FORM + '\u25a0' # 0x00fe -> BLACK SQUARE + '\ufffe' # 0x00ff -> UNDEFINED +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00a0, # NON-BREAKING SPACE + 0x00a2: 0x00c0, # CENT SIGN + 0x00a3: 0x00a3, # POUND SIGN + 0x00a4: 0x00a4, # CURRENCY SIGN + 0x00a6: 0x00db, # BROKEN VERTICAL BAR + 0x00ab: 0x0097, # LEFT POINTING GUILLEMET + 0x00ac: 0x00dc, # NOT SIGN + 0x00ad: 0x00a1, # SOFT HYPHEN + 0x00b0: 0x0080, # DEGREE SIGN + 0x00b1: 0x0093, # PLUS-OR-MINUS SIGN + 0x00b7: 0x0081, # MIDDLE DOT + 0x00bb: 0x0098, # RIGHT POINTING GUILLEMET + 0x00bc: 0x0095, # FRACTION 1/4 + 0x00bd: 0x0094, # FRACTION 1/2 + 0x00d7: 0x00de, # MULTIPLICATION SIGN + 0x00f7: 0x00dd, # DIVISION SIGN + 0x03b2: 0x0090, # GREEK SMALL BETA + 0x03c6: 0x0092, # GREEK SMALL PHI + 0x060c: 0x00ac, # ARABIC COMMA + 0x061b: 0x00bb, # ARABIC SEMICOLON + 0x061f: 0x00bf, # ARABIC QUESTION MARK + 0x0640: 0x00e0, # ARABIC TATWEEL + 0x0651: 0x00f1, # ARABIC SHADDAH + 0x0660: 0x00b0, # ARABIC-INDIC DIGIT ZERO + 0x0661: 0x00b1, # ARABIC-INDIC DIGIT ONE + 0x0662: 0x00b2, # ARABIC-INDIC DIGIT TWO + 0x0663: 0x00b3, # ARABIC-INDIC DIGIT THREE + 0x0664: 0x00b4, # ARABIC-INDIC DIGIT FOUR + 0x0665: 0x00b5, # ARABIC-INDIC DIGIT FIVE + 0x0666: 0x00b6, # ARABIC-INDIC DIGIT SIX + 0x0667: 0x00b7, # ARABIC-INDIC DIGIT SEVEN + 0x0668: 0x00b8, # ARABIC-INDIC DIGIT EIGHT + 0x0669: 0x00b9, # ARABIC-INDIC DIGIT NINE + 0x066a: 0x0025, # ARABIC PERCENT SIGN + 0x2219: 0x0082, # BULLET OPERATOR + 0x221a: 0x0083, # SQUARE ROOT + 0x221e: 0x0091, # INFINITY + 0x2248: 0x0096, # ALMOST EQUAL TO + 0x2500: 0x0085, # FORMS LIGHT HORIZONTAL + 0x2502: 0x0086, # FORMS LIGHT VERTICAL + 0x250c: 0x008d, # FORMS LIGHT DOWN AND RIGHT + 0x2510: 0x008c, # FORMS LIGHT DOWN AND LEFT + 0x2514: 0x008e, # FORMS LIGHT UP AND RIGHT + 0x2518: 0x008f, # FORMS LIGHT UP AND LEFT + 0x251c: 0x008a, # FORMS LIGHT VERTICAL AND RIGHT + 0x2524: 0x0088, # FORMS LIGHT VERTICAL AND LEFT + 0x252c: 0x0089, # FORMS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x008b, # FORMS LIGHT UP AND HORIZONTAL + 0x253c: 0x0087, # FORMS LIGHT VERTICAL AND HORIZONTAL + 0x2592: 0x0084, # MEDIUM SHADE + 0x25a0: 0x00fe, # BLACK SQUARE + 0xfe7d: 0x00f0, # ARABIC SHADDA MEDIAL FORM + 0xfe80: 0x00c1, # ARABIC LETTER HAMZA ISOLATED FORM + 0xfe81: 0x00c2, # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM + 0xfe82: 0x00a2, # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM + 0xfe83: 0x00c3, # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM + 0xfe84: 0x00a5, # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM + 0xfe85: 0x00c4, # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM + 0xfe8b: 0x00c6, # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM + 0xfe8d: 0x00c7, # ARABIC LETTER ALEF ISOLATED FORM + 0xfe8e: 0x00a8, # ARABIC LETTER ALEF FINAL FORM + 0xfe8f: 0x00a9, # ARABIC LETTER BEH ISOLATED FORM + 0xfe91: 0x00c8, # ARABIC LETTER BEH INITIAL FORM + 0xfe93: 0x00c9, # ARABIC LETTER TEH MARBUTA ISOLATED FORM + 0xfe95: 0x00aa, # ARABIC LETTER TEH ISOLATED FORM + 0xfe97: 0x00ca, # ARABIC LETTER TEH INITIAL FORM + 0xfe99: 0x00ab, # ARABIC LETTER THEH ISOLATED FORM + 0xfe9b: 0x00cb, # ARABIC LETTER THEH INITIAL FORM + 0xfe9d: 0x00ad, # ARABIC LETTER JEEM ISOLATED FORM + 0xfe9f: 0x00cc, # ARABIC LETTER JEEM INITIAL FORM + 0xfea1: 0x00ae, # ARABIC LETTER HAH ISOLATED FORM + 0xfea3: 0x00cd, # ARABIC LETTER HAH INITIAL FORM + 0xfea5: 0x00af, # ARABIC LETTER KHAH ISOLATED FORM + 0xfea7: 0x00ce, # ARABIC LETTER KHAH INITIAL FORM + 0xfea9: 0x00cf, # ARABIC LETTER DAL ISOLATED FORM + 0xfeab: 0x00d0, # ARABIC LETTER THAL ISOLATED FORM + 0xfead: 0x00d1, # ARABIC LETTER REH ISOLATED FORM + 0xfeaf: 0x00d2, # ARABIC LETTER ZAIN ISOLATED FORM + 0xfeb1: 0x00bc, # ARABIC LETTER SEEN ISOLATED FORM + 0xfeb3: 0x00d3, # ARABIC LETTER SEEN INITIAL FORM + 0xfeb5: 0x00bd, # ARABIC LETTER SHEEN ISOLATED FORM + 0xfeb7: 0x00d4, # ARABIC LETTER SHEEN INITIAL FORM + 0xfeb9: 0x00be, # ARABIC LETTER SAD ISOLATED FORM + 0xfebb: 0x00d5, # ARABIC LETTER SAD INITIAL FORM + 0xfebd: 0x00eb, # ARABIC LETTER DAD ISOLATED FORM + 0xfebf: 0x00d6, # ARABIC LETTER DAD INITIAL FORM + 0xfec1: 0x00d7, # ARABIC LETTER TAH ISOLATED FORM + 0xfec5: 0x00d8, # ARABIC LETTER ZAH ISOLATED FORM + 0xfec9: 0x00df, # ARABIC LETTER AIN ISOLATED FORM + 0xfeca: 0x00c5, # ARABIC LETTER AIN FINAL FORM + 0xfecb: 0x00d9, # ARABIC LETTER AIN INITIAL FORM + 0xfecc: 0x00ec, # ARABIC LETTER AIN MEDIAL FORM + 0xfecd: 0x00ee, # ARABIC LETTER GHAIN ISOLATED FORM + 0xfece: 0x00ed, # ARABIC LETTER GHAIN FINAL FORM + 0xfecf: 0x00da, # ARABIC LETTER GHAIN INITIAL FORM + 0xfed0: 0x00f7, # ARABIC LETTER GHAIN MEDIAL FORM + 0xfed1: 0x00ba, # ARABIC LETTER FEH ISOLATED FORM + 0xfed3: 0x00e1, # ARABIC LETTER FEH INITIAL FORM + 0xfed5: 0x00f8, # ARABIC LETTER QAF ISOLATED FORM + 0xfed7: 0x00e2, # ARABIC LETTER QAF INITIAL FORM + 0xfed9: 0x00fc, # ARABIC LETTER KAF ISOLATED FORM + 0xfedb: 0x00e3, # ARABIC LETTER KAF INITIAL FORM + 0xfedd: 0x00fb, # ARABIC LETTER LAM ISOLATED FORM + 0xfedf: 0x00e4, # ARABIC LETTER LAM INITIAL FORM + 0xfee1: 0x00ef, # ARABIC LETTER MEEM ISOLATED FORM + 0xfee3: 0x00e5, # ARABIC LETTER MEEM INITIAL FORM + 0xfee5: 0x00f2, # ARABIC LETTER NOON ISOLATED FORM + 0xfee7: 0x00e6, # ARABIC LETTER NOON INITIAL FORM + 0xfee9: 0x00f3, # ARABIC LETTER HEH ISOLATED FORM + 0xfeeb: 0x00e7, # ARABIC LETTER HEH INITIAL FORM + 0xfeec: 0x00f4, # ARABIC LETTER HEH MEDIAL FORM + 0xfeed: 0x00e8, # ARABIC LETTER WAW ISOLATED FORM + 0xfeef: 0x00e9, # ARABIC LETTER ALEF MAKSURA ISOLATED FORM + 0xfef0: 0x00f5, # ARABIC LETTER ALEF MAKSURA FINAL FORM + 0xfef1: 0x00fd, # ARABIC LETTER YEH ISOLATED FORM + 0xfef2: 0x00f6, # ARABIC LETTER YEH FINAL FORM + 0xfef3: 0x00ea, # ARABIC LETTER YEH INITIAL FORM + 0xfef5: 0x00f9, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM + 0xfef6: 0x00fa, # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM + 0xfef7: 0x0099, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM + 0xfef8: 0x009a, # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM + 0xfefb: 0x009d, # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM + 0xfefc: 0x009e, # ARABIC LIGATURE LAM WITH ALEF FINAL FORM +} diff --git a/winvenv/Lib/encodings/cp865.py b/winvenv/Lib/encodings/cp865.py new file mode 100644 index 0000000..6726cf3 --- /dev/null +++ b/winvenv/Lib/encodings/cp865.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP865.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp865', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0081: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x0082: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x0083: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x0084: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x0085: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0086: 0x00e5, # LATIN SMALL LETTER A WITH RING ABOVE + 0x0087: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x0088: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0089: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x008a: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x008b: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x008c: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x008d: 0x00ec, # LATIN SMALL LETTER I WITH GRAVE + 0x008e: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x008f: 0x00c5, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x0090: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0091: 0x00e6, # LATIN SMALL LIGATURE AE + 0x0092: 0x00c6, # LATIN CAPITAL LIGATURE AE + 0x0093: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x0094: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x0095: 0x00f2, # LATIN SMALL LETTER O WITH GRAVE + 0x0096: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x0097: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x0098: 0x00ff, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0099: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x009a: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x009b: 0x00f8, # LATIN SMALL LETTER O WITH STROKE + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x00d8, # LATIN CAPITAL LETTER O WITH STROKE + 0x009e: 0x20a7, # PESETA SIGN + 0x009f: 0x0192, # LATIN SMALL LETTER F WITH HOOK + 0x00a0: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x00a1: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x00a2: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x00a3: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x00a4: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x00a5: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x00a6: 0x00aa, # FEMININE ORDINAL INDICATOR + 0x00a7: 0x00ba, # MASCULINE ORDINAL INDICATOR + 0x00a8: 0x00bf, # INVERTED QUESTION MARK + 0x00a9: 0x2310, # REVERSED NOT SIGN + 0x00aa: 0x00ac, # NOT SIGN + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x00bc, # VULGAR FRACTION ONE QUARTER + 0x00ad: 0x00a1, # INVERTED EXCLAMATION MARK + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00a4, # CURRENCY SIGN + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00e1: 0x00df, # LATIN SMALL LETTER SHARP S + 0x00e2: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00e3: 0x03c0, # GREEK SMALL LETTER PI + 0x00e4: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00e5: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00e6: 0x00b5, # MICRO SIGN + 0x00e7: 0x03c4, # GREEK SMALL LETTER TAU + 0x00e8: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00e9: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ea: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00eb: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00ec: 0x221e, # INFINITY + 0x00ed: 0x03c6, # GREEK SMALL LETTER PHI + 0x00ee: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00ef: 0x2229, # INTERSECTION + 0x00f0: 0x2261, # IDENTICAL TO + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x2265, # GREATER-THAN OR EQUAL TO + 0x00f3: 0x2264, # LESS-THAN OR EQUAL TO + 0x00f4: 0x2320, # TOP HALF INTEGRAL + 0x00f5: 0x2321, # BOTTOM HALF INTEGRAL + 0x00f6: 0x00f7, # DIVISION SIGN + 0x00f7: 0x2248, # ALMOST EQUAL TO + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x207f, # SUPERSCRIPT LATIN SMALL LETTER N + 0x00fd: 0x00b2, # SUPERSCRIPT TWO + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\xc7' # 0x0080 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xfc' # 0x0081 -> LATIN SMALL LETTER U WITH DIAERESIS + '\xe9' # 0x0082 -> LATIN SMALL LETTER E WITH ACUTE + '\xe2' # 0x0083 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x0084 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe0' # 0x0085 -> LATIN SMALL LETTER A WITH GRAVE + '\xe5' # 0x0086 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x0087 -> LATIN SMALL LETTER C WITH CEDILLA + '\xea' # 0x0088 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0089 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xe8' # 0x008a -> LATIN SMALL LETTER E WITH GRAVE + '\xef' # 0x008b -> LATIN SMALL LETTER I WITH DIAERESIS + '\xee' # 0x008c -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xec' # 0x008d -> LATIN SMALL LETTER I WITH GRAVE + '\xc4' # 0x008e -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x008f -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc9' # 0x0090 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xe6' # 0x0091 -> LATIN SMALL LIGATURE AE + '\xc6' # 0x0092 -> LATIN CAPITAL LIGATURE AE + '\xf4' # 0x0093 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x0094 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf2' # 0x0095 -> LATIN SMALL LETTER O WITH GRAVE + '\xfb' # 0x0096 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xf9' # 0x0097 -> LATIN SMALL LETTER U WITH GRAVE + '\xff' # 0x0098 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xd6' # 0x0099 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x009a -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xf8' # 0x009b -> LATIN SMALL LETTER O WITH STROKE + '\xa3' # 0x009c -> POUND SIGN + '\xd8' # 0x009d -> LATIN CAPITAL LETTER O WITH STROKE + '\u20a7' # 0x009e -> PESETA SIGN + '\u0192' # 0x009f -> LATIN SMALL LETTER F WITH HOOK + '\xe1' # 0x00a0 -> LATIN SMALL LETTER A WITH ACUTE + '\xed' # 0x00a1 -> LATIN SMALL LETTER I WITH ACUTE + '\xf3' # 0x00a2 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0x00a3 -> LATIN SMALL LETTER U WITH ACUTE + '\xf1' # 0x00a4 -> LATIN SMALL LETTER N WITH TILDE + '\xd1' # 0x00a5 -> LATIN CAPITAL LETTER N WITH TILDE + '\xaa' # 0x00a6 -> FEMININE ORDINAL INDICATOR + '\xba' # 0x00a7 -> MASCULINE ORDINAL INDICATOR + '\xbf' # 0x00a8 -> INVERTED QUESTION MARK + '\u2310' # 0x00a9 -> REVERSED NOT SIGN + '\xac' # 0x00aa -> NOT SIGN + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\xbc' # 0x00ac -> VULGAR FRACTION ONE QUARTER + '\xa1' # 0x00ad -> INVERTED EXCLAMATION MARK + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xa4' # 0x00af -> CURRENCY SIGN + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b1' # 0x00e0 -> GREEK SMALL LETTER ALPHA + '\xdf' # 0x00e1 -> LATIN SMALL LETTER SHARP S + '\u0393' # 0x00e2 -> GREEK CAPITAL LETTER GAMMA + '\u03c0' # 0x00e3 -> GREEK SMALL LETTER PI + '\u03a3' # 0x00e4 -> GREEK CAPITAL LETTER SIGMA + '\u03c3' # 0x00e5 -> GREEK SMALL LETTER SIGMA + '\xb5' # 0x00e6 -> MICRO SIGN + '\u03c4' # 0x00e7 -> GREEK SMALL LETTER TAU + '\u03a6' # 0x00e8 -> GREEK CAPITAL LETTER PHI + '\u0398' # 0x00e9 -> GREEK CAPITAL LETTER THETA + '\u03a9' # 0x00ea -> GREEK CAPITAL LETTER OMEGA + '\u03b4' # 0x00eb -> GREEK SMALL LETTER DELTA + '\u221e' # 0x00ec -> INFINITY + '\u03c6' # 0x00ed -> GREEK SMALL LETTER PHI + '\u03b5' # 0x00ee -> GREEK SMALL LETTER EPSILON + '\u2229' # 0x00ef -> INTERSECTION + '\u2261' # 0x00f0 -> IDENTICAL TO + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u2265' # 0x00f2 -> GREATER-THAN OR EQUAL TO + '\u2264' # 0x00f3 -> LESS-THAN OR EQUAL TO + '\u2320' # 0x00f4 -> TOP HALF INTEGRAL + '\u2321' # 0x00f5 -> BOTTOM HALF INTEGRAL + '\xf7' # 0x00f6 -> DIVISION SIGN + '\u2248' # 0x00f7 -> ALMOST EQUAL TO + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u207f' # 0x00fc -> SUPERSCRIPT LATIN SMALL LETTER N + '\xb2' # 0x00fd -> SUPERSCRIPT TWO + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a1: 0x00ad, # INVERTED EXCLAMATION MARK + 0x00a3: 0x009c, # POUND SIGN + 0x00a4: 0x00af, # CURRENCY SIGN + 0x00aa: 0x00a6, # FEMININE ORDINAL INDICATOR + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00aa, # NOT SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x00fd, # SUPERSCRIPT TWO + 0x00b5: 0x00e6, # MICRO SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x00ba: 0x00a7, # MASCULINE ORDINAL INDICATOR + 0x00bc: 0x00ac, # VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x00bf: 0x00a8, # INVERTED QUESTION MARK + 0x00c4: 0x008e, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x008f, # LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x0092, # LATIN CAPITAL LIGATURE AE + 0x00c7: 0x0080, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0090, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d1: 0x00a5, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d6: 0x0099, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d8: 0x009d, # LATIN CAPITAL LETTER O WITH STROKE + 0x00dc: 0x009a, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00df: 0x00e1, # LATIN SMALL LETTER SHARP S + 0x00e0: 0x0085, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00a0, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0083, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x0084, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x0086, # LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x0091, # LATIN SMALL LIGATURE AE + 0x00e7: 0x0087, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008a, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x0082, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0088, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0089, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x008d, # LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00a1, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x008c, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x008b, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x00a4, # LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x0095, # LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00a2, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0093, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x0094, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00f6, # DIVISION SIGN + 0x00f8: 0x009b, # LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x0097, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00a3, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x0096, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x0081, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00ff: 0x0098, # LATIN SMALL LETTER Y WITH DIAERESIS + 0x0192: 0x009f, # LATIN SMALL LETTER F WITH HOOK + 0x0393: 0x00e2, # GREEK CAPITAL LETTER GAMMA + 0x0398: 0x00e9, # GREEK CAPITAL LETTER THETA + 0x03a3: 0x00e4, # GREEK CAPITAL LETTER SIGMA + 0x03a6: 0x00e8, # GREEK CAPITAL LETTER PHI + 0x03a9: 0x00ea, # GREEK CAPITAL LETTER OMEGA + 0x03b1: 0x00e0, # GREEK SMALL LETTER ALPHA + 0x03b4: 0x00eb, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00ee, # GREEK SMALL LETTER EPSILON + 0x03c0: 0x00e3, # GREEK SMALL LETTER PI + 0x03c3: 0x00e5, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00e7, # GREEK SMALL LETTER TAU + 0x03c6: 0x00ed, # GREEK SMALL LETTER PHI + 0x207f: 0x00fc, # SUPERSCRIPT LATIN SMALL LETTER N + 0x20a7: 0x009e, # PESETA SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x221e: 0x00ec, # INFINITY + 0x2229: 0x00ef, # INTERSECTION + 0x2248: 0x00f7, # ALMOST EQUAL TO + 0x2261: 0x00f0, # IDENTICAL TO + 0x2264: 0x00f3, # LESS-THAN OR EQUAL TO + 0x2265: 0x00f2, # GREATER-THAN OR EQUAL TO + 0x2310: 0x00a9, # REVERSED NOT SIGN + 0x2320: 0x00f4, # TOP HALF INTEGRAL + 0x2321: 0x00f5, # BOTTOM HALF INTEGRAL + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp866.py b/winvenv/Lib/encodings/cp866.py new file mode 100644 index 0000000..bec7ae3 --- /dev/null +++ b/winvenv/Lib/encodings/cp866.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP866.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp866', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x0410, # CYRILLIC CAPITAL LETTER A + 0x0081: 0x0411, # CYRILLIC CAPITAL LETTER BE + 0x0082: 0x0412, # CYRILLIC CAPITAL LETTER VE + 0x0083: 0x0413, # CYRILLIC CAPITAL LETTER GHE + 0x0084: 0x0414, # CYRILLIC CAPITAL LETTER DE + 0x0085: 0x0415, # CYRILLIC CAPITAL LETTER IE + 0x0086: 0x0416, # CYRILLIC CAPITAL LETTER ZHE + 0x0087: 0x0417, # CYRILLIC CAPITAL LETTER ZE + 0x0088: 0x0418, # CYRILLIC CAPITAL LETTER I + 0x0089: 0x0419, # CYRILLIC CAPITAL LETTER SHORT I + 0x008a: 0x041a, # CYRILLIC CAPITAL LETTER KA + 0x008b: 0x041b, # CYRILLIC CAPITAL LETTER EL + 0x008c: 0x041c, # CYRILLIC CAPITAL LETTER EM + 0x008d: 0x041d, # CYRILLIC CAPITAL LETTER EN + 0x008e: 0x041e, # CYRILLIC CAPITAL LETTER O + 0x008f: 0x041f, # CYRILLIC CAPITAL LETTER PE + 0x0090: 0x0420, # CYRILLIC CAPITAL LETTER ER + 0x0091: 0x0421, # CYRILLIC CAPITAL LETTER ES + 0x0092: 0x0422, # CYRILLIC CAPITAL LETTER TE + 0x0093: 0x0423, # CYRILLIC CAPITAL LETTER U + 0x0094: 0x0424, # CYRILLIC CAPITAL LETTER EF + 0x0095: 0x0425, # CYRILLIC CAPITAL LETTER HA + 0x0096: 0x0426, # CYRILLIC CAPITAL LETTER TSE + 0x0097: 0x0427, # CYRILLIC CAPITAL LETTER CHE + 0x0098: 0x0428, # CYRILLIC CAPITAL LETTER SHA + 0x0099: 0x0429, # CYRILLIC CAPITAL LETTER SHCHA + 0x009a: 0x042a, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x009b: 0x042b, # CYRILLIC CAPITAL LETTER YERU + 0x009c: 0x042c, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x009d: 0x042d, # CYRILLIC CAPITAL LETTER E + 0x009e: 0x042e, # CYRILLIC CAPITAL LETTER YU + 0x009f: 0x042f, # CYRILLIC CAPITAL LETTER YA + 0x00a0: 0x0430, # CYRILLIC SMALL LETTER A + 0x00a1: 0x0431, # CYRILLIC SMALL LETTER BE + 0x00a2: 0x0432, # CYRILLIC SMALL LETTER VE + 0x00a3: 0x0433, # CYRILLIC SMALL LETTER GHE + 0x00a4: 0x0434, # CYRILLIC SMALL LETTER DE + 0x00a5: 0x0435, # CYRILLIC SMALL LETTER IE + 0x00a6: 0x0436, # CYRILLIC SMALL LETTER ZHE + 0x00a7: 0x0437, # CYRILLIC SMALL LETTER ZE + 0x00a8: 0x0438, # CYRILLIC SMALL LETTER I + 0x00a9: 0x0439, # CYRILLIC SMALL LETTER SHORT I + 0x00aa: 0x043a, # CYRILLIC SMALL LETTER KA + 0x00ab: 0x043b, # CYRILLIC SMALL LETTER EL + 0x00ac: 0x043c, # CYRILLIC SMALL LETTER EM + 0x00ad: 0x043d, # CYRILLIC SMALL LETTER EN + 0x00ae: 0x043e, # CYRILLIC SMALL LETTER O + 0x00af: 0x043f, # CYRILLIC SMALL LETTER PE + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x2561, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x00b6: 0x2562, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x00b7: 0x2556, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x00b8: 0x2555, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x255c, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x00be: 0x255b, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x255e, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x00c7: 0x255f, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x2567, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x00d0: 0x2568, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x00d1: 0x2564, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x00d2: 0x2565, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x00d3: 0x2559, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x00d4: 0x2558, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x00d5: 0x2552, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x00d6: 0x2553, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x00d7: 0x256b, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x00d8: 0x256a, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x258c, # LEFT HALF BLOCK + 0x00de: 0x2590, # RIGHT HALF BLOCK + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x0440, # CYRILLIC SMALL LETTER ER + 0x00e1: 0x0441, # CYRILLIC SMALL LETTER ES + 0x00e2: 0x0442, # CYRILLIC SMALL LETTER TE + 0x00e3: 0x0443, # CYRILLIC SMALL LETTER U + 0x00e4: 0x0444, # CYRILLIC SMALL LETTER EF + 0x00e5: 0x0445, # CYRILLIC SMALL LETTER HA + 0x00e6: 0x0446, # CYRILLIC SMALL LETTER TSE + 0x00e7: 0x0447, # CYRILLIC SMALL LETTER CHE + 0x00e8: 0x0448, # CYRILLIC SMALL LETTER SHA + 0x00e9: 0x0449, # CYRILLIC SMALL LETTER SHCHA + 0x00ea: 0x044a, # CYRILLIC SMALL LETTER HARD SIGN + 0x00eb: 0x044b, # CYRILLIC SMALL LETTER YERU + 0x00ec: 0x044c, # CYRILLIC SMALL LETTER SOFT SIGN + 0x00ed: 0x044d, # CYRILLIC SMALL LETTER E + 0x00ee: 0x044e, # CYRILLIC SMALL LETTER YU + 0x00ef: 0x044f, # CYRILLIC SMALL LETTER YA + 0x00f0: 0x0401, # CYRILLIC CAPITAL LETTER IO + 0x00f1: 0x0451, # CYRILLIC SMALL LETTER IO + 0x00f2: 0x0404, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x00f3: 0x0454, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x00f4: 0x0407, # CYRILLIC CAPITAL LETTER YI + 0x00f5: 0x0457, # CYRILLIC SMALL LETTER YI + 0x00f6: 0x040e, # CYRILLIC CAPITAL LETTER SHORT U + 0x00f7: 0x045e, # CYRILLIC SMALL LETTER SHORT U + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x2219, # BULLET OPERATOR + 0x00fa: 0x00b7, # MIDDLE DOT + 0x00fb: 0x221a, # SQUARE ROOT + 0x00fc: 0x2116, # NUMERO SIGN + 0x00fd: 0x00a4, # CURRENCY SIGN + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\u0410' # 0x0080 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0x0081 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0x0082 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0x0083 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0x0084 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0x0085 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0x0086 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0x0087 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0x0088 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0x0089 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0x008a -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0x008b -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0x008c -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0x008d -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0x008e -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0x008f -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0x0090 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0x0091 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0x0092 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0x0093 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0x0094 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0x0095 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0x0096 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0x0097 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0x0098 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0x0099 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0x009a -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0x009b -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0x009c -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0x009d -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0x009e -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0x009f -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0x00a0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0x00a1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0x00a2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0x00a3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0x00a4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0x00a5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0x00a6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0x00a7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0x00a8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0x00a9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0x00aa -> CYRILLIC SMALL LETTER KA + '\u043b' # 0x00ab -> CYRILLIC SMALL LETTER EL + '\u043c' # 0x00ac -> CYRILLIC SMALL LETTER EM + '\u043d' # 0x00ad -> CYRILLIC SMALL LETTER EN + '\u043e' # 0x00ae -> CYRILLIC SMALL LETTER O + '\u043f' # 0x00af -> CYRILLIC SMALL LETTER PE + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u2561' # 0x00b5 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u2562' # 0x00b6 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2556' # 0x00b7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2555' # 0x00b8 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255c' # 0x00bd -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255b' # 0x00be -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u255e' # 0x00c6 -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0x00c7 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u2567' # 0x00cf -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0x00d0 -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2564' # 0x00d1 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0x00d2 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2559' # 0x00d3 -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u2558' # 0x00d4 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2552' # 0x00d5 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u2553' # 0x00d6 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u256b' # 0x00d7 -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256a' # 0x00d8 -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u258c' # 0x00dd -> LEFT HALF BLOCK + '\u2590' # 0x00de -> RIGHT HALF BLOCK + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u0440' # 0x00e0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0x00e1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0x00e2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0x00e3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0x00e4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0x00e5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0x00e6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0x00e7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0x00e8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0x00e9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0x00ea -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0x00eb -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0x00ec -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0x00ed -> CYRILLIC SMALL LETTER E + '\u044e' # 0x00ee -> CYRILLIC SMALL LETTER YU + '\u044f' # 0x00ef -> CYRILLIC SMALL LETTER YA + '\u0401' # 0x00f0 -> CYRILLIC CAPITAL LETTER IO + '\u0451' # 0x00f1 -> CYRILLIC SMALL LETTER IO + '\u0404' # 0x00f2 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\u0454' # 0x00f3 -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\u0407' # 0x00f4 -> CYRILLIC CAPITAL LETTER YI + '\u0457' # 0x00f5 -> CYRILLIC SMALL LETTER YI + '\u040e' # 0x00f6 -> CYRILLIC CAPITAL LETTER SHORT U + '\u045e' # 0x00f7 -> CYRILLIC SMALL LETTER SHORT U + '\xb0' # 0x00f8 -> DEGREE SIGN + '\u2219' # 0x00f9 -> BULLET OPERATOR + '\xb7' # 0x00fa -> MIDDLE DOT + '\u221a' # 0x00fb -> SQUARE ROOT + '\u2116' # 0x00fc -> NUMERO SIGN + '\xa4' # 0x00fd -> CURRENCY SIGN + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a4: 0x00fd, # CURRENCY SIGN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b7: 0x00fa, # MIDDLE DOT + 0x0401: 0x00f0, # CYRILLIC CAPITAL LETTER IO + 0x0404: 0x00f2, # CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x0407: 0x00f4, # CYRILLIC CAPITAL LETTER YI + 0x040e: 0x00f6, # CYRILLIC CAPITAL LETTER SHORT U + 0x0410: 0x0080, # CYRILLIC CAPITAL LETTER A + 0x0411: 0x0081, # CYRILLIC CAPITAL LETTER BE + 0x0412: 0x0082, # CYRILLIC CAPITAL LETTER VE + 0x0413: 0x0083, # CYRILLIC CAPITAL LETTER GHE + 0x0414: 0x0084, # CYRILLIC CAPITAL LETTER DE + 0x0415: 0x0085, # CYRILLIC CAPITAL LETTER IE + 0x0416: 0x0086, # CYRILLIC CAPITAL LETTER ZHE + 0x0417: 0x0087, # CYRILLIC CAPITAL LETTER ZE + 0x0418: 0x0088, # CYRILLIC CAPITAL LETTER I + 0x0419: 0x0089, # CYRILLIC CAPITAL LETTER SHORT I + 0x041a: 0x008a, # CYRILLIC CAPITAL LETTER KA + 0x041b: 0x008b, # CYRILLIC CAPITAL LETTER EL + 0x041c: 0x008c, # CYRILLIC CAPITAL LETTER EM + 0x041d: 0x008d, # CYRILLIC CAPITAL LETTER EN + 0x041e: 0x008e, # CYRILLIC CAPITAL LETTER O + 0x041f: 0x008f, # CYRILLIC CAPITAL LETTER PE + 0x0420: 0x0090, # CYRILLIC CAPITAL LETTER ER + 0x0421: 0x0091, # CYRILLIC CAPITAL LETTER ES + 0x0422: 0x0092, # CYRILLIC CAPITAL LETTER TE + 0x0423: 0x0093, # CYRILLIC CAPITAL LETTER U + 0x0424: 0x0094, # CYRILLIC CAPITAL LETTER EF + 0x0425: 0x0095, # CYRILLIC CAPITAL LETTER HA + 0x0426: 0x0096, # CYRILLIC CAPITAL LETTER TSE + 0x0427: 0x0097, # CYRILLIC CAPITAL LETTER CHE + 0x0428: 0x0098, # CYRILLIC CAPITAL LETTER SHA + 0x0429: 0x0099, # CYRILLIC CAPITAL LETTER SHCHA + 0x042a: 0x009a, # CYRILLIC CAPITAL LETTER HARD SIGN + 0x042b: 0x009b, # CYRILLIC CAPITAL LETTER YERU + 0x042c: 0x009c, # CYRILLIC CAPITAL LETTER SOFT SIGN + 0x042d: 0x009d, # CYRILLIC CAPITAL LETTER E + 0x042e: 0x009e, # CYRILLIC CAPITAL LETTER YU + 0x042f: 0x009f, # CYRILLIC CAPITAL LETTER YA + 0x0430: 0x00a0, # CYRILLIC SMALL LETTER A + 0x0431: 0x00a1, # CYRILLIC SMALL LETTER BE + 0x0432: 0x00a2, # CYRILLIC SMALL LETTER VE + 0x0433: 0x00a3, # CYRILLIC SMALL LETTER GHE + 0x0434: 0x00a4, # CYRILLIC SMALL LETTER DE + 0x0435: 0x00a5, # CYRILLIC SMALL LETTER IE + 0x0436: 0x00a6, # CYRILLIC SMALL LETTER ZHE + 0x0437: 0x00a7, # CYRILLIC SMALL LETTER ZE + 0x0438: 0x00a8, # CYRILLIC SMALL LETTER I + 0x0439: 0x00a9, # CYRILLIC SMALL LETTER SHORT I + 0x043a: 0x00aa, # CYRILLIC SMALL LETTER KA + 0x043b: 0x00ab, # CYRILLIC SMALL LETTER EL + 0x043c: 0x00ac, # CYRILLIC SMALL LETTER EM + 0x043d: 0x00ad, # CYRILLIC SMALL LETTER EN + 0x043e: 0x00ae, # CYRILLIC SMALL LETTER O + 0x043f: 0x00af, # CYRILLIC SMALL LETTER PE + 0x0440: 0x00e0, # CYRILLIC SMALL LETTER ER + 0x0441: 0x00e1, # CYRILLIC SMALL LETTER ES + 0x0442: 0x00e2, # CYRILLIC SMALL LETTER TE + 0x0443: 0x00e3, # CYRILLIC SMALL LETTER U + 0x0444: 0x00e4, # CYRILLIC SMALL LETTER EF + 0x0445: 0x00e5, # CYRILLIC SMALL LETTER HA + 0x0446: 0x00e6, # CYRILLIC SMALL LETTER TSE + 0x0447: 0x00e7, # CYRILLIC SMALL LETTER CHE + 0x0448: 0x00e8, # CYRILLIC SMALL LETTER SHA + 0x0449: 0x00e9, # CYRILLIC SMALL LETTER SHCHA + 0x044a: 0x00ea, # CYRILLIC SMALL LETTER HARD SIGN + 0x044b: 0x00eb, # CYRILLIC SMALL LETTER YERU + 0x044c: 0x00ec, # CYRILLIC SMALL LETTER SOFT SIGN + 0x044d: 0x00ed, # CYRILLIC SMALL LETTER E + 0x044e: 0x00ee, # CYRILLIC SMALL LETTER YU + 0x044f: 0x00ef, # CYRILLIC SMALL LETTER YA + 0x0451: 0x00f1, # CYRILLIC SMALL LETTER IO + 0x0454: 0x00f3, # CYRILLIC SMALL LETTER UKRAINIAN IE + 0x0457: 0x00f5, # CYRILLIC SMALL LETTER YI + 0x045e: 0x00f7, # CYRILLIC SMALL LETTER SHORT U + 0x2116: 0x00fc, # NUMERO SIGN + 0x2219: 0x00f9, # BULLET OPERATOR + 0x221a: 0x00fb, # SQUARE ROOT + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2552: 0x00d5, # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553: 0x00d6, # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2555: 0x00b8, # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2556: 0x00b7, # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x2558: 0x00d4, # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2559: 0x00d3, # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255b: 0x00be, # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x255c: 0x00bd, # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x255e: 0x00c6, # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f: 0x00c7, # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2561: 0x00b5, # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562: 0x00b6, # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2564: 0x00d1, # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565: 0x00d2, # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2567: 0x00cf, # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568: 0x00d0, # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256a: 0x00d8, # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x256b: 0x00d7, # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x258c: 0x00dd, # LEFT HALF BLOCK + 0x2590: 0x00de, # RIGHT HALF BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp869.py b/winvenv/Lib/encodings/cp869.py new file mode 100644 index 0000000..8d8a29b --- /dev/null +++ b/winvenv/Lib/encodings/cp869.py @@ -0,0 +1,689 @@ +""" Python Character Mapping Codec generated from 'VENDORS/MICSFT/PC/CP869.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp869', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: None, # UNDEFINED + 0x0081: None, # UNDEFINED + 0x0082: None, # UNDEFINED + 0x0083: None, # UNDEFINED + 0x0084: None, # UNDEFINED + 0x0085: None, # UNDEFINED + 0x0086: 0x0386, # GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x0087: None, # UNDEFINED + 0x0088: 0x00b7, # MIDDLE DOT + 0x0089: 0x00ac, # NOT SIGN + 0x008a: 0x00a6, # BROKEN BAR + 0x008b: 0x2018, # LEFT SINGLE QUOTATION MARK + 0x008c: 0x2019, # RIGHT SINGLE QUOTATION MARK + 0x008d: 0x0388, # GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x008e: 0x2015, # HORIZONTAL BAR + 0x008f: 0x0389, # GREEK CAPITAL LETTER ETA WITH TONOS + 0x0090: 0x038a, # GREEK CAPITAL LETTER IOTA WITH TONOS + 0x0091: 0x03aa, # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x0092: 0x038c, # GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x0093: None, # UNDEFINED + 0x0094: None, # UNDEFINED + 0x0095: 0x038e, # GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x0096: 0x03ab, # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x0097: 0x00a9, # COPYRIGHT SIGN + 0x0098: 0x038f, # GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x0099: 0x00b2, # SUPERSCRIPT TWO + 0x009a: 0x00b3, # SUPERSCRIPT THREE + 0x009b: 0x03ac, # GREEK SMALL LETTER ALPHA WITH TONOS + 0x009c: 0x00a3, # POUND SIGN + 0x009d: 0x03ad, # GREEK SMALL LETTER EPSILON WITH TONOS + 0x009e: 0x03ae, # GREEK SMALL LETTER ETA WITH TONOS + 0x009f: 0x03af, # GREEK SMALL LETTER IOTA WITH TONOS + 0x00a0: 0x03ca, # GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x00a1: 0x0390, # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + 0x00a2: 0x03cc, # GREEK SMALL LETTER OMICRON WITH TONOS + 0x00a3: 0x03cd, # GREEK SMALL LETTER UPSILON WITH TONOS + 0x00a4: 0x0391, # GREEK CAPITAL LETTER ALPHA + 0x00a5: 0x0392, # GREEK CAPITAL LETTER BETA + 0x00a6: 0x0393, # GREEK CAPITAL LETTER GAMMA + 0x00a7: 0x0394, # GREEK CAPITAL LETTER DELTA + 0x00a8: 0x0395, # GREEK CAPITAL LETTER EPSILON + 0x00a9: 0x0396, # GREEK CAPITAL LETTER ZETA + 0x00aa: 0x0397, # GREEK CAPITAL LETTER ETA + 0x00ab: 0x00bd, # VULGAR FRACTION ONE HALF + 0x00ac: 0x0398, # GREEK CAPITAL LETTER THETA + 0x00ad: 0x0399, # GREEK CAPITAL LETTER IOTA + 0x00ae: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00af: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00b0: 0x2591, # LIGHT SHADE + 0x00b1: 0x2592, # MEDIUM SHADE + 0x00b2: 0x2593, # DARK SHADE + 0x00b3: 0x2502, # BOX DRAWINGS LIGHT VERTICAL + 0x00b4: 0x2524, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x00b5: 0x039a, # GREEK CAPITAL LETTER KAPPA + 0x00b6: 0x039b, # GREEK CAPITAL LETTER LAMDA + 0x00b7: 0x039c, # GREEK CAPITAL LETTER MU + 0x00b8: 0x039d, # GREEK CAPITAL LETTER NU + 0x00b9: 0x2563, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x00ba: 0x2551, # BOX DRAWINGS DOUBLE VERTICAL + 0x00bb: 0x2557, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x00bc: 0x255d, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x00bd: 0x039e, # GREEK CAPITAL LETTER XI + 0x00be: 0x039f, # GREEK CAPITAL LETTER OMICRON + 0x00bf: 0x2510, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x00c0: 0x2514, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x00c1: 0x2534, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x00c2: 0x252c, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x00c3: 0x251c, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x00c4: 0x2500, # BOX DRAWINGS LIGHT HORIZONTAL + 0x00c5: 0x253c, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x00c6: 0x03a0, # GREEK CAPITAL LETTER PI + 0x00c7: 0x03a1, # GREEK CAPITAL LETTER RHO + 0x00c8: 0x255a, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x00c9: 0x2554, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x00ca: 0x2569, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x00cb: 0x2566, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x00cc: 0x2560, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x00cd: 0x2550, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x00ce: 0x256c, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x00cf: 0x03a3, # GREEK CAPITAL LETTER SIGMA + 0x00d0: 0x03a4, # GREEK CAPITAL LETTER TAU + 0x00d1: 0x03a5, # GREEK CAPITAL LETTER UPSILON + 0x00d2: 0x03a6, # GREEK CAPITAL LETTER PHI + 0x00d3: 0x03a7, # GREEK CAPITAL LETTER CHI + 0x00d4: 0x03a8, # GREEK CAPITAL LETTER PSI + 0x00d5: 0x03a9, # GREEK CAPITAL LETTER OMEGA + 0x00d6: 0x03b1, # GREEK SMALL LETTER ALPHA + 0x00d7: 0x03b2, # GREEK SMALL LETTER BETA + 0x00d8: 0x03b3, # GREEK SMALL LETTER GAMMA + 0x00d9: 0x2518, # BOX DRAWINGS LIGHT UP AND LEFT + 0x00da: 0x250c, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x00db: 0x2588, # FULL BLOCK + 0x00dc: 0x2584, # LOWER HALF BLOCK + 0x00dd: 0x03b4, # GREEK SMALL LETTER DELTA + 0x00de: 0x03b5, # GREEK SMALL LETTER EPSILON + 0x00df: 0x2580, # UPPER HALF BLOCK + 0x00e0: 0x03b6, # GREEK SMALL LETTER ZETA + 0x00e1: 0x03b7, # GREEK SMALL LETTER ETA + 0x00e2: 0x03b8, # GREEK SMALL LETTER THETA + 0x00e3: 0x03b9, # GREEK SMALL LETTER IOTA + 0x00e4: 0x03ba, # GREEK SMALL LETTER KAPPA + 0x00e5: 0x03bb, # GREEK SMALL LETTER LAMDA + 0x00e6: 0x03bc, # GREEK SMALL LETTER MU + 0x00e7: 0x03bd, # GREEK SMALL LETTER NU + 0x00e8: 0x03be, # GREEK SMALL LETTER XI + 0x00e9: 0x03bf, # GREEK SMALL LETTER OMICRON + 0x00ea: 0x03c0, # GREEK SMALL LETTER PI + 0x00eb: 0x03c1, # GREEK SMALL LETTER RHO + 0x00ec: 0x03c3, # GREEK SMALL LETTER SIGMA + 0x00ed: 0x03c2, # GREEK SMALL LETTER FINAL SIGMA + 0x00ee: 0x03c4, # GREEK SMALL LETTER TAU + 0x00ef: 0x0384, # GREEK TONOS + 0x00f0: 0x00ad, # SOFT HYPHEN + 0x00f1: 0x00b1, # PLUS-MINUS SIGN + 0x00f2: 0x03c5, # GREEK SMALL LETTER UPSILON + 0x00f3: 0x03c6, # GREEK SMALL LETTER PHI + 0x00f4: 0x03c7, # GREEK SMALL LETTER CHI + 0x00f5: 0x00a7, # SECTION SIGN + 0x00f6: 0x03c8, # GREEK SMALL LETTER PSI + 0x00f7: 0x0385, # GREEK DIALYTIKA TONOS + 0x00f8: 0x00b0, # DEGREE SIGN + 0x00f9: 0x00a8, # DIAERESIS + 0x00fa: 0x03c9, # GREEK SMALL LETTER OMEGA + 0x00fb: 0x03cb, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x00fc: 0x03b0, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + 0x00fd: 0x03ce, # GREEK SMALL LETTER OMEGA WITH TONOS + 0x00fe: 0x25a0, # BLACK SQUARE + 0x00ff: 0x00a0, # NO-BREAK SPACE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> NULL + '\x01' # 0x0001 -> START OF HEADING + '\x02' # 0x0002 -> START OF TEXT + '\x03' # 0x0003 -> END OF TEXT + '\x04' # 0x0004 -> END OF TRANSMISSION + '\x05' # 0x0005 -> ENQUIRY + '\x06' # 0x0006 -> ACKNOWLEDGE + '\x07' # 0x0007 -> BELL + '\x08' # 0x0008 -> BACKSPACE + '\t' # 0x0009 -> HORIZONTAL TABULATION + '\n' # 0x000a -> LINE FEED + '\x0b' # 0x000b -> VERTICAL TABULATION + '\x0c' # 0x000c -> FORM FEED + '\r' # 0x000d -> CARRIAGE RETURN + '\x0e' # 0x000e -> SHIFT OUT + '\x0f' # 0x000f -> SHIFT IN + '\x10' # 0x0010 -> DATA LINK ESCAPE + '\x11' # 0x0011 -> DEVICE CONTROL ONE + '\x12' # 0x0012 -> DEVICE CONTROL TWO + '\x13' # 0x0013 -> DEVICE CONTROL THREE + '\x14' # 0x0014 -> DEVICE CONTROL FOUR + '\x15' # 0x0015 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x0016 -> SYNCHRONOUS IDLE + '\x17' # 0x0017 -> END OF TRANSMISSION BLOCK + '\x18' # 0x0018 -> CANCEL + '\x19' # 0x0019 -> END OF MEDIUM + '\x1a' # 0x001a -> SUBSTITUTE + '\x1b' # 0x001b -> ESCAPE + '\x1c' # 0x001c -> FILE SEPARATOR + '\x1d' # 0x001d -> GROUP SEPARATOR + '\x1e' # 0x001e -> RECORD SEPARATOR + '\x1f' # 0x001f -> UNIT SEPARATOR + ' ' # 0x0020 -> SPACE + '!' # 0x0021 -> EXCLAMATION MARK + '"' # 0x0022 -> QUOTATION MARK + '#' # 0x0023 -> NUMBER SIGN + '$' # 0x0024 -> DOLLAR SIGN + '%' # 0x0025 -> PERCENT SIGN + '&' # 0x0026 -> AMPERSAND + "'" # 0x0027 -> APOSTROPHE + '(' # 0x0028 -> LEFT PARENTHESIS + ')' # 0x0029 -> RIGHT PARENTHESIS + '*' # 0x002a -> ASTERISK + '+' # 0x002b -> PLUS SIGN + ',' # 0x002c -> COMMA + '-' # 0x002d -> HYPHEN-MINUS + '.' # 0x002e -> FULL STOP + '/' # 0x002f -> SOLIDUS + '0' # 0x0030 -> DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE + '2' # 0x0032 -> DIGIT TWO + '3' # 0x0033 -> DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE + ':' # 0x003a -> COLON + ';' # 0x003b -> SEMICOLON + '<' # 0x003c -> LESS-THAN SIGN + '=' # 0x003d -> EQUALS SIGN + '>' # 0x003e -> GREATER-THAN SIGN + '?' # 0x003f -> QUESTION MARK + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET + '\\' # 0x005c -> REVERSE SOLIDUS + ']' # 0x005d -> RIGHT SQUARE BRACKET + '^' # 0x005e -> CIRCUMFLEX ACCENT + '_' # 0x005f -> LOW LINE + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET + '|' # 0x007c -> VERTICAL LINE + '}' # 0x007d -> RIGHT CURLY BRACKET + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> DELETE + '\ufffe' # 0x0080 -> UNDEFINED + '\ufffe' # 0x0081 -> UNDEFINED + '\ufffe' # 0x0082 -> UNDEFINED + '\ufffe' # 0x0083 -> UNDEFINED + '\ufffe' # 0x0084 -> UNDEFINED + '\ufffe' # 0x0085 -> UNDEFINED + '\u0386' # 0x0086 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + '\ufffe' # 0x0087 -> UNDEFINED + '\xb7' # 0x0088 -> MIDDLE DOT + '\xac' # 0x0089 -> NOT SIGN + '\xa6' # 0x008a -> BROKEN BAR + '\u2018' # 0x008b -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x008c -> RIGHT SINGLE QUOTATION MARK + '\u0388' # 0x008d -> GREEK CAPITAL LETTER EPSILON WITH TONOS + '\u2015' # 0x008e -> HORIZONTAL BAR + '\u0389' # 0x008f -> GREEK CAPITAL LETTER ETA WITH TONOS + '\u038a' # 0x0090 -> GREEK CAPITAL LETTER IOTA WITH TONOS + '\u03aa' # 0x0091 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + '\u038c' # 0x0092 -> GREEK CAPITAL LETTER OMICRON WITH TONOS + '\ufffe' # 0x0093 -> UNDEFINED + '\ufffe' # 0x0094 -> UNDEFINED + '\u038e' # 0x0095 -> GREEK CAPITAL LETTER UPSILON WITH TONOS + '\u03ab' # 0x0096 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + '\xa9' # 0x0097 -> COPYRIGHT SIGN + '\u038f' # 0x0098 -> GREEK CAPITAL LETTER OMEGA WITH TONOS + '\xb2' # 0x0099 -> SUPERSCRIPT TWO + '\xb3' # 0x009a -> SUPERSCRIPT THREE + '\u03ac' # 0x009b -> GREEK SMALL LETTER ALPHA WITH TONOS + '\xa3' # 0x009c -> POUND SIGN + '\u03ad' # 0x009d -> GREEK SMALL LETTER EPSILON WITH TONOS + '\u03ae' # 0x009e -> GREEK SMALL LETTER ETA WITH TONOS + '\u03af' # 0x009f -> GREEK SMALL LETTER IOTA WITH TONOS + '\u03ca' # 0x00a0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + '\u0390' # 0x00a1 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + '\u03cc' # 0x00a2 -> GREEK SMALL LETTER OMICRON WITH TONOS + '\u03cd' # 0x00a3 -> GREEK SMALL LETTER UPSILON WITH TONOS + '\u0391' # 0x00a4 -> GREEK CAPITAL LETTER ALPHA + '\u0392' # 0x00a5 -> GREEK CAPITAL LETTER BETA + '\u0393' # 0x00a6 -> GREEK CAPITAL LETTER GAMMA + '\u0394' # 0x00a7 -> GREEK CAPITAL LETTER DELTA + '\u0395' # 0x00a8 -> GREEK CAPITAL LETTER EPSILON + '\u0396' # 0x00a9 -> GREEK CAPITAL LETTER ZETA + '\u0397' # 0x00aa -> GREEK CAPITAL LETTER ETA + '\xbd' # 0x00ab -> VULGAR FRACTION ONE HALF + '\u0398' # 0x00ac -> GREEK CAPITAL LETTER THETA + '\u0399' # 0x00ad -> GREEK CAPITAL LETTER IOTA + '\xab' # 0x00ae -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0x00af -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2591' # 0x00b0 -> LIGHT SHADE + '\u2592' # 0x00b1 -> MEDIUM SHADE + '\u2593' # 0x00b2 -> DARK SHADE + '\u2502' # 0x00b3 -> BOX DRAWINGS LIGHT VERTICAL + '\u2524' # 0x00b4 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u039a' # 0x00b5 -> GREEK CAPITAL LETTER KAPPA + '\u039b' # 0x00b6 -> GREEK CAPITAL LETTER LAMDA + '\u039c' # 0x00b7 -> GREEK CAPITAL LETTER MU + '\u039d' # 0x00b8 -> GREEK CAPITAL LETTER NU + '\u2563' # 0x00b9 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2551' # 0x00ba -> BOX DRAWINGS DOUBLE VERTICAL + '\u2557' # 0x00bb -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u255d' # 0x00bc -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u039e' # 0x00bd -> GREEK CAPITAL LETTER XI + '\u039f' # 0x00be -> GREEK CAPITAL LETTER OMICRON + '\u2510' # 0x00bf -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x00c0 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2534' # 0x00c1 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u252c' # 0x00c2 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u251c' # 0x00c3 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2500' # 0x00c4 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u253c' # 0x00c5 -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u03a0' # 0x00c6 -> GREEK CAPITAL LETTER PI + '\u03a1' # 0x00c7 -> GREEK CAPITAL LETTER RHO + '\u255a' # 0x00c8 -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u2554' # 0x00c9 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2569' # 0x00ca -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u2566' # 0x00cb -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2560' # 0x00cc -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2550' # 0x00cd -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u256c' # 0x00ce -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\u03a3' # 0x00cf -> GREEK CAPITAL LETTER SIGMA + '\u03a4' # 0x00d0 -> GREEK CAPITAL LETTER TAU + '\u03a5' # 0x00d1 -> GREEK CAPITAL LETTER UPSILON + '\u03a6' # 0x00d2 -> GREEK CAPITAL LETTER PHI + '\u03a7' # 0x00d3 -> GREEK CAPITAL LETTER CHI + '\u03a8' # 0x00d4 -> GREEK CAPITAL LETTER PSI + '\u03a9' # 0x00d5 -> GREEK CAPITAL LETTER OMEGA + '\u03b1' # 0x00d6 -> GREEK SMALL LETTER ALPHA + '\u03b2' # 0x00d7 -> GREEK SMALL LETTER BETA + '\u03b3' # 0x00d8 -> GREEK SMALL LETTER GAMMA + '\u2518' # 0x00d9 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u250c' # 0x00da -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2588' # 0x00db -> FULL BLOCK + '\u2584' # 0x00dc -> LOWER HALF BLOCK + '\u03b4' # 0x00dd -> GREEK SMALL LETTER DELTA + '\u03b5' # 0x00de -> GREEK SMALL LETTER EPSILON + '\u2580' # 0x00df -> UPPER HALF BLOCK + '\u03b6' # 0x00e0 -> GREEK SMALL LETTER ZETA + '\u03b7' # 0x00e1 -> GREEK SMALL LETTER ETA + '\u03b8' # 0x00e2 -> GREEK SMALL LETTER THETA + '\u03b9' # 0x00e3 -> GREEK SMALL LETTER IOTA + '\u03ba' # 0x00e4 -> GREEK SMALL LETTER KAPPA + '\u03bb' # 0x00e5 -> GREEK SMALL LETTER LAMDA + '\u03bc' # 0x00e6 -> GREEK SMALL LETTER MU + '\u03bd' # 0x00e7 -> GREEK SMALL LETTER NU + '\u03be' # 0x00e8 -> GREEK SMALL LETTER XI + '\u03bf' # 0x00e9 -> GREEK SMALL LETTER OMICRON + '\u03c0' # 0x00ea -> GREEK SMALL LETTER PI + '\u03c1' # 0x00eb -> GREEK SMALL LETTER RHO + '\u03c3' # 0x00ec -> GREEK SMALL LETTER SIGMA + '\u03c2' # 0x00ed -> GREEK SMALL LETTER FINAL SIGMA + '\u03c4' # 0x00ee -> GREEK SMALL LETTER TAU + '\u0384' # 0x00ef -> GREEK TONOS + '\xad' # 0x00f0 -> SOFT HYPHEN + '\xb1' # 0x00f1 -> PLUS-MINUS SIGN + '\u03c5' # 0x00f2 -> GREEK SMALL LETTER UPSILON + '\u03c6' # 0x00f3 -> GREEK SMALL LETTER PHI + '\u03c7' # 0x00f4 -> GREEK SMALL LETTER CHI + '\xa7' # 0x00f5 -> SECTION SIGN + '\u03c8' # 0x00f6 -> GREEK SMALL LETTER PSI + '\u0385' # 0x00f7 -> GREEK DIALYTIKA TONOS + '\xb0' # 0x00f8 -> DEGREE SIGN + '\xa8' # 0x00f9 -> DIAERESIS + '\u03c9' # 0x00fa -> GREEK SMALL LETTER OMEGA + '\u03cb' # 0x00fb -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + '\u03b0' # 0x00fc -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + '\u03ce' # 0x00fd -> GREEK SMALL LETTER OMEGA WITH TONOS + '\u25a0' # 0x00fe -> BLACK SQUARE + '\xa0' # 0x00ff -> NO-BREAK SPACE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # NULL + 0x0001: 0x0001, # START OF HEADING + 0x0002: 0x0002, # START OF TEXT + 0x0003: 0x0003, # END OF TEXT + 0x0004: 0x0004, # END OF TRANSMISSION + 0x0005: 0x0005, # ENQUIRY + 0x0006: 0x0006, # ACKNOWLEDGE + 0x0007: 0x0007, # BELL + 0x0008: 0x0008, # BACKSPACE + 0x0009: 0x0009, # HORIZONTAL TABULATION + 0x000a: 0x000a, # LINE FEED + 0x000b: 0x000b, # VERTICAL TABULATION + 0x000c: 0x000c, # FORM FEED + 0x000d: 0x000d, # CARRIAGE RETURN + 0x000e: 0x000e, # SHIFT OUT + 0x000f: 0x000f, # SHIFT IN + 0x0010: 0x0010, # DATA LINK ESCAPE + 0x0011: 0x0011, # DEVICE CONTROL ONE + 0x0012: 0x0012, # DEVICE CONTROL TWO + 0x0013: 0x0013, # DEVICE CONTROL THREE + 0x0014: 0x0014, # DEVICE CONTROL FOUR + 0x0015: 0x0015, # NEGATIVE ACKNOWLEDGE + 0x0016: 0x0016, # SYNCHRONOUS IDLE + 0x0017: 0x0017, # END OF TRANSMISSION BLOCK + 0x0018: 0x0018, # CANCEL + 0x0019: 0x0019, # END OF MEDIUM + 0x001a: 0x001a, # SUBSTITUTE + 0x001b: 0x001b, # ESCAPE + 0x001c: 0x001c, # FILE SEPARATOR + 0x001d: 0x001d, # GROUP SEPARATOR + 0x001e: 0x001e, # RECORD SEPARATOR + 0x001f: 0x001f, # UNIT SEPARATOR + 0x0020: 0x0020, # SPACE + 0x0021: 0x0021, # EXCLAMATION MARK + 0x0022: 0x0022, # QUOTATION MARK + 0x0023: 0x0023, # NUMBER SIGN + 0x0024: 0x0024, # DOLLAR SIGN + 0x0025: 0x0025, # PERCENT SIGN + 0x0026: 0x0026, # AMPERSAND + 0x0027: 0x0027, # APOSTROPHE + 0x0028: 0x0028, # LEFT PARENTHESIS + 0x0029: 0x0029, # RIGHT PARENTHESIS + 0x002a: 0x002a, # ASTERISK + 0x002b: 0x002b, # PLUS SIGN + 0x002c: 0x002c, # COMMA + 0x002d: 0x002d, # HYPHEN-MINUS + 0x002e: 0x002e, # FULL STOP + 0x002f: 0x002f, # SOLIDUS + 0x0030: 0x0030, # DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE + 0x003a: 0x003a, # COLON + 0x003b: 0x003b, # SEMICOLON + 0x003c: 0x003c, # LESS-THAN SIGN + 0x003d: 0x003d, # EQUALS SIGN + 0x003e: 0x003e, # GREATER-THAN SIGN + 0x003f: 0x003f, # QUESTION MARK + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET + 0x005c: 0x005c, # REVERSE SOLIDUS + 0x005d: 0x005d, # RIGHT SQUARE BRACKET + 0x005e: 0x005e, # CIRCUMFLEX ACCENT + 0x005f: 0x005f, # LOW LINE + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET + 0x007c: 0x007c, # VERTICAL LINE + 0x007d: 0x007d, # RIGHT CURLY BRACKET + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # DELETE + 0x00a0: 0x00ff, # NO-BREAK SPACE + 0x00a3: 0x009c, # POUND SIGN + 0x00a6: 0x008a, # BROKEN BAR + 0x00a7: 0x00f5, # SECTION SIGN + 0x00a8: 0x00f9, # DIAERESIS + 0x00a9: 0x0097, # COPYRIGHT SIGN + 0x00ab: 0x00ae, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x0089, # NOT SIGN + 0x00ad: 0x00f0, # SOFT HYPHEN + 0x00b0: 0x00f8, # DEGREE SIGN + 0x00b1: 0x00f1, # PLUS-MINUS SIGN + 0x00b2: 0x0099, # SUPERSCRIPT TWO + 0x00b3: 0x009a, # SUPERSCRIPT THREE + 0x00b7: 0x0088, # MIDDLE DOT + 0x00bb: 0x00af, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bd: 0x00ab, # VULGAR FRACTION ONE HALF + 0x0384: 0x00ef, # GREEK TONOS + 0x0385: 0x00f7, # GREEK DIALYTIKA TONOS + 0x0386: 0x0086, # GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x0388: 0x008d, # GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x0389: 0x008f, # GREEK CAPITAL LETTER ETA WITH TONOS + 0x038a: 0x0090, # GREEK CAPITAL LETTER IOTA WITH TONOS + 0x038c: 0x0092, # GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x038e: 0x0095, # GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x038f: 0x0098, # GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x0390: 0x00a1, # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + 0x0391: 0x00a4, # GREEK CAPITAL LETTER ALPHA + 0x0392: 0x00a5, # GREEK CAPITAL LETTER BETA + 0x0393: 0x00a6, # GREEK CAPITAL LETTER GAMMA + 0x0394: 0x00a7, # GREEK CAPITAL LETTER DELTA + 0x0395: 0x00a8, # GREEK CAPITAL LETTER EPSILON + 0x0396: 0x00a9, # GREEK CAPITAL LETTER ZETA + 0x0397: 0x00aa, # GREEK CAPITAL LETTER ETA + 0x0398: 0x00ac, # GREEK CAPITAL LETTER THETA + 0x0399: 0x00ad, # GREEK CAPITAL LETTER IOTA + 0x039a: 0x00b5, # GREEK CAPITAL LETTER KAPPA + 0x039b: 0x00b6, # GREEK CAPITAL LETTER LAMDA + 0x039c: 0x00b7, # GREEK CAPITAL LETTER MU + 0x039d: 0x00b8, # GREEK CAPITAL LETTER NU + 0x039e: 0x00bd, # GREEK CAPITAL LETTER XI + 0x039f: 0x00be, # GREEK CAPITAL LETTER OMICRON + 0x03a0: 0x00c6, # GREEK CAPITAL LETTER PI + 0x03a1: 0x00c7, # GREEK CAPITAL LETTER RHO + 0x03a3: 0x00cf, # GREEK CAPITAL LETTER SIGMA + 0x03a4: 0x00d0, # GREEK CAPITAL LETTER TAU + 0x03a5: 0x00d1, # GREEK CAPITAL LETTER UPSILON + 0x03a6: 0x00d2, # GREEK CAPITAL LETTER PHI + 0x03a7: 0x00d3, # GREEK CAPITAL LETTER CHI + 0x03a8: 0x00d4, # GREEK CAPITAL LETTER PSI + 0x03a9: 0x00d5, # GREEK CAPITAL LETTER OMEGA + 0x03aa: 0x0091, # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x03ab: 0x0096, # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x03ac: 0x009b, # GREEK SMALL LETTER ALPHA WITH TONOS + 0x03ad: 0x009d, # GREEK SMALL LETTER EPSILON WITH TONOS + 0x03ae: 0x009e, # GREEK SMALL LETTER ETA WITH TONOS + 0x03af: 0x009f, # GREEK SMALL LETTER IOTA WITH TONOS + 0x03b0: 0x00fc, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + 0x03b1: 0x00d6, # GREEK SMALL LETTER ALPHA + 0x03b2: 0x00d7, # GREEK SMALL LETTER BETA + 0x03b3: 0x00d8, # GREEK SMALL LETTER GAMMA + 0x03b4: 0x00dd, # GREEK SMALL LETTER DELTA + 0x03b5: 0x00de, # GREEK SMALL LETTER EPSILON + 0x03b6: 0x00e0, # GREEK SMALL LETTER ZETA + 0x03b7: 0x00e1, # GREEK SMALL LETTER ETA + 0x03b8: 0x00e2, # GREEK SMALL LETTER THETA + 0x03b9: 0x00e3, # GREEK SMALL LETTER IOTA + 0x03ba: 0x00e4, # GREEK SMALL LETTER KAPPA + 0x03bb: 0x00e5, # GREEK SMALL LETTER LAMDA + 0x03bc: 0x00e6, # GREEK SMALL LETTER MU + 0x03bd: 0x00e7, # GREEK SMALL LETTER NU + 0x03be: 0x00e8, # GREEK SMALL LETTER XI + 0x03bf: 0x00e9, # GREEK SMALL LETTER OMICRON + 0x03c0: 0x00ea, # GREEK SMALL LETTER PI + 0x03c1: 0x00eb, # GREEK SMALL LETTER RHO + 0x03c2: 0x00ed, # GREEK SMALL LETTER FINAL SIGMA + 0x03c3: 0x00ec, # GREEK SMALL LETTER SIGMA + 0x03c4: 0x00ee, # GREEK SMALL LETTER TAU + 0x03c5: 0x00f2, # GREEK SMALL LETTER UPSILON + 0x03c6: 0x00f3, # GREEK SMALL LETTER PHI + 0x03c7: 0x00f4, # GREEK SMALL LETTER CHI + 0x03c8: 0x00f6, # GREEK SMALL LETTER PSI + 0x03c9: 0x00fa, # GREEK SMALL LETTER OMEGA + 0x03ca: 0x00a0, # GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x03cb: 0x00fb, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x03cc: 0x00a2, # GREEK SMALL LETTER OMICRON WITH TONOS + 0x03cd: 0x00a3, # GREEK SMALL LETTER UPSILON WITH TONOS + 0x03ce: 0x00fd, # GREEK SMALL LETTER OMEGA WITH TONOS + 0x2015: 0x008e, # HORIZONTAL BAR + 0x2018: 0x008b, # LEFT SINGLE QUOTATION MARK + 0x2019: 0x008c, # RIGHT SINGLE QUOTATION MARK + 0x2500: 0x00c4, # BOX DRAWINGS LIGHT HORIZONTAL + 0x2502: 0x00b3, # BOX DRAWINGS LIGHT VERTICAL + 0x250c: 0x00da, # BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2510: 0x00bf, # BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514: 0x00c0, # BOX DRAWINGS LIGHT UP AND RIGHT + 0x2518: 0x00d9, # BOX DRAWINGS LIGHT UP AND LEFT + 0x251c: 0x00c3, # BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2524: 0x00b4, # BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x252c: 0x00c2, # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x2534: 0x00c1, # BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x253c: 0x00c5, # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x2550: 0x00cd, # BOX DRAWINGS DOUBLE HORIZONTAL + 0x2551: 0x00ba, # BOX DRAWINGS DOUBLE VERTICAL + 0x2554: 0x00c9, # BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2557: 0x00bb, # BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255a: 0x00c8, # BOX DRAWINGS DOUBLE UP AND RIGHT + 0x255d: 0x00bc, # BOX DRAWINGS DOUBLE UP AND LEFT + 0x2560: 0x00cc, # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2563: 0x00b9, # BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2566: 0x00cb, # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2569: 0x00ca, # BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x256c: 0x00ce, # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2580: 0x00df, # UPPER HALF BLOCK + 0x2584: 0x00dc, # LOWER HALF BLOCK + 0x2588: 0x00db, # FULL BLOCK + 0x2591: 0x00b0, # LIGHT SHADE + 0x2592: 0x00b1, # MEDIUM SHADE + 0x2593: 0x00b2, # DARK SHADE + 0x25a0: 0x00fe, # BLACK SQUARE +} diff --git a/winvenv/Lib/encodings/cp874.py b/winvenv/Lib/encodings/cp874.py new file mode 100644 index 0000000..59bfcbc --- /dev/null +++ b/winvenv/Lib/encodings/cp874.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp874 generated from 'MAPPINGS/VENDORS/MICSFT/WINDOWS/CP874.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp874', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\ufffe' # 0x81 -> UNDEFINED + '\ufffe' # 0x82 -> UNDEFINED + '\ufffe' # 0x83 -> UNDEFINED + '\ufffe' # 0x84 -> UNDEFINED + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\ufffe' # 0x86 -> UNDEFINED + '\ufffe' # 0x87 -> UNDEFINED + '\ufffe' # 0x88 -> UNDEFINED + '\ufffe' # 0x89 -> UNDEFINED + '\ufffe' # 0x8A -> UNDEFINED + '\ufffe' # 0x8B -> UNDEFINED + '\ufffe' # 0x8C -> UNDEFINED + '\ufffe' # 0x8D -> UNDEFINED + '\ufffe' # 0x8E -> UNDEFINED + '\ufffe' # 0x8F -> UNDEFINED + '\ufffe' # 0x90 -> UNDEFINED + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\ufffe' # 0x99 -> UNDEFINED + '\ufffe' # 0x9A -> UNDEFINED + '\ufffe' # 0x9B -> UNDEFINED + '\ufffe' # 0x9C -> UNDEFINED + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\ufffe' # 0x9F -> UNDEFINED + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0e01' # 0xA1 -> THAI CHARACTER KO KAI + '\u0e02' # 0xA2 -> THAI CHARACTER KHO KHAI + '\u0e03' # 0xA3 -> THAI CHARACTER KHO KHUAT + '\u0e04' # 0xA4 -> THAI CHARACTER KHO KHWAI + '\u0e05' # 0xA5 -> THAI CHARACTER KHO KHON + '\u0e06' # 0xA6 -> THAI CHARACTER KHO RAKHANG + '\u0e07' # 0xA7 -> THAI CHARACTER NGO NGU + '\u0e08' # 0xA8 -> THAI CHARACTER CHO CHAN + '\u0e09' # 0xA9 -> THAI CHARACTER CHO CHING + '\u0e0a' # 0xAA -> THAI CHARACTER CHO CHANG + '\u0e0b' # 0xAB -> THAI CHARACTER SO SO + '\u0e0c' # 0xAC -> THAI CHARACTER CHO CHOE + '\u0e0d' # 0xAD -> THAI CHARACTER YO YING + '\u0e0e' # 0xAE -> THAI CHARACTER DO CHADA + '\u0e0f' # 0xAF -> THAI CHARACTER TO PATAK + '\u0e10' # 0xB0 -> THAI CHARACTER THO THAN + '\u0e11' # 0xB1 -> THAI CHARACTER THO NANGMONTHO + '\u0e12' # 0xB2 -> THAI CHARACTER THO PHUTHAO + '\u0e13' # 0xB3 -> THAI CHARACTER NO NEN + '\u0e14' # 0xB4 -> THAI CHARACTER DO DEK + '\u0e15' # 0xB5 -> THAI CHARACTER TO TAO + '\u0e16' # 0xB6 -> THAI CHARACTER THO THUNG + '\u0e17' # 0xB7 -> THAI CHARACTER THO THAHAN + '\u0e18' # 0xB8 -> THAI CHARACTER THO THONG + '\u0e19' # 0xB9 -> THAI CHARACTER NO NU + '\u0e1a' # 0xBA -> THAI CHARACTER BO BAIMAI + '\u0e1b' # 0xBB -> THAI CHARACTER PO PLA + '\u0e1c' # 0xBC -> THAI CHARACTER PHO PHUNG + '\u0e1d' # 0xBD -> THAI CHARACTER FO FA + '\u0e1e' # 0xBE -> THAI CHARACTER PHO PHAN + '\u0e1f' # 0xBF -> THAI CHARACTER FO FAN + '\u0e20' # 0xC0 -> THAI CHARACTER PHO SAMPHAO + '\u0e21' # 0xC1 -> THAI CHARACTER MO MA + '\u0e22' # 0xC2 -> THAI CHARACTER YO YAK + '\u0e23' # 0xC3 -> THAI CHARACTER RO RUA + '\u0e24' # 0xC4 -> THAI CHARACTER RU + '\u0e25' # 0xC5 -> THAI CHARACTER LO LING + '\u0e26' # 0xC6 -> THAI CHARACTER LU + '\u0e27' # 0xC7 -> THAI CHARACTER WO WAEN + '\u0e28' # 0xC8 -> THAI CHARACTER SO SALA + '\u0e29' # 0xC9 -> THAI CHARACTER SO RUSI + '\u0e2a' # 0xCA -> THAI CHARACTER SO SUA + '\u0e2b' # 0xCB -> THAI CHARACTER HO HIP + '\u0e2c' # 0xCC -> THAI CHARACTER LO CHULA + '\u0e2d' # 0xCD -> THAI CHARACTER O ANG + '\u0e2e' # 0xCE -> THAI CHARACTER HO NOKHUK + '\u0e2f' # 0xCF -> THAI CHARACTER PAIYANNOI + '\u0e30' # 0xD0 -> THAI CHARACTER SARA A + '\u0e31' # 0xD1 -> THAI CHARACTER MAI HAN-AKAT + '\u0e32' # 0xD2 -> THAI CHARACTER SARA AA + '\u0e33' # 0xD3 -> THAI CHARACTER SARA AM + '\u0e34' # 0xD4 -> THAI CHARACTER SARA I + '\u0e35' # 0xD5 -> THAI CHARACTER SARA II + '\u0e36' # 0xD6 -> THAI CHARACTER SARA UE + '\u0e37' # 0xD7 -> THAI CHARACTER SARA UEE + '\u0e38' # 0xD8 -> THAI CHARACTER SARA U + '\u0e39' # 0xD9 -> THAI CHARACTER SARA UU + '\u0e3a' # 0xDA -> THAI CHARACTER PHINTHU + '\ufffe' # 0xDB -> UNDEFINED + '\ufffe' # 0xDC -> UNDEFINED + '\ufffe' # 0xDD -> UNDEFINED + '\ufffe' # 0xDE -> UNDEFINED + '\u0e3f' # 0xDF -> THAI CURRENCY SYMBOL BAHT + '\u0e40' # 0xE0 -> THAI CHARACTER SARA E + '\u0e41' # 0xE1 -> THAI CHARACTER SARA AE + '\u0e42' # 0xE2 -> THAI CHARACTER SARA O + '\u0e43' # 0xE3 -> THAI CHARACTER SARA AI MAIMUAN + '\u0e44' # 0xE4 -> THAI CHARACTER SARA AI MAIMALAI + '\u0e45' # 0xE5 -> THAI CHARACTER LAKKHANGYAO + '\u0e46' # 0xE6 -> THAI CHARACTER MAIYAMOK + '\u0e47' # 0xE7 -> THAI CHARACTER MAITAIKHU + '\u0e48' # 0xE8 -> THAI CHARACTER MAI EK + '\u0e49' # 0xE9 -> THAI CHARACTER MAI THO + '\u0e4a' # 0xEA -> THAI CHARACTER MAI TRI + '\u0e4b' # 0xEB -> THAI CHARACTER MAI CHATTAWA + '\u0e4c' # 0xEC -> THAI CHARACTER THANTHAKHAT + '\u0e4d' # 0xED -> THAI CHARACTER NIKHAHIT + '\u0e4e' # 0xEE -> THAI CHARACTER YAMAKKAN + '\u0e4f' # 0xEF -> THAI CHARACTER FONGMAN + '\u0e50' # 0xF0 -> THAI DIGIT ZERO + '\u0e51' # 0xF1 -> THAI DIGIT ONE + '\u0e52' # 0xF2 -> THAI DIGIT TWO + '\u0e53' # 0xF3 -> THAI DIGIT THREE + '\u0e54' # 0xF4 -> THAI DIGIT FOUR + '\u0e55' # 0xF5 -> THAI DIGIT FIVE + '\u0e56' # 0xF6 -> THAI DIGIT SIX + '\u0e57' # 0xF7 -> THAI DIGIT SEVEN + '\u0e58' # 0xF8 -> THAI DIGIT EIGHT + '\u0e59' # 0xF9 -> THAI DIGIT NINE + '\u0e5a' # 0xFA -> THAI CHARACTER ANGKHANKHU + '\u0e5b' # 0xFB -> THAI CHARACTER KHOMUT + '\ufffe' # 0xFC -> UNDEFINED + '\ufffe' # 0xFD -> UNDEFINED + '\ufffe' # 0xFE -> UNDEFINED + '\ufffe' # 0xFF -> UNDEFINED +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp875.py b/winvenv/Lib/encodings/cp875.py new file mode 100644 index 0000000..c25a5a4 --- /dev/null +++ b/winvenv/Lib/encodings/cp875.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec cp875 generated from 'MAPPINGS/VENDORS/MICSFT/EBCDIC/CP875.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='cp875', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x9c' # 0x04 -> CONTROL + '\t' # 0x05 -> HORIZONTAL TABULATION + '\x86' # 0x06 -> CONTROL + '\x7f' # 0x07 -> DELETE + '\x97' # 0x08 -> CONTROL + '\x8d' # 0x09 -> CONTROL + '\x8e' # 0x0A -> CONTROL + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x9d' # 0x14 -> CONTROL + '\x85' # 0x15 -> CONTROL + '\x08' # 0x16 -> BACKSPACE + '\x87' # 0x17 -> CONTROL + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x92' # 0x1A -> CONTROL + '\x8f' # 0x1B -> CONTROL + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + '\x80' # 0x20 -> CONTROL + '\x81' # 0x21 -> CONTROL + '\x82' # 0x22 -> CONTROL + '\x83' # 0x23 -> CONTROL + '\x84' # 0x24 -> CONTROL + '\n' # 0x25 -> LINE FEED + '\x17' # 0x26 -> END OF TRANSMISSION BLOCK + '\x1b' # 0x27 -> ESCAPE + '\x88' # 0x28 -> CONTROL + '\x89' # 0x29 -> CONTROL + '\x8a' # 0x2A -> CONTROL + '\x8b' # 0x2B -> CONTROL + '\x8c' # 0x2C -> CONTROL + '\x05' # 0x2D -> ENQUIRY + '\x06' # 0x2E -> ACKNOWLEDGE + '\x07' # 0x2F -> BELL + '\x90' # 0x30 -> CONTROL + '\x91' # 0x31 -> CONTROL + '\x16' # 0x32 -> SYNCHRONOUS IDLE + '\x93' # 0x33 -> CONTROL + '\x94' # 0x34 -> CONTROL + '\x95' # 0x35 -> CONTROL + '\x96' # 0x36 -> CONTROL + '\x04' # 0x37 -> END OF TRANSMISSION + '\x98' # 0x38 -> CONTROL + '\x99' # 0x39 -> CONTROL + '\x9a' # 0x3A -> CONTROL + '\x9b' # 0x3B -> CONTROL + '\x14' # 0x3C -> DEVICE CONTROL FOUR + '\x15' # 0x3D -> NEGATIVE ACKNOWLEDGE + '\x9e' # 0x3E -> CONTROL + '\x1a' # 0x3F -> SUBSTITUTE + ' ' # 0x40 -> SPACE + '\u0391' # 0x41 -> GREEK CAPITAL LETTER ALPHA + '\u0392' # 0x42 -> GREEK CAPITAL LETTER BETA + '\u0393' # 0x43 -> GREEK CAPITAL LETTER GAMMA + '\u0394' # 0x44 -> GREEK CAPITAL LETTER DELTA + '\u0395' # 0x45 -> GREEK CAPITAL LETTER EPSILON + '\u0396' # 0x46 -> GREEK CAPITAL LETTER ZETA + '\u0397' # 0x47 -> GREEK CAPITAL LETTER ETA + '\u0398' # 0x48 -> GREEK CAPITAL LETTER THETA + '\u0399' # 0x49 -> GREEK CAPITAL LETTER IOTA + '[' # 0x4A -> LEFT SQUARE BRACKET + '.' # 0x4B -> FULL STOP + '<' # 0x4C -> LESS-THAN SIGN + '(' # 0x4D -> LEFT PARENTHESIS + '+' # 0x4E -> PLUS SIGN + '!' # 0x4F -> EXCLAMATION MARK + '&' # 0x50 -> AMPERSAND + '\u039a' # 0x51 -> GREEK CAPITAL LETTER KAPPA + '\u039b' # 0x52 -> GREEK CAPITAL LETTER LAMDA + '\u039c' # 0x53 -> GREEK CAPITAL LETTER MU + '\u039d' # 0x54 -> GREEK CAPITAL LETTER NU + '\u039e' # 0x55 -> GREEK CAPITAL LETTER XI + '\u039f' # 0x56 -> GREEK CAPITAL LETTER OMICRON + '\u03a0' # 0x57 -> GREEK CAPITAL LETTER PI + '\u03a1' # 0x58 -> GREEK CAPITAL LETTER RHO + '\u03a3' # 0x59 -> GREEK CAPITAL LETTER SIGMA + ']' # 0x5A -> RIGHT SQUARE BRACKET + '$' # 0x5B -> DOLLAR SIGN + '*' # 0x5C -> ASTERISK + ')' # 0x5D -> RIGHT PARENTHESIS + ';' # 0x5E -> SEMICOLON + '^' # 0x5F -> CIRCUMFLEX ACCENT + '-' # 0x60 -> HYPHEN-MINUS + '/' # 0x61 -> SOLIDUS + '\u03a4' # 0x62 -> GREEK CAPITAL LETTER TAU + '\u03a5' # 0x63 -> GREEK CAPITAL LETTER UPSILON + '\u03a6' # 0x64 -> GREEK CAPITAL LETTER PHI + '\u03a7' # 0x65 -> GREEK CAPITAL LETTER CHI + '\u03a8' # 0x66 -> GREEK CAPITAL LETTER PSI + '\u03a9' # 0x67 -> GREEK CAPITAL LETTER OMEGA + '\u03aa' # 0x68 -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + '\u03ab' # 0x69 -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + '|' # 0x6A -> VERTICAL LINE + ',' # 0x6B -> COMMA + '%' # 0x6C -> PERCENT SIGN + '_' # 0x6D -> LOW LINE + '>' # 0x6E -> GREATER-THAN SIGN + '?' # 0x6F -> QUESTION MARK + '\xa8' # 0x70 -> DIAERESIS + '\u0386' # 0x71 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + '\u0388' # 0x72 -> GREEK CAPITAL LETTER EPSILON WITH TONOS + '\u0389' # 0x73 -> GREEK CAPITAL LETTER ETA WITH TONOS + '\xa0' # 0x74 -> NO-BREAK SPACE + '\u038a' # 0x75 -> GREEK CAPITAL LETTER IOTA WITH TONOS + '\u038c' # 0x76 -> GREEK CAPITAL LETTER OMICRON WITH TONOS + '\u038e' # 0x77 -> GREEK CAPITAL LETTER UPSILON WITH TONOS + '\u038f' # 0x78 -> GREEK CAPITAL LETTER OMEGA WITH TONOS + '`' # 0x79 -> GRAVE ACCENT + ':' # 0x7A -> COLON + '#' # 0x7B -> NUMBER SIGN + '@' # 0x7C -> COMMERCIAL AT + "'" # 0x7D -> APOSTROPHE + '=' # 0x7E -> EQUALS SIGN + '"' # 0x7F -> QUOTATION MARK + '\u0385' # 0x80 -> GREEK DIALYTIKA TONOS + 'a' # 0x81 -> LATIN SMALL LETTER A + 'b' # 0x82 -> LATIN SMALL LETTER B + 'c' # 0x83 -> LATIN SMALL LETTER C + 'd' # 0x84 -> LATIN SMALL LETTER D + 'e' # 0x85 -> LATIN SMALL LETTER E + 'f' # 0x86 -> LATIN SMALL LETTER F + 'g' # 0x87 -> LATIN SMALL LETTER G + 'h' # 0x88 -> LATIN SMALL LETTER H + 'i' # 0x89 -> LATIN SMALL LETTER I + '\u03b1' # 0x8A -> GREEK SMALL LETTER ALPHA + '\u03b2' # 0x8B -> GREEK SMALL LETTER BETA + '\u03b3' # 0x8C -> GREEK SMALL LETTER GAMMA + '\u03b4' # 0x8D -> GREEK SMALL LETTER DELTA + '\u03b5' # 0x8E -> GREEK SMALL LETTER EPSILON + '\u03b6' # 0x8F -> GREEK SMALL LETTER ZETA + '\xb0' # 0x90 -> DEGREE SIGN + 'j' # 0x91 -> LATIN SMALL LETTER J + 'k' # 0x92 -> LATIN SMALL LETTER K + 'l' # 0x93 -> LATIN SMALL LETTER L + 'm' # 0x94 -> LATIN SMALL LETTER M + 'n' # 0x95 -> LATIN SMALL LETTER N + 'o' # 0x96 -> LATIN SMALL LETTER O + 'p' # 0x97 -> LATIN SMALL LETTER P + 'q' # 0x98 -> LATIN SMALL LETTER Q + 'r' # 0x99 -> LATIN SMALL LETTER R + '\u03b7' # 0x9A -> GREEK SMALL LETTER ETA + '\u03b8' # 0x9B -> GREEK SMALL LETTER THETA + '\u03b9' # 0x9C -> GREEK SMALL LETTER IOTA + '\u03ba' # 0x9D -> GREEK SMALL LETTER KAPPA + '\u03bb' # 0x9E -> GREEK SMALL LETTER LAMDA + '\u03bc' # 0x9F -> GREEK SMALL LETTER MU + '\xb4' # 0xA0 -> ACUTE ACCENT + '~' # 0xA1 -> TILDE + 's' # 0xA2 -> LATIN SMALL LETTER S + 't' # 0xA3 -> LATIN SMALL LETTER T + 'u' # 0xA4 -> LATIN SMALL LETTER U + 'v' # 0xA5 -> LATIN SMALL LETTER V + 'w' # 0xA6 -> LATIN SMALL LETTER W + 'x' # 0xA7 -> LATIN SMALL LETTER X + 'y' # 0xA8 -> LATIN SMALL LETTER Y + 'z' # 0xA9 -> LATIN SMALL LETTER Z + '\u03bd' # 0xAA -> GREEK SMALL LETTER NU + '\u03be' # 0xAB -> GREEK SMALL LETTER XI + '\u03bf' # 0xAC -> GREEK SMALL LETTER OMICRON + '\u03c0' # 0xAD -> GREEK SMALL LETTER PI + '\u03c1' # 0xAE -> GREEK SMALL LETTER RHO + '\u03c3' # 0xAF -> GREEK SMALL LETTER SIGMA + '\xa3' # 0xB0 -> POUND SIGN + '\u03ac' # 0xB1 -> GREEK SMALL LETTER ALPHA WITH TONOS + '\u03ad' # 0xB2 -> GREEK SMALL LETTER EPSILON WITH TONOS + '\u03ae' # 0xB3 -> GREEK SMALL LETTER ETA WITH TONOS + '\u03ca' # 0xB4 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + '\u03af' # 0xB5 -> GREEK SMALL LETTER IOTA WITH TONOS + '\u03cc' # 0xB6 -> GREEK SMALL LETTER OMICRON WITH TONOS + '\u03cd' # 0xB7 -> GREEK SMALL LETTER UPSILON WITH TONOS + '\u03cb' # 0xB8 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + '\u03ce' # 0xB9 -> GREEK SMALL LETTER OMEGA WITH TONOS + '\u03c2' # 0xBA -> GREEK SMALL LETTER FINAL SIGMA + '\u03c4' # 0xBB -> GREEK SMALL LETTER TAU + '\u03c5' # 0xBC -> GREEK SMALL LETTER UPSILON + '\u03c6' # 0xBD -> GREEK SMALL LETTER PHI + '\u03c7' # 0xBE -> GREEK SMALL LETTER CHI + '\u03c8' # 0xBF -> GREEK SMALL LETTER PSI + '{' # 0xC0 -> LEFT CURLY BRACKET + 'A' # 0xC1 -> LATIN CAPITAL LETTER A + 'B' # 0xC2 -> LATIN CAPITAL LETTER B + 'C' # 0xC3 -> LATIN CAPITAL LETTER C + 'D' # 0xC4 -> LATIN CAPITAL LETTER D + 'E' # 0xC5 -> LATIN CAPITAL LETTER E + 'F' # 0xC6 -> LATIN CAPITAL LETTER F + 'G' # 0xC7 -> LATIN CAPITAL LETTER G + 'H' # 0xC8 -> LATIN CAPITAL LETTER H + 'I' # 0xC9 -> LATIN CAPITAL LETTER I + '\xad' # 0xCA -> SOFT HYPHEN + '\u03c9' # 0xCB -> GREEK SMALL LETTER OMEGA + '\u0390' # 0xCC -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + '\u03b0' # 0xCD -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + '\u2018' # 0xCE -> LEFT SINGLE QUOTATION MARK + '\u2015' # 0xCF -> HORIZONTAL BAR + '}' # 0xD0 -> RIGHT CURLY BRACKET + 'J' # 0xD1 -> LATIN CAPITAL LETTER J + 'K' # 0xD2 -> LATIN CAPITAL LETTER K + 'L' # 0xD3 -> LATIN CAPITAL LETTER L + 'M' # 0xD4 -> LATIN CAPITAL LETTER M + 'N' # 0xD5 -> LATIN CAPITAL LETTER N + 'O' # 0xD6 -> LATIN CAPITAL LETTER O + 'P' # 0xD7 -> LATIN CAPITAL LETTER P + 'Q' # 0xD8 -> LATIN CAPITAL LETTER Q + 'R' # 0xD9 -> LATIN CAPITAL LETTER R + '\xb1' # 0xDA -> PLUS-MINUS SIGN + '\xbd' # 0xDB -> VULGAR FRACTION ONE HALF + '\x1a' # 0xDC -> SUBSTITUTE + '\u0387' # 0xDD -> GREEK ANO TELEIA + '\u2019' # 0xDE -> RIGHT SINGLE QUOTATION MARK + '\xa6' # 0xDF -> BROKEN BAR + '\\' # 0xE0 -> REVERSE SOLIDUS + '\x1a' # 0xE1 -> SUBSTITUTE + 'S' # 0xE2 -> LATIN CAPITAL LETTER S + 'T' # 0xE3 -> LATIN CAPITAL LETTER T + 'U' # 0xE4 -> LATIN CAPITAL LETTER U + 'V' # 0xE5 -> LATIN CAPITAL LETTER V + 'W' # 0xE6 -> LATIN CAPITAL LETTER W + 'X' # 0xE7 -> LATIN CAPITAL LETTER X + 'Y' # 0xE8 -> LATIN CAPITAL LETTER Y + 'Z' # 0xE9 -> LATIN CAPITAL LETTER Z + '\xb2' # 0xEA -> SUPERSCRIPT TWO + '\xa7' # 0xEB -> SECTION SIGN + '\x1a' # 0xEC -> SUBSTITUTE + '\x1a' # 0xED -> SUBSTITUTE + '\xab' # 0xEE -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xEF -> NOT SIGN + '0' # 0xF0 -> DIGIT ZERO + '1' # 0xF1 -> DIGIT ONE + '2' # 0xF2 -> DIGIT TWO + '3' # 0xF3 -> DIGIT THREE + '4' # 0xF4 -> DIGIT FOUR + '5' # 0xF5 -> DIGIT FIVE + '6' # 0xF6 -> DIGIT SIX + '7' # 0xF7 -> DIGIT SEVEN + '8' # 0xF8 -> DIGIT EIGHT + '9' # 0xF9 -> DIGIT NINE + '\xb3' # 0xFA -> SUPERSCRIPT THREE + '\xa9' # 0xFB -> COPYRIGHT SIGN + '\x1a' # 0xFC -> SUBSTITUTE + '\x1a' # 0xFD -> SUBSTITUTE + '\xbb' # 0xFE -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\x9f' # 0xFF -> CONTROL +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/cp932.py b/winvenv/Lib/encodings/cp932.py new file mode 100644 index 0000000..e01f59b --- /dev/null +++ b/winvenv/Lib/encodings/cp932.py @@ -0,0 +1,39 @@ +# +# cp932.py: Python Unicode Codec for CP932 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('cp932') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='cp932', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/cp949.py b/winvenv/Lib/encodings/cp949.py new file mode 100644 index 0000000..627c871 --- /dev/null +++ b/winvenv/Lib/encodings/cp949.py @@ -0,0 +1,39 @@ +# +# cp949.py: Python Unicode Codec for CP949 +# +# Written by Hye-Shik Chang +# + +import _codecs_kr, codecs +import _multibytecodec as mbc + +codec = _codecs_kr.getcodec('cp949') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='cp949', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/cp950.py b/winvenv/Lib/encodings/cp950.py new file mode 100644 index 0000000..39eec5e --- /dev/null +++ b/winvenv/Lib/encodings/cp950.py @@ -0,0 +1,39 @@ +# +# cp950.py: Python Unicode Codec for CP950 +# +# Written by Hye-Shik Chang +# + +import _codecs_tw, codecs +import _multibytecodec as mbc + +codec = _codecs_tw.getcodec('cp950') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='cp950', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/euc_jis_2004.py b/winvenv/Lib/encodings/euc_jis_2004.py new file mode 100644 index 0000000..72b87ae --- /dev/null +++ b/winvenv/Lib/encodings/euc_jis_2004.py @@ -0,0 +1,39 @@ +# +# euc_jis_2004.py: Python Unicode Codec for EUC_JIS_2004 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('euc_jis_2004') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_jis_2004', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/euc_jisx0213.py b/winvenv/Lib/encodings/euc_jisx0213.py new file mode 100644 index 0000000..cc47d04 --- /dev/null +++ b/winvenv/Lib/encodings/euc_jisx0213.py @@ -0,0 +1,39 @@ +# +# euc_jisx0213.py: Python Unicode Codec for EUC_JISX0213 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('euc_jisx0213') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_jisx0213', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/euc_jp.py b/winvenv/Lib/encodings/euc_jp.py new file mode 100644 index 0000000..7bcbe41 --- /dev/null +++ b/winvenv/Lib/encodings/euc_jp.py @@ -0,0 +1,39 @@ +# +# euc_jp.py: Python Unicode Codec for EUC_JP +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('euc_jp') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_jp', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/euc_kr.py b/winvenv/Lib/encodings/euc_kr.py new file mode 100644 index 0000000..c1fb126 --- /dev/null +++ b/winvenv/Lib/encodings/euc_kr.py @@ -0,0 +1,39 @@ +# +# euc_kr.py: Python Unicode Codec for EUC_KR +# +# Written by Hye-Shik Chang +# + +import _codecs_kr, codecs +import _multibytecodec as mbc + +codec = _codecs_kr.getcodec('euc_kr') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='euc_kr', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/gb18030.py b/winvenv/Lib/encodings/gb18030.py new file mode 100644 index 0000000..34fb6c3 --- /dev/null +++ b/winvenv/Lib/encodings/gb18030.py @@ -0,0 +1,39 @@ +# +# gb18030.py: Python Unicode Codec for GB18030 +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('gb18030') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='gb18030', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/gb2312.py b/winvenv/Lib/encodings/gb2312.py new file mode 100644 index 0000000..3c3b837 --- /dev/null +++ b/winvenv/Lib/encodings/gb2312.py @@ -0,0 +1,39 @@ +# +# gb2312.py: Python Unicode Codec for GB2312 +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('gb2312') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='gb2312', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/gbk.py b/winvenv/Lib/encodings/gbk.py new file mode 100644 index 0000000..1b45db8 --- /dev/null +++ b/winvenv/Lib/encodings/gbk.py @@ -0,0 +1,39 @@ +# +# gbk.py: Python Unicode Codec for GBK +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('gbk') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='gbk', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/hex_codec.py b/winvenv/Lib/encodings/hex_codec.py new file mode 100644 index 0000000..9fb1072 --- /dev/null +++ b/winvenv/Lib/encodings/hex_codec.py @@ -0,0 +1,55 @@ +"""Python 'hex_codec' Codec - 2-digit hex content transfer encoding. + +This codec de/encodes from bytes to bytes. + +Written by Marc-Andre Lemburg (mal@lemburg.com). +""" + +import codecs +import binascii + +### Codec APIs + +def hex_encode(input, errors='strict'): + assert errors == 'strict' + return (binascii.b2a_hex(input), len(input)) + +def hex_decode(input, errors='strict'): + assert errors == 'strict' + return (binascii.a2b_hex(input), len(input)) + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return hex_encode(input, errors) + def decode(self, input, errors='strict'): + return hex_decode(input, errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + assert self.errors == 'strict' + return binascii.b2a_hex(input) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + assert self.errors == 'strict' + return binascii.a2b_hex(input) + +class StreamWriter(Codec, codecs.StreamWriter): + charbuffertype = bytes + +class StreamReader(Codec, codecs.StreamReader): + charbuffertype = bytes + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='hex', + encode=hex_encode, + decode=hex_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + _is_text_encoding=False, + ) diff --git a/winvenv/Lib/encodings/hp_roman8.py b/winvenv/Lib/encodings/hp_roman8.py new file mode 100644 index 0000000..58de103 --- /dev/null +++ b/winvenv/Lib/encodings/hp_roman8.py @@ -0,0 +1,314 @@ +""" Python Character Mapping Codec generated from 'hp_roman8.txt' with gencodec.py. + + Based on data from ftp://dkuug.dk/i18n/charmaps/HP-ROMAN8 (Keld Simonsen) + + Original source: LaserJet IIP Printer User's Manual HP part no + 33471-90901, Hewlet-Packard, June 1989. + + (Used with permission) + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='hp-roman8', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xc0' # 0xA1 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc2' # 0xA2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc8' # 0xA3 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xca' # 0xA4 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xA5 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xce' # 0xA6 -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xA7 -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xb4' # 0xA8 -> ACUTE ACCENT + '\u02cb' # 0xA9 -> MODIFIER LETTER GRAVE ACCENT (MANDARIN CHINESE FOURTH TONE) + '\u02c6' # 0xAA -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\xa8' # 0xAB -> DIAERESIS + '\u02dc' # 0xAC -> SMALL TILDE + '\xd9' # 0xAD -> LATIN CAPITAL LETTER U WITH GRAVE + '\xdb' # 0xAE -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\u20a4' # 0xAF -> LIRA SIGN + '\xaf' # 0xB0 -> MACRON + '\xdd' # 0xB1 -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xfd' # 0xB2 -> LATIN SMALL LETTER Y WITH ACUTE + '\xb0' # 0xB3 -> DEGREE SIGN + '\xc7' # 0xB4 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xe7' # 0xB5 -> LATIN SMALL LETTER C WITH CEDILLA + '\xd1' # 0xB6 -> LATIN CAPITAL LETTER N WITH TILDE + '\xf1' # 0xB7 -> LATIN SMALL LETTER N WITH TILDE + '\xa1' # 0xB8 -> INVERTED EXCLAMATION MARK + '\xbf' # 0xB9 -> INVERTED QUESTION MARK + '\xa4' # 0xBA -> CURRENCY SIGN + '\xa3' # 0xBB -> POUND SIGN + '\xa5' # 0xBC -> YEN SIGN + '\xa7' # 0xBD -> SECTION SIGN + '\u0192' # 0xBE -> LATIN SMALL LETTER F WITH HOOK + '\xa2' # 0xBF -> CENT SIGN + '\xe2' # 0xC0 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xea' # 0xC1 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xf4' # 0xC2 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xfb' # 0xC3 -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xe1' # 0xC4 -> LATIN SMALL LETTER A WITH ACUTE + '\xe9' # 0xC5 -> LATIN SMALL LETTER E WITH ACUTE + '\xf3' # 0xC6 -> LATIN SMALL LETTER O WITH ACUTE + '\xfa' # 0xC7 -> LATIN SMALL LETTER U WITH ACUTE + '\xe0' # 0xC8 -> LATIN SMALL LETTER A WITH GRAVE + '\xe8' # 0xC9 -> LATIN SMALL LETTER E WITH GRAVE + '\xf2' # 0xCA -> LATIN SMALL LETTER O WITH GRAVE + '\xf9' # 0xCB -> LATIN SMALL LETTER U WITH GRAVE + '\xe4' # 0xCC -> LATIN SMALL LETTER A WITH DIAERESIS + '\xeb' # 0xCD -> LATIN SMALL LETTER E WITH DIAERESIS + '\xf6' # 0xCE -> LATIN SMALL LETTER O WITH DIAERESIS + '\xfc' # 0xCF -> LATIN SMALL LETTER U WITH DIAERESIS + '\xc5' # 0xD0 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xee' # 0xD1 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xd8' # 0xD2 -> LATIN CAPITAL LETTER O WITH STROKE + '\xc6' # 0xD3 -> LATIN CAPITAL LETTER AE + '\xe5' # 0xD4 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xed' # 0xD5 -> LATIN SMALL LETTER I WITH ACUTE + '\xf8' # 0xD6 -> LATIN SMALL LETTER O WITH STROKE + '\xe6' # 0xD7 -> LATIN SMALL LETTER AE + '\xc4' # 0xD8 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xec' # 0xD9 -> LATIN SMALL LETTER I WITH GRAVE + '\xd6' # 0xDA -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0xDB -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xc9' # 0xDC -> LATIN CAPITAL LETTER E WITH ACUTE + '\xef' # 0xDD -> LATIN SMALL LETTER I WITH DIAERESIS + '\xdf' # 0xDE -> LATIN SMALL LETTER SHARP S (GERMAN) + '\xd4' # 0xDF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xc1' # 0xE0 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc3' # 0xE1 -> LATIN CAPITAL LETTER A WITH TILDE + '\xe3' # 0xE2 -> LATIN SMALL LETTER A WITH TILDE + '\xd0' # 0xE3 -> LATIN CAPITAL LETTER ETH (ICELANDIC) + '\xf0' # 0xE4 -> LATIN SMALL LETTER ETH (ICELANDIC) + '\xcd' # 0xE5 -> LATIN CAPITAL LETTER I WITH ACUTE + '\xcc' # 0xE6 -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd3' # 0xE7 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd2' # 0xE8 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd5' # 0xE9 -> LATIN CAPITAL LETTER O WITH TILDE + '\xf5' # 0xEA -> LATIN SMALL LETTER O WITH TILDE + '\u0160' # 0xEB -> LATIN CAPITAL LETTER S WITH CARON + '\u0161' # 0xEC -> LATIN SMALL LETTER S WITH CARON + '\xda' # 0xED -> LATIN CAPITAL LETTER U WITH ACUTE + '\u0178' # 0xEE -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\xff' # 0xEF -> LATIN SMALL LETTER Y WITH DIAERESIS + '\xde' # 0xF0 -> LATIN CAPITAL LETTER THORN (ICELANDIC) + '\xfe' # 0xF1 -> LATIN SMALL LETTER THORN (ICELANDIC) + '\xb7' # 0xF2 -> MIDDLE DOT + '\xb5' # 0xF3 -> MICRO SIGN + '\xb6' # 0xF4 -> PILCROW SIGN + '\xbe' # 0xF5 -> VULGAR FRACTION THREE QUARTERS + '\u2014' # 0xF6 -> EM DASH + '\xbc' # 0xF7 -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xF8 -> VULGAR FRACTION ONE HALF + '\xaa' # 0xF9 -> FEMININE ORDINAL INDICATOR + '\xba' # 0xFA -> MASCULINE ORDINAL INDICATOR + '\xab' # 0xFB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u25a0' # 0xFC -> BLACK SQUARE + '\xbb' # 0xFD -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xb1' # 0xFE -> PLUS-MINUS SIGN + '\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/hz.py b/winvenv/Lib/encodings/hz.py new file mode 100644 index 0000000..383442a --- /dev/null +++ b/winvenv/Lib/encodings/hz.py @@ -0,0 +1,39 @@ +# +# hz.py: Python Unicode Codec for HZ +# +# Written by Hye-Shik Chang +# + +import _codecs_cn, codecs +import _multibytecodec as mbc + +codec = _codecs_cn.getcodec('hz') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='hz', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/idna.py b/winvenv/Lib/encodings/idna.py new file mode 100644 index 0000000..ea40585 --- /dev/null +++ b/winvenv/Lib/encodings/idna.py @@ -0,0 +1,309 @@ +# This module implements the RFCs 3490 (IDNA) and 3491 (Nameprep) + +import stringprep, re, codecs +from unicodedata import ucd_3_2_0 as unicodedata + +# IDNA section 3.1 +dots = re.compile("[\u002E\u3002\uFF0E\uFF61]") + +# IDNA section 5 +ace_prefix = b"xn--" +sace_prefix = "xn--" + +# This assumes query strings, so AllowUnassigned is true +def nameprep(label): + # Map + newlabel = [] + for c in label: + if stringprep.in_table_b1(c): + # Map to nothing + continue + newlabel.append(stringprep.map_table_b2(c)) + label = "".join(newlabel) + + # Normalize + label = unicodedata.normalize("NFKC", label) + + # Prohibit + for c in label: + if stringprep.in_table_c12(c) or \ + stringprep.in_table_c22(c) or \ + stringprep.in_table_c3(c) or \ + stringprep.in_table_c4(c) or \ + stringprep.in_table_c5(c) or \ + stringprep.in_table_c6(c) or \ + stringprep.in_table_c7(c) or \ + stringprep.in_table_c8(c) or \ + stringprep.in_table_c9(c): + raise UnicodeError("Invalid character %r" % c) + + # Check bidi + RandAL = [stringprep.in_table_d1(x) for x in label] + for c in RandAL: + if c: + # There is a RandAL char in the string. Must perform further + # tests: + # 1) The characters in section 5.8 MUST be prohibited. + # This is table C.8, which was already checked + # 2) If a string contains any RandALCat character, the string + # MUST NOT contain any LCat character. + if any(stringprep.in_table_d2(x) for x in label): + raise UnicodeError("Violation of BIDI requirement 2") + + # 3) If a string contains any RandALCat character, a + # RandALCat character MUST be the first character of the + # string, and a RandALCat character MUST be the last + # character of the string. + if not RandAL[0] or not RandAL[-1]: + raise UnicodeError("Violation of BIDI requirement 3") + + return label + +def ToASCII(label): + try: + # Step 1: try ASCII + label = label.encode("ascii") + except UnicodeError: + pass + else: + # Skip to step 3: UseSTD3ASCIIRules is false, so + # Skip to step 8. + if 0 < len(label) < 64: + return label + raise UnicodeError("label empty or too long") + + # Step 2: nameprep + label = nameprep(label) + + # Step 3: UseSTD3ASCIIRules is false + # Step 4: try ASCII + try: + label = label.encode("ascii") + except UnicodeError: + pass + else: + # Skip to step 8. + if 0 < len(label) < 64: + return label + raise UnicodeError("label empty or too long") + + # Step 5: Check ACE prefix + if label.startswith(sace_prefix): + raise UnicodeError("Label starts with ACE prefix") + + # Step 6: Encode with PUNYCODE + label = label.encode("punycode") + + # Step 7: Prepend ACE prefix + label = ace_prefix + label + + # Step 8: Check size + if 0 < len(label) < 64: + return label + raise UnicodeError("label empty or too long") + +def ToUnicode(label): + # Step 1: Check for ASCII + if isinstance(label, bytes): + pure_ascii = True + else: + try: + label = label.encode("ascii") + pure_ascii = True + except UnicodeError: + pure_ascii = False + if not pure_ascii: + # Step 2: Perform nameprep + label = nameprep(label) + # It doesn't say this, but apparently, it should be ASCII now + try: + label = label.encode("ascii") + except UnicodeError: + raise UnicodeError("Invalid character in IDN label") + # Step 3: Check for ACE prefix + if not label.startswith(ace_prefix): + return str(label, "ascii") + + # Step 4: Remove ACE prefix + label1 = label[len(ace_prefix):] + + # Step 5: Decode using PUNYCODE + result = label1.decode("punycode") + + # Step 6: Apply ToASCII + label2 = ToASCII(result) + + # Step 7: Compare the result of step 6 with the one of step 3 + # label2 will already be in lower case. + if str(label, "ascii").lower() != str(label2, "ascii"): + raise UnicodeError("IDNA does not round-trip", label, label2) + + # Step 8: return the result of step 5 + return result + +### Codec APIs + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + + if errors != 'strict': + # IDNA is quite clear that implementations must be strict + raise UnicodeError("unsupported error handling "+errors) + + if not input: + return b'', 0 + + try: + result = input.encode('ascii') + except UnicodeEncodeError: + pass + else: + # ASCII name: fast path + labels = result.split(b'.') + for label in labels[:-1]: + if not (0 < len(label) < 64): + raise UnicodeError("label empty or too long") + if len(labels[-1]) >= 64: + raise UnicodeError("label too long") + return result, len(input) + + result = bytearray() + labels = dots.split(input) + if labels and not labels[-1]: + trailing_dot = b'.' + del labels[-1] + else: + trailing_dot = b'' + for label in labels: + if result: + # Join with U+002E + result.extend(b'.') + result.extend(ToASCII(label)) + return bytes(result+trailing_dot), len(input) + + def decode(self, input, errors='strict'): + + if errors != 'strict': + raise UnicodeError("Unsupported error handling "+errors) + + if not input: + return "", 0 + + # IDNA allows decoding to operate on Unicode strings, too. + if not isinstance(input, bytes): + # XXX obviously wrong, see #3232 + input = bytes(input) + + if ace_prefix not in input: + # Fast path + try: + return input.decode('ascii'), len(input) + except UnicodeDecodeError: + pass + + labels = input.split(b".") + + if labels and len(labels[-1]) == 0: + trailing_dot = '.' + del labels[-1] + else: + trailing_dot = '' + + result = [] + for label in labels: + result.append(ToUnicode(label)) + + return ".".join(result)+trailing_dot, len(input) + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, input, errors, final): + if errors != 'strict': + # IDNA is quite clear that implementations must be strict + raise UnicodeError("unsupported error handling "+errors) + + if not input: + return (b'', 0) + + labels = dots.split(input) + trailing_dot = b'' + if labels: + if not labels[-1]: + trailing_dot = b'.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = b'.' + + result = bytearray() + size = 0 + for label in labels: + if size: + # Join with U+002E + result.extend(b'.') + size += 1 + result.extend(ToASCII(label)) + size += len(label) + + result += trailing_dot + size += len(trailing_dot) + return (bytes(result), size) + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, input, errors, final): + if errors != 'strict': + raise UnicodeError("Unsupported error handling "+errors) + + if not input: + return ("", 0) + + # IDNA allows decoding to operate on Unicode strings, too. + if isinstance(input, str): + labels = dots.split(input) + else: + # Must be ASCII string + input = str(input, "ascii") + labels = input.split(".") + + trailing_dot = '' + if labels: + if not labels[-1]: + trailing_dot = '.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = '.' + + result = [] + size = 0 + for label in labels: + result.append(ToUnicode(label)) + if size: + size += 1 + size += len(label) + + result = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='idna', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/iso2022_jp.py b/winvenv/Lib/encodings/iso2022_jp.py new file mode 100644 index 0000000..ab04060 --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_jp.py @@ -0,0 +1,39 @@ +# +# iso2022_jp.py: Python Unicode Codec for ISO2022_JP +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso2022_jp_1.py b/winvenv/Lib/encodings/iso2022_jp_1.py new file mode 100644 index 0000000..997044d --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_jp_1.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_1.py: Python Unicode Codec for ISO2022_JP_1 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_1') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_1', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso2022_jp_2.py b/winvenv/Lib/encodings/iso2022_jp_2.py new file mode 100644 index 0000000..9106bf7 --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_jp_2.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_2.py: Python Unicode Codec for ISO2022_JP_2 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_2') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_2', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso2022_jp_2004.py b/winvenv/Lib/encodings/iso2022_jp_2004.py new file mode 100644 index 0000000..40198bf --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_jp_2004.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_2004.py: Python Unicode Codec for ISO2022_JP_2004 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_2004') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_2004', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso2022_jp_3.py b/winvenv/Lib/encodings/iso2022_jp_3.py new file mode 100644 index 0000000..346e08b --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_jp_3.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_3.py: Python Unicode Codec for ISO2022_JP_3 +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_3') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_3', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso2022_jp_ext.py b/winvenv/Lib/encodings/iso2022_jp_ext.py new file mode 100644 index 0000000..752bab9 --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_jp_ext.py @@ -0,0 +1,39 @@ +# +# iso2022_jp_ext.py: Python Unicode Codec for ISO2022_JP_EXT +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_jp_ext') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_jp_ext', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso2022_kr.py b/winvenv/Lib/encodings/iso2022_kr.py new file mode 100644 index 0000000..bf70187 --- /dev/null +++ b/winvenv/Lib/encodings/iso2022_kr.py @@ -0,0 +1,39 @@ +# +# iso2022_kr.py: Python Unicode Codec for ISO2022_KR +# +# Written by Hye-Shik Chang +# + +import _codecs_iso2022, codecs +import _multibytecodec as mbc + +codec = _codecs_iso2022.getcodec('iso2022_kr') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='iso2022_kr', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/iso8859_1.py b/winvenv/Lib/encodings/iso8859_1.py new file mode 100644 index 0000000..8cfc01f --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_1.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_1 generated from 'MAPPINGS/ISO8859/8859-1.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-1', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic) + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xDE -> LATIN CAPITAL LETTER THORN (Icelandic) + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf0' # 0xF0 -> LATIN SMALL LETTER ETH (Icelandic) + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0xFE -> LATIN SMALL LETTER THORN (Icelandic) + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_10.py b/winvenv/Lib/encodings/iso8859_10.py new file mode 100644 index 0000000..b4fb041 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_10.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_10 generated from 'MAPPINGS/ISO8859/8859-10.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-10', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u0112' # 0xA2 -> LATIN CAPITAL LETTER E WITH MACRON + '\u0122' # 0xA3 -> LATIN CAPITAL LETTER G WITH CEDILLA + '\u012a' # 0xA4 -> LATIN CAPITAL LETTER I WITH MACRON + '\u0128' # 0xA5 -> LATIN CAPITAL LETTER I WITH TILDE + '\u0136' # 0xA6 -> LATIN CAPITAL LETTER K WITH CEDILLA + '\xa7' # 0xA7 -> SECTION SIGN + '\u013b' # 0xA8 -> LATIN CAPITAL LETTER L WITH CEDILLA + '\u0110' # 0xA9 -> LATIN CAPITAL LETTER D WITH STROKE + '\u0160' # 0xAA -> LATIN CAPITAL LETTER S WITH CARON + '\u0166' # 0xAB -> LATIN CAPITAL LETTER T WITH STROKE + '\u017d' # 0xAC -> LATIN CAPITAL LETTER Z WITH CARON + '\xad' # 0xAD -> SOFT HYPHEN + '\u016a' # 0xAE -> LATIN CAPITAL LETTER U WITH MACRON + '\u014a' # 0xAF -> LATIN CAPITAL LETTER ENG + '\xb0' # 0xB0 -> DEGREE SIGN + '\u0105' # 0xB1 -> LATIN SMALL LETTER A WITH OGONEK + '\u0113' # 0xB2 -> LATIN SMALL LETTER E WITH MACRON + '\u0123' # 0xB3 -> LATIN SMALL LETTER G WITH CEDILLA + '\u012b' # 0xB4 -> LATIN SMALL LETTER I WITH MACRON + '\u0129' # 0xB5 -> LATIN SMALL LETTER I WITH TILDE + '\u0137' # 0xB6 -> LATIN SMALL LETTER K WITH CEDILLA + '\xb7' # 0xB7 -> MIDDLE DOT + '\u013c' # 0xB8 -> LATIN SMALL LETTER L WITH CEDILLA + '\u0111' # 0xB9 -> LATIN SMALL LETTER D WITH STROKE + '\u0161' # 0xBA -> LATIN SMALL LETTER S WITH CARON + '\u0167' # 0xBB -> LATIN SMALL LETTER T WITH STROKE + '\u017e' # 0xBC -> LATIN SMALL LETTER Z WITH CARON + '\u2015' # 0xBD -> HORIZONTAL BAR + '\u016b' # 0xBE -> LATIN SMALL LETTER U WITH MACRON + '\u014b' # 0xBF -> LATIN SMALL LETTER ENG + '\u0100' # 0xC0 -> LATIN CAPITAL LETTER A WITH MACRON + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\u012e' # 0xC7 -> LATIN CAPITAL LETTER I WITH OGONEK + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u0116' # 0xCC -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic) + '\u0145' # 0xD1 -> LATIN CAPITAL LETTER N WITH CEDILLA + '\u014c' # 0xD2 -> LATIN CAPITAL LETTER O WITH MACRON + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\u0168' # 0xD7 -> LATIN CAPITAL LETTER U WITH TILDE + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\u0172' # 0xD9 -> LATIN CAPITAL LETTER U WITH OGONEK + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xDE -> LATIN CAPITAL LETTER THORN (Icelandic) + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + '\u0101' # 0xE0 -> LATIN SMALL LETTER A WITH MACRON + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\u012f' # 0xE7 -> LATIN SMALL LETTER I WITH OGONEK + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\u0117' # 0xEC -> LATIN SMALL LETTER E WITH DOT ABOVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf0' # 0xF0 -> LATIN SMALL LETTER ETH (Icelandic) + '\u0146' # 0xF1 -> LATIN SMALL LETTER N WITH CEDILLA + '\u014d' # 0xF2 -> LATIN SMALL LETTER O WITH MACRON + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\u0169' # 0xF7 -> LATIN SMALL LETTER U WITH TILDE + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\u0173' # 0xF9 -> LATIN SMALL LETTER U WITH OGONEK + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0xFE -> LATIN SMALL LETTER THORN (Icelandic) + '\u0138' # 0xFF -> LATIN SMALL LETTER KRA +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_11.py b/winvenv/Lib/encodings/iso8859_11.py new file mode 100644 index 0000000..c7258ec --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_11.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_11 generated from 'MAPPINGS/ISO8859/8859-11.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-11', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0e01' # 0xA1 -> THAI CHARACTER KO KAI + '\u0e02' # 0xA2 -> THAI CHARACTER KHO KHAI + '\u0e03' # 0xA3 -> THAI CHARACTER KHO KHUAT + '\u0e04' # 0xA4 -> THAI CHARACTER KHO KHWAI + '\u0e05' # 0xA5 -> THAI CHARACTER KHO KHON + '\u0e06' # 0xA6 -> THAI CHARACTER KHO RAKHANG + '\u0e07' # 0xA7 -> THAI CHARACTER NGO NGU + '\u0e08' # 0xA8 -> THAI CHARACTER CHO CHAN + '\u0e09' # 0xA9 -> THAI CHARACTER CHO CHING + '\u0e0a' # 0xAA -> THAI CHARACTER CHO CHANG + '\u0e0b' # 0xAB -> THAI CHARACTER SO SO + '\u0e0c' # 0xAC -> THAI CHARACTER CHO CHOE + '\u0e0d' # 0xAD -> THAI CHARACTER YO YING + '\u0e0e' # 0xAE -> THAI CHARACTER DO CHADA + '\u0e0f' # 0xAF -> THAI CHARACTER TO PATAK + '\u0e10' # 0xB0 -> THAI CHARACTER THO THAN + '\u0e11' # 0xB1 -> THAI CHARACTER THO NANGMONTHO + '\u0e12' # 0xB2 -> THAI CHARACTER THO PHUTHAO + '\u0e13' # 0xB3 -> THAI CHARACTER NO NEN + '\u0e14' # 0xB4 -> THAI CHARACTER DO DEK + '\u0e15' # 0xB5 -> THAI CHARACTER TO TAO + '\u0e16' # 0xB6 -> THAI CHARACTER THO THUNG + '\u0e17' # 0xB7 -> THAI CHARACTER THO THAHAN + '\u0e18' # 0xB8 -> THAI CHARACTER THO THONG + '\u0e19' # 0xB9 -> THAI CHARACTER NO NU + '\u0e1a' # 0xBA -> THAI CHARACTER BO BAIMAI + '\u0e1b' # 0xBB -> THAI CHARACTER PO PLA + '\u0e1c' # 0xBC -> THAI CHARACTER PHO PHUNG + '\u0e1d' # 0xBD -> THAI CHARACTER FO FA + '\u0e1e' # 0xBE -> THAI CHARACTER PHO PHAN + '\u0e1f' # 0xBF -> THAI CHARACTER FO FAN + '\u0e20' # 0xC0 -> THAI CHARACTER PHO SAMPHAO + '\u0e21' # 0xC1 -> THAI CHARACTER MO MA + '\u0e22' # 0xC2 -> THAI CHARACTER YO YAK + '\u0e23' # 0xC3 -> THAI CHARACTER RO RUA + '\u0e24' # 0xC4 -> THAI CHARACTER RU + '\u0e25' # 0xC5 -> THAI CHARACTER LO LING + '\u0e26' # 0xC6 -> THAI CHARACTER LU + '\u0e27' # 0xC7 -> THAI CHARACTER WO WAEN + '\u0e28' # 0xC8 -> THAI CHARACTER SO SALA + '\u0e29' # 0xC9 -> THAI CHARACTER SO RUSI + '\u0e2a' # 0xCA -> THAI CHARACTER SO SUA + '\u0e2b' # 0xCB -> THAI CHARACTER HO HIP + '\u0e2c' # 0xCC -> THAI CHARACTER LO CHULA + '\u0e2d' # 0xCD -> THAI CHARACTER O ANG + '\u0e2e' # 0xCE -> THAI CHARACTER HO NOKHUK + '\u0e2f' # 0xCF -> THAI CHARACTER PAIYANNOI + '\u0e30' # 0xD0 -> THAI CHARACTER SARA A + '\u0e31' # 0xD1 -> THAI CHARACTER MAI HAN-AKAT + '\u0e32' # 0xD2 -> THAI CHARACTER SARA AA + '\u0e33' # 0xD3 -> THAI CHARACTER SARA AM + '\u0e34' # 0xD4 -> THAI CHARACTER SARA I + '\u0e35' # 0xD5 -> THAI CHARACTER SARA II + '\u0e36' # 0xD6 -> THAI CHARACTER SARA UE + '\u0e37' # 0xD7 -> THAI CHARACTER SARA UEE + '\u0e38' # 0xD8 -> THAI CHARACTER SARA U + '\u0e39' # 0xD9 -> THAI CHARACTER SARA UU + '\u0e3a' # 0xDA -> THAI CHARACTER PHINTHU + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u0e3f' # 0xDF -> THAI CURRENCY SYMBOL BAHT + '\u0e40' # 0xE0 -> THAI CHARACTER SARA E + '\u0e41' # 0xE1 -> THAI CHARACTER SARA AE + '\u0e42' # 0xE2 -> THAI CHARACTER SARA O + '\u0e43' # 0xE3 -> THAI CHARACTER SARA AI MAIMUAN + '\u0e44' # 0xE4 -> THAI CHARACTER SARA AI MAIMALAI + '\u0e45' # 0xE5 -> THAI CHARACTER LAKKHANGYAO + '\u0e46' # 0xE6 -> THAI CHARACTER MAIYAMOK + '\u0e47' # 0xE7 -> THAI CHARACTER MAITAIKHU + '\u0e48' # 0xE8 -> THAI CHARACTER MAI EK + '\u0e49' # 0xE9 -> THAI CHARACTER MAI THO + '\u0e4a' # 0xEA -> THAI CHARACTER MAI TRI + '\u0e4b' # 0xEB -> THAI CHARACTER MAI CHATTAWA + '\u0e4c' # 0xEC -> THAI CHARACTER THANTHAKHAT + '\u0e4d' # 0xED -> THAI CHARACTER NIKHAHIT + '\u0e4e' # 0xEE -> THAI CHARACTER YAMAKKAN + '\u0e4f' # 0xEF -> THAI CHARACTER FONGMAN + '\u0e50' # 0xF0 -> THAI DIGIT ZERO + '\u0e51' # 0xF1 -> THAI DIGIT ONE + '\u0e52' # 0xF2 -> THAI DIGIT TWO + '\u0e53' # 0xF3 -> THAI DIGIT THREE + '\u0e54' # 0xF4 -> THAI DIGIT FOUR + '\u0e55' # 0xF5 -> THAI DIGIT FIVE + '\u0e56' # 0xF6 -> THAI DIGIT SIX + '\u0e57' # 0xF7 -> THAI DIGIT SEVEN + '\u0e58' # 0xF8 -> THAI DIGIT EIGHT + '\u0e59' # 0xF9 -> THAI DIGIT NINE + '\u0e5a' # 0xFA -> THAI CHARACTER ANGKHANKHU + '\u0e5b' # 0xFB -> THAI CHARACTER KHOMUT + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_13.py b/winvenv/Lib/encodings/iso8859_13.py new file mode 100644 index 0000000..6f8eab2 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_13.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_13 generated from 'MAPPINGS/ISO8859/8859-13.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-13', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u201d' # 0xA1 -> RIGHT DOUBLE QUOTATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u201e' # 0xA5 -> DOUBLE LOW-9 QUOTATION MARK + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xd8' # 0xA8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u0156' # 0xAA -> LATIN CAPITAL LETTER R WITH CEDILLA + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xc6' # 0xAF -> LATIN CAPITAL LETTER AE + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\u201c' # 0xB4 -> LEFT DOUBLE QUOTATION MARK + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xf8' # 0xB8 -> LATIN SMALL LETTER O WITH STROKE + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\u0157' # 0xBA -> LATIN SMALL LETTER R WITH CEDILLA + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xe6' # 0xBF -> LATIN SMALL LETTER AE + '\u0104' # 0xC0 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u012e' # 0xC1 -> LATIN CAPITAL LETTER I WITH OGONEK + '\u0100' # 0xC2 -> LATIN CAPITAL LETTER A WITH MACRON + '\u0106' # 0xC3 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\u0118' # 0xC6 -> LATIN CAPITAL LETTER E WITH OGONEK + '\u0112' # 0xC7 -> LATIN CAPITAL LETTER E WITH MACRON + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0179' # 0xCA -> LATIN CAPITAL LETTER Z WITH ACUTE + '\u0116' # 0xCB -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\u0122' # 0xCC -> LATIN CAPITAL LETTER G WITH CEDILLA + '\u0136' # 0xCD -> LATIN CAPITAL LETTER K WITH CEDILLA + '\u012a' # 0xCE -> LATIN CAPITAL LETTER I WITH MACRON + '\u013b' # 0xCF -> LATIN CAPITAL LETTER L WITH CEDILLA + '\u0160' # 0xD0 -> LATIN CAPITAL LETTER S WITH CARON + '\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\u0145' # 0xD2 -> LATIN CAPITAL LETTER N WITH CEDILLA + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\u014c' # 0xD4 -> LATIN CAPITAL LETTER O WITH MACRON + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\u0172' # 0xD8 -> LATIN CAPITAL LETTER U WITH OGONEK + '\u0141' # 0xD9 -> LATIN CAPITAL LETTER L WITH STROKE + '\u015a' # 0xDA -> LATIN CAPITAL LETTER S WITH ACUTE + '\u016a' # 0xDB -> LATIN CAPITAL LETTER U WITH MACRON + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u017b' # 0xDD -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\u017d' # 0xDE -> LATIN CAPITAL LETTER Z WITH CARON + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + '\u0105' # 0xE0 -> LATIN SMALL LETTER A WITH OGONEK + '\u012f' # 0xE1 -> LATIN SMALL LETTER I WITH OGONEK + '\u0101' # 0xE2 -> LATIN SMALL LETTER A WITH MACRON + '\u0107' # 0xE3 -> LATIN SMALL LETTER C WITH ACUTE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\u0119' # 0xE6 -> LATIN SMALL LETTER E WITH OGONEK + '\u0113' # 0xE7 -> LATIN SMALL LETTER E WITH MACRON + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\u017a' # 0xEA -> LATIN SMALL LETTER Z WITH ACUTE + '\u0117' # 0xEB -> LATIN SMALL LETTER E WITH DOT ABOVE + '\u0123' # 0xEC -> LATIN SMALL LETTER G WITH CEDILLA + '\u0137' # 0xED -> LATIN SMALL LETTER K WITH CEDILLA + '\u012b' # 0xEE -> LATIN SMALL LETTER I WITH MACRON + '\u013c' # 0xEF -> LATIN SMALL LETTER L WITH CEDILLA + '\u0161' # 0xF0 -> LATIN SMALL LETTER S WITH CARON + '\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + '\u0146' # 0xF2 -> LATIN SMALL LETTER N WITH CEDILLA + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\u014d' # 0xF4 -> LATIN SMALL LETTER O WITH MACRON + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\u0173' # 0xF8 -> LATIN SMALL LETTER U WITH OGONEK + '\u0142' # 0xF9 -> LATIN SMALL LETTER L WITH STROKE + '\u015b' # 0xFA -> LATIN SMALL LETTER S WITH ACUTE + '\u016b' # 0xFB -> LATIN SMALL LETTER U WITH MACRON + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u017e' # 0xFE -> LATIN SMALL LETTER Z WITH CARON + '\u2019' # 0xFF -> RIGHT SINGLE QUOTATION MARK +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_14.py b/winvenv/Lib/encodings/iso8859_14.py new file mode 100644 index 0000000..7568d4e --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_14.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_14 generated from 'MAPPINGS/ISO8859/8859-14.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-14', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u1e02' # 0xA1 -> LATIN CAPITAL LETTER B WITH DOT ABOVE + '\u1e03' # 0xA2 -> LATIN SMALL LETTER B WITH DOT ABOVE + '\xa3' # 0xA3 -> POUND SIGN + '\u010a' # 0xA4 -> LATIN CAPITAL LETTER C WITH DOT ABOVE + '\u010b' # 0xA5 -> LATIN SMALL LETTER C WITH DOT ABOVE + '\u1e0a' # 0xA6 -> LATIN CAPITAL LETTER D WITH DOT ABOVE + '\xa7' # 0xA7 -> SECTION SIGN + '\u1e80' # 0xA8 -> LATIN CAPITAL LETTER W WITH GRAVE + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u1e82' # 0xAA -> LATIN CAPITAL LETTER W WITH ACUTE + '\u1e0b' # 0xAB -> LATIN SMALL LETTER D WITH DOT ABOVE + '\u1ef2' # 0xAC -> LATIN CAPITAL LETTER Y WITH GRAVE + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\u0178' # 0xAF -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\u1e1e' # 0xB0 -> LATIN CAPITAL LETTER F WITH DOT ABOVE + '\u1e1f' # 0xB1 -> LATIN SMALL LETTER F WITH DOT ABOVE + '\u0120' # 0xB2 -> LATIN CAPITAL LETTER G WITH DOT ABOVE + '\u0121' # 0xB3 -> LATIN SMALL LETTER G WITH DOT ABOVE + '\u1e40' # 0xB4 -> LATIN CAPITAL LETTER M WITH DOT ABOVE + '\u1e41' # 0xB5 -> LATIN SMALL LETTER M WITH DOT ABOVE + '\xb6' # 0xB6 -> PILCROW SIGN + '\u1e56' # 0xB7 -> LATIN CAPITAL LETTER P WITH DOT ABOVE + '\u1e81' # 0xB8 -> LATIN SMALL LETTER W WITH GRAVE + '\u1e57' # 0xB9 -> LATIN SMALL LETTER P WITH DOT ABOVE + '\u1e83' # 0xBA -> LATIN SMALL LETTER W WITH ACUTE + '\u1e60' # 0xBB -> LATIN CAPITAL LETTER S WITH DOT ABOVE + '\u1ef3' # 0xBC -> LATIN SMALL LETTER Y WITH GRAVE + '\u1e84' # 0xBD -> LATIN CAPITAL LETTER W WITH DIAERESIS + '\u1e85' # 0xBE -> LATIN SMALL LETTER W WITH DIAERESIS + '\u1e61' # 0xBF -> LATIN SMALL LETTER S WITH DOT ABOVE + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u0174' # 0xD0 -> LATIN CAPITAL LETTER W WITH CIRCUMFLEX + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\u1e6a' # 0xD7 -> LATIN CAPITAL LETTER T WITH DOT ABOVE + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\u0176' # 0xDE -> LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\u0175' # 0xF0 -> LATIN SMALL LETTER W WITH CIRCUMFLEX + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\u1e6b' # 0xF7 -> LATIN SMALL LETTER T WITH DOT ABOVE + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\u0177' # 0xFE -> LATIN SMALL LETTER Y WITH CIRCUMFLEX + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_15.py b/winvenv/Lib/encodings/iso8859_15.py new file mode 100644 index 0000000..43bdecd --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_15.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_15 generated from 'MAPPINGS/ISO8859/8859-15.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-15', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\u20ac' # 0xA4 -> EURO SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\u0160' # 0xA6 -> LATIN CAPITAL LETTER S WITH CARON + '\xa7' # 0xA7 -> SECTION SIGN + '\u0161' # 0xA8 -> LATIN SMALL LETTER S WITH CARON + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\u017d' # 0xB4 -> LATIN CAPITAL LETTER Z WITH CARON + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u017e' # 0xB8 -> LATIN SMALL LETTER Z WITH CARON + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u0152' # 0xBC -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xBD -> LATIN SMALL LIGATURE OE + '\u0178' # 0xBE -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xDE -> LATIN CAPITAL LETTER THORN + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf0' # 0xF0 -> LATIN SMALL LETTER ETH + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0xFE -> LATIN SMALL LETTER THORN + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_16.py b/winvenv/Lib/encodings/iso8859_16.py new file mode 100644 index 0000000..e70c96e --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_16.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_16 generated from 'MAPPINGS/ISO8859/8859-16.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-16', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u0105' # 0xA2 -> LATIN SMALL LETTER A WITH OGONEK + '\u0141' # 0xA3 -> LATIN CAPITAL LETTER L WITH STROKE + '\u20ac' # 0xA4 -> EURO SIGN + '\u201e' # 0xA5 -> DOUBLE LOW-9 QUOTATION MARK + '\u0160' # 0xA6 -> LATIN CAPITAL LETTER S WITH CARON + '\xa7' # 0xA7 -> SECTION SIGN + '\u0161' # 0xA8 -> LATIN SMALL LETTER S WITH CARON + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u0218' # 0xAA -> LATIN CAPITAL LETTER S WITH COMMA BELOW + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u0179' # 0xAC -> LATIN CAPITAL LETTER Z WITH ACUTE + '\xad' # 0xAD -> SOFT HYPHEN + '\u017a' # 0xAE -> LATIN SMALL LETTER Z WITH ACUTE + '\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u010c' # 0xB2 -> LATIN CAPITAL LETTER C WITH CARON + '\u0142' # 0xB3 -> LATIN SMALL LETTER L WITH STROKE + '\u017d' # 0xB4 -> LATIN CAPITAL LETTER Z WITH CARON + '\u201d' # 0xB5 -> RIGHT DOUBLE QUOTATION MARK + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u017e' # 0xB8 -> LATIN SMALL LETTER Z WITH CARON + '\u010d' # 0xB9 -> LATIN SMALL LETTER C WITH CARON + '\u0219' # 0xBA -> LATIN SMALL LETTER S WITH COMMA BELOW + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u0152' # 0xBC -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xBD -> LATIN SMALL LIGATURE OE + '\u0178' # 0xBE -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u0106' # 0xC5 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + '\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u0150' # 0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\u015a' # 0xD7 -> LATIN CAPITAL LETTER S WITH ACUTE + '\u0170' # 0xD8 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u0118' # 0xDD -> LATIN CAPITAL LETTER E WITH OGONEK + '\u021a' # 0xDE -> LATIN CAPITAL LETTER T WITH COMMA BELOW + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\u0107' # 0xE5 -> LATIN SMALL LETTER C WITH ACUTE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + '\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\u0151' # 0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\u015b' # 0xF7 -> LATIN SMALL LETTER S WITH ACUTE + '\u0171' # 0xF8 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u0119' # 0xFD -> LATIN SMALL LETTER E WITH OGONEK + '\u021b' # 0xFE -> LATIN SMALL LETTER T WITH COMMA BELOW + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_2.py b/winvenv/Lib/encodings/iso8859_2.py new file mode 100644 index 0000000..3698747 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_2.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_2 generated from 'MAPPINGS/ISO8859/8859-2.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-2', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u02d8' # 0xA2 -> BREVE + '\u0141' # 0xA3 -> LATIN CAPITAL LETTER L WITH STROKE + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u013d' # 0xA5 -> LATIN CAPITAL LETTER L WITH CARON + '\u015a' # 0xA6 -> LATIN CAPITAL LETTER S WITH ACUTE + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\u0160' # 0xA9 -> LATIN CAPITAL LETTER S WITH CARON + '\u015e' # 0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA + '\u0164' # 0xAB -> LATIN CAPITAL LETTER T WITH CARON + '\u0179' # 0xAC -> LATIN CAPITAL LETTER Z WITH ACUTE + '\xad' # 0xAD -> SOFT HYPHEN + '\u017d' # 0xAE -> LATIN CAPITAL LETTER Z WITH CARON + '\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\xb0' # 0xB0 -> DEGREE SIGN + '\u0105' # 0xB1 -> LATIN SMALL LETTER A WITH OGONEK + '\u02db' # 0xB2 -> OGONEK + '\u0142' # 0xB3 -> LATIN SMALL LETTER L WITH STROKE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\u013e' # 0xB5 -> LATIN SMALL LETTER L WITH CARON + '\u015b' # 0xB6 -> LATIN SMALL LETTER S WITH ACUTE + '\u02c7' # 0xB7 -> CARON + '\xb8' # 0xB8 -> CEDILLA + '\u0161' # 0xB9 -> LATIN SMALL LETTER S WITH CARON + '\u015f' # 0xBA -> LATIN SMALL LETTER S WITH CEDILLA + '\u0165' # 0xBB -> LATIN SMALL LETTER T WITH CARON + '\u017a' # 0xBC -> LATIN SMALL LETTER Z WITH ACUTE + '\u02dd' # 0xBD -> DOUBLE ACUTE ACCENT + '\u017e' # 0xBE -> LATIN SMALL LETTER Z WITH CARON + '\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u0154' # 0xC0 -> LATIN CAPITAL LETTER R WITH ACUTE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\u0102' # 0xC3 -> LATIN CAPITAL LETTER A WITH BREVE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u0139' # 0xC5 -> LATIN CAPITAL LETTER L WITH ACUTE + '\u0106' # 0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u011a' # 0xCC -> LATIN CAPITAL LETTER E WITH CARON + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\u010e' # 0xCF -> LATIN CAPITAL LETTER D WITH CARON + '\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + '\u0143' # 0xD1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\u0147' # 0xD2 -> LATIN CAPITAL LETTER N WITH CARON + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u0150' # 0xD5 -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\u0158' # 0xD8 -> LATIN CAPITAL LETTER R WITH CARON + '\u016e' # 0xD9 -> LATIN CAPITAL LETTER U WITH RING ABOVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\u0170' # 0xDB -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\u0162' # 0xDE -> LATIN CAPITAL LETTER T WITH CEDILLA + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\u0155' # 0xE0 -> LATIN SMALL LETTER R WITH ACUTE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\u0103' # 0xE3 -> LATIN SMALL LETTER A WITH BREVE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\u013a' # 0xE5 -> LATIN SMALL LETTER L WITH ACUTE + '\u0107' # 0xE6 -> LATIN SMALL LETTER C WITH ACUTE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\u011b' # 0xEC -> LATIN SMALL LETTER E WITH CARON + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\u010f' # 0xEF -> LATIN SMALL LETTER D WITH CARON + '\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + '\u0144' # 0xF1 -> LATIN SMALL LETTER N WITH ACUTE + '\u0148' # 0xF2 -> LATIN SMALL LETTER N WITH CARON + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\u0151' # 0xF5 -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\u0159' # 0xF8 -> LATIN SMALL LETTER R WITH CARON + '\u016f' # 0xF9 -> LATIN SMALL LETTER U WITH RING ABOVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\u0171' # 0xFB -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\u0163' # 0xFE -> LATIN SMALL LETTER T WITH CEDILLA + '\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_3.py b/winvenv/Lib/encodings/iso8859_3.py new file mode 100644 index 0000000..96d3063 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_3.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_3 generated from 'MAPPINGS/ISO8859/8859-3.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-3', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0126' # 0xA1 -> LATIN CAPITAL LETTER H WITH STROKE + '\u02d8' # 0xA2 -> BREVE + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\ufffe' + '\u0124' # 0xA6 -> LATIN CAPITAL LETTER H WITH CIRCUMFLEX + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\u0130' # 0xA9 -> LATIN CAPITAL LETTER I WITH DOT ABOVE + '\u015e' # 0xAA -> LATIN CAPITAL LETTER S WITH CEDILLA + '\u011e' # 0xAB -> LATIN CAPITAL LETTER G WITH BREVE + '\u0134' # 0xAC -> LATIN CAPITAL LETTER J WITH CIRCUMFLEX + '\xad' # 0xAD -> SOFT HYPHEN + '\ufffe' + '\u017b' # 0xAF -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\xb0' # 0xB0 -> DEGREE SIGN + '\u0127' # 0xB1 -> LATIN SMALL LETTER H WITH STROKE + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\u0125' # 0xB6 -> LATIN SMALL LETTER H WITH CIRCUMFLEX + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\u0131' # 0xB9 -> LATIN SMALL LETTER DOTLESS I + '\u015f' # 0xBA -> LATIN SMALL LETTER S WITH CEDILLA + '\u011f' # 0xBB -> LATIN SMALL LETTER G WITH BREVE + '\u0135' # 0xBC -> LATIN SMALL LETTER J WITH CIRCUMFLEX + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\ufffe' + '\u017c' # 0xBF -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\ufffe' + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u010a' # 0xC5 -> LATIN CAPITAL LETTER C WITH DOT ABOVE + '\u0108' # 0xC6 -> LATIN CAPITAL LETTER C WITH CIRCUMFLEX + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\ufffe' + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u0120' # 0xD5 -> LATIN CAPITAL LETTER G WITH DOT ABOVE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\u011c' # 0xD8 -> LATIN CAPITAL LETTER G WITH CIRCUMFLEX + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u016c' # 0xDD -> LATIN CAPITAL LETTER U WITH BREVE + '\u015c' # 0xDE -> LATIN CAPITAL LETTER S WITH CIRCUMFLEX + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\ufffe' + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\u010b' # 0xE5 -> LATIN SMALL LETTER C WITH DOT ABOVE + '\u0109' # 0xE6 -> LATIN SMALL LETTER C WITH CIRCUMFLEX + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\ufffe' + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\u0121' # 0xF5 -> LATIN SMALL LETTER G WITH DOT ABOVE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\u011d' # 0xF8 -> LATIN SMALL LETTER G WITH CIRCUMFLEX + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u016d' # 0xFD -> LATIN SMALL LETTER U WITH BREVE + '\u015d' # 0xFE -> LATIN SMALL LETTER S WITH CIRCUMFLEX + '\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_4.py b/winvenv/Lib/encodings/iso8859_4.py new file mode 100644 index 0000000..65c1e00 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_4.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_4 generated from 'MAPPINGS/ISO8859/8859-4.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-4', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0104' # 0xA1 -> LATIN CAPITAL LETTER A WITH OGONEK + '\u0138' # 0xA2 -> LATIN SMALL LETTER KRA + '\u0156' # 0xA3 -> LATIN CAPITAL LETTER R WITH CEDILLA + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u0128' # 0xA5 -> LATIN CAPITAL LETTER I WITH TILDE + '\u013b' # 0xA6 -> LATIN CAPITAL LETTER L WITH CEDILLA + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\u0160' # 0xA9 -> LATIN CAPITAL LETTER S WITH CARON + '\u0112' # 0xAA -> LATIN CAPITAL LETTER E WITH MACRON + '\u0122' # 0xAB -> LATIN CAPITAL LETTER G WITH CEDILLA + '\u0166' # 0xAC -> LATIN CAPITAL LETTER T WITH STROKE + '\xad' # 0xAD -> SOFT HYPHEN + '\u017d' # 0xAE -> LATIN CAPITAL LETTER Z WITH CARON + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\u0105' # 0xB1 -> LATIN SMALL LETTER A WITH OGONEK + '\u02db' # 0xB2 -> OGONEK + '\u0157' # 0xB3 -> LATIN SMALL LETTER R WITH CEDILLA + '\xb4' # 0xB4 -> ACUTE ACCENT + '\u0129' # 0xB5 -> LATIN SMALL LETTER I WITH TILDE + '\u013c' # 0xB6 -> LATIN SMALL LETTER L WITH CEDILLA + '\u02c7' # 0xB7 -> CARON + '\xb8' # 0xB8 -> CEDILLA + '\u0161' # 0xB9 -> LATIN SMALL LETTER S WITH CARON + '\u0113' # 0xBA -> LATIN SMALL LETTER E WITH MACRON + '\u0123' # 0xBB -> LATIN SMALL LETTER G WITH CEDILLA + '\u0167' # 0xBC -> LATIN SMALL LETTER T WITH STROKE + '\u014a' # 0xBD -> LATIN CAPITAL LETTER ENG + '\u017e' # 0xBE -> LATIN SMALL LETTER Z WITH CARON + '\u014b' # 0xBF -> LATIN SMALL LETTER ENG + '\u0100' # 0xC0 -> LATIN CAPITAL LETTER A WITH MACRON + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\u012e' # 0xC7 -> LATIN CAPITAL LETTER I WITH OGONEK + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0118' # 0xCA -> LATIN CAPITAL LETTER E WITH OGONEK + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u0116' # 0xCC -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\u012a' # 0xCF -> LATIN CAPITAL LETTER I WITH MACRON + '\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + '\u0145' # 0xD1 -> LATIN CAPITAL LETTER N WITH CEDILLA + '\u014c' # 0xD2 -> LATIN CAPITAL LETTER O WITH MACRON + '\u0136' # 0xD3 -> LATIN CAPITAL LETTER K WITH CEDILLA + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\u0172' # 0xD9 -> LATIN CAPITAL LETTER U WITH OGONEK + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u0168' # 0xDD -> LATIN CAPITAL LETTER U WITH TILDE + '\u016a' # 0xDE -> LATIN CAPITAL LETTER U WITH MACRON + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\u0101' # 0xE0 -> LATIN SMALL LETTER A WITH MACRON + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\u012f' # 0xE7 -> LATIN SMALL LETTER I WITH OGONEK + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\u0119' # 0xEA -> LATIN SMALL LETTER E WITH OGONEK + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\u0117' # 0xEC -> LATIN SMALL LETTER E WITH DOT ABOVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\u012b' # 0xEF -> LATIN SMALL LETTER I WITH MACRON + '\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + '\u0146' # 0xF1 -> LATIN SMALL LETTER N WITH CEDILLA + '\u014d' # 0xF2 -> LATIN SMALL LETTER O WITH MACRON + '\u0137' # 0xF3 -> LATIN SMALL LETTER K WITH CEDILLA + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\u0173' # 0xF9 -> LATIN SMALL LETTER U WITH OGONEK + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u0169' # 0xFD -> LATIN SMALL LETTER U WITH TILDE + '\u016b' # 0xFE -> LATIN SMALL LETTER U WITH MACRON + '\u02d9' # 0xFF -> DOT ABOVE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_5.py b/winvenv/Lib/encodings/iso8859_5.py new file mode 100644 index 0000000..a3c868a --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_5.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_5 generated from 'MAPPINGS/ISO8859/8859-5.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-5', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u0401' # 0xA1 -> CYRILLIC CAPITAL LETTER IO + '\u0402' # 0xA2 -> CYRILLIC CAPITAL LETTER DJE + '\u0403' # 0xA3 -> CYRILLIC CAPITAL LETTER GJE + '\u0404' # 0xA4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\u0405' # 0xA5 -> CYRILLIC CAPITAL LETTER DZE + '\u0406' # 0xA6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0407' # 0xA7 -> CYRILLIC CAPITAL LETTER YI + '\u0408' # 0xA8 -> CYRILLIC CAPITAL LETTER JE + '\u0409' # 0xA9 -> CYRILLIC CAPITAL LETTER LJE + '\u040a' # 0xAA -> CYRILLIC CAPITAL LETTER NJE + '\u040b' # 0xAB -> CYRILLIC CAPITAL LETTER TSHE + '\u040c' # 0xAC -> CYRILLIC CAPITAL LETTER KJE + '\xad' # 0xAD -> SOFT HYPHEN + '\u040e' # 0xAE -> CYRILLIC CAPITAL LETTER SHORT U + '\u040f' # 0xAF -> CYRILLIC CAPITAL LETTER DZHE + '\u0410' # 0xB0 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xB1 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0xB2 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0xB3 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0xB4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xB5 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0xB6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0xB7 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0xB8 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xB9 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xBA -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xBB -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xBC -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xBD -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xBE -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xBF -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0xC0 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xC1 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xC2 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xC3 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0xC4 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0xC5 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0xC6 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0xC7 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0xC8 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0xC9 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0xCA -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0xCB -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0xCC -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0xCD -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0xCE -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0xCF -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0xD0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xD1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0xD2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0xD3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0xD4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xD5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0xD7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0xD8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xD9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xDA -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xDB -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xDC -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xDD -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xDE -> CYRILLIC SMALL LETTER O + '\u043f' # 0xDF -> CYRILLIC SMALL LETTER PE + '\u0440' # 0xE0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xE1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xE2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xE3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0xE4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0xE5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0xE6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0xE7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0xE8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0xE9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0xEA -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0xEB -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0xEC -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0xED -> CYRILLIC SMALL LETTER E + '\u044e' # 0xEE -> CYRILLIC SMALL LETTER YU + '\u044f' # 0xEF -> CYRILLIC SMALL LETTER YA + '\u2116' # 0xF0 -> NUMERO SIGN + '\u0451' # 0xF1 -> CYRILLIC SMALL LETTER IO + '\u0452' # 0xF2 -> CYRILLIC SMALL LETTER DJE + '\u0453' # 0xF3 -> CYRILLIC SMALL LETTER GJE + '\u0454' # 0xF4 -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\u0455' # 0xF5 -> CYRILLIC SMALL LETTER DZE + '\u0456' # 0xF6 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0457' # 0xF7 -> CYRILLIC SMALL LETTER YI + '\u0458' # 0xF8 -> CYRILLIC SMALL LETTER JE + '\u0459' # 0xF9 -> CYRILLIC SMALL LETTER LJE + '\u045a' # 0xFA -> CYRILLIC SMALL LETTER NJE + '\u045b' # 0xFB -> CYRILLIC SMALL LETTER TSHE + '\u045c' # 0xFC -> CYRILLIC SMALL LETTER KJE + '\xa7' # 0xFD -> SECTION SIGN + '\u045e' # 0xFE -> CYRILLIC SMALL LETTER SHORT U + '\u045f' # 0xFF -> CYRILLIC SMALL LETTER DZHE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_6.py b/winvenv/Lib/encodings/iso8859_6.py new file mode 100644 index 0000000..b02ade6 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_6.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_6 generated from 'MAPPINGS/ISO8859/8859-6.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-6', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\ufffe' + '\ufffe' + '\ufffe' + '\xa4' # 0xA4 -> CURRENCY SIGN + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u060c' # 0xAC -> ARABIC COMMA + '\xad' # 0xAD -> SOFT HYPHEN + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u061b' # 0xBB -> ARABIC SEMICOLON + '\ufffe' + '\ufffe' + '\ufffe' + '\u061f' # 0xBF -> ARABIC QUESTION MARK + '\ufffe' + '\u0621' # 0xC1 -> ARABIC LETTER HAMZA + '\u0622' # 0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + '\u0623' # 0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + '\u0624' # 0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + '\u0625' # 0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + '\u0626' # 0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + '\u0627' # 0xC7 -> ARABIC LETTER ALEF + '\u0628' # 0xC8 -> ARABIC LETTER BEH + '\u0629' # 0xC9 -> ARABIC LETTER TEH MARBUTA + '\u062a' # 0xCA -> ARABIC LETTER TEH + '\u062b' # 0xCB -> ARABIC LETTER THEH + '\u062c' # 0xCC -> ARABIC LETTER JEEM + '\u062d' # 0xCD -> ARABIC LETTER HAH + '\u062e' # 0xCE -> ARABIC LETTER KHAH + '\u062f' # 0xCF -> ARABIC LETTER DAL + '\u0630' # 0xD0 -> ARABIC LETTER THAL + '\u0631' # 0xD1 -> ARABIC LETTER REH + '\u0632' # 0xD2 -> ARABIC LETTER ZAIN + '\u0633' # 0xD3 -> ARABIC LETTER SEEN + '\u0634' # 0xD4 -> ARABIC LETTER SHEEN + '\u0635' # 0xD5 -> ARABIC LETTER SAD + '\u0636' # 0xD6 -> ARABIC LETTER DAD + '\u0637' # 0xD7 -> ARABIC LETTER TAH + '\u0638' # 0xD8 -> ARABIC LETTER ZAH + '\u0639' # 0xD9 -> ARABIC LETTER AIN + '\u063a' # 0xDA -> ARABIC LETTER GHAIN + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u0640' # 0xE0 -> ARABIC TATWEEL + '\u0641' # 0xE1 -> ARABIC LETTER FEH + '\u0642' # 0xE2 -> ARABIC LETTER QAF + '\u0643' # 0xE3 -> ARABIC LETTER KAF + '\u0644' # 0xE4 -> ARABIC LETTER LAM + '\u0645' # 0xE5 -> ARABIC LETTER MEEM + '\u0646' # 0xE6 -> ARABIC LETTER NOON + '\u0647' # 0xE7 -> ARABIC LETTER HEH + '\u0648' # 0xE8 -> ARABIC LETTER WAW + '\u0649' # 0xE9 -> ARABIC LETTER ALEF MAKSURA + '\u064a' # 0xEA -> ARABIC LETTER YEH + '\u064b' # 0xEB -> ARABIC FATHATAN + '\u064c' # 0xEC -> ARABIC DAMMATAN + '\u064d' # 0xED -> ARABIC KASRATAN + '\u064e' # 0xEE -> ARABIC FATHA + '\u064f' # 0xEF -> ARABIC DAMMA + '\u0650' # 0xF0 -> ARABIC KASRA + '\u0651' # 0xF1 -> ARABIC SHADDA + '\u0652' # 0xF2 -> ARABIC SUKUN + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_7.py b/winvenv/Lib/encodings/iso8859_7.py new file mode 100644 index 0000000..d7b39cb --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_7.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_7 generated from 'MAPPINGS/ISO8859/8859-7.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-7', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u2018' # 0xA1 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xA2 -> RIGHT SINGLE QUOTATION MARK + '\xa3' # 0xA3 -> POUND SIGN + '\u20ac' # 0xA4 -> EURO SIGN + '\u20af' # 0xA5 -> DRACHMA SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u037a' # 0xAA -> GREEK YPOGEGRAMMENI + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\ufffe' + '\u2015' # 0xAF -> HORIZONTAL BAR + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\u0384' # 0xB4 -> GREEK TONOS + '\u0385' # 0xB5 -> GREEK DIALYTIKA TONOS + '\u0386' # 0xB6 -> GREEK CAPITAL LETTER ALPHA WITH TONOS + '\xb7' # 0xB7 -> MIDDLE DOT + '\u0388' # 0xB8 -> GREEK CAPITAL LETTER EPSILON WITH TONOS + '\u0389' # 0xB9 -> GREEK CAPITAL LETTER ETA WITH TONOS + '\u038a' # 0xBA -> GREEK CAPITAL LETTER IOTA WITH TONOS + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u038c' # 0xBC -> GREEK CAPITAL LETTER OMICRON WITH TONOS + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\u038e' # 0xBE -> GREEK CAPITAL LETTER UPSILON WITH TONOS + '\u038f' # 0xBF -> GREEK CAPITAL LETTER OMEGA WITH TONOS + '\u0390' # 0xC0 -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + '\u0391' # 0xC1 -> GREEK CAPITAL LETTER ALPHA + '\u0392' # 0xC2 -> GREEK CAPITAL LETTER BETA + '\u0393' # 0xC3 -> GREEK CAPITAL LETTER GAMMA + '\u0394' # 0xC4 -> GREEK CAPITAL LETTER DELTA + '\u0395' # 0xC5 -> GREEK CAPITAL LETTER EPSILON + '\u0396' # 0xC6 -> GREEK CAPITAL LETTER ZETA + '\u0397' # 0xC7 -> GREEK CAPITAL LETTER ETA + '\u0398' # 0xC8 -> GREEK CAPITAL LETTER THETA + '\u0399' # 0xC9 -> GREEK CAPITAL LETTER IOTA + '\u039a' # 0xCA -> GREEK CAPITAL LETTER KAPPA + '\u039b' # 0xCB -> GREEK CAPITAL LETTER LAMDA + '\u039c' # 0xCC -> GREEK CAPITAL LETTER MU + '\u039d' # 0xCD -> GREEK CAPITAL LETTER NU + '\u039e' # 0xCE -> GREEK CAPITAL LETTER XI + '\u039f' # 0xCF -> GREEK CAPITAL LETTER OMICRON + '\u03a0' # 0xD0 -> GREEK CAPITAL LETTER PI + '\u03a1' # 0xD1 -> GREEK CAPITAL LETTER RHO + '\ufffe' + '\u03a3' # 0xD3 -> GREEK CAPITAL LETTER SIGMA + '\u03a4' # 0xD4 -> GREEK CAPITAL LETTER TAU + '\u03a5' # 0xD5 -> GREEK CAPITAL LETTER UPSILON + '\u03a6' # 0xD6 -> GREEK CAPITAL LETTER PHI + '\u03a7' # 0xD7 -> GREEK CAPITAL LETTER CHI + '\u03a8' # 0xD8 -> GREEK CAPITAL LETTER PSI + '\u03a9' # 0xD9 -> GREEK CAPITAL LETTER OMEGA + '\u03aa' # 0xDA -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + '\u03ab' # 0xDB -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + '\u03ac' # 0xDC -> GREEK SMALL LETTER ALPHA WITH TONOS + '\u03ad' # 0xDD -> GREEK SMALL LETTER EPSILON WITH TONOS + '\u03ae' # 0xDE -> GREEK SMALL LETTER ETA WITH TONOS + '\u03af' # 0xDF -> GREEK SMALL LETTER IOTA WITH TONOS + '\u03b0' # 0xE0 -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + '\u03b1' # 0xE1 -> GREEK SMALL LETTER ALPHA + '\u03b2' # 0xE2 -> GREEK SMALL LETTER BETA + '\u03b3' # 0xE3 -> GREEK SMALL LETTER GAMMA + '\u03b4' # 0xE4 -> GREEK SMALL LETTER DELTA + '\u03b5' # 0xE5 -> GREEK SMALL LETTER EPSILON + '\u03b6' # 0xE6 -> GREEK SMALL LETTER ZETA + '\u03b7' # 0xE7 -> GREEK SMALL LETTER ETA + '\u03b8' # 0xE8 -> GREEK SMALL LETTER THETA + '\u03b9' # 0xE9 -> GREEK SMALL LETTER IOTA + '\u03ba' # 0xEA -> GREEK SMALL LETTER KAPPA + '\u03bb' # 0xEB -> GREEK SMALL LETTER LAMDA + '\u03bc' # 0xEC -> GREEK SMALL LETTER MU + '\u03bd' # 0xED -> GREEK SMALL LETTER NU + '\u03be' # 0xEE -> GREEK SMALL LETTER XI + '\u03bf' # 0xEF -> GREEK SMALL LETTER OMICRON + '\u03c0' # 0xF0 -> GREEK SMALL LETTER PI + '\u03c1' # 0xF1 -> GREEK SMALL LETTER RHO + '\u03c2' # 0xF2 -> GREEK SMALL LETTER FINAL SIGMA + '\u03c3' # 0xF3 -> GREEK SMALL LETTER SIGMA + '\u03c4' # 0xF4 -> GREEK SMALL LETTER TAU + '\u03c5' # 0xF5 -> GREEK SMALL LETTER UPSILON + '\u03c6' # 0xF6 -> GREEK SMALL LETTER PHI + '\u03c7' # 0xF7 -> GREEK SMALL LETTER CHI + '\u03c8' # 0xF8 -> GREEK SMALL LETTER PSI + '\u03c9' # 0xF9 -> GREEK SMALL LETTER OMEGA + '\u03ca' # 0xFA -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + '\u03cb' # 0xFB -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + '\u03cc' # 0xFC -> GREEK SMALL LETTER OMICRON WITH TONOS + '\u03cd' # 0xFD -> GREEK SMALL LETTER UPSILON WITH TONOS + '\u03ce' # 0xFE -> GREEK SMALL LETTER OMEGA WITH TONOS + '\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_8.py b/winvenv/Lib/encodings/iso8859_8.py new file mode 100644 index 0000000..8184902 --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_8.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_8 generated from 'MAPPINGS/ISO8859/8859-8.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-8', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\ufffe' + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xd7' # 0xAA -> MULTIPLICATION SIGN + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xf7' # 0xBA -> DIVISION SIGN + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u2017' # 0xDF -> DOUBLE LOW LINE + '\u05d0' # 0xE0 -> HEBREW LETTER ALEF + '\u05d1' # 0xE1 -> HEBREW LETTER BET + '\u05d2' # 0xE2 -> HEBREW LETTER GIMEL + '\u05d3' # 0xE3 -> HEBREW LETTER DALET + '\u05d4' # 0xE4 -> HEBREW LETTER HE + '\u05d5' # 0xE5 -> HEBREW LETTER VAV + '\u05d6' # 0xE6 -> HEBREW LETTER ZAYIN + '\u05d7' # 0xE7 -> HEBREW LETTER HET + '\u05d8' # 0xE8 -> HEBREW LETTER TET + '\u05d9' # 0xE9 -> HEBREW LETTER YOD + '\u05da' # 0xEA -> HEBREW LETTER FINAL KAF + '\u05db' # 0xEB -> HEBREW LETTER KAF + '\u05dc' # 0xEC -> HEBREW LETTER LAMED + '\u05dd' # 0xED -> HEBREW LETTER FINAL MEM + '\u05de' # 0xEE -> HEBREW LETTER MEM + '\u05df' # 0xEF -> HEBREW LETTER FINAL NUN + '\u05e0' # 0xF0 -> HEBREW LETTER NUN + '\u05e1' # 0xF1 -> HEBREW LETTER SAMEKH + '\u05e2' # 0xF2 -> HEBREW LETTER AYIN + '\u05e3' # 0xF3 -> HEBREW LETTER FINAL PE + '\u05e4' # 0xF4 -> HEBREW LETTER PE + '\u05e5' # 0xF5 -> HEBREW LETTER FINAL TSADI + '\u05e6' # 0xF6 -> HEBREW LETTER TSADI + '\u05e7' # 0xF7 -> HEBREW LETTER QOF + '\u05e8' # 0xF8 -> HEBREW LETTER RESH + '\u05e9' # 0xF9 -> HEBREW LETTER SHIN + '\u05ea' # 0xFA -> HEBREW LETTER TAV + '\ufffe' + '\ufffe' + '\u200e' # 0xFD -> LEFT-TO-RIGHT MARK + '\u200f' # 0xFE -> RIGHT-TO-LEFT MARK + '\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/iso8859_9.py b/winvenv/Lib/encodings/iso8859_9.py new file mode 100644 index 0000000..e539fdd --- /dev/null +++ b/winvenv/Lib/encodings/iso8859_9.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec iso8859_9 generated from 'MAPPINGS/ISO8859/8859-9.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-9', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\u011e' # 0xD0 -> LATIN CAPITAL LETTER G WITH BREVE + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u0130' # 0xDD -> LATIN CAPITAL LETTER I WITH DOT ABOVE + '\u015e' # 0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\u011f' # 0xF0 -> LATIN SMALL LETTER G WITH BREVE + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\u0131' # 0xFD -> LATIN SMALL LETTER DOTLESS I + '\u015f' # 0xFE -> LATIN SMALL LETTER S WITH CEDILLA + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/johab.py b/winvenv/Lib/encodings/johab.py new file mode 100644 index 0000000..512aeeb --- /dev/null +++ b/winvenv/Lib/encodings/johab.py @@ -0,0 +1,39 @@ +# +# johab.py: Python Unicode Codec for JOHAB +# +# Written by Hye-Shik Chang +# + +import _codecs_kr, codecs +import _multibytecodec as mbc + +codec = _codecs_kr.getcodec('johab') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='johab', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/koi8_r.py b/winvenv/Lib/encodings/koi8_r.py new file mode 100644 index 0000000..41ddde8 --- /dev/null +++ b/winvenv/Lib/encodings/koi8_r.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec koi8_r generated from 'MAPPINGS/VENDORS/MISC/KOI8-R.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='koi8-r', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u2500' # 0x80 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u2502' # 0x81 -> BOX DRAWINGS LIGHT VERTICAL + '\u250c' # 0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2510' # 0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2518' # 0x85 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u251c' # 0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2524' # 0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u252c' # 0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u2534' # 0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u253c' # 0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u2580' # 0x8B -> UPPER HALF BLOCK + '\u2584' # 0x8C -> LOWER HALF BLOCK + '\u2588' # 0x8D -> FULL BLOCK + '\u258c' # 0x8E -> LEFT HALF BLOCK + '\u2590' # 0x8F -> RIGHT HALF BLOCK + '\u2591' # 0x90 -> LIGHT SHADE + '\u2592' # 0x91 -> MEDIUM SHADE + '\u2593' # 0x92 -> DARK SHADE + '\u2320' # 0x93 -> TOP HALF INTEGRAL + '\u25a0' # 0x94 -> BLACK SQUARE + '\u2219' # 0x95 -> BULLET OPERATOR + '\u221a' # 0x96 -> SQUARE ROOT + '\u2248' # 0x97 -> ALMOST EQUAL TO + '\u2264' # 0x98 -> LESS-THAN OR EQUAL TO + '\u2265' # 0x99 -> GREATER-THAN OR EQUAL TO + '\xa0' # 0x9A -> NO-BREAK SPACE + '\u2321' # 0x9B -> BOTTOM HALF INTEGRAL + '\xb0' # 0x9C -> DEGREE SIGN + '\xb2' # 0x9D -> SUPERSCRIPT TWO + '\xb7' # 0x9E -> MIDDLE DOT + '\xf7' # 0x9F -> DIVISION SIGN + '\u2550' # 0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u2551' # 0xA1 -> BOX DRAWINGS DOUBLE VERTICAL + '\u2552' # 0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u0451' # 0xA3 -> CYRILLIC SMALL LETTER IO + '\u2553' # 0xA4 -> BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + '\u2554' # 0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u2555' # 0xA6 -> BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + '\u2556' # 0xA7 -> BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + '\u2557' # 0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u2558' # 0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2559' # 0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u255a' # 0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u255b' # 0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u255c' # 0xAD -> BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + '\u255d' # 0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255e' # 0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u2560' # 0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2561' # 0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u0401' # 0xB3 -> CYRILLIC CAPITAL LETTER IO + '\u2562' # 0xB4 -> BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + '\u2563' # 0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u2564' # 0xB6 -> BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + '\u2565' # 0xB7 -> BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + '\u2566' # 0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2567' # 0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2569' # 0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u256a' # 0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u256b' # 0xBD -> BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + '\u256c' # 0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa9' # 0xBF -> COPYRIGHT SIGN + '\u044e' # 0xC0 -> CYRILLIC SMALL LETTER YU + '\u0430' # 0xC1 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xC2 -> CYRILLIC SMALL LETTER BE + '\u0446' # 0xC3 -> CYRILLIC SMALL LETTER TSE + '\u0434' # 0xC4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xC5 -> CYRILLIC SMALL LETTER IE + '\u0444' # 0xC6 -> CYRILLIC SMALL LETTER EF + '\u0433' # 0xC7 -> CYRILLIC SMALL LETTER GHE + '\u0445' # 0xC8 -> CYRILLIC SMALL LETTER HA + '\u0438' # 0xC9 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xCA -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xCB -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xCC -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xCD -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xCE -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xCF -> CYRILLIC SMALL LETTER O + '\u043f' # 0xD0 -> CYRILLIC SMALL LETTER PE + '\u044f' # 0xD1 -> CYRILLIC SMALL LETTER YA + '\u0440' # 0xD2 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xD3 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xD4 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xD5 -> CYRILLIC SMALL LETTER U + '\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + '\u0432' # 0xD7 -> CYRILLIC SMALL LETTER VE + '\u044c' # 0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044b' # 0xD9 -> CYRILLIC SMALL LETTER YERU + '\u0437' # 0xDA -> CYRILLIC SMALL LETTER ZE + '\u0448' # 0xDB -> CYRILLIC SMALL LETTER SHA + '\u044d' # 0xDC -> CYRILLIC SMALL LETTER E + '\u0449' # 0xDD -> CYRILLIC SMALL LETTER SHCHA + '\u0447' # 0xDE -> CYRILLIC SMALL LETTER CHE + '\u044a' # 0xDF -> CYRILLIC SMALL LETTER HARD SIGN + '\u042e' # 0xE0 -> CYRILLIC CAPITAL LETTER YU + '\u0410' # 0xE1 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xE2 -> CYRILLIC CAPITAL LETTER BE + '\u0426' # 0xE3 -> CYRILLIC CAPITAL LETTER TSE + '\u0414' # 0xE4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xE5 -> CYRILLIC CAPITAL LETTER IE + '\u0424' # 0xE6 -> CYRILLIC CAPITAL LETTER EF + '\u0413' # 0xE7 -> CYRILLIC CAPITAL LETTER GHE + '\u0425' # 0xE8 -> CYRILLIC CAPITAL LETTER HA + '\u0418' # 0xE9 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xEA -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xEB -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xEC -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xED -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xEE -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xEF -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xF0 -> CYRILLIC CAPITAL LETTER PE + '\u042f' # 0xF1 -> CYRILLIC CAPITAL LETTER YA + '\u0420' # 0xF2 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xF3 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xF4 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xF5 -> CYRILLIC CAPITAL LETTER U + '\u0416' # 0xF6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0412' # 0xF7 -> CYRILLIC CAPITAL LETTER VE + '\u042c' # 0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042b' # 0xF9 -> CYRILLIC CAPITAL LETTER YERU + '\u0417' # 0xFA -> CYRILLIC CAPITAL LETTER ZE + '\u0428' # 0xFB -> CYRILLIC CAPITAL LETTER SHA + '\u042d' # 0xFC -> CYRILLIC CAPITAL LETTER E + '\u0429' # 0xFD -> CYRILLIC CAPITAL LETTER SHCHA + '\u0427' # 0xFE -> CYRILLIC CAPITAL LETTER CHE + '\u042a' # 0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/koi8_t.py b/winvenv/Lib/encodings/koi8_t.py new file mode 100644 index 0000000..b5415ba --- /dev/null +++ b/winvenv/Lib/encodings/koi8_t.py @@ -0,0 +1,308 @@ +""" Python Character Mapping Codec koi8_t +""" +# http://ru.wikipedia.org/wiki/КОИ-8 +# http://www.opensource.apple.com/source/libiconv/libiconv-4/libiconv/tests/KOI8-T.TXT + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='koi8-t', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u049b' # 0x80 -> CYRILLIC SMALL LETTER KA WITH DESCENDER + '\u0493' # 0x81 -> CYRILLIC SMALL LETTER GHE WITH STROKE + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0492' # 0x83 -> CYRILLIC CAPITAL LETTER GHE WITH STROKE + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\ufffe' # 0x88 -> UNDEFINED + '\u2030' # 0x89 -> PER MILLE SIGN + '\u04b3' # 0x8A -> CYRILLIC SMALL LETTER HA WITH DESCENDER + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u04b2' # 0x8C -> CYRILLIC CAPITAL LETTER HA WITH DESCENDER + '\u04b7' # 0x8D -> CYRILLIC SMALL LETTER CHE WITH DESCENDER + '\u04b6' # 0x8E -> CYRILLIC CAPITAL LETTER CHE WITH DESCENDER + '\ufffe' # 0x8F -> UNDEFINED + '\u049a' # 0x90 -> CYRILLIC CAPITAL LETTER KA WITH DESCENDER + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\ufffe' # 0x9A -> UNDEFINED + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\ufffe' # 0x9C -> UNDEFINED + '\ufffe' # 0x9D -> UNDEFINED + '\ufffe' # 0x9E -> UNDEFINED + '\ufffe' # 0x9F -> UNDEFINED + '\ufffe' # 0xA0 -> UNDEFINED + '\u04ef' # 0xA1 -> CYRILLIC SMALL LETTER U WITH MACRON + '\u04ee' # 0xA2 -> CYRILLIC CAPITAL LETTER U WITH MACRON + '\u0451' # 0xA3 -> CYRILLIC SMALL LETTER IO + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u04e3' # 0xA5 -> CYRILLIC SMALL LETTER I WITH MACRON + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\ufffe' # 0xA8 -> UNDEFINED + '\ufffe' # 0xA9 -> UNDEFINED + '\ufffe' # 0xAA -> UNDEFINED + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\ufffe' # 0xAF -> UNDEFINED + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\u0401' # 0xB3 -> CYRILLIC CAPITAL LETTER IO + '\ufffe' # 0xB4 -> UNDEFINED + '\u04e2' # 0xB5 -> CYRILLIC CAPITAL LETTER I WITH MACRON + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\ufffe' # 0xB8 -> UNDEFINED + '\u2116' # 0xB9 -> NUMERO SIGN + '\ufffe' # 0xBA -> UNDEFINED + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\ufffe' # 0xBC -> UNDEFINED + '\ufffe' # 0xBD -> UNDEFINED + '\ufffe' # 0xBE -> UNDEFINED + '\xa9' # 0xBF -> COPYRIGHT SIGN + '\u044e' # 0xC0 -> CYRILLIC SMALL LETTER YU + '\u0430' # 0xC1 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xC2 -> CYRILLIC SMALL LETTER BE + '\u0446' # 0xC3 -> CYRILLIC SMALL LETTER TSE + '\u0434' # 0xC4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xC5 -> CYRILLIC SMALL LETTER IE + '\u0444' # 0xC6 -> CYRILLIC SMALL LETTER EF + '\u0433' # 0xC7 -> CYRILLIC SMALL LETTER GHE + '\u0445' # 0xC8 -> CYRILLIC SMALL LETTER HA + '\u0438' # 0xC9 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xCA -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xCB -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xCC -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xCD -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xCE -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xCF -> CYRILLIC SMALL LETTER O + '\u043f' # 0xD0 -> CYRILLIC SMALL LETTER PE + '\u044f' # 0xD1 -> CYRILLIC SMALL LETTER YA + '\u0440' # 0xD2 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xD3 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xD4 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xD5 -> CYRILLIC SMALL LETTER U + '\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + '\u0432' # 0xD7 -> CYRILLIC SMALL LETTER VE + '\u044c' # 0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044b' # 0xD9 -> CYRILLIC SMALL LETTER YERU + '\u0437' # 0xDA -> CYRILLIC SMALL LETTER ZE + '\u0448' # 0xDB -> CYRILLIC SMALL LETTER SHA + '\u044d' # 0xDC -> CYRILLIC SMALL LETTER E + '\u0449' # 0xDD -> CYRILLIC SMALL LETTER SHCHA + '\u0447' # 0xDE -> CYRILLIC SMALL LETTER CHE + '\u044a' # 0xDF -> CYRILLIC SMALL LETTER HARD SIGN + '\u042e' # 0xE0 -> CYRILLIC CAPITAL LETTER YU + '\u0410' # 0xE1 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xE2 -> CYRILLIC CAPITAL LETTER BE + '\u0426' # 0xE3 -> CYRILLIC CAPITAL LETTER TSE + '\u0414' # 0xE4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xE5 -> CYRILLIC CAPITAL LETTER IE + '\u0424' # 0xE6 -> CYRILLIC CAPITAL LETTER EF + '\u0413' # 0xE7 -> CYRILLIC CAPITAL LETTER GHE + '\u0425' # 0xE8 -> CYRILLIC CAPITAL LETTER HA + '\u0418' # 0xE9 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xEA -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xEB -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xEC -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xED -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xEE -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xEF -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xF0 -> CYRILLIC CAPITAL LETTER PE + '\u042f' # 0xF1 -> CYRILLIC CAPITAL LETTER YA + '\u0420' # 0xF2 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xF3 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xF4 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xF5 -> CYRILLIC CAPITAL LETTER U + '\u0416' # 0xF6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0412' # 0xF7 -> CYRILLIC CAPITAL LETTER VE + '\u042c' # 0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042b' # 0xF9 -> CYRILLIC CAPITAL LETTER YERU + '\u0417' # 0xFA -> CYRILLIC CAPITAL LETTER ZE + '\u0428' # 0xFB -> CYRILLIC CAPITAL LETTER SHA + '\u042d' # 0xFC -> CYRILLIC CAPITAL LETTER E + '\u0429' # 0xFD -> CYRILLIC CAPITAL LETTER SHCHA + '\u0427' # 0xFE -> CYRILLIC CAPITAL LETTER CHE + '\u042a' # 0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/koi8_u.py b/winvenv/Lib/encodings/koi8_u.py new file mode 100644 index 0000000..f9e3fae --- /dev/null +++ b/winvenv/Lib/encodings/koi8_u.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec koi8_u generated from 'python-mappings/KOI8-U.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='koi8-u', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u2500' # 0x80 -> BOX DRAWINGS LIGHT HORIZONTAL + '\u2502' # 0x81 -> BOX DRAWINGS LIGHT VERTICAL + '\u250c' # 0x82 -> BOX DRAWINGS LIGHT DOWN AND RIGHT + '\u2510' # 0x83 -> BOX DRAWINGS LIGHT DOWN AND LEFT + '\u2514' # 0x84 -> BOX DRAWINGS LIGHT UP AND RIGHT + '\u2518' # 0x85 -> BOX DRAWINGS LIGHT UP AND LEFT + '\u251c' # 0x86 -> BOX DRAWINGS LIGHT VERTICAL AND RIGHT + '\u2524' # 0x87 -> BOX DRAWINGS LIGHT VERTICAL AND LEFT + '\u252c' # 0x88 -> BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + '\u2534' # 0x89 -> BOX DRAWINGS LIGHT UP AND HORIZONTAL + '\u253c' # 0x8A -> BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + '\u2580' # 0x8B -> UPPER HALF BLOCK + '\u2584' # 0x8C -> LOWER HALF BLOCK + '\u2588' # 0x8D -> FULL BLOCK + '\u258c' # 0x8E -> LEFT HALF BLOCK + '\u2590' # 0x8F -> RIGHT HALF BLOCK + '\u2591' # 0x90 -> LIGHT SHADE + '\u2592' # 0x91 -> MEDIUM SHADE + '\u2593' # 0x92 -> DARK SHADE + '\u2320' # 0x93 -> TOP HALF INTEGRAL + '\u25a0' # 0x94 -> BLACK SQUARE + '\u2219' # 0x95 -> BULLET OPERATOR + '\u221a' # 0x96 -> SQUARE ROOT + '\u2248' # 0x97 -> ALMOST EQUAL TO + '\u2264' # 0x98 -> LESS-THAN OR EQUAL TO + '\u2265' # 0x99 -> GREATER-THAN OR EQUAL TO + '\xa0' # 0x9A -> NO-BREAK SPACE + '\u2321' # 0x9B -> BOTTOM HALF INTEGRAL + '\xb0' # 0x9C -> DEGREE SIGN + '\xb2' # 0x9D -> SUPERSCRIPT TWO + '\xb7' # 0x9E -> MIDDLE DOT + '\xf7' # 0x9F -> DIVISION SIGN + '\u2550' # 0xA0 -> BOX DRAWINGS DOUBLE HORIZONTAL + '\u2551' # 0xA1 -> BOX DRAWINGS DOUBLE VERTICAL + '\u2552' # 0xA2 -> BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + '\u0451' # 0xA3 -> CYRILLIC SMALL LETTER IO + '\u0454' # 0xA4 -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\u2554' # 0xA5 -> BOX DRAWINGS DOUBLE DOWN AND RIGHT + '\u0456' # 0xA6 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0457' # 0xA7 -> CYRILLIC SMALL LETTER YI (UKRAINIAN) + '\u2557' # 0xA8 -> BOX DRAWINGS DOUBLE DOWN AND LEFT + '\u2558' # 0xA9 -> BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + '\u2559' # 0xAA -> BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + '\u255a' # 0xAB -> BOX DRAWINGS DOUBLE UP AND RIGHT + '\u255b' # 0xAC -> BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + '\u0491' # 0xAD -> CYRILLIC SMALL LETTER UKRAINIAN GHE WITH UPTURN + '\u255d' # 0xAE -> BOX DRAWINGS DOUBLE UP AND LEFT + '\u255e' # 0xAF -> BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + '\u255f' # 0xB0 -> BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + '\u2560' # 0xB1 -> BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + '\u2561' # 0xB2 -> BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + '\u0401' # 0xB3 -> CYRILLIC CAPITAL LETTER IO + '\u0404' # 0xB4 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\u2563' # 0xB5 -> BOX DRAWINGS DOUBLE VERTICAL AND LEFT + '\u0406' # 0xB6 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0407' # 0xB7 -> CYRILLIC CAPITAL LETTER YI (UKRAINIAN) + '\u2566' # 0xB8 -> BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + '\u2567' # 0xB9 -> BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + '\u2568' # 0xBA -> BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + '\u2569' # 0xBB -> BOX DRAWINGS DOUBLE UP AND HORIZONTAL + '\u256a' # 0xBC -> BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + '\u0490' # 0xBD -> CYRILLIC CAPITAL LETTER UKRAINIAN GHE WITH UPTURN + '\u256c' # 0xBE -> BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + '\xa9' # 0xBF -> COPYRIGHT SIGN + '\u044e' # 0xC0 -> CYRILLIC SMALL LETTER YU + '\u0430' # 0xC1 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xC2 -> CYRILLIC SMALL LETTER BE + '\u0446' # 0xC3 -> CYRILLIC SMALL LETTER TSE + '\u0434' # 0xC4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xC5 -> CYRILLIC SMALL LETTER IE + '\u0444' # 0xC6 -> CYRILLIC SMALL LETTER EF + '\u0433' # 0xC7 -> CYRILLIC SMALL LETTER GHE + '\u0445' # 0xC8 -> CYRILLIC SMALL LETTER HA + '\u0438' # 0xC9 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xCA -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xCB -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xCC -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xCD -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xCE -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xCF -> CYRILLIC SMALL LETTER O + '\u043f' # 0xD0 -> CYRILLIC SMALL LETTER PE + '\u044f' # 0xD1 -> CYRILLIC SMALL LETTER YA + '\u0440' # 0xD2 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xD3 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xD4 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xD5 -> CYRILLIC SMALL LETTER U + '\u0436' # 0xD6 -> CYRILLIC SMALL LETTER ZHE + '\u0432' # 0xD7 -> CYRILLIC SMALL LETTER VE + '\u044c' # 0xD8 -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044b' # 0xD9 -> CYRILLIC SMALL LETTER YERU + '\u0437' # 0xDA -> CYRILLIC SMALL LETTER ZE + '\u0448' # 0xDB -> CYRILLIC SMALL LETTER SHA + '\u044d' # 0xDC -> CYRILLIC SMALL LETTER E + '\u0449' # 0xDD -> CYRILLIC SMALL LETTER SHCHA + '\u0447' # 0xDE -> CYRILLIC SMALL LETTER CHE + '\u044a' # 0xDF -> CYRILLIC SMALL LETTER HARD SIGN + '\u042e' # 0xE0 -> CYRILLIC CAPITAL LETTER YU + '\u0410' # 0xE1 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xE2 -> CYRILLIC CAPITAL LETTER BE + '\u0426' # 0xE3 -> CYRILLIC CAPITAL LETTER TSE + '\u0414' # 0xE4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xE5 -> CYRILLIC CAPITAL LETTER IE + '\u0424' # 0xE6 -> CYRILLIC CAPITAL LETTER EF + '\u0413' # 0xE7 -> CYRILLIC CAPITAL LETTER GHE + '\u0425' # 0xE8 -> CYRILLIC CAPITAL LETTER HA + '\u0418' # 0xE9 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xEA -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xEB -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xEC -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xED -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xEE -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xEF -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xF0 -> CYRILLIC CAPITAL LETTER PE + '\u042f' # 0xF1 -> CYRILLIC CAPITAL LETTER YA + '\u0420' # 0xF2 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xF3 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xF4 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xF5 -> CYRILLIC CAPITAL LETTER U + '\u0416' # 0xF6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0412' # 0xF7 -> CYRILLIC CAPITAL LETTER VE + '\u042c' # 0xF8 -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042b' # 0xF9 -> CYRILLIC CAPITAL LETTER YERU + '\u0417' # 0xFA -> CYRILLIC CAPITAL LETTER ZE + '\u0428' # 0xFB -> CYRILLIC CAPITAL LETTER SHA + '\u042d' # 0xFC -> CYRILLIC CAPITAL LETTER E + '\u0429' # 0xFD -> CYRILLIC CAPITAL LETTER SHCHA + '\u0427' # 0xFE -> CYRILLIC CAPITAL LETTER CHE + '\u042a' # 0xFF -> CYRILLIC CAPITAL LETTER HARD SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/kz1048.py b/winvenv/Lib/encodings/kz1048.py new file mode 100644 index 0000000..712aee6 --- /dev/null +++ b/winvenv/Lib/encodings/kz1048.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec kz1048 generated from 'MAPPINGS/VENDORS/MISC/KZ1048.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self, input, errors='strict'): + return codecs.charmap_encode(input, errors, encoding_table) + + def decode(self, input, errors='strict'): + return codecs.charmap_decode(input, errors, decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input, self.errors, encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input, self.errors, decoding_table)[0] + +class StreamWriter(Codec, codecs.StreamWriter): + pass + +class StreamReader(Codec, codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='kz1048', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u0402' # 0x80 -> CYRILLIC CAPITAL LETTER DJE + '\u0403' # 0x81 -> CYRILLIC CAPITAL LETTER GJE + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0453' # 0x83 -> CYRILLIC SMALL LETTER GJE + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u20ac' # 0x88 -> EURO SIGN + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0409' # 0x8A -> CYRILLIC CAPITAL LETTER LJE + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u040a' # 0x8C -> CYRILLIC CAPITAL LETTER NJE + '\u049a' # 0x8D -> CYRILLIC CAPITAL LETTER KA WITH DESCENDER + '\u04ba' # 0x8E -> CYRILLIC CAPITAL LETTER SHHA + '\u040f' # 0x8F -> CYRILLIC CAPITAL LETTER DZHE + '\u0452' # 0x90 -> CYRILLIC SMALL LETTER DJE + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\ufffe' # 0x98 -> UNDEFINED + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0459' # 0x9A -> CYRILLIC SMALL LETTER LJE + '\u203a' # 0x9B -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u045a' # 0x9C -> CYRILLIC SMALL LETTER NJE + '\u049b' # 0x9D -> CYRILLIC SMALL LETTER KA WITH DESCENDER + '\u04bb' # 0x9E -> CYRILLIC SMALL LETTER SHHA + '\u045f' # 0x9F -> CYRILLIC SMALL LETTER DZHE + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u04b0' # 0xA1 -> CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE + '\u04b1' # 0xA2 -> CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE + '\u04d8' # 0xA3 -> CYRILLIC CAPITAL LETTER SCHWA + '\xa4' # 0xA4 -> CURRENCY SIGN + '\u04e8' # 0xA5 -> CYRILLIC CAPITAL LETTER BARRED O + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\u0401' # 0xA8 -> CYRILLIC CAPITAL LETTER IO + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u0492' # 0xAA -> CYRILLIC CAPITAL LETTER GHE WITH STROKE + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\u04ae' # 0xAF -> CYRILLIC CAPITAL LETTER STRAIGHT U + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u0406' # 0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0456' # 0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u04e9' # 0xB4 -> CYRILLIC SMALL LETTER BARRED O + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u0451' # 0xB8 -> CYRILLIC SMALL LETTER IO + '\u2116' # 0xB9 -> NUMERO SIGN + '\u0493' # 0xBA -> CYRILLIC SMALL LETTER GHE WITH STROKE + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u04d9' # 0xBC -> CYRILLIC SMALL LETTER SCHWA + '\u04a2' # 0xBD -> CYRILLIC CAPITAL LETTER EN WITH DESCENDER + '\u04a3' # 0xBE -> CYRILLIC SMALL LETTER EN WITH DESCENDER + '\u04af' # 0xBF -> CYRILLIC SMALL LETTER STRAIGHT U + '\u0410' # 0xC0 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xC1 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0xC2 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0xC3 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0xC4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xC5 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0xC6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0xC7 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0xC8 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xC9 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xCA -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xCB -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xCC -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xCD -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xCE -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xCF -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0xD0 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xD1 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xD2 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xD3 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0xD4 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0xD5 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0xD6 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0xD7 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0xD8 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0xD9 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0xDB -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0xDD -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0xDE -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0xDF -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + '\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + '\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + '\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + '\u044f' # 0xFF -> CYRILLIC SMALL LETTER YA +) + +### Encoding table +encoding_table = codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/latin_1.py b/winvenv/Lib/encodings/latin_1.py new file mode 100644 index 0000000..370160c --- /dev/null +++ b/winvenv/Lib/encodings/latin_1.py @@ -0,0 +1,50 @@ +""" Python 'latin-1' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.latin_1_encode + decode = codecs.latin_1_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.latin_1_encode(input,self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.latin_1_decode(input,self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +class StreamConverter(StreamWriter,StreamReader): + + encode = codecs.latin_1_decode + decode = codecs.latin_1_encode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='iso8859-1', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/mac_arabic.py b/winvenv/Lib/encodings/mac_arabic.py new file mode 100644 index 0000000..72847e8 --- /dev/null +++ b/winvenv/Lib/encodings/mac_arabic.py @@ -0,0 +1,698 @@ +""" Python Character Mapping Codec generated from 'VENDORS/APPLE/ARABIC.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_map) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_map)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-arabic', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + +### Decoding Map + +decoding_map = codecs.make_identity_dict(range(256)) +decoding_map.update({ + 0x0080: 0x00c4, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x0081: 0x00a0, # NO-BREAK SPACE, right-left + 0x0082: 0x00c7, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x0083: 0x00c9, # LATIN CAPITAL LETTER E WITH ACUTE + 0x0084: 0x00d1, # LATIN CAPITAL LETTER N WITH TILDE + 0x0085: 0x00d6, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x0086: 0x00dc, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x0087: 0x00e1, # LATIN SMALL LETTER A WITH ACUTE + 0x0088: 0x00e0, # LATIN SMALL LETTER A WITH GRAVE + 0x0089: 0x00e2, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x008a: 0x00e4, # LATIN SMALL LETTER A WITH DIAERESIS + 0x008b: 0x06ba, # ARABIC LETTER NOON GHUNNA + 0x008c: 0x00ab, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x008d: 0x00e7, # LATIN SMALL LETTER C WITH CEDILLA + 0x008e: 0x00e9, # LATIN SMALL LETTER E WITH ACUTE + 0x008f: 0x00e8, # LATIN SMALL LETTER E WITH GRAVE + 0x0090: 0x00ea, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x0091: 0x00eb, # LATIN SMALL LETTER E WITH DIAERESIS + 0x0092: 0x00ed, # LATIN SMALL LETTER I WITH ACUTE + 0x0093: 0x2026, # HORIZONTAL ELLIPSIS, right-left + 0x0094: 0x00ee, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x0095: 0x00ef, # LATIN SMALL LETTER I WITH DIAERESIS + 0x0096: 0x00f1, # LATIN SMALL LETTER N WITH TILDE + 0x0097: 0x00f3, # LATIN SMALL LETTER O WITH ACUTE + 0x0098: 0x00bb, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x0099: 0x00f4, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x009a: 0x00f6, # LATIN SMALL LETTER O WITH DIAERESIS + 0x009b: 0x00f7, # DIVISION SIGN, right-left + 0x009c: 0x00fa, # LATIN SMALL LETTER U WITH ACUTE + 0x009d: 0x00f9, # LATIN SMALL LETTER U WITH GRAVE + 0x009e: 0x00fb, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x009f: 0x00fc, # LATIN SMALL LETTER U WITH DIAERESIS + 0x00a0: 0x0020, # SPACE, right-left + 0x00a1: 0x0021, # EXCLAMATION MARK, right-left + 0x00a2: 0x0022, # QUOTATION MARK, right-left + 0x00a3: 0x0023, # NUMBER SIGN, right-left + 0x00a4: 0x0024, # DOLLAR SIGN, right-left + 0x00a5: 0x066a, # ARABIC PERCENT SIGN + 0x00a6: 0x0026, # AMPERSAND, right-left + 0x00a7: 0x0027, # APOSTROPHE, right-left + 0x00a8: 0x0028, # LEFT PARENTHESIS, right-left + 0x00a9: 0x0029, # RIGHT PARENTHESIS, right-left + 0x00aa: 0x002a, # ASTERISK, right-left + 0x00ab: 0x002b, # PLUS SIGN, right-left + 0x00ac: 0x060c, # ARABIC COMMA + 0x00ad: 0x002d, # HYPHEN-MINUS, right-left + 0x00ae: 0x002e, # FULL STOP, right-left + 0x00af: 0x002f, # SOLIDUS, right-left + 0x00b0: 0x0660, # ARABIC-INDIC DIGIT ZERO, right-left (need override) + 0x00b1: 0x0661, # ARABIC-INDIC DIGIT ONE, right-left (need override) + 0x00b2: 0x0662, # ARABIC-INDIC DIGIT TWO, right-left (need override) + 0x00b3: 0x0663, # ARABIC-INDIC DIGIT THREE, right-left (need override) + 0x00b4: 0x0664, # ARABIC-INDIC DIGIT FOUR, right-left (need override) + 0x00b5: 0x0665, # ARABIC-INDIC DIGIT FIVE, right-left (need override) + 0x00b6: 0x0666, # ARABIC-INDIC DIGIT SIX, right-left (need override) + 0x00b7: 0x0667, # ARABIC-INDIC DIGIT SEVEN, right-left (need override) + 0x00b8: 0x0668, # ARABIC-INDIC DIGIT EIGHT, right-left (need override) + 0x00b9: 0x0669, # ARABIC-INDIC DIGIT NINE, right-left (need override) + 0x00ba: 0x003a, # COLON, right-left + 0x00bb: 0x061b, # ARABIC SEMICOLON + 0x00bc: 0x003c, # LESS-THAN SIGN, right-left + 0x00bd: 0x003d, # EQUALS SIGN, right-left + 0x00be: 0x003e, # GREATER-THAN SIGN, right-left + 0x00bf: 0x061f, # ARABIC QUESTION MARK + 0x00c0: 0x274a, # EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left + 0x00c1: 0x0621, # ARABIC LETTER HAMZA + 0x00c2: 0x0622, # ARABIC LETTER ALEF WITH MADDA ABOVE + 0x00c3: 0x0623, # ARABIC LETTER ALEF WITH HAMZA ABOVE + 0x00c4: 0x0624, # ARABIC LETTER WAW WITH HAMZA ABOVE + 0x00c5: 0x0625, # ARABIC LETTER ALEF WITH HAMZA BELOW + 0x00c6: 0x0626, # ARABIC LETTER YEH WITH HAMZA ABOVE + 0x00c7: 0x0627, # ARABIC LETTER ALEF + 0x00c8: 0x0628, # ARABIC LETTER BEH + 0x00c9: 0x0629, # ARABIC LETTER TEH MARBUTA + 0x00ca: 0x062a, # ARABIC LETTER TEH + 0x00cb: 0x062b, # ARABIC LETTER THEH + 0x00cc: 0x062c, # ARABIC LETTER JEEM + 0x00cd: 0x062d, # ARABIC LETTER HAH + 0x00ce: 0x062e, # ARABIC LETTER KHAH + 0x00cf: 0x062f, # ARABIC LETTER DAL + 0x00d0: 0x0630, # ARABIC LETTER THAL + 0x00d1: 0x0631, # ARABIC LETTER REH + 0x00d2: 0x0632, # ARABIC LETTER ZAIN + 0x00d3: 0x0633, # ARABIC LETTER SEEN + 0x00d4: 0x0634, # ARABIC LETTER SHEEN + 0x00d5: 0x0635, # ARABIC LETTER SAD + 0x00d6: 0x0636, # ARABIC LETTER DAD + 0x00d7: 0x0637, # ARABIC LETTER TAH + 0x00d8: 0x0638, # ARABIC LETTER ZAH + 0x00d9: 0x0639, # ARABIC LETTER AIN + 0x00da: 0x063a, # ARABIC LETTER GHAIN + 0x00db: 0x005b, # LEFT SQUARE BRACKET, right-left + 0x00dc: 0x005c, # REVERSE SOLIDUS, right-left + 0x00dd: 0x005d, # RIGHT SQUARE BRACKET, right-left + 0x00de: 0x005e, # CIRCUMFLEX ACCENT, right-left + 0x00df: 0x005f, # LOW LINE, right-left + 0x00e0: 0x0640, # ARABIC TATWEEL + 0x00e1: 0x0641, # ARABIC LETTER FEH + 0x00e2: 0x0642, # ARABIC LETTER QAF + 0x00e3: 0x0643, # ARABIC LETTER KAF + 0x00e4: 0x0644, # ARABIC LETTER LAM + 0x00e5: 0x0645, # ARABIC LETTER MEEM + 0x00e6: 0x0646, # ARABIC LETTER NOON + 0x00e7: 0x0647, # ARABIC LETTER HEH + 0x00e8: 0x0648, # ARABIC LETTER WAW + 0x00e9: 0x0649, # ARABIC LETTER ALEF MAKSURA + 0x00ea: 0x064a, # ARABIC LETTER YEH + 0x00eb: 0x064b, # ARABIC FATHATAN + 0x00ec: 0x064c, # ARABIC DAMMATAN + 0x00ed: 0x064d, # ARABIC KASRATAN + 0x00ee: 0x064e, # ARABIC FATHA + 0x00ef: 0x064f, # ARABIC DAMMA + 0x00f0: 0x0650, # ARABIC KASRA + 0x00f1: 0x0651, # ARABIC SHADDA + 0x00f2: 0x0652, # ARABIC SUKUN + 0x00f3: 0x067e, # ARABIC LETTER PEH + 0x00f4: 0x0679, # ARABIC LETTER TTEH + 0x00f5: 0x0686, # ARABIC LETTER TCHEH + 0x00f6: 0x06d5, # ARABIC LETTER AE + 0x00f7: 0x06a4, # ARABIC LETTER VEH + 0x00f8: 0x06af, # ARABIC LETTER GAF + 0x00f9: 0x0688, # ARABIC LETTER DDAL + 0x00fa: 0x0691, # ARABIC LETTER RREH + 0x00fb: 0x007b, # LEFT CURLY BRACKET, right-left + 0x00fc: 0x007c, # VERTICAL LINE, right-left + 0x00fd: 0x007d, # RIGHT CURLY BRACKET, right-left + 0x00fe: 0x0698, # ARABIC LETTER JEH + 0x00ff: 0x06d2, # ARABIC LETTER YEH BARREE +}) + +### Decoding Table + +decoding_table = ( + '\x00' # 0x0000 -> CONTROL CHARACTER + '\x01' # 0x0001 -> CONTROL CHARACTER + '\x02' # 0x0002 -> CONTROL CHARACTER + '\x03' # 0x0003 -> CONTROL CHARACTER + '\x04' # 0x0004 -> CONTROL CHARACTER + '\x05' # 0x0005 -> CONTROL CHARACTER + '\x06' # 0x0006 -> CONTROL CHARACTER + '\x07' # 0x0007 -> CONTROL CHARACTER + '\x08' # 0x0008 -> CONTROL CHARACTER + '\t' # 0x0009 -> CONTROL CHARACTER + '\n' # 0x000a -> CONTROL CHARACTER + '\x0b' # 0x000b -> CONTROL CHARACTER + '\x0c' # 0x000c -> CONTROL CHARACTER + '\r' # 0x000d -> CONTROL CHARACTER + '\x0e' # 0x000e -> CONTROL CHARACTER + '\x0f' # 0x000f -> CONTROL CHARACTER + '\x10' # 0x0010 -> CONTROL CHARACTER + '\x11' # 0x0011 -> CONTROL CHARACTER + '\x12' # 0x0012 -> CONTROL CHARACTER + '\x13' # 0x0013 -> CONTROL CHARACTER + '\x14' # 0x0014 -> CONTROL CHARACTER + '\x15' # 0x0015 -> CONTROL CHARACTER + '\x16' # 0x0016 -> CONTROL CHARACTER + '\x17' # 0x0017 -> CONTROL CHARACTER + '\x18' # 0x0018 -> CONTROL CHARACTER + '\x19' # 0x0019 -> CONTROL CHARACTER + '\x1a' # 0x001a -> CONTROL CHARACTER + '\x1b' # 0x001b -> CONTROL CHARACTER + '\x1c' # 0x001c -> CONTROL CHARACTER + '\x1d' # 0x001d -> CONTROL CHARACTER + '\x1e' # 0x001e -> CONTROL CHARACTER + '\x1f' # 0x001f -> CONTROL CHARACTER + ' ' # 0x0020 -> SPACE, left-right + '!' # 0x0021 -> EXCLAMATION MARK, left-right + '"' # 0x0022 -> QUOTATION MARK, left-right + '#' # 0x0023 -> NUMBER SIGN, left-right + '$' # 0x0024 -> DOLLAR SIGN, left-right + '%' # 0x0025 -> PERCENT SIGN, left-right + '&' # 0x0026 -> AMPERSAND, left-right + "'" # 0x0027 -> APOSTROPHE, left-right + '(' # 0x0028 -> LEFT PARENTHESIS, left-right + ')' # 0x0029 -> RIGHT PARENTHESIS, left-right + '*' # 0x002a -> ASTERISK, left-right + '+' # 0x002b -> PLUS SIGN, left-right + ',' # 0x002c -> COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR + '-' # 0x002d -> HYPHEN-MINUS, left-right + '.' # 0x002e -> FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR + '/' # 0x002f -> SOLIDUS, left-right + '0' # 0x0030 -> DIGIT ZERO; in Arabic-script context, displayed as 0x0660 ARABIC-INDIC DIGIT ZERO + '1' # 0x0031 -> DIGIT ONE; in Arabic-script context, displayed as 0x0661 ARABIC-INDIC DIGIT ONE + '2' # 0x0032 -> DIGIT TWO; in Arabic-script context, displayed as 0x0662 ARABIC-INDIC DIGIT TWO + '3' # 0x0033 -> DIGIT THREE; in Arabic-script context, displayed as 0x0663 ARABIC-INDIC DIGIT THREE + '4' # 0x0034 -> DIGIT FOUR; in Arabic-script context, displayed as 0x0664 ARABIC-INDIC DIGIT FOUR + '5' # 0x0035 -> DIGIT FIVE; in Arabic-script context, displayed as 0x0665 ARABIC-INDIC DIGIT FIVE + '6' # 0x0036 -> DIGIT SIX; in Arabic-script context, displayed as 0x0666 ARABIC-INDIC DIGIT SIX + '7' # 0x0037 -> DIGIT SEVEN; in Arabic-script context, displayed as 0x0667 ARABIC-INDIC DIGIT SEVEN + '8' # 0x0038 -> DIGIT EIGHT; in Arabic-script context, displayed as 0x0668 ARABIC-INDIC DIGIT EIGHT + '9' # 0x0039 -> DIGIT NINE; in Arabic-script context, displayed as 0x0669 ARABIC-INDIC DIGIT NINE + ':' # 0x003a -> COLON, left-right + ';' # 0x003b -> SEMICOLON, left-right + '<' # 0x003c -> LESS-THAN SIGN, left-right + '=' # 0x003d -> EQUALS SIGN, left-right + '>' # 0x003e -> GREATER-THAN SIGN, left-right + '?' # 0x003f -> QUESTION MARK, left-right + '@' # 0x0040 -> COMMERCIAL AT + 'A' # 0x0041 -> LATIN CAPITAL LETTER A + 'B' # 0x0042 -> LATIN CAPITAL LETTER B + 'C' # 0x0043 -> LATIN CAPITAL LETTER C + 'D' # 0x0044 -> LATIN CAPITAL LETTER D + 'E' # 0x0045 -> LATIN CAPITAL LETTER E + 'F' # 0x0046 -> LATIN CAPITAL LETTER F + 'G' # 0x0047 -> LATIN CAPITAL LETTER G + 'H' # 0x0048 -> LATIN CAPITAL LETTER H + 'I' # 0x0049 -> LATIN CAPITAL LETTER I + 'J' # 0x004a -> LATIN CAPITAL LETTER J + 'K' # 0x004b -> LATIN CAPITAL LETTER K + 'L' # 0x004c -> LATIN CAPITAL LETTER L + 'M' # 0x004d -> LATIN CAPITAL LETTER M + 'N' # 0x004e -> LATIN CAPITAL LETTER N + 'O' # 0x004f -> LATIN CAPITAL LETTER O + 'P' # 0x0050 -> LATIN CAPITAL LETTER P + 'Q' # 0x0051 -> LATIN CAPITAL LETTER Q + 'R' # 0x0052 -> LATIN CAPITAL LETTER R + 'S' # 0x0053 -> LATIN CAPITAL LETTER S + 'T' # 0x0054 -> LATIN CAPITAL LETTER T + 'U' # 0x0055 -> LATIN CAPITAL LETTER U + 'V' # 0x0056 -> LATIN CAPITAL LETTER V + 'W' # 0x0057 -> LATIN CAPITAL LETTER W + 'X' # 0x0058 -> LATIN CAPITAL LETTER X + 'Y' # 0x0059 -> LATIN CAPITAL LETTER Y + 'Z' # 0x005a -> LATIN CAPITAL LETTER Z + '[' # 0x005b -> LEFT SQUARE BRACKET, left-right + '\\' # 0x005c -> REVERSE SOLIDUS, left-right + ']' # 0x005d -> RIGHT SQUARE BRACKET, left-right + '^' # 0x005e -> CIRCUMFLEX ACCENT, left-right + '_' # 0x005f -> LOW LINE, left-right + '`' # 0x0060 -> GRAVE ACCENT + 'a' # 0x0061 -> LATIN SMALL LETTER A + 'b' # 0x0062 -> LATIN SMALL LETTER B + 'c' # 0x0063 -> LATIN SMALL LETTER C + 'd' # 0x0064 -> LATIN SMALL LETTER D + 'e' # 0x0065 -> LATIN SMALL LETTER E + 'f' # 0x0066 -> LATIN SMALL LETTER F + 'g' # 0x0067 -> LATIN SMALL LETTER G + 'h' # 0x0068 -> LATIN SMALL LETTER H + 'i' # 0x0069 -> LATIN SMALL LETTER I + 'j' # 0x006a -> LATIN SMALL LETTER J + 'k' # 0x006b -> LATIN SMALL LETTER K + 'l' # 0x006c -> LATIN SMALL LETTER L + 'm' # 0x006d -> LATIN SMALL LETTER M + 'n' # 0x006e -> LATIN SMALL LETTER N + 'o' # 0x006f -> LATIN SMALL LETTER O + 'p' # 0x0070 -> LATIN SMALL LETTER P + 'q' # 0x0071 -> LATIN SMALL LETTER Q + 'r' # 0x0072 -> LATIN SMALL LETTER R + 's' # 0x0073 -> LATIN SMALL LETTER S + 't' # 0x0074 -> LATIN SMALL LETTER T + 'u' # 0x0075 -> LATIN SMALL LETTER U + 'v' # 0x0076 -> LATIN SMALL LETTER V + 'w' # 0x0077 -> LATIN SMALL LETTER W + 'x' # 0x0078 -> LATIN SMALL LETTER X + 'y' # 0x0079 -> LATIN SMALL LETTER Y + 'z' # 0x007a -> LATIN SMALL LETTER Z + '{' # 0x007b -> LEFT CURLY BRACKET, left-right + '|' # 0x007c -> VERTICAL LINE, left-right + '}' # 0x007d -> RIGHT CURLY BRACKET, left-right + '~' # 0x007e -> TILDE + '\x7f' # 0x007f -> CONTROL CHARACTER + '\xc4' # 0x0080 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xa0' # 0x0081 -> NO-BREAK SPACE, right-left + '\xc7' # 0x0082 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x0083 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x0084 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x0085 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x0086 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x0087 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x0088 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x0089 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x008a -> LATIN SMALL LETTER A WITH DIAERESIS + '\u06ba' # 0x008b -> ARABIC LETTER NOON GHUNNA + '\xab' # 0x008c -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + '\xe7' # 0x008d -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x008e -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x008f -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x0090 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x0091 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x0092 -> LATIN SMALL LETTER I WITH ACUTE + '\u2026' # 0x0093 -> HORIZONTAL ELLIPSIS, right-left + '\xee' # 0x0094 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x0095 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x0096 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x0097 -> LATIN SMALL LETTER O WITH ACUTE + '\xbb' # 0x0098 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + '\xf4' # 0x0099 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x009a -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0x009b -> DIVISION SIGN, right-left + '\xfa' # 0x009c -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x009d -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x009e -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x009f -> LATIN SMALL LETTER U WITH DIAERESIS + ' ' # 0x00a0 -> SPACE, right-left + '!' # 0x00a1 -> EXCLAMATION MARK, right-left + '"' # 0x00a2 -> QUOTATION MARK, right-left + '#' # 0x00a3 -> NUMBER SIGN, right-left + '$' # 0x00a4 -> DOLLAR SIGN, right-left + '\u066a' # 0x00a5 -> ARABIC PERCENT SIGN + '&' # 0x00a6 -> AMPERSAND, right-left + "'" # 0x00a7 -> APOSTROPHE, right-left + '(' # 0x00a8 -> LEFT PARENTHESIS, right-left + ')' # 0x00a9 -> RIGHT PARENTHESIS, right-left + '*' # 0x00aa -> ASTERISK, right-left + '+' # 0x00ab -> PLUS SIGN, right-left + '\u060c' # 0x00ac -> ARABIC COMMA + '-' # 0x00ad -> HYPHEN-MINUS, right-left + '.' # 0x00ae -> FULL STOP, right-left + '/' # 0x00af -> SOLIDUS, right-left + '\u0660' # 0x00b0 -> ARABIC-INDIC DIGIT ZERO, right-left (need override) + '\u0661' # 0x00b1 -> ARABIC-INDIC DIGIT ONE, right-left (need override) + '\u0662' # 0x00b2 -> ARABIC-INDIC DIGIT TWO, right-left (need override) + '\u0663' # 0x00b3 -> ARABIC-INDIC DIGIT THREE, right-left (need override) + '\u0664' # 0x00b4 -> ARABIC-INDIC DIGIT FOUR, right-left (need override) + '\u0665' # 0x00b5 -> ARABIC-INDIC DIGIT FIVE, right-left (need override) + '\u0666' # 0x00b6 -> ARABIC-INDIC DIGIT SIX, right-left (need override) + '\u0667' # 0x00b7 -> ARABIC-INDIC DIGIT SEVEN, right-left (need override) + '\u0668' # 0x00b8 -> ARABIC-INDIC DIGIT EIGHT, right-left (need override) + '\u0669' # 0x00b9 -> ARABIC-INDIC DIGIT NINE, right-left (need override) + ':' # 0x00ba -> COLON, right-left + '\u061b' # 0x00bb -> ARABIC SEMICOLON + '<' # 0x00bc -> LESS-THAN SIGN, right-left + '=' # 0x00bd -> EQUALS SIGN, right-left + '>' # 0x00be -> GREATER-THAN SIGN, right-left + '\u061f' # 0x00bf -> ARABIC QUESTION MARK + '\u274a' # 0x00c0 -> EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left + '\u0621' # 0x00c1 -> ARABIC LETTER HAMZA + '\u0622' # 0x00c2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + '\u0623' # 0x00c3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + '\u0624' # 0x00c4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + '\u0625' # 0x00c5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + '\u0626' # 0x00c6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + '\u0627' # 0x00c7 -> ARABIC LETTER ALEF + '\u0628' # 0x00c8 -> ARABIC LETTER BEH + '\u0629' # 0x00c9 -> ARABIC LETTER TEH MARBUTA + '\u062a' # 0x00ca -> ARABIC LETTER TEH + '\u062b' # 0x00cb -> ARABIC LETTER THEH + '\u062c' # 0x00cc -> ARABIC LETTER JEEM + '\u062d' # 0x00cd -> ARABIC LETTER HAH + '\u062e' # 0x00ce -> ARABIC LETTER KHAH + '\u062f' # 0x00cf -> ARABIC LETTER DAL + '\u0630' # 0x00d0 -> ARABIC LETTER THAL + '\u0631' # 0x00d1 -> ARABIC LETTER REH + '\u0632' # 0x00d2 -> ARABIC LETTER ZAIN + '\u0633' # 0x00d3 -> ARABIC LETTER SEEN + '\u0634' # 0x00d4 -> ARABIC LETTER SHEEN + '\u0635' # 0x00d5 -> ARABIC LETTER SAD + '\u0636' # 0x00d6 -> ARABIC LETTER DAD + '\u0637' # 0x00d7 -> ARABIC LETTER TAH + '\u0638' # 0x00d8 -> ARABIC LETTER ZAH + '\u0639' # 0x00d9 -> ARABIC LETTER AIN + '\u063a' # 0x00da -> ARABIC LETTER GHAIN + '[' # 0x00db -> LEFT SQUARE BRACKET, right-left + '\\' # 0x00dc -> REVERSE SOLIDUS, right-left + ']' # 0x00dd -> RIGHT SQUARE BRACKET, right-left + '^' # 0x00de -> CIRCUMFLEX ACCENT, right-left + '_' # 0x00df -> LOW LINE, right-left + '\u0640' # 0x00e0 -> ARABIC TATWEEL + '\u0641' # 0x00e1 -> ARABIC LETTER FEH + '\u0642' # 0x00e2 -> ARABIC LETTER QAF + '\u0643' # 0x00e3 -> ARABIC LETTER KAF + '\u0644' # 0x00e4 -> ARABIC LETTER LAM + '\u0645' # 0x00e5 -> ARABIC LETTER MEEM + '\u0646' # 0x00e6 -> ARABIC LETTER NOON + '\u0647' # 0x00e7 -> ARABIC LETTER HEH + '\u0648' # 0x00e8 -> ARABIC LETTER WAW + '\u0649' # 0x00e9 -> ARABIC LETTER ALEF MAKSURA + '\u064a' # 0x00ea -> ARABIC LETTER YEH + '\u064b' # 0x00eb -> ARABIC FATHATAN + '\u064c' # 0x00ec -> ARABIC DAMMATAN + '\u064d' # 0x00ed -> ARABIC KASRATAN + '\u064e' # 0x00ee -> ARABIC FATHA + '\u064f' # 0x00ef -> ARABIC DAMMA + '\u0650' # 0x00f0 -> ARABIC KASRA + '\u0651' # 0x00f1 -> ARABIC SHADDA + '\u0652' # 0x00f2 -> ARABIC SUKUN + '\u067e' # 0x00f3 -> ARABIC LETTER PEH + '\u0679' # 0x00f4 -> ARABIC LETTER TTEH + '\u0686' # 0x00f5 -> ARABIC LETTER TCHEH + '\u06d5' # 0x00f6 -> ARABIC LETTER AE + '\u06a4' # 0x00f7 -> ARABIC LETTER VEH + '\u06af' # 0x00f8 -> ARABIC LETTER GAF + '\u0688' # 0x00f9 -> ARABIC LETTER DDAL + '\u0691' # 0x00fa -> ARABIC LETTER RREH + '{' # 0x00fb -> LEFT CURLY BRACKET, right-left + '|' # 0x00fc -> VERTICAL LINE, right-left + '}' # 0x00fd -> RIGHT CURLY BRACKET, right-left + '\u0698' # 0x00fe -> ARABIC LETTER JEH + '\u06d2' # 0x00ff -> ARABIC LETTER YEH BARREE +) + +### Encoding Map + +encoding_map = { + 0x0000: 0x0000, # CONTROL CHARACTER + 0x0001: 0x0001, # CONTROL CHARACTER + 0x0002: 0x0002, # CONTROL CHARACTER + 0x0003: 0x0003, # CONTROL CHARACTER + 0x0004: 0x0004, # CONTROL CHARACTER + 0x0005: 0x0005, # CONTROL CHARACTER + 0x0006: 0x0006, # CONTROL CHARACTER + 0x0007: 0x0007, # CONTROL CHARACTER + 0x0008: 0x0008, # CONTROL CHARACTER + 0x0009: 0x0009, # CONTROL CHARACTER + 0x000a: 0x000a, # CONTROL CHARACTER + 0x000b: 0x000b, # CONTROL CHARACTER + 0x000c: 0x000c, # CONTROL CHARACTER + 0x000d: 0x000d, # CONTROL CHARACTER + 0x000e: 0x000e, # CONTROL CHARACTER + 0x000f: 0x000f, # CONTROL CHARACTER + 0x0010: 0x0010, # CONTROL CHARACTER + 0x0011: 0x0011, # CONTROL CHARACTER + 0x0012: 0x0012, # CONTROL CHARACTER + 0x0013: 0x0013, # CONTROL CHARACTER + 0x0014: 0x0014, # CONTROL CHARACTER + 0x0015: 0x0015, # CONTROL CHARACTER + 0x0016: 0x0016, # CONTROL CHARACTER + 0x0017: 0x0017, # CONTROL CHARACTER + 0x0018: 0x0018, # CONTROL CHARACTER + 0x0019: 0x0019, # CONTROL CHARACTER + 0x001a: 0x001a, # CONTROL CHARACTER + 0x001b: 0x001b, # CONTROL CHARACTER + 0x001c: 0x001c, # CONTROL CHARACTER + 0x001d: 0x001d, # CONTROL CHARACTER + 0x001e: 0x001e, # CONTROL CHARACTER + 0x001f: 0x001f, # CONTROL CHARACTER + 0x0020: 0x0020, # SPACE, left-right + 0x0020: 0x00a0, # SPACE, right-left + 0x0021: 0x0021, # EXCLAMATION MARK, left-right + 0x0021: 0x00a1, # EXCLAMATION MARK, right-left + 0x0022: 0x0022, # QUOTATION MARK, left-right + 0x0022: 0x00a2, # QUOTATION MARK, right-left + 0x0023: 0x0023, # NUMBER SIGN, left-right + 0x0023: 0x00a3, # NUMBER SIGN, right-left + 0x0024: 0x0024, # DOLLAR SIGN, left-right + 0x0024: 0x00a4, # DOLLAR SIGN, right-left + 0x0025: 0x0025, # PERCENT SIGN, left-right + 0x0026: 0x0026, # AMPERSAND, left-right + 0x0026: 0x00a6, # AMPERSAND, right-left + 0x0027: 0x0027, # APOSTROPHE, left-right + 0x0027: 0x00a7, # APOSTROPHE, right-left + 0x0028: 0x0028, # LEFT PARENTHESIS, left-right + 0x0028: 0x00a8, # LEFT PARENTHESIS, right-left + 0x0029: 0x0029, # RIGHT PARENTHESIS, left-right + 0x0029: 0x00a9, # RIGHT PARENTHESIS, right-left + 0x002a: 0x002a, # ASTERISK, left-right + 0x002a: 0x00aa, # ASTERISK, right-left + 0x002b: 0x002b, # PLUS SIGN, left-right + 0x002b: 0x00ab, # PLUS SIGN, right-left + 0x002c: 0x002c, # COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR + 0x002d: 0x002d, # HYPHEN-MINUS, left-right + 0x002d: 0x00ad, # HYPHEN-MINUS, right-left + 0x002e: 0x002e, # FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR + 0x002e: 0x00ae, # FULL STOP, right-left + 0x002f: 0x002f, # SOLIDUS, left-right + 0x002f: 0x00af, # SOLIDUS, right-left + 0x0030: 0x0030, # DIGIT ZERO; in Arabic-script context, displayed as 0x0660 ARABIC-INDIC DIGIT ZERO + 0x0031: 0x0031, # DIGIT ONE; in Arabic-script context, displayed as 0x0661 ARABIC-INDIC DIGIT ONE + 0x0032: 0x0032, # DIGIT TWO; in Arabic-script context, displayed as 0x0662 ARABIC-INDIC DIGIT TWO + 0x0033: 0x0033, # DIGIT THREE; in Arabic-script context, displayed as 0x0663 ARABIC-INDIC DIGIT THREE + 0x0034: 0x0034, # DIGIT FOUR; in Arabic-script context, displayed as 0x0664 ARABIC-INDIC DIGIT FOUR + 0x0035: 0x0035, # DIGIT FIVE; in Arabic-script context, displayed as 0x0665 ARABIC-INDIC DIGIT FIVE + 0x0036: 0x0036, # DIGIT SIX; in Arabic-script context, displayed as 0x0666 ARABIC-INDIC DIGIT SIX + 0x0037: 0x0037, # DIGIT SEVEN; in Arabic-script context, displayed as 0x0667 ARABIC-INDIC DIGIT SEVEN + 0x0038: 0x0038, # DIGIT EIGHT; in Arabic-script context, displayed as 0x0668 ARABIC-INDIC DIGIT EIGHT + 0x0039: 0x0039, # DIGIT NINE; in Arabic-script context, displayed as 0x0669 ARABIC-INDIC DIGIT NINE + 0x003a: 0x003a, # COLON, left-right + 0x003a: 0x00ba, # COLON, right-left + 0x003b: 0x003b, # SEMICOLON, left-right + 0x003c: 0x003c, # LESS-THAN SIGN, left-right + 0x003c: 0x00bc, # LESS-THAN SIGN, right-left + 0x003d: 0x003d, # EQUALS SIGN, left-right + 0x003d: 0x00bd, # EQUALS SIGN, right-left + 0x003e: 0x003e, # GREATER-THAN SIGN, left-right + 0x003e: 0x00be, # GREATER-THAN SIGN, right-left + 0x003f: 0x003f, # QUESTION MARK, left-right + 0x0040: 0x0040, # COMMERCIAL AT + 0x0041: 0x0041, # LATIN CAPITAL LETTER A + 0x0042: 0x0042, # LATIN CAPITAL LETTER B + 0x0043: 0x0043, # LATIN CAPITAL LETTER C + 0x0044: 0x0044, # LATIN CAPITAL LETTER D + 0x0045: 0x0045, # LATIN CAPITAL LETTER E + 0x0046: 0x0046, # LATIN CAPITAL LETTER F + 0x0047: 0x0047, # LATIN CAPITAL LETTER G + 0x0048: 0x0048, # LATIN CAPITAL LETTER H + 0x0049: 0x0049, # LATIN CAPITAL LETTER I + 0x004a: 0x004a, # LATIN CAPITAL LETTER J + 0x004b: 0x004b, # LATIN CAPITAL LETTER K + 0x004c: 0x004c, # LATIN CAPITAL LETTER L + 0x004d: 0x004d, # LATIN CAPITAL LETTER M + 0x004e: 0x004e, # LATIN CAPITAL LETTER N + 0x004f: 0x004f, # LATIN CAPITAL LETTER O + 0x0050: 0x0050, # LATIN CAPITAL LETTER P + 0x0051: 0x0051, # LATIN CAPITAL LETTER Q + 0x0052: 0x0052, # LATIN CAPITAL LETTER R + 0x0053: 0x0053, # LATIN CAPITAL LETTER S + 0x0054: 0x0054, # LATIN CAPITAL LETTER T + 0x0055: 0x0055, # LATIN CAPITAL LETTER U + 0x0056: 0x0056, # LATIN CAPITAL LETTER V + 0x0057: 0x0057, # LATIN CAPITAL LETTER W + 0x0058: 0x0058, # LATIN CAPITAL LETTER X + 0x0059: 0x0059, # LATIN CAPITAL LETTER Y + 0x005a: 0x005a, # LATIN CAPITAL LETTER Z + 0x005b: 0x005b, # LEFT SQUARE BRACKET, left-right + 0x005b: 0x00db, # LEFT SQUARE BRACKET, right-left + 0x005c: 0x005c, # REVERSE SOLIDUS, left-right + 0x005c: 0x00dc, # REVERSE SOLIDUS, right-left + 0x005d: 0x005d, # RIGHT SQUARE BRACKET, left-right + 0x005d: 0x00dd, # RIGHT SQUARE BRACKET, right-left + 0x005e: 0x005e, # CIRCUMFLEX ACCENT, left-right + 0x005e: 0x00de, # CIRCUMFLEX ACCENT, right-left + 0x005f: 0x005f, # LOW LINE, left-right + 0x005f: 0x00df, # LOW LINE, right-left + 0x0060: 0x0060, # GRAVE ACCENT + 0x0061: 0x0061, # LATIN SMALL LETTER A + 0x0062: 0x0062, # LATIN SMALL LETTER B + 0x0063: 0x0063, # LATIN SMALL LETTER C + 0x0064: 0x0064, # LATIN SMALL LETTER D + 0x0065: 0x0065, # LATIN SMALL LETTER E + 0x0066: 0x0066, # LATIN SMALL LETTER F + 0x0067: 0x0067, # LATIN SMALL LETTER G + 0x0068: 0x0068, # LATIN SMALL LETTER H + 0x0069: 0x0069, # LATIN SMALL LETTER I + 0x006a: 0x006a, # LATIN SMALL LETTER J + 0x006b: 0x006b, # LATIN SMALL LETTER K + 0x006c: 0x006c, # LATIN SMALL LETTER L + 0x006d: 0x006d, # LATIN SMALL LETTER M + 0x006e: 0x006e, # LATIN SMALL LETTER N + 0x006f: 0x006f, # LATIN SMALL LETTER O + 0x0070: 0x0070, # LATIN SMALL LETTER P + 0x0071: 0x0071, # LATIN SMALL LETTER Q + 0x0072: 0x0072, # LATIN SMALL LETTER R + 0x0073: 0x0073, # LATIN SMALL LETTER S + 0x0074: 0x0074, # LATIN SMALL LETTER T + 0x0075: 0x0075, # LATIN SMALL LETTER U + 0x0076: 0x0076, # LATIN SMALL LETTER V + 0x0077: 0x0077, # LATIN SMALL LETTER W + 0x0078: 0x0078, # LATIN SMALL LETTER X + 0x0079: 0x0079, # LATIN SMALL LETTER Y + 0x007a: 0x007a, # LATIN SMALL LETTER Z + 0x007b: 0x007b, # LEFT CURLY BRACKET, left-right + 0x007b: 0x00fb, # LEFT CURLY BRACKET, right-left + 0x007c: 0x007c, # VERTICAL LINE, left-right + 0x007c: 0x00fc, # VERTICAL LINE, right-left + 0x007d: 0x007d, # RIGHT CURLY BRACKET, left-right + 0x007d: 0x00fd, # RIGHT CURLY BRACKET, right-left + 0x007e: 0x007e, # TILDE + 0x007f: 0x007f, # CONTROL CHARACTER + 0x00a0: 0x0081, # NO-BREAK SPACE, right-left + 0x00ab: 0x008c, # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x00bb: 0x0098, # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + 0x00c4: 0x0080, # LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c7: 0x0082, # LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c9: 0x0083, # LATIN CAPITAL LETTER E WITH ACUTE + 0x00d1: 0x0084, # LATIN CAPITAL LETTER N WITH TILDE + 0x00d6: 0x0085, # LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc: 0x0086, # LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00e0: 0x0088, # LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x0087, # LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x0089, # LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4: 0x008a, # LATIN SMALL LETTER A WITH DIAERESIS + 0x00e7: 0x008d, # LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x008f, # LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x008e, # LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x0090, # LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x0091, # LATIN SMALL LETTER E WITH DIAERESIS + 0x00ed: 0x0092, # LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x0094, # LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x0095, # LATIN SMALL LETTER I WITH DIAERESIS + 0x00f1: 0x0096, # LATIN SMALL LETTER N WITH TILDE + 0x00f3: 0x0097, # LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x0099, # LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6: 0x009a, # LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x009b, # DIVISION SIGN, right-left + 0x00f9: 0x009d, # LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x009c, # LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x009e, # LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x009f, # LATIN SMALL LETTER U WITH DIAERESIS + 0x060c: 0x00ac, # ARABIC COMMA + 0x061b: 0x00bb, # ARABIC SEMICOLON + 0x061f: 0x00bf, # ARABIC QUESTION MARK + 0x0621: 0x00c1, # ARABIC LETTER HAMZA + 0x0622: 0x00c2, # ARABIC LETTER ALEF WITH MADDA ABOVE + 0x0623: 0x00c3, # ARABIC LETTER ALEF WITH HAMZA ABOVE + 0x0624: 0x00c4, # ARABIC LETTER WAW WITH HAMZA ABOVE + 0x0625: 0x00c5, # ARABIC LETTER ALEF WITH HAMZA BELOW + 0x0626: 0x00c6, # ARABIC LETTER YEH WITH HAMZA ABOVE + 0x0627: 0x00c7, # ARABIC LETTER ALEF + 0x0628: 0x00c8, # ARABIC LETTER BEH + 0x0629: 0x00c9, # ARABIC LETTER TEH MARBUTA + 0x062a: 0x00ca, # ARABIC LETTER TEH + 0x062b: 0x00cb, # ARABIC LETTER THEH + 0x062c: 0x00cc, # ARABIC LETTER JEEM + 0x062d: 0x00cd, # ARABIC LETTER HAH + 0x062e: 0x00ce, # ARABIC LETTER KHAH + 0x062f: 0x00cf, # ARABIC LETTER DAL + 0x0630: 0x00d0, # ARABIC LETTER THAL + 0x0631: 0x00d1, # ARABIC LETTER REH + 0x0632: 0x00d2, # ARABIC LETTER ZAIN + 0x0633: 0x00d3, # ARABIC LETTER SEEN + 0x0634: 0x00d4, # ARABIC LETTER SHEEN + 0x0635: 0x00d5, # ARABIC LETTER SAD + 0x0636: 0x00d6, # ARABIC LETTER DAD + 0x0637: 0x00d7, # ARABIC LETTER TAH + 0x0638: 0x00d8, # ARABIC LETTER ZAH + 0x0639: 0x00d9, # ARABIC LETTER AIN + 0x063a: 0x00da, # ARABIC LETTER GHAIN + 0x0640: 0x00e0, # ARABIC TATWEEL + 0x0641: 0x00e1, # ARABIC LETTER FEH + 0x0642: 0x00e2, # ARABIC LETTER QAF + 0x0643: 0x00e3, # ARABIC LETTER KAF + 0x0644: 0x00e4, # ARABIC LETTER LAM + 0x0645: 0x00e5, # ARABIC LETTER MEEM + 0x0646: 0x00e6, # ARABIC LETTER NOON + 0x0647: 0x00e7, # ARABIC LETTER HEH + 0x0648: 0x00e8, # ARABIC LETTER WAW + 0x0649: 0x00e9, # ARABIC LETTER ALEF MAKSURA + 0x064a: 0x00ea, # ARABIC LETTER YEH + 0x064b: 0x00eb, # ARABIC FATHATAN + 0x064c: 0x00ec, # ARABIC DAMMATAN + 0x064d: 0x00ed, # ARABIC KASRATAN + 0x064e: 0x00ee, # ARABIC FATHA + 0x064f: 0x00ef, # ARABIC DAMMA + 0x0650: 0x00f0, # ARABIC KASRA + 0x0651: 0x00f1, # ARABIC SHADDA + 0x0652: 0x00f2, # ARABIC SUKUN + 0x0660: 0x00b0, # ARABIC-INDIC DIGIT ZERO, right-left (need override) + 0x0661: 0x00b1, # ARABIC-INDIC DIGIT ONE, right-left (need override) + 0x0662: 0x00b2, # ARABIC-INDIC DIGIT TWO, right-left (need override) + 0x0663: 0x00b3, # ARABIC-INDIC DIGIT THREE, right-left (need override) + 0x0664: 0x00b4, # ARABIC-INDIC DIGIT FOUR, right-left (need override) + 0x0665: 0x00b5, # ARABIC-INDIC DIGIT FIVE, right-left (need override) + 0x0666: 0x00b6, # ARABIC-INDIC DIGIT SIX, right-left (need override) + 0x0667: 0x00b7, # ARABIC-INDIC DIGIT SEVEN, right-left (need override) + 0x0668: 0x00b8, # ARABIC-INDIC DIGIT EIGHT, right-left (need override) + 0x0669: 0x00b9, # ARABIC-INDIC DIGIT NINE, right-left (need override) + 0x066a: 0x00a5, # ARABIC PERCENT SIGN + 0x0679: 0x00f4, # ARABIC LETTER TTEH + 0x067e: 0x00f3, # ARABIC LETTER PEH + 0x0686: 0x00f5, # ARABIC LETTER TCHEH + 0x0688: 0x00f9, # ARABIC LETTER DDAL + 0x0691: 0x00fa, # ARABIC LETTER RREH + 0x0698: 0x00fe, # ARABIC LETTER JEH + 0x06a4: 0x00f7, # ARABIC LETTER VEH + 0x06af: 0x00f8, # ARABIC LETTER GAF + 0x06ba: 0x008b, # ARABIC LETTER NOON GHUNNA + 0x06d2: 0x00ff, # ARABIC LETTER YEH BARREE + 0x06d5: 0x00f6, # ARABIC LETTER AE + 0x2026: 0x0093, # HORIZONTAL ELLIPSIS, right-left + 0x274a: 0x00c0, # EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left +} diff --git a/winvenv/Lib/encodings/mac_centeuro.py b/winvenv/Lib/encodings/mac_centeuro.py new file mode 100644 index 0000000..5785a0e --- /dev/null +++ b/winvenv/Lib/encodings/mac_centeuro.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_centeuro generated from 'MAPPINGS/VENDORS/APPLE/CENTEURO.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-centeuro', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u0100' # 0x81 -> LATIN CAPITAL LETTER A WITH MACRON + '\u0101' # 0x82 -> LATIN SMALL LETTER A WITH MACRON + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0104' # 0x84 -> LATIN CAPITAL LETTER A WITH OGONEK + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\u0105' # 0x88 -> LATIN SMALL LETTER A WITH OGONEK + '\u010c' # 0x89 -> LATIN CAPITAL LETTER C WITH CARON + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\u010d' # 0x8B -> LATIN SMALL LETTER C WITH CARON + '\u0106' # 0x8C -> LATIN CAPITAL LETTER C WITH ACUTE + '\u0107' # 0x8D -> LATIN SMALL LETTER C WITH ACUTE + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\u0179' # 0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE + '\u017a' # 0x90 -> LATIN SMALL LETTER Z WITH ACUTE + '\u010e' # 0x91 -> LATIN CAPITAL LETTER D WITH CARON + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\u010f' # 0x93 -> LATIN SMALL LETTER D WITH CARON + '\u0112' # 0x94 -> LATIN CAPITAL LETTER E WITH MACRON + '\u0113' # 0x95 -> LATIN SMALL LETTER E WITH MACRON + '\u0116' # 0x96 -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\u0117' # 0x98 -> LATIN SMALL LETTER E WITH DOT ABOVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\u011a' # 0x9D -> LATIN CAPITAL LETTER E WITH CARON + '\u011b' # 0x9E -> LATIN SMALL LETTER E WITH CARON + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\u0118' # 0xA2 -> LATIN CAPITAL LETTER E WITH OGONEK + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\u0119' # 0xAB -> LATIN SMALL LETTER E WITH OGONEK + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\u0123' # 0xAE -> LATIN SMALL LETTER G WITH CEDILLA + '\u012e' # 0xAF -> LATIN CAPITAL LETTER I WITH OGONEK + '\u012f' # 0xB0 -> LATIN SMALL LETTER I WITH OGONEK + '\u012a' # 0xB1 -> LATIN CAPITAL LETTER I WITH MACRON + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\u012b' # 0xB4 -> LATIN SMALL LETTER I WITH MACRON + '\u0136' # 0xB5 -> LATIN CAPITAL LETTER K WITH CEDILLA + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u0142' # 0xB8 -> LATIN SMALL LETTER L WITH STROKE + '\u013b' # 0xB9 -> LATIN CAPITAL LETTER L WITH CEDILLA + '\u013c' # 0xBA -> LATIN SMALL LETTER L WITH CEDILLA + '\u013d' # 0xBB -> LATIN CAPITAL LETTER L WITH CARON + '\u013e' # 0xBC -> LATIN SMALL LETTER L WITH CARON + '\u0139' # 0xBD -> LATIN CAPITAL LETTER L WITH ACUTE + '\u013a' # 0xBE -> LATIN SMALL LETTER L WITH ACUTE + '\u0145' # 0xBF -> LATIN CAPITAL LETTER N WITH CEDILLA + '\u0146' # 0xC0 -> LATIN SMALL LETTER N WITH CEDILLA + '\u0143' # 0xC1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0144' # 0xC4 -> LATIN SMALL LETTER N WITH ACUTE + '\u0147' # 0xC5 -> LATIN CAPITAL LETTER N WITH CARON + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\u0148' # 0xCB -> LATIN SMALL LETTER N WITH CARON + '\u0150' # 0xCC -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0151' # 0xCE -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + '\u014c' # 0xCF -> LATIN CAPITAL LETTER O WITH MACRON + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\u014d' # 0xD8 -> LATIN SMALL LETTER O WITH MACRON + '\u0154' # 0xD9 -> LATIN CAPITAL LETTER R WITH ACUTE + '\u0155' # 0xDA -> LATIN SMALL LETTER R WITH ACUTE + '\u0158' # 0xDB -> LATIN CAPITAL LETTER R WITH CARON + '\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u0159' # 0xDE -> LATIN SMALL LETTER R WITH CARON + '\u0156' # 0xDF -> LATIN CAPITAL LETTER R WITH CEDILLA + '\u0157' # 0xE0 -> LATIN SMALL LETTER R WITH CEDILLA + '\u0160' # 0xE1 -> LATIN CAPITAL LETTER S WITH CARON + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u0161' # 0xE4 -> LATIN SMALL LETTER S WITH CARON + '\u015a' # 0xE5 -> LATIN CAPITAL LETTER S WITH ACUTE + '\u015b' # 0xE6 -> LATIN SMALL LETTER S WITH ACUTE + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\u0164' # 0xE8 -> LATIN CAPITAL LETTER T WITH CARON + '\u0165' # 0xE9 -> LATIN SMALL LETTER T WITH CARON + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\u017d' # 0xEB -> LATIN CAPITAL LETTER Z WITH CARON + '\u017e' # 0xEC -> LATIN SMALL LETTER Z WITH CARON + '\u016a' # 0xED -> LATIN CAPITAL LETTER U WITH MACRON + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u016b' # 0xF0 -> LATIN SMALL LETTER U WITH MACRON + '\u016e' # 0xF1 -> LATIN CAPITAL LETTER U WITH RING ABOVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\u016f' # 0xF3 -> LATIN SMALL LETTER U WITH RING ABOVE + '\u0170' # 0xF4 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + '\u0171' # 0xF5 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + '\u0172' # 0xF6 -> LATIN CAPITAL LETTER U WITH OGONEK + '\u0173' # 0xF7 -> LATIN SMALL LETTER U WITH OGONEK + '\xdd' # 0xF8 -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xfd' # 0xF9 -> LATIN SMALL LETTER Y WITH ACUTE + '\u0137' # 0xFA -> LATIN SMALL LETTER K WITH CEDILLA + '\u017b' # 0xFB -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\u0141' # 0xFC -> LATIN CAPITAL LETTER L WITH STROKE + '\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u0122' # 0xFE -> LATIN CAPITAL LETTER G WITH CEDILLA + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_croatian.py b/winvenv/Lib/encodings/mac_croatian.py new file mode 100644 index 0000000..4a92fe6 --- /dev/null +++ b/winvenv/Lib/encodings/mac_croatian.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_croatian generated from 'MAPPINGS/VENDORS/APPLE/CROATIAN.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-croatian', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\u0160' # 0xA9 -> LATIN CAPITAL LETTER S WITH CARON + '\u2122' # 0xAA -> TRADE MARK SIGN + '\xb4' # 0xAB -> ACUTE ACCENT + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\u017d' # 0xAE -> LATIN CAPITAL LETTER Z WITH CARON + '\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + '\u221e' # 0xB0 -> INFINITY + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\u2206' # 0xB4 -> INCREMENT + '\xb5' # 0xB5 -> MICRO SIGN + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u220f' # 0xB8 -> N-ARY PRODUCT + '\u0161' # 0xB9 -> LATIN SMALL LETTER S WITH CARON + '\u222b' # 0xBA -> INTEGRAL + '\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + '\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + '\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + '\u017e' # 0xBE -> LATIN SMALL LETTER Z WITH CARON + '\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + '\xbf' # 0xC0 -> INVERTED QUESTION MARK + '\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u0106' # 0xC6 -> LATIN CAPITAL LETTER C WITH ACUTE + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u010c' # 0xC8 -> LATIN CAPITAL LETTER C WITH CARON + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + '\u0110' # 0xD0 -> LATIN CAPITAL LETTER D WITH STROKE + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\uf8ff' # 0xD8 -> Apple logo + '\xa9' # 0xD9 -> COPYRIGHT SIGN + '\u2044' # 0xDA -> FRACTION SLASH + '\u20ac' # 0xDB -> EURO SIGN + '\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\xc6' # 0xDE -> LATIN CAPITAL LETTER AE + '\xbb' # 0xDF -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2013' # 0xE0 -> EN DASH + '\xb7' # 0xE1 -> MIDDLE DOT + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u2030' # 0xE4 -> PER MILLE SIGN + '\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\u0107' # 0xE6 -> LATIN SMALL LETTER C WITH ACUTE + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\u010d' # 0xE8 -> LATIN SMALL LETTER C WITH CARON + '\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u0111' # 0xF0 -> LATIN SMALL LETTER D WITH STROKE + '\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + '\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + '\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u02dc' # 0xF7 -> SMALL TILDE + '\xaf' # 0xF8 -> MACRON + '\u03c0' # 0xF9 -> GREEK SMALL LETTER PI + '\xcb' # 0xFA -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\u02da' # 0xFB -> RING ABOVE + '\xb8' # 0xFC -> CEDILLA + '\xca' # 0xFD -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xe6' # 0xFE -> LATIN SMALL LETTER AE + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_cyrillic.py b/winvenv/Lib/encodings/mac_cyrillic.py new file mode 100644 index 0000000..d20272a --- /dev/null +++ b/winvenv/Lib/encodings/mac_cyrillic.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_cyrillic generated from 'MAPPINGS/VENDORS/APPLE/CYRILLIC.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-cyrillic', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\u0410' # 0x80 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0x81 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0x82 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0x83 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0x84 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0x85 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0x86 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0x87 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0x88 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0x89 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0x8A -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0x8B -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0x8C -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0x8D -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0x8E -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0x8F -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0x90 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0x91 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0x92 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0x93 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0x94 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0x95 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0x96 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0x97 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0x98 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0x99 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0x9A -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0x9B -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0x9C -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0x9D -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0x9E -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0x9F -> CYRILLIC CAPITAL LETTER YA + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\u0490' # 0xA2 -> CYRILLIC CAPITAL LETTER GHE WITH UPTURN + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\u0406' # 0xA7 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\u0402' # 0xAB -> CYRILLIC CAPITAL LETTER DJE + '\u0452' # 0xAC -> CYRILLIC SMALL LETTER DJE + '\u2260' # 0xAD -> NOT EQUAL TO + '\u0403' # 0xAE -> CYRILLIC CAPITAL LETTER GJE + '\u0453' # 0xAF -> CYRILLIC SMALL LETTER GJE + '\u221e' # 0xB0 -> INFINITY + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\u0456' # 0xB4 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\xb5' # 0xB5 -> MICRO SIGN + '\u0491' # 0xB6 -> CYRILLIC SMALL LETTER GHE WITH UPTURN + '\u0408' # 0xB7 -> CYRILLIC CAPITAL LETTER JE + '\u0404' # 0xB8 -> CYRILLIC CAPITAL LETTER UKRAINIAN IE + '\u0454' # 0xB9 -> CYRILLIC SMALL LETTER UKRAINIAN IE + '\u0407' # 0xBA -> CYRILLIC CAPITAL LETTER YI + '\u0457' # 0xBB -> CYRILLIC SMALL LETTER YI + '\u0409' # 0xBC -> CYRILLIC CAPITAL LETTER LJE + '\u0459' # 0xBD -> CYRILLIC SMALL LETTER LJE + '\u040a' # 0xBE -> CYRILLIC CAPITAL LETTER NJE + '\u045a' # 0xBF -> CYRILLIC SMALL LETTER NJE + '\u0458' # 0xC0 -> CYRILLIC SMALL LETTER JE + '\u0405' # 0xC1 -> CYRILLIC CAPITAL LETTER DZE + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\u040b' # 0xCB -> CYRILLIC CAPITAL LETTER TSHE + '\u045b' # 0xCC -> CYRILLIC SMALL LETTER TSHE + '\u040c' # 0xCD -> CYRILLIC CAPITAL LETTER KJE + '\u045c' # 0xCE -> CYRILLIC SMALL LETTER KJE + '\u0455' # 0xCF -> CYRILLIC SMALL LETTER DZE + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u201e' # 0xD7 -> DOUBLE LOW-9 QUOTATION MARK + '\u040e' # 0xD8 -> CYRILLIC CAPITAL LETTER SHORT U + '\u045e' # 0xD9 -> CYRILLIC SMALL LETTER SHORT U + '\u040f' # 0xDA -> CYRILLIC CAPITAL LETTER DZHE + '\u045f' # 0xDB -> CYRILLIC SMALL LETTER DZHE + '\u2116' # 0xDC -> NUMERO SIGN + '\u0401' # 0xDD -> CYRILLIC CAPITAL LETTER IO + '\u0451' # 0xDE -> CYRILLIC SMALL LETTER IO + '\u044f' # 0xDF -> CYRILLIC SMALL LETTER YA + '\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + '\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + '\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + '\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + '\u20ac' # 0xFF -> EURO SIGN +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_farsi.py b/winvenv/Lib/encodings/mac_farsi.py new file mode 100644 index 0000000..e357d43 --- /dev/null +++ b/winvenv/Lib/encodings/mac_farsi.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_farsi generated from 'MAPPINGS/VENDORS/APPLE/FARSI.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-farsi', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE, left-right + '!' # 0x21 -> EXCLAMATION MARK, left-right + '"' # 0x22 -> QUOTATION MARK, left-right + '#' # 0x23 -> NUMBER SIGN, left-right + '$' # 0x24 -> DOLLAR SIGN, left-right + '%' # 0x25 -> PERCENT SIGN, left-right + '&' # 0x26 -> AMPERSAND, left-right + "'" # 0x27 -> APOSTROPHE, left-right + '(' # 0x28 -> LEFT PARENTHESIS, left-right + ')' # 0x29 -> RIGHT PARENTHESIS, left-right + '*' # 0x2A -> ASTERISK, left-right + '+' # 0x2B -> PLUS SIGN, left-right + ',' # 0x2C -> COMMA, left-right; in Arabic-script context, displayed as 0x066C ARABIC THOUSANDS SEPARATOR + '-' # 0x2D -> HYPHEN-MINUS, left-right + '.' # 0x2E -> FULL STOP, left-right; in Arabic-script context, displayed as 0x066B ARABIC DECIMAL SEPARATOR + '/' # 0x2F -> SOLIDUS, left-right + '0' # 0x30 -> DIGIT ZERO; in Arabic-script context, displayed as 0x06F0 EXTENDED ARABIC-INDIC DIGIT ZERO + '1' # 0x31 -> DIGIT ONE; in Arabic-script context, displayed as 0x06F1 EXTENDED ARABIC-INDIC DIGIT ONE + '2' # 0x32 -> DIGIT TWO; in Arabic-script context, displayed as 0x06F2 EXTENDED ARABIC-INDIC DIGIT TWO + '3' # 0x33 -> DIGIT THREE; in Arabic-script context, displayed as 0x06F3 EXTENDED ARABIC-INDIC DIGIT THREE + '4' # 0x34 -> DIGIT FOUR; in Arabic-script context, displayed as 0x06F4 EXTENDED ARABIC-INDIC DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE; in Arabic-script context, displayed as 0x06F5 EXTENDED ARABIC-INDIC DIGIT FIVE + '6' # 0x36 -> DIGIT SIX; in Arabic-script context, displayed as 0x06F6 EXTENDED ARABIC-INDIC DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN; in Arabic-script context, displayed as 0x06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT; in Arabic-script context, displayed as 0x06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE; in Arabic-script context, displayed as 0x06F9 EXTENDED ARABIC-INDIC DIGIT NINE + ':' # 0x3A -> COLON, left-right + ';' # 0x3B -> SEMICOLON, left-right + '<' # 0x3C -> LESS-THAN SIGN, left-right + '=' # 0x3D -> EQUALS SIGN, left-right + '>' # 0x3E -> GREATER-THAN SIGN, left-right + '?' # 0x3F -> QUESTION MARK, left-right + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET, left-right + '\\' # 0x5C -> REVERSE SOLIDUS, left-right + ']' # 0x5D -> RIGHT SQUARE BRACKET, left-right + '^' # 0x5E -> CIRCUMFLEX ACCENT, left-right + '_' # 0x5F -> LOW LINE, left-right + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET, left-right + '|' # 0x7C -> VERTICAL LINE, left-right + '}' # 0x7D -> RIGHT CURLY BRACKET, left-right + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xa0' # 0x81 -> NO-BREAK SPACE, right-left + '\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\u06ba' # 0x8B -> ARABIC LETTER NOON GHUNNA + '\xab' # 0x8C -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\u2026' # 0x93 -> HORIZONTAL ELLIPSIS, right-left + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\xbb' # 0x98 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK, right-left + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0x9B -> DIVISION SIGN, right-left + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + ' ' # 0xA0 -> SPACE, right-left + '!' # 0xA1 -> EXCLAMATION MARK, right-left + '"' # 0xA2 -> QUOTATION MARK, right-left + '#' # 0xA3 -> NUMBER SIGN, right-left + '$' # 0xA4 -> DOLLAR SIGN, right-left + '\u066a' # 0xA5 -> ARABIC PERCENT SIGN + '&' # 0xA6 -> AMPERSAND, right-left + "'" # 0xA7 -> APOSTROPHE, right-left + '(' # 0xA8 -> LEFT PARENTHESIS, right-left + ')' # 0xA9 -> RIGHT PARENTHESIS, right-left + '*' # 0xAA -> ASTERISK, right-left + '+' # 0xAB -> PLUS SIGN, right-left + '\u060c' # 0xAC -> ARABIC COMMA + '-' # 0xAD -> HYPHEN-MINUS, right-left + '.' # 0xAE -> FULL STOP, right-left + '/' # 0xAF -> SOLIDUS, right-left + '\u06f0' # 0xB0 -> EXTENDED ARABIC-INDIC DIGIT ZERO, right-left (need override) + '\u06f1' # 0xB1 -> EXTENDED ARABIC-INDIC DIGIT ONE, right-left (need override) + '\u06f2' # 0xB2 -> EXTENDED ARABIC-INDIC DIGIT TWO, right-left (need override) + '\u06f3' # 0xB3 -> EXTENDED ARABIC-INDIC DIGIT THREE, right-left (need override) + '\u06f4' # 0xB4 -> EXTENDED ARABIC-INDIC DIGIT FOUR, right-left (need override) + '\u06f5' # 0xB5 -> EXTENDED ARABIC-INDIC DIGIT FIVE, right-left (need override) + '\u06f6' # 0xB6 -> EXTENDED ARABIC-INDIC DIGIT SIX, right-left (need override) + '\u06f7' # 0xB7 -> EXTENDED ARABIC-INDIC DIGIT SEVEN, right-left (need override) + '\u06f8' # 0xB8 -> EXTENDED ARABIC-INDIC DIGIT EIGHT, right-left (need override) + '\u06f9' # 0xB9 -> EXTENDED ARABIC-INDIC DIGIT NINE, right-left (need override) + ':' # 0xBA -> COLON, right-left + '\u061b' # 0xBB -> ARABIC SEMICOLON + '<' # 0xBC -> LESS-THAN SIGN, right-left + '=' # 0xBD -> EQUALS SIGN, right-left + '>' # 0xBE -> GREATER-THAN SIGN, right-left + '\u061f' # 0xBF -> ARABIC QUESTION MARK + '\u274a' # 0xC0 -> EIGHT TEARDROP-SPOKED PROPELLER ASTERISK, right-left + '\u0621' # 0xC1 -> ARABIC LETTER HAMZA + '\u0622' # 0xC2 -> ARABIC LETTER ALEF WITH MADDA ABOVE + '\u0623' # 0xC3 -> ARABIC LETTER ALEF WITH HAMZA ABOVE + '\u0624' # 0xC4 -> ARABIC LETTER WAW WITH HAMZA ABOVE + '\u0625' # 0xC5 -> ARABIC LETTER ALEF WITH HAMZA BELOW + '\u0626' # 0xC6 -> ARABIC LETTER YEH WITH HAMZA ABOVE + '\u0627' # 0xC7 -> ARABIC LETTER ALEF + '\u0628' # 0xC8 -> ARABIC LETTER BEH + '\u0629' # 0xC9 -> ARABIC LETTER TEH MARBUTA + '\u062a' # 0xCA -> ARABIC LETTER TEH + '\u062b' # 0xCB -> ARABIC LETTER THEH + '\u062c' # 0xCC -> ARABIC LETTER JEEM + '\u062d' # 0xCD -> ARABIC LETTER HAH + '\u062e' # 0xCE -> ARABIC LETTER KHAH + '\u062f' # 0xCF -> ARABIC LETTER DAL + '\u0630' # 0xD0 -> ARABIC LETTER THAL + '\u0631' # 0xD1 -> ARABIC LETTER REH + '\u0632' # 0xD2 -> ARABIC LETTER ZAIN + '\u0633' # 0xD3 -> ARABIC LETTER SEEN + '\u0634' # 0xD4 -> ARABIC LETTER SHEEN + '\u0635' # 0xD5 -> ARABIC LETTER SAD + '\u0636' # 0xD6 -> ARABIC LETTER DAD + '\u0637' # 0xD7 -> ARABIC LETTER TAH + '\u0638' # 0xD8 -> ARABIC LETTER ZAH + '\u0639' # 0xD9 -> ARABIC LETTER AIN + '\u063a' # 0xDA -> ARABIC LETTER GHAIN + '[' # 0xDB -> LEFT SQUARE BRACKET, right-left + '\\' # 0xDC -> REVERSE SOLIDUS, right-left + ']' # 0xDD -> RIGHT SQUARE BRACKET, right-left + '^' # 0xDE -> CIRCUMFLEX ACCENT, right-left + '_' # 0xDF -> LOW LINE, right-left + '\u0640' # 0xE0 -> ARABIC TATWEEL + '\u0641' # 0xE1 -> ARABIC LETTER FEH + '\u0642' # 0xE2 -> ARABIC LETTER QAF + '\u0643' # 0xE3 -> ARABIC LETTER KAF + '\u0644' # 0xE4 -> ARABIC LETTER LAM + '\u0645' # 0xE5 -> ARABIC LETTER MEEM + '\u0646' # 0xE6 -> ARABIC LETTER NOON + '\u0647' # 0xE7 -> ARABIC LETTER HEH + '\u0648' # 0xE8 -> ARABIC LETTER WAW + '\u0649' # 0xE9 -> ARABIC LETTER ALEF MAKSURA + '\u064a' # 0xEA -> ARABIC LETTER YEH + '\u064b' # 0xEB -> ARABIC FATHATAN + '\u064c' # 0xEC -> ARABIC DAMMATAN + '\u064d' # 0xED -> ARABIC KASRATAN + '\u064e' # 0xEE -> ARABIC FATHA + '\u064f' # 0xEF -> ARABIC DAMMA + '\u0650' # 0xF0 -> ARABIC KASRA + '\u0651' # 0xF1 -> ARABIC SHADDA + '\u0652' # 0xF2 -> ARABIC SUKUN + '\u067e' # 0xF3 -> ARABIC LETTER PEH + '\u0679' # 0xF4 -> ARABIC LETTER TTEH + '\u0686' # 0xF5 -> ARABIC LETTER TCHEH + '\u06d5' # 0xF6 -> ARABIC LETTER AE + '\u06a4' # 0xF7 -> ARABIC LETTER VEH + '\u06af' # 0xF8 -> ARABIC LETTER GAF + '\u0688' # 0xF9 -> ARABIC LETTER DDAL + '\u0691' # 0xFA -> ARABIC LETTER RREH + '{' # 0xFB -> LEFT CURLY BRACKET, right-left + '|' # 0xFC -> VERTICAL LINE, right-left + '}' # 0xFD -> RIGHT CURLY BRACKET, right-left + '\u0698' # 0xFE -> ARABIC LETTER JEH + '\u06d2' # 0xFF -> ARABIC LETTER YEH BARREE +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_greek.py b/winvenv/Lib/encodings/mac_greek.py new file mode 100644 index 0000000..d3d0c4f --- /dev/null +++ b/winvenv/Lib/encodings/mac_greek.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_greek generated from 'MAPPINGS/VENDORS/APPLE/GREEK.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-greek', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xb9' # 0x81 -> SUPERSCRIPT ONE + '\xb2' # 0x82 -> SUPERSCRIPT TWO + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xb3' # 0x84 -> SUPERSCRIPT THREE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\u0385' # 0x87 -> GREEK DIALYTIKA TONOS + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\u0384' # 0x8B -> GREEK TONOS + '\xa8' # 0x8C -> DIAERESIS + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xa3' # 0x92 -> POUND SIGN + '\u2122' # 0x93 -> TRADE MARK SIGN + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\u2022' # 0x96 -> BULLET + '\xbd' # 0x97 -> VULGAR FRACTION ONE HALF + '\u2030' # 0x98 -> PER MILLE SIGN + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xa6' # 0x9B -> BROKEN BAR + '\u20ac' # 0x9C -> EURO SIGN # before Mac OS 9.2.2, was SOFT HYPHEN + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\u0393' # 0xA1 -> GREEK CAPITAL LETTER GAMMA + '\u0394' # 0xA2 -> GREEK CAPITAL LETTER DELTA + '\u0398' # 0xA3 -> GREEK CAPITAL LETTER THETA + '\u039b' # 0xA4 -> GREEK CAPITAL LETTER LAMDA + '\u039e' # 0xA5 -> GREEK CAPITAL LETTER XI + '\u03a0' # 0xA6 -> GREEK CAPITAL LETTER PI + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u03a3' # 0xAA -> GREEK CAPITAL LETTER SIGMA + '\u03aa' # 0xAB -> GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + '\xa7' # 0xAC -> SECTION SIGN + '\u2260' # 0xAD -> NOT EQUAL TO + '\xb0' # 0xAE -> DEGREE SIGN + '\xb7' # 0xAF -> MIDDLE DOT + '\u0391' # 0xB0 -> GREEK CAPITAL LETTER ALPHA + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\xa5' # 0xB4 -> YEN SIGN + '\u0392' # 0xB5 -> GREEK CAPITAL LETTER BETA + '\u0395' # 0xB6 -> GREEK CAPITAL LETTER EPSILON + '\u0396' # 0xB7 -> GREEK CAPITAL LETTER ZETA + '\u0397' # 0xB8 -> GREEK CAPITAL LETTER ETA + '\u0399' # 0xB9 -> GREEK CAPITAL LETTER IOTA + '\u039a' # 0xBA -> GREEK CAPITAL LETTER KAPPA + '\u039c' # 0xBB -> GREEK CAPITAL LETTER MU + '\u03a6' # 0xBC -> GREEK CAPITAL LETTER PHI + '\u03ab' # 0xBD -> GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + '\u03a8' # 0xBE -> GREEK CAPITAL LETTER PSI + '\u03a9' # 0xBF -> GREEK CAPITAL LETTER OMEGA + '\u03ac' # 0xC0 -> GREEK SMALL LETTER ALPHA WITH TONOS + '\u039d' # 0xC1 -> GREEK CAPITAL LETTER NU + '\xac' # 0xC2 -> NOT SIGN + '\u039f' # 0xC3 -> GREEK CAPITAL LETTER OMICRON + '\u03a1' # 0xC4 -> GREEK CAPITAL LETTER RHO + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u03a4' # 0xC6 -> GREEK CAPITAL LETTER TAU + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\u03a5' # 0xCB -> GREEK CAPITAL LETTER UPSILON + '\u03a7' # 0xCC -> GREEK CAPITAL LETTER CHI + '\u0386' # 0xCD -> GREEK CAPITAL LETTER ALPHA WITH TONOS + '\u0388' # 0xCE -> GREEK CAPITAL LETTER EPSILON WITH TONOS + '\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + '\u2013' # 0xD0 -> EN DASH + '\u2015' # 0xD1 -> HORIZONTAL BAR + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u0389' # 0xD7 -> GREEK CAPITAL LETTER ETA WITH TONOS + '\u038a' # 0xD8 -> GREEK CAPITAL LETTER IOTA WITH TONOS + '\u038c' # 0xD9 -> GREEK CAPITAL LETTER OMICRON WITH TONOS + '\u038e' # 0xDA -> GREEK CAPITAL LETTER UPSILON WITH TONOS + '\u03ad' # 0xDB -> GREEK SMALL LETTER EPSILON WITH TONOS + '\u03ae' # 0xDC -> GREEK SMALL LETTER ETA WITH TONOS + '\u03af' # 0xDD -> GREEK SMALL LETTER IOTA WITH TONOS + '\u03cc' # 0xDE -> GREEK SMALL LETTER OMICRON WITH TONOS + '\u038f' # 0xDF -> GREEK CAPITAL LETTER OMEGA WITH TONOS + '\u03cd' # 0xE0 -> GREEK SMALL LETTER UPSILON WITH TONOS + '\u03b1' # 0xE1 -> GREEK SMALL LETTER ALPHA + '\u03b2' # 0xE2 -> GREEK SMALL LETTER BETA + '\u03c8' # 0xE3 -> GREEK SMALL LETTER PSI + '\u03b4' # 0xE4 -> GREEK SMALL LETTER DELTA + '\u03b5' # 0xE5 -> GREEK SMALL LETTER EPSILON + '\u03c6' # 0xE6 -> GREEK SMALL LETTER PHI + '\u03b3' # 0xE7 -> GREEK SMALL LETTER GAMMA + '\u03b7' # 0xE8 -> GREEK SMALL LETTER ETA + '\u03b9' # 0xE9 -> GREEK SMALL LETTER IOTA + '\u03be' # 0xEA -> GREEK SMALL LETTER XI + '\u03ba' # 0xEB -> GREEK SMALL LETTER KAPPA + '\u03bb' # 0xEC -> GREEK SMALL LETTER LAMDA + '\u03bc' # 0xED -> GREEK SMALL LETTER MU + '\u03bd' # 0xEE -> GREEK SMALL LETTER NU + '\u03bf' # 0xEF -> GREEK SMALL LETTER OMICRON + '\u03c0' # 0xF0 -> GREEK SMALL LETTER PI + '\u03ce' # 0xF1 -> GREEK SMALL LETTER OMEGA WITH TONOS + '\u03c1' # 0xF2 -> GREEK SMALL LETTER RHO + '\u03c3' # 0xF3 -> GREEK SMALL LETTER SIGMA + '\u03c4' # 0xF4 -> GREEK SMALL LETTER TAU + '\u03b8' # 0xF5 -> GREEK SMALL LETTER THETA + '\u03c9' # 0xF6 -> GREEK SMALL LETTER OMEGA + '\u03c2' # 0xF7 -> GREEK SMALL LETTER FINAL SIGMA + '\u03c7' # 0xF8 -> GREEK SMALL LETTER CHI + '\u03c5' # 0xF9 -> GREEK SMALL LETTER UPSILON + '\u03b6' # 0xFA -> GREEK SMALL LETTER ZETA + '\u03ca' # 0xFB -> GREEK SMALL LETTER IOTA WITH DIALYTIKA + '\u03cb' # 0xFC -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA + '\u0390' # 0xFD -> GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + '\u03b0' # 0xFE -> GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + '\xad' # 0xFF -> SOFT HYPHEN # before Mac OS 9.2.2, was undefined +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_iceland.py b/winvenv/Lib/encodings/mac_iceland.py new file mode 100644 index 0000000..add10f4 --- /dev/null +++ b/winvenv/Lib/encodings/mac_iceland.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_iceland generated from 'MAPPINGS/VENDORS/APPLE/ICELAND.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-iceland', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\xdd' # 0xA0 -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xb0' # 0xA1 -> DEGREE SIGN + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\xb4' # 0xAB -> ACUTE ACCENT + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\xc6' # 0xAE -> LATIN CAPITAL LETTER AE + '\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + '\u221e' # 0xB0 -> INFINITY + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\xa5' # 0xB4 -> YEN SIGN + '\xb5' # 0xB5 -> MICRO SIGN + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u220f' # 0xB8 -> N-ARY PRODUCT + '\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + '\u222b' # 0xBA -> INTEGRAL + '\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + '\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + '\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + '\xe6' # 0xBE -> LATIN SMALL LETTER AE + '\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + '\xbf' # 0xC0 -> INVERTED QUESTION MARK + '\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\u2044' # 0xDA -> FRACTION SLASH + '\u20ac' # 0xDB -> EURO SIGN + '\xd0' # 0xDC -> LATIN CAPITAL LETTER ETH + '\xf0' # 0xDD -> LATIN SMALL LETTER ETH + '\xde' # 0xDE -> LATIN CAPITAL LETTER THORN + '\xfe' # 0xDF -> LATIN SMALL LETTER THORN + '\xfd' # 0xE0 -> LATIN SMALL LETTER Y WITH ACUTE + '\xb7' # 0xE1 -> MIDDLE DOT + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u2030' # 0xE4 -> PER MILLE SIGN + '\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\uf8ff' # 0xF0 -> Apple logo + '\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + '\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + '\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u02dc' # 0xF7 -> SMALL TILDE + '\xaf' # 0xF8 -> MACRON + '\u02d8' # 0xF9 -> BREVE + '\u02d9' # 0xFA -> DOT ABOVE + '\u02da' # 0xFB -> RING ABOVE + '\xb8' # 0xFC -> CEDILLA + '\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + '\u02db' # 0xFE -> OGONEK + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_latin2.py b/winvenv/Lib/encodings/mac_latin2.py new file mode 100644 index 0000000..da9d4b1 --- /dev/null +++ b/winvenv/Lib/encodings/mac_latin2.py @@ -0,0 +1,312 @@ +""" Python Character Mapping Codec mac_latin2 generated from 'MAPPINGS/VENDORS/MICSFT/MAC/LATIN2.TXT' with gencodec.py. + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. +(c) Copyright 2000 Guido van Rossum. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-latin2', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\u0100' # 0x81 -> LATIN CAPITAL LETTER A WITH MACRON + '\u0101' # 0x82 -> LATIN SMALL LETTER A WITH MACRON + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\u0104' # 0x84 -> LATIN CAPITAL LETTER A WITH OGONEK + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\u0105' # 0x88 -> LATIN SMALL LETTER A WITH OGONEK + '\u010c' # 0x89 -> LATIN CAPITAL LETTER C WITH CARON + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\u010d' # 0x8B -> LATIN SMALL LETTER C WITH CARON + '\u0106' # 0x8C -> LATIN CAPITAL LETTER C WITH ACUTE + '\u0107' # 0x8D -> LATIN SMALL LETTER C WITH ACUTE + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\u0179' # 0x8F -> LATIN CAPITAL LETTER Z WITH ACUTE + '\u017a' # 0x90 -> LATIN SMALL LETTER Z WITH ACUTE + '\u010e' # 0x91 -> LATIN CAPITAL LETTER D WITH CARON + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\u010f' # 0x93 -> LATIN SMALL LETTER D WITH CARON + '\u0112' # 0x94 -> LATIN CAPITAL LETTER E WITH MACRON + '\u0113' # 0x95 -> LATIN SMALL LETTER E WITH MACRON + '\u0116' # 0x96 -> LATIN CAPITAL LETTER E WITH DOT ABOVE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\u0117' # 0x98 -> LATIN SMALL LETTER E WITH DOT ABOVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\u011a' # 0x9D -> LATIN CAPITAL LETTER E WITH CARON + '\u011b' # 0x9E -> LATIN SMALL LETTER E WITH CARON + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\u0118' # 0xA2 -> LATIN CAPITAL LETTER E WITH OGONEK + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\u0119' # 0xAB -> LATIN SMALL LETTER E WITH OGONEK + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\u0123' # 0xAE -> LATIN SMALL LETTER G WITH CEDILLA + '\u012e' # 0xAF -> LATIN CAPITAL LETTER I WITH OGONEK + '\u012f' # 0xB0 -> LATIN SMALL LETTER I WITH OGONEK + '\u012a' # 0xB1 -> LATIN CAPITAL LETTER I WITH MACRON + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\u012b' # 0xB4 -> LATIN SMALL LETTER I WITH MACRON + '\u0136' # 0xB5 -> LATIN CAPITAL LETTER K WITH CEDILLA + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u0142' # 0xB8 -> LATIN SMALL LETTER L WITH STROKE + '\u013b' # 0xB9 -> LATIN CAPITAL LETTER L WITH CEDILLA + '\u013c' # 0xBA -> LATIN SMALL LETTER L WITH CEDILLA + '\u013d' # 0xBB -> LATIN CAPITAL LETTER L WITH CARON + '\u013e' # 0xBC -> LATIN SMALL LETTER L WITH CARON + '\u0139' # 0xBD -> LATIN CAPITAL LETTER L WITH ACUTE + '\u013a' # 0xBE -> LATIN SMALL LETTER L WITH ACUTE + '\u0145' # 0xBF -> LATIN CAPITAL LETTER N WITH CEDILLA + '\u0146' # 0xC0 -> LATIN SMALL LETTER N WITH CEDILLA + '\u0143' # 0xC1 -> LATIN CAPITAL LETTER N WITH ACUTE + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0144' # 0xC4 -> LATIN SMALL LETTER N WITH ACUTE + '\u0147' # 0xC5 -> LATIN CAPITAL LETTER N WITH CARON + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\u0148' # 0xCB -> LATIN SMALL LETTER N WITH CARON + '\u0150' # 0xCC -> LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0151' # 0xCE -> LATIN SMALL LETTER O WITH DOUBLE ACUTE + '\u014c' # 0xCF -> LATIN CAPITAL LETTER O WITH MACRON + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\u014d' # 0xD8 -> LATIN SMALL LETTER O WITH MACRON + '\u0154' # 0xD9 -> LATIN CAPITAL LETTER R WITH ACUTE + '\u0155' # 0xDA -> LATIN SMALL LETTER R WITH ACUTE + '\u0158' # 0xDB -> LATIN CAPITAL LETTER R WITH CARON + '\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u0159' # 0xDE -> LATIN SMALL LETTER R WITH CARON + '\u0156' # 0xDF -> LATIN CAPITAL LETTER R WITH CEDILLA + '\u0157' # 0xE0 -> LATIN SMALL LETTER R WITH CEDILLA + '\u0160' # 0xE1 -> LATIN CAPITAL LETTER S WITH CARON + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u0161' # 0xE4 -> LATIN SMALL LETTER S WITH CARON + '\u015a' # 0xE5 -> LATIN CAPITAL LETTER S WITH ACUTE + '\u015b' # 0xE6 -> LATIN SMALL LETTER S WITH ACUTE + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\u0164' # 0xE8 -> LATIN CAPITAL LETTER T WITH CARON + '\u0165' # 0xE9 -> LATIN SMALL LETTER T WITH CARON + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\u017d' # 0xEB -> LATIN CAPITAL LETTER Z WITH CARON + '\u017e' # 0xEC -> LATIN SMALL LETTER Z WITH CARON + '\u016a' # 0xED -> LATIN CAPITAL LETTER U WITH MACRON + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\u016b' # 0xF0 -> LATIN SMALL LETTER U WITH MACRON + '\u016e' # 0xF1 -> LATIN CAPITAL LETTER U WITH RING ABOVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\u016f' # 0xF3 -> LATIN SMALL LETTER U WITH RING ABOVE + '\u0170' # 0xF4 -> LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + '\u0171' # 0xF5 -> LATIN SMALL LETTER U WITH DOUBLE ACUTE + '\u0172' # 0xF6 -> LATIN CAPITAL LETTER U WITH OGONEK + '\u0173' # 0xF7 -> LATIN SMALL LETTER U WITH OGONEK + '\xdd' # 0xF8 -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xfd' # 0xF9 -> LATIN SMALL LETTER Y WITH ACUTE + '\u0137' # 0xFA -> LATIN SMALL LETTER K WITH CEDILLA + '\u017b' # 0xFB -> LATIN CAPITAL LETTER Z WITH DOT ABOVE + '\u0141' # 0xFC -> LATIN CAPITAL LETTER L WITH STROKE + '\u017c' # 0xFD -> LATIN SMALL LETTER Z WITH DOT ABOVE + '\u0122' # 0xFE -> LATIN CAPITAL LETTER G WITH CEDILLA + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_roman.py b/winvenv/Lib/encodings/mac_roman.py new file mode 100644 index 0000000..b74b002 --- /dev/null +++ b/winvenv/Lib/encodings/mac_roman.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_roman generated from 'MAPPINGS/VENDORS/APPLE/ROMAN.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-roman', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\xb4' # 0xAB -> ACUTE ACCENT + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\xc6' # 0xAE -> LATIN CAPITAL LETTER AE + '\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + '\u221e' # 0xB0 -> INFINITY + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\xa5' # 0xB4 -> YEN SIGN + '\xb5' # 0xB5 -> MICRO SIGN + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u220f' # 0xB8 -> N-ARY PRODUCT + '\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + '\u222b' # 0xBA -> INTEGRAL + '\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + '\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + '\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + '\xe6' # 0xBE -> LATIN SMALL LETTER AE + '\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + '\xbf' # 0xC0 -> INVERTED QUESTION MARK + '\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\u2044' # 0xDA -> FRACTION SLASH + '\u20ac' # 0xDB -> EURO SIGN + '\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\ufb01' # 0xDE -> LATIN SMALL LIGATURE FI + '\ufb02' # 0xDF -> LATIN SMALL LIGATURE FL + '\u2021' # 0xE0 -> DOUBLE DAGGER + '\xb7' # 0xE1 -> MIDDLE DOT + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u2030' # 0xE4 -> PER MILLE SIGN + '\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\uf8ff' # 0xF0 -> Apple logo + '\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + '\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + '\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u02dc' # 0xF7 -> SMALL TILDE + '\xaf' # 0xF8 -> MACRON + '\u02d8' # 0xF9 -> BREVE + '\u02d9' # 0xFA -> DOT ABOVE + '\u02da' # 0xFB -> RING ABOVE + '\xb8' # 0xFC -> CEDILLA + '\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + '\u02db' # 0xFE -> OGONEK + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_romanian.py b/winvenv/Lib/encodings/mac_romanian.py new file mode 100644 index 0000000..d141b4c --- /dev/null +++ b/winvenv/Lib/encodings/mac_romanian.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_romanian generated from 'MAPPINGS/VENDORS/APPLE/ROMANIAN.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-romanian', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\xb4' # 0xAB -> ACUTE ACCENT + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\u0102' # 0xAE -> LATIN CAPITAL LETTER A WITH BREVE + '\u0218' # 0xAF -> LATIN CAPITAL LETTER S WITH COMMA BELOW # for Unicode 3.0 and later + '\u221e' # 0xB0 -> INFINITY + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\xa5' # 0xB4 -> YEN SIGN + '\xb5' # 0xB5 -> MICRO SIGN + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u220f' # 0xB8 -> N-ARY PRODUCT + '\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + '\u222b' # 0xBA -> INTEGRAL + '\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + '\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + '\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + '\u0103' # 0xBE -> LATIN SMALL LETTER A WITH BREVE + '\u0219' # 0xBF -> LATIN SMALL LETTER S WITH COMMA BELOW # for Unicode 3.0 and later + '\xbf' # 0xC0 -> INVERTED QUESTION MARK + '\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\u2044' # 0xDA -> FRACTION SLASH + '\u20ac' # 0xDB -> EURO SIGN + '\u2039' # 0xDC -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u203a' # 0xDD -> SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + '\u021a' # 0xDE -> LATIN CAPITAL LETTER T WITH COMMA BELOW # for Unicode 3.0 and later + '\u021b' # 0xDF -> LATIN SMALL LETTER T WITH COMMA BELOW # for Unicode 3.0 and later + '\u2021' # 0xE0 -> DOUBLE DAGGER + '\xb7' # 0xE1 -> MIDDLE DOT + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u2030' # 0xE4 -> PER MILLE SIGN + '\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\uf8ff' # 0xF0 -> Apple logo + '\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + '\u0131' # 0xF5 -> LATIN SMALL LETTER DOTLESS I + '\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u02dc' # 0xF7 -> SMALL TILDE + '\xaf' # 0xF8 -> MACRON + '\u02d8' # 0xF9 -> BREVE + '\u02d9' # 0xFA -> DOT ABOVE + '\u02da' # 0xFB -> RING ABOVE + '\xb8' # 0xFC -> CEDILLA + '\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + '\u02db' # 0xFE -> OGONEK + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mac_turkish.py b/winvenv/Lib/encodings/mac_turkish.py new file mode 100644 index 0000000..044d4cb --- /dev/null +++ b/winvenv/Lib/encodings/mac_turkish.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec mac_turkish generated from 'MAPPINGS/VENDORS/APPLE/TURKISH.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mac-turkish', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> CONTROL CHARACTER + '\x01' # 0x01 -> CONTROL CHARACTER + '\x02' # 0x02 -> CONTROL CHARACTER + '\x03' # 0x03 -> CONTROL CHARACTER + '\x04' # 0x04 -> CONTROL CHARACTER + '\x05' # 0x05 -> CONTROL CHARACTER + '\x06' # 0x06 -> CONTROL CHARACTER + '\x07' # 0x07 -> CONTROL CHARACTER + '\x08' # 0x08 -> CONTROL CHARACTER + '\t' # 0x09 -> CONTROL CHARACTER + '\n' # 0x0A -> CONTROL CHARACTER + '\x0b' # 0x0B -> CONTROL CHARACTER + '\x0c' # 0x0C -> CONTROL CHARACTER + '\r' # 0x0D -> CONTROL CHARACTER + '\x0e' # 0x0E -> CONTROL CHARACTER + '\x0f' # 0x0F -> CONTROL CHARACTER + '\x10' # 0x10 -> CONTROL CHARACTER + '\x11' # 0x11 -> CONTROL CHARACTER + '\x12' # 0x12 -> CONTROL CHARACTER + '\x13' # 0x13 -> CONTROL CHARACTER + '\x14' # 0x14 -> CONTROL CHARACTER + '\x15' # 0x15 -> CONTROL CHARACTER + '\x16' # 0x16 -> CONTROL CHARACTER + '\x17' # 0x17 -> CONTROL CHARACTER + '\x18' # 0x18 -> CONTROL CHARACTER + '\x19' # 0x19 -> CONTROL CHARACTER + '\x1a' # 0x1A -> CONTROL CHARACTER + '\x1b' # 0x1B -> CONTROL CHARACTER + '\x1c' # 0x1C -> CONTROL CHARACTER + '\x1d' # 0x1D -> CONTROL CHARACTER + '\x1e' # 0x1E -> CONTROL CHARACTER + '\x1f' # 0x1F -> CONTROL CHARACTER + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> CONTROL CHARACTER + '\xc4' # 0x80 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0x81 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc7' # 0x82 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc9' # 0x83 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xd1' # 0x84 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd6' # 0x85 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xdc' # 0x86 -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xe1' # 0x87 -> LATIN SMALL LETTER A WITH ACUTE + '\xe0' # 0x88 -> LATIN SMALL LETTER A WITH GRAVE + '\xe2' # 0x89 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe4' # 0x8A -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe3' # 0x8B -> LATIN SMALL LETTER A WITH TILDE + '\xe5' # 0x8C -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe7' # 0x8D -> LATIN SMALL LETTER C WITH CEDILLA + '\xe9' # 0x8E -> LATIN SMALL LETTER E WITH ACUTE + '\xe8' # 0x8F -> LATIN SMALL LETTER E WITH GRAVE + '\xea' # 0x90 -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0x91 -> LATIN SMALL LETTER E WITH DIAERESIS + '\xed' # 0x92 -> LATIN SMALL LETTER I WITH ACUTE + '\xec' # 0x93 -> LATIN SMALL LETTER I WITH GRAVE + '\xee' # 0x94 -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0x95 -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf1' # 0x96 -> LATIN SMALL LETTER N WITH TILDE + '\xf3' # 0x97 -> LATIN SMALL LETTER O WITH ACUTE + '\xf2' # 0x98 -> LATIN SMALL LETTER O WITH GRAVE + '\xf4' # 0x99 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf6' # 0x9A -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf5' # 0x9B -> LATIN SMALL LETTER O WITH TILDE + '\xfa' # 0x9C -> LATIN SMALL LETTER U WITH ACUTE + '\xf9' # 0x9D -> LATIN SMALL LETTER U WITH GRAVE + '\xfb' # 0x9E -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0x9F -> LATIN SMALL LETTER U WITH DIAERESIS + '\u2020' # 0xA0 -> DAGGER + '\xb0' # 0xA1 -> DEGREE SIGN + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa7' # 0xA4 -> SECTION SIGN + '\u2022' # 0xA5 -> BULLET + '\xb6' # 0xA6 -> PILCROW SIGN + '\xdf' # 0xA7 -> LATIN SMALL LETTER SHARP S + '\xae' # 0xA8 -> REGISTERED SIGN + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u2122' # 0xAA -> TRADE MARK SIGN + '\xb4' # 0xAB -> ACUTE ACCENT + '\xa8' # 0xAC -> DIAERESIS + '\u2260' # 0xAD -> NOT EQUAL TO + '\xc6' # 0xAE -> LATIN CAPITAL LETTER AE + '\xd8' # 0xAF -> LATIN CAPITAL LETTER O WITH STROKE + '\u221e' # 0xB0 -> INFINITY + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\u2264' # 0xB2 -> LESS-THAN OR EQUAL TO + '\u2265' # 0xB3 -> GREATER-THAN OR EQUAL TO + '\xa5' # 0xB4 -> YEN SIGN + '\xb5' # 0xB5 -> MICRO SIGN + '\u2202' # 0xB6 -> PARTIAL DIFFERENTIAL + '\u2211' # 0xB7 -> N-ARY SUMMATION + '\u220f' # 0xB8 -> N-ARY PRODUCT + '\u03c0' # 0xB9 -> GREEK SMALL LETTER PI + '\u222b' # 0xBA -> INTEGRAL + '\xaa' # 0xBB -> FEMININE ORDINAL INDICATOR + '\xba' # 0xBC -> MASCULINE ORDINAL INDICATOR + '\u03a9' # 0xBD -> GREEK CAPITAL LETTER OMEGA + '\xe6' # 0xBE -> LATIN SMALL LETTER AE + '\xf8' # 0xBF -> LATIN SMALL LETTER O WITH STROKE + '\xbf' # 0xC0 -> INVERTED QUESTION MARK + '\xa1' # 0xC1 -> INVERTED EXCLAMATION MARK + '\xac' # 0xC2 -> NOT SIGN + '\u221a' # 0xC3 -> SQUARE ROOT + '\u0192' # 0xC4 -> LATIN SMALL LETTER F WITH HOOK + '\u2248' # 0xC5 -> ALMOST EQUAL TO + '\u2206' # 0xC6 -> INCREMENT + '\xab' # 0xC7 -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbb' # 0xC8 -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u2026' # 0xC9 -> HORIZONTAL ELLIPSIS + '\xa0' # 0xCA -> NO-BREAK SPACE + '\xc0' # 0xCB -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc3' # 0xCC -> LATIN CAPITAL LETTER A WITH TILDE + '\xd5' # 0xCD -> LATIN CAPITAL LETTER O WITH TILDE + '\u0152' # 0xCE -> LATIN CAPITAL LIGATURE OE + '\u0153' # 0xCF -> LATIN SMALL LIGATURE OE + '\u2013' # 0xD0 -> EN DASH + '\u2014' # 0xD1 -> EM DASH + '\u201c' # 0xD2 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0xD3 -> RIGHT DOUBLE QUOTATION MARK + '\u2018' # 0xD4 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0xD5 -> RIGHT SINGLE QUOTATION MARK + '\xf7' # 0xD6 -> DIVISION SIGN + '\u25ca' # 0xD7 -> LOZENGE + '\xff' # 0xD8 -> LATIN SMALL LETTER Y WITH DIAERESIS + '\u0178' # 0xD9 -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\u011e' # 0xDA -> LATIN CAPITAL LETTER G WITH BREVE + '\u011f' # 0xDB -> LATIN SMALL LETTER G WITH BREVE + '\u0130' # 0xDC -> LATIN CAPITAL LETTER I WITH DOT ABOVE + '\u0131' # 0xDD -> LATIN SMALL LETTER DOTLESS I + '\u015e' # 0xDE -> LATIN CAPITAL LETTER S WITH CEDILLA + '\u015f' # 0xDF -> LATIN SMALL LETTER S WITH CEDILLA + '\u2021' # 0xE0 -> DOUBLE DAGGER + '\xb7' # 0xE1 -> MIDDLE DOT + '\u201a' # 0xE2 -> SINGLE LOW-9 QUOTATION MARK + '\u201e' # 0xE3 -> DOUBLE LOW-9 QUOTATION MARK + '\u2030' # 0xE4 -> PER MILLE SIGN + '\xc2' # 0xE5 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xca' # 0xE6 -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xc1' # 0xE7 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xcb' # 0xE8 -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xc8' # 0xE9 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xcd' # 0xEA -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xEB -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xEC -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xcc' # 0xED -> LATIN CAPITAL LETTER I WITH GRAVE + '\xd3' # 0xEE -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xEF -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\uf8ff' # 0xF0 -> Apple logo + '\xd2' # 0xF1 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xda' # 0xF2 -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xF3 -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xd9' # 0xF4 -> LATIN CAPITAL LETTER U WITH GRAVE + '\uf8a0' # 0xF5 -> undefined1 + '\u02c6' # 0xF6 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u02dc' # 0xF7 -> SMALL TILDE + '\xaf' # 0xF8 -> MACRON + '\u02d8' # 0xF9 -> BREVE + '\u02d9' # 0xFA -> DOT ABOVE + '\u02da' # 0xFB -> RING ABOVE + '\xb8' # 0xFC -> CEDILLA + '\u02dd' # 0xFD -> DOUBLE ACUTE ACCENT + '\u02db' # 0xFE -> OGONEK + '\u02c7' # 0xFF -> CARON +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/mbcs.py b/winvenv/Lib/encodings/mbcs.py new file mode 100644 index 0000000..baf46cb --- /dev/null +++ b/winvenv/Lib/encodings/mbcs.py @@ -0,0 +1,47 @@ +""" Python 'mbcs' Codec for Windows + + +Cloned by Mark Hammond (mhammond@skippinet.com.au) from ascii.py, +which was written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +# Import them explicitly to cause an ImportError +# on non-Windows systems +from codecs import mbcs_encode, mbcs_decode +# for IncrementalDecoder, IncrementalEncoder, ... +import codecs + +### Codec APIs + +encode = mbcs_encode + +def decode(input, errors='strict'): + return mbcs_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return mbcs_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = mbcs_decode + +class StreamWriter(codecs.StreamWriter): + encode = mbcs_encode + +class StreamReader(codecs.StreamReader): + decode = mbcs_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='mbcs', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/oem.py b/winvenv/Lib/encodings/oem.py new file mode 100644 index 0000000..2c3426b --- /dev/null +++ b/winvenv/Lib/encodings/oem.py @@ -0,0 +1,41 @@ +""" Python 'oem' Codec for Windows + +""" +# Import them explicitly to cause an ImportError +# on non-Windows systems +from codecs import oem_encode, oem_decode +# for IncrementalDecoder, IncrementalEncoder, ... +import codecs + +### Codec APIs + +encode = oem_encode + +def decode(input, errors='strict'): + return oem_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return oem_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = oem_decode + +class StreamWriter(codecs.StreamWriter): + encode = oem_encode + +class StreamReader(codecs.StreamReader): + decode = oem_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='oem', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/palmos.py b/winvenv/Lib/encodings/palmos.py new file mode 100644 index 0000000..c506d65 --- /dev/null +++ b/winvenv/Lib/encodings/palmos.py @@ -0,0 +1,308 @@ +""" Python Character Mapping Codec for PalmOS 3.5. + +Written by Sjoerd Mullender (sjoerd@acm.org); based on iso8859_15.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='palmos', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\u20ac' # 0x80 -> EURO SIGN + '\x81' # 0x81 -> + '\u201a' # 0x82 -> SINGLE LOW-9 QUOTATION MARK + '\u0192' # 0x83 -> LATIN SMALL LETTER F WITH HOOK + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u2020' # 0x86 -> DAGGER + '\u2021' # 0x87 -> DOUBLE DAGGER + '\u02c6' # 0x88 -> MODIFIER LETTER CIRCUMFLEX ACCENT + '\u2030' # 0x89 -> PER MILLE SIGN + '\u0160' # 0x8A -> LATIN CAPITAL LETTER S WITH CARON + '\u2039' # 0x8B -> SINGLE LEFT-POINTING ANGLE QUOTATION MARK + '\u0152' # 0x8C -> LATIN CAPITAL LIGATURE OE + '\u2666' # 0x8D -> BLACK DIAMOND SUIT + '\u2663' # 0x8E -> BLACK CLUB SUIT + '\u2665' # 0x8F -> BLACK HEART SUIT + '\u2660' # 0x90 -> BLACK SPADE SUIT + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u02dc' # 0x98 -> SMALL TILDE + '\u2122' # 0x99 -> TRADE MARK SIGN + '\u0161' # 0x9A -> LATIN SMALL LETTER S WITH CARON + '\x9b' # 0x9B -> + '\u0153' # 0x9C -> LATIN SMALL LIGATURE OE + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\u0178' # 0x9F -> LATIN CAPITAL LETTER Y WITH DIAERESIS + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\xa1' # 0xA1 -> INVERTED EXCLAMATION MARK + '\xa2' # 0xA2 -> CENT SIGN + '\xa3' # 0xA3 -> POUND SIGN + '\xa4' # 0xA4 -> CURRENCY SIGN + '\xa5' # 0xA5 -> YEN SIGN + '\xa6' # 0xA6 -> BROKEN BAR + '\xa7' # 0xA7 -> SECTION SIGN + '\xa8' # 0xA8 -> DIAERESIS + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\xaa' # 0xAA -> FEMININE ORDINAL INDICATOR + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\xad' # 0xAD -> SOFT HYPHEN + '\xae' # 0xAE -> REGISTERED SIGN + '\xaf' # 0xAF -> MACRON + '\xb0' # 0xB0 -> DEGREE SIGN + '\xb1' # 0xB1 -> PLUS-MINUS SIGN + '\xb2' # 0xB2 -> SUPERSCRIPT TWO + '\xb3' # 0xB3 -> SUPERSCRIPT THREE + '\xb4' # 0xB4 -> ACUTE ACCENT + '\xb5' # 0xB5 -> MICRO SIGN + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\xb8' # 0xB8 -> CEDILLA + '\xb9' # 0xB9 -> SUPERSCRIPT ONE + '\xba' # 0xBA -> MASCULINE ORDINAL INDICATOR + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xbc' # 0xBC -> VULGAR FRACTION ONE QUARTER + '\xbd' # 0xBD -> VULGAR FRACTION ONE HALF + '\xbe' # 0xBE -> VULGAR FRACTION THREE QUARTERS + '\xbf' # 0xBF -> INVERTED QUESTION MARK + '\xc0' # 0xC0 -> LATIN CAPITAL LETTER A WITH GRAVE + '\xc1' # 0xC1 -> LATIN CAPITAL LETTER A WITH ACUTE + '\xc2' # 0xC2 -> LATIN CAPITAL LETTER A WITH CIRCUMFLEX + '\xc3' # 0xC3 -> LATIN CAPITAL LETTER A WITH TILDE + '\xc4' # 0xC4 -> LATIN CAPITAL LETTER A WITH DIAERESIS + '\xc5' # 0xC5 -> LATIN CAPITAL LETTER A WITH RING ABOVE + '\xc6' # 0xC6 -> LATIN CAPITAL LETTER AE + '\xc7' # 0xC7 -> LATIN CAPITAL LETTER C WITH CEDILLA + '\xc8' # 0xC8 -> LATIN CAPITAL LETTER E WITH GRAVE + '\xc9' # 0xC9 -> LATIN CAPITAL LETTER E WITH ACUTE + '\xca' # 0xCA -> LATIN CAPITAL LETTER E WITH CIRCUMFLEX + '\xcb' # 0xCB -> LATIN CAPITAL LETTER E WITH DIAERESIS + '\xcc' # 0xCC -> LATIN CAPITAL LETTER I WITH GRAVE + '\xcd' # 0xCD -> LATIN CAPITAL LETTER I WITH ACUTE + '\xce' # 0xCE -> LATIN CAPITAL LETTER I WITH CIRCUMFLEX + '\xcf' # 0xCF -> LATIN CAPITAL LETTER I WITH DIAERESIS + '\xd0' # 0xD0 -> LATIN CAPITAL LETTER ETH (Icelandic) + '\xd1' # 0xD1 -> LATIN CAPITAL LETTER N WITH TILDE + '\xd2' # 0xD2 -> LATIN CAPITAL LETTER O WITH GRAVE + '\xd3' # 0xD3 -> LATIN CAPITAL LETTER O WITH ACUTE + '\xd4' # 0xD4 -> LATIN CAPITAL LETTER O WITH CIRCUMFLEX + '\xd5' # 0xD5 -> LATIN CAPITAL LETTER O WITH TILDE + '\xd6' # 0xD6 -> LATIN CAPITAL LETTER O WITH DIAERESIS + '\xd7' # 0xD7 -> MULTIPLICATION SIGN + '\xd8' # 0xD8 -> LATIN CAPITAL LETTER O WITH STROKE + '\xd9' # 0xD9 -> LATIN CAPITAL LETTER U WITH GRAVE + '\xda' # 0xDA -> LATIN CAPITAL LETTER U WITH ACUTE + '\xdb' # 0xDB -> LATIN CAPITAL LETTER U WITH CIRCUMFLEX + '\xdc' # 0xDC -> LATIN CAPITAL LETTER U WITH DIAERESIS + '\xdd' # 0xDD -> LATIN CAPITAL LETTER Y WITH ACUTE + '\xde' # 0xDE -> LATIN CAPITAL LETTER THORN (Icelandic) + '\xdf' # 0xDF -> LATIN SMALL LETTER SHARP S (German) + '\xe0' # 0xE0 -> LATIN SMALL LETTER A WITH GRAVE + '\xe1' # 0xE1 -> LATIN SMALL LETTER A WITH ACUTE + '\xe2' # 0xE2 -> LATIN SMALL LETTER A WITH CIRCUMFLEX + '\xe3' # 0xE3 -> LATIN SMALL LETTER A WITH TILDE + '\xe4' # 0xE4 -> LATIN SMALL LETTER A WITH DIAERESIS + '\xe5' # 0xE5 -> LATIN SMALL LETTER A WITH RING ABOVE + '\xe6' # 0xE6 -> LATIN SMALL LETTER AE + '\xe7' # 0xE7 -> LATIN SMALL LETTER C WITH CEDILLA + '\xe8' # 0xE8 -> LATIN SMALL LETTER E WITH GRAVE + '\xe9' # 0xE9 -> LATIN SMALL LETTER E WITH ACUTE + '\xea' # 0xEA -> LATIN SMALL LETTER E WITH CIRCUMFLEX + '\xeb' # 0xEB -> LATIN SMALL LETTER E WITH DIAERESIS + '\xec' # 0xEC -> LATIN SMALL LETTER I WITH GRAVE + '\xed' # 0xED -> LATIN SMALL LETTER I WITH ACUTE + '\xee' # 0xEE -> LATIN SMALL LETTER I WITH CIRCUMFLEX + '\xef' # 0xEF -> LATIN SMALL LETTER I WITH DIAERESIS + '\xf0' # 0xF0 -> LATIN SMALL LETTER ETH (Icelandic) + '\xf1' # 0xF1 -> LATIN SMALL LETTER N WITH TILDE + '\xf2' # 0xF2 -> LATIN SMALL LETTER O WITH GRAVE + '\xf3' # 0xF3 -> LATIN SMALL LETTER O WITH ACUTE + '\xf4' # 0xF4 -> LATIN SMALL LETTER O WITH CIRCUMFLEX + '\xf5' # 0xF5 -> LATIN SMALL LETTER O WITH TILDE + '\xf6' # 0xF6 -> LATIN SMALL LETTER O WITH DIAERESIS + '\xf7' # 0xF7 -> DIVISION SIGN + '\xf8' # 0xF8 -> LATIN SMALL LETTER O WITH STROKE + '\xf9' # 0xF9 -> LATIN SMALL LETTER U WITH GRAVE + '\xfa' # 0xFA -> LATIN SMALL LETTER U WITH ACUTE + '\xfb' # 0xFB -> LATIN SMALL LETTER U WITH CIRCUMFLEX + '\xfc' # 0xFC -> LATIN SMALL LETTER U WITH DIAERESIS + '\xfd' # 0xFD -> LATIN SMALL LETTER Y WITH ACUTE + '\xfe' # 0xFE -> LATIN SMALL LETTER THORN (Icelandic) + '\xff' # 0xFF -> LATIN SMALL LETTER Y WITH DIAERESIS +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/ptcp154.py b/winvenv/Lib/encodings/ptcp154.py new file mode 100644 index 0000000..656b79d --- /dev/null +++ b/winvenv/Lib/encodings/ptcp154.py @@ -0,0 +1,312 @@ +""" Python Character Mapping Codec generated from 'PTCP154.txt' with gencodec.py. + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. +(c) Copyright 2000 Guido van Rossum. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='ptcp154', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE (DEL) + '\u0496' # 0x80 -> CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER + '\u0492' # 0x81 -> CYRILLIC CAPITAL LETTER GHE WITH STROKE + '\u04ee' # 0x82 -> CYRILLIC CAPITAL LETTER U WITH MACRON + '\u0493' # 0x83 -> CYRILLIC SMALL LETTER GHE WITH STROKE + '\u201e' # 0x84 -> DOUBLE LOW-9 QUOTATION MARK + '\u2026' # 0x85 -> HORIZONTAL ELLIPSIS + '\u04b6' # 0x86 -> CYRILLIC CAPITAL LETTER CHE WITH DESCENDER + '\u04ae' # 0x87 -> CYRILLIC CAPITAL LETTER STRAIGHT U + '\u04b2' # 0x88 -> CYRILLIC CAPITAL LETTER HA WITH DESCENDER + '\u04af' # 0x89 -> CYRILLIC SMALL LETTER STRAIGHT U + '\u04a0' # 0x8A -> CYRILLIC CAPITAL LETTER BASHKIR KA + '\u04e2' # 0x8B -> CYRILLIC CAPITAL LETTER I WITH MACRON + '\u04a2' # 0x8C -> CYRILLIC CAPITAL LETTER EN WITH DESCENDER + '\u049a' # 0x8D -> CYRILLIC CAPITAL LETTER KA WITH DESCENDER + '\u04ba' # 0x8E -> CYRILLIC CAPITAL LETTER SHHA + '\u04b8' # 0x8F -> CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE + '\u0497' # 0x90 -> CYRILLIC SMALL LETTER ZHE WITH DESCENDER + '\u2018' # 0x91 -> LEFT SINGLE QUOTATION MARK + '\u2019' # 0x92 -> RIGHT SINGLE QUOTATION MARK + '\u201c' # 0x93 -> LEFT DOUBLE QUOTATION MARK + '\u201d' # 0x94 -> RIGHT DOUBLE QUOTATION MARK + '\u2022' # 0x95 -> BULLET + '\u2013' # 0x96 -> EN DASH + '\u2014' # 0x97 -> EM DASH + '\u04b3' # 0x98 -> CYRILLIC SMALL LETTER HA WITH DESCENDER + '\u04b7' # 0x99 -> CYRILLIC SMALL LETTER CHE WITH DESCENDER + '\u04a1' # 0x9A -> CYRILLIC SMALL LETTER BASHKIR KA + '\u04e3' # 0x9B -> CYRILLIC SMALL LETTER I WITH MACRON + '\u04a3' # 0x9C -> CYRILLIC SMALL LETTER EN WITH DESCENDER + '\u049b' # 0x9D -> CYRILLIC SMALL LETTER KA WITH DESCENDER + '\u04bb' # 0x9E -> CYRILLIC SMALL LETTER SHHA + '\u04b9' # 0x9F -> CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE + '\xa0' # 0xA0 -> NO-BREAK SPACE + '\u040e' # 0xA1 -> CYRILLIC CAPITAL LETTER SHORT U (Byelorussian) + '\u045e' # 0xA2 -> CYRILLIC SMALL LETTER SHORT U (Byelorussian) + '\u0408' # 0xA3 -> CYRILLIC CAPITAL LETTER JE + '\u04e8' # 0xA4 -> CYRILLIC CAPITAL LETTER BARRED O + '\u0498' # 0xA5 -> CYRILLIC CAPITAL LETTER ZE WITH DESCENDER + '\u04b0' # 0xA6 -> CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE + '\xa7' # 0xA7 -> SECTION SIGN + '\u0401' # 0xA8 -> CYRILLIC CAPITAL LETTER IO + '\xa9' # 0xA9 -> COPYRIGHT SIGN + '\u04d8' # 0xAA -> CYRILLIC CAPITAL LETTER SCHWA + '\xab' # 0xAB -> LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + '\xac' # 0xAC -> NOT SIGN + '\u04ef' # 0xAD -> CYRILLIC SMALL LETTER U WITH MACRON + '\xae' # 0xAE -> REGISTERED SIGN + '\u049c' # 0xAF -> CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE + '\xb0' # 0xB0 -> DEGREE SIGN + '\u04b1' # 0xB1 -> CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE + '\u0406' # 0xB2 -> CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0456' # 0xB3 -> CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + '\u0499' # 0xB4 -> CYRILLIC SMALL LETTER ZE WITH DESCENDER + '\u04e9' # 0xB5 -> CYRILLIC SMALL LETTER BARRED O + '\xb6' # 0xB6 -> PILCROW SIGN + '\xb7' # 0xB7 -> MIDDLE DOT + '\u0451' # 0xB8 -> CYRILLIC SMALL LETTER IO + '\u2116' # 0xB9 -> NUMERO SIGN + '\u04d9' # 0xBA -> CYRILLIC SMALL LETTER SCHWA + '\xbb' # 0xBB -> RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + '\u0458' # 0xBC -> CYRILLIC SMALL LETTER JE + '\u04aa' # 0xBD -> CYRILLIC CAPITAL LETTER ES WITH DESCENDER + '\u04ab' # 0xBE -> CYRILLIC SMALL LETTER ES WITH DESCENDER + '\u049d' # 0xBF -> CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE + '\u0410' # 0xC0 -> CYRILLIC CAPITAL LETTER A + '\u0411' # 0xC1 -> CYRILLIC CAPITAL LETTER BE + '\u0412' # 0xC2 -> CYRILLIC CAPITAL LETTER VE + '\u0413' # 0xC3 -> CYRILLIC CAPITAL LETTER GHE + '\u0414' # 0xC4 -> CYRILLIC CAPITAL LETTER DE + '\u0415' # 0xC5 -> CYRILLIC CAPITAL LETTER IE + '\u0416' # 0xC6 -> CYRILLIC CAPITAL LETTER ZHE + '\u0417' # 0xC7 -> CYRILLIC CAPITAL LETTER ZE + '\u0418' # 0xC8 -> CYRILLIC CAPITAL LETTER I + '\u0419' # 0xC9 -> CYRILLIC CAPITAL LETTER SHORT I + '\u041a' # 0xCA -> CYRILLIC CAPITAL LETTER KA + '\u041b' # 0xCB -> CYRILLIC CAPITAL LETTER EL + '\u041c' # 0xCC -> CYRILLIC CAPITAL LETTER EM + '\u041d' # 0xCD -> CYRILLIC CAPITAL LETTER EN + '\u041e' # 0xCE -> CYRILLIC CAPITAL LETTER O + '\u041f' # 0xCF -> CYRILLIC CAPITAL LETTER PE + '\u0420' # 0xD0 -> CYRILLIC CAPITAL LETTER ER + '\u0421' # 0xD1 -> CYRILLIC CAPITAL LETTER ES + '\u0422' # 0xD2 -> CYRILLIC CAPITAL LETTER TE + '\u0423' # 0xD3 -> CYRILLIC CAPITAL LETTER U + '\u0424' # 0xD4 -> CYRILLIC CAPITAL LETTER EF + '\u0425' # 0xD5 -> CYRILLIC CAPITAL LETTER HA + '\u0426' # 0xD6 -> CYRILLIC CAPITAL LETTER TSE + '\u0427' # 0xD7 -> CYRILLIC CAPITAL LETTER CHE + '\u0428' # 0xD8 -> CYRILLIC CAPITAL LETTER SHA + '\u0429' # 0xD9 -> CYRILLIC CAPITAL LETTER SHCHA + '\u042a' # 0xDA -> CYRILLIC CAPITAL LETTER HARD SIGN + '\u042b' # 0xDB -> CYRILLIC CAPITAL LETTER YERU + '\u042c' # 0xDC -> CYRILLIC CAPITAL LETTER SOFT SIGN + '\u042d' # 0xDD -> CYRILLIC CAPITAL LETTER E + '\u042e' # 0xDE -> CYRILLIC CAPITAL LETTER YU + '\u042f' # 0xDF -> CYRILLIC CAPITAL LETTER YA + '\u0430' # 0xE0 -> CYRILLIC SMALL LETTER A + '\u0431' # 0xE1 -> CYRILLIC SMALL LETTER BE + '\u0432' # 0xE2 -> CYRILLIC SMALL LETTER VE + '\u0433' # 0xE3 -> CYRILLIC SMALL LETTER GHE + '\u0434' # 0xE4 -> CYRILLIC SMALL LETTER DE + '\u0435' # 0xE5 -> CYRILLIC SMALL LETTER IE + '\u0436' # 0xE6 -> CYRILLIC SMALL LETTER ZHE + '\u0437' # 0xE7 -> CYRILLIC SMALL LETTER ZE + '\u0438' # 0xE8 -> CYRILLIC SMALL LETTER I + '\u0439' # 0xE9 -> CYRILLIC SMALL LETTER SHORT I + '\u043a' # 0xEA -> CYRILLIC SMALL LETTER KA + '\u043b' # 0xEB -> CYRILLIC SMALL LETTER EL + '\u043c' # 0xEC -> CYRILLIC SMALL LETTER EM + '\u043d' # 0xED -> CYRILLIC SMALL LETTER EN + '\u043e' # 0xEE -> CYRILLIC SMALL LETTER O + '\u043f' # 0xEF -> CYRILLIC SMALL LETTER PE + '\u0440' # 0xF0 -> CYRILLIC SMALL LETTER ER + '\u0441' # 0xF1 -> CYRILLIC SMALL LETTER ES + '\u0442' # 0xF2 -> CYRILLIC SMALL LETTER TE + '\u0443' # 0xF3 -> CYRILLIC SMALL LETTER U + '\u0444' # 0xF4 -> CYRILLIC SMALL LETTER EF + '\u0445' # 0xF5 -> CYRILLIC SMALL LETTER HA + '\u0446' # 0xF6 -> CYRILLIC SMALL LETTER TSE + '\u0447' # 0xF7 -> CYRILLIC SMALL LETTER CHE + '\u0448' # 0xF8 -> CYRILLIC SMALL LETTER SHA + '\u0449' # 0xF9 -> CYRILLIC SMALL LETTER SHCHA + '\u044a' # 0xFA -> CYRILLIC SMALL LETTER HARD SIGN + '\u044b' # 0xFB -> CYRILLIC SMALL LETTER YERU + '\u044c' # 0xFC -> CYRILLIC SMALL LETTER SOFT SIGN + '\u044d' # 0xFD -> CYRILLIC SMALL LETTER E + '\u044e' # 0xFE -> CYRILLIC SMALL LETTER YU + '\u044f' # 0xFF -> CYRILLIC SMALL LETTER YA +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/punycode.py b/winvenv/Lib/encodings/punycode.py new file mode 100644 index 0000000..66c5101 --- /dev/null +++ b/winvenv/Lib/encodings/punycode.py @@ -0,0 +1,237 @@ +""" Codec for the Punicode encoding, as specified in RFC 3492 + +Written by Martin v. Löwis. +""" + +import codecs + +##################### Encoding ##################################### + +def segregate(str): + """3.1 Basic code point segregation""" + base = bytearray() + extended = set() + for c in str: + if ord(c) < 128: + base.append(ord(c)) + else: + extended.add(c) + extended = sorted(extended) + return bytes(base), extended + +def selective_len(str, max): + """Return the length of str, considering only characters below max.""" + res = 0 + for c in str: + if ord(c) < max: + res += 1 + return res + +def selective_find(str, char, index, pos): + """Return a pair (index, pos), indicating the next occurrence of + char in str. index is the position of the character considering + only ordinals up to and including char, and pos is the position in + the full string. index/pos is the starting position in the full + string.""" + + l = len(str) + while 1: + pos += 1 + if pos == l: + return (-1, -1) + c = str[pos] + if c == char: + return index+1, pos + elif c < char: + index += 1 + +def insertion_unsort(str, extended): + """3.2 Insertion unsort coding""" + oldchar = 0x80 + result = [] + oldindex = -1 + for c in extended: + index = pos = -1 + char = ord(c) + curlen = selective_len(str, char) + delta = (curlen+1) * (char - oldchar) + while 1: + index,pos = selective_find(str,c,index,pos) + if index == -1: + break + delta += index - oldindex + result.append(delta-1) + oldindex = index + delta = 0 + oldchar = char + + return result + +def T(j, bias): + # Punycode parameters: tmin = 1, tmax = 26, base = 36 + res = 36 * (j + 1) - bias + if res < 1: return 1 + if res > 26: return 26 + return res + +digits = b"abcdefghijklmnopqrstuvwxyz0123456789" +def generate_generalized_integer(N, bias): + """3.3 Generalized variable-length integers""" + result = bytearray() + j = 0 + while 1: + t = T(j, bias) + if N < t: + result.append(digits[N]) + return bytes(result) + result.append(digits[t + ((N - t) % (36 - t))]) + N = (N - t) // (36 - t) + j += 1 + +def adapt(delta, first, numchars): + if first: + delta //= 700 + else: + delta //= 2 + delta += delta // numchars + # ((base - tmin) * tmax) // 2 == 455 + divisions = 0 + while delta > 455: + delta = delta // 35 # base - tmin + divisions += 36 + bias = divisions + (36 * delta // (delta + 38)) + return bias + + +def generate_integers(baselen, deltas): + """3.4 Bias adaptation""" + # Punycode parameters: initial bias = 72, damp = 700, skew = 38 + result = bytearray() + bias = 72 + for points, delta in enumerate(deltas): + s = generate_generalized_integer(delta, bias) + result.extend(s) + bias = adapt(delta, points==0, baselen+points+1) + return bytes(result) + +def punycode_encode(text): + base, extended = segregate(text) + deltas = insertion_unsort(text, extended) + extended = generate_integers(len(base), deltas) + if base: + return base + b"-" + extended + return extended + +##################### Decoding ##################################### + +def decode_generalized_number(extended, extpos, bias, errors): + """3.3 Generalized variable-length integers""" + result = 0 + w = 1 + j = 0 + while 1: + try: + char = ord(extended[extpos]) + except IndexError: + if errors == "strict": + raise UnicodeError("incomplete punicode string") + return extpos + 1, None + extpos += 1 + if 0x41 <= char <= 0x5A: # A-Z + digit = char - 0x41 + elif 0x30 <= char <= 0x39: + digit = char - 22 # 0x30-26 + elif errors == "strict": + raise UnicodeError("Invalid extended code point '%s'" + % extended[extpos]) + else: + return extpos, None + t = T(j, bias) + result += digit * w + if digit < t: + return extpos, result + w = w * (36 - t) + j += 1 + + +def insertion_sort(base, extended, errors): + """3.2 Insertion unsort coding""" + char = 0x80 + pos = -1 + bias = 72 + extpos = 0 + while extpos < len(extended): + newpos, delta = decode_generalized_number(extended, extpos, + bias, errors) + if delta is None: + # There was an error in decoding. We can't continue because + # synchronization is lost. + return base + pos += delta+1 + char += pos // (len(base) + 1) + if char > 0x10FFFF: + if errors == "strict": + raise UnicodeError("Invalid character U+%x" % char) + char = ord('?') + pos = pos % (len(base) + 1) + base = base[:pos] + chr(char) + base[pos:] + bias = adapt(delta, (extpos == 0), len(base)) + extpos = newpos + return base + +def punycode_decode(text, errors): + if isinstance(text, str): + text = text.encode("ascii") + if isinstance(text, memoryview): + text = bytes(text) + pos = text.rfind(b"-") + if pos == -1: + base = "" + extended = str(text, "ascii").upper() + else: + base = str(text[:pos], "ascii", errors) + extended = str(text[pos+1:], "ascii").upper() + return insertion_sort(base, extended, errors) + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self, input, errors='strict'): + res = punycode_encode(input) + return res, len(input) + + def decode(self, input, errors='strict'): + if errors not in ('strict', 'replace', 'ignore'): + raise UnicodeError("Unsupported error handling "+errors) + res = punycode_decode(input, errors) + return res, len(input) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return punycode_encode(input) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + if self.errors not in ('strict', 'replace', 'ignore'): + raise UnicodeError("Unsupported error handling "+self.errors) + return punycode_decode(input, self.errors) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='punycode', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/quopri_codec.py b/winvenv/Lib/encodings/quopri_codec.py new file mode 100644 index 0000000..496cb76 --- /dev/null +++ b/winvenv/Lib/encodings/quopri_codec.py @@ -0,0 +1,56 @@ +"""Codec for quoted-printable encoding. + +This codec de/encodes from bytes to bytes. +""" + +import codecs +import quopri +from io import BytesIO + +def quopri_encode(input, errors='strict'): + assert errors == 'strict' + f = BytesIO(input) + g = BytesIO() + quopri.encode(f, g, quotetabs=True) + return (g.getvalue(), len(input)) + +def quopri_decode(input, errors='strict'): + assert errors == 'strict' + f = BytesIO(input) + g = BytesIO() + quopri.decode(f, g) + return (g.getvalue(), len(input)) + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return quopri_encode(input, errors) + def decode(self, input, errors='strict'): + return quopri_decode(input, errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return quopri_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return quopri_decode(input, self.errors)[0] + +class StreamWriter(Codec, codecs.StreamWriter): + charbuffertype = bytes + +class StreamReader(Codec, codecs.StreamReader): + charbuffertype = bytes + +# encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='quopri', + encode=quopri_encode, + decode=quopri_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + _is_text_encoding=False, + ) diff --git a/winvenv/Lib/encodings/raw_unicode_escape.py b/winvenv/Lib/encodings/raw_unicode_escape.py new file mode 100644 index 0000000..2b919b4 --- /dev/null +++ b/winvenv/Lib/encodings/raw_unicode_escape.py @@ -0,0 +1,45 @@ +""" Python 'raw-unicode-escape' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.raw_unicode_escape_encode + decode = codecs.raw_unicode_escape_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.raw_unicode_escape_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.raw_unicode_escape_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='raw-unicode-escape', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/rot_13.py b/winvenv/Lib/encodings/rot_13.py new file mode 100644 index 0000000..5627bfb --- /dev/null +++ b/winvenv/Lib/encodings/rot_13.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +""" Python Character Mapping Codec for ROT13. + +This codec de/encodes from str to str. + +Written by Marc-Andre Lemburg (mal@lemburg.com). +""" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return (str.translate(input, rot13_map), len(input)) + + def decode(self, input, errors='strict'): + return (str.translate(input, rot13_map), len(input)) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return str.translate(input, rot13_map) + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return str.translate(input, rot13_map) + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='rot-13', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + _is_text_encoding=False, + ) + +### Map + +rot13_map = codecs.make_identity_dict(range(256)) +rot13_map.update({ + 0x0041: 0x004e, + 0x0042: 0x004f, + 0x0043: 0x0050, + 0x0044: 0x0051, + 0x0045: 0x0052, + 0x0046: 0x0053, + 0x0047: 0x0054, + 0x0048: 0x0055, + 0x0049: 0x0056, + 0x004a: 0x0057, + 0x004b: 0x0058, + 0x004c: 0x0059, + 0x004d: 0x005a, + 0x004e: 0x0041, + 0x004f: 0x0042, + 0x0050: 0x0043, + 0x0051: 0x0044, + 0x0052: 0x0045, + 0x0053: 0x0046, + 0x0054: 0x0047, + 0x0055: 0x0048, + 0x0056: 0x0049, + 0x0057: 0x004a, + 0x0058: 0x004b, + 0x0059: 0x004c, + 0x005a: 0x004d, + 0x0061: 0x006e, + 0x0062: 0x006f, + 0x0063: 0x0070, + 0x0064: 0x0071, + 0x0065: 0x0072, + 0x0066: 0x0073, + 0x0067: 0x0074, + 0x0068: 0x0075, + 0x0069: 0x0076, + 0x006a: 0x0077, + 0x006b: 0x0078, + 0x006c: 0x0079, + 0x006d: 0x007a, + 0x006e: 0x0061, + 0x006f: 0x0062, + 0x0070: 0x0063, + 0x0071: 0x0064, + 0x0072: 0x0065, + 0x0073: 0x0066, + 0x0074: 0x0067, + 0x0075: 0x0068, + 0x0076: 0x0069, + 0x0077: 0x006a, + 0x0078: 0x006b, + 0x0079: 0x006c, + 0x007a: 0x006d, +}) + +### Filter API + +def rot13(infile, outfile): + outfile.write(codecs.encode(infile.read(), 'rot-13')) + +if __name__ == '__main__': + import sys + rot13(sys.stdin, sys.stdout) diff --git a/winvenv/Lib/encodings/shift_jis.py b/winvenv/Lib/encodings/shift_jis.py new file mode 100644 index 0000000..8338117 --- /dev/null +++ b/winvenv/Lib/encodings/shift_jis.py @@ -0,0 +1,39 @@ +# +# shift_jis.py: Python Unicode Codec for SHIFT_JIS +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('shift_jis') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='shift_jis', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/shift_jis_2004.py b/winvenv/Lib/encodings/shift_jis_2004.py new file mode 100644 index 0000000..161b1e8 --- /dev/null +++ b/winvenv/Lib/encodings/shift_jis_2004.py @@ -0,0 +1,39 @@ +# +# shift_jis_2004.py: Python Unicode Codec for SHIFT_JIS_2004 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('shift_jis_2004') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='shift_jis_2004', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/shift_jisx0213.py b/winvenv/Lib/encodings/shift_jisx0213.py new file mode 100644 index 0000000..cb653f5 --- /dev/null +++ b/winvenv/Lib/encodings/shift_jisx0213.py @@ -0,0 +1,39 @@ +# +# shift_jisx0213.py: Python Unicode Codec for SHIFT_JISX0213 +# +# Written by Hye-Shik Chang +# + +import _codecs_jp, codecs +import _multibytecodec as mbc + +codec = _codecs_jp.getcodec('shift_jisx0213') + +class Codec(codecs.Codec): + encode = codec.encode + decode = codec.decode + +class IncrementalEncoder(mbc.MultibyteIncrementalEncoder, + codecs.IncrementalEncoder): + codec = codec + +class IncrementalDecoder(mbc.MultibyteIncrementalDecoder, + codecs.IncrementalDecoder): + codec = codec + +class StreamReader(Codec, mbc.MultibyteStreamReader, codecs.StreamReader): + codec = codec + +class StreamWriter(Codec, mbc.MultibyteStreamWriter, codecs.StreamWriter): + codec = codec + +def getregentry(): + return codecs.CodecInfo( + name='shift_jisx0213', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/tis_620.py b/winvenv/Lib/encodings/tis_620.py new file mode 100644 index 0000000..e288386 --- /dev/null +++ b/winvenv/Lib/encodings/tis_620.py @@ -0,0 +1,307 @@ +""" Python Character Mapping Codec tis_620 generated from 'python-mappings/TIS-620.TXT' with gencodec.py. + +"""#" + +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + return codecs.charmap_encode(input,errors,encoding_table) + + def decode(self,input,errors='strict'): + return codecs.charmap_decode(input,errors,decoding_table) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input,self.errors,encoding_table)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input,self.errors,decoding_table)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='tis-620', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) + + +### Decoding Table + +decoding_table = ( + '\x00' # 0x00 -> NULL + '\x01' # 0x01 -> START OF HEADING + '\x02' # 0x02 -> START OF TEXT + '\x03' # 0x03 -> END OF TEXT + '\x04' # 0x04 -> END OF TRANSMISSION + '\x05' # 0x05 -> ENQUIRY + '\x06' # 0x06 -> ACKNOWLEDGE + '\x07' # 0x07 -> BELL + '\x08' # 0x08 -> BACKSPACE + '\t' # 0x09 -> HORIZONTAL TABULATION + '\n' # 0x0A -> LINE FEED + '\x0b' # 0x0B -> VERTICAL TABULATION + '\x0c' # 0x0C -> FORM FEED + '\r' # 0x0D -> CARRIAGE RETURN + '\x0e' # 0x0E -> SHIFT OUT + '\x0f' # 0x0F -> SHIFT IN + '\x10' # 0x10 -> DATA LINK ESCAPE + '\x11' # 0x11 -> DEVICE CONTROL ONE + '\x12' # 0x12 -> DEVICE CONTROL TWO + '\x13' # 0x13 -> DEVICE CONTROL THREE + '\x14' # 0x14 -> DEVICE CONTROL FOUR + '\x15' # 0x15 -> NEGATIVE ACKNOWLEDGE + '\x16' # 0x16 -> SYNCHRONOUS IDLE + '\x17' # 0x17 -> END OF TRANSMISSION BLOCK + '\x18' # 0x18 -> CANCEL + '\x19' # 0x19 -> END OF MEDIUM + '\x1a' # 0x1A -> SUBSTITUTE + '\x1b' # 0x1B -> ESCAPE + '\x1c' # 0x1C -> FILE SEPARATOR + '\x1d' # 0x1D -> GROUP SEPARATOR + '\x1e' # 0x1E -> RECORD SEPARATOR + '\x1f' # 0x1F -> UNIT SEPARATOR + ' ' # 0x20 -> SPACE + '!' # 0x21 -> EXCLAMATION MARK + '"' # 0x22 -> QUOTATION MARK + '#' # 0x23 -> NUMBER SIGN + '$' # 0x24 -> DOLLAR SIGN + '%' # 0x25 -> PERCENT SIGN + '&' # 0x26 -> AMPERSAND + "'" # 0x27 -> APOSTROPHE + '(' # 0x28 -> LEFT PARENTHESIS + ')' # 0x29 -> RIGHT PARENTHESIS + '*' # 0x2A -> ASTERISK + '+' # 0x2B -> PLUS SIGN + ',' # 0x2C -> COMMA + '-' # 0x2D -> HYPHEN-MINUS + '.' # 0x2E -> FULL STOP + '/' # 0x2F -> SOLIDUS + '0' # 0x30 -> DIGIT ZERO + '1' # 0x31 -> DIGIT ONE + '2' # 0x32 -> DIGIT TWO + '3' # 0x33 -> DIGIT THREE + '4' # 0x34 -> DIGIT FOUR + '5' # 0x35 -> DIGIT FIVE + '6' # 0x36 -> DIGIT SIX + '7' # 0x37 -> DIGIT SEVEN + '8' # 0x38 -> DIGIT EIGHT + '9' # 0x39 -> DIGIT NINE + ':' # 0x3A -> COLON + ';' # 0x3B -> SEMICOLON + '<' # 0x3C -> LESS-THAN SIGN + '=' # 0x3D -> EQUALS SIGN + '>' # 0x3E -> GREATER-THAN SIGN + '?' # 0x3F -> QUESTION MARK + '@' # 0x40 -> COMMERCIAL AT + 'A' # 0x41 -> LATIN CAPITAL LETTER A + 'B' # 0x42 -> LATIN CAPITAL LETTER B + 'C' # 0x43 -> LATIN CAPITAL LETTER C + 'D' # 0x44 -> LATIN CAPITAL LETTER D + 'E' # 0x45 -> LATIN CAPITAL LETTER E + 'F' # 0x46 -> LATIN CAPITAL LETTER F + 'G' # 0x47 -> LATIN CAPITAL LETTER G + 'H' # 0x48 -> LATIN CAPITAL LETTER H + 'I' # 0x49 -> LATIN CAPITAL LETTER I + 'J' # 0x4A -> LATIN CAPITAL LETTER J + 'K' # 0x4B -> LATIN CAPITAL LETTER K + 'L' # 0x4C -> LATIN CAPITAL LETTER L + 'M' # 0x4D -> LATIN CAPITAL LETTER M + 'N' # 0x4E -> LATIN CAPITAL LETTER N + 'O' # 0x4F -> LATIN CAPITAL LETTER O + 'P' # 0x50 -> LATIN CAPITAL LETTER P + 'Q' # 0x51 -> LATIN CAPITAL LETTER Q + 'R' # 0x52 -> LATIN CAPITAL LETTER R + 'S' # 0x53 -> LATIN CAPITAL LETTER S + 'T' # 0x54 -> LATIN CAPITAL LETTER T + 'U' # 0x55 -> LATIN CAPITAL LETTER U + 'V' # 0x56 -> LATIN CAPITAL LETTER V + 'W' # 0x57 -> LATIN CAPITAL LETTER W + 'X' # 0x58 -> LATIN CAPITAL LETTER X + 'Y' # 0x59 -> LATIN CAPITAL LETTER Y + 'Z' # 0x5A -> LATIN CAPITAL LETTER Z + '[' # 0x5B -> LEFT SQUARE BRACKET + '\\' # 0x5C -> REVERSE SOLIDUS + ']' # 0x5D -> RIGHT SQUARE BRACKET + '^' # 0x5E -> CIRCUMFLEX ACCENT + '_' # 0x5F -> LOW LINE + '`' # 0x60 -> GRAVE ACCENT + 'a' # 0x61 -> LATIN SMALL LETTER A + 'b' # 0x62 -> LATIN SMALL LETTER B + 'c' # 0x63 -> LATIN SMALL LETTER C + 'd' # 0x64 -> LATIN SMALL LETTER D + 'e' # 0x65 -> LATIN SMALL LETTER E + 'f' # 0x66 -> LATIN SMALL LETTER F + 'g' # 0x67 -> LATIN SMALL LETTER G + 'h' # 0x68 -> LATIN SMALL LETTER H + 'i' # 0x69 -> LATIN SMALL LETTER I + 'j' # 0x6A -> LATIN SMALL LETTER J + 'k' # 0x6B -> LATIN SMALL LETTER K + 'l' # 0x6C -> LATIN SMALL LETTER L + 'm' # 0x6D -> LATIN SMALL LETTER M + 'n' # 0x6E -> LATIN SMALL LETTER N + 'o' # 0x6F -> LATIN SMALL LETTER O + 'p' # 0x70 -> LATIN SMALL LETTER P + 'q' # 0x71 -> LATIN SMALL LETTER Q + 'r' # 0x72 -> LATIN SMALL LETTER R + 's' # 0x73 -> LATIN SMALL LETTER S + 't' # 0x74 -> LATIN SMALL LETTER T + 'u' # 0x75 -> LATIN SMALL LETTER U + 'v' # 0x76 -> LATIN SMALL LETTER V + 'w' # 0x77 -> LATIN SMALL LETTER W + 'x' # 0x78 -> LATIN SMALL LETTER X + 'y' # 0x79 -> LATIN SMALL LETTER Y + 'z' # 0x7A -> LATIN SMALL LETTER Z + '{' # 0x7B -> LEFT CURLY BRACKET + '|' # 0x7C -> VERTICAL LINE + '}' # 0x7D -> RIGHT CURLY BRACKET + '~' # 0x7E -> TILDE + '\x7f' # 0x7F -> DELETE + '\x80' # 0x80 -> + '\x81' # 0x81 -> + '\x82' # 0x82 -> + '\x83' # 0x83 -> + '\x84' # 0x84 -> + '\x85' # 0x85 -> + '\x86' # 0x86 -> + '\x87' # 0x87 -> + '\x88' # 0x88 -> + '\x89' # 0x89 -> + '\x8a' # 0x8A -> + '\x8b' # 0x8B -> + '\x8c' # 0x8C -> + '\x8d' # 0x8D -> + '\x8e' # 0x8E -> + '\x8f' # 0x8F -> + '\x90' # 0x90 -> + '\x91' # 0x91 -> + '\x92' # 0x92 -> + '\x93' # 0x93 -> + '\x94' # 0x94 -> + '\x95' # 0x95 -> + '\x96' # 0x96 -> + '\x97' # 0x97 -> + '\x98' # 0x98 -> + '\x99' # 0x99 -> + '\x9a' # 0x9A -> + '\x9b' # 0x9B -> + '\x9c' # 0x9C -> + '\x9d' # 0x9D -> + '\x9e' # 0x9E -> + '\x9f' # 0x9F -> + '\ufffe' + '\u0e01' # 0xA1 -> THAI CHARACTER KO KAI + '\u0e02' # 0xA2 -> THAI CHARACTER KHO KHAI + '\u0e03' # 0xA3 -> THAI CHARACTER KHO KHUAT + '\u0e04' # 0xA4 -> THAI CHARACTER KHO KHWAI + '\u0e05' # 0xA5 -> THAI CHARACTER KHO KHON + '\u0e06' # 0xA6 -> THAI CHARACTER KHO RAKHANG + '\u0e07' # 0xA7 -> THAI CHARACTER NGO NGU + '\u0e08' # 0xA8 -> THAI CHARACTER CHO CHAN + '\u0e09' # 0xA9 -> THAI CHARACTER CHO CHING + '\u0e0a' # 0xAA -> THAI CHARACTER CHO CHANG + '\u0e0b' # 0xAB -> THAI CHARACTER SO SO + '\u0e0c' # 0xAC -> THAI CHARACTER CHO CHOE + '\u0e0d' # 0xAD -> THAI CHARACTER YO YING + '\u0e0e' # 0xAE -> THAI CHARACTER DO CHADA + '\u0e0f' # 0xAF -> THAI CHARACTER TO PATAK + '\u0e10' # 0xB0 -> THAI CHARACTER THO THAN + '\u0e11' # 0xB1 -> THAI CHARACTER THO NANGMONTHO + '\u0e12' # 0xB2 -> THAI CHARACTER THO PHUTHAO + '\u0e13' # 0xB3 -> THAI CHARACTER NO NEN + '\u0e14' # 0xB4 -> THAI CHARACTER DO DEK + '\u0e15' # 0xB5 -> THAI CHARACTER TO TAO + '\u0e16' # 0xB6 -> THAI CHARACTER THO THUNG + '\u0e17' # 0xB7 -> THAI CHARACTER THO THAHAN + '\u0e18' # 0xB8 -> THAI CHARACTER THO THONG + '\u0e19' # 0xB9 -> THAI CHARACTER NO NU + '\u0e1a' # 0xBA -> THAI CHARACTER BO BAIMAI + '\u0e1b' # 0xBB -> THAI CHARACTER PO PLA + '\u0e1c' # 0xBC -> THAI CHARACTER PHO PHUNG + '\u0e1d' # 0xBD -> THAI CHARACTER FO FA + '\u0e1e' # 0xBE -> THAI CHARACTER PHO PHAN + '\u0e1f' # 0xBF -> THAI CHARACTER FO FAN + '\u0e20' # 0xC0 -> THAI CHARACTER PHO SAMPHAO + '\u0e21' # 0xC1 -> THAI CHARACTER MO MA + '\u0e22' # 0xC2 -> THAI CHARACTER YO YAK + '\u0e23' # 0xC3 -> THAI CHARACTER RO RUA + '\u0e24' # 0xC4 -> THAI CHARACTER RU + '\u0e25' # 0xC5 -> THAI CHARACTER LO LING + '\u0e26' # 0xC6 -> THAI CHARACTER LU + '\u0e27' # 0xC7 -> THAI CHARACTER WO WAEN + '\u0e28' # 0xC8 -> THAI CHARACTER SO SALA + '\u0e29' # 0xC9 -> THAI CHARACTER SO RUSI + '\u0e2a' # 0xCA -> THAI CHARACTER SO SUA + '\u0e2b' # 0xCB -> THAI CHARACTER HO HIP + '\u0e2c' # 0xCC -> THAI CHARACTER LO CHULA + '\u0e2d' # 0xCD -> THAI CHARACTER O ANG + '\u0e2e' # 0xCE -> THAI CHARACTER HO NOKHUK + '\u0e2f' # 0xCF -> THAI CHARACTER PAIYANNOI + '\u0e30' # 0xD0 -> THAI CHARACTER SARA A + '\u0e31' # 0xD1 -> THAI CHARACTER MAI HAN-AKAT + '\u0e32' # 0xD2 -> THAI CHARACTER SARA AA + '\u0e33' # 0xD3 -> THAI CHARACTER SARA AM + '\u0e34' # 0xD4 -> THAI CHARACTER SARA I + '\u0e35' # 0xD5 -> THAI CHARACTER SARA II + '\u0e36' # 0xD6 -> THAI CHARACTER SARA UE + '\u0e37' # 0xD7 -> THAI CHARACTER SARA UEE + '\u0e38' # 0xD8 -> THAI CHARACTER SARA U + '\u0e39' # 0xD9 -> THAI CHARACTER SARA UU + '\u0e3a' # 0xDA -> THAI CHARACTER PHINTHU + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' + '\u0e3f' # 0xDF -> THAI CURRENCY SYMBOL BAHT + '\u0e40' # 0xE0 -> THAI CHARACTER SARA E + '\u0e41' # 0xE1 -> THAI CHARACTER SARA AE + '\u0e42' # 0xE2 -> THAI CHARACTER SARA O + '\u0e43' # 0xE3 -> THAI CHARACTER SARA AI MAIMUAN + '\u0e44' # 0xE4 -> THAI CHARACTER SARA AI MAIMALAI + '\u0e45' # 0xE5 -> THAI CHARACTER LAKKHANGYAO + '\u0e46' # 0xE6 -> THAI CHARACTER MAIYAMOK + '\u0e47' # 0xE7 -> THAI CHARACTER MAITAIKHU + '\u0e48' # 0xE8 -> THAI CHARACTER MAI EK + '\u0e49' # 0xE9 -> THAI CHARACTER MAI THO + '\u0e4a' # 0xEA -> THAI CHARACTER MAI TRI + '\u0e4b' # 0xEB -> THAI CHARACTER MAI CHATTAWA + '\u0e4c' # 0xEC -> THAI CHARACTER THANTHAKHAT + '\u0e4d' # 0xED -> THAI CHARACTER NIKHAHIT + '\u0e4e' # 0xEE -> THAI CHARACTER YAMAKKAN + '\u0e4f' # 0xEF -> THAI CHARACTER FONGMAN + '\u0e50' # 0xF0 -> THAI DIGIT ZERO + '\u0e51' # 0xF1 -> THAI DIGIT ONE + '\u0e52' # 0xF2 -> THAI DIGIT TWO + '\u0e53' # 0xF3 -> THAI DIGIT THREE + '\u0e54' # 0xF4 -> THAI DIGIT FOUR + '\u0e55' # 0xF5 -> THAI DIGIT FIVE + '\u0e56' # 0xF6 -> THAI DIGIT SIX + '\u0e57' # 0xF7 -> THAI DIGIT SEVEN + '\u0e58' # 0xF8 -> THAI DIGIT EIGHT + '\u0e59' # 0xF9 -> THAI DIGIT NINE + '\u0e5a' # 0xFA -> THAI CHARACTER ANGKHANKHU + '\u0e5b' # 0xFB -> THAI CHARACTER KHOMUT + '\ufffe' + '\ufffe' + '\ufffe' + '\ufffe' +) + +### Encoding table +encoding_table=codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/encodings/undefined.py b/winvenv/Lib/encodings/undefined.py new file mode 100644 index 0000000..4690288 --- /dev/null +++ b/winvenv/Lib/encodings/undefined.py @@ -0,0 +1,49 @@ +""" Python 'undefined' Codec + + This codec will always raise a ValueError exception when being + used. It is intended for use by the site.py file to switch off + automatic string to Unicode coercion. + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self,input,errors='strict'): + raise UnicodeError("undefined encoding") + + def decode(self,input,errors='strict'): + raise UnicodeError("undefined encoding") + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + raise UnicodeError("undefined encoding") + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + raise UnicodeError("undefined encoding") + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='undefined', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/unicode_escape.py b/winvenv/Lib/encodings/unicode_escape.py new file mode 100644 index 0000000..817f932 --- /dev/null +++ b/winvenv/Lib/encodings/unicode_escape.py @@ -0,0 +1,45 @@ +""" Python 'unicode-escape' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.unicode_escape_encode + decode = codecs.unicode_escape_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.unicode_escape_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.unicode_escape_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='unicode-escape', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/unicode_internal.py b/winvenv/Lib/encodings/unicode_internal.py new file mode 100644 index 0000000..df3e775 --- /dev/null +++ b/winvenv/Lib/encodings/unicode_internal.py @@ -0,0 +1,45 @@ +""" Python 'unicode-internal' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +class Codec(codecs.Codec): + + # Note: Binding these as C functions will result in the class not + # converting them to methods. This is intended. + encode = codecs.unicode_internal_encode + decode = codecs.unicode_internal_decode + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.unicode_internal_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.unicode_internal_decode(input, self.errors)[0] + +class StreamWriter(Codec,codecs.StreamWriter): + pass + +class StreamReader(Codec,codecs.StreamReader): + pass + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='unicode-internal', + encode=Codec.encode, + decode=Codec.decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/encodings/utf_16.py b/winvenv/Lib/encodings/utf_16.py new file mode 100644 index 0000000..c612482 --- /dev/null +++ b/winvenv/Lib/encodings/utf_16.py @@ -0,0 +1,155 @@ +""" Python 'utf-16' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs, sys + +### Codec APIs + +encode = codecs.utf_16_encode + +def decode(input, errors='strict'): + return codecs.utf_16_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict'): + codecs.IncrementalEncoder.__init__(self, errors) + self.encoder = None + + def encode(self, input, final=False): + if self.encoder is None: + result = codecs.utf_16_encode(input, self.errors)[0] + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + return result + return self.encoder(input, self.errors)[0] + + def reset(self): + codecs.IncrementalEncoder.reset(self) + self.encoder = None + + def getstate(self): + # state info we return to the caller: + # 0: stream is in natural order for this platform + # 2: endianness hasn't been determined yet + # (we're never writing in unnatural order) + return (2 if self.encoder is None else 0) + + def setstate(self, state): + if state: + self.encoder = None + else: + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def __init__(self, errors='strict'): + codecs.BufferedIncrementalDecoder.__init__(self, errors) + self.decoder = None + + def _buffer_decode(self, input, errors, final): + if self.decoder is None: + (output, consumed, byteorder) = \ + codecs.utf_16_ex_decode(input, errors, 0, final) + if byteorder == -1: + self.decoder = codecs.utf_16_le_decode + elif byteorder == 1: + self.decoder = codecs.utf_16_be_decode + elif consumed >= 2: + raise UnicodeError("UTF-16 stream does not start with BOM") + return (output, consumed) + return self.decoder(input, self.errors, final) + + def reset(self): + codecs.BufferedIncrementalDecoder.reset(self) + self.decoder = None + + def getstate(self): + # additional state info from the base class must be None here, + # as it isn't passed along to the caller + state = codecs.BufferedIncrementalDecoder.getstate(self)[0] + # additional state info we pass to the caller: + # 0: stream is in natural order for this platform + # 1: stream is in unnatural order + # 2: endianness hasn't been determined yet + if self.decoder is None: + return (state, 2) + addstate = int((sys.byteorder == "big") != + (self.decoder is codecs.utf_16_be_decode)) + return (state, addstate) + + def setstate(self, state): + # state[1] will be ignored by BufferedIncrementalDecoder.setstate() + codecs.BufferedIncrementalDecoder.setstate(self, state) + state = state[1] + if state == 0: + self.decoder = (codecs.utf_16_be_decode + if sys.byteorder == "big" + else codecs.utf_16_le_decode) + elif state == 1: + self.decoder = (codecs.utf_16_le_decode + if sys.byteorder == "big" + else codecs.utf_16_be_decode) + else: + self.decoder = None + +class StreamWriter(codecs.StreamWriter): + def __init__(self, stream, errors='strict'): + codecs.StreamWriter.__init__(self, stream, errors) + self.encoder = None + + def reset(self): + codecs.StreamWriter.reset(self) + self.encoder = None + + def encode(self, input, errors='strict'): + if self.encoder is None: + result = codecs.utf_16_encode(input, errors) + if sys.byteorder == 'little': + self.encoder = codecs.utf_16_le_encode + else: + self.encoder = codecs.utf_16_be_encode + return result + else: + return self.encoder(input, errors) + +class StreamReader(codecs.StreamReader): + + def reset(self): + codecs.StreamReader.reset(self) + try: + del self.decode + except AttributeError: + pass + + def decode(self, input, errors='strict'): + (object, consumed, byteorder) = \ + codecs.utf_16_ex_decode(input, errors, 0, False) + if byteorder == -1: + self.decode = codecs.utf_16_le_decode + elif byteorder == 1: + self.decode = codecs.utf_16_be_decode + elif consumed>=2: + raise UnicodeError("UTF-16 stream does not start with BOM") + return (object, consumed) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-16', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_16_be.py b/winvenv/Lib/encodings/utf_16_be.py new file mode 100644 index 0000000..86b458e --- /dev/null +++ b/winvenv/Lib/encodings/utf_16_be.py @@ -0,0 +1,42 @@ +""" Python 'utf-16-be' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +encode = codecs.utf_16_be_encode + +def decode(input, errors='strict'): + return codecs.utf_16_be_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_16_be_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_16_be_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_16_be_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_16_be_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-16-be', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_16_le.py b/winvenv/Lib/encodings/utf_16_le.py new file mode 100644 index 0000000..ec45414 --- /dev/null +++ b/winvenv/Lib/encodings/utf_16_le.py @@ -0,0 +1,42 @@ +""" Python 'utf-16-le' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +encode = codecs.utf_16_le_encode + +def decode(input, errors='strict'): + return codecs.utf_16_le_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_16_le_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_16_le_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_16_le_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_16_le_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-16-le', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_32.py b/winvenv/Lib/encodings/utf_32.py new file mode 100644 index 0000000..cdf84d1 --- /dev/null +++ b/winvenv/Lib/encodings/utf_32.py @@ -0,0 +1,150 @@ +""" +Python 'utf-32' Codec +""" +import codecs, sys + +### Codec APIs + +encode = codecs.utf_32_encode + +def decode(input, errors='strict'): + return codecs.utf_32_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict'): + codecs.IncrementalEncoder.__init__(self, errors) + self.encoder = None + + def encode(self, input, final=False): + if self.encoder is None: + result = codecs.utf_32_encode(input, self.errors)[0] + if sys.byteorder == 'little': + self.encoder = codecs.utf_32_le_encode + else: + self.encoder = codecs.utf_32_be_encode + return result + return self.encoder(input, self.errors)[0] + + def reset(self): + codecs.IncrementalEncoder.reset(self) + self.encoder = None + + def getstate(self): + # state info we return to the caller: + # 0: stream is in natural order for this platform + # 2: endianness hasn't been determined yet + # (we're never writing in unnatural order) + return (2 if self.encoder is None else 0) + + def setstate(self, state): + if state: + self.encoder = None + else: + if sys.byteorder == 'little': + self.encoder = codecs.utf_32_le_encode + else: + self.encoder = codecs.utf_32_be_encode + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def __init__(self, errors='strict'): + codecs.BufferedIncrementalDecoder.__init__(self, errors) + self.decoder = None + + def _buffer_decode(self, input, errors, final): + if self.decoder is None: + (output, consumed, byteorder) = \ + codecs.utf_32_ex_decode(input, errors, 0, final) + if byteorder == -1: + self.decoder = codecs.utf_32_le_decode + elif byteorder == 1: + self.decoder = codecs.utf_32_be_decode + elif consumed >= 4: + raise UnicodeError("UTF-32 stream does not start with BOM") + return (output, consumed) + return self.decoder(input, self.errors, final) + + def reset(self): + codecs.BufferedIncrementalDecoder.reset(self) + self.decoder = None + + def getstate(self): + # additional state info from the base class must be None here, + # as it isn't passed along to the caller + state = codecs.BufferedIncrementalDecoder.getstate(self)[0] + # additional state info we pass to the caller: + # 0: stream is in natural order for this platform + # 1: stream is in unnatural order + # 2: endianness hasn't been determined yet + if self.decoder is None: + return (state, 2) + addstate = int((sys.byteorder == "big") != + (self.decoder is codecs.utf_32_be_decode)) + return (state, addstate) + + def setstate(self, state): + # state[1] will be ignored by BufferedIncrementalDecoder.setstate() + codecs.BufferedIncrementalDecoder.setstate(self, state) + state = state[1] + if state == 0: + self.decoder = (codecs.utf_32_be_decode + if sys.byteorder == "big" + else codecs.utf_32_le_decode) + elif state == 1: + self.decoder = (codecs.utf_32_le_decode + if sys.byteorder == "big" + else codecs.utf_32_be_decode) + else: + self.decoder = None + +class StreamWriter(codecs.StreamWriter): + def __init__(self, stream, errors='strict'): + self.encoder = None + codecs.StreamWriter.__init__(self, stream, errors) + + def reset(self): + codecs.StreamWriter.reset(self) + self.encoder = None + + def encode(self, input, errors='strict'): + if self.encoder is None: + result = codecs.utf_32_encode(input, errors) + if sys.byteorder == 'little': + self.encoder = codecs.utf_32_le_encode + else: + self.encoder = codecs.utf_32_be_encode + return result + else: + return self.encoder(input, errors) + +class StreamReader(codecs.StreamReader): + + def reset(self): + codecs.StreamReader.reset(self) + try: + del self.decode + except AttributeError: + pass + + def decode(self, input, errors='strict'): + (object, consumed, byteorder) = \ + codecs.utf_32_ex_decode(input, errors, 0, False) + if byteorder == -1: + self.decode = codecs.utf_32_le_decode + elif byteorder == 1: + self.decode = codecs.utf_32_be_decode + elif consumed>=4: + raise UnicodeError("UTF-32 stream does not start with BOM") + return (object, consumed) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-32', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_32_be.py b/winvenv/Lib/encodings/utf_32_be.py new file mode 100644 index 0000000..fe272b5 --- /dev/null +++ b/winvenv/Lib/encodings/utf_32_be.py @@ -0,0 +1,37 @@ +""" +Python 'utf-32-be' Codec +""" +import codecs + +### Codec APIs + +encode = codecs.utf_32_be_encode + +def decode(input, errors='strict'): + return codecs.utf_32_be_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_32_be_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_32_be_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_32_be_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_32_be_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-32-be', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_32_le.py b/winvenv/Lib/encodings/utf_32_le.py new file mode 100644 index 0000000..9e48210 --- /dev/null +++ b/winvenv/Lib/encodings/utf_32_le.py @@ -0,0 +1,37 @@ +""" +Python 'utf-32-le' Codec +""" +import codecs + +### Codec APIs + +encode = codecs.utf_32_le_encode + +def decode(input, errors='strict'): + return codecs.utf_32_le_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_32_le_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_32_le_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_32_le_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_32_le_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-32-le', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_7.py b/winvenv/Lib/encodings/utf_7.py new file mode 100644 index 0000000..8e0567f --- /dev/null +++ b/winvenv/Lib/encodings/utf_7.py @@ -0,0 +1,38 @@ +""" Python 'utf-7' Codec + +Written by Brian Quinlan (brian@sweetapp.com). +""" +import codecs + +### Codec APIs + +encode = codecs.utf_7_encode + +def decode(input, errors='strict'): + return codecs.utf_7_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_7_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_7_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_7_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_7_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-7', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_8.py b/winvenv/Lib/encodings/utf_8.py new file mode 100644 index 0000000..1bf6336 --- /dev/null +++ b/winvenv/Lib/encodings/utf_8.py @@ -0,0 +1,42 @@ +""" Python 'utf-8' Codec + + +Written by Marc-Andre Lemburg (mal@lemburg.com). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +""" +import codecs + +### Codec APIs + +encode = codecs.utf_8_encode + +def decode(input, errors='strict'): + return codecs.utf_8_decode(input, errors, True) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.utf_8_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + _buffer_decode = codecs.utf_8_decode + +class StreamWriter(codecs.StreamWriter): + encode = codecs.utf_8_encode + +class StreamReader(codecs.StreamReader): + decode = codecs.utf_8_decode + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-8', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/utf_8_sig.py b/winvenv/Lib/encodings/utf_8_sig.py new file mode 100644 index 0000000..1bb4792 --- /dev/null +++ b/winvenv/Lib/encodings/utf_8_sig.py @@ -0,0 +1,130 @@ +""" Python 'utf-8-sig' Codec +This work similar to UTF-8 with the following changes: + +* On encoding/writing a UTF-8 encoded BOM will be prepended/written as the + first three bytes. + +* On decoding/reading if the first three bytes are a UTF-8 encoded BOM, these + bytes will be skipped. +""" +import codecs + +### Codec APIs + +def encode(input, errors='strict'): + return (codecs.BOM_UTF8 + codecs.utf_8_encode(input, errors)[0], + len(input)) + +def decode(input, errors='strict'): + prefix = 0 + if input[:3] == codecs.BOM_UTF8: + input = input[3:] + prefix = 3 + (output, consumed) = codecs.utf_8_decode(input, errors, True) + return (output, consumed+prefix) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict'): + codecs.IncrementalEncoder.__init__(self, errors) + self.first = 1 + + def encode(self, input, final=False): + if self.first: + self.first = 0 + return codecs.BOM_UTF8 + \ + codecs.utf_8_encode(input, self.errors)[0] + else: + return codecs.utf_8_encode(input, self.errors)[0] + + def reset(self): + codecs.IncrementalEncoder.reset(self) + self.first = 1 + + def getstate(self): + return self.first + + def setstate(self, state): + self.first = state + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def __init__(self, errors='strict'): + codecs.BufferedIncrementalDecoder.__init__(self, errors) + self.first = 1 + + def _buffer_decode(self, input, errors, final): + if self.first: + if len(input) < 3: + if codecs.BOM_UTF8.startswith(input): + # not enough data to decide if this really is a BOM + # => try again on the next call + return ("", 0) + else: + self.first = 0 + else: + self.first = 0 + if input[:3] == codecs.BOM_UTF8: + (output, consumed) = \ + codecs.utf_8_decode(input[3:], errors, final) + return (output, consumed+3) + return codecs.utf_8_decode(input, errors, final) + + def reset(self): + codecs.BufferedIncrementalDecoder.reset(self) + self.first = 1 + + def getstate(self): + state = codecs.BufferedIncrementalDecoder.getstate(self) + # state[1] must be 0 here, as it isn't passed along to the caller + return (state[0], self.first) + + def setstate(self, state): + # state[1] will be ignored by BufferedIncrementalDecoder.setstate() + codecs.BufferedIncrementalDecoder.setstate(self, state) + self.first = state[1] + +class StreamWriter(codecs.StreamWriter): + def reset(self): + codecs.StreamWriter.reset(self) + try: + del self.encode + except AttributeError: + pass + + def encode(self, input, errors='strict'): + self.encode = codecs.utf_8_encode + return encode(input, errors) + +class StreamReader(codecs.StreamReader): + def reset(self): + codecs.StreamReader.reset(self) + try: + del self.decode + except AttributeError: + pass + + def decode(self, input, errors='strict'): + if len(input) < 3: + if codecs.BOM_UTF8.startswith(input): + # not enough data to decide if this is a BOM + # => try again on the next call + return ("", 0) + elif input[:3] == codecs.BOM_UTF8: + self.decode = codecs.utf_8_decode + (output, consumed) = codecs.utf_8_decode(input[3:],errors) + return (output, consumed+3) + # (else) no BOM present + self.decode = codecs.utf_8_decode + return codecs.utf_8_decode(input, errors) + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='utf-8-sig', + encode=encode, + decode=decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + ) diff --git a/winvenv/Lib/encodings/uu_codec.py b/winvenv/Lib/encodings/uu_codec.py new file mode 100644 index 0000000..2a5728f --- /dev/null +++ b/winvenv/Lib/encodings/uu_codec.py @@ -0,0 +1,99 @@ +"""Python 'uu_codec' Codec - UU content transfer encoding. + +This codec de/encodes from bytes to bytes. + +Written by Marc-Andre Lemburg (mal@lemburg.com). Some details were +adapted from uu.py which was written by Lance Ellinghouse and +modified by Jack Jansen and Fredrik Lundh. +""" + +import codecs +import binascii +from io import BytesIO + +### Codec APIs + +def uu_encode(input, errors='strict', filename='', mode=0o666): + assert errors == 'strict' + infile = BytesIO(input) + outfile = BytesIO() + read = infile.read + write = outfile.write + + # Encode + write(('begin %o %s\n' % (mode & 0o777, filename)).encode('ascii')) + chunk = read(45) + while chunk: + write(binascii.b2a_uu(chunk)) + chunk = read(45) + write(b' \nend\n') + + return (outfile.getvalue(), len(input)) + +def uu_decode(input, errors='strict'): + assert errors == 'strict' + infile = BytesIO(input) + outfile = BytesIO() + readline = infile.readline + write = outfile.write + + # Find start of encoded data + while 1: + s = readline() + if not s: + raise ValueError('Missing "begin" line in input data') + if s[:5] == b'begin': + break + + # Decode + while True: + s = readline() + if not s or s == b'end\n': + break + try: + data = binascii.a2b_uu(s) + except binascii.Error as v: + # Workaround for broken uuencoders by /Fredrik Lundh + nbytes = (((s[0]-32) & 63) * 4 + 5) // 3 + data = binascii.a2b_uu(s[:nbytes]) + #sys.stderr.write("Warning: %s\n" % str(v)) + write(data) + if not s: + raise ValueError('Truncated input data') + + return (outfile.getvalue(), len(input)) + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return uu_encode(input, errors) + + def decode(self, input, errors='strict'): + return uu_decode(input, errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return uu_encode(input, self.errors)[0] + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return uu_decode(input, self.errors)[0] + +class StreamWriter(Codec, codecs.StreamWriter): + charbuffertype = bytes + +class StreamReader(Codec, codecs.StreamReader): + charbuffertype = bytes + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='uu', + encode=uu_encode, + decode=uu_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + _is_text_encoding=False, + ) diff --git a/winvenv/Lib/encodings/zlib_codec.py b/winvenv/Lib/encodings/zlib_codec.py new file mode 100644 index 0000000..95908a4 --- /dev/null +++ b/winvenv/Lib/encodings/zlib_codec.py @@ -0,0 +1,77 @@ +"""Python 'zlib_codec' Codec - zlib compression encoding. + +This codec de/encodes from bytes to bytes. + +Written by Marc-Andre Lemburg (mal@lemburg.com). +""" + +import codecs +import zlib # this codec needs the optional zlib module ! + +### Codec APIs + +def zlib_encode(input, errors='strict'): + assert errors == 'strict' + return (zlib.compress(input), len(input)) + +def zlib_decode(input, errors='strict'): + assert errors == 'strict' + return (zlib.decompress(input), len(input)) + +class Codec(codecs.Codec): + def encode(self, input, errors='strict'): + return zlib_encode(input, errors) + def decode(self, input, errors='strict'): + return zlib_decode(input, errors) + +class IncrementalEncoder(codecs.IncrementalEncoder): + def __init__(self, errors='strict'): + assert errors == 'strict' + self.errors = errors + self.compressobj = zlib.compressobj() + + def encode(self, input, final=False): + if final: + c = self.compressobj.compress(input) + return c + self.compressobj.flush() + else: + return self.compressobj.compress(input) + + def reset(self): + self.compressobj = zlib.compressobj() + +class IncrementalDecoder(codecs.IncrementalDecoder): + def __init__(self, errors='strict'): + assert errors == 'strict' + self.errors = errors + self.decompressobj = zlib.decompressobj() + + def decode(self, input, final=False): + if final: + c = self.decompressobj.decompress(input) + return c + self.decompressobj.flush() + else: + return self.decompressobj.decompress(input) + + def reset(self): + self.decompressobj = zlib.decompressobj() + +class StreamWriter(Codec, codecs.StreamWriter): + charbuffertype = bytes + +class StreamReader(Codec, codecs.StreamReader): + charbuffertype = bytes + +### encodings module API + +def getregentry(): + return codecs.CodecInfo( + name='zlib', + encode=zlib_encode, + decode=zlib_decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, + _is_text_encoding=False, + ) diff --git a/winvenv/Lib/enum.py b/winvenv/Lib/enum.py new file mode 100644 index 0000000..87f3691 --- /dev/null +++ b/winvenv/Lib/enum.py @@ -0,0 +1,889 @@ +import sys +from types import MappingProxyType, DynamicClassAttribute + +# try _collections first to reduce startup cost +try: + from _collections import OrderedDict +except ImportError: + from collections import OrderedDict + + +__all__ = [ + 'EnumMeta', + 'Enum', 'IntEnum', 'Flag', 'IntFlag', + 'auto', 'unique', + ] + + +def _is_descriptor(obj): + """Returns True if obj is a descriptor, False otherwise.""" + return ( + hasattr(obj, '__get__') or + hasattr(obj, '__set__') or + hasattr(obj, '__delete__')) + + +def _is_dunder(name): + """Returns True if a __dunder__ name, False otherwise.""" + return (name[:2] == name[-2:] == '__' and + name[2:3] != '_' and + name[-3:-2] != '_' and + len(name) > 4) + + +def _is_sunder(name): + """Returns True if a _sunder_ name, False otherwise.""" + return (name[0] == name[-1] == '_' and + name[1:2] != '_' and + name[-2:-1] != '_' and + len(name) > 2) + +def _make_class_unpicklable(cls): + """Make the given class un-picklable.""" + def _break_on_call_reduce(self, proto): + raise TypeError('%r cannot be pickled' % self) + cls.__reduce_ex__ = _break_on_call_reduce + cls.__module__ = '' + +_auto_null = object() +class auto: + """ + Instances are replaced with an appropriate value in Enum class suites. + """ + value = _auto_null + + +class _EnumDict(dict): + """Track enum member order and ensure member names are not reused. + + EnumMeta will use the names found in self._member_names as the + enumeration member names. + + """ + def __init__(self): + super().__init__() + self._member_names = [] + self._last_values = [] + self._ignore = [] + + def __setitem__(self, key, value): + """Changes anything not dundered or not a descriptor. + + If an enum member name is used twice, an error is raised; duplicate + values are not checked for. + + Single underscore (sunder) names are reserved. + + """ + if _is_sunder(key): + if key not in ( + '_order_', '_create_pseudo_member_', + '_generate_next_value_', '_missing_', '_ignore_', + ): + raise ValueError('_names_ are reserved for future Enum use') + if key == '_generate_next_value_': + setattr(self, '_generate_next_value', value) + elif key == '_ignore_': + if isinstance(value, str): + value = value.replace(',',' ').split() + else: + value = list(value) + self._ignore = value + already = set(value) & set(self._member_names) + if already: + raise ValueError('_ignore_ cannot specify already set names: %r' % (already, )) + elif _is_dunder(key): + if key == '__order__': + key = '_order_' + elif key in self._member_names: + # descriptor overwriting an enum? + raise TypeError('Attempted to reuse key: %r' % key) + elif key in self._ignore: + pass + elif not _is_descriptor(value): + if key in self: + # enum overwriting a descriptor? + raise TypeError('%r already defined as: %r' % (key, self[key])) + if isinstance(value, auto): + if value.value == _auto_null: + value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:]) + value = value.value + self._member_names.append(key) + self._last_values.append(value) + super().__setitem__(key, value) + + +# Dummy value for Enum as EnumMeta explicitly checks for it, but of course +# until EnumMeta finishes running the first time the Enum class doesn't exist. +# This is also why there are checks in EnumMeta like `if Enum is not None` +Enum = None + + +class EnumMeta(type): + """Metaclass for Enum""" + @classmethod + def __prepare__(metacls, cls, bases): + # create the namespace dict + enum_dict = _EnumDict() + # inherit previous flags and _generate_next_value_ function + member_type, first_enum = metacls._get_mixins_(bases) + if first_enum is not None: + enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None) + return enum_dict + + def __new__(metacls, cls, bases, classdict): + # an Enum class is final once enumeration items have been defined; it + # cannot be mixed with other types (int, float, etc.) if it has an + # inherited __new__ unless a new __new__ is defined (or the resulting + # class will fail). + # + # remove any keys listed in _ignore_ + classdict.setdefault('_ignore_', []).append('_ignore_') + ignore = classdict['_ignore_'] + for key in ignore: + classdict.pop(key, None) + member_type, first_enum = metacls._get_mixins_(bases) + __new__, save_new, use_args = metacls._find_new_(classdict, member_type, + first_enum) + + # save enum items into separate mapping so they don't get baked into + # the new class + enum_members = {k: classdict[k] for k in classdict._member_names} + for name in classdict._member_names: + del classdict[name] + + # adjust the sunders + _order_ = classdict.pop('_order_', None) + + # check for illegal enum names (any others?) + invalid_names = set(enum_members) & {'mro', } + if invalid_names: + raise ValueError('Invalid enum member name: {0}'.format( + ','.join(invalid_names))) + + # create a default docstring if one has not been provided + if '__doc__' not in classdict: + classdict['__doc__'] = 'An enumeration.' + + # create our new Enum type + enum_class = super().__new__(metacls, cls, bases, classdict) + enum_class._member_names_ = [] # names in definition order + enum_class._member_map_ = OrderedDict() # name->value map + enum_class._member_type_ = member_type + + # save DynamicClassAttribute attributes from super classes so we know + # if we can take the shortcut of storing members in the class dict + dynamic_attributes = {k for c in enum_class.mro() + for k, v in c.__dict__.items() + if isinstance(v, DynamicClassAttribute)} + + # Reverse value->name map for hashable values. + enum_class._value2member_map_ = {} + + # If a custom type is mixed into the Enum, and it does not know how + # to pickle itself, pickle.dumps will succeed but pickle.loads will + # fail. Rather than have the error show up later and possibly far + # from the source, sabotage the pickle protocol for this class so + # that pickle.dumps also fails. + # + # However, if the new class implements its own __reduce_ex__, do not + # sabotage -- it's on them to make sure it works correctly. We use + # __reduce_ex__ instead of any of the others as it is preferred by + # pickle over __reduce__, and it handles all pickle protocols. + if '__reduce_ex__' not in classdict: + if member_type is not object: + methods = ('__getnewargs_ex__', '__getnewargs__', + '__reduce_ex__', '__reduce__') + if not any(m in member_type.__dict__ for m in methods): + _make_class_unpicklable(enum_class) + + # instantiate them, checking for duplicates as we go + # we instantiate first instead of checking for duplicates first in case + # a custom __new__ is doing something funky with the values -- such as + # auto-numbering ;) + for member_name in classdict._member_names: + value = enum_members[member_name] + if not isinstance(value, tuple): + args = (value, ) + else: + args = value + if member_type is tuple: # special case for tuple enums + args = (args, ) # wrap it one more time + if not use_args: + enum_member = __new__(enum_class) + if not hasattr(enum_member, '_value_'): + enum_member._value_ = value + else: + enum_member = __new__(enum_class, *args) + if not hasattr(enum_member, '_value_'): + if member_type is object: + enum_member._value_ = value + else: + enum_member._value_ = member_type(*args) + value = enum_member._value_ + enum_member._name_ = member_name + enum_member.__objclass__ = enum_class + enum_member.__init__(*args) + # If another member with the same value was already defined, the + # new member becomes an alias to the existing one. + for name, canonical_member in enum_class._member_map_.items(): + if canonical_member._value_ == enum_member._value_: + enum_member = canonical_member + break + else: + # Aliases don't appear in member names (only in __members__). + enum_class._member_names_.append(member_name) + # performance boost for any member that would not shadow + # a DynamicClassAttribute + if member_name not in dynamic_attributes: + setattr(enum_class, member_name, enum_member) + # now add to _member_map_ + enum_class._member_map_[member_name] = enum_member + try: + # This may fail if value is not hashable. We can't add the value + # to the map, and by-value lookups for this value will be + # linear. + enum_class._value2member_map_[value] = enum_member + except TypeError: + pass + + # double check that repr and friends are not the mixin's or various + # things break (such as pickle) + for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): + class_method = getattr(enum_class, name) + obj_method = getattr(member_type, name, None) + enum_method = getattr(first_enum, name, None) + if obj_method is not None and obj_method is class_method: + setattr(enum_class, name, enum_method) + + # replace any other __new__ with our own (as long as Enum is not None, + # anyway) -- again, this is to support pickle + if Enum is not None: + # if the user defined their own __new__, save it before it gets + # clobbered in case they subclass later + if save_new: + enum_class.__new_member__ = __new__ + enum_class.__new__ = Enum.__new__ + + # py3 support for definition order (helps keep py2/py3 code in sync) + if _order_ is not None: + if isinstance(_order_, str): + _order_ = _order_.replace(',', ' ').split() + if _order_ != enum_class._member_names_: + raise TypeError('member order does not match _order_') + + return enum_class + + def __bool__(self): + """ + classes/types should always be True. + """ + return True + + def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1): + """Either returns an existing member, or creates a new enum class. + + This method is used both when an enum class is given a value to match + to an enumeration member (i.e. Color(3)) and for the functional API + (i.e. Color = Enum('Color', names='RED GREEN BLUE')). + + When used for the functional API: + + `value` will be the name of the new class. + + `names` should be either a string of white-space/comma delimited names + (values will start at `start`), or an iterator/mapping of name, value pairs. + + `module` should be set to the module this class is being created in; + if it is not set, an attempt to find that module will be made, but if + it fails the class will not be picklable. + + `qualname` should be set to the actual location this class can be found + at in its module; by default it is set to the global scope. If this is + not correct, unpickling will fail in some circumstances. + + `type`, if set, will be mixed in as the first base class. + + """ + if names is None: # simple value lookup + return cls.__new__(cls, value) + # otherwise, functional API: we're creating a new Enum type + return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start) + + def __contains__(cls, member): + if not isinstance(member, Enum): + import warnings + warnings.warn( + "using non-Enums in containment checks will raise " + "TypeError in Python 3.8", + DeprecationWarning, 2) + return isinstance(member, cls) and member._name_ in cls._member_map_ + + def __delattr__(cls, attr): + # nicer error message when someone tries to delete an attribute + # (see issue19025). + if attr in cls._member_map_: + raise AttributeError( + "%s: cannot delete Enum member." % cls.__name__) + super().__delattr__(attr) + + def __dir__(self): + return (['__class__', '__doc__', '__members__', '__module__'] + + self._member_names_) + + def __getattr__(cls, name): + """Return the enum member matching `name` + + We use __getattr__ instead of descriptors or inserting into the enum + class' __dict__ in order to support `name` and `value` being both + properties for enum members (which live in the class' __dict__) and + enum members themselves. + + """ + if _is_dunder(name): + raise AttributeError(name) + try: + return cls._member_map_[name] + except KeyError: + raise AttributeError(name) from None + + def __getitem__(cls, name): + return cls._member_map_[name] + + def __iter__(cls): + return (cls._member_map_[name] for name in cls._member_names_) + + def __len__(cls): + return len(cls._member_names_) + + @property + def __members__(cls): + """Returns a mapping of member name->value. + + This mapping lists all enum members, including aliases. Note that this + is a read-only view of the internal mapping. + + """ + return MappingProxyType(cls._member_map_) + + def __repr__(cls): + return "" % cls.__name__ + + def __reversed__(cls): + return (cls._member_map_[name] for name in reversed(cls._member_names_)) + + def __setattr__(cls, name, value): + """Block attempts to reassign Enum members. + + A simple assignment to the class namespace only changes one of the + several possible ways to get an Enum member from the Enum class, + resulting in an inconsistent Enumeration. + + """ + member_map = cls.__dict__.get('_member_map_', {}) + if name in member_map: + raise AttributeError('Cannot reassign members.') + super().__setattr__(name, value) + + def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): + """Convenience method to create a new Enum class. + + `names` can be: + + * A string containing member names, separated either with spaces or + commas. Values are incremented by 1 from `start`. + * An iterable of member names. Values are incremented by 1 from `start`. + * An iterable of (member name, value) pairs. + * A mapping of member name -> value pairs. + + """ + metacls = cls.__class__ + bases = (cls, ) if type is None else (type, cls) + _, first_enum = cls._get_mixins_(bases) + classdict = metacls.__prepare__(class_name, bases) + + # special processing needed for names? + if isinstance(names, str): + names = names.replace(',', ' ').split() + if isinstance(names, (tuple, list)) and names and isinstance(names[0], str): + original_names, names = names, [] + last_values = [] + for count, name in enumerate(original_names): + value = first_enum._generate_next_value_(name, start, count, last_values[:]) + last_values.append(value) + names.append((name, value)) + + # Here, names is either an iterable of (name, value) or a mapping. + for item in names: + if isinstance(item, str): + member_name, member_value = item, names[item] + else: + member_name, member_value = item + classdict[member_name] = member_value + enum_class = metacls.__new__(metacls, class_name, bases, classdict) + + # TODO: replace the frame hack if a blessed way to know the calling + # module is ever developed + if module is None: + try: + module = sys._getframe(2).f_globals['__name__'] + except (AttributeError, ValueError) as exc: + pass + if module is None: + _make_class_unpicklable(enum_class) + else: + enum_class.__module__ = module + if qualname is not None: + enum_class.__qualname__ = qualname + + return enum_class + + @staticmethod + def _get_mixins_(bases): + """Returns the type for creating enum members, and the first inherited + enum class. + + bases: the tuple of bases that was given to __new__ + + """ + if not bases: + return object, Enum + + def _find_data_type(bases): + for chain in bases: + for base in chain.__mro__: + if base is object: + continue + elif '__new__' in base.__dict__: + if issubclass(base, Enum): + continue + return base + + # ensure final parent class is an Enum derivative, find any concrete + # data type, and check that Enum has no members + first_enum = bases[-1] + if not issubclass(first_enum, Enum): + raise TypeError("new enumerations should be created as " + "`EnumName([mixin_type, ...] [data_type,] enum_type)`") + member_type = _find_data_type(bases) or object + if first_enum._member_names_: + raise TypeError("Cannot extend enumerations") + return member_type, first_enum + + @staticmethod + def _find_new_(classdict, member_type, first_enum): + """Returns the __new__ to be used for creating the enum members. + + classdict: the class dictionary given to __new__ + member_type: the data type whose __new__ will be used by default + first_enum: enumeration to check for an overriding __new__ + + """ + # now find the correct __new__, checking to see of one was defined + # by the user; also check earlier enum classes in case a __new__ was + # saved as __new_member__ + __new__ = classdict.get('__new__', None) + + # should __new__ be saved as __new_member__ later? + save_new = __new__ is not None + + if __new__ is None: + # check all possibles for __new_member__ before falling back to + # __new__ + for method in ('__new_member__', '__new__'): + for possible in (member_type, first_enum): + target = getattr(possible, method, None) + if target not in { + None, + None.__new__, + object.__new__, + Enum.__new__, + }: + __new__ = target + break + if __new__ is not None: + break + else: + __new__ = object.__new__ + + # if a non-object.__new__ is used then whatever value/tuple was + # assigned to the enum member name will be passed to __new__ and to the + # new enum member's __init__ + if __new__ is object.__new__: + use_args = False + else: + use_args = True + return __new__, save_new, use_args + + +class Enum(metaclass=EnumMeta): + """Generic enumeration. + + Derive from this class to define new enumerations. + + """ + def __new__(cls, value): + # all enum instances are actually created during class construction + # without calling this method; this method is called by the metaclass' + # __call__ (i.e. Color(3) ), and by pickle + if type(value) is cls: + # For lookups like Color(Color.RED) + return value + # by-value search for a matching enum member + # see if it's in the reverse mapping (for hashable values) + try: + if value in cls._value2member_map_: + return cls._value2member_map_[value] + except TypeError: + # not there, now do long search -- O(n) behavior + for member in cls._member_map_.values(): + if member._value_ == value: + return member + # still not found -- try _missing_ hook + return cls._missing_(value) + + def _generate_next_value_(name, start, count, last_values): + for last_value in reversed(last_values): + try: + return last_value + 1 + except TypeError: + pass + else: + return start + + @classmethod + def _missing_(cls, value): + raise ValueError("%r is not a valid %s" % (value, cls.__name__)) + + def __repr__(self): + return "<%s.%s: %r>" % ( + self.__class__.__name__, self._name_, self._value_) + + def __str__(self): + return "%s.%s" % (self.__class__.__name__, self._name_) + + def __dir__(self): + added_behavior = [ + m + for cls in self.__class__.mro() + for m in cls.__dict__ + if m[0] != '_' and m not in self._member_map_ + ] + return (['__class__', '__doc__', '__module__'] + added_behavior) + + def __format__(self, format_spec): + # mixed-in Enums should use the mixed-in type's __format__, otherwise + # we can get strange results with the Enum name showing up instead of + # the value + + # pure Enum branch + if self._member_type_ is object: + cls = str + val = str(self) + # mix-in branch + else: + cls = self._member_type_ + val = self._value_ + return cls.__format__(val, format_spec) + + def __hash__(self): + return hash(self._name_) + + def __reduce_ex__(self, proto): + return self.__class__, (self._value_, ) + + # DynamicClassAttribute is used to provide access to the `name` and + # `value` properties of enum members while keeping some measure of + # protection from modification, while still allowing for an enumeration + # to have members named `name` and `value`. This works because enumeration + # members are not set directly on the enum class -- __getattr__ is + # used to look them up. + + @DynamicClassAttribute + def name(self): + """The name of the Enum member.""" + return self._name_ + + @DynamicClassAttribute + def value(self): + """The value of the Enum member.""" + return self._value_ + + @classmethod + def _convert(cls, name, module, filter, source=None): + """ + Create a new Enum subclass that replaces a collection of global constants + """ + # convert all constants from source (or module) that pass filter() to + # a new Enum called name, and export the enum and its members back to + # module; + # also, replace the __reduce_ex__ method so unpickling works in + # previous Python versions + module_globals = vars(sys.modules[module]) + if source: + source = vars(source) + else: + source = module_globals + # We use an OrderedDict of sorted source keys so that the + # _value2member_map is populated in the same order every time + # for a consistent reverse mapping of number to name when there + # are multiple names for the same number rather than varying + # between runs due to hash randomization of the module dictionary. + members = [ + (name, source[name]) + for name in source.keys() + if filter(name)] + try: + # sort by value + members.sort(key=lambda t: (t[1], t[0])) + except TypeError: + # unless some values aren't comparable, in which case sort by name + members.sort(key=lambda t: t[0]) + cls = cls(name, members, module=module) + cls.__reduce_ex__ = _reduce_ex_by_name + module_globals.update(cls.__members__) + module_globals[name] = cls + return cls + + +class IntEnum(int, Enum): + """Enum where members are also (and must be) ints""" + + +def _reduce_ex_by_name(self, proto): + return self.name + +class Flag(Enum): + """Support for flags""" + + def _generate_next_value_(name, start, count, last_values): + """ + Generate the next value when not given. + + name: the name of the member + start: the initital start value or None + count: the number of existing members + last_value: the last value assigned or None + """ + if not count: + return start if start is not None else 1 + for last_value in reversed(last_values): + try: + high_bit = _high_bit(last_value) + break + except Exception: + raise TypeError('Invalid Flag value: %r' % last_value) from None + return 2 ** (high_bit+1) + + @classmethod + def _missing_(cls, value): + original_value = value + if value < 0: + value = ~value + possible_member = cls._create_pseudo_member_(value) + if original_value < 0: + possible_member = ~possible_member + return possible_member + + @classmethod + def _create_pseudo_member_(cls, value): + """ + Create a composite member iff value contains only members. + """ + pseudo_member = cls._value2member_map_.get(value, None) + if pseudo_member is None: + # verify all bits are accounted for + _, extra_flags = _decompose(cls, value) + if extra_flags: + raise ValueError("%r is not a valid %s" % (value, cls.__name__)) + # construct a singleton enum pseudo-member + pseudo_member = object.__new__(cls) + pseudo_member._name_ = None + pseudo_member._value_ = value + # use setdefault in case another thread already created a composite + # with this value + pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) + return pseudo_member + + def __contains__(self, other): + if not isinstance(other, self.__class__): + import warnings + warnings.warn( + "using non-Flags in containment checks will raise " + "TypeError in Python 3.8", + DeprecationWarning, 2) + return False + return other._value_ & self._value_ == other._value_ + + def __repr__(self): + cls = self.__class__ + if self._name_ is not None: + return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_) + members, uncovered = _decompose(cls, self._value_) + return '<%s.%s: %r>' % ( + cls.__name__, + '|'.join([str(m._name_ or m._value_) for m in members]), + self._value_, + ) + + def __str__(self): + cls = self.__class__ + if self._name_ is not None: + return '%s.%s' % (cls.__name__, self._name_) + members, uncovered = _decompose(cls, self._value_) + if len(members) == 1 and members[0]._name_ is None: + return '%s.%r' % (cls.__name__, members[0]._value_) + else: + return '%s.%s' % ( + cls.__name__, + '|'.join([str(m._name_ or m._value_) for m in members]), + ) + + def __bool__(self): + return bool(self._value_) + + def __or__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.__class__(self._value_ | other._value_) + + def __and__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.__class__(self._value_ & other._value_) + + def __xor__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.__class__(self._value_ ^ other._value_) + + def __invert__(self): + members, uncovered = _decompose(self.__class__, self._value_) + inverted = self.__class__(0) + for m in self.__class__: + if m not in members and not (m._value_ & self._value_): + inverted = inverted | m + return self.__class__(inverted) + + +class IntFlag(int, Flag): + """Support for integer-based Flags""" + + @classmethod + def _missing_(cls, value): + if not isinstance(value, int): + raise ValueError("%r is not a valid %s" % (value, cls.__name__)) + new_member = cls._create_pseudo_member_(value) + return new_member + + @classmethod + def _create_pseudo_member_(cls, value): + pseudo_member = cls._value2member_map_.get(value, None) + if pseudo_member is None: + need_to_create = [value] + # get unaccounted for bits + _, extra_flags = _decompose(cls, value) + # timer = 10 + while extra_flags: + # timer -= 1 + bit = _high_bit(extra_flags) + flag_value = 2 ** bit + if (flag_value not in cls._value2member_map_ and + flag_value not in need_to_create + ): + need_to_create.append(flag_value) + if extra_flags == -flag_value: + extra_flags = 0 + else: + extra_flags ^= flag_value + for value in reversed(need_to_create): + # construct singleton pseudo-members + pseudo_member = int.__new__(cls, value) + pseudo_member._name_ = None + pseudo_member._value_ = value + # use setdefault in case another thread already created a composite + # with this value + pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) + return pseudo_member + + def __or__(self, other): + if not isinstance(other, (self.__class__, int)): + return NotImplemented + result = self.__class__(self._value_ | self.__class__(other)._value_) + return result + + def __and__(self, other): + if not isinstance(other, (self.__class__, int)): + return NotImplemented + return self.__class__(self._value_ & self.__class__(other)._value_) + + def __xor__(self, other): + if not isinstance(other, (self.__class__, int)): + return NotImplemented + return self.__class__(self._value_ ^ self.__class__(other)._value_) + + __ror__ = __or__ + __rand__ = __and__ + __rxor__ = __xor__ + + def __invert__(self): + result = self.__class__(~self._value_) + return result + + +def _high_bit(value): + """returns index of highest bit, or -1 if value is zero or negative""" + return value.bit_length() - 1 + +def unique(enumeration): + """Class decorator for enumerations ensuring unique member values.""" + duplicates = [] + for name, member in enumeration.__members__.items(): + if name != member.name: + duplicates.append((name, member.name)) + if duplicates: + alias_details = ', '.join( + ["%s -> %s" % (alias, name) for (alias, name) in duplicates]) + raise ValueError('duplicate values found in %r: %s' % + (enumeration, alias_details)) + return enumeration + +def _decompose(flag, value): + """Extract all members from the value.""" + # _decompose is only called if the value is not named + not_covered = value + negative = value < 0 + # issue29167: wrap accesses to _value2member_map_ in a list to avoid race + # conditions between iterating over it and having more pseudo- + # members added to it + if negative: + # only check for named flags + flags_to_check = [ + (m, v) + for v, m in list(flag._value2member_map_.items()) + if m.name is not None + ] + else: + # check for named flags and powers-of-two flags + flags_to_check = [ + (m, v) + for v, m in list(flag._value2member_map_.items()) + if m.name is not None or _power_of_two(v) + ] + members = [] + for member, member_value in flags_to_check: + if member_value and member_value & value == member_value: + members.append(member) + not_covered &= ~member_value + if not members and value in flag._value2member_map_: + members.append(flag._value2member_map_[value]) + members.sort(key=lambda m: m._value_, reverse=True) + if len(members) > 1 and members[0].value == value: + # we have the breakdown, don't need the value member itself + members.pop(0) + return members, not_covered + +def _power_of_two(value): + if value < 1: + return False + return value == 2 ** _high_bit(value) diff --git a/winvenv/Lib/fnmatch.py b/winvenv/Lib/fnmatch.py new file mode 100644 index 0000000..b98e641 --- /dev/null +++ b/winvenv/Lib/fnmatch.py @@ -0,0 +1,128 @@ +"""Filename matching with shell patterns. + +fnmatch(FILENAME, PATTERN) matches according to the local convention. +fnmatchcase(FILENAME, PATTERN) always takes case in account. + +The functions operate by translating the pattern into a regular +expression. They cache the compiled regular expressions for speed. + +The function translate(PATTERN) returns a regular expression +corresponding to PATTERN. (It does not compile it.) +""" +import os +import posixpath +import re +import functools + +__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] + +def fnmatch(name, pat): + """Test whether FILENAME matches PATTERN. + + Patterns are Unix shell style: + + * matches everything + ? matches any single character + [seq] matches any character in seq + [!seq] matches any char not in seq + + An initial period in FILENAME is not special. + Both FILENAME and PATTERN are first case-normalized + if the operating system requires it. + If you don't want this, use fnmatchcase(FILENAME, PATTERN). + """ + name = os.path.normcase(name) + pat = os.path.normcase(pat) + return fnmatchcase(name, pat) + +@functools.lru_cache(maxsize=256, typed=True) +def _compile_pattern(pat): + if isinstance(pat, bytes): + pat_str = str(pat, 'ISO-8859-1') + res_str = translate(pat_str) + res = bytes(res_str, 'ISO-8859-1') + else: + res = translate(pat) + return re.compile(res).match + +def filter(names, pat): + """Return the subset of the list NAMES that match PAT.""" + result = [] + pat = os.path.normcase(pat) + match = _compile_pattern(pat) + if os.path is posixpath: + # normcase on posix is NOP. Optimize it away from the loop. + for name in names: + if match(name): + result.append(name) + else: + for name in names: + if match(os.path.normcase(name)): + result.append(name) + return result + +def fnmatchcase(name, pat): + """Test whether FILENAME matches PATTERN, including case. + + This is a version of fnmatch() which doesn't case-normalize + its arguments. + """ + match = _compile_pattern(pat) + return match(name) is not None + + +def translate(pat): + """Translate a shell PATTERN to a regular expression. + + There is no way to quote meta-characters. + """ + + i, n = 0, len(pat) + res = '' + while i < n: + c = pat[i] + i = i+1 + if c == '*': + res = res + '.*' + elif c == '?': + res = res + '.' + elif c == '[': + j = i + if j < n and pat[j] == '!': + j = j+1 + if j < n and pat[j] == ']': + j = j+1 + while j < n and pat[j] != ']': + j = j+1 + if j >= n: + res = res + '\\[' + else: + stuff = pat[i:j] + if '--' not in stuff: + stuff = stuff.replace('\\', r'\\') + else: + chunks = [] + k = i+2 if pat[i] == '!' else i+1 + while True: + k = pat.find('-', k, j) + if k < 0: + break + chunks.append(pat[i:k]) + i = k+1 + k = k+3 + chunks.append(pat[i:j]) + # Escape backslashes and hyphens for set difference (--). + # Hyphens that create ranges shouldn't be escaped. + stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-') + for s in chunks) + # Escape set operations (&&, ~~ and ||). + stuff = re.sub(r'([&~|])', r'\\\1', stuff) + i = j+1 + if stuff[0] == '!': + stuff = '^' + stuff[1:] + elif stuff[0] in ('^', '['): + stuff = '\\' + stuff + res = '%s[%s]' % (res, stuff) + else: + res = res + re.escape(c) + return r'(?s:%s)\Z' % res diff --git a/winvenv/Lib/functools.py b/winvenv/Lib/functools.py new file mode 100644 index 0000000..24b011d --- /dev/null +++ b/winvenv/Lib/functools.py @@ -0,0 +1,833 @@ +"""functools.py - Tools for working with functions and callable objects +""" +# Python module wrapper for _functools C module +# to allow utilities written in Python to be added +# to the functools module. +# Written by Nick Coghlan , +# Raymond Hettinger , +# and Łukasz Langa . +# Copyright (C) 2006-2013 Python Software Foundation. +# See C source code for _functools credits/copyright + +__all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', + 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial', + 'partialmethod', 'singledispatch'] + +try: + from _functools import reduce +except ImportError: + pass +from abc import get_cache_token +from collections import namedtuple +# import types, weakref # Deferred to single_dispatch() +from reprlib import recursive_repr +from _thread import RLock + + +################################################################################ +### update_wrapper() and wraps() decorator +################################################################################ + +# update_wrapper() and wraps() are tools to help write +# wrapper functions that can handle naive introspection + +WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__', + '__annotations__') +WRAPPER_UPDATES = ('__dict__',) +def update_wrapper(wrapper, + wrapped, + assigned = WRAPPER_ASSIGNMENTS, + updated = WRAPPER_UPDATES): + """Update a wrapper function to look like the wrapped function + + wrapper is the function to be updated + wrapped is the original function + assigned is a tuple naming the attributes assigned directly + from the wrapped function to the wrapper function (defaults to + functools.WRAPPER_ASSIGNMENTS) + updated is a tuple naming the attributes of the wrapper that + are updated with the corresponding attribute from the wrapped + function (defaults to functools.WRAPPER_UPDATES) + """ + for attr in assigned: + try: + value = getattr(wrapped, attr) + except AttributeError: + pass + else: + setattr(wrapper, attr, value) + for attr in updated: + getattr(wrapper, attr).update(getattr(wrapped, attr, {})) + # Issue #17482: set __wrapped__ last so we don't inadvertently copy it + # from the wrapped function when updating __dict__ + wrapper.__wrapped__ = wrapped + # Return the wrapper so this can be used as a decorator via partial() + return wrapper + +def wraps(wrapped, + assigned = WRAPPER_ASSIGNMENTS, + updated = WRAPPER_UPDATES): + """Decorator factory to apply update_wrapper() to a wrapper function + + Returns a decorator that invokes update_wrapper() with the decorated + function as the wrapper argument and the arguments to wraps() as the + remaining arguments. Default arguments are as for update_wrapper(). + This is a convenience function to simplify applying partial() to + update_wrapper(). + """ + return partial(update_wrapper, wrapped=wrapped, + assigned=assigned, updated=updated) + + +################################################################################ +### total_ordering class decorator +################################################################################ + +# The total ordering functions all invoke the root magic method directly +# rather than using the corresponding operator. This avoids possible +# infinite recursion that could occur when the operator dispatch logic +# detects a NotImplemented result and then calls a reflected method. + +def _gt_from_lt(self, other, NotImplemented=NotImplemented): + 'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).' + op_result = self.__lt__(other) + if op_result is NotImplemented: + return op_result + return not op_result and self != other + +def _le_from_lt(self, other, NotImplemented=NotImplemented): + 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).' + op_result = self.__lt__(other) + return op_result or self == other + +def _ge_from_lt(self, other, NotImplemented=NotImplemented): + 'Return a >= b. Computed by @total_ordering from (not a < b).' + op_result = self.__lt__(other) + if op_result is NotImplemented: + return op_result + return not op_result + +def _ge_from_le(self, other, NotImplemented=NotImplemented): + 'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).' + op_result = self.__le__(other) + if op_result is NotImplemented: + return op_result + return not op_result or self == other + +def _lt_from_le(self, other, NotImplemented=NotImplemented): + 'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).' + op_result = self.__le__(other) + if op_result is NotImplemented: + return op_result + return op_result and self != other + +def _gt_from_le(self, other, NotImplemented=NotImplemented): + 'Return a > b. Computed by @total_ordering from (not a <= b).' + op_result = self.__le__(other) + if op_result is NotImplemented: + return op_result + return not op_result + +def _lt_from_gt(self, other, NotImplemented=NotImplemented): + 'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).' + op_result = self.__gt__(other) + if op_result is NotImplemented: + return op_result + return not op_result and self != other + +def _ge_from_gt(self, other, NotImplemented=NotImplemented): + 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).' + op_result = self.__gt__(other) + return op_result or self == other + +def _le_from_gt(self, other, NotImplemented=NotImplemented): + 'Return a <= b. Computed by @total_ordering from (not a > b).' + op_result = self.__gt__(other) + if op_result is NotImplemented: + return op_result + return not op_result + +def _le_from_ge(self, other, NotImplemented=NotImplemented): + 'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).' + op_result = self.__ge__(other) + if op_result is NotImplemented: + return op_result + return not op_result or self == other + +def _gt_from_ge(self, other, NotImplemented=NotImplemented): + 'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).' + op_result = self.__ge__(other) + if op_result is NotImplemented: + return op_result + return op_result and self != other + +def _lt_from_ge(self, other, NotImplemented=NotImplemented): + 'Return a < b. Computed by @total_ordering from (not a >= b).' + op_result = self.__ge__(other) + if op_result is NotImplemented: + return op_result + return not op_result + +_convert = { + '__lt__': [('__gt__', _gt_from_lt), + ('__le__', _le_from_lt), + ('__ge__', _ge_from_lt)], + '__le__': [('__ge__', _ge_from_le), + ('__lt__', _lt_from_le), + ('__gt__', _gt_from_le)], + '__gt__': [('__lt__', _lt_from_gt), + ('__ge__', _ge_from_gt), + ('__le__', _le_from_gt)], + '__ge__': [('__le__', _le_from_ge), + ('__gt__', _gt_from_ge), + ('__lt__', _lt_from_ge)] +} + +def total_ordering(cls): + """Class decorator that fills in missing ordering methods""" + # Find user-defined comparisons (not those inherited from object). + roots = {op for op in _convert if getattr(cls, op, None) is not getattr(object, op, None)} + if not roots: + raise ValueError('must define at least one ordering operation: < > <= >=') + root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__ + for opname, opfunc in _convert[root]: + if opname not in roots: + opfunc.__name__ = opname + setattr(cls, opname, opfunc) + return cls + + +################################################################################ +### cmp_to_key() function converter +################################################################################ + +def cmp_to_key(mycmp): + """Convert a cmp= function into a key= function""" + class K(object): + __slots__ = ['obj'] + def __init__(self, obj): + self.obj = obj + def __lt__(self, other): + return mycmp(self.obj, other.obj) < 0 + def __gt__(self, other): + return mycmp(self.obj, other.obj) > 0 + def __eq__(self, other): + return mycmp(self.obj, other.obj) == 0 + def __le__(self, other): + return mycmp(self.obj, other.obj) <= 0 + def __ge__(self, other): + return mycmp(self.obj, other.obj) >= 0 + __hash__ = None + return K + +try: + from _functools import cmp_to_key +except ImportError: + pass + + +################################################################################ +### partial() argument application +################################################################################ + +# Purely functional, no descriptor behaviour +class partial: + """New function with partial application of the given arguments + and keywords. + """ + + __slots__ = "func", "args", "keywords", "__dict__", "__weakref__" + + def __new__(*args, **keywords): + if not args: + raise TypeError("descriptor '__new__' of partial needs an argument") + if len(args) < 2: + raise TypeError("type 'partial' takes at least one argument") + cls, func, *args = args + if not callable(func): + raise TypeError("the first argument must be callable") + args = tuple(args) + + if hasattr(func, "func"): + args = func.args + args + tmpkw = func.keywords.copy() + tmpkw.update(keywords) + keywords = tmpkw + del tmpkw + func = func.func + + self = super(partial, cls).__new__(cls) + + self.func = func + self.args = args + self.keywords = keywords + return self + + def __call__(*args, **keywords): + if not args: + raise TypeError("descriptor '__call__' of partial needs an argument") + self, *args = args + newkeywords = self.keywords.copy() + newkeywords.update(keywords) + return self.func(*self.args, *args, **newkeywords) + + @recursive_repr() + def __repr__(self): + qualname = type(self).__qualname__ + args = [repr(self.func)] + args.extend(repr(x) for x in self.args) + args.extend(f"{k}={v!r}" for (k, v) in self.keywords.items()) + if type(self).__module__ == "functools": + return f"functools.{qualname}({', '.join(args)})" + return f"{qualname}({', '.join(args)})" + + def __reduce__(self): + return type(self), (self.func,), (self.func, self.args, + self.keywords or None, self.__dict__ or None) + + def __setstate__(self, state): + if not isinstance(state, tuple): + raise TypeError("argument to __setstate__ must be a tuple") + if len(state) != 4: + raise TypeError(f"expected 4 items in state, got {len(state)}") + func, args, kwds, namespace = state + if (not callable(func) or not isinstance(args, tuple) or + (kwds is not None and not isinstance(kwds, dict)) or + (namespace is not None and not isinstance(namespace, dict))): + raise TypeError("invalid partial state") + + args = tuple(args) # just in case it's a subclass + if kwds is None: + kwds = {} + elif type(kwds) is not dict: # XXX does it need to be *exactly* dict? + kwds = dict(kwds) + if namespace is None: + namespace = {} + + self.__dict__ = namespace + self.func = func + self.args = args + self.keywords = kwds + +try: + from _functools import partial +except ImportError: + pass + +# Descriptor version +class partialmethod(object): + """Method descriptor with partial application of the given arguments + and keywords. + + Supports wrapping existing descriptors and handles non-descriptor + callables as instance methods. + """ + + def __init__(self, func, *args, **keywords): + if not callable(func) and not hasattr(func, "__get__"): + raise TypeError("{!r} is not callable or a descriptor" + .format(func)) + + # func could be a descriptor like classmethod which isn't callable, + # so we can't inherit from partial (it verifies func is callable) + if isinstance(func, partialmethod): + # flattening is mandatory in order to place cls/self before all + # other arguments + # it's also more efficient since only one function will be called + self.func = func.func + self.args = func.args + args + self.keywords = func.keywords.copy() + self.keywords.update(keywords) + else: + self.func = func + self.args = args + self.keywords = keywords + + def __repr__(self): + args = ", ".join(map(repr, self.args)) + keywords = ", ".join("{}={!r}".format(k, v) + for k, v in self.keywords.items()) + format_string = "{module}.{cls}({func}, {args}, {keywords})" + return format_string.format(module=self.__class__.__module__, + cls=self.__class__.__qualname__, + func=self.func, + args=args, + keywords=keywords) + + def _make_unbound_method(self): + def _method(*args, **keywords): + call_keywords = self.keywords.copy() + call_keywords.update(keywords) + cls_or_self, *rest = args + call_args = (cls_or_self,) + self.args + tuple(rest) + return self.func(*call_args, **call_keywords) + _method.__isabstractmethod__ = self.__isabstractmethod__ + _method._partialmethod = self + return _method + + def __get__(self, obj, cls): + get = getattr(self.func, "__get__", None) + result = None + if get is not None: + new_func = get(obj, cls) + if new_func is not self.func: + # Assume __get__ returning something new indicates the + # creation of an appropriate callable + result = partial(new_func, *self.args, **self.keywords) + try: + result.__self__ = new_func.__self__ + except AttributeError: + pass + if result is None: + # If the underlying descriptor didn't do anything, treat this + # like an instance method + result = self._make_unbound_method().__get__(obj, cls) + return result + + @property + def __isabstractmethod__(self): + return getattr(self.func, "__isabstractmethod__", False) + + +################################################################################ +### LRU Cache function decorator +################################################################################ + +_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"]) + +class _HashedSeq(list): + """ This class guarantees that hash() will be called no more than once + per element. This is important because the lru_cache() will hash + the key multiple times on a cache miss. + + """ + + __slots__ = 'hashvalue' + + def __init__(self, tup, hash=hash): + self[:] = tup + self.hashvalue = hash(tup) + + def __hash__(self): + return self.hashvalue + +def _make_key(args, kwds, typed, + kwd_mark = (object(),), + fasttypes = {int, str, frozenset, type(None)}, + tuple=tuple, type=type, len=len): + """Make a cache key from optionally typed positional and keyword arguments + + The key is constructed in a way that is flat as possible rather than + as a nested structure that would take more memory. + + If there is only a single argument and its data type is known to cache + its hash value, then that argument is returned without a wrapper. This + saves space and improves lookup speed. + + """ + # All of code below relies on kwds preserving the order input by the user. + # Formerly, we sorted() the kwds before looping. The new way is *much* + # faster; however, it means that f(x=1, y=2) will now be treated as a + # distinct call from f(y=2, x=1) which will be cached separately. + key = args + if kwds: + key += kwd_mark + for item in kwds.items(): + key += item + if typed: + key += tuple(type(v) for v in args) + if kwds: + key += tuple(type(v) for v in kwds.values()) + elif len(key) == 1 and type(key[0]) in fasttypes: + return key[0] + return _HashedSeq(key) + +def lru_cache(maxsize=128, typed=False): + """Least-recently-used cache decorator. + + If *maxsize* is set to None, the LRU features are disabled and the cache + can grow without bound. + + If *typed* is True, arguments of different types will be cached separately. + For example, f(3.0) and f(3) will be treated as distinct calls with + distinct results. + + Arguments to the cached function must be hashable. + + View the cache statistics named tuple (hits, misses, maxsize, currsize) + with f.cache_info(). Clear the cache and statistics with f.cache_clear(). + Access the underlying function with f.__wrapped__. + + See: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used + + """ + + # Users should only access the lru_cache through its public API: + # cache_info, cache_clear, and f.__wrapped__ + # The internals of the lru_cache are encapsulated for thread safety and + # to allow the implementation to change (including a possible C version). + + # Early detection of an erroneous call to @lru_cache without any arguments + # resulting in the inner function being passed to maxsize instead of an + # integer or None. + if maxsize is not None and not isinstance(maxsize, int): + raise TypeError('Expected maxsize to be an integer or None') + + def decorating_function(user_function): + wrapper = _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo) + return update_wrapper(wrapper, user_function) + + return decorating_function + +def _lru_cache_wrapper(user_function, maxsize, typed, _CacheInfo): + # Constants shared by all lru cache instances: + sentinel = object() # unique object used to signal cache misses + make_key = _make_key # build a key from the function arguments + PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields + + cache = {} + hits = misses = 0 + full = False + cache_get = cache.get # bound method to lookup a key or return None + cache_len = cache.__len__ # get cache size without calling len() + lock = RLock() # because linkedlist updates aren't threadsafe + root = [] # root of the circular doubly linked list + root[:] = [root, root, None, None] # initialize by pointing to self + + if maxsize == 0: + + def wrapper(*args, **kwds): + # No caching -- just a statistics update after a successful call + nonlocal misses + result = user_function(*args, **kwds) + misses += 1 + return result + + elif maxsize is None: + + def wrapper(*args, **kwds): + # Simple caching without ordering or size limit + nonlocal hits, misses + key = make_key(args, kwds, typed) + result = cache_get(key, sentinel) + if result is not sentinel: + hits += 1 + return result + result = user_function(*args, **kwds) + cache[key] = result + misses += 1 + return result + + else: + + def wrapper(*args, **kwds): + # Size limited caching that tracks accesses by recency + nonlocal root, hits, misses, full + key = make_key(args, kwds, typed) + with lock: + link = cache_get(key) + if link is not None: + # Move the link to the front of the circular queue + link_prev, link_next, _key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root + hits += 1 + return result + result = user_function(*args, **kwds) + with lock: + if key in cache: + # Getting here means that this same key was added to the + # cache while the lock was released. Since the link + # update is already done, we need only return the + # computed result and update the count of misses. + pass + elif full: + # Use the old root to store the new key and result. + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + # Empty the oldest link and make it the new root. + # Keep a reference to the old key and old result to + # prevent their ref counts from going to zero during the + # update. That will prevent potentially arbitrary object + # clean-up code (i.e. __del__) from running while we're + # still adjusting the links. + root = oldroot[NEXT] + oldkey = root[KEY] + oldresult = root[RESULT] + root[KEY] = root[RESULT] = None + # Now update the cache dictionary. + del cache[oldkey] + # Save the potentially reentrant cache[key] assignment + # for last, after the root and links have been put in + # a consistent state. + cache[key] = oldroot + else: + # Put result in a new link at the front of the queue. + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + # Use the cache_len bound method instead of the len() function + # which could potentially be wrapped in an lru_cache itself. + full = (cache_len() >= maxsize) + misses += 1 + return result + + def cache_info(): + """Report cache statistics""" + with lock: + return _CacheInfo(hits, misses, maxsize, cache_len()) + + def cache_clear(): + """Clear the cache and cache statistics""" + nonlocal hits, misses, full + with lock: + cache.clear() + root[:] = [root, root, None, None] + hits = misses = 0 + full = False + + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return wrapper + +try: + from _functools import _lru_cache_wrapper +except ImportError: + pass + + +################################################################################ +### singledispatch() - single-dispatch generic function decorator +################################################################################ + +def _c3_merge(sequences): + """Merges MROs in *sequences* to a single MRO using the C3 algorithm. + + Adapted from http://www.python.org/download/releases/2.3/mro/. + + """ + result = [] + while True: + sequences = [s for s in sequences if s] # purge empty sequences + if not sequences: + return result + for s1 in sequences: # find merge candidates among seq heads + candidate = s1[0] + for s2 in sequences: + if candidate in s2[1:]: + candidate = None + break # reject the current head, it appears later + else: + break + if candidate is None: + raise RuntimeError("Inconsistent hierarchy") + result.append(candidate) + # remove the chosen candidate + for seq in sequences: + if seq[0] == candidate: + del seq[0] + +def _c3_mro(cls, abcs=None): + """Computes the method resolution order using extended C3 linearization. + + If no *abcs* are given, the algorithm works exactly like the built-in C3 + linearization used for method resolution. + + If given, *abcs* is a list of abstract base classes that should be inserted + into the resulting MRO. Unrelated ABCs are ignored and don't end up in the + result. The algorithm inserts ABCs where their functionality is introduced, + i.e. issubclass(cls, abc) returns True for the class itself but returns + False for all its direct base classes. Implicit ABCs for a given class + (either registered or inferred from the presence of a special method like + __len__) are inserted directly after the last ABC explicitly listed in the + MRO of said class. If two implicit ABCs end up next to each other in the + resulting MRO, their ordering depends on the order of types in *abcs*. + + """ + for i, base in enumerate(reversed(cls.__bases__)): + if hasattr(base, '__abstractmethods__'): + boundary = len(cls.__bases__) - i + break # Bases up to the last explicit ABC are considered first. + else: + boundary = 0 + abcs = list(abcs) if abcs else [] + explicit_bases = list(cls.__bases__[:boundary]) + abstract_bases = [] + other_bases = list(cls.__bases__[boundary:]) + for base in abcs: + if issubclass(cls, base) and not any( + issubclass(b, base) for b in cls.__bases__ + ): + # If *cls* is the class that introduces behaviour described by + # an ABC *base*, insert said ABC to its MRO. + abstract_bases.append(base) + for base in abstract_bases: + abcs.remove(base) + explicit_c3_mros = [_c3_mro(base, abcs=abcs) for base in explicit_bases] + abstract_c3_mros = [_c3_mro(base, abcs=abcs) for base in abstract_bases] + other_c3_mros = [_c3_mro(base, abcs=abcs) for base in other_bases] + return _c3_merge( + [[cls]] + + explicit_c3_mros + abstract_c3_mros + other_c3_mros + + [explicit_bases] + [abstract_bases] + [other_bases] + ) + +def _compose_mro(cls, types): + """Calculates the method resolution order for a given class *cls*. + + Includes relevant abstract base classes (with their respective bases) from + the *types* iterable. Uses a modified C3 linearization algorithm. + + """ + bases = set(cls.__mro__) + # Remove entries which are already present in the __mro__ or unrelated. + def is_related(typ): + return (typ not in bases and hasattr(typ, '__mro__') + and issubclass(cls, typ)) + types = [n for n in types if is_related(n)] + # Remove entries which are strict bases of other entries (they will end up + # in the MRO anyway. + def is_strict_base(typ): + for other in types: + if typ != other and typ in other.__mro__: + return True + return False + types = [n for n in types if not is_strict_base(n)] + # Subclasses of the ABCs in *types* which are also implemented by + # *cls* can be used to stabilize ABC ordering. + type_set = set(types) + mro = [] + for typ in types: + found = [] + for sub in typ.__subclasses__(): + if sub not in bases and issubclass(cls, sub): + found.append([s for s in sub.__mro__ if s in type_set]) + if not found: + mro.append(typ) + continue + # Favor subclasses with the biggest number of useful bases + found.sort(key=len, reverse=True) + for sub in found: + for subcls in sub: + if subcls not in mro: + mro.append(subcls) + return _c3_mro(cls, abcs=mro) + +def _find_impl(cls, registry): + """Returns the best matching implementation from *registry* for type *cls*. + + Where there is no registered implementation for a specific type, its method + resolution order is used to find a more generic implementation. + + Note: if *registry* does not contain an implementation for the base + *object* type, this function may return None. + + """ + mro = _compose_mro(cls, registry.keys()) + match = None + for t in mro: + if match is not None: + # If *match* is an implicit ABC but there is another unrelated, + # equally matching implicit ABC, refuse the temptation to guess. + if (t in registry and t not in cls.__mro__ + and match not in cls.__mro__ + and not issubclass(match, t)): + raise RuntimeError("Ambiguous dispatch: {} or {}".format( + match, t)) + break + if t in registry: + match = t + return registry.get(match) + +def singledispatch(func): + """Single-dispatch generic function decorator. + + Transforms a function into a generic function, which can have different + behaviours depending upon the type of its first argument. The decorated + function acts as the default implementation, and additional + implementations can be registered using the register() attribute of the + generic function. + """ + # There are many programs that use functools without singledispatch, so we + # trade-off making singledispatch marginally slower for the benefit of + # making start-up of such applications slightly faster. + import types, weakref + + registry = {} + dispatch_cache = weakref.WeakKeyDictionary() + cache_token = None + + def dispatch(cls): + """generic_func.dispatch(cls) -> + + Runs the dispatch algorithm to return the best available implementation + for the given *cls* registered on *generic_func*. + + """ + nonlocal cache_token + if cache_token is not None: + current_token = get_cache_token() + if cache_token != current_token: + dispatch_cache.clear() + cache_token = current_token + try: + impl = dispatch_cache[cls] + except KeyError: + try: + impl = registry[cls] + except KeyError: + impl = _find_impl(cls, registry) + dispatch_cache[cls] = impl + return impl + + def register(cls, func=None): + """generic_func.register(cls, func) -> func + + Registers a new implementation for the given *cls* on a *generic_func*. + + """ + nonlocal cache_token + if func is None: + if isinstance(cls, type): + return lambda f: register(cls, f) + ann = getattr(cls, '__annotations__', {}) + if not ann: + raise TypeError( + f"Invalid first argument to `register()`: {cls!r}. " + f"Use either `@register(some_class)` or plain `@register` " + f"on an annotated function." + ) + func = cls + + # only import typing if annotation parsing is necessary + from typing import get_type_hints + argname, cls = next(iter(get_type_hints(func).items())) + assert isinstance(cls, type), ( + f"Invalid annotation for {argname!r}. {cls!r} is not a class." + ) + registry[cls] = func + if cache_token is None and hasattr(cls, '__abstractmethods__'): + cache_token = get_cache_token() + dispatch_cache.clear() + return func + + def wrapper(*args, **kw): + if not args: + raise TypeError(f'{funcname} requires at least ' + '1 positional argument') + + return dispatch(args[0].__class__)(*args, **kw) + + funcname = getattr(func, '__name__', 'singledispatch function') + registry[object] = func + wrapper.register = register + wrapper.dispatch = dispatch + wrapper.registry = types.MappingProxyType(registry) + wrapper._clear_cache = dispatch_cache.clear + update_wrapper(wrapper, func) + return wrapper diff --git a/winvenv/Lib/genericpath.py b/winvenv/Lib/genericpath.py new file mode 100644 index 0000000..303b3b3 --- /dev/null +++ b/winvenv/Lib/genericpath.py @@ -0,0 +1,151 @@ +""" +Path operations common to more than one OS +Do not use directly. The OS specific modules import the appropriate +functions from this module themselves. +""" +import os +import stat + +__all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime', + 'getsize', 'isdir', 'isfile', 'samefile', 'sameopenfile', + 'samestat'] + + +# Does a path exist? +# This is false for dangling symbolic links on systems that support them. +def exists(path): + """Test whether a path exists. Returns False for broken symbolic links""" + try: + os.stat(path) + except OSError: + return False + return True + + +# This follows symbolic links, so both islink() and isdir() can be true +# for the same path on systems that support symlinks +def isfile(path): + """Test whether a path is a regular file""" + try: + st = os.stat(path) + except OSError: + return False + return stat.S_ISREG(st.st_mode) + + +# Is a path a directory? +# This follows symbolic links, so both islink() and isdir() +# can be true for the same path on systems that support symlinks +def isdir(s): + """Return true if the pathname refers to an existing directory.""" + try: + st = os.stat(s) + except OSError: + return False + return stat.S_ISDIR(st.st_mode) + + +def getsize(filename): + """Return the size of a file, reported by os.stat().""" + return os.stat(filename).st_size + + +def getmtime(filename): + """Return the last modification time of a file, reported by os.stat().""" + return os.stat(filename).st_mtime + + +def getatime(filename): + """Return the last access time of a file, reported by os.stat().""" + return os.stat(filename).st_atime + + +def getctime(filename): + """Return the metadata change time of a file, reported by os.stat().""" + return os.stat(filename).st_ctime + + +# Return the longest prefix of all list elements. +def commonprefix(m): + "Given a list of pathnames, returns the longest common leading component" + if not m: return '' + # Some people pass in a list of pathname parts to operate in an OS-agnostic + # fashion; don't try to translate in that case as that's an abuse of the + # API and they are already doing what they need to be OS-agnostic and so + # they most likely won't be using an os.PathLike object in the sublists. + if not isinstance(m[0], (list, tuple)): + m = tuple(map(os.fspath, m)) + s1 = min(m) + s2 = max(m) + for i, c in enumerate(s1): + if c != s2[i]: + return s1[:i] + return s1 + +# Are two stat buffers (obtained from stat, fstat or lstat) +# describing the same file? +def samestat(s1, s2): + """Test whether two stat buffers reference the same file""" + return (s1.st_ino == s2.st_ino and + s1.st_dev == s2.st_dev) + + +# Are two filenames really pointing to the same file? +def samefile(f1, f2): + """Test whether two pathnames reference the same actual file""" + s1 = os.stat(f1) + s2 = os.stat(f2) + return samestat(s1, s2) + + +# Are two open files really referencing the same file? +# (Not necessarily the same file descriptor!) +def sameopenfile(fp1, fp2): + """Test whether two open file objects reference the same file""" + s1 = os.fstat(fp1) + s2 = os.fstat(fp2) + return samestat(s1, s2) + + +# Split a path in root and extension. +# The extension is everything starting at the last dot in the last +# pathname component; the root is everything before that. +# It is always true that root + ext == p. + +# Generic implementation of splitext, to be parametrized with +# the separators +def _splitext(p, sep, altsep, extsep): + """Split the extension from a pathname. + + Extension is everything from the last dot to the end, ignoring + leading dots. Returns "(root, ext)"; ext may be empty.""" + # NOTE: This code must work for text and bytes strings. + + sepIndex = p.rfind(sep) + if altsep: + altsepIndex = p.rfind(altsep) + sepIndex = max(sepIndex, altsepIndex) + + dotIndex = p.rfind(extsep) + if dotIndex > sepIndex: + # skip all leading dots + filenameIndex = sepIndex + 1 + while filenameIndex < dotIndex: + if p[filenameIndex:filenameIndex+1] != extsep: + return p[:dotIndex], p[dotIndex:] + filenameIndex += 1 + + return p, p[:0] + +def _check_arg_types(funcname, *args): + hasstr = hasbytes = False + for s in args: + if isinstance(s, str): + hasstr = True + elif isinstance(s, bytes): + hasbytes = True + else: + raise TypeError('%s() argument must be str or bytes, not %r' % + (funcname, s.__class__.__name__)) from None + if hasstr and hasbytes: + raise TypeError("Can't mix strings and bytes in path components") from None diff --git a/winvenv/Lib/hashlib.py b/winvenv/Lib/hashlib.py new file mode 100644 index 0000000..4e783a8 --- /dev/null +++ b/winvenv/Lib/hashlib.py @@ -0,0 +1,252 @@ +#. Copyright (C) 2005-2010 Gregory P. Smith (greg@krypto.org) +# Licensed to PSF under a Contributor Agreement. +# + +__doc__ = """hashlib module - A common interface to many hash functions. + +new(name, data=b'', **kwargs) - returns a new hash object implementing the + given hash function; initializing the hash + using the given binary data. + +Named constructor functions are also available, these are faster +than using new(name): + +md5(), sha1(), sha224(), sha256(), sha384(), sha512(), blake2b(), blake2s(), +sha3_224, sha3_256, sha3_384, sha3_512, shake_128, and shake_256. + +More algorithms may be available on your platform but the above are guaranteed +to exist. See the algorithms_guaranteed and algorithms_available attributes +to find out what algorithm names can be passed to new(). + +NOTE: If you want the adler32 or crc32 hash functions they are available in +the zlib module. + +Choose your hash function wisely. Some have known collision weaknesses. +sha384 and sha512 will be slow on 32 bit platforms. + +Hash objects have these methods: + - update(data): Update the hash object with the bytes in data. Repeated calls + are equivalent to a single call with the concatenation of all + the arguments. + - digest(): Return the digest of the bytes passed to the update() method + so far as a bytes object. + - hexdigest(): Like digest() except the digest is returned as a string + of double length, containing only hexadecimal digits. + - copy(): Return a copy (clone) of the hash object. This can be used to + efficiently compute the digests of datas that share a common + initial substring. + +For example, to obtain the digest of the byte string 'Nobody inspects the +spammish repetition': + + >>> import hashlib + >>> m = hashlib.md5() + >>> m.update(b"Nobody inspects") + >>> m.update(b" the spammish repetition") + >>> m.digest() + b'\\xbbd\\x9c\\x83\\xdd\\x1e\\xa5\\xc9\\xd9\\xde\\xc9\\xa1\\x8d\\xf0\\xff\\xe9' + +More condensed: + + >>> hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest() + 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2' + +""" + +# This tuple and __get_builtin_constructor() must be modified if a new +# always available algorithm is added. +__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', + 'blake2b', 'blake2s', + 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', + 'shake_128', 'shake_256') + + +algorithms_guaranteed = set(__always_supported) +algorithms_available = set(__always_supported) + +__all__ = __always_supported + ('new', 'algorithms_guaranteed', + 'algorithms_available', 'pbkdf2_hmac') + + +__builtin_constructor_cache = {} + +def __get_builtin_constructor(name): + cache = __builtin_constructor_cache + constructor = cache.get(name) + if constructor is not None: + return constructor + try: + if name in ('SHA1', 'sha1'): + import _sha1 + cache['SHA1'] = cache['sha1'] = _sha1.sha1 + elif name in ('MD5', 'md5'): + import _md5 + cache['MD5'] = cache['md5'] = _md5.md5 + elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): + import _sha256 + cache['SHA224'] = cache['sha224'] = _sha256.sha224 + cache['SHA256'] = cache['sha256'] = _sha256.sha256 + elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): + import _sha512 + cache['SHA384'] = cache['sha384'] = _sha512.sha384 + cache['SHA512'] = cache['sha512'] = _sha512.sha512 + elif name in ('blake2b', 'blake2s'): + import _blake2 + cache['blake2b'] = _blake2.blake2b + cache['blake2s'] = _blake2.blake2s + elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', + 'shake_128', 'shake_256'}: + import _sha3 + cache['sha3_224'] = _sha3.sha3_224 + cache['sha3_256'] = _sha3.sha3_256 + cache['sha3_384'] = _sha3.sha3_384 + cache['sha3_512'] = _sha3.sha3_512 + cache['shake_128'] = _sha3.shake_128 + cache['shake_256'] = _sha3.shake_256 + except ImportError: + pass # no extension module, this hash is unsupported. + + constructor = cache.get(name) + if constructor is not None: + return constructor + + raise ValueError('unsupported hash type ' + name) + + +def __get_openssl_constructor(name): + if name in {'blake2b', 'blake2s'}: + # Prefer our blake2 implementation. + return __get_builtin_constructor(name) + try: + f = getattr(_hashlib, 'openssl_' + name) + # Allow the C module to raise ValueError. The function will be + # defined but the hash not actually available thanks to OpenSSL. + f() + # Use the C function directly (very fast) + return f + except (AttributeError, ValueError): + return __get_builtin_constructor(name) + + +def __py_new(name, data=b'', **kwargs): + """new(name, data=b'', **kwargs) - Return a new hashing object using the + named algorithm; optionally initialized with data (which must be + a bytes-like object). + """ + return __get_builtin_constructor(name)(data, **kwargs) + + +def __hash_new(name, data=b'', **kwargs): + """new(name, data=b'') - Return a new hashing object using the named algorithm; + optionally initialized with data (which must be a bytes-like object). + """ + if name in {'blake2b', 'blake2s'}: + # Prefer our blake2 implementation. + # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s. + # It does neither support keyed blake2 nor advanced features like + # salt, personal, tree hashing or SSE. + return __get_builtin_constructor(name)(data, **kwargs) + try: + return _hashlib.new(name, data) + except ValueError: + # If the _hashlib module (OpenSSL) doesn't support the named + # hash, try using our builtin implementations. + # This allows for SHA224/256 and SHA384/512 support even though + # the OpenSSL library prior to 0.9.8 doesn't provide them. + return __get_builtin_constructor(name)(data) + + +try: + import _hashlib + new = __hash_new + __get_hash = __get_openssl_constructor + algorithms_available = algorithms_available.union( + _hashlib.openssl_md_meth_names) +except ImportError: + new = __py_new + __get_hash = __get_builtin_constructor + +try: + # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA + from _hashlib import pbkdf2_hmac +except ImportError: + _trans_5C = bytes((x ^ 0x5C) for x in range(256)) + _trans_36 = bytes((x ^ 0x36) for x in range(256)) + + def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None): + """Password based key derivation function 2 (PKCS #5 v2.0) + + This Python implementations based on the hmac module about as fast + as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster + for long passwords. + """ + if not isinstance(hash_name, str): + raise TypeError(hash_name) + + if not isinstance(password, (bytes, bytearray)): + password = bytes(memoryview(password)) + if not isinstance(salt, (bytes, bytearray)): + salt = bytes(memoryview(salt)) + + # Fast inline HMAC implementation + inner = new(hash_name) + outer = new(hash_name) + blocksize = getattr(inner, 'block_size', 64) + if len(password) > blocksize: + password = new(hash_name, password).digest() + password = password + b'\x00' * (blocksize - len(password)) + inner.update(password.translate(_trans_36)) + outer.update(password.translate(_trans_5C)) + + def prf(msg, inner=inner, outer=outer): + # PBKDF2_HMAC uses the password as key. We can re-use the same + # digest objects and just update copies to skip initialization. + icpy = inner.copy() + ocpy = outer.copy() + icpy.update(msg) + ocpy.update(icpy.digest()) + return ocpy.digest() + + if iterations < 1: + raise ValueError(iterations) + if dklen is None: + dklen = outer.digest_size + if dklen < 1: + raise ValueError(dklen) + + dkey = b'' + loop = 1 + from_bytes = int.from_bytes + while len(dkey) < dklen: + prev = prf(salt + loop.to_bytes(4, 'big')) + # endianness doesn't matter here as long to / from use the same + rkey = int.from_bytes(prev, 'big') + for i in range(iterations - 1): + prev = prf(prev) + # rkey = rkey ^ prev + rkey ^= from_bytes(prev, 'big') + loop += 1 + dkey += rkey.to_bytes(inner.digest_size, 'big') + + return dkey[:dklen] + +try: + # OpenSSL's scrypt requires OpenSSL 1.1+ + from _hashlib import scrypt +except ImportError: + pass + + +for __func_name in __always_supported: + # try them all, some may not work due to the OpenSSL + # version not supporting that algorithm. + try: + globals()[__func_name] = __get_hash(__func_name) + except ValueError: + import logging + logging.exception('code for hash %s was not found.', __func_name) + + +# Cleanup locals() +del __always_supported, __func_name, __get_hash +del __py_new, __hash_new, __get_openssl_constructor diff --git a/winvenv/Lib/heapq.py b/winvenv/Lib/heapq.py new file mode 100644 index 0000000..b31f418 --- /dev/null +++ b/winvenv/Lib/heapq.py @@ -0,0 +1,607 @@ +"""Heap queue algorithm (a.k.a. priority queue). + +Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for +all k, counting elements from 0. For the sake of comparison, +non-existing elements are considered to be infinite. The interesting +property of a heap is that a[0] is always its smallest element. + +Usage: + +heap = [] # creates an empty heap +heappush(heap, item) # pushes a new item on the heap +item = heappop(heap) # pops the smallest item from the heap +item = heap[0] # smallest item on the heap without popping it +heapify(x) # transforms list into a heap, in-place, in linear time +item = heapreplace(heap, item) # pops and returns smallest item, and adds + # new item; the heap size is unchanged + +Our API differs from textbook heap algorithms as follows: + +- We use 0-based indexing. This makes the relationship between the + index for a node and the indexes for its children slightly less + obvious, but is more suitable since Python uses 0-based indexing. + +- Our heappop() method returns the smallest item, not the largest. + +These two make it possible to view the heap as a regular Python list +without surprises: heap[0] is the smallest item, and heap.sort() +maintains the heap invariant! +""" + +# Original code by Kevin O'Connor, augmented by Tim Peters and Raymond Hettinger + +__about__ = """Heap queues + +[explanation by François Pinard] + +Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for +all k, counting elements from 0. For the sake of comparison, +non-existing elements are considered to be infinite. The interesting +property of a heap is that a[0] is always its smallest element. + +The strange invariant above is meant to be an efficient memory +representation for a tournament. The numbers below are `k', not a[k]: + + 0 + + 1 2 + + 3 4 5 6 + + 7 8 9 10 11 12 13 14 + + 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 + + +In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In +a usual binary tournament we see in sports, each cell is the winner +over the two cells it tops, and we can trace the winner down the tree +to see all opponents s/he had. However, in many computer applications +of such tournaments, we do not need to trace the history of a winner. +To be more memory efficient, when a winner is promoted, we try to +replace it by something else at a lower level, and the rule becomes +that a cell and the two cells it tops contain three different items, +but the top cell "wins" over the two topped cells. + +If this heap invariant is protected at all time, index 0 is clearly +the overall winner. The simplest algorithmic way to remove it and +find the "next" winner is to move some loser (let's say cell 30 in the +diagram above) into the 0 position, and then percolate this new 0 down +the tree, exchanging values, until the invariant is re-established. +This is clearly logarithmic on the total number of items in the tree. +By iterating over all items, you get an O(n ln n) sort. + +A nice feature of this sort is that you can efficiently insert new +items while the sort is going on, provided that the inserted items are +not "better" than the last 0'th element you extracted. This is +especially useful in simulation contexts, where the tree holds all +incoming events, and the "win" condition means the smallest scheduled +time. When an event schedule other events for execution, they are +scheduled into the future, so they can easily go into the heap. So, a +heap is a good structure for implementing schedulers (this is what I +used for my MIDI sequencer :-). + +Various structures for implementing schedulers have been extensively +studied, and heaps are good for this, as they are reasonably speedy, +the speed is almost constant, and the worst case is not much different +than the average case. However, there are other representations which +are more efficient overall, yet the worst cases might be terrible. + +Heaps are also very useful in big disk sorts. You most probably all +know that a big sort implies producing "runs" (which are pre-sorted +sequences, which size is usually related to the amount of CPU memory), +followed by a merging passes for these runs, which merging is often +very cleverly organised[1]. It is very important that the initial +sort produces the longest runs possible. Tournaments are a good way +to that. If, using all the memory available to hold a tournament, you +replace and percolate items that happen to fit the current run, you'll +produce runs which are twice the size of the memory for random input, +and much better for input fuzzily ordered. + +Moreover, if you output the 0'th item on disk and get an input which +may not fit in the current tournament (because the value "wins" over +the last output value), it cannot fit in the heap, so the size of the +heap decreases. The freed memory could be cleverly reused immediately +for progressively building a second heap, which grows at exactly the +same rate the first heap is melting. When the first heap completely +vanishes, you switch heaps and start a new run. Clever and quite +effective! + +In a word, heaps are useful memory structures to know. I use them in +a few applications, and I think it is good to keep a `heap' module +around. :-) + +-------------------- +[1] The disk balancing algorithms which are current, nowadays, are +more annoying than clever, and this is a consequence of the seeking +capabilities of the disks. On devices which cannot seek, like big +tape drives, the story was quite different, and one had to be very +clever to ensure (far in advance) that each tape movement will be the +most effective possible (that is, will best participate at +"progressing" the merge). Some tapes were even able to read +backwards, and this was also used to avoid the rewinding time. +Believe me, real good tape sorts were quite spectacular to watch! +From all times, sorting has always been a Great Art! :-) +""" + +__all__ = ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', + 'nlargest', 'nsmallest', 'heappushpop'] + +def heappush(heap, item): + """Push item onto heap, maintaining the heap invariant.""" + heap.append(item) + _siftdown(heap, 0, len(heap)-1) + +def heappop(heap): + """Pop the smallest item off the heap, maintaining the heap invariant.""" + lastelt = heap.pop() # raises appropriate IndexError if heap is empty + if heap: + returnitem = heap[0] + heap[0] = lastelt + _siftup(heap, 0) + return returnitem + return lastelt + +def heapreplace(heap, item): + """Pop and return the current smallest value, and add the new item. + + This is more efficient than heappop() followed by heappush(), and can be + more appropriate when using a fixed-size heap. Note that the value + returned may be larger than item! That constrains reasonable uses of + this routine unless written as part of a conditional replacement: + + if item > heap[0]: + item = heapreplace(heap, item) + """ + returnitem = heap[0] # raises appropriate IndexError if heap is empty + heap[0] = item + _siftup(heap, 0) + return returnitem + +def heappushpop(heap, item): + """Fast version of a heappush followed by a heappop.""" + if heap and heap[0] < item: + item, heap[0] = heap[0], item + _siftup(heap, 0) + return item + +def heapify(x): + """Transform list into a heap, in-place, in O(len(x)) time.""" + n = len(x) + # Transform bottom-up. The largest index there's any point to looking at + # is the largest with a child index in-range, so must have 2*i + 1 < n, + # or i < (n-1)/2. If n is even = 2*j, this is (2*j-1)/2 = j-1/2 so + # j-1 is the largest, which is n//2 - 1. If n is odd = 2*j+1, this is + # (2*j+1-1)/2 = j so j-1 is the largest, and that's again n//2-1. + for i in reversed(range(n//2)): + _siftup(x, i) + +def _heappop_max(heap): + """Maxheap version of a heappop.""" + lastelt = heap.pop() # raises appropriate IndexError if heap is empty + if heap: + returnitem = heap[0] + heap[0] = lastelt + _siftup_max(heap, 0) + return returnitem + return lastelt + +def _heapreplace_max(heap, item): + """Maxheap version of a heappop followed by a heappush.""" + returnitem = heap[0] # raises appropriate IndexError if heap is empty + heap[0] = item + _siftup_max(heap, 0) + return returnitem + +def _heapify_max(x): + """Transform list into a maxheap, in-place, in O(len(x)) time.""" + n = len(x) + for i in reversed(range(n//2)): + _siftup_max(x, i) + +# 'heap' is a heap at all indices >= startpos, except possibly for pos. pos +# is the index of a leaf with a possibly out-of-order value. Restore the +# heap invariant. +def _siftdown(heap, startpos, pos): + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if newitem < parent: + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +# The child indices of heap index pos are already heaps, and we want to make +# a heap at index pos too. We do this by bubbling the smaller child of +# pos up (and so on with that child's children, etc) until hitting a leaf, +# then using _siftdown to move the oddball originally at index pos into place. +# +# We *could* break out of the loop as soon as we find a pos where newitem <= +# both its children, but turns out that's not a good idea, and despite that +# many books write the algorithm that way. During a heap pop, the last array +# element is sifted in, and that tends to be large, so that comparing it +# against values starting from the root usually doesn't pay (= usually doesn't +# get us out of the loop early). See Knuth, Volume 3, where this is +# explained and quantified in an exercise. +# +# Cutting the # of comparisons is important, since these routines have no +# way to extract "the priority" from an array element, so that intelligence +# is likely to be hiding in custom comparison methods, or in array elements +# storing (priority, record) tuples. Comparisons are thus potentially +# expensive. +# +# On random arrays of length 1000, making this change cut the number of +# comparisons made by heapify() a little, and those made by exhaustive +# heappop() a lot, in accord with theory. Here are typical results from 3 +# runs (3 just to demonstrate how small the variance is): +# +# Compares needed by heapify Compares needed by 1000 heappops +# -------------------------- -------------------------------- +# 1837 cut to 1663 14996 cut to 8680 +# 1855 cut to 1659 14966 cut to 8678 +# 1847 cut to 1660 15024 cut to 8703 +# +# Building the heap by using heappush() 1000 times instead required +# 2198, 2148, and 2219 compares: heapify() is more efficient, when +# you can use it. +# +# The total compares needed by list.sort() on the same lists were 8627, +# 8627, and 8632 (this should be compared to the sum of heapify() and +# heappop() compares): list.sort() is (unsurprisingly!) more efficient +# for sorting. + +def _siftup(heap, pos): + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the smaller child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of smaller child. + rightpos = childpos + 1 + if rightpos < endpos and not heap[childpos] < heap[rightpos]: + childpos = rightpos + # Move the smaller child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown(heap, startpos, pos) + +def _siftdown_max(heap, startpos, pos): + 'Maxheap variant of _siftdown' + newitem = heap[pos] + # Follow the path to the root, moving parents down until finding a place + # newitem fits. + while pos > startpos: + parentpos = (pos - 1) >> 1 + parent = heap[parentpos] + if parent < newitem: + heap[pos] = parent + pos = parentpos + continue + break + heap[pos] = newitem + +def _siftup_max(heap, pos): + 'Maxheap variant of _siftup' + endpos = len(heap) + startpos = pos + newitem = heap[pos] + # Bubble up the larger child until hitting a leaf. + childpos = 2*pos + 1 # leftmost child position + while childpos < endpos: + # Set childpos to index of larger child. + rightpos = childpos + 1 + if rightpos < endpos and not heap[rightpos] < heap[childpos]: + childpos = rightpos + # Move the larger child up. + heap[pos] = heap[childpos] + pos = childpos + childpos = 2*pos + 1 + # The leaf at pos is empty now. Put newitem there, and bubble it up + # to its final resting place (by sifting its parents down). + heap[pos] = newitem + _siftdown_max(heap, startpos, pos) + +def merge(*iterables, key=None, reverse=False): + '''Merge multiple sorted inputs into a single sorted output. + + Similar to sorted(itertools.chain(*iterables)) but returns a generator, + does not pull the data into memory all at once, and assumes that each of + the input streams is already sorted (smallest to largest). + + >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25])) + [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25] + + If *key* is not None, applies a key function to each element to determine + its sort order. + + >>> list(merge(['dog', 'horse'], ['cat', 'fish', 'kangaroo'], key=len)) + ['dog', 'cat', 'fish', 'horse', 'kangaroo'] + + ''' + + h = [] + h_append = h.append + + if reverse: + _heapify = _heapify_max + _heappop = _heappop_max + _heapreplace = _heapreplace_max + direction = -1 + else: + _heapify = heapify + _heappop = heappop + _heapreplace = heapreplace + direction = 1 + + if key is None: + for order, it in enumerate(map(iter, iterables)): + try: + next = it.__next__ + h_append([next(), order * direction, next]) + except StopIteration: + pass + _heapify(h) + while len(h) > 1: + try: + while True: + value, order, next = s = h[0] + yield value + s[0] = next() # raises StopIteration when exhausted + _heapreplace(h, s) # restore heap condition + except StopIteration: + _heappop(h) # remove empty iterator + if h: + # fast case when only a single iterator remains + value, order, next = h[0] + yield value + yield from next.__self__ + return + + for order, it in enumerate(map(iter, iterables)): + try: + next = it.__next__ + value = next() + h_append([key(value), order * direction, value, next]) + except StopIteration: + pass + _heapify(h) + while len(h) > 1: + try: + while True: + key_value, order, value, next = s = h[0] + yield value + value = next() + s[0] = key(value) + s[2] = value + _heapreplace(h, s) + except StopIteration: + _heappop(h) + if h: + key_value, order, value, next = h[0] + yield value + yield from next.__self__ + + +# Algorithm notes for nlargest() and nsmallest() +# ============================================== +# +# Make a single pass over the data while keeping the k most extreme values +# in a heap. Memory consumption is limited to keeping k values in a list. +# +# Measured performance for random inputs: +# +# number of comparisons +# n inputs k-extreme values (average of 5 trials) % more than min() +# ------------- ---------------- --------------------- ----------------- +# 1,000 100 3,317 231.7% +# 10,000 100 14,046 40.5% +# 100,000 100 105,749 5.7% +# 1,000,000 100 1,007,751 0.8% +# 10,000,000 100 10,009,401 0.1% +# +# Theoretical number of comparisons for k smallest of n random inputs: +# +# Step Comparisons Action +# ---- -------------------------- --------------------------- +# 1 1.66 * k heapify the first k-inputs +# 2 n - k compare remaining elements to top of heap +# 3 k * (1 + lg2(k)) * ln(n/k) replace the topmost value on the heap +# 4 k * lg2(k) - (k/2) final sort of the k most extreme values +# +# Combining and simplifying for a rough estimate gives: +# +# comparisons = n + k * (log(k, 2) * log(n/k) + log(k, 2) + log(n/k)) +# +# Computing the number of comparisons for step 3: +# ----------------------------------------------- +# * For the i-th new value from the iterable, the probability of being in the +# k most extreme values is k/i. For example, the probability of the 101st +# value seen being in the 100 most extreme values is 100/101. +# * If the value is a new extreme value, the cost of inserting it into the +# heap is 1 + log(k, 2). +# * The probability times the cost gives: +# (k/i) * (1 + log(k, 2)) +# * Summing across the remaining n-k elements gives: +# sum((k/i) * (1 + log(k, 2)) for i in range(k+1, n+1)) +# * This reduces to: +# (H(n) - H(k)) * k * (1 + log(k, 2)) +# * Where H(n) is the n-th harmonic number estimated by: +# gamma = 0.5772156649 +# H(n) = log(n, e) + gamma + 1 / (2 * n) +# http://en.wikipedia.org/wiki/Harmonic_series_(mathematics)#Rate_of_divergence +# * Substituting the H(n) formula: +# comparisons = k * (1 + log(k, 2)) * (log(n/k, e) + (1/n - 1/k) / 2) +# +# Worst-case for step 3: +# ---------------------- +# In the worst case, the input data is reversed sorted so that every new element +# must be inserted in the heap: +# +# comparisons = 1.66 * k + log(k, 2) * (n - k) +# +# Alternative Algorithms +# ---------------------- +# Other algorithms were not used because they: +# 1) Took much more auxiliary memory, +# 2) Made multiple passes over the data. +# 3) Made more comparisons in common cases (small k, large n, semi-random input). +# See the more detailed comparison of approach at: +# http://code.activestate.com/recipes/577573-compare-algorithms-for-heapqsmallest + +def nsmallest(n, iterable, key=None): + """Find the n smallest elements in a dataset. + + Equivalent to: sorted(iterable, key=key)[:n] + """ + + # Short-cut for n==1 is to use min() + if n == 1: + it = iter(iterable) + sentinel = object() + if key is None: + result = min(it, default=sentinel) + else: + result = min(it, default=sentinel, key=key) + return [] if result is sentinel else [result] + + # When n>=size, it's faster to use sorted() + try: + size = len(iterable) + except (TypeError, AttributeError): + pass + else: + if n >= size: + return sorted(iterable, key=key)[:n] + + # When key is none, use simpler decoration + if key is None: + it = iter(iterable) + # put the range(n) first so that zip() doesn't + # consume one too many elements from the iterator + result = [(elem, i) for i, elem in zip(range(n), it)] + if not result: + return result + _heapify_max(result) + top = result[0][0] + order = n + _heapreplace = _heapreplace_max + for elem in it: + if elem < top: + _heapreplace(result, (elem, order)) + top, _order = result[0] + order += 1 + result.sort() + return [elem for (elem, order) in result] + + # General case, slowest method + it = iter(iterable) + result = [(key(elem), i, elem) for i, elem in zip(range(n), it)] + if not result: + return result + _heapify_max(result) + top = result[0][0] + order = n + _heapreplace = _heapreplace_max + for elem in it: + k = key(elem) + if k < top: + _heapreplace(result, (k, order, elem)) + top, _order, _elem = result[0] + order += 1 + result.sort() + return [elem for (k, order, elem) in result] + +def nlargest(n, iterable, key=None): + """Find the n largest elements in a dataset. + + Equivalent to: sorted(iterable, key=key, reverse=True)[:n] + """ + + # Short-cut for n==1 is to use max() + if n == 1: + it = iter(iterable) + sentinel = object() + if key is None: + result = max(it, default=sentinel) + else: + result = max(it, default=sentinel, key=key) + return [] if result is sentinel else [result] + + # When n>=size, it's faster to use sorted() + try: + size = len(iterable) + except (TypeError, AttributeError): + pass + else: + if n >= size: + return sorted(iterable, key=key, reverse=True)[:n] + + # When key is none, use simpler decoration + if key is None: + it = iter(iterable) + result = [(elem, i) for i, elem in zip(range(0, -n, -1), it)] + if not result: + return result + heapify(result) + top = result[0][0] + order = -n + _heapreplace = heapreplace + for elem in it: + if top < elem: + _heapreplace(result, (elem, order)) + top, _order = result[0] + order -= 1 + result.sort(reverse=True) + return [elem for (elem, order) in result] + + # General case, slowest method + it = iter(iterable) + result = [(key(elem), i, elem) for i, elem in zip(range(0, -n, -1), it)] + if not result: + return result + heapify(result) + top = result[0][0] + order = -n + _heapreplace = heapreplace + for elem in it: + k = key(elem) + if top < k: + _heapreplace(result, (k, order, elem)) + top, _order, _elem = result[0] + order -= 1 + result.sort(reverse=True) + return [elem for (k, order, elem) in result] + +# If available, use C implementation +try: + from _heapq import * +except ImportError: + pass +try: + from _heapq import _heapreplace_max +except ImportError: + pass +try: + from _heapq import _heapify_max +except ImportError: + pass +try: + from _heapq import _heappop_max +except ImportError: + pass + + +if __name__ == "__main__": + + import doctest + print(doctest.testmod()) diff --git a/winvenv/Lib/hmac.py b/winvenv/Lib/hmac.py new file mode 100644 index 0000000..43b7212 --- /dev/null +++ b/winvenv/Lib/hmac.py @@ -0,0 +1,188 @@ +"""HMAC (Keyed-Hashing for Message Authentication) Python module. + +Implements the HMAC algorithm as described by RFC 2104. +""" + +import warnings as _warnings +from _operator import _compare_digest as compare_digest +try: + import _hashlib as _hashopenssl +except ImportError: + _hashopenssl = None + _openssl_md_meths = None +else: + _openssl_md_meths = frozenset(_hashopenssl.openssl_md_meth_names) +import hashlib as _hashlib + +trans_5C = bytes((x ^ 0x5C) for x in range(256)) +trans_36 = bytes((x ^ 0x36) for x in range(256)) + +# The size of the digests returned by HMAC depends on the underlying +# hashing module used. Use digest_size from the instance of HMAC instead. +digest_size = None + + + +class HMAC: + """RFC 2104 HMAC class. Also complies with RFC 4231. + + This supports the API for Cryptographic Hash Functions (PEP 247). + """ + blocksize = 64 # 512-bit HMAC; can be changed in subclasses. + + def __init__(self, key, msg = None, digestmod = None): + """Create a new HMAC object. + + key: key for the keyed hash object. + msg: Initial input for the hash, if provided. + digestmod: A module supporting PEP 247. *OR* + A hashlib constructor returning a new hash object. *OR* + A hash name suitable for hashlib.new(). + Defaults to hashlib.md5. + Implicit default to hashlib.md5 is deprecated since Python + 3.4 and will be removed in Python 3.8. + + Note: key and msg must be a bytes or bytearray objects. + """ + + if not isinstance(key, (bytes, bytearray)): + raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__) + + if digestmod is None: + _warnings.warn("HMAC() without an explicit digestmod argument " + "is deprecated since Python 3.4, and will be removed " + "in 3.8", + DeprecationWarning, 2) + digestmod = _hashlib.md5 + + if callable(digestmod): + self.digest_cons = digestmod + elif isinstance(digestmod, str): + self.digest_cons = lambda d=b'': _hashlib.new(digestmod, d) + else: + self.digest_cons = lambda d=b'': digestmod.new(d) + + self.outer = self.digest_cons() + self.inner = self.digest_cons() + self.digest_size = self.inner.digest_size + + if hasattr(self.inner, 'block_size'): + blocksize = self.inner.block_size + if blocksize < 16: + _warnings.warn('block_size of %d seems too small; using our ' + 'default of %d.' % (blocksize, self.blocksize), + RuntimeWarning, 2) + blocksize = self.blocksize + else: + _warnings.warn('No block_size attribute on given digest object; ' + 'Assuming %d.' % (self.blocksize), + RuntimeWarning, 2) + blocksize = self.blocksize + + # self.blocksize is the default blocksize. self.block_size is + # effective block size as well as the public API attribute. + self.block_size = blocksize + + if len(key) > blocksize: + key = self.digest_cons(key).digest() + + key = key.ljust(blocksize, b'\0') + self.outer.update(key.translate(trans_5C)) + self.inner.update(key.translate(trans_36)) + if msg is not None: + self.update(msg) + + @property + def name(self): + return "hmac-" + self.inner.name + + def update(self, msg): + """Update this hashing object with the string msg. + """ + self.inner.update(msg) + + def copy(self): + """Return a separate copy of this hashing object. + + An update to this copy won't affect the original object. + """ + # Call __new__ directly to avoid the expensive __init__. + other = self.__class__.__new__(self.__class__) + other.digest_cons = self.digest_cons + other.digest_size = self.digest_size + other.inner = self.inner.copy() + other.outer = self.outer.copy() + return other + + def _current(self): + """Return a hash object for the current state. + + To be used only internally with digest() and hexdigest(). + """ + h = self.outer.copy() + h.update(self.inner.digest()) + return h + + def digest(self): + """Return the hash value of this hashing object. + + This returns a string containing 8-bit data. The object is + not altered in any way by this function; you can continue + updating the object after calling this function. + """ + h = self._current() + return h.digest() + + def hexdigest(self): + """Like digest(), but returns a string of hexadecimal digits instead. + """ + h = self._current() + return h.hexdigest() + +def new(key, msg = None, digestmod = None): + """Create a new hashing object and return it. + + key: The starting key for the hash. + msg: if available, will immediately be hashed into the object's starting + state. + + You can now feed arbitrary strings into the object using its update() + method, and can ask for the hash value at any time by calling its digest() + method. + """ + return HMAC(key, msg, digestmod) + + +def digest(key, msg, digest): + """Fast inline implementation of HMAC + + key: key for the keyed hash object. + msg: input message + digest: A hash name suitable for hashlib.new() for best performance. *OR* + A hashlib constructor returning a new hash object. *OR* + A module supporting PEP 247. + + Note: key and msg must be a bytes or bytearray objects. + """ + if (_hashopenssl is not None and + isinstance(digest, str) and digest in _openssl_md_meths): + return _hashopenssl.hmac_digest(key, msg, digest) + + if callable(digest): + digest_cons = digest + elif isinstance(digest, str): + digest_cons = lambda d=b'': _hashlib.new(digest, d) + else: + digest_cons = lambda d=b'': digest.new(d) + + inner = digest_cons() + outer = digest_cons() + blocksize = getattr(inner, 'block_size', 64) + if len(key) > blocksize: + key = digest_cons(key).digest() + key = key + b'\x00' * (blocksize - len(key)) + inner.update(key.translate(trans_36)) + outer.update(key.translate(trans_5C)) + inner.update(msg) + outer.update(inner.digest()) + return outer.digest() diff --git a/winvenv/Lib/imp.py b/winvenv/Lib/imp.py new file mode 100644 index 0000000..31f8c76 --- /dev/null +++ b/winvenv/Lib/imp.py @@ -0,0 +1,345 @@ +"""This module provides the components needed to build your own __import__ +function. Undocumented functions are obsolete. + +In most cases it is preferred you consider using the importlib module's +functionality over this module. + +""" +# (Probably) need to stay in _imp +from _imp import (lock_held, acquire_lock, release_lock, + get_frozen_object, is_frozen_package, + init_frozen, is_builtin, is_frozen, + _fix_co_filename) +try: + from _imp import create_dynamic +except ImportError: + # Platform doesn't support dynamic loading. + create_dynamic = None + +from importlib._bootstrap import _ERR_MSG, _exec, _load, _builtin_from_name +from importlib._bootstrap_external import SourcelessFileLoader + +from importlib import machinery +from importlib import util +import importlib +import os +import sys +import tokenize +import types +import warnings + +warnings.warn("the imp module is deprecated in favour of importlib; " + "see the module's documentation for alternative uses", + DeprecationWarning, stacklevel=2) + +# DEPRECATED +SEARCH_ERROR = 0 +PY_SOURCE = 1 +PY_COMPILED = 2 +C_EXTENSION = 3 +PY_RESOURCE = 4 +PKG_DIRECTORY = 5 +C_BUILTIN = 6 +PY_FROZEN = 7 +PY_CODERESOURCE = 8 +IMP_HOOK = 9 + + +def new_module(name): + """**DEPRECATED** + + Create a new module. + + The module is not entered into sys.modules. + + """ + return types.ModuleType(name) + + +def get_magic(): + """**DEPRECATED** + + Return the magic number for .pyc files. + """ + return util.MAGIC_NUMBER + + +def get_tag(): + """Return the magic tag for .pyc files.""" + return sys.implementation.cache_tag + + +def cache_from_source(path, debug_override=None): + """**DEPRECATED** + + Given the path to a .py file, return the path to its .pyc file. + + The .py file does not need to exist; this simply returns the path to the + .pyc file calculated as if the .py file were imported. + + If debug_override is not None, then it must be a boolean and is used in + place of sys.flags.optimize. + + If sys.implementation.cache_tag is None then NotImplementedError is raised. + + """ + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + return util.cache_from_source(path, debug_override) + + +def source_from_cache(path): + """**DEPRECATED** + + Given the path to a .pyc. file, return the path to its .py file. + + The .pyc file does not need to exist; this simply returns the path to + the .py file calculated to correspond to the .pyc file. If path does + not conform to PEP 3147 format, ValueError will be raised. If + sys.implementation.cache_tag is None then NotImplementedError is raised. + + """ + return util.source_from_cache(path) + + +def get_suffixes(): + """**DEPRECATED**""" + extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES] + source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES] + bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES] + + return extensions + source + bytecode + + +class NullImporter: + + """**DEPRECATED** + + Null import object. + + """ + + def __init__(self, path): + if path == '': + raise ImportError('empty pathname', path='') + elif os.path.isdir(path): + raise ImportError('existing directory', path=path) + + def find_module(self, fullname): + """Always returns None.""" + return None + + +class _HackedGetData: + + """Compatibility support for 'file' arguments of various load_*() + functions.""" + + def __init__(self, fullname, path, file=None): + super().__init__(fullname, path) + self.file = file + + def get_data(self, path): + """Gross hack to contort loader to deal w/ load_*()'s bad API.""" + if self.file and path == self.path: + # The contract of get_data() requires us to return bytes. Reopen the + # file in binary mode if needed. + if not self.file.closed: + file = self.file + if 'b' not in file.mode: + file.close() + if self.file.closed: + self.file = file = open(self.path, 'rb') + + with file: + return file.read() + else: + return super().get_data(path) + + +class _LoadSourceCompatibility(_HackedGetData, machinery.SourceFileLoader): + + """Compatibility support for implementing load_source().""" + + +def load_source(name, pathname, file=None): + loader = _LoadSourceCompatibility(name, pathname, file) + spec = util.spec_from_file_location(name, pathname, loader=loader) + if name in sys.modules: + module = _exec(spec, sys.modules[name]) + else: + module = _load(spec) + # To allow reloading to potentially work, use a non-hacked loader which + # won't rely on a now-closed file object. + module.__loader__ = machinery.SourceFileLoader(name, pathname) + module.__spec__.loader = module.__loader__ + return module + + +class _LoadCompiledCompatibility(_HackedGetData, SourcelessFileLoader): + + """Compatibility support for implementing load_compiled().""" + + +def load_compiled(name, pathname, file=None): + """**DEPRECATED**""" + loader = _LoadCompiledCompatibility(name, pathname, file) + spec = util.spec_from_file_location(name, pathname, loader=loader) + if name in sys.modules: + module = _exec(spec, sys.modules[name]) + else: + module = _load(spec) + # To allow reloading to potentially work, use a non-hacked loader which + # won't rely on a now-closed file object. + module.__loader__ = SourcelessFileLoader(name, pathname) + module.__spec__.loader = module.__loader__ + return module + + +def load_package(name, path): + """**DEPRECATED**""" + if os.path.isdir(path): + extensions = (machinery.SOURCE_SUFFIXES[:] + + machinery.BYTECODE_SUFFIXES[:]) + for extension in extensions: + init_path = os.path.join(path, '__init__' + extension) + if os.path.exists(init_path): + path = init_path + break + else: + raise ValueError('{!r} is not a package'.format(path)) + spec = util.spec_from_file_location(name, path, + submodule_search_locations=[]) + if name in sys.modules: + return _exec(spec, sys.modules[name]) + else: + return _load(spec) + + +def load_module(name, file, filename, details): + """**DEPRECATED** + + Load a module, given information returned by find_module(). + + The module name must include the full package name, if any. + + """ + suffix, mode, type_ = details + if mode and (not mode.startswith(('r', 'U')) or '+' in mode): + raise ValueError('invalid file open mode {!r}'.format(mode)) + elif file is None and type_ in {PY_SOURCE, PY_COMPILED}: + msg = 'file object required for import (type code {})'.format(type_) + raise ValueError(msg) + elif type_ == PY_SOURCE: + return load_source(name, filename, file) + elif type_ == PY_COMPILED: + return load_compiled(name, filename, file) + elif type_ == C_EXTENSION and load_dynamic is not None: + if file is None: + with open(filename, 'rb') as opened_file: + return load_dynamic(name, filename, opened_file) + else: + return load_dynamic(name, filename, file) + elif type_ == PKG_DIRECTORY: + return load_package(name, filename) + elif type_ == C_BUILTIN: + return init_builtin(name) + elif type_ == PY_FROZEN: + return init_frozen(name) + else: + msg = "Don't know how to import {} (type code {})".format(name, type_) + raise ImportError(msg, name=name) + + +def find_module(name, path=None): + """**DEPRECATED** + + Search for a module. + + If path is omitted or None, search for a built-in, frozen or special + module and continue search in sys.path. The module name cannot + contain '.'; to search for a submodule of a package, pass the + submodule name and the package's __path__. + + """ + if not isinstance(name, str): + raise TypeError("'name' must be a str, not {}".format(type(name))) + elif not isinstance(path, (type(None), list)): + # Backwards-compatibility + raise RuntimeError("'path' must be None or a list, " + "not {}".format(type(path))) + + if path is None: + if is_builtin(name): + return None, None, ('', '', C_BUILTIN) + elif is_frozen(name): + return None, None, ('', '', PY_FROZEN) + else: + path = sys.path + + for entry in path: + package_directory = os.path.join(entry, name) + for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]: + package_file_name = '__init__' + suffix + file_path = os.path.join(package_directory, package_file_name) + if os.path.isfile(file_path): + return None, package_directory, ('', '', PKG_DIRECTORY) + for suffix, mode, type_ in get_suffixes(): + file_name = name + suffix + file_path = os.path.join(entry, file_name) + if os.path.isfile(file_path): + break + else: + continue + break # Break out of outer loop when breaking out of inner loop. + else: + raise ImportError(_ERR_MSG.format(name), name=name) + + encoding = None + if 'b' not in mode: + with open(file_path, 'rb') as file: + encoding = tokenize.detect_encoding(file.readline)[0] + file = open(file_path, mode, encoding=encoding) + return file, file_path, (suffix, mode, type_) + + +def reload(module): + """**DEPRECATED** + + Reload the module and return it. + + The module must have been successfully imported before. + + """ + return importlib.reload(module) + + +def init_builtin(name): + """**DEPRECATED** + + Load and return a built-in module by name, or None is such module doesn't + exist + """ + try: + return _builtin_from_name(name) + except ImportError: + return None + + +if create_dynamic: + def load_dynamic(name, path, file=None): + """**DEPRECATED** + + Load an extension module. + """ + import importlib.machinery + loader = importlib.machinery.ExtensionFileLoader(name, path) + + # Issue #24748: Skip the sys.modules check in _load_module_shim; + # always load new extension + spec = importlib.machinery.ModuleSpec( + name=name, loader=loader, origin=path) + return _load(spec) + +else: + load_dynamic = None diff --git a/winvenv/Lib/importlib/__init__.py b/winvenv/Lib/importlib/__init__.py new file mode 100644 index 0000000..cb37d24 --- /dev/null +++ b/winvenv/Lib/importlib/__init__.py @@ -0,0 +1,176 @@ +"""A pure Python implementation of import.""" +__all__ = ['__import__', 'import_module', 'invalidate_caches', 'reload'] + +# Bootstrap help ##################################################### + +# Until bootstrapping is complete, DO NOT import any modules that attempt +# to import importlib._bootstrap (directly or indirectly). Since this +# partially initialised package would be present in sys.modules, those +# modules would get an uninitialised copy of the source version, instead +# of a fully initialised version (either the frozen one or the one +# initialised below if the frozen one is not available). +import _imp # Just the builtin component, NOT the full Python module +import sys + +try: + import _frozen_importlib as _bootstrap +except ImportError: + from . import _bootstrap + _bootstrap._setup(sys, _imp) +else: + # importlib._bootstrap is the built-in import, ensure we don't create + # a second copy of the module. + _bootstrap.__name__ = 'importlib._bootstrap' + _bootstrap.__package__ = 'importlib' + try: + _bootstrap.__file__ = __file__.replace('__init__.py', '_bootstrap.py') + except NameError: + # __file__ is not guaranteed to be defined, e.g. if this code gets + # frozen by a tool like cx_Freeze. + pass + sys.modules['importlib._bootstrap'] = _bootstrap + +try: + import _frozen_importlib_external as _bootstrap_external +except ImportError: + from . import _bootstrap_external + _bootstrap_external._setup(_bootstrap) + _bootstrap._bootstrap_external = _bootstrap_external +else: + _bootstrap_external.__name__ = 'importlib._bootstrap_external' + _bootstrap_external.__package__ = 'importlib' + try: + _bootstrap_external.__file__ = __file__.replace('__init__.py', '_bootstrap_external.py') + except NameError: + # __file__ is not guaranteed to be defined, e.g. if this code gets + # frozen by a tool like cx_Freeze. + pass + sys.modules['importlib._bootstrap_external'] = _bootstrap_external + +# To simplify imports in test code +_w_long = _bootstrap_external._w_long +_r_long = _bootstrap_external._r_long + +# Fully bootstrapped at this point, import whatever you like, circular +# dependencies and startup overhead minimisation permitting :) + +import types +import warnings + + +# Public API ######################################################### + +from ._bootstrap import __import__ + + +def invalidate_caches(): + """Call the invalidate_caches() method on all meta path finders stored in + sys.meta_path (where implemented).""" + for finder in sys.meta_path: + if hasattr(finder, 'invalidate_caches'): + finder.invalidate_caches() + + +def find_loader(name, path=None): + """Return the loader for the specified module. + + This is a backward-compatible wrapper around find_spec(). + + This function is deprecated in favor of importlib.util.find_spec(). + + """ + warnings.warn('Deprecated since Python 3.4. ' + 'Use importlib.util.find_spec() instead.', + DeprecationWarning, stacklevel=2) + try: + loader = sys.modules[name].__loader__ + if loader is None: + raise ValueError('{}.__loader__ is None'.format(name)) + else: + return loader + except KeyError: + pass + except AttributeError: + raise ValueError('{}.__loader__ is not set'.format(name)) from None + + spec = _bootstrap._find_spec(name, path) + # We won't worry about malformed specs (missing attributes). + if spec is None: + return None + if spec.loader is None: + if spec.submodule_search_locations is None: + raise ImportError('spec for {} missing loader'.format(name), + name=name) + raise ImportError('namespace packages do not have loaders', + name=name) + return spec.loader + + +def import_module(name, package=None): + """Import a module. + + The 'package' argument is required when performing a relative import. It + specifies the package to use as the anchor point from which to resolve the + relative import to an absolute import. + + """ + level = 0 + if name.startswith('.'): + if not package: + msg = ("the 'package' argument is required to perform a relative " + "import for {!r}") + raise TypeError(msg.format(name)) + for character in name: + if character != '.': + break + level += 1 + return _bootstrap._gcd_import(name[level:], package, level) + + +_RELOADING = {} + + +def reload(module): + """Reload the module and return it. + + The module must have been successfully imported before. + + """ + if not module or not isinstance(module, types.ModuleType): + raise TypeError("reload() argument must be a module") + try: + name = module.__spec__.name + except AttributeError: + name = module.__name__ + + if sys.modules.get(name) is not module: + msg = "module {} not in sys.modules" + raise ImportError(msg.format(name), name=name) + if name in _RELOADING: + return _RELOADING[name] + _RELOADING[name] = module + try: + parent_name = name.rpartition('.')[0] + if parent_name: + try: + parent = sys.modules[parent_name] + except KeyError: + msg = "parent {!r} not in sys.modules" + raise ImportError(msg.format(parent_name), + name=parent_name) from None + else: + pkgpath = parent.__path__ + else: + pkgpath = None + target = module + spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target) + if spec is None: + raise ModuleNotFoundError(f"spec not found for the module {name!r}", name=name) + _bootstrap._exec(spec, module) + # The module may have replaced itself in sys.modules! + return sys.modules[name] + finally: + try: + del _RELOADING[name] + except KeyError: + pass diff --git a/winvenv/Lib/importlib/_bootstrap.py b/winvenv/Lib/importlib/_bootstrap.py new file mode 100644 index 0000000..2bdd192 --- /dev/null +++ b/winvenv/Lib/importlib/_bootstrap.py @@ -0,0 +1,1164 @@ +"""Core implementation of import. + +This module is NOT meant to be directly imported! It has been designed such +that it can be bootstrapped into Python as the implementation of import. As +such it requires the injection of specific modules and attributes in order to +work. One should use importlib as the public-facing version of this module. + +""" +# +# IMPORTANT: Whenever making changes to this module, be sure to run +# a top-level make in order to get the frozen version of the module +# updated. Not doing so will result in the Makefile to fail for +# all others who don't have a ./python around to freeze the module +# in the early stages of compilation. +# + +# See importlib._setup() for what is injected into the global namespace. + +# When editing this code be aware that code executed at import time CANNOT +# reference any injected objects! This includes not only global code but also +# anything specified at the class level. + +# Bootstrap-related code ###################################################### + +_bootstrap_external = None + +def _wrap(new, old): + """Simple substitute for functools.update_wrapper.""" + for replace in ['__module__', '__name__', '__qualname__', '__doc__']: + if hasattr(old, replace): + setattr(new, replace, getattr(old, replace)) + new.__dict__.update(old.__dict__) + + +def _new_module(name): + return type(sys)(name) + + +# Module-level locking ######################################################## + +# A dict mapping module names to weakrefs of _ModuleLock instances +# Dictionary protected by the global import lock +_module_locks = {} +# A dict mapping thread ids to _ModuleLock instances +_blocking_on = {} + + +class _DeadlockError(RuntimeError): + pass + + +class _ModuleLock: + """A recursive lock implementation which is able to detect deadlocks + (e.g. thread 1 trying to take locks A then B, and thread 2 trying to + take locks B then A). + """ + + def __init__(self, name): + self.lock = _thread.allocate_lock() + self.wakeup = _thread.allocate_lock() + self.name = name + self.owner = None + self.count = 0 + self.waiters = 0 + + def has_deadlock(self): + # Deadlock avoidance for concurrent circular imports. + me = _thread.get_ident() + tid = self.owner + while True: + lock = _blocking_on.get(tid) + if lock is None: + return False + tid = lock.owner + if tid == me: + return True + + def acquire(self): + """ + Acquire the module lock. If a potential deadlock is detected, + a _DeadlockError is raised. + Otherwise, the lock is always acquired and True is returned. + """ + tid = _thread.get_ident() + _blocking_on[tid] = self + try: + while True: + with self.lock: + if self.count == 0 or self.owner == tid: + self.owner = tid + self.count += 1 + return True + if self.has_deadlock(): + raise _DeadlockError('deadlock detected by %r' % self) + if self.wakeup.acquire(False): + self.waiters += 1 + # Wait for a release() call + self.wakeup.acquire() + self.wakeup.release() + finally: + del _blocking_on[tid] + + def release(self): + tid = _thread.get_ident() + with self.lock: + if self.owner != tid: + raise RuntimeError('cannot release un-acquired lock') + assert self.count > 0 + self.count -= 1 + if self.count == 0: + self.owner = None + if self.waiters: + self.waiters -= 1 + self.wakeup.release() + + def __repr__(self): + return '_ModuleLock({!r}) at {}'.format(self.name, id(self)) + + +class _DummyModuleLock: + """A simple _ModuleLock equivalent for Python builds without + multi-threading support.""" + + def __init__(self, name): + self.name = name + self.count = 0 + + def acquire(self): + self.count += 1 + return True + + def release(self): + if self.count == 0: + raise RuntimeError('cannot release un-acquired lock') + self.count -= 1 + + def __repr__(self): + return '_DummyModuleLock({!r}) at {}'.format(self.name, id(self)) + + +class _ModuleLockManager: + + def __init__(self, name): + self._name = name + self._lock = None + + def __enter__(self): + self._lock = _get_module_lock(self._name) + self._lock.acquire() + + def __exit__(self, *args, **kwargs): + self._lock.release() + + +# The following two functions are for consumption by Python/import.c. + +def _get_module_lock(name): + """Get or create the module lock for a given module name. + + Acquire/release internally the global import lock to protect + _module_locks.""" + + _imp.acquire_lock() + try: + try: + lock = _module_locks[name]() + except KeyError: + lock = None + + if lock is None: + if _thread is None: + lock = _DummyModuleLock(name) + else: + lock = _ModuleLock(name) + + def cb(ref, name=name): + _imp.acquire_lock() + try: + # bpo-31070: Check if another thread created a new lock + # after the previous lock was destroyed + # but before the weakref callback was called. + if _module_locks.get(name) is ref: + del _module_locks[name] + finally: + _imp.release_lock() + + _module_locks[name] = _weakref.ref(lock, cb) + finally: + _imp.release_lock() + + return lock + + +def _lock_unlock_module(name): + """Acquires then releases the module lock for a given module name. + + This is used to ensure a module is completely initialized, in the + event it is being imported by another thread. + """ + lock = _get_module_lock(name) + try: + lock.acquire() + except _DeadlockError: + # Concurrent circular import, we'll accept a partially initialized + # module object. + pass + else: + lock.release() + +# Frame stripping magic ############################################### +def _call_with_frames_removed(f, *args, **kwds): + """remove_importlib_frames in import.c will always remove sequences + of importlib frames that end with a call to this function + + Use it instead of a normal call in places where including the importlib + frames introduces unwanted noise into the traceback (e.g. when executing + module code) + """ + return f(*args, **kwds) + + +def _verbose_message(message, *args, verbosity=1): + """Print the message to stderr if -v/PYTHONVERBOSE is turned on.""" + if sys.flags.verbose >= verbosity: + if not message.startswith(('#', 'import ')): + message = '# ' + message + print(message.format(*args), file=sys.stderr) + + +def _requires_builtin(fxn): + """Decorator to verify the named module is built-in.""" + def _requires_builtin_wrapper(self, fullname): + if fullname not in sys.builtin_module_names: + raise ImportError('{!r} is not a built-in module'.format(fullname), + name=fullname) + return fxn(self, fullname) + _wrap(_requires_builtin_wrapper, fxn) + return _requires_builtin_wrapper + + +def _requires_frozen(fxn): + """Decorator to verify the named module is frozen.""" + def _requires_frozen_wrapper(self, fullname): + if not _imp.is_frozen(fullname): + raise ImportError('{!r} is not a frozen module'.format(fullname), + name=fullname) + return fxn(self, fullname) + _wrap(_requires_frozen_wrapper, fxn) + return _requires_frozen_wrapper + + +# Typically used by loader classes as a method replacement. +def _load_module_shim(self, fullname): + """Load the specified module into sys.modules and return it. + + This method is deprecated. Use loader.exec_module instead. + + """ + spec = spec_from_loader(fullname, self) + if fullname in sys.modules: + module = sys.modules[fullname] + _exec(spec, module) + return sys.modules[fullname] + else: + return _load(spec) + +# Module specifications ####################################################### + +def _module_repr(module): + # The implementation of ModuleType.__repr__(). + loader = getattr(module, '__loader__', None) + if hasattr(loader, 'module_repr'): + # As soon as BuiltinImporter, FrozenImporter, and NamespaceLoader + # drop their implementations for module_repr. we can add a + # deprecation warning here. + try: + return loader.module_repr(module) + except Exception: + pass + try: + spec = module.__spec__ + except AttributeError: + pass + else: + if spec is not None: + return _module_repr_from_spec(spec) + + # We could use module.__class__.__name__ instead of 'module' in the + # various repr permutations. + try: + name = module.__name__ + except AttributeError: + name = '?' + try: + filename = module.__file__ + except AttributeError: + if loader is None: + return ''.format(name) + else: + return ''.format(name, loader) + else: + return ''.format(name, filename) + + +class _installed_safely: + + def __init__(self, module): + self._module = module + self._spec = module.__spec__ + + def __enter__(self): + # This must be done before putting the module in sys.modules + # (otherwise an optimization shortcut in import.c becomes + # wrong) + self._spec._initializing = True + sys.modules[self._spec.name] = self._module + + def __exit__(self, *args): + try: + spec = self._spec + if any(arg is not None for arg in args): + try: + del sys.modules[spec.name] + except KeyError: + pass + else: + _verbose_message('import {!r} # {!r}', spec.name, spec.loader) + finally: + self._spec._initializing = False + + +class ModuleSpec: + """The specification for a module, used for loading. + + A module's spec is the source for information about the module. For + data associated with the module, including source, use the spec's + loader. + + `name` is the absolute name of the module. `loader` is the loader + to use when loading the module. `parent` is the name of the + package the module is in. The parent is derived from the name. + + `is_package` determines if the module is considered a package or + not. On modules this is reflected by the `__path__` attribute. + + `origin` is the specific location used by the loader from which to + load the module, if that information is available. When filename is + set, origin will match. + + `has_location` indicates that a spec's "origin" reflects a location. + When this is True, `__file__` attribute of the module is set. + + `cached` is the location of the cached bytecode file, if any. It + corresponds to the `__cached__` attribute. + + `submodule_search_locations` is the sequence of path entries to + search when importing submodules. If set, is_package should be + True--and False otherwise. + + Packages are simply modules that (may) have submodules. If a spec + has a non-None value in `submodule_search_locations`, the import + system will consider modules loaded from the spec as packages. + + Only finders (see importlib.abc.MetaPathFinder and + importlib.abc.PathEntryFinder) should modify ModuleSpec instances. + + """ + + def __init__(self, name, loader, *, origin=None, loader_state=None, + is_package=None): + self.name = name + self.loader = loader + self.origin = origin + self.loader_state = loader_state + self.submodule_search_locations = [] if is_package else None + + # file-location attributes + self._set_fileattr = False + self._cached = None + + def __repr__(self): + args = ['name={!r}'.format(self.name), + 'loader={!r}'.format(self.loader)] + if self.origin is not None: + args.append('origin={!r}'.format(self.origin)) + if self.submodule_search_locations is not None: + args.append('submodule_search_locations={}' + .format(self.submodule_search_locations)) + return '{}({})'.format(self.__class__.__name__, ', '.join(args)) + + def __eq__(self, other): + smsl = self.submodule_search_locations + try: + return (self.name == other.name and + self.loader == other.loader and + self.origin == other.origin and + smsl == other.submodule_search_locations and + self.cached == other.cached and + self.has_location == other.has_location) + except AttributeError: + return False + + @property + def cached(self): + if self._cached is None: + if self.origin is not None and self._set_fileattr: + if _bootstrap_external is None: + raise NotImplementedError + self._cached = _bootstrap_external._get_cached(self.origin) + return self._cached + + @cached.setter + def cached(self, cached): + self._cached = cached + + @property + def parent(self): + """The name of the module's parent.""" + if self.submodule_search_locations is None: + return self.name.rpartition('.')[0] + else: + return self.name + + @property + def has_location(self): + return self._set_fileattr + + @has_location.setter + def has_location(self, value): + self._set_fileattr = bool(value) + + +def spec_from_loader(name, loader, *, origin=None, is_package=None): + """Return a module spec based on various loader methods.""" + if hasattr(loader, 'get_filename'): + if _bootstrap_external is None: + raise NotImplementedError + spec_from_file_location = _bootstrap_external.spec_from_file_location + + if is_package is None: + return spec_from_file_location(name, loader=loader) + search = [] if is_package else None + return spec_from_file_location(name, loader=loader, + submodule_search_locations=search) + + if is_package is None: + if hasattr(loader, 'is_package'): + try: + is_package = loader.is_package(name) + except ImportError: + is_package = None # aka, undefined + else: + # the default + is_package = False + + return ModuleSpec(name, loader, origin=origin, is_package=is_package) + + +def _spec_from_module(module, loader=None, origin=None): + # This function is meant for use in _setup(). + try: + spec = module.__spec__ + except AttributeError: + pass + else: + if spec is not None: + return spec + + name = module.__name__ + if loader is None: + try: + loader = module.__loader__ + except AttributeError: + # loader will stay None. + pass + try: + location = module.__file__ + except AttributeError: + location = None + if origin is None: + if location is None: + try: + origin = loader._ORIGIN + except AttributeError: + origin = None + else: + origin = location + try: + cached = module.__cached__ + except AttributeError: + cached = None + try: + submodule_search_locations = list(module.__path__) + except AttributeError: + submodule_search_locations = None + + spec = ModuleSpec(name, loader, origin=origin) + spec._set_fileattr = False if location is None else True + spec.cached = cached + spec.submodule_search_locations = submodule_search_locations + return spec + + +def _init_module_attrs(spec, module, *, override=False): + # The passed-in module may be not support attribute assignment, + # in which case we simply don't set the attributes. + # __name__ + if (override or getattr(module, '__name__', None) is None): + try: + module.__name__ = spec.name + except AttributeError: + pass + # __loader__ + if override or getattr(module, '__loader__', None) is None: + loader = spec.loader + if loader is None: + # A backward compatibility hack. + if spec.submodule_search_locations is not None: + if _bootstrap_external is None: + raise NotImplementedError + _NamespaceLoader = _bootstrap_external._NamespaceLoader + + loader = _NamespaceLoader.__new__(_NamespaceLoader) + loader._path = spec.submodule_search_locations + spec.loader = loader + # While the docs say that module.__file__ is not set for + # built-in modules, and the code below will avoid setting it if + # spec.has_location is false, this is incorrect for namespace + # packages. Namespace packages have no location, but their + # __spec__.origin is None, and thus their module.__file__ + # should also be None for consistency. While a bit of a hack, + # this is the best place to ensure this consistency. + # + # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module + # and bpo-32305 + module.__file__ = None + try: + module.__loader__ = loader + except AttributeError: + pass + # __package__ + if override or getattr(module, '__package__', None) is None: + try: + module.__package__ = spec.parent + except AttributeError: + pass + # __spec__ + try: + module.__spec__ = spec + except AttributeError: + pass + # __path__ + if override or getattr(module, '__path__', None) is None: + if spec.submodule_search_locations is not None: + try: + module.__path__ = spec.submodule_search_locations + except AttributeError: + pass + # __file__/__cached__ + if spec.has_location: + if override or getattr(module, '__file__', None) is None: + try: + module.__file__ = spec.origin + except AttributeError: + pass + + if override or getattr(module, '__cached__', None) is None: + if spec.cached is not None: + try: + module.__cached__ = spec.cached + except AttributeError: + pass + return module + + +def module_from_spec(spec): + """Create a module based on the provided spec.""" + # Typically loaders will not implement create_module(). + module = None + if hasattr(spec.loader, 'create_module'): + # If create_module() returns `None` then it means default + # module creation should be used. + module = spec.loader.create_module(spec) + elif hasattr(spec.loader, 'exec_module'): + raise ImportError('loaders that define exec_module() ' + 'must also define create_module()') + if module is None: + module = _new_module(spec.name) + _init_module_attrs(spec, module) + return module + + +def _module_repr_from_spec(spec): + """Return the repr to use for the module.""" + # We mostly replicate _module_repr() using the spec attributes. + name = '?' if spec.name is None else spec.name + if spec.origin is None: + if spec.loader is None: + return ''.format(name) + else: + return ''.format(name, spec.loader) + else: + if spec.has_location: + return ''.format(name, spec.origin) + else: + return ''.format(spec.name, spec.origin) + + +# Used by importlib.reload() and _load_module_shim(). +def _exec(spec, module): + """Execute the spec's specified module in an existing module's namespace.""" + name = spec.name + with _ModuleLockManager(name): + if sys.modules.get(name) is not module: + msg = 'module {!r} not in sys.modules'.format(name) + raise ImportError(msg, name=name) + if spec.loader is None: + if spec.submodule_search_locations is None: + raise ImportError('missing loader', name=spec.name) + # namespace package + _init_module_attrs(spec, module, override=True) + return module + _init_module_attrs(spec, module, override=True) + if not hasattr(spec.loader, 'exec_module'): + # (issue19713) Once BuiltinImporter and ExtensionFileLoader + # have exec_module() implemented, we can add a deprecation + # warning here. + spec.loader.load_module(name) + else: + spec.loader.exec_module(module) + return sys.modules[name] + + +def _load_backward_compatible(spec): + # (issue19713) Once BuiltinImporter and ExtensionFileLoader + # have exec_module() implemented, we can add a deprecation + # warning here. + spec.loader.load_module(spec.name) + # The module must be in sys.modules at this point! + module = sys.modules[spec.name] + if getattr(module, '__loader__', None) is None: + try: + module.__loader__ = spec.loader + except AttributeError: + pass + if getattr(module, '__package__', None) is None: + try: + # Since module.__path__ may not line up with + # spec.submodule_search_paths, we can't necessarily rely + # on spec.parent here. + module.__package__ = module.__name__ + if not hasattr(module, '__path__'): + module.__package__ = spec.name.rpartition('.')[0] + except AttributeError: + pass + if getattr(module, '__spec__', None) is None: + try: + module.__spec__ = spec + except AttributeError: + pass + return module + +def _load_unlocked(spec): + # A helper for direct use by the import system. + if spec.loader is not None: + # not a namespace package + if not hasattr(spec.loader, 'exec_module'): + return _load_backward_compatible(spec) + + module = module_from_spec(spec) + with _installed_safely(module): + if spec.loader is None: + if spec.submodule_search_locations is None: + raise ImportError('missing loader', name=spec.name) + # A namespace package so do nothing. + else: + spec.loader.exec_module(module) + + # We don't ensure that the import-related module attributes get + # set in the sys.modules replacement case. Such modules are on + # their own. + return sys.modules[spec.name] + +# A method used during testing of _load_unlocked() and by +# _load_module_shim(). +def _load(spec): + """Return a new module object, loaded by the spec's loader. + + The module is not added to its parent. + + If a module is already in sys.modules, that existing module gets + clobbered. + + """ + with _ModuleLockManager(spec.name): + return _load_unlocked(spec) + + +# Loaders ##################################################################### + +class BuiltinImporter: + + """Meta path import for built-in modules. + + All methods are either class or static methods to avoid the need to + instantiate the class. + + """ + + @staticmethod + def module_repr(module): + """Return repr for the module. + + The method is deprecated. The import machinery does the job itself. + + """ + return ''.format(module.__name__) + + @classmethod + def find_spec(cls, fullname, path=None, target=None): + if path is not None: + return None + if _imp.is_builtin(fullname): + return spec_from_loader(fullname, cls, origin='built-in') + else: + return None + + @classmethod + def find_module(cls, fullname, path=None): + """Find the built-in module. + + If 'path' is ever specified then the search is considered a failure. + + This method is deprecated. Use find_spec() instead. + + """ + spec = cls.find_spec(fullname, path) + return spec.loader if spec is not None else None + + @classmethod + def create_module(self, spec): + """Create a built-in module""" + if spec.name not in sys.builtin_module_names: + raise ImportError('{!r} is not a built-in module'.format(spec.name), + name=spec.name) + return _call_with_frames_removed(_imp.create_builtin, spec) + + @classmethod + def exec_module(self, module): + """Exec a built-in module""" + _call_with_frames_removed(_imp.exec_builtin, module) + + @classmethod + @_requires_builtin + def get_code(cls, fullname): + """Return None as built-in modules do not have code objects.""" + return None + + @classmethod + @_requires_builtin + def get_source(cls, fullname): + """Return None as built-in modules do not have source code.""" + return None + + @classmethod + @_requires_builtin + def is_package(cls, fullname): + """Return False as built-in modules are never packages.""" + return False + + load_module = classmethod(_load_module_shim) + + +class FrozenImporter: + + """Meta path import for frozen modules. + + All methods are either class or static methods to avoid the need to + instantiate the class. + + """ + + @staticmethod + def module_repr(m): + """Return repr for the module. + + The method is deprecated. The import machinery does the job itself. + + """ + return ''.format(m.__name__) + + @classmethod + def find_spec(cls, fullname, path=None, target=None): + if _imp.is_frozen(fullname): + return spec_from_loader(fullname, cls, origin='frozen') + else: + return None + + @classmethod + def find_module(cls, fullname, path=None): + """Find a frozen module. + + This method is deprecated. Use find_spec() instead. + + """ + return cls if _imp.is_frozen(fullname) else None + + @classmethod + def create_module(cls, spec): + """Use default semantics for module creation.""" + + @staticmethod + def exec_module(module): + name = module.__spec__.name + if not _imp.is_frozen(name): + raise ImportError('{!r} is not a frozen module'.format(name), + name=name) + code = _call_with_frames_removed(_imp.get_frozen_object, name) + exec(code, module.__dict__) + + @classmethod + def load_module(cls, fullname): + """Load a frozen module. + + This method is deprecated. Use exec_module() instead. + + """ + return _load_module_shim(cls, fullname) + + @classmethod + @_requires_frozen + def get_code(cls, fullname): + """Return the code object for the frozen module.""" + return _imp.get_frozen_object(fullname) + + @classmethod + @_requires_frozen + def get_source(cls, fullname): + """Return None as frozen modules do not have source code.""" + return None + + @classmethod + @_requires_frozen + def is_package(cls, fullname): + """Return True if the frozen module is a package.""" + return _imp.is_frozen_package(fullname) + + +# Import itself ############################################################### + +class _ImportLockContext: + + """Context manager for the import lock.""" + + def __enter__(self): + """Acquire the import lock.""" + _imp.acquire_lock() + + def __exit__(self, exc_type, exc_value, exc_traceback): + """Release the import lock regardless of any raised exceptions.""" + _imp.release_lock() + + +def _resolve_name(name, package, level): + """Resolve a relative module name to an absolute one.""" + bits = package.rsplit('.', level - 1) + if len(bits) < level: + raise ValueError('attempted relative import beyond top-level package') + base = bits[0] + return '{}.{}'.format(base, name) if name else base + + +def _find_spec_legacy(finder, name, path): + # This would be a good place for a DeprecationWarning if + # we ended up going that route. + loader = finder.find_module(name, path) + if loader is None: + return None + return spec_from_loader(name, loader) + + +def _find_spec(name, path, target=None): + """Find a module's spec.""" + meta_path = sys.meta_path + if meta_path is None: + # PyImport_Cleanup() is running or has been called. + raise ImportError("sys.meta_path is None, Python is likely " + "shutting down") + + if not meta_path: + _warnings.warn('sys.meta_path is empty', ImportWarning) + + # We check sys.modules here for the reload case. While a passed-in + # target will usually indicate a reload there is no guarantee, whereas + # sys.modules provides one. + is_reload = name in sys.modules + for finder in meta_path: + with _ImportLockContext(): + try: + find_spec = finder.find_spec + except AttributeError: + spec = _find_spec_legacy(finder, name, path) + if spec is None: + continue + else: + spec = find_spec(name, path, target) + if spec is not None: + # The parent import may have already imported this module. + if not is_reload and name in sys.modules: + module = sys.modules[name] + try: + __spec__ = module.__spec__ + except AttributeError: + # We use the found spec since that is the one that + # we would have used if the parent module hadn't + # beaten us to the punch. + return spec + else: + if __spec__ is None: + return spec + else: + return __spec__ + else: + return spec + else: + return None + + +def _sanity_check(name, package, level): + """Verify arguments are "sane".""" + if not isinstance(name, str): + raise TypeError('module name must be str, not {}'.format(type(name))) + if level < 0: + raise ValueError('level must be >= 0') + if level > 0: + if not isinstance(package, str): + raise TypeError('__package__ not set to a string') + elif not package: + raise ImportError('attempted relative import with no known parent ' + 'package') + if not name and level == 0: + raise ValueError('Empty module name') + + +_ERR_MSG_PREFIX = 'No module named ' +_ERR_MSG = _ERR_MSG_PREFIX + '{!r}' + +def _find_and_load_unlocked(name, import_): + path = None + parent = name.rpartition('.')[0] + if parent: + if parent not in sys.modules: + _call_with_frames_removed(import_, parent) + # Crazy side-effects! + if name in sys.modules: + return sys.modules[name] + parent_module = sys.modules[parent] + try: + path = parent_module.__path__ + except AttributeError: + msg = (_ERR_MSG + '; {!r} is not a package').format(name, parent) + raise ModuleNotFoundError(msg, name=name) from None + spec = _find_spec(name, path) + if spec is None: + raise ModuleNotFoundError(_ERR_MSG.format(name), name=name) + else: + module = _load_unlocked(spec) + if parent: + # Set the module as an attribute on its parent. + parent_module = sys.modules[parent] + setattr(parent_module, name.rpartition('.')[2], module) + return module + + +_NEEDS_LOADING = object() + + +def _find_and_load(name, import_): + """Find and load the module.""" + with _ModuleLockManager(name): + module = sys.modules.get(name, _NEEDS_LOADING) + if module is _NEEDS_LOADING: + return _find_and_load_unlocked(name, import_) + + if module is None: + message = ('import of {} halted; ' + 'None in sys.modules'.format(name)) + raise ModuleNotFoundError(message, name=name) + + _lock_unlock_module(name) + return module + + +def _gcd_import(name, package=None, level=0): + """Import and return the module based on its name, the package the call is + being made from, and the level adjustment. + + This function represents the greatest common denominator of functionality + between import_module and __import__. This includes setting __package__ if + the loader did not. + + """ + _sanity_check(name, package, level) + if level > 0: + name = _resolve_name(name, package, level) + return _find_and_load(name, _gcd_import) + + +def _handle_fromlist(module, fromlist, import_, *, recursive=False): + """Figure out what __import__ should return. + + The import_ parameter is a callable which takes the name of module to + import. It is required to decouple the function from assuming importlib's + import implementation is desired. + + """ + # The hell that is fromlist ... + # If a package was imported, try to import stuff from fromlist. + if hasattr(module, '__path__'): + for x in fromlist: + if not isinstance(x, str): + if recursive: + where = module.__name__ + '.__all__' + else: + where = "``from list''" + raise TypeError(f"Item in {where} must be str, " + f"not {type(x).__name__}") + elif x == '*': + if not recursive and hasattr(module, '__all__'): + _handle_fromlist(module, module.__all__, import_, + recursive=True) + elif not hasattr(module, x): + from_name = '{}.{}'.format(module.__name__, x) + try: + _call_with_frames_removed(import_, from_name) + except ModuleNotFoundError as exc: + # Backwards-compatibility dictates we ignore failed + # imports triggered by fromlist for modules that don't + # exist. + if (exc.name == from_name and + sys.modules.get(from_name, _NEEDS_LOADING) is not None): + continue + raise + return module + + +def _calc___package__(globals): + """Calculate what __package__ should be. + + __package__ is not guaranteed to be defined or could be set to None + to represent that its proper value is unknown. + + """ + package = globals.get('__package__') + spec = globals.get('__spec__') + if package is not None: + if spec is not None and package != spec.parent: + _warnings.warn("__package__ != __spec__.parent " + f"({package!r} != {spec.parent!r})", + ImportWarning, stacklevel=3) + return package + elif spec is not None: + return spec.parent + else: + _warnings.warn("can't resolve package from __spec__ or __package__, " + "falling back on __name__ and __path__", + ImportWarning, stacklevel=3) + package = globals['__name__'] + if '__path__' not in globals: + package = package.rpartition('.')[0] + return package + + +def __import__(name, globals=None, locals=None, fromlist=(), level=0): + """Import a module. + + The 'globals' argument is used to infer where the import is occurring from + to handle relative imports. The 'locals' argument is ignored. The + 'fromlist' argument specifies what should exist as attributes on the module + being imported (e.g. ``from module import ``). The 'level' + argument represents the package location to import from in a relative + import (e.g. ``from ..pkg import mod`` would have a 'level' of 2). + + """ + if level == 0: + module = _gcd_import(name) + else: + globals_ = globals if globals is not None else {} + package = _calc___package__(globals_) + module = _gcd_import(name, package, level) + if not fromlist: + # Return up to the first dot in 'name'. This is complicated by the fact + # that 'name' may be relative. + if level == 0: + return _gcd_import(name.partition('.')[0]) + elif not name: + return module + else: + # Figure out where to slice the module's name up to the first dot + # in 'name'. + cut_off = len(name) - len(name.partition('.')[0]) + # Slice end needs to be positive to alleviate need to special-case + # when ``'.' not in name``. + return sys.modules[module.__name__[:len(module.__name__)-cut_off]] + else: + return _handle_fromlist(module, fromlist, _gcd_import) + + +def _builtin_from_name(name): + spec = BuiltinImporter.find_spec(name) + if spec is None: + raise ImportError('no built-in module named ' + name) + return _load_unlocked(spec) + + +def _setup(sys_module, _imp_module): + """Setup importlib by importing needed built-in modules and injecting them + into the global namespace. + + As sys is needed for sys.modules access and _imp is needed to load built-in + modules, those two modules must be explicitly passed in. + + """ + global _imp, sys + _imp = _imp_module + sys = sys_module + + # Set up the spec for existing builtin/frozen modules. + module_type = type(sys) + for name, module in sys.modules.items(): + if isinstance(module, module_type): + if name in sys.builtin_module_names: + loader = BuiltinImporter + elif _imp.is_frozen(name): + loader = FrozenImporter + else: + continue + spec = _spec_from_module(module, loader) + _init_module_attrs(spec, module) + + # Directly load built-in modules needed during bootstrap. + self_module = sys.modules[__name__] + for builtin_name in ('_thread', '_warnings', '_weakref'): + if builtin_name not in sys.modules: + builtin_module = _builtin_from_name(builtin_name) + else: + builtin_module = sys.modules[builtin_name] + setattr(self_module, builtin_name, builtin_module) + + +def _install(sys_module, _imp_module): + """Install importers for builtin and frozen modules""" + _setup(sys_module, _imp_module) + + sys.meta_path.append(BuiltinImporter) + sys.meta_path.append(FrozenImporter) + + +def _install_external_importers(): + """Install importers that require external filesystem access""" + global _bootstrap_external + import _frozen_importlib_external + _bootstrap_external = _frozen_importlib_external + _frozen_importlib_external._install(sys.modules[__name__]) diff --git a/winvenv/Lib/importlib/_bootstrap_external.py b/winvenv/Lib/importlib/_bootstrap_external.py new file mode 100644 index 0000000..53b24ff --- /dev/null +++ b/winvenv/Lib/importlib/_bootstrap_external.py @@ -0,0 +1,1562 @@ +"""Core implementation of path-based import. + +This module is NOT meant to be directly imported! It has been designed such +that it can be bootstrapped into Python as the implementation of import. As +such it requires the injection of specific modules and attributes in order to +work. One should use importlib as the public-facing version of this module. + +""" +# IMPORTANT: Whenever making changes to this module, be sure to run a top-level +# `make regen-importlib` followed by `make` in order to get the frozen version +# of the module updated. Not doing so will result in the Makefile to fail for +# all others who don't have a ./python around to freeze the module in the early +# stages of compilation. +# + +# See importlib._setup() for what is injected into the global namespace. + +# When editing this code be aware that code executed at import time CANNOT +# reference any injected objects! This includes not only global code but also +# anything specified at the class level. + +# Bootstrap-related code ###################################################### +_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win', +_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin' +_CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY + + _CASE_INSENSITIVE_PLATFORMS_STR_KEY) + + +def _make_relax_case(): + if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): + if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS_STR_KEY): + key = 'PYTHONCASEOK' + else: + key = b'PYTHONCASEOK' + + def _relax_case(): + """True if filenames must be checked case-insensitively.""" + return key in _os.environ + else: + def _relax_case(): + """True if filenames must be checked case-insensitively.""" + return False + return _relax_case + + +def _w_long(x): + """Convert a 32-bit integer to little-endian.""" + return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little') + + +def _r_long(int_bytes): + """Convert 4 bytes in little-endian to an integer.""" + return int.from_bytes(int_bytes, 'little') + + +def _path_join(*path_parts): + """Replacement for os.path.join().""" + return path_sep.join([part.rstrip(path_separators) + for part in path_parts if part]) + + +def _path_split(path): + """Replacement for os.path.split().""" + if len(path_separators) == 1: + front, _, tail = path.rpartition(path_sep) + return front, tail + for x in reversed(path): + if x in path_separators: + front, tail = path.rsplit(x, maxsplit=1) + return front, tail + return '', path + + +def _path_stat(path): + """Stat the path. + + Made a separate function to make it easier to override in experiments + (e.g. cache stat results). + + """ + return _os.stat(path) + + +def _path_is_mode_type(path, mode): + """Test whether the path is the specified mode type.""" + try: + stat_info = _path_stat(path) + except OSError: + return False + return (stat_info.st_mode & 0o170000) == mode + + +def _path_isfile(path): + """Replacement for os.path.isfile.""" + return _path_is_mode_type(path, 0o100000) + + +def _path_isdir(path): + """Replacement for os.path.isdir.""" + if not path: + path = _os.getcwd() + return _path_is_mode_type(path, 0o040000) + + +def _write_atomic(path, data, mode=0o666): + """Best-effort function to write data to a path atomically. + Be prepared to handle a FileExistsError if concurrent writing of the + temporary file is attempted.""" + # id() is used to generate a pseudo-random filename. + path_tmp = '{}.{}'.format(path, id(path)) + fd = _os.open(path_tmp, + _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY, mode & 0o666) + try: + # We first write data to a temporary file, and then use os.replace() to + # perform an atomic rename. + with _io.FileIO(fd, 'wb') as file: + file.write(data) + _os.replace(path_tmp, path) + except OSError: + try: + _os.unlink(path_tmp) + except OSError: + pass + raise + + +_code_type = type(_write_atomic.__code__) + + +# Finder/loader utility code ############################################### + +# Magic word to reject .pyc files generated by other Python versions. +# It should change for each incompatible change to the bytecode. +# +# The value of CR and LF is incorporated so if you ever read or write +# a .pyc file in text mode the magic number will be wrong; also, the +# Apple MPW compiler swaps their values, botching string constants. +# +# There were a variety of old schemes for setting the magic number. +# The current working scheme is to increment the previous value by +# 10. +# +# Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic +# number also includes a new "magic tag", i.e. a human readable string used +# to represent the magic number in __pycache__ directories. When you change +# the magic number, you must also set a new unique magic tag. Generally this +# can be named after the Python major version of the magic number bump, but +# it can really be anything, as long as it's different than anything else +# that's come before. The tags are included in the following table, starting +# with Python 3.2a0. +# +# Known values: +# Python 1.5: 20121 +# Python 1.5.1: 20121 +# Python 1.5.2: 20121 +# Python 1.6: 50428 +# Python 2.0: 50823 +# Python 2.0.1: 50823 +# Python 2.1: 60202 +# Python 2.1.1: 60202 +# Python 2.1.2: 60202 +# Python 2.2: 60717 +# Python 2.3a0: 62011 +# Python 2.3a0: 62021 +# Python 2.3a0: 62011 (!) +# Python 2.4a0: 62041 +# Python 2.4a3: 62051 +# Python 2.4b1: 62061 +# Python 2.5a0: 62071 +# Python 2.5a0: 62081 (ast-branch) +# Python 2.5a0: 62091 (with) +# Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) +# Python 2.5b3: 62101 (fix wrong code: for x, in ...) +# Python 2.5b3: 62111 (fix wrong code: x += yield) +# Python 2.5c1: 62121 (fix wrong lnotab with for loops and +# storing constants that should have been removed) +# Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) +# Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode) +# Python 2.6a1: 62161 (WITH_CLEANUP optimization) +# Python 2.7a0: 62171 (optimize list comprehensions/change LIST_APPEND) +# Python 2.7a0: 62181 (optimize conditional branches: +# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) +# Python 2.7a0 62191 (introduce SETUP_WITH) +# Python 2.7a0 62201 (introduce BUILD_SET) +# Python 2.7a0 62211 (introduce MAP_ADD and SET_ADD) +# Python 3000: 3000 +# 3010 (removed UNARY_CONVERT) +# 3020 (added BUILD_SET) +# 3030 (added keyword-only parameters) +# 3040 (added signature annotations) +# 3050 (print becomes a function) +# 3060 (PEP 3115 metaclass syntax) +# 3061 (string literals become unicode) +# 3071 (PEP 3109 raise changes) +# 3081 (PEP 3137 make __file__ and __name__ unicode) +# 3091 (kill str8 interning) +# 3101 (merge from 2.6a0, see 62151) +# 3103 (__file__ points to source file) +# Python 3.0a4: 3111 (WITH_CLEANUP optimization). +# Python 3.0b1: 3131 (lexical exception stacking, including POP_EXCEPT + #3021) +# Python 3.1a1: 3141 (optimize list, set and dict comprehensions: +# change LIST_APPEND and SET_ADD, add MAP_ADD #2183) +# Python 3.1a1: 3151 (optimize conditional branches: +# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE + #4715) +# Python 3.2a1: 3160 (add SETUP_WITH #6101) +# tag: cpython-32 +# Python 3.2a2: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR #9225) +# tag: cpython-32 +# Python 3.2a3 3180 (add DELETE_DEREF #4617) +# Python 3.3a1 3190 (__class__ super closure changed) +# Python 3.3a1 3200 (PEP 3155 __qualname__ added #13448) +# Python 3.3a1 3210 (added size modulo 2**32 to the pyc header #13645) +# Python 3.3a2 3220 (changed PEP 380 implementation #14230) +# Python 3.3a4 3230 (revert changes to implicit __class__ closure #14857) +# Python 3.4a1 3250 (evaluate positional default arguments before +# keyword-only defaults #16967) +# Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override +# free vars #17853) +# Python 3.4a1 3270 (various tweaks to the __class__ closure #12370) +# Python 3.4a1 3280 (remove implicit class argument) +# Python 3.4a4 3290 (changes to __qualname__ computation #19301) +# Python 3.4a4 3300 (more changes to __qualname__ computation #19301) +# Python 3.4rc2 3310 (alter __qualname__ computation #20625) +# Python 3.5a1 3320 (PEP 465: Matrix multiplication operator #21176) +# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations #2292) +# Python 3.5b2 3340 (fix dictionary display evaluation order #11205) +# Python 3.5b3 3350 (add GET_YIELD_FROM_ITER opcode #24400) +# Python 3.5.2 3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286) +# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483) +# Python 3.6a1 3361 (lineno delta of code.co_lnotab becomes signed #26107) +# Python 3.6a2 3370 (16 bit wordcode #26647) +# Python 3.6a2 3371 (add BUILD_CONST_KEY_MAP opcode #27140) +# Python 3.6a2 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE +# #27095) +# Python 3.6b1 3373 (add BUILD_STRING opcode #27078) +# Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes +# #27985) +# Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL + #27213) +# Python 3.6b1 3377 (set __class__ cell from type.__new__ #23722) +# Python 3.6b2 3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257) +# Python 3.6rc1 3379 (more thorough __class__ validation #23722) +# Python 3.7a1 3390 (add LOAD_METHOD and CALL_METHOD opcodes #26110) +# Python 3.7a2 3391 (update GET_AITER #31709) +# Python 3.7a4 3392 (PEP 552: Deterministic pycs #31650) +# Python 3.7b1 3393 (remove STORE_ANNOTATION opcode #32550) +# Python 3.7b5 3394 (restored docstring as the firts stmt in the body; +# this might affected the first line number #32911) +# +# MAGIC must change whenever the bytecode emitted by the compiler may no +# longer be understood by older implementations of the eval loop (usually +# due to the addition of new opcodes). +# +# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array +# in PC/launcher.c must also be updated. + +MAGIC_NUMBER = (3394).to_bytes(2, 'little') + b'\r\n' +_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c + +_PYCACHE = '__pycache__' +_OPT = 'opt-' + +SOURCE_SUFFIXES = ['.py'] # _setup() adds .pyw as needed. + +BYTECODE_SUFFIXES = ['.pyc'] +# Deprecated. +DEBUG_BYTECODE_SUFFIXES = OPTIMIZED_BYTECODE_SUFFIXES = BYTECODE_SUFFIXES + +def cache_from_source(path, debug_override=None, *, optimization=None): + """Given the path to a .py file, return the path to its .pyc file. + + The .py file does not need to exist; this simply returns the path to the + .pyc file calculated as if the .py file were imported. + + The 'optimization' parameter controls the presumed optimization level of + the bytecode file. If 'optimization' is not None, the string representation + of the argument is taken and verified to be alphanumeric (else ValueError + is raised). + + The debug_override parameter is deprecated. If debug_override is not None, + a True value is the same as setting 'optimization' to the empty string + while a False value is equivalent to setting 'optimization' to '1'. + + If sys.implementation.cache_tag is None then NotImplementedError is raised. + + """ + if debug_override is not None: + _warnings.warn('the debug_override parameter is deprecated; use ' + "'optimization' instead", DeprecationWarning) + if optimization is not None: + message = 'debug_override or optimization must be set to None' + raise TypeError(message) + optimization = '' if debug_override else 1 + path = _os.fspath(path) + head, tail = _path_split(path) + base, sep, rest = tail.rpartition('.') + tag = sys.implementation.cache_tag + if tag is None: + raise NotImplementedError('sys.implementation.cache_tag is None') + almost_filename = ''.join([(base if base else rest), sep, tag]) + if optimization is None: + if sys.flags.optimize == 0: + optimization = '' + else: + optimization = sys.flags.optimize + optimization = str(optimization) + if optimization != '': + if not optimization.isalnum(): + raise ValueError('{!r} is not alphanumeric'.format(optimization)) + almost_filename = '{}.{}{}'.format(almost_filename, _OPT, optimization) + return _path_join(head, _PYCACHE, almost_filename + BYTECODE_SUFFIXES[0]) + + +def source_from_cache(path): + """Given the path to a .pyc. file, return the path to its .py file. + + The .pyc file does not need to exist; this simply returns the path to + the .py file calculated to correspond to the .pyc file. If path does + not conform to PEP 3147/488 format, ValueError will be raised. If + sys.implementation.cache_tag is None then NotImplementedError is raised. + + """ + if sys.implementation.cache_tag is None: + raise NotImplementedError('sys.implementation.cache_tag is None') + path = _os.fspath(path) + head, pycache_filename = _path_split(path) + head, pycache = _path_split(head) + if pycache != _PYCACHE: + raise ValueError('{} not bottom-level directory in ' + '{!r}'.format(_PYCACHE, path)) + dot_count = pycache_filename.count('.') + if dot_count not in {2, 3}: + raise ValueError('expected only 2 or 3 dots in ' + '{!r}'.format(pycache_filename)) + elif dot_count == 3: + optimization = pycache_filename.rsplit('.', 2)[-2] + if not optimization.startswith(_OPT): + raise ValueError("optimization portion of filename does not start " + "with {!r}".format(_OPT)) + opt_level = optimization[len(_OPT):] + if not opt_level.isalnum(): + raise ValueError("optimization level {!r} is not an alphanumeric " + "value".format(optimization)) + base_filename = pycache_filename.partition('.')[0] + return _path_join(head, base_filename + SOURCE_SUFFIXES[0]) + + +def _get_sourcefile(bytecode_path): + """Convert a bytecode file path to a source path (if possible). + + This function exists purely for backwards-compatibility for + PyImport_ExecCodeModuleWithFilenames() in the C API. + + """ + if len(bytecode_path) == 0: + return None + rest, _, extension = bytecode_path.rpartition('.') + if not rest or extension.lower()[-3:-1] != 'py': + return bytecode_path + try: + source_path = source_from_cache(bytecode_path) + except (NotImplementedError, ValueError): + source_path = bytecode_path[:-1] + return source_path if _path_isfile(source_path) else bytecode_path + + +def _get_cached(filename): + if filename.endswith(tuple(SOURCE_SUFFIXES)): + try: + return cache_from_source(filename) + except NotImplementedError: + pass + elif filename.endswith(tuple(BYTECODE_SUFFIXES)): + return filename + else: + return None + + +def _calc_mode(path): + """Calculate the mode permissions for a bytecode file.""" + try: + mode = _path_stat(path).st_mode + except OSError: + mode = 0o666 + # We always ensure write access so we can update cached files + # later even when the source files are read-only on Windows (#6074) + mode |= 0o200 + return mode + + +def _check_name(method): + """Decorator to verify that the module being requested matches the one the + loader can handle. + + The first argument (self) must define _name which the second argument is + compared against. If the comparison fails then ImportError is raised. + + """ + def _check_name_wrapper(self, name=None, *args, **kwargs): + if name is None: + name = self.name + elif self.name != name: + raise ImportError('loader for %s cannot handle %s' % + (self.name, name), name=name) + return method(self, name, *args, **kwargs) + try: + _wrap = _bootstrap._wrap + except NameError: + # XXX yuck + def _wrap(new, old): + for replace in ['__module__', '__name__', '__qualname__', '__doc__']: + if hasattr(old, replace): + setattr(new, replace, getattr(old, replace)) + new.__dict__.update(old.__dict__) + _wrap(_check_name_wrapper, method) + return _check_name_wrapper + + +def _find_module_shim(self, fullname): + """Try to find a loader for the specified module by delegating to + self.find_loader(). + + This method is deprecated in favor of finder.find_spec(). + + """ + # Call find_loader(). If it returns a string (indicating this + # is a namespace package portion), generate a warning and + # return None. + loader, portions = self.find_loader(fullname) + if loader is None and len(portions): + msg = 'Not importing directory {}: missing __init__' + _warnings.warn(msg.format(portions[0]), ImportWarning) + return loader + + +def _classify_pyc(data, name, exc_details): + """Perform basic validity checking of a pyc header and return the flags field, + which determines how the pyc should be further validated against the source. + + *data* is the contents of the pyc file. (Only the first 16 bytes are + required, though.) + + *name* is the name of the module being imported. It is used for logging. + + *exc_details* is a dictionary passed to ImportError if it raised for + improved debugging. + + ImportError is raised when the magic number is incorrect or when the flags + field is invalid. EOFError is raised when the data is found to be truncated. + + """ + magic = data[:4] + if magic != MAGIC_NUMBER: + message = f'bad magic number in {name!r}: {magic!r}' + _bootstrap._verbose_message('{}', message) + raise ImportError(message, **exc_details) + if len(data) < 16: + message = f'reached EOF while reading pyc header of {name!r}' + _bootstrap._verbose_message('{}', message) + raise EOFError(message) + flags = _r_long(data[4:8]) + # Only the first two flags are defined. + if flags & ~0b11: + message = f'invalid flags {flags!r} in {name!r}' + raise ImportError(message, **exc_details) + return flags + + +def _validate_timestamp_pyc(data, source_mtime, source_size, name, + exc_details): + """Validate a pyc against the source last-modified time. + + *data* is the contents of the pyc file. (Only the first 16 bytes are + required.) + + *source_mtime* is the last modified timestamp of the source file. + + *source_size* is None or the size of the source file in bytes. + + *name* is the name of the module being imported. It is used for logging. + + *exc_details* is a dictionary passed to ImportError if it raised for + improved debugging. + + An ImportError is raised if the bytecode is stale. + + """ + if _r_long(data[8:12]) != (source_mtime & 0xFFFFFFFF): + message = f'bytecode is stale for {name!r}' + _bootstrap._verbose_message('{}', message) + raise ImportError(message, **exc_details) + if (source_size is not None and + _r_long(data[12:16]) != (source_size & 0xFFFFFFFF)): + raise ImportError(f'bytecode is stale for {name!r}', **exc_details) + + +def _validate_hash_pyc(data, source_hash, name, exc_details): + """Validate a hash-based pyc by checking the real source hash against the one in + the pyc header. + + *data* is the contents of the pyc file. (Only the first 16 bytes are + required.) + + *source_hash* is the importlib.util.source_hash() of the source file. + + *name* is the name of the module being imported. It is used for logging. + + *exc_details* is a dictionary passed to ImportError if it raised for + improved debugging. + + An ImportError is raised if the bytecode is stale. + + """ + if data[8:16] != source_hash: + raise ImportError( + f'hash in bytecode doesn\'t match hash of source {name!r}', + **exc_details, + ) + + +def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None): + """Compile bytecode as found in a pyc.""" + code = marshal.loads(data) + if isinstance(code, _code_type): + _bootstrap._verbose_message('code object from {!r}', bytecode_path) + if source_path is not None: + _imp._fix_co_filename(code, source_path) + return code + else: + raise ImportError('Non-code object in {!r}'.format(bytecode_path), + name=name, path=bytecode_path) + + +def _code_to_timestamp_pyc(code, mtime=0, source_size=0): + "Produce the data for a timestamp-based pyc." + data = bytearray(MAGIC_NUMBER) + data.extend(_w_long(0)) + data.extend(_w_long(mtime)) + data.extend(_w_long(source_size)) + data.extend(marshal.dumps(code)) + return data + + +def _code_to_hash_pyc(code, source_hash, checked=True): + "Produce the data for a hash-based pyc." + data = bytearray(MAGIC_NUMBER) + flags = 0b1 | checked << 1 + data.extend(_w_long(flags)) + assert len(source_hash) == 8 + data.extend(source_hash) + data.extend(marshal.dumps(code)) + return data + + +def decode_source(source_bytes): + """Decode bytes representing source code and return the string. + + Universal newline support is used in the decoding. + """ + import tokenize # To avoid bootstrap issues. + source_bytes_readline = _io.BytesIO(source_bytes).readline + encoding = tokenize.detect_encoding(source_bytes_readline) + newline_decoder = _io.IncrementalNewlineDecoder(None, True) + return newline_decoder.decode(source_bytes.decode(encoding[0])) + + +# Module specifications ####################################################### + +_POPULATE = object() + + +def spec_from_file_location(name, location=None, *, loader=None, + submodule_search_locations=_POPULATE): + """Return a module spec based on a file location. + + To indicate that the module is a package, set + submodule_search_locations to a list of directory paths. An + empty list is sufficient, though its not otherwise useful to the + import system. + + The loader must take a spec as its only __init__() arg. + + """ + if location is None: + # The caller may simply want a partially populated location- + # oriented spec. So we set the location to a bogus value and + # fill in as much as we can. + location = '' + if hasattr(loader, 'get_filename'): + # ExecutionLoader + try: + location = loader.get_filename(name) + except ImportError: + pass + else: + location = _os.fspath(location) + + # If the location is on the filesystem, but doesn't actually exist, + # we could return None here, indicating that the location is not + # valid. However, we don't have a good way of testing since an + # indirect location (e.g. a zip file or URL) will look like a + # non-existent file relative to the filesystem. + + spec = _bootstrap.ModuleSpec(name, loader, origin=location) + spec._set_fileattr = True + + # Pick a loader if one wasn't provided. + if loader is None: + for loader_class, suffixes in _get_supported_file_loaders(): + if location.endswith(tuple(suffixes)): + loader = loader_class(name, location) + spec.loader = loader + break + else: + return None + + # Set submodule_search_paths appropriately. + if submodule_search_locations is _POPULATE: + # Check the loader. + if hasattr(loader, 'is_package'): + try: + is_package = loader.is_package(name) + except ImportError: + pass + else: + if is_package: + spec.submodule_search_locations = [] + else: + spec.submodule_search_locations = submodule_search_locations + if spec.submodule_search_locations == []: + if location: + dirname = _path_split(location)[0] + spec.submodule_search_locations.append(dirname) + + return spec + + +# Loaders ##################################################################### + +class WindowsRegistryFinder: + + """Meta path finder for modules declared in the Windows registry.""" + + REGISTRY_KEY = ( + 'Software\\Python\\PythonCore\\{sys_version}' + '\\Modules\\{fullname}') + REGISTRY_KEY_DEBUG = ( + 'Software\\Python\\PythonCore\\{sys_version}' + '\\Modules\\{fullname}\\Debug') + DEBUG_BUILD = False # Changed in _setup() + + @classmethod + def _open_registry(cls, key): + try: + return _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, key) + except OSError: + return _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key) + + @classmethod + def _search_registry(cls, fullname): + if cls.DEBUG_BUILD: + registry_key = cls.REGISTRY_KEY_DEBUG + else: + registry_key = cls.REGISTRY_KEY + key = registry_key.format(fullname=fullname, + sys_version='%d.%d' % sys.version_info[:2]) + try: + with cls._open_registry(key) as hkey: + filepath = _winreg.QueryValue(hkey, '') + except OSError: + return None + return filepath + + @classmethod + def find_spec(cls, fullname, path=None, target=None): + filepath = cls._search_registry(fullname) + if filepath is None: + return None + try: + _path_stat(filepath) + except OSError: + return None + for loader, suffixes in _get_supported_file_loaders(): + if filepath.endswith(tuple(suffixes)): + spec = _bootstrap.spec_from_loader(fullname, + loader(fullname, filepath), + origin=filepath) + return spec + + @classmethod + def find_module(cls, fullname, path=None): + """Find module named in the registry. + + This method is deprecated. Use exec_module() instead. + + """ + spec = cls.find_spec(fullname, path) + if spec is not None: + return spec.loader + else: + return None + + +class _LoaderBasics: + + """Base class of common code needed by both SourceLoader and + SourcelessFileLoader.""" + + def is_package(self, fullname): + """Concrete implementation of InspectLoader.is_package by checking if + the path returned by get_filename has a filename of '__init__.py'.""" + filename = _path_split(self.get_filename(fullname))[1] + filename_base = filename.rsplit('.', 1)[0] + tail_name = fullname.rpartition('.')[2] + return filename_base == '__init__' and tail_name != '__init__' + + def create_module(self, spec): + """Use default semantics for module creation.""" + + def exec_module(self, module): + """Execute the module.""" + code = self.get_code(module.__name__) + if code is None: + raise ImportError('cannot load module {!r} when get_code() ' + 'returns None'.format(module.__name__)) + _bootstrap._call_with_frames_removed(exec, code, module.__dict__) + + def load_module(self, fullname): + """This module is deprecated.""" + return _bootstrap._load_module_shim(self, fullname) + + +class SourceLoader(_LoaderBasics): + + def path_mtime(self, path): + """Optional method that returns the modification time (an int) for the + specified path, where path is a str. + + Raises OSError when the path cannot be handled. + """ + raise OSError + + def path_stats(self, path): + """Optional method returning a metadata dict for the specified path + to by the path (str). + Possible keys: + - 'mtime' (mandatory) is the numeric timestamp of last source + code modification; + - 'size' (optional) is the size in bytes of the source code. + + Implementing this method allows the loader to read bytecode files. + Raises OSError when the path cannot be handled. + """ + return {'mtime': self.path_mtime(path)} + + def _cache_bytecode(self, source_path, cache_path, data): + """Optional method which writes data (bytes) to a file path (a str). + + Implementing this method allows for the writing of bytecode files. + + The source path is needed in order to correctly transfer permissions + """ + # For backwards compatibility, we delegate to set_data() + return self.set_data(cache_path, data) + + def set_data(self, path, data): + """Optional method which writes data (bytes) to a file path (a str). + + Implementing this method allows for the writing of bytecode files. + """ + + + def get_source(self, fullname): + """Concrete implementation of InspectLoader.get_source.""" + path = self.get_filename(fullname) + try: + source_bytes = self.get_data(path) + except OSError as exc: + raise ImportError('source not available through get_data()', + name=fullname) from exc + return decode_source(source_bytes) + + def source_to_code(self, data, path, *, _optimize=-1): + """Return the code object compiled from source. + + The 'data' argument can be any object type that compile() supports. + """ + return _bootstrap._call_with_frames_removed(compile, data, path, 'exec', + dont_inherit=True, optimize=_optimize) + + def get_code(self, fullname): + """Concrete implementation of InspectLoader.get_code. + + Reading of bytecode requires path_stats to be implemented. To write + bytecode, set_data must also be implemented. + + """ + source_path = self.get_filename(fullname) + source_mtime = None + source_bytes = None + source_hash = None + hash_based = False + check_source = True + try: + bytecode_path = cache_from_source(source_path) + except NotImplementedError: + bytecode_path = None + else: + try: + st = self.path_stats(source_path) + except OSError: + pass + else: + source_mtime = int(st['mtime']) + try: + data = self.get_data(bytecode_path) + except OSError: + pass + else: + exc_details = { + 'name': fullname, + 'path': bytecode_path, + } + try: + flags = _classify_pyc(data, fullname, exc_details) + bytes_data = memoryview(data)[16:] + hash_based = flags & 0b1 != 0 + if hash_based: + check_source = flags & 0b10 != 0 + if (_imp.check_hash_based_pycs != 'never' and + (check_source or + _imp.check_hash_based_pycs == 'always')): + source_bytes = self.get_data(source_path) + source_hash = _imp.source_hash( + _RAW_MAGIC_NUMBER, + source_bytes, + ) + _validate_hash_pyc(data, source_hash, fullname, + exc_details) + else: + _validate_timestamp_pyc( + data, + source_mtime, + st['size'], + fullname, + exc_details, + ) + except (ImportError, EOFError): + pass + else: + _bootstrap._verbose_message('{} matches {}', bytecode_path, + source_path) + return _compile_bytecode(bytes_data, name=fullname, + bytecode_path=bytecode_path, + source_path=source_path) + if source_bytes is None: + source_bytes = self.get_data(source_path) + code_object = self.source_to_code(source_bytes, source_path) + _bootstrap._verbose_message('code object from {}', source_path) + if (not sys.dont_write_bytecode and bytecode_path is not None and + source_mtime is not None): + if hash_based: + if source_hash is None: + source_hash = _imp.source_hash(source_bytes) + data = _code_to_hash_pyc(code_object, source_hash, check_source) + else: + data = _code_to_timestamp_pyc(code_object, source_mtime, + len(source_bytes)) + try: + self._cache_bytecode(source_path, bytecode_path, data) + _bootstrap._verbose_message('wrote {!r}', bytecode_path) + except NotImplementedError: + pass + return code_object + + +class FileLoader: + + """Base file loader class which implements the loader protocol methods that + require file system usage.""" + + def __init__(self, fullname, path): + """Cache the module name and the path to the file found by the + finder.""" + self.name = fullname + self.path = path + + def __eq__(self, other): + return (self.__class__ == other.__class__ and + self.__dict__ == other.__dict__) + + def __hash__(self): + return hash(self.name) ^ hash(self.path) + + @_check_name + def load_module(self, fullname): + """Load a module from a file. + + This method is deprecated. Use exec_module() instead. + + """ + # The only reason for this method is for the name check. + # Issue #14857: Avoid the zero-argument form of super so the implementation + # of that form can be updated without breaking the frozen module + return super(FileLoader, self).load_module(fullname) + + @_check_name + def get_filename(self, fullname): + """Return the path to the source file as found by the finder.""" + return self.path + + def get_data(self, path): + """Return the data from path as raw bytes.""" + with _io.FileIO(path, 'r') as file: + return file.read() + + # ResourceReader ABC API. + + @_check_name + def get_resource_reader(self, module): + if self.is_package(module): + return self + return None + + def open_resource(self, resource): + path = _path_join(_path_split(self.path)[0], resource) + return _io.FileIO(path, 'r') + + def resource_path(self, resource): + if not self.is_resource(resource): + raise FileNotFoundError + path = _path_join(_path_split(self.path)[0], resource) + return path + + def is_resource(self, name): + if path_sep in name: + return False + path = _path_join(_path_split(self.path)[0], name) + return _path_isfile(path) + + def contents(self): + return iter(_os.listdir(_path_split(self.path)[0])) + + +class SourceFileLoader(FileLoader, SourceLoader): + + """Concrete implementation of SourceLoader using the file system.""" + + def path_stats(self, path): + """Return the metadata for the path.""" + st = _path_stat(path) + return {'mtime': st.st_mtime, 'size': st.st_size} + + def _cache_bytecode(self, source_path, bytecode_path, data): + # Adapt between the two APIs + mode = _calc_mode(source_path) + return self.set_data(bytecode_path, data, _mode=mode) + + def set_data(self, path, data, *, _mode=0o666): + """Write bytes data to a file.""" + parent, filename = _path_split(path) + path_parts = [] + # Figure out what directories are missing. + while parent and not _path_isdir(parent): + parent, part = _path_split(parent) + path_parts.append(part) + # Create needed directories. + for part in reversed(path_parts): + parent = _path_join(parent, part) + try: + _os.mkdir(parent) + except FileExistsError: + # Probably another Python process already created the dir. + continue + except OSError as exc: + # Could be a permission error, read-only filesystem: just forget + # about writing the data. + _bootstrap._verbose_message('could not create {!r}: {!r}', + parent, exc) + return + try: + _write_atomic(path, data, _mode) + _bootstrap._verbose_message('created {!r}', path) + except OSError as exc: + # Same as above: just don't write the bytecode. + _bootstrap._verbose_message('could not create {!r}: {!r}', path, + exc) + + +class SourcelessFileLoader(FileLoader, _LoaderBasics): + + """Loader which handles sourceless file imports.""" + + def get_code(self, fullname): + path = self.get_filename(fullname) + data = self.get_data(path) + # Call _classify_pyc to do basic validation of the pyc but ignore the + # result. There's no source to check against. + exc_details = { + 'name': fullname, + 'path': path, + } + _classify_pyc(data, fullname, exc_details) + return _compile_bytecode( + memoryview(data)[16:], + name=fullname, + bytecode_path=path, + ) + + def get_source(self, fullname): + """Return None as there is no source code.""" + return None + + +# Filled in by _setup(). +EXTENSION_SUFFIXES = [] + + +class ExtensionFileLoader(FileLoader, _LoaderBasics): + + """Loader for extension modules. + + The constructor is designed to work with FileFinder. + + """ + + def __init__(self, name, path): + self.name = name + self.path = path + + def __eq__(self, other): + return (self.__class__ == other.__class__ and + self.__dict__ == other.__dict__) + + def __hash__(self): + return hash(self.name) ^ hash(self.path) + + def create_module(self, spec): + """Create an unitialized extension module""" + module = _bootstrap._call_with_frames_removed( + _imp.create_dynamic, spec) + _bootstrap._verbose_message('extension module {!r} loaded from {!r}', + spec.name, self.path) + return module + + def exec_module(self, module): + """Initialize an extension module""" + _bootstrap._call_with_frames_removed(_imp.exec_dynamic, module) + _bootstrap._verbose_message('extension module {!r} executed from {!r}', + self.name, self.path) + + def is_package(self, fullname): + """Return True if the extension module is a package.""" + file_name = _path_split(self.path)[1] + return any(file_name == '__init__' + suffix + for suffix in EXTENSION_SUFFIXES) + + def get_code(self, fullname): + """Return None as an extension module cannot create a code object.""" + return None + + def get_source(self, fullname): + """Return None as extension modules have no source code.""" + return None + + @_check_name + def get_filename(self, fullname): + """Return the path to the source file as found by the finder.""" + return self.path + + +class _NamespacePath: + """Represents a namespace package's path. It uses the module name + to find its parent module, and from there it looks up the parent's + __path__. When this changes, the module's own path is recomputed, + using path_finder. For top-level modules, the parent module's path + is sys.path.""" + + def __init__(self, name, path, path_finder): + self._name = name + self._path = path + self._last_parent_path = tuple(self._get_parent_path()) + self._path_finder = path_finder + + def _find_parent_path_names(self): + """Returns a tuple of (parent-module-name, parent-path-attr-name)""" + parent, dot, me = self._name.rpartition('.') + if dot == '': + # This is a top-level module. sys.path contains the parent path. + return 'sys', 'path' + # Not a top-level module. parent-module.__path__ contains the + # parent path. + return parent, '__path__' + + def _get_parent_path(self): + parent_module_name, path_attr_name = self._find_parent_path_names() + return getattr(sys.modules[parent_module_name], path_attr_name) + + def _recalculate(self): + # If the parent's path has changed, recalculate _path + parent_path = tuple(self._get_parent_path()) # Make a copy + if parent_path != self._last_parent_path: + spec = self._path_finder(self._name, parent_path) + # Note that no changes are made if a loader is returned, but we + # do remember the new parent path + if spec is not None and spec.loader is None: + if spec.submodule_search_locations: + self._path = spec.submodule_search_locations + self._last_parent_path = parent_path # Save the copy + return self._path + + def __iter__(self): + return iter(self._recalculate()) + + def __setitem__(self, index, path): + self._path[index] = path + + def __len__(self): + return len(self._recalculate()) + + def __repr__(self): + return '_NamespacePath({!r})'.format(self._path) + + def __contains__(self, item): + return item in self._recalculate() + + def append(self, item): + self._path.append(item) + + +# We use this exclusively in module_from_spec() for backward-compatibility. +class _NamespaceLoader: + def __init__(self, name, path, path_finder): + self._path = _NamespacePath(name, path, path_finder) + + @classmethod + def module_repr(cls, module): + """Return repr for the module. + + The method is deprecated. The import machinery does the job itself. + + """ + return ''.format(module.__name__) + + def is_package(self, fullname): + return True + + def get_source(self, fullname): + return '' + + def get_code(self, fullname): + return compile('', '', 'exec', dont_inherit=True) + + def create_module(self, spec): + """Use default semantics for module creation.""" + + def exec_module(self, module): + pass + + def load_module(self, fullname): + """Load a namespace module. + + This method is deprecated. Use exec_module() instead. + + """ + # The import system never calls this method. + _bootstrap._verbose_message('namespace module loaded with path {!r}', + self._path) + return _bootstrap._load_module_shim(self, fullname) + + +# Finders ##################################################################### + +class PathFinder: + + """Meta path finder for sys.path and package __path__ attributes.""" + + @classmethod + def invalidate_caches(cls): + """Call the invalidate_caches() method on all path entry finders + stored in sys.path_importer_caches (where implemented).""" + for name, finder in list(sys.path_importer_cache.items()): + if finder is None: + del sys.path_importer_cache[name] + elif hasattr(finder, 'invalidate_caches'): + finder.invalidate_caches() + + @classmethod + def _path_hooks(cls, path): + """Search sys.path_hooks for a finder for 'path'.""" + if sys.path_hooks is not None and not sys.path_hooks: + _warnings.warn('sys.path_hooks is empty', ImportWarning) + for hook in sys.path_hooks: + try: + return hook(path) + except ImportError: + continue + else: + return None + + @classmethod + def _path_importer_cache(cls, path): + """Get the finder for the path entry from sys.path_importer_cache. + + If the path entry is not in the cache, find the appropriate finder + and cache it. If no finder is available, store None. + + """ + if path == '': + try: + path = _os.getcwd() + except FileNotFoundError: + # Don't cache the failure as the cwd can easily change to + # a valid directory later on. + return None + try: + finder = sys.path_importer_cache[path] + except KeyError: + finder = cls._path_hooks(path) + sys.path_importer_cache[path] = finder + return finder + + @classmethod + def _legacy_get_spec(cls, fullname, finder): + # This would be a good place for a DeprecationWarning if + # we ended up going that route. + if hasattr(finder, 'find_loader'): + loader, portions = finder.find_loader(fullname) + else: + loader = finder.find_module(fullname) + portions = [] + if loader is not None: + return _bootstrap.spec_from_loader(fullname, loader) + spec = _bootstrap.ModuleSpec(fullname, None) + spec.submodule_search_locations = portions + return spec + + @classmethod + def _get_spec(cls, fullname, path, target=None): + """Find the loader or namespace_path for this module/package name.""" + # If this ends up being a namespace package, namespace_path is + # the list of paths that will become its __path__ + namespace_path = [] + for entry in path: + if not isinstance(entry, (str, bytes)): + continue + finder = cls._path_importer_cache(entry) + if finder is not None: + if hasattr(finder, 'find_spec'): + spec = finder.find_spec(fullname, target) + else: + spec = cls._legacy_get_spec(fullname, finder) + if spec is None: + continue + if spec.loader is not None: + return spec + portions = spec.submodule_search_locations + if portions is None: + raise ImportError('spec missing loader') + # This is possibly part of a namespace package. + # Remember these path entries (if any) for when we + # create a namespace package, and continue iterating + # on path. + namespace_path.extend(portions) + else: + spec = _bootstrap.ModuleSpec(fullname, None) + spec.submodule_search_locations = namespace_path + return spec + + @classmethod + def find_spec(cls, fullname, path=None, target=None): + """Try to find a spec for 'fullname' on sys.path or 'path'. + + The search is based on sys.path_hooks and sys.path_importer_cache. + """ + if path is None: + path = sys.path + spec = cls._get_spec(fullname, path, target) + if spec is None: + return None + elif spec.loader is None: + namespace_path = spec.submodule_search_locations + if namespace_path: + # We found at least one namespace path. Return a spec which + # can create the namespace package. + spec.origin = None + spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) + return spec + else: + return None + else: + return spec + + @classmethod + def find_module(cls, fullname, path=None): + """find the module on sys.path or 'path' based on sys.path_hooks and + sys.path_importer_cache. + + This method is deprecated. Use find_spec() instead. + + """ + spec = cls.find_spec(fullname, path) + if spec is None: + return None + return spec.loader + + +class FileFinder: + + """File-based finder. + + Interactions with the file system are cached for performance, being + refreshed when the directory the finder is handling has been modified. + + """ + + def __init__(self, path, *loader_details): + """Initialize with the path to search on and a variable number of + 2-tuples containing the loader and the file suffixes the loader + recognizes.""" + loaders = [] + for loader, suffixes in loader_details: + loaders.extend((suffix, loader) for suffix in suffixes) + self._loaders = loaders + # Base (directory) path + self.path = path or '.' + self._path_mtime = -1 + self._path_cache = set() + self._relaxed_path_cache = set() + + def invalidate_caches(self): + """Invalidate the directory mtime.""" + self._path_mtime = -1 + + find_module = _find_module_shim + + def find_loader(self, fullname): + """Try to find a loader for the specified module, or the namespace + package portions. Returns (loader, list-of-portions). + + This method is deprecated. Use find_spec() instead. + + """ + spec = self.find_spec(fullname) + if spec is None: + return None, [] + return spec.loader, spec.submodule_search_locations or [] + + def _get_spec(self, loader_class, fullname, path, smsl, target): + loader = loader_class(fullname, path) + return spec_from_file_location(fullname, path, loader=loader, + submodule_search_locations=smsl) + + def find_spec(self, fullname, target=None): + """Try to find a spec for the specified module. + + Returns the matching spec, or None if not found. + """ + is_namespace = False + tail_module = fullname.rpartition('.')[2] + try: + mtime = _path_stat(self.path or _os.getcwd()).st_mtime + except OSError: + mtime = -1 + if mtime != self._path_mtime: + self._fill_cache() + self._path_mtime = mtime + # tail_module keeps the original casing, for __file__ and friends + if _relax_case(): + cache = self._relaxed_path_cache + cache_module = tail_module.lower() + else: + cache = self._path_cache + cache_module = tail_module + # Check if the module is the name of a directory (and thus a package). + if cache_module in cache: + base_path = _path_join(self.path, tail_module) + for suffix, loader_class in self._loaders: + init_filename = '__init__' + suffix + full_path = _path_join(base_path, init_filename) + if _path_isfile(full_path): + return self._get_spec(loader_class, fullname, full_path, [base_path], target) + else: + # If a namespace package, return the path if we don't + # find a module in the next section. + is_namespace = _path_isdir(base_path) + # Check for a file w/ a proper suffix exists. + for suffix, loader_class in self._loaders: + full_path = _path_join(self.path, tail_module + suffix) + _bootstrap._verbose_message('trying {}', full_path, verbosity=2) + if cache_module + suffix in cache: + if _path_isfile(full_path): + return self._get_spec(loader_class, fullname, full_path, + None, target) + if is_namespace: + _bootstrap._verbose_message('possible namespace for {}', base_path) + spec = _bootstrap.ModuleSpec(fullname, None) + spec.submodule_search_locations = [base_path] + return spec + return None + + def _fill_cache(self): + """Fill the cache of potential modules and packages for this directory.""" + path = self.path + try: + contents = _os.listdir(path or _os.getcwd()) + except (FileNotFoundError, PermissionError, NotADirectoryError): + # Directory has either been removed, turned into a file, or made + # unreadable. + contents = [] + # We store two cached versions, to handle runtime changes of the + # PYTHONCASEOK environment variable. + if not sys.platform.startswith('win'): + self._path_cache = set(contents) + else: + # Windows users can import modules with case-insensitive file + # suffixes (for legacy reasons). Make the suffix lowercase here + # so it's done once instead of for every import. This is safe as + # the specified suffixes to check against are always specified in a + # case-sensitive manner. + lower_suffix_contents = set() + for item in contents: + name, dot, suffix = item.partition('.') + if dot: + new_name = '{}.{}'.format(name, suffix.lower()) + else: + new_name = name + lower_suffix_contents.add(new_name) + self._path_cache = lower_suffix_contents + if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): + self._relaxed_path_cache = {fn.lower() for fn in contents} + + @classmethod + def path_hook(cls, *loader_details): + """A class method which returns a closure to use on sys.path_hook + which will return an instance using the specified loaders and the path + called on the closure. + + If the path called on the closure is not a directory, ImportError is + raised. + + """ + def path_hook_for_FileFinder(path): + """Path hook for importlib.machinery.FileFinder.""" + if not _path_isdir(path): + raise ImportError('only directories are supported', path=path) + return cls(path, *loader_details) + + return path_hook_for_FileFinder + + def __repr__(self): + return 'FileFinder({!r})'.format(self.path) + + +# Import setup ############################################################### + +def _fix_up_module(ns, name, pathname, cpathname=None): + # This function is used by PyImport_ExecCodeModuleObject(). + loader = ns.get('__loader__') + spec = ns.get('__spec__') + if not loader: + if spec: + loader = spec.loader + elif pathname == cpathname: + loader = SourcelessFileLoader(name, pathname) + else: + loader = SourceFileLoader(name, pathname) + if not spec: + spec = spec_from_file_location(name, pathname, loader=loader) + try: + ns['__spec__'] = spec + ns['__loader__'] = loader + ns['__file__'] = pathname + ns['__cached__'] = cpathname + except Exception: + # Not important enough to report. + pass + + +def _get_supported_file_loaders(): + """Returns a list of file-based module loaders. + + Each item is a tuple (loader, suffixes). + """ + extensions = ExtensionFileLoader, _imp.extension_suffixes() + source = SourceFileLoader, SOURCE_SUFFIXES + bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES + return [extensions, source, bytecode] + + +def _setup(_bootstrap_module): + """Setup the path-based importers for importlib by importing needed + built-in modules and injecting them into the global namespace. + + Other components are extracted from the core bootstrap module. + + """ + global sys, _imp, _bootstrap + _bootstrap = _bootstrap_module + sys = _bootstrap.sys + _imp = _bootstrap._imp + + # Directly load built-in modules needed during bootstrap. + self_module = sys.modules[__name__] + for builtin_name in ('_io', '_warnings', 'builtins', 'marshal'): + if builtin_name not in sys.modules: + builtin_module = _bootstrap._builtin_from_name(builtin_name) + else: + builtin_module = sys.modules[builtin_name] + setattr(self_module, builtin_name, builtin_module) + + # Directly load the os module (needed during bootstrap). + os_details = ('posix', ['/']), ('nt', ['\\', '/']) + for builtin_os, path_separators in os_details: + # Assumption made in _path_join() + assert all(len(sep) == 1 for sep in path_separators) + path_sep = path_separators[0] + if builtin_os in sys.modules: + os_module = sys.modules[builtin_os] + break + else: + try: + os_module = _bootstrap._builtin_from_name(builtin_os) + break + except ImportError: + continue + else: + raise ImportError('importlib requires posix or nt') + setattr(self_module, '_os', os_module) + setattr(self_module, 'path_sep', path_sep) + setattr(self_module, 'path_separators', ''.join(path_separators)) + + # Directly load the _thread module (needed during bootstrap). + thread_module = _bootstrap._builtin_from_name('_thread') + setattr(self_module, '_thread', thread_module) + + # Directly load the _weakref module (needed during bootstrap). + weakref_module = _bootstrap._builtin_from_name('_weakref') + setattr(self_module, '_weakref', weakref_module) + + # Directly load the winreg module (needed during bootstrap). + if builtin_os == 'nt': + winreg_module = _bootstrap._builtin_from_name('winreg') + setattr(self_module, '_winreg', winreg_module) + + # Constants + setattr(self_module, '_relax_case', _make_relax_case()) + EXTENSION_SUFFIXES.extend(_imp.extension_suffixes()) + if builtin_os == 'nt': + SOURCE_SUFFIXES.append('.pyw') + if '_d.pyd' in EXTENSION_SUFFIXES: + WindowsRegistryFinder.DEBUG_BUILD = True + + +def _install(_bootstrap_module): + """Install the path-based import components.""" + _setup(_bootstrap_module) + supported_loaders = _get_supported_file_loaders() + sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)]) + sys.meta_path.append(PathFinder) diff --git a/winvenv/Lib/importlib/abc.py b/winvenv/Lib/importlib/abc.py new file mode 100644 index 0000000..dbdd5bf --- /dev/null +++ b/winvenv/Lib/importlib/abc.py @@ -0,0 +1,388 @@ +"""Abstract base classes related to import.""" +from . import _bootstrap +from . import _bootstrap_external +from . import machinery +try: + import _frozen_importlib +except ImportError as exc: + if exc.name != '_frozen_importlib': + raise + _frozen_importlib = None +try: + import _frozen_importlib_external +except ImportError as exc: + _frozen_importlib_external = _bootstrap_external +import abc +import warnings + + +def _register(abstract_cls, *classes): + for cls in classes: + abstract_cls.register(cls) + if _frozen_importlib is not None: + try: + frozen_cls = getattr(_frozen_importlib, cls.__name__) + except AttributeError: + frozen_cls = getattr(_frozen_importlib_external, cls.__name__) + abstract_cls.register(frozen_cls) + + +class Finder(metaclass=abc.ABCMeta): + + """Legacy abstract base class for import finders. + + It may be subclassed for compatibility with legacy third party + reimplementations of the import system. Otherwise, finder + implementations should derive from the more specific MetaPathFinder + or PathEntryFinder ABCs. + + Deprecated since Python 3.3 + """ + + @abc.abstractmethod + def find_module(self, fullname, path=None): + """An abstract method that should find a module. + The fullname is a str and the optional path is a str or None. + Returns a Loader object or None. + """ + + +class MetaPathFinder(Finder): + + """Abstract base class for import finders on sys.meta_path.""" + + # We don't define find_spec() here since that would break + # hasattr checks we do to support backward compatibility. + + def find_module(self, fullname, path): + """Return a loader for the module. + + If no module is found, return None. The fullname is a str and + the path is a list of strings or None. + + This method is deprecated since Python 3.4 in favor of + finder.find_spec(). If find_spec() exists then backwards-compatible + functionality is provided for this method. + + """ + warnings.warn("MetaPathFinder.find_module() is deprecated since Python " + "3.4 in favor of MetaPathFinder.find_spec()" + "(available since 3.4)", + DeprecationWarning, + stacklevel=2) + if not hasattr(self, 'find_spec'): + return None + found = self.find_spec(fullname, path) + return found.loader if found is not None else None + + def invalidate_caches(self): + """An optional method for clearing the finder's cache, if any. + This method is used by importlib.invalidate_caches(). + """ + +_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter, + machinery.PathFinder, machinery.WindowsRegistryFinder) + + +class PathEntryFinder(Finder): + + """Abstract base class for path entry finders used by PathFinder.""" + + # We don't define find_spec() here since that would break + # hasattr checks we do to support backward compatibility. + + def find_loader(self, fullname): + """Return (loader, namespace portion) for the path entry. + + The fullname is a str. The namespace portion is a sequence of + path entries contributing to part of a namespace package. The + sequence may be empty. If loader is not None, the portion will + be ignored. + + The portion will be discarded if another path entry finder + locates the module as a normal module or package. + + This method is deprecated since Python 3.4 in favor of + finder.find_spec(). If find_spec() is provided than backwards-compatible + functionality is provided. + """ + warnings.warn("PathEntryFinder.find_loader() is deprecated since Python " + "3.4 in favor of PathEntryFinder.find_spec() " + "(available since 3.4)", + DeprecationWarning, + stacklevel=2) + if not hasattr(self, 'find_spec'): + return None, [] + found = self.find_spec(fullname) + if found is not None: + if not found.submodule_search_locations: + portions = [] + else: + portions = found.submodule_search_locations + return found.loader, portions + else: + return None, [] + + find_module = _bootstrap_external._find_module_shim + + def invalidate_caches(self): + """An optional method for clearing the finder's cache, if any. + This method is used by PathFinder.invalidate_caches(). + """ + +_register(PathEntryFinder, machinery.FileFinder) + + +class Loader(metaclass=abc.ABCMeta): + + """Abstract base class for import loaders.""" + + def create_module(self, spec): + """Return a module to initialize and into which to load. + + This method should raise ImportError if anything prevents it + from creating a new module. It may return None to indicate + that the spec should create the new module. + """ + # By default, defer to default semantics for the new module. + return None + + # We don't define exec_module() here since that would break + # hasattr checks we do to support backward compatibility. + + def load_module(self, fullname): + """Return the loaded module. + + The module must be added to sys.modules and have import-related + attributes set properly. The fullname is a str. + + ImportError is raised on failure. + + This method is deprecated in favor of loader.exec_module(). If + exec_module() exists then it is used to provide a backwards-compatible + functionality for this method. + + """ + if not hasattr(self, 'exec_module'): + raise ImportError + return _bootstrap._load_module_shim(self, fullname) + + def module_repr(self, module): + """Return a module's repr. + + Used by the module type when the method does not raise + NotImplementedError. + + This method is deprecated. + + """ + # The exception will cause ModuleType.__repr__ to ignore this method. + raise NotImplementedError + + +class ResourceLoader(Loader): + + """Abstract base class for loaders which can return data from their + back-end storage. + + This ABC represents one of the optional protocols specified by PEP 302. + + """ + + @abc.abstractmethod + def get_data(self, path): + """Abstract method which when implemented should return the bytes for + the specified path. The path must be a str.""" + raise OSError + + +class InspectLoader(Loader): + + """Abstract base class for loaders which support inspection about the + modules they can load. + + This ABC represents one of the optional protocols specified by PEP 302. + + """ + + def is_package(self, fullname): + """Optional method which when implemented should return whether the + module is a package. The fullname is a str. Returns a bool. + + Raises ImportError if the module cannot be found. + """ + raise ImportError + + def get_code(self, fullname): + """Method which returns the code object for the module. + + The fullname is a str. Returns a types.CodeType if possible, else + returns None if a code object does not make sense + (e.g. built-in module). Raises ImportError if the module cannot be + found. + """ + source = self.get_source(fullname) + if source is None: + return None + return self.source_to_code(source) + + @abc.abstractmethod + def get_source(self, fullname): + """Abstract method which should return the source code for the + module. The fullname is a str. Returns a str. + + Raises ImportError if the module cannot be found. + """ + raise ImportError + + @staticmethod + def source_to_code(data, path=''): + """Compile 'data' into a code object. + + The 'data' argument can be anything that compile() can handle. The'path' + argument should be where the data was retrieved (when applicable).""" + return compile(data, path, 'exec', dont_inherit=True) + + exec_module = _bootstrap_external._LoaderBasics.exec_module + load_module = _bootstrap_external._LoaderBasics.load_module + +_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter) + + +class ExecutionLoader(InspectLoader): + + """Abstract base class for loaders that wish to support the execution of + modules as scripts. + + This ABC represents one of the optional protocols specified in PEP 302. + + """ + + @abc.abstractmethod + def get_filename(self, fullname): + """Abstract method which should return the value that __file__ is to be + set to. + + Raises ImportError if the module cannot be found. + """ + raise ImportError + + def get_code(self, fullname): + """Method to return the code object for fullname. + + Should return None if not applicable (e.g. built-in module). + Raise ImportError if the module cannot be found. + """ + source = self.get_source(fullname) + if source is None: + return None + try: + path = self.get_filename(fullname) + except ImportError: + return self.source_to_code(source) + else: + return self.source_to_code(source, path) + +_register(ExecutionLoader, machinery.ExtensionFileLoader) + + +class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader): + + """Abstract base class partially implementing the ResourceLoader and + ExecutionLoader ABCs.""" + +_register(FileLoader, machinery.SourceFileLoader, + machinery.SourcelessFileLoader) + + +class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader): + + """Abstract base class for loading source code (and optionally any + corresponding bytecode). + + To support loading from source code, the abstractmethods inherited from + ResourceLoader and ExecutionLoader need to be implemented. To also support + loading from bytecode, the optional methods specified directly by this ABC + is required. + + Inherited abstractmethods not implemented in this ABC: + + * ResourceLoader.get_data + * ExecutionLoader.get_filename + + """ + + def path_mtime(self, path): + """Return the (int) modification time for the path (str).""" + if self.path_stats.__func__ is SourceLoader.path_stats: + raise OSError + return int(self.path_stats(path)['mtime']) + + def path_stats(self, path): + """Return a metadata dict for the source pointed to by the path (str). + Possible keys: + - 'mtime' (mandatory) is the numeric timestamp of last source + code modification; + - 'size' (optional) is the size in bytes of the source code. + """ + if self.path_mtime.__func__ is SourceLoader.path_mtime: + raise OSError + return {'mtime': self.path_mtime(path)} + + def set_data(self, path, data): + """Write the bytes to the path (if possible). + + Accepts a str path and data as bytes. + + Any needed intermediary directories are to be created. If for some + reason the file cannot be written because of permissions, fail + silently. + """ + +_register(SourceLoader, machinery.SourceFileLoader) + + +class ResourceReader(metaclass=abc.ABCMeta): + + """Abstract base class to provide resource-reading support. + + Loaders that support resource reading are expected to implement + the ``get_resource_reader(fullname)`` method and have it either return None + or an object compatible with this ABC. + """ + + @abc.abstractmethod + def open_resource(self, resource): + """Return an opened, file-like object for binary reading. + + The 'resource' argument is expected to represent only a file name + and thus not contain any subdirectory components. + + If the resource cannot be found, FileNotFoundError is raised. + """ + raise FileNotFoundError + + @abc.abstractmethod + def resource_path(self, resource): + """Return the file system path to the specified resource. + + The 'resource' argument is expected to represent only a file name + and thus not contain any subdirectory components. + + If the resource does not exist on the file system, raise + FileNotFoundError. + """ + raise FileNotFoundError + + @abc.abstractmethod + def is_resource(self, name): + """Return True if the named 'name' is consider a resource.""" + raise FileNotFoundError + + @abc.abstractmethod + def contents(self): + """Return an iterable of strings over the contents of the package.""" + return [] + + +_register(ResourceReader, machinery.SourceFileLoader) diff --git a/winvenv/Lib/importlib/machinery.py b/winvenv/Lib/importlib/machinery.py new file mode 100644 index 0000000..1b2b5c9 --- /dev/null +++ b/winvenv/Lib/importlib/machinery.py @@ -0,0 +1,21 @@ +"""The machinery of importlib: finders, loaders, hooks, etc.""" + +import _imp + +from ._bootstrap import ModuleSpec +from ._bootstrap import BuiltinImporter +from ._bootstrap import FrozenImporter +from ._bootstrap_external import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES, + OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES, + EXTENSION_SUFFIXES) +from ._bootstrap_external import WindowsRegistryFinder +from ._bootstrap_external import PathFinder +from ._bootstrap_external import FileFinder +from ._bootstrap_external import SourceFileLoader +from ._bootstrap_external import SourcelessFileLoader +from ._bootstrap_external import ExtensionFileLoader + + +def all_suffixes(): + """Returns a list of all recognized module suffixes for this process""" + return SOURCE_SUFFIXES + BYTECODE_SUFFIXES + EXTENSION_SUFFIXES diff --git a/winvenv/Lib/importlib/resources.py b/winvenv/Lib/importlib/resources.py new file mode 100644 index 0000000..cbefdd5 --- /dev/null +++ b/winvenv/Lib/importlib/resources.py @@ -0,0 +1,343 @@ +import os +import tempfile + +from . import abc as resources_abc +from contextlib import contextmanager, suppress +from importlib import import_module +from importlib.abc import ResourceLoader +from io import BytesIO, TextIOWrapper +from pathlib import Path +from types import ModuleType +from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401 +from typing import cast +from typing.io import BinaryIO, TextIO +from zipimport import ZipImportError + + +__all__ = [ + 'Package', + 'Resource', + 'contents', + 'is_resource', + 'open_binary', + 'open_text', + 'path', + 'read_binary', + 'read_text', + ] + + +Package = Union[str, ModuleType] +Resource = Union[str, os.PathLike] + + +def _get_package(package) -> ModuleType: + """Take a package name or module object and return the module. + + If a name, the module is imported. If the passed or imported module + object is not a package, raise an exception. + """ + if hasattr(package, '__spec__'): + if package.__spec__.submodule_search_locations is None: + raise TypeError('{!r} is not a package'.format( + package.__spec__.name)) + else: + return package + else: + module = import_module(package) + if module.__spec__.submodule_search_locations is None: + raise TypeError('{!r} is not a package'.format(package)) + else: + return module + + +def _normalize_path(path) -> str: + """Normalize a path by ensuring it is a string. + + If the resulting string contains path separators, an exception is raised. + """ + parent, file_name = os.path.split(path) + if parent: + raise ValueError('{!r} must be only a file name'.format(path)) + else: + return file_name + + +def _get_resource_reader( + package: ModuleType) -> Optional[resources_abc.ResourceReader]: + # Return the package's loader if it's a ResourceReader. We can't use + # a issubclass() check here because apparently abc.'s __subclasscheck__() + # hook wants to create a weak reference to the object, but + # zipimport.zipimporter does not support weak references, resulting in a + # TypeError. That seems terrible. + spec = package.__spec__ + if hasattr(spec.loader, 'get_resource_reader'): + return cast(resources_abc.ResourceReader, + spec.loader.get_resource_reader(spec.name)) + return None + + +def _check_location(package): + if package.__spec__.origin is None or not package.__spec__.has_location: + raise FileNotFoundError(f'Package has no location {package!r}') + + +def open_binary(package: Package, resource: Resource) -> BinaryIO: + """Return a file-like object opened for binary reading of the resource.""" + resource = _normalize_path(resource) + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + return reader.open_resource(resource) + _check_location(package) + absolute_package_path = os.path.abspath(package.__spec__.origin) + package_path = os.path.dirname(absolute_package_path) + full_path = os.path.join(package_path, resource) + try: + return open(full_path, mode='rb') + except OSError: + # Just assume the loader is a resource loader; all the relevant + # importlib.machinery loaders are and an AttributeError for + # get_data() will make it clear what is needed from the loader. + loader = cast(ResourceLoader, package.__spec__.loader) + data = None + if hasattr(package.__spec__.loader, 'get_data'): + with suppress(OSError): + data = loader.get_data(full_path) + if data is None: + package_name = package.__spec__.name + message = '{!r} resource not found in {!r}'.format( + resource, package_name) + raise FileNotFoundError(message) + else: + return BytesIO(data) + + +def open_text(package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict') -> TextIO: + """Return a file-like object opened for text reading of the resource.""" + resource = _normalize_path(resource) + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + return TextIOWrapper(reader.open_resource(resource), encoding, errors) + _check_location(package) + absolute_package_path = os.path.abspath(package.__spec__.origin) + package_path = os.path.dirname(absolute_package_path) + full_path = os.path.join(package_path, resource) + try: + return open(full_path, mode='r', encoding=encoding, errors=errors) + except OSError: + # Just assume the loader is a resource loader; all the relevant + # importlib.machinery loaders are and an AttributeError for + # get_data() will make it clear what is needed from the loader. + loader = cast(ResourceLoader, package.__spec__.loader) + data = None + if hasattr(package.__spec__.loader, 'get_data'): + with suppress(OSError): + data = loader.get_data(full_path) + if data is None: + package_name = package.__spec__.name + message = '{!r} resource not found in {!r}'.format( + resource, package_name) + raise FileNotFoundError(message) + else: + return TextIOWrapper(BytesIO(data), encoding, errors) + + +def read_binary(package: Package, resource: Resource) -> bytes: + """Return the binary contents of the resource.""" + resource = _normalize_path(resource) + package = _get_package(package) + with open_binary(package, resource) as fp: + return fp.read() + + +def read_text(package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict') -> str: + """Return the decoded string of the resource. + + The decoding-related arguments have the same semantics as those of + bytes.decode(). + """ + resource = _normalize_path(resource) + package = _get_package(package) + with open_text(package, resource, encoding, errors) as fp: + return fp.read() + + +@contextmanager +def path(package: Package, resource: Resource) -> Iterator[Path]: + """A context manager providing a file path object to the resource. + + If the resource does not already exist on its own on the file system, + a temporary file will be created. If the file was created, the file + will be deleted upon exiting the context manager (no exception is + raised if the file was deleted prior to the context manager + exiting). + """ + resource = _normalize_path(resource) + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + try: + yield Path(reader.resource_path(resource)) + return + except FileNotFoundError: + pass + else: + _check_location(package) + # Fall-through for both the lack of resource_path() *and* if + # resource_path() raises FileNotFoundError. + package_directory = Path(package.__spec__.origin).parent + file_path = package_directory / resource + if file_path.exists(): + yield file_path + else: + with open_binary(package, resource) as fp: + data = fp.read() + # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' + # blocks due to the need to close the temporary file to work on + # Windows properly. + fd, raw_path = tempfile.mkstemp() + try: + os.write(fd, data) + os.close(fd) + yield Path(raw_path) + finally: + try: + os.remove(raw_path) + except FileNotFoundError: + pass + + +def is_resource(package: Package, name: str) -> bool: + """True if 'name' is a resource inside 'package'. + + Directories are *not* resources. + """ + package = _get_package(package) + _normalize_path(name) + reader = _get_resource_reader(package) + if reader is not None: + return reader.is_resource(name) + try: + package_contents = set(contents(package)) + except (NotADirectoryError, FileNotFoundError): + return False + if name not in package_contents: + return False + # Just because the given file_name lives as an entry in the package's + # contents doesn't necessarily mean it's a resource. Directories are not + # resources, so let's try to find out if it's a directory or not. + path = Path(package.__spec__.origin).parent / name + return path.is_file() + + +def contents(package: Package) -> Iterable[str]: + """Return an iterable of entries in 'package'. + + Note that not all entries are resources. Specifically, directories are + not considered resources. Use `is_resource()` on each entry returned here + to check if it is a resource or not. + """ + package = _get_package(package) + reader = _get_resource_reader(package) + if reader is not None: + return reader.contents() + # Is the package a namespace package? By definition, namespace packages + # cannot have resources. We could use _check_location() and catch the + # exception, but that's extra work, so just inline the check. + elif package.__spec__.origin is None or not package.__spec__.has_location: + return () + else: + package_directory = Path(package.__spec__.origin).parent + return os.listdir(package_directory) + + +# Private implementation of ResourceReader and get_resource_reader() called +# from zipimport.c. Don't use these directly! We're implementing these in +# Python because 1) it's easier, 2) zipimport may get rewritten in Python +# itself at some point, so doing this all in C would difficult and a waste of +# effort. + +class _ZipImportResourceReader(resources_abc.ResourceReader): + """Private class used to support ZipImport.get_resource_reader(). + + This class is allowed to reference all the innards and private parts of + the zipimporter. + """ + + def __init__(self, zipimporter, fullname): + self.zipimporter = zipimporter + self.fullname = fullname + + def open_resource(self, resource): + fullname_as_path = self.fullname.replace('.', '/') + path = f'{fullname_as_path}/{resource}' + try: + return BytesIO(self.zipimporter.get_data(path)) + except OSError: + raise FileNotFoundError(path) + + def resource_path(self, resource): + # All resources are in the zip file, so there is no path to the file. + # Raising FileNotFoundError tells the higher level API to extract the + # binary data and create a temporary file. + raise FileNotFoundError + + def is_resource(self, name): + # Maybe we could do better, but if we can get the data, it's a + # resource. Otherwise it isn't. + fullname_as_path = self.fullname.replace('.', '/') + path = f'{fullname_as_path}/{name}' + try: + self.zipimporter.get_data(path) + except OSError: + return False + return True + + def contents(self): + # This is a bit convoluted, because fullname will be a module path, + # but _files is a list of file names relative to the top of the + # archive's namespace. We want to compare file paths to find all the + # names of things inside the module represented by fullname. So we + # turn the module path of fullname into a file path relative to the + # top of the archive, and then we iterate through _files looking for + # names inside that "directory". + fullname_path = Path(self.zipimporter.get_filename(self.fullname)) + relative_path = fullname_path.relative_to(self.zipimporter.archive) + # Don't forget that fullname names a package, so its path will include + # __init__.py, which we want to ignore. + assert relative_path.name == '__init__.py' + package_path = relative_path.parent + subdirs_seen = set() + for filename in self.zipimporter._files: + try: + relative = Path(filename).relative_to(package_path) + except ValueError: + continue + # If the path of the file (which is relative to the top of the zip + # namespace), relative to the package given when the resource + # reader was created, has a parent, then it's a name in a + # subdirectory and thus we skip it. + parent_name = relative.parent.name + if len(parent_name) == 0: + yield relative.name + elif parent_name not in subdirs_seen: + subdirs_seen.add(parent_name) + yield parent_name + + +# Called from zipimport.c +def _zipimport_get_resource_reader(zipimporter, fullname): + try: + if not zipimporter.is_package(fullname): + return None + except ZipImportError: + return None + return _ZipImportResourceReader(zipimporter, fullname) diff --git a/winvenv/Lib/importlib/util.py b/winvenv/Lib/importlib/util.py new file mode 100644 index 0000000..201e0f4 --- /dev/null +++ b/winvenv/Lib/importlib/util.py @@ -0,0 +1,300 @@ +"""Utility code for constructing importers, etc.""" +from . import abc +from ._bootstrap import module_from_spec +from ._bootstrap import _resolve_name +from ._bootstrap import spec_from_loader +from ._bootstrap import _find_spec +from ._bootstrap_external import MAGIC_NUMBER +from ._bootstrap_external import _RAW_MAGIC_NUMBER +from ._bootstrap_external import cache_from_source +from ._bootstrap_external import decode_source +from ._bootstrap_external import source_from_cache +from ._bootstrap_external import spec_from_file_location + +from contextlib import contextmanager +import _imp +import functools +import sys +import types +import warnings + + +def source_hash(source_bytes): + "Return the hash of *source_bytes* as used in hash-based pyc files." + return _imp.source_hash(_RAW_MAGIC_NUMBER, source_bytes) + + +def resolve_name(name, package): + """Resolve a relative module name to an absolute one.""" + if not name.startswith('.'): + return name + elif not package: + raise ValueError(f'no package specified for {repr(name)} ' + '(required for relative module names)') + level = 0 + for character in name: + if character != '.': + break + level += 1 + return _resolve_name(name[level:], package, level) + + +def _find_spec_from_path(name, path=None): + """Return the spec for the specified module. + + First, sys.modules is checked to see if the module was already imported. If + so, then sys.modules[name].__spec__ is returned. If that happens to be + set to None, then ValueError is raised. If the module is not in + sys.modules, then sys.meta_path is searched for a suitable spec with the + value of 'path' given to the finders. None is returned if no spec could + be found. + + Dotted names do not have their parent packages implicitly imported. You will + most likely need to explicitly import all parent packages in the proper + order for a submodule to get the correct spec. + + """ + if name not in sys.modules: + return _find_spec(name, path) + else: + module = sys.modules[name] + if module is None: + return None + try: + spec = module.__spec__ + except AttributeError: + raise ValueError('{}.__spec__ is not set'.format(name)) from None + else: + if spec is None: + raise ValueError('{}.__spec__ is None'.format(name)) + return spec + + +def find_spec(name, package=None): + """Return the spec for the specified module. + + First, sys.modules is checked to see if the module was already imported. If + so, then sys.modules[name].__spec__ is returned. If that happens to be + set to None, then ValueError is raised. If the module is not in + sys.modules, then sys.meta_path is searched for a suitable spec with the + value of 'path' given to the finders. None is returned if no spec could + be found. + + If the name is for submodule (contains a dot), the parent module is + automatically imported. + + The name and package arguments work the same as importlib.import_module(). + In other words, relative module names (with leading dots) work. + + """ + fullname = resolve_name(name, package) if name.startswith('.') else name + if fullname not in sys.modules: + parent_name = fullname.rpartition('.')[0] + if parent_name: + parent = __import__(parent_name, fromlist=['__path__']) + try: + parent_path = parent.__path__ + except AttributeError as e: + raise ModuleNotFoundError( + f"__path__ attribute not found on {parent_name!r} " + f"while trying to find {fullname!r}", name=fullname) from e + else: + parent_path = None + return _find_spec(fullname, parent_path) + else: + module = sys.modules[fullname] + if module is None: + return None + try: + spec = module.__spec__ + except AttributeError: + raise ValueError('{}.__spec__ is not set'.format(name)) from None + else: + if spec is None: + raise ValueError('{}.__spec__ is None'.format(name)) + return spec + + +@contextmanager +def _module_to_load(name): + is_reload = name in sys.modules + + module = sys.modules.get(name) + if not is_reload: + # This must be done before open() is called as the 'io' module + # implicitly imports 'locale' and would otherwise trigger an + # infinite loop. + module = type(sys)(name) + # This must be done before putting the module in sys.modules + # (otherwise an optimization shortcut in import.c becomes wrong) + module.__initializing__ = True + sys.modules[name] = module + try: + yield module + except Exception: + if not is_reload: + try: + del sys.modules[name] + except KeyError: + pass + finally: + module.__initializing__ = False + + +def set_package(fxn): + """Set __package__ on the returned module. + + This function is deprecated. + + """ + @functools.wraps(fxn) + def set_package_wrapper(*args, **kwargs): + warnings.warn('The import system now takes care of this automatically.', + DeprecationWarning, stacklevel=2) + module = fxn(*args, **kwargs) + if getattr(module, '__package__', None) is None: + module.__package__ = module.__name__ + if not hasattr(module, '__path__'): + module.__package__ = module.__package__.rpartition('.')[0] + return module + return set_package_wrapper + + +def set_loader(fxn): + """Set __loader__ on the returned module. + + This function is deprecated. + + """ + @functools.wraps(fxn) + def set_loader_wrapper(self, *args, **kwargs): + warnings.warn('The import system now takes care of this automatically.', + DeprecationWarning, stacklevel=2) + module = fxn(self, *args, **kwargs) + if getattr(module, '__loader__', None) is None: + module.__loader__ = self + return module + return set_loader_wrapper + + +def module_for_loader(fxn): + """Decorator to handle selecting the proper module for loaders. + + The decorated function is passed the module to use instead of the module + name. The module passed in to the function is either from sys.modules if + it already exists or is a new module. If the module is new, then __name__ + is set the first argument to the method, __loader__ is set to self, and + __package__ is set accordingly (if self.is_package() is defined) will be set + before it is passed to the decorated function (if self.is_package() does + not work for the module it will be set post-load). + + If an exception is raised and the decorator created the module it is + subsequently removed from sys.modules. + + The decorator assumes that the decorated function takes the module name as + the second argument. + + """ + warnings.warn('The import system now takes care of this automatically.', + DeprecationWarning, stacklevel=2) + @functools.wraps(fxn) + def module_for_loader_wrapper(self, fullname, *args, **kwargs): + with _module_to_load(fullname) as module: + module.__loader__ = self + try: + is_package = self.is_package(fullname) + except (ImportError, AttributeError): + pass + else: + if is_package: + module.__package__ = fullname + else: + module.__package__ = fullname.rpartition('.')[0] + # If __package__ was not set above, __import__() will do it later. + return fxn(self, module, *args, **kwargs) + + return module_for_loader_wrapper + + +class _LazyModule(types.ModuleType): + + """A subclass of the module type which triggers loading upon attribute access.""" + + def __getattribute__(self, attr): + """Trigger the load of the module and return the attribute.""" + # All module metadata must be garnered from __spec__ in order to avoid + # using mutated values. + # Stop triggering this method. + self.__class__ = types.ModuleType + # Get the original name to make sure no object substitution occurred + # in sys.modules. + original_name = self.__spec__.name + # Figure out exactly what attributes were mutated between the creation + # of the module and now. + attrs_then = self.__spec__.loader_state['__dict__'] + original_type = self.__spec__.loader_state['__class__'] + attrs_now = self.__dict__ + attrs_updated = {} + for key, value in attrs_now.items(): + # Code that set the attribute may have kept a reference to the + # assigned object, making identity more important than equality. + if key not in attrs_then: + attrs_updated[key] = value + elif id(attrs_now[key]) != id(attrs_then[key]): + attrs_updated[key] = value + self.__spec__.loader.exec_module(self) + # If exec_module() was used directly there is no guarantee the module + # object was put into sys.modules. + if original_name in sys.modules: + if id(self) != id(sys.modules[original_name]): + raise ValueError(f"module object for {original_name!r} " + "substituted in sys.modules during a lazy " + "load") + # Update after loading since that's what would happen in an eager + # loading situation. + self.__dict__.update(attrs_updated) + return getattr(self, attr) + + def __delattr__(self, attr): + """Trigger the load and then perform the deletion.""" + # To trigger the load and raise an exception if the attribute + # doesn't exist. + self.__getattribute__(attr) + delattr(self, attr) + + +class LazyLoader(abc.Loader): + + """A loader that creates a module which defers loading until attribute access.""" + + @staticmethod + def __check_eager_loader(loader): + if not hasattr(loader, 'exec_module'): + raise TypeError('loader must define exec_module()') + + @classmethod + def factory(cls, loader): + """Construct a callable which returns the eager loader made lazy.""" + cls.__check_eager_loader(loader) + return lambda *args, **kwargs: cls(loader(*args, **kwargs)) + + def __init__(self, loader): + self.__check_eager_loader(loader) + self.loader = loader + + def create_module(self, spec): + return self.loader.create_module(spec) + + def exec_module(self, module): + """Make the module load lazily.""" + module.__spec__.loader = self.loader + module.__loader__ = self.loader + # Don't need to worry about deep-copying as trying to set an attribute + # on an object would have triggered the load, + # e.g. ``module.__spec__.loader = None`` would trigger a load from + # trying to access module.__spec__. + loader_state = {} + loader_state['__dict__'] = module.__dict__.copy() + loader_state['__class__'] = module.__class__ + module.__spec__.loader_state = loader_state + module.__class__ = _LazyModule diff --git a/winvenv/Lib/io.py b/winvenv/Lib/io.py new file mode 100644 index 0000000..968ee50 --- /dev/null +++ b/winvenv/Lib/io.py @@ -0,0 +1,99 @@ +"""The io module provides the Python interfaces to stream handling. The +builtin open function is defined in this module. + +At the top of the I/O hierarchy is the abstract base class IOBase. It +defines the basic interface to a stream. Note, however, that there is no +separation between reading and writing to streams; implementations are +allowed to raise an OSError if they do not support a given operation. + +Extending IOBase is RawIOBase which deals simply with the reading and +writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide +an interface to OS files. + +BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its +subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer +streams that are readable, writable, and both respectively. +BufferedRandom provides a buffered interface to random access +streams. BytesIO is a simple stream of in-memory bytes. + +Another IOBase subclass, TextIOBase, deals with the encoding and decoding +of streams into text. TextIOWrapper, which extends it, is a buffered text +interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO +is an in-memory stream for text. + +Argument names are not part of the specification, and only the arguments +of open() are intended to be used as keyword arguments. + +data: + +DEFAULT_BUFFER_SIZE + + An int containing the default buffer size used by the module's buffered + I/O classes. open() uses the file's blksize (as obtained by os.stat) if + possible. +""" +# New I/O library conforming to PEP 3116. + +__author__ = ("Guido van Rossum , " + "Mike Verdone , " + "Mark Russell , " + "Antoine Pitrou , " + "Amaury Forgeot d'Arc , " + "Benjamin Peterson ") + +__all__ = ["BlockingIOError", "open", "IOBase", "RawIOBase", "FileIO", + "BytesIO", "StringIO", "BufferedIOBase", + "BufferedReader", "BufferedWriter", "BufferedRWPair", + "BufferedRandom", "TextIOBase", "TextIOWrapper", + "UnsupportedOperation", "SEEK_SET", "SEEK_CUR", "SEEK_END"] + + +import _io +import abc + +from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation, + open, FileIO, BytesIO, StringIO, BufferedReader, + BufferedWriter, BufferedRWPair, BufferedRandom, + IncrementalNewlineDecoder, TextIOWrapper) + +OpenWrapper = _io.open # for compatibility with _pyio + +# Pretend this exception was created here. +UnsupportedOperation.__module__ = "io" + +# for seek() +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 + +# Declaring ABCs in C is tricky so we do it here. +# Method descriptions and default implementations are inherited from the C +# version however. +class IOBase(_io._IOBase, metaclass=abc.ABCMeta): + __doc__ = _io._IOBase.__doc__ + +class RawIOBase(_io._RawIOBase, IOBase): + __doc__ = _io._RawIOBase.__doc__ + +class BufferedIOBase(_io._BufferedIOBase, IOBase): + __doc__ = _io._BufferedIOBase.__doc__ + +class TextIOBase(_io._TextIOBase, IOBase): + __doc__ = _io._TextIOBase.__doc__ + +RawIOBase.register(FileIO) + +for klass in (BytesIO, BufferedReader, BufferedWriter, BufferedRandom, + BufferedRWPair): + BufferedIOBase.register(klass) + +for klass in (StringIO, TextIOWrapper): + TextIOBase.register(klass) +del klass + +try: + from _io import _WindowsConsoleIO +except ImportError: + pass +else: + RawIOBase.register(_WindowsConsoleIO) diff --git a/winvenv/Lib/keyword.py b/winvenv/Lib/keyword.py new file mode 100644 index 0000000..431991d --- /dev/null +++ b/winvenv/Lib/keyword.py @@ -0,0 +1,96 @@ +#! /usr/bin/env python3 + +"""Keywords (from "graminit.c") + +This file is automatically generated; please don't muck it up! + +To update the symbols in this file, 'cd' to the top directory of +the python source tree after building the interpreter and run: + + ./python Lib/keyword.py +""" + +__all__ = ["iskeyword", "kwlist"] + +kwlist = [ +#--start keywords-- + 'False', + 'None', + 'True', + 'and', + 'as', + 'assert', + 'async', + 'await', + 'break', + 'class', + 'continue', + 'def', + 'del', + 'elif', + 'else', + 'except', + 'finally', + 'for', + 'from', + 'global', + 'if', + 'import', + 'in', + 'is', + 'lambda', + 'nonlocal', + 'not', + 'or', + 'pass', + 'raise', + 'return', + 'try', + 'while', + 'with', + 'yield', +#--end keywords-- + ] + +iskeyword = frozenset(kwlist).__contains__ + +def main(): + import sys, re + + args = sys.argv[1:] + iptfile = args and args[0] or "Python/graminit.c" + if len(args) > 1: optfile = args[1] + else: optfile = "Lib/keyword.py" + + # load the output skeleton from the target, taking care to preserve its + # newline convention. + with open(optfile, newline='') as fp: + format = fp.readlines() + nl = format[0][len(format[0].strip()):] if format else '\n' + + # scan the source file for keywords + with open(iptfile) as fp: + strprog = re.compile('"([^"]+)"') + lines = [] + for line in fp: + if '{1, "' in line: + match = strprog.search(line) + if match: + lines.append(" '" + match.group(1) + "'," + nl) + lines.sort() + + # insert the lines of keywords into the skeleton + try: + start = format.index("#--start keywords--" + nl) + 1 + end = format.index("#--end keywords--" + nl) + format[start:end] = lines + except ValueError: + sys.stderr.write("target does not contain format markers\n") + sys.exit(1) + + # write the output file + with open(optfile, 'w', newline='') as fp: + fp.writelines(format) + +if __name__ == "__main__": + main() diff --git a/winvenv/Lib/linecache.py b/winvenv/Lib/linecache.py new file mode 100644 index 0000000..3afcce1 --- /dev/null +++ b/winvenv/Lib/linecache.py @@ -0,0 +1,177 @@ +"""Cache lines from Python source files. + +This is intended to read lines from modules imported -- hence if a filename +is not found, it will look down the module search path for a file by +that name. +""" + +import functools +import sys +import os +import tokenize + +__all__ = ["getline", "clearcache", "checkcache"] + +def getline(filename, lineno, module_globals=None): + lines = getlines(filename, module_globals) + if 1 <= lineno <= len(lines): + return lines[lineno-1] + else: + return '' + + +# The cache + +# The cache. Maps filenames to either a thunk which will provide source code, +# or a tuple (size, mtime, lines, fullname) once loaded. +cache = {} + + +def clearcache(): + """Clear the cache entirely.""" + + global cache + cache = {} + + +def getlines(filename, module_globals=None): + """Get the lines for a Python source file from the cache. + Update the cache if it doesn't contain an entry for this file already.""" + + if filename in cache: + entry = cache[filename] + if len(entry) != 1: + return cache[filename][2] + + try: + return updatecache(filename, module_globals) + except MemoryError: + clearcache() + return [] + + +def checkcache(filename=None): + """Discard cache entries that are out of date. + (This is not checked upon each call!)""" + + if filename is None: + filenames = list(cache.keys()) + else: + if filename in cache: + filenames = [filename] + else: + return + + for filename in filenames: + entry = cache[filename] + if len(entry) == 1: + # lazy cache entry, leave it lazy. + continue + size, mtime, lines, fullname = entry + if mtime is None: + continue # no-op for files loaded via a __loader__ + try: + stat = os.stat(fullname) + except OSError: + del cache[filename] + continue + if size != stat.st_size or mtime != stat.st_mtime: + del cache[filename] + + +def updatecache(filename, module_globals=None): + """Update a cache entry and return its list of lines. + If something's wrong, print a message, discard the cache entry, + and return an empty list.""" + + if filename in cache: + if len(cache[filename]) != 1: + del cache[filename] + if not filename or (filename.startswith('<') and filename.endswith('>')): + return [] + + fullname = filename + try: + stat = os.stat(fullname) + except OSError: + basename = filename + + # Realise a lazy loader based lookup if there is one + # otherwise try to lookup right now. + if lazycache(filename, module_globals): + try: + data = cache[filename][0]() + except (ImportError, OSError): + pass + else: + if data is None: + # No luck, the PEP302 loader cannot find the source + # for this module. + return [] + cache[filename] = ( + len(data), None, + [line+'\n' for line in data.splitlines()], fullname + ) + return cache[filename][2] + + # Try looking through the module search path, which is only useful + # when handling a relative filename. + if os.path.isabs(filename): + return [] + + for dirname in sys.path: + try: + fullname = os.path.join(dirname, basename) + except (TypeError, AttributeError): + # Not sufficiently string-like to do anything useful with. + continue + try: + stat = os.stat(fullname) + break + except OSError: + pass + else: + return [] + try: + with tokenize.open(fullname) as fp: + lines = fp.readlines() + except OSError: + return [] + if lines and not lines[-1].endswith('\n'): + lines[-1] += '\n' + size, mtime = stat.st_size, stat.st_mtime + cache[filename] = size, mtime, lines, fullname + return lines + + +def lazycache(filename, module_globals): + """Seed the cache for filename with module_globals. + + The module loader will be asked for the source only when getlines is + called, not immediately. + + If there is an entry in the cache already, it is not altered. + + :return: True if a lazy load is registered in the cache, + otherwise False. To register such a load a module loader with a + get_source method must be found, the filename must be a cachable + filename, and the filename must not be already cached. + """ + if filename in cache: + if len(cache[filename]) == 1: + return True + else: + return False + if not filename or (filename.startswith('<') and filename.endswith('>')): + return False + # Try for a __loader__, if available + if module_globals and '__loader__' in module_globals: + name = module_globals.get('__name__') + loader = module_globals['__loader__'] + get_source = getattr(loader, 'get_source', None) + + if name and get_source: + get_lines = functools.partial(get_source, name) + cache[filename] = (get_lines,) + return True + return False diff --git a/winvenv/Lib/locale.py b/winvenv/Lib/locale.py new file mode 100644 index 0000000..f3d3973 --- /dev/null +++ b/winvenv/Lib/locale.py @@ -0,0 +1,1749 @@ +"""Locale support module. + +The module provides low-level access to the C lib's locale APIs and adds high +level number formatting APIs as well as a locale aliasing engine to complement +these. + +The aliasing engine includes support for many commonly used locale names and +maps them to values suitable for passing to the C lib's setlocale() function. It +also includes default encodings for all supported locale names. + +""" + +import sys +import encodings +import encodings.aliases +import re +import _collections_abc +from builtins import str as _builtin_str +import functools + +# Try importing the _locale module. +# +# If this fails, fall back on a basic 'C' locale emulation. + +# Yuck: LC_MESSAGES is non-standard: can't tell whether it exists before +# trying the import. So __all__ is also fiddled at the end of the file. +__all__ = ["getlocale", "getdefaultlocale", "getpreferredencoding", "Error", + "setlocale", "resetlocale", "localeconv", "strcoll", "strxfrm", + "str", "atof", "atoi", "format", "format_string", "currency", + "normalize", "LC_CTYPE", "LC_COLLATE", "LC_TIME", "LC_MONETARY", + "LC_NUMERIC", "LC_ALL", "CHAR_MAX"] + +def _strcoll(a,b): + """ strcoll(string,string) -> int. + Compares two strings according to the locale. + """ + return (a > b) - (a < b) + +def _strxfrm(s): + """ strxfrm(string) -> string. + Returns a string that behaves for cmp locale-aware. + """ + return s + +try: + + from _locale import * + +except ImportError: + + # Locale emulation + + CHAR_MAX = 127 + LC_ALL = 6 + LC_COLLATE = 3 + LC_CTYPE = 0 + LC_MESSAGES = 5 + LC_MONETARY = 4 + LC_NUMERIC = 1 + LC_TIME = 2 + Error = ValueError + + def localeconv(): + """ localeconv() -> dict. + Returns numeric and monetary locale-specific parameters. + """ + # 'C' locale default values + return {'grouping': [127], + 'currency_symbol': '', + 'n_sign_posn': 127, + 'p_cs_precedes': 127, + 'n_cs_precedes': 127, + 'mon_grouping': [], + 'n_sep_by_space': 127, + 'decimal_point': '.', + 'negative_sign': '', + 'positive_sign': '', + 'p_sep_by_space': 127, + 'int_curr_symbol': '', + 'p_sign_posn': 127, + 'thousands_sep': '', + 'mon_thousands_sep': '', + 'frac_digits': 127, + 'mon_decimal_point': '', + 'int_frac_digits': 127} + + def setlocale(category, value=None): + """ setlocale(integer,string=None) -> string. + Activates/queries locale processing. + """ + if value not in (None, '', 'C'): + raise Error('_locale emulation only supports "C" locale') + return 'C' + +# These may or may not exist in _locale, so be sure to set them. +if 'strxfrm' not in globals(): + strxfrm = _strxfrm +if 'strcoll' not in globals(): + strcoll = _strcoll + + +_localeconv = localeconv + +# With this dict, you can override some items of localeconv's return value. +# This is useful for testing purposes. +_override_localeconv = {} + +@functools.wraps(_localeconv) +def localeconv(): + d = _localeconv() + if _override_localeconv: + d.update(_override_localeconv) + return d + + +### Number formatting APIs + +# Author: Martin von Loewis +# improved by Georg Brandl + +# Iterate over grouping intervals +def _grouping_intervals(grouping): + last_interval = None + for interval in grouping: + # if grouping is -1, we are done + if interval == CHAR_MAX: + return + # 0: re-use last group ad infinitum + if interval == 0: + if last_interval is None: + raise ValueError("invalid grouping") + while True: + yield last_interval + yield interval + last_interval = interval + +#perform the grouping from right to left +def _group(s, monetary=False): + conv = localeconv() + thousands_sep = conv[monetary and 'mon_thousands_sep' or 'thousands_sep'] + grouping = conv[monetary and 'mon_grouping' or 'grouping'] + if not grouping: + return (s, 0) + if s[-1] == ' ': + stripped = s.rstrip() + right_spaces = s[len(stripped):] + s = stripped + else: + right_spaces = '' + left_spaces = '' + groups = [] + for interval in _grouping_intervals(grouping): + if not s or s[-1] not in "0123456789": + # only non-digit characters remain (sign, spaces) + left_spaces = s + s = '' + break + groups.append(s[-interval:]) + s = s[:-interval] + if s: + groups.append(s) + groups.reverse() + return ( + left_spaces + thousands_sep.join(groups) + right_spaces, + len(thousands_sep) * (len(groups) - 1) + ) + +# Strip a given amount of excess padding from the given string +def _strip_padding(s, amount): + lpos = 0 + while amount and s[lpos] == ' ': + lpos += 1 + amount -= 1 + rpos = len(s) - 1 + while amount and s[rpos] == ' ': + rpos -= 1 + amount -= 1 + return s[lpos:rpos+1] + +_percent_re = re.compile(r'%(?:\((?P.*?)\))?' + r'(?P[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]') + +def _format(percent, value, grouping=False, monetary=False, *additional): + if additional: + formatted = percent % ((value,) + additional) + else: + formatted = percent % value + # floats and decimal ints need special action! + if percent[-1] in 'eEfFgG': + seps = 0 + parts = formatted.split('.') + if grouping: + parts[0], seps = _group(parts[0], monetary=monetary) + decimal_point = localeconv()[monetary and 'mon_decimal_point' + or 'decimal_point'] + formatted = decimal_point.join(parts) + if seps: + formatted = _strip_padding(formatted, seps) + elif percent[-1] in 'diu': + seps = 0 + if grouping: + formatted, seps = _group(formatted, monetary=monetary) + if seps: + formatted = _strip_padding(formatted, seps) + return formatted + +def format_string(f, val, grouping=False, monetary=False): + """Formats a string in the same way that the % formatting would use, + but takes the current locale into account. + + Grouping is applied if the third parameter is true. + Conversion uses monetary thousands separator and grouping strings if + forth parameter monetary is true.""" + percents = list(_percent_re.finditer(f)) + new_f = _percent_re.sub('%s', f) + + if isinstance(val, _collections_abc.Mapping): + new_val = [] + for perc in percents: + if perc.group()[-1]=='%': + new_val.append('%') + else: + new_val.append(_format(perc.group(), val, grouping, monetary)) + else: + if not isinstance(val, tuple): + val = (val,) + new_val = [] + i = 0 + for perc in percents: + if perc.group()[-1]=='%': + new_val.append('%') + else: + starcount = perc.group('modifiers').count('*') + new_val.append(_format(perc.group(), + val[i], + grouping, + monetary, + *val[i+1:i+1+starcount])) + i += (1 + starcount) + val = tuple(new_val) + + return new_f % val + +def format(percent, value, grouping=False, monetary=False, *additional): + """Deprecated, use format_string instead.""" + import warnings + warnings.warn( + "This method will be removed in a future version of Python. " + "Use 'locale.format_string()' instead.", + DeprecationWarning, stacklevel=2 + ) + + match = _percent_re.match(percent) + if not match or len(match.group())!= len(percent): + raise ValueError(("format() must be given exactly one %%char " + "format specifier, %s not valid") % repr(percent)) + return _format(percent, value, grouping, monetary, *additional) + +def currency(val, symbol=True, grouping=False, international=False): + """Formats val according to the currency settings + in the current locale.""" + conv = localeconv() + + # check for illegal values + digits = conv[international and 'int_frac_digits' or 'frac_digits'] + if digits == 127: + raise ValueError("Currency formatting is not possible using " + "the 'C' locale.") + + s = _format('%%.%if' % digits, abs(val), grouping, monetary=True) + # '<' and '>' are markers if the sign must be inserted between symbol and value + s = '<' + s + '>' + + if symbol: + smb = conv[international and 'int_curr_symbol' or 'currency_symbol'] + precedes = conv[val<0 and 'n_cs_precedes' or 'p_cs_precedes'] + separated = conv[val<0 and 'n_sep_by_space' or 'p_sep_by_space'] + + if precedes: + s = smb + (separated and ' ' or '') + s + else: + s = s + (separated and ' ' or '') + smb + + sign_pos = conv[val<0 and 'n_sign_posn' or 'p_sign_posn'] + sign = conv[val<0 and 'negative_sign' or 'positive_sign'] + + if sign_pos == 0: + s = '(' + s + ')' + elif sign_pos == 1: + s = sign + s + elif sign_pos == 2: + s = s + sign + elif sign_pos == 3: + s = s.replace('<', sign) + elif sign_pos == 4: + s = s.replace('>', sign) + else: + # the default if nothing specified; + # this should be the most fitting sign position + s = sign + s + + return s.replace('<', '').replace('>', '') + +def str(val): + """Convert float to string, taking the locale into account.""" + return _format("%.12g", val) + +def delocalize(string): + "Parses a string as a normalized number according to the locale settings." + + conv = localeconv() + + #First, get rid of the grouping + ts = conv['thousands_sep'] + if ts: + string = string.replace(ts, '') + + #next, replace the decimal point with a dot + dd = conv['decimal_point'] + if dd: + string = string.replace(dd, '.') + return string + +def atof(string, func=float): + "Parses a string as a float according to the locale settings." + return func(delocalize(string)) + +def atoi(string): + "Converts a string to an integer according to the locale settings." + return int(delocalize(string)) + +def _test(): + setlocale(LC_ALL, "") + #do grouping + s1 = format_string("%d", 123456789,1) + print(s1, "is", atoi(s1)) + #standard formatting + s1 = str(3.14) + print(s1, "is", atof(s1)) + +### Locale name aliasing engine + +# Author: Marc-Andre Lemburg, mal@lemburg.com +# Various tweaks by Fredrik Lundh + +# store away the low-level version of setlocale (it's +# overridden below) +_setlocale = setlocale + +def _replace_encoding(code, encoding): + if '.' in code: + langname = code[:code.index('.')] + else: + langname = code + # Convert the encoding to a C lib compatible encoding string + norm_encoding = encodings.normalize_encoding(encoding) + #print('norm encoding: %r' % norm_encoding) + norm_encoding = encodings.aliases.aliases.get(norm_encoding.lower(), + norm_encoding) + #print('aliased encoding: %r' % norm_encoding) + encoding = norm_encoding + norm_encoding = norm_encoding.lower() + if norm_encoding in locale_encoding_alias: + encoding = locale_encoding_alias[norm_encoding] + else: + norm_encoding = norm_encoding.replace('_', '') + norm_encoding = norm_encoding.replace('-', '') + if norm_encoding in locale_encoding_alias: + encoding = locale_encoding_alias[norm_encoding] + #print('found encoding %r' % encoding) + return langname + '.' + encoding + +def _append_modifier(code, modifier): + if modifier == 'euro': + if '.' not in code: + return code + '.ISO8859-15' + _, _, encoding = code.partition('.') + if encoding in ('ISO8859-15', 'UTF-8'): + return code + if encoding == 'ISO8859-1': + return _replace_encoding(code, 'ISO8859-15') + return code + '@' + modifier + +def normalize(localename): + + """ Returns a normalized locale code for the given locale + name. + + The returned locale code is formatted for use with + setlocale(). + + If normalization fails, the original name is returned + unchanged. + + If the given encoding is not known, the function defaults to + the default encoding for the locale code just like setlocale() + does. + + """ + # Normalize the locale name and extract the encoding and modifier + code = localename.lower() + if ':' in code: + # ':' is sometimes used as encoding delimiter. + code = code.replace(':', '.') + if '@' in code: + code, modifier = code.split('@', 1) + else: + modifier = '' + if '.' in code: + langname, encoding = code.split('.')[:2] + else: + langname = code + encoding = '' + + # First lookup: fullname (possibly with encoding and modifier) + lang_enc = langname + if encoding: + norm_encoding = encoding.replace('-', '') + norm_encoding = norm_encoding.replace('_', '') + lang_enc += '.' + norm_encoding + lookup_name = lang_enc + if modifier: + lookup_name += '@' + modifier + code = locale_alias.get(lookup_name, None) + if code is not None: + return code + #print('first lookup failed') + + if modifier: + # Second try: fullname without modifier (possibly with encoding) + code = locale_alias.get(lang_enc, None) + if code is not None: + #print('lookup without modifier succeeded') + if '@' not in code: + return _append_modifier(code, modifier) + if code.split('@', 1)[1].lower() == modifier: + return code + #print('second lookup failed') + + if encoding: + # Third try: langname (without encoding, possibly with modifier) + lookup_name = langname + if modifier: + lookup_name += '@' + modifier + code = locale_alias.get(lookup_name, None) + if code is not None: + #print('lookup without encoding succeeded') + if '@' not in code: + return _replace_encoding(code, encoding) + code, modifier = code.split('@', 1) + return _replace_encoding(code, encoding) + '@' + modifier + + if modifier: + # Fourth try: langname (without encoding and modifier) + code = locale_alias.get(langname, None) + if code is not None: + #print('lookup without modifier and encoding succeeded') + if '@' not in code: + code = _replace_encoding(code, encoding) + return _append_modifier(code, modifier) + code, defmod = code.split('@', 1) + if defmod.lower() == modifier: + return _replace_encoding(code, encoding) + '@' + defmod + + return localename + +def _parse_localename(localename): + + """ Parses the locale code for localename and returns the + result as tuple (language code, encoding). + + The localename is normalized and passed through the locale + alias engine. A ValueError is raised in case the locale name + cannot be parsed. + + The language code corresponds to RFC 1766. code and encoding + can be None in case the values cannot be determined or are + unknown to this implementation. + + """ + code = normalize(localename) + if '@' in code: + # Deal with locale modifiers + code, modifier = code.split('@', 1) + if modifier == 'euro' and '.' not in code: + # Assume Latin-9 for @euro locales. This is bogus, + # since some systems may use other encodings for these + # locales. Also, we ignore other modifiers. + return code, 'iso-8859-15' + + if '.' in code: + return tuple(code.split('.')[:2]) + elif code == 'C': + return None, None + raise ValueError('unknown locale: %s' % localename) + +def _build_localename(localetuple): + + """ Builds a locale code from the given tuple (language code, + encoding). + + No aliasing or normalizing takes place. + + """ + try: + language, encoding = localetuple + + if language is None: + language = 'C' + if encoding is None: + return language + else: + return language + '.' + encoding + except (TypeError, ValueError): + raise TypeError('Locale must be None, a string, or an iterable of ' + 'two strings -- language code, encoding.') from None + +def getdefaultlocale(envvars=('LC_ALL', 'LC_CTYPE', 'LANG', 'LANGUAGE')): + + """ Tries to determine the default locale settings and returns + them as tuple (language code, encoding). + + According to POSIX, a program which has not called + setlocale(LC_ALL, "") runs using the portable 'C' locale. + Calling setlocale(LC_ALL, "") lets it use the default locale as + defined by the LANG variable. Since we don't want to interfere + with the current locale setting we thus emulate the behavior + in the way described above. + + To maintain compatibility with other platforms, not only the + LANG variable is tested, but a list of variables given as + envvars parameter. The first found to be defined will be + used. envvars defaults to the search path used in GNU gettext; + it must always contain the variable name 'LANG'. + + Except for the code 'C', the language code corresponds to RFC + 1766. code and encoding can be None in case the values cannot + be determined. + + """ + + try: + # check if it's supported by the _locale module + import _locale + code, encoding = _locale._getdefaultlocale() + except (ImportError, AttributeError): + pass + else: + # make sure the code/encoding values are valid + if sys.platform == "win32" and code and code[:2] == "0x": + # map windows language identifier to language name + code = windows_locale.get(int(code, 0)) + # ...add other platform-specific processing here, if + # necessary... + return code, encoding + + # fall back on POSIX behaviour + import os + lookup = os.environ.get + for variable in envvars: + localename = lookup(variable,None) + if localename: + if variable == 'LANGUAGE': + localename = localename.split(':')[0] + break + else: + localename = 'C' + return _parse_localename(localename) + + +def getlocale(category=LC_CTYPE): + + """ Returns the current setting for the given locale category as + tuple (language code, encoding). + + category may be one of the LC_* value except LC_ALL. It + defaults to LC_CTYPE. + + Except for the code 'C', the language code corresponds to RFC + 1766. code and encoding can be None in case the values cannot + be determined. + + """ + localename = _setlocale(category) + if category == LC_ALL and ';' in localename: + raise TypeError('category LC_ALL is not supported') + return _parse_localename(localename) + +def setlocale(category, locale=None): + + """ Set the locale for the given category. The locale can be + a string, an iterable of two strings (language code and encoding), + or None. + + Iterables are converted to strings using the locale aliasing + engine. Locale strings are passed directly to the C lib. + + category may be given as one of the LC_* values. + + """ + if locale and not isinstance(locale, _builtin_str): + # convert to string + locale = normalize(_build_localename(locale)) + return _setlocale(category, locale) + +def resetlocale(category=LC_ALL): + + """ Sets the locale for category to the default setting. + + The default setting is determined by calling + getdefaultlocale(). category defaults to LC_ALL. + + """ + _setlocale(category, _build_localename(getdefaultlocale())) + +if sys.platform.startswith("win"): + # On Win32, this will return the ANSI code page + def getpreferredencoding(do_setlocale = True): + """Return the charset that the user is likely using.""" + if sys.flags.utf8_mode: + return 'UTF-8' + import _bootlocale + return _bootlocale.getpreferredencoding(False) +else: + # On Unix, if CODESET is available, use that. + try: + CODESET + except NameError: + if hasattr(sys, 'getandroidapilevel'): + # On Android langinfo.h and CODESET are missing, and UTF-8 is + # always used in mbstowcs() and wcstombs(). + def getpreferredencoding(do_setlocale = True): + return 'UTF-8' + else: + # Fall back to parsing environment variables :-( + def getpreferredencoding(do_setlocale = True): + """Return the charset that the user is likely using, + by looking at environment variables.""" + if sys.flags.utf8_mode: + return 'UTF-8' + res = getdefaultlocale()[1] + if res is None: + # LANG not set, default conservatively to ASCII + res = 'ascii' + return res + else: + def getpreferredencoding(do_setlocale = True): + """Return the charset that the user is likely using, + according to the system configuration.""" + if sys.flags.utf8_mode: + return 'UTF-8' + import _bootlocale + if do_setlocale: + oldloc = setlocale(LC_CTYPE) + try: + setlocale(LC_CTYPE, "") + except Error: + pass + result = _bootlocale.getpreferredencoding(False) + if do_setlocale: + setlocale(LC_CTYPE, oldloc) + return result + + +### Database +# +# The following data was extracted from the locale.alias file which +# comes with X11 and then hand edited removing the explicit encoding +# definitions and adding some more aliases. The file is usually +# available as /usr/lib/X11/locale/locale.alias. +# + +# +# The local_encoding_alias table maps lowercase encoding alias names +# to C locale encoding names (case-sensitive). Note that normalize() +# first looks up the encoding in the encodings.aliases dictionary and +# then applies this mapping to find the correct C lib name for the +# encoding. +# +locale_encoding_alias = { + + # Mappings for non-standard encoding names used in locale names + '437': 'C', + 'c': 'C', + 'en': 'ISO8859-1', + 'jis': 'JIS7', + 'jis7': 'JIS7', + 'ajec': 'eucJP', + 'koi8c': 'KOI8-C', + 'microsoftcp1251': 'CP1251', + 'microsoftcp1255': 'CP1255', + 'microsoftcp1256': 'CP1256', + '88591': 'ISO8859-1', + '88592': 'ISO8859-2', + '88595': 'ISO8859-5', + '885915': 'ISO8859-15', + + # Mappings from Python codec names to C lib encoding names + 'ascii': 'ISO8859-1', + 'latin_1': 'ISO8859-1', + 'iso8859_1': 'ISO8859-1', + 'iso8859_10': 'ISO8859-10', + 'iso8859_11': 'ISO8859-11', + 'iso8859_13': 'ISO8859-13', + 'iso8859_14': 'ISO8859-14', + 'iso8859_15': 'ISO8859-15', + 'iso8859_16': 'ISO8859-16', + 'iso8859_2': 'ISO8859-2', + 'iso8859_3': 'ISO8859-3', + 'iso8859_4': 'ISO8859-4', + 'iso8859_5': 'ISO8859-5', + 'iso8859_6': 'ISO8859-6', + 'iso8859_7': 'ISO8859-7', + 'iso8859_8': 'ISO8859-8', + 'iso8859_9': 'ISO8859-9', + 'iso2022_jp': 'JIS7', + 'shift_jis': 'SJIS', + 'tactis': 'TACTIS', + 'euc_jp': 'eucJP', + 'euc_kr': 'eucKR', + 'utf_8': 'UTF-8', + 'koi8_r': 'KOI8-R', + 'koi8_t': 'KOI8-T', + 'koi8_u': 'KOI8-U', + 'kz1048': 'RK1048', + 'cp1251': 'CP1251', + 'cp1255': 'CP1255', + 'cp1256': 'CP1256', + + # XXX This list is still incomplete. If you know more + # mappings, please file a bug report. Thanks. +} + +for k, v in sorted(locale_encoding_alias.items()): + k = k.replace('_', '') + locale_encoding_alias.setdefault(k, v) + +# +# The locale_alias table maps lowercase alias names to C locale names +# (case-sensitive). Encodings are always separated from the locale +# name using a dot ('.'); they should only be given in case the +# language name is needed to interpret the given encoding alias +# correctly (CJK codes often have this need). +# +# Note that the normalize() function which uses this tables +# removes '_' and '-' characters from the encoding part of the +# locale name before doing the lookup. This saves a lot of +# space in the table. +# +# MAL 2004-12-10: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.4 +# and older): +# +# updated 'bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' +# updated 'bg_bg' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' +# updated 'bulgarian' -> 'bg_BG.ISO8859-5' to 'bg_BG.CP1251' +# updated 'cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'cz_cz' -> 'cz_CZ.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'czech' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'dutch' -> 'nl_BE.ISO8859-1' to 'nl_NL.ISO8859-1' +# updated 'et' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15' +# updated 'et_ee' -> 'et_EE.ISO8859-4' to 'et_EE.ISO8859-15' +# updated 'fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15' +# updated 'fi_fi' -> 'fi_FI.ISO8859-1' to 'fi_FI.ISO8859-15' +# updated 'iw' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'iw_il' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'japanese' -> 'ja_JP.SJIS' to 'ja_JP.eucJP' +# updated 'lt' -> 'lt_LT.ISO8859-4' to 'lt_LT.ISO8859-13' +# updated 'lv' -> 'lv_LV.ISO8859-4' to 'lv_LV.ISO8859-13' +# updated 'sl' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2' +# updated 'slovene' -> 'sl_CS.ISO8859-2' to 'sl_SI.ISO8859-2' +# updated 'th_th' -> 'th_TH.TACTIS' to 'th_TH.ISO8859-11' +# updated 'zh_cn' -> 'zh_CN.eucCN' to 'zh_CN.gb2312' +# updated 'zh_cn.big5' -> 'zh_TW.eucTW' to 'zh_TW.big5' +# updated 'zh_tw' -> 'zh_TW.eucTW' to 'zh_TW.big5' +# +# MAL 2008-05-30: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.5 +# and older): +# +# updated 'cs_cs.iso88592' -> 'cs_CZ.ISO8859-2' to 'cs_CS.ISO8859-2' +# updated 'serbocroatian' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sh' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sh_hr.iso88592' -> 'sh_HR.ISO8859-2' to 'hr_HR.ISO8859-2' +# updated 'sh_sp' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sh_yu' -> 'sh_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sp' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sp_yu' -> 'sp_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_sp' -> 'sr_SP.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sr_yu' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_yu.cp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251' +# updated 'sr_yu.iso88592' -> 'sr_YU.ISO8859-2' to 'sr_CS.ISO8859-2' +# updated 'sr_yu.iso88595' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_yu.iso88595@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# updated 'sr_yu.microsoftcp1251@cyrillic' -> 'sr_YU.CP1251' to 'sr_CS.CP1251' +# updated 'sr_yu.utf8@cyrillic' -> 'sr_YU.UTF-8' to 'sr_CS.UTF-8' +# updated 'sr_yu@cyrillic' -> 'sr_YU.ISO8859-5' to 'sr_CS.ISO8859-5' +# +# AP 2010-04-12: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 2.6.5 +# and older): +# +# updated 'ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8' +# updated 'ru_ru' -> 'ru_RU.ISO8859-5' to 'ru_RU.UTF-8' +# updated 'serbocroatian' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sh' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sh_yu' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sr' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' +# updated 'sr@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' +# updated 'sr@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sr_cs.utf8@latn' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8@latin' +# updated 'sr_cs@latn' -> 'sr_CS.ISO8859-2' to 'sr_RS.UTF-8@latin' +# updated 'sr_yu' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8@latin' +# updated 'sr_yu.utf8@cyrillic' -> 'sr_CS.UTF-8' to 'sr_RS.UTF-8' +# updated 'sr_yu@cyrillic' -> 'sr_CS.ISO8859-5' to 'sr_RS.UTF-8' +# +# SS 2013-12-20: +# Updated alias mapping to most recent locale.alias file +# from X.org distribution using makelocalealias.py. +# +# These are the differences compared to the old mapping (Python 3.3.3 +# and older): +# +# updated 'a3' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' +# updated 'a3_az' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' +# updated 'a3_az.koi8c' -> 'a3_AZ.KOI8-C' to 'az_AZ.KOI8-C' +# updated 'cs_cs.iso88592' -> 'cs_CS.ISO8859-2' to 'cs_CZ.ISO8859-2' +# updated 'hebrew' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'hebrew.iso88598' -> 'iw_IL.ISO8859-8' to 'he_IL.ISO8859-8' +# updated 'sd' -> 'sd_IN@devanagari.UTF-8' to 'sd_IN.UTF-8' +# updated 'sr@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' +# updated 'sr_cs' -> 'sr_RS.UTF-8' to 'sr_CS.UTF-8' +# updated 'sr_cs.utf8@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' +# updated 'sr_cs@latn' -> 'sr_RS.UTF-8@latin' to 'sr_CS.UTF-8@latin' +# +# SS 2014-10-01: +# Updated alias mapping with glibc 2.19 supported locales. +# +# SS 2018-05-05: +# Updated alias mapping with glibc 2.27 supported locales. +# +# These are the differences compared to the old mapping (Python 3.6.5 +# and older): +# +# updated 'ca_es@valencia' -> 'ca_ES.ISO8859-15@valencia' to 'ca_ES.UTF-8@valencia' +# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154' +# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R' + +locale_alias = { + 'a3': 'az_AZ.KOI8-C', + 'a3_az': 'az_AZ.KOI8-C', + 'a3_az.koic': 'az_AZ.KOI8-C', + 'aa_dj': 'aa_DJ.ISO8859-1', + 'aa_er': 'aa_ER.UTF-8', + 'aa_et': 'aa_ET.UTF-8', + 'af': 'af_ZA.ISO8859-1', + 'af_za': 'af_ZA.ISO8859-1', + 'agr_pe': 'agr_PE.UTF-8', + 'ak_gh': 'ak_GH.UTF-8', + 'am': 'am_ET.UTF-8', + 'am_et': 'am_ET.UTF-8', + 'american': 'en_US.ISO8859-1', + 'an_es': 'an_ES.ISO8859-15', + 'anp_in': 'anp_IN.UTF-8', + 'ar': 'ar_AA.ISO8859-6', + 'ar_aa': 'ar_AA.ISO8859-6', + 'ar_ae': 'ar_AE.ISO8859-6', + 'ar_bh': 'ar_BH.ISO8859-6', + 'ar_dz': 'ar_DZ.ISO8859-6', + 'ar_eg': 'ar_EG.ISO8859-6', + 'ar_in': 'ar_IN.UTF-8', + 'ar_iq': 'ar_IQ.ISO8859-6', + 'ar_jo': 'ar_JO.ISO8859-6', + 'ar_kw': 'ar_KW.ISO8859-6', + 'ar_lb': 'ar_LB.ISO8859-6', + 'ar_ly': 'ar_LY.ISO8859-6', + 'ar_ma': 'ar_MA.ISO8859-6', + 'ar_om': 'ar_OM.ISO8859-6', + 'ar_qa': 'ar_QA.ISO8859-6', + 'ar_sa': 'ar_SA.ISO8859-6', + 'ar_sd': 'ar_SD.ISO8859-6', + 'ar_ss': 'ar_SS.UTF-8', + 'ar_sy': 'ar_SY.ISO8859-6', + 'ar_tn': 'ar_TN.ISO8859-6', + 'ar_ye': 'ar_YE.ISO8859-6', + 'arabic': 'ar_AA.ISO8859-6', + 'as': 'as_IN.UTF-8', + 'as_in': 'as_IN.UTF-8', + 'ast_es': 'ast_ES.ISO8859-15', + 'ayc_pe': 'ayc_PE.UTF-8', + 'az': 'az_AZ.ISO8859-9E', + 'az_az': 'az_AZ.ISO8859-9E', + 'az_az.iso88599e': 'az_AZ.ISO8859-9E', + 'az_ir': 'az_IR.UTF-8', + 'be': 'be_BY.CP1251', + 'be@latin': 'be_BY.UTF-8@latin', + 'be_bg.utf8': 'bg_BG.UTF-8', + 'be_by': 'be_BY.CP1251', + 'be_by@latin': 'be_BY.UTF-8@latin', + 'bem_zm': 'bem_ZM.UTF-8', + 'ber_dz': 'ber_DZ.UTF-8', + 'ber_ma': 'ber_MA.UTF-8', + 'bg': 'bg_BG.CP1251', + 'bg_bg': 'bg_BG.CP1251', + 'bhb_in.utf8': 'bhb_IN.UTF-8', + 'bho_in': 'bho_IN.UTF-8', + 'bho_np': 'bho_NP.UTF-8', + 'bi_vu': 'bi_VU.UTF-8', + 'bn_bd': 'bn_BD.UTF-8', + 'bn_in': 'bn_IN.UTF-8', + 'bo_cn': 'bo_CN.UTF-8', + 'bo_in': 'bo_IN.UTF-8', + 'bokmal': 'nb_NO.ISO8859-1', + 'bokm\xe5l': 'nb_NO.ISO8859-1', + 'br': 'br_FR.ISO8859-1', + 'br_fr': 'br_FR.ISO8859-1', + 'brx_in': 'brx_IN.UTF-8', + 'bs': 'bs_BA.ISO8859-2', + 'bs_ba': 'bs_BA.ISO8859-2', + 'bulgarian': 'bg_BG.CP1251', + 'byn_er': 'byn_ER.UTF-8', + 'c': 'C', + 'c-french': 'fr_CA.ISO8859-1', + 'c.ascii': 'C', + 'c.en': 'C', + 'c.iso88591': 'en_US.ISO8859-1', + 'c.utf8': 'en_US.UTF-8', + 'c_c': 'C', + 'c_c.c': 'C', + 'ca': 'ca_ES.ISO8859-1', + 'ca_ad': 'ca_AD.ISO8859-1', + 'ca_es': 'ca_ES.ISO8859-1', + 'ca_es@valencia': 'ca_ES.UTF-8@valencia', + 'ca_fr': 'ca_FR.ISO8859-1', + 'ca_it': 'ca_IT.ISO8859-1', + 'catalan': 'ca_ES.ISO8859-1', + 'ce_ru': 'ce_RU.UTF-8', + 'cextend': 'en_US.ISO8859-1', + 'chinese-s': 'zh_CN.eucCN', + 'chinese-t': 'zh_TW.eucTW', + 'chr_us': 'chr_US.UTF-8', + 'ckb_iq': 'ckb_IQ.UTF-8', + 'cmn_tw': 'cmn_TW.UTF-8', + 'crh_ua': 'crh_UA.UTF-8', + 'croatian': 'hr_HR.ISO8859-2', + 'cs': 'cs_CZ.ISO8859-2', + 'cs_cs': 'cs_CZ.ISO8859-2', + 'cs_cz': 'cs_CZ.ISO8859-2', + 'csb_pl': 'csb_PL.UTF-8', + 'cv_ru': 'cv_RU.UTF-8', + 'cy': 'cy_GB.ISO8859-1', + 'cy_gb': 'cy_GB.ISO8859-1', + 'cz': 'cs_CZ.ISO8859-2', + 'cz_cz': 'cs_CZ.ISO8859-2', + 'czech': 'cs_CZ.ISO8859-2', + 'da': 'da_DK.ISO8859-1', + 'da_dk': 'da_DK.ISO8859-1', + 'danish': 'da_DK.ISO8859-1', + 'dansk': 'da_DK.ISO8859-1', + 'de': 'de_DE.ISO8859-1', + 'de_at': 'de_AT.ISO8859-1', + 'de_be': 'de_BE.ISO8859-1', + 'de_ch': 'de_CH.ISO8859-1', + 'de_de': 'de_DE.ISO8859-1', + 'de_it': 'de_IT.ISO8859-1', + 'de_li.utf8': 'de_LI.UTF-8', + 'de_lu': 'de_LU.ISO8859-1', + 'deutsch': 'de_DE.ISO8859-1', + 'doi_in': 'doi_IN.UTF-8', + 'dutch': 'nl_NL.ISO8859-1', + 'dutch.iso88591': 'nl_BE.ISO8859-1', + 'dv_mv': 'dv_MV.UTF-8', + 'dz_bt': 'dz_BT.UTF-8', + 'ee': 'ee_EE.ISO8859-4', + 'ee_ee': 'ee_EE.ISO8859-4', + 'eesti': 'et_EE.ISO8859-1', + 'el': 'el_GR.ISO8859-7', + 'el_cy': 'el_CY.ISO8859-7', + 'el_gr': 'el_GR.ISO8859-7', + 'el_gr@euro': 'el_GR.ISO8859-15', + 'en': 'en_US.ISO8859-1', + 'en_ag': 'en_AG.UTF-8', + 'en_au': 'en_AU.ISO8859-1', + 'en_be': 'en_BE.ISO8859-1', + 'en_bw': 'en_BW.ISO8859-1', + 'en_ca': 'en_CA.ISO8859-1', + 'en_dk': 'en_DK.ISO8859-1', + 'en_dl.utf8': 'en_DL.UTF-8', + 'en_gb': 'en_GB.ISO8859-1', + 'en_hk': 'en_HK.ISO8859-1', + 'en_ie': 'en_IE.ISO8859-1', + 'en_il': 'en_IL.UTF-8', + 'en_in': 'en_IN.ISO8859-1', + 'en_ng': 'en_NG.UTF-8', + 'en_nz': 'en_NZ.ISO8859-1', + 'en_ph': 'en_PH.ISO8859-1', + 'en_sc.utf8': 'en_SC.UTF-8', + 'en_sg': 'en_SG.ISO8859-1', + 'en_uk': 'en_GB.ISO8859-1', + 'en_us': 'en_US.ISO8859-1', + 'en_us@euro@euro': 'en_US.ISO8859-15', + 'en_za': 'en_ZA.ISO8859-1', + 'en_zm': 'en_ZM.UTF-8', + 'en_zw': 'en_ZW.ISO8859-1', + 'en_zw.utf8': 'en_ZS.UTF-8', + 'eng_gb': 'en_GB.ISO8859-1', + 'english': 'en_EN.ISO8859-1', + 'english.iso88591': 'en_US.ISO8859-1', + 'english_uk': 'en_GB.ISO8859-1', + 'english_united-states': 'en_US.ISO8859-1', + 'english_united-states.437': 'C', + 'english_us': 'en_US.ISO8859-1', + 'eo': 'eo_XX.ISO8859-3', + 'eo.utf8': 'eo.UTF-8', + 'eo_eo': 'eo_EO.ISO8859-3', + 'eo_us.utf8': 'eo_US.UTF-8', + 'eo_xx': 'eo_XX.ISO8859-3', + 'es': 'es_ES.ISO8859-1', + 'es_ar': 'es_AR.ISO8859-1', + 'es_bo': 'es_BO.ISO8859-1', + 'es_cl': 'es_CL.ISO8859-1', + 'es_co': 'es_CO.ISO8859-1', + 'es_cr': 'es_CR.ISO8859-1', + 'es_cu': 'es_CU.UTF-8', + 'es_do': 'es_DO.ISO8859-1', + 'es_ec': 'es_EC.ISO8859-1', + 'es_es': 'es_ES.ISO8859-1', + 'es_gt': 'es_GT.ISO8859-1', + 'es_hn': 'es_HN.ISO8859-1', + 'es_mx': 'es_MX.ISO8859-1', + 'es_ni': 'es_NI.ISO8859-1', + 'es_pa': 'es_PA.ISO8859-1', + 'es_pe': 'es_PE.ISO8859-1', + 'es_pr': 'es_PR.ISO8859-1', + 'es_py': 'es_PY.ISO8859-1', + 'es_sv': 'es_SV.ISO8859-1', + 'es_us': 'es_US.ISO8859-1', + 'es_uy': 'es_UY.ISO8859-1', + 'es_ve': 'es_VE.ISO8859-1', + 'estonian': 'et_EE.ISO8859-1', + 'et': 'et_EE.ISO8859-15', + 'et_ee': 'et_EE.ISO8859-15', + 'eu': 'eu_ES.ISO8859-1', + 'eu_es': 'eu_ES.ISO8859-1', + 'eu_fr': 'eu_FR.ISO8859-1', + 'fa': 'fa_IR.UTF-8', + 'fa_ir': 'fa_IR.UTF-8', + 'fa_ir.isiri3342': 'fa_IR.ISIRI-3342', + 'ff_sn': 'ff_SN.UTF-8', + 'fi': 'fi_FI.ISO8859-15', + 'fi_fi': 'fi_FI.ISO8859-15', + 'fil_ph': 'fil_PH.UTF-8', + 'finnish': 'fi_FI.ISO8859-1', + 'fo': 'fo_FO.ISO8859-1', + 'fo_fo': 'fo_FO.ISO8859-1', + 'fr': 'fr_FR.ISO8859-1', + 'fr_be': 'fr_BE.ISO8859-1', + 'fr_ca': 'fr_CA.ISO8859-1', + 'fr_ch': 'fr_CH.ISO8859-1', + 'fr_fr': 'fr_FR.ISO8859-1', + 'fr_lu': 'fr_LU.ISO8859-1', + 'fran\xe7ais': 'fr_FR.ISO8859-1', + 'fre_fr': 'fr_FR.ISO8859-1', + 'french': 'fr_FR.ISO8859-1', + 'french.iso88591': 'fr_CH.ISO8859-1', + 'french_france': 'fr_FR.ISO8859-1', + 'fur_it': 'fur_IT.UTF-8', + 'fy_de': 'fy_DE.UTF-8', + 'fy_nl': 'fy_NL.UTF-8', + 'ga': 'ga_IE.ISO8859-1', + 'ga_ie': 'ga_IE.ISO8859-1', + 'galego': 'gl_ES.ISO8859-1', + 'galician': 'gl_ES.ISO8859-1', + 'gd': 'gd_GB.ISO8859-1', + 'gd_gb': 'gd_GB.ISO8859-1', + 'ger_de': 'de_DE.ISO8859-1', + 'german': 'de_DE.ISO8859-1', + 'german.iso88591': 'de_CH.ISO8859-1', + 'german_germany': 'de_DE.ISO8859-1', + 'gez_er': 'gez_ER.UTF-8', + 'gez_et': 'gez_ET.UTF-8', + 'gl': 'gl_ES.ISO8859-1', + 'gl_es': 'gl_ES.ISO8859-1', + 'greek': 'el_GR.ISO8859-7', + 'gu_in': 'gu_IN.UTF-8', + 'gv': 'gv_GB.ISO8859-1', + 'gv_gb': 'gv_GB.ISO8859-1', + 'ha_ng': 'ha_NG.UTF-8', + 'hak_tw': 'hak_TW.UTF-8', + 'he': 'he_IL.ISO8859-8', + 'he_il': 'he_IL.ISO8859-8', + 'hebrew': 'he_IL.ISO8859-8', + 'hi': 'hi_IN.ISCII-DEV', + 'hi_in': 'hi_IN.ISCII-DEV', + 'hi_in.isciidev': 'hi_IN.ISCII-DEV', + 'hif_fj': 'hif_FJ.UTF-8', + 'hne': 'hne_IN.UTF-8', + 'hne_in': 'hne_IN.UTF-8', + 'hr': 'hr_HR.ISO8859-2', + 'hr_hr': 'hr_HR.ISO8859-2', + 'hrvatski': 'hr_HR.ISO8859-2', + 'hsb_de': 'hsb_DE.ISO8859-2', + 'ht_ht': 'ht_HT.UTF-8', + 'hu': 'hu_HU.ISO8859-2', + 'hu_hu': 'hu_HU.ISO8859-2', + 'hungarian': 'hu_HU.ISO8859-2', + 'hy_am': 'hy_AM.UTF-8', + 'hy_am.armscii8': 'hy_AM.ARMSCII_8', + 'ia': 'ia.UTF-8', + 'ia_fr': 'ia_FR.UTF-8', + 'icelandic': 'is_IS.ISO8859-1', + 'id': 'id_ID.ISO8859-1', + 'id_id': 'id_ID.ISO8859-1', + 'ig_ng': 'ig_NG.UTF-8', + 'ik_ca': 'ik_CA.UTF-8', + 'in': 'id_ID.ISO8859-1', + 'in_id': 'id_ID.ISO8859-1', + 'is': 'is_IS.ISO8859-1', + 'is_is': 'is_IS.ISO8859-1', + 'iso-8859-1': 'en_US.ISO8859-1', + 'iso-8859-15': 'en_US.ISO8859-15', + 'iso8859-1': 'en_US.ISO8859-1', + 'iso8859-15': 'en_US.ISO8859-15', + 'iso_8859_1': 'en_US.ISO8859-1', + 'iso_8859_15': 'en_US.ISO8859-15', + 'it': 'it_IT.ISO8859-1', + 'it_ch': 'it_CH.ISO8859-1', + 'it_it': 'it_IT.ISO8859-1', + 'italian': 'it_IT.ISO8859-1', + 'iu': 'iu_CA.NUNACOM-8', + 'iu_ca': 'iu_CA.NUNACOM-8', + 'iu_ca.nunacom8': 'iu_CA.NUNACOM-8', + 'iw': 'he_IL.ISO8859-8', + 'iw_il': 'he_IL.ISO8859-8', + 'iw_il.utf8': 'iw_IL.UTF-8', + 'ja': 'ja_JP.eucJP', + 'ja_jp': 'ja_JP.eucJP', + 'ja_jp.euc': 'ja_JP.eucJP', + 'ja_jp.mscode': 'ja_JP.SJIS', + 'ja_jp.pck': 'ja_JP.SJIS', + 'japan': 'ja_JP.eucJP', + 'japanese': 'ja_JP.eucJP', + 'japanese-euc': 'ja_JP.eucJP', + 'japanese.euc': 'ja_JP.eucJP', + 'jp_jp': 'ja_JP.eucJP', + 'ka': 'ka_GE.GEORGIAN-ACADEMY', + 'ka_ge': 'ka_GE.GEORGIAN-ACADEMY', + 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', + 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', + 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', + 'kab_dz': 'kab_DZ.UTF-8', + 'kk_kz': 'kk_KZ.ptcp154', + 'kl': 'kl_GL.ISO8859-1', + 'kl_gl': 'kl_GL.ISO8859-1', + 'km_kh': 'km_KH.UTF-8', + 'kn': 'kn_IN.UTF-8', + 'kn_in': 'kn_IN.UTF-8', + 'ko': 'ko_KR.eucKR', + 'ko_kr': 'ko_KR.eucKR', + 'ko_kr.euc': 'ko_KR.eucKR', + 'kok_in': 'kok_IN.UTF-8', + 'korean': 'ko_KR.eucKR', + 'korean.euc': 'ko_KR.eucKR', + 'ks': 'ks_IN.UTF-8', + 'ks_in': 'ks_IN.UTF-8', + 'ks_in@devanagari.utf8': 'ks_IN.UTF-8@devanagari', + 'ku_tr': 'ku_TR.ISO8859-9', + 'kw': 'kw_GB.ISO8859-1', + 'kw_gb': 'kw_GB.ISO8859-1', + 'ky': 'ky_KG.UTF-8', + 'ky_kg': 'ky_KG.UTF-8', + 'lb_lu': 'lb_LU.UTF-8', + 'lg_ug': 'lg_UG.ISO8859-10', + 'li_be': 'li_BE.UTF-8', + 'li_nl': 'li_NL.UTF-8', + 'lij_it': 'lij_IT.UTF-8', + 'lithuanian': 'lt_LT.ISO8859-13', + 'ln_cd': 'ln_CD.UTF-8', + 'lo': 'lo_LA.MULELAO-1', + 'lo_la': 'lo_LA.MULELAO-1', + 'lo_la.cp1133': 'lo_LA.IBM-CP1133', + 'lo_la.ibmcp1133': 'lo_LA.IBM-CP1133', + 'lo_la.mulelao1': 'lo_LA.MULELAO-1', + 'lt': 'lt_LT.ISO8859-13', + 'lt_lt': 'lt_LT.ISO8859-13', + 'lv': 'lv_LV.ISO8859-13', + 'lv_lv': 'lv_LV.ISO8859-13', + 'lzh_tw': 'lzh_TW.UTF-8', + 'mag_in': 'mag_IN.UTF-8', + 'mai': 'mai_IN.UTF-8', + 'mai_in': 'mai_IN.UTF-8', + 'mai_np': 'mai_NP.UTF-8', + 'mfe_mu': 'mfe_MU.UTF-8', + 'mg_mg': 'mg_MG.ISO8859-15', + 'mhr_ru': 'mhr_RU.UTF-8', + 'mi': 'mi_NZ.ISO8859-1', + 'mi_nz': 'mi_NZ.ISO8859-1', + 'miq_ni': 'miq_NI.UTF-8', + 'mjw_in': 'mjw_IN.UTF-8', + 'mk': 'mk_MK.ISO8859-5', + 'mk_mk': 'mk_MK.ISO8859-5', + 'ml': 'ml_IN.UTF-8', + 'ml_in': 'ml_IN.UTF-8', + 'mn_mn': 'mn_MN.UTF-8', + 'mni_in': 'mni_IN.UTF-8', + 'mr': 'mr_IN.UTF-8', + 'mr_in': 'mr_IN.UTF-8', + 'ms': 'ms_MY.ISO8859-1', + 'ms_my': 'ms_MY.ISO8859-1', + 'mt': 'mt_MT.ISO8859-3', + 'mt_mt': 'mt_MT.ISO8859-3', + 'my_mm': 'my_MM.UTF-8', + 'nan_tw': 'nan_TW.UTF-8', + 'nb': 'nb_NO.ISO8859-1', + 'nb_no': 'nb_NO.ISO8859-1', + 'nds_de': 'nds_DE.UTF-8', + 'nds_nl': 'nds_NL.UTF-8', + 'ne_np': 'ne_NP.UTF-8', + 'nhn_mx': 'nhn_MX.UTF-8', + 'niu_nu': 'niu_NU.UTF-8', + 'niu_nz': 'niu_NZ.UTF-8', + 'nl': 'nl_NL.ISO8859-1', + 'nl_aw': 'nl_AW.UTF-8', + 'nl_be': 'nl_BE.ISO8859-1', + 'nl_nl': 'nl_NL.ISO8859-1', + 'nn': 'nn_NO.ISO8859-1', + 'nn_no': 'nn_NO.ISO8859-1', + 'no': 'no_NO.ISO8859-1', + 'no@nynorsk': 'ny_NO.ISO8859-1', + 'no_no': 'no_NO.ISO8859-1', + 'no_no.iso88591@bokmal': 'no_NO.ISO8859-1', + 'no_no.iso88591@nynorsk': 'no_NO.ISO8859-1', + 'norwegian': 'no_NO.ISO8859-1', + 'nr': 'nr_ZA.ISO8859-1', + 'nr_za': 'nr_ZA.ISO8859-1', + 'nso': 'nso_ZA.ISO8859-15', + 'nso_za': 'nso_ZA.ISO8859-15', + 'ny': 'ny_NO.ISO8859-1', + 'ny_no': 'ny_NO.ISO8859-1', + 'nynorsk': 'nn_NO.ISO8859-1', + 'oc': 'oc_FR.ISO8859-1', + 'oc_fr': 'oc_FR.ISO8859-1', + 'om_et': 'om_ET.UTF-8', + 'om_ke': 'om_KE.ISO8859-1', + 'or': 'or_IN.UTF-8', + 'or_in': 'or_IN.UTF-8', + 'os_ru': 'os_RU.UTF-8', + 'pa': 'pa_IN.UTF-8', + 'pa_in': 'pa_IN.UTF-8', + 'pa_pk': 'pa_PK.UTF-8', + 'pap_an': 'pap_AN.UTF-8', + 'pap_aw': 'pap_AW.UTF-8', + 'pap_cw': 'pap_CW.UTF-8', + 'pd': 'pd_US.ISO8859-1', + 'pd_de': 'pd_DE.ISO8859-1', + 'pd_us': 'pd_US.ISO8859-1', + 'ph': 'ph_PH.ISO8859-1', + 'ph_ph': 'ph_PH.ISO8859-1', + 'pl': 'pl_PL.ISO8859-2', + 'pl_pl': 'pl_PL.ISO8859-2', + 'polish': 'pl_PL.ISO8859-2', + 'portuguese': 'pt_PT.ISO8859-1', + 'portuguese_brazil': 'pt_BR.ISO8859-1', + 'posix': 'C', + 'posix-utf2': 'C', + 'pp': 'pp_AN.ISO8859-1', + 'pp_an': 'pp_AN.ISO8859-1', + 'ps_af': 'ps_AF.UTF-8', + 'pt': 'pt_PT.ISO8859-1', + 'pt_br': 'pt_BR.ISO8859-1', + 'pt_pt': 'pt_PT.ISO8859-1', + 'quz_pe': 'quz_PE.UTF-8', + 'raj_in': 'raj_IN.UTF-8', + 'ro': 'ro_RO.ISO8859-2', + 'ro_ro': 'ro_RO.ISO8859-2', + 'romanian': 'ro_RO.ISO8859-2', + 'ru': 'ru_RU.UTF-8', + 'ru_ru': 'ru_RU.UTF-8', + 'ru_ua': 'ru_UA.KOI8-U', + 'rumanian': 'ro_RO.ISO8859-2', + 'russian': 'ru_RU.KOI8-R', + 'rw': 'rw_RW.ISO8859-1', + 'rw_rw': 'rw_RW.ISO8859-1', + 'sa_in': 'sa_IN.UTF-8', + 'sat_in': 'sat_IN.UTF-8', + 'sc_it': 'sc_IT.UTF-8', + 'sd': 'sd_IN.UTF-8', + 'sd_in': 'sd_IN.UTF-8', + 'sd_in@devanagari.utf8': 'sd_IN.UTF-8@devanagari', + 'sd_pk': 'sd_PK.UTF-8', + 'se_no': 'se_NO.UTF-8', + 'serbocroatian': 'sr_RS.UTF-8@latin', + 'sgs_lt': 'sgs_LT.UTF-8', + 'sh': 'sr_RS.UTF-8@latin', + 'sh_ba.iso88592@bosnia': 'sr_CS.ISO8859-2', + 'sh_hr': 'sh_HR.ISO8859-2', + 'sh_hr.iso88592': 'hr_HR.ISO8859-2', + 'sh_sp': 'sr_CS.ISO8859-2', + 'sh_yu': 'sr_RS.UTF-8@latin', + 'shn_mm': 'shn_MM.UTF-8', + 'shs_ca': 'shs_CA.UTF-8', + 'si': 'si_LK.UTF-8', + 'si_lk': 'si_LK.UTF-8', + 'sid_et': 'sid_ET.UTF-8', + 'sinhala': 'si_LK.UTF-8', + 'sk': 'sk_SK.ISO8859-2', + 'sk_sk': 'sk_SK.ISO8859-2', + 'sl': 'sl_SI.ISO8859-2', + 'sl_cs': 'sl_CS.ISO8859-2', + 'sl_si': 'sl_SI.ISO8859-2', + 'slovak': 'sk_SK.ISO8859-2', + 'slovene': 'sl_SI.ISO8859-2', + 'slovenian': 'sl_SI.ISO8859-2', + 'sm_ws': 'sm_WS.UTF-8', + 'so_dj': 'so_DJ.ISO8859-1', + 'so_et': 'so_ET.UTF-8', + 'so_ke': 'so_KE.ISO8859-1', + 'so_so': 'so_SO.ISO8859-1', + 'sp': 'sr_CS.ISO8859-5', + 'sp_yu': 'sr_CS.ISO8859-5', + 'spanish': 'es_ES.ISO8859-1', + 'spanish_spain': 'es_ES.ISO8859-1', + 'sq': 'sq_AL.ISO8859-2', + 'sq_al': 'sq_AL.ISO8859-2', + 'sq_mk': 'sq_MK.UTF-8', + 'sr': 'sr_RS.UTF-8', + 'sr@cyrillic': 'sr_RS.UTF-8', + 'sr@latn': 'sr_CS.UTF-8@latin', + 'sr_cs': 'sr_CS.UTF-8', + 'sr_cs.iso88592@latn': 'sr_CS.ISO8859-2', + 'sr_cs@latn': 'sr_CS.UTF-8@latin', + 'sr_me': 'sr_ME.UTF-8', + 'sr_rs': 'sr_RS.UTF-8', + 'sr_rs@latn': 'sr_RS.UTF-8@latin', + 'sr_sp': 'sr_CS.ISO8859-2', + 'sr_yu': 'sr_RS.UTF-8@latin', + 'sr_yu.cp1251@cyrillic': 'sr_CS.CP1251', + 'sr_yu.iso88592': 'sr_CS.ISO8859-2', + 'sr_yu.iso88595': 'sr_CS.ISO8859-5', + 'sr_yu.iso88595@cyrillic': 'sr_CS.ISO8859-5', + 'sr_yu.microsoftcp1251@cyrillic': 'sr_CS.CP1251', + 'sr_yu.utf8': 'sr_RS.UTF-8', + 'sr_yu.utf8@cyrillic': 'sr_RS.UTF-8', + 'sr_yu@cyrillic': 'sr_RS.UTF-8', + 'ss': 'ss_ZA.ISO8859-1', + 'ss_za': 'ss_ZA.ISO8859-1', + 'st': 'st_ZA.ISO8859-1', + 'st_za': 'st_ZA.ISO8859-1', + 'sv': 'sv_SE.ISO8859-1', + 'sv_fi': 'sv_FI.ISO8859-1', + 'sv_se': 'sv_SE.ISO8859-1', + 'sw_ke': 'sw_KE.UTF-8', + 'sw_tz': 'sw_TZ.UTF-8', + 'swedish': 'sv_SE.ISO8859-1', + 'szl_pl': 'szl_PL.UTF-8', + 'ta': 'ta_IN.TSCII-0', + 'ta_in': 'ta_IN.TSCII-0', + 'ta_in.tscii': 'ta_IN.TSCII-0', + 'ta_in.tscii0': 'ta_IN.TSCII-0', + 'ta_lk': 'ta_LK.UTF-8', + 'tcy_in.utf8': 'tcy_IN.UTF-8', + 'te': 'te_IN.UTF-8', + 'te_in': 'te_IN.UTF-8', + 'tg': 'tg_TJ.KOI8-C', + 'tg_tj': 'tg_TJ.KOI8-C', + 'th': 'th_TH.ISO8859-11', + 'th_th': 'th_TH.ISO8859-11', + 'th_th.tactis': 'th_TH.TIS620', + 'th_th.tis620': 'th_TH.TIS620', + 'thai': 'th_TH.ISO8859-11', + 'the_np': 'the_NP.UTF-8', + 'ti_er': 'ti_ER.UTF-8', + 'ti_et': 'ti_ET.UTF-8', + 'tig_er': 'tig_ER.UTF-8', + 'tk_tm': 'tk_TM.UTF-8', + 'tl': 'tl_PH.ISO8859-1', + 'tl_ph': 'tl_PH.ISO8859-1', + 'tn': 'tn_ZA.ISO8859-15', + 'tn_za': 'tn_ZA.ISO8859-15', + 'to_to': 'to_TO.UTF-8', + 'tpi_pg': 'tpi_PG.UTF-8', + 'tr': 'tr_TR.ISO8859-9', + 'tr_cy': 'tr_CY.ISO8859-9', + 'tr_tr': 'tr_TR.ISO8859-9', + 'ts': 'ts_ZA.ISO8859-1', + 'ts_za': 'ts_ZA.ISO8859-1', + 'tt': 'tt_RU.TATAR-CYR', + 'tt_ru': 'tt_RU.TATAR-CYR', + 'tt_ru.tatarcyr': 'tt_RU.TATAR-CYR', + 'tt_ru@iqtelif': 'tt_RU.UTF-8@iqtelif', + 'turkish': 'tr_TR.ISO8859-9', + 'ug_cn': 'ug_CN.UTF-8', + 'uk': 'uk_UA.KOI8-U', + 'uk_ua': 'uk_UA.KOI8-U', + 'univ': 'en_US.utf', + 'universal': 'en_US.utf', + 'universal.utf8@ucs4': 'en_US.UTF-8', + 'unm_us': 'unm_US.UTF-8', + 'ur': 'ur_PK.CP1256', + 'ur_in': 'ur_IN.UTF-8', + 'ur_pk': 'ur_PK.CP1256', + 'uz': 'uz_UZ.UTF-8', + 'uz_uz': 'uz_UZ.UTF-8', + 'uz_uz@cyrillic': 'uz_UZ.UTF-8', + 've': 've_ZA.UTF-8', + 've_za': 've_ZA.UTF-8', + 'vi': 'vi_VN.TCVN', + 'vi_vn': 'vi_VN.TCVN', + 'vi_vn.tcvn': 'vi_VN.TCVN', + 'vi_vn.tcvn5712': 'vi_VN.TCVN', + 'vi_vn.viscii': 'vi_VN.VISCII', + 'vi_vn.viscii111': 'vi_VN.VISCII', + 'wa': 'wa_BE.ISO8859-1', + 'wa_be': 'wa_BE.ISO8859-1', + 'wae_ch': 'wae_CH.UTF-8', + 'wal_et': 'wal_ET.UTF-8', + 'wo_sn': 'wo_SN.UTF-8', + 'xh': 'xh_ZA.ISO8859-1', + 'xh_za': 'xh_ZA.ISO8859-1', + 'yi': 'yi_US.CP1255', + 'yi_us': 'yi_US.CP1255', + 'yo_ng': 'yo_NG.UTF-8', + 'yue_hk': 'yue_HK.UTF-8', + 'yuw_pg': 'yuw_PG.UTF-8', + 'zh': 'zh_CN.eucCN', + 'zh_cn': 'zh_CN.gb2312', + 'zh_cn.big5': 'zh_TW.big5', + 'zh_cn.euc': 'zh_CN.eucCN', + 'zh_hk': 'zh_HK.big5hkscs', + 'zh_hk.big5hk': 'zh_HK.big5hkscs', + 'zh_sg': 'zh_SG.GB2312', + 'zh_sg.gbk': 'zh_SG.GBK', + 'zh_tw': 'zh_TW.big5', + 'zh_tw.euc': 'zh_TW.eucTW', + 'zh_tw.euctw': 'zh_TW.eucTW', + 'zu': 'zu_ZA.ISO8859-1', + 'zu_za': 'zu_ZA.ISO8859-1', +} + +# +# This maps Windows language identifiers to locale strings. +# +# This list has been updated from +# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/nls_238z.asp +# to include every locale up to Windows Vista. +# +# NOTE: this mapping is incomplete. If your language is missing, please +# submit a bug report to the Python bug tracker at http://bugs.python.org/ +# Make sure you include the missing language identifier and the suggested +# locale code. +# + +windows_locale = { + 0x0436: "af_ZA", # Afrikaans + 0x041c: "sq_AL", # Albanian + 0x0484: "gsw_FR",# Alsatian - France + 0x045e: "am_ET", # Amharic - Ethiopia + 0x0401: "ar_SA", # Arabic - Saudi Arabia + 0x0801: "ar_IQ", # Arabic - Iraq + 0x0c01: "ar_EG", # Arabic - Egypt + 0x1001: "ar_LY", # Arabic - Libya + 0x1401: "ar_DZ", # Arabic - Algeria + 0x1801: "ar_MA", # Arabic - Morocco + 0x1c01: "ar_TN", # Arabic - Tunisia + 0x2001: "ar_OM", # Arabic - Oman + 0x2401: "ar_YE", # Arabic - Yemen + 0x2801: "ar_SY", # Arabic - Syria + 0x2c01: "ar_JO", # Arabic - Jordan + 0x3001: "ar_LB", # Arabic - Lebanon + 0x3401: "ar_KW", # Arabic - Kuwait + 0x3801: "ar_AE", # Arabic - United Arab Emirates + 0x3c01: "ar_BH", # Arabic - Bahrain + 0x4001: "ar_QA", # Arabic - Qatar + 0x042b: "hy_AM", # Armenian + 0x044d: "as_IN", # Assamese - India + 0x042c: "az_AZ", # Azeri - Latin + 0x082c: "az_AZ", # Azeri - Cyrillic + 0x046d: "ba_RU", # Bashkir + 0x042d: "eu_ES", # Basque - Russia + 0x0423: "be_BY", # Belarusian + 0x0445: "bn_IN", # Begali + 0x201a: "bs_BA", # Bosnian - Cyrillic + 0x141a: "bs_BA", # Bosnian - Latin + 0x047e: "br_FR", # Breton - France + 0x0402: "bg_BG", # Bulgarian +# 0x0455: "my_MM", # Burmese - Not supported + 0x0403: "ca_ES", # Catalan + 0x0004: "zh_CHS",# Chinese - Simplified + 0x0404: "zh_TW", # Chinese - Taiwan + 0x0804: "zh_CN", # Chinese - PRC + 0x0c04: "zh_HK", # Chinese - Hong Kong S.A.R. + 0x1004: "zh_SG", # Chinese - Singapore + 0x1404: "zh_MO", # Chinese - Macao S.A.R. + 0x7c04: "zh_CHT",# Chinese - Traditional + 0x0483: "co_FR", # Corsican - France + 0x041a: "hr_HR", # Croatian + 0x101a: "hr_BA", # Croatian - Bosnia + 0x0405: "cs_CZ", # Czech + 0x0406: "da_DK", # Danish + 0x048c: "gbz_AF",# Dari - Afghanistan + 0x0465: "div_MV",# Divehi - Maldives + 0x0413: "nl_NL", # Dutch - The Netherlands + 0x0813: "nl_BE", # Dutch - Belgium + 0x0409: "en_US", # English - United States + 0x0809: "en_GB", # English - United Kingdom + 0x0c09: "en_AU", # English - Australia + 0x1009: "en_CA", # English - Canada + 0x1409: "en_NZ", # English - New Zealand + 0x1809: "en_IE", # English - Ireland + 0x1c09: "en_ZA", # English - South Africa + 0x2009: "en_JA", # English - Jamaica + 0x2409: "en_CB", # English - Caribbean + 0x2809: "en_BZ", # English - Belize + 0x2c09: "en_TT", # English - Trinidad + 0x3009: "en_ZW", # English - Zimbabwe + 0x3409: "en_PH", # English - Philippines + 0x4009: "en_IN", # English - India + 0x4409: "en_MY", # English - Malaysia + 0x4809: "en_IN", # English - Singapore + 0x0425: "et_EE", # Estonian + 0x0438: "fo_FO", # Faroese + 0x0464: "fil_PH",# Filipino + 0x040b: "fi_FI", # Finnish + 0x040c: "fr_FR", # French - France + 0x080c: "fr_BE", # French - Belgium + 0x0c0c: "fr_CA", # French - Canada + 0x100c: "fr_CH", # French - Switzerland + 0x140c: "fr_LU", # French - Luxembourg + 0x180c: "fr_MC", # French - Monaco + 0x0462: "fy_NL", # Frisian - Netherlands + 0x0456: "gl_ES", # Galician + 0x0437: "ka_GE", # Georgian + 0x0407: "de_DE", # German - Germany + 0x0807: "de_CH", # German - Switzerland + 0x0c07: "de_AT", # German - Austria + 0x1007: "de_LU", # German - Luxembourg + 0x1407: "de_LI", # German - Liechtenstein + 0x0408: "el_GR", # Greek + 0x046f: "kl_GL", # Greenlandic - Greenland + 0x0447: "gu_IN", # Gujarati + 0x0468: "ha_NG", # Hausa - Latin + 0x040d: "he_IL", # Hebrew + 0x0439: "hi_IN", # Hindi + 0x040e: "hu_HU", # Hungarian + 0x040f: "is_IS", # Icelandic + 0x0421: "id_ID", # Indonesian + 0x045d: "iu_CA", # Inuktitut - Syllabics + 0x085d: "iu_CA", # Inuktitut - Latin + 0x083c: "ga_IE", # Irish - Ireland + 0x0410: "it_IT", # Italian - Italy + 0x0810: "it_CH", # Italian - Switzerland + 0x0411: "ja_JP", # Japanese + 0x044b: "kn_IN", # Kannada - India + 0x043f: "kk_KZ", # Kazakh + 0x0453: "kh_KH", # Khmer - Cambodia + 0x0486: "qut_GT",# K'iche - Guatemala + 0x0487: "rw_RW", # Kinyarwanda - Rwanda + 0x0457: "kok_IN",# Konkani + 0x0412: "ko_KR", # Korean + 0x0440: "ky_KG", # Kyrgyz + 0x0454: "lo_LA", # Lao - Lao PDR + 0x0426: "lv_LV", # Latvian + 0x0427: "lt_LT", # Lithuanian + 0x082e: "dsb_DE",# Lower Sorbian - Germany + 0x046e: "lb_LU", # Luxembourgish + 0x042f: "mk_MK", # FYROM Macedonian + 0x043e: "ms_MY", # Malay - Malaysia + 0x083e: "ms_BN", # Malay - Brunei Darussalam + 0x044c: "ml_IN", # Malayalam - India + 0x043a: "mt_MT", # Maltese + 0x0481: "mi_NZ", # Maori + 0x047a: "arn_CL",# Mapudungun + 0x044e: "mr_IN", # Marathi + 0x047c: "moh_CA",# Mohawk - Canada + 0x0450: "mn_MN", # Mongolian - Cyrillic + 0x0850: "mn_CN", # Mongolian - PRC + 0x0461: "ne_NP", # Nepali + 0x0414: "nb_NO", # Norwegian - Bokmal + 0x0814: "nn_NO", # Norwegian - Nynorsk + 0x0482: "oc_FR", # Occitan - France + 0x0448: "or_IN", # Oriya - India + 0x0463: "ps_AF", # Pashto - Afghanistan + 0x0429: "fa_IR", # Persian + 0x0415: "pl_PL", # Polish + 0x0416: "pt_BR", # Portuguese - Brazil + 0x0816: "pt_PT", # Portuguese - Portugal + 0x0446: "pa_IN", # Punjabi + 0x046b: "quz_BO",# Quechua (Bolivia) + 0x086b: "quz_EC",# Quechua (Ecuador) + 0x0c6b: "quz_PE",# Quechua (Peru) + 0x0418: "ro_RO", # Romanian - Romania + 0x0417: "rm_CH", # Romansh + 0x0419: "ru_RU", # Russian + 0x243b: "smn_FI",# Sami Finland + 0x103b: "smj_NO",# Sami Norway + 0x143b: "smj_SE",# Sami Sweden + 0x043b: "se_NO", # Sami Northern Norway + 0x083b: "se_SE", # Sami Northern Sweden + 0x0c3b: "se_FI", # Sami Northern Finland + 0x203b: "sms_FI",# Sami Skolt + 0x183b: "sma_NO",# Sami Southern Norway + 0x1c3b: "sma_SE",# Sami Southern Sweden + 0x044f: "sa_IN", # Sanskrit + 0x0c1a: "sr_SP", # Serbian - Cyrillic + 0x1c1a: "sr_BA", # Serbian - Bosnia Cyrillic + 0x081a: "sr_SP", # Serbian - Latin + 0x181a: "sr_BA", # Serbian - Bosnia Latin + 0x045b: "si_LK", # Sinhala - Sri Lanka + 0x046c: "ns_ZA", # Northern Sotho + 0x0432: "tn_ZA", # Setswana - Southern Africa + 0x041b: "sk_SK", # Slovak + 0x0424: "sl_SI", # Slovenian + 0x040a: "es_ES", # Spanish - Spain + 0x080a: "es_MX", # Spanish - Mexico + 0x0c0a: "es_ES", # Spanish - Spain (Modern) + 0x100a: "es_GT", # Spanish - Guatemala + 0x140a: "es_CR", # Spanish - Costa Rica + 0x180a: "es_PA", # Spanish - Panama + 0x1c0a: "es_DO", # Spanish - Dominican Republic + 0x200a: "es_VE", # Spanish - Venezuela + 0x240a: "es_CO", # Spanish - Colombia + 0x280a: "es_PE", # Spanish - Peru + 0x2c0a: "es_AR", # Spanish - Argentina + 0x300a: "es_EC", # Spanish - Ecuador + 0x340a: "es_CL", # Spanish - Chile + 0x380a: "es_UR", # Spanish - Uruguay + 0x3c0a: "es_PY", # Spanish - Paraguay + 0x400a: "es_BO", # Spanish - Bolivia + 0x440a: "es_SV", # Spanish - El Salvador + 0x480a: "es_HN", # Spanish - Honduras + 0x4c0a: "es_NI", # Spanish - Nicaragua + 0x500a: "es_PR", # Spanish - Puerto Rico + 0x540a: "es_US", # Spanish - United States +# 0x0430: "", # Sutu - Not supported + 0x0441: "sw_KE", # Swahili + 0x041d: "sv_SE", # Swedish - Sweden + 0x081d: "sv_FI", # Swedish - Finland + 0x045a: "syr_SY",# Syriac + 0x0428: "tg_TJ", # Tajik - Cyrillic + 0x085f: "tmz_DZ",# Tamazight - Latin + 0x0449: "ta_IN", # Tamil + 0x0444: "tt_RU", # Tatar + 0x044a: "te_IN", # Telugu + 0x041e: "th_TH", # Thai + 0x0851: "bo_BT", # Tibetan - Bhutan + 0x0451: "bo_CN", # Tibetan - PRC + 0x041f: "tr_TR", # Turkish + 0x0442: "tk_TM", # Turkmen - Cyrillic + 0x0480: "ug_CN", # Uighur - Arabic + 0x0422: "uk_UA", # Ukrainian + 0x042e: "wen_DE",# Upper Sorbian - Germany + 0x0420: "ur_PK", # Urdu + 0x0820: "ur_IN", # Urdu - India + 0x0443: "uz_UZ", # Uzbek - Latin + 0x0843: "uz_UZ", # Uzbek - Cyrillic + 0x042a: "vi_VN", # Vietnamese + 0x0452: "cy_GB", # Welsh + 0x0488: "wo_SN", # Wolof - Senegal + 0x0434: "xh_ZA", # Xhosa - South Africa + 0x0485: "sah_RU",# Yakut - Cyrillic + 0x0478: "ii_CN", # Yi - PRC + 0x046a: "yo_NG", # Yoruba - Nigeria + 0x0435: "zu_ZA", # Zulu +} + +def _print_locale(): + + """ Test function. + """ + categories = {} + def _init_categories(categories=categories): + for k,v in globals().items(): + if k[:3] == 'LC_': + categories[k] = v + _init_categories() + del categories['LC_ALL'] + + print('Locale defaults as determined by getdefaultlocale():') + print('-'*72) + lang, enc = getdefaultlocale() + print('Language: ', lang or '(undefined)') + print('Encoding: ', enc or '(undefined)') + print() + + print('Locale settings on startup:') + print('-'*72) + for name,category in categories.items(): + print(name, '...') + lang, enc = getlocale(category) + print(' Language: ', lang or '(undefined)') + print(' Encoding: ', enc or '(undefined)') + print() + + print() + print('Locale settings after calling resetlocale():') + print('-'*72) + resetlocale() + for name,category in categories.items(): + print(name, '...') + lang, enc = getlocale(category) + print(' Language: ', lang or '(undefined)') + print(' Encoding: ', enc or '(undefined)') + print() + + try: + setlocale(LC_ALL, "") + except: + print('NOTE:') + print('setlocale(LC_ALL, "") does not support the default locale') + print('given in the OS environment variables.') + else: + print() + print('Locale settings after calling setlocale(LC_ALL, ""):') + print('-'*72) + for name,category in categories.items(): + print(name, '...') + lang, enc = getlocale(category) + print(' Language: ', lang or '(undefined)') + print(' Encoding: ', enc or '(undefined)') + print() + +### + +try: + LC_MESSAGES +except NameError: + pass +else: + __all__.append("LC_MESSAGES") + +if __name__=='__main__': + print('Locale aliasing:') + print() + _print_locale() + print() + print('Number formatting:') + print() + _test() diff --git a/winvenv/Lib/no-global-site-packages.txt b/winvenv/Lib/no-global-site-packages.txt new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/ntpath.py b/winvenv/Lib/ntpath.py new file mode 100644 index 0000000..f0e03a2 --- /dev/null +++ b/winvenv/Lib/ntpath.py @@ -0,0 +1,669 @@ +# Module 'ntpath' -- common operations on WinNT/Win95 pathnames +"""Common pathname manipulations, WindowsNT/95 version. + +Instead of importing this module directly, import os and refer to this +module as os.path. +""" + +# strings representing various path-related bits and pieces +# These are primarily for export; internally, they are hardcoded. +# Should be set before imports for resolving cyclic dependency. +curdir = '.' +pardir = '..' +extsep = '.' +sep = '\\' +pathsep = ';' +altsep = '/' +defpath = '.;C:\\bin' +devnull = 'nul' + +import os +import sys +import stat +import genericpath +from genericpath import * + +__all__ = ["normcase","isabs","join","splitdrive","split","splitext", + "basename","dirname","commonprefix","getsize","getmtime", + "getatime","getctime", "islink","exists","lexists","isdir","isfile", + "ismount", "expanduser","expandvars","normpath","abspath", + "curdir","pardir","sep","pathsep","defpath","altsep", + "extsep","devnull","realpath","supports_unicode_filenames","relpath", + "samefile", "sameopenfile", "samestat", "commonpath"] + +def _get_bothseps(path): + if isinstance(path, bytes): + return b'\\/' + else: + return '\\/' + +# Normalize the case of a pathname and map slashes to backslashes. +# Other normalizations (such as optimizing '../' away) are not done +# (this is done by normpath). + +def normcase(s): + """Normalize case of pathname. + + Makes all characters lowercase and all slashes into backslashes.""" + s = os.fspath(s) + try: + if isinstance(s, bytes): + return s.replace(b'/', b'\\').lower() + else: + return s.replace('/', '\\').lower() + except (TypeError, AttributeError): + if not isinstance(s, (bytes, str)): + raise TypeError("normcase() argument must be str or bytes, " + "not %r" % s.__class__.__name__) from None + raise + + +# Return whether a path is absolute. +# Trivial in Posix, harder on Windows. +# For Windows it is absolute if it starts with a slash or backslash (current +# volume), or if a pathname after the volume-letter-and-colon or UNC-resource +# starts with a slash or backslash. + +def isabs(s): + """Test whether a path is absolute""" + s = os.fspath(s) + s = splitdrive(s)[1] + return len(s) > 0 and s[0] in _get_bothseps(s) + + +# Join two (or more) paths. +def join(path, *paths): + path = os.fspath(path) + if isinstance(path, bytes): + sep = b'\\' + seps = b'\\/' + colon = b':' + else: + sep = '\\' + seps = '\\/' + colon = ':' + try: + if not paths: + path[:0] + sep #23780: Ensure compatible data type even if p is null. + result_drive, result_path = splitdrive(path) + for p in map(os.fspath, paths): + p_drive, p_path = splitdrive(p) + if p_path and p_path[0] in seps: + # Second path is absolute + if p_drive or not result_drive: + result_drive = p_drive + result_path = p_path + continue + elif p_drive and p_drive != result_drive: + if p_drive.lower() != result_drive.lower(): + # Different drives => ignore the first path entirely + result_drive = p_drive + result_path = p_path + continue + # Same drive in different case + result_drive = p_drive + # Second path is relative to the first + if result_path and result_path[-1] not in seps: + result_path = result_path + sep + result_path = result_path + p_path + ## add separator between UNC and non-absolute path + if (result_path and result_path[0] not in seps and + result_drive and result_drive[-1:] != colon): + return result_drive + sep + result_path + return result_drive + result_path + except (TypeError, AttributeError, BytesWarning): + genericpath._check_arg_types('join', path, *paths) + raise + + +# Split a path in a drive specification (a drive letter followed by a +# colon) and the path specification. +# It is always true that drivespec + pathspec == p +def splitdrive(p): + """Split a pathname into drive/UNC sharepoint and relative path specifiers. + Returns a 2-tuple (drive_or_unc, path); either part may be empty. + + If you assign + result = splitdrive(p) + It is always true that: + result[0] + result[1] == p + + If the path contained a drive letter, drive_or_unc will contain everything + up to and including the colon. e.g. splitdrive("c:/dir") returns ("c:", "/dir") + + If the path contained a UNC path, the drive_or_unc will contain the host name + and share up to but not including the fourth directory separator character. + e.g. splitdrive("//host/computer/dir") returns ("//host/computer", "/dir") + + Paths cannot contain both a drive letter and a UNC path. + + """ + p = os.fspath(p) + if len(p) >= 2: + if isinstance(p, bytes): + sep = b'\\' + altsep = b'/' + colon = b':' + else: + sep = '\\' + altsep = '/' + colon = ':' + normp = p.replace(altsep, sep) + if (normp[0:2] == sep*2) and (normp[2:3] != sep): + # is a UNC path: + # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path + # \\machine\mountpoint\directory\etc\... + # directory ^^^^^^^^^^^^^^^ + index = normp.find(sep, 2) + if index == -1: + return p[:0], p + index2 = normp.find(sep, index + 1) + # a UNC path can't have two slashes in a row + # (after the initial two) + if index2 == index + 1: + return p[:0], p + if index2 == -1: + index2 = len(p) + return p[:index2], p[index2:] + if normp[1:2] == colon: + return p[:2], p[2:] + return p[:0], p + + +# Split a path in head (everything up to the last '/') and tail (the +# rest). After the trailing '/' is stripped, the invariant +# join(head, tail) == p holds. +# The resulting head won't end in '/' unless it is the root. + +def split(p): + """Split a pathname. + + Return tuple (head, tail) where tail is everything after the final slash. + Either part may be empty.""" + p = os.fspath(p) + seps = _get_bothseps(p) + d, p = splitdrive(p) + # set i to index beyond p's last slash + i = len(p) + while i and p[i-1] not in seps: + i -= 1 + head, tail = p[:i], p[i:] # now tail has no slashes + # remove trailing slashes from head, unless it's all slashes + head = head.rstrip(seps) or head + return d + head, tail + + +# Split a path in root and extension. +# The extension is everything starting at the last dot in the last +# pathname component; the root is everything before that. +# It is always true that root + ext == p. + +def splitext(p): + p = os.fspath(p) + if isinstance(p, bytes): + return genericpath._splitext(p, b'\\', b'/', b'.') + else: + return genericpath._splitext(p, '\\', '/', '.') +splitext.__doc__ = genericpath._splitext.__doc__ + + +# Return the tail (basename) part of a path. + +def basename(p): + """Returns the final component of a pathname""" + return split(p)[1] + + +# Return the head (dirname) part of a path. + +def dirname(p): + """Returns the directory component of a pathname""" + return split(p)[0] + +# Is a path a symbolic link? +# This will always return false on systems where os.lstat doesn't exist. + +def islink(path): + """Test whether a path is a symbolic link. + This will always return false for Windows prior to 6.0. + """ + try: + st = os.lstat(path) + except (OSError, AttributeError): + return False + return stat.S_ISLNK(st.st_mode) + +# Being true for dangling symbolic links is also useful. + +def lexists(path): + """Test whether a path exists. Returns True for broken symbolic links""" + try: + st = os.lstat(path) + except OSError: + return False + return True + +# Is a path a mount point? +# Any drive letter root (eg c:\) +# Any share UNC (eg \\server\share) +# Any volume mounted on a filesystem folder +# +# No one method detects all three situations. Historically we've lexically +# detected drive letter roots and share UNCs. The canonical approach to +# detecting mounted volumes (querying the reparse tag) fails for the most +# common case: drive letter roots. The alternative which uses GetVolumePathName +# fails if the drive letter is the result of a SUBST. +try: + from nt import _getvolumepathname +except ImportError: + _getvolumepathname = None +def ismount(path): + """Test whether a path is a mount point (a drive root, the root of a + share, or a mounted volume)""" + path = os.fspath(path) + seps = _get_bothseps(path) + path = abspath(path) + root, rest = splitdrive(path) + if root and root[0] in seps: + return (not rest) or (rest in seps) + if rest in seps: + return True + + if _getvolumepathname: + return path.rstrip(seps) == _getvolumepathname(path).rstrip(seps) + else: + return False + + +# Expand paths beginning with '~' or '~user'. +# '~' means $HOME; '~user' means that user's home directory. +# If the path doesn't begin with '~', or if the user or $HOME is unknown, +# the path is returned unchanged (leaving error reporting to whatever +# function is called with the expanded path as argument). +# See also module 'glob' for expansion of *, ? and [...] in pathnames. +# (A function should also be defined to do full *sh-style environment +# variable expansion.) + +def expanduser(path): + """Expand ~ and ~user constructs. + + If user or $HOME is unknown, do nothing.""" + path = os.fspath(path) + if isinstance(path, bytes): + tilde = b'~' + else: + tilde = '~' + if not path.startswith(tilde): + return path + i, n = 1, len(path) + while i < n and path[i] not in _get_bothseps(path): + i += 1 + + if 'HOME' in os.environ: + userhome = os.environ['HOME'] + elif 'USERPROFILE' in os.environ: + userhome = os.environ['USERPROFILE'] + elif not 'HOMEPATH' in os.environ: + return path + else: + try: + drive = os.environ['HOMEDRIVE'] + except KeyError: + drive = '' + userhome = join(drive, os.environ['HOMEPATH']) + + if isinstance(path, bytes): + userhome = os.fsencode(userhome) + + if i != 1: #~user + userhome = join(dirname(userhome), path[1:i]) + + return userhome + path[i:] + + +# Expand paths containing shell variable substitutions. +# The following rules apply: +# - no expansion within single quotes +# - '$$' is translated into '$' +# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2% +# - ${varname} is accepted. +# - $varname is accepted. +# - %varname% is accepted. +# - varnames can be made out of letters, digits and the characters '_-' +# (though is not verified in the ${varname} and %varname% cases) +# XXX With COMMAND.COM you can use any characters in a variable name, +# XXX except '^|<>='. + +def expandvars(path): + """Expand shell variables of the forms $var, ${var} and %var%. + + Unknown variables are left unchanged.""" + path = os.fspath(path) + if isinstance(path, bytes): + if b'$' not in path and b'%' not in path: + return path + import string + varchars = bytes(string.ascii_letters + string.digits + '_-', 'ascii') + quote = b'\'' + percent = b'%' + brace = b'{' + rbrace = b'}' + dollar = b'$' + environ = getattr(os, 'environb', None) + else: + if '$' not in path and '%' not in path: + return path + import string + varchars = string.ascii_letters + string.digits + '_-' + quote = '\'' + percent = '%' + brace = '{' + rbrace = '}' + dollar = '$' + environ = os.environ + res = path[:0] + index = 0 + pathlen = len(path) + while index < pathlen: + c = path[index:index+1] + if c == quote: # no expansion within single quotes + path = path[index + 1:] + pathlen = len(path) + try: + index = path.index(c) + res += c + path[:index + 1] + except ValueError: + res += c + path + index = pathlen - 1 + elif c == percent: # variable or '%' + if path[index + 1:index + 2] == percent: + res += c + index += 1 + else: + path = path[index+1:] + pathlen = len(path) + try: + index = path.index(percent) + except ValueError: + res += percent + path + index = pathlen - 1 + else: + var = path[:index] + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = percent + var + percent + res += value + elif c == dollar: # variable or '$$' + if path[index + 1:index + 2] == dollar: + res += c + index += 1 + elif path[index + 1:index + 2] == brace: + path = path[index+2:] + pathlen = len(path) + try: + index = path.index(rbrace) + except ValueError: + res += dollar + brace + path + index = pathlen - 1 + else: + var = path[:index] + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = dollar + brace + var + rbrace + res += value + else: + var = path[:0] + index += 1 + c = path[index:index + 1] + while c and c in varchars: + var += c + index += 1 + c = path[index:index + 1] + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = dollar + var + res += value + if c: + index -= 1 + else: + res += c + index += 1 + return res + + +# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. +# Previously, this function also truncated pathnames to 8+3 format, +# but as this module is called "ntpath", that's obviously wrong! + +def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) + if isinstance(path, bytes): + sep = b'\\' + altsep = b'/' + curdir = b'.' + pardir = b'..' + special_prefixes = (b'\\\\.\\', b'\\\\?\\') + else: + sep = '\\' + altsep = '/' + curdir = '.' + pardir = '..' + special_prefixes = ('\\\\.\\', '\\\\?\\') + if path.startswith(special_prefixes): + # in the case of paths with these prefixes: + # \\.\ -> device names + # \\?\ -> literal paths + # do not do any normalization, but return the path unchanged + return path + path = path.replace(altsep, sep) + prefix, path = splitdrive(path) + + # collapse initial backslashes + if path.startswith(sep): + prefix += sep + path = path.lstrip(sep) + + comps = path.split(sep) + i = 0 + while i < len(comps): + if not comps[i] or comps[i] == curdir: + del comps[i] + elif comps[i] == pardir: + if i > 0 and comps[i-1] != pardir: + del comps[i-1:i+1] + i -= 1 + elif i == 0 and prefix.endswith(sep): + del comps[i] + else: + i += 1 + else: + i += 1 + # If the path is now empty, substitute '.' + if not prefix and not comps: + comps.append(curdir) + return prefix + sep.join(comps) + +def _abspath_fallback(path): + """Return the absolute version of a path as a fallback function in case + `nt._getfullpathname` is not available or raises OSError. See bpo-31047 for + more. + + """ + + path = os.fspath(path) + if not isabs(path): + if isinstance(path, bytes): + cwd = os.getcwdb() + else: + cwd = os.getcwd() + path = join(cwd, path) + return normpath(path) + +# Return an absolute path. +try: + from nt import _getfullpathname + +except ImportError: # not running on Windows - mock up something sensible + abspath = _abspath_fallback + +else: # use native Windows method on Windows + def abspath(path): + """Return the absolute version of a path.""" + try: + return _getfullpathname(path) + except OSError: + return _abspath_fallback(path) + +# realpath is a no-op on systems without islink support +realpath = abspath +# Win9x family and earlier have no Unicode filename support. +supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and + sys.getwindowsversion()[3] >= 2) + +def relpath(path, start=None): + """Return a relative version of a path""" + path = os.fspath(path) + if isinstance(path, bytes): + sep = b'\\' + curdir = b'.' + pardir = b'..' + else: + sep = '\\' + curdir = '.' + pardir = '..' + + if start is None: + start = curdir + + if not path: + raise ValueError("no path specified") + + start = os.fspath(start) + try: + start_abs = abspath(normpath(start)) + path_abs = abspath(normpath(path)) + start_drive, start_rest = splitdrive(start_abs) + path_drive, path_rest = splitdrive(path_abs) + if normcase(start_drive) != normcase(path_drive): + raise ValueError("path is on mount %r, start on mount %r" % ( + path_drive, start_drive)) + + start_list = [x for x in start_rest.split(sep) if x] + path_list = [x for x in path_rest.split(sep) if x] + # Work out how much of the filepath is shared by start and path. + i = 0 + for e1, e2 in zip(start_list, path_list): + if normcase(e1) != normcase(e2): + break + i += 1 + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return curdir + return join(*rel_list) + except (TypeError, ValueError, AttributeError, BytesWarning, DeprecationWarning): + genericpath._check_arg_types('relpath', path, start) + raise + + +# Return the longest common sub-path of the sequence of paths given as input. +# The function is case-insensitive and 'separator-insensitive', i.e. if the +# only difference between two paths is the use of '\' versus '/' as separator, +# they are deemed to be equal. +# +# However, the returned path will have the standard '\' separator (even if the +# given paths had the alternative '/' separator) and will have the case of the +# first path given in the sequence. Additionally, any trailing separator is +# stripped from the returned path. + +def commonpath(paths): + """Given a sequence of path names, returns the longest common sub-path.""" + + if not paths: + raise ValueError('commonpath() arg is an empty sequence') + + paths = tuple(map(os.fspath, paths)) + if isinstance(paths[0], bytes): + sep = b'\\' + altsep = b'/' + curdir = b'.' + else: + sep = '\\' + altsep = '/' + curdir = '.' + + try: + drivesplits = [splitdrive(p.replace(altsep, sep).lower()) for p in paths] + split_paths = [p.split(sep) for d, p in drivesplits] + + try: + isabs, = set(p[:1] == sep for d, p in drivesplits) + except ValueError: + raise ValueError("Can't mix absolute and relative paths") from None + + # Check that all drive letters or UNC paths match. The check is made only + # now otherwise type errors for mixing strings and bytes would not be + # caught. + if len(set(d for d, p in drivesplits)) != 1: + raise ValueError("Paths don't have the same drive") + + drive, path = splitdrive(paths[0].replace(altsep, sep)) + common = path.split(sep) + common = [c for c in common if c and c != curdir] + + split_paths = [[c for c in s if c and c != curdir] for s in split_paths] + s1 = min(split_paths) + s2 = max(split_paths) + for i, c in enumerate(s1): + if c != s2[i]: + common = common[:i] + break + else: + common = common[:len(s1)] + + prefix = drive + sep if isabs else drive + return prefix + sep.join(common) + except (TypeError, AttributeError): + genericpath._check_arg_types('commonpath', *paths) + raise + + +# determine if two files are in fact the same file +try: + # GetFinalPathNameByHandle is available starting with Windows 6.0. + # Windows XP and non-Windows OS'es will mock _getfinalpathname. + if sys.getwindowsversion()[:2] >= (6, 0): + from nt import _getfinalpathname + else: + raise ImportError +except (AttributeError, ImportError): + # On Windows XP and earlier, two files are the same if their absolute + # pathnames are the same. + # Non-Windows operating systems fake this method with an XP + # approximation. + def _getfinalpathname(f): + return normcase(abspath(f)) + + +try: + # The genericpath.isdir implementation uses os.stat and checks the mode + # attribute to tell whether or not the path is a directory. + # This is overkill on Windows - just pass the path to GetFileAttributes + # and check the attribute from there. + from nt import _isdir as isdir +except ImportError: + # Use genericpath.isdir as imported above. + pass diff --git a/winvenv/Lib/operator.py b/winvenv/Lib/operator.py new file mode 100644 index 0000000..0e2e53e --- /dev/null +++ b/winvenv/Lib/operator.py @@ -0,0 +1,464 @@ +""" +Operator Interface + +This module exports a set of functions corresponding to the intrinsic +operators of Python. For example, operator.add(x, y) is equivalent +to the expression x+y. The function names are those used for special +methods; variants without leading and trailing '__' are also provided +for convenience. + +This is the pure Python implementation of the module. +""" + +__all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf', + 'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand', + 'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul', + 'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift', + 'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le', + 'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod', + 'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', + 'setitem', 'sub', 'truediv', 'truth', 'xor'] + +from builtins import abs as _abs + + +# Comparison Operations *******************************************************# + +def lt(a, b): + "Same as a < b." + return a < b + +def le(a, b): + "Same as a <= b." + return a <= b + +def eq(a, b): + "Same as a == b." + return a == b + +def ne(a, b): + "Same as a != b." + return a != b + +def ge(a, b): + "Same as a >= b." + return a >= b + +def gt(a, b): + "Same as a > b." + return a > b + +# Logical Operations **********************************************************# + +def not_(a): + "Same as not a." + return not a + +def truth(a): + "Return True if a is true, False otherwise." + return True if a else False + +def is_(a, b): + "Same as a is b." + return a is b + +def is_not(a, b): + "Same as a is not b." + return a is not b + +# Mathematical/Bitwise Operations *********************************************# + +def abs(a): + "Same as abs(a)." + return _abs(a) + +def add(a, b): + "Same as a + b." + return a + b + +def and_(a, b): + "Same as a & b." + return a & b + +def floordiv(a, b): + "Same as a // b." + return a // b + +def index(a): + "Same as a.__index__()." + return a.__index__() + +def inv(a): + "Same as ~a." + return ~a +invert = inv + +def lshift(a, b): + "Same as a << b." + return a << b + +def mod(a, b): + "Same as a % b." + return a % b + +def mul(a, b): + "Same as a * b." + return a * b + +def matmul(a, b): + "Same as a @ b." + return a @ b + +def neg(a): + "Same as -a." + return -a + +def or_(a, b): + "Same as a | b." + return a | b + +def pos(a): + "Same as +a." + return +a + +def pow(a, b): + "Same as a ** b." + return a ** b + +def rshift(a, b): + "Same as a >> b." + return a >> b + +def sub(a, b): + "Same as a - b." + return a - b + +def truediv(a, b): + "Same as a / b." + return a / b + +def xor(a, b): + "Same as a ^ b." + return a ^ b + +# Sequence Operations *********************************************************# + +def concat(a, b): + "Same as a + b, for a and b sequences." + if not hasattr(a, '__getitem__'): + msg = "'%s' object can't be concatenated" % type(a).__name__ + raise TypeError(msg) + return a + b + +def contains(a, b): + "Same as b in a (note reversed operands)." + return b in a + +def countOf(a, b): + "Return the number of times b occurs in a." + count = 0 + for i in a: + if i == b: + count += 1 + return count + +def delitem(a, b): + "Same as del a[b]." + del a[b] + +def getitem(a, b): + "Same as a[b]." + return a[b] + +def indexOf(a, b): + "Return the first index of b in a." + for i, j in enumerate(a): + if j == b: + return i + else: + raise ValueError('sequence.index(x): x not in sequence') + +def setitem(a, b, c): + "Same as a[b] = c." + a[b] = c + +def length_hint(obj, default=0): + """ + Return an estimate of the number of items in obj. + This is useful for presizing containers when building from an iterable. + + If the object supports len(), the result will be exact. Otherwise, it may + over- or under-estimate by an arbitrary amount. The result will be an + integer >= 0. + """ + if not isinstance(default, int): + msg = ("'%s' object cannot be interpreted as an integer" % + type(default).__name__) + raise TypeError(msg) + + try: + return len(obj) + except TypeError: + pass + + try: + hint = type(obj).__length_hint__ + except AttributeError: + return default + + try: + val = hint(obj) + except TypeError: + return default + if val is NotImplemented: + return default + if not isinstance(val, int): + msg = ('__length_hint__ must be integer, not %s' % + type(val).__name__) + raise TypeError(msg) + if val < 0: + msg = '__length_hint__() should return >= 0' + raise ValueError(msg) + return val + +# Generalized Lookup Objects **************************************************# + +class attrgetter: + """ + Return a callable object that fetches the given attribute(s) from its operand. + After f = attrgetter('name'), the call f(r) returns r.name. + After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date). + After h = attrgetter('name.first', 'name.last'), the call h(r) returns + (r.name.first, r.name.last). + """ + __slots__ = ('_attrs', '_call') + + def __init__(self, attr, *attrs): + if not attrs: + if not isinstance(attr, str): + raise TypeError('attribute name must be a string') + self._attrs = (attr,) + names = attr.split('.') + def func(obj): + for name in names: + obj = getattr(obj, name) + return obj + self._call = func + else: + self._attrs = (attr,) + attrs + getters = tuple(map(attrgetter, self._attrs)) + def func(obj): + return tuple(getter(obj) for getter in getters) + self._call = func + + def __call__(self, obj): + return self._call(obj) + + def __repr__(self): + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__qualname__, + ', '.join(map(repr, self._attrs))) + + def __reduce__(self): + return self.__class__, self._attrs + +class itemgetter: + """ + Return a callable object that fetches the given item(s) from its operand. + After f = itemgetter(2), the call f(r) returns r[2]. + After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3]) + """ + __slots__ = ('_items', '_call') + + def __init__(self, item, *items): + if not items: + self._items = (item,) + def func(obj): + return obj[item] + self._call = func + else: + self._items = items = (item,) + items + def func(obj): + return tuple(obj[i] for i in items) + self._call = func + + def __call__(self, obj): + return self._call(obj) + + def __repr__(self): + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__name__, + ', '.join(map(repr, self._items))) + + def __reduce__(self): + return self.__class__, self._items + +class methodcaller: + """ + Return a callable object that calls the given method on its operand. + After f = methodcaller('name'), the call f(r) returns r.name(). + After g = methodcaller('name', 'date', foo=1), the call g(r) returns + r.name('date', foo=1). + """ + __slots__ = ('_name', '_args', '_kwargs') + + def __init__(*args, **kwargs): + if len(args) < 2: + msg = "methodcaller needs at least one argument, the method name" + raise TypeError(msg) + self = args[0] + self._name = args[1] + if not isinstance(self._name, str): + raise TypeError('method name must be a string') + self._args = args[2:] + self._kwargs = kwargs + + def __call__(self, obj): + return getattr(obj, self._name)(*self._args, **self._kwargs) + + def __repr__(self): + args = [repr(self._name)] + args.extend(map(repr, self._args)) + args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items()) + return '%s.%s(%s)' % (self.__class__.__module__, + self.__class__.__name__, + ', '.join(args)) + + def __reduce__(self): + if not self._kwargs: + return self.__class__, (self._name,) + self._args + else: + from functools import partial + return partial(self.__class__, self._name, **self._kwargs), self._args + + +# In-place Operations *********************************************************# + +def iadd(a, b): + "Same as a += b." + a += b + return a + +def iand(a, b): + "Same as a &= b." + a &= b + return a + +def iconcat(a, b): + "Same as a += b, for a and b sequences." + if not hasattr(a, '__getitem__'): + msg = "'%s' object can't be concatenated" % type(a).__name__ + raise TypeError(msg) + a += b + return a + +def ifloordiv(a, b): + "Same as a //= b." + a //= b + return a + +def ilshift(a, b): + "Same as a <<= b." + a <<= b + return a + +def imod(a, b): + "Same as a %= b." + a %= b + return a + +def imul(a, b): + "Same as a *= b." + a *= b + return a + +def imatmul(a, b): + "Same as a @= b." + a @= b + return a + +def ior(a, b): + "Same as a |= b." + a |= b + return a + +def ipow(a, b): + "Same as a **= b." + a **=b + return a + +def irshift(a, b): + "Same as a >>= b." + a >>= b + return a + +def isub(a, b): + "Same as a -= b." + a -= b + return a + +def itruediv(a, b): + "Same as a /= b." + a /= b + return a + +def ixor(a, b): + "Same as a ^= b." + a ^= b + return a + + +try: + from _operator import * +except ImportError: + pass +else: + from _operator import __doc__ + +# All of these "__func__ = func" assignments have to happen after importing +# from _operator to make sure they're set to the right function +__lt__ = lt +__le__ = le +__eq__ = eq +__ne__ = ne +__ge__ = ge +__gt__ = gt +__not__ = not_ +__abs__ = abs +__add__ = add +__and__ = and_ +__floordiv__ = floordiv +__index__ = index +__inv__ = inv +__invert__ = invert +__lshift__ = lshift +__mod__ = mod +__mul__ = mul +__matmul__ = matmul +__neg__ = neg +__or__ = or_ +__pos__ = pos +__pow__ = pow +__rshift__ = rshift +__sub__ = sub +__truediv__ = truediv +__xor__ = xor +__concat__ = concat +__contains__ = contains +__delitem__ = delitem +__getitem__ = getitem +__setitem__ = setitem +__iadd__ = iadd +__iand__ = iand +__iconcat__ = iconcat +__ifloordiv__ = ifloordiv +__ilshift__ = ilshift +__imod__ = imod +__imul__ = imul +__imatmul__ = imatmul +__ior__ = ior +__ipow__ = ipow +__irshift__ = irshift +__isub__ = isub +__itruediv__ = itruediv +__ixor__ = ixor diff --git a/winvenv/Lib/orig-prefix.txt b/winvenv/Lib/orig-prefix.txt new file mode 100644 index 0000000..565d5f3 --- /dev/null +++ b/winvenv/Lib/orig-prefix.txt @@ -0,0 +1 @@ +c:\users\lestebanez\appdata\local\programs\python\python37 \ No newline at end of file diff --git a/winvenv/Lib/os.py b/winvenv/Lib/os.py new file mode 100644 index 0000000..499e628 --- /dev/null +++ b/winvenv/Lib/os.py @@ -0,0 +1,1078 @@ +r"""OS routines for NT or Posix depending on what system we're on. + +This exports: + - all functions from posix or nt, e.g. unlink, stat, etc. + - os.path is either posixpath or ntpath + - os.name is either 'posix' or 'nt' + - os.curdir is a string representing the current directory (always '.') + - os.pardir is a string representing the parent directory (always '..') + - os.sep is the (or a most common) pathname separator ('/' or '\\') + - os.extsep is the extension separator (always '.') + - os.altsep is the alternate pathname separator (None or '/') + - os.pathsep is the component separator used in $PATH etc + - os.linesep is the line separator in text files ('\r' or '\n' or '\r\n') + - os.defpath is the default search path for executables + - os.devnull is the file path of the null device ('/dev/null', etc.) + +Programs that import and use 'os' stand a better chance of being +portable between different platforms. Of course, they must then +only use functions that are defined by all platforms (e.g., unlink +and opendir), and leave all pathname manipulation to os.path +(e.g., split and join). +""" + +#' +import abc +import sys +import stat as st + +_names = sys.builtin_module_names + +# Note: more names are added to __all__ later. +__all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep", + "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR", + "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen", + "popen", "extsep"] + +def _exists(name): + return name in globals() + +def _get_exports_list(module): + try: + return list(module.__all__) + except AttributeError: + return [n for n in dir(module) if n[0] != '_'] + +# Any new dependencies of the os module and/or changes in path separator +# requires updating importlib as well. +if 'posix' in _names: + name = 'posix' + linesep = '\n' + from posix import * + try: + from posix import _exit + __all__.append('_exit') + except ImportError: + pass + import posixpath as path + + try: + from posix import _have_functions + except ImportError: + pass + + import posix + __all__.extend(_get_exports_list(posix)) + del posix + +elif 'nt' in _names: + name = 'nt' + linesep = '\r\n' + from nt import * + try: + from nt import _exit + __all__.append('_exit') + except ImportError: + pass + import ntpath as path + + import nt + __all__.extend(_get_exports_list(nt)) + del nt + + try: + from nt import _have_functions + except ImportError: + pass + +else: + raise ImportError('no os specific module found') + +sys.modules['os.path'] = path +from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, + devnull) + +del _names + + +if _exists("_have_functions"): + _globals = globals() + def _add(str, fn): + if (fn in _globals) and (str in _have_functions): + _set.add(_globals[fn]) + + _set = set() + _add("HAVE_FACCESSAT", "access") + _add("HAVE_FCHMODAT", "chmod") + _add("HAVE_FCHOWNAT", "chown") + _add("HAVE_FSTATAT", "stat") + _add("HAVE_FUTIMESAT", "utime") + _add("HAVE_LINKAT", "link") + _add("HAVE_MKDIRAT", "mkdir") + _add("HAVE_MKFIFOAT", "mkfifo") + _add("HAVE_MKNODAT", "mknod") + _add("HAVE_OPENAT", "open") + _add("HAVE_READLINKAT", "readlink") + _add("HAVE_RENAMEAT", "rename") + _add("HAVE_SYMLINKAT", "symlink") + _add("HAVE_UNLINKAT", "unlink") + _add("HAVE_UNLINKAT", "rmdir") + _add("HAVE_UTIMENSAT", "utime") + supports_dir_fd = _set + + _set = set() + _add("HAVE_FACCESSAT", "access") + supports_effective_ids = _set + + _set = set() + _add("HAVE_FCHDIR", "chdir") + _add("HAVE_FCHMOD", "chmod") + _add("HAVE_FCHOWN", "chown") + _add("HAVE_FDOPENDIR", "listdir") + _add("HAVE_FDOPENDIR", "scandir") + _add("HAVE_FEXECVE", "execve") + _set.add(stat) # fstat always works + _add("HAVE_FTRUNCATE", "truncate") + _add("HAVE_FUTIMENS", "utime") + _add("HAVE_FUTIMES", "utime") + _add("HAVE_FPATHCONF", "pathconf") + if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3 + _add("HAVE_FSTATVFS", "statvfs") + supports_fd = _set + + _set = set() + _add("HAVE_FACCESSAT", "access") + # Some platforms don't support lchmod(). Often the function exists + # anyway, as a stub that always returns ENOSUP or perhaps EOPNOTSUPP. + # (No, I don't know why that's a good design.) ./configure will detect + # this and reject it--so HAVE_LCHMOD still won't be defined on such + # platforms. This is Very Helpful. + # + # However, sometimes platforms without a working lchmod() *do* have + # fchmodat(). (Examples: Linux kernel 3.2 with glibc 2.15, + # OpenIndiana 3.x.) And fchmodat() has a flag that theoretically makes + # it behave like lchmod(). So in theory it would be a suitable + # replacement for lchmod(). But when lchmod() doesn't work, fchmodat()'s + # flag doesn't work *either*. Sadly ./configure isn't sophisticated + # enough to detect this condition--it only determines whether or not + # fchmodat() minimally works. + # + # Therefore we simply ignore fchmodat() when deciding whether or not + # os.chmod supports follow_symlinks. Just checking lchmod() is + # sufficient. After all--if you have a working fchmodat(), your + # lchmod() almost certainly works too. + # + # _add("HAVE_FCHMODAT", "chmod") + _add("HAVE_FCHOWNAT", "chown") + _add("HAVE_FSTATAT", "stat") + _add("HAVE_LCHFLAGS", "chflags") + _add("HAVE_LCHMOD", "chmod") + if _exists("lchown"): # mac os x10.3 + _add("HAVE_LCHOWN", "chown") + _add("HAVE_LINKAT", "link") + _add("HAVE_LUTIMES", "utime") + _add("HAVE_LSTAT", "stat") + _add("HAVE_FSTATAT", "stat") + _add("HAVE_UTIMENSAT", "utime") + _add("MS_WINDOWS", "stat") + supports_follow_symlinks = _set + + del _set + del _have_functions + del _globals + del _add + + +# Python uses fixed values for the SEEK_ constants; they are mapped +# to native constants if necessary in posixmodule.c +# Other possible SEEK values are directly imported from posixmodule.c +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 + +# Super directory utilities. +# (Inspired by Eric Raymond; the doc strings are mostly his) + +def makedirs(name, mode=0o777, exist_ok=False): + """makedirs(name [, mode=0o777][, exist_ok=False]) + + Super-mkdir; create a leaf directory and all intermediate ones. Works like + mkdir, except that any intermediate path segment (not just the rightmost) + will be created if it does not exist. If the target directory already + exists, raise an OSError if exist_ok is False. Otherwise no exception is + raised. This is recursive. + + """ + head, tail = path.split(name) + if not tail: + head, tail = path.split(head) + if head and tail and not path.exists(head): + try: + makedirs(head, exist_ok=exist_ok) + except FileExistsError: + # Defeats race condition when another thread created the path + pass + cdir = curdir + if isinstance(tail, bytes): + cdir = bytes(curdir, 'ASCII') + if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists + return + try: + mkdir(name, mode) + except OSError: + # Cannot rely on checking for EEXIST, since the operating system + # could give priority to other errors like EACCES or EROFS + if not exist_ok or not path.isdir(name): + raise + +def removedirs(name): + """removedirs(name) + + Super-rmdir; remove a leaf directory and all empty intermediate + ones. Works like rmdir except that, if the leaf directory is + successfully removed, directories corresponding to rightmost path + segments will be pruned away until either the whole path is + consumed or an error occurs. Errors during this latter phase are + ignored -- they generally mean that a directory was not empty. + + """ + rmdir(name) + head, tail = path.split(name) + if not tail: + head, tail = path.split(head) + while head and tail: + try: + rmdir(head) + except OSError: + break + head, tail = path.split(head) + +def renames(old, new): + """renames(old, new) + + Super-rename; create directories as necessary and delete any left + empty. Works like rename, except creation of any intermediate + directories needed to make the new pathname good is attempted + first. After the rename, directories corresponding to rightmost + path segments of the old name will be pruned until either the + whole path is consumed or a nonempty directory is found. + + Note: this function can fail with the new directory structure made + if you lack permissions needed to unlink the leaf directory or + file. + + """ + head, tail = path.split(new) + if head and tail and not path.exists(head): + makedirs(head) + rename(old, new) + head, tail = path.split(old) + if head and tail: + try: + removedirs(head) + except OSError: + pass + +__all__.extend(["makedirs", "removedirs", "renames"]) + +def walk(top, topdown=True, onerror=None, followlinks=False): + """Directory tree generator. + + For each directory in the directory tree rooted at top (including top + itself, but excluding '.' and '..'), yields a 3-tuple + + dirpath, dirnames, filenames + + dirpath is a string, the path to the directory. dirnames is a list of + the names of the subdirectories in dirpath (excluding '.' and '..'). + filenames is a list of the names of the non-directory files in dirpath. + Note that the names in the lists are just names, with no path components. + To get a full path (which begins with top) to a file or directory in + dirpath, do os.path.join(dirpath, name). + + If optional arg 'topdown' is true or not specified, the triple for a + directory is generated before the triples for any of its subdirectories + (directories are generated top down). If topdown is false, the triple + for a directory is generated after the triples for all of its + subdirectories (directories are generated bottom up). + + When topdown is true, the caller can modify the dirnames list in-place + (e.g., via del or slice assignment), and walk will only recurse into the + subdirectories whose names remain in dirnames; this can be used to prune the + search, or to impose a specific order of visiting. Modifying dirnames when + topdown is false is ineffective, since the directories in dirnames have + already been generated by the time dirnames itself is generated. No matter + the value of topdown, the list of subdirectories is retrieved before the + tuples for the directory and its subdirectories are generated. + + By default errors from the os.scandir() call are ignored. If + optional arg 'onerror' is specified, it should be a function; it + will be called with one argument, an OSError instance. It can + report the error to continue with the walk, or raise the exception + to abort the walk. Note that the filename is available as the + filename attribute of the exception object. + + By default, os.walk does not follow symbolic links to subdirectories on + systems that support them. In order to get this functionality, set the + optional argument 'followlinks' to true. + + Caution: if you pass a relative pathname for top, don't change the + current working directory between resumptions of walk. walk never + changes the current directory, and assumes that the client doesn't + either. + + Example: + + import os + from os.path import join, getsize + for root, dirs, files in os.walk('python/Lib/email'): + print(root, "consumes", end="") + print(sum([getsize(join(root, name)) for name in files]), end="") + print("bytes in", len(files), "non-directory files") + if 'CVS' in dirs: + dirs.remove('CVS') # don't visit CVS directories + + """ + top = fspath(top) + dirs = [] + nondirs = [] + walk_dirs = [] + + # We may not have read permission for top, in which case we can't + # get a list of the files the directory contains. os.walk + # always suppressed the exception then, rather than blow up for a + # minor reason when (say) a thousand readable directories are still + # left to visit. That logic is copied here. + try: + # Note that scandir is global in this module due + # to earlier import-*. + scandir_it = scandir(top) + except OSError as error: + if onerror is not None: + onerror(error) + return + + with scandir_it: + while True: + try: + try: + entry = next(scandir_it) + except StopIteration: + break + except OSError as error: + if onerror is not None: + onerror(error) + return + + try: + is_dir = entry.is_dir() + except OSError: + # If is_dir() raises an OSError, consider that the entry is not + # a directory, same behaviour than os.path.isdir(). + is_dir = False + + if is_dir: + dirs.append(entry.name) + else: + nondirs.append(entry.name) + + if not topdown and is_dir: + # Bottom-up: recurse into sub-directory, but exclude symlinks to + # directories if followlinks is False + if followlinks: + walk_into = True + else: + try: + is_symlink = entry.is_symlink() + except OSError: + # If is_symlink() raises an OSError, consider that the + # entry is not a symbolic link, same behaviour than + # os.path.islink(). + is_symlink = False + walk_into = not is_symlink + + if walk_into: + walk_dirs.append(entry.path) + + # Yield before recursion if going top down + if topdown: + yield top, dirs, nondirs + + # Recurse into sub-directories + islink, join = path.islink, path.join + for dirname in dirs: + new_path = join(top, dirname) + # Issue #23605: os.path.islink() is used instead of caching + # entry.is_symlink() result during the loop on os.scandir() because + # the caller can replace the directory entry during the "yield" + # above. + if followlinks or not islink(new_path): + yield from walk(new_path, topdown, onerror, followlinks) + else: + # Recurse into sub-directories + for new_path in walk_dirs: + yield from walk(new_path, topdown, onerror, followlinks) + # Yield after recursion if going bottom up + yield top, dirs, nondirs + +__all__.append("walk") + +if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd: + + def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None): + """Directory tree generator. + + This behaves exactly like walk(), except that it yields a 4-tuple + + dirpath, dirnames, filenames, dirfd + + `dirpath`, `dirnames` and `filenames` are identical to walk() output, + and `dirfd` is a file descriptor referring to the directory `dirpath`. + + The advantage of fwalk() over walk() is that it's safe against symlink + races (when follow_symlinks is False). + + If dir_fd is not None, it should be a file descriptor open to a directory, + and top should be relative; top will then be relative to that directory. + (dir_fd is always supported for fwalk.) + + Caution: + Since fwalk() yields file descriptors, those are only valid until the + next iteration step, so you should dup() them if you want to keep them + for a longer period. + + Example: + + import os + for root, dirs, files, rootfd in os.fwalk('python/Lib/email'): + print(root, "consumes", end="") + print(sum([os.stat(name, dir_fd=rootfd).st_size for name in files]), + end="") + print("bytes in", len(files), "non-directory files") + if 'CVS' in dirs: + dirs.remove('CVS') # don't visit CVS directories + """ + if not isinstance(top, int) or not hasattr(top, '__index__'): + top = fspath(top) + # Note: To guard against symlink races, we use the standard + # lstat()/open()/fstat() trick. + if not follow_symlinks: + orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd) + topfd = open(top, O_RDONLY, dir_fd=dir_fd) + try: + if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and + path.samestat(orig_st, stat(topfd)))): + yield from _fwalk(topfd, top, isinstance(top, bytes), + topdown, onerror, follow_symlinks) + finally: + close(topfd) + + def _fwalk(topfd, toppath, isbytes, topdown, onerror, follow_symlinks): + # Note: This uses O(depth of the directory tree) file descriptors: if + # necessary, it can be adapted to only require O(1) FDs, see issue + # #13734. + + scandir_it = scandir(topfd) + dirs = [] + nondirs = [] + entries = None if topdown or follow_symlinks else [] + for entry in scandir_it: + name = entry.name + if isbytes: + name = fsencode(name) + try: + if entry.is_dir(): + dirs.append(name) + if entries is not None: + entries.append(entry) + else: + nondirs.append(name) + except OSError: + try: + # Add dangling symlinks, ignore disappeared files + if entry.is_symlink(): + nondirs.append(name) + except OSError: + pass + + if topdown: + yield toppath, dirs, nondirs, topfd + + for name in dirs if entries is None else zip(dirs, entries): + try: + if not follow_symlinks: + if topdown: + orig_st = stat(name, dir_fd=topfd, follow_symlinks=False) + else: + assert entries is not None + name, entry = name + orig_st = entry.stat(follow_symlinks=False) + dirfd = open(name, O_RDONLY, dir_fd=topfd) + except OSError as err: + if onerror is not None: + onerror(err) + continue + try: + if follow_symlinks or path.samestat(orig_st, stat(dirfd)): + dirpath = path.join(toppath, name) + yield from _fwalk(dirfd, dirpath, isbytes, + topdown, onerror, follow_symlinks) + finally: + close(dirfd) + + if not topdown: + yield toppath, dirs, nondirs, topfd + + __all__.append("fwalk") + +# Make sure os.environ exists, at least +try: + environ +except NameError: + environ = {} + +def execl(file, *args): + """execl(file, *args) + + Execute the executable file with argument list args, replacing the + current process. """ + execv(file, args) + +def execle(file, *args): + """execle(file, *args, env) + + Execute the executable file with argument list args and + environment env, replacing the current process. """ + env = args[-1] + execve(file, args[:-1], env) + +def execlp(file, *args): + """execlp(file, *args) + + Execute the executable file (which is searched for along $PATH) + with argument list args, replacing the current process. """ + execvp(file, args) + +def execlpe(file, *args): + """execlpe(file, *args, env) + + Execute the executable file (which is searched for along $PATH) + with argument list args and environment env, replacing the current + process. """ + env = args[-1] + execvpe(file, args[:-1], env) + +def execvp(file, args): + """execvp(file, args) + + Execute the executable file (which is searched for along $PATH) + with argument list args, replacing the current process. + args may be a list or tuple of strings. """ + _execvpe(file, args) + +def execvpe(file, args, env): + """execvpe(file, args, env) + + Execute the executable file (which is searched for along $PATH) + with argument list args and environment env , replacing the + current process. + args may be a list or tuple of strings. """ + _execvpe(file, args, env) + +__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) + +def _execvpe(file, args, env=None): + if env is not None: + exec_func = execve + argrest = (args, env) + else: + exec_func = execv + argrest = (args,) + env = environ + + if path.dirname(file): + exec_func(file, *argrest) + return + saved_exc = None + path_list = get_exec_path(env) + if name != 'nt': + file = fsencode(file) + path_list = map(fsencode, path_list) + for dir in path_list: + fullname = path.join(dir, file) + try: + exec_func(fullname, *argrest) + except (FileNotFoundError, NotADirectoryError) as e: + last_exc = e + except OSError as e: + last_exc = e + if saved_exc is None: + saved_exc = e + if saved_exc is not None: + raise saved_exc + raise last_exc + + +def get_exec_path(env=None): + """Returns the sequence of directories that will be searched for the + named executable (similar to a shell) when launching a process. + + *env* must be an environment variable dict or None. If *env* is None, + os.environ will be used. + """ + # Use a local import instead of a global import to limit the number of + # modules loaded at startup: the os module is always loaded at startup by + # Python. It may also avoid a bootstrap issue. + import warnings + + if env is None: + env = environ + + # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a + # BytesWarning when using python -b or python -bb: ignore the warning + with warnings.catch_warnings(): + warnings.simplefilter("ignore", BytesWarning) + + try: + path_list = env.get('PATH') + except TypeError: + path_list = None + + if supports_bytes_environ: + try: + path_listb = env[b'PATH'] + except (KeyError, TypeError): + pass + else: + if path_list is not None: + raise ValueError( + "env cannot contain 'PATH' and b'PATH' keys") + path_list = path_listb + + if path_list is not None and isinstance(path_list, bytes): + path_list = fsdecode(path_list) + + if path_list is None: + path_list = defpath + return path_list.split(pathsep) + + +# Change environ to automatically call putenv(), unsetenv if they exist. +from _collections_abc import MutableMapping + +class _Environ(MutableMapping): + def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv): + self.encodekey = encodekey + self.decodekey = decodekey + self.encodevalue = encodevalue + self.decodevalue = decodevalue + self.putenv = putenv + self.unsetenv = unsetenv + self._data = data + + def __getitem__(self, key): + try: + value = self._data[self.encodekey(key)] + except KeyError: + # raise KeyError with the original key value + raise KeyError(key) from None + return self.decodevalue(value) + + def __setitem__(self, key, value): + key = self.encodekey(key) + value = self.encodevalue(value) + self.putenv(key, value) + self._data[key] = value + + def __delitem__(self, key): + encodedkey = self.encodekey(key) + self.unsetenv(encodedkey) + try: + del self._data[encodedkey] + except KeyError: + # raise KeyError with the original key value + raise KeyError(key) from None + + def __iter__(self): + # list() from dict object is an atomic operation + keys = list(self._data) + for key in keys: + yield self.decodekey(key) + + def __len__(self): + return len(self._data) + + def __repr__(self): + return 'environ({{{}}})'.format(', '.join( + ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value)) + for key, value in self._data.items()))) + + def copy(self): + return dict(self) + + def setdefault(self, key, value): + if key not in self: + self[key] = value + return self[key] + +try: + _putenv = putenv +except NameError: + _putenv = lambda key, value: None +else: + if "putenv" not in __all__: + __all__.append("putenv") + +try: + _unsetenv = unsetenv +except NameError: + _unsetenv = lambda key: _putenv(key, "") +else: + if "unsetenv" not in __all__: + __all__.append("unsetenv") + +def _createenviron(): + if name == 'nt': + # Where Env Var Names Must Be UPPERCASE + def check_str(value): + if not isinstance(value, str): + raise TypeError("str expected, not %s" % type(value).__name__) + return value + encode = check_str + decode = str + def encodekey(key): + return encode(key).upper() + data = {} + for key, value in environ.items(): + data[encodekey(key)] = value + else: + # Where Env Var Names Can Be Mixed Case + encoding = sys.getfilesystemencoding() + def encode(value): + if not isinstance(value, str): + raise TypeError("str expected, not %s" % type(value).__name__) + return value.encode(encoding, 'surrogateescape') + def decode(value): + return value.decode(encoding, 'surrogateescape') + encodekey = encode + data = environ + return _Environ(data, + encodekey, decode, + encode, decode, + _putenv, _unsetenv) + +# unicode environ +environ = _createenviron() +del _createenviron + + +def getenv(key, default=None): + """Get an environment variable, return None if it doesn't exist. + The optional second argument can specify an alternate default. + key, default and the result are str.""" + return environ.get(key, default) + +supports_bytes_environ = (name != 'nt') +__all__.extend(("getenv", "supports_bytes_environ")) + +if supports_bytes_environ: + def _check_bytes(value): + if not isinstance(value, bytes): + raise TypeError("bytes expected, not %s" % type(value).__name__) + return value + + # bytes environ + environb = _Environ(environ._data, + _check_bytes, bytes, + _check_bytes, bytes, + _putenv, _unsetenv) + del _check_bytes + + def getenvb(key, default=None): + """Get an environment variable, return None if it doesn't exist. + The optional second argument can specify an alternate default. + key, default and the result are bytes.""" + return environb.get(key, default) + + __all__.extend(("environb", "getenvb")) + +def _fscodec(): + encoding = sys.getfilesystemencoding() + errors = sys.getfilesystemencodeerrors() + + def fsencode(filename): + """Encode filename (an os.PathLike, bytes, or str) to the filesystem + encoding with 'surrogateescape' error handler, return bytes unchanged. + On Windows, use 'strict' error handler if the file system encoding is + 'mbcs' (which is the default encoding). + """ + filename = fspath(filename) # Does type-checking of `filename`. + if isinstance(filename, str): + return filename.encode(encoding, errors) + else: + return filename + + def fsdecode(filename): + """Decode filename (an os.PathLike, bytes, or str) from the filesystem + encoding with 'surrogateescape' error handler, return str unchanged. On + Windows, use 'strict' error handler if the file system encoding is + 'mbcs' (which is the default encoding). + """ + filename = fspath(filename) # Does type-checking of `filename`. + if isinstance(filename, bytes): + return filename.decode(encoding, errors) + else: + return filename + + return fsencode, fsdecode + +fsencode, fsdecode = _fscodec() +del _fscodec + +# Supply spawn*() (probably only for Unix) +if _exists("fork") and not _exists("spawnv") and _exists("execv"): + + P_WAIT = 0 + P_NOWAIT = P_NOWAITO = 1 + + __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"]) + + # XXX Should we support P_DETACH? I suppose it could fork()**2 + # and close the std I/O streams. Also, P_OVERLAY is the same + # as execv*()? + + def _spawnvef(mode, file, args, env, func): + # Internal helper; func is the exec*() function to use + if not isinstance(args, (tuple, list)): + raise TypeError('argv must be a tuple or a list') + if not args or not args[0]: + raise ValueError('argv first element cannot be empty') + pid = fork() + if not pid: + # Child + try: + if env is None: + func(file, args) + else: + func(file, args, env) + except: + _exit(127) + else: + # Parent + if mode == P_NOWAIT: + return pid # Caller is responsible for waiting! + while 1: + wpid, sts = waitpid(pid, 0) + if WIFSTOPPED(sts): + continue + elif WIFSIGNALED(sts): + return -WTERMSIG(sts) + elif WIFEXITED(sts): + return WEXITSTATUS(sts) + else: + raise OSError("Not stopped, signaled or exited???") + + def spawnv(mode, file, args): + """spawnv(mode, file, args) -> integer + +Execute file with arguments from args in a subprocess. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, None, execv) + + def spawnve(mode, file, args, env): + """spawnve(mode, file, args, env) -> integer + +Execute file with arguments from args in a subprocess with the +specified environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, env, execve) + + # Note: spawnvp[e] isn't currently supported on Windows + + def spawnvp(mode, file, args): + """spawnvp(mode, file, args) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, None, execvp) + + def spawnvpe(mode, file, args, env): + """spawnvpe(mode, file, args, env) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess with the supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return _spawnvef(mode, file, args, env, execvpe) + + + __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"]) + + +if _exists("spawnv"): + # These aren't supplied by the basic Windows code + # but can be easily implemented in Python + + def spawnl(mode, file, *args): + """spawnl(mode, file, *args) -> integer + +Execute file with arguments from args in a subprocess. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return spawnv(mode, file, args) + + def spawnle(mode, file, *args): + """spawnle(mode, file, *args, env) -> integer + +Execute file with arguments from args in a subprocess with the +supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + env = args[-1] + return spawnve(mode, file, args[:-1], env) + + + __all__.extend(["spawnl", "spawnle"]) + + +if _exists("spawnvp"): + # At the moment, Windows doesn't implement spawnvp[e], + # so it won't have spawnlp[e] either. + def spawnlp(mode, file, *args): + """spawnlp(mode, file, *args) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess with the supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + return spawnvp(mode, file, args) + + def spawnlpe(mode, file, *args): + """spawnlpe(mode, file, *args, env) -> integer + +Execute file (which is looked for along $PATH) with arguments from +args in a subprocess with the supplied environment. +If mode == P_NOWAIT return the pid of the process. +If mode == P_WAIT return the process's exit code if it exits normally; +otherwise return -SIG, where SIG is the signal that killed it. """ + env = args[-1] + return spawnvpe(mode, file, args[:-1], env) + + + __all__.extend(["spawnlp", "spawnlpe"]) + + +# Supply os.popen() +def popen(cmd, mode="r", buffering=-1): + if not isinstance(cmd, str): + raise TypeError("invalid cmd type (%s, expected string)" % type(cmd)) + if mode not in ("r", "w"): + raise ValueError("invalid mode %r" % mode) + if buffering == 0 or buffering is None: + raise ValueError("popen() does not support unbuffered streams") + import subprocess, io + if mode == "r": + proc = subprocess.Popen(cmd, + shell=True, + stdout=subprocess.PIPE, + bufsize=buffering) + return _wrap_close(io.TextIOWrapper(proc.stdout), proc) + else: + proc = subprocess.Popen(cmd, + shell=True, + stdin=subprocess.PIPE, + bufsize=buffering) + return _wrap_close(io.TextIOWrapper(proc.stdin), proc) + +# Helper for popen() -- a proxy for a file whose close waits for the process +class _wrap_close: + def __init__(self, stream, proc): + self._stream = stream + self._proc = proc + def close(self): + self._stream.close() + returncode = self._proc.wait() + if returncode == 0: + return None + if name == 'nt': + return returncode + else: + return returncode << 8 # Shift left to match old behavior + def __enter__(self): + return self + def __exit__(self, *args): + self.close() + def __getattr__(self, name): + return getattr(self._stream, name) + def __iter__(self): + return iter(self._stream) + +# Supply os.fdopen() +def fdopen(fd, *args, **kwargs): + if not isinstance(fd, int): + raise TypeError("invalid fd type (%s, expected integer)" % type(fd)) + import io + return io.open(fd, *args, **kwargs) + + +# For testing purposes, make sure the function is available when the C +# implementation exists. +def _fspath(path): + """Return the path representation of a path-like object. + + If str or bytes is passed in, it is returned unchanged. Otherwise the + os.PathLike interface is used to get the path representation. If the + path representation is not str or bytes, TypeError is raised. If the + provided path is not str, bytes, or os.PathLike, TypeError is raised. + """ + if isinstance(path, (str, bytes)): + return path + + # Work from the object's type to match method resolution of other magic + # methods. + path_type = type(path) + try: + path_repr = path_type.__fspath__(path) + except AttributeError: + if hasattr(path_type, '__fspath__'): + raise + else: + raise TypeError("expected str, bytes or os.PathLike object, " + "not " + path_type.__name__) + if isinstance(path_repr, (str, bytes)): + return path_repr + else: + raise TypeError("expected {}.__fspath__() to return str or bytes, " + "not {}".format(path_type.__name__, + type(path_repr).__name__)) + +# If there is no C implementation, make the pure Python version the +# implementation as transparently as possible. +if not _exists('fspath'): + fspath = _fspath + fspath.__name__ = "fspath" + + +class PathLike(abc.ABC): + + """Abstract base class for implementing the file system path protocol.""" + + @abc.abstractmethod + def __fspath__(self): + """Return the file system path representation of the object.""" + raise NotImplementedError + + @classmethod + def __subclasshook__(cls, subclass): + return hasattr(subclass, '__fspath__') diff --git a/winvenv/Lib/posixpath.py b/winvenv/Lib/posixpath.py new file mode 100644 index 0000000..e92186c --- /dev/null +++ b/winvenv/Lib/posixpath.py @@ -0,0 +1,522 @@ +"""Common operations on Posix pathnames. + +Instead of importing this module directly, import os and refer to +this module as os.path. The "os.path" name is an alias for this +module on Posix systems; on other systems (e.g. Mac, Windows), +os.path provides the same operations in a manner specific to that +platform, and is an alias to another module (e.g. macpath, ntpath). + +Some of this can actually be useful on non-Posix systems too, e.g. +for manipulation of the pathname component of URLs. +""" + +# Strings representing various path-related bits and pieces. +# These are primarily for export; internally, they are hardcoded. +# Should be set before imports for resolving cyclic dependency. +curdir = '.' +pardir = '..' +extsep = '.' +sep = '/' +pathsep = ':' +defpath = ':/bin:/usr/bin' +altsep = None +devnull = '/dev/null' + +import os +import sys +import stat +import genericpath +from genericpath import * + +__all__ = ["normcase","isabs","join","splitdrive","split","splitext", + "basename","dirname","commonprefix","getsize","getmtime", + "getatime","getctime","islink","exists","lexists","isdir","isfile", + "ismount", "expanduser","expandvars","normpath","abspath", + "samefile","sameopenfile","samestat", + "curdir","pardir","sep","pathsep","defpath","altsep","extsep", + "devnull","realpath","supports_unicode_filenames","relpath", + "commonpath"] + + +def _get_sep(path): + if isinstance(path, bytes): + return b'/' + else: + return '/' + +# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac. +# On MS-DOS this may also turn slashes into backslashes; however, other +# normalizations (such as optimizing '../' away) are not allowed +# (another function should be defined to do that). + +def normcase(s): + """Normalize case of pathname. Has no effect under Posix""" + s = os.fspath(s) + if not isinstance(s, (bytes, str)): + raise TypeError("normcase() argument must be str or bytes, " + "not '{}'".format(s.__class__.__name__)) + return s + + +# Return whether a path is absolute. +# Trivial in Posix, harder on the Mac or MS-DOS. + +def isabs(s): + """Test whether a path is absolute""" + s = os.fspath(s) + sep = _get_sep(s) + return s.startswith(sep) + + +# Join pathnames. +# Ignore the previous parts if a part is absolute. +# Insert a '/' unless the first part is empty or already ends in '/'. + +def join(a, *p): + """Join two or more pathname components, inserting '/' as needed. + If any component is an absolute path, all previous path components + will be discarded. An empty last part will result in a path that + ends with a separator.""" + a = os.fspath(a) + sep = _get_sep(a) + path = a + try: + if not p: + path[:0] + sep #23780: Ensure compatible data type even if p is null. + for b in map(os.fspath, p): + if b.startswith(sep): + path = b + elif not path or path.endswith(sep): + path += b + else: + path += sep + b + except (TypeError, AttributeError, BytesWarning): + genericpath._check_arg_types('join', a, *p) + raise + return path + + +# Split a path in head (everything up to the last '/') and tail (the +# rest). If the path ends in '/', tail will be empty. If there is no +# '/' in the path, head will be empty. +# Trailing '/'es are stripped from head unless it is the root. + +def split(p): + """Split a pathname. Returns tuple "(head, tail)" where "tail" is + everything after the final slash. Either part may be empty.""" + p = os.fspath(p) + sep = _get_sep(p) + i = p.rfind(sep) + 1 + head, tail = p[:i], p[i:] + if head and head != sep*len(head): + head = head.rstrip(sep) + return head, tail + + +# Split a path in root and extension. +# The extension is everything starting at the last dot in the last +# pathname component; the root is everything before that. +# It is always true that root + ext == p. + +def splitext(p): + p = os.fspath(p) + if isinstance(p, bytes): + sep = b'/' + extsep = b'.' + else: + sep = '/' + extsep = '.' + return genericpath._splitext(p, sep, None, extsep) +splitext.__doc__ = genericpath._splitext.__doc__ + +# Split a pathname into a drive specification and the rest of the +# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. + +def splitdrive(p): + """Split a pathname into drive and path. On Posix, drive is always + empty.""" + p = os.fspath(p) + return p[:0], p + + +# Return the tail (basename) part of a path, same as split(path)[1]. + +def basename(p): + """Returns the final component of a pathname""" + p = os.fspath(p) + sep = _get_sep(p) + i = p.rfind(sep) + 1 + return p[i:] + + +# Return the head (dirname) part of a path, same as split(path)[0]. + +def dirname(p): + """Returns the directory component of a pathname""" + p = os.fspath(p) + sep = _get_sep(p) + i = p.rfind(sep) + 1 + head = p[:i] + if head and head != sep*len(head): + head = head.rstrip(sep) + return head + + +# Is a path a symbolic link? +# This will always return false on systems where os.lstat doesn't exist. + +def islink(path): + """Test whether a path is a symbolic link""" + try: + st = os.lstat(path) + except (OSError, AttributeError): + return False + return stat.S_ISLNK(st.st_mode) + +# Being true for dangling symbolic links is also useful. + +def lexists(path): + """Test whether a path exists. Returns True for broken symbolic links""" + try: + os.lstat(path) + except OSError: + return False + return True + + +# Is a path a mount point? +# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) + +def ismount(path): + """Test whether a path is a mount point""" + try: + s1 = os.lstat(path) + except OSError: + # It doesn't exist -- so not a mount point. :-) + return False + else: + # A symlink can never be a mount point + if stat.S_ISLNK(s1.st_mode): + return False + + if isinstance(path, bytes): + parent = join(path, b'..') + else: + parent = join(path, '..') + parent = realpath(parent) + try: + s2 = os.lstat(parent) + except OSError: + return False + + dev1 = s1.st_dev + dev2 = s2.st_dev + if dev1 != dev2: + return True # path/.. on a different device as path + ino1 = s1.st_ino + ino2 = s2.st_ino + if ino1 == ino2: + return True # path/.. is the same i-node as path + return False + + +# Expand paths beginning with '~' or '~user'. +# '~' means $HOME; '~user' means that user's home directory. +# If the path doesn't begin with '~', or if the user or $HOME is unknown, +# the path is returned unchanged (leaving error reporting to whatever +# function is called with the expanded path as argument). +# See also module 'glob' for expansion of *, ? and [...] in pathnames. +# (A function should also be defined to do full *sh-style environment +# variable expansion.) + +def expanduser(path): + """Expand ~ and ~user constructions. If user or $HOME is unknown, + do nothing.""" + path = os.fspath(path) + if isinstance(path, bytes): + tilde = b'~' + else: + tilde = '~' + if not path.startswith(tilde): + return path + sep = _get_sep(path) + i = path.find(sep, 1) + if i < 0: + i = len(path) + if i == 1: + if 'HOME' not in os.environ: + import pwd + userhome = pwd.getpwuid(os.getuid()).pw_dir + else: + userhome = os.environ['HOME'] + else: + import pwd + name = path[1:i] + if isinstance(name, bytes): + name = str(name, 'ASCII') + try: + pwent = pwd.getpwnam(name) + except KeyError: + return path + userhome = pwent.pw_dir + if isinstance(path, bytes): + userhome = os.fsencode(userhome) + root = b'/' + else: + root = '/' + userhome = userhome.rstrip(root) + return (userhome + path[i:]) or root + + +# Expand paths containing shell variable substitutions. +# This expands the forms $variable and ${variable} only. +# Non-existent variables are left unchanged. + +_varprog = None +_varprogb = None + +def expandvars(path): + """Expand shell variables of form $var and ${var}. Unknown variables + are left unchanged.""" + path = os.fspath(path) + global _varprog, _varprogb + if isinstance(path, bytes): + if b'$' not in path: + return path + if not _varprogb: + import re + _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII) + search = _varprogb.search + start = b'{' + end = b'}' + environ = getattr(os, 'environb', None) + else: + if '$' not in path: + return path + if not _varprog: + import re + _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) + search = _varprog.search + start = '{' + end = '}' + environ = os.environ + i = 0 + while True: + m = search(path, i) + if not m: + break + i, j = m.span(0) + name = m.group(1) + if name.startswith(start) and name.endswith(end): + name = name[1:-1] + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(name)]) + else: + value = environ[name] + except KeyError: + i = j + else: + tail = path[j:] + path = path[:i] + value + i = len(path) + path += tail + return path + + +# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. +# It should be understood that this may change the meaning of the path +# if it contains symbolic links! + +def normpath(path): + """Normalize path, eliminating double slashes, etc.""" + path = os.fspath(path) + if isinstance(path, bytes): + sep = b'/' + empty = b'' + dot = b'.' + dotdot = b'..' + else: + sep = '/' + empty = '' + dot = '.' + dotdot = '..' + if path == empty: + return dot + initial_slashes = path.startswith(sep) + # POSIX allows one or two initial slashes, but treats three or more + # as single slash. + if (initial_slashes and + path.startswith(sep*2) and not path.startswith(sep*3)): + initial_slashes = 2 + comps = path.split(sep) + new_comps = [] + for comp in comps: + if comp in (empty, dot): + continue + if (comp != dotdot or (not initial_slashes and not new_comps) or + (new_comps and new_comps[-1] == dotdot)): + new_comps.append(comp) + elif new_comps: + new_comps.pop() + comps = new_comps + path = sep.join(comps) + if initial_slashes: + path = sep*initial_slashes + path + return path or dot + + +def abspath(path): + """Return an absolute path.""" + path = os.fspath(path) + if not isabs(path): + if isinstance(path, bytes): + cwd = os.getcwdb() + else: + cwd = os.getcwd() + path = join(cwd, path) + return normpath(path) + + +# Return a canonical path (i.e. the absolute location of a file on the +# filesystem). + +def realpath(filename): + """Return the canonical path of the specified filename, eliminating any +symbolic links encountered in the path.""" + filename = os.fspath(filename) + path, ok = _joinrealpath(filename[:0], filename, {}) + return abspath(path) + +# Join two paths, normalizing and eliminating any symbolic links +# encountered in the second path. +def _joinrealpath(path, rest, seen): + if isinstance(path, bytes): + sep = b'/' + curdir = b'.' + pardir = b'..' + else: + sep = '/' + curdir = '.' + pardir = '..' + + if isabs(rest): + rest = rest[1:] + path = sep + + while rest: + name, _, rest = rest.partition(sep) + if not name or name == curdir: + # current dir + continue + if name == pardir: + # parent dir + if path: + path, name = split(path) + if name == pardir: + path = join(path, pardir, pardir) + else: + path = pardir + continue + newpath = join(path, name) + if not islink(newpath): + path = newpath + continue + # Resolve the symbolic link + if newpath in seen: + # Already seen this path + path = seen[newpath] + if path is not None: + # use cached value + continue + # The symlink is not resolved, so we must have a symlink loop. + # Return already resolved part + rest of the path unchanged. + return join(newpath, rest), False + seen[newpath] = None # not resolved symlink + path, ok = _joinrealpath(path, os.readlink(newpath), seen) + if not ok: + return join(path, rest), False + seen[newpath] = path # resolved symlink + + return path, True + + +supports_unicode_filenames = (sys.platform == 'darwin') + +def relpath(path, start=None): + """Return a relative version of a path""" + + if not path: + raise ValueError("no path specified") + + path = os.fspath(path) + if isinstance(path, bytes): + curdir = b'.' + sep = b'/' + pardir = b'..' + else: + curdir = '.' + sep = '/' + pardir = '..' + + if start is None: + start = curdir + else: + start = os.fspath(start) + + try: + start_list = [x for x in abspath(start).split(sep) if x] + path_list = [x for x in abspath(path).split(sep) if x] + # Work out how much of the filepath is shared by start and path. + i = len(commonprefix([start_list, path_list])) + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return curdir + return join(*rel_list) + except (TypeError, AttributeError, BytesWarning, DeprecationWarning): + genericpath._check_arg_types('relpath', path, start) + raise + + +# Return the longest common sub-path of the sequence of paths given as input. +# The paths are not normalized before comparing them (this is the +# responsibility of the caller). Any trailing separator is stripped from the +# returned path. + +def commonpath(paths): + """Given a sequence of path names, returns the longest common sub-path.""" + + if not paths: + raise ValueError('commonpath() arg is an empty sequence') + + paths = tuple(map(os.fspath, paths)) + if isinstance(paths[0], bytes): + sep = b'/' + curdir = b'.' + else: + sep = '/' + curdir = '.' + + try: + split_paths = [path.split(sep) for path in paths] + + try: + isabs, = set(p[:1] == sep for p in paths) + except ValueError: + raise ValueError("Can't mix absolute and relative paths") from None + + split_paths = [[c for c in s if c and c != curdir] for s in split_paths] + s1 = min(split_paths) + s2 = max(split_paths) + common = s1 + for i, c in enumerate(s1): + if c != s2[i]: + common = s1[:i] + break + + prefix = sep if isabs else sep[:0] + return prefix + sep.join(common) + except (TypeError, AttributeError): + genericpath._check_arg_types('commonpath', *paths) + raise diff --git a/winvenv/Lib/random.py b/winvenv/Lib/random.py new file mode 100644 index 0000000..8e94064 --- /dev/null +++ b/winvenv/Lib/random.py @@ -0,0 +1,777 @@ +"""Random variable generators. + + integers + -------- + uniform within range + + sequences + --------- + pick random element + pick random sample + pick weighted random sample + generate random permutation + + distributions on the real line: + ------------------------------ + uniform + triangular + normal (Gaussian) + lognormal + negative exponential + gamma + beta + pareto + Weibull + + distributions on the circle (angles 0 to 2pi) + --------------------------------------------- + circular uniform + von Mises + +General notes on the underlying Mersenne Twister core generator: + +* The period is 2**19937-1. +* It is one of the most extensively tested generators in existence. +* The random() method is implemented in C, executes in a single Python step, + and is, therefore, threadsafe. + +""" + +from warnings import warn as _warn +from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType +from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil +from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin +from os import urandom as _urandom +from _collections_abc import Set as _Set, Sequence as _Sequence +from hashlib import sha512 as _sha512 +import itertools as _itertools +import bisect as _bisect +import os as _os + +__all__ = ["Random","seed","random","uniform","randint","choice","sample", + "randrange","shuffle","normalvariate","lognormvariate", + "expovariate","vonmisesvariate","gammavariate","triangular", + "gauss","betavariate","paretovariate","weibullvariate", + "getstate","setstate", "getrandbits", "choices", + "SystemRandom"] + +NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) +TWOPI = 2.0*_pi +LOG4 = _log(4.0) +SG_MAGICCONST = 1.0 + _log(4.5) +BPF = 53 # Number of bits in a float +RECIP_BPF = 2**-BPF + + +# Translated by Guido van Rossum from C source provided by +# Adrian Baddeley. Adapted by Raymond Hettinger for use with +# the Mersenne Twister and os.urandom() core generators. + +import _random + +class Random(_random.Random): + """Random number generator base class used by bound module functions. + + Used to instantiate instances of Random to get generators that don't + share state. + + Class Random can also be subclassed if you want to use a different basic + generator of your own devising: in that case, override the following + methods: random(), seed(), getstate(), and setstate(). + Optionally, implement a getrandbits() method so that randrange() + can cover arbitrarily large ranges. + + """ + + VERSION = 3 # used by getstate/setstate + + def __init__(self, x=None): + """Initialize an instance. + + Optional argument x controls seeding, as for Random.seed(). + """ + + self.seed(x) + self.gauss_next = None + + def seed(self, a=None, version=2): + """Initialize internal state from hashable object. + + None or no argument seeds from current time or from an operating + system specific randomness source if available. + + If *a* is an int, all bits are used. + + For version 2 (the default), all of the bits are used if *a* is a str, + bytes, or bytearray. For version 1 (provided for reproducing random + sequences from older versions of Python), the algorithm for str and + bytes generates a narrower range of seeds. + + """ + + if version == 1 and isinstance(a, (str, bytes)): + a = a.decode('latin-1') if isinstance(a, bytes) else a + x = ord(a[0]) << 7 if a else 0 + for c in map(ord, a): + x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF + x ^= len(a) + a = -2 if x == -1 else x + + if version == 2 and isinstance(a, (str, bytes, bytearray)): + if isinstance(a, str): + a = a.encode() + a += _sha512(a).digest() + a = int.from_bytes(a, 'big') + + super().seed(a) + self.gauss_next = None + + def getstate(self): + """Return internal state; can be passed to setstate() later.""" + return self.VERSION, super().getstate(), self.gauss_next + + def setstate(self, state): + """Restore internal state from object returned by getstate().""" + version = state[0] + if version == 3: + version, internalstate, self.gauss_next = state + super().setstate(internalstate) + elif version == 2: + version, internalstate, self.gauss_next = state + # In version 2, the state was saved as signed ints, which causes + # inconsistencies between 32/64-bit systems. The state is + # really unsigned 32-bit ints, so we convert negative ints from + # version 2 to positive longs for version 3. + try: + internalstate = tuple(x % (2**32) for x in internalstate) + except ValueError as e: + raise TypeError from e + super().setstate(internalstate) + else: + raise ValueError("state with version %s passed to " + "Random.setstate() of version %s" % + (version, self.VERSION)) + +## ---- Methods below this point do not need to be overridden when +## ---- subclassing for the purpose of using a different core generator. + +## -------------------- pickle support ------------------- + + # Issue 17489: Since __reduce__ was defined to fix #759889 this is no + # longer called; we leave it here because it has been here since random was + # rewritten back in 2001 and why risk breaking something. + def __getstate__(self): # for pickle + return self.getstate() + + def __setstate__(self, state): # for pickle + self.setstate(state) + + def __reduce__(self): + return self.__class__, (), self.getstate() + +## -------------------- integer methods ------------------- + + def randrange(self, start, stop=None, step=1, _int=int): + """Choose a random item from range(start, stop[, step]). + + This fixes the problem with randint() which includes the + endpoint; in Python this is usually not what you want. + + """ + + # This code is a bit messy to make it fast for the + # common case while still doing adequate error checking. + istart = _int(start) + if istart != start: + raise ValueError("non-integer arg 1 for randrange()") + if stop is None: + if istart > 0: + return self._randbelow(istart) + raise ValueError("empty range for randrange()") + + # stop argument supplied. + istop = _int(stop) + if istop != stop: + raise ValueError("non-integer stop for randrange()") + width = istop - istart + if step == 1 and width > 0: + return istart + self._randbelow(width) + if step == 1: + raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width)) + + # Non-unit step argument supplied. + istep = _int(step) + if istep != step: + raise ValueError("non-integer step for randrange()") + if istep > 0: + n = (width + istep - 1) // istep + elif istep < 0: + n = (width + istep + 1) // istep + else: + raise ValueError("zero step for randrange()") + + if n <= 0: + raise ValueError("empty range for randrange()") + + return istart + istep*self._randbelow(n) + + def randint(self, a, b): + """Return random integer in range [a, b], including both end points. + """ + + return self.randrange(a, b+1) + + def _randbelow(self, n, int=int, maxsize=1<= n: + r = getrandbits(k) + return r + # There's an overridden random() method but no new getrandbits() method, + # so we can only use random() from here. + if n >= maxsize: + _warn("Underlying random() generator does not supply \n" + "enough bits to choose from a population range this large.\n" + "To remove the range limitation, add a getrandbits() method.") + return int(random() * n) + if n == 0: + raise ValueError("Boundary cannot be zero") + rem = maxsize % n + limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0 + r = random() + while r >= limit: + r = random() + return int(r*maxsize) % n + +## -------------------- sequence methods ------------------- + + def choice(self, seq): + """Choose a random element from a non-empty sequence.""" + try: + i = self._randbelow(len(seq)) + except ValueError: + raise IndexError('Cannot choose from an empty sequence') from None + return seq[i] + + def shuffle(self, x, random=None): + """Shuffle list x in place, and return None. + + Optional argument random is a 0-argument function returning a + random float in [0.0, 1.0); if it is the default None, the + standard random.random will be used. + + """ + + if random is None: + randbelow = self._randbelow + for i in reversed(range(1, len(x))): + # pick an element in x[:i+1] with which to exchange x[i] + j = randbelow(i+1) + x[i], x[j] = x[j], x[i] + else: + _int = int + for i in reversed(range(1, len(x))): + # pick an element in x[:i+1] with which to exchange x[i] + j = _int(random() * (i+1)) + x[i], x[j] = x[j], x[i] + + def sample(self, population, k): + """Chooses k unique random elements from a population sequence or set. + + Returns a new list containing elements from the population while + leaving the original population unchanged. The resulting list is + in selection order so that all sub-slices will also be valid random + samples. This allows raffle winners (the sample) to be partitioned + into grand prize and second place winners (the subslices). + + Members of the population need not be hashable or unique. If the + population contains repeats, then each occurrence is a possible + selection in the sample. + + To choose a sample in a range of integers, use range as an argument. + This is especially fast and space efficient for sampling from a + large population: sample(range(10000000), 60) + """ + + # Sampling without replacement entails tracking either potential + # selections (the pool) in a list or previous selections in a set. + + # When the number of selections is small compared to the + # population, then tracking selections is efficient, requiring + # only a small set and an occasional reselection. For + # a larger number of selections, the pool tracking method is + # preferred since the list takes less space than the + # set and it doesn't suffer from frequent reselections. + + if isinstance(population, _Set): + population = tuple(population) + if not isinstance(population, _Sequence): + raise TypeError("Population must be a sequence or set. For dicts, use list(d).") + randbelow = self._randbelow + n = len(population) + if not 0 <= k <= n: + raise ValueError("Sample larger than population or is negative") + result = [None] * k + setsize = 21 # size of a small set minus size of an empty list + if k > 5: + setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets + if n <= setsize: + # An n-length list is smaller than a k-length set + pool = list(population) + for i in range(k): # invariant: non-selected at [0,n-i) + j = randbelow(n-i) + result[i] = pool[j] + pool[j] = pool[n-i-1] # move non-selected item into vacancy + else: + selected = set() + selected_add = selected.add + for i in range(k): + j = randbelow(n) + while j in selected: + j = randbelow(n) + selected_add(j) + result[i] = population[j] + return result + + def choices(self, population, weights=None, *, cum_weights=None, k=1): + """Return a k sized list of population elements chosen with replacement. + + If the relative weights or cumulative weights are not specified, + the selections are made with equal probability. + + """ + random = self.random + if cum_weights is None: + if weights is None: + _int = int + total = len(population) + return [population[_int(random() * total)] for i in range(k)] + cum_weights = list(_itertools.accumulate(weights)) + elif weights is not None: + raise TypeError('Cannot specify both weights and cumulative weights') + if len(cum_weights) != len(population): + raise ValueError('The number of weights does not match the population') + bisect = _bisect.bisect + total = cum_weights[-1] + hi = len(cum_weights) - 1 + return [population[bisect(cum_weights, random() * total, 0, hi)] + for i in range(k)] + +## -------------------- real-valued distributions ------------------- + +## -------------------- uniform distribution ------------------- + + def uniform(self, a, b): + "Get a random number in the range [a, b) or [a, b] depending on rounding." + return a + (b-a) * self.random() + +## -------------------- triangular -------------------- + + def triangular(self, low=0.0, high=1.0, mode=None): + """Triangular distribution. + + Continuous distribution bounded by given lower and upper limits, + and having a given mode value in-between. + + http://en.wikipedia.org/wiki/Triangular_distribution + + """ + u = self.random() + try: + c = 0.5 if mode is None else (mode - low) / (high - low) + except ZeroDivisionError: + return low + if u > c: + u = 1.0 - u + c = 1.0 - c + low, high = high, low + return low + (high - low) * _sqrt(u * c) + +## -------------------- normal distribution -------------------- + + def normalvariate(self, mu, sigma): + """Normal distribution. + + mu is the mean, and sigma is the standard deviation. + + """ + # mu = mean, sigma = standard deviation + + # Uses Kinderman and Monahan method. Reference: Kinderman, + # A.J. and Monahan, J.F., "Computer generation of random + # variables using the ratio of uniform deviates", ACM Trans + # Math Software, 3, (1977), pp257-260. + + random = self.random + while 1: + u1 = random() + u2 = 1.0 - random() + z = NV_MAGICCONST*(u1-0.5)/u2 + zz = z*z/4.0 + if zz <= -_log(u2): + break + return mu + z*sigma + +## -------------------- lognormal distribution -------------------- + + def lognormvariate(self, mu, sigma): + """Log normal distribution. + + If you take the natural logarithm of this distribution, you'll get a + normal distribution with mean mu and standard deviation sigma. + mu can have any value, and sigma must be greater than zero. + + """ + return _exp(self.normalvariate(mu, sigma)) + +## -------------------- exponential distribution -------------------- + + def expovariate(self, lambd): + """Exponential distribution. + + lambd is 1.0 divided by the desired mean. It should be + nonzero. (The parameter would be called "lambda", but that is + a reserved word in Python.) Returned values range from 0 to + positive infinity if lambd is positive, and from negative + infinity to 0 if lambd is negative. + + """ + # lambd: rate lambd = 1/mean + # ('lambda' is a Python reserved word) + + # we use 1-random() instead of random() to preclude the + # possibility of taking the log of zero. + return -_log(1.0 - self.random())/lambd + +## -------------------- von Mises distribution -------------------- + + def vonmisesvariate(self, mu, kappa): + """Circular data distribution. + + mu is the mean angle, expressed in radians between 0 and 2*pi, and + kappa is the concentration parameter, which must be greater than or + equal to zero. If kappa is equal to zero, this distribution reduces + to a uniform random angle over the range 0 to 2*pi. + + """ + # mu: mean angle (in radians between 0 and 2*pi) + # kappa: concentration parameter kappa (>= 0) + # if kappa = 0 generate uniform random angle + + # Based upon an algorithm published in: Fisher, N.I., + # "Statistical Analysis of Circular Data", Cambridge + # University Press, 1993. + + # Thanks to Magnus Kessler for a correction to the + # implementation of step 4. + + random = self.random + if kappa <= 1e-6: + return TWOPI * random() + + s = 0.5 / kappa + r = s + _sqrt(1.0 + s * s) + + while 1: + u1 = random() + z = _cos(_pi * u1) + + d = z / (r + z) + u2 = random() + if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d): + break + + q = 1.0 / r + f = (q + z) / (1.0 + q * z) + u3 = random() + if u3 > 0.5: + theta = (mu + _acos(f)) % TWOPI + else: + theta = (mu - _acos(f)) % TWOPI + + return theta + +## -------------------- gamma distribution -------------------- + + def gammavariate(self, alpha, beta): + """Gamma distribution. Not the gamma function! + + Conditions on the parameters are alpha > 0 and beta > 0. + + The probability distribution function is: + + x ** (alpha - 1) * math.exp(-x / beta) + pdf(x) = -------------------------------------- + math.gamma(alpha) * beta ** alpha + + """ + + # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 + + # Warning: a few older sources define the gamma distribution in terms + # of alpha > -1.0 + if alpha <= 0.0 or beta <= 0.0: + raise ValueError('gammavariate: alpha and beta must be > 0.0') + + random = self.random + if alpha > 1.0: + + # Uses R.C.H. Cheng, "The generation of Gamma + # variables with non-integral shape parameters", + # Applied Statistics, (1977), 26, No. 1, p71-74 + + ainv = _sqrt(2.0 * alpha - 1.0) + bbb = alpha - LOG4 + ccc = alpha + ainv + + while 1: + u1 = random() + if not 1e-7 < u1 < .9999999: + continue + u2 = 1.0 - random() + v = _log(u1/(1.0-u1))/ainv + x = alpha*_exp(v) + z = u1*u1*u2 + r = bbb+ccc*v-x + if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): + return x * beta + + elif alpha == 1.0: + # expovariate(1/beta) + u = random() + while u <= 1e-7: + u = random() + return -_log(u) * beta + + else: # alpha is between 0 and 1 (exclusive) + + # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle + + while 1: + u = random() + b = (_e + alpha)/_e + p = b*u + if p <= 1.0: + x = p ** (1.0/alpha) + else: + x = -_log((b-p)/alpha) + u1 = random() + if p > 1.0: + if u1 <= x ** (alpha - 1.0): + break + elif u1 <= _exp(-x): + break + return x * beta + +## -------------------- Gauss (faster alternative) -------------------- + + def gauss(self, mu, sigma): + """Gaussian distribution. + + mu is the mean, and sigma is the standard deviation. This is + slightly faster than the normalvariate() function. + + Not thread-safe without a lock around calls. + + """ + + # When x and y are two variables from [0, 1), uniformly + # distributed, then + # + # cos(2*pi*x)*sqrt(-2*log(1-y)) + # sin(2*pi*x)*sqrt(-2*log(1-y)) + # + # are two *independent* variables with normal distribution + # (mu = 0, sigma = 1). + # (Lambert Meertens) + # (corrected version; bug discovered by Mike Miller, fixed by LM) + + # Multithreading note: When two threads call this function + # simultaneously, it is possible that they will receive the + # same return value. The window is very small though. To + # avoid this, you have to use a lock around all calls. (I + # didn't want to slow this down in the serial case by using a + # lock here.) + + random = self.random + z = self.gauss_next + self.gauss_next = None + if z is None: + x2pi = random() * TWOPI + g2rad = _sqrt(-2.0 * _log(1.0 - random())) + z = _cos(x2pi) * g2rad + self.gauss_next = _sin(x2pi) * g2rad + + return mu + z*sigma + +## -------------------- beta -------------------- +## See +## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html +## for Ivan Frohne's insightful analysis of why the original implementation: +## +## def betavariate(self, alpha, beta): +## # Discrete Event Simulation in C, pp 87-88. +## +## y = self.expovariate(alpha) +## z = self.expovariate(1.0/beta) +## return z/(y+z) +## +## was dead wrong, and how it probably got that way. + + def betavariate(self, alpha, beta): + """Beta distribution. + + Conditions on the parameters are alpha > 0 and beta > 0. + Returned values range between 0 and 1. + + """ + + # This version due to Janne Sinkkonen, and matches all the std + # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). + y = self.gammavariate(alpha, 1.0) + if y == 0: + return 0.0 + else: + return y / (y + self.gammavariate(beta, 1.0)) + +## -------------------- Pareto -------------------- + + def paretovariate(self, alpha): + """Pareto distribution. alpha is the shape parameter.""" + # Jain, pg. 495 + + u = 1.0 - self.random() + return 1.0 / u ** (1.0/alpha) + +## -------------------- Weibull -------------------- + + def weibullvariate(self, alpha, beta): + """Weibull distribution. + + alpha is the scale parameter and beta is the shape parameter. + + """ + # Jain, pg. 499; bug fix courtesy Bill Arms + + u = 1.0 - self.random() + return alpha * (-_log(u)) ** (1.0/beta) + +## --------------- Operating System Random Source ------------------ + +class SystemRandom(Random): + """Alternate random number generator using sources provided + by the operating system (such as /dev/urandom on Unix or + CryptGenRandom on Windows). + + Not available on all systems (see os.urandom() for details). + """ + + def random(self): + """Get the next random number in the range [0.0, 1.0).""" + return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF + + def getrandbits(self, k): + """getrandbits(k) -> x. Generates an int with k random bits.""" + if k <= 0: + raise ValueError('number of bits must be greater than zero') + if k != int(k): + raise TypeError('number of bits should be an integer') + numbytes = (k + 7) // 8 # bits / 8 and rounded up + x = int.from_bytes(_urandom(numbytes), 'big') + return x >> (numbytes * 8 - k) # trim excess bits + + def seed(self, *args, **kwds): + "Stub method. Not used for a system random number generator." + return None + + def _notimplemented(self, *args, **kwds): + "Method should not be called for a system random number generator." + raise NotImplementedError('System entropy source does not have state.') + getstate = setstate = _notimplemented + +## -------------------- test program -------------------- + +def _test_generator(n, func, args): + import time + print(n, 'times', func.__name__) + total = 0.0 + sqsum = 0.0 + smallest = 1e10 + largest = -1e10 + t0 = time.time() + for i in range(n): + x = func(*args) + total += x + sqsum = sqsum + x*x + smallest = min(x, smallest) + largest = max(x, largest) + t1 = time.time() + print(round(t1-t0, 3), 'sec,', end=' ') + avg = total/n + stddev = _sqrt(sqsum/n - avg*avg) + print('avg %g, stddev %g, min %g, max %g\n' % \ + (avg, stddev, smallest, largest)) + + +def _test(N=2000): + _test_generator(N, random, ()) + _test_generator(N, normalvariate, (0.0, 1.0)) + _test_generator(N, lognormvariate, (0.0, 1.0)) + _test_generator(N, vonmisesvariate, (0.0, 1.0)) + _test_generator(N, gammavariate, (0.01, 1.0)) + _test_generator(N, gammavariate, (0.1, 1.0)) + _test_generator(N, gammavariate, (0.1, 2.0)) + _test_generator(N, gammavariate, (0.5, 1.0)) + _test_generator(N, gammavariate, (0.9, 1.0)) + _test_generator(N, gammavariate, (1.0, 1.0)) + _test_generator(N, gammavariate, (2.0, 1.0)) + _test_generator(N, gammavariate, (20.0, 1.0)) + _test_generator(N, gammavariate, (200.0, 1.0)) + _test_generator(N, gauss, (0.0, 1.0)) + _test_generator(N, betavariate, (3.0, 3.0)) + _test_generator(N, triangular, (0.0, 1.0, 1.0/3.0)) + +# Create one instance, seeded from current time, and export its methods +# as module-level functions. The functions share state across all uses +#(both in the user's code and in the Python libraries), but that's fine +# for most programs and is easier for the casual user than making them +# instantiate their own Random() instance. + +_inst = Random() +seed = _inst.seed +random = _inst.random +uniform = _inst.uniform +triangular = _inst.triangular +randint = _inst.randint +choice = _inst.choice +randrange = _inst.randrange +sample = _inst.sample +shuffle = _inst.shuffle +choices = _inst.choices +normalvariate = _inst.normalvariate +lognormvariate = _inst.lognormvariate +expovariate = _inst.expovariate +vonmisesvariate = _inst.vonmisesvariate +gammavariate = _inst.gammavariate +gauss = _inst.gauss +betavariate = _inst.betavariate +paretovariate = _inst.paretovariate +weibullvariate = _inst.weibullvariate +getstate = _inst.getstate +setstate = _inst.setstate +getrandbits = _inst.getrandbits + +if hasattr(_os, "fork"): + _os.register_at_fork(after_in_child=_inst.seed) + + +if __name__ == '__main__': + _test() diff --git a/winvenv/Lib/re.py b/winvenv/Lib/re.py new file mode 100644 index 0000000..94d4865 --- /dev/null +++ b/winvenv/Lib/re.py @@ -0,0 +1,366 @@ +# +# Secret Labs' Regular Expression Engine +# +# re-compatible interface for the sre matching engine +# +# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. +# +# This version of the SRE library can be redistributed under CNRI's +# Python 1.6 license. For any other use, please contact Secret Labs +# AB (info@pythonware.com). +# +# Portions of this engine have been developed in cooperation with +# CNRI. Hewlett-Packard provided funding for 1.6 integration and +# other compatibility work. +# + +r"""Support for regular expressions (RE). + +This module provides regular expression matching operations similar to +those found in Perl. It supports both 8-bit and Unicode strings; both +the pattern and the strings being processed can contain null bytes and +characters outside the US ASCII range. + +Regular expressions can contain both special and ordinary characters. +Most ordinary characters, like "A", "a", or "0", are the simplest +regular expressions; they simply match themselves. You can +concatenate ordinary characters, so last matches the string 'last'. + +The special characters are: + "." Matches any character except a newline. + "^" Matches the start of the string. + "$" Matches the end of the string or just before the newline at + the end of the string. + "*" Matches 0 or more (greedy) repetitions of the preceding RE. + Greedy means that it will match as many repetitions as possible. + "+" Matches 1 or more (greedy) repetitions of the preceding RE. + "?" Matches 0 or 1 (greedy) of the preceding RE. + *?,+?,?? Non-greedy versions of the previous three special characters. + {m,n} Matches from m to n repetitions of the preceding RE. + {m,n}? Non-greedy version of the above. + "\\" Either escapes special characters or signals a special sequence. + [] Indicates a set of characters. + A "^" as the first character indicates a complementing set. + "|" A|B, creates an RE that will match either A or B. + (...) Matches the RE inside the parentheses. + The contents can be retrieved or matched later in the string. + (?aiLmsux) Set the A, I, L, M, S, U, or X flag for the RE (see below). + (?:...) Non-grouping version of regular parentheses. + (?P...) The substring matched by the group is accessible by name. + (?P=name) Matches the text matched earlier by the group named name. + (?#...) A comment; ignored. + (?=...) Matches if ... matches next, but doesn't consume the string. + (?!...) Matches if ... doesn't match next. + (?<=...) Matches if preceded by ... (must be fixed length). + (?= _MAXCACHE: + # Drop the oldest item + try: + del _cache[next(iter(_cache))] + except (StopIteration, RuntimeError, KeyError): + pass + _cache[type(pattern), pattern, flags] = p + return p + +@functools.lru_cache(_MAXCACHE) +def _compile_repl(repl, pattern): + # internal: compile replacement pattern + return sre_parse.parse_template(repl, pattern) + +def _expand(pattern, match, template): + # internal: Match.expand implementation hook + template = sre_parse.parse_template(template, pattern) + return sre_parse.expand_template(template, match) + +def _subx(pattern, template): + # internal: Pattern.sub/subn implementation helper + template = _compile_repl(template, pattern) + if not template[0] and len(template[1]) == 1: + # literal replacement + return template[1][0] + def filter(match, template=template): + return sre_parse.expand_template(template, match) + return filter + +# register myself for pickling + +import copyreg + +def _pickle(p): + return _compile, (p.pattern, p.flags) + +copyreg.pickle(Pattern, _pickle, _compile) + +# -------------------------------------------------------------------- +# experimental stuff (see python-dev discussions for details) + +class Scanner: + def __init__(self, lexicon, flags=0): + from sre_constants import BRANCH, SUBPATTERN + if isinstance(flags, RegexFlag): + flags = flags.value + self.lexicon = lexicon + # combine phrases into a compound pattern + p = [] + s = sre_parse.Pattern() + s.flags = flags + for phrase, action in lexicon: + gid = s.opengroup() + p.append(sre_parse.SubPattern(s, [ + (SUBPATTERN, (gid, 0, 0, sre_parse.parse(phrase, flags))), + ])) + s.closegroup(gid, p[-1]) + p = sre_parse.SubPattern(s, [(BRANCH, (None, p))]) + self.scanner = sre_compile.compile(p) + def scan(self, string): + result = [] + append = result.append + match = self.scanner.scanner(string).match + i = 0 + while True: + m = match() + if not m: + break + j = m.end() + if i == j: + break + action = self.lexicon[m.lastindex-1][1] + if callable(action): + self.match = m + action = action(self, m.group()) + if action is not None: + append(action) + i = j + return result, string[i:] diff --git a/winvenv/Lib/reprlib.py b/winvenv/Lib/reprlib.py new file mode 100644 index 0000000..616b343 --- /dev/null +++ b/winvenv/Lib/reprlib.py @@ -0,0 +1,161 @@ +"""Redo the builtin repr() (representation) but with limits on most sizes.""" + +__all__ = ["Repr", "repr", "recursive_repr"] + +import builtins +from itertools import islice +from _thread import get_ident + +def recursive_repr(fillvalue='...'): + 'Decorator to make a repr function return fillvalue for a recursive call' + + def decorating_function(user_function): + repr_running = set() + + def wrapper(self): + key = id(self), get_ident() + if key in repr_running: + return fillvalue + repr_running.add(key) + try: + result = user_function(self) + finally: + repr_running.discard(key) + return result + + # Can't use functools.wraps() here because of bootstrap issues + wrapper.__module__ = getattr(user_function, '__module__') + wrapper.__doc__ = getattr(user_function, '__doc__') + wrapper.__name__ = getattr(user_function, '__name__') + wrapper.__qualname__ = getattr(user_function, '__qualname__') + wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) + return wrapper + + return decorating_function + +class Repr: + + def __init__(self): + self.maxlevel = 6 + self.maxtuple = 6 + self.maxlist = 6 + self.maxarray = 5 + self.maxdict = 4 + self.maxset = 6 + self.maxfrozenset = 6 + self.maxdeque = 6 + self.maxstring = 30 + self.maxlong = 40 + self.maxother = 30 + + def repr(self, x): + return self.repr1(x, self.maxlevel) + + def repr1(self, x, level): + typename = type(x).__name__ + if ' ' in typename: + parts = typename.split() + typename = '_'.join(parts) + if hasattr(self, 'repr_' + typename): + return getattr(self, 'repr_' + typename)(x, level) + else: + return self.repr_instance(x, level) + + def _repr_iterable(self, x, level, left, right, maxiter, trail=''): + n = len(x) + if level <= 0 and n: + s = '...' + else: + newlevel = level - 1 + repr1 = self.repr1 + pieces = [repr1(elem, newlevel) for elem in islice(x, maxiter)] + if n > maxiter: pieces.append('...') + s = ', '.join(pieces) + if n == 1 and trail: right = trail + right + return '%s%s%s' % (left, s, right) + + def repr_tuple(self, x, level): + return self._repr_iterable(x, level, '(', ')', self.maxtuple, ',') + + def repr_list(self, x, level): + return self._repr_iterable(x, level, '[', ']', self.maxlist) + + def repr_array(self, x, level): + if not x: + return "array('%s')" % x.typecode + header = "array('%s', [" % x.typecode + return self._repr_iterable(x, level, header, '])', self.maxarray) + + def repr_set(self, x, level): + if not x: + return 'set()' + x = _possibly_sorted(x) + return self._repr_iterable(x, level, '{', '}', self.maxset) + + def repr_frozenset(self, x, level): + if not x: + return 'frozenset()' + x = _possibly_sorted(x) + return self._repr_iterable(x, level, 'frozenset({', '})', + self.maxfrozenset) + + def repr_deque(self, x, level): + return self._repr_iterable(x, level, 'deque([', '])', self.maxdeque) + + def repr_dict(self, x, level): + n = len(x) + if n == 0: return '{}' + if level <= 0: return '{...}' + newlevel = level - 1 + repr1 = self.repr1 + pieces = [] + for key in islice(_possibly_sorted(x), self.maxdict): + keyrepr = repr1(key, newlevel) + valrepr = repr1(x[key], newlevel) + pieces.append('%s: %s' % (keyrepr, valrepr)) + if n > self.maxdict: pieces.append('...') + s = ', '.join(pieces) + return '{%s}' % (s,) + + def repr_str(self, x, level): + s = builtins.repr(x[:self.maxstring]) + if len(s) > self.maxstring: + i = max(0, (self.maxstring-3)//2) + j = max(0, self.maxstring-3-i) + s = builtins.repr(x[:i] + x[len(x)-j:]) + s = s[:i] + '...' + s[len(s)-j:] + return s + + def repr_int(self, x, level): + s = builtins.repr(x) # XXX Hope this isn't too slow... + if len(s) > self.maxlong: + i = max(0, (self.maxlong-3)//2) + j = max(0, self.maxlong-3-i) + s = s[:i] + '...' + s[len(s)-j:] + return s + + def repr_instance(self, x, level): + try: + s = builtins.repr(x) + # Bugs in x.__repr__() can cause arbitrary + # exceptions -- then make up something + except Exception: + return '<%s instance at %#x>' % (x.__class__.__name__, id(x)) + if len(s) > self.maxother: + i = max(0, (self.maxother-3)//2) + j = max(0, self.maxother-3-i) + s = s[:i] + '...' + s[len(s)-j:] + return s + + +def _possibly_sorted(x): + # Since not all sequences of items can be sorted and comparison + # functions may raise arbitrary exceptions, return an unsorted + # sequence in that case. + try: + return sorted(x) + except Exception: + return list(x) + +aRepr = Repr() +repr = aRepr.repr diff --git a/winvenv/Lib/rlcompleter.py b/winvenv/Lib/rlcompleter.py new file mode 100644 index 0000000..bca4a7b --- /dev/null +++ b/winvenv/Lib/rlcompleter.py @@ -0,0 +1,205 @@ +"""Word completion for GNU readline. + +The completer completes keywords, built-ins and globals in a selectable +namespace (which defaults to __main__); when completing NAME.NAME..., it +evaluates (!) the expression up to the last dot and completes its attributes. + +It's very cool to do "import sys" type "sys.", hit the completion key (twice), +and see the list of names defined by the sys module! + +Tip: to use the tab key as the completion key, call + + readline.parse_and_bind("tab: complete") + +Notes: + +- Exceptions raised by the completer function are *ignored* (and generally cause + the completion to fail). This is a feature -- since readline sets the tty + device in raw (or cbreak) mode, printing a traceback wouldn't work well + without some complicated hoopla to save, reset and restore the tty state. + +- The evaluation of the NAME.NAME... form may cause arbitrary application + defined code to be executed if an object with a __getattr__ hook is found. + Since it is the responsibility of the application (or the user) to enable this + feature, I consider this an acceptable risk. More complicated expressions + (e.g. function calls or indexing operations) are *not* evaluated. + +- When the original stdin is not a tty device, GNU readline is never + used, and this module (and the readline module) are silently inactive. + +""" + +import atexit +import builtins +import __main__ + +__all__ = ["Completer"] + +class Completer: + def __init__(self, namespace = None): + """Create a new completer for the command line. + + Completer([namespace]) -> completer instance. + + If unspecified, the default namespace where completions are performed + is __main__ (technically, __main__.__dict__). Namespaces should be + given as dictionaries. + + Completer instances should be used as the completion mechanism of + readline via the set_completer() call: + + readline.set_completer(Completer(my_namespace).complete) + """ + + if namespace and not isinstance(namespace, dict): + raise TypeError('namespace must be a dictionary') + + # Don't bind to namespace quite yet, but flag whether the user wants a + # specific namespace or to use __main__.__dict__. This will allow us + # to bind to __main__.__dict__ at completion time, not now. + if namespace is None: + self.use_main_ns = 1 + else: + self.use_main_ns = 0 + self.namespace = namespace + + def complete(self, text, state): + """Return the next possible completion for 'text'. + + This is called successively with state == 0, 1, 2, ... until it + returns None. The completion should begin with 'text'. + + """ + if self.use_main_ns: + self.namespace = __main__.__dict__ + + if not text.strip(): + if state == 0: + if _readline_available: + readline.insert_text('\t') + readline.redisplay() + return '' + else: + return '\t' + else: + return None + + if state == 0: + if "." in text: + self.matches = self.attr_matches(text) + else: + self.matches = self.global_matches(text) + try: + return self.matches[state] + except IndexError: + return None + + def _callable_postfix(self, val, word): + if callable(val): + word = word + "(" + return word + + def global_matches(self, text): + """Compute matches when text is a simple name. + + Return a list of all keywords, built-in functions and names currently + defined in self.namespace that match. + + """ + import keyword + matches = [] + seen = {"__builtins__"} + n = len(text) + for word in keyword.kwlist: + if word[:n] == text: + seen.add(word) + if word in {'finally', 'try'}: + word = word + ':' + elif word not in {'False', 'None', 'True', + 'break', 'continue', 'pass', + 'else'}: + word = word + ' ' + matches.append(word) + for nspace in [self.namespace, builtins.__dict__]: + for word, val in nspace.items(): + if word[:n] == text and word not in seen: + seen.add(word) + matches.append(self._callable_postfix(val, word)) + return matches + + def attr_matches(self, text): + """Compute matches when text contains a dot. + + Assuming the text is of the form NAME.NAME....[NAME], and is + evaluable in self.namespace, it will be evaluated and its attributes + (as revealed by dir()) are used as possible completions. (For class + instances, class members are also considered.) + + WARNING: this can still invoke arbitrary C code, if an object + with a __getattr__ hook is evaluated. + + """ + import re + m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text) + if not m: + return [] + expr, attr = m.group(1, 3) + try: + thisobject = eval(expr, self.namespace) + except Exception: + return [] + + # get the content of the object, except __builtins__ + words = set(dir(thisobject)) + words.discard("__builtins__") + + if hasattr(thisobject, '__class__'): + words.add('__class__') + words.update(get_class_members(thisobject.__class__)) + matches = [] + n = len(attr) + if attr == '': + noprefix = '_' + elif attr == '_': + noprefix = '__' + else: + noprefix = None + while True: + for word in words: + if (word[:n] == attr and + not (noprefix and word[:n+1] == noprefix)): + match = "%s.%s" % (expr, word) + try: + val = getattr(thisobject, word) + except Exception: + pass # Include even if attribute not set + else: + match = self._callable_postfix(val, match) + matches.append(match) + if matches or not noprefix: + break + if noprefix == '_': + noprefix = '__' + else: + noprefix = None + matches.sort() + return matches + +def get_class_members(klass): + ret = dir(klass) + if hasattr(klass,'__bases__'): + for base in klass.__bases__: + ret = ret + get_class_members(base) + return ret + +try: + import readline +except ImportError: + _readline_available = False +else: + readline.set_completer(Completer().complete) + # Release references early at shutdown (the readline module's + # contents are quasi-immortal, and the completer function holds a + # reference to globals). + atexit.register(lambda: readline.set_completer(None)) + _readline_available = True diff --git a/winvenv/Lib/shutil.py b/winvenv/Lib/shutil.py new file mode 100644 index 0000000..3c02776 --- /dev/null +++ b/winvenv/Lib/shutil.py @@ -0,0 +1,1169 @@ +"""Utility functions for copying and archiving files and directory trees. + +XXX The functions here don't copy the resource fork or other metadata on Mac. + +""" + +import os +import sys +import stat +import fnmatch +import collections +import errno + +try: + import zlib + del zlib + _ZLIB_SUPPORTED = True +except ImportError: + _ZLIB_SUPPORTED = False + +try: + import bz2 + del bz2 + _BZ2_SUPPORTED = True +except ImportError: + _BZ2_SUPPORTED = False + +try: + import lzma + del lzma + _LZMA_SUPPORTED = True +except ImportError: + _LZMA_SUPPORTED = False + +try: + from pwd import getpwnam +except ImportError: + getpwnam = None + +try: + from grp import getgrnam +except ImportError: + getgrnam = None + +__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", + "copytree", "move", "rmtree", "Error", "SpecialFileError", + "ExecError", "make_archive", "get_archive_formats", + "register_archive_format", "unregister_archive_format", + "get_unpack_formats", "register_unpack_format", + "unregister_unpack_format", "unpack_archive", + "ignore_patterns", "chown", "which", "get_terminal_size", + "SameFileError"] + # disk_usage is added later, if available on the platform + +class Error(OSError): + pass + +class SameFileError(Error): + """Raised when source and destination are the same file.""" + +class SpecialFileError(OSError): + """Raised when trying to do a kind of operation (e.g. copying) which is + not supported on a special file (e.g. a named pipe)""" + +class ExecError(OSError): + """Raised when a command could not be executed""" + +class ReadError(OSError): + """Raised when an archive cannot be read""" + +class RegistryError(Exception): + """Raised when a registry operation with the archiving + and unpacking registries fails""" + + +def copyfileobj(fsrc, fdst, length=16*1024): + """copy data from file-like object fsrc to file-like object fdst""" + while 1: + buf = fsrc.read(length) + if not buf: + break + fdst.write(buf) + +def _samefile(src, dst): + # Macintosh, Unix. + if hasattr(os.path, 'samefile'): + try: + return os.path.samefile(src, dst) + except OSError: + return False + + # All other platforms: check for same pathname. + return (os.path.normcase(os.path.abspath(src)) == + os.path.normcase(os.path.abspath(dst))) + +def copyfile(src, dst, *, follow_symlinks=True): + """Copy data from src to dst. + + If follow_symlinks is not set and src is a symbolic link, a new + symlink will be created instead of copying the file it points to. + + """ + if _samefile(src, dst): + raise SameFileError("{!r} and {!r} are the same file".format(src, dst)) + + for fn in [src, dst]: + try: + st = os.stat(fn) + except OSError: + # File most likely does not exist + pass + else: + # XXX What about other special files? (sockets, devices...) + if stat.S_ISFIFO(st.st_mode): + raise SpecialFileError("`%s` is a named pipe" % fn) + + if not follow_symlinks and os.path.islink(src): + os.symlink(os.readlink(src), dst) + else: + with open(src, 'rb') as fsrc: + with open(dst, 'wb') as fdst: + copyfileobj(fsrc, fdst) + return dst + +def copymode(src, dst, *, follow_symlinks=True): + """Copy mode bits from src to dst. + + If follow_symlinks is not set, symlinks aren't followed if and only + if both `src` and `dst` are symlinks. If `lchmod` isn't available + (e.g. Linux) this method does nothing. + + """ + if not follow_symlinks and os.path.islink(src) and os.path.islink(dst): + if hasattr(os, 'lchmod'): + stat_func, chmod_func = os.lstat, os.lchmod + else: + return + elif hasattr(os, 'chmod'): + stat_func, chmod_func = os.stat, os.chmod + else: + return + + st = stat_func(src) + chmod_func(dst, stat.S_IMODE(st.st_mode)) + +if hasattr(os, 'listxattr'): + def _copyxattr(src, dst, *, follow_symlinks=True): + """Copy extended filesystem attributes from `src` to `dst`. + + Overwrite existing attributes. + + If `follow_symlinks` is false, symlinks won't be followed. + + """ + + try: + names = os.listxattr(src, follow_symlinks=follow_symlinks) + except OSError as e: + if e.errno not in (errno.ENOTSUP, errno.ENODATA): + raise + return + for name in names: + try: + value = os.getxattr(src, name, follow_symlinks=follow_symlinks) + os.setxattr(dst, name, value, follow_symlinks=follow_symlinks) + except OSError as e: + if e.errno not in (errno.EPERM, errno.ENOTSUP, errno.ENODATA): + raise +else: + def _copyxattr(*args, **kwargs): + pass + +def copystat(src, dst, *, follow_symlinks=True): + """Copy all stat info (mode bits, atime, mtime, flags) from src to dst. + + If the optional flag `follow_symlinks` is not set, symlinks aren't followed if and + only if both `src` and `dst` are symlinks. + + """ + def _nop(*args, ns=None, follow_symlinks=None): + pass + + # follow symlinks (aka don't not follow symlinks) + follow = follow_symlinks or not (os.path.islink(src) and os.path.islink(dst)) + if follow: + # use the real function if it exists + def lookup(name): + return getattr(os, name, _nop) + else: + # use the real function only if it exists + # *and* it supports follow_symlinks + def lookup(name): + fn = getattr(os, name, _nop) + if fn in os.supports_follow_symlinks: + return fn + return _nop + + st = lookup("stat")(src, follow_symlinks=follow) + mode = stat.S_IMODE(st.st_mode) + lookup("utime")(dst, ns=(st.st_atime_ns, st.st_mtime_ns), + follow_symlinks=follow) + try: + lookup("chmod")(dst, mode, follow_symlinks=follow) + except NotImplementedError: + # if we got a NotImplementedError, it's because + # * follow_symlinks=False, + # * lchown() is unavailable, and + # * either + # * fchownat() is unavailable or + # * fchownat() doesn't implement AT_SYMLINK_NOFOLLOW. + # (it returned ENOSUP.) + # therefore we're out of options--we simply cannot chown the + # symlink. give up, suppress the error. + # (which is what shutil always did in this circumstance.) + pass + if hasattr(st, 'st_flags'): + try: + lookup("chflags")(dst, st.st_flags, follow_symlinks=follow) + except OSError as why: + for err in 'EOPNOTSUPP', 'ENOTSUP': + if hasattr(errno, err) and why.errno == getattr(errno, err): + break + else: + raise + _copyxattr(src, dst, follow_symlinks=follow) + +def copy(src, dst, *, follow_symlinks=True): + """Copy data and mode bits ("cp src dst"). Return the file's destination. + + The destination may be a directory. + + If follow_symlinks is false, symlinks won't be followed. This + resembles GNU's "cp -P src dst". + + If source and destination are the same file, a SameFileError will be + raised. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst, follow_symlinks=follow_symlinks) + copymode(src, dst, follow_symlinks=follow_symlinks) + return dst + +def copy2(src, dst, *, follow_symlinks=True): + """Copy data and all stat info ("cp -p src dst"). Return the file's + destination." + + The destination may be a directory. + + If follow_symlinks is false, symlinks won't be followed. This + resembles GNU's "cp -P src dst". + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst, follow_symlinks=follow_symlinks) + copystat(src, dst, follow_symlinks=follow_symlinks) + return dst + +def ignore_patterns(*patterns): + """Function that can be used as copytree() ignore parameter. + + Patterns is a sequence of glob-style patterns + that are used to exclude files""" + def _ignore_patterns(path, names): + ignored_names = [] + for pattern in patterns: + ignored_names.extend(fnmatch.filter(names, pattern)) + return set(ignored_names) + return _ignore_patterns + +def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, + ignore_dangling_symlinks=False): + """Recursively copy a directory tree. + + The destination directory must not already exist. + If exception(s) occur, an Error is raised with a list of reasons. + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. If the file pointed by the symlink doesn't + exist, an exception will be added in the list of errors raised in + an Error exception at the end of the copy process. + + You can set the optional ignore_dangling_symlinks flag to true if you + want to silence this exception. Notice that this has no effect on + platforms that don't support os.symlink. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + The optional copy_function argument is a callable that will be used + to copy each file. It will be called with the source path and the + destination path as arguments. By default, copy2() is used, but any + function that supports the same signature (like copy()) can be used. + + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if os.path.islink(srcname): + linkto = os.readlink(srcname) + if symlinks: + # We can't just leave it to `copy_function` because legacy + # code with a custom `copy_function` may rely on copytree + # doing the right thing. + os.symlink(linkto, dstname) + copystat(srcname, dstname, follow_symlinks=not symlinks) + else: + # ignore dangling symlink if the flag is on + if not os.path.exists(linkto) and ignore_dangling_symlinks: + continue + # otherwise let the copy occurs. copy2 will raise an error + if os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, + copy_function) + else: + copy_function(srcname, dstname) + elif os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, copy_function) + else: + # Will raise a SpecialFileError for unsupported file types + copy_function(srcname, dstname) + # catch the Error from the recursive copytree so that we can + # continue with other files + except Error as err: + errors.extend(err.args[0]) + except OSError as why: + errors.append((srcname, dstname, str(why))) + try: + copystat(src, dst) + except OSError as why: + # Copying file access times may fail on Windows + if getattr(why, 'winerror', None) is None: + errors.append((src, dst, str(why))) + if errors: + raise Error(errors) + return dst + +# version vulnerable to race conditions +def _rmtree_unsafe(path, onerror): + try: + with os.scandir(path) as scandir_it: + entries = list(scandir_it) + except OSError: + onerror(os.scandir, path, sys.exc_info()) + entries = [] + for entry in entries: + fullname = entry.path + try: + is_dir = entry.is_dir(follow_symlinks=False) + except OSError: + is_dir = False + if is_dir: + try: + if entry.is_symlink(): + # This can only happen if someone replaces + # a directory with a symlink after the call to + # os.scandir or entry.is_dir above. + raise OSError("Cannot call rmtree on a symbolic link") + except OSError: + onerror(os.path.islink, fullname, sys.exc_info()) + continue + _rmtree_unsafe(fullname, onerror) + else: + try: + os.unlink(fullname) + except OSError: + onerror(os.unlink, fullname, sys.exc_info()) + try: + os.rmdir(path) + except OSError: + onerror(os.rmdir, path, sys.exc_info()) + +# Version using fd-based APIs to protect against races +def _rmtree_safe_fd(topfd, path, onerror): + try: + with os.scandir(topfd) as scandir_it: + entries = list(scandir_it) + except OSError as err: + err.filename = path + onerror(os.scandir, path, sys.exc_info()) + return + for entry in entries: + fullname = os.path.join(path, entry.name) + try: + is_dir = entry.is_dir(follow_symlinks=False) + if is_dir: + orig_st = entry.stat(follow_symlinks=False) + is_dir = stat.S_ISDIR(orig_st.st_mode) + except OSError: + is_dir = False + if is_dir: + try: + dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd) + except OSError: + onerror(os.open, fullname, sys.exc_info()) + else: + try: + if os.path.samestat(orig_st, os.fstat(dirfd)): + _rmtree_safe_fd(dirfd, fullname, onerror) + try: + os.rmdir(entry.name, dir_fd=topfd) + except OSError: + onerror(os.rmdir, fullname, sys.exc_info()) + else: + try: + # This can only happen if someone replaces + # a directory with a symlink after the call to + # os.scandir or stat.S_ISDIR above. + raise OSError("Cannot call rmtree on a symbolic " + "link") + except OSError: + onerror(os.path.islink, fullname, sys.exc_info()) + finally: + os.close(dirfd) + else: + try: + os.unlink(entry.name, dir_fd=topfd) + except OSError: + onerror(os.unlink, fullname, sys.exc_info()) + +_use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <= + os.supports_dir_fd and + os.scandir in os.supports_fd and + os.stat in os.supports_follow_symlinks) + +def rmtree(path, ignore_errors=False, onerror=None): + """Recursively delete a directory tree. + + If ignore_errors is set, errors are ignored; otherwise, if onerror + is set, it is called to handle the error with arguments (func, + path, exc_info) where func is platform and implementation dependent; + path is the argument to that function that caused it to fail; and + exc_info is a tuple returned by sys.exc_info(). If ignore_errors + is false and onerror is None, an exception is raised. + + """ + if ignore_errors: + def onerror(*args): + pass + elif onerror is None: + def onerror(*args): + raise + if _use_fd_functions: + # While the unsafe rmtree works fine on bytes, the fd based does not. + if isinstance(path, bytes): + path = os.fsdecode(path) + # Note: To guard against symlink races, we use the standard + # lstat()/open()/fstat() trick. + try: + orig_st = os.lstat(path) + except Exception: + onerror(os.lstat, path, sys.exc_info()) + return + try: + fd = os.open(path, os.O_RDONLY) + except Exception: + onerror(os.lstat, path, sys.exc_info()) + return + try: + if os.path.samestat(orig_st, os.fstat(fd)): + _rmtree_safe_fd(fd, path, onerror) + try: + os.rmdir(path) + except OSError: + onerror(os.rmdir, path, sys.exc_info()) + else: + try: + # symlinks to directories are forbidden, see bug #1669 + raise OSError("Cannot call rmtree on a symbolic link") + except OSError: + onerror(os.path.islink, path, sys.exc_info()) + finally: + os.close(fd) + else: + try: + if os.path.islink(path): + # symlinks to directories are forbidden, see bug #1669 + raise OSError("Cannot call rmtree on a symbolic link") + except OSError: + onerror(os.path.islink, path, sys.exc_info()) + # can't continue even if onerror hook returns + return + return _rmtree_unsafe(path, onerror) + +# Allow introspection of whether or not the hardening against symlink +# attacks is supported on the current platform +rmtree.avoids_symlink_attacks = _use_fd_functions + +def _basename(path): + # A basename() variant which first strips the trailing slash, if present. + # Thus we always get the last component of the path, even for directories. + sep = os.path.sep + (os.path.altsep or '') + return os.path.basename(path.rstrip(sep)) + +def move(src, dst, copy_function=copy2): + """Recursively move a file or directory to another location. This is + similar to the Unix "mv" command. Return the file or directory's + destination. + + If the destination is a directory or a symlink to a directory, the source + is moved inside the directory. The destination path must not already + exist. + + If the destination already exists but is not a directory, it may be + overwritten depending on os.rename() semantics. + + If the destination is on our current filesystem, then rename() is used. + Otherwise, src is copied to the destination and then removed. Symlinks are + recreated under the new name if os.rename() fails because of cross + filesystem renames. + + The optional `copy_function` argument is a callable that will be used + to copy the source or it will be delegated to `copytree`. + By default, copy2() is used, but any function that supports the same + signature (like copy()) can be used. + + A lot more could be done here... A look at a mv.c shows a lot of + the issues this implementation glosses over. + + """ + real_dst = dst + if os.path.isdir(dst): + if _samefile(src, dst): + # We might be on a case insensitive filesystem, + # perform the rename anyway. + os.rename(src, dst) + return + + real_dst = os.path.join(dst, _basename(src)) + if os.path.exists(real_dst): + raise Error("Destination path '%s' already exists" % real_dst) + try: + os.rename(src, real_dst) + except OSError: + if os.path.islink(src): + linkto = os.readlink(src) + os.symlink(linkto, real_dst) + os.unlink(src) + elif os.path.isdir(src): + if _destinsrc(src, dst): + raise Error("Cannot move a directory '%s' into itself" + " '%s'." % (src, dst)) + copytree(src, real_dst, copy_function=copy_function, + symlinks=True) + rmtree(src) + else: + copy_function(src, real_dst) + os.unlink(src) + return real_dst + +def _destinsrc(src, dst): + src = os.path.abspath(src) + dst = os.path.abspath(dst) + if not src.endswith(os.path.sep): + src += os.path.sep + if not dst.endswith(os.path.sep): + dst += os.path.sep + return dst.startswith(src) + +def _get_gid(name): + """Returns a gid, given a group name.""" + if getgrnam is None or name is None: + return None + try: + result = getgrnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _get_uid(name): + """Returns an uid, given a user name.""" + if getpwnam is None or name is None: + return None + try: + result = getpwnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, + owner=None, group=None, logger=None): + """Create a (possibly compressed) tar file from all the files under + 'base_dir'. + + 'compress' must be "gzip" (the default), "bzip2", "xz", or None. + + 'owner' and 'group' can be used to define an owner and a group for the + archive that is being built. If not provided, the current owner and group + will be used. + + The output tar file will be named 'base_name' + ".tar", possibly plus + the appropriate compression extension (".gz", ".bz2", or ".xz"). + + Returns the output filename. + """ + if compress is None: + tar_compression = '' + elif _ZLIB_SUPPORTED and compress == 'gzip': + tar_compression = 'gz' + elif _BZ2_SUPPORTED and compress == 'bzip2': + tar_compression = 'bz2' + elif _LZMA_SUPPORTED and compress == 'xz': + tar_compression = 'xz' + else: + raise ValueError("bad value for 'compress', or compression format not " + "supported : {0}".format(compress)) + + import tarfile # late import for breaking circular dependency + + compress_ext = '.' + tar_compression if compress else '' + archive_name = base_name + '.tar' + compress_ext + archive_dir = os.path.dirname(archive_name) + + if archive_dir and not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # creating the tarball + if logger is not None: + logger.info('Creating tar archive') + + uid = _get_uid(owner) + gid = _get_gid(group) + + def _set_uid_gid(tarinfo): + if gid is not None: + tarinfo.gid = gid + tarinfo.gname = group + if uid is not None: + tarinfo.uid = uid + tarinfo.uname = owner + return tarinfo + + if not dry_run: + tar = tarfile.open(archive_name, 'w|%s' % tar_compression) + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + return archive_name + +def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): + """Create a zip file from all the files under 'base_dir'. + + The output zip file will be named 'base_name' + ".zip". Returns the + name of the output zip file. + """ + import zipfile # late import for breaking circular dependency + + zip_filename = base_name + ".zip" + archive_dir = os.path.dirname(base_name) + + if archive_dir and not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + if logger is not None: + logger.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + with zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) as zf: + path = os.path.normpath(base_dir) + if path != os.curdir: + zf.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in sorted(dirnames): + path = os.path.normpath(os.path.join(dirpath, name)) + zf.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zf.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + + return zip_filename + +_ARCHIVE_FORMATS = { + 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), +} + +if _ZLIB_SUPPORTED: + _ARCHIVE_FORMATS['gztar'] = (_make_tarball, [('compress', 'gzip')], + "gzip'ed tar-file") + _ARCHIVE_FORMATS['zip'] = (_make_zipfile, [], "ZIP file") + +if _BZ2_SUPPORTED: + _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], + "bzip2'ed tar-file") + +if _LZMA_SUPPORTED: + _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')], + "xz'ed tar-file") + +def get_archive_formats(): + """Returns a list of supported formats for archiving and unarchiving. + + Each element of the returned sequence is a tuple (name, description) + """ + formats = [(name, registry[2]) for name, registry in + _ARCHIVE_FORMATS.items()] + formats.sort() + return formats + +def register_archive_format(name, function, extra_args=None, description=''): + """Registers an archive format. + + name is the name of the format. function is the callable that will be + used to create archives. If provided, extra_args is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_archive_formats() function. + """ + if extra_args is None: + extra_args = [] + if not callable(function): + raise TypeError('The %s object is not callable' % function) + if not isinstance(extra_args, (tuple, list)): + raise TypeError('extra_args needs to be a sequence') + for element in extra_args: + if not isinstance(element, (tuple, list)) or len(element) !=2: + raise TypeError('extra_args elements are : (arg_name, value)') + + _ARCHIVE_FORMATS[name] = (function, extra_args, description) + +def unregister_archive_format(name): + del _ARCHIVE_FORMATS[name] + +def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, + dry_run=0, owner=None, group=None, logger=None): + """Create an archive file (eg. zip or tar). + + 'base_name' is the name of the file to create, minus any format-specific + extension; 'format' is the archive format: one of "zip", "tar", "gztar", + "bztar", or "xztar". Or any other registered format. + + 'root_dir' is a directory that will be the root directory of the + archive; ie. we typically chdir into 'root_dir' before creating the + archive. 'base_dir' is the directory where we start archiving from; + ie. 'base_dir' will be the common prefix of all files and + directories in the archive. 'root_dir' and 'base_dir' both default + to the current directory. Returns the name of the archive file. + + 'owner' and 'group' are used when creating a tar archive. By default, + uses the current owner and group. + """ + save_cwd = os.getcwd() + if root_dir is not None: + if logger is not None: + logger.debug("changing into '%s'", root_dir) + base_name = os.path.abspath(base_name) + if not dry_run: + os.chdir(root_dir) + + if base_dir is None: + base_dir = os.curdir + + kwargs = {'dry_run': dry_run, 'logger': logger} + + try: + format_info = _ARCHIVE_FORMATS[format] + except KeyError: + raise ValueError("unknown archive format '%s'" % format) from None + + func = format_info[0] + for arg, val in format_info[1]: + kwargs[arg] = val + + if format != 'zip': + kwargs['owner'] = owner + kwargs['group'] = group + + try: + filename = func(base_name, base_dir, **kwargs) + finally: + if root_dir is not None: + if logger is not None: + logger.debug("changing back to '%s'", save_cwd) + os.chdir(save_cwd) + + return filename + + +def get_unpack_formats(): + """Returns a list of supported formats for unpacking. + + Each element of the returned sequence is a tuple + (name, extensions, description) + """ + formats = [(name, info[0], info[3]) for name, info in + _UNPACK_FORMATS.items()] + formats.sort() + return formats + +def _check_unpack_options(extensions, function, extra_args): + """Checks what gets registered as an unpacker.""" + # first make sure no other unpacker is registered for this extension + existing_extensions = {} + for name, info in _UNPACK_FORMATS.items(): + for ext in info[0]: + existing_extensions[ext] = name + + for extension in extensions: + if extension in existing_extensions: + msg = '%s is already registered for "%s"' + raise RegistryError(msg % (extension, + existing_extensions[extension])) + + if not callable(function): + raise TypeError('The registered function must be a callable') + + +def register_unpack_format(name, extensions, function, extra_args=None, + description=''): + """Registers an unpack format. + + `name` is the name of the format. `extensions` is a list of extensions + corresponding to the format. + + `function` is the callable that will be + used to unpack archives. The callable will receive archives to unpack. + If it's unable to handle an archive, it needs to raise a ReadError + exception. + + If provided, `extra_args` is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_unpack_formats() function. + """ + if extra_args is None: + extra_args = [] + _check_unpack_options(extensions, function, extra_args) + _UNPACK_FORMATS[name] = extensions, function, extra_args, description + +def unregister_unpack_format(name): + """Removes the pack format from the registry.""" + del _UNPACK_FORMATS[name] + +def _ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + +def _unpack_zipfile(filename, extract_dir): + """Unpack zip `filename` to `extract_dir` + """ + import zipfile # late import for breaking circular dependency + + if not zipfile.is_zipfile(filename): + raise ReadError("%s is not a zip file" % filename) + + zip = zipfile.ZipFile(filename) + try: + for info in zip.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name: + continue + + target = os.path.join(extract_dir, *name.split('/')) + if not target: + continue + + _ensure_directory(target) + if not name.endswith('/'): + # file + data = zip.read(info.filename) + f = open(target, 'wb') + try: + f.write(data) + finally: + f.close() + del data + finally: + zip.close() + +def _unpack_tarfile(filename, extract_dir): + """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir` + """ + import tarfile # late import for breaking circular dependency + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise ReadError( + "%s is not a compressed or uncompressed tar file" % filename) + try: + tarobj.extractall(extract_dir) + finally: + tarobj.close() + +_UNPACK_FORMATS = { + 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), + 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file"), +} + +if _ZLIB_SUPPORTED: + _UNPACK_FORMATS['gztar'] = (['.tar.gz', '.tgz'], _unpack_tarfile, [], + "gzip'ed tar-file") + +if _BZ2_SUPPORTED: + _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [], + "bzip2'ed tar-file") + +if _LZMA_SUPPORTED: + _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [], + "xz'ed tar-file") + +def _find_unpack_format(filename): + for name, info in _UNPACK_FORMATS.items(): + for extension in info[0]: + if filename.endswith(extension): + return name + return None + +def unpack_archive(filename, extract_dir=None, format=None): + """Unpack an archive. + + `filename` is the name of the archive. + + `extract_dir` is the name of the target directory, where the archive + is unpacked. If not provided, the current working directory is used. + + `format` is the archive format: one of "zip", "tar", "gztar", "bztar", + or "xztar". Or any other registered format. If not provided, + unpack_archive will use the filename extension and see if an unpacker + was registered for that extension. + + In case none is found, a ValueError is raised. + """ + if extract_dir is None: + extract_dir = os.getcwd() + + extract_dir = os.fspath(extract_dir) + filename = os.fspath(filename) + + if format is not None: + try: + format_info = _UNPACK_FORMATS[format] + except KeyError: + raise ValueError("Unknown unpack format '{0}'".format(format)) from None + + func = format_info[1] + func(filename, extract_dir, **dict(format_info[2])) + else: + # we need to look at the registered unpackers supported extensions + format = _find_unpack_format(filename) + if format is None: + raise ReadError("Unknown archive format '{0}'".format(filename)) + + func = _UNPACK_FORMATS[format][1] + kwargs = dict(_UNPACK_FORMATS[format][2]) + func(filename, extract_dir, **kwargs) + + +if hasattr(os, 'statvfs'): + + __all__.append('disk_usage') + _ntuple_diskusage = collections.namedtuple('usage', 'total used free') + _ntuple_diskusage.total.__doc__ = 'Total space in bytes' + _ntuple_diskusage.used.__doc__ = 'Used space in bytes' + _ntuple_diskusage.free.__doc__ = 'Free space in bytes' + + def disk_usage(path): + """Return disk usage statistics about the given path. + + Returned value is a named tuple with attributes 'total', 'used' and + 'free', which are the amount of total, used and free space, in bytes. + """ + st = os.statvfs(path) + free = st.f_bavail * st.f_frsize + total = st.f_blocks * st.f_frsize + used = (st.f_blocks - st.f_bfree) * st.f_frsize + return _ntuple_diskusage(total, used, free) + +elif os.name == 'nt': + + import nt + __all__.append('disk_usage') + _ntuple_diskusage = collections.namedtuple('usage', 'total used free') + + def disk_usage(path): + """Return disk usage statistics about the given path. + + Returned values is a named tuple with attributes 'total', 'used' and + 'free', which are the amount of total, used and free space, in bytes. + """ + total, free = nt._getdiskusage(path) + used = total - free + return _ntuple_diskusage(total, used, free) + + +def chown(path, user=None, group=None): + """Change owner user and group of the given path. + + user and group can be the uid/gid or the user/group names, and in that case, + they are converted to their respective uid/gid. + """ + + if user is None and group is None: + raise ValueError("user and/or group must be set") + + _user = user + _group = group + + # -1 means don't change it + if user is None: + _user = -1 + # user can either be an int (the uid) or a string (the system username) + elif isinstance(user, str): + _user = _get_uid(user) + if _user is None: + raise LookupError("no such user: {!r}".format(user)) + + if group is None: + _group = -1 + elif not isinstance(group, int): + _group = _get_gid(group) + if _group is None: + raise LookupError("no such group: {!r}".format(group)) + + os.chown(path, _user, _group) + +def get_terminal_size(fallback=(80, 24)): + """Get the size of the terminal window. + + For each of the two dimensions, the environment variable, COLUMNS + and LINES respectively, is checked. If the variable is defined and + the value is a positive integer, it is used. + + When COLUMNS or LINES is not defined, which is the common case, + the terminal connected to sys.__stdout__ is queried + by invoking os.get_terminal_size. + + If the terminal size cannot be successfully queried, either because + the system doesn't support querying, or because we are not + connected to a terminal, the value given in fallback parameter + is used. Fallback defaults to (80, 24) which is the default + size used by many terminal emulators. + + The value returned is a named tuple of type os.terminal_size. + """ + # columns, lines are the working values + try: + columns = int(os.environ['COLUMNS']) + except (KeyError, ValueError): + columns = 0 + + try: + lines = int(os.environ['LINES']) + except (KeyError, ValueError): + lines = 0 + + # only query if necessary + if columns <= 0 or lines <= 0: + try: + size = os.get_terminal_size(sys.__stdout__.fileno()) + except (AttributeError, ValueError, OSError): + # stdout is None, closed, detached, or not a terminal, or + # os.get_terminal_size() is unsupported + size = os.terminal_size(fallback) + if columns <= 0: + columns = size.columns + if lines <= 0: + lines = size.lines + + return os.terminal_size((columns, lines)) + +def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if not os.curdir in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None diff --git a/winvenv/Lib/site-packages/easy_install.py b/winvenv/Lib/site-packages/easy_install.py new file mode 100644 index 0000000..d87e984 --- /dev/null +++ b/winvenv/Lib/site-packages/easy_install.py @@ -0,0 +1,5 @@ +"""Run the EasyInstall command""" + +if __name__ == '__main__': + from setuptools.command.easy_install import main + main() diff --git a/winvenv/Lib/site-packages/google/protobuf/__init__.py b/winvenv/Lib/site-packages/google/protobuf/__init__.py new file mode 100644 index 0000000..249e18a --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/__init__.py @@ -0,0 +1,39 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# Copyright 2007 Google Inc. All Rights Reserved. + +__version__ = '3.6.1' + +if __name__ != '__main__': + try: + __import__('pkg_resources').declare_namespace(__name__) + except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/winvenv/Lib/site-packages/google/protobuf/any_pb2.py b/winvenv/Lib/site-packages/google/protobuf/any_pb2.py new file mode 100644 index 0000000..56291e8 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/any_pb2.py @@ -0,0 +1,77 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/any.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/any.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\010AnyProtoP\001Z%github.com/golang/protobuf/ptypes/any\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x19google/protobuf/any.proto\x12\x0fgoogle.protobuf\"&\n\x03\x41ny\x12\x10\n\x08type_url\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\x42o\n\x13\x63om.google.protobufB\x08\x41nyProtoP\x01Z%github.com/golang/protobuf/ptypes/any\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_ANY = _descriptor.Descriptor( + name='Any', + full_name='google.protobuf.Any', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type_url', full_name='google.protobuf.Any.type_url', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Any.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=46, + serialized_end=84, +) + +DESCRIPTOR.message_types_by_name['Any'] = _ANY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Any = _reflection.GeneratedProtocolMessageType('Any', (_message.Message,), dict( + DESCRIPTOR = _ANY, + __module__ = 'google.protobuf.any_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Any) + )) +_sym_db.RegisterMessage(Any) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/any_test_pb2.py b/winvenv/Lib/site-packages/google/protobuf/any_test_pb2.py new file mode 100644 index 0000000..843113b --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/any_test_pb2.py @@ -0,0 +1,87 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/any_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/any_test.proto', + package='protobuf_unittest', + syntax='proto3', + serialized_options=None, + serialized_pb=_b('\n\x1egoogle/protobuf/any_test.proto\x12\x11protobuf_unittest\x1a\x19google/protobuf/any.proto\"y\n\x07TestAny\x12\x13\n\x0bint32_value\x18\x01 \x01(\x05\x12\'\n\tany_value\x18\x02 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x30\n\x12repeated_any_value\x18\x03 \x03(\x0b\x32\x14.google.protobuf.Anyb\x06proto3') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,]) + + + + +_TESTANY = _descriptor.Descriptor( + name='TestAny', + full_name='protobuf_unittest.TestAny', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='int32_value', full_name='protobuf_unittest.TestAny.int32_value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='any_value', full_name='protobuf_unittest.TestAny.any_value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_any_value', full_name='protobuf_unittest.TestAny.repeated_any_value', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=80, + serialized_end=201, +) + +_TESTANY.fields_by_name['any_value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTANY.fields_by_name['repeated_any_value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +DESCRIPTOR.message_types_by_name['TestAny'] = _TESTANY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAny = _reflection.GeneratedProtocolMessageType('TestAny', (_message.Message,), dict( + DESCRIPTOR = _TESTANY, + __module__ = 'google.protobuf.any_test_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAny) + )) +_sym_db.RegisterMessage(TestAny) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/api_pb2.py b/winvenv/Lib/site-packages/google/protobuf/api_pb2.py new file mode 100644 index 0000000..41f4e62 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/api_pb2.py @@ -0,0 +1,249 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/api.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import source_context_pb2 as google_dot_protobuf_dot_source__context__pb2 +from google.protobuf import type_pb2 as google_dot_protobuf_dot_type__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/api.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\010ApiProtoP\001Z+google.golang.org/genproto/protobuf/api;api\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x19google/protobuf/api.proto\x12\x0fgoogle.protobuf\x1a$google/protobuf/source_context.proto\x1a\x1agoogle/protobuf/type.proto\"\x81\x02\n\x03\x41pi\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x07methods\x18\x02 \x03(\x0b\x32\x17.google.protobuf.Method\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x36\n\x0esource_context\x18\x05 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12&\n\x06mixins\x18\x06 \x03(\x0b\x32\x16.google.protobuf.Mixin\x12\'\n\x06syntax\x18\x07 \x01(\x0e\x32\x17.google.protobuf.Syntax\"\xd5\x01\n\x06Method\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10request_type_url\x18\x02 \x01(\t\x12\x19\n\x11request_streaming\x18\x03 \x01(\x08\x12\x19\n\x11response_type_url\x18\x04 \x01(\t\x12\x1a\n\x12response_streaming\x18\x05 \x01(\x08\x12(\n\x07options\x18\x06 \x03(\x0b\x32\x17.google.protobuf.Option\x12\'\n\x06syntax\x18\x07 \x01(\x0e\x32\x17.google.protobuf.Syntax\"#\n\x05Mixin\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04root\x18\x02 \x01(\tBu\n\x13\x63om.google.protobufB\x08\x41piProtoP\x01Z+google.golang.org/genproto/protobuf/api;api\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') + , + dependencies=[google_dot_protobuf_dot_source__context__pb2.DESCRIPTOR,google_dot_protobuf_dot_type__pb2.DESCRIPTOR,]) + + + + +_API = _descriptor.Descriptor( + name='Api', + full_name='google.protobuf.Api', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Api.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='methods', full_name='google.protobuf.Api.methods', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Api.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='google.protobuf.Api.version', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Api.source_context', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mixins', full_name='google.protobuf.Api.mixins', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Api.syntax', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=370, +) + + +_METHOD = _descriptor.Descriptor( + name='Method', + full_name='google.protobuf.Method', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Method.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='request_type_url', full_name='google.protobuf.Method.request_type_url', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='request_streaming', full_name='google.protobuf.Method.request_streaming', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='response_type_url', full_name='google.protobuf.Method.response_type_url', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='response_streaming', full_name='google.protobuf.Method.response_streaming', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Method.options', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Method.syntax', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=373, + serialized_end=586, +) + + +_MIXIN = _descriptor.Descriptor( + name='Mixin', + full_name='google.protobuf.Mixin', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Mixin.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='root', full_name='google.protobuf.Mixin.root', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=588, + serialized_end=623, +) + +_API.fields_by_name['methods'].message_type = _METHOD +_API.fields_by_name['options'].message_type = google_dot_protobuf_dot_type__pb2._OPTION +_API.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_API.fields_by_name['mixins'].message_type = _MIXIN +_API.fields_by_name['syntax'].enum_type = google_dot_protobuf_dot_type__pb2._SYNTAX +_METHOD.fields_by_name['options'].message_type = google_dot_protobuf_dot_type__pb2._OPTION +_METHOD.fields_by_name['syntax'].enum_type = google_dot_protobuf_dot_type__pb2._SYNTAX +DESCRIPTOR.message_types_by_name['Api'] = _API +DESCRIPTOR.message_types_by_name['Method'] = _METHOD +DESCRIPTOR.message_types_by_name['Mixin'] = _MIXIN +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Api = _reflection.GeneratedProtocolMessageType('Api', (_message.Message,), dict( + DESCRIPTOR = _API, + __module__ = 'google.protobuf.api_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Api) + )) +_sym_db.RegisterMessage(Api) + +Method = _reflection.GeneratedProtocolMessageType('Method', (_message.Message,), dict( + DESCRIPTOR = _METHOD, + __module__ = 'google.protobuf.api_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Method) + )) +_sym_db.RegisterMessage(Method) + +Mixin = _reflection.GeneratedProtocolMessageType('Mixin', (_message.Message,), dict( + DESCRIPTOR = _MIXIN, + __module__ = 'google.protobuf.api_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Mixin) + )) +_sym_db.RegisterMessage(Mixin) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/compiler/__init__.py b/winvenv/Lib/site-packages/google/protobuf/compiler/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py b/winvenv/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py new file mode 100644 index 0000000..82e832f --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/compiler/plugin_pb2.py @@ -0,0 +1,255 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/compiler/plugin.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/compiler/plugin.proto', + package='google.protobuf.compiler', + syntax='proto2', + serialized_options=_b('\n\034com.google.protobuf.compilerB\014PluginProtosZ9github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go'), + serialized_pb=_b('\n%google/protobuf/compiler/plugin.proto\x12\x18google.protobuf.compiler\x1a google/protobuf/descriptor.proto\"F\n\x07Version\x12\r\n\x05major\x18\x01 \x01(\x05\x12\r\n\x05minor\x18\x02 \x01(\x05\x12\r\n\x05patch\x18\x03 \x01(\x05\x12\x0e\n\x06suffix\x18\x04 \x01(\t\"\xba\x01\n\x14\x43odeGeneratorRequest\x12\x18\n\x10\x66ile_to_generate\x18\x01 \x03(\t\x12\x11\n\tparameter\x18\x02 \x01(\t\x12\x38\n\nproto_file\x18\x0f \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\x12;\n\x10\x63ompiler_version\x18\x03 \x01(\x0b\x32!.google.protobuf.compiler.Version\"\xaa\x01\n\x15\x43odeGeneratorResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\x12\x42\n\x04\x66ile\x18\x0f \x03(\x0b\x32\x34.google.protobuf.compiler.CodeGeneratorResponse.File\x1a>\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0finsertion_point\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x0f \x01(\tBg\n\x1c\x63om.google.protobuf.compilerB\x0cPluginProtosZ9github.com/golang/protobuf/protoc-gen-go/plugin;plugin_go') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + + + + +_VERSION = _descriptor.Descriptor( + name='Version', + full_name='google.protobuf.compiler.Version', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='major', full_name='google.protobuf.compiler.Version.major', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='minor', full_name='google.protobuf.compiler.Version.minor', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='patch', full_name='google.protobuf.compiler.Version.patch', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='suffix', full_name='google.protobuf.compiler.Version.suffix', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=101, + serialized_end=171, +) + + +_CODEGENERATORREQUEST = _descriptor.Descriptor( + name='CodeGeneratorRequest', + full_name='google.protobuf.compiler.CodeGeneratorRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file_to_generate', full_name='google.protobuf.compiler.CodeGeneratorRequest.file_to_generate', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='parameter', full_name='google.protobuf.compiler.CodeGeneratorRequest.parameter', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proto_file', full_name='google.protobuf.compiler.CodeGeneratorRequest.proto_file', index=2, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='compiler_version', full_name='google.protobuf.compiler.CodeGeneratorRequest.compiler_version', index=3, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=174, + serialized_end=360, +) + + +_CODEGENERATORRESPONSE_FILE = _descriptor.Descriptor( + name='File', + full_name='google.protobuf.compiler.CodeGeneratorResponse.File', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='insertion_point', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='content', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.content', index=2, + number=15, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=471, + serialized_end=533, +) + +_CODEGENERATORRESPONSE = _descriptor.Descriptor( + name='CodeGeneratorResponse', + full_name='google.protobuf.compiler.CodeGeneratorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='error', full_name='google.protobuf.compiler.CodeGeneratorResponse.error', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.compiler.CodeGeneratorResponse.file', index=1, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_CODEGENERATORRESPONSE_FILE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=363, + serialized_end=533, +) + +_CODEGENERATORREQUEST.fields_by_name['proto_file'].message_type = google_dot_protobuf_dot_descriptor__pb2._FILEDESCRIPTORPROTO +_CODEGENERATORREQUEST.fields_by_name['compiler_version'].message_type = _VERSION +_CODEGENERATORRESPONSE_FILE.containing_type = _CODEGENERATORRESPONSE +_CODEGENERATORRESPONSE.fields_by_name['file'].message_type = _CODEGENERATORRESPONSE_FILE +DESCRIPTOR.message_types_by_name['Version'] = _VERSION +DESCRIPTOR.message_types_by_name['CodeGeneratorRequest'] = _CODEGENERATORREQUEST +DESCRIPTOR.message_types_by_name['CodeGeneratorResponse'] = _CODEGENERATORRESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Version = _reflection.GeneratedProtocolMessageType('Version', (_message.Message,), dict( + DESCRIPTOR = _VERSION, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version) + )) +_sym_db.RegisterMessage(Version) + +CodeGeneratorRequest = _reflection.GeneratedProtocolMessageType('CodeGeneratorRequest', (_message.Message,), dict( + DESCRIPTOR = _CODEGENERATORREQUEST, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) + )) +_sym_db.RegisterMessage(CodeGeneratorRequest) + +CodeGeneratorResponse = _reflection.GeneratedProtocolMessageType('CodeGeneratorResponse', (_message.Message,), dict( + + File = _reflection.GeneratedProtocolMessageType('File', (_message.Message,), dict( + DESCRIPTOR = _CODEGENERATORRESPONSE_FILE, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) + )) + , + DESCRIPTOR = _CODEGENERATORRESPONSE, + __module__ = 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) + )) +_sym_db.RegisterMessage(CodeGeneratorResponse) +_sym_db.RegisterMessage(CodeGeneratorResponse.File) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/descriptor.py b/winvenv/Lib/site-packages/google/protobuf/descriptor.py new file mode 100644 index 0000000..8a9ba3d --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/descriptor.py @@ -0,0 +1,1076 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Descriptors essentially contain exactly the information found in a .proto +file, in types that make this information accessible in Python. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import threading +import six + +from google.protobuf.internal import api_implementation + +_USE_C_DESCRIPTORS = False +if api_implementation.Type() == 'cpp': + # Used by MakeDescriptor in cpp mode + import binascii + import os + from google.protobuf.pyext import _message + _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False) + + +class Error(Exception): + """Base error for this module.""" + + +class TypeTransformationError(Error): + """Error transforming between python proto type and corresponding C++ type.""" + + +if _USE_C_DESCRIPTORS: + # This metaclass allows to override the behavior of code like + # isinstance(my_descriptor, FieldDescriptor) + # and make it return True when the descriptor is an instance of the extension + # type written in C++. + class DescriptorMetaclass(type): + def __instancecheck__(cls, obj): + if super(DescriptorMetaclass, cls).__instancecheck__(obj): + return True + if isinstance(obj, cls._C_DESCRIPTOR_CLASS): + return True + return False +else: + # The standard metaclass; nothing changes. + DescriptorMetaclass = type + + +class _Lock(object): + """Wrapper class of threading.Lock(), which is allowed by 'with'.""" + + def __new__(cls): + self = object.__new__(cls) + self._lock = threading.Lock() # pylint: disable=protected-access + return self + + def __enter__(self): + self._lock.acquire() + + def __exit__(self, exc_type, exc_value, exc_tb): + self._lock.release() + + +_lock = threading.Lock() + + +class DescriptorBase(six.with_metaclass(DescriptorMetaclass)): + + """Descriptors base class. + + This class is the base of all descriptor classes. It provides common options + related functionality. + + Attributes: + has_options: True if the descriptor has non-default options. Usually it + is not necessary to read this -- just call GetOptions() which will + happily return the default instance. However, it's sometimes useful + for efficiency, and also useful inside the protobuf implementation to + avoid some bootstrapping issues. + """ + + if _USE_C_DESCRIPTORS: + # The class, or tuple of classes, that are considered as "virtual + # subclasses" of this descriptor class. + _C_DESCRIPTOR_CLASS = () + + def __init__(self, options, serialized_options, options_class_name): + """Initialize the descriptor given its options message and the name of the + class of the options message. The name of the class is required in case + the options message is None and has to be created. + """ + self._options = options + self._options_class_name = options_class_name + self._serialized_options = serialized_options + + # Does this descriptor have non-default options? + self.has_options = (options is not None) or (serialized_options is not None) + + def _SetOptions(self, options, options_class_name): + """Sets the descriptor's options + + This function is used in generated proto2 files to update descriptor + options. It must not be used outside proto2. + """ + self._options = options + self._options_class_name = options_class_name + + # Does this descriptor have non-default options? + self.has_options = options is not None + + def GetOptions(self): + """Retrieves descriptor options. + + This method returns the options set or creates the default options for the + descriptor. + """ + if self._options: + return self._options + + from google.protobuf import descriptor_pb2 + try: + options_class = getattr(descriptor_pb2, + self._options_class_name) + except AttributeError: + raise RuntimeError('Unknown options class name %s!' % + (self._options_class_name)) + + with _lock: + if self._serialized_options is None: + self._options = options_class() + else: + self._options = _ParseOptions(options_class(), + self._serialized_options) + + return self._options + + +class _NestedDescriptorBase(DescriptorBase): + """Common class for descriptors that can be nested.""" + + def __init__(self, options, options_class_name, name, full_name, + file, containing_type, serialized_start=None, + serialized_end=None, serialized_options=None): + """Constructor. + + Args: + options: Protocol message options or None + to use default message options. + options_class_name: (str) The class name of the above options. + + name: (str) Name of this protocol message type. + full_name: (str) Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + file: (FileDescriptor) Reference to file info. + containing_type: if provided, this is a nested descriptor, with this + descriptor as parent, otherwise None. + serialized_start: The start index (inclusive) in block in the + file.serialized_pb that describes this descriptor. + serialized_end: The end index (exclusive) in block in the + file.serialized_pb that describes this descriptor. + serialized_options: Protocol message serilized options or None. + """ + super(_NestedDescriptorBase, self).__init__( + options, serialized_options, options_class_name) + + self.name = name + # TODO(falk): Add function to calculate full_name instead of having it in + # memory? + self.full_name = full_name + self.file = file + self.containing_type = containing_type + + self._serialized_start = serialized_start + self._serialized_end = serialized_end + + def CopyToProto(self, proto): + """Copies this to the matching proto in descriptor_pb2. + + Args: + proto: An empty proto instance from descriptor_pb2. + + Raises: + Error: If self couldnt be serialized, due to to few constructor arguments. + """ + if (self.file is not None and + self._serialized_start is not None and + self._serialized_end is not None): + proto.ParseFromString(self.file.serialized_pb[ + self._serialized_start:self._serialized_end]) + else: + raise Error('Descriptor does not contain serialization.') + + +class Descriptor(_NestedDescriptorBase): + + """Descriptor for a protocol message type. + + A Descriptor instance has the following attributes: + + name: (str) Name of this protocol message type. + full_name: (str) Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + + containing_type: (Descriptor) Reference to the descriptor of the + type containing us, or None if this is top-level. + + fields: (list of FieldDescriptors) Field descriptors for all + fields in this type. + fields_by_number: (dict int -> FieldDescriptor) Same FieldDescriptor + objects as in |fields|, but indexed by "number" attribute in each + FieldDescriptor. + fields_by_name: (dict str -> FieldDescriptor) Same FieldDescriptor + objects as in |fields|, but indexed by "name" attribute in each + FieldDescriptor. + fields_by_camelcase_name: (dict str -> FieldDescriptor) Same + FieldDescriptor objects as in |fields|, but indexed by + "camelcase_name" attribute in each FieldDescriptor. + + nested_types: (list of Descriptors) Descriptor references + for all protocol message types nested within this one. + nested_types_by_name: (dict str -> Descriptor) Same Descriptor + objects as in |nested_types|, but indexed by "name" attribute + in each Descriptor. + + enum_types: (list of EnumDescriptors) EnumDescriptor references + for all enums contained within this type. + enum_types_by_name: (dict str ->EnumDescriptor) Same EnumDescriptor + objects as in |enum_types|, but indexed by "name" attribute + in each EnumDescriptor. + enum_values_by_name: (dict str -> EnumValueDescriptor) Dict mapping + from enum value name to EnumValueDescriptor for that value. + + extensions: (list of FieldDescriptor) All extensions defined directly + within this message type (NOT within a nested type). + extensions_by_name: (dict, string -> FieldDescriptor) Same FieldDescriptor + objects as |extensions|, but indexed by "name" attribute of each + FieldDescriptor. + + is_extendable: Does this type define any extension ranges? + + oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields + in this message. + oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|, + but indexed by "name" attribute. + + file: (FileDescriptor) Reference to file descriptor. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.Descriptor + + def __new__(cls, name, full_name, filename, containing_type, fields, + nested_types, enum_types, extensions, options=None, + serialized_options=None, + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin + syntax=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindMessageTypeByName(full_name) + + # NOTE(tmarek): The file argument redefining a builtin is nothing we can + # fix right now since we don't know how many clients already rely on the + # name of the argument. + def __init__(self, name, full_name, filename, containing_type, fields, + nested_types, enum_types, extensions, options=None, + serialized_options=None, + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin + syntax=None): + """Arguments to __init__() are as described in the description + of Descriptor fields above. + + Note that filename is an obsolete argument, that is not used anymore. + Please use file.name to access this as an attribute. + """ + super(Descriptor, self).__init__( + options, 'MessageOptions', name, full_name, file, + containing_type, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + + # We have fields in addition to fields_by_name and fields_by_number, + # so that: + # 1. Clients can index fields by "order in which they're listed." + # 2. Clients can easily iterate over all fields with the terse + # syntax: for f in descriptor.fields: ... + self.fields = fields + for field in self.fields: + field.containing_type = self + self.fields_by_number = dict((f.number, f) for f in fields) + self.fields_by_name = dict((f.name, f) for f in fields) + self._fields_by_camelcase_name = None + + self.nested_types = nested_types + for nested_type in nested_types: + nested_type.containing_type = self + self.nested_types_by_name = dict((t.name, t) for t in nested_types) + + self.enum_types = enum_types + for enum_type in self.enum_types: + enum_type.containing_type = self + self.enum_types_by_name = dict((t.name, t) for t in enum_types) + self.enum_values_by_name = dict( + (v.name, v) for t in enum_types for v in t.values) + + self.extensions = extensions + for extension in self.extensions: + extension.extension_scope = self + self.extensions_by_name = dict((f.name, f) for f in extensions) + self.is_extendable = is_extendable + self.extension_ranges = extension_ranges + self.oneofs = oneofs if oneofs is not None else [] + self.oneofs_by_name = dict((o.name, o) for o in self.oneofs) + for oneof in self.oneofs: + oneof.containing_type = self + self.syntax = syntax or "proto2" + + @property + def fields_by_camelcase_name(self): + if self._fields_by_camelcase_name is None: + self._fields_by_camelcase_name = dict( + (f.camelcase_name, f) for f in self.fields) + return self._fields_by_camelcase_name + + def EnumValueName(self, enum, value): + """Returns the string name of an enum value. + + This is just a small helper method to simplify a common operation. + + Args: + enum: string name of the Enum. + value: int, value of the enum. + + Returns: + string name of the enum value. + + Raises: + KeyError if either the Enum doesn't exist or the value is not a valid + value for the enum. + """ + return self.enum_types_by_name[enum].values_by_number[value].name + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.DescriptorProto. + + Args: + proto: An empty descriptor_pb2.DescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(Descriptor, self).CopyToProto(proto) + + +# TODO(robinson): We should have aggressive checking here, +# for example: +# * If you specify a repeated field, you should not be allowed +# to specify a default value. +# * [Other examples here as needed]. +# +# TODO(robinson): for this and other *Descriptor classes, we +# might also want to lock things down aggressively (e.g., +# prevent clients from setting the attributes). Having +# stronger invariants here in general will reduce the number +# of runtime checks we must do in reflection.py... +class FieldDescriptor(DescriptorBase): + + """Descriptor for a single field in a .proto file. + + A FieldDescriptor instance has the following attributes: + + name: (str) Name of this field, exactly as it appears in .proto. + full_name: (str) Name of this field, including containing scope. This is + particularly relevant for extensions. + camelcase_name: (str) Camelcase name of this field. + index: (int) Dense, 0-indexed index giving the order that this + field textually appears within its message in the .proto file. + number: (int) Tag number declared for this field in the .proto file. + + type: (One of the TYPE_* constants below) Declared type. + cpp_type: (One of the CPPTYPE_* constants below) C++ type used to + represent this field. + + label: (One of the LABEL_* constants below) Tells whether this + field is optional, required, or repeated. + has_default_value: (bool) True if this field has a default value defined, + otherwise false. + default_value: (Varies) Default value of this field. Only + meaningful for non-repeated scalar fields. Repeated fields + should always set this to [], and non-repeated composite + fields should always set this to None. + + containing_type: (Descriptor) Descriptor of the protocol message + type that contains this field. Set by the Descriptor constructor + if we're passed into one. + Somewhat confusingly, for extension fields, this is the + descriptor of the EXTENDED message, not the descriptor + of the message containing this field. (See is_extension and + extension_scope below). + message_type: (Descriptor) If a composite field, a descriptor + of the message type contained in this field. Otherwise, this is None. + enum_type: (EnumDescriptor) If this field contains an enum, a + descriptor of that enum. Otherwise, this is None. + + is_extension: True iff this describes an extension field. + extension_scope: (Descriptor) Only meaningful if is_extension is True. + Gives the message that immediately contains this extension field. + Will be None iff we're a top-level (file-level) extension field. + + options: (descriptor_pb2.FieldOptions) Protocol message field options or + None to use default field options. + + containing_oneof: (OneofDescriptor) If the field is a member of a oneof + union, contains its descriptor. Otherwise, None. + + file: (FileDescriptor) Reference to file descriptor. + """ + + # Must be consistent with C++ FieldDescriptor::Type enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + TYPE_DOUBLE = 1 + TYPE_FLOAT = 2 + TYPE_INT64 = 3 + TYPE_UINT64 = 4 + TYPE_INT32 = 5 + TYPE_FIXED64 = 6 + TYPE_FIXED32 = 7 + TYPE_BOOL = 8 + TYPE_STRING = 9 + TYPE_GROUP = 10 + TYPE_MESSAGE = 11 + TYPE_BYTES = 12 + TYPE_UINT32 = 13 + TYPE_ENUM = 14 + TYPE_SFIXED32 = 15 + TYPE_SFIXED64 = 16 + TYPE_SINT32 = 17 + TYPE_SINT64 = 18 + MAX_TYPE = 18 + + # Must be consistent with C++ FieldDescriptor::CppType enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + CPPTYPE_INT32 = 1 + CPPTYPE_INT64 = 2 + CPPTYPE_UINT32 = 3 + CPPTYPE_UINT64 = 4 + CPPTYPE_DOUBLE = 5 + CPPTYPE_FLOAT = 6 + CPPTYPE_BOOL = 7 + CPPTYPE_ENUM = 8 + CPPTYPE_STRING = 9 + CPPTYPE_MESSAGE = 10 + MAX_CPPTYPE = 10 + + _PYTHON_TO_CPP_PROTO_TYPE_MAP = { + TYPE_DOUBLE: CPPTYPE_DOUBLE, + TYPE_FLOAT: CPPTYPE_FLOAT, + TYPE_ENUM: CPPTYPE_ENUM, + TYPE_INT64: CPPTYPE_INT64, + TYPE_SINT64: CPPTYPE_INT64, + TYPE_SFIXED64: CPPTYPE_INT64, + TYPE_UINT64: CPPTYPE_UINT64, + TYPE_FIXED64: CPPTYPE_UINT64, + TYPE_INT32: CPPTYPE_INT32, + TYPE_SFIXED32: CPPTYPE_INT32, + TYPE_SINT32: CPPTYPE_INT32, + TYPE_UINT32: CPPTYPE_UINT32, + TYPE_FIXED32: CPPTYPE_UINT32, + TYPE_BYTES: CPPTYPE_STRING, + TYPE_STRING: CPPTYPE_STRING, + TYPE_BOOL: CPPTYPE_BOOL, + TYPE_MESSAGE: CPPTYPE_MESSAGE, + TYPE_GROUP: CPPTYPE_MESSAGE + } + + # Must be consistent with C++ FieldDescriptor::Label enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + LABEL_OPTIONAL = 1 + LABEL_REQUIRED = 2 + LABEL_REPEATED = 3 + MAX_LABEL = 3 + + # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber, + # and kLastReservedNumber in descriptor.h + MAX_FIELD_NUMBER = (1 << 29) - 1 + FIRST_RESERVED_FIELD_NUMBER = 19000 + LAST_RESERVED_FIELD_NUMBER = 19999 + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FieldDescriptor + + def __new__(cls, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + serialized_options=None, + has_default_value=True, containing_oneof=None, json_name=None, + file=None): # pylint: disable=redefined-builtin + _message.Message._CheckCalledFromGeneratedFile() + if is_extension: + return _message.default_pool.FindExtensionByName(full_name) + else: + return _message.default_pool.FindFieldByName(full_name) + + def __init__(self, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + serialized_options=None, + has_default_value=True, containing_oneof=None, json_name=None, + file=None): # pylint: disable=redefined-builtin + """The arguments are as described in the description of FieldDescriptor + attributes above. + + Note that containing_type may be None, and may be set later if necessary + (to deal with circular references between message types, for example). + Likewise for extension_scope. + """ + super(FieldDescriptor, self).__init__( + options, serialized_options, 'FieldOptions') + self.name = name + self.full_name = full_name + self.file = file + self._camelcase_name = None + if json_name is None: + self.json_name = _ToJsonName(name) + else: + self.json_name = json_name + self.index = index + self.number = number + self.type = type + self.cpp_type = cpp_type + self.label = label + self.has_default_value = has_default_value + self.default_value = default_value + self.containing_type = containing_type + self.message_type = message_type + self.enum_type = enum_type + self.is_extension = is_extension + self.extension_scope = extension_scope + self.containing_oneof = containing_oneof + if api_implementation.Type() == 'cpp': + if is_extension: + self._cdescriptor = _message.default_pool.FindExtensionByName(full_name) + else: + self._cdescriptor = _message.default_pool.FindFieldByName(full_name) + else: + self._cdescriptor = None + + @property + def camelcase_name(self): + if self._camelcase_name is None: + self._camelcase_name = _ToCamelCase(self.name) + return self._camelcase_name + + @staticmethod + def ProtoTypeToCppProtoType(proto_type): + """Converts from a Python proto type to a C++ Proto Type. + + The Python ProtocolBuffer classes specify both the 'Python' datatype and the + 'C++' datatype - and they're not the same. This helper method should + translate from one to another. + + Args: + proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*) + Returns: + descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. + Raises: + TypeTransformationError: when the Python proto type isn't known. + """ + try: + return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type] + except KeyError: + raise TypeTransformationError('Unknown proto_type: %s' % proto_type) + + +class EnumDescriptor(_NestedDescriptorBase): + + """Descriptor for an enum defined in a .proto file. + + An EnumDescriptor instance has the following attributes: + + name: (str) Name of the enum type. + full_name: (str) Full name of the type, including package name + and any enclosing type(s). + + values: (list of EnumValueDescriptors) List of the values + in this enum. + values_by_name: (dict str -> EnumValueDescriptor) Same as |values|, + but indexed by the "name" field of each EnumValueDescriptor. + values_by_number: (dict int -> EnumValueDescriptor) Same as |values|, + but indexed by the "number" field of each EnumValueDescriptor. + containing_type: (Descriptor) Descriptor of the immediate containing + type of this enum, or None if this is an enum defined at the + top level in a .proto file. Set by Descriptor's constructor + if we're passed into one. + file: (FileDescriptor) Reference to file descriptor. + options: (descriptor_pb2.EnumOptions) Enum options message or + None to use default enum options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumDescriptor + + def __new__(cls, name, full_name, filename, values, + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindEnumTypeByName(full_name) + + def __init__(self, name, full_name, filename, values, + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + """Arguments are as described in the attribute description above. + + Note that filename is an obsolete argument, that is not used anymore. + Please use file.name to access this as an attribute. + """ + super(EnumDescriptor, self).__init__( + options, 'EnumOptions', name, full_name, file, + containing_type, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + + self.values = values + for value in self.values: + value.type = self + self.values_by_name = dict((v.name, v) for v in values) + self.values_by_number = dict((v.number, v) for v in values) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.EnumDescriptorProto. + + Args: + proto: An empty descriptor_pb2.EnumDescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(EnumDescriptor, self).CopyToProto(proto) + + +class EnumValueDescriptor(DescriptorBase): + + """Descriptor for a single value within an enum. + + name: (str) Name of this value. + index: (int) Dense, 0-indexed index giving the order that this + value appears textually within its enum in the .proto file. + number: (int) Actual number assigned to this enum value. + type: (EnumDescriptor) EnumDescriptor to which this value + belongs. Set by EnumDescriptor's constructor if we're + passed into one. + options: (descriptor_pb2.EnumValueOptions) Enum value options message or + None to use default enum value options options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor + + def __new__(cls, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None): + _message.Message._CheckCalledFromGeneratedFile() + # There is no way we can build a complete EnumValueDescriptor with the + # given parameters (the name of the Enum is not known, for example). + # Fortunately generated files just pass it to the EnumDescriptor() + # constructor, which will ignore it, so returning None is good enough. + return None + + def __init__(self, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None): + """Arguments are as described in the attribute description above.""" + super(EnumValueDescriptor, self).__init__( + options, serialized_options, 'EnumValueOptions') + self.name = name + self.index = index + self.number = number + self.type = type + + +class OneofDescriptor(DescriptorBase): + """Descriptor for a oneof field. + + name: (str) Name of the oneof field. + full_name: (str) Full name of the oneof field, including package name. + index: (int) 0-based index giving the order of the oneof field inside + its containing type. + containing_type: (Descriptor) Descriptor of the protocol message + type that contains this field. Set by the Descriptor constructor + if we're passed into one. + fields: (list of FieldDescriptor) The list of field descriptors this + oneof can contain. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.OneofDescriptor + + def __new__( + cls, name, full_name, index, containing_type, fields, options=None, + serialized_options=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindOneofByName(full_name) + + def __init__( + self, name, full_name, index, containing_type, fields, options=None, + serialized_options=None): + """Arguments are as described in the attribute description above.""" + super(OneofDescriptor, self).__init__( + options, serialized_options, 'OneofOptions') + self.name = name + self.full_name = full_name + self.index = index + self.containing_type = containing_type + self.fields = fields + + +class ServiceDescriptor(_NestedDescriptorBase): + + """Descriptor for a service. + + name: (str) Name of the service. + full_name: (str) Full name of the service, including package name. + index: (int) 0-indexed index giving the order that this services + definition appears withing the .proto file. + methods: (list of MethodDescriptor) List of methods provided by this + service. + methods_by_name: (dict str -> MethodDescriptor) Same MethodDescriptor + objects as in |methods_by_name|, but indexed by "name" attribute in each + MethodDescriptor. + options: (descriptor_pb2.ServiceOptions) Service options message or + None to use default service options. + file: (FileDescriptor) Reference to file info. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor + + def __new__(cls, name, full_name, index, methods, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access + return _message.default_pool.FindServiceByName(full_name) + + def __init__(self, name, full_name, index, methods, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None): + super(ServiceDescriptor, self).__init__( + options, 'ServiceOptions', name, full_name, file, + None, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + self.index = index + self.methods = methods + self.methods_by_name = dict((m.name, m) for m in methods) + # Set the containing service for each method in this service. + for method in self.methods: + method.containing_service = self + + def FindMethodByName(self, name): + """Searches for the specified method, and returns its descriptor.""" + return self.methods_by_name.get(name, None) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.ServiceDescriptorProto. + + Args: + proto: An empty descriptor_pb2.ServiceDescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(ServiceDescriptor, self).CopyToProto(proto) + + +class MethodDescriptor(DescriptorBase): + + """Descriptor for a method in a service. + + name: (str) Name of the method within the service. + full_name: (str) Full name of method. + index: (int) 0-indexed index of the method inside the service. + containing_service: (ServiceDescriptor) The service that contains this + method. + input_type: The descriptor of the message that this method accepts. + output_type: The descriptor of the message that this method returns. + options: (descriptor_pb2.MethodOptions) Method options message or + None to use default method options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.MethodDescriptor + + def __new__(cls, name, full_name, index, containing_service, + input_type, output_type, options=None, serialized_options=None): + _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access + return _message.default_pool.FindMethodByName(full_name) + + def __init__(self, name, full_name, index, containing_service, + input_type, output_type, options=None, serialized_options=None): + """The arguments are as described in the description of MethodDescriptor + attributes above. + + Note that containing_service may be None, and may be set later if necessary. + """ + super(MethodDescriptor, self).__init__( + options, serialized_options, 'MethodOptions') + self.name = name + self.full_name = full_name + self.index = index + self.containing_service = containing_service + self.input_type = input_type + self.output_type = output_type + + +class FileDescriptor(DescriptorBase): + """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto. + + Note that enum_types_by_name, extensions_by_name, and dependencies + fields are only set by the message_factory module, and not by the + generated proto code. + + name: name of file, relative to root of source tree. + package: name of the package + syntax: string indicating syntax of the file (can be "proto2" or "proto3") + serialized_pb: (str) Byte string of serialized + descriptor_pb2.FileDescriptorProto. + dependencies: List of other FileDescriptors this FileDescriptor depends on. + public_dependencies: A list of FileDescriptors, subset of the dependencies + above, which were declared as "public". + message_types_by_name: Dict of message names of their descriptors. + enum_types_by_name: Dict of enum names and their descriptors. + extensions_by_name: Dict of extension names and their descriptors. + services_by_name: Dict of services names and their descriptors. + pool: the DescriptorPool this descriptor belongs to. When not passed to the + constructor, the global default pool is used. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FileDescriptor + + def __new__(cls, name, package, options=None, + serialized_options=None, serialized_pb=None, + dependencies=None, public_dependencies=None, + syntax=None, pool=None): + # FileDescriptor() is called from various places, not only from generated + # files, to register dynamic proto files and messages. + if serialized_pb: + # TODO(amauryfa): use the pool passed as argument. This will work only + # for C++-implemented DescriptorPools. + return _message.default_pool.AddSerializedFile(serialized_pb) + else: + return super(FileDescriptor, cls).__new__(cls) + + def __init__(self, name, package, options=None, + serialized_options=None, serialized_pb=None, + dependencies=None, public_dependencies=None, + syntax=None, pool=None): + """Constructor.""" + super(FileDescriptor, self).__init__( + options, serialized_options, 'FileOptions') + + if pool is None: + from google.protobuf import descriptor_pool + pool = descriptor_pool.Default() + self.pool = pool + self.message_types_by_name = {} + self.name = name + self.package = package + self.syntax = syntax or "proto2" + self.serialized_pb = serialized_pb + + self.enum_types_by_name = {} + self.extensions_by_name = {} + self.services_by_name = {} + self.dependencies = (dependencies or []) + self.public_dependencies = (public_dependencies or []) + + if (api_implementation.Type() == 'cpp' and + self.serialized_pb is not None): + _message.default_pool.AddSerializedFile(self.serialized_pb) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.FileDescriptorProto. + + Args: + proto: An empty descriptor_pb2.FileDescriptorProto. + """ + proto.ParseFromString(self.serialized_pb) + + +def _ParseOptions(message, string): + """Parses serialized options. + + This helper function is used to parse serialized options in generated + proto2 files. It must not be used outside proto2. + """ + message.ParseFromString(string) + return message + + +def _ToCamelCase(name): + """Converts name to camel-case and returns it.""" + capitalize_next = False + result = [] + + for c in name: + if c == '_': + if result: + capitalize_next = True + elif capitalize_next: + result.append(c.upper()) + capitalize_next = False + else: + result += c + + # Lower-case the first letter. + if result and result[0].isupper(): + result[0] = result[0].lower() + return ''.join(result) + + +def _OptionsOrNone(descriptor_proto): + """Returns the value of the field `options`, or None if it is not set.""" + if descriptor_proto.HasField('options'): + return descriptor_proto.options + else: + return None + + +def _ToJsonName(name): + """Converts name to Json name and returns it.""" + capitalize_next = False + result = [] + + for c in name: + if c == '_': + capitalize_next = True + elif capitalize_next: + result.append(c.upper()) + capitalize_next = False + else: + result += c + + return ''.join(result) + + +def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, + syntax=None): + """Make a protobuf Descriptor given a DescriptorProto protobuf. + + Handles nested descriptors. Note that this is limited to the scope of defining + a message inside of another message. Composite fields can currently only be + resolved if the message is defined in the same scope as the field. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: Optional package name for the new message Descriptor (string). + build_file_if_cpp: Update the C++ descriptor pool if api matches. + Set to False on recursion, so no duplicates are created. + syntax: The syntax/semantics that should be used. Set to "proto3" to get + proto3 field presence semantics. + Returns: + A Descriptor for protobuf messages. + """ + if api_implementation.Type() == 'cpp' and build_file_if_cpp: + # The C++ implementation requires all descriptors to be backed by the same + # definition in the C++ descriptor pool. To do this, we build a + # FileDescriptorProto with the same definition as this descriptor and build + # it into the pool. + from google.protobuf import descriptor_pb2 + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.message_type.add().MergeFrom(desc_proto) + + # Generate a random name for this proto file to prevent conflicts with any + # imported ones. We need to specify a file name so the descriptor pool + # accepts our FileDescriptorProto, but it is not important what that file + # name is actually set to. + proto_name = binascii.hexlify(os.urandom(16)).decode('ascii') + + if package: + file_descriptor_proto.name = os.path.join(package.replace('.', '/'), + proto_name + '.proto') + file_descriptor_proto.package = package + else: + file_descriptor_proto.name = proto_name + '.proto' + + _message.default_pool.Add(file_descriptor_proto) + result = _message.default_pool.FindFileByName(file_descriptor_proto.name) + + if _USE_C_DESCRIPTORS: + return result.message_types_by_name[desc_proto.name] + + full_message_name = [desc_proto.name] + if package: full_message_name.insert(0, package) + + # Create Descriptors for enum types + enum_types = {} + for enum_proto in desc_proto.enum_type: + full_name = '.'.join(full_message_name + [enum_proto.name]) + enum_desc = EnumDescriptor( + enum_proto.name, full_name, None, [ + EnumValueDescriptor(enum_val.name, ii, enum_val.number) + for ii, enum_val in enumerate(enum_proto.value)]) + enum_types[full_name] = enum_desc + + # Create Descriptors for nested types + nested_types = {} + for nested_proto in desc_proto.nested_type: + full_name = '.'.join(full_message_name + [nested_proto.name]) + # Nested types are just those defined inside of the message, not all types + # used by fields in the message, so no loops are possible here. + nested_desc = MakeDescriptor(nested_proto, + package='.'.join(full_message_name), + build_file_if_cpp=False, + syntax=syntax) + nested_types[full_name] = nested_desc + + fields = [] + for field_proto in desc_proto.field: + full_name = '.'.join(full_message_name + [field_proto.name]) + enum_desc = None + nested_desc = None + if field_proto.json_name: + json_name = field_proto.json_name + else: + json_name = None + if field_proto.HasField('type_name'): + type_name = field_proto.type_name + full_type_name = '.'.join(full_message_name + + [type_name[type_name.rfind('.')+1:]]) + if full_type_name in nested_types: + nested_desc = nested_types[full_type_name] + elif full_type_name in enum_types: + enum_desc = enum_types[full_type_name] + # Else type_name references a non-local type, which isn't implemented + field = FieldDescriptor( + field_proto.name, full_name, field_proto.number - 1, + field_proto.number, field_proto.type, + FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type), + field_proto.label, None, nested_desc, enum_desc, None, False, None, + options=_OptionsOrNone(field_proto), has_default_value=False, + json_name=json_name) + fields.append(field) + + desc_name = '.'.join(full_message_name) + return Descriptor(desc_proto.name, desc_name, None, None, fields, + list(nested_types.values()), list(enum_types.values()), [], + options=_OptionsOrNone(desc_proto)) diff --git a/winvenv/Lib/site-packages/google/protobuf/descriptor_database.py b/winvenv/Lib/site-packages/google/protobuf/descriptor_database.py new file mode 100644 index 0000000..8b7715c --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/descriptor_database.py @@ -0,0 +1,162 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides a container for DescriptorProtos.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import warnings + + +class Error(Exception): + pass + + +class DescriptorDatabaseConflictingDefinitionError(Error): + """Raised when a proto is added with the same name & different descriptor.""" + + +class DescriptorDatabase(object): + """A container accepting FileDescriptorProtos and maps DescriptorProtos.""" + + def __init__(self): + self._file_desc_protos_by_file = {} + self._file_desc_protos_by_symbol = {} + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this database. + + Args: + file_desc_proto: The FileDescriptorProto to add. + Raises: + DescriptorDatabaseConflictingDefinitionError: if an attempt is made to + add a proto with the same name but different definition than an + exisiting proto in the database. + """ + proto_name = file_desc_proto.name + if proto_name not in self._file_desc_protos_by_file: + self._file_desc_protos_by_file[proto_name] = file_desc_proto + elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: + raise DescriptorDatabaseConflictingDefinitionError( + '%s already added, but with different descriptor.' % proto_name) + else: + return + + # Add all the top-level descriptors to the index. + package = file_desc_proto.package + for message in file_desc_proto.message_type: + for name in _ExtractSymbols(message, package): + self._AddSymbol(name, file_desc_proto) + for enum in file_desc_proto.enum_type: + self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) + for extension in file_desc_proto.extension: + self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) + for service in file_desc_proto.service: + self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) + + def FindFileByName(self, name): + """Finds the file descriptor proto by file name. + + Typically the file name is a relative path ending to a .proto file. The + proto with the given name will have to have been added to this database + using the Add method or else an error will be raised. + + Args: + name: The file name to find. + + Returns: + The file descriptor proto matching the name. + + Raises: + KeyError if no file by the given name was added. + """ + + return self._file_desc_protos_by_file[name] + + def FindFileContainingSymbol(self, symbol): + """Finds the file descriptor proto containing the specified symbol. + + The symbol should be a fully qualified name including the file descriptor's + package and any containing messages. Some examples: + + 'some.package.name.Message' + 'some.package.name.Message.NestedEnum' + 'some.package.name.Message.some_field' + + The file descriptor proto containing the specified symbol must be added to + this database using the Add method or else an error will be raised. + + Args: + symbol: The fully qualified symbol name. + + Returns: + The file descriptor proto containing the symbol. + + Raises: + KeyError if no file contains the specified symbol. + """ + try: + return self._file_desc_protos_by_symbol[symbol] + except KeyError: + # Fields, enum values, and nested extensions are not in + # _file_desc_protos_by_symbol. Try to find the top level + # descriptor. Non-existent nested symbol under a valid top level + # descriptor can also be found. The behavior is the same with + # protobuf C++. + top_level, _, _ = symbol.rpartition('.') + return self._file_desc_protos_by_symbol[top_level] + + def _AddSymbol(self, name, file_desc_proto): + if name in self._file_desc_protos_by_symbol: + warn_msg = ('Conflict register for file "' + file_desc_proto.name + + '": ' + name + + ' is already defined in file "' + + self._file_desc_protos_by_symbol[name].name + '"') + warnings.warn(warn_msg, RuntimeWarning) + self._file_desc_protos_by_symbol[name] = file_desc_proto + + +def _ExtractSymbols(desc_proto, package): + """Pulls out all the symbols from a descriptor proto. + + Args: + desc_proto: The proto to extract symbols from. + package: The package containing the descriptor type. + + Yields: + The fully qualified name found in the descriptor. + """ + message_name = package + '.' + desc_proto.name if package else desc_proto.name + yield message_name + for nested_type in desc_proto.nested_type: + for symbol in _ExtractSymbols(nested_type, message_name): + yield symbol + for enum_type in desc_proto.enum_type: + yield '.'.join((message_name, enum_type.name)) diff --git a/winvenv/Lib/site-packages/google/protobuf/descriptor_pb2.py b/winvenv/Lib/site-packages/google/protobuf/descriptor_pb2.py new file mode 100644 index 0000000..34055d7 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/descriptor_pb2.py @@ -0,0 +1,2033 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/descriptor.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/descriptor.proto', + package='google.protobuf', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"G\n\x11\x46ileDescriptorSet\x12\x32\n\x04\x66ile\x18\x01 \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\"\xdb\x03\n\x13\x46ileDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07package\x18\x02 \x01(\t\x12\x12\n\ndependency\x18\x03 \x03(\t\x12\x19\n\x11public_dependency\x18\n \x03(\x05\x12\x17\n\x0fweak_dependency\x18\x0b \x03(\x05\x12\x36\n\x0cmessage_type\x18\x04 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x05 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12\x38\n\x07service\x18\x06 \x03(\x0b\x32\'.google.protobuf.ServiceDescriptorProto\x12\x38\n\textension\x18\x07 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12-\n\x07options\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.FileOptions\x12\x39\n\x10source_code_info\x18\t \x01(\x0b\x32\x1f.google.protobuf.SourceCodeInfo\x12\x0e\n\x06syntax\x18\x0c \x01(\t\"\xa9\x05\n\x0f\x44\x65scriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05\x66ield\x18\x02 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x38\n\textension\x18\x06 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x35\n\x0bnested_type\x18\x03 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x04 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12H\n\x0f\x65xtension_range\x18\x05 \x03(\x0b\x32/.google.protobuf.DescriptorProto.ExtensionRange\x12\x39\n\noneof_decl\x18\x08 \x03(\x0b\x32%.google.protobuf.OneofDescriptorProto\x12\x30\n\x07options\x18\x07 \x01(\x0b\x32\x1f.google.protobuf.MessageOptions\x12\x46\n\x0ereserved_range\x18\t \x03(\x0b\x32..google.protobuf.DescriptorProto.ReservedRange\x12\x15\n\rreserved_name\x18\n \x03(\t\x1a\x65\n\x0e\x45xtensionRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\x12\x37\n\x07options\x18\x03 \x01(\x0b\x32&.google.protobuf.ExtensionRangeOptions\x1a+\n\rReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"g\n\x15\x45xtensionRangeOptions\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xbc\x05\n\x14\x46ieldDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12:\n\x05label\x18\x04 \x01(\x0e\x32+.google.protobuf.FieldDescriptorProto.Label\x12\x38\n\x04type\x18\x05 \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x11\n\ttype_name\x18\x06 \x01(\t\x12\x10\n\x08\x65xtendee\x18\x02 \x01(\t\x12\x15\n\rdefault_value\x18\x07 \x01(\t\x12\x13\n\x0boneof_index\x18\t \x01(\x05\x12\x11\n\tjson_name\x18\n \x01(\t\x12.\n\x07options\x18\x08 \x01(\x0b\x32\x1d.google.protobuf.FieldOptions\"\xb6\x02\n\x04Type\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"C\n\x05Label\x12\x12\n\x0eLABEL_OPTIONAL\x10\x01\x12\x12\n\x0eLABEL_REQUIRED\x10\x02\x12\x12\n\x0eLABEL_REPEATED\x10\x03\"T\n\x14OneofDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\x07options\x18\x02 \x01(\x0b\x32\x1d.google.protobuf.OneofOptions\"\xa4\x02\n\x13\x45numDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x03(\x0b\x32).google.protobuf.EnumValueDescriptorProto\x12-\n\x07options\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.EnumOptions\x12N\n\x0ereserved_range\x18\x04 \x03(\x0b\x32\x36.google.protobuf.EnumDescriptorProto.EnumReservedRange\x12\x15\n\rreserved_name\x18\x05 \x03(\t\x1a/\n\x11\x45numReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"l\n\x18\x45numValueDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12\x32\n\x07options\x18\x03 \x01(\x0b\x32!.google.protobuf.EnumValueOptions\"\x90\x01\n\x16ServiceDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06method\x18\x02 \x03(\x0b\x32&.google.protobuf.MethodDescriptorProto\x12\x30\n\x07options\x18\x03 \x01(\x0b\x32\x1f.google.protobuf.ServiceOptions\"\xc1\x01\n\x15MethodDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ninput_type\x18\x02 \x01(\t\x12\x13\n\x0boutput_type\x18\x03 \x01(\t\x12/\n\x07options\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.MethodOptions\x12\x1f\n\x10\x63lient_streaming\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10server_streaming\x18\x06 \x01(\x08:\x05\x66\x61lse\"\xa6\x06\n\x0b\x46ileOptions\x12\x14\n\x0cjava_package\x18\x01 \x01(\t\x12\x1c\n\x14java_outer_classname\x18\x08 \x01(\t\x12\"\n\x13java_multiple_files\x18\n \x01(\x08:\x05\x66\x61lse\x12)\n\x1djava_generate_equals_and_hash\x18\x14 \x01(\x08\x42\x02\x18\x01\x12%\n\x16java_string_check_utf8\x18\x1b \x01(\x08:\x05\x66\x61lse\x12\x46\n\x0coptimize_for\x18\t \x01(\x0e\x32).google.protobuf.FileOptions.OptimizeMode:\x05SPEED\x12\x12\n\ngo_package\x18\x0b \x01(\t\x12\"\n\x13\x63\x63_generic_services\x18\x10 \x01(\x08:\x05\x66\x61lse\x12$\n\x15java_generic_services\x18\x11 \x01(\x08:\x05\x66\x61lse\x12\"\n\x13py_generic_services\x18\x12 \x01(\x08:\x05\x66\x61lse\x12#\n\x14php_generic_services\x18* \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10\x63\x63_enable_arenas\x18\x1f \x01(\x08:\x05\x66\x61lse\x12\x19\n\x11objc_class_prefix\x18$ \x01(\t\x12\x18\n\x10\x63sharp_namespace\x18% \x01(\t\x12\x14\n\x0cswift_prefix\x18\' \x01(\t\x12\x18\n\x10php_class_prefix\x18( \x01(\t\x12\x15\n\rphp_namespace\x18) \x01(\t\x12\x1e\n\x16php_metadata_namespace\x18, \x01(\t\x12\x14\n\x0cruby_package\x18- \x01(\t\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\":\n\x0cOptimizeMode\x12\t\n\x05SPEED\x10\x01\x12\r\n\tCODE_SIZE\x10\x02\x12\x10\n\x0cLITE_RUNTIME\x10\x03*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08&\x10\'\"\xf2\x01\n\x0eMessageOptions\x12&\n\x17message_set_wire_format\x18\x01 \x01(\x08:\x05\x66\x61lse\x12.\n\x1fno_standard_descriptor_accessor\x18\x02 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x11\n\tmap_entry\x18\x07 \x01(\x08\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x08\x10\tJ\x04\x08\t\x10\n\"\x9e\x03\n\x0c\x46ieldOptions\x12:\n\x05\x63type\x18\x01 \x01(\x0e\x32#.google.protobuf.FieldOptions.CType:\x06STRING\x12\x0e\n\x06packed\x18\x02 \x01(\x08\x12?\n\x06jstype\x18\x06 \x01(\x0e\x32$.google.protobuf.FieldOptions.JSType:\tJS_NORMAL\x12\x13\n\x04lazy\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x13\n\x04weak\x18\n \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"/\n\x05\x43Type\x12\n\n\x06STRING\x10\x00\x12\x08\n\x04\x43ORD\x10\x01\x12\x10\n\x0cSTRING_PIECE\x10\x02\"5\n\x06JSType\x12\r\n\tJS_NORMAL\x10\x00\x12\r\n\tJS_STRING\x10\x01\x12\r\n\tJS_NUMBER\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x04\x10\x05\"^\n\x0cOneofOptions\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x93\x01\n\x0b\x45numOptions\x12\x13\n\x0b\x61llow_alias\x18\x02 \x01(\x08\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x05\x10\x06\"}\n\x10\x45numValueOptions\x12\x19\n\ndeprecated\x18\x01 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"{\n\x0eServiceOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xad\x02\n\rMethodOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12_\n\x11idempotency_level\x18\" \x01(\x0e\x32/.google.protobuf.MethodOptions.IdempotencyLevel:\x13IDEMPOTENCY_UNKNOWN\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"P\n\x10IdempotencyLevel\x12\x17\n\x13IDEMPOTENCY_UNKNOWN\x10\x00\x12\x13\n\x0fNO_SIDE_EFFECTS\x10\x01\x12\x0e\n\nIDEMPOTENT\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x9e\x02\n\x13UninterpretedOption\x12;\n\x04name\x18\x02 \x03(\x0b\x32-.google.protobuf.UninterpretedOption.NamePart\x12\x18\n\x10identifier_value\x18\x03 \x01(\t\x12\x1a\n\x12positive_int_value\x18\x04 \x01(\x04\x12\x1a\n\x12negative_int_value\x18\x05 \x01(\x03\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x14\n\x0cstring_value\x18\x07 \x01(\x0c\x12\x17\n\x0f\x61ggregate_value\x18\x08 \x01(\t\x1a\x33\n\x08NamePart\x12\x11\n\tname_part\x18\x01 \x02(\t\x12\x14\n\x0cis_extension\x18\x02 \x02(\x08\"\xd5\x01\n\x0eSourceCodeInfo\x12:\n\x08location\x18\x01 \x03(\x0b\x32(.google.protobuf.SourceCodeInfo.Location\x1a\x86\x01\n\x08Location\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x10\n\x04span\x18\x02 \x03(\x05\x42\x02\x10\x01\x12\x18\n\x10leading_comments\x18\x03 \x01(\t\x12\x19\n\x11trailing_comments\x18\x04 \x01(\t\x12!\n\x19leading_detached_comments\x18\x06 \x03(\t\"\xa7\x01\n\x11GeneratedCodeInfo\x12\x41\n\nannotation\x18\x01 \x03(\x0b\x32-.google.protobuf.GeneratedCodeInfo.Annotation\x1aO\n\nAnnotation\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x13\n\x0bsource_file\x18\x02 \x01(\t\x12\r\n\x05\x62\x65gin\x18\x03 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x04 \x01(\x05\x42\x8f\x01\n\x13\x63om.google.protobufB\x10\x44\x65scriptorProtosH\x01Z>github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection') +) + + + +_FIELDDESCRIPTORPROTO_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='google.protobuf.FieldDescriptorProto.Type', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_DOUBLE', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FLOAT', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT64', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT64', index=3, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT32', index=4, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED64', index=5, number=6, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED32', index=6, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BOOL', index=7, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_STRING', index=8, number=9, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_GROUP', index=9, number=10, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_MESSAGE', index=10, number=11, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BYTES', index=11, number=12, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT32', index=12, number=13, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_ENUM', index=13, number=14, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED32', index=14, number=15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED64', index=15, number=16, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT32', index=16, number=17, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT64', index=17, number=18, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1715, + serialized_end=2025, +) +_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_TYPE) + +_FIELDDESCRIPTORPROTO_LABEL = _descriptor.EnumDescriptor( + name='Label', + full_name='google.protobuf.FieldDescriptorProto.Label', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LABEL_OPTIONAL', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LABEL_REQUIRED', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LABEL_REPEATED', index=2, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2027, + serialized_end=2094, +) +_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_LABEL) + +_FILEOPTIONS_OPTIMIZEMODE = _descriptor.EnumDescriptor( + name='OptimizeMode', + full_name='google.protobuf.FileOptions.OptimizeMode', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SPEED', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CODE_SIZE', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='LITE_RUNTIME', index=2, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3662, + serialized_end=3720, +) +_sym_db.RegisterEnumDescriptor(_FILEOPTIONS_OPTIMIZEMODE) + +_FIELDOPTIONS_CTYPE = _descriptor.EnumDescriptor( + name='CType', + full_name='google.protobuf.FieldOptions.CType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='STRING', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CORD', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='STRING_PIECE', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=4280, + serialized_end=4327, +) +_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_CTYPE) + +_FIELDOPTIONS_JSTYPE = _descriptor.EnumDescriptor( + name='JSType', + full_name='google.protobuf.FieldOptions.JSType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='JS_NORMAL', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='JS_STRING', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='JS_NUMBER', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=4329, + serialized_end=4382, +) +_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_JSTYPE) + +_METHODOPTIONS_IDEMPOTENCYLEVEL = _descriptor.EnumDescriptor( + name='IdempotencyLevel', + full_name='google.protobuf.MethodOptions.IdempotencyLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IDEMPOTENCY_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NO_SIDE_EFFECTS', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IDEMPOTENT', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=5110, + serialized_end=5190, +) +_sym_db.RegisterEnumDescriptor(_METHODOPTIONS_IDEMPOTENCYLEVEL) + + +_FILEDESCRIPTORSET = _descriptor.Descriptor( + name='FileDescriptorSet', + full_name='google.protobuf.FileDescriptorSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.FileDescriptorSet.file', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=53, + serialized_end=124, +) + + +_FILEDESCRIPTORPROTO = _descriptor.Descriptor( + name='FileDescriptorProto', + full_name='google.protobuf.FileDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.FileDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='package', full_name='google.protobuf.FileDescriptorProto.package', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dependency', full_name='google.protobuf.FileDescriptorProto.dependency', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='public_dependency', full_name='google.protobuf.FileDescriptorProto.public_dependency', index=3, + number=10, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weak_dependency', full_name='google.protobuf.FileDescriptorProto.weak_dependency', index=4, + number=11, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_type', full_name='google.protobuf.FileDescriptorProto.message_type', index=5, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_type', full_name='google.protobuf.FileDescriptorProto.enum_type', index=6, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='service', full_name='google.protobuf.FileDescriptorProto.service', index=7, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extension', full_name='google.protobuf.FileDescriptorProto.extension', index=8, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.FileDescriptorProto.options', index=9, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_code_info', full_name='google.protobuf.FileDescriptorProto.source_code_info', index=10, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.FileDescriptorProto.syntax', index=11, + number=12, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=127, + serialized_end=602, +) + + +_DESCRIPTORPROTO_EXTENSIONRANGE = _descriptor.Descriptor( + name='ExtensionRange', + full_name='google.protobuf.DescriptorProto.ExtensionRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.DescriptorProto.ExtensionRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.DescriptorProto.ExtensionRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.DescriptorProto.ExtensionRange.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1140, + serialized_end=1241, +) + +_DESCRIPTORPROTO_RESERVEDRANGE = _descriptor.Descriptor( + name='ReservedRange', + full_name='google.protobuf.DescriptorProto.ReservedRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.DescriptorProto.ReservedRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.DescriptorProto.ReservedRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1243, + serialized_end=1286, +) + +_DESCRIPTORPROTO = _descriptor.Descriptor( + name='DescriptorProto', + full_name='google.protobuf.DescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.DescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field', full_name='google.protobuf.DescriptorProto.field', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extension', full_name='google.protobuf.DescriptorProto.extension', index=2, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_type', full_name='google.protobuf.DescriptorProto.nested_type', index=3, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_type', full_name='google.protobuf.DescriptorProto.enum_type', index=4, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extension_range', full_name='google.protobuf.DescriptorProto.extension_range', index=5, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_decl', full_name='google.protobuf.DescriptorProto.oneof_decl', index=6, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.DescriptorProto.options', index=7, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_range', full_name='google.protobuf.DescriptorProto.reserved_range', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_name', full_name='google.protobuf.DescriptorProto.reserved_name', index=9, + number=10, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPROTO_EXTENSIONRANGE, _DESCRIPTORPROTO_RESERVEDRANGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=605, + serialized_end=1286, +) + + +_EXTENSIONRANGEOPTIONS = _descriptor.Descriptor( + name='ExtensionRangeOptions', + full_name='google.protobuf.ExtensionRangeOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.ExtensionRangeOptions.uninterpreted_option', index=0, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=1288, + serialized_end=1391, +) + + +_FIELDDESCRIPTORPROTO = _descriptor.Descriptor( + name='FieldDescriptorProto', + full_name='google.protobuf.FieldDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.FieldDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.FieldDescriptorProto.number', index=1, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='label', full_name='google.protobuf.FieldDescriptorProto.label', index=2, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type', full_name='google.protobuf.FieldDescriptorProto.type', index=3, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type_name', full_name='google.protobuf.FieldDescriptorProto.type_name', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='extendee', full_name='google.protobuf.FieldDescriptorProto.extendee', index=5, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_value', full_name='google.protobuf.FieldDescriptorProto.default_value', index=6, + number=7, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_index', full_name='google.protobuf.FieldDescriptorProto.oneof_index', index=7, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='json_name', full_name='google.protobuf.FieldDescriptorProto.json_name', index=8, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.FieldDescriptorProto.options', index=9, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELDDESCRIPTORPROTO_TYPE, + _FIELDDESCRIPTORPROTO_LABEL, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1394, + serialized_end=2094, +) + + +_ONEOFDESCRIPTORPROTO = _descriptor.Descriptor( + name='OneofDescriptorProto', + full_name='google.protobuf.OneofDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.OneofDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.OneofDescriptorProto.options', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2096, + serialized_end=2180, +) + + +_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE = _descriptor.Descriptor( + name='EnumReservedRange', + full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2428, + serialized_end=2475, +) + +_ENUMDESCRIPTORPROTO = _descriptor.Descriptor( + name='EnumDescriptorProto', + full_name='google.protobuf.EnumDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.EnumDescriptorProto.value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_range', full_name='google.protobuf.EnumDescriptorProto.reserved_range', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reserved_name', full_name='google.protobuf.EnumDescriptorProto.reserved_name', index=4, + number=5, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2183, + serialized_end=2475, +) + + +_ENUMVALUEDESCRIPTORPROTO = _descriptor.Descriptor( + name='EnumValueDescriptorProto', + full_name='google.protobuf.EnumValueDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumValueDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.EnumValueDescriptorProto.number', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumValueDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2477, + serialized_end=2585, +) + + +_SERVICEDESCRIPTORPROTO = _descriptor.Descriptor( + name='ServiceDescriptorProto', + full_name='google.protobuf.ServiceDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.ServiceDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='method', full_name='google.protobuf.ServiceDescriptorProto.method', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.ServiceDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2588, + serialized_end=2732, +) + + +_METHODDESCRIPTORPROTO = _descriptor.Descriptor( + name='MethodDescriptorProto', + full_name='google.protobuf.MethodDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.MethodDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='input_type', full_name='google.protobuf.MethodDescriptorProto.input_type', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='output_type', full_name='google.protobuf.MethodDescriptorProto.output_type', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.MethodDescriptorProto.options', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='client_streaming', full_name='google.protobuf.MethodDescriptorProto.client_streaming', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='server_streaming', full_name='google.protobuf.MethodDescriptorProto.server_streaming', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2735, + serialized_end=2928, +) + + +_FILEOPTIONS = _descriptor.Descriptor( + name='FileOptions', + full_name='google.protobuf.FileOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='java_package', full_name='google.protobuf.FileOptions.java_package', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_outer_classname', full_name='google.protobuf.FileOptions.java_outer_classname', index=1, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_multiple_files', full_name='google.protobuf.FileOptions.java_multiple_files', index=2, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_generate_equals_and_hash', full_name='google.protobuf.FileOptions.java_generate_equals_and_hash', index=3, + number=20, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_string_check_utf8', full_name='google.protobuf.FileOptions.java_string_check_utf8', index=4, + number=27, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optimize_for', full_name='google.protobuf.FileOptions.optimize_for', index=5, + number=9, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='go_package', full_name='google.protobuf.FileOptions.go_package', index=6, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cc_generic_services', full_name='google.protobuf.FileOptions.cc_generic_services', index=7, + number=16, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='java_generic_services', full_name='google.protobuf.FileOptions.java_generic_services', index=8, + number=17, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='py_generic_services', full_name='google.protobuf.FileOptions.py_generic_services', index=9, + number=18, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_generic_services', full_name='google.protobuf.FileOptions.php_generic_services', index=10, + number=42, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.FileOptions.deprecated', index=11, + number=23, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cc_enable_arenas', full_name='google.protobuf.FileOptions.cc_enable_arenas', index=12, + number=31, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='objc_class_prefix', full_name='google.protobuf.FileOptions.objc_class_prefix', index=13, + number=36, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='csharp_namespace', full_name='google.protobuf.FileOptions.csharp_namespace', index=14, + number=37, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='swift_prefix', full_name='google.protobuf.FileOptions.swift_prefix', index=15, + number=39, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_class_prefix', full_name='google.protobuf.FileOptions.php_class_prefix', index=16, + number=40, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_namespace', full_name='google.protobuf.FileOptions.php_namespace', index=17, + number=41, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='php_metadata_namespace', full_name='google.protobuf.FileOptions.php_metadata_namespace', index=18, + number=44, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ruby_package', full_name='google.protobuf.FileOptions.ruby_package', index=19, + number=45, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.FileOptions.uninterpreted_option', index=20, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FILEOPTIONS_OPTIMIZEMODE, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=2931, + serialized_end=3737, +) + + +_MESSAGEOPTIONS = _descriptor.Descriptor( + name='MessageOptions', + full_name='google.protobuf.MessageOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_set_wire_format', full_name='google.protobuf.MessageOptions.message_set_wire_format', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='no_standard_descriptor_accessor', full_name='google.protobuf.MessageOptions.no_standard_descriptor_accessor', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.MessageOptions.deprecated', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_entry', full_name='google.protobuf.MessageOptions.map_entry', index=3, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.MessageOptions.uninterpreted_option', index=4, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=3740, + serialized_end=3982, +) + + +_FIELDOPTIONS = _descriptor.Descriptor( + name='FieldOptions', + full_name='google.protobuf.FieldOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='ctype', full_name='google.protobuf.FieldOptions.ctype', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed', full_name='google.protobuf.FieldOptions.packed', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='jstype', full_name='google.protobuf.FieldOptions.jstype', index=2, + number=6, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lazy', full_name='google.protobuf.FieldOptions.lazy', index=3, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.FieldOptions.deprecated', index=4, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='weak', full_name='google.protobuf.FieldOptions.weak', index=5, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.FieldOptions.uninterpreted_option', index=6, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELDOPTIONS_CTYPE, + _FIELDOPTIONS_JSTYPE, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=3985, + serialized_end=4399, +) + + +_ONEOFOPTIONS = _descriptor.Descriptor( + name='OneofOptions', + full_name='google.protobuf.OneofOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.OneofOptions.uninterpreted_option', index=0, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4401, + serialized_end=4495, +) + + +_ENUMOPTIONS = _descriptor.Descriptor( + name='EnumOptions', + full_name='google.protobuf.EnumOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='allow_alias', full_name='google.protobuf.EnumOptions.allow_alias', index=0, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.EnumOptions.deprecated', index=1, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.EnumOptions.uninterpreted_option', index=2, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4498, + serialized_end=4645, +) + + +_ENUMVALUEOPTIONS = _descriptor.Descriptor( + name='EnumValueOptions', + full_name='google.protobuf.EnumValueOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.EnumValueOptions.deprecated', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.EnumValueOptions.uninterpreted_option', index=1, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4647, + serialized_end=4772, +) + + +_SERVICEOPTIONS = _descriptor.Descriptor( + name='ServiceOptions', + full_name='google.protobuf.ServiceOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.ServiceOptions.deprecated', index=0, + number=33, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.ServiceOptions.uninterpreted_option', index=1, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4774, + serialized_end=4897, +) + + +_METHODOPTIONS = _descriptor.Descriptor( + name='MethodOptions', + full_name='google.protobuf.MethodOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.MethodOptions.deprecated', index=0, + number=33, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='idempotency_level', full_name='google.protobuf.MethodOptions.idempotency_level', index=1, + number=34, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.MethodOptions.uninterpreted_option', index=2, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _METHODOPTIONS_IDEMPOTENCYLEVEL, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4900, + serialized_end=5201, +) + + +_UNINTERPRETEDOPTION_NAMEPART = _descriptor.Descriptor( + name='NamePart', + full_name='google.protobuf.UninterpretedOption.NamePart', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name_part', full_name='google.protobuf.UninterpretedOption.NamePart.name_part', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='is_extension', full_name='google.protobuf.UninterpretedOption.NamePart.is_extension', index=1, + number=2, type=8, cpp_type=7, label=2, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5439, + serialized_end=5490, +) + +_UNINTERPRETEDOPTION = _descriptor.Descriptor( + name='UninterpretedOption', + full_name='google.protobuf.UninterpretedOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.UninterpretedOption.name', index=0, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='identifier_value', full_name='google.protobuf.UninterpretedOption.identifier_value', index=1, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='positive_int_value', full_name='google.protobuf.UninterpretedOption.positive_int_value', index=2, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='negative_int_value', full_name='google.protobuf.UninterpretedOption.negative_int_value', index=3, + number=5, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_value', full_name='google.protobuf.UninterpretedOption.double_value', index=4, + number=6, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='google.protobuf.UninterpretedOption.string_value', index=5, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='aggregate_value', full_name='google.protobuf.UninterpretedOption.aggregate_value', index=6, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_UNINTERPRETEDOPTION_NAMEPART, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5204, + serialized_end=5490, +) + + +_SOURCECODEINFO_LOCATION = _descriptor.Descriptor( + name='Location', + full_name='google.protobuf.SourceCodeInfo.Location', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='path', full_name='google.protobuf.SourceCodeInfo.Location.path', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='span', full_name='google.protobuf.SourceCodeInfo.Location.span', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='leading_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_comments', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='trailing_comments', full_name='google.protobuf.SourceCodeInfo.Location.trailing_comments', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='leading_detached_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_detached_comments', index=4, + number=6, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5572, + serialized_end=5706, +) + +_SOURCECODEINFO = _descriptor.Descriptor( + name='SourceCodeInfo', + full_name='google.protobuf.SourceCodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='location', full_name='google.protobuf.SourceCodeInfo.location', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_SOURCECODEINFO_LOCATION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5493, + serialized_end=5706, +) + + +_GENERATEDCODEINFO_ANNOTATION = _descriptor.Descriptor( + name='Annotation', + full_name='google.protobuf.GeneratedCodeInfo.Annotation', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='path', full_name='google.protobuf.GeneratedCodeInfo.Annotation.path', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_file', full_name='google.protobuf.GeneratedCodeInfo.Annotation.source_file', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='begin', full_name='google.protobuf.GeneratedCodeInfo.Annotation.begin', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.GeneratedCodeInfo.Annotation.end', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5797, + serialized_end=5876, +) + +_GENERATEDCODEINFO = _descriptor.Descriptor( + name='GeneratedCodeInfo', + full_name='google.protobuf.GeneratedCodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='annotation', full_name='google.protobuf.GeneratedCodeInfo.annotation', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_GENERATEDCODEINFO_ANNOTATION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5709, + serialized_end=5876, +) + +_FILEDESCRIPTORSET.fields_by_name['file'].message_type = _FILEDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['message_type'].message_type = _DESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['service'].message_type = _SERVICEDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['options'].message_type = _FILEOPTIONS +_FILEDESCRIPTORPROTO.fields_by_name['source_code_info'].message_type = _SOURCECODEINFO +_DESCRIPTORPROTO_EXTENSIONRANGE.fields_by_name['options'].message_type = _EXTENSIONRANGEOPTIONS +_DESCRIPTORPROTO_EXTENSIONRANGE.containing_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO_RESERVEDRANGE.containing_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['field'].message_type = _FIELDDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['nested_type'].message_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['extension_range'].message_type = _DESCRIPTORPROTO_EXTENSIONRANGE +_DESCRIPTORPROTO.fields_by_name['oneof_decl'].message_type = _ONEOFDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['options'].message_type = _MESSAGEOPTIONS +_DESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _DESCRIPTORPROTO_RESERVEDRANGE +_EXTENSIONRANGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDDESCRIPTORPROTO.fields_by_name['label'].enum_type = _FIELDDESCRIPTORPROTO_LABEL +_FIELDDESCRIPTORPROTO.fields_by_name['type'].enum_type = _FIELDDESCRIPTORPROTO_TYPE +_FIELDDESCRIPTORPROTO.fields_by_name['options'].message_type = _FIELDOPTIONS +_FIELDDESCRIPTORPROTO_TYPE.containing_type = _FIELDDESCRIPTORPROTO +_FIELDDESCRIPTORPROTO_LABEL.containing_type = _FIELDDESCRIPTORPROTO +_ONEOFDESCRIPTORPROTO.fields_by_name['options'].message_type = _ONEOFOPTIONS +_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE.containing_type = _ENUMDESCRIPTORPROTO +_ENUMDESCRIPTORPROTO.fields_by_name['value'].message_type = _ENUMVALUEDESCRIPTORPROTO +_ENUMDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMOPTIONS +_ENUMDESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE +_ENUMVALUEDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMVALUEOPTIONS +_SERVICEDESCRIPTORPROTO.fields_by_name['method'].message_type = _METHODDESCRIPTORPROTO +_SERVICEDESCRIPTORPROTO.fields_by_name['options'].message_type = _SERVICEOPTIONS +_METHODDESCRIPTORPROTO.fields_by_name['options'].message_type = _METHODOPTIONS +_FILEOPTIONS.fields_by_name['optimize_for'].enum_type = _FILEOPTIONS_OPTIMIZEMODE +_FILEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FILEOPTIONS_OPTIMIZEMODE.containing_type = _FILEOPTIONS +_MESSAGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDOPTIONS.fields_by_name['ctype'].enum_type = _FIELDOPTIONS_CTYPE +_FIELDOPTIONS.fields_by_name['jstype'].enum_type = _FIELDOPTIONS_JSTYPE +_FIELDOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDOPTIONS_CTYPE.containing_type = _FIELDOPTIONS +_FIELDOPTIONS_JSTYPE.containing_type = _FIELDOPTIONS +_ONEOFOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_ENUMOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_ENUMVALUEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_SERVICEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_METHODOPTIONS.fields_by_name['idempotency_level'].enum_type = _METHODOPTIONS_IDEMPOTENCYLEVEL +_METHODOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_METHODOPTIONS_IDEMPOTENCYLEVEL.containing_type = _METHODOPTIONS +_UNINTERPRETEDOPTION_NAMEPART.containing_type = _UNINTERPRETEDOPTION +_UNINTERPRETEDOPTION.fields_by_name['name'].message_type = _UNINTERPRETEDOPTION_NAMEPART +_SOURCECODEINFO_LOCATION.containing_type = _SOURCECODEINFO +_SOURCECODEINFO.fields_by_name['location'].message_type = _SOURCECODEINFO_LOCATION +_GENERATEDCODEINFO_ANNOTATION.containing_type = _GENERATEDCODEINFO +_GENERATEDCODEINFO.fields_by_name['annotation'].message_type = _GENERATEDCODEINFO_ANNOTATION +DESCRIPTOR.message_types_by_name['FileDescriptorSet'] = _FILEDESCRIPTORSET +DESCRIPTOR.message_types_by_name['FileDescriptorProto'] = _FILEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['DescriptorProto'] = _DESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['ExtensionRangeOptions'] = _EXTENSIONRANGEOPTIONS +DESCRIPTOR.message_types_by_name['FieldDescriptorProto'] = _FIELDDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['OneofDescriptorProto'] = _ONEOFDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['EnumDescriptorProto'] = _ENUMDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['EnumValueDescriptorProto'] = _ENUMVALUEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['ServiceDescriptorProto'] = _SERVICEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['MethodDescriptorProto'] = _METHODDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['FileOptions'] = _FILEOPTIONS +DESCRIPTOR.message_types_by_name['MessageOptions'] = _MESSAGEOPTIONS +DESCRIPTOR.message_types_by_name['FieldOptions'] = _FIELDOPTIONS +DESCRIPTOR.message_types_by_name['OneofOptions'] = _ONEOFOPTIONS +DESCRIPTOR.message_types_by_name['EnumOptions'] = _ENUMOPTIONS +DESCRIPTOR.message_types_by_name['EnumValueOptions'] = _ENUMVALUEOPTIONS +DESCRIPTOR.message_types_by_name['ServiceOptions'] = _SERVICEOPTIONS +DESCRIPTOR.message_types_by_name['MethodOptions'] = _METHODOPTIONS +DESCRIPTOR.message_types_by_name['UninterpretedOption'] = _UNINTERPRETEDOPTION +DESCRIPTOR.message_types_by_name['SourceCodeInfo'] = _SOURCECODEINFO +DESCRIPTOR.message_types_by_name['GeneratedCodeInfo'] = _GENERATEDCODEINFO +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FileDescriptorSet = _reflection.GeneratedProtocolMessageType('FileDescriptorSet', (_message.Message,), dict( + DESCRIPTOR = _FILEDESCRIPTORSET, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + )) +_sym_db.RegisterMessage(FileDescriptorSet) + +FileDescriptorProto = _reflection.GeneratedProtocolMessageType('FileDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _FILEDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + )) +_sym_db.RegisterMessage(FileDescriptorProto) + +DescriptorProto = _reflection.GeneratedProtocolMessageType('DescriptorProto', (_message.Message,), dict( + + ExtensionRange = _reflection.GeneratedProtocolMessageType('ExtensionRange', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPROTO_EXTENSIONRANGE, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + )) + , + + ReservedRange = _reflection.GeneratedProtocolMessageType('ReservedRange', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPROTO_RESERVEDRANGE, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) + )) + , + DESCRIPTOR = _DESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + )) +_sym_db.RegisterMessage(DescriptorProto) +_sym_db.RegisterMessage(DescriptorProto.ExtensionRange) +_sym_db.RegisterMessage(DescriptorProto.ReservedRange) + +ExtensionRangeOptions = _reflection.GeneratedProtocolMessageType('ExtensionRangeOptions', (_message.Message,), dict( + DESCRIPTOR = _EXTENSIONRANGEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions) + )) +_sym_db.RegisterMessage(ExtensionRangeOptions) + +FieldDescriptorProto = _reflection.GeneratedProtocolMessageType('FieldDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _FIELDDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) + )) +_sym_db.RegisterMessage(FieldDescriptorProto) + +OneofDescriptorProto = _reflection.GeneratedProtocolMessageType('OneofDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _ONEOFDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) + )) +_sym_db.RegisterMessage(OneofDescriptorProto) + +EnumDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumDescriptorProto', (_message.Message,), dict( + + EnumReservedRange = _reflection.GeneratedProtocolMessageType('EnumReservedRange', (_message.Message,), dict( + DESCRIPTOR = _ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto.EnumReservedRange) + )) + , + DESCRIPTOR = _ENUMDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + )) +_sym_db.RegisterMessage(EnumDescriptorProto) +_sym_db.RegisterMessage(EnumDescriptorProto.EnumReservedRange) + +EnumValueDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumValueDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _ENUMVALUEDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) + )) +_sym_db.RegisterMessage(EnumValueDescriptorProto) + +ServiceDescriptorProto = _reflection.GeneratedProtocolMessageType('ServiceDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _SERVICEDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) + )) +_sym_db.RegisterMessage(ServiceDescriptorProto) + +MethodDescriptorProto = _reflection.GeneratedProtocolMessageType('MethodDescriptorProto', (_message.Message,), dict( + DESCRIPTOR = _METHODDESCRIPTORPROTO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) + )) +_sym_db.RegisterMessage(MethodDescriptorProto) + +FileOptions = _reflection.GeneratedProtocolMessageType('FileOptions', (_message.Message,), dict( + DESCRIPTOR = _FILEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) + )) +_sym_db.RegisterMessage(FileOptions) + +MessageOptions = _reflection.GeneratedProtocolMessageType('MessageOptions', (_message.Message,), dict( + DESCRIPTOR = _MESSAGEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) + )) +_sym_db.RegisterMessage(MessageOptions) + +FieldOptions = _reflection.GeneratedProtocolMessageType('FieldOptions', (_message.Message,), dict( + DESCRIPTOR = _FIELDOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) + )) +_sym_db.RegisterMessage(FieldOptions) + +OneofOptions = _reflection.GeneratedProtocolMessageType('OneofOptions', (_message.Message,), dict( + DESCRIPTOR = _ONEOFOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.OneofOptions) + )) +_sym_db.RegisterMessage(OneofOptions) + +EnumOptions = _reflection.GeneratedProtocolMessageType('EnumOptions', (_message.Message,), dict( + DESCRIPTOR = _ENUMOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) + )) +_sym_db.RegisterMessage(EnumOptions) + +EnumValueOptions = _reflection.GeneratedProtocolMessageType('EnumValueOptions', (_message.Message,), dict( + DESCRIPTOR = _ENUMVALUEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) + )) +_sym_db.RegisterMessage(EnumValueOptions) + +ServiceOptions = _reflection.GeneratedProtocolMessageType('ServiceOptions', (_message.Message,), dict( + DESCRIPTOR = _SERVICEOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) + )) +_sym_db.RegisterMessage(ServiceOptions) + +MethodOptions = _reflection.GeneratedProtocolMessageType('MethodOptions', (_message.Message,), dict( + DESCRIPTOR = _METHODOPTIONS, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) + )) +_sym_db.RegisterMessage(MethodOptions) + +UninterpretedOption = _reflection.GeneratedProtocolMessageType('UninterpretedOption', (_message.Message,), dict( + + NamePart = _reflection.GeneratedProtocolMessageType('NamePart', (_message.Message,), dict( + DESCRIPTOR = _UNINTERPRETEDOPTION_NAMEPART, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) + )) + , + DESCRIPTOR = _UNINTERPRETEDOPTION, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) + )) +_sym_db.RegisterMessage(UninterpretedOption) +_sym_db.RegisterMessage(UninterpretedOption.NamePart) + +SourceCodeInfo = _reflection.GeneratedProtocolMessageType('SourceCodeInfo', (_message.Message,), dict( + + Location = _reflection.GeneratedProtocolMessageType('Location', (_message.Message,), dict( + DESCRIPTOR = _SOURCECODEINFO_LOCATION, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + )) + , + DESCRIPTOR = _SOURCECODEINFO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + )) +_sym_db.RegisterMessage(SourceCodeInfo) +_sym_db.RegisterMessage(SourceCodeInfo.Location) + +GeneratedCodeInfo = _reflection.GeneratedProtocolMessageType('GeneratedCodeInfo', (_message.Message,), dict( + + Annotation = _reflection.GeneratedProtocolMessageType('Annotation', (_message.Message,), dict( + DESCRIPTOR = _GENERATEDCODEINFO_ANNOTATION, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation) + )) + , + DESCRIPTOR = _GENERATEDCODEINFO, + __module__ = 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo) + )) +_sym_db.RegisterMessage(GeneratedCodeInfo) +_sym_db.RegisterMessage(GeneratedCodeInfo.Annotation) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/descriptor_pool.py b/winvenv/Lib/site-packages/google/protobuf/descriptor_pool.py new file mode 100644 index 0000000..8983f76 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/descriptor_pool.py @@ -0,0 +1,1057 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides DescriptorPool to use as a container for proto2 descriptors. + +The DescriptorPool is used in conjection with a DescriptorDatabase to maintain +a collection of protocol buffer descriptors for use when dynamically creating +message types at runtime. + +For most applications protocol buffers should be used via modules generated by +the protocol buffer compiler tool. This should only be used when the type of +protocol buffers used in an application or library cannot be predetermined. + +Below is a straightforward example on how to use this class: + + pool = DescriptorPool() + file_descriptor_protos = [ ... ] + for file_descriptor_proto in file_descriptor_protos: + pool.Add(file_descriptor_proto) + my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType') + +The message descriptor can be used in conjunction with the message_factory +module in order to create a protocol buffer class that can be encoded and +decoded. + +If you want to get a Python class for the specified proto, use the +helper functions inside google.protobuf.message_factory +directly instead of this class. +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import collections +import warnings + +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import text_encoding + + +_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS # pylint: disable=protected-access + + +def _NormalizeFullyQualifiedName(name): + """Remove leading period from fully-qualified type name. + + Due to b/13860351 in descriptor_database.py, types in the root namespace are + generated with a leading period. This function removes that prefix. + + Args: + name: A str, the fully-qualified symbol name. + + Returns: + A str, the normalized fully-qualified symbol name. + """ + return name.lstrip('.') + + +def _OptionsOrNone(descriptor_proto): + """Returns the value of the field `options`, or None if it is not set.""" + if descriptor_proto.HasField('options'): + return descriptor_proto.options + else: + return None + + +def _IsMessageSetExtension(field): + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL) + + +class DescriptorPool(object): + """A collection of protobufs dynamically constructed by descriptor protos.""" + + if _USE_C_DESCRIPTORS: + + def __new__(cls, descriptor_db=None): + # pylint: disable=protected-access + return descriptor._message.DescriptorPool(descriptor_db) + + def __init__(self, descriptor_db=None): + """Initializes a Pool of proto buffs. + + The descriptor_db argument to the constructor is provided to allow + specialized file descriptor proto lookup code to be triggered on demand. An + example would be an implementation which will read and compile a file + specified in a call to FindFileByName() and not require the call to Add() + at all. Results from this database will be cached internally here as well. + + Args: + descriptor_db: A secondary source of file descriptors. + """ + + self._internal_db = descriptor_database.DescriptorDatabase() + self._descriptor_db = descriptor_db + self._descriptors = {} + self._enum_descriptors = {} + self._service_descriptors = {} + self._file_descriptors = {} + self._toplevel_extensions = {} + # TODO(jieluo): Remove _file_desc_by_toplevel_extension after + # maybe year 2020 for compatibility issue (with 3.4.1 only). + self._file_desc_by_toplevel_extension = {} + # We store extensions in two two-level mappings: The first key is the + # descriptor of the message being extended, the second key is the extension + # full name or its tag number. + self._extensions_by_name = collections.defaultdict(dict) + self._extensions_by_number = collections.defaultdict(dict) + + def _CheckConflictRegister(self, desc): + """Check if the descriptor name conflicts with another of the same name. + + Args: + desc: Descriptor of a message, enum, service or extension. + """ + desc_name = desc.full_name + for register, descriptor_type in [ + (self._descriptors, descriptor.Descriptor), + (self._enum_descriptors, descriptor.EnumDescriptor), + (self._service_descriptors, descriptor.ServiceDescriptor), + (self._toplevel_extensions, descriptor.FieldDescriptor)]: + if desc_name in register: + file_name = register[desc_name].file.name + if not isinstance(desc, descriptor_type) or ( + file_name != desc.file.name): + warn_msg = ('Conflict register for file "' + desc.file.name + + '": ' + desc_name + + ' is already defined in file "' + + file_name + '"') + warnings.warn(warn_msg, RuntimeWarning) + return + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + file_desc_proto: The FileDescriptorProto to add. + """ + + self._internal_db.Add(file_desc_proto) + + def AddSerializedFile(self, serialized_file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + serialized_file_desc_proto: A bytes string, serialization of the + FileDescriptorProto to add. + """ + + # pylint: disable=g-import-not-at-top + from google.protobuf import descriptor_pb2 + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + serialized_file_desc_proto) + self.Add(file_desc_proto) + + def AddDescriptor(self, desc): + """Adds a Descriptor to the pool, non-recursively. + + If the Descriptor contains nested messages or enums, the caller must + explicitly register them. This method also registers the FileDescriptor + associated with the message. + + Args: + desc: A Descriptor. + """ + if not isinstance(desc, descriptor.Descriptor): + raise TypeError('Expected instance of descriptor.Descriptor.') + + self._CheckConflictRegister(desc) + + self._descriptors[desc.full_name] = desc + self._AddFileDescriptor(desc.file) + + def AddEnumDescriptor(self, enum_desc): + """Adds an EnumDescriptor to the pool. + + This method also registers the FileDescriptor associated with the enum. + + Args: + enum_desc: An EnumDescriptor. + """ + + if not isinstance(enum_desc, descriptor.EnumDescriptor): + raise TypeError('Expected instance of descriptor.EnumDescriptor.') + + self._CheckConflictRegister(enum_desc) + self._enum_descriptors[enum_desc.full_name] = enum_desc + self._AddFileDescriptor(enum_desc.file) + + def AddServiceDescriptor(self, service_desc): + """Adds a ServiceDescriptor to the pool. + + Args: + service_desc: A ServiceDescriptor. + """ + + if not isinstance(service_desc, descriptor.ServiceDescriptor): + raise TypeError('Expected instance of descriptor.ServiceDescriptor.') + + self._CheckConflictRegister(service_desc) + self._service_descriptors[service_desc.full_name] = service_desc + + def AddExtensionDescriptor(self, extension): + """Adds a FieldDescriptor describing an extension to the pool. + + Args: + extension: A FieldDescriptor. + + Raises: + AssertionError: when another extension with the same number extends the + same message. + TypeError: when the specified extension is not a + descriptor.FieldDescriptor. + """ + if not (isinstance(extension, descriptor.FieldDescriptor) and + extension.is_extension): + raise TypeError('Expected an extension descriptor.') + + if extension.extension_scope is None: + self._CheckConflictRegister(extension) + self._toplevel_extensions[extension.full_name] = extension + + try: + existing_desc = self._extensions_by_number[ + extension.containing_type][extension.number] + except KeyError: + pass + else: + if extension is not existing_desc: + raise AssertionError( + 'Extensions "%s" and "%s" both try to extend message type "%s" ' + 'with field number %d.' % + (extension.full_name, existing_desc.full_name, + extension.containing_type.full_name, extension.number)) + + self._extensions_by_number[extension.containing_type][ + extension.number] = extension + self._extensions_by_name[extension.containing_type][ + extension.full_name] = extension + + # Also register MessageSet extensions with the type name. + if _IsMessageSetExtension(extension): + self._extensions_by_name[extension.containing_type][ + extension.message_type.full_name] = extension + + def AddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + self._AddFileDescriptor(file_desc) + # TODO(jieluo): This is a temporary solution for FieldDescriptor.file. + # FieldDescriptor.file is added in code gen. Remove this solution after + # maybe 2020 for compatibility reason (with 3.4.1 only). + for extension in file_desc.extensions_by_name.values(): + self._file_desc_by_toplevel_extension[ + extension.full_name] = file_desc + + def _AddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + if not isinstance(file_desc, descriptor.FileDescriptor): + raise TypeError('Expected instance of descriptor.FileDescriptor.') + self._file_descriptors[file_desc.name] = file_desc + + def FindFileByName(self, file_name): + """Gets a FileDescriptor by file name. + + Args: + file_name: The path to the file to get a descriptor for. + + Returns: + A FileDescriptor for the named file. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + + try: + return self._file_descriptors[file_name] + except KeyError: + pass + + try: + file_proto = self._internal_db.FindFileByName(file_name) + except KeyError as error: + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileByName(file_name) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file named %s' % file_name) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def FindFileContainingSymbol(self, symbol): + """Gets the FileDescriptor for the file containing the specified symbol. + + Args: + symbol: The name of the symbol to search for. + + Returns: + A FileDescriptor that contains the specified symbol. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + + symbol = _NormalizeFullyQualifiedName(symbol) + try: + return self._descriptors[symbol].file + except KeyError: + pass + + try: + return self._enum_descriptors[symbol].file + except KeyError: + pass + + try: + return self._service_descriptors[symbol].file + except KeyError: + pass + + try: + return self._FindFileContainingSymbolInDb(symbol) + except KeyError: + pass + + try: + return self._file_desc_by_toplevel_extension[symbol] + except KeyError: + pass + + # Try nested extensions inside a message. + message_name, _, extension_name = symbol.rpartition('.') + try: + message = self.FindMessageTypeByName(message_name) + assert message.extensions_by_name[extension_name] + return message.file + except KeyError: + raise KeyError('Cannot find a file containing %s' % symbol) + + def FindMessageTypeByName(self, full_name): + """Loads the named descriptor from the pool. + + Args: + full_name: The full name of the descriptor to load. + + Returns: + The descriptor for the named type. + + Raises: + KeyError: if the message cannot be found in the pool. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._descriptors[full_name] + + def FindEnumTypeByName(self, full_name): + """Loads the named enum descriptor from the pool. + + Args: + full_name: The full name of the enum descriptor to load. + + Returns: + The enum descriptor for the named type. + + Raises: + KeyError: if the enum cannot be found in the pool. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._enum_descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._enum_descriptors[full_name] + + def FindFieldByName(self, full_name): + """Loads the named field descriptor from the pool. + + Args: + full_name: The full name of the field descriptor to load. + + Returns: + The field descriptor for the named field. + + Raises: + KeyError: if the field cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, field_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.fields_by_name[field_name] + + def FindOneofByName(self, full_name): + """Loads the named oneof descriptor from the pool. + + Args: + full_name: The full name of the oneof descriptor to load. + + Returns: + The oneof descriptor for the named oneof. + + Raises: + KeyError: if the oneof cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, oneof_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.oneofs_by_name[oneof_name] + + def FindExtensionByName(self, full_name): + """Loads the named extension descriptor from the pool. + + Args: + full_name: The full name of the extension descriptor to load. + + Returns: + A FieldDescriptor, describing the named extension. + + Raises: + KeyError: if the extension cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + try: + # The proto compiler does not give any link between the FileDescriptor + # and top-level extensions unless the FileDescriptorProto is added to + # the DescriptorDatabase, but this can impact memory usage. + # So we registered these extensions by name explicitly. + return self._toplevel_extensions[full_name] + except KeyError: + pass + message_name, _, extension_name = full_name.rpartition('.') + try: + # Most extensions are nested inside a message. + scope = self.FindMessageTypeByName(message_name) + except KeyError: + # Some extensions are defined at file scope. + scope = self._FindFileContainingSymbolInDb(full_name) + return scope.extensions_by_name[extension_name] + + def FindExtensionByNumber(self, message_descriptor, number): + """Gets the extension of the specified message with the specified number. + + Extensions have to be registered to this pool by calling + AddExtensionDescriptor. + + Args: + message_descriptor: descriptor of the extended message. + number: integer, number of the extension field. + + Returns: + A FieldDescriptor describing the extension. + + Raises: + KeyError: when no extension with the given number is known for the + specified message. + """ + return self._extensions_by_number[message_descriptor][number] + + def FindAllExtensions(self, message_descriptor): + """Gets all the known extension of a given message. + + Extensions have to be registered to this pool by calling + AddExtensionDescriptor. + + Args: + message_descriptor: descriptor of the extended message. + + Returns: + A list of FieldDescriptor describing the extensions. + """ + return list(self._extensions_by_number[message_descriptor].values()) + + def FindServiceByName(self, full_name): + """Loads the named service descriptor from the pool. + + Args: + full_name: The full name of the service descriptor to load. + + Returns: + The service descriptor for the named service. + + Raises: + KeyError: if the service cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._service_descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._service_descriptors[full_name] + + def _FindFileContainingSymbolInDb(self, symbol): + """Finds the file in descriptor DB containing the specified symbol. + + Args: + symbol: The name of the symbol to search for. + + Returns: + A FileDescriptor that contains the specified symbol. + + Raises: + KeyError: if the file cannot be found in the descriptor database. + """ + try: + file_proto = self._internal_db.FindFileContainingSymbol(symbol) + except KeyError as error: + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileContainingSymbol(symbol) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file containing %s' % symbol) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def _ConvertFileProtoToFileDescriptor(self, file_proto): + """Creates a FileDescriptor from a proto or returns a cached copy. + + This method also has the side effect of loading all the symbols found in + the file into the appropriate dictionaries in the pool. + + Args: + file_proto: The proto to convert. + + Returns: + A FileDescriptor matching the passed in proto. + """ + + if file_proto.name not in self._file_descriptors: + built_deps = list(self._GetDeps(file_proto.dependency)) + direct_deps = [self.FindFileByName(n) for n in file_proto.dependency] + public_deps = [direct_deps[i] for i in file_proto.public_dependency] + + file_descriptor = descriptor.FileDescriptor( + pool=self, + name=file_proto.name, + package=file_proto.package, + syntax=file_proto.syntax, + options=_OptionsOrNone(file_proto), + serialized_pb=file_proto.SerializeToString(), + dependencies=direct_deps, + public_dependencies=public_deps) + scope = {} + + # This loop extracts all the message and enum types from all the + # dependencies of the file_proto. This is necessary to create the + # scope of available message types when defining the passed in + # file proto. + for dependency in built_deps: + scope.update(self._ExtractSymbols( + dependency.message_types_by_name.values())) + scope.update((_PrefixWithDot(enum.full_name), enum) + for enum in dependency.enum_types_by_name.values()) + + for message_type in file_proto.message_type: + message_desc = self._ConvertMessageDescriptor( + message_type, file_proto.package, file_descriptor, scope, + file_proto.syntax) + file_descriptor.message_types_by_name[message_desc.name] = ( + message_desc) + + for enum_type in file_proto.enum_type: + file_descriptor.enum_types_by_name[enum_type.name] = ( + self._ConvertEnumDescriptor(enum_type, file_proto.package, + file_descriptor, None, scope)) + + for index, extension_proto in enumerate(file_proto.extension): + extension_desc = self._MakeFieldDescriptor( + extension_proto, file_proto.package, index, file_descriptor, + is_extension=True) + extension_desc.containing_type = self._GetTypeFromScope( + file_descriptor.package, extension_proto.extendee, scope) + self._SetFieldType(extension_proto, extension_desc, + file_descriptor.package, scope) + file_descriptor.extensions_by_name[extension_desc.name] = ( + extension_desc) + + for desc_proto in file_proto.message_type: + self._SetAllFieldTypes(file_proto.package, desc_proto, scope) + + if file_proto.package: + desc_proto_prefix = _PrefixWithDot(file_proto.package) + else: + desc_proto_prefix = '' + + for desc_proto in file_proto.message_type: + desc = self._GetTypeFromScope( + desc_proto_prefix, desc_proto.name, scope) + file_descriptor.message_types_by_name[desc_proto.name] = desc + + for index, service_proto in enumerate(file_proto.service): + file_descriptor.services_by_name[service_proto.name] = ( + self._MakeServiceDescriptor(service_proto, index, scope, + file_proto.package, file_descriptor)) + + self.Add(file_proto) + self._file_descriptors[file_proto.name] = file_descriptor + + return self._file_descriptors[file_proto.name] + + def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, + scope=None, syntax=None): + """Adds the proto to the pool in the specified package. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: The package the proto should be located in. + file_desc: The file containing this message. + scope: Dict mapping short and full symbols to message and enum types. + syntax: string indicating syntax of the file ("proto2" or "proto3") + + Returns: + The added descriptor. + """ + + if package: + desc_name = '.'.join((package, desc_proto.name)) + else: + desc_name = desc_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + if scope is None: + scope = {} + + nested = [ + self._ConvertMessageDescriptor( + nested, desc_name, file_desc, scope, syntax) + for nested in desc_proto.nested_type] + enums = [ + self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) + for enum in desc_proto.enum_type] + fields = [self._MakeFieldDescriptor(field, desc_name, index, file_desc) + for index, field in enumerate(desc_proto.field)] + extensions = [ + self._MakeFieldDescriptor(extension, desc_name, index, file_desc, + is_extension=True) + for index, extension in enumerate(desc_proto.extension)] + oneofs = [ + descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), + index, None, [], desc.options) + for index, desc in enumerate(desc_proto.oneof_decl)] + extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range] + if extension_ranges: + is_extendable = True + else: + is_extendable = False + desc = descriptor.Descriptor( + name=desc_proto.name, + full_name=desc_name, + filename=file_name, + containing_type=None, + fields=fields, + oneofs=oneofs, + nested_types=nested, + enum_types=enums, + extensions=extensions, + options=_OptionsOrNone(desc_proto), + is_extendable=is_extendable, + extension_ranges=extension_ranges, + file=file_desc, + serialized_start=None, + serialized_end=None, + syntax=syntax) + for nested in desc.nested_types: + nested.containing_type = desc + for enum in desc.enum_types: + enum.containing_type = desc + for field_index, field_desc in enumerate(desc_proto.field): + if field_desc.HasField('oneof_index'): + oneof_index = field_desc.oneof_index + oneofs[oneof_index].fields.append(fields[field_index]) + fields[field_index].containing_oneof = oneofs[oneof_index] + + scope[_PrefixWithDot(desc_name)] = desc + self._CheckConflictRegister(desc) + self._descriptors[desc_name] = desc + return desc + + def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, + containing_type=None, scope=None): + """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf. + + Args: + enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the enum descriptor. + containing_type: The type containing this enum. + scope: Scope containing available types. + + Returns: + The added descriptor + """ + + if package: + enum_name = '.'.join((package, enum_proto.name)) + else: + enum_name = enum_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + values = [self._MakeEnumValueDescriptor(value, index) + for index, value in enumerate(enum_proto.value)] + desc = descriptor.EnumDescriptor(name=enum_proto.name, + full_name=enum_name, + filename=file_name, + file=file_desc, + values=values, + containing_type=containing_type, + options=_OptionsOrNone(enum_proto)) + scope['.%s' % enum_name] = desc + self._CheckConflictRegister(desc) + self._enum_descriptors[enum_name] = desc + return desc + + def _MakeFieldDescriptor(self, field_proto, message_name, index, + file_desc, is_extension=False): + """Creates a field descriptor from a FieldDescriptorProto. + + For message and enum type fields, this method will do a look up + in the pool for the appropriate descriptor for that type. If it + is unavailable, it will fall back to the _source function to + create it. If this type is still unavailable, construction will + fail. + + Args: + field_proto: The proto describing the field. + message_name: The name of the containing message. + index: Index of the field + file_desc: The file containing the field descriptor. + is_extension: Indication that this field is for an extension. + + Returns: + An initialized FieldDescriptor object + """ + + if message_name: + full_name = '.'.join((message_name, field_proto.name)) + else: + full_name = field_proto.name + + return descriptor.FieldDescriptor( + name=field_proto.name, + full_name=full_name, + index=index, + number=field_proto.number, + type=field_proto.type, + cpp_type=None, + message_type=None, + enum_type=None, + containing_type=None, + label=field_proto.label, + has_default_value=False, + default_value=None, + is_extension=is_extension, + extension_scope=None, + options=_OptionsOrNone(field_proto), + file=file_desc) + + def _SetAllFieldTypes(self, package, desc_proto, scope): + """Sets all the descriptor's fields's types. + + This method also sets the containing types on any extensions. + + Args: + package: The current package of desc_proto. + desc_proto: The message descriptor to update. + scope: Enclosing scope of available types. + """ + + package = _PrefixWithDot(package) + + main_desc = self._GetTypeFromScope(package, desc_proto.name, scope) + + if package == '.': + nested_package = _PrefixWithDot(desc_proto.name) + else: + nested_package = '.'.join([package, desc_proto.name]) + + for field_proto, field_desc in zip(desc_proto.field, main_desc.fields): + self._SetFieldType(field_proto, field_desc, nested_package, scope) + + for extension_proto, extension_desc in ( + zip(desc_proto.extension, main_desc.extensions)): + extension_desc.containing_type = self._GetTypeFromScope( + nested_package, extension_proto.extendee, scope) + self._SetFieldType(extension_proto, extension_desc, nested_package, scope) + + for nested_type in desc_proto.nested_type: + self._SetAllFieldTypes(nested_package, nested_type, scope) + + def _SetFieldType(self, field_proto, field_desc, package, scope): + """Sets the field's type, cpp_type, message_type and enum_type. + + Args: + field_proto: Data about the field in proto format. + field_desc: The descriptor to modiy. + package: The package the field's container is in. + scope: Enclosing scope of available types. + """ + if field_proto.type_name: + desc = self._GetTypeFromScope(package, field_proto.type_name, scope) + else: + desc = None + + if not field_proto.HasField('type'): + if isinstance(desc, descriptor.Descriptor): + field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE + else: + field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM + + field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType( + field_proto.type) + + if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE + or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP): + field_desc.message_type = desc + + if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.enum_type = desc + + if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED: + field_desc.has_default_value = False + field_desc.default_value = [] + elif field_proto.HasField('default_value'): + field_desc.has_default_value = True + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = float(field_proto.default_value) + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = field_proto.default_value + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = field_proto.default_value.lower() == 'true' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values_by_name[ + field_proto.default_value].number + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = text_encoding.CUnescape( + field_proto.default_value) + else: + # All other types are of the "int" type. + field_desc.default_value = int(field_proto.default_value) + else: + field_desc.has_default_value = False + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = 0.0 + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = u'' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = False + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values[0].number + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = b'' + else: + # All other types are of the "int" type. + field_desc.default_value = 0 + + field_desc.type = field_proto.type + + def _MakeEnumValueDescriptor(self, value_proto, index): + """Creates a enum value descriptor object from a enum value proto. + + Args: + value_proto: The proto describing the enum value. + index: The index of the enum value. + + Returns: + An initialized EnumValueDescriptor object. + """ + + return descriptor.EnumValueDescriptor( + name=value_proto.name, + index=index, + number=value_proto.number, + options=_OptionsOrNone(value_proto), + type=None) + + def _MakeServiceDescriptor(self, service_proto, service_index, scope, + package, file_desc): + """Make a protobuf ServiceDescriptor given a ServiceDescriptorProto. + + Args: + service_proto: The descriptor_pb2.ServiceDescriptorProto protobuf message. + service_index: The index of the service in the File. + scope: Dict mapping short and full symbols to message and enum types. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the service descriptor. + + Returns: + The added descriptor. + """ + + if package: + service_name = '.'.join((package, service_proto.name)) + else: + service_name = service_proto.name + + methods = [self._MakeMethodDescriptor(method_proto, service_name, package, + scope, index) + for index, method_proto in enumerate(service_proto.method)] + desc = descriptor.ServiceDescriptor(name=service_proto.name, + full_name=service_name, + index=service_index, + methods=methods, + options=_OptionsOrNone(service_proto), + file=file_desc) + self._CheckConflictRegister(desc) + self._service_descriptors[service_name] = desc + return desc + + def _MakeMethodDescriptor(self, method_proto, service_name, package, scope, + index): + """Creates a method descriptor from a MethodDescriptorProto. + + Args: + method_proto: The proto describing the method. + service_name: The name of the containing service. + package: Optional package name to look up for types. + scope: Scope containing available types. + index: Index of the method in the service. + + Returns: + An initialized MethodDescriptor object. + """ + full_name = '.'.join((service_name, method_proto.name)) + input_type = self._GetTypeFromScope( + package, method_proto.input_type, scope) + output_type = self._GetTypeFromScope( + package, method_proto.output_type, scope) + return descriptor.MethodDescriptor(name=method_proto.name, + full_name=full_name, + index=index, + containing_service=None, + input_type=input_type, + output_type=output_type, + options=_OptionsOrNone(method_proto)) + + def _ExtractSymbols(self, descriptors): + """Pulls out all the symbols from descriptor protos. + + Args: + descriptors: The messages to extract descriptors from. + Yields: + A two element tuple of the type name and descriptor object. + """ + + for desc in descriptors: + yield (_PrefixWithDot(desc.full_name), desc) + for symbol in self._ExtractSymbols(desc.nested_types): + yield symbol + for enum in desc.enum_types: + yield (_PrefixWithDot(enum.full_name), enum) + + def _GetDeps(self, dependencies): + """Recursively finds dependencies for file protos. + + Args: + dependencies: The names of the files being depended on. + + Yields: + Each direct and indirect dependency. + """ + + for dependency in dependencies: + dep_desc = self.FindFileByName(dependency) + yield dep_desc + for parent_dep in dep_desc.dependencies: + yield parent_dep + + def _GetTypeFromScope(self, package, type_name, scope): + """Finds a given type name in the current scope. + + Args: + package: The package the proto should be located in. + type_name: The name of the type to be found in the scope. + scope: Dict mapping short and full symbols to message and enum types. + + Returns: + The descriptor for the requested type. + """ + if type_name not in scope: + components = _PrefixWithDot(package).split('.') + while components: + possible_match = '.'.join(components + [type_name]) + if possible_match in scope: + type_name = possible_match + break + else: + components.pop(-1) + return scope[type_name] + + +def _PrefixWithDot(name): + return name if name.startswith('.') else '.%s' % name + + +if _USE_C_DESCRIPTORS: + # TODO(amauryfa): This pool could be constructed from Python code, when we + # support a flag like 'use_cpp_generated_pool=True'. + # pylint: disable=protected-access + _DEFAULT = descriptor._message.default_pool +else: + _DEFAULT = DescriptorPool() + + +def Default(): + return _DEFAULT diff --git a/winvenv/Lib/site-packages/google/protobuf/duration_pb2.py b/winvenv/Lib/site-packages/google/protobuf/duration_pb2.py new file mode 100644 index 0000000..2428889 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/duration_pb2.py @@ -0,0 +1,77 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/duration.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/duration.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\rDurationProtoP\001Z*github.com/golang/protobuf/ptypes/duration\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1egoogle/protobuf/duration.proto\x12\x0fgoogle.protobuf\"*\n\x08\x44uration\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x42|\n\x13\x63om.google.protobufB\rDurationProtoP\x01Z*github.com/golang/protobuf/ptypes/duration\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_DURATION = _descriptor.Descriptor( + name='Duration', + full_name='google.protobuf.Duration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='seconds', full_name='google.protobuf.Duration.seconds', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nanos', full_name='google.protobuf.Duration.nanos', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=93, +) + +DESCRIPTOR.message_types_by_name['Duration'] = _DURATION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Duration = _reflection.GeneratedProtocolMessageType('Duration', (_message.Message,), dict( + DESCRIPTOR = _DURATION, + __module__ = 'google.protobuf.duration_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Duration) + )) +_sym_db.RegisterMessage(Duration) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/empty_pb2.py b/winvenv/Lib/site-packages/google/protobuf/empty_pb2.py new file mode 100644 index 0000000..46682b2 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/empty_pb2.py @@ -0,0 +1,63 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/empty.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/empty.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\nEmptyProtoP\001Z\'github.com/golang/protobuf/ptypes/empty\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1bgoogle/protobuf/empty.proto\x12\x0fgoogle.protobuf\"\x07\n\x05\x45mptyBv\n\x13\x63om.google.protobufB\nEmptyProtoP\x01Z\'github.com/golang/protobuf/ptypes/empty\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_EMPTY = _descriptor.Descriptor( + name='Empty', + full_name='google.protobuf.Empty', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=48, + serialized_end=55, +) + +DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), dict( + DESCRIPTOR = _EMPTY, + __module__ = 'google.protobuf.empty_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Empty) + )) +_sym_db.RegisterMessage(Empty) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/field_mask_pb2.py b/winvenv/Lib/site-packages/google/protobuf/field_mask_pb2.py new file mode 100644 index 0000000..5373887 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/field_mask_pb2.py @@ -0,0 +1,70 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/field_mask.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/field_mask.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\016FieldMaskProtoP\001Z9google.golang.org/genproto/protobuf/field_mask;field_mask\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n google/protobuf/field_mask.proto\x12\x0fgoogle.protobuf\"\x1a\n\tFieldMask\x12\r\n\x05paths\x18\x01 \x03(\tB\x89\x01\n\x13\x63om.google.protobufB\x0e\x46ieldMaskProtoP\x01Z9google.golang.org/genproto/protobuf/field_mask;field_mask\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_FIELDMASK = _descriptor.Descriptor( + name='FieldMask', + full_name='google.protobuf.FieldMask', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='paths', full_name='google.protobuf.FieldMask.paths', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=53, + serialized_end=79, +) + +DESCRIPTOR.message_types_by_name['FieldMask'] = _FIELDMASK +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FieldMask = _reflection.GeneratedProtocolMessageType('FieldMask', (_message.Message,), dict( + DESCRIPTOR = _FIELDMASK, + __module__ = 'google.protobuf.field_mask_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldMask) + )) +_sym_db.RegisterMessage(FieldMask) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/__init__.py b/winvenv/Lib/site-packages/google/protobuf/internal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/_parameterized.py b/winvenv/Lib/site-packages/google/protobuf/internal/_parameterized.py new file mode 100644 index 0000000..f2c0b30 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/_parameterized.py @@ -0,0 +1,443 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Adds support for parameterized tests to Python's unittest TestCase class. + +A parameterized test is a method in a test case that is invoked with different +argument tuples. + +A simple example: + + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( + (1, 2, 3), + (4, 5, 9), + (1, 1, 3)) + def testAddition(self, op1, op2, result): + self.assertEqual(result, op1 + op2) + + +Each invocation is a separate test case and properly isolated just +like a normal test method, with its own setUp/tearDown cycle. In the +example above, there are three separate testcases, one of which will +fail due to an assertion error (1 + 1 != 3). + +Parameters for invididual test cases can be tuples (with positional parameters) +or dictionaries (with named parameters): + + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( + {'op1': 1, 'op2': 2, 'result': 3}, + {'op1': 4, 'op2': 5, 'result': 9}, + ) + def testAddition(self, op1, op2, result): + self.assertEqual(result, op1 + op2) + +If a parameterized test fails, the error message will show the +original test name (which is modified internally) and the arguments +for the specific invocation, which are part of the string returned by +the shortDescription() method on test cases. + +The id method of the test, used internally by the unittest framework, +is also modified to show the arguments. To make sure that test names +stay the same across several invocations, object representations like + + >>> class Foo(object): + ... pass + >>> repr(Foo()) + '<__main__.Foo object at 0x23d8610>' + +are turned into '<__main__.Foo>'. For even more descriptive names, +especially in test logs, you can use the named_parameters decorator. In +this case, only tuples are supported, and the first parameters has to +be a string (or an object that returns an apt name when converted via +str()): + + class NamedExample(parameterized.TestCase): + @parameterized.named_parameters( + ('Normal', 'aa', 'aaa', True), + ('EmptyPrefix', '', 'abc', True), + ('BothEmpty', '', '', True)) + def testStartsWith(self, prefix, string, result): + self.assertEqual(result, strings.startswith(prefix)) + +Named tests also have the benefit that they can be run individually +from the command line: + + $ testmodule.py NamedExample.testStartsWithNormal + . + -------------------------------------------------------------------- + Ran 1 test in 0.000s + + OK + +Parameterized Classes +===================== +If invocation arguments are shared across test methods in a single +TestCase class, instead of decorating all test methods +individually, the class itself can be decorated: + + @parameterized.parameters( + (1, 2, 3) + (4, 5, 9)) + class ArithmeticTest(parameterized.TestCase): + def testAdd(self, arg1, arg2, result): + self.assertEqual(arg1 + arg2, result) + + def testSubtract(self, arg2, arg2, result): + self.assertEqual(result - arg1, arg2) + +Inputs from Iterables +===================== +If parameters should be shared across several test cases, or are dynamically +created from other sources, a single non-tuple iterable can be passed into +the decorator. This iterable will be used to obtain the test cases: + + class AdditionExample(parameterized.TestCase): + @parameterized.parameters( + c.op1, c.op2, c.result for c in testcases + ) + def testAddition(self, op1, op2, result): + self.assertEqual(result, op1 + op2) + + +Single-Argument Test Methods +============================ +If a test method takes only one argument, the single argument does not need to +be wrapped into a tuple: + + class NegativeNumberExample(parameterized.TestCase): + @parameterized.parameters( + -1, -3, -4, -5 + ) + def testIsNegative(self, arg): + self.assertTrue(IsNegative(arg)) +""" + +__author__ = 'tmarek@google.com (Torsten Marek)' + +import collections +import functools +import re +import types +try: + import unittest2 as unittest +except ImportError: + import unittest +import uuid + +import six + +ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>') +_SEPARATOR = uuid.uuid1().hex +_FIRST_ARG = object() +_ARGUMENT_REPR = object() + + +def _CleanRepr(obj): + return ADDR_RE.sub(r'<\1>', repr(obj)) + + +# Helper function formerly from the unittest module, removed from it in +# Python 2.7. +def _StrClass(cls): + return '%s.%s' % (cls.__module__, cls.__name__) + + +def _NonStringIterable(obj): + return (isinstance(obj, collections.Iterable) and not + isinstance(obj, six.string_types)) + + +def _FormatParameterList(testcase_params): + if isinstance(testcase_params, collections.Mapping): + return ', '.join('%s=%s' % (argname, _CleanRepr(value)) + for argname, value in testcase_params.items()) + elif _NonStringIterable(testcase_params): + return ', '.join(map(_CleanRepr, testcase_params)) + else: + return _FormatParameterList((testcase_params,)) + + +class _ParameterizedTestIter(object): + """Callable and iterable class for producing new test cases.""" + + def __init__(self, test_method, testcases, naming_type): + """Returns concrete test functions for a test and a list of parameters. + + The naming_type is used to determine the name of the concrete + functions as reported by the unittest framework. If naming_type is + _FIRST_ARG, the testcases must be tuples, and the first element must + have a string representation that is a valid Python identifier. + + Args: + test_method: The decorated test method. + testcases: (list of tuple/dict) A list of parameter + tuples/dicts for individual test invocations. + naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR. + """ + self._test_method = test_method + self.testcases = testcases + self._naming_type = naming_type + + def __call__(self, *args, **kwargs): + raise RuntimeError('You appear to be running a parameterized test case ' + 'without having inherited from parameterized.' + 'TestCase. This is bad because none of ' + 'your test cases are actually being run.') + + def __iter__(self): + test_method = self._test_method + naming_type = self._naming_type + + def MakeBoundParamTest(testcase_params): + @functools.wraps(test_method) + def BoundParamTest(self): + if isinstance(testcase_params, collections.Mapping): + test_method(self, **testcase_params) + elif _NonStringIterable(testcase_params): + test_method(self, *testcase_params) + else: + test_method(self, testcase_params) + + if naming_type is _FIRST_ARG: + # Signal the metaclass that the name of the test function is unique + # and descriptive. + BoundParamTest.__x_use_name__ = True + BoundParamTest.__name__ += str(testcase_params[0]) + testcase_params = testcase_params[1:] + elif naming_type is _ARGUMENT_REPR: + # __x_extra_id__ is used to pass naming information to the __new__ + # method of TestGeneratorMetaclass. + # The metaclass will make sure to create a unique, but nondescriptive + # name for this test. + BoundParamTest.__x_extra_id__ = '(%s)' % ( + _FormatParameterList(testcase_params),) + else: + raise RuntimeError('%s is not a valid naming type.' % (naming_type,)) + + BoundParamTest.__doc__ = '%s(%s)' % ( + BoundParamTest.__name__, _FormatParameterList(testcase_params)) + if test_method.__doc__: + BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,) + return BoundParamTest + return (MakeBoundParamTest(c) for c in self.testcases) + + +def _IsSingletonList(testcases): + """True iff testcases contains only a single non-tuple element.""" + return len(testcases) == 1 and not isinstance(testcases[0], tuple) + + +def _ModifyClass(class_object, testcases, naming_type): + assert not getattr(class_object, '_id_suffix', None), ( + 'Cannot add parameters to %s,' + ' which already has parameterized methods.' % (class_object,)) + class_object._id_suffix = id_suffix = {} + # We change the size of __dict__ while we iterate over it, + # which Python 3.x will complain about, so use copy(). + for name, obj in class_object.__dict__.copy().items(): + if (name.startswith(unittest.TestLoader.testMethodPrefix) + and isinstance(obj, types.FunctionType)): + delattr(class_object, name) + methods = {} + _UpdateClassDictForParamTestCase( + methods, id_suffix, name, + _ParameterizedTestIter(obj, testcases, naming_type)) + for name, meth in methods.items(): + setattr(class_object, name, meth) + + +def _ParameterDecorator(naming_type, testcases): + """Implementation of the parameterization decorators. + + Args: + naming_type: The naming type. + testcases: Testcase parameters. + + Returns: + A function for modifying the decorated object. + """ + def _Apply(obj): + if isinstance(obj, type): + _ModifyClass( + obj, + list(testcases) if not isinstance(testcases, collections.Sequence) + else testcases, + naming_type) + return obj + else: + return _ParameterizedTestIter(obj, testcases, naming_type) + + if _IsSingletonList(testcases): + assert _NonStringIterable(testcases[0]), ( + 'Single parameter argument must be a non-string iterable') + testcases = testcases[0] + + return _Apply + + +def parameters(*testcases): # pylint: disable=invalid-name + """A decorator for creating parameterized tests. + + See the module docstring for a usage example. + Args: + *testcases: Parameters for the decorated method, either a single + iterable, or a list of tuples/dicts/objects (for tests + with only one argument). + + Returns: + A test generator to be handled by TestGeneratorMetaclass. + """ + return _ParameterDecorator(_ARGUMENT_REPR, testcases) + + +def named_parameters(*testcases): # pylint: disable=invalid-name + """A decorator for creating parameterized tests. + + See the module docstring for a usage example. The first element of + each parameter tuple should be a string and will be appended to the + name of the test method. + + Args: + *testcases: Parameters for the decorated method, either a single + iterable, or a list of tuples. + + Returns: + A test generator to be handled by TestGeneratorMetaclass. + """ + return _ParameterDecorator(_FIRST_ARG, testcases) + + +class TestGeneratorMetaclass(type): + """Metaclass for test cases with test generators. + + A test generator is an iterable in a testcase that produces callables. These + callables must be single-argument methods. These methods are injected into + the class namespace and the original iterable is removed. If the name of the + iterable conforms to the test pattern, the injected methods will be picked + up as tests by the unittest framework. + + In general, it is supposed to be used in conjunction with the + parameters decorator. + """ + + def __new__(mcs, class_name, bases, dct): + dct['_id_suffix'] = id_suffix = {} + for name, obj in dct.items(): + if (name.startswith(unittest.TestLoader.testMethodPrefix) and + _NonStringIterable(obj)): + iterator = iter(obj) + dct.pop(name) + _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator) + + return type.__new__(mcs, class_name, bases, dct) + + +def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator): + """Adds individual test cases to a dictionary. + + Args: + dct: The target dictionary. + id_suffix: The dictionary for mapping names to test IDs. + name: The original name of the test case. + iterator: The iterator generating the individual test cases. + """ + for idx, func in enumerate(iterator): + assert callable(func), 'Test generators must yield callables, got %r' % ( + func,) + if getattr(func, '__x_use_name__', False): + new_name = func.__name__ + else: + new_name = '%s%s%d' % (name, _SEPARATOR, idx) + assert new_name not in dct, ( + 'Name of parameterized test case "%s" not unique' % (new_name,)) + dct[new_name] = func + id_suffix[new_name] = getattr(func, '__x_extra_id__', '') + + +class TestCase(unittest.TestCase): + """Base class for test cases using the parameters decorator.""" + __metaclass__ = TestGeneratorMetaclass + + def _OriginalName(self): + return self._testMethodName.split(_SEPARATOR)[0] + + def __str__(self): + return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__)) + + def id(self): # pylint: disable=invalid-name + """Returns the descriptive ID of the test. + + This is used internally by the unittesting framework to get a name + for the test to be used in reports. + + Returns: + The test id. + """ + return '%s.%s%s' % (_StrClass(self.__class__), + self._OriginalName(), + self._id_suffix.get(self._testMethodName, '')) + + +def CoopTestCase(other_base_class): + """Returns a new base class with a cooperative metaclass base. + + This enables the TestCase to be used in combination + with other base classes that have custom metaclasses, such as + mox.MoxTestBase. + + Only works with metaclasses that do not override type.__new__. + + Example: + + import google3 + import mox + + from google3.testing.pybase import parameterized + + class ExampleTest(parameterized.CoopTestCase(mox.MoxTestBase)): + ... + + Args: + other_base_class: (class) A test case base class. + + Returns: + A new class object. + """ + metaclass = type( + 'CoopMetaclass', + (other_base_class.__metaclass__, + TestGeneratorMetaclass), {}) + return metaclass( + 'CoopTestCase', + (other_base_class, TestCase), {}) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/any_test_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/any_test_pb2.py new file mode 100644 index 0000000..f59c0b2 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/any_test_pb2.py @@ -0,0 +1,182 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/any_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/any_test.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n\'google/protobuf/internal/any_test.proto\x12\x18google.protobuf.internal\x1a\x19google/protobuf/any.proto\"\xc0\x01\n\x07TestAny\x12#\n\x05value\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12\x11\n\tint_value\x18\x02 \x01(\x05\x12\x42\n\tmap_value\x18\x03 \x03(\x0b\x32/.google.protobuf.internal.TestAny.MapValueEntry\x1a/\n\rMapValueEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01*\x08\x08\n\x10\x80\x80\x80\x80\x02\"\x85\x01\n\x11TestAnyExtension1\x12\t\n\x01i\x18\x0f \x01(\x05\x32\x65\n\nextension1\x12!.google.protobuf.internal.TestAny\x18\xab\xff\xf6. \x01(\x0b\x32+.google.protobuf.internal.TestAnyExtension1') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,]) + + + + +_TESTANY_MAPVALUEENTRY = _descriptor.Descriptor( + name='MapValueEntry', + full_name='google.protobuf.internal.TestAny.MapValueEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='google.protobuf.internal.TestAny.MapValueEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.internal.TestAny.MapValueEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=232, + serialized_end=279, +) + +_TESTANY = _descriptor.Descriptor( + name='TestAny', + full_name='google.protobuf.internal.TestAny', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.internal.TestAny.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_value', full_name='google.protobuf.internal.TestAny.int_value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_value', full_name='google.protobuf.internal.TestAny.map_value', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTANY_MAPVALUEENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(10, 536870912), ], + oneofs=[ + ], + serialized_start=97, + serialized_end=289, +) + + +_TESTANYEXTENSION1 = _descriptor.Descriptor( + name='TestAnyExtension1', + full_name='google.protobuf.internal.TestAnyExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='google.protobuf.internal.TestAnyExtension1.i', index=0, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='extension1', full_name='google.protobuf.internal.TestAnyExtension1.extension1', index=0, + number=98418603, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=292, + serialized_end=425, +) + +_TESTANY_MAPVALUEENTRY.containing_type = _TESTANY +_TESTANY.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTANY.fields_by_name['map_value'].message_type = _TESTANY_MAPVALUEENTRY +DESCRIPTOR.message_types_by_name['TestAny'] = _TESTANY +DESCRIPTOR.message_types_by_name['TestAnyExtension1'] = _TESTANYEXTENSION1 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAny = _reflection.GeneratedProtocolMessageType('TestAny', (_message.Message,), dict( + + MapValueEntry = _reflection.GeneratedProtocolMessageType('MapValueEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTANY_MAPVALUEENTRY, + __module__ = 'google.protobuf.internal.any_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestAny.MapValueEntry) + )) + , + DESCRIPTOR = _TESTANY, + __module__ = 'google.protobuf.internal.any_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestAny) + )) +_sym_db.RegisterMessage(TestAny) +_sym_db.RegisterMessage(TestAny.MapValueEntry) + +TestAnyExtension1 = _reflection.GeneratedProtocolMessageType('TestAnyExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTANYEXTENSION1, + __module__ = 'google.protobuf.internal.any_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestAnyExtension1) + )) +_sym_db.RegisterMessage(TestAnyExtension1) + +_TESTANYEXTENSION1.extensions_by_name['extension1'].message_type = _TESTANYEXTENSION1 +TestAny.RegisterExtension(_TESTANYEXTENSION1.extensions_by_name['extension1']) + +_TESTANY_MAPVALUEENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/api_implementation.py b/winvenv/Lib/site-packages/google/protobuf/internal/api_implementation.py new file mode 100644 index 0000000..ab9e781 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/api_implementation.py @@ -0,0 +1,173 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Determine which implementation of the protobuf API is used in this process. +""" + +import os +import warnings +import sys + +try: + # pylint: disable=g-import-not-at-top + from google.protobuf.internal import _api_implementation + # The compile-time constants in the _api_implementation module can be used to + # switch to a certain implementation of the Python API at build time. + _api_version = _api_implementation.api_version + _proto_extension_modules_exist_in_build = True +except ImportError: + _api_version = -1 # Unspecified by compiler flags. + _proto_extension_modules_exist_in_build = False + +if _api_version == 1: + raise ValueError('api_version=1 is no longer supported.') +if _api_version < 0: # Still unspecified? + try: + # The presence of this module in a build allows the proto implementation to + # be upgraded merely via build deps rather than a compiler flag or the + # runtime environment variable. + # pylint: disable=g-import-not-at-top + from google.protobuf import _use_fast_cpp_protos + # Work around a known issue in the classic bootstrap .par import hook. + if not _use_fast_cpp_protos: + raise ImportError('_use_fast_cpp_protos import succeeded but was None') + del _use_fast_cpp_protos + _api_version = 2 + except ImportError: + try: + # pylint: disable=g-import-not-at-top + from google.protobuf.internal import use_pure_python + del use_pure_python # Avoids a pylint error and namespace pollution. + except ImportError: + # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default; + # it can cause data loss if you have any Python-only extensions to any + # message passed back and forth with C++ code. + # + # TODO(b/17427486): Once that bug is fixed, we want to make both Python 2 + # and Python 3 default to `_api_version = 2` (C++ implementation V2). + pass + +_default_implementation_type = ( + 'python' if _api_version <= 0 else 'cpp') + +# This environment variable can be used to switch to a certain implementation +# of the Python API, overriding the compile-time constants in the +# _api_implementation module. Right now only 'python' and 'cpp' are valid +# values. Any other value will be ignored. +_implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', + _default_implementation_type) + +if _implementation_type != 'python': + _implementation_type = 'cpp' + +if 'PyPy' in sys.version and _implementation_type == 'cpp': + warnings.warn('PyPy does not work yet with cpp protocol buffers. ' + 'Falling back to the python implementation.') + _implementation_type = 'python' + +# This environment variable can be used to switch between the two +# 'cpp' implementations, overriding the compile-time constants in the +# _api_implementation module. Right now only '2' is supported. Any other +# value will cause an error to be raised. +_implementation_version_str = os.getenv( + 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2') + +if _implementation_version_str != '2': + raise ValueError( + 'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' + + _implementation_version_str + '" (supported versions: 2)' + ) + +_implementation_version = int(_implementation_version_str) + + +# Detect if serialization should be deterministic by default +try: + # The presence of this module in a build allows the proto implementation to + # be upgraded merely via build deps. + # + # NOTE: Merely importing this automatically enables deterministic proto + # serialization for C++ code, but we still need to export it as a boolean so + # that we can do the same for `_implementation_type == 'python'`. + # + # NOTE2: It is possible for C++ code to enable deterministic serialization by + # default _without_ affecting Python code, if the C++ implementation is not in + # use by this module. That is intended behavior, so we don't actually expose + # this boolean outside of this module. + # + # pylint: disable=g-import-not-at-top,unused-import + from google.protobuf import enable_deterministic_proto_serialization + _python_deterministic_proto_serialization = True +except ImportError: + _python_deterministic_proto_serialization = False + + +# Usage of this function is discouraged. Clients shouldn't care which +# implementation of the API is in use. Note that there is no guarantee +# that differences between APIs will be maintained. +# Please don't use this function if possible. +def Type(): + return _implementation_type + + +# See comment on 'Type' above. +def Version(): + return _implementation_version + + +# For internal use only +def IsPythonDefaultSerializationDeterministic(): + return _python_deterministic_proto_serialization + +# DO NOT USE: For migration and testing only. Will be removed when Proto3 +# defaults to preserve unknowns. +if _implementation_type == 'cpp': + try: + # pylint: disable=g-import-not-at-top + from google.protobuf.pyext import _message + + def GetPythonProto3PreserveUnknownsDefault(): + return _message.GetPythonProto3PreserveUnknownsDefault() + + def SetPythonProto3PreserveUnknownsDefault(preserve): + _message.SetPythonProto3PreserveUnknownsDefault(preserve) + except ImportError: + # Unrecognized cpp implementation. Skipping the unknown fields APIs. + pass +else: + _python_proto3_preserve_unknowns_default = True + + def GetPythonProto3PreserveUnknownsDefault(): + return _python_proto3_preserve_unknowns_default + + def SetPythonProto3PreserveUnknownsDefault(preserve): + global _python_proto3_preserve_unknowns_default + _python_proto3_preserve_unknowns_default = preserve + diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/containers.py b/winvenv/Lib/site-packages/google/protobuf/internal/containers.py new file mode 100644 index 0000000..c6a3692 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/containers.py @@ -0,0 +1,630 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains container classes to represent different protocol buffer types. + +This file defines container classes which represent categories of protocol +buffer field types which need extra maintenance. Currently these categories +are: + - Repeated scalar fields - These are all repeated fields which aren't + composite (e.g. they are of simple types like int32, string, etc). + - Repeated composite fields - Repeated fields which are composite. This + includes groups and nested messages. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + +import collections +import sys + +if sys.version_info[0] < 3: + # We would use collections.MutableMapping all the time, but in Python 2 it + # doesn't define __slots__. This causes two significant problems: + # + # 1. we can't disallow arbitrary attribute assignment, even if our derived + # classes *do* define __slots__. + # + # 2. we can't safely derive a C type from it without __slots__ defined (the + # interpreter expects to find a dict at tp_dictoffset, which we can't + # robustly provide. And we don't want an instance dict anyway. + # + # So this is the Python 2.7 definition of Mapping/MutableMapping functions + # verbatim, except that: + # 1. We declare __slots__. + # 2. We don't declare this as a virtual base class. The classes defined + # in collections are the interesting base classes, not us. + # + # Note: deriving from object is critical. It is the only thing that makes + # this a true type, allowing us to derive from it in C++ cleanly and making + # __slots__ properly disallow arbitrary element assignment. + + class Mapping(object): + __slots__ = () + + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def __contains__(self, key): + try: + self[key] + except KeyError: + return False + else: + return True + + def iterkeys(self): + return iter(self) + + def itervalues(self): + for key in self: + yield self[key] + + def iteritems(self): + for key in self: + yield (key, self[key]) + + def keys(self): + return list(self) + + def items(self): + return [(key, self[key]) for key in self] + + def values(self): + return [self[key] for key in self] + + # Mappings are not hashable by default, but subclasses can change this + __hash__ = None + + def __eq__(self, other): + if not isinstance(other, collections.Mapping): + return NotImplemented + return dict(self.items()) == dict(other.items()) + + def __ne__(self, other): + return not (self == other) + + class MutableMapping(Mapping): + __slots__ = () + + __marker = object() + + def pop(self, key, default=__marker): + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def popitem(self): + try: + key = next(iter(self)) + except StopIteration: + raise KeyError + value = self[key] + del self[key] + return key, value + + def clear(self): + try: + while True: + self.popitem() + except KeyError: + pass + + def update(*args, **kwds): + if len(args) > 2: + raise TypeError("update() takes at most 2 positional " + "arguments ({} given)".format(len(args))) + elif not args: + raise TypeError("update() takes at least 1 argument (0 given)") + self = args[0] + other = args[1] if len(args) >= 2 else () + + if isinstance(other, Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + def setdefault(self, key, default=None): + try: + return self[key] + except KeyError: + self[key] = default + return default + + collections.Mapping.register(Mapping) + collections.MutableMapping.register(MutableMapping) + +else: + # In Python 3 we can just use MutableMapping directly, because it defines + # __slots__. + MutableMapping = collections.MutableMapping + + +class BaseContainer(object): + + """Base container class.""" + + # Minimizes memory usage and disallows assignment to other attributes. + __slots__ = ['_message_listener', '_values'] + + def __init__(self, message_listener): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + Modified() method when it is modified. + """ + self._message_listener = message_listener + self._values = [] + + def __getitem__(self, key): + """Retrieves item by the specified key.""" + return self._values[key] + + def __len__(self): + """Returns the number of elements in the container.""" + return len(self._values) + + def __ne__(self, other): + """Checks if another instance isn't equal to this one.""" + # The concrete classes should define __eq__. + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + def __repr__(self): + return repr(self._values) + + def sort(self, *args, **kwargs): + # Continue to support the old sort_function keyword argument. + # This is expected to be a rare occurrence, so use LBYL to avoid + # the overhead of actually catching KeyError. + if 'sort_function' in kwargs: + kwargs['cmp'] = kwargs.pop('sort_function') + self._values.sort(*args, **kwargs) + + +class RepeatedScalarFieldContainer(BaseContainer): + + """Simple, type-checked, list-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_type_checker'] + + def __init__(self, message_listener, type_checker): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + Modified() method when it is modified. + type_checker: A type_checkers.ValueChecker instance to run on elements + inserted into this container. + """ + super(RepeatedScalarFieldContainer, self).__init__(message_listener) + self._type_checker = type_checker + + def append(self, value): + """Appends an item to the list. Similar to list.append().""" + self._values.append(self._type_checker.CheckValue(value)) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def insert(self, key, value): + """Inserts the item at the specified position. Similar to list.insert().""" + self._values.insert(key, self._type_checker.CheckValue(value)) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def extend(self, elem_seq): + """Extends by appending the given iterable. Similar to list.extend().""" + + if elem_seq is None: + return + try: + elem_seq_iter = iter(elem_seq) + except TypeError: + if not elem_seq: + # silently ignore falsy inputs :-/. + # TODO(ptucker): Deprecate this behavior. b/18413862 + return + raise + + new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter] + if new_values: + self._values.extend(new_values) + self._message_listener.Modified() + + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one. We do not check the types of the individual fields. + """ + self._values.extend(other._values) + self._message_listener.Modified() + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + + def __setitem__(self, key, value): + """Sets the item on the specified position.""" + if isinstance(key, slice): # PY3 + if key.step is not None: + raise ValueError('Extended slices not supported') + self.__setslice__(key.start, key.stop, value) + else: + self._values[key] = self._type_checker.CheckValue(value) + self._message_listener.Modified() + + def __getslice__(self, start, stop): + """Retrieves the subset of items from between the specified indices.""" + return self._values[start:stop] + + def __setslice__(self, start, stop, values): + """Sets the subset of items from between the specified indices.""" + new_values = [] + for value in values: + new_values.append(self._type_checker.CheckValue(value)) + self._values[start:stop] = new_values + self._message_listener.Modified() + + def __delitem__(self, key): + """Deletes the item at the specified position.""" + del self._values[key] + self._message_listener.Modified() + + def __delslice__(self, start, stop): + """Deletes the subset of items from between the specified indices.""" + del self._values[start:stop] + self._message_listener.Modified() + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + # Special case for the same type which should be common and fast. + if isinstance(other, self.__class__): + return other._values == self._values + # We are presumably comparing against some other sequence type. + return other == self._values + +collections.MutableSequence.register(BaseContainer) + + +class RepeatedCompositeFieldContainer(BaseContainer): + + """Simple, list-like container for holding repeated composite fields.""" + + # Disallows assignment to other attributes. + __slots__ = ['_message_descriptor'] + + def __init__(self, message_listener, message_descriptor): + """ + Note that we pass in a descriptor instead of the generated directly, + since at the time we construct a _RepeatedCompositeFieldContainer we + haven't yet necessarily initialized the type that will be contained in the + container. + + Args: + message_listener: A MessageListener implementation. + The RepeatedCompositeFieldContainer will call this object's + Modified() method when it is modified. + message_descriptor: A Descriptor instance describing the protocol type + that should be present in this container. We'll use the + _concrete_class field of this descriptor when the client calls add(). + """ + super(RepeatedCompositeFieldContainer, self).__init__(message_listener) + self._message_descriptor = message_descriptor + + def add(self, **kwargs): + """Adds a new element at the end of the list and returns it. Keyword + arguments may be used to initialize the element. + """ + new_element = self._message_descriptor._concrete_class(**kwargs) + new_element._SetListener(self._message_listener) + self._values.append(new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + return new_element + + def extend(self, elem_seq): + """Extends by appending the given sequence of elements of the same type + as this one, copying each individual message. + """ + message_class = self._message_descriptor._concrete_class + listener = self._message_listener + values = self._values + for message in elem_seq: + new_element = message_class() + new_element._SetListener(listener) + new_element.MergeFrom(message) + values.append(new_element) + listener.Modified() + + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one, copying each individual message. + """ + self.extend(other._values) + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + + def __getslice__(self, start, stop): + """Retrieves the subset of items from between the specified indices.""" + return self._values[start:stop] + + def __delitem__(self, key): + """Deletes the item at the specified position.""" + del self._values[key] + self._message_listener.Modified() + + def __delslice__(self, start, stop): + """Deletes the subset of items from between the specified indices.""" + del self._values[start:stop] + self._message_listener.Modified() + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + if not isinstance(other, self.__class__): + raise TypeError('Can only compare repeated composite fields against ' + 'other repeated composite fields.') + return self._values == other._values + + +class ScalarMap(MutableMapping): + + """Simple, type-checked, dict-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener', + '_entry_descriptor'] + + def __init__(self, message_listener, key_checker, value_checker, + entry_descriptor): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + entry_descriptor: The MessageDescriptor of a map entry: key and value. + """ + self._message_listener = message_listener + self._key_checker = key_checker + self._value_checker = value_checker + self._entry_descriptor = entry_descriptor + self._values = {} + + def __getitem__(self, key): + try: + return self._values[key] + except KeyError: + key = self._key_checker.CheckValue(key) + val = self._value_checker.DefaultValue() + self._values[key] = val + return val + + def __contains__(self, item): + # We check the key's type to match the strong-typing flavor of the API. + # Also this makes it easier to match the behavior of the C++ implementation. + self._key_checker.CheckValue(item) + return item in self._values + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __setitem__(self, key, value): + checked_key = self._key_checker.CheckValue(key) + checked_value = self._value_checker.CheckValue(value) + self._values[checked_key] = checked_value + self._message_listener.Modified() + + def __delitem__(self, key): + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def __repr__(self): + return repr(self._values) + + def MergeFrom(self, other): + self._values.update(other._values) + self._message_listener.Modified() + + def InvalidateIterators(self): + # It appears that the only way to reliably invalidate iterators to + # self._values is to ensure that its size changes. + original = self._values + self._values = original.copy() + original[None] = None + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + def GetEntryClass(self): + return self._entry_descriptor._concrete_class + + +class MessageMap(MutableMapping): + + """Simple, type-checked, dict-like container for with submessage values.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_values', '_message_listener', + '_message_descriptor', '_entry_descriptor'] + + def __init__(self, message_listener, message_descriptor, key_checker, + entry_descriptor): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + entry_descriptor: The MessageDescriptor of a map entry: key and value. + """ + self._message_listener = message_listener + self._message_descriptor = message_descriptor + self._key_checker = key_checker + self._entry_descriptor = entry_descriptor + self._values = {} + + def __getitem__(self, key): + key = self._key_checker.CheckValue(key) + try: + return self._values[key] + except KeyError: + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + self._values[key] = new_element + self._message_listener.Modified() + + return new_element + + def get_or_create(self, key): + """get_or_create() is an alias for getitem (ie. map[key]). + + Args: + key: The key to get or create in the map. + + This is useful in cases where you want to be explicit that the call is + mutating the map. This can avoid lint errors for statements like this + that otherwise would appear to be pointless statements: + + msg.my_map[key] + """ + return self[key] + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __contains__(self, item): + item = self._key_checker.CheckValue(item) + return item in self._values + + def __setitem__(self, key, value): + raise ValueError('May not set values directly, call my_map[key].foo = 5') + + def __delitem__(self, key): + key = self._key_checker.CheckValue(key) + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def __repr__(self): + return repr(self._values) + + def MergeFrom(self, other): + for key in other: + # According to documentation: "When parsing from the wire or when merging, + # if there are duplicate map keys the last key seen is used". + if key in self: + del self[key] + self[key].CopyFrom(other[key]) + # self._message_listener.Modified() not required here, because + # mutations to submessages already propagate. + + def InvalidateIterators(self): + # It appears that the only way to reliably invalidate iterators to + # self._values is to ensure that its size changes. + original = self._values + self._values = original.copy() + original[None] = None + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + def GetEntryClass(self): + return self._entry_descriptor._concrete_class diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/decoder.py b/winvenv/Lib/site-packages/google/protobuf/internal/decoder.py new file mode 100644 index 0000000..52b6491 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/decoder.py @@ -0,0 +1,854 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Code for decoding protocol buffer primitives. + +This code is very similar to encoder.py -- read the docs for that module first. + +A "decoder" is a function with the signature: + Decode(buffer, pos, end, message, field_dict) +The arguments are: + buffer: The string containing the encoded message. + pos: The current position in the string. + end: The position in the string where the current message ends. May be + less than len(buffer) if we're reading a sub-message. + message: The message object into which we're parsing. + field_dict: message._fields (avoids a hashtable lookup). +The decoder reads the field and stores it into field_dict, returning the new +buffer position. A decoder for a repeated field may proactively decode all of +the elements of that field, if they appear consecutively. + +Note that decoders may throw any of the following: + IndexError: Indicates a truncated message. + struct.error: Unpacking of a fixed-width field failed. + message.DecodeError: Other errors. + +Decoders are expected to raise an exception if they are called with pos > end. +This allows callers to be lax about bounds checking: it's fineto read past +"end" as long as you are sure that someone else will notice and throw an +exception later on. + +Something up the call stack is expected to catch IndexError and struct.error +and convert them to message.DecodeError. + +Decoders are constructed using decoder constructors with the signature: + MakeDecoder(field_number, is_repeated, is_packed, key, new_default) +The arguments are: + field_number: The field number of the field we want to decode. + is_repeated: Is the field a repeated field? (bool) + is_packed: Is the field a packed field? (bool) + key: The key to use when looking up the field within field_dict. + (This is actually the FieldDescriptor but nothing in this + file should depend on that.) + new_default: A function which takes a message object as a parameter and + returns a new instance of the default value for this field. + (This is called for repeated fields and sub-messages, when an + instance does not already exist.) + +As with encoders, we define a decoder constructor for every type of field. +Then, for every field of every message class we construct an actual decoder. +That decoder goes into a dict indexed by tag, so when we decode a message +we repeatedly read a tag, look up the corresponding decoder, and invoke it. +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import struct + +import six + +if six.PY3: + long = int + +from google.protobuf.internal import encoder +from google.protobuf.internal import wire_format +from google.protobuf import message + + +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF +_NAN = _POS_INF * 0 + + +# This is not for optimization, but rather to avoid conflicts with local +# variables named "message". +_DecodeError = message.DecodeError + + +def _VarintDecoder(mask, result_type): + """Return an encoder for a basic varint value (does not include tag). + + Decoded values will be bitwise-anded with the given mask before being + returned, e.g. to limit them to 32 bits. The returned decoder does not + take the usual "end" parameter -- the caller is expected to do bounds checking + after the fact (often the caller can defer such checking until later). The + decoder returns a (value, new_pos) pair. + """ + + def DecodeVarint(buffer, pos): + result = 0 + shift = 0 + while 1: + b = six.indexbytes(buffer, pos) + result |= ((b & 0x7f) << shift) + pos += 1 + if not (b & 0x80): + result &= mask + result = result_type(result) + return (result, pos) + shift += 7 + if shift >= 64: + raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint + + +def _SignedVarintDecoder(bits, result_type): + """Like _VarintDecoder() but decodes signed values.""" + + signbit = 1 << (bits - 1) + mask = (1 << bits) - 1 + + def DecodeVarint(buffer, pos): + result = 0 + shift = 0 + while 1: + b = six.indexbytes(buffer, pos) + result |= ((b & 0x7f) << shift) + pos += 1 + if not (b & 0x80): + result &= mask + result = (result ^ signbit) - signbit + result = result_type(result) + return (result, pos) + shift += 7 + if shift >= 64: + raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint + +# We force 32-bit values to int and 64-bit values to long to make +# alternate implementations where the distinction is more significant +# (e.g. the C++ implementation) simpler. + +_DecodeVarint = _VarintDecoder((1 << 64) - 1, long) +_DecodeSignedVarint = _SignedVarintDecoder(64, long) + +# Use these versions for values which must be limited to 32 bits. +_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int) +_DecodeSignedVarint32 = _SignedVarintDecoder(32, int) + + +def ReadTag(buffer, pos): + """Read a tag from the buffer, and return a (tag_bytes, new_pos) tuple. + + We return the raw bytes of the tag rather than decoding them. The raw + bytes can then be used to look up the proper decoder. This effectively allows + us to trade some work that would be done in pure-python (decoding a varint) + for work that is done in C (searching for a byte string in a hash table). + In a low-level language it would be much cheaper to decode the varint and + use that, but not in Python. + """ + + start = pos + while six.indexbytes(buffer, pos) & 0x80: + pos += 1 + pos += 1 + return (six.binary_type(buffer[start:pos]), pos) + + +# -------------------------------------------------------------------- + + +def _SimpleDecoder(wire_type, decode_value): + """Return a constructor for a decoder for fields of a particular type. + + Args: + wire_type: The field's wire type. + decode_value: A function which decodes an individual value, e.g. + _DecodeVarint() + """ + + def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default): + if is_packed: + local_DecodeVarint = _DecodeVarint + def DecodePackedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + (endpoint, pos) = local_DecodeVarint(buffer, pos) + endpoint += pos + if endpoint > end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + (element, pos) = decode_value(buffer, pos) + value.append(element) + if pos > endpoint: + del value[-1] # Discard corrupt value. + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_type) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = decode_value(buffer, pos) + value.append(element) + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (field_dict[key], pos) = decode_value(buffer, pos) + if pos > end: + del field_dict[key] # Discard corrupt value. + raise _DecodeError('Truncated message.') + return pos + return DecodeField + + return SpecificDecoder + + +def _ModifiedDecoder(wire_type, decode_value, modify_value): + """Like SimpleDecoder but additionally invokes modify_value on every value + before storing it. Usually modify_value is ZigZagDecode. + """ + + # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but + # not enough to make a significant difference. + + def InnerDecode(buffer, pos): + (result, new_pos) = decode_value(buffer, pos) + return (modify_value(result), new_pos) + return _SimpleDecoder(wire_type, InnerDecode) + + +def _StructPackDecoder(wire_type, format): + """Return a constructor for a decoder for a fixed-width field. + + Args: + wire_type: The field's wire type. + format: The format string to pass to struct.unpack(). + """ + + value_size = struct.calcsize(format) + local_unpack = struct.unpack + + # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but + # not enough to make a significant difference. + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + + def InnerDecode(buffer, pos): + new_pos = pos + value_size + result = local_unpack(format, buffer[pos:new_pos])[0] + return (result, new_pos) + return _SimpleDecoder(wire_type, InnerDecode) + + +def _FloatDecoder(): + """Returns a decoder for a float field. + + This code works around a bug in struct.unpack for non-finite 32-bit + floating-point values. + """ + + local_unpack = struct.unpack + + def InnerDecode(buffer, pos): + # We expect a 32-bit value in little-endian byte order. Bit 1 is the sign + # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand. + new_pos = pos + 4 + float_bytes = buffer[pos:new_pos] + + # If this value has all its exponent bits set, then it's non-finite. + # In Python 2.4, struct.unpack will convert it to a finite 64-bit value. + # To avoid that, we parse it specially. + if (float_bytes[3:4] in b'\x7F\xFF' and float_bytes[2:3] >= b'\x80'): + # If at least one significand bit is set... + if float_bytes[0:3] != b'\x00\x00\x80': + return (_NAN, new_pos) + # If sign bit is set... + if float_bytes[3:4] == b'\xFF': + return (_NEG_INF, new_pos) + return (_POS_INF, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack('= b'\xF0') + and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')): + return (_NAN, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack(' end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + value_start_pos = pos + (element, pos) = _DecodeSignedVarint32(buffer, pos) + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos])) + if pos > endpoint: + if element in enum_type.values_by_number: + del value[-1] # Discard corrupt value. + else: + del message._unknown_fields[-1] + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = _DecodeSignedVarint32(buffer, pos) + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append( + (tag_bytes, buffer[pos:new_pos])) + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value_start_pos = pos + (enum_value, pos) = _DecodeSignedVarint32(buffer, pos) + if pos > end: + raise _DecodeError('Truncated message.') + if enum_value in enum_type.values_by_number: + field_dict[key] = enum_value + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos])) + return pos + return DecodeField + + +# -------------------------------------------------------------------- + + +Int32Decoder = _SimpleDecoder( + wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32) + +Int64Decoder = _SimpleDecoder( + wire_format.WIRETYPE_VARINT, _DecodeSignedVarint) + +UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32) +UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint) + +SInt32Decoder = _ModifiedDecoder( + wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode) +SInt64Decoder = _ModifiedDecoder( + wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode) + +# Note that Python conveniently guarantees that when using the '<' prefix on +# formats, they will also have the same size across all platforms (as opposed +# to without the prefix, where their sizes depend on the C compiler's basic +# type sizes). +Fixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, ' end: + raise _DecodeError('Truncated string.') + value.append(_ConvertToUnicode(buffer[pos:new_pos])) + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos]) + return new_pos + return DecodeField + + +def BytesDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a bytes field.""" + + local_DecodeVarint = _DecodeVarint + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + value.append(buffer[pos:new_pos]) + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + field_dict[key] = buffer[pos:new_pos] + return new_pos + return DecodeField + + +def GroupDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a group field.""" + + end_tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_END_GROUP) + end_tag_len = len(end_tag_bytes) + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_START_GROUP) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read sub-message. + pos = value.add()._InternalParse(buffer, pos, end) + # Read end tag. + new_pos = pos+end_tag_len + if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: + raise _DecodeError('Missing group end tag.') + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read sub-message. + pos = value._InternalParse(buffer, pos, end) + # Read end tag. + new_pos = pos+end_tag_len + if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: + raise _DecodeError('Missing group end tag.') + return new_pos + return DecodeField + + +def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a message field.""" + + local_DecodeVarint = _DecodeVarint + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + if value.add()._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + if value._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it encountered + # an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + return new_pos + return DecodeField + + +# -------------------------------------------------------------------- + +MESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP) + +def MessageSetItemDecoder(descriptor): + """Returns a decoder for a MessageSet item. + + The parameter is the message Descriptor. + + The message set message looks like this: + message MessageSet { + repeated group Item = 1 { + required int32 type_id = 2; + required string message = 3; + } + } + """ + + type_id_tag_bytes = encoder.TagBytes(2, wire_format.WIRETYPE_VARINT) + message_tag_bytes = encoder.TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED) + item_end_tag_bytes = encoder.TagBytes(1, wire_format.WIRETYPE_END_GROUP) + + local_ReadTag = ReadTag + local_DecodeVarint = _DecodeVarint + local_SkipField = SkipField + + def DecodeItem(buffer, pos, end, message, field_dict): + message_set_item_start = pos + type_id = -1 + message_start = -1 + message_end = -1 + + # Technically, type_id and message can appear in any order, so we need + # a little loop here. + while 1: + (tag_bytes, pos) = local_ReadTag(buffer, pos) + if tag_bytes == type_id_tag_bytes: + (type_id, pos) = local_DecodeVarint(buffer, pos) + elif tag_bytes == message_tag_bytes: + (size, message_start) = local_DecodeVarint(buffer, pos) + pos = message_end = message_start + size + elif tag_bytes == item_end_tag_bytes: + break + else: + pos = SkipField(buffer, pos, end, tag_bytes) + if pos == -1: + raise _DecodeError('Missing group end tag.') + + if pos > end: + raise _DecodeError('Truncated message.') + + if type_id == -1: + raise _DecodeError('MessageSet item missing type_id.') + if message_start == -1: + raise _DecodeError('MessageSet item missing message.') + + extension = message.Extensions._FindExtensionByNumber(type_id) + if extension is not None: + value = field_dict.get(extension) + if value is None: + value = field_dict.setdefault( + extension, extension.message_type._concrete_class()) + if value._InternalParse(buffer, message_start,message_end) != message_end: + # The only reason _InternalParse would return early is if it encountered + # an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append((MESSAGE_SET_ITEM_TAG, + buffer[message_set_item_start:pos])) + + return pos + + return DecodeItem + +# -------------------------------------------------------------------- + +def MapDecoder(field_descriptor, new_default, is_message_map): + """Returns a decoder for a map field.""" + + key = field_descriptor + tag_bytes = encoder.TagBytes(field_descriptor.number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + local_DecodeVarint = _DecodeVarint + # Can't read _concrete_class yet; might not be initialized. + message_type = field_descriptor.message_type + + def DecodeMap(buffer, pos, end, message, field_dict): + submsg = message_type._concrete_class() + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + submsg.Clear() + if submsg._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + + if is_message_map: + value[submsg.key].MergeFrom(submsg.value) + else: + value[submsg.key] = submsg.value + + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + + return DecodeMap + +# -------------------------------------------------------------------- +# Optimization is not as heavy here because calls to SkipField() are rare, +# except for handling end-group tags. + +def _SkipVarint(buffer, pos, end): + """Skip a varint value. Returns the new position.""" + # Previously ord(buffer[pos]) raised IndexError when pos is out of range. + # With this code, ord(b'') raises TypeError. Both are handled in + # python_message.py to generate a 'Truncated message' error. + while ord(buffer[pos:pos+1]) & 0x80: + pos += 1 + pos += 1 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipFixed64(buffer, pos, end): + """Skip a fixed64 value. Returns the new position.""" + + pos += 8 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipLengthDelimited(buffer, pos, end): + """Skip a length-delimited value. Returns the new position.""" + + (size, pos) = _DecodeVarint(buffer, pos) + pos += size + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipGroup(buffer, pos, end): + """Skip sub-group. Returns the new position.""" + + while 1: + (tag_bytes, pos) = ReadTag(buffer, pos) + new_pos = SkipField(buffer, pos, end, tag_bytes) + if new_pos == -1: + return pos + pos = new_pos + +def _EndGroup(buffer, pos, end): + """Skipping an END_GROUP tag returns -1 to tell the parent loop to break.""" + + return -1 + +def _SkipFixed32(buffer, pos, end): + """Skip a fixed32 value. Returns the new position.""" + + pos += 4 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _RaiseInvalidWireType(buffer, pos, end): + """Skip function for unknown wire types. Raises an exception.""" + + raise _DecodeError('Tag had invalid wire type.') + +def _FieldSkipper(): + """Constructs the SkipField function.""" + + WIRETYPE_TO_SKIPPER = [ + _SkipVarint, + _SkipFixed64, + _SkipLengthDelimited, + _SkipGroup, + _EndGroup, + _SkipFixed32, + _RaiseInvalidWireType, + _RaiseInvalidWireType, + ] + + wiretype_mask = wire_format.TAG_TYPE_MASK + + def SkipField(buffer, pos, end, tag_bytes): + """Skips a field with the specified tag. + + |pos| should point to the byte immediately after the tag. + + Returns: + The new position (after the tag value), or -1 if the tag is an end-group + tag (in which case the calling loop should break). + """ + + # The wire type is always in the first byte since varints are little-endian. + wire_type = ord(tag_bytes[0:1]) & wiretype_mask + return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end) + + return SkipField + +SkipField = _FieldSkipper() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_database_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_database_test.py new file mode 100644 index 0000000..f97477b --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_database_test.py @@ -0,0 +1,124 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.descriptor_database.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest +import warnings + +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf import descriptor_database + + +class DescriptorDatabaseTest(unittest.TestCase): + + def testAdd(self): + db = descriptor_database.DescriptorDatabase() + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + db.Add(file_desc_proto) + + self.assertEqual(file_desc_proto, db.FindFileByName( + 'google/protobuf/internal/factory_test2.proto')) + # Can find message type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message')) + # Can find nested message type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message')) + # Can find enum type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Enum')) + # Can find nested enum type. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum')) + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum')) + # Can find field. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.list_field')) + # Can find enum value. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Enum.FACTORY_2_VALUE_0')) + # Can find top level extension. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.another_field')) + # Can find nested extension inside a message. + self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.one_more_field')) + + # Can find service. + file_desc_proto2 = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + db.Add(file_desc_proto2) + self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( + 'protobuf_unittest.TestService')) + + # Non-existent field under a valid top level symbol can also be + # found. The behavior is the same with protobuf C++. + self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes.none_field')) + + self.assertRaises(KeyError, + db.FindFileContainingSymbol, + 'protobuf_unittest.NoneMessage') + + def testConflictRegister(self): + db = descriptor_database.DescriptorDatabase() + unittest_fd = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + db.Add(unittest_fd) + conflict_fd = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + conflict_fd.name = 'other_file' + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + db.Add(conflict_fd) + self.assertTrue(len(w)) + self.assertIs(w[0].category, RuntimeWarning) + self.assertIn('Conflict register for file "other_file": ', + str(w[0].message)) + self.assertIn('already defined in file ' + '"google/protobuf/unittest.proto"', + str(w[0].message)) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test.py new file mode 100644 index 0000000..2cbf781 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test.py @@ -0,0 +1,1055 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.descriptor_pool.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import copy +import os +import sys +import warnings + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_import_public_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import descriptor_pool_test1_pb2 +from google.protobuf.internal import descriptor_pool_test2_pb2 +from google.protobuf.internal import factory_test1_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf.internal import file_options_test_pb2 +from google.protobuf.internal import more_messages_pb2 +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool +from google.protobuf import message_factory +from google.protobuf import symbol_database + + + +class DescriptorPoolTestBase(object): + + def testFindFileByName(self): + name1 = 'google/protobuf/internal/factory_test1.proto' + file_desc1 = self.pool.FindFileByName(name1) + self.assertIsInstance(file_desc1, descriptor.FileDescriptor) + self.assertEqual(name1, file_desc1.name) + self.assertEqual('google.protobuf.python.internal', file_desc1.package) + self.assertIn('Factory1Message', file_desc1.message_types_by_name) + + name2 = 'google/protobuf/internal/factory_test2.proto' + file_desc2 = self.pool.FindFileByName(name2) + self.assertIsInstance(file_desc2, descriptor.FileDescriptor) + self.assertEqual(name2, file_desc2.name) + self.assertEqual('google.protobuf.python.internal', file_desc2.package) + self.assertIn('Factory2Message', file_desc2.message_types_by_name) + + def testFindFileByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindFileByName('Does not exist') + + def testFindFileContainingSymbol(self): + file_desc1 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory1Message') + self.assertIsInstance(file_desc1, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test1.proto', + file_desc1.name) + self.assertEqual('google.protobuf.python.internal', file_desc1.package) + self.assertIn('Factory1Message', file_desc1.message_types_by_name) + + file_desc2 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message') + self.assertIsInstance(file_desc2, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test2.proto', + file_desc2.name) + self.assertEqual('google.protobuf.python.internal', file_desc2.package) + self.assertIn('Factory2Message', file_desc2.message_types_by_name) + + # Tests top level extension. + file_desc3 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.another_field') + self.assertIsInstance(file_desc3, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test2.proto', + file_desc3.name) + + # Tests nested extension inside a message. + file_desc4 = self.pool.FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + self.assertIsInstance(file_desc4, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/internal/factory_test2.proto', + file_desc4.name) + + file_desc5 = self.pool.FindFileContainingSymbol( + 'protobuf_unittest.TestService') + self.assertIsInstance(file_desc5, descriptor.FileDescriptor) + self.assertEqual('google/protobuf/unittest.proto', + file_desc5.name) + + # Tests the generated pool. + assert descriptor_pool.Default().FindFileContainingSymbol( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + assert descriptor_pool.Default().FindFileContainingSymbol( + 'google.protobuf.python.internal.another_field') + assert descriptor_pool.Default().FindFileContainingSymbol( + 'protobuf_unittest.TestService') + + def testFindFileContainingSymbolFailure(self): + with self.assertRaises(KeyError): + self.pool.FindFileContainingSymbol('Does not exist') + + def testFindMessageTypeByName(self): + msg1 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + self.assertIsInstance(msg1, descriptor.Descriptor) + self.assertEqual('Factory1Message', msg1.name) + self.assertEqual('google.protobuf.python.internal.Factory1Message', + msg1.full_name) + self.assertEqual(None, msg1.containing_type) + self.assertFalse(msg1.has_options) + + nested_msg1 = msg1.nested_types[0] + self.assertEqual('NestedFactory1Message', nested_msg1.name) + self.assertEqual(msg1, nested_msg1.containing_type) + + nested_enum1 = msg1.enum_types[0] + self.assertEqual('NestedFactory1Enum', nested_enum1.name) + self.assertEqual(msg1, nested_enum1.containing_type) + + self.assertEqual(nested_msg1, msg1.fields_by_name[ + 'nested_factory_1_message'].message_type) + self.assertEqual(nested_enum1, msg1.fields_by_name[ + 'nested_factory_1_enum'].enum_type) + + msg2 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + self.assertIsInstance(msg2, descriptor.Descriptor) + self.assertEqual('Factory2Message', msg2.name) + self.assertEqual('google.protobuf.python.internal.Factory2Message', + msg2.full_name) + self.assertIsNone(msg2.containing_type) + + nested_msg2 = msg2.nested_types[0] + self.assertEqual('NestedFactory2Message', nested_msg2.name) + self.assertEqual(msg2, nested_msg2.containing_type) + + nested_enum2 = msg2.enum_types[0] + self.assertEqual('NestedFactory2Enum', nested_enum2.name) + self.assertEqual(msg2, nested_enum2.containing_type) + + self.assertEqual(nested_msg2, msg2.fields_by_name[ + 'nested_factory_2_message'].message_type) + self.assertEqual(nested_enum2, msg2.fields_by_name[ + 'nested_factory_2_enum'].enum_type) + + self.assertTrue(msg2.fields_by_name['int_with_default'].has_default_value) + self.assertEqual( + 1776, msg2.fields_by_name['int_with_default'].default_value) + + self.assertTrue( + msg2.fields_by_name['double_with_default'].has_default_value) + self.assertEqual( + 9.99, msg2.fields_by_name['double_with_default'].default_value) + + self.assertTrue( + msg2.fields_by_name['string_with_default'].has_default_value) + self.assertEqual( + 'hello world', msg2.fields_by_name['string_with_default'].default_value) + + self.assertTrue(msg2.fields_by_name['bool_with_default'].has_default_value) + self.assertFalse(msg2.fields_by_name['bool_with_default'].default_value) + + self.assertTrue(msg2.fields_by_name['enum_with_default'].has_default_value) + self.assertEqual( + 1, msg2.fields_by_name['enum_with_default'].default_value) + + msg3 = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Message') + self.assertEqual(nested_msg2, msg3) + + self.assertTrue(msg2.fields_by_name['bytes_with_default'].has_default_value) + self.assertEqual( + b'a\xfb\x00c', + msg2.fields_by_name['bytes_with_default'].default_value) + + self.assertEqual(1, len(msg2.oneofs)) + self.assertEqual(1, len(msg2.oneofs_by_name)) + self.assertEqual(2, len(msg2.oneofs[0].fields)) + for name in ['oneof_int', 'oneof_string']: + self.assertEqual(msg2.oneofs[0], + msg2.fields_by_name[name].containing_oneof) + self.assertIn(msg2.fields_by_name[name], msg2.oneofs[0].fields) + + def testFindTypeErrors(self): + self.assertRaises(TypeError, self.pool.FindExtensionByNumber, '') + + # TODO(jieluo): Fix python to raise correct errors. + if api_implementation.Type() == 'cpp': + self.assertRaises(TypeError, self.pool.FindMethodByName, 0) + self.assertRaises(KeyError, self.pool.FindMethodByName, '') + error_type = TypeError + else: + error_type = AttributeError + self.assertRaises(error_type, self.pool.FindMessageTypeByName, 0) + self.assertRaises(error_type, self.pool.FindFieldByName, 0) + self.assertRaises(error_type, self.pool.FindExtensionByName, 0) + self.assertRaises(error_type, self.pool.FindEnumTypeByName, 0) + self.assertRaises(error_type, self.pool.FindOneofByName, 0) + self.assertRaises(error_type, self.pool.FindServiceByName, 0) + self.assertRaises(error_type, self.pool.FindFileContainingSymbol, 0) + if api_implementation.Type() == 'python': + error_type = KeyError + self.assertRaises(error_type, self.pool.FindFileByName, 0) + + def testFindMessageTypeByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindMessageTypeByName('Does not exist') + + def testFindEnumTypeByName(self): + enum1 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory1Enum') + self.assertIsInstance(enum1, descriptor.EnumDescriptor) + self.assertEqual(0, enum1.values_by_name['FACTORY_1_VALUE_0'].number) + self.assertEqual(1, enum1.values_by_name['FACTORY_1_VALUE_1'].number) + self.assertFalse(enum1.has_options) + + nested_enum1 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory1Message.NestedFactory1Enum') + self.assertIsInstance(nested_enum1, descriptor.EnumDescriptor) + self.assertEqual( + 0, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_0'].number) + self.assertEqual( + 1, nested_enum1.values_by_name['NESTED_FACTORY_1_VALUE_1'].number) + + enum2 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory2Enum') + self.assertIsInstance(enum2, descriptor.EnumDescriptor) + self.assertEqual(0, enum2.values_by_name['FACTORY_2_VALUE_0'].number) + self.assertEqual(1, enum2.values_by_name['FACTORY_2_VALUE_1'].number) + + nested_enum2 = self.pool.FindEnumTypeByName( + 'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum') + self.assertIsInstance(nested_enum2, descriptor.EnumDescriptor) + self.assertEqual( + 0, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_0'].number) + self.assertEqual( + 1, nested_enum2.values_by_name['NESTED_FACTORY_2_VALUE_1'].number) + + def testFindEnumTypeByNameFailure(self): + with self.assertRaises(KeyError): + self.pool.FindEnumTypeByName('Does not exist') + + def testFindFieldByName(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix cpp extension to find field correctly + # when descriptor pool is using an underlying database. + return + field = self.pool.FindFieldByName( + 'google.protobuf.python.internal.Factory1Message.list_value') + self.assertEqual(field.name, 'list_value') + self.assertEqual(field.label, field.LABEL_REPEATED) + self.assertFalse(field.has_options) + + with self.assertRaises(KeyError): + self.pool.FindFieldByName('Does not exist') + + def testFindOneofByName(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix cpp extension to find oneof correctly + # when descriptor pool is using an underlying database. + return + oneof = self.pool.FindOneofByName( + 'google.protobuf.python.internal.Factory2Message.oneof_field') + self.assertEqual(oneof.name, 'oneof_field') + with self.assertRaises(KeyError): + self.pool.FindOneofByName('Does not exist') + + def testFindExtensionByName(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix cpp extension to find extension correctly + # when descriptor pool is using an underlying database. + return + # An extension defined in a message. + extension = self.pool.FindExtensionByName( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + self.assertEqual(extension.name, 'one_more_field') + # An extension defined at file scope. + extension = self.pool.FindExtensionByName( + 'google.protobuf.python.internal.another_field') + self.assertEqual(extension.name, 'another_field') + self.assertEqual(extension.number, 1002) + with self.assertRaises(KeyError): + self.pool.FindFieldByName('Does not exist') + + def testFindAllExtensions(self): + factory1_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + factory2_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + # An extension defined in a message. + one_more_field = factory2_message.extensions_by_name['one_more_field'] + self.pool.AddExtensionDescriptor(one_more_field) + # An extension defined at file scope. + factory_test2 = self.pool.FindFileByName( + 'google/protobuf/internal/factory_test2.proto') + another_field = factory_test2.extensions_by_name['another_field'] + self.pool.AddExtensionDescriptor(another_field) + + extensions = self.pool.FindAllExtensions(factory1_message) + expected_extension_numbers = set([one_more_field, another_field]) + self.assertEqual(expected_extension_numbers, set(extensions)) + # Verify that mutating the returned list does not affect the pool. + extensions.append('unexpected_element') + # Get the extensions again, the returned value does not contain the + # 'unexpected_element'. + extensions = self.pool.FindAllExtensions(factory1_message) + self.assertEqual(expected_extension_numbers, set(extensions)) + + def testFindExtensionByNumber(self): + factory1_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory1Message') + factory2_message = self.pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message') + # An extension defined in a message. + one_more_field = factory2_message.extensions_by_name['one_more_field'] + self.pool.AddExtensionDescriptor(one_more_field) + # An extension defined at file scope. + factory_test2 = self.pool.FindFileByName( + 'google/protobuf/internal/factory_test2.proto') + another_field = factory_test2.extensions_by_name['another_field'] + self.pool.AddExtensionDescriptor(another_field) + + # An extension defined in a message. + extension = self.pool.FindExtensionByNumber(factory1_message, 1001) + self.assertEqual(extension.name, 'one_more_field') + # An extension defined at file scope. + extension = self.pool.FindExtensionByNumber(factory1_message, 1002) + self.assertEqual(extension.name, 'another_field') + with self.assertRaises(KeyError): + extension = self.pool.FindExtensionByNumber(factory1_message, 1234567) + + def testExtensionsAreNotFields(self): + with self.assertRaises(KeyError): + self.pool.FindFieldByName('google.protobuf.python.internal.another_field') + with self.assertRaises(KeyError): + self.pool.FindFieldByName( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + with self.assertRaises(KeyError): + self.pool.FindExtensionByName( + 'google.protobuf.python.internal.Factory1Message.list_value') + + def testFindService(self): + service = self.pool.FindServiceByName('protobuf_unittest.TestService') + self.assertEqual(service.full_name, 'protobuf_unittest.TestService') + with self.assertRaises(KeyError): + self.pool.FindServiceByName('Does not exist') + + def testUserDefinedDB(self): + db = descriptor_database.DescriptorDatabase() + self.pool = descriptor_pool.DescriptorPool(db) + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + self.testFindMessageTypeByName() + + def testAddSerializedFile(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + self.pool = descriptor_pool.DescriptorPool() + self.pool.AddSerializedFile(self.factory_test1_fd.SerializeToString()) + self.pool.AddSerializedFile(self.factory_test2_fd.SerializeToString()) + self.testFindMessageTypeByName() + + + def testEnumDefaultValue(self): + """Test the default value of enums which don't start at zero.""" + def _CheckDefaultValue(file_descriptor): + default_value = (file_descriptor + .message_types_by_name['DescriptorPoolTest1'] + .fields_by_name['nested_enum'] + .default_value) + self.assertEqual(default_value, + descriptor_pool_test1_pb2.DescriptorPoolTest1.BETA) + # First check what the generated descriptor contains. + _CheckDefaultValue(descriptor_pool_test1_pb2.DESCRIPTOR) + # Then check the generated pool. Normally this is the same descriptor. + file_descriptor = symbol_database.Default().pool.FindFileByName( + 'google/protobuf/internal/descriptor_pool_test1.proto') + self.assertIs(file_descriptor, descriptor_pool_test1_pb2.DESCRIPTOR) + _CheckDefaultValue(file_descriptor) + + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + # Then check the dynamic pool and its internal DescriptorDatabase. + descriptor_proto = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(descriptor_proto) + # And do the same check as above + file_descriptor = self.pool.FindFileByName( + 'google/protobuf/internal/descriptor_pool_test1.proto') + _CheckDefaultValue(file_descriptor) + + def testDefaultValueForCustomMessages(self): + """Check the value returned by non-existent fields.""" + def _CheckValueAndType(value, expected_value, expected_type): + self.assertEqual(value, expected_value) + self.assertIsInstance(value, expected_type) + + def _CheckDefaultValues(msg): + try: + int64 = long + except NameError: # Python3 + int64 = int + try: + unicode_type = unicode + except NameError: # Python3 + unicode_type = str + _CheckValueAndType(msg.optional_int32, 0, int) + _CheckValueAndType(msg.optional_uint64, 0, (int64, int)) + _CheckValueAndType(msg.optional_float, 0, (float, int)) + _CheckValueAndType(msg.optional_double, 0, (float, int)) + _CheckValueAndType(msg.optional_bool, False, bool) + _CheckValueAndType(msg.optional_string, u'', unicode_type) + _CheckValueAndType(msg.optional_bytes, b'', bytes) + _CheckValueAndType(msg.optional_nested_enum, msg.FOO, int) + # First for the generated message + _CheckDefaultValues(unittest_pb2.TestAllTypes()) + # Then for a message built with from the DescriptorPool. + pool = descriptor_pool.DescriptorPool() + pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) + pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_pb2.DESCRIPTOR.serialized_pb)) + pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb)) + message_class = message_factory.MessageFactory(pool).GetPrototype( + pool.FindMessageTypeByName( + unittest_pb2.TestAllTypes.DESCRIPTOR.full_name)) + _CheckDefaultValues(message_class()) + + def testAddFileDescriptor(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto') + self.pool.Add(file_desc) + self.pool.AddSerializedFile(file_desc.SerializeToString()) + + def testComplexNesting(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + more_messages_desc = descriptor_pb2.FileDescriptorProto.FromString( + more_messages_pb2.DESCRIPTOR.serialized_pb) + test1_desc = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) + test2_desc = descriptor_pb2.FileDescriptorProto.FromString( + descriptor_pool_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(more_messages_desc) + self.pool.Add(test1_desc) + self.pool.Add(test2_desc) + TEST1_FILE.CheckFile(self, self.pool) + TEST2_FILE.CheckFile(self, self.pool) + + def testConflictRegister(self): + if isinstance(self, SecondaryDescriptorFromDescriptorDB): + if api_implementation.Type() == 'cpp': + # Cpp extension cannot call Add on a DescriptorPool + # that uses a DescriptorDatabase. + # TODO(jieluo): Fix python and cpp extension diff. + return + unittest_fd = descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb) + conflict_fd = copy.deepcopy(unittest_fd) + conflict_fd.name = 'other_file' + if api_implementation.Type() == 'cpp': + try: + self.pool.Add(unittest_fd) + self.pool.Add(conflict_fd) + except TypeError: + pass + else: + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + pool = copy.deepcopy(self.pool) + # No warnings to add the same descriptors. + file_descriptor = unittest_pb2.DESCRIPTOR + pool.AddDescriptor( + file_descriptor.message_types_by_name['TestAllTypes']) + pool.AddEnumDescriptor( + file_descriptor.enum_types_by_name['ForeignEnum']) + pool.AddServiceDescriptor( + file_descriptor.services_by_name['TestService']) + pool.AddExtensionDescriptor( + file_descriptor.extensions_by_name['optional_int32_extension']) + self.assertEqual(len(w), 0) + # Check warnings for conflict descriptors with the same name. + pool.Add(unittest_fd) + pool.Add(conflict_fd) + pool.FindFileByName(unittest_fd.name) + pool.FindFileByName(conflict_fd.name) + self.assertTrue(len(w)) + self.assertIs(w[0].category, RuntimeWarning) + self.assertIn('Conflict register for file "other_file": ', + str(w[0].message)) + self.assertIn('already defined in file ' + '"google/protobuf/unittest.proto"', + str(w[0].message)) + + +class DefaultDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase): + + def setUp(self): + self.pool = descriptor_pool.Default() + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + + def testFindMethods(self): + self.assertIs( + self.pool.FindFileByName('google/protobuf/unittest.proto'), + unittest_pb2.DESCRIPTOR) + self.assertIs( + self.pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'), + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertIs( + self.pool.FindFieldByName( + 'protobuf_unittest.TestAllTypes.optional_int32'), + unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32']) + self.assertIs( + self.pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'), + unittest_pb2.ForeignEnum.DESCRIPTOR) + self.assertIs( + self.pool.FindExtensionByName( + 'protobuf_unittest.optional_int32_extension'), + unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension']) + self.assertIs( + self.pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'), + unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field']) + self.assertIs( + self.pool.FindServiceByName('protobuf_unittest.TestService'), + unittest_pb2.DESCRIPTOR.services_by_name['TestService']) + + +class CreateDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase): + + def setUp(self): + self.pool = descriptor_pool.DescriptorPool() + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + self.pool.Add(self.factory_test1_fd) + self.pool.Add(self.factory_test2_fd) + + self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) + self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_pb2.DESCRIPTOR.serialized_pb)) + self.pool.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb)) + + +class SecondaryDescriptorFromDescriptorDB(DescriptorPoolTestBase, + unittest.TestCase): + + def setUp(self): + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + db = descriptor_database.DescriptorDatabase() + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + db.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_public_pb2.DESCRIPTOR.serialized_pb)) + db.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_import_pb2.DESCRIPTOR.serialized_pb)) + db.Add(descriptor_pb2.FileDescriptorProto.FromString( + unittest_pb2.DESCRIPTOR.serialized_pb)) + self.pool = descriptor_pool.DescriptorPool(descriptor_db=db) + + +class ProtoFile(object): + + def __init__(self, name, package, messages, dependencies=None, + public_dependencies=None): + self.name = name + self.package = package + self.messages = messages + self.dependencies = dependencies or [] + self.public_dependencies = public_dependencies or [] + + def CheckFile(self, test, pool): + file_desc = pool.FindFileByName(self.name) + test.assertEqual(self.name, file_desc.name) + test.assertEqual(self.package, file_desc.package) + dependencies_names = [f.name for f in file_desc.dependencies] + test.assertEqual(self.dependencies, dependencies_names) + public_dependencies_names = [f.name for f in file_desc.public_dependencies] + test.assertEqual(self.public_dependencies, public_dependencies_names) + for name, msg_type in self.messages.items(): + msg_type.CheckType(test, None, name, file_desc) + + +class EnumType(object): + + def __init__(self, values): + self.values = values + + def CheckType(self, test, msg_desc, name, file_desc): + enum_desc = msg_desc.enum_types_by_name[name] + test.assertEqual(name, enum_desc.name) + expected_enum_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_enum_full_name, enum_desc.full_name) + test.assertEqual(msg_desc, enum_desc.containing_type) + test.assertEqual(file_desc, enum_desc.file) + for index, (value, number) in enumerate(self.values): + value_desc = enum_desc.values_by_name[value] + test.assertEqual(value, value_desc.name) + test.assertEqual(index, value_desc.index) + test.assertEqual(number, value_desc.number) + test.assertEqual(enum_desc, value_desc.type) + test.assertIn(value, msg_desc.enum_values_by_name) + + +class MessageType(object): + + def __init__(self, type_dict, field_list, is_extendable=False, + extensions=None): + self.type_dict = type_dict + self.field_list = field_list + self.is_extendable = is_extendable + self.extensions = extensions or [] + + def CheckType(self, test, containing_type_desc, name, file_desc): + if containing_type_desc is None: + desc = file_desc.message_types_by_name[name] + expected_full_name = '.'.join([file_desc.package, name]) + else: + desc = containing_type_desc.nested_types_by_name[name] + expected_full_name = '.'.join([containing_type_desc.full_name, name]) + + test.assertEqual(name, desc.name) + test.assertEqual(expected_full_name, desc.full_name) + test.assertEqual(containing_type_desc, desc.containing_type) + test.assertEqual(desc.file, file_desc) + test.assertEqual(self.is_extendable, desc.is_extendable) + for name, subtype in self.type_dict.items(): + subtype.CheckType(test, desc, name, file_desc) + + for index, (name, field) in enumerate(self.field_list): + field.CheckField(test, desc, name, index, file_desc) + + for index, (name, field) in enumerate(self.extensions): + field.CheckField(test, desc, name, index, file_desc) + + +class EnumField(object): + + def __init__(self, number, type_name, default_value): + self.number = number + self.type_name = type_name + self.default_value = default_value + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.fields_by_name[name] + enum_desc = msg_desc.enum_types_by_name[self.type_name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_ENUM, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM, + field_desc.cpp_type) + test.assertTrue(field_desc.has_default_value) + test.assertEqual(enum_desc.values_by_name[self.default_value].number, + field_desc.default_value) + test.assertFalse(enum_desc.values_by_name[self.default_value].has_options) + test.assertEqual(msg_desc, field_desc.containing_type) + test.assertEqual(enum_desc, field_desc.enum_type) + test.assertEqual(file_desc, enum_desc.file) + + +class MessageField(object): + + def __init__(self, number, type_name): + self.number = number + self.type_name = type_name + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.fields_by_name[name] + field_type_desc = msg_desc.nested_types_by_name[self.type_name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, + field_desc.cpp_type) + test.assertFalse(field_desc.has_default_value) + test.assertEqual(msg_desc, field_desc.containing_type) + test.assertEqual(field_type_desc, field_desc.message_type) + test.assertEqual(file_desc, field_desc.file) + # TODO(jieluo): Fix python and cpp extension diff for message field + # default value. + if api_implementation.Type() == 'cpp': + test.assertRaises( + NotImplementedError, getattr, field_desc, 'default_value') + + +class StringField(object): + + def __init__(self, number, default_value): + self.number = number + self.default_value = default_value + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.fields_by_name[name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(index, field_desc.index) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(descriptor.FieldDescriptor.TYPE_STRING, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_STRING, + field_desc.cpp_type) + test.assertTrue(field_desc.has_default_value) + test.assertEqual(self.default_value, field_desc.default_value) + test.assertEqual(file_desc, field_desc.file) + + +class ExtensionField(object): + + def __init__(self, number, extended_type): + self.number = number + self.extended_type = extended_type + + def CheckField(self, test, msg_desc, name, index, file_desc): + field_desc = msg_desc.extensions_by_name[name] + test.assertEqual(name, field_desc.name) + expected_field_full_name = '.'.join([msg_desc.full_name, name]) + test.assertEqual(expected_field_full_name, field_desc.full_name) + test.assertEqual(self.number, field_desc.number) + test.assertEqual(index, field_desc.index) + test.assertEqual(descriptor.FieldDescriptor.TYPE_MESSAGE, field_desc.type) + test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_MESSAGE, + field_desc.cpp_type) + test.assertFalse(field_desc.has_default_value) + test.assertTrue(field_desc.is_extension) + test.assertEqual(msg_desc, field_desc.extension_scope) + test.assertEqual(msg_desc, field_desc.message_type) + test.assertEqual(self.extended_type, field_desc.containing_type.name) + test.assertEqual(file_desc, field_desc.file) + + +class AddDescriptorTest(unittest.TestCase): + + def _TestMessage(self, prefix): + pool = descriptor_pool.DescriptorPool() + pool.AddDescriptor(unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.TestAllTypes', + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes').full_name) + + # AddDescriptor is not recursive. + with self.assertRaises(KeyError): + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage') + + pool.AddDescriptor(unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.TestAllTypes.NestedMessage', + pool.FindMessageTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').full_name) + + # Files are implicitly also indexed when messages are added. + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileContainingSymbol( + prefix + 'protobuf_unittest.TestAllTypes.NestedMessage').name) + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testMessage(self): + self._TestMessage('') + self._TestMessage('.') + + def _TestEnum(self, prefix): + pool = descriptor_pool.DescriptorPool() + pool.AddEnumDescriptor(unittest_pb2.ForeignEnum.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.ForeignEnum', + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.ForeignEnum').full_name) + + # AddEnumDescriptor is not recursive. + with self.assertRaises(KeyError): + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.ForeignEnum.NestedEnum') + + pool.AddEnumDescriptor(unittest_pb2.TestAllTypes.NestedEnum.DESCRIPTOR) + self.assertEqual( + 'protobuf_unittest.TestAllTypes.NestedEnum', + pool.FindEnumTypeByName( + prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) + + # Files are implicitly also indexed when enums are added. + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileContainingSymbol( + prefix + 'protobuf_unittest.TestAllTypes.NestedEnum').name) + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testEnum(self): + self._TestEnum('') + self._TestEnum('.') + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testService(self): + pool = descriptor_pool.DescriptorPool() + with self.assertRaises(KeyError): + pool.FindServiceByName('protobuf_unittest.TestService') + pool.AddServiceDescriptor(unittest_pb2._TESTSERVICE) + self.assertEqual( + 'protobuf_unittest.TestService', + pool.FindServiceByName('protobuf_unittest.TestService').full_name) + + @unittest.skipIf(api_implementation.Type() == 'cpp', + 'With the cpp implementation, Add() must be called first') + def testFile(self): + pool = descriptor_pool.DescriptorPool() + pool.AddFileDescriptor(unittest_pb2.DESCRIPTOR) + self.assertEqual( + 'google/protobuf/unittest.proto', + pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + + # AddFileDescriptor is not recursive; messages and enums within files must + # be explicitly registered. + with self.assertRaises(KeyError): + pool.FindFileContainingSymbol( + 'protobuf_unittest.TestAllTypes') + + def testEmptyDescriptorPool(self): + # Check that an empty DescriptorPool() contains no messages. + pool = descriptor_pool.DescriptorPool() + proto_file_name = descriptor_pb2.DESCRIPTOR.name + self.assertRaises(KeyError, pool.FindFileByName, proto_file_name) + # Add the above file to the pool + file_descriptor = descriptor_pb2.FileDescriptorProto() + descriptor_pb2.DESCRIPTOR.CopyToProto(file_descriptor) + pool.Add(file_descriptor) + # Now it exists. + self.assertTrue(pool.FindFileByName(proto_file_name)) + + def testCustomDescriptorPool(self): + # Create a new pool, and add a file descriptor. + pool = descriptor_pool.DescriptorPool() + file_desc = descriptor_pb2.FileDescriptorProto( + name='some/file.proto', package='package') + file_desc.message_type.add(name='Message') + pool.Add(file_desc) + self.assertEqual(pool.FindFileByName('some/file.proto').name, + 'some/file.proto') + self.assertEqual(pool.FindMessageTypeByName('package.Message').name, + 'Message') + # Test no package + file_proto = descriptor_pb2.FileDescriptorProto( + name='some/filename/container.proto') + message_proto = file_proto.message_type.add( + name='TopMessage') + message_proto.field.add( + name='bb', + number=1, + type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, + label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) + enum_proto = file_proto.enum_type.add(name='TopEnum') + enum_proto.value.add(name='FOREIGN_FOO', number=4) + file_proto.service.add(name='TopService') + pool = descriptor_pool.DescriptorPool() + pool.Add(file_proto) + self.assertEqual('TopMessage', + pool.FindMessageTypeByName('TopMessage').name) + self.assertEqual('TopEnum', pool.FindEnumTypeByName('TopEnum').name) + self.assertEqual('TopService', pool.FindServiceByName('TopService').name) + + def testFileDescriptorOptionsWithCustomDescriptorPool(self): + # Create a descriptor pool, and add a new FileDescriptorProto to it. + pool = descriptor_pool.DescriptorPool() + file_name = 'file_descriptor_options_with_custom_descriptor_pool.proto' + file_descriptor_proto = descriptor_pb2.FileDescriptorProto(name=file_name) + extension_id = file_options_test_pb2.foo_options + file_descriptor_proto.options.Extensions[extension_id].foo_name = 'foo' + pool.Add(file_descriptor_proto) + # The options set on the FileDescriptorProto should be available in the + # descriptor even if they contain extensions that cannot be deserialized + # using the pool. + file_descriptor = pool.FindFileByName(file_name) + options = file_descriptor.GetOptions() + self.assertEqual('foo', options.Extensions[extension_id].foo_name) + # The object returned by GetOptions() is cached. + self.assertIs(options, file_descriptor.GetOptions()) + + def testAddTypeError(self): + pool = descriptor_pool.DescriptorPool() + with self.assertRaises(TypeError): + pool.AddDescriptor(0) + with self.assertRaises(TypeError): + pool.AddEnumDescriptor(0) + with self.assertRaises(TypeError): + pool.AddServiceDescriptor(0) + with self.assertRaises(TypeError): + pool.AddExtensionDescriptor(0) + with self.assertRaises(TypeError): + pool.AddFileDescriptor(0) + + +TEST1_FILE = ProtoFile( + 'google/protobuf/internal/descriptor_pool_test1.proto', + 'google.protobuf.python.internal', + { + 'DescriptorPoolTest1': MessageType({ + 'NestedEnum': EnumType([('ALPHA', 1), ('BETA', 2)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('EPSILON', 5), ('ZETA', 6)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('ETA', 7), ('THETA', 8)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'ETA')), + ('nested_field', StringField(2, 'theta')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'ZETA')), + ('nested_field', StringField(2, 'beta')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'BETA')), + ('nested_message', MessageField(2, 'NestedMessage')), + ], is_extendable=True), + + 'DescriptorPoolTest2': MessageType({ + 'NestedEnum': EnumType([('GAMMA', 3), ('DELTA', 4)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('IOTA', 9), ('KAPPA', 10)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('LAMBDA', 11), ('MU', 12)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'MU')), + ('nested_field', StringField(2, 'lambda')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'IOTA')), + ('nested_field', StringField(2, 'delta')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'GAMMA')), + ('nested_message', MessageField(2, 'NestedMessage')), + ]), + }) + + +TEST2_FILE = ProtoFile( + 'google/protobuf/internal/descriptor_pool_test2.proto', + 'google.protobuf.python.internal', + { + 'DescriptorPoolTest3': MessageType({ + 'NestedEnum': EnumType([('NU', 13), ('XI', 14)]), + 'NestedMessage': MessageType({ + 'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]), + 'DeepNestedMessage': MessageType({ + 'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')), + ('nested_field', StringField(2, 'sigma')), + ]), + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'PI')), + ('nested_field', StringField(2, 'nu')), + ('deep_nested_message', MessageField(3, 'DeepNestedMessage')), + ]) + }, [ + ('nested_enum', EnumField(1, 'NestedEnum', 'XI')), + ('nested_message', MessageField(2, 'NestedMessage')), + ], extensions=[ + ('descriptor_pool_test', + ExtensionField(1001, 'DescriptorPoolTest1')), + ]), + }, + dependencies=['google/protobuf/internal/descriptor_pool_test1.proto', + 'google/protobuf/internal/more_messages.proto'], + public_dependencies=['google/protobuf/internal/more_messages.proto']) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py new file mode 100644 index 0000000..56835ea --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test1_pb2.py @@ -0,0 +1,474 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/descriptor_pool_test1.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/descriptor_pool_test1.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n4google/protobuf/internal/descriptor_pool_test1.proto\x12\x1fgoogle.protobuf.python.internal\"\xfb\x05\n\x13\x44\x65scriptorPoolTest1\x12Z\n\x0bnested_enum\x18\x01 \x01(\x0e\x32?.google.protobuf.python.internal.DescriptorPoolTest1.NestedEnum:\x04\x42\x45TA\x12Z\n\x0enested_message\x18\x02 \x01(\x0b\x32\x42.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage\x1a\xfd\x03\n\rNestedMessage\x12h\n\x0bnested_enum\x18\x01 \x01(\x0e\x32M.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.NestedEnum:\x04ZETA\x12\x1a\n\x0cnested_field\x18\x02 \x01(\t:\x04\x62\x65ta\x12q\n\x13\x64\x65\x65p_nested_message\x18\x03 \x01(\x0b\x32T.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage\x1a\xcd\x01\n\x11\x44\x65\x65pNestedMessage\x12y\n\x0bnested_enum\x18\x01 \x01(\x0e\x32_.google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.NestedEnum:\x03\x45TA\x12\x1b\n\x0cnested_field\x18\x02 \x01(\t:\x05theta\" \n\nNestedEnum\x12\x07\n\x03\x45TA\x10\x07\x12\t\n\x05THETA\x10\x08\"#\n\nNestedEnum\x12\x0b\n\x07\x45PSILON\x10\x05\x12\x08\n\x04ZETA\x10\x06\"!\n\nNestedEnum\x12\t\n\x05\x41LPHA\x10\x01\x12\x08\n\x04\x42\x45TA\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xf1\x05\n\x13\x44\x65scriptorPoolTest2\x12[\n\x0bnested_enum\x18\x01 \x01(\x0e\x32?.google.protobuf.python.internal.DescriptorPoolTest2.NestedEnum:\x05GAMMA\x12Z\n\x0enested_message\x18\x02 \x01(\x0b\x32\x42.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage\x1a\xfc\x03\n\rNestedMessage\x12h\n\x0bnested_enum\x18\x01 \x01(\x0e\x32M.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.NestedEnum:\x04IOTA\x12\x1b\n\x0cnested_field\x18\x02 \x01(\t:\x05\x64\x65lta\x12q\n\x13\x64\x65\x65p_nested_message\x18\x03 \x01(\x0b\x32T.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage\x1a\xcd\x01\n\x11\x44\x65\x65pNestedMessage\x12x\n\x0bnested_enum\x18\x01 \x01(\x0e\x32_.google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.NestedEnum:\x02MU\x12\x1c\n\x0cnested_field\x18\x02 \x01(\t:\x06lambda\" \n\nNestedEnum\x12\n\n\x06LAMBDA\x10\x0b\x12\x06\n\x02MU\x10\x0c\"!\n\nNestedEnum\x12\x08\n\x04IOTA\x10\t\x12\t\n\x05KAPPA\x10\n\"\"\n\nNestedEnum\x12\t\n\x05GAMMA\x10\x03\x12\t\n\x05\x44\x45LTA\x10\x04') +) + + + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ETA', index=0, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='THETA', index=1, number=8, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=738, + serialized_end=770, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='EPSILON', index=0, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ZETA', index=1, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=772, + serialized_end=807, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST1_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ALPHA', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BETA', index=1, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=809, + serialized_end=842, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST1_NESTEDENUM) + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LAMBDA', index=0, number=11, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MU', index=1, number=12, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1506, + serialized_end=1538, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IOTA', index=0, number=9, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='KAPPA', index=1, number=10, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1540, + serialized_end=1573, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST2_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='GAMMA', index=0, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DELTA', index=1, number=4, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1575, + serialized_end=1609, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST2_NESTEDENUM) + + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE = _descriptor.Descriptor( + name='DeepNestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("theta").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=565, + serialized_end=770, +) + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=6, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("beta").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deep_nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.deep_nested_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=298, + serialized_end=807, +) + +_DESCRIPTORPOOLTEST1 = _descriptor.Descriptor( + name='DescriptorPoolTest1', + full_name='google.protobuf.python.internal.DescriptorPoolTest1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest1.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest1.nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST1_NESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST1_NESTEDENUM, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=90, + serialized_end=853, +) + + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE = _descriptor.Descriptor( + name='DeepNestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=12, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("lambda").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1333, + serialized_end=1538, +) + +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=9, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("delta").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deep_nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.deep_nested_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1065, + serialized_end=1573, +) + +_DESCRIPTORPOOLTEST2 = _descriptor.Descriptor( + name='DescriptorPoolTest2', + full_name='google.protobuf.python.internal.DescriptorPoolTest2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest2.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=3, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest2.nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST2_NESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST2_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=856, + serialized_end=1609, +) + +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE.fields_by_name['deep_nested_message'].message_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST1 +_DESCRIPTORPOOLTEST1_NESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE +_DESCRIPTORPOOLTEST1.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST1_NESTEDENUM +_DESCRIPTORPOOLTEST1.fields_by_name['nested_message'].message_type = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE +_DESCRIPTORPOOLTEST1_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST1 +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE.fields_by_name['deep_nested_message'].message_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST2 +_DESCRIPTORPOOLTEST2_NESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE +_DESCRIPTORPOOLTEST2.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST2_NESTEDENUM +_DESCRIPTORPOOLTEST2.fields_by_name['nested_message'].message_type = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE +_DESCRIPTORPOOLTEST2_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST2 +DESCRIPTOR.message_types_by_name['DescriptorPoolTest1'] = _DESCRIPTORPOOLTEST1 +DESCRIPTOR.message_types_by_name['DescriptorPoolTest2'] = _DESCRIPTORPOOLTEST2 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DescriptorPoolTest1 = _reflection.GeneratedProtocolMessageType('DescriptorPoolTest1', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + + DeepNestedMessage = _reflection.GeneratedProtocolMessageType('DeepNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE_DEEPNESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage.DeepNestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST1_NESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest1.NestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST1, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest1) + )) +_sym_db.RegisterMessage(DescriptorPoolTest1) +_sym_db.RegisterMessage(DescriptorPoolTest1.NestedMessage) +_sym_db.RegisterMessage(DescriptorPoolTest1.NestedMessage.DeepNestedMessage) + +DescriptorPoolTest2 = _reflection.GeneratedProtocolMessageType('DescriptorPoolTest2', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + + DeepNestedMessage = _reflection.GeneratedProtocolMessageType('DeepNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE_DEEPNESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage.DeepNestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST2_NESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest2.NestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST2, + __module__ = 'google.protobuf.internal.descriptor_pool_test1_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest2) + )) +_sym_db.RegisterMessage(DescriptorPoolTest2) +_sym_db.RegisterMessage(DescriptorPoolTest2.NestedMessage) +_sym_db.RegisterMessage(DescriptorPoolTest2.NestedMessage.DeepNestedMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py new file mode 100644 index 0000000..cfc8920 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_pool_test2_pb2.py @@ -0,0 +1,266 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/descriptor_pool_test2.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf.internal import descriptor_pool_test1_pb2 as google_dot_protobuf_dot_internal_dot_descriptor__pool__test1__pb2 +from google.protobuf.internal import more_messages_pb2 as google_dot_protobuf_dot_internal_dot_more__messages__pb2 + +from google.protobuf.internal.more_messages_pb2 import * + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/descriptor_pool_test2.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n4google/protobuf/internal/descriptor_pool_test2.proto\x12\x1fgoogle.protobuf.python.internal\x1a\x34google/protobuf/internal/descriptor_pool_test1.proto\x1a,google/protobuf/internal/more_messages.proto\"\xef\x06\n\x13\x44\x65scriptorPoolTest3\x12X\n\x0bnested_enum\x18\x01 \x01(\x0e\x32?.google.protobuf.python.internal.DescriptorPoolTest3.NestedEnum:\x02XI\x12Z\n\x0enested_message\x18\x02 \x01(\x0b\x32\x42.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage\x1a\xf7\x03\n\rNestedMessage\x12\x66\n\x0bnested_enum\x18\x01 \x01(\x0e\x32M.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.NestedEnum:\x02PI\x12\x18\n\x0cnested_field\x18\x02 \x01(\t:\x02nu\x12q\n\x13\x64\x65\x65p_nested_message\x18\x03 \x01(\x0b\x32T.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage\x1a\xcd\x01\n\x11\x44\x65\x65pNestedMessage\x12y\n\x0bnested_enum\x18\x01 \x01(\x0e\x32_.google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.NestedEnum:\x03RHO\x12\x1b\n\x0cnested_field\x18\x02 \x01(\t:\x05sigma\" \n\nNestedEnum\x12\x07\n\x03RHO\x10\x11\x12\t\n\x05SIGMA\x10\x12\"!\n\nNestedEnum\x12\x0b\n\x07OMICRON\x10\x0f\x12\x06\n\x02PI\x10\x10\"\x1c\n\nNestedEnum\x12\x06\n\x02NU\x10\r\x12\x06\n\x02XI\x10\x0e\x32\x89\x01\n\x14\x64\x65scriptor_pool_test\x12\x34.google.protobuf.python.internal.DescriptorPoolTest1\x18\xe9\x07 \x01(\x0b\x32\x34.google.protobuf.python.internal.DescriptorPoolTest3P\x01') + , + dependencies=[google_dot_protobuf_dot_internal_dot_descriptor__pool__test1__pb2.DESCRIPTOR,google_dot_protobuf_dot_internal_dot_more__messages__pb2.DESCRIPTOR,], + public_dependencies=[google_dot_protobuf_dot_internal_dot_more__messages__pb2.DESCRIPTOR,]) + + + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='RHO', index=0, number=17, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SIGMA', index=1, number=18, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=832, + serialized_end=864, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OMICRON', index=0, number=15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='PI', index=1, number=16, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=866, + serialized_end=899, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM) + +_DESCRIPTORPOOLTEST3_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NU', index=0, number=13, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='XI', index=1, number=14, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=901, + serialized_end=929, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORPOOLTEST3_NESTEDENUM) + + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE = _descriptor.Descriptor( + name='DeepNestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=17, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("sigma").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=659, + serialized_end=864, +) + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=16, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_field', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.nested_field', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("nu").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deep_nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.deep_nested_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=396, + serialized_end=899, +) + +_DESCRIPTORPOOLTEST3 = _descriptor.Descriptor( + name='DescriptorPoolTest3', + full_name='google.protobuf.python.internal.DescriptorPoolTest3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_enum', full_name='google.protobuf.python.internal.DescriptorPoolTest3.nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=14, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_message', full_name='google.protobuf.python.internal.DescriptorPoolTest3.nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='descriptor_pool_test', full_name='google.protobuf.python.internal.DescriptorPoolTest3.descriptor_pool_test', index=0, + number=1001, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_DESCRIPTORPOOLTEST3_NESTEDMESSAGE, ], + enum_types=[ + _DESCRIPTORPOOLTEST3_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=190, + serialized_end=1069, +) + +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE.fields_by_name['deep_nested_message'].message_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE.containing_type = _DESCRIPTORPOOLTEST3 +_DESCRIPTORPOOLTEST3_NESTEDMESSAGE_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE +_DESCRIPTORPOOLTEST3.fields_by_name['nested_enum'].enum_type = _DESCRIPTORPOOLTEST3_NESTEDENUM +_DESCRIPTORPOOLTEST3.fields_by_name['nested_message'].message_type = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE +_DESCRIPTORPOOLTEST3_NESTEDENUM.containing_type = _DESCRIPTORPOOLTEST3 +DESCRIPTOR.message_types_by_name['DescriptorPoolTest3'] = _DESCRIPTORPOOLTEST3 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DescriptorPoolTest3 = _reflection.GeneratedProtocolMessageType('DescriptorPoolTest3', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + + DeepNestedMessage = _reflection.GeneratedProtocolMessageType('DeepNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE_DEEPNESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage.DeepNestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST3_NESTEDMESSAGE, + __module__ = 'google.protobuf.internal.descriptor_pool_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest3.NestedMessage) + )) + , + DESCRIPTOR = _DESCRIPTORPOOLTEST3, + __module__ = 'google.protobuf.internal.descriptor_pool_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.DescriptorPoolTest3) + )) +_sym_db.RegisterMessage(DescriptorPoolTest3) +_sym_db.RegisterMessage(DescriptorPoolTest3.NestedMessage) +_sym_db.RegisterMessage(DescriptorPoolTest3.NestedMessage.DeepNestedMessage) + +_DESCRIPTORPOOLTEST3.extensions_by_name['descriptor_pool_test'].message_type = _DESCRIPTORPOOLTEST3 +google_dot_protobuf_dot_internal_dot_descriptor__pool__test1__pb2.DescriptorPoolTest1.RegisterExtension(_DESCRIPTORPOOLTEST3.extensions_by_name['descriptor_pool_test']) + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_test.py new file mode 100644 index 0000000..02a43d1 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/descriptor_test.py @@ -0,0 +1,1036 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Unittest for google.protobuf.internal.descriptor.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import sys + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import unittest_custom_options_pb2 +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import test_util +from google.protobuf import descriptor +from google.protobuf import descriptor_pool +from google.protobuf import symbol_database +from google.protobuf import text_format + + +TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """ +name: 'TestEmptyMessage' +""" + + +class DescriptorTest(unittest.TestCase): + + def setUp(self): + file_proto = descriptor_pb2.FileDescriptorProto( + name='some/filename/some.proto', + package='protobuf_unittest') + message_proto = file_proto.message_type.add( + name='NestedMessage') + message_proto.field.add( + name='bb', + number=1, + type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, + label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) + enum_proto = message_proto.enum_type.add( + name='ForeignEnum') + enum_proto.value.add(name='FOREIGN_FOO', number=4) + enum_proto.value.add(name='FOREIGN_BAR', number=5) + enum_proto.value.add(name='FOREIGN_BAZ', number=6) + + file_proto.message_type.add(name='ResponseMessage') + service_proto = file_proto.service.add( + name='Service') + method_proto = service_proto.method.add( + name='CallMethod', + input_type='.protobuf_unittest.NestedMessage', + output_type='.protobuf_unittest.ResponseMessage') + + # Note: Calling DescriptorPool.Add() multiple times with the same file only + # works if the input is canonical; in particular, all type names must be + # fully qualified. + self.pool = self.GetDescriptorPool() + self.pool.Add(file_proto) + self.my_file = self.pool.FindFileByName(file_proto.name) + self.my_message = self.my_file.message_types_by_name[message_proto.name] + self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] + self.my_service = self.my_file.services_by_name[service_proto.name] + self.my_method = self.my_service.methods_by_name[method_proto.name] + + def GetDescriptorPool(self): + return symbol_database.Default().pool + + def testEnumValueName(self): + self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), + 'FOREIGN_FOO') + + self.assertEqual( + self.my_message.enum_types_by_name[ + 'ForeignEnum'].values_by_number[4].name, + self.my_message.EnumValueName('ForeignEnum', 4)) + with self.assertRaises(KeyError): + self.my_message.EnumValueName('ForeignEnum', 999) + with self.assertRaises(KeyError): + self.my_message.EnumValueName('NoneEnum', 999) + with self.assertRaises(TypeError): + self.my_message.EnumValueName() + + def testEnumFixups(self): + self.assertEqual(self.my_enum, self.my_enum.values[0].type) + + def testContainingTypeFixups(self): + self.assertEqual(self.my_message, self.my_message.fields[0].containing_type) + self.assertEqual(self.my_message, self.my_enum.containing_type) + + def testContainingServiceFixups(self): + self.assertEqual(self.my_service, self.my_method.containing_service) + + def testGetOptions(self): + self.assertEqual(self.my_enum.GetOptions(), + descriptor_pb2.EnumOptions()) + self.assertEqual(self.my_enum.values[0].GetOptions(), + descriptor_pb2.EnumValueOptions()) + self.assertEqual(self.my_message.GetOptions(), + descriptor_pb2.MessageOptions()) + self.assertEqual(self.my_message.fields[0].GetOptions(), + descriptor_pb2.FieldOptions()) + self.assertEqual(self.my_method.GetOptions(), + descriptor_pb2.MethodOptions()) + self.assertEqual(self.my_service.GetOptions(), + descriptor_pb2.ServiceOptions()) + + def testSimpleCustomOptions(self): + file_descriptor = unittest_custom_options_pb2.DESCRIPTOR + message_descriptor = (unittest_custom_options_pb2. + TestMessageWithCustomOptions.DESCRIPTOR) + field_descriptor = message_descriptor.fields_by_name['field1'] + oneof_descriptor = message_descriptor.oneofs_by_name['AnOneof'] + enum_descriptor = message_descriptor.enum_types_by_name['AnEnum'] + enum_value_descriptor = (message_descriptor. + enum_values_by_name['ANENUM_VAL2']) + other_enum_value_descriptor = (message_descriptor. + enum_values_by_name['ANENUM_VAL1']) + service_descriptor = (unittest_custom_options_pb2. + TestServiceWithCustomOptions.DESCRIPTOR) + method_descriptor = service_descriptor.FindMethodByName('Foo') + + file_options = file_descriptor.GetOptions() + file_opt1 = unittest_custom_options_pb2.file_opt1 + self.assertEqual(9876543210, file_options.Extensions[file_opt1]) + message_options = message_descriptor.GetOptions() + message_opt1 = unittest_custom_options_pb2.message_opt1 + self.assertEqual(-56, message_options.Extensions[message_opt1]) + field_options = field_descriptor.GetOptions() + field_opt1 = unittest_custom_options_pb2.field_opt1 + self.assertEqual(8765432109, field_options.Extensions[field_opt1]) + field_opt2 = unittest_custom_options_pb2.field_opt2 + self.assertEqual(42, field_options.Extensions[field_opt2]) + oneof_options = oneof_descriptor.GetOptions() + oneof_opt1 = unittest_custom_options_pb2.oneof_opt1 + self.assertEqual(-99, oneof_options.Extensions[oneof_opt1]) + enum_options = enum_descriptor.GetOptions() + enum_opt1 = unittest_custom_options_pb2.enum_opt1 + self.assertEqual(-789, enum_options.Extensions[enum_opt1]) + enum_value_options = enum_value_descriptor.GetOptions() + enum_value_opt1 = unittest_custom_options_pb2.enum_value_opt1 + self.assertEqual(123, enum_value_options.Extensions[enum_value_opt1]) + + service_options = service_descriptor.GetOptions() + service_opt1 = unittest_custom_options_pb2.service_opt1 + self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) + method_options = method_descriptor.GetOptions() + method_opt1 = unittest_custom_options_pb2.method_opt1 + self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, + method_options.Extensions[method_opt1]) + + message_descriptor = ( + unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) + self.assertTrue(file_descriptor.has_options) + self.assertFalse(message_descriptor.has_options) + self.assertTrue(field_descriptor.has_options) + self.assertTrue(oneof_descriptor.has_options) + self.assertTrue(enum_descriptor.has_options) + self.assertTrue(enum_value_descriptor.has_options) + self.assertFalse(other_enum_value_descriptor.has_options) + + def testDifferentCustomOptionTypes(self): + kint32min = -2**31 + kint64min = -2**63 + kint32max = 2**31 - 1 + kint64max = 2**63 - 1 + kuint32max = 2**32 - 1 + kuint64max = 2**64 - 1 + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionMinIntegerValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(False, message_options.Extensions[ + unittest_custom_options_pb2.bool_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.int64_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.uint32_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.uint64_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.sint32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.sint64_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.fixed32_opt]) + self.assertEqual(0, message_options.Extensions[ + unittest_custom_options_pb2.fixed64_opt]) + self.assertEqual(kint32min, message_options.Extensions[ + unittest_custom_options_pb2.sfixed32_opt]) + self.assertEqual(kint64min, message_options.Extensions[ + unittest_custom_options_pb2.sfixed64_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionMaxIntegerValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(True, message_options.Extensions[ + unittest_custom_options_pb2.bool_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.int64_opt]) + self.assertEqual(kuint32max, message_options.Extensions[ + unittest_custom_options_pb2.uint32_opt]) + self.assertEqual(kuint64max, message_options.Extensions[ + unittest_custom_options_pb2.uint64_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.sint32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.sint64_opt]) + self.assertEqual(kuint32max, message_options.Extensions[ + unittest_custom_options_pb2.fixed32_opt]) + self.assertEqual(kuint64max, message_options.Extensions[ + unittest_custom_options_pb2.fixed64_opt]) + self.assertEqual(kint32max, message_options.Extensions[ + unittest_custom_options_pb2.sfixed32_opt]) + self.assertEqual(kint64max, message_options.Extensions[ + unittest_custom_options_pb2.sfixed64_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.CustomOptionOtherValues.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertEqual(-100, message_options.Extensions[ + unittest_custom_options_pb2.int32_opt]) + self.assertAlmostEqual(12.3456789, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(1.234567890123456789, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + self.assertEqual("Hello, \"World\"", message_options.Extensions[ + unittest_custom_options_pb2.string_opt]) + self.assertEqual(b"Hello\0World", message_options.Extensions[ + unittest_custom_options_pb2.bytes_opt]) + dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum + self.assertEqual( + dummy_enum.TEST_OPTION_ENUM_TYPE2, + message_options.Extensions[unittest_custom_options_pb2.enum_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.SettingRealsFromPositiveInts.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertAlmostEqual(12, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(154, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + + message_descriptor =\ + unittest_custom_options_pb2.SettingRealsFromNegativeInts.DESCRIPTOR + message_options = message_descriptor.GetOptions() + self.assertAlmostEqual(-12, message_options.Extensions[ + unittest_custom_options_pb2.float_opt], 6) + self.assertAlmostEqual(-154, message_options.Extensions[ + unittest_custom_options_pb2.double_opt]) + + def testComplexExtensionOptions(self): + descriptor =\ + unittest_custom_options_pb2.VariousComplexOptions.DESCRIPTOR + options = descriptor.GetOptions() + self.assertEqual(42, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].foo) + self.assertEqual(324, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(876, options.Extensions[ + unittest_custom_options_pb2.complex_opt1].Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(987, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].baz) + self.assertEqual(654, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.grault]) + self.assertEqual(743, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.foo) + self.assertEqual(1999, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(2008, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].bar.Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(741, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].foo) + self.assertEqual(1998, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].Extensions[ + unittest_custom_options_pb2.quux]) + self.assertEqual(2121, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].Extensions[ + unittest_custom_options_pb2.garply].Extensions[ + unittest_custom_options_pb2.corge].qux) + self.assertEqual(1971, options.Extensions[ + unittest_custom_options_pb2.ComplexOptionType2 + .ComplexOptionType4.complex_opt4].waldo) + self.assertEqual(321, options.Extensions[ + unittest_custom_options_pb2.complex_opt2].fred.waldo) + self.assertEqual(9, options.Extensions[ + unittest_custom_options_pb2.complex_opt3].qux) + self.assertEqual(22, options.Extensions[ + unittest_custom_options_pb2.complex_opt3].complexoptiontype5.plugh) + self.assertEqual(24, options.Extensions[ + unittest_custom_options_pb2.complexopt6].xyzzy) + + # Check that aggregate options were parsed and saved correctly in + # the appropriate descriptors. + def testAggregateOptions(self): + file_descriptor = unittest_custom_options_pb2.DESCRIPTOR + message_descriptor =\ + unittest_custom_options_pb2.AggregateMessage.DESCRIPTOR + field_descriptor = message_descriptor.fields_by_name["fieldname"] + enum_descriptor = unittest_custom_options_pb2.AggregateEnum.DESCRIPTOR + enum_value_descriptor = enum_descriptor.values_by_name["VALUE"] + service_descriptor =\ + unittest_custom_options_pb2.AggregateService.DESCRIPTOR + method_descriptor = service_descriptor.FindMethodByName("Method") + + # Tests for the different types of data embedded in fileopt + file_options = file_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.fileopt] + self.assertEqual(100, file_options.i) + self.assertEqual("FileAnnotation", file_options.s) + self.assertEqual("NestedFileAnnotation", file_options.sub.s) + self.assertEqual("FileExtensionAnnotation", file_options.file.Extensions[ + unittest_custom_options_pb2.fileopt].s) + self.assertEqual("EmbeddedMessageSetElement", file_options.mset.Extensions[ + unittest_custom_options_pb2.AggregateMessageSetElement + .message_set_extension].s) + + # Simple tests for all the other types of annotations + self.assertEqual( + "MessageAnnotation", + message_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.msgopt].s) + self.assertEqual( + "FieldAnnotation", + field_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.fieldopt].s) + self.assertEqual( + "EnumAnnotation", + enum_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.enumopt].s) + self.assertEqual( + "EnumValueAnnotation", + enum_value_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.enumvalopt].s) + self.assertEqual( + "ServiceAnnotation", + service_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.serviceopt].s) + self.assertEqual( + "MethodAnnotation", + method_descriptor.GetOptions().Extensions[ + unittest_custom_options_pb2.methodopt].s) + + def testNestedOptions(self): + nested_message =\ + unittest_custom_options_pb2.NestedOptionType.NestedMessage.DESCRIPTOR + self.assertEqual(1001, nested_message.GetOptions().Extensions[ + unittest_custom_options_pb2.message_opt1]) + nested_field = nested_message.fields_by_name["nested_field"] + self.assertEqual(1002, nested_field.GetOptions().Extensions[ + unittest_custom_options_pb2.field_opt1]) + outer_message =\ + unittest_custom_options_pb2.NestedOptionType.DESCRIPTOR + nested_enum = outer_message.enum_types_by_name["NestedEnum"] + self.assertEqual(1003, nested_enum.GetOptions().Extensions[ + unittest_custom_options_pb2.enum_opt1]) + nested_enum_value = outer_message.enum_values_by_name["NESTED_ENUM_VALUE"] + self.assertEqual(1004, nested_enum_value.GetOptions().Extensions[ + unittest_custom_options_pb2.enum_value_opt1]) + nested_extension = outer_message.extensions_by_name["nested_extension"] + self.assertEqual(1005, nested_extension.GetOptions().Extensions[ + unittest_custom_options_pb2.field_opt2]) + + def testFileDescriptorReferences(self): + self.assertEqual(self.my_enum.file, self.my_file) + self.assertEqual(self.my_message.file, self.my_file) + + def testFileDescriptor(self): + self.assertEqual(self.my_file.name, 'some/filename/some.proto') + self.assertEqual(self.my_file.package, 'protobuf_unittest') + self.assertEqual(self.my_file.pool, self.pool) + self.assertFalse(self.my_file.has_options) + self.assertEqual('proto2', self.my_file.syntax) + file_proto = descriptor_pb2.FileDescriptorProto() + self.my_file.CopyToProto(file_proto) + self.assertEqual(self.my_file.serialized_pb, + file_proto.SerializeToString()) + # Generated modules also belong to the default pool. + self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default()) + + @unittest.skipIf( + api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, + 'Immutability of descriptors is only enforced in v2 implementation') + def testImmutableCppDescriptor(self): + file_descriptor = unittest_pb2.DESCRIPTOR + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + field_descriptor = message_descriptor.fields_by_name['optional_int32'] + enum_descriptor = message_descriptor.enum_types_by_name['NestedEnum'] + oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] + with self.assertRaises(AttributeError): + message_descriptor.fields_by_name = None + with self.assertRaises(TypeError): + message_descriptor.fields_by_name['Another'] = None + with self.assertRaises(TypeError): + message_descriptor.fields.append(None) + with self.assertRaises(AttributeError): + field_descriptor.containing_type = message_descriptor + with self.assertRaises(AttributeError): + file_descriptor.has_options = False + with self.assertRaises(AttributeError): + field_descriptor.has_options = False + with self.assertRaises(AttributeError): + oneof_descriptor.has_options = False + with self.assertRaises(AttributeError): + enum_descriptor.has_options = False + with self.assertRaises(AttributeError) as e: + message_descriptor.has_options = True + self.assertEqual('attribute is not writable: has_options', + str(e.exception)) + + +class NewDescriptorTest(DescriptorTest): + """Redo the same tests as above, but with a separate DescriptorPool.""" + + def GetDescriptorPool(self): + return descriptor_pool.DescriptorPool() + + +class GeneratedDescriptorTest(unittest.TestCase): + """Tests for the properties of descriptors in generated code.""" + + def CheckMessageDescriptor(self, message_descriptor): + # Basic properties + self.assertEqual(message_descriptor.name, 'TestAllTypes') + self.assertEqual(message_descriptor.full_name, + 'protobuf_unittest.TestAllTypes') + # Test equality and hashability + self.assertEqual(message_descriptor, message_descriptor) + self.assertEqual(message_descriptor.fields[0].containing_type, + message_descriptor) + self.assertIn(message_descriptor, [message_descriptor]) + self.assertIn(message_descriptor, {message_descriptor: None}) + # Test field containers + self.CheckDescriptorSequence(message_descriptor.fields) + self.CheckDescriptorMapping(message_descriptor.fields_by_name) + self.CheckDescriptorMapping(message_descriptor.fields_by_number) + self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name) + self.CheckDescriptorMapping(message_descriptor.enum_types_by_name) + self.CheckDescriptorMapping(message_descriptor.enum_values_by_name) + self.CheckDescriptorMapping(message_descriptor.oneofs_by_name) + self.CheckDescriptorMapping(message_descriptor.enum_types[0].values_by_name) + # Test extension range + self.assertEqual(message_descriptor.extension_ranges, []) + + def CheckFieldDescriptor(self, field_descriptor): + # Basic properties + self.assertEqual(field_descriptor.name, 'optional_int32') + self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32') + self.assertEqual(field_descriptor.full_name, + 'protobuf_unittest.TestAllTypes.optional_int32') + self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') + self.assertEqual(field_descriptor.file, unittest_pb2.DESCRIPTOR) + # Test equality and hashability + self.assertEqual(field_descriptor, field_descriptor) + self.assertEqual( + field_descriptor.containing_type.fields_by_name['optional_int32'], + field_descriptor) + self.assertEqual( + field_descriptor.containing_type.fields_by_camelcase_name[ + 'optionalInt32'], + field_descriptor) + self.assertIn(field_descriptor, [field_descriptor]) + self.assertIn(field_descriptor, {field_descriptor: None}) + self.assertEqual(None, field_descriptor.extension_scope) + self.assertEqual(None, field_descriptor.enum_type) + if api_implementation.Type() == 'cpp': + # For test coverage only + self.assertEqual(field_descriptor.id, field_descriptor.id) + + def CheckDescriptorSequence(self, sequence): + # Verifies that a property like 'messageDescriptor.fields' has all the + # properties of an immutable abc.Sequence. + self.assertNotEqual(sequence, + unittest_pb2.TestAllExtensions.DESCRIPTOR.fields) + self.assertNotEqual(sequence, []) + self.assertNotEqual(sequence, 1) + self.assertFalse(sequence == 1) # Only for cpp test coverage + self.assertEqual(sequence, sequence) + expected_list = list(sequence) + self.assertEqual(expected_list, sequence) + self.assertGreater(len(sequence), 0) # Sized + self.assertEqual(len(sequence), len(expected_list)) # Iterable + self.assertEqual(sequence[len(sequence) -1], sequence[-1]) + item = sequence[0] + self.assertEqual(item, sequence[0]) + self.assertIn(item, sequence) # Container + self.assertEqual(sequence.index(item), 0) + self.assertEqual(sequence.count(item), 1) + other_item = unittest_pb2.NestedTestAllTypes.DESCRIPTOR.fields[0] + self.assertNotIn(other_item, sequence) + self.assertEqual(sequence.count(other_item), 0) + self.assertRaises(ValueError, sequence.index, other_item) + self.assertRaises(ValueError, sequence.index, []) + reversed_iterator = reversed(sequence) + self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) + self.assertRaises(StopIteration, next, reversed_iterator) + expected_list[0] = 'change value' + self.assertNotEqual(expected_list, sequence) + # TODO(jieluo): Change __repr__ support for DescriptorSequence. + if api_implementation.Type() == 'python': + self.assertEqual(str(list(sequence)), str(sequence)) + else: + self.assertEqual(str(sequence)[0], '<') + + def CheckDescriptorMapping(self, mapping): + # Verifies that a property like 'messageDescriptor.fields' has all the + # properties of an immutable abc.Mapping. + self.assertNotEqual( + mapping, unittest_pb2.TestAllExtensions.DESCRIPTOR.fields_by_name) + self.assertNotEqual(mapping, {}) + self.assertNotEqual(mapping, 1) + self.assertFalse(mapping == 1) # Only for cpp test coverage + excepted_dict = dict(mapping.items()) + self.assertEqual(mapping, excepted_dict) + self.assertEqual(mapping, mapping) + self.assertGreater(len(mapping), 0) # Sized + self.assertEqual(len(mapping), len(excepted_dict)) # Iterable + if sys.version_info >= (3,): + key, item = next(iter(mapping.items())) + else: + key, item = mapping.items()[0] + self.assertIn(key, mapping) # Container + self.assertEqual(mapping.get(key), item) + with self.assertRaises(TypeError): + mapping.get() + # TODO(jieluo): Fix python and cpp extension diff. + if api_implementation.Type() == 'python': + self.assertRaises(TypeError, mapping.get, []) + else: + self.assertEqual(None, mapping.get([])) + # keys(), iterkeys() &co + item = (next(iter(mapping.keys())), next(iter(mapping.values()))) + self.assertEqual(item, next(iter(mapping.items()))) + if sys.version_info < (3,): + def CheckItems(seq, iterator): + self.assertEqual(next(iterator), seq[0]) + self.assertEqual(list(iterator), seq[1:]) + CheckItems(mapping.keys(), mapping.iterkeys()) + CheckItems(mapping.values(), mapping.itervalues()) + CheckItems(mapping.items(), mapping.iteritems()) + excepted_dict[key] = 'change value' + self.assertNotEqual(mapping, excepted_dict) + del excepted_dict[key] + excepted_dict['new_key'] = 'new' + self.assertNotEqual(mapping, excepted_dict) + self.assertRaises(KeyError, mapping.__getitem__, 'key_error') + self.assertRaises(KeyError, mapping.__getitem__, len(mapping) + 1) + # TODO(jieluo): Add __repr__ support for DescriptorMapping. + if api_implementation.Type() == 'python': + self.assertEqual(len(str(dict(mapping.items()))), len(str(mapping))) + else: + self.assertEqual(str(mapping)[0], '<') + + def testDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.CheckMessageDescriptor(message_descriptor) + field_descriptor = message_descriptor.fields_by_name['optional_int32'] + self.CheckFieldDescriptor(field_descriptor) + field_descriptor = message_descriptor.fields_by_camelcase_name[ + 'optionalInt32'] + self.CheckFieldDescriptor(field_descriptor) + enum_descriptor = unittest_pb2.DESCRIPTOR.enum_types_by_name[ + 'ForeignEnum'] + self.assertEqual(None, enum_descriptor.containing_type) + # Test extension range + self.assertEqual( + unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, + [(1, 536870912)]) + self.assertEqual( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, + [(42, 43), (4143, 4244), (65536, 536870912)]) + + def testCppDescriptorContainer(self): + containing_file = unittest_pb2.DESCRIPTOR + self.CheckDescriptorSequence(containing_file.dependencies) + self.CheckDescriptorMapping(containing_file.message_types_by_name) + self.CheckDescriptorMapping(containing_file.enum_types_by_name) + self.CheckDescriptorMapping(containing_file.services_by_name) + self.CheckDescriptorMapping(containing_file.extensions_by_name) + self.CheckDescriptorMapping( + unittest_pb2.TestNestedExtension.DESCRIPTOR.extensions_by_name) + + def testCppDescriptorContainer_Iterator(self): + # Same test with the iterator + enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] + values_iter = iter(enum.values) + del enum + self.assertEqual('FOO', next(values_iter).name) + + def testServiceDescriptor(self): + service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService'] + self.assertEqual(service_descriptor.name, 'TestService') + self.assertEqual(service_descriptor.methods[0].name, 'Foo') + self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR) + self.assertEqual(service_descriptor.index, 0) + self.CheckDescriptorMapping(service_descriptor.methods_by_name) + + def testOneofDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + oneof_descriptor = message_descriptor.oneofs_by_name['oneof_field'] + self.assertFalse(oneof_descriptor.has_options) + self.assertEqual(message_descriptor, oneof_descriptor.containing_type) + self.assertEqual('oneof_field', oneof_descriptor.name) + self.assertEqual('protobuf_unittest.TestAllTypes.oneof_field', + oneof_descriptor.full_name) + self.assertEqual(0, oneof_descriptor.index) + + +class DescriptorCopyToProtoTest(unittest.TestCase): + """Tests for CopyTo functions of Descriptor.""" + + def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii): + expected_proto = expected_class() + text_format.Merge(expected_ascii, expected_proto) + + self.assertEqual( + actual_proto, expected_proto, + 'Not equal,\nActual:\n%s\nExpected:\n%s\n' + % (str(actual_proto), str(expected_proto))) + + def _InternalTestCopyToProto(self, desc, expected_proto_class, + expected_proto_ascii): + actual = expected_proto_class() + desc.CopyToProto(actual) + self._AssertProtoEqual( + actual, expected_proto_class, expected_proto_ascii) + + def testCopyToProto_EmptyMessage(self): + self._InternalTestCopyToProto( + unittest_pb2.TestEmptyMessage.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII) + + def testCopyToProto_NestedMessage(self): + TEST_NESTED_MESSAGE_ASCII = """ + name: 'NestedMessage' + field: < + name: 'bb' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_NESTED_MESSAGE_ASCII) + + def testCopyToProto_ForeignNestedMessage(self): + TEST_FOREIGN_NESTED_ASCII = """ + name: 'TestForeignNested' + field: < + name: 'foreign_nested' + number: 1 + label: 1 # Optional + type: 11 # TYPE_MESSAGE + type_name: '.protobuf_unittest.TestAllTypes.NestedMessage' + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestForeignNested.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_FOREIGN_NESTED_ASCII) + + def testCopyToProto_ForeignEnum(self): + TEST_FOREIGN_ENUM_ASCII = """ + name: 'ForeignEnum' + value: < + name: 'FOREIGN_FOO' + number: 4 + > + value: < + name: 'FOREIGN_BAR' + number: 5 + > + value: < + name: 'FOREIGN_BAZ' + number: 6 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.ForeignEnum.DESCRIPTOR, + descriptor_pb2.EnumDescriptorProto, + TEST_FOREIGN_ENUM_ASCII) + + def testCopyToProto_Options(self): + TEST_DEPRECATED_FIELDS_ASCII = """ + name: 'TestDeprecatedFields' + field: < + name: 'deprecated_int32' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + options: < + deprecated: true + > + > + field { + name: "deprecated_int32_in_oneof" + number: 2 + label: LABEL_OPTIONAL + type: TYPE_INT32 + options { + deprecated: true + } + oneof_index: 0 + } + oneof_decl { + name: "oneof_fields" + } + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestDeprecatedFields.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_DEPRECATED_FIELDS_ASCII) + + def testCopyToProto_AllExtensions(self): + TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """ + name: 'TestEmptyMessageWithExtensions' + extension_range: < + start: 1 + end: 536870912 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII) + + def testCopyToProto_SeveralExtensions(self): + TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """ + name: 'TestMultipleExtensionRanges' + extension_range: < + start: 42 + end: 43 + > + extension_range: < + start: 4143 + end: 4244 + > + extension_range: < + start: 65536 + end: 536870912 + > + """ + + self._InternalTestCopyToProto( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR, + descriptor_pb2.DescriptorProto, + TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) + + def testCopyToProto_FileDescriptor(self): + UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" + name: 'google/protobuf/unittest_import.proto' + package: 'protobuf_unittest_import' + dependency: 'google/protobuf/unittest_import_public.proto' + message_type: < + name: 'ImportMessage' + field: < + name: 'd' + number: 1 + label: 1 # Optional + type: 5 # TYPE_INT32 + > + > + """ + + """enum_type: < + name: 'ImportEnum' + value: < + name: 'IMPORT_FOO' + number: 7 + > + value: < + name: 'IMPORT_BAR' + number: 8 + > + value: < + name: 'IMPORT_BAZ' + number: 9 + > + > + enum_type: < + name: 'ImportEnumForMap' + value: < + name: 'UNKNOWN' + number: 0 + > + value: < + name: 'FOO' + number: 1 + > + value: < + name: 'BAR' + number: 2 + > + > + options: < + java_package: 'com.google.protobuf.test' + optimize_for: 1 # SPEED + """ + + """ + cc_enable_arenas: true + > + public_dependency: 0 + """) + self._InternalTestCopyToProto( + unittest_import_pb2.DESCRIPTOR, + descriptor_pb2.FileDescriptorProto, + UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) + + def testCopyToProto_ServiceDescriptor(self): + TEST_SERVICE_ASCII = """ + name: 'TestService' + method: < + name: 'Foo' + input_type: '.protobuf_unittest.FooRequest' + output_type: '.protobuf_unittest.FooResponse' + > + method: < + name: 'Bar' + input_type: '.protobuf_unittest.BarRequest' + output_type: '.protobuf_unittest.BarResponse' + > + """ + self._InternalTestCopyToProto( + unittest_pb2.TestService.DESCRIPTOR, + descriptor_pb2.ServiceDescriptorProto, + TEST_SERVICE_ASCII) + + @unittest.skipIf( + api_implementation.Type() == 'python', + 'It is not implemented in python.') + # TODO(jieluo): Add support for pure python or remove in c extension. + def testCopyToProto_MethodDescriptor(self): + expected_ascii = """ + name: 'Foo' + input_type: '.protobuf_unittest.FooRequest' + output_type: '.protobuf_unittest.FooResponse' + """ + method_descriptor = unittest_pb2.TestService.DESCRIPTOR.FindMethodByName( + 'Foo') + self._InternalTestCopyToProto( + method_descriptor, + descriptor_pb2.MethodDescriptorProto, + expected_ascii) + + @unittest.skipIf( + api_implementation.Type() == 'python', + 'Pure python does not raise error.') + # TODO(jieluo): Fix pure python to check with the proto type. + def testCopyToProto_TypeError(self): + file_proto = descriptor_pb2.FileDescriptorProto() + self.assertRaises(TypeError, + unittest_pb2.TestEmptyMessage.DESCRIPTOR.CopyToProto, + file_proto) + self.assertRaises(TypeError, + unittest_pb2.ForeignEnum.DESCRIPTOR.CopyToProto, + file_proto) + self.assertRaises(TypeError, + unittest_pb2.TestService.DESCRIPTOR.CopyToProto, + file_proto) + proto = descriptor_pb2.DescriptorProto() + self.assertRaises(TypeError, + unittest_import_pb2.DESCRIPTOR.CopyToProto, + proto) + + +class MakeDescriptorTest(unittest.TestCase): + + def testMakeDescriptorWithNestedFields(self): + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = 'Foo2' + message_type = file_descriptor_proto.message_type.add() + message_type.name = file_descriptor_proto.name + nested_type = message_type.nested_type.add() + nested_type.name = 'Sub' + enum_type = nested_type.enum_type.add() + enum_type.name = 'FOO' + enum_type_val = enum_type.value.add() + enum_type_val.name = 'BAR' + enum_type_val.number = 3 + field = message_type.field.add() + field.number = 1 + field.name = 'uint64_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_UINT64 + field = message_type.field.add() + field.number = 2 + field.name = 'nested_message_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_MESSAGE + field.type_name = 'Sub' + enum_field = nested_type.field.add() + enum_field.number = 2 + enum_field.name = 'bar_field' + enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM + enum_field.type_name = 'Foo2.Sub.FOO' + + result = descriptor.MakeDescriptor(message_type) + self.assertEqual(result.fields[0].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_UINT64) + self.assertEqual(result.fields[1].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_MESSAGE) + self.assertEqual(result.fields[1].message_type.containing_type, + result) + self.assertEqual(result.nested_types[0].fields[0].full_name, + 'Foo2.Sub.bar_field') + self.assertEqual(result.nested_types[0].fields[0].enum_type, + result.nested_types[0].enum_types[0]) + self.assertFalse(result.has_options) + self.assertFalse(result.fields[0].has_options) + if api_implementation.Type() == 'cpp': + with self.assertRaises(AttributeError): + result.fields[0].has_options = False + + def testMakeDescriptorWithUnsignedIntField(self): + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.name = 'Foo' + message_type = file_descriptor_proto.message_type.add() + message_type.name = file_descriptor_proto.name + enum_type = message_type.enum_type.add() + enum_type.name = 'FOO' + enum_type_val = enum_type.value.add() + enum_type_val.name = 'BAR' + enum_type_val.number = 3 + field = message_type.field.add() + field.number = 1 + field.name = 'uint64_field' + field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + field.type = descriptor.FieldDescriptor.TYPE_UINT64 + enum_field = message_type.field.add() + enum_field.number = 2 + enum_field.name = 'bar_field' + enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED + enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM + enum_field.type_name = 'Foo.FOO' + + result = descriptor.MakeDescriptor(message_type) + self.assertEqual(result.fields[0].cpp_type, + descriptor.FieldDescriptor.CPPTYPE_UINT64) + + + def testMakeDescriptorWithOptions(self): + descriptor_proto = descriptor_pb2.DescriptorProto() + aggregate_message = unittest_custom_options_pb2.AggregateMessage + aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto) + reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto) + + options = reformed_descriptor.GetOptions() + self.assertEqual(101, + options.Extensions[unittest_custom_options_pb2.msgopt].i) + + def testCamelcaseName(self): + descriptor_proto = descriptor_pb2.DescriptorProto() + descriptor_proto.name = 'Bar' + names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar'] + camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar'] + for index in range(len(names)): + field = descriptor_proto.field.add() + field.number = index + 1 + field.name = names[index] + result = descriptor.MakeDescriptor(descriptor_proto) + for index in range(len(camelcase_names)): + self.assertEqual(result.fields[index].camelcase_name, + camelcase_names[index]) + + def testJsonName(self): + descriptor_proto = descriptor_pb2.DescriptorProto() + descriptor_proto.name = 'TestJsonName' + names = ['field_name', 'fieldName', 'FieldName', + '_field_name', 'FIELD_NAME', 'json_name'] + json_names = ['fieldName', 'fieldName', 'FieldName', + 'FieldName', 'FIELDNAME', '@type'] + for index in range(len(names)): + field = descriptor_proto.field.add() + field.number = index + 1 + field.name = names[index] + field.json_name = '@type' + result = descriptor.MakeDescriptor(descriptor_proto) + for index in range(len(json_names)): + self.assertEqual(result.fields[index].json_name, + json_names[index]) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/encoder.py b/winvenv/Lib/site-packages/google/protobuf/internal/encoder.py new file mode 100644 index 0000000..0d1f49d --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/encoder.py @@ -0,0 +1,828 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Code for encoding protocol message primitives. + +Contains the logic for encoding every logical protocol field type +into one of the 5 physical wire types. + +This code is designed to push the Python interpreter's performance to the +limits. + +The basic idea is that at startup time, for every field (i.e. every +FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The +sizer takes a value of this field's type and computes its byte size. The +encoder takes a writer function and a value. It encodes the value into byte +strings and invokes the writer function to write those strings. Typically the +writer function is the write() method of a BytesIO. + +We try to do as much work as possible when constructing the writer and the +sizer rather than when calling them. In particular: +* We copy any needed global functions to local variables, so that we do not need + to do costly global table lookups at runtime. +* Similarly, we try to do any attribute lookups at startup time if possible. +* Every field's tag is encoded to bytes at startup, since it can't change at + runtime. +* Whatever component of the field size we can compute at startup, we do. +* We *avoid* sharing code if doing so would make the code slower and not sharing + does not burden us too much. For example, encoders for repeated fields do + not just call the encoders for singular fields in a loop because this would + add an extra function call overhead for every loop iteration; instead, we + manually inline the single-value encoder into the loop. +* If a Python function lacks a return statement, Python actually generates + instructions to pop the result of the last statement off the stack, push + None onto the stack, and then return that. If we really don't care what + value is returned, then we can save two instructions by returning the + result of the last statement. It looks funny but it helps. +* We assume that type and bounds checking has happened at a higher level. +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import struct + +import six + +from google.protobuf.internal import wire_format + + +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF + + +def _VarintSize(value): + """Compute the size of a varint value.""" + if value <= 0x7f: return 1 + if value <= 0x3fff: return 2 + if value <= 0x1fffff: return 3 + if value <= 0xfffffff: return 4 + if value <= 0x7ffffffff: return 5 + if value <= 0x3ffffffffff: return 6 + if value <= 0x1ffffffffffff: return 7 + if value <= 0xffffffffffffff: return 8 + if value <= 0x7fffffffffffffff: return 9 + return 10 + + +def _SignedVarintSize(value): + """Compute the size of a signed varint value.""" + if value < 0: return 10 + if value <= 0x7f: return 1 + if value <= 0x3fff: return 2 + if value <= 0x1fffff: return 3 + if value <= 0xfffffff: return 4 + if value <= 0x7ffffffff: return 5 + if value <= 0x3ffffffffff: return 6 + if value <= 0x1ffffffffffff: return 7 + if value <= 0xffffffffffffff: return 8 + if value <= 0x7fffffffffffffff: return 9 + return 10 + + +def _TagSize(field_number): + """Returns the number of bytes required to serialize a tag with this field + number.""" + # Just pass in type 0, since the type won't affect the tag+type size. + return _VarintSize(wire_format.PackTag(field_number, 0)) + + +# -------------------------------------------------------------------- +# In this section we define some generic sizers. Each of these functions +# takes parameters specific to a particular field type, e.g. int32 or fixed64. +# It returns another function which in turn takes parameters specific to a +# particular field, e.g. the field number and whether it is repeated or packed. +# Look at the next section to see how these are used. + + +def _SimpleSizer(compute_value_size): + """A sizer which uses the function compute_value_size to compute the size of + each value. Typically compute_value_size is _VarintSize.""" + + def SpecificSizer(field_number, is_repeated, is_packed): + tag_size = _TagSize(field_number) + if is_packed: + local_VarintSize = _VarintSize + def PackedFieldSize(value): + result = 0 + for element in value: + result += compute_value_size(element) + return result + local_VarintSize(result) + tag_size + return PackedFieldSize + elif is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + result += compute_value_size(element) + return result + return RepeatedFieldSize + else: + def FieldSize(value): + return tag_size + compute_value_size(value) + return FieldSize + + return SpecificSizer + + +def _ModifiedSizer(compute_value_size, modify_value): + """Like SimpleSizer, but modify_value is invoked on each value before it is + passed to compute_value_size. modify_value is typically ZigZagEncode.""" + + def SpecificSizer(field_number, is_repeated, is_packed): + tag_size = _TagSize(field_number) + if is_packed: + local_VarintSize = _VarintSize + def PackedFieldSize(value): + result = 0 + for element in value: + result += compute_value_size(modify_value(element)) + return result + local_VarintSize(result) + tag_size + return PackedFieldSize + elif is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + result += compute_value_size(modify_value(element)) + return result + return RepeatedFieldSize + else: + def FieldSize(value): + return tag_size + compute_value_size(modify_value(value)) + return FieldSize + + return SpecificSizer + + +def _FixedSizer(value_size): + """Like _SimpleSizer except for a fixed-size field. The input is the size + of one value.""" + + def SpecificSizer(field_number, is_repeated, is_packed): + tag_size = _TagSize(field_number) + if is_packed: + local_VarintSize = _VarintSize + def PackedFieldSize(value): + result = len(value) * value_size + return result + local_VarintSize(result) + tag_size + return PackedFieldSize + elif is_repeated: + element_size = value_size + tag_size + def RepeatedFieldSize(value): + return len(value) * element_size + return RepeatedFieldSize + else: + field_size = value_size + tag_size + def FieldSize(value): + return field_size + return FieldSize + + return SpecificSizer + + +# ==================================================================== +# Here we declare a sizer constructor for each field type. Each "sizer +# constructor" is a function that takes (field_number, is_repeated, is_packed) +# as parameters and returns a sizer, which in turn takes a field value as +# a parameter and returns its encoded size. + + +Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize) + +UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize) + +SInt32Sizer = SInt64Sizer = _ModifiedSizer( + _SignedVarintSize, wire_format.ZigZagEncode) + +Fixed32Sizer = SFixed32Sizer = FloatSizer = _FixedSizer(4) +Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8) + +BoolSizer = _FixedSizer(1) + + +def StringSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a string field.""" + + tag_size = _TagSize(field_number) + local_VarintSize = _VarintSize + local_len = len + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + l = local_len(element.encode('utf-8')) + result += local_VarintSize(l) + l + return result + return RepeatedFieldSize + else: + def FieldSize(value): + l = local_len(value.encode('utf-8')) + return tag_size + local_VarintSize(l) + l + return FieldSize + + +def BytesSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a bytes field.""" + + tag_size = _TagSize(field_number) + local_VarintSize = _VarintSize + local_len = len + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + l = local_len(element) + result += local_VarintSize(l) + l + return result + return RepeatedFieldSize + else: + def FieldSize(value): + l = local_len(value) + return tag_size + local_VarintSize(l) + l + return FieldSize + + +def GroupSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a group field.""" + + tag_size = _TagSize(field_number) * 2 + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + result += element.ByteSize() + return result + return RepeatedFieldSize + else: + def FieldSize(value): + return tag_size + value.ByteSize() + return FieldSize + + +def MessageSizer(field_number, is_repeated, is_packed): + """Returns a sizer for a message field.""" + + tag_size = _TagSize(field_number) + local_VarintSize = _VarintSize + assert not is_packed + if is_repeated: + def RepeatedFieldSize(value): + result = tag_size * len(value) + for element in value: + l = element.ByteSize() + result += local_VarintSize(l) + l + return result + return RepeatedFieldSize + else: + def FieldSize(value): + l = value.ByteSize() + return tag_size + local_VarintSize(l) + l + return FieldSize + + +# -------------------------------------------------------------------- +# MessageSet is special: it needs custom logic to compute its size properly. + + +def MessageSetItemSizer(field_number): + """Returns a sizer for extensions of MessageSet. + + The message set message looks like this: + message MessageSet { + repeated group Item = 1 { + required int32 type_id = 2; + required string message = 3; + } + } + """ + static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) + + _TagSize(3)) + local_VarintSize = _VarintSize + + def FieldSize(value): + l = value.ByteSize() + return static_size + local_VarintSize(l) + l + + return FieldSize + + +# -------------------------------------------------------------------- +# Map is special: it needs custom logic to compute its size properly. + + +def MapSizer(field_descriptor, is_message_map): + """Returns a sizer for a map field.""" + + # Can't look at field_descriptor.message_type._concrete_class because it may + # not have been initialized yet. + message_type = field_descriptor.message_type + message_sizer = MessageSizer(field_descriptor.number, False, False) + + def FieldSize(map_value): + total = 0 + for key in map_value: + value = map_value[key] + # It's wasteful to create the messages and throw them away one second + # later since we'll do the same for the actual encode. But there's not an + # obvious way to avoid this within the current design without tons of code + # duplication. For message map, value.ByteSize() should be called to + # update the status. + entry_msg = message_type._concrete_class(key=key, value=value) + total += message_sizer(entry_msg) + if is_message_map: + value.ByteSize() + return total + + return FieldSize + +# ==================================================================== +# Encoders! + + +def _VarintEncoder(): + """Return an encoder for a basic varint value (does not include tag).""" + + def EncodeVarint(write, value, unused_deterministic=None): + bits = value & 0x7f + value >>= 7 + while value: + write(six.int2byte(0x80|bits)) + bits = value & 0x7f + value >>= 7 + return write(six.int2byte(bits)) + + return EncodeVarint + + +def _SignedVarintEncoder(): + """Return an encoder for a basic signed varint value (does not include + tag).""" + + def EncodeSignedVarint(write, value, unused_deterministic=None): + if value < 0: + value += (1 << 64) + bits = value & 0x7f + value >>= 7 + while value: + write(six.int2byte(0x80|bits)) + bits = value & 0x7f + value >>= 7 + return write(six.int2byte(bits)) + + return EncodeSignedVarint + + +_EncodeVarint = _VarintEncoder() +_EncodeSignedVarint = _SignedVarintEncoder() + + +def _VarintBytes(value): + """Encode the given integer as a varint and return the bytes. This is only + called at startup time so it doesn't need to be fast.""" + + pieces = [] + _EncodeVarint(pieces.append, value, True) + return b"".join(pieces) + + +def TagBytes(field_number, wire_type): + """Encode the given tag and return the bytes. Only called at startup.""" + + return six.binary_type( + _VarintBytes(wire_format.PackTag(field_number, wire_type))) + +# -------------------------------------------------------------------- +# As with sizers (see above), we have a number of common encoder +# implementations. + + +def _SimpleEncoder(wire_type, encode_value, compute_value_size): + """Return a constructor for an encoder for fields of a particular type. + + Args: + wire_type: The field's wire type, for encoding tags. + encode_value: A function which encodes an individual value, e.g. + _EncodeVarint(). + compute_value_size: A function which computes the size of an individual + value, e.g. _VarintSize(). + """ + + def SpecificEncoder(field_number, is_repeated, is_packed): + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + size = 0 + for element in value: + size += compute_value_size(element) + local_EncodeVarint(write, size, deterministic) + for element in value: + encode_value(write, element, deterministic) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, deterministic): + for element in value: + write(tag_bytes) + encode_value(write, element, deterministic) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, deterministic): + write(tag_bytes) + return encode_value(write, value, deterministic) + return EncodeField + + return SpecificEncoder + + +def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value): + """Like SimpleEncoder but additionally invokes modify_value on every value + before passing it to encode_value. Usually modify_value is ZigZagEncode.""" + + def SpecificEncoder(field_number, is_repeated, is_packed): + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + size = 0 + for element in value: + size += compute_value_size(modify_value(element)) + local_EncodeVarint(write, size, deterministic) + for element in value: + encode_value(write, modify_value(element), deterministic) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, deterministic): + for element in value: + write(tag_bytes) + encode_value(write, modify_value(element), deterministic) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, deterministic): + write(tag_bytes) + return encode_value(write, modify_value(value), deterministic) + return EncodeField + + return SpecificEncoder + + +def _StructPackEncoder(wire_type, format): + """Return a constructor for an encoder for a fixed-width field. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + value_size = struct.calcsize(format) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size, deterministic) + for element in value: + write(local_struct_pack(format, element)) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, unused_deterministic=None): + for element in value: + write(tag_bytes) + write(local_struct_pack(format, element)) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, unused_deterministic=None): + write(tag_bytes) + return write(local_struct_pack(format, value)) + return EncodeField + + return SpecificEncoder + + +def _FloatingPointEncoder(wire_type, format): + """Return a constructor for an encoder for float fields. + + This is like StructPackEncoder, but catches errors that may be due to + passing non-finite floating-point values to struct.pack, and makes a + second attempt to encode those values. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + value_size = struct.calcsize(format) + if value_size == 4: + def EncodeNonFiniteOrRaise(write, value): + # Remember that the serialized form uses little-endian byte order. + if value == _POS_INF: + write(b'\x00\x00\x80\x7F') + elif value == _NEG_INF: + write(b'\x00\x00\x80\xFF') + elif value != value: # NaN + write(b'\x00\x00\xC0\x7F') + else: + raise + elif value_size == 8: + def EncodeNonFiniteOrRaise(write, value): + if value == _POS_INF: + write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') + elif value == _NEG_INF: + write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') + elif value != value: # NaN + write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') + else: + raise + else: + raise ValueError('Can\'t encode floating-point values that are ' + '%d bytes long (only 4 or 8)' % value_size) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size, deterministic) + for element in value: + # This try/except block is going to be faster than any code that + # we could write to check whether element is finite. + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, unused_deterministic=None): + for element in value: + write(tag_bytes) + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, unused_deterministic=None): + write(tag_bytes) + try: + write(local_struct_pack(format, value)) + except SystemError: + EncodeNonFiniteOrRaise(write, value) + return EncodeField + + return SpecificEncoder + + +# ==================================================================== +# Here we declare an encoder constructor for each field type. These work +# very similarly to sizer constructors, described earlier. + + +Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder( + wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) + +UInt32Encoder = UInt64Encoder = _SimpleEncoder( + wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) + +SInt32Encoder = SInt64Encoder = _ModifiedEncoder( + wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, + wire_format.ZigZagEncode) + +# Note that Python conveniently guarantees that when using the '<' prefix on +# formats, they will also have the same size across all platforms (as opposed +# to without the prefix, where their sizes depend on the C compiler's basic +# type sizes). +Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '\n\x04loop\x18\x01 \x01(\x0b\x32\x30.google.protobuf.python.internal.Factory2Message\"D\n\x19MessageWithNestedEnumOnly\"\'\n\nNestedEnum\x12\x19\n\x15NESTED_MESSAGE_ENUM_0\x10\x00\"\'\n\x11MessageWithOption\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05:\x02\x10\x01*<\n\x0c\x46\x61\x63tory2Enum\x12\x15\n\x11\x46\x41\x43TORY_2_VALUE_0\x10\x00\x12\x15\n\x11\x46\x41\x43TORY_2_VALUE_1\x10\x01:H\n\ranother_field\x12\x30.google.protobuf.python.internal.Factory1Message\x18\xea\x07 \x01(\t') + , + dependencies=[google_dot_protobuf_dot_internal_dot_factory__test1__pb2.DESCRIPTOR,]) + +_FACTORY2ENUM = _descriptor.EnumDescriptor( + name='Factory2Enum', + full_name='google.protobuf.python.internal.Factory2Enum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FACTORY_2_VALUE_0', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FACTORY_2_VALUE_1', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1816, + serialized_end=1876, +) +_sym_db.RegisterEnumDescriptor(_FACTORY2ENUM) + +Factory2Enum = enum_type_wrapper.EnumTypeWrapper(_FACTORY2ENUM) +FACTORY_2_VALUE_0 = 0 +FACTORY_2_VALUE_1 = 1 + +ANOTHER_FIELD_FIELD_NUMBER = 1002 +another_field = _descriptor.FieldDescriptor( + name='another_field', full_name='google.protobuf.python.internal.another_field', index=0, + number=1002, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_FACTORY2MESSAGE_NESTEDFACTORY2ENUM = _descriptor.EnumDescriptor( + name='NestedFactory2Enum', + full_name='google.protobuf.python.internal.Factory2Message.NestedFactory2Enum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NESTED_FACTORY_2_VALUE_0', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NESTED_FACTORY_2_VALUE_1', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1454, + serialized_end=1534, +) +_sym_db.RegisterEnumDescriptor(_FACTORY2MESSAGE_NESTEDFACTORY2ENUM) + +_MESSAGEWITHNESTEDENUMONLY_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NESTED_MESSAGE_ENUM_0', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1734, + serialized_end=1773, +) +_sym_db.RegisterEnumDescriptor(_MESSAGEWITHNESTEDENUMONLY_NESTEDENUM) + + +_FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE = _descriptor.Descriptor( + name='NestedFactory2Message', + full_name='google.protobuf.python.internal.Factory2Message.NestedFactory2Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.python.internal.Factory2Message.NestedFactory2Message.value', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1371, + serialized_end=1409, +) + +_FACTORY2MESSAGE_GROUPED = _descriptor.Descriptor( + name='Grouped', + full_name='google.protobuf.python.internal.Factory2Message.Grouped', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='part_1', full_name='google.protobuf.python.internal.Factory2Message.Grouped.part_1', index=0, + number=13, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='part_2', full_name='google.protobuf.python.internal.Factory2Message.Grouped.part_2', index=1, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1411, + serialized_end=1452, +) + +_FACTORY2MESSAGE = _descriptor.Descriptor( + name='Factory2Message', + full_name='google.protobuf.python.internal.Factory2Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='mandatory', full_name='google.protobuf.python.internal.Factory2Message.mandatory', index=0, + number=1, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='factory_2_enum', full_name='google.protobuf.python.internal.Factory2Message.factory_2_enum', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_2_enum', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_2_enum', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_2_message', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_2_message', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='factory_1_message', full_name='google.protobuf.python.internal.Factory2Message.factory_1_message', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='factory_1_enum', full_name='google.protobuf.python.internal.Factory2Message.factory_1_enum', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_1_enum', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_1_enum', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_factory_1_message', full_name='google.protobuf.python.internal.Factory2Message.nested_factory_1_message', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='circular_message', full_name='google.protobuf.python.internal.Factory2Message.circular_message', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='scalar_value', full_name='google.protobuf.python.internal.Factory2Message.scalar_value', index=9, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='list_value', full_name='google.protobuf.python.internal.Factory2Message.list_value', index=10, + number=11, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='grouped', full_name='google.protobuf.python.internal.Factory2Message.grouped', index=11, + number=12, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='loop', full_name='google.protobuf.python.internal.Factory2Message.loop', index=12, + number=15, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_with_default', full_name='google.protobuf.python.internal.Factory2Message.int_with_default', index=13, + number=16, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=1776, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_with_default', full_name='google.protobuf.python.internal.Factory2Message.double_with_default', index=14, + number=17, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(9.99), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_with_default', full_name='google.protobuf.python.internal.Factory2Message.string_with_default', index=15, + number=18, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello world").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_with_default', full_name='google.protobuf.python.internal.Factory2Message.bool_with_default', index=16, + number=19, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_with_default', full_name='google.protobuf.python.internal.Factory2Message.enum_with_default', index=17, + number=20, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_with_default', full_name='google.protobuf.python.internal.Factory2Message.bytes_with_default', index=18, + number=21, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("a\373\000c"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_int', full_name='google.protobuf.python.internal.Factory2Message.oneof_int', index=19, + number=22, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='google.protobuf.python.internal.Factory2Message.oneof_string', index=20, + number=23, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='one_more_field', full_name='google.protobuf.python.internal.Factory2Message.one_more_field', index=0, + number=1001, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE, _FACTORY2MESSAGE_GROUPED, ], + enum_types=[ + _FACTORY2MESSAGE_NESTEDFACTORY2ENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='google.protobuf.python.internal.Factory2Message.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=128, + serialized_end=1624, +) + + +_LOOPMESSAGE = _descriptor.Descriptor( + name='LoopMessage', + full_name='google.protobuf.python.internal.LoopMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='loop', full_name='google.protobuf.python.internal.LoopMessage.loop', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1626, + serialized_end=1703, +) + + +_MESSAGEWITHNESTEDENUMONLY = _descriptor.Descriptor( + name='MessageWithNestedEnumOnly', + full_name='google.protobuf.python.internal.MessageWithNestedEnumOnly', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _MESSAGEWITHNESTEDENUMONLY_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1705, + serialized_end=1773, +) + + +_MESSAGEWITHOPTION = _descriptor.Descriptor( + name='MessageWithOption', + full_name='google.protobuf.python.internal.MessageWithOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='google.protobuf.python.internal.MessageWithOption.field1', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\020\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1775, + serialized_end=1814, +) + +_FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE.containing_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE_GROUPED.containing_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE.fields_by_name['factory_2_enum'].enum_type = _FACTORY2ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_2_enum'].enum_type = _FACTORY2MESSAGE_NESTEDFACTORY2ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_2_message'].message_type = _FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE +_FACTORY2MESSAGE.fields_by_name['factory_1_message'].message_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1MESSAGE +_FACTORY2MESSAGE.fields_by_name['factory_1_enum'].enum_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_1_enum'].enum_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1MESSAGE_NESTEDFACTORY1ENUM +_FACTORY2MESSAGE.fields_by_name['nested_factory_1_message'].message_type = google_dot_protobuf_dot_internal_dot_factory__test1__pb2._FACTORY1MESSAGE_NESTEDFACTORY1MESSAGE +_FACTORY2MESSAGE.fields_by_name['circular_message'].message_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE.fields_by_name['grouped'].message_type = _FACTORY2MESSAGE_GROUPED +_FACTORY2MESSAGE.fields_by_name['loop'].message_type = _LOOPMESSAGE +_FACTORY2MESSAGE.fields_by_name['enum_with_default'].enum_type = _FACTORY2ENUM +_FACTORY2MESSAGE_NESTEDFACTORY2ENUM.containing_type = _FACTORY2MESSAGE +_FACTORY2MESSAGE.oneofs_by_name['oneof_field'].fields.append( + _FACTORY2MESSAGE.fields_by_name['oneof_int']) +_FACTORY2MESSAGE.fields_by_name['oneof_int'].containing_oneof = _FACTORY2MESSAGE.oneofs_by_name['oneof_field'] +_FACTORY2MESSAGE.oneofs_by_name['oneof_field'].fields.append( + _FACTORY2MESSAGE.fields_by_name['oneof_string']) +_FACTORY2MESSAGE.fields_by_name['oneof_string'].containing_oneof = _FACTORY2MESSAGE.oneofs_by_name['oneof_field'] +_LOOPMESSAGE.fields_by_name['loop'].message_type = _FACTORY2MESSAGE +_MESSAGEWITHNESTEDENUMONLY_NESTEDENUM.containing_type = _MESSAGEWITHNESTEDENUMONLY +DESCRIPTOR.message_types_by_name['Factory2Message'] = _FACTORY2MESSAGE +DESCRIPTOR.message_types_by_name['LoopMessage'] = _LOOPMESSAGE +DESCRIPTOR.message_types_by_name['MessageWithNestedEnumOnly'] = _MESSAGEWITHNESTEDENUMONLY +DESCRIPTOR.message_types_by_name['MessageWithOption'] = _MESSAGEWITHOPTION +DESCRIPTOR.enum_types_by_name['Factory2Enum'] = _FACTORY2ENUM +DESCRIPTOR.extensions_by_name['another_field'] = another_field +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Factory2Message = _reflection.GeneratedProtocolMessageType('Factory2Message', (_message.Message,), dict( + + NestedFactory2Message = _reflection.GeneratedProtocolMessageType('NestedFactory2Message', (_message.Message,), dict( + DESCRIPTOR = _FACTORY2MESSAGE_NESTEDFACTORY2MESSAGE, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.Factory2Message.NestedFactory2Message) + )) + , + + Grouped = _reflection.GeneratedProtocolMessageType('Grouped', (_message.Message,), dict( + DESCRIPTOR = _FACTORY2MESSAGE_GROUPED, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.Factory2Message.Grouped) + )) + , + DESCRIPTOR = _FACTORY2MESSAGE, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.Factory2Message) + )) +_sym_db.RegisterMessage(Factory2Message) +_sym_db.RegisterMessage(Factory2Message.NestedFactory2Message) +_sym_db.RegisterMessage(Factory2Message.Grouped) + +LoopMessage = _reflection.GeneratedProtocolMessageType('LoopMessage', (_message.Message,), dict( + DESCRIPTOR = _LOOPMESSAGE, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.LoopMessage) + )) +_sym_db.RegisterMessage(LoopMessage) + +MessageWithNestedEnumOnly = _reflection.GeneratedProtocolMessageType('MessageWithNestedEnumOnly', (_message.Message,), dict( + DESCRIPTOR = _MESSAGEWITHNESTEDENUMONLY, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.MessageWithNestedEnumOnly) + )) +_sym_db.RegisterMessage(MessageWithNestedEnumOnly) + +MessageWithOption = _reflection.GeneratedProtocolMessageType('MessageWithOption', (_message.Message,), dict( + DESCRIPTOR = _MESSAGEWITHOPTION, + __module__ = 'google.protobuf.internal.factory_test2_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.MessageWithOption) + )) +_sym_db.RegisterMessage(MessageWithOption) + +google_dot_protobuf_dot_internal_dot_factory__test1__pb2.Factory1Message.RegisterExtension(another_field) +google_dot_protobuf_dot_internal_dot_factory__test1__pb2.Factory1Message.RegisterExtension(_FACTORY2MESSAGE.extensions_by_name['one_more_field']) + +_MESSAGEWITHOPTION._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/file_options_test_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/file_options_test_pb2.py new file mode 100644 index 0000000..31566ca --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/file_options_test_pb2.py @@ -0,0 +1,82 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/file_options_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/file_options_test.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n0google/protobuf/internal/file_options_test.proto\x12\x1fgoogle.protobuf.python.internal\x1a google/protobuf/descriptor.proto\"\x1e\n\nFooOptions\x12\x10\n\x08\x66oo_name\x18\x01 \x01(\t:a\n\x0b\x66oo_options\x12\x1c.google.protobuf.FileOptions\x18\xac\xec\xb6\x39 \x01(\x0b\x32+.google.protobuf.python.internal.FooOptions') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + + +FOO_OPTIONS_FIELD_NUMBER = 120436268 +foo_options = _descriptor.FieldDescriptor( + name='foo_options', full_name='google.protobuf.python.internal.foo_options', index=0, + number=120436268, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_FOOOPTIONS = _descriptor.Descriptor( + name='FooOptions', + full_name='google.protobuf.python.internal.FooOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_name', full_name='google.protobuf.python.internal.FooOptions.foo_name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=119, + serialized_end=149, +) + +DESCRIPTOR.message_types_by_name['FooOptions'] = _FOOOPTIONS +DESCRIPTOR.extensions_by_name['foo_options'] = foo_options +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FooOptions = _reflection.GeneratedProtocolMessageType('FooOptions', (_message.Message,), dict( + DESCRIPTOR = _FOOOPTIONS, + __module__ = 'google.protobuf.internal.file_options_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.FooOptions) + )) +_sym_db.RegisterMessage(FooOptions) + +foo_options.message_type = _FOOOPTIONS +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(foo_options) + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/generator_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/generator_test.py new file mode 100644 index 0000000..7f13f9d --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/generator_test.py @@ -0,0 +1,349 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# TODO(robinson): Flesh this out considerably. We focused on reflection_test.py +# first, since it's testing the subtler code, and since it provides decent +# indirect testing of the protocol compiler output. + +"""Unittest that directly tests the output of the pure-Python protocol +compiler. See //google/protobuf/internal/reflection_test.py for a test which +further ensures that we can use Python protocol message objects as we expect. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf.internal import test_bad_identifiers_pb2 +from google.protobuf import unittest_custom_options_pb2 +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_import_public_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_mset_wire_format_pb2 +from google.protobuf import unittest_no_generic_services_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import service +from google.protobuf import symbol_database + +MAX_EXTENSION = 536870912 + + +class GeneratorTest(unittest.TestCase): + + def testNestedMessageDescriptor(self): + field_name = 'optional_nested_message' + proto_type = unittest_pb2.TestAllTypes + self.assertEqual( + proto_type.NestedMessage.DESCRIPTOR, + proto_type.DESCRIPTOR.fields_by_name[field_name].message_type) + + def testEnums(self): + # We test only module-level enums here. + # TODO(robinson): Examine descriptors directly to check + # enum descriptor output. + self.assertEqual(4, unittest_pb2.FOREIGN_FOO) + self.assertEqual(5, unittest_pb2.FOREIGN_BAR) + self.assertEqual(6, unittest_pb2.FOREIGN_BAZ) + + proto = unittest_pb2.TestAllTypes() + self.assertEqual(1, proto.FOO) + self.assertEqual(1, unittest_pb2.TestAllTypes.FOO) + self.assertEqual(2, proto.BAR) + self.assertEqual(2, unittest_pb2.TestAllTypes.BAR) + self.assertEqual(3, proto.BAZ) + self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ) + + def testExtremeDefaultValues(self): + message = unittest_pb2.TestExtremeDefaultValues() + + # Python pre-2.6 does not have isinf() or isnan() functions, so we have + # to provide our own. + def isnan(val): + # NaN is never equal to itself. + return val != val + def isinf(val): + # Infinity times zero equals NaN. + return not isnan(val) and isnan(val * 0) + + self.assertTrue(isinf(message.inf_double)) + self.assertTrue(message.inf_double > 0) + self.assertTrue(isinf(message.neg_inf_double)) + self.assertTrue(message.neg_inf_double < 0) + self.assertTrue(isnan(message.nan_double)) + + self.assertTrue(isinf(message.inf_float)) + self.assertTrue(message.inf_float > 0) + self.assertTrue(isinf(message.neg_inf_float)) + self.assertTrue(message.neg_inf_float < 0) + self.assertTrue(isnan(message.nan_float)) + self.assertEqual("? ? ?? ?? ??? ??/ ??-", message.cpp_trigraph) + + def testHasDefaultValues(self): + desc = unittest_pb2.TestAllTypes.DESCRIPTOR + + expected_has_default_by_name = { + 'optional_int32': False, + 'repeated_int32': False, + 'optional_nested_message': False, + 'default_int32': True, + } + + has_default_by_name = dict( + [(f.name, f.has_default_value) + for f in desc.fields + if f.name in expected_has_default_by_name]) + self.assertEqual(expected_has_default_by_name, has_default_by_name) + + def testContainingTypeBehaviorForExtensions(self): + self.assertEqual(unittest_pb2.optional_int32_extension.containing_type, + unittest_pb2.TestAllExtensions.DESCRIPTOR) + self.assertEqual(unittest_pb2.TestRequired.single.containing_type, + unittest_pb2.TestAllExtensions.DESCRIPTOR) + + def testExtensionScope(self): + self.assertEqual(unittest_pb2.optional_int32_extension.extension_scope, + None) + self.assertEqual(unittest_pb2.TestRequired.single.extension_scope, + unittest_pb2.TestRequired.DESCRIPTOR) + + def testIsExtension(self): + self.assertTrue(unittest_pb2.optional_int32_extension.is_extension) + self.assertTrue(unittest_pb2.TestRequired.single.is_extension) + + message_descriptor = unittest_pb2.TestRequired.DESCRIPTOR + non_extension_descriptor = message_descriptor.fields_by_name['a'] + self.assertTrue(not non_extension_descriptor.is_extension) + + def testOptions(self): + proto = unittest_mset_wire_format_pb2.TestMessageSet() + self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format) + + def testMessageWithCustomOptions(self): + proto = unittest_custom_options_pb2.TestMessageWithCustomOptions() + enum_options = proto.DESCRIPTOR.enum_types_by_name['AnEnum'].GetOptions() + self.assertTrue(enum_options is not None) + # TODO(gps): We really should test for the presence of the enum_opt1 + # extension and for its value to be set to -789. + + def testNestedTypes(self): + self.assertEqual( + set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types), + set([ + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR, + unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR, + unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR, + ])) + self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, []) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, []) + + def testContainingType(self): + self.assertTrue( + unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None) + self.assertTrue( + unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertEqual( + unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + + def testContainingTypeInEnumDescriptor(self): + self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None) + self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type, + unittest_pb2.TestAllTypes.DESCRIPTOR) + + def testPackage(self): + self.assertEqual( + unittest_pb2.TestAllTypes.DESCRIPTOR.file.package, + 'protobuf_unittest') + desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR + self.assertEqual(desc.file.package, 'protobuf_unittest') + self.assertEqual( + unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package, + 'protobuf_unittest_import') + + self.assertEqual( + unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest') + self.assertEqual( + unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package, + 'protobuf_unittest') + self.assertEqual( + unittest_import_pb2._IMPORTENUM.file.package, + 'protobuf_unittest_import') + + def testExtensionRange(self): + self.assertEqual( + unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, []) + self.assertEqual( + unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges, + [(1, MAX_EXTENSION)]) + self.assertEqual( + unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges, + [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)]) + + def testFileDescriptor(self): + self.assertEqual(unittest_pb2.DESCRIPTOR.name, + 'google/protobuf/unittest.proto') + self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest') + self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None) + self.assertEqual(unittest_pb2.DESCRIPTOR.dependencies, + [unittest_import_pb2.DESCRIPTOR]) + self.assertEqual(unittest_import_pb2.DESCRIPTOR.dependencies, + [unittest_import_public_pb2.DESCRIPTOR]) + self.assertEqual(unittest_import_pb2.DESCRIPTOR.public_dependencies, + [unittest_import_public_pb2.DESCRIPTOR]) + def testNoGenericServices(self): + self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage")) + self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO")) + self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension")) + + # Make sure unittest_no_generic_services_pb2 has no services subclassing + # Proto2 Service class. + if hasattr(unittest_no_generic_services_pb2, "TestService"): + self.assertFalse(issubclass(unittest_no_generic_services_pb2.TestService, + service.Service)) + + def testMessageTypesByName(self): + file_type = unittest_pb2.DESCRIPTOR + self.assertEqual( + unittest_pb2._TESTALLTYPES, + file_type.message_types_by_name[unittest_pb2._TESTALLTYPES.name]) + + # Nested messages shouldn't be included in the message_types_by_name + # dictionary (like in the C++ API). + self.assertFalse( + unittest_pb2._TESTALLTYPES_NESTEDMESSAGE.name in + file_type.message_types_by_name) + + def testEnumTypesByName(self): + file_type = unittest_pb2.DESCRIPTOR + self.assertEqual( + unittest_pb2._FOREIGNENUM, + file_type.enum_types_by_name[unittest_pb2._FOREIGNENUM.name]) + + def testExtensionsByName(self): + file_type = unittest_pb2.DESCRIPTOR + self.assertEqual( + unittest_pb2.my_extension_string, + file_type.extensions_by_name[unittest_pb2.my_extension_string.name]) + + def testPublicImports(self): + # Test public imports as embedded message. + all_type_proto = unittest_pb2.TestAllTypes() + self.assertEqual(0, all_type_proto.optional_public_import_message.e) + + # PublicImportMessage is actually defined in unittest_import_public_pb2 + # module, and is public imported by unittest_import_pb2 module. + public_import_proto = unittest_import_pb2.PublicImportMessage() + self.assertEqual(0, public_import_proto.e) + self.assertTrue(unittest_import_public_pb2.PublicImportMessage is + unittest_import_pb2.PublicImportMessage) + + def testBadIdentifiers(self): + # We're just testing that the code was imported without problems. + message = test_bad_identifiers_pb2.TestBadIdentifiers() + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.message], + "foo") + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.descriptor], + "bar") + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.reflection], + "baz") + self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service], + "qux") + + def testOneof(self): + desc = unittest_pb2.TestAllTypes.DESCRIPTOR + self.assertEqual(1, len(desc.oneofs)) + self.assertEqual('oneof_field', desc.oneofs[0].name) + self.assertEqual(0, desc.oneofs[0].index) + self.assertIs(desc, desc.oneofs[0].containing_type) + self.assertIs(desc.oneofs[0], desc.oneofs_by_name['oneof_field']) + nested_names = set(['oneof_uint32', 'oneof_nested_message', + 'oneof_string', 'oneof_bytes']) + self.assertEqual( + nested_names, + set([field.name for field in desc.oneofs[0].fields])) + for field_name, field_desc in desc.fields_by_name.items(): + if field_name in nested_names: + self.assertIs(desc.oneofs[0], field_desc.containing_oneof) + else: + self.assertIsNone(field_desc.containing_oneof) + + +class SymbolDatabaseRegistrationTest(unittest.TestCase): + """Checks that messages, enums and files are correctly registered.""" + + def testGetSymbol(self): + self.assertEqual( + unittest_pb2.TestAllTypes, symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes')) + self.assertEqual( + unittest_pb2.TestAllTypes.NestedMessage, + symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes.NestedMessage')) + with self.assertRaises(KeyError): + symbol_database.Default().GetSymbol('protobuf_unittest.NestedMessage') + self.assertEqual( + unittest_pb2.TestAllTypes.OptionalGroup, + symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes.OptionalGroup')) + self.assertEqual( + unittest_pb2.TestAllTypes.RepeatedGroup, + symbol_database.Default().GetSymbol( + 'protobuf_unittest.TestAllTypes.RepeatedGroup')) + + def testEnums(self): + self.assertEqual( + 'protobuf_unittest.ForeignEnum', + symbol_database.Default().pool.FindEnumTypeByName( + 'protobuf_unittest.ForeignEnum').full_name) + self.assertEqual( + 'protobuf_unittest.TestAllTypes.NestedEnum', + symbol_database.Default().pool.FindEnumTypeByName( + 'protobuf_unittest.TestAllTypes.NestedEnum').full_name) + + def testFindFileByName(self): + self.assertEqual( + 'google/protobuf/unittest.proto', + symbol_database.Default().pool.FindFileByName( + 'google/protobuf/unittest.proto').name) + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/__init__.py b/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/__init__.py new file mode 100644 index 0000000..5121dd0 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/__init__.py @@ -0,0 +1,33 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Sample module importing a nested proto from itself.""" + +from google.protobuf.internal.import_test_package import outer_pb2 as myproto diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py new file mode 100644 index 0000000..61db2a5 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/inner_pb2.py @@ -0,0 +1,69 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/import_test_package/inner.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/import_test_package/inner.proto', + package='google.protobuf.python.internal.import_test_package', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n8google/protobuf/internal/import_test_package/inner.proto\x12\x33google.protobuf.python.internal.import_test_package\"\x1a\n\x05Inner\x12\x11\n\x05value\x18\x01 \x01(\x05:\x02\x35\x37') +) + + + + +_INNER = _descriptor.Descriptor( + name='Inner', + full_name='google.protobuf.python.internal.import_test_package.Inner', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.python.internal.import_test_package.Inner.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=57, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=139, +) + +DESCRIPTOR.message_types_by_name['Inner'] = _INNER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Inner = _reflection.GeneratedProtocolMessageType('Inner', (_message.Message,), dict( + DESCRIPTOR = _INNER, + __module__ = 'google.protobuf.internal.import_test_package.inner_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.import_test_package.Inner) + )) +_sym_db.RegisterMessage(Inner) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py new file mode 100644 index 0000000..966b18c --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/import_test_package/outer_pb2.py @@ -0,0 +1,72 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/import_test_package/outer.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf.internal.import_test_package import inner_pb2 as google_dot_protobuf_dot_internal_dot_import__test__package_dot_inner__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/import_test_package/outer.proto', + package='google.protobuf.python.internal.import_test_package', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n8google/protobuf/internal/import_test_package/outer.proto\x12\x33google.protobuf.python.internal.import_test_package\x1a\x38google/protobuf/internal/import_test_package/inner.proto\"R\n\x05Outer\x12I\n\x05inner\x18\x01 \x01(\x0b\x32:.google.protobuf.python.internal.import_test_package.Inner') + , + dependencies=[google_dot_protobuf_dot_internal_dot_import__test__package_dot_inner__pb2.DESCRIPTOR,]) + + + + +_OUTER = _descriptor.Descriptor( + name='Outer', + full_name='google.protobuf.python.internal.import_test_package.Outer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='inner', full_name='google.protobuf.python.internal.import_test_package.Outer.inner', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=171, + serialized_end=253, +) + +_OUTER.fields_by_name['inner'].message_type = google_dot_protobuf_dot_internal_dot_import__test__package_dot_inner__pb2._INNER +DESCRIPTOR.message_types_by_name['Outer'] = _OUTER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Outer = _reflection.GeneratedProtocolMessageType('Outer', (_message.Message,), dict( + DESCRIPTOR = _OUTER, + __module__ = 'google.protobuf.internal.import_test_package.outer_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.import_test_package.Outer) + )) +_sym_db.RegisterMessage(Outer) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/json_format_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/json_format_test.py new file mode 100644 index 0000000..d891dce --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/json_format_test.py @@ -0,0 +1,1038 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.json_format.""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import json +import math +import sys + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import any_pb2 +from google.protobuf import duration_pb2 +from google.protobuf import field_mask_pb2 +from google.protobuf import struct_pb2 +from google.protobuf import timestamp_pb2 +from google.protobuf import wrappers_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf.internal import well_known_types +from google.protobuf import json_format +from google.protobuf.util import json_format_proto3_pb2 + + +class JsonFormatBase(unittest.TestCase): + + def FillAllFields(self, message): + message.int32_value = 20 + message.int64_value = -20 + message.uint32_value = 3120987654 + message.uint64_value = 12345678900 + message.float_value = float('-inf') + message.double_value = 3.1415 + message.bool_value = True + message.string_value = 'foo' + message.bytes_value = b'bar' + message.message_value.value = 10 + message.enum_value = json_format_proto3_pb2.BAR + # Repeated + message.repeated_int32_value.append(0x7FFFFFFF) + message.repeated_int32_value.append(-2147483648) + message.repeated_int64_value.append(9007199254740992) + message.repeated_int64_value.append(-9007199254740992) + message.repeated_uint32_value.append(0xFFFFFFF) + message.repeated_uint32_value.append(0x7FFFFFF) + message.repeated_uint64_value.append(9007199254740992) + message.repeated_uint64_value.append(9007199254740991) + message.repeated_float_value.append(0) + + message.repeated_double_value.append(1E-15) + message.repeated_double_value.append(float('inf')) + message.repeated_bool_value.append(True) + message.repeated_bool_value.append(False) + message.repeated_string_value.append('Few symbols!#$,;') + message.repeated_string_value.append('bar') + message.repeated_bytes_value.append(b'foo') + message.repeated_bytes_value.append(b'bar') + message.repeated_message_value.add().value = 10 + message.repeated_message_value.add().value = 11 + message.repeated_enum_value.append(json_format_proto3_pb2.FOO) + message.repeated_enum_value.append(json_format_proto3_pb2.BAR) + self.message = message + + def CheckParseBack(self, message, parsed_message): + json_format.Parse(json_format.MessageToJson(message), + parsed_message) + self.assertEqual(message, parsed_message) + + def CheckError(self, text, error_message): + message = json_format_proto3_pb2.TestMessage() + self.assertRaisesRegexp( + json_format.ParseError, + error_message, + json_format.Parse, text, message) + + +class JsonFormatTest(JsonFormatBase): + + def testEmptyMessageToJson(self): + message = json_format_proto3_pb2.TestMessage() + self.assertEqual(json_format.MessageToJson(message), + '{}') + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + + def testPartialMessageToJson(self): + message = json_format_proto3_pb2.TestMessage( + string_value='test', + repeated_int32_value=[89, 4]) + self.assertEqual(json.loads(json_format.MessageToJson(message)), + json.loads('{"stringValue": "test", ' + '"repeatedInt32Value": [89, 4]}')) + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + + def testAllFieldsToJson(self): + message = json_format_proto3_pb2.TestMessage() + text = ('{"int32Value": 20, ' + '"int64Value": "-20", ' + '"uint32Value": 3120987654,' + '"uint64Value": "12345678900",' + '"floatValue": "-Infinity",' + '"doubleValue": 3.1415,' + '"boolValue": true,' + '"stringValue": "foo",' + '"bytesValue": "YmFy",' + '"messageValue": {"value": 10},' + '"enumValue": "BAR",' + '"repeatedInt32Value": [2147483647, -2147483648],' + '"repeatedInt64Value": ["9007199254740992", "-9007199254740992"],' + '"repeatedUint32Value": [268435455, 134217727],' + '"repeatedUint64Value": ["9007199254740992", "9007199254740991"],' + '"repeatedFloatValue": [0],' + '"repeatedDoubleValue": [1e-15, "Infinity"],' + '"repeatedBoolValue": [true, false],' + '"repeatedStringValue": ["Few symbols!#$,;", "bar"],' + '"repeatedBytesValue": ["Zm9v", "YmFy"],' + '"repeatedMessageValue": [{"value": 10}, {"value": 11}],' + '"repeatedEnumValue": ["FOO", "BAR"]' + '}') + self.FillAllFields(message) + self.assertEqual( + json.loads(json_format.MessageToJson(message)), + json.loads(text)) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + + def testUnknownEnumToJsonAndBack(self): + text = '{\n "enumValue": 999\n}' + message = json_format_proto3_pb2.TestMessage() + message.enum_value = 999 + self.assertEqual(json_format.MessageToJson(message), + text) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message) + + def testExtensionToJsonAndBack(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_text = json_format.MessageToJson( + message + ) + parsed_message = unittest_mset_pb2.TestMessageSetContainer() + json_format.Parse(message_text, parsed_message) + self.assertEqual(message, parsed_message) + + def testExtensionErrors(self): + self.CheckError('{"[extensionField]": {}}', + 'Message type proto3.TestMessage does not have extensions') + + def testExtensionToDictAndBack(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_dict = json_format.MessageToDict( + message + ) + parsed_message = unittest_mset_pb2.TestMessageSetContainer() + json_format.ParseDict(message_dict, parsed_message) + self.assertEqual(message, parsed_message) + + def testExtensionSerializationDictMatchesProto3Spec(self): + """See go/proto3-json-spec for spec. + """ + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_dict = json_format.MessageToDict( + message + ) + golden_dict = { + 'messageSet': { + '[protobuf_unittest.' + 'TestMessageSetExtension1.messageSetExtension]': { + 'i': 23, + }, + '[protobuf_unittest.' + 'TestMessageSetExtension2.messageSetExtension]': { + 'str': u'foo', + }, + }, + } + self.assertEqual(golden_dict, message_dict) + + + def testExtensionSerializationJsonMatchesProto3Spec(self): + """See go/proto3-json-spec for spec. + """ + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + message_text = json_format.MessageToJson( + message + ) + ext1_text = ('protobuf_unittest.TestMessageSetExtension1.' + 'messageSetExtension') + ext2_text = ('protobuf_unittest.TestMessageSetExtension2.' + 'messageSetExtension') + golden_text = ('{"messageSet": {' + ' "[%s]": {' + ' "i": 23' + ' },' + ' "[%s]": {' + ' "str": "foo"' + ' }' + '}}') % (ext1_text, ext2_text) + self.assertEqual(json.loads(golden_text), json.loads(message_text)) + + + def testJsonEscapeString(self): + message = json_format_proto3_pb2.TestMessage() + if sys.version_info[0] < 3: + message.string_value = '&\n<\"\r>\b\t\f\\\001/\xe2\x80\xa8\xe2\x80\xa9' + else: + message.string_value = '&\n<\"\r>\b\t\f\\\001/' + message.string_value += (b'\xe2\x80\xa8\xe2\x80\xa9').decode('utf-8') + self.assertEqual( + json_format.MessageToJson(message), + '{\n "stringValue": ' + '"&\\n<\\\"\\r>\\b\\t\\f\\\\\\u0001/\\u2028\\u2029"\n}') + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + text = u'{"int32Value": "\u0031"}' + json_format.Parse(text, message) + self.assertEqual(message.int32_value, 1) + + def testAlwaysSeriliaze(self): + message = json_format_proto3_pb2.TestMessage( + string_value='foo') + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"repeatedStringValue": [],' + '"stringValue": "foo",' + '"repeatedBoolValue": [],' + '"repeatedUint32Value": [],' + '"repeatedInt32Value": [],' + '"enumValue": "FOO",' + '"int32Value": 0,' + '"floatValue": 0,' + '"int64Value": "0",' + '"uint32Value": 0,' + '"repeatedBytesValue": [],' + '"repeatedUint64Value": [],' + '"repeatedDoubleValue": [],' + '"bytesValue": "",' + '"boolValue": false,' + '"repeatedEnumValue": [],' + '"uint64Value": "0",' + '"doubleValue": 0,' + '"repeatedFloatValue": [],' + '"repeatedInt64Value": [],' + '"repeatedMessageValue": []}')) + parsed_message = json_format_proto3_pb2.TestMessage() + self.CheckParseBack(message, parsed_message) + + def testIntegersRepresentedAsFloat(self): + message = json_format_proto3_pb2.TestMessage() + json_format.Parse('{"int32Value": -2.147483648e9}', message) + self.assertEqual(message.int32_value, -2147483648) + json_format.Parse('{"int32Value": 1e5}', message) + self.assertEqual(message.int32_value, 100000) + json_format.Parse('{"int32Value": 1.0}', message) + self.assertEqual(message.int32_value, 1) + + def testMapFields(self): + message = json_format_proto3_pb2.TestNestedMap() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"boolMap": {},' + '"int32Map": {},' + '"int64Map": {},' + '"uint32Map": {},' + '"uint64Map": {},' + '"stringMap": {},' + '"mapMap": {}' + '}')) + message.bool_map[True] = 1 + message.bool_map[False] = 2 + message.int32_map[1] = 2 + message.int32_map[2] = 3 + message.int64_map[1] = 2 + message.int64_map[2] = 3 + message.uint32_map[1] = 2 + message.uint32_map[2] = 3 + message.uint64_map[1] = 2 + message.uint64_map[2] = 3 + message.string_map['1'] = 2 + message.string_map['null'] = 3 + message.map_map['1'].bool_map[True] = 3 + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads('{' + '"boolMap": {"false": 2, "true": 1},' + '"int32Map": {"1": 2, "2": 3},' + '"int64Map": {"1": 2, "2": 3},' + '"uint32Map": {"1": 2, "2": 3},' + '"uint64Map": {"1": 2, "2": 3},' + '"stringMap": {"1": 2, "null": 3},' + '"mapMap": {"1": {"boolMap": {"true": 3}}}' + '}')) + parsed_message = json_format_proto3_pb2.TestNestedMap() + self.CheckParseBack(message, parsed_message) + + def testOneofFields(self): + message = json_format_proto3_pb2.TestOneof() + # Always print does not affect oneof fields. + self.assertEqual( + json_format.MessageToJson(message, True), + '{}') + message.oneof_int32_value = 0 + self.assertEqual( + json_format.MessageToJson(message, True), + '{\n' + ' "oneofInt32Value": 0\n' + '}') + parsed_message = json_format_proto3_pb2.TestOneof() + self.CheckParseBack(message, parsed_message) + + def testSurrogates(self): + # Test correct surrogate handling. + message = json_format_proto3_pb2.TestMessage() + json_format.Parse('{"stringValue": "\\uD83D\\uDE01"}', message) + self.assertEqual(message.string_value, + b'\xF0\x9F\x98\x81'.decode('utf-8', 'strict')) + + # Error case: unpaired high surrogate. + self.CheckError( + '{"stringValue": "\\uD83D"}', + r'Invalid \\uXXXX escape|Unpaired.*surrogate') + + # Unpaired low surrogate. + self.CheckError( + '{"stringValue": "\\uDE01"}', + r'Invalid \\uXXXX escape|Unpaired.*surrogate') + + def testTimestampMessage(self): + message = json_format_proto3_pb2.TestTimestamp() + message.value.seconds = 0 + message.value.nanos = 0 + message.repeated_value.add().seconds = 20 + message.repeated_value[0].nanos = 1 + message.repeated_value.add().seconds = 0 + message.repeated_value[1].nanos = 10000 + message.repeated_value.add().seconds = 100000000 + message.repeated_value[2].nanos = 0 + # Maximum time + message.repeated_value.add().seconds = 253402300799 + message.repeated_value[3].nanos = 999999999 + # Minimum time + message.repeated_value.add().seconds = -62135596800 + message.repeated_value[4].nanos = 0 + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"value": "1970-01-01T00:00:00Z",' + '"repeatedValue": [' + ' "1970-01-01T00:00:20.000000001Z",' + ' "1970-01-01T00:00:00.000010Z",' + ' "1973-03-03T09:46:40Z",' + ' "9999-12-31T23:59:59.999999999Z",' + ' "0001-01-01T00:00:00Z"' + ']' + '}')) + parsed_message = json_format_proto3_pb2.TestTimestamp() + self.CheckParseBack(message, parsed_message) + text = (r'{"value": "1970-01-01T00:00:00.01+08:00",' + r'"repeatedValue":[' + r' "1970-01-01T00:00:00.01+08:30",' + r' "1970-01-01T00:00:00.01-01:23"]}') + json_format.Parse(text, parsed_message) + self.assertEqual(parsed_message.value.seconds, -8 * 3600) + self.assertEqual(parsed_message.value.nanos, 10000000) + self.assertEqual(parsed_message.repeated_value[0].seconds, -8.5 * 3600) + self.assertEqual(parsed_message.repeated_value[1].seconds, 3600 + 23 * 60) + + def testDurationMessage(self): + message = json_format_proto3_pb2.TestDuration() + message.value.seconds = 1 + message.repeated_value.add().seconds = 0 + message.repeated_value[0].nanos = 10 + message.repeated_value.add().seconds = -1 + message.repeated_value[1].nanos = -1000 + message.repeated_value.add().seconds = 10 + message.repeated_value[2].nanos = 11000000 + message.repeated_value.add().seconds = -315576000000 + message.repeated_value.add().seconds = 315576000000 + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{' + '"value": "1s",' + '"repeatedValue": [' + ' "0.000000010s",' + ' "-1.000001s",' + ' "10.011s",' + ' "-315576000000s",' + ' "315576000000s"' + ']' + '}')) + parsed_message = json_format_proto3_pb2.TestDuration() + self.CheckParseBack(message, parsed_message) + + def testFieldMaskMessage(self): + message = json_format_proto3_pb2.TestFieldMask() + message.value.paths.append('foo.bar') + message.value.paths.append('bar') + self.assertEqual( + json_format.MessageToJson(message, True), + '{\n' + ' "value": "foo.bar,bar"\n' + '}') + parsed_message = json_format_proto3_pb2.TestFieldMask() + self.CheckParseBack(message, parsed_message) + + def testWrapperMessage(self): + message = json_format_proto3_pb2.TestWrapper() + message.bool_value.value = False + message.int32_value.value = 0 + message.string_value.value = '' + message.bytes_value.value = b'' + message.repeated_bool_value.add().value = True + message.repeated_bool_value.add().value = False + message.repeated_int32_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads('{\n' + ' "int32Value": 0,' + ' "boolValue": false,' + ' "stringValue": "",' + ' "bytesValue": "",' + ' "repeatedBoolValue": [true, false],' + ' "repeatedInt32Value": [0],' + ' "repeatedUint32Value": [],' + ' "repeatedFloatValue": [],' + ' "repeatedDoubleValue": [],' + ' "repeatedBytesValue": [],' + ' "repeatedInt64Value": [],' + ' "repeatedUint64Value": [],' + ' "repeatedStringValue": []' + '}')) + parsed_message = json_format_proto3_pb2.TestWrapper() + self.CheckParseBack(message, parsed_message) + + def testStructMessage(self): + message = json_format_proto3_pb2.TestStruct() + message.value['name'] = 'Jim' + message.value['age'] = 10 + message.value['attend'] = True + message.value['email'] = None + message.value.get_or_create_struct('address')['city'] = 'SFO' + message.value['address']['house_number'] = 1024 + struct_list = message.value.get_or_create_list('list') + struct_list.extend([6, 'seven', True, False, None]) + struct_list.add_struct()['subkey2'] = 9 + message.repeated_value.add()['age'] = 11 + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{' + ' "value": {' + ' "address": {' + ' "city": "SFO", ' + ' "house_number": 1024' + ' }, ' + ' "age": 10, ' + ' "name": "Jim", ' + ' "attend": true, ' + ' "email": null, ' + ' "list": [6, "seven", true, false, null, {"subkey2": 9}]' + ' },' + ' "repeatedValue": [{"age": 11}, {}]' + '}')) + parsed_message = json_format_proto3_pb2.TestStruct() + self.CheckParseBack(message, parsed_message) + + def testValueMessage(self): + message = json_format_proto3_pb2.TestValue() + message.value.string_value = 'hello' + message.repeated_value.add().number_value = 11.1 + message.repeated_value.add().bool_value = False + message.repeated_value.add().null_value = 0 + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{' + ' "value": "hello",' + ' "repeatedValue": [11.1, false, null]' + '}')) + parsed_message = json_format_proto3_pb2.TestValue() + self.CheckParseBack(message, parsed_message) + # Can't parse back if the Value message is not set. + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{' + ' "value": "hello",' + ' "repeatedValue": [11.1, false, null, null]' + '}')) + message.Clear() + json_format.Parse('{"value": null}', message) + self.assertEqual(message.value.WhichOneof('kind'), 'null_value') + + def testListValueMessage(self): + message = json_format_proto3_pb2.TestListValue() + message.value.values.add().number_value = 11.1 + message.value.values.add().null_value = 0 + message.value.values.add().bool_value = True + message.value.values.add().string_value = 'hello' + message.value.values.add().struct_value['name'] = 'Jim' + message.repeated_value.add().values.add().number_value = 1 + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, False)), + json.loads( + '{"value": [11.1, null, true, "hello", {"name": "Jim"}]\n,' + '"repeatedValue": [[1], []]}')) + parsed_message = json_format_proto3_pb2.TestListValue() + self.CheckParseBack(message, parsed_message) + + def testAnyMessage(self): + message = json_format_proto3_pb2.TestAny() + value1 = json_format_proto3_pb2.MessageType() + value2 = json_format_proto3_pb2.MessageType() + value1.value = 1234 + value2.value = 5678 + message.value.Pack(value1) + message.repeated_value.add().Pack(value1) + message.repeated_value.add().Pack(value2) + message.repeated_value.add() + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "repeatedValue": [ {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "value": 1234\n' + ' }, {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "value": 5678\n' + ' },\n' + ' {}],\n' + ' "value": {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "value": 1234\n' + ' }\n' + '}\n')) + parsed_message = json_format_proto3_pb2.TestAny() + self.CheckParseBack(message, parsed_message) + # Must print @type first + test_message = json_format_proto3_pb2.TestMessage( + bool_value=True, + int32_value=20, + int64_value=-20, + uint32_value=20, + uint64_value=20, + double_value=3.14, + string_value='foo') + message.Clear() + message.value.Pack(test_message) + self.assertEqual( + json_format.MessageToJson(message, False)[0:68], + '{\n' + ' "value": {\n' + ' "@type": "type.googleapis.com/proto3.TestMessage"') + + def testWellKnownInAnyMessage(self): + message = any_pb2.Any() + int32_value = wrappers_pb2.Int32Value() + int32_value.value = 1234 + message.Pack(int32_value) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": \"type.googleapis.com/google.protobuf.Int32Value\",\n' + ' "value": 1234\n' + '}\n')) + parsed_message = any_pb2.Any() + self.CheckParseBack(message, parsed_message) + + timestamp = timestamp_pb2.Timestamp() + message.Pack(timestamp) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Timestamp",\n' + ' "value": "1970-01-01T00:00:00Z"\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + duration = duration_pb2.Duration() + duration.seconds = 1 + message.Pack(duration) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Duration",\n' + ' "value": "1s"\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + field_mask = field_mask_pb2.FieldMask() + field_mask.paths.append('foo.bar') + field_mask.paths.append('bar') + message.Pack(field_mask) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.FieldMask",\n' + ' "value": "foo.bar,bar"\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + struct_message = struct_pb2.Struct() + struct_message['name'] = 'Jim' + message.Pack(struct_message) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Struct",\n' + ' "value": {"name": "Jim"}\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + nested_any = any_pb2.Any() + int32_value.value = 5678 + nested_any.Pack(int32_value) + message.Pack(nested_any) + self.assertEqual( + json.loads(json_format.MessageToJson(message, True)), + json.loads( + '{\n' + ' "@type": "type.googleapis.com/google.protobuf.Any",\n' + ' "value": {\n' + ' "@type": "type.googleapis.com/google.protobuf.Int32Value",\n' + ' "value": 5678\n' + ' }\n' + '}\n')) + self.CheckParseBack(message, parsed_message) + + def testParseNull(self): + message = json_format_proto3_pb2.TestMessage() + parsed_message = json_format_proto3_pb2.TestMessage() + self.FillAllFields(parsed_message) + json_format.Parse('{"int32Value": null, ' + '"int64Value": null, ' + '"uint32Value": null,' + '"uint64Value": null,' + '"floatValue": null,' + '"doubleValue": null,' + '"boolValue": null,' + '"stringValue": null,' + '"bytesValue": null,' + '"messageValue": null,' + '"enumValue": null,' + '"repeatedInt32Value": null,' + '"repeatedInt64Value": null,' + '"repeatedUint32Value": null,' + '"repeatedUint64Value": null,' + '"repeatedFloatValue": null,' + '"repeatedDoubleValue": null,' + '"repeatedBoolValue": null,' + '"repeatedStringValue": null,' + '"repeatedBytesValue": null,' + '"repeatedMessageValue": null,' + '"repeatedEnumValue": null' + '}', + parsed_message) + self.assertEqual(message, parsed_message) + # Null and {} should have different behavior for sub message. + self.assertFalse(parsed_message.HasField('message_value')) + json_format.Parse('{"messageValue": {}}', parsed_message) + self.assertTrue(parsed_message.HasField('message_value')) + # Null is not allowed to be used as an element in repeated field. + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse repeatedInt32Value field: ' + 'null is not allowed to be used as an element in a repeated field.', + json_format.Parse, + '{"repeatedInt32Value":[1, null]}', + parsed_message) + self.CheckError('{"repeatedMessageValue":[null]}', + 'Failed to parse repeatedMessageValue field: null is not' + ' allowed to be used as an element in a repeated field.') + + def testNanFloat(self): + message = json_format_proto3_pb2.TestMessage() + message.float_value = float('nan') + text = '{\n "floatValue": "NaN"\n}' + self.assertEqual(json_format.MessageToJson(message), text) + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message) + self.assertTrue(math.isnan(parsed_message.float_value)) + + def testParseEmptyText(self): + self.CheckError('', + r'Failed to load JSON: (Expecting value)|(No JSON).') + + def testParseEnumValue(self): + message = json_format_proto3_pb2.TestMessage() + text = '{"enumValue": 0}' + json_format.Parse(text, message) + text = '{"enumValue": 1}' + json_format.Parse(text, message) + self.CheckError( + '{"enumValue": "baz"}', + 'Failed to parse enumValue field: Invalid enum value baz ' + 'for enum type proto3.EnumType.') + # Proto3 accepts numeric unknown enums. + text = '{"enumValue": 12345}' + json_format.Parse(text, message) + # Proto2 does not accept unknown enums. + message = unittest_pb2.TestAllTypes() + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse optionalNestedEnum field: Invalid enum value 12345 ' + 'for enum type protobuf_unittest.TestAllTypes.NestedEnum.', + json_format.Parse, '{"optionalNestedEnum": 12345}', message) + + def testParseBadIdentifer(self): + self.CheckError('{int32Value: 1}', + (r'Failed to load JSON: Expecting property name' + r'( enclosed in double quotes)?: line 1')) + self.CheckError('{"unknownName": 1}', + 'Message type "proto3.TestMessage" has no field named ' + '"unknownName".') + + def testIgnoreUnknownField(self): + text = '{"unknownName": 1}' + parsed_message = json_format_proto3_pb2.TestMessage() + json_format.Parse(text, parsed_message, ignore_unknown_fields=True) + text = ('{\n' + ' "repeatedValue": [ {\n' + ' "@type": "type.googleapis.com/proto3.MessageType",\n' + ' "unknownName": 1\n' + ' }]\n' + '}\n') + parsed_message = json_format_proto3_pb2.TestAny() + json_format.Parse(text, parsed_message, ignore_unknown_fields=True) + + def testDuplicateField(self): + # Duplicate key check is not supported for python2.6 + if sys.version_info < (2, 7): + return + self.CheckError('{"int32Value": 1,\n"int32Value":2}', + 'Failed to load JSON: duplicate key int32Value.') + + def testInvalidBoolValue(self): + self.CheckError('{"boolValue": 1}', + 'Failed to parse boolValue field: ' + 'Expected true or false without quotes.') + self.CheckError('{"boolValue": "true"}', + 'Failed to parse boolValue field: ' + 'Expected true or false without quotes.') + + def testInvalidIntegerValue(self): + message = json_format_proto3_pb2.TestMessage() + text = '{"int32Value": 0x12345}' + self.assertRaises(json_format.ParseError, + json_format.Parse, text, message) + self.CheckError('{"int32Value": 1.5}', + 'Failed to parse int32Value field: ' + 'Couldn\'t parse integer: 1.5.') + self.CheckError('{"int32Value": 012345}', + (r'Failed to load JSON: Expecting \'?,\'? delimiter: ' + r'line 1.')) + self.CheckError('{"int32Value": " 1 "}', + 'Failed to parse int32Value field: ' + 'Couldn\'t parse integer: " 1 ".') + self.CheckError('{"int32Value": "1 "}', + 'Failed to parse int32Value field: ' + 'Couldn\'t parse integer: "1 ".') + self.CheckError('{"int32Value": 12345678901234567890}', + 'Failed to parse int32Value field: Value out of range: ' + '12345678901234567890.') + self.CheckError('{"uint32Value": -1}', + 'Failed to parse uint32Value field: ' + 'Value out of range: -1.') + + def testInvalidFloatValue(self): + self.CheckError('{"floatValue": "nan"}', + 'Failed to parse floatValue field: Couldn\'t ' + 'parse float "nan", use "NaN" instead.') + + def testInvalidBytesValue(self): + self.CheckError('{"bytesValue": "AQI"}', + 'Failed to parse bytesValue field: Incorrect padding.') + self.CheckError('{"bytesValue": "AQI*"}', + 'Failed to parse bytesValue field: Incorrect padding.') + + def testInvalidRepeated(self): + self.CheckError('{"repeatedInt32Value": 12345}', + (r'Failed to parse repeatedInt32Value field: repeated field' + r' repeatedInt32Value must be in \[\] which is 12345.')) + + def testInvalidMap(self): + message = json_format_proto3_pb2.TestMap() + text = '{"int32Map": {"null": 2, "2": 3}}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse int32Map field: invalid literal', + json_format.Parse, text, message) + text = '{"int32Map": {1: 2, "2": 3}}' + self.assertRaisesRegexp( + json_format.ParseError, + (r'Failed to load JSON: Expecting property name' + r'( enclosed in double quotes)?: line 1'), + json_format.Parse, text, message) + text = '{"boolMap": {"null": 1}}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse boolMap field: Expected "true" or "false", not null.', + json_format.Parse, text, message) + if sys.version_info < (2, 7): + return + text = r'{"stringMap": {"a": 3, "\u0061": 2}}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to load JSON: duplicate key a', + json_format.Parse, text, message) + text = r'{"stringMap": 0}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse stringMap field: Map field string_map must be ' + 'in a dict which is 0.', + json_format.Parse, text, message) + + def testInvalidTimestamp(self): + message = json_format_proto3_pb2.TestTimestamp() + text = '{"value": "10000-01-01T00:00:00.00Z"}' + self.assertRaisesRegexp( + json_format.ParseError, + 'time data \'10000-01-01T00:00:00\' does not match' + ' format \'%Y-%m-%dT%H:%M:%S\'.', + json_format.Parse, text, message) + text = '{"value": "1970-01-01T00:00:00.0123456789012Z"}' + self.assertRaisesRegexp( + well_known_types.ParseError, + 'nanos 0123456789012 more than 9 fractional digits.', + json_format.Parse, text, message) + text = '{"value": "1972-01-01T01:00:00.01+08"}' + self.assertRaisesRegexp( + well_known_types.ParseError, + (r'Invalid timezone offset value: \+08.'), + json_format.Parse, text, message) + # Time smaller than minimum time. + text = '{"value": "0000-01-01T00:00:00Z"}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse value field: year (0 )?is out of range.', + json_format.Parse, text, message) + # Time bigger than maxinum time. + message.value.seconds = 253402300800 + self.assertRaisesRegexp( + OverflowError, + 'date value out of range', + json_format.MessageToJson, message) + + def testInvalidOneof(self): + message = json_format_proto3_pb2.TestOneof() + text = '{"oneofInt32Value": 1, "oneofStringValue": "2"}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Message type "proto3.TestOneof"' + ' should not have multiple "oneof_value" oneof fields.', + json_format.Parse, text, message) + + def testInvalidListValue(self): + message = json_format_proto3_pb2.TestListValue() + text = '{"value": 1234}' + self.assertRaisesRegexp( + json_format.ParseError, + r'Failed to parse value field: ListValue must be in \[\] which is 1234', + json_format.Parse, text, message) + + def testInvalidStruct(self): + message = json_format_proto3_pb2.TestStruct() + text = '{"value": 1234}' + self.assertRaisesRegexp( + json_format.ParseError, + 'Failed to parse value field: Struct must be in a dict which is 1234', + json_format.Parse, text, message) + + def testInvalidAny(self): + message = any_pb2.Any() + text = '{"@type": "type.googleapis.com/google.protobuf.Int32Value"}' + self.assertRaisesRegexp( + KeyError, + 'value', + json_format.Parse, text, message) + text = '{"value": 1234}' + self.assertRaisesRegexp( + json_format.ParseError, + '@type is missing when parsing any message.', + json_format.Parse, text, message) + text = '{"@type": "type.googleapis.com/MessageNotExist", "value": 1234}' + self.assertRaisesRegexp( + TypeError, + 'Can not find message descriptor by type_url: ' + 'type.googleapis.com/MessageNotExist.', + json_format.Parse, text, message) + # Only last part is to be used: b/25630112 + text = (r'{"@type": "incorrect.googleapis.com/google.protobuf.Int32Value",' + r'"value": 1234}') + json_format.Parse(text, message) + + def testPreservingProtoFieldNames(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + self.assertEqual('{\n "int32Value": 12345\n}', + json_format.MessageToJson(message)) + self.assertEqual('{\n "int32_value": 12345\n}', + json_format.MessageToJson(message, False, True)) + # When including_default_value_fields is True. + message = json_format_proto3_pb2.TestTimestamp() + self.assertEqual('{\n "repeatedValue": []\n}', + json_format.MessageToJson(message, True, False)) + self.assertEqual('{\n "repeated_value": []\n}', + json_format.MessageToJson(message, True, True)) + + # Parsers accept both original proto field names and lowerCamelCase names. + message = json_format_proto3_pb2.TestMessage() + json_format.Parse('{"int32Value": 54321}', message) + self.assertEqual(54321, message.int32_value) + json_format.Parse('{"int32_value": 12345}', message) + self.assertEqual(12345, message.int32_value) + + def testIndent(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + self.assertEqual('{\n"int32Value": 12345\n}', + json_format.MessageToJson(message, indent=0)) + + def testFormatEnumsAsInts(self): + message = json_format_proto3_pb2.TestMessage() + message.enum_value = json_format_proto3_pb2.BAR + message.repeated_enum_value.append(json_format_proto3_pb2.FOO) + message.repeated_enum_value.append(json_format_proto3_pb2.BAR) + self.assertEqual(json.loads('{\n' + ' "enumValue": 1,\n' + ' "repeatedEnumValue": [0, 1]\n' + '}\n'), + json.loads(json_format.MessageToJson( + message, use_integers_for_enums=True))) + + def testParseDict(self): + expected = 12345 + js_dict = {'int32Value': expected} + message = json_format_proto3_pb2.TestMessage() + json_format.ParseDict(js_dict, message) + self.assertEqual(expected, message.int32_value) + + def testMessageToDict(self): + message = json_format_proto3_pb2.TestMessage() + message.int32_value = 12345 + expected = {'int32Value': 12345} + self.assertEqual(expected, + json_format.MessageToDict(message)) + + def testJsonName(self): + message = json_format_proto3_pb2.TestCustomJsonName() + message.value = 12345 + self.assertEqual('{\n "@value": 12345\n}', + json_format.MessageToJson(message)) + parsed_message = json_format_proto3_pb2.TestCustomJsonName() + self.CheckParseBack(message, parsed_message) + + def testSortKeys(self): + # Testing sort_keys is not perfectly working, as by random luck we could + # get the output sorted. We just use a selection of names. + message = json_format_proto3_pb2.TestMessage(bool_value=True, + int32_value=1, + int64_value=3, + uint32_value=4, + string_value='bla') + self.assertEqual( + json_format.MessageToJson(message, sort_keys=True), + # We use json.dumps() instead of a hardcoded string due to differences + # between Python 2 and Python 3. + json.dumps({'boolValue': True, 'int32Value': 1, 'int64Value': '3', + 'uint32Value': 4, 'stringValue': 'bla'}, + indent=2, sort_keys=True)) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/message_factory_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/message_factory_test.py new file mode 100644 index 0000000..6df52ed --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/message_factory_test.py @@ -0,0 +1,222 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.message_factory.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import factory_test1_pb2 +from google.protobuf.internal import factory_test2_pb2 +from google.protobuf import descriptor_database +from google.protobuf import descriptor_pool +from google.protobuf import message_factory + + +class MessageFactoryTest(unittest.TestCase): + + def setUp(self): + self.factory_test1_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test1_pb2.DESCRIPTOR.serialized_pb) + self.factory_test2_fd = descriptor_pb2.FileDescriptorProto.FromString( + factory_test2_pb2.DESCRIPTOR.serialized_pb) + + def _ExerciseDynamicClass(self, cls): + msg = cls() + msg.mandatory = 42 + msg.nested_factory_2_enum = 0 + msg.nested_factory_2_message.value = 'nested message value' + msg.factory_1_message.factory_1_enum = 1 + msg.factory_1_message.nested_factory_1_enum = 0 + msg.factory_1_message.nested_factory_1_message.value = ( + 'nested message value') + msg.factory_1_message.scalar_value = 22 + msg.factory_1_message.list_value.extend([u'one', u'two', u'three']) + msg.factory_1_message.list_value.append(u'four') + msg.factory_1_enum = 1 + msg.nested_factory_1_enum = 0 + msg.nested_factory_1_message.value = 'nested message value' + msg.circular_message.mandatory = 1 + msg.circular_message.circular_message.mandatory = 2 + msg.circular_message.scalar_value = 'one deep' + msg.scalar_value = 'zero deep' + msg.list_value.extend([u'four', u'three', u'two']) + msg.list_value.append(u'one') + msg.grouped.add() + msg.grouped[0].part_1 = 'hello' + msg.grouped[0].part_2 = 'world' + msg.grouped.add(part_1='testing', part_2='123') + msg.loop.loop.mandatory = 2 + msg.loop.loop.loop.loop.mandatory = 4 + serialized = msg.SerializeToString() + converted = factory_test2_pb2.Factory2Message.FromString(serialized) + reserialized = converted.SerializeToString() + self.assertEqual(serialized, reserialized) + result = cls.FromString(reserialized) + self.assertEqual(msg, result) + + def testGetPrototype(self): + db = descriptor_database.DescriptorDatabase() + pool = descriptor_pool.DescriptorPool(db) + db.Add(self.factory_test1_fd) + db.Add(self.factory_test2_fd) + factory = message_factory.MessageFactory() + cls = factory.GetPrototype(pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message')) + self.assertFalse(cls is factory_test2_pb2.Factory2Message) + self._ExerciseDynamicClass(cls) + cls2 = factory.GetPrototype(pool.FindMessageTypeByName( + 'google.protobuf.python.internal.Factory2Message')) + self.assertTrue(cls is cls2) + + def testGetMessages(self): + # performed twice because multiple calls with the same input must be allowed + for _ in range(2): + # GetMessage should work regardless of the order the FileDescriptorProto + # are provided. In particular, the function should succeed when the files + # are not in the topological order of dependencies. + + # Assuming factory_test2_fd depends on factory_test1_fd. + self.assertIn(self.factory_test1_fd.name, + self.factory_test2_fd.dependency) + # Get messages should work when a file comes before its dependencies: + # factory_test2_fd comes before factory_test1_fd. + messages = message_factory.GetMessages([self.factory_test2_fd, + self.factory_test1_fd]) + self.assertTrue( + set(['google.protobuf.python.internal.Factory2Message', + 'google.protobuf.python.internal.Factory1Message'], + ).issubset(set(messages.keys()))) + self._ExerciseDynamicClass( + messages['google.protobuf.python.internal.Factory2Message']) + factory_msg1 = messages['google.protobuf.python.internal.Factory1Message'] + self.assertTrue(set( + ['google.protobuf.python.internal.Factory2Message.one_more_field', + 'google.protobuf.python.internal.another_field'],).issubset(set( + ext.full_name + for ext in factory_msg1.DESCRIPTOR.file.pool.FindAllExtensions( + factory_msg1.DESCRIPTOR)))) + msg1 = messages['google.protobuf.python.internal.Factory1Message']() + ext1 = msg1.Extensions._FindExtensionByName( + 'google.protobuf.python.internal.Factory2Message.one_more_field') + ext2 = msg1.Extensions._FindExtensionByName( + 'google.protobuf.python.internal.another_field') + msg1.Extensions[ext1] = 'test1' + msg1.Extensions[ext2] = 'test2' + self.assertEqual('test1', msg1.Extensions[ext1]) + self.assertEqual('test2', msg1.Extensions[ext2]) + self.assertEqual(None, + msg1.Extensions._FindExtensionByNumber(12321)) + if api_implementation.Type() == 'cpp': + # TODO(jieluo): Fix len to return the correct value. + # self.assertEqual(2, len(msg1.Extensions)) + self.assertEqual(len(msg1.Extensions), len(msg1.Extensions)) + self.assertRaises(TypeError, + msg1.Extensions._FindExtensionByName, 0) + self.assertRaises(TypeError, + msg1.Extensions._FindExtensionByNumber, '') + else: + self.assertEqual(None, + msg1.Extensions._FindExtensionByName(0)) + self.assertEqual(None, + msg1.Extensions._FindExtensionByNumber('')) + + def testDuplicateExtensionNumber(self): + pool = descriptor_pool.DescriptorPool() + factory = message_factory.MessageFactory(pool=pool) + + # Add Container message. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/container.proto' + f.package = 'google.protobuf.python.internal' + msg = f.message_type.add() + msg.name = 'Container' + rng = msg.extension_range.add() + rng.start = 1 + rng.end = 10 + pool.Add(f) + msgs = factory.GetMessages([f.name]) + self.assertIn('google.protobuf.python.internal.Container', msgs) + + # Extend container. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/extension.proto' + f.package = 'google.protobuf.python.internal' + f.dependency.append('google/protobuf/internal/container.proto') + msg = f.message_type.add() + msg.name = 'Extension' + ext = msg.extension.add() + ext.name = 'extension_field' + ext.number = 2 + ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + ext.type_name = 'Extension' + ext.extendee = 'Container' + pool.Add(f) + msgs = factory.GetMessages([f.name]) + self.assertIn('google.protobuf.python.internal.Extension', msgs) + + # Add Duplicate extending the same field number. + f = descriptor_pb2.FileDescriptorProto() + f.name = 'google/protobuf/internal/duplicate.proto' + f.package = 'google.protobuf.python.internal' + f.dependency.append('google/protobuf/internal/container.proto') + msg = f.message_type.add() + msg.name = 'Duplicate' + ext = msg.extension.add() + ext.name = 'extension_field' + ext.number = 2 + ext.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + ext.type_name = 'Duplicate' + ext.extendee = 'Container' + pool.Add(f) + + with self.assertRaises(Exception) as cm: + factory.GetMessages([f.name]) + + self.assertIn(str(cm.exception), + ['Extensions ' + '"google.protobuf.python.internal.Duplicate.extension_field" and' + ' "google.protobuf.python.internal.Extension.extension_field"' + ' both try to extend message type' + ' "google.protobuf.python.internal.Container"' + ' with field number 2.', + 'Double registration of Extensions']) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/message_listener.py b/winvenv/Lib/site-packages/google/protobuf/internal/message_listener.py new file mode 100644 index 0000000..0fc255a --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/message_listener.py @@ -0,0 +1,78 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Defines a listener interface for observing certain +state transitions on Message objects. + +Also defines a null implementation of this interface. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + + +class MessageListener(object): + + """Listens for modifications made to a message. Meant to be registered via + Message._SetListener(). + + Attributes: + dirty: If True, then calling Modified() would be a no-op. This can be + used to avoid these calls entirely in the common case. + """ + + def Modified(self): + """Called every time the message is modified in such a way that the parent + message may need to be updated. This currently means either: + (a) The message was modified for the first time, so the parent message + should henceforth mark the message as present. + (b) The message's cached byte size became dirty -- i.e. the message was + modified for the first time after a previous call to ByteSize(). + Therefore the parent should also mark its byte size as dirty. + Note that (a) implies (b), since new objects start out with a client cached + size (zero). However, we document (a) explicitly because it is important. + + Modified() will *only* be called in response to one of these two events -- + not every time the sub-message is modified. + + Note that if the listener's |dirty| attribute is true, then calling + Modified at the moment would be a no-op, so it can be skipped. Performance- + sensitive callers should check this attribute directly before calling since + it will be true most of the time. + """ + + raise NotImplementedError + + +class NullMessageListener(object): + + """No-op MessageListener implementation.""" + + def Modified(self): + pass diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/message_set_extensions_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/message_set_extensions_pb2.py new file mode 100644 index 0000000..ed992f6 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/message_set_extensions_pb2.py @@ -0,0 +1,209 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/message_set_extensions.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/message_set_extensions.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n5google/protobuf/internal/message_set_extensions.proto\x12\x18google.protobuf.internal\"\x1e\n\x0eTestMessageSet*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\"\xa5\x01\n\x18TestMessageSetExtension1\x12\t\n\x01i\x18\x0f \x01(\x05\x32~\n\x15message_set_extension\x12(.google.protobuf.internal.TestMessageSet\x18\xab\xff\xf6. \x01(\x0b\x32\x32.google.protobuf.internal.TestMessageSetExtension1\"\xa7\x01\n\x18TestMessageSetExtension2\x12\x0b\n\x03str\x18\x19 \x01(\t2~\n\x15message_set_extension\x12(.google.protobuf.internal.TestMessageSet\x18\xca\xff\xf6. \x01(\x0b\x32\x32.google.protobuf.internal.TestMessageSetExtension2\"(\n\x18TestMessageSetExtension3\x12\x0c\n\x04text\x18# \x01(\t:\x7f\n\x16message_set_extension3\x12(.google.protobuf.internal.TestMessageSet\x18\xdf\xff\xf6. \x01(\x0b\x32\x32.google.protobuf.internal.TestMessageSetExtension3') +) + + +MESSAGE_SET_EXTENSION3_FIELD_NUMBER = 98418655 +message_set_extension3 = _descriptor.FieldDescriptor( + name='message_set_extension3', full_name='google.protobuf.internal.message_set_extension3', index=0, + number=98418655, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTMESSAGESET = _descriptor.Descriptor( + name='TestMessageSet', + full_name='google.protobuf.internal.TestMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=83, + serialized_end=113, +) + + +_TESTMESSAGESETEXTENSION1 = _descriptor.Descriptor( + name='TestMessageSetExtension1', + full_name='google.protobuf.internal.TestMessageSetExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='google.protobuf.internal.TestMessageSetExtension1.i', index=0, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='google.protobuf.internal.TestMessageSetExtension1.message_set_extension', index=0, + number=98418603, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=116, + serialized_end=281, +) + + +_TESTMESSAGESETEXTENSION2 = _descriptor.Descriptor( + name='TestMessageSetExtension2', + full_name='google.protobuf.internal.TestMessageSetExtension2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='str', full_name='google.protobuf.internal.TestMessageSetExtension2.str', index=0, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='google.protobuf.internal.TestMessageSetExtension2.message_set_extension', index=0, + number=98418634, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=284, + serialized_end=451, +) + + +_TESTMESSAGESETEXTENSION3 = _descriptor.Descriptor( + name='TestMessageSetExtension3', + full_name='google.protobuf.internal.TestMessageSetExtension3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='text', full_name='google.protobuf.internal.TestMessageSetExtension3.text', index=0, + number=35, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=453, + serialized_end=493, +) + +DESCRIPTOR.message_types_by_name['TestMessageSet'] = _TESTMESSAGESET +DESCRIPTOR.message_types_by_name['TestMessageSetExtension1'] = _TESTMESSAGESETEXTENSION1 +DESCRIPTOR.message_types_by_name['TestMessageSetExtension2'] = _TESTMESSAGESETEXTENSION2 +DESCRIPTOR.message_types_by_name['TestMessageSetExtension3'] = _TESTMESSAGESETEXTENSION3 +DESCRIPTOR.extensions_by_name['message_set_extension3'] = message_set_extension3 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageSet = _reflection.GeneratedProtocolMessageType('TestMessageSet', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESET, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSet) + )) +_sym_db.RegisterMessage(TestMessageSet) + +TestMessageSetExtension1 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION1, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSetExtension1) + )) +_sym_db.RegisterMessage(TestMessageSetExtension1) + +TestMessageSetExtension2 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension2', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION2, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSetExtension2) + )) +_sym_db.RegisterMessage(TestMessageSetExtension2) + +TestMessageSetExtension3 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension3', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION3, + __module__ = 'google.protobuf.internal.message_set_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TestMessageSetExtension3) + )) +_sym_db.RegisterMessage(TestMessageSetExtension3) + +message_set_extension3.message_type = _TESTMESSAGESETEXTENSION3 +TestMessageSet.RegisterExtension(message_set_extension3) +_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION1 +TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension']) +_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION2 +TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension']) + +_TESTMESSAGESET._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/message_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/message_test.py new file mode 100644 index 0000000..61a56a6 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/message_test.py @@ -0,0 +1,2203 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests python protocol buffers against the golden message. + +Note that the golden messages exercise every known field type, thus this +test ends up exercising and verifying nearly all of the parsing and +serialization code in the whole library. + +TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of +sense to call this a test of the "message" module, which only declares an +abstract interface. +""" + +__author__ = 'gps@google.com (Gregory P. Smith)' + + +import collections +import copy +import math +import operator +import pickle +import six +import sys +import warnings + +try: + import unittest2 as unittest # PY26 +except ImportError: + import unittest +try: + cmp # Python 2 +except NameError: + cmp = lambda x, y: (x > y) - (x < y) # Python 3 + +from google.protobuf import map_proto2_unittest_pb2 +from google.protobuf import map_unittest_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf import descriptor_pool +from google.protobuf import message_factory +from google.protobuf import text_format +from google.protobuf.internal import api_implementation +from google.protobuf.internal import encoder +from google.protobuf.internal import packed_field_test_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks +from google.protobuf import message +from google.protobuf.internal import _parameterized + +if six.PY3: + long = int + + +# Python pre-2.6 does not have isinf() or isnan() functions, so we have +# to provide our own. +def isnan(val): + # NaN is never equal to itself. + return val != val +def isinf(val): + # Infinity times zero equals NaN. + return not isnan(val) and isnan(val * 0) +def IsPosInf(val): + return isinf(val) and (val > 0) +def IsNegInf(val): + return isinf(val) and (val < 0) + + +BaseTestCase = testing_refleaks.BaseTestCase + + +@_parameterized.named_parameters( + ('_proto2', unittest_pb2), + ('_proto3', unittest_proto3_arena_pb2)) +class MessageTest(BaseTestCase): + + def testBadUtf8String(self, message_module): + if api_implementation.Type() != 'python': + self.skipTest("Skipping testBadUtf8String, currently only the python " + "api implementation raises UnicodeDecodeError when a " + "string field contains bad utf-8.") + bad_utf8_data = test_util.GoldenFileData('bad_utf8_string') + with self.assertRaises(UnicodeDecodeError) as context: + message_module.TestAllTypes.FromString(bad_utf8_data) + self.assertIn('TestAllTypes.optional_string', str(context.exception)) + + def testGoldenMessage(self, message_module): + # Proto3 doesn't have the "default_foo" members or foreign enums, + # and doesn't preserve unknown fields, so for proto3 we use a golden + # message that doesn't have these fields set. + if message_module is unittest_pb2: + golden_data = test_util.GoldenFileData( + 'golden_message_oneof_implemented') + else: + golden_data = test_util.GoldenFileData('golden_message_proto3') + + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, golden_message) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testGoldenPackedMessage(self, message_module): + golden_data = test_util.GoldenFileData('golden_packed_fields_message') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + all_set = message_module.TestPackedTypes() + test_util.SetAllPackedFields(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testParseErrors(self, message_module): + msg = message_module.TestAllTypes() + self.assertRaises(TypeError, msg.FromString, 0) + self.assertRaises(Exception, msg.FromString, '0') + # TODO(jieluo): Fix cpp extension to raise error instead of warning. + # b/27494216 + end_tag = encoder.TagBytes(1, 4) + if api_implementation.Type() == 'python': + with self.assertRaises(message.DecodeError) as context: + msg.FromString(end_tag) + self.assertEqual('Unexpected end-group tag.', str(context.exception)) + else: + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter('always') + msg.FromString(end_tag) + assert len(w) == 1 + assert issubclass(w[-1].category, RuntimeWarning) + self.assertEqual('Unexpected end-group tag: Not all data was converted', + str(w[-1].message)) + + def testDeterminismParameters(self, message_module): + # This message is always deterministically serialized, even if determinism + # is disabled, so we can use it to verify that all the determinism + # parameters work correctly. + golden_data = (b'\xe2\x02\nOne string' + b'\xe2\x02\nTwo string' + b'\xe2\x02\nRed string' + b'\xe2\x02\x0bBlue string') + golden_message = message_module.TestAllTypes() + golden_message.repeated_string.extend([ + 'One string', + 'Two string', + 'Red string', + 'Blue string', + ]) + self.assertEqual(golden_data, + golden_message.SerializeToString(deterministic=None)) + self.assertEqual(golden_data, + golden_message.SerializeToString(deterministic=False)) + self.assertEqual(golden_data, + golden_message.SerializeToString(deterministic=True)) + + class BadArgError(Exception): + pass + + class BadArg(object): + + def __nonzero__(self): + raise BadArgError() + + def __bool__(self): + raise BadArgError() + + with self.assertRaises(BadArgError): + golden_message.SerializeToString(deterministic=BadArg()) + + def testPickleSupport(self, message_module): + golden_data = test_util.GoldenFileData('golden_message') + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + + def testPositiveInfinity(self, message_module): + if message_module is unittest_pb2: + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCD\x02\x00\x00\x80\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') + else: + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCA\x02\x04\x00\x00\x80\x7F' + b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') + + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsPosInf(golden_message.optional_float)) + self.assertTrue(IsPosInf(golden_message.optional_double)) + self.assertTrue(IsPosInf(golden_message.repeated_float[0])) + self.assertTrue(IsPosInf(golden_message.repeated_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNegativeInfinity(self, message_module): + if message_module is unittest_pb2: + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCD\x02\x00\x00\x80\xFF' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') + else: + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCA\x02\x04\x00\x00\x80\xFF' + b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') + + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsNegInf(golden_message.optional_float)) + self.assertTrue(IsNegInf(golden_message.optional_double)) + self.assertTrue(IsNegInf(golden_message.repeated_float[0])) + self.assertTrue(IsNegInf(golden_message.repeated_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNotANumber(self, message_module): + golden_data = (b'\x5D\x00\x00\xC0\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F' + b'\xCD\x02\x00\x00\xC0\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F') + golden_message = message_module.TestAllTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(isnan(golden_message.optional_float)) + self.assertTrue(isnan(golden_message.optional_double)) + self.assertTrue(isnan(golden_message.repeated_float[0])) + self.assertTrue(isnan(golden_message.repeated_double[0])) + + # The protocol buffer may serialize to any one of multiple different + # representations of a NaN. Rather than verify a specific representation, + # verify the serialized string can be converted into a correctly + # behaving protocol buffer. + serialized = golden_message.SerializeToString() + message = message_module.TestAllTypes() + message.ParseFromString(serialized) + self.assertTrue(isnan(message.optional_float)) + self.assertTrue(isnan(message.optional_double)) + self.assertTrue(isnan(message.repeated_float[0])) + self.assertTrue(isnan(message.repeated_double[0])) + + def testPositiveInfinityPacked(self, message_module): + golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsPosInf(golden_message.packed_float[0])) + self.assertTrue(IsPosInf(golden_message.packed_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNegativeInfinityPacked(self, message_module): + golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(IsNegInf(golden_message.packed_float[0])) + self.assertTrue(IsNegInf(golden_message.packed_double[0])) + self.assertEqual(golden_data, golden_message.SerializeToString()) + + def testNotANumberPacked(self, message_module): + golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F' + b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F') + golden_message = message_module.TestPackedTypes() + golden_message.ParseFromString(golden_data) + self.assertTrue(isnan(golden_message.packed_float[0])) + self.assertTrue(isnan(golden_message.packed_double[0])) + + serialized = golden_message.SerializeToString() + message = message_module.TestPackedTypes() + message.ParseFromString(serialized) + self.assertTrue(isnan(message.packed_float[0])) + self.assertTrue(isnan(message.packed_double[0])) + + def testExtremeFloatValues(self, message_module): + message = message_module.TestAllTypes() + + # Most positive exponent, no significand bits set. + kMostPosExponentNoSigBits = math.pow(2, 127) + message.optional_float = kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostPosExponentNoSigBits) + + # Most positive exponent, one significand bit set. + kMostPosExponentOneSigBit = 1.5 * math.pow(2, 127) + message.optional_float = kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostPosExponentOneSigBit) + + # Repeat last two cases with values of same magnitude, but negative. + message.optional_float = -kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostPosExponentNoSigBits) + + message.optional_float = -kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostPosExponentOneSigBit) + + # Most negative exponent, no significand bits set. + kMostNegExponentNoSigBits = math.pow(2, -127) + message.optional_float = kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostNegExponentNoSigBits) + + # Most negative exponent, one significand bit set. + kMostNegExponentOneSigBit = 1.5 * math.pow(2, -127) + message.optional_float = kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == kMostNegExponentOneSigBit) + + # Repeat last two cases with values of the same magnitude, but negative. + message.optional_float = -kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostNegExponentNoSigBits) + + message.optional_float = -kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) + + def testExtremeDoubleValues(self, message_module): + message = message_module.TestAllTypes() + + # Most positive exponent, no significand bits set. + kMostPosExponentNoSigBits = math.pow(2, 1023) + message.optional_double = kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostPosExponentNoSigBits) + + # Most positive exponent, one significand bit set. + kMostPosExponentOneSigBit = 1.5 * math.pow(2, 1023) + message.optional_double = kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostPosExponentOneSigBit) + + # Repeat last two cases with values of same magnitude, but negative. + message.optional_double = -kMostPosExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostPosExponentNoSigBits) + + message.optional_double = -kMostPosExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostPosExponentOneSigBit) + + # Most negative exponent, no significand bits set. + kMostNegExponentNoSigBits = math.pow(2, -1023) + message.optional_double = kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostNegExponentNoSigBits) + + # Most negative exponent, one significand bit set. + kMostNegExponentOneSigBit = 1.5 * math.pow(2, -1023) + message.optional_double = kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == kMostNegExponentOneSigBit) + + # Repeat last two cases with values of the same magnitude, but negative. + message.optional_double = -kMostNegExponentNoSigBits + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostNegExponentNoSigBits) + + message.optional_double = -kMostNegExponentOneSigBit + message.ParseFromString(message.SerializeToString()) + self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit) + + def testFloatPrinting(self, message_module): + message = message_module.TestAllTypes() + message.optional_float = 2.0 + self.assertEqual(str(message), 'optional_float: 2.0\n') + + def testHighPrecisionFloatPrinting(self, message_module): + message = message_module.TestAllTypes() + message.optional_double = 0.12345678912345678 + if sys.version_info >= (3,): + self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n') + else: + self.assertEqual(str(message), 'optional_double: 0.123456789123\n') + + def testUnknownFieldPrinting(self, message_module): + populated = message_module.TestAllTypes() + test_util.SetAllNonLazyFields(populated) + empty = message_module.TestEmptyMessage() + empty.ParseFromString(populated.SerializeToString()) + self.assertEqual(str(empty), '') + + def testRepeatedNestedFieldIteration(self, message_module): + msg = message_module.TestAllTypes() + msg.repeated_nested_message.add(bb=1) + msg.repeated_nested_message.add(bb=2) + msg.repeated_nested_message.add(bb=3) + msg.repeated_nested_message.add(bb=4) + + self.assertEqual([1, 2, 3, 4], + [m.bb for m in msg.repeated_nested_message]) + self.assertEqual([4, 3, 2, 1], + [m.bb for m in reversed(msg.repeated_nested_message)]) + self.assertEqual([4, 3, 2, 1], + [m.bb for m in msg.repeated_nested_message[::-1]]) + + def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module): + """Check some different types with the default comparator.""" + message = message_module.TestAllTypes() + + # TODO(mattp): would testing more scalar types strengthen test? + message.repeated_int32.append(1) + message.repeated_int32.append(3) + message.repeated_int32.append(2) + message.repeated_int32.sort() + self.assertEqual(message.repeated_int32[0], 1) + self.assertEqual(message.repeated_int32[1], 2) + self.assertEqual(message.repeated_int32[2], 3) + self.assertEqual(str(message.repeated_int32), str([1, 2, 3])) + + message.repeated_float.append(1.1) + message.repeated_float.append(1.3) + message.repeated_float.append(1.2) + message.repeated_float.sort() + self.assertAlmostEqual(message.repeated_float[0], 1.1) + self.assertAlmostEqual(message.repeated_float[1], 1.2) + self.assertAlmostEqual(message.repeated_float[2], 1.3) + + message.repeated_string.append('a') + message.repeated_string.append('c') + message.repeated_string.append('b') + message.repeated_string.sort() + self.assertEqual(message.repeated_string[0], 'a') + self.assertEqual(message.repeated_string[1], 'b') + self.assertEqual(message.repeated_string[2], 'c') + self.assertEqual(str(message.repeated_string), str([u'a', u'b', u'c'])) + + message.repeated_bytes.append(b'a') + message.repeated_bytes.append(b'c') + message.repeated_bytes.append(b'b') + message.repeated_bytes.sort() + self.assertEqual(message.repeated_bytes[0], b'a') + self.assertEqual(message.repeated_bytes[1], b'b') + self.assertEqual(message.repeated_bytes[2], b'c') + self.assertEqual(str(message.repeated_bytes), str([b'a', b'b', b'c'])) + + def testSortingRepeatedScalarFieldsCustomComparator(self, message_module): + """Check some different types with custom comparator.""" + message = message_module.TestAllTypes() + + message.repeated_int32.append(-3) + message.repeated_int32.append(-2) + message.repeated_int32.append(-1) + message.repeated_int32.sort(key=abs) + self.assertEqual(message.repeated_int32[0], -1) + self.assertEqual(message.repeated_int32[1], -2) + self.assertEqual(message.repeated_int32[2], -3) + + message.repeated_string.append('aaa') + message.repeated_string.append('bb') + message.repeated_string.append('c') + message.repeated_string.sort(key=len) + self.assertEqual(message.repeated_string[0], 'c') + self.assertEqual(message.repeated_string[1], 'bb') + self.assertEqual(message.repeated_string[2], 'aaa') + + def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module): + """Check passing a custom comparator to sort a repeated composite field.""" + message = message_module.TestAllTypes() + + message.repeated_nested_message.add().bb = 1 + message.repeated_nested_message.add().bb = 3 + message.repeated_nested_message.add().bb = 2 + message.repeated_nested_message.add().bb = 6 + message.repeated_nested_message.add().bb = 5 + message.repeated_nested_message.add().bb = 4 + message.repeated_nested_message.sort(key=operator.attrgetter('bb')) + self.assertEqual(message.repeated_nested_message[0].bb, 1) + self.assertEqual(message.repeated_nested_message[1].bb, 2) + self.assertEqual(message.repeated_nested_message[2].bb, 3) + self.assertEqual(message.repeated_nested_message[3].bb, 4) + self.assertEqual(message.repeated_nested_message[4].bb, 5) + self.assertEqual(message.repeated_nested_message[5].bb, 6) + self.assertEqual(str(message.repeated_nested_message), + '[bb: 1\n, bb: 2\n, bb: 3\n, bb: 4\n, bb: 5\n, bb: 6\n]') + + def testSortingRepeatedCompositeFieldsStable(self, message_module): + """Check passing a custom comparator to sort a repeated composite field.""" + message = message_module.TestAllTypes() + + message.repeated_nested_message.add().bb = 21 + message.repeated_nested_message.add().bb = 20 + message.repeated_nested_message.add().bb = 13 + message.repeated_nested_message.add().bb = 33 + message.repeated_nested_message.add().bb = 11 + message.repeated_nested_message.add().bb = 24 + message.repeated_nested_message.add().bb = 10 + message.repeated_nested_message.sort(key=lambda z: z.bb // 10) + self.assertEqual( + [13, 11, 10, 21, 20, 24, 33], + [n.bb for n in message.repeated_nested_message]) + + # Make sure that for the C++ implementation, the underlying fields + # are actually reordered. + pb = message.SerializeToString() + message.Clear() + message.MergeFromString(pb) + self.assertEqual( + [13, 11, 10, 21, 20, 24, 33], + [n.bb for n in message.repeated_nested_message]) + + def testRepeatedCompositeFieldSortArguments(self, message_module): + """Check sorting a repeated composite field using list.sort() arguments.""" + message = message_module.TestAllTypes() + + get_bb = operator.attrgetter('bb') + cmp_bb = lambda a, b: cmp(a.bb, b.bb) + message.repeated_nested_message.add().bb = 1 + message.repeated_nested_message.add().bb = 3 + message.repeated_nested_message.add().bb = 2 + message.repeated_nested_message.add().bb = 6 + message.repeated_nested_message.add().bb = 5 + message.repeated_nested_message.add().bb = 4 + message.repeated_nested_message.sort(key=get_bb) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [1, 2, 3, 4, 5, 6]) + message.repeated_nested_message.sort(key=get_bb, reverse=True) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [6, 5, 4, 3, 2, 1]) + if sys.version_info >= (3,): return # No cmp sorting in PY3. + message.repeated_nested_message.sort(sort_function=cmp_bb) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [1, 2, 3, 4, 5, 6]) + message.repeated_nested_message.sort(cmp=cmp_bb, reverse=True) + self.assertEqual([k.bb for k in message.repeated_nested_message], + [6, 5, 4, 3, 2, 1]) + + def testRepeatedScalarFieldSortArguments(self, message_module): + """Check sorting a scalar field using list.sort() arguments.""" + message = message_module.TestAllTypes() + + message.repeated_int32.append(-3) + message.repeated_int32.append(-2) + message.repeated_int32.append(-1) + message.repeated_int32.sort(key=abs) + self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) + message.repeated_int32.sort(key=abs, reverse=True) + self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) + if sys.version_info < (3,): # No cmp sorting in PY3. + abs_cmp = lambda a, b: cmp(abs(a), abs(b)) + message.repeated_int32.sort(sort_function=abs_cmp) + self.assertEqual(list(message.repeated_int32), [-1, -2, -3]) + message.repeated_int32.sort(cmp=abs_cmp, reverse=True) + self.assertEqual(list(message.repeated_int32), [-3, -2, -1]) + + message.repeated_string.append('aaa') + message.repeated_string.append('bb') + message.repeated_string.append('c') + message.repeated_string.sort(key=len) + self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) + message.repeated_string.sort(key=len, reverse=True) + self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) + if sys.version_info < (3,): # No cmp sorting in PY3. + len_cmp = lambda a, b: cmp(len(a), len(b)) + message.repeated_string.sort(sort_function=len_cmp) + self.assertEqual(list(message.repeated_string), ['c', 'bb', 'aaa']) + message.repeated_string.sort(cmp=len_cmp, reverse=True) + self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) + + def testRepeatedFieldsComparable(self, message_module): + m1 = message_module.TestAllTypes() + m2 = message_module.TestAllTypes() + m1.repeated_int32.append(0) + m1.repeated_int32.append(1) + m1.repeated_int32.append(2) + m2.repeated_int32.append(0) + m2.repeated_int32.append(1) + m2.repeated_int32.append(2) + m1.repeated_nested_message.add().bb = 1 + m1.repeated_nested_message.add().bb = 2 + m1.repeated_nested_message.add().bb = 3 + m2.repeated_nested_message.add().bb = 1 + m2.repeated_nested_message.add().bb = 2 + m2.repeated_nested_message.add().bb = 3 + + if sys.version_info >= (3,): return # No cmp() in PY3. + + # These comparisons should not raise errors. + _ = m1 < m2 + _ = m1.repeated_nested_message < m2.repeated_nested_message + + # Make sure cmp always works. If it wasn't defined, these would be + # id() comparisons and would all fail. + self.assertEqual(cmp(m1, m2), 0) + self.assertEqual(cmp(m1.repeated_int32, m2.repeated_int32), 0) + self.assertEqual(cmp(m1.repeated_int32, [0, 1, 2]), 0) + self.assertEqual(cmp(m1.repeated_nested_message, + m2.repeated_nested_message), 0) + with self.assertRaises(TypeError): + # Can't compare repeated composite containers to lists. + cmp(m1.repeated_nested_message, m2.repeated_nested_message[:]) + + # TODO(anuraag): Implement extensiondict comparison in C++ and then add test + + def testRepeatedFieldsAreSequences(self, message_module): + m = message_module.TestAllTypes() + self.assertIsInstance(m.repeated_int32, collections.MutableSequence) + self.assertIsInstance(m.repeated_nested_message, + collections.MutableSequence) + + def testRepeatedFieldsNotHashable(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(TypeError): + hash(m.repeated_int32) + with self.assertRaises(TypeError): + hash(m.repeated_nested_message) + + def testRepeatedFieldInsideNestedMessage(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.repeated_int32.extend([]) + self.assertTrue(m.HasField('payload')) + + def ensureNestedMessageExists(self, msg, attribute): + """Make sure that a nested message object exists. + + As soon as a nested message attribute is accessed, it will be present in the + _fields dict, without being marked as actually being set. + """ + getattr(msg, attribute) + self.assertFalse(msg.HasField(attribute)) + + def testOneofGetCaseNonexistingField(self, message_module): + m = message_module.TestAllTypes() + self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field') + self.assertRaises(Exception, m.WhichOneof, 0) + + def testOneofDefaultValues(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + + # Oneof is set even when setting it to a default value. + m.oneof_uint32 = 0 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + self.assertFalse(m.HasField('oneof_string')) + + m.oneof_string = "" + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_uint32')) + + def testOneofSemantics(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + + m.oneof_uint32 = 11 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + + m.oneof_string = u'foo' + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertTrue(m.HasField('oneof_string')) + + # Read nested message accessor without accessing submessage. + m.oneof_nested_message + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_nested_message')) + + # Read accessor of nested message without accessing submessage. + m.oneof_nested_message.bb + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_nested_message')) + + m.oneof_nested_message.bb = 11 + self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_string')) + self.assertTrue(m.HasField('oneof_nested_message')) + + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_nested_message')) + self.assertTrue(m.HasField('oneof_bytes')) + + def testOneofCompositeFieldReadAccess(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + + self.ensureNestedMessageExists(m, 'oneof_nested_message') + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertEqual(11, m.oneof_uint32) + + def testOneofWhichOneof(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + + m.oneof_uint32 = 11 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertTrue(m.HasField('oneof_field')) + + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + + m.ClearField('oneof_bytes') + self.assertIs(None, m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + + def testOneofClearField(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m.ClearField('oneof_field') + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertIs(None, m.WhichOneof('oneof_field')) + + def testOneofClearSetField(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m.ClearField('oneof_uint32') + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + self.assertIs(None, m.WhichOneof('oneof_field')) + + def testOneofClearUnsetField(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + self.ensureNestedMessageExists(m, 'oneof_nested_message') + m.ClearField('oneof_nested_message') + self.assertEqual(11, m.oneof_uint32) + if message_module is unittest_pb2: + self.assertTrue(m.HasField('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + + def testOneofDeserialize(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + m2.ParseFromString(m.SerializeToString()) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testOneofCopyFrom(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + m2.CopyFrom(m) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testOneofNestedMergeFrom(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.oneof_uint32 = 11 + m2 = message_module.NestedTestAllTypes() + m2.payload.oneof_bytes = b'bb' + m2.child.payload.oneof_bytes = b'bb' + m2.MergeFrom(m) + self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field')) + self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field')) + + def testOneofMessageMergeFrom(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.oneof_nested_message.bb = 11 + m.child.payload.oneof_nested_message.bb = 12 + m2 = message_module.NestedTestAllTypes() + m2.payload.oneof_uint32 = 13 + m2.MergeFrom(m) + self.assertEqual('oneof_nested_message', + m2.payload.WhichOneof('oneof_field')) + self.assertEqual('oneof_nested_message', + m2.child.payload.WhichOneof('oneof_field')) + + def testOneofNestedMessageInit(self, message_module): + m = message_module.TestAllTypes( + oneof_nested_message=message_module.TestAllTypes.NestedMessage()) + self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field')) + + def testOneofClear(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m.Clear() + self.assertIsNone(m.WhichOneof('oneof_field')) + m.oneof_bytes = b'bb' + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + + def testAssignByteStringToUnicodeField(self, message_module): + """Assigning a byte string to a string field should result + in the value being converted to a Unicode string.""" + m = message_module.TestAllTypes() + m.optional_string = str('') + self.assertIsInstance(m.optional_string, six.text_type) + + def testLongValuedSlice(self, message_module): + """It should be possible to use long-valued indicies in slices + + This didn't used to work in the v2 C++ implementation. + """ + m = message_module.TestAllTypes() + + # Repeated scalar + m.repeated_int32.append(1) + sl = m.repeated_int32[long(0):long(len(m.repeated_int32))] + self.assertEqual(len(m.repeated_int32), len(sl)) + + # Repeated composite + m.repeated_nested_message.add().bb = 3 + sl = m.repeated_nested_message[long(0):long(len(m.repeated_nested_message))] + self.assertEqual(len(m.repeated_nested_message), len(sl)) + + def testExtendShouldNotSwallowExceptions(self, message_module): + """This didn't use to work in the v2 C++ implementation.""" + m = message_module.TestAllTypes() + with self.assertRaises(NameError) as _: + m.repeated_int32.extend(a for i in range(10)) # pylint: disable=undefined-variable + with self.assertRaises(NameError) as _: + m.repeated_nested_enum.extend( + a for i in range(10)) # pylint: disable=undefined-variable + + FALSY_VALUES = [None, False, 0, 0.0, b'', u'', bytearray(), [], {}, set()] + + def testExtendInt32WithNothing(self, message_module): + """Test no-ops extending repeated int32 fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_int32.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_int32) + + m.repeated_int32.extend([]) + self.assertSequenceEqual([], m.repeated_int32) + + def testExtendFloatWithNothing(self, message_module): + """Test no-ops extending repeated float fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_float.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_float) + + m.repeated_float.extend([]) + self.assertSequenceEqual([], m.repeated_float) + + def testExtendStringWithNothing(self, message_module): + """Test no-ops extending repeated string fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_string.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_string) + + m.repeated_string.extend([]) + self.assertSequenceEqual([], m.repeated_string) + + def testExtendInt32WithPythonList(self, message_module): + """Test extending repeated int32 fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend([0]) + self.assertSequenceEqual([0], m.repeated_int32) + m.repeated_int32.extend([1, 2]) + self.assertSequenceEqual([0, 1, 2], m.repeated_int32) + m.repeated_int32.extend([3, 4]) + self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32) + + def testExtendFloatWithPythonList(self, message_module): + """Test extending repeated float fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend([0.0]) + self.assertSequenceEqual([0.0], m.repeated_float) + m.repeated_float.extend([1.0, 2.0]) + self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float) + m.repeated_float.extend([3.0, 4.0]) + self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float) + + def testExtendStringWithPythonList(self, message_module): + """Test extending repeated string fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(['']) + self.assertSequenceEqual([''], m.repeated_string) + m.repeated_string.extend(['11', '22']) + self.assertSequenceEqual(['', '11', '22'], m.repeated_string) + m.repeated_string.extend(['33', '44']) + self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string) + + def testExtendStringWithString(self, message_module): + """Test extending repeated string fields with characters from a string.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend('abc') + self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string) + + class TestIterable(object): + """This iterable object mimics the behavior of numpy.array. + + __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1. + + """ + + def __init__(self, values=None): + self._list = values or [] + + def __nonzero__(self): + size = len(self._list) + if size == 0: + return False + if size == 1: + return bool(self._list[0]) + raise ValueError('Truth value is ambiguous.') + + def __len__(self): + return len(self._list) + + def __iter__(self): + return self._list.__iter__() + + def testExtendInt32WithIterable(self, message_module): + """Test extending repeated int32 fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([0])) + self.assertSequenceEqual([0], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([1, 2])) + self.assertSequenceEqual([0, 1, 2], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([3, 4])) + self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32) + + def testExtendFloatWithIterable(self, message_module): + """Test extending repeated float fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([0.0])) + self.assertSequenceEqual([0.0], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0])) + self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0])) + self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float) + + def testExtendStringWithIterable(self, message_module): + """Test extending repeated string fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable([''])) + self.assertSequenceEqual([''], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable(['1', '2'])) + self.assertSequenceEqual(['', '1', '2'], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable(['3', '4'])) + self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string) + + def testPickleRepeatedScalarContainer(self, message_module): + # TODO(tibell): The pure-Python implementation support pickling of + # scalar containers in *some* cases. For now the cpp2 version + # throws an exception to avoid a segfault. Investigate if we + # want to support pickling of these fields. + # + # For more information see: https://b2.corp.google.com/u/0/issues/18677897 + if (api_implementation.Type() != 'cpp' or + api_implementation.Version() == 2): + return + m = message_module.TestAllTypes() + with self.assertRaises(pickle.PickleError) as _: + pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL) + + def testSortEmptyRepeatedCompositeContainer(self, message_module): + """Exercise a scenario that has led to segfaults in the past. + """ + m = message_module.TestAllTypes() + m.repeated_nested_message.sort() + + def testHasFieldOnRepeatedField(self, message_module): + """Using HasField on a repeated field should raise an exception. + """ + m = message_module.TestAllTypes() + with self.assertRaises(ValueError) as _: + m.HasField('repeated_int32') + + def testRepeatedScalarFieldPop(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(IndexError) as _: + m.repeated_int32.pop() + m.repeated_int32.extend(range(5)) + self.assertEqual(4, m.repeated_int32.pop()) + self.assertEqual(0, m.repeated_int32.pop(0)) + self.assertEqual(2, m.repeated_int32.pop(1)) + self.assertEqual([1, 3], m.repeated_int32) + + def testRepeatedCompositeFieldPop(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(IndexError) as _: + m.repeated_nested_message.pop() + with self.assertRaises(TypeError) as _: + m.repeated_nested_message.pop('0') + for i in range(5): + n = m.repeated_nested_message.add() + n.bb = i + self.assertEqual(4, m.repeated_nested_message.pop().bb) + self.assertEqual(0, m.repeated_nested_message.pop(0).bb) + self.assertEqual(2, m.repeated_nested_message.pop(1).bb) + self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message]) + + def testRepeatedCompareWithSelf(self, message_module): + m = message_module.TestAllTypes() + for i in range(5): + m.repeated_int32.insert(i, i) + n = m.repeated_nested_message.add() + n.bb = i + self.assertSequenceEqual(m.repeated_int32, m.repeated_int32) + self.assertEqual(m.repeated_nested_message, m.repeated_nested_message) + + def testReleasedNestedMessages(self, message_module): + """A case that lead to a segfault when a message detached from its parent + container has itself a child container. + """ + m = message_module.NestedTestAllTypes() + m = m.repeated_child.add() + m = m.child + m = m.repeated_child.add() + self.assertEqual(m.payload.optional_int32, 0) + + def testSetRepeatedComposite(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(AttributeError): + m.repeated_int32 = [] + m.repeated_int32.append(1) + if api_implementation.Type() == 'cpp': + # For test coverage: cpp has a different path if composite + # field is in cache + with self.assertRaises(TypeError): + m.repeated_int32 = [] + else: + with self.assertRaises(AttributeError): + m.repeated_int32 = [] + + +# Class to test proto2-only features (required, extensions, etc.) +class Proto2Test(BaseTestCase): + + def testFieldPresence(self): + message = unittest_pb2.TestAllTypes() + + self.assertFalse(message.HasField("optional_int32")) + self.assertFalse(message.HasField("optional_bool")) + self.assertFalse(message.HasField("optional_nested_message")) + + with self.assertRaises(ValueError): + message.HasField("field_doesnt_exist") + + with self.assertRaises(ValueError): + message.HasField("repeated_int32") + with self.assertRaises(ValueError): + message.HasField("repeated_nested_message") + + self.assertEqual(0, message.optional_int32) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # Fields are set even when setting the values to default values. + message.optional_int32 = 0 + message.optional_bool = False + message.optional_nested_message.bb = 0 + self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField("optional_bool")) + self.assertTrue(message.HasField("optional_nested_message")) + + # Set the fields to non-default values. + message.optional_int32 = 5 + message.optional_bool = True + message.optional_nested_message.bb = 15 + + self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField("optional_bool")) + self.assertTrue(message.HasField("optional_nested_message")) + + # Clearing the fields unsets them and resets their value to default. + message.ClearField("optional_int32") + message.ClearField("optional_bool") + message.ClearField("optional_nested_message") + + self.assertFalse(message.HasField("optional_int32")) + self.assertFalse(message.HasField("optional_bool")) + self.assertFalse(message.HasField("optional_nested_message")) + self.assertEqual(0, message.optional_int32) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + def testAssignInvalidEnum(self): + """Assigning an invalid enum number is not allowed in proto2.""" + m = unittest_pb2.TestAllTypes() + + # Proto2 can not assign unknown enum. + with self.assertRaises(ValueError) as _: + m.optional_nested_enum = 1234567 + self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum.append(2) + m.repeated_nested_enum[0] = 2 + with self.assertRaises(ValueError): + m.repeated_nested_enum[0] = 123456 + + # Unknown enum value can be parsed but is ignored. + m2 = unittest_proto3_arena_pb2.TestAllTypes() + m2.optional_nested_enum = 1234567 + m2.repeated_nested_enum.append(7654321) + serialized = m2.SerializeToString() + + m3 = unittest_pb2.TestAllTypes() + m3.ParseFromString(serialized) + self.assertFalse(m3.HasField('optional_nested_enum')) + # 1 is the default value for optional_nested_enum. + self.assertEqual(1, m3.optional_nested_enum) + self.assertEqual(0, len(m3.repeated_nested_enum)) + m2.Clear() + m2.ParseFromString(m3.SerializeToString()) + self.assertEqual(1234567, m2.optional_nested_enum) + self.assertEqual(7654321, m2.repeated_nested_enum[0]) + + def testUnknownEnumMap(self): + m = map_proto2_unittest_pb2.TestEnumMap() + m.known_map_field[123] = 0 + with self.assertRaises(ValueError): + m.unknown_map_field[1] = 123 + + def testExtensionsErrors(self): + msg = unittest_pb2.TestAllTypes() + self.assertRaises(AttributeError, getattr, msg, 'Extensions') + + def testGoldenExtensions(self): + golden_data = test_util.GoldenFileData('golden_message') + golden_message = unittest_pb2.TestAllExtensions() + golden_message.ParseFromString(golden_data) + all_set = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testGoldenPackedExtensions(self): + golden_data = test_util.GoldenFileData('golden_packed_fields_message') + golden_message = unittest_pb2.TestPackedExtensions() + golden_message.ParseFromString(golden_data) + all_set = unittest_pb2.TestPackedExtensions() + test_util.SetAllPackedExtensions(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testPickleIncompleteProto(self): + golden_message = unittest_pb2.TestRequired(a=1) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + self.assertEqual(unpickled_message.a, 1) + # This is still an incomplete proto - so serializing should fail + self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) + + + # TODO(haberman): this isn't really a proto2-specific test except that this + # message has a required field in it. Should probably be factored out so + # that we can test the other parts with proto3. + def testParsingMerge(self): + """Check the merge behavior when a required or optional field appears + multiple times in the input.""" + messages = [ + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes() ] + messages[0].optional_int32 = 1 + messages[1].optional_int64 = 2 + messages[2].optional_int32 = 3 + messages[2].optional_string = 'hello' + + merged_message = unittest_pb2.TestAllTypes() + merged_message.optional_int32 = 3 + merged_message.optional_int64 = 2 + merged_message.optional_string = 'hello' + + generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator() + generator.field1.extend(messages) + generator.field2.extend(messages) + generator.field3.extend(messages) + generator.ext1.extend(messages) + generator.ext2.extend(messages) + generator.group1.add().field1.MergeFrom(messages[0]) + generator.group1.add().field1.MergeFrom(messages[1]) + generator.group1.add().field1.MergeFrom(messages[2]) + generator.group2.add().field1.MergeFrom(messages[0]) + generator.group2.add().field1.MergeFrom(messages[1]) + generator.group2.add().field1.MergeFrom(messages[2]) + + data = generator.SerializeToString() + parsing_merge = unittest_pb2.TestParsingMerge() + parsing_merge.ParseFromString(data) + + # Required and optional fields should be merged. + self.assertEqual(parsing_merge.required_all_types, merged_message) + self.assertEqual(parsing_merge.optional_all_types, merged_message) + self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types, + merged_message) + self.assertEqual(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.optional_ext], + merged_message) + + # Repeated fields should not be merged. + self.assertEqual(len(parsing_merge.repeated_all_types), 3) + self.assertEqual(len(parsing_merge.repeatedgroup), 3) + self.assertEqual(len(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.repeated_ext]), 3) + + def testPythonicInit(self): + message = unittest_pb2.TestAllTypes( + optional_int32=100, + optional_fixed32=200, + optional_float=300.5, + optional_bytes=b'x', + optionalgroup={'a': 400}, + optional_nested_message={'bb': 500}, + optional_foreign_message={}, + optional_nested_enum='BAZ', + repeatedgroup=[{'a': 600}, + {'a': 700}], + repeated_nested_enum=['FOO', unittest_pb2.TestAllTypes.BAR], + default_int32=800, + oneof_string='y') + self.assertIsInstance(message, unittest_pb2.TestAllTypes) + self.assertEqual(100, message.optional_int32) + self.assertEqual(200, message.optional_fixed32) + self.assertEqual(300.5, message.optional_float) + self.assertEqual(b'x', message.optional_bytes) + self.assertEqual(400, message.optionalgroup.a) + self.assertIsInstance(message.optional_nested_message, + unittest_pb2.TestAllTypes.NestedMessage) + self.assertEqual(500, message.optional_nested_message.bb) + self.assertTrue(message.HasField('optional_foreign_message')) + self.assertEqual(message.optional_foreign_message, + unittest_pb2.ForeignMessage()) + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + self.assertEqual(2, len(message.repeatedgroup)) + self.assertEqual(600, message.repeatedgroup[0].a) + self.assertEqual(700, message.repeatedgroup[1].a) + self.assertEqual(2, len(message.repeated_nested_enum)) + self.assertEqual(unittest_pb2.TestAllTypes.FOO, + message.repeated_nested_enum[0]) + self.assertEqual(unittest_pb2.TestAllTypes.BAR, + message.repeated_nested_enum[1]) + self.assertEqual(800, message.default_int32) + self.assertEqual('y', message.oneof_string) + self.assertFalse(message.HasField('optional_int64')) + self.assertEqual(0, len(message.repeated_float)) + self.assertEqual(42, message.default_int64) + + message = unittest_pb2.TestAllTypes(optional_nested_enum=u'BAZ') + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes( + optional_nested_message={'INVALID_NESTED_FIELD': 17}) + + with self.assertRaises(TypeError): + unittest_pb2.TestAllTypes( + optional_nested_message={'bb': 'INVALID_VALUE_TYPE'}) + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes(optional_nested_enum='INVALID_LABEL') + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes(repeated_nested_enum='FOO') + + + +# Class to test proto3-only features/behavior (updated field presence & enums) +class Proto3Test(BaseTestCase): + + # Utility method for comparing equality with a map. + def assertMapIterEquals(self, map_iter, dict_value): + # Avoid mutating caller's copy. + dict_value = dict(dict_value) + + for k, v in map_iter: + self.assertEqual(v, dict_value[k]) + del dict_value[k] + + self.assertEqual({}, dict_value) + + def testFieldPresence(self): + message = unittest_proto3_arena_pb2.TestAllTypes() + + # We can't test presence of non-repeated, non-submessage fields. + with self.assertRaises(ValueError): + message.HasField('optional_int32') + with self.assertRaises(ValueError): + message.HasField('optional_float') + with self.assertRaises(ValueError): + message.HasField('optional_string') + with self.assertRaises(ValueError): + message.HasField('optional_bool') + + # But we can still test presence of submessage fields. + self.assertFalse(message.HasField('optional_nested_message')) + + # As with proto2, we can't test presence of fields that don't exist, or + # repeated fields. + with self.assertRaises(ValueError): + message.HasField('field_doesnt_exist') + + with self.assertRaises(ValueError): + message.HasField('repeated_int32') + with self.assertRaises(ValueError): + message.HasField('repeated_nested_message') + + # Fields should default to their type-specific default. + self.assertEqual(0, message.optional_int32) + self.assertEqual(0, message.optional_float) + self.assertEqual('', message.optional_string) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # Setting a submessage should still return proper presence information. + message.optional_nested_message.bb = 0 + self.assertTrue(message.HasField('optional_nested_message')) + + # Set the fields to non-default values. + message.optional_int32 = 5 + message.optional_float = 1.1 + message.optional_string = 'abc' + message.optional_bool = True + message.optional_nested_message.bb = 15 + + # Clearing the fields unsets them and resets their value to default. + message.ClearField('optional_int32') + message.ClearField('optional_float') + message.ClearField('optional_string') + message.ClearField('optional_bool') + message.ClearField('optional_nested_message') + + self.assertEqual(0, message.optional_int32) + self.assertEqual(0, message.optional_float) + self.assertEqual('', message.optional_string) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + def testAssignUnknownEnum(self): + """Assigning an unknown enum value is allowed and preserves the value.""" + m = unittest_proto3_arena_pb2.TestAllTypes() + + # Proto3 can assign unknown enums. + m.optional_nested_enum = 1234567 + self.assertEqual(1234567, m.optional_nested_enum) + m.repeated_nested_enum.append(22334455) + self.assertEqual(22334455, m.repeated_nested_enum[0]) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum[0] = 7654321 + self.assertEqual(7654321, m.repeated_nested_enum[0]) + serialized = m.SerializeToString() + + m2 = unittest_proto3_arena_pb2.TestAllTypes() + m2.ParseFromString(serialized) + self.assertEqual(1234567, m2.optional_nested_enum) + self.assertEqual(7654321, m2.repeated_nested_enum[0]) + + # Map isn't really a proto3-only feature. But there is no proto2 equivalent + # of google/protobuf/map_unittest.proto right now, so it's not easy to + # test both with the same test like we do for the other proto2/proto3 tests. + # (google/protobuf/map_proto2_unittest.proto is very different in the set + # of messages and fields it contains). + def testScalarMapDefaults(self): + msg = map_unittest_pb2.TestMap() + + # Scalars start out unset. + self.assertFalse(-123 in msg.map_int32_int32) + self.assertFalse(-2**33 in msg.map_int64_int64) + self.assertFalse(123 in msg.map_uint32_uint32) + self.assertFalse(2**33 in msg.map_uint64_uint64) + self.assertFalse(123 in msg.map_int32_double) + self.assertFalse(False in msg.map_bool_bool) + self.assertFalse('abc' in msg.map_string_string) + self.assertFalse(111 in msg.map_int32_bytes) + self.assertFalse(888 in msg.map_int32_enum) + + # Accessing an unset key returns the default. + self.assertEqual(0, msg.map_int32_int32[-123]) + self.assertEqual(0, msg.map_int64_int64[-2**33]) + self.assertEqual(0, msg.map_uint32_uint32[123]) + self.assertEqual(0, msg.map_uint64_uint64[2**33]) + self.assertEqual(0.0, msg.map_int32_double[123]) + self.assertTrue(isinstance(msg.map_int32_double[123], float)) + self.assertEqual(False, msg.map_bool_bool[False]) + self.assertTrue(isinstance(msg.map_bool_bool[False], bool)) + self.assertEqual('', msg.map_string_string['abc']) + self.assertEqual(b'', msg.map_int32_bytes[111]) + self.assertEqual(0, msg.map_int32_enum[888]) + + # It also sets the value in the map + self.assertTrue(-123 in msg.map_int32_int32) + self.assertTrue(-2**33 in msg.map_int64_int64) + self.assertTrue(123 in msg.map_uint32_uint32) + self.assertTrue(2**33 in msg.map_uint64_uint64) + self.assertTrue(123 in msg.map_int32_double) + self.assertTrue(False in msg.map_bool_bool) + self.assertTrue('abc' in msg.map_string_string) + self.assertTrue(111 in msg.map_int32_bytes) + self.assertTrue(888 in msg.map_int32_enum) + + self.assertIsInstance(msg.map_string_string['abc'], six.text_type) + + # Accessing an unset key still throws TypeError if the type of the key + # is incorrect. + with self.assertRaises(TypeError): + msg.map_string_string[123] + + with self.assertRaises(TypeError): + 123 in msg.map_string_string + + def testMapGet(self): + # Need to test that get() properly returns the default, even though the dict + # has defaultdict-like semantics. + msg = map_unittest_pb2.TestMap() + + self.assertIsNone(msg.map_int32_int32.get(5)) + self.assertEqual(10, msg.map_int32_int32.get(5, 10)) + self.assertIsNone(msg.map_int32_int32.get(5)) + + msg.map_int32_int32[5] = 15 + self.assertEqual(15, msg.map_int32_int32.get(5)) + self.assertEqual(15, msg.map_int32_int32.get(5)) + with self.assertRaises(TypeError): + msg.map_int32_int32.get('') + + self.assertIsNone(msg.map_int32_foreign_message.get(5)) + self.assertEqual(10, msg.map_int32_foreign_message.get(5, 10)) + + submsg = msg.map_int32_foreign_message[5] + self.assertIs(submsg, msg.map_int32_foreign_message.get(5)) + with self.assertRaises(TypeError): + msg.map_int32_foreign_message.get('') + + def testScalarMap(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_int32)) + self.assertFalse(5 in msg.map_int32_int32) + + msg.map_int32_int32[-123] = -456 + msg.map_int64_int64[-2**33] = -2**34 + msg.map_uint32_uint32[123] = 456 + msg.map_uint64_uint64[2**33] = 2**34 + msg.map_int32_float[2] = 1.2 + msg.map_int32_double[1] = 3.3 + msg.map_string_string['abc'] = '123' + msg.map_bool_bool[True] = True + msg.map_int32_enum[888] = 2 + # Unknown numeric enum is supported in proto3. + msg.map_int32_enum[123] = 456 + + self.assertEqual([], msg.FindInitializationErrors()) + + self.assertEqual(1, len(msg.map_string_string)) + + # Bad key. + with self.assertRaises(TypeError): + msg.map_string_string[123] = '123' + + # Verify that trying to assign a bad key doesn't actually add a member to + # the map. + self.assertEqual(1, len(msg.map_string_string)) + + # Bad value. + with self.assertRaises(TypeError): + msg.map_string_string['123'] = 123 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + # Bad key. + with self.assertRaises(TypeError): + msg2.map_string_string[123] = '123' + + # Bad value. + with self.assertRaises(TypeError): + msg2.map_string_string['123'] = 123 + + self.assertEqual(-456, msg2.map_int32_int32[-123]) + self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) + self.assertEqual(456, msg2.map_uint32_uint32[123]) + self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + self.assertAlmostEqual(1.2, msg.map_int32_float[2]) + self.assertEqual(3.3, msg.map_int32_double[1]) + self.assertEqual('123', msg2.map_string_string['abc']) + self.assertEqual(True, msg2.map_bool_bool[True]) + self.assertEqual(2, msg2.map_int32_enum[888]) + self.assertEqual(456, msg2.map_int32_enum[123]) + # TODO(jieluo): Add cpp extension support. + if api_implementation.Type() == 'python': + self.assertEqual('{-123: -456}', + str(msg2.map_int32_int32)) + + def testMapEntryAlwaysSerialized(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[0] = 0 + msg.map_string_string[''] = '' + self.assertEqual(msg.ByteSize(), 12) + self.assertEqual(b'\n\x04\x08\x00\x10\x00r\x04\n\x00\x12\x00', + msg.SerializeToString()) + + def testStringUnicodeConversionInMap(self): + msg = map_unittest_pb2.TestMap() + + unicode_obj = u'\u1234' + bytes_obj = unicode_obj.encode('utf8') + + msg.map_string_string[bytes_obj] = bytes_obj + + (key, value) = list(msg.map_string_string.items())[0] + + self.assertEqual(key, unicode_obj) + self.assertEqual(value, unicode_obj) + + self.assertIsInstance(key, six.text_type) + self.assertIsInstance(value, six.text_type) + + def testMessageMap(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_foreign_message)) + self.assertFalse(5 in msg.map_int32_foreign_message) + + msg.map_int32_foreign_message[123] + # get_or_create() is an alias for getitem. + msg.map_int32_foreign_message.get_or_create(-456) + + self.assertEqual(2, len(msg.map_int32_foreign_message)) + self.assertIn(123, msg.map_int32_foreign_message) + self.assertIn(-456, msg.map_int32_foreign_message) + self.assertEqual(2, len(msg.map_int32_foreign_message)) + + # Bad key. + with self.assertRaises(TypeError): + msg.map_int32_foreign_message['123'] + + # Can't assign directly to submessage. + with self.assertRaises(ValueError): + msg.map_int32_foreign_message[999] = msg.map_int32_foreign_message[123] + + # Verify that trying to assign a bad key doesn't actually add a member to + # the map. + self.assertEqual(2, len(msg.map_int32_foreign_message)) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(2, len(msg2.map_int32_foreign_message)) + self.assertIn(123, msg2.map_int32_foreign_message) + self.assertIn(-456, msg2.map_int32_foreign_message) + self.assertEqual(2, len(msg2.map_int32_foreign_message)) + # TODO(jieluo): Fix text format for message map. + # TODO(jieluo): Add cpp extension support. + if api_implementation.Type() == 'python': + self.assertEqual(15, + len(str(msg2.map_int32_foreign_message))) + + def testNestedMessageMapItemDelete(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_all_types[1].optional_nested_message.bb = 1 + del msg.map_int32_all_types[1] + msg.map_int32_all_types[2].optional_nested_message.bb = 2 + self.assertEqual(1, len(msg.map_int32_all_types)) + msg.map_int32_all_types[1].optional_nested_message.bb = 1 + self.assertEqual(2, len(msg.map_int32_all_types)) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + keys = [1, 2] + # The loop triggers PyErr_Occurred() in c extension. + for key in keys: + del msg2.map_int32_all_types[key] + + def testMapByteSize(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[1] = 1 + size = msg.ByteSize() + msg.map_int32_int32[1] = 128 + self.assertEqual(msg.ByteSize(), size + 1) + + msg.map_int32_foreign_message[19].c = 1 + size = msg.ByteSize() + msg.map_int32_foreign_message[19].c = 128 + self.assertEqual(msg.ByteSize(), size + 1) + + def testMergeFrom(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[12] = 34 + msg.map_int32_int32[56] = 78 + msg.map_int64_int64[22] = 33 + msg.map_int32_foreign_message[111].c = 5 + msg.map_int32_foreign_message[222].c = 10 + + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_int32[12] = 55 + msg2.map_int64_int64[88] = 99 + msg2.map_int32_foreign_message[222].c = 15 + msg2.map_int32_foreign_message[222].d = 20 + old_map_value = msg2.map_int32_foreign_message[222] + + msg2.MergeFrom(msg) + + self.assertEqual(34, msg2.map_int32_int32[12]) + self.assertEqual(78, msg2.map_int32_int32[56]) + self.assertEqual(33, msg2.map_int64_int64[22]) + self.assertEqual(99, msg2.map_int64_int64[88]) + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + self.assertEqual(10, msg2.map_int32_foreign_message[222].c) + self.assertFalse(msg2.map_int32_foreign_message[222].HasField('d')) + if api_implementation.Type() != 'cpp': + # During the call to MergeFrom(), the C++ implementation will have + # deallocated the underlying message, but this is very difficult to detect + # properly. The line below is likely to cause a segmentation fault. + # With the Python implementation, old_map_value is just 'detached' from + # the main message. Using it will not crash of course, but since it still + # have a reference to the parent message I'm sure we can find interesting + # ways to cause inconsistencies. + self.assertEqual(15, old_map_value.c) + + # Verify that there is only one entry per key, even though the MergeFrom + # may have internally created multiple entries for a single key in the + # list representation. + as_dict = {} + for key in msg2.map_int32_foreign_message: + self.assertFalse(key in as_dict) + as_dict[key] = msg2.map_int32_foreign_message[key].c + + self.assertEqual({111: 5, 222: 10}, as_dict) + + # Special case: test that delete of item really removes the item, even if + # there might have physically been duplicate keys due to the previous merge. + # This is only a special case for the C++ implementation which stores the + # map as an array. + del msg2.map_int32_int32[12] + self.assertFalse(12 in msg2.map_int32_int32) + + del msg2.map_int32_foreign_message[222] + self.assertFalse(222 in msg2.map_int32_foreign_message) + with self.assertRaises(TypeError): + del msg2.map_int32_foreign_message[''] + + def testMapMergeFrom(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[12] = 34 + msg.map_int32_int32[56] = 78 + msg.map_int64_int64[22] = 33 + msg.map_int32_foreign_message[111].c = 5 + msg.map_int32_foreign_message[222].c = 10 + + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_int32[12] = 55 + msg2.map_int64_int64[88] = 99 + msg2.map_int32_foreign_message[222].c = 15 + msg2.map_int32_foreign_message[222].d = 20 + + msg2.map_int32_int32.MergeFrom(msg.map_int32_int32) + self.assertEqual(34, msg2.map_int32_int32[12]) + self.assertEqual(78, msg2.map_int32_int32[56]) + + msg2.map_int64_int64.MergeFrom(msg.map_int64_int64) + self.assertEqual(33, msg2.map_int64_int64[22]) + self.assertEqual(99, msg2.map_int64_int64[88]) + + msg2.map_int32_foreign_message.MergeFrom(msg.map_int32_foreign_message) + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + self.assertEqual(10, msg2.map_int32_foreign_message[222].c) + self.assertFalse(msg2.map_int32_foreign_message[222].HasField('d')) + + def testMergeFromBadType(self): + msg = map_unittest_pb2.TestMap() + with self.assertRaisesRegexp( + TypeError, + r'Parameter to MergeFrom\(\) must be instance of same class: expected ' + r'.*TestMap got int\.'): + msg.MergeFrom(1) + + def testCopyFromBadType(self): + msg = map_unittest_pb2.TestMap() + with self.assertRaisesRegexp( + TypeError, + r'Parameter to [A-Za-z]*From\(\) must be instance of same class: ' + r'expected .*TestMap got int\.'): + msg.CopyFrom(1) + + def testIntegerMapWithLongs(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[long(-123)] = long(-456) + msg.map_int64_int64[long(-2**33)] = long(-2**34) + msg.map_uint32_uint32[long(123)] = long(456) + msg.map_uint64_uint64[long(2**33)] = long(2**34) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(-456, msg2.map_int32_int32[-123]) + self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) + self.assertEqual(456, msg2.map_uint32_uint32[123]) + self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + + def testMapAssignmentCausesPresence(self): + msg = map_unittest_pb2.TestMapSubmessage() + msg.test_map.map_int32_int32[123] = 456 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMapSubmessage() + msg2.ParseFromString(serialized) + + self.assertEqual(msg, msg2) + + # Now test that various mutations of the map properly invalidate the + # cached size of the submessage. + msg.test_map.map_int32_int32[888] = 999 + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_int32.clear() + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + def testMapAssignmentCausesPresenceForSubmessages(self): + msg = map_unittest_pb2.TestMapSubmessage() + msg.test_map.map_int32_foreign_message[123].c = 5 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMapSubmessage() + msg2.ParseFromString(serialized) + + self.assertEqual(msg, msg2) + + # Now test that various mutations of the map properly invalidate the + # cached size of the submessage. + msg.test_map.map_int32_foreign_message[888].c = 7 + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_foreign_message[888].MergeFrom( + msg.test_map.map_int32_foreign_message[123]) + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_foreign_message.clear() + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + def testModifyMapWhileIterating(self): + msg = map_unittest_pb2.TestMap() + + string_string_iter = iter(msg.map_string_string) + int32_foreign_iter = iter(msg.map_int32_foreign_message) + + msg.map_string_string['abc'] = '123' + msg.map_int32_foreign_message[5].c = 5 + + with self.assertRaises(RuntimeError): + for key in string_string_iter: + pass + + with self.assertRaises(RuntimeError): + for key in int32_foreign_iter: + pass + + def testSubmessageMap(self): + msg = map_unittest_pb2.TestMap() + + submsg = msg.map_int32_foreign_message[111] + self.assertIs(submsg, msg.map_int32_foreign_message[111]) + self.assertIsInstance(submsg, unittest_pb2.ForeignMessage) + + submsg.c = 5 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + + # Doesn't allow direct submessage assignment. + with self.assertRaises(ValueError): + msg.map_int32_foreign_message[88] = unittest_pb2.ForeignMessage() + + def testMapIteration(self): + msg = map_unittest_pb2.TestMap() + + for k, v in msg.map_int32_int32.items(): + # Should not be reached. + self.assertTrue(False) + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + self.assertEqual(3, len(msg.map_int32_int32)) + + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(msg.map_int32_int32.items(), matching_dict) + + def testPython2Map(self): + if sys.version_info < (3,): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + msg.map_int32_int32[5] = 10 + map_int32 = msg.map_int32_int32 + self.assertEqual(4, len(map_int32)) + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(msg.SerializeToString()) + + def CheckItems(seq, iterator): + self.assertEqual(next(iterator), seq[0]) + self.assertEqual(list(iterator), seq[1:]) + + CheckItems(map_int32.items(), map_int32.iteritems()) + CheckItems(map_int32.keys(), map_int32.iterkeys()) + CheckItems(map_int32.values(), map_int32.itervalues()) + + self.assertEqual(6, map_int32.get(3)) + self.assertEqual(None, map_int32.get(999)) + self.assertEqual(6, map_int32.pop(3)) + self.assertEqual(0, map_int32.pop(3)) + self.assertEqual(3, len(map_int32)) + key, value = map_int32.popitem() + self.assertEqual(2 * key, value) + self.assertEqual(2, len(map_int32)) + map_int32.clear() + self.assertEqual(0, len(map_int32)) + + with self.assertRaises(KeyError): + map_int32.popitem() + + self.assertEqual(0, map_int32.setdefault(2)) + self.assertEqual(1, len(map_int32)) + + map_int32.update(msg2.map_int32_int32) + self.assertEqual(4, len(map_int32)) + + with self.assertRaises(TypeError): + map_int32.update(msg2.map_int32_int32, + msg2.map_int32_int32) + with self.assertRaises(TypeError): + map_int32.update(0) + with self.assertRaises(TypeError): + map_int32.update(value=12) + + def testMapItems(self): + # Map items used to have strange behaviors when use c extension. Because + # [] may reorder the map and invalidate any exsting iterators. + # TODO(jieluo): Check if [] reordering the map is a bug or intended + # behavior. + msg = map_unittest_pb2.TestMap() + msg.map_string_string['local_init_op'] = '' + msg.map_string_string['trainable_variables'] = '' + msg.map_string_string['variables'] = '' + msg.map_string_string['init_op'] = '' + msg.map_string_string['summaries'] = '' + items1 = msg.map_string_string.items() + items2 = msg.map_string_string.items() + self.assertEqual(items1, items2) + + def testMapDeterministicSerialization(self): + golden_data = (b'r\x0c\n\x07init_op\x12\x01d' + b'r\n\n\x05item1\x12\x01e' + b'r\n\n\x05item2\x12\x01f' + b'r\n\n\x05item3\x12\x01g' + b'r\x0b\n\x05item4\x12\x02QQ' + b'r\x12\n\rlocal_init_op\x12\x01a' + b'r\x0e\n\tsummaries\x12\x01e' + b'r\x18\n\x13trainable_variables\x12\x01b' + b'r\x0e\n\tvariables\x12\x01c') + msg = map_unittest_pb2.TestMap() + msg.map_string_string['local_init_op'] = 'a' + msg.map_string_string['trainable_variables'] = 'b' + msg.map_string_string['variables'] = 'c' + msg.map_string_string['init_op'] = 'd' + msg.map_string_string['summaries'] = 'e' + msg.map_string_string['item1'] = 'e' + msg.map_string_string['item2'] = 'f' + msg.map_string_string['item3'] = 'g' + msg.map_string_string['item4'] = 'QQ' + + # If deterministic serialization is not working correctly, this will be + # "flaky" depending on the exact python dict hash seed. + # + # Fortunately, there are enough items in this map that it is extremely + # unlikely to ever hit the "right" in-order combination, so the test + # itself should fail reliably. + self.assertEqual(golden_data, msg.SerializeToString(deterministic=True)) + + def testMapIterationClearMessage(self): + # Iterator needs to work even if message and map are deleted. + msg = map_unittest_pb2.TestMap() + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + + it = msg.map_int32_int32.items() + del msg + + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(it, matching_dict) + + def testMapConstruction(self): + msg = map_unittest_pb2.TestMap(map_int32_int32={1: 2, 3: 4}) + self.assertEqual(2, msg.map_int32_int32[1]) + self.assertEqual(4, msg.map_int32_int32[3]) + + msg = map_unittest_pb2.TestMap( + map_int32_foreign_message={3: unittest_pb2.ForeignMessage(c=5)}) + self.assertEqual(5, msg.map_int32_foreign_message[3].c) + + def testMapValidAfterFieldCleared(self): + # Map needs to work even if field is cleared. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + int32_map = msg.map_int32_int32 + + int32_map[2] = 4 + int32_map[3] = 6 + int32_map[4] = 8 + + msg.ClearField('map_int32_int32') + self.assertEqual(b'', msg.SerializeToString()) + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(int32_map.items(), matching_dict) + + def testMessageMapValidAfterFieldCleared(self): + # Map needs to work even if field is cleared. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + int32_foreign_message = msg.map_int32_foreign_message + + int32_foreign_message[2].c = 5 + + msg.ClearField('map_int32_foreign_message') + self.assertEqual(b'', msg.SerializeToString()) + self.assertTrue(2 in int32_foreign_message.keys()) + + def testMapIterInvalidatedByClearField(self): + # Map iterator is invalidated when field is cleared. + # But this case does need to not crash the interpreter. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + + it = iter(msg.map_int32_int32) + + msg.ClearField('map_int32_int32') + with self.assertRaises(RuntimeError): + for _ in it: + pass + + it = iter(msg.map_int32_foreign_message) + msg.ClearField('map_int32_foreign_message') + with self.assertRaises(RuntimeError): + for _ in it: + pass + + def testMapDelete(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_int32)) + + msg.map_int32_int32[4] = 6 + self.assertEqual(1, len(msg.map_int32_int32)) + + with self.assertRaises(KeyError): + del msg.map_int32_int32[88] + + del msg.map_int32_int32[4] + self.assertEqual(0, len(msg.map_int32_int32)) + + with self.assertRaises(KeyError): + del msg.map_int32_all_types[32] + + def testMapsAreMapping(self): + msg = map_unittest_pb2.TestMap() + self.assertIsInstance(msg.map_int32_int32, collections.Mapping) + self.assertIsInstance(msg.map_int32_int32, collections.MutableMapping) + self.assertIsInstance(msg.map_int32_foreign_message, collections.Mapping) + self.assertIsInstance(msg.map_int32_foreign_message, + collections.MutableMapping) + + def testMapsCompare(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[-123] = -456 + self.assertEqual(msg.map_int32_int32, msg.map_int32_int32) + self.assertEqual(msg.map_int32_foreign_message, + msg.map_int32_foreign_message) + self.assertNotEqual(msg.map_int32_int32, 0) + + def testMapFindInitializationErrorsSmokeTest(self): + msg = map_unittest_pb2.TestMap() + msg.map_string_string['abc'] = '123' + msg.map_int32_int32[35] = 64 + msg.map_string_foreign_message['foo'].c = 5 + self.assertEqual(0, len(msg.FindInitializationErrors())) + + + +class ValidTypeNamesTest(BaseTestCase): + + def assertImportFromName(self, msg, base_name): + # Parse to extra 'some.name' as a string. + tp_name = str(type(msg)).split("'")[1] + valid_names = ('Repeated%sContainer' % base_name, + 'Repeated%sFieldContainer' % base_name) + self.assertTrue(any(tp_name.endswith(v) for v in valid_names), + '%r does end with any of %r' % (tp_name, valid_names)) + + parts = tp_name.split('.') + class_name = parts[-1] + module_name = '.'.join(parts[:-1]) + __import__(module_name, fromlist=[class_name]) + + def testTypeNamesCanBeImported(self): + # If import doesn't work, pickling won't work either. + pb = unittest_pb2.TestAllTypes() + self.assertImportFromName(pb.repeated_int32, 'Scalar') + self.assertImportFromName(pb.repeated_nested_message, 'Composite') + +class PackedFieldTest(BaseTestCase): + + def setMessage(self, message): + message.repeated_int32.append(1) + message.repeated_int64.append(1) + message.repeated_uint32.append(1) + message.repeated_uint64.append(1) + message.repeated_sint32.append(1) + message.repeated_sint64.append(1) + message.repeated_fixed32.append(1) + message.repeated_fixed64.append(1) + message.repeated_sfixed32.append(1) + message.repeated_sfixed64.append(1) + message.repeated_float.append(1.0) + message.repeated_double.append(1.0) + message.repeated_bool.append(True) + message.repeated_nested_enum.append(1) + + def testPackedFields(self): + message = packed_field_test_pb2.TestPackedTypes() + self.setMessage(message) + golden_data = (b'\x0A\x01\x01' + b'\x12\x01\x01' + b'\x1A\x01\x01' + b'\x22\x01\x01' + b'\x2A\x01\x02' + b'\x32\x01\x02' + b'\x3A\x04\x01\x00\x00\x00' + b'\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x4A\x04\x01\x00\x00\x00' + b'\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x5A\x04\x00\x00\x80\x3f' + b'\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f' + b'\x6A\x01\x01' + b'\x72\x01\x01') + self.assertEqual(golden_data, message.SerializeToString()) + + def testUnpackedFields(self): + message = packed_field_test_pb2.TestUnpackedTypes() + self.setMessage(message) + golden_data = (b'\x08\x01' + b'\x10\x01' + b'\x18\x01' + b'\x20\x01' + b'\x28\x02' + b'\x30\x02' + b'\x3D\x01\x00\x00\x00' + b'\x41\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x4D\x01\x00\x00\x00' + b'\x51\x01\x00\x00\x00\x00\x00\x00\x00' + b'\x5D\x00\x00\x80\x3f' + b'\x61\x00\x00\x00\x00\x00\x00\xf0\x3f' + b'\x68\x01' + b'\x70\x01') + self.assertEqual(golden_data, message.SerializeToString()) + + +@unittest.skipIf(api_implementation.Type() != 'cpp' or + sys.version_info < (2, 7), + 'explicit tests of the C++ implementation for PY27 and above') +class OversizeProtosTest(BaseTestCase): + + @classmethod + def setUpClass(cls): + # At the moment, reference cycles between DescriptorPool and Message classes + # are not detected and these objects are never freed. + # To avoid errors with ReferenceLeakChecker, we create the class only once. + file_desc = """ + name: "f/f.msg2" + package: "f" + message_type { + name: "msg1" + field { + name: "payload" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_STRING + } + } + message_type { + name: "msg2" + field { + name: "field" + number: 1 + label: LABEL_OPTIONAL + type: TYPE_MESSAGE + type_name: "msg1" + } + } + """ + pool = descriptor_pool.DescriptorPool() + desc = descriptor_pb2.FileDescriptorProto() + text_format.Parse(file_desc, desc) + pool.Add(desc) + cls.proto_cls = message_factory.MessageFactory(pool).GetPrototype( + pool.FindMessageTypeByName('f.msg2')) + + def setUp(self): + self.p = self.proto_cls() + self.p.field.payload = 'c' * (1024 * 1024 * 64 + 1) + self.p_serialized = self.p.SerializeToString() + + def testAssertOversizeProto(self): + from google.protobuf.pyext._message import SetAllowOversizeProtos + SetAllowOversizeProtos(False) + q = self.proto_cls() + try: + q.ParseFromString(self.p_serialized) + except message.DecodeError as e: + self.assertEqual(str(e), 'Error parsing message') + + def testSucceedOversizeProto(self): + from google.protobuf.pyext._message import SetAllowOversizeProtos + SetAllowOversizeProtos(True) + q = self.proto_cls() + q.ParseFromString(self.p_serialized) + self.assertEqual(self.p.field.payload, q.field.payload) + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/missing_enum_values_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/missing_enum_values_pb2.py new file mode 100644 index 0000000..5ad6cff --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/missing_enum_values_pb2.py @@ -0,0 +1,227 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/missing_enum_values.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/missing_enum_values.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n2google/protobuf/internal/missing_enum_values.proto\x12\x1fgoogle.protobuf.python.internal\"\xc1\x02\n\x0eTestEnumValues\x12X\n\x14optional_nested_enum\x18\x01 \x01(\x0e\x32:.google.protobuf.python.internal.TestEnumValues.NestedEnum\x12X\n\x14repeated_nested_enum\x18\x02 \x03(\x0e\x32:.google.protobuf.python.internal.TestEnumValues.NestedEnum\x12Z\n\x12packed_nested_enum\x18\x03 \x03(\x0e\x32:.google.protobuf.python.internal.TestEnumValues.NestedEnumB\x02\x10\x01\"\x1f\n\nNestedEnum\x12\x08\n\x04ZERO\x10\x00\x12\x07\n\x03ONE\x10\x01\"\xd3\x02\n\x15TestMissingEnumValues\x12_\n\x14optional_nested_enum\x18\x01 \x01(\x0e\x32\x41.google.protobuf.python.internal.TestMissingEnumValues.NestedEnum\x12_\n\x14repeated_nested_enum\x18\x02 \x03(\x0e\x32\x41.google.protobuf.python.internal.TestMissingEnumValues.NestedEnum\x12\x61\n\x12packed_nested_enum\x18\x03 \x03(\x0e\x32\x41.google.protobuf.python.internal.TestMissingEnumValues.NestedEnumB\x02\x10\x01\"\x15\n\nNestedEnum\x12\x07\n\x03TWO\x10\x02\"\x1b\n\nJustString\x12\r\n\x05\x64ummy\x18\x01 \x02(\t') +) + + + +_TESTENUMVALUES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.TestEnumValues.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ZERO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ONE', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=378, + serialized_end=409, +) +_sym_db.RegisterEnumDescriptor(_TESTENUMVALUES_NESTEDENUM) + +_TESTMISSINGENUMVALUES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.TestMissingEnumValues.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TWO', index=0, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=730, + serialized_end=751, +) +_sym_db.RegisterEnumDescriptor(_TESTMISSINGENUMVALUES_NESTEDENUM) + + +_TESTENUMVALUES = _descriptor.Descriptor( + name='TestEnumValues', + full_name='google.protobuf.python.internal.TestEnumValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='google.protobuf.python.internal.TestEnumValues.optional_nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestEnumValues.repeated_nested_enum', index=1, + number=2, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_nested_enum', full_name='google.protobuf.python.internal.TestEnumValues.packed_nested_enum', index=2, + number=3, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTENUMVALUES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=88, + serialized_end=409, +) + + +_TESTMISSINGENUMVALUES = _descriptor.Descriptor( + name='TestMissingEnumValues', + full_name='google.protobuf.python.internal.TestMissingEnumValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='google.protobuf.python.internal.TestMissingEnumValues.optional_nested_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestMissingEnumValues.repeated_nested_enum', index=1, + number=2, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_nested_enum', full_name='google.protobuf.python.internal.TestMissingEnumValues.packed_nested_enum', index=2, + number=3, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTMISSINGENUMVALUES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=412, + serialized_end=751, +) + + +_JUSTSTRING = _descriptor.Descriptor( + name='JustString', + full_name='google.protobuf.python.internal.JustString', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='dummy', full_name='google.protobuf.python.internal.JustString.dummy', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=753, + serialized_end=780, +) + +_TESTENUMVALUES.fields_by_name['optional_nested_enum'].enum_type = _TESTENUMVALUES_NESTEDENUM +_TESTENUMVALUES.fields_by_name['repeated_nested_enum'].enum_type = _TESTENUMVALUES_NESTEDENUM +_TESTENUMVALUES.fields_by_name['packed_nested_enum'].enum_type = _TESTENUMVALUES_NESTEDENUM +_TESTENUMVALUES_NESTEDENUM.containing_type = _TESTENUMVALUES +_TESTMISSINGENUMVALUES.fields_by_name['optional_nested_enum'].enum_type = _TESTMISSINGENUMVALUES_NESTEDENUM +_TESTMISSINGENUMVALUES.fields_by_name['repeated_nested_enum'].enum_type = _TESTMISSINGENUMVALUES_NESTEDENUM +_TESTMISSINGENUMVALUES.fields_by_name['packed_nested_enum'].enum_type = _TESTMISSINGENUMVALUES_NESTEDENUM +_TESTMISSINGENUMVALUES_NESTEDENUM.containing_type = _TESTMISSINGENUMVALUES +DESCRIPTOR.message_types_by_name['TestEnumValues'] = _TESTENUMVALUES +DESCRIPTOR.message_types_by_name['TestMissingEnumValues'] = _TESTMISSINGENUMVALUES +DESCRIPTOR.message_types_by_name['JustString'] = _JUSTSTRING +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestEnumValues = _reflection.GeneratedProtocolMessageType('TestEnumValues', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMVALUES, + __module__ = 'google.protobuf.internal.missing_enum_values_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestEnumValues) + )) +_sym_db.RegisterMessage(TestEnumValues) + +TestMissingEnumValues = _reflection.GeneratedProtocolMessageType('TestMissingEnumValues', (_message.Message,), dict( + DESCRIPTOR = _TESTMISSINGENUMVALUES, + __module__ = 'google.protobuf.internal.missing_enum_values_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestMissingEnumValues) + )) +_sym_db.RegisterMessage(TestMissingEnumValues) + +JustString = _reflection.GeneratedProtocolMessageType('JustString', (_message.Message,), dict( + DESCRIPTOR = _JUSTSTRING, + __module__ = 'google.protobuf.internal.missing_enum_values_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.JustString) + )) +_sym_db.RegisterMessage(JustString) + + +_TESTENUMVALUES.fields_by_name['packed_nested_enum']._options = None +_TESTMISSINGENUMVALUES.fields_by_name['packed_nested_enum']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py new file mode 100644 index 0000000..3417ed6 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_dynamic_pb2.py @@ -0,0 +1,103 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/more_extensions_dynamic.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf.internal import more_extensions_pb2 as google_dot_protobuf_dot_internal_dot_more__extensions__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/more_extensions_dynamic.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n6google/protobuf/internal/more_extensions_dynamic.proto\x12\x18google.protobuf.internal\x1a.google/protobuf/internal/more_extensions.proto\"\x1f\n\x12\x44ynamicMessageType\x12\t\n\x01\x61\x18\x01 \x01(\x05:J\n\x17\x64ynamic_int32_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x64 \x01(\x05:z\n\x19\x64ynamic_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x65 \x01(\x0b\x32,.google.protobuf.internal.DynamicMessageType:\x83\x01\n\"repeated_dynamic_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x66 \x03(\x0b\x32,.google.protobuf.internal.DynamicMessageType') + , + dependencies=[google_dot_protobuf_dot_internal_dot_more__extensions__pb2.DESCRIPTOR,]) + + +DYNAMIC_INT32_EXTENSION_FIELD_NUMBER = 100 +dynamic_int32_extension = _descriptor.FieldDescriptor( + name='dynamic_int32_extension', full_name='google.protobuf.internal.dynamic_int32_extension', index=0, + number=100, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DYNAMIC_MESSAGE_EXTENSION_FIELD_NUMBER = 101 +dynamic_message_extension = _descriptor.FieldDescriptor( + name='dynamic_message_extension', full_name='google.protobuf.internal.dynamic_message_extension', index=1, + number=101, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_DYNAMIC_MESSAGE_EXTENSION_FIELD_NUMBER = 102 +repeated_dynamic_message_extension = _descriptor.FieldDescriptor( + name='repeated_dynamic_message_extension', full_name='google.protobuf.internal.repeated_dynamic_message_extension', index=2, + number=102, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_DYNAMICMESSAGETYPE = _descriptor.Descriptor( + name='DynamicMessageType', + full_name='google.protobuf.internal.DynamicMessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='google.protobuf.internal.DynamicMessageType.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=132, + serialized_end=163, +) + +DESCRIPTOR.message_types_by_name['DynamicMessageType'] = _DYNAMICMESSAGETYPE +DESCRIPTOR.extensions_by_name['dynamic_int32_extension'] = dynamic_int32_extension +DESCRIPTOR.extensions_by_name['dynamic_message_extension'] = dynamic_message_extension +DESCRIPTOR.extensions_by_name['repeated_dynamic_message_extension'] = repeated_dynamic_message_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DynamicMessageType = _reflection.GeneratedProtocolMessageType('DynamicMessageType', (_message.Message,), dict( + DESCRIPTOR = _DYNAMICMESSAGETYPE, + __module__ = 'google.protobuf.internal.more_extensions_dynamic_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.DynamicMessageType) + )) +_sym_db.RegisterMessage(DynamicMessageType) + +google_dot_protobuf_dot_internal_dot_more__extensions__pb2.ExtendedMessage.RegisterExtension(dynamic_int32_extension) +dynamic_message_extension.message_type = _DYNAMICMESSAGETYPE +google_dot_protobuf_dot_internal_dot_more__extensions__pb2.ExtendedMessage.RegisterExtension(dynamic_message_extension) +repeated_dynamic_message_extension.message_type = _DYNAMICMESSAGETYPE +google_dot_protobuf_dot_internal_dot_more__extensions__pb2.ExtendedMessage.RegisterExtension(repeated_dynamic_message_extension) + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_pb2.py new file mode 100644 index 0000000..1433e53 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/more_extensions_pb2.py @@ -0,0 +1,183 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/more_extensions.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/more_extensions.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n.google/protobuf/internal/more_extensions.proto\x12\x18google.protobuf.internal\"P\n\x0fTopLevelMessage\x12=\n\nsubmessage\x18\x01 \x01(\x0b\x32).google.protobuf.internal.ExtendedMessage\"\x1b\n\x0f\x45xtendedMessage*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"-\n\x0e\x46oreignMessage\x12\x1b\n\x13\x66oreign_message_int\x18\x01 \x01(\x05:I\n\x16optional_int_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x01 \x01(\x05:w\n\x1aoptional_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x02 \x01(\x0b\x32(.google.protobuf.internal.ForeignMessage:I\n\x16repeated_int_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x03 \x03(\x05:w\n\x1arepeated_message_extension\x12).google.protobuf.internal.ExtendedMessage\x18\x04 \x03(\x0b\x32(.google.protobuf.internal.ForeignMessage') +) + + +OPTIONAL_INT_EXTENSION_FIELD_NUMBER = 1 +optional_int_extension = _descriptor.FieldDescriptor( + name='optional_int_extension', full_name='google.protobuf.internal.optional_int_extension', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_MESSAGE_EXTENSION_FIELD_NUMBER = 2 +optional_message_extension = _descriptor.FieldDescriptor( + name='optional_message_extension', full_name='google.protobuf.internal.optional_message_extension', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_INT_EXTENSION_FIELD_NUMBER = 3 +repeated_int_extension = _descriptor.FieldDescriptor( + name='repeated_int_extension', full_name='google.protobuf.internal.repeated_int_extension', index=2, + number=3, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_MESSAGE_EXTENSION_FIELD_NUMBER = 4 +repeated_message_extension = _descriptor.FieldDescriptor( + name='repeated_message_extension', full_name='google.protobuf.internal.repeated_message_extension', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TOPLEVELMESSAGE = _descriptor.Descriptor( + name='TopLevelMessage', + full_name='google.protobuf.internal.TopLevelMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='submessage', full_name='google.protobuf.internal.TopLevelMessage.submessage', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=76, + serialized_end=156, +) + + +_EXTENDEDMESSAGE = _descriptor.Descriptor( + name='ExtendedMessage', + full_name='google.protobuf.internal.ExtendedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=158, + serialized_end=185, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='google.protobuf.internal.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foreign_message_int', full_name='google.protobuf.internal.ForeignMessage.foreign_message_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=187, + serialized_end=232, +) + +_TOPLEVELMESSAGE.fields_by_name['submessage'].message_type = _EXTENDEDMESSAGE +DESCRIPTOR.message_types_by_name['TopLevelMessage'] = _TOPLEVELMESSAGE +DESCRIPTOR.message_types_by_name['ExtendedMessage'] = _EXTENDEDMESSAGE +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.extensions_by_name['optional_int_extension'] = optional_int_extension +DESCRIPTOR.extensions_by_name['optional_message_extension'] = optional_message_extension +DESCRIPTOR.extensions_by_name['repeated_int_extension'] = repeated_int_extension +DESCRIPTOR.extensions_by_name['repeated_message_extension'] = repeated_message_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TopLevelMessage = _reflection.GeneratedProtocolMessageType('TopLevelMessage', (_message.Message,), dict( + DESCRIPTOR = _TOPLEVELMESSAGE, + __module__ = 'google.protobuf.internal.more_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.TopLevelMessage) + )) +_sym_db.RegisterMessage(TopLevelMessage) + +ExtendedMessage = _reflection.GeneratedProtocolMessageType('ExtendedMessage', (_message.Message,), dict( + DESCRIPTOR = _EXTENDEDMESSAGE, + __module__ = 'google.protobuf.internal.more_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.ExtendedMessage) + )) +_sym_db.RegisterMessage(ExtendedMessage) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.internal.more_extensions_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +ExtendedMessage.RegisterExtension(optional_int_extension) +optional_message_extension.message_type = _FOREIGNMESSAGE +ExtendedMessage.RegisterExtension(optional_message_extension) +ExtendedMessage.RegisterExtension(repeated_int_extension) +repeated_message_extension.message_type = _FOREIGNMESSAGE +ExtendedMessage.RegisterExtension(repeated_message_extension) + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/more_messages_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/more_messages_pb2.py new file mode 100644 index 0000000..99d53dc --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/more_messages_pb2.py @@ -0,0 +1,103 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/more_messages.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/more_messages.proto', + package='google.protobuf.internal', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n,google/protobuf/internal/more_messages.proto\x12\x18google.protobuf.internal\"h\n\x10OutOfOrderFields\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05*\x04\x08\x04\x10\x05*\x04\x08\x02\x10\x03:C\n\x0foptional_uint64\x12*.google.protobuf.internal.OutOfOrderFields\x18\x04 \x01(\x04:B\n\x0eoptional_int64\x12*.google.protobuf.internal.OutOfOrderFields\x18\x02 \x01(\x03') +) + + +OPTIONAL_UINT64_FIELD_NUMBER = 4 +optional_uint64 = _descriptor.FieldDescriptor( + name='optional_uint64', full_name='google.protobuf.internal.optional_uint64', index=0, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_INT64_FIELD_NUMBER = 2 +optional_int64 = _descriptor.FieldDescriptor( + name='optional_int64', full_name='google.protobuf.internal.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_OUTOFORDERFIELDS = _descriptor.Descriptor( + name='OutOfOrderFields', + full_name='google.protobuf.internal.OutOfOrderFields', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='google.protobuf.internal.OutOfOrderFields.optional_sint32', index=0, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='google.protobuf.internal.OutOfOrderFields.optional_uint32', index=1, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32', full_name='google.protobuf.internal.OutOfOrderFields.optional_int32', index=2, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 5), (2, 3), ], + oneofs=[ + ], + serialized_start=74, + serialized_end=178, +) + +DESCRIPTOR.message_types_by_name['OutOfOrderFields'] = _OUTOFORDERFIELDS +DESCRIPTOR.extensions_by_name['optional_uint64'] = optional_uint64 +DESCRIPTOR.extensions_by_name['optional_int64'] = optional_int64 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +OutOfOrderFields = _reflection.GeneratedProtocolMessageType('OutOfOrderFields', (_message.Message,), dict( + DESCRIPTOR = _OUTOFORDERFIELDS, + __module__ = 'google.protobuf.internal.more_messages_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.internal.OutOfOrderFields) + )) +_sym_db.RegisterMessage(OutOfOrderFields) + +OutOfOrderFields.RegisterExtension(optional_uint64) +OutOfOrderFields.RegisterExtension(optional_int64) + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/no_package_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/no_package_pb2.py new file mode 100644 index 0000000..8663666 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/no_package_pb2.py @@ -0,0 +1,97 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/no_package.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/no_package.proto', + package='', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n)google/protobuf/internal/no_package.proto\";\n\x10NoPackageMessage\x12\'\n\x0fno_package_enum\x18\x01 \x01(\x0e\x32\x0e.NoPackageEnum*?\n\rNoPackageEnum\x12\x16\n\x12NO_PACKAGE_VALUE_0\x10\x00\x12\x16\n\x12NO_PACKAGE_VALUE_1\x10\x01') +) + +_NOPACKAGEENUM = _descriptor.EnumDescriptor( + name='NoPackageEnum', + full_name='NoPackageEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NO_PACKAGE_VALUE_0', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NO_PACKAGE_VALUE_1', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=106, + serialized_end=169, +) +_sym_db.RegisterEnumDescriptor(_NOPACKAGEENUM) + +NoPackageEnum = enum_type_wrapper.EnumTypeWrapper(_NOPACKAGEENUM) +NO_PACKAGE_VALUE_0 = 0 +NO_PACKAGE_VALUE_1 = 1 + + + +_NOPACKAGEMESSAGE = _descriptor.Descriptor( + name='NoPackageMessage', + full_name='NoPackageMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='no_package_enum', full_name='NoPackageMessage.no_package_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=45, + serialized_end=104, +) + +_NOPACKAGEMESSAGE.fields_by_name['no_package_enum'].enum_type = _NOPACKAGEENUM +DESCRIPTOR.message_types_by_name['NoPackageMessage'] = _NOPACKAGEMESSAGE +DESCRIPTOR.enum_types_by_name['NoPackageEnum'] = _NOPACKAGEENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +NoPackageMessage = _reflection.GeneratedProtocolMessageType('NoPackageMessage', (_message.Message,), dict( + DESCRIPTOR = _NOPACKAGEMESSAGE, + __module__ = 'google.protobuf.internal.no_package_pb2' + # @@protoc_insertion_point(class_scope:NoPackageMessage) + )) +_sym_db.RegisterMessage(NoPackageMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/packed_field_test_pb2.py b/winvenv/Lib/site-packages/google/protobuf/internal/packed_field_test_pb2.py new file mode 100644 index 0000000..5e95400 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/packed_field_test_pb2.py @@ -0,0 +1,334 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/internal/packed_field_test.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/internal/packed_field_test.proto', + package='google.protobuf.python.internal', + syntax='proto3', + serialized_options=None, + serialized_pb=_b('\n0google/protobuf/internal/packed_field_test.proto\x12\x1fgoogle.protobuf.python.internal\"\xdb\x03\n\x0fTestPackedTypes\x12\x16\n\x0erepeated_int32\x18\x01 \x03(\x05\x12\x16\n\x0erepeated_int64\x18\x02 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18\x03 \x03(\r\x12\x17\n\x0frepeated_uint64\x18\x04 \x03(\x04\x12\x17\n\x0frepeated_sint32\x18\x05 \x03(\x11\x12\x17\n\x0frepeated_sint64\x18\x06 \x03(\x12\x12\x18\n\x10repeated_fixed32\x18\x07 \x03(\x07\x12\x18\n\x10repeated_fixed64\x18\x08 \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\t \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18\n \x03(\x10\x12\x16\n\x0erepeated_float\x18\x0b \x03(\x02\x12\x17\n\x0frepeated_double\x18\x0c \x03(\x01\x12\x15\n\rrepeated_bool\x18\r \x03(\x08\x12Y\n\x14repeated_nested_enum\x18\x0e \x03(\x0e\x32;.google.protobuf.python.internal.TestPackedTypes.NestedEnum\"\'\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x12\x07\n\x03\x42\x41Z\x10\x02\"\xec\x03\n\x11TestUnpackedTypes\x12\x1a\n\x0erepeated_int32\x18\x01 \x03(\x05\x42\x02\x10\x00\x12\x1a\n\x0erepeated_int64\x18\x02 \x03(\x03\x42\x02\x10\x00\x12\x1b\n\x0frepeated_uint32\x18\x03 \x03(\rB\x02\x10\x00\x12\x1b\n\x0frepeated_uint64\x18\x04 \x03(\x04\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint32\x18\x05 \x03(\x11\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint64\x18\x06 \x03(\x12\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed32\x18\x07 \x03(\x07\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed64\x18\x08 \x03(\x06\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed32\x18\t \x03(\x0f\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed64\x18\n \x03(\x10\x42\x02\x10\x00\x12\x1a\n\x0erepeated_float\x18\x0b \x03(\x02\x42\x02\x10\x00\x12\x1b\n\x0frepeated_double\x18\x0c \x03(\x01\x42\x02\x10\x00\x12\x19\n\rrepeated_bool\x18\r \x03(\x08\x42\x02\x10\x00\x12]\n\x14repeated_nested_enum\x18\x0e \x03(\x0e\x32;.google.protobuf.python.internal.TestPackedTypes.NestedEnumB\x02\x10\x00\x62\x06proto3') +) + + + +_TESTPACKEDTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='google.protobuf.python.internal.TestPackedTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=522, + serialized_end=561, +) +_sym_db.RegisterEnumDescriptor(_TESTPACKEDTYPES_NESTEDENUM) + + +_TESTPACKEDTYPES = _descriptor.Descriptor( + name='TestPackedTypes', + full_name='google.protobuf.python.internal.TestPackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_int64', index=1, + number=2, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_uint32', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_uint64', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sint32', index=4, + number=5, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sint64', index=5, + number=6, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_fixed32', index=6, + number=7, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_fixed64', index=7, + number=8, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_float', index=10, + number=11, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_double', index=11, + number=12, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_bool', index=12, + number=13, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestPackedTypes.repeated_nested_enum', index=13, + number=14, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTPACKEDTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=86, + serialized_end=561, +) + + +_TESTUNPACKEDTYPES = _descriptor.Descriptor( + name='TestUnpackedTypes', + full_name='google.protobuf.python.internal.TestUnpackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_int64', index=1, + number=2, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_uint32', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_uint64', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sint32', index=4, + number=5, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sint64', index=5, + number=6, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_fixed32', index=6, + number=7, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_fixed64', index=7, + number=8, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_float', index=10, + number=11, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_double', index=11, + number=12, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_bool', index=12, + number=13, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='google.protobuf.python.internal.TestUnpackedTypes.repeated_nested_enum', index=13, + number=14, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=564, + serialized_end=1056, +) + +_TESTPACKEDTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTPACKEDTYPES_NESTEDENUM +_TESTPACKEDTYPES_NESTEDENUM.containing_type = _TESTPACKEDTYPES +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTPACKEDTYPES_NESTEDENUM +DESCRIPTOR.message_types_by_name['TestPackedTypes'] = _TESTPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestUnpackedTypes'] = _TESTUNPACKEDTYPES +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestPackedTypes = _reflection.GeneratedProtocolMessageType('TestPackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDTYPES, + __module__ = 'google.protobuf.internal.packed_field_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestPackedTypes) + )) +_sym_db.RegisterMessage(TestPackedTypes) + +TestUnpackedTypes = _reflection.GeneratedProtocolMessageType('TestUnpackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDTYPES, + __module__ = 'google.protobuf.internal.packed_field_test_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestUnpackedTypes) + )) +_sym_db.RegisterMessage(TestUnpackedTypes) + + +_TESTUNPACKEDTYPES.fields_by_name['repeated_int32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_int64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_float']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_double']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_bool']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/proto_builder_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/proto_builder_test.py new file mode 100644 index 0000000..36dfbfd --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/proto_builder_test.py @@ -0,0 +1,96 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.proto_builder.""" + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict #PY26 +try: + import unittest2 as unittest +except ImportError: + import unittest + +from google.protobuf import descriptor_pb2 +from google.protobuf import descriptor_pool +from google.protobuf import proto_builder +from google.protobuf import text_format + + +class ProtoBuilderTest(unittest.TestCase): + + def setUp(self): + self.ordered_fields = OrderedDict([ + ('foo', descriptor_pb2.FieldDescriptorProto.TYPE_INT64), + ('bar', descriptor_pb2.FieldDescriptorProto.TYPE_STRING), + ]) + self._fields = dict(self.ordered_fields) + + def testMakeSimpleProtoClass(self): + """Test that we can create a proto class.""" + proto_cls = proto_builder.MakeSimpleProtoClass( + self._fields, + full_name='net.proto2.python.public.proto_builder_test.Test') + proto = proto_cls() + proto.foo = 12345 + proto.bar = 'asdf' + self.assertMultiLineEqual( + 'bar: "asdf"\nfoo: 12345\n', text_format.MessageToString(proto)) + + def testOrderedFields(self): + """Test that the field order is maintained when given an OrderedDict.""" + proto_cls = proto_builder.MakeSimpleProtoClass( + self.ordered_fields, + full_name='net.proto2.python.public.proto_builder_test.OrderedTest') + proto = proto_cls() + proto.foo = 12345 + proto.bar = 'asdf' + self.assertMultiLineEqual( + 'foo: 12345\nbar: "asdf"\n', text_format.MessageToString(proto)) + + def testMakeSameProtoClassTwice(self): + """Test that the DescriptorPool is used.""" + pool = descriptor_pool.DescriptorPool() + proto_cls1 = proto_builder.MakeSimpleProtoClass( + self._fields, + full_name='net.proto2.python.public.proto_builder_test.Test', + pool=pool) + proto_cls2 = proto_builder.MakeSimpleProtoClass( + self._fields, + full_name='net.proto2.python.public.proto_builder_test.Test', + pool=pool) + self.assertIs(proto_cls1.DESCRIPTOR, proto_cls2.DESCRIPTOR) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/python_message.py b/winvenv/Lib/site-packages/google/protobuf/internal/python_message.py new file mode 100644 index 0000000..975e3b4 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/python_message.py @@ -0,0 +1,1559 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# This code is meant to work on Python 2.4 and above only. +# +# TODO(robinson): Helpers for verbose, common checks like seeing if a +# descriptor's cpp_type is CPPTYPE_MESSAGE. + +"""Contains a metaclass and helper functions used to create +protocol message classes from Descriptor objects at runtime. + +Recall that a metaclass is the "type" of a class. +(A class is to a metaclass what an instance is to a class.) + +In this case, we use the GeneratedProtocolMessageType metaclass +to inject all the useful functionality into the classes +output by the protocol compiler at compile-time. + +The upshot of all this is that the real implementation +details for ALL pure-Python protocol buffers are *here in +this file*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +from io import BytesIO +import struct +import sys +import weakref + +import six + +# We use "as" to avoid name collisions with variables. +from google.protobuf.internal import api_implementation +from google.protobuf.internal import containers +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.internal import enum_type_wrapper +from google.protobuf.internal import message_listener as message_listener_mod +from google.protobuf.internal import type_checkers +from google.protobuf.internal import well_known_types +from google.protobuf.internal import wire_format +from google.protobuf import descriptor as descriptor_mod +from google.protobuf import message as message_mod +from google.protobuf import text_format + +_FieldDescriptor = descriptor_mod.FieldDescriptor +_AnyFullTypeName = 'google.protobuf.Any' + + +class GeneratedProtocolMessageType(type): + + """Metaclass for protocol message classes created at runtime from Descriptors. + + We add implementations for all methods described in the Message class. We + also create properties to allow getting/setting all fields in the protocol + message. Finally, we create slots to prevent users from accidentally + "setting" nonexistent fields in the protocol message, which then wouldn't get + serialized / deserialized properly. + + The protocol compiler currently uses this metaclass to create protocol + message classes at runtime. Clients can also manually create their own + classes at runtime, as in this example: + + mydescriptor = Descriptor(.....) + factory = symbol_database.Default() + factory.pool.AddDescriptor(mydescriptor) + MyProtoClass = factory.GetPrototype(mydescriptor) + myproto_instance = MyProtoClass() + myproto.foo_field = 23 + ... + """ + + # Must be consistent with the protocol-compiler code in + # proto2/compiler/internal/generator.*. + _DESCRIPTOR_KEY = 'DESCRIPTOR' + + def __new__(cls, name, bases, dictionary): + """Custom allocation for runtime-generated class types. + + We override __new__ because this is apparently the only place + where we can meaningfully set __slots__ on the class we're creating(?). + (The interplay between metaclasses and slots is not very well-documented). + + Args: + name: Name of the class (ignored, but required by the + metaclass protocol). + bases: Base classes of the class we're constructing. + (Should be message.Message). We ignore this field, but + it's required by the metaclass protocol + dictionary: The class dictionary of the class we're + constructing. dictionary[_DESCRIPTOR_KEY] must contain + a Descriptor object describing this protocol message + type. + + Returns: + Newly-allocated class. + """ + descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] + if descriptor.full_name in well_known_types.WKTBASES: + bases += (well_known_types.WKTBASES[descriptor.full_name],) + _AddClassAttributesForNestedExtensions(descriptor, dictionary) + _AddSlots(descriptor, dictionary) + + superclass = super(GeneratedProtocolMessageType, cls) + new_class = superclass.__new__(cls, name, bases, dictionary) + return new_class + + def __init__(cls, name, bases, dictionary): + """Here we perform the majority of our work on the class. + We add enum getters, an __init__ method, implementations + of all Message methods, and properties for all fields + in the protocol type. + + Args: + name: Name of the class (ignored, but required by the + metaclass protocol). + bases: Base classes of the class we're constructing. + (Should be message.Message). We ignore this field, but + it's required by the metaclass protocol + dictionary: The class dictionary of the class we're + constructing. dictionary[_DESCRIPTOR_KEY] must contain + a Descriptor object describing this protocol message + type. + """ + descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY] + cls._decoders_by_tag = {} + if (descriptor.has_options and + descriptor.GetOptions().message_set_wire_format): + cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = ( + decoder.MessageSetItemDecoder(descriptor), None) + + # Attach stuff to each FieldDescriptor for quick lookup later on. + for field in descriptor.fields: + _AttachFieldHelpers(cls, field) + + descriptor._concrete_class = cls # pylint: disable=protected-access + _AddEnumValues(descriptor, cls) + _AddInitMethod(descriptor, cls) + _AddPropertiesForFields(descriptor, cls) + _AddPropertiesForExtensions(descriptor, cls) + _AddStaticMethods(cls) + _AddMessageMethods(descriptor, cls) + _AddPrivateHelperMethods(descriptor, cls) + + superclass = super(GeneratedProtocolMessageType, cls) + superclass.__init__(name, bases, dictionary) + + +# Stateless helpers for GeneratedProtocolMessageType below. +# Outside clients should not access these directly. +# +# I opted not to make any of these methods on the metaclass, to make it more +# clear that I'm not really using any state there and to keep clients from +# thinking that they have direct access to these construction helpers. + + +def _PropertyName(proto_field_name): + """Returns the name of the public property attribute which + clients can use to get and (in some cases) set the value + of a protocol message field. + + Args: + proto_field_name: The protocol message field name, exactly + as it appears (or would appear) in a .proto file. + """ + # TODO(robinson): Escape Python keywords (e.g., yield), and test this support. + # nnorwitz makes my day by writing: + # """ + # FYI. See the keyword module in the stdlib. This could be as simple as: + # + # if keyword.iskeyword(proto_field_name): + # return proto_field_name + "_" + # return proto_field_name + # """ + # Kenton says: The above is a BAD IDEA. People rely on being able to use + # getattr() and setattr() to reflectively manipulate field values. If we + # rename the properties, then every such user has to also make sure to apply + # the same transformation. Note that currently if you name a field "yield", + # you can still access it just fine using getattr/setattr -- it's not even + # that cumbersome to do so. + # TODO(kenton): Remove this method entirely if/when everyone agrees with my + # position. + return proto_field_name + + +def _VerifyExtensionHandle(message, extension_handle): + """Verify that the given extension handle is valid.""" + + if not isinstance(extension_handle, _FieldDescriptor): + raise KeyError('HasExtension() expects an extension handle, got: %s' % + extension_handle) + + if not extension_handle.is_extension: + raise KeyError('"%s" is not an extension.' % extension_handle.full_name) + + if not extension_handle.containing_type: + raise KeyError('"%s" is missing a containing_type.' + % extension_handle.full_name) + + if extension_handle.containing_type is not message.DESCRIPTOR: + raise KeyError('Extension "%s" extends message type "%s", but this ' + 'message is of type "%s".' % + (extension_handle.full_name, + extension_handle.containing_type.full_name, + message.DESCRIPTOR.full_name)) + + +def _AddSlots(message_descriptor, dictionary): + """Adds a __slots__ entry to dictionary, containing the names of all valid + attributes for this message type. + + Args: + message_descriptor: A Descriptor instance describing this message type. + dictionary: Class dictionary to which we'll add a '__slots__' entry. + """ + dictionary['__slots__'] = ['_cached_byte_size', + '_cached_byte_size_dirty', + '_fields', + '_unknown_fields', + '_is_present_in_parent', + '_listener', + '_listener_for_children', + '__weakref__', + '_oneofs'] + + +def _IsMessageSetExtension(field): + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == _FieldDescriptor.TYPE_MESSAGE and + field.label == _FieldDescriptor.LABEL_OPTIONAL) + + +def _IsMapField(field): + return (field.type == _FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) + + +def _IsMessageMapField(field): + value_type = field.message_type.fields_by_name["value"] + return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE + + +def _AttachFieldHelpers(cls, field_descriptor): + is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED) + is_packable = (is_repeated and + wire_format.IsTypePackable(field_descriptor.type)) + if not is_packable: + is_packed = False + elif field_descriptor.containing_type.syntax == "proto2": + is_packed = (field_descriptor.has_options and + field_descriptor.GetOptions().packed) + else: + has_packed_false = (field_descriptor.has_options and + field_descriptor.GetOptions().HasField("packed") and + field_descriptor.GetOptions().packed == False) + is_packed = not has_packed_false + is_map_entry = _IsMapField(field_descriptor) + + if is_map_entry: + field_encoder = encoder.MapEncoder(field_descriptor) + sizer = encoder.MapSizer(field_descriptor, + _IsMessageMapField(field_descriptor)) + elif _IsMessageSetExtension(field_descriptor): + field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number) + sizer = encoder.MessageSetItemSizer(field_descriptor.number) + else: + field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed) + sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type]( + field_descriptor.number, is_repeated, is_packed) + + field_descriptor._encoder = field_encoder + field_descriptor._sizer = sizer + field_descriptor._default_constructor = _DefaultValueConstructorForField( + field_descriptor) + + def AddDecoder(wiretype, is_packed): + tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype) + decode_type = field_descriptor.type + if (decode_type == _FieldDescriptor.TYPE_ENUM and + type_checkers.SupportsOpenEnums(field_descriptor)): + decode_type = _FieldDescriptor.TYPE_INT32 + + oneof_descriptor = None + if field_descriptor.containing_oneof is not None: + oneof_descriptor = field_descriptor + + if is_map_entry: + is_message_map = _IsMessageMapField(field_descriptor) + + field_decoder = decoder.MapDecoder( + field_descriptor, _GetInitializeDefaultForMap(field_descriptor), + is_message_map) + else: + field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor) + + cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor) + + AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], + False) + + if is_repeated and wire_format.IsTypePackable(field_descriptor.type): + # To support wire compatibility of adding packed = true, add a decoder for + # packed values regardless of the field's options. + AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True) + + +def _AddClassAttributesForNestedExtensions(descriptor, dictionary): + extension_dict = descriptor.extensions_by_name + for extension_name, extension_field in extension_dict.items(): + assert extension_name not in dictionary + dictionary[extension_name] = extension_field + + +def _AddEnumValues(descriptor, cls): + """Sets class-level attributes for all enum fields defined in this message. + + Also exporting a class-level object that can name enum values. + + Args: + descriptor: Descriptor object for this message type. + cls: Class we're constructing for this message type. + """ + for enum_type in descriptor.enum_types: + setattr(cls, enum_type.name, enum_type_wrapper.EnumTypeWrapper(enum_type)) + for enum_value in enum_type.values: + setattr(cls, enum_value.name, enum_value.number) + + +def _GetInitializeDefaultForMap(field): + if field.label != _FieldDescriptor.LABEL_REPEATED: + raise ValueError('map_entry set on non-repeated field %s' % ( + field.name)) + fields_by_name = field.message_type.fields_by_name + key_checker = type_checkers.GetTypeChecker(fields_by_name['key']) + + value_field = fields_by_name['value'] + if _IsMessageMapField(field): + def MakeMessageMapDefault(message): + return containers.MessageMap( + message._listener_for_children, value_field.message_type, key_checker, + field.message_type) + return MakeMessageMapDefault + else: + value_checker = type_checkers.GetTypeChecker(value_field) + def MakePrimitiveMapDefault(message): + return containers.ScalarMap( + message._listener_for_children, key_checker, value_checker, + field.message_type) + return MakePrimitiveMapDefault + +def _DefaultValueConstructorForField(field): + """Returns a function which returns a default value for a field. + + Args: + field: FieldDescriptor object for this field. + + The returned function has one argument: + message: Message instance containing this field, or a weakref proxy + of same. + + That function in turn returns a default value for this field. The default + value may refer back to |message| via a weak reference. + """ + + if _IsMapField(field): + return _GetInitializeDefaultForMap(field) + + if field.label == _FieldDescriptor.LABEL_REPEATED: + if field.has_default_value and field.default_value != []: + raise ValueError('Repeated field default value not empty list: %s' % ( + field.default_value)) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + # We can't look at _concrete_class yet since it might not have + # been set. (Depends on order in which we initialize the classes). + message_type = field.message_type + def MakeRepeatedMessageDefault(message): + return containers.RepeatedCompositeFieldContainer( + message._listener_for_children, field.message_type) + return MakeRepeatedMessageDefault + else: + type_checker = type_checkers.GetTypeChecker(field) + def MakeRepeatedScalarDefault(message): + return containers.RepeatedScalarFieldContainer( + message._listener_for_children, type_checker) + return MakeRepeatedScalarDefault + + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + # _concrete_class may not yet be initialized. + message_type = field.message_type + def MakeSubMessageDefault(message): + result = message_type._concrete_class() + result._SetListener( + _OneofListener(message, field) + if field.containing_oneof is not None + else message._listener_for_children) + return result + return MakeSubMessageDefault + + def MakeScalarDefault(message): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return field.default_value + return MakeScalarDefault + + +def _ReraiseTypeErrorWithFieldName(message_name, field_name): + """Re-raise the currently-handled TypeError with the field name added.""" + exc = sys.exc_info()[1] + if len(exc.args) == 1 and type(exc) is TypeError: + # simple TypeError; add field name to exception message + exc = TypeError('%s for field %s.%s' % (str(exc), message_name, field_name)) + + # re-raise possibly-amended exception with original traceback: + six.reraise(type(exc), exc, sys.exc_info()[2]) + + +def _AddInitMethod(message_descriptor, cls): + """Adds an __init__ method to cls.""" + + def _GetIntegerEnumValue(enum_type, value): + """Convert a string or integer enum value to an integer. + + If the value is a string, it is converted to the enum value in + enum_type with the same name. If the value is not a string, it's + returned as-is. (No conversion or bounds-checking is done.) + """ + if isinstance(value, six.string_types): + try: + return enum_type.values_by_name[value].number + except KeyError: + raise ValueError('Enum type %s: unknown label "%s"' % ( + enum_type.full_name, value)) + return value + + def init(self, **kwargs): + self._cached_byte_size = 0 + self._cached_byte_size_dirty = len(kwargs) > 0 + self._fields = {} + # Contains a mapping from oneof field descriptors to the descriptor + # of the currently set field in that oneof field. + self._oneofs = {} + + # _unknown_fields is () when empty for efficiency, and will be turned into + # a list if fields are added. + self._unknown_fields = () + self._is_present_in_parent = False + self._listener = message_listener_mod.NullMessageListener() + self._listener_for_children = _Listener(self) + for field_name, field_value in kwargs.items(): + field = _GetFieldByName(message_descriptor, field_name) + if field is None: + raise TypeError("%s() got an unexpected keyword argument '%s'" % + (message_descriptor.name, field_name)) + if field_value is None: + # field=None is the same as no field at all. + continue + if field.label == _FieldDescriptor.LABEL_REPEATED: + copy = field._default_constructor(self) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite + if _IsMapField(field): + if _IsMessageMapField(field): + for key in field_value: + copy[key].MergeFrom(field_value[key]) + else: + copy.update(field_value) + else: + for val in field_value: + if isinstance(val, dict): + copy.add(**val) + else: + copy.add().MergeFrom(val) + else: # Scalar + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = [_GetIntegerEnumValue(field.enum_type, val) + for val in field_value] + copy.extend(field_value) + self._fields[field] = copy + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + copy = field._default_constructor(self) + new_val = field_value + if isinstance(field_value, dict): + new_val = field.message_type._concrete_class(**field_value) + try: + copy.MergeFrom(new_val) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + self._fields[field] = copy + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = _GetIntegerEnumValue(field.enum_type, field_value) + try: + setattr(self, field_name, field_value) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + + init.__module__ = None + init.__doc__ = None + cls.__init__ = init + + +def _GetFieldByName(message_descriptor, field_name): + """Returns a field descriptor by field name. + + Args: + message_descriptor: A Descriptor describing all fields in message. + field_name: The name of the field to retrieve. + Returns: + The field descriptor associated with the field name. + """ + try: + return message_descriptor.fields_by_name[field_name] + except KeyError: + raise ValueError('Protocol message %s has no "%s" field.' % + (message_descriptor.name, field_name)) + + +def _AddPropertiesForFields(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + for field in descriptor.fields: + _AddPropertiesForField(field, cls) + + if descriptor.is_extendable: + # _ExtensionDict is just an adaptor with no state so we allocate a new one + # every time it is accessed. + cls.Extensions = property(lambda self: _ExtensionDict(self)) + + +def _AddPropertiesForField(field, cls): + """Adds a public property for a protocol message field. + Clients can use this property to get and (in the case + of non-repeated scalar fields) directly set the value + of a protocol message field. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # Catch it if we add other types that we should + # handle specially here. + assert _FieldDescriptor.MAX_CPPTYPE == 10 + + constant_name = field.name.upper() + "_FIELD_NUMBER" + setattr(cls, constant_name, field.number) + + if field.label == _FieldDescriptor.LABEL_REPEATED: + _AddPropertiesForRepeatedField(field, cls) + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + _AddPropertiesForNonRepeatedCompositeField(field, cls) + else: + _AddPropertiesForNonRepeatedScalarField(field, cls) + + +def _AddPropertiesForRepeatedField(field, cls): + """Adds a public property for a "repeated" protocol message field. Clients + can use this property to get the value of the field, which will be either a + _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see + below). + + Note that when clients add values to these containers, we perform + type-checking in the case of repeated scalar fields, and we also set any + necessary "has" bits as a side-effect. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to repeated field ' + '"%s" in protocol message object.' % proto_field_name) + + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedScalarField(field, cls): + """Adds a public property for a nonrepeated, scalar protocol message field. + Clients can use this property to get and directly set the value of the field. + Note that when the client sets the value of a field by using this property, + all necessary "has" bits are set as a side-effect, and we also perform + type-checking. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + type_checker = type_checkers.GetTypeChecker(field) + default_value = field.default_value + valid_values = set() + is_proto3 = field.containing_type.syntax == "proto3" + + def getter(self): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return self._fields.get(field, default_value) + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + clear_when_set_to_default = is_proto3 and not field.containing_oneof + + def field_setter(self, new_value): + # pylint: disable=protected-access + # Testing the value for truthiness captures all of the proto3 defaults + # (0, 0.0, enum 0, and False). + new_value = type_checker.CheckValue(new_value) + if clear_when_set_to_default and not new_value: + self._fields.pop(field, None) + else: + self._fields[field] = new_value + # Check _cached_byte_size_dirty inline to improve performance, since scalar + # setters are called frequently. + if not self._cached_byte_size_dirty: + self._Modified() + + if field.containing_oneof: + def setter(self, new_value): + field_setter(self, new_value) + self._UpdateOneofState(field) + else: + setter = field_setter + + setter.__module__ = None + setter.__doc__ = 'Setter for %s.' % proto_field_name + + # Add a property to encapsulate the getter/setter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedCompositeField(field, cls): + """Adds a public property for a nonrepeated, composite protocol message field. + A composite field is a "group" or "message" field. + + Clients can use this property to get the value of the field, but cannot + assign to the property directly. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # TODO(robinson): Remove duplication with similar method + # for non-repeated scalars. + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to composite field ' + '"%s" in protocol message object.' % proto_field_name) + + # Add a property to encapsulate the getter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, property(getter, setter, doc=doc)) + + +def _AddPropertiesForExtensions(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + extension_dict = descriptor.extensions_by_name + for extension_name, extension_field in extension_dict.items(): + constant_name = extension_name.upper() + "_FIELD_NUMBER" + setattr(cls, constant_name, extension_field.number) + + # TODO(amauryfa): Migrate all users of these attributes to functions like + # pool.FindExtensionByNumber(descriptor). + if descriptor.file is not None: + # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. + pool = descriptor.file.pool + cls._extensions_by_number = pool._extensions_by_number[descriptor] + cls._extensions_by_name = pool._extensions_by_name[descriptor] + +def _AddStaticMethods(cls): + # TODO(robinson): This probably needs to be thread-safe(?) + def RegisterExtension(extension_handle): + extension_handle.containing_type = cls.DESCRIPTOR + # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. + cls.DESCRIPTOR.file.pool.AddExtensionDescriptor(extension_handle) + _AttachFieldHelpers(cls, extension_handle) + cls.RegisterExtension = staticmethod(RegisterExtension) + + def FromString(s): + message = cls() + message.MergeFromString(s) + return message + cls.FromString = staticmethod(FromString) + + +def _IsPresent(item): + """Given a (FieldDescriptor, value) tuple from _fields, return true if the + value should be included in the list returned by ListFields().""" + + if item[0].label == _FieldDescriptor.LABEL_REPEATED: + return bool(item[1]) + elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + return item[1]._is_present_in_parent + else: + return True + + +def _AddListFieldsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ListFields(self): + all_fields = [item for item in self._fields.items() if _IsPresent(item)] + all_fields.sort(key = lambda item: item[0].number) + return all_fields + + cls.ListFields = ListFields + +_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"' +_Proto2HasError = 'Protocol message has no non-repeated field "%s"' + +def _AddHasFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + is_proto3 = (message_descriptor.syntax == "proto3") + error_msg = _Proto3HasError if is_proto3 else _Proto2HasError + + hassable_fields = {} + for field in message_descriptor.fields: + if field.label == _FieldDescriptor.LABEL_REPEATED: + continue + # For proto3, only submessages and fields inside a oneof have presence. + if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and + not field.containing_oneof): + continue + hassable_fields[field.name] = field + + if not is_proto3: + # Fields inside oneofs are never repeated (enforced by the compiler). + for oneof in message_descriptor.oneofs: + hassable_fields[oneof.name] = oneof + + def HasField(self, field_name): + try: + field = hassable_fields[field_name] + except KeyError: + raise ValueError(error_msg % field_name) + + if isinstance(field, descriptor_mod.OneofDescriptor): + try: + return HasField(self, self._oneofs[field].name) + except KeyError: + return False + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(field) + return value is not None and value._is_present_in_parent + else: + return field in self._fields + + cls.HasField = HasField + + +def _AddClearFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def ClearField(self, field_name): + try: + field = message_descriptor.fields_by_name[field_name] + except KeyError: + try: + field = message_descriptor.oneofs_by_name[field_name] + if field in self._oneofs: + field = self._oneofs[field] + else: + return + except KeyError: + raise ValueError('Protocol message %s() has no "%s" field.' % + (message_descriptor.name, field_name)) + + if field in self._fields: + # To match the C++ implementation, we need to invalidate iterators + # for map fields when ClearField() happens. + if hasattr(self._fields[field], 'InvalidateIterators'): + self._fields[field].InvalidateIterators() + + # Note: If the field is a sub-message, its listener will still point + # at us. That's fine, because the worst than can happen is that it + # will call _Modified() and invalidate our byte size. Big deal. + del self._fields[field] + + if self._oneofs.get(field.containing_oneof, None) is field: + del self._oneofs[field.containing_oneof] + + # Always call _Modified() -- even if nothing was changed, this is + # a mutating method, and thus calling it should cause the field to become + # present in the parent message. + self._Modified() + + cls.ClearField = ClearField + + +def _AddClearExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def ClearExtension(self, extension_handle): + _VerifyExtensionHandle(self, extension_handle) + + # Similar to ClearField(), above. + if extension_handle in self._fields: + del self._fields[extension_handle] + self._Modified() + cls.ClearExtension = ClearExtension + + +def _AddHasExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def HasExtension(self, extension_handle): + _VerifyExtensionHandle(self, extension_handle) + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + raise KeyError('"%s" is repeated.' % extension_handle.full_name) + + if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(extension_handle) + return value is not None and value._is_present_in_parent + else: + return extension_handle in self._fields + cls.HasExtension = HasExtension + +def _InternalUnpackAny(msg): + """Unpacks Any message and returns the unpacked message. + + This internal method is different from public Any Unpack method which takes + the target message as argument. _InternalUnpackAny method does not have + target message type and need to find the message type in descriptor pool. + + Args: + msg: An Any message to be unpacked. + + Returns: + The unpacked message. + """ + # TODO(amauryfa): Don't use the factory of generated messages. + # To make Any work with custom factories, use the message factory of the + # parent message. + # pylint: disable=g-import-not-at-top + from google.protobuf import symbol_database + factory = symbol_database.Default() + + type_url = msg.type_url + + if not type_url: + return None + + # TODO(haberman): For now we just strip the hostname. Better logic will be + # required. + type_name = type_url.split('/')[-1] + descriptor = factory.pool.FindMessageTypeByName(type_name) + + if descriptor is None: + return None + + message_class = factory.GetPrototype(descriptor) + message = message_class() + + message.ParseFromString(msg.value) + return message + + +def _AddEqualsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __eq__(self, other): + if (not isinstance(other, message_mod.Message) or + other.DESCRIPTOR != self.DESCRIPTOR): + return False + + if self is other: + return True + + if self.DESCRIPTOR.full_name == _AnyFullTypeName: + any_a = _InternalUnpackAny(self) + any_b = _InternalUnpackAny(other) + if any_a and any_b: + return any_a == any_b + + if not self.ListFields() == other.ListFields(): + return False + + # Sort unknown fields because their order shouldn't affect equality test. + unknown_fields = list(self._unknown_fields) + unknown_fields.sort() + other_unknown_fields = list(other._unknown_fields) + other_unknown_fields.sort() + + return unknown_fields == other_unknown_fields + + cls.__eq__ = __eq__ + + +def _AddStrMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __str__(self): + return text_format.MessageToString(self) + cls.__str__ = __str__ + + +def _AddReprMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __repr__(self): + return text_format.MessageToString(self) + cls.__repr__ = __repr__ + + +def _AddUnicodeMethod(unused_message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def __unicode__(self): + return text_format.MessageToString(self, as_utf8=True).decode('utf-8') + cls.__unicode__ = __unicode__ + + +def _BytesForNonRepeatedElement(value, field_number, field_type): + """Returns the number of bytes needed to serialize a non-repeated element. + The returned byte count includes space for tag information and any + other additional space associated with serializing value. + + Args: + value: Value we're serializing. + field_number: Field number of this value. (Since the field number + is stored as part of a varint-encoded tag, this has an impact + on the total bytes required to serialize the value). + field_type: The type of the field. One of the TYPE_* constants + within FieldDescriptor. + """ + try: + fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type] + return fn(field_number, value) + except KeyError: + raise message_mod.EncodeError('Unrecognized field type: %d' % field_type) + + +def _AddByteSizeMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ByteSize(self): + if not self._cached_byte_size_dirty: + return self._cached_byte_size + + size = 0 + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + size = descriptor.fields_by_name['key']._sizer(self.key) + size += descriptor.fields_by_name['value']._sizer(self.value) + else: + for field_descriptor, field_value in self.ListFields(): + size += field_descriptor._sizer(field_value) + for tag_bytes, value_bytes in self._unknown_fields: + size += len(tag_bytes) + len(value_bytes) + + self._cached_byte_size = size + self._cached_byte_size_dirty = False + self._listener_for_children.dirty = False + return size + + cls.ByteSize = ByteSize + + +def _AddSerializeToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializeToString(self, **kwargs): + # Check if the message has all of its required fields set. + errors = [] + if not self.IsInitialized(): + raise message_mod.EncodeError( + 'Message %s is missing required fields: %s' % ( + self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors()))) + return self.SerializePartialToString(**kwargs) + cls.SerializeToString = SerializeToString + + +def _AddSerializePartialToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializePartialToString(self, **kwargs): + out = BytesIO() + self._InternalSerialize(out.write, **kwargs) + return out.getvalue() + cls.SerializePartialToString = SerializePartialToString + + def InternalSerialize(self, write_bytes, deterministic=None): + if deterministic is None: + deterministic = ( + api_implementation.IsPythonDefaultSerializationDeterministic()) + else: + deterministic = bool(deterministic) + + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + descriptor.fields_by_name['key']._encoder( + write_bytes, self.key, deterministic) + descriptor.fields_by_name['value']._encoder( + write_bytes, self.value, deterministic) + else: + for field_descriptor, field_value in self.ListFields(): + field_descriptor._encoder(write_bytes, field_value, deterministic) + for tag_bytes, value_bytes in self._unknown_fields: + write_bytes(tag_bytes) + write_bytes(value_bytes) + cls._InternalSerialize = InternalSerialize + + +def _AddMergeFromStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def MergeFromString(self, serialized): + length = len(serialized) + try: + if self._InternalParse(serialized, 0, length) != length: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise message_mod.DecodeError('Unexpected end-group tag.') + except (IndexError, TypeError): + # Now ord(buf[p:p+1]) == ord('') gets TypeError. + raise message_mod.DecodeError('Truncated message.') + except struct.error as e: + raise message_mod.DecodeError(e) + return length # Return this for legacy reasons. + cls.MergeFromString = MergeFromString + + local_ReadTag = decoder.ReadTag + local_SkipField = decoder.SkipField + decoders_by_tag = cls._decoders_by_tag + is_proto3 = message_descriptor.syntax == "proto3" + + def InternalParse(self, buffer, pos, end): + self._Modified() + field_dict = self._fields + unknown_field_list = self._unknown_fields + while pos != end: + (tag_bytes, new_pos) = local_ReadTag(buffer, pos) + field_decoder, field_desc = decoders_by_tag.get(tag_bytes, (None, None)) + if field_decoder is None: + value_start_pos = new_pos + new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) + if new_pos == -1: + return pos + if (not is_proto3 or + api_implementation.GetPythonProto3PreserveUnknownsDefault()): + if not unknown_field_list: + unknown_field_list = self._unknown_fields = [] + unknown_field_list.append( + (tag_bytes, buffer[value_start_pos:new_pos])) + pos = new_pos + else: + pos = field_decoder(buffer, new_pos, end, self, field_dict) + if field_desc: + self._UpdateOneofState(field_desc) + return pos + cls._InternalParse = InternalParse + + +def _AddIsInitializedMethod(message_descriptor, cls): + """Adds the IsInitialized and FindInitializationError methods to the + protocol message class.""" + + required_fields = [field for field in message_descriptor.fields + if field.label == _FieldDescriptor.LABEL_REQUIRED] + + def IsInitialized(self, errors=None): + """Checks if all required fields of a message are set. + + Args: + errors: A list which, if provided, will be populated with the field + paths of all missing required fields. + + Returns: + True iff the specified message has all required fields set. + """ + + # Performance is critical so we avoid HasField() and ListFields(). + + for field in required_fields: + if (field not in self._fields or + (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and + not self._fields[field]._is_present_in_parent)): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + for field, value in list(self._fields.items()): # dict can change size! + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + if (field.message_type.has_options and + field.message_type.GetOptions().map_entry): + continue + for element in value: + if not element.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + elif value._is_present_in_parent and not value.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + return True + + cls.IsInitialized = IsInitialized + + def FindInitializationErrors(self): + """Finds required fields which are not initialized. + + Returns: + A list of strings. Each string is a path to an uninitialized field from + the top-level message, e.g. "foo.bar[5].baz". + """ + + errors = [] # simplify things + + for field in required_fields: + if not self.HasField(field.name): + errors.append(field.name) + + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.is_extension: + name = "(%s)" % field.full_name + else: + name = field.name + + if _IsMapField(field): + if _IsMessageMapField(field): + for key in value: + element = value[key] + prefix = "%s[%s]." % (name, key) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + # ScalarMaps can't have any initialization errors. + pass + elif field.label == _FieldDescriptor.LABEL_REPEATED: + for i in range(len(value)): + element = value[i] + prefix = "%s[%d]." % (name, i) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + prefix = name + "." + sub_errors = value.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + + return errors + + cls.FindInitializationErrors = FindInitializationErrors + + +def _AddMergeFromMethod(cls): + LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED + CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE + + def MergeFrom(self, msg): + if not isinstance(msg, cls): + raise TypeError( + "Parameter to MergeFrom() must be instance of same class: " + 'expected %s got %s.' % (cls.__name__, msg.__class__.__name__)) + + assert msg is not self + self._Modified() + + fields = self._fields + + for field, value in msg._fields.items(): + if field.label == LABEL_REPEATED: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + elif field.cpp_type == CPPTYPE_MESSAGE: + if value._is_present_in_parent: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + else: + self._fields[field] = value + if field.containing_oneof: + self._UpdateOneofState(field) + + if msg._unknown_fields: + if not self._unknown_fields: + self._unknown_fields = [] + self._unknown_fields.extend(msg._unknown_fields) + + cls.MergeFrom = MergeFrom + + +def _AddWhichOneofMethod(message_descriptor, cls): + def WhichOneof(self, oneof_name): + """Returns the name of the currently set field inside a oneof, or None.""" + try: + field = message_descriptor.oneofs_by_name[oneof_name] + except KeyError: + raise ValueError( + 'Protocol message has no oneof "%s" field.' % oneof_name) + + nested_field = self._oneofs.get(field, None) + if nested_field is not None and self.HasField(nested_field.name): + return nested_field.name + else: + return None + + cls.WhichOneof = WhichOneof + + +def _AddReduceMethod(cls): + def __reduce__(self): # pylint: disable=invalid-name + return (type(self), (), self.__getstate__()) + cls.__reduce__ = __reduce__ + + +def _Clear(self): + # Clear fields. + self._fields = {} + self._unknown_fields = () + self._oneofs = {} + self._Modified() + + +def _DiscardUnknownFields(self): + self._unknown_fields = [] + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + for sub_message in value: + sub_message.DiscardUnknownFields() + else: + value.DiscardUnknownFields() + + +def _SetListener(self, listener): + if listener is None: + self._listener = message_listener_mod.NullMessageListener() + else: + self._listener = listener + + +def _AddMessageMethods(message_descriptor, cls): + """Adds implementations of all Message methods to cls.""" + _AddListFieldsMethod(message_descriptor, cls) + _AddHasFieldMethod(message_descriptor, cls) + _AddClearFieldMethod(message_descriptor, cls) + if message_descriptor.is_extendable: + _AddClearExtensionMethod(cls) + _AddHasExtensionMethod(cls) + _AddEqualsMethod(message_descriptor, cls) + _AddStrMethod(message_descriptor, cls) + _AddReprMethod(message_descriptor, cls) + _AddUnicodeMethod(message_descriptor, cls) + _AddByteSizeMethod(message_descriptor, cls) + _AddSerializeToStringMethod(message_descriptor, cls) + _AddSerializePartialToStringMethod(message_descriptor, cls) + _AddMergeFromStringMethod(message_descriptor, cls) + _AddIsInitializedMethod(message_descriptor, cls) + _AddMergeFromMethod(cls) + _AddWhichOneofMethod(message_descriptor, cls) + _AddReduceMethod(cls) + # Adds methods which do not depend on cls. + cls.Clear = _Clear + cls.DiscardUnknownFields = _DiscardUnknownFields + cls._SetListener = _SetListener + + +def _AddPrivateHelperMethods(message_descriptor, cls): + """Adds implementation of private helper methods to cls.""" + + def Modified(self): + """Sets the _cached_byte_size_dirty bit to true, + and propagates this to our listener iff this was a state change. + """ + + # Note: Some callers check _cached_byte_size_dirty before calling + # _Modified() as an extra optimization. So, if this method is ever + # changed such that it does stuff even when _cached_byte_size_dirty is + # already true, the callers need to be updated. + if not self._cached_byte_size_dirty: + self._cached_byte_size_dirty = True + self._listener_for_children.dirty = True + self._is_present_in_parent = True + self._listener.Modified() + + def _UpdateOneofState(self, field): + """Sets field as the active field in its containing oneof. + + Will also delete currently active field in the oneof, if it is different + from the argument. Does not mark the message as modified. + """ + other_field = self._oneofs.setdefault(field.containing_oneof, field) + if other_field is not field: + del self._fields[other_field] + self._oneofs[field.containing_oneof] = field + + cls._Modified = Modified + cls.SetInParent = Modified + cls._UpdateOneofState = _UpdateOneofState + + +class _Listener(object): + + """MessageListener implementation that a parent message registers with its + child message. + + In order to support semantics like: + + foo.bar.baz.qux = 23 + assert foo.HasField('bar') + + ...child objects must have back references to their parents. + This helper class is at the heart of this support. + """ + + def __init__(self, parent_message): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + """ + # This listener establishes a back reference from a child (contained) object + # to its parent (containing) object. We make this a weak reference to avoid + # creating cyclic garbage when the client finishes with the 'parent' object + # in the tree. + if isinstance(parent_message, weakref.ProxyType): + self._parent_message_weakref = parent_message + else: + self._parent_message_weakref = weakref.proxy(parent_message) + + # As an optimization, we also indicate directly on the listener whether + # or not the parent message is dirty. This way we can avoid traversing + # up the tree in the common case. + self.dirty = False + + def Modified(self): + if self.dirty: + return + try: + # Propagate the signal to our parents iff this is the first field set. + self._parent_message_weakref._Modified() + except ReferenceError: + # We can get here if a client has kept a reference to a child object, + # and is now setting a field on it, but the child's parent has been + # garbage-collected. This is not an error. + pass + + +class _OneofListener(_Listener): + """Special listener implementation for setting composite oneof fields.""" + + def __init__(self, parent_message, field): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + field: The descriptor of the field being set in the parent message. + """ + super(_OneofListener, self).__init__(parent_message) + self._field = field + + def Modified(self): + """Also updates the state of the containing oneof in the parent message.""" + try: + self._parent_message_weakref._UpdateOneofState(self._field) + super(_OneofListener, self).Modified() + except ReferenceError: + pass + + +# TODO(robinson): Move elsewhere? This file is getting pretty ridiculous... +# TODO(robinson): Unify error handling of "unknown extension" crap. +# TODO(robinson): Support iteritems()-style iteration over all +# extensions with the "has" bits turned on? +class _ExtensionDict(object): + + """Dict-like container for supporting an indexable "Extensions" + field on proto instances. + + Note that in all cases we expect extension handles to be + FieldDescriptors. + """ + + def __init__(self, extended_message): + """extended_message: Message instance for which we are the Extensions dict. + """ + + self._extended_message = extended_message + + def __getitem__(self, extension_handle): + """Returns the current value of the given extension handle.""" + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + result = self._extended_message._fields.get(extension_handle) + if result is not None: + return result + + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + result = extension_handle._default_constructor(self._extended_message) + elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + result = extension_handle.message_type._concrete_class() + try: + result._SetListener(self._extended_message._listener_for_children) + except ReferenceError: + pass + else: + # Singular scalar -- just return the default without inserting into the + # dict. + return extension_handle.default_value + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + result = self._extended_message._fields.setdefault( + extension_handle, result) + + return result + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + + my_fields = self._extended_message.ListFields() + other_fields = other._extended_message.ListFields() + + # Get rid of non-extension fields. + my_fields = [ field for field in my_fields if field.is_extension ] + other_fields = [ field for field in other_fields if field.is_extension ] + + return my_fields == other_fields + + def __ne__(self, other): + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + # Note that this is only meaningful for non-repeated, scalar extension + # fields. Note also that we may have to call _Modified() when we do + # successfully set a field this way, to set any necssary "has" bits in the + # ancestors of the extended message. + def __setitem__(self, extension_handle, value): + """If extension_handle specifies a non-repeated, scalar extension + field, sets the value of that field. + """ + + _VerifyExtensionHandle(self._extended_message, extension_handle) + + if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or + extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE): + raise TypeError( + 'Cannot assign to extension "%s" because it is a repeated or ' + 'composite type.' % extension_handle.full_name) + + # It's slightly wasteful to lookup the type checker each time, + # but we expect this to be a vanishingly uncommon case anyway. + type_checker = type_checkers.GetTypeChecker(extension_handle) + # pylint: disable=protected-access + self._extended_message._fields[extension_handle] = ( + type_checker.CheckValue(value)) + self._extended_message._Modified() + + def _FindExtensionByName(self, name): + """Tries to find a known extension with the specified name. + + Args: + name: Extension full name. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_name.get(name, None) + + def _FindExtensionByNumber(self, number): + """Tries to find a known extension with the field number. + + Args: + number: Extension field number. + + Returns: + Extension field descriptor. + """ + return self._extended_message._extensions_by_number.get(number, None) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/reflection_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/reflection_test.py new file mode 100644 index 0000000..0306ff4 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/reflection_test.py @@ -0,0 +1,3106 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Unittest for reflection.py, which also indirectly tests the output of the +pure-Python protocol compiler. +""" + +import copy +import gc +import operator +import six +import struct + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +from google.protobuf import descriptor +from google.protobuf import message +from google.protobuf import reflection +from google.protobuf import text_format +from google.protobuf.internal import api_implementation +from google.protobuf.internal import more_extensions_pb2 +from google.protobuf.internal import more_messages_pb2 +from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import wire_format +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks +from google.protobuf.internal import decoder + + +BaseTestCase = testing_refleaks.BaseTestCase + + +class _MiniDecoder(object): + """Decodes a stream of values from a string. + + Once upon a time we actually had a class called decoder.Decoder. Then we + got rid of it during a redesign that made decoding much, much faster overall. + But a couple tests in this file used it to check that the serialized form of + a message was correct. So, this class implements just the methods that were + used by said tests, so that we don't have to rewrite the tests. + """ + + def __init__(self, bytes): + self._bytes = bytes + self._pos = 0 + + def ReadVarint(self): + result, self._pos = decoder._DecodeVarint(self._bytes, self._pos) + return result + + ReadInt32 = ReadVarint + ReadInt64 = ReadVarint + ReadUInt32 = ReadVarint + ReadUInt64 = ReadVarint + + def ReadSInt64(self): + return wire_format.ZigZagDecode(self.ReadVarint()) + + ReadSInt32 = ReadSInt64 + + def ReadFieldNumberAndWireType(self): + return wire_format.UnpackTag(self.ReadVarint()) + + def ReadFloat(self): + result = struct.unpack('\n\ndescriptor\x12%.protobuf_unittest.TestBadIdentifiers\x18\x65 \x01(\t:\x03\x62\x61r:>\n\nreflection\x12%.protobuf_unittest.TestBadIdentifiers\x18\x66 \x01(\t:\x03\x62\x61z:;\n\x07service\x12%.protobuf_unittest.TestBadIdentifiers\x18g \x01(\t:\x03quxB\x03\x90\x01\x01') +) + + +MESSAGE_FIELD_NUMBER = 100 +message = _descriptor.FieldDescriptor( + name='message', full_name='protobuf_unittest.message', index=0, + number=100, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("foo").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DESCRIPTOR_FIELD_NUMBER = 101 +descriptor = _descriptor.FieldDescriptor( + name='descriptor', full_name='protobuf_unittest.descriptor', index=1, + number=101, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("bar").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REFLECTION_FIELD_NUMBER = 102 +reflection = _descriptor.FieldDescriptor( + name='reflection', full_name='protobuf_unittest.reflection', index=2, + number=102, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("baz").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SERVICE_FIELD_NUMBER = 103 +service = _descriptor.FieldDescriptor( + name='service', full_name='protobuf_unittest.service', index=3, + number=103, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("qux").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTBADIDENTIFIERS = _descriptor.Descriptor( + name='TestBadIdentifiers', + full_name='protobuf_unittest.TestBadIdentifiers', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=74, + serialized_end=104, +) + + +_ANOTHERMESSAGE = _descriptor.Descriptor( + name='AnotherMessage', + full_name='protobuf_unittest.AnotherMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=106, + serialized_end=122, +) + +DESCRIPTOR.message_types_by_name['TestBadIdentifiers'] = _TESTBADIDENTIFIERS +DESCRIPTOR.message_types_by_name['AnotherMessage'] = _ANOTHERMESSAGE +DESCRIPTOR.extensions_by_name['message'] = message +DESCRIPTOR.extensions_by_name['descriptor'] = descriptor +DESCRIPTOR.extensions_by_name['reflection'] = reflection +DESCRIPTOR.extensions_by_name['service'] = service +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestBadIdentifiers = _reflection.GeneratedProtocolMessageType('TestBadIdentifiers', (_message.Message,), dict( + DESCRIPTOR = _TESTBADIDENTIFIERS, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestBadIdentifiers) + )) +_sym_db.RegisterMessage(TestBadIdentifiers) + +AnotherMessage = _reflection.GeneratedProtocolMessageType('AnotherMessage', (_message.Message,), dict( + DESCRIPTOR = _ANOTHERMESSAGE, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AnotherMessage) + )) +_sym_db.RegisterMessage(AnotherMessage) + +TestBadIdentifiers.RegisterExtension(message) +TestBadIdentifiers.RegisterExtension(descriptor) +TestBadIdentifiers.RegisterExtension(reflection) +TestBadIdentifiers.RegisterExtension(service) + +DESCRIPTOR._options = None + +_ANOTHERSERVICE = _descriptor.ServiceDescriptor( + name='AnotherService', + full_name='protobuf_unittest.AnotherService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=124, + serialized_end=140, + methods=[ +]) +_sym_db.RegisterServiceDescriptor(_ANOTHERSERVICE) + +DESCRIPTOR.services_by_name['AnotherService'] = _ANOTHERSERVICE + +AnotherService = service_reflection.GeneratedServiceType('AnotherService', (_service.Service,), dict( + DESCRIPTOR = _ANOTHERSERVICE, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + )) + +AnotherService_Stub = service_reflection.GeneratedServiceStubType('AnotherService_Stub', (AnotherService,), dict( + DESCRIPTOR = _ANOTHERSERVICE, + __module__ = 'google.protobuf.internal.test_bad_identifiers_pb2' + )) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/test_util.py b/winvenv/Lib/site-packages/google/protobuf/internal/test_util.py new file mode 100644 index 0000000..a6e34ef --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/test_util.py @@ -0,0 +1,868 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Utilities for Python proto2 tests. + +This is intentionally modeled on C++ code in +//google/protobuf/test_util.*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import numbers +import operator +import os.path + +from google.protobuf import unittest_import_pb2 +from google.protobuf import unittest_pb2 + +try: + long # Python 2 +except NameError: + long = int # Python 3 + + +# Tests whether the given TestAllTypes message is proto2 or not. +# This is used to gate several fields/features that only exist +# for the proto2 version of the message. +def IsProto2(message): + return message.DESCRIPTOR.syntax == "proto2" + + +def SetAllNonLazyFields(message): + """Sets every non-lazy field in the message to a unique value. + + Args: + message: A TestAllTypes instance. + """ + + # + # Optional fields. + # + + message.optional_int32 = 101 + message.optional_int64 = 102 + message.optional_uint32 = 103 + message.optional_uint64 = 104 + message.optional_sint32 = 105 + message.optional_sint64 = 106 + message.optional_fixed32 = 107 + message.optional_fixed64 = 108 + message.optional_sfixed32 = 109 + message.optional_sfixed64 = 110 + message.optional_float = 111 + message.optional_double = 112 + message.optional_bool = True + message.optional_string = u'115' + message.optional_bytes = b'116' + + if IsProto2(message): + message.optionalgroup.a = 117 + message.optional_nested_message.bb = 118 + message.optional_foreign_message.c = 119 + message.optional_import_message.d = 120 + message.optional_public_import_message.e = 126 + + message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ + message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ + if IsProto2(message): + message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ + + message.optional_string_piece = u'124' + message.optional_cord = u'125' + + # + # Repeated fields. + # + + message.repeated_int32.append(201) + message.repeated_int64.append(202) + message.repeated_uint32.append(203) + message.repeated_uint64.append(204) + message.repeated_sint32.append(205) + message.repeated_sint64.append(206) + message.repeated_fixed32.append(207) + message.repeated_fixed64.append(208) + message.repeated_sfixed32.append(209) + message.repeated_sfixed64.append(210) + message.repeated_float.append(211) + message.repeated_double.append(212) + message.repeated_bool.append(True) + message.repeated_string.append(u'215') + message.repeated_bytes.append(b'216') + + if IsProto2(message): + message.repeatedgroup.add().a = 217 + message.repeated_nested_message.add().bb = 218 + message.repeated_foreign_message.add().c = 219 + message.repeated_import_message.add().d = 220 + message.repeated_lazy_message.add().bb = 227 + + message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR) + if IsProto2(message): + message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR) + + message.repeated_string_piece.append(u'224') + message.repeated_cord.append(u'225') + + # Add a second one of each field and set value by index. + message.repeated_int32.append(0) + message.repeated_int64.append(0) + message.repeated_uint32.append(0) + message.repeated_uint64.append(0) + message.repeated_sint32.append(0) + message.repeated_sint64.append(0) + message.repeated_fixed32.append(0) + message.repeated_fixed64.append(0) + message.repeated_sfixed32.append(0) + message.repeated_sfixed64.append(0) + message.repeated_float.append(0) + message.repeated_double.append(0) + message.repeated_bool.append(True) + message.repeated_string.append(u'0') + message.repeated_bytes.append(b'0') + message.repeated_int32[1] = 301 + message.repeated_int64[1] = 302 + message.repeated_uint32[1] = 303 + message.repeated_uint64[1] = 304 + message.repeated_sint32[1] = 305 + message.repeated_sint64[1] = 306 + message.repeated_fixed32[1] = 307 + message.repeated_fixed64[1] = 308 + message.repeated_sfixed32[1] = 309 + message.repeated_sfixed64[1] = 310 + message.repeated_float[1] = 311 + message.repeated_double[1] = 312 + message.repeated_bool[1] = False + message.repeated_string[1] = u'315' + message.repeated_bytes[1] = b'316' + + if IsProto2(message): + message.repeatedgroup.add().a = 317 + message.repeated_nested_message.add().bb = 318 + message.repeated_foreign_message.add().c = 319 + message.repeated_import_message.add().d = 320 + message.repeated_lazy_message.add().bb = 327 + + message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) + message.repeated_nested_enum[1] = unittest_pb2.TestAllTypes.BAZ + message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ) + if IsProto2(message): + message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ) + + message.repeated_string_piece.append(u'324') + message.repeated_cord.append(u'325') + + # + # Fields that have defaults. + # + + if IsProto2(message): + message.default_int32 = 401 + message.default_int64 = 402 + message.default_uint32 = 403 + message.default_uint64 = 404 + message.default_sint32 = 405 + message.default_sint64 = 406 + message.default_fixed32 = 407 + message.default_fixed64 = 408 + message.default_sfixed32 = 409 + message.default_sfixed64 = 410 + message.default_float = 411 + message.default_double = 412 + message.default_bool = False + message.default_string = '415' + message.default_bytes = b'416' + + message.default_nested_enum = unittest_pb2.TestAllTypes.FOO + message.default_foreign_enum = unittest_pb2.FOREIGN_FOO + message.default_import_enum = unittest_import_pb2.IMPORT_FOO + + message.default_string_piece = '424' + message.default_cord = '425' + + message.oneof_uint32 = 601 + message.oneof_nested_message.bb = 602 + message.oneof_string = '603' + message.oneof_bytes = b'604' + + +def SetAllFields(message): + SetAllNonLazyFields(message) + message.optional_lazy_message.bb = 127 + + +def SetAllExtensions(message): + """Sets every extension in the message to a unique value. + + Args: + message: A unittest_pb2.TestAllExtensions instance. + """ + + extensions = message.Extensions + pb2 = unittest_pb2 + import_pb2 = unittest_import_pb2 + + # + # Optional fields. + # + + extensions[pb2.optional_int32_extension] = 101 + extensions[pb2.optional_int64_extension] = 102 + extensions[pb2.optional_uint32_extension] = 103 + extensions[pb2.optional_uint64_extension] = 104 + extensions[pb2.optional_sint32_extension] = 105 + extensions[pb2.optional_sint64_extension] = 106 + extensions[pb2.optional_fixed32_extension] = 107 + extensions[pb2.optional_fixed64_extension] = 108 + extensions[pb2.optional_sfixed32_extension] = 109 + extensions[pb2.optional_sfixed64_extension] = 110 + extensions[pb2.optional_float_extension] = 111 + extensions[pb2.optional_double_extension] = 112 + extensions[pb2.optional_bool_extension] = True + extensions[pb2.optional_string_extension] = u'115' + extensions[pb2.optional_bytes_extension] = b'116' + + extensions[pb2.optionalgroup_extension].a = 117 + extensions[pb2.optional_nested_message_extension].bb = 118 + extensions[pb2.optional_foreign_message_extension].c = 119 + extensions[pb2.optional_import_message_extension].d = 120 + extensions[pb2.optional_public_import_message_extension].e = 126 + extensions[pb2.optional_lazy_message_extension].bb = 127 + + extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ + extensions[pb2.optional_nested_enum_extension] = pb2.TestAllTypes.BAZ + extensions[pb2.optional_foreign_enum_extension] = pb2.FOREIGN_BAZ + extensions[pb2.optional_import_enum_extension] = import_pb2.IMPORT_BAZ + + extensions[pb2.optional_string_piece_extension] = u'124' + extensions[pb2.optional_cord_extension] = u'125' + + # + # Repeated fields. + # + + extensions[pb2.repeated_int32_extension].append(201) + extensions[pb2.repeated_int64_extension].append(202) + extensions[pb2.repeated_uint32_extension].append(203) + extensions[pb2.repeated_uint64_extension].append(204) + extensions[pb2.repeated_sint32_extension].append(205) + extensions[pb2.repeated_sint64_extension].append(206) + extensions[pb2.repeated_fixed32_extension].append(207) + extensions[pb2.repeated_fixed64_extension].append(208) + extensions[pb2.repeated_sfixed32_extension].append(209) + extensions[pb2.repeated_sfixed64_extension].append(210) + extensions[pb2.repeated_float_extension].append(211) + extensions[pb2.repeated_double_extension].append(212) + extensions[pb2.repeated_bool_extension].append(True) + extensions[pb2.repeated_string_extension].append(u'215') + extensions[pb2.repeated_bytes_extension].append(b'216') + + extensions[pb2.repeatedgroup_extension].add().a = 217 + extensions[pb2.repeated_nested_message_extension].add().bb = 218 + extensions[pb2.repeated_foreign_message_extension].add().c = 219 + extensions[pb2.repeated_import_message_extension].add().d = 220 + extensions[pb2.repeated_lazy_message_extension].add().bb = 227 + + extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAR) + extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAR) + extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAR) + + extensions[pb2.repeated_string_piece_extension].append(u'224') + extensions[pb2.repeated_cord_extension].append(u'225') + + # Append a second one of each field. + extensions[pb2.repeated_int32_extension].append(301) + extensions[pb2.repeated_int64_extension].append(302) + extensions[pb2.repeated_uint32_extension].append(303) + extensions[pb2.repeated_uint64_extension].append(304) + extensions[pb2.repeated_sint32_extension].append(305) + extensions[pb2.repeated_sint64_extension].append(306) + extensions[pb2.repeated_fixed32_extension].append(307) + extensions[pb2.repeated_fixed64_extension].append(308) + extensions[pb2.repeated_sfixed32_extension].append(309) + extensions[pb2.repeated_sfixed64_extension].append(310) + extensions[pb2.repeated_float_extension].append(311) + extensions[pb2.repeated_double_extension].append(312) + extensions[pb2.repeated_bool_extension].append(False) + extensions[pb2.repeated_string_extension].append(u'315') + extensions[pb2.repeated_bytes_extension].append(b'316') + + extensions[pb2.repeatedgroup_extension].add().a = 317 + extensions[pb2.repeated_nested_message_extension].add().bb = 318 + extensions[pb2.repeated_foreign_message_extension].add().c = 319 + extensions[pb2.repeated_import_message_extension].add().d = 320 + extensions[pb2.repeated_lazy_message_extension].add().bb = 327 + + extensions[pb2.repeated_nested_enum_extension].append(pb2.TestAllTypes.BAZ) + extensions[pb2.repeated_foreign_enum_extension].append(pb2.FOREIGN_BAZ) + extensions[pb2.repeated_import_enum_extension].append(import_pb2.IMPORT_BAZ) + + extensions[pb2.repeated_string_piece_extension].append(u'324') + extensions[pb2.repeated_cord_extension].append(u'325') + + # + # Fields with defaults. + # + + extensions[pb2.default_int32_extension] = 401 + extensions[pb2.default_int64_extension] = 402 + extensions[pb2.default_uint32_extension] = 403 + extensions[pb2.default_uint64_extension] = 404 + extensions[pb2.default_sint32_extension] = 405 + extensions[pb2.default_sint64_extension] = 406 + extensions[pb2.default_fixed32_extension] = 407 + extensions[pb2.default_fixed64_extension] = 408 + extensions[pb2.default_sfixed32_extension] = 409 + extensions[pb2.default_sfixed64_extension] = 410 + extensions[pb2.default_float_extension] = 411 + extensions[pb2.default_double_extension] = 412 + extensions[pb2.default_bool_extension] = False + extensions[pb2.default_string_extension] = u'415' + extensions[pb2.default_bytes_extension] = b'416' + + extensions[pb2.default_nested_enum_extension] = pb2.TestAllTypes.FOO + extensions[pb2.default_foreign_enum_extension] = pb2.FOREIGN_FOO + extensions[pb2.default_import_enum_extension] = import_pb2.IMPORT_FOO + + extensions[pb2.default_string_piece_extension] = u'424' + extensions[pb2.default_cord_extension] = '425' + + extensions[pb2.oneof_uint32_extension] = 601 + extensions[pb2.oneof_nested_message_extension].bb = 602 + extensions[pb2.oneof_string_extension] = u'603' + extensions[pb2.oneof_bytes_extension] = b'604' + + +def SetAllFieldsAndExtensions(message): + """Sets every field and extension in the message to a unique value. + + Args: + message: A unittest_pb2.TestAllExtensions message. + """ + message.my_int = 1 + message.my_string = 'foo' + message.my_float = 1.0 + message.Extensions[unittest_pb2.my_extension_int] = 23 + message.Extensions[unittest_pb2.my_extension_string] = 'bar' + + +def ExpectAllFieldsAndExtensionsInOrder(serialized): + """Ensures that serialized is the serialization we expect for a message + filled with SetAllFieldsAndExtensions(). (Specifically, ensures that the + serialization is in canonical, tag-number order). + """ + my_extension_int = unittest_pb2.my_extension_int + my_extension_string = unittest_pb2.my_extension_string + expected_strings = [] + message = unittest_pb2.TestFieldOrderings() + message.my_int = 1 # Field 1. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.Extensions[my_extension_int] = 23 # Field 5. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.my_string = 'foo' # Field 11. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.Extensions[my_extension_string] = 'bar' # Field 50. + expected_strings.append(message.SerializeToString()) + message.Clear() + message.my_float = 1.0 + expected_strings.append(message.SerializeToString()) + message.Clear() + expected = b''.join(expected_strings) + + if expected != serialized: + raise ValueError('Expected %r, found %r' % (expected, serialized)) + + +def ExpectAllFieldsSet(test_case, message): + """Check all fields for correct values have after Set*Fields() is called.""" + test_case.assertTrue(message.HasField('optional_int32')) + test_case.assertTrue(message.HasField('optional_int64')) + test_case.assertTrue(message.HasField('optional_uint32')) + test_case.assertTrue(message.HasField('optional_uint64')) + test_case.assertTrue(message.HasField('optional_sint32')) + test_case.assertTrue(message.HasField('optional_sint64')) + test_case.assertTrue(message.HasField('optional_fixed32')) + test_case.assertTrue(message.HasField('optional_fixed64')) + test_case.assertTrue(message.HasField('optional_sfixed32')) + test_case.assertTrue(message.HasField('optional_sfixed64')) + test_case.assertTrue(message.HasField('optional_float')) + test_case.assertTrue(message.HasField('optional_double')) + test_case.assertTrue(message.HasField('optional_bool')) + test_case.assertTrue(message.HasField('optional_string')) + test_case.assertTrue(message.HasField('optional_bytes')) + + if IsProto2(message): + test_case.assertTrue(message.HasField('optionalgroup')) + test_case.assertTrue(message.HasField('optional_nested_message')) + test_case.assertTrue(message.HasField('optional_foreign_message')) + test_case.assertTrue(message.HasField('optional_import_message')) + + test_case.assertTrue(message.optionalgroup.HasField('a')) + test_case.assertTrue(message.optional_nested_message.HasField('bb')) + test_case.assertTrue(message.optional_foreign_message.HasField('c')) + test_case.assertTrue(message.optional_import_message.HasField('d')) + + test_case.assertTrue(message.HasField('optional_nested_enum')) + test_case.assertTrue(message.HasField('optional_foreign_enum')) + if IsProto2(message): + test_case.assertTrue(message.HasField('optional_import_enum')) + + test_case.assertTrue(message.HasField('optional_string_piece')) + test_case.assertTrue(message.HasField('optional_cord')) + + test_case.assertEqual(101, message.optional_int32) + test_case.assertEqual(102, message.optional_int64) + test_case.assertEqual(103, message.optional_uint32) + test_case.assertEqual(104, message.optional_uint64) + test_case.assertEqual(105, message.optional_sint32) + test_case.assertEqual(106, message.optional_sint64) + test_case.assertEqual(107, message.optional_fixed32) + test_case.assertEqual(108, message.optional_fixed64) + test_case.assertEqual(109, message.optional_sfixed32) + test_case.assertEqual(110, message.optional_sfixed64) + test_case.assertEqual(111, message.optional_float) + test_case.assertEqual(112, message.optional_double) + test_case.assertEqual(True, message.optional_bool) + test_case.assertEqual('115', message.optional_string) + test_case.assertEqual(b'116', message.optional_bytes) + + if IsProto2(message): + test_case.assertEqual(117, message.optionalgroup.a) + test_case.assertEqual(118, message.optional_nested_message.bb) + test_case.assertEqual(119, message.optional_foreign_message.c) + test_case.assertEqual(120, message.optional_import_message.d) + test_case.assertEqual(126, message.optional_public_import_message.e) + test_case.assertEqual(127, message.optional_lazy_message.bb) + + test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + test_case.assertEqual(unittest_pb2.FOREIGN_BAZ, + message.optional_foreign_enum) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.optional_import_enum) + + # ----------------------------------------------------------------- + + test_case.assertEqual(2, len(message.repeated_int32)) + test_case.assertEqual(2, len(message.repeated_int64)) + test_case.assertEqual(2, len(message.repeated_uint32)) + test_case.assertEqual(2, len(message.repeated_uint64)) + test_case.assertEqual(2, len(message.repeated_sint32)) + test_case.assertEqual(2, len(message.repeated_sint64)) + test_case.assertEqual(2, len(message.repeated_fixed32)) + test_case.assertEqual(2, len(message.repeated_fixed64)) + test_case.assertEqual(2, len(message.repeated_sfixed32)) + test_case.assertEqual(2, len(message.repeated_sfixed64)) + test_case.assertEqual(2, len(message.repeated_float)) + test_case.assertEqual(2, len(message.repeated_double)) + test_case.assertEqual(2, len(message.repeated_bool)) + test_case.assertEqual(2, len(message.repeated_string)) + test_case.assertEqual(2, len(message.repeated_bytes)) + + if IsProto2(message): + test_case.assertEqual(2, len(message.repeatedgroup)) + test_case.assertEqual(2, len(message.repeated_nested_message)) + test_case.assertEqual(2, len(message.repeated_foreign_message)) + test_case.assertEqual(2, len(message.repeated_import_message)) + test_case.assertEqual(2, len(message.repeated_nested_enum)) + test_case.assertEqual(2, len(message.repeated_foreign_enum)) + if IsProto2(message): + test_case.assertEqual(2, len(message.repeated_import_enum)) + + test_case.assertEqual(2, len(message.repeated_string_piece)) + test_case.assertEqual(2, len(message.repeated_cord)) + + test_case.assertEqual(201, message.repeated_int32[0]) + test_case.assertEqual(202, message.repeated_int64[0]) + test_case.assertEqual(203, message.repeated_uint32[0]) + test_case.assertEqual(204, message.repeated_uint64[0]) + test_case.assertEqual(205, message.repeated_sint32[0]) + test_case.assertEqual(206, message.repeated_sint64[0]) + test_case.assertEqual(207, message.repeated_fixed32[0]) + test_case.assertEqual(208, message.repeated_fixed64[0]) + test_case.assertEqual(209, message.repeated_sfixed32[0]) + test_case.assertEqual(210, message.repeated_sfixed64[0]) + test_case.assertEqual(211, message.repeated_float[0]) + test_case.assertEqual(212, message.repeated_double[0]) + test_case.assertEqual(True, message.repeated_bool[0]) + test_case.assertEqual('215', message.repeated_string[0]) + test_case.assertEqual(b'216', message.repeated_bytes[0]) + + if IsProto2(message): + test_case.assertEqual(217, message.repeatedgroup[0].a) + test_case.assertEqual(218, message.repeated_nested_message[0].bb) + test_case.assertEqual(219, message.repeated_foreign_message[0].c) + test_case.assertEqual(220, message.repeated_import_message[0].d) + test_case.assertEqual(227, message.repeated_lazy_message[0].bb) + + test_case.assertEqual(unittest_pb2.TestAllTypes.BAR, + message.repeated_nested_enum[0]) + test_case.assertEqual(unittest_pb2.FOREIGN_BAR, + message.repeated_foreign_enum[0]) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAR, + message.repeated_import_enum[0]) + + test_case.assertEqual(301, message.repeated_int32[1]) + test_case.assertEqual(302, message.repeated_int64[1]) + test_case.assertEqual(303, message.repeated_uint32[1]) + test_case.assertEqual(304, message.repeated_uint64[1]) + test_case.assertEqual(305, message.repeated_sint32[1]) + test_case.assertEqual(306, message.repeated_sint64[1]) + test_case.assertEqual(307, message.repeated_fixed32[1]) + test_case.assertEqual(308, message.repeated_fixed64[1]) + test_case.assertEqual(309, message.repeated_sfixed32[1]) + test_case.assertEqual(310, message.repeated_sfixed64[1]) + test_case.assertEqual(311, message.repeated_float[1]) + test_case.assertEqual(312, message.repeated_double[1]) + test_case.assertEqual(False, message.repeated_bool[1]) + test_case.assertEqual('315', message.repeated_string[1]) + test_case.assertEqual(b'316', message.repeated_bytes[1]) + + if IsProto2(message): + test_case.assertEqual(317, message.repeatedgroup[1].a) + test_case.assertEqual(318, message.repeated_nested_message[1].bb) + test_case.assertEqual(319, message.repeated_foreign_message[1].c) + test_case.assertEqual(320, message.repeated_import_message[1].d) + test_case.assertEqual(327, message.repeated_lazy_message[1].bb) + + test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.repeated_nested_enum[1]) + test_case.assertEqual(unittest_pb2.FOREIGN_BAZ, + message.repeated_foreign_enum[1]) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.repeated_import_enum[1]) + + # ----------------------------------------------------------------- + + if IsProto2(message): + test_case.assertTrue(message.HasField('default_int32')) + test_case.assertTrue(message.HasField('default_int64')) + test_case.assertTrue(message.HasField('default_uint32')) + test_case.assertTrue(message.HasField('default_uint64')) + test_case.assertTrue(message.HasField('default_sint32')) + test_case.assertTrue(message.HasField('default_sint64')) + test_case.assertTrue(message.HasField('default_fixed32')) + test_case.assertTrue(message.HasField('default_fixed64')) + test_case.assertTrue(message.HasField('default_sfixed32')) + test_case.assertTrue(message.HasField('default_sfixed64')) + test_case.assertTrue(message.HasField('default_float')) + test_case.assertTrue(message.HasField('default_double')) + test_case.assertTrue(message.HasField('default_bool')) + test_case.assertTrue(message.HasField('default_string')) + test_case.assertTrue(message.HasField('default_bytes')) + + test_case.assertTrue(message.HasField('default_nested_enum')) + test_case.assertTrue(message.HasField('default_foreign_enum')) + test_case.assertTrue(message.HasField('default_import_enum')) + + test_case.assertEqual(401, message.default_int32) + test_case.assertEqual(402, message.default_int64) + test_case.assertEqual(403, message.default_uint32) + test_case.assertEqual(404, message.default_uint64) + test_case.assertEqual(405, message.default_sint32) + test_case.assertEqual(406, message.default_sint64) + test_case.assertEqual(407, message.default_fixed32) + test_case.assertEqual(408, message.default_fixed64) + test_case.assertEqual(409, message.default_sfixed32) + test_case.assertEqual(410, message.default_sfixed64) + test_case.assertEqual(411, message.default_float) + test_case.assertEqual(412, message.default_double) + test_case.assertEqual(False, message.default_bool) + test_case.assertEqual('415', message.default_string) + test_case.assertEqual(b'416', message.default_bytes) + + test_case.assertEqual(unittest_pb2.TestAllTypes.FOO, + message.default_nested_enum) + test_case.assertEqual(unittest_pb2.FOREIGN_FOO, + message.default_foreign_enum) + test_case.assertEqual(unittest_import_pb2.IMPORT_FOO, + message.default_import_enum) + + +def GoldenFile(filename): + """Finds the given golden file and returns a file object representing it.""" + + # Search up the directory tree looking for the C++ protobuf source code. + path = '.' + while os.path.exists(path): + if os.path.exists(os.path.join(path, 'src/google/protobuf')): + # Found it. Load the golden file from the testdata directory. + full_path = os.path.join(path, 'src/google/protobuf/testdata', filename) + return open(full_path, 'rb') + path = os.path.join(path, '..') + + # Search internally. + path = '.' + full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata', + filename) + if os.path.exists(full_path): + # Found it. Load the golden file from the testdata directory. + return open(full_path, 'rb') + + raise RuntimeError( + 'Could not find golden files. This test must be run from within the ' + 'protobuf source package so that it can read test data files from the ' + 'C++ source tree.') + + +def GoldenFileData(filename): + """Finds the given golden file and returns its contents.""" + with GoldenFile(filename) as f: + return f.read() + + +def SetAllPackedFields(message): + """Sets every field in the message to a unique value. + + Args: + message: A TestPackedTypes instance. + """ + message.packed_int32.extend([601, 701]) + message.packed_int64.extend([602, 702]) + message.packed_uint32.extend([603, 703]) + message.packed_uint64.extend([604, 704]) + message.packed_sint32.extend([605, 705]) + message.packed_sint64.extend([606, 706]) + message.packed_fixed32.extend([607, 707]) + message.packed_fixed64.extend([608, 708]) + message.packed_sfixed32.extend([609, 709]) + message.packed_sfixed64.extend([610, 710]) + message.packed_float.extend([611.0, 711.0]) + message.packed_double.extend([612.0, 712.0]) + message.packed_bool.extend([True, False]) + message.packed_enum.extend([unittest_pb2.FOREIGN_BAR, + unittest_pb2.FOREIGN_BAZ]) + + +def SetAllPackedExtensions(message): + """Sets every extension in the message to a unique value. + + Args: + message: A unittest_pb2.TestPackedExtensions instance. + """ + extensions = message.Extensions + pb2 = unittest_pb2 + + extensions[pb2.packed_int32_extension].extend([601, 701]) + extensions[pb2.packed_int64_extension].extend([602, 702]) + extensions[pb2.packed_uint32_extension].extend([603, 703]) + extensions[pb2.packed_uint64_extension].extend([604, 704]) + extensions[pb2.packed_sint32_extension].extend([605, 705]) + extensions[pb2.packed_sint64_extension].extend([606, 706]) + extensions[pb2.packed_fixed32_extension].extend([607, 707]) + extensions[pb2.packed_fixed64_extension].extend([608, 708]) + extensions[pb2.packed_sfixed32_extension].extend([609, 709]) + extensions[pb2.packed_sfixed64_extension].extend([610, 710]) + extensions[pb2.packed_float_extension].extend([611.0, 711.0]) + extensions[pb2.packed_double_extension].extend([612.0, 712.0]) + extensions[pb2.packed_bool_extension].extend([True, False]) + extensions[pb2.packed_enum_extension].extend([unittest_pb2.FOREIGN_BAR, + unittest_pb2.FOREIGN_BAZ]) + + +def SetAllUnpackedFields(message): + """Sets every field in the message to a unique value. + + Args: + message: A unittest_pb2.TestUnpackedTypes instance. + """ + message.unpacked_int32.extend([601, 701]) + message.unpacked_int64.extend([602, 702]) + message.unpacked_uint32.extend([603, 703]) + message.unpacked_uint64.extend([604, 704]) + message.unpacked_sint32.extend([605, 705]) + message.unpacked_sint64.extend([606, 706]) + message.unpacked_fixed32.extend([607, 707]) + message.unpacked_fixed64.extend([608, 708]) + message.unpacked_sfixed32.extend([609, 709]) + message.unpacked_sfixed64.extend([610, 710]) + message.unpacked_float.extend([611.0, 711.0]) + message.unpacked_double.extend([612.0, 712.0]) + message.unpacked_bool.extend([True, False]) + message.unpacked_enum.extend([unittest_pb2.FOREIGN_BAR, + unittest_pb2.FOREIGN_BAZ]) + + +class NonStandardInteger(numbers.Integral): + """An integer object that does not subclass int. + + This is used to verify that both C++ and regular proto systems can handle + integer others than int and long and that they handle them in predictable + ways. + + NonStandardInteger is the minimal legal specification for a custom Integral. + As such, it does not support 0 < x < 5 and it is not hashable. + + Note: This is added here instead of relying on numpy or a similar library + with custom integers to limit dependencies. + """ + + def __init__(self, val, error_string_on_conversion=None): + assert isinstance(val, numbers.Integral) + if isinstance(val, NonStandardInteger): + val = val.val + self.val = val + self.error_string_on_conversion = error_string_on_conversion + + def __long__(self): + if self.error_string_on_conversion: + raise RuntimeError(self.error_string_on_conversion) + return long(self.val) + + def __abs__(self): + return NonStandardInteger(operator.abs(self.val)) + + def __add__(self, y): + return NonStandardInteger(operator.add(self.val, y)) + + def __div__(self, y): + return NonStandardInteger(operator.div(self.val, y)) + + def __eq__(self, y): + return operator.eq(self.val, y) + + def __floordiv__(self, y): + return NonStandardInteger(operator.floordiv(self.val, y)) + + def __truediv__(self, y): + return NonStandardInteger(operator.truediv(self.val, y)) + + def __invert__(self): + return NonStandardInteger(operator.invert(self.val)) + + def __mod__(self, y): + return NonStandardInteger(operator.mod(self.val, y)) + + def __mul__(self, y): + return NonStandardInteger(operator.mul(self.val, y)) + + def __neg__(self): + return NonStandardInteger(operator.neg(self.val)) + + def __pos__(self): + return NonStandardInteger(operator.pos(self.val)) + + def __pow__(self, y): + return NonStandardInteger(operator.pow(self.val, y)) + + def __trunc__(self): + return int(self.val) + + def __radd__(self, y): + return NonStandardInteger(operator.add(y, self.val)) + + def __rdiv__(self, y): + return NonStandardInteger(operator.div(y, self.val)) + + def __rmod__(self, y): + return NonStandardInteger(operator.mod(y, self.val)) + + def __rmul__(self, y): + return NonStandardInteger(operator.mul(y, self.val)) + + def __rpow__(self, y): + return NonStandardInteger(operator.pow(y, self.val)) + + def __rfloordiv__(self, y): + return NonStandardInteger(operator.floordiv(y, self.val)) + + def __rtruediv__(self, y): + return NonStandardInteger(operator.truediv(y, self.val)) + + def __lshift__(self, y): + return NonStandardInteger(operator.lshift(self.val, y)) + + def __rshift__(self, y): + return NonStandardInteger(operator.rshift(self.val, y)) + + def __rlshift__(self, y): + return NonStandardInteger(operator.lshift(y, self.val)) + + def __rrshift__(self, y): + return NonStandardInteger(operator.rshift(y, self.val)) + + def __le__(self, y): + if isinstance(y, NonStandardInteger): + y = y.val + return operator.le(self.val, y) + + def __lt__(self, y): + if isinstance(y, NonStandardInteger): + y = y.val + return operator.lt(self.val, y) + + def __and__(self, y): + return NonStandardInteger(operator.and_(self.val, y)) + + def __or__(self, y): + return NonStandardInteger(operator.or_(self.val, y)) + + def __xor__(self, y): + return NonStandardInteger(operator.xor(self.val, y)) + + def __rand__(self, y): + return NonStandardInteger(operator.and_(y, self.val)) + + def __ror__(self, y): + return NonStandardInteger(operator.or_(y, self.val)) + + def __rxor__(self, y): + return NonStandardInteger(operator.xor(y, self.val)) + + def __bool__(self): + return self.val + + def __nonzero__(self): + return self.val + + def __ceil__(self): + return self + + def __floor__(self): + return self + + def __int__(self): + if self.error_string_on_conversion: + raise RuntimeError(self.error_string_on_conversion) + return int(self.val) + + def __round__(self): + return self + + def __repr__(self): + return 'NonStandardInteger(%s)' % self.val diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/testing_refleaks.py b/winvenv/Lib/site-packages/google/protobuf/internal/testing_refleaks.py new file mode 100644 index 0000000..8ce0651 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/testing_refleaks.py @@ -0,0 +1,126 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""A subclass of unittest.TestCase which checks for reference leaks. + +To use: +- Use testing_refleak.BaseTestCase instead of unittest.TestCase +- Configure and compile Python with --with-pydebug + +If sys.gettotalrefcount() is not available (because Python was built without +the Py_DEBUG option), then this module is a no-op and tests will run normally. +""" + +import gc +import sys + +try: + import copy_reg as copyreg #PY26 +except ImportError: + import copyreg + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + + +class LocalTestResult(unittest.TestResult): + """A TestResult which forwards events to a parent object, except for Skips.""" + + def __init__(self, parent_result): + unittest.TestResult.__init__(self) + self.parent_result = parent_result + + def addError(self, test, error): + self.parent_result.addError(test, error) + + def addFailure(self, test, error): + self.parent_result.addFailure(test, error) + + def addSkip(self, test, reason): + pass + + +class ReferenceLeakCheckerTestCase(unittest.TestCase): + """A TestCase which runs tests multiple times, collecting reference counts.""" + + NB_RUNS = 3 + + def run(self, result=None): + # python_message.py registers all Message classes to some pickle global + # registry, which makes the classes immortal. + # We save a copy of this registry, and reset it before we could references. + self._saved_pickle_registry = copyreg.dispatch_table.copy() + + # Run the test twice, to warm up the instance attributes. + super(ReferenceLeakCheckerTestCase, self).run(result=result) + super(ReferenceLeakCheckerTestCase, self).run(result=result) + + oldrefcount = 0 + local_result = LocalTestResult(result) + + refcount_deltas = [] + for _ in range(self.NB_RUNS): + oldrefcount = self._getRefcounts() + super(ReferenceLeakCheckerTestCase, self).run(result=local_result) + newrefcount = self._getRefcounts() + refcount_deltas.append(newrefcount - oldrefcount) + print(refcount_deltas, self) + + try: + self.assertEqual(refcount_deltas, [0] * self.NB_RUNS) + except Exception: # pylint: disable=broad-except + result.addError(self, sys.exc_info()) + + def _getRefcounts(self): + copyreg.dispatch_table.clear() + copyreg.dispatch_table.update(self._saved_pickle_registry) + # It is sometimes necessary to gc.collect() multiple times, to ensure + # that all objects can be collected. + gc.collect() + gc.collect() + gc.collect() + return sys.gettotalrefcount() + + +if hasattr(sys, 'gettotalrefcount'): + BaseTestCase = ReferenceLeakCheckerTestCase + SkipReferenceLeakChecker = unittest.skip + +else: + # When PyDEBUG is not enabled, run the tests normally. + BaseTestCase = unittest.TestCase + + def SkipReferenceLeakChecker(reason): + del reason # Don't skip, so don't need a reason. + def Same(func): + return func + return Same diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/text_encoding_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/text_encoding_test.py new file mode 100644 index 0000000..c7d182c --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/text_encoding_test.py @@ -0,0 +1,72 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Tests for google.protobuf.text_encoding.""" + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import text_encoding + +TEST_VALUES = [ + ("foo\\rbar\\nbaz\\t", + "foo\\rbar\\nbaz\\t", + b"foo\rbar\nbaz\t"), + ("\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", + "\\'full of \\\"sound\\\" and \\\"fury\\\"\\'", + b"'full of \"sound\" and \"fury\"'"), + ("signi\\\\fying\\\\ nothing\\\\", + "signi\\\\fying\\\\ nothing\\\\", + b"signi\\fying\\ nothing\\"), + ("\\010\\t\\n\\013\\014\\r", + "\x08\\t\\n\x0b\x0c\\r", + b"\010\011\012\013\014\015")] + + +class TextEncodingTestCase(unittest.TestCase): + def testCEscape(self): + for escaped, escaped_utf8, unescaped in TEST_VALUES: + self.assertEqual(escaped, + text_encoding.CEscape(unescaped, as_utf8=False)) + self.assertEqual(escaped_utf8, + text_encoding.CEscape(unescaped, as_utf8=True)) + + def testCUnescape(self): + for escaped, escaped_utf8, unescaped in TEST_VALUES: + self.assertEqual(unescaped, text_encoding.CUnescape(escaped)) + self.assertEqual(unescaped, text_encoding.CUnescape(escaped_utf8)) + + +if __name__ == "__main__": + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/text_format_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/text_format_test.py new file mode 100644 index 0000000..237a2d5 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/text_format_test.py @@ -0,0 +1,1656 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.text_format.""" + +__author__ = 'kenton@google.com (Kenton Varda)' + + +import math +import re +import six +import string + +try: + import unittest2 as unittest # PY26, pylint: disable=g-import-not-at-top +except ImportError: + import unittest # pylint: disable=g-import-not-at-top + +from google.protobuf.internal import _parameterized + +from google.protobuf import any_pb2 +from google.protobuf import any_test_pb2 +from google.protobuf import map_unittest_pb2 +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import any_test_pb2 as test_extend_any +from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import test_util +from google.protobuf import descriptor_pool +from google.protobuf import text_format + + +# Low-level nuts-n-bolts tests. +class SimpleTextFormatTests(unittest.TestCase): + + # The members of _QUOTES are formatted into a regexp template that + # expects single characters. Therefore it's an error (in addition to being + # non-sensical in the first place) to try to specify a "quote mark" that is + # more than one character. + def testQuoteMarksAreSingleChars(self): + for quote in text_format._QUOTES: + self.assertEqual(1, len(quote)) + + +# Base class with some common functionality. +class TextFormatBase(unittest.TestCase): + + def ReadGolden(self, golden_filename): + with test_util.GoldenFile(golden_filename) as f: + return (f.readlines() if str is bytes else # PY3 + [golden_line.decode('utf-8') for golden_line in f]) + + def CompareToGoldenFile(self, text, golden_filename): + golden_lines = self.ReadGolden(golden_filename) + self.assertMultiLineEqual(text, ''.join(golden_lines)) + + def CompareToGoldenText(self, text, golden_text): + self.assertEqual(text, golden_text) + + def RemoveRedundantZeros(self, text): + # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove + # these zeros in order to match the golden file. + text = text.replace('e+0','e+').replace('e+0','e+') \ + .replace('e-0','e-').replace('e-0','e-') + # Floating point fields are printed with .0 suffix even if they are + # actualy integer numbers. + text = re.compile(r'\.0$', re.MULTILINE).sub('', text) + return text + + +@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) +class TextFormatTest(TextFormatBase): + + def testPrintExotic(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append(u'\u00fc\ua71f') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'repeated_int64: -9223372036854775808\n' + 'repeated_uint64: 18446744073709551615\n' + 'repeated_double: 123.456\n' + 'repeated_double: 1.23e+22\n' + 'repeated_double: 1.23e-18\n' + 'repeated_string:' + ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' + 'repeated_string: "\\303\\274\\352\\234\\237"\n') + + def testPrintExoticUnicodeSubclass(self, message_module): + + class UnicodeSub(six.text_type): + pass + + message = message_module.TestAllTypes() + message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f')) + self.CompareToGoldenText( + text_format.MessageToString(message), + 'repeated_string: "\\303\\274\\352\\234\\237"\n') + + def testPrintNestedMessageAsOneLine(self, message_module): + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'repeated_nested_message { bb: 42 }') + + def testPrintRepeatedFieldsAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int32.append(1) + message.repeated_int32.append(1) + message.repeated_int32.append(3) + message.repeated_string.append('Google') + message.repeated_string.append('Zurich') + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 ' + 'repeated_string: "Google" repeated_string: "Zurich"') + + def testPrintNestedNewLineInStringAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.optional_string = 'a\nnew\nline' + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'optional_string: "a\\nnew\\nline"') + + def testPrintExoticAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append(u'\u00fc\ua71f') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString( + message, as_one_line=True)), + 'repeated_int64: -9223372036854775808' + ' repeated_uint64: 18446744073709551615' + ' repeated_double: 123.456' + ' repeated_double: 1.23e+22' + ' repeated_double: 1.23e-18' + ' repeated_string: ' + '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""' + ' repeated_string: "\\303\\274\\352\\234\\237"') + + def testRoundTripExoticAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.repeated_int64.append(-9223372036854775808) + message.repeated_uint64.append(18446744073709551615) + message.repeated_double.append(123.456) + message.repeated_double.append(1.23e22) + message.repeated_double.append(1.23e-18) + message.repeated_string.append('\000\001\a\b\f\n\r\t\v\\\'"') + message.repeated_string.append(u'\u00fc\ua71f') + + # Test as_utf8 = False. + wire_text = text_format.MessageToString(message, + as_one_line=True, + as_utf8=False) + parsed_message = message_module.TestAllTypes() + r = text_format.Parse(wire_text, parsed_message) + self.assertIs(r, parsed_message) + self.assertEqual(message, parsed_message) + + # Test as_utf8 = True. + wire_text = text_format.MessageToString(message, + as_one_line=True, + as_utf8=True) + parsed_message = message_module.TestAllTypes() + r = text_format.Parse(wire_text, parsed_message) + self.assertIs(r, parsed_message) + self.assertEqual(message, parsed_message, + '\n%s != %s' % (message, parsed_message)) + + def testPrintRawUtf8String(self, message_module): + message = message_module.TestAllTypes() + message.repeated_string.append(u'\u00fc\ua71f') + text = text_format.MessageToString(message, as_utf8=True) + self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n') + parsed_message = message_module.TestAllTypes() + text_format.Parse(text, parsed_message) + self.assertEqual(message, parsed_message, + '\n%s != %s' % (message, parsed_message)) + + def testPrintFloatFormat(self, message_module): + # Check that float_format argument is passed to sub-message formatting. + message = message_module.NestedTestAllTypes() + # We use 1.25 as it is a round number in binary. The proto 32-bit float + # will not gain additional imprecise digits as a 64-bit Python float and + # show up in its str. 32-bit 1.2 is noisy when extended to 64-bit: + # >>> struct.unpack('f', struct.pack('f', 1.2))[0] + # 1.2000000476837158 + # >>> struct.unpack('f', struct.pack('f', 1.25))[0] + # 1.25 + message.payload.optional_float = 1.25 + # Check rounding at 15 significant digits + message.payload.optional_double = -.000003456789012345678 + # Check no decimal point. + message.payload.repeated_float.append(-5642) + # Check no trailing zeros. + message.payload.repeated_double.append(.000078900) + formatted_fields = ['optional_float: 1.25', + 'optional_double: -3.45678901234568e-6', + 'repeated_float: -5642', 'repeated_double: 7.89e-5'] + text_message = text_format.MessageToString(message, float_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format( + *formatted_fields)) + # as_one_line=True is a separate code branch where float_format is passed. + text_message = text_format.MessageToString(message, + as_one_line=True, + float_format='.15g') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_message), + 'payload {{ {0} {1} {2} {3} }}'.format(*formatted_fields)) + + def testMessageToString(self, message_module): + message = message_module.ForeignMessage() + message.c = 123 + self.assertEqual('c: 123\n', str(message)) + + def testPrintField(self, message_module): + message = message_module.TestAllTypes() + field = message.DESCRIPTOR.fields_by_name['optional_float'] + value = message.optional_float + out = text_format.TextWriter(False) + text_format.PrintField(field, value, out) + self.assertEqual('optional_float: 0.0\n', out.getvalue()) + out.close() + # Test Printer + out = text_format.TextWriter(False) + printer = text_format._Printer(out) + printer.PrintField(field, value) + self.assertEqual('optional_float: 0.0\n', out.getvalue()) + out.close() + + def testPrintFieldValue(self, message_module): + message = message_module.TestAllTypes() + field = message.DESCRIPTOR.fields_by_name['optional_float'] + value = message.optional_float + out = text_format.TextWriter(False) + text_format.PrintFieldValue(field, value, out) + self.assertEqual('0.0', out.getvalue()) + out.close() + # Test Printer + out = text_format.TextWriter(False) + printer = text_format._Printer(out) + printer.PrintFieldValue(field, value) + self.assertEqual('0.0', out.getvalue()) + out.close() + + def testParseAllFields(self, message_module): + message = message_module.TestAllTypes() + test_util.SetAllFields(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = message_module.TestAllTypes() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + def testParseAndMergeUtf8(self, message_module): + message = message_module.TestAllTypes() + test_util.SetAllFields(message) + ascii_text = text_format.MessageToString(message) + ascii_text = ascii_text.encode('utf-8') + + parsed_message = message_module.TestAllTypes() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + parsed_message.Clear() + text_format.Merge(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) + + if six.PY2: + msg2 = message_module.TestAllTypes() + text = (u'optional_string: "café"') + text_format.Merge(text, msg2) + self.assertEqual(msg2.optional_string, u'café') + msg2.Clear() + text_format.Parse(text, msg2) + self.assertEqual(msg2.optional_string, u'café') + + def testParseExotic(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_int64: -9223372036854775808\n' + 'repeated_uint64: 18446744073709551615\n' + 'repeated_double: 123.456\n' + 'repeated_double: 1.23e+22\n' + 'repeated_double: 1.23e-18\n' + 'repeated_string: \n' + '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' + 'repeated_string: "foo" \'corge\' "grault"\n' + 'repeated_string: "\\303\\274\\352\\234\\237"\n' + 'repeated_string: "\\xc3\\xbc"\n' + 'repeated_string: "\xc3\xbc"\n') + text_format.Parse(text, message) + + self.assertEqual(-9223372036854775808, message.repeated_int64[0]) + self.assertEqual(18446744073709551615, message.repeated_uint64[0]) + self.assertEqual(123.456, message.repeated_double[0]) + self.assertEqual(1.23e22, message.repeated_double[1]) + self.assertEqual(1.23e-18, message.repeated_double[2]) + self.assertEqual('\000\001\a\b\f\n\r\t\v\\\'"', message.repeated_string[0]) + self.assertEqual('foocorgegrault', message.repeated_string[1]) + self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2]) + self.assertEqual(u'\u00fc', message.repeated_string[3]) + + def testParseTrailingCommas(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_int64: 100;\n' + 'repeated_int64: 200;\n' + 'repeated_int64: 300,\n' + 'repeated_string: "one",\n' + 'repeated_string: "two";\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_int64[0]) + self.assertEqual(200, message.repeated_int64[1]) + self.assertEqual(300, message.repeated_int64[2]) + self.assertEqual(u'one', message.repeated_string[0]) + self.assertEqual(u'two', message.repeated_string[1]) + + def testParseRepeatedScalarShortFormat(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_int64: [100, 200];\n' + 'repeated_int64: []\n' + 'repeated_int64: 300,\n' + 'repeated_string: ["one", "two"];\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_int64[0]) + self.assertEqual(200, message.repeated_int64[1]) + self.assertEqual(300, message.repeated_int64[2]) + self.assertEqual(u'one', message.repeated_string[0]) + self.assertEqual(u'two', message.repeated_string[1]) + + def testParseRepeatedMessageShortFormat(self, message_module): + message = message_module.TestAllTypes() + text = ('repeated_nested_message: [{bb: 100}, {bb: 200}],\n' + 'repeated_nested_message: {bb: 300}\n' + 'repeated_nested_message [{bb: 400}];\n') + text_format.Parse(text, message) + + self.assertEqual(100, message.repeated_nested_message[0].bb) + self.assertEqual(200, message.repeated_nested_message[1].bb) + self.assertEqual(300, message.repeated_nested_message[2].bb) + self.assertEqual(400, message.repeated_nested_message[3].bb) + + def testParseEmptyText(self, message_module): + message = message_module.TestAllTypes() + text = '' + text_format.Parse(text, message) + self.assertEqual(message_module.TestAllTypes(), message) + + def testParseInvalidUtf8(self, message_module): + message = message_module.TestAllTypes() + text = 'repeated_string: "\\xc3\\xc3"' + with self.assertRaises(text_format.ParseError) as e: + text_format.Parse(text, message) + self.assertEqual(e.exception.GetLine(), 1) + self.assertEqual(e.exception.GetColumn(), 28) + + def testParseSingleWord(self, message_module): + message = message_module.TestAllTypes() + text = 'foo' + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"foo".'), text_format.Parse, text, message) + + def testParseUnknownField(self, message_module): + message = message_module.TestAllTypes() + text = 'unknown_field: 8\n' + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"unknown_field".'), text_format.Parse, text, message) + + def testParseBadEnumValue(self, message_module): + message = message_module.TestAllTypes() + text = 'optional_nested_enum: BARR' + six.assertRaisesRegex(self, text_format.ParseError, + (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value named BARR.'), text_format.Parse, + text, message) + + def testParseBadIntValue(self, message_module): + message = message_module.TestAllTypes() + text = 'optional_int32: bork' + six.assertRaisesRegex(self, text_format.ParseError, + ('1:17 : Couldn\'t parse integer: bork'), + text_format.Parse, text, message) + + def testParseStringFieldUnescape(self, message_module): + message = message_module.TestAllTypes() + text = r'''repeated_string: "\xf\x62" + repeated_string: "\\xf\\x62" + repeated_string: "\\\xf\\\x62" + repeated_string: "\\\\xf\\\\x62" + repeated_string: "\\\\\xf\\\\\x62" + repeated_string: "\x5cx20"''' + + text_format.Parse(text, message) + + SLASH = '\\' + self.assertEqual('\x0fb', message.repeated_string[0]) + self.assertEqual(SLASH + 'xf' + SLASH + 'x62', message.repeated_string[1]) + self.assertEqual(SLASH + '\x0f' + SLASH + 'b', message.repeated_string[2]) + self.assertEqual(SLASH + SLASH + 'xf' + SLASH + SLASH + 'x62', + message.repeated_string[3]) + self.assertEqual(SLASH + SLASH + '\x0f' + SLASH + SLASH + 'b', + message.repeated_string[4]) + self.assertEqual(SLASH + 'x20', message.repeated_string[5]) + + def testMergeDuplicateScalars(self, message_module): + message = message_module.TestAllTypes() + text = ('optional_int32: 42 ' 'optional_int32: 67') + r = text_format.Merge(text, message) + self.assertIs(r, message) + self.assertEqual(67, message.optional_int32) + + def testMergeDuplicateNestedMessageScalars(self, message_module): + message = message_module.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + r = text_format.Merge(text, message) + self.assertTrue(r is message) + self.assertEqual(2, message.optional_nested_message.bb) + + def testParseOneof(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + text_format.Parse(text_format.MessageToString(m), m2) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + def testMergeMultipleOneof(self, message_module): + m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) + m2 = message_module.TestAllTypes() + text_format.Merge(m_string, m2) + self.assertEqual('oneof_string', m2.WhichOneof('oneof_field')) + + def testParseMultipleOneof(self, message_module): + m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"']) + m2 = message_module.TestAllTypes() + with self.assertRaisesRegexp(text_format.ParseError, + ' is specified along with field '): + text_format.Parse(m_string, m2) + + +# These are tests that aren't fundamentally specific to proto2, but are at +# the moment because of differences between the proto2 and proto3 test schemas. +# Ideally the schemas would be made more similar so these tests could pass. +class OnlyWorksWithProto2RightNowTests(TextFormatBase): + + def testPrintAllFieldsPointy(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString( + message, pointy_brackets=True)), + 'text_format_unittest_data_pointy_oneof.txt') + + def testParseGolden(self): + golden_text = '\n'.join(self.ReadGolden( + 'text_format_unittest_data_oneof_implemented.txt')) + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.Parse(golden_text, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testPrintAllFields(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_data_oneof_implemented.txt') + + def testPrintInIndexOrder(self): + message = unittest_pb2.TestFieldOrderings() + # Fields are listed in index order instead of field number. + message.my_string = 'str' + message.my_int = 101 + message.my_float = 111 + message.optional_nested_message.oo = 0 + message.optional_nested_message.bb = 1 + message.Extensions[unittest_pb2.my_extension_string] = 'ext_str0' + # Extensions are listed based on the order of extension number. + # Extension number 12. + message.Extensions[unittest_pb2.TestExtensionOrderings2. + test_ext_orderings2].my_string = 'ext_str2' + # Extension number 13. + message.Extensions[unittest_pb2.TestExtensionOrderings1. + test_ext_orderings1].my_string = 'ext_str1' + # Extension number 14. + message.Extensions[ + unittest_pb2.TestExtensionOrderings2.TestExtensionOrderings3. + test_ext_orderings3].my_string = 'ext_str3' + + # Print in index order. + self.CompareToGoldenText( + self.RemoveRedundantZeros( + text_format.MessageToString(message, use_index_order=True)), + 'my_string: "str"\n' + 'my_int: 101\n' + 'my_float: 111\n' + 'optional_nested_message {\n' + ' oo: 0\n' + ' bb: 1\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n' + ' my_string: "ext_str2"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n' + ' my_string: "ext_str1"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3' + '.test_ext_orderings3] {\n' + ' my_string: "ext_str3"\n' + '}\n' + '[protobuf_unittest.my_extension_string]: "ext_str0"\n') + # By default, print in field number order. + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'my_int: 101\n' + 'my_string: "str"\n' + '[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] {\n' + ' my_string: "ext_str2"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] {\n' + ' my_string: "ext_str1"\n' + '}\n' + '[protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3' + '.test_ext_orderings3] {\n' + ' my_string: "ext_str3"\n' + '}\n' + '[protobuf_unittest.my_extension_string]: "ext_str0"\n' + 'my_float: 111\n' + 'optional_nested_message {\n' + ' bb: 1\n' + ' oo: 0\n' + '}\n') + + def testMergeLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.MergeLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testParseLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data_oneof_implemented.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.ParseLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testPrintMap(self): + message = map_unittest_pb2.TestMap() + + message.map_int32_int32[-123] = -456 + message.map_int64_int64[-2**33] = -2**34 + message.map_uint32_uint32[123] = 456 + message.map_uint64_uint64[2**33] = 2**34 + message.map_string_string['abc'] = '123' + message.map_int32_foreign_message[111].c = 5 + + # Maps are serialized to text format using their underlying repeated + # representation. + self.CompareToGoldenText( + text_format.MessageToString(message), 'map_int32_int32 {\n' + ' key: -123\n' + ' value: -456\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + ' value: -17179869184\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + ' value: 456\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + ' value: 17179869184\n' + '}\n' + 'map_string_string {\n' + ' key: "abc"\n' + ' value: "123"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 5\n' + ' }\n' + '}\n') + + def testMapOrderEnforcement(self): + message = map_unittest_pb2.TestMap() + for letter in string.ascii_uppercase[13:26]: + message.map_string_string[letter] = 'dummy' + for letter in reversed(string.ascii_uppercase[0:13]): + message.map_string_string[letter] = 'dummy' + golden = ''.join(('map_string_string {\n key: "%c"\n value: "dummy"\n}\n' + % (letter,) for letter in string.ascii_uppercase)) + self.CompareToGoldenText(text_format.MessageToString(message), golden) + + # TODO(teboring): In c/137553523, not serializing default value for map entry + # message has been fixed. This test needs to be disabled in order to submit + # that cl. Add this back when c/137553523 has been submitted. + # def testMapOrderSemantics(self): + # golden_lines = self.ReadGolden('map_test_data.txt') + + # message = map_unittest_pb2.TestMap() + # text_format.ParseLines(golden_lines, message) + # candidate = text_format.MessageToString(message) + # # The Python implementation emits "1.0" for the double value that the C++ + # # implementation emits as "1". + # candidate = candidate.replace('1.0', '1', 2) + # candidate = candidate.replace('0.0', '0', 2) + # self.assertMultiLineEqual(candidate, ''.join(golden_lines)) + + +# Tests of proto2-only features (MessageSet, extensions, etc.). +class Proto2Tests(TextFormatBase): + + def testPrintMessageSet(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message), 'message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + + message = message_set_extensions_pb2.TestMessageSet() + ext = message_set_extensions_pb2.message_set_extension3 + message.Extensions[ext].text = 'bar' + self.CompareToGoldenText( + text_format.MessageToString(message), + '[google.protobuf.internal.TestMessageSetExtension3] {\n' + ' text: \"bar\"\n' + '}\n') + + def testPrintMessageSetByFieldNumber(self): + out = text_format.TextWriter(False) + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + text_format.PrintMessage(message, out, use_field_number=True) + self.CompareToGoldenText(out.getvalue(), '1 {\n' + ' 1545008 {\n' + ' 15: 23\n' + ' }\n' + ' 1547769 {\n' + ' 25: \"foo\"\n' + ' }\n' + '}\n') + out.close() + + def testPrintMessageSetAsOneLine(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'message_set {' + ' [protobuf_unittest.TestMessageSetExtension1] {' + ' i: 23' + ' }' + ' [protobuf_unittest.TestMessageSetExtension2] {' + ' str: \"foo\"' + ' }' + ' }') + + def testParseMessageSet(self): + message = unittest_pb2.TestAllTypes() + text = ('repeated_uint64: 1\n' 'repeated_uint64: 2\n') + text_format.Parse(text, message) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + def testExtensionInsideAnyMessage(self): + message = test_extend_any.TestAny() + text = ('value {\n' + ' [type.googleapis.com/google.protobuf.internal.TestAny] {\n' + ' [google.protobuf.internal.TestAnyExtension1.extension1] {\n' + ' i: 10\n' + ' }\n' + ' }\n' + '}\n') + text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default()) + self.CompareToGoldenText( + text_format.MessageToString( + message, descriptor_pool=descriptor_pool.Default()), + text) + + def testParseMessageByFieldNumber(self): + message = unittest_pb2.TestAllTypes() + text = ('34: 1\n' 'repeated_uint64: 2\n') + text_format.Parse(text, message, allow_field_number=True) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('1 {\n' + ' 1545008 {\n' + ' 15: 23\n' + ' }\n' + ' 1547769 {\n' + ' 25: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_field_number=True) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + # Can't parse field number without set allow_field_number=True. + message = unittest_pb2.TestAllTypes() + text = '34:1\n' + six.assertRaisesRegex(self, text_format.ParseError, ( + r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"34".'), text_format.Parse, text, message) + + # Can't parse if field number is not found. + text = '1234:1\n' + six.assertRaisesRegex( + self, + text_format.ParseError, + (r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"1234".'), + text_format.Parse, + text, + message, + allow_field_number=True) + + def testPrintAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_extensions_data.txt') + + def testPrintAllExtensionsPointy(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString( + message, pointy_brackets=True)), + 'text_format_unittest_extensions_data_pointy.txt') + + def testParseGoldenExtensions(self): + golden_text = '\n'.join(self.ReadGolden( + 'text_format_unittest_extensions_data.txt')) + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Parse(golden_text, parsed_message) + + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.assertEqual(message, parsed_message) + + def testParseAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + + def testParseAllowedUnknownExtension(self): + # Skip over unknown extension correctly. + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [unknown_extension] {\n' + ' i: 23\n' + ' bin: "\xe0"' + ' [nested_unknown_ext]: {\n' + ' i: 23\n' + ' x: x\n' + ' test: "test_string"\n' + ' floaty_float: -0.315\n' + ' num: -inf\n' + ' multiline_str: "abc"\n' + ' "def"\n' + ' "xyz."\n' + ' [nested_unknown_ext.ext]: <\n' + ' i: 23\n' + ' i: 24\n' + ' pointfloat: .3\n' + ' test: "test_string"\n' + ' floaty_float: -0.315\n' + ' num: -inf\n' + ' long_string: "test" "test2" \n' + ' >\n' + ' }\n' + ' }\n' + ' [unknown_extension]: 5\n' + ' [unknown_extension_with_number_field] {\n' + ' 1: "some_field"\n' + ' 2: -0.451\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_unknown_extension=True) + golden = 'message_set {\n}\n' + self.CompareToGoldenText(text_format.MessageToString(message), golden) + + # Catch parse errors in unknown extension. + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [unknown_extension] {\n' + ' i:\n' # Missing value. + ' }\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + 'Invalid field value: }', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [unknown_extension] {\n' + ' str: "malformed string\n' # Missing closing quote. + ' }\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + 'Invalid field value: "', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [unknown_extension] {\n' + ' str: "malformed\n multiline\n string\n' + ' }\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + 'Invalid field value: "', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' [malformed_extension] <\n' + ' i: -5\n' + ' \n' # Missing '>' here. + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + '5:1 : Expected ">".', + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + # Don't allow unknown fields with allow_unknown_extension=True. + message = unittest_mset_pb2.TestMessageSetContainer() + malformed = ('message_set {\n' + ' unknown_field: true\n' + '}\n') + six.assertRaisesRegex(self, + text_format.ParseError, + ('2:3 : Message type ' + '"proto2_wireformat_unittest.TestMessageSet" has no' + ' field named "unknown_field".'), + text_format.Parse, + malformed, + message, + allow_unknown_extension=True) + + # Parse known extension correctly. + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message, allow_unknown_extension=True) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEqual(23, message.message_set.Extensions[ext1].i) + self.assertEqual('foo', message.message_set.Extensions[ext2].str) + + def testParseBadIdentifier(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { "bb": 1 }') + with self.assertRaises(text_format.ParseError) as e: + text_format.Parse(text, message) + self.assertEqual(str(e.exception), + '1:27 : Expected identifier or number, got "bb".') + + def testParseBadExtension(self): + message = unittest_pb2.TestAllExtensions() + text = '[unknown_extension]: 8\n' + six.assertRaisesRegex(self, text_format.ParseError, + '1:2 : Extension "unknown_extension" not registered.', + text_format.Parse, text, message) + message = unittest_pb2.TestAllTypes() + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:2 : Message type "protobuf_unittest.TestAllTypes" does not have ' + 'extensions.'), text_format.Parse, text, message) + + def testParseNumericUnknownEnum(self): + message = unittest_pb2.TestAllTypes() + text = 'optional_nested_enum: 100' + six.assertRaisesRegex(self, text_format.ParseError, + (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value with number 100.'), text_format.Parse, + text, message) + + def testMergeDuplicateExtensionScalars(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_int32_extension]: 42 ' + '[protobuf_unittest.optional_int32_extension]: 67') + text_format.Merge(text, message) + self.assertEqual(67, + message.Extensions[unittest_pb2.optional_int32_extension]) + + def testParseDuplicateExtensionScalars(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_int32_extension]: 42 ' + '[protobuf_unittest.optional_int32_extension]: 67') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:96 : Message type "protobuf_unittest.TestAllExtensions" ' + 'should not have multiple ' + '"protobuf_unittest.optional_int32_extension" extensions.'), + text_format.Parse, text, message) + + def testParseDuplicateMessages(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:59 : Message type "protobuf_unittest.TestAllTypes" ' + 'should not have multiple "optional_nested_message" fields.'), + text_format.Parse, text, + message) + + def testParseDuplicateExtensionMessages(self): + message = unittest_pb2.TestAllExtensions() + text = ('[protobuf_unittest.optional_nested_message_extension]: {} ' + '[protobuf_unittest.optional_nested_message_extension]: {}') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:114 : Message type "protobuf_unittest.TestAllExtensions" ' + 'should not have multiple ' + '"protobuf_unittest.optional_nested_message_extension" extensions.'), + text_format.Parse, text, message) + + def testParseDuplicateScalars(self): + message = unittest_pb2.TestAllTypes() + text = ('optional_int32: 42 ' 'optional_int32: 67') + six.assertRaisesRegex(self, text_format.ParseError, ( + '1:36 : Message type "protobuf_unittest.TestAllTypes" should not ' + 'have multiple "optional_int32" fields.'), text_format.Parse, text, + message) + + def testParseGroupNotClosed(self): + message = unittest_pb2.TestAllTypes() + text = 'RepeatedGroup: <' + six.assertRaisesRegex(self, text_format.ParseError, '1:16 : Expected ">".', + text_format.Parse, text, message) + text = 'RepeatedGroup: {' + six.assertRaisesRegex(self, text_format.ParseError, '1:16 : Expected "}".', + text_format.Parse, text, message) + + def testParseEmptyGroup(self): + message = unittest_pb2.TestAllTypes() + text = 'OptionalGroup: {}' + text_format.Parse(text, message) + self.assertTrue(message.HasField('optionalgroup')) + + message.Clear() + + message = unittest_pb2.TestAllTypes() + text = 'OptionalGroup: <>' + text_format.Parse(text, message) + self.assertTrue(message.HasField('optionalgroup')) + + # Maps aren't really proto2-only, but our test schema only has maps for + # proto2. + def testParseMap(self): + text = ('map_int32_int32 {\n' + ' key: -123\n' + ' value: -456\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + ' value: -17179869184\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + ' value: 456\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + ' value: 17179869184\n' + '}\n' + 'map_string_string {\n' + ' key: "abc"\n' + ' value: "123"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 5\n' + ' }\n' + '}\n') + message = map_unittest_pb2.TestMap() + text_format.Parse(text, message) + + self.assertEqual(-456, message.map_int32_int32[-123]) + self.assertEqual(-2**34, message.map_int64_int64[-2**33]) + self.assertEqual(456, message.map_uint32_uint32[123]) + self.assertEqual(2**34, message.map_uint64_uint64[2**33]) + self.assertEqual('123', message.map_string_string['abc']) + self.assertEqual(5, message.map_int32_foreign_message[111].c) + + +class Proto3Tests(unittest.TestCase): + + def testPrintMessageExpandAny(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + descriptor_pool=descriptor_pool.Default()), + 'any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + + def testTopAnyMessage(self): + packed_msg = unittest_pb2.OneString() + msg = any_pb2.Any() + msg.Pack(packed_msg) + text = text_format.MessageToString(msg) + other_msg = text_format.Parse(text, any_pb2.Any()) + self.assertEqual(msg, other_msg) + + def testPrintMessageExpandAnyRepeated(self): + packed_message = unittest_pb2.OneString() + message = any_test_pb2.TestAny() + packed_message.data = 'string0' + message.repeated_any_value.add().Pack(packed_message) + packed_message.data = 'string1' + message.repeated_any_value.add().Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message), + 'repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string0"\n' + ' }\n' + '}\n' + 'repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string1"\n' + ' }\n' + '}\n') + + def testPrintMessageExpandAnyDescriptorPoolMissingType(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + empty_pool = descriptor_pool.DescriptorPool() + self.assertEqual( + text_format.MessageToString(message, descriptor_pool=empty_pool), + 'any_value {\n' + ' type_url: "type.googleapis.com/protobuf_unittest.OneString"\n' + ' value: "\\n\\006string"\n' + '}\n') + + def testPrintMessageExpandAnyPointyBrackets(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + pointy_brackets=True), + 'any_value <\n' + ' [type.googleapis.com/protobuf_unittest.OneString] <\n' + ' data: "string"\n' + ' >\n' + '>\n') + + def testPrintMessageExpandAnyAsOneLine(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + as_one_line=True), + 'any_value {' + ' [type.googleapis.com/protobuf_unittest.OneString]' + ' { data: "string" } ' + '}') + + def testPrintMessageExpandAnyAsOneLinePointyBrackets(self): + packed_message = unittest_pb2.OneString() + packed_message.data = 'string' + message = any_test_pb2.TestAny() + message.any_value.Pack(packed_message) + self.assertEqual( + text_format.MessageToString(message, + as_one_line=True, + pointy_brackets=True, + descriptor_pool=descriptor_pool.Default()), + 'any_value <' + ' [type.googleapis.com/protobuf_unittest.OneString]' + ' < data: "string" > ' + '>') + + def testUnknownEnums(self): + message = unittest_proto3_arena_pb2.TestAllTypes() + message2 = unittest_proto3_arena_pb2.TestAllTypes() + message.optional_nested_enum = 999 + text_string = text_format.MessageToString(message) + text_format.Parse(text_string, message2) + self.assertEqual(999, message2.optional_nested_enum) + + def testMergeExpandedAny(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + message.Clear() + text_format.Parse(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + + def testMergeExpandedAnyRepeated(self): + message = any_test_pb2.TestAny() + text = ('repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string0"\n' + ' }\n' + '}\n' + 'repeated_any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string1"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.repeated_any_value[0].Unpack(packed_message) + self.assertEqual('string0', packed_message.data) + message.repeated_any_value[1].Unpack(packed_message) + self.assertEqual('string1', packed_message.data) + + def testMergeExpandedAnyPointyBrackets(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] <\n' + ' data: "string"\n' + ' >\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + + def testMergeAlternativeUrl(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.otherapi.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + self.assertEqual('type.otherapi.com/protobuf_unittest.OneString', + message.any_value.type_url) + + def testMergeExpandedAnyDescriptorPoolMissingType(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n' + ' }\n' + '}\n') + with self.assertRaises(text_format.ParseError) as e: + empty_pool = descriptor_pool.DescriptorPool() + text_format.Merge(text, message, descriptor_pool=empty_pool) + self.assertEqual( + str(e.exception), + 'Type protobuf_unittest.OneString not found in descriptor pool') + + def testMergeUnexpandedAny(self): + text = ('any_value {\n' + ' type_url: "type.googleapis.com/protobuf_unittest.OneString"\n' + ' value: "\\n\\006string"\n' + '}\n') + message = any_test_pb2.TestAny() + text_format.Merge(text, message) + packed_message = unittest_pb2.OneString() + message.any_value.Unpack(packed_message) + self.assertEqual('string', packed_message.data) + + def testMergeMissingAnyEndToken(self): + message = any_test_pb2.TestAny() + text = ('any_value {\n' + ' [type.googleapis.com/protobuf_unittest.OneString] {\n' + ' data: "string"\n') + with self.assertRaises(text_format.ParseError) as e: + text_format.Merge(text, message) + self.assertEqual(str(e.exception), '3:11 : Expected "}".') + + +class TokenizerTest(unittest.TestCase): + + def testSimpleTokenCases(self): + text = ('identifier1:"string1"\n \n\n' + 'identifier2 : \n \n123 \n identifier3 :\'string\'\n' + 'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n' + 'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n' + 'ID9: 22 ID10: -111111111111111111 ID11: -22\n' + 'ID12: 2222222222222222222 ID13: 1.23456f ID14: 1.2e+2f ' + 'false_bool: 0 true_BOOL:t \n true_bool1: 1 false_BOOL1:f ' + 'False_bool: False True_bool: True X:iNf Y:-inF Z:nAN') + tokenizer = text_format.Tokenizer(text.splitlines()) + methods = [(tokenizer.ConsumeIdentifier, 'identifier1'), ':', + (tokenizer.ConsumeString, 'string1'), + (tokenizer.ConsumeIdentifier, 'identifier2'), ':', + (tokenizer.ConsumeInteger, 123), + (tokenizer.ConsumeIdentifier, 'identifier3'), ':', + (tokenizer.ConsumeString, 'string'), + (tokenizer.ConsumeIdentifier, 'identifiER_4'), ':', + (tokenizer.ConsumeFloat, 1.1e+2), + (tokenizer.ConsumeIdentifier, 'ID5'), ':', + (tokenizer.ConsumeFloat, -0.23), + (tokenizer.ConsumeIdentifier, 'ID6'), ':', + (tokenizer.ConsumeString, 'aaaa\'bbbb'), + (tokenizer.ConsumeIdentifier, 'ID7'), ':', + (tokenizer.ConsumeString, 'aa\"bb'), + (tokenizer.ConsumeIdentifier, 'ID8'), ':', '{', + (tokenizer.ConsumeIdentifier, 'A'), ':', + (tokenizer.ConsumeFloat, float('inf')), + (tokenizer.ConsumeIdentifier, 'B'), ':', + (tokenizer.ConsumeFloat, -float('inf')), + (tokenizer.ConsumeIdentifier, 'C'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'D'), ':', + (tokenizer.ConsumeBool, False), '}', + (tokenizer.ConsumeIdentifier, 'ID9'), ':', + (tokenizer.ConsumeInteger, 22), + (tokenizer.ConsumeIdentifier, 'ID10'), ':', + (tokenizer.ConsumeInteger, -111111111111111111), + (tokenizer.ConsumeIdentifier, 'ID11'), ':', + (tokenizer.ConsumeInteger, -22), + (tokenizer.ConsumeIdentifier, 'ID12'), ':', + (tokenizer.ConsumeInteger, 2222222222222222222), + (tokenizer.ConsumeIdentifier, 'ID13'), ':', + (tokenizer.ConsumeFloat, 1.23456), + (tokenizer.ConsumeIdentifier, 'ID14'), ':', + (tokenizer.ConsumeFloat, 1.2e+2), + (tokenizer.ConsumeIdentifier, 'false_bool'), ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'true_BOOL'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'true_bool1'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'false_BOOL1'), ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'False_bool'), ':', + (tokenizer.ConsumeBool, False), + (tokenizer.ConsumeIdentifier, 'True_bool'), ':', + (tokenizer.ConsumeBool, True), + (tokenizer.ConsumeIdentifier, 'X'), ':', + (tokenizer.ConsumeFloat, float('inf')), + (tokenizer.ConsumeIdentifier, 'Y'), ':', + (tokenizer.ConsumeFloat, float('-inf')), + (tokenizer.ConsumeIdentifier, 'Z'), ':', + (tokenizer.ConsumeFloat, float('nan'))] + + i = 0 + while not tokenizer.AtEnd(): + m = methods[i] + if isinstance(m, str): + token = tokenizer.token + self.assertEqual(token, m) + tokenizer.NextToken() + elif isinstance(m[1], float) and math.isnan(m[1]): + self.assertTrue(math.isnan(m[0]())) + else: + self.assertEqual(m[1], m[0]()) + i += 1 + + def testConsumeAbstractIntegers(self): + # This test only tests the failures in the integer parsing methods as well + # as the '0' special cases. + int64_max = (1 << 63) - 1 + uint32_max = (1 << 32) - 1 + text = '-1 %d %d' % (uint32_max + 1, int64_max + 1) + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(-1, tokenizer.ConsumeInteger()) + + self.assertEqual(uint32_max + 1, tokenizer.ConsumeInteger()) + + self.assertEqual(int64_max + 1, tokenizer.ConsumeInteger()) + self.assertTrue(tokenizer.AtEnd()) + + text = '-0 0 0 1.2' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(0, tokenizer.ConsumeInteger()) + self.assertEqual(True, tokenizer.TryConsumeInteger()) + self.assertEqual(False, tokenizer.TryConsumeInteger()) + with self.assertRaises(text_format.ParseError): + tokenizer.ConsumeInteger() + self.assertEqual(1.2, tokenizer.ConsumeFloat()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeIntegers(self): + # This test only tests the failures in the integer parsing methods as well + # as the '0' special cases. + int64_max = (1 << 63) - 1 + uint32_max = (1 << 32) - 1 + text = '-1 %d %d' % (uint32_max + 1, int64_max + 1) + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, + text_format._ConsumeUint32, tokenizer) + self.assertRaises(text_format.ParseError, + text_format._ConsumeUint64, tokenizer) + self.assertEqual(-1, text_format._ConsumeInt32(tokenizer)) + + self.assertRaises(text_format.ParseError, + text_format._ConsumeUint32, tokenizer) + self.assertRaises(text_format.ParseError, + text_format._ConsumeInt32, tokenizer) + self.assertEqual(uint32_max + 1, text_format._ConsumeInt64(tokenizer)) + + self.assertRaises(text_format.ParseError, + text_format._ConsumeInt64, tokenizer) + self.assertEqual(int64_max + 1, text_format._ConsumeUint64(tokenizer)) + self.assertTrue(tokenizer.AtEnd()) + + text = '-0 -0 0 0' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertEqual(0, text_format._ConsumeUint32(tokenizer)) + self.assertEqual(0, text_format._ConsumeUint64(tokenizer)) + self.assertEqual(0, text_format._ConsumeUint32(tokenizer)) + self.assertEqual(0, text_format._ConsumeUint64(tokenizer)) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeByteString(self): + text = '"string1\'' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = 'string1"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\xt"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + text = '\n"\\x"' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString) + + def testConsumeBool(self): + text = 'not-a-bool' + tokenizer = text_format.Tokenizer(text.splitlines()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool) + + def testSkipComment(self): + tokenizer = text_format.Tokenizer('# some comment'.splitlines()) + self.assertTrue(tokenizer.AtEnd()) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeComment) + + def testConsumeComment(self): + tokenizer = text_format.Tokenizer('# some comment'.splitlines(), + skip_comments=False) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual('# some comment', tokenizer.ConsumeComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeTwoComments(self): + text = '# some comment\n# another comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertEqual('# some comment', tokenizer.ConsumeComment()) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual('# another comment', tokenizer.ConsumeComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeTrailingComment(self): + text = 'some_number: 4\n# some comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertRaises(text_format.ParseError, tokenizer.ConsumeComment) + + self.assertEqual('some_number', tokenizer.ConsumeIdentifier()) + self.assertEqual(tokenizer.token, ':') + tokenizer.NextToken() + self.assertRaises(text_format.ParseError, tokenizer.ConsumeComment) + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertFalse(tokenizer.AtEnd()) + + self.assertEqual('# some comment', tokenizer.ConsumeComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeLineComment(self): + tokenizer = text_format.Tokenizer('# some comment'.splitlines(), + skip_comments=False) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual((False, '# some comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeTwoLineComments(self): + text = '# some comment\n# another comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertEqual((False, '# some comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertFalse(tokenizer.AtEnd()) + self.assertEqual((False, '# another comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testConsumeAndCheckTrailingComment(self): + text = 'some_number: 4 # some comment' # trailing comment on the same line + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertRaises(text_format.ParseError, + tokenizer.ConsumeCommentOrTrailingComment) + + self.assertEqual('some_number', tokenizer.ConsumeIdentifier()) + self.assertEqual(tokenizer.token, ':') + tokenizer.NextToken() + self.assertRaises(text_format.ParseError, + tokenizer.ConsumeCommentOrTrailingComment) + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertFalse(tokenizer.AtEnd()) + + self.assertEqual((True, '# some comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + def testHashinComment(self): + text = 'some_number: 4 # some comment # not a new comment' + tokenizer = text_format.Tokenizer(text.splitlines(), skip_comments=False) + self.assertEqual('some_number', tokenizer.ConsumeIdentifier()) + self.assertEqual(tokenizer.token, ':') + tokenizer.NextToken() + self.assertEqual(4, tokenizer.ConsumeInteger()) + self.assertEqual((True, '# some comment # not a new comment'), + tokenizer.ConsumeCommentOrTrailingComment()) + self.assertTrue(tokenizer.AtEnd()) + + +# Tests for pretty printer functionality. +@_parameterized.parameters((unittest_pb2), (unittest_proto3_arena_pb2)) +class PrettyPrinterTest(TextFormatBase): + + def testPrettyPrintNoMatch(self, message_module): + + def printer(message, indent, as_one_line): + del message, indent, as_one_line + return None + + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'repeated_nested_message { bb: 42 }') + + def testPrettyPrintOneLine(self, message_module): + + def printer(m, indent, as_one_line): + del indent, as_one_line + if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR: + return 'My lucky number is %s' % m.bb + + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'repeated_nested_message { My lucky number is 42 }') + + def testPrettyPrintMultiLine(self, message_module): + + def printer(m, indent, as_one_line): + if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR: + line_deliminator = (' ' if as_one_line else '\n') + ' ' * indent + return 'My lucky number is:%s%s' % (line_deliminator, m.bb) + return None + + message = message_module.TestAllTypes() + msg = message.repeated_nested_message.add() + msg.bb = 42 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'repeated_nested_message { My lucky number is: 42 }') + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=False, message_formatter=printer), + 'repeated_nested_message {\n My lucky number is:\n 42\n}\n') + + def testPrettyPrintEntireMessage(self, message_module): + + def printer(m, indent, as_one_line): + del indent, as_one_line + if m.DESCRIPTOR == message_module.TestAllTypes.DESCRIPTOR: + return 'The is the message!' + return None + + message = message_module.TestAllTypes() + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=False, message_formatter=printer), + 'The is the message!\n') + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + 'The is the message!') + + def testPrettyPrintMultipleParts(self, message_module): + + def printer(m, indent, as_one_line): + del indent, as_one_line + if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR: + return 'My lucky number is %s' % m.bb + return None + + message = message_module.TestAllTypes() + message.optional_int32 = 61 + msg = message.repeated_nested_message.add() + msg.bb = 42 + msg = message.repeated_nested_message.add() + msg.bb = 99 + msg = message.optional_nested_message + msg.bb = 1 + self.CompareToGoldenText( + text_format.MessageToString( + message, as_one_line=True, message_formatter=printer), + ('optional_int32: 61 ' + 'optional_nested_message { My lucky number is 1 } ' + 'repeated_nested_message { My lucky number is 42 } ' + 'repeated_nested_message { My lucky number is 99 }')) + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/type_checkers.py b/winvenv/Lib/site-packages/google/protobuf/internal/type_checkers.py new file mode 100644 index 0000000..4a76cd4 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/type_checkers.py @@ -0,0 +1,353 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides type checking routines. + +This module defines type checking utilities in the forms of dictionaries: + +VALUE_CHECKERS: A dictionary of field types and a value validation object. +TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing + function. +TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization + function. +FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their + coresponding wire types. +TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization + function. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import numbers +import six + +if six.PY3: + long = int + +from google.protobuf.internal import api_implementation +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.internal import wire_format +from google.protobuf import descriptor + +_FieldDescriptor = descriptor.FieldDescriptor + +def SupportsOpenEnums(field_descriptor): + return field_descriptor.containing_type.syntax == "proto3" + +def GetTypeChecker(field): + """Returns a type checker for a message field of the specified types. + + Args: + field: FieldDescriptor object for this field. + + Returns: + An instance of TypeChecker which can be used to verify the types + of values assigned to a field of the specified type. + """ + if (field.cpp_type == _FieldDescriptor.CPPTYPE_STRING and + field.type == _FieldDescriptor.TYPE_STRING): + return UnicodeValueChecker() + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + if SupportsOpenEnums(field): + # When open enums are supported, any int32 can be assigned. + return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32] + else: + return EnumValueChecker(field.enum_type) + return _VALUE_CHECKERS[field.cpp_type] + + +# None of the typecheckers below make any attempt to guard against people +# subclassing builtin types and doing weird things. We're not trying to +# protect against malicious clients here, just people accidentally shooting +# themselves in the foot in obvious ways. + +class TypeChecker(object): + + """Type checker used to catch type errors as early as possible + when the client is setting scalar fields in protocol messages. + """ + + def __init__(self, *acceptable_types): + self._acceptable_types = acceptable_types + + def CheckValue(self, proposed_value): + """Type check the provided value and return it. + + The returned value might have been normalized to another type. + """ + if not isinstance(proposed_value, self._acceptable_types): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), self._acceptable_types)) + raise TypeError(message) + return proposed_value + + +class TypeCheckerWithDefault(TypeChecker): + + def __init__(self, default_value, *acceptable_types): + TypeChecker.__init__(self, acceptable_types) + self._default_value = default_value + + def DefaultValue(self): + return self._default_value + + +# IntValueChecker and its subclasses perform integer type-checks +# and bounds-checks. +class IntValueChecker(object): + + """Checker used for integer fields. Performs type-check and range check.""" + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, numbers.Integral): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), six.integer_types)) + raise TypeError(message) + if not self._MIN <= int(proposed_value) <= self._MAX: + raise ValueError('Value out of range: %d' % proposed_value) + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + proposed_value = self._TYPE(proposed_value) + return proposed_value + + def DefaultValue(self): + return 0 + + +class EnumValueChecker(object): + + """Checker used for enum fields. Performs type-check and range check.""" + + def __init__(self, enum_type): + self._enum_type = enum_type + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, numbers.Integral): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), six.integer_types)) + raise TypeError(message) + if int(proposed_value) not in self._enum_type.values_by_number: + raise ValueError('Unknown enum value: %d' % proposed_value) + return proposed_value + + def DefaultValue(self): + return self._enum_type.values[0].number + + +class UnicodeValueChecker(object): + + """Checker used for string fields. + + Always returns a unicode value, even if the input is of type str. + """ + + def CheckValue(self, proposed_value): + if not isinstance(proposed_value, (bytes, six.text_type)): + message = ('%.1024r has type %s, but expected one of: %s' % + (proposed_value, type(proposed_value), (bytes, six.text_type))) + raise TypeError(message) + + # If the value is of type 'bytes' make sure that it is valid UTF-8 data. + if isinstance(proposed_value, bytes): + try: + proposed_value = proposed_value.decode('utf-8') + except UnicodeDecodeError: + raise ValueError('%.1024r has type bytes, but isn\'t valid UTF-8 ' + 'encoding. Non-UTF-8 strings must be converted to ' + 'unicode objects before being added.' % + (proposed_value)) + return proposed_value + + def DefaultValue(self): + return u"" + + +class Int32ValueChecker(IntValueChecker): + # We're sure to use ints instead of longs here since comparison may be more + # efficient. + _MIN = -2147483648 + _MAX = 2147483647 + _TYPE = int + + +class Uint32ValueChecker(IntValueChecker): + _MIN = 0 + _MAX = (1 << 32) - 1 + _TYPE = int + + +class Int64ValueChecker(IntValueChecker): + _MIN = -(1 << 63) + _MAX = (1 << 63) - 1 + _TYPE = long + + +class Uint64ValueChecker(IntValueChecker): + _MIN = 0 + _MAX = (1 << 64) - 1 + _TYPE = long + + +# Type-checkers for all scalar CPPTYPEs. +_VALUE_CHECKERS = { + _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), + _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), + _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), + _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), + _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault( + 0.0, numbers.Real), + _FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault( + 0.0, numbers.Real), + _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault( + False, bool, numbers.Integral), + _FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes), + } + + +# Map from field type to a function F, such that F(field_num, value) +# gives the total byte size for a value of the given type. This +# byte size includes tag information and any other additional space +# associated with serializing "value". +TYPE_TO_BYTE_SIZE_FN = { + _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize, + _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize, + _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize, + _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize, + _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize, + _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize, + _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize, + _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize, + _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize, + _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize, + _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize, + _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize, + _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize, + _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize, + _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize, + _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize, + _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize, + _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize + } + + +# Maps from field types to encoder constructors. +TYPE_TO_ENCODER = { + _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder, + _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder, + _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder, + _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder, + _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder, + _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder, + _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder, + _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder, + _FieldDescriptor.TYPE_STRING: encoder.StringEncoder, + _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder, + _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder, + _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder, + _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder, + _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder, + _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder, + _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder, + _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder, + _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder, + } + + +# Maps from field types to sizer constructors. +TYPE_TO_SIZER = { + _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer, + _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer, + _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer, + _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer, + _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer, + _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer, + _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer, + _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer, + _FieldDescriptor.TYPE_STRING: encoder.StringSizer, + _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer, + _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer, + _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer, + _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer, + _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer, + _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer, + _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer, + _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer, + _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer, + } + + +# Maps from field type to a decoder constructor. +TYPE_TO_DECODER = { + _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder, + _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder, + _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder, + _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder, + _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder, + _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder, + _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder, + _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder, + _FieldDescriptor.TYPE_STRING: decoder.StringDecoder, + _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder, + _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder, + _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder, + _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder, + _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder, + _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder, + _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder, + _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder, + _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder, + } + +# Maps from field type to expected wiretype. +FIELD_TYPE_TO_WIRE_TYPE = { + _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_STRING: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP, + _FieldDescriptor.TYPE_MESSAGE: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_BYTES: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT, + } diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/unknown_fields_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/unknown_fields_test.py new file mode 100644 index 0000000..8b7de2e --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/unknown_fields_test.py @@ -0,0 +1,336 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for preservation of unknown fields in the pure Python implementation.""" + +__author__ = 'bohdank@google.com (Bohdan Koval)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 +from google.protobuf.internal import api_implementation +from google.protobuf.internal import encoder +from google.protobuf.internal import message_set_extensions_pb2 +from google.protobuf.internal import missing_enum_values_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import testing_refleaks +from google.protobuf.internal import type_checkers + + +BaseTestCase = testing_refleaks.BaseTestCase + + +# CheckUnknownField() cannot be used by the C++ implementation because +# some protect members are called. It is not a behavior difference +# for python and C++ implementation. +def SkipCheckUnknownFieldIfCppImplementation(func): + return unittest.skipIf( + api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, + 'Addtional test for pure python involved protect members')(func) + + +class UnknownFieldsTest(BaseTestCase): + + def setUp(self): + self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.all_fields = unittest_pb2.TestAllTypes() + test_util.SetAllFields(self.all_fields) + self.all_fields_data = self.all_fields.SerializeToString() + self.empty_message = unittest_pb2.TestEmptyMessage() + self.empty_message.ParseFromString(self.all_fields_data) + + def testSerialize(self): + data = self.empty_message.SerializeToString() + + # Don't use assertEqual because we don't want to dump raw binary data to + # stdout. + self.assertTrue(data == self.all_fields_data) + + def expectSerializeProto3(self, preserve): + message = unittest_proto3_arena_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + if preserve: + self.assertEqual(self.all_fields_data, message.SerializeToString()) + else: + self.assertEqual(0, len(message.SerializeToString())) + + def testSerializeProto3(self): + # Verify that proto3 unknown fields behavior. + default_preserve = (api_implementation + .GetPythonProto3PreserveUnknownsDefault()) + self.expectSerializeProto3(default_preserve) + api_implementation.SetPythonProto3PreserveUnknownsDefault( + not default_preserve) + self.expectSerializeProto3(not default_preserve) + api_implementation.SetPythonProto3PreserveUnknownsDefault(default_preserve) + + def testByteSize(self): + self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize()) + + def testListFields(self): + # Make sure ListFields doesn't return unknown fields. + self.assertEqual(0, len(self.empty_message.ListFields())) + + def testSerializeMessageSetWireFormatUnknownExtension(self): + # Create a message using the message set wire format with an unknown + # message. + raw = unittest_mset_pb2.RawMessageSet() + + # Add an unknown extension. + item = raw.item.add() + item.type_id = 98418603 + message1 = message_set_extensions_pb2.TestMessageSetExtension1() + message1.i = 12345 + item.message = message1.SerializeToString() + + serialized = raw.SerializeToString() + + # Parse message using the message set wire format. + proto = message_set_extensions_pb2.TestMessageSet() + proto.MergeFromString(serialized) + + # Verify that the unknown extension is serialized unchanged + reserialized = proto.SerializeToString() + new_raw = unittest_mset_pb2.RawMessageSet() + new_raw.MergeFromString(reserialized) + self.assertEqual(raw, new_raw) + + def testEquals(self): + message = unittest_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + self.assertEqual(self.empty_message, message) + + self.all_fields.ClearField('optional_string') + message.ParseFromString(self.all_fields.SerializeToString()) + self.assertNotEqual(self.empty_message, message) + + def testDiscardUnknownFields(self): + self.empty_message.DiscardUnknownFields() + self.assertEqual(b'', self.empty_message.SerializeToString()) + # Test message field and repeated message field. + message = unittest_pb2.TestAllTypes() + other_message = unittest_pb2.TestAllTypes() + other_message.optional_string = 'discard' + message.optional_nested_message.ParseFromString( + other_message.SerializeToString()) + message.repeated_nested_message.add().ParseFromString( + other_message.SerializeToString()) + self.assertNotEqual( + b'', message.optional_nested_message.SerializeToString()) + self.assertNotEqual( + b'', message.repeated_nested_message[0].SerializeToString()) + message.DiscardUnknownFields() + self.assertEqual(b'', message.optional_nested_message.SerializeToString()) + self.assertEqual( + b'', message.repeated_nested_message[0].SerializeToString()) + + +class UnknownFieldsAccessorsTest(BaseTestCase): + + def setUp(self): + self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.all_fields = unittest_pb2.TestAllTypes() + test_util.SetAllFields(self.all_fields) + self.all_fields_data = self.all_fields.SerializeToString() + self.empty_message = unittest_pb2.TestEmptyMessage() + self.empty_message.ParseFromString(self.all_fields_data) + + # CheckUnknownField() is an additional Pure Python check which checks + # a detail of unknown fields. It cannot be used by the C++ + # implementation because some protect members are called. + # The test is added for historical reasons. It is not necessary as + # serialized string is checked. + + def CheckUnknownField(self, name, expected_value): + field_descriptor = self.descriptor.fields_by_name[name] + wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] + field_tag = encoder.TagBytes(field_descriptor.number, wire_type) + result_dict = {} + for tag_bytes, value in self.empty_message._unknown_fields: + if tag_bytes == field_tag: + decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes][0] + decoder(value, 0, len(value), self.all_fields, result_dict) + self.assertEqual(expected_value, result_dict[field_descriptor]) + + @SkipCheckUnknownFieldIfCppImplementation + def testCheckUnknownFieldValue(self): + # Test enum. + self.CheckUnknownField('optional_nested_enum', + self.all_fields.optional_nested_enum) + # Test repeated enum. + self.CheckUnknownField('repeated_nested_enum', + self.all_fields.repeated_nested_enum) + + # Test varint. + self.CheckUnknownField('optional_int32', + self.all_fields.optional_int32) + # Test fixed32. + self.CheckUnknownField('optional_fixed32', + self.all_fields.optional_fixed32) + + # Test fixed64. + self.CheckUnknownField('optional_fixed64', + self.all_fields.optional_fixed64) + + # Test lengthd elimited. + self.CheckUnknownField('optional_string', + self.all_fields.optional_string) + + # Test group. + self.CheckUnknownField('optionalgroup', + self.all_fields.optionalgroup) + + def testCopyFrom(self): + message = unittest_pb2.TestEmptyMessage() + message.CopyFrom(self.empty_message) + self.assertEqual(message.SerializeToString(), self.all_fields_data) + + def testMergeFrom(self): + message = unittest_pb2.TestAllTypes() + message.optional_int32 = 1 + message.optional_uint32 = 2 + source = unittest_pb2.TestEmptyMessage() + source.ParseFromString(message.SerializeToString()) + + message.ClearField('optional_int32') + message.optional_int64 = 3 + message.optional_uint32 = 4 + destination = unittest_pb2.TestEmptyMessage() + destination.ParseFromString(message.SerializeToString()) + + destination.MergeFrom(source) + # Check that the fields where correctly merged, even stored in the unknown + # fields set. + message.ParseFromString(destination.SerializeToString()) + self.assertEqual(message.optional_int32, 1) + self.assertEqual(message.optional_uint32, 2) + self.assertEqual(message.optional_int64, 3) + + def testClear(self): + self.empty_message.Clear() + # All cleared, even unknown fields. + self.assertEqual(self.empty_message.SerializeToString(), b'') + + def testUnknownExtensions(self): + message = unittest_pb2.TestEmptyMessageWithExtensions() + message.ParseFromString(self.all_fields_data) + self.assertEqual(message.SerializeToString(), self.all_fields_data) + + +class UnknownEnumValuesTest(BaseTestCase): + + def setUp(self): + self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR + + self.message = missing_enum_values_pb2.TestEnumValues() + # TestEnumValues.ZERO = 0, but does not exist in the other NestedEnum. + self.message.optional_nested_enum = ( + missing_enum_values_pb2.TestEnumValues.ZERO) + self.message.repeated_nested_enum.extend([ + missing_enum_values_pb2.TestEnumValues.ZERO, + missing_enum_values_pb2.TestEnumValues.ONE, + ]) + self.message.packed_nested_enum.extend([ + missing_enum_values_pb2.TestEnumValues.ZERO, + missing_enum_values_pb2.TestEnumValues.ONE, + ]) + self.message_data = self.message.SerializeToString() + self.missing_message = missing_enum_values_pb2.TestMissingEnumValues() + self.missing_message.ParseFromString(self.message_data) + + # CheckUnknownField() is an additional Pure Python check which checks + # a detail of unknown fields. It cannot be used by the C++ + # implementation because some protect members are called. + # The test is added for historical reasons. It is not necessary as + # serialized string is checked. + + def CheckUnknownField(self, name, expected_value): + field_descriptor = self.descriptor.fields_by_name[name] + wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] + field_tag = encoder.TagBytes(field_descriptor.number, wire_type) + result_dict = {} + for tag_bytes, value in self.missing_message._unknown_fields: + if tag_bytes == field_tag: + decoder = missing_enum_values_pb2.TestEnumValues._decoders_by_tag[ + tag_bytes][0] + decoder(value, 0, len(value), self.message, result_dict) + self.assertEqual(expected_value, result_dict[field_descriptor]) + + def testUnknownParseMismatchEnumValue(self): + just_string = missing_enum_values_pb2.JustString() + just_string.dummy = 'blah' + + missing = missing_enum_values_pb2.TestEnumValues() + # The parse is invalid, storing the string proto into the set of + # unknown fields. + missing.ParseFromString(just_string.SerializeToString()) + + # Fetching the enum field shouldn't crash, instead returning the + # default value. + self.assertEqual(missing.optional_nested_enum, 0) + + def testUnknownEnumValue(self): + self.assertFalse(self.missing_message.HasField('optional_nested_enum')) + self.assertEqual(self.missing_message.optional_nested_enum, 2) + # Clear does not do anything. + serialized = self.missing_message.SerializeToString() + self.missing_message.ClearField('optional_nested_enum') + self.assertEqual(self.missing_message.SerializeToString(), serialized) + + def testUnknownRepeatedEnumValue(self): + self.assertEqual([], self.missing_message.repeated_nested_enum) + + def testUnknownPackedEnumValue(self): + self.assertEqual([], self.missing_message.packed_nested_enum) + + @SkipCheckUnknownFieldIfCppImplementation + def testCheckUnknownFieldValueForEnum(self): + self.CheckUnknownField('optional_nested_enum', + self.message.optional_nested_enum) + self.CheckUnknownField('repeated_nested_enum', + self.message.repeated_nested_enum) + self.CheckUnknownField('packed_nested_enum', + self.message.packed_nested_enum) + + def testRoundTrip(self): + new_message = missing_enum_values_pb2.TestEnumValues() + new_message.ParseFromString(self.missing_message.SerializeToString()) + self.assertEqual(self.message, new_message) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/well_known_types.py b/winvenv/Lib/site-packages/google/protobuf/internal/well_known_types.py new file mode 100644 index 0000000..37a65cf --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/well_known_types.py @@ -0,0 +1,839 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains well known classes. + +This files defines well known classes which need extra maintenance including: + - Any + - Duration + - FieldMask + - Struct + - Timestamp +""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import collections +from datetime import datetime +from datetime import timedelta +import six + +from google.protobuf.descriptor import FieldDescriptor + +_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' +_NANOS_PER_SECOND = 1000000000 +_NANOS_PER_MILLISECOND = 1000000 +_NANOS_PER_MICROSECOND = 1000 +_MILLIS_PER_SECOND = 1000 +_MICROS_PER_SECOND = 1000000 +_SECONDS_PER_DAY = 24 * 3600 +_DURATION_SECONDS_MAX = 315576000000 + + +class Error(Exception): + """Top-level module error.""" + + +class ParseError(Error): + """Thrown in case of parsing error.""" + + +class Any(object): + """Class for Any Message type.""" + + def Pack(self, msg, type_url_prefix='type.googleapis.com/', + deterministic=None): + """Packs the specified message into current Any message.""" + if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/': + self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) + else: + self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) + self.value = msg.SerializeToString(deterministic=deterministic) + + def Unpack(self, msg): + """Unpacks the current Any message into specified message.""" + descriptor = msg.DESCRIPTOR + if not self.Is(descriptor): + return False + msg.ParseFromString(self.value) + return True + + def TypeName(self): + """Returns the protobuf type name of the inner message.""" + # Only last part is to be used: b/25630112 + return self.type_url.split('/')[-1] + + def Is(self, descriptor): + """Checks if this Any represents the given protobuf type.""" + return self.TypeName() == descriptor.full_name + + +class Timestamp(object): + """Class for Timestamp message type.""" + + def ToJsonString(self): + """Converts Timestamp to RFC 3339 date string format. + + Returns: + A string converted from timestamp. The string is always Z-normalized + and uses 3, 6 or 9 fractional digits as required to represent the + exact time. Example of the return format: '1972-01-01T10:00:20.021Z' + """ + nanos = self.nanos % _NANOS_PER_SECOND + total_sec = self.seconds + (self.nanos - nanos) // _NANOS_PER_SECOND + seconds = total_sec % _SECONDS_PER_DAY + days = (total_sec - seconds) // _SECONDS_PER_DAY + dt = datetime(1970, 1, 1) + timedelta(days, seconds) + + result = dt.isoformat() + if (nanos % 1e9) == 0: + # If there are 0 fractional digits, the fractional + # point '.' should be omitted when serializing. + return result + 'Z' + if (nanos % 1e6) == 0: + # Serialize 3 fractional digits. + return result + '.%03dZ' % (nanos / 1e6) + if (nanos % 1e3) == 0: + # Serialize 6 fractional digits. + return result + '.%06dZ' % (nanos / 1e3) + # Serialize 9 fractional digits. + return result + '.%09dZ' % nanos + + def FromJsonString(self, value): + """Parse a RFC 3339 date string format to Timestamp. + + Args: + value: A date string. Any fractional digits (or none) and any offset are + accepted as long as they fit into nano-seconds precision. + Example of accepted format: '1972-01-01T10:00:20.021-05:00' + + Raises: + ParseError: On parsing problems. + """ + timezone_offset = value.find('Z') + if timezone_offset == -1: + timezone_offset = value.find('+') + if timezone_offset == -1: + timezone_offset = value.rfind('-') + if timezone_offset == -1: + raise ParseError( + 'Failed to parse timestamp: missing valid timezone offset.') + time_value = value[0:timezone_offset] + # Parse datetime and nanos. + point_position = time_value.find('.') + if point_position == -1: + second_value = time_value + nano_value = '' + else: + second_value = time_value[:point_position] + nano_value = time_value[point_position + 1:] + date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT) + td = date_object - datetime(1970, 1, 1) + seconds = td.seconds + td.days * _SECONDS_PER_DAY + if len(nano_value) > 9: + raise ParseError( + 'Failed to parse Timestamp: nanos {0} more than ' + '9 fractional digits.'.format(nano_value)) + if nano_value: + nanos = round(float('0.' + nano_value) * 1e9) + else: + nanos = 0 + # Parse timezone offsets. + if value[timezone_offset] == 'Z': + if len(value) != timezone_offset + 1: + raise ParseError('Failed to parse timestamp: invalid trailing' + ' data {0}.'.format(value)) + else: + timezone = value[timezone_offset:] + pos = timezone.find(':') + if pos == -1: + raise ParseError( + 'Invalid timezone offset value: {0}.'.format(timezone)) + if timezone[0] == '+': + seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 + else: + seconds += (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 + # Set seconds and nanos + self.seconds = int(seconds) + self.nanos = int(nanos) + + def GetCurrentTime(self): + """Get the current UTC into Timestamp.""" + self.FromDatetime(datetime.utcnow()) + + def ToNanoseconds(self): + """Converts Timestamp to nanoseconds since epoch.""" + return self.seconds * _NANOS_PER_SECOND + self.nanos + + def ToMicroseconds(self): + """Converts Timestamp to microseconds since epoch.""" + return (self.seconds * _MICROS_PER_SECOND + + self.nanos // _NANOS_PER_MICROSECOND) + + def ToMilliseconds(self): + """Converts Timestamp to milliseconds since epoch.""" + return (self.seconds * _MILLIS_PER_SECOND + + self.nanos // _NANOS_PER_MILLISECOND) + + def ToSeconds(self): + """Converts Timestamp to seconds since epoch.""" + return self.seconds + + def FromNanoseconds(self, nanos): + """Converts nanoseconds since epoch to Timestamp.""" + self.seconds = nanos // _NANOS_PER_SECOND + self.nanos = nanos % _NANOS_PER_SECOND + + def FromMicroseconds(self, micros): + """Converts microseconds since epoch to Timestamp.""" + self.seconds = micros // _MICROS_PER_SECOND + self.nanos = (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND + + def FromMilliseconds(self, millis): + """Converts milliseconds since epoch to Timestamp.""" + self.seconds = millis // _MILLIS_PER_SECOND + self.nanos = (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND + + def FromSeconds(self, seconds): + """Converts seconds since epoch to Timestamp.""" + self.seconds = seconds + self.nanos = 0 + + def ToDatetime(self): + """Converts Timestamp to datetime.""" + return datetime.utcfromtimestamp( + self.seconds + self.nanos / float(_NANOS_PER_SECOND)) + + def FromDatetime(self, dt): + """Converts datetime to Timestamp.""" + td = dt - datetime(1970, 1, 1) + self.seconds = td.seconds + td.days * _SECONDS_PER_DAY + self.nanos = td.microseconds * _NANOS_PER_MICROSECOND + + +class Duration(object): + """Class for Duration message type.""" + + def ToJsonString(self): + """Converts Duration to string format. + + Returns: + A string converted from self. The string format will contains + 3, 6, or 9 fractional digits depending on the precision required to + represent the exact Duration value. For example: "1s", "1.010s", + "1.000000100s", "-3.100s" + """ + _CheckDurationValid(self.seconds, self.nanos) + if self.seconds < 0 or self.nanos < 0: + result = '-' + seconds = - self.seconds + int((0 - self.nanos) // 1e9) + nanos = (0 - self.nanos) % 1e9 + else: + result = '' + seconds = self.seconds + int(self.nanos // 1e9) + nanos = self.nanos % 1e9 + result += '%d' % seconds + if (nanos % 1e9) == 0: + # If there are 0 fractional digits, the fractional + # point '.' should be omitted when serializing. + return result + 's' + if (nanos % 1e6) == 0: + # Serialize 3 fractional digits. + return result + '.%03ds' % (nanos / 1e6) + if (nanos % 1e3) == 0: + # Serialize 6 fractional digits. + return result + '.%06ds' % (nanos / 1e3) + # Serialize 9 fractional digits. + return result + '.%09ds' % nanos + + def FromJsonString(self, value): + """Converts a string to Duration. + + Args: + value: A string to be converted. The string must end with 's'. Any + fractional digits (or none) are accepted as long as they fit into + precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s + + Raises: + ParseError: On parsing problems. + """ + if len(value) < 1 or value[-1] != 's': + raise ParseError( + 'Duration must end with letter "s": {0}.'.format(value)) + try: + pos = value.find('.') + if pos == -1: + seconds = int(value[:-1]) + nanos = 0 + else: + seconds = int(value[:pos]) + if value[0] == '-': + nanos = int(round(float('-0{0}'.format(value[pos: -1])) *1e9)) + else: + nanos = int(round(float('0{0}'.format(value[pos: -1])) *1e9)) + _CheckDurationValid(seconds, nanos) + self.seconds = seconds + self.nanos = nanos + except ValueError: + raise ParseError( + 'Couldn\'t parse duration: {0}.'.format(value)) + + def ToNanoseconds(self): + """Converts a Duration to nanoseconds.""" + return self.seconds * _NANOS_PER_SECOND + self.nanos + + def ToMicroseconds(self): + """Converts a Duration to microseconds.""" + micros = _RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND) + return self.seconds * _MICROS_PER_SECOND + micros + + def ToMilliseconds(self): + """Converts a Duration to milliseconds.""" + millis = _RoundTowardZero(self.nanos, _NANOS_PER_MILLISECOND) + return self.seconds * _MILLIS_PER_SECOND + millis + + def ToSeconds(self): + """Converts a Duration to seconds.""" + return self.seconds + + def FromNanoseconds(self, nanos): + """Converts nanoseconds to Duration.""" + self._NormalizeDuration(nanos // _NANOS_PER_SECOND, + nanos % _NANOS_PER_SECOND) + + def FromMicroseconds(self, micros): + """Converts microseconds to Duration.""" + self._NormalizeDuration( + micros // _MICROS_PER_SECOND, + (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND) + + def FromMilliseconds(self, millis): + """Converts milliseconds to Duration.""" + self._NormalizeDuration( + millis // _MILLIS_PER_SECOND, + (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND) + + def FromSeconds(self, seconds): + """Converts seconds to Duration.""" + self.seconds = seconds + self.nanos = 0 + + def ToTimedelta(self): + """Converts Duration to timedelta.""" + return timedelta( + seconds=self.seconds, microseconds=_RoundTowardZero( + self.nanos, _NANOS_PER_MICROSECOND)) + + def FromTimedelta(self, td): + """Converts timedelta to Duration.""" + self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY, + td.microseconds * _NANOS_PER_MICROSECOND) + + def _NormalizeDuration(self, seconds, nanos): + """Set Duration by seconds and nanos.""" + # Force nanos to be negative if the duration is negative. + if seconds < 0 and nanos > 0: + seconds += 1 + nanos -= _NANOS_PER_SECOND + self.seconds = seconds + self.nanos = nanos + + +def _CheckDurationValid(seconds, nanos): + if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX: + raise Error( + 'Duration is not valid: Seconds {0} must be in range ' + '[-315576000000, 315576000000].'.format(seconds)) + if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND: + raise Error( + 'Duration is not valid: Nanos {0} must be in range ' + '[-999999999, 999999999].'.format(nanos)) + if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0): + raise Error( + 'Duration is not valid: Sign mismatch.') + + +def _RoundTowardZero(value, divider): + """Truncates the remainder part after division.""" + # For some languanges, the sign of the remainder is implementation + # dependent if any of the operands is negative. Here we enforce + # "rounded toward zero" semantics. For example, for (-5) / 2 an + # implementation may give -3 as the result with the remainder being + # 1. This function ensures we always return -2 (closer to zero). + result = value // divider + remainder = value % divider + if result < 0 and remainder > 0: + return result + 1 + else: + return result + + +class FieldMask(object): + """Class for FieldMask message type.""" + + def ToJsonString(self): + """Converts FieldMask to string according to proto3 JSON spec.""" + camelcase_paths = [] + for path in self.paths: + camelcase_paths.append(_SnakeCaseToCamelCase(path)) + return ','.join(camelcase_paths) + + def FromJsonString(self, value): + """Converts string to FieldMask according to proto3 JSON spec.""" + self.Clear() + for path in value.split(','): + self.paths.append(_CamelCaseToSnakeCase(path)) + + def IsValidForDescriptor(self, message_descriptor): + """Checks whether the FieldMask is valid for Message Descriptor.""" + for path in self.paths: + if not _IsValidPath(message_descriptor, path): + return False + return True + + def AllFieldsFromDescriptor(self, message_descriptor): + """Gets all direct fields of Message Descriptor to FieldMask.""" + self.Clear() + for field in message_descriptor.fields: + self.paths.append(field.name) + + def CanonicalFormFromMask(self, mask): + """Converts a FieldMask to the canonical form. + + Removes paths that are covered by another path. For example, + "foo.bar" is covered by "foo" and will be removed if "foo" + is also in the FieldMask. Then sorts all paths in alphabetical order. + + Args: + mask: The original FieldMask to be converted. + """ + tree = _FieldMaskTree(mask) + tree.ToFieldMask(self) + + def Union(self, mask1, mask2): + """Merges mask1 and mask2 into this FieldMask.""" + _CheckFieldMaskMessage(mask1) + _CheckFieldMaskMessage(mask2) + tree = _FieldMaskTree(mask1) + tree.MergeFromFieldMask(mask2) + tree.ToFieldMask(self) + + def Intersect(self, mask1, mask2): + """Intersects mask1 and mask2 into this FieldMask.""" + _CheckFieldMaskMessage(mask1) + _CheckFieldMaskMessage(mask2) + tree = _FieldMaskTree(mask1) + intersection = _FieldMaskTree() + for path in mask2.paths: + tree.IntersectPath(path, intersection) + intersection.ToFieldMask(self) + + def MergeMessage( + self, source, destination, + replace_message_field=False, replace_repeated_field=False): + """Merges fields specified in FieldMask from source to destination. + + Args: + source: Source message. + destination: The destination message to be merged into. + replace_message_field: Replace message field if True. Merge message + field if False. + replace_repeated_field: Replace repeated field if True. Append + elements of repeated field if False. + """ + tree = _FieldMaskTree(self) + tree.MergeMessage( + source, destination, replace_message_field, replace_repeated_field) + + +def _IsValidPath(message_descriptor, path): + """Checks whether the path is valid for Message Descriptor.""" + parts = path.split('.') + last = parts.pop() + for name in parts: + field = message_descriptor.fields_by_name.get(name) + if (field is None or + field.label == FieldDescriptor.LABEL_REPEATED or + field.type != FieldDescriptor.TYPE_MESSAGE): + return False + message_descriptor = field.message_type + return last in message_descriptor.fields_by_name + + +def _CheckFieldMaskMessage(message): + """Raises ValueError if message is not a FieldMask.""" + message_descriptor = message.DESCRIPTOR + if (message_descriptor.name != 'FieldMask' or + message_descriptor.file.name != 'google/protobuf/field_mask.proto'): + raise ValueError('Message {0} is not a FieldMask.'.format( + message_descriptor.full_name)) + + +def _SnakeCaseToCamelCase(path_name): + """Converts a path name from snake_case to camelCase.""" + result = [] + after_underscore = False + for c in path_name: + if c.isupper(): + raise Error('Fail to print FieldMask to Json string: Path name ' + '{0} must not contain uppercase letters.'.format(path_name)) + if after_underscore: + if c.islower(): + result.append(c.upper()) + after_underscore = False + else: + raise Error('Fail to print FieldMask to Json string: The ' + 'character after a "_" must be a lowercase letter ' + 'in path name {0}.'.format(path_name)) + elif c == '_': + after_underscore = True + else: + result += c + + if after_underscore: + raise Error('Fail to print FieldMask to Json string: Trailing "_" ' + 'in path name {0}.'.format(path_name)) + return ''.join(result) + + +def _CamelCaseToSnakeCase(path_name): + """Converts a field name from camelCase to snake_case.""" + result = [] + for c in path_name: + if c == '_': + raise ParseError('Fail to parse FieldMask: Path name ' + '{0} must not contain "_"s.'.format(path_name)) + if c.isupper(): + result += '_' + result += c.lower() + else: + result += c + return ''.join(result) + + +class _FieldMaskTree(object): + """Represents a FieldMask in a tree structure. + + For example, given a FieldMask "foo.bar,foo.baz,bar.baz", + the FieldMaskTree will be: + [_root] -+- foo -+- bar + | | + | +- baz + | + +- bar --- baz + In the tree, each leaf node represents a field path. + """ + + def __init__(self, field_mask=None): + """Initializes the tree by FieldMask.""" + self._root = {} + if field_mask: + self.MergeFromFieldMask(field_mask) + + def MergeFromFieldMask(self, field_mask): + """Merges a FieldMask to the tree.""" + for path in field_mask.paths: + self.AddPath(path) + + def AddPath(self, path): + """Adds a field path into the tree. + + If the field path to add is a sub-path of an existing field path + in the tree (i.e., a leaf node), it means the tree already matches + the given path so nothing will be added to the tree. If the path + matches an existing non-leaf node in the tree, that non-leaf node + will be turned into a leaf node with all its children removed because + the path matches all the node's children. Otherwise, a new path will + be added. + + Args: + path: The field path to add. + """ + node = self._root + for name in path.split('.'): + if name not in node: + node[name] = {} + elif not node[name]: + # Pre-existing empty node implies we already have this entire tree. + return + node = node[name] + # Remove any sub-trees we might have had. + node.clear() + + def ToFieldMask(self, field_mask): + """Converts the tree to a FieldMask.""" + field_mask.Clear() + _AddFieldPaths(self._root, '', field_mask) + + def IntersectPath(self, path, intersection): + """Calculates the intersection part of a field path with this tree. + + Args: + path: The field path to calculates. + intersection: The out tree to record the intersection part. + """ + node = self._root + for name in path.split('.'): + if name not in node: + return + elif not node[name]: + intersection.AddPath(path) + return + node = node[name] + intersection.AddLeafNodes(path, node) + + def AddLeafNodes(self, prefix, node): + """Adds leaf nodes begin with prefix to this tree.""" + if not node: + self.AddPath(prefix) + for name in node: + child_path = prefix + '.' + name + self.AddLeafNodes(child_path, node[name]) + + def MergeMessage( + self, source, destination, + replace_message, replace_repeated): + """Merge all fields specified by this tree from source to destination.""" + _MergeMessage( + self._root, source, destination, replace_message, replace_repeated) + + +def _StrConvert(value): + """Converts value to str if it is not.""" + # This file is imported by c extension and some methods like ClearField + # requires string for the field name. py2/py3 has different text + # type and may use unicode. + if not isinstance(value, str): + return value.encode('utf-8') + return value + + +def _MergeMessage( + node, source, destination, replace_message, replace_repeated): + """Merge all fields specified by a sub-tree from source to destination.""" + source_descriptor = source.DESCRIPTOR + for name in node: + child = node[name] + field = source_descriptor.fields_by_name[name] + if field is None: + raise ValueError('Error: Can\'t find field {0} in message {1}.'.format( + name, source_descriptor.full_name)) + if child: + # Sub-paths are only allowed for singular message fields. + if (field.label == FieldDescriptor.LABEL_REPEATED or + field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE): + raise ValueError('Error: Field {0} in message {1} is not a singular ' + 'message field and cannot have sub-fields.'.format( + name, source_descriptor.full_name)) + if source.HasField(name): + _MergeMessage( + child, getattr(source, name), getattr(destination, name), + replace_message, replace_repeated) + continue + if field.label == FieldDescriptor.LABEL_REPEATED: + if replace_repeated: + destination.ClearField(_StrConvert(name)) + repeated_source = getattr(source, name) + repeated_destination = getattr(destination, name) + if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + for item in repeated_source: + repeated_destination.add().MergeFrom(item) + else: + repeated_destination.extend(repeated_source) + else: + if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + if replace_message: + destination.ClearField(_StrConvert(name)) + if source.HasField(name): + getattr(destination, name).MergeFrom(getattr(source, name)) + else: + setattr(destination, name, getattr(source, name)) + + +def _AddFieldPaths(node, prefix, field_mask): + """Adds the field paths descended from node to field_mask.""" + if not node: + field_mask.paths.append(prefix) + return + for name in sorted(node): + if prefix: + child_path = prefix + '.' + name + else: + child_path = name + _AddFieldPaths(node[name], child_path, field_mask) + + +_INT_OR_FLOAT = six.integer_types + (float,) + + +def _SetStructValue(struct_value, value): + if value is None: + struct_value.null_value = 0 + elif isinstance(value, bool): + # Note: this check must come before the number check because in Python + # True and False are also considered numbers. + struct_value.bool_value = value + elif isinstance(value, six.string_types): + struct_value.string_value = value + elif isinstance(value, _INT_OR_FLOAT): + struct_value.number_value = value + elif isinstance(value, dict): + struct_value.struct_value.Clear() + struct_value.struct_value.update(value) + elif isinstance(value, list): + struct_value.list_value.Clear() + struct_value.list_value.extend(value) + else: + raise ValueError('Unexpected type') + + +def _GetStructValue(struct_value): + which = struct_value.WhichOneof('kind') + if which == 'struct_value': + return struct_value.struct_value + elif which == 'null_value': + return None + elif which == 'number_value': + return struct_value.number_value + elif which == 'string_value': + return struct_value.string_value + elif which == 'bool_value': + return struct_value.bool_value + elif which == 'list_value': + return struct_value.list_value + elif which is None: + raise ValueError('Value not set') + + +class Struct(object): + """Class for Struct message type.""" + + __slots__ = [] + + def __getitem__(self, key): + return _GetStructValue(self.fields[key]) + + def __contains__(self, item): + return item in self.fields + + def __setitem__(self, key, value): + _SetStructValue(self.fields[key], value) + + def __delitem__(self, key): + del self.fields[key] + + def __len__(self): + return len(self.fields) + + def __iter__(self): + return iter(self.fields) + + def keys(self): # pylint: disable=invalid-name + return self.fields.keys() + + def values(self): # pylint: disable=invalid-name + return [self[key] for key in self] + + def items(self): # pylint: disable=invalid-name + return [(key, self[key]) for key in self] + + def get_or_create_list(self, key): + """Returns a list for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('list_value'): + # Clear will mark list_value modified which will indeed create a list. + self.fields[key].list_value.Clear() + return self.fields[key].list_value + + def get_or_create_struct(self, key): + """Returns a struct for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('struct_value'): + # Clear will mark struct_value modified which will indeed create a struct. + self.fields[key].struct_value.Clear() + return self.fields[key].struct_value + + def update(self, dictionary): # pylint: disable=invalid-name + for key, value in dictionary.items(): + _SetStructValue(self.fields[key], value) + +collections.MutableMapping.register(Struct) + + +class ListValue(object): + """Class for ListValue message type.""" + + def __len__(self): + return len(self.values) + + def append(self, value): + _SetStructValue(self.values.add(), value) + + def extend(self, elem_seq): + for value in elem_seq: + self.append(value) + + def __getitem__(self, index): + """Retrieves item by the specified index.""" + return _GetStructValue(self.values.__getitem__(index)) + + def __setitem__(self, index, value): + _SetStructValue(self.values.__getitem__(index), value) + + def __delitem__(self, key): + del self.values[key] + + def items(self): + for i in range(len(self)): + yield self[i] + + def add_struct(self): + """Appends and returns a struct value as the next value in the list.""" + struct_value = self.values.add().struct_value + # Clear will mark struct_value modified which will indeed create a struct. + struct_value.Clear() + return struct_value + + def add_list(self): + """Appends and returns a list value as the next value in the list.""" + list_value = self.values.add().list_value + # Clear will mark list_value modified which will indeed create a list. + list_value.Clear() + return list_value + +collections.MutableSequence.register(ListValue) + + +WKTBASES = { + 'google.protobuf.Any': Any, + 'google.protobuf.Duration': Duration, + 'google.protobuf.FieldMask': FieldMask, + 'google.protobuf.ListValue': ListValue, + 'google.protobuf.Struct': Struct, + 'google.protobuf.Timestamp': Timestamp, +} diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/well_known_types_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/well_known_types_test.py new file mode 100644 index 0000000..965940b --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/well_known_types_test.py @@ -0,0 +1,927 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.internal.well_known_types.""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import collections +from datetime import datetime + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import any_pb2 +from google.protobuf import duration_pb2 +from google.protobuf import field_mask_pb2 +from google.protobuf import struct_pb2 +from google.protobuf import timestamp_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf.internal import any_test_pb2 +from google.protobuf.internal import test_util +from google.protobuf.internal import well_known_types +from google.protobuf import descriptor +from google.protobuf import text_format + + +class TimeUtilTestBase(unittest.TestCase): + + def CheckTimestampConversion(self, message, text): + self.assertEqual(text, message.ToJsonString()) + parsed_message = timestamp_pb2.Timestamp() + parsed_message.FromJsonString(text) + self.assertEqual(message, parsed_message) + + def CheckDurationConversion(self, message, text): + self.assertEqual(text, message.ToJsonString()) + parsed_message = duration_pb2.Duration() + parsed_message.FromJsonString(text) + self.assertEqual(message, parsed_message) + + +class TimeUtilTest(TimeUtilTestBase): + + def testTimestampSerializeAndParse(self): + message = timestamp_pb2.Timestamp() + # Generated output should contain 3, 6, or 9 fractional digits. + message.seconds = 0 + message.nanos = 0 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00Z') + message.nanos = 10000000 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00.010Z') + message.nanos = 10000 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000010Z') + message.nanos = 10 + self.CheckTimestampConversion(message, '1970-01-01T00:00:00.000000010Z') + # Test min timestamps. + message.seconds = -62135596800 + message.nanos = 0 + self.CheckTimestampConversion(message, '0001-01-01T00:00:00Z') + # Test max timestamps. + message.seconds = 253402300799 + message.nanos = 999999999 + self.CheckTimestampConversion(message, '9999-12-31T23:59:59.999999999Z') + # Test negative timestamps. + message.seconds = -1 + self.CheckTimestampConversion(message, '1969-12-31T23:59:59.999999999Z') + + # Parsing accepts an fractional digits as long as they fit into nano + # precision. + message.FromJsonString('1970-01-01T00:00:00.1Z') + self.assertEqual(0, message.seconds) + self.assertEqual(100000000, message.nanos) + # Parsing accepts offsets. + message.FromJsonString('1970-01-01T00:00:00-08:00') + self.assertEqual(8 * 3600, message.seconds) + self.assertEqual(0, message.nanos) + + # It is not easy to check with current time. For test coverage only. + message.GetCurrentTime() + self.assertNotEqual(8 * 3600, message.seconds) + + def testDurationSerializeAndParse(self): + message = duration_pb2.Duration() + # Generated output should contain 3, 6, or 9 fractional digits. + message.seconds = 0 + message.nanos = 0 + self.CheckDurationConversion(message, '0s') + message.nanos = 10000000 + self.CheckDurationConversion(message, '0.010s') + message.nanos = 10000 + self.CheckDurationConversion(message, '0.000010s') + message.nanos = 10 + self.CheckDurationConversion(message, '0.000000010s') + + # Test min and max + message.seconds = 315576000000 + message.nanos = 999999999 + self.CheckDurationConversion(message, '315576000000.999999999s') + message.seconds = -315576000000 + message.nanos = -999999999 + self.CheckDurationConversion(message, '-315576000000.999999999s') + + # Parsing accepts an fractional digits as long as they fit into nano + # precision. + message.FromJsonString('0.1s') + self.assertEqual(100000000, message.nanos) + message.FromJsonString('0.0000001s') + self.assertEqual(100, message.nanos) + + def testTimestampIntegerConversion(self): + message = timestamp_pb2.Timestamp() + message.FromNanoseconds(1) + self.assertEqual('1970-01-01T00:00:00.000000001Z', + message.ToJsonString()) + self.assertEqual(1, message.ToNanoseconds()) + + message.FromNanoseconds(-1) + self.assertEqual('1969-12-31T23:59:59.999999999Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToNanoseconds()) + + message.FromMicroseconds(1) + self.assertEqual('1970-01-01T00:00:00.000001Z', + message.ToJsonString()) + self.assertEqual(1, message.ToMicroseconds()) + + message.FromMicroseconds(-1) + self.assertEqual('1969-12-31T23:59:59.999999Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToMicroseconds()) + + message.FromMilliseconds(1) + self.assertEqual('1970-01-01T00:00:00.001Z', + message.ToJsonString()) + self.assertEqual(1, message.ToMilliseconds()) + + message.FromMilliseconds(-1) + self.assertEqual('1969-12-31T23:59:59.999Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToMilliseconds()) + + message.FromSeconds(1) + self.assertEqual('1970-01-01T00:00:01Z', + message.ToJsonString()) + self.assertEqual(1, message.ToSeconds()) + + message.FromSeconds(-1) + self.assertEqual('1969-12-31T23:59:59Z', + message.ToJsonString()) + self.assertEqual(-1, message.ToSeconds()) + + message.FromNanoseconds(1999) + self.assertEqual(1, message.ToMicroseconds()) + # For negative values, Timestamp will be rounded down. + # For example, "1969-12-31T23:59:59.5Z" (i.e., -0.5s) rounded to seconds + # will be "1969-12-31T23:59:59Z" (i.e., -1s) rather than + # "1970-01-01T00:00:00Z" (i.e., 0s). + message.FromNanoseconds(-1999) + self.assertEqual(-2, message.ToMicroseconds()) + + def testDurationIntegerConversion(self): + message = duration_pb2.Duration() + message.FromNanoseconds(1) + self.assertEqual('0.000000001s', + message.ToJsonString()) + self.assertEqual(1, message.ToNanoseconds()) + + message.FromNanoseconds(-1) + self.assertEqual('-0.000000001s', + message.ToJsonString()) + self.assertEqual(-1, message.ToNanoseconds()) + + message.FromMicroseconds(1) + self.assertEqual('0.000001s', + message.ToJsonString()) + self.assertEqual(1, message.ToMicroseconds()) + + message.FromMicroseconds(-1) + self.assertEqual('-0.000001s', + message.ToJsonString()) + self.assertEqual(-1, message.ToMicroseconds()) + + message.FromMilliseconds(1) + self.assertEqual('0.001s', + message.ToJsonString()) + self.assertEqual(1, message.ToMilliseconds()) + + message.FromMilliseconds(-1) + self.assertEqual('-0.001s', + message.ToJsonString()) + self.assertEqual(-1, message.ToMilliseconds()) + + message.FromSeconds(1) + self.assertEqual('1s', message.ToJsonString()) + self.assertEqual(1, message.ToSeconds()) + + message.FromSeconds(-1) + self.assertEqual('-1s', + message.ToJsonString()) + self.assertEqual(-1, message.ToSeconds()) + + # Test truncation behavior. + message.FromNanoseconds(1999) + self.assertEqual(1, message.ToMicroseconds()) + + # For negative values, Duration will be rounded towards 0. + message.FromNanoseconds(-1999) + self.assertEqual(-1, message.ToMicroseconds()) + + def testDatetimeConverison(self): + message = timestamp_pb2.Timestamp() + dt = datetime(1970, 1, 1) + message.FromDatetime(dt) + self.assertEqual(dt, message.ToDatetime()) + + message.FromMilliseconds(1999) + self.assertEqual(datetime(1970, 1, 1, 0, 0, 1, 999000), + message.ToDatetime()) + + def testTimedeltaConversion(self): + message = duration_pb2.Duration() + message.FromNanoseconds(1999999999) + td = message.ToTimedelta() + self.assertEqual(1, td.seconds) + self.assertEqual(999999, td.microseconds) + + message.FromNanoseconds(-1999999999) + td = message.ToTimedelta() + self.assertEqual(-1, td.days) + self.assertEqual(86398, td.seconds) + self.assertEqual(1, td.microseconds) + + message.FromMicroseconds(-1) + td = message.ToTimedelta() + self.assertEqual(-1, td.days) + self.assertEqual(86399, td.seconds) + self.assertEqual(999999, td.microseconds) + converted_message = duration_pb2.Duration() + converted_message.FromTimedelta(td) + self.assertEqual(message, converted_message) + + def testInvalidTimestamp(self): + message = timestamp_pb2.Timestamp() + self.assertRaisesRegexp( + well_known_types.ParseError, + 'Failed to parse timestamp: missing valid timezone offset.', + message.FromJsonString, + '') + self.assertRaisesRegexp( + well_known_types.ParseError, + 'Failed to parse timestamp: invalid trailing data ' + '1970-01-01T00:00:01Ztrail.', + message.FromJsonString, + '1970-01-01T00:00:01Ztrail') + self.assertRaisesRegexp( + ValueError, + 'time data \'10000-01-01T00:00:00\' does not match' + ' format \'%Y-%m-%dT%H:%M:%S\'', + message.FromJsonString, '10000-01-01T00:00:00.00Z') + self.assertRaisesRegexp( + well_known_types.ParseError, + 'nanos 0123456789012 more than 9 fractional digits.', + message.FromJsonString, + '1970-01-01T00:00:00.0123456789012Z') + self.assertRaisesRegexp( + well_known_types.ParseError, + (r'Invalid timezone offset value: \+08.'), + message.FromJsonString, + '1972-01-01T01:00:00.01+08',) + self.assertRaisesRegexp( + ValueError, + 'year (0 )?is out of range', + message.FromJsonString, + '0000-01-01T00:00:00Z') + message.seconds = 253402300800 + self.assertRaisesRegexp( + OverflowError, + 'date value out of range', + message.ToJsonString) + + def testInvalidDuration(self): + message = duration_pb2.Duration() + self.assertRaisesRegexp( + well_known_types.ParseError, + 'Duration must end with letter "s": 1.', + message.FromJsonString, '1') + self.assertRaisesRegexp( + well_known_types.ParseError, + 'Couldn\'t parse duration: 1...2s.', + message.FromJsonString, '1...2s') + text = '-315576000001.000000000s' + self.assertRaisesRegexp( + well_known_types.Error, + r'Duration is not valid\: Seconds -315576000001 must be in range' + r' \[-315576000000\, 315576000000\].', + message.FromJsonString, text) + text = '315576000001.000000000s' + self.assertRaisesRegexp( + well_known_types.Error, + r'Duration is not valid\: Seconds 315576000001 must be in range' + r' \[-315576000000\, 315576000000\].', + message.FromJsonString, text) + message.seconds = -315576000001 + message.nanos = 0 + self.assertRaisesRegexp( + well_known_types.Error, + r'Duration is not valid\: Seconds -315576000001 must be in range' + r' \[-315576000000\, 315576000000\].', + message.ToJsonString) + message.seconds = 0 + message.nanos = 999999999 + 1 + self.assertRaisesRegexp( + well_known_types.Error, + r'Duration is not valid\: Nanos 1000000000 must be in range' + r' \[-999999999\, 999999999\].', + message.ToJsonString) + message.seconds = -1 + message.nanos = 1 + self.assertRaisesRegexp( + well_known_types.Error, + r'Duration is not valid\: Sign mismatch.', + message.ToJsonString) + + +class FieldMaskTest(unittest.TestCase): + + def testStringFormat(self): + mask = field_mask_pb2.FieldMask() + self.assertEqual('', mask.ToJsonString()) + mask.paths.append('foo') + self.assertEqual('foo', mask.ToJsonString()) + mask.paths.append('bar') + self.assertEqual('foo,bar', mask.ToJsonString()) + + mask.FromJsonString('') + self.assertEqual('', mask.ToJsonString()) + mask.FromJsonString('foo') + self.assertEqual(['foo'], mask.paths) + mask.FromJsonString('foo,bar') + self.assertEqual(['foo', 'bar'], mask.paths) + + # Test camel case + mask.Clear() + mask.paths.append('foo_bar') + self.assertEqual('fooBar', mask.ToJsonString()) + mask.paths.append('bar_quz') + self.assertEqual('fooBar,barQuz', mask.ToJsonString()) + + mask.FromJsonString('') + self.assertEqual('', mask.ToJsonString()) + mask.FromJsonString('fooBar') + self.assertEqual(['foo_bar'], mask.paths) + mask.FromJsonString('fooBar,barQuz') + self.assertEqual(['foo_bar', 'bar_quz'], mask.paths) + + def testDescriptorToFieldMask(self): + mask = field_mask_pb2.FieldMask() + msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + mask.AllFieldsFromDescriptor(msg_descriptor) + self.assertEqual(75, len(mask.paths)) + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + for field in msg_descriptor.fields: + self.assertTrue(field.name in mask.paths) + + def testIsValidForDescriptor(self): + msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + # Empty mask + mask = field_mask_pb2.FieldMask() + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # All fields from descriptor + mask.AllFieldsFromDescriptor(msg_descriptor) + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # Child under optional message + mask.paths.append('optional_nested_message.bb') + self.assertTrue(mask.IsValidForDescriptor(msg_descriptor)) + # Repeated field is only allowed in the last position of path + mask.paths.append('repeated_nested_message.bb') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid top level field + mask = field_mask_pb2.FieldMask() + mask.paths.append('xxx') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in root + mask = field_mask_pb2.FieldMask() + mask.paths.append('xxx.zzz') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in internal node + mask = field_mask_pb2.FieldMask() + mask.paths.append('optional_nested_message.xxx.zzz') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + # Invalid field in leaf + mask = field_mask_pb2.FieldMask() + mask.paths.append('optional_nested_message.xxx') + self.assertFalse(mask.IsValidForDescriptor(msg_descriptor)) + + def testCanonicalFrom(self): + mask = field_mask_pb2.FieldMask() + out_mask = field_mask_pb2.FieldMask() + # Paths will be sorted. + mask.FromJsonString('baz.quz,bar,foo') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('bar,baz.quz,foo', out_mask.ToJsonString()) + # Duplicated paths will be removed. + mask.FromJsonString('foo,bar,foo') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('bar,foo', out_mask.ToJsonString()) + # Sub-paths of other paths will be removed. + mask.FromJsonString('foo.b1,bar.b1,foo.b2,bar') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('bar,foo.b1,foo.b2', out_mask.ToJsonString()) + + # Test more deeply nested cases. + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2.quz,foo.bar.baz2') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo.bar.baz1,foo.bar.baz2', + out_mask.ToJsonString()) + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo.bar.baz1,foo.bar.baz2', + out_mask.ToJsonString()) + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo.bar') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo.bar', out_mask.ToJsonString()) + mask.FromJsonString( + 'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo') + out_mask.CanonicalFormFromMask(mask) + self.assertEqual('foo', out_mask.ToJsonString()) + + def testUnion(self): + mask1 = field_mask_pb2.FieldMask() + mask2 = field_mask_pb2.FieldMask() + out_mask = field_mask_pb2.FieldMask() + mask1.FromJsonString('foo,baz') + mask2.FromJsonString('bar,quz') + out_mask.Union(mask1, mask2) + self.assertEqual('bar,baz,foo,quz', out_mask.ToJsonString()) + # Overlap with duplicated paths. + mask1.FromJsonString('foo,baz.bb') + mask2.FromJsonString('baz.bb,quz') + out_mask.Union(mask1, mask2) + self.assertEqual('baz.bb,foo,quz', out_mask.ToJsonString()) + # Overlap with paths covering some other paths. + mask1.FromJsonString('foo.bar.baz,quz') + mask2.FromJsonString('foo.bar,bar') + out_mask.Union(mask1, mask2) + self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString()) + src = unittest_pb2.TestAllTypes() + with self.assertRaises(ValueError): + out_mask.Union(src, mask2) + + def testIntersect(self): + mask1 = field_mask_pb2.FieldMask() + mask2 = field_mask_pb2.FieldMask() + out_mask = field_mask_pb2.FieldMask() + # Test cases without overlapping. + mask1.FromJsonString('foo,baz') + mask2.FromJsonString('bar,quz') + out_mask.Intersect(mask1, mask2) + self.assertEqual('', out_mask.ToJsonString()) + # Overlap with duplicated paths. + mask1.FromJsonString('foo,baz.bb') + mask2.FromJsonString('baz.bb,quz') + out_mask.Intersect(mask1, mask2) + self.assertEqual('baz.bb', out_mask.ToJsonString()) + # Overlap with paths covering some other paths. + mask1.FromJsonString('foo.bar.baz,quz') + mask2.FromJsonString('foo.bar,bar') + out_mask.Intersect(mask1, mask2) + self.assertEqual('foo.bar.baz', out_mask.ToJsonString()) + mask1.FromJsonString('foo.bar,bar') + mask2.FromJsonString('foo.bar.baz,quz') + out_mask.Intersect(mask1, mask2) + self.assertEqual('foo.bar.baz', out_mask.ToJsonString()) + + def testMergeMessage(self): + # Test merge one field. + src = unittest_pb2.TestAllTypes() + test_util.SetAllFields(src) + for field in src.DESCRIPTOR.fields: + if field.containing_oneof: + continue + field_name = field.name + dst = unittest_pb2.TestAllTypes() + # Only set one path to mask. + mask = field_mask_pb2.FieldMask() + mask.paths.append(field_name) + mask.MergeMessage(src, dst) + # The expected result message. + msg = unittest_pb2.TestAllTypes() + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + repeated_src = getattr(src, field_name) + repeated_msg = getattr(msg, field_name) + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + for item in repeated_src: + repeated_msg.add().CopyFrom(item) + else: + repeated_msg.extend(repeated_src) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + getattr(msg, field_name).CopyFrom(getattr(src, field_name)) + else: + setattr(msg, field_name, getattr(src, field_name)) + # Only field specified in mask is merged. + self.assertEqual(msg, dst) + + # Test merge nested fields. + nested_src = unittest_pb2.NestedTestAllTypes() + nested_dst = unittest_pb2.NestedTestAllTypes() + nested_src.child.payload.optional_int32 = 1234 + nested_src.child.child.payload.optional_int32 = 5678 + mask = field_mask_pb2.FieldMask() + mask.FromJsonString('child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(0, nested_dst.child.child.payload.optional_int32) + + mask.FromJsonString('child.child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(5678, nested_dst.child.child.payload.optional_int32) + + nested_dst.Clear() + mask.FromJsonString('child.child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(0, nested_dst.child.payload.optional_int32) + self.assertEqual(5678, nested_dst.child.child.payload.optional_int32) + + nested_dst.Clear() + mask.FromJsonString('child') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(5678, nested_dst.child.child.payload.optional_int32) + + # Test MergeOptions. + nested_dst.Clear() + nested_dst.child.payload.optional_int64 = 4321 + # Message fields will be merged by default. + mask.FromJsonString('child.payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(4321, nested_dst.child.payload.optional_int64) + # Change the behavior to replace message fields. + mask.FromJsonString('child.payload') + mask.MergeMessage(nested_src, nested_dst, True, False) + self.assertEqual(1234, nested_dst.child.payload.optional_int32) + self.assertEqual(0, nested_dst.child.payload.optional_int64) + + # By default, fields missing in source are not cleared in destination. + nested_dst.payload.optional_int32 = 1234 + self.assertTrue(nested_dst.HasField('payload')) + mask.FromJsonString('payload') + mask.MergeMessage(nested_src, nested_dst) + self.assertTrue(nested_dst.HasField('payload')) + # But they are cleared when replacing message fields. + nested_dst.Clear() + nested_dst.payload.optional_int32 = 1234 + mask.FromJsonString('payload') + mask.MergeMessage(nested_src, nested_dst, True, False) + self.assertFalse(nested_dst.HasField('payload')) + + nested_src.payload.repeated_int32.append(1234) + nested_dst.payload.repeated_int32.append(5678) + # Repeated fields will be appended by default. + mask.FromJsonString('payload.repeatedInt32') + mask.MergeMessage(nested_src, nested_dst) + self.assertEqual(2, len(nested_dst.payload.repeated_int32)) + self.assertEqual(5678, nested_dst.payload.repeated_int32[0]) + self.assertEqual(1234, nested_dst.payload.repeated_int32[1]) + # Change the behavior to replace repeated fields. + mask.FromJsonString('payload.repeatedInt32') + mask.MergeMessage(nested_src, nested_dst, False, True) + self.assertEqual(1, len(nested_dst.payload.repeated_int32)) + self.assertEqual(1234, nested_dst.payload.repeated_int32[0]) + + # Test Merge oneof field. + new_msg = unittest_pb2.TestOneof2() + dst = unittest_pb2.TestOneof2() + dst.foo_message.qux_int = 1 + mask = field_mask_pb2.FieldMask() + mask.FromJsonString('fooMessage,fooLazyMessage.quxInt') + mask.MergeMessage(new_msg, dst) + self.assertTrue(dst.HasField('foo_message')) + self.assertFalse(dst.HasField('foo_lazy_message')) + + def testMergeErrors(self): + src = unittest_pb2.TestAllTypes() + dst = unittest_pb2.TestAllTypes() + mask = field_mask_pb2.FieldMask() + test_util.SetAllFields(src) + mask.FromJsonString('optionalInt32.field') + with self.assertRaises(ValueError) as e: + mask.MergeMessage(src, dst) + self.assertEqual('Error: Field optional_int32 in message ' + 'protobuf_unittest.TestAllTypes is not a singular ' + 'message field and cannot have sub-fields.', + str(e.exception)) + + def testSnakeCaseToCamelCase(self): + self.assertEqual('fooBar', + well_known_types._SnakeCaseToCamelCase('foo_bar')) + self.assertEqual('FooBar', + well_known_types._SnakeCaseToCamelCase('_foo_bar')) + self.assertEqual('foo3Bar', + well_known_types._SnakeCaseToCamelCase('foo3_bar')) + + # No uppercase letter is allowed. + self.assertRaisesRegexp( + well_known_types.Error, + 'Fail to print FieldMask to Json string: Path name Foo must ' + 'not contain uppercase letters.', + well_known_types._SnakeCaseToCamelCase, + 'Foo') + # Any character after a "_" must be a lowercase letter. + # 1. "_" cannot be followed by another "_". + # 2. "_" cannot be followed by a digit. + # 3. "_" cannot appear as the last character. + self.assertRaisesRegexp( + well_known_types.Error, + 'Fail to print FieldMask to Json string: The character after a ' + '"_" must be a lowercase letter in path name foo__bar.', + well_known_types._SnakeCaseToCamelCase, + 'foo__bar') + self.assertRaisesRegexp( + well_known_types.Error, + 'Fail to print FieldMask to Json string: The character after a ' + '"_" must be a lowercase letter in path name foo_3bar.', + well_known_types._SnakeCaseToCamelCase, + 'foo_3bar') + self.assertRaisesRegexp( + well_known_types.Error, + 'Fail to print FieldMask to Json string: Trailing "_" in path ' + 'name foo_bar_.', + well_known_types._SnakeCaseToCamelCase, + 'foo_bar_') + + def testCamelCaseToSnakeCase(self): + self.assertEqual('foo_bar', + well_known_types._CamelCaseToSnakeCase('fooBar')) + self.assertEqual('_foo_bar', + well_known_types._CamelCaseToSnakeCase('FooBar')) + self.assertEqual('foo3_bar', + well_known_types._CamelCaseToSnakeCase('foo3Bar')) + self.assertRaisesRegexp( + well_known_types.ParseError, + 'Fail to parse FieldMask: Path name foo_bar must not contain "_"s.', + well_known_types._CamelCaseToSnakeCase, + 'foo_bar') + + +class StructTest(unittest.TestCase): + + def testStruct(self): + struct = struct_pb2.Struct() + self.assertIsInstance(struct, collections.Mapping) + self.assertEqual(0, len(struct)) + struct_class = struct.__class__ + + struct['key1'] = 5 + struct['key2'] = 'abc' + struct['key3'] = True + struct.get_or_create_struct('key4')['subkey'] = 11.0 + struct_list = struct.get_or_create_list('key5') + self.assertIsInstance(struct_list, collections.Sequence) + struct_list.extend([6, 'seven', True, False, None]) + struct_list.add_struct()['subkey2'] = 9 + struct['key6'] = {'subkey': {}} + struct['key7'] = [2, False] + + self.assertEqual(7, len(struct)) + self.assertTrue(isinstance(struct, well_known_types.Struct)) + self.assertEqual(5, struct['key1']) + self.assertEqual('abc', struct['key2']) + self.assertIs(True, struct['key3']) + self.assertEqual(11, struct['key4']['subkey']) + inner_struct = struct_class() + inner_struct['subkey2'] = 9 + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct['key5'].items())) + self.assertEqual({}, dict(struct['key6']['subkey'].fields)) + self.assertEqual([2, False], list(struct['key7'].items())) + + serialized = struct.SerializeToString() + struct2 = struct_pb2.Struct() + struct2.ParseFromString(serialized) + + self.assertEqual(struct, struct2) + for key, value in struct.items(): + self.assertIn(key, struct) + self.assertIn(key, struct2) + self.assertEqual(value, struct2[key]) + + self.assertEqual(7, len(struct.keys())) + self.assertEqual(7, len(struct.values())) + for key in struct.keys(): + self.assertIn(key, struct) + self.assertIn(key, struct2) + self.assertEqual(struct[key], struct2[key]) + + item = (next(iter(struct.keys())), next(iter(struct.values()))) + self.assertEqual(item, next(iter(struct.items()))) + + self.assertTrue(isinstance(struct2, well_known_types.Struct)) + self.assertEqual(5, struct2['key1']) + self.assertEqual('abc', struct2['key2']) + self.assertIs(True, struct2['key3']) + self.assertEqual(11, struct2['key4']['subkey']) + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct2['key5'].items())) + + struct_list = struct2['key5'] + self.assertEqual(6, struct_list[0]) + self.assertEqual('seven', struct_list[1]) + self.assertEqual(True, struct_list[2]) + self.assertEqual(False, struct_list[3]) + self.assertEqual(None, struct_list[4]) + self.assertEqual(inner_struct, struct_list[5]) + + struct_list[1] = 7 + self.assertEqual(7, struct_list[1]) + + struct_list.add_list().extend([1, 'two', True, False, None]) + self.assertEqual([1, 'two', True, False, None], + list(struct_list[6].items())) + struct_list.extend([{'nested_struct': 30}, ['nested_list', 99], {}, []]) + self.assertEqual(11, len(struct_list.values)) + self.assertEqual(30, struct_list[7]['nested_struct']) + self.assertEqual('nested_list', struct_list[8][0]) + self.assertEqual(99, struct_list[8][1]) + self.assertEqual({}, dict(struct_list[9].fields)) + self.assertEqual([], list(struct_list[10].items())) + struct_list[0] = {'replace': 'set'} + struct_list[1] = ['replace', 'set'] + self.assertEqual('set', struct_list[0]['replace']) + self.assertEqual(['replace', 'set'], list(struct_list[1].items())) + + text_serialized = str(struct) + struct3 = struct_pb2.Struct() + text_format.Merge(text_serialized, struct3) + self.assertEqual(struct, struct3) + + struct.get_or_create_struct('key3')['replace'] = 12 + self.assertEqual(12, struct['key3']['replace']) + + # Tests empty list. + struct.get_or_create_list('empty_list') + empty_list = struct['empty_list'] + self.assertEqual([], list(empty_list.items())) + list2 = struct_pb2.ListValue() + list2.add_list() + empty_list = list2[0] + self.assertEqual([], list(empty_list.items())) + + # Tests empty struct. + struct.get_or_create_struct('empty_struct') + empty_struct = struct['empty_struct'] + self.assertEqual({}, dict(empty_struct.fields)) + list2.add_struct() + empty_struct = list2[1] + self.assertEqual({}, dict(empty_struct.fields)) + + self.assertEqual(9, len(struct)) + del struct['key3'] + del struct['key4'] + self.assertEqual(7, len(struct)) + self.assertEqual(6, len(struct['key5'])) + del struct['key5'][1] + self.assertEqual(5, len(struct['key5'])) + self.assertEqual([6, True, False, None, inner_struct], + list(struct['key5'].items())) + + def testMergeFrom(self): + struct = struct_pb2.Struct() + struct_class = struct.__class__ + + dictionary = { + 'key1': 5, + 'key2': 'abc', + 'key3': True, + 'key4': {'subkey': 11.0}, + 'key5': [6, 'seven', True, False, None, {'subkey2': 9}], + 'key6': [['nested_list', True]], + 'empty_struct': {}, + 'empty_list': [] + } + struct.update(dictionary) + self.assertEqual(5, struct['key1']) + self.assertEqual('abc', struct['key2']) + self.assertIs(True, struct['key3']) + self.assertEqual(11, struct['key4']['subkey']) + inner_struct = struct_class() + inner_struct['subkey2'] = 9 + self.assertEqual([6, 'seven', True, False, None, inner_struct], + list(struct['key5'].items())) + self.assertEqual(2, len(struct['key6'][0].values)) + self.assertEqual('nested_list', struct['key6'][0][0]) + self.assertEqual(True, struct['key6'][0][1]) + empty_list = struct['empty_list'] + self.assertEqual([], list(empty_list.items())) + empty_struct = struct['empty_struct'] + self.assertEqual({}, dict(empty_struct.fields)) + + # According to documentation: "When parsing from the wire or when merging, + # if there are duplicate map keys the last key seen is used". + duplicate = { + 'key4': {'replace': 20}, + 'key5': [[False, 5]] + } + struct.update(duplicate) + self.assertEqual(1, len(struct['key4'].fields)) + self.assertEqual(20, struct['key4']['replace']) + self.assertEqual(1, len(struct['key5'].values)) + self.assertEqual(False, struct['key5'][0][0]) + self.assertEqual(5, struct['key5'][0][1]) + + +class AnyTest(unittest.TestCase): + + def testAnyMessage(self): + # Creates and sets message. + msg = any_test_pb2.TestAny() + msg_descriptor = msg.DESCRIPTOR + all_types = unittest_pb2.TestAllTypes() + all_descriptor = all_types.DESCRIPTOR + all_types.repeated_string.append(u'\u00fc\ua71f') + # Packs to Any. + msg.value.Pack(all_types) + self.assertEqual(msg.value.type_url, + 'type.googleapis.com/%s' % all_descriptor.full_name) + self.assertEqual(msg.value.value, + all_types.SerializeToString()) + # Tests Is() method. + self.assertTrue(msg.value.Is(all_descriptor)) + self.assertFalse(msg.value.Is(msg_descriptor)) + # Unpacks Any. + unpacked_message = unittest_pb2.TestAllTypes() + self.assertTrue(msg.value.Unpack(unpacked_message)) + self.assertEqual(all_types, unpacked_message) + # Unpacks to different type. + self.assertFalse(msg.value.Unpack(msg)) + # Only Any messages have Pack method. + try: + msg.Pack(all_types) + except AttributeError: + pass + else: + raise AttributeError('%s should not have Pack method.' % + msg_descriptor.full_name) + + def testMessageName(self): + # Creates and sets message. + submessage = any_test_pb2.TestAny() + submessage.int_value = 12345 + msg = any_pb2.Any() + msg.Pack(submessage) + self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny') + + def testPackWithCustomTypeUrl(self): + submessage = any_test_pb2.TestAny() + submessage.int_value = 12345 + msg = any_pb2.Any() + # Pack with a custom type URL prefix. + msg.Pack(submessage, 'type.myservice.com') + self.assertEqual(msg.type_url, + 'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name) + # Pack with a custom type URL prefix ending with '/'. + msg.Pack(submessage, 'type.myservice.com/') + self.assertEqual(msg.type_url, + 'type.myservice.com/%s' % submessage.DESCRIPTOR.full_name) + # Pack with an empty type URL prefix. + msg.Pack(submessage, '') + self.assertEqual(msg.type_url, + '/%s' % submessage.DESCRIPTOR.full_name) + # Test unpacking the type. + unpacked_message = any_test_pb2.TestAny() + self.assertTrue(msg.Unpack(unpacked_message)) + self.assertEqual(submessage, unpacked_message) + + def testPackDeterministic(self): + submessage = any_test_pb2.TestAny() + for i in range(10): + submessage.map_value[str(i)] = i * 2 + msg = any_pb2.Any() + msg.Pack(submessage, deterministic=True) + serialized = msg.SerializeToString(deterministic=True) + golden = (b'\n4type.googleapis.com/google.protobuf.internal.TestAny\x12F' + b'\x1a\x05\n\x010\x10\x00\x1a\x05\n\x011\x10\x02\x1a\x05\n\x01' + b'2\x10\x04\x1a\x05\n\x013\x10\x06\x1a\x05\n\x014\x10\x08\x1a' + b'\x05\n\x015\x10\n\x1a\x05\n\x016\x10\x0c\x1a\x05\n\x017\x10' + b'\x0e\x1a\x05\n\x018\x10\x10\x1a\x05\n\x019\x10\x12') + self.assertEqual(golden, serialized) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/wire_format.py b/winvenv/Lib/site-packages/google/protobuf/internal/wire_format.py new file mode 100644 index 0000000..883f525 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/wire_format.py @@ -0,0 +1,268 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Constants and static functions to support protocol buffer wire format.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import struct +from google.protobuf import descriptor +from google.protobuf import message + + +TAG_TYPE_BITS = 3 # Number of bits used to hold type info in a proto tag. +TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1 # 0x7 + +# These numbers identify the wire type of a protocol buffer value. +# We use the least-significant TAG_TYPE_BITS bits of the varint-encoded +# tag-and-type to store one of these WIRETYPE_* constants. +# These values must match WireType enum in google/protobuf/wire_format.h. +WIRETYPE_VARINT = 0 +WIRETYPE_FIXED64 = 1 +WIRETYPE_LENGTH_DELIMITED = 2 +WIRETYPE_START_GROUP = 3 +WIRETYPE_END_GROUP = 4 +WIRETYPE_FIXED32 = 5 +_WIRETYPE_MAX = 5 + + +# Bounds for various integer types. +INT32_MAX = int((1 << 31) - 1) +INT32_MIN = int(-(1 << 31)) +UINT32_MAX = (1 << 32) - 1 + +INT64_MAX = (1 << 63) - 1 +INT64_MIN = -(1 << 63) +UINT64_MAX = (1 << 64) - 1 + +# "struct" format strings that will encode/decode the specified formats. +FORMAT_UINT32_LITTLE_ENDIAN = '> TAG_TYPE_BITS), (tag & TAG_TYPE_MASK) + + +def ZigZagEncode(value): + """ZigZag Transform: Encodes signed integers so that they can be + effectively used with varint encoding. See wire_format.h for + more details. + """ + if value >= 0: + return value << 1 + return (value << 1) ^ (~0) + + +def ZigZagDecode(value): + """Inverse of ZigZagEncode().""" + if not value & 0x1: + return value >> 1 + return (value >> 1) ^ (~0) + + + +# The *ByteSize() functions below return the number of bytes required to +# serialize "field number + type" information and then serialize the value. + + +def Int32ByteSize(field_number, int32): + return Int64ByteSize(field_number, int32) + + +def Int32ByteSizeNoTag(int32): + return _VarUInt64ByteSizeNoTag(0xffffffffffffffff & int32) + + +def Int64ByteSize(field_number, int64): + # Have to convert to uint before calling UInt64ByteSize(). + return UInt64ByteSize(field_number, 0xffffffffffffffff & int64) + + +def UInt32ByteSize(field_number, uint32): + return UInt64ByteSize(field_number, uint32) + + +def UInt64ByteSize(field_number, uint64): + return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64) + + +def SInt32ByteSize(field_number, int32): + return UInt32ByteSize(field_number, ZigZagEncode(int32)) + + +def SInt64ByteSize(field_number, int64): + return UInt64ByteSize(field_number, ZigZagEncode(int64)) + + +def Fixed32ByteSize(field_number, fixed32): + return TagByteSize(field_number) + 4 + + +def Fixed64ByteSize(field_number, fixed64): + return TagByteSize(field_number) + 8 + + +def SFixed32ByteSize(field_number, sfixed32): + return TagByteSize(field_number) + 4 + + +def SFixed64ByteSize(field_number, sfixed64): + return TagByteSize(field_number) + 8 + + +def FloatByteSize(field_number, flt): + return TagByteSize(field_number) + 4 + + +def DoubleByteSize(field_number, double): + return TagByteSize(field_number) + 8 + + +def BoolByteSize(field_number, b): + return TagByteSize(field_number) + 1 + + +def EnumByteSize(field_number, enum): + return UInt32ByteSize(field_number, enum) + + +def StringByteSize(field_number, string): + return BytesByteSize(field_number, string.encode('utf-8')) + + +def BytesByteSize(field_number, b): + return (TagByteSize(field_number) + + _VarUInt64ByteSizeNoTag(len(b)) + + len(b)) + + +def GroupByteSize(field_number, message): + return (2 * TagByteSize(field_number) # START and END group. + + message.ByteSize()) + + +def MessageByteSize(field_number, message): + return (TagByteSize(field_number) + + _VarUInt64ByteSizeNoTag(message.ByteSize()) + + message.ByteSize()) + + +def MessageSetItemByteSize(field_number, msg): + # First compute the sizes of the tags. + # There are 2 tags for the beginning and ending of the repeated group, that + # is field number 1, one with field number 2 (type_id) and one with field + # number 3 (message). + total_size = (2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3)) + + # Add the number of bytes for type_id. + total_size += _VarUInt64ByteSizeNoTag(field_number) + + message_size = msg.ByteSize() + + # The number of bytes for encoding the length of the message. + total_size += _VarUInt64ByteSizeNoTag(message_size) + + # The size of the message. + total_size += message_size + return total_size + + +def TagByteSize(field_number): + """Returns the bytes required to serialize a tag with this field number.""" + # Just pass in type 0, since the type won't affect the tag+type size. + return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0)) + + +# Private helper function for the *ByteSize() functions above. + +def _VarUInt64ByteSizeNoTag(uint64): + """Returns the number of bytes required to serialize a single varint + using boundary value comparisons. (unrolled loop optimization -WPierce) + uint64 must be unsigned. + """ + if uint64 <= 0x7f: return 1 + if uint64 <= 0x3fff: return 2 + if uint64 <= 0x1fffff: return 3 + if uint64 <= 0xfffffff: return 4 + if uint64 <= 0x7ffffffff: return 5 + if uint64 <= 0x3ffffffffff: return 6 + if uint64 <= 0x1ffffffffffff: return 7 + if uint64 <= 0xffffffffffffff: return 8 + if uint64 <= 0x7fffffffffffffff: return 9 + if uint64 > UINT64_MAX: + raise message.EncodeError('Value out of range: %d' % uint64) + return 10 + + +NON_PACKABLE_TYPES = ( + descriptor.FieldDescriptor.TYPE_STRING, + descriptor.FieldDescriptor.TYPE_GROUP, + descriptor.FieldDescriptor.TYPE_MESSAGE, + descriptor.FieldDescriptor.TYPE_BYTES +) + + +def IsTypePackable(field_type): + """Return true iff packable = true is valid for fields of this type. + + Args: + field_type: a FieldDescriptor::Type value. + + Returns: + True iff fields of this type are packable. + """ + return field_type not in NON_PACKABLE_TYPES diff --git a/winvenv/Lib/site-packages/google/protobuf/internal/wire_format_test.py b/winvenv/Lib/site-packages/google/protobuf/internal/wire_format_test.py new file mode 100644 index 0000000..da120f3 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/internal/wire_format_test.py @@ -0,0 +1,257 @@ +#! /usr/bin/env python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Test for google.protobuf.internal.wire_format.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +try: + import unittest2 as unittest #PY26 +except ImportError: + import unittest + +from google.protobuf import message +from google.protobuf.internal import wire_format + + +class WireFormatTest(unittest.TestCase): + + def testPackTag(self): + field_number = 0xabc + tag_type = 2 + self.assertEqual((field_number << 3) | tag_type, + wire_format.PackTag(field_number, tag_type)) + PackTag = wire_format.PackTag + # Number too high. + self.assertRaises(message.EncodeError, PackTag, field_number, 6) + # Number too low. + self.assertRaises(message.EncodeError, PackTag, field_number, -1) + + def testUnpackTag(self): + # Test field numbers that will require various varint sizes. + for expected_field_number in (1, 15, 16, 2047, 2048): + for expected_wire_type in range(6): # Highest-numbered wiretype is 5. + field_number, wire_type = wire_format.UnpackTag( + wire_format.PackTag(expected_field_number, expected_wire_type)) + self.assertEqual(expected_field_number, field_number) + self.assertEqual(expected_wire_type, wire_type) + + self.assertRaises(TypeError, wire_format.UnpackTag, None) + self.assertRaises(TypeError, wire_format.UnpackTag, 'abc') + self.assertRaises(TypeError, wire_format.UnpackTag, 0.0) + self.assertRaises(TypeError, wire_format.UnpackTag, object()) + + def testZigZagEncode(self): + Z = wire_format.ZigZagEncode + self.assertEqual(0, Z(0)) + self.assertEqual(1, Z(-1)) + self.assertEqual(2, Z(1)) + self.assertEqual(3, Z(-2)) + self.assertEqual(4, Z(2)) + self.assertEqual(0xfffffffe, Z(0x7fffffff)) + self.assertEqual(0xffffffff, Z(-0x80000000)) + self.assertEqual(0xfffffffffffffffe, Z(0x7fffffffffffffff)) + self.assertEqual(0xffffffffffffffff, Z(-0x8000000000000000)) + + self.assertRaises(TypeError, Z, None) + self.assertRaises(TypeError, Z, 'abcd') + self.assertRaises(TypeError, Z, 0.0) + self.assertRaises(TypeError, Z, object()) + + def testZigZagDecode(self): + Z = wire_format.ZigZagDecode + self.assertEqual(0, Z(0)) + self.assertEqual(-1, Z(1)) + self.assertEqual(1, Z(2)) + self.assertEqual(-2, Z(3)) + self.assertEqual(2, Z(4)) + self.assertEqual(0x7fffffff, Z(0xfffffffe)) + self.assertEqual(-0x80000000, Z(0xffffffff)) + self.assertEqual(0x7fffffffffffffff, Z(0xfffffffffffffffe)) + self.assertEqual(-0x8000000000000000, Z(0xffffffffffffffff)) + + self.assertRaises(TypeError, Z, None) + self.assertRaises(TypeError, Z, 'abcd') + self.assertRaises(TypeError, Z, 0.0) + self.assertRaises(TypeError, Z, object()) + + def NumericByteSizeTestHelper(self, byte_size_fn, value, expected_value_size): + # Use field numbers that cause various byte sizes for the tag information. + for field_number, tag_bytes in ((15, 1), (16, 2), (2047, 2), (2048, 3)): + expected_size = expected_value_size + tag_bytes + actual_size = byte_size_fn(field_number, value) + self.assertEqual(expected_size, actual_size, + 'byte_size_fn: %s, field_number: %d, value: %r\n' + 'Expected: %d, Actual: %d'% ( + byte_size_fn, field_number, value, expected_size, actual_size)) + + def testByteSizeFunctions(self): + # Test all numeric *ByteSize() functions. + NUMERIC_ARGS = [ + # Int32ByteSize(). + [wire_format.Int32ByteSize, 0, 1], + [wire_format.Int32ByteSize, 127, 1], + [wire_format.Int32ByteSize, 128, 2], + [wire_format.Int32ByteSize, -1, 10], + # Int64ByteSize(). + [wire_format.Int64ByteSize, 0, 1], + [wire_format.Int64ByteSize, 127, 1], + [wire_format.Int64ByteSize, 128, 2], + [wire_format.Int64ByteSize, -1, 10], + # UInt32ByteSize(). + [wire_format.UInt32ByteSize, 0, 1], + [wire_format.UInt32ByteSize, 127, 1], + [wire_format.UInt32ByteSize, 128, 2], + [wire_format.UInt32ByteSize, wire_format.UINT32_MAX, 5], + # UInt64ByteSize(). + [wire_format.UInt64ByteSize, 0, 1], + [wire_format.UInt64ByteSize, 127, 1], + [wire_format.UInt64ByteSize, 128, 2], + [wire_format.UInt64ByteSize, wire_format.UINT64_MAX, 10], + # SInt32ByteSize(). + [wire_format.SInt32ByteSize, 0, 1], + [wire_format.SInt32ByteSize, -1, 1], + [wire_format.SInt32ByteSize, 1, 1], + [wire_format.SInt32ByteSize, -63, 1], + [wire_format.SInt32ByteSize, 63, 1], + [wire_format.SInt32ByteSize, -64, 1], + [wire_format.SInt32ByteSize, 64, 2], + # SInt64ByteSize(). + [wire_format.SInt64ByteSize, 0, 1], + [wire_format.SInt64ByteSize, -1, 1], + [wire_format.SInt64ByteSize, 1, 1], + [wire_format.SInt64ByteSize, -63, 1], + [wire_format.SInt64ByteSize, 63, 1], + [wire_format.SInt64ByteSize, -64, 1], + [wire_format.SInt64ByteSize, 64, 2], + # Fixed32ByteSize(). + [wire_format.Fixed32ByteSize, 0, 4], + [wire_format.Fixed32ByteSize, wire_format.UINT32_MAX, 4], + # Fixed64ByteSize(). + [wire_format.Fixed64ByteSize, 0, 8], + [wire_format.Fixed64ByteSize, wire_format.UINT64_MAX, 8], + # SFixed32ByteSize(). + [wire_format.SFixed32ByteSize, 0, 4], + [wire_format.SFixed32ByteSize, wire_format.INT32_MIN, 4], + [wire_format.SFixed32ByteSize, wire_format.INT32_MAX, 4], + # SFixed64ByteSize(). + [wire_format.SFixed64ByteSize, 0, 8], + [wire_format.SFixed64ByteSize, wire_format.INT64_MIN, 8], + [wire_format.SFixed64ByteSize, wire_format.INT64_MAX, 8], + # FloatByteSize(). + [wire_format.FloatByteSize, 0.0, 4], + [wire_format.FloatByteSize, 1000000000.0, 4], + [wire_format.FloatByteSize, -1000000000.0, 4], + # DoubleByteSize(). + [wire_format.DoubleByteSize, 0.0, 8], + [wire_format.DoubleByteSize, 1000000000.0, 8], + [wire_format.DoubleByteSize, -1000000000.0, 8], + # BoolByteSize(). + [wire_format.BoolByteSize, False, 1], + [wire_format.BoolByteSize, True, 1], + # EnumByteSize(). + [wire_format.EnumByteSize, 0, 1], + [wire_format.EnumByteSize, 127, 1], + [wire_format.EnumByteSize, 128, 2], + [wire_format.EnumByteSize, wire_format.UINT32_MAX, 5], + ] + for args in NUMERIC_ARGS: + self.NumericByteSizeTestHelper(*args) + + # Test strings and bytes. + for byte_size_fn in (wire_format.StringByteSize, wire_format.BytesByteSize): + # 1 byte for tag, 1 byte for length, 3 bytes for contents. + self.assertEqual(5, byte_size_fn(10, 'abc')) + # 2 bytes for tag, 1 byte for length, 3 bytes for contents. + self.assertEqual(6, byte_size_fn(16, 'abc')) + # 2 bytes for tag, 2 bytes for length, 128 bytes for contents. + self.assertEqual(132, byte_size_fn(16, 'a' * 128)) + + # Test UTF-8 string byte size calculation. + # 1 byte for tag, 1 byte for length, 8 bytes for content. + self.assertEqual(10, wire_format.StringByteSize( + 5, b'\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'.decode('utf-8'))) + + class MockMessage(object): + def __init__(self, byte_size): + self.byte_size = byte_size + def ByteSize(self): + return self.byte_size + + message_byte_size = 10 + mock_message = MockMessage(byte_size=message_byte_size) + # Test groups. + # (2 * 1) bytes for begin and end tags, plus message_byte_size. + self.assertEqual(2 + message_byte_size, + wire_format.GroupByteSize(1, mock_message)) + # (2 * 2) bytes for begin and end tags, plus message_byte_size. + self.assertEqual(4 + message_byte_size, + wire_format.GroupByteSize(16, mock_message)) + + # Test messages. + # 1 byte for tag, plus 1 byte for length, plus contents. + self.assertEqual(2 + mock_message.byte_size, + wire_format.MessageByteSize(1, mock_message)) + # 2 bytes for tag, plus 1 byte for length, plus contents. + self.assertEqual(3 + mock_message.byte_size, + wire_format.MessageByteSize(16, mock_message)) + # 2 bytes for tag, plus 2 bytes for length, plus contents. + mock_message.byte_size = 128 + self.assertEqual(4 + mock_message.byte_size, + wire_format.MessageByteSize(16, mock_message)) + + + # Test message set item byte size. + # 4 bytes for tags, plus 1 byte for length, plus 1 byte for type_id, + # plus contents. + mock_message.byte_size = 10 + self.assertEqual(mock_message.byte_size + 6, + wire_format.MessageSetItemByteSize(1, mock_message)) + + # 4 bytes for tags, plus 2 bytes for length, plus 1 byte for type_id, + # plus contents. + mock_message.byte_size = 128 + self.assertEqual(mock_message.byte_size + 7, + wire_format.MessageSetItemByteSize(1, mock_message)) + + # 4 bytes for tags, plus 2 bytes for length, plus 2 byte for type_id, + # plus contents. + self.assertEqual(mock_message.byte_size + 8, + wire_format.MessageSetItemByteSize(128, mock_message)) + + # Too-long varint. + self.assertRaises(message.EncodeError, + wire_format.UInt64ByteSize, 1, 1 << 128) + + +if __name__ == '__main__': + unittest.main() diff --git a/winvenv/Lib/site-packages/google/protobuf/json_format.py b/winvenv/Lib/site-packages/google/protobuf/json_format.py new file mode 100644 index 0000000..8d338d3 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/json_format.py @@ -0,0 +1,785 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains routines for printing protocol messages in JSON format. + +Simple usage example: + + # Create a proto object and serialize it to a json format string. + message = my_proto_pb2.MyMessage(foo='bar') + json_string = json_format.MessageToJson(message) + + # Parse a json format string to proto object. + message = json_format.Parse(json_string, my_proto_pb2.MyMessage()) +""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +# pylint: disable=g-statement-before-imports,g-import-not-at-top +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # PY26 +# pylint: enable=g-statement-before-imports,g-import-not-at-top + +import base64 +import json +import math + +from operator import methodcaller + +import re +import sys + +import six + +from google.protobuf import descriptor +from google.protobuf import symbol_database + + +_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' +_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32, + descriptor.FieldDescriptor.CPPTYPE_UINT32, + descriptor.FieldDescriptor.CPPTYPE_INT64, + descriptor.FieldDescriptor.CPPTYPE_UINT64]) +_INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64, + descriptor.FieldDescriptor.CPPTYPE_UINT64]) +_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, + descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) +_INFINITY = 'Infinity' +_NEG_INFINITY = '-Infinity' +_NAN = 'NaN' + +_UNPAIRED_SURROGATE_PATTERN = re.compile(six.u( + r'[\ud800-\udbff](?![\udc00-\udfff])|(?\n\nm_sfixed32\x18\t \x03(\x0b\x32*.protobuf_unittest.TestMaps.MSfixed32Entry\x12>\n\nm_sfixed64\x18\n \x03(\x0b\x32*.protobuf_unittest.TestMaps.MSfixed64Entry\x12\x36\n\x06m_bool\x18\x0b \x03(\x0b\x32&.protobuf_unittest.TestMaps.MBoolEntry\x12:\n\x08m_string\x18\x0c \x03(\x0b\x32(.protobuf_unittest.TestMaps.MStringEntry\x1aO\n\x0bMInt32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aO\n\x0bMInt64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMUint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMUint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMSint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMSint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aQ\n\rMFixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aQ\n\rMFixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aR\n\x0eMSfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aR\n\x0eMSfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aN\n\nMBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\x1aP\n\x0cMStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12/\n\x05value\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestIntIntMap:\x02\x38\x01\"<\n\x12TestSubmessageMaps\x12&\n\x01m\x18\x01 \x01(\x0b\x32\x1b.protobuf_unittest.TestMaps*Z\n\rProto2MapEnum\x12\x17\n\x13PROTO2_MAP_ENUM_FOO\x10\x00\x12\x17\n\x13PROTO2_MAP_ENUM_BAR\x10\x01\x12\x17\n\x13PROTO2_MAP_ENUM_BAZ\x10\x02*\x86\x01\n\x16Proto2MapEnumPlusExtra\x12\x19\n\x15\x45_PROTO2_MAP_ENUM_FOO\x10\x00\x12\x19\n\x15\x45_PROTO2_MAP_ENUM_BAR\x10\x01\x12\x19\n\x15\x45_PROTO2_MAP_ENUM_BAZ\x10\x02\x12\x1b\n\x17\x45_PROTO2_MAP_ENUM_EXTRA\x10\x03\x42\x03\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,]) + +_PROTO2MAPENUM = _descriptor.EnumDescriptor( + name='Proto2MapEnum', + full_name='protobuf_unittest.Proto2MapEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='PROTO2_MAP_ENUM_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='PROTO2_MAP_ENUM_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='PROTO2_MAP_ENUM_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2946, + serialized_end=3036, +) +_sym_db.RegisterEnumDescriptor(_PROTO2MAPENUM) + +Proto2MapEnum = enum_type_wrapper.EnumTypeWrapper(_PROTO2MAPENUM) +_PROTO2MAPENUMPLUSEXTRA = _descriptor.EnumDescriptor( + name='Proto2MapEnumPlusExtra', + full_name='protobuf_unittest.Proto2MapEnumPlusExtra', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_BAZ', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='E_PROTO2_MAP_ENUM_EXTRA', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3039, + serialized_end=3173, +) +_sym_db.RegisterEnumDescriptor(_PROTO2MAPENUMPLUSEXTRA) + +Proto2MapEnumPlusExtra = enum_type_wrapper.EnumTypeWrapper(_PROTO2MAPENUMPLUSEXTRA) +PROTO2_MAP_ENUM_FOO = 0 +PROTO2_MAP_ENUM_BAR = 1 +PROTO2_MAP_ENUM_BAZ = 2 +E_PROTO2_MAP_ENUM_FOO = 0 +E_PROTO2_MAP_ENUM_BAR = 1 +E_PROTO2_MAP_ENUM_BAZ = 2 +E_PROTO2_MAP_ENUM_EXTRA = 3 + + + +_TESTENUMMAP_KNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='KnownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMap.KnownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMap.KnownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMap.KnownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=275, + serialized_end=361, +) + +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='UnknownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMap.UnknownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMap.UnknownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMap.UnknownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=363, + serialized_end=451, +) + +_TESTENUMMAP = _descriptor.Descriptor( + name='TestEnumMap', + full_name='protobuf_unittest.TestEnumMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='known_map_field', full_name='protobuf_unittest.TestEnumMap.known_map_field', index=0, + number=101, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unknown_map_field', full_name='protobuf_unittest.TestEnumMap.unknown_map_field', index=1, + number=102, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTENUMMAP_KNOWNMAPFIELDENTRY, _TESTENUMMAP_UNKNOWNMAPFIELDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=104, + serialized_end=451, +) + + +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='KnownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=652, + serialized_end=747, +) + +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY = _descriptor.Descriptor( + name='UnknownMapFieldEntry', + full_name='protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=749, + serialized_end=846, +) + +_TESTENUMMAPPLUSEXTRA = _descriptor.Descriptor( + name='TestEnumMapPlusExtra', + full_name='protobuf_unittest.TestEnumMapPlusExtra', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='known_map_field', full_name='protobuf_unittest.TestEnumMapPlusExtra.known_map_field', index=0, + number=101, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unknown_map_field', full_name='protobuf_unittest.TestEnumMapPlusExtra.unknown_map_field', index=1, + number=102, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY, _TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=454, + serialized_end=846, +) + + +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY = _descriptor.Descriptor( + name='ImportEnumAmpEntry', + full_name='protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=952, + serialized_end=1048, +) + +_TESTIMPORTENUMMAP = _descriptor.Descriptor( + name='TestImportEnumMap', + full_name='protobuf_unittest.TestImportEnumMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='import_enum_amp', full_name='protobuf_unittest.TestImportEnumMap.import_enum_amp', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=849, + serialized_end=1048, +) + + +_TESTINTINTMAP_MENTRY = _descriptor.Descriptor( + name='MEntry', + full_name='protobuf_unittest.TestIntIntMap.MEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestIntIntMap.MEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestIntIntMap.MEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1119, + serialized_end=1159, +) + +_TESTINTINTMAP = _descriptor.Descriptor( + name='TestIntIntMap', + full_name='protobuf_unittest.TestIntIntMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='m', full_name='protobuf_unittest.TestIntIntMap.m', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTINTINTMAP_MENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1050, + serialized_end=1159, +) + + +_TESTMAPS_MINT32ENTRY = _descriptor.Descriptor( + name='MInt32Entry', + full_name='protobuf_unittest.TestMaps.MInt32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MInt32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MInt32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1898, + serialized_end=1977, +) + +_TESTMAPS_MINT64ENTRY = _descriptor.Descriptor( + name='MInt64Entry', + full_name='protobuf_unittest.TestMaps.MInt64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MInt64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MInt64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1979, + serialized_end=2058, +) + +_TESTMAPS_MUINT32ENTRY = _descriptor.Descriptor( + name='MUint32Entry', + full_name='protobuf_unittest.TestMaps.MUint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MUint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MUint32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2060, + serialized_end=2140, +) + +_TESTMAPS_MUINT64ENTRY = _descriptor.Descriptor( + name='MUint64Entry', + full_name='protobuf_unittest.TestMaps.MUint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MUint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MUint64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2142, + serialized_end=2222, +) + +_TESTMAPS_MSINT32ENTRY = _descriptor.Descriptor( + name='MSint32Entry', + full_name='protobuf_unittest.TestMaps.MSint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSint32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2224, + serialized_end=2304, +) + +_TESTMAPS_MSINT64ENTRY = _descriptor.Descriptor( + name='MSint64Entry', + full_name='protobuf_unittest.TestMaps.MSint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSint64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2306, + serialized_end=2386, +) + +_TESTMAPS_MFIXED32ENTRY = _descriptor.Descriptor( + name='MFixed32Entry', + full_name='protobuf_unittest.TestMaps.MFixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MFixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MFixed32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2388, + serialized_end=2469, +) + +_TESTMAPS_MFIXED64ENTRY = _descriptor.Descriptor( + name='MFixed64Entry', + full_name='protobuf_unittest.TestMaps.MFixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MFixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MFixed64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2471, + serialized_end=2552, +) + +_TESTMAPS_MSFIXED32ENTRY = _descriptor.Descriptor( + name='MSfixed32Entry', + full_name='protobuf_unittest.TestMaps.MSfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSfixed32Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2554, + serialized_end=2636, +) + +_TESTMAPS_MSFIXED64ENTRY = _descriptor.Descriptor( + name='MSfixed64Entry', + full_name='protobuf_unittest.TestMaps.MSfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MSfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MSfixed64Entry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2638, + serialized_end=2720, +) + +_TESTMAPS_MBOOLENTRY = _descriptor.Descriptor( + name='MBoolEntry', + full_name='protobuf_unittest.TestMaps.MBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MBoolEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2722, + serialized_end=2800, +) + +_TESTMAPS_MSTRINGENTRY = _descriptor.Descriptor( + name='MStringEntry', + full_name='protobuf_unittest.TestMaps.MStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMaps.MStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMaps.MStringEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2802, + serialized_end=2882, +) + +_TESTMAPS = _descriptor.Descriptor( + name='TestMaps', + full_name='protobuf_unittest.TestMaps', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='m_int32', full_name='protobuf_unittest.TestMaps.m_int32', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_int64', full_name='protobuf_unittest.TestMaps.m_int64', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_uint32', full_name='protobuf_unittest.TestMaps.m_uint32', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_uint64', full_name='protobuf_unittest.TestMaps.m_uint64', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sint32', full_name='protobuf_unittest.TestMaps.m_sint32', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sint64', full_name='protobuf_unittest.TestMaps.m_sint64', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_fixed32', full_name='protobuf_unittest.TestMaps.m_fixed32', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_fixed64', full_name='protobuf_unittest.TestMaps.m_fixed64', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sfixed32', full_name='protobuf_unittest.TestMaps.m_sfixed32', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_sfixed64', full_name='protobuf_unittest.TestMaps.m_sfixed64', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_bool', full_name='protobuf_unittest.TestMaps.m_bool', index=10, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='m_string', full_name='protobuf_unittest.TestMaps.m_string', index=11, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMAPS_MINT32ENTRY, _TESTMAPS_MINT64ENTRY, _TESTMAPS_MUINT32ENTRY, _TESTMAPS_MUINT64ENTRY, _TESTMAPS_MSINT32ENTRY, _TESTMAPS_MSINT64ENTRY, _TESTMAPS_MFIXED32ENTRY, _TESTMAPS_MFIXED64ENTRY, _TESTMAPS_MSFIXED32ENTRY, _TESTMAPS_MSFIXED64ENTRY, _TESTMAPS_MBOOLENTRY, _TESTMAPS_MSTRINGENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1162, + serialized_end=2882, +) + + +_TESTSUBMESSAGEMAPS = _descriptor.Descriptor( + name='TestSubmessageMaps', + full_name='protobuf_unittest.TestSubmessageMaps', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='m', full_name='protobuf_unittest.TestSubmessageMaps.m', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2884, + serialized_end=2944, +) + +_TESTENUMMAP_KNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUM +_TESTENUMMAP_KNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAP +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUM +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAP +_TESTENUMMAP.fields_by_name['known_map_field'].message_type = _TESTENUMMAP_KNOWNMAPFIELDENTRY +_TESTENUMMAP.fields_by_name['unknown_map_field'].message_type = _TESTENUMMAP_UNKNOWNMAPFIELDENTRY +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUMPLUSEXTRA +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAPPLUSEXTRA +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY.fields_by_name['value'].enum_type = _PROTO2MAPENUMPLUSEXTRA +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY.containing_type = _TESTENUMMAPPLUSEXTRA +_TESTENUMMAPPLUSEXTRA.fields_by_name['known_map_field'].message_type = _TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY +_TESTENUMMAPPLUSEXTRA.fields_by_name['unknown_map_field'].message_type = _TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY.fields_by_name['value'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUMFORMAP +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY.containing_type = _TESTIMPORTENUMMAP +_TESTIMPORTENUMMAP.fields_by_name['import_enum_amp'].message_type = _TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY +_TESTINTINTMAP_MENTRY.containing_type = _TESTINTINTMAP +_TESTINTINTMAP.fields_by_name['m'].message_type = _TESTINTINTMAP_MENTRY +_TESTMAPS_MINT32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MINT32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MINT64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MINT64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MUINT32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MUINT32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MUINT64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MUINT64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSINT32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSINT32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSINT64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSINT64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MFIXED32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MFIXED32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MFIXED64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MFIXED64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSFIXED32ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSFIXED32ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSFIXED64ENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSFIXED64ENTRY.containing_type = _TESTMAPS +_TESTMAPS_MBOOLENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MBOOLENTRY.containing_type = _TESTMAPS +_TESTMAPS_MSTRINGENTRY.fields_by_name['value'].message_type = _TESTINTINTMAP +_TESTMAPS_MSTRINGENTRY.containing_type = _TESTMAPS +_TESTMAPS.fields_by_name['m_int32'].message_type = _TESTMAPS_MINT32ENTRY +_TESTMAPS.fields_by_name['m_int64'].message_type = _TESTMAPS_MINT64ENTRY +_TESTMAPS.fields_by_name['m_uint32'].message_type = _TESTMAPS_MUINT32ENTRY +_TESTMAPS.fields_by_name['m_uint64'].message_type = _TESTMAPS_MUINT64ENTRY +_TESTMAPS.fields_by_name['m_sint32'].message_type = _TESTMAPS_MSINT32ENTRY +_TESTMAPS.fields_by_name['m_sint64'].message_type = _TESTMAPS_MSINT64ENTRY +_TESTMAPS.fields_by_name['m_fixed32'].message_type = _TESTMAPS_MFIXED32ENTRY +_TESTMAPS.fields_by_name['m_fixed64'].message_type = _TESTMAPS_MFIXED64ENTRY +_TESTMAPS.fields_by_name['m_sfixed32'].message_type = _TESTMAPS_MSFIXED32ENTRY +_TESTMAPS.fields_by_name['m_sfixed64'].message_type = _TESTMAPS_MSFIXED64ENTRY +_TESTMAPS.fields_by_name['m_bool'].message_type = _TESTMAPS_MBOOLENTRY +_TESTMAPS.fields_by_name['m_string'].message_type = _TESTMAPS_MSTRINGENTRY +_TESTSUBMESSAGEMAPS.fields_by_name['m'].message_type = _TESTMAPS +DESCRIPTOR.message_types_by_name['TestEnumMap'] = _TESTENUMMAP +DESCRIPTOR.message_types_by_name['TestEnumMapPlusExtra'] = _TESTENUMMAPPLUSEXTRA +DESCRIPTOR.message_types_by_name['TestImportEnumMap'] = _TESTIMPORTENUMMAP +DESCRIPTOR.message_types_by_name['TestIntIntMap'] = _TESTINTINTMAP +DESCRIPTOR.message_types_by_name['TestMaps'] = _TESTMAPS +DESCRIPTOR.message_types_by_name['TestSubmessageMaps'] = _TESTSUBMESSAGEMAPS +DESCRIPTOR.enum_types_by_name['Proto2MapEnum'] = _PROTO2MAPENUM +DESCRIPTOR.enum_types_by_name['Proto2MapEnumPlusExtra'] = _PROTO2MAPENUMPLUSEXTRA +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestEnumMap = _reflection.GeneratedProtocolMessageType('TestEnumMap', (_message.Message,), dict( + + KnownMapFieldEntry = _reflection.GeneratedProtocolMessageType('KnownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAP_KNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMap.KnownMapFieldEntry) + )) + , + + UnknownMapFieldEntry = _reflection.GeneratedProtocolMessageType('UnknownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAP_UNKNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMap.UnknownMapFieldEntry) + )) + , + DESCRIPTOR = _TESTENUMMAP, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMap) + )) +_sym_db.RegisterMessage(TestEnumMap) +_sym_db.RegisterMessage(TestEnumMap.KnownMapFieldEntry) +_sym_db.RegisterMessage(TestEnumMap.UnknownMapFieldEntry) + +TestEnumMapPlusExtra = _reflection.GeneratedProtocolMessageType('TestEnumMapPlusExtra', (_message.Message,), dict( + + KnownMapFieldEntry = _reflection.GeneratedProtocolMessageType('KnownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMapPlusExtra.KnownMapFieldEntry) + )) + , + + UnknownMapFieldEntry = _reflection.GeneratedProtocolMessageType('UnknownMapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMapPlusExtra.UnknownMapFieldEntry) + )) + , + DESCRIPTOR = _TESTENUMMAPPLUSEXTRA, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEnumMapPlusExtra) + )) +_sym_db.RegisterMessage(TestEnumMapPlusExtra) +_sym_db.RegisterMessage(TestEnumMapPlusExtra.KnownMapFieldEntry) +_sym_db.RegisterMessage(TestEnumMapPlusExtra.UnknownMapFieldEntry) + +TestImportEnumMap = _reflection.GeneratedProtocolMessageType('TestImportEnumMap', (_message.Message,), dict( + + ImportEnumAmpEntry = _reflection.GeneratedProtocolMessageType('ImportEnumAmpEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestImportEnumMap.ImportEnumAmpEntry) + )) + , + DESCRIPTOR = _TESTIMPORTENUMMAP, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestImportEnumMap) + )) +_sym_db.RegisterMessage(TestImportEnumMap) +_sym_db.RegisterMessage(TestImportEnumMap.ImportEnumAmpEntry) + +TestIntIntMap = _reflection.GeneratedProtocolMessageType('TestIntIntMap', (_message.Message,), dict( + + MEntry = _reflection.GeneratedProtocolMessageType('MEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTINTINTMAP_MENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIntIntMap.MEntry) + )) + , + DESCRIPTOR = _TESTINTINTMAP, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIntIntMap) + )) +_sym_db.RegisterMessage(TestIntIntMap) +_sym_db.RegisterMessage(TestIntIntMap.MEntry) + +TestMaps = _reflection.GeneratedProtocolMessageType('TestMaps', (_message.Message,), dict( + + MInt32Entry = _reflection.GeneratedProtocolMessageType('MInt32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MINT32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MInt32Entry) + )) + , + + MInt64Entry = _reflection.GeneratedProtocolMessageType('MInt64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MINT64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MInt64Entry) + )) + , + + MUint32Entry = _reflection.GeneratedProtocolMessageType('MUint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MUINT32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MUint32Entry) + )) + , + + MUint64Entry = _reflection.GeneratedProtocolMessageType('MUint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MUINT64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MUint64Entry) + )) + , + + MSint32Entry = _reflection.GeneratedProtocolMessageType('MSint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSINT32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSint32Entry) + )) + , + + MSint64Entry = _reflection.GeneratedProtocolMessageType('MSint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSINT64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSint64Entry) + )) + , + + MFixed32Entry = _reflection.GeneratedProtocolMessageType('MFixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MFIXED32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MFixed32Entry) + )) + , + + MFixed64Entry = _reflection.GeneratedProtocolMessageType('MFixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MFIXED64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MFixed64Entry) + )) + , + + MSfixed32Entry = _reflection.GeneratedProtocolMessageType('MSfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSFIXED32ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSfixed32Entry) + )) + , + + MSfixed64Entry = _reflection.GeneratedProtocolMessageType('MSfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSFIXED64ENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MSfixed64Entry) + )) + , + + MBoolEntry = _reflection.GeneratedProtocolMessageType('MBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MBOOLENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MBoolEntry) + )) + , + + MStringEntry = _reflection.GeneratedProtocolMessageType('MStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPS_MSTRINGENTRY, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps.MStringEntry) + )) + , + DESCRIPTOR = _TESTMAPS, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMaps) + )) +_sym_db.RegisterMessage(TestMaps) +_sym_db.RegisterMessage(TestMaps.MInt32Entry) +_sym_db.RegisterMessage(TestMaps.MInt64Entry) +_sym_db.RegisterMessage(TestMaps.MUint32Entry) +_sym_db.RegisterMessage(TestMaps.MUint64Entry) +_sym_db.RegisterMessage(TestMaps.MSint32Entry) +_sym_db.RegisterMessage(TestMaps.MSint64Entry) +_sym_db.RegisterMessage(TestMaps.MFixed32Entry) +_sym_db.RegisterMessage(TestMaps.MFixed64Entry) +_sym_db.RegisterMessage(TestMaps.MSfixed32Entry) +_sym_db.RegisterMessage(TestMaps.MSfixed64Entry) +_sym_db.RegisterMessage(TestMaps.MBoolEntry) +_sym_db.RegisterMessage(TestMaps.MStringEntry) + +TestSubmessageMaps = _reflection.GeneratedProtocolMessageType('TestSubmessageMaps', (_message.Message,), dict( + DESCRIPTOR = _TESTSUBMESSAGEMAPS, + __module__ = 'google.protobuf.map_proto2_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSubmessageMaps) + )) +_sym_db.RegisterMessage(TestSubmessageMaps) + + +DESCRIPTOR._options = None +_TESTENUMMAP_KNOWNMAPFIELDENTRY._options = None +_TESTENUMMAP_UNKNOWNMAPFIELDENTRY._options = None +_TESTENUMMAPPLUSEXTRA_KNOWNMAPFIELDENTRY._options = None +_TESTENUMMAPPLUSEXTRA_UNKNOWNMAPFIELDENTRY._options = None +_TESTIMPORTENUMMAP_IMPORTENUMAMPENTRY._options = None +_TESTINTINTMAP_MENTRY._options = None +_TESTMAPS_MINT32ENTRY._options = None +_TESTMAPS_MINT64ENTRY._options = None +_TESTMAPS_MUINT32ENTRY._options = None +_TESTMAPS_MUINT64ENTRY._options = None +_TESTMAPS_MSINT32ENTRY._options = None +_TESTMAPS_MSINT64ENTRY._options = None +_TESTMAPS_MFIXED32ENTRY._options = None +_TESTMAPS_MFIXED64ENTRY._options = None +_TESTMAPS_MSFIXED32ENTRY._options = None +_TESTMAPS_MSFIXED64ENTRY._options = None +_TESTMAPS_MBOOLENTRY._options = None +_TESTMAPS_MSTRINGENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/map_unittest_pb2.py b/winvenv/Lib/site-packages/google/protobuf/map_unittest_pb2.py new file mode 100644 index 0000000..af1eca0 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/map_unittest_pb2.py @@ -0,0 +1,2813 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/map_unittest.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_pb2 as google_dot_protobuf_dot_unittest__pb2 +from google.protobuf import unittest_no_arena_pb2 as google_dot_protobuf_dot_unittest__no__arena__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/map_unittest.proto', + package='protobuf_unittest', + syntax='proto3', + serialized_options=_b('\370\001\001'), + serialized_pb=_b('\n\"google/protobuf/map_unittest.proto\x12\x11protobuf_unittest\x1a\x1egoogle/protobuf/unittest.proto\x1a\'google/protobuf/unittest_no_arena.proto\"\xff\x14\n\x07TestMap\x12\x46\n\x0fmap_int32_int32\x18\x01 \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt32Int32Entry\x12\x46\n\x0fmap_int64_int64\x18\x02 \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt64Int64Entry\x12J\n\x11map_uint32_uint32\x18\x03 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapUint32Uint32Entry\x12J\n\x11map_uint64_uint64\x18\x04 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapUint64Uint64Entry\x12J\n\x11map_sint32_sint32\x18\x05 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapSint32Sint32Entry\x12J\n\x11map_sint64_sint64\x18\x06 \x03(\x0b\x32/.protobuf_unittest.TestMap.MapSint64Sint64Entry\x12N\n\x13map_fixed32_fixed32\x18\x07 \x03(\x0b\x32\x31.protobuf_unittest.TestMap.MapFixed32Fixed32Entry\x12N\n\x13map_fixed64_fixed64\x18\x08 \x03(\x0b\x32\x31.protobuf_unittest.TestMap.MapFixed64Fixed64Entry\x12R\n\x15map_sfixed32_sfixed32\x18\t \x03(\x0b\x32\x33.protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry\x12R\n\x15map_sfixed64_sfixed64\x18\n \x03(\x0b\x32\x33.protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry\x12\x46\n\x0fmap_int32_float\x18\x0b \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt32FloatEntry\x12H\n\x10map_int32_double\x18\x0c \x03(\x0b\x32..protobuf_unittest.TestMap.MapInt32DoubleEntry\x12\x42\n\rmap_bool_bool\x18\r \x03(\x0b\x32+.protobuf_unittest.TestMap.MapBoolBoolEntry\x12J\n\x11map_string_string\x18\x0e \x03(\x0b\x32/.protobuf_unittest.TestMap.MapStringStringEntry\x12\x46\n\x0fmap_int32_bytes\x18\x0f \x03(\x0b\x32-.protobuf_unittest.TestMap.MapInt32BytesEntry\x12\x44\n\x0emap_int32_enum\x18\x10 \x03(\x0b\x32,.protobuf_unittest.TestMap.MapInt32EnumEntry\x12Y\n\x19map_int32_foreign_message\x18\x11 \x03(\x0b\x32\x36.protobuf_unittest.TestMap.MapInt32ForeignMessageEntry\x12[\n\x1amap_string_foreign_message\x18\x12 \x03(\x0b\x32\x37.protobuf_unittest.TestMap.MapStringForeignMessageEntry\x12M\n\x13map_int32_all_types\x18\x13 \x03(\x0b\x32\x30.protobuf_unittest.TestMap.MapInt32AllTypesEntry\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12MapInt32BytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1aO\n\x11MapInt32EnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12)\n\x05value\x18\x02 \x01(\x0e\x32\x1a.protobuf_unittest.MapEnum:\x02\x38\x01\x1a`\n\x1bMapInt32ForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:\x02\x38\x01\x1a\x61\n\x1cMapStringForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:\x02\x38\x01\x1aX\n\x15MapInt32AllTypesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes:\x02\x38\x01\"A\n\x11TestMapSubmessage\x12,\n\x08test_map\x18\x01 \x01(\x0b\x32\x1a.protobuf_unittest.TestMap\"\xbc\x01\n\x0eTestMessageMap\x12Q\n\x11map_int32_message\x18\x01 \x03(\x0b\x32\x36.protobuf_unittest.TestMessageMap.MapInt32MessageEntry\x1aW\n\x14MapInt32MessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes:\x02\x38\x01\"\xe3\x01\n\x0fTestSameTypeMap\x12:\n\x04map1\x18\x01 \x03(\x0b\x32,.protobuf_unittest.TestSameTypeMap.Map1Entry\x12:\n\x04map2\x18\x02 \x03(\x0b\x32,.protobuf_unittest.TestSameTypeMap.Map2Entry\x1a+\n\tMap1Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tMap2Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xb6\x01\n\x16TestRequiredMessageMap\x12J\n\tmap_field\x18\x01 \x03(\x0b\x32\x37.protobuf_unittest.TestRequiredMessageMap.MapFieldEntry\x1aP\n\rMapFieldEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired:\x02\x38\x01\"\xd2\x14\n\x0cTestArenaMap\x12K\n\x0fmap_int32_int32\x18\x01 \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt32Int32Entry\x12K\n\x0fmap_int64_int64\x18\x02 \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt64Int64Entry\x12O\n\x11map_uint32_uint32\x18\x03 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapUint32Uint32Entry\x12O\n\x11map_uint64_uint64\x18\x04 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapUint64Uint64Entry\x12O\n\x11map_sint32_sint32\x18\x05 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapSint32Sint32Entry\x12O\n\x11map_sint64_sint64\x18\x06 \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapSint64Sint64Entry\x12S\n\x13map_fixed32_fixed32\x18\x07 \x03(\x0b\x32\x36.protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry\x12S\n\x13map_fixed64_fixed64\x18\x08 \x03(\x0b\x32\x36.protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry\x12W\n\x15map_sfixed32_sfixed32\x18\t \x03(\x0b\x32\x38.protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry\x12W\n\x15map_sfixed64_sfixed64\x18\n \x03(\x0b\x32\x38.protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry\x12K\n\x0fmap_int32_float\x18\x0b \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt32FloatEntry\x12M\n\x10map_int32_double\x18\x0c \x03(\x0b\x32\x33.protobuf_unittest.TestArenaMap.MapInt32DoubleEntry\x12G\n\rmap_bool_bool\x18\r \x03(\x0b\x32\x30.protobuf_unittest.TestArenaMap.MapBoolBoolEntry\x12O\n\x11map_string_string\x18\x0e \x03(\x0b\x32\x34.protobuf_unittest.TestArenaMap.MapStringStringEntry\x12K\n\x0fmap_int32_bytes\x18\x0f \x03(\x0b\x32\x32.protobuf_unittest.TestArenaMap.MapInt32BytesEntry\x12I\n\x0emap_int32_enum\x18\x10 \x03(\x0b\x32\x31.protobuf_unittest.TestArenaMap.MapInt32EnumEntry\x12^\n\x19map_int32_foreign_message\x18\x11 \x03(\x0b\x32;.protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry\x12n\n\"map_int32_foreign_message_no_arena\x18\x12 \x03(\x0b\x32\x42.protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12MapInt32BytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1aO\n\x11MapInt32EnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12)\n\x05value\x18\x02 \x01(\x0e\x32\x1a.protobuf_unittest.MapEnum:\x02\x38\x01\x1a`\n\x1bMapInt32ForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:\x02\x38\x01\x1ap\n\"MapInt32ForeignMessageNoArenaEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.protobuf_unittest_no_arena.ForeignMessage:\x02\x38\x01\"\xe4\x01\n\x1fMessageContainingEnumCalledType\x12J\n\x04type\x18\x01 \x03(\x0b\x32<.protobuf_unittest.MessageContainingEnumCalledType.TypeEntry\x1a_\n\tTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x41\n\x05value\x18\x02 \x01(\x0b\x32\x32.protobuf_unittest.MessageContainingEnumCalledType:\x02\x38\x01\"\x14\n\x04Type\x12\x0c\n\x08TYPE_FOO\x10\x00\"\x9d\x01\n\x1fMessageContainingMapCalledEntry\x12L\n\x05\x65ntry\x18\x01 \x03(\x0b\x32=.protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry\x1a,\n\nEntryEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\xad\x01\n\x17TestRecursiveMapMessage\x12<\n\x01\x61\x18\x01 \x03(\x0b\x32\x31.protobuf_unittest.TestRecursiveMapMessage.AEntry\x1aT\n\x06\x41\x45ntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0b\x32*.protobuf_unittest.TestRecursiveMapMessage:\x02\x38\x01*?\n\x07MapEnum\x12\x10\n\x0cMAP_ENUM_FOO\x10\x00\x12\x10\n\x0cMAP_ENUM_BAR\x10\x01\x12\x10\n\x0cMAP_ENUM_BAZ\x10\x02\x42\x03\xf8\x01\x01\x62\x06proto3') + , + dependencies=[google_dot_protobuf_dot_unittest__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__no__arena__pb2.DESCRIPTOR,]) + +_MAPENUM = _descriptor.EnumDescriptor( + name='MapEnum', + full_name='protobuf_unittest.MapEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='MAP_ENUM_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MAP_ENUM_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MAP_ENUM_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6705, + serialized_end=6768, +) +_sym_db.RegisterEnumDescriptor(_MAPENUM) + +MapEnum = enum_type_wrapper.EnumTypeWrapper(_MAPENUM) +MAP_ENUM_FOO = 0 +MAP_ENUM_BAR = 1 +MAP_ENUM_BAZ = 2 + + +_MESSAGECONTAININGENUMCALLEDTYPE_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='protobuf_unittest.MessageContainingEnumCalledType.Type', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_FOO', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6347, + serialized_end=6367, +) +_sym_db.RegisterEnumDescriptor(_MESSAGECONTAININGENUMCALLEDTYPE_TYPE) + + +_TESTMAP_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_unittest.TestMap.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1613, + serialized_end=1665, +) + +_TESTMAP_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_unittest.TestMap.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1667, + serialized_end=1719, +) + +_TESTMAP_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_unittest.TestMap.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1721, + serialized_end=1775, +) + +_TESTMAP_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_unittest.TestMap.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1777, + serialized_end=1831, +) + +_TESTMAP_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_unittest.TestMap.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1833, + serialized_end=1887, +) + +_TESTMAP_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_unittest.TestMap.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1889, + serialized_end=1943, +) + +_TESTMAP_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_unittest.TestMap.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1945, + serialized_end=2001, +) + +_TESTMAP_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_unittest.TestMap.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2003, + serialized_end=2059, +) + +_TESTMAP_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2061, + serialized_end=2119, +) + +_TESTMAP_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2121, + serialized_end=2179, +) + +_TESTMAP_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_unittest.TestMap.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2181, + serialized_end=2233, +) + +_TESTMAP_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_unittest.TestMap.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2235, + serialized_end=2288, +) + +_TESTMAP_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_unittest.TestMap.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2290, + serialized_end=2340, +) + +_TESTMAP_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_unittest.TestMap.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2342, + serialized_end=2396, +) + +_TESTMAP_MAPINT32BYTESENTRY = _descriptor.Descriptor( + name='MapInt32BytesEntry', + full_name='protobuf_unittest.TestMap.MapInt32BytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32BytesEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32BytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2398, + serialized_end=2450, +) + +_TESTMAP_MAPINT32ENUMENTRY = _descriptor.Descriptor( + name='MapInt32EnumEntry', + full_name='protobuf_unittest.TestMap.MapInt32EnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32EnumEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32EnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2452, + serialized_end=2531, +) + +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapInt32ForeignMessageEntry', + full_name='protobuf_unittest.TestMap.MapInt32ForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32ForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2533, + serialized_end=2629, +) + +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringForeignMessageEntry', + full_name='protobuf_unittest.TestMap.MapStringForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapStringForeignMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapStringForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2631, + serialized_end=2728, +) + +_TESTMAP_MAPINT32ALLTYPESENTRY = _descriptor.Descriptor( + name='MapInt32AllTypesEntry', + full_name='protobuf_unittest.TestMap.MapInt32AllTypesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMap.MapInt32AllTypesEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMap.MapInt32AllTypesEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2730, + serialized_end=2818, +) + +_TESTMAP = _descriptor.Descriptor( + name='TestMap', + full_name='protobuf_unittest.TestMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_unittest.TestMap.map_int32_int32', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_unittest.TestMap.map_int64_int64', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_unittest.TestMap.map_uint32_uint32', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_unittest.TestMap.map_uint64_uint64', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_unittest.TestMap.map_sint32_sint32', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_unittest.TestMap.map_sint64_sint64', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_unittest.TestMap.map_fixed32_fixed32', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_unittest.TestMap.map_fixed64_fixed64', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_unittest.TestMap.map_sfixed32_sfixed32', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_unittest.TestMap.map_sfixed64_sfixed64', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_unittest.TestMap.map_int32_float', index=10, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_unittest.TestMap.map_int32_double', index=11, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_unittest.TestMap.map_bool_bool', index=12, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_unittest.TestMap.map_string_string', index=13, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_bytes', full_name='protobuf_unittest.TestMap.map_int32_bytes', index=14, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_enum', full_name='protobuf_unittest.TestMap.map_int32_enum', index=15, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_foreign_message', full_name='protobuf_unittest.TestMap.map_int32_foreign_message', index=16, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_message', full_name='protobuf_unittest.TestMap.map_string_foreign_message', index=17, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_all_types', full_name='protobuf_unittest.TestMap.map_int32_all_types', index=18, + number=19, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMAP_MAPINT32INT32ENTRY, _TESTMAP_MAPINT64INT64ENTRY, _TESTMAP_MAPUINT32UINT32ENTRY, _TESTMAP_MAPUINT64UINT64ENTRY, _TESTMAP_MAPSINT32SINT32ENTRY, _TESTMAP_MAPSINT64SINT64ENTRY, _TESTMAP_MAPFIXED32FIXED32ENTRY, _TESTMAP_MAPFIXED64FIXED64ENTRY, _TESTMAP_MAPSFIXED32SFIXED32ENTRY, _TESTMAP_MAPSFIXED64SFIXED64ENTRY, _TESTMAP_MAPINT32FLOATENTRY, _TESTMAP_MAPINT32DOUBLEENTRY, _TESTMAP_MAPBOOLBOOLENTRY, _TESTMAP_MAPSTRINGSTRINGENTRY, _TESTMAP_MAPINT32BYTESENTRY, _TESTMAP_MAPINT32ENUMENTRY, _TESTMAP_MAPINT32FOREIGNMESSAGEENTRY, _TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY, _TESTMAP_MAPINT32ALLTYPESENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=131, + serialized_end=2818, +) + + +_TESTMAPSUBMESSAGE = _descriptor.Descriptor( + name='TestMapSubmessage', + full_name='protobuf_unittest.TestMapSubmessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='test_map', full_name='protobuf_unittest.TestMapSubmessage.test_map', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2820, + serialized_end=2885, +) + + +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY = _descriptor.Descriptor( + name='MapInt32MessageEntry', + full_name='protobuf_unittest.TestMessageMap.MapInt32MessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestMessageMap.MapInt32MessageEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestMessageMap.MapInt32MessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2989, + serialized_end=3076, +) + +_TESTMESSAGEMAP = _descriptor.Descriptor( + name='TestMessageMap', + full_name='protobuf_unittest.TestMessageMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_int32_message', full_name='protobuf_unittest.TestMessageMap.map_int32_message', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2888, + serialized_end=3076, +) + + +_TESTSAMETYPEMAP_MAP1ENTRY = _descriptor.Descriptor( + name='Map1Entry', + full_name='protobuf_unittest.TestSameTypeMap.Map1Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestSameTypeMap.Map1Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestSameTypeMap.Map1Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3218, + serialized_end=3261, +) + +_TESTSAMETYPEMAP_MAP2ENTRY = _descriptor.Descriptor( + name='Map2Entry', + full_name='protobuf_unittest.TestSameTypeMap.Map2Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestSameTypeMap.Map2Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestSameTypeMap.Map2Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3263, + serialized_end=3306, +) + +_TESTSAMETYPEMAP = _descriptor.Descriptor( + name='TestSameTypeMap', + full_name='protobuf_unittest.TestSameTypeMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map1', full_name='protobuf_unittest.TestSameTypeMap.map1', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map2', full_name='protobuf_unittest.TestSameTypeMap.map2', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTSAMETYPEMAP_MAP1ENTRY, _TESTSAMETYPEMAP_MAP2ENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3079, + serialized_end=3306, +) + + +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY = _descriptor.Descriptor( + name='MapFieldEntry', + full_name='protobuf_unittest.TestRequiredMessageMap.MapFieldEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestRequiredMessageMap.MapFieldEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestRequiredMessageMap.MapFieldEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3411, + serialized_end=3491, +) + +_TESTREQUIREDMESSAGEMAP = _descriptor.Descriptor( + name='TestRequiredMessageMap', + full_name='protobuf_unittest.TestRequiredMessageMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_field', full_name='protobuf_unittest.TestRequiredMessageMap.map_field', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3309, + serialized_end=3491, +) + + +_TESTARENAMAP_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_unittest.TestArenaMap.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1613, + serialized_end=1665, +) + +_TESTARENAMAP_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_unittest.TestArenaMap.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1667, + serialized_end=1719, +) + +_TESTARENAMAP_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_unittest.TestArenaMap.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1721, + serialized_end=1775, +) + +_TESTARENAMAP_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_unittest.TestArenaMap.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1777, + serialized_end=1831, +) + +_TESTARENAMAP_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_unittest.TestArenaMap.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1833, + serialized_end=1887, +) + +_TESTARENAMAP_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_unittest.TestArenaMap.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1889, + serialized_end=1943, +) + +_TESTARENAMAP_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1945, + serialized_end=2001, +) + +_TESTARENAMAP_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2003, + serialized_end=2059, +) + +_TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2061, + serialized_end=2119, +) + +_TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2121, + serialized_end=2179, +) + +_TESTARENAMAP_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2181, + serialized_end=2233, +) + +_TESTARENAMAP_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2235, + serialized_end=2288, +) + +_TESTARENAMAP_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_unittest.TestArenaMap.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2290, + serialized_end=2340, +) + +_TESTARENAMAP_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_unittest.TestArenaMap.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2342, + serialized_end=2396, +) + +_TESTARENAMAP_MAPINT32BYTESENTRY = _descriptor.Descriptor( + name='MapInt32BytesEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32BytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32BytesEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32BytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2398, + serialized_end=2450, +) + +_TESTARENAMAP_MAPINT32ENUMENTRY = _descriptor.Descriptor( + name='MapInt32EnumEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32EnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32EnumEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32EnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2452, + serialized_end=2531, +) + +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapInt32ForeignMessageEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2533, + serialized_end=2629, +) + +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY = _descriptor.Descriptor( + name='MapInt32ForeignMessageNoArenaEntry', + full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6024, + serialized_end=6136, +) + +_TESTARENAMAP = _descriptor.Descriptor( + name='TestArenaMap', + full_name='protobuf_unittest.TestArenaMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_unittest.TestArenaMap.map_int32_int32', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_unittest.TestArenaMap.map_int64_int64', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_unittest.TestArenaMap.map_uint32_uint32', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_unittest.TestArenaMap.map_uint64_uint64', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_unittest.TestArenaMap.map_sint32_sint32', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_unittest.TestArenaMap.map_sint64_sint64', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_unittest.TestArenaMap.map_fixed32_fixed32', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_unittest.TestArenaMap.map_fixed64_fixed64', index=7, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_unittest.TestArenaMap.map_sfixed32_sfixed32', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_unittest.TestArenaMap.map_sfixed64_sfixed64', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_unittest.TestArenaMap.map_int32_float', index=10, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_unittest.TestArenaMap.map_int32_double', index=11, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_unittest.TestArenaMap.map_bool_bool', index=12, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_unittest.TestArenaMap.map_string_string', index=13, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_bytes', full_name='protobuf_unittest.TestArenaMap.map_int32_bytes', index=14, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_enum', full_name='protobuf_unittest.TestArenaMap.map_int32_enum', index=15, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_foreign_message', full_name='protobuf_unittest.TestArenaMap.map_int32_foreign_message', index=16, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_foreign_message_no_arena', full_name='protobuf_unittest.TestArenaMap.map_int32_foreign_message_no_arena', index=17, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTARENAMAP_MAPINT32INT32ENTRY, _TESTARENAMAP_MAPINT64INT64ENTRY, _TESTARENAMAP_MAPUINT32UINT32ENTRY, _TESTARENAMAP_MAPUINT64UINT64ENTRY, _TESTARENAMAP_MAPSINT32SINT32ENTRY, _TESTARENAMAP_MAPSINT64SINT64ENTRY, _TESTARENAMAP_MAPFIXED32FIXED32ENTRY, _TESTARENAMAP_MAPFIXED64FIXED64ENTRY, _TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY, _TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY, _TESTARENAMAP_MAPINT32FLOATENTRY, _TESTARENAMAP_MAPINT32DOUBLEENTRY, _TESTARENAMAP_MAPBOOLBOOLENTRY, _TESTARENAMAP_MAPSTRINGSTRINGENTRY, _TESTARENAMAP_MAPINT32BYTESENTRY, _TESTARENAMAP_MAPINT32ENUMENTRY, _TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY, _TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3494, + serialized_end=6136, +) + + +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY = _descriptor.Descriptor( + name='TypeEntry', + full_name='protobuf_unittest.MessageContainingEnumCalledType.TypeEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.MessageContainingEnumCalledType.TypeEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.MessageContainingEnumCalledType.TypeEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6250, + serialized_end=6345, +) + +_MESSAGECONTAININGENUMCALLEDTYPE = _descriptor.Descriptor( + name='MessageContainingEnumCalledType', + full_name='protobuf_unittest.MessageContainingEnumCalledType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type', full_name='protobuf_unittest.MessageContainingEnumCalledType.type', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY, ], + enum_types=[ + _MESSAGECONTAININGENUMCALLEDTYPE_TYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6139, + serialized_end=6367, +) + + +_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY = _descriptor.Descriptor( + name='EntryEntry', + full_name='protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6483, + serialized_end=6527, +) + +_MESSAGECONTAININGMAPCALLEDENTRY = _descriptor.Descriptor( + name='MessageContainingMapCalledEntry', + full_name='protobuf_unittest.MessageContainingMapCalledEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='entry', full_name='protobuf_unittest.MessageContainingMapCalledEntry.entry', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6370, + serialized_end=6527, +) + + +_TESTRECURSIVEMAPMESSAGE_AENTRY = _descriptor.Descriptor( + name='AEntry', + full_name='protobuf_unittest.TestRecursiveMapMessage.AEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestRecursiveMapMessage.AEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestRecursiveMapMessage.AEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6619, + serialized_end=6703, +) + +_TESTRECURSIVEMAPMESSAGE = _descriptor.Descriptor( + name='TestRecursiveMapMessage', + full_name='protobuf_unittest.TestRecursiveMapMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestRecursiveMapMessage.a', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTRECURSIVEMAPMESSAGE_AENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6530, + serialized_end=6703, +) + +_TESTMAP_MAPINT32INT32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT64INT64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPUINT32UINT32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPUINT64UINT64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSINT32SINT32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSINT64SINT64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPFIXED32FIXED32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPFIXED64FIXED64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32FLOATENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32DOUBLEENTRY.containing_type = _TESTMAP +_TESTMAP_MAPBOOLBOOLENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSTRINGSTRINGENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32BYTESENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32ENUMENTRY.fields_by_name['value'].enum_type = _MAPENUM +_TESTMAP_MAPINT32ENUMENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._FOREIGNMESSAGE +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY.containing_type = _TESTMAP +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._FOREIGNMESSAGE +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY.containing_type = _TESTMAP +_TESTMAP_MAPINT32ALLTYPESENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLTYPES +_TESTMAP_MAPINT32ALLTYPESENTRY.containing_type = _TESTMAP +_TESTMAP.fields_by_name['map_int32_int32'].message_type = _TESTMAP_MAPINT32INT32ENTRY +_TESTMAP.fields_by_name['map_int64_int64'].message_type = _TESTMAP_MAPINT64INT64ENTRY +_TESTMAP.fields_by_name['map_uint32_uint32'].message_type = _TESTMAP_MAPUINT32UINT32ENTRY +_TESTMAP.fields_by_name['map_uint64_uint64'].message_type = _TESTMAP_MAPUINT64UINT64ENTRY +_TESTMAP.fields_by_name['map_sint32_sint32'].message_type = _TESTMAP_MAPSINT32SINT32ENTRY +_TESTMAP.fields_by_name['map_sint64_sint64'].message_type = _TESTMAP_MAPSINT64SINT64ENTRY +_TESTMAP.fields_by_name['map_fixed32_fixed32'].message_type = _TESTMAP_MAPFIXED32FIXED32ENTRY +_TESTMAP.fields_by_name['map_fixed64_fixed64'].message_type = _TESTMAP_MAPFIXED64FIXED64ENTRY +_TESTMAP.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTMAP_MAPSFIXED32SFIXED32ENTRY +_TESTMAP.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTMAP_MAPSFIXED64SFIXED64ENTRY +_TESTMAP.fields_by_name['map_int32_float'].message_type = _TESTMAP_MAPINT32FLOATENTRY +_TESTMAP.fields_by_name['map_int32_double'].message_type = _TESTMAP_MAPINT32DOUBLEENTRY +_TESTMAP.fields_by_name['map_bool_bool'].message_type = _TESTMAP_MAPBOOLBOOLENTRY +_TESTMAP.fields_by_name['map_string_string'].message_type = _TESTMAP_MAPSTRINGSTRINGENTRY +_TESTMAP.fields_by_name['map_int32_bytes'].message_type = _TESTMAP_MAPINT32BYTESENTRY +_TESTMAP.fields_by_name['map_int32_enum'].message_type = _TESTMAP_MAPINT32ENUMENTRY +_TESTMAP.fields_by_name['map_int32_foreign_message'].message_type = _TESTMAP_MAPINT32FOREIGNMESSAGEENTRY +_TESTMAP.fields_by_name['map_string_foreign_message'].message_type = _TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY +_TESTMAP.fields_by_name['map_int32_all_types'].message_type = _TESTMAP_MAPINT32ALLTYPESENTRY +_TESTMAPSUBMESSAGE.fields_by_name['test_map'].message_type = _TESTMAP +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLTYPES +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY.containing_type = _TESTMESSAGEMAP +_TESTMESSAGEMAP.fields_by_name['map_int32_message'].message_type = _TESTMESSAGEMAP_MAPINT32MESSAGEENTRY +_TESTSAMETYPEMAP_MAP1ENTRY.containing_type = _TESTSAMETYPEMAP +_TESTSAMETYPEMAP_MAP2ENTRY.containing_type = _TESTSAMETYPEMAP +_TESTSAMETYPEMAP.fields_by_name['map1'].message_type = _TESTSAMETYPEMAP_MAP1ENTRY +_TESTSAMETYPEMAP.fields_by_name['map2'].message_type = _TESTSAMETYPEMAP_MAP2ENTRY +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTREQUIRED +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY.containing_type = _TESTREQUIREDMESSAGEMAP +_TESTREQUIREDMESSAGEMAP.fields_by_name['map_field'].message_type = _TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY +_TESTARENAMAP_MAPINT32INT32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT64INT64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPUINT32UINT32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPUINT64UINT64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSINT32SINT32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSINT64SINT64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPFIXED32FIXED32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPFIXED64FIXED64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32FLOATENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32DOUBLEENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPBOOLBOOLENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPSTRINGSTRINGENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32BYTESENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32ENUMENTRY.fields_by_name['value'].enum_type = _MAPENUM +_TESTARENAMAP_MAPINT32ENUMENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__pb2._FOREIGNMESSAGE +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY.fields_by_name['value'].message_type = google_dot_protobuf_dot_unittest__no__arena__pb2._FOREIGNMESSAGE +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY.containing_type = _TESTARENAMAP +_TESTARENAMAP.fields_by_name['map_int32_int32'].message_type = _TESTARENAMAP_MAPINT32INT32ENTRY +_TESTARENAMAP.fields_by_name['map_int64_int64'].message_type = _TESTARENAMAP_MAPINT64INT64ENTRY +_TESTARENAMAP.fields_by_name['map_uint32_uint32'].message_type = _TESTARENAMAP_MAPUINT32UINT32ENTRY +_TESTARENAMAP.fields_by_name['map_uint64_uint64'].message_type = _TESTARENAMAP_MAPUINT64UINT64ENTRY +_TESTARENAMAP.fields_by_name['map_sint32_sint32'].message_type = _TESTARENAMAP_MAPSINT32SINT32ENTRY +_TESTARENAMAP.fields_by_name['map_sint64_sint64'].message_type = _TESTARENAMAP_MAPSINT64SINT64ENTRY +_TESTARENAMAP.fields_by_name['map_fixed32_fixed32'].message_type = _TESTARENAMAP_MAPFIXED32FIXED32ENTRY +_TESTARENAMAP.fields_by_name['map_fixed64_fixed64'].message_type = _TESTARENAMAP_MAPFIXED64FIXED64ENTRY +_TESTARENAMAP.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY +_TESTARENAMAP.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY +_TESTARENAMAP.fields_by_name['map_int32_float'].message_type = _TESTARENAMAP_MAPINT32FLOATENTRY +_TESTARENAMAP.fields_by_name['map_int32_double'].message_type = _TESTARENAMAP_MAPINT32DOUBLEENTRY +_TESTARENAMAP.fields_by_name['map_bool_bool'].message_type = _TESTARENAMAP_MAPBOOLBOOLENTRY +_TESTARENAMAP.fields_by_name['map_string_string'].message_type = _TESTARENAMAP_MAPSTRINGSTRINGENTRY +_TESTARENAMAP.fields_by_name['map_int32_bytes'].message_type = _TESTARENAMAP_MAPINT32BYTESENTRY +_TESTARENAMAP.fields_by_name['map_int32_enum'].message_type = _TESTARENAMAP_MAPINT32ENUMENTRY +_TESTARENAMAP.fields_by_name['map_int32_foreign_message'].message_type = _TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY +_TESTARENAMAP.fields_by_name['map_int32_foreign_message_no_arena'].message_type = _TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY.fields_by_name['value'].message_type = _MESSAGECONTAININGENUMCALLEDTYPE +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY.containing_type = _MESSAGECONTAININGENUMCALLEDTYPE +_MESSAGECONTAININGENUMCALLEDTYPE.fields_by_name['type'].message_type = _MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY +_MESSAGECONTAININGENUMCALLEDTYPE_TYPE.containing_type = _MESSAGECONTAININGENUMCALLEDTYPE +_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY.containing_type = _MESSAGECONTAININGMAPCALLEDENTRY +_MESSAGECONTAININGMAPCALLEDENTRY.fields_by_name['entry'].message_type = _MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY +_TESTRECURSIVEMAPMESSAGE_AENTRY.fields_by_name['value'].message_type = _TESTRECURSIVEMAPMESSAGE +_TESTRECURSIVEMAPMESSAGE_AENTRY.containing_type = _TESTRECURSIVEMAPMESSAGE +_TESTRECURSIVEMAPMESSAGE.fields_by_name['a'].message_type = _TESTRECURSIVEMAPMESSAGE_AENTRY +DESCRIPTOR.message_types_by_name['TestMap'] = _TESTMAP +DESCRIPTOR.message_types_by_name['TestMapSubmessage'] = _TESTMAPSUBMESSAGE +DESCRIPTOR.message_types_by_name['TestMessageMap'] = _TESTMESSAGEMAP +DESCRIPTOR.message_types_by_name['TestSameTypeMap'] = _TESTSAMETYPEMAP +DESCRIPTOR.message_types_by_name['TestRequiredMessageMap'] = _TESTREQUIREDMESSAGEMAP +DESCRIPTOR.message_types_by_name['TestArenaMap'] = _TESTARENAMAP +DESCRIPTOR.message_types_by_name['MessageContainingEnumCalledType'] = _MESSAGECONTAININGENUMCALLEDTYPE +DESCRIPTOR.message_types_by_name['MessageContainingMapCalledEntry'] = _MESSAGECONTAININGMAPCALLEDENTRY +DESCRIPTOR.message_types_by_name['TestRecursiveMapMessage'] = _TESTRECURSIVEMAPMESSAGE +DESCRIPTOR.enum_types_by_name['MapEnum'] = _MAPENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMap = _reflection.GeneratedProtocolMessageType('TestMap', (_message.Message,), dict( + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapStringStringEntry) + )) + , + + MapInt32BytesEntry = _reflection.GeneratedProtocolMessageType('MapInt32BytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32BYTESENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32BytesEntry) + )) + , + + MapInt32EnumEntry = _reflection.GeneratedProtocolMessageType('MapInt32EnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32ENUMENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32EnumEntry) + )) + , + + MapInt32ForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapInt32ForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32FOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32ForeignMessageEntry) + )) + , + + MapStringForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapStringForeignMessageEntry) + )) + , + + MapInt32AllTypesEntry = _reflection.GeneratedProtocolMessageType('MapInt32AllTypesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_MAPINT32ALLTYPESENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap.MapInt32AllTypesEntry) + )) + , + DESCRIPTOR = _TESTMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMap) + )) +_sym_db.RegisterMessage(TestMap) +_sym_db.RegisterMessage(TestMap.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestMap.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestMap.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestMap.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestMap.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestMap.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestMap.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestMap.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestMap.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestMap.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestMap.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestMap.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestMap.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestMap.MapStringStringEntry) +_sym_db.RegisterMessage(TestMap.MapInt32BytesEntry) +_sym_db.RegisterMessage(TestMap.MapInt32EnumEntry) +_sym_db.RegisterMessage(TestMap.MapInt32ForeignMessageEntry) +_sym_db.RegisterMessage(TestMap.MapStringForeignMessageEntry) +_sym_db.RegisterMessage(TestMap.MapInt32AllTypesEntry) + +TestMapSubmessage = _reflection.GeneratedProtocolMessageType('TestMapSubmessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMAPSUBMESSAGE, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMapSubmessage) + )) +_sym_db.RegisterMessage(TestMapSubmessage) + +TestMessageMap = _reflection.GeneratedProtocolMessageType('TestMessageMap', (_message.Message,), dict( + + MapInt32MessageEntry = _reflection.GeneratedProtocolMessageType('MapInt32MessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGEMAP_MAPINT32MESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageMap.MapInt32MessageEntry) + )) + , + DESCRIPTOR = _TESTMESSAGEMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageMap) + )) +_sym_db.RegisterMessage(TestMessageMap) +_sym_db.RegisterMessage(TestMessageMap.MapInt32MessageEntry) + +TestSameTypeMap = _reflection.GeneratedProtocolMessageType('TestSameTypeMap', (_message.Message,), dict( + + Map1Entry = _reflection.GeneratedProtocolMessageType('Map1Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTSAMETYPEMAP_MAP1ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSameTypeMap.Map1Entry) + )) + , + + Map2Entry = _reflection.GeneratedProtocolMessageType('Map2Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTSAMETYPEMAP_MAP2ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSameTypeMap.Map2Entry) + )) + , + DESCRIPTOR = _TESTSAMETYPEMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestSameTypeMap) + )) +_sym_db.RegisterMessage(TestSameTypeMap) +_sym_db.RegisterMessage(TestSameTypeMap.Map1Entry) +_sym_db.RegisterMessage(TestSameTypeMap.Map2Entry) + +TestRequiredMessageMap = _reflection.GeneratedProtocolMessageType('TestRequiredMessageMap', (_message.Message,), dict( + + MapFieldEntry = _reflection.GeneratedProtocolMessageType('MapFieldEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredMessageMap.MapFieldEntry) + )) + , + DESCRIPTOR = _TESTREQUIREDMESSAGEMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredMessageMap) + )) +_sym_db.RegisterMessage(TestRequiredMessageMap) +_sym_db.RegisterMessage(TestRequiredMessageMap.MapFieldEntry) + +TestArenaMap = _reflection.GeneratedProtocolMessageType('TestArenaMap', (_message.Message,), dict( + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapStringStringEntry) + )) + , + + MapInt32BytesEntry = _reflection.GeneratedProtocolMessageType('MapInt32BytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32BYTESENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32BytesEntry) + )) + , + + MapInt32EnumEntry = _reflection.GeneratedProtocolMessageType('MapInt32EnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32ENUMENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32EnumEntry) + )) + , + + MapInt32ForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapInt32ForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32ForeignMessageEntry) + )) + , + + MapInt32ForeignMessageNoArenaEntry = _reflection.GeneratedProtocolMessageType('MapInt32ForeignMessageNoArenaEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap.MapInt32ForeignMessageNoArenaEntry) + )) + , + DESCRIPTOR = _TESTARENAMAP, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestArenaMap) + )) +_sym_db.RegisterMessage(TestArenaMap) +_sym_db.RegisterMessage(TestArenaMap.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestArenaMap.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestArenaMap.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestArenaMap.MapStringStringEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32BytesEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32EnumEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32ForeignMessageEntry) +_sym_db.RegisterMessage(TestArenaMap.MapInt32ForeignMessageNoArenaEntry) + +MessageContainingEnumCalledType = _reflection.GeneratedProtocolMessageType('MessageContainingEnumCalledType', (_message.Message,), dict( + + TypeEntry = _reflection.GeneratedProtocolMessageType('TypeEntry', (_message.Message,), dict( + DESCRIPTOR = _MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingEnumCalledType.TypeEntry) + )) + , + DESCRIPTOR = _MESSAGECONTAININGENUMCALLEDTYPE, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingEnumCalledType) + )) +_sym_db.RegisterMessage(MessageContainingEnumCalledType) +_sym_db.RegisterMessage(MessageContainingEnumCalledType.TypeEntry) + +MessageContainingMapCalledEntry = _reflection.GeneratedProtocolMessageType('MessageContainingMapCalledEntry', (_message.Message,), dict( + + EntryEntry = _reflection.GeneratedProtocolMessageType('EntryEntry', (_message.Message,), dict( + DESCRIPTOR = _MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingMapCalledEntry.EntryEntry) + )) + , + DESCRIPTOR = _MESSAGECONTAININGMAPCALLEDENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MessageContainingMapCalledEntry) + )) +_sym_db.RegisterMessage(MessageContainingMapCalledEntry) +_sym_db.RegisterMessage(MessageContainingMapCalledEntry.EntryEntry) + +TestRecursiveMapMessage = _reflection.GeneratedProtocolMessageType('TestRecursiveMapMessage', (_message.Message,), dict( + + AEntry = _reflection.GeneratedProtocolMessageType('AEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTRECURSIVEMAPMESSAGE_AENTRY, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursiveMapMessage.AEntry) + )) + , + DESCRIPTOR = _TESTRECURSIVEMAPMESSAGE, + __module__ = 'google.protobuf.map_unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursiveMapMessage) + )) +_sym_db.RegisterMessage(TestRecursiveMapMessage) +_sym_db.RegisterMessage(TestRecursiveMapMessage.AEntry) + + +DESCRIPTOR._options = None +_TESTMAP_MAPINT32INT32ENTRY._options = None +_TESTMAP_MAPINT64INT64ENTRY._options = None +_TESTMAP_MAPUINT32UINT32ENTRY._options = None +_TESTMAP_MAPUINT64UINT64ENTRY._options = None +_TESTMAP_MAPSINT32SINT32ENTRY._options = None +_TESTMAP_MAPSINT64SINT64ENTRY._options = None +_TESTMAP_MAPFIXED32FIXED32ENTRY._options = None +_TESTMAP_MAPFIXED64FIXED64ENTRY._options = None +_TESTMAP_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTMAP_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTMAP_MAPINT32FLOATENTRY._options = None +_TESTMAP_MAPINT32DOUBLEENTRY._options = None +_TESTMAP_MAPBOOLBOOLENTRY._options = None +_TESTMAP_MAPSTRINGSTRINGENTRY._options = None +_TESTMAP_MAPINT32BYTESENTRY._options = None +_TESTMAP_MAPINT32ENUMENTRY._options = None +_TESTMAP_MAPINT32FOREIGNMESSAGEENTRY._options = None +_TESTMAP_MAPSTRINGFOREIGNMESSAGEENTRY._options = None +_TESTMAP_MAPINT32ALLTYPESENTRY._options = None +_TESTMESSAGEMAP_MAPINT32MESSAGEENTRY._options = None +_TESTSAMETYPEMAP_MAP1ENTRY._options = None +_TESTSAMETYPEMAP_MAP2ENTRY._options = None +_TESTREQUIREDMESSAGEMAP_MAPFIELDENTRY._options = None +_TESTARENAMAP_MAPINT32INT32ENTRY._options = None +_TESTARENAMAP_MAPINT64INT64ENTRY._options = None +_TESTARENAMAP_MAPUINT32UINT32ENTRY._options = None +_TESTARENAMAP_MAPUINT64UINT64ENTRY._options = None +_TESTARENAMAP_MAPSINT32SINT32ENTRY._options = None +_TESTARENAMAP_MAPSINT64SINT64ENTRY._options = None +_TESTARENAMAP_MAPFIXED32FIXED32ENTRY._options = None +_TESTARENAMAP_MAPFIXED64FIXED64ENTRY._options = None +_TESTARENAMAP_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTARENAMAP_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTARENAMAP_MAPINT32FLOATENTRY._options = None +_TESTARENAMAP_MAPINT32DOUBLEENTRY._options = None +_TESTARENAMAP_MAPBOOLBOOLENTRY._options = None +_TESTARENAMAP_MAPSTRINGSTRINGENTRY._options = None +_TESTARENAMAP_MAPINT32BYTESENTRY._options = None +_TESTARENAMAP_MAPINT32ENUMENTRY._options = None +_TESTARENAMAP_MAPINT32FOREIGNMESSAGEENTRY._options = None +_TESTARENAMAP_MAPINT32FOREIGNMESSAGENOARENAENTRY._options = None +_MESSAGECONTAININGENUMCALLEDTYPE_TYPEENTRY._options = None +_MESSAGECONTAININGMAPCALLEDENTRY_ENTRYENTRY._options = None +_TESTRECURSIVEMAPMESSAGE_AENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/message.py b/winvenv/Lib/site-packages/google/protobuf/message.py new file mode 100644 index 0000000..eeb0d57 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/message.py @@ -0,0 +1,308 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# TODO(robinson): We should just make these methods all "pure-virtual" and move +# all implementation out, into reflection.py for now. + + +"""Contains an abstract base class for protocol messages.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +class Error(Exception): pass +class DecodeError(Error): pass +class EncodeError(Error): pass + + +class Message(object): + + """Abstract base class for protocol messages. + + Protocol message classes are almost always generated by the protocol + compiler. These generated types subclass Message and implement the methods + shown below. + + TODO(robinson): Link to an HTML document here. + + TODO(robinson): Document that instances of this class will also + have an Extensions attribute with __getitem__ and __setitem__. + Again, not sure how to best convey this. + + TODO(robinson): Document that the class must also have a static + RegisterExtension(extension_field) method. + Not sure how to best express at this point. + """ + + # TODO(robinson): Document these fields and methods. + + __slots__ = [] + + DESCRIPTOR = None + + def __deepcopy__(self, memo=None): + clone = type(self)() + clone.MergeFrom(self) + return clone + + def __eq__(self, other_msg): + """Recursively compares two messages by value and structure.""" + raise NotImplementedError + + def __ne__(self, other_msg): + # Can't just say self != other_msg, since that would infinitely recurse. :) + return not self == other_msg + + def __hash__(self): + raise TypeError('unhashable object') + + def __str__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def __unicode__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def MergeFrom(self, other_msg): + """Merges the contents of the specified message into current message. + + This method merges the contents of the specified message into the current + message. Singular fields that are set in the specified message overwrite + the corresponding fields in the current message. Repeated fields are + appended. Singular sub-messages and groups are recursively merged. + + Args: + other_msg: Message to merge into the current message. + """ + raise NotImplementedError + + def CopyFrom(self, other_msg): + """Copies the content of the specified message into the current message. + + The method clears the current message and then merges the specified + message using MergeFrom. + + Args: + other_msg: Message to copy into the current one. + """ + if self is other_msg: + return + self.Clear() + self.MergeFrom(other_msg) + + def Clear(self): + """Clears all data that was set in the message.""" + raise NotImplementedError + + def SetInParent(self): + """Mark this as present in the parent. + + This normally happens automatically when you assign a field of a + sub-message, but sometimes you want to make the sub-message + present while keeping it empty. If you find yourself using this, + you may want to reconsider your design.""" + raise NotImplementedError + + def IsInitialized(self): + """Checks if the message is initialized. + + Returns: + The method returns True if the message is initialized (i.e. all of its + required fields are set). + """ + raise NotImplementedError + + # TODO(robinson): MergeFromString() should probably return None and be + # implemented in terms of a helper that returns the # of bytes read. Our + # deserialization routines would use the helper when recursively + # deserializing, but the end user would almost always just want the no-return + # MergeFromString(). + + def MergeFromString(self, serialized): + """Merges serialized protocol buffer data into this message. + + When we find a field in |serialized| that is already present + in this message: + - If it's a "repeated" field, we append to the end of our list. + - Else, if it's a scalar, we overwrite our field. + - Else, (it's a nonrepeated composite), we recursively merge + into the existing composite. + + TODO(robinson): Document handling of unknown fields. + + Args: + serialized: Any object that allows us to call buffer(serialized) + to access a string of bytes using the buffer interface. + + TODO(robinson): When we switch to a helper, this will return None. + + Returns: + The number of bytes read from |serialized|. + For non-group messages, this will always be len(serialized), + but for messages which are actually groups, this will + generally be less than len(serialized), since we must + stop when we reach an END_GROUP tag. Note that if + we *do* stop because of an END_GROUP tag, the number + of bytes returned does not include the bytes + for the END_GROUP tag information. + """ + raise NotImplementedError + + def ParseFromString(self, serialized): + """Parse serialized protocol buffer data into this message. + + Like MergeFromString(), except we clear the object first and + do not return the value that MergeFromString returns. + """ + self.Clear() + self.MergeFromString(serialized) + + def SerializeToString(self, **kwargs): + """Serializes the protocol message to a binary string. + + Arguments: + **kwargs: Keyword arguments to the serialize method, accepts + the following keyword args: + deterministic: If true, requests deterministic serialization of the + protobuf, with predictable ordering of map keys. + + Returns: + A binary string representation of the message if all of the required + fields in the message are set (i.e. the message is initialized). + + Raises: + message.EncodeError if the message isn't initialized. + """ + raise NotImplementedError + + def SerializePartialToString(self, **kwargs): + """Serializes the protocol message to a binary string. + + This method is similar to SerializeToString but doesn't check if the + message is initialized. + + Arguments: + **kwargs: Keyword arguments to the serialize method, accepts + the following keyword args: + deterministic: If true, requests deterministic serialization of the + protobuf, with predictable ordering of map keys. + + Returns: + A string representation of the partial message. + """ + raise NotImplementedError + + # TODO(robinson): Decide whether we like these better + # than auto-generated has_foo() and clear_foo() methods + # on the instances themselves. This way is less consistent + # with C++, but it makes reflection-type access easier and + # reduces the number of magically autogenerated things. + # + # TODO(robinson): Be sure to document (and test) exactly + # which field names are accepted here. Are we case-sensitive? + # What do we do with fields that share names with Python keywords + # like 'lambda' and 'yield'? + # + # nnorwitz says: + # """ + # Typically (in python), an underscore is appended to names that are + # keywords. So they would become lambda_ or yield_. + # """ + def ListFields(self): + """Returns a list of (FieldDescriptor, value) tuples for all + fields in the message which are not empty. A message field is + non-empty if HasField() would return true. A singular primitive field + is non-empty if HasField() would return true in proto2 or it is non zero + in proto3. A repeated field is non-empty if it contains at least one + element. The fields are ordered by field number""" + raise NotImplementedError + + def HasField(self, field_name): + """Checks if a certain field is set for the message, or if any field inside + a oneof group is set. Note that if the field_name is not defined in the + message descriptor, ValueError will be raised.""" + raise NotImplementedError + + def ClearField(self, field_name): + """Clears the contents of a given field, or the field set inside a oneof + group. If the name neither refers to a defined field or oneof group, + ValueError is raised.""" + raise NotImplementedError + + def WhichOneof(self, oneof_group): + """Returns the name of the field that is set inside a oneof group, or + None if no field is set. If no group with the given name exists, ValueError + will be raised.""" + raise NotImplementedError + + def HasExtension(self, extension_handle): + raise NotImplementedError + + def ClearExtension(self, extension_handle): + raise NotImplementedError + + def DiscardUnknownFields(self): + raise NotImplementedError + + def ByteSize(self): + """Returns the serialized size of this message. + Recursively calls ByteSize() on all contained messages. + """ + raise NotImplementedError + + def _SetListener(self, message_listener): + """Internal method used by the protocol message implementation. + Clients should not call this directly. + + Sets a listener that this message will call on certain state transitions. + + The purpose of this method is to register back-edges from children to + parents at runtime, for the purpose of setting "has" bits and + byte-size-dirty bits in the parent and ancestor objects whenever a child or + descendant object is modified. + + If the client wants to disconnect this Message from the object tree, she + explicitly sets callback to None. + + If message_listener is None, unregisters any existing listener. Otherwise, + message_listener must implement the MessageListener interface in + internal/message_listener.py, and we discard any listener registered + via a previous _SetListener() call. + """ + raise NotImplementedError + + def __getstate__(self): + """Support the pickle protocol.""" + return dict(serialized=self.SerializePartialToString()) + + def __setstate__(self, state): + """Support the pickle protocol.""" + self.__init__() + self.ParseFromString(state['serialized']) diff --git a/winvenv/Lib/site-packages/google/protobuf/message_factory.py b/winvenv/Lib/site-packages/google/protobuf/message_factory.py new file mode 100644 index 0000000..e4fb065 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/message_factory.py @@ -0,0 +1,151 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Provides a factory class for generating dynamic messages. + +The easiest way to use this class is if you have access to the FileDescriptor +protos containing the messages you want to create you can just do the following: + +message_classes = message_factory.GetMessages(iterable_of_file_descriptors) +my_proto_instance = message_classes['some.proto.package.MessageName']() +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +from google.protobuf import descriptor_pool +from google.protobuf import message +from google.protobuf import reflection + + +class MessageFactory(object): + """Factory for creating Proto2 messages from descriptors in a pool.""" + + def __init__(self, pool=None): + """Initializes a new factory.""" + self.pool = pool or descriptor_pool.DescriptorPool() + + # local cache of all classes built from protobuf descriptors + self._classes = {} + + def GetPrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Passing a descriptor with a fully qualified name matching a previous + invocation will cause the same class to be returned. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + if descriptor not in self._classes: + descriptor_name = descriptor.name + if str is bytes: # PY2 + descriptor_name = descriptor.name.encode('ascii', 'ignore') + result_class = reflection.GeneratedProtocolMessageType( + descriptor_name, + (message.Message,), + {'DESCRIPTOR': descriptor, '__module__': None}) + # If module not set, it wrongly points to the reflection.py module. + self._classes[descriptor] = result_class + for field in descriptor.fields: + if field.message_type: + self.GetPrototype(field.message_type) + for extension in result_class.DESCRIPTOR.extensions: + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return self._classes[descriptor] + + def GetMessages(self, files): + """Gets all the messages from a specified file. + + This will find and resolve dependencies, failing if the descriptor + pool cannot satisfy them. + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + result = {} + for file_name in files: + file_desc = self.pool.FindFileByName(file_name) + for desc in file_desc.message_types_by_name.values(): + result[desc.full_name] = self.GetPrototype(desc) + + # While the extension FieldDescriptors are created by the descriptor pool, + # the python classes created in the factory need them to be registered + # explicitly, which is done below. + # + # The call to RegisterExtension will specifically check if the + # extension was already registered on the object and either + # ignore the registration if the original was the same, or raise + # an error if they were different. + + for extension in file_desc.extensions_by_name.values(): + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return result + + +_FACTORY = MessageFactory() + + +def GetMessages(file_protos): + """Builds a dictionary of all the messages available in a set of files. + + Args: + file_protos: Iterable of FileDescriptorProto to build messages out of. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + # The cpp implementation of the protocol buffer library requires to add the + # message in topological order of the dependency graph. + file_by_name = {file_proto.name: file_proto for file_proto in file_protos} + def _AddFile(file_proto): + for dependency in file_proto.dependency: + if dependency in file_by_name: + # Remove from elements to be visited, in order to cut cycles. + _AddFile(file_by_name.pop(dependency)) + _FACTORY.pool.Add(file_proto) + while file_by_name: + _AddFile(file_by_name.popitem()[1]) + return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos]) diff --git a/winvenv/Lib/site-packages/google/protobuf/proto_builder.py b/winvenv/Lib/site-packages/google/protobuf/proto_builder.py new file mode 100644 index 0000000..736caed --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/proto_builder.py @@ -0,0 +1,130 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Dynamic Protobuf class creator.""" + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict #PY26 +import hashlib +import os + +from google.protobuf import descriptor_pb2 +from google.protobuf import message_factory + + +def _GetMessageFromFactory(factory, full_name): + """Get a proto class from the MessageFactory by name. + + Args: + factory: a MessageFactory instance. + full_name: str, the fully qualified name of the proto type. + Returns: + A class, for the type identified by full_name. + Raises: + KeyError, if the proto is not found in the factory's descriptor pool. + """ + proto_descriptor = factory.pool.FindMessageTypeByName(full_name) + proto_cls = factory.GetPrototype(proto_descriptor) + return proto_cls + + +def MakeSimpleProtoClass(fields, full_name=None, pool=None): + """Create a Protobuf class whose fields are basic types. + + Note: this doesn't validate field names! + + Args: + fields: dict of {name: field_type} mappings for each field in the proto. If + this is an OrderedDict the order will be maintained, otherwise the + fields will be sorted by name. + full_name: optional str, the fully-qualified name of the proto type. + pool: optional DescriptorPool instance. + Returns: + a class, the new protobuf class with a FileDescriptor. + """ + factory = message_factory.MessageFactory(pool=pool) + + if full_name is not None: + try: + proto_cls = _GetMessageFromFactory(factory, full_name) + return proto_cls + except KeyError: + # The factory's DescriptorPool doesn't know about this class yet. + pass + + # Get a list of (name, field_type) tuples from the fields dict. If fields was + # an OrderedDict we keep the order, but otherwise we sort the field to ensure + # consistent ordering. + field_items = fields.items() + if not isinstance(fields, OrderedDict): + field_items = sorted(field_items) + + # Use a consistent file name that is unlikely to conflict with any imported + # proto files. + fields_hash = hashlib.sha1() + for f_name, f_type in field_items: + fields_hash.update(f_name.encode('utf-8')) + fields_hash.update(str(f_type).encode('utf-8')) + proto_file_name = fields_hash.hexdigest() + '.proto' + + # If the proto is anonymous, use the same hash to name it. + if full_name is None: + full_name = ('net.proto2.python.public.proto_builder.AnonymousProto_' + + fields_hash.hexdigest()) + try: + proto_cls = _GetMessageFromFactory(factory, full_name) + return proto_cls + except KeyError: + # The factory's DescriptorPool doesn't know about this class yet. + pass + + # This is the first time we see this proto: add a new descriptor to the pool. + factory.pool.Add( + _MakeFileDescriptorProto(proto_file_name, full_name, field_items)) + return _GetMessageFromFactory(factory, full_name) + + +def _MakeFileDescriptorProto(proto_file_name, full_name, field_items): + """Populate FileDescriptorProto for MessageFactory's DescriptorPool.""" + package, name = full_name.rsplit('.', 1) + file_proto = descriptor_pb2.FileDescriptorProto() + file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name) + file_proto.package = package + desc_proto = file_proto.message_type.add() + desc_proto.name = name + for f_number, (f_name, f_type) in enumerate(field_items, 1): + field_proto = desc_proto.field.add() + field_proto.name = f_name + field_proto.number = f_number + field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + field_proto.type = f_type + return file_proto diff --git a/winvenv/Lib/site-packages/google/protobuf/pyext/__init__.py b/winvenv/Lib/site-packages/google/protobuf/pyext/__init__.py new file mode 100644 index 0000000..5585614 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/pyext/__init__.py @@ -0,0 +1,4 @@ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) diff --git a/winvenv/Lib/site-packages/google/protobuf/pyext/cpp_message.py b/winvenv/Lib/site-packages/google/protobuf/pyext/cpp_message.py new file mode 100644 index 0000000..fc8eb32 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/pyext/cpp_message.py @@ -0,0 +1,65 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Protocol message implementation hooks for C++ implementation. + +Contains helper functions used to create protocol message classes from +Descriptor objects at runtime backed by the protocol buffer C++ API. +""" + +__author__ = 'tibell@google.com (Johan Tibell)' + +from google.protobuf.pyext import _message + + +class GeneratedProtocolMessageType(_message.MessageMeta): + + """Metaclass for protocol message classes created at runtime from Descriptors. + + The protocol compiler currently uses this metaclass to create protocol + message classes at runtime. Clients can also manually create their own + classes at runtime, as in this example: + + mydescriptor = Descriptor(.....) + factory = symbol_database.Default() + factory.pool.AddDescriptor(mydescriptor) + MyProtoClass = factory.GetPrototype(mydescriptor) + myproto_instance = MyProtoClass() + myproto.foo_field = 23 + ... + + The above example will not work for nested types. If you wish to include them, + use reflection.MakeClass() instead of manually instantiating the class in + order to create the appropriate class structure. + """ + + # Must be consistent with the protocol-compiler code in + # proto2/compiler/internal/generator.*. + _DESCRIPTOR_KEY = 'DESCRIPTOR' diff --git a/winvenv/Lib/site-packages/google/protobuf/pyext/python_pb2.py b/winvenv/Lib/site-packages/google/protobuf/pyext/python_pb2.py new file mode 100644 index 0000000..1e75eee --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/pyext/python_pb2.py @@ -0,0 +1,233 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/pyext/python.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/pyext/python.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=_b('H\001'), + serialized_pb=_b('\n\"google/protobuf/pyext/python.proto\x12\x1fgoogle.protobuf.python.internal\"\xbc\x02\n\x0cTestAllTypes\x12\\\n\x17repeated_nested_message\x18\x01 \x03(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessage\x12\\\n\x17optional_nested_message\x18\x02 \x01(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessage\x12\x16\n\x0eoptional_int32\x18\x03 \x01(\x05\x1aX\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\x12;\n\x02\x63\x63\x18\x02 \x01(\x0b\x32/.google.protobuf.python.internal.ForeignMessage\"&\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\x12\t\n\x01\x64\x18\x02 \x03(\x05\"\x1d\n\x11TestAllExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02:\x9a\x01\n!optional_nested_message_extension\x12\x32.google.protobuf.python.internal.TestAllExtensions\x18\x01 \x01(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessage:\x9a\x01\n!repeated_nested_message_extension\x12\x32.google.protobuf.python.internal.TestAllExtensions\x18\x02 \x03(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessageB\x02H\x01') +) + + +OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 1 +optional_nested_message_extension = _descriptor.FieldDescriptor( + name='optional_nested_message_extension', full_name='google.protobuf.python.internal.optional_nested_message_extension', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 2 +repeated_nested_message_extension = _descriptor.FieldDescriptor( + name='repeated_nested_message_extension', full_name='google.protobuf.python.internal.repeated_nested_message_extension', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='google.protobuf.python.internal.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cc', full_name='google.protobuf.python.internal.TestAllTypes.NestedMessage.cc', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=300, + serialized_end=388, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='google.protobuf.python.internal.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='google.protobuf.python.internal.TestAllTypes.repeated_nested_message', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='google.protobuf.python.internal.TestAllTypes.optional_nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32', full_name='google.protobuf.python.internal.TestAllTypes.optional_int32', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=72, + serialized_end=388, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='google.protobuf.python.internal.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='google.protobuf.python.internal.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='d', full_name='google.protobuf.python.internal.ForeignMessage.d', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=390, + serialized_end=428, +) + + +_TESTALLEXTENSIONS = _descriptor.Descriptor( + name='TestAllExtensions', + full_name='google.protobuf.python.internal.TestAllExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=430, + serialized_end=459, +) + +_TESTALLTYPES_NESTEDMESSAGE.fields_by_name['cc'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestAllExtensions'] = _TESTALLEXTENSIONS +DESCRIPTOR.extensions_by_name['optional_nested_message_extension'] = optional_nested_message_extension +DESCRIPTOR.extensions_by_name['repeated_nested_message_extension'] = repeated_nested_message_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestAllTypes.NestedMessage) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestAllExtensions = _reflection.GeneratedProtocolMessageType('TestAllExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTALLEXTENSIONS, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestAllExtensions) + )) +_sym_db.RegisterMessage(TestAllExtensions) + +optional_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(optional_nested_message_extension) +repeated_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(repeated_nested_message_extension) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/reflection.py b/winvenv/Lib/site-packages/google/protobuf/reflection.py new file mode 100644 index 0000000..f4ce8ca --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/reflection.py @@ -0,0 +1,121 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# This code is meant to work on Python 2.4 and above only. + +"""Contains a metaclass and helper functions used to create +protocol message classes from Descriptor objects at runtime. + +Recall that a metaclass is the "type" of a class. +(A class is to a metaclass what an instance is to a class.) + +In this case, we use the GeneratedProtocolMessageType metaclass +to inject all the useful functionality into the classes +output by the protocol compiler at compile-time. + +The upshot of all this is that the real implementation +details for ALL pure-Python protocol buffers are *here in +this file*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + + +from google.protobuf.internal import api_implementation +from google.protobuf import message + + +if api_implementation.Type() == 'cpp': + from google.protobuf.pyext import cpp_message as message_impl +else: + from google.protobuf.internal import python_message as message_impl + +# The type of all Message classes. +# Part of the public interface, but normally only used by message factories. +GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType + +MESSAGE_CLASS_CACHE = {} + + +def ParseMessage(descriptor, byte_str): + """Generate a new Message instance from this Descriptor and a byte string. + + Args: + descriptor: Protobuf Descriptor object + byte_str: Serialized protocol buffer byte string + + Returns: + Newly created protobuf Message object. + """ + result_class = MakeClass(descriptor) + new_msg = result_class() + new_msg.ParseFromString(byte_str) + return new_msg + + +def MakeClass(descriptor): + """Construct a class object for a protobuf described by descriptor. + + Composite descriptors are handled by defining the new class as a member of the + parent class, recursing as deep as necessary. + This is the dynamic equivalent to: + + class Parent(message.Message): + __metaclass__ = GeneratedProtocolMessageType + DESCRIPTOR = descriptor + class Child(message.Message): + __metaclass__ = GeneratedProtocolMessageType + DESCRIPTOR = descriptor.nested_types[0] + + Sample usage: + file_descriptor = descriptor_pb2.FileDescriptorProto() + file_descriptor.ParseFromString(proto2_string) + msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0]) + msg_class = reflection.MakeClass(msg_descriptor) + msg = msg_class() + + Args: + descriptor: A descriptor.Descriptor object describing the protobuf. + Returns: + The Message class object described by the descriptor. + """ + if descriptor in MESSAGE_CLASS_CACHE: + return MESSAGE_CLASS_CACHE[descriptor] + + attributes = {} + for name, nested_type in descriptor.nested_types_by_name.items(): + attributes[name] = MakeClass(nested_type) + + attributes[GeneratedProtocolMessageType._DESCRIPTOR_KEY] = descriptor + + result = GeneratedProtocolMessageType( + str(descriptor.name), (message.Message,), attributes) + MESSAGE_CLASS_CACHE[descriptor] = result + return result diff --git a/winvenv/Lib/site-packages/google/protobuf/service.py b/winvenv/Lib/site-packages/google/protobuf/service.py new file mode 100644 index 0000000..9e00de7 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/service.py @@ -0,0 +1,226 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""DEPRECATED: Declares the RPC service interfaces. + +This module declares the abstract interfaces underlying proto2 RPC +services. These are intended to be independent of any particular RPC +implementation, so that proto2 services can be used on top of a variety +of implementations. Starting with version 2.3.0, RPC implementations should +not try to build on these, but should instead provide code generator plugins +which generate code specific to the particular RPC implementation. This way +the generated code can be more appropriate for the implementation in use +and can avoid unnecessary layers of indirection. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + + +class RpcException(Exception): + """Exception raised on failed blocking RPC method call.""" + pass + + +class Service(object): + + """Abstract base interface for protocol-buffer-based RPC services. + + Services themselves are abstract classes (implemented either by servers or as + stubs), but they subclass this base interface. The methods of this + interface can be used to call the methods of the service without knowing + its exact type at compile time (analogous to the Message interface). + """ + + def GetDescriptor(): + """Retrieves this service's descriptor.""" + raise NotImplementedError + + def CallMethod(self, method_descriptor, rpc_controller, + request, done): + """Calls a method of the service specified by method_descriptor. + + If "done" is None then the call is blocking and the response + message will be returned directly. Otherwise the call is asynchronous + and "done" will later be called with the response value. + + In the blocking case, RpcException will be raised on error. + + Preconditions: + * method_descriptor.service == GetDescriptor + * request is of the exact same classes as returned by + GetRequestClass(method). + * After the call has started, the request must not be modified. + * "rpc_controller" is of the correct type for the RPC implementation being + used by this Service. For stubs, the "correct type" depends on the + RpcChannel which the stub is using. + + Postconditions: + * "done" will be called when the method is complete. This may be + before CallMethod() returns or it may be at some point in the future. + * If the RPC failed, the response value passed to "done" will be None. + Further details about the failure can be found by querying the + RpcController. + """ + raise NotImplementedError + + def GetRequestClass(self, method_descriptor): + """Returns the class of the request message for the specified method. + + CallMethod() requires that the request is of a particular subclass of + Message. GetRequestClass() gets the default instance of this required + type. + + Example: + method = service.GetDescriptor().FindMethodByName("Foo") + request = stub.GetRequestClass(method)() + request.ParseFromString(input) + service.CallMethod(method, request, callback) + """ + raise NotImplementedError + + def GetResponseClass(self, method_descriptor): + """Returns the class of the response message for the specified method. + + This method isn't really needed, as the RpcChannel's CallMethod constructs + the response protocol message. It's provided anyway in case it is useful + for the caller to know the response type in advance. + """ + raise NotImplementedError + + +class RpcController(object): + + """An RpcController mediates a single method call. + + The primary purpose of the controller is to provide a way to manipulate + settings specific to the RPC implementation and to find out about RPC-level + errors. The methods provided by the RpcController interface are intended + to be a "least common denominator" set of features which we expect all + implementations to support. Specific implementations may provide more + advanced features (e.g. deadline propagation). + """ + + # Client-side methods below + + def Reset(self): + """Resets the RpcController to its initial state. + + After the RpcController has been reset, it may be reused in + a new call. Must not be called while an RPC is in progress. + """ + raise NotImplementedError + + def Failed(self): + """Returns true if the call failed. + + After a call has finished, returns true if the call failed. The possible + reasons for failure depend on the RPC implementation. Failed() must not + be called before a call has finished. If Failed() returns true, the + contents of the response message are undefined. + """ + raise NotImplementedError + + def ErrorText(self): + """If Failed is true, returns a human-readable description of the error.""" + raise NotImplementedError + + def StartCancel(self): + """Initiate cancellation. + + Advises the RPC system that the caller desires that the RPC call be + canceled. The RPC system may cancel it immediately, may wait awhile and + then cancel it, or may not even cancel the call at all. If the call is + canceled, the "done" callback will still be called and the RpcController + will indicate that the call failed at that time. + """ + raise NotImplementedError + + # Server-side methods below + + def SetFailed(self, reason): + """Sets a failure reason. + + Causes Failed() to return true on the client side. "reason" will be + incorporated into the message returned by ErrorText(). If you find + you need to return machine-readable information about failures, you + should incorporate it into your response protocol buffer and should + NOT call SetFailed(). + """ + raise NotImplementedError + + def IsCanceled(self): + """Checks if the client cancelled the RPC. + + If true, indicates that the client canceled the RPC, so the server may + as well give up on replying to it. The server should still call the + final "done" callback. + """ + raise NotImplementedError + + def NotifyOnCancel(self, callback): + """Sets a callback to invoke on cancel. + + Asks that the given callback be called when the RPC is canceled. The + callback will always be called exactly once. If the RPC completes without + being canceled, the callback will be called after completion. If the RPC + has already been canceled when NotifyOnCancel() is called, the callback + will be called immediately. + + NotifyOnCancel() must be called no more than once per request. + """ + raise NotImplementedError + + +class RpcChannel(object): + + """Abstract interface for an RPC channel. + + An RpcChannel represents a communication line to a service which can be used + to call that service's methods. The service may be running on another + machine. Normally, you should not use an RpcChannel directly, but instead + construct a stub {@link Service} wrapping it. Example: + + Example: + RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234") + RpcController controller = rpcImpl.Controller() + MyService service = MyService_Stub(channel) + service.MyMethod(controller, request, callback) + """ + + def CallMethod(self, method_descriptor, rpc_controller, + request, response_class, done): + """Calls the method identified by the descriptor. + + Call the given method of the remote service. The signature of this + procedure looks the same as Service.CallMethod(), but the requirements + are less strict in one important way: the request object doesn't have to + be of any specific class as long as its descriptor is method.input_type. + """ + raise NotImplementedError diff --git a/winvenv/Lib/site-packages/google/protobuf/service_reflection.py b/winvenv/Lib/site-packages/google/protobuf/service_reflection.py new file mode 100644 index 0000000..1c3636a --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/service_reflection.py @@ -0,0 +1,284 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains metaclasses used to create protocol service and service stub +classes from ServiceDescriptor objects at runtime. + +The GeneratedServiceType and GeneratedServiceStubType metaclasses are used to +inject all useful functionality into the classes output by the protocol +compiler at compile-time. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + + +class GeneratedServiceType(type): + + """Metaclass for service classes created at runtime from ServiceDescriptors. + + Implementations for all methods described in the Service class are added here + by this class. We also create properties to allow getting/setting all fields + in the protocol message. + + The protocol compiler currently uses this metaclass to create protocol service + classes at runtime. Clients can also manually create their own classes at + runtime, as in this example: + + mydescriptor = ServiceDescriptor(.....) + class MyProtoService(service.Service): + __metaclass__ = GeneratedServiceType + DESCRIPTOR = mydescriptor + myservice_instance = MyProtoService() + ... + """ + + _DESCRIPTOR_KEY = 'DESCRIPTOR' + + def __init__(cls, name, bases, dictionary): + """Creates a message service class. + + Args: + name: Name of the class (ignored, but required by the metaclass + protocol). + bases: Base classes of the class being constructed. + dictionary: The class dictionary of the class being constructed. + dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object + describing this protocol service type. + """ + # Don't do anything if this class doesn't have a descriptor. This happens + # when a service class is subclassed. + if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary: + return + descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY] + service_builder = _ServiceBuilder(descriptor) + service_builder.BuildService(cls) + + +class GeneratedServiceStubType(GeneratedServiceType): + + """Metaclass for service stubs created at runtime from ServiceDescriptors. + + This class has similar responsibilities as GeneratedServiceType, except that + it creates the service stub classes. + """ + + _DESCRIPTOR_KEY = 'DESCRIPTOR' + + def __init__(cls, name, bases, dictionary): + """Creates a message service stub class. + + Args: + name: Name of the class (ignored, here). + bases: Base classes of the class being constructed. + dictionary: The class dictionary of the class being constructed. + dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object + describing this protocol service type. + """ + super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary) + # Don't do anything if this class doesn't have a descriptor. This happens + # when a service stub is subclassed. + if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary: + return + descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] + service_stub_builder = _ServiceStubBuilder(descriptor) + service_stub_builder.BuildServiceStub(cls) + + +class _ServiceBuilder(object): + + """This class constructs a protocol service class using a service descriptor. + + Given a service descriptor, this class constructs a class that represents + the specified service descriptor. One service builder instance constructs + exactly one service class. That means all instances of that class share the + same builder. + """ + + def __init__(self, service_descriptor): + """Initializes an instance of the service class builder. + + Args: + service_descriptor: ServiceDescriptor to use when constructing the + service class. + """ + self.descriptor = service_descriptor + + def BuildService(self, cls): + """Constructs the service class. + + Args: + cls: The class that will be constructed. + """ + + # CallMethod needs to operate with an instance of the Service class. This + # internal wrapper function exists only to be able to pass the service + # instance to the method that does the real CallMethod work. + def _WrapCallMethod(srvc, method_descriptor, + rpc_controller, request, callback): + return self._CallMethod(srvc, method_descriptor, + rpc_controller, request, callback) + self.cls = cls + cls.CallMethod = _WrapCallMethod + cls.GetDescriptor = staticmethod(lambda: self.descriptor) + cls.GetDescriptor.__doc__ = "Returns the service descriptor." + cls.GetRequestClass = self._GetRequestClass + cls.GetResponseClass = self._GetResponseClass + for method in self.descriptor.methods: + setattr(cls, method.name, self._GenerateNonImplementedMethod(method)) + + def _CallMethod(self, srvc, method_descriptor, + rpc_controller, request, callback): + """Calls the method described by a given method descriptor. + + Args: + srvc: Instance of the service for which this method is called. + method_descriptor: Descriptor that represent the method to call. + rpc_controller: RPC controller to use for this method's execution. + request: Request protocol message. + callback: A callback to invoke after the method has completed. + """ + if method_descriptor.containing_service != self.descriptor: + raise RuntimeError( + 'CallMethod() given method descriptor for wrong service type.') + method = getattr(srvc, method_descriptor.name) + return method(rpc_controller, request, callback) + + def _GetRequestClass(self, method_descriptor): + """Returns the class of the request protocol message. + + Args: + method_descriptor: Descriptor of the method for which to return the + request protocol message class. + + Returns: + A class that represents the input protocol message of the specified + method. + """ + if method_descriptor.containing_service != self.descriptor: + raise RuntimeError( + 'GetRequestClass() given method descriptor for wrong service type.') + return method_descriptor.input_type._concrete_class + + def _GetResponseClass(self, method_descriptor): + """Returns the class of the response protocol message. + + Args: + method_descriptor: Descriptor of the method for which to return the + response protocol message class. + + Returns: + A class that represents the output protocol message of the specified + method. + """ + if method_descriptor.containing_service != self.descriptor: + raise RuntimeError( + 'GetResponseClass() given method descriptor for wrong service type.') + return method_descriptor.output_type._concrete_class + + def _GenerateNonImplementedMethod(self, method): + """Generates and returns a method that can be set for a service methods. + + Args: + method: Descriptor of the service method for which a method is to be + generated. + + Returns: + A method that can be added to the service class. + """ + return lambda inst, rpc_controller, request, callback: ( + self._NonImplementedMethod(method.name, rpc_controller, callback)) + + def _NonImplementedMethod(self, method_name, rpc_controller, callback): + """The body of all methods in the generated service class. + + Args: + method_name: Name of the method being executed. + rpc_controller: RPC controller used to execute this method. + callback: A callback which will be invoked when the method finishes. + """ + rpc_controller.SetFailed('Method %s not implemented.' % method_name) + callback(None) + + +class _ServiceStubBuilder(object): + + """Constructs a protocol service stub class using a service descriptor. + + Given a service descriptor, this class constructs a suitable stub class. + A stub is just a type-safe wrapper around an RpcChannel which emulates a + local implementation of the service. + + One service stub builder instance constructs exactly one class. It means all + instances of that class share the same service stub builder. + """ + + def __init__(self, service_descriptor): + """Initializes an instance of the service stub class builder. + + Args: + service_descriptor: ServiceDescriptor to use when constructing the + stub class. + """ + self.descriptor = service_descriptor + + def BuildServiceStub(self, cls): + """Constructs the stub class. + + Args: + cls: The class that will be constructed. + """ + + def _ServiceStubInit(stub, rpc_channel): + stub.rpc_channel = rpc_channel + self.cls = cls + cls.__init__ = _ServiceStubInit + for method in self.descriptor.methods: + setattr(cls, method.name, self._GenerateStubMethod(method)) + + def _GenerateStubMethod(self, method): + return (lambda inst, rpc_controller, request, callback=None: + self._StubMethod(inst, method, rpc_controller, request, callback)) + + def _StubMethod(self, stub, method_descriptor, + rpc_controller, request, callback): + """The body of all service methods in the generated stub class. + + Args: + stub: Stub instance. + method_descriptor: Descriptor of the invoked method. + rpc_controller: Rpc controller to execute the method. + request: Request protocol message. + callback: A callback to execute when the method finishes. + Returns: + Response message (in case of blocking call). + """ + return stub.rpc_channel.CallMethod( + method_descriptor, rpc_controller, request, + method_descriptor.output_type._concrete_class, callback) diff --git a/winvenv/Lib/site-packages/google/protobuf/source_context_pb2.py b/winvenv/Lib/site-packages/google/protobuf/source_context_pb2.py new file mode 100644 index 0000000..6699c81 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/source_context_pb2.py @@ -0,0 +1,70 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/source_context.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/source_context.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\022SourceContextProtoP\001ZAgoogle.golang.org/genproto/protobuf/source_context;source_context\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n$google/protobuf/source_context.proto\x12\x0fgoogle.protobuf\"\"\n\rSourceContext\x12\x11\n\tfile_name\x18\x01 \x01(\tB\x95\x01\n\x13\x63om.google.protobufB\x12SourceContextProtoP\x01ZAgoogle.golang.org/genproto/protobuf/source_context;source_context\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_SOURCECONTEXT = _descriptor.Descriptor( + name='SourceContext', + full_name='google.protobuf.SourceContext', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file_name', full_name='google.protobuf.SourceContext.file_name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=57, + serialized_end=91, +) + +DESCRIPTOR.message_types_by_name['SourceContext'] = _SOURCECONTEXT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +SourceContext = _reflection.GeneratedProtocolMessageType('SourceContext', (_message.Message,), dict( + DESCRIPTOR = _SOURCECONTEXT, + __module__ = 'google.protobuf.source_context_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceContext) + )) +_sym_db.RegisterMessage(SourceContext) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/struct_pb2.py b/winvenv/Lib/site-packages/google/protobuf/struct_pb2.py new file mode 100644 index 0000000..6c5c445 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/struct_pb2.py @@ -0,0 +1,279 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/struct.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/struct.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\013StructProtoP\001Z1github.com/golang/protobuf/ptypes/struct;structpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1cgoogle/protobuf/struct.proto\x12\x0fgoogle.protobuf\"\x84\x01\n\x06Struct\x12\x33\n\x06\x66ields\x18\x01 \x03(\x0b\x32#.google.protobuf.Struct.FieldsEntry\x1a\x45\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01\"\xea\x01\n\x05Value\x12\x30\n\nnull_value\x18\x01 \x01(\x0e\x32\x1a.google.protobuf.NullValueH\x00\x12\x16\n\x0cnumber_value\x18\x02 \x01(\x01H\x00\x12\x16\n\x0cstring_value\x18\x03 \x01(\tH\x00\x12\x14\n\nbool_value\x18\x04 \x01(\x08H\x00\x12/\n\x0cstruct_value\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x12\x30\n\nlist_value\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.ListValueH\x00\x42\x06\n\x04kind\"3\n\tListValue\x12&\n\x06values\x18\x01 \x03(\x0b\x32\x16.google.protobuf.Value*\x1b\n\tNullValue\x12\x0e\n\nNULL_VALUE\x10\x00\x42\x81\x01\n\x13\x63om.google.protobufB\x0bStructProtoP\x01Z1github.com/golang/protobuf/ptypes/struct;structpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + +_NULLVALUE = _descriptor.EnumDescriptor( + name='NullValue', + full_name='google.protobuf.NullValue', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NULL_VALUE', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=474, + serialized_end=501, +) +_sym_db.RegisterEnumDescriptor(_NULLVALUE) + +NullValue = enum_type_wrapper.EnumTypeWrapper(_NULLVALUE) +NULL_VALUE = 0 + + + +_STRUCT_FIELDSENTRY = _descriptor.Descriptor( + name='FieldsEntry', + full_name='google.protobuf.Struct.FieldsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='google.protobuf.Struct.FieldsEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Struct.FieldsEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=182, +) + +_STRUCT = _descriptor.Descriptor( + name='Struct', + full_name='google.protobuf.Struct', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='fields', full_name='google.protobuf.Struct.fields', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_STRUCT_FIELDSENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=50, + serialized_end=182, +) + + +_VALUE = _descriptor.Descriptor( + name='Value', + full_name='google.protobuf.Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='null_value', full_name='google.protobuf.Value.null_value', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number_value', full_name='google.protobuf.Value.number_value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='google.protobuf.Value.string_value', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_value', full_name='google.protobuf.Value.bool_value', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='struct_value', full_name='google.protobuf.Value.struct_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='list_value', full_name='google.protobuf.Value.list_value', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='kind', full_name='google.protobuf.Value.kind', + index=0, containing_type=None, fields=[]), + ], + serialized_start=185, + serialized_end=419, +) + + +_LISTVALUE = _descriptor.Descriptor( + name='ListValue', + full_name='google.protobuf.ListValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='values', full_name='google.protobuf.ListValue.values', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=421, + serialized_end=472, +) + +_STRUCT_FIELDSENTRY.fields_by_name['value'].message_type = _VALUE +_STRUCT_FIELDSENTRY.containing_type = _STRUCT +_STRUCT.fields_by_name['fields'].message_type = _STRUCT_FIELDSENTRY +_VALUE.fields_by_name['null_value'].enum_type = _NULLVALUE +_VALUE.fields_by_name['struct_value'].message_type = _STRUCT +_VALUE.fields_by_name['list_value'].message_type = _LISTVALUE +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['null_value']) +_VALUE.fields_by_name['null_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['number_value']) +_VALUE.fields_by_name['number_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['string_value']) +_VALUE.fields_by_name['string_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['bool_value']) +_VALUE.fields_by_name['bool_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['struct_value']) +_VALUE.fields_by_name['struct_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['list_value']) +_VALUE.fields_by_name['list_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_LISTVALUE.fields_by_name['values'].message_type = _VALUE +DESCRIPTOR.message_types_by_name['Struct'] = _STRUCT +DESCRIPTOR.message_types_by_name['Value'] = _VALUE +DESCRIPTOR.message_types_by_name['ListValue'] = _LISTVALUE +DESCRIPTOR.enum_types_by_name['NullValue'] = _NULLVALUE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Struct = _reflection.GeneratedProtocolMessageType('Struct', (_message.Message,), dict( + + FieldsEntry = _reflection.GeneratedProtocolMessageType('FieldsEntry', (_message.Message,), dict( + DESCRIPTOR = _STRUCT_FIELDSENTRY, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Struct.FieldsEntry) + )) + , + DESCRIPTOR = _STRUCT, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Struct) + )) +_sym_db.RegisterMessage(Struct) +_sym_db.RegisterMessage(Struct.FieldsEntry) + +Value = _reflection.GeneratedProtocolMessageType('Value', (_message.Message,), dict( + DESCRIPTOR = _VALUE, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Value) + )) +_sym_db.RegisterMessage(Value) + +ListValue = _reflection.GeneratedProtocolMessageType('ListValue', (_message.Message,), dict( + DESCRIPTOR = _LISTVALUE, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ListValue) + )) +_sym_db.RegisterMessage(ListValue) + + +DESCRIPTOR._options = None +_STRUCT_FIELDSENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/symbol_database.py b/winvenv/Lib/site-packages/google/protobuf/symbol_database.py new file mode 100644 index 0000000..5ad869f --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/symbol_database.py @@ -0,0 +1,189 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""A database of Python protocol buffer generated symbols. + +SymbolDatabase is the MessageFactory for messages generated at compile time, +and makes it easy to create new instances of a registered type, given only the +type's protocol buffer symbol name. + +Example usage: + + db = symbol_database.SymbolDatabase() + + # Register symbols of interest, from one or multiple files. + db.RegisterFileDescriptor(my_proto_pb2.DESCRIPTOR) + db.RegisterMessage(my_proto_pb2.MyMessage) + db.RegisterEnumDescriptor(my_proto_pb2.MyEnum.DESCRIPTOR) + + # The database can be used as a MessageFactory, to generate types based on + # their name: + types = db.GetMessages(['my_proto.proto']) + my_message_instance = types['MyMessage']() + + # The database's underlying descriptor pool can be queried, so it's not + # necessary to know a type's filename to be able to generate it: + filename = db.pool.FindFileContainingSymbol('MyMessage') + my_message_instance = db.GetMessages([filename])['MyMessage']() + + # This functionality is also provided directly via a convenience method: + my_message_instance = db.GetSymbol('MyMessage')() +""" + + +from google.protobuf import descriptor_pool +from google.protobuf import message_factory + + +class SymbolDatabase(message_factory.MessageFactory): + """A database of Python generated symbols.""" + + def RegisterMessage(self, message): + """Registers the given message type in the local database. + + Calls to GetSymbol() and GetMessages() will return messages registered here. + + Args: + message: a message.Message, to be registered. + + Returns: + The provided message. + """ + + desc = message.DESCRIPTOR + self._classes[desc] = message + self.RegisterMessageDescriptor(desc) + return message + + def RegisterMessageDescriptor(self, message_descriptor): + """Registers the given message descriptor in the local database. + + Args: + message_descriptor: a descriptor.MessageDescriptor. + """ + self.pool.AddDescriptor(message_descriptor) + + def RegisterEnumDescriptor(self, enum_descriptor): + """Registers the given enum descriptor in the local database. + + Args: + enum_descriptor: a descriptor.EnumDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddEnumDescriptor(enum_descriptor) + return enum_descriptor + + def RegisterServiceDescriptor(self, service_descriptor): + """Registers the given service descriptor in the local database. + + Args: + service_descriptor: a descriptor.ServiceDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddServiceDescriptor(service_descriptor) + + def RegisterFileDescriptor(self, file_descriptor): + """Registers the given file descriptor in the local database. + + Args: + file_descriptor: a descriptor.FileDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddFileDescriptor(file_descriptor) + + def GetSymbol(self, symbol): + """Tries to find a symbol in the local database. + + Currently, this method only returns message.Message instances, however, if + may be extended in future to support other symbol types. + + Args: + symbol: A str, a protocol buffer symbol. + + Returns: + A Python class corresponding to the symbol. + + Raises: + KeyError: if the symbol could not be found. + """ + + return self._classes[self.pool.FindMessageTypeByName(symbol)] + + def GetMessages(self, files): + # TODO(amauryfa): Fix the differences with MessageFactory. + """Gets all registered messages from a specified file. + + Only messages already created and registered will be returned; (this is the + case for imported _pb2 modules) + But unlike MessageFactory, this version also returns already defined nested + messages, but does not register any message extensions. + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. + + Raises: + KeyError: if a file could not be found. + """ + + def _GetAllMessages(desc): + """Walk a message Descriptor and recursively yields all message names.""" + yield desc + for msg_desc in desc.nested_types: + for nested_desc in _GetAllMessages(msg_desc): + yield nested_desc + + result = {} + for file_name in files: + file_desc = self.pool.FindFileByName(file_name) + for msg_desc in file_desc.message_types_by_name.values(): + for desc in _GetAllMessages(msg_desc): + try: + result[desc.full_name] = self._classes[desc] + except KeyError: + # This descriptor has no registered class, skip it. + pass + return result + + +_DEFAULT = SymbolDatabase(pool=descriptor_pool.Default()) + + +def Default(): + """Returns the default SymbolDatabase.""" + return _DEFAULT diff --git a/winvenv/Lib/site-packages/google/protobuf/test_messages_proto2_pb2.py b/winvenv/Lib/site-packages/google/protobuf/test_messages_proto2_pb2.py new file mode 100644 index 0000000..6b98193 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/test_messages_proto2_pb2.py @@ -0,0 +1,1990 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/test_messages_proto2.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/test_messages_proto2.proto', + package='protobuf_test_messages.proto2', + syntax='proto2', + serialized_options=_b('\n(com.google.protobuf_test_messages.proto2H\001\370\001\001'), + serialized_pb=_b('\n*google/protobuf/test_messages_proto2.proto\x12\x1dprotobuf_test_messages.proto2\"\xde\x32\n\x12TestAllTypesProto2\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12`\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage\x12U\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32\x33.protobuf_test_messages.proto2.ForeignMessageProto2\x12Z\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum\x12O\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x30.protobuf_test_messages.proto2.ForeignEnumProto2\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12L\n\x11recursive_message\x18\x1b \x01(\x0b\x32\x31.protobuf_test_messages.proto2.TestAllTypesProto2\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12`\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage\x12U\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32\x33.protobuf_test_messages.proto2.ForeignMessageProto2\x12Z\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum\x12O\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\x30.protobuf_test_messages.proto2.ForeignEnumProto2\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12]\n\x0fmap_int32_int32\x18\x38 \x03(\x0b\x32\x44.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry\x12]\n\x0fmap_int64_int64\x18\x39 \x03(\x0b\x32\x44.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry\x12\x61\n\x11map_uint32_uint32\x18: \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry\x12\x61\n\x11map_uint64_uint64\x18; \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry\x12\x61\n\x11map_sint32_sint32\x18< \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry\x12\x61\n\x11map_sint64_sint64\x18= \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry\x12\x65\n\x13map_fixed32_fixed32\x18> \x03(\x0b\x32H.protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry\x12\x65\n\x13map_fixed64_fixed64\x18? \x03(\x0b\x32H.protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry\x12i\n\x15map_sfixed32_sfixed32\x18@ \x03(\x0b\x32J.protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry\x12i\n\x15map_sfixed64_sfixed64\x18\x41 \x03(\x0b\x32J.protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry\x12]\n\x0fmap_int32_float\x18\x42 \x03(\x0b\x32\x44.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry\x12_\n\x10map_int32_double\x18\x43 \x03(\x0b\x32\x45.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry\x12Y\n\rmap_bool_bool\x18\x44 \x03(\x0b\x32\x42.protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry\x12\x61\n\x11map_string_string\x18\x45 \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry\x12_\n\x10map_string_bytes\x18\x46 \x03(\x0b\x32\x45.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry\x12p\n\x19map_string_nested_message\x18G \x03(\x0b\x32M.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry\x12r\n\x1amap_string_foreign_message\x18H \x03(\x0b\x32N.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry\x12j\n\x16map_string_nested_enum\x18I \x03(\x0b\x32J.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry\x12l\n\x17map_string_foreign_enum\x18J \x03(\x0b\x32K.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12_\n\x14oneof_nested_message\x18p \x01(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12\x14\n\noneof_bool\x18s \x01(\x08H\x00\x12\x16\n\x0coneof_uint64\x18t \x01(\x04H\x00\x12\x15\n\x0boneof_float\x18u \x01(\x02H\x00\x12\x16\n\x0coneof_double\x18v \x01(\x01H\x00\x12R\n\noneof_enum\x18w \x01(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnumH\x00\x12\x45\n\x04\x64\x61ta\x18\xc9\x01 \x01(\n26.protobuf_test_messages.proto2.TestAllTypesProto2.Data\x12\x13\n\nfieldname1\x18\x91\x03 \x01(\x05\x12\x14\n\x0b\x66ield_name2\x18\x92\x03 \x01(\x05\x12\x15\n\x0c_field_name3\x18\x93\x03 \x01(\x05\x12\x16\n\rfield__name4_\x18\x94\x03 \x01(\x05\x12\x14\n\x0b\x66ield0name5\x18\x95\x03 \x01(\x05\x12\x16\n\rfield_0_name6\x18\x96\x03 \x01(\x05\x12\x13\n\nfieldName7\x18\x97\x03 \x01(\x05\x12\x13\n\nFieldName8\x18\x98\x03 \x01(\x05\x12\x14\n\x0b\x66ield_Name9\x18\x99\x03 \x01(\x05\x12\x15\n\x0c\x46ield_Name10\x18\x9a\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_NAME11\x18\x9b\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_name12\x18\x9c\x03 \x01(\x05\x12\x17\n\x0e__field_name13\x18\x9d\x03 \x01(\x05\x12\x17\n\x0e__Field_name14\x18\x9e\x03 \x01(\x05\x12\x16\n\rfield__name15\x18\x9f\x03 \x01(\x05\x12\x16\n\rfield__Name16\x18\xa0\x03 \x01(\x05\x12\x17\n\x0e\x66ield_name17__\x18\xa1\x03 \x01(\x05\x12\x17\n\x0e\x46ield_name18__\x18\xa2\x03 \x01(\x05\x1a\x62\n\rNestedMessage\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\x46\n\x0b\x63orecursive\x18\x02 \x01(\x0b\x32\x31.protobuf_test_messages.proto2.TestAllTypesProto2\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13MapStringBytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a~\n\x1bMapStringNestedMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12N\n\x05value\x18\x02 \x01(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage:\x02\x38\x01\x1as\n\x1cMapStringForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x42\n\x05value\x18\x02 \x01(\x0b\x32\x33.protobuf_test_messages.proto2.ForeignMessageProto2:\x02\x38\x01\x1ax\n\x18MapStringNestedEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12K\n\x05value\x18\x02 \x01(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum:\x02\x38\x01\x1am\n\x19MapStringForeignEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0e\x32\x30.protobuf_test_messages.proto2.ForeignEnumProto2:\x02\x38\x01\x1a\x33\n\x04\x44\x61ta\x12\x14\n\x0bgroup_int32\x18\xca\x01 \x01(\x05\x12\x15\n\x0cgroup_uint32\x18\xcb\x01 \x01(\r\x1a!\n\x11MessageSetCorrect*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\x1a\xe0\x01\n\x1bMessageSetCorrectExtension1\x12\x0b\n\x03str\x18\x19 \x01(\t2\xb3\x01\n\x15message_set_extension\x12\x43.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect\x18\xf9\xbb^ \x01(\x0b\x32M.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1\x1a\xdf\x01\n\x1bMessageSetCorrectExtension2\x12\t\n\x01i\x18\t \x01(\x05\x32\xb4\x01\n\x15message_set_extension\x12\x43.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect\x18\x90\xb3\xfc\x01 \x01(\x0b\x32M.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x12\x07\n\x03\x42\x41Z\x10\x02\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01*\x05\x08x\x10\xc9\x01\x42\r\n\x0boneof_field\"!\n\x14\x46oreignMessageProto2\x12\t\n\x01\x63\x18\x01 \x01(\x05*F\n\x11\x46oreignEnumProto2\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x00\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x01\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x02:J\n\x0f\x65xtension_int32\x12\x31.protobuf_test_messages.proto2.TestAllTypesProto2\x18x \x01(\x05\x42/\n(com.google.protobuf_test_messages.proto2H\x01\xf8\x01\x01') +) + +_FOREIGNENUMPROTO2 = _descriptor.EnumDescriptor( + name='ForeignEnumProto2', + full_name='protobuf_test_messages.proto2.ForeignEnumProto2', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6609, + serialized_end=6679, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUMPROTO2) + +ForeignEnumProto2 = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUMPROTO2) +FOREIGN_FOO = 0 +FOREIGN_BAR = 1 +FOREIGN_BAZ = 2 + +EXTENSION_INT32_FIELD_NUMBER = 120 +extension_int32 = _descriptor.FieldDescriptor( + name='extension_int32', full_name='protobuf_test_messages.proto2.extension_int32', index=0, + number=120, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_TESTALLTYPESPROTO2_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6493, + serialized_end=6550, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPESPROTO2_NESTEDENUM) + + +_TESTALLTYPESPROTO2_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='corecursive', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage.corecursive', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4534, + serialized_end=4632, +) + +_TESTALLTYPESPROTO2_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4634, + serialized_end=4686, +) + +_TESTALLTYPESPROTO2_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4688, + serialized_end=4740, +) + +_TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4742, + serialized_end=4796, +) + +_TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4798, + serialized_end=4852, +) + +_TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4854, + serialized_end=4908, +) + +_TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4910, + serialized_end=4964, +) + +_TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4966, + serialized_end=5022, +) + +_TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5024, + serialized_end=5080, +) + +_TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5082, + serialized_end=5140, +) + +_TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5142, + serialized_end=5200, +) + +_TESTALLTYPESPROTO2_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5202, + serialized_end=5254, +) + +_TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5256, + serialized_end=5309, +) + +_TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5311, + serialized_end=5361, +) + +_TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5363, + serialized_end=5417, +) + +_TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY = _descriptor.Descriptor( + name='MapStringBytesEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5419, + serialized_end=5472, +) + +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringNestedMessageEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5474, + serialized_end=5600, +) + +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringForeignMessageEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5602, + serialized_end=5717, +) + +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY = _descriptor.Descriptor( + name='MapStringNestedEnumEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5719, + serialized_end=5839, +) + +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY = _descriptor.Descriptor( + name='MapStringForeignEnumEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5841, + serialized_end=5950, +) + +_TESTALLTYPESPROTO2_DATA = _descriptor.Descriptor( + name='Data', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Data', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='group_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Data.group_int32', index=0, + number=202, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='group_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Data.group_uint32', index=1, + number=203, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5952, + serialized_end=6003, +) + +_TESTALLTYPESPROTO2_MESSAGESETCORRECT = _descriptor.Descriptor( + name='MessageSetCorrect', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=6005, + serialized_end=6038, +) + +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1 = _descriptor.Descriptor( + name='MessageSetCorrectExtension1', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='str', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1.str', index=0, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1.message_set_extension', index=0, + number=1547769, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6041, + serialized_end=6265, +) + +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2 = _descriptor.Descriptor( + name='MessageSetCorrectExtension2', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2.i', index=0, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2.message_set_extension', index=0, + number=4135312, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6268, + serialized_end=6491, +) + +_TESTALLTYPESPROTO2 = _descriptor.Descriptor( + name='TestAllTypesProto2', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_nested_message', index=15, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_foreign_message', index=16, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_nested_enum', index=17, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_foreign_enum', index=18, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_string_piece', index=19, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_cord', index=20, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='recursive_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.recursive_message', index=21, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_int32', index=22, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_int64', index=23, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_uint32', index=24, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_uint64', index=25, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sint32', index=26, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sint64', index=27, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_fixed32', index=28, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_fixed64', index=29, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sfixed32', index=30, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sfixed64', index=31, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_float', index=32, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_double', index=33, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_bool', index=34, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_string', index=35, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_bytes', index=36, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_nested_message', index=37, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_foreign_message', index=38, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_nested_enum', index=39, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_foreign_enum', index=40, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_string_piece', index=41, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_cord', index=42, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int32_int32', index=43, + number=56, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int64_int64', index=44, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_uint32_uint32', index=45, + number=58, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_uint64_uint64', index=46, + number=59, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sint32_sint32', index=47, + number=60, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sint64_sint64', index=48, + number=61, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_fixed32_fixed32', index=49, + number=62, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_fixed64_fixed64', index=50, + number=63, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sfixed32_sfixed32', index=51, + number=64, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sfixed64_sfixed64', index=52, + number=65, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int32_float', index=53, + number=66, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int32_double', index=54, + number=67, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_bool_bool', index=55, + number=68, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_string', index=56, + number=69, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_bytes', index=57, + number=70, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_nested_message', index=58, + number=71, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_foreign_message', index=59, + number=72, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_nested_enum', index=60, + number=73, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_foreign_enum', index=61, + number=74, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_uint32', index=62, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_nested_message', index=63, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_string', index=64, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_bytes', index=65, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_bool', index=66, + number=115, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_uint64', index=67, + number=116, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_float', index=68, + number=117, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_double', index=69, + number=118, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_enum', index=70, + number=119, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.data', index=71, + number=201, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldname1', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.fieldname1', index=72, + number=401, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name2', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_name2', index=73, + number=402, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='_field_name3', full_name='protobuf_test_messages.proto2.TestAllTypesProto2._field_name3', index=74, + number=403, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name4_', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field__name4_', index=75, + number=404, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field0name5', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field0name5', index=76, + number=405, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_0_name6', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_0_name6', index=77, + number=406, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldName7', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.fieldName7', index=78, + number=407, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FieldName8', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.FieldName8', index=79, + number=408, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_Name9', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_Name9', index=80, + number=409, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_Name10', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Field_Name10', index=81, + number=410, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_NAME11', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.FIELD_NAME11', index=82, + number=411, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_name12', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.FIELD_name12', index=83, + number=412, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__field_name13', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.__field_name13', index=84, + number=413, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__Field_name14', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.__Field_name14', index=85, + number=414, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name15', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field__name15', index=86, + number=415, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__Name16', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field__Name16', index=87, + number=416, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name17__', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_name17__', index=88, + number=417, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_name18__', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Field_name18__', index=89, + number=418, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPESPROTO2_NESTEDMESSAGE, _TESTALLTYPESPROTO2_MAPINT32INT32ENTRY, _TESTALLTYPESPROTO2_MAPINT64INT64ENTRY, _TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY, _TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY, _TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY, _TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY, _TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY, _TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY, _TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY, _TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY, _TESTALLTYPESPROTO2_MAPINT32FLOATENTRY, _TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY, _TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY, _TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY, _TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY, _TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY, _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY, _TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY, _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY, _TESTALLTYPESPROTO2_DATA, _TESTALLTYPESPROTO2_MESSAGESETCORRECT, _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1, _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2, ], + enum_types=[ + _TESTALLTYPESPROTO2_NESTEDENUM, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(120, 201), ], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=78, + serialized_end=6572, +) + + +_FOREIGNMESSAGEPROTO2 = _descriptor.Descriptor( + name='ForeignMessageProto2', + full_name='protobuf_test_messages.proto2.ForeignMessageProto2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_test_messages.proto2.ForeignMessageProto2.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6574, + serialized_end=6607, +) + +_TESTALLTYPESPROTO2_NESTEDMESSAGE.fields_by_name['corecursive'].message_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_NESTEDMESSAGE.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT32INT32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT64INT64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT32FLOATENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY.fields_by_name['value'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = _FOREIGNMESSAGEPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY.fields_by_name['value'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY.fields_by_name['value'].enum_type = _FOREIGNENUMPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_DATA.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MESSAGESETCORRECT.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGEPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUMPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['recursive_message'].message_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGEPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUMPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['map_int32_int32'].message_type = _TESTALLTYPESPROTO2_MAPINT32INT32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_int64_int64'].message_type = _TESTALLTYPESPROTO2_MAPINT64INT64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_uint32_uint32'].message_type = _TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_uint64_uint64'].message_type = _TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sint32_sint32'].message_type = _TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sint64_sint64'].message_type = _TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_fixed32_fixed32'].message_type = _TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_fixed64_fixed64'].message_type = _TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_int32_float'].message_type = _TESTALLTYPESPROTO2_MAPINT32FLOATENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_int32_double'].message_type = _TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_bool_bool'].message_type = _TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_string'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_bytes'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_nested_message'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_foreign_message'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_nested_enum'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_foreign_enum'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY +_TESTALLTYPESPROTO2.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2.fields_by_name['oneof_enum'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2.fields_by_name['data'].message_type = _TESTALLTYPESPROTO2_DATA +_TESTALLTYPESPROTO2_NESTEDENUM.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_uint32']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_nested_message']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_string']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_bytes']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_bool']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_bool'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_uint64']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_uint64'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_float']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_float'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_double']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_double'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_enum']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_enum'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +DESCRIPTOR.message_types_by_name['TestAllTypesProto2'] = _TESTALLTYPESPROTO2 +DESCRIPTOR.message_types_by_name['ForeignMessageProto2'] = _FOREIGNMESSAGEPROTO2 +DESCRIPTOR.enum_types_by_name['ForeignEnumProto2'] = _FOREIGNENUMPROTO2 +DESCRIPTOR.extensions_by_name['extension_int32'] = extension_int32 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypesProto2 = _reflection.GeneratedProtocolMessageType('TestAllTypesProto2', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_NESTEDMESSAGE, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage) + )) + , + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry) + )) + , + + MapStringBytesEntry = _reflection.GeneratedProtocolMessageType('MapStringBytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry) + )) + , + + MapStringNestedMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry) + )) + , + + MapStringForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry) + )) + , + + MapStringNestedEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry) + )) + , + + MapStringForeignEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry) + )) + , + + Data = _reflection.GeneratedProtocolMessageType('Data', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_DATA, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.Data) + )) + , + + MessageSetCorrect = _reflection.GeneratedProtocolMessageType('MessageSetCorrect', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MESSAGESETCORRECT, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect) + )) + , + + MessageSetCorrectExtension1 = _reflection.GeneratedProtocolMessageType('MessageSetCorrectExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1) + )) + , + + MessageSetCorrectExtension2 = _reflection.GeneratedProtocolMessageType('MessageSetCorrectExtension2', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2) + )) + , + DESCRIPTOR = _TESTALLTYPESPROTO2, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2) + )) +_sym_db.RegisterMessage(TestAllTypesProto2) +_sym_db.RegisterMessage(TestAllTypesProto2.NestedMessage) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringStringEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringBytesEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringNestedMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringForeignMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringNestedEnumEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringForeignEnumEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.Data) +_sym_db.RegisterMessage(TestAllTypesProto2.MessageSetCorrect) +_sym_db.RegisterMessage(TestAllTypesProto2.MessageSetCorrectExtension1) +_sym_db.RegisterMessage(TestAllTypesProto2.MessageSetCorrectExtension2) + +ForeignMessageProto2 = _reflection.GeneratedProtocolMessageType('ForeignMessageProto2', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGEPROTO2, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.ForeignMessageProto2) + )) +_sym_db.RegisterMessage(ForeignMessageProto2) + +TestAllTypesProto2.RegisterExtension(extension_int32) +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1.extensions_by_name['message_set_extension'].message_type = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1 +TestAllTypesProto2.MessageSetCorrect.RegisterExtension(_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1.extensions_by_name['message_set_extension']) +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2.extensions_by_name['message_set_extension'].message_type = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2 +TestAllTypesProto2.MessageSetCorrect.RegisterExtension(_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2.extensions_by_name['message_set_extension']) + +DESCRIPTOR._options = None +_TESTALLTYPESPROTO2_MAPINT32INT32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPINT64INT64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPINT32FLOATENTRY._options = None +_TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY._options = None +_TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY._options = None +_TESTALLTYPESPROTO2_MESSAGESETCORRECT._options = None +_TESTALLTYPESPROTO2.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPESPROTO2.fields_by_name['optional_cord']._options = None +_TESTALLTYPESPROTO2.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPESPROTO2.fields_by_name['repeated_cord']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/test_messages_proto3_pb2.py b/winvenv/Lib/site-packages/google/protobuf/test_messages_proto3_pb2.py new file mode 100644 index 0000000..81411cd --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/test_messages_proto3_pb2.py @@ -0,0 +1,2044 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/test_messages_proto3.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/test_messages_proto3.proto', + package='protobuf_test_messages.proto3', + syntax='proto3', + serialized_options=_b('\n(com.google.protobuf_test_messages.proto3H\001\370\001\001\242\002\006Proto3'), + serialized_pb=_b('\n*google/protobuf/test_messages_proto3.proto\x12\x1dprotobuf_test_messages.proto3\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\xb4;\n\x12TestAllTypesProto3\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12`\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage\x12O\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32-.protobuf_test_messages.proto3.ForeignMessage\x12Z\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum\x12I\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32*.protobuf_test_messages.proto3.ForeignEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12L\n\x11recursive_message\x18\x1b \x01(\x0b\x32\x31.protobuf_test_messages.proto3.TestAllTypesProto3\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12`\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage\x12O\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32-.protobuf_test_messages.proto3.ForeignMessage\x12Z\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum\x12I\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32*.protobuf_test_messages.proto3.ForeignEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12]\n\x0fmap_int32_int32\x18\x38 \x03(\x0b\x32\x44.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry\x12]\n\x0fmap_int64_int64\x18\x39 \x03(\x0b\x32\x44.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry\x12\x61\n\x11map_uint32_uint32\x18: \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry\x12\x61\n\x11map_uint64_uint64\x18; \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry\x12\x61\n\x11map_sint32_sint32\x18< \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry\x12\x61\n\x11map_sint64_sint64\x18= \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry\x12\x65\n\x13map_fixed32_fixed32\x18> \x03(\x0b\x32H.protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry\x12\x65\n\x13map_fixed64_fixed64\x18? \x03(\x0b\x32H.protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry\x12i\n\x15map_sfixed32_sfixed32\x18@ \x03(\x0b\x32J.protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry\x12i\n\x15map_sfixed64_sfixed64\x18\x41 \x03(\x0b\x32J.protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry\x12]\n\x0fmap_int32_float\x18\x42 \x03(\x0b\x32\x44.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry\x12_\n\x10map_int32_double\x18\x43 \x03(\x0b\x32\x45.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry\x12Y\n\rmap_bool_bool\x18\x44 \x03(\x0b\x32\x42.protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry\x12\x61\n\x11map_string_string\x18\x45 \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry\x12_\n\x10map_string_bytes\x18\x46 \x03(\x0b\x32\x45.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry\x12p\n\x19map_string_nested_message\x18G \x03(\x0b\x32M.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry\x12r\n\x1amap_string_foreign_message\x18H \x03(\x0b\x32N.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry\x12j\n\x16map_string_nested_enum\x18I \x03(\x0b\x32J.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry\x12l\n\x17map_string_foreign_enum\x18J \x03(\x0b\x32K.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12_\n\x14oneof_nested_message\x18p \x01(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12\x14\n\noneof_bool\x18s \x01(\x08H\x00\x12\x16\n\x0coneof_uint64\x18t \x01(\x04H\x00\x12\x15\n\x0boneof_float\x18u \x01(\x02H\x00\x12\x16\n\x0coneof_double\x18v \x01(\x01H\x00\x12R\n\noneof_enum\x18w \x01(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnumH\x00\x12:\n\x15optional_bool_wrapper\x18\xc9\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\x12<\n\x16optional_int32_wrapper\x18\xca\x01 \x01(\x0b\x32\x1b.google.protobuf.Int32Value\x12<\n\x16optional_int64_wrapper\x18\xcb\x01 \x01(\x0b\x32\x1b.google.protobuf.Int64Value\x12>\n\x17optional_uint32_wrapper\x18\xcc\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12>\n\x17optional_uint64_wrapper\x18\xcd\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12<\n\x16optional_float_wrapper\x18\xce\x01 \x01(\x0b\x32\x1b.google.protobuf.FloatValue\x12>\n\x17optional_double_wrapper\x18\xcf\x01 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue\x12>\n\x17optional_string_wrapper\x18\xd0\x01 \x01(\x0b\x32\x1c.google.protobuf.StringValue\x12<\n\x16optional_bytes_wrapper\x18\xd1\x01 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x12:\n\x15repeated_bool_wrapper\x18\xd3\x01 \x03(\x0b\x32\x1a.google.protobuf.BoolValue\x12<\n\x16repeated_int32_wrapper\x18\xd4\x01 \x03(\x0b\x32\x1b.google.protobuf.Int32Value\x12<\n\x16repeated_int64_wrapper\x18\xd5\x01 \x03(\x0b\x32\x1b.google.protobuf.Int64Value\x12>\n\x17repeated_uint32_wrapper\x18\xd6\x01 \x03(\x0b\x32\x1c.google.protobuf.UInt32Value\x12>\n\x17repeated_uint64_wrapper\x18\xd7\x01 \x03(\x0b\x32\x1c.google.protobuf.UInt64Value\x12<\n\x16repeated_float_wrapper\x18\xd8\x01 \x03(\x0b\x32\x1b.google.protobuf.FloatValue\x12>\n\x17repeated_double_wrapper\x18\xd9\x01 \x03(\x0b\x32\x1c.google.protobuf.DoubleValue\x12>\n\x17repeated_string_wrapper\x18\xda\x01 \x03(\x0b\x32\x1c.google.protobuf.StringValue\x12<\n\x16repeated_bytes_wrapper\x18\xdb\x01 \x03(\x0b\x32\x1b.google.protobuf.BytesValue\x12\x35\n\x11optional_duration\x18\xad\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x12optional_timestamp\x18\xae\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x38\n\x13optional_field_mask\x18\xaf\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x31\n\x0foptional_struct\x18\xb0\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x12+\n\x0coptional_any\x18\xb1\x02 \x01(\x0b\x32\x14.google.protobuf.Any\x12/\n\x0eoptional_value\x18\xb2\x02 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x35\n\x11repeated_duration\x18\xb7\x02 \x03(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x12repeated_timestamp\x18\xb8\x02 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x12repeated_fieldmask\x18\xb9\x02 \x03(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x31\n\x0frepeated_struct\x18\xc4\x02 \x03(\x0b\x32\x17.google.protobuf.Struct\x12+\n\x0crepeated_any\x18\xbb\x02 \x03(\x0b\x32\x14.google.protobuf.Any\x12/\n\x0erepeated_value\x18\xbc\x02 \x03(\x0b\x32\x16.google.protobuf.Value\x12\x13\n\nfieldname1\x18\x91\x03 \x01(\x05\x12\x14\n\x0b\x66ield_name2\x18\x92\x03 \x01(\x05\x12\x15\n\x0c_field_name3\x18\x93\x03 \x01(\x05\x12\x16\n\rfield__name4_\x18\x94\x03 \x01(\x05\x12\x14\n\x0b\x66ield0name5\x18\x95\x03 \x01(\x05\x12\x16\n\rfield_0_name6\x18\x96\x03 \x01(\x05\x12\x13\n\nfieldName7\x18\x97\x03 \x01(\x05\x12\x13\n\nFieldName8\x18\x98\x03 \x01(\x05\x12\x14\n\x0b\x66ield_Name9\x18\x99\x03 \x01(\x05\x12\x15\n\x0c\x46ield_Name10\x18\x9a\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_NAME11\x18\x9b\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_name12\x18\x9c\x03 \x01(\x05\x12\x17\n\x0e__field_name13\x18\x9d\x03 \x01(\x05\x12\x17\n\x0e__Field_name14\x18\x9e\x03 \x01(\x05\x12\x16\n\rfield__name15\x18\x9f\x03 \x01(\x05\x12\x16\n\rfield__Name16\x18\xa0\x03 \x01(\x05\x12\x17\n\x0e\x66ield_name17__\x18\xa1\x03 \x01(\x05\x12\x17\n\x0e\x46ield_name18__\x18\xa2\x03 \x01(\x05\x1a\x62\n\rNestedMessage\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\x46\n\x0b\x63orecursive\x18\x02 \x01(\x0b\x32\x31.protobuf_test_messages.proto3.TestAllTypesProto3\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13MapStringBytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a~\n\x1bMapStringNestedMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12N\n\x05value\x18\x02 \x01(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage:\x02\x38\x01\x1am\n\x1cMapStringForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12<\n\x05value\x18\x02 \x01(\x0b\x32-.protobuf_test_messages.proto3.ForeignMessage:\x02\x38\x01\x1ax\n\x18MapStringNestedEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12K\n\x05value\x18\x02 \x01(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum:\x02\x38\x01\x1ag\n\x19MapStringForeignEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0e\x32*.protobuf_test_messages.proto3.ForeignEnum:\x02\x38\x01\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x12\x07\n\x03\x42\x41Z\x10\x02\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_fieldJ\x06\x08\xf5\x03\x10\xff\x03\"\x1b\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05*@\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x00\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x01\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x02\x42\x38\n(com.google.protobuf_test_messages.proto3H\x01\xf8\x01\x01\xa2\x02\x06Proto3b\x06proto3') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='protobuf_test_messages.proto3.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=7901, + serialized_end=7965, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +FOREIGN_FOO = 0 +FOREIGN_BAR = 1 +FOREIGN_BAZ = 2 + + +_TESTALLTYPESPROTO3_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=7790, + serialized_end=7847, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPESPROTO3_NESTEDENUM) + + +_TESTALLTYPESPROTO3_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='corecursive', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage.corecursive', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6384, + serialized_end=6482, +) + +_TESTALLTYPESPROTO3_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6484, + serialized_end=6536, +) + +_TESTALLTYPESPROTO3_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6538, + serialized_end=6590, +) + +_TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6592, + serialized_end=6646, +) + +_TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6648, + serialized_end=6702, +) + +_TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6704, + serialized_end=6758, +) + +_TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6760, + serialized_end=6814, +) + +_TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6816, + serialized_end=6872, +) + +_TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6874, + serialized_end=6930, +) + +_TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6932, + serialized_end=6990, +) + +_TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6992, + serialized_end=7050, +) + +_TESTALLTYPESPROTO3_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7052, + serialized_end=7104, +) + +_TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7106, + serialized_end=7159, +) + +_TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7161, + serialized_end=7211, +) + +_TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7213, + serialized_end=7267, +) + +_TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY = _descriptor.Descriptor( + name='MapStringBytesEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7269, + serialized_end=7322, +) + +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringNestedMessageEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7324, + serialized_end=7450, +) + +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringForeignMessageEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7452, + serialized_end=7561, +) + +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY = _descriptor.Descriptor( + name='MapStringNestedEnumEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7563, + serialized_end=7683, +) + +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY = _descriptor.Descriptor( + name='MapStringForeignEnumEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7685, + serialized_end=7788, +) + +_TESTALLTYPESPROTO3 = _descriptor.Descriptor( + name='TestAllTypesProto3', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_nested_message', index=15, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_foreign_message', index=16, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_nested_enum', index=17, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_foreign_enum', index=18, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_string_piece', index=19, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_cord', index=20, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='recursive_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.recursive_message', index=21, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int32', index=22, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int64', index=23, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint32', index=24, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint64', index=25, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sint32', index=26, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sint64', index=27, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_fixed32', index=28, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_fixed64', index=29, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sfixed32', index=30, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sfixed64', index=31, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_float', index=32, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_double', index=33, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bool', index=34, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_string', index=35, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bytes', index=36, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_nested_message', index=37, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_foreign_message', index=38, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_nested_enum', index=39, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_foreign_enum', index=40, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_string_piece', index=41, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_cord', index=42, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int32_int32', index=43, + number=56, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int64_int64', index=44, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_uint32_uint32', index=45, + number=58, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_uint64_uint64', index=46, + number=59, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sint32_sint32', index=47, + number=60, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sint64_sint64', index=48, + number=61, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_fixed32_fixed32', index=49, + number=62, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_fixed64_fixed64', index=50, + number=63, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sfixed32_sfixed32', index=51, + number=64, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sfixed64_sfixed64', index=52, + number=65, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int32_float', index=53, + number=66, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int32_double', index=54, + number=67, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_bool_bool', index=55, + number=68, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_string', index=56, + number=69, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_bytes', index=57, + number=70, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_nested_message', index=58, + number=71, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_foreign_message', index=59, + number=72, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_nested_enum', index=60, + number=73, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_foreign_enum', index=61, + number=74, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_uint32', index=62, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_nested_message', index=63, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_string', index=64, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_bytes', index=65, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_bool', index=66, + number=115, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_uint64', index=67, + number=116, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_float', index=68, + number=117, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_double', index=69, + number=118, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_enum', index=70, + number=119, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bool_wrapper', index=71, + number=201, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int32_wrapper', index=72, + number=202, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int64_wrapper', index=73, + number=203, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint32_wrapper', index=74, + number=204, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint64_wrapper', index=75, + number=205, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_float_wrapper', index=76, + number=206, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_double_wrapper', index=77, + number=207, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_string_wrapper', index=78, + number=208, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bytes_wrapper', index=79, + number=209, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bool_wrapper', index=80, + number=211, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int32_wrapper', index=81, + number=212, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int64_wrapper', index=82, + number=213, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint32_wrapper', index=83, + number=214, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint64_wrapper', index=84, + number=215, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_float_wrapper', index=85, + number=216, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_double_wrapper', index=86, + number=217, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_string_wrapper', index=87, + number=218, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bytes_wrapper', index=88, + number=219, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_duration', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_duration', index=89, + number=301, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_timestamp', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_timestamp', index=90, + number=302, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_field_mask', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_field_mask', index=91, + number=303, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_struct', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_struct', index=92, + number=304, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_any', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_any', index=93, + number=305, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_value', index=94, + number=306, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_duration', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_duration', index=95, + number=311, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_timestamp', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_timestamp', index=96, + number=312, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fieldmask', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_fieldmask', index=97, + number=313, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_struct', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_struct', index=98, + number=324, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_any', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_any', index=99, + number=315, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_value', index=100, + number=316, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldname1', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.fieldname1', index=101, + number=401, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name2', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_name2', index=102, + number=402, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='_field_name3', full_name='protobuf_test_messages.proto3.TestAllTypesProto3._field_name3', index=103, + number=403, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name4_', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field__name4_', index=104, + number=404, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field0name5', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field0name5', index=105, + number=405, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_0_name6', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_0_name6', index=106, + number=406, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldName7', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.fieldName7', index=107, + number=407, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FieldName8', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.FieldName8', index=108, + number=408, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_Name9', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_Name9', index=109, + number=409, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_Name10', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.Field_Name10', index=110, + number=410, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_NAME11', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.FIELD_NAME11', index=111, + number=411, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_name12', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.FIELD_name12', index=112, + number=412, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__field_name13', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.__field_name13', index=113, + number=413, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__Field_name14', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.__Field_name14', index=114, + number=414, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name15', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field__name15', index=115, + number=415, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__Name16', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field__Name16', index=116, + number=416, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name17__', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_name17__', index=117, + number=417, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_name18__', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.Field_name18__', index=118, + number=418, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPESPROTO3_NESTEDMESSAGE, _TESTALLTYPESPROTO3_MAPINT32INT32ENTRY, _TESTALLTYPESPROTO3_MAPINT64INT64ENTRY, _TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY, _TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY, _TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY, _TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY, _TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY, _TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY, _TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY, _TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY, _TESTALLTYPESPROTO3_MAPINT32FLOATENTRY, _TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY, _TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY, _TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY, _TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY, _TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY, _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY, _TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY, _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY, ], + enum_types=[ + _TESTALLTYPESPROTO3_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=266, + serialized_end=7870, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='protobuf_test_messages.proto3.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_test_messages.proto3.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7872, + serialized_end=7899, +) + +_TESTALLTYPESPROTO3_NESTEDMESSAGE.fields_by_name['corecursive'].message_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_NESTEDMESSAGE.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT32INT32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT64INT64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT32FLOATENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY.fields_by_name['value'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = _FOREIGNMESSAGE +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY.fields_by_name['value'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY.fields_by_name['value'].enum_type = _FOREIGNENUM +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPESPROTO3.fields_by_name['recursive_message'].message_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPESPROTO3.fields_by_name['map_int32_int32'].message_type = _TESTALLTYPESPROTO3_MAPINT32INT32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_int64_int64'].message_type = _TESTALLTYPESPROTO3_MAPINT64INT64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_uint32_uint32'].message_type = _TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_uint64_uint64'].message_type = _TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sint32_sint32'].message_type = _TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sint64_sint64'].message_type = _TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_fixed32_fixed32'].message_type = _TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_fixed64_fixed64'].message_type = _TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_int32_float'].message_type = _TESTALLTYPESPROTO3_MAPINT32FLOATENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_int32_double'].message_type = _TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_bool_bool'].message_type = _TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_string'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_bytes'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_nested_message'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_foreign_message'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_nested_enum'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_foreign_enum'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY +_TESTALLTYPESPROTO3.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['oneof_enum'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3.fields_by_name['optional_bool_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_int32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_int64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_uint32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_uint64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_float_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_double_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_string_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_bytes_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_bool_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_int32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_int64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_uint32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_uint64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_float_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_double_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_string_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_bytes_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_duration'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTALLTYPESPROTO3.fields_by_name['optional_timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTALLTYPESPROTO3.fields_by_name['optional_field_mask'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTALLTYPESPROTO3.fields_by_name['optional_struct'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTALLTYPESPROTO3.fields_by_name['optional_any'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTALLTYPESPROTO3.fields_by_name['optional_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_duration'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTALLTYPESPROTO3.fields_by_name['repeated_timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTALLTYPESPROTO3.fields_by_name['repeated_fieldmask'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTALLTYPESPROTO3.fields_by_name['repeated_struct'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTALLTYPESPROTO3.fields_by_name['repeated_any'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTALLTYPESPROTO3.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTALLTYPESPROTO3_NESTEDENUM.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_uint32']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_nested_message']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_string']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_bytes']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_bool']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_bool'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_uint64']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_uint64'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_float']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_float'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_double']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_double'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_enum']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_enum'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +DESCRIPTOR.message_types_by_name['TestAllTypesProto3'] = _TESTALLTYPESPROTO3 +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypesProto3 = _reflection.GeneratedProtocolMessageType('TestAllTypesProto3', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_NESTEDMESSAGE, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage) + )) + , + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry) + )) + , + + MapStringBytesEntry = _reflection.GeneratedProtocolMessageType('MapStringBytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry) + )) + , + + MapStringNestedMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry) + )) + , + + MapStringForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry) + )) + , + + MapStringNestedEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry) + )) + , + + MapStringForeignEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry) + )) + , + DESCRIPTOR = _TESTALLTYPESPROTO3, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3) + )) +_sym_db.RegisterMessage(TestAllTypesProto3) +_sym_db.RegisterMessage(TestAllTypesProto3.NestedMessage) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringStringEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringBytesEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringNestedMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringForeignMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringNestedEnumEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringForeignEnumEntry) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + + +DESCRIPTOR._options = None +_TESTALLTYPESPROTO3_MAPINT32INT32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPINT64INT64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPINT32FLOATENTRY._options = None +_TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY._options = None +_TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY._options = None +_TESTALLTYPESPROTO3.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPESPROTO3.fields_by_name['optional_cord']._options = None +_TESTALLTYPESPROTO3.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPESPROTO3.fields_by_name['repeated_cord']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/text_encoding.py b/winvenv/Lib/site-packages/google/protobuf/text_encoding.py new file mode 100644 index 0000000..9899563 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/text_encoding.py @@ -0,0 +1,107 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Encoding related utilities.""" +import re + +import six + +# Lookup table for utf8 +_cescape_utf8_to_str = [chr(i) for i in range(0, 256)] +_cescape_utf8_to_str[9] = r'\t' # optional escape +_cescape_utf8_to_str[10] = r'\n' # optional escape +_cescape_utf8_to_str[13] = r'\r' # optional escape +_cescape_utf8_to_str[39] = r"\'" # optional escape + +_cescape_utf8_to_str[34] = r'\"' # necessary escape +_cescape_utf8_to_str[92] = r'\\' # necessary escape + +# Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32) +_cescape_byte_to_str = ([r'\%03o' % i for i in range(0, 32)] + + [chr(i) for i in range(32, 127)] + + [r'\%03o' % i for i in range(127, 256)]) +_cescape_byte_to_str[9] = r'\t' # optional escape +_cescape_byte_to_str[10] = r'\n' # optional escape +_cescape_byte_to_str[13] = r'\r' # optional escape +_cescape_byte_to_str[39] = r"\'" # optional escape + +_cescape_byte_to_str[34] = r'\"' # necessary escape +_cescape_byte_to_str[92] = r'\\' # necessary escape + + +def CEscape(text, as_utf8): + """Escape a bytes string for use in an ascii protocol buffer. + + text.encode('string_escape') does not seem to satisfy our needs as it + encodes unprintable characters using two-digit hex escapes whereas our + C++ unescaping function allows hex escapes to be any length. So, + "\0011".encode('string_escape') ends up being "\\x011", which will be + decoded in C++ as a single-character string with char code 0x11. + + Args: + text: A byte string to be escaped + as_utf8: Specifies if result should be returned in UTF-8 encoding + Returns: + Escaped string + """ + # PY3 hack: make Ord work for str and bytes: + # //platforms/networking/data uses unicode here, hence basestring. + Ord = ord if isinstance(text, six.string_types) else lambda x: x + if as_utf8: + return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text) + return ''.join(_cescape_byte_to_str[Ord(c)] for c in text) + + +_CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])') +_cescape_highbit_to_str = ([chr(i) for i in range(0, 127)] + + [r'\%03o' % i for i in range(127, 256)]) + + +def CUnescape(text): + """Unescape a text string with C-style escape sequences to UTF-8 bytes.""" + + def ReplaceHex(m): + # Only replace the match if the number of leading back slashes is odd. i.e. + # the slash itself is not escaped. + if len(m.group(1)) & 1: + return m.group(1) + 'x0' + m.group(2) + return m.group(0) + + # This is required because the 'string_escape' encoding doesn't + # allow single-digit hex escapes (like '\xf'). + result = _CUNESCAPE_HEX.sub(ReplaceHex, text) + + if str is bytes: # PY2 + return result.decode('string_escape') + result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result) + return (result.encode('ascii') # Make it bytes to allow decode. + .decode('unicode_escape') + # Make it bytes again to return the proper type. + .encode('raw_unicode_escape')) diff --git a/winvenv/Lib/site-packages/google/protobuf/text_format.py b/winvenv/Lib/site-packages/google/protobuf/text_format.py new file mode 100644 index 0000000..2cbd21b --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/text_format.py @@ -0,0 +1,1593 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains routines for printing protocol messages in text format. + +Simple usage example: + + # Create a proto object and serialize it to a text proto string. + message = my_proto_pb2.MyMessage(foo='bar') + text_proto = text_format.MessageToString(message) + + # Parse a text proto string. + message = text_format.Parse(text_proto, my_proto_pb2.MyMessage()) +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import io +import re + +import six + +if six.PY3: + long = int # pylint: disable=redefined-builtin,invalid-name + +# pylint: disable=g-import-not-at-top +from google.protobuf.internal import type_checkers +from google.protobuf import descriptor +from google.protobuf import text_encoding + +__all__ = ['MessageToString', 'PrintMessage', 'PrintField', 'PrintFieldValue', + 'Merge'] + +_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(), + type_checkers.Int32ValueChecker(), + type_checkers.Uint64ValueChecker(), + type_checkers.Int64ValueChecker()) +_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE) +_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE) +_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, + descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) +_QUOTES = frozenset(("'", '"')) +_ANY_FULL_TYPE_NAME = 'google.protobuf.Any' + + +class Error(Exception): + """Top-level module error for text_format.""" + + +class ParseError(Error): + """Thrown in case of text parsing or tokenizing error.""" + + def __init__(self, message=None, line=None, column=None): + if message is not None and line is not None: + loc = str(line) + if column is not None: + loc += ':{0}'.format(column) + message = '{0} : {1}'.format(loc, message) + if message is not None: + super(ParseError, self).__init__(message) + else: + super(ParseError, self).__init__() + self._line = line + self._column = column + + def GetLine(self): + return self._line + + def GetColumn(self): + return self._column + + +class TextWriter(object): + + def __init__(self, as_utf8): + if six.PY2: + self._writer = io.BytesIO() + else: + self._writer = io.StringIO() + + def write(self, val): + if six.PY2: + if isinstance(val, six.text_type): + val = val.encode('utf-8') + return self._writer.write(val) + + def close(self): + return self._writer.close() + + def getvalue(self): + return self._writer.getvalue() + + +def MessageToString(message, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + use_field_number=False, + descriptor_pool=None, + indent=0, + message_formatter=None): + """Convert protobuf message to text format. + + Floating point values can be formatted compactly with 15 digits of + precision (which is the most that IEEE 754 "double" can guarantee) + using float_format='.15g'. To ensure that converting to text and back to a + proto will result in an identical value, float_format='.17g' should be used. + + Args: + message: The protocol buffers message. + as_utf8: Produce text output in UTF8 format. + as_one_line: Don't introduce newlines between fields. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, fields of a proto message will be printed using + the order defined in source code instead of the field number, extensions + will be printed at the end of the message and their relative order is + determined by the extension number. By default, use the field number + order. + float_format: If set, use this to specify floating point number formatting + (per the "Format Specification Mini-Language"); otherwise, str() is used. + use_field_number: If True, print field numbers instead of names. + descriptor_pool: A DescriptorPool used to resolve Any types. + indent: The indent level, in terms of spaces, for pretty print. + message_formatter: A function(message, indent, as_one_line): unicode|None + to custom format selected sub-messages (usually based on message type). + Use to pretty print parts of the protobuf for easier diffing. + + Returns: + A string of the text formatted protocol buffer message. + """ + out = TextWriter(as_utf8) + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, use_field_number, + descriptor_pool, message_formatter) + printer.PrintMessage(message) + result = out.getvalue() + out.close() + if as_one_line: + return result.rstrip() + return result + + +def _IsMapEntry(field): + return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) + + +def PrintMessage(message, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None): + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, use_field_number, + descriptor_pool, message_formatter) + printer.PrintMessage(message) + + +def PrintField(field, + value, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + message_formatter=None): + """Print a single field name/value pair.""" + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, message_formatter) + printer.PrintField(field, value) + + +def PrintFieldValue(field, + value, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + message_formatter=None): + """Print a single field value (not including name).""" + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, message_formatter) + printer.PrintFieldValue(field, value) + + +def _BuildMessageFromTypeName(type_name, descriptor_pool): + """Returns a protobuf message instance. + + Args: + type_name: Fully-qualified protobuf message type name string. + descriptor_pool: DescriptorPool instance. + + Returns: + A Message instance of type matching type_name, or None if the a Descriptor + wasn't found matching type_name. + """ + # pylint: disable=g-import-not-at-top + if descriptor_pool is None: + from google.protobuf import descriptor_pool as pool_mod + descriptor_pool = pool_mod.Default() + from google.protobuf import symbol_database + database = symbol_database.Default() + try: + message_descriptor = descriptor_pool.FindMessageTypeByName(type_name) + except KeyError: + return None + message_type = database.GetPrototype(message_descriptor) + return message_type() + + +class _Printer(object): + """Text format printer for protocol message.""" + + def __init__(self, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None): + """Initialize the Printer. + + Floating point values can be formatted compactly with 15 digits of + precision (which is the most that IEEE 754 "double" can guarantee) + using float_format='.15g'. To ensure that converting to text and back to a + proto will result in an identical value, float_format='.17g' should be used. + + Args: + out: To record the text format result. + indent: The indent level for pretty print. + as_utf8: Produce text output in UTF8 format. + as_one_line: Don't introduce newlines between fields. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, print fields of a proto message using the order + defined in source code instead of the field number. By default, use the + field number order. + float_format: If set, use this to specify floating point number formatting + (per the "Format Specification Mini-Language"); otherwise, str() is + used. + use_field_number: If True, print field numbers instead of names. + descriptor_pool: A DescriptorPool used to resolve Any types. + message_formatter: A function(message, indent, as_one_line): unicode|None + to custom format selected sub-messages (usually based on message type). + Use to pretty print parts of the protobuf for easier diffing. + """ + self.out = out + self.indent = indent + self.as_utf8 = as_utf8 + self.as_one_line = as_one_line + self.pointy_brackets = pointy_brackets + self.use_index_order = use_index_order + self.float_format = float_format + self.use_field_number = use_field_number + self.descriptor_pool = descriptor_pool + self.message_formatter = message_formatter + + def _TryPrintAsAnyMessage(self, message): + """Serializes if message is a google.protobuf.Any field.""" + packed_message = _BuildMessageFromTypeName(message.TypeName(), + self.descriptor_pool) + if packed_message: + packed_message.MergeFromString(message.value) + self.out.write('%s[%s]' % (self.indent * ' ', message.type_url)) + self._PrintMessageFieldValue(packed_message) + self.out.write(' ' if self.as_one_line else '\n') + return True + else: + return False + + def _TryCustomFormatMessage(self, message): + formatted = self.message_formatter(message, self.indent, self.as_one_line) + if formatted is None: + return False + + out = self.out + out.write(' ' * self.indent) + out.write(formatted) + out.write(' ' if self.as_one_line else '\n') + return True + + def PrintMessage(self, message): + """Convert protobuf message to text format. + + Args: + message: The protocol buffers message. + """ + if self.message_formatter and self._TryCustomFormatMessage(message): + return + if (message.DESCRIPTOR.full_name == _ANY_FULL_TYPE_NAME and + self._TryPrintAsAnyMessage(message)): + return + fields = message.ListFields() + if self.use_index_order: + fields.sort( + key=lambda x: x[0].number if x[0].is_extension else x[0].index) + for field, value in fields: + if _IsMapEntry(field): + for key in sorted(value): + # This is slow for maps with submessage entries because it copies the + # entire tree. Unfortunately this would take significant refactoring + # of this file to work around. + # + # TODO(haberman): refactor and optimize if this becomes an issue. + entry_submsg = value.GetEntryClass()(key=key, value=value[key]) + self.PrintField(field, entry_submsg) + elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + for element in value: + self.PrintField(field, element) + else: + self.PrintField(field, value) + + def PrintField(self, field, value): + """Print a single field name/value pair.""" + out = self.out + out.write(' ' * self.indent) + if self.use_field_number: + out.write(str(field.number)) + else: + if field.is_extension: + out.write('[') + if (field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): + out.write(field.message_type.full_name) + else: + out.write(field.full_name) + out.write(']') + elif field.type == descriptor.FieldDescriptor.TYPE_GROUP: + # For groups, use the capitalized name. + out.write(field.message_type.name) + else: + out.write(field.name) + + if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + # The colon is optional in this case, but our cross-language golden files + # don't include it. + out.write(': ') + + self.PrintFieldValue(field, value) + if self.as_one_line: + out.write(' ') + else: + out.write('\n') + + def _PrintMessageFieldValue(self, value): + if self.pointy_brackets: + openb = '<' + closeb = '>' + else: + openb = '{' + closeb = '}' + + if self.as_one_line: + self.out.write(' %s ' % openb) + self.PrintMessage(value) + self.out.write(closeb) + else: + self.out.write(' %s\n' % openb) + self.indent += 2 + self.PrintMessage(value) + self.indent -= 2 + self.out.write(' ' * self.indent + closeb) + + def PrintFieldValue(self, field, value): + """Print a single field value (not including name). + + For repeated fields, the value should be a single element. + + Args: + field: The descriptor of the field to be printed. + value: The value of the field. + """ + out = self.out + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + self._PrintMessageFieldValue(value) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: + enum_value = field.enum_type.values_by_number.get(value, None) + if enum_value is not None: + out.write(enum_value.name) + else: + out.write(str(value)) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: + out.write('\"') + if isinstance(value, six.text_type): + out_value = value.encode('utf-8') + else: + out_value = value + if field.type == descriptor.FieldDescriptor.TYPE_BYTES: + # We need to escape non-UTF8 chars in TYPE_BYTES field. + out_as_utf8 = False + else: + out_as_utf8 = self.as_utf8 + out.write(text_encoding.CEscape(out_value, out_as_utf8)) + out.write('\"') + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: + if value: + out.write('true') + else: + out.write('false') + elif field.cpp_type in _FLOAT_TYPES and self.float_format is not None: + out.write('{1:{0}}'.format(self.float_format, value)) + else: + out.write(str(value)) + + +def Parse(text, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + NOTE: for historical reasons this function does not clear the input + message. This is different from what the binary msg.ParseFrom(...) does. + + Example + a = MyProto() + a.repeated_field.append('test') + b = MyProto() + + text_format.Parse(repr(a), b) + text_format.Parse(repr(a), b) # repeated_field contains ["test", "test"] + + # Binary version: + b.ParseFromString(a.SerializeToString()) # repeated_field is now "test" + + Caller is responsible for clearing the message as needed. + + Args: + text: Message text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + if not isinstance(text, str): + if six.PY3: + text = text.decode('utf-8') + else: + text = text.encode('utf-8') + return ParseLines(text.split('\n'), + message, + allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + + +def Merge(text, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + Like Parse(), but allows repeated values for a non-repeated field, and uses + the last one. + + Args: + text: Message text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + if not isinstance(text, str): + if six.PY3: + text = text.decode('utf-8') + else: + text = text.encode('utf-8') + return MergeLines( + text.split('\n'), + message, + allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + + +def ParseLines(lines, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + Args: + lines: An iterable of lines of a message's text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + parser = _Parser(allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + return parser.ParseLines(lines, message) + + +def MergeLines(lines, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + Args: + lines: An iterable of lines of a message's text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + parser = _Parser(allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + return parser.MergeLines(lines, message) + + +class _Parser(object): + """Text format parser for protocol message.""" + + def __init__(self, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + self.allow_unknown_extension = allow_unknown_extension + self.allow_field_number = allow_field_number + self.descriptor_pool = descriptor_pool + + def ParseFromString(self, text, message): + """Parses a text representation of a protocol message into a message.""" + if not isinstance(text, str): + text = text.decode('utf-8') + return self.ParseLines(text.split('\n'), message) + + def ParseLines(self, lines, message): + """Parses a text representation of a protocol message into a message.""" + self._allow_multiple_scalars = False + self._ParseOrMerge(lines, message) + return message + + def MergeFromString(self, text, message): + """Merges a text representation of a protocol message into a message.""" + return self._MergeLines(text.split('\n'), message) + + def MergeLines(self, lines, message): + """Merges a text representation of a protocol message into a message.""" + self._allow_multiple_scalars = True + self._ParseOrMerge(lines, message) + return message + + def _ParseOrMerge(self, lines, message): + """Converts a text representation of a protocol message into a message. + + Args: + lines: Lines of a message's text representation. + message: A protocol buffer message to merge into. + + Raises: + ParseError: On text parsing problems. + """ + tokenizer = Tokenizer(lines) + while not tokenizer.AtEnd(): + self._MergeField(tokenizer, message) + + def _MergeField(self, tokenizer, message): + """Merges a single protocol message field into a message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + message: A protocol message to record the data. + + Raises: + ParseError: In case of text parsing problems. + """ + message_descriptor = message.DESCRIPTOR + if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and + tokenizer.TryConsume('[')): + type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer) + tokenizer.Consume(']') + tokenizer.TryConsume(':') + if tokenizer.TryConsume('<'): + expanded_any_end_token = '>' + else: + tokenizer.Consume('{') + expanded_any_end_token = '}' + expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name, + self.descriptor_pool) + if not expanded_any_sub_message: + raise ParseError('Type %s not found in descriptor pool' % + packed_type_name) + while not tokenizer.TryConsume(expanded_any_end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % + (expanded_any_end_token,)) + self._MergeField(tokenizer, expanded_any_sub_message) + message.Pack(expanded_any_sub_message, + type_url_prefix=type_url_prefix) + return + + if tokenizer.TryConsume('['): + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + name = '.'.join(name) + + if not message_descriptor.is_extendable: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" does not have extensions.' % + message_descriptor.full_name) + # pylint: disable=protected-access + field = message.Extensions._FindExtensionByName(name) + # pylint: enable=protected-access + if not field: + if self.allow_unknown_extension: + field = None + else: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" not registered. ' + 'Did you import the _pb2 module which defines it? ' + 'If you are trying to place the extension in the MessageSet ' + 'field of another message that is in an Any or MessageSet field, ' + 'that message\'s _pb2 module must be imported as well' % name) + elif message_descriptor != field.containing_type: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" does not extend message type "%s".' % + (name, message_descriptor.full_name)) + + tokenizer.Consume(']') + + else: + name = tokenizer.ConsumeIdentifierOrNumber() + if self.allow_field_number and name.isdigit(): + number = ParseInteger(name, True, True) + field = message_descriptor.fields_by_number.get(number, None) + if not field and message_descriptor.is_extendable: + field = message.Extensions._FindExtensionByNumber(number) + else: + field = message_descriptor.fields_by_name.get(name, None) + + # Group names are expected to be capitalized as they appear in the + # .proto file, which actually matches their type names, not their field + # names. + if not field: + field = message_descriptor.fields_by_name.get(name.lower(), None) + if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP: + field = None + + if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and + field.message_type.name != name): + field = None + + if not field: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" has no field named "%s".' % + (message_descriptor.full_name, name)) + + if field: + if not self._allow_multiple_scalars and field.containing_oneof: + # Check if there's a different field set in this oneof. + # Note that we ignore the case if the same field was set before, and we + # apply _allow_multiple_scalars to non-scalar fields as well. + which_oneof = message.WhichOneof(field.containing_oneof.name) + if which_oneof is not None and which_oneof != field.name: + raise tokenizer.ParseErrorPreviousToken( + 'Field "%s" is specified along with field "%s", another member ' + 'of oneof "%s" for message type "%s".' % + (field.name, which_oneof, field.containing_oneof.name, + message_descriptor.full_name)) + + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + tokenizer.TryConsume(':') + merger = self._MergeMessageField + else: + tokenizer.Consume(':') + merger = self._MergeScalarField + + if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and + tokenizer.TryConsume('[')): + # Short repeated format, e.g. "foo: [1, 2, 3]" + if not tokenizer.TryConsume(']'): + while True: + merger(tokenizer, message, field) + if tokenizer.TryConsume(']'): + break + tokenizer.Consume(',') + + else: + merger(tokenizer, message, field) + + else: # Proto field is unknown. + assert self.allow_unknown_extension + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + def _ConsumeAnyTypeUrl(self, tokenizer): + """Consumes a google.protobuf.Any type URL and returns the type name.""" + # Consume "type.googleapis.com/". + prefix = [tokenizer.ConsumeIdentifier()] + tokenizer.Consume('.') + prefix.append(tokenizer.ConsumeIdentifier()) + tokenizer.Consume('.') + prefix.append(tokenizer.ConsumeIdentifier()) + tokenizer.Consume('/') + # Consume the fully-qualified type name. + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + return '.'.join(prefix), '.'.join(name) + + def _MergeMessageField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: The message of which field is a member. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + """ + is_map_entry = _IsMapEntry(field) + + if tokenizer.TryConsume('<'): + end_token = '>' + else: + tokenizer.Consume('{') + end_token = '}' + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + sub_message = message.Extensions[field].add() + elif is_map_entry: + sub_message = getattr(message, field.name).GetEntryClass()() + else: + sub_message = getattr(message, field.name).add() + else: + if field.is_extension: + if (not self._allow_multiple_scalars and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + sub_message = message.Extensions[field] + else: + # Also apply _allow_multiple_scalars to message field. + # TODO(jieluo): Change to _allow_singular_overwrites. + if (not self._allow_multiple_scalars and + message.HasField(field.name)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + sub_message = getattr(message, field.name) + sub_message.SetInParent() + + while not tokenizer.TryConsume(end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,)) + self._MergeField(tokenizer, sub_message) + + if is_map_entry: + value_cpptype = field.message_type.fields_by_name['value'].cpp_type + if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + value = getattr(message, field.name)[sub_message.key] + value.MergeFrom(sub_message.value) + else: + getattr(message, field.name)[sub_message.key] = sub_message.value + + @staticmethod + def _IsProto3Syntax(message): + message_descriptor = message.DESCRIPTOR + return (hasattr(message_descriptor, 'syntax') and + message_descriptor.syntax == 'proto3') + + def _MergeScalarField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: A protocol message to record the data. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + RuntimeError: On runtime errors. + """ + _ = self.allow_unknown_extension + value = None + + if field.type in (descriptor.FieldDescriptor.TYPE_INT32, + descriptor.FieldDescriptor.TYPE_SINT32, + descriptor.FieldDescriptor.TYPE_SFIXED32): + value = _ConsumeInt32(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_INT64, + descriptor.FieldDescriptor.TYPE_SINT64, + descriptor.FieldDescriptor.TYPE_SFIXED64): + value = _ConsumeInt64(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32, + descriptor.FieldDescriptor.TYPE_FIXED32): + value = _ConsumeUint32(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64, + descriptor.FieldDescriptor.TYPE_FIXED64): + value = _ConsumeUint64(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT, + descriptor.FieldDescriptor.TYPE_DOUBLE): + value = tokenizer.ConsumeFloat() + elif field.type == descriptor.FieldDescriptor.TYPE_BOOL: + value = tokenizer.ConsumeBool() + elif field.type == descriptor.FieldDescriptor.TYPE_STRING: + value = tokenizer.ConsumeString() + elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: + value = tokenizer.ConsumeByteString() + elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: + value = tokenizer.ConsumeEnum(field) + else: + raise RuntimeError('Unknown field type %d' % field.type) + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + message.Extensions[field].append(value) + else: + getattr(message, field.name).append(value) + else: + # Proto3 doesn't represent presence so we can't test if multiple scalars + # have occurred. We have to allow them. + can_check_presence = not self._IsProto3Syntax(message) + if field.is_extension: + if (not self._allow_multiple_scalars and can_check_presence and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + else: + message.Extensions[field] = value + else: + if (not self._allow_multiple_scalars and can_check_presence and + message.HasField(field.name)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + else: + setattr(message, field.name, value) + + +def _SkipFieldContents(tokenizer): + """Skips over contents (value or message) of a field. + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + # Try to guess the type of this field. + # If this field is not a message, there should be a ":" between the + # field name and the field value and also the field value should not + # start with "{" or "<" which indicates the beginning of a message body. + # If there is no ":" or there is a "{" or "<" after ":", this field has + # to be a message or the input is ill-formed. + if tokenizer.TryConsume(':') and not tokenizer.LookingAt( + '{') and not tokenizer.LookingAt('<'): + _SkipFieldValue(tokenizer) + else: + _SkipFieldMessage(tokenizer) + + +def _SkipField(tokenizer): + """Skips over a complete field (name and value/message). + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + if tokenizer.TryConsume('['): + # Consume extension name. + tokenizer.ConsumeIdentifier() + while tokenizer.TryConsume('.'): + tokenizer.ConsumeIdentifier() + tokenizer.Consume(']') + else: + tokenizer.ConsumeIdentifierOrNumber() + + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + +def _SkipFieldMessage(tokenizer): + """Skips over a field message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + + if tokenizer.TryConsume('<'): + delimiter = '>' + else: + tokenizer.Consume('{') + delimiter = '}' + + while not tokenizer.LookingAt('>') and not tokenizer.LookingAt('}'): + _SkipField(tokenizer) + + tokenizer.Consume(delimiter) + + +def _SkipFieldValue(tokenizer): + """Skips over a field value. + + Args: + tokenizer: A tokenizer to parse the field name and values. + + Raises: + ParseError: In case an invalid field value is found. + """ + # String/bytes tokens can come in multiple adjacent string literals. + # If we can consume one, consume as many as we can. + if tokenizer.TryConsumeByteString(): + while tokenizer.TryConsumeByteString(): + pass + return + + if (not tokenizer.TryConsumeIdentifier() and + not _TryConsumeInt64(tokenizer) and not _TryConsumeUint64(tokenizer) and + not tokenizer.TryConsumeFloat()): + raise ParseError('Invalid field value: ' + tokenizer.token) + + +class Tokenizer(object): + """Protocol buffer text representation tokenizer. + + This class handles the lower level string parsing by splitting it into + meaningful tokens. + + It was directly ported from the Java protocol buffer API. + """ + + _WHITESPACE = re.compile(r'\s+') + _COMMENT = re.compile(r'(\s*#.*$)', re.MULTILINE) + _WHITESPACE_OR_COMMENT = re.compile(r'(\s|(#.*$))+', re.MULTILINE) + _TOKEN = re.compile('|'.join([ + r'[a-zA-Z_][0-9a-zA-Z_+-]*', # an identifier + r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*', # a number + ] + [ # quoted str for each quote mark + r'{qt}([^{qt}\n\\]|\\.)*({qt}|\\?$)'.format(qt=mark) for mark in _QUOTES + ])) + + _IDENTIFIER = re.compile(r'[^\d\W]\w*') + _IDENTIFIER_OR_NUMBER = re.compile(r'\w+') + + def __init__(self, lines, skip_comments=True): + self._position = 0 + self._line = -1 + self._column = 0 + self._token_start = None + self.token = '' + self._lines = iter(lines) + self._current_line = '' + self._previous_line = 0 + self._previous_column = 0 + self._more_lines = True + self._skip_comments = skip_comments + self._whitespace_pattern = (skip_comments and self._WHITESPACE_OR_COMMENT + or self._WHITESPACE) + self._SkipWhitespace() + self.NextToken() + + def LookingAt(self, token): + return self.token == token + + def AtEnd(self): + """Checks the end of the text was reached. + + Returns: + True iff the end was reached. + """ + return not self.token + + def _PopLine(self): + while len(self._current_line) <= self._column: + try: + self._current_line = next(self._lines) + except StopIteration: + self._current_line = '' + self._more_lines = False + return + else: + self._line += 1 + self._column = 0 + + def _SkipWhitespace(self): + while True: + self._PopLine() + match = self._whitespace_pattern.match(self._current_line, self._column) + if not match: + break + length = len(match.group(0)) + self._column += length + + def TryConsume(self, token): + """Tries to consume a given piece of text. + + Args: + token: Text to consume. + + Returns: + True iff the text was consumed. + """ + if self.token == token: + self.NextToken() + return True + return False + + def Consume(self, token): + """Consumes a piece of text. + + Args: + token: Text to consume. + + Raises: + ParseError: If the text couldn't be consumed. + """ + if not self.TryConsume(token): + raise self.ParseError('Expected "%s".' % token) + + def ConsumeComment(self): + result = self.token + if not self._COMMENT.match(result): + raise self.ParseError('Expected comment.') + self.NextToken() + return result + + def ConsumeCommentOrTrailingComment(self): + """Consumes a comment, returns a 2-tuple (trailing bool, comment str).""" + + # Tokenizer initializes _previous_line and _previous_column to 0. As the + # tokenizer starts, it looks like there is a previous token on the line. + just_started = self._line == 0 and self._column == 0 + + before_parsing = self._previous_line + comment = self.ConsumeComment() + + # A trailing comment is a comment on the same line than the previous token. + trailing = (self._previous_line == before_parsing + and not just_started) + + return trailing, comment + + def TryConsumeIdentifier(self): + try: + self.ConsumeIdentifier() + return True + except ParseError: + return False + + def ConsumeIdentifier(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not self._IDENTIFIER.match(result): + raise self.ParseError('Expected identifier.') + self.NextToken() + return result + + def TryConsumeIdentifierOrNumber(self): + try: + self.ConsumeIdentifierOrNumber() + return True + except ParseError: + return False + + def ConsumeIdentifierOrNumber(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not self._IDENTIFIER_OR_NUMBER.match(result): + raise self.ParseError('Expected identifier or number, got %s.' % result) + self.NextToken() + return result + + def TryConsumeInteger(self): + try: + # Note: is_long only affects value type, not whether an error is raised. + self.ConsumeInteger() + return True + except ParseError: + return False + + def ConsumeInteger(self, is_long=False): + """Consumes an integer number. + + Args: + is_long: True if the value should be returned as a long integer. + Returns: + The integer parsed. + + Raises: + ParseError: If an integer couldn't be consumed. + """ + try: + result = _ParseAbstractInteger(self.token, is_long=is_long) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def TryConsumeFloat(self): + try: + self.ConsumeFloat() + return True + except ParseError: + return False + + def ConsumeFloat(self): + """Consumes an floating point number. + + Returns: + The number parsed. + + Raises: + ParseError: If a floating point number couldn't be consumed. + """ + try: + result = ParseFloat(self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ConsumeBool(self): + """Consumes a boolean value. + + Returns: + The bool parsed. + + Raises: + ParseError: If a boolean value couldn't be consumed. + """ + try: + result = ParseBool(self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def TryConsumeByteString(self): + try: + self.ConsumeByteString() + return True + except ParseError: + return False + + def ConsumeString(self): + """Consumes a string value. + + Returns: + The string parsed. + + Raises: + ParseError: If a string value couldn't be consumed. + """ + the_bytes = self.ConsumeByteString() + try: + return six.text_type(the_bytes, 'utf-8') + except UnicodeDecodeError as e: + raise self._StringParseError(e) + + def ConsumeByteString(self): + """Consumes a byte array value. + + Returns: + The array parsed (as a string). + + Raises: + ParseError: If a byte array value couldn't be consumed. + """ + the_list = [self._ConsumeSingleByteString()] + while self.token and self.token[0] in _QUOTES: + the_list.append(self._ConsumeSingleByteString()) + return b''.join(the_list) + + def _ConsumeSingleByteString(self): + """Consume one token of a string literal. + + String literals (whether bytes or text) can come in multiple adjacent + tokens which are automatically concatenated, like in C or Python. This + method only consumes one token. + + Returns: + The token parsed. + Raises: + ParseError: When the wrong format data is found. + """ + text = self.token + if len(text) < 1 or text[0] not in _QUOTES: + raise self.ParseError('Expected string but found: %r' % (text,)) + + if len(text) < 2 or text[-1] != text[0]: + raise self.ParseError('String missing ending quote: %r' % (text,)) + + try: + result = text_encoding.CUnescape(text[1:-1]) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ConsumeEnum(self, field): + try: + result = ParseEnum(field, self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ParseErrorPreviousToken(self, message): + """Creates and *returns* a ParseError for the previously read token. + + Args: + message: A message to set for the exception. + + Returns: + A ParseError instance. + """ + return ParseError(message, self._previous_line + 1, + self._previous_column + 1) + + def ParseError(self, message): + """Creates and *returns* a ParseError for the current token.""" + return ParseError(message, self._line + 1, self._column + 1) + + def _StringParseError(self, e): + return self.ParseError('Couldn\'t parse string: ' + str(e)) + + def NextToken(self): + """Reads the next meaningful token.""" + self._previous_line = self._line + self._previous_column = self._column + + self._column += len(self.token) + self._SkipWhitespace() + + if not self._more_lines: + self.token = '' + return + + match = self._TOKEN.match(self._current_line, self._column) + if not match and not self._skip_comments: + match = self._COMMENT.match(self._current_line, self._column) + if match: + token = match.group(0) + self.token = token + else: + self.token = self._current_line[self._column] + +# Aliased so it can still be accessed by current visibility violators. +# TODO(dbarnett): Migrate violators to textformat_tokenizer. +_Tokenizer = Tokenizer # pylint: disable=invalid-name + + +def _ConsumeInt32(tokenizer): + """Consumes a signed 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=True, is_long=False) + + +def _ConsumeUint32(tokenizer): + """Consumes an unsigned 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=False, is_long=False) + + +def _TryConsumeInt64(tokenizer): + try: + _ConsumeInt64(tokenizer) + return True + except ParseError: + return False + + +def _ConsumeInt64(tokenizer): + """Consumes a signed 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=True, is_long=True) + + +def _TryConsumeUint64(tokenizer): + try: + _ConsumeUint64(tokenizer) + return True + except ParseError: + return False + + +def _ConsumeUint64(tokenizer): + """Consumes an unsigned 64bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 64bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=False, is_long=True) + + +def _TryConsumeInteger(tokenizer, is_signed=False, is_long=False): + try: + _ConsumeInteger(tokenizer, is_signed=is_signed, is_long=is_long) + return True + except ParseError: + return False + + +def _ConsumeInteger(tokenizer, is_signed=False, is_long=False): + """Consumes an integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer parsed. + + Raises: + ParseError: If an integer with given characteristics couldn't be consumed. + """ + try: + result = ParseInteger(tokenizer.token, is_signed=is_signed, is_long=is_long) + except ValueError as e: + raise tokenizer.ParseError(str(e)) + tokenizer.NextToken() + return result + + +def ParseInteger(text, is_signed=False, is_long=False): + """Parses an integer. + + Args: + text: The text to parse. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + result = _ParseAbstractInteger(text, is_long=is_long) + + # Check if the integer is sane. Exceptions handled by callers. + checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] + checker.CheckValue(result) + return result + + +def _ParseAbstractInteger(text, is_long=False): + """Parses an integer without checking size/signedness. + + Args: + text: The text to parse. + is_long: True if the value should be returned as a long integer. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + try: + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + if is_long: + return long(text, 0) + else: + return int(text, 0) + except ValueError: + raise ValueError('Couldn\'t parse integer: %s' % text) + + +def ParseFloat(text): + """Parse a floating point number. + + Args: + text: Text to parse. + + Returns: + The number parsed. + + Raises: + ValueError: If a floating point number couldn't be parsed. + """ + try: + # Assume Python compatible syntax. + return float(text) + except ValueError: + # Check alternative spellings. + if _FLOAT_INFINITY.match(text): + if text[0] == '-': + return float('-inf') + else: + return float('inf') + elif _FLOAT_NAN.match(text): + return float('nan') + else: + # assume '1.0f' format + try: + return float(text.rstrip('f')) + except ValueError: + raise ValueError('Couldn\'t parse float: %s' % text) + + +def ParseBool(text): + """Parse a boolean value. + + Args: + text: Text to parse. + + Returns: + Boolean values parsed + + Raises: + ValueError: If text is not a valid boolean. + """ + if text in ('true', 't', '1', 'True'): + return True + elif text in ('false', 'f', '0', 'False'): + return False + else: + raise ValueError('Expected "true" or "false".') + + +def ParseEnum(field, value): + """Parse an enum value. + + The value can be specified by a number (the enum value), or by + a string literal (the enum name). + + Args: + field: Enum field descriptor. + value: String value. + + Returns: + Enum value number. + + Raises: + ValueError: If the enum value could not be parsed. + """ + enum_descriptor = field.enum_type + try: + number = int(value, 0) + except ValueError: + # Identifier. + enum_value = enum_descriptor.values_by_name.get(value, None) + if enum_value is None: + raise ValueError('Enum type "%s" has no value named %s.' % + (enum_descriptor.full_name, value)) + else: + # Numeric value. + if hasattr(field.file, 'syntax'): + # Attribute is checked for compatibility. + if field.file.syntax == 'proto3': + # Proto3 accept numeric unknown enums. + return number + enum_value = enum_descriptor.values_by_number.get(number, None) + if enum_value is None: + raise ValueError('Enum type "%s" has no value with number %d.' % + (enum_descriptor.full_name, number)) + return enum_value.number diff --git a/winvenv/Lib/site-packages/google/protobuf/timestamp_pb2.py b/winvenv/Lib/site-packages/google/protobuf/timestamp_pb2.py new file mode 100644 index 0000000..eae6c2e --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/timestamp_pb2.py @@ -0,0 +1,77 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/timestamp.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/timestamp.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\016TimestampProtoP\001Z+github.com/golang/protobuf/ptypes/timestamp\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1fgoogle/protobuf/timestamp.proto\x12\x0fgoogle.protobuf\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x42~\n\x13\x63om.google.protobufB\x0eTimestampProtoP\x01Z+github.com/golang/protobuf/ptypes/timestamp\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_TIMESTAMP = _descriptor.Descriptor( + name='Timestamp', + full_name='google.protobuf.Timestamp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='seconds', full_name='google.protobuf.Timestamp.seconds', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nanos', full_name='google.protobuf.Timestamp.nanos', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=52, + serialized_end=95, +) + +DESCRIPTOR.message_types_by_name['Timestamp'] = _TIMESTAMP +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Timestamp = _reflection.GeneratedProtocolMessageType('Timestamp', (_message.Message,), dict( + DESCRIPTOR = _TIMESTAMP, + __module__ = 'google.protobuf.timestamp_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Timestamp) + )) +_sym_db.RegisterMessage(Timestamp) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/type_pb2.py b/winvenv/Lib/site-packages/google/protobuf/type_pb2.py new file mode 100644 index 0000000..edf78d9 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/type_pb2.py @@ -0,0 +1,540 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/type.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import source_context_pb2 as google_dot_protobuf_dot_source__context__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/type.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\tTypeProtoP\001Z/google.golang.org/genproto/protobuf/ptype;ptype\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1agoogle/protobuf/type.proto\x12\x0fgoogle.protobuf\x1a\x19google/protobuf/any.proto\x1a$google/protobuf/source_context.proto\"\xd7\x01\n\x04Type\x12\x0c\n\x04name\x18\x01 \x01(\t\x12&\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x16.google.protobuf.Field\x12\x0e\n\x06oneofs\x18\x03 \x03(\t\x12(\n\x07options\x18\x04 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x36\n\x0esource_context\x18\x05 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12\'\n\x06syntax\x18\x06 \x01(\x0e\x32\x17.google.protobuf.Syntax\"\xd5\x05\n\x05\x46ield\x12)\n\x04kind\x18\x01 \x01(\x0e\x32\x1b.google.protobuf.Field.Kind\x12\x37\n\x0b\x63\x61rdinality\x18\x02 \x01(\x0e\x32\".google.protobuf.Field.Cardinality\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x10\n\x08type_url\x18\x06 \x01(\t\x12\x13\n\x0boneof_index\x18\x07 \x01(\x05\x12\x0e\n\x06packed\x18\x08 \x01(\x08\x12(\n\x07options\x18\t \x03(\x0b\x32\x17.google.protobuf.Option\x12\x11\n\tjson_name\x18\n \x01(\t\x12\x15\n\rdefault_value\x18\x0b \x01(\t\"\xc8\x02\n\x04Kind\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"t\n\x0b\x43\x61rdinality\x12\x17\n\x13\x43\x41RDINALITY_UNKNOWN\x10\x00\x12\x18\n\x14\x43\x41RDINALITY_OPTIONAL\x10\x01\x12\x18\n\x14\x43\x41RDINALITY_REQUIRED\x10\x02\x12\x18\n\x14\x43\x41RDINALITY_REPEATED\x10\x03\"\xce\x01\n\x04\x45num\x12\x0c\n\x04name\x18\x01 \x01(\t\x12-\n\tenumvalue\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.EnumValue\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x36\n\x0esource_context\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12\'\n\x06syntax\x18\x05 \x01(\x0e\x32\x17.google.protobuf.Syntax\"S\n\tEnumValue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\";\n\x06Option\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.google.protobuf.Any*.\n\x06Syntax\x12\x11\n\rSYNTAX_PROTO2\x10\x00\x12\x11\n\rSYNTAX_PROTO3\x10\x01\x42}\n\x13\x63om.google.protobufB\tTypeProtoP\x01Z/google.golang.org/genproto/protobuf/ptype;ptype\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_source__context__pb2.DESCRIPTOR,]) + +_SYNTAX = _descriptor.EnumDescriptor( + name='Syntax', + full_name='google.protobuf.Syntax', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SYNTAX_PROTO2', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SYNTAX_PROTO3', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1413, + serialized_end=1459, +) +_sym_db.RegisterEnumDescriptor(_SYNTAX) + +Syntax = enum_type_wrapper.EnumTypeWrapper(_SYNTAX) +SYNTAX_PROTO2 = 0 +SYNTAX_PROTO3 = 1 + + +_FIELD_KIND = _descriptor.EnumDescriptor( + name='Kind', + full_name='google.protobuf.Field.Kind', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_DOUBLE', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FLOAT', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT64', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT64', index=4, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT32', index=5, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED64', index=6, number=6, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED32', index=7, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BOOL', index=8, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_STRING', index=9, number=9, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_GROUP', index=10, number=10, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_MESSAGE', index=11, number=11, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BYTES', index=12, number=12, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT32', index=13, number=13, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_ENUM', index=14, number=14, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED32', index=15, number=15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED64', index=16, number=16, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT32', index=17, number=17, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT64', index=18, number=18, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=610, + serialized_end=938, +) +_sym_db.RegisterEnumDescriptor(_FIELD_KIND) + +_FIELD_CARDINALITY = _descriptor.EnumDescriptor( + name='Cardinality', + full_name='google.protobuf.Field.Cardinality', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='CARDINALITY_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_OPTIONAL', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_REQUIRED', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_REPEATED', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=940, + serialized_end=1056, +) +_sym_db.RegisterEnumDescriptor(_FIELD_CARDINALITY) + + +_TYPE = _descriptor.Descriptor( + name='Type', + full_name='google.protobuf.Type', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Type.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fields', full_name='google.protobuf.Type.fields', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneofs', full_name='google.protobuf.Type.oneofs', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Type.options', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Type.source_context', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Type.syntax', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=328, +) + + +_FIELD = _descriptor.Descriptor( + name='Field', + full_name='google.protobuf.Field', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='kind', full_name='google.protobuf.Field.kind', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cardinality', full_name='google.protobuf.Field.cardinality', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.Field.number', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Field.name', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type_url', full_name='google.protobuf.Field.type_url', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_index', full_name='google.protobuf.Field.oneof_index', index=5, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed', full_name='google.protobuf.Field.packed', index=6, + number=8, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Field.options', index=7, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='json_name', full_name='google.protobuf.Field.json_name', index=8, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_value', full_name='google.protobuf.Field.default_value', index=9, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELD_KIND, + _FIELD_CARDINALITY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=331, + serialized_end=1056, +) + + +_ENUM = _descriptor.Descriptor( + name='Enum', + full_name='google.protobuf.Enum', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Enum.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enumvalue', full_name='google.protobuf.Enum.enumvalue', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Enum.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Enum.source_context', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Enum.syntax', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1059, + serialized_end=1265, +) + + +_ENUMVALUE = _descriptor.Descriptor( + name='EnumValue', + full_name='google.protobuf.EnumValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumValue.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.EnumValue.number', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumValue.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1267, + serialized_end=1350, +) + + +_OPTION = _descriptor.Descriptor( + name='Option', + full_name='google.protobuf.Option', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Option.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Option.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1352, + serialized_end=1411, +) + +_TYPE.fields_by_name['fields'].message_type = _FIELD +_TYPE.fields_by_name['options'].message_type = _OPTION +_TYPE.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_TYPE.fields_by_name['syntax'].enum_type = _SYNTAX +_FIELD.fields_by_name['kind'].enum_type = _FIELD_KIND +_FIELD.fields_by_name['cardinality'].enum_type = _FIELD_CARDINALITY +_FIELD.fields_by_name['options'].message_type = _OPTION +_FIELD_KIND.containing_type = _FIELD +_FIELD_CARDINALITY.containing_type = _FIELD +_ENUM.fields_by_name['enumvalue'].message_type = _ENUMVALUE +_ENUM.fields_by_name['options'].message_type = _OPTION +_ENUM.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_ENUM.fields_by_name['syntax'].enum_type = _SYNTAX +_ENUMVALUE.fields_by_name['options'].message_type = _OPTION +_OPTION.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +DESCRIPTOR.message_types_by_name['Type'] = _TYPE +DESCRIPTOR.message_types_by_name['Field'] = _FIELD +DESCRIPTOR.message_types_by_name['Enum'] = _ENUM +DESCRIPTOR.message_types_by_name['EnumValue'] = _ENUMVALUE +DESCRIPTOR.message_types_by_name['Option'] = _OPTION +DESCRIPTOR.enum_types_by_name['Syntax'] = _SYNTAX +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Type = _reflection.GeneratedProtocolMessageType('Type', (_message.Message,), dict( + DESCRIPTOR = _TYPE, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Type) + )) +_sym_db.RegisterMessage(Type) + +Field = _reflection.GeneratedProtocolMessageType('Field', (_message.Message,), dict( + DESCRIPTOR = _FIELD, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Field) + )) +_sym_db.RegisterMessage(Field) + +Enum = _reflection.GeneratedProtocolMessageType('Enum', (_message.Message,), dict( + DESCRIPTOR = _ENUM, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Enum) + )) +_sym_db.RegisterMessage(Enum) + +EnumValue = _reflection.GeneratedProtocolMessageType('EnumValue', (_message.Message,), dict( + DESCRIPTOR = _ENUMVALUE, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValue) + )) +_sym_db.RegisterMessage(EnumValue) + +Option = _reflection.GeneratedProtocolMessageType('Option', (_message.Message,), dict( + DESCRIPTOR = _OPTION, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Option) + )) +_sym_db.RegisterMessage(Option) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_arena_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_arena_pb2.py new file mode 100644 index 0000000..6ed8aec --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_arena_pb2.py @@ -0,0 +1,120 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_arena.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_no_arena_import_pb2 as google_dot_protobuf_dot_unittest__no__arena__import__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_arena.proto', + package='proto2_arena_unittest', + syntax='proto2', + serialized_options=_b('\370\001\001'), + serialized_pb=_b('\n$google/protobuf/unittest_arena.proto\x12\x15proto2_arena_unittest\x1a.google/protobuf/unittest_no_arena_import.proto\"\x1a\n\rNestedMessage\x12\t\n\x01\x64\x18\x01 \x01(\x05\"\xb2\x01\n\x0c\x41renaMessage\x12\x45\n\x17repeated_nested_message\x18\x01 \x03(\x0b\x32$.proto2_arena_unittest.NestedMessage\x12[\n repeated_import_no_arena_message\x18\x02 \x03(\x0b\x32\x31.proto2_arena_unittest.ImportNoArenaNestedMessageB\x03\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__no__arena__import__pb2.DESCRIPTOR,]) + + + + +_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='proto2_arena_unittest.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='proto2_arena_unittest.NestedMessage.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=111, + serialized_end=137, +) + + +_ARENAMESSAGE = _descriptor.Descriptor( + name='ArenaMessage', + full_name='proto2_arena_unittest.ArenaMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='proto2_arena_unittest.ArenaMessage.repeated_nested_message', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_no_arena_message', full_name='proto2_arena_unittest.ArenaMessage.repeated_import_no_arena_message', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=140, + serialized_end=318, +) + +_ARENAMESSAGE.fields_by_name['repeated_nested_message'].message_type = _NESTEDMESSAGE +_ARENAMESSAGE.fields_by_name['repeated_import_no_arena_message'].message_type = google_dot_protobuf_dot_unittest__no__arena__import__pb2._IMPORTNOARENANESTEDMESSAGE +DESCRIPTOR.message_types_by_name['NestedMessage'] = _NESTEDMESSAGE +DESCRIPTOR.message_types_by_name['ArenaMessage'] = _ARENAMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_arena_pb2' + # @@protoc_insertion_point(class_scope:proto2_arena_unittest.NestedMessage) + )) +_sym_db.RegisterMessage(NestedMessage) + +ArenaMessage = _reflection.GeneratedProtocolMessageType('ArenaMessage', (_message.Message,), dict( + DESCRIPTOR = _ARENAMESSAGE, + __module__ = 'google.protobuf.unittest_arena_pb2' + # @@protoc_insertion_point(class_scope:proto2_arena_unittest.ArenaMessage) + )) +_sym_db.RegisterMessage(ArenaMessage) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_custom_options_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_custom_options_pb2.py new file mode 100644 index 0000000..954cb27 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_custom_options_pb2.py @@ -0,0 +1,1845 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_custom_options.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import service as _service +from google.protobuf import service_reflection +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_custom_options.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=_b('\200\001\001\210\001\001\220\001\001\360\350\301\035\352\255\300\345$\372\354\205;p\010d\022\016FileAnnotation\032\026\022\024NestedFileAnnotation\"\036\372\354\205;\031\022\027FileExtensionAnnotation*$\013\020\366\353\256\007\032\033\n\031EmbeddedMessageSetElement\014'), + serialized_pb=_b('\n-google/protobuf/unittest_custom_options.proto\x12\x11protobuf_unittest\x1a google/protobuf/descriptor.proto\"\xbf\x01\n\x1cTestMessageWithCustomOptions\x12\x1e\n\x06\x66ield1\x18\x01 \x01(\tB\x0e\x08\x01\xc1\xe0\xc3\x1d-\xe1u\n\x02\x00\x00\x00\x12\x15\n\x0boneof_field\x18\x02 \x01(\x05H\x00\";\n\x06\x41nEnum\x12\x0f\n\x0b\x41NENUM_VAL1\x10\x01\x12\x16\n\x0b\x41NENUM_VAL2\x10\x02\x1a\x05\xb0\x86\xfa\x05{\x1a\x08\xc5\xf6\xc9\x1d\xeb\xfc\xff\xff:\x10\x08\x00\xe0\xe9\xc2\x1d\xc8\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\x19\n\x07\x41nOneof\x12\x0e\xf8\xac\xc3\x1d\x9d\xff\xff\xff\xff\xff\xff\xff\xff\x01\"\x18\n\x16\x43ustomOptionFooRequest\"\x19\n\x17\x43ustomOptionFooResponse\"\x1e\n\x1c\x43ustomOptionFooClientMessage\"\x1e\n\x1c\x43ustomOptionFooServerMessage\"m\n\x1a\x44ummyMessageContainingEnum\"O\n\x0cTestEnumType\x12\x1a\n\x16TEST_OPTION_ENUM_TYPE1\x10\x16\x12#\n\x16TEST_OPTION_ENUM_TYPE2\x10\xe9\xff\xff\xff\xff\xff\xff\xff\xff\x01\"!\n\x1f\x44ummyMessageInvalidAsOptionType\"\x8a\x01\n\x1c\x43ustomOptionMinIntegerValues:j\xd0\xde\xb2\x1d\x00\xe8\xc6\xb2\x1d\x80\x80\x80\x80\xf8\xff\xff\xff\xff\x01\xb0\xbc\xb2\x1d\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01\x80\x93\xb2\x1d\x00\xf8\xf5\xb0\x1d\x00\x80\xc4\xb0\x1d\xff\xff\xff\xff\x0f\xf8\x97\xb0\x1d\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x9d\xf5\xaf\x1d\x00\x00\x00\x00\x91\xee\xaf\x1d\x00\x00\x00\x00\x00\x00\x00\x00\xad\x8d\xaf\x1d\x00\x00\x00\x80\x99\xd6\xa8\x1d\x00\x00\x00\x00\x00\x00\x00\x80\"\x91\x01\n\x1c\x43ustomOptionMaxIntegerValues:q\xd0\xde\xb2\x1d\x01\xe8\xc6\xb2\x1d\xff\xff\xff\xff\x07\xb0\xbc\xb2\x1d\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x80\x93\xb2\x1d\xff\xff\xff\xff\x0f\xf8\xf5\xb0\x1d\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\xc4\xb0\x1d\xfe\xff\xff\xff\x0f\xf8\x97\xb0\x1d\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01\x9d\xf5\xaf\x1d\xff\xff\xff\xff\x91\xee\xaf\x1d\xff\xff\xff\xff\xff\xff\xff\xff\xad\x8d\xaf\x1d\xff\xff\xff\x7f\x99\xd6\xa8\x1d\xff\xff\xff\xff\xff\xff\xff\x7f\"n\n\x17\x43ustomOptionOtherValues:S\xe8\xc6\xb2\x1d\x9c\xff\xff\xff\xff\xff\xff\xff\xff\x01\xf5\xdf\xa3\x1d\xe7\x87\x45\x41\xe9\xdc\xa2\x1d\xfbY\x8c\x42\xca\xc0\xf3?\xaa\xdc\xa2\x1d\x0eHello, \"World\"\xb2\xd9\xa2\x1d\x0bHello\x00World\x88\xd9\xa2\x1d\xe9\xff\xff\xff\xff\xff\xff\xff\xff\x01\"4\n\x1cSettingRealsFromPositiveInts:\x14\xf5\xdf\xa3\x1d\x00\x00@A\xe9\xdc\xa2\x1d\x00\x00\x00\x00\x00@c@\"4\n\x1cSettingRealsFromNegativeInts:\x14\xf5\xdf\xa3\x1d\x00\x00@\xc1\xe9\xdc\xa2\x1d\x00\x00\x00\x00\x00@c\xc0\"U\n\x12\x43omplexOptionType1\x12\x0b\n\x03\x66oo\x18\x01 \x01(\x05\x12\x0c\n\x04\x66oo2\x18\x02 \x01(\x05\x12\x0c\n\x04\x66oo3\x18\x03 \x01(\x05\x12\x0c\n\x04\x66oo4\x18\x04 \x03(\x05*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x8b\x03\n\x12\x43omplexOptionType2\x12\x32\n\x03\x62\x61r\x18\x01 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType1\x12\x0b\n\x03\x62\x61z\x18\x02 \x01(\x05\x12\x46\n\x04\x66red\x18\x03 \x01(\x0b\x32\x38.protobuf_unittest.ComplexOptionType2.ComplexOptionType4\x12H\n\x06\x62\x61rney\x18\x04 \x03(\x0b\x32\x38.protobuf_unittest.ComplexOptionType2.ComplexOptionType4\x1a\x97\x01\n\x12\x43omplexOptionType4\x12\r\n\x05waldo\x18\x01 \x01(\x05\x32r\n\x0c\x63omplex_opt4\x12\x1f.google.protobuf.MessageOptions\x18\x8a\xf5\xd1\x03 \x01(\x0b\x32\x38.protobuf_unittest.ComplexOptionType2.ComplexOptionType4*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x9c\x01\n\x12\x43omplexOptionType3\x12\x0b\n\x03qux\x18\x01 \x01(\x05\x12T\n\x12\x63omplexoptiontype5\x18\x02 \x01(\n28.protobuf_unittest.ComplexOptionType3.ComplexOptionType5\x1a#\n\x12\x43omplexOptionType5\x12\r\n\x05plugh\x18\x03 \x01(\x05\"\x1f\n\x0b\x43omplexOpt6\x12\x10\n\x05xyzzy\x18\xdf\xbf\xcf\x03 \x01(\x05\"\xf1\x01\n\x15VariousComplexOptions:\xd7\x01\xa2\xe2\x95\x1d\x02\x08*\xa2\xe2\x95\x1d\x06\xd8\x85\x9e\x1d\xc4\x02\xa2\xe2\x95\x1d\x08\x92\xf5\x9d\x1d\x03\x08\xec\x06\xa2\xe2\x95\x1d\x02 c\xa2\xe2\x95\x1d\x02 X\xaa\xfd\x90\x1d\x03\x10\xdb\x07\xaa\xfd\x90\x1d\x06\xf8\xe6\x97\x1d\x8e\x05\xaa\xfd\x90\x1d\x05\n\x03\x08\xe7\x05\xaa\xfd\x90\x1d\x08\n\x06\xd8\x85\x9e\x1d\xcf\x0f\xaa\xfd\x90\x1d\n\n\x08\x92\xf5\x9d\x1d\x03\x08\xd8\x0f\xaa\xfd\x90\x1d\x08\xc2\xac\x97\x1d\x03\x08\xe5\x05\xaa\xfd\x90\x1d\x0b\xc2\xac\x97\x1d\x06\xd8\x85\x9e\x1d\xce\x0f\xaa\xfd\x90\x1d\r\xc2\xac\x97\x1d\x08\x92\xf5\x9d\x1d\x03\x08\xc9\x10\xd2\xa8\x8f\x1d\x03\x08\xb3\x0f\xaa\xfd\x90\x1d\x05\x1a\x03\x08\xc1\x02\xaa\xfd\x90\x1d\x04\"\x02\x08\x65\xaa\xfd\x90\x1d\x05\"\x03\x08\xd4\x01\xfa\xde\x90\x1d\x02\x08\t\xfa\xde\x90\x1d\x04\x13\x18\x16\x14\xe3\xdc\xfc\x1c\xf8\xfd\xfb\x1c\x18\xe4\xdc\xfc\x1c\"#\n\x13\x41ggregateMessageSet*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\"\xa0\x01\n\x1a\x41ggregateMessageSetElement\x12\t\n\x01s\x18\x01 \x01(\t2w\n\x15message_set_extension\x12&.protobuf_unittest.AggregateMessageSet\x18\xf6\xeb\xae\x07 \x01(\x0b\x32-.protobuf_unittest.AggregateMessageSetElement\"\xfd\x01\n\tAggregate\x12\t\n\x01i\x18\x01 \x01(\x05\x12\t\n\x01s\x18\x02 \x01(\t\x12)\n\x03sub\x18\x03 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate\x12*\n\x04\x66ile\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.FileOptions\x12\x34\n\x04mset\x18\x05 \x01(\x0b\x32&.protobuf_unittest.AggregateMessageSet2M\n\x06nested\x12\x1c.google.protobuf.FileOptions\x18\xa7\xd1\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate\"Y\n\x10\x41ggregateMessage\x12)\n\tfieldname\x18\x01 \x01(\x05\x42\x16\xf2\xa1\x87;\x11\x12\x0f\x46ieldAnnotation:\x1a\xc2\xd1\x86;\x15\x08\x65\x12\x11MessageAnnotation\"\xc9\x01\n\x10NestedOptionType\x1a;\n\rNestedMessage\x12\"\n\x0cnested_field\x18\x01 \x01(\x05\x42\x0c\xc1\xe0\xc3\x1d\xea\x03\x00\x00\x00\x00\x00\x00:\x06\xe0\xe9\xc2\x1d\xe9\x07\"5\n\nNestedEnum\x12\x1d\n\x11NESTED_ENUM_VALUE\x10\x01\x1a\x06\xb0\x86\xfa\x05\xec\x07\x1a\x08\xc5\xf6\xc9\x1d\xeb\x03\x00\x00\x32\x41\n\x10nested_extension\x12\x1c.google.protobuf.FileOptions\x18\xfd\xf8\xe2\x03 \x01(\x05\x42\x06\xc8\x8b\xca\x1d\xed\x07\"d\n\rOldOptionType\x12\x38\n\x05value\x18\x01 \x02(\x0e\x32).protobuf_unittest.OldOptionType.TestEnum\"\x19\n\x08TestEnum\x12\r\n\tOLD_VALUE\x10\x00\"s\n\rNewOptionType\x12\x38\n\x05value\x18\x01 \x02(\x0e\x32).protobuf_unittest.NewOptionType.TestEnum\"(\n\x08TestEnum\x12\r\n\tOLD_VALUE\x10\x00\x12\r\n\tNEW_VALUE\x10\x01\"-\n!TestMessageWithRequiredEnumOption:\x08\xfa\xe8\xfc\x94\x03\x02\x08\x00*6\n\nMethodOpt1\x12\x13\n\x0fMETHODOPT1_VAL1\x10\x01\x12\x13\n\x0fMETHODOPT1_VAL2\x10\x02*M\n\rAggregateEnum\x12%\n\x05VALUE\x10\x01\x1a\x1a\xca\xfc\x89;\x15\x12\x13\x45numValueAnnotation\x1a\x15\x92\x95\x88;\x10\x12\x0e\x45numAnnotation2\x8e\x01\n\x1cTestServiceWithCustomOptions\x12\x63\n\x03\x46oo\x12).protobuf_unittest.CustomOptionFooRequest\x1a*.protobuf_unittest.CustomOptionFooResponse\"\x05\xe0\xfa\x8c\x1e\x02\x1a\t\x90\xb2\x8b\x1e\xd3\xdb\x80\xcbI2\x99\x01\n\x10\x41ggregateService\x12k\n\x06Method\x12#.protobuf_unittest.AggregateMessage\x1a#.protobuf_unittest.AggregateMessage\"\x17\xca\xc8\x96;\x12\x12\x10MethodAnnotation\x1a\x18\xca\xfb\x8e;\x13\x12\x11ServiceAnnotation:2\n\tfile_opt1\x12\x1c.google.protobuf.FileOptions\x18\x8e\x9d\xd8\x03 \x01(\x04:8\n\x0cmessage_opt1\x12\x1f.google.protobuf.MessageOptions\x18\x9c\xad\xd8\x03 \x01(\x05:4\n\nfield_opt1\x12\x1d.google.protobuf.FieldOptions\x18\x88\xbc\xd8\x03 \x01(\x06:8\n\nfield_opt2\x12\x1d.google.protobuf.FieldOptions\x18\xb9\xa1\xd9\x03 \x01(\x05:\x02\x34\x32:4\n\noneof_opt1\x12\x1d.google.protobuf.OneofOptions\x18\xcf\xb5\xd8\x03 \x01(\x05:2\n\tenum_opt1\x12\x1c.google.protobuf.EnumOptions\x18\xe8\x9e\xd9\x03 \x01(\x0f:<\n\x0f\x65num_value_opt1\x12!.google.protobuf.EnumValueOptions\x18\xe6\xa0_ \x01(\x05:8\n\x0cservice_opt1\x12\x1f.google.protobuf.ServiceOptions\x18\xa2\xb6\xe1\x03 \x01(\x12:U\n\x0bmethod_opt1\x12\x1e.google.protobuf.MethodOptions\x18\xac\xcf\xe1\x03 \x01(\x0e\x32\x1d.protobuf_unittest.MethodOpt1:4\n\x08\x62ool_opt\x12\x1f.google.protobuf.MessageOptions\x18\xea\xab\xd6\x03 \x01(\x08:5\n\tint32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xed\xa8\xd6\x03 \x01(\x05:5\n\tint64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xc6\xa7\xd6\x03 \x01(\x03:6\n\nuint32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xb0\xa2\xd6\x03 \x01(\r:6\n\nuint64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xdf\x8e\xd6\x03 \x01(\x04:6\n\nsint32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xc0\x88\xd6\x03 \x01(\x11:6\n\nsint64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xff\x82\xd6\x03 \x01(\x12:7\n\x0b\x66ixed32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xd3\xfe\xd5\x03 \x01(\x07:7\n\x0b\x66ixed64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xe2\xfd\xd5\x03 \x01(\x06:8\n\x0csfixed32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xd5\xf1\xd5\x03 \x01(\x0f:8\n\x0csfixed64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xe3\x8a\xd5\x03 \x01(\x10:5\n\tfloat_opt\x12\x1f.google.protobuf.MessageOptions\x18\xfe\xbb\xd4\x03 \x01(\x02:6\n\ndouble_opt\x12\x1f.google.protobuf.MessageOptions\x18\xcd\xab\xd4\x03 \x01(\x01:6\n\nstring_opt\x12\x1f.google.protobuf.MessageOptions\x18\xc5\xab\xd4\x03 \x01(\t:5\n\tbytes_opt\x12\x1f.google.protobuf.MessageOptions\x18\x96\xab\xd4\x03 \x01(\x0c:p\n\x08\x65num_opt\x12\x1f.google.protobuf.MessageOptions\x18\x91\xab\xd4\x03 \x01(\x0e\x32:.protobuf_unittest.DummyMessageContainingEnum.TestEnumType:p\n\x10message_type_opt\x12\x1f.google.protobuf.MessageOptions\x18\xaf\xf2\xd3\x03 \x01(\x0b\x32\x32.protobuf_unittest.DummyMessageInvalidAsOptionType:6\n\x04quux\x12%.protobuf_unittest.ComplexOptionType1\x18\xdb\xe0\xd3\x03 \x01(\x05:^\n\x05\x63orge\x12%.protobuf_unittest.ComplexOptionType1\x18\xd2\xde\xd3\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType3:8\n\x06grault\x12%.protobuf_unittest.ComplexOptionType2\x18\xef\xfc\xd2\x03 \x01(\x05:_\n\x06garply\x12%.protobuf_unittest.ComplexOptionType2\x18\xc8\xf5\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType1:_\n\x0c\x63omplex_opt1\x12\x1f.google.protobuf.MessageOptions\x18\xa4\xdc\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType1:_\n\x0c\x63omplex_opt2\x12\x1f.google.protobuf.MessageOptions\x18\xd5\x8f\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType2:_\n\x0c\x63omplex_opt3\x12\x1f.google.protobuf.MessageOptions\x18\xef\x8b\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType3:W\n\x0b\x63omplexopt6\x12\x1f.google.protobuf.MessageOptions\x18\xcc\xcb\xcf\x03 \x01(\n2\x1e.protobuf_unittest.ComplexOpt6:N\n\x07\x66ileopt\x12\x1c.google.protobuf.FileOptions\x18\xcf\xdd\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:P\n\x06msgopt\x12\x1f.google.protobuf.MessageOptions\x18\x98\xea\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:P\n\x08\x66ieldopt\x12\x1d.google.protobuf.FieldOptions\x18\x9e\xf4\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:N\n\x07\x65numopt\x12\x1c.google.protobuf.EnumOptions\x18\xd2\x82\xb1\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:V\n\nenumvalopt\x12!.google.protobuf.EnumValueOptions\x18\xc9\x9f\xb1\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:T\n\nserviceopt\x12\x1f.google.protobuf.ServiceOptions\x18\xb9\xef\xb1\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:R\n\tmethodopt\x12\x1e.google.protobuf.MethodOptions\x18\x89\xe9\xb2\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:_\n\x11required_enum_opt\x12\x1f.google.protobuf.MessageOptions\x18\x8f\xcd\xcf\x32 \x01(\x0b\x32 .protobuf_unittest.OldOptionTypeB\x87\x01\x80\x01\x01\x88\x01\x01\x90\x01\x01\xf0\xe8\xc1\x1d\xea\xad\xc0\xe5$\xfa\xec\x85;p\x08\x64\x12\x0e\x46ileAnnotation\x1a\x16\x12\x14NestedFileAnnotation\"\x1e\xfa\xec\x85;\x19\x12\x17\x46ileExtensionAnnotation*$\x0b\x10\xf6\xeb\xae\x07\x1a\x1b\n\x19\x45mbeddedMessageSetElement\x0c') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + +_METHODOPT1 = _descriptor.EnumDescriptor( + name='MethodOpt1', + full_name='protobuf_unittest.MethodOpt1', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='METHODOPT1_VAL1', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='METHODOPT1_VAL2', index=1, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3006, + serialized_end=3060, +) +_sym_db.RegisterEnumDescriptor(_METHODOPT1) + +MethodOpt1 = enum_type_wrapper.EnumTypeWrapper(_METHODOPT1) +_AGGREGATEENUM = _descriptor.EnumDescriptor( + name='AggregateEnum', + full_name='protobuf_unittest.AggregateEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='VALUE', index=0, number=1, + serialized_options=_b('\312\374\211;\025\022\023EnumValueAnnotation'), + type=None), + ], + containing_type=None, + serialized_options=_b('\222\225\210;\020\022\016EnumAnnotation'), + serialized_start=3062, + serialized_end=3139, +) +_sym_db.RegisterEnumDescriptor(_AGGREGATEENUM) + +AggregateEnum = enum_type_wrapper.EnumTypeWrapper(_AGGREGATEENUM) +METHODOPT1_VAL1 = 1 +METHODOPT1_VAL2 = 2 +VALUE = 1 + +FILE_OPT1_FIELD_NUMBER = 7736974 +file_opt1 = _descriptor.FieldDescriptor( + name='file_opt1', full_name='protobuf_unittest.file_opt1', index=0, + number=7736974, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MESSAGE_OPT1_FIELD_NUMBER = 7739036 +message_opt1 = _descriptor.FieldDescriptor( + name='message_opt1', full_name='protobuf_unittest.message_opt1', index=1, + number=7739036, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIELD_OPT1_FIELD_NUMBER = 7740936 +field_opt1 = _descriptor.FieldDescriptor( + name='field_opt1', full_name='protobuf_unittest.field_opt1', index=2, + number=7740936, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIELD_OPT2_FIELD_NUMBER = 7753913 +field_opt2 = _descriptor.FieldDescriptor( + name='field_opt2', full_name='protobuf_unittest.field_opt2', index=3, + number=7753913, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_OPT1_FIELD_NUMBER = 7740111 +oneof_opt1 = _descriptor.FieldDescriptor( + name='oneof_opt1', full_name='protobuf_unittest.oneof_opt1', index=4, + number=7740111, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUM_OPT1_FIELD_NUMBER = 7753576 +enum_opt1 = _descriptor.FieldDescriptor( + name='enum_opt1', full_name='protobuf_unittest.enum_opt1', index=5, + number=7753576, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUM_VALUE_OPT1_FIELD_NUMBER = 1560678 +enum_value_opt1 = _descriptor.FieldDescriptor( + name='enum_value_opt1', full_name='protobuf_unittest.enum_value_opt1', index=6, + number=1560678, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SERVICE_OPT1_FIELD_NUMBER = 7887650 +service_opt1 = _descriptor.FieldDescriptor( + name='service_opt1', full_name='protobuf_unittest.service_opt1', index=7, + number=7887650, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +METHOD_OPT1_FIELD_NUMBER = 7890860 +method_opt1 = _descriptor.FieldDescriptor( + name='method_opt1', full_name='protobuf_unittest.method_opt1', index=8, + number=7890860, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +BOOL_OPT_FIELD_NUMBER = 7706090 +bool_opt = _descriptor.FieldDescriptor( + name='bool_opt', full_name='protobuf_unittest.bool_opt', index=9, + number=7706090, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +INT32_OPT_FIELD_NUMBER = 7705709 +int32_opt = _descriptor.FieldDescriptor( + name='int32_opt', full_name='protobuf_unittest.int32_opt', index=10, + number=7705709, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +INT64_OPT_FIELD_NUMBER = 7705542 +int64_opt = _descriptor.FieldDescriptor( + name='int64_opt', full_name='protobuf_unittest.int64_opt', index=11, + number=7705542, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +UINT32_OPT_FIELD_NUMBER = 7704880 +uint32_opt = _descriptor.FieldDescriptor( + name='uint32_opt', full_name='protobuf_unittest.uint32_opt', index=12, + number=7704880, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +UINT64_OPT_FIELD_NUMBER = 7702367 +uint64_opt = _descriptor.FieldDescriptor( + name='uint64_opt', full_name='protobuf_unittest.uint64_opt', index=13, + number=7702367, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SINT32_OPT_FIELD_NUMBER = 7701568 +sint32_opt = _descriptor.FieldDescriptor( + name='sint32_opt', full_name='protobuf_unittest.sint32_opt', index=14, + number=7701568, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SINT64_OPT_FIELD_NUMBER = 7700863 +sint64_opt = _descriptor.FieldDescriptor( + name='sint64_opt', full_name='protobuf_unittest.sint64_opt', index=15, + number=7700863, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIXED32_OPT_FIELD_NUMBER = 7700307 +fixed32_opt = _descriptor.FieldDescriptor( + name='fixed32_opt', full_name='protobuf_unittest.fixed32_opt', index=16, + number=7700307, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIXED64_OPT_FIELD_NUMBER = 7700194 +fixed64_opt = _descriptor.FieldDescriptor( + name='fixed64_opt', full_name='protobuf_unittest.fixed64_opt', index=17, + number=7700194, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SFIXED32_OPT_FIELD_NUMBER = 7698645 +sfixed32_opt = _descriptor.FieldDescriptor( + name='sfixed32_opt', full_name='protobuf_unittest.sfixed32_opt', index=18, + number=7698645, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SFIXED64_OPT_FIELD_NUMBER = 7685475 +sfixed64_opt = _descriptor.FieldDescriptor( + name='sfixed64_opt', full_name='protobuf_unittest.sfixed64_opt', index=19, + number=7685475, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FLOAT_OPT_FIELD_NUMBER = 7675390 +float_opt = _descriptor.FieldDescriptor( + name='float_opt', full_name='protobuf_unittest.float_opt', index=20, + number=7675390, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DOUBLE_OPT_FIELD_NUMBER = 7673293 +double_opt = _descriptor.FieldDescriptor( + name='double_opt', full_name='protobuf_unittest.double_opt', index=21, + number=7673293, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +STRING_OPT_FIELD_NUMBER = 7673285 +string_opt = _descriptor.FieldDescriptor( + name='string_opt', full_name='protobuf_unittest.string_opt', index=22, + number=7673285, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +BYTES_OPT_FIELD_NUMBER = 7673238 +bytes_opt = _descriptor.FieldDescriptor( + name='bytes_opt', full_name='protobuf_unittest.bytes_opt', index=23, + number=7673238, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUM_OPT_FIELD_NUMBER = 7673233 +enum_opt = _descriptor.FieldDescriptor( + name='enum_opt', full_name='protobuf_unittest.enum_opt', index=24, + number=7673233, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=22, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MESSAGE_TYPE_OPT_FIELD_NUMBER = 7665967 +message_type_opt = _descriptor.FieldDescriptor( + name='message_type_opt', full_name='protobuf_unittest.message_type_opt', index=25, + number=7665967, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +QUUX_FIELD_NUMBER = 7663707 +quux = _descriptor.FieldDescriptor( + name='quux', full_name='protobuf_unittest.quux', index=26, + number=7663707, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +CORGE_FIELD_NUMBER = 7663442 +corge = _descriptor.FieldDescriptor( + name='corge', full_name='protobuf_unittest.corge', index=27, + number=7663442, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +GRAULT_FIELD_NUMBER = 7650927 +grault = _descriptor.FieldDescriptor( + name='grault', full_name='protobuf_unittest.grault', index=28, + number=7650927, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +GARPLY_FIELD_NUMBER = 7649992 +garply = _descriptor.FieldDescriptor( + name='garply', full_name='protobuf_unittest.garply', index=29, + number=7649992, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEX_OPT1_FIELD_NUMBER = 7646756 +complex_opt1 = _descriptor.FieldDescriptor( + name='complex_opt1', full_name='protobuf_unittest.complex_opt1', index=30, + number=7646756, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEX_OPT2_FIELD_NUMBER = 7636949 +complex_opt2 = _descriptor.FieldDescriptor( + name='complex_opt2', full_name='protobuf_unittest.complex_opt2', index=31, + number=7636949, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEX_OPT3_FIELD_NUMBER = 7636463 +complex_opt3 = _descriptor.FieldDescriptor( + name='complex_opt3', full_name='protobuf_unittest.complex_opt3', index=32, + number=7636463, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEXOPT6_FIELD_NUMBER = 7595468 +complexopt6 = _descriptor.FieldDescriptor( + name='complexopt6', full_name='protobuf_unittest.complexopt6', index=33, + number=7595468, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FILEOPT_FIELD_NUMBER = 15478479 +fileopt = _descriptor.FieldDescriptor( + name='fileopt', full_name='protobuf_unittest.fileopt', index=34, + number=15478479, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MSGOPT_FIELD_NUMBER = 15480088 +msgopt = _descriptor.FieldDescriptor( + name='msgopt', full_name='protobuf_unittest.msgopt', index=35, + number=15480088, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIELDOPT_FIELD_NUMBER = 15481374 +fieldopt = _descriptor.FieldDescriptor( + name='fieldopt', full_name='protobuf_unittest.fieldopt', index=36, + number=15481374, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUMOPT_FIELD_NUMBER = 15483218 +enumopt = _descriptor.FieldDescriptor( + name='enumopt', full_name='protobuf_unittest.enumopt', index=37, + number=15483218, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUMVALOPT_FIELD_NUMBER = 15486921 +enumvalopt = _descriptor.FieldDescriptor( + name='enumvalopt', full_name='protobuf_unittest.enumvalopt', index=38, + number=15486921, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SERVICEOPT_FIELD_NUMBER = 15497145 +serviceopt = _descriptor.FieldDescriptor( + name='serviceopt', full_name='protobuf_unittest.serviceopt', index=39, + number=15497145, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +METHODOPT_FIELD_NUMBER = 15512713 +methodopt = _descriptor.FieldDescriptor( + name='methodopt', full_name='protobuf_unittest.methodopt', index=40, + number=15512713, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REQUIRED_ENUM_OPT_FIELD_NUMBER = 106161807 +required_enum_opt = _descriptor.FieldDescriptor( + name='required_enum_opt', full_name='protobuf_unittest.required_enum_opt', index=41, + number=106161807, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM = _descriptor.EnumDescriptor( + name='AnEnum', + full_name='protobuf_unittest.TestMessageWithCustomOptions.AnEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ANENUM_VAL1', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ANENUM_VAL2', index=1, number=2, + serialized_options=_b('\260\206\372\005{'), + type=None), + ], + containing_type=None, + serialized_options=_b('\305\366\311\035\353\374\377\377'), + serialized_start=190, + serialized_end=249, +) +_sym_db.RegisterEnumDescriptor(_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM) + +_DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE = _descriptor.EnumDescriptor( + name='TestEnumType', + full_name='protobuf_unittest.DummyMessageContainingEnum.TestEnumType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TEST_OPTION_ENUM_TYPE1', index=0, number=22, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TEST_OPTION_ENUM_TYPE2', index=1, number=-23, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=443, + serialized_end=522, +) +_sym_db.RegisterEnumDescriptor(_DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE) + +_NESTEDOPTIONTYPE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest.NestedOptionType.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NESTED_ENUM_VALUE', index=0, number=1, + serialized_options=_b('\260\206\372\005\354\007'), + type=None), + ], + containing_type=None, + serialized_options=_b('\305\366\311\035\353\003\000\000'), + serialized_start=2618, + serialized_end=2671, +) +_sym_db.RegisterEnumDescriptor(_NESTEDOPTIONTYPE_NESTEDENUM) + +_OLDOPTIONTYPE_TESTENUM = _descriptor.EnumDescriptor( + name='TestEnum', + full_name='protobuf_unittest.OldOptionType.TestEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OLD_VALUE', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2815, + serialized_end=2840, +) +_sym_db.RegisterEnumDescriptor(_OLDOPTIONTYPE_TESTENUM) + +_NEWOPTIONTYPE_TESTENUM = _descriptor.EnumDescriptor( + name='TestEnum', + full_name='protobuf_unittest.NewOptionType.TestEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OLD_VALUE', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEW_VALUE', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2917, + serialized_end=2957, +) +_sym_db.RegisterEnumDescriptor(_NEWOPTIONTYPE_TESTENUM) + + +_TESTMESSAGEWITHCUSTOMOPTIONS = _descriptor.Descriptor( + name='TestMessageWithCustomOptions', + full_name='protobuf_unittest.TestMessageWithCustomOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestMessageWithCustomOptions.field1', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001\301\340\303\035-\341u\n\002\000\000\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_field', full_name='protobuf_unittest.TestMessageWithCustomOptions.oneof_field', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM, + ], + serialized_options=_b('\010\000\340\351\302\035\310\377\377\377\377\377\377\377\377\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='AnOneof', full_name='protobuf_unittest.TestMessageWithCustomOptions.AnOneof', + index=0, containing_type=None, fields=[], serialized_options=_b('\370\254\303\035\235\377\377\377\377\377\377\377\377\001')), + ], + serialized_start=103, + serialized_end=294, +) + + +_CUSTOMOPTIONFOOREQUEST = _descriptor.Descriptor( + name='CustomOptionFooRequest', + full_name='protobuf_unittest.CustomOptionFooRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=296, + serialized_end=320, +) + + +_CUSTOMOPTIONFOORESPONSE = _descriptor.Descriptor( + name='CustomOptionFooResponse', + full_name='protobuf_unittest.CustomOptionFooResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=322, + serialized_end=347, +) + + +_CUSTOMOPTIONFOOCLIENTMESSAGE = _descriptor.Descriptor( + name='CustomOptionFooClientMessage', + full_name='protobuf_unittest.CustomOptionFooClientMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=349, + serialized_end=379, +) + + +_CUSTOMOPTIONFOOSERVERMESSAGE = _descriptor.Descriptor( + name='CustomOptionFooServerMessage', + full_name='protobuf_unittest.CustomOptionFooServerMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=381, + serialized_end=411, +) + + +_DUMMYMESSAGECONTAININGENUM = _descriptor.Descriptor( + name='DummyMessageContainingEnum', + full_name='protobuf_unittest.DummyMessageContainingEnum', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=413, + serialized_end=522, +) + + +_DUMMYMESSAGEINVALIDASOPTIONTYPE = _descriptor.Descriptor( + name='DummyMessageInvalidAsOptionType', + full_name='protobuf_unittest.DummyMessageInvalidAsOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=524, + serialized_end=557, +) + + +_CUSTOMOPTIONMININTEGERVALUES = _descriptor.Descriptor( + name='CustomOptionMinIntegerValues', + full_name='protobuf_unittest.CustomOptionMinIntegerValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\320\336\262\035\000\350\306\262\035\200\200\200\200\370\377\377\377\377\001\260\274\262\035\200\200\200\200\200\200\200\200\200\001\200\223\262\035\000\370\365\260\035\000\200\304\260\035\377\377\377\377\017\370\227\260\035\377\377\377\377\377\377\377\377\377\001\235\365\257\035\000\000\000\000\221\356\257\035\000\000\000\000\000\000\000\000\255\215\257\035\000\000\000\200\231\326\250\035\000\000\000\000\000\000\000\200'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=560, + serialized_end=698, +) + + +_CUSTOMOPTIONMAXINTEGERVALUES = _descriptor.Descriptor( + name='CustomOptionMaxIntegerValues', + full_name='protobuf_unittest.CustomOptionMaxIntegerValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\320\336\262\035\001\350\306\262\035\377\377\377\377\007\260\274\262\035\377\377\377\377\377\377\377\377\177\200\223\262\035\377\377\377\377\017\370\365\260\035\377\377\377\377\377\377\377\377\377\001\200\304\260\035\376\377\377\377\017\370\227\260\035\376\377\377\377\377\377\377\377\377\001\235\365\257\035\377\377\377\377\221\356\257\035\377\377\377\377\377\377\377\377\255\215\257\035\377\377\377\177\231\326\250\035\377\377\377\377\377\377\377\177'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=701, + serialized_end=846, +) + + +_CUSTOMOPTIONOTHERVALUES = _descriptor.Descriptor( + name='CustomOptionOtherValues', + full_name='protobuf_unittest.CustomOptionOtherValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\350\306\262\035\234\377\377\377\377\377\377\377\377\001\365\337\243\035\347\207EA\351\334\242\035\373Y\214B\312\300\363?\252\334\242\035\016Hello, \"World\"\262\331\242\035\013Hello\000World\210\331\242\035\351\377\377\377\377\377\377\377\377\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=848, + serialized_end=958, +) + + +_SETTINGREALSFROMPOSITIVEINTS = _descriptor.Descriptor( + name='SettingRealsFromPositiveInts', + full_name='protobuf_unittest.SettingRealsFromPositiveInts', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\365\337\243\035\000\000@A\351\334\242\035\000\000\000\000\000@c@'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=960, + serialized_end=1012, +) + + +_SETTINGREALSFROMNEGATIVEINTS = _descriptor.Descriptor( + name='SettingRealsFromNegativeInts', + full_name='protobuf_unittest.SettingRealsFromNegativeInts', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\365\337\243\035\000\000@\301\351\334\242\035\000\000\000\000\000@c\300'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1014, + serialized_end=1066, +) + + +_COMPLEXOPTIONTYPE1 = _descriptor.Descriptor( + name='ComplexOptionType1', + full_name='protobuf_unittest.ComplexOptionType1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo', full_name='protobuf_unittest.ComplexOptionType1.foo', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo2', full_name='protobuf_unittest.ComplexOptionType1.foo2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo3', full_name='protobuf_unittest.ComplexOptionType1.foo3', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo4', full_name='protobuf_unittest.ComplexOptionType1.foo4', index=3, + number=4, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=1068, + serialized_end=1153, +) + + +_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 = _descriptor.Descriptor( + name='ComplexOptionType4', + full_name='protobuf_unittest.ComplexOptionType2.ComplexOptionType4', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='waldo', full_name='protobuf_unittest.ComplexOptionType2.ComplexOptionType4.waldo', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='complex_opt4', full_name='protobuf_unittest.ComplexOptionType2.ComplexOptionType4.complex_opt4', index=0, + number=7633546, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1390, + serialized_end=1541, +) + +_COMPLEXOPTIONTYPE2 = _descriptor.Descriptor( + name='ComplexOptionType2', + full_name='protobuf_unittest.ComplexOptionType2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bar', full_name='protobuf_unittest.ComplexOptionType2.bar', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='baz', full_name='protobuf_unittest.ComplexOptionType2.baz', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fred', full_name='protobuf_unittest.ComplexOptionType2.fred', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='barney', full_name='protobuf_unittest.ComplexOptionType2.barney', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=1156, + serialized_end=1551, +) + + +_COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5 = _descriptor.Descriptor( + name='ComplexOptionType5', + full_name='protobuf_unittest.ComplexOptionType3.ComplexOptionType5', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='plugh', full_name='protobuf_unittest.ComplexOptionType3.ComplexOptionType5.plugh', index=0, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1675, + serialized_end=1710, +) + +_COMPLEXOPTIONTYPE3 = _descriptor.Descriptor( + name='ComplexOptionType3', + full_name='protobuf_unittest.ComplexOptionType3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='qux', full_name='protobuf_unittest.ComplexOptionType3.qux', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='complexoptiontype5', full_name='protobuf_unittest.ComplexOptionType3.complexoptiontype5', index=1, + number=2, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1554, + serialized_end=1710, +) + + +_COMPLEXOPT6 = _descriptor.Descriptor( + name='ComplexOpt6', + full_name='protobuf_unittest.ComplexOpt6', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='xyzzy', full_name='protobuf_unittest.ComplexOpt6.xyzzy', index=0, + number=7593951, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1712, + serialized_end=1743, +) + + +_VARIOUSCOMPLEXOPTIONS = _descriptor.Descriptor( + name='VariousComplexOptions', + full_name='protobuf_unittest.VariousComplexOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\242\342\225\035\002\010*\242\342\225\035\006\330\205\236\035\304\002\242\342\225\035\010\222\365\235\035\003\010\354\006\242\342\225\035\002 c\242\342\225\035\002 X\252\375\220\035\003\020\333\007\252\375\220\035\006\370\346\227\035\216\005\252\375\220\035\005\n\003\010\347\005\252\375\220\035\010\n\006\330\205\236\035\317\017\252\375\220\035\n\n\010\222\365\235\035\003\010\330\017\252\375\220\035\010\302\254\227\035\003\010\345\005\252\375\220\035\013\302\254\227\035\006\330\205\236\035\316\017\252\375\220\035\r\302\254\227\035\010\222\365\235\035\003\010\311\020\322\250\217\035\003\010\263\017\252\375\220\035\005\032\003\010\301\002\252\375\220\035\004\"\002\010e\252\375\220\035\005\"\003\010\324\001\372\336\220\035\002\010\t\372\336\220\035\004\023\030\026\024\343\334\374\034\370\375\373\034\030\344\334\374\034'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1746, + serialized_end=1987, +) + + +_AGGREGATEMESSAGESET = _descriptor.Descriptor( + name='AggregateMessageSet', + full_name='protobuf_unittest.AggregateMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=1989, + serialized_end=2024, +) + + +_AGGREGATEMESSAGESETELEMENT = _descriptor.Descriptor( + name='AggregateMessageSetElement', + full_name='protobuf_unittest.AggregateMessageSetElement', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='s', full_name='protobuf_unittest.AggregateMessageSetElement.s', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_unittest.AggregateMessageSetElement.message_set_extension', index=0, + number=15447542, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2027, + serialized_end=2187, +) + + +_AGGREGATE = _descriptor.Descriptor( + name='Aggregate', + full_name='protobuf_unittest.Aggregate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.Aggregate.i', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='s', full_name='protobuf_unittest.Aggregate.s', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sub', full_name='protobuf_unittest.Aggregate.sub', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='file', full_name='protobuf_unittest.Aggregate.file', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mset', full_name='protobuf_unittest.Aggregate.mset', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='nested', full_name='protobuf_unittest.Aggregate.nested', index=0, + number=15476903, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2190, + serialized_end=2443, +) + + +_AGGREGATEMESSAGE = _descriptor.Descriptor( + name='AggregateMessage', + full_name='protobuf_unittest.AggregateMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='fieldname', full_name='protobuf_unittest.AggregateMessage.fieldname', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\362\241\207;\021\022\017FieldAnnotation'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\302\321\206;\025\010e\022\021MessageAnnotation'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2445, + serialized_end=2534, +) + + +_NESTEDOPTIONTYPE_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.NestedOptionType.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_field', full_name='protobuf_unittest.NestedOptionType.NestedMessage.nested_field', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\301\340\303\035\352\003\000\000\000\000\000\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\340\351\302\035\351\007'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2557, + serialized_end=2616, +) + +_NESTEDOPTIONTYPE = _descriptor.Descriptor( + name='NestedOptionType', + full_name='protobuf_unittest.NestedOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + _descriptor.FieldDescriptor( + name='nested_extension', full_name='protobuf_unittest.NestedOptionType.nested_extension', index=0, + number=7912573, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\310\213\312\035\355\007'), file=DESCRIPTOR), + ], + nested_types=[_NESTEDOPTIONTYPE_NESTEDMESSAGE, ], + enum_types=[ + _NESTEDOPTIONTYPE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2537, + serialized_end=2738, +) + + +_OLDOPTIONTYPE = _descriptor.Descriptor( + name='OldOptionType', + full_name='protobuf_unittest.OldOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.OldOptionType.value', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _OLDOPTIONTYPE_TESTENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2740, + serialized_end=2840, +) + + +_NEWOPTIONTYPE = _descriptor.Descriptor( + name='NewOptionType', + full_name='protobuf_unittest.NewOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.NewOptionType.value', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _NEWOPTIONTYPE_TESTENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2842, + serialized_end=2957, +) + + +_TESTMESSAGEWITHREQUIREDENUMOPTION = _descriptor.Descriptor( + name='TestMessageWithRequiredEnumOption', + full_name='protobuf_unittest.TestMessageWithRequiredEnumOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\372\350\374\224\003\002\010\000'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2959, + serialized_end=3004, +) + +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM.containing_type = _TESTMESSAGEWITHCUSTOMOPTIONS +_TESTMESSAGEWITHCUSTOMOPTIONS.oneofs_by_name['AnOneof'].fields.append( + _TESTMESSAGEWITHCUSTOMOPTIONS.fields_by_name['oneof_field']) +_TESTMESSAGEWITHCUSTOMOPTIONS.fields_by_name['oneof_field'].containing_oneof = _TESTMESSAGEWITHCUSTOMOPTIONS.oneofs_by_name['AnOneof'] +_DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE.containing_type = _DUMMYMESSAGECONTAININGENUM +_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4.containing_type = _COMPLEXOPTIONTYPE2 +_COMPLEXOPTIONTYPE2.fields_by_name['bar'].message_type = _COMPLEXOPTIONTYPE1 +_COMPLEXOPTIONTYPE2.fields_by_name['fred'].message_type = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 +_COMPLEXOPTIONTYPE2.fields_by_name['barney'].message_type = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 +_COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5.containing_type = _COMPLEXOPTIONTYPE3 +_COMPLEXOPTIONTYPE3.fields_by_name['complexoptiontype5'].message_type = _COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5 +_AGGREGATE.fields_by_name['sub'].message_type = _AGGREGATE +_AGGREGATE.fields_by_name['file'].message_type = google_dot_protobuf_dot_descriptor__pb2._FILEOPTIONS +_AGGREGATE.fields_by_name['mset'].message_type = _AGGREGATEMESSAGESET +_NESTEDOPTIONTYPE_NESTEDMESSAGE.containing_type = _NESTEDOPTIONTYPE +_NESTEDOPTIONTYPE_NESTEDENUM.containing_type = _NESTEDOPTIONTYPE +_OLDOPTIONTYPE.fields_by_name['value'].enum_type = _OLDOPTIONTYPE_TESTENUM +_OLDOPTIONTYPE_TESTENUM.containing_type = _OLDOPTIONTYPE +_NEWOPTIONTYPE.fields_by_name['value'].enum_type = _NEWOPTIONTYPE_TESTENUM +_NEWOPTIONTYPE_TESTENUM.containing_type = _NEWOPTIONTYPE +DESCRIPTOR.message_types_by_name['TestMessageWithCustomOptions'] = _TESTMESSAGEWITHCUSTOMOPTIONS +DESCRIPTOR.message_types_by_name['CustomOptionFooRequest'] = _CUSTOMOPTIONFOOREQUEST +DESCRIPTOR.message_types_by_name['CustomOptionFooResponse'] = _CUSTOMOPTIONFOORESPONSE +DESCRIPTOR.message_types_by_name['CustomOptionFooClientMessage'] = _CUSTOMOPTIONFOOCLIENTMESSAGE +DESCRIPTOR.message_types_by_name['CustomOptionFooServerMessage'] = _CUSTOMOPTIONFOOSERVERMESSAGE +DESCRIPTOR.message_types_by_name['DummyMessageContainingEnum'] = _DUMMYMESSAGECONTAININGENUM +DESCRIPTOR.message_types_by_name['DummyMessageInvalidAsOptionType'] = _DUMMYMESSAGEINVALIDASOPTIONTYPE +DESCRIPTOR.message_types_by_name['CustomOptionMinIntegerValues'] = _CUSTOMOPTIONMININTEGERVALUES +DESCRIPTOR.message_types_by_name['CustomOptionMaxIntegerValues'] = _CUSTOMOPTIONMAXINTEGERVALUES +DESCRIPTOR.message_types_by_name['CustomOptionOtherValues'] = _CUSTOMOPTIONOTHERVALUES +DESCRIPTOR.message_types_by_name['SettingRealsFromPositiveInts'] = _SETTINGREALSFROMPOSITIVEINTS +DESCRIPTOR.message_types_by_name['SettingRealsFromNegativeInts'] = _SETTINGREALSFROMNEGATIVEINTS +DESCRIPTOR.message_types_by_name['ComplexOptionType1'] = _COMPLEXOPTIONTYPE1 +DESCRIPTOR.message_types_by_name['ComplexOptionType2'] = _COMPLEXOPTIONTYPE2 +DESCRIPTOR.message_types_by_name['ComplexOptionType3'] = _COMPLEXOPTIONTYPE3 +DESCRIPTOR.message_types_by_name['ComplexOpt6'] = _COMPLEXOPT6 +DESCRIPTOR.message_types_by_name['VariousComplexOptions'] = _VARIOUSCOMPLEXOPTIONS +DESCRIPTOR.message_types_by_name['AggregateMessageSet'] = _AGGREGATEMESSAGESET +DESCRIPTOR.message_types_by_name['AggregateMessageSetElement'] = _AGGREGATEMESSAGESETELEMENT +DESCRIPTOR.message_types_by_name['Aggregate'] = _AGGREGATE +DESCRIPTOR.message_types_by_name['AggregateMessage'] = _AGGREGATEMESSAGE +DESCRIPTOR.message_types_by_name['NestedOptionType'] = _NESTEDOPTIONTYPE +DESCRIPTOR.message_types_by_name['OldOptionType'] = _OLDOPTIONTYPE +DESCRIPTOR.message_types_by_name['NewOptionType'] = _NEWOPTIONTYPE +DESCRIPTOR.message_types_by_name['TestMessageWithRequiredEnumOption'] = _TESTMESSAGEWITHREQUIREDENUMOPTION +DESCRIPTOR.enum_types_by_name['MethodOpt1'] = _METHODOPT1 +DESCRIPTOR.enum_types_by_name['AggregateEnum'] = _AGGREGATEENUM +DESCRIPTOR.extensions_by_name['file_opt1'] = file_opt1 +DESCRIPTOR.extensions_by_name['message_opt1'] = message_opt1 +DESCRIPTOR.extensions_by_name['field_opt1'] = field_opt1 +DESCRIPTOR.extensions_by_name['field_opt2'] = field_opt2 +DESCRIPTOR.extensions_by_name['oneof_opt1'] = oneof_opt1 +DESCRIPTOR.extensions_by_name['enum_opt1'] = enum_opt1 +DESCRIPTOR.extensions_by_name['enum_value_opt1'] = enum_value_opt1 +DESCRIPTOR.extensions_by_name['service_opt1'] = service_opt1 +DESCRIPTOR.extensions_by_name['method_opt1'] = method_opt1 +DESCRIPTOR.extensions_by_name['bool_opt'] = bool_opt +DESCRIPTOR.extensions_by_name['int32_opt'] = int32_opt +DESCRIPTOR.extensions_by_name['int64_opt'] = int64_opt +DESCRIPTOR.extensions_by_name['uint32_opt'] = uint32_opt +DESCRIPTOR.extensions_by_name['uint64_opt'] = uint64_opt +DESCRIPTOR.extensions_by_name['sint32_opt'] = sint32_opt +DESCRIPTOR.extensions_by_name['sint64_opt'] = sint64_opt +DESCRIPTOR.extensions_by_name['fixed32_opt'] = fixed32_opt +DESCRIPTOR.extensions_by_name['fixed64_opt'] = fixed64_opt +DESCRIPTOR.extensions_by_name['sfixed32_opt'] = sfixed32_opt +DESCRIPTOR.extensions_by_name['sfixed64_opt'] = sfixed64_opt +DESCRIPTOR.extensions_by_name['float_opt'] = float_opt +DESCRIPTOR.extensions_by_name['double_opt'] = double_opt +DESCRIPTOR.extensions_by_name['string_opt'] = string_opt +DESCRIPTOR.extensions_by_name['bytes_opt'] = bytes_opt +DESCRIPTOR.extensions_by_name['enum_opt'] = enum_opt +DESCRIPTOR.extensions_by_name['message_type_opt'] = message_type_opt +DESCRIPTOR.extensions_by_name['quux'] = quux +DESCRIPTOR.extensions_by_name['corge'] = corge +DESCRIPTOR.extensions_by_name['grault'] = grault +DESCRIPTOR.extensions_by_name['garply'] = garply +DESCRIPTOR.extensions_by_name['complex_opt1'] = complex_opt1 +DESCRIPTOR.extensions_by_name['complex_opt2'] = complex_opt2 +DESCRIPTOR.extensions_by_name['complex_opt3'] = complex_opt3 +DESCRIPTOR.extensions_by_name['complexopt6'] = complexopt6 +DESCRIPTOR.extensions_by_name['fileopt'] = fileopt +DESCRIPTOR.extensions_by_name['msgopt'] = msgopt +DESCRIPTOR.extensions_by_name['fieldopt'] = fieldopt +DESCRIPTOR.extensions_by_name['enumopt'] = enumopt +DESCRIPTOR.extensions_by_name['enumvalopt'] = enumvalopt +DESCRIPTOR.extensions_by_name['serviceopt'] = serviceopt +DESCRIPTOR.extensions_by_name['methodopt'] = methodopt +DESCRIPTOR.extensions_by_name['required_enum_opt'] = required_enum_opt +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageWithCustomOptions = _reflection.GeneratedProtocolMessageType('TestMessageWithCustomOptions', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGEWITHCUSTOMOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageWithCustomOptions) + )) +_sym_db.RegisterMessage(TestMessageWithCustomOptions) + +CustomOptionFooRequest = _reflection.GeneratedProtocolMessageType('CustomOptionFooRequest', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOOREQUEST, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooRequest) + )) +_sym_db.RegisterMessage(CustomOptionFooRequest) + +CustomOptionFooResponse = _reflection.GeneratedProtocolMessageType('CustomOptionFooResponse', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOORESPONSE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooResponse) + )) +_sym_db.RegisterMessage(CustomOptionFooResponse) + +CustomOptionFooClientMessage = _reflection.GeneratedProtocolMessageType('CustomOptionFooClientMessage', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOOCLIENTMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooClientMessage) + )) +_sym_db.RegisterMessage(CustomOptionFooClientMessage) + +CustomOptionFooServerMessage = _reflection.GeneratedProtocolMessageType('CustomOptionFooServerMessage', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOOSERVERMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooServerMessage) + )) +_sym_db.RegisterMessage(CustomOptionFooServerMessage) + +DummyMessageContainingEnum = _reflection.GeneratedProtocolMessageType('DummyMessageContainingEnum', (_message.Message,), dict( + DESCRIPTOR = _DUMMYMESSAGECONTAININGENUM, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.DummyMessageContainingEnum) + )) +_sym_db.RegisterMessage(DummyMessageContainingEnum) + +DummyMessageInvalidAsOptionType = _reflection.GeneratedProtocolMessageType('DummyMessageInvalidAsOptionType', (_message.Message,), dict( + DESCRIPTOR = _DUMMYMESSAGEINVALIDASOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.DummyMessageInvalidAsOptionType) + )) +_sym_db.RegisterMessage(DummyMessageInvalidAsOptionType) + +CustomOptionMinIntegerValues = _reflection.GeneratedProtocolMessageType('CustomOptionMinIntegerValues', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONMININTEGERVALUES, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionMinIntegerValues) + )) +_sym_db.RegisterMessage(CustomOptionMinIntegerValues) + +CustomOptionMaxIntegerValues = _reflection.GeneratedProtocolMessageType('CustomOptionMaxIntegerValues', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONMAXINTEGERVALUES, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionMaxIntegerValues) + )) +_sym_db.RegisterMessage(CustomOptionMaxIntegerValues) + +CustomOptionOtherValues = _reflection.GeneratedProtocolMessageType('CustomOptionOtherValues', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONOTHERVALUES, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionOtherValues) + )) +_sym_db.RegisterMessage(CustomOptionOtherValues) + +SettingRealsFromPositiveInts = _reflection.GeneratedProtocolMessageType('SettingRealsFromPositiveInts', (_message.Message,), dict( + DESCRIPTOR = _SETTINGREALSFROMPOSITIVEINTS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.SettingRealsFromPositiveInts) + )) +_sym_db.RegisterMessage(SettingRealsFromPositiveInts) + +SettingRealsFromNegativeInts = _reflection.GeneratedProtocolMessageType('SettingRealsFromNegativeInts', (_message.Message,), dict( + DESCRIPTOR = _SETTINGREALSFROMNEGATIVEINTS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.SettingRealsFromNegativeInts) + )) +_sym_db.RegisterMessage(SettingRealsFromNegativeInts) + +ComplexOptionType1 = _reflection.GeneratedProtocolMessageType('ComplexOptionType1', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPTIONTYPE1, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType1) + )) +_sym_db.RegisterMessage(ComplexOptionType1) + +ComplexOptionType2 = _reflection.GeneratedProtocolMessageType('ComplexOptionType2', (_message.Message,), dict( + + ComplexOptionType4 = _reflection.GeneratedProtocolMessageType('ComplexOptionType4', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType2.ComplexOptionType4) + )) + , + DESCRIPTOR = _COMPLEXOPTIONTYPE2, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType2) + )) +_sym_db.RegisterMessage(ComplexOptionType2) +_sym_db.RegisterMessage(ComplexOptionType2.ComplexOptionType4) + +ComplexOptionType3 = _reflection.GeneratedProtocolMessageType('ComplexOptionType3', (_message.Message,), dict( + + ComplexOptionType5 = _reflection.GeneratedProtocolMessageType('ComplexOptionType5', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType3.ComplexOptionType5) + )) + , + DESCRIPTOR = _COMPLEXOPTIONTYPE3, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType3) + )) +_sym_db.RegisterMessage(ComplexOptionType3) +_sym_db.RegisterMessage(ComplexOptionType3.ComplexOptionType5) + +ComplexOpt6 = _reflection.GeneratedProtocolMessageType('ComplexOpt6', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPT6, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOpt6) + )) +_sym_db.RegisterMessage(ComplexOpt6) + +VariousComplexOptions = _reflection.GeneratedProtocolMessageType('VariousComplexOptions', (_message.Message,), dict( + DESCRIPTOR = _VARIOUSCOMPLEXOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.VariousComplexOptions) + )) +_sym_db.RegisterMessage(VariousComplexOptions) + +AggregateMessageSet = _reflection.GeneratedProtocolMessageType('AggregateMessageSet', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATEMESSAGESET, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AggregateMessageSet) + )) +_sym_db.RegisterMessage(AggregateMessageSet) + +AggregateMessageSetElement = _reflection.GeneratedProtocolMessageType('AggregateMessageSetElement', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATEMESSAGESETELEMENT, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AggregateMessageSetElement) + )) +_sym_db.RegisterMessage(AggregateMessageSetElement) + +Aggregate = _reflection.GeneratedProtocolMessageType('Aggregate', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Aggregate) + )) +_sym_db.RegisterMessage(Aggregate) + +AggregateMessage = _reflection.GeneratedProtocolMessageType('AggregateMessage', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATEMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AggregateMessage) + )) +_sym_db.RegisterMessage(AggregateMessage) + +NestedOptionType = _reflection.GeneratedProtocolMessageType('NestedOptionType', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _NESTEDOPTIONTYPE_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NestedOptionType.NestedMessage) + )) + , + DESCRIPTOR = _NESTEDOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NestedOptionType) + )) +_sym_db.RegisterMessage(NestedOptionType) +_sym_db.RegisterMessage(NestedOptionType.NestedMessage) + +OldOptionType = _reflection.GeneratedProtocolMessageType('OldOptionType', (_message.Message,), dict( + DESCRIPTOR = _OLDOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OldOptionType) + )) +_sym_db.RegisterMessage(OldOptionType) + +NewOptionType = _reflection.GeneratedProtocolMessageType('NewOptionType', (_message.Message,), dict( + DESCRIPTOR = _NEWOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NewOptionType) + )) +_sym_db.RegisterMessage(NewOptionType) + +TestMessageWithRequiredEnumOption = _reflection.GeneratedProtocolMessageType('TestMessageWithRequiredEnumOption', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGEWITHREQUIREDENUMOPTION, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageWithRequiredEnumOption) + )) +_sym_db.RegisterMessage(TestMessageWithRequiredEnumOption) + +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(file_opt1) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(message_opt1) +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(field_opt1) +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(field_opt2) +google_dot_protobuf_dot_descriptor__pb2.OneofOptions.RegisterExtension(oneof_opt1) +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(enum_opt1) +google_dot_protobuf_dot_descriptor__pb2.EnumValueOptions.RegisterExtension(enum_value_opt1) +google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension(service_opt1) +method_opt1.enum_type = _METHODOPT1 +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(method_opt1) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(bool_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(int32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(int64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(uint32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(uint64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sint32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sint64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(fixed32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(fixed64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sfixed32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sfixed64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(float_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(double_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(string_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(bytes_opt) +enum_opt.enum_type = _DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(enum_opt) +message_type_opt.message_type = _DUMMYMESSAGEINVALIDASOPTIONTYPE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(message_type_opt) +ComplexOptionType1.RegisterExtension(quux) +corge.message_type = _COMPLEXOPTIONTYPE3 +ComplexOptionType1.RegisterExtension(corge) +ComplexOptionType2.RegisterExtension(grault) +garply.message_type = _COMPLEXOPTIONTYPE1 +ComplexOptionType2.RegisterExtension(garply) +complex_opt1.message_type = _COMPLEXOPTIONTYPE1 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complex_opt1) +complex_opt2.message_type = _COMPLEXOPTIONTYPE2 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complex_opt2) +complex_opt3.message_type = _COMPLEXOPTIONTYPE3 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complex_opt3) +complexopt6.message_type = _COMPLEXOPT6 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complexopt6) +fileopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(fileopt) +msgopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(msgopt) +fieldopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(fieldopt) +enumopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(enumopt) +enumvalopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.EnumValueOptions.RegisterExtension(enumvalopt) +serviceopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension(serviceopt) +methodopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(methodopt) +required_enum_opt.message_type = _OLDOPTIONTYPE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(required_enum_opt) +_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4.extensions_by_name['complex_opt4'].message_type = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4.extensions_by_name['complex_opt4']) +_AGGREGATEMESSAGESETELEMENT.extensions_by_name['message_set_extension'].message_type = _AGGREGATEMESSAGESETELEMENT +AggregateMessageSet.RegisterExtension(_AGGREGATEMESSAGESETELEMENT.extensions_by_name['message_set_extension']) +_AGGREGATE.extensions_by_name['nested'].message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(_AGGREGATE.extensions_by_name['nested']) +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(_NESTEDOPTIONTYPE.extensions_by_name['nested_extension']) + +DESCRIPTOR._options = None +_AGGREGATEENUM._options = None +_AGGREGATEENUM.values_by_name["VALUE"]._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS.oneofs_by_name['AnOneof']._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM.values_by_name["ANENUM_VAL2"]._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS.fields_by_name['field1']._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS._options = None +_CUSTOMOPTIONMININTEGERVALUES._options = None +_CUSTOMOPTIONMAXINTEGERVALUES._options = None +_CUSTOMOPTIONOTHERVALUES._options = None +_SETTINGREALSFROMPOSITIVEINTS._options = None +_SETTINGREALSFROMNEGATIVEINTS._options = None +_VARIOUSCOMPLEXOPTIONS._options = None +_AGGREGATEMESSAGESET._options = None +_AGGREGATEMESSAGE.fields_by_name['fieldname']._options = None +_AGGREGATEMESSAGE._options = None +_NESTEDOPTIONTYPE_NESTEDMESSAGE.fields_by_name['nested_field']._options = None +_NESTEDOPTIONTYPE_NESTEDMESSAGE._options = None +_NESTEDOPTIONTYPE_NESTEDENUM._options = None +_NESTEDOPTIONTYPE_NESTEDENUM.values_by_name["NESTED_ENUM_VALUE"]._options = None +_NESTEDOPTIONTYPE.extensions_by_name['nested_extension']._options = None +_TESTMESSAGEWITHREQUIREDENUMOPTION._options = None + +_TESTSERVICEWITHCUSTOMOPTIONS = _descriptor.ServiceDescriptor( + name='TestServiceWithCustomOptions', + full_name='protobuf_unittest.TestServiceWithCustomOptions', + file=DESCRIPTOR, + index=0, + serialized_options=_b('\220\262\213\036\323\333\200\313I'), + serialized_start=3142, + serialized_end=3284, + methods=[ + _descriptor.MethodDescriptor( + name='Foo', + full_name='protobuf_unittest.TestServiceWithCustomOptions.Foo', + index=0, + containing_service=None, + input_type=_CUSTOMOPTIONFOOREQUEST, + output_type=_CUSTOMOPTIONFOORESPONSE, + serialized_options=_b('\340\372\214\036\002'), + ), +]) +_sym_db.RegisterServiceDescriptor(_TESTSERVICEWITHCUSTOMOPTIONS) + +DESCRIPTOR.services_by_name['TestServiceWithCustomOptions'] = _TESTSERVICEWITHCUSTOMOPTIONS + + +_AGGREGATESERVICE = _descriptor.ServiceDescriptor( + name='AggregateService', + full_name='protobuf_unittest.AggregateService', + file=DESCRIPTOR, + index=1, + serialized_options=_b('\312\373\216;\023\022\021ServiceAnnotation'), + serialized_start=3287, + serialized_end=3440, + methods=[ + _descriptor.MethodDescriptor( + name='Method', + full_name='protobuf_unittest.AggregateService.Method', + index=0, + containing_service=None, + input_type=_AGGREGATEMESSAGE, + output_type=_AGGREGATEMESSAGE, + serialized_options=_b('\312\310\226;\022\022\020MethodAnnotation'), + ), +]) +_sym_db.RegisterServiceDescriptor(_AGGREGATESERVICE) + +DESCRIPTOR.services_by_name['AggregateService'] = _AGGREGATESERVICE + +TestServiceWithCustomOptions = service_reflection.GeneratedServiceType('TestServiceWithCustomOptions', (_service.Service,), dict( + DESCRIPTOR = _TESTSERVICEWITHCUSTOMOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + +TestServiceWithCustomOptions_Stub = service_reflection.GeneratedServiceStubType('TestServiceWithCustomOptions_Stub', (TestServiceWithCustomOptions,), dict( + DESCRIPTOR = _TESTSERVICEWITHCUSTOMOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + + +AggregateService = service_reflection.GeneratedServiceType('AggregateService', (_service.Service,), dict( + DESCRIPTOR = _AGGREGATESERVICE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + +AggregateService_Stub = service_reflection.GeneratedServiceStubType('AggregateService_Stub', (AggregateService,), dict( + DESCRIPTOR = _AGGREGATESERVICE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_import_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_import_pb2.py new file mode 100644 index 0000000..5812759 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_import_pb2.py @@ -0,0 +1,137 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_import.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_public_pb2 as google_dot_protobuf_dot_unittest__import__public__pb2 + +from google.protobuf.unittest_import_public_pb2 import * + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_import.proto', + package='protobuf_unittest_import', + syntax='proto2', + serialized_options=_b('\n\030com.google.protobuf.testH\001\370\001\001'), + serialized_pb=_b('\n%google/protobuf/unittest_import.proto\x12\x18protobuf_unittest_import\x1a,google/protobuf/unittest_import_public.proto\"\x1a\n\rImportMessage\x12\t\n\x01\x64\x18\x01 \x01(\x05*<\n\nImportEnum\x12\x0e\n\nIMPORT_FOO\x10\x07\x12\x0e\n\nIMPORT_BAR\x10\x08\x12\x0e\n\nIMPORT_BAZ\x10\t*1\n\x10ImportEnumForMap\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x42\x1f\n\x18\x63om.google.protobuf.testH\x01\xf8\x01\x01P\x00') + , + dependencies=[google_dot_protobuf_dot_unittest__import__public__pb2.DESCRIPTOR,], + public_dependencies=[google_dot_protobuf_dot_unittest__import__public__pb2.DESCRIPTOR,]) + +_IMPORTENUM = _descriptor.EnumDescriptor( + name='ImportEnum', + full_name='protobuf_unittest_import.ImportEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IMPORT_FOO', index=0, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IMPORT_BAR', index=1, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IMPORT_BAZ', index=2, number=9, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=141, + serialized_end=201, +) +_sym_db.RegisterEnumDescriptor(_IMPORTENUM) + +ImportEnum = enum_type_wrapper.EnumTypeWrapper(_IMPORTENUM) +_IMPORTENUMFORMAP = _descriptor.EnumDescriptor( + name='ImportEnumForMap', + full_name='protobuf_unittest_import.ImportEnumForMap', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOO', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=203, + serialized_end=252, +) +_sym_db.RegisterEnumDescriptor(_IMPORTENUMFORMAP) + +ImportEnumForMap = enum_type_wrapper.EnumTypeWrapper(_IMPORTENUMFORMAP) +IMPORT_FOO = 7 +IMPORT_BAR = 8 +IMPORT_BAZ = 9 +UNKNOWN = 0 +FOO = 1 +BAR = 2 + + + +_IMPORTMESSAGE = _descriptor.Descriptor( + name='ImportMessage', + full_name='protobuf_unittest_import.ImportMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest_import.ImportMessage.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=139, +) + +DESCRIPTOR.message_types_by_name['ImportMessage'] = _IMPORTMESSAGE +DESCRIPTOR.enum_types_by_name['ImportEnum'] = _IMPORTENUM +DESCRIPTOR.enum_types_by_name['ImportEnumForMap'] = _IMPORTENUMFORMAP +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ImportMessage = _reflection.GeneratedProtocolMessageType('ImportMessage', (_message.Message,), dict( + DESCRIPTOR = _IMPORTMESSAGE, + __module__ = 'google.protobuf.unittest_import_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_import.ImportMessage) + )) +_sym_db.RegisterMessage(ImportMessage) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_import_public_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_import_public_pb2.py new file mode 100644 index 0000000..3a07bef --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_import_public_pb2.py @@ -0,0 +1,70 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_import_public.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_import_public.proto', + package='protobuf_unittest_import', + syntax='proto2', + serialized_options=_b('\n\030com.google.protobuf.test'), + serialized_pb=_b('\n,google/protobuf/unittest_import_public.proto\x12\x18protobuf_unittest_import\" \n\x13PublicImportMessage\x12\t\n\x01\x65\x18\x01 \x01(\x05\x42\x1a\n\x18\x63om.google.protobuf.test') +) + + + + +_PUBLICIMPORTMESSAGE = _descriptor.Descriptor( + name='PublicImportMessage', + full_name='protobuf_unittest_import.PublicImportMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='e', full_name='protobuf_unittest_import.PublicImportMessage.e', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=74, + serialized_end=106, +) + +DESCRIPTOR.message_types_by_name['PublicImportMessage'] = _PUBLICIMPORTMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PublicImportMessage = _reflection.GeneratedProtocolMessageType('PublicImportMessage', (_message.Message,), dict( + DESCRIPTOR = _PUBLICIMPORTMESSAGE, + __module__ = 'google.protobuf.unittest_import_public_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_import.PublicImportMessage) + )) +_sym_db.RegisterMessage(PublicImportMessage) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_mset_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_mset_pb2.py new file mode 100644 index 0000000..f100110 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_mset_pb2.py @@ -0,0 +1,255 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_mset.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_mset_wire_format_pb2 as google_dot_protobuf_dot_unittest__mset__wire__format__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_mset.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=_b('H\001\370\001\001'), + serialized_pb=_b('\n#google/protobuf/unittest_mset.proto\x12\x11protobuf_unittest\x1a/google/protobuf/unittest_mset_wire_format.proto\"Z\n\x17TestMessageSetContainer\x12?\n\x0bmessage_set\x18\x01 \x01(\x0b\x32*.proto2_wireformat_unittest.TestMessageSet\"\x9f\x01\n\x18TestMessageSetExtension1\x12\t\n\x01i\x18\x0f \x01(\x05\x32x\n\x15message_set_extension\x12*.proto2_wireformat_unittest.TestMessageSet\x18\xb0\xa6^ \x01(\x0b\x32+.protobuf_unittest.TestMessageSetExtension1\"\xa1\x01\n\x18TestMessageSetExtension2\x12\x0b\n\x03str\x18\x19 \x01(\t2x\n\x15message_set_extension\x12*.proto2_wireformat_unittest.TestMessageSet\x18\xf9\xbb^ \x01(\x0b\x32+.protobuf_unittest.TestMessageSetExtension2\"n\n\rRawMessageSet\x12\x33\n\x04item\x18\x01 \x03(\n2%.protobuf_unittest.RawMessageSet.Item\x1a(\n\x04Item\x12\x0f\n\x07type_id\x18\x02 \x02(\x05\x12\x0f\n\x07message\x18\x03 \x02(\x0c\x42\x05H\x01\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__mset__wire__format__pb2.DESCRIPTOR,]) + + + + +_TESTMESSAGESETCONTAINER = _descriptor.Descriptor( + name='TestMessageSetContainer', + full_name='protobuf_unittest.TestMessageSetContainer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_set', full_name='protobuf_unittest.TestMessageSetContainer.message_set', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=107, + serialized_end=197, +) + + +_TESTMESSAGESETEXTENSION1 = _descriptor.Descriptor( + name='TestMessageSetExtension1', + full_name='protobuf_unittest.TestMessageSetExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.TestMessageSetExtension1.i', index=0, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_unittest.TestMessageSetExtension1.message_set_extension', index=0, + number=1545008, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=200, + serialized_end=359, +) + + +_TESTMESSAGESETEXTENSION2 = _descriptor.Descriptor( + name='TestMessageSetExtension2', + full_name='protobuf_unittest.TestMessageSetExtension2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='str', full_name='protobuf_unittest.TestMessageSetExtension2.str', index=0, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_unittest.TestMessageSetExtension2.message_set_extension', index=0, + number=1547769, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=362, + serialized_end=523, +) + + +_RAWMESSAGESET_ITEM = _descriptor.Descriptor( + name='Item', + full_name='protobuf_unittest.RawMessageSet.Item', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type_id', full_name='protobuf_unittest.RawMessageSet.Item.type_id', index=0, + number=2, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message', full_name='protobuf_unittest.RawMessageSet.Item.message', index=1, + number=3, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=595, + serialized_end=635, +) + +_RAWMESSAGESET = _descriptor.Descriptor( + name='RawMessageSet', + full_name='protobuf_unittest.RawMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='item', full_name='protobuf_unittest.RawMessageSet.item', index=0, + number=1, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_RAWMESSAGESET_ITEM, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=525, + serialized_end=635, +) + +_TESTMESSAGESETCONTAINER.fields_by_name['message_set'].message_type = google_dot_protobuf_dot_unittest__mset__wire__format__pb2._TESTMESSAGESET +_RAWMESSAGESET_ITEM.containing_type = _RAWMESSAGESET +_RAWMESSAGESET.fields_by_name['item'].message_type = _RAWMESSAGESET_ITEM +DESCRIPTOR.message_types_by_name['TestMessageSetContainer'] = _TESTMESSAGESETCONTAINER +DESCRIPTOR.message_types_by_name['TestMessageSetExtension1'] = _TESTMESSAGESETEXTENSION1 +DESCRIPTOR.message_types_by_name['TestMessageSetExtension2'] = _TESTMESSAGESETEXTENSION2 +DESCRIPTOR.message_types_by_name['RawMessageSet'] = _RAWMESSAGESET +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageSetContainer = _reflection.GeneratedProtocolMessageType('TestMessageSetContainer', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETCONTAINER, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageSetContainer) + )) +_sym_db.RegisterMessage(TestMessageSetContainer) + +TestMessageSetExtension1 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION1, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageSetExtension1) + )) +_sym_db.RegisterMessage(TestMessageSetExtension1) + +TestMessageSetExtension2 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension2', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION2, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageSetExtension2) + )) +_sym_db.RegisterMessage(TestMessageSetExtension2) + +RawMessageSet = _reflection.GeneratedProtocolMessageType('RawMessageSet', (_message.Message,), dict( + + Item = _reflection.GeneratedProtocolMessageType('Item', (_message.Message,), dict( + DESCRIPTOR = _RAWMESSAGESET_ITEM, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.RawMessageSet.Item) + )) + , + DESCRIPTOR = _RAWMESSAGESET, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.RawMessageSet) + )) +_sym_db.RegisterMessage(RawMessageSet) +_sym_db.RegisterMessage(RawMessageSet.Item) + +_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION1 +google_dot_protobuf_dot_unittest__mset__wire__format__pb2.TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension']) +_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION2 +google_dot_protobuf_dot_unittest__mset__wire__format__pb2.TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension']) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py new file mode 100644 index 0000000..b3eebad --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py @@ -0,0 +1,104 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_mset_wire_format.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_mset_wire_format.proto', + package='proto2_wireformat_unittest', + syntax='proto2', + serialized_options=_b('H\001\370\001\001\252\002!Google.ProtocolBuffers.TestProtos'), + serialized_pb=_b('\n/google/protobuf/unittest_mset_wire_format.proto\x12\x1aproto2_wireformat_unittest\"\x1e\n\x0eTestMessageSet*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\"d\n!TestMessageSetWireFormatContainer\x12?\n\x0bmessage_set\x18\x01 \x01(\x0b\x32*.proto2_wireformat_unittest.TestMessageSetB)H\x01\xf8\x01\x01\xaa\x02!Google.ProtocolBuffers.TestProtos') +) + + + + +_TESTMESSAGESET = _descriptor.Descriptor( + name='TestMessageSet', + full_name='proto2_wireformat_unittest.TestMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=79, + serialized_end=109, +) + + +_TESTMESSAGESETWIREFORMATCONTAINER = _descriptor.Descriptor( + name='TestMessageSetWireFormatContainer', + full_name='proto2_wireformat_unittest.TestMessageSetWireFormatContainer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_set', full_name='proto2_wireformat_unittest.TestMessageSetWireFormatContainer.message_set', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=111, + serialized_end=211, +) + +_TESTMESSAGESETWIREFORMATCONTAINER.fields_by_name['message_set'].message_type = _TESTMESSAGESET +DESCRIPTOR.message_types_by_name['TestMessageSet'] = _TESTMESSAGESET +DESCRIPTOR.message_types_by_name['TestMessageSetWireFormatContainer'] = _TESTMESSAGESETWIREFORMATCONTAINER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageSet = _reflection.GeneratedProtocolMessageType('TestMessageSet', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESET, + __module__ = 'google.protobuf.unittest_mset_wire_format_pb2' + # @@protoc_insertion_point(class_scope:proto2_wireformat_unittest.TestMessageSet) + )) +_sym_db.RegisterMessage(TestMessageSet) + +TestMessageSetWireFormatContainer = _reflection.GeneratedProtocolMessageType('TestMessageSetWireFormatContainer', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETWIREFORMATCONTAINER, + __module__ = 'google.protobuf.unittest_mset_wire_format_pb2' + # @@protoc_insertion_point(class_scope:proto2_wireformat_unittest.TestMessageSetWireFormatContainer) + )) +_sym_db.RegisterMessage(TestMessageSetWireFormatContainer) + + +DESCRIPTOR._options = None +_TESTMESSAGESET._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_import_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_import_pb2.py new file mode 100644 index 0000000..8bb9c3c --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_import_pb2.py @@ -0,0 +1,69 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_no_arena_import.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_no_arena_import.proto', + package='proto2_arena_unittest', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n.google/protobuf/unittest_no_arena_import.proto\x12\x15proto2_arena_unittest\"\'\n\x1aImportNoArenaNestedMessage\x12\t\n\x01\x64\x18\x01 \x01(\x05') +) + + + + +_IMPORTNOARENANESTEDMESSAGE = _descriptor.Descriptor( + name='ImportNoArenaNestedMessage', + full_name='proto2_arena_unittest.ImportNoArenaNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='proto2_arena_unittest.ImportNoArenaNestedMessage.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=73, + serialized_end=112, +) + +DESCRIPTOR.message_types_by_name['ImportNoArenaNestedMessage'] = _IMPORTNOARENANESTEDMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ImportNoArenaNestedMessage = _reflection.GeneratedProtocolMessageType('ImportNoArenaNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _IMPORTNOARENANESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_import_pb2' + # @@protoc_insertion_point(class_scope:proto2_arena_unittest.ImportNoArenaNestedMessage) + )) +_sym_db.RegisterMessage(ImportNoArenaNestedMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_pb2.py new file mode 100644 index 0000000..6fe69db --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_no_arena_pb2.py @@ -0,0 +1,911 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_no_arena.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_pb2 as google_dot_protobuf_dot_unittest__import__pb2 +try: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google_dot_protobuf_dot_unittest__import__public__pb2 +except AttributeError: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google.protobuf.unittest_import_public_pb2 +from google.protobuf import unittest_arena_pb2 as google_dot_protobuf_dot_unittest__arena__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_no_arena.proto', + package='protobuf_unittest_no_arena', + syntax='proto2', + serialized_options=_b('B\rUnittestProtoH\001\200\001\001\210\001\001\220\001\001\370\001\000\242\002\005NOARN'), + serialized_pb=_b('\n\'google/protobuf/unittest_no_arena.proto\x12\x1aprotobuf_unittest_no_arena\x1a%google/protobuf/unittest_import.proto\x1a$google/protobuf/unittest_arena.proto\"\xd0\x1a\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12M\n\roptionalgroup\x18\x10 \x01(\n26.protobuf_unittest_no_arena.TestAllTypes.OptionalGroup\x12W\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessage\x12L\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32*.protobuf_unittest_no_arena.ForeignMessage\x12H\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12Q\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32\x33.protobuf_unittest_no_arena.TestAllTypes.NestedEnum\x12\x46\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\'.protobuf_unittest_no_arena.ForeignEnum\x12\x42\n\x14optional_import_enum\x18\x17 \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12U\n\x1eoptional_public_import_message\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage\x12T\n\x10optional_message\x18\x1b \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12M\n\rrepeatedgroup\x18. \x03(\n26.protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup\x12W\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessage\x12L\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32*.protobuf_unittest_no_arena.ForeignMessage\x12H\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12Q\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32\x33.protobuf_unittest_no_arena.TestAllTypes.NestedEnum\x12\x46\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\'.protobuf_unittest_no_arena.ForeignEnum\x12\x42\n\x14repeated_import_enum\x18\x35 \x03(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12Y\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageB\x02(\x01\x12\x19\n\rdefault_int32\x18= \x01(\x05:\x02\x34\x31\x12\x19\n\rdefault_int64\x18> \x01(\x03:\x02\x34\x32\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint32\x18? \x01(\r:\x02\x34\x33\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint64\x18@ \x01(\x04:\x02\x34\x34\x12\x1b\n\x0e\x64\x65\x66\x61ult_sint32\x18\x41 \x01(\x11:\x03-45\x12\x1a\n\x0e\x64\x65\x66\x61ult_sint64\x18\x42 \x01(\x12:\x02\x34\x36\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed32\x18\x43 \x01(\x07:\x02\x34\x37\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed64\x18\x44 \x01(\x06:\x02\x34\x38\x12\x1c\n\x10\x64\x65\x66\x61ult_sfixed32\x18\x45 \x01(\x0f:\x02\x34\x39\x12\x1d\n\x10\x64\x65\x66\x61ult_sfixed64\x18\x46 \x01(\x10:\x03-50\x12\x1b\n\rdefault_float\x18G \x01(\x02:\x04\x35\x31.5\x12\x1d\n\x0e\x64\x65\x66\x61ult_double\x18H \x01(\x01:\x05\x35\x32\x30\x30\x30\x12\x1a\n\x0c\x64\x65\x66\x61ult_bool\x18I \x01(\x08:\x04true\x12\x1d\n\x0e\x64\x65\x66\x61ult_string\x18J \x01(\t:\x05hello\x12\x1c\n\rdefault_bytes\x18K \x01(\x0c:\x05world\x12U\n\x13\x64\x65\x66\x61ult_nested_enum\x18Q \x01(\x0e\x32\x33.protobuf_unittest_no_arena.TestAllTypes.NestedEnum:\x03\x42\x41R\x12R\n\x14\x64\x65\x66\x61ult_foreign_enum\x18R \x01(\x0e\x32\'.protobuf_unittest_no_arena.ForeignEnum:\x0b\x46OREIGN_BAR\x12M\n\x13\x64\x65\x66\x61ult_import_enum\x18S \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:\nIMPORT_BAR\x12%\n\x14\x64\x65\x66\x61ult_string_piece\x18T \x01(\t:\x03\x61\x62\x63\x42\x02\x08\x02\x12\x1d\n\x0c\x64\x65\x66\x61ult_cord\x18U \x01(\t:\x03\x31\x32\x33\x42\x02\x08\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12V\n\x14oneof_nested_message\x18p \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12_\n\x19lazy_oneof_nested_message\x18s \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageB\x02(\x01H\x00\x1a\x1b\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\x1a\x1a\n\rRepeatedGroup\x12\t\n\x01\x61\x18/ \x01(\x05\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_field\"\x1b\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\"P\n\x12TestNoArenaMessage\x12:\n\rarena_message\x18\x01 \x01(\x0b\x32#.proto2_arena_unittest.ArenaMessage*@\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x04\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x05\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x06\x42%B\rUnittestProtoH\x01\x80\x01\x01\x88\x01\x01\x90\x01\x01\xf8\x01\x00\xa2\x02\x05NOARN') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__arena__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='protobuf_unittest_no_arena.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3670, + serialized_end=3734, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +FOREIGN_FOO = 4 +FOREIGN_BAR = 5 +FOREIGN_BAZ = 6 + + +_TESTALLTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest_no_arena.TestAllTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3485, + serialized_end=3542, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPES_NESTEDENUM) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest_no_arena.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest_no_arena.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3400, + serialized_end=3427, +) + +_TESTALLTYPES_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest_no_arena.TestAllTypes.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest_no_arena.TestAllTypes.OptionalGroup.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3429, + serialized_end=3455, +) + +_TESTALLTYPES_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup.a', index=0, + number=47, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3457, + serialized_end=3483, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='protobuf_unittest_no_arena.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest_no_arena.TestAllTypes.optionalgroup', index=15, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_nested_message', index=16, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_foreign_message', index=17, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_import_message', index=18, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_nested_enum', index=19, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_foreign_enum', index=20, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_import_enum', index=21, + number=23, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_string_piece', index=22, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_cord', index=23, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_public_import_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_public_import_message', index=24, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_message', index=25, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_int32', index=26, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_int64', index=27, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_uint32', index=28, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_uint64', index=29, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sint32', index=30, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sint64', index=31, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_fixed32', index=32, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_fixed64', index=33, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sfixed32', index=34, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sfixed64', index=35, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_float', index=36, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_double', index=37, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_bool', index=38, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_string', index=39, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_bytes', index=40, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest_no_arena.TestAllTypes.repeatedgroup', index=41, + number=46, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_nested_message', index=42, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_foreign_message', index=43, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_import_message', index=44, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_nested_enum', index=45, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_foreign_enum', index=46, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_import_enum', index=47, + number=53, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_string_piece', index=48, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_cord', index=49, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_lazy_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_lazy_message', index=50, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_int32', index=51, + number=61, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=41, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_int64', index=52, + number=62, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_uint32', index=53, + number=63, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=43, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_uint64', index=54, + number=64, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=44, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sint32', index=55, + number=65, type=17, cpp_type=1, label=1, + has_default_value=True, default_value=-45, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sint64', index=56, + number=66, type=18, cpp_type=2, label=1, + has_default_value=True, default_value=46, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_fixed32', index=57, + number=67, type=7, cpp_type=3, label=1, + has_default_value=True, default_value=47, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_fixed64', index=58, + number=68, type=6, cpp_type=4, label=1, + has_default_value=True, default_value=48, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sfixed32', index=59, + number=69, type=15, cpp_type=1, label=1, + has_default_value=True, default_value=49, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sfixed64', index=60, + number=70, type=16, cpp_type=2, label=1, + has_default_value=True, default_value=-50, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_float', full_name='protobuf_unittest_no_arena.TestAllTypes.default_float', index=61, + number=71, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(51.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_double', full_name='protobuf_unittest_no_arena.TestAllTypes.default_double', index=62, + number=72, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(52000), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bool', full_name='protobuf_unittest_no_arena.TestAllTypes.default_bool', index=63, + number=73, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string', full_name='protobuf_unittest_no_arena.TestAllTypes.default_string', index=64, + number=74, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.default_bytes', index=65, + number=75, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("world"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_nested_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.default_nested_enum', index=66, + number=81, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_foreign_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.default_foreign_enum', index=67, + number=82, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_import_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.default_import_enum', index=68, + number=83, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=8, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string_piece', full_name='protobuf_unittest_no_arena.TestAllTypes.default_string_piece', index=69, + number=84, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("abc").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_cord', full_name='protobuf_unittest_no_arena.TestAllTypes.default_cord', index=70, + number=85, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("123").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_uint32', index=71, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_nested_message', index=72, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_string', index=73, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_bytes', index=74, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lazy_oneof_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.lazy_oneof_nested_message', index=75, + number=115, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, _TESTALLTYPES_OPTIONALGROUP, _TESTALLTYPES_REPEATEDGROUP, ], + enum_types=[ + _TESTALLTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=149, + serialized_end=3557, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='protobuf_unittest_no_arena.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest_no_arena.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3559, + serialized_end=3586, +) + + +_TESTNOARENAMESSAGE = _descriptor.Descriptor( + name='TestNoArenaMessage', + full_name='protobuf_unittest_no_arena.TestNoArenaMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='arena_message', full_name='protobuf_unittest_no_arena.TestNoArenaMessage.arena_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3588, + serialized_end=3668, +) + +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES_OPTIONALGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES_REPEATEDGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['optionalgroup'].message_type = _TESTALLTYPES_OPTIONALGROUP +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['optional_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['optional_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['optional_public_import_message'].message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeatedgroup'].message_type = _TESTALLTYPES_REPEATEDGROUP +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['repeated_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['repeated_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['repeated_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['default_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['default_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['default_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['lazy_oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES_NESTEDENUM.containing_type = _TESTALLTYPES +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_uint32']) +_TESTALLTYPES.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_nested_message']) +_TESTALLTYPES.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_string']) +_TESTALLTYPES.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_bytes']) +_TESTALLTYPES.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['lazy_oneof_nested_message']) +_TESTALLTYPES.fields_by_name['lazy_oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTNOARENAMESSAGE.fields_by_name['arena_message'].message_type = google_dot_protobuf_dot_unittest__arena__pb2._ARENAMESSAGE +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestNoArenaMessage'] = _TESTNOARENAMESSAGE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes.NestedMessage) + )) + , + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes.OptionalGroup) + )) + , + + RepeatedGroup = _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_REPEATEDGROUP, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) +_sym_db.RegisterMessage(TestAllTypes.OptionalGroup) +_sym_db.RegisterMessage(TestAllTypes.RepeatedGroup) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestNoArenaMessage = _reflection.GeneratedProtocolMessageType('TestNoArenaMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTNOARENAMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestNoArenaMessage) + )) +_sym_db.RegisterMessage(TestNoArenaMessage) + + +DESCRIPTOR._options = None +_TESTALLTYPES.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPES.fields_by_name['optional_cord']._options = None +_TESTALLTYPES.fields_by_name['optional_message']._options = None +_TESTALLTYPES.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPES.fields_by_name['repeated_cord']._options = None +_TESTALLTYPES.fields_by_name['repeated_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['default_string_piece']._options = None +_TESTALLTYPES.fields_by_name['default_cord']._options = None +_TESTALLTYPES.fields_by_name['lazy_oneof_nested_message']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_no_generic_services_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_no_generic_services_pb2.py new file mode 100644 index 0000000..6746a67 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_no_generic_services_pb2.py @@ -0,0 +1,125 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_no_generic_services.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_no_generic_services.proto', + package='google.protobuf.no_generic_services_test', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n2google/protobuf/unittest_no_generic_services.proto\x12(google.protobuf.no_generic_services_test\"#\n\x0bTestMessage\x12\t\n\x01\x61\x18\x01 \x01(\x05*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02*\x13\n\x08TestEnum\x12\x07\n\x03\x46OO\x10\x01\x32\x82\x01\n\x0bTestService\x12s\n\x03\x46oo\x12\x35.google.protobuf.no_generic_services_test.TestMessage\x1a\x35.google.protobuf.no_generic_services_test.TestMessage:N\n\x0etest_extension\x12\x35.google.protobuf.no_generic_services_test.TestMessage\x18\xe8\x07 \x01(\x05') +) + +_TESTENUM = _descriptor.EnumDescriptor( + name='TestEnum', + full_name='google.protobuf.no_generic_services_test.TestEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=133, + serialized_end=152, +) +_sym_db.RegisterEnumDescriptor(_TESTENUM) + +TestEnum = enum_type_wrapper.EnumTypeWrapper(_TESTENUM) +FOO = 1 + +TEST_EXTENSION_FIELD_NUMBER = 1000 +test_extension = _descriptor.FieldDescriptor( + name='test_extension', full_name='google.protobuf.no_generic_services_test.test_extension', index=0, + number=1000, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTMESSAGE = _descriptor.Descriptor( + name='TestMessage', + full_name='google.protobuf.no_generic_services_test.TestMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='google.protobuf.no_generic_services_test.TestMessage.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=96, + serialized_end=131, +) + +DESCRIPTOR.message_types_by_name['TestMessage'] = _TESTMESSAGE +DESCRIPTOR.enum_types_by_name['TestEnum'] = _TESTENUM +DESCRIPTOR.extensions_by_name['test_extension'] = test_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessage = _reflection.GeneratedProtocolMessageType('TestMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGE, + __module__ = 'google.protobuf.unittest_no_generic_services_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.no_generic_services_test.TestMessage) + )) +_sym_db.RegisterMessage(TestMessage) + +TestMessage.RegisterExtension(test_extension) + + +_TESTSERVICE = _descriptor.ServiceDescriptor( + name='TestService', + full_name='google.protobuf.no_generic_services_test.TestService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=155, + serialized_end=285, + methods=[ + _descriptor.MethodDescriptor( + name='Foo', + full_name='google.protobuf.no_generic_services_test.TestService.Foo', + index=0, + containing_service=None, + input_type=_TESTMESSAGE, + output_type=_TESTMESSAGE, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_TESTSERVICE) + +DESCRIPTOR.services_by_name['TestService'] = _TESTSERVICE + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_pb2.py new file mode 100644 index 0000000..1a4a7db --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_pb2.py @@ -0,0 +1,7082 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import service as _service +from google.protobuf import service_reflection +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_pb2 as google_dot_protobuf_dot_unittest__import__pb2 +try: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google_dot_protobuf_dot_unittest__import__public__pb2 +except AttributeError: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google.protobuf.unittest_import_public_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=_b('B\rUnittestProtoH\001\200\001\001\210\001\001\220\001\001\370\001\001'), + serialized_pb=_b('\n\x1egoogle/protobuf/unittest.proto\x12\x11protobuf_unittest\x1a%google/protobuf/unittest_import.proto\"\xed\x18\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12\x44\n\roptionalgroup\x18\x10 \x01(\n2-.protobuf_unittest.TestAllTypes.OptionalGroup\x12N\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage\x12\x43\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12H\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12H\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum\x12=\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x42\n\x14optional_import_enum\x18\x17 \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12U\n\x1eoptional_public_import_message\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage\x12P\n\x15optional_lazy_message\x18\x1b \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12\x44\n\rrepeatedgroup\x18. \x03(\n2-.protobuf_unittest.TestAllTypes.RepeatedGroup\x12N\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage\x12\x43\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32!.protobuf_unittest.ForeignMessage\x12H\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12H\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum\x12=\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x42\n\x14repeated_import_enum\x18\x35 \x03(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12P\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12\x19\n\rdefault_int32\x18= \x01(\x05:\x02\x34\x31\x12\x19\n\rdefault_int64\x18> \x01(\x03:\x02\x34\x32\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint32\x18? \x01(\r:\x02\x34\x33\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint64\x18@ \x01(\x04:\x02\x34\x34\x12\x1b\n\x0e\x64\x65\x66\x61ult_sint32\x18\x41 \x01(\x11:\x03-45\x12\x1a\n\x0e\x64\x65\x66\x61ult_sint64\x18\x42 \x01(\x12:\x02\x34\x36\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed32\x18\x43 \x01(\x07:\x02\x34\x37\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed64\x18\x44 \x01(\x06:\x02\x34\x38\x12\x1c\n\x10\x64\x65\x66\x61ult_sfixed32\x18\x45 \x01(\x0f:\x02\x34\x39\x12\x1d\n\x10\x64\x65\x66\x61ult_sfixed64\x18\x46 \x01(\x10:\x03-50\x12\x1b\n\rdefault_float\x18G \x01(\x02:\x04\x35\x31.5\x12\x1d\n\x0e\x64\x65\x66\x61ult_double\x18H \x01(\x01:\x05\x35\x32\x30\x30\x30\x12\x1a\n\x0c\x64\x65\x66\x61ult_bool\x18I \x01(\x08:\x04true\x12\x1d\n\x0e\x64\x65\x66\x61ult_string\x18J \x01(\t:\x05hello\x12\x1c\n\rdefault_bytes\x18K \x01(\x0c:\x05world\x12L\n\x13\x64\x65\x66\x61ult_nested_enum\x18Q \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:\x03\x42\x41R\x12I\n\x14\x64\x65\x66\x61ult_foreign_enum\x18R \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:\x0b\x46OREIGN_BAR\x12M\n\x13\x64\x65\x66\x61ult_import_enum\x18S \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:\nIMPORT_BAR\x12%\n\x14\x64\x65\x66\x61ult_string_piece\x18T \x01(\t:\x03\x61\x62\x63\x42\x02\x08\x02\x12\x1d\n\x0c\x64\x65\x66\x61ult_cord\x18U \x01(\t:\x03\x31\x32\x33\x42\x02\x08\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12M\n\x14oneof_nested_message\x18p \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x1a\x1b\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\x1a\x1a\n\rRepeatedGroup\x12\t\n\x01\x61\x18/ \x01(\x05\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_field\"\xbb\x01\n\x12NestedTestAllTypes\x12\x34\n\x05\x63hild\x18\x01 \x01(\x0b\x32%.protobuf_unittest.NestedTestAllTypes\x12\x30\n\x07payload\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12=\n\x0erepeated_child\x18\x03 \x03(\x0b\x32%.protobuf_unittest.NestedTestAllTypes\"m\n\x14TestDeprecatedFields\x12\x1c\n\x10\x64\x65precated_int32\x18\x01 \x01(\x05\x42\x02\x18\x01\x12\'\n\x19\x64\x65precated_int32_in_oneof\x18\x02 \x01(\x05\x42\x02\x18\x01H\x00\x42\x0e\n\x0coneof_fields\"\x1b\n\x15TestDeprecatedMessage:\x02\x18\x01\"&\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\x12\t\n\x01\x64\x18\x02 \x01(\x05\"0\n\x12TestReservedFieldsJ\x04\x08\x02\x10\x03J\x04\x08\x0f\x10\x10J\x04\x08\t\x10\x0cR\x03\x62\x61rR\x03\x62\x61z\"\x1d\n\x11TestAllExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"$\n\x17OptionalGroup_extension\x12\t\n\x01\x61\x18\x11 \x01(\x05\"$\n\x17RepeatedGroup_extension\x12\t\n\x01\x61\x18/ \x01(\x05\"\xa9\x01\n\tTestGroup\x12\x41\n\roptionalgroup\x18\x10 \x01(\n2*.protobuf_unittest.TestGroup.OptionalGroup\x12=\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\"\x1e\n\x12TestGroupExtension*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"\xb7\x03\n\x13TestNestedExtension\x1a$\n\x17OptionalGroup_extension\x12\t\n\x01\x61\x18\x11 \x01(\x05\x32\x39\n\x04test\x12$.protobuf_unittest.TestAllExtensions\x18\xea\x07 \x01(\t:\x04test2F\n\x17nested_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18\xeb\x07 \x01(\t2\x86\x01\n\x17optionalgroup_extension\x12%.protobuf_unittest.TestGroupExtension\x18\x10 \x01(\n2>.protobuf_unittest.TestNestedExtension.OptionalGroup_extension2n\n\x1foptional_foreign_enum_extension\x12%.protobuf_unittest.TestGroupExtension\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\"\xd5\x05\n\x0cTestRequired\x12\t\n\x01\x61\x18\x01 \x02(\x05\x12\x0e\n\x06\x64ummy2\x18\x02 \x01(\x05\x12\t\n\x01\x62\x18\x03 \x02(\x05\x12\x0e\n\x06\x64ummy4\x18\x04 \x01(\x05\x12\x0e\n\x06\x64ummy5\x18\x05 \x01(\x05\x12\x0e\n\x06\x64ummy6\x18\x06 \x01(\x05\x12\x0e\n\x06\x64ummy7\x18\x07 \x01(\x05\x12\x0e\n\x06\x64ummy8\x18\x08 \x01(\x05\x12\x0e\n\x06\x64ummy9\x18\t \x01(\x05\x12\x0f\n\x07\x64ummy10\x18\n \x01(\x05\x12\x0f\n\x07\x64ummy11\x18\x0b \x01(\x05\x12\x0f\n\x07\x64ummy12\x18\x0c \x01(\x05\x12\x0f\n\x07\x64ummy13\x18\r \x01(\x05\x12\x0f\n\x07\x64ummy14\x18\x0e \x01(\x05\x12\x0f\n\x07\x64ummy15\x18\x0f \x01(\x05\x12\x0f\n\x07\x64ummy16\x18\x10 \x01(\x05\x12\x0f\n\x07\x64ummy17\x18\x11 \x01(\x05\x12\x0f\n\x07\x64ummy18\x18\x12 \x01(\x05\x12\x0f\n\x07\x64ummy19\x18\x13 \x01(\x05\x12\x0f\n\x07\x64ummy20\x18\x14 \x01(\x05\x12\x0f\n\x07\x64ummy21\x18\x15 \x01(\x05\x12\x0f\n\x07\x64ummy22\x18\x16 \x01(\x05\x12\x0f\n\x07\x64ummy23\x18\x17 \x01(\x05\x12\x0f\n\x07\x64ummy24\x18\x18 \x01(\x05\x12\x0f\n\x07\x64ummy25\x18\x19 \x01(\x05\x12\x0f\n\x07\x64ummy26\x18\x1a \x01(\x05\x12\x0f\n\x07\x64ummy27\x18\x1b \x01(\x05\x12\x0f\n\x07\x64ummy28\x18\x1c \x01(\x05\x12\x0f\n\x07\x64ummy29\x18\x1d \x01(\x05\x12\x0f\n\x07\x64ummy30\x18\x1e \x01(\x05\x12\x0f\n\x07\x64ummy31\x18\x1f \x01(\x05\x12\x0f\n\x07\x64ummy32\x18 \x01(\x05\x12\t\n\x01\x63\x18! \x02(\x05\x32V\n\x06single\x12$.protobuf_unittest.TestAllExtensions\x18\xe8\x07 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired2U\n\x05multi\x12$.protobuf_unittest.TestAllExtensions\x18\xe9\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestRequired\"\x9a\x01\n\x13TestRequiredForeign\x12\x39\n\x10optional_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\x39\n\x10repeated_message\x18\x02 \x03(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\r\n\x05\x64ummy\x18\x03 \x01(\x05\"\xc6\x01\n\x13TestRequiredMessage\x12\x39\n\x10optional_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\x39\n\x10repeated_message\x18\x02 \x03(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\x39\n\x10required_message\x18\x03 \x02(\x0b\x32\x1f.protobuf_unittest.TestRequired\"Z\n\x11TestForeignNested\x12\x45\n\x0e\x66oreign_nested\x18\x01 \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage\"\x12\n\x10TestEmptyMessage\"*\n\x1eTestEmptyMessageWithExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"7\n\x1bTestMultipleExtensionRanges*\x04\x08*\x10+*\x06\x08\xaf \x10\x94!*\n\x08\x80\x80\x04\x10\x80\x80\x80\x80\x02\"4\n\x18TestReallyLargeTagNumber\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\r\n\x02\x62\x62\x18\xff\xff\xff\x7f \x01(\x05\"U\n\x14TestRecursiveMessage\x12\x32\n\x01\x61\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestRecursiveMessage\x12\t\n\x01i\x18\x02 \x01(\x05\"\xe1\x02\n\x14TestMutualRecursionA\x12\x33\n\x02\x62\x62\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestMutualRecursionB\x12\x42\n\x08subgroup\x18\x02 \x01(\n20.protobuf_unittest.TestMutualRecursionA.SubGroup\x1a@\n\nSubMessage\x12\x32\n\x01\x62\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestMutualRecursionB\x1a\x8d\x01\n\x08SubGroup\x12G\n\x0bsub_message\x18\x03 \x01(\x0b\x32\x32.protobuf_unittest.TestMutualRecursionA.SubMessage\x12\x38\n\x0fnot_in_this_scc\x18\x04 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\"b\n\x14TestMutualRecursionB\x12\x32\n\x01\x61\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestMutualRecursionA\x12\x16\n\x0eoptional_int32\x18\x02 \x01(\x05\"\xca\x01\n\x11TestIsInitialized\x12\x44\n\x0bsub_message\x18\x01 \x01(\x0b\x32/.protobuf_unittest.TestIsInitialized.SubMessage\x1ao\n\nSubMessage\x12J\n\x08subgroup\x18\x01 \x01(\n28.protobuf_unittest.TestIsInitialized.SubMessage.SubGroup\x1a\x15\n\x08SubGroup\x12\t\n\x01i\x18\x02 \x02(\x05\"\xb3\x01\n\x12TestDupFieldNumber\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\x36\n\x03\x66oo\x18\x02 \x01(\n2).protobuf_unittest.TestDupFieldNumber.Foo\x12\x36\n\x03\x62\x61r\x18\x03 \x01(\n2).protobuf_unittest.TestDupFieldNumber.Bar\x1a\x10\n\x03\x46oo\x12\t\n\x01\x61\x18\x01 \x01(\x05\x1a\x10\n\x03\x42\x61r\x12\t\n\x01\x61\x18\x01 \x01(\x05\"L\n\x10TestEagerMessage\x12\x38\n\x0bsub_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesB\x02(\x00\"K\n\x0fTestLazyMessage\x12\x38\n\x0bsub_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesB\x02(\x01\"\x80\x02\n\x18TestNestedMessageHasBits\x12Z\n\x17optional_nested_message\x18\x01 \x01(\x0b\x32\x39.protobuf_unittest.TestNestedMessageHasBits.NestedMessage\x1a\x87\x01\n\rNestedMessage\x12$\n\x1cnestedmessage_repeated_int32\x18\x01 \x03(\x05\x12P\n%nestedmessage_repeated_foreignmessage\x18\x02 \x03(\x0b\x32!.protobuf_unittest.ForeignMessage\"\xe5\x03\n\x17TestCamelCaseFieldNames\x12\x16\n\x0ePrimitiveField\x18\x01 \x01(\x05\x12\x13\n\x0bStringField\x18\x02 \x01(\t\x12\x31\n\tEnumField\x18\x03 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x37\n\x0cMessageField\x18\x04 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12\x1c\n\x10StringPieceField\x18\x05 \x01(\tB\x02\x08\x02\x12\x15\n\tCordField\x18\x06 \x01(\tB\x02\x08\x01\x12\x1e\n\x16RepeatedPrimitiveField\x18\x07 \x03(\x05\x12\x1b\n\x13RepeatedStringField\x18\x08 \x03(\t\x12\x39\n\x11RepeatedEnumField\x18\t \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12?\n\x14RepeatedMessageField\x18\n \x03(\x0b\x32!.protobuf_unittest.ForeignMessage\x12$\n\x18RepeatedStringPieceField\x18\x0b \x03(\tB\x02\x08\x02\x12\x1d\n\x11RepeatedCordField\x18\x0c \x03(\tB\x02\x08\x01\"\xd5\x01\n\x12TestFieldOrderings\x12\x11\n\tmy_string\x18\x0b \x01(\t\x12\x0e\n\x06my_int\x18\x01 \x01(\x03\x12\x10\n\x08my_float\x18\x65 \x01(\x02\x12U\n\x17optional_nested_message\x18\xc8\x01 \x01(\x0b\x32\x33.protobuf_unittest.TestFieldOrderings.NestedMessage\x1a\'\n\rNestedMessage\x12\n\n\x02oo\x18\x02 \x01(\x03\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05*\x04\x08\x02\x10\x0b*\x04\x08\x0c\x10\x65\"\x9c\x01\n\x17TestExtensionOrderings1\x12\x11\n\tmy_string\x18\x01 \x01(\t2n\n\x13test_ext_orderings1\x12%.protobuf_unittest.TestFieldOrderings\x18\r \x01(\x0b\x32*.protobuf_unittest.TestExtensionOrderings1\"\xd4\x02\n\x17TestExtensionOrderings2\x12\x11\n\tmy_string\x18\x01 \x01(\t\x1a\xb5\x01\n\x17TestExtensionOrderings3\x12\x11\n\tmy_string\x18\x01 \x01(\t2\x86\x01\n\x13test_ext_orderings3\x12%.protobuf_unittest.TestFieldOrderings\x18\x0e \x01(\x0b\x32\x42.protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings32n\n\x13test_ext_orderings2\x12%.protobuf_unittest.TestFieldOrderings\x18\x0c \x01(\x0b\x32*.protobuf_unittest.TestExtensionOrderings2\"\xb6\x07\n\x18TestExtremeDefaultValues\x12?\n\rescaped_bytes\x18\x01 \x01(\x0c:(\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\\376\x12 \n\x0clarge_uint32\x18\x02 \x01(\r:\n4294967295\x12*\n\x0clarge_uint64\x18\x03 \x01(\x04:\x14\x31\x38\x34\x34\x36\x37\x34\x34\x30\x37\x33\x37\x30\x39\x35\x35\x31\x36\x31\x35\x12 \n\x0bsmall_int32\x18\x04 \x01(\x05:\x0b-2147483647\x12)\n\x0bsmall_int64\x18\x05 \x01(\x03:\x14-9223372036854775807\x12\'\n\x12really_small_int32\x18\x15 \x01(\x05:\x0b-2147483648\x12\x30\n\x12really_small_int64\x18\x16 \x01(\x03:\x14-9223372036854775808\x12\x18\n\x0butf8_string\x18\x06 \x01(\t:\x03\xe1\x88\xb4\x12\x15\n\nzero_float\x18\x07 \x01(\x02:\x01\x30\x12\x14\n\tone_float\x18\x08 \x01(\x02:\x01\x31\x12\x18\n\x0bsmall_float\x18\t \x01(\x02:\x03\x31.5\x12\x1e\n\x12negative_one_float\x18\n \x01(\x02:\x02-1\x12\x1c\n\x0enegative_float\x18\x0b \x01(\x02:\x04-1.5\x12\x1a\n\x0blarge_float\x18\x0c \x01(\x02:\x05\x32\x65+08\x12$\n\x14small_negative_float\x18\r \x01(\x02:\x06-8e-28\x12\x17\n\ninf_double\x18\x0e \x01(\x01:\x03inf\x12\x1c\n\x0eneg_inf_double\x18\x0f \x01(\x01:\x04-inf\x12\x17\n\nnan_double\x18\x10 \x01(\x01:\x03nan\x12\x16\n\tinf_float\x18\x11 \x01(\x02:\x03inf\x12\x1b\n\rneg_inf_float\x18\x12 \x01(\x02:\x04-inf\x12\x16\n\tnan_float\x18\x13 \x01(\x02:\x03nan\x12+\n\x0c\x63pp_trigraph\x18\x14 \x01(\t:\x15? ? ?? ?? ??? ??/ ??-\x12 \n\x10string_with_zero\x18\x17 \x01(\t:\x06hel\x00lo\x12\"\n\x0f\x62ytes_with_zero\x18\x18 \x01(\x0c:\twor\\000ld\x12(\n\x16string_piece_with_zero\x18\x19 \x01(\t:\x04\x61\x62\x00\x63\x42\x02\x08\x02\x12 \n\x0e\x63ord_with_zero\x18\x1a \x01(\t:\x04\x31\x32\x00\x33\x42\x02\x08\x01\x12&\n\x12replacement_string\x18\x1b \x01(\t:\n${unknown}\"K\n\x11SparseEnumMessage\x12\x36\n\x0bsparse_enum\x18\x01 \x01(\x0e\x32!.protobuf_unittest.TestSparseEnum\"\x19\n\tOneString\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"\x1a\n\nMoreString\x12\x0c\n\x04\x64\x61ta\x18\x01 \x03(\t\"\x18\n\x08OneBytes\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\"\x19\n\tMoreBytes\x12\x0c\n\x04\x64\x61ta\x18\x01 \x03(\x0c\"\x1c\n\x0cInt32Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x05\"\x1d\n\rUint32Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\r\"\x1c\n\x0cInt64Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x03\"\x1d\n\rUint64Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x04\"\x1b\n\x0b\x42oolMessage\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x08\"\xd0\x01\n\tTestOneof\x12\x11\n\x07\x66oo_int\x18\x01 \x01(\x05H\x00\x12\x14\n\nfoo_string\x18\x02 \x01(\tH\x00\x12\x36\n\x0b\x66oo_message\x18\x03 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesH\x00\x12\x39\n\x08\x66oogroup\x18\x04 \x01(\n2%.protobuf_unittest.TestOneof.FooGroupH\x00\x1a \n\x08\x46ooGroup\x12\t\n\x01\x61\x18\x05 \x01(\x05\x12\t\n\x01\x62\x18\x06 \x01(\tB\x05\n\x03\x66oo\"\xe7\x01\n\x1cTestOneofBackwardsCompatible\x12\x0f\n\x07\x66oo_int\x18\x01 \x01(\x05\x12\x12\n\nfoo_string\x18\x02 \x01(\t\x12\x34\n\x0b\x66oo_message\x18\x03 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12J\n\x08\x66oogroup\x18\x04 \x01(\n28.protobuf_unittest.TestOneofBackwardsCompatible.FooGroup\x1a \n\x08\x46ooGroup\x12\t\n\x01\x61\x18\x05 \x01(\x05\x12\t\n\x01\x62\x18\x06 \x01(\t\"\x9e\x06\n\nTestOneof2\x12\x11\n\x07\x66oo_int\x18\x01 \x01(\x05H\x00\x12\x14\n\nfoo_string\x18\x02 \x01(\tH\x00\x12\x16\n\x08\x66oo_cord\x18\x03 \x01(\tB\x02\x08\x01H\x00\x12\x1e\n\x10\x66oo_string_piece\x18\x04 \x01(\tB\x02\x08\x02H\x00\x12\x13\n\tfoo_bytes\x18\x05 \x01(\x0cH\x00\x12<\n\x08\x66oo_enum\x18\x06 \x01(\x0e\x32(.protobuf_unittest.TestOneof2.NestedEnumH\x00\x12\x42\n\x0b\x66oo_message\x18\x07 \x01(\x0b\x32+.protobuf_unittest.TestOneof2.NestedMessageH\x00\x12:\n\x08\x66oogroup\x18\x08 \x01(\n2&.protobuf_unittest.TestOneof2.FooGroupH\x00\x12K\n\x10\x66oo_lazy_message\x18\x0b \x01(\x0b\x32+.protobuf_unittest.TestOneof2.NestedMessageB\x02(\x01H\x00\x12\x14\n\x07\x62\x61r_int\x18\x0c \x01(\x05:\x01\x35H\x01\x12\x1c\n\nbar_string\x18\r \x01(\t:\x06STRINGH\x01\x12\x1c\n\x08\x62\x61r_cord\x18\x0e \x01(\t:\x04\x43ORDB\x02\x08\x01H\x01\x12&\n\x10\x62\x61r_string_piece\x18\x0f \x01(\t:\x06SPIECEB\x02\x08\x02H\x01\x12\x1a\n\tbar_bytes\x18\x10 \x01(\x0c:\x05\x42YTESH\x01\x12\x41\n\x08\x62\x61r_enum\x18\x11 \x01(\x0e\x32(.protobuf_unittest.TestOneof2.NestedEnum:\x03\x42\x41RH\x01\x12\x0f\n\x07\x62\x61z_int\x18\x12 \x01(\x05\x12\x17\n\nbaz_string\x18\x13 \x01(\t:\x03\x42\x41Z\x1a \n\x08\x46ooGroup\x12\t\n\x01\x61\x18\t \x01(\x05\x12\t\n\x01\x62\x18\n \x01(\t\x1a\x33\n\rNestedMessage\x12\x0f\n\x07qux_int\x18\x01 \x01(\x03\x12\x11\n\tcorge_int\x18\x02 \x03(\x05\"\'\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x42\x05\n\x03\x66ooB\x05\n\x03\x62\x61r\"\xb8\x01\n\x11TestRequiredOneof\x12\x11\n\x07\x66oo_int\x18\x01 \x01(\x05H\x00\x12\x14\n\nfoo_string\x18\x02 \x01(\tH\x00\x12I\n\x0b\x66oo_message\x18\x03 \x01(\x0b\x32\x32.protobuf_unittest.TestRequiredOneof.NestedMessageH\x00\x1a(\n\rNestedMessage\x12\x17\n\x0frequired_double\x18\x01 \x02(\x01\x42\x05\n\x03\x66oo\"\xaa\x03\n\x0fTestPackedTypes\x12\x18\n\x0cpacked_int32\x18Z \x03(\x05\x42\x02\x10\x01\x12\x18\n\x0cpacked_int64\x18[ \x03(\x03\x42\x02\x10\x01\x12\x19\n\rpacked_uint32\x18\\ \x03(\rB\x02\x10\x01\x12\x19\n\rpacked_uint64\x18] \x03(\x04\x42\x02\x10\x01\x12\x19\n\rpacked_sint32\x18^ \x03(\x11\x42\x02\x10\x01\x12\x19\n\rpacked_sint64\x18_ \x03(\x12\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed32\x18` \x03(\x07\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed64\x18\x61 \x03(\x06\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed32\x18\x62 \x03(\x0f\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed64\x18\x63 \x03(\x10\x42\x02\x10\x01\x12\x18\n\x0cpacked_float\x18\x64 \x03(\x02\x42\x02\x10\x01\x12\x19\n\rpacked_double\x18\x65 \x03(\x01\x42\x02\x10\x01\x12\x17\n\x0bpacked_bool\x18\x66 \x03(\x08\x42\x02\x10\x01\x12\x37\n\x0bpacked_enum\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x01\"\xc8\x03\n\x11TestUnpackedTypes\x12\x1a\n\x0eunpacked_int32\x18Z \x03(\x05\x42\x02\x10\x00\x12\x1a\n\x0eunpacked_int64\x18[ \x03(\x03\x42\x02\x10\x00\x12\x1b\n\x0funpacked_uint32\x18\\ \x03(\rB\x02\x10\x00\x12\x1b\n\x0funpacked_uint64\x18] \x03(\x04\x42\x02\x10\x00\x12\x1b\n\x0funpacked_sint32\x18^ \x03(\x11\x42\x02\x10\x00\x12\x1b\n\x0funpacked_sint64\x18_ \x03(\x12\x42\x02\x10\x00\x12\x1c\n\x10unpacked_fixed32\x18` \x03(\x07\x42\x02\x10\x00\x12\x1c\n\x10unpacked_fixed64\x18\x61 \x03(\x06\x42\x02\x10\x00\x12\x1d\n\x11unpacked_sfixed32\x18\x62 \x03(\x0f\x42\x02\x10\x00\x12\x1d\n\x11unpacked_sfixed64\x18\x63 \x03(\x10\x42\x02\x10\x00\x12\x1a\n\x0eunpacked_float\x18\x64 \x03(\x02\x42\x02\x10\x00\x12\x1b\n\x0funpacked_double\x18\x65 \x03(\x01\x42\x02\x10\x00\x12\x19\n\runpacked_bool\x18\x66 \x03(\x08\x42\x02\x10\x00\x12\x39\n\runpacked_enum\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x00\" \n\x14TestPackedExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"\"\n\x16TestUnpackedExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"\x99\x04\n\x15TestDynamicExtensions\x12\x19\n\x10scalar_extension\x18\xd0\x0f \x01(\x07\x12\x37\n\x0e\x65num_extension\x18\xd1\x0f \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12Y\n\x16\x64ynamic_enum_extension\x18\xd2\x0f \x01(\x0e\x32\x38.protobuf_unittest.TestDynamicExtensions.DynamicEnumType\x12=\n\x11message_extension\x18\xd3\x0f \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12_\n\x19\x64ynamic_message_extension\x18\xd4\x0f \x01(\x0b\x32;.protobuf_unittest.TestDynamicExtensions.DynamicMessageType\x12\x1b\n\x12repeated_extension\x18\xd5\x0f \x03(\t\x12\x1d\n\x10packed_extension\x18\xd6\x0f \x03(\x11\x42\x02\x10\x01\x1a,\n\x12\x44ynamicMessageType\x12\x16\n\rdynamic_field\x18\xb4\x10 \x01(\x05\"G\n\x0f\x44ynamicEnumType\x12\x10\n\x0b\x44YNAMIC_FOO\x10\x98\x11\x12\x10\n\x0b\x44YNAMIC_BAR\x10\x99\x11\x12\x10\n\x0b\x44YNAMIC_BAZ\x10\x9a\x11\"\xc0\x01\n#TestRepeatedScalarDifferentTagSizes\x12\x18\n\x10repeated_fixed32\x18\x0c \x03(\x07\x12\x16\n\x0erepeated_int32\x18\r \x03(\x05\x12\x19\n\x10repeated_fixed64\x18\xfe\x0f \x03(\x06\x12\x17\n\x0erepeated_int64\x18\xff\x0f \x03(\x03\x12\x18\n\x0erepeated_float\x18\xfe\xff\x0f \x03(\x02\x12\x19\n\x0frepeated_uint64\x18\xff\xff\x0f \x03(\x04\"\xf7\t\n\x10TestParsingMerge\x12;\n\x12required_all_types\x18\x01 \x02(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12;\n\x12optional_all_types\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12;\n\x12repeated_all_types\x18\x03 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12H\n\roptionalgroup\x18\n \x01(\n21.protobuf_unittest.TestParsingMerge.OptionalGroup\x12H\n\rrepeatedgroup\x18\x14 \x03(\n21.protobuf_unittest.TestParsingMerge.RepeatedGroup\x1a\xaa\x04\n\x17RepeatedFieldsGenerator\x12/\n\x06\x66ield1\x18\x01 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12/\n\x06\x66ield2\x18\x02 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12/\n\x06\x66ield3\x18\x03 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12R\n\x06group1\x18\n \x03(\n2B.protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1\x12R\n\x06group2\x18\x14 \x03(\n2B.protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2\x12.\n\x04\x65xt1\x18\xe8\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12.\n\x04\x65xt2\x18\xe9\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1a\x39\n\x06Group1\x12/\n\x06\x66ield1\x18\x0b \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1a\x39\n\x06Group2\x12/\n\x06\x66ield1\x18\x15 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1aR\n\rOptionalGroup\x12\x41\n\x18optional_group_all_types\x18\x0b \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1aR\n\rRepeatedGroup\x12\x41\n\x18repeated_group_all_types\x18\x15 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\x32[\n\x0coptional_ext\x12#.protobuf_unittest.TestParsingMerge\x18\xe8\x07 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes2[\n\x0crepeated_ext\x12#.protobuf_unittest.TestParsingMerge\x18\xe9\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\"D\n\x1bTestCommentInjectionMessage\x12%\n\x01\x61\x18\x01 \x01(\t:\x1a*/ <- Neither should this.\"\x0c\n\nFooRequest\"\r\n\x0b\x46ooResponse\"\x12\n\x10\x46ooClientMessage\"\x12\n\x10\x46ooServerMessage\"\x0c\n\nBarRequest\"\r\n\x0b\x42\x61rResponse\"\x92\x01\n\x0cTestJsonName\x12\x13\n\x0b\x66ield_name1\x18\x01 \x01(\x05\x12\x12\n\nfieldName2\x18\x02 \x01(\x05\x12\x12\n\nFieldName3\x18\x03 \x01(\x05\x12\x14\n\x0c_field_name4\x18\x04 \x01(\x05\x12\x13\n\x0b\x46IELD_NAME5\x18\x05 \x01(\x05\x12\x1a\n\x0b\x66ield_name6\x18\x06 \x01(\x05R\x05@type\"\xfd\x05\n\x14TestHugeFieldNumbers\x12\x1a\n\x0eoptional_int32\x18\xf0\xf8\xff\xff\x01 \x01(\x05\x12\x14\n\x08\x66ixed_32\x18\xf1\xf8\xff\xff\x01 \x01(\x05\x12\x1e\n\x0erepeated_int32\x18\xf2\xf8\xff\xff\x01 \x03(\x05\x42\x02\x10\x00\x12\x1c\n\x0cpacked_int32\x18\xf3\xf8\xff\xff\x01 \x03(\x05\x42\x02\x10\x01\x12\x39\n\roptional_enum\x18\xf4\xf8\xff\xff\x01 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x1b\n\x0foptional_string\x18\xf5\xf8\xff\xff\x01 \x01(\t\x12\x1a\n\x0eoptional_bytes\x18\xf6\xf8\xff\xff\x01 \x01(\x0c\x12?\n\x10optional_message\x18\xf7\xf8\xff\xff\x01 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12P\n\roptionalgroup\x18\xf8\xf8\xff\xff\x01 \x01(\n25.protobuf_unittest.TestHugeFieldNumbers.OptionalGroup\x12[\n\x11string_string_map\x18\xfa\xf8\xff\xff\x01 \x03(\x0b\x32<.protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry\x12\x1a\n\x0coneof_uint32\x18\xfb\xf8\xff\xff\x01 \x01(\rH\x00\x12\x43\n\x14oneof_test_all_types\x18\xfc\xf8\xff\xff\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesH\x00\x12\x1a\n\x0coneof_string\x18\xfd\xf8\xff\xff\x01 \x01(\tH\x00\x12\x19\n\x0boneof_bytes\x18\xfe\xf8\xff\xff\x01 \x01(\x0cH\x00\x1a$\n\rOptionalGroup\x12\x13\n\x07group_a\x18\xf9\xf8\xff\xff\x01 \x01(\x05\x1a\x36\n\x14StringStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01*\x0c\x08\xe0\xaa\xff\xff\x01\x10\xf0\xf8\xff\xff\x01\x42\r\n\x0boneof_field\"\xb1\x01\n\x18TestExtensionInsideTable\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\x05\x12\x0e\n\x06\x66ield3\x18\x03 \x01(\x05\x12\x0e\n\x06\x66ield4\x18\x04 \x01(\x05\x12\x0e\n\x06\x66ield6\x18\x06 \x01(\x05\x12\x0e\n\x06\x66ield7\x18\x07 \x01(\x05\x12\x0e\n\x06\x66ield8\x18\x08 \x01(\x05\x12\x0e\n\x06\x66ield9\x18\t \x01(\x05\x12\x0f\n\x07\x66ield10\x18\n \x01(\x05*\x04\x08\x05\x10\x06*@\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x04\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x05\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x06*K\n\x14TestEnumWithDupValue\x12\x08\n\x04\x46OO1\x10\x01\x12\x08\n\x04\x42\x41R1\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x08\n\x04\x46OO2\x10\x01\x12\x08\n\x04\x42\x41R2\x10\x02\x1a\x02\x10\x01*\x89\x01\n\x0eTestSparseEnum\x12\x0c\n\x08SPARSE_A\x10{\x12\x0e\n\x08SPARSE_B\x10\xa6\xe7\x03\x12\x0f\n\x08SPARSE_C\x10\xb2\xb1\x80\x06\x12\x15\n\x08SPARSE_D\x10\xf1\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x15\n\x08SPARSE_E\x10\xb4\xde\xfc\xff\xff\xff\xff\xff\xff\x01\x12\x0c\n\x08SPARSE_F\x10\x00\x12\x0c\n\x08SPARSE_G\x10\x02\x32\x99\x01\n\x0bTestService\x12\x44\n\x03\x46oo\x12\x1d.protobuf_unittest.FooRequest\x1a\x1e.protobuf_unittest.FooResponse\x12\x44\n\x03\x42\x61r\x12\x1d.protobuf_unittest.BarRequest\x1a\x1e.protobuf_unittest.BarResponse:F\n\x18optional_int32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x01 \x01(\x05:F\n\x18optional_int64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x02 \x01(\x03:G\n\x19optional_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x03 \x01(\r:G\n\x19optional_uint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x04 \x01(\x04:G\n\x19optional_sint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x05 \x01(\x11:G\n\x19optional_sint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x06 \x01(\x12:H\n\x1aoptional_fixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x07 \x01(\x07:H\n\x1aoptional_fixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x08 \x01(\x06:I\n\x1boptional_sfixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\t \x01(\x0f:I\n\x1boptional_sfixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\n \x01(\x10:F\n\x18optional_float_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0b \x01(\x02:G\n\x19optional_double_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0c \x01(\x01:E\n\x17optional_bool_extension\x12$.protobuf_unittest.TestAllExtensions\x18\r \x01(\x08:G\n\x19optional_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0e \x01(\t:F\n\x18optional_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0f \x01(\x0c:q\n\x17optionalgroup_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x10 \x01(\n2*.protobuf_unittest.OptionalGroup_extension:~\n!optional_nested_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x12 \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage:s\n\"optional_foreign_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x13 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:x\n!optional_import_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage:x\n\x1eoptional_nested_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x15 \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:m\n\x1foptional_foreign_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:r\n\x1eoptional_import_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x17 \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:Q\n\x1foptional_string_piece_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x18 \x01(\tB\x02\x08\x02:I\n\x17optional_cord_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x19 \x01(\tB\x02\x08\x01:\x85\x01\n(optional_public_import_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage:\x80\x01\n\x1foptional_lazy_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x1b \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01:F\n\x18repeated_int32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x1f \x03(\x05:F\n\x18repeated_int64_extension\x12$.protobuf_unittest.TestAllExtensions\x18 \x03(\x03:G\n\x19repeated_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18! \x03(\r:G\n\x19repeated_uint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\" \x03(\x04:G\n\x19repeated_sint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18# \x03(\x11:G\n\x19repeated_sint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18$ \x03(\x12:H\n\x1arepeated_fixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18% \x03(\x07:H\n\x1arepeated_fixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18& \x03(\x06:I\n\x1brepeated_sfixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\' \x03(\x0f:I\n\x1brepeated_sfixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18( \x03(\x10:F\n\x18repeated_float_extension\x12$.protobuf_unittest.TestAllExtensions\x18) \x03(\x02:G\n\x19repeated_double_extension\x12$.protobuf_unittest.TestAllExtensions\x18* \x03(\x01:E\n\x17repeated_bool_extension\x12$.protobuf_unittest.TestAllExtensions\x18+ \x03(\x08:G\n\x19repeated_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18, \x03(\t:F\n\x18repeated_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18- \x03(\x0c:q\n\x17repeatedgroup_extension\x12$.protobuf_unittest.TestAllExtensions\x18. \x03(\n2*.protobuf_unittest.RepeatedGroup_extension:~\n!repeated_nested_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x30 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage:s\n\"repeated_foreign_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x31 \x03(\x0b\x32!.protobuf_unittest.ForeignMessage:x\n!repeated_import_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage:x\n\x1erepeated_nested_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x33 \x03(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:m\n\x1frepeated_foreign_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x34 \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:r\n\x1erepeated_import_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x35 \x03(\x0e\x32$.protobuf_unittest_import.ImportEnum:Q\n\x1frepeated_string_piece_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x36 \x03(\tB\x02\x08\x02:I\n\x17repeated_cord_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x37 \x03(\tB\x02\x08\x01:\x80\x01\n\x1frepeated_lazy_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x39 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01:I\n\x17\x64\x65\x66\x61ult_int32_extension\x12$.protobuf_unittest.TestAllExtensions\x18= \x01(\x05:\x02\x34\x31:I\n\x17\x64\x65\x66\x61ult_int64_extension\x12$.protobuf_unittest.TestAllExtensions\x18> \x01(\x03:\x02\x34\x32:J\n\x18\x64\x65\x66\x61ult_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18? \x01(\r:\x02\x34\x33:J\n\x18\x64\x65\x66\x61ult_uint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18@ \x01(\x04:\x02\x34\x34:K\n\x18\x64\x65\x66\x61ult_sint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x41 \x01(\x11:\x03-45:J\n\x18\x64\x65\x66\x61ult_sint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x42 \x01(\x12:\x02\x34\x36:K\n\x19\x64\x65\x66\x61ult_fixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x43 \x01(\x07:\x02\x34\x37:K\n\x19\x64\x65\x66\x61ult_fixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x44 \x01(\x06:\x02\x34\x38:L\n\x1a\x64\x65\x66\x61ult_sfixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x45 \x01(\x0f:\x02\x34\x39:M\n\x1a\x64\x65\x66\x61ult_sfixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x46 \x01(\x10:\x03-50:K\n\x17\x64\x65\x66\x61ult_float_extension\x12$.protobuf_unittest.TestAllExtensions\x18G \x01(\x02:\x04\x35\x31.5:M\n\x18\x64\x65\x66\x61ult_double_extension\x12$.protobuf_unittest.TestAllExtensions\x18H \x01(\x01:\x05\x35\x32\x30\x30\x30:J\n\x16\x64\x65\x66\x61ult_bool_extension\x12$.protobuf_unittest.TestAllExtensions\x18I \x01(\x08:\x04true:M\n\x18\x64\x65\x66\x61ult_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18J \x01(\t:\x05hello:L\n\x17\x64\x65\x66\x61ult_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18K \x01(\x0c:\x05world:|\n\x1d\x64\x65\x66\x61ult_nested_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18Q \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:\x03\x42\x41R:y\n\x1e\x64\x65\x66\x61ult_foreign_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18R \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:\x0b\x46OREIGN_BAR:}\n\x1d\x64\x65\x66\x61ult_import_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18S \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:\nIMPORT_BAR:U\n\x1e\x64\x65\x66\x61ult_string_piece_extension\x12$.protobuf_unittest.TestAllExtensions\x18T \x01(\t:\x03\x61\x62\x63\x42\x02\x08\x02:M\n\x16\x64\x65\x66\x61ult_cord_extension\x12$.protobuf_unittest.TestAllExtensions\x18U \x01(\t:\x03\x31\x32\x33\x42\x02\x08\x01:D\n\x16oneof_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18o \x01(\r:{\n\x1eoneof_nested_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18p \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage:D\n\x16oneof_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18q \x01(\t:C\n\x15oneof_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18r \x01(\x0c:B\n\x13my_extension_string\x12%.protobuf_unittest.TestFieldOrderings\x18\x32 \x01(\t:?\n\x10my_extension_int\x12%.protobuf_unittest.TestFieldOrderings\x18\x05 \x01(\x05:K\n\x16packed_int32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18Z \x03(\x05\x42\x02\x10\x01:K\n\x16packed_int64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18[ \x03(\x03\x42\x02\x10\x01:L\n\x17packed_uint32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\\ \x03(\rB\x02\x10\x01:L\n\x17packed_uint64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18] \x03(\x04\x42\x02\x10\x01:L\n\x17packed_sint32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18^ \x03(\x11\x42\x02\x10\x01:L\n\x17packed_sint64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18_ \x03(\x12\x42\x02\x10\x01:M\n\x18packed_fixed32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18` \x03(\x07\x42\x02\x10\x01:M\n\x18packed_fixed64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x61 \x03(\x06\x42\x02\x10\x01:N\n\x19packed_sfixed32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x62 \x03(\x0f\x42\x02\x10\x01:N\n\x19packed_sfixed64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x63 \x03(\x10\x42\x02\x10\x01:K\n\x16packed_float_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x64 \x03(\x02\x42\x02\x10\x01:L\n\x17packed_double_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x65 \x03(\x01\x42\x02\x10\x01:J\n\x15packed_bool_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x66 \x03(\x08\x42\x02\x10\x01:j\n\x15packed_enum_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x01:O\n\x18unpacked_int32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18Z \x03(\x05\x42\x02\x10\x00:O\n\x18unpacked_int64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18[ \x03(\x03\x42\x02\x10\x00:P\n\x19unpacked_uint32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\\ \x03(\rB\x02\x10\x00:P\n\x19unpacked_uint64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18] \x03(\x04\x42\x02\x10\x00:P\n\x19unpacked_sint32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18^ \x03(\x11\x42\x02\x10\x00:P\n\x19unpacked_sint64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18_ \x03(\x12\x42\x02\x10\x00:Q\n\x1aunpacked_fixed32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18` \x03(\x07\x42\x02\x10\x00:Q\n\x1aunpacked_fixed64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x61 \x03(\x06\x42\x02\x10\x00:R\n\x1bunpacked_sfixed32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x62 \x03(\x0f\x42\x02\x10\x00:R\n\x1bunpacked_sfixed64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x63 \x03(\x10\x42\x02\x10\x00:O\n\x18unpacked_float_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x64 \x03(\x02\x42\x02\x10\x00:P\n\x19unpacked_double_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x65 \x03(\x01\x42\x02\x10\x00:N\n\x17unpacked_bool_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x66 \x03(\x08\x42\x02\x10\x00:n\n\x17unpacked_enum_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x00:d\n\x0etest_all_types\x12\'.protobuf_unittest.TestHugeFieldNumbers\x18\xe0\xaa\xff\xff\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes:Z\n%test_extension_inside_table_extension\x12+.protobuf_unittest.TestExtensionInsideTable\x18\x05 \x01(\x05\x42\x1d\x42\rUnittestProtoH\x01\x80\x01\x01\x88\x01\x01\x90\x01\x01\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='protobuf_unittest.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=15306, + serialized_end=15370, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +_TESTENUMWITHDUPVALUE = _descriptor.EnumDescriptor( + name='TestEnumWithDupValue', + full_name='protobuf_unittest.TestEnumWithDupValue', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO1', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR1', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOO2', index=3, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR2', index=4, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=_b('\020\001'), + serialized_start=15372, + serialized_end=15447, +) +_sym_db.RegisterEnumDescriptor(_TESTENUMWITHDUPVALUE) + +TestEnumWithDupValue = enum_type_wrapper.EnumTypeWrapper(_TESTENUMWITHDUPVALUE) +_TESTSPARSEENUM = _descriptor.EnumDescriptor( + name='TestSparseEnum', + full_name='protobuf_unittest.TestSparseEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SPARSE_A', index=0, number=123, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_B', index=1, number=62374, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_C', index=2, number=12589234, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_D', index=3, number=-15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_E', index=4, number=-53452, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_F', index=5, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_G', index=6, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=15450, + serialized_end=15587, +) +_sym_db.RegisterEnumDescriptor(_TESTSPARSEENUM) + +TestSparseEnum = enum_type_wrapper.EnumTypeWrapper(_TESTSPARSEENUM) +FOREIGN_FOO = 4 +FOREIGN_BAR = 5 +FOREIGN_BAZ = 6 +FOO1 = 1 +BAR1 = 2 +BAZ = 3 +FOO2 = 1 +BAR2 = 2 +SPARSE_A = 123 +SPARSE_B = 62374 +SPARSE_C = 12589234 +SPARSE_D = -15 +SPARSE_E = -53452 +SPARSE_F = 0 +SPARSE_G = 2 + +OPTIONAL_INT32_EXTENSION_FIELD_NUMBER = 1 +optional_int32_extension = _descriptor.FieldDescriptor( + name='optional_int32_extension', full_name='protobuf_unittest.optional_int32_extension', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_INT64_EXTENSION_FIELD_NUMBER = 2 +optional_int64_extension = _descriptor.FieldDescriptor( + name='optional_int64_extension', full_name='protobuf_unittest.optional_int64_extension', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_UINT32_EXTENSION_FIELD_NUMBER = 3 +optional_uint32_extension = _descriptor.FieldDescriptor( + name='optional_uint32_extension', full_name='protobuf_unittest.optional_uint32_extension', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_UINT64_EXTENSION_FIELD_NUMBER = 4 +optional_uint64_extension = _descriptor.FieldDescriptor( + name='optional_uint64_extension', full_name='protobuf_unittest.optional_uint64_extension', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SINT32_EXTENSION_FIELD_NUMBER = 5 +optional_sint32_extension = _descriptor.FieldDescriptor( + name='optional_sint32_extension', full_name='protobuf_unittest.optional_sint32_extension', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SINT64_EXTENSION_FIELD_NUMBER = 6 +optional_sint64_extension = _descriptor.FieldDescriptor( + name='optional_sint64_extension', full_name='protobuf_unittest.optional_sint64_extension', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FIXED32_EXTENSION_FIELD_NUMBER = 7 +optional_fixed32_extension = _descriptor.FieldDescriptor( + name='optional_fixed32_extension', full_name='protobuf_unittest.optional_fixed32_extension', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FIXED64_EXTENSION_FIELD_NUMBER = 8 +optional_fixed64_extension = _descriptor.FieldDescriptor( + name='optional_fixed64_extension', full_name='protobuf_unittest.optional_fixed64_extension', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SFIXED32_EXTENSION_FIELD_NUMBER = 9 +optional_sfixed32_extension = _descriptor.FieldDescriptor( + name='optional_sfixed32_extension', full_name='protobuf_unittest.optional_sfixed32_extension', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SFIXED64_EXTENSION_FIELD_NUMBER = 10 +optional_sfixed64_extension = _descriptor.FieldDescriptor( + name='optional_sfixed64_extension', full_name='protobuf_unittest.optional_sfixed64_extension', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FLOAT_EXTENSION_FIELD_NUMBER = 11 +optional_float_extension = _descriptor.FieldDescriptor( + name='optional_float_extension', full_name='protobuf_unittest.optional_float_extension', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_DOUBLE_EXTENSION_FIELD_NUMBER = 12 +optional_double_extension = _descriptor.FieldDescriptor( + name='optional_double_extension', full_name='protobuf_unittest.optional_double_extension', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_BOOL_EXTENSION_FIELD_NUMBER = 13 +optional_bool_extension = _descriptor.FieldDescriptor( + name='optional_bool_extension', full_name='protobuf_unittest.optional_bool_extension', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_STRING_EXTENSION_FIELD_NUMBER = 14 +optional_string_extension = _descriptor.FieldDescriptor( + name='optional_string_extension', full_name='protobuf_unittest.optional_string_extension', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_BYTES_EXTENSION_FIELD_NUMBER = 15 +optional_bytes_extension = _descriptor.FieldDescriptor( + name='optional_bytes_extension', full_name='protobuf_unittest.optional_bytes_extension', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONALGROUP_EXTENSION_FIELD_NUMBER = 16 +optionalgroup_extension = _descriptor.FieldDescriptor( + name='optionalgroup_extension', full_name='protobuf_unittest.optionalgroup_extension', index=15, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 18 +optional_nested_message_extension = _descriptor.FieldDescriptor( + name='optional_nested_message_extension', full_name='protobuf_unittest.optional_nested_message_extension', index=16, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FOREIGN_MESSAGE_EXTENSION_FIELD_NUMBER = 19 +optional_foreign_message_extension = _descriptor.FieldDescriptor( + name='optional_foreign_message_extension', full_name='protobuf_unittest.optional_foreign_message_extension', index=17, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_IMPORT_MESSAGE_EXTENSION_FIELD_NUMBER = 20 +optional_import_message_extension = _descriptor.FieldDescriptor( + name='optional_import_message_extension', full_name='protobuf_unittest.optional_import_message_extension', index=18, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER = 21 +optional_nested_enum_extension = _descriptor.FieldDescriptor( + name='optional_nested_enum_extension', full_name='protobuf_unittest.optional_nested_enum_extension', index=19, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FOREIGN_ENUM_EXTENSION_FIELD_NUMBER = 22 +optional_foreign_enum_extension = _descriptor.FieldDescriptor( + name='optional_foreign_enum_extension', full_name='protobuf_unittest.optional_foreign_enum_extension', index=20, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_IMPORT_ENUM_EXTENSION_FIELD_NUMBER = 23 +optional_import_enum_extension = _descriptor.FieldDescriptor( + name='optional_import_enum_extension', full_name='protobuf_unittest.optional_import_enum_extension', index=21, + number=23, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_STRING_PIECE_EXTENSION_FIELD_NUMBER = 24 +optional_string_piece_extension = _descriptor.FieldDescriptor( + name='optional_string_piece_extension', full_name='protobuf_unittest.optional_string_piece_extension', index=22, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR) +OPTIONAL_CORD_EXTENSION_FIELD_NUMBER = 25 +optional_cord_extension = _descriptor.FieldDescriptor( + name='optional_cord_extension', full_name='protobuf_unittest.optional_cord_extension', index=23, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR) +OPTIONAL_PUBLIC_IMPORT_MESSAGE_EXTENSION_FIELD_NUMBER = 26 +optional_public_import_message_extension = _descriptor.FieldDescriptor( + name='optional_public_import_message_extension', full_name='protobuf_unittest.optional_public_import_message_extension', index=24, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_LAZY_MESSAGE_EXTENSION_FIELD_NUMBER = 27 +optional_lazy_message_extension = _descriptor.FieldDescriptor( + name='optional_lazy_message_extension', full_name='protobuf_unittest.optional_lazy_message_extension', index=25, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR) +REPEATED_INT32_EXTENSION_FIELD_NUMBER = 31 +repeated_int32_extension = _descriptor.FieldDescriptor( + name='repeated_int32_extension', full_name='protobuf_unittest.repeated_int32_extension', index=26, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_INT64_EXTENSION_FIELD_NUMBER = 32 +repeated_int64_extension = _descriptor.FieldDescriptor( + name='repeated_int64_extension', full_name='protobuf_unittest.repeated_int64_extension', index=27, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_UINT32_EXTENSION_FIELD_NUMBER = 33 +repeated_uint32_extension = _descriptor.FieldDescriptor( + name='repeated_uint32_extension', full_name='protobuf_unittest.repeated_uint32_extension', index=28, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_UINT64_EXTENSION_FIELD_NUMBER = 34 +repeated_uint64_extension = _descriptor.FieldDescriptor( + name='repeated_uint64_extension', full_name='protobuf_unittest.repeated_uint64_extension', index=29, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SINT32_EXTENSION_FIELD_NUMBER = 35 +repeated_sint32_extension = _descriptor.FieldDescriptor( + name='repeated_sint32_extension', full_name='protobuf_unittest.repeated_sint32_extension', index=30, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SINT64_EXTENSION_FIELD_NUMBER = 36 +repeated_sint64_extension = _descriptor.FieldDescriptor( + name='repeated_sint64_extension', full_name='protobuf_unittest.repeated_sint64_extension', index=31, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FIXED32_EXTENSION_FIELD_NUMBER = 37 +repeated_fixed32_extension = _descriptor.FieldDescriptor( + name='repeated_fixed32_extension', full_name='protobuf_unittest.repeated_fixed32_extension', index=32, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FIXED64_EXTENSION_FIELD_NUMBER = 38 +repeated_fixed64_extension = _descriptor.FieldDescriptor( + name='repeated_fixed64_extension', full_name='protobuf_unittest.repeated_fixed64_extension', index=33, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SFIXED32_EXTENSION_FIELD_NUMBER = 39 +repeated_sfixed32_extension = _descriptor.FieldDescriptor( + name='repeated_sfixed32_extension', full_name='protobuf_unittest.repeated_sfixed32_extension', index=34, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SFIXED64_EXTENSION_FIELD_NUMBER = 40 +repeated_sfixed64_extension = _descriptor.FieldDescriptor( + name='repeated_sfixed64_extension', full_name='protobuf_unittest.repeated_sfixed64_extension', index=35, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FLOAT_EXTENSION_FIELD_NUMBER = 41 +repeated_float_extension = _descriptor.FieldDescriptor( + name='repeated_float_extension', full_name='protobuf_unittest.repeated_float_extension', index=36, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_DOUBLE_EXTENSION_FIELD_NUMBER = 42 +repeated_double_extension = _descriptor.FieldDescriptor( + name='repeated_double_extension', full_name='protobuf_unittest.repeated_double_extension', index=37, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_BOOL_EXTENSION_FIELD_NUMBER = 43 +repeated_bool_extension = _descriptor.FieldDescriptor( + name='repeated_bool_extension', full_name='protobuf_unittest.repeated_bool_extension', index=38, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_STRING_EXTENSION_FIELD_NUMBER = 44 +repeated_string_extension = _descriptor.FieldDescriptor( + name='repeated_string_extension', full_name='protobuf_unittest.repeated_string_extension', index=39, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_BYTES_EXTENSION_FIELD_NUMBER = 45 +repeated_bytes_extension = _descriptor.FieldDescriptor( + name='repeated_bytes_extension', full_name='protobuf_unittest.repeated_bytes_extension', index=40, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATEDGROUP_EXTENSION_FIELD_NUMBER = 46 +repeatedgroup_extension = _descriptor.FieldDescriptor( + name='repeatedgroup_extension', full_name='protobuf_unittest.repeatedgroup_extension', index=41, + number=46, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 48 +repeated_nested_message_extension = _descriptor.FieldDescriptor( + name='repeated_nested_message_extension', full_name='protobuf_unittest.repeated_nested_message_extension', index=42, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FOREIGN_MESSAGE_EXTENSION_FIELD_NUMBER = 49 +repeated_foreign_message_extension = _descriptor.FieldDescriptor( + name='repeated_foreign_message_extension', full_name='protobuf_unittest.repeated_foreign_message_extension', index=43, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_IMPORT_MESSAGE_EXTENSION_FIELD_NUMBER = 50 +repeated_import_message_extension = _descriptor.FieldDescriptor( + name='repeated_import_message_extension', full_name='protobuf_unittest.repeated_import_message_extension', index=44, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER = 51 +repeated_nested_enum_extension = _descriptor.FieldDescriptor( + name='repeated_nested_enum_extension', full_name='protobuf_unittest.repeated_nested_enum_extension', index=45, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FOREIGN_ENUM_EXTENSION_FIELD_NUMBER = 52 +repeated_foreign_enum_extension = _descriptor.FieldDescriptor( + name='repeated_foreign_enum_extension', full_name='protobuf_unittest.repeated_foreign_enum_extension', index=46, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_IMPORT_ENUM_EXTENSION_FIELD_NUMBER = 53 +repeated_import_enum_extension = _descriptor.FieldDescriptor( + name='repeated_import_enum_extension', full_name='protobuf_unittest.repeated_import_enum_extension', index=47, + number=53, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_STRING_PIECE_EXTENSION_FIELD_NUMBER = 54 +repeated_string_piece_extension = _descriptor.FieldDescriptor( + name='repeated_string_piece_extension', full_name='protobuf_unittest.repeated_string_piece_extension', index=48, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR) +REPEATED_CORD_EXTENSION_FIELD_NUMBER = 55 +repeated_cord_extension = _descriptor.FieldDescriptor( + name='repeated_cord_extension', full_name='protobuf_unittest.repeated_cord_extension', index=49, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR) +REPEATED_LAZY_MESSAGE_EXTENSION_FIELD_NUMBER = 57 +repeated_lazy_message_extension = _descriptor.FieldDescriptor( + name='repeated_lazy_message_extension', full_name='protobuf_unittest.repeated_lazy_message_extension', index=50, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR) +DEFAULT_INT32_EXTENSION_FIELD_NUMBER = 61 +default_int32_extension = _descriptor.FieldDescriptor( + name='default_int32_extension', full_name='protobuf_unittest.default_int32_extension', index=51, + number=61, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=41, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_INT64_EXTENSION_FIELD_NUMBER = 62 +default_int64_extension = _descriptor.FieldDescriptor( + name='default_int64_extension', full_name='protobuf_unittest.default_int64_extension', index=52, + number=62, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_UINT32_EXTENSION_FIELD_NUMBER = 63 +default_uint32_extension = _descriptor.FieldDescriptor( + name='default_uint32_extension', full_name='protobuf_unittest.default_uint32_extension', index=53, + number=63, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=43, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_UINT64_EXTENSION_FIELD_NUMBER = 64 +default_uint64_extension = _descriptor.FieldDescriptor( + name='default_uint64_extension', full_name='protobuf_unittest.default_uint64_extension', index=54, + number=64, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=44, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SINT32_EXTENSION_FIELD_NUMBER = 65 +default_sint32_extension = _descriptor.FieldDescriptor( + name='default_sint32_extension', full_name='protobuf_unittest.default_sint32_extension', index=55, + number=65, type=17, cpp_type=1, label=1, + has_default_value=True, default_value=-45, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SINT64_EXTENSION_FIELD_NUMBER = 66 +default_sint64_extension = _descriptor.FieldDescriptor( + name='default_sint64_extension', full_name='protobuf_unittest.default_sint64_extension', index=56, + number=66, type=18, cpp_type=2, label=1, + has_default_value=True, default_value=46, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FIXED32_EXTENSION_FIELD_NUMBER = 67 +default_fixed32_extension = _descriptor.FieldDescriptor( + name='default_fixed32_extension', full_name='protobuf_unittest.default_fixed32_extension', index=57, + number=67, type=7, cpp_type=3, label=1, + has_default_value=True, default_value=47, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FIXED64_EXTENSION_FIELD_NUMBER = 68 +default_fixed64_extension = _descriptor.FieldDescriptor( + name='default_fixed64_extension', full_name='protobuf_unittest.default_fixed64_extension', index=58, + number=68, type=6, cpp_type=4, label=1, + has_default_value=True, default_value=48, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SFIXED32_EXTENSION_FIELD_NUMBER = 69 +default_sfixed32_extension = _descriptor.FieldDescriptor( + name='default_sfixed32_extension', full_name='protobuf_unittest.default_sfixed32_extension', index=59, + number=69, type=15, cpp_type=1, label=1, + has_default_value=True, default_value=49, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SFIXED64_EXTENSION_FIELD_NUMBER = 70 +default_sfixed64_extension = _descriptor.FieldDescriptor( + name='default_sfixed64_extension', full_name='protobuf_unittest.default_sfixed64_extension', index=60, + number=70, type=16, cpp_type=2, label=1, + has_default_value=True, default_value=-50, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FLOAT_EXTENSION_FIELD_NUMBER = 71 +default_float_extension = _descriptor.FieldDescriptor( + name='default_float_extension', full_name='protobuf_unittest.default_float_extension', index=61, + number=71, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(51.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_DOUBLE_EXTENSION_FIELD_NUMBER = 72 +default_double_extension = _descriptor.FieldDescriptor( + name='default_double_extension', full_name='protobuf_unittest.default_double_extension', index=62, + number=72, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(52000), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_BOOL_EXTENSION_FIELD_NUMBER = 73 +default_bool_extension = _descriptor.FieldDescriptor( + name='default_bool_extension', full_name='protobuf_unittest.default_bool_extension', index=63, + number=73, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_STRING_EXTENSION_FIELD_NUMBER = 74 +default_string_extension = _descriptor.FieldDescriptor( + name='default_string_extension', full_name='protobuf_unittest.default_string_extension', index=64, + number=74, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_BYTES_EXTENSION_FIELD_NUMBER = 75 +default_bytes_extension = _descriptor.FieldDescriptor( + name='default_bytes_extension', full_name='protobuf_unittest.default_bytes_extension', index=65, + number=75, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("world"), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_NESTED_ENUM_EXTENSION_FIELD_NUMBER = 81 +default_nested_enum_extension = _descriptor.FieldDescriptor( + name='default_nested_enum_extension', full_name='protobuf_unittest.default_nested_enum_extension', index=66, + number=81, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FOREIGN_ENUM_EXTENSION_FIELD_NUMBER = 82 +default_foreign_enum_extension = _descriptor.FieldDescriptor( + name='default_foreign_enum_extension', full_name='protobuf_unittest.default_foreign_enum_extension', index=67, + number=82, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_IMPORT_ENUM_EXTENSION_FIELD_NUMBER = 83 +default_import_enum_extension = _descriptor.FieldDescriptor( + name='default_import_enum_extension', full_name='protobuf_unittest.default_import_enum_extension', index=68, + number=83, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=8, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_STRING_PIECE_EXTENSION_FIELD_NUMBER = 84 +default_string_piece_extension = _descriptor.FieldDescriptor( + name='default_string_piece_extension', full_name='protobuf_unittest.default_string_piece_extension', index=69, + number=84, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("abc").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR) +DEFAULT_CORD_EXTENSION_FIELD_NUMBER = 85 +default_cord_extension = _descriptor.FieldDescriptor( + name='default_cord_extension', full_name='protobuf_unittest.default_cord_extension', index=70, + number=85, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("123").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR) +ONEOF_UINT32_EXTENSION_FIELD_NUMBER = 111 +oneof_uint32_extension = _descriptor.FieldDescriptor( + name='oneof_uint32_extension', full_name='protobuf_unittest.oneof_uint32_extension', index=71, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 112 +oneof_nested_message_extension = _descriptor.FieldDescriptor( + name='oneof_nested_message_extension', full_name='protobuf_unittest.oneof_nested_message_extension', index=72, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_STRING_EXTENSION_FIELD_NUMBER = 113 +oneof_string_extension = _descriptor.FieldDescriptor( + name='oneof_string_extension', full_name='protobuf_unittest.oneof_string_extension', index=73, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_BYTES_EXTENSION_FIELD_NUMBER = 114 +oneof_bytes_extension = _descriptor.FieldDescriptor( + name='oneof_bytes_extension', full_name='protobuf_unittest.oneof_bytes_extension', index=74, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MY_EXTENSION_STRING_FIELD_NUMBER = 50 +my_extension_string = _descriptor.FieldDescriptor( + name='my_extension_string', full_name='protobuf_unittest.my_extension_string', index=75, + number=50, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MY_EXTENSION_INT_FIELD_NUMBER = 5 +my_extension_int = _descriptor.FieldDescriptor( + name='my_extension_int', full_name='protobuf_unittest.my_extension_int', index=76, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +PACKED_INT32_EXTENSION_FIELD_NUMBER = 90 +packed_int32_extension = _descriptor.FieldDescriptor( + name='packed_int32_extension', full_name='protobuf_unittest.packed_int32_extension', index=77, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_INT64_EXTENSION_FIELD_NUMBER = 91 +packed_int64_extension = _descriptor.FieldDescriptor( + name='packed_int64_extension', full_name='protobuf_unittest.packed_int64_extension', index=78, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_UINT32_EXTENSION_FIELD_NUMBER = 92 +packed_uint32_extension = _descriptor.FieldDescriptor( + name='packed_uint32_extension', full_name='protobuf_unittest.packed_uint32_extension', index=79, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_UINT64_EXTENSION_FIELD_NUMBER = 93 +packed_uint64_extension = _descriptor.FieldDescriptor( + name='packed_uint64_extension', full_name='protobuf_unittest.packed_uint64_extension', index=80, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SINT32_EXTENSION_FIELD_NUMBER = 94 +packed_sint32_extension = _descriptor.FieldDescriptor( + name='packed_sint32_extension', full_name='protobuf_unittest.packed_sint32_extension', index=81, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SINT64_EXTENSION_FIELD_NUMBER = 95 +packed_sint64_extension = _descriptor.FieldDescriptor( + name='packed_sint64_extension', full_name='protobuf_unittest.packed_sint64_extension', index=82, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_FIXED32_EXTENSION_FIELD_NUMBER = 96 +packed_fixed32_extension = _descriptor.FieldDescriptor( + name='packed_fixed32_extension', full_name='protobuf_unittest.packed_fixed32_extension', index=83, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_FIXED64_EXTENSION_FIELD_NUMBER = 97 +packed_fixed64_extension = _descriptor.FieldDescriptor( + name='packed_fixed64_extension', full_name='protobuf_unittest.packed_fixed64_extension', index=84, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SFIXED32_EXTENSION_FIELD_NUMBER = 98 +packed_sfixed32_extension = _descriptor.FieldDescriptor( + name='packed_sfixed32_extension', full_name='protobuf_unittest.packed_sfixed32_extension', index=85, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SFIXED64_EXTENSION_FIELD_NUMBER = 99 +packed_sfixed64_extension = _descriptor.FieldDescriptor( + name='packed_sfixed64_extension', full_name='protobuf_unittest.packed_sfixed64_extension', index=86, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_FLOAT_EXTENSION_FIELD_NUMBER = 100 +packed_float_extension = _descriptor.FieldDescriptor( + name='packed_float_extension', full_name='protobuf_unittest.packed_float_extension', index=87, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_DOUBLE_EXTENSION_FIELD_NUMBER = 101 +packed_double_extension = _descriptor.FieldDescriptor( + name='packed_double_extension', full_name='protobuf_unittest.packed_double_extension', index=88, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_BOOL_EXTENSION_FIELD_NUMBER = 102 +packed_bool_extension = _descriptor.FieldDescriptor( + name='packed_bool_extension', full_name='protobuf_unittest.packed_bool_extension', index=89, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_ENUM_EXTENSION_FIELD_NUMBER = 103 +packed_enum_extension = _descriptor.FieldDescriptor( + name='packed_enum_extension', full_name='protobuf_unittest.packed_enum_extension', index=90, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +UNPACKED_INT32_EXTENSION_FIELD_NUMBER = 90 +unpacked_int32_extension = _descriptor.FieldDescriptor( + name='unpacked_int32_extension', full_name='protobuf_unittest.unpacked_int32_extension', index=91, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_INT64_EXTENSION_FIELD_NUMBER = 91 +unpacked_int64_extension = _descriptor.FieldDescriptor( + name='unpacked_int64_extension', full_name='protobuf_unittest.unpacked_int64_extension', index=92, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_UINT32_EXTENSION_FIELD_NUMBER = 92 +unpacked_uint32_extension = _descriptor.FieldDescriptor( + name='unpacked_uint32_extension', full_name='protobuf_unittest.unpacked_uint32_extension', index=93, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_UINT64_EXTENSION_FIELD_NUMBER = 93 +unpacked_uint64_extension = _descriptor.FieldDescriptor( + name='unpacked_uint64_extension', full_name='protobuf_unittest.unpacked_uint64_extension', index=94, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SINT32_EXTENSION_FIELD_NUMBER = 94 +unpacked_sint32_extension = _descriptor.FieldDescriptor( + name='unpacked_sint32_extension', full_name='protobuf_unittest.unpacked_sint32_extension', index=95, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SINT64_EXTENSION_FIELD_NUMBER = 95 +unpacked_sint64_extension = _descriptor.FieldDescriptor( + name='unpacked_sint64_extension', full_name='protobuf_unittest.unpacked_sint64_extension', index=96, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_FIXED32_EXTENSION_FIELD_NUMBER = 96 +unpacked_fixed32_extension = _descriptor.FieldDescriptor( + name='unpacked_fixed32_extension', full_name='protobuf_unittest.unpacked_fixed32_extension', index=97, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_FIXED64_EXTENSION_FIELD_NUMBER = 97 +unpacked_fixed64_extension = _descriptor.FieldDescriptor( + name='unpacked_fixed64_extension', full_name='protobuf_unittest.unpacked_fixed64_extension', index=98, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SFIXED32_EXTENSION_FIELD_NUMBER = 98 +unpacked_sfixed32_extension = _descriptor.FieldDescriptor( + name='unpacked_sfixed32_extension', full_name='protobuf_unittest.unpacked_sfixed32_extension', index=99, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SFIXED64_EXTENSION_FIELD_NUMBER = 99 +unpacked_sfixed64_extension = _descriptor.FieldDescriptor( + name='unpacked_sfixed64_extension', full_name='protobuf_unittest.unpacked_sfixed64_extension', index=100, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_FLOAT_EXTENSION_FIELD_NUMBER = 100 +unpacked_float_extension = _descriptor.FieldDescriptor( + name='unpacked_float_extension', full_name='protobuf_unittest.unpacked_float_extension', index=101, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_DOUBLE_EXTENSION_FIELD_NUMBER = 101 +unpacked_double_extension = _descriptor.FieldDescriptor( + name='unpacked_double_extension', full_name='protobuf_unittest.unpacked_double_extension', index=102, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_BOOL_EXTENSION_FIELD_NUMBER = 102 +unpacked_bool_extension = _descriptor.FieldDescriptor( + name='unpacked_bool_extension', full_name='protobuf_unittest.unpacked_bool_extension', index=103, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_ENUM_EXTENSION_FIELD_NUMBER = 103 +unpacked_enum_extension = _descriptor.FieldDescriptor( + name='unpacked_enum_extension', full_name='protobuf_unittest.unpacked_enum_extension', index=104, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +TEST_ALL_TYPES_FIELD_NUMBER = 536860000 +test_all_types = _descriptor.FieldDescriptor( + name='test_all_types', full_name='protobuf_unittest.test_all_types', index=105, + number=536860000, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +TEST_EXTENSION_INSIDE_TABLE_EXTENSION_FIELD_NUMBER = 5 +test_extension_inside_table_extension = _descriptor.FieldDescriptor( + name='test_extension_inside_table_extension', full_name='protobuf_unittest.test_extension_inside_table_extension', index=106, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_TESTALLTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest.TestAllTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3202, + serialized_end=3259, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPES_NESTEDENUM) + +_TESTONEOF2_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest.TestOneof2.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3202, + serialized_end=3241, +) +_sym_db.RegisterEnumDescriptor(_TESTONEOF2_NESTEDENUM) + +_TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE = _descriptor.EnumDescriptor( + name='DynamicEnumType', + full_name='protobuf_unittest.TestDynamicExtensions.DynamicEnumType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DYNAMIC_FOO', index=0, number=2200, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DYNAMIC_BAR', index=1, number=2201, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DYNAMIC_BAZ', index=2, number=2202, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=12499, + serialized_end=12570, +) +_sym_db.RegisterEnumDescriptor(_TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3117, + serialized_end=3144, +) + +_TESTALLTYPES_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestAllTypes.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestAllTypes.OptionalGroup.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3146, + serialized_end=3172, +) + +_TESTALLTYPES_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest.TestAllTypes.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestAllTypes.RepeatedGroup.a', index=0, + number=47, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3174, + serialized_end=3200, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='protobuf_unittest.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest.TestAllTypes.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_unittest.TestAllTypes.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_unittest.TestAllTypes.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_unittest.TestAllTypes.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_unittest.TestAllTypes.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_unittest.TestAllTypes.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_unittest.TestAllTypes.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_unittest.TestAllTypes.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_unittest.TestAllTypes.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_unittest.TestAllTypes.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_unittest.TestAllTypes.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_unittest.TestAllTypes.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_unittest.TestAllTypes.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_unittest.TestAllTypes.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_unittest.TestAllTypes.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestAllTypes.optionalgroup', index=15, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest.TestAllTypes.optional_nested_message', index=16, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_unittest.TestAllTypes.optional_foreign_message', index=17, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_message', full_name='protobuf_unittest.TestAllTypes.optional_import_message', index=18, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_unittest.TestAllTypes.optional_nested_enum', index=19, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_unittest.TestAllTypes.optional_foreign_enum', index=20, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_enum', full_name='protobuf_unittest.TestAllTypes.optional_import_enum', index=21, + number=23, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_unittest.TestAllTypes.optional_string_piece', index=22, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_unittest.TestAllTypes.optional_cord', index=23, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_public_import_message', full_name='protobuf_unittest.TestAllTypes.optional_public_import_message', index=24, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_lazy_message', full_name='protobuf_unittest.TestAllTypes.optional_lazy_message', index=25, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest.TestAllTypes.repeated_int32', index=26, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_unittest.TestAllTypes.repeated_int64', index=27, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_unittest.TestAllTypes.repeated_uint32', index=28, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_unittest.TestAllTypes.repeated_uint64', index=29, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_unittest.TestAllTypes.repeated_sint32', index=30, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_unittest.TestAllTypes.repeated_sint64', index=31, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_unittest.TestAllTypes.repeated_fixed32', index=32, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_unittest.TestAllTypes.repeated_fixed64', index=33, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_unittest.TestAllTypes.repeated_sfixed32', index=34, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_unittest.TestAllTypes.repeated_sfixed64', index=35, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_unittest.TestAllTypes.repeated_float', index=36, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_unittest.TestAllTypes.repeated_double', index=37, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_unittest.TestAllTypes.repeated_bool', index=38, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_unittest.TestAllTypes.repeated_string', index=39, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_unittest.TestAllTypes.repeated_bytes', index=40, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest.TestAllTypes.repeatedgroup', index=41, + number=46, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_unittest.TestAllTypes.repeated_nested_message', index=42, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_unittest.TestAllTypes.repeated_foreign_message', index=43, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_message', full_name='protobuf_unittest.TestAllTypes.repeated_import_message', index=44, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_unittest.TestAllTypes.repeated_nested_enum', index=45, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_unittest.TestAllTypes.repeated_foreign_enum', index=46, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_enum', full_name='protobuf_unittest.TestAllTypes.repeated_import_enum', index=47, + number=53, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_unittest.TestAllTypes.repeated_string_piece', index=48, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_unittest.TestAllTypes.repeated_cord', index=49, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_lazy_message', full_name='protobuf_unittest.TestAllTypes.repeated_lazy_message', index=50, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int32', full_name='protobuf_unittest.TestAllTypes.default_int32', index=51, + number=61, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=41, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int64', full_name='protobuf_unittest.TestAllTypes.default_int64', index=52, + number=62, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint32', full_name='protobuf_unittest.TestAllTypes.default_uint32', index=53, + number=63, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=43, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint64', full_name='protobuf_unittest.TestAllTypes.default_uint64', index=54, + number=64, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=44, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint32', full_name='protobuf_unittest.TestAllTypes.default_sint32', index=55, + number=65, type=17, cpp_type=1, label=1, + has_default_value=True, default_value=-45, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint64', full_name='protobuf_unittest.TestAllTypes.default_sint64', index=56, + number=66, type=18, cpp_type=2, label=1, + has_default_value=True, default_value=46, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed32', full_name='protobuf_unittest.TestAllTypes.default_fixed32', index=57, + number=67, type=7, cpp_type=3, label=1, + has_default_value=True, default_value=47, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed64', full_name='protobuf_unittest.TestAllTypes.default_fixed64', index=58, + number=68, type=6, cpp_type=4, label=1, + has_default_value=True, default_value=48, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed32', full_name='protobuf_unittest.TestAllTypes.default_sfixed32', index=59, + number=69, type=15, cpp_type=1, label=1, + has_default_value=True, default_value=49, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed64', full_name='protobuf_unittest.TestAllTypes.default_sfixed64', index=60, + number=70, type=16, cpp_type=2, label=1, + has_default_value=True, default_value=-50, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_float', full_name='protobuf_unittest.TestAllTypes.default_float', index=61, + number=71, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(51.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_double', full_name='protobuf_unittest.TestAllTypes.default_double', index=62, + number=72, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(52000), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bool', full_name='protobuf_unittest.TestAllTypes.default_bool', index=63, + number=73, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string', full_name='protobuf_unittest.TestAllTypes.default_string', index=64, + number=74, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bytes', full_name='protobuf_unittest.TestAllTypes.default_bytes', index=65, + number=75, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("world"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_nested_enum', full_name='protobuf_unittest.TestAllTypes.default_nested_enum', index=66, + number=81, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_foreign_enum', full_name='protobuf_unittest.TestAllTypes.default_foreign_enum', index=67, + number=82, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_import_enum', full_name='protobuf_unittest.TestAllTypes.default_import_enum', index=68, + number=83, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=8, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string_piece', full_name='protobuf_unittest.TestAllTypes.default_string_piece', index=69, + number=84, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("abc").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_cord', full_name='protobuf_unittest.TestAllTypes.default_cord', index=70, + number=85, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("123").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_unittest.TestAllTypes.oneof_uint32', index=71, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_unittest.TestAllTypes.oneof_nested_message', index=72, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_unittest.TestAllTypes.oneof_string', index=73, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_unittest.TestAllTypes.oneof_bytes', index=74, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, _TESTALLTYPES_OPTIONALGROUP, _TESTALLTYPES_REPEATEDGROUP, ], + enum_types=[ + _TESTALLTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_unittest.TestAllTypes.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=93, + serialized_end=3274, +) + + +_NESTEDTESTALLTYPES = _descriptor.Descriptor( + name='NestedTestAllTypes', + full_name='protobuf_unittest.NestedTestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='child', full_name='protobuf_unittest.NestedTestAllTypes.child', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payload', full_name='protobuf_unittest.NestedTestAllTypes.payload', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_child', full_name='protobuf_unittest.NestedTestAllTypes.repeated_child', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3277, + serialized_end=3464, +) + + +_TESTDEPRECATEDFIELDS = _descriptor.Descriptor( + name='TestDeprecatedFields', + full_name='protobuf_unittest.TestDeprecatedFields', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated_int32', full_name='protobuf_unittest.TestDeprecatedFields.deprecated_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\030\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated_int32_in_oneof', full_name='protobuf_unittest.TestDeprecatedFields.deprecated_int32_in_oneof', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\030\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_fields', full_name='protobuf_unittest.TestDeprecatedFields.oneof_fields', + index=0, containing_type=None, fields=[]), + ], + serialized_start=3466, + serialized_end=3575, +) + + +_TESTDEPRECATEDMESSAGE = _descriptor.Descriptor( + name='TestDeprecatedMessage', + full_name='protobuf_unittest.TestDeprecatedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\030\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3577, + serialized_end=3604, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='protobuf_unittest.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest.ForeignMessage.d', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3606, + serialized_end=3644, +) + + +_TESTRESERVEDFIELDS = _descriptor.Descriptor( + name='TestReservedFields', + full_name='protobuf_unittest.TestReservedFields', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3646, + serialized_end=3694, +) + + +_TESTALLEXTENSIONS = _descriptor.Descriptor( + name='TestAllExtensions', + full_name='protobuf_unittest.TestAllExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=3696, + serialized_end=3725, +) + + +_OPTIONALGROUP_EXTENSION = _descriptor.Descriptor( + name='OptionalGroup_extension', + full_name='protobuf_unittest.OptionalGroup_extension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.OptionalGroup_extension.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3727, + serialized_end=3763, +) + + +_REPEATEDGROUP_EXTENSION = _descriptor.Descriptor( + name='RepeatedGroup_extension', + full_name='protobuf_unittest.RepeatedGroup_extension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.RepeatedGroup_extension.a', index=0, + number=47, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3765, + serialized_end=3801, +) + + +_TESTGROUP_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestGroup.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestGroup.OptionalGroup.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3146, + serialized_end=3172, +) + +_TESTGROUP = _descriptor.Descriptor( + name='TestGroup', + full_name='protobuf_unittest.TestGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestGroup.optionalgroup', index=0, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_unittest.TestGroup.optional_foreign_enum', index=1, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTGROUP_OPTIONALGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3804, + serialized_end=3973, +) + + +_TESTGROUPEXTENSION = _descriptor.Descriptor( + name='TestGroupExtension', + full_name='protobuf_unittest.TestGroupExtension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=3975, + serialized_end=4005, +) + + +_TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION = _descriptor.Descriptor( + name='OptionalGroup_extension', + full_name='protobuf_unittest.TestNestedExtension.OptionalGroup_extension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestNestedExtension.OptionalGroup_extension.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3727, + serialized_end=3763, +) + +_TESTNESTEDEXTENSION = _descriptor.Descriptor( + name='TestNestedExtension', + full_name='protobuf_unittest.TestNestedExtension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test', full_name='protobuf_unittest.TestNestedExtension.test', index=0, + number=1002, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("test").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_string_extension', full_name='protobuf_unittest.TestNestedExtension.nested_string_extension', index=1, + number=1003, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup_extension', full_name='protobuf_unittest.TestNestedExtension.optionalgroup_extension', index=2, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum_extension', full_name='protobuf_unittest.TestNestedExtension.optional_foreign_enum_extension', index=3, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4008, + serialized_end=4447, +) + + +_TESTREQUIRED = _descriptor.Descriptor( + name='TestRequired', + full_name='protobuf_unittest.TestRequired', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestRequired.a', index=0, + number=1, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy2', full_name='protobuf_unittest.TestRequired.dummy2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestRequired.b', index=2, + number=3, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy4', full_name='protobuf_unittest.TestRequired.dummy4', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy5', full_name='protobuf_unittest.TestRequired.dummy5', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy6', full_name='protobuf_unittest.TestRequired.dummy6', index=5, + number=6, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy7', full_name='protobuf_unittest.TestRequired.dummy7', index=6, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy8', full_name='protobuf_unittest.TestRequired.dummy8', index=7, + number=8, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy9', full_name='protobuf_unittest.TestRequired.dummy9', index=8, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy10', full_name='protobuf_unittest.TestRequired.dummy10', index=9, + number=10, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy11', full_name='protobuf_unittest.TestRequired.dummy11', index=10, + number=11, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy12', full_name='protobuf_unittest.TestRequired.dummy12', index=11, + number=12, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy13', full_name='protobuf_unittest.TestRequired.dummy13', index=12, + number=13, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy14', full_name='protobuf_unittest.TestRequired.dummy14', index=13, + number=14, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy15', full_name='protobuf_unittest.TestRequired.dummy15', index=14, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy16', full_name='protobuf_unittest.TestRequired.dummy16', index=15, + number=16, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy17', full_name='protobuf_unittest.TestRequired.dummy17', index=16, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy18', full_name='protobuf_unittest.TestRequired.dummy18', index=17, + number=18, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy19', full_name='protobuf_unittest.TestRequired.dummy19', index=18, + number=19, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy20', full_name='protobuf_unittest.TestRequired.dummy20', index=19, + number=20, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy21', full_name='protobuf_unittest.TestRequired.dummy21', index=20, + number=21, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy22', full_name='protobuf_unittest.TestRequired.dummy22', index=21, + number=22, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy23', full_name='protobuf_unittest.TestRequired.dummy23', index=22, + number=23, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy24', full_name='protobuf_unittest.TestRequired.dummy24', index=23, + number=24, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy25', full_name='protobuf_unittest.TestRequired.dummy25', index=24, + number=25, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy26', full_name='protobuf_unittest.TestRequired.dummy26', index=25, + number=26, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy27', full_name='protobuf_unittest.TestRequired.dummy27', index=26, + number=27, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy28', full_name='protobuf_unittest.TestRequired.dummy28', index=27, + number=28, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy29', full_name='protobuf_unittest.TestRequired.dummy29', index=28, + number=29, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy30', full_name='protobuf_unittest.TestRequired.dummy30', index=29, + number=30, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy31', full_name='protobuf_unittest.TestRequired.dummy31', index=30, + number=31, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy32', full_name='protobuf_unittest.TestRequired.dummy32', index=31, + number=32, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.TestRequired.c', index=32, + number=33, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='single', full_name='protobuf_unittest.TestRequired.single', index=0, + number=1000, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='multi', full_name='protobuf_unittest.TestRequired.multi', index=1, + number=1001, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4450, + serialized_end=5175, +) + + +_TESTREQUIREDFOREIGN = _descriptor.Descriptor( + name='TestRequiredForeign', + full_name='protobuf_unittest.TestRequiredForeign', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest.TestRequiredForeign.optional_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_message', full_name='protobuf_unittest.TestRequiredForeign.repeated_message', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy', full_name='protobuf_unittest.TestRequiredForeign.dummy', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5178, + serialized_end=5332, +) + + +_TESTREQUIREDMESSAGE = _descriptor.Descriptor( + name='TestRequiredMessage', + full_name='protobuf_unittest.TestRequiredMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest.TestRequiredMessage.optional_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_message', full_name='protobuf_unittest.TestRequiredMessage.repeated_message', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='required_message', full_name='protobuf_unittest.TestRequiredMessage.required_message', index=2, + number=3, type=11, cpp_type=10, label=2, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5335, + serialized_end=5533, +) + + +_TESTFOREIGNNESTED = _descriptor.Descriptor( + name='TestForeignNested', + full_name='protobuf_unittest.TestForeignNested', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foreign_nested', full_name='protobuf_unittest.TestForeignNested.foreign_nested', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5535, + serialized_end=5625, +) + + +_TESTEMPTYMESSAGE = _descriptor.Descriptor( + name='TestEmptyMessage', + full_name='protobuf_unittest.TestEmptyMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5627, + serialized_end=5645, +) + + +_TESTEMPTYMESSAGEWITHEXTENSIONS = _descriptor.Descriptor( + name='TestEmptyMessageWithExtensions', + full_name='protobuf_unittest.TestEmptyMessageWithExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=5647, + serialized_end=5689, +) + + +_TESTMULTIPLEEXTENSIONRANGES = _descriptor.Descriptor( + name='TestMultipleExtensionRanges', + full_name='protobuf_unittest.TestMultipleExtensionRanges', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(42, 43), (4143, 4244), (65536, 536870912), ], + oneofs=[ + ], + serialized_start=5691, + serialized_end=5746, +) + + +_TESTREALLYLARGETAGNUMBER = _descriptor.Descriptor( + name='TestReallyLargeTagNumber', + full_name='protobuf_unittest.TestReallyLargeTagNumber', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestReallyLargeTagNumber.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestReallyLargeTagNumber.bb', index=1, + number=268435455, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5748, + serialized_end=5800, +) + + +_TESTRECURSIVEMESSAGE = _descriptor.Descriptor( + name='TestRecursiveMessage', + full_name='protobuf_unittest.TestRecursiveMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestRecursiveMessage.a', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.TestRecursiveMessage.i', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5802, + serialized_end=5887, +) + + +_TESTMUTUALRECURSIONA_SUBMESSAGE = _descriptor.Descriptor( + name='SubMessage', + full_name='protobuf_unittest.TestMutualRecursionA.SubMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestMutualRecursionA.SubMessage.b', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6035, + serialized_end=6099, +) + +_TESTMUTUALRECURSIONA_SUBGROUP = _descriptor.Descriptor( + name='SubGroup', + full_name='protobuf_unittest.TestMutualRecursionA.SubGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestMutualRecursionA.SubGroup.sub_message', index=0, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='not_in_this_scc', full_name='protobuf_unittest.TestMutualRecursionA.SubGroup.not_in_this_scc', index=1, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6102, + serialized_end=6243, +) + +_TESTMUTUALRECURSIONA = _descriptor.Descriptor( + name='TestMutualRecursionA', + full_name='protobuf_unittest.TestMutualRecursionA', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestMutualRecursionA.bb', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='subgroup', full_name='protobuf_unittest.TestMutualRecursionA.subgroup', index=1, + number=2, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMUTUALRECURSIONA_SUBMESSAGE, _TESTMUTUALRECURSIONA_SUBGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5890, + serialized_end=6243, +) + + +_TESTMUTUALRECURSIONB = _descriptor.Descriptor( + name='TestMutualRecursionB', + full_name='protobuf_unittest.TestMutualRecursionB', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestMutualRecursionB.a', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest.TestMutualRecursionB.optional_int32', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6245, + serialized_end=6343, +) + + +_TESTISINITIALIZED_SUBMESSAGE_SUBGROUP = _descriptor.Descriptor( + name='SubGroup', + full_name='protobuf_unittest.TestIsInitialized.SubMessage.SubGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.TestIsInitialized.SubMessage.SubGroup.i', index=0, + number=2, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6527, + serialized_end=6548, +) + +_TESTISINITIALIZED_SUBMESSAGE = _descriptor.Descriptor( + name='SubMessage', + full_name='protobuf_unittest.TestIsInitialized.SubMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='subgroup', full_name='protobuf_unittest.TestIsInitialized.SubMessage.subgroup', index=0, + number=1, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTISINITIALIZED_SUBMESSAGE_SUBGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6437, + serialized_end=6548, +) + +_TESTISINITIALIZED = _descriptor.Descriptor( + name='TestIsInitialized', + full_name='protobuf_unittest.TestIsInitialized', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestIsInitialized.sub_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTISINITIALIZED_SUBMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6346, + serialized_end=6548, +) + + +_TESTDUPFIELDNUMBER_FOO = _descriptor.Descriptor( + name='Foo', + full_name='protobuf_unittest.TestDupFieldNumber.Foo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestDupFieldNumber.Foo.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6696, + serialized_end=6712, +) + +_TESTDUPFIELDNUMBER_BAR = _descriptor.Descriptor( + name='Bar', + full_name='protobuf_unittest.TestDupFieldNumber.Bar', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestDupFieldNumber.Bar.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6714, + serialized_end=6730, +) + +_TESTDUPFIELDNUMBER = _descriptor.Descriptor( + name='TestDupFieldNumber', + full_name='protobuf_unittest.TestDupFieldNumber', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestDupFieldNumber.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo', full_name='protobuf_unittest.TestDupFieldNumber.foo', index=1, + number=2, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar', full_name='protobuf_unittest.TestDupFieldNumber.bar', index=2, + number=3, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTDUPFIELDNUMBER_FOO, _TESTDUPFIELDNUMBER_BAR, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6551, + serialized_end=6730, +) + + +_TESTEAGERMESSAGE = _descriptor.Descriptor( + name='TestEagerMessage', + full_name='protobuf_unittest.TestEagerMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestEagerMessage.sub_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6732, + serialized_end=6808, +) + + +_TESTLAZYMESSAGE = _descriptor.Descriptor( + name='TestLazyMessage', + full_name='protobuf_unittest.TestLazyMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestLazyMessage.sub_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6810, + serialized_end=6885, +) + + +_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestNestedMessageHasBits.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nestedmessage_repeated_int32', full_name='protobuf_unittest.TestNestedMessageHasBits.NestedMessage.nestedmessage_repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nestedmessage_repeated_foreignmessage', full_name='protobuf_unittest.TestNestedMessageHasBits.NestedMessage.nestedmessage_repeated_foreignmessage', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7009, + serialized_end=7144, +) + +_TESTNESTEDMESSAGEHASBITS = _descriptor.Descriptor( + name='TestNestedMessageHasBits', + full_name='protobuf_unittest.TestNestedMessageHasBits', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest.TestNestedMessageHasBits.optional_nested_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6888, + serialized_end=7144, +) + + +_TESTCAMELCASEFIELDNAMES = _descriptor.Descriptor( + name='TestCamelCaseFieldNames', + full_name='protobuf_unittest.TestCamelCaseFieldNames', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='PrimitiveField', full_name='protobuf_unittest.TestCamelCaseFieldNames.PrimitiveField', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='StringField', full_name='protobuf_unittest.TestCamelCaseFieldNames.StringField', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='EnumField', full_name='protobuf_unittest.TestCamelCaseFieldNames.EnumField', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='MessageField', full_name='protobuf_unittest.TestCamelCaseFieldNames.MessageField', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='StringPieceField', full_name='protobuf_unittest.TestCamelCaseFieldNames.StringPieceField', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='CordField', full_name='protobuf_unittest.TestCamelCaseFieldNames.CordField', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedPrimitiveField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedPrimitiveField', index=6, + number=7, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedStringField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedStringField', index=7, + number=8, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedEnumField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedEnumField', index=8, + number=9, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedMessageField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedMessageField', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedStringPieceField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedStringPieceField', index=10, + number=11, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedCordField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedCordField', index=11, + number=12, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7147, + serialized_end=7632, +) + + +_TESTFIELDORDERINGS_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestFieldOrderings.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='oo', full_name='protobuf_unittest.TestFieldOrderings.NestedMessage.oo', index=0, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestFieldOrderings.NestedMessage.bb', index=1, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7797, + serialized_end=7836, +) + +_TESTFIELDORDERINGS = _descriptor.Descriptor( + name='TestFieldOrderings', + full_name='protobuf_unittest.TestFieldOrderings', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestFieldOrderings.my_string', index=0, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='my_int', full_name='protobuf_unittest.TestFieldOrderings.my_int', index=1, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='my_float', full_name='protobuf_unittest.TestFieldOrderings.my_float', index=2, + number=101, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest.TestFieldOrderings.optional_nested_message', index=3, + number=200, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTFIELDORDERINGS_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(2, 11), (12, 101), ], + oneofs=[ + ], + serialized_start=7635, + serialized_end=7848, +) + + +_TESTEXTENSIONORDERINGS1 = _descriptor.Descriptor( + name='TestExtensionOrderings1', + full_name='protobuf_unittest.TestExtensionOrderings1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestExtensionOrderings1.my_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test_ext_orderings1', full_name='protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1', index=0, + number=13, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7851, + serialized_end=8007, +) + + +_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3 = _descriptor.Descriptor( + name='TestExtensionOrderings3', + full_name='protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.my_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test_ext_orderings3', full_name='protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.test_ext_orderings3', index=0, + number=14, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8057, + serialized_end=8238, +) + +_TESTEXTENSIONORDERINGS2 = _descriptor.Descriptor( + name='TestExtensionOrderings2', + full_name='protobuf_unittest.TestExtensionOrderings2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestExtensionOrderings2.my_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test_ext_orderings2', full_name='protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2', index=0, + number=12, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8010, + serialized_end=8350, +) + + +_TESTEXTREMEDEFAULTVALUES = _descriptor.Descriptor( + name='TestExtremeDefaultValues', + full_name='protobuf_unittest.TestExtremeDefaultValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='escaped_bytes', full_name='protobuf_unittest.TestExtremeDefaultValues.escaped_bytes', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("\000\001\007\010\014\n\r\t\013\\\'\"\376"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='large_uint32', full_name='protobuf_unittest.TestExtremeDefaultValues.large_uint32', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=4294967295, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='large_uint64', full_name='protobuf_unittest.TestExtremeDefaultValues.large_uint64', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=18446744073709551615, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_int32', full_name='protobuf_unittest.TestExtremeDefaultValues.small_int32', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=-2147483647, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_int64', full_name='protobuf_unittest.TestExtremeDefaultValues.small_int64', index=4, + number=5, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=-9223372036854775807, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='really_small_int32', full_name='protobuf_unittest.TestExtremeDefaultValues.really_small_int32', index=5, + number=21, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=-2147483648, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='really_small_int64', full_name='protobuf_unittest.TestExtremeDefaultValues.really_small_int64', index=6, + number=22, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=-9223372036854775808, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='utf8_string', full_name='protobuf_unittest.TestExtremeDefaultValues.utf8_string', index=7, + number=6, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("\341\210\264").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='zero_float', full_name='protobuf_unittest.TestExtremeDefaultValues.zero_float', index=8, + number=7, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='one_float', full_name='protobuf_unittest.TestExtremeDefaultValues.one_float', index=9, + number=8, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(1), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_float', full_name='protobuf_unittest.TestExtremeDefaultValues.small_float', index=10, + number=9, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(1.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='negative_one_float', full_name='protobuf_unittest.TestExtremeDefaultValues.negative_one_float', index=11, + number=10, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(-1), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='negative_float', full_name='protobuf_unittest.TestExtremeDefaultValues.negative_float', index=12, + number=11, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(-1.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='large_float', full_name='protobuf_unittest.TestExtremeDefaultValues.large_float', index=13, + number=12, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(2e+08), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_negative_float', full_name='protobuf_unittest.TestExtremeDefaultValues.small_negative_float', index=14, + number=13, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(-8e-28), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='inf_double', full_name='protobuf_unittest.TestExtremeDefaultValues.inf_double', index=15, + number=14, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='neg_inf_double', full_name='protobuf_unittest.TestExtremeDefaultValues.neg_inf_double', index=16, + number=15, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=-1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nan_double', full_name='protobuf_unittest.TestExtremeDefaultValues.nan_double', index=17, + number=16, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=(1e10000 * 0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='inf_float', full_name='protobuf_unittest.TestExtremeDefaultValues.inf_float', index=18, + number=17, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='neg_inf_float', full_name='protobuf_unittest.TestExtremeDefaultValues.neg_inf_float', index=19, + number=18, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=-1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nan_float', full_name='protobuf_unittest.TestExtremeDefaultValues.nan_float', index=20, + number=19, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=(1e10000 * 0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cpp_trigraph', full_name='protobuf_unittest.TestExtremeDefaultValues.cpp_trigraph', index=21, + number=20, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("? ? ?? ?? ??? ??/ ??-").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.string_with_zero', index=22, + number=23, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hel\000lo").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.bytes_with_zero', index=23, + number=24, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("wor\000ld"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_piece_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.string_piece_with_zero', index=24, + number=25, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("ab\000c").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cord_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.cord_with_zero', index=25, + number=26, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("12\0003").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='replacement_string', full_name='protobuf_unittest.TestExtremeDefaultValues.replacement_string', index=26, + number=27, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("${unknown}").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8353, + serialized_end=9303, +) + + +_SPARSEENUMMESSAGE = _descriptor.Descriptor( + name='SparseEnumMessage', + full_name='protobuf_unittest.SparseEnumMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sparse_enum', full_name='protobuf_unittest.SparseEnumMessage.sparse_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=123, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9305, + serialized_end=9380, +) + + +_ONESTRING = _descriptor.Descriptor( + name='OneString', + full_name='protobuf_unittest.OneString', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.OneString.data', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9382, + serialized_end=9407, +) + + +_MORESTRING = _descriptor.Descriptor( + name='MoreString', + full_name='protobuf_unittest.MoreString', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.MoreString.data', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9409, + serialized_end=9435, +) + + +_ONEBYTES = _descriptor.Descriptor( + name='OneBytes', + full_name='protobuf_unittest.OneBytes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.OneBytes.data', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9437, + serialized_end=9461, +) + + +_MOREBYTES = _descriptor.Descriptor( + name='MoreBytes', + full_name='protobuf_unittest.MoreBytes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.MoreBytes.data', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9463, + serialized_end=9488, +) + + +_INT32MESSAGE = _descriptor.Descriptor( + name='Int32Message', + full_name='protobuf_unittest.Int32Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Int32Message.data', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9490, + serialized_end=9518, +) + + +_UINT32MESSAGE = _descriptor.Descriptor( + name='Uint32Message', + full_name='protobuf_unittest.Uint32Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Uint32Message.data', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9520, + serialized_end=9549, +) + + +_INT64MESSAGE = _descriptor.Descriptor( + name='Int64Message', + full_name='protobuf_unittest.Int64Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Int64Message.data', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9551, + serialized_end=9579, +) + + +_UINT64MESSAGE = _descriptor.Descriptor( + name='Uint64Message', + full_name='protobuf_unittest.Uint64Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Uint64Message.data', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9581, + serialized_end=9610, +) + + +_BOOLMESSAGE = _descriptor.Descriptor( + name='BoolMessage', + full_name='protobuf_unittest.BoolMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.BoolMessage.data', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9612, + serialized_end=9639, +) + + +_TESTONEOF_FOOGROUP = _descriptor.Descriptor( + name='FooGroup', + full_name='protobuf_unittest.TestOneof.FooGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestOneof.FooGroup.a', index=0, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestOneof.FooGroup.b', index=1, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9811, + serialized_end=9843, +) + +_TESTONEOF = _descriptor.Descriptor( + name='TestOneof', + full_name='protobuf_unittest.TestOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestOneof.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestOneof.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestOneof.foo_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foogroup', full_name='protobuf_unittest.TestOneof.foogroup', index=3, + number=4, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTONEOF_FOOGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='foo', full_name='protobuf_unittest.TestOneof.foo', + index=0, containing_type=None, fields=[]), + ], + serialized_start=9642, + serialized_end=9850, +) + + +_TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP = _descriptor.Descriptor( + name='FooGroup', + full_name='protobuf_unittest.TestOneofBackwardsCompatible.FooGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestOneofBackwardsCompatible.FooGroup.a', index=0, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestOneofBackwardsCompatible.FooGroup.b', index=1, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9811, + serialized_end=9843, +) + +_TESTONEOFBACKWARDSCOMPATIBLE = _descriptor.Descriptor( + name='TestOneofBackwardsCompatible', + full_name='protobuf_unittest.TestOneofBackwardsCompatible', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foo_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foogroup', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foogroup', index=3, + number=4, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9853, + serialized_end=10084, +) + + +_TESTONEOF2_FOOGROUP = _descriptor.Descriptor( + name='FooGroup', + full_name='protobuf_unittest.TestOneof2.FooGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestOneof2.FooGroup.a', index=0, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestOneof2.FooGroup.b', index=1, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10745, + serialized_end=10777, +) + +_TESTONEOF2_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestOneof2.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='qux_int', full_name='protobuf_unittest.TestOneof2.NestedMessage.qux_int', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='corge_int', full_name='protobuf_unittest.TestOneof2.NestedMessage.corge_int', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10779, + serialized_end=10830, +) + +_TESTONEOF2 = _descriptor.Descriptor( + name='TestOneof2', + full_name='protobuf_unittest.TestOneof2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestOneof2.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestOneof2.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_cord', full_name='protobuf_unittest.TestOneof2.foo_cord', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string_piece', full_name='protobuf_unittest.TestOneof2.foo_string_piece', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_bytes', full_name='protobuf_unittest.TestOneof2.foo_bytes', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_enum', full_name='protobuf_unittest.TestOneof2.foo_enum', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestOneof2.foo_message', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foogroup', full_name='protobuf_unittest.TestOneof2.foogroup', index=7, + number=8, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_lazy_message', full_name='protobuf_unittest.TestOneof2.foo_lazy_message', index=8, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_int', full_name='protobuf_unittest.TestOneof2.bar_int', index=9, + number=12, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_string', full_name='protobuf_unittest.TestOneof2.bar_string', index=10, + number=13, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("STRING").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_cord', full_name='protobuf_unittest.TestOneof2.bar_cord', index=11, + number=14, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("CORD").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_string_piece', full_name='protobuf_unittest.TestOneof2.bar_string_piece', index=12, + number=15, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("SPIECE").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_bytes', full_name='protobuf_unittest.TestOneof2.bar_bytes', index=13, + number=16, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("BYTES"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_enum', full_name='protobuf_unittest.TestOneof2.bar_enum', index=14, + number=17, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='baz_int', full_name='protobuf_unittest.TestOneof2.baz_int', index=15, + number=18, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='baz_string', full_name='protobuf_unittest.TestOneof2.baz_string', index=16, + number=19, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("BAZ").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTONEOF2_FOOGROUP, _TESTONEOF2_NESTEDMESSAGE, ], + enum_types=[ + _TESTONEOF2_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='foo', full_name='protobuf_unittest.TestOneof2.foo', + index=0, containing_type=None, fields=[]), + _descriptor.OneofDescriptor( + name='bar', full_name='protobuf_unittest.TestOneof2.bar', + index=1, containing_type=None, fields=[]), + ], + serialized_start=10087, + serialized_end=10885, +) + + +_TESTREQUIREDONEOF_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestRequiredOneof.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='required_double', full_name='protobuf_unittest.TestRequiredOneof.NestedMessage.required_double', index=0, + number=1, type=1, cpp_type=5, label=2, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11025, + serialized_end=11065, +) + +_TESTREQUIREDONEOF = _descriptor.Descriptor( + name='TestRequiredOneof', + full_name='protobuf_unittest.TestRequiredOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestRequiredOneof.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestRequiredOneof.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestRequiredOneof.foo_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTREQUIREDONEOF_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='foo', full_name='protobuf_unittest.TestRequiredOneof.foo', + index=0, containing_type=None, fields=[]), + ], + serialized_start=10888, + serialized_end=11072, +) + + +_TESTPACKEDTYPES = _descriptor.Descriptor( + name='TestPackedTypes', + full_name='protobuf_unittest.TestPackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='packed_int32', full_name='protobuf_unittest.TestPackedTypes.packed_int32', index=0, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_int64', full_name='protobuf_unittest.TestPackedTypes.packed_int64', index=1, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint32', full_name='protobuf_unittest.TestPackedTypes.packed_uint32', index=2, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint64', full_name='protobuf_unittest.TestPackedTypes.packed_uint64', index=3, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint32', full_name='protobuf_unittest.TestPackedTypes.packed_sint32', index=4, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint64', full_name='protobuf_unittest.TestPackedTypes.packed_sint64', index=5, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed32', full_name='protobuf_unittest.TestPackedTypes.packed_fixed32', index=6, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed64', full_name='protobuf_unittest.TestPackedTypes.packed_fixed64', index=7, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed32', full_name='protobuf_unittest.TestPackedTypes.packed_sfixed32', index=8, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed64', full_name='protobuf_unittest.TestPackedTypes.packed_sfixed64', index=9, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_float', full_name='protobuf_unittest.TestPackedTypes.packed_float', index=10, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_double', full_name='protobuf_unittest.TestPackedTypes.packed_double', index=11, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_bool', full_name='protobuf_unittest.TestPackedTypes.packed_bool', index=12, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='protobuf_unittest.TestPackedTypes.packed_enum', index=13, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11075, + serialized_end=11501, +) + + +_TESTUNPACKEDTYPES = _descriptor.Descriptor( + name='TestUnpackedTypes', + full_name='protobuf_unittest.TestUnpackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='unpacked_int32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_int32', index=0, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_int64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_int64', index=1, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_uint32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_uint32', index=2, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_uint64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_uint64', index=3, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sint32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sint32', index=4, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sint64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sint64', index=5, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_fixed32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_fixed32', index=6, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_fixed64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_fixed64', index=7, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sfixed32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sfixed32', index=8, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sfixed64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sfixed64', index=9, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_float', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_float', index=10, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_double', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_double', index=11, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_bool', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_bool', index=12, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_enum', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_enum', index=13, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11504, + serialized_end=11960, +) + + +_TESTPACKEDEXTENSIONS = _descriptor.Descriptor( + name='TestPackedExtensions', + full_name='protobuf_unittest.TestPackedExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=11962, + serialized_end=11994, +) + + +_TESTUNPACKEDEXTENSIONS = _descriptor.Descriptor( + name='TestUnpackedExtensions', + full_name='protobuf_unittest.TestUnpackedExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=11996, + serialized_end=12030, +) + + +_TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE = _descriptor.Descriptor( + name='DynamicMessageType', + full_name='protobuf_unittest.TestDynamicExtensions.DynamicMessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='dynamic_field', full_name='protobuf_unittest.TestDynamicExtensions.DynamicMessageType.dynamic_field', index=0, + number=2100, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12453, + serialized_end=12497, +) + +_TESTDYNAMICEXTENSIONS = _descriptor.Descriptor( + name='TestDynamicExtensions', + full_name='protobuf_unittest.TestDynamicExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='scalar_extension', full_name='protobuf_unittest.TestDynamicExtensions.scalar_extension', index=0, + number=2000, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_extension', full_name='protobuf_unittest.TestDynamicExtensions.enum_extension', index=1, + number=2001, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dynamic_enum_extension', full_name='protobuf_unittest.TestDynamicExtensions.dynamic_enum_extension', index=2, + number=2002, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=2200, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_extension', full_name='protobuf_unittest.TestDynamicExtensions.message_extension', index=3, + number=2003, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dynamic_message_extension', full_name='protobuf_unittest.TestDynamicExtensions.dynamic_message_extension', index=4, + number=2004, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_extension', full_name='protobuf_unittest.TestDynamicExtensions.repeated_extension', index=5, + number=2005, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_extension', full_name='protobuf_unittest.TestDynamicExtensions.packed_extension', index=6, + number=2006, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE, ], + enum_types=[ + _TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12033, + serialized_end=12570, +) + + +_TESTREPEATEDSCALARDIFFERENTTAGSIZES = _descriptor.Descriptor( + name='TestRepeatedScalarDifferentTagSizes', + full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_fixed32', index=0, + number=12, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_int32', index=1, + number=13, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_fixed64', index=2, + number=2046, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_int64', index=3, + number=2047, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_float', index=4, + number=262142, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_uint64', index=5, + number=262143, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12573, + serialized_end=12765, +) + + +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1 = _descriptor.Descriptor( + name='Group1', + full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1.field1', index=0, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13558, + serialized_end=13615, +) + +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2 = _descriptor.Descriptor( + name='Group2', + full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2.field1', index=0, + number=21, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13617, + serialized_end=13674, +) + +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR = _descriptor.Descriptor( + name='RepeatedFieldsGenerator', + full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.field1', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field2', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.field2', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field3', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.field3', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='group1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.group1', index=3, + number=10, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='group2', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.group2', index=4, + number=20, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ext1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.ext1', index=5, + number=1000, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ext2', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.ext2', index=6, + number=1001, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1, _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13120, + serialized_end=13674, +) + +_TESTPARSINGMERGE_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestParsingMerge.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_group_all_types', full_name='protobuf_unittest.TestParsingMerge.OptionalGroup.optional_group_all_types', index=0, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13676, + serialized_end=13758, +) + +_TESTPARSINGMERGE_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest.TestParsingMerge.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_group_all_types', full_name='protobuf_unittest.TestParsingMerge.RepeatedGroup.repeated_group_all_types', index=0, + number=21, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13760, + serialized_end=13842, +) + +_TESTPARSINGMERGE = _descriptor.Descriptor( + name='TestParsingMerge', + full_name='protobuf_unittest.TestParsingMerge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='required_all_types', full_name='protobuf_unittest.TestParsingMerge.required_all_types', index=0, + number=1, type=11, cpp_type=10, label=2, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_all_types', full_name='protobuf_unittest.TestParsingMerge.optional_all_types', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_all_types', full_name='protobuf_unittest.TestParsingMerge.repeated_all_types', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestParsingMerge.optionalgroup', index=3, + number=10, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest.TestParsingMerge.repeatedgroup', index=4, + number=20, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='optional_ext', full_name='protobuf_unittest.TestParsingMerge.optional_ext', index=0, + number=1000, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_ext', full_name='protobuf_unittest.TestParsingMerge.repeated_ext', index=1, + number=1001, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR, _TESTPARSINGMERGE_OPTIONALGROUP, _TESTPARSINGMERGE_REPEATEDGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=12768, + serialized_end=14039, +) + + +_TESTCOMMENTINJECTIONMESSAGE = _descriptor.Descriptor( + name='TestCommentInjectionMessage', + full_name='protobuf_unittest.TestCommentInjectionMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestCommentInjectionMessage.a', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("*/ <- Neither should this.").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14041, + serialized_end=14109, +) + + +_FOOREQUEST = _descriptor.Descriptor( + name='FooRequest', + full_name='protobuf_unittest.FooRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14111, + serialized_end=14123, +) + + +_FOORESPONSE = _descriptor.Descriptor( + name='FooResponse', + full_name='protobuf_unittest.FooResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14125, + serialized_end=14138, +) + + +_FOOCLIENTMESSAGE = _descriptor.Descriptor( + name='FooClientMessage', + full_name='protobuf_unittest.FooClientMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14140, + serialized_end=14158, +) + + +_FOOSERVERMESSAGE = _descriptor.Descriptor( + name='FooServerMessage', + full_name='protobuf_unittest.FooServerMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14160, + serialized_end=14178, +) + + +_BARREQUEST = _descriptor.Descriptor( + name='BarRequest', + full_name='protobuf_unittest.BarRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14180, + serialized_end=14192, +) + + +_BARRESPONSE = _descriptor.Descriptor( + name='BarResponse', + full_name='protobuf_unittest.BarResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14194, + serialized_end=14207, +) + + +_TESTJSONNAME = _descriptor.Descriptor( + name='TestJsonName', + full_name='protobuf_unittest.TestJsonName', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field_name1', full_name='protobuf_unittest.TestJsonName.field_name1', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldName2', full_name='protobuf_unittest.TestJsonName.fieldName2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FieldName3', full_name='protobuf_unittest.TestJsonName.FieldName3', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='_field_name4', full_name='protobuf_unittest.TestJsonName._field_name4', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_NAME5', full_name='protobuf_unittest.TestJsonName.FIELD_NAME5', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name6', full_name='protobuf_unittest.TestJsonName.field_name6', index=5, + number=6, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='@type', file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14210, + serialized_end=14356, +) + + +_TESTHUGEFIELDNUMBERS_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestHugeFieldNumbers.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='group_a', full_name='protobuf_unittest.TestHugeFieldNumbers.OptionalGroup.group_a', index=0, + number=536870009, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15003, + serialized_end=15039, +) + +_TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY = _descriptor.Descriptor( + name='StringStringMapEntry', + full_name='protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15041, + serialized_end=15095, +) + +_TESTHUGEFIELDNUMBERS = _descriptor.Descriptor( + name='TestHugeFieldNumbers', + full_name='protobuf_unittest.TestHugeFieldNumbers', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_int32', index=0, + number=536870000, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fixed_32', full_name='protobuf_unittest.TestHugeFieldNumbers.fixed_32', index=1, + number=536870001, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest.TestHugeFieldNumbers.repeated_int32', index=2, + number=536870002, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_int32', full_name='protobuf_unittest.TestHugeFieldNumbers.packed_int32', index=3, + number=536870003, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_enum', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_enum', index=4, + number=536870004, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_string', index=5, + number=536870005, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_bytes', index=6, + number=536870006, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_message', index=7, + number=536870007, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestHugeFieldNumbers.optionalgroup', index=8, + number=536870008, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_string_map', full_name='protobuf_unittest.TestHugeFieldNumbers.string_string_map', index=9, + number=536870010, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_uint32', index=10, + number=536870011, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_test_all_types', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_test_all_types', index=11, + number=536870012, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_string', index=12, + number=536870013, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_bytes', index=13, + number=536870014, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTHUGEFIELDNUMBERS_OPTIONALGROUP, _TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(536860000, 536870000), ], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=14359, + serialized_end=15124, +) + + +_TESTEXTENSIONINSIDETABLE = _descriptor.Descriptor( + name='TestExtensionInsideTable', + full_name='protobuf_unittest.TestExtensionInsideTable', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestExtensionInsideTable.field1', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field2', full_name='protobuf_unittest.TestExtensionInsideTable.field2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field3', full_name='protobuf_unittest.TestExtensionInsideTable.field3', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field4', full_name='protobuf_unittest.TestExtensionInsideTable.field4', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field6', full_name='protobuf_unittest.TestExtensionInsideTable.field6', index=4, + number=6, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field7', full_name='protobuf_unittest.TestExtensionInsideTable.field7', index=5, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field8', full_name='protobuf_unittest.TestExtensionInsideTable.field8', index=6, + number=8, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field9', full_name='protobuf_unittest.TestExtensionInsideTable.field9', index=7, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field10', full_name='protobuf_unittest.TestExtensionInsideTable.field10', index=8, + number=10, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(5, 6), ], + oneofs=[ + ], + serialized_start=15127, + serialized_end=15304, +) + +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES_OPTIONALGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES_REPEATEDGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['optionalgroup'].message_type = _TESTALLTYPES_OPTIONALGROUP +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['optional_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['optional_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['optional_public_import_message'].message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeatedgroup'].message_type = _TESTALLTYPES_REPEATEDGROUP +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['repeated_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['repeated_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['repeated_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['default_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['default_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['default_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES_NESTEDENUM.containing_type = _TESTALLTYPES +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_uint32']) +_TESTALLTYPES.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_nested_message']) +_TESTALLTYPES.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_string']) +_TESTALLTYPES.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_bytes']) +_TESTALLTYPES.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_NESTEDTESTALLTYPES.fields_by_name['child'].message_type = _NESTEDTESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['payload'].message_type = _TESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['repeated_child'].message_type = _NESTEDTESTALLTYPES +_TESTDEPRECATEDFIELDS.oneofs_by_name['oneof_fields'].fields.append( + _TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32_in_oneof']) +_TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32_in_oneof'].containing_oneof = _TESTDEPRECATEDFIELDS.oneofs_by_name['oneof_fields'] +_TESTGROUP_OPTIONALGROUP.containing_type = _TESTGROUP +_TESTGROUP.fields_by_name['optionalgroup'].message_type = _TESTGROUP_OPTIONALGROUP +_TESTGROUP.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION.containing_type = _TESTNESTEDEXTENSION +_TESTREQUIREDFOREIGN.fields_by_name['optional_message'].message_type = _TESTREQUIRED +_TESTREQUIREDFOREIGN.fields_by_name['repeated_message'].message_type = _TESTREQUIRED +_TESTREQUIREDMESSAGE.fields_by_name['optional_message'].message_type = _TESTREQUIRED +_TESTREQUIREDMESSAGE.fields_by_name['repeated_message'].message_type = _TESTREQUIRED +_TESTREQUIREDMESSAGE.fields_by_name['required_message'].message_type = _TESTREQUIRED +_TESTFOREIGNNESTED.fields_by_name['foreign_nested'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTRECURSIVEMESSAGE.fields_by_name['a'].message_type = _TESTRECURSIVEMESSAGE +_TESTMUTUALRECURSIONA_SUBMESSAGE.fields_by_name['b'].message_type = _TESTMUTUALRECURSIONB +_TESTMUTUALRECURSIONA_SUBMESSAGE.containing_type = _TESTMUTUALRECURSIONA +_TESTMUTUALRECURSIONA_SUBGROUP.fields_by_name['sub_message'].message_type = _TESTMUTUALRECURSIONA_SUBMESSAGE +_TESTMUTUALRECURSIONA_SUBGROUP.fields_by_name['not_in_this_scc'].message_type = _TESTALLTYPES +_TESTMUTUALRECURSIONA_SUBGROUP.containing_type = _TESTMUTUALRECURSIONA +_TESTMUTUALRECURSIONA.fields_by_name['bb'].message_type = _TESTMUTUALRECURSIONB +_TESTMUTUALRECURSIONA.fields_by_name['subgroup'].message_type = _TESTMUTUALRECURSIONA_SUBGROUP +_TESTMUTUALRECURSIONB.fields_by_name['a'].message_type = _TESTMUTUALRECURSIONA +_TESTISINITIALIZED_SUBMESSAGE_SUBGROUP.containing_type = _TESTISINITIALIZED_SUBMESSAGE +_TESTISINITIALIZED_SUBMESSAGE.fields_by_name['subgroup'].message_type = _TESTISINITIALIZED_SUBMESSAGE_SUBGROUP +_TESTISINITIALIZED_SUBMESSAGE.containing_type = _TESTISINITIALIZED +_TESTISINITIALIZED.fields_by_name['sub_message'].message_type = _TESTISINITIALIZED_SUBMESSAGE +_TESTDUPFIELDNUMBER_FOO.containing_type = _TESTDUPFIELDNUMBER +_TESTDUPFIELDNUMBER_BAR.containing_type = _TESTDUPFIELDNUMBER +_TESTDUPFIELDNUMBER.fields_by_name['foo'].message_type = _TESTDUPFIELDNUMBER_FOO +_TESTDUPFIELDNUMBER.fields_by_name['bar'].message_type = _TESTDUPFIELDNUMBER_BAR +_TESTEAGERMESSAGE.fields_by_name['sub_message'].message_type = _TESTALLTYPES +_TESTLAZYMESSAGE.fields_by_name['sub_message'].message_type = _TESTALLTYPES +_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE.fields_by_name['nestedmessage_repeated_foreignmessage'].message_type = _FOREIGNMESSAGE +_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE.containing_type = _TESTNESTEDMESSAGEHASBITS +_TESTNESTEDMESSAGEHASBITS.fields_by_name['optional_nested_message'].message_type = _TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE +_TESTCAMELCASEFIELDNAMES.fields_by_name['EnumField'].enum_type = _FOREIGNENUM +_TESTCAMELCASEFIELDNAMES.fields_by_name['MessageField'].message_type = _FOREIGNMESSAGE +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedEnumField'].enum_type = _FOREIGNENUM +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedMessageField'].message_type = _FOREIGNMESSAGE +_TESTFIELDORDERINGS_NESTEDMESSAGE.containing_type = _TESTFIELDORDERINGS +_TESTFIELDORDERINGS.fields_by_name['optional_nested_message'].message_type = _TESTFIELDORDERINGS_NESTEDMESSAGE +_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3.containing_type = _TESTEXTENSIONORDERINGS2 +_SPARSEENUMMESSAGE.fields_by_name['sparse_enum'].enum_type = _TESTSPARSEENUM +_TESTONEOF_FOOGROUP.containing_type = _TESTONEOF +_TESTONEOF.fields_by_name['foo_message'].message_type = _TESTALLTYPES +_TESTONEOF.fields_by_name['foogroup'].message_type = _TESTONEOF_FOOGROUP +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foo_int']) +_TESTONEOF.fields_by_name['foo_int'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foo_string']) +_TESTONEOF.fields_by_name['foo_string'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foo_message']) +_TESTONEOF.fields_by_name['foo_message'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foogroup']) +_TESTONEOF.fields_by_name['foogroup'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP.containing_type = _TESTONEOFBACKWARDSCOMPATIBLE +_TESTONEOFBACKWARDSCOMPATIBLE.fields_by_name['foo_message'].message_type = _TESTALLTYPES +_TESTONEOFBACKWARDSCOMPATIBLE.fields_by_name['foogroup'].message_type = _TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP +_TESTONEOF2_FOOGROUP.containing_type = _TESTONEOF2 +_TESTONEOF2_NESTEDMESSAGE.containing_type = _TESTONEOF2 +_TESTONEOF2.fields_by_name['foo_enum'].enum_type = _TESTONEOF2_NESTEDENUM +_TESTONEOF2.fields_by_name['foo_message'].message_type = _TESTONEOF2_NESTEDMESSAGE +_TESTONEOF2.fields_by_name['foogroup'].message_type = _TESTONEOF2_FOOGROUP +_TESTONEOF2.fields_by_name['foo_lazy_message'].message_type = _TESTONEOF2_NESTEDMESSAGE +_TESTONEOF2.fields_by_name['bar_enum'].enum_type = _TESTONEOF2_NESTEDENUM +_TESTONEOF2_NESTEDENUM.containing_type = _TESTONEOF2 +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_int']) +_TESTONEOF2.fields_by_name['foo_int'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_string']) +_TESTONEOF2.fields_by_name['foo_string'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_cord']) +_TESTONEOF2.fields_by_name['foo_cord'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_string_piece']) +_TESTONEOF2.fields_by_name['foo_string_piece'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_bytes']) +_TESTONEOF2.fields_by_name['foo_bytes'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_enum']) +_TESTONEOF2.fields_by_name['foo_enum'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_message']) +_TESTONEOF2.fields_by_name['foo_message'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foogroup']) +_TESTONEOF2.fields_by_name['foogroup'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_lazy_message']) +_TESTONEOF2.fields_by_name['foo_lazy_message'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_int']) +_TESTONEOF2.fields_by_name['bar_int'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_string']) +_TESTONEOF2.fields_by_name['bar_string'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_cord']) +_TESTONEOF2.fields_by_name['bar_cord'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_string_piece']) +_TESTONEOF2.fields_by_name['bar_string_piece'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_bytes']) +_TESTONEOF2.fields_by_name['bar_bytes'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_enum']) +_TESTONEOF2.fields_by_name['bar_enum'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTREQUIREDONEOF_NESTEDMESSAGE.containing_type = _TESTREQUIREDONEOF +_TESTREQUIREDONEOF.fields_by_name['foo_message'].message_type = _TESTREQUIREDONEOF_NESTEDMESSAGE +_TESTREQUIREDONEOF.oneofs_by_name['foo'].fields.append( + _TESTREQUIREDONEOF.fields_by_name['foo_int']) +_TESTREQUIREDONEOF.fields_by_name['foo_int'].containing_oneof = _TESTREQUIREDONEOF.oneofs_by_name['foo'] +_TESTREQUIREDONEOF.oneofs_by_name['foo'].fields.append( + _TESTREQUIREDONEOF.fields_by_name['foo_string']) +_TESTREQUIREDONEOF.fields_by_name['foo_string'].containing_oneof = _TESTREQUIREDONEOF.oneofs_by_name['foo'] +_TESTREQUIREDONEOF.oneofs_by_name['foo'].fields.append( + _TESTREQUIREDONEOF.fields_by_name['foo_message']) +_TESTREQUIREDONEOF.fields_by_name['foo_message'].containing_oneof = _TESTREQUIREDONEOF.oneofs_by_name['foo'] +_TESTPACKEDTYPES.fields_by_name['packed_enum'].enum_type = _FOREIGNENUM +_TESTUNPACKEDTYPES.fields_by_name['unpacked_enum'].enum_type = _FOREIGNENUM +_TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE.containing_type = _TESTDYNAMICEXTENSIONS +_TESTDYNAMICEXTENSIONS.fields_by_name['enum_extension'].enum_type = _FOREIGNENUM +_TESTDYNAMICEXTENSIONS.fields_by_name['dynamic_enum_extension'].enum_type = _TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE +_TESTDYNAMICEXTENSIONS.fields_by_name['message_extension'].message_type = _FOREIGNMESSAGE +_TESTDYNAMICEXTENSIONS.fields_by_name['dynamic_message_extension'].message_type = _TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE +_TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE.containing_type = _TESTDYNAMICEXTENSIONS +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1.fields_by_name['field1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1.containing_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2.fields_by_name['field1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2.containing_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['field1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['field2'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['field3'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['group1'].message_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1 +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['group2'].message_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2 +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['ext1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['ext2'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.containing_type = _TESTPARSINGMERGE +_TESTPARSINGMERGE_OPTIONALGROUP.fields_by_name['optional_group_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_OPTIONALGROUP.containing_type = _TESTPARSINGMERGE +_TESTPARSINGMERGE_REPEATEDGROUP.fields_by_name['repeated_group_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDGROUP.containing_type = _TESTPARSINGMERGE +_TESTPARSINGMERGE.fields_by_name['required_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE.fields_by_name['optional_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE.fields_by_name['repeated_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE.fields_by_name['optionalgroup'].message_type = _TESTPARSINGMERGE_OPTIONALGROUP +_TESTPARSINGMERGE.fields_by_name['repeatedgroup'].message_type = _TESTPARSINGMERGE_REPEATEDGROUP +_TESTHUGEFIELDNUMBERS_OPTIONALGROUP.containing_type = _TESTHUGEFIELDNUMBERS +_TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY.containing_type = _TESTHUGEFIELDNUMBERS +_TESTHUGEFIELDNUMBERS.fields_by_name['optional_enum'].enum_type = _FOREIGNENUM +_TESTHUGEFIELDNUMBERS.fields_by_name['optional_message'].message_type = _FOREIGNMESSAGE +_TESTHUGEFIELDNUMBERS.fields_by_name['optionalgroup'].message_type = _TESTHUGEFIELDNUMBERS_OPTIONALGROUP +_TESTHUGEFIELDNUMBERS.fields_by_name['string_string_map'].message_type = _TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_test_all_types'].message_type = _TESTALLTYPES +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_uint32']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_uint32'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_test_all_types']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_test_all_types'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_string']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_string'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_bytes']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_bytes'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['NestedTestAllTypes'] = _NESTEDTESTALLTYPES +DESCRIPTOR.message_types_by_name['TestDeprecatedFields'] = _TESTDEPRECATEDFIELDS +DESCRIPTOR.message_types_by_name['TestDeprecatedMessage'] = _TESTDEPRECATEDMESSAGE +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestReservedFields'] = _TESTRESERVEDFIELDS +DESCRIPTOR.message_types_by_name['TestAllExtensions'] = _TESTALLEXTENSIONS +DESCRIPTOR.message_types_by_name['OptionalGroup_extension'] = _OPTIONALGROUP_EXTENSION +DESCRIPTOR.message_types_by_name['RepeatedGroup_extension'] = _REPEATEDGROUP_EXTENSION +DESCRIPTOR.message_types_by_name['TestGroup'] = _TESTGROUP +DESCRIPTOR.message_types_by_name['TestGroupExtension'] = _TESTGROUPEXTENSION +DESCRIPTOR.message_types_by_name['TestNestedExtension'] = _TESTNESTEDEXTENSION +DESCRIPTOR.message_types_by_name['TestRequired'] = _TESTREQUIRED +DESCRIPTOR.message_types_by_name['TestRequiredForeign'] = _TESTREQUIREDFOREIGN +DESCRIPTOR.message_types_by_name['TestRequiredMessage'] = _TESTREQUIREDMESSAGE +DESCRIPTOR.message_types_by_name['TestForeignNested'] = _TESTFOREIGNNESTED +DESCRIPTOR.message_types_by_name['TestEmptyMessage'] = _TESTEMPTYMESSAGE +DESCRIPTOR.message_types_by_name['TestEmptyMessageWithExtensions'] = _TESTEMPTYMESSAGEWITHEXTENSIONS +DESCRIPTOR.message_types_by_name['TestMultipleExtensionRanges'] = _TESTMULTIPLEEXTENSIONRANGES +DESCRIPTOR.message_types_by_name['TestReallyLargeTagNumber'] = _TESTREALLYLARGETAGNUMBER +DESCRIPTOR.message_types_by_name['TestRecursiveMessage'] = _TESTRECURSIVEMESSAGE +DESCRIPTOR.message_types_by_name['TestMutualRecursionA'] = _TESTMUTUALRECURSIONA +DESCRIPTOR.message_types_by_name['TestMutualRecursionB'] = _TESTMUTUALRECURSIONB +DESCRIPTOR.message_types_by_name['TestIsInitialized'] = _TESTISINITIALIZED +DESCRIPTOR.message_types_by_name['TestDupFieldNumber'] = _TESTDUPFIELDNUMBER +DESCRIPTOR.message_types_by_name['TestEagerMessage'] = _TESTEAGERMESSAGE +DESCRIPTOR.message_types_by_name['TestLazyMessage'] = _TESTLAZYMESSAGE +DESCRIPTOR.message_types_by_name['TestNestedMessageHasBits'] = _TESTNESTEDMESSAGEHASBITS +DESCRIPTOR.message_types_by_name['TestCamelCaseFieldNames'] = _TESTCAMELCASEFIELDNAMES +DESCRIPTOR.message_types_by_name['TestFieldOrderings'] = _TESTFIELDORDERINGS +DESCRIPTOR.message_types_by_name['TestExtensionOrderings1'] = _TESTEXTENSIONORDERINGS1 +DESCRIPTOR.message_types_by_name['TestExtensionOrderings2'] = _TESTEXTENSIONORDERINGS2 +DESCRIPTOR.message_types_by_name['TestExtremeDefaultValues'] = _TESTEXTREMEDEFAULTVALUES +DESCRIPTOR.message_types_by_name['SparseEnumMessage'] = _SPARSEENUMMESSAGE +DESCRIPTOR.message_types_by_name['OneString'] = _ONESTRING +DESCRIPTOR.message_types_by_name['MoreString'] = _MORESTRING +DESCRIPTOR.message_types_by_name['OneBytes'] = _ONEBYTES +DESCRIPTOR.message_types_by_name['MoreBytes'] = _MOREBYTES +DESCRIPTOR.message_types_by_name['Int32Message'] = _INT32MESSAGE +DESCRIPTOR.message_types_by_name['Uint32Message'] = _UINT32MESSAGE +DESCRIPTOR.message_types_by_name['Int64Message'] = _INT64MESSAGE +DESCRIPTOR.message_types_by_name['Uint64Message'] = _UINT64MESSAGE +DESCRIPTOR.message_types_by_name['BoolMessage'] = _BOOLMESSAGE +DESCRIPTOR.message_types_by_name['TestOneof'] = _TESTONEOF +DESCRIPTOR.message_types_by_name['TestOneofBackwardsCompatible'] = _TESTONEOFBACKWARDSCOMPATIBLE +DESCRIPTOR.message_types_by_name['TestOneof2'] = _TESTONEOF2 +DESCRIPTOR.message_types_by_name['TestRequiredOneof'] = _TESTREQUIREDONEOF +DESCRIPTOR.message_types_by_name['TestPackedTypes'] = _TESTPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestUnpackedTypes'] = _TESTUNPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestPackedExtensions'] = _TESTPACKEDEXTENSIONS +DESCRIPTOR.message_types_by_name['TestUnpackedExtensions'] = _TESTUNPACKEDEXTENSIONS +DESCRIPTOR.message_types_by_name['TestDynamicExtensions'] = _TESTDYNAMICEXTENSIONS +DESCRIPTOR.message_types_by_name['TestRepeatedScalarDifferentTagSizes'] = _TESTREPEATEDSCALARDIFFERENTTAGSIZES +DESCRIPTOR.message_types_by_name['TestParsingMerge'] = _TESTPARSINGMERGE +DESCRIPTOR.message_types_by_name['TestCommentInjectionMessage'] = _TESTCOMMENTINJECTIONMESSAGE +DESCRIPTOR.message_types_by_name['FooRequest'] = _FOOREQUEST +DESCRIPTOR.message_types_by_name['FooResponse'] = _FOORESPONSE +DESCRIPTOR.message_types_by_name['FooClientMessage'] = _FOOCLIENTMESSAGE +DESCRIPTOR.message_types_by_name['FooServerMessage'] = _FOOSERVERMESSAGE +DESCRIPTOR.message_types_by_name['BarRequest'] = _BARREQUEST +DESCRIPTOR.message_types_by_name['BarResponse'] = _BARRESPONSE +DESCRIPTOR.message_types_by_name['TestJsonName'] = _TESTJSONNAME +DESCRIPTOR.message_types_by_name['TestHugeFieldNumbers'] = _TESTHUGEFIELDNUMBERS +DESCRIPTOR.message_types_by_name['TestExtensionInsideTable'] = _TESTEXTENSIONINSIDETABLE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +DESCRIPTOR.enum_types_by_name['TestEnumWithDupValue'] = _TESTENUMWITHDUPVALUE +DESCRIPTOR.enum_types_by_name['TestSparseEnum'] = _TESTSPARSEENUM +DESCRIPTOR.extensions_by_name['optional_int32_extension'] = optional_int32_extension +DESCRIPTOR.extensions_by_name['optional_int64_extension'] = optional_int64_extension +DESCRIPTOR.extensions_by_name['optional_uint32_extension'] = optional_uint32_extension +DESCRIPTOR.extensions_by_name['optional_uint64_extension'] = optional_uint64_extension +DESCRIPTOR.extensions_by_name['optional_sint32_extension'] = optional_sint32_extension +DESCRIPTOR.extensions_by_name['optional_sint64_extension'] = optional_sint64_extension +DESCRIPTOR.extensions_by_name['optional_fixed32_extension'] = optional_fixed32_extension +DESCRIPTOR.extensions_by_name['optional_fixed64_extension'] = optional_fixed64_extension +DESCRIPTOR.extensions_by_name['optional_sfixed32_extension'] = optional_sfixed32_extension +DESCRIPTOR.extensions_by_name['optional_sfixed64_extension'] = optional_sfixed64_extension +DESCRIPTOR.extensions_by_name['optional_float_extension'] = optional_float_extension +DESCRIPTOR.extensions_by_name['optional_double_extension'] = optional_double_extension +DESCRIPTOR.extensions_by_name['optional_bool_extension'] = optional_bool_extension +DESCRIPTOR.extensions_by_name['optional_string_extension'] = optional_string_extension +DESCRIPTOR.extensions_by_name['optional_bytes_extension'] = optional_bytes_extension +DESCRIPTOR.extensions_by_name['optionalgroup_extension'] = optionalgroup_extension +DESCRIPTOR.extensions_by_name['optional_nested_message_extension'] = optional_nested_message_extension +DESCRIPTOR.extensions_by_name['optional_foreign_message_extension'] = optional_foreign_message_extension +DESCRIPTOR.extensions_by_name['optional_import_message_extension'] = optional_import_message_extension +DESCRIPTOR.extensions_by_name['optional_nested_enum_extension'] = optional_nested_enum_extension +DESCRIPTOR.extensions_by_name['optional_foreign_enum_extension'] = optional_foreign_enum_extension +DESCRIPTOR.extensions_by_name['optional_import_enum_extension'] = optional_import_enum_extension +DESCRIPTOR.extensions_by_name['optional_string_piece_extension'] = optional_string_piece_extension +DESCRIPTOR.extensions_by_name['optional_cord_extension'] = optional_cord_extension +DESCRIPTOR.extensions_by_name['optional_public_import_message_extension'] = optional_public_import_message_extension +DESCRIPTOR.extensions_by_name['optional_lazy_message_extension'] = optional_lazy_message_extension +DESCRIPTOR.extensions_by_name['repeated_int32_extension'] = repeated_int32_extension +DESCRIPTOR.extensions_by_name['repeated_int64_extension'] = repeated_int64_extension +DESCRIPTOR.extensions_by_name['repeated_uint32_extension'] = repeated_uint32_extension +DESCRIPTOR.extensions_by_name['repeated_uint64_extension'] = repeated_uint64_extension +DESCRIPTOR.extensions_by_name['repeated_sint32_extension'] = repeated_sint32_extension +DESCRIPTOR.extensions_by_name['repeated_sint64_extension'] = repeated_sint64_extension +DESCRIPTOR.extensions_by_name['repeated_fixed32_extension'] = repeated_fixed32_extension +DESCRIPTOR.extensions_by_name['repeated_fixed64_extension'] = repeated_fixed64_extension +DESCRIPTOR.extensions_by_name['repeated_sfixed32_extension'] = repeated_sfixed32_extension +DESCRIPTOR.extensions_by_name['repeated_sfixed64_extension'] = repeated_sfixed64_extension +DESCRIPTOR.extensions_by_name['repeated_float_extension'] = repeated_float_extension +DESCRIPTOR.extensions_by_name['repeated_double_extension'] = repeated_double_extension +DESCRIPTOR.extensions_by_name['repeated_bool_extension'] = repeated_bool_extension +DESCRIPTOR.extensions_by_name['repeated_string_extension'] = repeated_string_extension +DESCRIPTOR.extensions_by_name['repeated_bytes_extension'] = repeated_bytes_extension +DESCRIPTOR.extensions_by_name['repeatedgroup_extension'] = repeatedgroup_extension +DESCRIPTOR.extensions_by_name['repeated_nested_message_extension'] = repeated_nested_message_extension +DESCRIPTOR.extensions_by_name['repeated_foreign_message_extension'] = repeated_foreign_message_extension +DESCRIPTOR.extensions_by_name['repeated_import_message_extension'] = repeated_import_message_extension +DESCRIPTOR.extensions_by_name['repeated_nested_enum_extension'] = repeated_nested_enum_extension +DESCRIPTOR.extensions_by_name['repeated_foreign_enum_extension'] = repeated_foreign_enum_extension +DESCRIPTOR.extensions_by_name['repeated_import_enum_extension'] = repeated_import_enum_extension +DESCRIPTOR.extensions_by_name['repeated_string_piece_extension'] = repeated_string_piece_extension +DESCRIPTOR.extensions_by_name['repeated_cord_extension'] = repeated_cord_extension +DESCRIPTOR.extensions_by_name['repeated_lazy_message_extension'] = repeated_lazy_message_extension +DESCRIPTOR.extensions_by_name['default_int32_extension'] = default_int32_extension +DESCRIPTOR.extensions_by_name['default_int64_extension'] = default_int64_extension +DESCRIPTOR.extensions_by_name['default_uint32_extension'] = default_uint32_extension +DESCRIPTOR.extensions_by_name['default_uint64_extension'] = default_uint64_extension +DESCRIPTOR.extensions_by_name['default_sint32_extension'] = default_sint32_extension +DESCRIPTOR.extensions_by_name['default_sint64_extension'] = default_sint64_extension +DESCRIPTOR.extensions_by_name['default_fixed32_extension'] = default_fixed32_extension +DESCRIPTOR.extensions_by_name['default_fixed64_extension'] = default_fixed64_extension +DESCRIPTOR.extensions_by_name['default_sfixed32_extension'] = default_sfixed32_extension +DESCRIPTOR.extensions_by_name['default_sfixed64_extension'] = default_sfixed64_extension +DESCRIPTOR.extensions_by_name['default_float_extension'] = default_float_extension +DESCRIPTOR.extensions_by_name['default_double_extension'] = default_double_extension +DESCRIPTOR.extensions_by_name['default_bool_extension'] = default_bool_extension +DESCRIPTOR.extensions_by_name['default_string_extension'] = default_string_extension +DESCRIPTOR.extensions_by_name['default_bytes_extension'] = default_bytes_extension +DESCRIPTOR.extensions_by_name['default_nested_enum_extension'] = default_nested_enum_extension +DESCRIPTOR.extensions_by_name['default_foreign_enum_extension'] = default_foreign_enum_extension +DESCRIPTOR.extensions_by_name['default_import_enum_extension'] = default_import_enum_extension +DESCRIPTOR.extensions_by_name['default_string_piece_extension'] = default_string_piece_extension +DESCRIPTOR.extensions_by_name['default_cord_extension'] = default_cord_extension +DESCRIPTOR.extensions_by_name['oneof_uint32_extension'] = oneof_uint32_extension +DESCRIPTOR.extensions_by_name['oneof_nested_message_extension'] = oneof_nested_message_extension +DESCRIPTOR.extensions_by_name['oneof_string_extension'] = oneof_string_extension +DESCRIPTOR.extensions_by_name['oneof_bytes_extension'] = oneof_bytes_extension +DESCRIPTOR.extensions_by_name['my_extension_string'] = my_extension_string +DESCRIPTOR.extensions_by_name['my_extension_int'] = my_extension_int +DESCRIPTOR.extensions_by_name['packed_int32_extension'] = packed_int32_extension +DESCRIPTOR.extensions_by_name['packed_int64_extension'] = packed_int64_extension +DESCRIPTOR.extensions_by_name['packed_uint32_extension'] = packed_uint32_extension +DESCRIPTOR.extensions_by_name['packed_uint64_extension'] = packed_uint64_extension +DESCRIPTOR.extensions_by_name['packed_sint32_extension'] = packed_sint32_extension +DESCRIPTOR.extensions_by_name['packed_sint64_extension'] = packed_sint64_extension +DESCRIPTOR.extensions_by_name['packed_fixed32_extension'] = packed_fixed32_extension +DESCRIPTOR.extensions_by_name['packed_fixed64_extension'] = packed_fixed64_extension +DESCRIPTOR.extensions_by_name['packed_sfixed32_extension'] = packed_sfixed32_extension +DESCRIPTOR.extensions_by_name['packed_sfixed64_extension'] = packed_sfixed64_extension +DESCRIPTOR.extensions_by_name['packed_float_extension'] = packed_float_extension +DESCRIPTOR.extensions_by_name['packed_double_extension'] = packed_double_extension +DESCRIPTOR.extensions_by_name['packed_bool_extension'] = packed_bool_extension +DESCRIPTOR.extensions_by_name['packed_enum_extension'] = packed_enum_extension +DESCRIPTOR.extensions_by_name['unpacked_int32_extension'] = unpacked_int32_extension +DESCRIPTOR.extensions_by_name['unpacked_int64_extension'] = unpacked_int64_extension +DESCRIPTOR.extensions_by_name['unpacked_uint32_extension'] = unpacked_uint32_extension +DESCRIPTOR.extensions_by_name['unpacked_uint64_extension'] = unpacked_uint64_extension +DESCRIPTOR.extensions_by_name['unpacked_sint32_extension'] = unpacked_sint32_extension +DESCRIPTOR.extensions_by_name['unpacked_sint64_extension'] = unpacked_sint64_extension +DESCRIPTOR.extensions_by_name['unpacked_fixed32_extension'] = unpacked_fixed32_extension +DESCRIPTOR.extensions_by_name['unpacked_fixed64_extension'] = unpacked_fixed64_extension +DESCRIPTOR.extensions_by_name['unpacked_sfixed32_extension'] = unpacked_sfixed32_extension +DESCRIPTOR.extensions_by_name['unpacked_sfixed64_extension'] = unpacked_sfixed64_extension +DESCRIPTOR.extensions_by_name['unpacked_float_extension'] = unpacked_float_extension +DESCRIPTOR.extensions_by_name['unpacked_double_extension'] = unpacked_double_extension +DESCRIPTOR.extensions_by_name['unpacked_bool_extension'] = unpacked_bool_extension +DESCRIPTOR.extensions_by_name['unpacked_enum_extension'] = unpacked_enum_extension +DESCRIPTOR.extensions_by_name['test_all_types'] = test_all_types +DESCRIPTOR.extensions_by_name['test_extension_inside_table_extension'] = test_extension_inside_table_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes.NestedMessage) + )) + , + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes.OptionalGroup) + )) + , + + RepeatedGroup = _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_REPEATEDGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes.RepeatedGroup) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) +_sym_db.RegisterMessage(TestAllTypes.OptionalGroup) +_sym_db.RegisterMessage(TestAllTypes.RepeatedGroup) + +NestedTestAllTypes = _reflection.GeneratedProtocolMessageType('NestedTestAllTypes', (_message.Message,), dict( + DESCRIPTOR = _NESTEDTESTALLTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NestedTestAllTypes) + )) +_sym_db.RegisterMessage(NestedTestAllTypes) + +TestDeprecatedFields = _reflection.GeneratedProtocolMessageType('TestDeprecatedFields', (_message.Message,), dict( + DESCRIPTOR = _TESTDEPRECATEDFIELDS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDeprecatedFields) + )) +_sym_db.RegisterMessage(TestDeprecatedFields) + +TestDeprecatedMessage = _reflection.GeneratedProtocolMessageType('TestDeprecatedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTDEPRECATEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDeprecatedMessage) + )) +_sym_db.RegisterMessage(TestDeprecatedMessage) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestReservedFields = _reflection.GeneratedProtocolMessageType('TestReservedFields', (_message.Message,), dict( + DESCRIPTOR = _TESTRESERVEDFIELDS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestReservedFields) + )) +_sym_db.RegisterMessage(TestReservedFields) + +TestAllExtensions = _reflection.GeneratedProtocolMessageType('TestAllExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTALLEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllExtensions) + )) +_sym_db.RegisterMessage(TestAllExtensions) + +OptionalGroup_extension = _reflection.GeneratedProtocolMessageType('OptionalGroup_extension', (_message.Message,), dict( + DESCRIPTOR = _OPTIONALGROUP_EXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OptionalGroup_extension) + )) +_sym_db.RegisterMessage(OptionalGroup_extension) + +RepeatedGroup_extension = _reflection.GeneratedProtocolMessageType('RepeatedGroup_extension', (_message.Message,), dict( + DESCRIPTOR = _REPEATEDGROUP_EXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.RepeatedGroup_extension) + )) +_sym_db.RegisterMessage(RepeatedGroup_extension) + +TestGroup = _reflection.GeneratedProtocolMessageType('TestGroup', (_message.Message,), dict( + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTGROUP_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestGroup.OptionalGroup) + )) + , + DESCRIPTOR = _TESTGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestGroup) + )) +_sym_db.RegisterMessage(TestGroup) +_sym_db.RegisterMessage(TestGroup.OptionalGroup) + +TestGroupExtension = _reflection.GeneratedProtocolMessageType('TestGroupExtension', (_message.Message,), dict( + DESCRIPTOR = _TESTGROUPEXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestGroupExtension) + )) +_sym_db.RegisterMessage(TestGroupExtension) + +TestNestedExtension = _reflection.GeneratedProtocolMessageType('TestNestedExtension', (_message.Message,), dict( + + OptionalGroup_extension = _reflection.GeneratedProtocolMessageType('OptionalGroup_extension', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedExtension.OptionalGroup_extension) + )) + , + DESCRIPTOR = _TESTNESTEDEXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedExtension) + )) +_sym_db.RegisterMessage(TestNestedExtension) +_sym_db.RegisterMessage(TestNestedExtension.OptionalGroup_extension) + +TestRequired = _reflection.GeneratedProtocolMessageType('TestRequired', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIRED, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequired) + )) +_sym_db.RegisterMessage(TestRequired) + +TestRequiredForeign = _reflection.GeneratedProtocolMessageType('TestRequiredForeign', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDFOREIGN, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredForeign) + )) +_sym_db.RegisterMessage(TestRequiredForeign) + +TestRequiredMessage = _reflection.GeneratedProtocolMessageType('TestRequiredMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredMessage) + )) +_sym_db.RegisterMessage(TestRequiredMessage) + +TestForeignNested = _reflection.GeneratedProtocolMessageType('TestForeignNested', (_message.Message,), dict( + DESCRIPTOR = _TESTFOREIGNNESTED, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestForeignNested) + )) +_sym_db.RegisterMessage(TestForeignNested) + +TestEmptyMessage = _reflection.GeneratedProtocolMessageType('TestEmptyMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTEMPTYMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEmptyMessage) + )) +_sym_db.RegisterMessage(TestEmptyMessage) + +TestEmptyMessageWithExtensions = _reflection.GeneratedProtocolMessageType('TestEmptyMessageWithExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTEMPTYMESSAGEWITHEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEmptyMessageWithExtensions) + )) +_sym_db.RegisterMessage(TestEmptyMessageWithExtensions) + +TestMultipleExtensionRanges = _reflection.GeneratedProtocolMessageType('TestMultipleExtensionRanges', (_message.Message,), dict( + DESCRIPTOR = _TESTMULTIPLEEXTENSIONRANGES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMultipleExtensionRanges) + )) +_sym_db.RegisterMessage(TestMultipleExtensionRanges) + +TestReallyLargeTagNumber = _reflection.GeneratedProtocolMessageType('TestReallyLargeTagNumber', (_message.Message,), dict( + DESCRIPTOR = _TESTREALLYLARGETAGNUMBER, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestReallyLargeTagNumber) + )) +_sym_db.RegisterMessage(TestReallyLargeTagNumber) + +TestRecursiveMessage = _reflection.GeneratedProtocolMessageType('TestRecursiveMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTRECURSIVEMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursiveMessage) + )) +_sym_db.RegisterMessage(TestRecursiveMessage) + +TestMutualRecursionA = _reflection.GeneratedProtocolMessageType('TestMutualRecursionA', (_message.Message,), dict( + + SubMessage = _reflection.GeneratedProtocolMessageType('SubMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMUTUALRECURSIONA_SUBMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionA.SubMessage) + )) + , + + SubGroup = _reflection.GeneratedProtocolMessageType('SubGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTMUTUALRECURSIONA_SUBGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionA.SubGroup) + )) + , + DESCRIPTOR = _TESTMUTUALRECURSIONA, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionA) + )) +_sym_db.RegisterMessage(TestMutualRecursionA) +_sym_db.RegisterMessage(TestMutualRecursionA.SubMessage) +_sym_db.RegisterMessage(TestMutualRecursionA.SubGroup) + +TestMutualRecursionB = _reflection.GeneratedProtocolMessageType('TestMutualRecursionB', (_message.Message,), dict( + DESCRIPTOR = _TESTMUTUALRECURSIONB, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionB) + )) +_sym_db.RegisterMessage(TestMutualRecursionB) + +TestIsInitialized = _reflection.GeneratedProtocolMessageType('TestIsInitialized', (_message.Message,), dict( + + SubMessage = _reflection.GeneratedProtocolMessageType('SubMessage', (_message.Message,), dict( + + SubGroup = _reflection.GeneratedProtocolMessageType('SubGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTISINITIALIZED_SUBMESSAGE_SUBGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIsInitialized.SubMessage.SubGroup) + )) + , + DESCRIPTOR = _TESTISINITIALIZED_SUBMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIsInitialized.SubMessage) + )) + , + DESCRIPTOR = _TESTISINITIALIZED, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIsInitialized) + )) +_sym_db.RegisterMessage(TestIsInitialized) +_sym_db.RegisterMessage(TestIsInitialized.SubMessage) +_sym_db.RegisterMessage(TestIsInitialized.SubMessage.SubGroup) + +TestDupFieldNumber = _reflection.GeneratedProtocolMessageType('TestDupFieldNumber', (_message.Message,), dict( + + Foo = _reflection.GeneratedProtocolMessageType('Foo', (_message.Message,), dict( + DESCRIPTOR = _TESTDUPFIELDNUMBER_FOO, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDupFieldNumber.Foo) + )) + , + + Bar = _reflection.GeneratedProtocolMessageType('Bar', (_message.Message,), dict( + DESCRIPTOR = _TESTDUPFIELDNUMBER_BAR, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDupFieldNumber.Bar) + )) + , + DESCRIPTOR = _TESTDUPFIELDNUMBER, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDupFieldNumber) + )) +_sym_db.RegisterMessage(TestDupFieldNumber) +_sym_db.RegisterMessage(TestDupFieldNumber.Foo) +_sym_db.RegisterMessage(TestDupFieldNumber.Bar) + +TestEagerMessage = _reflection.GeneratedProtocolMessageType('TestEagerMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTEAGERMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEagerMessage) + )) +_sym_db.RegisterMessage(TestEagerMessage) + +TestLazyMessage = _reflection.GeneratedProtocolMessageType('TestLazyMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTLAZYMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestLazyMessage) + )) +_sym_db.RegisterMessage(TestLazyMessage) + +TestNestedMessageHasBits = _reflection.GeneratedProtocolMessageType('TestNestedMessageHasBits', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedMessageHasBits.NestedMessage) + )) + , + DESCRIPTOR = _TESTNESTEDMESSAGEHASBITS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedMessageHasBits) + )) +_sym_db.RegisterMessage(TestNestedMessageHasBits) +_sym_db.RegisterMessage(TestNestedMessageHasBits.NestedMessage) + +TestCamelCaseFieldNames = _reflection.GeneratedProtocolMessageType('TestCamelCaseFieldNames', (_message.Message,), dict( + DESCRIPTOR = _TESTCAMELCASEFIELDNAMES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestCamelCaseFieldNames) + )) +_sym_db.RegisterMessage(TestCamelCaseFieldNames) + +TestFieldOrderings = _reflection.GeneratedProtocolMessageType('TestFieldOrderings', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTFIELDORDERINGS_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestFieldOrderings.NestedMessage) + )) + , + DESCRIPTOR = _TESTFIELDORDERINGS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestFieldOrderings) + )) +_sym_db.RegisterMessage(TestFieldOrderings) +_sym_db.RegisterMessage(TestFieldOrderings.NestedMessage) + +TestExtensionOrderings1 = _reflection.GeneratedProtocolMessageType('TestExtensionOrderings1', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONORDERINGS1, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionOrderings1) + )) +_sym_db.RegisterMessage(TestExtensionOrderings1) + +TestExtensionOrderings2 = _reflection.GeneratedProtocolMessageType('TestExtensionOrderings2', (_message.Message,), dict( + + TestExtensionOrderings3 = _reflection.GeneratedProtocolMessageType('TestExtensionOrderings3', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3) + )) + , + DESCRIPTOR = _TESTEXTENSIONORDERINGS2, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionOrderings2) + )) +_sym_db.RegisterMessage(TestExtensionOrderings2) +_sym_db.RegisterMessage(TestExtensionOrderings2.TestExtensionOrderings3) + +TestExtremeDefaultValues = _reflection.GeneratedProtocolMessageType('TestExtremeDefaultValues', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTREMEDEFAULTVALUES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtremeDefaultValues) + )) +_sym_db.RegisterMessage(TestExtremeDefaultValues) + +SparseEnumMessage = _reflection.GeneratedProtocolMessageType('SparseEnumMessage', (_message.Message,), dict( + DESCRIPTOR = _SPARSEENUMMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.SparseEnumMessage) + )) +_sym_db.RegisterMessage(SparseEnumMessage) + +OneString = _reflection.GeneratedProtocolMessageType('OneString', (_message.Message,), dict( + DESCRIPTOR = _ONESTRING, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OneString) + )) +_sym_db.RegisterMessage(OneString) + +MoreString = _reflection.GeneratedProtocolMessageType('MoreString', (_message.Message,), dict( + DESCRIPTOR = _MORESTRING, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MoreString) + )) +_sym_db.RegisterMessage(MoreString) + +OneBytes = _reflection.GeneratedProtocolMessageType('OneBytes', (_message.Message,), dict( + DESCRIPTOR = _ONEBYTES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OneBytes) + )) +_sym_db.RegisterMessage(OneBytes) + +MoreBytes = _reflection.GeneratedProtocolMessageType('MoreBytes', (_message.Message,), dict( + DESCRIPTOR = _MOREBYTES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MoreBytes) + )) +_sym_db.RegisterMessage(MoreBytes) + +Int32Message = _reflection.GeneratedProtocolMessageType('Int32Message', (_message.Message,), dict( + DESCRIPTOR = _INT32MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Int32Message) + )) +_sym_db.RegisterMessage(Int32Message) + +Uint32Message = _reflection.GeneratedProtocolMessageType('Uint32Message', (_message.Message,), dict( + DESCRIPTOR = _UINT32MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Uint32Message) + )) +_sym_db.RegisterMessage(Uint32Message) + +Int64Message = _reflection.GeneratedProtocolMessageType('Int64Message', (_message.Message,), dict( + DESCRIPTOR = _INT64MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Int64Message) + )) +_sym_db.RegisterMessage(Int64Message) + +Uint64Message = _reflection.GeneratedProtocolMessageType('Uint64Message', (_message.Message,), dict( + DESCRIPTOR = _UINT64MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Uint64Message) + )) +_sym_db.RegisterMessage(Uint64Message) + +BoolMessage = _reflection.GeneratedProtocolMessageType('BoolMessage', (_message.Message,), dict( + DESCRIPTOR = _BOOLMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.BoolMessage) + )) +_sym_db.RegisterMessage(BoolMessage) + +TestOneof = _reflection.GeneratedProtocolMessageType('TestOneof', (_message.Message,), dict( + + FooGroup = _reflection.GeneratedProtocolMessageType('FooGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF_FOOGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof.FooGroup) + )) + , + DESCRIPTOR = _TESTONEOF, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof) + )) +_sym_db.RegisterMessage(TestOneof) +_sym_db.RegisterMessage(TestOneof.FooGroup) + +TestOneofBackwardsCompatible = _reflection.GeneratedProtocolMessageType('TestOneofBackwardsCompatible', (_message.Message,), dict( + + FooGroup = _reflection.GeneratedProtocolMessageType('FooGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneofBackwardsCompatible.FooGroup) + )) + , + DESCRIPTOR = _TESTONEOFBACKWARDSCOMPATIBLE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneofBackwardsCompatible) + )) +_sym_db.RegisterMessage(TestOneofBackwardsCompatible) +_sym_db.RegisterMessage(TestOneofBackwardsCompatible.FooGroup) + +TestOneof2 = _reflection.GeneratedProtocolMessageType('TestOneof2', (_message.Message,), dict( + + FooGroup = _reflection.GeneratedProtocolMessageType('FooGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF2_FOOGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof2.FooGroup) + )) + , + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF2_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof2.NestedMessage) + )) + , + DESCRIPTOR = _TESTONEOF2, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof2) + )) +_sym_db.RegisterMessage(TestOneof2) +_sym_db.RegisterMessage(TestOneof2.FooGroup) +_sym_db.RegisterMessage(TestOneof2.NestedMessage) + +TestRequiredOneof = _reflection.GeneratedProtocolMessageType('TestRequiredOneof', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDONEOF_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredOneof.NestedMessage) + )) + , + DESCRIPTOR = _TESTREQUIREDONEOF, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredOneof) + )) +_sym_db.RegisterMessage(TestRequiredOneof) +_sym_db.RegisterMessage(TestRequiredOneof.NestedMessage) + +TestPackedTypes = _reflection.GeneratedProtocolMessageType('TestPackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestPackedTypes) + )) +_sym_db.RegisterMessage(TestPackedTypes) + +TestUnpackedTypes = _reflection.GeneratedProtocolMessageType('TestUnpackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestUnpackedTypes) + )) +_sym_db.RegisterMessage(TestUnpackedTypes) + +TestPackedExtensions = _reflection.GeneratedProtocolMessageType('TestPackedExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestPackedExtensions) + )) +_sym_db.RegisterMessage(TestPackedExtensions) + +TestUnpackedExtensions = _reflection.GeneratedProtocolMessageType('TestUnpackedExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestUnpackedExtensions) + )) +_sym_db.RegisterMessage(TestUnpackedExtensions) + +TestDynamicExtensions = _reflection.GeneratedProtocolMessageType('TestDynamicExtensions', (_message.Message,), dict( + + DynamicMessageType = _reflection.GeneratedProtocolMessageType('DynamicMessageType', (_message.Message,), dict( + DESCRIPTOR = _TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDynamicExtensions.DynamicMessageType) + )) + , + DESCRIPTOR = _TESTDYNAMICEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDynamicExtensions) + )) +_sym_db.RegisterMessage(TestDynamicExtensions) +_sym_db.RegisterMessage(TestDynamicExtensions.DynamicMessageType) + +TestRepeatedScalarDifferentTagSizes = _reflection.GeneratedProtocolMessageType('TestRepeatedScalarDifferentTagSizes', (_message.Message,), dict( + DESCRIPTOR = _TESTREPEATEDSCALARDIFFERENTTAGSIZES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRepeatedScalarDifferentTagSizes) + )) +_sym_db.RegisterMessage(TestRepeatedScalarDifferentTagSizes) + +TestParsingMerge = _reflection.GeneratedProtocolMessageType('TestParsingMerge', (_message.Message,), dict( + + RepeatedFieldsGenerator = _reflection.GeneratedProtocolMessageType('RepeatedFieldsGenerator', (_message.Message,), dict( + + Group1 = _reflection.GeneratedProtocolMessageType('Group1', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1) + )) + , + + Group2 = _reflection.GeneratedProtocolMessageType('Group2', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2) + )) + , + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator) + )) + , + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.OptionalGroup) + )) + , + + RepeatedGroup = _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedGroup) + )) + , + DESCRIPTOR = _TESTPARSINGMERGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge) + )) +_sym_db.RegisterMessage(TestParsingMerge) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedFieldsGenerator) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedFieldsGenerator.Group1) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedFieldsGenerator.Group2) +_sym_db.RegisterMessage(TestParsingMerge.OptionalGroup) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedGroup) + +TestCommentInjectionMessage = _reflection.GeneratedProtocolMessageType('TestCommentInjectionMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTCOMMENTINJECTIONMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestCommentInjectionMessage) + )) +_sym_db.RegisterMessage(TestCommentInjectionMessage) + +FooRequest = _reflection.GeneratedProtocolMessageType('FooRequest', (_message.Message,), dict( + DESCRIPTOR = _FOOREQUEST, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooRequest) + )) +_sym_db.RegisterMessage(FooRequest) + +FooResponse = _reflection.GeneratedProtocolMessageType('FooResponse', (_message.Message,), dict( + DESCRIPTOR = _FOORESPONSE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooResponse) + )) +_sym_db.RegisterMessage(FooResponse) + +FooClientMessage = _reflection.GeneratedProtocolMessageType('FooClientMessage', (_message.Message,), dict( + DESCRIPTOR = _FOOCLIENTMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooClientMessage) + )) +_sym_db.RegisterMessage(FooClientMessage) + +FooServerMessage = _reflection.GeneratedProtocolMessageType('FooServerMessage', (_message.Message,), dict( + DESCRIPTOR = _FOOSERVERMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooServerMessage) + )) +_sym_db.RegisterMessage(FooServerMessage) + +BarRequest = _reflection.GeneratedProtocolMessageType('BarRequest', (_message.Message,), dict( + DESCRIPTOR = _BARREQUEST, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.BarRequest) + )) +_sym_db.RegisterMessage(BarRequest) + +BarResponse = _reflection.GeneratedProtocolMessageType('BarResponse', (_message.Message,), dict( + DESCRIPTOR = _BARRESPONSE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.BarResponse) + )) +_sym_db.RegisterMessage(BarResponse) + +TestJsonName = _reflection.GeneratedProtocolMessageType('TestJsonName', (_message.Message,), dict( + DESCRIPTOR = _TESTJSONNAME, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestJsonName) + )) +_sym_db.RegisterMessage(TestJsonName) + +TestHugeFieldNumbers = _reflection.GeneratedProtocolMessageType('TestHugeFieldNumbers', (_message.Message,), dict( + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTHUGEFIELDNUMBERS_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestHugeFieldNumbers.OptionalGroup) + )) + , + + StringStringMapEntry = _reflection.GeneratedProtocolMessageType('StringStringMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry) + )) + , + DESCRIPTOR = _TESTHUGEFIELDNUMBERS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestHugeFieldNumbers) + )) +_sym_db.RegisterMessage(TestHugeFieldNumbers) +_sym_db.RegisterMessage(TestHugeFieldNumbers.OptionalGroup) +_sym_db.RegisterMessage(TestHugeFieldNumbers.StringStringMapEntry) + +TestExtensionInsideTable = _reflection.GeneratedProtocolMessageType('TestExtensionInsideTable', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONINSIDETABLE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionInsideTable) + )) +_sym_db.RegisterMessage(TestExtensionInsideTable) + +TestAllExtensions.RegisterExtension(optional_int32_extension) +TestAllExtensions.RegisterExtension(optional_int64_extension) +TestAllExtensions.RegisterExtension(optional_uint32_extension) +TestAllExtensions.RegisterExtension(optional_uint64_extension) +TestAllExtensions.RegisterExtension(optional_sint32_extension) +TestAllExtensions.RegisterExtension(optional_sint64_extension) +TestAllExtensions.RegisterExtension(optional_fixed32_extension) +TestAllExtensions.RegisterExtension(optional_fixed64_extension) +TestAllExtensions.RegisterExtension(optional_sfixed32_extension) +TestAllExtensions.RegisterExtension(optional_sfixed64_extension) +TestAllExtensions.RegisterExtension(optional_float_extension) +TestAllExtensions.RegisterExtension(optional_double_extension) +TestAllExtensions.RegisterExtension(optional_bool_extension) +TestAllExtensions.RegisterExtension(optional_string_extension) +TestAllExtensions.RegisterExtension(optional_bytes_extension) +optionalgroup_extension.message_type = _OPTIONALGROUP_EXTENSION +TestAllExtensions.RegisterExtension(optionalgroup_extension) +optional_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(optional_nested_message_extension) +optional_foreign_message_extension.message_type = _FOREIGNMESSAGE +TestAllExtensions.RegisterExtension(optional_foreign_message_extension) +optional_import_message_extension.message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +TestAllExtensions.RegisterExtension(optional_import_message_extension) +optional_nested_enum_extension.enum_type = _TESTALLTYPES_NESTEDENUM +TestAllExtensions.RegisterExtension(optional_nested_enum_extension) +optional_foreign_enum_extension.enum_type = _FOREIGNENUM +TestAllExtensions.RegisterExtension(optional_foreign_enum_extension) +optional_import_enum_extension.enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +TestAllExtensions.RegisterExtension(optional_import_enum_extension) +TestAllExtensions.RegisterExtension(optional_string_piece_extension) +TestAllExtensions.RegisterExtension(optional_cord_extension) +optional_public_import_message_extension.message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +TestAllExtensions.RegisterExtension(optional_public_import_message_extension) +optional_lazy_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(optional_lazy_message_extension) +TestAllExtensions.RegisterExtension(repeated_int32_extension) +TestAllExtensions.RegisterExtension(repeated_int64_extension) +TestAllExtensions.RegisterExtension(repeated_uint32_extension) +TestAllExtensions.RegisterExtension(repeated_uint64_extension) +TestAllExtensions.RegisterExtension(repeated_sint32_extension) +TestAllExtensions.RegisterExtension(repeated_sint64_extension) +TestAllExtensions.RegisterExtension(repeated_fixed32_extension) +TestAllExtensions.RegisterExtension(repeated_fixed64_extension) +TestAllExtensions.RegisterExtension(repeated_sfixed32_extension) +TestAllExtensions.RegisterExtension(repeated_sfixed64_extension) +TestAllExtensions.RegisterExtension(repeated_float_extension) +TestAllExtensions.RegisterExtension(repeated_double_extension) +TestAllExtensions.RegisterExtension(repeated_bool_extension) +TestAllExtensions.RegisterExtension(repeated_string_extension) +TestAllExtensions.RegisterExtension(repeated_bytes_extension) +repeatedgroup_extension.message_type = _REPEATEDGROUP_EXTENSION +TestAllExtensions.RegisterExtension(repeatedgroup_extension) +repeated_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(repeated_nested_message_extension) +repeated_foreign_message_extension.message_type = _FOREIGNMESSAGE +TestAllExtensions.RegisterExtension(repeated_foreign_message_extension) +repeated_import_message_extension.message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +TestAllExtensions.RegisterExtension(repeated_import_message_extension) +repeated_nested_enum_extension.enum_type = _TESTALLTYPES_NESTEDENUM +TestAllExtensions.RegisterExtension(repeated_nested_enum_extension) +repeated_foreign_enum_extension.enum_type = _FOREIGNENUM +TestAllExtensions.RegisterExtension(repeated_foreign_enum_extension) +repeated_import_enum_extension.enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +TestAllExtensions.RegisterExtension(repeated_import_enum_extension) +TestAllExtensions.RegisterExtension(repeated_string_piece_extension) +TestAllExtensions.RegisterExtension(repeated_cord_extension) +repeated_lazy_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(repeated_lazy_message_extension) +TestAllExtensions.RegisterExtension(default_int32_extension) +TestAllExtensions.RegisterExtension(default_int64_extension) +TestAllExtensions.RegisterExtension(default_uint32_extension) +TestAllExtensions.RegisterExtension(default_uint64_extension) +TestAllExtensions.RegisterExtension(default_sint32_extension) +TestAllExtensions.RegisterExtension(default_sint64_extension) +TestAllExtensions.RegisterExtension(default_fixed32_extension) +TestAllExtensions.RegisterExtension(default_fixed64_extension) +TestAllExtensions.RegisterExtension(default_sfixed32_extension) +TestAllExtensions.RegisterExtension(default_sfixed64_extension) +TestAllExtensions.RegisterExtension(default_float_extension) +TestAllExtensions.RegisterExtension(default_double_extension) +TestAllExtensions.RegisterExtension(default_bool_extension) +TestAllExtensions.RegisterExtension(default_string_extension) +TestAllExtensions.RegisterExtension(default_bytes_extension) +default_nested_enum_extension.enum_type = _TESTALLTYPES_NESTEDENUM +TestAllExtensions.RegisterExtension(default_nested_enum_extension) +default_foreign_enum_extension.enum_type = _FOREIGNENUM +TestAllExtensions.RegisterExtension(default_foreign_enum_extension) +default_import_enum_extension.enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +TestAllExtensions.RegisterExtension(default_import_enum_extension) +TestAllExtensions.RegisterExtension(default_string_piece_extension) +TestAllExtensions.RegisterExtension(default_cord_extension) +TestAllExtensions.RegisterExtension(oneof_uint32_extension) +oneof_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(oneof_nested_message_extension) +TestAllExtensions.RegisterExtension(oneof_string_extension) +TestAllExtensions.RegisterExtension(oneof_bytes_extension) +TestFieldOrderings.RegisterExtension(my_extension_string) +TestFieldOrderings.RegisterExtension(my_extension_int) +TestPackedExtensions.RegisterExtension(packed_int32_extension) +TestPackedExtensions.RegisterExtension(packed_int64_extension) +TestPackedExtensions.RegisterExtension(packed_uint32_extension) +TestPackedExtensions.RegisterExtension(packed_uint64_extension) +TestPackedExtensions.RegisterExtension(packed_sint32_extension) +TestPackedExtensions.RegisterExtension(packed_sint64_extension) +TestPackedExtensions.RegisterExtension(packed_fixed32_extension) +TestPackedExtensions.RegisterExtension(packed_fixed64_extension) +TestPackedExtensions.RegisterExtension(packed_sfixed32_extension) +TestPackedExtensions.RegisterExtension(packed_sfixed64_extension) +TestPackedExtensions.RegisterExtension(packed_float_extension) +TestPackedExtensions.RegisterExtension(packed_double_extension) +TestPackedExtensions.RegisterExtension(packed_bool_extension) +packed_enum_extension.enum_type = _FOREIGNENUM +TestPackedExtensions.RegisterExtension(packed_enum_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_int32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_int64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_uint32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_uint64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sint32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sint64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_fixed32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_fixed64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sfixed32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sfixed64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_float_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_double_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_bool_extension) +unpacked_enum_extension.enum_type = _FOREIGNENUM +TestUnpackedExtensions.RegisterExtension(unpacked_enum_extension) +test_all_types.message_type = _TESTALLTYPES +TestHugeFieldNumbers.RegisterExtension(test_all_types) +TestExtensionInsideTable.RegisterExtension(test_extension_inside_table_extension) +TestAllExtensions.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['test']) +TestAllExtensions.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['nested_string_extension']) +_TESTNESTEDEXTENSION.extensions_by_name['optionalgroup_extension'].message_type = _TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION +TestGroupExtension.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['optionalgroup_extension']) +_TESTNESTEDEXTENSION.extensions_by_name['optional_foreign_enum_extension'].enum_type = _FOREIGNENUM +TestGroupExtension.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['optional_foreign_enum_extension']) +_TESTREQUIRED.extensions_by_name['single'].message_type = _TESTREQUIRED +TestAllExtensions.RegisterExtension(_TESTREQUIRED.extensions_by_name['single']) +_TESTREQUIRED.extensions_by_name['multi'].message_type = _TESTREQUIRED +TestAllExtensions.RegisterExtension(_TESTREQUIRED.extensions_by_name['multi']) +_TESTEXTENSIONORDERINGS1.extensions_by_name['test_ext_orderings1'].message_type = _TESTEXTENSIONORDERINGS1 +TestFieldOrderings.RegisterExtension(_TESTEXTENSIONORDERINGS1.extensions_by_name['test_ext_orderings1']) +_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3.extensions_by_name['test_ext_orderings3'].message_type = _TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3 +TestFieldOrderings.RegisterExtension(_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3.extensions_by_name['test_ext_orderings3']) +_TESTEXTENSIONORDERINGS2.extensions_by_name['test_ext_orderings2'].message_type = _TESTEXTENSIONORDERINGS2 +TestFieldOrderings.RegisterExtension(_TESTEXTENSIONORDERINGS2.extensions_by_name['test_ext_orderings2']) +_TESTPARSINGMERGE.extensions_by_name['optional_ext'].message_type = _TESTALLTYPES +TestParsingMerge.RegisterExtension(_TESTPARSINGMERGE.extensions_by_name['optional_ext']) +_TESTPARSINGMERGE.extensions_by_name['repeated_ext'].message_type = _TESTALLTYPES +TestParsingMerge.RegisterExtension(_TESTPARSINGMERGE.extensions_by_name['repeated_ext']) + +DESCRIPTOR._options = None +_TESTENUMWITHDUPVALUE._options = None +optional_string_piece_extension._options = None +optional_cord_extension._options = None +optional_lazy_message_extension._options = None +repeated_string_piece_extension._options = None +repeated_cord_extension._options = None +repeated_lazy_message_extension._options = None +default_string_piece_extension._options = None +default_cord_extension._options = None +packed_int32_extension._options = None +packed_int64_extension._options = None +packed_uint32_extension._options = None +packed_uint64_extension._options = None +packed_sint32_extension._options = None +packed_sint64_extension._options = None +packed_fixed32_extension._options = None +packed_fixed64_extension._options = None +packed_sfixed32_extension._options = None +packed_sfixed64_extension._options = None +packed_float_extension._options = None +packed_double_extension._options = None +packed_bool_extension._options = None +packed_enum_extension._options = None +unpacked_int32_extension._options = None +unpacked_int64_extension._options = None +unpacked_uint32_extension._options = None +unpacked_uint64_extension._options = None +unpacked_sint32_extension._options = None +unpacked_sint64_extension._options = None +unpacked_fixed32_extension._options = None +unpacked_fixed64_extension._options = None +unpacked_sfixed32_extension._options = None +unpacked_sfixed64_extension._options = None +unpacked_float_extension._options = None +unpacked_double_extension._options = None +unpacked_bool_extension._options = None +unpacked_enum_extension._options = None +_TESTALLTYPES.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPES.fields_by_name['optional_cord']._options = None +_TESTALLTYPES.fields_by_name['optional_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPES.fields_by_name['repeated_cord']._options = None +_TESTALLTYPES.fields_by_name['repeated_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['default_string_piece']._options = None +_TESTALLTYPES.fields_by_name['default_cord']._options = None +_TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32']._options = None +_TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32_in_oneof']._options = None +_TESTDEPRECATEDMESSAGE._options = None +_TESTEAGERMESSAGE.fields_by_name['sub_message']._options = None +_TESTLAZYMESSAGE.fields_by_name['sub_message']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['StringPieceField']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['CordField']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedStringPieceField']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedCordField']._options = None +_TESTEXTREMEDEFAULTVALUES.fields_by_name['string_piece_with_zero']._options = None +_TESTEXTREMEDEFAULTVALUES.fields_by_name['cord_with_zero']._options = None +_TESTONEOF2.fields_by_name['foo_cord']._options = None +_TESTONEOF2.fields_by_name['foo_string_piece']._options = None +_TESTONEOF2.fields_by_name['foo_lazy_message']._options = None +_TESTONEOF2.fields_by_name['bar_cord']._options = None +_TESTONEOF2.fields_by_name['bar_string_piece']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_float']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_double']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_bool']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_enum']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_int32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_int64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_uint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_uint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_fixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_fixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sfixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sfixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_float']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_double']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_bool']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_enum']._options = None +_TESTDYNAMICEXTENSIONS.fields_by_name['packed_extension']._options = None +_TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY._options = None +_TESTHUGEFIELDNUMBERS.fields_by_name['repeated_int32']._options = None +_TESTHUGEFIELDNUMBERS.fields_by_name['packed_int32']._options = None + +_TESTSERVICE = _descriptor.ServiceDescriptor( + name='TestService', + full_name='protobuf_unittest.TestService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=15590, + serialized_end=15743, + methods=[ + _descriptor.MethodDescriptor( + name='Foo', + full_name='protobuf_unittest.TestService.Foo', + index=0, + containing_service=None, + input_type=_FOOREQUEST, + output_type=_FOORESPONSE, + serialized_options=None, + ), + _descriptor.MethodDescriptor( + name='Bar', + full_name='protobuf_unittest.TestService.Bar', + index=1, + containing_service=None, + input_type=_BARREQUEST, + output_type=_BARRESPONSE, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_TESTSERVICE) + +DESCRIPTOR.services_by_name['TestService'] = _TESTSERVICE + +TestService = service_reflection.GeneratedServiceType('TestService', (_service.Service,), dict( + DESCRIPTOR = _TESTSERVICE, + __module__ = 'google.protobuf.unittest_pb2' + )) + +TestService_Stub = service_reflection.GeneratedServiceStubType('TestService_Stub', (TestService,), dict( + DESCRIPTOR = _TESTSERVICE, + __module__ = 'google.protobuf.unittest_pb2' + )) + + +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/unittest_proto3_arena_pb2.py b/winvenv/Lib/site-packages/google/protobuf/unittest_proto3_arena_pb2.py new file mode 100644 index 0000000..c68ca38 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/unittest_proto3_arena_pb2.py @@ -0,0 +1,999 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_proto3_arena.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_pb2 as google_dot_protobuf_dot_unittest__import__pb2 +try: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google_dot_protobuf_dot_unittest__import__public__pb2 +except AttributeError: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google.protobuf.unittest_import_public_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_proto3_arena.proto', + package='proto3_arena_unittest', + syntax='proto3', + serialized_options=_b('\370\001\001'), + serialized_pb=_b('\n+google/protobuf/unittest_proto3_arena.proto\x12\x15proto3_arena_unittest\x1a%google/protobuf/unittest_import.proto\"\xc9\x11\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12R\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessage\x12G\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32%.proto3_arena_unittest.ForeignMessage\x12H\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12L\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32..proto3_arena_unittest.TestAllTypes.NestedEnum\x12\x41\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\".proto3_arena_unittest.ForeignEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12U\n\x1eoptional_public_import_message\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage\x12T\n\x15optional_lazy_message\x18\x1b \x01(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12Q\n\x1coptional_lazy_import_message\x18s \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessageB\x02(\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12R\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessage\x12G\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32%.proto3_arena_unittest.ForeignMessage\x12H\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12L\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32..proto3_arena_unittest.TestAllTypes.NestedEnum\x12\x41\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\".proto3_arena_unittest.ForeignEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12T\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12Q\n\x14oneof_nested_message\x18p \x01(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x1a\x1b\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\"C\n\nNestedEnum\x12\x08\n\x04ZERO\x10\x00\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_field\"\xae\x03\n\x0fTestPackedTypes\x12\x18\n\x0cpacked_int32\x18Z \x03(\x05\x42\x02\x10\x01\x12\x18\n\x0cpacked_int64\x18[ \x03(\x03\x42\x02\x10\x01\x12\x19\n\rpacked_uint32\x18\\ \x03(\rB\x02\x10\x01\x12\x19\n\rpacked_uint64\x18] \x03(\x04\x42\x02\x10\x01\x12\x19\n\rpacked_sint32\x18^ \x03(\x11\x42\x02\x10\x01\x12\x19\n\rpacked_sint64\x18_ \x03(\x12\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed32\x18` \x03(\x07\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed64\x18\x61 \x03(\x06\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed32\x18\x62 \x03(\x0f\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed64\x18\x63 \x03(\x10\x42\x02\x10\x01\x12\x18\n\x0cpacked_float\x18\x64 \x03(\x02\x42\x02\x10\x01\x12\x19\n\rpacked_double\x18\x65 \x03(\x01\x42\x02\x10\x01\x12\x17\n\x0bpacked_bool\x18\x66 \x03(\x08\x42\x02\x10\x01\x12;\n\x0bpacked_enum\x18g \x03(\x0e\x32\".proto3_arena_unittest.ForeignEnumB\x02\x10\x01\"\xdf\x03\n\x11TestUnpackedTypes\x12\x1a\n\x0erepeated_int32\x18\x01 \x03(\x05\x42\x02\x10\x00\x12\x1a\n\x0erepeated_int64\x18\x02 \x03(\x03\x42\x02\x10\x00\x12\x1b\n\x0frepeated_uint32\x18\x03 \x03(\rB\x02\x10\x00\x12\x1b\n\x0frepeated_uint64\x18\x04 \x03(\x04\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint32\x18\x05 \x03(\x11\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint64\x18\x06 \x03(\x12\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed32\x18\x07 \x03(\x07\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed64\x18\x08 \x03(\x06\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed32\x18\t \x03(\x0f\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed64\x18\n \x03(\x10\x42\x02\x10\x00\x12\x1a\n\x0erepeated_float\x18\x0b \x03(\x02\x42\x02\x10\x00\x12\x1b\n\x0frepeated_double\x18\x0c \x03(\x01\x42\x02\x10\x00\x12\x19\n\rrepeated_bool\x18\r \x03(\x08\x42\x02\x10\x00\x12P\n\x14repeated_nested_enum\x18\x0e \x03(\x0e\x32..proto3_arena_unittest.TestAllTypes.NestedEnumB\x02\x10\x00\"\xc7\x01\n\x12NestedTestAllTypes\x12\x38\n\x05\x63hild\x18\x01 \x01(\x0b\x32).proto3_arena_unittest.NestedTestAllTypes\x12\x34\n\x07payload\x18\x02 \x01(\x0b\x32#.proto3_arena_unittest.TestAllTypes\x12\x41\n\x0erepeated_child\x18\x03 \x03(\x0b\x32).proto3_arena_unittest.NestedTestAllTypes\"\x1b\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\"\x12\n\x10TestEmptyMessage*R\n\x0b\x46oreignEnum\x12\x10\n\x0c\x46OREIGN_ZERO\x10\x00\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x04\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x05\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x06\x42\x03\xf8\x01\x01\x62\x06proto3') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='proto3_arena_unittest.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_ZERO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=1, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=2, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=3, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3527, + serialized_end=3609, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +FOREIGN_ZERO = 0 +FOREIGN_FOO = 4 +FOREIGN_BAR = 5 +FOREIGN_BAZ = 6 + + +_TESTALLTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='proto3_arena_unittest.TestAllTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ZERO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOO', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=4, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2277, + serialized_end=2344, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPES_NESTEDENUM) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='proto3_arena_unittest.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='proto3_arena_unittest.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2248, + serialized_end=2275, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='proto3_arena_unittest.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='proto3_arena_unittest.TestAllTypes.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='proto3_arena_unittest.TestAllTypes.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='proto3_arena_unittest.TestAllTypes.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='proto3_arena_unittest.TestAllTypes.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='proto3_arena_unittest.TestAllTypes.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='proto3_arena_unittest.TestAllTypes.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='proto3_arena_unittest.TestAllTypes.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='proto3_arena_unittest.TestAllTypes.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='proto3_arena_unittest.TestAllTypes.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='proto3_arena_unittest.TestAllTypes.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='proto3_arena_unittest.TestAllTypes.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='proto3_arena_unittest.TestAllTypes.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='proto3_arena_unittest.TestAllTypes.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='proto3_arena_unittest.TestAllTypes.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='proto3_arena_unittest.TestAllTypes.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='proto3_arena_unittest.TestAllTypes.optional_nested_message', index=15, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='proto3_arena_unittest.TestAllTypes.optional_foreign_message', index=16, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_message', full_name='proto3_arena_unittest.TestAllTypes.optional_import_message', index=17, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='proto3_arena_unittest.TestAllTypes.optional_nested_enum', index=18, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='proto3_arena_unittest.TestAllTypes.optional_foreign_enum', index=19, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='proto3_arena_unittest.TestAllTypes.optional_string_piece', index=20, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='proto3_arena_unittest.TestAllTypes.optional_cord', index=21, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_public_import_message', full_name='proto3_arena_unittest.TestAllTypes.optional_public_import_message', index=22, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_lazy_message', full_name='proto3_arena_unittest.TestAllTypes.optional_lazy_message', index=23, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_lazy_import_message', full_name='proto3_arena_unittest.TestAllTypes.optional_lazy_import_message', index=24, + number=115, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='proto3_arena_unittest.TestAllTypes.repeated_int32', index=25, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='proto3_arena_unittest.TestAllTypes.repeated_int64', index=26, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='proto3_arena_unittest.TestAllTypes.repeated_uint32', index=27, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='proto3_arena_unittest.TestAllTypes.repeated_uint64', index=28, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='proto3_arena_unittest.TestAllTypes.repeated_sint32', index=29, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='proto3_arena_unittest.TestAllTypes.repeated_sint64', index=30, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='proto3_arena_unittest.TestAllTypes.repeated_fixed32', index=31, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='proto3_arena_unittest.TestAllTypes.repeated_fixed64', index=32, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='proto3_arena_unittest.TestAllTypes.repeated_sfixed32', index=33, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='proto3_arena_unittest.TestAllTypes.repeated_sfixed64', index=34, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='proto3_arena_unittest.TestAllTypes.repeated_float', index=35, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='proto3_arena_unittest.TestAllTypes.repeated_double', index=36, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='proto3_arena_unittest.TestAllTypes.repeated_bool', index=37, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='proto3_arena_unittest.TestAllTypes.repeated_string', index=38, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='proto3_arena_unittest.TestAllTypes.repeated_bytes', index=39, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_nested_message', index=40, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_foreign_message', index=41, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_import_message', index=42, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='proto3_arena_unittest.TestAllTypes.repeated_nested_enum', index=43, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='proto3_arena_unittest.TestAllTypes.repeated_foreign_enum', index=44, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='proto3_arena_unittest.TestAllTypes.repeated_string_piece', index=45, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='proto3_arena_unittest.TestAllTypes.repeated_cord', index=46, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_lazy_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_lazy_message', index=47, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='proto3_arena_unittest.TestAllTypes.oneof_uint32', index=48, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='proto3_arena_unittest.TestAllTypes.oneof_nested_message', index=49, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='proto3_arena_unittest.TestAllTypes.oneof_string', index=50, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='proto3_arena_unittest.TestAllTypes.oneof_bytes', index=51, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, ], + enum_types=[ + _TESTALLTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='proto3_arena_unittest.TestAllTypes.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=110, + serialized_end=2359, +) + + +_TESTPACKEDTYPES = _descriptor.Descriptor( + name='TestPackedTypes', + full_name='proto3_arena_unittest.TestPackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='packed_int32', full_name='proto3_arena_unittest.TestPackedTypes.packed_int32', index=0, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_int64', full_name='proto3_arena_unittest.TestPackedTypes.packed_int64', index=1, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint32', full_name='proto3_arena_unittest.TestPackedTypes.packed_uint32', index=2, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint64', full_name='proto3_arena_unittest.TestPackedTypes.packed_uint64', index=3, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint32', full_name='proto3_arena_unittest.TestPackedTypes.packed_sint32', index=4, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint64', full_name='proto3_arena_unittest.TestPackedTypes.packed_sint64', index=5, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed32', full_name='proto3_arena_unittest.TestPackedTypes.packed_fixed32', index=6, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed64', full_name='proto3_arena_unittest.TestPackedTypes.packed_fixed64', index=7, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed32', full_name='proto3_arena_unittest.TestPackedTypes.packed_sfixed32', index=8, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed64', full_name='proto3_arena_unittest.TestPackedTypes.packed_sfixed64', index=9, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_float', full_name='proto3_arena_unittest.TestPackedTypes.packed_float', index=10, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_double', full_name='proto3_arena_unittest.TestPackedTypes.packed_double', index=11, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_bool', full_name='proto3_arena_unittest.TestPackedTypes.packed_bool', index=12, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='proto3_arena_unittest.TestPackedTypes.packed_enum', index=13, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2362, + serialized_end=2792, +) + + +_TESTUNPACKEDTYPES = _descriptor.Descriptor( + name='TestUnpackedTypes', + full_name='proto3_arena_unittest.TestUnpackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_int64', index=1, + number=2, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_uint32', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_uint64', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sint32', index=4, + number=5, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sint64', index=5, + number=6, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_fixed32', index=6, + number=7, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_fixed64', index=7, + number=8, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_float', index=10, + number=11, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_double', index=11, + number=12, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_bool', index=12, + number=13, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_nested_enum', index=13, + number=14, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2795, + serialized_end=3274, +) + + +_NESTEDTESTALLTYPES = _descriptor.Descriptor( + name='NestedTestAllTypes', + full_name='proto3_arena_unittest.NestedTestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='child', full_name='proto3_arena_unittest.NestedTestAllTypes.child', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payload', full_name='proto3_arena_unittest.NestedTestAllTypes.payload', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_child', full_name='proto3_arena_unittest.NestedTestAllTypes.repeated_child', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3277, + serialized_end=3476, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='proto3_arena_unittest.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='proto3_arena_unittest.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3478, + serialized_end=3505, +) + + +_TESTEMPTYMESSAGE = _descriptor.Descriptor( + name='TestEmptyMessage', + full_name='proto3_arena_unittest.TestEmptyMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3507, + serialized_end=3525, +) + +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['optional_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['optional_public_import_message'].message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_lazy_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['repeated_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['repeated_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES_NESTEDENUM.containing_type = _TESTALLTYPES +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_uint32']) +_TESTALLTYPES.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_nested_message']) +_TESTALLTYPES.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_string']) +_TESTALLTYPES.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_bytes']) +_TESTALLTYPES.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTPACKEDTYPES.fields_by_name['packed_enum'].enum_type = _FOREIGNENUM +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_NESTEDTESTALLTYPES.fields_by_name['child'].message_type = _NESTEDTESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['payload'].message_type = _TESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['repeated_child'].message_type = _NESTEDTESTALLTYPES +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['TestPackedTypes'] = _TESTPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestUnpackedTypes'] = _TESTUNPACKEDTYPES +DESCRIPTOR.message_types_by_name['NestedTestAllTypes'] = _NESTEDTESTALLTYPES +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestEmptyMessage'] = _TESTEMPTYMESSAGE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestAllTypes.NestedMessage) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) + +TestPackedTypes = _reflection.GeneratedProtocolMessageType('TestPackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestPackedTypes) + )) +_sym_db.RegisterMessage(TestPackedTypes) + +TestUnpackedTypes = _reflection.GeneratedProtocolMessageType('TestUnpackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestUnpackedTypes) + )) +_sym_db.RegisterMessage(TestUnpackedTypes) + +NestedTestAllTypes = _reflection.GeneratedProtocolMessageType('NestedTestAllTypes', (_message.Message,), dict( + DESCRIPTOR = _NESTEDTESTALLTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.NestedTestAllTypes) + )) +_sym_db.RegisterMessage(NestedTestAllTypes) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestEmptyMessage = _reflection.GeneratedProtocolMessageType('TestEmptyMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTEMPTYMESSAGE, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestEmptyMessage) + )) +_sym_db.RegisterMessage(TestEmptyMessage) + + +DESCRIPTOR._options = None +_TESTALLTYPES.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPES.fields_by_name['optional_cord']._options = None +_TESTALLTYPES.fields_by_name['optional_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['optional_lazy_import_message']._options = None +_TESTALLTYPES.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPES.fields_by_name['repeated_cord']._options = None +_TESTALLTYPES.fields_by_name['repeated_lazy_message']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_float']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_double']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_bool']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_enum']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_int32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_int64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_float']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_double']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_bool']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/util/__init__.py b/winvenv/Lib/site-packages/google/protobuf/util/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/google/protobuf/util/json_format_proto3_pb2.py b/winvenv/Lib/site-packages/google/protobuf/util/json_format_proto3_pb2.py new file mode 100644 index 0000000..ff09093 --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/util/json_format_proto3_pb2.py @@ -0,0 +1,1895 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/util/json_format_proto3.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 +from google.protobuf import unittest_pb2 as google_dot_protobuf_dot_unittest__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/util/json_format_proto3.proto', + package='proto3', + syntax='proto3', + serialized_options=_b('\n\030com.google.protobuf.utilB\020JsonFormatProto3'), + serialized_pb=_b('\n-google/protobuf/util/json_format_proto3.proto\x12\x06proto3\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x19google/protobuf/any.proto\x1a google/protobuf/field_mask.proto\x1a\x1egoogle/protobuf/unittest.proto\"\x1c\n\x0bMessageType\x12\r\n\x05value\x18\x01 \x01(\x05\"\x94\x05\n\x0bTestMessage\x12\x12\n\nbool_value\x18\x01 \x01(\x08\x12\x13\n\x0bint32_value\x18\x02 \x01(\x05\x12\x13\n\x0bint64_value\x18\x03 \x01(\x03\x12\x14\n\x0cuint32_value\x18\x04 \x01(\r\x12\x14\n\x0cuint64_value\x18\x05 \x01(\x04\x12\x13\n\x0b\x66loat_value\x18\x06 \x01(\x02\x12\x14\n\x0c\x64ouble_value\x18\x07 \x01(\x01\x12\x14\n\x0cstring_value\x18\x08 \x01(\t\x12\x13\n\x0b\x62ytes_value\x18\t \x01(\x0c\x12$\n\nenum_value\x18\n \x01(\x0e\x32\x10.proto3.EnumType\x12*\n\rmessage_value\x18\x0b \x01(\x0b\x32\x13.proto3.MessageType\x12\x1b\n\x13repeated_bool_value\x18\x15 \x03(\x08\x12\x1c\n\x14repeated_int32_value\x18\x16 \x03(\x05\x12\x1c\n\x14repeated_int64_value\x18\x17 \x03(\x03\x12\x1d\n\x15repeated_uint32_value\x18\x18 \x03(\r\x12\x1d\n\x15repeated_uint64_value\x18\x19 \x03(\x04\x12\x1c\n\x14repeated_float_value\x18\x1a \x03(\x02\x12\x1d\n\x15repeated_double_value\x18\x1b \x03(\x01\x12\x1d\n\x15repeated_string_value\x18\x1c \x03(\t\x12\x1c\n\x14repeated_bytes_value\x18\x1d \x03(\x0c\x12-\n\x13repeated_enum_value\x18\x1e \x03(\x0e\x32\x10.proto3.EnumType\x12\x33\n\x16repeated_message_value\x18\x1f \x03(\x0b\x32\x13.proto3.MessageType\"\xd4\x01\n\tTestOneof\x12\x1b\n\x11oneof_int32_value\x18\x01 \x01(\x05H\x00\x12\x1c\n\x12oneof_string_value\x18\x02 \x01(\tH\x00\x12\x1b\n\x11oneof_bytes_value\x18\x03 \x01(\x0cH\x00\x12,\n\x10oneof_enum_value\x18\x04 \x01(\x0e\x32\x10.proto3.EnumTypeH\x00\x12\x32\n\x13oneof_message_value\x18\x05 \x01(\x0b\x32\x13.proto3.MessageTypeH\x00\x42\r\n\x0boneof_value\"\xe1\x04\n\x07TestMap\x12.\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32\x1c.proto3.TestMap.BoolMapEntry\x12\x30\n\tint32_map\x18\x02 \x03(\x0b\x32\x1d.proto3.TestMap.Int32MapEntry\x12\x30\n\tint64_map\x18\x03 \x03(\x0b\x32\x1d.proto3.TestMap.Int64MapEntry\x12\x32\n\nuint32_map\x18\x04 \x03(\x0b\x32\x1e.proto3.TestMap.Uint32MapEntry\x12\x32\n\nuint64_map\x18\x05 \x03(\x0b\x32\x1e.proto3.TestMap.Uint64MapEntry\x12\x32\n\nstring_map\x18\x06 \x03(\x0b\x32\x1e.proto3.TestMap.StringMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\x85\x06\n\rTestNestedMap\x12\x34\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32\".proto3.TestNestedMap.BoolMapEntry\x12\x36\n\tint32_map\x18\x02 \x03(\x0b\x32#.proto3.TestNestedMap.Int32MapEntry\x12\x36\n\tint64_map\x18\x03 \x03(\x0b\x32#.proto3.TestNestedMap.Int64MapEntry\x12\x38\n\nuint32_map\x18\x04 \x03(\x0b\x32$.proto3.TestNestedMap.Uint32MapEntry\x12\x38\n\nuint64_map\x18\x05 \x03(\x0b\x32$.proto3.TestNestedMap.Uint64MapEntry\x12\x38\n\nstring_map\x18\x06 \x03(\x0b\x32$.proto3.TestNestedMap.StringMapEntry\x12\x32\n\x07map_map\x18\x07 \x03(\x0b\x32!.proto3.TestNestedMap.MapMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x44\n\x0bMapMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.proto3.TestNestedMap:\x02\x38\x01\"\xee\x07\n\x0bTestWrapper\x12.\n\nbool_value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\x12\x30\n\x0bint32_value\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.Int32Value\x12\x30\n\x0bint64_value\x18\x03 \x01(\x0b\x32\x1b.google.protobuf.Int64Value\x12\x32\n\x0cuint32_value\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x32\n\x0cuint64_value\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12\x30\n\x0b\x66loat_value\x18\x06 \x01(\x0b\x32\x1b.google.protobuf.FloatValue\x12\x32\n\x0c\x64ouble_value\x18\x07 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue\x12\x32\n\x0cstring_value\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.StringValue\x12\x30\n\x0b\x62ytes_value\x18\t \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x12\x37\n\x13repeated_bool_value\x18\x0b \x03(\x0b\x32\x1a.google.protobuf.BoolValue\x12\x39\n\x14repeated_int32_value\x18\x0c \x03(\x0b\x32\x1b.google.protobuf.Int32Value\x12\x39\n\x14repeated_int64_value\x18\r \x03(\x0b\x32\x1b.google.protobuf.Int64Value\x12;\n\x15repeated_uint32_value\x18\x0e \x03(\x0b\x32\x1c.google.protobuf.UInt32Value\x12;\n\x15repeated_uint64_value\x18\x0f \x03(\x0b\x32\x1c.google.protobuf.UInt64Value\x12\x39\n\x14repeated_float_value\x18\x10 \x03(\x0b\x32\x1b.google.protobuf.FloatValue\x12;\n\x15repeated_double_value\x18\x11 \x03(\x0b\x32\x1c.google.protobuf.DoubleValue\x12;\n\x15repeated_string_value\x18\x12 \x03(\x0b\x32\x1c.google.protobuf.StringValue\x12\x39\n\x14repeated_bytes_value\x18\x13 \x03(\x0b\x32\x1b.google.protobuf.BytesValue\"n\n\rTestTimestamp\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x0cTestDuration\x12(\n\x05value\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x19.google.protobuf.Duration\":\n\rTestFieldMask\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"e\n\nTestStruct\x12&\n\x05value\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12/\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x17.google.protobuf.Struct\"\\\n\x07TestAny\x12#\n\x05value\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12,\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x14.google.protobuf.Any\"b\n\tTestValue\x12%\n\x05value\x18\x01 \x01(\x0b\x32\x16.google.protobuf.Value\x12.\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x16.google.protobuf.Value\"n\n\rTestListValue\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.ListValue\x12\x32\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.ListValue\"\x89\x01\n\rTestBoolValue\x12\x12\n\nbool_value\x18\x01 \x01(\x08\x12\x34\n\x08\x62ool_map\x18\x02 \x03(\x0b\x32\".proto3.TestBoolValue.BoolMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"+\n\x12TestCustomJsonName\x12\x15\n\x05value\x18\x01 \x01(\x05R\x06@value\"J\n\x0eTestExtensions\x12\x38\n\nextensions\x18\x01 \x01(\x0b\x32$.protobuf_unittest.TestAllExtensions\"\x84\x01\n\rTestEnumValue\x12%\n\x0b\x65num_value1\x18\x01 \x01(\x0e\x32\x10.proto3.EnumType\x12%\n\x0b\x65num_value2\x18\x02 \x01(\x0e\x32\x10.proto3.EnumType\x12%\n\x0b\x65num_value3\x18\x03 \x01(\x0e\x32\x10.proto3.EnumType*\x1c\n\x08\x45numType\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x42,\n\x18\x63om.google.protobuf.utilB\x10JsonFormatProto3b\x06proto3') + , + dependencies=[google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__pb2.DESCRIPTOR,]) + +_ENUMTYPE = _descriptor.EnumDescriptor( + name='EnumType', + full_name='proto3.EnumType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=4668, + serialized_end=4696, +) +_sym_db.RegisterEnumDescriptor(_ENUMTYPE) + +EnumType = enum_type_wrapper.EnumTypeWrapper(_ENUMTYPE) +FOO = 0 +BAR = 1 + + + +_MESSAGETYPE = _descriptor.Descriptor( + name='MessageType', + full_name='proto3.MessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.MessageType.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=277, + serialized_end=305, +) + + +_TESTMESSAGE = _descriptor.Descriptor( + name='TestMessage', + full_name='proto3.TestMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestMessage.bool_value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_value', full_name='proto3.TestMessage.int32_value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_value', full_name='proto3.TestMessage.int64_value', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_value', full_name='proto3.TestMessage.uint32_value', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_value', full_name='proto3.TestMessage.uint64_value', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='float_value', full_name='proto3.TestMessage.float_value', index=5, + number=6, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_value', full_name='proto3.TestMessage.double_value', index=6, + number=7, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='proto3.TestMessage.string_value', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_value', full_name='proto3.TestMessage.bytes_value', index=8, + number=9, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_value', full_name='proto3.TestMessage.enum_value', index=9, + number=10, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_value', full_name='proto3.TestMessage.message_value', index=10, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool_value', full_name='proto3.TestMessage.repeated_bool_value', index=11, + number=21, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32_value', full_name='proto3.TestMessage.repeated_int32_value', index=12, + number=22, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64_value', full_name='proto3.TestMessage.repeated_int64_value', index=13, + number=23, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32_value', full_name='proto3.TestMessage.repeated_uint32_value', index=14, + number=24, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64_value', full_name='proto3.TestMessage.repeated_uint64_value', index=15, + number=25, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float_value', full_name='proto3.TestMessage.repeated_float_value', index=16, + number=26, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double_value', full_name='proto3.TestMessage.repeated_double_value', index=17, + number=27, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_value', full_name='proto3.TestMessage.repeated_string_value', index=18, + number=28, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes_value', full_name='proto3.TestMessage.repeated_bytes_value', index=19, + number=29, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_enum_value', full_name='proto3.TestMessage.repeated_enum_value', index=20, + number=30, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_message_value', full_name='proto3.TestMessage.repeated_message_value', index=21, + number=31, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=308, + serialized_end=968, +) + + +_TESTONEOF = _descriptor.Descriptor( + name='TestOneof', + full_name='proto3.TestOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='oneof_int32_value', full_name='proto3.TestOneof.oneof_int32_value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string_value', full_name='proto3.TestOneof.oneof_string_value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes_value', full_name='proto3.TestOneof.oneof_bytes_value', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_enum_value', full_name='proto3.TestOneof.oneof_enum_value', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_message_value', full_name='proto3.TestOneof.oneof_message_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_value', full_name='proto3.TestOneof.oneof_value', + index=0, containing_type=None, fields=[]), + ], + serialized_start=971, + serialized_end=1183, +) + + +_TESTMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1501, + serialized_end=1547, +) + +_TESTMAP_INT32MAPENTRY = _descriptor.Descriptor( + name='Int32MapEntry', + full_name='proto3.TestMap.Int32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Int32MapEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Int32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1549, + serialized_end=1596, +) + +_TESTMAP_INT64MAPENTRY = _descriptor.Descriptor( + name='Int64MapEntry', + full_name='proto3.TestMap.Int64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Int64MapEntry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Int64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1598, + serialized_end=1645, +) + +_TESTMAP_UINT32MAPENTRY = _descriptor.Descriptor( + name='Uint32MapEntry', + full_name='proto3.TestMap.Uint32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Uint32MapEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Uint32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1647, + serialized_end=1695, +) + +_TESTMAP_UINT64MAPENTRY = _descriptor.Descriptor( + name='Uint64MapEntry', + full_name='proto3.TestMap.Uint64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Uint64MapEntry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Uint64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1697, + serialized_end=1745, +) + +_TESTMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.StringMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1747, + serialized_end=1795, +) + +_TESTMAP = _descriptor.Descriptor( + name='TestMap', + full_name='proto3.TestMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_map', full_name='proto3.TestMap.int32_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_map', full_name='proto3.TestMap.int64_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_map', full_name='proto3.TestMap.uint32_map', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_map', full_name='proto3.TestMap.uint64_map', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestMap.string_map', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMAP_BOOLMAPENTRY, _TESTMAP_INT32MAPENTRY, _TESTMAP_INT64MAPENTRY, _TESTMAP_UINT32MAPENTRY, _TESTMAP_UINT64MAPENTRY, _TESTMAP_STRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1186, + serialized_end=1795, +) + + +_TESTNESTEDMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestNestedMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1501, + serialized_end=1547, +) + +_TESTNESTEDMAP_INT32MAPENTRY = _descriptor.Descriptor( + name='Int32MapEntry', + full_name='proto3.TestNestedMap.Int32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Int32MapEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Int32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1549, + serialized_end=1596, +) + +_TESTNESTEDMAP_INT64MAPENTRY = _descriptor.Descriptor( + name='Int64MapEntry', + full_name='proto3.TestNestedMap.Int64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Int64MapEntry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Int64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1598, + serialized_end=1645, +) + +_TESTNESTEDMAP_UINT32MAPENTRY = _descriptor.Descriptor( + name='Uint32MapEntry', + full_name='proto3.TestNestedMap.Uint32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Uint32MapEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Uint32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1647, + serialized_end=1695, +) + +_TESTNESTEDMAP_UINT64MAPENTRY = _descriptor.Descriptor( + name='Uint64MapEntry', + full_name='proto3.TestNestedMap.Uint64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Uint64MapEntry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Uint64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1697, + serialized_end=1745, +) + +_TESTNESTEDMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestNestedMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.StringMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1747, + serialized_end=1795, +) + +_TESTNESTEDMAP_MAPMAPENTRY = _descriptor.Descriptor( + name='MapMapEntry', + full_name='proto3.TestNestedMap.MapMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.MapMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.MapMapEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2503, + serialized_end=2571, +) + +_TESTNESTEDMAP = _descriptor.Descriptor( + name='TestNestedMap', + full_name='proto3.TestNestedMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestNestedMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_map', full_name='proto3.TestNestedMap.int32_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_map', full_name='proto3.TestNestedMap.int64_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_map', full_name='proto3.TestNestedMap.uint32_map', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_map', full_name='proto3.TestNestedMap.uint64_map', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestNestedMap.string_map', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_map', full_name='proto3.TestNestedMap.map_map', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTNESTEDMAP_BOOLMAPENTRY, _TESTNESTEDMAP_INT32MAPENTRY, _TESTNESTEDMAP_INT64MAPENTRY, _TESTNESTEDMAP_UINT32MAPENTRY, _TESTNESTEDMAP_UINT64MAPENTRY, _TESTNESTEDMAP_STRINGMAPENTRY, _TESTNESTEDMAP_MAPMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1798, + serialized_end=2571, +) + + +_TESTWRAPPER = _descriptor.Descriptor( + name='TestWrapper', + full_name='proto3.TestWrapper', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestWrapper.bool_value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_value', full_name='proto3.TestWrapper.int32_value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_value', full_name='proto3.TestWrapper.int64_value', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_value', full_name='proto3.TestWrapper.uint32_value', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_value', full_name='proto3.TestWrapper.uint64_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='float_value', full_name='proto3.TestWrapper.float_value', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_value', full_name='proto3.TestWrapper.double_value', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='proto3.TestWrapper.string_value', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_value', full_name='proto3.TestWrapper.bytes_value', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool_value', full_name='proto3.TestWrapper.repeated_bool_value', index=9, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32_value', full_name='proto3.TestWrapper.repeated_int32_value', index=10, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64_value', full_name='proto3.TestWrapper.repeated_int64_value', index=11, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32_value', full_name='proto3.TestWrapper.repeated_uint32_value', index=12, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64_value', full_name='proto3.TestWrapper.repeated_uint64_value', index=13, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float_value', full_name='proto3.TestWrapper.repeated_float_value', index=14, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double_value', full_name='proto3.TestWrapper.repeated_double_value', index=15, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_value', full_name='proto3.TestWrapper.repeated_string_value', index=16, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes_value', full_name='proto3.TestWrapper.repeated_bytes_value', index=17, + number=19, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2574, + serialized_end=3580, +) + + +_TESTTIMESTAMP = _descriptor.Descriptor( + name='TestTimestamp', + full_name='proto3.TestTimestamp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestTimestamp.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestTimestamp.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3582, + serialized_end=3692, +) + + +_TESTDURATION = _descriptor.Descriptor( + name='TestDuration', + full_name='proto3.TestDuration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestDuration.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestDuration.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3694, + serialized_end=3801, +) + + +_TESTFIELDMASK = _descriptor.Descriptor( + name='TestFieldMask', + full_name='proto3.TestFieldMask', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestFieldMask.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3803, + serialized_end=3861, +) + + +_TESTSTRUCT = _descriptor.Descriptor( + name='TestStruct', + full_name='proto3.TestStruct', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestStruct.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestStruct.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3863, + serialized_end=3964, +) + + +_TESTANY = _descriptor.Descriptor( + name='TestAny', + full_name='proto3.TestAny', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestAny.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestAny.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3966, + serialized_end=4058, +) + + +_TESTVALUE = _descriptor.Descriptor( + name='TestValue', + full_name='proto3.TestValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestValue.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestValue.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4060, + serialized_end=4158, +) + + +_TESTLISTVALUE = _descriptor.Descriptor( + name='TestListValue', + full_name='proto3.TestListValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestListValue.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestListValue.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4160, + serialized_end=4270, +) + + +_TESTBOOLVALUE_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestBoolValue.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestBoolValue.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestBoolValue.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1501, + serialized_end=1547, +) + +_TESTBOOLVALUE = _descriptor.Descriptor( + name='TestBoolValue', + full_name='proto3.TestBoolValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestBoolValue.bool_value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestBoolValue.bool_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTBOOLVALUE_BOOLMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4273, + serialized_end=4410, +) + + +_TESTCUSTOMJSONNAME = _descriptor.Descriptor( + name='TestCustomJsonName', + full_name='proto3.TestCustomJsonName', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestCustomJsonName.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='@value', file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4412, + serialized_end=4455, +) + + +_TESTEXTENSIONS = _descriptor.Descriptor( + name='TestExtensions', + full_name='proto3.TestExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='extensions', full_name='proto3.TestExtensions.extensions', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4457, + serialized_end=4531, +) + + +_TESTENUMVALUE = _descriptor.Descriptor( + name='TestEnumValue', + full_name='proto3.TestEnumValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='enum_value1', full_name='proto3.TestEnumValue.enum_value1', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_value2', full_name='proto3.TestEnumValue.enum_value2', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_value3', full_name='proto3.TestEnumValue.enum_value3', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4534, + serialized_end=4666, +) + +_TESTMESSAGE.fields_by_name['enum_value'].enum_type = _ENUMTYPE +_TESTMESSAGE.fields_by_name['message_value'].message_type = _MESSAGETYPE +_TESTMESSAGE.fields_by_name['repeated_enum_value'].enum_type = _ENUMTYPE +_TESTMESSAGE.fields_by_name['repeated_message_value'].message_type = _MESSAGETYPE +_TESTONEOF.fields_by_name['oneof_enum_value'].enum_type = _ENUMTYPE +_TESTONEOF.fields_by_name['oneof_message_value'].message_type = _MESSAGETYPE +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_int32_value']) +_TESTONEOF.fields_by_name['oneof_int32_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_string_value']) +_TESTONEOF.fields_by_name['oneof_string_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_bytes_value']) +_TESTONEOF.fields_by_name['oneof_bytes_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_enum_value']) +_TESTONEOF.fields_by_name['oneof_enum_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_message_value']) +_TESTONEOF.fields_by_name['oneof_message_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTMAP_BOOLMAPENTRY.containing_type = _TESTMAP +_TESTMAP_INT32MAPENTRY.containing_type = _TESTMAP +_TESTMAP_INT64MAPENTRY.containing_type = _TESTMAP +_TESTMAP_UINT32MAPENTRY.containing_type = _TESTMAP +_TESTMAP_UINT64MAPENTRY.containing_type = _TESTMAP +_TESTMAP_STRINGMAPENTRY.containing_type = _TESTMAP +_TESTMAP.fields_by_name['bool_map'].message_type = _TESTMAP_BOOLMAPENTRY +_TESTMAP.fields_by_name['int32_map'].message_type = _TESTMAP_INT32MAPENTRY +_TESTMAP.fields_by_name['int64_map'].message_type = _TESTMAP_INT64MAPENTRY +_TESTMAP.fields_by_name['uint32_map'].message_type = _TESTMAP_UINT32MAPENTRY +_TESTMAP.fields_by_name['uint64_map'].message_type = _TESTMAP_UINT64MAPENTRY +_TESTMAP.fields_by_name['string_map'].message_type = _TESTMAP_STRINGMAPENTRY +_TESTNESTEDMAP_BOOLMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_INT32MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_INT64MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_UINT32MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_UINT64MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_STRINGMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_MAPMAPENTRY.fields_by_name['value'].message_type = _TESTNESTEDMAP +_TESTNESTEDMAP_MAPMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP.fields_by_name['bool_map'].message_type = _TESTNESTEDMAP_BOOLMAPENTRY +_TESTNESTEDMAP.fields_by_name['int32_map'].message_type = _TESTNESTEDMAP_INT32MAPENTRY +_TESTNESTEDMAP.fields_by_name['int64_map'].message_type = _TESTNESTEDMAP_INT64MAPENTRY +_TESTNESTEDMAP.fields_by_name['uint32_map'].message_type = _TESTNESTEDMAP_UINT32MAPENTRY +_TESTNESTEDMAP.fields_by_name['uint64_map'].message_type = _TESTNESTEDMAP_UINT64MAPENTRY +_TESTNESTEDMAP.fields_by_name['string_map'].message_type = _TESTNESTEDMAP_STRINGMAPENTRY +_TESTNESTEDMAP.fields_by_name['map_map'].message_type = _TESTNESTEDMAP_MAPMAPENTRY +_TESTWRAPPER.fields_by_name['bool_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTWRAPPER.fields_by_name['int32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTWRAPPER.fields_by_name['int64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTWRAPPER.fields_by_name['uint32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTWRAPPER.fields_by_name['uint64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTWRAPPER.fields_by_name['float_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTWRAPPER.fields_by_name['double_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTWRAPPER.fields_by_name['string_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTWRAPPER.fields_by_name['bytes_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTWRAPPER.fields_by_name['repeated_bool_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTWRAPPER.fields_by_name['repeated_int32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTWRAPPER.fields_by_name['repeated_int64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTWRAPPER.fields_by_name['repeated_uint32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTWRAPPER.fields_by_name['repeated_uint64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTWRAPPER.fields_by_name['repeated_float_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTWRAPPER.fields_by_name['repeated_double_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTWRAPPER.fields_by_name['repeated_string_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTWRAPPER.fields_by_name['repeated_bytes_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTTIMESTAMP.fields_by_name['value'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTTIMESTAMP.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTDURATION.fields_by_name['value'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTDURATION.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTFIELDMASK.fields_by_name['value'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTSTRUCT.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTSTRUCT.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTANY.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTANY.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTVALUE.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTVALUE.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTLISTVALUE.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE +_TESTLISTVALUE.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE +_TESTBOOLVALUE_BOOLMAPENTRY.containing_type = _TESTBOOLVALUE +_TESTBOOLVALUE.fields_by_name['bool_map'].message_type = _TESTBOOLVALUE_BOOLMAPENTRY +_TESTEXTENSIONS.fields_by_name['extensions'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLEXTENSIONS +_TESTENUMVALUE.fields_by_name['enum_value1'].enum_type = _ENUMTYPE +_TESTENUMVALUE.fields_by_name['enum_value2'].enum_type = _ENUMTYPE +_TESTENUMVALUE.fields_by_name['enum_value3'].enum_type = _ENUMTYPE +DESCRIPTOR.message_types_by_name['MessageType'] = _MESSAGETYPE +DESCRIPTOR.message_types_by_name['TestMessage'] = _TESTMESSAGE +DESCRIPTOR.message_types_by_name['TestOneof'] = _TESTONEOF +DESCRIPTOR.message_types_by_name['TestMap'] = _TESTMAP +DESCRIPTOR.message_types_by_name['TestNestedMap'] = _TESTNESTEDMAP +DESCRIPTOR.message_types_by_name['TestWrapper'] = _TESTWRAPPER +DESCRIPTOR.message_types_by_name['TestTimestamp'] = _TESTTIMESTAMP +DESCRIPTOR.message_types_by_name['TestDuration'] = _TESTDURATION +DESCRIPTOR.message_types_by_name['TestFieldMask'] = _TESTFIELDMASK +DESCRIPTOR.message_types_by_name['TestStruct'] = _TESTSTRUCT +DESCRIPTOR.message_types_by_name['TestAny'] = _TESTANY +DESCRIPTOR.message_types_by_name['TestValue'] = _TESTVALUE +DESCRIPTOR.message_types_by_name['TestListValue'] = _TESTLISTVALUE +DESCRIPTOR.message_types_by_name['TestBoolValue'] = _TESTBOOLVALUE +DESCRIPTOR.message_types_by_name['TestCustomJsonName'] = _TESTCUSTOMJSONNAME +DESCRIPTOR.message_types_by_name['TestExtensions'] = _TESTEXTENSIONS +DESCRIPTOR.message_types_by_name['TestEnumValue'] = _TESTENUMVALUE +DESCRIPTOR.enum_types_by_name['EnumType'] = _ENUMTYPE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +MessageType = _reflection.GeneratedProtocolMessageType('MessageType', (_message.Message,), dict( + DESCRIPTOR = _MESSAGETYPE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.MessageType) + )) +_sym_db.RegisterMessage(MessageType) + +TestMessage = _reflection.GeneratedProtocolMessageType('TestMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMessage) + )) +_sym_db.RegisterMessage(TestMessage) + +TestOneof = _reflection.GeneratedProtocolMessageType('TestOneof', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestOneof) + )) +_sym_db.RegisterMessage(TestOneof) + +TestMap = _reflection.GeneratedProtocolMessageType('TestMap', (_message.Message,), dict( + + BoolMapEntry = _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_BOOLMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.BoolMapEntry) + )) + , + + Int32MapEntry = _reflection.GeneratedProtocolMessageType('Int32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_INT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Int32MapEntry) + )) + , + + Int64MapEntry = _reflection.GeneratedProtocolMessageType('Int64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_INT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Int64MapEntry) + )) + , + + Uint32MapEntry = _reflection.GeneratedProtocolMessageType('Uint32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_UINT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Uint32MapEntry) + )) + , + + Uint64MapEntry = _reflection.GeneratedProtocolMessageType('Uint64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_UINT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Uint64MapEntry) + )) + , + + StringMapEntry = _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_STRINGMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.StringMapEntry) + )) + , + DESCRIPTOR = _TESTMAP, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap) + )) +_sym_db.RegisterMessage(TestMap) +_sym_db.RegisterMessage(TestMap.BoolMapEntry) +_sym_db.RegisterMessage(TestMap.Int32MapEntry) +_sym_db.RegisterMessage(TestMap.Int64MapEntry) +_sym_db.RegisterMessage(TestMap.Uint32MapEntry) +_sym_db.RegisterMessage(TestMap.Uint64MapEntry) +_sym_db.RegisterMessage(TestMap.StringMapEntry) + +TestNestedMap = _reflection.GeneratedProtocolMessageType('TestNestedMap', (_message.Message,), dict( + + BoolMapEntry = _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_BOOLMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.BoolMapEntry) + )) + , + + Int32MapEntry = _reflection.GeneratedProtocolMessageType('Int32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_INT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Int32MapEntry) + )) + , + + Int64MapEntry = _reflection.GeneratedProtocolMessageType('Int64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_INT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Int64MapEntry) + )) + , + + Uint32MapEntry = _reflection.GeneratedProtocolMessageType('Uint32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_UINT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Uint32MapEntry) + )) + , + + Uint64MapEntry = _reflection.GeneratedProtocolMessageType('Uint64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_UINT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Uint64MapEntry) + )) + , + + StringMapEntry = _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_STRINGMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.StringMapEntry) + )) + , + + MapMapEntry = _reflection.GeneratedProtocolMessageType('MapMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_MAPMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.MapMapEntry) + )) + , + DESCRIPTOR = _TESTNESTEDMAP, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap) + )) +_sym_db.RegisterMessage(TestNestedMap) +_sym_db.RegisterMessage(TestNestedMap.BoolMapEntry) +_sym_db.RegisterMessage(TestNestedMap.Int32MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Int64MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Uint32MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Uint64MapEntry) +_sym_db.RegisterMessage(TestNestedMap.StringMapEntry) +_sym_db.RegisterMessage(TestNestedMap.MapMapEntry) + +TestWrapper = _reflection.GeneratedProtocolMessageType('TestWrapper', (_message.Message,), dict( + DESCRIPTOR = _TESTWRAPPER, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestWrapper) + )) +_sym_db.RegisterMessage(TestWrapper) + +TestTimestamp = _reflection.GeneratedProtocolMessageType('TestTimestamp', (_message.Message,), dict( + DESCRIPTOR = _TESTTIMESTAMP, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestTimestamp) + )) +_sym_db.RegisterMessage(TestTimestamp) + +TestDuration = _reflection.GeneratedProtocolMessageType('TestDuration', (_message.Message,), dict( + DESCRIPTOR = _TESTDURATION, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestDuration) + )) +_sym_db.RegisterMessage(TestDuration) + +TestFieldMask = _reflection.GeneratedProtocolMessageType('TestFieldMask', (_message.Message,), dict( + DESCRIPTOR = _TESTFIELDMASK, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestFieldMask) + )) +_sym_db.RegisterMessage(TestFieldMask) + +TestStruct = _reflection.GeneratedProtocolMessageType('TestStruct', (_message.Message,), dict( + DESCRIPTOR = _TESTSTRUCT, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestStruct) + )) +_sym_db.RegisterMessage(TestStruct) + +TestAny = _reflection.GeneratedProtocolMessageType('TestAny', (_message.Message,), dict( + DESCRIPTOR = _TESTANY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestAny) + )) +_sym_db.RegisterMessage(TestAny) + +TestValue = _reflection.GeneratedProtocolMessageType('TestValue', (_message.Message,), dict( + DESCRIPTOR = _TESTVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestValue) + )) +_sym_db.RegisterMessage(TestValue) + +TestListValue = _reflection.GeneratedProtocolMessageType('TestListValue', (_message.Message,), dict( + DESCRIPTOR = _TESTLISTVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestListValue) + )) +_sym_db.RegisterMessage(TestListValue) + +TestBoolValue = _reflection.GeneratedProtocolMessageType('TestBoolValue', (_message.Message,), dict( + + BoolMapEntry = _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTBOOLVALUE_BOOLMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestBoolValue.BoolMapEntry) + )) + , + DESCRIPTOR = _TESTBOOLVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestBoolValue) + )) +_sym_db.RegisterMessage(TestBoolValue) +_sym_db.RegisterMessage(TestBoolValue.BoolMapEntry) + +TestCustomJsonName = _reflection.GeneratedProtocolMessageType('TestCustomJsonName', (_message.Message,), dict( + DESCRIPTOR = _TESTCUSTOMJSONNAME, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestCustomJsonName) + )) +_sym_db.RegisterMessage(TestCustomJsonName) + +TestExtensions = _reflection.GeneratedProtocolMessageType('TestExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONS, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestExtensions) + )) +_sym_db.RegisterMessage(TestExtensions) + +TestEnumValue = _reflection.GeneratedProtocolMessageType('TestEnumValue', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestEnumValue) + )) +_sym_db.RegisterMessage(TestEnumValue) + + +DESCRIPTOR._options = None +_TESTMAP_BOOLMAPENTRY._options = None +_TESTMAP_INT32MAPENTRY._options = None +_TESTMAP_INT64MAPENTRY._options = None +_TESTMAP_UINT32MAPENTRY._options = None +_TESTMAP_UINT64MAPENTRY._options = None +_TESTMAP_STRINGMAPENTRY._options = None +_TESTNESTEDMAP_BOOLMAPENTRY._options = None +_TESTNESTEDMAP_INT32MAPENTRY._options = None +_TESTNESTEDMAP_INT64MAPENTRY._options = None +_TESTNESTEDMAP_UINT32MAPENTRY._options = None +_TESTNESTEDMAP_UINT64MAPENTRY._options = None +_TESTNESTEDMAP_STRINGMAPENTRY._options = None +_TESTNESTEDMAP_MAPMAPENTRY._options = None +_TESTBOOLVALUE_BOOLMAPENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/google/protobuf/wrappers_pb2.py b/winvenv/Lib/site-packages/google/protobuf/wrappers_pb2.py new file mode 100644 index 0000000..7b66e8a --- /dev/null +++ b/winvenv/Lib/site-packages/google/protobuf/wrappers_pb2.py @@ -0,0 +1,382 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/wrappers.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/wrappers.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\rWrappersProtoP\001Z*github.com/golang/protobuf/ptypes/wrappers\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1egoogle/protobuf/wrappers.proto\x12\x0fgoogle.protobuf\"\x1c\n\x0b\x44oubleValue\x12\r\n\x05value\x18\x01 \x01(\x01\"\x1b\n\nFloatValue\x12\r\n\x05value\x18\x01 \x01(\x02\"\x1b\n\nInt64Value\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1c\n\x0bUInt64Value\x12\r\n\x05value\x18\x01 \x01(\x04\"\x1b\n\nInt32Value\x12\r\n\x05value\x18\x01 \x01(\x05\"\x1c\n\x0bUInt32Value\x12\r\n\x05value\x18\x01 \x01(\r\"\x1a\n\tBoolValue\x12\r\n\x05value\x18\x01 \x01(\x08\"\x1c\n\x0bStringValue\x12\r\n\x05value\x18\x01 \x01(\t\"\x1b\n\nBytesValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x42|\n\x13\x63om.google.protobufB\rWrappersProtoP\x01Z*github.com/golang/protobuf/ptypes/wrappers\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_DOUBLEVALUE = _descriptor.Descriptor( + name='DoubleValue', + full_name='google.protobuf.DoubleValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.DoubleValue.value', index=0, + number=1, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=79, +) + + +_FLOATVALUE = _descriptor.Descriptor( + name='FloatValue', + full_name='google.protobuf.FloatValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.FloatValue.value', index=0, + number=1, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=81, + serialized_end=108, +) + + +_INT64VALUE = _descriptor.Descriptor( + name='Int64Value', + full_name='google.protobuf.Int64Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Int64Value.value', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=110, + serialized_end=137, +) + + +_UINT64VALUE = _descriptor.Descriptor( + name='UInt64Value', + full_name='google.protobuf.UInt64Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.UInt64Value.value', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=139, + serialized_end=167, +) + + +_INT32VALUE = _descriptor.Descriptor( + name='Int32Value', + full_name='google.protobuf.Int32Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Int32Value.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=169, + serialized_end=196, +) + + +_UINT32VALUE = _descriptor.Descriptor( + name='UInt32Value', + full_name='google.protobuf.UInt32Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.UInt32Value.value', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=198, + serialized_end=226, +) + + +_BOOLVALUE = _descriptor.Descriptor( + name='BoolValue', + full_name='google.protobuf.BoolValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.BoolValue.value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=228, + serialized_end=254, +) + + +_STRINGVALUE = _descriptor.Descriptor( + name='StringValue', + full_name='google.protobuf.StringValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.StringValue.value', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=256, + serialized_end=284, +) + + +_BYTESVALUE = _descriptor.Descriptor( + name='BytesValue', + full_name='google.protobuf.BytesValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.BytesValue.value', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=286, + serialized_end=313, +) + +DESCRIPTOR.message_types_by_name['DoubleValue'] = _DOUBLEVALUE +DESCRIPTOR.message_types_by_name['FloatValue'] = _FLOATVALUE +DESCRIPTOR.message_types_by_name['Int64Value'] = _INT64VALUE +DESCRIPTOR.message_types_by_name['UInt64Value'] = _UINT64VALUE +DESCRIPTOR.message_types_by_name['Int32Value'] = _INT32VALUE +DESCRIPTOR.message_types_by_name['UInt32Value'] = _UINT32VALUE +DESCRIPTOR.message_types_by_name['BoolValue'] = _BOOLVALUE +DESCRIPTOR.message_types_by_name['StringValue'] = _STRINGVALUE +DESCRIPTOR.message_types_by_name['BytesValue'] = _BYTESVALUE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DoubleValue = _reflection.GeneratedProtocolMessageType('DoubleValue', (_message.Message,), dict( + DESCRIPTOR = _DOUBLEVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DoubleValue) + )) +_sym_db.RegisterMessage(DoubleValue) + +FloatValue = _reflection.GeneratedProtocolMessageType('FloatValue', (_message.Message,), dict( + DESCRIPTOR = _FLOATVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FloatValue) + )) +_sym_db.RegisterMessage(FloatValue) + +Int64Value = _reflection.GeneratedProtocolMessageType('Int64Value', (_message.Message,), dict( + DESCRIPTOR = _INT64VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Int64Value) + )) +_sym_db.RegisterMessage(Int64Value) + +UInt64Value = _reflection.GeneratedProtocolMessageType('UInt64Value', (_message.Message,), dict( + DESCRIPTOR = _UINT64VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value) + )) +_sym_db.RegisterMessage(UInt64Value) + +Int32Value = _reflection.GeneratedProtocolMessageType('Int32Value', (_message.Message,), dict( + DESCRIPTOR = _INT32VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Int32Value) + )) +_sym_db.RegisterMessage(Int32Value) + +UInt32Value = _reflection.GeneratedProtocolMessageType('UInt32Value', (_message.Message,), dict( + DESCRIPTOR = _UINT32VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value) + )) +_sym_db.RegisterMessage(UInt32Value) + +BoolValue = _reflection.GeneratedProtocolMessageType('BoolValue', (_message.Message,), dict( + DESCRIPTOR = _BOOLVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.BoolValue) + )) +_sym_db.RegisterMessage(BoolValue) + +StringValue = _reflection.GeneratedProtocolMessageType('StringValue', (_message.Message,), dict( + DESCRIPTOR = _STRINGVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.StringValue) + )) +_sym_db.RegisterMessage(StringValue) + +BytesValue = _reflection.GeneratedProtocolMessageType('BytesValue', (_message.Message,), dict( + DESCRIPTOR = _BYTESVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.BytesValue) + )) +_sym_db.RegisterMessage(BytesValue) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/winvenv/Lib/site-packages/pip-18.1.dist-info/INSTALLER b/winvenv/Lib/site-packages/pip-18.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/winvenv/Lib/site-packages/pip-18.1.dist-info/LICENSE.txt b/winvenv/Lib/site-packages/pip-18.1.dist-info/LICENSE.txt new file mode 100644 index 0000000..d3379fa --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2018 The pip developers (see AUTHORS.txt file) + +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/winvenv/Lib/site-packages/pip-18.1.dist-info/METADATA b/winvenv/Lib/site-packages/pip-18.1.dist-info/METADATA new file mode 100644 index 0000000..2e314aa --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/METADATA @@ -0,0 +1,70 @@ +Metadata-Version: 2.1 +Name: pip +Version: 18.1 +Summary: The PyPA recommended tool for installing Python packages. +Home-page: https://pip.pypa.io/ +Author: The pip developers +Author-email: pypa-dev@groups.google.com +License: MIT +Keywords: distutils easy_install egg setuptools wheel virtualenv +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Build Tools +Classifier: Programming Language :: Python +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 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* + +pip +=== + +The `PyPA recommended`_ tool for installing Python packages. + +.. image:: https://img.shields.io/pypi/v/pip.svg + :target: https://pypi.org/project/pip/ + +.. image:: https://img.shields.io/travis/pypa/pip/master.svg?label=travis-ci + :target: https://travis-ci.org/pypa/pip + +.. image:: https://img.shields.io/appveyor/ci/pypa/pip.svg?label=appveyor-ci + :target: https://ci.appveyor.com/project/pypa/pip/history + +.. image:: https://readthedocs.org/projects/pip/badge/?version=latest + :target: https://pip.pypa.io/en/latest + +* `Installation`_ +* `Documentation`_ +* `Changelog`_ +* `GitHub Page`_ +* `Issue Tracking`_ +* `User mailing list`_ +* `Dev mailing list`_ +* User IRC: #pypa on Freenode. +* Dev IRC: #pypa-dev on Freenode. + +Code of Conduct +--------------- + +Everyone interacting in the pip project's codebases, issue trackers, chat +rooms and mailing lists is expected to follow the `PyPA Code of Conduct`_. + +.. _PyPA recommended: https://packaging.python.org/en/latest/current/ +.. _Installation: https://pip.pypa.io/en/stable/installing.html +.. _Documentation: https://pip.pypa.io/en/stable/ +.. _Changelog: https://pip.pypa.io/en/stable/news.html +.. _GitHub Page: https://github.com/pypa/pip +.. _Issue Tracking: https://github.com/pypa/pip/issues +.. _User mailing list: https://groups.google.com/forum/#!forum/python-virtualenv +.. _Dev mailing list: https://groups.google.com/forum/#!forum/pypa-dev +.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ + + diff --git a/winvenv/Lib/site-packages/pip-18.1.dist-info/RECORD b/winvenv/Lib/site-packages/pip-18.1.dist-info/RECORD new file mode 100644 index 0000000..ae498da --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/RECORD @@ -0,0 +1,614 @@ +../../Scripts/pip.exe,sha256=bKPRIodcTx_tSVGjggSW4YgwqnCTk48hFAdzPunAydc,102791 +../../Scripts/pip3.7.exe,sha256=bKPRIodcTx_tSVGjggSW4YgwqnCTk48hFAdzPunAydc,102791 +../../Scripts/pip3.exe,sha256=bKPRIodcTx_tSVGjggSW4YgwqnCTk48hFAdzPunAydc,102791 +pip-18.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip-18.1.dist-info/LICENSE.txt,sha256=ORqHhOMZ2uVDFHfUzJvFBPxdcf2eieHIDxzThV9dfPo,1090 +pip-18.1.dist-info/METADATA,sha256=D7pqBJTuqM9w_HTW91a0XGjLT9vynlBAE4pPCt_W_UE,2588 +pip-18.1.dist-info/RECORD,, +pip-18.1.dist-info/WHEEL,sha256=8T8fxefr_r-A79qbOJ9d_AaEgkpCGmEPHc-gpCq5BRg,110 +pip-18.1.dist-info/entry_points.txt,sha256=S_zfxY25QtQDVY1BiLAmOKSkkI5llzCKPLiYOSEupsY,98 +pip-18.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/__init__.py,sha256=nO-iphoXiDoci_ZAMl-PG2zdd4Y7m88jBDILTYzwGy4,21 +pip/__main__.py,sha256=L3IHqBeasELUHvwy5CT_izVEMhM12tve289qut49DvU,623 +pip/__pycache__/__init__.cpython-37.pyc,, +pip/__pycache__/__main__.cpython-37.pyc,, +pip/_internal/__init__.py,sha256=b0jSFCCViGhB1RWni35_NMkH3Y-mbZrV648DGMagDjs,2869 +pip/_internal/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/__pycache__/build_env.cpython-37.pyc,, +pip/_internal/__pycache__/cache.cpython-37.pyc,, +pip/_internal/__pycache__/configuration.cpython-37.pyc,, +pip/_internal/__pycache__/download.cpython-37.pyc,, +pip/_internal/__pycache__/exceptions.cpython-37.pyc,, +pip/_internal/__pycache__/index.cpython-37.pyc,, +pip/_internal/__pycache__/locations.cpython-37.pyc,, +pip/_internal/__pycache__/pep425tags.cpython-37.pyc,, +pip/_internal/__pycache__/pyproject.cpython-37.pyc,, +pip/_internal/__pycache__/resolve.cpython-37.pyc,, +pip/_internal/__pycache__/wheel.cpython-37.pyc,, +pip/_internal/build_env.py,sha256=zKhqmDMnrX5OTSNQ4xBw-mN5mTGVu6wjiNFW-ajWYEI,4797 +pip/_internal/cache.py,sha256=96_aKtDbwgLEVNgNabOT8GrFCYZEACedoiucqU5ccg8,6829 +pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 +pip/_internal/cli/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/cli/__pycache__/autocompletion.cpython-37.pyc,, +pip/_internal/cli/__pycache__/base_command.cpython-37.pyc,, +pip/_internal/cli/__pycache__/cmdoptions.cpython-37.pyc,, +pip/_internal/cli/__pycache__/main_parser.cpython-37.pyc,, +pip/_internal/cli/__pycache__/parser.cpython-37.pyc,, +pip/_internal/cli/__pycache__/status_codes.cpython-37.pyc,, +pip/_internal/cli/autocompletion.py,sha256=ptvsMdGjq42pzoY4skABVF43u2xAtLJlXAulPi-A10Y,6083 +pip/_internal/cli/base_command.py,sha256=ke6af4iWzrZoc3HtiPKnCZJvD6GlX8dRwBwpFCg1axc,9963 +pip/_internal/cli/cmdoptions.py,sha256=WoPPY1uHsDjA_NvZek8Mko38rxraD3pX8eZUkNKvk10,19468 +pip/_internal/cli/main_parser.py,sha256=Ga_kT7if-Gg0rmmRqlGEHW6JWVm9zwzO7igJm6RE9EI,2763 +pip/_internal/cli/parser.py,sha256=VZKUKJPbU6I2cHPLDOikin-aCx7OvLcZ3fzYp3xytd8,9378 +pip/_internal/cli/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 +pip/_internal/commands/__init__.py,sha256=CQAzhVx9ViPtqLNUvAeqnKj5iWfFEcqMx5RlZWjJ30c,2251 +pip/_internal/commands/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/commands/__pycache__/check.cpython-37.pyc,, +pip/_internal/commands/__pycache__/completion.cpython-37.pyc,, +pip/_internal/commands/__pycache__/configuration.cpython-37.pyc,, +pip/_internal/commands/__pycache__/download.cpython-37.pyc,, +pip/_internal/commands/__pycache__/freeze.cpython-37.pyc,, +pip/_internal/commands/__pycache__/hash.cpython-37.pyc,, +pip/_internal/commands/__pycache__/help.cpython-37.pyc,, +pip/_internal/commands/__pycache__/install.cpython-37.pyc,, +pip/_internal/commands/__pycache__/list.cpython-37.pyc,, +pip/_internal/commands/__pycache__/search.cpython-37.pyc,, +pip/_internal/commands/__pycache__/show.cpython-37.pyc,, +pip/_internal/commands/__pycache__/uninstall.cpython-37.pyc,, +pip/_internal/commands/__pycache__/wheel.cpython-37.pyc,, +pip/_internal/commands/check.py,sha256=CyeYH2kfDKSGSURoBfWtx-sTcZZQP-bK170NmKYlmsg,1398 +pip/_internal/commands/completion.py,sha256=hqvCvoxsIHjysiD7olHKTqK2lzE1_lS6LWn69kN5qyI,2929 +pip/_internal/commands/configuration.py,sha256=265HWuUxPggCNcIeWHA3p-LDDiRVnexwFgwmHGgWOHY,7125 +pip/_internal/commands/download.py,sha256=D_iGMp3xX2iD7KZYZAjXlYT3rf3xjwxyYe05KE-DVzE,6514 +pip/_internal/commands/freeze.py,sha256=VvS3G0wrm_9BH3B7Ex5msLL_1UQTtCq5G8dDI63Iemo,3259 +pip/_internal/commands/hash.py,sha256=K1JycsD-rpjqrRcL_ijacY9UKmI82pQcLYq4kCM4Pv0,1681 +pip/_internal/commands/help.py,sha256=MwBhPJpW1Dt3GfJV3V8V6kgAy_pXT0jGrZJB1wCTW-E,1090 +pip/_internal/commands/install.py,sha256=tKyzfo5bhDGLVTTQCQJ9PFnDjimQvEWnwIAI2XHpaac,21039 +pip/_internal/commands/list.py,sha256=n740MsR0cG34EuvGWMzdVl0uIA3UIYx1_95FUsTktN0,10272 +pip/_internal/commands/search.py,sha256=sLZ9icKMEEGekHvzRRZMiTd1zCFIZeDptyyU1mQCYzk,4728 +pip/_internal/commands/show.py,sha256=9EVh86vY0NZdlhT-wsuV-zq_MAV6qqV4S1Akn3wkUuw,6289 +pip/_internal/commands/uninstall.py,sha256=h0gfPF5jylDESx_IHgF6bZME7QAEOHzQHdn65GP-jrE,2963 +pip/_internal/commands/wheel.py,sha256=ZuVf_DMpKCUzBVstolvQPAeajQRC51Oky5_hDHzhhFs,7020 +pip/_internal/configuration.py,sha256=KMgG3ufFrUKX_QESi2cMVvFi47tl845Bg1ZkNthlWik,13243 +pip/_internal/download.py,sha256=c5Hkimq39eJdZ6DN0_0etjK43-0a5CK_W_3sVLqH87g,33300 +pip/_internal/exceptions.py,sha256=EIGotnq6qM2nbGtnlgZ8Xp5VfP2W4-9UOCzQGMwy5MY,8899 +pip/_internal/index.py,sha256=6CAtZ8QTLcpw0fJqQ9OPu-Os1ettLZtVY1pPSKia8r8,34789 +pip/_internal/locations.py,sha256=ujNrLnA04Y_EmSriO0nS6qkkw_BkPfobB_hdwIDPvpM,6307 +pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 +pip/_internal/models/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/models/__pycache__/candidate.cpython-37.pyc,, +pip/_internal/models/__pycache__/format_control.cpython-37.pyc,, +pip/_internal/models/__pycache__/index.cpython-37.pyc,, +pip/_internal/models/__pycache__/link.cpython-37.pyc,, +pip/_internal/models/candidate.py,sha256=zq2Vb5l5JflrVX7smHTJHQciZWHyoJZuYTLeQa1G16c,741 +pip/_internal/models/format_control.py,sha256=aDbH4D2XuyaGjtRjTLQhNzClAcLZdJCKSHO8xbZSmFA,2202 +pip/_internal/models/index.py,sha256=YI1WlhWfS9mVPY0bIboA5la2pjJ2J0qgPJIbvdEjZBk,996 +pip/_internal/models/link.py,sha256=E61PvS2Wrmb9-zT-eAc_8_xI3C-89wJlpL8SL-mlQmg,3998 +pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/operations/__pycache__/check.cpython-37.pyc,, +pip/_internal/operations/__pycache__/freeze.cpython-37.pyc,, +pip/_internal/operations/__pycache__/prepare.cpython-37.pyc,, +pip/_internal/operations/check.py,sha256=ahcOg5p68nNow6_wy5prYYK0KZq22lm0CsJn8AyDMCI,4937 +pip/_internal/operations/freeze.py,sha256=lskaBcqf3bPZupG032fuLf76QYv5wpAQ6jsiXac56Bg,10450 +pip/_internal/operations/prepare.py,sha256=atoLFj3OD5KfXsa5dYBMC_mI06l068F5yZhF4jle1JA,14280 +pip/_internal/pep425tags.py,sha256=TQhxOPss4RjxgyVgxpSRe31HaTcWmn-LVjWBbkvkjzk,10845 +pip/_internal/pyproject.py,sha256=fpO52MCa3w5xSlXIBXw39BDTGzP8G4570EW34hVvIKQ,5481 +pip/_internal/req/__init__.py,sha256=JnNZWvKUQuqAwHh64LCD3zprzWIVQEXChTo2UGHzVqo,2093 +pip/_internal/req/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/req/__pycache__/constructors.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_file.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_install.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_set.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_tracker.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_uninstall.cpython-37.pyc,, +pip/_internal/req/constructors.py,sha256=97WQp9Svh-Jw3oLZL9_57gJ3zihm5LnWlSRjOwOorDU,9573 +pip/_internal/req/req_file.py,sha256=ORA0GKUjGd6vy7pmBwXR55FFj4h_OxYykFQ6gHuWvt0,11940 +pip/_internal/req/req_install.py,sha256=ry1RtNNCefDHAnf3EeGMpea-9pC6Yk1uHzP0Q5p2Un0,34046 +pip/_internal/req/req_set.py,sha256=nE6oagXJSiQREuuebX3oJO5OHSOVUIlvLLilodetBzc,7264 +pip/_internal/req/req_tracker.py,sha256=zH28YHV5TXAVh1ZOEZi6Z1Edkiu26dN2tXfR6VbQ3B4,2370 +pip/_internal/req/req_uninstall.py,sha256=ORSPah64KOVrKo-InMM3zgS5HQqbl5TLHFnE_Lxstq8,16737 +pip/_internal/resolve.py,sha256=tdepxCewsXXNFKSIYGSxiLvzi1xCv7UVFT9jRCDO90A,13578 +pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/utils/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/utils/__pycache__/appdirs.cpython-37.pyc,, +pip/_internal/utils/__pycache__/compat.cpython-37.pyc,, +pip/_internal/utils/__pycache__/deprecation.cpython-37.pyc,, +pip/_internal/utils/__pycache__/encoding.cpython-37.pyc,, +pip/_internal/utils/__pycache__/filesystem.cpython-37.pyc,, +pip/_internal/utils/__pycache__/glibc.cpython-37.pyc,, +pip/_internal/utils/__pycache__/hashes.cpython-37.pyc,, +pip/_internal/utils/__pycache__/logging.cpython-37.pyc,, +pip/_internal/utils/__pycache__/misc.cpython-37.pyc,, +pip/_internal/utils/__pycache__/models.cpython-37.pyc,, +pip/_internal/utils/__pycache__/outdated.cpython-37.pyc,, +pip/_internal/utils/__pycache__/packaging.cpython-37.pyc,, +pip/_internal/utils/__pycache__/setuptools_build.cpython-37.pyc,, +pip/_internal/utils/__pycache__/temp_dir.cpython-37.pyc,, +pip/_internal/utils/__pycache__/typing.cpython-37.pyc,, +pip/_internal/utils/__pycache__/ui.cpython-37.pyc,, +pip/_internal/utils/appdirs.py,sha256=SPfibHtvOKzD_sHrpEZ60HfLae3GharU4Tg7SB3c-XM,9120 +pip/_internal/utils/compat.py,sha256=LSAvzXcsGY2O2drKIPszR5Ja2G0kup__51l3bx1jR_Q,8015 +pip/_internal/utils/deprecation.py,sha256=yQTe6dyWlBfxSBrOv_MdRXF1RPLER_EWOp-pa2zLoZc,3021 +pip/_internal/utils/encoding.py,sha256=D8tmfStCah6xh9OLhH9mWLr77q4akhg580YHJMKpq3Y,1025 +pip/_internal/utils/filesystem.py,sha256=ZOIHbacJ-SJtuZru4GoA5DuSIYyeaE4G5kfZPf5cn1A,915 +pip/_internal/utils/glibc.py,sha256=prOrsBjmgkDE-hY4Pl120yF5MIlkkmGrFLs8XfIyT-w,3004 +pip/_internal/utils/hashes.py,sha256=rJk-gj6F-sHggXAG97dhynqUHFFgApyZLWgaG2xCHME,2900 +pip/_internal/utils/logging.py,sha256=BQeUDEER3zlK0O4yv6DBfz6TK3f9XoLXyDlnB0mZVf0,6295 +pip/_internal/utils/misc.py,sha256=YscDfBiFx1spYOtSgdI_5hnc5BZUysWAyz1aVL5y-48,29904 +pip/_internal/utils/models.py,sha256=DQYZSRhjvSdDTAaJLLCpDtxAn1S_-v_8nlNjv4T2jwY,1042 +pip/_internal/utils/outdated.py,sha256=BXtCMKR6gjTrvMfP3MWzZ1Y4ZU4qqoCfbRNqQCusVt8,5642 +pip/_internal/utils/packaging.py,sha256=Ru8ls_S8PPKR8RKEn7jMetENY_A9jPet1HlhTZwpFxU,2443 +pip/_internal/utils/setuptools_build.py,sha256=0blfscmNJW_iZ5DcswJeDB_PbtTEjfK9RL1R1WEDW2E,278 +pip/_internal/utils/temp_dir.py,sha256=n2FkVlwRX_hS61fYt3nSAh2e2V6CcZn_dfbPId1pAQE,2615 +pip/_internal/utils/typing.py,sha256=ztYtZAcqjCYDwP-WlF6EiAAskAsZBMMXtuqvfgZIlgQ,1139 +pip/_internal/utils/ui.py,sha256=FW8wdtc7DvNwJClGr_TvGZlqcoO482GYe0UY9nKmpso,13657 +pip/_internal/vcs/__init__.py,sha256=2Ct9ogOwzS6ZKKaEXKN2XDiBOiFHMcejnN1KM21mLrQ,16319 +pip/_internal/vcs/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/bazaar.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/git.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/mercurial.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/subversion.cpython-37.pyc,, +pip/_internal/vcs/bazaar.py,sha256=rjskVmSSn68O7lC5JrGmDTWXneXFMMJJvj_bbdSM8QA,3669 +pip/_internal/vcs/git.py,sha256=n1cFBqTnLIcxAOClZMgOBqELjEjygDBPZ9z-Q7g0qVQ,12580 +pip/_internal/vcs/mercurial.py,sha256=jVTa0XQpFR6EiBcaqW4E4JjTce_t1tFnKRaIhaIPlS8,3471 +pip/_internal/vcs/subversion.py,sha256=vDLTfcjj0kgqcEsbPBfveC4CRxyhWiOjke-qN0Zr8CE,7676 +pip/_internal/wheel.py,sha256=fg9E936DaI1LyrBPHqtzHG_WEVyuUwipHISkD6N3jNw,32007 +pip/_vendor/__init__.py,sha256=XnhkujjE1qUGRlYGYbIRrEGYYYBcNLBraE27HH48wYw,4756 +pip/_vendor/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/__pycache__/appdirs.cpython-37.pyc,, +pip/_vendor/__pycache__/distro.cpython-37.pyc,, +pip/_vendor/__pycache__/ipaddress.cpython-37.pyc,, +pip/_vendor/__pycache__/pyparsing.cpython-37.pyc,, +pip/_vendor/__pycache__/retrying.cpython-37.pyc,, +pip/_vendor/__pycache__/six.cpython-37.pyc,, +pip/_vendor/appdirs.py,sha256=BENKsvcA08IpccD9345-rMrg3aXWFA1q6BFEglnHg6I,24547 +pip/_vendor/cachecontrol/__init__.py,sha256=6cRPchVqkAkeUtYTSW8qCetjSqJo-GxP-n4VMVDbvmc,302 +pip/_vendor/cachecontrol/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/adapter.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/cache.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/controller.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/serialize.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-37.pyc,, +pip/_vendor/cachecontrol/_cmd.py,sha256=URGE0KrA87QekCG3SGPatlSPT571dZTDjNa-ZXX3pDc,1295 +pip/_vendor/cachecontrol/adapter.py,sha256=eBGAtVNRZgtl_Kj5JV54miqL9YND-D0JZPahwY8kFtY,4863 +pip/_vendor/cachecontrol/cache.py,sha256=1fc4wJP8HYt1ycnJXeEw5pCpeBL2Cqxx6g9Fb0AYDWQ,805 +pip/_vendor/cachecontrol/caches/__init__.py,sha256=-gHNKYvaeD0kOk5M74eOrsSgIKUtC6i6GfbmugGweEo,86 +pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-37.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-37.pyc,, +pip/_vendor/cachecontrol/caches/file_cache.py,sha256=8vrSzzGcdfEfICago1uSFbkumNJMGLbCdEkXsmUIExw,4177 +pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=HxelMpNCo-dYr2fiJDwM3hhhRmxUYtB5tXm1GpAAT4Y,856 +pip/_vendor/cachecontrol/compat.py,sha256=kHNvMRdt6s_Xwqq_9qJmr9ou3wYMOMUMxPPcwNxT8Mc,695 +pip/_vendor/cachecontrol/controller.py,sha256=U7g-YwizQ2O5NRgK_MZreF1ntM4E49C3PuF3od-Vwz4,13698 +pip/_vendor/cachecontrol/filewrapper.py,sha256=vACKO8Llzu_ZWyjV1Fxn1MA4TGU60N5N3GSrAFdAY2Q,2533 +pip/_vendor/cachecontrol/heuristics.py,sha256=BFGHJ3yQcxvZizfo90LLZ04T_Z5XSCXvFotrp7Us0sc,4070 +pip/_vendor/cachecontrol/serialize.py,sha256=GebE34fgToyWwAsRPguh8hEPN6CqoG-5hRMXRsjVABQ,6954 +pip/_vendor/cachecontrol/wrapper.py,sha256=sfr9YHWx-5TwNz1H5rT6QOo8ggII6v3vbEDjQFwR6wc,671 +pip/_vendor/certifi/__init__.py,sha256=5lCYV1iWxoirX1OAaSHkBYUuZGdcwEjEBS6DS_trL0s,63 +pip/_vendor/certifi/__main__.py,sha256=NaCn6WtWME-zzVWQ2j4zFyl8cY4knDa9CwtHNIeFPhM,53 +pip/_vendor/certifi/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/certifi/__pycache__/__main__.cpython-37.pyc,, +pip/_vendor/certifi/__pycache__/core.cpython-37.pyc,, +pip/_vendor/certifi/cacert.pem,sha256=XA-4HVBsOrBD5lfg-b3PiUzAvwUd2qlIzwXypIMIRGM,263074 +pip/_vendor/certifi/core.py,sha256=xPQDdG_siy5A7BfqGWa7RJhcA61xXEqPiSrw9GNyhHE,836 +pip/_vendor/chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 +pip/_vendor/chardet/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/big5freq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/big5prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/chardistribution.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/charsetprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/cp949prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/enums.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/escprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/escsm.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/eucjpprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euckrfreq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euckrprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euctwfreq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euctwprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/gb2312freq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/gb2312prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/hebrewprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/jisfreq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/jpcntx.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langcyrillicmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langthaimodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/latin1prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/mbcssm.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/sjisprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/universaldetector.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/utf8prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/version.cpython-37.pyc,, +pip/_vendor/chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 +pip/_vendor/chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 +pip/_vendor/chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 +pip/_vendor/chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 +pip/_vendor/chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 +pip/_vendor/chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +pip/_vendor/chardet/cli/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-37.pyc,, +pip/_vendor/chardet/cli/chardetect.py,sha256=DI8dlV3FBD0c0XA_y3sQ78z754DUv1J8n34RtDjOXNw,2774 +pip/_vendor/chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 +pip/_vendor/chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 +pip/_vendor/chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 +pip/_vendor/chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 +pip/_vendor/chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 +pip/_vendor/chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 +pip/_vendor/chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 +pip/_vendor/chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 +pip/_vendor/chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 +pip/_vendor/chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 +pip/_vendor/chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 +pip/_vendor/chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 +pip/_vendor/chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 +pip/_vendor/chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 +pip/_vendor/chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 +pip/_vendor/chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 +pip/_vendor/chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 +pip/_vendor/chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 +pip/_vendor/chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 +pip/_vendor/chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 +pip/_vendor/chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 +pip/_vendor/chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 +pip/_vendor/chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 +pip/_vendor/chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 +pip/_vendor/chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 +pip/_vendor/chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 +pip/_vendor/chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 +pip/_vendor/chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 +pip/_vendor/chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 +pip/_vendor/chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 +pip/_vendor/chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 +pip/_vendor/chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 +pip/_vendor/chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 +pip/_vendor/colorama/__init__.py,sha256=V3-Hv_vOa-2lE5Q_0mGkdhZo-9e4XrGTW_44cU81qQY,240 +pip/_vendor/colorama/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/ansi.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/ansitowin32.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/initialise.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/win32.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/winterm.cpython-37.pyc,, +pip/_vendor/colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 +pip/_vendor/colorama/ansitowin32.py,sha256=QrieYX2tsaWIO19P6biMa1zUCt-_abudoEp2_IdqZZU,9668 +pip/_vendor/colorama/initialise.py,sha256=cHqVJtb82OG7HUCxvQ2joG7N_CoxbIKbI_fgryZkj20,1917 +pip/_vendor/colorama/win32.py,sha256=5Hc7L1LabubrYDhdWAfRyzlt14ErP3YKDvf_zYaarLk,5426 +pip/_vendor/colorama/winterm.py,sha256=V7U7ojwG1q4n6PKripjEvW_htYQi5ueXSM3LUUoqqDY,6290 +pip/_vendor/distlib/__init__.py,sha256=GxRrh1augb66Eo9NB9jrdwQS02KcBypj9o_-C3oyKZI,581 +pip/_vendor/distlib/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/database.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/index.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/locators.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/manifest.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/markers.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/metadata.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/resources.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/scripts.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/util.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/version.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/wheel.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 +pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/misc.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-37.pyc,, +pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 +pip/_vendor/distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 +pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 +pip/_vendor/distlib/_backport/sysconfig.py,sha256=JdJ9ztRy4Hc-b5-VS74x3nUtdEIVr_OBvMsIb8O2sjc,26964 +pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 +pip/_vendor/distlib/compat.py,sha256=xdNZmqFN5HwF30HjRn5M415pcC2kgXRBXn767xS8v-M,41404 +pip/_vendor/distlib/database.py,sha256=LqTcNkDyV4bWcc_qDxiYJHnXaNxFs1O1bFSAg_reaI0,50868 +pip/_vendor/distlib/index.py,sha256=Dd1kIV06XIdynNpKxHMMRRIKsXuoUsG7QIzntfVtZCI,21073 +pip/_vendor/distlib/locators.py,sha256=e4UaQSzNg5iG3PfQRH6lnVMfLOwhm2sVmGGRdjdB3ik,51657 +pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 +pip/_vendor/distlib/markers.py,sha256=6Ac3cCfFBERexiESWIOXmg-apIP8l2esafNSX3KMy-8,4387 +pip/_vendor/distlib/metadata.py,sha256=Ns92dqeMxopDPQsiEWnhMtd4RagJaA58lz8O_vjCxyk,39986 +pip/_vendor/distlib/resources.py,sha256=2FGv0ZHF14KXjLIlL0R991lyQQGcewOS4mJ-5n-JVnc,10766 +pip/_vendor/distlib/scripts.py,sha256=WEqXkpRvqR6oe-QlMRYg8gEJxXRWJeWn1GPc0ihZ4N0,16585 +pip/_vendor/distlib/t32.exe,sha256=ftub1bsSPUCOnBn-eCtcarKTk0N0CBEP53BumkIxWJE,92672 +pip/_vendor/distlib/t64.exe,sha256=iChOG627LWTHY8-jzSwlo9SYU5a-0JHwQu4AqDz8I68,102400 +pip/_vendor/distlib/util.py,sha256=FnzjaibVcIg1xOtET6QPNeqTnn3LcWLCjNOficMyGKA,59494 +pip/_vendor/distlib/version.py,sha256=_n7F6juvQGAcn769E_SHa7fOcf5ERlEVymJ_EjPRwGw,23391 +pip/_vendor/distlib/w32.exe,sha256=NPYPpt7PIjVqABEu1CzabbDyHHkJpuw-_qZq_48H0j0,89088 +pip/_vendor/distlib/w64.exe,sha256=Yb-qr1OQEzL8KRGTk-XHUZDwMSljfQeZnVoTk-K4e7E,99328 +pip/_vendor/distlib/wheel.py,sha256=W9aKwi4CQL_bQFYb8IcwH-c6WK-yku5P8SY3RGPv-Mk,39506 +pip/_vendor/distro.py,sha256=dOMrjIXv-3GmEbtP-NJc057Sv19P7ZAdke-v0TBeNio,42455 +pip/_vendor/html5lib/__init__.py,sha256=Ztrn7UvF-wIFAgRBBa0ML-Gu5AffH3BPX_INJx4SaBI,1162 +pip/_vendor/html5lib/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_inputstream.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_utils.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/constants.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/html5parser.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/serializer.cpython-37.pyc,, +pip/_vendor/html5lib/_ihatexml.py,sha256=3LBtJMlzgwM8vpQiU1TvGmEEmNH72sV0yD8yS53y07A,16705 +pip/_vendor/html5lib/_inputstream.py,sha256=bPUWcAfJScK4xkjQQaG_HsI2BvEVbFvI0AsodDYPQj0,32552 +pip/_vendor/html5lib/_tokenizer.py,sha256=YAaOEBD6qc5ISq9Xt9Nif1OFgcybTTfMdwqBkZhpAq4,76580 +pip/_vendor/html5lib/_trie/__init__.py,sha256=8VR1bcgD2OpeS2XExpu5yBhP_Q1K-lwKbBKICBPf1kU,289 +pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/py.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/_base.py,sha256=uJHVhzif9S0MJXgy9F98iEev5evi_rgUk5BmEbUSp8c,930 +pip/_vendor/html5lib/_trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 +pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 +pip/_vendor/html5lib/_utils.py,sha256=ismpASeqa2jqEPQjHUj8vReAf7yIoKnvLN5fuOw6nv0,4015 +pip/_vendor/html5lib/constants.py,sha256=4lmZWLtEPRLnl8NzftOoYTJdo6jpeMtP6dqQC0g_bWQ,83518 +pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/base.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/lint.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-37.pyc,, +pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=lViZc2JMCclXi_5gduvmdzrRxtO5Xo9ONnbHBVCsykU,919 +pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 +pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=egDXUEHXmAG9504xz0K6ALDgYkvUrC2q15YUVeNlVQg,2945 +pip/_vendor/html5lib/filters/lint.py,sha256=jk6q56xY0ojiYfvpdP-OZSm9eTqcAdRqhCoPItemPYA,3643 +pip/_vendor/html5lib/filters/optionaltags.py,sha256=8lWT75J0aBOHmPgfmqTHSfPpPMp01T84NKu0CRedxcE,10588 +pip/_vendor/html5lib/filters/sanitizer.py,sha256=4ON02KNjuqda1lCw5_JCUZxb0BzWR5M7ON84dtJ7dm0,26248 +pip/_vendor/html5lib/filters/whitespace.py,sha256=8eWqZxd4UC4zlFGW6iyY6f-2uuT8pOCSALc3IZt7_t4,1214 +pip/_vendor/html5lib/html5parser.py,sha256=g5g2ezkusHxhi7b23vK_-d6K6BfIJRbqIQmvQ9z4EgI,118963 +pip/_vendor/html5lib/serializer.py,sha256=yfcfBHse2wDs6ojxn-kieJjLT5s1ipilQJ0gL3-rJis,15758 +pip/_vendor/html5lib/treeadapters/__init__.py,sha256=A0rY5gXIe4bJOiSGRO_j_tFhngRBO8QZPzPtPw5dFzo,679 +pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-37.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-37.pyc,, +pip/_vendor/html5lib/treeadapters/genshi.py,sha256=CH27pAsDKmu4ZGkAUrwty7u0KauGLCZRLPMzaO3M5vo,1715 +pip/_vendor/html5lib/treeadapters/sax.py,sha256=BKS8woQTnKiqeffHsxChUqL4q2ZR_wb5fc9MJ3zQC8s,1776 +pip/_vendor/html5lib/treebuilders/__init__.py,sha256=AysSJyvPfikCMMsTVvaxwkgDieELD5dfR8FJIAuq7hY,3592 +pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/base.py,sha256=wQGp5yy22TNG8tJ6aREe4UUeTR7A99dEz0BXVaedWb4,14579 +pip/_vendor/html5lib/treebuilders/dom.py,sha256=SY3MsijXyzdNPc8aK5IQsupBoM8J67y56DgNtGvsb9g,8835 +pip/_vendor/html5lib/treebuilders/etree.py,sha256=aqIBOGj_dFYqBURIcTegGNBhAIJOw5iFDHb4jrkYH-8,12764 +pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=9V0dXxbJYYq-Skgb5-_OL2NkVYpjioEb4CHajo0e9yI,14122 +pip/_vendor/html5lib/treewalkers/__init__.py,sha256=yhXxHpjlSqfQyUag3v8-vWjMPriFBU8YRAPNpDgBTn8,5714 +pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/base.py,sha256=ouiOsuSzvI0KgzdWP8PlxIaSNs9falhbiinAEc_UIJY,7476 +pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 +pip/_vendor/html5lib/treewalkers/etree.py,sha256=sz1o6mmE93NQ53qJFDO7HKyDtuwgK-Ay3qSFZPC6u00,4550 +pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=sY6wfRshWTllu6n48TPWpKsQRPp-0CQrT0hj_AdzHSU,6309 +pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 +pip/_vendor/idna/__init__.py,sha256=9Nt7xpyet3DmOrPUGooDdAwmHZZu1qUAy2EaJ93kGiQ,58 +pip/_vendor/idna/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/codec.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/core.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/idnadata.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/intranges.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/package_data.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/uts46data.cpython-37.pyc,, +pip/_vendor/idna/codec.py,sha256=lvYb7yu7PhAqFaAIAdWcwgaWI2UmgseUua-1c0AsG0A,3299 +pip/_vendor/idna/compat.py,sha256=R-h29D-6mrnJzbXxymrWUW7iZUvy-26TQwZ0ij57i4U,232 +pip/_vendor/idna/core.py,sha256=OwI5R_uuXU4PlOSoG8cjaMPA1hhdGGjjZ8I2MZhSPxo,11858 +pip/_vendor/idna/idnadata.py,sha256=zwxvoSsYqPHNa6xzXWHizXpDC28JJMGXRinhJ4Gkcz0,39285 +pip/_vendor/idna/intranges.py,sha256=TY1lpxZIQWEP6tNqjZkFA5hgoMWOj1OBmnUG8ihT87E,1749 +pip/_vendor/idna/package_data.py,sha256=Vt9rtr32BzO7O25rypo8nzAs3syTJhG1ojU3J-s2RFo,21 +pip/_vendor/idna/uts46data.py,sha256=czULzYN5Lr9K5MmOH-1g3CJY7QPjGeHjYmC3saJ_BHk,197803 +pip/_vendor/ipaddress.py,sha256=2OgbkeAD2rLkcXqbcvof3J5R7lRwjNLoBySyTkBtKnc,79852 +pip/_vendor/lockfile/__init__.py,sha256=Tqpz90DwKYfhPsfzVOJl84TL87pdFE5ePNHdXAxs4Tk,9371 +pip/_vendor/lockfile/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/linklockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/pidlockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/sqlitelockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/symlinklockfile.cpython-37.pyc,, +pip/_vendor/lockfile/linklockfile.py,sha256=C7OH3H4GdK68u4FQgp8fkP2kO4fyUTSyj3X6blgfobc,2652 +pip/_vendor/lockfile/mkdirlockfile.py,sha256=e3qgIL-etZMLsS-3ft19iW_8IQ360HNkGOqE3yBKsUw,3096 +pip/_vendor/lockfile/pidlockfile.py,sha256=ukH9uk6NFuxyVmG5QiWw4iKq3fT7MjqUguX95avYPIY,6090 +pip/_vendor/lockfile/sqlitelockfile.py,sha256=o2TMkMRY0iwn-iL1XMRRIFStMUkS4i3ajceeYNntKFg,5506 +pip/_vendor/lockfile/symlinklockfile.py,sha256=ABwXXmvTHvCl5viPblShL3PG-gGsLiT1roAMfDRwhi8,2616 +pip/_vendor/msgpack/__init__.py,sha256=y0bk2YbzK6J2e0J_dyreN6nD7yM2IezT6m_tU2h-Mdg,1677 +pip/_vendor/msgpack/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/_version.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/exceptions.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/fallback.cpython-37.pyc,, +pip/_vendor/msgpack/_version.py,sha256=dN7wVIjbyuQIJ35B2o6gymQNDLPlj_7-uTfgCv7KErM,20 +pip/_vendor/msgpack/exceptions.py,sha256=lPkAi_u12NlFajDz4FELSHEdfU8hrR3zeTvKX8aQuz4,1056 +pip/_vendor/msgpack/fallback.py,sha256=h0ll8xnq12mI9PuQ9Qd_Ihtt08Sp8L0JqhG9KY8Vyjk,36411 +pip/_vendor/packaging/__about__.py,sha256=mH-sMIEu48PzdYakZ6Y6OBzL3TlSetzz1fQSkCXiy30,720 +pip/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pip/_vendor/packaging/__pycache__/__about__.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/_compat.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/_structures.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/markers.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/requirements.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/utils.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/version.cpython-37.pyc,, +pip/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pip/_vendor/packaging/_structures.py,sha256=DCpKtb7u94_oqgVsIJQTrTyZcb3Gz7sSGbk9vYDMME0,1418 +pip/_vendor/packaging/markers.py,sha256=ftZegBU5oEmulEKApDGEPgti2lYIchFQHAfH9tZy3_U,8221 +pip/_vendor/packaging/requirements.py,sha256=xIWdoZXVKhUHxqFP5xmnKylM7NHXQS48hUfIIX1PvY0,4439 +pip/_vendor/packaging/specifiers.py,sha256=pFp716eLYBRt0eLNsy6cnWD9dyMKq-Zag7bsLbLv4Fs,28026 +pip/_vendor/packaging/utils.py,sha256=c9obOpok2CpKDApkc2M5ma0YFnT-jtt4I6XI4F0jYiI,1580 +pip/_vendor/packaging/version.py,sha256=MKL8nbKLPLGPouIwFvwSVnYRzNpkMo5AIcsa6LGqDF8,12219 +pip/_vendor/pep517/__init__.py,sha256=GH4HshnLERtjAjkY0zHoz3f7-35UcIvr27iFWSOUazU,82 +pip/_vendor/pep517/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/_in_process.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/check.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/colorlog.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/envbuild.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/wrappers.cpython-37.pyc,, +pip/_vendor/pep517/_in_process.py,sha256=iWpagFk2GhNBbvl-Ca2RagfD0ALuits4WWSM6nQMTdg,5831 +pip/_vendor/pep517/check.py,sha256=Yp2NHW71DIOCgkFb7HKJOzKmsum_s_OokRP6HnR3bTg,5761 +pip/_vendor/pep517/colorlog.py,sha256=2AJuPI_DHM5T9IDgcTwf0E8suyHAFnfsesogr0AB7RQ,4048 +pip/_vendor/pep517/compat.py,sha256=4SFG4QN-cNj8ebSa0wV0HUtEEQWwmbok2a0uk1gYEOM,631 +pip/_vendor/pep517/envbuild.py,sha256=osRsJVd7hir1w_uFXiVeeWxfJ3iYhwxsKRgNBWpqtCI,5672 +pip/_vendor/pep517/wrappers.py,sha256=RhgWm-MLxpYPgc9cZ3-A3ToN99ZzgM8-ia4FDB58koM,5018 +pip/_vendor/pkg_resources/__init__.py,sha256=ykZI7-YBIAQ7ztWf0RskP8Oy1VQU88o-16PJbIMCtLg,103915 +pip/_vendor/pkg_resources/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-37.pyc,, +pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562 +pip/_vendor/progress/__init__.py,sha256=Hv3Y8Hr6RyM34NdZkrZQWMURjS2h5sONRHJSvZXWZgQ,3188 +pip/_vendor/progress/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/bar.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/counter.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/helpers.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/spinner.cpython-37.pyc,, +pip/_vendor/progress/bar.py,sha256=hlkDAEv9pRRiWqR5XL6vIAgMG4u_dBGEW_8klQhBRq0,2942 +pip/_vendor/progress/counter.py,sha256=XtBuZY4yYmr50E2A_fAzjWhm0IkwaVwxNsNVYDE7nsw,1528 +pip/_vendor/progress/helpers.py,sha256=6FsBLh_xUlKiVua-zZIutCjxth-IO8FtyUj6I2tx9fg,2952 +pip/_vendor/progress/spinner.py,sha256=m7bASI2GUbLFG-PbAefdHtrrWWlJLFhhSBbw70gp2TY,1439 +pip/_vendor/pyparsing.py,sha256=My2ZwDJCEaZkZgZyG9gL--48RLGmf9vnVCTW93rhdYI,226342 +pip/_vendor/pytoml/__init__.py,sha256=q12Xv23Tta44gtK4HGK68Gr4tKfciILidFPmPuoIqIo,92 +pip/_vendor/pytoml/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/core.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/parser.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/writer.cpython-37.pyc,, +pip/_vendor/pytoml/core.py,sha256=9CrLLTs1PdWjEwRnYzt_i4dhHcZvGxs_GsMlYAX3iY4,509 +pip/_vendor/pytoml/parser.py,sha256=mcTzHB2GQGyK8KVwuQ0EraSz_78O36U60NqHBtgVmV0,11247 +pip/_vendor/pytoml/writer.py,sha256=-mSOVGaiGLrpj5BRR7czmquZXJGflcElHrwAd33J48A,3815 +pip/_vendor/requests/__init__.py,sha256=OrwNk1JwZGqIQ4JVGgMbfpstqey-oHS_Re_Dw6D4ciI,4209 +pip/_vendor/requests/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/__version__.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/_internal_utils.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/adapters.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/api.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/auth.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/certs.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/cookies.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/exceptions.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/help.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/hooks.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/models.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/packages.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/sessions.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/status_codes.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/structures.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/utils.cpython-37.pyc,, +pip/_vendor/requests/__version__.py,sha256=rJ2xgNOLhjspGkNPfgXTBctqqvsf2uJMFTaE0rlVtbI,436 +pip/_vendor/requests/_internal_utils.py,sha256=Zx3PnEUccyfsB-ie11nZVAW8qClJy0gx1qNME7rgT18,1096 +pip/_vendor/requests/adapters.py,sha256=y5DISepvSsGlu3II_VUsdgKBej1dGY4b5beRrTE2tsI,21428 +pip/_vendor/requests/api.py,sha256=zub9ENcEUT2m9gwgBgqH5RIRDfrx2kwRpZ7L6hX3mcw,6261 +pip/_vendor/requests/auth.py,sha256=oRSQkBYcLkTEssudkzoR1UW1Glb1ts3p1RWusgHf1YU,10208 +pip/_vendor/requests/certs.py,sha256=nXRVq9DtGmv_1AYbwjTu9UrgAcdJv05ZvkNeaoLOZxY,465 +pip/_vendor/requests/compat.py,sha256=7EC6fZY4dJDxuBQnqUGwe13OTZ3VLGO3QfOApE5lE3I,1998 +pip/_vendor/requests/cookies.py,sha256=olUaLeNci_z1K-Bn5PeEKllSspmQqN9-s8Ug7CasaPE,18346 +pip/_vendor/requests/exceptions.py,sha256=-mLam3TAx80V09EaH3H-ZxR61eAVuLRZ8zgBBSLjK44,3197 +pip/_vendor/requests/help.py,sha256=T4K-Oo_FS9fxF8NHVR8hxMwFo71gIkRM7UddCc9vH7Y,3669 +pip/_vendor/requests/hooks.py,sha256=HXAHoC1FNTFRZX6-lNdvPM7Tst4kvGwYTN-AOKRxoRU,767 +pip/_vendor/requests/models.py,sha256=3fmmYdDW7U18SrVeZaseHuk8KPI-7vLp_435DY3ejes,34160 +pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 +pip/_vendor/requests/sessions.py,sha256=71MK2HCadovka1vAx9dyDFWAuw69KgRPRBpd0HWSEAo,27829 +pip/_vendor/requests/status_codes.py,sha256=pgw-xlnxO5zHQWn3fKps2cxwQehKzPxEbdhIrMQe6Ec,4128 +pip/_vendor/requests/structures.py,sha256=zoP8qly2Jak5e89HwpqjN1z2diztI-_gaqts1raJJBc,2981 +pip/_vendor/requests/utils.py,sha256=3OxbbLUQFVdm84fdBD9nduXvhw6hIzj59mhvBomKuJI,30156 +pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 +pip/_vendor/six.py,sha256=A08MPb-Gi9FfInI3IW7HimXFmEH2T2IPzHgDvdhZPRA,30888 +pip/_vendor/urllib3/__init__.py,sha256=DZucS8tlzGYKmK5FIsyUViMghpCq_0_0Ouvm_Jp9GNc,2853 +pip/_vendor/urllib3/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/_collections.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/connection.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/connectionpool.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/exceptions.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/fields.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/filepost.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/poolmanager.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/request.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/response.cpython-37.pyc,, +pip/_vendor/urllib3/_collections.py,sha256=iNeAU_we9L3lMGRUKKdq24Mf7o050TXP5U4Jm9AzAY4,10841 +pip/_vendor/urllib3/connection.py,sha256=My76qeWMDkV-KP1l3iChXHOE7J-ZCaUdP3sPIiLA2uE,14485 +pip/_vendor/urllib3/connectionpool.py,sha256=w20OwKdIqk6f8FIl6QGgn6jf9gZ0-tmgH7VPxnpEgkQ,35464 +pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=x2kLSh-ASZKsun0FxtraBuLVe3oHuth4YW6yZ5Vof-w,17560 +pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=Umy5u-3Z957GirdapnicXVOpHaM4xdOZABJuJxfaeJA,12162 +pip/_vendor/urllib3/contrib/appengine.py,sha256=Q3BDy5C_TrI-3cSyo0ELNGlNiK2eSVptQAQMdz4PH9Q,11197 +pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=Q9-rO5Rh2-IqyEd4ZicpTDfMnOlf0IPPCkjhChBCjV4,4478 +pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=cM7fVZJRrdLZsprcdWe3meM_hvq8LR73UNDveIMa-20,15480 +pip/_vendor/urllib3/contrib/securetransport.py,sha256=BqXSlChN9_hjCWgyN6JdcgvBUdc37QCCX4u3_8zE_9o,30309 +pip/_vendor/urllib3/contrib/socks.py,sha256=Iom0snbHkCuZbZ7Sle2Kueha1W0jYAJ0SyCOtePLaio,6391 +pip/_vendor/urllib3/exceptions.py,sha256=rFeIfBNKC8KJ61ux-MtJyJlEC9G9ggkmCeF751JwVR4,6604 +pip/_vendor/urllib3/fields.py,sha256=D_TE_SK15YatdbhWDMN0OE3X6UCJn1RTkANINCYOobE,5943 +pip/_vendor/urllib3/filepost.py,sha256=40CROlpRKVBpFUkD0R6wJf_PpvbcRQRFUu0OOQlFkKM,2436 +pip/_vendor/urllib3/packages/__init__.py,sha256=nlChrGzkjCkmhCX9HrF_qHPUgosfsPQkVIJxiiLhk9g,109 +pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/packages/__pycache__/ordered_dict.cpython-37.pyc,, +pip/_vendor/urllib3/packages/__pycache__/six.cpython-37.pyc,, +pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-37.pyc,, +pip/_vendor/urllib3/packages/backports/makefile.py,sha256=r1IADol_pBBq2Y1ub4CPyuS2hXuShK47nfFngZRcRhI,1461 +pip/_vendor/urllib3/packages/ordered_dict.py,sha256=VQaPONfhVMsb8B63Xg7ZOydJqIE_jzeMhVN3Pec6ogw,8935 +pip/_vendor/urllib3/packages/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py,sha256=WBVbxQBojNAxfZwNavkox3BgJiMA9BJmm-_fwd0jD_o,688 +pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-37.pyc,, +pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=XCW0ydHg171GfOqNbvUAnRzQ0lc0twp5-dIlolgf4RM,5719 +pip/_vendor/urllib3/poolmanager.py,sha256=FHBjb7odbP2LyQRzeitgpuh1AQAPyegzmrm2b3gSZlY,16821 +pip/_vendor/urllib3/request.py,sha256=fwjlq5nQfcUa7aoncR25z6-fJAX_oNTcPksKKGjBm38,5996 +pip/_vendor/urllib3/response.py,sha256=uAuOTZSuTodzvQWIDCZghDoKmZ2bKbgIRCfaVIIZfn8,24667 +pip/_vendor/urllib3/util/__init__.py,sha256=6Ran4oAVIy40Cu_oEPWnNV9bwF5rXx6G1DUZ7oehjPY,1044 +pip/_vendor/urllib3/util/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/connection.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/queue.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/request.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/response.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/retry.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/timeout.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/url.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/wait.cpython-37.pyc,, +pip/_vendor/urllib3/util/connection.py,sha256=8K1VXm8BHsM3QATJJGBNRa_MStkzDy1Da2IaPAaCU8c,4279 +pip/_vendor/urllib3/util/queue.py,sha256=myTX3JDHntglKQNBf3b6dasHH-uF-W59vzGSQiFdAfI,497 +pip/_vendor/urllib3/util/request.py,sha256=H5_lrHvtwl2U2BbT1UYN9HpruNc1gsNFlz2njQmhPrQ,3705 +pip/_vendor/urllib3/util/response.py,sha256=SSNL888W-MQ8t3HAi44kNGgF682p6H__ytEXzBYxV_M,2343 +pip/_vendor/urllib3/util/retry.py,sha256=tlxiEq8OU2BSenPpPjYYO1URne8A-qTEgaykam6rZPg,15104 +pip/_vendor/urllib3/util/ssl_.py,sha256=iHJopgSv8_vXfmGg3lOsTS3ldMD9zhe130huHZxQEGU,14022 +pip/_vendor/urllib3/util/timeout.py,sha256=7lHNrgL5YH2cI1j-yZnzV_J8jBlRVdmFhQaNyM1_2b8,9757 +pip/_vendor/urllib3/util/url.py,sha256=qCY_HHUXvo05wAsEERALgExtlgxLnAHSQ7ce1b-g3SM,6487 +pip/_vendor/urllib3/util/wait.py,sha256=_4vvsT1BTTpqxQYK-2kXVfGsUsVRiuc4R4F-0Bf5BPc,5468 +pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579 +pip/_vendor/webencodings/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/labels.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/mklabels.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/tests.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-37.pyc,, +pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 +pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 +pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563 +pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307 diff --git a/winvenv/Lib/site-packages/pip-18.1.dist-info/WHEEL b/winvenv/Lib/site-packages/pip-18.1.dist-info/WHEEL new file mode 100644 index 0000000..1001235 --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/winvenv/Lib/site-packages/pip-18.1.dist-info/entry_points.txt b/winvenv/Lib/site-packages/pip-18.1.dist-info/entry_points.txt new file mode 100644 index 0000000..f5809cb --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +pip = pip._internal:main +pip3 = pip._internal:main +pip3.7 = pip._internal:main + diff --git a/winvenv/Lib/site-packages/pip-18.1.dist-info/top_level.txt b/winvenv/Lib/site-packages/pip-18.1.dist-info/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/winvenv/Lib/site-packages/pip-18.1.dist-info/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/winvenv/Lib/site-packages/pip/__init__.py b/winvenv/Lib/site-packages/pip/__init__.py new file mode 100644 index 0000000..ae265fa --- /dev/null +++ b/winvenv/Lib/site-packages/pip/__init__.py @@ -0,0 +1 @@ +__version__ = "18.1" diff --git a/winvenv/Lib/site-packages/pip/__main__.py b/winvenv/Lib/site-packages/pip/__main__.py new file mode 100644 index 0000000..0c223f8 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/__main__.py @@ -0,0 +1,19 @@ +from __future__ import absolute_import + +import os +import sys + +# If we are running from a wheel, add the wheel to sys.path +# This allows the usage python pip-*.whl/pip install pip-*.whl +if __package__ == '': + # __file__ is pip-*.whl/pip/__main__.py + # first dirname call strips of '/__main__.py', second strips off '/pip' + # Resulting path is the name of the wheel itself + # Add that to sys.path so we can import pip + path = os.path.dirname(os.path.dirname(__file__)) + sys.path.insert(0, path) + +from pip._internal import main as _main # isort:skip # noqa + +if __name__ == '__main__': + sys.exit(_main()) diff --git a/winvenv/Lib/site-packages/pip/_internal/__init__.py b/winvenv/Lib/site-packages/pip/_internal/__init__.py new file mode 100644 index 0000000..276124d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/__init__.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +from __future__ import absolute_import + +import locale +import logging +import os +import warnings + +import sys + +# 2016-06-17 barry@debian.org: urllib3 1.14 added optional support for socks, +# but if invoked (i.e. imported), it will issue a warning to stderr if socks +# isn't available. requests unconditionally imports urllib3's socks contrib +# module, triggering this warning. The warning breaks DEP-8 tests (because of +# the stderr output) and is just plain annoying in normal usage. I don't want +# to add socks as yet another dependency for pip, nor do I want to allow-stder +# in the DEP-8 tests, so just suppress the warning. pdb tells me this has to +# be done before the import of pip.vcs. +from pip._vendor.urllib3.exceptions import DependencyWarning +warnings.filterwarnings("ignore", category=DependencyWarning) # noqa + +# We want to inject the use of SecureTransport as early as possible so that any +# references or sessions or what have you are ensured to have it, however we +# only want to do this in the case that we're running on macOS and the linked +# OpenSSL is too old to handle TLSv1.2 +try: + import ssl +except ImportError: + pass +else: + # Checks for OpenSSL 1.0.1 on MacOS + if sys.platform == "darwin" and ssl.OPENSSL_VERSION_NUMBER < 0x1000100f: + try: + from pip._vendor.urllib3.contrib import securetransport + except (ImportError, OSError): + pass + else: + securetransport.inject_into_urllib3() + +from pip._internal.cli.autocompletion import autocomplete +from pip._internal.cli.main_parser import parse_command +from pip._internal.commands import commands_dict +from pip._internal.exceptions import PipError +from pip._internal.utils import deprecation +from pip._internal.vcs import git, mercurial, subversion, bazaar # noqa +from pip._vendor.urllib3.exceptions import InsecureRequestWarning + +logger = logging.getLogger(__name__) + +# Hide the InsecureRequestWarning from urllib3 +warnings.filterwarnings("ignore", category=InsecureRequestWarning) + + +def main(args=None): + if args is None: + args = sys.argv[1:] + + # Configure our deprecation warnings to be sent through loggers + deprecation.install_warning_logger() + + autocomplete() + + try: + cmd_name, cmd_args = parse_command(args) + except PipError as exc: + sys.stderr.write("ERROR: %s" % exc) + sys.stderr.write(os.linesep) + sys.exit(1) + + # Needed for locale.getpreferredencoding(False) to work + # in pip._internal.utils.encoding.auto_decode + try: + locale.setlocale(locale.LC_ALL, '') + except locale.Error as e: + # setlocale can apparently crash if locale are uninitialized + logger.debug("Ignoring error %s when setting locale", e) + command = commands_dict[cmd_name](isolated=("--isolated" in cmd_args)) + return command.main(cmd_args) diff --git a/winvenv/Lib/site-packages/pip/_internal/build_env.py b/winvenv/Lib/site-packages/pip/_internal/build_env.py new file mode 100644 index 0000000..673409d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/build_env.py @@ -0,0 +1,142 @@ +"""Build Environment used for isolation during sdist building +""" + +import logging +import os +import sys +from distutils.sysconfig import get_python_lib +from sysconfig import get_paths + +from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet + +from pip._internal.utils.misc import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.ui import open_spinner + +logger = logging.getLogger(__name__) + + +class BuildEnvironment(object): + """Creates and manages an isolated environment to install build deps + """ + + def __init__(self): + self._temp_dir = TempDirectory(kind="build-env") + self._temp_dir.create() + + @property + def path(self): + return self._temp_dir.path + + def __enter__(self): + self.save_path = os.environ.get('PATH', None) + self.save_pythonpath = os.environ.get('PYTHONPATH', None) + self.save_nousersite = os.environ.get('PYTHONNOUSERSITE', None) + + install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix' + install_dirs = get_paths(install_scheme, vars={ + 'base': self.path, + 'platbase': self.path, + }) + + scripts = install_dirs['scripts'] + if self.save_path: + os.environ['PATH'] = scripts + os.pathsep + self.save_path + else: + os.environ['PATH'] = scripts + os.pathsep + os.defpath + + # Note: prefer distutils' sysconfig to get the + # library paths so PyPy is correctly supported. + purelib = get_python_lib(plat_specific=0, prefix=self.path) + platlib = get_python_lib(plat_specific=1, prefix=self.path) + if purelib == platlib: + lib_dirs = purelib + else: + lib_dirs = purelib + os.pathsep + platlib + if self.save_pythonpath: + os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ + self.save_pythonpath + else: + os.environ['PYTHONPATH'] = lib_dirs + + os.environ['PYTHONNOUSERSITE'] = '1' + + return self.path + + def __exit__(self, exc_type, exc_val, exc_tb): + def restore_var(varname, old_value): + if old_value is None: + os.environ.pop(varname, None) + else: + os.environ[varname] = old_value + + restore_var('PATH', self.save_path) + restore_var('PYTHONPATH', self.save_pythonpath) + restore_var('PYTHONNOUSERSITE', self.save_nousersite) + + def cleanup(self): + self._temp_dir.cleanup() + + def missing_requirements(self, reqs): + """Return a list of the requirements from reqs that are not present + """ + missing = [] + with self: + ws = WorkingSet(os.environ["PYTHONPATH"].split(os.pathsep)) + for req in reqs: + try: + if ws.find(Requirement.parse(req)) is None: + missing.append(req) + except VersionConflict: + missing.append(req) + return missing + + def install_requirements(self, finder, requirements, message): + args = [ + sys.executable, '-m', 'pip', 'install', '--ignore-installed', + '--no-user', '--prefix', self.path, '--no-warn-script-location', + ] + if logger.getEffectiveLevel() <= logging.DEBUG: + args.append('-v') + for format_control in ('no_binary', 'only_binary'): + formats = getattr(finder.format_control, format_control) + args.extend(('--' + format_control.replace('_', '-'), + ','.join(sorted(formats or {':none:'})))) + if finder.index_urls: + args.extend(['-i', finder.index_urls[0]]) + for extra_index in finder.index_urls[1:]: + args.extend(['--extra-index-url', extra_index]) + else: + args.append('--no-index') + for link in finder.find_links: + args.extend(['--find-links', link]) + for _, host, _ in finder.secure_origins: + args.extend(['--trusted-host', host]) + if finder.allow_all_prereleases: + args.append('--pre') + if finder.process_dependency_links: + args.append('--process-dependency-links') + args.append('--') + args.extend(requirements) + with open_spinner(message) as spinner: + call_subprocess(args, show_stdout=False, spinner=spinner) + + +class NoOpBuildEnvironment(BuildEnvironment): + """A no-op drop-in replacement for BuildEnvironment + """ + + def __init__(self): + pass + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_val, exc_tb): + pass + + def cleanup(self): + pass + + def install_requirements(self, finder, requirements, message): + raise NotImplementedError() diff --git a/winvenv/Lib/site-packages/pip/_internal/cache.py b/winvenv/Lib/site-packages/pip/_internal/cache.py new file mode 100644 index 0000000..33bec97 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cache.py @@ -0,0 +1,202 @@ +"""Cache Management +""" + +import errno +import hashlib +import logging +import os + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.download import path_to_url +from pip._internal.models.link import Link +from pip._internal.utils.compat import expanduser +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel import InvalidWheelFilename, Wheel + +logger = logging.getLogger(__name__) + + +class Cache(object): + """An abstract class - provides cache directories for data from links + + + :param cache_dir: The root of the cache. + :param format_control: An object of FormatControl class to limit + binaries being read from the cache. + :param allowed_formats: which formats of files the cache should store. + ('binary' and 'source' are the only allowed values) + """ + + def __init__(self, cache_dir, format_control, allowed_formats): + super(Cache, self).__init__() + self.cache_dir = expanduser(cache_dir) if cache_dir else None + self.format_control = format_control + self.allowed_formats = allowed_formats + + _valid_formats = {"source", "binary"} + assert self.allowed_formats.union(_valid_formats) == _valid_formats + + def _get_cache_path_parts(self, link): + """Get parts of part that must be os.path.joined with cache_dir + """ + + # We want to generate an url to use as our cache key, we don't want to + # just re-use the URL because it might have other items in the fragment + # and we don't care about those. + key_parts = [link.url_without_fragment] + if link.hash_name is not None and link.hash is not None: + key_parts.append("=".join([link.hash_name, link.hash])) + key_url = "#".join(key_parts) + + # Encode our key url with sha224, we'll use this because it has similar + # security properties to sha256, but with a shorter total output (and + # thus less secure). However the differences don't make a lot of + # difference for our use case here. + hashed = hashlib.sha224(key_url.encode()).hexdigest() + + # We want to nest the directories some to prevent having a ton of top + # level directories where we might run out of sub directories on some + # FS. + parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] + + return parts + + def _get_candidates(self, link, package_name): + can_not_cache = ( + not self.cache_dir or + not package_name or + not link + ) + if can_not_cache: + return [] + + canonical_name = canonicalize_name(package_name) + formats = self.format_control.get_allowed_formats( + canonical_name + ) + if not self.allowed_formats.intersection(formats): + return [] + + root = self.get_path_for_link(link) + try: + return os.listdir(root) + except OSError as err: + if err.errno in {errno.ENOENT, errno.ENOTDIR}: + return [] + raise + + def get_path_for_link(self, link): + """Return a directory to store cached items in for link. + """ + raise NotImplementedError() + + def get(self, link, package_name): + """Returns a link to a cached item if it exists, otherwise returns the + passed link. + """ + raise NotImplementedError() + + def _link_for_candidate(self, link, candidate): + root = self.get_path_for_link(link) + path = os.path.join(root, candidate) + + return Link(path_to_url(path)) + + def cleanup(self): + pass + + +class SimpleWheelCache(Cache): + """A cache of wheels for future installs. + """ + + def __init__(self, cache_dir, format_control): + super(SimpleWheelCache, self).__init__( + cache_dir, format_control, {"binary"} + ) + + def get_path_for_link(self, link): + """Return a directory to store cached wheels for link + + Because there are M wheels for any one sdist, we provide a directory + to cache them in, and then consult that directory when looking up + cache hits. + + We only insert things into the cache if they have plausible version + numbers, so that we don't contaminate the cache with things that were + not unique. E.g. ./package might have dozens of installs done for it + and build a version of 0.0...and if we built and cached a wheel, we'd + end up using the same wheel even if the source has been edited. + + :param link: The link of the sdist for which this will cache wheels. + """ + parts = self._get_cache_path_parts(link) + + # Store wheels within the root cache_dir + return os.path.join(self.cache_dir, "wheels", *parts) + + def get(self, link, package_name): + candidates = [] + + for wheel_name in self._get_candidates(link, package_name): + try: + wheel = Wheel(wheel_name) + except InvalidWheelFilename: + continue + if not wheel.supported(): + # Built for a different python/arch/etc + continue + candidates.append((wheel.support_index_min(), wheel_name)) + + if not candidates: + return link + + return self._link_for_candidate(link, min(candidates)[1]) + + +class EphemWheelCache(SimpleWheelCache): + """A SimpleWheelCache that creates it's own temporary cache directory + """ + + def __init__(self, format_control): + self._temp_dir = TempDirectory(kind="ephem-wheel-cache") + self._temp_dir.create() + + super(EphemWheelCache, self).__init__( + self._temp_dir.path, format_control + ) + + def cleanup(self): + self._temp_dir.cleanup() + + +class WheelCache(Cache): + """Wraps EphemWheelCache and SimpleWheelCache into a single Cache + + This Cache allows for gracefully degradation, using the ephem wheel cache + when a certain link is not found in the simple wheel cache first. + """ + + def __init__(self, cache_dir, format_control): + super(WheelCache, self).__init__( + cache_dir, format_control, {'binary'} + ) + self._wheel_cache = SimpleWheelCache(cache_dir, format_control) + self._ephem_cache = EphemWheelCache(format_control) + + def get_path_for_link(self, link): + return self._wheel_cache.get_path_for_link(link) + + def get_ephem_path_for_link(self, link): + return self._ephem_cache.get_path_for_link(link) + + def get(self, link, package_name): + retval = self._wheel_cache.get(link, package_name) + if retval is link: + retval = self._ephem_cache.get(link, package_name) + return retval + + def cleanup(self): + self._wheel_cache.cleanup() + self._ephem_cache.cleanup() diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/__init__.py b/winvenv/Lib/site-packages/pip/_internal/cli/__init__.py new file mode 100644 index 0000000..e589bb9 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/__init__.py @@ -0,0 +1,4 @@ +"""Subpackage containing all of pip's command line interface related code +""" + +# This file intentionally does not import submodules diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/autocompletion.py b/winvenv/Lib/site-packages/pip/_internal/cli/autocompletion.py new file mode 100644 index 0000000..0a04199 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/autocompletion.py @@ -0,0 +1,152 @@ +"""Logic that powers autocompletion installed by ``pip completion``. +""" + +import optparse +import os +import sys + +from pip._internal.cli.main_parser import create_main_parser +from pip._internal.commands import commands_dict, get_summaries +from pip._internal.utils.misc import get_installed_distributions + + +def autocomplete(): + """Entry Point for completion of main and subcommand options. + """ + # Don't complete if user hasn't sourced bash_completion file. + if 'PIP_AUTO_COMPLETE' not in os.environ: + return + cwords = os.environ['COMP_WORDS'].split()[1:] + cword = int(os.environ['COMP_CWORD']) + try: + current = cwords[cword - 1] + except IndexError: + current = '' + + subcommands = [cmd for cmd, summary in get_summaries()] + options = [] + # subcommand + try: + subcommand_name = [w for w in cwords if w in subcommands][0] + except IndexError: + subcommand_name = None + + parser = create_main_parser() + # subcommand options + if subcommand_name: + # special case: 'help' subcommand has no options + if subcommand_name == 'help': + sys.exit(1) + # special case: list locally installed dists for show and uninstall + should_list_installed = ( + subcommand_name in ['show', 'uninstall'] and + not current.startswith('-') + ) + if should_list_installed: + installed = [] + lc = current.lower() + for dist in get_installed_distributions(local_only=True): + if dist.key.startswith(lc) and dist.key not in cwords[1:]: + installed.append(dist.key) + # if there are no dists installed, fall back to option completion + if installed: + for dist in installed: + print(dist) + sys.exit(1) + + subcommand = commands_dict[subcommand_name]() + + for opt in subcommand.parser.option_list_all: + if opt.help != optparse.SUPPRESS_HELP: + for opt_str in opt._long_opts + opt._short_opts: + options.append((opt_str, opt.nargs)) + + # filter out previously specified options from available options + prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] + options = [(x, v) for (x, v) in options if x not in prev_opts] + # filter options by current input + options = [(k, v) for k, v in options if k.startswith(current)] + # get completion type given cwords and available subcommand options + completion_type = get_path_completion_type( + cwords, cword, subcommand.parser.option_list_all, + ) + # get completion files and directories if ``completion_type`` is + # ````, ```` or ```` + if completion_type: + options = auto_complete_paths(current, completion_type) + options = ((opt, 0) for opt in options) + for option in options: + opt_label = option[0] + # append '=' to options which require args + if option[1] and option[0][:2] == "--": + opt_label += '=' + print(opt_label) + else: + # show main parser options only when necessary + + opts = [i.option_list for i in parser.option_groups] + opts.append(parser.option_list) + opts = (o for it in opts for o in it) + if current.startswith('-'): + for opt in opts: + if opt.help != optparse.SUPPRESS_HELP: + subcommands += opt._long_opts + opt._short_opts + else: + # get completion type given cwords and all available options + completion_type = get_path_completion_type(cwords, cword, opts) + if completion_type: + subcommands = auto_complete_paths(current, completion_type) + + print(' '.join([x for x in subcommands if x.startswith(current)])) + sys.exit(1) + + +def get_path_completion_type(cwords, cword, opts): + """Get the type of path completion (``file``, ``dir``, ``path`` or None) + + :param cwords: same as the environmental variable ``COMP_WORDS`` + :param cword: same as the environmental variable ``COMP_CWORD`` + :param opts: The available options to check + :return: path completion type (``file``, ``dir``, ``path`` or None) + """ + if cword < 2 or not cwords[cword - 2].startswith('-'): + return + for opt in opts: + if opt.help == optparse.SUPPRESS_HELP: + continue + for o in str(opt).split('/'): + if cwords[cword - 2].split('=')[0] == o: + if not opt.metavar or any( + x in ('path', 'file', 'dir') + for x in opt.metavar.split('/')): + return opt.metavar + + +def auto_complete_paths(current, completion_type): + """If ``completion_type`` is ``file`` or ``path``, list all regular files + and directories starting with ``current``; otherwise only list directories + starting with ``current``. + + :param current: The word to be completed + :param completion_type: path completion type(`file`, `path` or `dir`)i + :return: A generator of regular files and/or directories + """ + directory, filename = os.path.split(current) + current_path = os.path.abspath(directory) + # Don't complete paths if they can't be accessed + if not os.access(current_path, os.R_OK): + return + filename = os.path.normcase(filename) + # list all files that start with ``filename`` + file_list = (x for x in os.listdir(current_path) + if os.path.normcase(x).startswith(filename)) + for f in file_list: + opt = os.path.join(current_path, f) + comp_file = os.path.normcase(os.path.join(directory, f)) + # complete regular files when there is not ```` after option + # complete directories when there is ````, ```` or + # ````after option + if completion_type != 'dir' and os.path.isfile(opt): + yield comp_file + elif os.path.isdir(opt): + yield os.path.join(comp_file, '') diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/base_command.py b/winvenv/Lib/site-packages/pip/_internal/cli/base_command.py new file mode 100644 index 0000000..dac4b05 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/base_command.py @@ -0,0 +1,278 @@ +"""Base Command class, and related routines""" +from __future__ import absolute_import + +import logging +import logging.config +import optparse +import os +import sys + +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ( + ConfigOptionParser, UpdatingDefaultsHelpFormatter, +) +from pip._internal.cli.status_codes import ( + ERROR, PREVIOUS_BUILD_DIR_ERROR, SUCCESS, UNKNOWN_ERROR, + VIRTUALENV_NOT_FOUND, +) +from pip._internal.download import PipSession +from pip._internal.exceptions import ( + BadCommand, CommandError, InstallationError, PreviousBuildDirError, + UninstallationError, +) +from pip._internal.index import PackageFinder +from pip._internal.locations import running_under_virtualenv +from pip._internal.req.constructors import ( + install_req_from_editable, install_req_from_line, +) +from pip._internal.req.req_file import parse_requirements +from pip._internal.utils.logging import setup_logging +from pip._internal.utils.misc import get_prog, normalize_path +from pip._internal.utils.outdated import pip_version_check +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Optional # noqa: F401 + +__all__ = ['Command'] + +logger = logging.getLogger(__name__) + + +class Command(object): + name = None # type: Optional[str] + usage = None # type: Optional[str] + hidden = False # type: bool + ignore_require_venv = False # type: bool + + def __init__(self, isolated=False): + parser_kw = { + 'usage': self.usage, + 'prog': '%s %s' % (get_prog(), self.name), + 'formatter': UpdatingDefaultsHelpFormatter(), + 'add_help_option': False, + 'name': self.name, + 'description': self.__doc__, + 'isolated': isolated, + } + + self.parser = ConfigOptionParser(**parser_kw) + + # Commands should add options to this option group + optgroup_name = '%s Options' % self.name.capitalize() + self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) + + # Add the general options + gen_opts = cmdoptions.make_option_group( + cmdoptions.general_group, + self.parser, + ) + self.parser.add_option_group(gen_opts) + + def _build_session(self, options, retries=None, timeout=None): + session = PipSession( + cache=( + normalize_path(os.path.join(options.cache_dir, "http")) + if options.cache_dir else None + ), + retries=retries if retries is not None else options.retries, + insecure_hosts=options.trusted_hosts, + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = ( + timeout if timeout is not None else options.timeout + ) + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + + return session + + def parse_args(self, args): + # factored out for testability + return self.parser.parse_args(args) + + def main(self, args): + options, args = self.parse_args(args) + + # Set verbosity so that it can be used elsewhere. + self.verbosity = options.verbose - options.quiet + + setup_logging( + verbosity=self.verbosity, + no_color=options.no_color, + user_log_file=options.log, + ) + + # TODO: Try to get these passing down from the command? + # without resorting to os.environ to hold these. + # This also affects isolated builds and it should. + + if options.no_input: + os.environ['PIP_NO_INPUT'] = '1' + + if options.exists_action: + os.environ['PIP_EXISTS_ACTION'] = ' '.join(options.exists_action) + + if options.require_venv and not self.ignore_require_venv: + # If a venv is required check if it can really be found + if not running_under_virtualenv(): + logger.critical( + 'Could not find an activated virtualenv (required).' + ) + sys.exit(VIRTUALENV_NOT_FOUND) + + try: + status = self.run(options, args) + # FIXME: all commands should return an exit status + # and when it is done, isinstance is not needed anymore + if isinstance(status, int): + return status + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug('Exception information:', exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except (InstallationError, UninstallationError, BadCommand) as exc: + logger.critical(str(exc)) + logger.debug('Exception information:', exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical('ERROR: %s', exc) + logger.debug('Exception information:', exc_info=True) + + return ERROR + except KeyboardInterrupt: + logger.critical('Operation cancelled by user') + logger.debug('Exception information:', exc_info=True) + + return ERROR + except BaseException: + logger.critical('Exception:', exc_info=True) + + return UNKNOWN_ERROR + finally: + allow_version_check = ( + # Does this command have the index_group options? + hasattr(options, "no_index") and + # Is this command allowed to perform this check? + not (options.disable_pip_version_check or options.no_index) + ) + # Check if we're using the latest version of pip available + if allow_version_check: + session = self._build_session( + options, + retries=0, + timeout=min(5, options.timeout) + ) + with session: + pip_version_check(session, options) + + # Shutdown the logging module + logging.shutdown() + + return SUCCESS + + +class RequirementCommand(Command): + + @staticmethod + def populate_requirement_set(requirement_set, args, options, finder, + session, name, wheel_cache): + """ + Marshal cmd line args into a requirement set. + """ + # NOTE: As a side-effect, options.require_hashes and + # requirement_set.require_hashes may be updated + + for filename in options.constraints: + for req_to_add in parse_requirements( + filename, + constraint=True, finder=finder, options=options, + session=session, wheel_cache=wheel_cache): + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for req in args: + req_to_add = install_req_from_line( + req, None, isolated=options.isolated_mode, + wheel_cache=wheel_cache + ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for req in options.editables: + req_to_add = install_req_from_editable( + req, + isolated=options.isolated_mode, + wheel_cache=wheel_cache + ) + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + + for filename in options.requirements: + for req_to_add in parse_requirements( + filename, + finder=finder, options=options, session=session, + wheel_cache=wheel_cache): + req_to_add.is_direct = True + requirement_set.add_requirement(req_to_add) + # If --require-hashes was a line in a requirements file, tell + # RequirementSet about it: + requirement_set.require_hashes = options.require_hashes + + if not (args or options.editables or options.requirements): + opts = {'name': name} + if options.find_links: + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(maybe you meant "pip %(name)s %(links)s"?)' % + dict(opts, links=' '.join(options.find_links))) + else: + raise CommandError( + 'You must give at least one requirement to %(name)s ' + '(see "pip help %(name)s")' % opts) + + def _build_package_finder(self, options, session, + platform=None, python_versions=None, + abi=None, implementation=None): + """ + Create a package finder appropriate to this requirement command. + """ + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index: + logger.debug('Ignoring indexes: %s', ','.join(index_urls)) + index_urls = [] + + return PackageFinder( + find_links=options.find_links, + format_control=options.format_control, + index_urls=index_urls, + trusted_hosts=options.trusted_hosts, + allow_all_prereleases=options.pre, + process_dependency_links=options.process_dependency_links, + session=session, + platform=platform, + versions=python_versions, + abi=abi, + implementation=implementation, + prefer_binary=options.prefer_binary, + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/cmdoptions.py b/winvenv/Lib/site-packages/pip/_internal/cli/cmdoptions.py new file mode 100644 index 0000000..3033cd4 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/cmdoptions.py @@ -0,0 +1,714 @@ +""" +shared options and groups + +The principle here is to define options once, but *not* instantiate them +globally. One reason being that options with action='append' can carry state +between parses. pip parses general options twice internally, and shouldn't +pass on state. To be consistent, all options will follow this design. + +""" +from __future__ import absolute_import + +import warnings +from functools import partial +from optparse import SUPPRESS_HELP, Option, OptionGroup + +from pip._internal.exceptions import CommandError +from pip._internal.locations import USER_CACHE_DIR, src_prefix +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.utils.hashes import STRONG_HASHES +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.ui import BAR_TYPES + +if MYPY_CHECK_RUNNING: + from typing import Any # noqa: F401 + + +def make_option_group(group, parser): + """ + Return an OptionGroup object + group -- assumed to be dict with 'name' and 'options' keys + parser -- an optparse Parser + """ + option_group = OptionGroup(parser, group['name']) + for option in group['options']: + option_group.add_option(option()) + return option_group + + +def check_install_build_global(options, check_options=None): + """Disable wheels if per-setup.py call options are set. + + :param options: The OptionParser options to update. + :param check_options: The options to check, if not supplied defaults to + options. + """ + if check_options is None: + check_options = options + + def getname(n): + return getattr(check_options, n, None) + names = ["build_options", "global_options", "install_options"] + if any(map(getname, names)): + control = options.format_control + control.disallow_binaries() + warnings.warn( + 'Disabling all use of wheels due to the use of --build-options ' + '/ --global-options / --install-options.', stacklevel=2, + ) + + +def check_dist_restriction(options, check_target=False): + """Function for determining if custom platform options are allowed. + + :param options: The OptionParser options. + :param check_target: Whether or not to check if --target is being used. + """ + dist_restriction_set = any([ + options.python_version, + options.platform, + options.abi, + options.implementation, + ]) + + binary_only = FormatControl(set(), {':all:'}) + sdist_dependencies_allowed = ( + options.format_control != binary_only and + not options.ignore_dependencies + ) + + # Installations or downloads using dist restrictions must not combine + # source distributions and dist-specific wheels, as they are not + # gauranteed to be locally compatible. + if dist_restriction_set and sdist_dependencies_allowed: + raise CommandError( + "When restricting platform and interpreter constraints using " + "--python-version, --platform, --abi, or --implementation, " + "either --no-deps must be set, or --only-binary=:all: must be " + "set and --no-binary must not be set (or must be set to " + ":none:)." + ) + + if check_target: + if dist_restriction_set and not options.target_dir: + raise CommandError( + "Can not use any platform or abi specific options unless " + "installing via '--target'" + ) + + +########### +# options # +########### + +help_ = partial( + Option, + '-h', '--help', + dest='help', + action='help', + help='Show help.', +) # type: Any + +isolated_mode = partial( + Option, + "--isolated", + dest="isolated_mode", + action="store_true", + default=False, + help=( + "Run pip in an isolated mode, ignoring environment variables and user " + "configuration." + ), +) + +require_virtualenv = partial( + Option, + # Run only if inside a virtualenv, bail if not. + '--require-virtualenv', '--require-venv', + dest='require_venv', + action='store_true', + default=False, + help=SUPPRESS_HELP +) # type: Any + +verbose = partial( + Option, + '-v', '--verbose', + dest='verbose', + action='count', + default=0, + help='Give more output. Option is additive, and can be used up to 3 times.' +) + +no_color = partial( + Option, + '--no-color', + dest='no_color', + action='store_true', + default=False, + help="Suppress colored output", +) + +version = partial( + Option, + '-V', '--version', + dest='version', + action='store_true', + help='Show version and exit.', +) # type: Any + +quiet = partial( + Option, + '-q', '--quiet', + dest='quiet', + action='count', + default=0, + help=( + 'Give less output. Option is additive, and can be used up to 3' + ' times (corresponding to WARNING, ERROR, and CRITICAL logging' + ' levels).' + ), +) # type: Any + +progress_bar = partial( + Option, + '--progress-bar', + dest='progress_bar', + type='choice', + choices=list(BAR_TYPES.keys()), + default='on', + help=( + 'Specify type of progress to be displayed [' + + '|'.join(BAR_TYPES.keys()) + '] (default: %default)' + ), +) # type: Any + +log = partial( + Option, + "--log", "--log-file", "--local-log", + dest="log", + metavar="path", + help="Path to a verbose appending log." +) # type: Any + +no_input = partial( + Option, + # Don't ask for input + '--no-input', + dest='no_input', + action='store_true', + default=False, + help=SUPPRESS_HELP +) # type: Any + +proxy = partial( + Option, + '--proxy', + dest='proxy', + type='str', + default='', + help="Specify a proxy in the form [user:passwd@]proxy.server:port." +) # type: Any + +retries = partial( + Option, + '--retries', + dest='retries', + type='int', + default=5, + help="Maximum number of retries each connection should attempt " + "(default %default times).", +) # type: Any + +timeout = partial( + Option, + '--timeout', '--default-timeout', + metavar='sec', + dest='timeout', + type='float', + default=15, + help='Set the socket timeout (default %default seconds).', +) # type: Any + +skip_requirements_regex = partial( + Option, + # A regex to be used to skip requirements + '--skip-requirements-regex', + dest='skip_requirements_regex', + type='str', + default='', + help=SUPPRESS_HELP, +) # type: Any + + +def exists_action(): + return Option( + # Option when path already exist + '--exists-action', + dest='exists_action', + type='choice', + choices=['s', 'i', 'w', 'b', 'a'], + default=[], + action='append', + metavar='action', + help="Default action when a path already exists: " + "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort).", + ) + + +cert = partial( + Option, + '--cert', + dest='cert', + type='str', + metavar='path', + help="Path to alternate CA bundle.", +) # type: Any + +client_cert = partial( + Option, + '--client-cert', + dest='client_cert', + type='str', + default=None, + metavar='path', + help="Path to SSL client certificate, a single file containing the " + "private key and the certificate in PEM format.", +) # type: Any + +index_url = partial( + Option, + '-i', '--index-url', '--pypi-url', + dest='index_url', + metavar='URL', + default=PyPI.simple_url, + help="Base URL of Python Package Index (default %default). " + "This should point to a repository compliant with PEP 503 " + "(the simple repository API) or a local directory laid out " + "in the same format.", +) # type: Any + + +def extra_index_url(): + return Option( + '--extra-index-url', + dest='extra_index_urls', + metavar='URL', + action='append', + default=[], + help="Extra URLs of package indexes to use in addition to " + "--index-url. Should follow the same rules as " + "--index-url.", + ) + + +no_index = partial( + Option, + '--no-index', + dest='no_index', + action='store_true', + default=False, + help='Ignore package index (only looking at --find-links URLs instead).', +) # type: Any + + +def find_links(): + return Option( + '-f', '--find-links', + dest='find_links', + action='append', + default=[], + metavar='url', + help="If a url or path to an html file, then parse for links to " + "archives. If a local path or file:// url that's a directory, " + "then look for archives in the directory listing.", + ) + + +def trusted_host(): + return Option( + "--trusted-host", + dest="trusted_hosts", + action="append", + metavar="HOSTNAME", + default=[], + help="Mark this host as trusted, even though it does not have valid " + "or any HTTPS.", + ) + + +# Remove after 1.5 +process_dependency_links = partial( + Option, + "--process-dependency-links", + dest="process_dependency_links", + action="store_true", + default=False, + help="Enable the processing of dependency links.", +) # type: Any + + +def constraints(): + return Option( + '-c', '--constraint', + dest='constraints', + action='append', + default=[], + metavar='file', + help='Constrain versions using the given constraints file. ' + 'This option can be used multiple times.' + ) + + +def requirements(): + return Option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help='Install from the given requirements file. ' + 'This option can be used multiple times.' + ) + + +def editable(): + return Option( + '-e', '--editable', + dest='editables', + action='append', + default=[], + metavar='path/url', + help=('Install a project in editable mode (i.e. setuptools ' + '"develop mode") from a local project path or a VCS url.'), + ) + + +src = partial( + Option, + '--src', '--source', '--source-dir', '--source-directory', + dest='src_dir', + metavar='dir', + default=src_prefix, + help='Directory to check out editable projects into. ' + 'The default in a virtualenv is "/src". ' + 'The default for global installs is "/src".' +) # type: Any + + +def _get_format_control(values, option): + """Get a format_control object.""" + return getattr(values, option.dest) + + +def _handle_no_binary(option, opt_str, value, parser): + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, existing.no_binary, existing.only_binary, + ) + + +def _handle_only_binary(option, opt_str, value, parser): + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, existing.only_binary, existing.no_binary, + ) + + +def no_binary(): + format_control = FormatControl(set(), set()) + return Option( + "--no-binary", dest="format_control", action="callback", + callback=_handle_no_binary, type="str", + default=format_control, + help="Do not use binary packages. Can be supplied multiple times, and " + "each time adds to the existing value. Accepts either :all: to " + "disable all binary packages, :none: to empty the set, or one or " + "more package names with commas between them. Note that some " + "packages are tricky to compile and may fail to install when " + "this option is used on them.", + ) + + +def only_binary(): + format_control = FormatControl(set(), set()) + return Option( + "--only-binary", dest="format_control", action="callback", + callback=_handle_only_binary, type="str", + default=format_control, + help="Do not use source packages. Can be supplied multiple times, and " + "each time adds to the existing value. Accepts either :all: to " + "disable all source packages, :none: to empty the set, or one or " + "more package names with commas between them. Packages without " + "binary distributions will fail to install when this option is " + "used on them.", + ) + + +platform = partial( + Option, + '--platform', + dest='platform', + metavar='platform', + default=None, + help=("Only use wheels compatible with . " + "Defaults to the platform of the running system."), +) + + +python_version = partial( + Option, + '--python-version', + dest='python_version', + metavar='python_version', + default=None, + help=("Only use wheels compatible with Python " + "interpreter version . If not specified, then the " + "current system interpreter minor version is used. A major " + "version (e.g. '2') can be specified to match all " + "minor revs of that major version. A minor version " + "(e.g. '34') can also be specified."), +) + + +implementation = partial( + Option, + '--implementation', + dest='implementation', + metavar='implementation', + default=None, + help=("Only use wheels compatible with Python " + "implementation , e.g. 'pp', 'jy', 'cp', " + " or 'ip'. If not specified, then the current " + "interpreter implementation is used. Use 'py' to force " + "implementation-agnostic wheels."), +) + + +abi = partial( + Option, + '--abi', + dest='abi', + metavar='abi', + default=None, + help=("Only use wheels compatible with Python " + "abi , e.g. 'pypy_41'. If not specified, then the " + "current interpreter abi tag is used. Generally " + "you will need to specify --implementation, " + "--platform, and --python-version when using " + "this option."), +) + + +def prefer_binary(): + return Option( + "--prefer-binary", + dest="prefer_binary", + action="store_true", + default=False, + help="Prefer older binary packages over newer source packages." + ) + + +cache_dir = partial( + Option, + "--cache-dir", + dest="cache_dir", + default=USER_CACHE_DIR, + metavar="dir", + help="Store the cache data in ." +) + +no_cache = partial( + Option, + "--no-cache-dir", + dest="cache_dir", + action="store_false", + help="Disable the cache.", +) + +no_deps = partial( + Option, + '--no-deps', '--no-dependencies', + dest='ignore_dependencies', + action='store_true', + default=False, + help="Don't install package dependencies.", +) # type: Any + +build_dir = partial( + Option, + '-b', '--build', '--build-dir', '--build-directory', + dest='build_dir', + metavar='dir', + help='Directory to unpack packages into and build in. Note that ' + 'an initial build still takes place in a temporary directory. ' + 'The location of temporary directories can be controlled by setting ' + 'the TMPDIR environment variable (TEMP on Windows) appropriately. ' + 'When passed, build directories are not cleaned in case of failures.' +) # type: Any + +ignore_requires_python = partial( + Option, + '--ignore-requires-python', + dest='ignore_requires_python', + action='store_true', + help='Ignore the Requires-Python information.' +) # type: Any + +no_build_isolation = partial( + Option, + '--no-build-isolation', + dest='build_isolation', + action='store_false', + default=True, + help='Disable isolation when building a modern source distribution. ' + 'Build dependencies specified by PEP 518 must be already installed ' + 'if this option is used.' +) # type: Any + +install_options = partial( + Option, + '--install-option', + dest='install_options', + action='append', + metavar='options', + help="Extra arguments to be supplied to the setup.py install " + "command (use like --install-option=\"--install-scripts=/usr/local/" + "bin\"). Use multiple --install-option options to pass multiple " + "options to setup.py install. If you are using an option with a " + "directory path, be sure to use absolute path.", +) # type: Any + +global_options = partial( + Option, + '--global-option', + dest='global_options', + action='append', + metavar='options', + help="Extra global options to be supplied to the setup.py " + "call before the install command.", +) # type: Any + +no_clean = partial( + Option, + '--no-clean', + action='store_true', + default=False, + help="Don't clean up build directories." +) # type: Any + +pre = partial( + Option, + '--pre', + action='store_true', + default=False, + help="Include pre-release and development versions. By default, " + "pip only finds stable versions.", +) # type: Any + +disable_pip_version_check = partial( + Option, + "--disable-pip-version-check", + dest="disable_pip_version_check", + action="store_true", + default=False, + help="Don't periodically check PyPI to determine whether a new version " + "of pip is available for download. Implied with --no-index.", +) # type: Any + + +# Deprecated, Remove later +always_unzip = partial( + Option, + '-Z', '--always-unzip', + dest='always_unzip', + action='store_true', + help=SUPPRESS_HELP, +) # type: Any + + +def _merge_hash(option, opt_str, value, parser): + """Given a value spelled "algo:digest", append the digest to a list + pointed to in a dict by the algo name.""" + if not parser.values.hashes: + parser.values.hashes = {} + try: + algo, digest = value.split(':', 1) + except ValueError: + parser.error('Arguments to %s must be a hash name ' + 'followed by a value, like --hash=sha256:abcde...' % + opt_str) + if algo not in STRONG_HASHES: + parser.error('Allowed hash algorithms for %s are %s.' % + (opt_str, ', '.join(STRONG_HASHES))) + parser.values.hashes.setdefault(algo, []).append(digest) + + +hash = partial( + Option, + '--hash', + # Hash values eventually end up in InstallRequirement.hashes due to + # __dict__ copying in process_line(). + dest='hashes', + action='callback', + callback=_merge_hash, + type='string', + help="Verify that the package's archive matches this " + 'hash before installing. Example: --hash=sha256:abcdef...', +) # type: Any + + +require_hashes = partial( + Option, + '--require-hashes', + dest='require_hashes', + action='store_true', + default=False, + help='Require a hash to check each requirement against, for ' + 'repeatable installs. This option is implied when any package in a ' + 'requirements file has a --hash option.', +) # type: Any + + +########## +# groups # +########## + +general_group = { + 'name': 'General Options', + 'options': [ + help_, + isolated_mode, + require_virtualenv, + verbose, + version, + quiet, + log, + no_input, + proxy, + retries, + timeout, + skip_requirements_regex, + exists_action, + trusted_host, + cert, + client_cert, + cache_dir, + no_cache, + disable_pip_version_check, + no_color, + ] +} + +index_group = { + 'name': 'Package Index Options', + 'options': [ + index_url, + extra_index_url, + no_index, + find_links, + process_dependency_links, + ] +} diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/main_parser.py b/winvenv/Lib/site-packages/pip/_internal/cli/main_parser.py new file mode 100644 index 0000000..1774a6b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/main_parser.py @@ -0,0 +1,96 @@ +"""A single place for constructing and exposing the main parser +""" + +import os +import sys + +from pip import __version__ +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ( + ConfigOptionParser, UpdatingDefaultsHelpFormatter, +) +from pip._internal.commands import ( + commands_dict, get_similar_commands, get_summaries, +) +from pip._internal.exceptions import CommandError +from pip._internal.utils.misc import get_prog + +__all__ = ["create_main_parser", "parse_command"] + + +def create_main_parser(): + """Creates and returns the main parser for pip's CLI + """ + + parser_kw = { + 'usage': '\n%prog [options]', + 'add_help_option': False, + 'formatter': UpdatingDefaultsHelpFormatter(), + 'name': 'global', + 'prog': get_prog(), + } + + parser = ConfigOptionParser(**parser_kw) + parser.disable_interspersed_args() + + pip_pkg_dir = os.path.abspath(os.path.join( + os.path.dirname(__file__), "..", "..", + )) + parser.version = 'pip %s from %s (python %s)' % ( + __version__, pip_pkg_dir, sys.version[:3], + ) + + # add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) + parser.add_option_group(gen_opts) + + parser.main = True # so the help formatter knows + + # create command listing for description + command_summaries = get_summaries() + description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries] + parser.description = '\n'.join(description) + + return parser + + +def parse_command(args): + parser = create_main_parser() + + # Note: parser calls disable_interspersed_args(), so the result of this + # call is to split the initial args into the general options before the + # subcommand and everything else. + # For example: + # args: ['--timeout=5', 'install', '--user', 'INITools'] + # general_options: ['--timeout==5'] + # args_else: ['install', '--user', 'INITools'] + general_options, args_else = parser.parse_args(args) + + # --version + if general_options.version: + sys.stdout.write(parser.version) + sys.stdout.write(os.linesep) + sys.exit() + + # pip || pip help -> print_help() + if not args_else or (args_else[0] == 'help' and len(args_else) == 1): + parser.print_help() + sys.exit() + + # the subcommand name + cmd_name = args_else[0] + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = ['unknown command "%s"' % cmd_name] + if guess: + msg.append('maybe you meant "%s"' % guess) + + raise CommandError(' - '.join(msg)) + + # all the args without the subcommand + cmd_args = args[:] + cmd_args.remove(cmd_name) + + return cmd_name, cmd_args diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/parser.py b/winvenv/Lib/site-packages/pip/_internal/cli/parser.py new file mode 100644 index 0000000..e1eaac4 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/parser.py @@ -0,0 +1,261 @@ +"""Base option parser setup""" +from __future__ import absolute_import + +import logging +import optparse +import sys +import textwrap +from distutils.util import strtobool + +from pip._vendor.six import string_types + +from pip._internal.cli.status_codes import UNKNOWN_ERROR +from pip._internal.configuration import Configuration, ConfigurationError +from pip._internal.utils.compat import get_terminal_size + +logger = logging.getLogger(__name__) + + +class PrettyHelpFormatter(optparse.IndentedHelpFormatter): + """A prettier/less verbose help formatter for optparse.""" + + def __init__(self, *args, **kwargs): + # help position must be aligned with __init__.parseopts.description + kwargs['max_help_position'] = 30 + kwargs['indent_increment'] = 1 + kwargs['width'] = get_terminal_size()[0] - 2 + optparse.IndentedHelpFormatter.__init__(self, *args, **kwargs) + + def format_option_strings(self, option): + return self._format_option_strings(option, ' <%s>', ', ') + + def _format_option_strings(self, option, mvarfmt=' <%s>', optsep=', '): + """ + Return a comma-separated list of option strings and metavars. + + :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') + :param mvarfmt: metavar format string - evaluated as mvarfmt % metavar + :param optsep: separator + """ + opts = [] + + if option._short_opts: + opts.append(option._short_opts[0]) + if option._long_opts: + opts.append(option._long_opts[0]) + if len(opts) > 1: + opts.insert(1, optsep) + + if option.takes_value(): + metavar = option.metavar or option.dest.lower() + opts.append(mvarfmt % metavar.lower()) + + return ''.join(opts) + + def format_heading(self, heading): + if heading == 'Options': + return '' + return heading + ':\n' + + def format_usage(self, usage): + """ + Ensure there is only one newline between usage and the first heading + if there is no description. + """ + msg = '\nUsage: %s\n' % self.indent_lines(textwrap.dedent(usage), " ") + return msg + + def format_description(self, description): + # leave full control over description to us + if description: + if hasattr(self.parser, 'main'): + label = 'Commands' + else: + label = 'Description' + # some doc strings have initial newlines, some don't + description = description.lstrip('\n') + # some doc strings have final newlines and spaces, some don't + description = description.rstrip() + # dedent, then reindent + description = self.indent_lines(textwrap.dedent(description), " ") + description = '%s:\n%s\n' % (label, description) + return description + else: + return '' + + def format_epilog(self, epilog): + # leave full control over epilog to us + if epilog: + return epilog + else: + return '' + + def indent_lines(self, text, indent): + new_lines = [indent + line for line in text.split('\n')] + return "\n".join(new_lines) + + +class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): + """Custom help formatter for use in ConfigOptionParser. + + This is updates the defaults before expanding them, allowing + them to show up correctly in the help listing. + """ + + def expand_default(self, option): + if self.parser is not None: + self.parser._update_defaults(self.parser.defaults) + return optparse.IndentedHelpFormatter.expand_default(self, option) + + +class CustomOptionParser(optparse.OptionParser): + + def insert_option_group(self, idx, *args, **kwargs): + """Insert an OptionGroup at a given position.""" + group = self.add_option_group(*args, **kwargs) + + self.option_groups.pop() + self.option_groups.insert(idx, group) + + return group + + @property + def option_list_all(self): + """Get a list of all options, including those in option groups.""" + res = self.option_list[:] + for i in self.option_groups: + res.extend(i.option_list) + + return res + + +class ConfigOptionParser(CustomOptionParser): + """Custom option parser which updates its defaults by checking the + configuration files and environmental variables""" + + def __init__(self, *args, **kwargs): + self.name = kwargs.pop('name') + + isolated = kwargs.pop("isolated", False) + self.config = Configuration(isolated) + + assert self.name + optparse.OptionParser.__init__(self, *args, **kwargs) + + def check_default(self, option, key, val): + try: + return option.check_value(key, val) + except optparse.OptionValueError as exc: + print("An error occurred during configuration: %s" % exc) + sys.exit(3) + + def _get_ordered_configuration_items(self): + # Configuration gives keys in an unordered manner. Order them. + override_order = ["global", self.name, ":env:"] + + # Pool the options into different groups + section_items = {name: [] for name in override_order} + for section_key, val in self.config.items(): + # ignore empty values + if not val: + logger.debug( + "Ignoring configuration key '%s' as it's value is empty.", + section_key + ) + continue + + section, key = section_key.split(".", 1) + if section in override_order: + section_items[section].append((key, val)) + + # Yield each group in their override order + for section in override_order: + for key, val in section_items[section]: + yield key, val + + def _update_defaults(self, defaults): + """Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists).""" + + # Accumulate complex default state. + self.values = optparse.Values(self.defaults) + late_eval = set() + # Then set the options with those values + for key, val in self._get_ordered_configuration_items(): + # '--' because configuration supports only long names + option = self.get_option('--' + key) + + # Ignore options not present in this parser. E.g. non-globals put + # in [global] by users that want them to apply to all applicable + # commands. + if option is None: + continue + + if option.action in ('store_true', 'store_false', 'count'): + try: + val = strtobool(val) + except ValueError: + error_msg = invalid_config_error_message( + option.action, key, val + ) + self.error(error_msg) + + elif option.action == 'append': + val = val.split() + val = [self.check_default(option, key, v) for v in val] + elif option.action == 'callback': + late_eval.add(option.dest) + opt_str = option.get_opt_string() + val = option.convert_value(opt_str, val) + # From take_action + args = option.callback_args or () + kwargs = option.callback_kwargs or {} + option.callback(option, opt_str, val, self, *args, **kwargs) + else: + val = self.check_default(option, key, val) + + defaults[option.dest] = val + + for key in late_eval: + defaults[key] = getattr(self.values, key) + self.values = None + return defaults + + def get_default_values(self): + """Overriding to make updating the defaults after instantiation of + the option parser possible, _update_defaults() does the dirty work.""" + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + # Load the configuration, or error out in case of an error + try: + self.config.load() + except ConfigurationError as err: + self.exit(UNKNOWN_ERROR, str(err)) + + defaults = self._update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + default = defaults.get(option.dest) + if isinstance(default, string_types): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + def error(self, msg): + self.print_usage(sys.stderr) + self.exit(UNKNOWN_ERROR, "%s\n" % msg) + + +def invalid_config_error_message(action, key, val): + """Returns a better error message when invalid configuration option + is provided.""" + if action in ('store_true', 'store_false'): + return ("{0} is not a valid value for {1} option, " + "please specify a boolean value like yes/no, " + "true/false or 1/0 instead.").format(val, key) + + return ("{0} is not a valid value for {1} option, " + "please specify a numerical value like 1/0 " + "instead.").format(val, key) diff --git a/winvenv/Lib/site-packages/pip/_internal/cli/status_codes.py b/winvenv/Lib/site-packages/pip/_internal/cli/status_codes.py new file mode 100644 index 0000000..275360a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/cli/status_codes.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 +VIRTUALENV_NOT_FOUND = 3 +PREVIOUS_BUILD_DIR_ERROR = 4 +NO_MATCHES_FOUND = 23 diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/__init__.py b/winvenv/Lib/site-packages/pip/_internal/commands/__init__.py new file mode 100644 index 0000000..c7d1da3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/__init__.py @@ -0,0 +1,79 @@ +""" +Package containing all pip commands +""" +from __future__ import absolute_import + +from pip._internal.commands.completion import CompletionCommand +from pip._internal.commands.configuration import ConfigurationCommand +from pip._internal.commands.download import DownloadCommand +from pip._internal.commands.freeze import FreezeCommand +from pip._internal.commands.hash import HashCommand +from pip._internal.commands.help import HelpCommand +from pip._internal.commands.list import ListCommand +from pip._internal.commands.check import CheckCommand +from pip._internal.commands.search import SearchCommand +from pip._internal.commands.show import ShowCommand +from pip._internal.commands.install import InstallCommand +from pip._internal.commands.uninstall import UninstallCommand +from pip._internal.commands.wheel import WheelCommand + +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import List, Type # noqa: F401 + from pip._internal.cli.base_command import Command # noqa: F401 + +commands_order = [ + InstallCommand, + DownloadCommand, + UninstallCommand, + FreezeCommand, + ListCommand, + ShowCommand, + CheckCommand, + ConfigurationCommand, + SearchCommand, + WheelCommand, + HashCommand, + CompletionCommand, + HelpCommand, +] # type: List[Type[Command]] + +commands_dict = {c.name: c for c in commands_order} + + +def get_summaries(ordered=True): + """Yields sorted (command name, command summary) tuples.""" + + if ordered: + cmditems = _sort_commands(commands_dict, commands_order) + else: + cmditems = commands_dict.items() + + for name, command_class in cmditems: + yield (name, command_class.summary) + + +def get_similar_commands(name): + """Command name auto-correct.""" + from difflib import get_close_matches + + name = name.lower() + + close_commands = get_close_matches(name, commands_dict.keys()) + + if close_commands: + return close_commands[0] + else: + return False + + +def _sort_commands(cmddict, order): + def keyfn(key): + try: + return order.index(key[1]) + except ValueError: + # unordered items should come last + return 0xff + + return sorted(cmddict.items(), key=keyfn) diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/check.py b/winvenv/Lib/site-packages/pip/_internal/commands/check.py new file mode 100644 index 0000000..1be3ec2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/check.py @@ -0,0 +1,41 @@ +import logging + +from pip._internal.cli.base_command import Command +from pip._internal.operations.check import ( + check_package_set, create_package_set_from_installed, +) + +logger = logging.getLogger(__name__) + + +class CheckCommand(Command): + """Verify installed packages have compatible dependencies.""" + name = 'check' + usage = """ + %prog [options]""" + summary = 'Verify installed packages have compatible dependencies.' + + def run(self, options, args): + package_set = create_package_set_from_installed() + missing, conflicting = check_package_set(package_set) + + for project_name in missing: + version = package_set[project_name].version + for dependency in missing[project_name]: + logger.info( + "%s %s requires %s, which is not installed.", + project_name, version, dependency[0], + ) + + for project_name in conflicting: + version = package_set[project_name].version + for dep_name, dep_version, req in conflicting[project_name]: + logger.info( + "%s %s has requirement %s, but you have %s %s.", + project_name, version, req, dep_name, dep_version, + ) + + if missing or conflicting: + return 1 + else: + logger.info("No broken requirements found.") diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/completion.py b/winvenv/Lib/site-packages/pip/_internal/commands/completion.py new file mode 100644 index 0000000..2fcdd39 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/completion.py @@ -0,0 +1,94 @@ +from __future__ import absolute_import + +import sys +import textwrap + +from pip._internal.cli.base_command import Command +from pip._internal.utils.misc import get_prog + +BASE_COMPLETION = """ +# pip %(shell)s completion start%(script)s# pip %(shell)s completion end +""" + +COMPLETION_SCRIPTS = { + 'bash': """ + _pip_completion() + { + COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\ + COMP_CWORD=$COMP_CWORD \\ + PIP_AUTO_COMPLETE=1 $1 ) ) + } + complete -o default -F _pip_completion %(prog)s + """, + 'zsh': """ + function _pip_completion { + local words cword + read -Ac words + read -cn cword + reply=( $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$(( cword-1 )) \\ + PIP_AUTO_COMPLETE=1 $words[1] ) ) + } + compctl -K _pip_completion %(prog)s + """, + 'fish': """ + function __fish_complete_pip + set -lx COMP_WORDS (commandline -o) "" + set -lx COMP_CWORD ( \\ + math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ + ) + set -lx PIP_AUTO_COMPLETE 1 + string split \\ -- (eval $COMP_WORDS[1]) + end + complete -fa "(__fish_complete_pip)" -c %(prog)s + """, +} + + +class CompletionCommand(Command): + """A helper command to be used for command completion.""" + name = 'completion' + summary = 'A helper command used for command completion.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(CompletionCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option( + '--bash', '-b', + action='store_const', + const='bash', + dest='shell', + help='Emit completion code for bash') + cmd_opts.add_option( + '--zsh', '-z', + action='store_const', + const='zsh', + dest='shell', + help='Emit completion code for zsh') + cmd_opts.add_option( + '--fish', '-f', + action='store_const', + const='fish', + dest='shell', + help='Emit completion code for fish') + + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + """Prints the completion code of the given shell""" + shells = COMPLETION_SCRIPTS.keys() + shell_options = ['--' + shell for shell in sorted(shells)] + if options.shell in shells: + script = textwrap.dedent( + COMPLETION_SCRIPTS.get(options.shell, '') % { + 'prog': get_prog(), + } + ) + print(BASE_COMPLETION % {'script': script, 'shell': options.shell}) + else: + sys.stderr.write( + 'ERROR: You must pass %s\n' % ' or '.join(shell_options) + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/configuration.py b/winvenv/Lib/site-packages/pip/_internal/commands/configuration.py new file mode 100644 index 0000000..826c08d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/configuration.py @@ -0,0 +1,227 @@ +import logging +import os +import subprocess + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.configuration import Configuration, kinds +from pip._internal.exceptions import PipError +from pip._internal.locations import venv_config_file +from pip._internal.utils.misc import get_prog + +logger = logging.getLogger(__name__) + + +class ConfigurationCommand(Command): + """Manage local and global configuration. + + Subcommands: + + list: List the active configuration (or from the file specified) + edit: Edit the configuration file in an editor + get: Get the value associated with name + set: Set the name=value + unset: Unset the value associated with name + + If none of --user, --global and --venv are passed, a virtual + environment configuration file is used if one is active and the file + exists. Otherwise, all modifications happen on the to the user file by + default. + """ + + name = 'config' + usage = """ + %prog [] list + %prog [] [--editor ] edit + + %prog [] get name + %prog [] set name value + %prog [] unset name + """ + + summary = "Manage local and global configuration." + + def __init__(self, *args, **kwargs): + super(ConfigurationCommand, self).__init__(*args, **kwargs) + + self.configuration = None + + self.cmd_opts.add_option( + '--editor', + dest='editor', + action='store', + default=None, + help=( + 'Editor to use to edit the file. Uses VISUAL or EDITOR ' + 'environment variables if not provided.' + ) + ) + + self.cmd_opts.add_option( + '--global', + dest='global_file', + action='store_true', + default=False, + help='Use the system-wide configuration file only' + ) + + self.cmd_opts.add_option( + '--user', + dest='user_file', + action='store_true', + default=False, + help='Use the user configuration file only' + ) + + self.cmd_opts.add_option( + '--venv', + dest='venv_file', + action='store_true', + default=False, + help='Use the virtualenv configuration file only' + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + handlers = { + "list": self.list_values, + "edit": self.open_in_editor, + "get": self.get_name, + "set": self.set_name_value, + "unset": self.unset_name + } + + # Determine action + if not args or args[0] not in handlers: + logger.error("Need an action ({}) to perform.".format( + ", ".join(sorted(handlers))) + ) + return ERROR + + action = args[0] + + # Determine which configuration files are to be loaded + # Depends on whether the command is modifying. + try: + load_only = self._determine_file( + options, need_value=(action in ["get", "set", "unset", "edit"]) + ) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + # Load a new configuration + self.configuration = Configuration( + isolated=options.isolated_mode, load_only=load_only + ) + self.configuration.load() + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _determine_file(self, options, need_value): + file_options = { + kinds.USER: options.user_file, + kinds.GLOBAL: options.global_file, + kinds.VENV: options.venv_file + } + + if sum(file_options.values()) == 0: + if not need_value: + return None + # Default to user, unless there's a virtualenv file. + elif os.path.exists(venv_config_file): + return kinds.VENV + else: + return kinds.USER + elif sum(file_options.values()) == 1: + # There's probably a better expression for this. + return [key for key in file_options if file_options[key]][0] + + raise PipError( + "Need exactly one file to operate upon " + "(--user, --venv, --global) to perform." + ) + + def list_values(self, options, args): + self._get_n_args(args, "list", n=0) + + for key, value in sorted(self.configuration.items()): + logger.info("%s=%r", key, value) + + def get_name(self, options, args): + key = self._get_n_args(args, "get [name]", n=1) + value = self.configuration.get_value(key) + + logger.info("%s", value) + + def set_name_value(self, options, args): + key, value = self._get_n_args(args, "set [name] [value]", n=2) + self.configuration.set_value(key, value) + + self._save_configuration() + + def unset_name(self, options, args): + key = self._get_n_args(args, "unset [name]", n=1) + self.configuration.unset_value(key) + + self._save_configuration() + + def open_in_editor(self, options, args): + editor = self._determine_editor(options) + + fname = self.configuration.get_file_to_edit() + if fname is None: + raise PipError("Could not determine appropriate file.") + + try: + subprocess.check_call([editor, fname]) + except subprocess.CalledProcessError as e: + raise PipError( + "Editor Subprocess exited with exit code {}" + .format(e.returncode) + ) + + def _get_n_args(self, args, example, n): + """Helper to make sure the command got the right number of arguments + """ + if len(args) != n: + msg = ( + 'Got unexpected number of arguments, expected {}. ' + '(example: "{} config {}")' + ).format(n, get_prog(), example) + raise PipError(msg) + + if n == 1: + return args[0] + else: + return args + + def _save_configuration(self): + # We successfully ran a modifying command. Need to save the + # configuration. + try: + self.configuration.save() + except Exception: + logger.error( + "Unable to save configuration. Please report this as a bug.", + exc_info=1 + ) + raise PipError("Internal Error.") + + def _determine_editor(self, options): + if options.editor is not None: + return options.editor + elif "VISUAL" in os.environ: + return os.environ["VISUAL"] + elif "EDITOR" in os.environ: + return os.environ["EDITOR"] + else: + raise PipError("Could not determine editor to use.") diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/download.py b/winvenv/Lib/site-packages/pip/_internal/commands/download.py new file mode 100644 index 0000000..b3f3c6e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/download.py @@ -0,0 +1,174 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import RequirementCommand +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req import RequirementSet +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolve import Resolver +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.misc import ensure_dir, normalize_path +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +class DownloadCommand(RequirementCommand): + """ + Download packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports downloading from "requirements files", which provide + an easy way to specify a whole environment to be downloaded. + """ + name = 'download' + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] ... + %prog [options] ... + %prog [options] ...""" + + summary = 'Download packages.' + + def __init__(self, *args, **kw): + super(DownloadCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option(cmdoptions.constraints()) + cmd_opts.add_option(cmdoptions.requirements()) + cmd_opts.add_option(cmdoptions.build_dir()) + cmd_opts.add_option(cmdoptions.no_deps()) + cmd_opts.add_option(cmdoptions.global_options()) + cmd_opts.add_option(cmdoptions.no_binary()) + cmd_opts.add_option(cmdoptions.only_binary()) + cmd_opts.add_option(cmdoptions.prefer_binary()) + cmd_opts.add_option(cmdoptions.src()) + cmd_opts.add_option(cmdoptions.pre()) + cmd_opts.add_option(cmdoptions.no_clean()) + cmd_opts.add_option(cmdoptions.require_hashes()) + cmd_opts.add_option(cmdoptions.progress_bar()) + cmd_opts.add_option(cmdoptions.no_build_isolation()) + + cmd_opts.add_option( + '-d', '--dest', '--destination-dir', '--destination-directory', + dest='download_dir', + metavar='dir', + default=os.curdir, + help=("Download packages into ."), + ) + + cmd_opts.add_option(cmdoptions.platform()) + cmd_opts.add_option(cmdoptions.python_version()) + cmd_opts.add_option(cmdoptions.implementation()) + cmd_opts.add_option(cmdoptions.abi()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + options.ignore_installed = True + # editable doesn't really make sense for `pip download`, but the bowels + # of the RequirementSet code require that property. + options.editables = [] + + if options.python_version: + python_versions = [options.python_version] + else: + python_versions = None + + cmdoptions.check_dist_restriction(options) + + options.src_dir = os.path.abspath(options.src_dir) + options.download_dir = normalize_path(options.download_dir) + + ensure_dir(options.download_dir) + + with self._build_session(options) as session: + finder = self._build_package_finder( + options=options, + session=session, + platform=options.platform, + python_versions=python_versions, + abi=options.abi, + implementation=options.implementation, + ) + build_delete = (not (options.no_clean or options.build_dir)) + if options.cache_dir and not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "by the current user and caching wheels has been " + "disabled. check the permissions and owner of that " + "directory. If executing pip with sudo, you may want " + "sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + with RequirementTracker() as req_tracker, TempDirectory( + options.build_dir, delete=build_delete, kind="download" + ) as directory: + + requirement_set = RequirementSet( + require_hashes=options.require_hashes, + ) + self.populate_requirement_set( + requirement_set, + args, + options, + finder, + session, + self.name, + None + ) + + preparer = RequirementPreparer( + build_dir=directory.path, + src_dir=options.src_dir, + download_dir=options.download_dir, + wheel_download_dir=None, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + resolver = Resolver( + preparer=preparer, + finder=finder, + session=session, + wheel_cache=None, + use_user_site=False, + upgrade_strategy="to-satisfy-only", + force_reinstall=False, + ignore_dependencies=options.ignore_dependencies, + ignore_requires_python=False, + ignore_installed=True, + isolated=options.isolated_mode, + ) + resolver.resolve(requirement_set) + + downloaded = ' '.join([ + req.name for req in requirement_set.successfully_downloaded + ]) + if downloaded: + logger.info('Successfully downloaded %s', downloaded) + + # Clean up + if not options.no_clean: + requirement_set.cleanup_files() + + return requirement_set diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/freeze.py b/winvenv/Lib/site-packages/pip/_internal/commands/freeze.py new file mode 100644 index 0000000..dc9c53a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/freeze.py @@ -0,0 +1,96 @@ +from __future__ import absolute_import + +import sys + +from pip._internal.cache import WheelCache +from pip._internal.cli.base_command import Command +from pip._internal.models.format_control import FormatControl +from pip._internal.operations.freeze import freeze +from pip._internal.utils.compat import stdlib_pkgs + +DEV_PKGS = {'pip', 'setuptools', 'distribute', 'wheel'} + + +class FreezeCommand(Command): + """ + Output installed packages in requirements format. + + packages are listed in a case-insensitive sorted order. + """ + name = 'freeze' + usage = """ + %prog [options]""" + summary = 'Output installed packages in requirements format.' + log_streams = ("ext://sys.stderr", "ext://sys.stderr") + + def __init__(self, *args, **kw): + super(FreezeCommand, self).__init__(*args, **kw) + + self.cmd_opts.add_option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help="Use the order in the given requirements file and its " + "comments when generating output. This option can be " + "used multiple times.") + self.cmd_opts.add_option( + '-f', '--find-links', + dest='find_links', + action='append', + default=[], + metavar='URL', + help='URL for finding packages, which will be added to the ' + 'output.') + self.cmd_opts.add_option( + '-l', '--local', + dest='local', + action='store_true', + default=False, + help='If in a virtualenv that has global access, do not output ' + 'globally-installed packages.') + self.cmd_opts.add_option( + '--user', + dest='user', + action='store_true', + default=False, + help='Only output packages installed in user-site.') + self.cmd_opts.add_option( + '--all', + dest='freeze_all', + action='store_true', + help='Do not skip these packages in the output:' + ' %s' % ', '.join(DEV_PKGS)) + self.cmd_opts.add_option( + '--exclude-editable', + dest='exclude_editable', + action='store_true', + help='Exclude editable package from output.') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + format_control = FormatControl(set(), set()) + wheel_cache = WheelCache(options.cache_dir, format_control) + skip = set(stdlib_pkgs) + if not options.freeze_all: + skip.update(DEV_PKGS) + + freeze_kwargs = dict( + requirement=options.requirements, + find_links=options.find_links, + local_only=options.local, + user_only=options.user, + skip_regex=options.skip_requirements_regex, + isolated=options.isolated_mode, + wheel_cache=wheel_cache, + skip=skip, + exclude_editable=options.exclude_editable, + ) + + try: + for line in freeze(**freeze_kwargs): + sys.stdout.write(line + '\n') + finally: + wheel_cache.cleanup() diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/hash.py b/winvenv/Lib/site-packages/pip/_internal/commands/hash.py new file mode 100644 index 0000000..423440e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/hash.py @@ -0,0 +1,57 @@ +from __future__ import absolute_import + +import hashlib +import logging +import sys + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR +from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES +from pip._internal.utils.misc import read_chunks + +logger = logging.getLogger(__name__) + + +class HashCommand(Command): + """ + Compute a hash of a local package archive. + + These can be used with --hash in a requirements file to do repeatable + installs. + + """ + name = 'hash' + usage = '%prog [options] ...' + summary = 'Compute hashes of package archives.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(HashCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-a', '--algorithm', + dest='algorithm', + choices=STRONG_HASHES, + action='store', + default=FAVORITE_HASH, + help='The hash algorithm to use: one of %s' % + ', '.join(STRONG_HASHES)) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + if not args: + self.parser.print_usage(sys.stderr) + return ERROR + + algorithm = options.algorithm + for path in args: + logger.info('%s:\n--hash=%s:%s', + path, algorithm, _hash_of_file(path, algorithm)) + + +def _hash_of_file(path, algorithm): + """Return the hash digest of a file.""" + with open(path, 'rb') as archive: + hash = hashlib.new(algorithm) + for chunk in read_chunks(archive): + hash.update(chunk) + return hash.hexdigest() diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/help.py b/winvenv/Lib/site-packages/pip/_internal/commands/help.py new file mode 100644 index 0000000..49a81cb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/help.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError + + +class HelpCommand(Command): + """Show help for commands""" + name = 'help' + usage = """ + %prog """ + summary = 'Show help for commands.' + ignore_require_venv = True + + def run(self, options, args): + from pip._internal.commands import commands_dict, get_similar_commands + + try: + # 'pip help' with no args is handled by pip.__init__.parseopt() + cmd_name = args[0] # the command we need help for + except IndexError: + return SUCCESS + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = ['unknown command "%s"' % cmd_name] + if guess: + msg.append('maybe you meant "%s"' % guess) + + raise CommandError(' - '.join(msg)) + + command = commands_dict[cmd_name]() + command.parser.print_help() + + return SUCCESS diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/install.py b/winvenv/Lib/site-packages/pip/_internal/commands/install.py new file mode 100644 index 0000000..6fc178f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/install.py @@ -0,0 +1,535 @@ +from __future__ import absolute_import + +import errno +import logging +import operator +import os +import shutil +from optparse import SUPPRESS_HELP + +from pip._vendor import pkg_resources + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import RequirementCommand +from pip._internal.cli.status_codes import ERROR +from pip._internal.exceptions import ( + CommandError, InstallationError, PreviousBuildDirError, +) +from pip._internal.locations import distutils_scheme, virtualenv_no_global +from pip._internal.operations.check import check_install_conflicts +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req import RequirementSet, install_given_reqs +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolve import Resolver +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.misc import ( + ensure_dir, get_installed_version, + protect_pip_from_modification_on_windows, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel import WheelBuilder + +try: + import wheel +except ImportError: + wheel = None + + +logger = logging.getLogger(__name__) + + +class InstallCommand(RequirementCommand): + """ + Install packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports installing from "requirements files", which provide + an easy way to specify a whole environment to be installed. + """ + name = 'install' + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + summary = 'Install packages.' + + def __init__(self, *args, **kw): + super(InstallCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option(cmdoptions.requirements()) + cmd_opts.add_option(cmdoptions.constraints()) + cmd_opts.add_option(cmdoptions.no_deps()) + cmd_opts.add_option(cmdoptions.pre()) + + cmd_opts.add_option(cmdoptions.editable()) + cmd_opts.add_option( + '-t', '--target', + dest='target_dir', + metavar='dir', + default=None, + help='Install packages into . ' + 'By default this will not replace existing files/folders in ' + '. Use --upgrade to replace existing packages in ' + 'with new versions.' + ) + cmd_opts.add_option(cmdoptions.platform()) + cmd_opts.add_option(cmdoptions.python_version()) + cmd_opts.add_option(cmdoptions.implementation()) + cmd_opts.add_option(cmdoptions.abi()) + + cmd_opts.add_option( + '--user', + dest='use_user_site', + action='store_true', + help="Install to the Python user install directory for your " + "platform. Typically ~/.local/, or %APPDATA%\\Python on " + "Windows. (See the Python documentation for site.USER_BASE " + "for full details.)") + cmd_opts.add_option( + '--no-user', + dest='use_user_site', + action='store_false', + help=SUPPRESS_HELP) + cmd_opts.add_option( + '--root', + dest='root_path', + metavar='dir', + default=None, + help="Install everything relative to this alternate root " + "directory.") + cmd_opts.add_option( + '--prefix', + dest='prefix_path', + metavar='dir', + default=None, + help="Installation prefix where lib, bin and other top-level " + "folders are placed") + + cmd_opts.add_option(cmdoptions.build_dir()) + + cmd_opts.add_option(cmdoptions.src()) + + cmd_opts.add_option( + '-U', '--upgrade', + dest='upgrade', + action='store_true', + help='Upgrade all specified packages to the newest available ' + 'version. The handling of dependencies depends on the ' + 'upgrade-strategy used.' + ) + + cmd_opts.add_option( + '--upgrade-strategy', + dest='upgrade_strategy', + default='only-if-needed', + choices=['only-if-needed', 'eager'], + help='Determines how dependency upgrading should be handled ' + '[default: %default]. ' + '"eager" - dependencies are upgraded regardless of ' + 'whether the currently installed version satisfies the ' + 'requirements of the upgraded package(s). ' + '"only-if-needed" - are upgraded only when they do not ' + 'satisfy the requirements of the upgraded package(s).' + ) + + cmd_opts.add_option( + '--force-reinstall', + dest='force_reinstall', + action='store_true', + help='Reinstall all packages even if they are already ' + 'up-to-date.') + + cmd_opts.add_option( + '-I', '--ignore-installed', + dest='ignore_installed', + action='store_true', + help='Ignore the installed packages (reinstalling instead).') + + cmd_opts.add_option(cmdoptions.ignore_requires_python()) + cmd_opts.add_option(cmdoptions.no_build_isolation()) + + cmd_opts.add_option(cmdoptions.install_options()) + cmd_opts.add_option(cmdoptions.global_options()) + + cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile Python source files to bytecode", + ) + + cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile Python source files to bytecode", + ) + + cmd_opts.add_option( + "--no-warn-script-location", + action="store_false", + dest="warn_script_location", + default=True, + help="Do not warn when installing scripts outside PATH", + ) + cmd_opts.add_option( + "--no-warn-conflicts", + action="store_false", + dest="warn_about_conflicts", + default=True, + help="Do not warn about broken dependencies", + ) + + cmd_opts.add_option(cmdoptions.no_binary()) + cmd_opts.add_option(cmdoptions.only_binary()) + cmd_opts.add_option(cmdoptions.prefer_binary()) + cmd_opts.add_option(cmdoptions.no_clean()) + cmd_opts.add_option(cmdoptions.require_hashes()) + cmd_opts.add_option(cmdoptions.progress_bar()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + cmdoptions.check_install_build_global(options) + upgrade_strategy = "to-satisfy-only" + if options.upgrade: + upgrade_strategy = options.upgrade_strategy + + if options.build_dir: + options.build_dir = os.path.abspath(options.build_dir) + + cmdoptions.check_dist_restriction(options, check_target=True) + + if options.python_version: + python_versions = [options.python_version] + else: + python_versions = None + + options.src_dir = os.path.abspath(options.src_dir) + install_options = options.install_options or [] + if options.use_user_site: + if options.prefix_path: + raise CommandError( + "Can not combine '--user' and '--prefix' as they imply " + "different installation locations" + ) + if virtualenv_no_global(): + raise InstallationError( + "Can not perform a '--user' install. User site-packages " + "are not visible in this virtualenv." + ) + install_options.append('--user') + install_options.append('--prefix=') + + target_temp_dir = TempDirectory(kind="target") + if options.target_dir: + options.ignore_installed = True + options.target_dir = os.path.abspath(options.target_dir) + if (os.path.exists(options.target_dir) and not + os.path.isdir(options.target_dir)): + raise CommandError( + "Target path exists but is not a directory, will not " + "continue." + ) + + # Create a target directory for using with the target option + target_temp_dir.create() + install_options.append('--home=' + target_temp_dir.path) + + global_options = options.global_options or [] + + with self._build_session(options) as session: + finder = self._build_package_finder( + options=options, + session=session, + platform=options.platform, + python_versions=python_versions, + abi=options.abi, + implementation=options.implementation, + ) + build_delete = (not (options.no_clean or options.build_dir)) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + if options.cache_dir and not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "by the current user and caching wheels has been " + "disabled. check the permissions and owner of that " + "directory. If executing pip with sudo, you may want " + "sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + with RequirementTracker() as req_tracker, TempDirectory( + options.build_dir, delete=build_delete, kind="install" + ) as directory: + requirement_set = RequirementSet( + require_hashes=options.require_hashes, + check_supported_wheels=not options.target_dir, + ) + + try: + self.populate_requirement_set( + requirement_set, args, options, finder, session, + self.name, wheel_cache + ) + preparer = RequirementPreparer( + build_dir=directory.path, + src_dir=options.src_dir, + download_dir=None, + wheel_download_dir=None, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + resolver = Resolver( + preparer=preparer, + finder=finder, + session=session, + wheel_cache=wheel_cache, + use_user_site=options.use_user_site, + upgrade_strategy=upgrade_strategy, + force_reinstall=options.force_reinstall, + ignore_dependencies=options.ignore_dependencies, + ignore_requires_python=options.ignore_requires_python, + ignore_installed=options.ignore_installed, + isolated=options.isolated_mode, + ) + resolver.resolve(requirement_set) + + protect_pip_from_modification_on_windows( + modifying_pip=requirement_set.has_requirement("pip") + ) + + # If caching is disabled or wheel is not installed don't + # try to build wheels. + if wheel and options.cache_dir: + # build wheels before install. + wb = WheelBuilder( + finder, preparer, wheel_cache, + build_options=[], global_options=[], + ) + # Ignore the result: a failed wheel will be + # installed from the sdist/vcs whatever. + wb.build( + requirement_set.requirements.values(), + session=session, autobuilding=True + ) + + to_install = resolver.get_installation_order( + requirement_set + ) + + # Consistency Checking of the package set we're installing. + should_warn_about_conflicts = ( + not options.ignore_dependencies and + options.warn_about_conflicts + ) + if should_warn_about_conflicts: + self._warn_about_conflicts(to_install) + + # Don't warn about script install locations if + # --target has been specified + warn_script_location = options.warn_script_location + if options.target_dir: + warn_script_location = False + + installed = install_given_reqs( + to_install, + install_options, + global_options, + root=options.root_path, + home=target_temp_dir.path, + prefix=options.prefix_path, + pycompile=options.compile, + warn_script_location=warn_script_location, + use_user_site=options.use_user_site, + ) + + lib_locations = get_lib_location_guesses( + user=options.use_user_site, + home=target_temp_dir.path, + root=options.root_path, + prefix=options.prefix_path, + isolated=options.isolated_mode, + ) + working_set = pkg_resources.WorkingSet(lib_locations) + + reqs = sorted(installed, key=operator.attrgetter('name')) + items = [] + for req in reqs: + item = req.name + try: + installed_version = get_installed_version( + req.name, working_set=working_set + ) + if installed_version: + item += '-' + installed_version + except Exception: + pass + items.append(item) + installed = ' '.join(items) + if installed: + logger.info('Successfully installed %s', installed) + except EnvironmentError as error: + show_traceback = (self.verbosity >= 1) + + message = create_env_error_message( + error, show_traceback, options.use_user_site, + ) + logger.error(message, exc_info=show_traceback) + + return ERROR + except PreviousBuildDirError: + options.no_clean = True + raise + finally: + # Clean up + if not options.no_clean: + requirement_set.cleanup_files() + wheel_cache.cleanup() + + if options.target_dir: + self._handle_target_dir( + options.target_dir, target_temp_dir, options.upgrade + ) + return requirement_set + + def _handle_target_dir(self, target_dir, target_temp_dir, upgrade): + ensure_dir(target_dir) + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + lib_dir_list = [] + + with target_temp_dir: + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + scheme = distutils_scheme('', home=target_temp_dir.path) + purelib_dir = scheme['purelib'] + platlib_dir = scheme['platlib'] + data_dir = scheme['data'] + + if os.path.exists(purelib_dir): + lib_dir_list.append(purelib_dir) + if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: + lib_dir_list.append(platlib_dir) + if os.path.exists(data_dir): + lib_dir_list.append(data_dir) + + for lib_dir in lib_dir_list: + for item in os.listdir(lib_dir): + if lib_dir == data_dir: + ddir = os.path.join(data_dir, item) + if any(s.startswith(ddir) for s in lib_dir_list[:-1]): + continue + target_item_dir = os.path.join(target_dir, item) + if os.path.exists(target_item_dir): + if not upgrade: + logger.warning( + 'Target directory %s already exists. Specify ' + '--upgrade to force replacement.', + target_item_dir + ) + continue + if os.path.islink(target_item_dir): + logger.warning( + 'Target directory %s already exists and is ' + 'a link. Pip will not automatically replace ' + 'links, please remove if replacement is ' + 'desired.', + target_item_dir + ) + continue + if os.path.isdir(target_item_dir): + shutil.rmtree(target_item_dir) + else: + os.remove(target_item_dir) + + shutil.move( + os.path.join(lib_dir, item), + target_item_dir + ) + + def _warn_about_conflicts(self, to_install): + package_set, _dep_info = check_install_conflicts(to_install) + missing, conflicting = _dep_info + + # NOTE: There is some duplication here from pip check + for project_name in missing: + version = package_set[project_name][0] + for dependency in missing[project_name]: + logger.critical( + "%s %s requires %s, which is not installed.", + project_name, version, dependency[1], + ) + + for project_name in conflicting: + version = package_set[project_name][0] + for dep_name, dep_version, req in conflicting[project_name]: + logger.critical( + "%s %s has requirement %s, but you'll have %s %s which is " + "incompatible.", + project_name, version, req, dep_name, dep_version, + ) + + +def get_lib_location_guesses(*args, **kwargs): + scheme = distutils_scheme('', *args, **kwargs) + return [scheme['purelib'], scheme['platlib']] + + +def create_env_error_message(error, show_traceback, using_user_site): + """Format an error message for an EnvironmentError + + It may occur anytime during the execution of the install command. + """ + parts = [] + + # Mention the error if we are not going to show a traceback + parts.append("Could not install packages due to an EnvironmentError") + if not show_traceback: + parts.append(": ") + parts.append(str(error)) + else: + parts.append(".") + + # Spilt the error indication from a helper message (if any) + parts[-1] += "\n" + + # Suggest useful actions to the user: + # (1) using user site-packages or (2) verifying the permissions + if error.errno == errno.EACCES: + user_option_part = "Consider using the `--user` option" + permissions_part = "Check the permissions" + + if not using_user_site: + parts.extend([ + user_option_part, " or ", + permissions_part.lower(), + ]) + else: + parts.append(permissions_part) + parts.append(".\n") + + return "".join(parts).strip() + "\n" diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/list.py b/winvenv/Lib/site-packages/pip/_internal/commands/list.py new file mode 100644 index 0000000..c6eeca7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/list.py @@ -0,0 +1,306 @@ +from __future__ import absolute_import + +import json +import logging + +from pip._vendor import six +from pip._vendor.six.moves import zip_longest + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.exceptions import CommandError +from pip._internal.index import PackageFinder +from pip._internal.utils.misc import ( + dist_is_editable, get_installed_distributions, +) +from pip._internal.utils.packaging import get_installer + +logger = logging.getLogger(__name__) + + +class ListCommand(Command): + """ + List installed packages, including editables. + + Packages are listed in a case-insensitive sorted order. + """ + name = 'list' + usage = """ + %prog [options]""" + summary = 'List installed packages.' + + def __init__(self, *args, **kw): + super(ListCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option( + '-o', '--outdated', + action='store_true', + default=False, + help='List outdated packages') + cmd_opts.add_option( + '-u', '--uptodate', + action='store_true', + default=False, + help='List uptodate packages') + cmd_opts.add_option( + '-e', '--editable', + action='store_true', + default=False, + help='List editable projects.') + cmd_opts.add_option( + '-l', '--local', + action='store_true', + default=False, + help=('If in a virtualenv that has global access, do not list ' + 'globally-installed packages.'), + ) + self.cmd_opts.add_option( + '--user', + dest='user', + action='store_true', + default=False, + help='Only output packages installed in user-site.') + + cmd_opts.add_option( + '--pre', + action='store_true', + default=False, + help=("Include pre-release and development versions. By default, " + "pip only finds stable versions."), + ) + + cmd_opts.add_option( + '--format', + action='store', + dest='list_format', + default="columns", + choices=('columns', 'freeze', 'json'), + help="Select the output format among: columns (default), freeze, " + "or json", + ) + + cmd_opts.add_option( + '--not-required', + action='store_true', + dest='not_required', + help="List packages that are not dependencies of " + "installed packages.", + ) + + cmd_opts.add_option( + '--exclude-editable', + action='store_false', + dest='include_editable', + help='Exclude editable package from output.', + ) + cmd_opts.add_option( + '--include-editable', + action='store_true', + dest='include_editable', + help='Include editable package from output.', + default=True, + ) + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, self.parser + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def _build_package_finder(self, options, index_urls, session): + """ + Create a package finder appropriate to this list command. + """ + return PackageFinder( + find_links=options.find_links, + index_urls=index_urls, + allow_all_prereleases=options.pre, + trusted_hosts=options.trusted_hosts, + process_dependency_links=options.process_dependency_links, + session=session, + ) + + def run(self, options, args): + if options.outdated and options.uptodate: + raise CommandError( + "Options --outdated and --uptodate cannot be combined.") + + packages = get_installed_distributions( + local_only=options.local, + user_only=options.user, + editables_only=options.editable, + include_editables=options.include_editable, + ) + + if options.outdated: + packages = self.get_outdated(packages, options) + elif options.uptodate: + packages = self.get_uptodate(packages, options) + + if options.not_required: + packages = self.get_not_required(packages, options) + + self.output_package_listing(packages, options) + + def get_outdated(self, packages, options): + return [ + dist for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version > dist.parsed_version + ] + + def get_uptodate(self, packages, options): + return [ + dist for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version == dist.parsed_version + ] + + def get_not_required(self, packages, options): + dep_keys = set() + for dist in packages: + dep_keys.update(requirement.key for requirement in dist.requires()) + return {pkg for pkg in packages if pkg.key not in dep_keys} + + def iter_packages_latest_infos(self, packages, options): + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index: + logger.debug('Ignoring indexes: %s', ','.join(index_urls)) + index_urls = [] + + dependency_links = [] + for dist in packages: + if dist.has_metadata('dependency_links.txt'): + dependency_links.extend( + dist.get_metadata_lines('dependency_links.txt'), + ) + + with self._build_session(options) as session: + finder = self._build_package_finder(options, index_urls, session) + finder.add_dependency_links(dependency_links) + + for dist in packages: + typ = 'unknown' + all_candidates = finder.find_all_candidates(dist.key) + if not options.pre: + # Remove prereleases + all_candidates = [candidate for candidate in all_candidates + if not candidate.version.is_prerelease] + + if not all_candidates: + continue + best_candidate = max(all_candidates, + key=finder._candidate_sort_key) + remote_version = best_candidate.version + if best_candidate.location.is_wheel: + typ = 'wheel' + else: + typ = 'sdist' + # This is dirty but makes the rest of the code much cleaner + dist.latest_version = remote_version + dist.latest_filetype = typ + yield dist + + def output_package_listing(self, packages, options): + packages = sorted( + packages, + key=lambda dist: dist.project_name.lower(), + ) + if options.list_format == 'columns' and packages: + data, header = format_for_columns(packages, options) + self.output_package_listing_columns(data, header) + elif options.list_format == 'freeze': + for dist in packages: + if options.verbose >= 1: + logger.info("%s==%s (%s)", dist.project_name, + dist.version, dist.location) + else: + logger.info("%s==%s", dist.project_name, dist.version) + elif options.list_format == 'json': + logger.info(format_for_json(packages, options)) + + def output_package_listing_columns(self, data, header): + # insert the header first: we need to know the size of column names + if len(data) > 0: + data.insert(0, header) + + pkg_strings, sizes = tabulate(data) + + # Create and add a separator. + if len(data) > 0: + pkg_strings.insert(1, " ".join(map(lambda x: '-' * x, sizes))) + + for val in pkg_strings: + logger.info(val) + + +def tabulate(vals): + # From pfmoore on GitHub: + # https://github.com/pypa/pip/issues/3651#issuecomment-216932564 + assert len(vals) > 0 + + sizes = [0] * max(len(x) for x in vals) + for row in vals: + sizes = [max(s, len(str(c))) for s, c in zip_longest(sizes, row)] + + result = [] + for row in vals: + display = " ".join([str(c).ljust(s) if c is not None else '' + for s, c in zip_longest(sizes, row)]) + result.append(display) + + return result, sizes + + +def format_for_columns(pkgs, options): + """ + Convert the package data into something usable + by output_package_listing_columns. + """ + running_outdated = options.outdated + # Adjust the header for the `pip list --outdated` case. + if running_outdated: + header = ["Package", "Version", "Latest", "Type"] + else: + header = ["Package", "Version"] + + data = [] + if options.verbose >= 1 or any(dist_is_editable(x) for x in pkgs): + header.append("Location") + if options.verbose >= 1: + header.append("Installer") + + for proj in pkgs: + # if we're working on the 'outdated' list, separate out the + # latest_version and type + row = [proj.project_name, proj.version] + + if running_outdated: + row.append(proj.latest_version) + row.append(proj.latest_filetype) + + if options.verbose >= 1 or dist_is_editable(proj): + row.append(proj.location) + if options.verbose >= 1: + row.append(get_installer(proj)) + + data.append(row) + + return data, header + + +def format_for_json(packages, options): + data = [] + for dist in packages: + info = { + 'name': dist.project_name, + 'version': six.text_type(dist.version), + } + if options.verbose >= 1: + info['location'] = dist.location + info['installer'] = get_installer(dist) + if options.outdated: + info['latest_version'] = six.text_type(dist.latest_version) + info['latest_filetype'] = dist.latest_filetype + data.append(info) + return json.dumps(data) diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/search.py b/winvenv/Lib/site-packages/pip/_internal/commands/search.py new file mode 100644 index 0000000..c157a31 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/search.py @@ -0,0 +1,135 @@ +from __future__ import absolute_import + +import logging +import sys +import textwrap +from collections import OrderedDict + +from pip._vendor import pkg_resources +from pip._vendor.packaging.version import parse as parse_version +# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import +from pip._vendor.six.moves import xmlrpc_client # type: ignore + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.download import PipXmlrpcTransport +from pip._internal.exceptions import CommandError +from pip._internal.models.index import PyPI +from pip._internal.utils.compat import get_terminal_size +from pip._internal.utils.logging import indent_log + +logger = logging.getLogger(__name__) + + +class SearchCommand(Command): + """Search for PyPI packages whose name or summary contains .""" + name = 'search' + usage = """ + %prog [options] """ + summary = 'Search PyPI for packages.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(SearchCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-i', '--index', + dest='index', + metavar='URL', + default=PyPI.pypi_url, + help='Base URL of Python Package Index (default %default)') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + if not args: + raise CommandError('Missing required argument (search query).') + query = args + pypi_hits = self.search(query, options) + hits = transform_hits(pypi_hits) + + terminal_width = None + if sys.stdout.isatty(): + terminal_width = get_terminal_size()[0] + + print_results(hits, terminal_width=terminal_width) + if pypi_hits: + return SUCCESS + return NO_MATCHES_FOUND + + def search(self, query, options): + index_url = options.index + with self._build_session(options) as session: + transport = PipXmlrpcTransport(index_url, session) + pypi = xmlrpc_client.ServerProxy(index_url, transport) + hits = pypi.search({'name': query, 'summary': query}, 'or') + return hits + + +def transform_hits(hits): + """ + The list from pypi is really a list of versions. We want a list of + packages with the list of versions stored inline. This converts the + list from pypi into one we can use. + """ + packages = OrderedDict() + for hit in hits: + name = hit['name'] + summary = hit['summary'] + version = hit['version'] + + if name not in packages.keys(): + packages[name] = { + 'name': name, + 'summary': summary, + 'versions': [version], + } + else: + packages[name]['versions'].append(version) + + # if this is the highest version, replace summary and score + if version == highest_version(packages[name]['versions']): + packages[name]['summary'] = summary + + return list(packages.values()) + + +def print_results(hits, name_column_width=None, terminal_width=None): + if not hits: + return + if name_column_width is None: + name_column_width = max([ + len(hit['name']) + len(highest_version(hit.get('versions', ['-']))) + for hit in hits + ]) + 4 + + installed_packages = [p.project_name for p in pkg_resources.working_set] + for hit in hits: + name = hit['name'] + summary = hit['summary'] or '' + latest = highest_version(hit.get('versions', ['-'])) + if terminal_width is not None: + target_width = terminal_width - name_column_width - 5 + if target_width > 10: + # wrap and indent summary to fit terminal + summary = textwrap.wrap(summary, target_width) + summary = ('\n' + ' ' * (name_column_width + 3)).join(summary) + + line = '%-*s - %s' % (name_column_width, + '%s (%s)' % (name, latest), summary) + try: + logger.info(line) + if name in installed_packages: + dist = pkg_resources.get_distribution(name) + with indent_log(): + if dist.version == latest: + logger.info('INSTALLED: %s (latest)', dist.version) + else: + logger.info('INSTALLED: %s', dist.version) + logger.info('LATEST: %s', latest) + except UnicodeEncodeError: + pass + + +def highest_version(versions): + return max(versions, key=parse_version) diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/show.py b/winvenv/Lib/site-packages/pip/_internal/commands/show.py new file mode 100644 index 0000000..f92c9bc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/show.py @@ -0,0 +1,168 @@ +from __future__ import absolute_import + +import logging +import os +from email.parser import FeedParser # type: ignore + +from pip._vendor import pkg_resources +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS + +logger = logging.getLogger(__name__) + + +class ShowCommand(Command): + """ + Show information about one or more installed packages. + + The output is in RFC-compliant mail header format. + """ + name = 'show' + usage = """ + %prog [options] ...""" + summary = 'Show information about installed packages.' + ignore_require_venv = True + + def __init__(self, *args, **kw): + super(ShowCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-f', '--files', + dest='files', + action='store_true', + default=False, + help='Show the full list of installed files for each package.') + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + if not args: + logger.warning('ERROR: Please provide a package name or names.') + return ERROR + query = args + + results = search_packages_info(query) + if not print_results( + results, list_files=options.files, verbose=options.verbose): + return ERROR + return SUCCESS + + +def search_packages_info(query): + """ + Gather details from installed distributions. Print distribution name, + version, location, and installed files. Installed files requires a + pip generated 'installed-files.txt' in the distributions '.egg-info' + directory. + """ + installed = {} + for p in pkg_resources.working_set: + installed[canonicalize_name(p.project_name)] = p + + query_names = [canonicalize_name(name) for name in query] + + for dist in [installed[pkg] for pkg in query_names if pkg in installed]: + package = { + 'name': dist.project_name, + 'version': dist.version, + 'location': dist.location, + 'requires': [dep.project_name for dep in dist.requires()], + } + file_list = None + metadata = None + if isinstance(dist, pkg_resources.DistInfoDistribution): + # RECORDs should be part of .dist-info metadatas + if dist.has_metadata('RECORD'): + lines = dist.get_metadata_lines('RECORD') + paths = [l.split(',')[0] for l in lines] + paths = [os.path.join(dist.location, p) for p in paths] + file_list = [os.path.relpath(p, dist.location) for p in paths] + + if dist.has_metadata('METADATA'): + metadata = dist.get_metadata('METADATA') + else: + # Otherwise use pip's log for .egg-info's + if dist.has_metadata('installed-files.txt'): + paths = dist.get_metadata_lines('installed-files.txt') + paths = [os.path.join(dist.egg_info, p) for p in paths] + file_list = [os.path.relpath(p, dist.location) for p in paths] + + if dist.has_metadata('PKG-INFO'): + metadata = dist.get_metadata('PKG-INFO') + + if dist.has_metadata('entry_points.txt'): + entry_points = dist.get_metadata_lines('entry_points.txt') + package['entry_points'] = entry_points + + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + package['installer'] = line.strip() + break + + # @todo: Should pkg_resources.Distribution have a + # `get_pkg_info` method? + feed_parser = FeedParser() + feed_parser.feed(metadata) + pkg_info_dict = feed_parser.close() + for key in ('metadata-version', 'summary', + 'home-page', 'author', 'author-email', 'license'): + package[key] = pkg_info_dict.get(key) + + # It looks like FeedParser cannot deal with repeated headers + classifiers = [] + for line in metadata.splitlines(): + if line.startswith('Classifier: '): + classifiers.append(line[len('Classifier: '):]) + package['classifiers'] = classifiers + + if file_list: + package['files'] = sorted(file_list) + yield package + + +def print_results(distributions, list_files=False, verbose=False): + """ + Print the informations from installed distributions found. + """ + results_printed = False + for i, dist in enumerate(distributions): + results_printed = True + if i > 0: + logger.info("---") + + name = dist.get('name', '') + required_by = [ + pkg.project_name for pkg in pkg_resources.working_set + if name in [required.name for required in pkg.requires()] + ] + + logger.info("Name: %s", name) + logger.info("Version: %s", dist.get('version', '')) + logger.info("Summary: %s", dist.get('summary', '')) + logger.info("Home-page: %s", dist.get('home-page', '')) + logger.info("Author: %s", dist.get('author', '')) + logger.info("Author-email: %s", dist.get('author-email', '')) + logger.info("License: %s", dist.get('license', '')) + logger.info("Location: %s", dist.get('location', '')) + logger.info("Requires: %s", ', '.join(dist.get('requires', []))) + logger.info("Required-by: %s", ', '.join(required_by)) + + if verbose: + logger.info("Metadata-Version: %s", + dist.get('metadata-version', '')) + logger.info("Installer: %s", dist.get('installer', '')) + logger.info("Classifiers:") + for classifier in dist.get('classifiers', []): + logger.info(" %s", classifier) + logger.info("Entry-points:") + for entry in dist.get('entry_points', []): + logger.info(" %s", entry.strip()) + if list_files: + logger.info("Files:") + for line in dist.get('files', []): + logger.info(" %s", line.strip()) + if "files" not in dist: + logger.info("Cannot locate installed-files.txt") + return results_printed diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/uninstall.py b/winvenv/Lib/site-packages/pip/_internal/commands/uninstall.py new file mode 100644 index 0000000..0cd6f54 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/uninstall.py @@ -0,0 +1,78 @@ +from __future__ import absolute_import + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.exceptions import InstallationError +from pip._internal.req import parse_requirements +from pip._internal.req.constructors import install_req_from_line +from pip._internal.utils.misc import protect_pip_from_modification_on_windows + + +class UninstallCommand(Command): + """ + Uninstall packages. + + pip is able to uninstall most installed packages. Known exceptions are: + + - Pure distutils packages installed with ``python setup.py install``, which + leave behind no metadata to determine what files were installed. + - Script wrappers installed by ``python setup.py develop``. + """ + name = 'uninstall' + usage = """ + %prog [options] ... + %prog [options] -r ...""" + summary = 'Uninstall packages.' + + def __init__(self, *args, **kw): + super(UninstallCommand, self).__init__(*args, **kw) + self.cmd_opts.add_option( + '-r', '--requirement', + dest='requirements', + action='append', + default=[], + metavar='file', + help='Uninstall all the packages listed in the given requirements ' + 'file. This option can be used multiple times.', + ) + self.cmd_opts.add_option( + '-y', '--yes', + dest='yes', + action='store_true', + help="Don't ask for confirmation of uninstall deletions.") + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options, args): + with self._build_session(options) as session: + reqs_to_uninstall = {} + for name in args: + req = install_req_from_line( + name, isolated=options.isolated_mode, + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + for filename in options.requirements: + for req in parse_requirements( + filename, + options=options, + session=session): + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + if not reqs_to_uninstall: + raise InstallationError( + 'You must give at least one requirement to %(name)s (see ' + '"pip help %(name)s")' % dict(name=self.name) + ) + + protect_pip_from_modification_on_windows( + modifying_pip="pip" in reqs_to_uninstall + ) + + for req in reqs_to_uninstall.values(): + uninstall_pathset = req.uninstall( + auto_confirm=options.yes, verbose=self.verbosity > 0, + ) + if uninstall_pathset: + uninstall_pathset.commit() diff --git a/winvenv/Lib/site-packages/pip/_internal/commands/wheel.py b/winvenv/Lib/site-packages/pip/_internal/commands/wheel.py new file mode 100644 index 0000000..9c1f149 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/commands/wheel.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +import logging +import os + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import RequirementCommand +from pip._internal.exceptions import CommandError, PreviousBuildDirError +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req import RequirementSet +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolve import Resolver +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel import WheelBuilder + +logger = logging.getLogger(__name__) + + +class WheelCommand(RequirementCommand): + """ + Build Wheel archives for your requirements and dependencies. + + Wheel is a built-package format, and offers the advantage of not + recompiling your software during every install. For more details, see the + wheel docs: https://wheel.readthedocs.io/en/latest/ + + Requirements: setuptools>=0.8, and wheel. + + 'pip wheel' uses the bdist_wheel setuptools extension from the wheel + package to build individual wheels. + + """ + + name = 'wheel' + usage = """ + %prog [options] ... + %prog [options] -r ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + summary = 'Build wheels from your requirements.' + + def __init__(self, *args, **kw): + super(WheelCommand, self).__init__(*args, **kw) + + cmd_opts = self.cmd_opts + + cmd_opts.add_option( + '-w', '--wheel-dir', + dest='wheel_dir', + metavar='dir', + default=os.curdir, + help=("Build wheels into , where the default is the " + "current working directory."), + ) + cmd_opts.add_option(cmdoptions.no_binary()) + cmd_opts.add_option(cmdoptions.only_binary()) + cmd_opts.add_option(cmdoptions.prefer_binary()) + cmd_opts.add_option( + '--build-option', + dest='build_options', + metavar='options', + action='append', + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", + ) + cmd_opts.add_option(cmdoptions.no_build_isolation()) + cmd_opts.add_option(cmdoptions.constraints()) + cmd_opts.add_option(cmdoptions.editable()) + cmd_opts.add_option(cmdoptions.requirements()) + cmd_opts.add_option(cmdoptions.src()) + cmd_opts.add_option(cmdoptions.ignore_requires_python()) + cmd_opts.add_option(cmdoptions.no_deps()) + cmd_opts.add_option(cmdoptions.build_dir()) + cmd_opts.add_option(cmdoptions.progress_bar()) + + cmd_opts.add_option( + '--global-option', + dest='global_options', + action='append', + metavar='options', + help="Extra global options to be supplied to the setup.py " + "call before the 'bdist_wheel' command.") + + cmd_opts.add_option( + '--pre', + action='store_true', + default=False, + help=("Include pre-release and development versions. By default, " + "pip only finds stable versions."), + ) + + cmd_opts.add_option(cmdoptions.no_clean()) + cmd_opts.add_option(cmdoptions.require_hashes()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, cmd_opts) + + def run(self, options, args): + cmdoptions.check_install_build_global(options) + + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index: + logger.debug('Ignoring indexes: %s', ','.join(index_urls)) + index_urls = [] + + if options.build_dir: + options.build_dir = os.path.abspath(options.build_dir) + + options.src_dir = os.path.abspath(options.src_dir) + + with self._build_session(options) as session: + finder = self._build_package_finder(options, session) + build_delete = (not (options.no_clean or options.build_dir)) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + with RequirementTracker() as req_tracker, TempDirectory( + options.build_dir, delete=build_delete, kind="wheel" + ) as directory: + + requirement_set = RequirementSet( + require_hashes=options.require_hashes, + ) + + try: + self.populate_requirement_set( + requirement_set, args, options, finder, session, + self.name, wheel_cache + ) + + preparer = RequirementPreparer( + build_dir=directory.path, + src_dir=options.src_dir, + download_dir=None, + wheel_download_dir=options.wheel_dir, + progress_bar=options.progress_bar, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + ) + + resolver = Resolver( + preparer=preparer, + finder=finder, + session=session, + wheel_cache=wheel_cache, + use_user_site=False, + upgrade_strategy="to-satisfy-only", + force_reinstall=False, + ignore_dependencies=options.ignore_dependencies, + ignore_requires_python=options.ignore_requires_python, + ignore_installed=True, + isolated=options.isolated_mode, + ) + resolver.resolve(requirement_set) + + # build wheels + wb = WheelBuilder( + finder, preparer, wheel_cache, + build_options=options.build_options or [], + global_options=options.global_options or [], + no_clean=options.no_clean, + ) + wheels_built_successfully = wb.build( + requirement_set.requirements.values(), session=session, + ) + if not wheels_built_successfully: + raise CommandError( + "Failed to build one or more wheels" + ) + except PreviousBuildDirError: + options.no_clean = True + raise + finally: + if not options.no_clean: + requirement_set.cleanup_files() + wheel_cache.cleanup() diff --git a/winvenv/Lib/site-packages/pip/_internal/configuration.py b/winvenv/Lib/site-packages/pip/_internal/configuration.py new file mode 100644 index 0000000..fe6df9b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/configuration.py @@ -0,0 +1,387 @@ +"""Configuration management setup + +Some terminology: +- name + As written in config files. +- value + Value associated with a name +- key + Name combined with it's section (section.name) +- variant + A single word describing where the configuration key-value pair came from +""" + +import locale +import logging +import os + +from pip._vendor import six +from pip._vendor.six.moves import configparser + +from pip._internal.exceptions import ( + ConfigurationError, ConfigurationFileCouldNotBeLoaded, +) +from pip._internal.locations import ( + legacy_config_file, new_config_file, running_under_virtualenv, + site_config_files, venv_config_file, +) +from pip._internal.utils.misc import ensure_dir, enum +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import ( # noqa: F401 + Any, Dict, Iterable, List, NewType, Optional, Tuple + ) + + RawConfigParser = configparser.RawConfigParser # Shorthand + Kind = NewType("Kind", str) + +logger = logging.getLogger(__name__) + + +# NOTE: Maybe use the optionx attribute to normalize keynames. +def _normalize_name(name): + # type: (str) -> str + """Make a name consistent regardless of source (environment or file) + """ + name = name.lower().replace('_', '-') + if name.startswith('--'): + name = name[2:] # only prefer long opts + return name + + +def _disassemble_key(name): + # type: (str) -> List[str] + return name.split(".", 1) + + +# The kinds of configurations there are. +kinds = enum( + USER="user", # User Specific + GLOBAL="global", # System Wide + VENV="venv", # Virtual Environment Specific + ENV="env", # from PIP_CONFIG_FILE + ENV_VAR="env-var", # from Environment Variables +) + + +class Configuration(object): + """Handles management of configuration. + + Provides an interface to accessing and managing configuration files. + + This class converts provides an API that takes "section.key-name" style + keys and stores the value associated with it as "key-name" under the + section "section". + + This allows for a clean interface wherein the both the section and the + key-name are preserved in an easy to manage form in the configuration files + and the data stored is also nice. + """ + + def __init__(self, isolated, load_only=None): + # type: (bool, Kind) -> None + super(Configuration, self).__init__() + + _valid_load_only = [kinds.USER, kinds.GLOBAL, kinds.VENV, None] + if load_only not in _valid_load_only: + raise ConfigurationError( + "Got invalid value for load_only - should be one of {}".format( + ", ".join(map(repr, _valid_load_only[:-1])) + ) + ) + self.isolated = isolated # type: bool + self.load_only = load_only # type: Optional[Kind] + + # The order here determines the override order. + self._override_order = [ + kinds.GLOBAL, kinds.USER, kinds.VENV, kinds.ENV, kinds.ENV_VAR + ] + + self._ignore_env_names = ["version", "help"] + + # Because we keep track of where we got the data from + self._parsers = { + variant: [] for variant in self._override_order + } # type: Dict[Kind, List[Tuple[str, RawConfigParser]]] + self._config = { + variant: {} for variant in self._override_order + } # type: Dict[Kind, Dict[str, Any]] + self._modified_parsers = [] # type: List[Tuple[str, RawConfigParser]] + + def load(self): + # type: () -> None + """Loads configuration from configuration files and environment + """ + self._load_config_files() + if not self.isolated: + self._load_environment_vars() + + def get_file_to_edit(self): + # type: () -> Optional[str] + """Returns the file with highest priority in configuration + """ + assert self.load_only is not None, \ + "Need to be specified a file to be editing" + + try: + return self._get_parser_to_modify()[0] + except IndexError: + return None + + def items(self): + # type: () -> Iterable[Tuple[str, Any]] + """Returns key-value pairs like dict.items() representing the loaded + configuration + """ + return self._dictionary.items() + + def get_value(self, key): + # type: (str) -> Any + """Get a value from the configuration. + """ + try: + return self._dictionary[key] + except KeyError: + raise ConfigurationError("No such key - {}".format(key)) + + def set_value(self, key, value): + # type: (str, Any) -> None + """Modify a value in the configuration. + """ + self._ensure_have_load_only() + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Modify the parser and the configuration + if not parser.has_section(section): + parser.add_section(section) + parser.set(section, name, value) + + self._config[self.load_only][key] = value + self._mark_as_modified(fname, parser) + + def unset_value(self, key): + # type: (str) -> None + """Unset a value in the configuration. + """ + self._ensure_have_load_only() + + if key not in self._config[self.load_only]: + raise ConfigurationError("No such key - {}".format(key)) + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Remove the key in the parser + modified_something = False + if parser.has_section(section): + # Returns whether the option was removed or not + modified_something = parser.remove_option(section, name) + + if modified_something: + # name removed from parser, section may now be empty + section_iter = iter(parser.items(section)) + try: + val = six.next(section_iter) + except StopIteration: + val = None + + if val is None: + parser.remove_section(section) + + self._mark_as_modified(fname, parser) + else: + raise ConfigurationError( + "Fatal Internal error [id=1]. Please report as a bug." + ) + + del self._config[self.load_only][key] + + def save(self): + # type: () -> None + """Save the currentin-memory state. + """ + self._ensure_have_load_only() + + for fname, parser in self._modified_parsers: + logger.info("Writing to %s", fname) + + # Ensure directory exists. + ensure_dir(os.path.dirname(fname)) + + with open(fname, "w") as f: + parser.write(f) # type: ignore + + # + # Private routines + # + + def _ensure_have_load_only(self): + # type: () -> None + if self.load_only is None: + raise ConfigurationError("Needed a specific file to be modifying.") + logger.debug("Will be working with %s variant only", self.load_only) + + @property + def _dictionary(self): + # type: () -> Dict[str, Any] + """A dictionary representing the loaded configuration. + """ + # NOTE: Dictionaries are not populated if not loaded. So, conditionals + # are not needed here. + retval = {} + + for variant in self._override_order: + retval.update(self._config[variant]) + + return retval + + def _load_config_files(self): + # type: () -> None + """Loads configuration from configuration files + """ + config_files = dict(self._iter_config_files()) + if config_files[kinds.ENV][0:1] == [os.devnull]: + logger.debug( + "Skipping loading configuration files due to " + "environment's PIP_CONFIG_FILE being os.devnull" + ) + return + + for variant, files in config_files.items(): + for fname in files: + # If there's specific variant set in `load_only`, load only + # that variant, not the others. + if self.load_only is not None and variant != self.load_only: + logger.debug( + "Skipping file '%s' (variant: %s)", fname, variant + ) + continue + + parser = self._load_file(variant, fname) + + # Keeping track of the parsers used + self._parsers[variant].append((fname, parser)) + + def _load_file(self, variant, fname): + # type: (Kind, str) -> RawConfigParser + logger.debug("For variant '%s', will try loading '%s'", variant, fname) + parser = self._construct_parser(fname) + + for section in parser.sections(): + items = parser.items(section) + self._config[variant].update(self._normalized_keys(section, items)) + + return parser + + def _construct_parser(self, fname): + # type: (str) -> RawConfigParser + parser = configparser.RawConfigParser() + # If there is no such file, don't bother reading it but create the + # parser anyway, to hold the data. + # Doing this is useful when modifying and saving files, where we don't + # need to construct a parser. + if os.path.exists(fname): + try: + parser.read(fname) + except UnicodeDecodeError: + # See https://github.com/pypa/pip/issues/4963 + raise ConfigurationFileCouldNotBeLoaded( + reason="contains invalid {} characters".format( + locale.getpreferredencoding(False) + ), + fname=fname, + ) + except configparser.Error as error: + # See https://github.com/pypa/pip/issues/4893 + raise ConfigurationFileCouldNotBeLoaded(error=error) + return parser + + def _load_environment_vars(self): + # type: () -> None + """Loads configuration from environment variables + """ + self._config[kinds.ENV_VAR].update( + self._normalized_keys(":env:", self._get_environ_vars()) + ) + + def _normalized_keys(self, section, items): + # type: (str, Iterable[Tuple[str, Any]]) -> Dict[str, Any] + """Normalizes items to construct a dictionary with normalized keys. + + This routine is where the names become keys and are made the same + regardless of source - configuration files or environment. + """ + normalized = {} + for name, val in items: + key = section + "." + _normalize_name(name) + normalized[key] = val + return normalized + + def _get_environ_vars(self): + # type: () -> Iterable[Tuple[str, str]] + """Returns a generator with all environmental vars with prefix PIP_""" + for key, val in os.environ.items(): + should_be_yielded = ( + key.startswith("PIP_") and + key[4:].lower() not in self._ignore_env_names + ) + if should_be_yielded: + yield key[4:].lower(), val + + # XXX: This is patched in the tests. + def _iter_config_files(self): + # type: () -> Iterable[Tuple[Kind, List[str]]] + """Yields variant and configuration files associated with it. + + This should be treated like items of a dictionary. + """ + # SMELL: Move the conditions out of this function + + # environment variables have the lowest priority + config_file = os.environ.get('PIP_CONFIG_FILE', None) + if config_file is not None: + yield kinds.ENV, [config_file] + else: + yield kinds.ENV, [] + + # at the base we have any global configuration + yield kinds.GLOBAL, list(site_config_files) + + # per-user configuration next + should_load_user_config = not self.isolated and not ( + config_file and os.path.exists(config_file) + ) + if should_load_user_config: + # The legacy config file is overridden by the new config file + yield kinds.USER, [legacy_config_file, new_config_file] + + # finally virtualenv configuration first trumping others + if running_under_virtualenv(): + yield kinds.VENV, [venv_config_file] + + def _get_parser_to_modify(self): + # type: () -> Tuple[str, RawConfigParser] + # Determine which parser to modify + parsers = self._parsers[self.load_only] + if not parsers: + # This should not happen if everything works correctly. + raise ConfigurationError( + "Fatal Internal error [id=2]. Please report as a bug." + ) + + # Use the highest priority parser. + return parsers[-1] + + # XXX: This is patched in the tests. + def _mark_as_modified(self, fname, parser): + # type: (str, RawConfigParser) -> None + file_parser_tuple = (fname, parser) + if file_parser_tuple not in self._modified_parsers: + self._modified_parsers.append(file_parser_tuple) diff --git a/winvenv/Lib/site-packages/pip/_internal/download.py b/winvenv/Lib/site-packages/pip/_internal/download.py new file mode 100644 index 0000000..96f3b65 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/download.py @@ -0,0 +1,921 @@ +from __future__ import absolute_import + +import cgi +import email.utils +import getpass +import json +import logging +import mimetypes +import os +import platform +import re +import shutil +import sys + +from pip._vendor import requests, six, urllib3 +from pip._vendor.cachecontrol import CacheControlAdapter +from pip._vendor.cachecontrol.caches import FileCache +from pip._vendor.lockfile import LockError +from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter +from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response +from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.requests.utils import get_netrc_auth +# NOTE: XMLRPC Client is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import +from pip._vendor.six.moves import xmlrpc_client # type: ignore +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request +from pip._vendor.six.moves.urllib.parse import unquote as urllib_unquote +from pip._vendor.urllib3.util import IS_PYOPENSSL + +import pip +from pip._internal.exceptions import HashMismatch, InstallationError +from pip._internal.locations import write_delete_marker_file +from pip._internal.models.index import PyPI +from pip._internal.utils.encoding import auto_decode +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.glibc import libc_ver +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, ask_path_exists, backup_dir, call_subprocess, consume, + display_path, format_size, get_installed_version, rmtree, splitext, + unpack_file, +) +from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.ui import DownloadProgressProvider +from pip._internal.vcs import vcs + +try: + import ssl # noqa +except ImportError: + ssl = None + +HAS_TLS = (ssl is not None) or IS_PYOPENSSL + +__all__ = ['get_file_content', + 'is_url', 'url_to_path', 'path_to_url', + 'is_archive_file', 'unpack_vcs_link', + 'unpack_file_url', 'is_vcs_url', 'is_file_url', + 'unpack_http_url', 'unpack_url'] + + +logger = logging.getLogger(__name__) + + +def user_agent(): + """ + Return a string representing the user agent. + """ + data = { + "installer": {"name": "pip", "version": pip.__version__}, + "python": platform.python_version(), + "implementation": { + "name": platform.python_implementation(), + }, + } + + if data["implementation"]["name"] == 'CPython': + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == 'PyPy': + if sys.pypy_version_info.releaselevel == 'final': + pypy_version_info = sys.pypy_version_info[:3] + else: + pypy_version_info = sys.pypy_version_info + data["implementation"]["version"] = ".".join( + [str(x) for x in pypy_version_info] + ) + elif data["implementation"]["name"] == 'Jython': + # Complete Guess + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == 'IronPython': + # Complete Guess + data["implementation"]["version"] = platform.python_version() + + if sys.platform.startswith("linux"): + from pip._vendor import distro + distro_infos = dict(filter( + lambda x: x[1], + zip(["name", "version", "id"], distro.linux_distribution()), + )) + libc = dict(filter( + lambda x: x[1], + zip(["lib", "version"], libc_ver()), + )) + if libc: + distro_infos["libc"] = libc + if distro_infos: + data["distro"] = distro_infos + + if sys.platform.startswith("darwin") and platform.mac_ver()[0]: + data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]} + + if platform.system(): + data.setdefault("system", {})["name"] = platform.system() + + if platform.release(): + data.setdefault("system", {})["release"] = platform.release() + + if platform.machine(): + data["cpu"] = platform.machine() + + if HAS_TLS: + data["openssl_version"] = ssl.OPENSSL_VERSION + + setuptools_version = get_installed_version("setuptools") + if setuptools_version is not None: + data["setuptools_version"] = setuptools_version + + return "{data[installer][name]}/{data[installer][version]} {json}".format( + data=data, + json=json.dumps(data, separators=(",", ":"), sort_keys=True), + ) + + +class MultiDomainBasicAuth(AuthBase): + + def __init__(self, prompting=True): + self.prompting = prompting + self.passwords = {} + + def __call__(self, req): + parsed = urllib_parse.urlparse(req.url) + + # Get the netloc without any embedded credentials + netloc = parsed.netloc.rsplit("@", 1)[-1] + + # Set the url of the request to the url without any credentials + req.url = urllib_parse.urlunparse(parsed[:1] + (netloc,) + parsed[2:]) + + # Use any stored credentials that we have for this netloc + username, password = self.passwords.get(netloc, (None, None)) + + # Extract credentials embedded in the url if we have none stored + if username is None: + username, password = self.parse_credentials(parsed.netloc) + + # Get creds from netrc if we still don't have them + if username is None and password is None: + netrc_auth = get_netrc_auth(req.url) + username, password = netrc_auth if netrc_auth else (None, None) + + if username or password: + # Store the username and password + self.passwords[netloc] = (username, password) + + # Send the basic auth with this request + req = HTTPBasicAuth(username or "", password or "")(req) + + # Attach a hook to handle 401 responses + req.register_hook("response", self.handle_401) + + return req + + def handle_401(self, resp, **kwargs): + # We only care about 401 responses, anything else we want to just + # pass through the actual response + if resp.status_code != 401: + return resp + + # We are not able to prompt the user so simply return the response + if not self.prompting: + return resp + + parsed = urllib_parse.urlparse(resp.url) + + # Prompt the user for a new username and password + username = six.moves.input("User for %s: " % parsed.netloc) + password = getpass.getpass("Password: ") + + # Store the new username and password to use for future requests + if username or password: + self.passwords[parsed.netloc] = (username, password) + + # Consume content and release the original connection to allow our new + # request to reuse the same one. + resp.content + resp.raw.release_conn() + + # Add our new username and password to the request + req = HTTPBasicAuth(username or "", password or "")(resp.request) + + # Send our new request + new_resp = resp.connection.send(req, **kwargs) + new_resp.history.append(resp) + + return new_resp + + def parse_credentials(self, netloc): + if "@" in netloc: + userinfo = netloc.rsplit("@", 1)[0] + if ":" in userinfo: + user, pwd = userinfo.split(":", 1) + return (urllib_unquote(user), urllib_unquote(pwd)) + return urllib_unquote(userinfo), None + return None, None + + +class LocalFSAdapter(BaseAdapter): + + def send(self, request, stream=None, timeout=None, verify=None, cert=None, + proxies=None): + pathname = url_to_path(request.url) + + resp = Response() + resp.status_code = 200 + resp.url = request.url + + try: + stats = os.stat(pathname) + except OSError as exc: + resp.status_code = 404 + resp.raw = exc + else: + modified = email.utils.formatdate(stats.st_mtime, usegmt=True) + content_type = mimetypes.guess_type(pathname)[0] or "text/plain" + resp.headers = CaseInsensitiveDict({ + "Content-Type": content_type, + "Content-Length": stats.st_size, + "Last-Modified": modified, + }) + + resp.raw = open(pathname, "rb") + resp.close = resp.raw.close + + return resp + + def close(self): + pass + + +class SafeFileCache(FileCache): + """ + A file based cache which is safe to use even when the target directory may + not be accessible or writable. + """ + + def __init__(self, *args, **kwargs): + super(SafeFileCache, self).__init__(*args, **kwargs) + + # Check to ensure that the directory containing our cache directory + # is owned by the user current executing pip. If it does not exist + # we will check the parent directory until we find one that does exist. + # If it is not owned by the user executing pip then we will disable + # the cache and log a warning. + if not check_path_owner(self.directory): + logger.warning( + "The directory '%s' or its parent directory is not owned by " + "the current user and the cache has been disabled. Please " + "check the permissions and owner of that directory. If " + "executing pip with sudo, you may want sudo's -H flag.", + self.directory, + ) + + # Set our directory to None to disable the Cache + self.directory = None + + def get(self, *args, **kwargs): + # If we don't have a directory, then the cache should be a no-op. + if self.directory is None: + return + + try: + return super(SafeFileCache, self).get(*args, **kwargs) + except (LockError, OSError, IOError): + # We intentionally silence this error, if we can't access the cache + # then we can just skip caching and process the request as if + # caching wasn't enabled. + pass + + def set(self, *args, **kwargs): + # If we don't have a directory, then the cache should be a no-op. + if self.directory is None: + return + + try: + return super(SafeFileCache, self).set(*args, **kwargs) + except (LockError, OSError, IOError): + # We intentionally silence this error, if we can't access the cache + # then we can just skip caching and process the request as if + # caching wasn't enabled. + pass + + def delete(self, *args, **kwargs): + # If we don't have a directory, then the cache should be a no-op. + if self.directory is None: + return + + try: + return super(SafeFileCache, self).delete(*args, **kwargs) + except (LockError, OSError, IOError): + # We intentionally silence this error, if we can't access the cache + # then we can just skip caching and process the request as if + # caching wasn't enabled. + pass + + +class InsecureHTTPAdapter(HTTPAdapter): + + def cert_verify(self, conn, url, verify, cert): + conn.cert_reqs = 'CERT_NONE' + conn.ca_certs = None + + +class PipSession(requests.Session): + + timeout = None + + def __init__(self, *args, **kwargs): + retries = kwargs.pop("retries", 0) + cache = kwargs.pop("cache", None) + insecure_hosts = kwargs.pop("insecure_hosts", []) + + super(PipSession, self).__init__(*args, **kwargs) + + # Attach our User Agent to the request + self.headers["User-Agent"] = user_agent() + + # Attach our Authentication handler to the session + self.auth = MultiDomainBasicAuth() + + # Create our urllib3.Retry instance which will allow us to customize + # how we handle retries. + retries = urllib3.Retry( + # Set the total number of retries that a particular request can + # have. + total=retries, + + # A 503 error from PyPI typically means that the Fastly -> Origin + # connection got interrupted in some way. A 503 error in general + # is typically considered a transient error so we'll go ahead and + # retry it. + # A 500 may indicate transient error in Amazon S3 + # A 520 or 527 - may indicate transient error in CloudFlare + status_forcelist=[500, 503, 520, 527], + + # Add a small amount of back off between failed requests in + # order to prevent hammering the service. + backoff_factor=0.25, + ) + + # We want to _only_ cache responses on securely fetched origins. We do + # this because we can't validate the response of an insecurely fetched + # origin, and we don't want someone to be able to poison the cache and + # require manual eviction from the cache to fix it. + if cache: + secure_adapter = CacheControlAdapter( + cache=SafeFileCache(cache, use_dir_lock=True), + max_retries=retries, + ) + else: + secure_adapter = HTTPAdapter(max_retries=retries) + + # Our Insecure HTTPAdapter disables HTTPS validation. It does not + # support caching (see above) so we'll use it for all http:// URLs as + # well as any https:// host that we've marked as ignoring TLS errors + # for. + insecure_adapter = InsecureHTTPAdapter(max_retries=retries) + + self.mount("https://", secure_adapter) + self.mount("http://", insecure_adapter) + + # Enable file:// urls + self.mount("file://", LocalFSAdapter()) + + # We want to use a non-validating adapter for any requests which are + # deemed insecure. + for host in insecure_hosts: + self.mount("https://{}/".format(host), insecure_adapter) + + def request(self, method, url, *args, **kwargs): + # Allow setting a default timeout on a session + kwargs.setdefault("timeout", self.timeout) + + # Dispatch the actual request + return super(PipSession, self).request(method, url, *args, **kwargs) + + +def get_file_content(url, comes_from=None, session=None): + """Gets the content of a file; it may be a filename, file: URL, or + http: URL. Returns (location, content). Content is unicode. + + :param url: File path or url. + :param comes_from: Origin description of requirements. + :param session: Instance of pip.download.PipSession. + """ + if session is None: + raise TypeError( + "get_file_content() missing 1 required keyword argument: 'session'" + ) + + match = _scheme_re.search(url) + if match: + scheme = match.group(1).lower() + if (scheme == 'file' and comes_from and + comes_from.startswith('http')): + raise InstallationError( + 'Requirements file %s references URL %s, which is local' + % (comes_from, url)) + if scheme == 'file': + path = url.split(':', 1)[1] + path = path.replace('\\', '/') + match = _url_slash_drive_re.match(path) + if match: + path = match.group(1) + ':' + path.split('|', 1)[1] + path = urllib_parse.unquote(path) + if path.startswith('/'): + path = '/' + path.lstrip('/') + url = path + else: + # FIXME: catch some errors + resp = session.get(url) + resp.raise_for_status() + return resp.url, resp.text + try: + with open(url, 'rb') as f: + content = auto_decode(f.read()) + except IOError as exc: + raise InstallationError( + 'Could not open requirements file: %s' % str(exc) + ) + return url, content + + +_scheme_re = re.compile(r'^(http|https|file):', re.I) +_url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I) + + +def is_url(name): + """Returns true if the name looks like a URL""" + if ':' not in name: + return False + scheme = name.split(':', 1)[0].lower() + return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes + + +def url_to_path(url): + """ + Convert a file: URL to a path. + """ + assert url.startswith('file:'), ( + "You can only turn file: urls into filenames (not %r)" % url) + + _, netloc, path, _, _ = urllib_parse.urlsplit(url) + + # if we have a UNC path, prepend UNC share notation + if netloc: + netloc = '\\\\' + netloc + + path = urllib_request.url2pathname(netloc + path) + return path + + +def path_to_url(path): + """ + Convert a path to a file: URL. The path will be made absolute and have + quoted path parts. + """ + path = os.path.normpath(os.path.abspath(path)) + url = urllib_parse.urljoin('file:', urllib_request.pathname2url(path)) + return url + + +def is_archive_file(name): + """Return True if `name` is a considered as an archive file.""" + ext = splitext(name)[1].lower() + if ext in ARCHIVE_EXTENSIONS: + return True + return False + + +def unpack_vcs_link(link, location): + vcs_backend = _get_used_vcs_backend(link) + vcs_backend.unpack(location) + + +def _get_used_vcs_backend(link): + for backend in vcs.backends: + if link.scheme in backend.schemes: + vcs_backend = backend(link.url) + return vcs_backend + + +def is_vcs_url(link): + return bool(_get_used_vcs_backend(link)) + + +def is_file_url(link): + return link.url.lower().startswith('file:') + + +def is_dir_url(link): + """Return whether a file:// Link points to a directory. + + ``link`` must not have any other scheme but file://. Call is_file_url() + first. + + """ + link_path = url_to_path(link.url_without_fragment) + return os.path.isdir(link_path) + + +def _progress_indicator(iterable, *args, **kwargs): + return iterable + + +def _download_url(resp, link, content_file, hashes, progress_bar): + try: + total_length = int(resp.headers['content-length']) + except (ValueError, KeyError, TypeError): + total_length = 0 + + cached_resp = getattr(resp, "from_cache", False) + if logger.getEffectiveLevel() > logging.INFO: + show_progress = False + elif cached_resp: + show_progress = False + elif total_length > (40 * 1000): + show_progress = True + elif not total_length: + show_progress = True + else: + show_progress = False + + show_url = link.show_url + + def resp_read(chunk_size): + try: + # Special case for urllib3. + for chunk in resp.raw.stream( + chunk_size, + # We use decode_content=False here because we don't + # want urllib3 to mess with the raw bytes we get + # from the server. If we decompress inside of + # urllib3 then we cannot verify the checksum + # because the checksum will be of the compressed + # file. This breakage will only occur if the + # server adds a Content-Encoding header, which + # depends on how the server was configured: + # - Some servers will notice that the file isn't a + # compressible file and will leave the file alone + # and with an empty Content-Encoding + # - Some servers will notice that the file is + # already compressed and will leave the file + # alone and will add a Content-Encoding: gzip + # header + # - Some servers won't notice anything at all and + # will take a file that's already been compressed + # and compress it again and set the + # Content-Encoding: gzip header + # + # By setting this not to decode automatically we + # hope to eliminate problems with the second case. + decode_content=False): + yield chunk + except AttributeError: + # Standard file-like object. + while True: + chunk = resp.raw.read(chunk_size) + if not chunk: + break + yield chunk + + def written_chunks(chunks): + for chunk in chunks: + content_file.write(chunk) + yield chunk + + progress_indicator = _progress_indicator + + if link.netloc == PyPI.netloc: + url = show_url + else: + url = link.url_without_fragment + + if show_progress: # We don't show progress on cached responses + progress_indicator = DownloadProgressProvider(progress_bar, + max=total_length) + if total_length: + logger.info("Downloading %s (%s)", url, format_size(total_length)) + else: + logger.info("Downloading %s", url) + elif cached_resp: + logger.info("Using cached %s", url) + else: + logger.info("Downloading %s", url) + + logger.debug('Downloading from URL %s', link) + + downloaded_chunks = written_chunks( + progress_indicator( + resp_read(CONTENT_CHUNK_SIZE), + CONTENT_CHUNK_SIZE + ) + ) + if hashes: + hashes.check_against_chunks(downloaded_chunks) + else: + consume(downloaded_chunks) + + +def _copy_file(filename, location, link): + copy = True + download_location = os.path.join(location, link.filename) + if os.path.exists(download_location): + response = ask_path_exists( + 'The file %s exists. (i)gnore, (w)ipe, (b)ackup, (a)abort' % + display_path(download_location), ('i', 'w', 'b', 'a')) + if response == 'i': + copy = False + elif response == 'w': + logger.warning('Deleting %s', display_path(download_location)) + os.remove(download_location) + elif response == 'b': + dest_file = backup_dir(download_location) + logger.warning( + 'Backing up %s to %s', + display_path(download_location), + display_path(dest_file), + ) + shutil.move(download_location, dest_file) + elif response == 'a': + sys.exit(-1) + if copy: + shutil.copy(filename, download_location) + logger.info('Saved %s', display_path(download_location)) + + +def unpack_http_url(link, location, download_dir=None, + session=None, hashes=None, progress_bar="on"): + if session is None: + raise TypeError( + "unpack_http_url() missing 1 required keyword argument: 'session'" + ) + + with TempDirectory(kind="unpack") as temp_dir: + # If a download dir is specified, is the file already downloaded there? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, + download_dir, + hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + content_type = mimetypes.guess_type(from_path)[0] + else: + # let's download to a tmp dir + from_path, content_type = _download_http_url(link, + session, + temp_dir.path, + hashes, + progress_bar) + + # unpack the archive to the build dir location. even when only + # downloading archives, they have to be unpacked to parse dependencies + unpack_file(from_path, location, content_type, link) + + # a download dir is specified; let's copy the archive there + if download_dir and not already_downloaded_path: + _copy_file(from_path, download_dir, link) + + if not already_downloaded_path: + os.unlink(from_path) + + +def unpack_file_url(link, location, download_dir=None, hashes=None): + """Unpack link into location. + + If download_dir is provided and link points to a file, make a copy + of the link file inside download_dir. + """ + link_path = url_to_path(link.url_without_fragment) + + # If it's a url to a local directory + if is_dir_url(link): + if os.path.isdir(location): + rmtree(location) + shutil.copytree(link_path, location, symlinks=True) + if download_dir: + logger.info('Link is a directory, ignoring download_dir') + return + + # If --require-hashes is off, `hashes` is either empty, the + # link's embedded hash, or MissingHashes; it is required to + # match. If --require-hashes is on, we are satisfied by any + # hash in `hashes` matching: a URL-based or an option-based + # one; no internet-sourced hash will be in `hashes`. + if hashes: + hashes.check_against_path(link_path) + + # If a download dir is specified, is the file already there and valid? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, + download_dir, + hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + else: + from_path = link_path + + content_type = mimetypes.guess_type(from_path)[0] + + # unpack the archive to the build dir location. even when only downloading + # archives, they have to be unpacked to parse dependencies + unpack_file(from_path, location, content_type, link) + + # a download dir is specified and not already downloaded + if download_dir and not already_downloaded_path: + _copy_file(from_path, download_dir, link) + + +def _copy_dist_from_dir(link_path, location): + """Copy distribution files in `link_path` to `location`. + + Invoked when user requests to install a local directory. E.g.: + + pip install . + pip install ~/dev/git-repos/python-prompt-toolkit + + """ + + # Note: This is currently VERY SLOW if you have a lot of data in the + # directory, because it copies everything with `shutil.copytree`. + # What it should really do is build an sdist and install that. + # See https://github.com/pypa/pip/issues/2195 + + if os.path.isdir(location): + rmtree(location) + + # build an sdist + setup_py = 'setup.py' + sdist_args = [sys.executable] + sdist_args.append('-c') + sdist_args.append(SETUPTOOLS_SHIM % setup_py) + sdist_args.append('sdist') + sdist_args += ['--dist-dir', location] + logger.info('Running setup.py sdist for %s', link_path) + + with indent_log(): + call_subprocess(sdist_args, cwd=link_path, show_stdout=False) + + # unpack sdist into `location` + sdist = os.path.join(location, os.listdir(location)[0]) + logger.info('Unpacking sdist %s into %s', sdist, location) + unpack_file(sdist, location, content_type=None, link=None) + + +class PipXmlrpcTransport(xmlrpc_client.Transport): + """Provide a `xmlrpclib.Transport` implementation via a `PipSession` + object. + """ + + def __init__(self, index_url, session, use_datetime=False): + xmlrpc_client.Transport.__init__(self, use_datetime) + index_parts = urllib_parse.urlparse(index_url) + self._scheme = index_parts.scheme + self._session = session + + def request(self, host, handler, request_body, verbose=False): + parts = (self._scheme, host, handler, None, None, None) + url = urllib_parse.urlunparse(parts) + try: + headers = {'Content-Type': 'text/xml'} + response = self._session.post(url, data=request_body, + headers=headers, stream=True) + response.raise_for_status() + self.verbose = verbose + return self.parse_response(response.raw) + except requests.HTTPError as exc: + logger.critical( + "HTTP error %s while getting %s", + exc.response.status_code, url, + ) + raise + + +def unpack_url(link, location, download_dir=None, + only_download=False, session=None, hashes=None, + progress_bar="on"): + """Unpack link. + If link is a VCS link: + if only_download, export into download_dir and ignore location + else unpack into location + for other types of link: + - unpack into location + - if download_dir, copy the file into download_dir + - if only_download, mark location for deletion + + :param hashes: A Hashes object, one of whose embedded hashes must match, + or HashMismatch will be raised. If the Hashes is empty, no matches are + required, and unhashable types of requirements (like VCS ones, which + would ordinarily raise HashUnsupported) are allowed. + """ + # non-editable vcs urls + if is_vcs_url(link): + unpack_vcs_link(link, location) + + # file urls + elif is_file_url(link): + unpack_file_url(link, location, download_dir, hashes=hashes) + + # http urls + else: + if session is None: + session = PipSession() + + unpack_http_url( + link, + location, + download_dir, + session, + hashes=hashes, + progress_bar=progress_bar + ) + if only_download: + write_delete_marker_file(location) + + +def _download_http_url(link, session, temp_dir, hashes, progress_bar): + """Download link url into temp_dir using provided session""" + target_url = link.url.split('#', 1)[0] + try: + resp = session.get( + target_url, + # We use Accept-Encoding: identity here because requests + # defaults to accepting compressed responses. This breaks in + # a variety of ways depending on how the server is configured. + # - Some servers will notice that the file isn't a compressible + # file and will leave the file alone and with an empty + # Content-Encoding + # - Some servers will notice that the file is already + # compressed and will leave the file alone and will add a + # Content-Encoding: gzip header + # - Some servers won't notice anything at all and will take + # a file that's already been compressed and compress it again + # and set the Content-Encoding: gzip header + # By setting this to request only the identity encoding We're + # hoping to eliminate the third case. Hopefully there does not + # exist a server which when given a file will notice it is + # already compressed and that you're not asking for a + # compressed file and will then decompress it before sending + # because if that's the case I don't think it'll ever be + # possible to make this work. + headers={"Accept-Encoding": "identity"}, + stream=True, + ) + resp.raise_for_status() + except requests.HTTPError as exc: + logger.critical( + "HTTP error %s while getting %s", exc.response.status_code, link, + ) + raise + + content_type = resp.headers.get('content-type', '') + filename = link.filename # fallback + # Have a look at the Content-Disposition header for a better guess + content_disposition = resp.headers.get('content-disposition') + if content_disposition: + type, params = cgi.parse_header(content_disposition) + # We use ``or`` here because we don't want to use an "empty" value + # from the filename param. + filename = params.get('filename') or filename + ext = splitext(filename)[1] + if not ext: + ext = mimetypes.guess_extension(content_type) + if ext: + filename += ext + if not ext and link.url != resp.url: + ext = os.path.splitext(resp.url)[1] + if ext: + filename += ext + file_path = os.path.join(temp_dir, filename) + with open(file_path, 'wb') as content_file: + _download_url(resp, link, content_file, hashes, progress_bar) + return file_path, content_type + + +def _check_download_dir(link, download_dir, hashes): + """ Check download_dir for previously downloaded file with correct hash + If a correct file is found return its path else None + """ + download_path = os.path.join(download_dir, link.filename) + if os.path.exists(download_path): + # If already downloaded, does its hash match? + logger.info('File was already downloaded %s', download_path) + if hashes: + try: + hashes.check_against_path(download_path) + except HashMismatch: + logger.warning( + 'Previously-downloaded file %s has bad hash. ' + 'Re-downloading.', + download_path + ) + os.unlink(download_path) + return None + return download_path + return None diff --git a/winvenv/Lib/site-packages/pip/_internal/exceptions.py b/winvenv/Lib/site-packages/pip/_internal/exceptions.py new file mode 100644 index 0000000..f1ca6f3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/exceptions.py @@ -0,0 +1,268 @@ +"""Exceptions used throughout package""" +from __future__ import absolute_import + +from itertools import chain, groupby, repeat + +from pip._vendor.six import iteritems + + +class PipError(Exception): + """Base pip exception""" + + +class ConfigurationError(PipError): + """General exception in configuration""" + + +class InstallationError(PipError): + """General exception during installation""" + + +class UninstallationError(PipError): + """General exception during uninstallation""" + + +class DistributionNotFound(InstallationError): + """Raised when a distribution cannot be found to satisfy a requirement""" + + +class RequirementsFileParseError(InstallationError): + """Raised when a general error occurs parsing a requirements file line.""" + + +class BestVersionAlreadyInstalled(PipError): + """Raised when the most up-to-date version of a package is already + installed.""" + + +class BadCommand(PipError): + """Raised when virtualenv or a command is not found""" + + +class CommandError(PipError): + """Raised when there is an error in command-line arguments""" + + +class PreviousBuildDirError(PipError): + """Raised when there's a previous conflicting build directory""" + + +class InvalidWheelFilename(InstallationError): + """Invalid wheel filename.""" + + +class UnsupportedWheel(InstallationError): + """Unsupported wheel.""" + + +class HashErrors(InstallationError): + """Multiple HashError instances rolled into one for reporting""" + + def __init__(self): + self.errors = [] + + def append(self, error): + self.errors.append(error) + + def __str__(self): + lines = [] + self.errors.sort(key=lambda e: e.order) + for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__): + lines.append(cls.head) + lines.extend(e.body() for e in errors_of_cls) + if lines: + return '\n'.join(lines) + + def __nonzero__(self): + return bool(self.errors) + + def __bool__(self): + return self.__nonzero__() + + +class HashError(InstallationError): + """ + A failure to verify a package against known-good hashes + + :cvar order: An int sorting hash exception classes by difficulty of + recovery (lower being harder), so the user doesn't bother fretting + about unpinned packages when he has deeper issues, like VCS + dependencies, to deal with. Also keeps error reports in a + deterministic order. + :cvar head: A section heading for display above potentially many + exceptions of this kind + :ivar req: The InstallRequirement that triggered this error. This is + pasted on after the exception is instantiated, because it's not + typically available earlier. + + """ + req = None + head = '' + + def body(self): + """Return a summary of me for display under the heading. + + This default implementation simply prints a description of the + triggering requirement. + + :param req: The InstallRequirement that provoked this error, with + populate_link() having already been called + + """ + return ' %s' % self._requirement_name() + + def __str__(self): + return '%s\n%s' % (self.head, self.body()) + + def _requirement_name(self): + """Return a description of the requirement that triggered me. + + This default implementation returns long description of the req, with + line numbers + + """ + return str(self.req) if self.req else 'unknown package' + + +class VcsHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 0 + head = ("Can't verify hashes for these requirements because we don't " + "have a way to hash version control repositories:") + + +class DirectoryUrlHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 1 + head = ("Can't verify hashes for these file:// requirements because they " + "point to directories:") + + +class HashMissing(HashError): + """A hash was needed for a requirement but is absent.""" + + order = 2 + head = ('Hashes are required in --require-hashes mode, but they are ' + 'missing from some requirements. Here is a list of those ' + 'requirements along with the hashes their downloaded archives ' + 'actually had. Add lines like these to your requirements files to ' + 'prevent tampering. (If you did not enable --require-hashes ' + 'manually, note that it turns on automatically when any package ' + 'has a hash.)') + + def __init__(self, gotten_hash): + """ + :param gotten_hash: The hash of the (possibly malicious) archive we + just downloaded + """ + self.gotten_hash = gotten_hash + + def body(self): + # Dodge circular import. + from pip._internal.utils.hashes import FAVORITE_HASH + + package = None + if self.req: + # In the case of URL-based requirements, display the original URL + # seen in the requirements file rather than the package name, + # so the output can be directly copied into the requirements file. + package = (self.req.original_link if self.req.original_link + # In case someone feeds something downright stupid + # to InstallRequirement's constructor. + else getattr(self.req, 'req', None)) + return ' %s --hash=%s:%s' % (package or 'unknown package', + FAVORITE_HASH, + self.gotten_hash) + + +class HashUnpinned(HashError): + """A requirement had a hash specified but was not pinned to a specific + version.""" + + order = 3 + head = ('In --require-hashes mode, all requirements must have their ' + 'versions pinned with ==. These do not:') + + +class HashMismatch(HashError): + """ + Distribution file hash values don't match. + + :ivar package_name: The name of the package that triggered the hash + mismatch. Feel free to write to this after the exception is raise to + improve its error message. + + """ + order = 4 + head = ('THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS ' + 'FILE. If you have updated the package versions, please update ' + 'the hashes. Otherwise, examine the package contents carefully; ' + 'someone may have tampered with them.') + + def __init__(self, allowed, gots): + """ + :param allowed: A dict of algorithm names pointing to lists of allowed + hex digests + :param gots: A dict of algorithm names pointing to hashes we + actually got from the files under suspicion + """ + self.allowed = allowed + self.gots = gots + + def body(self): + return ' %s:\n%s' % (self._requirement_name(), + self._hash_comparison()) + + def _hash_comparison(self): + """ + Return a comparison of actual and expected hash values. + + Example:: + + Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde + or 123451234512345123451234512345123451234512345 + Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef + + """ + def hash_then_or(hash_name): + # For now, all the decent hashes have 6-char names, so we can get + # away with hard-coding space literals. + return chain([hash_name], repeat(' or')) + + lines = [] + for hash_name, expecteds in iteritems(self.allowed): + prefix = hash_then_or(hash_name) + lines.extend((' Expected %s %s' % (next(prefix), e)) + for e in expecteds) + lines.append(' Got %s\n' % + self.gots[hash_name].hexdigest()) + prefix = ' or' + return '\n'.join(lines) + + +class UnsupportedPythonVersion(InstallationError): + """Unsupported python version according to Requires-Python package + metadata.""" + + +class ConfigurationFileCouldNotBeLoaded(ConfigurationError): + """When there are errors while loading a configuration file + """ + + def __init__(self, reason="could not be loaded", fname=None, error=None): + super(ConfigurationFileCouldNotBeLoaded, self).__init__(error) + self.reason = reason + self.fname = fname + self.error = error + + def __str__(self): + if self.fname is not None: + message_part = " in {}.".format(self.fname) + else: + assert self.error is not None + message_part = ".\n{}\n".format(self.error.message) + return "Configuration file {}{}".format(self.reason, message_part) diff --git a/winvenv/Lib/site-packages/pip/_internal/index.py b/winvenv/Lib/site-packages/pip/_internal/index.py new file mode 100644 index 0000000..8c2f24f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/index.py @@ -0,0 +1,899 @@ +"""Routines related to PyPI, indexes""" +from __future__ import absolute_import + +import cgi +import itertools +import logging +import mimetypes +import os +import posixpath +import re +import sys +from collections import namedtuple + +from pip._vendor import html5lib, requests, six +from pip._vendor.distlib.compat import unescape +from pip._vendor.packaging import specifiers +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.requests.exceptions import SSLError +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.download import HAS_TLS, is_url, path_to_url, url_to_path +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, DistributionNotFound, InvalidWheelFilename, + UnsupportedWheel, +) +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.models.link import Link +from pip._internal.pep425tags import get_supported +from pip._internal.utils.compat import ipaddress +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + ARCHIVE_EXTENSIONS, SUPPORTED_EXTENSIONS, normalize_path, + remove_auth_from_url, +) +from pip._internal.utils.packaging import check_requires_python +from pip._internal.wheel import Wheel, wheel_ext + +__all__ = ['FormatControl', 'PackageFinder'] + + +SECURE_ORIGINS = [ + # protocol, hostname, port + # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) + ("https", "*", "*"), + ("*", "localhost", "*"), + ("*", "127.0.0.0/8", "*"), + ("*", "::1/128", "*"), + ("file", "*", None), + # ssh is always secure. + ("ssh", "*", "*"), +] + + +logger = logging.getLogger(__name__) + + +def _get_content_type(url, session): + """Get the Content-Type of the given url, using a HEAD request""" + scheme, netloc, path, query, fragment = urllib_parse.urlsplit(url) + if scheme not in {'http', 'https'}: + # FIXME: some warning or something? + # assertion error? + return '' + + resp = session.head(url, allow_redirects=True) + resp.raise_for_status() + + return resp.headers.get("Content-Type", "") + + +def _handle_get_page_fail(link, reason, url, meth=None): + if meth is None: + meth = logger.debug + meth("Could not fetch URL %s: %s - skipping", link, reason) + + +def _get_html_page(link, session=None): + if session is None: + raise TypeError( + "_get_html_page() missing 1 required keyword argument: 'session'" + ) + + url = link.url + url = url.split('#', 1)[0] + + # Check for VCS schemes that do not support lookup as web pages. + from pip._internal.vcs import VcsSupport + for scheme in VcsSupport.schemes: + if url.lower().startswith(scheme) and url[len(scheme)] in '+:': + logger.debug('Cannot look at %s URL %s', scheme, link) + return None + + try: + filename = link.filename + for bad_ext in ARCHIVE_EXTENSIONS: + if filename.endswith(bad_ext): + content_type = _get_content_type(url, session=session) + if content_type.lower().startswith('text/html'): + break + else: + logger.debug( + 'Skipping page %s because of Content-Type: %s', + link, + content_type, + ) + return + + logger.debug('Getting page %s', url) + + # Tack index.html onto file:// URLs that point to directories + (scheme, netloc, path, params, query, fragment) = \ + urllib_parse.urlparse(url) + if (scheme == 'file' and + os.path.isdir(urllib_request.url2pathname(path))): + # add trailing slash if not present so urljoin doesn't trim + # final segment + if not url.endswith('/'): + url += '/' + url = urllib_parse.urljoin(url, 'index.html') + logger.debug(' file: URL is directory, getting %s', url) + + resp = session.get( + url, + headers={ + "Accept": "text/html", + # We don't want to blindly returned cached data for + # /simple/, because authors generally expecting that + # twine upload && pip install will function, but if + # they've done a pip install in the last ~10 minutes + # it won't. Thus by setting this to zero we will not + # blindly use any cached data, however the benefit of + # using max-age=0 instead of no-cache, is that we will + # still support conditional requests, so we will still + # minimize traffic sent in cases where the page hasn't + # changed at all, we will just always incur the round + # trip for the conditional GET now instead of only + # once per 10 minutes. + # For more information, please see pypa/pip#5670. + "Cache-Control": "max-age=0", + }, + ) + resp.raise_for_status() + + # The check for archives above only works if the url ends with + # something that looks like an archive. However that is not a + # requirement of an url. Unless we issue a HEAD request on every + # url we cannot know ahead of time for sure if something is HTML + # or not. However we can check after we've downloaded it. + content_type = resp.headers.get('Content-Type', 'unknown') + if not content_type.lower().startswith("text/html"): + logger.debug( + 'Skipping page %s because of Content-Type: %s', + link, + content_type, + ) + return + + inst = HTMLPage(resp.content, resp.url, resp.headers) + except requests.HTTPError as exc: + _handle_get_page_fail(link, exc, url) + except SSLError as exc: + reason = "There was a problem confirming the ssl certificate: " + reason += str(exc) + _handle_get_page_fail(link, reason, url, meth=logger.info) + except requests.ConnectionError as exc: + _handle_get_page_fail(link, "connection error: %s" % exc, url) + except requests.Timeout: + _handle_get_page_fail(link, "timed out", url) + else: + return inst + + +class PackageFinder(object): + """This finds packages. + + This is meant to match easy_install's technique for looking for + packages, by reading pages and looking for appropriate links. + """ + + def __init__(self, find_links, index_urls, allow_all_prereleases=False, + trusted_hosts=None, process_dependency_links=False, + session=None, format_control=None, platform=None, + versions=None, abi=None, implementation=None, + prefer_binary=False): + """Create a PackageFinder. + + :param format_control: A FormatControl object or None. Used to control + the selection of source packages / binary packages when consulting + the index and links. + :param platform: A string or None. If None, searches for packages + that are supported by the current system. Otherwise, will find + packages that can be built on the platform passed in. These + packages will only be downloaded for distribution: they will + not be built locally. + :param versions: A list of strings or None. This is passed directly + to pep425tags.py in the get_supported() method. + :param abi: A string or None. This is passed directly + to pep425tags.py in the get_supported() method. + :param implementation: A string or None. This is passed directly + to pep425tags.py in the get_supported() method. + """ + if session is None: + raise TypeError( + "PackageFinder() missing 1 required keyword argument: " + "'session'" + ) + + # Build find_links. If an argument starts with ~, it may be + # a local file relative to a home directory. So try normalizing + # it and if it exists, use the normalized version. + # This is deliberately conservative - it might be fine just to + # blindly normalize anything starting with a ~... + self.find_links = [] + for link in find_links: + if link.startswith('~'): + new_link = normalize_path(link) + if os.path.exists(new_link): + link = new_link + self.find_links.append(link) + + self.index_urls = index_urls + self.dependency_links = [] + + # These are boring links that have already been logged somehow: + self.logged_links = set() + + self.format_control = format_control or FormatControl(set(), set()) + + # Domains that we won't emit warnings for when not using HTTPS + self.secure_origins = [ + ("*", host, "*") + for host in (trusted_hosts if trusted_hosts else []) + ] + + # Do we want to allow _all_ pre-releases? + self.allow_all_prereleases = allow_all_prereleases + + # Do we process dependency links? + self.process_dependency_links = process_dependency_links + + # The Session we'll use to make requests + self.session = session + + # The valid tags to check potential found wheel candidates against + self.valid_tags = get_supported( + versions=versions, + platform=platform, + abi=abi, + impl=implementation, + ) + + # Do we prefer old, but valid, binary dist over new source dist + self.prefer_binary = prefer_binary + + # If we don't have TLS enabled, then WARN if anyplace we're looking + # relies on TLS. + if not HAS_TLS: + for link in itertools.chain(self.index_urls, self.find_links): + parsed = urllib_parse.urlparse(link) + if parsed.scheme == "https": + logger.warning( + "pip is configured with locations that require " + "TLS/SSL, however the ssl module in Python is not " + "available." + ) + break + + def get_formatted_locations(self): + lines = [] + if self.index_urls and self.index_urls != [PyPI.simple_url]: + lines.append( + "Looking in indexes: {}".format(", ".join( + remove_auth_from_url(url) for url in self.index_urls)) + ) + if self.find_links: + lines.append( + "Looking in links: {}".format(", ".join(self.find_links)) + ) + return "\n".join(lines) + + def add_dependency_links(self, links): + # FIXME: this shouldn't be global list this, it should only + # apply to requirements of the package that specifies the + # dependency_links value + # FIXME: also, we should track comes_from (i.e., use Link) + if self.process_dependency_links: + deprecated( + "Dependency Links processing has been deprecated and will be " + "removed in a future release.", + replacement="PEP 508 URL dependencies", + gone_in="18.2", + issue=4187, + ) + self.dependency_links.extend(links) + + @staticmethod + def _sort_locations(locations, expand_dir=False): + """ + Sort locations into "files" (archives) and "urls", and return + a pair of lists (files,urls) + """ + files = [] + urls = [] + + # puts the url for the given file path into the appropriate list + def sort_path(path): + url = path_to_url(path) + if mimetypes.guess_type(url, strict=False)[0] == 'text/html': + urls.append(url) + else: + files.append(url) + + for url in locations: + + is_local_path = os.path.exists(url) + is_file_url = url.startswith('file:') + + if is_local_path or is_file_url: + if is_local_path: + path = url + else: + path = url_to_path(url) + if os.path.isdir(path): + if expand_dir: + path = os.path.realpath(path) + for item in os.listdir(path): + sort_path(os.path.join(path, item)) + elif is_file_url: + urls.append(url) + elif os.path.isfile(path): + sort_path(path) + else: + logger.warning( + "Url '%s' is ignored: it is neither a file " + "nor a directory.", url, + ) + elif is_url(url): + # Only add url with clear scheme + urls.append(url) + else: + logger.warning( + "Url '%s' is ignored. It is either a non-existing " + "path or lacks a specific scheme.", url, + ) + + return files, urls + + def _candidate_sort_key(self, candidate): + """ + Function used to generate link sort key for link tuples. + The greater the return value, the more preferred it is. + If not finding wheels, then sorted by version only. + If finding wheels, then the sort order is by version, then: + 1. existing installs + 2. wheels ordered via Wheel.support_index_min(self.valid_tags) + 3. source archives + If prefer_binary was set, then all wheels are sorted above sources. + Note: it was considered to embed this logic into the Link + comparison operators, but then different sdist links + with the same version, would have to be considered equal + """ + support_num = len(self.valid_tags) + build_tag = tuple() + binary_preference = 0 + if candidate.location.is_wheel: + # can raise InvalidWheelFilename + wheel = Wheel(candidate.location.filename) + if not wheel.supported(self.valid_tags): + raise UnsupportedWheel( + "%s is not a supported wheel for this platform. It " + "can't be sorted." % wheel.filename + ) + if self.prefer_binary: + binary_preference = 1 + pri = -(wheel.support_index_min(self.valid_tags)) + if wheel.build_tag is not None: + match = re.match(r'^(\d+)(.*)$', wheel.build_tag) + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) + else: # sdist + pri = -(support_num) + return (binary_preference, candidate.version, build_tag, pri) + + def _validate_secure_origin(self, logger, location): + # Determine if this url used a secure transport mechanism + parsed = urllib_parse.urlparse(str(location)) + origin = (parsed.scheme, parsed.hostname, parsed.port) + + # The protocol to use to see if the protocol matches. + # Don't count the repository type as part of the protocol: in + # cases such as "git+ssh", only use "ssh". (I.e., Only verify against + # the last scheme.) + protocol = origin[0].rsplit('+', 1)[-1] + + # Determine if our origin is a secure origin by looking through our + # hardcoded list of secure origins, as well as any additional ones + # configured on this PackageFinder instance. + for secure_origin in (SECURE_ORIGINS + self.secure_origins): + if protocol != secure_origin[0] and secure_origin[0] != "*": + continue + + try: + # We need to do this decode dance to ensure that we have a + # unicode object, even on Python 2.x. + addr = ipaddress.ip_address( + origin[1] + if ( + isinstance(origin[1], six.text_type) or + origin[1] is None + ) + else origin[1].decode("utf8") + ) + network = ipaddress.ip_network( + secure_origin[1] + if isinstance(secure_origin[1], six.text_type) + else secure_origin[1].decode("utf8") + ) + except ValueError: + # We don't have both a valid address or a valid network, so + # we'll check this origin against hostnames. + if (origin[1] and + origin[1].lower() != secure_origin[1].lower() and + secure_origin[1] != "*"): + continue + else: + # We have a valid address and network, so see if the address + # is contained within the network. + if addr not in network: + continue + + # Check to see if the port patches + if (origin[2] != secure_origin[2] and + secure_origin[2] != "*" and + secure_origin[2] is not None): + continue + + # If we've gotten here, then this origin matches the current + # secure origin and we should return True + return True + + # If we've gotten to this point, then the origin isn't secure and we + # will not accept it as a valid location to search. We will however + # log a warning that we are ignoring it. + logger.warning( + "The repository located at %s is not a trusted or secure host and " + "is being ignored. If this repository is available via HTTPS we " + "recommend you use HTTPS instead, otherwise you may silence " + "this warning and allow it anyway with '--trusted-host %s'.", + parsed.hostname, + parsed.hostname, + ) + + return False + + def _get_index_urls_locations(self, project_name): + """Returns the locations found via self.index_urls + + Checks the url_name on the main (first in the list) index and + use this url_name to produce all locations + """ + + def mkurl_pypi_url(url): + loc = posixpath.join( + url, + urllib_parse.quote(canonicalize_name(project_name))) + # For maximum compatibility with easy_install, ensure the path + # ends in a trailing slash. Although this isn't in the spec + # (and PyPI can handle it without the slash) some other index + # implementations might break if they relied on easy_install's + # behavior. + if not loc.endswith('/'): + loc = loc + '/' + return loc + + return [mkurl_pypi_url(url) for url in self.index_urls] + + def find_all_candidates(self, project_name): + """Find all available InstallationCandidate for project_name + + This checks index_urls, find_links and dependency_links. + All versions found are returned as an InstallationCandidate list. + + See _link_package_versions for details on which files are accepted + """ + index_locations = self._get_index_urls_locations(project_name) + index_file_loc, index_url_loc = self._sort_locations(index_locations) + fl_file_loc, fl_url_loc = self._sort_locations( + self.find_links, expand_dir=True, + ) + dep_file_loc, dep_url_loc = self._sort_locations(self.dependency_links) + + file_locations = (Link(url) for url in itertools.chain( + index_file_loc, fl_file_loc, dep_file_loc, + )) + + # We trust every url that the user has given us whether it was given + # via --index-url or --find-links + # We explicitly do not trust links that came from dependency_links + # We want to filter out any thing which does not have a secure origin. + url_locations = [ + link for link in itertools.chain( + (Link(url) for url in index_url_loc), + (Link(url) for url in fl_url_loc), + (Link(url) for url in dep_url_loc), + ) + if self._validate_secure_origin(logger, link) + ] + + logger.debug('%d location(s) to search for versions of %s:', + len(url_locations), project_name) + + for location in url_locations: + logger.debug('* %s', location) + + canonical_name = canonicalize_name(project_name) + formats = self.format_control.get_allowed_formats(canonical_name) + search = Search(project_name, canonical_name, formats) + find_links_versions = self._package_versions( + # We trust every directly linked archive in find_links + (Link(url, '-f') for url in self.find_links), + search + ) + + page_versions = [] + for page in self._get_pages(url_locations, project_name): + logger.debug('Analyzing links from page %s', page.url) + with indent_log(): + page_versions.extend( + self._package_versions(page.iter_links(), search) + ) + + dependency_versions = self._package_versions( + (Link(url) for url in self.dependency_links), search + ) + if dependency_versions: + logger.debug( + 'dependency_links found: %s', + ', '.join([ + version.location.url for version in dependency_versions + ]) + ) + + file_versions = self._package_versions(file_locations, search) + if file_versions: + file_versions.sort(reverse=True) + logger.debug( + 'Local files found: %s', + ', '.join([ + url_to_path(candidate.location.url) + for candidate in file_versions + ]) + ) + + # This is an intentional priority ordering + return ( + file_versions + find_links_versions + page_versions + + dependency_versions + ) + + def find_requirement(self, req, upgrade): + """Try to find a Link matching req + + Expects req, an InstallRequirement and upgrade, a boolean + Returns a Link if found, + Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise + """ + all_candidates = self.find_all_candidates(req.name) + + # Filter out anything which doesn't match our specifier + compatible_versions = set( + req.specifier.filter( + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + [str(c.version) for c in all_candidates], + prereleases=( + self.allow_all_prereleases + if self.allow_all_prereleases else None + ), + ) + ) + applicable_candidates = [ + # Again, converting to str to deal with debundling. + c for c in all_candidates if str(c.version) in compatible_versions + ] + + if applicable_candidates: + best_candidate = max(applicable_candidates, + key=self._candidate_sort_key) + else: + best_candidate = None + + if req.satisfied_by is not None: + installed_version = parse_version(req.satisfied_by.version) + else: + installed_version = None + + if installed_version is None and best_candidate is None: + logger.critical( + 'Could not find a version that satisfies the requirement %s ' + '(from versions: %s)', + req, + ', '.join( + sorted( + {str(c.version) for c in all_candidates}, + key=parse_version, + ) + ) + ) + + raise DistributionNotFound( + 'No matching distribution found for %s' % req + ) + + best_installed = False + if installed_version and ( + best_candidate is None or + best_candidate.version <= installed_version): + best_installed = True + + if not upgrade and installed_version is not None: + if best_installed: + logger.debug( + 'Existing installed version (%s) is most up-to-date and ' + 'satisfies requirement', + installed_version, + ) + else: + logger.debug( + 'Existing installed version (%s) satisfies requirement ' + '(most up-to-date version is %s)', + installed_version, + best_candidate.version, + ) + return None + + if best_installed: + # We have an existing version, and its the best version + logger.debug( + 'Installed version (%s) is most up-to-date (past versions: ' + '%s)', + installed_version, + ', '.join(sorted(compatible_versions, key=parse_version)) or + "none", + ) + raise BestVersionAlreadyInstalled + + logger.debug( + 'Using version %s (newest of versions: %s)', + best_candidate.version, + ', '.join(sorted(compatible_versions, key=parse_version)) + ) + return best_candidate.location + + def _get_pages(self, locations, project_name): + """ + Yields (page, page_url) from the given locations, skipping + locations that have errors. + """ + seen = set() + for location in locations: + if location in seen: + continue + seen.add(location) + + page = self._get_page(location) + if page is None: + continue + + yield page + + _py_version_re = re.compile(r'-py([123]\.?[0-9]?)$') + + def _sort_links(self, links): + """ + Returns elements of links in order, non-egg links first, egg links + second, while eliminating duplicates + """ + eggs, no_eggs = [], [] + seen = set() + for link in links: + if link not in seen: + seen.add(link) + if link.egg_fragment: + eggs.append(link) + else: + no_eggs.append(link) + return no_eggs + eggs + + def _package_versions(self, links, search): + result = [] + for link in self._sort_links(links): + v = self._link_package_versions(link, search) + if v is not None: + result.append(v) + return result + + def _log_skipped_link(self, link, reason): + if link not in self.logged_links: + logger.debug('Skipping link %s; %s', link, reason) + self.logged_links.add(link) + + def _link_package_versions(self, link, search): + """Return an InstallationCandidate or None""" + version = None + if link.egg_fragment: + egg_info = link.egg_fragment + ext = link.ext + else: + egg_info, ext = link.splitext() + if not ext: + self._log_skipped_link(link, 'not a file') + return + if ext not in SUPPORTED_EXTENSIONS: + self._log_skipped_link( + link, 'unsupported archive format: %s' % ext, + ) + return + if "binary" not in search.formats and ext == wheel_ext: + self._log_skipped_link( + link, 'No binaries permitted for %s' % search.supplied, + ) + return + if "macosx10" in link.path and ext == '.zip': + self._log_skipped_link(link, 'macosx10 one') + return + if ext == wheel_ext: + try: + wheel = Wheel(link.filename) + except InvalidWheelFilename: + self._log_skipped_link(link, 'invalid wheel filename') + return + if canonicalize_name(wheel.name) != search.canonical: + self._log_skipped_link( + link, 'wrong project name (not %s)' % search.supplied) + return + + if not wheel.supported(self.valid_tags): + self._log_skipped_link( + link, 'it is not compatible with this Python') + return + + version = wheel.version + + # This should be up by the search.ok_binary check, but see issue 2700. + if "source" not in search.formats and ext != wheel_ext: + self._log_skipped_link( + link, 'No sources permitted for %s' % search.supplied, + ) + return + + if not version: + version = egg_info_matches(egg_info, search.supplied, link) + if version is None: + self._log_skipped_link( + link, 'Missing project version for %s' % search.supplied) + return + + match = self._py_version_re.search(version) + if match: + version = version[:match.start()] + py_version = match.group(1) + if py_version != sys.version[:3]: + self._log_skipped_link( + link, 'Python version is incorrect') + return + try: + support_this_python = check_requires_python(link.requires_python) + except specifiers.InvalidSpecifier: + logger.debug("Package %s has an invalid Requires-Python entry: %s", + link.filename, link.requires_python) + support_this_python = True + + if not support_this_python: + logger.debug("The package %s is incompatible with the python" + "version in use. Acceptable python versions are:%s", + link, link.requires_python) + return + logger.debug('Found link %s, version: %s', link, version) + + return InstallationCandidate(search.supplied, version, link) + + def _get_page(self, link): + return _get_html_page(link, session=self.session) + + +def egg_info_matches( + egg_info, search_name, link, + _egg_info_re=re.compile(r'([a-z0-9_.]+)-([a-z0-9_.!+-]+)', re.I)): + """Pull the version part out of a string. + + :param egg_info: The string to parse. E.g. foo-2.1 + :param search_name: The name of the package this belongs to. None to + infer the name. Note that this cannot unambiguously parse strings + like foo-2-2 which might be foo, 2-2 or foo-2, 2. + :param link: The link the string came from, for logging on failure. + """ + match = _egg_info_re.search(egg_info) + if not match: + logger.debug('Could not parse version from link: %s', link) + return None + if search_name is None: + full_match = match.group(0) + return full_match.split('-', 1)[-1] + name = match.group(0).lower() + # To match the "safe" name that pkg_resources creates: + name = name.replace('_', '-') + # project name and version must be separated by a dash + look_for = search_name.lower() + "-" + if name.startswith(look_for): + return match.group(0)[len(look_for):] + else: + return None + + +def _determine_base_url(document, page_url): + """Determine the HTML document's base URL. + + This looks for a ```` tag in the HTML document. If present, its href + attribute denotes the base URL of anchor tags in the document. If there is + no such tag (or if it does not have a valid href attribute), the HTML + file's URL is used as the base URL. + + :param document: An HTML document representation. The current + implementation expects the result of ``html5lib.parse()``. + :param page_url: The URL of the HTML document. + """ + for base in document.findall(".//base"): + href = base.get("href") + if href is not None: + return href + return page_url + + +def _get_encoding_from_headers(headers): + """Determine if we have any encoding information in our headers. + """ + if headers and "Content-Type" in headers: + content_type, params = cgi.parse_header(headers["Content-Type"]) + if "charset" in params: + return params['charset'] + return None + + +_CLEAN_LINK_RE = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + +def _clean_link(url): + """Makes sure a link is fully encoded. That is, if a ' ' shows up in + the link, it will be rewritten to %20 (while not over-quoting + % or other characters).""" + return _CLEAN_LINK_RE.sub(lambda match: '%%%2x' % ord(match.group(0)), url) + + +class HTMLPage(object): + """Represents one page, along with its URL""" + + def __init__(self, content, url, headers=None): + self.content = content + self.url = url + self.headers = headers + + def __str__(self): + return self.url + + def iter_links(self): + """Yields all links in the page""" + document = html5lib.parse( + self.content, + transport_encoding=_get_encoding_from_headers(self.headers), + namespaceHTMLElements=False, + ) + base_url = _determine_base_url(document, self.url) + for anchor in document.findall(".//a"): + if anchor.get("href"): + href = anchor.get("href") + url = _clean_link(urllib_parse.urljoin(base_url, href)) + pyrequire = anchor.get('data-requires-python') + pyrequire = unescape(pyrequire) if pyrequire else None + yield Link(url, self.url, requires_python=pyrequire) + + +Search = namedtuple('Search', 'supplied canonical formats') +"""Capture key aspects of a search. + +:attribute supplied: The user supplied package. +:attribute canonical: The canonical package name. +:attribute formats: The formats allowed for this package. Should be a set + with 'binary' or 'source' or both in it. +""" diff --git a/winvenv/Lib/site-packages/pip/_internal/locations.py b/winvenv/Lib/site-packages/pip/_internal/locations.py new file mode 100644 index 0000000..183aaa3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/locations.py @@ -0,0 +1,194 @@ +"""Locations where we look for configs, install stuff, etc""" +from __future__ import absolute_import + +import os +import os.path +import platform +import site +import sys +import sysconfig +from distutils import sysconfig as distutils_sysconfig +from distutils.command.install import SCHEME_KEYS # type: ignore + +from pip._internal.utils import appdirs +from pip._internal.utils.compat import WINDOWS, expanduser + +# Application Directories +USER_CACHE_DIR = appdirs.user_cache_dir("pip") + + +DELETE_MARKER_MESSAGE = '''\ +This file is placed here by pip to indicate the source was put +here by pip. + +Once this package is successfully installed this source code will be +deleted (unless you remove this file). +''' +PIP_DELETE_MARKER_FILENAME = 'pip-delete-this-directory.txt' + + +def write_delete_marker_file(directory): + """ + Write the pip delete marker file into this directory. + """ + filepath = os.path.join(directory, PIP_DELETE_MARKER_FILENAME) + with open(filepath, 'w') as marker_fp: + marker_fp.write(DELETE_MARKER_MESSAGE) + + +def running_under_virtualenv(): + """ + Return True if we're running inside a virtualenv, False otherwise. + + """ + if hasattr(sys, 'real_prefix'): + return True + elif sys.prefix != getattr(sys, "base_prefix", sys.prefix): + return True + + return False + + +def virtualenv_no_global(): + """ + Return True if in a venv and no system site packages. + """ + # this mirrors the logic in virtualenv.py for locating the + # no-global-site-packages.txt file + site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) + no_global_file = os.path.join(site_mod_dir, 'no-global-site-packages.txt') + if running_under_virtualenv() and os.path.isfile(no_global_file): + return True + + +if running_under_virtualenv(): + src_prefix = os.path.join(sys.prefix, 'src') +else: + # FIXME: keep src in cwd for now (it is not a temporary folder) + try: + src_prefix = os.path.join(os.getcwd(), 'src') + except OSError: + # In case the current working directory has been renamed or deleted + sys.exit( + "The folder you are executing pip from can no longer be found." + ) + +# under macOS + virtualenv sys.prefix is not properly resolved +# it is something like /path/to/python/bin/.. +# Note: using realpath due to tmp dirs on OSX being symlinks +src_prefix = os.path.abspath(src_prefix) + +# FIXME doesn't account for venv linked to global site-packages + +site_packages = sysconfig.get_path("purelib") +# This is because of a bug in PyPy's sysconfig module, see +# https://bitbucket.org/pypy/pypy/issues/2506/sysconfig-returns-incorrect-paths +# for more information. +if platform.python_implementation().lower() == "pypy": + site_packages = distutils_sysconfig.get_python_lib() +try: + # Use getusersitepackages if this is present, as it ensures that the + # value is initialised properly. + user_site = site.getusersitepackages() +except AttributeError: + user_site = site.USER_SITE +user_dir = expanduser('~') +if WINDOWS: + bin_py = os.path.join(sys.prefix, 'Scripts') + bin_user = os.path.join(user_site, 'Scripts') + # buildout uses 'bin' on Windows too? + if not os.path.exists(bin_py): + bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') + + config_basename = 'pip.ini' + + legacy_storage_dir = os.path.join(user_dir, 'pip') + legacy_config_file = os.path.join( + legacy_storage_dir, + config_basename, + ) +else: + bin_py = os.path.join(sys.prefix, 'bin') + bin_user = os.path.join(user_site, 'bin') + + config_basename = 'pip.conf' + + legacy_storage_dir = os.path.join(user_dir, '.pip') + legacy_config_file = os.path.join( + legacy_storage_dir, + config_basename, + ) + # Forcing to use /usr/local/bin for standard macOS framework installs + # Also log to ~/Library/Logs/ for use with the Console.app log viewer + if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/': + bin_py = '/usr/local/bin' + +site_config_files = [ + os.path.join(path, config_basename) + for path in appdirs.site_config_dirs('pip') +] + +venv_config_file = os.path.join(sys.prefix, config_basename) +new_config_file = os.path.join(appdirs.user_config_dir("pip"), config_basename) + + +def distutils_scheme(dist_name, user=False, home=None, root=None, + isolated=False, prefix=None): + """ + Return a distutils install scheme + """ + from distutils.dist import Distribution + + scheme = {} + + if isolated: + extra_dist_args = {"script_args": ["--no-user-cfg"]} + else: + extra_dist_args = {} + dist_args = {'name': dist_name} + dist_args.update(extra_dist_args) + + d = Distribution(dist_args) + d.parse_config_files() + i = d.get_command_obj('install', create=True) + # NOTE: setting user or home has the side-effect of creating the home dir + # or user base for installations during finalize_options() + # ideally, we'd prefer a scheme class that has no side-effects. + assert not (user and prefix), "user={} prefix={}".format(user, prefix) + i.user = user or i.user + if user: + i.prefix = "" + i.prefix = prefix or i.prefix + i.home = home or i.home + i.root = root or i.root + i.finalize_options() + for key in SCHEME_KEYS: + scheme[key] = getattr(i, 'install_' + key) + + # install_lib specified in setup.cfg should install *everything* + # into there (i.e. it takes precedence over both purelib and + # platlib). Note, i.install_lib is *always* set after + # finalize_options(); we only want to override here if the user + # has explicitly requested it hence going back to the config + if 'install_lib' in d.get_option_dict('install'): + scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + + if running_under_virtualenv(): + scheme['headers'] = os.path.join( + sys.prefix, + 'include', + 'site', + 'python' + sys.version[:3], + dist_name, + ) + + if root is not None: + path_no_drive = os.path.splitdrive( + os.path.abspath(scheme["headers"]))[1] + scheme["headers"] = os.path.join( + root, + path_no_drive[1:], + ) + + return scheme diff --git a/winvenv/Lib/site-packages/pip/_internal/models/__init__.py b/winvenv/Lib/site-packages/pip/_internal/models/__init__.py new file mode 100644 index 0000000..7855226 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/models/__init__.py @@ -0,0 +1,2 @@ +"""A package that contains models that represent entities. +""" diff --git a/winvenv/Lib/site-packages/pip/_internal/models/candidate.py b/winvenv/Lib/site-packages/pip/_internal/models/candidate.py new file mode 100644 index 0000000..c736de6 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/models/candidate.py @@ -0,0 +1,23 @@ +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.utils.models import KeyBasedCompareMixin + + +class InstallationCandidate(KeyBasedCompareMixin): + """Represents a potential "candidate" for installation. + """ + + def __init__(self, project, version, location): + self.project = project + self.version = parse_version(version) + self.location = location + + super(InstallationCandidate, self).__init__( + key=(self.project, self.version, self.location), + defining_class=InstallationCandidate + ) + + def __repr__(self): + return "".format( + self.project, self.version, self.location, + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/models/format_control.py b/winvenv/Lib/site-packages/pip/_internal/models/format_control.py new file mode 100644 index 0000000..2748856 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/models/format_control.py @@ -0,0 +1,62 @@ +from pip._vendor.packaging.utils import canonicalize_name + + +class FormatControl(object): + """A helper class for controlling formats from which packages are installed. + If a field is falsy, it isn't set. If it is {':all:'}, it should match all + packages except those listed in the other field. Only one field can be set + to {':all:'} at a time. The rest of the time exact package name matches + are listed, with any given package only showing up in one field at a time. + """ + def __init__(self, no_binary=None, only_binary=None): + self.no_binary = set() if no_binary is None else no_binary + self.only_binary = set() if only_binary is None else only_binary + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return "{}({}, {})".format( + self.__class__.__name__, + self.no_binary, + self.only_binary + ) + + @staticmethod + def handle_mutual_excludes(value, target, other): + new = value.split(',') + while ':all:' in new: + other.clear() + target.clear() + target.add(':all:') + del new[:new.index(':all:') + 1] + # Without a none, we want to discard everything as :all: covers it + if ':none:' not in new: + return + for name in new: + if name == ':none:': + target.clear() + continue + name = canonicalize_name(name) + other.discard(name) + target.add(name) + + def get_allowed_formats(self, canonical_name): + result = {"binary", "source"} + if canonical_name in self.only_binary: + result.discard('source') + elif canonical_name in self.no_binary: + result.discard('binary') + elif ':all:' in self.only_binary: + result.discard('source') + elif ':all:' in self.no_binary: + result.discard('binary') + return frozenset(result) + + def disallow_binaries(self): + self.handle_mutual_excludes( + ':all:', self.no_binary, self.only_binary, + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/models/index.py b/winvenv/Lib/site-packages/pip/_internal/models/index.py new file mode 100644 index 0000000..870a315 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/models/index.py @@ -0,0 +1,29 @@ +from pip._vendor.six.moves.urllib import parse as urllib_parse + + +class PackageIndex(object): + """Represents a Package Index and provides easier access to endpoints + """ + + def __init__(self, url, file_storage_domain): + super(PackageIndex, self).__init__() + self.url = url + self.netloc = urllib_parse.urlsplit(url).netloc + self.simple_url = self._url_for_path('simple') + self.pypi_url = self._url_for_path('pypi') + + # This is part of a temporary hack used to block installs of PyPI + # packages which depend on external urls only necessary until PyPI can + # block such packages themselves + self.file_storage_domain = file_storage_domain + + def _url_for_path(self, path): + return urllib_parse.urljoin(self.url, path) + + +PyPI = PackageIndex( + 'https://pypi.org/', file_storage_domain='files.pythonhosted.org' +) +TestPyPI = PackageIndex( + 'https://test.pypi.org/', file_storage_domain='test-files.pythonhosted.org' +) diff --git a/winvenv/Lib/site-packages/pip/_internal/models/link.py b/winvenv/Lib/site-packages/pip/_internal/models/link.py new file mode 100644 index 0000000..5decb7c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/models/link.py @@ -0,0 +1,141 @@ +import posixpath +import re + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.download import path_to_url +from pip._internal.utils.misc import splitext +from pip._internal.utils.models import KeyBasedCompareMixin +from pip._internal.wheel import wheel_ext + + +class Link(KeyBasedCompareMixin): + """Represents a parsed link from a Package Index's simple URL + """ + + def __init__(self, url, comes_from=None, requires_python=None): + """ + url: + url of the resource pointed to (href of the link) + comes_from: + instance of HTMLPage where the link was found, or string. + requires_python: + String containing the `Requires-Python` metadata field, specified + in PEP 345. This may be specified by a data-requires-python + attribute in the HTML link tag, as described in PEP 503. + """ + + # url can be a UNC windows share + if url.startswith('\\\\'): + url = path_to_url(url) + + self.url = url + self.comes_from = comes_from + self.requires_python = requires_python if requires_python else None + + super(Link, self).__init__( + key=(self.url), + defining_class=Link + ) + + def __str__(self): + if self.requires_python: + rp = ' (requires-python:%s)' % self.requires_python + else: + rp = '' + if self.comes_from: + return '%s (from %s)%s' % (self.url, self.comes_from, rp) + else: + return str(self.url) + + def __repr__(self): + return '' % self + + @property + def filename(self): + _, netloc, path, _, _ = urllib_parse.urlsplit(self.url) + name = posixpath.basename(path.rstrip('/')) or netloc + name = urllib_parse.unquote(name) + assert name, ('URL %r produced no filename' % self.url) + return name + + @property + def scheme(self): + return urllib_parse.urlsplit(self.url)[0] + + @property + def netloc(self): + return urllib_parse.urlsplit(self.url)[1] + + @property + def path(self): + return urllib_parse.unquote(urllib_parse.urlsplit(self.url)[2]) + + def splitext(self): + return splitext(posixpath.basename(self.path.rstrip('/'))) + + @property + def ext(self): + return self.splitext()[1] + + @property + def url_without_fragment(self): + scheme, netloc, path, query, fragment = urllib_parse.urlsplit(self.url) + return urllib_parse.urlunsplit((scheme, netloc, path, query, None)) + + _egg_fragment_re = re.compile(r'[#&]egg=([^&]*)') + + @property + def egg_fragment(self): + match = self._egg_fragment_re.search(self.url) + if not match: + return None + return match.group(1) + + _subdirectory_fragment_re = re.compile(r'[#&]subdirectory=([^&]*)') + + @property + def subdirectory_fragment(self): + match = self._subdirectory_fragment_re.search(self.url) + if not match: + return None + return match.group(1) + + _hash_re = re.compile( + r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)' + ) + + @property + def hash(self): + match = self._hash_re.search(self.url) + if match: + return match.group(2) + return None + + @property + def hash_name(self): + match = self._hash_re.search(self.url) + if match: + return match.group(1) + return None + + @property + def show_url(self): + return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0]) + + @property + def is_wheel(self): + return self.ext == wheel_ext + + @property + def is_artifact(self): + """ + Determines if this points to an actual artifact (e.g. a tarball) or if + it points to an "abstract" thing like a path or a VCS location. + """ + from pip._internal.vcs import vcs + + if self.scheme in vcs.all_schemes: + return False + + return True diff --git a/winvenv/Lib/site-packages/pip/_internal/operations/__init__.py b/winvenv/Lib/site-packages/pip/_internal/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pip/_internal/operations/check.py b/winvenv/Lib/site-packages/pip/_internal/operations/check.py new file mode 100644 index 0000000..799257a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/operations/check.py @@ -0,0 +1,148 @@ +"""Validation of dependencies of packages +""" + +from collections import namedtuple + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.operations.prepare import make_abstract_dist +from pip._internal.utils.misc import get_installed_distributions +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from pip._internal.req.req_install import InstallRequirement # noqa: F401 + from typing import ( # noqa: F401 + Any, Callable, Dict, Iterator, Optional, Set, Tuple, List + ) + + # Shorthands + PackageSet = Dict[str, 'PackageDetails'] + Missing = Tuple[str, Any] + Conflicting = Tuple[str, str, Any] + + MissingDict = Dict[str, List[Missing]] + ConflictingDict = Dict[str, List[Conflicting]] + CheckResult = Tuple[MissingDict, ConflictingDict] + +PackageDetails = namedtuple('PackageDetails', ['version', 'requires']) + + +def create_package_set_from_installed(**kwargs): + # type: (**Any) -> PackageSet + """Converts a list of distributions into a PackageSet. + """ + # Default to using all packages installed on the system + if kwargs == {}: + kwargs = {"local_only": False, "skip": ()} + + package_set = {} + for dist in get_installed_distributions(**kwargs): + name = canonicalize_name(dist.project_name) + package_set[name] = PackageDetails(dist.version, dist.requires()) + return package_set + + +def check_package_set(package_set, should_ignore=None): + # type: (PackageSet, Optional[Callable[[str], bool]]) -> CheckResult + """Check if a package set is consistent + + If should_ignore is passed, it should be a callable that takes a + package name and returns a boolean. + """ + if should_ignore is None: + def should_ignore(name): + return False + + missing = dict() + conflicting = dict() + + for package_name in package_set: + # Info about dependencies of package_name + missing_deps = set() # type: Set[Missing] + conflicting_deps = set() # type: Set[Conflicting] + + if should_ignore(package_name): + continue + + for req in package_set[package_name].requires: + name = canonicalize_name(req.project_name) # type: str + + # Check if it's missing + if name not in package_set: + missed = True + if req.marker is not None: + missed = req.marker.evaluate() + if missed: + missing_deps.add((name, req)) + continue + + # Check if there's a conflict + version = package_set[name].version # type: str + if not req.specifier.contains(version, prereleases=True): + conflicting_deps.add((name, version, req)) + + if missing_deps: + missing[package_name] = sorted(missing_deps, key=str) + if conflicting_deps: + conflicting[package_name] = sorted(conflicting_deps, key=str) + + return missing, conflicting + + +def check_install_conflicts(to_install): + # type: (List[InstallRequirement]) -> Tuple[PackageSet, CheckResult] + """For checking if the dependency graph would be consistent after \ + installing given requirements + """ + # Start from the current state + package_set = create_package_set_from_installed() + # Install packages + would_be_installed = _simulate_installation_of(to_install, package_set) + + # Only warn about directly-dependent packages; create a whitelist of them + whitelist = _create_whitelist(would_be_installed, package_set) + + return ( + package_set, + check_package_set( + package_set, should_ignore=lambda name: name not in whitelist + ) + ) + + +# NOTE from @pradyunsg +# This required a minor update in dependency link handling logic over at +# operations.prepare.IsSDist.dist() to get it working +def _simulate_installation_of(to_install, package_set): + # type: (List[InstallRequirement], PackageSet) -> Set[str] + """Computes the version of packages after installing to_install. + """ + + # Keep track of packages that were installed + installed = set() + + # Modify it as installing requirement_set would (assuming no errors) + for inst_req in to_install: + dist = make_abstract_dist(inst_req).dist(finder=None) + name = canonicalize_name(dist.key) + package_set[name] = PackageDetails(dist.version, dist.requires()) + + installed.add(name) + + return installed + + +def _create_whitelist(would_be_installed, package_set): + # type: (Set[str], PackageSet) -> Set[str] + packages_affected = set(would_be_installed) + + for package_name in package_set: + if package_name in packages_affected: + continue + + for req in package_set[package_name].requires: + if canonicalize_name(req.name) in packages_affected: + packages_affected.add(package_name) + break + + return packages_affected diff --git a/winvenv/Lib/site-packages/pip/_internal/operations/freeze.py b/winvenv/Lib/site-packages/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..beb2feb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/operations/freeze.py @@ -0,0 +1,264 @@ +from __future__ import absolute_import + +import collections +import logging +import os +import re + +from pip._vendor import pkg_resources, six +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.pkg_resources import RequirementParseError + +from pip._internal.exceptions import InstallationError +from pip._internal.req.constructors import ( + install_req_from_editable, install_req_from_line, +) +from pip._internal.req.req_file import COMMENT_RE +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.misc import ( + dist_is_editable, get_installed_distributions, make_vcs_requirement_url, +) + +logger = logging.getLogger(__name__) + + +def freeze( + requirement=None, + find_links=None, local_only=None, user_only=None, skip_regex=None, + isolated=False, + wheel_cache=None, + exclude_editable=False, + skip=()): + find_links = find_links or [] + skip_match = None + + if skip_regex: + skip_match = re.compile(skip_regex).search + + dependency_links = [] + + for dist in pkg_resources.working_set: + if dist.has_metadata('dependency_links.txt'): + dependency_links.extend( + dist.get_metadata_lines('dependency_links.txt') + ) + for link in find_links: + if '#egg=' in link: + dependency_links.append(link) + for link in find_links: + yield '-f %s' % link + installations = {} + for dist in get_installed_distributions(local_only=local_only, + skip=(), + user_only=user_only): + try: + req = FrozenRequirement.from_dist( + dist, + dependency_links + ) + except RequirementParseError: + logger.warning( + "Could not parse requirement: %s", + dist.project_name + ) + continue + if exclude_editable and req.editable: + continue + installations[req.name] = req + + if requirement: + # the options that don't get turned into an InstallRequirement + # should only be emitted once, even if the same option is in multiple + # requirements files, so we need to keep track of what has been emitted + # so that we don't emit it again if it's seen again + emitted_options = set() + # keep track of which files a requirement is in so that we can + # give an accurate warning if a requirement appears multiple times. + req_files = collections.defaultdict(list) + for req_file_path in requirement: + with open(req_file_path) as req_file: + for line in req_file: + if (not line.strip() or + line.strip().startswith('#') or + (skip_match and skip_match(line)) or + line.startswith(( + '-r', '--requirement', + '-Z', '--always-unzip', + '-f', '--find-links', + '-i', '--index-url', + '--pre', + '--trusted-host', + '--process-dependency-links', + '--extra-index-url'))): + line = line.rstrip() + if line not in emitted_options: + emitted_options.add(line) + yield line + continue + + if line.startswith('-e') or line.startswith('--editable'): + if line.startswith('-e'): + line = line[2:].strip() + else: + line = line[len('--editable'):].strip().lstrip('=') + line_req = install_req_from_editable( + line, + isolated=isolated, + wheel_cache=wheel_cache, + ) + else: + line_req = install_req_from_line( + COMMENT_RE.sub('', line).strip(), + isolated=isolated, + wheel_cache=wheel_cache, + ) + + if not line_req.name: + logger.info( + "Skipping line in requirement file [%s] because " + "it's not clear what it would install: %s", + req_file_path, line.strip(), + ) + logger.info( + " (add #egg=PackageName to the URL to avoid" + " this warning)" + ) + elif line_req.name not in installations: + # either it's not installed, or it is installed + # but has been processed already + if not req_files[line_req.name]: + logger.warning( + "Requirement file [%s] contains %s, but that " + "package is not installed", + req_file_path, + COMMENT_RE.sub('', line).strip(), + ) + else: + req_files[line_req.name].append(req_file_path) + else: + yield str(installations[line_req.name]).rstrip() + del installations[line_req.name] + req_files[line_req.name].append(req_file_path) + + # Warn about requirements that were included multiple times (in a + # single requirements file or in different requirements files). + for name, files in six.iteritems(req_files): + if len(files) > 1: + logger.warning("Requirement %s included multiple times [%s]", + name, ', '.join(sorted(set(files)))) + + yield( + '## The following requirements were added by ' + 'pip freeze:' + ) + for installation in sorted( + installations.values(), key=lambda x: x.name.lower()): + if canonicalize_name(installation.name) not in skip: + yield str(installation).rstrip() + + +class FrozenRequirement(object): + def __init__(self, name, req, editable, comments=()): + self.name = name + self.req = req + self.editable = editable + self.comments = comments + + _rev_re = re.compile(r'-r(\d+)$') + _date_re = re.compile(r'-(20\d\d\d\d\d\d)$') + + @classmethod + def _init_args_from_dist(cls, dist, dependency_links): + """ + Compute and return arguments (req, editable, comments) to pass to + FrozenRequirement.__init__(). + + This method is for use in FrozenRequirement.from_dist(). + """ + location = os.path.normcase(os.path.abspath(dist.location)) + comments = [] + from pip._internal.vcs import vcs, get_src_requirement + if dist_is_editable(dist) and vcs.get_backend_name(location): + editable = True + try: + req = get_src_requirement(dist, location) + except InstallationError as exc: + logger.warning( + "Error when trying to get requirement for VCS system %s, " + "falling back to uneditable format", exc + ) + req = None + if req is None: + logger.warning( + 'Could not determine repository location of %s', location + ) + comments.append( + '## !! Could not determine repository location' + ) + req = dist.as_requirement() + editable = False + else: + editable = False + req = dist.as_requirement() + specs = req.specs + assert len(specs) == 1 and specs[0][0] in ["==", "==="], \ + 'Expected 1 spec with == or ===; specs = %r; dist = %r' % \ + (specs, dist) + version = specs[0][1] + ver_match = cls._rev_re.search(version) + date_match = cls._date_re.search(version) + if ver_match or date_match: + svn_backend = vcs.get_backend('svn') + if svn_backend: + svn_location = svn_backend().get_location( + dist, + dependency_links, + ) + if not svn_location: + logger.warning( + 'Warning: cannot find svn location for %s', req, + ) + comments.append( + '## FIXME: could not find svn URL in dependency_links ' + 'for this package:' + ) + else: + deprecated( + "SVN editable detection based on dependency links " + "will be dropped in the future.", + replacement=None, + gone_in="18.2", + issue=4187, + ) + comments.append( + '# Installing as editable to satisfy requirement %s:' % + req + ) + if ver_match: + rev = ver_match.group(1) + else: + rev = '{%s}' % date_match.group(1) + editable = True + egg_name = cls.egg_name(dist) + req = make_vcs_requirement_url(svn_location, rev, egg_name) + + return (req, editable, comments) + + @classmethod + def from_dist(cls, dist, dependency_links): + args = cls._init_args_from_dist(dist, dependency_links) + return cls(dist.project_name, *args) + + @staticmethod + def egg_name(dist): + name = dist.egg_name() + match = re.search(r'-py\d\.\d$', name) + if match: + name = name[:match.start()] + return name + + def __str__(self): + req = self.req + if self.editable: + req = '-e %s' % req + return '\n'.join(list(self.comments) + [str(req)]) + '\n' diff --git a/winvenv/Lib/site-packages/pip/_internal/operations/prepare.py b/winvenv/Lib/site-packages/pip/_internal/operations/prepare.py new file mode 100644 index 0000000..104bea3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/operations/prepare.py @@ -0,0 +1,355 @@ +"""Prepares a distribution for installation +""" + +import logging +import os + +from pip._vendor import pkg_resources, requests + +from pip._internal.build_env import BuildEnvironment +from pip._internal.download import ( + is_dir_url, is_file_url, is_vcs_url, unpack_url, url_to_path, +) +from pip._internal.exceptions import ( + DirectoryUrlHashUnsupported, HashUnpinned, InstallationError, + PreviousBuildDirError, VcsHashUnsupported, +) +from pip._internal.utils.compat import expanduser +from pip._internal.utils.hashes import MissingHashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import display_path, normalize_path +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + + +def make_abstract_dist(req): + """Factory to make an abstract dist object. + + Preconditions: Either an editable req with a source_dir, or satisfied_by or + a wheel link, or a non-editable req with a source_dir. + + :return: A concrete DistAbstraction. + """ + if req.editable: + return IsSDist(req) + elif req.link and req.link.is_wheel: + return IsWheel(req) + else: + return IsSDist(req) + + +class DistAbstraction(object): + """Abstracts out the wheel vs non-wheel Resolver.resolve() logic. + + The requirements for anything installable are as follows: + - we must be able to determine the requirement name + (or we can't correctly handle the non-upgrade case). + - we must be able to generate a list of run-time dependencies + without installing any additional packages (or we would + have to either burn time by doing temporary isolated installs + or alternatively violate pips 'don't start installing unless + all requirements are available' rule - neither of which are + desirable). + - for packages with setup requirements, we must also be able + to determine their requirements without installing additional + packages (for the same reason as run-time dependencies) + - we must be able to create a Distribution object exposing the + above metadata. + """ + + def __init__(self, req): + self.req = req + + def dist(self, finder): + """Return a setuptools Dist object.""" + raise NotImplementedError(self.dist) + + def prep_for_dist(self, finder, build_isolation): + """Ensure that we can get a Dist for this requirement.""" + raise NotImplementedError(self.dist) + + +class IsWheel(DistAbstraction): + + def dist(self, finder): + return list(pkg_resources.find_distributions( + self.req.source_dir))[0] + + def prep_for_dist(self, finder, build_isolation): + # FIXME:https://github.com/pypa/pip/issues/1112 + pass + + +class IsSDist(DistAbstraction): + + def dist(self, finder): + dist = self.req.get_dist() + # FIXME: shouldn't be globally added. + if finder and dist.has_metadata('dependency_links.txt'): + finder.add_dependency_links( + dist.get_metadata_lines('dependency_links.txt') + ) + return dist + + def prep_for_dist(self, finder, build_isolation): + # Prepare for building. We need to: + # 1. Load pyproject.toml (if it exists) + # 2. Set up the build environment + + self.req.load_pyproject_toml() + should_isolate = self.req.use_pep517 and build_isolation + + if should_isolate: + # Isolate in a BuildEnvironment and install the build-time + # requirements. + self.req.build_env = BuildEnvironment() + self.req.build_env.install_requirements( + finder, self.req.pyproject_requires, + "Installing build dependencies" + ) + missing = [] + if self.req.requirements_to_check: + check = self.req.requirements_to_check + missing = self.req.build_env.missing_requirements(check) + if missing: + logger.warning( + "Missing build requirements in pyproject.toml for %s.", + self.req, + ) + logger.warning( + "The project does not specify a build backend, and pip " + "cannot fall back to setuptools without %s.", + " and ".join(map(repr, sorted(missing))) + ) + + self.req.run_egg_info() + self.req.assert_source_matches_version() + + +class Installed(DistAbstraction): + + def dist(self, finder): + return self.req.satisfied_by + + def prep_for_dist(self, finder, build_isolation): + pass + + +class RequirementPreparer(object): + """Prepares a Requirement + """ + + def __init__(self, build_dir, download_dir, src_dir, wheel_download_dir, + progress_bar, build_isolation, req_tracker): + super(RequirementPreparer, self).__init__() + + self.src_dir = src_dir + self.build_dir = build_dir + self.req_tracker = req_tracker + + # Where still packed archives should be written to. If None, they are + # not saved, and are deleted immediately after unpacking. + self.download_dir = download_dir + + # Where still-packed .whl files should be written to. If None, they are + # written to the download_dir parameter. Separate to download_dir to + # permit only keeping wheel archives for pip wheel. + if wheel_download_dir: + wheel_download_dir = normalize_path(wheel_download_dir) + self.wheel_download_dir = wheel_download_dir + + # NOTE + # download_dir and wheel_download_dir overlap semantically and may + # be combined if we're willing to have non-wheel archives present in + # the wheelhouse output by 'pip wheel'. + + self.progress_bar = progress_bar + + # Is build isolation allowed? + self.build_isolation = build_isolation + + @property + def _download_should_save(self): + # TODO: Modify to reduce indentation needed + if self.download_dir: + self.download_dir = expanduser(self.download_dir) + if os.path.exists(self.download_dir): + return True + else: + logger.critical('Could not find download directory') + raise InstallationError( + "Could not find or access download directory '%s'" + % display_path(self.download_dir)) + return False + + def prepare_linked_requirement(self, req, session, finder, + upgrade_allowed, require_hashes): + """Prepare a requirement that would be obtained from req.link + """ + # TODO: Breakup into smaller functions + if req.link and req.link.scheme == 'file': + path = url_to_path(req.link.url) + logger.info('Processing %s', display_path(path)) + else: + logger.info('Collecting %s', req) + + with indent_log(): + # @@ if filesystem packages are not marked + # editable in a req, a non deterministic error + # occurs when the script attempts to unpack the + # build directory + req.ensure_has_source_dir(self.build_dir) + # If a checkout exists, it's unwise to keep going. version + # inconsistencies are logged later, but do not fail the + # installation. + # FIXME: this won't upgrade when there's an existing + # package unpacked in `req.source_dir` + # package unpacked in `req.source_dir` + if os.path.exists(os.path.join(req.source_dir, 'setup.py')): + raise PreviousBuildDirError( + "pip can't proceed with requirements '%s' due to a" + " pre-existing build directory (%s). This is " + "likely due to a previous installation that failed" + ". pip is being responsible and not assuming it " + "can delete this. Please delete it and try again." + % (req, req.source_dir) + ) + req.populate_link(finder, upgrade_allowed, require_hashes) + + # We can't hit this spot and have populate_link return None. + # req.satisfied_by is None here (because we're + # guarded) and upgrade has no impact except when satisfied_by + # is not None. + # Then inside find_requirement existing_applicable -> False + # If no new versions are found, DistributionNotFound is raised, + # otherwise a result is guaranteed. + assert req.link + link = req.link + + # Now that we have the real link, we can tell what kind of + # requirements we have and raise some more informative errors + # than otherwise. (For example, we can raise VcsHashUnsupported + # for a VCS URL rather than HashMissing.) + if require_hashes: + # We could check these first 2 conditions inside + # unpack_url and save repetition of conditions, but then + # we would report less-useful error messages for + # unhashable requirements, complaining that there's no + # hash provided. + if is_vcs_url(link): + raise VcsHashUnsupported() + elif is_file_url(link) and is_dir_url(link): + raise DirectoryUrlHashUnsupported() + if not req.original_link and not req.is_pinned: + # Unpinned packages are asking for trouble when a new + # version is uploaded. This isn't a security check, but + # it saves users a surprising hash mismatch in the + # future. + # + # file:/// URLs aren't pinnable, so don't complain + # about them not being pinned. + raise HashUnpinned() + + hashes = req.hashes(trust_internet=not require_hashes) + if require_hashes and not hashes: + # Known-good hashes are missing for this requirement, so + # shim it with a facade object that will provoke hash + # computation and then raise a HashMissing exception + # showing the user what the hash should be. + hashes = MissingHashes() + + try: + download_dir = self.download_dir + # We always delete unpacked sdists after pip ran. + autodelete_unpacked = True + if req.link.is_wheel and self.wheel_download_dir: + # when doing 'pip wheel` we download wheels to a + # dedicated dir. + download_dir = self.wheel_download_dir + if req.link.is_wheel: + if download_dir: + # When downloading, we only unpack wheels to get + # metadata. + autodelete_unpacked = True + else: + # When installing a wheel, we use the unpacked + # wheel. + autodelete_unpacked = False + unpack_url( + req.link, req.source_dir, + download_dir, autodelete_unpacked, + session=session, hashes=hashes, + progress_bar=self.progress_bar + ) + except requests.HTTPError as exc: + logger.critical( + 'Could not install requirement %s because of error %s', + req, + exc, + ) + raise InstallationError( + 'Could not install requirement %s because of HTTP ' + 'error %s for URL %s' % + (req, exc, req.link) + ) + abstract_dist = make_abstract_dist(req) + with self.req_tracker.track(req): + abstract_dist.prep_for_dist(finder, self.build_isolation) + if self._download_should_save: + # Make a .zip of the source_dir we already created. + if req.link.scheme in vcs.all_schemes: + req.archive(self.download_dir) + return abstract_dist + + def prepare_editable_requirement(self, req, require_hashes, use_user_site, + finder): + """Prepare an editable requirement + """ + assert req.editable, "cannot prepare a non-editable req as editable" + + logger.info('Obtaining %s', req) + + with indent_log(): + if require_hashes: + raise InstallationError( + 'The editable requirement %s cannot be installed when ' + 'requiring hashes, because there is no single file to ' + 'hash.' % req + ) + req.ensure_has_source_dir(self.src_dir) + req.update_editable(not self._download_should_save) + + abstract_dist = make_abstract_dist(req) + with self.req_tracker.track(req): + abstract_dist.prep_for_dist(finder, self.build_isolation) + + if self._download_should_save: + req.archive(self.download_dir) + req.check_if_exists(use_user_site) + + return abstract_dist + + def prepare_installed_requirement(self, req, require_hashes, skip_reason): + """Prepare an already-installed requirement + """ + assert req.satisfied_by, "req should have been satisfied but isn't" + assert skip_reason is not None, ( + "did not get skip reason skipped but req.satisfied_by " + "is set to %r" % (req.satisfied_by,) + ) + logger.info( + 'Requirement %s: %s (%s)', + skip_reason, req, req.satisfied_by.version + ) + with indent_log(): + if require_hashes: + logger.debug( + 'Since it is already installed, we are trusting this ' + 'package without checking its hash. To ensure a ' + 'completely repeatable environment, install into an ' + 'empty virtualenv.' + ) + abstract_dist = Installed(req) + + return abstract_dist diff --git a/winvenv/Lib/site-packages/pip/_internal/pep425tags.py b/winvenv/Lib/site-packages/pip/_internal/pep425tags.py new file mode 100644 index 0000000..ab1a029 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/pep425tags.py @@ -0,0 +1,317 @@ +"""Generate and work with PEP 425 Compatibility Tags.""" +from __future__ import absolute_import + +import distutils.util +import logging +import platform +import re +import sys +import sysconfig +import warnings +from collections import OrderedDict + +import pip._internal.utils.glibc +from pip._internal.utils.compat import get_extension_suffixes + +logger = logging.getLogger(__name__) + +_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') + + +def get_config_var(var): + try: + return sysconfig.get_config_var(var) + except IOError as e: # Issue #1074 + warnings.warn("{}".format(e), RuntimeWarning) + return None + + +def get_abbr_impl(): + """Return abbreviated implementation name.""" + if hasattr(sys, 'pypy_version_info'): + pyimpl = 'pp' + elif sys.platform.startswith('java'): + pyimpl = 'jy' + elif sys.platform == 'cli': + pyimpl = 'ip' + else: + pyimpl = 'cp' + return pyimpl + + +def get_impl_ver(): + """Return implementation version.""" + impl_ver = get_config_var("py_version_nodot") + if not impl_ver or get_abbr_impl() == 'pp': + impl_ver = ''.join(map(str, get_impl_version_info())) + return impl_ver + + +def get_impl_version_info(): + """Return sys.version_info-like tuple for use in decrementing the minor + version.""" + if get_abbr_impl() == 'pp': + # as per https://github.com/pypa/pip/issues/2882 + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return sys.version_info[0], sys.version_info[1] + + +def get_impl_tag(): + """ + Returns the Tag for this specific implementation. + """ + return "{}{}".format(get_abbr_impl(), get_impl_ver()) + + +def get_flag(var, fallback, expected=True, warn=True): + """Use a fallback method for determining SOABI flags if the needed config + var is unset or unavailable.""" + val = get_config_var(var) + if val is None: + if warn: + logger.debug("Config variable '%s' is unset, Python ABI tag may " + "be incorrect", var) + return fallback() + return val == expected + + +def get_abi_tag(): + """Return the ABI tag based on SOABI (if available) or emulate SOABI + (CPython 2, PyPy).""" + soabi = get_config_var('SOABI') + impl = get_abbr_impl() + if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): + d = '' + m = '' + u = '' + if get_flag('Py_DEBUG', + lambda: hasattr(sys, 'gettotalrefcount'), + warn=(impl == 'cp')): + d = 'd' + if get_flag('WITH_PYMALLOC', + lambda: impl == 'cp', + warn=(impl == 'cp')): + m = 'm' + if get_flag('Py_UNICODE_SIZE', + lambda: sys.maxunicode == 0x10ffff, + expected=4, + warn=(impl == 'cp' and + sys.version_info < (3, 3))) \ + and sys.version_info < (3, 3): + u = 'u' + abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) + elif soabi and soabi.startswith('cpython-'): + abi = 'cp' + soabi.split('-')[1] + elif soabi: + abi = soabi.replace('.', '_').replace('-', '_') + else: + abi = None + return abi + + +def _is_running_32bit(): + return sys.maxsize == 2147483647 + + +def get_platform(): + """Return our platform name 'win32', 'linux_x86_64'""" + if sys.platform == 'darwin': + # distutils.util.get_platform() returns the release based on the value + # of MACOSX_DEPLOYMENT_TARGET on which Python was built, which may + # be significantly older than the user's current machine. + release, _, machine = platform.mac_ver() + split_ver = release.split('.') + + if machine == "x86_64" and _is_running_32bit(): + machine = "i386" + elif machine == "ppc64" and _is_running_32bit(): + machine = "ppc" + + return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) + + # XXX remove distutils dependency + result = distutils.util.get_platform().replace('.', '_').replace('-', '_') + if result == "linux_x86_64" and _is_running_32bit(): + # 32 bit Python program (running on a 64 bit Linux): pip should only + # install and run 32 bit compiled extensions in that case. + result = "linux_i686" + + return result + + +def is_manylinux1_compatible(): + # Only Linux, and only x86-64 / i686 + if get_platform() not in {"linux_x86_64", "linux_i686"}: + return False + + # Check for presence of _manylinux module + try: + import _manylinux + return bool(_manylinux.manylinux1_compatible) + except (ImportError, AttributeError): + # Fall through to heuristic check below + pass + + # Check glibc version. CentOS 5 uses glibc 2.5. + return pip._internal.utils.glibc.have_compatible_glibc(2, 5) + + +def get_darwin_arches(major, minor, machine): + """Return a list of supported arches (including group arches) for + the given major, minor and machine architecture of an macOS machine. + """ + arches = [] + + def _supports_arch(major, minor, arch): + # Looking at the application support for macOS versions in the chart + # provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears + # our timeline looks roughly like: + # + # 10.0 - Introduces ppc support. + # 10.4 - Introduces ppc64, i386, and x86_64 support, however the ppc64 + # and x86_64 support is CLI only, and cannot be used for GUI + # applications. + # 10.5 - Extends ppc64 and x86_64 support to cover GUI applications. + # 10.6 - Drops support for ppc64 + # 10.7 - Drops support for ppc + # + # Given that we do not know if we're installing a CLI or a GUI + # application, we must be conservative and assume it might be a GUI + # application and behave as if ppc64 and x86_64 support did not occur + # until 10.5. + # + # Note: The above information is taken from the "Application support" + # column in the chart not the "Processor support" since I believe + # that we care about what instruction sets an application can use + # not which processors the OS supports. + if arch == 'ppc': + return (major, minor) <= (10, 5) + if arch == 'ppc64': + return (major, minor) == (10, 5) + if arch == 'i386': + return (major, minor) >= (10, 4) + if arch == 'x86_64': + return (major, minor) >= (10, 5) + if arch in groups: + for garch in groups[arch]: + if _supports_arch(major, minor, garch): + return True + return False + + groups = OrderedDict([ + ("fat", ("i386", "ppc")), + ("intel", ("x86_64", "i386")), + ("fat64", ("x86_64", "ppc64")), + ("fat32", ("x86_64", "i386", "ppc")), + ]) + + if _supports_arch(major, minor, machine): + arches.append(machine) + + for garch in groups: + if machine in groups[garch] and _supports_arch(major, minor, garch): + arches.append(garch) + + arches.append('universal') + + return arches + + +def get_supported(versions=None, noarch=False, platform=None, + impl=None, abi=None): + """Return a list of supported tags for each version specified in + `versions`. + + :param versions: a list of string versions, of the form ["33", "32"], + or None. The first version will be assumed to support our ABI. + :param platform: specify the exact platform you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abi: specify the exact abi you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported = [] + + # Versions must be given with respect to the preference + if versions is None: + versions = [] + version_info = get_impl_version_info() + major = version_info[:-1] + # Support all previous minor Python versions. + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = impl or get_abbr_impl() + + abis = [] + + abi = abi or get_abi_tag() + if abi: + abis[0:0] = [abi] + + abi3s = set() + for suffix in get_extension_suffixes(): + if suffix.startswith('.abi'): + abi3s.add(suffix.split('.', 2)[1]) + + abis.extend(sorted(list(abi3s))) + + abis.append('none') + + if not noarch: + arch = platform or get_platform() + if arch.startswith('macosx'): + # support macosx-10.6-intel on macosx-10.9-x86_64 + match = _osx_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + tpl = '{}_{}_%i_%s'.format(name, major) + arches = [] + for m in reversed(range(int(minor) + 1)): + for a in get_darwin_arches(int(major), m, actual_arch): + arches.append(tpl % (m, a)) + else: + # arch pattern didn't match (?!) + arches = [arch] + elif platform is None and is_manylinux1_compatible(): + arches = [arch.replace('linux', 'manylinux1'), arch] + else: + arches = [arch] + + # Current version, current API (built specifically for our Python): + for abi in abis: + for arch in arches: + supported.append(('%s%s' % (impl, versions[0]), abi, arch)) + + # abi3 modules compatible with older version of Python + for version in versions[1:]: + # abi3 was introduced in Python 3.2 + if version in {'31', '30'}: + break + for abi in abi3s: # empty set if not Python 3 + for arch in arches: + supported.append(("%s%s" % (impl, version), abi, arch)) + + # Has binaries, does not use the Python API: + for arch in arches: + supported.append(('py%s' % (versions[0][0]), 'none', arch)) + + # No abi / arch, but requires our implementation: + supported.append(('%s%s' % (impl, versions[0]), 'none', 'any')) + # Tagged specifically as being cross-version compatible + # (with just the major version specified) + supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + # No abi / arch, generic Python + for i, version in enumerate(versions): + supported.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + supported.append(('py%s' % (version[0]), 'none', 'any')) + + return supported + + +implementation_tag = get_impl_tag() diff --git a/winvenv/Lib/site-packages/pip/_internal/pyproject.py b/winvenv/Lib/site-packages/pip/_internal/pyproject.py new file mode 100644 index 0000000..f938a76 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/pyproject.py @@ -0,0 +1,144 @@ +from __future__ import absolute_import + +import io +import os + +from pip._vendor import pytoml, six + +from pip._internal.exceptions import InstallationError + + +def _is_list_of_str(obj): + return ( + isinstance(obj, list) and + all(isinstance(item, six.string_types) for item in obj) + ) + + +def load_pyproject_toml(use_pep517, pyproject_toml, setup_py, req_name): + """Load the pyproject.toml file. + + Parameters: + use_pep517 - Has the user requested PEP 517 processing? None + means the user hasn't explicitly specified. + pyproject_toml - Location of the project's pyproject.toml file + setup_py - Location of the project's setup.py file + req_name - The name of the requirement we're processing (for + error reporting) + + Returns: + None if we should use the legacy code path, otherwise a tuple + ( + requirements from pyproject.toml, + name of PEP 517 backend, + requirements we should check are installed after setting + up the build environment + ) + """ + has_pyproject = os.path.isfile(pyproject_toml) + has_setup = os.path.isfile(setup_py) + + if has_pyproject: + with io.open(pyproject_toml, encoding="utf-8") as f: + pp_toml = pytoml.load(f) + build_system = pp_toml.get("build-system") + else: + build_system = None + + # The following cases must use PEP 517 + # We check for use_pep517 equalling False because that + # means the user explicitly requested --no-use-pep517 + if has_pyproject and not has_setup: + if use_pep517 is False: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project does not have a setup.py" + ) + use_pep517 = True + elif build_system and "build-backend" in build_system: + if use_pep517 is False: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project specifies a build backend of {} " + "in pyproject.toml".format( + build_system["build-backend"] + ) + ) + use_pep517 = True + + # If we haven't worked out whether to use PEP 517 yet, + # and the user hasn't explicitly stated a preference, + # we do so if the project has a pyproject.toml file. + elif use_pep517 is None: + use_pep517 = has_pyproject + + # At this point, we know whether we're going to use PEP 517. + assert use_pep517 is not None + + # If we're using the legacy code path, there is nothing further + # for us to do here. + if not use_pep517: + return None + + if build_system is None: + # Either the user has a pyproject.toml with no build-system + # section, or the user has no pyproject.toml, but has opted in + # explicitly via --use-pep517. + # In the absence of any explicit backend specification, we + # assume the setuptools backend, and require wheel and a version + # of setuptools that supports that backend. + build_system = { + "requires": ["setuptools>=38.2.5", "wheel"], + "build-backend": "setuptools.build_meta", + } + + # If we're using PEP 517, we have build system information (either + # from pyproject.toml, or defaulted by the code above). + # Note that at this point, we do not know if the user has actually + # specified a backend, though. + assert build_system is not None + + # Ensure that the build-system section in pyproject.toml conforms + # to PEP 518. + error_template = ( + "{package} has a pyproject.toml file that does not comply " + "with PEP 518: {reason}" + ) + + # Specifying the build-system table but not the requires key is invalid + if "requires" not in build_system: + raise InstallationError( + error_template.format(package=req_name, reason=( + "it has a 'build-system' table but not " + "'build-system.requires' which is mandatory in the table" + )) + ) + + # Error out if requires is not a list of strings + requires = build_system["requires"] + if not _is_list_of_str(requires): + raise InstallationError(error_template.format( + package=req_name, + reason="'build-system.requires' is not a list of strings.", + )) + + backend = build_system.get("build-backend") + check = [] + if backend is None: + # If the user didn't specify a backend, we assume they want to use + # the setuptools backend. But we can't be sure they have included + # a version of setuptools which supplies the backend, or wheel + # (which is neede by the backend) in their requirements. So we + # make a note to check that those requirements are present once + # we have set up the environment. + # TODO: Review this - it's quite a lot of work to check for a very + # specific case. The problem is, that case is potentially quite + # common - projects that adopted PEP 518 early for the ability to + # specify requirements to execute setup.py, but never considered + # needing to mention the build tools themselves. The original PEP + # 518 code had a similar check (but implemented in a different + # way). + backend = "setuptools.build_meta" + check = ["setuptools>=38.2.5", "wheel"] + + return (requires, backend, check) diff --git a/winvenv/Lib/site-packages/pip/_internal/req/__init__.py b/winvenv/Lib/site-packages/pip/_internal/req/__init__.py new file mode 100644 index 0000000..b270498 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/__init__.py @@ -0,0 +1,69 @@ +from __future__ import absolute_import + +import logging + +from .req_install import InstallRequirement +from .req_set import RequirementSet +from .req_file import parse_requirements +from pip._internal.utils.logging import indent_log + + +__all__ = [ + "RequirementSet", "InstallRequirement", + "parse_requirements", "install_given_reqs", +] + +logger = logging.getLogger(__name__) + + +def install_given_reqs(to_install, install_options, global_options=(), + *args, **kwargs): + """ + Install everything in the given list. + + (to be called after having downloaded and unpacked the packages) + """ + + if to_install: + logger.info( + 'Installing collected packages: %s', + ', '.join([req.name for req in to_install]), + ) + + with indent_log(): + for requirement in to_install: + if requirement.conflicts_with: + logger.info( + 'Found existing installation: %s', + requirement.conflicts_with, + ) + with indent_log(): + uninstalled_pathset = requirement.uninstall( + auto_confirm=True + ) + try: + requirement.install( + install_options, + global_options, + *args, + **kwargs + ) + except Exception: + should_rollback = ( + requirement.conflicts_with and + not requirement.install_succeeded + ) + # if install did not succeed, rollback previous uninstall + if should_rollback: + uninstalled_pathset.rollback() + raise + else: + should_commit = ( + requirement.conflicts_with and + requirement.install_succeeded + ) + if should_commit: + uninstalled_pathset.commit() + requirement.remove_temporary_source() + + return to_install diff --git a/winvenv/Lib/site-packages/pip/_internal/req/constructors.py b/winvenv/Lib/site-packages/pip/_internal/req/constructors.py new file mode 100644 index 0000000..4c4641d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/constructors.py @@ -0,0 +1,298 @@ +"""Backing implementation for InstallRequirement's various constructors + +The idea here is that these formed a major chunk of InstallRequirement's size +so, moving them and support code dedicated to them outside of that class +helps creates for better understandability for the rest of the code. + +These are meant to be used elsewhere within pip to create instances of +InstallRequirement. +""" + +import logging +import os +import re +import traceback + +from pip._vendor.packaging.markers import Marker +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement +from pip._vendor.packaging.specifiers import Specifier +from pip._vendor.pkg_resources import RequirementParseError, parse_requirements + +from pip._internal.download import ( + is_archive_file, is_url, path_to_url, url_to_path, +) +from pip._internal.exceptions import InstallationError +from pip._internal.models.index import PyPI, TestPyPI +from pip._internal.models.link import Link +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.misc import is_installable_dir +from pip._internal.vcs import vcs +from pip._internal.wheel import Wheel + +__all__ = [ + "install_req_from_editable", "install_req_from_line", + "parse_editable" +] + +logger = logging.getLogger(__name__) +operators = Specifier._operators.keys() + + +def _strip_extras(path): + m = re.match(r'^(.+)(\[[^\]]+\])$', path) + extras = None + if m: + path_no_extras = m.group(1) + extras = m.group(2) + else: + path_no_extras = path + + return path_no_extras, extras + + +def parse_editable(editable_req): + """Parses an editable requirement into: + - a requirement name + - an URL + - extras + - editable options + Accepted requirements: + svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir + .[some_extra] + """ + + url = editable_req + + # If a file path is specified with extras, strip off the extras. + url_no_extras, extras = _strip_extras(url) + + if os.path.isdir(url_no_extras): + if not os.path.exists(os.path.join(url_no_extras, 'setup.py')): + raise InstallationError( + "Directory %r is not installable. File 'setup.py' not found." % + url_no_extras + ) + # Treating it as code that has already been checked out + url_no_extras = path_to_url(url_no_extras) + + if url_no_extras.lower().startswith('file:'): + package_name = Link(url_no_extras).egg_fragment + if extras: + return ( + package_name, + url_no_extras, + Requirement("placeholder" + extras.lower()).extras, + ) + else: + return package_name, url_no_extras, None + + for version_control in vcs: + if url.lower().startswith('%s:' % version_control): + url = '%s+%s' % (version_control, url) + break + + if '+' not in url: + raise InstallationError( + '%s should either be a path to a local project or a VCS url ' + 'beginning with svn+, git+, hg+, or bzr+' % + editable_req + ) + + vc_type = url.split('+', 1)[0].lower() + + if not vcs.get_backend(vc_type): + error_message = 'For --editable=%s only ' % editable_req + \ + ', '.join([backend.name + '+URL' for backend in vcs.backends]) + \ + ' is currently supported' + raise InstallationError(error_message) + + package_name = Link(url).egg_fragment + if not package_name: + raise InstallationError( + "Could not detect requirement name for '%s', please specify one " + "with #egg=your_package_name" % editable_req + ) + return package_name, url, None + + +def deduce_helpful_msg(req): + """Returns helpful msg in case requirements file does not exist, + or cannot be parsed. + + :params req: Requirements file path + """ + msg = "" + if os.path.exists(req): + msg = " It does exist." + # Try to parse and check if it is a requirements file. + try: + with open(req, 'r') as fp: + # parse first line only + next(parse_requirements(fp.read())) + msg += " The argument you provided " + \ + "(%s) appears to be a" % (req) + \ + " requirements file. If that is the" + \ + " case, use the '-r' flag to install" + \ + " the packages specified within it." + except RequirementParseError: + logger.debug("Cannot parse '%s' as requirements \ + file" % (req), exc_info=1) + else: + msg += " File '%s' does not exist." % (req) + return msg + + +# ---- The actual constructors follow ---- + + +def install_req_from_editable( + editable_req, comes_from=None, isolated=False, options=None, + wheel_cache=None, constraint=False +): + name, url, extras_override = parse_editable(editable_req) + if url.startswith('file:'): + source_dir = url_to_path(url) + else: + source_dir = None + + if name is not None: + try: + req = Requirement(name) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '%s'" % name) + else: + req = None + return InstallRequirement( + req, comes_from, source_dir=source_dir, + editable=True, + link=Link(url), + constraint=constraint, + isolated=isolated, + options=options if options else {}, + wheel_cache=wheel_cache, + extras=extras_override or (), + ) + + +def install_req_from_line( + name, comes_from=None, isolated=False, options=None, wheel_cache=None, + constraint=False +): + """Creates an InstallRequirement from a name, which might be a + requirement, directory containing 'setup.py', filename, or URL. + """ + if is_url(name): + marker_sep = '; ' + else: + marker_sep = ';' + if marker_sep in name: + name, markers = name.split(marker_sep, 1) + markers = markers.strip() + if not markers: + markers = None + else: + markers = Marker(markers) + else: + markers = None + name = name.strip() + req = None + path = os.path.normpath(os.path.abspath(name)) + link = None + extras = None + + if is_url(name): + link = Link(name) + else: + p, extras = _strip_extras(path) + looks_like_dir = os.path.isdir(p) and ( + os.path.sep in name or + (os.path.altsep is not None and os.path.altsep in name) or + name.startswith('.') + ) + if looks_like_dir: + if not is_installable_dir(p): + raise InstallationError( + "Directory %r is not installable. Neither 'setup.py' " + "nor 'pyproject.toml' found." % name + ) + link = Link(path_to_url(p)) + elif is_archive_file(p): + if not os.path.isfile(p): + logger.warning( + 'Requirement %r looks like a filename, but the ' + 'file does not exist', + name + ) + link = Link(path_to_url(p)) + + # it's a local file, dir, or url + if link: + # Handle relative file URLs + if link.scheme == 'file' and re.search(r'\.\./', link.url): + link = Link( + path_to_url(os.path.normpath(os.path.abspath(link.path)))) + # wheel file + if link.is_wheel: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + req = "%s==%s" % (wheel.name, wheel.version) + else: + # set the req to the egg fragment. when it's not there, this + # will become an 'unnamed' requirement + req = link.egg_fragment + + # a requirement specifier + else: + req = name + + if extras: + extras = Requirement("placeholder" + extras.lower()).extras + else: + extras = () + if req is not None: + try: + req = Requirement(req) + except InvalidRequirement: + if os.path.sep in req: + add_msg = "It looks like a path." + add_msg += deduce_helpful_msg(req) + elif '=' in req and not any(op in req for op in operators): + add_msg = "= is not a valid operator. Did you mean == ?" + else: + add_msg = traceback.format_exc() + raise InstallationError( + "Invalid requirement: '%s'\n%s" % (req, add_msg) + ) + + return InstallRequirement( + req, comes_from, link=link, markers=markers, + isolated=isolated, + options=options if options else {}, + wheel_cache=wheel_cache, + constraint=constraint, + extras=extras, + ) + + +def install_req_from_req( + req, comes_from=None, isolated=False, wheel_cache=None +): + try: + req = Requirement(req) + except InvalidRequirement: + raise InstallationError("Invalid requirement: '%s'" % req) + + domains_not_allowed = [ + PyPI.file_storage_domain, + TestPyPI.file_storage_domain, + ] + if req.url and comes_from.link.netloc in domains_not_allowed: + # Explicitly disallow pypi packages that depend on external urls + raise InstallationError( + "Packages installed from PyPI cannot depend on packages " + "which are not also hosted on PyPI.\n" + "%s depends on %s " % (comes_from.name, req) + ) + + return InstallRequirement( + req, comes_from, isolated=isolated, wheel_cache=wheel_cache + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/req/req_file.py b/winvenv/Lib/site-packages/pip/_internal/req/req_file.py new file mode 100644 index 0000000..e7acf7c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/req_file.py @@ -0,0 +1,340 @@ +""" +Requirements file parsing +""" + +from __future__ import absolute_import + +import optparse +import os +import re +import shlex +import sys + +from pip._vendor.six.moves import filterfalse +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.cli import cmdoptions +from pip._internal.download import get_file_content +from pip._internal.exceptions import RequirementsFileParseError +from pip._internal.req.constructors import ( + install_req_from_editable, install_req_from_line, +) + +__all__ = ['parse_requirements'] + +SCHEME_RE = re.compile(r'^(http|https|file):', re.I) +COMMENT_RE = re.compile(r'(^|\s)+#.*$') + +# Matches environment variable-style values in '${MY_VARIABLE_1}' with the +# variable name consisting of only uppercase letters, digits or the '_' +# (underscore). This follows the POSIX standard defined in IEEE Std 1003.1, +# 2013 Edition. +ENV_VAR_RE = re.compile(r'(?P\$\{(?P[A-Z0-9_]+)\})') + +SUPPORTED_OPTIONS = [ + cmdoptions.constraints, + cmdoptions.editable, + cmdoptions.requirements, + cmdoptions.no_index, + cmdoptions.index_url, + cmdoptions.find_links, + cmdoptions.extra_index_url, + cmdoptions.always_unzip, + cmdoptions.no_binary, + cmdoptions.only_binary, + cmdoptions.pre, + cmdoptions.process_dependency_links, + cmdoptions.trusted_host, + cmdoptions.require_hashes, +] + +# options to be passed to requirements +SUPPORTED_OPTIONS_REQ = [ + cmdoptions.install_options, + cmdoptions.global_options, + cmdoptions.hash, +] + +# the 'dest' string values +SUPPORTED_OPTIONS_REQ_DEST = [o().dest for o in SUPPORTED_OPTIONS_REQ] + + +def parse_requirements(filename, finder=None, comes_from=None, options=None, + session=None, constraint=False, wheel_cache=None): + """Parse a requirements file and yield InstallRequirement instances. + + :param filename: Path or url of requirements file. + :param finder: Instance of pip.index.PackageFinder. + :param comes_from: Origin description of requirements. + :param options: cli options. + :param session: Instance of pip.download.PipSession. + :param constraint: If true, parsing a constraint file rather than + requirements file. + :param wheel_cache: Instance of pip.wheel.WheelCache + """ + if session is None: + raise TypeError( + "parse_requirements() missing 1 required keyword argument: " + "'session'" + ) + + _, content = get_file_content( + filename, comes_from=comes_from, session=session + ) + + lines_enum = preprocess(content, options) + + for line_number, line in lines_enum: + req_iter = process_line(line, filename, line_number, finder, + comes_from, options, session, wheel_cache, + constraint=constraint) + for req in req_iter: + yield req + + +def preprocess(content, options): + """Split, filter, and join lines, and return a line iterator + + :param content: the content of the requirements file + :param options: cli options + """ + lines_enum = enumerate(content.splitlines(), start=1) + lines_enum = join_lines(lines_enum) + lines_enum = ignore_comments(lines_enum) + lines_enum = skip_regex(lines_enum, options) + lines_enum = expand_env_variables(lines_enum) + return lines_enum + + +def process_line(line, filename, line_number, finder=None, comes_from=None, + options=None, session=None, wheel_cache=None, + constraint=False): + """Process a single requirements line; This can result in creating/yielding + requirements, or updating the finder. + + For lines that contain requirements, the only options that have an effect + are from SUPPORTED_OPTIONS_REQ, and they are scoped to the + requirement. Other options from SUPPORTED_OPTIONS may be present, but are + ignored. + + For lines that do not contain requirements, the only options that have an + effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may + be present, but are ignored. These lines may contain multiple options + (although our docs imply only one is supported), and all our parsed and + affect the finder. + + :param constraint: If True, parsing a constraints file. + :param options: OptionParser options that we may update + """ + parser = build_parser(line) + defaults = parser.get_default_values() + defaults.index_url = None + if finder: + # `finder.format_control` will be updated during parsing + defaults.format_control = finder.format_control + args_str, options_str = break_args_options(line) + if sys.version_info < (2, 7, 3): + # Prior to 2.7.3, shlex cannot deal with unicode entries + options_str = options_str.encode('utf8') + opts, _ = parser.parse_args(shlex.split(options_str), defaults) + + # preserve for the nested code path + line_comes_from = '%s %s (line %s)' % ( + '-c' if constraint else '-r', filename, line_number, + ) + + # yield a line requirement + if args_str: + isolated = options.isolated_mode if options else False + if options: + cmdoptions.check_install_build_global(options, opts) + # get the options that apply to requirements + req_options = {} + for dest in SUPPORTED_OPTIONS_REQ_DEST: + if dest in opts.__dict__ and opts.__dict__[dest]: + req_options[dest] = opts.__dict__[dest] + yield install_req_from_line( + args_str, line_comes_from, constraint=constraint, + isolated=isolated, options=req_options, wheel_cache=wheel_cache + ) + + # yield an editable requirement + elif opts.editables: + isolated = options.isolated_mode if options else False + yield install_req_from_editable( + opts.editables[0], comes_from=line_comes_from, + constraint=constraint, isolated=isolated, wheel_cache=wheel_cache + ) + + # parse a nested requirements file + elif opts.requirements or opts.constraints: + if opts.requirements: + req_path = opts.requirements[0] + nested_constraint = False + else: + req_path = opts.constraints[0] + nested_constraint = True + # original file is over http + if SCHEME_RE.search(filename): + # do a url join so relative paths work + req_path = urllib_parse.urljoin(filename, req_path) + # original file and nested file are paths + elif not SCHEME_RE.search(req_path): + # do a join so relative paths work + req_path = os.path.join(os.path.dirname(filename), req_path) + # TODO: Why not use `comes_from='-r {} (line {})'` here as well? + parser = parse_requirements( + req_path, finder, comes_from, options, session, + constraint=nested_constraint, wheel_cache=wheel_cache + ) + for req in parser: + yield req + + # percolate hash-checking option upward + elif opts.require_hashes: + options.require_hashes = opts.require_hashes + + # set finder options + elif finder: + if opts.index_url: + finder.index_urls = [opts.index_url] + if opts.no_index is True: + finder.index_urls = [] + if opts.extra_index_urls: + finder.index_urls.extend(opts.extra_index_urls) + if opts.find_links: + # FIXME: it would be nice to keep track of the source + # of the find_links: support a find-links local path + # relative to a requirements file. + value = opts.find_links[0] + req_dir = os.path.dirname(os.path.abspath(filename)) + relative_to_reqs_file = os.path.join(req_dir, value) + if os.path.exists(relative_to_reqs_file): + value = relative_to_reqs_file + finder.find_links.append(value) + if opts.pre: + finder.allow_all_prereleases = True + if opts.process_dependency_links: + finder.process_dependency_links = True + if opts.trusted_hosts: + finder.secure_origins.extend( + ("*", host, "*") for host in opts.trusted_hosts) + + +def break_args_options(line): + """Break up the line into an args and options string. We only want to shlex + (and then optparse) the options, not the args. args can contain markers + which are corrupted by shlex. + """ + tokens = line.split(' ') + args = [] + options = tokens[:] + for token in tokens: + if token.startswith('-') or token.startswith('--'): + break + else: + args.append(token) + options.pop(0) + return ' '.join(args), ' '.join(options) + + +def build_parser(line): + """ + Return a parser for parsing requirement lines + """ + parser = optparse.OptionParser(add_help_option=False) + + option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ + for option_factory in option_factories: + option = option_factory() + parser.add_option(option) + + # By default optparse sys.exits on parsing errors. We want to wrap + # that in our own exception. + def parser_exit(self, msg): + # add offending line + msg = 'Invalid requirement: %s\n%s' % (line, msg) + raise RequirementsFileParseError(msg) + parser.exit = parser_exit + + return parser + + +def join_lines(lines_enum): + """Joins a line ending in '\' with the previous line (except when following + comments). The joined line takes on the index of the first line. + """ + primary_line_number = None + new_line = [] + for line_number, line in lines_enum: + if not line.endswith('\\') or COMMENT_RE.match(line): + if COMMENT_RE.match(line): + # this ensures comments are always matched later + line = ' ' + line + if new_line: + new_line.append(line) + yield primary_line_number, ''.join(new_line) + new_line = [] + else: + yield line_number, line + else: + if not new_line: + primary_line_number = line_number + new_line.append(line.strip('\\')) + + # last line contains \ + if new_line: + yield primary_line_number, ''.join(new_line) + + # TODO: handle space after '\'. + + +def ignore_comments(lines_enum): + """ + Strips comments and filter empty lines. + """ + for line_number, line in lines_enum: + line = COMMENT_RE.sub('', line) + line = line.strip() + if line: + yield line_number, line + + +def skip_regex(lines_enum, options): + """ + Skip lines that match '--skip-requirements-regex' pattern + + Note: the regex pattern is only built once + """ + skip_regex = options.skip_requirements_regex if options else None + if skip_regex: + pattern = re.compile(skip_regex) + lines_enum = filterfalse(lambda e: pattern.search(e[1]), lines_enum) + return lines_enum + + +def expand_env_variables(lines_enum): + """Replace all environment variables that can be retrieved via `os.getenv`. + + The only allowed format for environment variables defined in the + requirement file is `${MY_VARIABLE_1}` to ensure two things: + + 1. Strings that contain a `$` aren't accidentally (partially) expanded. + 2. Ensure consistency across platforms for requirement files. + + These points are the result of a discusssion on the `github pull + request #3514 `_. + + Valid characters in variable names follow the `POSIX standard + `_ and are limited + to uppercase letter, digits and the `_` (underscore). + """ + for line_number, line in lines_enum: + for env_var, var_name in ENV_VAR_RE.findall(line): + value = os.getenv(var_name) + if not value: + continue + + line = line.replace(env_var, value) + + yield line_number, line diff --git a/winvenv/Lib/site-packages/pip/_internal/req/req_install.py b/winvenv/Lib/site-packages/pip/_internal/req/req_install.py new file mode 100644 index 0000000..c2624fe --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/req_install.py @@ -0,0 +1,860 @@ +from __future__ import absolute_import + +import logging +import os +import shutil +import sys +import sysconfig +import zipfile +from distutils.util import change_root + +from pip._vendor import pkg_resources, six +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.pep517.wrappers import Pep517HookCaller + +from pip._internal import wheel +from pip._internal.build_env import NoOpBuildEnvironment +from pip._internal.exceptions import InstallationError +from pip._internal.locations import ( + PIP_DELETE_MARKER_FILENAME, running_under_virtualenv, +) +from pip._internal.models.link import Link +from pip._internal.pyproject import load_pyproject_toml +from pip._internal.req.req_uninstall import UninstallPathSet +from pip._internal.utils.compat import native_str +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + _make_build_dir, ask_path_exists, backup_dir, call_subprocess, + display_path, dist_in_site_packages, dist_in_usersite, ensure_dir, + get_installed_version, rmtree, +) +from pip._internal.utils.packaging import get_metadata +from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.ui import open_spinner +from pip._internal.vcs import vcs +from pip._internal.wheel import move_wheel_files + +logger = logging.getLogger(__name__) + + +class InstallRequirement(object): + """ + Represents something that may be installed later on, may have information + about where to fetch the relavant requirement and also contains logic for + installing the said requirement. + """ + + def __init__(self, req, comes_from, source_dir=None, editable=False, + link=None, update=True, markers=None, + isolated=False, options=None, wheel_cache=None, + constraint=False, extras=()): + assert req is None or isinstance(req, Requirement), req + self.req = req + self.comes_from = comes_from + self.constraint = constraint + if source_dir is not None: + self.source_dir = os.path.normpath(os.path.abspath(source_dir)) + else: + self.source_dir = None + self.editable = editable + + self._wheel_cache = wheel_cache + if link is not None: + self.link = self.original_link = link + else: + self.link = self.original_link = req and req.url and Link(req.url) + + if extras: + self.extras = extras + elif req: + self.extras = { + pkg_resources.safe_extra(extra) for extra in req.extras + } + else: + self.extras = set() + if markers is not None: + self.markers = markers + else: + self.markers = req and req.marker + self._egg_info_path = None + # This holds the pkg_resources.Distribution object if this requirement + # is already available: + self.satisfied_by = None + # This hold the pkg_resources.Distribution object if this requirement + # conflicts with another installed distribution: + self.conflicts_with = None + # Temporary build location + self._temp_build_dir = TempDirectory(kind="req-build") + # Used to store the global directory where the _temp_build_dir should + # have been created. Cf _correct_build_location method. + self._ideal_build_dir = None + # True if the editable should be updated: + self.update = update + # Set to True after successful installation + self.install_succeeded = None + # UninstallPathSet of uninstalled distribution (for possible rollback) + self.uninstalled_pathset = None + self.options = options if options else {} + # Set to True after successful preparation of this requirement + self.prepared = False + self.is_direct = False + + self.isolated = isolated + self.build_env = NoOpBuildEnvironment() + + # The static build requirements (from pyproject.toml) + self.pyproject_requires = None + + # Build requirements that we will check are available + # TODO: We don't do this for --no-build-isolation. Should we? + self.requirements_to_check = [] + + # The PEP 517 backend we should use to build the project + self.pep517_backend = None + + # Are we using PEP 517 for this requirement? + # After pyproject.toml has been loaded, the only valid values are True + # and False. Before loading, None is valid (meaning "use the default"). + # Setting an explicit value before loading pyproject.toml is supported, + # but after loading this flag should be treated as read only. + self.use_pep517 = None + + def __str__(self): + if self.req: + s = str(self.req) + if self.link: + s += ' from %s' % self.link.url + elif self.link: + s = self.link.url + else: + s = '' + if self.satisfied_by is not None: + s += ' in %s' % display_path(self.satisfied_by.location) + if self.comes_from: + if isinstance(self.comes_from, six.string_types): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += ' (from %s)' % comes_from + return s + + def __repr__(self): + return '<%s object: %s editable=%r>' % ( + self.__class__.__name__, str(self), self.editable) + + def populate_link(self, finder, upgrade, require_hashes): + """Ensure that if a link can be found for this, that it is found. + + Note that self.link may still be None - if Upgrade is False and the + requirement is already installed. + + If require_hashes is True, don't use the wheel cache, because cached + wheels, always built locally, have different hashes than the files + downloaded from the index server and thus throw false hash mismatches. + Furthermore, cached wheels at present have undeterministic contents due + to file modification times. + """ + if self.link is None: + self.link = finder.find_requirement(self, upgrade) + if self._wheel_cache is not None and not require_hashes: + old_link = self.link + self.link = self._wheel_cache.get(self.link, self.name) + if old_link != self.link: + logger.debug('Using cached wheel link: %s', self.link) + + # Things that are valid for all kinds of requirements? + @property + def name(self): + if self.req is None: + return None + return native_str(pkg_resources.safe_name(self.req.name)) + + @property + def specifier(self): + return self.req.specifier + + @property + def is_pinned(self): + """Return whether I am pinned to an exact version. + + For example, some-package==1.2 is pinned; some-package>1.2 is not. + """ + specifiers = self.specifier + return (len(specifiers) == 1 and + next(iter(specifiers)).operator in {'==', '==='}) + + @property + def installed_version(self): + return get_installed_version(self.name) + + def match_markers(self, extras_requested=None): + if not extras_requested: + # Provide an extra to safely evaluate the markers + # without matching any extra + extras_requested = ('',) + if self.markers is not None: + return any( + self.markers.evaluate({'extra': extra}) + for extra in extras_requested) + else: + return True + + @property + def has_hash_options(self): + """Return whether any known-good hashes are specified as options. + + These activate --require-hashes mode; hashes specified as part of a + URL do not. + + """ + return bool(self.options.get('hashes', {})) + + def hashes(self, trust_internet=True): + """Return a hash-comparer that considers my option- and URL-based + hashes to be known-good. + + Hashes in URLs--ones embedded in the requirements file, not ones + downloaded from an index server--are almost peers with ones from + flags. They satisfy --require-hashes (whether it was implicitly or + explicitly activated) but do not activate it. md5 and sha224 are not + allowed in flags, which should nudge people toward good algos. We + always OR all hashes together, even ones from URLs. + + :param trust_internet: Whether to trust URL-based (#md5=...) hashes + downloaded from the internet, as by populate_link() + + """ + good_hashes = self.options.get('hashes', {}).copy() + link = self.link if trust_internet else self.original_link + if link and link.hash: + good_hashes.setdefault(link.hash_name, []).append(link.hash) + return Hashes(good_hashes) + + def from_path(self): + """Format a nice indicator to show where this "comes from" + """ + if self.req is None: + return None + s = str(self.req) + if self.comes_from: + if isinstance(self.comes_from, six.string_types): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += '->' + comes_from + return s + + def build_location(self, build_dir): + assert build_dir is not None + if self._temp_build_dir.path is not None: + return self._temp_build_dir.path + if self.req is None: + # for requirement via a path to a directory: the name of the + # package is not available yet so we create a temp directory + # Once run_egg_info will have run, we'll be able + # to fix it via _correct_build_location + # Some systems have /tmp as a symlink which confuses custom + # builds (such as numpy). Thus, we ensure that the real path + # is returned. + self._temp_build_dir.create() + self._ideal_build_dir = build_dir + + return self._temp_build_dir.path + if self.editable: + name = self.name.lower() + else: + name = self.name + # FIXME: Is there a better place to create the build_dir? (hg and bzr + # need this) + if not os.path.exists(build_dir): + logger.debug('Creating directory %s', build_dir) + _make_build_dir(build_dir) + return os.path.join(build_dir, name) + + def _correct_build_location(self): + """Move self._temp_build_dir to self._ideal_build_dir/self.req.name + + For some requirements (e.g. a path to a directory), the name of the + package is not available until we run egg_info, so the build_location + will return a temporary directory and store the _ideal_build_dir. + + This is only called by self.run_egg_info to fix the temporary build + directory. + """ + if self.source_dir is not None: + return + assert self.req is not None + assert self._temp_build_dir.path + assert self._ideal_build_dir.path + old_location = self._temp_build_dir.path + self._temp_build_dir.path = None + + new_location = self.build_location(self._ideal_build_dir) + if os.path.exists(new_location): + raise InstallationError( + 'A package already exists in %s; please remove it to continue' + % display_path(new_location)) + logger.debug( + 'Moving package %s from %s to new location %s', + self, display_path(old_location), display_path(new_location), + ) + shutil.move(old_location, new_location) + self._temp_build_dir.path = new_location + self._ideal_build_dir = None + self.source_dir = os.path.normpath(os.path.abspath(new_location)) + self._egg_info_path = None + + def remove_temporary_source(self): + """Remove the source files from this requirement, if they are marked + for deletion""" + if self.source_dir and os.path.exists( + os.path.join(self.source_dir, PIP_DELETE_MARKER_FILENAME)): + logger.debug('Removing source in %s', self.source_dir) + rmtree(self.source_dir) + self.source_dir = None + self._temp_build_dir.cleanup() + self.build_env.cleanup() + + def check_if_exists(self, use_user_site): + """Find an installed distribution that satisfies or conflicts + with this requirement, and set self.satisfied_by or + self.conflicts_with appropriately. + """ + if self.req is None: + return False + try: + # get_distribution() will resolve the entire list of requirements + # anyway, and we've already determined that we need the requirement + # in question, so strip the marker so that we don't try to + # evaluate it. + no_marker = Requirement(str(self.req)) + no_marker.marker = None + self.satisfied_by = pkg_resources.get_distribution(str(no_marker)) + if self.editable and self.satisfied_by: + self.conflicts_with = self.satisfied_by + # when installing editables, nothing pre-existing should ever + # satisfy + self.satisfied_by = None + return True + except pkg_resources.DistributionNotFound: + return False + except pkg_resources.VersionConflict: + existing_dist = pkg_resources.get_distribution( + self.req.name + ) + if use_user_site: + if dist_in_usersite(existing_dist): + self.conflicts_with = existing_dist + elif (running_under_virtualenv() and + dist_in_site_packages(existing_dist)): + raise InstallationError( + "Will not install to the user site because it will " + "lack sys.path precedence to %s in %s" % + (existing_dist.project_name, existing_dist.location) + ) + else: + self.conflicts_with = existing_dist + return True + + # Things valid for wheels + @property + def is_wheel(self): + return self.link and self.link.is_wheel + + def move_wheel_files(self, wheeldir, root=None, home=None, prefix=None, + warn_script_location=True, use_user_site=False, + pycompile=True): + move_wheel_files( + self.name, self.req, wheeldir, + user=use_user_site, + home=home, + root=root, + prefix=prefix, + pycompile=pycompile, + isolated=self.isolated, + warn_script_location=warn_script_location, + ) + + # Things valid for sdists + @property + def setup_py_dir(self): + return os.path.join( + self.source_dir, + self.link and self.link.subdirectory_fragment or '') + + @property + def setup_py(self): + assert self.source_dir, "No source dir for %s" % self + + setup_py = os.path.join(self.setup_py_dir, 'setup.py') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(setup_py, six.text_type): + setup_py = setup_py.encode(sys.getfilesystemencoding()) + + return setup_py + + @property + def pyproject_toml(self): + assert self.source_dir, "No source dir for %s" % self + + pp_toml = os.path.join(self.setup_py_dir, 'pyproject.toml') + + # Python2 __file__ should not be unicode + if six.PY2 and isinstance(pp_toml, six.text_type): + pp_toml = pp_toml.encode(sys.getfilesystemencoding()) + + return pp_toml + + def load_pyproject_toml(self): + """Load the pyproject.toml file. + + After calling this routine, all of the attributes related to PEP 517 + processing for this requirement have been set. In particular, the + use_pep517 attribute can be used to determine whether we should + follow the PEP 517 or legacy (setup.py) code path. + """ + pep517_data = load_pyproject_toml( + self.use_pep517, + self.pyproject_toml, + self.setup_py, + str(self) + ) + + if pep517_data is None: + self.use_pep517 = False + else: + self.use_pep517 = True + requires, backend, check = pep517_data + self.requirements_to_check = check + self.pyproject_requires = requires + self.pep517_backend = Pep517HookCaller(self.setup_py_dir, backend) + + def run_egg_info(self): + assert self.source_dir + if self.name: + logger.debug( + 'Running setup.py (path:%s) egg_info for package %s', + self.setup_py, self.name, + ) + else: + logger.debug( + 'Running setup.py (path:%s) egg_info for package from %s', + self.setup_py, self.link, + ) + + with indent_log(): + script = SETUPTOOLS_SHIM % self.setup_py + base_cmd = [sys.executable, '-c', script] + if self.isolated: + base_cmd += ["--no-user-cfg"] + egg_info_cmd = base_cmd + ['egg_info'] + # We can't put the .egg-info files at the root, because then the + # source code will be mistaken for an installed egg, causing + # problems + if self.editable: + egg_base_option = [] + else: + egg_info_dir = os.path.join(self.setup_py_dir, 'pip-egg-info') + ensure_dir(egg_info_dir) + egg_base_option = ['--egg-base', 'pip-egg-info'] + with self.build_env: + call_subprocess( + egg_info_cmd + egg_base_option, + cwd=self.setup_py_dir, + show_stdout=False, + command_desc='python setup.py egg_info') + + if not self.req: + if isinstance(parse_version(self.metadata["Version"]), Version): + op = "==" + else: + op = "===" + self.req = Requirement( + "".join([ + self.metadata["Name"], + op, + self.metadata["Version"], + ]) + ) + self._correct_build_location() + else: + metadata_name = canonicalize_name(self.metadata["Name"]) + if canonicalize_name(self.req.name) != metadata_name: + logger.warning( + 'Running setup.py (path:%s) egg_info for package %s ' + 'produced metadata for project name %s. Fix your ' + '#egg=%s fragments.', + self.setup_py, self.name, metadata_name, self.name + ) + self.req = Requirement(metadata_name) + + @property + def egg_info_path(self): + if self._egg_info_path is None: + if self.editable: + base = self.source_dir + else: + base = os.path.join(self.setup_py_dir, 'pip-egg-info') + filenames = os.listdir(base) + if self.editable: + filenames = [] + for root, dirs, files in os.walk(base): + for dir in vcs.dirnames: + if dir in dirs: + dirs.remove(dir) + # Iterate over a copy of ``dirs``, since mutating + # a list while iterating over it can cause trouble. + # (See https://github.com/pypa/pip/pull/462.) + for dir in list(dirs): + # Don't search in anything that looks like a virtualenv + # environment + if ( + os.path.lexists( + os.path.join(root, dir, 'bin', 'python') + ) or + os.path.exists( + os.path.join( + root, dir, 'Scripts', 'Python.exe' + ) + )): + dirs.remove(dir) + # Also don't search through tests + elif dir == 'test' or dir == 'tests': + dirs.remove(dir) + filenames.extend([os.path.join(root, dir) + for dir in dirs]) + filenames = [f for f in filenames if f.endswith('.egg-info')] + + if not filenames: + raise InstallationError( + "Files/directories not found in %s" % base + ) + # if we have more than one match, we pick the toplevel one. This + # can easily be the case if there is a dist folder which contains + # an extracted tarball for testing purposes. + if len(filenames) > 1: + filenames.sort( + key=lambda x: x.count(os.path.sep) + + (os.path.altsep and x.count(os.path.altsep) or 0) + ) + self._egg_info_path = os.path.join(base, filenames[0]) + return self._egg_info_path + + @property + def metadata(self): + if not hasattr(self, '_metadata'): + self._metadata = get_metadata(self.get_dist()) + + return self._metadata + + def get_dist(self): + """Return a pkg_resources.Distribution built from self.egg_info_path""" + egg_info = self.egg_info_path.rstrip(os.path.sep) + base_dir = os.path.dirname(egg_info) + metadata = pkg_resources.PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + return pkg_resources.Distribution( + os.path.dirname(egg_info), + project_name=dist_name, + metadata=metadata, + ) + + def assert_source_matches_version(self): + assert self.source_dir + version = self.metadata['version'] + if self.req.specifier and version not in self.req.specifier: + logger.warning( + 'Requested %s, but installing version %s', + self, + version, + ) + else: + logger.debug( + 'Source in %s has version %s, which satisfies requirement %s', + display_path(self.source_dir), + version, + self, + ) + + # For both source distributions and editables + def ensure_has_source_dir(self, parent_dir): + """Ensure that a source_dir is set. + + This will create a temporary build dir if the name of the requirement + isn't known yet. + + :param parent_dir: The ideal pip parent_dir for the source_dir. + Generally src_dir for editables and build_dir for sdists. + :return: self.source_dir + """ + if self.source_dir is None: + self.source_dir = self.build_location(parent_dir) + return self.source_dir + + # For editable installations + def install_editable(self, install_options, + global_options=(), prefix=None): + logger.info('Running setup.py develop for %s', self.name) + + if self.isolated: + global_options = list(global_options) + ["--no-user-cfg"] + + if prefix: + prefix_param = ['--prefix={}'.format(prefix)] + install_options = list(install_options) + prefix_param + + with indent_log(): + # FIXME: should we do --install-headers here too? + with self.build_env: + call_subprocess( + [ + sys.executable, + '-c', + SETUPTOOLS_SHIM % self.setup_py + ] + + list(global_options) + + ['develop', '--no-deps'] + + list(install_options), + + cwd=self.setup_py_dir, + show_stdout=False, + ) + + self.install_succeeded = True + + def update_editable(self, obtain=True): + if not self.link: + logger.debug( + "Cannot update repository at %s; repository location is " + "unknown", + self.source_dir, + ) + return + assert self.editable + assert self.source_dir + if self.link.scheme == 'file': + # Static paths don't get updated + return + assert '+' in self.link.url, "bad url: %r" % self.link.url + if not self.update: + return + vc_type, url = self.link.url.split('+', 1) + backend = vcs.get_backend(vc_type) + if backend: + vcs_backend = backend(self.link.url) + if obtain: + vcs_backend.obtain(self.source_dir) + else: + vcs_backend.export(self.source_dir) + else: + assert 0, ( + 'Unexpected version control type (in %s): %s' + % (self.link, vc_type)) + + # Top-level Actions + def uninstall(self, auto_confirm=False, verbose=False, + use_user_site=False): + """ + Uninstall the distribution currently satisfying this requirement. + + Prompts before removing or modifying files unless + ``auto_confirm`` is True. + + Refuses to delete or modify files outside of ``sys.prefix`` - + thus uninstallation within a virtual environment can only + modify that virtual environment, even if the virtualenv is + linked to global site-packages. + + """ + if not self.check_if_exists(use_user_site): + logger.warning("Skipping %s as it is not installed.", self.name) + return + dist = self.satisfied_by or self.conflicts_with + + uninstalled_pathset = UninstallPathSet.from_dist(dist) + uninstalled_pathset.remove(auto_confirm, verbose) + return uninstalled_pathset + + def _clean_zip_name(self, name, prefix): # only used by archive. + assert name.startswith(prefix + os.path.sep), ( + "name %r doesn't start with prefix %r" % (name, prefix) + ) + name = name[len(prefix) + 1:] + name = name.replace(os.path.sep, '/') + return name + + # TODO: Investigate if this should be kept in InstallRequirement + # Seems to be used only when VCS + downloads + def archive(self, build_dir): + assert self.source_dir + create_archive = True + archive_name = '%s-%s.zip' % (self.name, self.metadata["version"]) + archive_path = os.path.join(build_dir, archive_name) + if os.path.exists(archive_path): + response = ask_path_exists( + 'The file %s exists. (i)gnore, (w)ipe, (b)ackup, (a)bort ' % + display_path(archive_path), ('i', 'w', 'b', 'a')) + if response == 'i': + create_archive = False + elif response == 'w': + logger.warning('Deleting %s', display_path(archive_path)) + os.remove(archive_path) + elif response == 'b': + dest_file = backup_dir(archive_path) + logger.warning( + 'Backing up %s to %s', + display_path(archive_path), + display_path(dest_file), + ) + shutil.move(archive_path, dest_file) + elif response == 'a': + sys.exit(-1) + if create_archive: + zip = zipfile.ZipFile( + archive_path, 'w', zipfile.ZIP_DEFLATED, + allowZip64=True + ) + dir = os.path.normcase(os.path.abspath(self.setup_py_dir)) + for dirpath, dirnames, filenames in os.walk(dir): + if 'pip-egg-info' in dirnames: + dirnames.remove('pip-egg-info') + for dirname in dirnames: + dirname = os.path.join(dirpath, dirname) + name = self._clean_zip_name(dirname, dir) + zipdir = zipfile.ZipInfo(self.name + '/' + name + '/') + zipdir.external_attr = 0x1ED << 16 # 0o755 + zip.writestr(zipdir, '') + for filename in filenames: + if filename == PIP_DELETE_MARKER_FILENAME: + continue + filename = os.path.join(dirpath, filename) + name = self._clean_zip_name(filename, dir) + zip.write(filename, self.name + '/' + name) + zip.close() + logger.info('Saved %s', display_path(archive_path)) + + def install(self, install_options, global_options=None, root=None, + home=None, prefix=None, warn_script_location=True, + use_user_site=False, pycompile=True): + global_options = global_options if global_options is not None else [] + if self.editable: + self.install_editable( + install_options, global_options, prefix=prefix, + ) + return + if self.is_wheel: + version = wheel.wheel_version(self.source_dir) + wheel.check_compatibility(version, self.name) + + self.move_wheel_files( + self.source_dir, root=root, prefix=prefix, home=home, + warn_script_location=warn_script_location, + use_user_site=use_user_site, pycompile=pycompile, + ) + self.install_succeeded = True + return + + # Extend the list of global and install options passed on to + # the setup.py call with the ones from the requirements file. + # Options specified in requirements file override those + # specified on the command line, since the last option given + # to setup.py is the one that is used. + global_options = list(global_options) + \ + self.options.get('global_options', []) + install_options = list(install_options) + \ + self.options.get('install_options', []) + + if self.isolated: + global_options = global_options + ["--no-user-cfg"] + + with TempDirectory(kind="record") as temp_dir: + record_filename = os.path.join(temp_dir.path, 'install-record.txt') + install_args = self.get_install_args( + global_options, record_filename, root, prefix, pycompile, + ) + msg = 'Running setup.py install for %s' % (self.name,) + with open_spinner(msg) as spinner: + with indent_log(): + with self.build_env: + call_subprocess( + install_args + install_options, + cwd=self.setup_py_dir, + show_stdout=False, + spinner=spinner, + ) + + if not os.path.exists(record_filename): + logger.debug('Record file %s not found', record_filename) + return + self.install_succeeded = True + + def prepend_root(path): + if root is None or not os.path.isabs(path): + return path + else: + return change_root(root, path) + + with open(record_filename) as f: + for line in f: + directory = os.path.dirname(line) + if directory.endswith('.egg-info'): + egg_info_dir = prepend_root(directory) + break + else: + logger.warning( + 'Could not find .egg-info directory in install record' + ' for %s', + self, + ) + # FIXME: put the record somewhere + # FIXME: should this be an error? + return + new_lines = [] + with open(record_filename) as f: + for line in f: + filename = line.strip() + if os.path.isdir(filename): + filename += os.path.sep + new_lines.append( + os.path.relpath(prepend_root(filename), egg_info_dir) + ) + new_lines.sort() + ensure_dir(egg_info_dir) + inst_files_path = os.path.join(egg_info_dir, 'installed-files.txt') + with open(inst_files_path, 'w') as f: + f.write('\n'.join(new_lines) + '\n') + + def get_install_args(self, global_options, record_filename, root, prefix, + pycompile): + install_args = [sys.executable, "-u"] + install_args.append('-c') + install_args.append(SETUPTOOLS_SHIM % self.setup_py) + install_args += list(global_options) + \ + ['install', '--record', record_filename] + install_args += ['--single-version-externally-managed'] + + if root is not None: + install_args += ['--root', root] + if prefix is not None: + install_args += ['--prefix', prefix] + + if pycompile: + install_args += ["--compile"] + else: + install_args += ["--no-compile"] + + if running_under_virtualenv(): + py_ver_str = 'python' + sysconfig.get_python_version() + install_args += ['--install-headers', + os.path.join(sys.prefix, 'include', 'site', + py_ver_str, self.name)] + + return install_args diff --git a/winvenv/Lib/site-packages/pip/_internal/req/req_set.py b/winvenv/Lib/site-packages/pip/_internal/req/req_set.py new file mode 100644 index 0000000..b198317 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/req_set.py @@ -0,0 +1,181 @@ +from __future__ import absolute_import + +import logging +from collections import OrderedDict + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.logging import indent_log +from pip._internal.wheel import Wheel + +logger = logging.getLogger(__name__) + + +class RequirementSet(object): + + def __init__(self, require_hashes=False, check_supported_wheels=True): + """Create a RequirementSet. + """ + + self.requirements = OrderedDict() + self.require_hashes = require_hashes + self.check_supported_wheels = check_supported_wheels + + # Mapping of alias: real_name + self.requirement_aliases = {} + self.unnamed_requirements = [] + self.successfully_downloaded = [] + self.reqs_to_cleanup = [] + + def __str__(self): + reqs = [req for req in self.requirements.values() + if not req.comes_from] + reqs.sort(key=lambda req: req.name.lower()) + return ' '.join([str(req.req) for req in reqs]) + + def __repr__(self): + reqs = [req for req in self.requirements.values()] + reqs.sort(key=lambda req: req.name.lower()) + reqs_str = ', '.join([str(req.req) for req in reqs]) + return ('<%s object; %d requirement(s): %s>' + % (self.__class__.__name__, len(reqs), reqs_str)) + + def add_requirement(self, install_req, parent_req_name=None, + extras_requested=None): + """Add install_req as a requirement to install. + + :param parent_req_name: The name of the requirement that needed this + added. The name is used because when multiple unnamed requirements + resolve to the same name, we could otherwise end up with dependency + links that point outside the Requirements set. parent_req must + already be added. Note that None implies that this is a user + supplied requirement, vs an inferred one. + :param extras_requested: an iterable of extras used to evaluate the + environment markers. + :return: Additional requirements to scan. That is either [] if + the requirement is not applicable, or [install_req] if the + requirement is applicable and has just been added. + """ + name = install_req.name + + # If the markers do not match, ignore this requirement. + if not install_req.match_markers(extras_requested): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + name, install_req.markers, + ) + return [], None + + # If the wheel is not supported, raise an error. + # Should check this after filtering out based on environment markers to + # allow specifying different wheels based on the environment/OS, in a + # single requirements file. + if install_req.link and install_req.link.is_wheel: + wheel = Wheel(install_req.link.filename) + if self.check_supported_wheels and not wheel.supported(): + raise InstallationError( + "%s is not a supported wheel on this platform." % + wheel.filename + ) + + # This next bit is really a sanity check. + assert install_req.is_direct == (parent_req_name is None), ( + "a direct req shouldn't have a parent and also, " + "a non direct req should have a parent" + ) + + # Unnamed requirements are scanned again and the requirement won't be + # added as a dependency until after scanning. + if not name: + # url or path requirement w/o an egg fragment + self.unnamed_requirements.append(install_req) + return [install_req], None + + try: + existing_req = self.get_requirement(name) + except KeyError: + existing_req = None + + has_conflicting_requirement = ( + parent_req_name is None and + existing_req and + not existing_req.constraint and + existing_req.extras == install_req.extras and + existing_req.req.specifier != install_req.req.specifier + ) + if has_conflicting_requirement: + raise InstallationError( + "Double requirement given: %s (already in %s, name=%r)" + % (install_req, existing_req, name) + ) + + # When no existing requirement exists, add the requirement as a + # dependency and it will be scanned again after. + if not existing_req: + self.requirements[name] = install_req + # FIXME: what about other normalizations? E.g., _ vs. -? + if name.lower() != name: + self.requirement_aliases[name.lower()] = name + # We'd want to rescan this requirements later + return [install_req], install_req + + # Assume there's no need to scan, and that we've already + # encountered this for scanning. + if install_req.constraint or not existing_req.constraint: + return [], existing_req + + does_not_satisfy_constraint = ( + install_req.link and + not ( + existing_req.link and + install_req.link.path == existing_req.link.path + ) + ) + if does_not_satisfy_constraint: + self.reqs_to_cleanup.append(install_req) + raise InstallationError( + "Could not satisfy constraints for '%s': " + "installation from path or url cannot be " + "constrained to a version" % name, + ) + # If we're now installing a constraint, mark the existing + # object for real installation. + existing_req.constraint = False + existing_req.extras = tuple(sorted( + set(existing_req.extras) | set(install_req.extras) + )) + logger.debug( + "Setting %s extras to: %s", + existing_req, existing_req.extras, + ) + # Return the existing requirement for addition to the parent and + # scanning again. + return [existing_req], existing_req + + def has_requirement(self, project_name): + name = project_name.lower() + if (name in self.requirements and + not self.requirements[name].constraint or + name in self.requirement_aliases and + not self.requirements[self.requirement_aliases[name]].constraint): + return True + return False + + @property + def has_requirements(self): + return list(req for req in self.requirements.values() if not + req.constraint) or self.unnamed_requirements + + def get_requirement(self, project_name): + for name in project_name, project_name.lower(): + if name in self.requirements: + return self.requirements[name] + if name in self.requirement_aliases: + return self.requirements[self.requirement_aliases[name]] + raise KeyError("No project with the name %r" % project_name) + + def cleanup_files(self): + """Clean up files, remove builds.""" + logger.debug('Cleaning up...') + with indent_log(): + for req in self.reqs_to_cleanup: + req.remove_temporary_source() diff --git a/winvenv/Lib/site-packages/pip/_internal/req/req_tracker.py b/winvenv/Lib/site-packages/pip/_internal/req/req_tracker.py new file mode 100644 index 0000000..0a86f4c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/req_tracker.py @@ -0,0 +1,76 @@ +from __future__ import absolute_import + +import contextlib +import errno +import hashlib +import logging +import os + +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +class RequirementTracker(object): + + def __init__(self): + self._root = os.environ.get('PIP_REQ_TRACKER') + if self._root is None: + self._temp_dir = TempDirectory(delete=False, kind='req-tracker') + self._temp_dir.create() + self._root = os.environ['PIP_REQ_TRACKER'] = self._temp_dir.path + logger.debug('Created requirements tracker %r', self._root) + else: + self._temp_dir = None + logger.debug('Re-using requirements tracker %r', self._root) + self._entries = set() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.cleanup() + + def _entry_path(self, link): + hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() + return os.path.join(self._root, hashed) + + def add(self, req): + link = req.link + info = str(req) + entry_path = self._entry_path(link) + try: + with open(entry_path) as fp: + # Error, these's already a build in progress. + raise LookupError('%s is already being built: %s' + % (link, fp.read())) + except IOError as e: + if e.errno != errno.ENOENT: + raise + assert req not in self._entries + with open(entry_path, 'w') as fp: + fp.write(info) + self._entries.add(req) + logger.debug('Added %s to build tracker %r', req, self._root) + + def remove(self, req): + link = req.link + self._entries.remove(req) + os.unlink(self._entry_path(link)) + logger.debug('Removed %s from build tracker %r', req, self._root) + + def cleanup(self): + for req in set(self._entries): + self.remove(req) + remove = self._temp_dir is not None + if remove: + self._temp_dir.cleanup() + logger.debug('%s build tracker %r', + 'Removed' if remove else 'Cleaned', + self._root) + + @contextlib.contextmanager + def track(self, req): + self.add(req) + yield + self.remove(req) diff --git a/winvenv/Lib/site-packages/pip/_internal/req/req_uninstall.py b/winvenv/Lib/site-packages/pip/_internal/req/req_uninstall.py new file mode 100644 index 0000000..a7d8230 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/req/req_uninstall.py @@ -0,0 +1,460 @@ +from __future__ import absolute_import + +import csv +import functools +import logging +import os +import sys +import sysconfig + +from pip._vendor import pkg_resources + +from pip._internal.exceptions import UninstallationError +from pip._internal.locations import bin_py, bin_user +from pip._internal.utils.compat import WINDOWS, cache_from_source, uses_pycache +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + FakeFile, ask, dist_in_usersite, dist_is_local, egg_link_path, is_local, + normalize_path, renames, +) +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +def _script_names(dist, script_name, is_gui): + """Create the fully qualified name of the files created by + {console,gui}_scripts for the given ``dist``. + Returns the list of file names + """ + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + exe_name = os.path.join(bin_dir, script_name) + paths_to_remove = [exe_name] + if WINDOWS: + paths_to_remove.append(exe_name + '.exe') + paths_to_remove.append(exe_name + '.exe.manifest') + if is_gui: + paths_to_remove.append(exe_name + '-script.pyw') + else: + paths_to_remove.append(exe_name + '-script.py') + return paths_to_remove + + +def _unique(fn): + @functools.wraps(fn) + def unique(*args, **kw): + seen = set() + for item in fn(*args, **kw): + if item not in seen: + seen.add(item) + yield item + return unique + + +@_unique +def uninstallation_paths(dist): + """ + Yield all the uninstallation paths for dist based on RECORD-without-.py[co] + + Yield paths to all the files in RECORD. For each .py file in RECORD, add + the .pyc and .pyo in the same directory. + + UninstallPathSet.add() takes care of the __pycache__ .py[co]. + """ + r = csv.reader(FakeFile(dist.get_metadata_lines('RECORD'))) + for row in r: + path = os.path.join(dist.location, row[0]) + yield path + if path.endswith('.py'): + dn, fn = os.path.split(path) + base = fn[:-3] + path = os.path.join(dn, base + '.pyc') + yield path + path = os.path.join(dn, base + '.pyo') + yield path + + +def compact(paths): + """Compact a path set to contain the minimal number of paths + necessary to contain all paths in the set. If /a/path/ and + /a/path/to/a/file.txt are both in the set, leave only the + shorter path.""" + + sep = os.path.sep + short_paths = set() + for path in sorted(paths, key=len): + should_add = any( + path.startswith(shortpath.rstrip("*")) and + path[len(shortpath.rstrip("*").rstrip(sep))] == sep + for shortpath in short_paths + ) + if not should_add: + short_paths.add(path) + return short_paths + + +def compress_for_output_listing(paths): + """Returns a tuple of 2 sets of which paths to display to user + + The first set contains paths that would be deleted. Files of a package + are not added and the top-level directory of the package has a '*' added + at the end - to signify that all it's contents are removed. + + The second set contains files that would have been skipped in the above + folders. + """ + + will_remove = list(paths) + will_skip = set() + + # Determine folders and files + folders = set() + files = set() + for path in will_remove: + if path.endswith(".pyc"): + continue + if path.endswith("__init__.py") or ".dist-info" in path: + folders.add(os.path.dirname(path)) + files.add(path) + + _normcased_files = set(map(os.path.normcase, files)) + + folders = compact(folders) + + # This walks the tree using os.walk to not miss extra folders + # that might get added. + for folder in folders: + for dirpath, _, dirfiles in os.walk(folder): + for fname in dirfiles: + if fname.endswith(".pyc"): + continue + + file_ = os.path.join(dirpath, fname) + if (os.path.isfile(file_) and + os.path.normcase(file_) not in _normcased_files): + # We are skipping this file. Add it to the set. + will_skip.add(file_) + + will_remove = files | { + os.path.join(folder, "*") for folder in folders + } + + return will_remove, will_skip + + +class UninstallPathSet(object): + """A set of file paths to be removed in the uninstallation of a + requirement.""" + def __init__(self, dist): + self.paths = set() + self._refuse = set() + self.pth = {} + self.dist = dist + self.save_dir = TempDirectory(kind="uninstall") + self._moved_paths = [] + + def _permitted(self, path): + """ + Return True if the given path is one we are permitted to + remove/modify, False otherwise. + + """ + return is_local(path) + + def add(self, path): + head, tail = os.path.split(path) + + # we normalize the head to resolve parent directory symlinks, but not + # the tail, since we only want to uninstall symlinks, not their targets + path = os.path.join(normalize_path(head), os.path.normcase(tail)) + + if not os.path.exists(path): + return + if self._permitted(path): + self.paths.add(path) + else: + self._refuse.add(path) + + # __pycache__ files can show up after 'installed-files.txt' is created, + # due to imports + if os.path.splitext(path)[1] == '.py' and uses_pycache: + self.add(cache_from_source(path)) + + def add_pth(self, pth_file, entry): + pth_file = normalize_path(pth_file) + if self._permitted(pth_file): + if pth_file not in self.pth: + self.pth[pth_file] = UninstallPthEntries(pth_file) + self.pth[pth_file].add(entry) + else: + self._refuse.add(pth_file) + + def _stash(self, path): + return os.path.join( + self.save_dir.path, os.path.splitdrive(path)[1].lstrip(os.path.sep) + ) + + def remove(self, auto_confirm=False, verbose=False): + """Remove paths in ``self.paths`` with confirmation (unless + ``auto_confirm`` is True).""" + + if not self.paths: + logger.info( + "Can't uninstall '%s'. No files were found to uninstall.", + self.dist.project_name, + ) + return + + dist_name_version = ( + self.dist.project_name + "-" + self.dist.version + ) + logger.info('Uninstalling %s:', dist_name_version) + + with indent_log(): + if auto_confirm or self._allowed_to_proceed(verbose): + self.save_dir.create() + + for path in sorted(compact(self.paths)): + new_path = self._stash(path) + logger.debug('Removing file or directory %s', path) + self._moved_paths.append(path) + renames(path, new_path) + for pth in self.pth.values(): + pth.remove() + + logger.info('Successfully uninstalled %s', dist_name_version) + + def _allowed_to_proceed(self, verbose): + """Display which files would be deleted and prompt for confirmation + """ + + def _display(msg, paths): + if not paths: + return + + logger.info(msg) + with indent_log(): + for path in sorted(compact(paths)): + logger.info(path) + + if not verbose: + will_remove, will_skip = compress_for_output_listing(self.paths) + else: + # In verbose mode, display all the files that are going to be + # deleted. + will_remove = list(self.paths) + will_skip = set() + + _display('Would remove:', will_remove) + _display('Would not remove (might be manually added):', will_skip) + _display('Would not remove (outside of prefix):', self._refuse) + + return ask('Proceed (y/n)? ', ('y', 'n')) == 'y' + + def rollback(self): + """Rollback the changes previously made by remove().""" + if self.save_dir.path is None: + logger.error( + "Can't roll back %s; was not uninstalled", + self.dist.project_name, + ) + return False + logger.info('Rolling back uninstall of %s', self.dist.project_name) + for path in self._moved_paths: + tmp_path = self._stash(path) + logger.debug('Replacing %s', path) + renames(tmp_path, path) + for pth in self.pth.values(): + pth.rollback() + + def commit(self): + """Remove temporary save dir: rollback will no longer be possible.""" + self.save_dir.cleanup() + self._moved_paths = [] + + @classmethod + def from_dist(cls, dist): + dist_path = normalize_path(dist.location) + if not dist_is_local(dist): + logger.info( + "Not uninstalling %s at %s, outside environment %s", + dist.key, + dist_path, + sys.prefix, + ) + return cls(dist) + + if dist_path in {p for p in {sysconfig.get_path("stdlib"), + sysconfig.get_path("platstdlib")} + if p}: + logger.info( + "Not uninstalling %s at %s, as it is in the standard library.", + dist.key, + dist_path, + ) + return cls(dist) + + paths_to_remove = cls(dist) + develop_egg_link = egg_link_path(dist) + develop_egg_link_egg_info = '{}.egg-info'.format( + pkg_resources.to_filename(dist.project_name)) + egg_info_exists = dist.egg_info and os.path.exists(dist.egg_info) + # Special case for distutils installed package + distutils_egg_info = getattr(dist._provider, 'path', None) + + # Uninstall cases order do matter as in the case of 2 installs of the + # same package, pip needs to uninstall the currently detected version + if (egg_info_exists and dist.egg_info.endswith('.egg-info') and + not dist.egg_info.endswith(develop_egg_link_egg_info)): + # if dist.egg_info.endswith(develop_egg_link_egg_info), we + # are in fact in the develop_egg_link case + paths_to_remove.add(dist.egg_info) + if dist.has_metadata('installed-files.txt'): + for installed_file in dist.get_metadata( + 'installed-files.txt').splitlines(): + path = os.path.normpath( + os.path.join(dist.egg_info, installed_file) + ) + paths_to_remove.add(path) + # FIXME: need a test for this elif block + # occurs with --single-version-externally-managed/--record outside + # of pip + elif dist.has_metadata('top_level.txt'): + if dist.has_metadata('namespace_packages.txt'): + namespaces = dist.get_metadata('namespace_packages.txt') + else: + namespaces = [] + for top_level_pkg in [ + p for p + in dist.get_metadata('top_level.txt').splitlines() + if p and p not in namespaces]: + path = os.path.join(dist.location, top_level_pkg) + paths_to_remove.add(path) + paths_to_remove.add(path + '.py') + paths_to_remove.add(path + '.pyc') + paths_to_remove.add(path + '.pyo') + + elif distutils_egg_info: + raise UninstallationError( + "Cannot uninstall {!r}. It is a distutils installed project " + "and thus we cannot accurately determine which files belong " + "to it which would lead to only a partial uninstall.".format( + dist.project_name, + ) + ) + + elif dist.location.endswith('.egg'): + # package installed by easy_install + # We cannot match on dist.egg_name because it can slightly vary + # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg + paths_to_remove.add(dist.location) + easy_install_egg = os.path.split(dist.location)[1] + easy_install_pth = os.path.join(os.path.dirname(dist.location), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg) + + elif egg_info_exists and dist.egg_info.endswith('.dist-info'): + for path in uninstallation_paths(dist): + paths_to_remove.add(path) + + elif develop_egg_link: + # develop egg + with open(develop_egg_link, 'r') as fh: + link_pointer = os.path.normcase(fh.readline().strip()) + assert (link_pointer == dist.location), ( + 'Egg-link %s does not match installed location of %s ' + '(at %s)' % (link_pointer, dist.project_name, dist.location) + ) + paths_to_remove.add(develop_egg_link) + easy_install_pth = os.path.join(os.path.dirname(develop_egg_link), + 'easy-install.pth') + paths_to_remove.add_pth(easy_install_pth, dist.location) + + else: + logger.debug( + 'Not sure how to uninstall: %s - Check: %s', + dist, dist.location, + ) + + # find distutils scripts= scripts + if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'): + for script in dist.metadata_listdir('scripts'): + if dist_in_usersite(dist): + bin_dir = bin_user + else: + bin_dir = bin_py + paths_to_remove.add(os.path.join(bin_dir, script)) + if WINDOWS: + paths_to_remove.add(os.path.join(bin_dir, script) + '.bat') + + # find console_scripts + _scripts_to_remove = [] + console_scripts = dist.get_entry_map(group='console_scripts') + for name in console_scripts.keys(): + _scripts_to_remove.extend(_script_names(dist, name, False)) + # find gui_scripts + gui_scripts = dist.get_entry_map(group='gui_scripts') + for name in gui_scripts.keys(): + _scripts_to_remove.extend(_script_names(dist, name, True)) + + for s in _scripts_to_remove: + paths_to_remove.add(s) + + return paths_to_remove + + +class UninstallPthEntries(object): + def __init__(self, pth_file): + if not os.path.isfile(pth_file): + raise UninstallationError( + "Cannot remove entries from nonexistent file %s" % pth_file + ) + self.file = pth_file + self.entries = set() + self._saved_lines = None + + def add(self, entry): + entry = os.path.normcase(entry) + # On Windows, os.path.normcase converts the entry to use + # backslashes. This is correct for entries that describe absolute + # paths outside of site-packages, but all the others use forward + # slashes. + if WINDOWS and not os.path.splitdrive(entry)[0]: + entry = entry.replace('\\', '/') + self.entries.add(entry) + + def remove(self): + logger.debug('Removing pth entries from %s:', self.file) + with open(self.file, 'rb') as fh: + # windows uses '\r\n' with py3k, but uses '\n' with py2.x + lines = fh.readlines() + self._saved_lines = lines + if any(b'\r\n' in line for line in lines): + endline = '\r\n' + else: + endline = '\n' + # handle missing trailing newline + if lines and not lines[-1].endswith(endline.encode("utf-8")): + lines[-1] = lines[-1] + endline.encode("utf-8") + for entry in self.entries: + try: + logger.debug('Removing entry: %s', entry) + lines.remove((entry + endline).encode("utf-8")) + except ValueError: + pass + with open(self.file, 'wb') as fh: + fh.writelines(lines) + + def rollback(self): + if self._saved_lines is None: + logger.error( + 'Cannot roll back changes to %s, none were made', self.file + ) + return False + logger.debug('Rolling %s back to previous state', self.file) + with open(self.file, 'wb') as fh: + fh.writelines(self._saved_lines) + return True diff --git a/winvenv/Lib/site-packages/pip/_internal/resolve.py b/winvenv/Lib/site-packages/pip/_internal/resolve.py new file mode 100644 index 0000000..2d9f1c5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/resolve.py @@ -0,0 +1,353 @@ +"""Dependency Resolution + +The dependency resolution in pip is performed as follows: + +for top-level requirements: + a. only one spec allowed per project, regardless of conflicts or not. + otherwise a "double requirement" exception is raised + b. they override sub-dependency requirements. +for sub-dependencies + a. "first found, wins" (where the order is breadth first) +""" + +import logging +from collections import defaultdict +from itertools import chain + +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, DistributionNotFound, HashError, HashErrors, + UnsupportedPythonVersion, +) +from pip._internal.req.constructors import install_req_from_req +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import dist_in_usersite, ensure_dir +from pip._internal.utils.packaging import check_dist_requires_python + +logger = logging.getLogger(__name__) + + +class Resolver(object): + """Resolves which packages need to be installed/uninstalled to perform \ + the requested operation without breaking the requirements of any package. + """ + + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__(self, preparer, session, finder, wheel_cache, use_user_site, + ignore_dependencies, ignore_installed, ignore_requires_python, + force_reinstall, isolated, upgrade_strategy): + super(Resolver, self).__init__() + assert upgrade_strategy in self._allowed_strategies + + self.preparer = preparer + self.finder = finder + self.session = session + + # NOTE: This would eventually be replaced with a cache that can give + # information about both sdist and wheels transparently. + self.wheel_cache = wheel_cache + + self.require_hashes = None # This is set in resolve + + self.upgrade_strategy = upgrade_strategy + self.force_reinstall = force_reinstall + self.isolated = isolated + self.ignore_dependencies = ignore_dependencies + self.ignore_installed = ignore_installed + self.ignore_requires_python = ignore_requires_python + self.use_user_site = use_user_site + + self._discovered_dependencies = defaultdict(list) + + def resolve(self, requirement_set): + """Resolve what operations need to be done + + As a side-effect of this method, the packages (and their dependencies) + are downloaded, unpacked and prepared for installation. This + preparation is done by ``pip.operations.prepare``. + + Once PyPI has static dependency metadata available, it would be + possible to move the preparation to become a step separated from + dependency resolution. + """ + # make the wheelhouse + if self.preparer.wheel_download_dir: + ensure_dir(self.preparer.wheel_download_dir) + + # If any top-level requirement has a hash specified, enter + # hash-checking mode, which requires hashes from all. + root_reqs = ( + requirement_set.unnamed_requirements + + list(requirement_set.requirements.values()) + ) + self.require_hashes = ( + requirement_set.require_hashes or + any(req.has_hash_options for req in root_reqs) + ) + + # Display where finder is looking for packages + locations = self.finder.get_formatted_locations() + if locations: + logger.info(locations) + + # Actually prepare the files, and collect any exceptions. Most hash + # exceptions cannot be checked ahead of time, because + # req.populate_link() needs to be called before we can make decisions + # based on link type. + discovered_reqs = [] + hash_errors = HashErrors() + for req in chain(root_reqs, discovered_reqs): + try: + discovered_reqs.extend( + self._resolve_one(requirement_set, req) + ) + except HashError as exc: + exc.req = req + hash_errors.append(exc) + + if hash_errors: + raise hash_errors + + def _is_upgrade_allowed(self, req): + if self.upgrade_strategy == "to-satisfy-only": + return False + elif self.upgrade_strategy == "eager": + return True + else: + assert self.upgrade_strategy == "only-if-needed" + return req.is_direct + + def _set_req_to_reinstall(self, req): + """ + Set a requirement to be installed. + """ + # Don't uninstall the conflict if doing a user install and the + # conflict is not a user install. + if not self.use_user_site or dist_in_usersite(req.satisfied_by): + req.conflicts_with = req.satisfied_by + req.satisfied_by = None + + # XXX: Stop passing requirement_set for options + def _check_skip_installed(self, req_to_install): + """Check if req_to_install should be skipped. + + This will check if the req is installed, and whether we should upgrade + or reinstall it, taking into account all the relevant user options. + + After calling this req_to_install will only have satisfied_by set to + None if the req_to_install is to be upgraded/reinstalled etc. Any + other value will be a dist recording the current thing installed that + satisfies the requirement. + + Note that for vcs urls and the like we can't assess skipping in this + routine - we simply identify that we need to pull the thing down, + then later on it is pulled down and introspected to assess upgrade/ + reinstalls etc. + + :return: A text reason for why it was skipped, or None. + """ + if self.ignore_installed: + return None + + req_to_install.check_if_exists(self.use_user_site) + if not req_to_install.satisfied_by: + return None + + if self.force_reinstall: + self._set_req_to_reinstall(req_to_install) + return None + + if not self._is_upgrade_allowed(req_to_install): + if self.upgrade_strategy == "only-if-needed": + return 'already satisfied, skipping upgrade' + return 'already satisfied' + + # Check for the possibility of an upgrade. For link-based + # requirements we have to pull the tree down and inspect to assess + # the version #, so it's handled way down. + if not req_to_install.link: + try: + self.finder.find_requirement(req_to_install, upgrade=True) + except BestVersionAlreadyInstalled: + # Then the best version is installed. + return 'already up-to-date' + except DistributionNotFound: + # No distribution found, so we squash the error. It will + # be raised later when we re-try later to do the install. + # Why don't we just raise here? + pass + + self._set_req_to_reinstall(req_to_install) + return None + + def _get_abstract_dist_for(self, req): + """Takes a InstallRequirement and returns a single AbstractDist \ + representing a prepared variant of the same. + """ + assert self.require_hashes is not None, ( + "require_hashes should have been set in Resolver.resolve()" + ) + + if req.editable: + return self.preparer.prepare_editable_requirement( + req, self.require_hashes, self.use_user_site, self.finder, + ) + + # satisfied_by is only evaluated by calling _check_skip_installed, + # so it must be None here. + assert req.satisfied_by is None + skip_reason = self._check_skip_installed(req) + + if req.satisfied_by: + return self.preparer.prepare_installed_requirement( + req, self.require_hashes, skip_reason + ) + + upgrade_allowed = self._is_upgrade_allowed(req) + abstract_dist = self.preparer.prepare_linked_requirement( + req, self.session, self.finder, upgrade_allowed, + self.require_hashes + ) + + # NOTE + # The following portion is for determining if a certain package is + # going to be re-installed/upgraded or not and reporting to the user. + # This should probably get cleaned up in a future refactor. + + # req.req is only avail after unpack for URL + # pkgs repeat check_if_exists to uninstall-on-upgrade + # (#14) + if not self.ignore_installed: + req.check_if_exists(self.use_user_site) + + if req.satisfied_by: + should_modify = ( + self.upgrade_strategy != "to-satisfy-only" or + self.force_reinstall or + self.ignore_installed or + req.link.scheme == 'file' + ) + if should_modify: + self._set_req_to_reinstall(req) + else: + logger.info( + 'Requirement already satisfied (use --upgrade to upgrade):' + ' %s', req, + ) + + return abstract_dist + + def _resolve_one(self, requirement_set, req_to_install): + """Prepare a single requirements file. + + :return: A list of additional InstallRequirements to also install. + """ + # Tell user what we are doing for this requirement: + # obtain (editable), skipping, processing (local url), collecting + # (remote url or package name) + if req_to_install.constraint or req_to_install.prepared: + return [] + + req_to_install.prepared = True + + # register tmp src for cleanup in case something goes wrong + requirement_set.reqs_to_cleanup.append(req_to_install) + + abstract_dist = self._get_abstract_dist_for(req_to_install) + + # Parse and return dependencies + dist = abstract_dist.dist(self.finder) + try: + check_dist_requires_python(dist) + except UnsupportedPythonVersion as err: + if self.ignore_requires_python: + logger.warning(err.args[0]) + else: + raise + + more_reqs = [] + + def add_req(subreq, extras_requested): + sub_install_req = install_req_from_req( + str(subreq), + req_to_install, + isolated=self.isolated, + wheel_cache=self.wheel_cache, + ) + parent_req_name = req_to_install.name + to_scan_again, add_to_parent = requirement_set.add_requirement( + sub_install_req, + parent_req_name=parent_req_name, + extras_requested=extras_requested, + ) + if parent_req_name and add_to_parent: + self._discovered_dependencies[parent_req_name].append( + add_to_parent + ) + more_reqs.extend(to_scan_again) + + with indent_log(): + # We add req_to_install before its dependencies, so that we + # can refer to it when adding dependencies. + if not requirement_set.has_requirement(req_to_install.name): + # 'unnamed' requirements will get added here + req_to_install.is_direct = True + requirement_set.add_requirement( + req_to_install, parent_req_name=None, + ) + + if not self.ignore_dependencies: + if req_to_install.extras: + logger.debug( + "Installing extra requirements: %r", + ','.join(req_to_install.extras), + ) + missing_requested = sorted( + set(req_to_install.extras) - set(dist.extras) + ) + for missing in missing_requested: + logger.warning( + '%s does not provide the extra \'%s\'', + dist, missing + ) + + available_requested = sorted( + set(dist.extras) & set(req_to_install.extras) + ) + for subreq in dist.requires(available_requested): + add_req(subreq, extras_requested=available_requested) + + if not req_to_install.editable and not req_to_install.satisfied_by: + # XXX: --no-install leads this to report 'Successfully + # downloaded' for only non-editable reqs, even though we took + # action on them. + requirement_set.successfully_downloaded.append(req_to_install) + + return more_reqs + + def get_installation_order(self, req_set): + """Create the installation order. + + The installation order is topological - requirements are installed + before the requiring thing. We break cycles at an arbitrary point, + and make no other guarantees. + """ + # The current implementation, which we may change at any point + # installs the user specified things in the order given, except when + # dependencies must come earlier to achieve topological order. + order = [] + ordered_reqs = set() + + def schedule(req): + if req.satisfied_by or req in ordered_reqs: + return + if req.constraint: + return + ordered_reqs.add(req) + for dep in self._discovered_dependencies[req.name]: + schedule(dep) + order.append(req) + + for install_req in req_set.requirements.values(): + schedule(install_req) + return order diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/__init__.py b/winvenv/Lib/site-packages/pip/_internal/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/appdirs.py b/winvenv/Lib/site-packages/pip/_internal/utils/appdirs.py new file mode 100644 index 0000000..cc96f98 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/appdirs.py @@ -0,0 +1,258 @@ +""" +This code was taken from https://github.com/ActiveState/appdirs and modified +to suit our purposes. +""" +from __future__ import absolute_import + +import os +import sys + +from pip._vendor.six import PY2, text_type + +from pip._internal.utils.compat import WINDOWS, expanduser + + +def user_cache_dir(appname): + r""" + Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + + Typical user cache directories are: + macOS: ~/Library/Caches/ + Unix: ~/.cache/ (XDG default) + Windows: C:\Users\\AppData\Local\\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go + in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the + non-roaming app data dir (the default returned by `user_data_dir`). Apps + typically put cache data somewhere *under* the given dir here. Some + examples: + ...\Mozilla\Firefox\Profiles\\Cache + ...\Acme\SuperApp\Cache\1.0 + + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + """ + if WINDOWS: + # Get the base path + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + + # When using Python 2, return paths as bytes on Windows like we do on + # other operating systems. See helper function docs for more details. + if PY2 and isinstance(path, text_type): + path = _win_path_to_bytes(path) + + # Add our app name and Cache directory to it + path = os.path.join(path, appname, "Cache") + elif sys.platform == "darwin": + # Get the base path + path = expanduser("~/Library/Caches") + + # Add our app name to it + path = os.path.join(path, appname) + else: + # Get the base path + path = os.getenv("XDG_CACHE_HOME", expanduser("~/.cache")) + + # Add our app name to it + path = os.path.join(path, appname) + + return path + + +def user_data_dir(appname, roaming=False): + r""" + Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user data directories are: + macOS: ~/Library/Application Support/ + if it exists, else ~/.config/ + Unix: ~/.local/share/ # or in + $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\\ ... + ...Application Data\ + Win XP (roaming): C:\Documents and Settings\\Local ... + ...Settings\Application Data\ + Win 7 (not roaming): C:\\Users\\AppData\Local\ + Win 7 (roaming): C:\\Users\\AppData\Roaming\ + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/". + """ + if WINDOWS: + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.join(os.path.normpath(_get_win_folder(const)), appname) + elif sys.platform == "darwin": + path = os.path.join( + expanduser('~/Library/Application Support/'), + appname, + ) if os.path.isdir(os.path.join( + expanduser('~/Library/Application Support/'), + appname, + ) + ) else os.path.join( + expanduser('~/.config/'), + appname, + ) + else: + path = os.path.join( + os.getenv('XDG_DATA_HOME', expanduser("~/.local/share")), + appname, + ) + + return path + + +def user_config_dir(appname, roaming=True): + """Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "roaming" (boolean, default True) can be set False to not use the + Windows roaming appdata directory. That means that for users on a + Windows network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user data directories are: + macOS: same as user_data_dir + Unix: ~/.config/ + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/". + """ + if WINDOWS: + path = user_data_dir(appname, roaming=roaming) + elif sys.platform == "darwin": + path = user_data_dir(appname) + else: + path = os.getenv('XDG_CONFIG_HOME', expanduser("~/.config")) + path = os.path.join(path, appname) + + return path + + +# for the discussion regarding site_config_dirs locations +# see +def site_config_dirs(appname): + r"""Return a list of potential user-shared config dirs for this application. + + "appname" is the name of application. + + Typical user config directories are: + macOS: /Library/Application Support// + Unix: /etc or $XDG_CONFIG_DIRS[i]// for each value in + $XDG_CONFIG_DIRS + Win XP: C:\Documents and Settings\All Users\Application ... + ...Data\\ + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory + on Vista.) + Win 7: Hidden, but writeable on Win 7: + C:\ProgramData\\ + """ + if WINDOWS: + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + pathlist = [os.path.join(path, appname)] + elif sys.platform == 'darwin': + pathlist = [os.path.join('/Library/Application Support', appname)] + else: + # try looking in $XDG_CONFIG_DIRS + xdg_config_dirs = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + if xdg_config_dirs: + pathlist = [ + os.path.join(expanduser(x), appname) + for x in xdg_config_dirs.split(os.pathsep) + ] + else: + pathlist = [] + + # always look in /etc directly as well + pathlist.append('/etc') + + return pathlist + + +# -- Windows support functions -- + +def _get_win_folder_from_registry(csidl_name): + """ + This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + directory, _type = _winreg.QueryValueEx(key, shell_folder_name) + return directory + + +def _get_win_folder_with_ctypes(csidl_name): + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + + +if WINDOWS: + try: + import ctypes + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +def _win_path_to_bytes(path): + """Encode Windows paths to bytes. Only used on Python 2. + + Motivation is to be consistent with other operating systems where paths + are also returned as bytes. This avoids problems mixing bytes and Unicode + elsewhere in the codebase. For more details and discussion see + . + + If encoding using ASCII and MBCS fails, return the original Unicode path. + """ + for encoding in ('ASCII', 'MBCS'): + try: + return path.encode(encoding) + except (UnicodeEncodeError, LookupError): + pass + return path diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/compat.py b/winvenv/Lib/site-packages/pip/_internal/utils/compat.py new file mode 100644 index 0000000..3114f2d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/compat.py @@ -0,0 +1,248 @@ +"""Stuff that differs in different Python versions and platform +distributions.""" +from __future__ import absolute_import, division + +import codecs +import locale +import logging +import os +import shutil +import sys + +from pip._vendor.six import text_type + +try: + import ipaddress +except ImportError: + try: + from pip._vendor import ipaddress # type: ignore + except ImportError: + import ipaddr as ipaddress # type: ignore + ipaddress.ip_address = ipaddress.IPAddress + ipaddress.ip_network = ipaddress.IPNetwork + + +__all__ = [ + "ipaddress", "uses_pycache", "console_to_str", "native_str", + "get_path_uid", "stdlib_pkgs", "WINDOWS", "samefile", "get_terminal_size", + "get_extension_suffixes", +] + + +logger = logging.getLogger(__name__) + +if sys.version_info >= (3, 4): + uses_pycache = True + from importlib.util import cache_from_source +else: + import imp + + try: + cache_from_source = imp.cache_from_source # type: ignore + except AttributeError: + # does not use __pycache__ + cache_from_source = None + + uses_pycache = cache_from_source is not None + + +if sys.version_info >= (3, 5): + backslashreplace_decode = "backslashreplace" +else: + # In version 3.4 and older, backslashreplace exists + # but does not support use for decoding. + # We implement our own replace handler for this + # situation, so that we can consistently use + # backslash replacement for all versions. + def backslashreplace_decode_fn(err): + raw_bytes = (err.object[i] for i in range(err.start, err.end)) + if sys.version_info[0] == 2: + # Python 2 gave us characters - convert to numeric bytes + raw_bytes = (ord(b) for b in raw_bytes) + return u"".join(u"\\x%x" % c for c in raw_bytes), err.end + codecs.register_error( + "backslashreplace_decode", + backslashreplace_decode_fn, + ) + backslashreplace_decode = "backslashreplace_decode" + + +def console_to_str(data): + """Return a string, safe for output, of subprocess output. + + We assume the data is in the locale preferred encoding. + If it won't decode properly, we warn the user but decode as + best we can. + + We also ensure that the output can be safely written to + standard output without encoding errors. + """ + + # First, get the encoding we assume. This is the preferred + # encoding for the locale, unless that is not found, or + # it is ASCII, in which case assume UTF-8 + encoding = locale.getpreferredencoding() + if (not encoding) or codecs.lookup(encoding).name == "ascii": + encoding = "utf-8" + + # Now try to decode the data - if we fail, warn the user and + # decode with replacement. + try: + s = data.decode(encoding) + except UnicodeDecodeError: + logger.warning( + "Subprocess output does not appear to be encoded as %s", + encoding, + ) + s = data.decode(encoding, errors=backslashreplace_decode) + + # Make sure we can print the output, by encoding it to the output + # encoding with replacement of unencodable characters, and then + # decoding again. + # We use stderr's encoding because it's less likely to be + # redirected and if we don't find an encoding we skip this + # step (on the assumption that output is wrapped by something + # that won't fail). + # The double getattr is to deal with the possibility that we're + # being called in a situation where sys.__stderr__ doesn't exist, + # or doesn't have an encoding attribute. Neither of these cases + # should occur in normal pip use, but there's no harm in checking + # in case people use pip in (unsupported) unusual situations. + output_encoding = getattr(getattr(sys, "__stderr__", None), + "encoding", None) + + if output_encoding: + s = s.encode(output_encoding, errors="backslashreplace") + s = s.decode(output_encoding) + + return s + + +if sys.version_info >= (3,): + def native_str(s, replace=False): + if isinstance(s, bytes): + return s.decode('utf-8', 'replace' if replace else 'strict') + return s + +else: + def native_str(s, replace=False): + # Replace is ignored -- unicode to UTF-8 can't fail + if isinstance(s, text_type): + return s.encode('utf-8') + return s + + +def get_path_uid(path): + """ + Return path's uid. + + Does not follow symlinks: + https://github.com/pypa/pip/pull/935#discussion_r5307003 + + Placed this function in compat due to differences on AIX and + Jython, that should eventually go away. + + :raises OSError: When path is a symlink or can't be read. + """ + if hasattr(os, 'O_NOFOLLOW'): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + file_uid = os.fstat(fd).st_uid + os.close(fd) + else: # AIX and Jython + # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW + if not os.path.islink(path): + # older versions of Jython don't have `os.fstat` + file_uid = os.stat(path).st_uid + else: + # raise OSError for parity with os.O_NOFOLLOW above + raise OSError( + "%s is a symlink; Will not return uid for symlinks" % path + ) + return file_uid + + +if sys.version_info >= (3, 4): + from importlib.machinery import EXTENSION_SUFFIXES + + def get_extension_suffixes(): + return EXTENSION_SUFFIXES +else: + from imp import get_suffixes + + def get_extension_suffixes(): + return [suffix[0] for suffix in get_suffixes()] + + +def expanduser(path): + """ + Expand ~ and ~user constructions. + + Includes a workaround for https://bugs.python.org/issue14768 + """ + expanded = os.path.expanduser(path) + if path.startswith('~/') and expanded.startswith('//'): + expanded = expanded[1:] + return expanded + + +# packages in the stdlib that may have installation metadata, but should not be +# considered 'installed'. this theoretically could be determined based on +# dist.location (py27:`sysconfig.get_paths()['stdlib']`, +# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may +# make this ineffective, so hard-coding +stdlib_pkgs = {"python", "wsgiref", "argparse"} + + +# windows detection, covers cpython and ironpython +WINDOWS = (sys.platform.startswith("win") or + (sys.platform == 'cli' and os.name == 'nt')) + + +def samefile(file1, file2): + """Provide an alternative for os.path.samefile on Windows/Python2""" + if hasattr(os.path, 'samefile'): + return os.path.samefile(file1, file2) + else: + path1 = os.path.normcase(os.path.abspath(file1)) + path2 = os.path.normcase(os.path.abspath(file2)) + return path1 == path2 + + +if hasattr(shutil, 'get_terminal_size'): + def get_terminal_size(): + """ + Returns a tuple (x, y) representing the width(x) and the height(y) + in characters of the terminal window. + """ + return tuple(shutil.get_terminal_size()) +else: + def get_terminal_size(): + """ + Returns a tuple (x, y) representing the width(x) and the height(y) + in characters of the terminal window. + """ + def ioctl_GWINSZ(fd): + try: + import fcntl + import termios + import struct + cr = struct.unpack_from( + 'hh', + fcntl.ioctl(fd, termios.TIOCGWINSZ, '12345678') + ) + except Exception: + return None + if cr == (0, 0): + return None + return cr + cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) + if not cr: + try: + fd = os.open(os.ctermid(), os.O_RDONLY) + cr = ioctl_GWINSZ(fd) + os.close(fd) + except Exception: + pass + if not cr: + cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80)) + return int(cr[1]), int(cr[0]) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/deprecation.py b/winvenv/Lib/site-packages/pip/_internal/utils/deprecation.py new file mode 100644 index 0000000..bd744cf --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/deprecation.py @@ -0,0 +1,89 @@ +""" +A module that implements tooling to enable easy warnings about deprecations. +""" +from __future__ import absolute_import + +import logging +import warnings + +from pip._vendor.packaging.version import parse + +from pip import __version__ as current_version +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any, Optional # noqa: F401 + + +class PipDeprecationWarning(Warning): + pass + + +_original_showwarning = None # type: Any + + +# Warnings <-> Logging Integration +def _showwarning(message, category, filename, lineno, file=None, line=None): + if file is not None: + if _original_showwarning is not None: + _original_showwarning( + message, category, filename, lineno, file, line, + ) + elif issubclass(category, PipDeprecationWarning): + # We use a specially named logger which will handle all of the + # deprecation messages for pip. + logger = logging.getLogger("pip._internal.deprecations") + logger.warning(message) + else: + _original_showwarning( + message, category, filename, lineno, file, line, + ) + + +def install_warning_logger(): + # Enable our Deprecation Warnings + warnings.simplefilter("default", PipDeprecationWarning, append=True) + + global _original_showwarning + + if _original_showwarning is None: + _original_showwarning = warnings.showwarning + warnings.showwarning = _showwarning + + +def deprecated(reason, replacement, gone_in, issue=None): + # type: (str, Optional[str], Optional[str], Optional[int]) -> None + """Helper to deprecate existing functionality. + + reason: + Textual reason shown to the user about why this functionality has + been deprecated. + replacement: + Textual suggestion shown to the user about what alternative + functionality they can use. + gone_in: + The version of pip does this functionality should get removed in. + Raises errors if pip's current version is greater than or equal to + this. + issue: + Issue number on the tracker that would serve as a useful place for + users to find related discussion and provide feedback. + + Always pass replacement, gone_in and issue as keyword arguments for clarity + at the call site. + """ + + # Construct a nice message. + # This is purposely eagerly formatted as we want it to appear as if someone + # typed this entire message out. + message = "DEPRECATION: " + reason + if replacement is not None: + message += " A possible replacement is {}.".format(replacement) + if issue is not None: + url = "https://github.com/pypa/pip/issues/" + str(issue) + message += " You can find discussion regarding this at {}.".format(url) + + # Raise as an error if it has to be removed. + if gone_in is not None and parse(current_version) >= parse(gone_in): + raise PipDeprecationWarning(message) + warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/encoding.py b/winvenv/Lib/site-packages/pip/_internal/utils/encoding.py new file mode 100644 index 0000000..56f6036 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/encoding.py @@ -0,0 +1,33 @@ +import codecs +import locale +import re +import sys + +BOMS = [ + (codecs.BOM_UTF8, 'utf8'), + (codecs.BOM_UTF16, 'utf16'), + (codecs.BOM_UTF16_BE, 'utf16-be'), + (codecs.BOM_UTF16_LE, 'utf16-le'), + (codecs.BOM_UTF32, 'utf32'), + (codecs.BOM_UTF32_BE, 'utf32-be'), + (codecs.BOM_UTF32_LE, 'utf32-le'), +] + +ENCODING_RE = re.compile(br'coding[:=]\s*([-\w.]+)') + + +def auto_decode(data): + """Check a bytes string for a BOM to correctly detect the encoding + + Fallback to locale.getpreferredencoding(False) like open() on Python3""" + for bom, encoding in BOMS: + if data.startswith(bom): + return data[len(bom):].decode(encoding) + # Lets check the first two lines as in PEP263 + for line in data.split(b'\n')[:2]: + if line[0:1] == b'#' and ENCODING_RE.search(line): + encoding = ENCODING_RE.search(line).groups()[0].decode('ascii') + return data.decode(encoding) + return data.decode( + locale.getpreferredencoding(False) or sys.getdefaultencoding(), + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/filesystem.py b/winvenv/Lib/site-packages/pip/_internal/utils/filesystem.py new file mode 100644 index 0000000..1e9cebd --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/filesystem.py @@ -0,0 +1,28 @@ +import os +import os.path + +from pip._internal.utils.compat import get_path_uid + + +def check_path_owner(path): + # If we don't have a way to check the effective uid of this process, then + # we'll just assume that we own the directory. + if not hasattr(os, "geteuid"): + return True + + previous = None + while path != previous: + if os.path.lexists(path): + # Check if path is writable by current user. + if os.geteuid() == 0: + # Special handling for root user in order to handle properly + # cases where users use sudo without -H flag. + try: + path_uid = get_path_uid(path) + except OSError: + return False + return path_uid == 0 + else: + return os.access(path, os.W_OK) + else: + previous, path = path, os.path.dirname(path) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/glibc.py b/winvenv/Lib/site-packages/pip/_internal/utils/glibc.py new file mode 100644 index 0000000..ebcfc5b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/glibc.py @@ -0,0 +1,84 @@ +from __future__ import absolute_import + +import ctypes +import re +import warnings + + +def glibc_version_string(): + "Returns glibc version string, or None if not using glibc." + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# Separated out from have_compatible_glibc for easier unit testing +def check_glibc_version(version_str, required_major, minimum_minor): + # Parse string and check against requested version. + # + # We use a regexp instead of str.split because we want to discard any + # random junk that might come after the minor version -- this might happen + # in patched/forked versions of glibc (e.g. Linaro's version of glibc + # uses version strings like "2.20-2014.11"). See gh-3588. + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn("Expected glibc version with 2 components major.minor," + " got: %s" % version_str, RuntimeWarning) + return False + return (int(m.group("major")) == required_major and + int(m.group("minor")) >= minimum_minor) + + +def have_compatible_glibc(required_major, minimum_minor): + version_str = glibc_version_string() + if version_str is None: + return False + return check_glibc_version(version_str, required_major, minimum_minor) + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver(): + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/hashes.py b/winvenv/Lib/site-packages/pip/_internal/utils/hashes.py new file mode 100644 index 0000000..8b909ba --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/hashes.py @@ -0,0 +1,94 @@ +from __future__ import absolute_import + +import hashlib + +from pip._vendor.six import iteritems, iterkeys, itervalues + +from pip._internal.exceptions import ( + HashMismatch, HashMissing, InstallationError, +) +from pip._internal.utils.misc import read_chunks + +# The recommended hash algo of the moment. Change this whenever the state of +# the art changes; it won't hurt backward compatibility. +FAVORITE_HASH = 'sha256' + + +# Names of hashlib algorithms allowed by the --hash option and ``pip hash`` +# Currently, those are the ones at least as collision-resistant as sha256. +STRONG_HASHES = ['sha256', 'sha384', 'sha512'] + + +class Hashes(object): + """A wrapper that builds multiple hashes at once and checks them against + known-good values + + """ + def __init__(self, hashes=None): + """ + :param hashes: A dict of algorithm names pointing to lists of allowed + hex digests + """ + self._allowed = {} if hashes is None else hashes + + def check_against_chunks(self, chunks): + """Check good hashes against ones built from iterable of chunks of + data. + + Raise HashMismatch if none match. + + """ + gots = {} + for hash_name in iterkeys(self._allowed): + try: + gots[hash_name] = hashlib.new(hash_name) + except (ValueError, TypeError): + raise InstallationError('Unknown hash name: %s' % hash_name) + + for chunk in chunks: + for hash in itervalues(gots): + hash.update(chunk) + + for hash_name, got in iteritems(gots): + if got.hexdigest() in self._allowed[hash_name]: + return + self._raise(gots) + + def _raise(self, gots): + raise HashMismatch(self._allowed, gots) + + def check_against_file(self, file): + """Check good hashes against a file-like object + + Raise HashMismatch if none match. + + """ + return self.check_against_chunks(read_chunks(file)) + + def check_against_path(self, path): + with open(path, 'rb') as file: + return self.check_against_file(file) + + def __nonzero__(self): + """Return whether I know any known-good hashes.""" + return bool(self._allowed) + + def __bool__(self): + return self.__nonzero__() + + +class MissingHashes(Hashes): + """A workalike for Hashes used when we're missing a hash for a requirement + + It computes the actual hash of the requirement and raises a HashMissing + exception showing it to the user. + + """ + def __init__(self): + """Don't offer the ``hashes`` kwarg.""" + # Pass our favorite hash in to generate a "gotten hash". With the + # empty list, it will never match, so an error will always raise. + super(MissingHashes, self).__init__(hashes={FAVORITE_HASH: []}) + + def _raise(self, gots): + raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/logging.py b/winvenv/Lib/site-packages/pip/_internal/utils/logging.py new file mode 100644 index 0000000..d9b9541 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/logging.py @@ -0,0 +1,225 @@ +from __future__ import absolute_import + +import contextlib +import logging +import logging.handlers +import os + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.misc import ensure_dir + +try: + import threading +except ImportError: + import dummy_threading as threading # type: ignore + + +try: + from pip._vendor import colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None + + +_log_state = threading.local() +_log_state.indentation = 0 + + +@contextlib.contextmanager +def indent_log(num=2): + """ + A context manager which will cause the log output to be indented for any + log messages emitted inside it. + """ + _log_state.indentation += num + try: + yield + finally: + _log_state.indentation -= num + + +def get_indentation(): + return getattr(_log_state, 'indentation', 0) + + +class IndentingFormatter(logging.Formatter): + + def format(self, record): + """ + Calls the standard formatter, but will indent all of the log messages + by our current indentation level. + """ + formatted = logging.Formatter.format(self, record) + formatted = "".join([ + (" " * get_indentation()) + line + for line in formatted.splitlines(True) + ]) + return formatted + + +def _color_wrap(*colors): + def wrapped(inp): + return "".join(list(colors) + [inp, colorama.Style.RESET_ALL]) + return wrapped + + +class ColorizedStreamHandler(logging.StreamHandler): + + # Don't build up a list of colors if we don't have colorama + if colorama: + COLORS = [ + # This needs to be in order from highest logging level to lowest. + (logging.ERROR, _color_wrap(colorama.Fore.RED)), + (logging.WARNING, _color_wrap(colorama.Fore.YELLOW)), + ] + else: + COLORS = [] + + def __init__(self, stream=None, no_color=None): + logging.StreamHandler.__init__(self, stream) + self._no_color = no_color + + if WINDOWS and colorama: + self.stream = colorama.AnsiToWin32(self.stream) + + def should_color(self): + # Don't colorize things if we do not have colorama or if told not to + if not colorama or self._no_color: + return False + + real_stream = ( + self.stream if not isinstance(self.stream, colorama.AnsiToWin32) + else self.stream.wrapped + ) + + # If the stream is a tty we should color it + if hasattr(real_stream, "isatty") and real_stream.isatty(): + return True + + # If we have an ANSI term we should color it + if os.environ.get("TERM") == "ANSI": + return True + + # If anything else we should not color it + return False + + def format(self, record): + msg = logging.StreamHandler.format(self, record) + + if self.should_color(): + for level, color in self.COLORS: + if record.levelno >= level: + msg = color(msg) + break + + return msg + + +class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): + + def _open(self): + ensure_dir(os.path.dirname(self.baseFilename)) + return logging.handlers.RotatingFileHandler._open(self) + + +class MaxLevelFilter(logging.Filter): + + def __init__(self, level): + self.level = level + + def filter(self, record): + return record.levelno < self.level + + +def setup_logging(verbosity, no_color, user_log_file): + """Configures and sets up all of the logging + """ + + # Determine the level to be logging at. + if verbosity >= 1: + level = "DEBUG" + elif verbosity == -1: + level = "WARNING" + elif verbosity == -2: + level = "ERROR" + elif verbosity <= -3: + level = "CRITICAL" + else: + level = "INFO" + + # The "root" logger should match the "console" level *unless* we also need + # to log to a user log file. + include_user_log = user_log_file is not None + if include_user_log: + additional_log_file = user_log_file + root_level = "DEBUG" + else: + additional_log_file = "/dev/null" + root_level = level + + # Disable any logging besides WARNING unless we have DEBUG level logging + # enabled for vendored libraries. + vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" + + # Shorthands for clarity + log_streams = { + "stdout": "ext://sys.stdout", + "stderr": "ext://sys.stderr", + } + handler_classes = { + "stream": "pip._internal.utils.logging.ColorizedStreamHandler", + "file": "pip._internal.utils.logging.BetterRotatingFileHandler", + } + + logging.config.dictConfig({ + "version": 1, + "disable_existing_loggers": False, + "filters": { + "exclude_warnings": { + "()": "pip._internal.utils.logging.MaxLevelFilter", + "level": logging.WARNING, + }, + }, + "formatters": { + "indent": { + "()": IndentingFormatter, + "format": "%(message)s", + }, + }, + "handlers": { + "console": { + "level": level, + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stdout"], + "filters": ["exclude_warnings"], + "formatter": "indent", + }, + "console_errors": { + "level": "WARNING", + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "formatter": "indent", + }, + "user_log": { + "level": "DEBUG", + "class": handler_classes["file"], + "filename": additional_log_file, + "delay": True, + "formatter": "indent", + }, + }, + "root": { + "level": root_level, + "handlers": ["console", "console_errors"] + ( + ["user_log"] if include_user_log else [] + ), + }, + "loggers": { + "pip._vendor": { + "level": vendored_log_level + } + }, + }) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/misc.py b/winvenv/Lib/site-packages/pip/_internal/utils/misc.py new file mode 100644 index 0000000..84a421f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/misc.py @@ -0,0 +1,940 @@ +from __future__ import absolute_import + +import contextlib +import errno +import io +import locale +# we have a submodule named 'logging' which would shadow this if we used the +# regular name: +import logging as std_logging +import os +import posixpath +import re +import shutil +import stat +import subprocess +import sys +import tarfile +import zipfile +from collections import deque + +from pip._vendor import pkg_resources +# NOTE: retrying is not annotated in typeshed as on 2017-07-17, which is +# why we ignore the type on this import. +from pip._vendor.retrying import retry # type: ignore +from pip._vendor.six import PY2 +from pip._vendor.six.moves import input +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import CommandError, InstallationError +from pip._internal.locations import ( + running_under_virtualenv, site_packages, user_site, virtualenv_no_global, + write_delete_marker_file, +) +from pip._internal.utils.compat import ( + WINDOWS, console_to_str, expanduser, stdlib_pkgs, +) + +if PY2: + from io import BytesIO as StringIO +else: + from io import StringIO + +__all__ = ['rmtree', 'display_path', 'backup_dir', + 'ask', 'splitext', + 'format_size', 'is_installable_dir', + 'is_svn_page', 'file_contents', + 'split_leading_dir', 'has_leading_dir', + 'normalize_path', + 'renames', 'get_prog', + 'unzip_file', 'untar_file', 'unpack_file', 'call_subprocess', + 'captured_stdout', 'ensure_dir', + 'ARCHIVE_EXTENSIONS', 'SUPPORTED_EXTENSIONS', + 'get_installed_version', 'remove_auth_from_url'] + + +logger = std_logging.getLogger(__name__) + +BZ2_EXTENSIONS = ('.tar.bz2', '.tbz') +XZ_EXTENSIONS = ('.tar.xz', '.txz', '.tlz', '.tar.lz', '.tar.lzma') +ZIP_EXTENSIONS = ('.zip', '.whl') +TAR_EXTENSIONS = ('.tar.gz', '.tgz', '.tar') +ARCHIVE_EXTENSIONS = ( + ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS) +SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS +try: + import bz2 # noqa + SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS +except ImportError: + logger.debug('bz2 module is not available') + +try: + # Only for Python 3.3+ + import lzma # noqa + SUPPORTED_EXTENSIONS += XZ_EXTENSIONS +except ImportError: + logger.debug('lzma module is not available') + + +def import_or_raise(pkg_or_module_string, ExceptionType, *args, **kwargs): + try: + return __import__(pkg_or_module_string) + except ImportError: + raise ExceptionType(*args, **kwargs) + + +def ensure_dir(path): + """os.path.makedirs without EEXIST.""" + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + +def get_prog(): + try: + prog = os.path.basename(sys.argv[0]) + if prog in ('__main__.py', '-c'): + return "%s -m pip" % sys.executable + else: + return prog + except (AttributeError, TypeError, IndexError): + pass + return 'pip' + + +# Retry every half second for up to 3 seconds +@retry(stop_max_delay=3000, wait_fixed=500) +def rmtree(dir, ignore_errors=False): + shutil.rmtree(dir, ignore_errors=ignore_errors, + onerror=rmtree_errorhandler) + + +def rmtree_errorhandler(func, path, exc_info): + """On Windows, the files in .svn are read-only, so when rmtree() tries to + remove them, an exception is thrown. We catch that here, remove the + read-only attribute, and hopefully continue without problems.""" + # if file type currently read only + if os.stat(path).st_mode & stat.S_IREAD: + # convert to read/write + os.chmod(path, stat.S_IWRITE) + # use the original function to repeat the operation + func(path) + return + else: + raise + + +def display_path(path): + """Gives the display value for a given path, making it relative to cwd + if possible.""" + path = os.path.normcase(os.path.abspath(path)) + if sys.version_info[0] == 2: + path = path.decode(sys.getfilesystemencoding(), 'replace') + path = path.encode(sys.getdefaultencoding(), 'replace') + if path.startswith(os.getcwd() + os.path.sep): + path = '.' + path[len(os.getcwd()):] + return path + + +def backup_dir(dir, ext='.bak'): + """Figure out the name of a directory to back up the given dir to + (adding .bak, .bak2, etc)""" + n = 1 + extension = ext + while os.path.exists(dir + extension): + n += 1 + extension = ext + str(n) + return dir + extension + + +def ask_path_exists(message, options): + for action in os.environ.get('PIP_EXISTS_ACTION', '').split(): + if action in options: + return action + return ask(message, options) + + +def ask(message, options): + """Ask the message interactively, with the given possible responses""" + while 1: + if os.environ.get('PIP_NO_INPUT'): + raise Exception( + 'No input was expected ($PIP_NO_INPUT set); question: %s' % + message + ) + response = input(message) + response = response.strip().lower() + if response not in options: + print( + 'Your response (%r) was not one of the expected responses: ' + '%s' % (response, ', '.join(options)) + ) + else: + return response + + +def format_size(bytes): + if bytes > 1000 * 1000: + return '%.1fMB' % (bytes / 1000.0 / 1000) + elif bytes > 10 * 1000: + return '%ikB' % (bytes / 1000) + elif bytes > 1000: + return '%.1fkB' % (bytes / 1000.0) + else: + return '%ibytes' % bytes + + +def is_installable_dir(path): + """Is path is a directory containing setup.py or pyproject.toml? + """ + if not os.path.isdir(path): + return False + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + return True + pyproject_toml = os.path.join(path, 'pyproject.toml') + if os.path.isfile(pyproject_toml): + return True + return False + + +def is_svn_page(html): + """ + Returns true if the page appears to be the index page of an svn repository + """ + return (re.search(r'[^<]*Revision \d+:', html) and + re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I)) + + +def file_contents(filename): + with open(filename, 'rb') as fp: + return fp.read().decode('utf-8') + + +def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE): + """Yield pieces of data from a file-like object until EOF.""" + while True: + chunk = file.read(size) + if not chunk: + break + yield chunk + + +def split_leading_dir(path): + path = path.lstrip('/').lstrip('\\') + if '/' in path and (('\\' in path and path.find('/') < path.find('\\')) or + '\\' not in path): + return path.split('/', 1) + elif '\\' in path: + return path.split('\\', 1) + else: + return path, '' + + +def has_leading_dir(paths): + """Returns true if all the paths have the same leading path name + (i.e., everything is in one subdirectory in an archive)""" + common_prefix = None + for path in paths: + prefix, rest = split_leading_dir(path) + if not prefix: + return False + elif common_prefix is None: + common_prefix = prefix + elif prefix != common_prefix: + return False + return True + + +def normalize_path(path, resolve_symlinks=True): + """ + Convert a path to its canonical, case-normalized, absolute version. + + """ + path = expanduser(path) + if resolve_symlinks: + path = os.path.realpath(path) + else: + path = os.path.abspath(path) + return os.path.normcase(path) + + +def splitext(path): + """Like os.path.splitext, but take off .tar too""" + base, ext = posixpath.splitext(path) + if base.lower().endswith('.tar'): + ext = base[-4:] + ext + base = base[:-4] + return base, ext + + +def renames(old, new): + """Like os.renames(), but handles renaming across devices.""" + # Implementation borrowed from os.renames(). + head, tail = os.path.split(new) + if head and tail and not os.path.exists(head): + os.makedirs(head) + + shutil.move(old, new) + + head, tail = os.path.split(old) + if head and tail: + try: + os.removedirs(head) + except OSError: + pass + + +def is_local(path): + """ + Return True if path is within sys.prefix, if we're running in a virtualenv. + + If we're not in a virtualenv, all paths are considered "local." + + """ + if not running_under_virtualenv(): + return True + return normalize_path(path).startswith(normalize_path(sys.prefix)) + + +def dist_is_local(dist): + """ + Return True if given Distribution object is installed locally + (i.e. within current virtualenv). + + Always True if we're not in a virtualenv. + + """ + return is_local(dist_location(dist)) + + +def dist_in_usersite(dist): + """ + Return True if given Distribution is installed in user site. + """ + norm_path = normalize_path(dist_location(dist)) + return norm_path.startswith(normalize_path(user_site)) + + +def dist_in_site_packages(dist): + """ + Return True if given Distribution is installed in + sysconfig.get_python_lib(). + """ + return normalize_path( + dist_location(dist) + ).startswith(normalize_path(site_packages)) + + +def dist_is_editable(dist): + """Is distribution an editable install?""" + for path_item in sys.path: + egg_link = os.path.join(path_item, dist.project_name + '.egg-link') + if os.path.isfile(egg_link): + return True + return False + + +def get_installed_distributions(local_only=True, + skip=stdlib_pkgs, + include_editables=True, + editables_only=False, + user_only=False): + """ + Return a list of installed Distribution objects. + + If ``local_only`` is True (default), only return installations + local to the current virtualenv, if in a virtualenv. + + ``skip`` argument is an iterable of lower-case project names to + ignore; defaults to stdlib_pkgs + + If ``include_editables`` is False, don't report editables. + + If ``editables_only`` is True , only report editables. + + If ``user_only`` is True , only report installations in the user + site directory. + + """ + if local_only: + local_test = dist_is_local + else: + def local_test(d): + return True + + if include_editables: + def editable_test(d): + return True + else: + def editable_test(d): + return not dist_is_editable(d) + + if editables_only: + def editables_only_test(d): + return dist_is_editable(d) + else: + def editables_only_test(d): + return True + + if user_only: + user_test = dist_in_usersite + else: + def user_test(d): + return True + + return [d for d in pkg_resources.working_set + if local_test(d) and + d.key not in skip and + editable_test(d) and + editables_only_test(d) and + user_test(d) + ] + + +def egg_link_path(dist): + """ + Return the path for the .egg-link file if it exists, otherwise, None. + + There's 3 scenarios: + 1) not in a virtualenv + try to find in site.USER_SITE, then site_packages + 2) in a no-global virtualenv + try to find in site_packages + 3) in a yes-global virtualenv + try to find in site_packages, then site.USER_SITE + (don't look in global location) + + For #1 and #3, there could be odd cases, where there's an egg-link in 2 + locations. + + This method will just return the first one found. + """ + sites = [] + if running_under_virtualenv(): + if virtualenv_no_global(): + sites.append(site_packages) + else: + sites.append(site_packages) + if user_site: + sites.append(user_site) + else: + if user_site: + sites.append(user_site) + sites.append(site_packages) + + for site in sites: + egglink = os.path.join(site, dist.project_name) + '.egg-link' + if os.path.isfile(egglink): + return egglink + + +def dist_location(dist): + """ + Get the site-packages location of this distribution. Generally + this is dist.location, except in the case of develop-installed + packages, where dist.location is the source code location, and we + want to know where the egg-link file is. + + """ + egg_link = egg_link_path(dist) + if egg_link: + return egg_link + return dist.location + + +def current_umask(): + """Get the current umask which involves having to set it temporarily.""" + mask = os.umask(0) + os.umask(mask) + return mask + + +def unzip_file(filename, location, flatten=True): + """ + Unzip the file (with path `filename`) to the destination `location`. All + files are written based on system defaults and umask (i.e. permissions are + not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + zipfp = open(filename, 'rb') + try: + zip = zipfile.ZipFile(zipfp, allowZip64=True) + leading = has_leading_dir(zip.namelist()) and flatten + for info in zip.infolist(): + name = info.filename + data = zip.read(name) + fn = name + if leading: + fn = split_leading_dir(name)[1] + fn = os.path.join(location, fn) + dir = os.path.dirname(fn) + if fn.endswith('/') or fn.endswith('\\'): + # A directory + ensure_dir(fn) + else: + ensure_dir(dir) + fp = open(fn, 'wb') + try: + fp.write(data) + finally: + fp.close() + mode = info.external_attr >> 16 + # if mode and regular file and any execute permissions for + # user/group/world? + if mode and stat.S_ISREG(mode) and mode & 0o111: + # make dest file have execute for user/group/world + # (chmod +x) no-op on windows per python docs + os.chmod(fn, (0o777 - current_umask() | 0o111)) + finally: + zipfp.close() + + +def untar_file(filename, location): + """ + Untar the file (with path `filename`) to the destination `location`. + All files are written based on system defaults and umask (i.e. permissions + are not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'): + mode = 'r:gz' + elif filename.lower().endswith(BZ2_EXTENSIONS): + mode = 'r:bz2' + elif filename.lower().endswith(XZ_EXTENSIONS): + mode = 'r:xz' + elif filename.lower().endswith('.tar'): + mode = 'r' + else: + logger.warning( + 'Cannot determine compression type for file %s', filename, + ) + mode = 'r:*' + tar = tarfile.open(filename, mode) + try: + # note: python<=2.5 doesn't seem to know about pax headers, filter them + leading = has_leading_dir([ + member.name for member in tar.getmembers() + if member.name != 'pax_global_header' + ]) + for member in tar.getmembers(): + fn = member.name + if fn == 'pax_global_header': + continue + if leading: + fn = split_leading_dir(fn)[1] + path = os.path.join(location, fn) + if member.isdir(): + ensure_dir(path) + elif member.issym(): + try: + tar._extract_member(member, path) + except Exception as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + 'In the tar file %s the member %s is invalid: %s', + filename, member.name, exc, + ) + continue + else: + try: + fp = tar.extractfile(member) + except (KeyError, AttributeError) as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + 'In the tar file %s the member %s is invalid: %s', + filename, member.name, exc, + ) + continue + ensure_dir(os.path.dirname(path)) + with open(path, 'wb') as destfp: + shutil.copyfileobj(fp, destfp) + fp.close() + # Update the timestamp (useful for cython compiled files) + tar.utime(member, path) + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + # make dest file have execute for user/group/world + # no-op on windows per python docs + os.chmod(path, (0o777 - current_umask() | 0o111)) + finally: + tar.close() + + +def unpack_file(filename, location, content_type, link): + filename = os.path.realpath(filename) + if (content_type == 'application/zip' or + filename.lower().endswith(ZIP_EXTENSIONS) or + zipfile.is_zipfile(filename)): + unzip_file( + filename, + location, + flatten=not filename.endswith('.whl') + ) + elif (content_type == 'application/x-gzip' or + tarfile.is_tarfile(filename) or + filename.lower().endswith( + TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS)): + untar_file(filename, location) + elif (content_type and content_type.startswith('text/html') and + is_svn_page(file_contents(filename))): + # We don't really care about this + from pip._internal.vcs.subversion import Subversion + Subversion('svn+' + link.url).unpack(location) + else: + # FIXME: handle? + # FIXME: magic signatures? + logger.critical( + 'Cannot unpack file %s (downloaded from %s, content-type: %s); ' + 'cannot detect archive format', + filename, location, content_type, + ) + raise InstallationError( + 'Cannot determine archive format of %s' % location + ) + + +def call_subprocess(cmd, show_stdout=True, cwd=None, + on_returncode='raise', + command_desc=None, + extra_environ=None, unset_environ=None, spinner=None): + """ + Args: + unset_environ: an iterable of environment variable names to unset + prior to calling subprocess.Popen(). + """ + if unset_environ is None: + unset_environ = [] + # This function's handling of subprocess output is confusing and I + # previously broke it terribly, so as penance I will write a long comment + # explaining things. + # + # The obvious thing that affects output is the show_stdout= + # kwarg. show_stdout=True means, let the subprocess write directly to our + # stdout. Even though it is nominally the default, it is almost never used + # inside pip (and should not be used in new code without a very good + # reason); as of 2016-02-22 it is only used in a few places inside the VCS + # wrapper code. Ideally we should get rid of it entirely, because it + # creates a lot of complexity here for a rarely used feature. + # + # Most places in pip set show_stdout=False. What this means is: + # - We connect the child stdout to a pipe, which we read. + # - By default, we hide the output but show a spinner -- unless the + # subprocess exits with an error, in which case we show the output. + # - If the --verbose option was passed (= loglevel is DEBUG), then we show + # the output unconditionally. (But in this case we don't want to show + # the output a second time if it turns out that there was an error.) + # + # stderr is always merged with stdout (even if show_stdout=True). + if show_stdout: + stdout = None + else: + stdout = subprocess.PIPE + if command_desc is None: + cmd_parts = [] + for part in cmd: + if ' ' in part or '\n' in part or '"' in part or "'" in part: + part = '"%s"' % part.replace('"', '\\"') + cmd_parts.append(part) + command_desc = ' '.join(cmd_parts) + logger.debug("Running command %s", command_desc) + env = os.environ.copy() + if extra_environ: + env.update(extra_environ) + for name in unset_environ: + env.pop(name, None) + try: + proc = subprocess.Popen( + cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE, + stdout=stdout, cwd=cwd, env=env, + ) + proc.stdin.close() + except Exception as exc: + logger.critical( + "Error %s while executing command %s", exc, command_desc, + ) + raise + all_output = [] + if stdout is not None: + while True: + line = console_to_str(proc.stdout.readline()) + if not line: + break + line = line.rstrip() + all_output.append(line + '\n') + if logger.getEffectiveLevel() <= std_logging.DEBUG: + # Show the line immediately + logger.debug(line) + else: + # Update the spinner + if spinner is not None: + spinner.spin() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() + if spinner is not None: + if proc.returncode: + spinner.finish("error") + else: + spinner.finish("done") + if proc.returncode: + if on_returncode == 'raise': + if (logger.getEffectiveLevel() > std_logging.DEBUG and + not show_stdout): + logger.info( + 'Complete output from command %s:', command_desc, + ) + logger.info( + ''.join(all_output) + + '\n----------------------------------------' + ) + raise InstallationError( + 'Command "%s" failed with error code %s in %s' + % (command_desc, proc.returncode, cwd)) + elif on_returncode == 'warn': + logger.warning( + 'Command "%s" had error code %s in %s', + command_desc, proc.returncode, cwd, + ) + elif on_returncode == 'ignore': + pass + else: + raise ValueError('Invalid value: on_returncode=%s' % + repr(on_returncode)) + if not show_stdout: + return ''.join(all_output) + + +def read_text_file(filename): + """Return the contents of *filename*. + + Try to decode the file contents with utf-8, the preferred system encoding + (e.g., cp1252 on some Windows machines), and latin1, in that order. + Decoding a byte string with latin1 will never raise an error. In the worst + case, the returned string will contain some garbage characters. + + """ + with open(filename, 'rb') as fp: + data = fp.read() + + encodings = ['utf-8', locale.getpreferredencoding(False), 'latin1'] + for enc in encodings: + try: + data = data.decode(enc) + except UnicodeDecodeError: + continue + break + + assert type(data) != bytes # Latin1 should have worked. + return data + + +def _make_build_dir(build_dir): + os.makedirs(build_dir) + write_delete_marker_file(build_dir) + + +class FakeFile(object): + """Wrap a list of lines in an object with readline() to make + ConfigParser happy.""" + def __init__(self, lines): + self._gen = (l for l in lines) + + def readline(self): + try: + try: + return next(self._gen) + except NameError: + return self._gen.next() + except StopIteration: + return '' + + def __iter__(self): + return self._gen + + +class StreamWrapper(StringIO): + + @classmethod + def from_stream(cls, orig_stream): + cls.orig_stream = orig_stream + return cls() + + # compileall.compile_dir() needs stdout.encoding to print to stdout + @property + def encoding(self): + return self.orig_stream.encoding + + +@contextlib.contextmanager +def captured_output(stream_name): + """Return a context manager used by captured_stdout/stdin/stderr + that temporarily replaces the sys stream *stream_name* with a StringIO. + + Taken from Lib/support/__init__.py in the CPython repo. + """ + orig_stdout = getattr(sys, stream_name) + setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) + try: + yield getattr(sys, stream_name) + finally: + setattr(sys, stream_name, orig_stdout) + + +def captured_stdout(): + """Capture the output of sys.stdout: + + with captured_stdout() as stdout: + print('hello') + self.assertEqual(stdout.getvalue(), 'hello\n') + + Taken from Lib/support/__init__.py in the CPython repo. + """ + return captured_output('stdout') + + +class cached_property(object): + """A property that is only computed once per instance and then replaces + itself with an ordinary attribute. Deleting the attribute resets the + property. + + Source: https://github.com/bottlepy/bottle/blob/0.11.5/bottle.py#L175 + """ + + def __init__(self, func): + self.__doc__ = getattr(func, '__doc__') + self.func = func + + def __get__(self, obj, cls): + if obj is None: + # We're being accessed from the class itself, not from an object + return self + value = obj.__dict__[self.func.__name__] = self.func(obj) + return value + + +def get_installed_version(dist_name, working_set=None): + """Get the installed version of dist_name avoiding pkg_resources cache""" + # Create a requirement that we'll look for inside of setuptools. + req = pkg_resources.Requirement.parse(dist_name) + + if working_set is None: + # We want to avoid having this cached, so we need to construct a new + # working set each time. + working_set = pkg_resources.WorkingSet() + + # Get the installed distribution from our working set + dist = working_set.find(req) + + # Check to see if we got an installed distribution or not, if we did + # we want to return it's version. + return dist.version if dist else None + + +def consume(iterator): + """Consume an iterable at C speed.""" + deque(iterator, maxlen=0) + + +# Simulates an enum +def enum(*sequential, **named): + enums = dict(zip(sequential, range(len(sequential))), **named) + reverse = {value: key for key, value in enums.items()} + enums['reverse_mapping'] = reverse + return type('Enum', (), enums) + + +def make_vcs_requirement_url(repo_url, rev, egg_project_name, subdir=None): + """ + Return the URL for a VCS requirement. + + Args: + repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+"). + """ + req = '{}@{}#egg={}'.format(repo_url, rev, egg_project_name) + if subdir: + req += '&subdirectory={}'.format(subdir) + + return req + + +def split_auth_from_netloc(netloc): + """ + Parse out and remove the auth information from a netloc. + + Returns: (netloc, (username, password)). + """ + if '@' not in netloc: + return netloc, (None, None) + + # Split from the right because that's how urllib.parse.urlsplit() + # behaves if more than one @ is present (which can be checked using + # the password attribute of urlsplit()'s return value). + auth, netloc = netloc.rsplit('@', 1) + if ':' in auth: + # Split from the left because that's how urllib.parse.urlsplit() + # behaves if more than one : is present (which again can be checked + # using the password attribute of the return value) + user_pass = tuple(auth.split(':', 1)) + else: + user_pass = auth, None + + return netloc, user_pass + + +def remove_auth_from_url(url): + # Return a copy of url with 'username:password@' removed. + # username/pass params are passed to subversion through flags + # and are not recognized in the url. + + # parsed url + purl = urllib_parse.urlsplit(url) + netloc, user_pass = split_auth_from_netloc(purl.netloc) + + # stripped url + url_pieces = ( + purl.scheme, netloc, purl.path, purl.query, purl.fragment + ) + surl = urllib_parse.urlunsplit(url_pieces) + return surl + + +def protect_pip_from_modification_on_windows(modifying_pip): + """Protection of pip.exe from modification on Windows + + On Windows, any operation modifying pip should be run as: + python -m pip ... + """ + pip_names = [ + "pip.exe", + "pip{}.exe".format(sys.version_info[0]), + "pip{}.{}.exe".format(*sys.version_info[:2]) + ] + + # See https://github.com/pypa/pip/issues/1299 for more discussion + should_show_use_python_msg = ( + modifying_pip and + WINDOWS and + os.path.basename(sys.argv[0]) in pip_names + ) + + if should_show_use_python_msg: + new_command = [ + sys.executable, "-m", "pip" + ] + sys.argv[1:] + raise CommandError( + 'To modify pip, please run the following command:\n{}' + .format(" ".join(new_command)) + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/models.py b/winvenv/Lib/site-packages/pip/_internal/utils/models.py new file mode 100644 index 0000000..d5cb80a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/models.py @@ -0,0 +1,40 @@ +"""Utilities for defining models +""" + +import operator + + +class KeyBasedCompareMixin(object): + """Provides comparision capabilities that is based on a key + """ + + def __init__(self, key, defining_class): + self._compare_key = key + self._defining_class = defining_class + + def __hash__(self): + return hash(self._compare_key) + + def __lt__(self, other): + return self._compare(other, operator.__lt__) + + def __le__(self, other): + return self._compare(other, operator.__le__) + + def __gt__(self, other): + return self._compare(other, operator.__gt__) + + def __ge__(self, other): + return self._compare(other, operator.__ge__) + + def __eq__(self, other): + return self._compare(other, operator.__eq__) + + def __ne__(self, other): + return self._compare(other, operator.__ne__) + + def _compare(self, other, method): + if not isinstance(other, self._defining_class): + return NotImplemented + + return method(self._compare_key, other._compare_key) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/outdated.py b/winvenv/Lib/site-packages/pip/_internal/utils/outdated.py new file mode 100644 index 0000000..5bfbfe1 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/outdated.py @@ -0,0 +1,154 @@ +from __future__ import absolute_import + +import datetime +import json +import logging +import os.path +import sys + +from pip._vendor import lockfile, pkg_resources +from pip._vendor.packaging import version as packaging_version + +from pip._internal.index import PackageFinder +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.misc import ensure_dir, get_installed_version + +SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" + + +logger = logging.getLogger(__name__) + + +class SelfCheckState(object): + def __init__(self, cache_dir): + self.state = {} + self.statefile_path = None + + # Try to load the existing state + if cache_dir: + self.statefile_path = os.path.join(cache_dir, "selfcheck.json") + try: + with open(self.statefile_path) as statefile: + self.state = json.load(statefile)[sys.prefix] + except (IOError, ValueError, KeyError): + # Explicitly suppressing exceptions, since we don't want to + # error out if the cache file is invalid. + pass + + def save(self, pypi_version, current_time): + # If we do not have a path to cache in, don't bother saving. + if not self.statefile_path: + return + + # Check to make sure that we own the directory + if not check_path_owner(os.path.dirname(self.statefile_path)): + return + + # Now that we've ensured the directory is owned by this user, we'll go + # ahead and make sure that all our directories are created. + ensure_dir(os.path.dirname(self.statefile_path)) + + # Attempt to write out our version check file + with lockfile.LockFile(self.statefile_path): + if os.path.exists(self.statefile_path): + with open(self.statefile_path) as statefile: + state = json.load(statefile) + else: + state = {} + + state[sys.prefix] = { + "last_check": current_time.strftime(SELFCHECK_DATE_FMT), + "pypi_version": pypi_version, + } + + with open(self.statefile_path, "w") as statefile: + json.dump(state, statefile, sort_keys=True, + separators=(",", ":")) + + +def was_installed_by_pip(pkg): + """Checks whether pkg was installed by pip + + This is used not to display the upgrade message when pip is in fact + installed by system package manager, such as dnf on Fedora. + """ + try: + dist = pkg_resources.get_distribution(pkg) + return (dist.has_metadata('INSTALLER') and + 'pip' in dist.get_metadata_lines('INSTALLER')) + except pkg_resources.DistributionNotFound: + return False + + +def pip_version_check(session, options): + """Check for an update for pip. + + Limit the frequency of checks to once per week. State is stored either in + the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix + of the pip script path. + """ + installed_version = get_installed_version("pip") + if not installed_version: + return + + pip_version = packaging_version.parse(installed_version) + pypi_version = None + + try: + state = SelfCheckState(cache_dir=options.cache_dir) + + current_time = datetime.datetime.utcnow() + # Determine if we need to refresh the state + if "last_check" in state.state and "pypi_version" in state.state: + last_check = datetime.datetime.strptime( + state.state["last_check"], + SELFCHECK_DATE_FMT + ) + if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: + pypi_version = state.state["pypi_version"] + + # Refresh the version if we need to or just see if we need to warn + if pypi_version is None: + # Lets use PackageFinder to see what the latest pip version is + finder = PackageFinder( + find_links=options.find_links, + index_urls=[options.index_url] + options.extra_index_urls, + allow_all_prereleases=False, # Explicitly set to False + trusted_hosts=options.trusted_hosts, + process_dependency_links=options.process_dependency_links, + session=session, + ) + all_candidates = finder.find_all_candidates("pip") + if not all_candidates: + return + pypi_version = str( + max(all_candidates, key=lambda c: c.version).version + ) + + # save that we've performed a check + state.save(pypi_version, current_time) + + remote_version = packaging_version.parse(pypi_version) + + # Determine if our pypi_version is older + if (pip_version < remote_version and + pip_version.base_version != remote_version.base_version and + was_installed_by_pip('pip')): + # Advise "python -m pip" on Windows to avoid issues + # with overwriting pip.exe. + if WINDOWS: + pip_cmd = "python -m pip" + else: + pip_cmd = "pip" + logger.warning( + "You are using pip version %s, however version %s is " + "available.\nYou should consider upgrading via the " + "'%s install --upgrade pip' command.", + pip_version, pypi_version, pip_cmd + ) + except Exception: + logger.debug( + "There was an error checking the latest version of pip", + exc_info=True, + ) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/packaging.py b/winvenv/Lib/site-packages/pip/_internal/utils/packaging.py new file mode 100644 index 0000000..c43142f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/packaging.py @@ -0,0 +1,75 @@ +from __future__ import absolute_import + +import logging +import sys +from email.parser import FeedParser # type: ignore + +from pip._vendor import pkg_resources +from pip._vendor.packaging import specifiers, version + +from pip._internal import exceptions +from pip._internal.utils.misc import display_path + +logger = logging.getLogger(__name__) + + +def check_requires_python(requires_python): + """ + Check if the python version in use match the `requires_python` specifier. + + Returns `True` if the version of python in use matches the requirement. + Returns `False` if the version of python in use does not matches the + requirement. + + Raises an InvalidSpecifier if `requires_python` have an invalid format. + """ + if requires_python is None: + # The package provides no information + return True + requires_python_specifier = specifiers.SpecifierSet(requires_python) + + # We only use major.minor.micro + python_version = version.parse('.'.join(map(str, sys.version_info[:3]))) + return python_version in requires_python_specifier + + +def get_metadata(dist): + if (isinstance(dist, pkg_resources.DistInfoDistribution) and + dist.has_metadata('METADATA')): + metadata = dist.get_metadata('METADATA') + elif dist.has_metadata('PKG-INFO'): + metadata = dist.get_metadata('PKG-INFO') + else: + logger.warning("No metadata found in %s", display_path(dist.location)) + metadata = '' + + feed_parser = FeedParser() + feed_parser.feed(metadata) + return feed_parser.close() + + +def check_dist_requires_python(dist): + pkg_info_dict = get_metadata(dist) + requires_python = pkg_info_dict.get('Requires-Python') + try: + if not check_requires_python(requires_python): + raise exceptions.UnsupportedPythonVersion( + "%s requires Python '%s' but the running Python is %s" % ( + dist.project_name, + requires_python, + '.'.join(map(str, sys.version_info[:3])),) + ) + except specifiers.InvalidSpecifier as e: + logger.warning( + "Package %s has an invalid Requires-Python entry %s - %s", + dist.project_name, requires_python, e, + ) + return + + +def get_installer(dist): + if dist.has_metadata('INSTALLER'): + for line in dist.get_metadata_lines('INSTALLER'): + if line.strip(): + return line.strip() + return '' diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/setuptools_build.py b/winvenv/Lib/site-packages/pip/_internal/utils/setuptools_build.py new file mode 100644 index 0000000..03973e9 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/setuptools_build.py @@ -0,0 +1,8 @@ +# Shim to wrap setup.py invocation with setuptools +SETUPTOOLS_SHIM = ( + "import setuptools, tokenize;__file__=%r;" + "f=getattr(tokenize, 'open', open)(__file__);" + "code=f.read().replace('\\r\\n', '\\n');" + "f.close();" + "exec(compile(code, __file__, 'exec'))" +) diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/temp_dir.py b/winvenv/Lib/site-packages/pip/_internal/utils/temp_dir.py new file mode 100644 index 0000000..edc506b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/temp_dir.py @@ -0,0 +1,82 @@ +from __future__ import absolute_import + +import logging +import os.path +import tempfile + +from pip._internal.utils.misc import rmtree + +logger = logging.getLogger(__name__) + + +class TempDirectory(object): + """Helper class that owns and cleans up a temporary directory. + + This class can be used as a context manager or as an OO representation of a + temporary directory. + + Attributes: + path + Location to the created temporary directory or None + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + Methods: + create() + Creates a temporary directory and stores its path in the path + attribute. + cleanup() + Deletes the temporary directory and sets path attribute to None + + When used as a context manager, a temporary directory is created on + entering the context and, if the delete attribute is True, on exiting the + context the created directory is deleted. + """ + + def __init__(self, path=None, delete=None, kind="temp"): + super(TempDirectory, self).__init__() + + if path is None and delete is None: + # If we were not given an explicit directory, and we were not given + # an explicit delete option, then we'll default to deleting. + delete = True + + self.path = path + self.delete = delete + self.kind = kind + + def __repr__(self): + return "<{} {!r}>".format(self.__class__.__name__, self.path) + + def __enter__(self): + self.create() + return self + + def __exit__(self, exc, value, tb): + if self.delete: + self.cleanup() + + def create(self): + """Create a temporary directory and store it's path in self.path + """ + if self.path is not None: + logger.debug( + "Skipped creation of temporary directory: {}".format(self.path) + ) + return + # We realpath here because some systems have their default tmpdir + # symlinked to another directory. This tends to confuse build + # scripts, so we canonicalize the path by traversing potential + # symlinks here. + self.path = os.path.realpath( + tempfile.mkdtemp(prefix="pip-{}-".format(self.kind)) + ) + logger.debug("Created temporary directory: {}".format(self.path)) + + def cleanup(self): + """Remove the temporary directory created and reset state + """ + if self.path is not None and os.path.exists(self.path): + rmtree(self.path) + self.path = None diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/typing.py b/winvenv/Lib/site-packages/pip/_internal/utils/typing.py new file mode 100644 index 0000000..e085cdf --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/typing.py @@ -0,0 +1,29 @@ +"""For neatly implementing static typing in pip. + +`mypy` - the static type analysis tool we use - uses the `typing` module, which +provides core functionality fundamental to mypy's functioning. + +Generally, `typing` would be imported at runtime and used in that fashion - +it acts as a no-op at runtime and does not have any run-time overhead by +design. + +As it turns out, `typing` is not vendorable - it uses separate sources for +Python 2/Python 3. Thus, this codebase can not expect it to be present. +To work around this, mypy allows the typing import to be behind a False-y +optional to prevent it from running at runtime and type-comments can be used +to remove the need for the types to be accessible directly during runtime. + +This module provides the False-y guard in a nicely named fashion so that a +curious maintainer can reach here to read this. + +In pip, all static-typing related imports should be guarded as follows: + + from pip._internal.utils.typing import MYPY_CHECK_RUNNING + + if MYPY_CHECK_RUNNING: + from typing import ... # noqa: F401 + +Ref: https://github.com/python/mypy/issues/3216 +""" + +MYPY_CHECK_RUNNING = False diff --git a/winvenv/Lib/site-packages/pip/_internal/utils/ui.py b/winvenv/Lib/site-packages/pip/_internal/utils/ui.py new file mode 100644 index 0000000..6bab904 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/utils/ui.py @@ -0,0 +1,421 @@ +from __future__ import absolute_import, division + +import contextlib +import itertools +import logging +import sys +import time +from signal import SIGINT, default_int_handler, signal + +from pip._vendor import six +from pip._vendor.progress.bar import ( + Bar, ChargingBar, FillingCirclesBar, FillingSquaresBar, IncrementalBar, + ShadyBar, +) +from pip._vendor.progress.helpers import HIDE_CURSOR, SHOW_CURSOR, WritelnMixin +from pip._vendor.progress.spinner import Spinner + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation +from pip._internal.utils.misc import format_size +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Any # noqa: F401 + +try: + from pip._vendor import colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None + +logger = logging.getLogger(__name__) + + +def _select_progress_class(preferred, fallback): + encoding = getattr(preferred.file, "encoding", None) + + # If we don't know what encoding this file is in, then we'll just assume + # that it doesn't support unicode and use the ASCII bar. + if not encoding: + return fallback + + # Collect all of the possible characters we want to use with the preferred + # bar. + characters = [ + getattr(preferred, "empty_fill", six.text_type()), + getattr(preferred, "fill", six.text_type()), + ] + characters += list(getattr(preferred, "phases", [])) + + # Try to decode the characters we're using for the bar using the encoding + # of the given file, if this works then we'll assume that we can use the + # fancier bar and if not we'll fall back to the plaintext bar. + try: + six.text_type().join(characters).encode(encoding) + except UnicodeEncodeError: + return fallback + else: + return preferred + + +_BaseBar = _select_progress_class(IncrementalBar, Bar) # type: Any + + +class InterruptibleMixin(object): + """ + Helper to ensure that self.finish() gets called on keyboard interrupt. + + This allows downloads to be interrupted without leaving temporary state + (like hidden cursors) behind. + + This class is similar to the progress library's existing SigIntMixin + helper, but as of version 1.2, that helper has the following problems: + + 1. It calls sys.exit(). + 2. It discards the existing SIGINT handler completely. + 3. It leaves its own handler in place even after an uninterrupted finish, + which will have unexpected delayed effects if the user triggers an + unrelated keyboard interrupt some time after a progress-displaying + download has already completed, for example. + """ + + def __init__(self, *args, **kwargs): + """ + Save the original SIGINT handler for later. + """ + super(InterruptibleMixin, self).__init__(*args, **kwargs) + + self.original_handler = signal(SIGINT, self.handle_sigint) + + # If signal() returns None, the previous handler was not installed from + # Python, and we cannot restore it. This probably should not happen, + # but if it does, we must restore something sensible instead, at least. + # The least bad option should be Python's default SIGINT handler, which + # just raises KeyboardInterrupt. + if self.original_handler is None: + self.original_handler = default_int_handler + + def finish(self): + """ + Restore the original SIGINT handler after finishing. + + This should happen regardless of whether the progress display finishes + normally, or gets interrupted. + """ + super(InterruptibleMixin, self).finish() + signal(SIGINT, self.original_handler) + + def handle_sigint(self, signum, frame): + """ + Call self.finish() before delegating to the original SIGINT handler. + + This handler should only be in place while the progress display is + active. + """ + self.finish() + self.original_handler(signum, frame) + + +class SilentBar(Bar): + + def update(self): + pass + + +class BlueEmojiBar(IncrementalBar): + + suffix = "%(percent)d%%" + bar_prefix = " " + bar_suffix = " " + phases = (u"\U0001F539", u"\U0001F537", u"\U0001F535") # type: Any + + +class DownloadProgressMixin(object): + + def __init__(self, *args, **kwargs): + super(DownloadProgressMixin, self).__init__(*args, **kwargs) + self.message = (" " * (get_indentation() + 2)) + self.message + + @property + def downloaded(self): + return format_size(self.index) + + @property + def download_speed(self): + # Avoid zero division errors... + if self.avg == 0.0: + return "..." + return format_size(1 / self.avg) + "/s" + + @property + def pretty_eta(self): + if self.eta: + return "eta %s" % self.eta_td + return "" + + def iter(self, it, n=1): + for x in it: + yield x + self.next(n) + self.finish() + + +class WindowsMixin(object): + + def __init__(self, *args, **kwargs): + # The Windows terminal does not support the hide/show cursor ANSI codes + # even with colorama. So we'll ensure that hide_cursor is False on + # Windows. + # This call neds to go before the super() call, so that hide_cursor + # is set in time. The base progress bar class writes the "hide cursor" + # code to the terminal in its init, so if we don't set this soon + # enough, we get a "hide" with no corresponding "show"... + if WINDOWS and self.hide_cursor: + self.hide_cursor = False + + super(WindowsMixin, self).__init__(*args, **kwargs) + + # Check if we are running on Windows and we have the colorama module, + # if we do then wrap our file with it. + if WINDOWS and colorama: + self.file = colorama.AnsiToWin32(self.file) + # The progress code expects to be able to call self.file.isatty() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.isatty = lambda: self.file.wrapped.isatty() + # The progress code expects to be able to call self.file.flush() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.flush = lambda: self.file.wrapped.flush() + + +class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin): + + file = sys.stdout + message = "%(percent)d%%" + suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s" + +# NOTE: The "type: ignore" comments on the following classes are there to +# work around https://github.com/python/typing/issues/241 + + +class DefaultDownloadProgressBar(BaseDownloadProgressBar, + _BaseBar): # type: ignore + pass + + +class DownloadSilentBar(BaseDownloadProgressBar, SilentBar): # type: ignore + pass + + +class DownloadIncrementalBar(BaseDownloadProgressBar, # type: ignore + IncrementalBar): + pass + + +class DownloadChargingBar(BaseDownloadProgressBar, # type: ignore + ChargingBar): + pass + + +class DownloadShadyBar(BaseDownloadProgressBar, ShadyBar): # type: ignore + pass + + +class DownloadFillingSquaresBar(BaseDownloadProgressBar, # type: ignore + FillingSquaresBar): + pass + + +class DownloadFillingCirclesBar(BaseDownloadProgressBar, # type: ignore + FillingCirclesBar): + pass + + +class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, # type: ignore + BlueEmojiBar): + pass + + +class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin, + DownloadProgressMixin, WritelnMixin, Spinner): + + file = sys.stdout + suffix = "%(downloaded)s %(download_speed)s" + + def next_phase(self): + if not hasattr(self, "_phaser"): + self._phaser = itertools.cycle(self.phases) + return next(self._phaser) + + def update(self): + message = self.message % self + phase = self.next_phase() + suffix = self.suffix % self + line = ''.join([ + message, + " " if message else "", + phase, + " " if suffix else "", + suffix, + ]) + + self.writeln(line) + + +BAR_TYPES = { + "off": (DownloadSilentBar, DownloadSilentBar), + "on": (DefaultDownloadProgressBar, DownloadProgressSpinner), + "ascii": (DownloadIncrementalBar, DownloadProgressSpinner), + "pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner), + "emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner) +} + + +def DownloadProgressProvider(progress_bar, max=None): + if max is None or max == 0: + return BAR_TYPES[progress_bar][1]().iter + else: + return BAR_TYPES[progress_bar][0](max=max).iter + + +################################################################ +# Generic "something is happening" spinners +# +# We don't even try using progress.spinner.Spinner here because it's actually +# simpler to reimplement from scratch than to coerce their code into doing +# what we need. +################################################################ + +@contextlib.contextmanager +def hidden_cursor(file): + # The Windows terminal does not support the hide/show cursor ANSI codes, + # even via colorama. So don't even try. + if WINDOWS: + yield + # We don't want to clutter the output with control characters if we're + # writing to a file, or if the user is running with --quiet. + # See https://github.com/pypa/pip/issues/3418 + elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: + yield + else: + file.write(HIDE_CURSOR) + try: + yield + finally: + file.write(SHOW_CURSOR) + + +class RateLimiter(object): + def __init__(self, min_update_interval_seconds): + self._min_update_interval_seconds = min_update_interval_seconds + self._last_update = 0 + + def ready(self): + now = time.time() + delta = now - self._last_update + return delta >= self._min_update_interval_seconds + + def reset(self): + self._last_update = time.time() + + +class InteractiveSpinner(object): + def __init__(self, message, file=None, spin_chars="-\\|/", + # Empirically, 8 updates/second looks nice + min_update_interval_seconds=0.125): + self._message = message + if file is None: + file = sys.stdout + self._file = file + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._finished = False + + self._spin_cycle = itertools.cycle(spin_chars) + + self._file.write(" " * get_indentation() + self._message + " ... ") + self._width = 0 + + def _write(self, status): + assert not self._finished + # Erase what we wrote before by backspacing to the beginning, writing + # spaces to overwrite the old text, and then backspacing again + backup = "\b" * self._width + self._file.write(backup + " " * self._width + backup) + # Now we have a blank slate to add our status + self._file.write(status) + self._width = len(status) + self._file.flush() + self._rate_limiter.reset() + + def spin(self): + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._write(next(self._spin_cycle)) + + def finish(self, final_status): + if self._finished: + return + self._write(final_status) + self._file.write("\n") + self._file.flush() + self._finished = True + + +# Used for dumb terminals, non-interactive installs (no tty), etc. +# We still print updates occasionally (once every 60 seconds by default) to +# act as a keep-alive for systems like Travis-CI that take lack-of-output as +# an indication that a task has frozen. +class NonInteractiveSpinner(object): + def __init__(self, message, min_update_interval_seconds=60): + self._message = message + self._finished = False + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._update("started") + + def _update(self, status): + assert not self._finished + self._rate_limiter.reset() + logger.info("%s: %s", self._message, status) + + def spin(self): + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._update("still running...") + + def finish(self, final_status): + if self._finished: + return + self._update("finished with status '%s'" % (final_status,)) + self._finished = True + + +@contextlib.contextmanager +def open_spinner(message): + # Interactive spinner goes directly to sys.stdout rather than being routed + # through the logging system, but it acts like it has level INFO, + # i.e. it's only displayed if we're at level INFO or better. + # Non-interactive spinner goes through the logging system, so it is always + # in sync with logging configuration. + if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: + spinner = InteractiveSpinner(message) + else: + spinner = NonInteractiveSpinner(message) + try: + with hidden_cursor(sys.stdout): + yield spinner + except KeyboardInterrupt: + spinner.finish("canceled") + raise + except Exception: + spinner.finish("error") + raise + else: + spinner.finish("done") diff --git a/winvenv/Lib/site-packages/pip/_internal/vcs/__init__.py b/winvenv/Lib/site-packages/pip/_internal/vcs/__init__.py new file mode 100644 index 0000000..794b35d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/vcs/__init__.py @@ -0,0 +1,509 @@ +"""Handles all VCS (version control) support""" +from __future__ import absolute_import + +import errno +import logging +import os +import shutil +import sys + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.exceptions import BadCommand +from pip._internal.utils.misc import ( + display_path, backup_dir, call_subprocess, rmtree, ask_path_exists, +) +from pip._internal.utils.typing import MYPY_CHECK_RUNNING + +if MYPY_CHECK_RUNNING: + from typing import Dict, Optional, Tuple # noqa: F401 + from pip._internal.cli.base_command import Command # noqa: F401 + +__all__ = ['vcs', 'get_src_requirement'] + + +logger = logging.getLogger(__name__) + + +class RevOptions(object): + + """ + Encapsulates a VCS-specific revision to install, along with any VCS + install options. + + Instances of this class should be treated as if immutable. + """ + + def __init__(self, vcs, rev=None, extra_args=None): + """ + Args: + vcs: a VersionControl object. + rev: the name of the revision to install. + extra_args: a list of extra options. + """ + if extra_args is None: + extra_args = [] + + self.extra_args = extra_args + self.rev = rev + self.vcs = vcs + + def __repr__(self): + return '<RevOptions {}: rev={!r}>'.format(self.vcs.name, self.rev) + + @property + def arg_rev(self): + if self.rev is None: + return self.vcs.default_arg_rev + + return self.rev + + def to_args(self): + """ + Return the VCS-specific command arguments. + """ + args = [] + rev = self.arg_rev + if rev is not None: + args += self.vcs.get_base_rev_args(rev) + args += self.extra_args + + return args + + def to_display(self): + if not self.rev: + return '' + + return ' (to revision {})'.format(self.rev) + + def make_new(self, rev): + """ + Make a copy of the current instance, but with a new rev. + + Args: + rev: the name of the revision for the new object. + """ + return self.vcs.make_rev_options(rev, extra_args=self.extra_args) + + +class VcsSupport(object): + _registry = {} # type: Dict[str, Command] + schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp', 'svn'] + + def __init__(self): + # Register more schemes with urlparse for various version control + # systems + urllib_parse.uses_netloc.extend(self.schemes) + # Python >= 2.7.4, 3.3 doesn't have uses_fragment + if getattr(urllib_parse, 'uses_fragment', None): + urllib_parse.uses_fragment.extend(self.schemes) + super(VcsSupport, self).__init__() + + def __iter__(self): + return self._registry.__iter__() + + @property + def backends(self): + return list(self._registry.values()) + + @property + def dirnames(self): + return [backend.dirname for backend in self.backends] + + @property + def all_schemes(self): + schemes = [] + for backend in self.backends: + schemes.extend(backend.schemes) + return schemes + + def register(self, cls): + if not hasattr(cls, 'name'): + logger.warning('Cannot register VCS %s', cls.__name__) + return + if cls.name not in self._registry: + self._registry[cls.name] = cls + logger.debug('Registered VCS backend: %s', cls.name) + + def unregister(self, cls=None, name=None): + if name in self._registry: + del self._registry[name] + elif cls in self._registry.values(): + del self._registry[cls.name] + else: + logger.warning('Cannot unregister because no class or name given') + + def get_backend_name(self, location): + """ + Return the name of the version control backend if found at given + location, e.g. vcs.get_backend_name('/path/to/vcs/checkout') + """ + for vc_type in self._registry.values(): + if vc_type.controls_location(location): + logger.debug('Determine that %s uses VCS: %s', + location, vc_type.name) + return vc_type.name + return None + + def get_backend(self, name): + name = name.lower() + if name in self._registry: + return self._registry[name] + + def get_backend_from_location(self, location): + vc_type = self.get_backend_name(location) + if vc_type: + return self.get_backend(vc_type) + return None + + +vcs = VcsSupport() + + +class VersionControl(object): + name = '' + dirname = '' + # List of supported schemes for this Version Control + schemes = () # type: Tuple[str, ...] + # Iterable of environment variable names to pass to call_subprocess(). + unset_environ = () # type: Tuple[str, ...] + default_arg_rev = None # type: Optional[str] + + def __init__(self, url=None, *args, **kwargs): + self.url = url + super(VersionControl, self).__init__(*args, **kwargs) + + def get_base_rev_args(self, rev): + """ + Return the base revision arguments for a vcs command. + + Args: + rev: the name of a revision to install. Cannot be None. + """ + raise NotImplementedError + + def make_rev_options(self, rev=None, extra_args=None): + """ + Return a RevOptions object. + + Args: + rev: the name of a revision to install. + extra_args: a list of extra options. + """ + return RevOptions(self, rev, extra_args=extra_args) + + def _is_local_repository(self, repo): + """ + posix absolute paths start with os.path.sep, + win32 ones start with drive (like c:\\folder) + """ + drive, tail = os.path.splitdrive(repo) + return repo.startswith(os.path.sep) or drive + + def export(self, location): + """ + Export the repository at the url to the destination location + i.e. only download the files, without vcs informations + """ + raise NotImplementedError + + def get_netloc_and_auth(self, netloc, scheme): + """ + Parse the repository URL's netloc, and return the new netloc to use + along with auth information. + + Args: + netloc: the original repository URL netloc. + scheme: the repository URL's scheme without the vcs prefix. + + This is mainly for the Subversion class to override, so that auth + information can be provided via the --username and --password options + instead of through the URL. For other subclasses like Git without + such an option, auth information must stay in the URL. + + Returns: (netloc, (username, password)). + """ + return netloc, (None, None) + + def get_url_rev_and_auth(self, url): + """ + Parse the repository URL to use, and return the URL, revision, + and auth info to use. + + Returns: (url, rev, (username, password)). + """ + scheme, netloc, path, query, frag = urllib_parse.urlsplit(url) + if '+' not in scheme: + raise ValueError( + "Sorry, {!r} is a malformed VCS url. " + "The format is <vcs>+<protocol>://<url>, " + "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url) + ) + # Remove the vcs prefix. + scheme = scheme.split('+', 1)[1] + netloc, user_pass = self.get_netloc_and_auth(netloc, scheme) + rev = None + if '@' in path: + path, rev = path.rsplit('@', 1) + url = urllib_parse.urlunsplit((scheme, netloc, path, query, '')) + return url, rev, user_pass + + def make_rev_args(self, username, password): + """ + Return the RevOptions "extra arguments" to use in obtain(). + """ + return [] + + def get_url_rev_options(self, url): + """ + Return the URL and RevOptions object to use in obtain() and in + some cases export(), as a tuple (url, rev_options). + """ + url, rev, user_pass = self.get_url_rev_and_auth(url) + username, password = user_pass + extra_args = self.make_rev_args(username, password) + rev_options = self.make_rev_options(rev, extra_args=extra_args) + + return url, rev_options + + def normalize_url(self, url): + """ + Normalize a URL for comparison by unquoting it and removing any + trailing slash. + """ + return urllib_parse.unquote(url).rstrip('/') + + def compare_urls(self, url1, url2): + """ + Compare two repo URLs for identity, ignoring incidental differences. + """ + return (self.normalize_url(url1) == self.normalize_url(url2)) + + def fetch_new(self, dest, url, rev_options): + """ + Fetch a revision from a repository, in the case that this is the + first fetch from the repository. + + Args: + dest: the directory to fetch the repository to. + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def switch(self, dest, url, rev_options): + """ + Switch the repo at ``dest`` to point to ``URL``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def update(self, dest, url, rev_options): + """ + Update an already-existing repo to the given ``rev_options``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def is_commit_id_equal(self, dest, name): + """ + Return whether the id of the current commit equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + raise NotImplementedError + + def obtain(self, dest): + """ + Install or update in editable mode the package represented by this + VersionControl object. + + Args: + dest: the repository directory in which to install or update. + """ + url, rev_options = self.get_url_rev_options(self.url) + + if not os.path.exists(dest): + self.fetch_new(dest, url, rev_options) + return + + rev_display = rev_options.to_display() + if self.is_repository_directory(dest): + existing_url = self.get_url(dest) + if self.compare_urls(existing_url, url): + logger.debug( + '%s in %s exists, and has correct URL (%s)', + self.repo_name.title(), + display_path(dest), + url, + ) + if not self.is_commit_id_equal(dest, rev_options.rev): + logger.info( + 'Updating %s %s%s', + display_path(dest), + self.repo_name, + rev_display, + ) + self.update(dest, url, rev_options) + else: + logger.info('Skipping because already up-to-date.') + return + + logger.warning( + '%s %s in %s exists with URL %s', + self.name, + self.repo_name, + display_path(dest), + existing_url, + ) + prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', + ('s', 'i', 'w', 'b')) + else: + logger.warning( + 'Directory %s already exists, and is not a %s %s.', + dest, + self.name, + self.repo_name, + ) + prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b')) + + logger.warning( + 'The plan is to install the %s repository %s', + self.name, + url, + ) + response = ask_path_exists('What to do? %s' % prompt[0], prompt[1]) + + if response == 'a': + sys.exit(-1) + + if response == 'w': + logger.warning('Deleting %s', display_path(dest)) + rmtree(dest) + self.fetch_new(dest, url, rev_options) + return + + if response == 'b': + dest_dir = backup_dir(dest) + logger.warning( + 'Backing up %s to %s', display_path(dest), dest_dir, + ) + shutil.move(dest, dest_dir) + self.fetch_new(dest, url, rev_options) + return + + # Do nothing if the response is "i". + if response == 's': + logger.info( + 'Switching %s %s to %s%s', + self.repo_name, + display_path(dest), + url, + rev_display, + ) + self.switch(dest, url, rev_options) + + def unpack(self, location): + """ + Clean up current location and download the url repository + (and vcs infos) into location + """ + if os.path.exists(location): + rmtree(location) + self.obtain(location) + + def get_src_requirement(self, dist, location): + """ + Return a string representing the requirement needed to + redownload the files currently present in location, something + like: + {repository_url}@{revision}#egg={project_name}-{version_identifier} + """ + raise NotImplementedError + + def get_url(self, location): + """ + Return the url used at location + """ + raise NotImplementedError + + def get_revision(self, location): + """ + Return the current commit id of the files at the given location. + """ + raise NotImplementedError + + def run_command(self, cmd, show_stdout=True, cwd=None, + on_returncode='raise', + command_desc=None, + extra_environ=None, spinner=None): + """ + Run a VCS subcommand + This is simply a wrapper around call_subprocess that adds the VCS + command name, and checks that the VCS is available + """ + cmd = [self.name] + cmd + try: + return call_subprocess(cmd, show_stdout, cwd, + on_returncode, + command_desc, extra_environ, + unset_environ=self.unset_environ, + spinner=spinner) + except OSError as e: + # errno.ENOENT = no such file or directory + # In other words, the VCS executable isn't available + if e.errno == errno.ENOENT: + raise BadCommand( + 'Cannot find command %r - do you have ' + '%r installed and in your ' + 'PATH?' % (self.name, self.name)) + else: + raise # re-raise exception if a different error occurred + + @classmethod + def is_repository_directory(cls, path): + """ + Return whether a directory path is a repository directory. + """ + logger.debug('Checking in %s for %s (%s)...', + path, cls.dirname, cls.name) + return os.path.exists(os.path.join(path, cls.dirname)) + + @classmethod + def controls_location(cls, location): + """ + Check if a location is controlled by the vcs. + It is meant to be overridden to implement smarter detection + mechanisms for specific vcs. + + This can do more than is_repository_directory() alone. For example, + the Git override checks that Git is actually available. + """ + return cls.is_repository_directory(location) + + +def get_src_requirement(dist, location): + version_control = vcs.get_backend_from_location(location) + if version_control: + try: + return version_control().get_src_requirement(dist, + location) + except BadCommand: + logger.warning( + 'cannot determine version of editable source in %s ' + '(%s command not found in path)', + location, + version_control.name, + ) + return dist.as_requirement() + logger.warning( + 'cannot determine version of editable source in %s (is not SVN ' + 'checkout, Git clone, Mercurial clone or Bazaar branch)', + location, + ) + return dist.as_requirement() diff --git a/winvenv/Lib/site-packages/pip/_internal/vcs/bazaar.py b/winvenv/Lib/site-packages/pip/_internal/vcs/bazaar.py new file mode 100644 index 0000000..3cc66c9 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/vcs/bazaar.py @@ -0,0 +1,112 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._vendor.six.moves.urllib import parse as urllib_parse + +from pip._internal.download import path_to_url +from pip._internal.utils.misc import ( + display_path, make_vcs_requirement_url, rmtree, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.vcs import VersionControl, vcs + +logger = logging.getLogger(__name__) + + +class Bazaar(VersionControl): + name = 'bzr' + dirname = '.bzr' + repo_name = 'branch' + schemes = ( + 'bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp', + 'bzr+lp', + ) + + def __init__(self, url=None, *args, **kwargs): + super(Bazaar, self).__init__(url, *args, **kwargs) + # This is only needed for python <2.7.5 + # Register lp but do not expose as a scheme to support bzr+lp. + if getattr(urllib_parse, 'uses_fragment', None): + urllib_parse.uses_fragment.extend(['lp']) + + def get_base_rev_args(self, rev): + return ['-r', rev] + + def export(self, location): + """ + Export the Bazaar repository at the url to the destination location + """ + # Remove the location to make sure Bazaar can export it correctly + if os.path.exists(location): + rmtree(location) + + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + + self.run_command( + ['export', location], + cwd=temp_dir.path, show_stdout=False, + ) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Checking out %s%s to %s', + url, + rev_display, + display_path(dest), + ) + cmd_args = ['branch', '-q'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) + + def switch(self, dest, url, rev_options): + self.run_command(['switch', url], cwd=dest) + + def update(self, dest, url, rev_options): + cmd_args = ['pull', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def get_url_rev_and_auth(self, url): + # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it + url, rev, user_pass = super(Bazaar, self).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'bzr+' + url + return url, rev, user_pass + + def get_url(self, location): + urls = self.run_command(['info'], show_stdout=False, cwd=location) + for line in urls.splitlines(): + line = line.strip() + for x in ('checkout of branch: ', + 'parent branch: '): + if line.startswith(x): + repo = line.split(x)[1] + if self._is_local_repository(repo): + return path_to_url(repo) + return repo + return None + + def get_revision(self, location): + revision = self.run_command( + ['revno'], show_stdout=False, cwd=location, + ) + return revision.splitlines()[-1] + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if not repo: + return None + if not repo.lower().startswith('bzr:'): + repo = 'bzr+' + repo + current_rev = self.get_revision(location) + egg_project_name = dist.egg_name().split('-', 1)[0] + return make_vcs_requirement_url(repo, current_rev, egg_project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Bazaar) diff --git a/winvenv/Lib/site-packages/pip/_internal/vcs/git.py b/winvenv/Lib/site-packages/pip/_internal/vcs/git.py new file mode 100644 index 0000000..9778539 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/vcs/git.py @@ -0,0 +1,346 @@ +from __future__ import absolute_import + +import logging +import os.path +import re + +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.six.moves.urllib import parse as urllib_parse +from pip._vendor.six.moves.urllib import request as urllib_request + +from pip._internal.exceptions import BadCommand +from pip._internal.utils.compat import samefile +from pip._internal.utils.misc import display_path, make_vcs_requirement_url +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.vcs import VersionControl, vcs + +urlsplit = urllib_parse.urlsplit +urlunsplit = urllib_parse.urlunsplit + + +logger = logging.getLogger(__name__) + + +HASH_REGEX = re.compile('[a-fA-F0-9]{40}') + + +def looks_like_hash(sha): + return bool(HASH_REGEX.match(sha)) + + +class Git(VersionControl): + name = 'git' + dirname = '.git' + repo_name = 'clone' + schemes = ( + 'git', 'git+http', 'git+https', 'git+ssh', 'git+git', 'git+file', + ) + # Prevent the user's environment variables from interfering with pip: + # https://github.com/pypa/pip/issues/1130 + unset_environ = ('GIT_DIR', 'GIT_WORK_TREE') + default_arg_rev = 'HEAD' + + def __init__(self, url=None, *args, **kwargs): + + # Works around an apparent Git bug + # (see https://article.gmane.org/gmane.comp.version-control.git/146500) + if url: + scheme, netloc, path, query, fragment = urlsplit(url) + if scheme.endswith('file'): + initial_slashes = path[:-len(path.lstrip('/'))] + newpath = ( + initial_slashes + + urllib_request.url2pathname(path) + .replace('\\', '/').lstrip('/') + ) + url = urlunsplit((scheme, netloc, newpath, query, fragment)) + after_plus = scheme.find('+') + 1 + url = scheme[:after_plus] + urlunsplit( + (scheme[after_plus:], netloc, newpath, query, fragment), + ) + + super(Git, self).__init__(url, *args, **kwargs) + + def get_base_rev_args(self, rev): + return [rev] + + def get_git_version(self): + VERSION_PFX = 'git version ' + version = self.run_command(['version'], show_stdout=False) + if version.startswith(VERSION_PFX): + version = version[len(VERSION_PFX):].split()[0] + else: + version = '' + # get first 3 positions of the git version becasue + # on windows it is x.y.z.windows.t, and this parses as + # LegacyVersion which always smaller than a Version. + version = '.'.join(version.split('.')[:3]) + return parse_version(version) + + def get_branch(self, location): + """ + Return the current branch, or None if HEAD isn't at a branch + (e.g. detached HEAD). + """ + args = ['rev-parse', '--abbrev-ref', 'HEAD'] + output = self.run_command(args, show_stdout=False, cwd=location) + branch = output.strip() + + if branch == 'HEAD': + return None + + return branch + + def export(self, location): + """Export the Git repository at the url to the destination location""" + if not location.endswith('/'): + location = location + '/' + + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + self.run_command( + ['checkout-index', '-a', '-f', '--prefix', location], + show_stdout=False, cwd=temp_dir.path + ) + + def get_revision_sha(self, dest, rev): + """ + Return (sha_or_none, is_branch), where sha_or_none is a commit hash + if the revision names a remote branch or tag, otherwise None. + + Args: + dest: the repository directory. + rev: the revision name. + """ + # Pass rev to pre-filter the list. + output = self.run_command(['show-ref', rev], cwd=dest, + show_stdout=False, on_returncode='ignore') + refs = {} + for line in output.strip().splitlines(): + try: + sha, ref = line.split() + except ValueError: + # Include the offending line to simplify troubleshooting if + # this error ever occurs. + raise ValueError('unexpected show-ref line: {!r}'.format(line)) + + refs[ref] = sha + + branch_ref = 'refs/remotes/origin/{}'.format(rev) + tag_ref = 'refs/tags/{}'.format(rev) + + sha = refs.get(branch_ref) + if sha is not None: + return (sha, True) + + sha = refs.get(tag_ref) + + return (sha, False) + + def resolve_revision(self, dest, url, rev_options): + """ + Resolve a revision to a new RevOptions object with the SHA1 of the + branch, tag, or ref if found. + + Args: + rev_options: a RevOptions object. + """ + rev = rev_options.arg_rev + sha, is_branch = self.get_revision_sha(dest, rev) + + if sha is not None: + rev_options = rev_options.make_new(sha) + rev_options.branch_name = rev if is_branch else None + + return rev_options + + # Do not show a warning for the common case of something that has + # the form of a Git commit hash. + if not looks_like_hash(rev): + logger.warning( + "Did not find branch or tag '%s', assuming revision or ref.", + rev, + ) + + if not rev.startswith('refs/'): + return rev_options + + # If it looks like a ref, we have to fetch it explicitly. + self.run_command( + ['fetch', '-q', url] + rev_options.to_args(), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + sha = self.get_revision(dest, rev='FETCH_HEAD') + rev_options = rev_options.make_new(sha) + + return rev_options + + def is_commit_id_equal(self, dest, name): + """ + Return whether the current commit hash equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + if not name: + # Then avoid an unnecessary subprocess call. + return False + + return self.get_revision(dest) == name + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Cloning %s%s to %s', url, rev_display, display_path(dest), + ) + self.run_command(['clone', '-q', url, dest]) + + if rev_options.rev: + # Then a specific revision was requested. + rev_options = self.resolve_revision(dest, url, rev_options) + branch_name = getattr(rev_options, 'branch_name', None) + if branch_name is None: + # Only do a checkout if the current commit id doesn't match + # the requested revision. + if not self.is_commit_id_equal(dest, rev_options.rev): + cmd_args = ['checkout', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + elif self.get_branch(dest) != branch_name: + # Then a specific branch was requested, and that branch + # is not yet checked out. + track_branch = 'origin/{}'.format(branch_name) + cmd_args = [ + 'checkout', '-b', branch_name, '--track', track_branch, + ] + self.run_command(cmd_args, cwd=dest) + + #: repo may contain submodules + self.update_submodules(dest) + + def switch(self, dest, url, rev_options): + self.run_command(['config', 'remote.origin.url', url], cwd=dest) + cmd_args = ['checkout', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + self.update_submodules(dest) + + def update(self, dest, url, rev_options): + # First fetch changes from the default remote + if self.get_git_version() >= parse_version('1.9.0'): + # fetch tags in addition to everything else + self.run_command(['fetch', '-q', '--tags'], cwd=dest) + else: + self.run_command(['fetch', '-q'], cwd=dest) + # Then reset to wanted revision (maybe even origin/master) + rev_options = self.resolve_revision(dest, url, rev_options) + cmd_args = ['reset', '--hard', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + #: update submodules + self.update_submodules(dest) + + def get_url(self, location): + """Return URL of the first remote encountered.""" + remotes = self.run_command( + ['config', '--get-regexp', r'remote\..*\.url'], + show_stdout=False, cwd=location, + ) + remotes = remotes.splitlines() + found_remote = remotes[0] + for remote in remotes: + if remote.startswith('remote.origin.url '): + found_remote = remote + break + url = found_remote.split(' ')[1] + return url.strip() + + def get_revision(self, location, rev=None): + if rev is None: + rev = 'HEAD' + current_rev = self.run_command( + ['rev-parse', rev], show_stdout=False, cwd=location, + ) + return current_rev.strip() + + def _get_subdirectory(self, location): + """Return the relative path of setup.py to the git repo root.""" + # find the repo root + git_dir = self.run_command(['rev-parse', '--git-dir'], + show_stdout=False, cwd=location).strip() + if not os.path.isabs(git_dir): + git_dir = os.path.join(location, git_dir) + root_dir = os.path.join(git_dir, '..') + # find setup.py + orig_location = location + while not os.path.exists(os.path.join(location, 'setup.py')): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding setup.py + logger.warning( + "Could not find setup.py for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + # relative path of setup.py to repo root + if samefile(root_dir, location): + return None + return os.path.relpath(location, root_dir) + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if not repo.lower().startswith('git:'): + repo = 'git+' + repo + current_rev = self.get_revision(location) + egg_project_name = dist.egg_name().split('-', 1)[0] + subdir = self._get_subdirectory(location) + req = make_vcs_requirement_url(repo, current_rev, egg_project_name, + subdir=subdir) + + return req + + def get_url_rev_and_auth(self, url): + """ + Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. + That's required because although they use SSH they sometimes don't + work with a ssh:// scheme (e.g. GitHub). But we need a scheme for + parsing. Hence we remove it again afterwards and return it as a stub. + """ + if '://' not in url: + assert 'file:' not in url + url = url.replace('git+', 'git+ssh://') + url, rev, user_pass = super(Git, self).get_url_rev_and_auth(url) + url = url.replace('ssh://', '') + else: + url, rev, user_pass = super(Git, self).get_url_rev_and_auth(url) + + return url, rev, user_pass + + def update_submodules(self, location): + if not os.path.exists(os.path.join(location, '.gitmodules')): + return + self.run_command( + ['submodule', 'update', '--init', '--recursive', '-q'], + cwd=location, + ) + + @classmethod + def controls_location(cls, location): + if super(Git, cls).controls_location(location): + return True + try: + r = cls().run_command(['rev-parse'], + cwd=location, + show_stdout=False, + on_returncode='ignore') + return not r + except BadCommand: + logger.debug("could not determine if %s is under git control " + "because git is not available", location) + return False + + +vcs.register(Git) diff --git a/winvenv/Lib/site-packages/pip/_internal/vcs/mercurial.py b/winvenv/Lib/site-packages/pip/_internal/vcs/mercurial.py new file mode 100644 index 0000000..17cfb67 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/vcs/mercurial.py @@ -0,0 +1,101 @@ +from __future__ import absolute_import + +import logging +import os + +from pip._vendor.six.moves import configparser + +from pip._internal.download import path_to_url +from pip._internal.utils.misc import display_path, make_vcs_requirement_url +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.vcs import VersionControl, vcs + +logger = logging.getLogger(__name__) + + +class Mercurial(VersionControl): + name = 'hg' + dirname = '.hg' + repo_name = 'clone' + schemes = ('hg', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http') + + def get_base_rev_args(self, rev): + return [rev] + + def export(self, location): + """Export the Hg repository at the url to the destination location""" + with TempDirectory(kind="export") as temp_dir: + self.unpack(temp_dir.path) + + self.run_command( + ['archive', location], show_stdout=False, cwd=temp_dir.path + ) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Cloning hg %s%s to %s', + url, + rev_display, + display_path(dest), + ) + self.run_command(['clone', '--noupdate', '-q', url, dest]) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def switch(self, dest, url, rev_options): + repo_config = os.path.join(dest, self.dirname, 'hgrc') + config = configparser.SafeConfigParser() + try: + config.read(repo_config) + config.set('paths', 'default', url) + with open(repo_config, 'w') as config_file: + config.write(config_file) + except (OSError, configparser.NoSectionError) as exc: + logger.warning( + 'Could not switch Mercurial repository to %s: %s', url, exc, + ) + else: + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def update(self, dest, url, rev_options): + self.run_command(['pull', '-q'], cwd=dest) + cmd_args = ['update', '-q'] + rev_options.to_args() + self.run_command(cmd_args, cwd=dest) + + def get_url(self, location): + url = self.run_command( + ['showconfig', 'paths.default'], + show_stdout=False, cwd=location).strip() + if self._is_local_repository(url): + url = path_to_url(url) + return url.strip() + + def get_revision(self, location): + current_revision = self.run_command( + ['parents', '--template={rev}'], + show_stdout=False, cwd=location).strip() + return current_revision + + def get_revision_hash(self, location): + current_rev_hash = self.run_command( + ['parents', '--template={node}'], + show_stdout=False, cwd=location).strip() + return current_rev_hash + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if not repo.lower().startswith('hg:'): + repo = 'hg+' + repo + current_rev_hash = self.get_revision_hash(location) + egg_project_name = dist.egg_name().split('-', 1)[0] + return make_vcs_requirement_url(repo, current_rev_hash, + egg_project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Mercurial) diff --git a/winvenv/Lib/site-packages/pip/_internal/vcs/subversion.py b/winvenv/Lib/site-packages/pip/_internal/vcs/subversion.py new file mode 100644 index 0000000..6f7cb5d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/vcs/subversion.py @@ -0,0 +1,213 @@ +from __future__ import absolute_import + +import logging +import os +import re + +from pip._internal.models.link import Link +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + display_path, make_vcs_requirement_url, rmtree, split_auth_from_netloc, +) +from pip._internal.vcs import VersionControl, vcs + +_svn_xml_url_re = re.compile('url="([^"]+)"') +_svn_rev_re = re.compile(r'committed-rev="(\d+)"') +_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') +_svn_info_xml_url_re = re.compile(r'<url>(.*)</url>') + + +logger = logging.getLogger(__name__) + + +class Subversion(VersionControl): + name = 'svn' + dirname = '.svn' + repo_name = 'checkout' + schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https', 'svn+svn') + + def get_base_rev_args(self, rev): + return ['-r', rev] + + def export(self, location): + """Export the svn repository at the url to the destination location""" + url, rev_options = self.get_url_rev_options(self.url) + + logger.info('Exporting svn repository %s to %s', url, location) + with indent_log(): + if os.path.exists(location): + # Subversion doesn't like to check out over an existing + # directory --force fixes this, but was only added in svn 1.5 + rmtree(location) + cmd_args = ['export'] + rev_options.to_args() + [url, location] + self.run_command(cmd_args, show_stdout=False) + + def fetch_new(self, dest, url, rev_options): + rev_display = rev_options.to_display() + logger.info( + 'Checking out %s%s to %s', + url, + rev_display, + display_path(dest), + ) + cmd_args = ['checkout', '-q'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) + + def switch(self, dest, url, rev_options): + cmd_args = ['switch'] + rev_options.to_args() + [url, dest] + self.run_command(cmd_args) + + def update(self, dest, url, rev_options): + cmd_args = ['update'] + rev_options.to_args() + [dest] + self.run_command(cmd_args) + + def get_location(self, dist, dependency_links): + for url in dependency_links: + egg_fragment = Link(url).egg_fragment + if not egg_fragment: + continue + if '-' in egg_fragment: + # FIXME: will this work when a package has - in the name? + key = '-'.join(egg_fragment.split('-')[:-1]).lower() + else: + key = egg_fragment + if key == dist.key: + return url.split('#', 1)[0] + return None + + def get_revision(self, location): + """ + Return the maximum revision for all files under a given location + """ + # Note: taken from setuptools.command.egg_info + revision = 0 + + for base, dirs, files in os.walk(location): + if self.dirname not in dirs: + dirs[:] = [] + continue # no sense walking uncontrolled subdirs + dirs.remove(self.dirname) + entries_fn = os.path.join(base, self.dirname, 'entries') + if not os.path.exists(entries_fn): + # FIXME: should we warn? + continue + + dirurl, localrev = self._get_svn_url_rev(base) + + if base == location: + base = dirurl + '/' # save the root url + elif not dirurl or not dirurl.startswith(base): + dirs[:] = [] + continue # not part of the same svn tree, skip it + revision = max(revision, localrev) + return revision + + def get_netloc_and_auth(self, netloc, scheme): + """ + This override allows the auth information to be passed to svn via the + --username and --password options instead of via the URL. + """ + if scheme == 'ssh': + # The --username and --password options can't be used for + # svn+ssh URLs, so keep the auth information in the URL. + return super(Subversion, self).get_netloc_and_auth( + netloc, scheme) + + return split_auth_from_netloc(netloc) + + def get_url_rev_and_auth(self, url): + # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it + url, rev, user_pass = super(Subversion, self).get_url_rev_and_auth(url) + if url.startswith('ssh://'): + url = 'svn+' + url + return url, rev, user_pass + + def make_rev_args(self, username, password): + extra_args = [] + if username: + extra_args += ['--username', username] + if password: + extra_args += ['--password', password] + + return extra_args + + def get_url(self, location): + # In cases where the source is in a subdirectory, not alongside + # setup.py we have to look up in the location until we find a real + # setup.py + orig_location = location + while not os.path.exists(os.path.join(location, 'setup.py')): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding setup.py + logger.warning( + "Could not find setup.py for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + + return self._get_svn_url_rev(location)[0] + + def _get_svn_url_rev(self, location): + from pip._internal.exceptions import InstallationError + + entries_path = os.path.join(location, self.dirname, 'entries') + if os.path.exists(entries_path): + with open(entries_path) as f: + data = f.read() + else: # subversion >= 1.7 does not have the 'entries' file + data = '' + + if (data.startswith('8') or + data.startswith('9') or + data.startswith('10')): + data = list(map(str.splitlines, data.split('\n\x0c\n'))) + del data[0][0] # get rid of the '8' + url = data[0][3] + revs = [int(d[9]) for d in data if len(d) > 9 and d[9]] + [0] + elif data.startswith('<?xml'): + match = _svn_xml_url_re.search(data) + if not match: + raise ValueError('Badly formatted data: %r' % data) + url = match.group(1) # get repository URL + revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)] + [0] + else: + try: + # subversion >= 1.7 + xml = self.run_command( + ['info', '--xml', location], + show_stdout=False, + ) + url = _svn_info_xml_url_re.search(xml).group(1) + revs = [ + int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml) + ] + except InstallationError: + url, revs = None, [] + + if revs: + rev = max(revs) + else: + rev = 0 + + return url, rev + + def get_src_requirement(self, dist, location): + repo = self.get_url(location) + if repo is None: + return None + repo = 'svn+' + repo + rev = self.get_revision(location) + # FIXME: why not project name? + egg_project_name = dist.egg_name().split('-', 1)[0] + return make_vcs_requirement_url(repo, rev, egg_project_name) + + def is_commit_id_equal(self, dest, name): + """Always assume the versions don't match""" + return False + + +vcs.register(Subversion) diff --git a/winvenv/Lib/site-packages/pip/_internal/wheel.py b/winvenv/Lib/site-packages/pip/_internal/wheel.py new file mode 100644 index 0000000..5ce890e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_internal/wheel.py @@ -0,0 +1,831 @@ +""" +Support for installing and building the "wheel" binary package format. +""" +from __future__ import absolute_import + +import collections +import compileall +import csv +import hashlib +import logging +import os.path +import re +import shutil +import stat +import sys +import warnings +from base64 import urlsafe_b64encode +from email.parser import Parser + +from pip._vendor import pkg_resources +from pip._vendor.distlib.scripts import ScriptMaker +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.six import StringIO + +from pip._internal import pep425tags +from pip._internal.download import path_to_url, unpack_url +from pip._internal.exceptions import ( + InstallationError, InvalidWheelFilename, UnsupportedWheel, +) +from pip._internal.locations import ( + PIP_DELETE_MARKER_FILENAME, distutils_scheme, +) +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ( + call_subprocess, captured_stdout, ensure_dir, read_chunks, +) +from pip._internal.utils.setuptools_build import SETUPTOOLS_SHIM +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.typing import MYPY_CHECK_RUNNING +from pip._internal.utils.ui import open_spinner + +if MYPY_CHECK_RUNNING: + from typing import Dict, List, Optional # noqa: F401 + +wheel_ext = '.whl' + +VERSION_COMPATIBLE = (1, 0) + + +logger = logging.getLogger(__name__) + + +def rehash(path, blocksize=1 << 20): + """Return (hash, length) for path using hashlib.sha256()""" + h = hashlib.sha256() + length = 0 + with open(path, 'rb') as f: + for block in read_chunks(f, size=blocksize): + length += len(block) + h.update(block) + digest = 'sha256=' + urlsafe_b64encode( + h.digest() + ).decode('latin1').rstrip('=') + return (digest, length) + + +def open_for_csv(name, mode): + if sys.version_info[0] < 3: + nl = {} + bin = 'b' + else: + nl = {'newline': ''} + bin = '' + return open(name, mode + bin, **nl) + + +def fix_script(path): + """Replace #!python with #!/path/to/python + Return True if file was changed.""" + # XXX RECORD hashes will need to be updated + if os.path.isfile(path): + with open(path, 'rb') as script: + firstline = script.readline() + if not firstline.startswith(b'#!python'): + return False + exename = sys.executable.encode(sys.getfilesystemencoding()) + firstline = b'#!' + exename + os.linesep.encode("ascii") + rest = script.read() + with open(path, 'wb') as script: + script.write(firstline) + script.write(rest) + return True + + +dist_info_re = re.compile(r"""^(?P<namever>(?P<name>.+?)(-(?P<ver>.+?))?) + \.dist-info$""", re.VERBOSE) + + +def root_is_purelib(name, wheeldir): + """ + Return True if the extracted wheel in wheeldir should go into purelib. + """ + name_folded = name.replace("-", "_") + for item in os.listdir(wheeldir): + match = dist_info_re.match(item) + if match and match.group('name') == name_folded: + with open(os.path.join(wheeldir, item, 'WHEEL')) as wheel: + for line in wheel: + line = line.lower().rstrip() + if line == "root-is-purelib: true": + return True + return False + + +def get_entrypoints(filename): + if not os.path.exists(filename): + return {}, {} + + # This is done because you can pass a string to entry_points wrappers which + # means that they may or may not be valid INI files. The attempt here is to + # strip leading and trailing whitespace in order to make them valid INI + # files. + with open(filename) as fp: + data = StringIO() + for line in fp: + data.write(line.strip()) + data.write("\n") + data.seek(0) + + # get the entry points and then the script names + entry_points = pkg_resources.EntryPoint.parse_map(data) + console = entry_points.get('console_scripts', {}) + gui = entry_points.get('gui_scripts', {}) + + def _split_ep(s): + """get the string representation of EntryPoint, remove space and split + on '='""" + return str(s).replace(" ", "").split("=") + + # convert the EntryPoint objects into strings with module:function + console = dict(_split_ep(v) for v in console.values()) + gui = dict(_split_ep(v) for v in gui.values()) + return console, gui + + +def message_about_scripts_not_on_PATH(scripts): + # type: (List[str]) -> Optional[str] + """Determine if any scripts are not on PATH and format a warning. + + Returns a warning message if one or more scripts are not on PATH, + otherwise None. + """ + if not scripts: + return None + + # Group scripts by the path they were installed in + grouped_by_dir = collections.defaultdict(set) # type: Dict[str, set] + for destfile in scripts: + parent_dir = os.path.dirname(destfile) + script_name = os.path.basename(destfile) + grouped_by_dir[parent_dir].add(script_name) + + # We don't want to warn for directories that are on PATH. + not_warn_dirs = [ + os.path.normcase(i).rstrip(os.sep) for i in + os.environ.get("PATH", "").split(os.pathsep) + ] + # If an executable sits with sys.executable, we don't warn for it. + # This covers the case of venv invocations without activating the venv. + not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) + warn_for = { + parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() + if os.path.normcase(parent_dir) not in not_warn_dirs + } + if not warn_for: + return None + + # Format a message + msg_lines = [] + for parent_dir, scripts in warn_for.items(): + scripts = sorted(scripts) + if len(scripts) == 1: + start_text = "script {} is".format(scripts[0]) + else: + start_text = "scripts {} are".format( + ", ".join(scripts[:-1]) + " and " + scripts[-1] + ) + + msg_lines.append( + "The {} installed in '{}' which is not on PATH." + .format(start_text, parent_dir) + ) + + last_line_fmt = ( + "Consider adding {} to PATH or, if you prefer " + "to suppress this warning, use --no-warn-script-location." + ) + if len(msg_lines) == 1: + msg_lines.append(last_line_fmt.format("this directory")) + else: + msg_lines.append(last_line_fmt.format("these directories")) + + # Returns the formatted multiline message + return "\n".join(msg_lines) + + +def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, + pycompile=True, scheme=None, isolated=False, prefix=None, + warn_script_location=True): + """Install a wheel""" + + if not scheme: + scheme = distutils_scheme( + name, user=user, home=home, root=root, isolated=isolated, + prefix=prefix, + ) + + if root_is_purelib(name, wheeldir): + lib_dir = scheme['purelib'] + else: + lib_dir = scheme['platlib'] + + info_dir = [] + data_dirs = [] + source = wheeldir.rstrip(os.path.sep) + os.path.sep + + # Record details of the files moved + # installed = files copied from the wheel to the destination + # changed = files changed while installing (scripts #! line typically) + # generated = files newly generated during the install (script wrappers) + installed = {} + changed = set() + generated = [] + + # Compile all of the pyc files that we're going to be installing + if pycompile: + with captured_stdout() as stdout: + with warnings.catch_warnings(): + warnings.filterwarnings('ignore') + compileall.compile_dir(source, force=True, quiet=True) + logger.debug(stdout.getvalue()) + + def normpath(src, p): + return os.path.relpath(src, p).replace(os.path.sep, '/') + + def record_installed(srcfile, destfile, modified=False): + """Map archive RECORD paths to installation RECORD paths.""" + oldpath = normpath(srcfile, wheeldir) + newpath = normpath(destfile, lib_dir) + installed[oldpath] = newpath + if modified: + changed.add(destfile) + + def clobber(source, dest, is_base, fixer=None, filter=None): + ensure_dir(dest) # common for the 'include' path + + for dir, subdirs, files in os.walk(source): + basedir = dir[len(source):].lstrip(os.path.sep) + destdir = os.path.join(dest, basedir) + if is_base and basedir.split(os.path.sep, 1)[0].endswith('.data'): + continue + for s in subdirs: + destsubdir = os.path.join(dest, basedir, s) + if is_base and basedir == '' and destsubdir.endswith('.data'): + data_dirs.append(s) + continue + elif (is_base and + s.endswith('.dist-info') and + canonicalize_name(s).startswith( + canonicalize_name(req.name))): + assert not info_dir, ('Multiple .dist-info directories: ' + + destsubdir + ', ' + + ', '.join(info_dir)) + info_dir.append(destsubdir) + for f in files: + # Skip unwanted files + if filter and filter(f): + continue + srcfile = os.path.join(dir, f) + destfile = os.path.join(dest, basedir, f) + # directory creation is lazy and after the file filtering above + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + ensure_dir(destdir) + + # copyfile (called below) truncates the destination if it + # exists and then writes the new contents. This is fine in most + # cases, but can cause a segfault if pip has loaded a shared + # object (e.g. from pyopenssl through its vendored urllib3) + # Since the shared object is mmap'd an attempt to call a + # symbol in it will then cause a segfault. Unlinking the file + # allows writing of new contents while allowing the process to + # continue to use the old copy. + if os.path.exists(destfile): + os.unlink(destfile) + + # We use copyfile (not move, copy, or copy2) to be extra sure + # that we are not moving directories over (copyfile fails for + # directories) as well as to ensure that we are not copying + # over any metadata because we want more control over what + # metadata we actually copy over. + shutil.copyfile(srcfile, destfile) + + # Copy over the metadata for the file, currently this only + # includes the atime and mtime. + st = os.stat(srcfile) + if hasattr(os, "utime"): + os.utime(destfile, (st.st_atime, st.st_mtime)) + + # If our file is executable, then make our destination file + # executable. + if os.access(srcfile, os.X_OK): + st = os.stat(srcfile) + permissions = ( + st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH + ) + os.chmod(destfile, permissions) + + changed = False + if fixer: + changed = fixer(destfile) + record_installed(srcfile, destfile, changed) + + clobber(source, lib_dir, True) + + assert info_dir, "%s .dist-info directory not found" % req + + # Get the defined entry points + ep_file = os.path.join(info_dir[0], 'entry_points.txt') + console, gui = get_entrypoints(ep_file) + + def is_entrypoint_wrapper(name): + # EP, EP.exe and EP-script.py are scripts generated for + # entry point EP by setuptools + if name.lower().endswith('.exe'): + matchname = name[:-4] + elif name.lower().endswith('-script.py'): + matchname = name[:-10] + elif name.lower().endswith(".pya"): + matchname = name[:-4] + else: + matchname = name + # Ignore setuptools-generated scripts + return (matchname in console or matchname in gui) + + for datadir in data_dirs: + fixer = None + filter = None + for subdir in os.listdir(os.path.join(wheeldir, datadir)): + fixer = None + if subdir == 'scripts': + fixer = fix_script + filter = is_entrypoint_wrapper + source = os.path.join(wheeldir, datadir, subdir) + dest = scheme[subdir] + clobber(source, dest, False, fixer=fixer, filter=filter) + + maker = ScriptMaker(None, scheme['scripts']) + + # Ensure old scripts are overwritten. + # See https://github.com/pypa/pip/issues/1800 + maker.clobber = True + + # Ensure we don't generate any variants for scripts because this is almost + # never what somebody wants. + # See https://bitbucket.org/pypa/distlib/issue/35/ + maker.variants = {''} + + # This is required because otherwise distlib creates scripts that are not + # executable. + # See https://bitbucket.org/pypa/distlib/issue/32/ + maker.set_mode = True + + # Simplify the script and fix the fact that the default script swallows + # every single stack trace. + # See https://bitbucket.org/pypa/distlib/issue/34/ + # See https://bitbucket.org/pypa/distlib/issue/33/ + def _get_script_text(entry): + if entry.suffix is None: + raise InstallationError( + "Invalid script entry point: %s for req: %s - A callable " + "suffix is required. Cf https://packaging.python.org/en/" + "latest/distributing.html#console-scripts for more " + "information." % (entry, req) + ) + return maker.script_template % { + "module": entry.prefix, + "import_name": entry.suffix.split(".")[0], + "func": entry.suffix, + } + + maker._get_script_text = _get_script_text + maker.script_template = r"""# -*- coding: utf-8 -*- +import re +import sys + +from %(module)s import %(import_name)s + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(%(func)s()) +""" + + # Special case pip and setuptools to generate versioned wrappers + # + # The issue is that some projects (specifically, pip and setuptools) use + # code in setup.py to create "versioned" entry points - pip2.7 on Python + # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into + # the wheel metadata at build time, and so if the wheel is installed with + # a *different* version of Python the entry points will be wrong. The + # correct fix for this is to enhance the metadata to be able to describe + # such versioned entry points, but that won't happen till Metadata 2.0 is + # available. + # In the meantime, projects using versioned entry points will either have + # incorrect versioned entry points, or they will not be able to distribute + # "universal" wheels (i.e., they will need a wheel per Python version). + # + # Because setuptools and pip are bundled with _ensurepip and virtualenv, + # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we + # override the versioned entry points in the wheel and generate the + # correct ones. This code is purely a short-term measure until Metadata 2.0 + # is available. + # + # To add the level of hack in this section of code, in order to support + # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment + # variable which will control which version scripts get installed. + # + # ENSUREPIP_OPTIONS=altinstall + # - Only pipX.Y and easy_install-X.Y will be generated and installed + # ENSUREPIP_OPTIONS=install + # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note + # that this option is technically if ENSUREPIP_OPTIONS is set and is + # not altinstall + # DEFAULT + # - The default behavior is to install pip, pipX, pipX.Y, easy_install + # and easy_install-X.Y. + pip_script = console.pop('pip', None) + if pip_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + spec = 'pip = ' + pip_script + generated.extend(maker.make(spec)) + + if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": + spec = 'pip%s = %s' % (sys.version[:1], pip_script) + generated.extend(maker.make(spec)) + + spec = 'pip%s = %s' % (sys.version[:3], pip_script) + generated.extend(maker.make(spec)) + # Delete any other versioned pip entry points + pip_ep = [k for k in console if re.match(r'pip(\d(\.\d)?)?$', k)] + for k in pip_ep: + del console[k] + easy_install_script = console.pop('easy_install', None) + if easy_install_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + spec = 'easy_install = ' + easy_install_script + generated.extend(maker.make(spec)) + + spec = 'easy_install-%s = %s' % (sys.version[:3], easy_install_script) + generated.extend(maker.make(spec)) + # Delete any other versioned easy_install entry points + easy_install_ep = [ + k for k in console if re.match(r'easy_install(-\d\.\d)?$', k) + ] + for k in easy_install_ep: + del console[k] + + # Generate the console and GUI entry points specified in the wheel + if len(console) > 0: + generated_console_scripts = maker.make_multiple( + ['%s = %s' % kv for kv in console.items()] + ) + generated.extend(generated_console_scripts) + + if warn_script_location: + msg = message_about_scripts_not_on_PATH(generated_console_scripts) + if msg is not None: + logger.warning(msg) + + if len(gui) > 0: + generated.extend( + maker.make_multiple( + ['%s = %s' % kv for kv in gui.items()], + {'gui': True} + ) + ) + + # Record pip as the installer + installer = os.path.join(info_dir[0], 'INSTALLER') + temp_installer = os.path.join(info_dir[0], 'INSTALLER.pip') + with open(temp_installer, 'wb') as installer_file: + installer_file.write(b'pip\n') + shutil.move(temp_installer, installer) + generated.append(installer) + + # Record details of all files installed + record = os.path.join(info_dir[0], 'RECORD') + temp_record = os.path.join(info_dir[0], 'RECORD.pip') + with open_for_csv(record, 'r') as record_in: + with open_for_csv(temp_record, 'w+') as record_out: + reader = csv.reader(record_in) + writer = csv.writer(record_out) + outrows = [] + for row in reader: + row[0] = installed.pop(row[0], row[0]) + if row[0] in changed: + row[1], row[2] = rehash(row[0]) + outrows.append(tuple(row)) + for f in generated: + digest, length = rehash(f) + outrows.append((normpath(f, lib_dir), digest, length)) + for f in installed: + outrows.append((installed[f], '', '')) + for row in sorted(outrows): + writer.writerow(row) + shutil.move(temp_record, record) + + +def wheel_version(source_dir): + """ + Return the Wheel-Version of an extracted wheel, if possible. + + Otherwise, return False if we couldn't parse / extract it. + """ + try: + dist = [d for d in pkg_resources.find_on_path(None, source_dir)][0] + + wheel_data = dist.get_metadata('WHEEL') + wheel_data = Parser().parsestr(wheel_data) + + version = wheel_data['Wheel-Version'].strip() + version = tuple(map(int, version.split('.'))) + return version + except Exception: + return False + + +def check_compatibility(version, name): + """ + Raises errors or warns if called with an incompatible Wheel-Version. + + Pip should refuse to install a Wheel-Version that's a major series + ahead of what it's compatible with (e.g 2.0 > 1.1); and warn when + installing a version only minor version ahead (e.g 1.2 > 1.1). + + version: a 2-tuple representing a Wheel-Version (Major, Minor) + name: name of wheel or package to raise exception about + + :raises UnsupportedWheel: when an incompatible Wheel-Version is given + """ + if not version: + raise UnsupportedWheel( + "%s is in an unsupported or invalid wheel" % name + ) + if version[0] > VERSION_COMPATIBLE[0]: + raise UnsupportedWheel( + "%s's Wheel-Version (%s) is not compatible with this version " + "of pip" % (name, '.'.join(map(str, version))) + ) + elif version > VERSION_COMPATIBLE: + logger.warning( + 'Installing from a newer Wheel-Version (%s)', + '.'.join(map(str, version)), + ) + + +class Wheel(object): + """A wheel file""" + + # TODO: maybe move the install code into this class + + wheel_file_re = re.compile( + r"""^(?P<namever>(?P<name>.+?)-(?P<ver>.*?)) + ((-(?P<build>\d[^-]*?))?-(?P<pyver>.+?)-(?P<abi>.+?)-(?P<plat>.+?) + \.whl|\.dist-info)$""", + re.VERBOSE + ) + + def __init__(self, filename): + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ + wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename( + "%s is not a valid wheel filename." % filename + ) + self.filename = filename + self.name = wheel_info.group('name').replace('_', '-') + # we'll assume "_" means "-" due to wheel naming scheme + # (https://github.com/pypa/pip/issues/1150) + self.version = wheel_info.group('ver').replace('_', '-') + self.build_tag = wheel_info.group('build') + self.pyversions = wheel_info.group('pyver').split('.') + self.abis = wheel_info.group('abi').split('.') + self.plats = wheel_info.group('plat').split('.') + + # All the tag combinations from this file + self.file_tags = { + (x, y, z) for x in self.pyversions + for y in self.abis for z in self.plats + } + + def support_index_min(self, tags=None): + """ + Return the lowest index that one of the wheel's file_tag combinations + achieves in the supported_tags list e.g. if there are 8 supported tags, + and one of the file tags is first in the list, then return 0. Returns + None is the wheel is not supported. + """ + if tags is None: # for mock + tags = pep425tags.get_supported() + indexes = [tags.index(c) for c in self.file_tags if c in tags] + return min(indexes) if indexes else None + + def supported(self, tags=None): + """Is this wheel supported on this system?""" + if tags is None: # for mock + tags = pep425tags.get_supported() + return bool(set(tags).intersection(self.file_tags)) + + +class WheelBuilder(object): + """Build wheels from a RequirementSet.""" + + def __init__(self, finder, preparer, wheel_cache, + build_options=None, global_options=None, no_clean=False): + self.finder = finder + self.preparer = preparer + self.wheel_cache = wheel_cache + + self._wheel_dir = preparer.wheel_download_dir + + self.build_options = build_options or [] + self.global_options = global_options or [] + self.no_clean = no_clean + + def _build_one(self, req, output_dir, python_tag=None): + """Build one wheel. + + :return: The filename of the built wheel, or None if the build failed. + """ + # Install build deps into temporary directory (PEP 518) + with req.build_env: + return self._build_one_inside_env(req, output_dir, + python_tag=python_tag) + + def _build_one_inside_env(self, req, output_dir, python_tag=None): + with TempDirectory(kind="wheel") as temp_dir: + if self.__build_one(req, temp_dir.path, python_tag=python_tag): + try: + wheel_name = os.listdir(temp_dir.path)[0] + wheel_path = os.path.join(output_dir, wheel_name) + shutil.move( + os.path.join(temp_dir.path, wheel_name), wheel_path + ) + logger.info('Stored in directory: %s', output_dir) + return wheel_path + except Exception: + pass + # Ignore return, we can't do anything else useful. + self._clean_one(req) + return None + + def _base_setup_args(self, req): + # NOTE: Eventually, we'd want to also -S to the flags here, when we're + # isolating. Currently, it breaks Python in virtualenvs, because it + # relies on site.py to find parts of the standard library outside the + # virtualenv. + return [ + sys.executable, '-u', '-c', + SETUPTOOLS_SHIM % req.setup_py + ] + list(self.global_options) + + def __build_one(self, req, tempd, python_tag=None): + base_args = self._base_setup_args(req) + + spin_message = 'Running setup.py bdist_wheel for %s' % (req.name,) + with open_spinner(spin_message) as spinner: + logger.debug('Destination directory: %s', tempd) + wheel_args = base_args + ['bdist_wheel', '-d', tempd] \ + + self.build_options + + if python_tag is not None: + wheel_args += ["--python-tag", python_tag] + + try: + call_subprocess(wheel_args, cwd=req.setup_py_dir, + show_stdout=False, spinner=spinner) + return True + except Exception: + spinner.finish("error") + logger.error('Failed building wheel for %s', req.name) + return False + + def _clean_one(self, req): + base_args = self._base_setup_args(req) + + logger.info('Running setup.py clean for %s', req.name) + clean_args = base_args + ['clean', '--all'] + try: + call_subprocess(clean_args, cwd=req.source_dir, show_stdout=False) + return True + except Exception: + logger.error('Failed cleaning build dir for %s', req.name) + return False + + def build(self, requirements, session, autobuilding=False): + """Build wheels. + + :param unpack: If True, replace the sdist we built from with the + newly built wheel, in preparation for installation. + :return: True if all the wheels built correctly. + """ + from pip._internal import index + from pip._internal.models.link import Link + + building_is_possible = self._wheel_dir or ( + autobuilding and self.wheel_cache.cache_dir + ) + assert building_is_possible + + buildset = [] + format_control = self.finder.format_control + for req in requirements: + if req.constraint: + continue + if req.is_wheel: + if not autobuilding: + logger.info( + 'Skipping %s, due to already being wheel.', req.name, + ) + elif autobuilding and req.editable: + pass + elif autobuilding and not req.source_dir: + pass + elif autobuilding and req.link and not req.link.is_artifact: + # VCS checkout. Build wheel just for this run. + buildset.append((req, True)) + else: + ephem_cache = False + if autobuilding: + link = req.link + base, ext = link.splitext() + if index.egg_info_matches(base, None, link) is None: + # E.g. local directory. Build wheel just for this run. + ephem_cache = True + if "binary" not in format_control.get_allowed_formats( + canonicalize_name(req.name)): + logger.info( + "Skipping bdist_wheel for %s, due to binaries " + "being disabled for it.", req.name, + ) + continue + buildset.append((req, ephem_cache)) + + if not buildset: + return True + + # Build the wheels. + logger.info( + 'Building wheels for collected packages: %s', + ', '.join([req.name for (req, _) in buildset]), + ) + _cache = self.wheel_cache # shorter name + with indent_log(): + build_success, build_failure = [], [] + for req, ephem in buildset: + python_tag = None + if autobuilding: + python_tag = pep425tags.implementation_tag + if ephem: + output_dir = _cache.get_ephem_path_for_link(req.link) + else: + output_dir = _cache.get_path_for_link(req.link) + try: + ensure_dir(output_dir) + except OSError as e: + logger.warning("Building wheel for %s failed: %s", + req.name, e) + build_failure.append(req) + continue + else: + output_dir = self._wheel_dir + wheel_file = self._build_one( + req, output_dir, + python_tag=python_tag, + ) + if wheel_file: + build_success.append(req) + if autobuilding: + # XXX: This is mildly duplicative with prepare_files, + # but not close enough to pull out to a single common + # method. + # The code below assumes temporary source dirs - + # prevent it doing bad things. + if req.source_dir and not os.path.exists(os.path.join( + req.source_dir, PIP_DELETE_MARKER_FILENAME)): + raise AssertionError( + "bad source dir - missing marker") + # Delete the source we built the wheel from + req.remove_temporary_source() + # set the build directory again - name is known from + # the work prepare_files did. + req.source_dir = req.build_location( + self.preparer.build_dir + ) + # Update the link for this. + req.link = Link(path_to_url(wheel_file)) + assert req.link.is_wheel + # extract the wheel into the dir + unpack_url( + req.link, req.source_dir, None, False, + session=session, + ) + else: + build_failure.append(req) + + # notify success/failure + if build_success: + logger.info( + 'Successfully built %s', + ' '.join([req.name for req in build_success]), + ) + if build_failure: + logger.info( + 'Failed to build %s', + ' '.join([req.name for req in build_failure]), + ) + # Return True if all builds were successful + return len(build_failure) == 0 diff --git a/winvenv/Lib/site-packages/pip/_vendor/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000..a0aae81 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,110 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import + +import glob +import os.path +import sys + +# Downstream redistributors which have debundled our dependencies should also +# patch this value to be true. This will trigger the additional patching +# to cause things like "six" to be available as pip. +DEBUNDLED = False + +# By default, look in this directory for a bunch of .whl files which we will +# add to the beginning of sys.path before attempting to import anything. This +# is done to support downstream re-distributors like Debian and Fedora who +# wish to create their own Wheels for our dependencies to aid in debundling. +WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) + + +# Define a small helper function to alias our vendored modules to the real ones +# if the vendored ones do not exist. This idea of this was taken from +# https://github.com/kennethreitz/requests/pull/2567. +def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: + __import__(vendored_name, globals(), locals(), level=0) + except ImportError: + try: + __import__(modulename, globals(), locals(), level=0) + except ImportError: + # We can just silently allow import failures to pass here. If we + # got to this point it means that ``import pip._vendor.whatever`` + # failed and so did ``import whatever``. Since we're importing this + # upfront in an attempt to alias imports, not erroring here will + # just mean we get a regular import error whenever pip *actually* + # tries to import one of these modules to use it, which actually + # gives us a better error message than we would have otherwise + # gotten. + pass + else: + sys.modules[vendored_name] = sys.modules[modulename] + base, head = vendored_name.rsplit(".", 1) + setattr(sys.modules[base], head, sys.modules[modulename]) + + +# If we're operating in a debundled setup, then we want to go ahead and trigger +# the aliasing of our vendored libraries as well as looking for wheels to add +# to our sys.path. This will cause all of this code to be a no-op typically +# however downstream redistributors can enable it in a consistent way across +# all platforms. +if DEBUNDLED: + # Actually look inside of WHEEL_DIR to find .whl files and add them to the + # front of our sys.path. + sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path + + # Actually alias all of our vendored dependencies. + vendored("cachecontrol") + vendored("colorama") + vendored("distlib") + vendored("distro") + vendored("html5lib") + vendored("lockfile") + vendored("six") + vendored("six.moves") + vendored("six.moves.urllib") + vendored("six.moves.urllib.parse") + vendored("packaging") + vendored("packaging.version") + vendored("packaging.specifiers") + vendored("pkg_resources") + vendored("progress") + vendored("pytoml") + vendored("retrying") + vendored("requests") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") + vendored("requests.packages.urllib3.connection") + vendored("requests.packages.urllib3.connectionpool") + vendored("requests.packages.urllib3.contrib") + vendored("requests.packages.urllib3.contrib.ntlmpool") + vendored("requests.packages.urllib3.contrib.pyopenssl") + vendored("requests.packages.urllib3.exceptions") + vendored("requests.packages.urllib3.fields") + vendored("requests.packages.urllib3.filepost") + vendored("requests.packages.urllib3.packages") + vendored("requests.packages.urllib3.packages.ordered_dict") + vendored("requests.packages.urllib3.packages.six") + vendored("requests.packages.urllib3.packages.ssl_match_hostname") + vendored("requests.packages.urllib3.packages.ssl_match_hostname." + "_implementation") + vendored("requests.packages.urllib3.poolmanager") + vendored("requests.packages.urllib3.request") + vendored("requests.packages.urllib3.response") + vendored("requests.packages.urllib3.util") + vendored("requests.packages.urllib3.util.connection") + vendored("requests.packages.urllib3.util.request") + vendored("requests.packages.urllib3.util.response") + vendored("requests.packages.urllib3.util.retry") + vendored("requests.packages.urllib3.util.ssl_") + vendored("requests.packages.urllib3.util.timeout") + vendored("requests.packages.urllib3.util.url") + vendored("urllib3") diff --git a/winvenv/Lib/site-packages/pip/_vendor/appdirs.py b/winvenv/Lib/site-packages/pip/_vendor/appdirs.py new file mode 100644 index 0000000..2bd3911 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/appdirs.py @@ -0,0 +1,604 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2005-2010 ActiveState Software Inc. +# Copyright (c) 2013 Eddy Petrișor + +"""Utilities for determining application-specific dirs. + +See <http://github.com/ActiveState/appdirs> for details and usage. +""" +# Dev Notes: +# - MSDN on where to store app data files: +# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 +# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +__version_info__ = (1, 4, 3) +__version__ = '.'.join(map(str, __version_info__)) + + +import sys +import os + +PY3 = sys.version_info[0] == 3 + +if PY3: + unicode = str + +if sys.platform.startswith('java'): + import platform + os_name = platform.java_ver()[3][0] + if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. + system = 'win32' + elif os_name.startswith('Mac'): # "Mac OS X", etc. + system = 'darwin' + else: # "Linux", "SunOS", "FreeBSD", etc. + # Setting this to "linux2" is not ideal, but only Windows or Mac + # are actually checked for and the rest of the module expects + # *sys.platform* style strings. + system = 'linux2' +else: + system = sys.platform + + + +def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user data directories are: + Mac OS X: ~/Library/Application Support/<AppName> + Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> + Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> + Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> + Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/<AppName>". + """ + if system == "win32": + if appauthor is None: + appauthor = appname + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.normpath(_get_win_folder(const)) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('~/Library/Application Support/') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of data dirs should be + returned. By default, the first item from XDG_DATA_DIRS is + returned, or '/usr/local/share/<AppName>', + if XDG_DATA_DIRS is not set + + Typical site data directories are: + Mac OS X: /Library/Application Support/<AppName> + Unix: /usr/local/share/<AppName> or /usr/share/<AppName> + Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. + + For Unix, this is using the $XDG_DATA_DIRS[0] default. + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('/Library/Application Support') + if appname: + path = os.path.join(path, appname) + else: + # XDG default for $XDG_DATA_DIRS + # only first, if multipath is False + path = os.getenv('XDG_DATA_DIRS', + os.pathsep.join(['/usr/local/share', '/usr/share'])) + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + if appname and version: + path = os.path.join(path, version) + return path + + +def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user config directories are: + Mac OS X: same as user_data_dir + Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of config dirs should be + returned. By default, the first item from XDG_CONFIG_DIRS is + returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set + + Typical site config directories are: + Mac OS X: same as site_data_dir + Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in + $XDG_CONFIG_DIRS + Win *: same as site_data_dir + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + + For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system in ["win32", "darwin"]: + path = site_data_dir(appname, appauthor) + if appname and version: + path = os.path.join(path, version) + else: + # XDG default for $XDG_CONFIG_DIRS + # only first, if multipath is False + path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + +def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Cache" to the base app data dir for Windows. See + discussion below. + + Typical user cache directories are: + Mac OS X: ~/Library/Caches/<AppName> + Unix: ~/.cache/<AppName> (XDG default) + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go in + the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming + app data dir (the default returned by `user_data_dir` above). Apps typically + put cache data somewhere *under* the given dir here. Some examples: + ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache + ...\Acme\SuperApp\Cache\1.0 + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + This can be disabled with the `opinion=False` option. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + if opinion: + path = os.path.join(path, "Cache") + elif system == 'darwin': + path = os.path.expanduser('~/Library/Caches') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific state dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific log dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Logs" to the base app data dir for Windows, and "log" to the + base cache dir for Unix. See discussion below. + + Typical user log directories are: + Mac OS X: ~/Library/Logs/<AppName> + Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs + + On Windows the only suggestion in the MSDN docs is that local settings + go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in + examples of what some windows apps use for a logs dir.) + + OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` + value for Windows and appends "log" to the user cache dir for Unix. + This can be disabled with the `opinion=False` option. + """ + if system == "darwin": + path = os.path.join( + os.path.expanduser('~/Library/Logs'), + appname) + elif system == "win32": + path = user_data_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "Logs") + else: + path = user_cache_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "log") + if appname and version: + path = os.path.join(path, version) + return path + + +class AppDirs(object): + """Convenience wrapper for getting application dirs.""" + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): + self.appname = appname + self.appauthor = appauthor + self.version = version + self.roaming = roaming + self.multipath = multipath + + @property + def user_data_dir(self): + return user_data_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_data_dir(self): + return site_data_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_config_dir(self): + return user_config_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_config_dir(self): + return site_config_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_cache_dir(self): + return user_cache_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_state_dir(self): + return user_state_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_log_dir(self): + return user_log_dir(self.appname, self.appauthor, + version=self.version) + + +#---- internal support stuff + +def _get_win_folder_from_registry(csidl_name): + """This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + if PY3: + import winreg as _winreg + else: + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + dir, type = _winreg.QueryValueEx(key, shell_folder_name) + return dir + + +def _get_win_folder_with_pywin32(csidl_name): + from win32com.shell import shellcon, shell + dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) + # Try to make this a unicode path because SHGetFolderPath does + # not return unicode strings when there is unicode data in the + # path. + try: + dir = unicode(dir) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + try: + import win32api + dir = win32api.GetShortPathName(dir) + except ImportError: + pass + except UnicodeError: + pass + return dir + + +def _get_win_folder_with_ctypes(csidl_name): + import ctypes + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + +def _get_win_folder_with_jna(csidl_name): + import array + from com.sun import jna + from com.sun.jna.platform import win32 + + buf_size = win32.WinDef.MAX_PATH * 2 + buf = array.zeros('c', buf_size) + shell = win32.Shell32.INSTANCE + shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf = array.zeros('c', buf_size) + kernel = win32.Kernel32.INSTANCE + if kernel.GetShortPathName(dir, buf, buf_size): + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + return dir + +if system == "win32": + try: + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + try: + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +#---- self test code + +if __name__ == "__main__": + appname = "MyApp" + appauthor = "MyCompany" + + props = ("user_data_dir", + "user_config_dir", + "user_cache_dir", + "user_state_dir", + "user_log_dir", + "site_data_dir", + "site_config_dir") + + print("-- app dirs %s --" % __version__) + + print("-- app dirs (with optional 'version')") + dirs = AppDirs(appname, appauthor, version="1.0") + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'version')") + dirs = AppDirs(appname, appauthor) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'appauthor')") + dirs = AppDirs(appname) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (with disabled 'appauthor')") + dirs = AppDirs(appname, appauthor=False) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py new file mode 100644 index 0000000..8fdee66 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py @@ -0,0 +1,11 @@ +"""CacheControl import Interface. + +Make it easy to import from cachecontrol without long namespaces. +""" +__author__ = "Eric Larson" +__email__ = "eric@ionrock.org" +__version__ = "0.12.5" + +from .wrapper import CacheControl +from .adapter import CacheControlAdapter +from .controller import CacheController diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py new file mode 100644 index 0000000..f1e0ad9 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py @@ -0,0 +1,57 @@ +import logging + +from pip._vendor import requests + +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.cache import DictCache +from pip._vendor.cachecontrol.controller import logger + +from argparse import ArgumentParser + + +def setup_logging(): + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + logger.addHandler(handler) + + +def get_session(): + adapter = CacheControlAdapter( + DictCache(), cache_etags=True, serializer=None, heuristic=None + ) + sess = requests.Session() + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + sess.cache_controller = adapter.controller + return sess + + +def get_args(): + parser = ArgumentParser() + parser.add_argument("url", help="The URL to try and cache") + return parser.parse_args() + + +def main(args=None): + args = get_args() + sess = get_session() + + # Make a request to get a response + resp = sess.get(args.url) + + # Turn on logging + setup_logging() + + # try setting the cache + sess.cache_controller.cache_response(resp.request, resp.raw) + + # Now try to get it + if sess.cache_controller.cached_request(resp.request): + print("Cached!") + else: + print("Not cached :(") + + +if __name__ == "__main__": + main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py new file mode 100644 index 0000000..780eb28 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py @@ -0,0 +1,133 @@ +import types +import functools +import zlib + +from pip._vendor.requests.adapters import HTTPAdapter + +from .controller import CacheController +from .cache import DictCache +from .filewrapper import CallbackFileWrapper + + +class CacheControlAdapter(HTTPAdapter): + invalidating_methods = {"PUT", "DELETE"} + + def __init__( + self, + cache=None, + cache_etags=True, + controller_class=None, + serializer=None, + heuristic=None, + cacheable_methods=None, + *args, + **kw + ): + super(CacheControlAdapter, self).__init__(*args, **kw) + self.cache = cache or DictCache() + self.heuristic = heuristic + self.cacheable_methods = cacheable_methods or ("GET",) + + controller_factory = controller_class or CacheController + self.controller = controller_factory( + self.cache, cache_etags=cache_etags, serializer=serializer + ) + + def send(self, request, cacheable_methods=None, **kw): + """ + Send a request. Use the request information to see if it + exists in the cache and cache the response if we need to and can. + """ + cacheable = cacheable_methods or self.cacheable_methods + if request.method in cacheable: + try: + cached_response = self.controller.cached_request(request) + except zlib.error: + cached_response = None + if cached_response: + return self.build_response(request, cached_response, from_cache=True) + + # check for etags and add headers if appropriate + request.headers.update(self.controller.conditional_headers(request)) + + resp = super(CacheControlAdapter, self).send(request, **kw) + + return resp + + def build_response( + self, request, response, from_cache=False, cacheable_methods=None + ): + """ + Build a response by making a request or using the cache. + + This will end up calling send and returning a potentially + cached response + """ + cacheable = cacheable_methods or self.cacheable_methods + if not from_cache and request.method in cacheable: + # Check for any heuristics that might update headers + # before trying to cache. + if self.heuristic: + response = self.heuristic.apply(response) + + # apply any expiration heuristics + if response.status == 304: + # We must have sent an ETag request. This could mean + # that we've been expired already or that we simply + # have an etag. In either case, we want to try and + # update the cache if that is the case. + cached_response = self.controller.update_cached_response( + request, response + ) + + if cached_response is not response: + from_cache = True + + # We are done with the server response, read a + # possible response body (compliant servers will + # not return one, but we cannot be 100% sure) and + # release the connection back to the pool. + response.read(decode_content=False) + response.release_conn() + + response = cached_response + + # We always cache the 301 responses + elif response.status == 301: + self.controller.cache_response(request, response) + else: + # Wrap the response file with a wrapper that will cache the + # response when the stream has been consumed. + response._fp = CallbackFileWrapper( + response._fp, + functools.partial( + self.controller.cache_response, request, response + ), + ) + if response.chunked: + super_update_chunk_length = response._update_chunk_length + + def _update_chunk_length(self): + super_update_chunk_length() + if self.chunk_left == 0: + self._fp._close() + + response._update_chunk_length = types.MethodType( + _update_chunk_length, response + ) + + resp = super(CacheControlAdapter, self).build_response(request, response) + + # See if we should invalidate the cache. + if request.method in self.invalidating_methods and resp.ok: + cache_url = self.controller.cache_url(request.url) + self.cache.delete(cache_url) + + # Give the request a from_cache attr to let people use it + resp.from_cache = from_cache + + return resp + + def close(self): + self.cache.close() + super(CacheControlAdapter, self).close() diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py new file mode 100644 index 0000000..94e0773 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py @@ -0,0 +1,39 @@ +""" +The cache object API for implementing caches. The default is a thread +safe in-memory dictionary. +""" +from threading import Lock + + +class BaseCache(object): + + def get(self, key): + raise NotImplementedError() + + def set(self, key, value): + raise NotImplementedError() + + def delete(self, key): + raise NotImplementedError() + + def close(self): + pass + + +class DictCache(BaseCache): + + def __init__(self, init_dict=None): + self.lock = Lock() + self.data = init_dict or {} + + def get(self, key): + return self.data.get(key, None) + + def set(self, key, value): + with self.lock: + self.data.update({key: value}) + + def delete(self, key): + with self.lock: + if key in self.data: + self.data.pop(key) diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py new file mode 100644 index 0000000..0e1658f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py @@ -0,0 +1,2 @@ +from .file_cache import FileCache # noqa +from .redis_cache import RedisCache # noqa diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py new file mode 100644 index 0000000..1ba0080 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py @@ -0,0 +1,146 @@ +import hashlib +import os +from textwrap import dedent + +from ..cache import BaseCache +from ..controller import CacheController + +try: + FileNotFoundError +except NameError: + # py2.X + FileNotFoundError = (IOError, OSError) + + +def _secure_open_write(filename, fmode): + # We only want to write to this file, so open it in write only mode + flags = os.O_WRONLY + + # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only + # will open *new* files. + # We specify this because we want to ensure that the mode we pass is the + # mode of the file. + flags |= os.O_CREAT | os.O_EXCL + + # Do not follow symlinks to prevent someone from making a symlink that + # we follow and insecurely open a cache file. + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + + # On Windows we'll mark this file as binary + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + + # Before we open our file, we want to delete any existing file that is + # there + try: + os.remove(filename) + except (IOError, OSError): + # The file must not exist already, so we can just skip ahead to opening + pass + + # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a + # race condition happens between the os.remove and this line, that an + # error will be raised. Because we utilize a lockfile this should only + # happen if someone is attempting to attack us. + fd = os.open(filename, flags, fmode) + try: + return os.fdopen(fd, "wb") + + except: + # An error occurred wrapping our FD in a file object + os.close(fd) + raise + + +class FileCache(BaseCache): + + def __init__( + self, + directory, + forever=False, + filemode=0o0600, + dirmode=0o0700, + use_dir_lock=None, + lock_class=None, + ): + + if use_dir_lock is not None and lock_class is not None: + raise ValueError("Cannot use use_dir_lock and lock_class together") + + try: + from pip._vendor.lockfile import LockFile + from pip._vendor.lockfile.mkdirlockfile import MkdirLockFile + except ImportError: + notice = dedent( + """ + NOTE: In order to use the FileCache you must have + lockfile installed. You can install it via pip: + pip install lockfile + """ + ) + raise ImportError(notice) + + else: + if use_dir_lock: + lock_class = MkdirLockFile + + elif lock_class is None: + lock_class = LockFile + + self.directory = directory + self.forever = forever + self.filemode = filemode + self.dirmode = dirmode + self.lock_class = lock_class + + @staticmethod + def encode(x): + return hashlib.sha224(x.encode()).hexdigest() + + def _fn(self, name): + # NOTE: This method should not change as some may depend on it. + # See: https://github.com/ionrock/cachecontrol/issues/63 + hashed = self.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key): + name = self._fn(key) + try: + with open(name, "rb") as fh: + return fh.read() + + except FileNotFoundError: + return None + + def set(self, key, value): + name = self._fn(key) + + # Make sure the directory exists + try: + os.makedirs(os.path.dirname(name), self.dirmode) + except (IOError, OSError): + pass + + with self.lock_class(name) as lock: + # Write our actual file + with _secure_open_write(lock.path, self.filemode) as fh: + fh.write(value) + + def delete(self, key): + name = self._fn(key) + if not self.forever: + try: + os.remove(name) + except FileNotFoundError: + pass + + +def url_to_file_path(url, filecache): + """Return the file cache path based on the URL. + + This does not ensure the file exists! + """ + key = CacheController.cache_url(url) + return filecache._fn(key) diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py new file mode 100644 index 0000000..ed705ce --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -0,0 +1,33 @@ +from __future__ import division + +from datetime import datetime +from pip._vendor.cachecontrol.cache import BaseCache + + +class RedisCache(BaseCache): + + def __init__(self, conn): + self.conn = conn + + def get(self, key): + return self.conn.get(key) + + def set(self, key, value, expires=None): + if not expires: + self.conn.set(key, value) + else: + expires = expires - datetime.utcnow() + self.conn.setex(key, int(expires.total_seconds()), value) + + def delete(self, key): + self.conn.delete(key) + + def clear(self): + """Helper for clearing all the keys in a database. Use with + caution!""" + for key in self.conn.keys(): + self.conn.delete(key) + + def close(self): + """Redis uses connection pooling, no need to close the connection.""" + pass diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py new file mode 100644 index 0000000..33b5aed --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py @@ -0,0 +1,29 @@ +try: + from urllib.parse import urljoin +except ImportError: + from urlparse import urljoin + + +try: + import cPickle as pickle +except ImportError: + import pickle + + +# Handle the case where the requests module has been patched to not have +# urllib3 bundled as part of its source. +try: + from pip._vendor.requests.packages.urllib3.response import HTTPResponse +except ImportError: + from pip._vendor.urllib3.response import HTTPResponse + +try: + from pip._vendor.requests.packages.urllib3.util import is_fp_closed +except ImportError: + from pip._vendor.urllib3.util import is_fp_closed + +# Replicate some six behaviour +try: + text_type = unicode +except NameError: + text_type = str diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py new file mode 100644 index 0000000..1b2b943 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py @@ -0,0 +1,367 @@ +""" +The httplib2 algorithms ported for use with requests. +""" +import logging +import re +import calendar +import time +from email.utils import parsedate_tz + +from pip._vendor.requests.structures import CaseInsensitiveDict + +from .cache import DictCache +from .serialize import Serializer + + +logger = logging.getLogger(__name__) + +URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") + + +def parse_uri(uri): + """Parses a URI using the regex given in Appendix B of RFC 3986. + + (scheme, authority, path, query, fragment) = parse_uri(uri) + """ + groups = URI.match(uri).groups() + return (groups[1], groups[3], groups[4], groups[6], groups[8]) + + +class CacheController(object): + """An interface to see if request should cached or not. + """ + + def __init__( + self, cache=None, cache_etags=True, serializer=None, status_codes=None + ): + self.cache = cache or DictCache() + self.cache_etags = cache_etags + self.serializer = serializer or Serializer() + self.cacheable_status_codes = status_codes or (200, 203, 300, 301) + + @classmethod + def _urlnorm(cls, uri): + """Normalize the URL to create a safe key for the cache""" + (scheme, authority, path, query, fragment) = parse_uri(uri) + if not scheme or not authority: + raise Exception("Only absolute URIs are allowed. uri = %s" % uri) + + scheme = scheme.lower() + authority = authority.lower() + + if not path: + path = "/" + + # Could do syntax based normalization of the URI before + # computing the digest. See Section 6.2.2 of Std 66. + request_uri = query and "?".join([path, query]) or path + defrag_uri = scheme + "://" + authority + request_uri + + return defrag_uri + + @classmethod + def cache_url(cls, uri): + return cls._urlnorm(uri) + + def parse_cache_control(self, headers): + known_directives = { + # https://tools.ietf.org/html/rfc7234#section-5.2 + "max-age": (int, True), + "max-stale": (int, False), + "min-fresh": (int, True), + "no-cache": (None, False), + "no-store": (None, False), + "no-transform": (None, False), + "only-if-cached": (None, False), + "must-revalidate": (None, False), + "public": (None, False), + "private": (None, False), + "proxy-revalidate": (None, False), + "s-maxage": (int, True), + } + + cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) + + retval = {} + + for cc_directive in cc_headers.split(","): + if not cc_directive.strip(): + continue + + parts = cc_directive.split("=", 1) + directive = parts[0].strip() + + try: + typ, required = known_directives[directive] + except KeyError: + logger.debug("Ignoring unknown cache-control directive: %s", directive) + continue + + if not typ or not required: + retval[directive] = None + if typ: + try: + retval[directive] = typ(parts[1].strip()) + except IndexError: + if required: + logger.debug( + "Missing value for cache-control " "directive: %s", + directive, + ) + except ValueError: + logger.debug( + "Invalid value for cache-control directive " "%s, must be %s", + directive, + typ.__name__, + ) + + return retval + + def cached_request(self, request): + """ + Return a cached response if it exists in the cache, otherwise + return False. + """ + cache_url = self.cache_url(request.url) + logger.debug('Looking up "%s" in the cache', cache_url) + cc = self.parse_cache_control(request.headers) + + # Bail out if the request insists on fresh data + if "no-cache" in cc: + logger.debug('Request header has "no-cache", cache bypassed') + return False + + if "max-age" in cc and cc["max-age"] == 0: + logger.debug('Request header has "max_age" as 0, cache bypassed') + return False + + # Request allows serving from the cache, let's see if we find something + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return False + + # Check whether it can be deserialized + resp = self.serializer.loads(request, cache_data) + if not resp: + logger.warning("Cache entry deserialization failed, entry ignored") + return False + + # If we have a cached 301, return it immediately. We don't + # need to test our response for other headers b/c it is + # intrinsically "cacheable" as it is Permanent. + # See: + # https://tools.ietf.org/html/rfc7231#section-6.4.2 + # + # Client can try to refresh the value by repeating the request + # with cache busting headers as usual (ie no-cache). + if resp.status == 301: + msg = ( + 'Returning cached "301 Moved Permanently" response ' + "(ignoring date and etag information)" + ) + logger.debug(msg) + return resp + + headers = CaseInsensitiveDict(resp.headers) + if not headers or "date" not in headers: + if "etag" not in headers: + # Without date or etag, the cached response can never be used + # and should be deleted. + logger.debug("Purging cached response: no date or etag") + self.cache.delete(cache_url) + logger.debug("Ignoring cached response: no date") + return False + + now = time.time() + date = calendar.timegm(parsedate_tz(headers["date"])) + current_age = max(0, now - date) + logger.debug("Current age based on date: %i", current_age) + + # TODO: There is an assumption that the result will be a + # urllib3 response object. This may not be best since we + # could probably avoid instantiating or constructing the + # response until we know we need it. + resp_cc = self.parse_cache_control(headers) + + # determine freshness + freshness_lifetime = 0 + + # Check the max-age pragma in the cache control header + if "max-age" in resp_cc: + freshness_lifetime = resp_cc["max-age"] + logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) + + # If there isn't a max-age, check for an expires header + elif "expires" in headers: + expires = parsedate_tz(headers["expires"]) + if expires is not None: + expire_time = calendar.timegm(expires) - date + freshness_lifetime = max(0, expire_time) + logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) + + # Determine if we are setting freshness limit in the + # request. Note, this overrides what was in the response. + if "max-age" in cc: + freshness_lifetime = cc["max-age"] + logger.debug( + "Freshness lifetime from request max-age: %i", freshness_lifetime + ) + + if "min-fresh" in cc: + min_fresh = cc["min-fresh"] + # adjust our current age by our min fresh + current_age += min_fresh + logger.debug("Adjusted current age from min-fresh: %i", current_age) + + # Return entry if it is fresh enough + if freshness_lifetime > current_age: + logger.debug('The response is "fresh", returning cached response') + logger.debug("%i > %i", freshness_lifetime, current_age) + return resp + + # we're not fresh. If we don't have an Etag, clear it out + if "etag" not in headers: + logger.debug('The cached response is "stale" with no etag, purging') + self.cache.delete(cache_url) + + # return the original handler + return False + + def conditional_headers(self, request): + cache_url = self.cache_url(request.url) + resp = self.serializer.loads(request, self.cache.get(cache_url)) + new_headers = {} + + if resp: + headers = CaseInsensitiveDict(resp.headers) + + if "etag" in headers: + new_headers["If-None-Match"] = headers["ETag"] + + if "last-modified" in headers: + new_headers["If-Modified-Since"] = headers["Last-Modified"] + + return new_headers + + def cache_response(self, request, response, body=None, status_codes=None): + """ + Algorithm for caching requests. + + This assumes a requests Response object. + """ + # From httplib2: Don't cache 206's since we aren't going to + # handle byte range requests + cacheable_status_codes = status_codes or self.cacheable_status_codes + if response.status not in cacheable_status_codes: + logger.debug( + "Status code %s not in %s", response.status, cacheable_status_codes + ) + return + + response_headers = CaseInsensitiveDict(response.headers) + + # If we've been given a body, our response has a Content-Length, that + # Content-Length is valid then we can check to see if the body we've + # been given matches the expected size, and if it doesn't we'll just + # skip trying to cache it. + if ( + body is not None + and "content-length" in response_headers + and response_headers["content-length"].isdigit() + and int(response_headers["content-length"]) != len(body) + ): + return + + cc_req = self.parse_cache_control(request.headers) + cc = self.parse_cache_control(response_headers) + + cache_url = self.cache_url(request.url) + logger.debug('Updating cache with response from "%s"', cache_url) + + # Delete it from the cache if we happen to have it stored there + no_store = False + if "no-store" in cc: + no_store = True + logger.debug('Response header has "no-store"') + if "no-store" in cc_req: + no_store = True + logger.debug('Request header has "no-store"') + if no_store and self.cache.get(cache_url): + logger.debug('Purging existing cache entry to honor "no-store"') + self.cache.delete(cache_url) + if no_store: + return + + # If we've been given an etag, then keep the response + if self.cache_etags and "etag" in response_headers: + logger.debug("Caching due to etag") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + # Add to the cache any 301s. We do this before looking that + # the Date headers. + elif response.status == 301: + logger.debug("Caching permanant redirect") + self.cache.set(cache_url, self.serializer.dumps(request, response)) + + # Add to the cache if the response headers demand it. If there + # is no date header then we can't do anything about expiring + # the cache. + elif "date" in response_headers: + # cache when there is a max-age > 0 + if "max-age" in cc and cc["max-age"] > 0: + logger.debug("Caching b/c date exists and max-age > 0") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + # If the request can expire, it means we should cache it + # in the meantime. + elif "expires" in response_headers: + if response_headers["expires"]: + logger.debug("Caching b/c of expires header") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + def update_cached_response(self, request, response): + """On a 304 we will get a new set of headers that we want to + update our cached value with, assuming we have one. + + This should only ever be called when we've sent an ETag and + gotten a 304 as the response. + """ + cache_url = self.cache_url(request.url) + + cached_response = self.serializer.loads(request, self.cache.get(cache_url)) + + if not cached_response: + # we didn't have a cached response + return response + + # Lets update our headers with the headers from the new request: + # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 + # + # The server isn't supposed to send headers that would make + # the cached body invalid. But... just in case, we'll be sure + # to strip out ones we know that might be problmatic due to + # typical assumptions. + excluded_headers = ["content-length"] + + cached_response.headers.update( + dict( + (k, v) + for k, v in response.headers.items() + if k.lower() not in excluded_headers + ) + ) + + # we want a 200 b/c we have content via the cache + cached_response.status = 200 + + # update our cache + self.cache.set(cache_url, self.serializer.dumps(request, cached_response)) + + return cached_response diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py new file mode 100644 index 0000000..30ed4c5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py @@ -0,0 +1,80 @@ +from io import BytesIO + + +class CallbackFileWrapper(object): + """ + Small wrapper around a fp object which will tee everything read into a + buffer, and when that file is closed it will execute a callback with the + contents of that buffer. + + All attributes are proxied to the underlying file object. + + This class uses members with a double underscore (__) leading prefix so as + not to accidentally shadow an attribute. + """ + + def __init__(self, fp, callback): + self.__buf = BytesIO() + self.__fp = fp + self.__callback = callback + + def __getattr__(self, name): + # The vaguaries of garbage collection means that self.__fp is + # not always set. By using __getattribute__ and the private + # name[0] allows looking up the attribute value and raising an + # AttributeError when it doesn't exist. This stop thigns from + # infinitely recursing calls to getattr in the case where + # self.__fp hasn't been set. + # + # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers + fp = self.__getattribute__("_CallbackFileWrapper__fp") + return getattr(fp, name) + + def __is_fp_closed(self): + try: + return self.__fp.fp is None + + except AttributeError: + pass + + try: + return self.__fp.closed + + except AttributeError: + pass + + # We just don't cache it then. + # TODO: Add some logging here... + return False + + def _close(self): + if self.__callback: + self.__callback(self.__buf.getvalue()) + + # We assign this to None here, because otherwise we can get into + # really tricky problems where the CPython interpreter dead locks + # because the callback is holding a reference to something which + # has a __del__ method. Setting this to None breaks the cycle + # and allows the garbage collector to do it's thing normally. + self.__callback = None + + def read(self, amt=None): + data = self.__fp.read(amt) + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data + + def _safe_read(self, amt): + data = self.__fp._safe_read(amt) + if amt == 2 and data == b"\r\n": + # urllib executes this read to toss the CRLF at the end + # of the chunk. + return data + + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py new file mode 100644 index 0000000..6c0e979 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py @@ -0,0 +1,135 @@ +import calendar +import time + +from email.utils import formatdate, parsedate, parsedate_tz + +from datetime import datetime, timedelta + +TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" + + +def expire_after(delta, date=None): + date = date or datetime.utcnow() + return date + delta + + +def datetime_to_header(dt): + return formatdate(calendar.timegm(dt.timetuple())) + + +class BaseHeuristic(object): + + def warning(self, response): + """ + Return a valid 1xx warning header value describing the cache + adjustments. + + The response is provided too allow warnings like 113 + http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need + to explicitly say response is over 24 hours old. + """ + return '110 - "Response is Stale"' + + def update_headers(self, response): + """Update the response headers with any new headers. + + NOTE: This SHOULD always include some Warning header to + signify that the response was cached by the client, not + by way of the provided headers. + """ + return {} + + def apply(self, response): + updated_headers = self.update_headers(response) + + if updated_headers: + response.headers.update(updated_headers) + warning_header_value = self.warning(response) + if warning_header_value is not None: + response.headers.update({"Warning": warning_header_value}) + + return response + + +class OneDayCache(BaseHeuristic): + """ + Cache the response by providing an expires 1 day in the + future. + """ + + def update_headers(self, response): + headers = {} + + if "expires" not in response.headers: + date = parsedate(response.headers["date"]) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) + headers["expires"] = datetime_to_header(expires) + headers["cache-control"] = "public" + return headers + + +class ExpiresAfter(BaseHeuristic): + """ + Cache **all** requests for a defined time period. + """ + + def __init__(self, **kw): + self.delta = timedelta(**kw) + + def update_headers(self, response): + expires = expire_after(self.delta) + return {"expires": datetime_to_header(expires), "cache-control": "public"} + + def warning(self, response): + tmpl = "110 - Automatically cached for %s. Response might be stale" + return tmpl % self.delta + + +class LastModified(BaseHeuristic): + """ + If there is no Expires header already, fall back on Last-Modified + using the heuristic from + http://tools.ietf.org/html/rfc7234#section-4.2.2 + to calculate a reasonable value. + + Firefox also does something like this per + https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ + http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 + Unlike mozilla we limit this to 24-hr. + """ + cacheable_by_default_statuses = { + 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 + } + + def update_headers(self, resp): + headers = resp.headers + + if "expires" in headers: + return {} + + if "cache-control" in headers and headers["cache-control"] != "public": + return {} + + if resp.status not in self.cacheable_by_default_statuses: + return {} + + if "date" not in headers or "last-modified" not in headers: + return {} + + date = calendar.timegm(parsedate_tz(headers["date"])) + last_modified = parsedate(headers["last-modified"]) + if date is None or last_modified is None: + return {} + + now = time.time() + current_age = max(0, now - date) + delta = date - calendar.timegm(last_modified) + freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) + if freshness_lifetime <= current_age: + return {} + + expires = date + freshness_lifetime + return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} + + def warning(self, resp): + return None diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py new file mode 100644 index 0000000..ec43ff2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py @@ -0,0 +1,186 @@ +import base64 +import io +import json +import zlib + +from pip._vendor import msgpack +from pip._vendor.requests.structures import CaseInsensitiveDict + +from .compat import HTTPResponse, pickle, text_type + + +def _b64_decode_bytes(b): + return base64.b64decode(b.encode("ascii")) + + +def _b64_decode_str(s): + return _b64_decode_bytes(s).decode("utf8") + + +class Serializer(object): + + def dumps(self, request, response, body=None): + response_headers = CaseInsensitiveDict(response.headers) + + if body is None: + body = response.read(decode_content=False) + + # NOTE: 99% sure this is dead code. I'm only leaving it + # here b/c I don't have a test yet to prove + # it. Basically, before using + # `cachecontrol.filewrapper.CallbackFileWrapper`, + # this made an effort to reset the file handle. The + # `CallbackFileWrapper` short circuits this code by + # setting the body as the content is consumed, the + # result being a `body` argument is *always* passed + # into cache_response, and in turn, + # `Serializer.dump`. + response._fp = io.BytesIO(body) + + # NOTE: This is all a bit weird, but it's really important that on + # Python 2.x these objects are unicode and not str, even when + # they contain only ascii. The problem here is that msgpack + # understands the difference between unicode and bytes and we + # have it set to differentiate between them, however Python 2 + # doesn't know the difference. Forcing these to unicode will be + # enough to have msgpack know the difference. + data = { + u"response": { + u"body": body, + u"headers": dict( + (text_type(k), text_type(v)) for k, v in response.headers.items() + ), + u"status": response.status, + u"version": response.version, + u"reason": text_type(response.reason), + u"strict": response.strict, + u"decode_content": response.decode_content, + } + } + + # Construct our vary headers + data[u"vary"] = {} + if u"vary" in response_headers: + varied_headers = response_headers[u"vary"].split(",") + for header in varied_headers: + header = text_type(header).strip() + header_value = request.headers.get(header, None) + if header_value is not None: + header_value = text_type(header_value) + data[u"vary"][header] = header_value + + return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) + + def loads(self, request, data): + # Short circuit if we've been given an empty set of data + if not data: + return + + # Determine what version of the serializer the data was serialized + # with + try: + ver, data = data.split(b",", 1) + except ValueError: + ver = b"cc=0" + + # Make sure that our "ver" is actually a version and isn't a false + # positive from a , being in the data stream. + if ver[:3] != b"cc=": + data = ver + data + ver = b"cc=0" + + # Get the version number out of the cc=N + ver = ver.split(b"=", 1)[-1].decode("ascii") + + # Dispatch to the actual load method for the given version + try: + return getattr(self, "_loads_v{}".format(ver))(request, data) + + except AttributeError: + # This is a version we don't have a loads function for, so we'll + # just treat it as a miss and return None + return + + def prepare_response(self, request, cached): + """Verify our vary headers match and construct a real urllib3 + HTTPResponse object. + """ + # Special case the '*' Vary value as it means we cannot actually + # determine if the cached response is suitable for this request. + if "*" in cached.get("vary", {}): + return + + # Ensure that the Vary headers for the cached response match our + # request + for header, value in cached.get("vary", {}).items(): + if request.headers.get(header, None) != value: + return + + body_raw = cached["response"].pop("body") + + headers = CaseInsensitiveDict(data=cached["response"]["headers"]) + if headers.get("transfer-encoding", "") == "chunked": + headers.pop("transfer-encoding") + + cached["response"]["headers"] = headers + + try: + body = io.BytesIO(body_raw) + except TypeError: + # This can happen if cachecontrol serialized to v1 format (pickle) + # using Python 2. A Python 2 str(byte string) will be unpickled as + # a Python 3 str (unicode string), which will cause the above to + # fail with: + # + # TypeError: 'str' does not support the buffer interface + body = io.BytesIO(body_raw.encode("utf8")) + + return HTTPResponse(body=body, preload_content=False, **cached["response"]) + + def _loads_v0(self, request, data): + # The original legacy cache data. This doesn't contain enough + # information to construct everything we need, so we'll treat this as + # a miss. + return + + def _loads_v1(self, request, data): + try: + cached = pickle.loads(data) + except ValueError: + return + + return self.prepare_response(request, cached) + + def _loads_v2(self, request, data): + try: + cached = json.loads(zlib.decompress(data).decode("utf8")) + except (ValueError, zlib.error): + return + + # We need to decode the items that we've base64 encoded + cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) + cached["response"]["headers"] = dict( + (_b64_decode_str(k), _b64_decode_str(v)) + for k, v in cached["response"]["headers"].items() + ) + cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) + cached["vary"] = dict( + (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) + for k, v in cached["vary"].items() + ) + + return self.prepare_response(request, cached) + + def _loads_v3(self, request, data): + # Due to Python 2 encoding issues, it's impossible to know for sure + # exactly how to load v3 entries, thus we'll treat these as a miss so + # that they get rewritten out as v4 entries. + return + + def _loads_v4(self, request, data): + try: + cached = msgpack.loads(data, encoding="utf-8") + except ValueError: + return + + return self.prepare_response(request, cached) diff --git a/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py new file mode 100644 index 0000000..265bfc8 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py @@ -0,0 +1,29 @@ +from .adapter import CacheControlAdapter +from .cache import DictCache + + +def CacheControl( + sess, + cache=None, + cache_etags=True, + serializer=None, + heuristic=None, + controller_class=None, + adapter_class=None, + cacheable_methods=None, +): + + cache = cache or DictCache() + adapter_class = adapter_class or CacheControlAdapter + adapter = adapter_class( + cache, + cache_etags=cache_etags, + serializer=serializer, + heuristic=heuristic, + controller_class=controller_class, + cacheable_methods=cacheable_methods, + ) + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + return sess diff --git a/winvenv/Lib/site-packages/pip/_vendor/certifi/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/certifi/__init__.py new file mode 100644 index 0000000..aa329fb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/certifi/__init__.py @@ -0,0 +1,3 @@ +from .core import where, old_where + +__version__ = "2018.08.24" diff --git a/winvenv/Lib/site-packages/pip/_vendor/certifi/__main__.py b/winvenv/Lib/site-packages/pip/_vendor/certifi/__main__.py new file mode 100644 index 0000000..ae2aff5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/certifi/__main__.py @@ -0,0 +1,2 @@ +from pip._vendor.certifi import where +print(where()) diff --git a/winvenv/Lib/site-packages/pip/_vendor/certifi/cacert.pem b/winvenv/Lib/site-packages/pip/_vendor/certifi/cacert.pem new file mode 100644 index 0000000..85de024 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/certifi/cacert.pem @@ -0,0 +1,4300 @@ + +# 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=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Label: "GlobalSign Root CA - R2" +# Serial: 4835703278459682885658125 +# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 +# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe +# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 3 Public Primary Certification Authority - G3" +# Serial: 206684696279472310254277870180966723415 +# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 +# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 +# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----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=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Label: "AddTrust External Root" +# Serial: 1 +# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f +# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 +# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----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=GeoTrust Global CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. +# Label: "GeoTrust Global CA" +# Serial: 144470 +# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 +# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 +# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Label: "GeoTrust Universal CA" +# Serial: 1 +# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 +# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 +# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Universal CA 2" +# Serial: 1 +# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 +# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 +# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association +# Label: "Visa eCommerce Root" +# Serial: 25952180776285836048024890241505565794 +# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02 +# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62 +# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22 +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr +MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl +cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw +CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h +dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l +cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h +2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E +lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV +ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq +299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t +vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL +dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF +AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR +zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 +LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd +7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw +++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----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 Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Label: "QuoVadis Root CA" +# Serial: 985026699 +# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 +# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 +# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----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=Sonera Class2 CA O=Sonera +# Subject: CN=Sonera Class2 CA O=Sonera +# Label: "Sonera Class 2 Root CA" +# Serial: 29 +# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb +# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 +# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----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: O=Government Root Certification Authority +# Subject: O=Government Root Certification Authority +# Label: "Taiwan GRCA" +# Serial: 42023070807708724159991140556527066870 +# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e +# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 +# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----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=Class 2 Primary CA O=Certplus +# Subject: CN=Class 2 Primary CA O=Certplus +# Label: "Certplus Class 2 Primary CA" +# Serial: 177770208045934040241468760488327595043 +# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b +# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb +# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw +PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz +cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 +MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz +IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ +ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR +VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL +kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd +EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas +H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 +HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud +DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 +QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu +Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ +AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 +yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR +FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA +ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB +kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Label: "DST Root CA X3" +# Serial: 91299735575339953335919266965803778155 +# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 +# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 +# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----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----- +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 +-----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----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Label: "GeoTrust Primary Certification Authority" +# Serial: 32798226551256963324313806436981982369 +# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf +# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 +# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA" +# Serial: 69529181992039203566298953787712940909 +# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 +# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 +# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" +# Serial: 33037644167568058970164719475676101450 +# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c +# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 +# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----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=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Label: "Network Solutions Certificate Authority" +# Serial: 116697915152937497490437556386812487904 +# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e +# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce +# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----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=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GA CA" +# Serial: 86718877871133159090080555911823548314 +# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 +# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 +# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----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: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center +# Label: "Deutsche Telekom Root CA 2" +# Serial: 38 +# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08 +# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf +# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3 +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc +MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj +IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB +IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE +RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl +U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 +IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU +ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC +QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr +rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S +NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc +QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH +txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP +BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC +AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp +tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa +IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl +6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ +xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc +# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc +# Label: "Cybertrust Global Root" +# Serial: 4835703278459682877484360 +# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 +# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 +# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----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=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G3" +# Serial: 28809105769928564313984085209975885599 +# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 +# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd +# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G2" +# Serial: 71758320672825410020661621085256472406 +# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f +# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 +# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G3" +# Serial: 127614157056681299805556476275995414779 +# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 +# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 +# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G2" +# Serial: 80682863203381065782177908751794619243 +# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a +# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 +# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Universal Root Certification Authority" +# Serial: 85209574734084581917763752644031726877 +# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 +# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 +# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" +# Serial: 63143484348153506665311985501458640051 +# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 +# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a +# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----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=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G2" +# Serial: 10000012 +# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a +# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 +# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----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=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Label: "Chambers of Commerce Root - 2008" +# Serial: 11806822484801597146 +# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 +# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c +# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Label: "Global Chambersign Root - 2008" +# Serial: 14541511773111788494 +# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 +# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c +# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----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=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2011" +# Serial: 0 +# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 +# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d +# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----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: O=Trustis Limited OU=Trustis FPS Root CA +# Subject: O=Trustis Limited OU=Trustis FPS Root CA +# Label: "Trustis FPS Root CA" +# Serial: 36053640375399034304724988975563710553 +# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d +# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 +# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----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=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Label: "EE Certification Centre Root CA" +# Serial: 112324828676200291871926431888494945866 +# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f +# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 +# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----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 - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 14367148294922964480859022125800977897474 +# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e +# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb +# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----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=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G3" +# Serial: 10003001 +# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 +# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc +# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX +DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP +cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW +IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX +xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy +KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR +9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az +5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 +6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 +Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP +bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt +BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt +XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd +INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp +LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 +Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp +gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh +/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw +0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A +fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq +4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR +1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ +QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM +94B7IWcnMFk= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden EV Root CA" +# Serial: 10000013 +# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba +# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb +# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----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=Certinomis - Root CA O=Certinomis OU=0002 433998903 +# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903 +# Label: "Certinomis - Root CA" +# Serial: 1 +# MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f +# SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8 +# SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58 +-----BEGIN CERTIFICATE----- +MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET +MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb +BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz +MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx +FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g +Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 +fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl +LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV +WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF +TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb +5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc +CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri +wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ +wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG +m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 +F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng +WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 +2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF +AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ +0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw +F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS +g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj +qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN +h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ +ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V +btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj +Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ +8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW +gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= +-----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=LuxTrust Global Root 2 O=LuxTrust S.A. +# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A. +# Label: "LuxTrust Global Root 2" +# Serial: 59914338225734147123941058376788110305822489521 +# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c +# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f +# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5 +-----BEGIN CERTIFICATE----- +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 +-----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=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-1" +# Serial: 15752444095811006489 +# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45 +# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a +# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-2" +# Serial: 2711694510199101698 +# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64 +# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0 +# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor ECA-1" +# Serial: 9548242946988625984 +# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c +# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd +# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----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----- diff --git a/winvenv/Lib/site-packages/pip/_vendor/certifi/core.py b/winvenv/Lib/site-packages/pip/_vendor/certifi/core.py new file mode 100644 index 0000000..eab9d1d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/certifi/core.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem. +""" +import os +import warnings + + +class DeprecatedBundleWarning(DeprecationWarning): + """ + The weak security bundle is being deprecated. Please bother your service + provider to get them to stop using cross-signed roots. + """ + + +def where(): + f = os.path.dirname(__file__) + + return os.path.join(f, 'cacert.pem') + + +def old_where(): + warnings.warn( + "The weak security bundle has been removed. certifi.old_where() is now an alias " + "of certifi.where(). Please update your code to use certifi.where() instead. " + "certifi.old_where() will be removed in 2018.", + DeprecatedBundleWarning + ) + return where() + +if __name__ == '__main__': + print(where()) diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/__init__.py new file mode 100644 index 0000000..0f9f820 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/__init__.py @@ -0,0 +1,39 @@ +######################## BEGIN LICENSE BLOCK ######################## +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +from .compat import PY2, PY3 +from .universaldetector import UniversalDetector +from .version import __version__, VERSION + + +def detect(byte_str): + """ + Detect the encoding of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{0}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + detector = UniversalDetector() + detector.feed(byte_str) + return detector.close() diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/big5freq.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/big5freq.py new file mode 100644 index 0000000..38f3251 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/big5freq.py @@ -0,0 +1,386 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Big5 frequency table +# by Taiwan's Mandarin Promotion Council +# <http://www.edu.tw:81/mandr/> +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +BIG5_CHAR_TO_FREQ_ORDER = ( + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 +) + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/big5prober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/big5prober.py new file mode 100644 index 0000000..98f9970 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/big5prober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import Big5DistributionAnalysis +from .mbcssm import BIG5_SM_MODEL + + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + super(Big5Prober, self).__init__() + self.coding_sm = CodingStateMachine(BIG5_SM_MODEL) + self.distribution_analyzer = Big5DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "Big5" + + @property + def language(self): + return "Chinese" diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py new file mode 100644 index 0000000..c0395f4 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .euctwfreq import (EUCTW_CHAR_TO_FREQ_ORDER, EUCTW_TABLE_SIZE, + EUCTW_TYPICAL_DISTRIBUTION_RATIO) +from .euckrfreq import (EUCKR_CHAR_TO_FREQ_ORDER, EUCKR_TABLE_SIZE, + EUCKR_TYPICAL_DISTRIBUTION_RATIO) +from .gb2312freq import (GB2312_CHAR_TO_FREQ_ORDER, GB2312_TABLE_SIZE, + GB2312_TYPICAL_DISTRIBUTION_RATIO) +from .big5freq import (BIG5_CHAR_TO_FREQ_ORDER, BIG5_TABLE_SIZE, + BIG5_TYPICAL_DISTRIBUTION_RATIO) +from .jisfreq import (JIS_CHAR_TO_FREQ_ORDER, JIS_TABLE_SIZE, + JIS_TYPICAL_DISTRIBUTION_RATIO) + + +class CharDistributionAnalysis(object): + ENOUGH_DATA_THRESHOLD = 1024 + SURE_YES = 0.99 + SURE_NO = 0.01 + MINIMUM_DATA_THRESHOLD = 3 + + def __init__(self): + # Mapping table to get frequency order from char order (get from + # GetOrder()) + self._char_to_freq_order = None + self._table_size = None # Size of above table + # This is a constant value which varies from language to language, + # used in calculating confidence. See + # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html + # for further detail. + self.typical_distribution_ratio = None + self._done = None + self._total_chars = None + self._freq_chars = None + self.reset() + + def reset(self): + """reset analyser, clear any state""" + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + self._total_chars = 0 # Total characters encountered + # The number of characters whose frequency order is less than 512 + self._freq_chars = 0 + + def feed(self, char, char_len): + """feed a character with known length""" + if char_len == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(char) + else: + order = -1 + if order >= 0: + self._total_chars += 1 + # order is valid + if order < self._table_size: + if 512 > self._char_to_freq_order[order]: + self._freq_chars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, + # return negative answer + if self._total_chars <= 0 or self._freq_chars <= self.MINIMUM_DATA_THRESHOLD: + return self.SURE_NO + + if self._total_chars != self._freq_chars: + r = (self._freq_chars / ((self._total_chars - self._freq_chars) + * self.typical_distribution_ratio)) + if r < self.SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return self.SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. + # For charset detection, certain amount of data is enough + return self._total_chars > self.ENOUGH_DATA_THRESHOLD + + def get_order(self, byte_str): + # We do not handle characters based on the original encoding string, + # but convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency + # table. + return -1 + + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCTWDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCTW_CHAR_TO_FREQ_ORDER + self._table_size = EUCTW_TABLE_SIZE + self.typical_distribution_ratio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xC4: + return 94 * (first_char - 0xC4) + byte_str[1] - 0xA1 + else: + return -1 + + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCKRDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCKR_CHAR_TO_FREQ_ORDER + self._table_size = EUCKR_TABLE_SIZE + self.typical_distribution_ratio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xB0: + return 94 * (first_char - 0xB0) + byte_str[1] - 0xA1 + else: + return -1 + + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(GB2312DistributionAnalysis, self).__init__() + self._char_to_freq_order = GB2312_CHAR_TO_FREQ_ORDER + self._table_size = GB2312_TABLE_SIZE + self.typical_distribution_ratio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0xB0) and (second_char >= 0xA1): + return 94 * (first_char - 0xB0) + second_char - 0xA1 + else: + return -1 + + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(Big5DistributionAnalysis, self).__init__() + self._char_to_freq_order = BIG5_CHAR_TO_FREQ_ORDER + self._table_size = BIG5_TABLE_SIZE + self.typical_distribution_ratio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if first_char >= 0xA4: + if second_char >= 0xA1: + return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 + else: + return 157 * (first_char - 0xA4) + second_char - 0x40 + else: + return -1 + + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(SJISDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0x81) and (first_char <= 0x9F): + order = 188 * (first_char - 0x81) + elif (first_char >= 0xE0) and (first_char <= 0xEF): + order = 188 * (first_char - 0xE0 + 31) + else: + return -1 + order = order + second_char - 0x40 + if second_char > 0x7F: + order = -1 + return order + + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCJPDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + char = byte_str[0] + if char >= 0xA0: + return 94 * (char - 0xA1) + byte_str[1] - 0xa1 + else: + return -1 diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py new file mode 100644 index 0000000..8b3738e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py @@ -0,0 +1,106 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState +from .charsetprober import CharSetProber + + +class CharSetGroupProber(CharSetProber): + def __init__(self, lang_filter=None): + super(CharSetGroupProber, self).__init__(lang_filter=lang_filter) + self._active_num = 0 + self.probers = [] + self._best_guess_prober = None + + def reset(self): + super(CharSetGroupProber, self).reset() + self._active_num = 0 + for prober in self.probers: + if prober: + prober.reset() + prober.active = True + self._active_num += 1 + self._best_guess_prober = None + + @property + def charset_name(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.charset_name + + @property + def language(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.language + + def feed(self, byte_str): + for prober in self.probers: + if not prober: + continue + if not prober.active: + continue + state = prober.feed(byte_str) + if not state: + continue + if state == ProbingState.FOUND_IT: + self._best_guess_prober = prober + return self.state + elif state == ProbingState.NOT_ME: + prober.active = False + self._active_num -= 1 + if self._active_num <= 0: + self._state = ProbingState.NOT_ME + return self.state + return self.state + + def get_confidence(self): + state = self.state + if state == ProbingState.FOUND_IT: + return 0.99 + elif state == ProbingState.NOT_ME: + return 0.01 + best_conf = 0.0 + self._best_guess_prober = None + for prober in self.probers: + if not prober: + continue + if not prober.active: + self.logger.debug('%s not active', prober.charset_name) + continue + conf = prober.get_confidence() + self.logger.debug('%s %s confidence = %s', prober.charset_name, prober.language, conf) + if best_conf < conf: + best_conf = conf + self._best_guess_prober = prober + if not self._best_guess_prober: + return 0.0 + return best_conf diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py new file mode 100644 index 0000000..eac4e59 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging +import re + +from .enums import ProbingState + + +class CharSetProber(object): + + SHORTCUT_THRESHOLD = 0.95 + + def __init__(self, lang_filter=None): + self._state = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + + def reset(self): + self._state = ProbingState.DETECTING + + @property + def charset_name(self): + return None + + def feed(self, buf): + pass + + @property + def state(self): + return self._state + + def get_confidence(self): + return 0.0 + + @staticmethod + def filter_high_byte_only(buf): + buf = re.sub(b'([\x00-\x7F])+', b' ', buf) + return buf + + @staticmethod + def filter_international_words(buf): + """ + We define three types of bytes: + alphabet: english alphabets [a-zA-Z] + international: international characters [\x80-\xFF] + marker: everything else [^a-zA-Z\x80-\xFF] + + The input buffer can be thought to contain a series of words delimited + by markers. This function works to filter all words that contain at + least one international character. All contiguous sequences of markers + are replaced by a single space ascii character. + + This filter applies to all scripts which do not use English characters. + """ + filtered = bytearray() + + # This regex expression filters out only words that have at-least one + # international character. The word may include one marker character at + # the end. + words = re.findall(b'[a-zA-Z]*[\x80-\xFF]+[a-zA-Z]*[^a-zA-Z\x80-\xFF]?', + buf) + + for word in words: + filtered.extend(word[:-1]) + + # If the last character in the word is a marker, replace it with a + # space as markers shouldn't affect our analysis (they are used + # similarly across all languages and may thus have similar + # frequencies). + last_char = word[-1:] + if not last_char.isalpha() and last_char < b'\x80': + last_char = b' ' + filtered.extend(last_char) + + return filtered + + @staticmethod + def filter_with_english_letters(buf): + """ + Returns a copy of ``buf`` that retains only the sequences of English + alphabet and high byte characters that are not between <> characters. + Also retains English alphabet and high byte characters immediately + before occurrences of >. + + This filter can be applied to all scripts which contain both English + characters and extended ASCII characters, but is currently only used by + ``Latin1Prober``. + """ + filtered = bytearray() + in_tag = False + prev = 0 + + for curr in range(len(buf)): + # Slice here to get bytes instead of an int with Python 3 + buf_char = buf[curr:curr + 1] + # Check if we're coming out of or entering an HTML tag + if buf_char == b'>': + in_tag = False + elif buf_char == b'<': + in_tag = True + + # If current character is not extended-ASCII and not alphabetic... + if buf_char < b'\x80' and not buf_char.isalpha(): + # ...and we're not in a tag + if curr > prev and not in_tag: + # Keep everything after last non-extended-ASCII, + # non-alphabetic character + filtered.extend(buf[prev:curr]) + # Output a space to delimit stretch we kept + filtered.extend(b' ') + prev = curr + 1 + + # If we're not in a tag... + if not in_tag: + # Keep everything after last non-extended-ASCII, non-alphabetic + # character + filtered.extend(buf[prev:]) + + return filtered diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py new file mode 100644 index 0000000..c61136b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +""" +Script which takes one or more file paths and reports on their detected +encodings + +Example:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +If no paths are provided, it takes its input from stdin. + +""" + +from __future__ import absolute_import, print_function, unicode_literals + +import argparse +import sys + +from pip._vendor.chardet import __version__ +from pip._vendor.chardet.compat import PY2 +from pip._vendor.chardet.universaldetector import UniversalDetector + + +def description_of(lines, name='stdin'): + """ + Return a string describing the probable encoding of a file or + list of strings. + + :param lines: The lines to get the encoding of. + :type lines: Iterable of bytes + :param name: Name of file or collection of lines + :type name: str + """ + u = UniversalDetector() + for line in lines: + line = bytearray(line) + u.feed(line) + # shortcut out of the loop to save reading further - particularly useful if we read a BOM. + if u.done: + break + u.close() + result = u.result + if PY2: + name = name.decode(sys.getfilesystemencoding(), 'ignore') + if result['encoding']: + return '{0}: {1} with confidence {2}'.format(name, result['encoding'], + result['confidence']) + else: + return '{0}: no result'.format(name) + + +def main(argv=None): + """ + Handles command line arguments and gets things started. + + :param argv: List of arguments, as if specified on the command-line. + If None, ``sys.argv[1:]`` is used instead. + :type argv: list of str + """ + # Get command line arguments + parser = argparse.ArgumentParser( + description="Takes one or more file paths and reports their detected \ + encodings") + parser.add_argument('input', + help='File whose encoding we would like to determine. \ + (default: stdin)', + type=argparse.FileType('rb'), nargs='*', + default=[sys.stdin if PY2 else sys.stdin.buffer]) + parser.add_argument('--version', action='version', + version='%(prog)s {0}'.format(__version__)) + args = parser.parse_args(argv) + + for f in args.input: + if f.isatty(): + print("You are running chardetect interactively. Press " + + "CTRL-D twice at the start of a blank line to signal the " + + "end of your input. If you want help, run chardetect " + + "--help\n", file=sys.stderr) + print(description_of(f, f.name)) + + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py new file mode 100644 index 0000000..68fba44 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py @@ -0,0 +1,88 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging + +from .enums import MachineState + + +class CodingStateMachine(object): + """ + A state machine to verify a byte sequence for a particular encoding. For + each byte the detector receives, it will feed that byte to every active + state machine available, one byte at a time. The state machine changes its + state based on its previous state and the byte it receives. There are 3 + states in a state machine that are of interest to an auto-detector: + + START state: This is the state to start with, or a legal byte sequence + (i.e. a valid code point) for character has been identified. + + ME state: This indicates that the state machine identified a byte sequence + that is specific to the charset it is designed for and that + there is no other possible encoding which can contain this byte + sequence. This will to lead to an immediate positive answer for + the detector. + + ERROR state: This indicates the state machine identified an illegal byte + sequence for that encoding. This will lead to an immediate + negative answer for this encoding. Detector will exclude this + encoding from consideration from here on. + """ + def __init__(self, sm): + self._model = sm + self._curr_byte_pos = 0 + self._curr_char_len = 0 + self._curr_state = None + self.logger = logging.getLogger(__name__) + self.reset() + + def reset(self): + self._curr_state = MachineState.START + + def next_state(self, c): + # for each byte we get its class + # if it is first byte, we also get byte length + byte_class = self._model['class_table'][c] + if self._curr_state == MachineState.START: + self._curr_byte_pos = 0 + self._curr_char_len = self._model['char_len_table'][byte_class] + # from byte's class and state_table, we get its next state + curr_state = (self._curr_state * self._model['class_factor'] + + byte_class) + self._curr_state = self._model['state_table'][curr_state] + self._curr_byte_pos += 1 + return self._curr_state + + def get_current_charlen(self): + return self._curr_char_len + + def get_coding_state_machine(self): + return self._model['name'] + + @property + def language(self): + return self._model['language'] diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/compat.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/compat.py new file mode 100644 index 0000000..ddd7468 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/compat.py @@ -0,0 +1,34 @@ +######################## BEGIN LICENSE BLOCK ######################## +# Contributor(s): +# Dan Blanchard +# Ian Cordasco +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys + + +if sys.version_info < (3, 0): + PY2 = True + PY3 = False + base_str = (str, unicode) + text_type = unicode +else: + PY2 = False + PY3 = True + base_str = (bytes, str) + text_type = str diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py new file mode 100644 index 0000000..efd793a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py @@ -0,0 +1,49 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .chardistribution import EUCKRDistributionAnalysis +from .codingstatemachine import CodingStateMachine +from .mbcharsetprober import MultiByteCharSetProber +from .mbcssm import CP949_SM_MODEL + + +class CP949Prober(MultiByteCharSetProber): + def __init__(self): + super(CP949Prober, self).__init__() + self.coding_sm = CodingStateMachine(CP949_SM_MODEL) + # NOTE: CP949 is a superset of EUC-KR, so the distribution should be + # not different. + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "CP949" + + @property + def language(self): + return "Korean" diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/enums.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/enums.py new file mode 100644 index 0000000..0451207 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/enums.py @@ -0,0 +1,76 @@ +""" +All of the Enums that are used throughout the chardet package. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + + +class InputState(object): + """ + This enum represents the different states a universal detector can be in. + """ + PURE_ASCII = 0 + ESC_ASCII = 1 + HIGH_BYTE = 2 + + +class LanguageFilter(object): + """ + This enum represents the different language filters we can apply to a + ``UniversalDetector``. + """ + CHINESE_SIMPLIFIED = 0x01 + CHINESE_TRADITIONAL = 0x02 + JAPANESE = 0x04 + KOREAN = 0x08 + NON_CJK = 0x10 + ALL = 0x1F + CHINESE = CHINESE_SIMPLIFIED | CHINESE_TRADITIONAL + CJK = CHINESE | JAPANESE | KOREAN + + +class ProbingState(object): + """ + This enum represents the different states a prober can be in. + """ + DETECTING = 0 + FOUND_IT = 1 + NOT_ME = 2 + + +class MachineState(object): + """ + This enum represents the different states a state machine can be in. + """ + START = 0 + ERROR = 1 + ITS_ME = 2 + + +class SequenceLikelihood(object): + """ + This enum represents the likelihood of a character following the previous one. + """ + NEGATIVE = 0 + UNLIKELY = 1 + LIKELY = 2 + POSITIVE = 3 + + @classmethod + def get_num_categories(cls): + """:returns: The number of likelihood categories in the enum.""" + return 4 + + +class CharacterCategory(object): + """ + This enum represents the different categories language models for + ``SingleByteCharsetProber`` put characters into. + + Anything less than CONTROL is considered a letter. + """ + UNDEFINED = 255 + LINE_BREAK = 254 + SYMBOL = 253 + DIGIT = 252 + CONTROL = 251 diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/escprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/escprober.py new file mode 100644 index 0000000..c70493f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/escprober.py @@ -0,0 +1,101 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .codingstatemachine import CodingStateMachine +from .enums import LanguageFilter, ProbingState, MachineState +from .escsm import (HZ_SM_MODEL, ISO2022CN_SM_MODEL, ISO2022JP_SM_MODEL, + ISO2022KR_SM_MODEL) + + +class EscCharSetProber(CharSetProber): + """ + This CharSetProber uses a "code scheme" approach for detecting encodings, + whereby easily recognizable escape or shift sequences are relied on to + identify these encodings. + """ + + def __init__(self, lang_filter=None): + super(EscCharSetProber, self).__init__(lang_filter=lang_filter) + self.coding_sm = [] + if self.lang_filter & LanguageFilter.CHINESE_SIMPLIFIED: + self.coding_sm.append(CodingStateMachine(HZ_SM_MODEL)) + self.coding_sm.append(CodingStateMachine(ISO2022CN_SM_MODEL)) + if self.lang_filter & LanguageFilter.JAPANESE: + self.coding_sm.append(CodingStateMachine(ISO2022JP_SM_MODEL)) + if self.lang_filter & LanguageFilter.KOREAN: + self.coding_sm.append(CodingStateMachine(ISO2022KR_SM_MODEL)) + self.active_sm_count = None + self._detected_charset = None + self._detected_language = None + self._state = None + self.reset() + + def reset(self): + super(EscCharSetProber, self).reset() + for coding_sm in self.coding_sm: + if not coding_sm: + continue + coding_sm.active = True + coding_sm.reset() + self.active_sm_count = len(self.coding_sm) + self._detected_charset = None + self._detected_language = None + + @property + def charset_name(self): + return self._detected_charset + + @property + def language(self): + return self._detected_language + + def get_confidence(self): + if self._detected_charset: + return 0.99 + else: + return 0.00 + + def feed(self, byte_str): + for c in byte_str: + for coding_sm in self.coding_sm: + if not coding_sm or not coding_sm.active: + continue + coding_state = coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + coding_sm.active = False + self.active_sm_count -= 1 + if self.active_sm_count <= 0: + self._state = ProbingState.NOT_ME + return self.state + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + self._detected_charset = coding_sm.get_coding_state_machine() + self._detected_language = coding_sm.language + return self.state + + return self.state diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/escsm.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/escsm.py new file mode 100644 index 0000000..0069523 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/escsm.py @@ -0,0 +1,246 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +HZ_CLS = ( +1,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,0,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,4,0,5,2,0, # 78 - 7f +1,1,1,1,1,1,1,1, # 80 - 87 +1,1,1,1,1,1,1,1, # 88 - 8f +1,1,1,1,1,1,1,1, # 90 - 97 +1,1,1,1,1,1,1,1, # 98 - 9f +1,1,1,1,1,1,1,1, # a0 - a7 +1,1,1,1,1,1,1,1, # a8 - af +1,1,1,1,1,1,1,1, # b0 - b7 +1,1,1,1,1,1,1,1, # b8 - bf +1,1,1,1,1,1,1,1, # c0 - c7 +1,1,1,1,1,1,1,1, # c8 - cf +1,1,1,1,1,1,1,1, # d0 - d7 +1,1,1,1,1,1,1,1, # d8 - df +1,1,1,1,1,1,1,1, # e0 - e7 +1,1,1,1,1,1,1,1, # e8 - ef +1,1,1,1,1,1,1,1, # f0 - f7 +1,1,1,1,1,1,1,1, # f8 - ff +) + +HZ_ST = ( +MachineState.START,MachineState.ERROR, 3,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START, 4,MachineState.ERROR,# 10-17 + 5,MachineState.ERROR, 6,MachineState.ERROR, 5, 5, 4,MachineState.ERROR,# 18-1f + 4,MachineState.ERROR, 4, 4, 4,MachineState.ERROR, 4,MachineState.ERROR,# 20-27 + 4,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 28-2f +) + +HZ_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +HZ_SM_MODEL = {'class_table': HZ_CLS, + 'class_factor': 6, + 'state_table': HZ_ST, + 'char_len_table': HZ_CHAR_LEN_TABLE, + 'name': "HZ-GB-2312", + 'language': 'Chinese'} + +ISO2022CN_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,3,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,4,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022CN_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 20-27 + 5, 6,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,# 38-3f +) + +ISO2022CN_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022CN_SM_MODEL = {'class_table': ISO2022CN_CLS, + 'class_factor': 9, + 'state_table': ISO2022CN_ST, + 'char_len_table': ISO2022CN_CHAR_LEN_TABLE, + 'name': "ISO-2022-CN", + 'language': 'Chinese'} + +ISO2022JP_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,2,2, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,7,0,0,0, # 20 - 27 +3,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +6,0,4,0,8,0,0,0, # 40 - 47 +0,9,5,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022JP_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 20-27 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 6,MachineState.ITS_ME,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 38-3f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.START,# 40-47 +) + +ISO2022JP_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022JP_SM_MODEL = {'class_table': ISO2022JP_CLS, + 'class_factor': 10, + 'state_table': ISO2022JP_ST, + 'char_len_table': ISO2022JP_CHAR_LEN_TABLE, + 'name': "ISO-2022-JP", + 'language': 'Japanese'} + +ISO2022KR_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,3,0,0,0, # 20 - 27 +0,4,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,5,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022KR_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 10-17 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 20-27 +) + +ISO2022KR_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +ISO2022KR_SM_MODEL = {'class_table': ISO2022KR_CLS, + 'class_factor': 6, + 'state_table': ISO2022KR_ST, + 'char_len_table': ISO2022KR_CHAR_LEN_TABLE, + 'name': "ISO-2022-KR", + 'language': 'Korean'} + + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py new file mode 100644 index 0000000..20ce8f7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState, MachineState +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCJPDistributionAnalysis +from .jpcntx import EUCJPContextAnalysis +from .mbcssm import EUCJP_SM_MODEL + + +class EUCJPProber(MultiByteCharSetProber): + def __init__(self): + super(EUCJPProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCJP_SM_MODEL) + self.distribution_analyzer = EUCJPDistributionAnalysis() + self.context_analyzer = EUCJPContextAnalysis() + self.reset() + + def reset(self): + super(EUCJPProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return "EUC-JP" + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + # PY3K: byte_str is a byte array, so byte_str[i] is an int, not a byte + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char, char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py new file mode 100644 index 0000000..b68078c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py @@ -0,0 +1,195 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKR_CHAR_TO_FREQ_ORDER = ( + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +) + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py new file mode 100644 index 0000000..345a060 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import EUCKR_SM_MODEL + + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + super(EUCKRProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCKR_SM_MODEL) + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-KR" + + @property + def language(self): + return "Korean" diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py new file mode 100644 index 0000000..ed7a995 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py @@ -0,0 +1,387 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# <http:#www.edu.tw:81/mandr/> + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 5376 + +EUCTW_CHAR_TO_FREQ_ORDER = ( + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +) + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py new file mode 100644 index 0000000..35669cc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCTWDistributionAnalysis +from .mbcssm import EUCTW_SM_MODEL + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + super(EUCTWProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCTW_SM_MODEL) + self.distribution_analyzer = EUCTWDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-TW" + + @property + def language(self): + return "Taiwan" diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py new file mode 100644 index 0000000..697837b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py @@ -0,0 +1,283 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312_CHAR_TO_FREQ_ORDER = ( +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, #last 512 +) + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py new file mode 100644 index 0000000..8446d2d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import GB2312DistributionAnalysis +from .mbcssm import GB2312_SM_MODEL + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + super(GB2312Prober, self).__init__() + self.coding_sm = CodingStateMachine(GB2312_SM_MODEL) + self.distribution_analyzer = GB2312DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "GB2312" + + @property + def language(self): + return "Chinese" diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py new file mode 100644 index 0000000..b0e1bf4 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py @@ -0,0 +1,292 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +class HebrewProber(CharSetProber): + # windows-1255 / ISO-8859-8 code points of interest + FINAL_KAF = 0xea + NORMAL_KAF = 0xeb + FINAL_MEM = 0xed + NORMAL_MEM = 0xee + FINAL_NUN = 0xef + NORMAL_NUN = 0xf0 + FINAL_PE = 0xf3 + NORMAL_PE = 0xf4 + FINAL_TSADI = 0xf5 + NORMAL_TSADI = 0xf6 + + # Minimum Visual vs Logical final letter score difference. + # If the difference is below this, don't rely solely on the final letter score + # distance. + MIN_FINAL_CHAR_DISTANCE = 5 + + # Minimum Visual vs Logical model score difference. + # If the difference is below this, don't rely at all on the model score + # distance. + MIN_MODEL_DISTANCE = 0.01 + + VISUAL_HEBREW_NAME = "ISO-8859-8" + LOGICAL_HEBREW_NAME = "windows-1255" + + def __init__(self): + super(HebrewProber, self).__init__() + self._final_char_logical_score = None + self._final_char_visual_score = None + self._prev = None + self._before_prev = None + self._logical_prober = None + self._visual_prober = None + self.reset() + + def reset(self): + self._final_char_logical_score = 0 + self._final_char_visual_score = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate + # a word delimiter at the beginning of the data + self._prev = ' ' + self._before_prev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._logical_prober = logicalProber + self._visual_prober = visualProber + + def is_final(self, c): + return c in [self.FINAL_KAF, self.FINAL_MEM, self.FINAL_NUN, + self.FINAL_PE, self.FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters + # causing the Non-Final tsadi to appear at an end of a word even + # though this is not the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being + # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' + # for example legally end with a Non-Final Pe or Kaf. However, the + # benefit of these letters as Non-Final letters outweighs the damage + # since these words are quite rare. + return c in [self.NORMAL_KAF, self.NORMAL_MEM, + self.NORMAL_NUN, self.NORMAL_PE] + + def feed(self, byte_str): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew + # or visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is + # an indication that the text is laid out "naturally" since the + # final letter really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In + # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, + # should not end with the Non-Final form of that letter. Exceptions + # to this rule are mentioned above in isNonFinal(). This is an + # indication that the text is laid out backwards. +1 for visual + # score + # 3) A word longer than 1 letter, starting with a final letter. Final + # letters should not appear at the beginning of a word. This is an + # indication that the text is laid out backwards. +1 for visual + # score. + # + # The visual score and logical score are accumulated throughout the + # text and are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since + # that case is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with + # spaces) so the word boundary detection works properly. [MAP] + + if self.state == ProbingState.NOT_ME: + # Both model probers say it's not them. No reason to continue. + return ProbingState.NOT_ME + + byte_str = self.filter_high_byte_only(byte_str) + + for cur in byte_str: + if cur == ' ': + # We stand on a space - a word just ended + if self._before_prev != ' ': + # next-to-last char was not a space so self._prev is not a + # 1 letter word + if self.is_final(self._prev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._final_char_logical_score += 1 + elif self.is_non_final(self._prev): + # case (2) [-2:not space][-1:Non-Final letter][ + # cur:space] + self._final_char_visual_score += 1 + else: + # Not standing on a space + if ((self._before_prev == ' ') and + (self.is_final(self._prev)) and (cur != ' ')): + # case (3) [-2:space][-1:final letter][cur:not space] + self._final_char_visual_score += 1 + self._before_prev = self._prev + self._prev = cur + + # Forever detecting, till the end or until both model probers return + # ProbingState.NOT_ME (handled above) + return ProbingState.DETECTING + + @property + def charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._final_char_logical_score - self._final_char_visual_score + if finalsub >= self.MIN_FINAL_CHAR_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if finalsub <= -self.MIN_FINAL_CHAR_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = (self._logical_prober.get_confidence() + - self._visual_prober.get_confidence()) + if modelsub > self.MIN_MODEL_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if modelsub < -self.MIN_MODEL_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the + # day. + if finalsub < 0.0: + return self.VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to + # Logical. + return self.LOGICAL_HEBREW_NAME + + @property + def language(self): + return 'Hebrew' + + @property + def state(self): + # Remain active as long as any of the model probers are active. + if (self._logical_prober.state == ProbingState.NOT_ME) and \ + (self._visual_prober.state == ProbingState.NOT_ME): + return ProbingState.NOT_ME + return ProbingState.DETECTING diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py new file mode 100644 index 0000000..83fc082 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py @@ -0,0 +1,325 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JIS_CHAR_TO_FREQ_ORDER = ( + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +) + + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py new file mode 100644 index 0000000..20044e4 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( +(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis(object): + NUM_OF_CATEGORY = 6 + DONT_KNOW = -1 + ENOUGH_REL_THRESHOLD = 100 + MAX_REL_THRESHOLD = 1000 + MINIMUM_DATA_THRESHOLD = 4 + + def __init__(self): + self._total_rel = None + self._rel_sample = None + self._need_to_skip_char_num = None + self._last_char_order = None + self._done = None + self.reset() + + def reset(self): + self._total_rel = 0 # total sequence received + # category counters, each integer counts sequence in its category + self._rel_sample = [0] * self.NUM_OF_CATEGORY + # if last byte in current buffer is not the last byte of a character, + # we need to know how many bytes to skip in next buffer + self._need_to_skip_char_num = 0 + self._last_char_order = -1 # The order of previous char + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + + def feed(self, byte_str, num_bytes): + if self._done: + return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not + # complete, we record how many byte needed to complete that character + # and skip these bytes here. We can choose to record those bytes as + # well and analyse the character once it is complete, but since a + # character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._need_to_skip_char_num + while i < num_bytes: + order, char_len = self.get_order(byte_str[i:i + 2]) + i += char_len + if i > num_bytes: + self._need_to_skip_char_num = i - num_bytes + self._last_char_order = -1 + else: + if (order != -1) and (self._last_char_order != -1): + self._total_rel += 1 + if self._total_rel > self.MAX_REL_THRESHOLD: + self._done = True + break + self._rel_sample[jp2CharContext[self._last_char_order][order]] += 1 + self._last_char_order = order + + def got_enough_data(self): + return self._total_rel > self.ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._total_rel > self.MINIMUM_DATA_THRESHOLD: + return (self._total_rel - self._rel_sample[0]) / self._total_rel + else: + return self.DONT_KNOW + + def get_order(self, byte_str): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def __init__(self): + super(SJISContextAnalysis, self).__init__() + self._charset_name = "SHIFT_JIS" + + @property + def charset_name(self): + return self._charset_name + + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC): + char_len = 2 + if (first_char == 0x87) or (0xFA <= first_char <= 0xFC): + self._charset_name = "CP932" + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 202) and (0x9F <= second_char <= 0xF1): + return second_char - 0x9F, char_len + + return -1, char_len + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): + char_len = 2 + elif first_char == 0x8F: + char_len = 3 + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): + return second_char - 0xA1, char_len + + return -1, char_len + + diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py new file mode 100644 index 0000000..2aa4fb2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py @@ -0,0 +1,228 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +# this table is modified base on win1251BulgarianCharToOrderMap, so +# only number <64 is sure valid + +Latin5_BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 +210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 + 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 + 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 +) + +win1251BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 +221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 + 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 + 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 96.9392% +# first 1024 sequences:3.0618% +# rest sequences: 0.2992% +# negative sequences: 0.0020% +BulgarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, +3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, +0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, +0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, +0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, +0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, +2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, +3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, +1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, +3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, +1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, +2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, +2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, +3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, +1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, +2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, +2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, +1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, +2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, +2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, +2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, +1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, +2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, +1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, +3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, +1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, +3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, +1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, +2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, +1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, +2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, +1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, +2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, +1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, +2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, +1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, +0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, +1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, +1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, +1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, +0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, +1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, +1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +) + +Latin5BulgarianModel = { + 'char_to_order_map': Latin5_BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Bulgairan', +} + +Win1251BulgarianModel = { + 'char_to_order_map': win1251BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Bulgarian', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langcyrillicmodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langcyrillicmodel.py new file mode 100644 index 0000000..e5f9a1f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langcyrillicmodel.py @@ -0,0 +1,333 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# KOI8-R language model +# Character Mapping Table: +KOI8R_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 +223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 + 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 + 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 + 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 + 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 +) + +win1251_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +) + +latin5_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +macCyrillic_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, +) + +IBM855_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, +206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, + 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, +220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, +230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, + 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, + 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, +250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, +) + +IBM866_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 97.6601% +# first 1024 sequences: 2.3389% +# rest sequences: 0.1237% +# negative sequences: 0.0009% +RussianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, +1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, +1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, +2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, +1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, +3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, +1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, +2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, +1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, +1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, +1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, +1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, +3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, +1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, +2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, +1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, +2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, +1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, +1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, +1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, +3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, +3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, +1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, +1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, +0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, +1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, +1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, +0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, +1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, +2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, +1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, +1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, +2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, +1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, +1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, +0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, +0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, +2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, +0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +) + +Koi8rModel = { + 'char_to_order_map': KOI8R_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "KOI8-R", + 'language': 'Russian', +} + +Win1251CyrillicModel = { + 'char_to_order_map': win1251_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Russian', +} + +Latin5CyrillicModel = { + 'char_to_order_map': latin5_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Russian', +} + +MacCyrillicModel = { + 'char_to_order_map': macCyrillic_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "MacCyrillic", + 'language': 'Russian', +} + +Ibm866Model = { + 'char_to_order_map': IBM866_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM866", + 'language': 'Russian', +} + +Ibm855Model = { + 'char_to_order_map': IBM855_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM855", + 'language': 'Russian', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py new file mode 100644 index 0000000..5332221 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin7_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +win1253_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.2851% +# first 1024 sequences:1.7001% +# rest sequences: 0.0359% +# negative sequences: 0.0148% +GreekLangModel = ( +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, +2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, +2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, +2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, +0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, +3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, +2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, +0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, +0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, +0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, +0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, +0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, +0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, +0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, +0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, +0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, +0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, +0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, +0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, +0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, +0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, +0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, +0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, +0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin7GreekModel = { + 'char_to_order_map': Latin7_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-7", + 'language': 'Greek', +} + +Win1253GreekModel = { + 'char_to_order_map': win1253_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "windows-1253", + 'language': 'Greek', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py new file mode 100644 index 0000000..58f4c87 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Simon Montagu +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Shoshannah Forbes - original C code (?) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Windows-1255 language model +# Character Mapping Table: +WIN1255_CHAR_TO_ORDER_MAP = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 + 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 +253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 + 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 +124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, +215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, + 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, +106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, + 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, +238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, + 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, + 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.4004% +# first 1024 sequences: 1.5981% +# rest sequences: 0.087% +# negative sequences: 0.0015% +HEBREW_LANG_MODEL = ( +0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, +3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, +1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, +1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, +1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, +1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, +0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, +0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, +0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, +0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, +0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, +0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, +0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, +0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, +0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, +0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, +0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, +0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, +0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, +1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, +1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, +2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, +0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, +) + +Win1255HebrewModel = { + 'char_to_order_map': WIN1255_CHAR_TO_ORDER_MAP, + 'precedence_matrix': HEBREW_LANG_MODEL, + 'typical_positive_ratio': 0.984004, + 'keep_english_letter': False, + 'charset_name': "windows-1255", + 'language': 'Hebrew', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py new file mode 100644 index 0000000..bb7c095 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin2_HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, + 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, + 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, +245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +win1250HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, +177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, + 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, + 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, +245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 94.7368% +# first 1024 sequences:5.2623% +# rest sequences: 0.8894% +# negative sequences: 0.0009% +HungarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, +3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, +0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, +1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, +1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, +3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, +2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, +2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, +2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, +2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, +1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, +1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, +3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, +1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, +1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, +2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, +2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, +2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, +3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, +1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, +1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, +1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, +2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, +1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, +2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, +2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, +1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, +1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, +0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, +2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, +2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, +1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, +1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, +2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, +2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, +2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, +1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, +0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +) + +Latin2HungarianModel = { + 'char_to_order_map': Latin2_HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-2", + 'language': 'Hungarian', +} + +Win1250HungarianModel = { + 'char_to_order_map': win1250HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "windows-1250", + 'language': 'Hungarian', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py new file mode 100644 index 0000000..15f94c2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py @@ -0,0 +1,199 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# The following result for thai was collected from a limited sample (1M). + +# Character Mapping Table: +TIS620CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 +188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 +253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 + 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 +209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, +223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, +236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, + 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, + 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, + 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, + 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, + 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 92.6386% +# first 1024 sequences:7.3177% +# rest sequences: 1.0230% +# negative sequences: 0.0436% +ThaiLangModel = ( +0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, +0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, +3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, +0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, +3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, +3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, +3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, +3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, +2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, +3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, +1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, +3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, +1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, +0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, +0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, +2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, +0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, +3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, +2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, +2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, +3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, +3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, +3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, +3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, +1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, +0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, +0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, +3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, +3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, +1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, +3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, +3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, +0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, +0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, +1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, +1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, +3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, +0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, +3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, +0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, +0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, +0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, +0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, +0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, +0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, +0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, +3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, +2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, +0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, +3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, +1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, +1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +TIS620ThaiModel = { + 'char_to_order_map': TIS620CharToOrderMap, + 'precedence_matrix': ThaiLangModel, + 'typical_positive_ratio': 0.926386, + 'keep_english_letter': False, + 'charset_name': "TIS-620", + 'language': 'Thai', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py new file mode 100644 index 0000000..a427a45 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Özgür Baskın - Turkish Language Model +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin5_TurkishCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255, 23, 37, 47, 39, 29, 52, 36, 45, 53, 60, 16, 49, 20, 46, 42, + 48, 69, 44, 35, 31, 51, 38, 62, 65, 43, 56,255,255,255,255,255, +255, 1, 21, 28, 12, 2, 18, 27, 25, 3, 24, 10, 5, 13, 4, 15, + 26, 64, 7, 8, 9, 14, 32, 57, 58, 11, 22,255,255,255,255,255, +180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165, +164,163,162,161,160,159,101,158,157,156,155,154,153,152,151,106, +150,149,148,147,146,145,144,100,143,142,141,140,139,138,137,136, + 94, 80, 93,135,105,134,133, 63,132,131,130,129,128,127,126,125, +124,104, 73, 99, 79, 85,123, 54,122, 98, 92,121,120, 91,103,119, + 68,118,117, 97,116,115, 50, 90,114,113,112,111, 55, 41, 40, 86, + 89, 70, 59, 78, 71, 82, 88, 33, 77, 66, 84, 83,110, 75, 61, 96, + 30, 67,109, 74, 87,102, 34, 95, 81,108, 76, 72, 17, 6, 19,107, +) + +TurkishLangModel = ( +3,2,3,3,3,1,3,3,3,3,3,3,3,3,2,1,1,3,3,1,3,3,0,3,3,3,3,3,0,3,1,3, +3,2,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,3,1,0,3,3,1,3,3,0,3,3,3,3,3,0,3,0,3, +3,1,1,0,1,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,0,1,0,1, +3,3,2,3,3,0,3,3,3,3,3,3,3,2,3,1,1,3,3,0,3,3,1,2,3,3,3,3,0,3,0,3, +3,1,1,0,0,0,1,0,0,0,0,1,1,0,1,2,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,1, +3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,1,3,3,2,0,3,2,1,2,2,1,3,3,0,0,0,2, +2,2,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1, +3,3,3,2,3,3,1,2,3,3,3,3,3,3,3,1,3,2,1,0,3,2,0,1,2,3,3,2,1,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0, +1,0,1,3,3,1,3,3,3,3,3,3,3,1,2,0,0,2,3,0,2,3,0,0,2,2,2,3,0,3,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,0,3,2,0,2,3,2,3,3,1,0,0,2, +3,2,0,0,1,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,2,0,0,1, +3,3,3,2,3,3,2,3,3,3,3,2,3,3,3,0,3,3,0,0,2,1,0,0,2,3,2,2,0,0,0,2, +2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,2,0,0,1, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,0,1,3,2,1,1,3,2,3,2,1,0,0,2, +2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,2,0,2,3,0,0,2,2,2,2,0,0,0,2, +3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,3,3,3,3,2,2,2,2,3,2,3,3,0,3,3,1,1,2,2,0,0,2,2,3,2,0,0,1,3, +0,3,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1, +3,3,3,2,3,3,3,2,1,2,2,3,2,3,3,0,3,2,0,0,1,1,0,1,1,2,1,2,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0, +3,3,3,2,3,3,2,3,2,2,2,3,3,3,3,1,3,1,1,0,3,2,1,1,3,3,2,3,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,2,1,0,3,3,1,3,3,0,1,3,3,2,3,0,3,0,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +2,2,2,3,3,0,3,3,3,3,3,3,3,3,3,0,0,3,2,0,3,3,0,3,2,3,3,3,0,3,1,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,1,2,0,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,3,3,1,2,3,3,1,0,0,1,0,0,3,3,2,3,0,0,2,0,0,2,0,2,0,0,0,2,0,2,0, +0,3,1,0,1,0,0,0,2,2,1,0,1,1,2,1,2,2,2,0,2,1,1,0,0,0,2,0,0,0,0,0, +1,2,1,3,3,0,3,3,3,3,3,2,3,0,0,0,0,2,3,0,2,3,1,0,2,3,1,3,0,3,0,2, +3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,3,2,2,3,2,2,0,1,2,3,0,1,2,1,0,1,0,0,0,1,0,2,2,0,0,0,1, +1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0, +3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,0,2,1,2,0,2,1,0,0,1,1,2,1,0,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,0,2,1,3,0,0,2,0,0,3,3,0,3,0,0,1,0,1,2,0,0,1,1,2,2,0,1,0, +0,1,2,1,1,0,1,0,1,1,1,1,1,0,1,1,1,2,2,1,2,0,1,0,0,0,0,0,0,1,0,0, +3,3,3,2,3,2,3,3,0,2,2,2,3,3,3,0,3,0,0,0,2,2,0,1,2,1,1,1,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +3,3,3,3,3,3,2,1,2,2,3,3,3,3,2,0,2,0,0,0,2,2,0,0,2,1,3,3,0,0,1,1, +1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0, +1,1,2,3,3,0,3,3,3,3,3,3,2,2,0,2,0,2,3,2,3,2,2,2,2,2,2,2,1,3,2,3, +2,0,2,1,2,2,2,2,1,1,2,2,1,2,2,1,2,0,0,2,1,1,0,2,1,0,0,1,0,0,0,1, +2,3,3,1,1,1,0,1,1,1,2,3,2,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,2,2,1,3,3,3,0,2,1,2,0,2,1,0,0,1,1,1,1,1,0,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,2,3,3,3,3,3,2,3,1,2,3,3,1,2,0,0,0,0,0,0,0,3,2,1,1,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +3,3,3,2,2,3,3,2,1,1,1,1,1,3,3,0,3,1,0,0,1,1,0,0,3,1,2,1,0,0,0,0, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, +3,3,3,2,2,3,2,2,2,3,2,1,1,3,3,0,3,0,0,0,0,1,0,0,3,1,1,2,0,0,0,1, +1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,3,3,0,3,3,3,3,3,2,2,2,1,2,0,2,1,2,2,1,1,0,1,2,2,2,2,2,2,2, +0,0,2,1,2,1,2,1,0,1,1,3,1,2,1,1,2,0,0,2,0,1,0,1,0,1,0,0,0,1,0,1, +3,3,3,1,3,3,3,0,1,1,0,2,2,3,1,0,3,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,2,2,1,0,0,1,0,0,3,3,1,3,0,0,1,1,0,2,0,3,0,0,0,2,0,1,1, +0,1,2,0,1,2,2,0,2,2,2,2,1,0,2,1,1,0,2,0,2,1,2,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,2,3,2,0,2,2,2,1,3,2,0,2,1,2,0,1,2,0,0,1,0,2,2,0,0,0,2, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0, +3,3,3,0,3,3,1,1,2,3,1,0,3,2,3,0,3,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0, +1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,3,3,2,3,3,2,2,0,0,0,0,1,2,0,1,3,0,0,0,3,1,1,0,3,0,2, +2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,2,2,1,0,3,1,1,1,1,3,3,2,3,0,0,1,0,1,2,0,2,2,0,2,2,0,2,1, +0,2,2,1,1,1,1,0,2,1,1,0,1,1,1,1,2,1,2,1,2,0,1,0,1,0,0,0,0,0,0,0, +3,3,3,0,1,1,3,0,0,1,1,0,0,2,2,0,3,0,0,1,1,0,1,0,0,0,0,0,2,0,0,0, +0,3,1,0,1,0,1,0,2,0,0,1,0,1,0,1,1,1,2,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,0,2,0,1,1,1,0,0,3,3,0,2,0,0,1,0,0,2,1,1,0,1,0,1,0,1,0, +0,2,0,1,2,0,2,0,2,1,1,0,1,0,2,1,1,0,2,1,1,0,1,0,0,0,1,1,0,0,0,0, +3,2,3,0,1,0,0,0,0,0,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,0,2,0,0,0, +0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,2,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,0,2,3,0,0,1,0,1,0,2,3,2,3,0,0,1,3,0,2,1,0,0,0,0,2,0,1,0, +0,2,1,0,0,1,1,0,2,1,0,0,1,0,0,1,1,0,1,1,2,0,1,0,0,0,0,1,0,0,0,0, +3,2,2,0,0,1,1,0,0,0,0,0,0,3,1,1,1,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0, +0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,2,3,2,2,1,2,2,1,1,2,0,1,3,2,2,2,0,0,2,2,0,0,0,1,2,1, +3,0,2,1,1,0,1,1,1,0,1,2,2,2,1,1,2,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0, +0,1,1,2,3,0,3,3,3,2,2,2,2,1,0,1,0,1,0,1,2,2,0,0,2,2,1,3,1,1,2,1, +0,0,1,1,2,0,1,1,0,0,1,2,0,2,1,1,2,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0, +3,3,2,0,0,3,1,0,0,0,0,0,0,3,2,1,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,2,1,1,0,0,1,0,1,2,0,0,1,1,0,0,2,1,1,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,1,0,0,0,0,1,0,0,3,3,2,2,0,0,1,0,0,2,0,1,0,0,0,2,0,1,0, +0,0,1,1,0,0,2,0,2,1,0,0,1,1,2,1,2,0,2,1,2,1,1,1,0,0,1,1,0,0,0,0, +3,3,2,0,0,2,2,0,0,0,1,1,0,2,2,1,3,1,0,1,0,1,2,0,0,0,0,0,1,0,1,0, +0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,0,0,0,1,0,0,1,0,0,2,3,1,2,0,0,1,0,0,2,0,0,0,1,0,2,0,2,0, +0,1,1,2,2,1,2,0,2,1,1,0,0,1,1,0,1,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,1,0,0,1,1,0,3,3,1,2,0,0,1,0,0,2,0,2,0,1,1,2,0,0,0, +0,0,1,1,1,1,2,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +3,3,3,0,2,2,3,2,0,0,1,0,0,2,3,1,0,0,0,0,0,0,2,0,2,0,0,0,2,0,0,0, +0,1,1,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,0,0,0,0,0,0,1,0,0,2,2,2,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,0,2,1,1,0,1,0,2,1,1,0,0,1,1,2,1,0,2,0,2,0,1,0,0,0,2,0,0,0,0,0, +0,0,0,2,2,0,2,1,1,1,1,2,2,0,0,1,0,1,0,0,1,3,0,0,0,0,1,0,0,2,1,0, +0,0,1,0,1,0,0,0,0,0,2,1,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +2,0,0,2,3,0,2,3,1,2,2,0,2,0,0,2,0,2,1,1,1,2,1,0,0,1,2,1,1,2,1,0, +1,0,2,0,1,0,1,1,0,0,2,2,1,2,1,1,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,0,0,0,1,0,0,3,2,0,1,0,0,1,0,0,2,0,0,0,1,2,1,0,1,0, +0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,2,2,0,2,2,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,0,1,0,0,0,1,1,1,1, +0,0,2,1,0,1,1,1,0,1,1,2,1,2,1,1,2,0,1,1,2,1,0,2,0,0,0,0,0,0,0,0, +3,2,2,0,0,2,0,0,0,0,0,0,0,2,2,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,0, +0,2,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,0,2,2,0,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0, +2,0,1,0,1,0,1,1,0,0,1,2,0,1,0,1,1,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0, +2,2,2,0,1,1,0,0,0,1,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,1,2,0,1,0, +0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,1,1,1,0,0,0,0,1,2,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +1,1,2,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,1, +0,0,1,2,2,0,2,1,2,1,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,2,2,0,0,0,1,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin5TurkishModel = { + 'char_to_order_map': Latin5_TurkishCharToOrderMap, + 'precedence_matrix': TurkishLangModel, + 'typical_positive_ratio': 0.970290, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-9", + 'language': 'Turkish', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py new file mode 100644 index 0000000..7d1e8c2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( +# UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + + +class Latin1Prober(CharSetProber): + def __init__(self): + super(Latin1Prober, self).__init__() + self._last_char_class = None + self._freq_counter = None + self.reset() + + def reset(self): + self._last_char_class = OTH + self._freq_counter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + @property + def charset_name(self): + return "ISO-8859-1" + + @property + def language(self): + return "" + + def feed(self, byte_str): + byte_str = self.filter_with_english_letters(byte_str) + for c in byte_str: + char_class = Latin1_CharToClass[c] + freq = Latin1ClassModel[(self._last_char_class * CLASS_NUM) + + char_class] + if freq == 0: + self._state = ProbingState.NOT_ME + break + self._freq_counter[freq] += 1 + self._last_char_class = char_class + + return self.state + + def get_confidence(self): + if self.state == ProbingState.NOT_ME: + return 0.01 + + total = sum(self._freq_counter) + if total < 0.01: + confidence = 0.0 + else: + confidence = ((self._freq_counter[3] - self._freq_counter[1] * 20.0) + / total) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate + # detector can take priority. + confidence = confidence * 0.73 + return confidence diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py new file mode 100644 index 0000000..6256ecf --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py @@ -0,0 +1,91 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState + + +class MultiByteCharSetProber(CharSetProber): + """ + MultiByteCharSetProber + """ + + def __init__(self, lang_filter=None): + super(MultiByteCharSetProber, self).__init__(lang_filter=lang_filter) + self.distribution_analyzer = None + self.coding_sm = None + self._last_char = [0, 0] + + def reset(self): + super(MultiByteCharSetProber, self).reset() + if self.coding_sm: + self.coding_sm.reset() + if self.distribution_analyzer: + self.distribution_analyzer.reset() + self._last_char = [0, 0] + + @property + def charset_name(self): + raise NotImplementedError + + @property + def language(self): + raise NotImplementedError + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.distribution_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + return self.distribution_analyzer.get_confidence() diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py new file mode 100644 index 0000000..530abe7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .utf8prober import UTF8Prober +from .sjisprober import SJISProber +from .eucjpprober import EUCJPProber +from .gb2312prober import GB2312Prober +from .euckrprober import EUCKRProber +from .cp949prober import CP949Prober +from .big5prober import Big5Prober +from .euctwprober import EUCTWProber + + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self, lang_filter=None): + super(MBCSGroupProber, self).__init__(lang_filter=lang_filter) + self.probers = [ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + CP949Prober(), + Big5Prober(), + EUCTWProber() + ] + self.reset() diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py new file mode 100644 index 0000000..8360d0f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py @@ -0,0 +1,572 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +# BIG5 + +BIG5_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +BIG5_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,#08-0f + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START#10-17 +) + +BIG5_CHAR_LEN_TABLE = (0, 1, 1, 2, 0) + +BIG5_SM_MODEL = {'class_table': BIG5_CLS, + 'class_factor': 5, + 'state_table': BIG5_ST, + 'char_len_table': BIG5_CHAR_LEN_TABLE, + 'name': 'Big5'} + +# CP949 + +CP949_CLS = ( + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f + 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f + 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f + 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f + 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f + 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f + 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f + 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f + 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af + 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf + 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff +) + +CP949_ST = ( +#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START, 4, 5,MachineState.ERROR, 6, # MachineState.START + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, # MachineState.ERROR + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME, # MachineState.ITS_ME + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 3 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 4 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 5 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 6 +) + +CP949_CHAR_LEN_TABLE = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) + +CP949_SM_MODEL = {'class_table': CP949_CLS, + 'class_factor': 10, + 'state_table': CP949_ST, + 'char_len_table': CP949_CHAR_LEN_TABLE, + 'name': 'CP949'} + +# EUC-JP + +EUCJP_CLS = ( + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5 # f8 - ff +) + +EUCJP_ST = ( + 3, 4, 3, 5,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 3,MachineState.ERROR,#18-1f + 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START#20-27 +) + +EUCJP_CHAR_LEN_TABLE = (2, 2, 2, 3, 1, 0) + +EUCJP_SM_MODEL = {'class_table': EUCJP_CLS, + 'class_factor': 6, + 'state_table': EUCJP_ST, + 'char_len_table': EUCJP_CHAR_LEN_TABLE, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0 # f8 - ff +) + +EUCKR_ST = ( + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #08-0f +) + +EUCKR_CHAR_LEN_TABLE = (0, 1, 2, 0) + +EUCKR_SM_MODEL = {'class_table': EUCKR_CLS, + 'class_factor': 4, + 'state_table': EUCKR_ST, + 'char_len_table': EUCKR_CHAR_LEN_TABLE, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_CLS = ( + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +EUCTW_ST = ( + MachineState.ERROR,MachineState.ERROR,MachineState.START, 3, 3, 3, 4,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.ERROR,#10-17 + MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,#20-27 + MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +EUCTW_CHAR_LEN_TABLE = (0, 0, 1, 2, 2, 2, 3) + +EUCTW_SM_MODEL = {'class_table': EUCTW_CLS, + 'class_factor': 7, + 'state_table': EUCTW_ST, + 'char_len_table': EUCTW_CHAR_LEN_TABLE, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0 # f8 - ff +) + +GB2312_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, 3,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,#10-17 + 4,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#20-27 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validating +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312_CHAR_LEN_TABLE = (0, 1, 1, 1, 1, 1, 2) + +GB2312_SM_MODEL = {'class_table': GB2312_CLS, + 'class_factor': 7, + 'state_table': GB2312_ST, + 'char_len_table': GB2312_CHAR_LEN_TABLE, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,2,2,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,0,0,0) # f8 - ff + + +SJIS_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START #10-17 +) + +SJIS_CHAR_LEN_TABLE = (0, 1, 1, 2, 0, 0) + +SJIS_SM_MODEL = {'class_table': SJIS_CLS, + 'class_factor': 6, + 'state_table': SJIS_ST, + 'char_len_table': SJIS_CHAR_LEN_TABLE, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2BE_ST = ( + 5, 7, 7,MachineState.ERROR, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,#10-17 + 6, 6, 6, 6, 6,MachineState.ITS_ME, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,MachineState.ERROR,#20-27 + 5, 8, 6, 6,MachineState.ERROR, 6, 6, 6,#28-2f + 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2BE_CHAR_LEN_TABLE = (2, 2, 2, 0, 2, 2) + +UCS2BE_SM_MODEL = {'class_table': UCS2BE_CLS, + 'class_factor': 6, + 'state_table': UCS2BE_ST, + 'char_len_table': UCS2BE_CHAR_LEN_TABLE, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2LE_ST = ( + 6, 6, 7, 6, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 5, 5, 5,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#10-17 + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,MachineState.ERROR,#20-27 + 5, 5, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5,#28-2f + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2LE_CHAR_LEN_TABLE = (2, 2, 2, 2, 2, 2) + +UCS2LE_SM_MODEL = {'class_table': UCS2LE_CLS, + 'class_factor': 6, + 'state_table': UCS2LE_ST, + 'char_len_table': UCS2LE_CHAR_LEN_TABLE, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0 # f8 - ff +) + +UTF8_ST = ( + MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#20-27 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#28-2f + MachineState.ERROR,MachineState.ERROR, 5, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#30-37 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#38-3f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#40-47 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#48-4f + MachineState.ERROR,MachineState.ERROR, 7, 7, 7, 7,MachineState.ERROR,MachineState.ERROR,#50-57 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#58-5f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 7, 7,MachineState.ERROR,MachineState.ERROR,#60-67 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#68-6f + MachineState.ERROR,MachineState.ERROR, 9, 9, 9, 9,MachineState.ERROR,MachineState.ERROR,#70-77 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#78-7f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 9,MachineState.ERROR,MachineState.ERROR,#80-87 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#88-8f + MachineState.ERROR,MachineState.ERROR, 12, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,#90-97 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#98-9f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12,MachineState.ERROR,MachineState.ERROR,#a0-a7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#a8-af + MachineState.ERROR,MachineState.ERROR, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b0-b7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b8-bf + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,#c0-c7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR #c8-cf +) + +UTF8_CHAR_LEN_TABLE = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8_SM_MODEL = {'class_table': UTF8_CLS, + 'class_factor': 16, + 'state_table': UTF8_ST, + 'char_len_table': UTF8_CHAR_LEN_TABLE, + 'name': 'UTF-8'} diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py new file mode 100644 index 0000000..0adb51d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py @@ -0,0 +1,132 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import CharacterCategory, ProbingState, SequenceLikelihood + + +class SingleByteCharSetProber(CharSetProber): + SAMPLE_SIZE = 64 + SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 + POSITIVE_SHORTCUT_THRESHOLD = 0.95 + NEGATIVE_SHORTCUT_THRESHOLD = 0.05 + + def __init__(self, model, reversed=False, name_prober=None): + super(SingleByteCharSetProber, self).__init__() + self._model = model + # TRUE if we need to reverse every pair in the model lookup + self._reversed = reversed + # Optional auxiliary prober for name decision + self._name_prober = name_prober + self._last_order = None + self._seq_counters = None + self._total_seqs = None + self._total_char = None + self._freq_char = None + self.reset() + + def reset(self): + super(SingleByteCharSetProber, self).reset() + # char order of last character + self._last_order = 255 + self._seq_counters = [0] * SequenceLikelihood.get_num_categories() + self._total_seqs = 0 + self._total_char = 0 + # characters that fall in our sampling range + self._freq_char = 0 + + @property + def charset_name(self): + if self._name_prober: + return self._name_prober.charset_name + else: + return self._model['charset_name'] + + @property + def language(self): + if self._name_prober: + return self._name_prober.language + else: + return self._model.get('language') + + def feed(self, byte_str): + if not self._model['keep_english_letter']: + byte_str = self.filter_international_words(byte_str) + if not byte_str: + return self.state + char_to_order_map = self._model['char_to_order_map'] + for i, c in enumerate(byte_str): + # XXX: Order is in range 1-64, so one would think we want 0-63 here, + # but that leads to 27 more test failures than before. + order = char_to_order_map[c] + # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but + # CharacterCategory.SYMBOL is actually 253, so we use CONTROL + # to make it closer to the original intent. The only difference + # is whether or not we count digits and control characters for + # _total_char purposes. + if order < CharacterCategory.CONTROL: + self._total_char += 1 + if order < self.SAMPLE_SIZE: + self._freq_char += 1 + if self._last_order < self.SAMPLE_SIZE: + self._total_seqs += 1 + if not self._reversed: + i = (self._last_order * self.SAMPLE_SIZE) + order + model = self._model['precedence_matrix'][i] + else: # reverse the order of the letters in the lookup + i = (order * self.SAMPLE_SIZE) + self._last_order + model = self._model['precedence_matrix'][i] + self._seq_counters[model] += 1 + self._last_order = order + + charset_name = self._model['charset_name'] + if self.state == ProbingState.DETECTING: + if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: + confidence = self.get_confidence() + if confidence > self.POSITIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, we have a winner', + charset_name, confidence) + self._state = ProbingState.FOUND_IT + elif confidence < self.NEGATIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, below negative ' + 'shortcut threshhold %s', charset_name, + confidence, + self.NEGATIVE_SHORTCUT_THRESHOLD) + self._state = ProbingState.NOT_ME + + return self.state + + def get_confidence(self): + r = 0.01 + if self._total_seqs > 0: + r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / + self._total_seqs / self._model['typical_positive_ratio']) + r = r * self._freq_char / self._total_char + if r >= 1.0: + r = 0.99 + return r diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py new file mode 100644 index 0000000..98e95dc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py @@ -0,0 +1,73 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .sbcharsetprober import SingleByteCharSetProber +from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, + Latin5CyrillicModel, MacCyrillicModel, + Ibm866Model, Ibm855Model) +from .langgreekmodel import Latin7GreekModel, Win1253GreekModel +from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel +# from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel +from .langthaimodel import TIS620ThaiModel +from .langhebrewmodel import Win1255HebrewModel +from .hebrewprober import HebrewProber +from .langturkishmodel import Latin5TurkishModel + + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + super(SBCSGroupProber, self).__init__() + self.probers = [ + SingleByteCharSetProber(Win1251CyrillicModel), + SingleByteCharSetProber(Koi8rModel), + SingleByteCharSetProber(Latin5CyrillicModel), + SingleByteCharSetProber(MacCyrillicModel), + SingleByteCharSetProber(Ibm866Model), + SingleByteCharSetProber(Ibm855Model), + SingleByteCharSetProber(Latin7GreekModel), + SingleByteCharSetProber(Win1253GreekModel), + SingleByteCharSetProber(Latin5BulgarianModel), + SingleByteCharSetProber(Win1251BulgarianModel), + # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) + # after we retrain model. + # SingleByteCharSetProber(Latin2HungarianModel), + # SingleByteCharSetProber(Win1250HungarianModel), + SingleByteCharSetProber(TIS620ThaiModel), + SingleByteCharSetProber(Latin5TurkishModel), + ] + hebrew_prober = HebrewProber() + logical_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, + False, hebrew_prober) + visual_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, True, + hebrew_prober) + hebrew_prober.set_model_probers(logical_hebrew_prober, visual_hebrew_prober) + self.probers.extend([hebrew_prober, logical_hebrew_prober, + visual_hebrew_prober]) + + self.reset() diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py new file mode 100644 index 0000000..9e29623 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import SJISDistributionAnalysis +from .jpcntx import SJISContextAnalysis +from .mbcssm import SJIS_SM_MODEL +from .enums import ProbingState, MachineState + + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + super(SJISProber, self).__init__() + self.coding_sm = CodingStateMachine(SJIS_SM_MODEL) + self.distribution_analyzer = SJISDistributionAnalysis() + self.context_analyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + super(SJISProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return self.context_analyzer.charset_name + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char[2 - char_len:], + char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i + 1 - char_len:i + 3 + - char_len], char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py new file mode 100644 index 0000000..7b4e92d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py @@ -0,0 +1,286 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### +""" +Module containing the UniversalDetector detector class, which is the primary +class a user of ``chardet`` should use. + +:author: Mark Pilgrim (initial port to Python) +:author: Shy Shalom (original C code) +:author: Dan Blanchard (major refactoring for 3.0) +:author: Ian Cordasco +""" + + +import codecs +import logging +import re + +from .charsetgroupprober import CharSetGroupProber +from .enums import InputState, LanguageFilter, ProbingState +from .escprober import EscCharSetProber +from .latin1prober import Latin1Prober +from .mbcsgroupprober import MBCSGroupProber +from .sbcsgroupprober import SBCSGroupProber + + +class UniversalDetector(object): + """ + The ``UniversalDetector`` class underlies the ``chardet.detect`` function + and coordinates all of the different charset probers. + + To get a ``dict`` containing an encoding and its confidence, you can simply + run: + + .. code:: + + u = UniversalDetector() + u.feed(some_bytes) + u.close() + detected = u.result + + """ + + MINIMUM_THRESHOLD = 0.20 + HIGH_BYTE_DETECTOR = re.compile(b'[\x80-\xFF]') + ESC_DETECTOR = re.compile(b'(\033|~{)') + WIN_BYTE_DETECTOR = re.compile(b'[\x80-\x9F]') + ISO_WIN_MAP = {'iso-8859-1': 'Windows-1252', + 'iso-8859-2': 'Windows-1250', + 'iso-8859-5': 'Windows-1251', + 'iso-8859-6': 'Windows-1256', + 'iso-8859-7': 'Windows-1253', + 'iso-8859-8': 'Windows-1255', + 'iso-8859-9': 'Windows-1254', + 'iso-8859-13': 'Windows-1257'} + + def __init__(self, lang_filter=LanguageFilter.ALL): + self._esc_charset_prober = None + self._charset_probers = [] + self.result = None + self.done = None + self._got_data = None + self._input_state = None + self._last_char = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + self._has_win_bytes = None + self.reset() + + def reset(self): + """ + Reset the UniversalDetector and all of its probers back to their + initial states. This is called by ``__init__``, so you only need to + call this directly in between analyses of different documents. + """ + self.result = {'encoding': None, 'confidence': 0.0, 'language': None} + self.done = False + self._got_data = False + self._has_win_bytes = False + self._input_state = InputState.PURE_ASCII + self._last_char = b'' + if self._esc_charset_prober: + self._esc_charset_prober.reset() + for prober in self._charset_probers: + prober.reset() + + def feed(self, byte_str): + """ + Takes a chunk of a document and feeds it through all of the relevant + charset probers. + + After calling ``feed``, you can check the value of the ``done`` + attribute to see if you need to continue feeding the + ``UniversalDetector`` more data, or if it has made a prediction + (in the ``result`` attribute). + + .. note:: + You should always call ``close`` when you're done feeding in your + document if ``done`` is not already ``True``. + """ + if self.done: + return + + if not len(byte_str): + return + + if not isinstance(byte_str, bytearray): + byte_str = bytearray(byte_str) + + # First check for known BOMs, since these are guaranteed to be correct + if not self._got_data: + # If the data starts with BOM, we know it is UTF + if byte_str.startswith(codecs.BOM_UTF8): + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8-SIG", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_UTF32_LE, + codecs.BOM_UTF32_BE)): + # FF FE 00 00 UTF-32, little-endian BOM + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\xFE\xFF\x00\x00'): + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = {'encoding': "X-ISO-10646-UCS-4-3412", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\x00\x00\xFF\xFE'): + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = {'encoding': "X-ISO-10646-UCS-4-2143", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_LE, codecs.BOM_BE)): + # FF FE UTF-16, little endian BOM + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16", + 'confidence': 1.0, + 'language': ''} + + self._got_data = True + if self.result['encoding'] is not None: + self.done = True + return + + # If none of those matched and we've only see ASCII so far, check + # for high bytes and escape sequences + if self._input_state == InputState.PURE_ASCII: + if self.HIGH_BYTE_DETECTOR.search(byte_str): + self._input_state = InputState.HIGH_BYTE + elif self._input_state == InputState.PURE_ASCII and \ + self.ESC_DETECTOR.search(self._last_char + byte_str): + self._input_state = InputState.ESC_ASCII + + self._last_char = byte_str[-1:] + + # If we've seen escape sequences, use the EscCharSetProber, which + # uses a simple state machine to check for known escape sequences in + # HZ and ISO-2022 encodings, since those are the only encodings that + # use such sequences. + if self._input_state == InputState.ESC_ASCII: + if not self._esc_charset_prober: + self._esc_charset_prober = EscCharSetProber(self.lang_filter) + if self._esc_charset_prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': + self._esc_charset_prober.charset_name, + 'confidence': + self._esc_charset_prober.get_confidence(), + 'language': + self._esc_charset_prober.language} + self.done = True + # If we've seen high bytes (i.e., those with values greater than 127), + # we need to do more complicated checks using all our multi-byte and + # single-byte probers that are left. The single-byte probers + # use character bigram distributions to determine the encoding, whereas + # the multi-byte probers use a combination of character unigram and + # bigram distributions. + elif self._input_state == InputState.HIGH_BYTE: + if not self._charset_probers: + self._charset_probers = [MBCSGroupProber(self.lang_filter)] + # If we're checking non-CJK encodings, use single-byte prober + if self.lang_filter & LanguageFilter.NON_CJK: + self._charset_probers.append(SBCSGroupProber()) + self._charset_probers.append(Latin1Prober()) + for prober in self._charset_probers: + if prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': prober.charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language} + self.done = True + break + if self.WIN_BYTE_DETECTOR.search(byte_str): + self._has_win_bytes = True + + def close(self): + """ + Stop analyzing the current document and come up with a final + prediction. + + :returns: The ``result`` attribute, a ``dict`` with the keys + `encoding`, `confidence`, and `language`. + """ + # Don't bother with checks if we're already done + if self.done: + return self.result + self.done = True + + if not self._got_data: + self.logger.debug('no data received!') + + # Default to ASCII if it is all we've seen so far + elif self._input_state == InputState.PURE_ASCII: + self.result = {'encoding': 'ascii', + 'confidence': 1.0, + 'language': ''} + + # If we have seen non-ASCII, return the best that met MINIMUM_THRESHOLD + elif self._input_state == InputState.HIGH_BYTE: + prober_confidence = None + max_prober_confidence = 0.0 + max_prober = None + for prober in self._charset_probers: + if not prober: + continue + prober_confidence = prober.get_confidence() + if prober_confidence > max_prober_confidence: + max_prober_confidence = prober_confidence + max_prober = prober + if max_prober and (max_prober_confidence > self.MINIMUM_THRESHOLD): + charset_name = max_prober.charset_name + lower_charset_name = max_prober.charset_name.lower() + confidence = max_prober.get_confidence() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if self._has_win_bytes: + charset_name = self.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + self.result = {'encoding': charset_name, + 'confidence': confidence, + 'language': max_prober.language} + + # Log all prober confidences if none met MINIMUM_THRESHOLD + if self.logger.getEffectiveLevel() == logging.DEBUG: + if self.result['encoding'] is None: + self.logger.debug('no probers hit minimum threshold') + for group_prober in self._charset_probers: + if not group_prober: + continue + if isinstance(group_prober, CharSetGroupProber): + for prober in group_prober.probers: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + else: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + return self.result diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py new file mode 100644 index 0000000..6c3196c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py @@ -0,0 +1,82 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState +from .codingstatemachine import CodingStateMachine +from .mbcssm import UTF8_SM_MODEL + + + +class UTF8Prober(CharSetProber): + ONE_CHAR_PROB = 0.5 + + def __init__(self): + super(UTF8Prober, self).__init__() + self.coding_sm = CodingStateMachine(UTF8_SM_MODEL) + self._num_mb_chars = None + self.reset() + + def reset(self): + super(UTF8Prober, self).reset() + self.coding_sm.reset() + self._num_mb_chars = 0 + + @property + def charset_name(self): + return "utf-8" + + @property + def language(self): + return "" + + def feed(self, byte_str): + for c in byte_str: + coding_state = self.coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + if self.coding_sm.get_current_charlen() >= 2: + self._num_mb_chars += 1 + + if self.state == ProbingState.DETECTING: + if self.get_confidence() > self.SHORTCUT_THRESHOLD: + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + unlike = 0.99 + if self._num_mb_chars < 6: + unlike *= self.ONE_CHAR_PROB ** self._num_mb_chars + return 1.0 - unlike + else: + return unlike diff --git a/winvenv/Lib/site-packages/pip/_vendor/chardet/version.py b/winvenv/Lib/site-packages/pip/_vendor/chardet/version.py new file mode 100644 index 0000000..bb2a34a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/chardet/version.py @@ -0,0 +1,9 @@ +""" +This module exists only to simplify retrieving the version number of chardet +from within setup.py and from chardet subpackages. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + +__version__ = "3.0.4" +VERSION = __version__.split('.') diff --git a/winvenv/Lib/site-packages/pip/_vendor/colorama/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/colorama/__init__.py new file mode 100644 index 0000000..f4d9ce2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/colorama/__init__.py @@ -0,0 +1,7 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit, colorama_text +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.3.9' + diff --git a/winvenv/Lib/site-packages/pip/_vendor/colorama/ansi.py b/winvenv/Lib/site-packages/pip/_vendor/colorama/ansi.py new file mode 100644 index 0000000..7877658 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/colorama/ansi.py @@ -0,0 +1,102 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\007' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + +def set_title(title): + return OSC + '2;' + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + 'J' + +def clear_line(mode=2): + return CSI + str(mode) + 'K' + + +class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + 'A' + def DOWN(self, n=1): + return CSI + str(n) + 'B' + def FORWARD(self, n=1): + return CSI + str(n) + 'C' + def BACK(self, n=1): + return CSI + str(n) + 'D' + def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + + +class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() diff --git a/winvenv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py b/winvenv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py new file mode 100644 index 0000000..1d6e605 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py @@ -0,0 +1,236 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll, winapi_test + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +def is_stream_closed(stream): + return not hasattr(stream, 'closed') or stream.closed + + +def is_a_tty(stream): + return hasattr(stream, 'isatty') and stream.isatty() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def write(self, text): + self.__convertor.write(text) + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + + # should we strip ANSI sequences from our output? + if strip is None: + strip = conversion_supported or (not is_stream_closed(wrapped) and not is_a_tty(wrapped)) + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = conversion_supported and not is_stream_closed(wrapped) and is_a_tty(wrapped) + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not is_stream_closed(self.wrapped): + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command in '\x07': # \x07 = BEL + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text diff --git a/winvenv/Lib/site-packages/pip/_vendor/colorama/initialise.py b/winvenv/Lib/site-packages/pip/_vendor/colorama/initialise.py new file mode 100644 index 0000000..834962a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/colorama/initialise.py @@ -0,0 +1,82 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import contextlib +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = None +orig_stderr = None + +wrapped_stdout = None +wrapped_stderr = None + +atexit_done = False + + +def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +@contextlib.contextmanager +def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + diff --git a/winvenv/Lib/site-packages/pip/_vendor/colorama/win32.py b/winvenv/Lib/site-packages/pip/_vendor/colorama/win32.py new file mode 100644 index 0000000..8262e35 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/colorama/win32.py @@ -0,0 +1,156 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None + winapi_test = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW + _SetConsoleTitleW.argtypes = [ + wintypes.LPCWSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + handles = { + STDOUT: _GetStdHandle(STDOUT), + STDERR: _GetStdHandle(STDERR), + } + + def _winapi_test(handle): + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) + + def winapi_test(): + return any(_winapi_test(h) for h in handles.values()) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = handles[stream_id] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = handles[stream_id] + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = handles[stream_id] + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = handles[stream_id] + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = handles[stream_id] + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) diff --git a/winvenv/Lib/site-packages/pip/_vendor/colorama/winterm.py b/winvenv/Lib/site-packages/pip/_vendor/colorama/winterm.py new file mode 100644 index 0000000..60309d3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/colorama/winterm.py @@ -0,0 +1,162 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + + def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + if mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + if mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/__init__.py new file mode 100644 index 0000000..d4aab45 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import logging + +__version__ = '0.2.7' + +class DistlibException(Exception): + pass + +try: + from logging import NullHandler +except ImportError: # pragma: no cover + class NullHandler(logging.Handler): + def handle(self, record): pass + def emit(self, record): pass + def createLock(self): self.lock = None + +logger = logging.getLogger(__name__) +logger.addHandler(NullHandler()) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py new file mode 100644 index 0000000..f7dbf4c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py @@ -0,0 +1,6 @@ +"""Modules copied from Python 3 standard libraries, for internal use only. + +Individual classes and functions are found in d2._backport.misc. Intended +usage is to always import things missing from 3.1 from that module: the +built-in/stdlib objects will be used if found. +""" diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py new file mode 100644 index 0000000..cfb318d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Backports for individual classes and functions.""" + +import os +import sys + +__all__ = ['cache_from_source', 'callable', 'fsencode'] + + +try: + from imp import cache_from_source +except ImportError: + def cache_from_source(py_file, debug=__debug__): + ext = debug and 'c' or 'o' + return py_file + ext + + +try: + callable = callable +except NameError: + from collections import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode +except AttributeError: + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, str): + return filename.encode(sys.getfilesystemencoding()) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py new file mode 100644 index 0000000..159e49e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py @@ -0,0 +1,761 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Utility functions for copying and archiving files and directory trees. + +XXX The functions here don't copy the resource fork or other metadata on Mac. + +""" + +import os +import sys +import stat +from os.path import abspath +import fnmatch +import collections +import errno +from . import tarfile + +try: + import bz2 + _BZ2_SUPPORTED = True +except ImportError: + _BZ2_SUPPORTED = False + +try: + from pwd import getpwnam +except ImportError: + getpwnam = None + +try: + from grp import getgrnam +except ImportError: + getgrnam = None + +__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", + "copytree", "move", "rmtree", "Error", "SpecialFileError", + "ExecError", "make_archive", "get_archive_formats", + "register_archive_format", "unregister_archive_format", + "get_unpack_formats", "register_unpack_format", + "unregister_unpack_format", "unpack_archive", "ignore_patterns"] + +class Error(EnvironmentError): + pass + +class SpecialFileError(EnvironmentError): + """Raised when trying to do a kind of operation (e.g. copying) which is + not supported on a special file (e.g. a named pipe)""" + +class ExecError(EnvironmentError): + """Raised when a command could not be executed""" + +class ReadError(EnvironmentError): + """Raised when an archive cannot be read""" + +class RegistryError(Exception): + """Raised when a registry operation with the archiving + and unpacking registries fails""" + + +try: + WindowsError +except NameError: + WindowsError = None + +def copyfileobj(fsrc, fdst, length=16*1024): + """copy data from file-like object fsrc to file-like object fdst""" + while 1: + buf = fsrc.read(length) + if not buf: + break + fdst.write(buf) + +def _samefile(src, dst): + # Macintosh, Unix. + if hasattr(os.path, 'samefile'): + try: + return os.path.samefile(src, dst) + except OSError: + return False + + # All other platforms: check for same pathname. + return (os.path.normcase(os.path.abspath(src)) == + os.path.normcase(os.path.abspath(dst))) + +def copyfile(src, dst): + """Copy data from src to dst""" + if _samefile(src, dst): + raise Error("`%s` and `%s` are the same file" % (src, dst)) + + for fn in [src, dst]: + try: + st = os.stat(fn) + except OSError: + # File most likely does not exist + pass + else: + # XXX What about other special files? (sockets, devices...) + if stat.S_ISFIFO(st.st_mode): + raise SpecialFileError("`%s` is a named pipe" % fn) + + with open(src, 'rb') as fsrc: + with open(dst, 'wb') as fdst: + copyfileobj(fsrc, fdst) + +def copymode(src, dst): + """Copy mode bits from src to dst""" + if hasattr(os, 'chmod'): + st = os.stat(src) + mode = stat.S_IMODE(st.st_mode) + os.chmod(dst, mode) + +def copystat(src, dst): + """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" + st = os.stat(src) + mode = stat.S_IMODE(st.st_mode) + if hasattr(os, 'utime'): + os.utime(dst, (st.st_atime, st.st_mtime)) + if hasattr(os, 'chmod'): + os.chmod(dst, mode) + if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): + try: + os.chflags(dst, st.st_flags) + except OSError as why: + if (not hasattr(errno, 'EOPNOTSUPP') or + why.errno != errno.EOPNOTSUPP): + raise + +def copy(src, dst): + """Copy data and mode bits ("cp src dst"). + + The destination may be a directory. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst) + copymode(src, dst) + +def copy2(src, dst): + """Copy data and all stat info ("cp -p src dst"). + + The destination may be a directory. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst) + copystat(src, dst) + +def ignore_patterns(*patterns): + """Function that can be used as copytree() ignore parameter. + + Patterns is a sequence of glob-style patterns + that are used to exclude files""" + def _ignore_patterns(path, names): + ignored_names = [] + for pattern in patterns: + ignored_names.extend(fnmatch.filter(names, pattern)) + return set(ignored_names) + return _ignore_patterns + +def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, + ignore_dangling_symlinks=False): + """Recursively copy a directory tree. + + The destination directory must not already exist. + If exception(s) occur, an Error is raised with a list of reasons. + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. If the file pointed by the symlink doesn't + exist, an exception will be added in the list of errors raised in + an Error exception at the end of the copy process. + + You can set the optional ignore_dangling_symlinks flag to true if you + want to silence this exception. Notice that this has no effect on + platforms that don't support os.symlink. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + The optional copy_function argument is a callable that will be used + to copy each file. It will be called with the source path and the + destination path as arguments. By default, copy2() is used, but any + function that supports the same signature (like copy()) can be used. + + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if os.path.islink(srcname): + linkto = os.readlink(srcname) + if symlinks: + os.symlink(linkto, dstname) + else: + # ignore dangling symlink if the flag is on + if not os.path.exists(linkto) and ignore_dangling_symlinks: + continue + # otherwise let the copy occurs. copy2 will raise an error + copy_function(srcname, dstname) + elif os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, copy_function) + else: + # Will raise a SpecialFileError for unsupported file types + copy_function(srcname, dstname) + # catch the Error from the recursive copytree so that we can + # continue with other files + except Error as err: + errors.extend(err.args[0]) + except EnvironmentError as why: + errors.append((srcname, dstname, str(why))) + try: + copystat(src, dst) + except OSError as why: + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) + if errors: + raise Error(errors) + +def rmtree(path, ignore_errors=False, onerror=None): + """Recursively delete a directory tree. + + If ignore_errors is set, errors are ignored; otherwise, if onerror + is set, it is called to handle the error with arguments (func, + path, exc_info) where func is os.listdir, os.remove, or os.rmdir; + path is the argument to that function that caused it to fail; and + exc_info is a tuple returned by sys.exc_info(). If ignore_errors + is false and onerror is None, an exception is raised. + + """ + if ignore_errors: + def onerror(*args): + pass + elif onerror is None: + def onerror(*args): + raise + try: + if os.path.islink(path): + # symlinks to directories are forbidden, see bug #1669 + raise OSError("Cannot call rmtree on a symbolic link") + except OSError: + onerror(os.path.islink, path, sys.exc_info()) + # can't continue even if onerror hook returns + return + names = [] + try: + names = os.listdir(path) + except os.error: + onerror(os.listdir, path, sys.exc_info()) + for name in names: + fullname = os.path.join(path, name) + try: + mode = os.lstat(fullname).st_mode + except os.error: + mode = 0 + if stat.S_ISDIR(mode): + rmtree(fullname, ignore_errors, onerror) + else: + try: + os.remove(fullname) + except os.error: + onerror(os.remove, fullname, sys.exc_info()) + try: + os.rmdir(path) + except os.error: + onerror(os.rmdir, path, sys.exc_info()) + + +def _basename(path): + # A basename() variant which first strips the trailing slash, if present. + # Thus we always get the last component of the path, even for directories. + return os.path.basename(path.rstrip(os.path.sep)) + +def move(src, dst): + """Recursively move a file or directory to another location. This is + similar to the Unix "mv" command. + + If the destination is a directory or a symlink to a directory, the source + is moved inside the directory. The destination path must not already + exist. + + If the destination already exists but is not a directory, it may be + overwritten depending on os.rename() semantics. + + If the destination is on our current filesystem, then rename() is used. + Otherwise, src is copied to the destination and then removed. + A lot more could be done here... A look at a mv.c shows a lot of + the issues this implementation glosses over. + + """ + real_dst = dst + if os.path.isdir(dst): + if _samefile(src, dst): + # We might be on a case insensitive filesystem, + # perform the rename anyway. + os.rename(src, dst) + return + + real_dst = os.path.join(dst, _basename(src)) + if os.path.exists(real_dst): + raise Error("Destination path '%s' already exists" % real_dst) + try: + os.rename(src, real_dst) + except OSError: + if os.path.isdir(src): + if _destinsrc(src, dst): + raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) + copytree(src, real_dst, symlinks=True) + rmtree(src) + else: + copy2(src, real_dst) + os.unlink(src) + +def _destinsrc(src, dst): + src = abspath(src) + dst = abspath(dst) + if not src.endswith(os.path.sep): + src += os.path.sep + if not dst.endswith(os.path.sep): + dst += os.path.sep + return dst.startswith(src) + +def _get_gid(name): + """Returns a gid, given a group name.""" + if getgrnam is None or name is None: + return None + try: + result = getgrnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _get_uid(name): + """Returns an uid, given a user name.""" + if getpwnam is None or name is None: + return None + try: + result = getpwnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, + owner=None, group=None, logger=None): + """Create a (possibly compressed) tar file from all the files under + 'base_dir'. + + 'compress' must be "gzip" (the default), "bzip2", or None. + + 'owner' and 'group' can be used to define an owner and a group for the + archive that is being built. If not provided, the current owner and group + will be used. + + The output tar file will be named 'base_name' + ".tar", possibly plus + the appropriate compression extension (".gz", or ".bz2"). + + Returns the output filename. + """ + tar_compression = {'gzip': 'gz', None: ''} + compress_ext = {'gzip': '.gz'} + + if _BZ2_SUPPORTED: + tar_compression['bzip2'] = 'bz2' + compress_ext['bzip2'] = '.bz2' + + # flags for compression program, each element of list will be an argument + if compress is not None and compress not in compress_ext: + raise ValueError("bad value for 'compress', or compression format not " + "supported : {0}".format(compress)) + + archive_name = base_name + '.tar' + compress_ext.get(compress, '') + archive_dir = os.path.dirname(archive_name) + + if not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # creating the tarball + if logger is not None: + logger.info('Creating tar archive') + + uid = _get_uid(owner) + gid = _get_gid(group) + + def _set_uid_gid(tarinfo): + if gid is not None: + tarinfo.gid = gid + tarinfo.gname = group + if uid is not None: + tarinfo.uid = uid + tarinfo.uname = owner + return tarinfo + + if not dry_run: + tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + return archive_name + +def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): + # XXX see if we want to keep an external call here + if verbose: + zipoptions = "-r" + else: + zipoptions = "-rq" + from distutils.errors import DistutilsExecError + from distutils.spawn import spawn + try: + spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) + except DistutilsExecError: + # XXX really should distinguish between "couldn't find + # external 'zip' command" and "zip failed". + raise ExecError("unable to create zip file '%s': " + "could neither import the 'zipfile' module nor " + "find a standalone zip utility") % zip_filename + +def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): + """Create a zip file from all the files under 'base_dir'. + + The output zip file will be named 'base_name' + ".zip". Uses either the + "zipfile" Python module (if available) or the InfoZIP "zip" utility + (if installed and found on the default search path). If neither tool is + available, raises ExecError. Returns the name of the output zip + file. + """ + zip_filename = base_name + ".zip" + archive_dir = os.path.dirname(base_name) + + if not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # If zipfile module is not available, try spawning an external 'zip' + # command. + try: + import zipfile + except ImportError: + zipfile = None + + if zipfile is None: + _call_external_zip(base_dir, zip_filename, verbose, dry_run) + else: + if logger is not None: + logger.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + zip = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) + + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zip.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + zip.close() + + return zip_filename + +_ARCHIVE_FORMATS = { + 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), + 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), + 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), + 'zip': (_make_zipfile, [], "ZIP file"), + } + +if _BZ2_SUPPORTED: + _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], + "bzip2'ed tar-file") + +def get_archive_formats(): + """Returns a list of supported formats for archiving and unarchiving. + + Each element of the returned sequence is a tuple (name, description) + """ + formats = [(name, registry[2]) for name, registry in + _ARCHIVE_FORMATS.items()] + formats.sort() + return formats + +def register_archive_format(name, function, extra_args=None, description=''): + """Registers an archive format. + + name is the name of the format. function is the callable that will be + used to create archives. If provided, extra_args is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_archive_formats() function. + """ + if extra_args is None: + extra_args = [] + if not isinstance(function, collections.Callable): + raise TypeError('The %s object is not callable' % function) + if not isinstance(extra_args, (tuple, list)): + raise TypeError('extra_args needs to be a sequence') + for element in extra_args: + if not isinstance(element, (tuple, list)) or len(element) !=2: + raise TypeError('extra_args elements are : (arg_name, value)') + + _ARCHIVE_FORMATS[name] = (function, extra_args, description) + +def unregister_archive_format(name): + del _ARCHIVE_FORMATS[name] + +def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, + dry_run=0, owner=None, group=None, logger=None): + """Create an archive file (eg. zip or tar). + + 'base_name' is the name of the file to create, minus any format-specific + extension; 'format' is the archive format: one of "zip", "tar", "bztar" + or "gztar". + + 'root_dir' is a directory that will be the root directory of the + archive; ie. we typically chdir into 'root_dir' before creating the + archive. 'base_dir' is the directory where we start archiving from; + ie. 'base_dir' will be the common prefix of all files and + directories in the archive. 'root_dir' and 'base_dir' both default + to the current directory. Returns the name of the archive file. + + 'owner' and 'group' are used when creating a tar archive. By default, + uses the current owner and group. + """ + save_cwd = os.getcwd() + if root_dir is not None: + if logger is not None: + logger.debug("changing into '%s'", root_dir) + base_name = os.path.abspath(base_name) + if not dry_run: + os.chdir(root_dir) + + if base_dir is None: + base_dir = os.curdir + + kwargs = {'dry_run': dry_run, 'logger': logger} + + try: + format_info = _ARCHIVE_FORMATS[format] + except KeyError: + raise ValueError("unknown archive format '%s'" % format) + + func = format_info[0] + for arg, val in format_info[1]: + kwargs[arg] = val + + if format != 'zip': + kwargs['owner'] = owner + kwargs['group'] = group + + try: + filename = func(base_name, base_dir, **kwargs) + finally: + if root_dir is not None: + if logger is not None: + logger.debug("changing back to '%s'", save_cwd) + os.chdir(save_cwd) + + return filename + + +def get_unpack_formats(): + """Returns a list of supported formats for unpacking. + + Each element of the returned sequence is a tuple + (name, extensions, description) + """ + formats = [(name, info[0], info[3]) for name, info in + _UNPACK_FORMATS.items()] + formats.sort() + return formats + +def _check_unpack_options(extensions, function, extra_args): + """Checks what gets registered as an unpacker.""" + # first make sure no other unpacker is registered for this extension + existing_extensions = {} + for name, info in _UNPACK_FORMATS.items(): + for ext in info[0]: + existing_extensions[ext] = name + + for extension in extensions: + if extension in existing_extensions: + msg = '%s is already registered for "%s"' + raise RegistryError(msg % (extension, + existing_extensions[extension])) + + if not isinstance(function, collections.Callable): + raise TypeError('The registered function must be a callable') + + +def register_unpack_format(name, extensions, function, extra_args=None, + description=''): + """Registers an unpack format. + + `name` is the name of the format. `extensions` is a list of extensions + corresponding to the format. + + `function` is the callable that will be + used to unpack archives. The callable will receive archives to unpack. + If it's unable to handle an archive, it needs to raise a ReadError + exception. + + If provided, `extra_args` is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_unpack_formats() function. + """ + if extra_args is None: + extra_args = [] + _check_unpack_options(extensions, function, extra_args) + _UNPACK_FORMATS[name] = extensions, function, extra_args, description + +def unregister_unpack_format(name): + """Removes the pack format from the registry.""" + del _UNPACK_FORMATS[name] + +def _ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + +def _unpack_zipfile(filename, extract_dir): + """Unpack zip `filename` to `extract_dir` + """ + try: + import zipfile + except ImportError: + raise ReadError('zlib not supported, cannot unpack this archive.') + + if not zipfile.is_zipfile(filename): + raise ReadError("%s is not a zip file" % filename) + + zip = zipfile.ZipFile(filename) + try: + for info in zip.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name: + continue + + target = os.path.join(extract_dir, *name.split('/')) + if not target: + continue + + _ensure_directory(target) + if not name.endswith('/'): + # file + data = zip.read(info.filename) + f = open(target, 'wb') + try: + f.write(data) + finally: + f.close() + del data + finally: + zip.close() + +def _unpack_tarfile(filename, extract_dir): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise ReadError( + "%s is not a compressed or uncompressed tar file" % filename) + try: + tarobj.extractall(extract_dir) + finally: + tarobj.close() + +_UNPACK_FORMATS = { + 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), + 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), + 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") + } + +if _BZ2_SUPPORTED: + _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], + "bzip2'ed tar-file") + +def _find_unpack_format(filename): + for name, info in _UNPACK_FORMATS.items(): + for extension in info[0]: + if filename.endswith(extension): + return name + return None + +def unpack_archive(filename, extract_dir=None, format=None): + """Unpack an archive. + + `filename` is the name of the archive. + + `extract_dir` is the name of the target directory, where the archive + is unpacked. If not provided, the current working directory is used. + + `format` is the archive format: one of "zip", "tar", or "gztar". Or any + other registered format. If not provided, unpack_archive will use the + filename extension and see if an unpacker was registered for that + extension. + + In case none is found, a ValueError is raised. + """ + if extract_dir is None: + extract_dir = os.getcwd() + + if format is not None: + try: + format_info = _UNPACK_FORMATS[format] + except KeyError: + raise ValueError("Unknown unpack format '{0}'".format(format)) + + func = format_info[1] + func(filename, extract_dir, **dict(format_info[2])) + else: + # we need to look at the registered unpackers supported extensions + format = _find_unpack_format(filename) + if format is None: + raise ReadError("Unknown archive format '{0}'".format(filename)) + + func = _UNPACK_FORMATS[format][1] + kwargs = dict(_UNPACK_FORMATS[format][2]) + func(filename, extract_dir, **kwargs) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg new file mode 100644 index 0000000..1746bd0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg @@ -0,0 +1,84 @@ +[posix_prefix] +# Configuration directories. Some of these come straight out of the +# configure script. They are for implementing the other variables, not to +# be used directly in [resource_locations]. +confdir = /etc +datadir = /usr/share +libdir = /usr/lib +statedir = /var +# User resource directory +local = ~/.local/{distribution.name} + +stdlib = {base}/lib/python{py_version_short} +platstdlib = {platbase}/lib/python{py_version_short} +purelib = {base}/lib/python{py_version_short}/site-packages +platlib = {platbase}/lib/python{py_version_short}/site-packages +include = {base}/include/python{py_version_short}{abiflags} +platinclude = {platbase}/include/python{py_version_short}{abiflags} +data = {base} + +[posix_home] +stdlib = {base}/lib/python +platstdlib = {base}/lib/python +purelib = {base}/lib/python +platlib = {base}/lib/python +include = {base}/include/python +platinclude = {base}/include/python +scripts = {base}/bin +data = {base} + +[nt] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2_home] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[nt_user] +stdlib = {userbase}/Python{py_version_nodot} +platstdlib = {userbase}/Python{py_version_nodot} +purelib = {userbase}/Python{py_version_nodot}/site-packages +platlib = {userbase}/Python{py_version_nodot}/site-packages +include = {userbase}/Python{py_version_nodot}/Include +scripts = {userbase}/Scripts +data = {userbase} + +[posix_user] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[osx_framework_user] +stdlib = {userbase}/lib/python +platstdlib = {userbase}/lib/python +purelib = {userbase}/lib/python/site-packages +platlib = {userbase}/lib/python/site-packages +include = {userbase}/include +scripts = {userbase}/bin +data = {userbase} diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py new file mode 100644 index 0000000..1df3aba --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py @@ -0,0 +1,788 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Access to Python's configuration information.""" + +import codecs +import os +import re +import sys +from os.path import pardir, realpath +try: + import configparser +except ImportError: + import ConfigParser as configparser + + +__all__ = [ + 'get_config_h_filename', + 'get_config_var', + 'get_config_vars', + 'get_makefile_filename', + 'get_path', + 'get_path_names', + 'get_paths', + 'get_platform', + 'get_python_version', + 'get_scheme_names', + 'parse_config_h', +] + + +def _safe_realpath(path): + try: + return realpath(path) + except OSError: + return path + + +if sys.executable: + _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) +else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + _PROJECT_BASE = _safe_realpath(os.getcwd()) + +if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) +# PC/VS7.1 +if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) +# PC/AMD64 +if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) + + +def is_python_build(): + for fn in ("Setup.dist", "Setup.local"): + if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): + return True + return False + +_PYTHON_BUILD = is_python_build() + +_cfg_read = False + +def _ensure_cfg_read(): + global _cfg_read + if not _cfg_read: + from ..resources import finder + backport_package = __name__.rsplit('.', 1)[0] + _finder = finder(backport_package) + _cfgfile = _finder.find('sysconfig.cfg') + assert _cfgfile, 'sysconfig.cfg exists' + with _cfgfile.as_stream() as s: + _SCHEMES.readfp(s) + if _PYTHON_BUILD: + for scheme in ('posix_prefix', 'posix_home'): + _SCHEMES.set(scheme, 'include', '{srcdir}/Include') + _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.') + + _cfg_read = True + + +_SCHEMES = configparser.RawConfigParser() +_VAR_REPL = re.compile(r'\{([^{]*?)\}') + +def _expand_globals(config): + _ensure_cfg_read() + if config.has_section('globals'): + globals = config.items('globals') + else: + globals = tuple() + + sections = config.sections() + for section in sections: + if section == 'globals': + continue + for option, value in globals: + if config.has_option(section, option): + continue + config.set(section, option, value) + config.remove_section('globals') + + # now expanding local variables defined in the cfg file + # + for section in config.sections(): + variables = dict(config.items(section)) + + def _replacer(matchobj): + name = matchobj.group(1) + if name in variables: + return variables[name] + return matchobj.group(0) + + for option, value in config.items(section): + config.set(section, option, _VAR_REPL.sub(_replacer, value)) + +#_expand_globals(_SCHEMES) + + # FIXME don't rely on sys.version here, its format is an implementation detail + # of CPython, use sys.version_info or sys.hexversion +_PY_VERSION = sys.version.split()[0] +_PY_VERSION_SHORT = sys.version[:3] +_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2] +_PREFIX = os.path.normpath(sys.prefix) +_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +_CONFIG_VARS = None +_USER_BASE = None + + +def _subst_vars(path, local_vars): + """In the string `path`, replace tokens like {some.thing} with the + corresponding value from the map `local_vars`. + + If there is no corresponding value, leave the token unchanged. + """ + def _replacer(matchobj): + name = matchobj.group(1) + if name in local_vars: + return local_vars[name] + elif name in os.environ: + return os.environ[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, path) + + +def _extend_dict(target_dict, other_dict): + target_keys = target_dict.keys() + for key, value in other_dict.items(): + if key in target_keys: + continue + target_dict[key] = value + + +def _expand_vars(scheme, vars): + res = {} + if vars is None: + vars = {} + _extend_dict(vars, get_config_vars()) + + for key, value in _SCHEMES.items(scheme): + if os.name in ('posix', 'nt'): + value = os.path.expanduser(value) + res[key] = os.path.normpath(_subst_vars(value, vars)) + return res + + +def format_value(value, vars): + def _replacer(matchobj): + name = matchobj.group(1) + if name in vars: + return vars[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, value) + + +def _get_default_scheme(): + if os.name == 'posix': + # the default scheme for posix is posix_prefix + return 'posix_prefix' + return os.name + + +def _getuserbase(): + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + # what about 'os2emx', 'riscos' ? + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + return env_base + else: + return joinuser(base, "Python") + + if sys.platform == "darwin": + framework = get_config_var("PYTHONFRAMEWORK") + if framework: + if env_base: + return env_base + else: + return joinuser("~", "Library", framework, "%d.%d" % + sys.version_info[:2]) + + if env_base: + return env_base + else: + return joinuser("~", ".local") + + +def _parse_makefile(filename, vars=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + # Regexes needed for parsing Makefile (and similar syntaxes, + # like old-style Setup files). + _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") + _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") + _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + + if vars is None: + vars = {} + done = {} + notdone = {} + + with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f: + lines = f.readlines() + + for line in lines: + if line.startswith('#') or line.strip() == '': + continue + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m is not None: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if (name.startswith('PY_') and + name[3:] in renamed_variables): + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + + else: + done[n] = item = "" + + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: + value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + variables.remove(name) + + if (name.startswith('PY_') and + name[3:] in renamed_variables): + + name = name[3:] + if name not in done: + done[name] = value + + else: + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value + variables.remove(name) + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + vars.update(done) + return vars + + +def get_makefile_filename(): + """Return the path of the Makefile.""" + if _PYTHON_BUILD: + return os.path.join(_PROJECT_BASE, "Makefile") + if hasattr(sys, 'abiflags'): + config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags) + else: + config_dir_name = 'config' + return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') + + +def _init_posix(vars): + """Initialize the module as appropriate for POSIX systems.""" + # load the installed Makefile: + makefile = get_makefile_filename() + try: + _parse_makefile(makefile, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % makefile + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # load the installed pyconfig.h: + config_h = get_config_h_filename() + try: + with open(config_h) as f: + parse_config_h(f, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % config_h + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # On AIX, there are wrong paths to the linker scripts in the Makefile + # -- these paths are relative to the Python source, but when installed + # the scripts are in another directory. + if _PYTHON_BUILD: + vars['LDSHARED'] = vars['BLDSHARED'] + + +def _init_non_posix(vars): + """Initialize the module as appropriate for NT""" + # set basic install directories + vars['LIBDEST'] = get_path('stdlib') + vars['BINLIBDEST'] = get_path('platstdlib') + vars['INCLUDEPY'] = get_path('include') + vars['SO'] = '.pyd' + vars['EXE'] = '.exe' + vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT + vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + +# +# public APIs +# + + +def parse_config_h(fp, vars=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if vars is None: + vars = {} + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + + while True: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: + v = int(v) + except ValueError: + pass + vars[n] = v + else: + m = undef_rx.match(line) + if m: + vars[m.group(1)] = 0 + return vars + + +def get_config_h_filename(): + """Return the path of pyconfig.h.""" + if _PYTHON_BUILD: + if os.name == "nt": + inc_dir = os.path.join(_PROJECT_BASE, "PC") + else: + inc_dir = _PROJECT_BASE + else: + inc_dir = get_path('platinclude') + return os.path.join(inc_dir, 'pyconfig.h') + + +def get_scheme_names(): + """Return a tuple containing the schemes names.""" + return tuple(sorted(_SCHEMES.sections())) + + +def get_path_names(): + """Return a tuple containing the paths names.""" + # xxx see if we want a static list + return _SCHEMES.options('posix_prefix') + + +def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): + """Return a mapping containing an install scheme. + + ``scheme`` is the install scheme name. If not provided, it will + return the default scheme for the current platform. + """ + _ensure_cfg_read() + if expand: + return _expand_vars(scheme, vars) + else: + return dict(_SCHEMES.items(scheme)) + + +def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): + """Return a path corresponding to the scheme. + + ``scheme`` is the install scheme name. + """ + return get_paths(scheme, vars, expand)[name] + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. + + On Unix, this means every variable defined in Python's installed Makefile; + On Windows and Mac OS it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _CONFIG_VARS + if _CONFIG_VARS is None: + _CONFIG_VARS = {} + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # distutils2 module. + _CONFIG_VARS['prefix'] = _PREFIX + _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX + _CONFIG_VARS['py_version'] = _PY_VERSION + _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT + _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] + _CONFIG_VARS['base'] = _PREFIX + _CONFIG_VARS['platbase'] = _EXEC_PREFIX + _CONFIG_VARS['projectbase'] = _PROJECT_BASE + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = '' + + if os.name in ('nt', 'os2'): + _init_non_posix(_CONFIG_VARS) + if os.name == 'posix': + _init_posix(_CONFIG_VARS) + # Setting 'userbase' is done below the call to the + # init function to enable using 'get_config_var' in + # the init-function. + if sys.version >= '2.6': + _CONFIG_VARS['userbase'] = _getuserbase() + + if 'srcdir' not in _CONFIG_VARS: + _CONFIG_VARS['srcdir'] = _PROJECT_BASE + else: + _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) + + # Convert srcdir into an absolute path if it appears necessary. + # Normally it is relative to the build directory. However, during + # testing, for example, we might be running a non-installed python + # from a different directory. + if _PYTHON_BUILD and os.name == "posix": + base = _PROJECT_BASE + try: + cwd = os.getcwd() + except OSError: + cwd = None + if (not os.path.isabs(_CONFIG_VARS['srcdir']) and + base != cwd): + # srcdir is relative and we are not in the same directory + # as the executable. Assume executable is in the build + # directory and make srcdir absolute. + srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) + _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) + + if sys.platform == 'darwin': + kernel_version = os.uname()[2] # Kernel version (8.4.3) + major_version = int(kernel_version.split('.')[0]) + + if major_version < 8: + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _CONFIG_VARS[key] = flags + else: + # Allow the user to override the architecture flags using + # an environment variable. + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _CONFIG_VARS[key] = flags + + # If we're on OSX 10.5 or later and the user tries to + # compiles an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. + # + # The major usecase for this is users using a Python.org + # binary installer on OSX 10.6: that installer uses + # the 10.4u SDK, but that SDK is not installed by default + # when you install Xcode. + # + CFLAGS = _CONFIG_VARS.get('CFLAGS', '') + m = re.search(r'-isysroot\s+(\S+)', CFLAGS) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-isysroot\s+\S+(\s|$)', ' ', flags) + _CONFIG_VARS[key] = flags + + if args: + vals = [] + for name in args: + vals.append(_CONFIG_VARS.get(name)) + return vals + else: + return _CONFIG_VARS + + +def get_config_var(name): + """Return the value of a single variable using the dictionary returned by + 'get_config_vars()'. + + Equivalent to get_config_vars().get(name) + """ + return get_config_vars().get(name) + + +def get_platform(): + """Return a string that identifies the current platform. + + This is used mainly to distinguish platform-specific build directories and + platform-specific built distributions. Typically includes the OS name + and version and the architecture (as supplied by 'os.uname()'), + although the exact information included depends on the OS; eg. for IRIX + the architecture isn't particularly important (IRIX only runs on SGI + hardware), but for Linux the kernel version isn't particularly + important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + irix-5.3 + irix64-6.2 + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win-ia64 (64bit Windows on Itanium) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + """ + if os.name == 'nt': + # sniff sys.version for architecture. + prefix = " bit (" + i = sys.version.find(prefix) + if i == -1: + return sys.platform + j = sys.version.find(")", i) + look = sys.version[i+len(prefix):j].lower() + if look == 'amd64': + return 'win-amd64' + if look == 'itanium': + return 'win-ia64' + return sys.platform + + if os.name != "posix" or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + osname, host, release, version, machine = os.uname() + + # Convert the OS name to lowercase, remove '/' characters + # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname[:5] == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = "%d.%s" % (int(release[0]) - 3, release[2:]) + # fall through to standard osname-release-machine representation + elif osname[:4] == "irix": # could be "irix64"! + return "%s-%s" % (osname, release) + elif osname[:3] == "aix": + return "%s-%s.%s" % (osname, version, release) + elif osname[:6] == "cygwin": + osname = "cygwin" + rel_re = re.compile(r'[\d.]+') + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + # + # For our purposes, we'll assume that the system version from + # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set + # to. This makes the compatibility story a bit more sane because the + # machine is going to compile and link as if it were + # MACOSX_DEPLOYMENT_TARGET. + cfgvars = get_config_vars() + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + + if True: + # Always calculate the release of the running machine, + # needed to determine if we can build fat binaries or not. + + macrelease = macver + # Get the system version. Reading this plist is a documented + # way to get the system version (see the documentation for + # the Gestalt Manager) + try: + f = open('/System/Library/CoreServices/SystemVersion.plist') + except IOError: + # We're on a plain darwin box, fall back to the default + # behaviour. + pass + else: + try: + m = re.search(r'<key>ProductUserVisibleVersion</key>\s*' + r'<string>(.*?)</string>', f.read()) + finally: + f.close() + if m is not None: + macrelease = '.'.join(m.group(1).split('.')[:2]) + # else: fall back to the default behaviour + + if not macver: + macver = macrelease + + if macver: + release = macver + osname = "macosx" + + if ((macrelease + '.') >= '10.4.' and + '-arch' in get_config_vars().get('CFLAGS', '').strip()): + # The universal build will build fat binaries, but not on + # systems before 10.4 + # + # Try to detect 4-way universal builds, those have machine-type + # 'universal' instead of 'fat'. + + machine = 'fat' + cflags = get_config_vars().get('CFLAGS') + + archs = re.findall(r'-arch\s+(\S+)', cflags) + archs = tuple(sorted(set(archs))) + + if len(archs) == 1: + machine = archs[0] + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): + machine = 'intel' + elif archs == ('i386', 'ppc', 'x86_64'): + machine = 'fat3' + elif archs == ('ppc64', 'x86_64'): + machine = 'fat64' + elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): + machine = 'universal' + else: + raise ValueError( + "Don't know machine value for archs=%r" % (archs,)) + + elif machine == 'i386': + # On OSX the machine type returned by uname is always the + # 32-bit variant, even if the executable architecture is + # the 64-bit variant + if sys.maxsize >= 2**32: + machine = 'x86_64' + + elif machine in ('PowerPC', 'Power_Macintosh'): + # Pick a sane name for the PPC architecture. + # See 'i386' case + if sys.maxsize >= 2**32: + machine = 'ppc64' + else: + machine = 'ppc' + + return "%s-%s-%s" % (osname, release, machine) + + +def get_python_version(): + return _PY_VERSION_SHORT + + +def _print_dict(title, data): + for index, (key, value) in enumerate(sorted(data.items())): + if index == 0: + print('%s: ' % (title)) + print('\t%s = "%s"' % (key, value)) + + +def _main(): + """Display all information sysconfig detains.""" + print('Platform: "%s"' % get_platform()) + print('Python version: "%s"' % get_python_version()) + print('Current installation scheme: "%s"' % _get_default_scheme()) + print() + _print_dict('Paths', get_paths()) + print() + _print_dict('Variables', get_config_vars()) + + +if __name__ == '__main__': + _main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py new file mode 100644 index 0000000..d66d856 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py @@ -0,0 +1,2607 @@ +#------------------------------------------------------------------- +# tarfile.py +#------------------------------------------------------------------- +# Copyright (C) 2002 Lars Gustaebel <lars@gustaebel.de> +# All rights reserved. +# +# 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. +# +from __future__ import print_function + +"""Read from and write to tar format archives. +""" + +__version__ = "$Revision$" + +version = "0.9.0" +__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" +__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" +__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" +__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." + +#--------- +# Imports +#--------- +import sys +import os +import stat +import errno +import time +import struct +import copy +import re + +try: + import grp, pwd +except ImportError: + grp = pwd = None + +# os.symlink on Windows prior to 6.0 raises NotImplementedError +symlink_exception = (AttributeError, NotImplementedError) +try: + # WindowsError (1314) will be raised if the caller does not hold the + # SeCreateSymbolicLinkPrivilege privilege + symlink_exception += (WindowsError,) +except NameError: + pass + +# from tarfile import * +__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] + +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins + +_open = builtins.open # Since 'open' is TarFile.open + +#--------------------------------------------------------- +# tar constants +#--------------------------------------------------------- +NUL = b"\0" # the null character +BLOCKSIZE = 512 # length of processing blocks +RECORDSIZE = BLOCKSIZE * 20 # length of records +GNU_MAGIC = b"ustar \0" # magic gnu tar string +POSIX_MAGIC = b"ustar\x0000" # magic posix tar string + +LENGTH_NAME = 100 # maximum length of a filename +LENGTH_LINK = 100 # maximum length of a linkname +LENGTH_PREFIX = 155 # maximum length of the prefix field + +REGTYPE = b"0" # regular file +AREGTYPE = b"\0" # regular file +LNKTYPE = b"1" # link (inside tarfile) +SYMTYPE = b"2" # symbolic link +CHRTYPE = b"3" # character special device +BLKTYPE = b"4" # block special device +DIRTYPE = b"5" # directory +FIFOTYPE = b"6" # fifo special device +CONTTYPE = b"7" # contiguous file + +GNUTYPE_LONGNAME = b"L" # GNU tar longname +GNUTYPE_LONGLINK = b"K" # GNU tar longlink +GNUTYPE_SPARSE = b"S" # GNU tar sparse file + +XHDTYPE = b"x" # POSIX.1-2001 extended header +XGLTYPE = b"g" # POSIX.1-2001 global header +SOLARIS_XHDTYPE = b"X" # Solaris extended header + +USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format +GNU_FORMAT = 1 # GNU tar format +PAX_FORMAT = 2 # POSIX.1-2001 (pax) format +DEFAULT_FORMAT = GNU_FORMAT + +#--------------------------------------------------------- +# tarfile constants +#--------------------------------------------------------- +# File types that tarfile supports: +SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, + SYMTYPE, DIRTYPE, FIFOTYPE, + CONTTYPE, CHRTYPE, BLKTYPE, + GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# File types that will be treated as a regular file. +REGULAR_TYPES = (REGTYPE, AREGTYPE, + CONTTYPE, GNUTYPE_SPARSE) + +# File types that are part of the GNU tar format. +GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# Fields from a pax header that override a TarInfo attribute. +PAX_FIELDS = ("path", "linkpath", "size", "mtime", + "uid", "gid", "uname", "gname") + +# Fields from a pax header that are affected by hdrcharset. +PAX_NAME_FIELDS = set(("path", "linkpath", "uname", "gname")) + +# Fields in a pax header that are numbers, all other fields +# are treated as strings. +PAX_NUMBER_FIELDS = { + "atime": float, + "ctime": float, + "mtime": float, + "uid": int, + "gid": int, + "size": int +} + +#--------------------------------------------------------- +# Bits used in the mode field, values in octal. +#--------------------------------------------------------- +S_IFLNK = 0o120000 # symbolic link +S_IFREG = 0o100000 # regular file +S_IFBLK = 0o060000 # block device +S_IFDIR = 0o040000 # directory +S_IFCHR = 0o020000 # character device +S_IFIFO = 0o010000 # fifo + +TSUID = 0o4000 # set UID on execution +TSGID = 0o2000 # set GID on execution +TSVTX = 0o1000 # reserved + +TUREAD = 0o400 # read by owner +TUWRITE = 0o200 # write by owner +TUEXEC = 0o100 # execute/search by owner +TGREAD = 0o040 # read by group +TGWRITE = 0o020 # write by group +TGEXEC = 0o010 # execute/search by group +TOREAD = 0o004 # read by other +TOWRITE = 0o002 # write by other +TOEXEC = 0o001 # execute/search by other + +#--------------------------------------------------------- +# initialization +#--------------------------------------------------------- +if os.name in ("nt", "ce"): + ENCODING = "utf-8" +else: + ENCODING = sys.getfilesystemencoding() + +#--------------------------------------------------------- +# Some useful functions +#--------------------------------------------------------- + +def stn(s, length, encoding, errors): + """Convert a string to a null-terminated bytes object. + """ + s = s.encode(encoding, errors) + return s[:length] + (length - len(s)) * NUL + +def nts(s, encoding, errors): + """Convert a null-terminated bytes object to a string. + """ + p = s.find(b"\0") + if p != -1: + s = s[:p] + return s.decode(encoding, errors) + +def nti(s): + """Convert a number field to a python number. + """ + # There are two possible encodings for a number field, see + # itn() below. + if s[0] != chr(0o200): + try: + n = int(nts(s, "ascii", "strict") or "0", 8) + except ValueError: + raise InvalidHeaderError("invalid header") + else: + n = 0 + for i in range(len(s) - 1): + n <<= 8 + n += ord(s[i + 1]) + return n + +def itn(n, digits=8, format=DEFAULT_FORMAT): + """Convert a python number to a number field. + """ + # POSIX 1003.1-1988 requires numbers to be encoded as a string of + # octal digits followed by a null-byte, this allows values up to + # (8**(digits-1))-1. GNU tar allows storing numbers greater than + # that if necessary. A leading 0o200 byte indicates this particular + # encoding, the following digits-1 bytes are a big-endian + # representation. This allows values up to (256**(digits-1))-1. + if 0 <= n < 8 ** (digits - 1): + s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL + else: + if format != GNU_FORMAT or n >= 256 ** (digits - 1): + raise ValueError("overflow in number field") + + if n < 0: + # XXX We mimic GNU tar's behaviour with negative numbers, + # this could raise OverflowError. + n = struct.unpack("L", struct.pack("l", n))[0] + + s = bytearray() + for i in range(digits - 1): + s.insert(0, n & 0o377) + n >>= 8 + s.insert(0, 0o200) + return s + +def calc_chksums(buf): + """Calculate the checksum for a member's header by summing up all + characters except for the chksum field which is treated as if + it was filled with spaces. According to the GNU tar sources, + some tars (Sun and NeXT) calculate chksum with signed char, + which will be different if there are chars in the buffer with + the high bit set. So we calculate two checksums, unsigned and + signed. + """ + unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) + signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) + return unsigned_chksum, signed_chksum + +def copyfileobj(src, dst, length=None): + """Copy length bytes from fileobj src to fileobj dst. + If length is None, copy the entire content. + """ + if length == 0: + return + if length is None: + while True: + buf = src.read(16*1024) + if not buf: + break + dst.write(buf) + return + + BUFSIZE = 16 * 1024 + blocks, remainder = divmod(length, BUFSIZE) + for b in range(blocks): + buf = src.read(BUFSIZE) + if len(buf) < BUFSIZE: + raise IOError("end of file reached") + dst.write(buf) + + if remainder != 0: + buf = src.read(remainder) + if len(buf) < remainder: + raise IOError("end of file reached") + dst.write(buf) + return + +filemode_table = ( + ((S_IFLNK, "l"), + (S_IFREG, "-"), + (S_IFBLK, "b"), + (S_IFDIR, "d"), + (S_IFCHR, "c"), + (S_IFIFO, "p")), + + ((TUREAD, "r"),), + ((TUWRITE, "w"),), + ((TUEXEC|TSUID, "s"), + (TSUID, "S"), + (TUEXEC, "x")), + + ((TGREAD, "r"),), + ((TGWRITE, "w"),), + ((TGEXEC|TSGID, "s"), + (TSGID, "S"), + (TGEXEC, "x")), + + ((TOREAD, "r"),), + ((TOWRITE, "w"),), + ((TOEXEC|TSVTX, "t"), + (TSVTX, "T"), + (TOEXEC, "x")) +) + +def filemode(mode): + """Convert a file's mode to a string of the form + -rwxrwxrwx. + Used by TarFile.list() + """ + perm = [] + for table in filemode_table: + for bit, char in table: + if mode & bit == bit: + perm.append(char) + break + else: + perm.append("-") + return "".join(perm) + +class TarError(Exception): + """Base exception.""" + pass +class ExtractError(TarError): + """General exception for extract errors.""" + pass +class ReadError(TarError): + """Exception for unreadable tar archives.""" + pass +class CompressionError(TarError): + """Exception for unavailable compression methods.""" + pass +class StreamError(TarError): + """Exception for unsupported operations on stream-like TarFiles.""" + pass +class HeaderError(TarError): + """Base exception for header errors.""" + pass +class EmptyHeaderError(HeaderError): + """Exception for empty headers.""" + pass +class TruncatedHeaderError(HeaderError): + """Exception for truncated headers.""" + pass +class EOFHeaderError(HeaderError): + """Exception for end of file headers.""" + pass +class InvalidHeaderError(HeaderError): + """Exception for invalid headers.""" + pass +class SubsequentHeaderError(HeaderError): + """Exception for missing and invalid extended headers.""" + pass + +#--------------------------- +# internal stream interface +#--------------------------- +class _LowLevelFile(object): + """Low-level file object. Supports reading and writing. + It is used instead of a regular file object for streaming + access. + """ + + def __init__(self, name, mode): + mode = { + "r": os.O_RDONLY, + "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + }[mode] + if hasattr(os, "O_BINARY"): + mode |= os.O_BINARY + self.fd = os.open(name, mode, 0o666) + + def close(self): + os.close(self.fd) + + def read(self, size): + return os.read(self.fd, size) + + def write(self, s): + os.write(self.fd, s) + +class _Stream(object): + """Class that serves as an adapter between TarFile and + a stream-like object. The stream-like object only + needs to have a read() or write() method and is accessed + blockwise. Use of gzip or bzip2 compression is possible. + A stream-like object could be for example: sys.stdin, + sys.stdout, a socket, a tape device etc. + + _Stream is intended to be used only internally. + """ + + def __init__(self, name, mode, comptype, fileobj, bufsize): + """Construct a _Stream object. + """ + self._extfileobj = True + if fileobj is None: + fileobj = _LowLevelFile(name, mode) + self._extfileobj = False + + if comptype == '*': + # Enable transparent compression detection for the + # stream interface + fileobj = _StreamProxy(fileobj) + comptype = fileobj.getcomptype() + + self.name = name or "" + self.mode = mode + self.comptype = comptype + self.fileobj = fileobj + self.bufsize = bufsize + self.buf = b"" + self.pos = 0 + self.closed = False + + try: + if comptype == "gz": + try: + import zlib + except ImportError: + raise CompressionError("zlib module is not available") + self.zlib = zlib + self.crc = zlib.crc32(b"") + if mode == "r": + self._init_read_gz() + else: + self._init_write_gz() + + if comptype == "bz2": + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + if mode == "r": + self.dbuf = b"" + self.cmp = bz2.BZ2Decompressor() + else: + self.cmp = bz2.BZ2Compressor() + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + def __del__(self): + if hasattr(self, "closed") and not self.closed: + self.close() + + def _init_write_gz(self): + """Initialize for writing with gzip compression. + """ + self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, + -self.zlib.MAX_WBITS, + self.zlib.DEF_MEM_LEVEL, + 0) + timestamp = struct.pack("<L", int(time.time())) + self.__write(b"\037\213\010\010" + timestamp + b"\002\377") + if self.name.endswith(".gz"): + self.name = self.name[:-3] + # RFC1952 says we must use ISO-8859-1 for the FNAME field. + self.__write(self.name.encode("iso-8859-1", "replace") + NUL) + + def write(self, s): + """Write string s to the stream. + """ + if self.comptype == "gz": + self.crc = self.zlib.crc32(s, self.crc) + self.pos += len(s) + if self.comptype != "tar": + s = self.cmp.compress(s) + self.__write(s) + + def __write(self, s): + """Write string s to the stream if a whole new block + is ready to be written. + """ + self.buf += s + while len(self.buf) > self.bufsize: + self.fileobj.write(self.buf[:self.bufsize]) + self.buf = self.buf[self.bufsize:] + + def close(self): + """Close the _Stream object. No operation should be + done on it afterwards. + """ + if self.closed: + return + + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() + + if self.mode == "w" and self.buf: + self.fileobj.write(self.buf) + self.buf = b"" + if self.comptype == "gz": + # The native zlib crc is an unsigned 32-bit integer, but + # the Python wrapper implicitly casts that to a signed C + # long. So, on a 32-bit box self.crc may "look negative", + # while the same crc on a 64-bit box may "look positive". + # To avoid irksome warnings from the `struct` module, force + # it to look positive on all boxes. + self.fileobj.write(struct.pack("<L", self.crc & 0xffffffff)) + self.fileobj.write(struct.pack("<L", self.pos & 0xffffFFFF)) + + if not self._extfileobj: + self.fileobj.close() + + self.closed = True + + def _init_read_gz(self): + """Initialize for reading a gzip compressed fileobj. + """ + self.cmp = self.zlib.decompressobj(-self.zlib.MAX_WBITS) + self.dbuf = b"" + + # taken from gzip.GzipFile with some alterations + if self.__read(2) != b"\037\213": + raise ReadError("not a gzip file") + if self.__read(1) != b"\010": + raise CompressionError("unsupported compression method") + + flag = ord(self.__read(1)) + self.__read(6) + + if flag & 4: + xlen = ord(self.__read(1)) + 256 * ord(self.__read(1)) + self.read(xlen) + if flag & 8: + while True: + s = self.__read(1) + if not s or s == NUL: + break + if flag & 16: + while True: + s = self.__read(1) + if not s or s == NUL: + break + if flag & 2: + self.__read(2) + + def tell(self): + """Return the stream's file pointer position. + """ + return self.pos + + def seek(self, pos=0): + """Set the stream's file pointer to pos. Negative seeking + is forbidden. + """ + if pos - self.pos >= 0: + blocks, remainder = divmod(pos - self.pos, self.bufsize) + for i in range(blocks): + self.read(self.bufsize) + self.read(remainder) + else: + raise StreamError("seeking backwards is not allowed") + return self.pos + + def read(self, size=None): + """Return the next size number of bytes from the stream. + If size is not defined, return all bytes of the stream + up to EOF. + """ + if size is None: + t = [] + while True: + buf = self._read(self.bufsize) + if not buf: + break + t.append(buf) + buf = "".join(t) + else: + buf = self._read(size) + self.pos += len(buf) + return buf + + def _read(self, size): + """Return size bytes from the stream. + """ + if self.comptype == "tar": + return self.__read(size) + + c = len(self.dbuf) + while c < size: + buf = self.__read(self.bufsize) + if not buf: + break + try: + buf = self.cmp.decompress(buf) + except IOError: + raise ReadError("invalid compressed data") + self.dbuf += buf + c += len(buf) + buf = self.dbuf[:size] + self.dbuf = self.dbuf[size:] + return buf + + def __read(self, size): + """Return size bytes from stream. If internal buffer is empty, + read another block from the stream. + """ + c = len(self.buf) + while c < size: + buf = self.fileobj.read(self.bufsize) + if not buf: + break + self.buf += buf + c += len(buf) + buf = self.buf[:size] + self.buf = self.buf[size:] + return buf +# class _Stream + +class _StreamProxy(object): + """Small proxy class that enables transparent compression + detection for the Stream interface (mode 'r|*'). + """ + + def __init__(self, fileobj): + self.fileobj = fileobj + self.buf = self.fileobj.read(BLOCKSIZE) + + def read(self, size): + self.read = self.fileobj.read + return self.buf + + def getcomptype(self): + if self.buf.startswith(b"\037\213\010"): + return "gz" + if self.buf.startswith(b"BZh91"): + return "bz2" + return "tar" + + def close(self): + self.fileobj.close() +# class StreamProxy + +class _BZ2Proxy(object): + """Small proxy class that enables external file object + support for "r:bz2" and "w:bz2" modes. This is actually + a workaround for a limitation in bz2 module's BZ2File + class which (unlike gzip.GzipFile) has no support for + a file object argument. + """ + + blocksize = 16 * 1024 + + def __init__(self, fileobj, mode): + self.fileobj = fileobj + self.mode = mode + self.name = getattr(self.fileobj, "name", None) + self.init() + + def init(self): + import bz2 + self.pos = 0 + if self.mode == "r": + self.bz2obj = bz2.BZ2Decompressor() + self.fileobj.seek(0) + self.buf = b"" + else: + self.bz2obj = bz2.BZ2Compressor() + + def read(self, size): + x = len(self.buf) + while x < size: + raw = self.fileobj.read(self.blocksize) + if not raw: + break + data = self.bz2obj.decompress(raw) + self.buf += data + x += len(data) + + buf = self.buf[:size] + self.buf = self.buf[size:] + self.pos += len(buf) + return buf + + def seek(self, pos): + if pos < self.pos: + self.init() + self.read(pos - self.pos) + + def tell(self): + return self.pos + + def write(self, data): + self.pos += len(data) + raw = self.bz2obj.compress(data) + self.fileobj.write(raw) + + def close(self): + if self.mode == "w": + raw = self.bz2obj.flush() + self.fileobj.write(raw) +# class _BZ2Proxy + +#------------------------ +# Extraction file object +#------------------------ +class _FileInFile(object): + """A thin wrapper around an existing file object that + provides a part of its data as an individual file + object. + """ + + def __init__(self, fileobj, offset, size, blockinfo=None): + self.fileobj = fileobj + self.offset = offset + self.size = size + self.position = 0 + + if blockinfo is None: + blockinfo = [(0, size)] + + # Construct a map with data and zero blocks. + self.map_index = 0 + self.map = [] + lastpos = 0 + realpos = self.offset + for offset, size in blockinfo: + if offset > lastpos: + self.map.append((False, lastpos, offset, None)) + self.map.append((True, offset, offset + size, realpos)) + realpos += size + lastpos = offset + size + if lastpos < self.size: + self.map.append((False, lastpos, self.size, None)) + + def seekable(self): + if not hasattr(self.fileobj, "seekable"): + # XXX gzip.GzipFile and bz2.BZ2File + return True + return self.fileobj.seekable() + + def tell(self): + """Return the current file position. + """ + return self.position + + def seek(self, position): + """Seek to a position in the file. + """ + self.position = position + + def read(self, size=None): + """Read data from the file. + """ + if size is None: + size = self.size - self.position + else: + size = min(size, self.size - self.position) + + buf = b"" + while size > 0: + while True: + data, start, stop, offset = self.map[self.map_index] + if start <= self.position < stop: + break + else: + self.map_index += 1 + if self.map_index == len(self.map): + self.map_index = 0 + length = min(size, stop - self.position) + if data: + self.fileobj.seek(offset + (self.position - start)) + buf += self.fileobj.read(length) + else: + buf += NUL * length + size -= length + self.position += length + return buf +#class _FileInFile + + +class ExFileObject(object): + """File-like object for reading an archive member. + Is returned by TarFile.extractfile(). + """ + blocksize = 1024 + + def __init__(self, tarfile, tarinfo): + self.fileobj = _FileInFile(tarfile.fileobj, + tarinfo.offset_data, + tarinfo.size, + tarinfo.sparse) + self.name = tarinfo.name + self.mode = "r" + self.closed = False + self.size = tarinfo.size + + self.position = 0 + self.buffer = b"" + + def readable(self): + return True + + def writable(self): + return False + + def seekable(self): + return self.fileobj.seekable() + + def read(self, size=None): + """Read at most size bytes from the file. If size is not + present or None, read all data until EOF is reached. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + buf = b"" + if self.buffer: + if size is None: + buf = self.buffer + self.buffer = b"" + else: + buf = self.buffer[:size] + self.buffer = self.buffer[size:] + + if size is None: + buf += self.fileobj.read() + else: + buf += self.fileobj.read(size - len(buf)) + + self.position += len(buf) + return buf + + # XXX TextIOWrapper uses the read1() method. + read1 = read + + def readline(self, size=-1): + """Read one entire line from the file. If size is present + and non-negative, return a string with at most that + size, which may be an incomplete line. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + while True: + buf = self.fileobj.read(self.blocksize) + self.buffer += buf + if not buf or b"\n" in buf: + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + pos = len(self.buffer) + break + + if size != -1: + pos = min(size, pos) + + buf = self.buffer[:pos] + self.buffer = self.buffer[pos:] + self.position += len(buf) + return buf + + def readlines(self): + """Return a list with all remaining lines. + """ + result = [] + while True: + line = self.readline() + if not line: break + result.append(line) + return result + + def tell(self): + """Return the current file position. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + return self.position + + def seek(self, pos, whence=os.SEEK_SET): + """Seek to a position in the file. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + if whence == os.SEEK_SET: + self.position = min(max(pos, 0), self.size) + elif whence == os.SEEK_CUR: + if pos < 0: + self.position = max(self.position + pos, 0) + else: + self.position = min(self.position + pos, self.size) + elif whence == os.SEEK_END: + self.position = max(min(self.size + pos, self.size), 0) + else: + raise ValueError("Invalid argument") + + self.buffer = b"" + self.fileobj.seek(self.position) + + def close(self): + """Close the file object. + """ + self.closed = True + + def __iter__(self): + """Get an iterator over the file's lines. + """ + while True: + line = self.readline() + if not line: + break + yield line +#class ExFileObject + +#------------------ +# Exported Classes +#------------------ +class TarInfo(object): + """Informational class which holds the details about an + archive member given by a tar header block. + TarInfo objects are returned by TarFile.getmember(), + TarFile.getmembers() and TarFile.gettarinfo() and are + usually created internally. + """ + + __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", + "chksum", "type", "linkname", "uname", "gname", + "devmajor", "devminor", + "offset", "offset_data", "pax_headers", "sparse", + "tarfile", "_sparse_structs", "_link_target") + + def __init__(self, name=""): + """Construct a TarInfo object. name is the optional name + of the member. + """ + self.name = name # member name + self.mode = 0o644 # file permissions + self.uid = 0 # user id + self.gid = 0 # group id + self.size = 0 # file size + self.mtime = 0 # modification time + self.chksum = 0 # header checksum + self.type = REGTYPE # member type + self.linkname = "" # link name + self.uname = "" # user name + self.gname = "" # group name + self.devmajor = 0 # device major number + self.devminor = 0 # device minor number + + self.offset = 0 # the tar header starts here + self.offset_data = 0 # the file's data starts here + + self.sparse = None # sparse member information + self.pax_headers = {} # pax header information + + # In pax headers the "name" and "linkname" field are called + # "path" and "linkpath". + def _getpath(self): + return self.name + def _setpath(self, name): + self.name = name + path = property(_getpath, _setpath) + + def _getlinkpath(self): + return self.linkname + def _setlinkpath(self, linkname): + self.linkname = linkname + linkpath = property(_getlinkpath, _setlinkpath) + + def __repr__(self): + return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) + + def get_info(self): + """Return the TarInfo's attributes as a dictionary. + """ + info = { + "name": self.name, + "mode": self.mode & 0o7777, + "uid": self.uid, + "gid": self.gid, + "size": self.size, + "mtime": self.mtime, + "chksum": self.chksum, + "type": self.type, + "linkname": self.linkname, + "uname": self.uname, + "gname": self.gname, + "devmajor": self.devmajor, + "devminor": self.devminor + } + + if info["type"] == DIRTYPE and not info["name"].endswith("/"): + info["name"] += "/" + + return info + + def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): + """Return a tar header as a string of 512 byte blocks. + """ + info = self.get_info() + + if format == USTAR_FORMAT: + return self.create_ustar_header(info, encoding, errors) + elif format == GNU_FORMAT: + return self.create_gnu_header(info, encoding, errors) + elif format == PAX_FORMAT: + return self.create_pax_header(info, encoding) + else: + raise ValueError("invalid format") + + def create_ustar_header(self, info, encoding, errors): + """Return the object as a ustar header block. + """ + info["magic"] = POSIX_MAGIC + + if len(info["linkname"]) > LENGTH_LINK: + raise ValueError("linkname is too long") + + if len(info["name"]) > LENGTH_NAME: + info["prefix"], info["name"] = self._posix_split_name(info["name"]) + + return self._create_header(info, USTAR_FORMAT, encoding, errors) + + def create_gnu_header(self, info, encoding, errors): + """Return the object as a GNU header block sequence. + """ + info["magic"] = GNU_MAGIC + + buf = b"" + if len(info["linkname"]) > LENGTH_LINK: + buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) + + if len(info["name"]) > LENGTH_NAME: + buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) + + return buf + self._create_header(info, GNU_FORMAT, encoding, errors) + + def create_pax_header(self, info, encoding): + """Return the object as a ustar header block. If it cannot be + represented this way, prepend a pax extended header sequence + with supplement information. + """ + info["magic"] = POSIX_MAGIC + pax_headers = self.pax_headers.copy() + + # Test string fields for values that exceed the field length or cannot + # be represented in ASCII encoding. + for name, hname, length in ( + ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), + ("uname", "uname", 32), ("gname", "gname", 32)): + + if hname in pax_headers: + # The pax header has priority. + continue + + # Try to encode the string as ASCII. + try: + info[name].encode("ascii", "strict") + except UnicodeEncodeError: + pax_headers[hname] = info[name] + continue + + if len(info[name]) > length: + pax_headers[hname] = info[name] + + # Test number fields for values that exceed the field limit or values + # that like to be stored as float. + for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): + if name in pax_headers: + # The pax header has priority. Avoid overflow. + info[name] = 0 + continue + + val = info[name] + if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): + pax_headers[name] = str(val) + info[name] = 0 + + # Create a pax extended header if necessary. + if pax_headers: + buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) + else: + buf = b"" + + return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") + + @classmethod + def create_pax_global_header(cls, pax_headers): + """Return the object as a pax global header block sequence. + """ + return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf8") + + def _posix_split_name(self, name): + """Split a name longer than 100 chars into a prefix + and a name part. + """ + prefix = name[:LENGTH_PREFIX + 1] + while prefix and prefix[-1] != "/": + prefix = prefix[:-1] + + name = name[len(prefix):] + prefix = prefix[:-1] + + if not prefix or len(name) > LENGTH_NAME: + raise ValueError("name is too long") + return prefix, name + + @staticmethod + def _create_header(info, format, encoding, errors): + """Return a header block. info is a dictionary with file + information, format must be one of the *_FORMAT constants. + """ + parts = [ + stn(info.get("name", ""), 100, encoding, errors), + itn(info.get("mode", 0) & 0o7777, 8, format), + itn(info.get("uid", 0), 8, format), + itn(info.get("gid", 0), 8, format), + itn(info.get("size", 0), 12, format), + itn(info.get("mtime", 0), 12, format), + b" ", # checksum field + info.get("type", REGTYPE), + stn(info.get("linkname", ""), 100, encoding, errors), + info.get("magic", POSIX_MAGIC), + stn(info.get("uname", ""), 32, encoding, errors), + stn(info.get("gname", ""), 32, encoding, errors), + itn(info.get("devmajor", 0), 8, format), + itn(info.get("devminor", 0), 8, format), + stn(info.get("prefix", ""), 155, encoding, errors) + ] + + buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) + chksum = calc_chksums(buf[-BLOCKSIZE:])[0] + buf = buf[:-364] + ("%06o\0" % chksum).encode("ascii") + buf[-357:] + return buf + + @staticmethod + def _create_payload(payload): + """Return the string payload filled with zero bytes + up to the next 512 byte border. + """ + blocks, remainder = divmod(len(payload), BLOCKSIZE) + if remainder > 0: + payload += (BLOCKSIZE - remainder) * NUL + return payload + + @classmethod + def _create_gnu_long_header(cls, name, type, encoding, errors): + """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence + for name. + """ + name = name.encode(encoding, errors) + NUL + + info = {} + info["name"] = "././@LongLink" + info["type"] = type + info["size"] = len(name) + info["magic"] = GNU_MAGIC + + # create extended header + name blocks. + return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ + cls._create_payload(name) + + @classmethod + def _create_pax_generic_header(cls, pax_headers, type, encoding): + """Return a POSIX.1-2008 extended or global header sequence + that contains a list of keyword, value pairs. The values + must be strings. + """ + # Check if one of the fields contains surrogate characters and thereby + # forces hdrcharset=BINARY, see _proc_pax() for more information. + binary = False + for keyword, value in pax_headers.items(): + try: + value.encode("utf8", "strict") + except UnicodeEncodeError: + binary = True + break + + records = b"" + if binary: + # Put the hdrcharset field at the beginning of the header. + records += b"21 hdrcharset=BINARY\n" + + for keyword, value in pax_headers.items(): + keyword = keyword.encode("utf8") + if binary: + # Try to restore the original byte representation of `value'. + # Needless to say, that the encoding must match the string. + value = value.encode(encoding, "surrogateescape") + else: + value = value.encode("utf8") + + l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' + n = p = 0 + while True: + n = l + len(str(p)) + if n == p: + break + p = n + records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" + + # We use a hardcoded "././@PaxHeader" name like star does + # instead of the one that POSIX recommends. + info = {} + info["name"] = "././@PaxHeader" + info["type"] = type + info["size"] = len(records) + info["magic"] = POSIX_MAGIC + + # Create pax header + record blocks. + return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ + cls._create_payload(records) + + @classmethod + def frombuf(cls, buf, encoding, errors): + """Construct a TarInfo object from a 512 byte bytes object. + """ + if len(buf) == 0: + raise EmptyHeaderError("empty header") + if len(buf) != BLOCKSIZE: + raise TruncatedHeaderError("truncated header") + if buf.count(NUL) == BLOCKSIZE: + raise EOFHeaderError("end of file header") + + chksum = nti(buf[148:156]) + if chksum not in calc_chksums(buf): + raise InvalidHeaderError("bad checksum") + + obj = cls() + obj.name = nts(buf[0:100], encoding, errors) + obj.mode = nti(buf[100:108]) + obj.uid = nti(buf[108:116]) + obj.gid = nti(buf[116:124]) + obj.size = nti(buf[124:136]) + obj.mtime = nti(buf[136:148]) + obj.chksum = chksum + obj.type = buf[156:157] + obj.linkname = nts(buf[157:257], encoding, errors) + obj.uname = nts(buf[265:297], encoding, errors) + obj.gname = nts(buf[297:329], encoding, errors) + obj.devmajor = nti(buf[329:337]) + obj.devminor = nti(buf[337:345]) + prefix = nts(buf[345:500], encoding, errors) + + # Old V7 tar format represents a directory as a regular + # file with a trailing slash. + if obj.type == AREGTYPE and obj.name.endswith("/"): + obj.type = DIRTYPE + + # The old GNU sparse format occupies some of the unused + # space in the buffer for up to 4 sparse structures. + # Save the them for later processing in _proc_sparse(). + if obj.type == GNUTYPE_SPARSE: + pos = 386 + structs = [] + for i in range(4): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[482]) + origsize = nti(buf[483:495]) + obj._sparse_structs = (structs, isextended, origsize) + + # Remove redundant slashes from directories. + if obj.isdir(): + obj.name = obj.name.rstrip("/") + + # Reconstruct a ustar longname. + if prefix and obj.type not in GNU_TYPES: + obj.name = prefix + "/" + obj.name + return obj + + @classmethod + def fromtarfile(cls, tarfile): + """Return the next TarInfo object from TarFile object + tarfile. + """ + buf = tarfile.fileobj.read(BLOCKSIZE) + obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) + obj.offset = tarfile.fileobj.tell() - BLOCKSIZE + return obj._proc_member(tarfile) + + #-------------------------------------------------------------------------- + # The following are methods that are called depending on the type of a + # member. The entry point is _proc_member() which can be overridden in a + # subclass to add custom _proc_*() methods. A _proc_*() method MUST + # implement the following + # operations: + # 1. Set self.offset_data to the position where the data blocks begin, + # if there is data that follows. + # 2. Set tarfile.offset to the position where the next member's header will + # begin. + # 3. Return self or another valid TarInfo object. + def _proc_member(self, tarfile): + """Choose the right processing method depending on + the type and call it. + """ + if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): + return self._proc_gnulong(tarfile) + elif self.type == GNUTYPE_SPARSE: + return self._proc_sparse(tarfile) + elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): + return self._proc_pax(tarfile) + else: + return self._proc_builtin(tarfile) + + def _proc_builtin(self, tarfile): + """Process a builtin type or an unknown type which + will be treated as a regular file. + """ + self.offset_data = tarfile.fileobj.tell() + offset = self.offset_data + if self.isreg() or self.type not in SUPPORTED_TYPES: + # Skip the following data blocks. + offset += self._block(self.size) + tarfile.offset = offset + + # Patch the TarInfo object with saved global + # header information. + self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) + + return self + + def _proc_gnulong(self, tarfile): + """Process the blocks that hold a GNU longname + or longlink member. + """ + buf = tarfile.fileobj.read(self._block(self.size)) + + # Fetch the next header and process it. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Patch the TarInfo object from the next header with + # the longname information. + next.offset = self.offset + if self.type == GNUTYPE_LONGNAME: + next.name = nts(buf, tarfile.encoding, tarfile.errors) + elif self.type == GNUTYPE_LONGLINK: + next.linkname = nts(buf, tarfile.encoding, tarfile.errors) + + return next + + def _proc_sparse(self, tarfile): + """Process a GNU sparse header plus extra headers. + """ + # We already collected some sparse structures in frombuf(). + structs, isextended, origsize = self._sparse_structs + del self._sparse_structs + + # Collect sparse structures from extended header blocks. + while isextended: + buf = tarfile.fileobj.read(BLOCKSIZE) + pos = 0 + for i in range(21): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + if offset and numbytes: + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[504]) + self.sparse = structs + + self.offset_data = tarfile.fileobj.tell() + tarfile.offset = self.offset_data + self._block(self.size) + self.size = origsize + return self + + def _proc_pax(self, tarfile): + """Process an extended or global header as described in + POSIX.1-2008. + """ + # Read the header information. + buf = tarfile.fileobj.read(self._block(self.size)) + + # A pax header stores supplemental information for either + # the following file (extended) or all following files + # (global). + if self.type == XGLTYPE: + pax_headers = tarfile.pax_headers + else: + pax_headers = tarfile.pax_headers.copy() + + # Check if the pax header contains a hdrcharset field. This tells us + # the encoding of the path, linkpath, uname and gname fields. Normally, + # these fields are UTF-8 encoded but since POSIX.1-2008 tar + # implementations are allowed to store them as raw binary strings if + # the translation to UTF-8 fails. + match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) + if match is not None: + pax_headers["hdrcharset"] = match.group(1).decode("utf8") + + # For the time being, we don't care about anything other than "BINARY". + # The only other value that is currently allowed by the standard is + # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. + hdrcharset = pax_headers.get("hdrcharset") + if hdrcharset == "BINARY": + encoding = tarfile.encoding + else: + encoding = "utf8" + + # Parse pax header information. A record looks like that: + # "%d %s=%s\n" % (length, keyword, value). length is the size + # of the complete record including the length field itself and + # the newline. keyword and value are both UTF-8 encoded strings. + regex = re.compile(br"(\d+) ([^=]+)=") + pos = 0 + while True: + match = regex.match(buf, pos) + if not match: + break + + length, keyword = match.groups() + length = int(length) + value = buf[match.end(2) + 1:match.start(1) + length - 1] + + # Normally, we could just use "utf8" as the encoding and "strict" + # as the error handler, but we better not take the risk. For + # example, GNU tar <= 1.23 is known to store filenames it cannot + # translate to UTF-8 as raw strings (unfortunately without a + # hdrcharset=BINARY header). + # We first try the strict standard encoding, and if that fails we + # fall back on the user's encoding and error handler. + keyword = self._decode_pax_field(keyword, "utf8", "utf8", + tarfile.errors) + if keyword in PAX_NAME_FIELDS: + value = self._decode_pax_field(value, encoding, tarfile.encoding, + tarfile.errors) + else: + value = self._decode_pax_field(value, "utf8", "utf8", + tarfile.errors) + + pax_headers[keyword] = value + pos += length + + # Fetch the next header. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Process GNU sparse information. + if "GNU.sparse.map" in pax_headers: + # GNU extended sparse format version 0.1. + self._proc_gnusparse_01(next, pax_headers) + + elif "GNU.sparse.size" in pax_headers: + # GNU extended sparse format version 0.0. + self._proc_gnusparse_00(next, pax_headers, buf) + + elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": + # GNU extended sparse format version 1.0. + self._proc_gnusparse_10(next, pax_headers, tarfile) + + if self.type in (XHDTYPE, SOLARIS_XHDTYPE): + # Patch the TarInfo object with the extended header info. + next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) + next.offset = self.offset + + if "size" in pax_headers: + # If the extended header replaces the size field, + # we need to recalculate the offset where the next + # header starts. + offset = next.offset_data + if next.isreg() or next.type not in SUPPORTED_TYPES: + offset += next._block(next.size) + tarfile.offset = offset + + return next + + def _proc_gnusparse_00(self, next, pax_headers, buf): + """Process a GNU tar extended sparse header, version 0.0. + """ + offsets = [] + for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): + offsets.append(int(match.group(1))) + numbytes = [] + for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): + numbytes.append(int(match.group(1))) + next.sparse = list(zip(offsets, numbytes)) + + def _proc_gnusparse_01(self, next, pax_headers): + """Process a GNU tar extended sparse header, version 0.1. + """ + sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _proc_gnusparse_10(self, next, pax_headers, tarfile): + """Process a GNU tar extended sparse header, version 1.0. + """ + fields = None + sparse = [] + buf = tarfile.fileobj.read(BLOCKSIZE) + fields, buf = buf.split(b"\n", 1) + fields = int(fields) + while len(sparse) < fields * 2: + if b"\n" not in buf: + buf += tarfile.fileobj.read(BLOCKSIZE) + number, buf = buf.split(b"\n", 1) + sparse.append(int(number)) + next.offset_data = tarfile.fileobj.tell() + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _apply_pax_info(self, pax_headers, encoding, errors): + """Replace fields with supplemental information from a previous + pax extended or global header. + """ + for keyword, value in pax_headers.items(): + if keyword == "GNU.sparse.name": + setattr(self, "path", value) + elif keyword == "GNU.sparse.size": + setattr(self, "size", int(value)) + elif keyword == "GNU.sparse.realsize": + setattr(self, "size", int(value)) + elif keyword in PAX_FIELDS: + if keyword in PAX_NUMBER_FIELDS: + try: + value = PAX_NUMBER_FIELDS[keyword](value) + except ValueError: + value = 0 + if keyword == "path": + value = value.rstrip("/") + setattr(self, keyword, value) + + self.pax_headers = pax_headers.copy() + + def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): + """Decode a single field from a pax record. + """ + try: + return value.decode(encoding, "strict") + except UnicodeDecodeError: + return value.decode(fallback_encoding, fallback_errors) + + def _block(self, count): + """Round up a byte count by BLOCKSIZE and return it, + e.g. _block(834) => 1024. + """ + blocks, remainder = divmod(count, BLOCKSIZE) + if remainder: + blocks += 1 + return blocks * BLOCKSIZE + + def isreg(self): + return self.type in REGULAR_TYPES + def isfile(self): + return self.isreg() + def isdir(self): + return self.type == DIRTYPE + def issym(self): + return self.type == SYMTYPE + def islnk(self): + return self.type == LNKTYPE + def ischr(self): + return self.type == CHRTYPE + def isblk(self): + return self.type == BLKTYPE + def isfifo(self): + return self.type == FIFOTYPE + def issparse(self): + return self.sparse is not None + def isdev(self): + return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) +# class TarInfo + +class TarFile(object): + """The TarFile Class provides an interface to tar archives. + """ + + debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) + + dereference = False # If true, add content of linked file to the + # tar file, else the link. + + ignore_zeros = False # If true, skips empty or invalid blocks and + # continues processing. + + errorlevel = 1 # If 0, fatal errors only appear in debug + # messages (if debug >= 0). If > 0, errors + # are passed to the caller as exceptions. + + format = DEFAULT_FORMAT # The format to use when creating an archive. + + encoding = ENCODING # Encoding for 8-bit character strings. + + errors = None # Error handler for unicode conversion. + + tarinfo = TarInfo # The default TarInfo class to use. + + fileobject = ExFileObject # The default ExFileObject class to use. + + def __init__(self, name=None, mode="r", fileobj=None, format=None, + tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, + errors="surrogateescape", pax_headers=None, debug=None, errorlevel=None): + """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to + read from an existing archive, 'a' to append data to an existing + file or 'w' to create a new file overwriting an existing one. `mode' + defaults to 'r'. + If `fileobj' is given, it is used for reading or writing data. If it + can be determined, `mode' is overridden by `fileobj's mode. + `fileobj' is not closed, when TarFile is closed. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + self.mode = mode + self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] + + if not fileobj: + if self.mode == "a" and not os.path.exists(name): + # Create nonexistent files in append mode. + self.mode = "w" + self._mode = "wb" + fileobj = bltn_open(name, self._mode) + self._extfileobj = False + else: + if name is None and hasattr(fileobj, "name"): + name = fileobj.name + if hasattr(fileobj, "mode"): + self._mode = fileobj.mode + self._extfileobj = True + self.name = os.path.abspath(name) if name else None + self.fileobj = fileobj + + # Init attributes. + if format is not None: + self.format = format + if tarinfo is not None: + self.tarinfo = tarinfo + if dereference is not None: + self.dereference = dereference + if ignore_zeros is not None: + self.ignore_zeros = ignore_zeros + if encoding is not None: + self.encoding = encoding + self.errors = errors + + if pax_headers is not None and self.format == PAX_FORMAT: + self.pax_headers = pax_headers + else: + self.pax_headers = {} + + if debug is not None: + self.debug = debug + if errorlevel is not None: + self.errorlevel = errorlevel + + # Init datastructures. + self.closed = False + self.members = [] # list of members as TarInfo objects + self._loaded = False # flag if all members have been read + self.offset = self.fileobj.tell() + # current position in the archive file + self.inodes = {} # dictionary caching the inodes of + # archive members already added + + try: + if self.mode == "r": + self.firstmember = None + self.firstmember = self.next() + + if self.mode == "a": + # Move to the end of the archive, + # before the first empty block. + while True: + self.fileobj.seek(self.offset) + try: + tarinfo = self.tarinfo.fromtarfile(self) + self.members.append(tarinfo) + except EOFHeaderError: + self.fileobj.seek(self.offset) + break + except HeaderError as e: + raise ReadError(str(e)) + + if self.mode in "aw": + self._loaded = True + + if self.pax_headers: + buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) + self.fileobj.write(buf) + self.offset += len(buf) + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + #-------------------------------------------------------------------------- + # Below are the classmethods which act as alternate constructors to the + # TarFile class. The open() method is the only one that is needed for + # public use; it is the "super"-constructor and is able to select an + # adequate "sub"-constructor for a particular compression using the mapping + # from OPEN_METH. + # + # This concept allows one to subclass TarFile without losing the comfort of + # the super-constructor. A sub-constructor is registered and made available + # by adding it to the mapping in OPEN_METH. + + @classmethod + def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): + """Open a tar archive for reading, writing or appending. Return + an appropriate TarFile class. + + mode: + 'r' or 'r:*' open for reading with transparent compression + 'r:' open for reading exclusively uncompressed + 'r:gz' open for reading with gzip compression + 'r:bz2' open for reading with bzip2 compression + 'a' or 'a:' open for appending, creating the file if necessary + 'w' or 'w:' open for writing without compression + 'w:gz' open for writing with gzip compression + 'w:bz2' open for writing with bzip2 compression + + 'r|*' open a stream of tar blocks with transparent compression + 'r|' open an uncompressed stream of tar blocks for reading + 'r|gz' open a gzip compressed stream of tar blocks + 'r|bz2' open a bzip2 compressed stream of tar blocks + 'w|' open an uncompressed stream for writing + 'w|gz' open a gzip compressed stream for writing + 'w|bz2' open a bzip2 compressed stream for writing + """ + + if not name and not fileobj: + raise ValueError("nothing to open") + + if mode in ("r", "r:*"): + # Find out which *open() is appropriate for opening the file. + for comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + if fileobj is not None: + saved_pos = fileobj.tell() + try: + return func(name, "r", fileobj, **kwargs) + except (ReadError, CompressionError) as e: + if fileobj is not None: + fileobj.seek(saved_pos) + continue + raise ReadError("file could not be opened successfully") + + elif ":" in mode: + filemode, comptype = mode.split(":", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + # Select the *open() function according to + # given compression. + if comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + else: + raise CompressionError("unknown compression type %r" % comptype) + return func(name, filemode, fileobj, **kwargs) + + elif "|" in mode: + filemode, comptype = mode.split("|", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + if filemode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + stream = _Stream(name, filemode, comptype, fileobj, bufsize) + try: + t = cls(name, filemode, stream, **kwargs) + except: + stream.close() + raise + t._extfileobj = False + return t + + elif mode in "aw": + return cls.taropen(name, mode, fileobj, **kwargs) + + raise ValueError("undiscernible mode") + + @classmethod + def taropen(cls, name, mode="r", fileobj=None, **kwargs): + """Open uncompressed tar archive name for reading or writing. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + return cls(name, mode, fileobj, **kwargs) + + @classmethod + def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open gzip compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + try: + import gzip + gzip.GzipFile + except (ImportError, AttributeError): + raise CompressionError("gzip module is not available") + + extfileobj = fileobj is not None + try: + fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + t = cls.taropen(name, mode, fileobj, **kwargs) + except IOError: + if not extfileobj and fileobj is not None: + fileobj.close() + if fileobj is None: + raise + raise ReadError("not a gzip file") + except: + if not extfileobj and fileobj is not None: + fileobj.close() + raise + t._extfileobj = extfileobj + return t + + @classmethod + def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open bzip2 compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'.") + + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + + if fileobj is not None: + fileobj = _BZ2Proxy(fileobj, mode) + else: + fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except (IOError, EOFError): + fileobj.close() + raise ReadError("not a bzip2 file") + t._extfileobj = False + return t + + # All *open() methods are registered here. + OPEN_METH = { + "tar": "taropen", # uncompressed tar + "gz": "gzopen", # gzip compressed tar + "bz2": "bz2open" # bzip2 compressed tar + } + + #-------------------------------------------------------------------------- + # The public methods which TarFile provides: + + def close(self): + """Close the TarFile. In write-mode, two finishing zero blocks are + appended to the archive. + """ + if self.closed: + return + + if self.mode in "aw": + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + + if not self._extfileobj: + self.fileobj.close() + self.closed = True + + def getmember(self, name): + """Return a TarInfo object for member `name'. If `name' can not be + found in the archive, KeyError is raised. If a member occurs more + than once in the archive, its last occurrence is assumed to be the + most up-to-date version. + """ + tarinfo = self._getmember(name) + if tarinfo is None: + raise KeyError("filename %r not found" % name) + return tarinfo + + def getmembers(self): + """Return the members of the archive as a list of TarInfo objects. The + list has the same order as the members in the archive. + """ + self._check() + if not self._loaded: # if we want to obtain a list of + self._load() # all members, we first have to + # scan the whole archive. + return self.members + + def getnames(self): + """Return the members of the archive as a list of their names. It has + the same order as the list returned by getmembers(). + """ + return [tarinfo.name for tarinfo in self.getmembers()] + + def gettarinfo(self, name=None, arcname=None, fileobj=None): + """Create a TarInfo object for either the file `name' or the file + object `fileobj' (using os.fstat on its file descriptor). You can + modify some of the TarInfo's attributes before you add it using + addfile(). If given, `arcname' specifies an alternative name for the + file in the archive. + """ + self._check("aw") + + # When fileobj is given, replace name by + # fileobj's real name. + if fileobj is not None: + name = fileobj.name + + # Building the name of the member in the archive. + # Backward slashes are converted to forward slashes, + # Absolute paths are turned to relative paths. + if arcname is None: + arcname = name + drv, arcname = os.path.splitdrive(arcname) + arcname = arcname.replace(os.sep, "/") + arcname = arcname.lstrip("/") + + # Now, fill the TarInfo object with + # information specific for the file. + tarinfo = self.tarinfo() + tarinfo.tarfile = self + + # Use os.stat or os.lstat, depending on platform + # and if symlinks shall be resolved. + if fileobj is None: + if hasattr(os, "lstat") and not self.dereference: + statres = os.lstat(name) + else: + statres = os.stat(name) + else: + statres = os.fstat(fileobj.fileno()) + linkname = "" + + stmd = statres.st_mode + if stat.S_ISREG(stmd): + inode = (statres.st_ino, statres.st_dev) + if not self.dereference and statres.st_nlink > 1 and \ + inode in self.inodes and arcname != self.inodes[inode]: + # Is it a hardlink to an already + # archived file? + type = LNKTYPE + linkname = self.inodes[inode] + else: + # The inode is added only if its valid. + # For win32 it is always 0. + type = REGTYPE + if inode[0]: + self.inodes[inode] = arcname + elif stat.S_ISDIR(stmd): + type = DIRTYPE + elif stat.S_ISFIFO(stmd): + type = FIFOTYPE + elif stat.S_ISLNK(stmd): + type = SYMTYPE + linkname = os.readlink(name) + elif stat.S_ISCHR(stmd): + type = CHRTYPE + elif stat.S_ISBLK(stmd): + type = BLKTYPE + else: + return None + + # Fill the TarInfo object with all + # information we can get. + tarinfo.name = arcname + tarinfo.mode = stmd + tarinfo.uid = statres.st_uid + tarinfo.gid = statres.st_gid + if type == REGTYPE: + tarinfo.size = statres.st_size + else: + tarinfo.size = 0 + tarinfo.mtime = statres.st_mtime + tarinfo.type = type + tarinfo.linkname = linkname + if pwd: + try: + tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] + except KeyError: + pass + if grp: + try: + tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] + except KeyError: + pass + + if type in (CHRTYPE, BLKTYPE): + if hasattr(os, "major") and hasattr(os, "minor"): + tarinfo.devmajor = os.major(statres.st_rdev) + tarinfo.devminor = os.minor(statres.st_rdev) + return tarinfo + + def list(self, verbose=True): + """Print a table of contents to sys.stdout. If `verbose' is False, only + the names of the members are printed. If it is True, an `ls -l'-like + output is produced. + """ + self._check() + + for tarinfo in self: + if verbose: + print(filemode(tarinfo.mode), end=' ') + print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid), end=' ') + if tarinfo.ischr() or tarinfo.isblk(): + print("%10s" % ("%d,%d" \ + % (tarinfo.devmajor, tarinfo.devminor)), end=' ') + else: + print("%10d" % tarinfo.size, end=' ') + print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6], end=' ') + + print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + + if verbose: + if tarinfo.issym(): + print("->", tarinfo.linkname, end=' ') + if tarinfo.islnk(): + print("link to", tarinfo.linkname, end=' ') + print() + + def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): + """Add the file `name' to the archive. `name' may be any type of file + (directory, fifo, symbolic link, etc.). If given, `arcname' + specifies an alternative name for the file in the archive. + Directories are added recursively by default. This can be avoided by + setting `recursive' to False. `exclude' is a function that should + return True for each filename to be excluded. `filter' is a function + that expects a TarInfo object argument and returns the changed + TarInfo object, if it returns None the TarInfo object will be + excluded from the archive. + """ + self._check("aw") + + if arcname is None: + arcname = name + + # Exclude pathnames. + if exclude is not None: + import warnings + warnings.warn("use the filter argument instead", + DeprecationWarning, 2) + if exclude(name): + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Skip if somebody tries to archive the archive... + if self.name is not None and os.path.abspath(name) == self.name: + self._dbg(2, "tarfile: Skipped %r" % name) + return + + self._dbg(1, name) + + # Create a TarInfo object from the file. + tarinfo = self.gettarinfo(name, arcname) + + if tarinfo is None: + self._dbg(1, "tarfile: Unsupported type %r" % name) + return + + # Change or exclude the TarInfo object. + if filter is not None: + tarinfo = filter(tarinfo) + if tarinfo is None: + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Append the tar header and data to the archive. + if tarinfo.isreg(): + f = bltn_open(name, "rb") + self.addfile(tarinfo, f) + f.close() + + elif tarinfo.isdir(): + self.addfile(tarinfo) + if recursive: + for f in os.listdir(name): + self.add(os.path.join(name, f), os.path.join(arcname, f), + recursive, exclude, filter=filter) + + else: + self.addfile(tarinfo) + + def addfile(self, tarinfo, fileobj=None): + """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is + given, tarinfo.size bytes are read from it and added to the archive. + You can create TarInfo objects using gettarinfo(). + On Windows platforms, `fileobj' should always be opened with mode + 'rb' to avoid irritation about the file size. + """ + self._check("aw") + + tarinfo = copy.copy(tarinfo) + + buf = tarinfo.tobuf(self.format, self.encoding, self.errors) + self.fileobj.write(buf) + self.offset += len(buf) + + # If there's data to follow, append it. + if fileobj is not None: + copyfileobj(fileobj, self.fileobj, tarinfo.size) + blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) + if remainder > 0: + self.fileobj.write(NUL * (BLOCKSIZE - remainder)) + blocks += 1 + self.offset += blocks * BLOCKSIZE + + self.members.append(tarinfo) + + def extractall(self, path=".", members=None): + """Extract all members from the archive to the current working + directory and set owner, modification time and permissions on + directories afterwards. `path' specifies a different directory + to extract to. `members' is optional and must be a subset of the + list returned by getmembers(). + """ + directories = [] + + if members is None: + members = self + + for tarinfo in members: + if tarinfo.isdir(): + # Extract directories with a safe mode. + directories.append(tarinfo) + tarinfo = copy.copy(tarinfo) + tarinfo.mode = 0o700 + # Do not set_attrs directories, as we will do that further down + self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) + + # Reverse sort directories. + directories.sort(key=lambda a: a.name) + directories.reverse() + + # Set correct owner, mtime and filemode on directories. + for tarinfo in directories: + dirpath = os.path.join(path, tarinfo.name) + try: + self.chown(tarinfo, dirpath) + self.utime(tarinfo, dirpath) + self.chmod(tarinfo, dirpath) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extract(self, member, path="", set_attrs=True): + """Extract a member from the archive to the current working directory, + using its full name. Its file information is extracted as accurately + as possible. `member' may be a filename or a TarInfo object. You can + specify a different directory using `path'. File attributes (owner, + mtime, mode) are set unless `set_attrs' is False. + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + # Prepare the link target for makelink(). + if tarinfo.islnk(): + tarinfo._link_target = os.path.join(path, tarinfo.linkname) + + try: + self._extract_member(tarinfo, os.path.join(path, tarinfo.name), + set_attrs=set_attrs) + except EnvironmentError as e: + if self.errorlevel > 0: + raise + else: + if e.filename is None: + self._dbg(1, "tarfile: %s" % e.strerror) + else: + self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extractfile(self, member): + """Extract a member from the archive as a file object. `member' may be + a filename or a TarInfo object. If `member' is a regular file, a + file-like object is returned. If `member' is a link, a file-like + object is constructed from the link's target. If `member' is none of + the above, None is returned. + The file-like object is read-only and provides the following + methods: read(), readline(), readlines(), seek() and tell() + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + if tarinfo.isreg(): + return self.fileobject(self, tarinfo) + + elif tarinfo.type not in SUPPORTED_TYPES: + # If a member's type is unknown, it is treated as a + # regular file. + return self.fileobject(self, tarinfo) + + elif tarinfo.islnk() or tarinfo.issym(): + if isinstance(self.fileobj, _Stream): + # A small but ugly workaround for the case that someone tries + # to extract a (sym)link as a file-object from a non-seekable + # stream of tar blocks. + raise StreamError("cannot extract (sym)link as file object") + else: + # A (sym)link's file object is its target's file object. + return self.extractfile(self._find_link_target(tarinfo)) + else: + # If there's no data associated with the member (directory, chrdev, + # blkdev, etc.), return None instead of a file object. + return None + + def _extract_member(self, tarinfo, targetpath, set_attrs=True): + """Extract the TarInfo object tarinfo to a physical + file called targetpath. + """ + # Fetch the TarInfo object for the given name + # and build the destination pathname, replacing + # forward slashes to platform specific separators. + targetpath = targetpath.rstrip("/") + targetpath = targetpath.replace("/", os.sep) + + # Create all upper directories. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + # Create directories that are not part of the archive with + # default permissions. + os.makedirs(upperdirs) + + if tarinfo.islnk() or tarinfo.issym(): + self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) + else: + self._dbg(1, tarinfo.name) + + if tarinfo.isreg(): + self.makefile(tarinfo, targetpath) + elif tarinfo.isdir(): + self.makedir(tarinfo, targetpath) + elif tarinfo.isfifo(): + self.makefifo(tarinfo, targetpath) + elif tarinfo.ischr() or tarinfo.isblk(): + self.makedev(tarinfo, targetpath) + elif tarinfo.islnk() or tarinfo.issym(): + self.makelink(tarinfo, targetpath) + elif tarinfo.type not in SUPPORTED_TYPES: + self.makeunknown(tarinfo, targetpath) + else: + self.makefile(tarinfo, targetpath) + + if set_attrs: + self.chown(tarinfo, targetpath) + if not tarinfo.issym(): + self.chmod(tarinfo, targetpath) + self.utime(tarinfo, targetpath) + + #-------------------------------------------------------------------------- + # Below are the different file methods. They are called via + # _extract_member() when extract() is called. They can be replaced in a + # subclass to implement other functionality. + + def makedir(self, tarinfo, targetpath): + """Make a directory called targetpath. + """ + try: + # Use a safe mode for the directory, the real mode is set + # later in _extract_member(). + os.mkdir(targetpath, 0o700) + except EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + + def makefile(self, tarinfo, targetpath): + """Make a file called targetpath. + """ + source = self.fileobj + source.seek(tarinfo.offset_data) + target = bltn_open(targetpath, "wb") + if tarinfo.sparse is not None: + for offset, size in tarinfo.sparse: + target.seek(offset) + copyfileobj(source, target, size) + else: + copyfileobj(source, target, tarinfo.size) + target.seek(tarinfo.size) + target.truncate() + target.close() + + def makeunknown(self, tarinfo, targetpath): + """Make a file from a TarInfo object with an unknown type + at targetpath. + """ + self.makefile(tarinfo, targetpath) + self._dbg(1, "tarfile: Unknown file type %r, " \ + "extracted as regular file." % tarinfo.type) + + def makefifo(self, tarinfo, targetpath): + """Make a fifo called targetpath. + """ + if hasattr(os, "mkfifo"): + os.mkfifo(targetpath) + else: + raise ExtractError("fifo not supported by system") + + def makedev(self, tarinfo, targetpath): + """Make a character or block device called targetpath. + """ + if not hasattr(os, "mknod") or not hasattr(os, "makedev"): + raise ExtractError("special devices not supported by system") + + mode = tarinfo.mode + if tarinfo.isblk(): + mode |= stat.S_IFBLK + else: + mode |= stat.S_IFCHR + + os.mknod(targetpath, mode, + os.makedev(tarinfo.devmajor, tarinfo.devminor)) + + def makelink(self, tarinfo, targetpath): + """Make a (symbolic) link called targetpath. If it cannot be created + (platform limitation), we try to make a copy of the referenced file + instead of a link. + """ + try: + # For systems that support symbolic and hard links. + if tarinfo.issym(): + os.symlink(tarinfo.linkname, targetpath) + else: + # See extract(). + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except symlink_exception: + if tarinfo.issym(): + linkpath = os.path.join(os.path.dirname(tarinfo.name), + tarinfo.linkname) + else: + linkpath = tarinfo.linkname + else: + try: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") + + def chown(self, tarinfo, targetpath): + """Set owner of targetpath according to tarinfo. + """ + if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: + # We have to be root to do so. + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid + try: + if tarinfo.issym() and hasattr(os, "lchown"): + os.lchown(targetpath, u, g) + else: + if sys.platform != "os2emx": + os.chown(targetpath, u, g) + except EnvironmentError as e: + raise ExtractError("could not change owner") + + def chmod(self, tarinfo, targetpath): + """Set file permissions of targetpath according to tarinfo. + """ + if hasattr(os, 'chmod'): + try: + os.chmod(targetpath, tarinfo.mode) + except EnvironmentError as e: + raise ExtractError("could not change mode") + + def utime(self, tarinfo, targetpath): + """Set modification time of targetpath according to tarinfo. + """ + if not hasattr(os, 'utime'): + return + try: + os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) + except EnvironmentError as e: + raise ExtractError("could not change modification time") + + #-------------------------------------------------------------------------- + def next(self): + """Return the next member of the archive as a TarInfo object, when + TarFile is opened for reading. Return None if there is no more + available. + """ + self._check("ra") + if self.firstmember is not None: + m = self.firstmember + self.firstmember = None + return m + + # Read the next block. + self.fileobj.seek(self.offset) + tarinfo = None + while True: + try: + tarinfo = self.tarinfo.fromtarfile(self) + except EOFHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + except InvalidHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + elif self.offset == 0: + raise ReadError(str(e)) + except EmptyHeaderError: + if self.offset == 0: + raise ReadError("empty file") + except TruncatedHeaderError as e: + if self.offset == 0: + raise ReadError(str(e)) + except SubsequentHeaderError as e: + raise ReadError(str(e)) + break + + if tarinfo is not None: + self.members.append(tarinfo) + else: + self._loaded = True + + return tarinfo + + #-------------------------------------------------------------------------- + # Little helper methods: + + def _getmember(self, name, tarinfo=None, normalize=False): + """Find an archive member by name from bottom to top. + If tarinfo is given, it is used as the starting point. + """ + # Ensure that all members have been loaded. + members = self.getmembers() + + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] + + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member + + def _load(self): + """Read through the entire archive file and look for readable + members. + """ + while True: + tarinfo = self.next() + if tarinfo is None: + break + self._loaded = True + + def _check(self, mode=None): + """Check if TarFile is still open, and if the operation's mode + corresponds to TarFile's mode. + """ + if self.closed: + raise IOError("%s is closed" % self.__class__.__name__) + if mode is not None and self.mode not in mode: + raise IOError("bad operation for mode %r" % self.mode) + + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + + def __iter__(self): + """Provide an iterator object. + """ + if self._loaded: + return iter(self.members) + else: + return TarIter(self) + + def _dbg(self, level, msg): + """Write debugging output to sys.stderr. + """ + if level <= self.debug: + print(msg, file=sys.stderr) + + def __enter__(self): + self._check() + return self + + def __exit__(self, type, value, traceback): + if type is None: + self.close() + else: + # An exception occurred. We must not call close() because + # it would try to write end-of-archive blocks and padding. + if not self._extfileobj: + self.fileobj.close() + self.closed = True +# class TarFile + +class TarIter(object): + """Iterator Class. + + for tarinfo in TarFile(...): + suite... + """ + + def __init__(self, tarfile): + """Construct a TarIter object. + """ + self.tarfile = tarfile + self.index = 0 + def __iter__(self): + """Return iterator object. + """ + return self + + def __next__(self): + """Return the next item using TarFile's next() method. + When all members have been read, set TarFile as _loaded. + """ + # Fix for SF #1100429: Under rare circumstances it can + # happen that getmembers() is called during iteration, + # which will cause TarIter to stop prematurely. + if not self.tarfile._loaded: + tarinfo = self.tarfile.next() + if not tarinfo: + self.tarfile._loaded = True + raise StopIteration + else: + try: + tarinfo = self.tarfile.members[self.index] + except IndexError: + raise StopIteration + self.index += 1 + return tarinfo + + next = __next__ # for Python 2.x + +#-------------------- +# exported functions +#-------------------- +def is_tarfile(name): + """Return True if name points to a tar archive that we + are able to handle, else return False. + """ + try: + t = open(name) + t.close() + return True + except TarError: + return False + +bltn_open = open +open = TarFile.open diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/compat.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/compat.py new file mode 100644 index 0000000..ff328c8 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/compat.py @@ -0,0 +1,1120 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import absolute_import + +import os +import re +import sys + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + +if sys.version_info[0] < 3: # pragma: no cover + from StringIO import StringIO + string_types = basestring, + text_type = unicode + from types import FileType as file_type + import __builtin__ as builtins + import ConfigParser as configparser + from ._backport import shutil + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit + from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, + pathname2url, ContentTooShortError, splittype) + + def quote(s): + if isinstance(s, unicode): + s = s.encode('utf-8') + return _quote(s) + + import urllib2 + from urllib2 import (Request, urlopen, URLError, HTTPError, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib2 import HTTPSHandler + import httplib + import xmlrpclib + import Queue as queue + from HTMLParser import HTMLParser + import htmlentitydefs + raw_input = raw_input + from itertools import ifilter as filter + from itertools import ifilterfalse as filterfalse + + _userprog = None + def splituser(host): + """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + global _userprog + if _userprog is None: + import re + _userprog = re.compile('^(.*)@(.*)$') + + match = _userprog.match(host) + if match: return match.group(1, 2) + return None, host + +else: # pragma: no cover + from io import StringIO + string_types = str, + text_type = str + from io import TextIOWrapper as file_type + import builtins + import configparser + import shutil + from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, + unquote, urlsplit, urlunsplit, splittype) + from urllib.request import (urlopen, urlretrieve, Request, url2pathname, + pathname2url, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib.request import HTTPSHandler + from urllib.error import HTTPError, URLError, ContentTooShortError + import http.client as httplib + import urllib.request as urllib2 + import xmlrpc.client as xmlrpclib + import queue + from html.parser import HTMLParser + import html.entities as htmlentitydefs + raw_input = input + from itertools import filterfalse + filter = filter + +try: + from ssl import match_hostname, CertificateError +except ImportError: # pragma: no cover + class CertificateError(ValueError): + pass + + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + parts = dn.split('.') + leftmost, remainder = parts[0], parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +try: + from types import SimpleNamespace as Container +except ImportError: # pragma: no cover + class Container(object): + """ + A generic container for when multiple values need to be returned + """ + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +try: + from shutil import which +except ImportError: # pragma: no cover + # Implementation from Python 3.3 + def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if not os.curdir in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None + + +# ZipFile is a context manager in 2.7, but not in 2.6 + +from zipfile import ZipFile as BaseZipFile + +if hasattr(BaseZipFile, '__enter__'): # pragma: no cover + ZipFile = BaseZipFile +else: # pragma: no cover + from zipfile import ZipExtFile as BaseZipExtFile + + class ZipExtFile(BaseZipExtFile): + def __init__(self, base): + self.__dict__.update(base.__dict__) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + class ZipFile(BaseZipFile): + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + def open(self, *args, **kwargs): + base = BaseZipFile.open(self, *args, **kwargs) + return ZipExtFile(base) + +try: + from platform import python_implementation +except ImportError: # pragma: no cover + def python_implementation(): + """Return a string identifying the Python implementation.""" + if 'PyPy' in sys.version: + return 'PyPy' + if os.name == 'java': + return 'Jython' + if sys.version.startswith('IronPython'): + return 'IronPython' + return 'CPython' + +try: + import sysconfig +except ImportError: # pragma: no cover + from ._backport import sysconfig + +try: + callable = callable +except NameError: # pragma: no cover + from collections import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode + fsdecode = os.fsdecode +except AttributeError: # pragma: no cover + # Issue #99: on some systems (e.g. containerised), + # sys.getfilesystemencoding() returns None, and we need a real value, + # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and + # sys.getfilesystemencoding(): the return value is "the user’s preference + # according to the result of nl_langinfo(CODESET), or None if the + # nl_langinfo(CODESET) failed." + _fsencoding = sys.getfilesystemencoding() or 'utf-8' + if _fsencoding == 'mbcs': + _fserrors = 'strict' + else: + _fserrors = 'surrogateescape' + + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, text_type): + return filename.encode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + + def fsdecode(filename): + if isinstance(filename, text_type): + return filename + elif isinstance(filename, bytes): + return filename.decode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + +try: + from tokenize import detect_encoding +except ImportError: # pragma: no cover + from codecs import BOM_UTF8, lookup + import re + + cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") + + def _get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace("_", "-") + if enc == "utf-8" or enc.startswith("utf-8-"): + return "utf-8" + if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ + enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): + return "iso-8859-1" + return orig_enc + + def detect_encoding(readline): + """ + The detect_encoding() function is used to detect the encoding that should + be used to decode a Python source file. It requires one argument, readline, + in the same way as the tokenize() generator. + + It will call readline a maximum of twice, and return the encoding used + (as a string) and a list of any lines (left as bytes) it has read in. + + It detects the encoding from the presence of a utf-8 bom or an encoding + cookie as specified in pep-0263. If both a bom and a cookie are present, + but disagree, a SyntaxError will be raised. If the encoding cookie is an + invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, + 'utf-8-sig' is returned. + + If no encoding is specified, then the default of 'utf-8' will be returned. + """ + try: + filename = readline.__self__.name + except AttributeError: + filename = None + bom_found = False + encoding = None + default = 'utf-8' + def read_or_stop(): + try: + return readline() + except StopIteration: + return b'' + + def find_cookie(line): + try: + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') + except UnicodeDecodeError: + msg = "invalid or missing encoding declaration" + if filename is not None: + msg = '{} for {!r}'.format(msg, filename) + raise SyntaxError(msg) + + matches = cookie_re.findall(line_string) + if not matches: + return None + encoding = _get_normal_name(matches[0]) + try: + codec = lookup(encoding) + except LookupError: + # This behaviour mimics the Python interpreter + if filename is None: + msg = "unknown encoding: " + encoding + else: + msg = "unknown encoding for {!r}: {}".format(filename, + encoding) + raise SyntaxError(msg) + + if bom_found: + if codec.name != 'utf-8': + # This behaviour mimics the Python interpreter + if filename is None: + msg = 'encoding problem: utf-8' + else: + msg = 'encoding problem for {!r}: utf-8'.format(filename) + raise SyntaxError(msg) + encoding += '-sig' + return encoding + + first = read_or_stop() + if first.startswith(BOM_UTF8): + bom_found = True + first = first[3:] + default = 'utf-8-sig' + if not first: + return default, [] + + encoding = find_cookie(first) + if encoding: + return encoding, [first] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + +# For converting & <-> & etc. +try: + from html import escape +except ImportError: + from cgi import escape +if sys.version_info[:2] < (3, 4): + unescape = HTMLParser().unescape +else: + from html import unescape + +try: + from collections import ChainMap +except ImportError: # pragma: no cover + from collections import MutableMapping + + try: + from reprlib import recursive_repr as _recursive_repr + except ImportError: + def _recursive_repr(fillvalue='...'): + ''' + Decorator to make a repr function return fillvalue for a recursive + call + ''' + + def decorating_function(user_function): + repr_running = set() + + def wrapper(self): + key = id(self), get_ident() + if key in repr_running: + return fillvalue + repr_running.add(key) + try: + result = user_function(self) + finally: + repr_running.discard(key) + return result + + # Can't use functools.wraps() here because of bootstrap issues + wrapper.__module__ = getattr(user_function, '__module__') + wrapper.__doc__ = getattr(user_function, '__doc__') + wrapper.__name__ = getattr(user_function, '__name__') + wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) + return wrapper + + return decorating_function + + class ChainMap(MutableMapping): + ''' A ChainMap groups multiple dicts (or other mappings) together + to create a single, updateable view. + + The underlying mappings are stored in a list. That list is public and can + accessed or updated using the *maps* attribute. There is no other state. + + Lookups search the underlying mappings successively until a key is found. + In contrast, writes, updates, and deletions only operate on the first + mapping. + + ''' + + def __init__(self, *maps): + '''Initialize a ChainMap by setting *maps* to the given mappings. + If no mappings are provided, a single empty dictionary is used. + + ''' + self.maps = list(maps) or [{}] # always at least one map + + def __missing__(self, key): + raise KeyError(key) + + def __getitem__(self, key): + for mapping in self.maps: + try: + return mapping[key] # can't use 'key in mapping' with defaultdict + except KeyError: + pass + return self.__missing__(key) # support subclasses that define __missing__ + + def get(self, key, default=None): + return self[key] if key in self else default + + def __len__(self): + return len(set().union(*self.maps)) # reuses stored hash values if possible + + def __iter__(self): + return iter(set().union(*self.maps)) + + def __contains__(self, key): + return any(key in m for m in self.maps) + + def __bool__(self): + return any(self.maps) + + @_recursive_repr() + def __repr__(self): + return '{0.__class__.__name__}({1})'.format( + self, ', '.join(map(repr, self.maps))) + + @classmethod + def fromkeys(cls, iterable, *args): + 'Create a ChainMap with a single dict created from the iterable.' + return cls(dict.fromkeys(iterable, *args)) + + def copy(self): + 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' + return self.__class__(self.maps[0].copy(), *self.maps[1:]) + + __copy__ = copy + + def new_child(self): # like Django's Context.push() + 'New ChainMap with a new dict followed by all previous maps.' + return self.__class__({}, *self.maps) + + @property + def parents(self): # like Django's Context.pop() + 'New ChainMap from maps[1:].' + return self.__class__(*self.maps[1:]) + + def __setitem__(self, key, value): + self.maps[0][key] = value + + def __delitem__(self, key): + try: + del self.maps[0][key] + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def popitem(self): + 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' + try: + return self.maps[0].popitem() + except KeyError: + raise KeyError('No keys found in the first mapping.') + + def pop(self, key, *args): + 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' + try: + return self.maps[0].pop(key, *args) + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def clear(self): + 'Clear maps[0], leaving maps[1:] intact.' + self.maps[0].clear() + +try: + from importlib.util import cache_from_source # Python >= 3.4 +except ImportError: # pragma: no cover + try: + from imp import cache_from_source + except ImportError: # pragma: no cover + def cache_from_source(path, debug_override=None): + assert path.endswith('.py') + if debug_override is None: + debug_override = __debug__ + if debug_override: + suffix = 'c' + else: + suffix = 'o' + return path + suffix + +try: + from collections import OrderedDict +except ImportError: # pragma: no cover +## {{{ http://code.activestate.com/recipes/576693/ (r9) +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. + try: + from thread import get_ident as _get_ident + except ImportError: + from dummy_thread import get_ident as _get_ident + + try: + from _abcoll import KeysView, ValuesView, ItemsView + except ImportError: + pass + + + class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running=None): + 'od.__repr__() <==> repr(od)' + if not _repr_running: _repr_running = {} + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + +try: + from logging.config import BaseConfigurator, valid_ident +except ImportError: # pragma: no cover + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + + def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + + # The ConvertingXXX classes are wrappers around standard Python containers, + # and they serve to convert any suitable values in the container. The + # conversion converts base dicts, lists and tuples to their wrapped + # equivalents, whereas strings which match a conversion format are converted + # appropriately. + # + # Each wrapper should have a configurator attribute holding the actual + # configurator to use for conversion. + + class ConvertingDict(dict): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def get(self, key, default=None): + value = dict.get(self, key, default) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class ConvertingList(list): + """A converting list wrapper.""" + def __getitem__(self, key): + value = list.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, idx=-1): + value = list.pop(self, idx) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + class ConvertingTuple(tuple): + """A converting tuple wrapper.""" + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = staticmethod(__import__) + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + #print d, rest + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int(idx) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + #rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance(value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance(value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, string_types): + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/database.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/database.py new file mode 100644 index 0000000..a19905e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/database.py @@ -0,0 +1,1336 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""PEP 376 implementation.""" + +from __future__ import unicode_literals + +import base64 +import codecs +import contextlib +import hashlib +import logging +import os +import posixpath +import sys +import zipimport + +from . import DistlibException, resources +from .compat import StringIO +from .version import get_scheme, UnsupportedVersionError +from .metadata import Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME +from .util import (parse_requirement, cached_property, parse_name_and_version, + read_exports, write_exports, CSVReader, CSVWriter) + + +__all__ = ['Distribution', 'BaseInstalledDistribution', + 'InstalledDistribution', 'EggInfoDistribution', + 'DistributionPath'] + + +logger = logging.getLogger(__name__) + +EXPORTS_FILENAME = 'pydist-exports.json' +COMMANDS_FILENAME = 'pydist-commands.json' + +DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', + 'RESOURCES', EXPORTS_FILENAME, 'SHARED') + +DISTINFO_EXT = '.dist-info' + + +class _Cache(object): + """ + A simple cache mapping names and .dist-info paths to distributions + """ + def __init__(self): + """ + Initialise an instance. There is normally one for each DistributionPath. + """ + self.name = {} + self.path = {} + self.generated = False + + def clear(self): + """ + Clear the cache, setting it to its initial state. + """ + self.name.clear() + self.path.clear() + self.generated = False + + def add(self, dist): + """ + Add a distribution to the cache. + :param dist: The distribution to add. + """ + if dist.path not in self.path: + self.path[dist.path] = dist + self.name.setdefault(dist.key, []).append(dist) + + +class DistributionPath(object): + """ + Represents a set of distributions installed on a path (typically sys.path). + """ + def __init__(self, path=None, include_egg=False): + """ + Create an instance from a path, optionally including legacy (distutils/ + setuptools/distribute) distributions. + :param path: The path to use, as a list of directories. If not specified, + sys.path is used. + :param include_egg: If True, this instance will look for and return legacy + distributions as well as those based on PEP 376. + """ + if path is None: + path = sys.path + self.path = path + self._include_dist = True + self._include_egg = include_egg + + self._cache = _Cache() + self._cache_egg = _Cache() + self._cache_enabled = True + self._scheme = get_scheme('default') + + def _get_cache_enabled(self): + return self._cache_enabled + + def _set_cache_enabled(self, value): + self._cache_enabled = value + + cache_enabled = property(_get_cache_enabled, _set_cache_enabled) + + def clear_cache(self): + """ + Clears the internal cache. + """ + self._cache.clear() + self._cache_egg.clear() + + + def _yield_distributions(self): + """ + Yield .dist-info and/or .egg(-info) distributions. + """ + # We need to check if we've seen some resources already, because on + # some Linux systems (e.g. some Debian/Ubuntu variants) there are + # symlinks which alias other files in the environment. + seen = set() + for path in self.path: + finder = resources.finder_for_path(path) + if finder is None: + continue + r = finder.find('') + if not r or not r.is_container: + continue + rset = sorted(r.resources) + for entry in rset: + r = finder.find(entry) + if not r or r.path in seen: + continue + if self._include_dist and entry.endswith(DISTINFO_EXT): + possible_filenames = [METADATA_FILENAME, WHEEL_METADATA_FILENAME] + for metadata_filename in possible_filenames: + metadata_path = posixpath.join(entry, metadata_filename) + pydist = finder.find(metadata_path) + if pydist: + break + else: + continue + + with contextlib.closing(pydist.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + logger.debug('Found %s', r.path) + seen.add(r.path) + yield new_dist_class(r.path, metadata=metadata, + env=self) + elif self._include_egg and entry.endswith(('.egg-info', + '.egg')): + logger.debug('Found %s', r.path) + seen.add(r.path) + yield old_dist_class(r.path, self) + + def _generate_cache(self): + """ + Scan the path for distributions and populate the cache with + those that are found. + """ + gen_dist = not self._cache.generated + gen_egg = self._include_egg and not self._cache_egg.generated + if gen_dist or gen_egg: + for dist in self._yield_distributions(): + if isinstance(dist, InstalledDistribution): + self._cache.add(dist) + else: + self._cache_egg.add(dist) + + if gen_dist: + self._cache.generated = True + if gen_egg: + self._cache_egg.generated = True + + @classmethod + def distinfo_dirname(cls, name, version): + """ + The *name* and *version* parameters are converted into their + filename-escaped form, i.e. any ``'-'`` characters are replaced + with ``'_'`` other than the one in ``'dist-info'`` and the one + separating the name from the version number. + + :parameter name: is converted to a standard distribution name by replacing + any runs of non- alphanumeric characters with a single + ``'-'``. + :type name: string + :parameter version: is converted to a standard version string. Spaces + become dots, and all other non-alphanumeric characters + (except dots) become dashes, with runs of multiple + dashes condensed to a single dash. + :type version: string + :returns: directory name + :rtype: string""" + name = name.replace('-', '_') + return '-'.join([name, version]) + DISTINFO_EXT + + def get_distributions(self): + """ + Provides an iterator that looks for distributions and returns + :class:`InstalledDistribution` or + :class:`EggInfoDistribution` instances for each one of them. + + :rtype: iterator of :class:`InstalledDistribution` and + :class:`EggInfoDistribution` instances + """ + if not self._cache_enabled: + for dist in self._yield_distributions(): + yield dist + else: + self._generate_cache() + + for dist in self._cache.path.values(): + yield dist + + if self._include_egg: + for dist in self._cache_egg.path.values(): + yield dist + + def get_distribution(self, name): + """ + Looks for a named distribution on the path. + + This function only returns the first result found, as no more than one + value is expected. If nothing is found, ``None`` is returned. + + :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` + or ``None`` + """ + result = None + name = name.lower() + if not self._cache_enabled: + for dist in self._yield_distributions(): + if dist.key == name: + result = dist + break + else: + self._generate_cache() + + if name in self._cache.name: + result = self._cache.name[name][0] + elif self._include_egg and name in self._cache_egg.name: + result = self._cache_egg.name[name][0] + return result + + def provides_distribution(self, name, version=None): + """ + Iterates over all distributions to find which distributions provide *name*. + If a *version* is provided, it will be used to filter the results. + + This function only returns the first result found, since no more than + one values are expected. If the directory is not found, returns ``None``. + + :parameter version: a version specifier that indicates the version + required, conforming to the format in ``PEP-345`` + + :type name: string + :type version: string + """ + matcher = None + if version is not None: + try: + matcher = self._scheme.matcher('%s (%s)' % (name, version)) + except ValueError: + raise DistlibException('invalid name or version: %r, %r' % + (name, version)) + + for dist in self.get_distributions(): + # We hit a problem on Travis where enum34 was installed and doesn't + # have a provides attribute ... + if not hasattr(dist, 'provides'): + logger.debug('No "provides": %s', dist) + else: + provided = dist.provides + + for p in provided: + p_name, p_ver = parse_name_and_version(p) + if matcher is None: + if p_name == name: + yield dist + break + else: + if p_name == name and matcher.match(p_ver): + yield dist + break + + def get_file_path(self, name, relative_path): + """ + Return the path to a resource file. + """ + dist = self.get_distribution(name) + if dist is None: + raise LookupError('no distribution named %r found' % name) + return dist.get_resource_path(relative_path) + + def get_exported_entries(self, category, name=None): + """ + Return all of the exported entries in a particular category. + + :param category: The category to search for entries. + :param name: If specified, only entries with that name are returned. + """ + for dist in self.get_distributions(): + r = dist.exports + if category in r: + d = r[category] + if name is not None: + if name in d: + yield d[name] + else: + for v in d.values(): + yield v + + +class Distribution(object): + """ + A base class for distributions, whether installed or from indexes. + Either way, it must have some metadata, so that's all that's needed + for construction. + """ + + build_time_dependency = False + """ + Set to True if it's known to be only a build-time dependency (i.e. + not needed after installation). + """ + + requested = False + """A boolean that indicates whether the ``REQUESTED`` metadata file is + present (in other words, whether the package was installed by user + request or it was installed as a dependency).""" + + def __init__(self, metadata): + """ + Initialise an instance. + :param metadata: The instance of :class:`Metadata` describing this + distribution. + """ + self.metadata = metadata + self.name = metadata.name + self.key = self.name.lower() # for case-insensitive comparisons + self.version = metadata.version + self.locator = None + self.digest = None + self.extras = None # additional features requested + self.context = None # environment marker overrides + self.download_urls = set() + self.digests = {} + + @property + def source_url(self): + """ + The source archive download URL for this distribution. + """ + return self.metadata.source_url + + download_url = source_url # Backward compatibility + + @property + def name_and_version(self): + """ + A utility property which displays the name and version in parentheses. + """ + return '%s (%s)' % (self.name, self.version) + + @property + def provides(self): + """ + A set of distribution names and versions provided by this distribution. + :return: A set of "name (version)" strings. + """ + plist = self.metadata.provides + s = '%s (%s)' % (self.name, self.version) + if s not in plist: + plist.append(s) + return plist + + def _get_requirements(self, req_attr): + md = self.metadata + logger.debug('Getting requirements from metadata %r', md.todict()) + reqts = getattr(md, req_attr) + return set(md.get_requirements(reqts, extras=self.extras, + env=self.context)) + + @property + def run_requires(self): + return self._get_requirements('run_requires') + + @property + def meta_requires(self): + return self._get_requirements('meta_requires') + + @property + def build_requires(self): + return self._get_requirements('build_requires') + + @property + def test_requires(self): + return self._get_requirements('test_requires') + + @property + def dev_requires(self): + return self._get_requirements('dev_requires') + + def matches_requirement(self, req): + """ + Say if this instance matches (fulfills) a requirement. + :param req: The requirement to match. + :rtype req: str + :return: True if it matches, else False. + """ + # Requirement may contain extras - parse to lose those + # from what's passed to the matcher + r = parse_requirement(req) + scheme = get_scheme(self.metadata.scheme) + try: + matcher = scheme.matcher(r.requirement) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + result = False + for p in self.provides: + p_name, p_ver = parse_name_and_version(p) + if p_name != name: + continue + try: + result = matcher.match(p_ver) + break + except UnsupportedVersionError: + pass + return result + + def __repr__(self): + """ + Return a textual representation of this instance, + """ + if self.source_url: + suffix = ' [%s]' % self.source_url + else: + suffix = '' + return '<Distribution %s (%s)%s>' % (self.name, self.version, suffix) + + def __eq__(self, other): + """ + See if this distribution is the same as another. + :param other: The distribution to compare with. To be equal to one + another. distributions must have the same type, name, + version and source_url. + :return: True if it is the same, else False. + """ + if type(other) is not type(self): + result = False + else: + result = (self.name == other.name and + self.version == other.version and + self.source_url == other.source_url) + return result + + def __hash__(self): + """ + Compute hash in a way which matches the equality test. + """ + return hash(self.name) + hash(self.version) + hash(self.source_url) + + +class BaseInstalledDistribution(Distribution): + """ + This is the base class for installed distributions (whether PEP 376 or + legacy). + """ + + hasher = None + + def __init__(self, metadata, path, env=None): + """ + Initialise an instance. + :param metadata: An instance of :class:`Metadata` which describes the + distribution. This will normally have been initialised + from a metadata file in the ``path``. + :param path: The path of the ``.dist-info`` or ``.egg-info`` + directory for the distribution. + :param env: This is normally the :class:`DistributionPath` + instance where this distribution was found. + """ + super(BaseInstalledDistribution, self).__init__(metadata) + self.path = path + self.dist_path = env + + def get_hash(self, data, hasher=None): + """ + Get the hash of some data, using a particular hash algorithm, if + specified. + + :param data: The data to be hashed. + :type data: bytes + :param hasher: The name of a hash implementation, supported by hashlib, + or ``None``. Examples of valid values are ``'sha1'``, + ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and + ``'sha512'``. If no hasher is specified, the ``hasher`` + attribute of the :class:`InstalledDistribution` instance + is used. If the hasher is determined to be ``None``, MD5 + is used as the hashing algorithm. + :returns: The hash of the data. If a hasher was explicitly specified, + the returned hash will be prefixed with the specified hasher + followed by '='. + :rtype: str + """ + if hasher is None: + hasher = self.hasher + if hasher is None: + hasher = hashlib.md5 + prefix = '' + else: + hasher = getattr(hashlib, hasher) + prefix = '%s=' % self.hasher + digest = hasher(data).digest() + digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') + return '%s%s' % (prefix, digest) + + +class InstalledDistribution(BaseInstalledDistribution): + """ + Created with the *path* of the ``.dist-info`` directory provided to the + constructor. It reads the metadata contained in ``pydist.json`` when it is + instantiated., or uses a passed in Metadata instance (useful for when + dry-run mode is being used). + """ + + hasher = 'sha256' + + def __init__(self, path, metadata=None, env=None): + self.modules = [] + self.finder = finder = resources.finder_for_path(path) + if finder is None: + raise ValueError('finder unavailable for %s' % path) + if env and env._cache_enabled and path in env._cache.path: + metadata = env._cache.path[path].metadata + elif metadata is None: + r = finder.find(METADATA_FILENAME) + # Temporary - for Wheel 0.23 support + if r is None: + r = finder.find(WHEEL_METADATA_FILENAME) + # Temporary - for legacy support + if r is None: + r = finder.find('METADATA') + if r is None: + raise ValueError('no %s found in %s' % (METADATA_FILENAME, + path)) + with contextlib.closing(r.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + + super(InstalledDistribution, self).__init__(metadata, path, env) + + if env and env._cache_enabled: + env._cache.add(self) + + r = finder.find('REQUESTED') + self.requested = r is not None + p = os.path.join(path, 'top_level.txt') + if os.path.exists(p): + with open(p, 'rb') as f: + data = f.read() + self.modules = data.splitlines() + + def __repr__(self): + return '<InstalledDistribution %r %s at %r>' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def _get_records(self): + """ + Get the list of installed files for the distribution + :return: A list of tuples of path, hash and size. Note that hash and + size might be ``None`` for some entries. The path is exactly + as stored in the file (which is as in PEP 376). + """ + results = [] + r = self.get_distinfo_resource('RECORD') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as record_reader: + # Base location is parent dir of .dist-info dir + #base_location = os.path.dirname(self.path) + #base_location = os.path.abspath(base_location) + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + #if not os.path.isabs(path): + # path = path.replace('/', os.sep) + # path = os.path.join(base_location, path) + results.append((path, checksum, size)) + return results + + @cached_property + def exports(self): + """ + Return the information exported by this distribution. + :return: A dictionary of exports, mapping an export category to a dict + of :class:`ExportEntry` instances describing the individual + export entries, and keyed by name. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + result = self.read_exports() + return result + + def read_exports(self): + """ + Read exports data from a file in .ini format. + + :return: A dictionary of exports, mapping an export category to a list + of :class:`ExportEntry` instances describing the individual + export entries. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + with contextlib.closing(r.as_stream()) as stream: + result = read_exports(stream) + return result + + def write_exports(self, exports): + """ + Write a dictionary of exports to a file in .ini format. + :param exports: A dictionary of exports, mapping an export category to + a list of :class:`ExportEntry` instances describing the + individual export entries. + """ + rf = self.get_distinfo_file(EXPORTS_FILENAME) + with open(rf, 'w') as f: + write_exports(exports, f) + + def get_resource_path(self, relative_path): + """ + NOTE: This API may change in the future. + + Return the absolute path to a resource file with the given relative + path. + + :param relative_path: The path, relative to .dist-info, of the resource + of interest. + :return: The absolute path where the resource is to be found. + """ + r = self.get_distinfo_resource('RESOURCES') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as resources_reader: + for relative, destination in resources_reader: + if relative == relative_path: + return destination + raise KeyError('no resource file with relative path %r ' + 'is installed' % relative_path) + + def list_installed_files(self): + """ + Iterates over the ``RECORD`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: iterator of (path, hash, size) + """ + for result in self._get_records(): + yield result + + def write_installed_files(self, paths, prefix, dry_run=False): + """ + Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any + existing ``RECORD`` file is silently overwritten. + + prefix is used to determine when to write absolute paths. + """ + prefix = os.path.join(prefix, '') + base = os.path.dirname(self.path) + base_under_prefix = base.startswith(prefix) + base = os.path.join(base, '') + record_path = self.get_distinfo_file('RECORD') + logger.info('creating %s', record_path) + if dry_run: + return None + with CSVWriter(record_path) as writer: + for path in paths: + if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): + # do not put size and hash, as in PEP-376 + hash_value = size = '' + else: + size = '%d' % os.path.getsize(path) + with open(path, 'rb') as fp: + hash_value = self.get_hash(fp.read()) + if path.startswith(base) or (base_under_prefix and + path.startswith(prefix)): + path = os.path.relpath(path, base) + writer.writerow((path, hash_value, size)) + + # add the RECORD file itself + if record_path.startswith(base): + record_path = os.path.relpath(record_path, base) + writer.writerow((record_path, '', '')) + return record_path + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + base = os.path.dirname(self.path) + record_path = self.get_distinfo_file('RECORD') + for path, hash_value, size in self.list_installed_files(): + if not os.path.isabs(path): + path = os.path.join(base, path) + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + elif os.path.isfile(path): + actual_size = str(os.path.getsize(path)) + if size and actual_size != size: + mismatches.append((path, 'size', size, actual_size)) + elif hash_value: + if '=' in hash_value: + hasher = hash_value.split('=', 1)[0] + else: + hasher = None + + with open(path, 'rb') as f: + actual_hash = self.get_hash(f.read(), hasher) + if actual_hash != hash_value: + mismatches.append((path, 'hash', hash_value, actual_hash)) + return mismatches + + @cached_property + def shared_locations(self): + """ + A dictionary of shared locations whose keys are in the set 'prefix', + 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. + The corresponding value is the absolute path of that category for + this distribution, and takes into account any paths selected by the + user at installation time (e.g. via command-line arguments). In the + case of the 'namespace' key, this would be a list of absolute paths + for the roots of namespace packages in this distribution. + + The first time this property is accessed, the relevant information is + read from the SHARED file in the .dist-info directory. + """ + result = {} + shared_path = os.path.join(self.path, 'SHARED') + if os.path.isfile(shared_path): + with codecs.open(shared_path, 'r', encoding='utf-8') as f: + lines = f.read().splitlines() + for line in lines: + key, value = line.split('=', 1) + if key == 'namespace': + result.setdefault(key, []).append(value) + else: + result[key] = value + return result + + def write_shared_locations(self, paths, dry_run=False): + """ + Write shared location information to the SHARED file in .dist-info. + :param paths: A dictionary as described in the documentation for + :meth:`shared_locations`. + :param dry_run: If True, the action is logged but no file is actually + written. + :return: The path of the file written to. + """ + shared_path = os.path.join(self.path, 'SHARED') + logger.info('creating %s', shared_path) + if dry_run: + return None + lines = [] + for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): + path = paths[key] + if os.path.isdir(paths[key]): + lines.append('%s=%s' % (key, path)) + for ns in paths.get('namespace', ()): + lines.append('namespace=%s' % ns) + + with codecs.open(shared_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + return shared_path + + def get_distinfo_resource(self, path): + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + finder = resources.finder_for_path(self.path) + if finder is None: + raise DistlibException('Unable to get a finder for %s' % self.path) + return finder.find(path) + + def get_distinfo_file(self, path): + """ + Returns a path located under the ``.dist-info`` directory. Returns a + string representing the path. + + :parameter path: a ``'/'``-separated path relative to the + ``.dist-info`` directory or an absolute path; + If *path* is an absolute path and doesn't start + with the ``.dist-info`` directory path, + a :class:`DistlibException` is raised + :type path: str + :rtype: str + """ + # Check if it is an absolute path # XXX use relpath, add tests + if path.find(os.sep) >= 0: + # it's an absolute path? + distinfo_dirname, path = path.split(os.sep)[-2:] + if distinfo_dirname != self.path.split(os.sep)[-1]: + raise DistlibException( + 'dist-info file %r does not belong to the %r %s ' + 'distribution' % (path, self.name, self.version)) + + # The file must be relative + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + + return os.path.join(self.path, path) + + def list_distinfo_files(self): + """ + Iterates over the ``RECORD`` entries and returns paths for each line if + the path is pointing to a file located in the ``.dist-info`` directory + or one of its subdirectories. + + :returns: iterator of paths + """ + base = os.path.dirname(self.path) + for path, checksum, size in self._get_records(): + # XXX add separator or use real relpath algo + if not os.path.isabs(path): + path = os.path.join(base, path) + if path.startswith(self.path): + yield path + + def __eq__(self, other): + return (isinstance(other, InstalledDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + + +class EggInfoDistribution(BaseInstalledDistribution): + """Created with the *path* of the ``.egg-info`` directory or file provided + to the constructor. It reads the metadata contained in the file itself, or + if the given path happens to be a directory, the metadata is read from the + file ``PKG-INFO`` under that directory.""" + + requested = True # as we have no way of knowing, assume it was + shared_locations = {} + + def __init__(self, path, env=None): + def set_name_and_version(s, n, v): + s.name = n + s.key = n.lower() # for case-insensitive comparisons + s.version = v + + self.path = path + self.dist_path = env + if env and env._cache_enabled and path in env._cache_egg.path: + metadata = env._cache_egg.path[path].metadata + set_name_and_version(self, metadata.name, metadata.version) + else: + metadata = self._get_metadata(path) + + # Need to be set before caching + set_name_and_version(self, metadata.name, metadata.version) + + if env and env._cache_enabled: + env._cache_egg.add(self) + super(EggInfoDistribution, self).__init__(metadata, path, env) + + def _get_metadata(self, path): + requires = None + + def parse_requires_data(data): + """Create a list of dependencies from a requires.txt file. + + *data*: the contents of a setuptools-produced requires.txt file. + """ + reqs = [] + lines = data.splitlines() + for line in lines: + line = line.strip() + if line.startswith('['): + logger.warning('Unexpected line: quitting requirement scan: %r', + line) + break + r = parse_requirement(line) + if not r: + logger.warning('Not recognised as a requirement: %r', line) + continue + if r.extras: + logger.warning('extra requirements in requires.txt are ' + 'not supported') + if not r.constraints: + reqs.append(r.name) + else: + cons = ', '.join('%s%s' % c for c in r.constraints) + reqs.append('%s (%s)' % (r.name, cons)) + return reqs + + def parse_requires_path(req_path): + """Create a list of dependencies from a requires.txt file. + + *req_path*: the path to a setuptools-produced requires.txt file. + """ + + reqs = [] + try: + with codecs.open(req_path, 'r', 'utf-8') as fp: + reqs = parse_requires_data(fp.read()) + except IOError: + pass + return reqs + + tl_path = tl_data = None + if path.endswith('.egg'): + if os.path.isdir(path): + p = os.path.join(path, 'EGG-INFO') + meta_path = os.path.join(p, 'PKG-INFO') + metadata = Metadata(path=meta_path, scheme='legacy') + req_path = os.path.join(p, 'requires.txt') + tl_path = os.path.join(p, 'top_level.txt') + requires = parse_requires_path(req_path) + else: + # FIXME handle the case where zipfile is not available + zipf = zipimport.zipimporter(path) + fileobj = StringIO( + zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) + metadata = Metadata(fileobj=fileobj, scheme='legacy') + try: + data = zipf.get_data('EGG-INFO/requires.txt') + tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8') + requires = parse_requires_data(data.decode('utf-8')) + except IOError: + requires = None + elif path.endswith('.egg-info'): + if os.path.isdir(path): + req_path = os.path.join(path, 'requires.txt') + requires = parse_requires_path(req_path) + path = os.path.join(path, 'PKG-INFO') + tl_path = os.path.join(path, 'top_level.txt') + metadata = Metadata(path=path, scheme='legacy') + else: + raise DistlibException('path must end with .egg-info or .egg, ' + 'got %r' % path) + + if requires: + metadata.add_requirements(requires) + # look for top-level modules in top_level.txt, if present + if tl_data is None: + if tl_path is not None and os.path.exists(tl_path): + with open(tl_path, 'rb') as f: + tl_data = f.read().decode('utf-8') + if not tl_data: + tl_data = [] + else: + tl_data = tl_data.splitlines() + self.modules = tl_data + return metadata + + def __repr__(self): + return '<EggInfoDistribution %r %s at %r>' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + for path, _, _ in self.list_installed_files(): + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + return mismatches + + def list_installed_files(self): + """ + Iterates over the ``installed-files.txt`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: a list of (path, hash, size) + """ + + def _md5(path): + f = open(path, 'rb') + try: + content = f.read() + finally: + f.close() + return hashlib.md5(content).hexdigest() + + def _size(path): + return os.stat(path).st_size + + record_path = os.path.join(self.path, 'installed-files.txt') + result = [] + if os.path.exists(record_path): + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + p = os.path.normpath(os.path.join(self.path, line)) + # "./" is present as a marker between installed files + # and installation metadata files + if not os.path.exists(p): + logger.warning('Non-existent file: %s', p) + if p.endswith(('.pyc', '.pyo')): + continue + #otherwise fall through and fail + if not os.path.isdir(p): + result.append((p, _md5(p), _size(p))) + result.append((record_path, None, None)) + return result + + def list_distinfo_files(self, absolute=False): + """ + Iterates over the ``installed-files.txt`` entries and returns paths for + each line if the path is pointing to a file located in the + ``.egg-info`` directory or one of its subdirectories. + + :parameter absolute: If *absolute* is ``True``, each returned path is + transformed into a local absolute path. Otherwise the + raw value from ``installed-files.txt`` is returned. + :type absolute: boolean + :returns: iterator of paths + """ + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + skip = True + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line == './': + skip = False + continue + if not skip: + p = os.path.normpath(os.path.join(self.path, line)) + if p.startswith(self.path): + if absolute: + yield p + else: + yield line + + def __eq__(self, other): + return (isinstance(other, EggInfoDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + +new_dist_class = InstalledDistribution +old_dist_class = EggInfoDistribution + + +class DependencyGraph(object): + """ + Represents a dependency graph between distributions. + + The dependency relationships are stored in an ``adjacency_list`` that maps + distributions to a list of ``(other, label)`` tuples where ``other`` + is a distribution and the edge is labeled with ``label`` (i.e. the version + specifier, if such was provided). Also, for more efficient traversal, for + every distribution ``x``, a list of predecessors is kept in + ``reverse_list[x]``. An edge from distribution ``a`` to + distribution ``b`` means that ``a`` depends on ``b``. If any missing + dependencies are found, they are stored in ``missing``, which is a + dictionary that maps distributions to a list of requirements that were not + provided by any other distributions. + """ + + def __init__(self): + self.adjacency_list = {} + self.reverse_list = {} + self.missing = {} + + def add_distribution(self, distribution): + """Add the *distribution* to the graph. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + """ + self.adjacency_list[distribution] = [] + self.reverse_list[distribution] = [] + #self.missing[distribution] = [] + + def add_edge(self, x, y, label=None): + """Add an edge from distribution *x* to distribution *y* with the given + *label*. + + :type x: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type y: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type label: ``str`` or ``None`` + """ + self.adjacency_list[x].append((y, label)) + # multiple edges are allowed, so be careful + if x not in self.reverse_list[y]: + self.reverse_list[y].append(x) + + def add_missing(self, distribution, requirement): + """ + Add a missing *requirement* for the given *distribution*. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + :type requirement: ``str`` + """ + logger.debug('%s missing %r', distribution, requirement) + self.missing.setdefault(distribution, []).append(requirement) + + def _repr_dist(self, dist): + return '%s %s' % (dist.name, dist.version) + + def repr_node(self, dist, level=1): + """Prints only a subgraph""" + output = [self._repr_dist(dist)] + for other, label in self.adjacency_list[dist]: + dist = self._repr_dist(other) + if label is not None: + dist = '%s [%s]' % (dist, label) + output.append(' ' * level + str(dist)) + suboutput = self.repr_node(other, level + 1) + subs = suboutput.split('\n') + output.extend(subs[1:]) + return '\n'.join(output) + + def to_dot(self, f, skip_disconnected=True): + """Writes a DOT output for the graph to the provided file *f*. + + If *skip_disconnected* is set to ``True``, then all distributions + that are not dependent on any other distribution are skipped. + + :type f: has to support ``file``-like operations + :type skip_disconnected: ``bool`` + """ + disconnected = [] + + f.write("digraph dependencies {\n") + for dist, adjs in self.adjacency_list.items(): + if len(adjs) == 0 and not skip_disconnected: + disconnected.append(dist) + for other, label in adjs: + if not label is None: + f.write('"%s" -> "%s" [label="%s"]\n' % + (dist.name, other.name, label)) + else: + f.write('"%s" -> "%s"\n' % (dist.name, other.name)) + if not skip_disconnected and len(disconnected) > 0: + f.write('subgraph disconnected {\n') + f.write('label = "Disconnected"\n') + f.write('bgcolor = red\n') + + for dist in disconnected: + f.write('"%s"' % dist.name) + f.write('\n') + f.write('}\n') + f.write('}\n') + + def topological_sort(self): + """ + Perform a topological sort of the graph. + :return: A tuple, the first element of which is a topologically sorted + list of distributions, and the second element of which is a + list of distributions that cannot be sorted because they have + circular dependencies and so form a cycle. + """ + result = [] + # Make a shallow copy of the adjacency list + alist = {} + for k, v in self.adjacency_list.items(): + alist[k] = v[:] + while True: + # See what we can remove in this run + to_remove = [] + for k, v in list(alist.items())[:]: + if not v: + to_remove.append(k) + del alist[k] + if not to_remove: + # What's left in alist (if anything) is a cycle. + break + # Remove from the adjacency list of others + for k, v in alist.items(): + alist[k] = [(d, r) for d, r in v if d not in to_remove] + logger.debug('Moving to result: %s', + ['%s (%s)' % (d.name, d.version) for d in to_remove]) + result.extend(to_remove) + return result, list(alist.keys()) + + def __repr__(self): + """Representation of the graph""" + output = [] + for dist, adjs in self.adjacency_list.items(): + output.append(self.repr_node(dist)) + return '\n'.join(output) + + +def make_graph(dists, scheme='default'): + """Makes a dependency graph from the given distributions. + + :parameter dists: a list of distributions + :type dists: list of :class:`distutils2.database.InstalledDistribution` and + :class:`distutils2.database.EggInfoDistribution` instances + :rtype: a :class:`DependencyGraph` instance + """ + scheme = get_scheme(scheme) + graph = DependencyGraph() + provided = {} # maps names to lists of (version, dist) tuples + + # first, build the graph and find out what's provided + for dist in dists: + graph.add_distribution(dist) + + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + provided.setdefault(name, []).append((version, dist)) + + # now make the edges + for dist in dists: + requires = (dist.run_requires | dist.meta_requires | + dist.build_requires | dist.dev_requires) + for req in requires: + try: + matcher = scheme.matcher(req) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + matched = False + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + graph.add_edge(dist, provider, req) + matched = True + break + if not matched: + graph.add_missing(dist, req) + return graph + + +def get_dependent_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + dependent on *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + dep = [dist] # dependent distributions + todo = graph.reverse_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop() + dep.append(d) + for succ in graph.reverse_list[d]: + if succ not in dep: + todo.append(succ) + + dep.pop(0) # remove dist from dep, was there to prevent infinite loops + return dep + + +def get_required_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + required by *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + req = [] # required distributions + todo = graph.adjacency_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop()[0] + req.append(d) + for pred in graph.adjacency_list[d]: + if pred not in req: + todo.append(pred) + + return req + + +def make_dist(name, version, **kwargs): + """ + A convenience method for making a dist given just a name and version. + """ + summary = kwargs.pop('summary', 'Placeholder for summary') + md = Metadata(**kwargs) + md.name = name + md.version = version + md.summary = summary or 'Placeholder for summary' + return Distribution(md) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/index.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/index.py new file mode 100644 index 0000000..2406be2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/index.py @@ -0,0 +1,516 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import hashlib +import logging +import os +import shutil +import subprocess +import tempfile +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread + +from . import DistlibException +from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, + urlparse, build_opener, string_types) +from .util import cached_property, zip_dir, ServerProxy + +logger = logging.getLogger(__name__) + +DEFAULT_INDEX = 'https://pypi.python.org/pypi' +DEFAULT_REALM = 'pypi' + +class PackageIndex(object): + """ + This class represents a package index compatible with PyPI, the Python + Package Index. + """ + + boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' + + def __init__(self, url=None): + """ + Initialise an instance. + + :param url: The URL of the index. If not specified, the URL for PyPI is + used. + """ + self.url = url or DEFAULT_INDEX + self.read_configuration() + scheme, netloc, path, params, query, frag = urlparse(self.url) + if params or query or frag or scheme not in ('http', 'https'): + raise DistlibException('invalid repository: %s' % self.url) + self.password_handler = None + self.ssl_verifier = None + self.gpg = None + self.gpg_home = None + with open(os.devnull, 'w') as sink: + # Use gpg by default rather than gpg2, as gpg2 insists on + # prompting for passwords + for s in ('gpg', 'gpg2'): + try: + rc = subprocess.check_call([s, '--version'], stdout=sink, + stderr=sink) + if rc == 0: + self.gpg = s + break + except OSError: + pass + + def _get_pypirc_command(self): + """ + Get the distutils command for interacting with PyPI configurations. + :return: the command. + """ + from distutils.core import Distribution + from distutils.config import PyPIRCCommand + d = Distribution() + return PyPIRCCommand(d) + + def read_configuration(self): + """ + Read the PyPI access configuration as supported by distutils, getting + PyPI to do the actual work. This populates ``username``, ``password``, + ``realm`` and ``url`` attributes from the configuration. + """ + # get distutils to do the work + c = self._get_pypirc_command() + c.repository = self.url + cfg = c._read_pypirc() + self.username = cfg.get('username') + self.password = cfg.get('password') + self.realm = cfg.get('realm', 'pypi') + self.url = cfg.get('repository', self.url) + + def save_configuration(self): + """ + Save the PyPI access configuration. You must have set ``username`` and + ``password`` attributes before calling this method. + + Again, distutils is used to do the actual work. + """ + self.check_credentials() + # get distutils to do the work + c = self._get_pypirc_command() + c._store_pypirc(self.username, self.password) + + def check_credentials(self): + """ + Check that ``username`` and ``password`` have been set, and raise an + exception if not. + """ + if self.username is None or self.password is None: + raise DistlibException('username and password must be set') + pm = HTTPPasswordMgr() + _, netloc, _, _, _, _ = urlparse(self.url) + pm.add_password(self.realm, netloc, self.username, self.password) + self.password_handler = HTTPBasicAuthHandler(pm) + + def register(self, metadata): + """ + Register a distribution on PyPI, using the provided metadata. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the distribution to be + registered. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + metadata.validate() + d = metadata.todict() + d[':action'] = 'verify' + request = self.encode_request(d.items(), []) + response = self.send_request(request) + d[':action'] = 'submit' + request = self.encode_request(d.items(), []) + return self.send_request(request) + + def _reader(self, name, stream, outbuf): + """ + Thread runner for reading lines of from a subprocess into a buffer. + + :param name: The logical name of the stream (used for logging only). + :param stream: The stream to read from. This will typically a pipe + connected to the output stream of a subprocess. + :param outbuf: The list to append the read lines to. + """ + while True: + s = stream.readline() + if not s: + break + s = s.decode('utf-8').rstrip() + outbuf.append(s) + logger.debug('%s: %s' % (name, s)) + stream.close() + + def get_sign_command(self, filename, signer, sign_password, + keystore=None): + """ + Return a suitable command for signing a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The signing command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + if sign_password is not None: + cmd.extend(['--batch', '--passphrase-fd', '0']) + td = tempfile.mkdtemp() + sf = os.path.join(td, os.path.basename(filename) + '.asc') + cmd.extend(['--detach-sign', '--armor', '--local-user', + signer, '--output', sf, filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd, sf + + def run_command(self, cmd, input_data=None): + """ + Run a command in a child process , passing it any input data specified. + + :param cmd: The command to run. + :param input_data: If specified, this must be a byte string containing + data to be sent to the child process. + :return: A tuple consisting of the subprocess' exit code, a list of + lines read from the subprocess' ``stdout``, and a list of + lines read from the subprocess' ``stderr``. + """ + kwargs = { + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + } + if input_data is not None: + kwargs['stdin'] = subprocess.PIPE + stdout = [] + stderr = [] + p = subprocess.Popen(cmd, **kwargs) + # We don't use communicate() here because we may need to + # get clever with interacting with the command + t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) + t1.start() + t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) + t2.start() + if input_data is not None: + p.stdin.write(input_data) + p.stdin.close() + + p.wait() + t1.join() + t2.join() + return p.returncode, stdout, stderr + + def sign_file(self, filename, signer, sign_password, keystore=None): + """ + Sign a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The absolute pathname of the file where the signature is + stored. + """ + cmd, sig_file = self.get_sign_command(filename, signer, sign_password, + keystore) + rc, stdout, stderr = self.run_command(cmd, + sign_password.encode('utf-8')) + if rc != 0: + raise DistlibException('sign command failed with error ' + 'code %s' % rc) + return sig_file + + def upload_file(self, metadata, filename, signer=None, sign_password=None, + filetype='sdist', pyversion='source', keystore=None): + """ + Upload a release file to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the file to be uploaded. + :param filename: The pathname of the file to be uploaded. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param filetype: The type of the file being uploaded. This is the + distutils command which produced that file, e.g. + ``sdist`` or ``bdist_wheel``. + :param pyversion: The version of Python which the release relates + to. For code compatible with any Python, this would + be ``source``, otherwise it would be e.g. ``3.2``. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.exists(filename): + raise DistlibException('not found: %s' % filename) + metadata.validate() + d = metadata.todict() + sig_file = None + if signer: + if not self.gpg: + logger.warning('no signing program available - not signed') + else: + sig_file = self.sign_file(filename, signer, sign_password, + keystore) + with open(filename, 'rb') as f: + file_data = f.read() + md5_digest = hashlib.md5(file_data).hexdigest() + sha256_digest = hashlib.sha256(file_data).hexdigest() + d.update({ + ':action': 'file_upload', + 'protocol_version': '1', + 'filetype': filetype, + 'pyversion': pyversion, + 'md5_digest': md5_digest, + 'sha256_digest': sha256_digest, + }) + files = [('content', os.path.basename(filename), file_data)] + if sig_file: + with open(sig_file, 'rb') as f: + sig_data = f.read() + files.append(('gpg_signature', os.path.basename(sig_file), + sig_data)) + shutil.rmtree(os.path.dirname(sig_file)) + request = self.encode_request(d.items(), files) + return self.send_request(request) + + def upload_documentation(self, metadata, doc_dir): + """ + Upload documentation to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the documentation to be + uploaded. + :param doc_dir: The pathname of the directory which contains the + documentation. This should be the directory that + contains the ``index.html`` for the documentation. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.isdir(doc_dir): + raise DistlibException('not a directory: %r' % doc_dir) + fn = os.path.join(doc_dir, 'index.html') + if not os.path.exists(fn): + raise DistlibException('not found: %r' % fn) + metadata.validate() + name, version = metadata.name, metadata.version + zip_data = zip_dir(doc_dir).getvalue() + fields = [(':action', 'doc_upload'), + ('name', name), ('version', version)] + files = [('content', name, zip_data)] + request = self.encode_request(fields, files) + return self.send_request(request) + + def get_verify_command(self, signature_filename, data_filename, + keystore=None): + """ + Return a suitable command for verifying a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The verifying command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + cmd.extend(['--verify', signature_filename, data_filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd + + def verify_signature(self, signature_filename, data_filename, + keystore=None): + """ + Verify a signature for a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: True if the signature was verified, else False. + """ + if not self.gpg: + raise DistlibException('verification unavailable because gpg ' + 'unavailable') + cmd = self.get_verify_command(signature_filename, data_filename, + keystore) + rc, stdout, stderr = self.run_command(cmd) + if rc not in (0, 1): + raise DistlibException('verify command failed with error ' + 'code %s' % rc) + return rc == 0 + + def download_file(self, url, destfile, digest=None, reporthook=None): + """ + This is a convenience method for downloading a file from an URL. + Normally, this will be a file from the index, though currently + no check is made for this (i.e. a file can be downloaded from + anywhere). + + The method is just like the :func:`urlretrieve` function in the + standard library, except that it allows digest computation to be + done during download and checking that the downloaded data + matched any expected value. + + :param url: The URL of the file to be downloaded (assumed to be + available via an HTTP GET request). + :param destfile: The pathname where the downloaded file is to be + saved. + :param digest: If specified, this must be a (hasher, value) + tuple, where hasher is the algorithm used (e.g. + ``'md5'``) and ``value`` is the expected value. + :param reporthook: The same as for :func:`urlretrieve` in the + standard library. + """ + if digest is None: + digester = None + logger.debug('No digest specified') + else: + if isinstance(digest, (list, tuple)): + hasher, digest = digest + else: + hasher = 'md5' + digester = getattr(hashlib, hasher)() + logger.debug('Digest specified: %s' % digest) + # The following code is equivalent to urlretrieve. + # We need to do it this way so that we can compute the + # digest of the file as we go. + with open(destfile, 'wb') as dfp: + # addinfourl is not a context manager on 2.x + # so we have to use try/finally + sfp = self.send_request(Request(url)) + try: + headers = sfp.info() + blocksize = 8192 + size = -1 + read = 0 + blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) + if reporthook: + reporthook(blocknum, blocksize, size) + while True: + block = sfp.read(blocksize) + if not block: + break + read += len(block) + dfp.write(block) + if digester: + digester.update(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, blocksize, size) + finally: + sfp.close() + + # check that we got the whole file, if we can + if size >= 0 and read < size: + raise DistlibException( + 'retrieval incomplete: got only %d out of %d bytes' + % (read, size)) + # if we have a digest, it must match. + if digester: + actual = digester.hexdigest() + if digest != actual: + raise DistlibException('%s digest mismatch for %s: expected ' + '%s, got %s' % (hasher, destfile, + digest, actual)) + logger.debug('Digest verified: %s', digest) + + def send_request(self, req): + """ + Send a standard library :class:`Request` to PyPI and return its + response. + + :param req: The request to send. + :return: The HTTP response from PyPI (a standard library HTTPResponse). + """ + handlers = [] + if self.password_handler: + handlers.append(self.password_handler) + if self.ssl_verifier: + handlers.append(self.ssl_verifier) + opener = build_opener(*handlers) + return opener.open(req) + + def encode_request(self, fields, files): + """ + Encode fields and files for posting to an HTTP server. + + :param fields: The fields to send as a list of (fieldname, value) + tuples. + :param files: The files to send as a list of (fieldname, filename, + file_bytes) tuple. + """ + # Adapted from packaging, which in turn was adapted from + # http://code.activestate.com/recipes/146306 + + parts = [] + boundary = self.boundary + for k, values in fields: + if not isinstance(values, (list, tuple)): + values = [values] + + for v in values: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"' % + k).encode('utf-8'), + b'', + v.encode('utf-8'))) + for key, filename, value in files: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)).encode('utf-8'), + b'', + value)) + + parts.extend((b'--' + boundary + b'--', b'')) + + body = b'\r\n'.join(parts) + ct = b'multipart/form-data; boundary=' + boundary + headers = { + 'Content-type': ct, + 'Content-length': str(len(body)) + } + return Request(self.url, body, headers) + + def search(self, terms, operator=None): + if isinstance(terms, string_types): + terms = {'name': terms} + rpc_proxy = ServerProxy(self.url, timeout=3.0) + try: + return rpc_proxy.search(terms, operator or 'and') + finally: + rpc_proxy('close')() diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/locators.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/locators.py new file mode 100644 index 0000000..11d2636 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/locators.py @@ -0,0 +1,1292 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# + +import gzip +from io import BytesIO +import json +import logging +import os +import posixpath +import re +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import zlib + +from . import DistlibException +from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, + queue, quote, unescape, string_types, build_opener, + HTTPRedirectHandler as BaseRedirectHandler, text_type, + Request, HTTPError, URLError) +from .database import Distribution, DistributionPath, make_dist +from .metadata import Metadata, MetadataInvalidError +from .util import (cached_property, parse_credentials, ensure_slash, + split_filename, get_project_data, parse_requirement, + parse_name_and_version, ServerProxy, normalize_name) +from .version import get_scheme, UnsupportedVersionError +from .wheel import Wheel, is_compatible + +logger = logging.getLogger(__name__) + +HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)') +CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) +HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') +DEFAULT_INDEX = 'https://pypi.python.org/pypi' + +def get_all_distribution_names(url=None): + """ + Return all distribution names known by an index. + :param url: The URL of the index. + :return: A list of all known distribution names. + """ + if url is None: + url = DEFAULT_INDEX + client = ServerProxy(url, timeout=3.0) + try: + return client.list_packages() + finally: + client('close')() + +class RedirectHandler(BaseRedirectHandler): + """ + A class to work around a bug in some Python 3.2.x releases. + """ + # There's a bug in the base version for some 3.2.x + # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header + # returns e.g. /abc, it bails because it says the scheme '' + # is bogus, when actually it should use the request's + # URL for the scheme. See Python issue #13696. + def http_error_302(self, req, fp, code, msg, headers): + # Some servers (incorrectly) return multiple Location headers + # (so probably same goes for URI). Use first header. + newurl = None + for key in ('location', 'uri'): + if key in headers: + newurl = headers[key] + break + if newurl is None: # pragma: no cover + return + urlparts = urlparse(newurl) + if urlparts.scheme == '': + newurl = urljoin(req.get_full_url(), newurl) + if hasattr(headers, 'replace_header'): + headers.replace_header(key, newurl) + else: + headers[key] = newurl + return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, + headers) + + http_error_301 = http_error_303 = http_error_307 = http_error_302 + +class Locator(object): + """ + A base class for locators - things that locate distributions. + """ + source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') + binary_extensions = ('.egg', '.exe', '.whl') + excluded_extensions = ('.pdf',) + + # A list of tags indicating which wheels you want to match. The default + # value of None matches against the tags compatible with the running + # Python. If you want to match other values, set wheel_tags on a locator + # instance to a list of tuples (pyver, abi, arch) which you want to match. + wheel_tags = None + + downloadable_extensions = source_extensions + ('.whl',) + + def __init__(self, scheme='default'): + """ + Initialise an instance. + :param scheme: Because locators look for most recent versions, they + need to know the version scheme to use. This specifies + the current PEP-recommended scheme - use ``'legacy'`` + if you need to support existing distributions on PyPI. + """ + self._cache = {} + self.scheme = scheme + # Because of bugs in some of the handlers on some of the platforms, + # we use our own opener rather than just using urlopen. + self.opener = build_opener(RedirectHandler()) + # If get_project() is called from locate(), the matcher instance + # is set from the requirement passed to locate(). See issue #18 for + # why this can be useful to know. + self.matcher = None + self.errors = queue.Queue() + + def get_errors(self): + """ + Return any errors which have occurred. + """ + result = [] + while not self.errors.empty(): # pragma: no cover + try: + e = self.errors.get(False) + result.append(e) + except self.errors.Empty: + continue + self.errors.task_done() + return result + + def clear_errors(self): + """ + Clear any errors which may have been logged. + """ + # Just get the errors and throw them away + self.get_errors() + + def clear_cache(self): + self._cache.clear() + + def _get_scheme(self): + return self._scheme + + def _set_scheme(self, value): + self._scheme = value + + scheme = property(_get_scheme, _set_scheme) + + def _get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This should be implemented in subclasses. + + If called from a locate() request, self.matcher will be set to a + matcher for the requirement to satisfy, otherwise it will be None. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This calls _get_project to do all the work, and just implements a caching layer on top. + """ + if self._cache is None: # pragma: no cover + result = self._get_project(name) + elif name in self._cache: + result = self._cache[name] + else: + self.clear_errors() + result = self._get_project(name) + self._cache[name] = result + return result + + def score_url(self, url): + """ + Give an url a score which can be used to choose preferred URLs + for a given project release. + """ + t = urlparse(url) + basename = posixpath.basename(t.path) + compatible = True + is_wheel = basename.endswith('.whl') + is_downloadable = basename.endswith(self.downloadable_extensions) + if is_wheel: + compatible = is_compatible(Wheel(basename), self.wheel_tags) + return (t.scheme == 'https', 'pypi.python.org' in t.netloc, + is_downloadable, is_wheel, compatible, basename) + + def prefer_url(self, url1, url2): + """ + Choose one of two URLs where both are candidates for distribution + archives for the same version of a distribution (for example, + .tar.gz vs. zip). + + The current implementation favours https:// URLs over http://, archives + from PyPI over those from other locations, wheel compatibility (if a + wheel) and then the archive name. + """ + result = url2 + if url1: + s1 = self.score_url(url1) + s2 = self.score_url(url2) + if s1 > s2: + result = url1 + if result != url2: + logger.debug('Not replacing %r with %r', url1, url2) + else: + logger.debug('Replacing %r with %r', url1, url2) + return result + + def split_filename(self, filename, project_name): + """ + Attempt to split a filename in project name, version and Python version. + """ + return split_filename(filename, project_name) + + def convert_url_to_download_info(self, url, project_name): + """ + See if a URL is a candidate for a download URL for a project (the URL + has typically been scraped from an HTML page). + + If it is, a dictionary is returned with keys "name", "version", + "filename" and "url"; otherwise, None is returned. + """ + def same_project(name1, name2): + return normalize_name(name1) == normalize_name(name2) + + result = None + scheme, netloc, path, params, query, frag = urlparse(url) + if frag.lower().startswith('egg='): # pragma: no cover + logger.debug('%s: version hint in fragment: %r', + project_name, frag) + m = HASHER_HASH.match(frag) + if m: + algo, digest = m.groups() + else: + algo, digest = None, None + origpath = path + if path and path[-1] == '/': # pragma: no cover + path = path[:-1] + if path.endswith('.whl'): + try: + wheel = Wheel(path) + if is_compatible(wheel, self.wheel_tags): + if project_name is None: + include = True + else: + include = same_project(wheel.name, project_name) + if include: + result = { + 'name': wheel.name, + 'version': wheel.version, + 'filename': wheel.filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + 'python-version': ', '.join( + ['.'.join(list(v[2:])) for v in wheel.pyver]), + } + except Exception as e: # pragma: no cover + logger.warning('invalid path for wheel: %s', path) + elif not path.endswith(self.downloadable_extensions): # pragma: no cover + logger.debug('Not downloadable: %s', path) + else: # downloadable extension + path = filename = posixpath.basename(path) + for ext in self.downloadable_extensions: + if path.endswith(ext): + path = path[:-len(ext)] + t = self.split_filename(path, project_name) + if not t: # pragma: no cover + logger.debug('No match for project/version: %s', path) + else: + name, version, pyver = t + if not project_name or same_project(project_name, name): + result = { + 'name': name, + 'version': version, + 'filename': filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + #'packagetype': 'sdist', + } + if pyver: # pragma: no cover + result['python-version'] = pyver + break + if result and algo: + result['%s_digest' % algo] = digest + return result + + def _get_digest(self, info): + """ + Get a digest from a dictionary by looking at keys of the form + 'algo_digest'. + + Returns a 2-tuple (algo, digest) if found, else None. Currently + looks only for SHA256, then MD5. + """ + result = None + for algo in ('sha256', 'md5'): + key = '%s_digest' % algo + if key in info: + result = (algo, info[key]) + break + return result + + def _update_version_data(self, result, info): + """ + Update a result dictionary (the final result from _get_project) with a + dictionary for a specific version, which typically holds information + gleaned from a filename or URL for an archive for the distribution. + """ + name = info.pop('name') + version = info.pop('version') + if version in result: + dist = result[version] + md = dist.metadata + else: + dist = make_dist(name, version, scheme=self.scheme) + md = dist.metadata + dist.digest = digest = self._get_digest(info) + url = info['url'] + result['digests'][url] = digest + if md.source_url != info['url']: + md.source_url = self.prefer_url(md.source_url, url) + result['urls'].setdefault(version, set()).add(url) + dist.locator = self + result[version] = dist + + def locate(self, requirement, prereleases=False): + """ + Find the most recent distribution which matches the given + requirement. + + :param requirement: A requirement of the form 'foo (1.0)' or perhaps + 'foo (>= 1.0, < 2.0, != 1.3)' + :param prereleases: If ``True``, allow pre-release versions + to be located. Otherwise, pre-release versions + are not returned. + :return: A :class:`Distribution` instance, or ``None`` if no such + distribution could be located. + """ + result = None + r = parse_requirement(requirement) + if r is None: # pragma: no cover + raise DistlibException('Not a valid requirement: %r' % requirement) + scheme = get_scheme(self.scheme) + self.matcher = matcher = scheme.matcher(r.requirement) + logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) + versions = self.get_project(r.name) + if len(versions) > 2: # urls and digests keys are present + # sometimes, versions are invalid + slist = [] + vcls = matcher.version_class + for k in versions: + if k in ('urls', 'digests'): + continue + try: + if not matcher.match(k): + logger.debug('%s did not match %r', matcher, k) + else: + if prereleases or not vcls(k).is_prerelease: + slist.append(k) + else: + logger.debug('skipping pre-release ' + 'version %s of %s', k, matcher.name) + except Exception: # pragma: no cover + logger.warning('error matching %s with %r', matcher, k) + pass # slist.append(k) + if len(slist) > 1: + slist = sorted(slist, key=scheme.key) + if slist: + logger.debug('sorted list: %s', slist) + version = slist[-1] + result = versions[version] + if result: + if r.extras: + result.extras = r.extras + result.download_urls = versions.get('urls', {}).get(version, set()) + d = {} + sd = versions.get('digests', {}) + for url in result.download_urls: + if url in sd: # pragma: no cover + d[url] = sd[url] + result.digests = d + self.matcher = None + return result + + +class PyPIRPCLocator(Locator): + """ + This locator uses XML-RPC to locate distributions. It therefore + cannot be used with simple mirrors (that only mirror file content). + """ + def __init__(self, url, **kwargs): + """ + Initialise an instance. + + :param url: The URL to use for XML-RPC. + :param kwargs: Passed to the superclass constructor. + """ + super(PyPIRPCLocator, self).__init__(**kwargs) + self.base_url = url + self.client = ServerProxy(url, timeout=3.0) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + return set(self.client.list_packages()) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + versions = self.client.package_releases(name, True) + for v in versions: + urls = self.client.release_urls(name, v) + data = self.client.release_data(name, v) + metadata = Metadata(scheme=self.scheme) + metadata.name = data['name'] + metadata.version = data['version'] + metadata.license = data.get('license') + metadata.keywords = data.get('keywords', []) + metadata.summary = data.get('summary') + dist = Distribution(metadata) + if urls: + info = urls[0] + metadata.source_url = info['url'] + dist.digest = self._get_digest(info) + dist.locator = self + result[v] = dist + for info in urls: + url = info['url'] + digest = self._get_digest(info) + result['urls'].setdefault(v, set()).add(url) + result['digests'][url] = digest + return result + +class PyPIJSONLocator(Locator): + """ + This locator uses PyPI's JSON interface. It's very limited in functionality + and probably not worth using. + """ + def __init__(self, url, **kwargs): + super(PyPIJSONLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + url = urljoin(self.base_url, '%s/json' % quote(name)) + try: + resp = self.opener.open(url) + data = resp.read().decode() # for now + d = json.loads(data) + md = Metadata(scheme=self.scheme) + data = d['info'] + md.name = data['name'] + md.version = data['version'] + md.license = data.get('license') + md.keywords = data.get('keywords', []) + md.summary = data.get('summary') + dist = Distribution(md) + dist.locator = self + urls = d['urls'] + result[md.version] = dist + for info in d['urls']: + url = info['url'] + dist.download_urls.add(url) + dist.digests[url] = self._get_digest(info) + result['urls'].setdefault(md.version, set()).add(url) + result['digests'][url] = self._get_digest(info) + # Now get other releases + for version, infos in d['releases'].items(): + if version == md.version: + continue # already done + omd = Metadata(scheme=self.scheme) + omd.name = md.name + omd.version = version + odist = Distribution(omd) + odist.locator = self + result[version] = odist + for info in infos: + url = info['url'] + odist.download_urls.add(url) + odist.digests[url] = self._get_digest(info) + result['urls'].setdefault(version, set()).add(url) + result['digests'][url] = self._get_digest(info) +# for info in urls: +# md.source_url = info['url'] +# dist.digest = self._get_digest(info) +# dist.locator = self +# for info in urls: +# url = info['url'] +# result['urls'].setdefault(md.version, set()).add(url) +# result['digests'][url] = self._get_digest(info) + except Exception as e: + self.errors.put(text_type(e)) + logger.exception('JSON fetch failed: %s', e) + return result + + +class Page(object): + """ + This class represents a scraped HTML page. + """ + # The following slightly hairy-looking regex just looks for the contents of + # an anchor link, which has an attribute "href" either immediately preceded + # or immediately followed by a "rel" attribute. The attribute values can be + # declared with double quotes, single quotes or no quotes - which leads to + # the length of the expression. + _href = re.compile(""" +(rel\\s*=\\s*(?:"(?P<rel1>[^"]*)"|'(?P<rel2>[^']*)'|(?P<rel3>[^>\\s\n]*))\\s+)? +href\\s*=\\s*(?:"(?P<url1>[^"]*)"|'(?P<url2>[^']*)'|(?P<url3>[^>\\s\n]*)) +(\\s+rel\\s*=\\s*(?:"(?P<rel4>[^"]*)"|'(?P<rel5>[^']*)'|(?P<rel6>[^>\\s\n]*)))? +""", re.I | re.S | re.X) + _base = re.compile(r"""<base\s+href\s*=\s*['"]?([^'">]+)""", re.I | re.S) + + def __init__(self, data, url): + """ + Initialise an instance with the Unicode page contents and the URL they + came from. + """ + self.data = data + self.base_url = self.url = url + m = self._base.search(self.data) + if m: + self.base_url = m.group(1) + + _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + @cached_property + def links(self): + """ + Return the URLs of all the links on a page together with information + about their "rel" attribute, for determining which ones to treat as + downloads and which ones to queue for further scraping. + """ + def clean(url): + "Tidy up an URL." + scheme, netloc, path, params, query, frag = urlparse(url) + return urlunparse((scheme, netloc, quote(path), + params, query, frag)) + + result = set() + for match in self._href.finditer(self.data): + d = match.groupdict('') + rel = (d['rel1'] or d['rel2'] or d['rel3'] or + d['rel4'] or d['rel5'] or d['rel6']) + url = d['url1'] or d['url2'] or d['url3'] + url = urljoin(self.base_url, url) + url = unescape(url) + url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) + result.add((url, rel)) + # We sort the result, hoping to bring the most recent versions + # to the front + result = sorted(result, key=lambda t: t[0], reverse=True) + return result + + +class SimpleScrapingLocator(Locator): + """ + A locator which scrapes HTML pages to locate downloads for a distribution. + This runs multiple threads to do the I/O; performance is at least as good + as pip's PackageFinder, which works in an analogous fashion. + """ + + # These are used to deal with various Content-Encoding schemes. + decoders = { + 'deflate': zlib.decompress, + 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(), + 'none': lambda b: b, + } + + def __init__(self, url, timeout=None, num_workers=10, **kwargs): + """ + Initialise an instance. + :param url: The root URL to use for scraping. + :param timeout: The timeout, in seconds, to be applied to requests. + This defaults to ``None`` (no timeout specified). + :param num_workers: The number of worker threads you want to do I/O, + This defaults to 10. + :param kwargs: Passed to the superclass. + """ + super(SimpleScrapingLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + self.timeout = timeout + self._page_cache = {} + self._seen = set() + self._to_fetch = queue.Queue() + self._bad_hosts = set() + self.skip_externals = False + self.num_workers = num_workers + self._lock = threading.RLock() + # See issue #45: we need to be resilient when the locator is used + # in a thread, e.g. with concurrent.futures. We can't use self._lock + # as it is for coordinating our internal threads - the ones created + # in _prepare_threads. + self._gplock = threading.RLock() + + def _prepare_threads(self): + """ + Threads are created only when get_project is called, and terminate + before it returns. They are there primarily to parallelise I/O (i.e. + fetching web pages). + """ + self._threads = [] + for i in range(self.num_workers): + t = threading.Thread(target=self._fetch) + t.setDaemon(True) + t.start() + self._threads.append(t) + + def _wait_threads(self): + """ + Tell all the threads to terminate (by sending a sentinel value) and + wait for them to do so. + """ + # Note that you need two loops, since you can't say which + # thread will get each sentinel + for t in self._threads: + self._to_fetch.put(None) # sentinel + for t in self._threads: + t.join() + self._threads = [] + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + with self._gplock: + self.result = result + self.project_name = name + url = urljoin(self.base_url, '%s/' % quote(name)) + self._seen.clear() + self._page_cache.clear() + self._prepare_threads() + try: + logger.debug('Queueing %s', url) + self._to_fetch.put(url) + self._to_fetch.join() + finally: + self._wait_threads() + del self.result + return result + + platform_dependent = re.compile(r'\b(linux-(i\d86|x86_64|arm\w+)|' + r'win(32|-amd64)|macosx-?\d+)\b', re.I) + + def _is_platform_dependent(self, url): + """ + Does an URL refer to a platform-specific download? + """ + return self.platform_dependent.search(url) + + def _process_download(self, url): + """ + See if an URL is a suitable download for a project. + + If it is, register information in the result dictionary (for + _get_project) about the specific version it's for. + + Note that the return value isn't actually used other than as a boolean + value. + """ + if self._is_platform_dependent(url): + info = None + else: + info = self.convert_url_to_download_info(url, self.project_name) + logger.debug('process_download: %s -> %s', url, info) + if info: + with self._lock: # needed because self.result is shared + self._update_version_data(self.result, info) + return info + + def _should_queue(self, link, referrer, rel): + """ + Determine whether a link URL from a referring page and with a + particular "rel" attribute should be queued for scraping. + """ + scheme, netloc, path, _, _, _ = urlparse(link) + if path.endswith(self.source_extensions + self.binary_extensions + + self.excluded_extensions): + result = False + elif self.skip_externals and not link.startswith(self.base_url): + result = False + elif not referrer.startswith(self.base_url): + result = False + elif rel not in ('homepage', 'download'): + result = False + elif scheme not in ('http', 'https', 'ftp'): + result = False + elif self._is_platform_dependent(link): + result = False + else: + host = netloc.split(':', 1)[0] + if host.lower() == 'localhost': + result = False + else: + result = True + logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, + referrer, result) + return result + + def _fetch(self): + """ + Get a URL to fetch from the work queue, get the HTML page, examine its + links for download candidates and candidates for further scraping. + + This is a handy method to run in a thread. + """ + while True: + url = self._to_fetch.get() + try: + if url: + page = self.get_page(url) + if page is None: # e.g. after an error + continue + for link, rel in page.links: + if link not in self._seen: + try: + self._seen.add(link) + if (not self._process_download(link) and + self._should_queue(link, url, rel)): + logger.debug('Queueing %s from %s', link, url) + self._to_fetch.put(link) + except MetadataInvalidError: # e.g. invalid versions + pass + except Exception as e: # pragma: no cover + self.errors.put(text_type(e)) + finally: + # always do this, to avoid hangs :-) + self._to_fetch.task_done() + if not url: + #logger.debug('Sentinel seen, quitting.') + break + + def get_page(self, url): + """ + Get the HTML for an URL, possibly from an in-memory cache. + + XXX TODO Note: this cache is never actually cleared. It's assumed that + the data won't get stale over the lifetime of a locator instance (not + necessarily true for the default_locator). + """ + # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api + scheme, netloc, path, _, _, _ = urlparse(url) + if scheme == 'file' and os.path.isdir(url2pathname(path)): + url = urljoin(ensure_slash(url), 'index.html') + + if url in self._page_cache: + result = self._page_cache[url] + logger.debug('Returning %s from cache: %s', url, result) + else: + host = netloc.split(':', 1)[0] + result = None + if host in self._bad_hosts: + logger.debug('Skipping %s due to bad host %s', url, host) + else: + req = Request(url, headers={'Accept-encoding': 'identity'}) + try: + logger.debug('Fetching %s', url) + resp = self.opener.open(req, timeout=self.timeout) + logger.debug('Fetched %s', url) + headers = resp.info() + content_type = headers.get('Content-Type', '') + if HTML_CONTENT_TYPE.match(content_type): + final_url = resp.geturl() + data = resp.read() + encoding = headers.get('Content-Encoding') + if encoding: + decoder = self.decoders[encoding] # fail if not found + data = decoder(data) + encoding = 'utf-8' + m = CHARSET.search(content_type) + if m: + encoding = m.group(1) + try: + data = data.decode(encoding) + except UnicodeError: # pragma: no cover + data = data.decode('latin-1') # fallback + result = Page(data, final_url) + self._page_cache[final_url] = result + except HTTPError as e: + if e.code != 404: + logger.exception('Fetch failed: %s: %s', url, e) + except URLError as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + with self._lock: + self._bad_hosts.add(host) + except Exception as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + finally: + self._page_cache[url] = result # even if None (failure) + return result + + _distname_re = re.compile('<a href=[^>]*>([^<]+)<') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + page = self.get_page(self.base_url) + if not page: + raise DistlibException('Unable to get %s' % self.base_url) + for match in self._distname_re.finditer(page.data): + result.add(match.group(1)) + return result + +class DirectoryLocator(Locator): + """ + This class locates distributions in a directory tree. + """ + + def __init__(self, path, **kwargs): + """ + Initialise an instance. + :param path: The root of the directory tree to search. + :param kwargs: Passed to the superclass constructor, + except for: + * recursive - if True (the default), subdirectories are + recursed into. If False, only the top-level directory + is searched, + """ + self.recursive = kwargs.pop('recursive', True) + super(DirectoryLocator, self).__init__(**kwargs) + path = os.path.abspath(path) + if not os.path.isdir(path): # pragma: no cover + raise DistlibException('Not a directory: %r' % path) + self.base_dir = path + + def should_include(self, filename, parent): + """ + Should a filename be considered as a candidate for a distribution + archive? As well as the filename, the directory which contains it + is provided, though not used by the current implementation. + """ + return filename.endswith(self.downloadable_extensions) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, name) + if info: + self._update_version_data(result, info) + if not self.recursive: + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, None) + if info: + result.add(info['name']) + if not self.recursive: + break + return result + +class JSONLocator(Locator): + """ + This locator uses special extended metadata (not available on PyPI) and is + the basis of performant dependency resolution in distlib. Other locators + require archive downloads before dependencies can be determined! As you + might imagine, that can be slow. + """ + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + data = get_project_data(name) + if data: + for info in data.get('files', []): + if info['ptype'] != 'sdist' or info['pyversion'] != 'source': + continue + # We don't store summary in project metadata as it makes + # the data bigger for no benefit during dependency + # resolution + dist = make_dist(data['name'], info['version'], + summary=data.get('summary', + 'Placeholder for summary'), + scheme=self.scheme) + md = dist.metadata + md.source_url = info['url'] + # TODO SHA256 digest + if 'digest' in info and info['digest']: + dist.digest = ('md5', info['digest']) + md.dependencies = info.get('requirements', {}) + dist.exports = info.get('exports', {}) + result[dist.version] = dist + result['urls'].setdefault(dist.version, set()).add(info['url']) + return result + +class DistPathLocator(Locator): + """ + This locator finds installed distributions in a path. It can be useful for + adding to an :class:`AggregatingLocator`. + """ + def __init__(self, distpath, **kwargs): + """ + Initialise an instance. + + :param distpath: A :class:`DistributionPath` instance to search. + """ + super(DistPathLocator, self).__init__(**kwargs) + assert isinstance(distpath, DistributionPath) + self.distpath = distpath + + def _get_project(self, name): + dist = self.distpath.get_distribution(name) + if dist is None: + result = {'urls': {}, 'digests': {}} + else: + result = { + dist.version: dist, + 'urls': {dist.version: set([dist.source_url])}, + 'digests': {dist.version: set([None])} + } + return result + + +class AggregatingLocator(Locator): + """ + This class allows you to chain and/or merge a list of locators. + """ + def __init__(self, *locators, **kwargs): + """ + Initialise an instance. + + :param locators: The list of locators to search. + :param kwargs: Passed to the superclass constructor, + except for: + * merge - if False (the default), the first successful + search from any of the locators is returned. If True, + the results from all locators are merged (this can be + slow). + """ + self.merge = kwargs.pop('merge', False) + self.locators = locators + super(AggregatingLocator, self).__init__(**kwargs) + + def clear_cache(self): + super(AggregatingLocator, self).clear_cache() + for locator in self.locators: + locator.clear_cache() + + def _set_scheme(self, value): + self._scheme = value + for locator in self.locators: + locator.scheme = value + + scheme = property(Locator.scheme.fget, _set_scheme) + + def _get_project(self, name): + result = {} + for locator in self.locators: + d = locator.get_project(name) + if d: + if self.merge: + files = result.get('urls', {}) + digests = result.get('digests', {}) + # next line could overwrite result['urls'], result['digests'] + result.update(d) + df = result.get('urls') + if files and df: + for k, v in files.items(): + if k in df: + df[k] |= v + else: + df[k] = v + dd = result.get('digests') + if digests and dd: + dd.update(digests) + else: + # See issue #18. If any dists are found and we're looking + # for specific constraints, we only return something if + # a match is found. For example, if a DirectoryLocator + # returns just foo (1.0) while we're looking for + # foo (>= 2.0), we'll pretend there was nothing there so + # that subsequent locators can be queried. Otherwise we + # would just return foo (1.0) which would then lead to a + # failure to find foo (>= 2.0), because other locators + # weren't searched. Note that this only matters when + # merge=False. + if self.matcher is None: + found = True + else: + found = False + for k in d: + if self.matcher.match(k): + found = True + break + if found: + result = d + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for locator in self.locators: + try: + result |= locator.get_distribution_names() + except NotImplementedError: + pass + return result + + +# We use a legacy scheme simply because most of the dists on PyPI use legacy +# versions which don't conform to PEP 426 / PEP 440. +default_locator = AggregatingLocator( + JSONLocator(), + SimpleScrapingLocator('https://pypi.python.org/simple/', + timeout=3.0), + scheme='legacy') + +locate = default_locator.locate + +NAME_VERSION_RE = re.compile(r'(?P<name>[\w-]+)\s*' + r'\(\s*(==\s*)?(?P<ver>[^)]+)\)$') + +class DependencyFinder(object): + """ + Locate dependencies for distributions. + """ + + def __init__(self, locator=None): + """ + Initialise an instance, using the specified locator + to locate distributions. + """ + self.locator = locator or default_locator + self.scheme = get_scheme(self.locator.scheme) + + def add_distribution(self, dist): + """ + Add a distribution to the finder. This will update internal information + about who provides what. + :param dist: The distribution to add. + """ + logger.debug('adding distribution %s', dist) + name = dist.key + self.dists_by_name[name] = dist + self.dists[(name, dist.version)] = dist + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + self.provided.setdefault(name, set()).add((version, dist)) + + def remove_distribution(self, dist): + """ + Remove a distribution from the finder. This will update internal + information about who provides what. + :param dist: The distribution to remove. + """ + logger.debug('removing distribution %s', dist) + name = dist.key + del self.dists_by_name[name] + del self.dists[(name, dist.version)] + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Remove from provided: %s, %s, %s', name, version, dist) + s = self.provided[name] + s.remove((version, dist)) + if not s: + del self.provided[name] + + def get_matcher(self, reqt): + """ + Get a version matcher for a requirement. + :param reqt: The requirement + :type reqt: str + :return: A version matcher (an instance of + :class:`distlib.version.Matcher`). + """ + try: + matcher = self.scheme.matcher(reqt) + except UnsupportedVersionError: # pragma: no cover + # XXX compat-mode if cannot read the version + name = reqt.split()[0] + matcher = self.scheme.matcher(name) + return matcher + + def find_providers(self, reqt): + """ + Find the distributions which can fulfill a requirement. + + :param reqt: The requirement. + :type reqt: str + :return: A set of distribution which can fulfill the requirement. + """ + matcher = self.get_matcher(reqt) + name = matcher.key # case-insensitive + result = set() + provided = self.provided + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + result.add(provider) + break + return result + + def try_to_replace(self, provider, other, problems): + """ + Attempt to replace one provider with another. This is typically used + when resolving dependencies from multiple sources, e.g. A requires + (B >= 1.0) while C requires (B >= 1.1). + + For successful replacement, ``provider`` must meet all the requirements + which ``other`` fulfills. + + :param provider: The provider we are trying to replace with. + :param other: The provider we're trying to replace. + :param problems: If False is returned, this will contain what + problems prevented replacement. This is currently + a tuple of the literal string 'cantreplace', + ``provider``, ``other`` and the set of requirements + that ``provider`` couldn't fulfill. + :return: True if we can replace ``other`` with ``provider``, else + False. + """ + rlist = self.reqts[other] + unmatched = set() + for s in rlist: + matcher = self.get_matcher(s) + if not matcher.match(provider.version): + unmatched.add(s) + if unmatched: + # can't replace other with provider + problems.add(('cantreplace', provider, other, + frozenset(unmatched))) + result = False + else: + # can replace other with provider + self.remove_distribution(other) + del self.reqts[other] + for s in rlist: + self.reqts.setdefault(provider, set()).add(s) + self.add_distribution(provider) + result = True + return result + + def find(self, requirement, meta_extras=None, prereleases=False): + """ + Find a distribution and all distributions it depends on. + + :param requirement: The requirement specifying the distribution to + find, or a Distribution instance. + :param meta_extras: A list of meta extras such as :test:, :build: and + so on. + :param prereleases: If ``True``, allow pre-release versions to be + returned - otherwise, don't return prereleases + unless they're all that's available. + + Return a set of :class:`Distribution` instances and a set of + problems. + + The distributions returned should be such that they have the + :attr:`required` attribute set to ``True`` if they were + from the ``requirement`` passed to ``find()``, and they have the + :attr:`build_time_dependency` attribute set to ``True`` unless they + are post-installation dependencies of the ``requirement``. + + The problems should be a tuple consisting of the string + ``'unsatisfied'`` and the requirement which couldn't be satisfied + by any distribution known to the locator. + """ + + self.provided = {} + self.dists = {} + self.dists_by_name = {} + self.reqts = {} + + meta_extras = set(meta_extras or []) + if ':*:' in meta_extras: + meta_extras.remove(':*:') + # :meta: and :run: are implicitly included + meta_extras |= set([':test:', ':build:', ':dev:']) + + if isinstance(requirement, Distribution): + dist = odist = requirement + logger.debug('passed %s as requirement', odist) + else: + dist = odist = self.locator.locate(requirement, + prereleases=prereleases) + if dist is None: + raise DistlibException('Unable to locate %r' % requirement) + logger.debug('located %s', odist) + dist.requested = True + problems = set() + todo = set([dist]) + install_dists = set([odist]) + while todo: + dist = todo.pop() + name = dist.key # case-insensitive + if name not in self.dists_by_name: + self.add_distribution(dist) + else: + #import pdb; pdb.set_trace() + other = self.dists_by_name[name] + if other != dist: + self.try_to_replace(dist, other, problems) + + ireqts = dist.run_requires | dist.meta_requires + sreqts = dist.build_requires + ereqts = set() + if meta_extras and dist in install_dists: + for key in ('test', 'build', 'dev'): + e = ':%s:' % key + if e in meta_extras: + ereqts |= getattr(dist, '%s_requires' % key) + all_reqts = ireqts | sreqts | ereqts + for r in all_reqts: + providers = self.find_providers(r) + if not providers: + logger.debug('No providers found for %r', r) + provider = self.locator.locate(r, prereleases=prereleases) + # If no provider is found and we didn't consider + # prereleases, consider them now. + if provider is None and not prereleases: + provider = self.locator.locate(r, prereleases=True) + if provider is None: + logger.debug('Cannot satisfy %r', r) + problems.add(('unsatisfied', r)) + else: + n, v = provider.key, provider.version + if (n, v) not in self.dists: + todo.add(provider) + providers.add(provider) + if r in ireqts and dist in install_dists: + install_dists.add(provider) + logger.debug('Adding %s to install_dists', + provider.name_and_version) + for p in providers: + name = p.key + if name not in self.dists_by_name: + self.reqts.setdefault(p, set()).add(r) + else: + other = self.dists_by_name[name] + if other != p: + # see if other can be replaced by p + self.try_to_replace(p, other, problems) + + dists = set(self.dists.values()) + for dist in dists: + dist.build_time_dependency = dist not in install_dists + if dist.build_time_dependency: + logger.debug('%s is a build-time dependency only.', + dist.name_and_version) + logger.debug('find done for %s', odist) + return dists, problems diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/manifest.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/manifest.py new file mode 100644 index 0000000..ca0fe44 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/manifest.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Class representing the list of files in a distribution. + +Equivalent to distutils.filelist, but fixes some problems. +""" +import fnmatch +import logging +import os +import re +import sys + +from . import DistlibException +from .compat import fsdecode +from .util import convert_path + + +__all__ = ['Manifest'] + +logger = logging.getLogger(__name__) + +# a \ followed by some spaces + EOL +_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M) +_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) + +# +# Due to the different results returned by fnmatch.translate, we need +# to do slightly different processing for Python 2.7 and 3.2 ... this needed +# to be brought in for Python 3.6 onwards. +# +_PYTHON_VERSION = sys.version_info[:2] + +class Manifest(object): + """A list of files built by on exploring the filesystem and filtered by + applying various patterns to what we find there. + """ + + def __init__(self, base=None): + """ + Initialise an instance. + + :param base: The base directory to explore under. + """ + self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) + self.prefix = self.base + os.sep + self.allfiles = None + self.files = set() + + # + # Public API + # + + def findall(self): + """Find all files under the base and set ``allfiles`` to the absolute + pathnames of files found. + """ + from stat import S_ISREG, S_ISDIR, S_ISLNK + + self.allfiles = allfiles = [] + root = self.base + stack = [root] + pop = stack.pop + push = stack.append + + while stack: + root = pop() + names = os.listdir(root) + + for name in names: + fullname = os.path.join(root, name) + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat.st_mode + if S_ISREG(mode): + allfiles.append(fsdecode(fullname)) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push(fullname) + + def add(self, item): + """ + Add a file to the manifest. + + :param item: The pathname to add. This can be relative to the base. + """ + if not item.startswith(self.prefix): + item = os.path.join(self.base, item) + self.files.add(os.path.normpath(item)) + + def add_many(self, items): + """ + Add a list of files to the manifest. + + :param items: The pathnames to add. These can be relative to the base. + """ + for item in items: + self.add(item) + + def sorted(self, wantdirs=False): + """ + Return sorted files in directory order + """ + + def add_dir(dirs, d): + dirs.add(d) + logger.debug('add_dir added %s', d) + if d != self.base: + parent, _ = os.path.split(d) + assert parent not in ('', '/') + add_dir(dirs, parent) + + result = set(self.files) # make a copy! + if wantdirs: + dirs = set() + for f in result: + add_dir(dirs, os.path.dirname(f)) + result |= dirs + return [os.path.join(*path_tuple) for path_tuple in + sorted(os.path.split(path) for path in result)] + + def clear(self): + """Clear all collected files.""" + self.files = set() + self.allfiles = [] + + def process_directive(self, directive): + """ + Process a directive which either adds some files from ``allfiles`` to + ``files``, or removes some files from ``files``. + + :param directive: The directive to process. This should be in a format + compatible with distutils ``MANIFEST.in`` files: + + http://docs.python.org/distutils/sourcedist.html#commands + """ + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dirpattern). + action, patterns, thedir, dirpattern = self._parse_directive(directive) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=True): + logger.warning('no files found matching %r', pattern) + + elif action == 'exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=True) + #if not found: + # logger.warning('no previously-included files ' + # 'found matching %r', pattern) + + elif action == 'global-include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=False): + logger.warning('no files found matching %r ' + 'anywhere in distribution', pattern) + + elif action == 'global-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=False) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found anywhere in ' + # 'distribution', pattern) + + elif action == 'recursive-include': + for pattern in patterns: + if not self._include_pattern(pattern, prefix=thedir): + logger.warning('no files found matching %r ' + 'under directory %r', pattern, thedir) + + elif action == 'recursive-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, prefix=thedir) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found under directory %r', + # pattern, thedir) + + elif action == 'graft': + if not self._include_pattern(None, prefix=dirpattern): + logger.warning('no directories found matching %r', + dirpattern) + + elif action == 'prune': + if not self._exclude_pattern(None, prefix=dirpattern): + logger.warning('no previously-included directories found ' + 'matching %r', dirpattern) + else: # pragma: no cover + # This should never happen, as it should be caught in + # _parse_template_line + raise DistlibException( + 'invalid action %r' % action) + + # + # Private API + # + + def _parse_directive(self, directive): + """ + Validate a directive. + :param directive: The directive to validate. + :return: A tuple of action, patterns, thedir, dir_patterns + """ + words = directive.split() + if len(words) == 1 and words[0] not in ('include', 'exclude', + 'global-include', + 'global-exclude', + 'recursive-include', + 'recursive-exclude', + 'graft', 'prune'): + # no action given, let's use the default 'include' + words.insert(0, 'include') + + action = words[0] + patterns = thedir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistlibException( + '%r expects <pattern1> <pattern2> ...' % action) + + patterns = [convert_path(word) for word in words[1:]] + + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistlibException( + '%r expects <dir> <pattern1> <pattern2> ...' % action) + + thedir = convert_path(words[1]) + patterns = [convert_path(word) for word in words[2:]] + + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistlibException( + '%r expects a single <dir_pattern>' % action) + + dir_pattern = convert_path(words[1]) + + else: + raise DistlibException('unknown action %r' % action) + + return action, patterns, thedir, dir_pattern + + def _include_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. + + Patterns are not quite the same as implemented by the 'fnmatch' + module: '*' and '?' match non-special characters, where "special" + is platform-dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return True if files are found. + """ + # XXX docstring lying about what the special chars are? + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.files.add(name) + found = True + return found + + def _exclude_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. + + Other parameters are the same as for 'include_pattern()', above. + The list 'self.files' is modified in place. Return True if files are + found. + + This API is public to allow e.g. exclusion of SCM subdirs, e.g. when + packaging source distributions + """ + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + for f in list(self.files): + if pattern_re.search(f): + self.files.remove(f) + found = True + return found + + def _translate_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Translate a shell-like wildcard pattern to a compiled regular + expression. + + Return the compiled regex. If 'is_regex' true, + then 'pattern' is directly compiled to a regex (if it's a string) + or just returned as-is (assumes it's a regex object). + """ + if is_regex: + if isinstance(pattern, str): + return re.compile(pattern) + else: + return pattern + + if _PYTHON_VERSION > (3, 2): + # ditch start and end characters + start, _, end = self._glob_to_re('_').partition('_') + + if pattern: + pattern_re = self._glob_to_re(pattern) + if _PYTHON_VERSION > (3, 2): + assert pattern_re.startswith(start) and pattern_re.endswith(end) + else: + pattern_re = '' + + base = re.escape(os.path.join(self.base, '')) + if prefix is not None: + # ditch end of pattern character + if _PYTHON_VERSION <= (3, 2): + empty_pattern = self._glob_to_re('') + prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] + else: + prefix_re = self._glob_to_re(prefix) + assert prefix_re.startswith(start) and prefix_re.endswith(end) + prefix_re = prefix_re[len(start): len(prefix_re) - len(end)] + sep = os.sep + if os.sep == '\\': + sep = r'\\' + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + sep.join((prefix_re, + '.*' + pattern_re)) + else: + pattern_re = pattern_re[len(start): len(pattern_re) - len(end)] + pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep, + pattern_re, end) + else: # no prefix -- respect anchor flag + if anchor: + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + pattern_re + else: + pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):]) + + return re.compile(pattern_re) + + def _glob_to_re(self, pattern): + """Translate a shell-like glob pattern to a regular expression. + + Return a string containing the regex. Differs from + 'fnmatch.translate()' in that '*' does not match "special characters" + (which are platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', escaped, pattern_re) + return pattern_re diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/markers.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/markers.py new file mode 100644 index 0000000..ee1f3e2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/markers.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Parser for the environment markers micro-language defined in PEP 508. +""" + +# Note: In PEP 345, the micro-language was Python compatible, so the ast +# module could be used to parse it. However, PEP 508 introduced operators such +# as ~= and === which aren't in Python, necessitating a different approach. + +import os +import sys +import platform +import re + +from .compat import python_implementation, urlparse, string_types +from .util import in_venv, parse_marker + +__all__ = ['interpret'] + +def _is_literal(o): + if not isinstance(o, string_types) or not o: + return False + return o[0] in '\'"' + +class Evaluator(object): + """ + This class is used to evaluate marker expessions. + """ + + operations = { + '==': lambda x, y: x == y, + '===': lambda x, y: x == y, + '~=': lambda x, y: x == y or x > y, + '!=': lambda x, y: x != y, + '<': lambda x, y: x < y, + '<=': lambda x, y: x == y or x < y, + '>': lambda x, y: x > y, + '>=': lambda x, y: x == y or x > y, + 'and': lambda x, y: x and y, + 'or': lambda x, y: x or y, + 'in': lambda x, y: x in y, + 'not in': lambda x, y: x not in y, + } + + def evaluate(self, expr, context): + """ + Evaluate a marker expression returned by the :func:`parse_requirement` + function in the specified context. + """ + if isinstance(expr, string_types): + if expr[0] in '\'"': + result = expr[1:-1] + else: + if expr not in context: + raise SyntaxError('unknown variable: %s' % expr) + result = context[expr] + else: + assert isinstance(expr, dict) + op = expr['op'] + if op not in self.operations: + raise NotImplementedError('op not implemented: %s' % op) + elhs = expr['lhs'] + erhs = expr['rhs'] + if _is_literal(expr['lhs']) and _is_literal(expr['rhs']): + raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs)) + + lhs = self.evaluate(elhs, context) + rhs = self.evaluate(erhs, context) + result = self.operations[op](lhs, rhs) + return result + +def default_context(): + def format_full_version(info): + version = '%s.%s.%s' % (info.major, info.minor, info.micro) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + if hasattr(sys, 'implementation'): + implementation_version = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + implementation_version = '0' + implementation_name = '' + + result = { + 'implementation_name': implementation_name, + 'implementation_version': implementation_version, + 'os_name': os.name, + 'platform_machine': platform.machine(), + 'platform_python_implementation': platform.python_implementation(), + 'platform_release': platform.release(), + 'platform_system': platform.system(), + 'platform_version': platform.version(), + 'platform_in_venv': str(in_venv()), + 'python_full_version': platform.python_version(), + 'python_version': platform.python_version()[:3], + 'sys_platform': sys.platform, + } + return result + +DEFAULT_CONTEXT = default_context() +del default_context + +evaluator = Evaluator() + +def interpret(marker, execution_context=None): + """ + Interpret a marker and return a result depending on environment. + + :param marker: The marker to interpret. + :type marker: str + :param execution_context: The context used for name lookup. + :type execution_context: mapping + """ + try: + expr, rest = parse_marker(marker) + except Exception as e: + raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e)) + if rest and rest[0] != '#': + raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest)) + context = dict(DEFAULT_CONTEXT) + if execution_context: + context.update(execution_context) + return evaluator.evaluate(expr, context) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/metadata.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/metadata.py new file mode 100644 index 0000000..6d6470f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/metadata.py @@ -0,0 +1,1091 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Implementation of the Metadata for Python packages PEPs. + +Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental). +""" +from __future__ import unicode_literals + +import codecs +from email import message_from_file +import json +import logging +import re + + +from . import DistlibException, __version__ +from .compat import StringIO, string_types, text_type +from .markers import interpret +from .util import extract_by_key, get_extras +from .version import get_scheme, PEP440_VERSION_RE + +logger = logging.getLogger(__name__) + + +class MetadataMissingError(DistlibException): + """A required metadata is missing""" + + +class MetadataConflictError(DistlibException): + """Attempt to read or write metadata fields that are conflictual.""" + + +class MetadataUnrecognizedVersionError(DistlibException): + """Unknown metadata version number.""" + + +class MetadataInvalidError(DistlibException): + """A metadata value is invalid""" + +# public API of this module +__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] + +# Encoding used for the PKG-INFO files +PKG_INFO_ENCODING = 'utf-8' + +# preferred version. Hopefully will be changed +# to 1.2 once PEP 345 is supported everywhere +PKG_INFO_PREFERRED_VERSION = '1.1' + +_LINE_PREFIX_1_2 = re.compile('\n \\|') +_LINE_PREFIX_PRE_1_2 = re.compile('\n ') +_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License') + +_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License', 'Classifier', 'Download-URL', 'Obsoletes', + 'Provides', 'Requires') + +_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', + 'Download-URL') + +_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External') + +_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', + 'Obsoletes-Dist', 'Requires-External', 'Maintainer', + 'Maintainer-email', 'Project-URL') + +_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External', 'Private-Version', + 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension', + 'Provides-Extra') + +_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', + 'Setup-Requires-Dist', 'Extension') + +_566_FIELDS = _426_FIELDS + ('Description-Content-Type',) + +_566_MARKERS = ('Description-Content-Type',) + +_ALL_FIELDS = set() +_ALL_FIELDS.update(_241_FIELDS) +_ALL_FIELDS.update(_314_FIELDS) +_ALL_FIELDS.update(_345_FIELDS) +_ALL_FIELDS.update(_426_FIELDS) +_ALL_FIELDS.update(_566_FIELDS) + +EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') + + +def _version2fieldlist(version): + if version == '1.0': + return _241_FIELDS + elif version == '1.1': + return _314_FIELDS + elif version == '1.2': + return _345_FIELDS + elif version in ('1.3', '2.1'): + return _345_FIELDS + _566_FIELDS + elif version == '2.0': + return _426_FIELDS + raise MetadataUnrecognizedVersionError(version) + + +def _best_version(fields): + """Detect the best version depending on the fields used.""" + def _has_marker(keys, markers): + for marker in markers: + if marker in keys: + return True + return False + + keys = [] + for key, value in fields.items(): + if value in ([], 'UNKNOWN', None): + continue + keys.append(key) + + possible_versions = ['1.0', '1.1', '1.2', '1.3', '2.0', '2.1'] + + # first let's try to see if a field is not part of one of the version + for key in keys: + if key not in _241_FIELDS and '1.0' in possible_versions: + possible_versions.remove('1.0') + logger.debug('Removed 1.0 due to %s', key) + if key not in _314_FIELDS and '1.1' in possible_versions: + possible_versions.remove('1.1') + logger.debug('Removed 1.1 due to %s', key) + if key not in _345_FIELDS and '1.2' in possible_versions: + possible_versions.remove('1.2') + logger.debug('Removed 1.2 due to %s', key) + if key not in _566_FIELDS and '1.3' in possible_versions: + possible_versions.remove('1.3') + logger.debug('Removed 1.3 due to %s', key) + if key not in _566_FIELDS and '2.1' in possible_versions: + if key != 'Description': # In 2.1, description allowed after headers + possible_versions.remove('2.1') + logger.debug('Removed 2.1 due to %s', key) + if key not in _426_FIELDS and '2.0' in possible_versions: + possible_versions.remove('2.0') + logger.debug('Removed 2.0 due to %s', key) + + # possible_version contains qualified versions + if len(possible_versions) == 1: + return possible_versions[0] # found ! + elif len(possible_versions) == 0: + logger.debug('Out of options - unknown metadata set: %s', fields) + raise MetadataConflictError('Unknown metadata set') + + # let's see if one unique marker is found + is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) + is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) + is_2_1 = '2.1' in possible_versions and _has_marker(keys, _566_MARKERS) + is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) + if int(is_1_1) + int(is_1_2) + int(is_2_1) + int(is_2_0) > 1: + raise MetadataConflictError('You used incompatible 1.1/1.2/2.0/2.1 fields') + + # we have the choice, 1.0, or 1.2, or 2.0 + # - 1.0 has a broken Summary field but works with all tools + # - 1.1 is to avoid + # - 1.2 fixes Summary but has little adoption + # - 2.0 adds more features and is very new + if not is_1_1 and not is_1_2 and not is_2_1 and not is_2_0: + # we couldn't find any specific marker + if PKG_INFO_PREFERRED_VERSION in possible_versions: + return PKG_INFO_PREFERRED_VERSION + if is_1_1: + return '1.1' + if is_1_2: + return '1.2' + if is_2_1: + return '2.1' + + return '2.0' + +_ATTR2FIELD = { + 'metadata_version': 'Metadata-Version', + 'name': 'Name', + 'version': 'Version', + 'platform': 'Platform', + 'supported_platform': 'Supported-Platform', + 'summary': 'Summary', + 'description': 'Description', + 'keywords': 'Keywords', + 'home_page': 'Home-page', + 'author': 'Author', + 'author_email': 'Author-email', + 'maintainer': 'Maintainer', + 'maintainer_email': 'Maintainer-email', + 'license': 'License', + 'classifier': 'Classifier', + 'download_url': 'Download-URL', + 'obsoletes_dist': 'Obsoletes-Dist', + 'provides_dist': 'Provides-Dist', + 'requires_dist': 'Requires-Dist', + 'setup_requires_dist': 'Setup-Requires-Dist', + 'requires_python': 'Requires-Python', + 'requires_external': 'Requires-External', + 'requires': 'Requires', + 'provides': 'Provides', + 'obsoletes': 'Obsoletes', + 'project_url': 'Project-URL', + 'private_version': 'Private-Version', + 'obsoleted_by': 'Obsoleted-By', + 'extension': 'Extension', + 'provides_extra': 'Provides-Extra', +} + +_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') +_VERSIONS_FIELDS = ('Requires-Python',) +_VERSION_FIELDS = ('Version',) +_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', + 'Requires', 'Provides', 'Obsoletes-Dist', + 'Provides-Dist', 'Requires-Dist', 'Requires-External', + 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', + 'Provides-Extra', 'Extension') +_LISTTUPLEFIELDS = ('Project-URL',) + +_ELEMENTSFIELD = ('Keywords',) + +_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') + +_MISSING = object() + +_FILESAFE = re.compile('[^A-Za-z0-9.]+') + + +def _get_name_and_version(name, version, for_filename=False): + """Return the distribution name with version. + + If for_filename is true, return a filename-escaped form.""" + if for_filename: + # For both name and version any runs of non-alphanumeric or '.' + # characters are replaced with a single '-'. Additionally any + # spaces in the version string become '.' + name = _FILESAFE.sub('-', name) + version = _FILESAFE.sub('-', version.replace(' ', '.')) + return '%s-%s' % (name, version) + + +class LegacyMetadata(object): + """The legacy metadata of a release. + + Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can + instantiate the class with one of these arguments (or none): + - *path*, the path to a metadata file + - *fileobj* give a file-like object with metadata as content + - *mapping* is a dict-like object + - *scheme* is a version scheme name + """ + # TODO document the mapping API and UNKNOWN default key + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._fields = {} + self.requires_files = [] + self._dependencies = None + self.scheme = scheme + if path is not None: + self.read(path) + elif fileobj is not None: + self.read_file(fileobj) + elif mapping is not None: + self.update(mapping) + self.set_metadata_version() + + def set_metadata_version(self): + self._fields['Metadata-Version'] = _best_version(self._fields) + + def _write_field(self, fileobj, name, value): + fileobj.write('%s: %s\n' % (name, value)) + + def __getitem__(self, name): + return self.get(name) + + def __setitem__(self, name, value): + return self.set(name, value) + + def __delitem__(self, name): + field_name = self._convert_name(name) + try: + del self._fields[field_name] + except KeyError: + raise KeyError(name) + + def __contains__(self, name): + return (name in self._fields or + self._convert_name(name) in self._fields) + + def _convert_name(self, name): + if name in _ALL_FIELDS: + return name + name = name.replace('-', '_').lower() + return _ATTR2FIELD.get(name, name) + + def _default_value(self, name): + if name in _LISTFIELDS or name in _ELEMENTSFIELD: + return [] + return 'UNKNOWN' + + def _remove_line_prefix(self, value): + if self.metadata_version in ('1.0', '1.1'): + return _LINE_PREFIX_PRE_1_2.sub('\n', value) + else: + return _LINE_PREFIX_1_2.sub('\n', value) + + def __getattr__(self, name): + if name in _ATTR2FIELD: + return self[name] + raise AttributeError(name) + + # + # Public API + # + +# dependencies = property(_get_dependencies, _set_dependencies) + + def get_fullname(self, filesafe=False): + """Return the distribution name with version. + + If filesafe is true, return a filename-escaped form.""" + return _get_name_and_version(self['Name'], self['Version'], filesafe) + + def is_field(self, name): + """return True if name is a valid metadata key""" + name = self._convert_name(name) + return name in _ALL_FIELDS + + def is_multi_field(self, name): + name = self._convert_name(name) + return name in _LISTFIELDS + + def read(self, filepath): + """Read the metadata values from a file path.""" + fp = codecs.open(filepath, 'r', encoding='utf-8') + try: + self.read_file(fp) + finally: + fp.close() + + def read_file(self, fileob): + """Read the metadata values from a file object.""" + msg = message_from_file(fileob) + self._fields['Metadata-Version'] = msg['metadata-version'] + + # When reading, get all the fields we can + for field in _ALL_FIELDS: + if field not in msg: + continue + if field in _LISTFIELDS: + # we can have multiple lines + values = msg.get_all(field) + if field in _LISTTUPLEFIELDS and values is not None: + values = [tuple(value.split(',')) for value in values] + self.set(field, values) + else: + # single line + value = msg[field] + if value is not None and value != 'UNKNOWN': + self.set(field, value) + logger.debug('Attempting to set metadata for %s', self) + self.set_metadata_version() + + def write(self, filepath, skip_unknown=False): + """Write the metadata fields to filepath.""" + fp = codecs.open(filepath, 'w', encoding='utf-8') + try: + self.write_file(fp, skip_unknown) + finally: + fp.close() + + def write_file(self, fileobject, skip_unknown=False): + """Write the PKG-INFO format data to a file object.""" + self.set_metadata_version() + + for field in _version2fieldlist(self['Metadata-Version']): + values = self.get(field) + if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): + continue + if field in _ELEMENTSFIELD: + self._write_field(fileobject, field, ','.join(values)) + continue + if field not in _LISTFIELDS: + if field == 'Description': + if self.metadata_version in ('1.0', '1.1'): + values = values.replace('\n', '\n ') + else: + values = values.replace('\n', '\n |') + values = [values] + + if field in _LISTTUPLEFIELDS: + values = [','.join(value) for value in values] + + for value in values: + self._write_field(fileobject, field, value) + + def update(self, other=None, **kwargs): + """Set metadata values from the given iterable `other` and kwargs. + + Behavior is like `dict.update`: If `other` has a ``keys`` method, + they are looped over and ``self[key]`` is assigned ``other[key]``. + Else, ``other`` is an iterable of ``(key, value)`` iterables. + + Keys that don't match a metadata field or that have an empty value are + dropped. + """ + def _set(key, value): + if key in _ATTR2FIELD and value: + self.set(self._convert_name(key), value) + + if not other: + # other is None or empty container + pass + elif hasattr(other, 'keys'): + for k in other.keys(): + _set(k, other[k]) + else: + for k, v in other: + _set(k, v) + + if kwargs: + for k, v in kwargs.items(): + _set(k, v) + + def set(self, name, value): + """Control then set a metadata field.""" + name = self._convert_name(name) + + if ((name in _ELEMENTSFIELD or name == 'Platform') and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [v.strip() for v in value.split(',')] + else: + value = [] + elif (name in _LISTFIELDS and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [value] + else: + value = [] + + if logger.isEnabledFor(logging.WARNING): + project_name = self['Name'] + + scheme = get_scheme(self.scheme) + if name in _PREDICATE_FIELDS and value is not None: + for v in value: + # check that the values are valid + if not scheme.is_valid_matcher(v.split(';')[0]): + logger.warning( + "'%s': '%s' is not valid (field '%s')", + project_name, v, name) + # FIXME this rejects UNKNOWN, is that right? + elif name in _VERSIONS_FIELDS and value is not None: + if not scheme.is_valid_constraint_list(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + elif name in _VERSION_FIELDS and value is not None: + if not scheme.is_valid_version(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + + if name in _UNICODEFIELDS: + if name == 'Description': + value = self._remove_line_prefix(value) + + self._fields[name] = value + + def get(self, name, default=_MISSING): + """Get a metadata field.""" + name = self._convert_name(name) + if name not in self._fields: + if default is _MISSING: + default = self._default_value(name) + return default + if name in _UNICODEFIELDS: + value = self._fields[name] + return value + elif name in _LISTFIELDS: + value = self._fields[name] + if value is None: + return [] + res = [] + for val in value: + if name not in _LISTTUPLEFIELDS: + res.append(val) + else: + # That's for Project-URL + res.append((val[0], val[1])) + return res + + elif name in _ELEMENTSFIELD: + value = self._fields[name] + if isinstance(value, string_types): + return value.split(',') + return self._fields[name] + + def check(self, strict=False): + """Check if the metadata is compliant. If strict is True then raise if + no Name or Version are provided""" + self.set_metadata_version() + + # XXX should check the versions (if the file was loaded) + missing, warnings = [], [] + + for attr in ('Name', 'Version'): # required by PEP 345 + if attr not in self: + missing.append(attr) + + if strict and missing != []: + msg = 'missing required metadata: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + + for attr in ('Home-page', 'Author'): + if attr not in self: + missing.append(attr) + + # checking metadata 1.2 (XXX needs to check 1.1, 1.0) + if self['Metadata-Version'] != '1.2': + return missing, warnings + + scheme = get_scheme(self.scheme) + + def are_valid_constraints(value): + for v in value: + if not scheme.is_valid_matcher(v.split(';')[0]): + return False + return True + + for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), + (_VERSIONS_FIELDS, + scheme.is_valid_constraint_list), + (_VERSION_FIELDS, + scheme.is_valid_version)): + for field in fields: + value = self.get(field, None) + if value is not None and not controller(value): + warnings.append("Wrong value for '%s': %s" % (field, value)) + + return missing, warnings + + def todict(self, skip_missing=False): + """Return fields as a dict. + + Field names will be converted to use the underscore-lowercase style + instead of hyphen-mixed case (i.e. home_page instead of Home-page). + """ + self.set_metadata_version() + + mapping_1_0 = ( + ('metadata_version', 'Metadata-Version'), + ('name', 'Name'), + ('version', 'Version'), + ('summary', 'Summary'), + ('home_page', 'Home-page'), + ('author', 'Author'), + ('author_email', 'Author-email'), + ('license', 'License'), + ('description', 'Description'), + ('keywords', 'Keywords'), + ('platform', 'Platform'), + ('classifiers', 'Classifier'), + ('download_url', 'Download-URL'), + ) + + data = {} + for key, field_name in mapping_1_0: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] + + if self['Metadata-Version'] == '1.2': + mapping_1_2 = ( + ('requires_dist', 'Requires-Dist'), + ('requires_python', 'Requires-Python'), + ('requires_external', 'Requires-External'), + ('provides_dist', 'Provides-Dist'), + ('obsoletes_dist', 'Obsoletes-Dist'), + ('project_url', 'Project-URL'), + ('maintainer', 'Maintainer'), + ('maintainer_email', 'Maintainer-email'), + ) + for key, field_name in mapping_1_2: + if not skip_missing or field_name in self._fields: + if key != 'project_url': + data[key] = self[field_name] + else: + data[key] = [','.join(u) for u in self[field_name]] + + elif self['Metadata-Version'] == '1.1': + mapping_1_1 = ( + ('provides', 'Provides'), + ('requires', 'Requires'), + ('obsoletes', 'Obsoletes'), + ) + for key, field_name in mapping_1_1: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] + + return data + + def add_requirements(self, requirements): + if self['Metadata-Version'] == '1.1': + # we can't have 1.1 metadata *and* Setuptools requires + for field in ('Obsoletes', 'Requires', 'Provides'): + if field in self: + del self[field] + self['Requires-Dist'] += requirements + + # Mapping API + # TODO could add iter* variants + + def keys(self): + return list(_version2fieldlist(self['Metadata-Version'])) + + def __iter__(self): + for key in self.keys(): + yield key + + def values(self): + return [self[key] for key in self.keys()] + + def items(self): + return [(key, self[key]) for key in self.keys()] + + def __repr__(self): + return '<%s %s %s>' % (self.__class__.__name__, self.name, + self.version) + + +METADATA_FILENAME = 'pydist.json' +WHEEL_METADATA_FILENAME = 'metadata.json' + + +class Metadata(object): + """ + The metadata of a release. This implementation uses 2.0 (JSON) + metadata where possible. If not possible, it wraps a LegacyMetadata + instance which handles the key-value metadata format. + """ + + METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$') + + NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) + + VERSION_MATCHER = PEP440_VERSION_RE + + SUMMARY_MATCHER = re.compile('.{1,2047}') + + METADATA_VERSION = '2.0' + + GENERATOR = 'distlib (%s)' % __version__ + + MANDATORY_KEYS = { + 'name': (), + 'version': (), + 'summary': ('legacy',), + } + + INDEX_KEYS = ('name version license summary description author ' + 'author_email keywords platform home_page classifiers ' + 'download_url') + + DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' + 'dev_requires provides meta_requires obsoleted_by ' + 'supports_environments') + + SYNTAX_VALIDATORS = { + 'metadata_version': (METADATA_VERSION_MATCHER, ()), + 'name': (NAME_MATCHER, ('legacy',)), + 'version': (VERSION_MATCHER, ('legacy',)), + 'summary': (SUMMARY_MATCHER, ('legacy',)), + } + + __slots__ = ('_legacy', '_data', 'scheme') + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._legacy = None + self._data = None + self.scheme = scheme + #import pdb; pdb.set_trace() + if mapping is not None: + try: + self._validate_mapping(mapping, scheme) + self._data = mapping + except MetadataUnrecognizedVersionError: + self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) + self.validate() + else: + data = None + if path: + with open(path, 'rb') as f: + data = f.read() + elif fileobj: + data = fileobj.read() + if data is None: + # Initialised with no args - to be added + self._data = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + else: + if not isinstance(data, text_type): + data = data.decode('utf-8') + try: + self._data = json.loads(data) + self._validate_mapping(self._data, scheme) + except ValueError: + # Note: MetadataUnrecognizedVersionError does not + # inherit from ValueError (it's a DistlibException, + # which should not inherit from ValueError). + # The ValueError comes from the json.load - if that + # succeeds and we get a validation error, we want + # that to propagate + self._legacy = LegacyMetadata(fileobj=StringIO(data), + scheme=scheme) + self.validate() + + common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) + + none_list = (None, list) + none_dict = (None, dict) + + mapped_keys = { + 'run_requires': ('Requires-Dist', list), + 'build_requires': ('Setup-Requires-Dist', list), + 'dev_requires': none_list, + 'test_requires': none_list, + 'meta_requires': none_list, + 'extras': ('Provides-Extra', list), + 'modules': none_list, + 'namespaces': none_list, + 'exports': none_dict, + 'commands': none_dict, + 'classifiers': ('Classifier', list), + 'source_url': ('Download-URL', None), + 'metadata_version': ('Metadata-Version', None), + } + + del none_list, none_dict + + def __getattribute__(self, key): + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, maker = mapped[key] + if self._legacy: + if lk is None: + result = None if maker is None else maker() + else: + result = self._legacy.get(lk) + else: + value = None if maker is None else maker() + if key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + result = self._data.get(key, value) + else: + # special cases for PEP 459 + sentinel = object() + result = sentinel + d = self._data.get('extensions') + if d: + if key == 'commands': + result = d.get('python.commands', value) + elif key == 'classifiers': + d = d.get('python.details') + if d: + result = d.get(key, value) + else: + d = d.get('python.exports') + if not d: + d = self._data.get('python.exports') + if d: + result = d.get(key, value) + if result is sentinel: + result = value + elif key not in common: + result = object.__getattribute__(self, key) + elif self._legacy: + result = self._legacy.get(key) + else: + result = self._data.get(key) + return result + + def _validate_value(self, key, value, scheme=None): + if key in self.SYNTAX_VALIDATORS: + pattern, exclusions = self.SYNTAX_VALIDATORS[key] + if (scheme or self.scheme) not in exclusions: + m = pattern.match(value) + if not m: + raise MetadataInvalidError("'%s' is an invalid value for " + "the '%s' property" % (value, + key)) + + def __setattr__(self, key, value): + self._validate_value(key, value) + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, _ = mapped[key] + if self._legacy: + if lk is None: + raise NotImplementedError + self._legacy[lk] = value + elif key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + self._data[key] = value + else: + # special cases for PEP 459 + d = self._data.setdefault('extensions', {}) + if key == 'commands': + d['python.commands'] = value + elif key == 'classifiers': + d = d.setdefault('python.details', {}) + d[key] = value + else: + d = d.setdefault('python.exports', {}) + d[key] = value + elif key not in common: + object.__setattr__(self, key, value) + else: + if key == 'keywords': + if isinstance(value, string_types): + value = value.strip() + if value: + value = value.split() + else: + value = [] + if self._legacy: + self._legacy[key] = value + else: + self._data[key] = value + + @property + def name_and_version(self): + return _get_name_and_version(self.name, self.version, True) + + @property + def provides(self): + if self._legacy: + result = self._legacy['Provides-Dist'] + else: + result = self._data.setdefault('provides', []) + s = '%s (%s)' % (self.name, self.version) + if s not in result: + result.append(s) + return result + + @provides.setter + def provides(self, value): + if self._legacy: + self._legacy['Provides-Dist'] = value + else: + self._data['provides'] = value + + def get_requirements(self, reqts, extras=None, env=None): + """ + Base method to get dependencies, given a set of extras + to satisfy and an optional environment context. + :param reqts: A list of sometimes-wanted dependencies, + perhaps dependent on extras and environment. + :param extras: A list of optional components being requested. + :param env: An optional environment for marker evaluation. + """ + if self._legacy: + result = reqts + else: + result = [] + extras = get_extras(extras or [], self.extras) + for d in reqts: + if 'extra' not in d and 'environment' not in d: + # unconditional + include = True + else: + if 'extra' not in d: + # Not extra-dependent - only environment-dependent + include = True + else: + include = d.get('extra') in extras + if include: + # Not excluded because of extras, check environment + marker = d.get('environment') + if marker: + include = interpret(marker, env) + if include: + result.extend(d['requires']) + for key in ('build', 'dev', 'test'): + e = ':%s:' % key + if e in extras: + extras.remove(e) + # A recursive call, but it should terminate since 'test' + # has been removed from the extras + reqts = self._data.get('%s_requires' % key, []) + result.extend(self.get_requirements(reqts, extras=extras, + env=env)) + return result + + @property + def dictionary(self): + if self._legacy: + return self._from_legacy() + return self._data + + @property + def dependencies(self): + if self._legacy: + raise NotImplementedError + else: + return extract_by_key(self._data, self.DEPENDENCY_KEYS) + + @dependencies.setter + def dependencies(self, value): + if self._legacy: + raise NotImplementedError + else: + self._data.update(value) + + def _validate_mapping(self, mapping, scheme): + if mapping.get('metadata_version') != self.METADATA_VERSION: + raise MetadataUnrecognizedVersionError() + missing = [] + for key, exclusions in self.MANDATORY_KEYS.items(): + if key not in mapping: + if scheme not in exclusions: + missing.append(key) + if missing: + msg = 'Missing metadata items: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + for k, v in mapping.items(): + self._validate_value(k, v, scheme) + + def validate(self): + if self._legacy: + missing, warnings = self._legacy.check(True) + if missing or warnings: + logger.warning('Metadata: missing: %s, warnings: %s', + missing, warnings) + else: + self._validate_mapping(self._data, self.scheme) + + def todict(self): + if self._legacy: + return self._legacy.todict(True) + else: + result = extract_by_key(self._data, self.INDEX_KEYS) + return result + + def _from_legacy(self): + assert self._legacy and not self._data + result = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + lmd = self._legacy.todict(True) # skip missing ones + for k in ('name', 'version', 'license', 'summary', 'description', + 'classifier'): + if k in lmd: + if k == 'classifier': + nk = 'classifiers' + else: + nk = k + result[nk] = lmd[k] + kw = lmd.get('Keywords', []) + if kw == ['']: + kw = [] + result['keywords'] = kw + keys = (('requires_dist', 'run_requires'), + ('setup_requires_dist', 'build_requires')) + for ok, nk in keys: + if ok in lmd and lmd[ok]: + result[nk] = [{'requires': lmd[ok]}] + result['provides'] = self.provides + author = {} + maintainer = {} + return result + + LEGACY_MAPPING = { + 'name': 'Name', + 'version': 'Version', + 'license': 'License', + 'summary': 'Summary', + 'description': 'Description', + 'classifiers': 'Classifier', + } + + def _to_legacy(self): + def process_entries(entries): + reqts = set() + for e in entries: + extra = e.get('extra') + env = e.get('environment') + rlist = e['requires'] + for r in rlist: + if not env and not extra: + reqts.add(r) + else: + marker = '' + if extra: + marker = 'extra == "%s"' % extra + if env: + if marker: + marker = '(%s) and %s' % (env, marker) + else: + marker = env + reqts.add(';'.join((r, marker))) + return reqts + + assert self._data and not self._legacy + result = LegacyMetadata() + nmd = self._data + for nk, ok in self.LEGACY_MAPPING.items(): + if nk in nmd: + result[ok] = nmd[nk] + r1 = process_entries(self.run_requires + self.meta_requires) + r2 = process_entries(self.build_requires + self.dev_requires) + if self.extras: + result['Provides-Extra'] = sorted(self.extras) + result['Requires-Dist'] = sorted(r1) + result['Setup-Requires-Dist'] = sorted(r2) + # TODO: other fields such as contacts + return result + + def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): + if [path, fileobj].count(None) != 1: + raise ValueError('Exactly one of path and fileobj is needed') + self.validate() + if legacy: + if self._legacy: + legacy_md = self._legacy + else: + legacy_md = self._to_legacy() + if path: + legacy_md.write(path, skip_unknown=skip_unknown) + else: + legacy_md.write_file(fileobj, skip_unknown=skip_unknown) + else: + if self._legacy: + d = self._from_legacy() + else: + d = self._data + if fileobj: + json.dump(d, fileobj, ensure_ascii=True, indent=2, + sort_keys=True) + else: + with codecs.open(path, 'w', 'utf-8') as f: + json.dump(d, f, ensure_ascii=True, indent=2, + sort_keys=True) + + def add_requirements(self, requirements): + if self._legacy: + self._legacy.add_requirements(requirements) + else: + run_requires = self._data.setdefault('run_requires', []) + always = None + for entry in run_requires: + if 'environment' not in entry and 'extra' not in entry: + always = entry + break + if always is None: + always = { 'requires': requirements } + run_requires.insert(0, always) + else: + rset = set(always['requires']) | set(requirements) + always['requires'] = sorted(rset) + + def __repr__(self): + name = self.name or '(no name)' + version = self.version or 'no version' + return '<%s %s %s (%s)>' % (self.__class__.__name__, + self.metadata_version, name, version) diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/resources.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/resources.py new file mode 100644 index 0000000..1884016 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/resources.py @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import bisect +import io +import logging +import os +import pkgutil +import shutil +import sys +import types +import zipimport + +from . import DistlibException +from .util import cached_property, get_cache_base, path_to_cache_dir, Cache + +logger = logging.getLogger(__name__) + + +cache = None # created when needed + + +class ResourceCache(Cache): + def __init__(self, base=None): + if base is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('resource-cache')) + super(ResourceCache, self).__init__(base) + + def is_stale(self, resource, path): + """ + Is the cache stale for the given resource? + + :param resource: The :class:`Resource` being cached. + :param path: The path of the resource in the cache. + :return: True if the cache is stale. + """ + # Cache invalidation is a hard problem :-) + return True + + def get(self, resource): + """ + Get a resource into the cache, + + :param resource: A :class:`Resource` instance. + :return: The pathname of the resource in the cache. + """ + prefix, path = resource.finder.get_cache_info(resource) + if prefix is None: + result = path + else: + result = os.path.join(self.base, self.prefix_to_dir(prefix), path) + dirname = os.path.dirname(result) + if not os.path.isdir(dirname): + os.makedirs(dirname) + if not os.path.exists(result): + stale = True + else: + stale = self.is_stale(resource, path) + if stale: + # write the bytes of the resource to the cache location + with open(result, 'wb') as f: + f.write(resource.bytes) + return result + + +class ResourceBase(object): + def __init__(self, finder, name): + self.finder = finder + self.name = name + + +class Resource(ResourceBase): + """ + A class representing an in-package resource, such as a data file. This is + not normally instantiated by user code, but rather by a + :class:`ResourceFinder` which manages the resource. + """ + is_container = False # Backwards compatibility + + def as_stream(self): + """ + Get the resource as a stream. + + This is not a property to make it obvious that it returns a new stream + each time. + """ + return self.finder.get_stream(self) + + @cached_property + def file_path(self): + global cache + if cache is None: + cache = ResourceCache() + return cache.get(self) + + @cached_property + def bytes(self): + return self.finder.get_bytes(self) + + @cached_property + def size(self): + return self.finder.get_size(self) + + +class ResourceContainer(ResourceBase): + is_container = True # Backwards compatibility + + @cached_property + def resources(self): + return self.finder.get_resources(self) + + +class ResourceFinder(object): + """ + Resource finder for file system resources. + """ + + if sys.platform.startswith('java'): + skipped_extensions = ('.pyc', '.pyo', '.class') + else: + skipped_extensions = ('.pyc', '.pyo') + + def __init__(self, module): + self.module = module + self.loader = getattr(module, '__loader__', None) + self.base = os.path.dirname(getattr(module, '__file__', '')) + + def _adjust_path(self, path): + return os.path.realpath(path) + + def _make_path(self, resource_name): + # Issue #50: need to preserve type of path on Python 2.x + # like os.path._get_sep + if isinstance(resource_name, bytes): # should only happen on 2.x + sep = b'/' + else: + sep = '/' + parts = resource_name.split(sep) + parts.insert(0, self.base) + result = os.path.join(*parts) + return self._adjust_path(result) + + def _find(self, path): + return os.path.exists(path) + + def get_cache_info(self, resource): + return None, resource.path + + def find(self, resource_name): + path = self._make_path(resource_name) + if not self._find(path): + result = None + else: + if self._is_directory(path): + result = ResourceContainer(self, resource_name) + else: + result = Resource(self, resource_name) + result.path = path + return result + + def get_stream(self, resource): + return open(resource.path, 'rb') + + def get_bytes(self, resource): + with open(resource.path, 'rb') as f: + return f.read() + + def get_size(self, resource): + return os.path.getsize(resource.path) + + def get_resources(self, resource): + def allowed(f): + return (f != '__pycache__' and not + f.endswith(self.skipped_extensions)) + return set([f for f in os.listdir(resource.path) if allowed(f)]) + + def is_container(self, resource): + return self._is_directory(resource.path) + + _is_directory = staticmethod(os.path.isdir) + + def iterator(self, resource_name): + resource = self.find(resource_name) + if resource is not None: + todo = [resource] + while todo: + resource = todo.pop(0) + yield resource + if resource.is_container: + rname = resource.name + for name in resource.resources: + if not rname: + new_name = name + else: + new_name = '/'.join([rname, name]) + child = self.find(new_name) + if child.is_container: + todo.append(child) + else: + yield child + + +class ZipResourceFinder(ResourceFinder): + """ + Resource finder for resources in .zip files. + """ + def __init__(self, module): + super(ZipResourceFinder, self).__init__(module) + archive = self.loader.archive + self.prefix_len = 1 + len(archive) + # PyPy doesn't have a _files attr on zipimporter, and you can't set one + if hasattr(self.loader, '_files'): + self._files = self.loader._files + else: + self._files = zipimport._zip_directory_cache[archive] + self.index = sorted(self._files) + + def _adjust_path(self, path): + return path + + def _find(self, path): + path = path[self.prefix_len:] + if path in self._files: + result = True + else: + if path and path[-1] != os.sep: + path = path + os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + if not result: + logger.debug('_find failed: %r %r', path, self.loader.prefix) + else: + logger.debug('_find worked: %r %r', path, self.loader.prefix) + return result + + def get_cache_info(self, resource): + prefix = self.loader.archive + path = resource.path[1 + len(prefix):] + return prefix, path + + def get_bytes(self, resource): + return self.loader.get_data(resource.path) + + def get_stream(self, resource): + return io.BytesIO(self.get_bytes(resource)) + + def get_size(self, resource): + path = resource.path[self.prefix_len:] + return self._files[path][3] + + def get_resources(self, resource): + path = resource.path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + plen = len(path) + result = set() + i = bisect.bisect(self.index, path) + while i < len(self.index): + if not self.index[i].startswith(path): + break + s = self.index[i][plen:] + result.add(s.split(os.sep, 1)[0]) # only immediate children + i += 1 + return result + + def _is_directory(self, path): + path = path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + return result + +_finder_registry = { + type(None): ResourceFinder, + zipimport.zipimporter: ZipResourceFinder +} + +try: + # In Python 3.6, _frozen_importlib -> _frozen_importlib_external + try: + import _frozen_importlib_external as _fi + except ImportError: + import _frozen_importlib as _fi + _finder_registry[_fi.SourceFileLoader] = ResourceFinder + _finder_registry[_fi.FileFinder] = ResourceFinder + del _fi +except (ImportError, AttributeError): + pass + + +def register_finder(loader, finder_maker): + _finder_registry[type(loader)] = finder_maker + +_finder_cache = {} + + +def finder(package): + """ + Return a resource finder for a package. + :param package: The name of the package. + :return: A :class:`ResourceFinder` instance for the package. + """ + if package in _finder_cache: + result = _finder_cache[package] + else: + if package not in sys.modules: + __import__(package) + module = sys.modules[package] + path = getattr(module, '__path__', None) + if path is None: + raise DistlibException('You cannot get a finder for a module, ' + 'only for a package') + loader = getattr(module, '__loader__', None) + finder_maker = _finder_registry.get(type(loader)) + if finder_maker is None: + raise DistlibException('Unable to locate finder for %r' % package) + result = finder_maker(module) + _finder_cache[package] = result + return result + + +_dummy_module = types.ModuleType(str('__dummy__')) + + +def finder_for_path(path): + """ + Return a resource finder for a path, which should represent a container. + + :param path: The path. + :return: A :class:`ResourceFinder` instance for the path. + """ + result = None + # calls any path hooks, gets importer into cache + pkgutil.get_importer(path) + loader = sys.path_importer_cache.get(path) + finder = _finder_registry.get(type(loader)) + if finder: + module = _dummy_module + module.__file__ = os.path.join(path, '') + module.__loader__ = loader + result = finder(module) + return result diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/scripts.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/scripts.py new file mode 100644 index 0000000..0b7c3d0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/scripts.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from io import BytesIO +import logging +import os +import re +import struct +import sys + +from .compat import sysconfig, detect_encoding, ZipFile +from .resources import finder +from .util import (FileOperator, get_export_entry, convert_path, + get_executable, in_venv) + +logger = logging.getLogger(__name__) + +_DEFAULT_MANIFEST = ''' +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" + processorArchitecture="X86" + name="%s" + type="win32"/> + + <!-- Identify the application security requirements. --> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly>'''.strip() + +# check if Python is called on the first line with this expression +FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') +SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- +if __name__ == '__main__': + import sys, re + + def _resolve(module, func): + __import__(module) + mod = sys.modules[module] + parts = func.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + try: + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + + func = _resolve('%(module)s', '%(func)s') + rc = func() # None interpreted as 0 + except Exception as e: # only supporting Python >= 2.6 + sys.stderr.write('%%s\n' %% e) + rc = 1 + sys.exit(rc) +''' + + +def _enquote_executable(executable): + if ' ' in executable: + # make sure we quote only the executable in case of env + # for example /usr/bin/env "/dir with spaces/bin/jython" + # instead of "/usr/bin/env /dir with spaces/bin/jython" + # otherwise whole + if executable.startswith('/usr/bin/env '): + env, _executable = executable.split(' ', 1) + if ' ' in _executable and not _executable.startswith('"'): + executable = '%s "%s"' % (env, _executable) + else: + if not executable.startswith('"'): + executable = '"%s"' % executable + return executable + + +class ScriptMaker(object): + """ + A class to copy or create scripts from source scripts or callable + specifications. + """ + script_template = SCRIPT_TEMPLATE + + executable = None # for shebangs + + def __init__(self, source_dir, target_dir, add_launchers=True, + dry_run=False, fileop=None): + self.source_dir = source_dir + self.target_dir = target_dir + self.add_launchers = add_launchers + self.force = False + self.clobber = False + # It only makes sense to set mode bits on POSIX. + self.set_mode = (os.name == 'posix') or (os.name == 'java' and + os._name == 'posix') + self.variants = set(('', 'X.Y')) + self._fileop = fileop or FileOperator(dry_run) + + self._is_nt = os.name == 'nt' or ( + os.name == 'java' and os._name == 'nt') + + def _get_alternate_executable(self, executable, options): + if options.get('gui', False) and self._is_nt: # pragma: no cover + dn, fn = os.path.split(executable) + fn = fn.replace('python', 'pythonw') + executable = os.path.join(dn, fn) + return executable + + if sys.platform.startswith('java'): # pragma: no cover + def _is_shell(self, executable): + """ + Determine if the specified executable is a script + (contains a #! line) + """ + try: + with open(executable) as fp: + return fp.read(2) == '#!' + except (OSError, IOError): + logger.warning('Failed to open %s', executable) + return False + + def _fix_jython_executable(self, executable): + if self._is_shell(executable): + # Workaround for Jython is not needed on Linux systems. + import java + + if java.lang.System.getProperty('os.name') == 'Linux': + return executable + elif executable.lower().endswith('jython.exe'): + # Use wrapper exe for Jython on Windows + return executable + return '/usr/bin/env %s' % executable + + def _build_shebang(self, executable, post_interp): + """ + Build a shebang line. In the simple case (on Windows, or a shebang line + which is not too long or contains spaces) use a simple formulation for + the shebang. Otherwise, use /bin/sh as the executable, with a contrived + shebang which allows the script to run either under Python or sh, using + suitable quoting. Thanks to Harald Nordgren for his input. + + See also: http://www.in-ulm.de/~mascheck/various/shebang/#length + https://hg.mozilla.org/mozilla-central/file/tip/mach + """ + if os.name != 'posix': + simple_shebang = True + else: + # Add 3 for '#!' prefix and newline suffix. + shebang_length = len(executable) + len(post_interp) + 3 + if sys.platform == 'darwin': + max_shebang_length = 512 + else: + max_shebang_length = 127 + simple_shebang = ((b' ' not in executable) and + (shebang_length <= max_shebang_length)) + + if simple_shebang: + result = b'#!' + executable + post_interp + b'\n' + else: + result = b'#!/bin/sh\n' + result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n' + result += b"' '''" + return result + + def _get_shebang(self, encoding, post_interp=b'', options=None): + enquote = True + if self.executable: + executable = self.executable + enquote = False # assume this will be taken care of + elif not sysconfig.is_python_build(): + executable = get_executable() + elif in_venv(): # pragma: no cover + executable = os.path.join(sysconfig.get_path('scripts'), + 'python%s' % sysconfig.get_config_var('EXE')) + else: # pragma: no cover + executable = os.path.join( + sysconfig.get_config_var('BINDIR'), + 'python%s%s' % (sysconfig.get_config_var('VERSION'), + sysconfig.get_config_var('EXE'))) + if options: + executable = self._get_alternate_executable(executable, options) + + if sys.platform.startswith('java'): # pragma: no cover + executable = self._fix_jython_executable(executable) + # Normalise case for Windows + executable = os.path.normcase(executable) + # If the user didn't specify an executable, it may be necessary to + # cater for executable paths with spaces (not uncommon on Windows) + if enquote: + executable = _enquote_executable(executable) + # Issue #51: don't use fsencode, since we later try to + # check that the shebang is decodable using utf-8. + executable = executable.encode('utf-8') + # in case of IronPython, play safe and enable frames support + if (sys.platform == 'cli' and '-X:Frames' not in post_interp + and '-X:FullFrames' not in post_interp): # pragma: no cover + post_interp += b' -X:Frames' + shebang = self._build_shebang(executable, post_interp) + # Python parser starts to read a script using UTF-8 until + # it gets a #coding:xxx cookie. The shebang has to be the + # first line of a file, the #coding:xxx cookie cannot be + # written before. So the shebang has to be decodable from + # UTF-8. + try: + shebang.decode('utf-8') + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable from utf-8' % shebang) + # If the script is encoded to a custom encoding (use a + # #coding:xxx cookie), the shebang has to be decodable from + # the script encoding too. + if encoding != 'utf-8': + try: + shebang.decode(encoding) + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable ' + 'from the script encoding (%r)' % (shebang, encoding)) + return shebang + + def _get_script_text(self, entry): + return self.script_template % dict(module=entry.prefix, + func=entry.suffix) + + manifest = _DEFAULT_MANIFEST + + def get_manifest(self, exename): + base = os.path.basename(exename) + return self.manifest % base + + def _write_script(self, names, shebang, script_bytes, filenames, ext): + use_launcher = self.add_launchers and self._is_nt + linesep = os.linesep.encode('utf-8') + if not use_launcher: + script_bytes = shebang + linesep + script_bytes + else: # pragma: no cover + if ext == 'py': + launcher = self._get_launcher('t') + else: + launcher = self._get_launcher('w') + stream = BytesIO() + with ZipFile(stream, 'w') as zf: + zf.writestr('__main__.py', script_bytes) + zip_data = stream.getvalue() + script_bytes = launcher + shebang + linesep + zip_data + for name in names: + outname = os.path.join(self.target_dir, name) + if use_launcher: # pragma: no cover + n, e = os.path.splitext(outname) + if e.startswith('.py'): + outname = n + outname = '%s.exe' % outname + try: + self._fileop.write_binary_file(outname, script_bytes) + except Exception: + # Failed writing an executable - it might be in use. + logger.warning('Failed to write executable - trying to ' + 'use .deleteme logic') + dfname = '%s.deleteme' % outname + if os.path.exists(dfname): + os.remove(dfname) # Not allowed to fail here + os.rename(outname, dfname) # nor here + self._fileop.write_binary_file(outname, script_bytes) + logger.debug('Able to replace executable using ' + '.deleteme logic') + try: + os.remove(dfname) + except Exception: + pass # still in use - ignore error + else: + if self._is_nt and not outname.endswith('.' + ext): # pragma: no cover + outname = '%s.%s' % (outname, ext) + if os.path.exists(outname) and not self.clobber: + logger.warning('Skipping existing file %s', outname) + continue + self._fileop.write_binary_file(outname, script_bytes) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + + def _make_script(self, entry, filenames, options=None): + post_interp = b'' + if options: + args = options.get('interpreter_args', []) + if args: + args = ' %s' % ' '.join(args) + post_interp = args.encode('utf-8') + shebang = self._get_shebang('utf-8', post_interp, options=options) + script = self._get_script_text(entry).encode('utf-8') + name = entry.name + scriptnames = set() + if '' in self.variants: + scriptnames.add(name) + if 'X' in self.variants: + scriptnames.add('%s%s' % (name, sys.version[0])) + if 'X.Y' in self.variants: + scriptnames.add('%s-%s' % (name, sys.version[:3])) + if options and options.get('gui', False): + ext = 'pyw' + else: + ext = 'py' + self._write_script(scriptnames, shebang, script, filenames, ext) + + def _copy_script(self, script, filenames): + adjust = False + script = os.path.join(self.source_dir, convert_path(script)) + outname = os.path.join(self.target_dir, os.path.basename(script)) + if not self.force and not self._fileop.newer(script, outname): + logger.debug('not copying %s (up-to-date)', script) + return + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, 'rb') + except IOError: # pragma: no cover + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: # pragma: no cover + logger.warning('%s: %s is an empty file (skipping)', + self.get_command_name(), script) + return + + match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) + if match: + adjust = True + post_interp = match.group(1) or b'' + + if not adjust: + if f: + f.close() + self._fileop.copy_file(script, outname) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + else: + logger.info('copying and adjusting %s -> %s', script, + self.target_dir) + if not self._fileop.dry_run: + encoding, lines = detect_encoding(f.readline) + f.seek(0) + shebang = self._get_shebang(encoding, post_interp) + if b'pythonw' in first_line: # pragma: no cover + ext = 'pyw' + else: + ext = 'py' + n = os.path.basename(outname) + self._write_script([n], shebang, f.read(), filenames, ext) + if f: + f.close() + + @property + def dry_run(self): + return self._fileop.dry_run + + @dry_run.setter + def dry_run(self, value): + self._fileop.dry_run = value + + if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'): # pragma: no cover + # Executable launcher support. + # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ + + def _get_launcher(self, kind): + if struct.calcsize('P') == 8: # 64-bit + bits = '64' + else: + bits = '32' + name = '%s%s.exe' % (kind, bits) + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + distlib_package = __name__.rsplit('.', 1)[0] + result = finder(distlib_package).find(name).bytes + return result + + # Public API follows + + def make(self, specification, options=None): + """ + Make a script. + + :param specification: The specification, which is either a valid export + entry specification (to make a script from a + callable) or a filename (to make a script by + copying from a source location). + :param options: A dictionary of options controlling script generation. + :return: A list of all absolute pathnames written to. + """ + filenames = [] + entry = get_export_entry(specification) + if entry is None: + self._copy_script(specification, filenames) + else: + self._make_script(entry, filenames, options=options) + return filenames + + def make_multiple(self, specifications, options=None): + """ + Take a list of specifications and make scripts from them, + :param specifications: A list of specifications. + :return: A list of all absolute pathnames written to, + """ + filenames = [] + for specification in specifications: + filenames.extend(self.make(specification, options)) + return filenames diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/t32.exe b/winvenv/Lib/site-packages/pip/_vendor/distlib/t32.exe new file mode 100644 index 0000000000000000000000000000000000000000..a09d926872d84ae22a617dfe9ebb560d420b37de GIT binary patch literal 92672 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/t64.exe b/winvenv/Lib/site-packages/pip/_vendor/distlib/t64.exe new file mode 100644 index 0000000000000000000000000000000000000000..9da9b40de922fb203df6b9a1d0ad4139af536850 GIT binary patch literal 102400 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�vlnW`{LoXpTySn$@;x8yoz96jn?+Kk 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�?dYNUd4WaURX_A__M4W}D0!0n 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/util.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/util.py new file mode 100644 index 0000000..0b14a93 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/util.py @@ -0,0 +1,1755 @@ +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import codecs +from collections import deque +import contextlib +import csv +from glob import iglob as std_iglob +import io +import json +import logging +import os +import py_compile +import re +import socket +try: + import ssl +except ImportError: # pragma: no cover + ssl = None +import subprocess +import sys +import tarfile +import tempfile +import textwrap + +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import time + +from . import DistlibException +from .compat import (string_types, text_type, shutil, raw_input, StringIO, + cache_from_source, urlopen, urljoin, httplib, xmlrpclib, + splittype, HTTPHandler, BaseConfigurator, valid_ident, + Container, configparser, URLError, ZipFile, fsdecode, + unquote, urlparse) + +logger = logging.getLogger(__name__) + +# +# Requirement parsing code as per PEP 508 +# + +IDENTIFIER = re.compile(r'^([\w\.-]+)\s*') +VERSION_IDENTIFIER = re.compile(r'^([\w\.*+-]+)\s*') +COMPARE_OP = re.compile(r'^(<=?|>=?|={2,3}|[~!]=)\s*') +MARKER_OP = re.compile(r'^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*') +OR = re.compile(r'^or\b\s*') +AND = re.compile(r'^and\b\s*') +NON_SPACE = re.compile(r'(\S+)\s*') +STRING_CHUNK = re.compile(r'([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)') + + +def parse_marker(marker_string): + """ + Parse a marker string and return a dictionary containing a marker expression. + + The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in + the expression grammar, or strings. A string contained in quotes is to be + interpreted as a literal string, and a string not contained in quotes is a + variable (such as os_name). + """ + def marker_var(remaining): + # either identifier, or literal string + m = IDENTIFIER.match(remaining) + if m: + result = m.groups()[0] + remaining = remaining[m.end():] + elif not remaining: + raise SyntaxError('unexpected end of input') + else: + q = remaining[0] + if q not in '\'"': + raise SyntaxError('invalid expression: %s' % remaining) + oq = '\'"'.replace(q, '') + remaining = remaining[1:] + parts = [q] + while remaining: + # either a string chunk, or oq, or q to terminate + if remaining[0] == q: + break + elif remaining[0] == oq: + parts.append(oq) + remaining = remaining[1:] + else: + m = STRING_CHUNK.match(remaining) + if not m: + raise SyntaxError('error in string literal: %s' % remaining) + parts.append(m.groups()[0]) + remaining = remaining[m.end():] + else: + s = ''.join(parts) + raise SyntaxError('unterminated string: %s' % s) + parts.append(q) + result = ''.join(parts) + remaining = remaining[1:].lstrip() # skip past closing quote + return result, remaining + + def marker_expr(remaining): + if remaining and remaining[0] == '(': + result, remaining = marker(remaining[1:].lstrip()) + if remaining[0] != ')': + raise SyntaxError('unterminated parenthesis: %s' % remaining) + remaining = remaining[1:].lstrip() + else: + lhs, remaining = marker_var(remaining) + while remaining: + m = MARKER_OP.match(remaining) + if not m: + break + op = m.groups()[0] + remaining = remaining[m.end():] + rhs, remaining = marker_var(remaining) + lhs = {'op': op, 'lhs': lhs, 'rhs': rhs} + result = lhs + return result, remaining + + def marker_and(remaining): + lhs, remaining = marker_expr(remaining) + while remaining: + m = AND.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_expr(remaining) + lhs = {'op': 'and', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + def marker(remaining): + lhs, remaining = marker_and(remaining) + while remaining: + m = OR.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_and(remaining) + lhs = {'op': 'or', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + return marker(marker_string) + + +def parse_requirement(req): + """ + Parse a requirement passed in as a string. Return a Container + whose attributes contain the various parts of the requirement. + """ + remaining = req.strip() + if not remaining or remaining.startswith('#'): + return None + m = IDENTIFIER.match(remaining) + if not m: + raise SyntaxError('name expected: %s' % remaining) + distname = m.groups()[0] + remaining = remaining[m.end():] + extras = mark_expr = versions = uri = None + if remaining and remaining[0] == '[': + i = remaining.find(']', 1) + if i < 0: + raise SyntaxError('unterminated extra: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + extras = [] + while s: + m = IDENTIFIER.match(s) + if not m: + raise SyntaxError('malformed extra: %s' % s) + extras.append(m.groups()[0]) + s = s[m.end():] + if not s: + break + if s[0] != ',': + raise SyntaxError('comma expected in extras: %s' % s) + s = s[1:].lstrip() + if not extras: + extras = None + if remaining: + if remaining[0] == '@': + # it's a URI + remaining = remaining[1:].lstrip() + m = NON_SPACE.match(remaining) + if not m: + raise SyntaxError('invalid URI: %s' % remaining) + uri = m.groups()[0] + t = urlparse(uri) + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not (t.scheme and t.netloc): + raise SyntaxError('Invalid URL: %s' % uri) + remaining = remaining[m.end():].lstrip() + else: + + def get_versions(ver_remaining): + """ + Return a list of operator, version tuples if any are + specified, else None. + """ + m = COMPARE_OP.match(ver_remaining) + versions = None + if m: + versions = [] + while True: + op = m.groups()[0] + ver_remaining = ver_remaining[m.end():] + m = VERSION_IDENTIFIER.match(ver_remaining) + if not m: + raise SyntaxError('invalid version: %s' % ver_remaining) + v = m.groups()[0] + versions.append((op, v)) + ver_remaining = ver_remaining[m.end():] + if not ver_remaining or ver_remaining[0] != ',': + break + ver_remaining = ver_remaining[1:].lstrip() + m = COMPARE_OP.match(ver_remaining) + if not m: + raise SyntaxError('invalid constraint: %s' % ver_remaining) + if not versions: + versions = None + return versions, ver_remaining + + if remaining[0] != '(': + versions, remaining = get_versions(remaining) + else: + i = remaining.find(')', 1) + if i < 0: + raise SyntaxError('unterminated parenthesis: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + # As a special diversion from PEP 508, allow a version number + # a.b.c in parentheses as a synonym for ~= a.b.c (because this + # is allowed in earlier PEPs) + if COMPARE_OP.match(s): + versions, _ = get_versions(s) + else: + m = VERSION_IDENTIFIER.match(s) + if not m: + raise SyntaxError('invalid constraint: %s' % s) + v = m.groups()[0] + s = s[m.end():].lstrip() + if s: + raise SyntaxError('invalid constraint: %s' % s) + versions = [('~=', v)] + + if remaining: + if remaining[0] != ';': + raise SyntaxError('invalid requirement: %s' % remaining) + remaining = remaining[1:].lstrip() + + mark_expr, remaining = parse_marker(remaining) + + if remaining and remaining[0] != '#': + raise SyntaxError('unexpected trailing data: %s' % remaining) + + if not versions: + rs = distname + else: + rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions])) + return Container(name=distname, extras=extras, constraints=versions, + marker=mark_expr, url=uri, requirement=rs) + + +def get_resources_dests(resources_root, rules): + """Find destinations for resources files""" + + def get_rel_path(root, path): + # normalizes and returns a lstripped-/-separated path + root = root.replace(os.path.sep, '/') + path = path.replace(os.path.sep, '/') + assert path.startswith(root) + return path[len(root):].lstrip('/') + + destinations = {} + for base, suffix, dest in rules: + prefix = os.path.join(resources_root, base) + for abs_base in iglob(prefix): + abs_glob = os.path.join(abs_base, suffix) + for abs_path in iglob(abs_glob): + resource_file = get_rel_path(resources_root, abs_path) + if dest is None: # remove the entry if it was here + destinations.pop(resource_file, None) + else: + rel_path = get_rel_path(abs_base, abs_path) + rel_dest = dest.replace(os.path.sep, '/').rstrip('/') + destinations[resource_file] = rel_dest + '/' + rel_path + return destinations + + +def in_venv(): + if hasattr(sys, 'real_prefix'): + # virtualenv venvs + result = True + else: + # PEP 405 venvs + result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) + return result + + +def get_executable(): +# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as +# changes to the stub launcher mean that sys.executable always points +# to the stub on OS X +# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' +# in os.environ): +# result = os.environ['__PYVENV_LAUNCHER__'] +# else: +# result = sys.executable +# return result + result = os.path.normcase(sys.executable) + if not isinstance(result, text_type): + result = fsdecode(result) + return result + + +def proceed(prompt, allowed_chars, error_prompt=None, default=None): + p = prompt + while True: + s = raw_input(p) + p = prompt + if not s and default: + s = default + if s: + c = s[0].lower() + if c in allowed_chars: + break + if error_prompt: + p = '%c: %s\n%s' % (c, error_prompt, prompt) + return c + + +def extract_by_key(d, keys): + if isinstance(keys, string_types): + keys = keys.split() + result = {} + for key in keys: + if key in d: + result[key] = d[key] + return result + +def read_exports(stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + # Try to load as JSON, falling back on legacy format + data = stream.read() + stream = StringIO(data) + try: + jdata = json.load(stream) + result = jdata['extensions']['python.exports']['exports'] + for group, entries in result.items(): + for k, v in entries.items(): + s = '%s = %s' % (k, v) + entry = get_export_entry(s) + assert entry is not None + entries[k] = entry + return result + except Exception: + stream.seek(0, 0) + + def read_stream(cp, stream): + if hasattr(cp, 'read_file'): + cp.read_file(stream) + else: + cp.readfp(stream) + + cp = configparser.ConfigParser() + try: + read_stream(cp, stream) + except configparser.MissingSectionHeaderError: + stream.close() + data = textwrap.dedent(data) + stream = StringIO(data) + read_stream(cp, stream) + + result = {} + for key in cp.sections(): + result[key] = entries = {} + for name, value in cp.items(key): + s = '%s = %s' % (name, value) + entry = get_export_entry(s) + assert entry is not None + #entry.dist = self + entries[name] = entry + return result + + +def write_exports(exports, stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getwriter('utf-8')(stream) + cp = configparser.ConfigParser() + for k, v in exports.items(): + # TODO check k, v for valid values + cp.add_section(k) + for entry in v.values(): + if entry.suffix is None: + s = entry.prefix + else: + s = '%s:%s' % (entry.prefix, entry.suffix) + if entry.flags: + s = '%s [%s]' % (s, ', '.join(entry.flags)) + cp.set(k, entry.name, s) + cp.write(stream) + + +@contextlib.contextmanager +def tempdir(): + td = tempfile.mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + +@contextlib.contextmanager +def chdir(d): + cwd = os.getcwd() + try: + os.chdir(d) + yield + finally: + os.chdir(cwd) + + +@contextlib.contextmanager +def socket_timeout(seconds=15): + cto = socket.getdefaulttimeout() + try: + socket.setdefaulttimeout(seconds) + yield + finally: + socket.setdefaulttimeout(cto) + + +class cached_property(object): + def __init__(self, func): + self.func = func + #for attr in ('__name__', '__module__', '__doc__'): + # setattr(self, attr, getattr(func, attr, None)) + + def __get__(self, obj, cls=None): + if obj is None: + return self + value = self.func(obj) + object.__setattr__(obj, self.func.__name__, value) + #obj.__dict__[self.func.__name__] = value = self.func(obj) + return value + +def convert_path(pathname): + """Return 'pathname' as a name that will work on the native filesystem. + + The path is split on '/' and put back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError("path '%s' cannot be absolute" % pathname) + if pathname[-1] == '/': + raise ValueError("path '%s' cannot end with '/'" % pathname) + + paths = pathname.split('/') + while os.curdir in paths: + paths.remove(os.curdir) + if not paths: + return os.curdir + return os.path.join(*paths) + + +class FileOperator(object): + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.ensured = set() + self._init_record() + + def _init_record(self): + self.record = False + self.files_written = set() + self.dirs_created = set() + + def record_as_written(self, path): + if self.record: + self.files_written.add(path) + + def newer(self, source, target): + """Tell if the target is newer than the source. + + Returns true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. + + Returns false if both exist and 'target' is the same age or younger + than 'source'. Raise PackagingFileError if 'source' does not exist. + + Note that this test is not very accurate: files created in the same + second will have the same "age". + """ + if not os.path.exists(source): + raise DistlibException("file '%r' does not exist" % + os.path.abspath(source)) + if not os.path.exists(target): + return True + + return os.stat(source).st_mtime > os.stat(target).st_mtime + + def copy_file(self, infile, outfile, check=True): + """Copy a file respecting dry-run and force flags. + """ + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying %s to %s', infile, outfile) + if not self.dry_run: + msg = None + if check: + if os.path.islink(outfile): + msg = '%s is a symlink' % outfile + elif os.path.exists(outfile) and not os.path.isfile(outfile): + msg = '%s is a non-regular file' % outfile + if msg: + raise ValueError(msg + ' which would be overwritten') + shutil.copyfile(infile, outfile) + self.record_as_written(outfile) + + def copy_stream(self, instream, outfile, encoding=None): + assert not os.path.isdir(outfile) + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying stream %s to %s', instream, outfile) + if not self.dry_run: + if encoding is None: + outstream = open(outfile, 'wb') + else: + outstream = codecs.open(outfile, 'w', encoding=encoding) + try: + shutil.copyfileobj(instream, outstream) + finally: + outstream.close() + self.record_as_written(outfile) + + def write_binary_file(self, path, data): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + with open(path, 'wb') as f: + f.write(data) + self.record_as_written(path) + + def write_text_file(self, path, data, encoding): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + with open(path, 'wb') as f: + f.write(data.encode(encoding)) + self.record_as_written(path) + + def set_mode(self, bits, mask, files): + if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'): + # Set the executable bits (owner, group, and world) on + # all the files specified. + for f in files: + if self.dry_run: + logger.info("changing mode of %s", f) + else: + mode = (os.stat(f).st_mode | bits) & mask + logger.info("changing mode of %s to %o", f, mode) + os.chmod(f, mode) + + set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) + + def ensure_dir(self, path): + path = os.path.abspath(path) + if path not in self.ensured and not os.path.exists(path): + self.ensured.add(path) + d, f = os.path.split(path) + self.ensure_dir(d) + logger.info('Creating %s' % path) + if not self.dry_run: + os.mkdir(path) + if self.record: + self.dirs_created.add(path) + + def byte_compile(self, path, optimize=False, force=False, prefix=None): + dpath = cache_from_source(path, not optimize) + logger.info('Byte-compiling %s to %s', path, dpath) + if not self.dry_run: + if force or self.newer(path, dpath): + if not prefix: + diagpath = None + else: + assert path.startswith(prefix) + diagpath = path[len(prefix):] + py_compile.compile(path, dpath, diagpath, True) # raise error + self.record_as_written(dpath) + return dpath + + def ensure_removed(self, path): + if os.path.exists(path): + if os.path.isdir(path) and not os.path.islink(path): + logger.debug('Removing directory tree at %s', path) + if not self.dry_run: + shutil.rmtree(path) + if self.record: + if path in self.dirs_created: + self.dirs_created.remove(path) + else: + if os.path.islink(path): + s = 'link' + else: + s = 'file' + logger.debug('Removing %s %s', s, path) + if not self.dry_run: + os.remove(path) + if self.record: + if path in self.files_written: + self.files_written.remove(path) + + def is_writable(self, path): + result = False + while not result: + if os.path.exists(path): + result = os.access(path, os.W_OK) + break + parent = os.path.dirname(path) + if parent == path: + break + path = parent + return result + + def commit(self): + """ + Commit recorded changes, turn off recording, return + changes. + """ + assert self.record + result = self.files_written, self.dirs_created + self._init_record() + return result + + def rollback(self): + if not self.dry_run: + for f in list(self.files_written): + if os.path.exists(f): + os.remove(f) + # dirs should all be empty now, except perhaps for + # __pycache__ subdirs + # reverse so that subdirs appear before their parents + dirs = sorted(self.dirs_created, reverse=True) + for d in dirs: + flist = os.listdir(d) + if flist: + assert flist == ['__pycache__'] + sd = os.path.join(d, flist[0]) + os.rmdir(sd) + os.rmdir(d) # should fail if non-empty + self._init_record() + +def resolve(module_name, dotted_path): + if module_name in sys.modules: + mod = sys.modules[module_name] + else: + mod = __import__(module_name) + if dotted_path is None: + result = mod + else: + parts = dotted_path.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + +class ExportEntry(object): + def __init__(self, name, prefix, suffix, flags): + self.name = name + self.prefix = prefix + self.suffix = suffix + self.flags = flags + + @cached_property + def value(self): + return resolve(self.prefix, self.suffix) + + def __repr__(self): # pragma: no cover + return '<ExportEntry %s = %s:%s %s>' % (self.name, self.prefix, + self.suffix, self.flags) + + def __eq__(self, other): + if not isinstance(other, ExportEntry): + result = False + else: + result = (self.name == other.name and + self.prefix == other.prefix and + self.suffix == other.suffix and + self.flags == other.flags) + return result + + __hash__ = object.__hash__ + + +ENTRY_RE = re.compile(r'''(?P<name>(\w|[-.+])+) + \s*=\s*(?P<callable>(\w+)([:\.]\w+)*) + \s*(\[\s*(?P<flags>\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? + ''', re.VERBOSE) + +def get_export_entry(specification): + m = ENTRY_RE.search(specification) + if not m: + result = None + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + else: + d = m.groupdict() + name = d['name'] + path = d['callable'] + colons = path.count(':') + if colons == 0: + prefix, suffix = path, None + else: + if colons != 1: + raise DistlibException("Invalid specification " + "'%s'" % specification) + prefix, suffix = path.split(':') + flags = d['flags'] + if flags is None: + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + flags = [] + else: + flags = [f.strip() for f in flags.split(',')] + result = ExportEntry(name, prefix, suffix, flags) + return result + + +def get_cache_base(suffix=None): + """ + Return the default base location for distlib caches. If the directory does + not exist, it is created. Use the suffix provided for the base directory, + and default to '.distlib' if it isn't provided. + + On Windows, if LOCALAPPDATA is defined in the environment, then it is + assumed to be a directory, and will be the parent directory of the result. + On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home + directory - using os.expanduser('~') - will be the parent directory of + the result. + + The result is just the directory '.distlib' in the parent directory as + determined above, or with the name specified with ``suffix``. + """ + if suffix is None: + suffix = '.distlib' + if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: + result = os.path.expandvars('$localappdata') + else: + # Assume posix, or old Windows + result = os.path.expanduser('~') + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if os.path.isdir(result): + usable = os.access(result, os.W_OK) + if not usable: + logger.warning('Directory exists but is not writable: %s', result) + else: + try: + os.makedirs(result) + usable = True + except OSError: + logger.warning('Unable to create %s', result, exc_info=True) + usable = False + if not usable: + result = tempfile.mkdtemp() + logger.warning('Default location unusable, using %s', result) + return os.path.join(result, suffix) + + +def path_to_cache_dir(path): + """ + Convert an absolute path to a directory name for use in a cache. + + The algorithm used is: + + #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. + #. Any occurrence of ``os.sep`` is replaced with ``'--'``. + #. ``'.cache'`` is appended. + """ + d, p = os.path.splitdrive(os.path.abspath(path)) + if d: + d = d.replace(':', '---') + p = p.replace(os.sep, '--') + return d + p + '.cache' + + +def ensure_slash(s): + if not s.endswith('/'): + return s + '/' + return s + + +def parse_credentials(netloc): + username = password = None + if '@' in netloc: + prefix, netloc = netloc.split('@', 1) + if ':' not in prefix: + username = prefix + else: + username, password = prefix.split(':', 1) + return username, password, netloc + + +def get_process_umask(): + result = os.umask(0o22) + os.umask(result) + return result + +def is_string_sequence(seq): + result = True + i = None + for i, s in enumerate(seq): + if not isinstance(s, string_types): + result = False + break + assert i is not None + return result + +PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' + '([a-z0-9_.+-]+)', re.I) +PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') + + +def split_filename(filename, project_name=None): + """ + Extract name, version, python version from a filename (no extension) + + Return name, version, pyver or None + """ + result = None + pyver = None + filename = unquote(filename).replace(' ', '-') + m = PYTHON_VERSION.search(filename) + if m: + pyver = m.group(1) + filename = filename[:m.start()] + if project_name and len(filename) > len(project_name) + 1: + m = re.match(re.escape(project_name) + r'\b', filename) + if m: + n = m.end() + result = filename[:n], filename[n + 1:], pyver + if result is None: + m = PROJECT_NAME_AND_VERSION.match(filename) + if m: + result = m.group(1), m.group(3), pyver + return result + +# Allow spaces in name because of legacy dists like "Twisted Core" +NAME_VERSION_RE = re.compile(r'(?P<name>[\w .-]+)\s*' + r'\(\s*(?P<ver>[^\s)]+)\)$') + +def parse_name_and_version(p): + """ + A utility method used to get name and version from a string. + + From e.g. a Provides-Dist value. + + :param p: A value in a form 'foo (1.0)' + :return: The name and version as a tuple. + """ + m = NAME_VERSION_RE.match(p) + if not m: + raise DistlibException('Ill-formed name/version string: \'%s\'' % p) + d = m.groupdict() + return d['name'].strip().lower(), d['ver'] + +def get_extras(requested, available): + result = set() + requested = set(requested or []) + available = set(available or []) + if '*' in requested: + requested.remove('*') + result |= available + for r in requested: + if r == '-': + result.add(r) + elif r.startswith('-'): + unwanted = r[1:] + if unwanted not in available: + logger.warning('undeclared extra: %s' % unwanted) + if unwanted in result: + result.remove(unwanted) + else: + if r not in available: + logger.warning('undeclared extra: %s' % r) + result.add(r) + return result +# +# Extended metadata functionality +# + +def _get_external_data(url): + result = {} + try: + # urlopen might fail if it runs into redirections, + # because of Python issue #13696. Fixed in locators + # using a custom redirect handler. + resp = urlopen(url) + headers = resp.info() + ct = headers.get('Content-Type') + if not ct.startswith('application/json'): + logger.debug('Unexpected response for JSON request: %s', ct) + else: + reader = codecs.getreader('utf-8')(resp) + #data = reader.read().decode('utf-8') + #result = json.loads(data) + result = json.load(reader) + except Exception as e: + logger.exception('Failed to get external data for %s: %s', url, e) + return result + +_external_data_base_url = 'https://www.red-dove.com/pypi/projects/' + +def get_project_data(name): + url = '%s/%s/project.json' % (name[0].upper(), name) + url = urljoin(_external_data_base_url, url) + result = _get_external_data(url) + return result + +def get_package_data(name, version): + url = '%s/%s/package-%s.json' % (name[0].upper(), name, version) + url = urljoin(_external_data_base_url, url) + return _get_external_data(url) + + +class Cache(object): + """ + A class implementing a cache for resources that need to live in the file system + e.g. shared libraries. This class was moved from resources to here because it + could be used by other modules, e.g. the wheel module. + """ + + def __init__(self, base): + """ + Initialise an instance. + + :param base: The base directory where the cache should be located. + """ + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if not os.path.isdir(base): # pragma: no cover + os.makedirs(base) + if (os.stat(base).st_mode & 0o77) != 0: + logger.warning('Directory \'%s\' is not private', base) + self.base = os.path.abspath(os.path.normpath(base)) + + def prefix_to_dir(self, prefix): + """ + Converts a resource prefix to a directory name in the cache. + """ + return path_to_cache_dir(prefix) + + def clear(self): + """ + Clear the cache. + """ + not_removed = [] + for fn in os.listdir(self.base): + fn = os.path.join(self.base, fn) + try: + if os.path.islink(fn) or os.path.isfile(fn): + os.remove(fn) + elif os.path.isdir(fn): + shutil.rmtree(fn) + except Exception: + not_removed.append(fn) + return not_removed + + +class EventMixin(object): + """ + A very simple publish/subscribe system. + """ + def __init__(self): + self._subscribers = {} + + def add(self, event, subscriber, append=True): + """ + Add a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be added (and called when the + event is published). + :param append: Whether to append or prepend the subscriber to an + existing subscriber list for the event. + """ + subs = self._subscribers + if event not in subs: + subs[event] = deque([subscriber]) + else: + sq = subs[event] + if append: + sq.append(subscriber) + else: + sq.appendleft(subscriber) + + def remove(self, event, subscriber): + """ + Remove a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be removed. + """ + subs = self._subscribers + if event not in subs: + raise ValueError('No subscribers: %r' % event) + subs[event].remove(subscriber) + + def get_subscribers(self, event): + """ + Return an iterator for the subscribers for an event. + :param event: The event to return subscribers for. + """ + return iter(self._subscribers.get(event, ())) + + def publish(self, event, *args, **kwargs): + """ + Publish a event and return a list of values returned by its + subscribers. + + :param event: The event to publish. + :param args: The positional arguments to pass to the event's + subscribers. + :param kwargs: The keyword arguments to pass to the event's + subscribers. + """ + result = [] + for subscriber in self.get_subscribers(event): + try: + value = subscriber(event, *args, **kwargs) + except Exception: + logger.exception('Exception during event publication') + value = None + result.append(value) + logger.debug('publish %s: args = %s, kwargs = %s, result = %s', + event, args, kwargs, result) + return result + +# +# Simple sequencing +# +class Sequencer(object): + def __init__(self): + self._preds = {} + self._succs = {} + self._nodes = set() # nodes with no preds/succs + + def add_node(self, node): + self._nodes.add(node) + + def remove_node(self, node, edges=False): + if node in self._nodes: + self._nodes.remove(node) + if edges: + for p in set(self._preds.get(node, ())): + self.remove(p, node) + for s in set(self._succs.get(node, ())): + self.remove(node, s) + # Remove empties + for k, v in list(self._preds.items()): + if not v: + del self._preds[k] + for k, v in list(self._succs.items()): + if not v: + del self._succs[k] + + def add(self, pred, succ): + assert pred != succ + self._preds.setdefault(succ, set()).add(pred) + self._succs.setdefault(pred, set()).add(succ) + + def remove(self, pred, succ): + assert pred != succ + try: + preds = self._preds[succ] + succs = self._succs[pred] + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of anything' % succ) + try: + preds.remove(pred) + succs.remove(succ) + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of %r' % (succ, pred)) + + def is_step(self, step): + return (step in self._preds or step in self._succs or + step in self._nodes) + + def get_steps(self, final): + if not self.is_step(final): + raise ValueError('Unknown: %r' % final) + result = [] + todo = [] + seen = set() + todo.append(final) + while todo: + step = todo.pop(0) + if step in seen: + # if a step was already seen, + # move it to the end (so it will appear earlier + # when reversed on return) ... but not for the + # final step, as that would be confusing for + # users + if step != final: + result.remove(step) + result.append(step) + else: + seen.add(step) + result.append(step) + preds = self._preds.get(step, ()) + todo.extend(preds) + return reversed(result) + + @property + def strong_connections(self): + #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + index_counter = [0] + stack = [] + lowlinks = {} + index = {} + result = [] + + graph = self._succs + + def strongconnect(node): + # set the depth index for this node to the smallest unused index + index[node] = index_counter[0] + lowlinks[node] = index_counter[0] + index_counter[0] += 1 + stack.append(node) + + # Consider successors + try: + successors = graph[node] + except Exception: + successors = [] + for successor in successors: + if successor not in lowlinks: + # Successor has not yet been visited + strongconnect(successor) + lowlinks[node] = min(lowlinks[node],lowlinks[successor]) + elif successor in stack: + # the successor is in the stack and hence in the current + # strongly connected component (SCC) + lowlinks[node] = min(lowlinks[node],index[successor]) + + # If `node` is a root node, pop the stack and generate an SCC + if lowlinks[node] == index[node]: + connected_component = [] + + while True: + successor = stack.pop() + connected_component.append(successor) + if successor == node: break + component = tuple(connected_component) + # storing the result + result.append(component) + + for node in graph: + if node not in lowlinks: + strongconnect(node) + + return result + + @property + def dot(self): + result = ['digraph G {'] + for succ in self._preds: + preds = self._preds[succ] + for pred in preds: + result.append(' %s -> %s;' % (pred, succ)) + for node in self._nodes: + result.append(' %s;' % node) + result.append('}') + return '\n'.join(result) + +# +# Unarchiving functionality for zip, tar, tgz, tbz, whl +# + +ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', + '.tgz', '.tbz', '.whl') + +def unarchive(archive_filename, dest_dir, format=None, check=True): + + def check_path(path): + if not isinstance(path, text_type): + path = path.decode('utf-8') + p = os.path.abspath(os.path.join(dest_dir, path)) + if not p.startswith(dest_dir) or p[plen] != os.sep: + raise ValueError('path outside destination: %r' % p) + + dest_dir = os.path.abspath(dest_dir) + plen = len(dest_dir) + archive = None + if format is None: + if archive_filename.endswith(('.zip', '.whl')): + format = 'zip' + elif archive_filename.endswith(('.tar.gz', '.tgz')): + format = 'tgz' + mode = 'r:gz' + elif archive_filename.endswith(('.tar.bz2', '.tbz')): + format = 'tbz' + mode = 'r:bz2' + elif archive_filename.endswith('.tar'): + format = 'tar' + mode = 'r' + else: # pragma: no cover + raise ValueError('Unknown format for %r' % archive_filename) + try: + if format == 'zip': + archive = ZipFile(archive_filename, 'r') + if check: + names = archive.namelist() + for name in names: + check_path(name) + else: + archive = tarfile.open(archive_filename, mode) + if check: + names = archive.getnames() + for name in names: + check_path(name) + if format != 'zip' and sys.version_info[0] < 3: + # See Python issue 17153. If the dest path contains Unicode, + # tarfile extraction fails on Python 2.x if a member path name + # contains non-ASCII characters - it leads to an implicit + # bytes -> unicode conversion using ASCII to decode. + for tarinfo in archive.getmembers(): + if not isinstance(tarinfo.name, text_type): + tarinfo.name = tarinfo.name.decode('utf-8') + archive.extractall(dest_dir) + + finally: + if archive: + archive.close() + + +def zip_dir(directory): + """zip a directory tree into a BytesIO object""" + result = io.BytesIO() + dlen = len(directory) + with ZipFile(result, "w") as zf: + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + rel = root[dlen:] + dest = os.path.join(rel, name) + zf.write(full, dest) + return result + +# +# Simple progress bar +# + +UNITS = ('', 'K', 'M', 'G','T','P') + + +class Progress(object): + unknown = 'UNKNOWN' + + def __init__(self, minval=0, maxval=100): + assert maxval is None or maxval >= minval + self.min = self.cur = minval + self.max = maxval + self.started = None + self.elapsed = 0 + self.done = False + + def update(self, curval): + assert self.min <= curval + assert self.max is None or curval <= self.max + self.cur = curval + now = time.time() + if self.started is None: + self.started = now + else: + self.elapsed = now - self.started + + def increment(self, incr): + assert incr >= 0 + self.update(self.cur + incr) + + def start(self): + self.update(self.min) + return self + + def stop(self): + if self.max is not None: + self.update(self.max) + self.done = True + + @property + def maximum(self): + return self.unknown if self.max is None else self.max + + @property + def percentage(self): + if self.done: + result = '100 %' + elif self.max is None: + result = ' ?? %' + else: + v = 100.0 * (self.cur - self.min) / (self.max - self.min) + result = '%3d %%' % v + return result + + def format_duration(self, duration): + if (duration <= 0) and self.max is None or self.cur == self.min: + result = '??:??:??' + #elif duration < 1: + # result = '--:--:--' + else: + result = time.strftime('%H:%M:%S', time.gmtime(duration)) + return result + + @property + def ETA(self): + if self.done: + prefix = 'Done' + t = self.elapsed + #import pdb; pdb.set_trace() + else: + prefix = 'ETA ' + if self.max is None: + t = -1 + elif self.elapsed == 0 or (self.cur == self.min): + t = 0 + else: + #import pdb; pdb.set_trace() + t = float(self.max - self.min) + t /= self.cur - self.min + t = (t - 1) * self.elapsed + return '%s: %s' % (prefix, self.format_duration(t)) + + @property + def speed(self): + if self.elapsed == 0: + result = 0.0 + else: + result = (self.cur - self.min) / self.elapsed + for unit in UNITS: + if result < 1000: + break + result /= 1000.0 + return '%d %sB/s' % (result, unit) + +# +# Glob functionality +# + +RICH_GLOB = re.compile(r'\{([^}]*)\}') +_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') +_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') + + +def iglob(path_glob): + """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" + if _CHECK_RECURSIVE_GLOB.search(path_glob): + msg = """invalid glob %r: recursive glob "**" must be used alone""" + raise ValueError(msg % path_glob) + if _CHECK_MISMATCH_SET.search(path_glob): + msg = """invalid glob %r: mismatching set marker '{' or '}'""" + raise ValueError(msg % path_glob) + return _iglob(path_glob) + + +def _iglob(path_glob): + rich_path_glob = RICH_GLOB.split(path_glob, 1) + if len(rich_path_glob) > 1: + assert len(rich_path_glob) == 3, rich_path_glob + prefix, set, suffix = rich_path_glob + for item in set.split(','): + for path in _iglob(''.join((prefix, item, suffix))): + yield path + else: + if '**' not in path_glob: + for item in std_iglob(path_glob): + yield item + else: + prefix, radical = path_glob.split('**', 1) + if prefix == '': + prefix = '.' + if radical == '': + radical = '*' + else: + # we support both + radical = radical.lstrip('/') + radical = radical.lstrip('\\') + for path, dir, files in os.walk(prefix): + path = os.path.normpath(path) + for fn in _iglob(os.path.join(path, radical)): + yield fn + +if ssl: + from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname, + CertificateError) + + +# +# HTTPSConnection which verifies certificates/matches domains +# + + class HTTPSConnection(httplib.HTTPSConnection): + ca_certs = None # set this to the path to the certs file (.pem) + check_domain = True # only used if ca_certs is not None + + # noinspection PyPropertyAccess + def connect(self): + sock = socket.create_connection((self.host, self.port), self.timeout) + if getattr(self, '_tunnel_host', False): + self.sock = sock + self._tunnel() + + if not hasattr(ssl, 'SSLContext'): + # For 2.x + if self.ca_certs: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, + cert_reqs=cert_reqs, + ssl_version=ssl.PROTOCOL_SSLv23, + ca_certs=self.ca_certs) + else: # pragma: no cover + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + context.options |= ssl.OP_NO_SSLv2 + if self.cert_file: + context.load_cert_chain(self.cert_file, self.key_file) + kwargs = {} + if self.ca_certs: + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(cafile=self.ca_certs) + if getattr(ssl, 'HAS_SNI', False): + kwargs['server_hostname'] = self.host + self.sock = context.wrap_socket(sock, **kwargs) + if self.ca_certs and self.check_domain: + try: + match_hostname(self.sock.getpeercert(), self.host) + logger.debug('Host verified: %s', self.host) + except CertificateError: # pragma: no cover + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + class HTTPSHandler(BaseHTTPSHandler): + def __init__(self, ca_certs, check_domain=True): + BaseHTTPSHandler.__init__(self) + self.ca_certs = ca_certs + self.check_domain = check_domain + + def _conn_maker(self, *args, **kwargs): + """ + This is called to create a connection instance. Normally you'd + pass a connection class to do_open, but it doesn't actually check for + a class, and just expects a callable. As long as we behave just as a + constructor would have, we should be OK. If it ever changes so that + we *must* pass a class, we'll create an UnsafeHTTPSConnection class + which just sets check_domain to False in the class definition, and + choose which one to pass to do_open. + """ + result = HTTPSConnection(*args, **kwargs) + if self.ca_certs: + result.ca_certs = self.ca_certs + result.check_domain = self.check_domain + return result + + def https_open(self, req): + try: + return self.do_open(self._conn_maker, req) + except URLError as e: + if 'certificate verify failed' in str(e.reason): + raise CertificateError('Unable to verify server certificate ' + 'for %s' % req.host) + else: + raise + + # + # To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- + # Middle proxy using HTTP listens on port 443, or an index mistakenly serves + # HTML containing a http://xyz link when it should be https://xyz), + # you can use the following handler class, which does not allow HTTP traffic. + # + # It works by inheriting from HTTPHandler - so build_opener won't add a + # handler for HTTP itself. + # + class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): + def http_open(self, req): + raise URLError('Unexpected HTTP request on what should be a secure ' + 'connection: %s' % req) + +# +# XML-RPC with timeouts +# + +_ver_info = sys.version_info[:2] + +if _ver_info == (2, 6): + class HTTP(httplib.HTTP): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + + if ssl: + class HTTPS(httplib.HTTPS): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + +class Transport(xmlrpclib.Transport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.Transport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, x509 = self.get_host_info(host) + if _ver_info == (2, 6): + result = HTTP(h, timeout=self.timeout) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPConnection(h) + result = self._connection[1] + return result + +if ssl: + class SafeTransport(xmlrpclib.SafeTransport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.SafeTransport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, kwargs = self.get_host_info(host) + if not kwargs: + kwargs = {} + kwargs['timeout'] = self.timeout + if _ver_info == (2, 6): + result = HTTPS(host, None, **kwargs) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPSConnection(h, None, + **kwargs) + result = self._connection[1] + return result + + +class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, **kwargs): + self.timeout = timeout = kwargs.pop('timeout', None) + # The above classes only come into play if a timeout + # is specified + if timeout is not None: + scheme, _ = splittype(uri) + use_datetime = kwargs.get('use_datetime', 0) + if scheme == 'https': + tcls = SafeTransport + else: + tcls = Transport + kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) + self.transport = t + xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) + +# +# CSV functionality. This is provided because on 2.x, the csv module can't +# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. +# + +def _csv_open(fn, mode, **kwargs): + if sys.version_info[0] < 3: + mode += 'b' + else: + kwargs['newline'] = '' + # Python 3 determines encoding from locale. Force 'utf-8' + # file encoding to match other forced utf-8 encoding + kwargs['encoding'] = 'utf-8' + return open(fn, mode, **kwargs) + + +class CSVBase(object): + defaults = { + 'delimiter': str(','), # The strs are used because we need native + 'quotechar': str('"'), # str in the csv API (2.x won't take + 'lineterminator': str('\n') # Unicode) + } + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.stream.close() + + +class CSVReader(CSVBase): + def __init__(self, **kwargs): + if 'stream' in kwargs: + stream = kwargs['stream'] + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + self.stream = stream + else: + self.stream = _csv_open(kwargs['path'], 'r') + self.reader = csv.reader(self.stream, **self.defaults) + + def __iter__(self): + return self + + def next(self): + result = next(self.reader) + if sys.version_info[0] < 3: + for i, item in enumerate(result): + if not isinstance(item, text_type): + result[i] = item.decode('utf-8') + return result + + __next__ = next + +class CSVWriter(CSVBase): + def __init__(self, fn, **kwargs): + self.stream = _csv_open(fn, 'w') + self.writer = csv.writer(self.stream, **self.defaults) + + def writerow(self, row): + if sys.version_info[0] < 3: + r = [] + for item in row: + if isinstance(item, text_type): + item = item.encode('utf-8') + r.append(item) + row = r + self.writer.writerow(row) + +# +# Configurator functionality +# + +class Configurator(BaseConfigurator): + + value_converters = dict(BaseConfigurator.value_converters) + value_converters['inc'] = 'inc_convert' + + def __init__(self, config, base=None): + super(Configurator, self).__init__(config) + self.base = base or os.getcwd() + + def configure_custom(self, config): + def convert(o): + if isinstance(o, (list, tuple)): + result = type(o)([convert(i) for i in o]) + elif isinstance(o, dict): + if '()' in o: + result = self.configure_custom(o) + else: + result = {} + for k in o: + result[k] = convert(o[k]) + else: + result = self.convert(o) + return result + + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + args = config.pop('[]', ()) + if args: + args = tuple([convert(o) for o in args]) + items = [(k, convert(config[k])) for k in config if valid_ident(k)] + kwargs = dict(items) + result = c(*args, **kwargs) + if props: + for n, v in props.items(): + setattr(result, n, convert(v)) + return result + + def __getitem__(self, key): + result = self.config[key] + if isinstance(result, dict) and '()' in result: + self.config[key] = result = self.configure_custom(result) + return result + + def inc_convert(self, value): + """Default converter for the inc:// protocol.""" + if not os.path.isabs(value): + value = os.path.join(self.base, value) + with codecs.open(value, 'r', encoding='utf-8') as f: + result = json.load(f) + return result + + +class SubprocessMixin(object): + """ + Mixin for running subprocesses and capturing their output + """ + def __init__(self, verbose=False, progress=None): + self.verbose = verbose + self.progress = progress + + def reader(self, stream, context): + """ + Read lines from a subprocess' output stream and either pass to a progress + callable (if specified) or write progress information to sys.stderr. + """ + progress = self.progress + verbose = self.verbose + while True: + s = stream.readline() + if not s: + break + if progress is not None: + progress(s, context) + else: + if not verbose: + sys.stderr.write('.') + else: + sys.stderr.write(s.decode('utf-8')) + sys.stderr.flush() + stream.close() + + def run_command(self, cmd, **kwargs): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, **kwargs) + t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) + t1.start() + t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) + t2.start() + p.wait() + t1.join() + t2.join() + if self.progress is not None: + self.progress('done.', 'main') + elif self.verbose: + sys.stderr.write('done.\n') + return p + + +def normalize_name(name): + """Normalize a python package name a la PEP 503""" + # https://www.python.org/dev/peps/pep-0503/#normalized-names + return re.sub('[-_.]+', '-', name).lower() diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/version.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/version.py new file mode 100644 index 0000000..3eebe18 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/version.py @@ -0,0 +1,736 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Implementation of a flexible versioning scheme providing support for PEP-440, +setuptools-compatible and semantic versioning. +""" + +import logging +import re + +from .compat import string_types +from .util import parse_requirement + +__all__ = ['NormalizedVersion', 'NormalizedMatcher', + 'LegacyVersion', 'LegacyMatcher', + 'SemanticVersion', 'SemanticMatcher', + 'UnsupportedVersionError', 'get_scheme'] + +logger = logging.getLogger(__name__) + + +class UnsupportedVersionError(ValueError): + """This is an unsupported version.""" + pass + + +class Version(object): + def __init__(self, s): + self._string = s = s.strip() + self._parts = parts = self.parse(s) + assert isinstance(parts, tuple) + assert len(parts) > 0 + + def parse(self, s): + raise NotImplementedError('please implement in a subclass') + + def _check_compatible(self, other): + if type(self) != type(other): + raise TypeError('cannot compare %r and %r' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + def __lt__(self, other): + self._check_compatible(other) + return self._parts < other._parts + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__lt__(other) or self.__eq__(other) + + def __ge__(self, other): + return self.__gt__(other) or self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self._parts) + + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + @property + def is_prerelease(self): + raise NotImplementedError('Please implement in subclasses.') + + +class Matcher(object): + version_class = None + + # value is either a callable or the name of a method + _operators = { + '<': lambda v, c, p: v < c, + '>': lambda v, c, p: v > c, + '<=': lambda v, c, p: v == c or v < c, + '>=': lambda v, c, p: v == c or v > c, + '==': lambda v, c, p: v == c, + '===': lambda v, c, p: v == c, + # by default, compatible => >=. + '~=': lambda v, c, p: v == c or v > c, + '!=': lambda v, c, p: v != c, + } + + # this is a method only to support alternative implementations + # via overriding + def parse_requirement(self, s): + return parse_requirement(s) + + def __init__(self, s): + if self.version_class is None: + raise ValueError('Please specify a version class') + self._string = s = s.strip() + r = self.parse_requirement(s) + if not r: + raise ValueError('Not valid: %r' % s) + self.name = r.name + self.key = self.name.lower() # for case-insensitive comparisons + clist = [] + if r.constraints: + # import pdb; pdb.set_trace() + for op, s in r.constraints: + if s.endswith('.*'): + if op not in ('==', '!='): + raise ValueError('\'.*\' not allowed for ' + '%r constraints' % op) + # Could be a partial version (e.g. for '2.*') which + # won't parse as a version, so keep it as a string + vn, prefix = s[:-2], True + # Just to check that vn is a valid version + self.version_class(vn) + else: + # Should parse as a version, so we can create an + # instance for the comparison + vn, prefix = self.version_class(s), False + clist.append((op, vn, prefix)) + self._parts = tuple(clist) + + def match(self, version): + """ + Check if the provided version matches the constraints. + + :param version: The version to match against this instance. + :type version: String or :class:`Version` instance. + """ + if isinstance(version, string_types): + version = self.version_class(version) + for operator, constraint, prefix in self._parts: + f = self._operators.get(operator) + if isinstance(f, string_types): + f = getattr(self, f) + if not f: + msg = ('%r not implemented ' + 'for %s' % (operator, self.__class__.__name__)) + raise NotImplementedError(msg) + if not f(version, constraint, prefix): + return False + return True + + @property + def exact_version(self): + result = None + if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='): + result = self._parts[0][1] + return result + + def _check_compatible(self, other): + if type(self) != type(other) or self.name != other.name: + raise TypeError('cannot compare %s and %s' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self.key == other.key and self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self.key) + hash(self._parts) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + +PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?' + r'(\.(post)(\d+))?(\.(dev)(\d+))?' + r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$') + + +def _pep_440_key(s): + s = s.strip() + m = PEP440_VERSION_RE.match(s) + if not m: + raise UnsupportedVersionError('Not a valid version: %s' % s) + groups = m.groups() + nums = tuple(int(v) for v in groups[1].split('.')) + while len(nums) > 1 and nums[-1] == 0: + nums = nums[:-1] + + if not groups[0]: + epoch = 0 + else: + epoch = int(groups[0]) + pre = groups[4:6] + post = groups[7:9] + dev = groups[10:12] + local = groups[13] + if pre == (None, None): + pre = () + else: + pre = pre[0], int(pre[1]) + if post == (None, None): + post = () + else: + post = post[0], int(post[1]) + if dev == (None, None): + dev = () + else: + dev = dev[0], int(dev[1]) + if local is None: + local = () + else: + parts = [] + for part in local.split('.'): + # to ensure that numeric compares as > lexicographic, avoid + # comparing them directly, but encode a tuple which ensures + # correct sorting + if part.isdigit(): + part = (1, int(part)) + else: + part = (0, part) + parts.append(part) + local = tuple(parts) + if not pre: + # either before pre-release, or final release and after + if not post and dev: + # before pre-release + pre = ('a', -1) # to sort before a0 + else: + pre = ('z',) # to sort after all pre-releases + # now look at the state of post and dev. + if not post: + post = ('_',) # sort before 'a' + if not dev: + dev = ('final',) + + #print('%s -> %s' % (s, m.groups())) + return epoch, nums, pre, post, dev, local + + +_normalized_key = _pep_440_key + + +class NormalizedVersion(Version): + """A rational version. + + Good: + 1.2 # equivalent to "1.2.0" + 1.2.0 + 1.2a1 + 1.2.3a2 + 1.2.3b1 + 1.2.3c1 + 1.2.3.4 + TODO: fill this out + + Bad: + 1 # minimum two numbers + 1.2a # release level must have a release serial + 1.2.3b + """ + def parse(self, s): + result = _normalized_key(s) + # _normalized_key loses trailing zeroes in the release + # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 + # However, PEP 440 prefix matching needs it: for example, + # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). + m = PEP440_VERSION_RE.match(s) # must succeed + groups = m.groups() + self._release_clause = tuple(int(v) for v in groups[1].split('.')) + return result + + PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) + + @property + def is_prerelease(self): + return any(t[0] in self.PREREL_TAGS for t in self._parts if t) + + +def _match_prefix(x, y): + x = str(x) + y = str(y) + if x == y: + return True + if not x.startswith(y): + return False + n = len(y) + return x[n] == '.' + + +class NormalizedMatcher(Matcher): + version_class = NormalizedVersion + + # value is either a callable or the name of a method + _operators = { + '~=': '_match_compatible', + '<': '_match_lt', + '>': '_match_gt', + '<=': '_match_le', + '>=': '_match_ge', + '==': '_match_eq', + '===': '_match_arbitrary', + '!=': '_match_ne', + } + + def _adjust_local(self, version, constraint, prefix): + if prefix: + strip_local = '+' not in constraint and version._parts[-1] + else: + # both constraint and version are + # NormalizedVersion instances. + # If constraint does not have a local component, + # ensure the version doesn't, either. + strip_local = not constraint._parts[-1] and version._parts[-1] + if strip_local: + s = version._string.split('+', 1)[0] + version = self.version_class(s) + return version, constraint + + def _match_lt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version >= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_gt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version <= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_le(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version <= constraint + + def _match_ge(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version >= constraint + + def _match_eq(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version == constraint) + else: + result = _match_prefix(version, constraint) + return result + + def _match_arbitrary(self, version, constraint, prefix): + return str(version) == str(constraint) + + def _match_ne(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version != constraint) + else: + result = not _match_prefix(version, constraint) + return result + + def _match_compatible(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version == constraint: + return True + if version < constraint: + return False +# if not prefix: +# return True + release_clause = constraint._release_clause + if len(release_clause) > 1: + release_clause = release_clause[:-1] + pfx = '.'.join([str(i) for i in release_clause]) + return _match_prefix(version, pfx) + +_REPLACEMENTS = ( + (re.compile('[.+-]$'), ''), # remove trailing puncts + (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start + (re.compile('^[.-]'), ''), # remove leading puncts + (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses + (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha + (re.compile(r'\b(pre-alpha|prealpha)\b'), + 'pre.alpha'), # standardise + (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses +) + +_SUFFIX_REPLACEMENTS = ( + (re.compile('^[:~._+-]+'), ''), # remove leading puncts + (re.compile('[,*")([\\]]'), ''), # remove unwanted chars + (re.compile('[~:+_ -]'), '.'), # replace illegal chars + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\.$'), ''), # trailing '.' +) + +_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') + + +def _suggest_semantic_version(s): + """ + Try to suggest a semantic form for a version for which + _suggest_normalized_version couldn't come up with anything. + """ + result = s.strip().lower() + for pat, repl in _REPLACEMENTS: + result = pat.sub(repl, result) + if not result: + result = '0.0.0' + + # Now look for numeric prefix, and separate it out from + # the rest. + #import pdb; pdb.set_trace() + m = _NUMERIC_PREFIX.match(result) + if not m: + prefix = '0.0.0' + suffix = result + else: + prefix = m.groups()[0].split('.') + prefix = [int(i) for i in prefix] + while len(prefix) < 3: + prefix.append(0) + if len(prefix) == 3: + suffix = result[m.end():] + else: + suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] + prefix = prefix[:3] + prefix = '.'.join([str(i) for i in prefix]) + suffix = suffix.strip() + if suffix: + #import pdb; pdb.set_trace() + # massage the suffix. + for pat, repl in _SUFFIX_REPLACEMENTS: + suffix = pat.sub(repl, suffix) + + if not suffix: + result = prefix + else: + sep = '-' if 'dev' in suffix else '+' + result = prefix + sep + suffix + if not is_semver(result): + result = None + return result + + +def _suggest_normalized_version(s): + """Suggest a normalized version close to the given version string. + + If you have a version string that isn't rational (i.e. NormalizedVersion + doesn't like it) then you might be able to get an equivalent (or close) + rational version from this function. + + This does a number of simple normalizations to the given string, based + on observation of versions currently in use on PyPI. Given a dump of + those version during PyCon 2009, 4287 of them: + - 2312 (53.93%) match NormalizedVersion without change + with the automatic suggestion + - 3474 (81.04%) match when using this suggestion method + + @param s {str} An irrational version string. + @returns A rational version string, or None, if couldn't determine one. + """ + try: + _normalized_key(s) + return s # already rational + except UnsupportedVersionError: + pass + + rs = s.lower() + + # part of this could use maketrans + for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), + ('beta', 'b'), ('rc', 'c'), ('-final', ''), + ('-pre', 'c'), + ('-release', ''), ('.release', ''), ('-stable', ''), + ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), + ('final', '')): + rs = rs.replace(orig, repl) + + # if something ends with dev or pre, we add a 0 + rs = re.sub(r"pre$", r"pre0", rs) + rs = re.sub(r"dev$", r"dev0", rs) + + # if we have something like "b-2" or "a.2" at the end of the + # version, that is probably beta, alpha, etc + # let's remove the dash or dot + rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) + + # 1.0-dev-r371 -> 1.0.dev371 + # 0.1-dev-r79 -> 0.1.dev79 + rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) + + # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 + rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) + + # Clean: v0.3, v1.0 + if rs.startswith('v'): + rs = rs[1:] + + # Clean leading '0's on numbers. + #TODO: unintended side-effect on, e.g., "2003.05.09" + # PyPI stats: 77 (~2%) better + rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) + + # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers + # zero. + # PyPI stats: 245 (7.56%) better + rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) + + # the 'dev-rNNN' tag is a dev tag + rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) + + # clean the - when used as a pre delimiter + rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) + + # a terminal "dev" or "devel" can be changed into ".dev0" + rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) + + # a terminal "dev" can be changed into ".dev0" + rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) + + # a terminal "final" or "stable" can be removed + rs = re.sub(r"(final|stable)$", "", rs) + + # The 'r' and the '-' tags are post release tags + # 0.4a1.r10 -> 0.4a1.post10 + # 0.9.33-17222 -> 0.9.33.post17222 + # 0.9.33-r17222 -> 0.9.33.post17222 + rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) + + # Clean 'r' instead of 'dev' usage: + # 0.9.33+r17222 -> 0.9.33.dev17222 + # 1.0dev123 -> 1.0.dev123 + # 1.0.git123 -> 1.0.dev123 + # 1.0.bzr123 -> 1.0.dev123 + # 0.1a0dev.123 -> 0.1a0.dev123 + # PyPI stats: ~150 (~4%) better + rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) + + # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: + # 0.2.pre1 -> 0.2c1 + # 0.2-c1 -> 0.2c1 + # 1.0preview123 -> 1.0c123 + # PyPI stats: ~21 (0.62%) better + rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) + + # Tcl/Tk uses "px" for their post release markers + rs = re.sub(r"p(\d+)$", r".post\1", rs) + + try: + _normalized_key(rs) + except UnsupportedVersionError: + rs = None + return rs + +# +# Legacy version processing (distribute-compatible) +# + +_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) +_VERSION_REPLACE = { + 'pre': 'c', + 'preview': 'c', + '-': 'final-', + 'rc': 'c', + 'dev': '@', + '': None, + '.': None, +} + + +def _legacy_key(s): + def get_parts(s): + result = [] + for p in _VERSION_PART.split(s.lower()): + p = _VERSION_REPLACE.get(p, p) + if p: + if '0' <= p[:1] <= '9': + p = p.zfill(8) + else: + p = '*' + p + result.append(p) + result.append('*final') + return result + + result = [] + for p in get_parts(s): + if p.startswith('*'): + if p < '*final': + while result and result[-1] == '*final-': + result.pop() + while result and result[-1] == '00000000': + result.pop() + result.append(p) + return tuple(result) + + +class LegacyVersion(Version): + def parse(self, s): + return _legacy_key(s) + + @property + def is_prerelease(self): + result = False + for x in self._parts: + if (isinstance(x, string_types) and x.startswith('*') and + x < '*final'): + result = True + break + return result + + +class LegacyMatcher(Matcher): + version_class = LegacyVersion + + _operators = dict(Matcher._operators) + _operators['~='] = '_match_compatible' + + numeric_re = re.compile(r'^(\d+(\.\d+)*)') + + def _match_compatible(self, version, constraint, prefix): + if version < constraint: + return False + m = self.numeric_re.match(str(constraint)) + if not m: + logger.warning('Cannot compute compatible match for version %s ' + ' and constraint %s', version, constraint) + return True + s = m.groups()[0] + if '.' in s: + s = s.rsplit('.', 1)[0] + return _match_prefix(version, s) + +# +# Semantic versioning +# + +_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' + r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' + r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) + + +def is_semver(s): + return _SEMVER_RE.match(s) + + +def _semantic_key(s): + def make_tuple(s, absent): + if s is None: + result = (absent,) + else: + parts = s[1:].split('.') + # We can't compare ints and strings on Python 3, so fudge it + # by zero-filling numeric values so simulate a numeric comparison + result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) + return result + + m = is_semver(s) + if not m: + raise UnsupportedVersionError(s) + groups = m.groups() + major, minor, patch = [int(i) for i in groups[:3]] + # choose the '|' and '*' so that versions sort correctly + pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') + return (major, minor, patch), pre, build + + +class SemanticVersion(Version): + def parse(self, s): + return _semantic_key(s) + + @property + def is_prerelease(self): + return self._parts[1][0] != '|' + + +class SemanticMatcher(Matcher): + version_class = SemanticVersion + + +class VersionScheme(object): + def __init__(self, key, matcher, suggester=None): + self.key = key + self.matcher = matcher + self.suggester = suggester + + def is_valid_version(self, s): + try: + self.matcher.version_class(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_matcher(self, s): + try: + self.matcher(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_constraint_list(self, s): + """ + Used for processing some metadata fields + """ + return self.is_valid_matcher('dummy_name (%s)' % s) + + def suggest(self, s): + if self.suggester is None: + result = None + else: + result = self.suggester(s) + return result + +_SCHEMES = { + 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, + _suggest_normalized_version), + 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), + 'semantic': VersionScheme(_semantic_key, SemanticMatcher, + _suggest_semantic_version), +} + +_SCHEMES['default'] = _SCHEMES['normalized'] + + +def get_scheme(name): + if name not in _SCHEMES: + raise ValueError('unknown scheme name: %r' % name) + return _SCHEMES[name] diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/w32.exe b/winvenv/Lib/site-packages/pip/_vendor/distlib/w32.exe new file mode 100644 index 0000000000000000000000000000000000000000..732215a9d34ccb7b417d637a7646d9b843ecafa8 GIT binary patch literal 89088 zcmeFae|S?>wm*FGqitH!CO`{C3REl(SahnPNDYM`O{q#T7)Xdvz$<hz5gjb&0FD$| zPs=nt#$jgk-tk`NUb*PJIy$3wMg@OiORy=5PEkZ0P^;6cyPm2=Y8#~Xyq~pC(iU~@ z_dd`2ywCg3TS)e=wSTX@_S$Q$y;FJf9>F9Cf*Bu86NCeB>CeT#|L3nblC!40kR?2m z{>H@z3`^g*ct!B1Tk<#8{Ol(+x7?n8>n(TO@iQ_1pEl;#NO$D_^p5<p8@>6r|7^p? zD>5@P3KB)%InlPUc<U{5lb_$uJ2!U@!dIxT&CTYnHuoCtzCL#`-1%8w%`JjkymkHD zpYr&>Cg9H}+(GW%^wV2|ROUbGfyXTfOART)i?<!WISJD#7!6|#8G`TvV*Xu^z32+K zc6>T0?9%;4K}Zn{6fx`yPa}*$9C+R!7zI~72c&$InY+UdMGBkF3c`HyxD3K09`bzW z?_q;rO&5ec#{?noJ4vI19bbHBt~vx^h2FH$V8i|^#EsiUg#JboP3@w-(&Uf&%NK<8 zSJZ5{MZ852W)~s>WeT(LIf&1wKNqULLI)GN_(-E-D)X~ZK=1;t<%*guHMhdg`-(mb zHzDv1KBN9zR9?--O+N$ReOXAr81V9z!X5SJ5`=3<1^<8V|AP@&sr2}Qvp;hQT24iW zOHg|EiZd1ojV;oo#(r^ba2`^8T22{~_UQ@YMZp7O1R*2@?SerFE~TuJB_wDaYC0h8 zfONF1t%{=H`W`bdYp+>YBsg9Ty9ec3iy+O3xa}TIvPK#Q&udyx1MvwG0(#iaGC|N| zJ#3?<Y4YLRkU`54s9BYRjyISA>){9$tW;Y34lPnX=&>D4X~|k7c$TwEfOzs@Yh#Nz z`FV;`(w!E`sKg@`2E}bDY>ku^4XS@tV(WO*<eu67;0Clk;vRHp!Qf<+5w0B!*Y>g? zYH=KK#%%Yu1~&m>IlB^#2^syGG|2AB1(}4aOcaC%!)}%`I7AIC2(Ro3yW`GSttng^ z_xb=ECor!L{-PNO>_ulJ3%fm=O0X!s%)$GZ?~I94l-^KEAX0n$?4wGpr7&i4#~)OB zQD%2NrWUKtZuYT1Vnu}AeF`cSgx>Rkk@}Lg{WltgT76VeA2aic`cTnpXrt2WXmJkM z9%u<Rp-*9{$HQ)>Xm?McyDyZ28Ux7mpxy?mnmvzMMr-85vkRrJLaDRx>|I7je+cM+ zj{RJ(3Vrgke;W@#D!y%U%fQLtlPKTAzWtVuOQdXpwsy6eRjt^cZ%0D4bF7$F;f!th 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ð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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/w64.exe b/winvenv/Lib/site-packages/pip/_vendor/distlib/w64.exe new file mode 100644 index 0000000000000000000000000000000000000000..c41bd0a011fd760ce20ba795d9e535e0d2c39876 GIT binary patch literal 99328 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 B=L-M; literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/pip/_vendor/distlib/wheel.py b/winvenv/Lib/site-packages/pip/_vendor/distlib/wheel.py new file mode 100644 index 0000000..7737223 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distlib/wheel.py @@ -0,0 +1,984 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import base64 +import codecs +import datetime +import distutils.util +from email import message_from_file +import hashlib +import imp +import json +import logging +import os +import posixpath +import re +import shutil +import sys +import tempfile +import zipfile + +from . import __version__, DistlibException +from .compat import sysconfig, ZipFile, fsdecode, text_type, filter +from .database import InstalledDistribution +from .metadata import Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME +from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, + cached_property, get_cache_base, read_exports, tempdir) +from .version import NormalizedVersion, UnsupportedVersionError + +logger = logging.getLogger(__name__) + +cache = None # created when needed + +if hasattr(sys, 'pypy_version_info'): # pragma: no cover + IMP_PREFIX = 'pp' +elif sys.platform.startswith('java'): # pragma: no cover + IMP_PREFIX = 'jy' +elif sys.platform == 'cli': # pragma: no cover + IMP_PREFIX = 'ip' +else: + IMP_PREFIX = 'cp' + +VER_SUFFIX = sysconfig.get_config_var('py_version_nodot') +if not VER_SUFFIX: # pragma: no cover + VER_SUFFIX = '%s%s' % sys.version_info[:2] +PYVER = 'py' + VER_SUFFIX +IMPVER = IMP_PREFIX + VER_SUFFIX + +ARCH = distutils.util.get_platform().replace('-', '_').replace('.', '_') + +ABI = sysconfig.get_config_var('SOABI') +if ABI and ABI.startswith('cpython-'): + ABI = ABI.replace('cpython-', 'cp') +else: + def _derive_abi(): + parts = ['cp', VER_SUFFIX] + if sysconfig.get_config_var('Py_DEBUG'): + parts.append('d') + if sysconfig.get_config_var('WITH_PYMALLOC'): + parts.append('m') + if sysconfig.get_config_var('Py_UNICODE_SIZE') == 4: + parts.append('u') + return ''.join(parts) + ABI = _derive_abi() + del _derive_abi + +FILENAME_RE = re.compile(r''' +(?P<nm>[^-]+) +-(?P<vn>\d+[^-]*) +(-(?P<bn>\d+[^-]*))? +-(?P<py>\w+\d+(\.\w+\d+)*) +-(?P<bi>\w+) +-(?P<ar>\w+(\.\w+)*) +\.whl$ +''', re.IGNORECASE | re.VERBOSE) + +NAME_VERSION_RE = re.compile(r''' +(?P<nm>[^-]+) +-(?P<vn>\d+[^-]*) +(-(?P<bn>\d+[^-]*))?$ +''', re.IGNORECASE | re.VERBOSE) + +SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') +SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$') +SHEBANG_PYTHON = b'#!python' +SHEBANG_PYTHONW = b'#!pythonw' + +if os.sep == '/': + to_posix = lambda o: o +else: + to_posix = lambda o: o.replace(os.sep, '/') + + +class Mounter(object): + def __init__(self): + self.impure_wheels = {} + self.libs = {} + + def add(self, pathname, extensions): + self.impure_wheels[pathname] = extensions + self.libs.update(extensions) + + def remove(self, pathname): + extensions = self.impure_wheels.pop(pathname) + for k, v in extensions: + if k in self.libs: + del self.libs[k] + + def find_module(self, fullname, path=None): + if fullname in self.libs: + result = self + else: + result = None + return result + + def load_module(self, fullname): + if fullname in sys.modules: + result = sys.modules[fullname] + else: + if fullname not in self.libs: + raise ImportError('unable to find extension for %s' % fullname) + result = imp.load_dynamic(fullname, self.libs[fullname]) + result.__loader__ = self + parts = fullname.rsplit('.', 1) + if len(parts) > 1: + result.__package__ = parts[0] + return result + +_hook = Mounter() + + +class Wheel(object): + """ + Class to build and install from Wheel files (PEP 427). + """ + + wheel_version = (1, 1) + hash_kind = 'sha256' + + def __init__(self, filename=None, sign=False, verify=False): + """ + Initialise an instance using a (valid) filename. + """ + self.sign = sign + self.should_verify = verify + self.buildver = '' + self.pyver = [PYVER] + self.abi = ['none'] + self.arch = ['any'] + self.dirname = os.getcwd() + if filename is None: + self.name = 'dummy' + self.version = '0.1' + self._filename = self.filename + else: + m = NAME_VERSION_RE.match(filename) + if m: + info = m.groupdict('') + self.name = info['nm'] + # Reinstate the local version separator + self.version = info['vn'].replace('_', '-') + self.buildver = info['bn'] + self._filename = self.filename + else: + dirname, filename = os.path.split(filename) + m = FILENAME_RE.match(filename) + if not m: + raise DistlibException('Invalid name or ' + 'filename: %r' % filename) + if dirname: + self.dirname = os.path.abspath(dirname) + self._filename = filename + info = m.groupdict('') + self.name = info['nm'] + self.version = info['vn'] + self.buildver = info['bn'] + self.pyver = info['py'].split('.') + self.abi = info['bi'].split('.') + self.arch = info['ar'].split('.') + + @property + def filename(self): + """ + Build and return a filename from the various components. + """ + if self.buildver: + buildver = '-' + self.buildver + else: + buildver = '' + pyver = '.'.join(self.pyver) + abi = '.'.join(self.abi) + arch = '.'.join(self.arch) + # replace - with _ as a local version separator + version = self.version.replace('-', '_') + return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, + pyver, abi, arch) + + @property + def exists(self): + path = os.path.join(self.dirname, self.filename) + return os.path.isfile(path) + + @property + def tags(self): + for pyver in self.pyver: + for abi in self.abi: + for arch in self.arch: + yield pyver, abi, arch + + @cached_property + def metadata(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + wrapper = codecs.getreader('utf-8') + with ZipFile(pathname, 'r') as zf: + wheel_metadata = self.get_wheel_metadata(zf) + wv = wheel_metadata['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if file_version < (1, 1): + fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME, 'METADATA'] + else: + fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME] + result = None + for fn in fns: + try: + metadata_filename = posixpath.join(info_dir, fn) + with zf.open(metadata_filename) as bf: + wf = wrapper(bf) + result = Metadata(fileobj=wf) + if result: + break + except KeyError: + pass + if not result: + raise ValueError('Invalid wheel, because metadata is ' + 'missing: looked in %s' % ', '.join(fns)) + return result + + def get_wheel_metadata(self, zf): + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + metadata_filename = posixpath.join(info_dir, 'WHEEL') + with zf.open(metadata_filename) as bf: + wf = codecs.getreader('utf-8')(bf) + message = message_from_file(wf) + return dict(message) + + @cached_property + def info(self): + pathname = os.path.join(self.dirname, self.filename) + with ZipFile(pathname, 'r') as zf: + result = self.get_wheel_metadata(zf) + return result + + def process_shebang(self, data): + m = SHEBANG_RE.match(data) + if m: + end = m.end() + shebang, data_after_shebang = data[:end], data[end:] + # Preserve any arguments after the interpreter + if b'pythonw' in shebang.lower(): + shebang_python = SHEBANG_PYTHONW + else: + shebang_python = SHEBANG_PYTHON + m = SHEBANG_DETAIL_RE.match(shebang) + if m: + args = b' ' + m.groups()[-1] + else: + args = b'' + shebang = shebang_python + args + data = shebang + data_after_shebang + else: + cr = data.find(b'\r') + lf = data.find(b'\n') + if cr < 0 or cr > lf: + term = b'\n' + else: + if data[cr:cr + 2] == b'\r\n': + term = b'\r\n' + else: + term = b'\r' + data = SHEBANG_PYTHON + term + data + return data + + def get_hash(self, data, hash_kind=None): + if hash_kind is None: + hash_kind = self.hash_kind + try: + hasher = getattr(hashlib, hash_kind) + except AttributeError: + raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) + result = hasher(data).digest() + result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') + return hash_kind, result + + def write_record(self, records, record_path, base): + records = list(records) # make a copy for sorting + p = to_posix(os.path.relpath(record_path, base)) + records.append((p, '', '')) + records.sort() + with CSVWriter(record_path) as writer: + for row in records: + writer.writerow(row) + + def write_records(self, info, libdir, archive_paths): + records = [] + distinfo, info_dir = info + hasher = getattr(hashlib, self.hash_kind) + for ap, p in archive_paths: + with open(p, 'rb') as f: + data = f.read() + digest = '%s=%s' % self.get_hash(data) + size = os.path.getsize(p) + records.append((ap, digest, size)) + + p = os.path.join(distinfo, 'RECORD') + self.write_record(records, p, libdir) + ap = to_posix(os.path.join(info_dir, 'RECORD')) + archive_paths.append((ap, p)) + + def build_zip(self, pathname, archive_paths): + with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: + for ap, p in archive_paths: + logger.debug('Wrote %s to %s in wheel', p, ap) + zf.write(p, ap) + + def build(self, paths, tags=None, wheel_version=None): + """ + Build a wheel from files in specified paths, and use any specified tags + when determining the name of the wheel. + """ + if tags is None: + tags = {} + + libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] + if libkey == 'platlib': + is_pure = 'false' + default_pyver = [IMPVER] + default_abi = [ABI] + default_arch = [ARCH] + else: + is_pure = 'true' + default_pyver = [PYVER] + default_abi = ['none'] + default_arch = ['any'] + + self.pyver = tags.get('pyver', default_pyver) + self.abi = tags.get('abi', default_abi) + self.arch = tags.get('arch', default_arch) + + libdir = paths[libkey] + + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + archive_paths = [] + + # First, stuff which is not in site-packages + for key in ('data', 'headers', 'scripts'): + if key not in paths: + continue + path = paths[key] + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + for fn in files: + p = fsdecode(os.path.join(root, fn)) + rp = os.path.relpath(p, path) + ap = to_posix(os.path.join(data_dir, key, rp)) + archive_paths.append((ap, p)) + if key == 'scripts' and not p.endswith('.exe'): + with open(p, 'rb') as f: + data = f.read() + data = self.process_shebang(data) + with open(p, 'wb') as f: + f.write(data) + + # Now, stuff which is in site-packages, other than the + # distinfo stuff. + path = libdir + distinfo = None + for root, dirs, files in os.walk(path): + if root == path: + # At the top level only, save distinfo for later + # and skip it for now + for i, dn in enumerate(dirs): + dn = fsdecode(dn) + if dn.endswith('.dist-info'): + distinfo = os.path.join(root, dn) + del dirs[i] + break + assert distinfo, '.dist-info directory expected, not found' + + for fn in files: + # comment out next suite to leave .pyc files in + if fsdecode(fn).endswith(('.pyc', '.pyo')): + continue + p = os.path.join(root, fn) + rp = to_posix(os.path.relpath(p, path)) + archive_paths.append((rp, p)) + + # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. + files = os.listdir(distinfo) + for fn in files: + if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'): + p = fsdecode(os.path.join(distinfo, fn)) + ap = to_posix(os.path.join(info_dir, fn)) + archive_paths.append((ap, p)) + + wheel_metadata = [ + 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), + 'Generator: distlib %s' % __version__, + 'Root-Is-Purelib: %s' % is_pure, + ] + for pyver, abi, arch in self.tags: + wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) + p = os.path.join(distinfo, 'WHEEL') + with open(p, 'w') as f: + f.write('\n'.join(wheel_metadata)) + ap = to_posix(os.path.join(info_dir, 'WHEEL')) + archive_paths.append((ap, p)) + + # Now, at last, RECORD. + # Paths in here are archive paths - nothing else makes sense. + self.write_records((distinfo, info_dir), libdir, archive_paths) + # Now, ready to build the zip file + pathname = os.path.join(self.dirname, self.filename) + self.build_zip(pathname, archive_paths) + return pathname + + def install(self, paths, maker, **kwargs): + """ + Install a wheel to the specified paths. If kwarg ``warner`` is + specified, it should be a callable, which will be called with two + tuples indicating the wheel version of this software and the wheel + version in the file, if there is a discrepancy in the versions. + This can be used to issue any warnings to raise any exceptions. + If kwarg ``lib_only`` is True, only the purelib/platlib files are + installed, and the headers, scripts, data and dist-info metadata are + not written. + + The return value is a :class:`InstalledDistribution` instance unless + ``options.lib_only`` is True, in which case the return value is ``None``. + """ + + dry_run = maker.dry_run + warner = kwargs.get('warner') + lib_only = kwargs.get('lib_only', False) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if (file_version != self.wheel_version) and warner: + warner(self.wheel_version, file_version) + + if message['Root-Is-Purelib'] == 'true': + libdir = paths['purelib'] + else: + libdir = paths['platlib'] + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + data_pfx = posixpath.join(data_dir, '') + info_pfx = posixpath.join(info_dir, '') + script_pfx = posixpath.join(data_dir, 'scripts', '') + + # make a new instance rather than a copy of maker's, + # as we mutate it + fileop = FileOperator(dry_run=dry_run) + fileop.record = True # so we can rollback if needed + + bc = not sys.dont_write_bytecode # Double negatives. Lovely! + + outfiles = [] # for RECORD writing + + # for script copying/shebang processing + workdir = tempfile.mkdtemp() + # set target dir later + # we default add_launchers to False, as the + # Python Launcher should be used instead + maker.source_dir = workdir + maker.target_dir = None + try: + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + if u_arcname.endswith('/RECORD.jws'): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + if lib_only and u_arcname.startswith((info_pfx, data_pfx)): + logger.debug('lib_only: skipping %s', u_arcname) + continue + is_script = (u_arcname.startswith(script_pfx) + and not u_arcname.endswith('.exe')) + + if u_arcname.startswith(data_pfx): + _, where, rp = u_arcname.split('/', 2) + outfile = os.path.join(paths[where], convert_path(rp)) + else: + # meant for site-packages. + if u_arcname in (wheel_metadata_name, record_name): + continue + outfile = os.path.join(libdir, convert_path(u_arcname)) + if not is_script: + with zf.open(arcname) as bf: + fileop.copy_stream(bf, outfile) + outfiles.append(outfile) + # Double check the digest of the written file + if not dry_run and row[1]: + with open(outfile, 'rb') as bf: + data = bf.read() + _, newdigest = self.get_hash(data, kind) + if newdigest != digest: + raise DistlibException('digest mismatch ' + 'on write for ' + '%s' % outfile) + if bc and outfile.endswith('.py'): + try: + pyc = fileop.byte_compile(outfile) + outfiles.append(pyc) + except Exception: + # Don't give up if byte-compilation fails, + # but log it and perhaps warn the user + logger.warning('Byte-compilation failed', + exc_info=True) + else: + fn = os.path.basename(convert_path(arcname)) + workname = os.path.join(workdir, fn) + with zf.open(arcname) as bf: + fileop.copy_stream(bf, workname) + + dn, fn = os.path.split(outfile) + maker.target_dir = dn + filenames = maker.make(fn) + fileop.set_executable_mode(filenames) + outfiles.extend(filenames) + + if lib_only: + logger.debug('lib_only: returning None') + dist = None + else: + # Generate scripts + + # Try to get pydist.json so we can see if there are + # any commands to generate. If this fails (e.g. because + # of a legacy wheel), log a warning but don't give up. + commands = None + file_version = self.info['Wheel-Version'] + if file_version == '1.0': + # Use legacy info + ep = posixpath.join(info_dir, 'entry_points.txt') + try: + with zf.open(ep) as bwf: + epdata = read_exports(bwf) + commands = {} + for key in ('console', 'gui'): + k = '%s_scripts' % key + if k in epdata: + commands['wrap_%s' % key] = d = {} + for v in epdata[k].values(): + s = '%s:%s' % (v.prefix, v.suffix) + if v.flags: + s += ' %s' % v.flags + d[v.name] = s + except Exception: + logger.warning('Unable to read legacy script ' + 'metadata, so cannot generate ' + 'scripts') + else: + try: + with zf.open(metadata_name) as bwf: + wf = wrapper(bwf) + commands = json.load(wf).get('extensions') + if commands: + commands = commands.get('python.commands') + except Exception: + logger.warning('Unable to read JSON metadata, so ' + 'cannot generate scripts') + if commands: + console_scripts = commands.get('wrap_console', {}) + gui_scripts = commands.get('wrap_gui', {}) + if console_scripts or gui_scripts: + script_dir = paths.get('scripts', '') + if not os.path.isdir(script_dir): + raise ValueError('Valid script path not ' + 'specified') + maker.target_dir = script_dir + for k, v in console_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script) + fileop.set_executable_mode(filenames) + + if gui_scripts: + options = {'gui': True } + for k, v in gui_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script, options) + fileop.set_executable_mode(filenames) + + p = os.path.join(libdir, info_dir) + dist = InstalledDistribution(p) + + # Write SHARED + paths = dict(paths) # don't change passed in dict + del paths['purelib'] + del paths['platlib'] + paths['lib'] = libdir + p = dist.write_shared_locations(paths, dry_run) + if p: + outfiles.append(p) + + # Write RECORD + dist.write_installed_files(outfiles, paths['prefix'], + dry_run) + return dist + except Exception: # pragma: no cover + logger.exception('installation failed.') + fileop.rollback() + raise + finally: + shutil.rmtree(workdir) + + def _get_dylib_cache(self): + global cache + if cache is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('dylib-cache'), + sys.version[:3]) + cache = Cache(base) + return cache + + def _get_extensions(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + arcname = posixpath.join(info_dir, 'EXTENSIONS') + wrapper = codecs.getreader('utf-8') + result = [] + with ZipFile(pathname, 'r') as zf: + try: + with zf.open(arcname) as bf: + wf = wrapper(bf) + extensions = json.load(wf) + cache = self._get_dylib_cache() + prefix = cache.prefix_to_dir(pathname) + cache_base = os.path.join(cache.base, prefix) + if not os.path.isdir(cache_base): + os.makedirs(cache_base) + for name, relpath in extensions.items(): + dest = os.path.join(cache_base, convert_path(relpath)) + if not os.path.exists(dest): + extract = True + else: + file_time = os.stat(dest).st_mtime + file_time = datetime.datetime.fromtimestamp(file_time) + info = zf.getinfo(relpath) + wheel_time = datetime.datetime(*info.date_time) + extract = wheel_time > file_time + if extract: + zf.extract(relpath, cache_base) + result.append((name, dest)) + except KeyError: + pass + return result + + def is_compatible(self): + """ + Determine if a wheel is compatible with the running system. + """ + return is_compatible(self) + + def is_mountable(self): + """ + Determine if a wheel is asserted as mountable by its metadata. + """ + return True # for now - metadata details TBD + + def mount(self, append=False): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if not self.is_compatible(): + msg = 'Wheel %s not compatible with this Python.' % pathname + raise DistlibException(msg) + if not self.is_mountable(): + msg = 'Wheel %s is marked as not mountable.' % pathname + raise DistlibException(msg) + if pathname in sys.path: + logger.debug('%s already in path', pathname) + else: + if append: + sys.path.append(pathname) + else: + sys.path.insert(0, pathname) + extensions = self._get_extensions() + if extensions: + if _hook not in sys.meta_path: + sys.meta_path.append(_hook) + _hook.add(pathname, extensions) + + def unmount(self): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if pathname not in sys.path: + logger.debug('%s not in path', pathname) + else: + sys.path.remove(pathname) + if pathname in _hook.impure_wheels: + _hook.remove(pathname) + if not _hook.impure_wheels: + if _hook in sys.meta_path: + sys.meta_path.remove(_hook) + + def verify(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + # TODO version verification + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + if u_arcname.endswith('/RECORD.jws'): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + def update(self, modifier, dest_dir=None, **kwargs): + """ + Update the contents of a wheel in a generic way. The modifier should + be a callable which expects a dictionary argument: its keys are + archive-entry paths, and its values are absolute filesystem paths + where the contents the corresponding archive entries can be found. The + modifier is free to change the contents of the files pointed to, add + new entries and remove entries, before returning. This method will + extract the entire contents of the wheel to a temporary location, call + the modifier, and then use the passed (and possibly updated) + dictionary to write a new wheel. If ``dest_dir`` is specified, the new + wheel is written there -- otherwise, the original wheel is overwritten. + + The modifier should return True if it updated the wheel, else False. + This method returns the same value the modifier returns. + """ + + def get_version(path_map, info_dir): + version = path = None + key = '%s/%s' % (info_dir, METADATA_FILENAME) + if key not in path_map: + key = '%s/PKG-INFO' % info_dir + if key in path_map: + path = path_map[key] + version = Metadata(path=path).version + return version, path + + def update_version(version, path): + updated = None + try: + v = NormalizedVersion(version) + i = version.find('-') + if i < 0: + updated = '%s+1' % version + else: + parts = [int(s) for s in version[i + 1:].split('.')] + parts[-1] += 1 + updated = '%s+%s' % (version[:i], + '.'.join(str(i) for i in parts)) + except UnsupportedVersionError: + logger.debug('Cannot update non-compliant (PEP-440) ' + 'version %r', version) + if updated: + md = Metadata(path=path) + md.version = updated + legacy = not path.endswith(METADATA_FILENAME) + md.write(path=path, legacy=legacy) + logger.debug('Version updated from %r to %r', version, + updated) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + record_name = posixpath.join(info_dir, 'RECORD') + with tempdir() as workdir: + with ZipFile(pathname, 'r') as zf: + path_map = {} + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if u_arcname == record_name: + continue + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + zf.extract(zinfo, workdir) + path = os.path.join(workdir, convert_path(u_arcname)) + path_map[u_arcname] = path + + # Remember the version. + original_version, _ = get_version(path_map, info_dir) + # Files extracted. Call the modifier. + modified = modifier(path_map, **kwargs) + if modified: + # Something changed - need to build a new wheel. + current_version, path = get_version(path_map, info_dir) + if current_version and (current_version == original_version): + # Add or update local version to signify changes. + update_version(current_version, path) + # Decide where the new wheel goes. + if dest_dir is None: + fd, newpath = tempfile.mkstemp(suffix='.whl', + prefix='wheel-update-', + dir=workdir) + os.close(fd) + else: + if not os.path.isdir(dest_dir): + raise DistlibException('Not a directory: %r' % dest_dir) + newpath = os.path.join(dest_dir, self.filename) + archive_paths = list(path_map.items()) + distinfo = os.path.join(workdir, info_dir) + info = distinfo, info_dir + self.write_records(info, workdir, archive_paths) + self.build_zip(newpath, archive_paths) + if dest_dir is None: + shutil.copyfile(newpath, pathname) + return modified + +def compatible_tags(): + """ + Return (pyver, abi, arch) tuples compatible with this Python. + """ + versions = [VER_SUFFIX] + major = VER_SUFFIX[0] + for minor in range(sys.version_info[1] - 1, - 1, -1): + versions.append(''.join([major, str(minor)])) + + abis = [] + for suffix, _, _ in imp.get_suffixes(): + if suffix.startswith('.abi'): + abis.append(suffix.split('.', 2)[1]) + abis.sort() + if ABI != 'none': + abis.insert(0, ABI) + abis.append('none') + result = [] + + arches = [ARCH] + if sys.platform == 'darwin': + m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH) + if m: + name, major, minor, arch = m.groups() + minor = int(minor) + matches = [arch] + if arch in ('i386', 'ppc'): + matches.append('fat') + if arch in ('i386', 'ppc', 'x86_64'): + matches.append('fat3') + if arch in ('ppc64', 'x86_64'): + matches.append('fat64') + if arch in ('i386', 'x86_64'): + matches.append('intel') + if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'): + matches.append('universal') + while minor >= 0: + for match in matches: + s = '%s_%s_%s_%s' % (name, major, minor, match) + if s != ARCH: # already there + arches.append(s) + minor -= 1 + + # Most specific - our Python version, ABI and arch + for abi in abis: + for arch in arches: + result.append((''.join((IMP_PREFIX, versions[0])), abi, arch)) + + # where no ABI / arch dependency, but IMP_PREFIX dependency + for i, version in enumerate(versions): + result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) + if i == 0: + result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) + + # no IMP_PREFIX, ABI or arch dependency + for i, version in enumerate(versions): + result.append((''.join(('py', version)), 'none', 'any')) + if i == 0: + result.append((''.join(('py', version[0])), 'none', 'any')) + return set(result) + + +COMPATIBLE_TAGS = compatible_tags() + +del compatible_tags + + +def is_compatible(wheel, tags=None): + if not isinstance(wheel, Wheel): + wheel = Wheel(wheel) # assume it's a filename + result = False + if tags is None: + tags = COMPATIBLE_TAGS + for ver, abi, arch in tags: + if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: + result = True + break + return result diff --git a/winvenv/Lib/site-packages/pip/_vendor/distro.py b/winvenv/Lib/site-packages/pip/_vendor/distro.py new file mode 100644 index 0000000..aa4defc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/distro.py @@ -0,0 +1,1197 @@ +# Copyright 2015,2016,2017 Nir Cohen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +The ``distro`` package (``distro`` stands for Linux Distribution) provides +information about the Linux distribution it runs on, such as a reliable +machine-readable distro ID, or version information. + +It is a renewed alternative implementation for Python's original +:py:func:`platform.linux_distribution` function, but it provides much more +functionality. An alternative implementation became necessary because Python +3.5 deprecated this function, and Python 3.7 is expected to remove it +altogether. Its predecessor function :py:func:`platform.dist` was already +deprecated since Python 2.6 and is also expected to be removed in Python 3.7. +Still, there are many cases in which access to OS distribution information +is needed. See `Python issue 1322 <https://bugs.python.org/issue1322>`_ for +more information. +""" + +import os +import re +import sys +import json +import shlex +import logging +import argparse +import subprocess + + +_UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc') +_OS_RELEASE_BASENAME = 'os-release' + +#: Translation table for normalizing the "ID" attribute defined in os-release +#: files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as defined in the os-release file, translated to lower case, +#: with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_OS_ID = {} + +#: Translation table for normalizing the "Distributor ID" attribute returned by +#: the lsb_release command, for use by the :func:`distro.id` method. +#: +#: * Key: Value as returned by the lsb_release command, translated to lower +#: case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_LSB_ID = { + 'enterpriseenterprise': 'oracle', # Oracle Enterprise Linux + 'redhatenterpriseworkstation': 'rhel', # RHEL 6, 7 Workstation + 'redhatenterpriseserver': 'rhel', # RHEL 6, 7 Server +} + +#: Translation table for normalizing the distro ID derived from the file name +#: of distro release files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as derived from the file name of a distro release file, +#: translated to lower case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_DISTRO_ID = { + 'redhat': 'rhel', # RHEL 6.x, 7.x +} + +# Pattern for content of distro release file (reversed) +_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( + r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)') + +# Pattern for base file name of distro release file +_DISTRO_RELEASE_BASENAME_PATTERN = re.compile( + r'(\w+)[-_](release|version)$') + +# Base file names to be ignored when searching for distro release file +_DISTRO_RELEASE_IGNORE_BASENAMES = ( + 'debian_version', + 'lsb-release', + 'oem-release', + _OS_RELEASE_BASENAME, + 'system-release' +) + + +def linux_distribution(full_distribution_name=True): + """ + Return information about the current OS distribution as a tuple + ``(id_name, version, codename)`` with items as follows: + + * ``id_name``: If *full_distribution_name* is false, the result of + :func:`distro.id`. Otherwise, the result of :func:`distro.name`. + + * ``version``: The result of :func:`distro.version`. + + * ``codename``: The result of :func:`distro.codename`. + + The interface of this function is compatible with the original + :py:func:`platform.linux_distribution` function, supporting a subset of + its parameters. + + The data it returns may not exactly be the same, because it uses more data + sources than the original function, and that may lead to different data if + the OS distribution is not consistent across multiple data sources it + provides (there are indeed such distributions ...). + + Another reason for differences is the fact that the :func:`distro.id` + method normalizes the distro ID string to a reliable machine-readable value + for a number of popular OS distributions. + """ + return _distro.linux_distribution(full_distribution_name) + + +def id(): + """ + Return the distro ID of the current distribution, as a + machine-readable string. + + For a number of OS distributions, the returned distro ID value is + *reliable*, in the sense that it is documented and that it does not change + across releases of the distribution. + + This package maintains the following reliable distro ID values: + + ============== ========================================= + Distro ID Distribution + ============== ========================================= + "ubuntu" Ubuntu + "debian" Debian + "rhel" RedHat Enterprise Linux + "centos" CentOS + "fedora" Fedora + "sles" SUSE Linux Enterprise Server + "opensuse" openSUSE + "amazon" Amazon Linux + "arch" Arch Linux + "cloudlinux" CloudLinux OS + "exherbo" Exherbo Linux + "gentoo" GenToo Linux + "ibm_powerkvm" IBM PowerKVM + "kvmibm" KVM for IBM z Systems + "linuxmint" Linux Mint + "mageia" Mageia + "mandriva" Mandriva Linux + "parallels" Parallels + "pidora" Pidora + "raspbian" Raspbian + "oracle" Oracle Linux (and Oracle Enterprise Linux) + "scientific" Scientific Linux + "slackware" Slackware + "xenserver" XenServer + "openbsd" OpenBSD + "netbsd" NetBSD + "freebsd" FreeBSD + ============== ========================================= + + If you have a need to get distros for reliable IDs added into this set, + or if you find that the :func:`distro.id` function returns a different + distro ID for one of the listed distros, please create an issue in the + `distro issue tracker`_. + + **Lookup hierarchy and transformations:** + + First, the ID is obtained from the following sources, in the specified + order. The first available and non-empty value is used: + + * the value of the "ID" attribute of the os-release file, + + * the value of the "Distributor ID" attribute returned by the lsb_release + command, + + * the first part of the file name of the distro release file, + + The so determined ID value then passes the following transformations, + before it is returned by this method: + + * it is translated to lower case, + + * blanks (which should not be there anyway) are translated to underscores, + + * a normalization of the ID is performed, based upon + `normalization tables`_. The purpose of this normalization is to ensure + that the ID is as reliable as possible, even across incompatible changes + in the OS distributions. A common reason for an incompatible change is + the addition of an os-release file, or the addition of the lsb_release + command, with ID values that differ from what was previously determined + from the distro release file name. + """ + return _distro.id() + + +def name(pretty=False): + """ + Return the name of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the name is returned without version or codename. + (e.g. "CentOS Linux") + + If *pretty* is true, the version and codename are appended. + (e.g. "CentOS Linux 7.1.1503 (Core)") + + **Lookup hierarchy:** + + The name is obtained from the following sources, in the specified order. + The first available and non-empty value is used: + + * If *pretty* is false: + + - the value of the "NAME" attribute of the os-release file, + + - the value of the "Distributor ID" attribute returned by the lsb_release + command, + + - the value of the "<name>" field of the distro release file. + + * If *pretty* is true: + + - the value of the "PRETTY_NAME" attribute of the os-release file, + + - the value of the "Description" attribute returned by the lsb_release + command, + + - the value of the "<name>" field of the distro release file, appended + with the value of the pretty version ("<version_id>" and "<codename>" + fields) of the distro release file, if available. + """ + return _distro.name(pretty) + + +def version(pretty=False, best=False): + """ + Return the version of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the version is returned without codename (e.g. + "7.0"). + + If *pretty* is true, the codename in parenthesis is appended, if the + codename is non-empty (e.g. "7.0 (Maipo)"). + + Some distributions provide version numbers with different precisions in + the different sources of distribution information. Examining the different + sources in a fixed priority order does not always yield the most precise + version (e.g. for Debian 8.2, or CentOS 7.1). + + The *best* parameter can be used to control the approach for the returned + version: + + If *best* is false, the first non-empty version number in priority order of + the examined sources is returned. + + If *best* is true, the most precise version number out of all examined + sources is returned. + + **Lookup hierarchy:** + + In all cases, the version number is obtained from the following sources. + If *best* is false, this order represents the priority order: + + * the value of the "VERSION_ID" attribute of the os-release file, + * the value of the "Release" attribute returned by the lsb_release + command, + * the version number parsed from the "<version_id>" field of the first line + of the distro release file, + * the version number parsed from the "PRETTY_NAME" attribute of the + os-release file, if it follows the format of the distro release files. + * the version number parsed from the "Description" attribute returned by + the lsb_release command, if it follows the format of the distro release + files. + """ + return _distro.version(pretty, best) + + +def version_parts(best=False): + """ + Return the version of the current OS distribution as a tuple + ``(major, minor, build_number)`` with items as follows: + + * ``major``: The result of :func:`distro.major_version`. + + * ``minor``: The result of :func:`distro.minor_version`. + + * ``build_number``: The result of :func:`distro.build_number`. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.version_parts(best) + + +def major_version(best=False): + """ + Return the major version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The major version is the first + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.major_version(best) + + +def minor_version(best=False): + """ + Return the minor version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The minor version is the second + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.minor_version(best) + + +def build_number(best=False): + """ + Return the build number of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The build number is the third part + of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.build_number(best) + + +def like(): + """ + Return a space-separated list of distro IDs of distributions that are + closely related to the current OS distribution in regards to packaging + and programming interfaces, for example distributions the current + distribution is a derivative from. + + **Lookup hierarchy:** + + This information item is only provided by the os-release file. + For details, see the description of the "ID_LIKE" attribute in the + `os-release man page + <http://www.freedesktop.org/software/systemd/man/os-release.html>`_. + """ + return _distro.like() + + +def codename(): + """ + Return the codename for the release of the current OS distribution, + as a string. + + If the distribution does not have a codename, an empty string is returned. + + Note that the returned codename is not always really a codename. For + example, openSUSE returns "x86_64". This function does not handle such + cases in any special way and just returns the string it finds, if any. + + **Lookup hierarchy:** + + * the codename within the "VERSION" attribute of the os-release file, if + provided, + + * the value of the "Codename" attribute returned by the lsb_release + command, + + * the value of the "<codename>" field of the distro release file. + """ + return _distro.codename() + + +def info(pretty=False, best=False): + """ + Return certain machine-readable information items about the current OS + distribution in a dictionary, as shown in the following example: + + .. sourcecode:: python + + { + 'id': 'rhel', + 'version': '7.0', + 'version_parts': { + 'major': '7', + 'minor': '0', + 'build_number': '' + }, + 'like': 'fedora', + 'codename': 'Maipo' + } + + The dictionary structure and keys are always the same, regardless of which + information items are available in the underlying data sources. The values + for the various keys are as follows: + + * ``id``: The result of :func:`distro.id`. + + * ``version``: The result of :func:`distro.version`. + + * ``version_parts -> major``: The result of :func:`distro.major_version`. + + * ``version_parts -> minor``: The result of :func:`distro.minor_version`. + + * ``version_parts -> build_number``: The result of + :func:`distro.build_number`. + + * ``like``: The result of :func:`distro.like`. + + * ``codename``: The result of :func:`distro.codename`. + + For a description of the *pretty* and *best* parameters, see the + :func:`distro.version` method. + """ + return _distro.info(pretty, best) + + +def os_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the os-release file data source of the current OS distribution. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_info() + + +def lsb_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the lsb_release command data source of the current OS distribution. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_info() + + +def distro_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_info() + + +def uname_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + """ + return _distro.uname_info() + + +def os_release_attr(attribute): + """ + Return a single named information item from the os-release file data source + of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_attr(attribute) + + +def lsb_release_attr(attribute): + """ + Return a single named information item from the lsb_release command output + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_attr(attribute) + + +def distro_release_attr(attribute): + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_attr(attribute) + + +def uname_attr(attribute): + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + """ + return _distro.uname_attr(attribute) + + +class cached_property(object): + """A version of @property which caches the value. On access, it calls the + underlying function and sets the value in `__dict__` so future accesses + will not re-call the property. + """ + def __init__(self, f): + self._fname = f.__name__ + self._f = f + + def __get__(self, obj, owner): + assert obj is not None, 'call {} on an instance'.format(self._fname) + ret = obj.__dict__[self._fname] = self._f(obj) + return ret + + +class LinuxDistribution(object): + """ + Provides information about a OS distribution. + + This package creates a private module-global instance of this class with + default initialization arguments, that is used by the + `consolidated accessor functions`_ and `single source accessor functions`_. + By using default initialization arguments, that module-global instance + returns data about the current OS distribution (i.e. the distro this + package runs on). + + Normally, it is not necessary to create additional instances of this class. + However, in situations where control is needed over the exact data sources + that are used, instances of this class can be created with a specific + distro release file, or a specific os-release file, or without invoking the + lsb_release command. + """ + + def __init__(self, + include_lsb=True, + os_release_file='', + distro_release_file='', + include_uname=True): + """ + The initialization method of this class gathers information from the + available data sources, and stores that in private instance attributes. + Subsequent access to the information items uses these private instance + attributes, so that the data sources are read only once. + + Parameters: + + * ``include_lsb`` (bool): Controls whether the + `lsb_release command output`_ is included as a data source. + + If the lsb_release command is not available in the program execution + path, the data source for the lsb_release command will be empty. + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is to be used as a data source. + + An empty string (the default) will cause the default path name to + be used (see `os-release file`_ for details). + + If the specified or defaulted os-release file does not exist, the + data source for the os-release file will be empty. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is to be used as a data source. + + An empty string (the default) will cause a default search algorithm + to be used (see `distro release file`_ for details). + + If the specified distro release file does not exist, or if no default + distro release file can be found, the data source for the distro + release file will be empty. + + * ``include_name`` (bool): Controls whether uname command output is + included as a data source. If the uname command is not available in + the program execution path the data source for the uname command will + be empty. + + Public instance attributes: + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. + This controls whether the lsb information will be loaded. + + * ``include_uname`` (bool): The result of the ``include_uname`` + parameter. This controls whether the uname information will + be loaded. + + Raises: + + * :py:exc:`IOError`: Some I/O issue with an os-release file or distro + release file. + + * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had + some issue (other than not being available in the program execution + path). + + * :py:exc:`UnicodeError`: A data source has unexpected characters or + uses an unexpected encoding. + """ + self.os_release_file = os_release_file or \ + os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME) + self.distro_release_file = distro_release_file or '' # updated later + self.include_lsb = include_lsb + self.include_uname = include_uname + + def __repr__(self): + """Return repr of all info + """ + return \ + "LinuxDistribution(" \ + "os_release_file={self.os_release_file!r}, " \ + "distro_release_file={self.distro_release_file!r}, " \ + "include_lsb={self.include_lsb!r}, " \ + "include_uname={self.include_uname!r}, " \ + "_os_release_info={self._os_release_info!r}, " \ + "_lsb_release_info={self._lsb_release_info!r}, " \ + "_distro_release_info={self._distro_release_info!r}, " \ + "_uname_info={self._uname_info!r})".format( + self=self) + + def linux_distribution(self, full_distribution_name=True): + """ + Return information about the OS distribution that is compatible + with Python's :func:`platform.linux_distribution`, supporting a subset + of its parameters. + + For details, see :func:`distro.linux_distribution`. + """ + return ( + self.name() if full_distribution_name else self.id(), + self.version(), + self.codename() + ) + + def id(self): + """Return the distro ID of the OS distribution, as a string. + + For details, see :func:`distro.id`. + """ + def normalize(distro_id, table): + distro_id = distro_id.lower().replace(' ', '_') + return table.get(distro_id, distro_id) + + distro_id = self.os_release_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_OS_ID) + + distro_id = self.lsb_release_attr('distributor_id') + if distro_id: + return normalize(distro_id, NORMALIZED_LSB_ID) + + distro_id = self.distro_release_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + distro_id = self.uname_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + return '' + + def name(self, pretty=False): + """ + Return the name of the OS distribution, as a string. + + For details, see :func:`distro.name`. + """ + name = self.os_release_attr('name') \ + or self.lsb_release_attr('distributor_id') \ + or self.distro_release_attr('name') \ + or self.uname_attr('name') + if pretty: + name = self.os_release_attr('pretty_name') \ + or self.lsb_release_attr('description') + if not name: + name = self.distro_release_attr('name') \ + or self.uname_attr('name') + version = self.version(pretty=True) + if version: + name = name + ' ' + version + return name or '' + + def version(self, pretty=False, best=False): + """ + Return the version of the OS distribution, as a string. + + For details, see :func:`distro.version`. + """ + versions = [ + self.os_release_attr('version_id'), + self.lsb_release_attr('release'), + self.distro_release_attr('version_id'), + self._parse_distro_release_content( + self.os_release_attr('pretty_name')).get('version_id', ''), + self._parse_distro_release_content( + self.lsb_release_attr('description')).get('version_id', ''), + self.uname_attr('release') + ] + version = '' + if best: + # This algorithm uses the last version in priority order that has + # the best precision. If the versions are not in conflict, that + # does not matter; otherwise, using the last one instead of the + # first one might be considered a surprise. + for v in versions: + if v.count(".") > version.count(".") or version == '': + version = v + else: + for v in versions: + if v != '': + version = v + break + if pretty and version and self.codename(): + version = u'{0} ({1})'.format(version, self.codename()) + return version + + def version_parts(self, best=False): + """ + Return the version of the OS distribution, as a tuple of version + numbers. + + For details, see :func:`distro.version_parts`. + """ + version_str = self.version(best=best) + if version_str: + version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?') + matches = version_regex.match(version_str) + if matches: + major, minor, build_number = matches.groups() + return major, minor or '', build_number or '' + return '', '', '' + + def major_version(self, best=False): + """ + Return the major version number of the current distribution. + + For details, see :func:`distro.major_version`. + """ + return self.version_parts(best)[0] + + def minor_version(self, best=False): + """ + Return the minor version number of the current distribution. + + For details, see :func:`distro.minor_version`. + """ + return self.version_parts(best)[1] + + def build_number(self, best=False): + """ + Return the build number of the current distribution. + + For details, see :func:`distro.build_number`. + """ + return self.version_parts(best)[2] + + def like(self): + """ + Return the IDs of distributions that are like the OS distribution. + + For details, see :func:`distro.like`. + """ + return self.os_release_attr('id_like') or '' + + def codename(self): + """ + Return the codename of the OS distribution. + + For details, see :func:`distro.codename`. + """ + return self.os_release_attr('codename') \ + or self.lsb_release_attr('codename') \ + or self.distro_release_attr('codename') \ + or '' + + def info(self, pretty=False, best=False): + """ + Return certain machine-readable information about the OS + distribution. + + For details, see :func:`distro.info`. + """ + return dict( + id=self.id(), + version=self.version(pretty, best), + version_parts=dict( + major=self.major_version(best), + minor=self.minor_version(best), + build_number=self.build_number(best) + ), + like=self.like(), + codename=self.codename(), + ) + + def os_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the os-release file data source of the OS distribution. + + For details, see :func:`distro.os_release_info`. + """ + return self._os_release_info + + def lsb_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the lsb_release command data source of the OS + distribution. + + For details, see :func:`distro.lsb_release_info`. + """ + return self._lsb_release_info + + def distro_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the distro release file data source of the OS + distribution. + + For details, see :func:`distro.distro_release_info`. + """ + return self._distro_release_info + + def uname_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the uname command data source of the OS distribution. + + For details, see :func:`distro.uname_info`. + """ + + def os_release_attr(self, attribute): + """ + Return a single named information item from the os-release file data + source of the OS distribution. + + For details, see :func:`distro.os_release_attr`. + """ + return self._os_release_info.get(attribute, '') + + def lsb_release_attr(self, attribute): + """ + Return a single named information item from the lsb_release command + output data source of the OS distribution. + + For details, see :func:`distro.lsb_release_attr`. + """ + return self._lsb_release_info.get(attribute, '') + + def distro_release_attr(self, attribute): + """ + Return a single named information item from the distro release file + data source of the OS distribution. + + For details, see :func:`distro.distro_release_attr`. + """ + return self._distro_release_info.get(attribute, '') + + def uname_attr(self, attribute): + """ + Return a single named information item from the uname command + output data source of the OS distribution. + + For details, see :func:`distro.uname_release_attr`. + """ + return self._uname_info.get(attribute, '') + + @cached_property + def _os_release_info(self): + """ + Get the information items from the specified os-release file. + + Returns: + A dictionary containing all information items. + """ + if os.path.isfile(self.os_release_file): + with open(self.os_release_file) as release_file: + return self._parse_os_release_content(release_file) + return {} + + @staticmethod + def _parse_os_release_content(lines): + """ + Parse the lines of an os-release file. + + Parameters: + + * lines: Iterable through the lines in the os-release file. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + lexer = shlex.shlex(lines, posix=True) + lexer.whitespace_split = True + + # The shlex module defines its `wordchars` variable using literals, + # making it dependent on the encoding of the Python source file. + # In Python 2.6 and 2.7, the shlex source file is encoded in + # 'iso-8859-1', and the `wordchars` variable is defined as a byte + # string. This causes a UnicodeDecodeError to be raised when the + # parsed content is a unicode object. The following fix resolves that + # (... but it should be fixed in shlex...): + if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes): + lexer.wordchars = lexer.wordchars.decode('iso-8859-1') + + tokens = list(lexer) + for token in tokens: + # At this point, all shell-like parsing has been done (i.e. + # comments processed, quotes and backslash escape sequences + # processed, multi-line values assembled, trailing newlines + # stripped, etc.), so the tokens are now either: + # * variable assignments: var=value + # * commands or their arguments (not allowed in os-release) + if '=' in token: + k, v = token.split('=', 1) + if isinstance(v, bytes): + v = v.decode('utf-8') + props[k.lower()] = v + if k == 'VERSION': + # this handles cases in which the codename is in + # the `(CODENAME)` (rhel, centos, fedora) format + # or in the `, CODENAME` format (Ubuntu). + codename = re.search(r'(\(\D+\))|,(\s+)?\D+', v) + if codename: + codename = codename.group() + codename = codename.strip('()') + codename = codename.strip(',') + codename = codename.strip() + # codename appears within paranthese. + props['codename'] = codename + else: + props['codename'] = '' + else: + # Ignore any tokens that are not variable assignments + pass + return props + + @cached_property + def _lsb_release_info(self): + """ + Get the information items from the lsb_release command output. + + Returns: + A dictionary containing all information items. + """ + if not self.include_lsb: + return {} + with open(os.devnull, 'w') as devnull: + try: + cmd = ('lsb_release', '-a') + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: # Command not found + return {} + content = stdout.decode(sys.getfilesystemencoding()).splitlines() + return self._parse_lsb_release_content(content) + + @staticmethod + def _parse_lsb_release_content(lines): + """ + Parse the output of the lsb_release command. + + Parameters: + + * lines: Iterable through the lines of the lsb_release output. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + for line in lines: + kv = line.strip('\n').split(':', 1) + if len(kv) != 2: + # Ignore lines without colon. + continue + k, v = kv + props.update({k.replace(' ', '_').lower(): v.strip()}) + return props + + @cached_property + def _uname_info(self): + with open(os.devnull, 'w') as devnull: + try: + cmd = ('uname', '-rs') + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: + return {} + content = stdout.decode(sys.getfilesystemencoding()).splitlines() + return self._parse_uname_content(content) + + @staticmethod + def _parse_uname_content(lines): + props = {} + match = re.search(r'^([^\s]+)\s+([\d\.]+)', lines[0].strip()) + if match: + name, version = match.groups() + + # This is to prevent the Linux kernel version from + # appearing as the 'best' version on otherwise + # identifiable distributions. + if name == 'Linux': + return {} + props['id'] = name.lower() + props['name'] = name + props['release'] = version + return props + + @cached_property + def _distro_release_info(self): + """ + Get the information items from the specified distro release file. + + Returns: + A dictionary containing all information items. + """ + if self.distro_release_file: + # If it was specified, we use it and parse what we can, even if + # its file name or content does not match the expected pattern. + distro_info = self._parse_distro_release_file( + self.distro_release_file) + basename = os.path.basename(self.distro_release_file) + # The file name pattern for user-specified distro release files + # is somewhat more tolerant (compared to when searching for the + # file), because we want to use what was specified as best as + # possible. + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match: + distro_info['id'] = match.group(1) + return distro_info + else: + try: + basenames = os.listdir(_UNIXCONFDIR) + # We sort for repeatability in cases where there are multiple + # distro specific files; e.g. CentOS, Oracle, Enterprise all + # containing `redhat-release` on top of their own. + basenames.sort() + except OSError: + # This may occur when /etc is not readable but we can't be + # sure about the *-release files. Check common entries of + # /etc for information. If they turn out to not be there the + # error is handled in `_parse_distro_release_file()`. + basenames = ['SuSE-release', + 'arch-release', + 'base-release', + 'centos-release', + 'fedora-release', + 'gentoo-release', + 'mageia-release', + 'mandrake-release', + 'mandriva-release', + 'mandrivalinux-release', + 'manjaro-release', + 'oracle-release', + 'redhat-release', + 'sl-release', + 'slackware-version'] + for basename in basenames: + if basename in _DISTRO_RELEASE_IGNORE_BASENAMES: + continue + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match: + filepath = os.path.join(_UNIXCONFDIR, basename) + distro_info = self._parse_distro_release_file(filepath) + if 'name' in distro_info: + # The name is always present if the pattern matches + self.distro_release_file = filepath + distro_info['id'] = match.group(1) + return distro_info + return {} + + def _parse_distro_release_file(self, filepath): + """ + Parse a distro release file. + + Parameters: + + * filepath: Path name of the distro release file. + + Returns: + A dictionary containing all information items. + """ + try: + with open(filepath) as fp: + # Only parse the first line. For instance, on SLES there + # are multiple lines. We don't want them... + return self._parse_distro_release_content(fp.readline()) + except (OSError, IOError): + # Ignore not being able to read a specific, seemingly version + # related file. + # See https://github.com/nir0s/distro/issues/162 + return {} + + @staticmethod + def _parse_distro_release_content(line): + """ + Parse a line from a distro release file. + + Parameters: + * line: Line from the distro release file. Must be a unicode string + or a UTF-8 encoded byte string. + + Returns: + A dictionary containing all information items. + """ + if isinstance(line, bytes): + line = line.decode('utf-8') + matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match( + line.strip()[::-1]) + distro_info = {} + if matches: + # regexp ensures non-None + distro_info['name'] = matches.group(3)[::-1] + if matches.group(2): + distro_info['version_id'] = matches.group(2)[::-1] + if matches.group(1): + distro_info['codename'] = matches.group(1)[::-1] + elif line: + distro_info['name'] = line.strip() + return distro_info + + +_distro = LinuxDistribution() + + +def main(): + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(logging.StreamHandler(sys.stdout)) + + parser = argparse.ArgumentParser(description="OS distro info tool") + parser.add_argument( + '--json', + '-j', + help="Output in machine readable format", + action="store_true") + args = parser.parse_args() + + if args.json: + logger.info(json.dumps(info(), indent=4, sort_keys=True)) + else: + logger.info('Name: %s', name(pretty=True)) + distribution_version = version(pretty=True) + logger.info('Version: %s', distribution_version) + distribution_codename = codename() + logger.info('Codename: %s', distribution_codename) + + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/__init__.py new file mode 100644 index 0000000..0491234 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/__init__.py @@ -0,0 +1,35 @@ +""" +HTML parsing library based on the `WHATWG HTML specification +<https://whatwg.org/html>`_. The parser is designed to be compatible with +existing HTML found in the wild and implements well-defined error recovery that +is largely compatible with modern desktop web browsers. + +Example usage:: + + from pip._vendor import html5lib + with open("my_document.html", "rb") as f: + tree = html5lib.parse(f) + +For convenience, this module re-exports the following names: + +* :func:`~.html5parser.parse` +* :func:`~.html5parser.parseFragment` +* :class:`~.html5parser.HTMLParser` +* :func:`~.treebuilders.getTreeBuilder` +* :func:`~.treewalkers.getTreeWalker` +* :func:`~.serializer.serialize` +""" + +from __future__ import absolute_import, division, unicode_literals + +from .html5parser import HTMLParser, parse, parseFragment +from .treebuilders import getTreeBuilder +from .treewalkers import getTreeWalker +from .serializer import serialize + +__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", + "getTreeWalker", "serialize"] + +# this has to be at the top level, see how setup.py parses this +#: Distribution version number. +__version__ = "1.0.1" diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_ihatexml.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_ihatexml.py new file mode 100644 index 0000000..4c77717 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_ihatexml.py @@ -0,0 +1,288 @@ +from __future__ import absolute_import, division, unicode_literals + +import re +import warnings + +from .constants import DataLossWarning + +baseChar = """ +[#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | +[#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] | +[#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] | +[#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 | +[#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] | +[#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] | +[#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] | +[#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] | +[#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 | +[#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] | +[#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] | +[#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D | +[#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] | +[#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] | +[#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] | +[#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] | +[#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] | +[#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] | +[#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 | +[#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] | +[#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] | +[#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] | +[#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] | +[#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] | +[#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] | +[#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] | +[#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] | +[#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] | +[#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] | +[#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A | +#x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 | +#x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] | +#x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] | +[#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] | +[#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C | +#x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 | +[#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] | +[#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] | +[#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 | +[#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] | +[#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B | +#x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE | +[#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] | +[#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 | +[#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] | +[#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]""" + +ideographic = """[#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]""" + +combiningCharacter = """ +[#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] | +[#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 | +[#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] | +[#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] | +#x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] | +[#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] | +[#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 | +#x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] | +[#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC | +[#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] | +#x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] | +[#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] | +[#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] | +[#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] | +[#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] | +[#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] | +#x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 | +[#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] | +#x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] | +[#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] | +[#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] | +#x3099 | #x309A""" + +digit = """ +[#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] | +[#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] | +[#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] | +[#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]""" + +extender = """ +#x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46 | #x0EC6 | #x3005 | +#[#x3031-#x3035] | [#x309D-#x309E] | [#x30FC-#x30FE]""" + +letter = " | ".join([baseChar, ideographic]) + +# Without the +name = " | ".join([letter, digit, ".", "-", "_", combiningCharacter, + extender]) +nameFirst = " | ".join([letter, "_"]) + +reChar = re.compile(r"#x([\d|A-F]{4,4})") +reCharRange = re.compile(r"\[#x([\d|A-F]{4,4})-#x([\d|A-F]{4,4})\]") + + +def charStringToList(chars): + charRanges = [item.strip() for item in chars.split(" | ")] + rv = [] + for item in charRanges: + foundMatch = False + for regexp in (reChar, reCharRange): + match = regexp.match(item) + if match is not None: + rv.append([hexToInt(item) for item in match.groups()]) + if len(rv[-1]) == 1: + rv[-1] = rv[-1] * 2 + foundMatch = True + break + if not foundMatch: + assert len(item) == 1 + + rv.append([ord(item)] * 2) + rv = normaliseCharList(rv) + return rv + + +def normaliseCharList(charList): + charList = sorted(charList) + for item in charList: + assert item[1] >= item[0] + rv = [] + i = 0 + while i < len(charList): + j = 1 + rv.append(charList[i]) + while i + j < len(charList) and charList[i + j][0] <= rv[-1][1] + 1: + rv[-1][1] = charList[i + j][1] + j += 1 + i += j + return rv + +# We don't really support characters above the BMP :( +max_unicode = int("FFFF", 16) + + +def missingRanges(charList): + rv = [] + if charList[0] != 0: + rv.append([0, charList[0][0] - 1]) + for i, item in enumerate(charList[:-1]): + rv.append([item[1] + 1, charList[i + 1][0] - 1]) + if charList[-1][1] != max_unicode: + rv.append([charList[-1][1] + 1, max_unicode]) + return rv + + +def listToRegexpStr(charList): + rv = [] + for item in charList: + if item[0] == item[1]: + rv.append(escapeRegexp(chr(item[0]))) + else: + rv.append(escapeRegexp(chr(item[0])) + "-" + + escapeRegexp(chr(item[1]))) + return "[%s]" % "".join(rv) + + +def hexToInt(hex_str): + return int(hex_str, 16) + + +def escapeRegexp(string): + specialCharacters = (".", "^", "$", "*", "+", "?", "{", "}", + "[", "]", "|", "(", ")", "-") + for char in specialCharacters: + string = string.replace(char, "\\" + char) + + return string + +# output from the above +nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u02cf\u02d2-\u02ff\u0346-\u035f\u0362-\u0385\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482\u0487-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u0590\u05a2\u05ba\u05be\u05c0\u05c3\u05c5-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u063f\u0653-\u065f\u066a-\u066f\u06b8-\u06b9\u06bf\u06cf\u06d4\u06e9\u06ee-\u06ef\u06fa-\u0900\u0904\u093a-\u093b\u094e-\u0950\u0955-\u0957\u0964-\u0965\u0970-\u0980\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09bd\u09c5-\u09c6\u09c9-\u09ca\u09ce-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09f2-\u0a01\u0a03-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a58\u0a5d\u0a5f-\u0a65\u0a75-\u0a80\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0adf\u0ae1-\u0ae5\u0af0-\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3b\u0b44-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b62-\u0b65\u0b70-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bd6\u0bd8-\u0be6\u0bf0-\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c3d\u0c45\u0c49\u0c4e-\u0c54\u0c57-\u0c5f\u0c62-\u0c65\u0c70-\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbd\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce2-\u0ce5\u0cf0-\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d3d\u0d44-\u0d45\u0d49\u0d4e-\u0d56\u0d58-\u0d5f\u0d62-\u0d65\u0d70-\u0e00\u0e2f\u0e3b-\u0e3f\u0e4f\u0e5a-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0f17\u0f1a-\u0f1f\u0f2a-\u0f34\u0f36\u0f38\u0f3a-\u0f3d\u0f48\u0f6a-\u0f70\u0f85\u0f8c-\u0f8f\u0f96\u0f98\u0fae-\u0fb0\u0fb8\u0fba-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u20cf\u20dd-\u20e0\u20e2-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3004\u3006\u3008-\u3020\u3030\u3036-\u3040\u3095-\u3098\u309b-\u309c\u309f-\u30a0\u30fb\u30ff-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa + +nonXmlNameFirstBMPRegexp = re.compile('[\x00-@\\[-\\^`\\{-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u0385\u0387\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u0640\u064b-\u0670\u06b8-\u06b9\u06bf\u06cf\u06d4\u06d6-\u06e4\u06e7-\u0904\u093a-\u093c\u093e-\u0957\u0962-\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09db\u09de\u09e2-\u09ef\u09f2-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a58\u0a5d\u0a5f-\u0a71\u0a75-\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abc\u0abe-\u0adf\u0ae1-\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3c\u0b3e-\u0b5b\u0b5e\u0b62-\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c5f\u0c62-\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cdd\u0cdf\u0ce2-\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d5f\u0d62-\u0e00\u0e2f\u0e31\u0e34-\u0e3f\u0e46-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eb1\u0eb4-\u0ebc\u0ebe-\u0ebf\u0ec5-\u0f3f\u0f48\u0f6a-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3006\u3008-\u3020\u302a-\u3040\u3095-\u30a0\u30fb-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa + +# Simpler things +nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\\-'()+,./:=?;!*#@$_%]") + + +class InfosetFilter(object): + replacementRegexp = re.compile(r"U[\dA-F]{5,5}") + + def __init__(self, + dropXmlnsLocalName=False, + dropXmlnsAttrNs=False, + preventDoubleDashComments=False, + preventDashAtCommentEnd=False, + replaceFormFeedCharacters=True, + preventSingleQuotePubid=False): + + self.dropXmlnsLocalName = dropXmlnsLocalName + self.dropXmlnsAttrNs = dropXmlnsAttrNs + + self.preventDoubleDashComments = preventDoubleDashComments + self.preventDashAtCommentEnd = preventDashAtCommentEnd + + self.replaceFormFeedCharacters = replaceFormFeedCharacters + + self.preventSingleQuotePubid = preventSingleQuotePubid + + self.replaceCache = {} + + def coerceAttribute(self, name, namespace=None): + if self.dropXmlnsLocalName and name.startswith("xmlns:"): + warnings.warn("Attributes cannot begin with xmlns", DataLossWarning) + return None + elif (self.dropXmlnsAttrNs and + namespace == "http://www.w3.org/2000/xmlns/"): + warnings.warn("Attributes cannot be in the xml namespace", DataLossWarning) + return None + else: + return self.toXmlName(name) + + def coerceElement(self, name): + return self.toXmlName(name) + + def coerceComment(self, data): + if self.preventDoubleDashComments: + while "--" in data: + warnings.warn("Comments cannot contain adjacent dashes", DataLossWarning) + data = data.replace("--", "- -") + if data.endswith("-"): + warnings.warn("Comments cannot end in a dash", DataLossWarning) + data += " " + return data + + def coerceCharacters(self, data): + if self.replaceFormFeedCharacters: + for _ in range(data.count("\x0C")): + warnings.warn("Text cannot contain U+000C", DataLossWarning) + data = data.replace("\x0C", " ") + # Other non-xml characters + return data + + def coercePubid(self, data): + dataOutput = data + for char in nonPubidCharRegexp.findall(data): + warnings.warn("Coercing non-XML pubid", DataLossWarning) + replacement = self.getReplacementCharacter(char) + dataOutput = dataOutput.replace(char, replacement) + if self.preventSingleQuotePubid and dataOutput.find("'") >= 0: + warnings.warn("Pubid cannot contain single quote", DataLossWarning) + dataOutput = dataOutput.replace("'", self.getReplacementCharacter("'")) + return dataOutput + + def toXmlName(self, name): + nameFirst = name[0] + nameRest = name[1:] + m = nonXmlNameFirstBMPRegexp.match(nameFirst) + if m: + warnings.warn("Coercing non-XML name", DataLossWarning) + nameFirstOutput = self.getReplacementCharacter(nameFirst) + else: + nameFirstOutput = nameFirst + + nameRestOutput = nameRest + replaceChars = set(nonXmlNameBMPRegexp.findall(nameRest)) + for char in replaceChars: + warnings.warn("Coercing non-XML name", DataLossWarning) + replacement = self.getReplacementCharacter(char) + nameRestOutput = nameRestOutput.replace(char, replacement) + return nameFirstOutput + nameRestOutput + + def getReplacementCharacter(self, char): + if char in self.replaceCache: + replacement = self.replaceCache[char] + else: + replacement = self.escapeChar(char) + return replacement + + def fromXmlName(self, name): + for item in set(self.replacementRegexp.findall(name)): + name = name.replace(item, self.unescapeChar(item)) + return name + + def escapeChar(self, char): + replacement = "U%05X" % ord(char) + self.replaceCache[char] = replacement + return replacement + + def unescapeChar(self, charcode): + return chr(int(charcode[1:], 16)) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py new file mode 100644 index 0000000..a65e55f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py @@ -0,0 +1,923 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import text_type, binary_type +from pip._vendor.six.moves import http_client, urllib + +import codecs +import re + +from pip._vendor import webencodings + +from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase +from .constants import _ReparseException +from . import _utils + +from io import StringIO + +try: + from io import BytesIO +except ImportError: + BytesIO = StringIO + +# Non-unicode versions of constants for use in the pre-parser +spaceCharactersBytes = frozenset([item.encode("ascii") for item in spaceCharacters]) +asciiLettersBytes = frozenset([item.encode("ascii") for item in asciiLetters]) +asciiUppercaseBytes = frozenset([item.encode("ascii") for item in asciiUppercase]) +spacesAngleBrackets = spaceCharactersBytes | frozenset([b">", b"<"]) + + +invalid_unicode_no_surrogate = "[\u0001-\u0008\u000B\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\uFFFE\uFFFF\U0001FFFE\U0001FFFF\U0002FFFE\U0002FFFF\U0003FFFE\U0003FFFF\U0004FFFE\U0004FFFF\U0005FFFE\U0005FFFF\U0006FFFE\U0006FFFF\U0007FFFE\U0007FFFF\U0008FFFE\U0008FFFF\U0009FFFE\U0009FFFF\U000AFFFE\U000AFFFF\U000BFFFE\U000BFFFF\U000CFFFE\U000CFFFF\U000DFFFE\U000DFFFF\U000EFFFE\U000EFFFF\U000FFFFE\U000FFFFF\U0010FFFE\U0010FFFF]" # noqa + +if _utils.supports_lone_surrogates: + # Use one extra step of indirection and create surrogates with + # eval. Not using this indirection would introduce an illegal + # unicode literal on platforms not supporting such lone + # surrogates. + assert invalid_unicode_no_surrogate[-1] == "]" and invalid_unicode_no_surrogate.count("]") == 1 + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate[:-1] + + eval('"\\uD800-\\uDFFF"') + # pylint:disable=eval-used + "]") +else: + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate) + +non_bmp_invalid_codepoints = set([0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, + 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, + 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, + 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, + 0x10FFFE, 0x10FFFF]) + +ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005C\u005B-\u0060\u007B-\u007E]") + +# Cache for charsUntil() +charsUntilRegEx = {} + + +class BufferedStream(object): + """Buffering for streams that do not have buffering of their own + + The buffer is implemented as a list of chunks on the assumption that + joining many strings will be slow since it is O(n**2) + """ + + def __init__(self, stream): + self.stream = stream + self.buffer = [] + self.position = [-1, 0] # chunk number, offset + + def tell(self): + pos = 0 + for chunk in self.buffer[:self.position[0]]: + pos += len(chunk) + pos += self.position[1] + return pos + + def seek(self, pos): + assert pos <= self._bufferedBytes() + offset = pos + i = 0 + while len(self.buffer[i]) < offset: + offset -= len(self.buffer[i]) + i += 1 + self.position = [i, offset] + + def read(self, bytes): + if not self.buffer: + return self._readStream(bytes) + elif (self.position[0] == len(self.buffer) and + self.position[1] == len(self.buffer[-1])): + return self._readStream(bytes) + else: + return self._readFromBuffer(bytes) + + def _bufferedBytes(self): + return sum([len(item) for item in self.buffer]) + + def _readStream(self, bytes): + data = self.stream.read(bytes) + self.buffer.append(data) + self.position[0] += 1 + self.position[1] = len(data) + return data + + def _readFromBuffer(self, bytes): + remainingBytes = bytes + rv = [] + bufferIndex = self.position[0] + bufferOffset = self.position[1] + while bufferIndex < len(self.buffer) and remainingBytes != 0: + assert remainingBytes > 0 + bufferedData = self.buffer[bufferIndex] + + if remainingBytes <= len(bufferedData) - bufferOffset: + bytesToRead = remainingBytes + self.position = [bufferIndex, bufferOffset + bytesToRead] + else: + bytesToRead = len(bufferedData) - bufferOffset + self.position = [bufferIndex, len(bufferedData)] + bufferIndex += 1 + rv.append(bufferedData[bufferOffset:bufferOffset + bytesToRead]) + remainingBytes -= bytesToRead + + bufferOffset = 0 + + if remainingBytes: + rv.append(self._readStream(remainingBytes)) + + return b"".join(rv) + + +def HTMLInputStream(source, **kwargs): + # Work around Python bug #20007: read(0) closes the connection. + # http://bugs.python.org/issue20007 + if (isinstance(source, http_client.HTTPResponse) or + # Also check for addinfourl wrapping HTTPResponse + (isinstance(source, urllib.response.addbase) and + isinstance(source.fp, http_client.HTTPResponse))): + isUnicode = False + elif hasattr(source, "read"): + isUnicode = isinstance(source.read(0), text_type) + else: + isUnicode = isinstance(source, text_type) + + if isUnicode: + encodings = [x for x in kwargs if x.endswith("_encoding")] + if encodings: + raise TypeError("Cannot set an encoding with a unicode input, set %r" % encodings) + + return HTMLUnicodeInputStream(source, **kwargs) + else: + return HTMLBinaryInputStream(source, **kwargs) + + +class HTMLUnicodeInputStream(object): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + _defaultChunkSize = 10240 + + def __init__(self, source): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + """ + + if not _utils.supports_lone_surrogates: + # Such platforms will have already checked for such + # surrogate errors, so no need to do this checking. + self.reportCharacterErrors = None + elif len("\U0010FFFF") == 1: + self.reportCharacterErrors = self.characterErrorsUCS4 + else: + self.reportCharacterErrors = self.characterErrorsUCS2 + + # List of where new lines occur + self.newLines = [0] + + self.charEncoding = (lookupEncoding("utf-8"), "certain") + self.dataStream = self.openStream(source) + + self.reset() + + def reset(self): + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + self.errors = [] + + # number of (complete) lines in previous chunks + self.prevNumLines = 0 + # number of columns in the last line of the previous chunk + self.prevNumCols = 0 + + # Deal with CR LF and surrogates split over chunk boundaries + self._bufferedCharacter = None + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = StringIO(source) + + return stream + + def _position(self, offset): + chunk = self.chunk + nLines = chunk.count('\n', 0, offset) + positionLine = self.prevNumLines + nLines + lastLinePos = chunk.rfind('\n', 0, offset) + if lastLinePos == -1: + positionColumn = self.prevNumCols + offset + else: + positionColumn = offset - (lastLinePos + 1) + return (positionLine, positionColumn) + + def position(self): + """Returns (line, col) of the current position in the stream.""" + line, col = self._position(self.chunkOffset) + return (line + 1, col) + + def char(self): + """ Read one character from the stream or queue if available. Return + EOF when EOF is reached. + """ + # Read a new chunk from the input stream if necessary + if self.chunkOffset >= self.chunkSize: + if not self.readChunk(): + return EOF + + chunkOffset = self.chunkOffset + char = self.chunk[chunkOffset] + self.chunkOffset = chunkOffset + 1 + + return char + + def readChunk(self, chunkSize=None): + if chunkSize is None: + chunkSize = self._defaultChunkSize + + self.prevNumLines, self.prevNumCols = self._position(self.chunkSize) + + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + + data = self.dataStream.read(chunkSize) + + # Deal with CR LF and surrogates broken across chunks + if self._bufferedCharacter: + data = self._bufferedCharacter + data + self._bufferedCharacter = None + elif not data: + # We have no more data, bye-bye stream + return False + + if len(data) > 1: + lastv = ord(data[-1]) + if lastv == 0x0D or 0xD800 <= lastv <= 0xDBFF: + self._bufferedCharacter = data[-1] + data = data[:-1] + + if self.reportCharacterErrors: + self.reportCharacterErrors(data) + + # Replace invalid characters + data = data.replace("\r\n", "\n") + data = data.replace("\r", "\n") + + self.chunk = data + self.chunkSize = len(data) + + return True + + def characterErrorsUCS4(self, data): + for _ in range(len(invalid_unicode_re.findall(data))): + self.errors.append("invalid-codepoint") + + def characterErrorsUCS2(self, data): + # Someone picked the wrong compile option + # You lose + skip = False + for match in invalid_unicode_re.finditer(data): + if skip: + continue + codepoint = ord(match.group()) + pos = match.start() + # Pretty sure there should be endianness issues here + if _utils.isSurrogatePair(data[pos:pos + 2]): + # We have a surrogate pair! + char_val = _utils.surrogatePairToCodepoint(data[pos:pos + 2]) + if char_val in non_bmp_invalid_codepoints: + self.errors.append("invalid-codepoint") + skip = True + elif (codepoint >= 0xD800 and codepoint <= 0xDFFF and + pos == len(data) - 1): + self.errors.append("invalid-codepoint") + else: + skip = False + self.errors.append("invalid-codepoint") + + def charsUntil(self, characters, opposite=False): + """ Returns a string of characters from the stream up to but not + including any character in 'characters' or EOF. 'characters' must be + a container that supports the 'in' method and iteration over its + characters. + """ + + # Use a cache of regexps to find the required characters + try: + chars = charsUntilRegEx[(characters, opposite)] + except KeyError: + if __debug__: + for c in characters: + assert(ord(c) < 128) + regex = "".join(["\\x%02x" % ord(c) for c in characters]) + if not opposite: + regex = "^%s" % regex + chars = charsUntilRegEx[(characters, opposite)] = re.compile("[%s]+" % regex) + + rv = [] + + while True: + # Find the longest matching prefix + m = chars.match(self.chunk, self.chunkOffset) + if m is None: + # If nothing matched, and it wasn't because we ran out of chunk, + # then stop + if self.chunkOffset != self.chunkSize: + break + else: + end = m.end() + # If not the whole chunk matched, return everything + # up to the part that didn't match + if end != self.chunkSize: + rv.append(self.chunk[self.chunkOffset:end]) + self.chunkOffset = end + break + # If the whole remainder of the chunk matched, + # use it all and read the next chunk + rv.append(self.chunk[self.chunkOffset:]) + if not self.readChunk(): + # Reached EOF + break + + r = "".join(rv) + return r + + def unget(self, char): + # Only one character is allowed to be ungotten at once - it must + # be consumed again before any further call to unget + if char is not None: + if self.chunkOffset == 0: + # unget is called quite rarely, so it's a good idea to do + # more work here if it saves a bit of work in the frequently + # called char and charsUntil. + # So, just prepend the ungotten character onto the current + # chunk: + self.chunk = char + self.chunk + self.chunkSize += 1 + else: + self.chunkOffset -= 1 + assert self.chunk[self.chunkOffset] == char + + +class HTMLBinaryInputStream(HTMLUnicodeInputStream): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + def __init__(self, source, override_encoding=None, transport_encoding=None, + same_origin_parent_encoding=None, likely_encoding=None, + default_encoding="windows-1252", useChardet=True): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + """ + # Raw Stream - for unicode objects this will encode to utf-8 and set + # self.charEncoding as appropriate + self.rawStream = self.openStream(source) + + HTMLUnicodeInputStream.__init__(self, self.rawStream) + + # Encoding Information + # Number of bytes to use when looking for a meta element with + # encoding information + self.numBytesMeta = 1024 + # Number of bytes to use when using detecting encoding using chardet + self.numBytesChardet = 100 + # Things from args + self.override_encoding = override_encoding + self.transport_encoding = transport_encoding + self.same_origin_parent_encoding = same_origin_parent_encoding + self.likely_encoding = likely_encoding + self.default_encoding = default_encoding + + # Determine encoding + self.charEncoding = self.determineEncoding(useChardet) + assert self.charEncoding[0] is not None + + # Call superclass + self.reset() + + def reset(self): + self.dataStream = self.charEncoding[0].codec_info.streamreader(self.rawStream, 'replace') + HTMLUnicodeInputStream.reset(self) + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = BytesIO(source) + + try: + stream.seek(stream.tell()) + except: # pylint:disable=bare-except + stream = BufferedStream(stream) + + return stream + + def determineEncoding(self, chardet=True): + # BOMs take precedence over everything + # This will also read past the BOM if present + charEncoding = self.detectBOM(), "certain" + if charEncoding[0] is not None: + return charEncoding + + # If we've been overriden, we've been overriden + charEncoding = lookupEncoding(self.override_encoding), "certain" + if charEncoding[0] is not None: + return charEncoding + + # Now check the transport layer + charEncoding = lookupEncoding(self.transport_encoding), "certain" + if charEncoding[0] is not None: + return charEncoding + + # Look for meta elements with encoding information + charEncoding = self.detectEncodingMeta(), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Parent document encoding + charEncoding = lookupEncoding(self.same_origin_parent_encoding), "tentative" + if charEncoding[0] is not None and not charEncoding[0].name.startswith("utf-16"): + return charEncoding + + # "likely" encoding + charEncoding = lookupEncoding(self.likely_encoding), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Guess with chardet, if available + if chardet: + try: + from pip._vendor.chardet.universaldetector import UniversalDetector + except ImportError: + pass + else: + buffers = [] + detector = UniversalDetector() + while not detector.done: + buffer = self.rawStream.read(self.numBytesChardet) + assert isinstance(buffer, bytes) + if not buffer: + break + buffers.append(buffer) + detector.feed(buffer) + detector.close() + encoding = lookupEncoding(detector.result['encoding']) + self.rawStream.seek(0) + if encoding is not None: + return encoding, "tentative" + + # Try the default encoding + charEncoding = lookupEncoding(self.default_encoding), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Fallback to html5lib's default if even that hasn't worked + return lookupEncoding("windows-1252"), "tentative" + + def changeEncoding(self, newEncoding): + assert self.charEncoding[1] != "certain" + newEncoding = lookupEncoding(newEncoding) + if newEncoding is None: + return + if newEncoding.name in ("utf-16be", "utf-16le"): + newEncoding = lookupEncoding("utf-8") + assert newEncoding is not None + elif newEncoding == self.charEncoding[0]: + self.charEncoding = (self.charEncoding[0], "certain") + else: + self.rawStream.seek(0) + self.charEncoding = (newEncoding, "certain") + self.reset() + raise _ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding)) + + def detectBOM(self): + """Attempts to detect at BOM at the start of the stream. If + an encoding can be determined from the BOM return the name of the + encoding otherwise return None""" + bomDict = { + codecs.BOM_UTF8: 'utf-8', + codecs.BOM_UTF16_LE: 'utf-16le', codecs.BOM_UTF16_BE: 'utf-16be', + codecs.BOM_UTF32_LE: 'utf-32le', codecs.BOM_UTF32_BE: 'utf-32be' + } + + # Go to beginning of file and read in 4 bytes + string = self.rawStream.read(4) + assert isinstance(string, bytes) + + # Try detecting the BOM using bytes from the string + encoding = bomDict.get(string[:3]) # UTF-8 + seek = 3 + if not encoding: + # Need to detect UTF-32 before UTF-16 + encoding = bomDict.get(string) # UTF-32 + seek = 4 + if not encoding: + encoding = bomDict.get(string[:2]) # UTF-16 + seek = 2 + + # Set the read position past the BOM if one was found, otherwise + # set it to the start of the stream + if encoding: + self.rawStream.seek(seek) + return lookupEncoding(encoding) + else: + self.rawStream.seek(0) + return None + + def detectEncodingMeta(self): + """Report the encoding declared by the meta element + """ + buffer = self.rawStream.read(self.numBytesMeta) + assert isinstance(buffer, bytes) + parser = EncodingParser(buffer) + self.rawStream.seek(0) + encoding = parser.getEncoding() + + if encoding is not None and encoding.name in ("utf-16be", "utf-16le"): + encoding = lookupEncoding("utf-8") + + return encoding + + +class EncodingBytes(bytes): + """String-like object with an associated position and various extra methods + If the position is ever greater than the string length then an exception is + raised""" + def __new__(self, value): + assert isinstance(value, bytes) + return bytes.__new__(self, value.lower()) + + def __init__(self, value): + # pylint:disable=unused-argument + self._position = -1 + + def __iter__(self): + return self + + def __next__(self): + p = self._position = self._position + 1 + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + return self[p:p + 1] + + def next(self): + # Py2 compat + return self.__next__() + + def previous(self): + p = self._position + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + self._position = p = p - 1 + return self[p:p + 1] + + def setPosition(self, position): + if self._position >= len(self): + raise StopIteration + self._position = position + + def getPosition(self): + if self._position >= len(self): + raise StopIteration + if self._position >= 0: + return self._position + else: + return None + + position = property(getPosition, setPosition) + + def getCurrentByte(self): + return self[self.position:self.position + 1] + + currentByte = property(getCurrentByte) + + def skip(self, chars=spaceCharactersBytes): + """Skip past a list of characters""" + p = self.position # use property for the error-checking + while p < len(self): + c = self[p:p + 1] + if c not in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def skipUntil(self, chars): + p = self.position + while p < len(self): + c = self[p:p + 1] + if c in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def matchBytes(self, bytes): + """Look for a sequence of bytes at the start of a string. If the bytes + are found return True and advance the position to the byte after the + match. Otherwise return False and leave the position alone""" + p = self.position + data = self[p:p + len(bytes)] + rv = data.startswith(bytes) + if rv: + self.position += len(bytes) + return rv + + def jumpTo(self, bytes): + """Look for the next sequence of bytes matching a given sequence. If + a match is found advance the position to the last byte of the match""" + newPosition = self[self.position:].find(bytes) + if newPosition > -1: + # XXX: This is ugly, but I can't see a nicer way to fix this. + if self._position == -1: + self._position = 0 + self._position += (newPosition + len(bytes) - 1) + return True + else: + raise StopIteration + + +class EncodingParser(object): + """Mini parser for detecting character encoding from meta elements""" + + def __init__(self, data): + """string - the data to work on for encoding detection""" + self.data = EncodingBytes(data) + self.encoding = None + + def getEncoding(self): + methodDispatch = ( + (b"<!--", self.handleComment), + (b"<meta", self.handleMeta), + (b"</", self.handlePossibleEndTag), + (b"<!", self.handleOther), + (b"<?", self.handleOther), + (b"<", self.handlePossibleStartTag)) + for _ in self.data: + keepParsing = True + for key, method in methodDispatch: + if self.data.matchBytes(key): + try: + keepParsing = method() + break + except StopIteration: + keepParsing = False + break + if not keepParsing: + break + + return self.encoding + + def handleComment(self): + """Skip over comments""" + return self.data.jumpTo(b"-->") + + def handleMeta(self): + if self.data.currentByte not in spaceCharactersBytes: + # if we have <meta not followed by a space so just keep going + return True + # We have a valid meta element we want to search for attributes + hasPragma = False + pendingEncoding = None + while True: + # Try to find the next attribute after the current position + attr = self.getAttribute() + if attr is None: + return True + else: + if attr[0] == b"http-equiv": + hasPragma = attr[1] == b"content-type" + if hasPragma and pendingEncoding is not None: + self.encoding = pendingEncoding + return False + elif attr[0] == b"charset": + tentativeEncoding = attr[1] + codec = lookupEncoding(tentativeEncoding) + if codec is not None: + self.encoding = codec + return False + elif attr[0] == b"content": + contentParser = ContentAttrParser(EncodingBytes(attr[1])) + tentativeEncoding = contentParser.parse() + if tentativeEncoding is not None: + codec = lookupEncoding(tentativeEncoding) + if codec is not None: + if hasPragma: + self.encoding = codec + return False + else: + pendingEncoding = codec + + def handlePossibleStartTag(self): + return self.handlePossibleTag(False) + + def handlePossibleEndTag(self): + next(self.data) + return self.handlePossibleTag(True) + + def handlePossibleTag(self, endTag): + data = self.data + if data.currentByte not in asciiLettersBytes: + # If the next byte is not an ascii letter either ignore this + # fragment (possible start tag case) or treat it according to + # handleOther + if endTag: + data.previous() + self.handleOther() + return True + + c = data.skipUntil(spacesAngleBrackets) + if c == b"<": + # return to the first step in the overall "two step" algorithm + # reprocessing the < byte + data.previous() + else: + # Read all attributes + attr = self.getAttribute() + while attr is not None: + attr = self.getAttribute() + return True + + def handleOther(self): + return self.data.jumpTo(b">") + + def getAttribute(self): + """Return a name,value pair for the next attribute in the stream, + if one is found, or None""" + data = self.data + # Step 1 (skip chars) + c = data.skip(spaceCharactersBytes | frozenset([b"/"])) + assert c is None or len(c) == 1 + # Step 2 + if c in (b">", None): + return None + # Step 3 + attrName = [] + attrValue = [] + # Step 4 attribute name + while True: + if c == b"=" and attrName: + break + elif c in spaceCharactersBytes: + # Step 6! + c = data.skip() + break + elif c in (b"/", b">"): + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrName.append(c.lower()) + elif c is None: + return None + else: + attrName.append(c) + # Step 5 + c = next(data) + # Step 7 + if c != b"=": + data.previous() + return b"".join(attrName), b"" + # Step 8 + next(data) + # Step 9 + c = data.skip() + # Step 10 + if c in (b"'", b'"'): + # 10.1 + quoteChar = c + while True: + # 10.2 + c = next(data) + # 10.3 + if c == quoteChar: + next(data) + return b"".join(attrName), b"".join(attrValue) + # 10.4 + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + # 10.5 + else: + attrValue.append(c) + elif c == b">": + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + # Step 11 + while True: + c = next(data) + if c in spacesAngleBrackets: + return b"".join(attrName), b"".join(attrValue) + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + + +class ContentAttrParser(object): + def __init__(self, data): + assert isinstance(data, bytes) + self.data = data + + def parse(self): + try: + # Check if the attr name is charset + # otherwise return + self.data.jumpTo(b"charset") + self.data.position += 1 + self.data.skip() + if not self.data.currentByte == b"=": + # If there is no = sign keep looking for attrs + return None + self.data.position += 1 + self.data.skip() + # Look for an encoding between matching quote marks + if self.data.currentByte in (b'"', b"'"): + quoteMark = self.data.currentByte + self.data.position += 1 + oldPosition = self.data.position + if self.data.jumpTo(quoteMark): + return self.data[oldPosition:self.data.position] + else: + return None + else: + # Unquoted value + oldPosition = self.data.position + try: + self.data.skipUntil(spaceCharactersBytes) + return self.data[oldPosition:self.data.position] + except StopIteration: + # Return the whole remaining value + return self.data[oldPosition:] + except StopIteration: + return None + + +def lookupEncoding(encoding): + """Return the python codec name corresponding to an encoding or None if the + string doesn't correspond to a valid encoding.""" + if isinstance(encoding, binary_type): + try: + encoding = encoding.decode("ascii") + except UnicodeDecodeError: + return None + + if encoding is not None: + try: + return webencodings.lookup(encoding) + except AttributeError: + return None + else: + return None diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py new file mode 100644 index 0000000..178f6e7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py @@ -0,0 +1,1721 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import unichr as chr + +from collections import deque + +from .constants import spaceCharacters +from .constants import entities +from .constants import asciiLetters, asciiUpper2Lower +from .constants import digits, hexDigits, EOF +from .constants import tokenTypes, tagTokenTypes +from .constants import replacementCharacters + +from ._inputstream import HTMLInputStream + +from ._trie import Trie + +entitiesTrie = Trie(entities) + + +class HTMLTokenizer(object): + """ This class takes care of tokenizing HTML. + + * self.currentToken + Holds the token that is currently being processed. + + * self.state + Holds a reference to the method to be invoked... XXX + + * self.stream + Points to HTMLInputStream object. + """ + + def __init__(self, stream, parser=None, **kwargs): + + self.stream = HTMLInputStream(stream, **kwargs) + self.parser = parser + + # Setup the initial tokenizer state + self.escapeFlag = False + self.lastFourChars = [] + self.state = self.dataState + self.escape = False + + # The current token being created + self.currentToken = None + super(HTMLTokenizer, self).__init__() + + def __iter__(self): + """ This is where the magic happens. + + We do our usually processing through the states and when we have a token + to return we yield the token which pauses processing until the next token + is requested. + """ + self.tokenQueue = deque([]) + # Start processing. When EOF is reached self.state will return False + # instead of True and the loop will terminate. + while self.state(): + while self.stream.errors: + yield {"type": tokenTypes["ParseError"], "data": self.stream.errors.pop(0)} + while self.tokenQueue: + yield self.tokenQueue.popleft() + + def consumeNumberEntity(self, isHex): + """This function returns either U+FFFD or the character based on the + decimal or hexadecimal representation. It also discards ";" if present. + If not present self.tokenQueue.append({"type": tokenTypes["ParseError"]}) is invoked. + """ + + allowed = digits + radix = 10 + if isHex: + allowed = hexDigits + radix = 16 + + charStack = [] + + # Consume all the characters that are in range while making sure we + # don't hit an EOF. + c = self.stream.char() + while c in allowed and c is not EOF: + charStack.append(c) + c = self.stream.char() + + # Convert the set of characters consumed to an int. + charAsInt = int("".join(charStack), radix) + + # Certain characters get replaced with others + if charAsInt in replacementCharacters: + char = replacementCharacters[charAsInt] + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + elif ((0xD800 <= charAsInt <= 0xDFFF) or + (charAsInt > 0x10FFFF)): + char = "\uFFFD" + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + else: + # Should speed up this check somehow (e.g. move the set to a constant) + if ((0x0001 <= charAsInt <= 0x0008) or + (0x000E <= charAsInt <= 0x001F) or + (0x007F <= charAsInt <= 0x009F) or + (0xFDD0 <= charAsInt <= 0xFDEF) or + charAsInt in frozenset([0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, + 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, + 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, + 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, + 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, + 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, + 0xFFFFF, 0x10FFFE, 0x10FFFF])): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + try: + # Try/except needed as UCS-2 Python builds' unichar only works + # within the BMP. + char = chr(charAsInt) + except ValueError: + v = charAsInt - 0x10000 + char = chr(0xD800 | (v >> 10)) + chr(0xDC00 | (v & 0x3FF)) + + # Discard the ; if present. Otherwise, put it back on the queue and + # invoke parseError on parser. + if c != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "numeric-entity-without-semicolon"}) + self.stream.unget(c) + + return char + + def consumeEntity(self, allowedChar=None, fromAttribute=False): + # Initialise to the default output for when no entity is matched + output = "&" + + charStack = [self.stream.char()] + if (charStack[0] in spaceCharacters or charStack[0] in (EOF, "<", "&") or + (allowedChar is not None and allowedChar == charStack[0])): + self.stream.unget(charStack[0]) + + elif charStack[0] == "#": + # Read the next character to see if it's hex or decimal + hex = False + charStack.append(self.stream.char()) + if charStack[-1] in ("x", "X"): + hex = True + charStack.append(self.stream.char()) + + # charStack[-1] should be the first digit + if (hex and charStack[-1] in hexDigits) \ + or (not hex and charStack[-1] in digits): + # At least one digit found, so consume the whole number + self.stream.unget(charStack[-1]) + output = self.consumeNumberEntity(hex) + else: + # No digits found + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "expected-numeric-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + else: + # At this point in the process might have named entity. Entities + # are stored in the global variable "entities". + # + # Consume characters and compare to these to a substring of the + # entity names in the list until the substring no longer matches. + while (charStack[-1] is not EOF): + if not entitiesTrie.has_keys_with_prefix("".join(charStack)): + break + charStack.append(self.stream.char()) + + # At this point we have a string that starts with some characters + # that may match an entity + # Try to find the longest entity the string will match to take care + # of ¬i for instance. + try: + entityName = entitiesTrie.longest_prefix("".join(charStack[:-1])) + entityLength = len(entityName) + except KeyError: + entityName = None + + if entityName is not None: + if entityName[-1] != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "named-entity-without-semicolon"}) + if (entityName[-1] != ";" and fromAttribute and + (charStack[entityLength] in asciiLetters or + charStack[entityLength] in digits or + charStack[entityLength] == "=")): + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + else: + output = entities[entityName] + self.stream.unget(charStack.pop()) + output += "".join(charStack[entityLength:]) + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-named-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + if fromAttribute: + self.currentToken["data"][-1][1] += output + else: + if output in spaceCharacters: + tokenType = "SpaceCharacters" + else: + tokenType = "Characters" + self.tokenQueue.append({"type": tokenTypes[tokenType], "data": output}) + + def processEntityInAttribute(self, allowedChar): + """This method replaces the need for "entityInAttributeValueState". + """ + self.consumeEntity(allowedChar=allowedChar, fromAttribute=True) + + def emitCurrentToken(self): + """This method is a generic handler for emitting the tags. It also sets + the state to "data" because that's what's needed after a token has been + emitted. + """ + token = self.currentToken + # Add token to the queue to be yielded + if (token["type"] in tagTokenTypes): + token["name"] = token["name"].translate(asciiUpper2Lower) + if token["type"] == tokenTypes["EndTag"]: + if token["data"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "attributes-in-end-tag"}) + if token["selfClosing"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "self-closing-flag-on-end-tag"}) + self.tokenQueue.append(token) + self.state = self.dataState + + # Below are the various tokenizer states worked out. + def dataState(self): + data = self.stream.char() + if data == "&": + self.state = self.entityDataState + elif data == "<": + self.state = self.tagOpenState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\u0000"}) + elif data is EOF: + # Tokenization ends. + return False + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any <!-- or --> sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def entityDataState(self): + self.consumeEntity() + self.state = self.dataState + return True + + def rcdataState(self): + data = self.stream.char() + if data == "&": + self.state = self.characterReferenceInRcdata + elif data == "<": + self.state = self.rcdataLessThanSignState + elif data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any <!-- or --> sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def characterReferenceInRcdata(self): + self.consumeEntity() + self.state = self.rcdataState + return True + + def rawtextState(self): + data = self.stream.char() + if data == "<": + self.state = self.rawtextLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataState(self): + data = self.stream.char() + if data == "<": + self.state = self.scriptDataLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def plaintextState(self): + data = self.stream.char() + if data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + self.stream.charsUntil("\u0000")}) + return True + + def tagOpenState(self): + data = self.stream.char() + if data == "!": + self.state = self.markupDeclarationOpenState + elif data == "/": + self.state = self.closeTagOpenState + elif data in asciiLetters: + self.currentToken = {"type": tokenTypes["StartTag"], + "name": data, "data": [], + "selfClosing": False, + "selfClosingAcknowledged": False} + self.state = self.tagNameState + elif data == ">": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-right-bracket"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<>"}) + self.state = self.dataState + elif data == "?": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-question-mark"}) + self.stream.unget(data) + self.state = self.bogusCommentState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.dataState + return True + + def closeTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.currentToken = {"type": tokenTypes["EndTag"], "name": data, + "data": [], "selfClosing": False} + self.state = self.tagNameState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-right-bracket"}) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-eof"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.state = self.dataState + else: + # XXX data can be _'_... + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-char", + "datavars": {"data": data}}) + self.stream.unget(data) + self.state = self.bogusCommentState + return True + + def tagNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-tag-name"}) + self.state = self.dataState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + else: + self.currentToken["name"] += data + # (Don't use charsUntil here, because tag names are + # very short and it's faster to not do anything fancy) + return True + + def rcdataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rcdataEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rcdataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rawtextLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rawtextEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def rawtextEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rawtextEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def rawtextEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.rawtextState + return True + + def scriptDataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEndTagOpenState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<!"}) + self.state = self.scriptDataEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.scriptDataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapeStartState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapeStartDashState + else: + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapeStartDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashDashState + else: + self.stream.unget(data) + self.state = self.scriptDataState + return True + + def scriptDataEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashState + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.state = self.dataState + else: + chars = self.stream.charsUntil(("<", "-", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataEscapedDashDashState + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.state = self.scriptDataEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEscapedEndTagOpenState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<" + data}) + self.temporaryBuffer = data + self.state = self.scriptDataDoubleEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer = data + self.state = self.scriptDataEscapedEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagNameState(self): + appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower() + data = self.stream.char() + if data in spaceCharacters and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.beforeAttributeNameState + elif data == "/" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.state = self.selfClosingStartTagState + elif data == ">" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "</" + self.temporaryBuffer}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapeStartState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataDoubleEscapedState + else: + self.state = self.scriptDataEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + return True + + def scriptDataDoubleEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "/"}) + self.temporaryBuffer = "" + self.state = self.scriptDataDoubleEscapeEndState + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapeEndState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataEscapedState + else: + self.state = self.scriptDataDoubleEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def beforeAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data in ("'", '"', "=", "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-name-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def attributeNameState(self): + data = self.stream.char() + leavingThisState = True + emitToken = False + if data == "=": + self.state = self.beforeAttributeValueState + elif data in asciiLetters: + self.currentToken["data"][-1][0] += data +\ + self.stream.charsUntil(asciiLetters, True) + leavingThisState = False + elif data == ">": + # XXX If we emit here the attributes are converted to a dict + # without being checked and when the code below runs we error + # because data is a dict not a list + emitToken = True + elif data in spaceCharacters: + self.state = self.afterAttributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][0] += "\uFFFD" + leavingThisState = False + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"][-1][0] += data + leavingThisState = False + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-attribute-name"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][0] += data + leavingThisState = False + + if leavingThisState: + # Attributes are not dropped at this stage. That happens when the + # start tag token is emitted so values can still be safely appended + # to attributes, but we do want to report the parse error in time. + self.currentToken["data"][-1][0] = ( + self.currentToken["data"][-1][0].translate(asciiUpper2Lower)) + for name, _ in self.currentToken["data"][:-1]: + if self.currentToken["data"][-1][0] == name: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "duplicate-attribute"}) + break + # XXX Fix for above XXX + if emitToken: + self.emitCurrentToken() + return True + + def afterAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "=": + self.state = self.beforeAttributeValueState + elif data == ">": + self.emitCurrentToken() + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-after-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-end-of-tag-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def beforeAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "\"": + self.state = self.attributeValueDoubleQuotedState + elif data == "&": + self.state = self.attributeValueUnQuotedState + self.stream.unget(data) + elif data == "'": + self.state = self.attributeValueSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-right-bracket"}) + self.emitCurrentToken() + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + self.state = self.attributeValueUnQuotedState + elif data in ("=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "equals-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + return True + + def attributeValueDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute('"') + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-double-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("\"", "&", "\u0000")) + return True + + def attributeValueSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute("'") + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-single-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("'", "&", "\u0000")) + return True + + def attributeValueUnQuotedState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == "&": + self.processEntityInAttribute(">") + elif data == ">": + self.emitCurrentToken() + elif data in ('"', "'", "=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-no-quotes"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.stream.charsUntil( + frozenset(("&", ">", '"', "'", "=", "<", "`", "\u0000")) | spaceCharacters) + return True + + def afterAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-EOF-after-attribute-value"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-attribute-value"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def selfClosingStartTagState(self): + data = self.stream.char() + if data == ">": + self.currentToken["selfClosing"] = True + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "unexpected-EOF-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def bogusCommentState(self): + # Make a new comment token and give it as value all the characters + # until the first > or EOF (charsUntil checks for EOF automatically) + # and emit it. + data = self.stream.charsUntil(">") + data = data.replace("\u0000", "\uFFFD") + self.tokenQueue.append( + {"type": tokenTypes["Comment"], "data": data}) + + # Eat the character directly after the bogus comment which is either a + # ">" or an EOF. + self.stream.char() + self.state = self.dataState + return True + + def markupDeclarationOpenState(self): + charStack = [self.stream.char()] + if charStack[-1] == "-": + charStack.append(self.stream.char()) + if charStack[-1] == "-": + self.currentToken = {"type": tokenTypes["Comment"], "data": ""} + self.state = self.commentStartState + return True + elif charStack[-1] in ('d', 'D'): + matched = True + for expected in (('o', 'O'), ('c', 'C'), ('t', 'T'), + ('y', 'Y'), ('p', 'P'), ('e', 'E')): + charStack.append(self.stream.char()) + if charStack[-1] not in expected: + matched = False + break + if matched: + self.currentToken = {"type": tokenTypes["Doctype"], + "name": "", + "publicId": None, "systemId": None, + "correct": True} + self.state = self.doctypeState + return True + elif (charStack[-1] == "[" and + self.parser is not None and + self.parser.tree.openElements and + self.parser.tree.openElements[-1].namespace != self.parser.tree.defaultNamespace): + matched = True + for expected in ["C", "D", "A", "T", "A", "["]: + charStack.append(self.stream.char()) + if charStack[-1] != expected: + matched = False + break + if matched: + self.state = self.cdataSectionState + return True + + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-dashes-or-doctype"}) + + while charStack: + self.stream.unget(charStack.pop()) + self.state = self.bogusCommentState + return True + + def commentStartState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentStartDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + self.state = self.commentState + return True + + def commentStartDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + \ + self.stream.charsUntil(("-", "\u0000")) + return True + + def commentEndDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentEndState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--\uFFFD" + self.state = self.commentState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-bang-after-double-dash-in-comment"}) + self.state = self.commentEndBangState + elif data == "-": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-dash-after-double-dash-in-comment"}) + self.currentToken["data"] += data + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-double-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-comment"}) + self.currentToken["data"] += "--" + data + self.state = self.commentState + return True + + def commentEndBangState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "-": + self.currentToken["data"] += "--!" + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--!\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-bang-state"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "--!" + data + self.state = self.commentState + return True + + def doctypeState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "need-space-after-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeNameState + return True + + def beforeDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-right-bracket"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] = "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] = data + self.state = self.doctypeNameState + return True + + def doctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.state = self.afterDoctypeNameState + elif data == ">": + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype-name"}) + self.currentToken["correct"] = False + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] += data + return True + + def afterDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.currentToken["correct"] = False + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + if data in ("p", "P"): + matched = True + for expected in (("u", "U"), ("b", "B"), ("l", "L"), + ("i", "I"), ("c", "C")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypePublicKeywordState + return True + elif data in ("s", "S"): + matched = True + for expected in (("y", "Y"), ("s", "S"), ("t", "T"), + ("e", "E"), ("m", "M")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypeSystemKeywordState + return True + + # All the characters read before the current 'data' will be + # [a-zA-Z], so they're garbage in the bogus doctype and can be + # discarded; only the latest character might be '>' or EOF + # and needs to be ungetted + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-space-or-right-bracket-in-doctype", "datavars": + {"data": data}}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + + return True + + def afterDoctypePublicKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypePublicIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + return True + + def beforeDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypePublicIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def doctypePublicIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def afterDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.betweenDoctypePublicAndSystemIdentifiersState + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def betweenDoctypePublicAndSystemIdentifiersState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def afterDoctypeSystemKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeSystemIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + return True + + def beforeDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypeSystemIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def doctypeSystemIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def afterDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.state = self.bogusDoctypeState + return True + + def bogusDoctypeState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + # XXX EMIT + self.stream.unget(data) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + pass + return True + + def cdataSectionState(self): + data = [] + while True: + data.append(self.stream.charsUntil("]")) + data.append(self.stream.charsUntil(">")) + char = self.stream.char() + if char == EOF: + break + else: + assert char == ">" + if data[-1][-2:] == "]]": + data[-1] = data[-1][:-2] + break + else: + data.append(char) + + data = "".join(data) # pylint:disable=redefined-variable-type + # Deal with null here rather than in the parser + nullCount = data.count("\u0000") + if nullCount > 0: + for _ in range(nullCount): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + data = data.replace("\u0000", "\uFFFD") + if data: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": data}) + self.state = self.dataState + return True diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py new file mode 100644 index 0000000..a5ba4bf --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py @@ -0,0 +1,14 @@ +from __future__ import absolute_import, division, unicode_literals + +from .py import Trie as PyTrie + +Trie = PyTrie + +# pylint:disable=wrong-import-position +try: + from .datrie import Trie as DATrie +except ImportError: + pass +else: + Trie = DATrie +# pylint:enable=wrong-import-position diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py new file mode 100644 index 0000000..a1158bb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import, division, unicode_literals + +from collections import Mapping + + +class Trie(Mapping): + """Abstract base class for tries""" + + def keys(self, prefix=None): + # pylint:disable=arguments-differ + keys = super(Trie, self).keys() + + if prefix is None: + return set(keys) + + return {x for x in keys if x.startswith(prefix)} + + def has_keys_with_prefix(self, prefix): + for key in self.keys(): + if key.startswith(prefix): + return True + + return False + + def longest_prefix(self, prefix): + if prefix in self: + return prefix + + for i in range(1, len(prefix) + 1): + if prefix[:-i] in self: + return prefix[:-i] + + raise KeyError(prefix) + + def longest_prefix_item(self, prefix): + lprefix = self.longest_prefix(prefix) + return (lprefix, self[lprefix]) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/datrie.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/datrie.py new file mode 100644 index 0000000..e2e5f86 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/datrie.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import, division, unicode_literals + +from datrie import Trie as DATrie +from pip._vendor.six import text_type + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + chars = set() + for key in data.keys(): + if not isinstance(key, text_type): + raise TypeError("All keys must be strings") + for char in key: + chars.add(char) + + self._data = DATrie("".join(chars)) + for key, value in data.items(): + self._data[key] = value + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + raise NotImplementedError() + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + return self._data.keys(prefix) + + def has_keys_with_prefix(self, prefix): + return self._data.has_keys_with_prefix(prefix) + + def longest_prefix(self, prefix): + return self._data.longest_prefix(prefix) + + def longest_prefix_item(self, prefix): + return self._data.longest_prefix_item(prefix) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py new file mode 100644 index 0000000..c178b21 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py @@ -0,0 +1,67 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from bisect import bisect_left + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + if not all(isinstance(x, text_type) for x in data.keys()): + raise TypeError("All keys must be strings") + + self._data = data + self._keys = sorted(data.keys()) + self._cachestr = "" + self._cachepoints = (0, len(data)) + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + return iter(self._data) + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + if prefix is None or prefix == "" or not self._keys: + return set(self._keys) + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + start = i = bisect_left(self._keys, prefix, lo, hi) + else: + start = i = bisect_left(self._keys, prefix) + + keys = set() + if start == len(self._keys): + return keys + + while self._keys[i].startswith(prefix): + keys.add(self._keys[i]) + i += 1 + + self._cachestr = prefix + self._cachepoints = (start, i) + + return keys + + def has_keys_with_prefix(self, prefix): + if prefix in self._data: + return True + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + i = bisect_left(self._keys, prefix, lo, hi) + else: + i = bisect_left(self._keys, prefix) + + if i == len(self._keys): + return False + + return self._keys[i].startswith(prefix) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/_utils.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_utils.py new file mode 100644 index 0000000..0703afb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/_utils.py @@ -0,0 +1,124 @@ +from __future__ import absolute_import, division, unicode_literals + +from types import ModuleType + +from pip._vendor.six import text_type + +try: + import xml.etree.cElementTree as default_etree +except ImportError: + import xml.etree.ElementTree as default_etree + + +__all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair", + "surrogatePairToCodepoint", "moduleFactoryFactory", + "supports_lone_surrogates"] + + +# Platforms not supporting lone surrogates (\uD800-\uDFFF) should be +# caught by the below test. In general this would be any platform +# using UTF-16 as its encoding of unicode strings, such as +# Jython. This is because UTF-16 itself is based on the use of such +# surrogates, and there is no mechanism to further escape such +# escapes. +try: + _x = eval('"\\uD800"') # pylint:disable=eval-used + if not isinstance(_x, text_type): + # We need this with u"" because of http://bugs.jython.org/issue2039 + _x = eval('u"\\uD800"') # pylint:disable=eval-used + assert isinstance(_x, text_type) +except: # pylint:disable=bare-except + supports_lone_surrogates = False +else: + supports_lone_surrogates = True + + +class MethodDispatcher(dict): + """Dict with 2 special properties: + + On initiation, keys that are lists, sets or tuples are converted to + multiple keys so accessing any one of the items in the original + list-like object returns the matching value + + md = MethodDispatcher({("foo", "bar"):"baz"}) + md["foo"] == "baz" + + A default value which can be set through the default attribute. + """ + + def __init__(self, items=()): + # Using _dictEntries instead of directly assigning to self is about + # twice as fast. Please do careful performance testing before changing + # anything here. + _dictEntries = [] + for name, value in items: + if isinstance(name, (list, tuple, frozenset, set)): + for item in name: + _dictEntries.append((item, value)) + else: + _dictEntries.append((name, value)) + dict.__init__(self, _dictEntries) + assert len(self) == len(_dictEntries) + self.default = None + + def __getitem__(self, key): + return dict.get(self, key, self.default) + + +# Some utility functions to deal with weirdness around UCS2 vs UCS4 +# python builds + +def isSurrogatePair(data): + return (len(data) == 2 and + ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and + ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF) + + +def surrogatePairToCodepoint(data): + char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 + + (ord(data[1]) - 0xDC00)) + return char_val + +# Module Factory Factory (no, this isn't Java, I know) +# Here to stop this being duplicated all over the place. + + +def moduleFactoryFactory(factory): + moduleCache = {} + + def moduleFactory(baseModule, *args, **kwargs): + if isinstance(ModuleType.__name__, type("")): + name = "_%s_factory" % baseModule.__name__ + else: + name = b"_%s_factory" % baseModule.__name__ + + kwargs_tuple = tuple(kwargs.items()) + + try: + return moduleCache[name][args][kwargs_tuple] + except KeyError: + mod = ModuleType(name) + objs = factory(baseModule, *args, **kwargs) + mod.__dict__.update(objs) + if "name" not in moduleCache: + moduleCache[name] = {} + if "args" not in moduleCache[name]: + moduleCache[name][args] = {} + if "kwargs" not in moduleCache[name][args]: + moduleCache[name][args][kwargs_tuple] = {} + moduleCache[name][args][kwargs_tuple] = mod + return mod + + return moduleFactory + + +def memoize(func): + cache = {} + + def wrapped(*args, **kwargs): + key = (tuple(args), tuple(kwargs.items())) + if key not in cache: + cache[key] = func(*args, **kwargs) + return cache[key] + + return wrapped diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/constants.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/constants.py new file mode 100644 index 0000000..1ff8041 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/constants.py @@ -0,0 +1,2947 @@ +from __future__ import absolute_import, division, unicode_literals + +import string + +EOF = None + +E = { + "null-character": + "Null character in input stream, replaced with U+FFFD.", + "invalid-codepoint": + "Invalid codepoint in stream.", + "incorrectly-placed-solidus": + "Solidus (/) incorrectly placed in tag.", + "incorrect-cr-newline-entity": + "Incorrect CR newline entity, replaced with LF.", + "illegal-windows-1252-entity": + "Entity used with illegal number (windows-1252 reference).", + "cant-convert-numeric-entity": + "Numeric entity couldn't be converted to character " + "(codepoint U+%(charAsInt)08x).", + "illegal-codepoint-for-numeric-entity": + "Numeric entity represents an illegal codepoint: " + "U+%(charAsInt)08x.", + "numeric-entity-without-semicolon": + "Numeric entity didn't end with ';'.", + "expected-numeric-entity-but-got-eof": + "Numeric entity expected. Got end of file instead.", + "expected-numeric-entity": + "Numeric entity expected but none found.", + "named-entity-without-semicolon": + "Named entity didn't end with ';'.", + "expected-named-entity": + "Named entity expected. Got none.", + "attributes-in-end-tag": + "End tag contains unexpected attributes.", + 'self-closing-flag-on-end-tag': + "End tag contains unexpected self-closing flag.", + "expected-tag-name-but-got-right-bracket": + "Expected tag name. Got '>' instead.", + "expected-tag-name-but-got-question-mark": + "Expected tag name. Got '?' instead. (HTML doesn't " + "support processing instructions.)", + "expected-tag-name": + "Expected tag name. Got something else instead", + "expected-closing-tag-but-got-right-bracket": + "Expected closing tag. Got '>' instead. Ignoring '</>'.", + "expected-closing-tag-but-got-eof": + "Expected closing tag. Unexpected end of file.", + "expected-closing-tag-but-got-char": + "Expected closing tag. Unexpected character '%(data)s' found.", + "eof-in-tag-name": + "Unexpected end of file in the tag name.", + "expected-attribute-name-but-got-eof": + "Unexpected end of file. Expected attribute name instead.", + "eof-in-attribute-name": + "Unexpected end of file in attribute name.", + "invalid-character-in-attribute-name": + "Invalid character in attribute name", + "duplicate-attribute": + "Dropped duplicate attribute on tag.", + "expected-end-of-tag-name-but-got-eof": + "Unexpected end of file. Expected = or end of tag.", + "expected-attribute-value-but-got-eof": + "Unexpected end of file. Expected attribute value.", + "expected-attribute-value-but-got-right-bracket": + "Expected attribute value. Got '>' instead.", + 'equals-in-unquoted-attribute-value': + "Unexpected = in unquoted attribute", + 'unexpected-character-in-unquoted-attribute-value': + "Unexpected character in unquoted attribute", + "invalid-character-after-attribute-name": + "Unexpected character after attribute name.", + "unexpected-character-after-attribute-value": + "Unexpected character after attribute value.", + "eof-in-attribute-value-double-quote": + "Unexpected end of file in attribute value (\").", + "eof-in-attribute-value-single-quote": + "Unexpected end of file in attribute value (').", + "eof-in-attribute-value-no-quotes": + "Unexpected end of file in attribute value.", + "unexpected-EOF-after-solidus-in-tag": + "Unexpected end of file in tag. Expected >", + "unexpected-character-after-solidus-in-tag": + "Unexpected character after / in tag. Expected >", + "expected-dashes-or-doctype": + "Expected '--' or 'DOCTYPE'. Not found.", + "unexpected-bang-after-double-dash-in-comment": + "Unexpected ! after -- in comment", + "unexpected-space-after-double-dash-in-comment": + "Unexpected space after -- in comment", + "incorrect-comment": + "Incorrect comment.", + "eof-in-comment": + "Unexpected end of file in comment.", + "eof-in-comment-end-dash": + "Unexpected end of file in comment (-)", + "unexpected-dash-after-double-dash-in-comment": + "Unexpected '-' after '--' found in comment.", + "eof-in-comment-double-dash": + "Unexpected end of file in comment (--).", + "eof-in-comment-end-space-state": + "Unexpected end of file in comment.", + "eof-in-comment-end-bang-state": + "Unexpected end of file in comment.", + "unexpected-char-in-comment": + "Unexpected character in comment found.", + "need-space-after-doctype": + "No space after literal string 'DOCTYPE'.", + "expected-doctype-name-but-got-right-bracket": + "Unexpected > character. Expected DOCTYPE name.", + "expected-doctype-name-but-got-eof": + "Unexpected end of file. Expected DOCTYPE name.", + "eof-in-doctype-name": + "Unexpected end of file in DOCTYPE name.", + "eof-in-doctype": + "Unexpected end of file in DOCTYPE.", + "expected-space-or-right-bracket-in-doctype": + "Expected space or '>'. Got '%(data)s'", + "unexpected-end-of-doctype": + "Unexpected end of DOCTYPE.", + "unexpected-char-in-doctype": + "Unexpected character in DOCTYPE.", + "eof-in-innerhtml": + "XXX innerHTML EOF", + "unexpected-doctype": + "Unexpected DOCTYPE. Ignored.", + "non-html-root": + "html needs to be the first start tag.", + "expected-doctype-but-got-eof": + "Unexpected End of file. Expected DOCTYPE.", + "unknown-doctype": + "Erroneous DOCTYPE.", + "expected-doctype-but-got-chars": + "Unexpected non-space characters. Expected DOCTYPE.", + "expected-doctype-but-got-start-tag": + "Unexpected start tag (%(name)s). Expected DOCTYPE.", + "expected-doctype-but-got-end-tag": + "Unexpected end tag (%(name)s). Expected DOCTYPE.", + "end-tag-after-implied-root": + "Unexpected end tag (%(name)s) after the (implied) root element.", + "expected-named-closing-tag-but-got-eof": + "Unexpected end of file. Expected end tag (%(name)s).", + "two-heads-are-not-better-than-one": + "Unexpected start tag head in existing head. Ignored.", + "unexpected-end-tag": + "Unexpected end tag (%(name)s). Ignored.", + "unexpected-start-tag-out-of-my-head": + "Unexpected start tag (%(name)s) that can be in head. Moved.", + "unexpected-start-tag": + "Unexpected start tag (%(name)s).", + "missing-end-tag": + "Missing end tag (%(name)s).", + "missing-end-tags": + "Missing end tags (%(name)s).", + "unexpected-start-tag-implies-end-tag": + "Unexpected start tag (%(startName)s) " + "implies end tag (%(endName)s).", + "unexpected-start-tag-treated-as": + "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", + "deprecated-tag": + "Unexpected start tag %(name)s. Don't use it!", + "unexpected-start-tag-ignored": + "Unexpected start tag %(name)s. Ignored.", + "expected-one-end-tag-but-got-another": + "Unexpected end tag (%(gotName)s). " + "Missing end tag (%(expectedName)s).", + "end-tag-too-early": + "End tag (%(name)s) seen too early. Expected other end tag.", + "end-tag-too-early-named": + "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", + "end-tag-too-early-ignored": + "End tag (%(name)s) seen too early. Ignored.", + "adoption-agency-1.1": + "End tag (%(name)s) violates step 1, " + "paragraph 1 of the adoption agency algorithm.", + "adoption-agency-1.2": + "End tag (%(name)s) violates step 1, " + "paragraph 2 of the adoption agency algorithm.", + "adoption-agency-1.3": + "End tag (%(name)s) violates step 1, " + "paragraph 3 of the adoption agency algorithm.", + "adoption-agency-4.4": + "End tag (%(name)s) violates step 4, " + "paragraph 4 of the adoption agency algorithm.", + "unexpected-end-tag-treated-as": + "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", + "no-end-tag": + "This element (%(name)s) has no end tag.", + "unexpected-implied-end-tag-in-table": + "Unexpected implied end tag (%(name)s) in the table phase.", + "unexpected-implied-end-tag-in-table-body": + "Unexpected implied end tag (%(name)s) in the table body phase.", + "unexpected-char-implies-table-voodoo": + "Unexpected non-space characters in " + "table context caused voodoo mode.", + "unexpected-hidden-input-in-table": + "Unexpected input with type hidden in table context.", + "unexpected-form-in-table": + "Unexpected form in table context.", + "unexpected-start-tag-implies-table-voodoo": + "Unexpected start tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-end-tag-implies-table-voodoo": + "Unexpected end tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-cell-in-table-body": + "Unexpected table cell start tag (%(name)s) " + "in the table body phase.", + "unexpected-cell-end-tag": + "Got table cell end tag (%(name)s) " + "while required end tags are missing.", + "unexpected-end-tag-in-table-body": + "Unexpected end tag (%(name)s) in the table body phase. Ignored.", + "unexpected-implied-end-tag-in-table-row": + "Unexpected implied end tag (%(name)s) in the table row phase.", + "unexpected-end-tag-in-table-row": + "Unexpected end tag (%(name)s) in the table row phase. Ignored.", + "unexpected-select-in-select": + "Unexpected select start tag in the select phase " + "treated as select end tag.", + "unexpected-input-in-select": + "Unexpected input start tag in the select phase.", + "unexpected-start-tag-in-select": + "Unexpected start tag token (%(name)s in the select phase. " + "Ignored.", + "unexpected-end-tag-in-select": + "Unexpected end tag (%(name)s) in the select phase. Ignored.", + "unexpected-table-element-start-tag-in-select-in-table": + "Unexpected table element start tag (%(name)s) in the select in table phase.", + "unexpected-table-element-end-tag-in-select-in-table": + "Unexpected table element end tag (%(name)s) in the select in table phase.", + "unexpected-char-after-body": + "Unexpected non-space characters in the after body phase.", + "unexpected-start-tag-after-body": + "Unexpected start tag token (%(name)s)" + " in the after body phase.", + "unexpected-end-tag-after-body": + "Unexpected end tag token (%(name)s)" + " in the after body phase.", + "unexpected-char-in-frameset": + "Unexpected characters in the frameset phase. Characters ignored.", + "unexpected-start-tag-in-frameset": + "Unexpected start tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-frameset-in-frameset-innerhtml": + "Unexpected end tag token (frameset) " + "in the frameset phase (innerHTML).", + "unexpected-end-tag-in-frameset": + "Unexpected end tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-char-after-frameset": + "Unexpected non-space characters in the " + "after frameset phase. Ignored.", + "unexpected-start-tag-after-frameset": + "Unexpected start tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-frameset": + "Unexpected end tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-body-innerhtml": + "Unexpected end tag after body(innerHtml)", + "expected-eof-but-got-char": + "Unexpected non-space characters. Expected end of file.", + "expected-eof-but-got-start-tag": + "Unexpected start tag (%(name)s)" + ". Expected end of file.", + "expected-eof-but-got-end-tag": + "Unexpected end tag (%(name)s)" + ". Expected end of file.", + "eof-in-table": + "Unexpected end of file. Expected table content.", + "eof-in-select": + "Unexpected end of file. Expected select content.", + "eof-in-frameset": + "Unexpected end of file. Expected frameset content.", + "eof-in-script-in-script": + "Unexpected end of file. Expected script content.", + "eof-in-foreign-lands": + "Unexpected end of file. Expected foreign content", + "non-void-element-with-trailing-solidus": + "Trailing solidus not allowed on element %(name)s", + "unexpected-html-element-in-foreign-content": + "Element %(name)s not allowed in a non-html context", + "unexpected-end-tag-before-html": + "Unexpected end tag (%(name)s) before html.", + "unexpected-inhead-noscript-tag": + "Element %(name)s not allowed in a inhead-noscript context", + "eof-in-head-noscript": + "Unexpected end of file. Expected inhead-noscript content", + "char-in-head-noscript": + "Unexpected non-space character. Expected inhead-noscript content", + "XXX-undefined-error": + "Undefined error (this sucks and should be fixed)", +} + +namespaces = { + "html": "http://www.w3.org/1999/xhtml", + "mathml": "http://www.w3.org/1998/Math/MathML", + "svg": "http://www.w3.org/2000/svg", + "xlink": "http://www.w3.org/1999/xlink", + "xml": "http://www.w3.org/XML/1998/namespace", + "xmlns": "http://www.w3.org/2000/xmlns/" +} + +scopingElements = frozenset([ + (namespaces["html"], "applet"), + (namespaces["html"], "caption"), + (namespaces["html"], "html"), + (namespaces["html"], "marquee"), + (namespaces["html"], "object"), + (namespaces["html"], "table"), + (namespaces["html"], "td"), + (namespaces["html"], "th"), + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext"), + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title"), +]) + +formattingElements = frozenset([ + (namespaces["html"], "a"), + (namespaces["html"], "b"), + (namespaces["html"], "big"), + (namespaces["html"], "code"), + (namespaces["html"], "em"), + (namespaces["html"], "font"), + (namespaces["html"], "i"), + (namespaces["html"], "nobr"), + (namespaces["html"], "s"), + (namespaces["html"], "small"), + (namespaces["html"], "strike"), + (namespaces["html"], "strong"), + (namespaces["html"], "tt"), + (namespaces["html"], "u") +]) + +specialElements = frozenset([ + (namespaces["html"], "address"), + (namespaces["html"], "applet"), + (namespaces["html"], "area"), + (namespaces["html"], "article"), + (namespaces["html"], "aside"), + (namespaces["html"], "base"), + (namespaces["html"], "basefont"), + (namespaces["html"], "bgsound"), + (namespaces["html"], "blockquote"), + (namespaces["html"], "body"), + (namespaces["html"], "br"), + (namespaces["html"], "button"), + (namespaces["html"], "caption"), + (namespaces["html"], "center"), + (namespaces["html"], "col"), + (namespaces["html"], "colgroup"), + (namespaces["html"], "command"), + (namespaces["html"], "dd"), + (namespaces["html"], "details"), + (namespaces["html"], "dir"), + (namespaces["html"], "div"), + (namespaces["html"], "dl"), + (namespaces["html"], "dt"), + (namespaces["html"], "embed"), + (namespaces["html"], "fieldset"), + (namespaces["html"], "figure"), + (namespaces["html"], "footer"), + (namespaces["html"], "form"), + (namespaces["html"], "frame"), + (namespaces["html"], "frameset"), + (namespaces["html"], "h1"), + (namespaces["html"], "h2"), + (namespaces["html"], "h3"), + (namespaces["html"], "h4"), + (namespaces["html"], "h5"), + (namespaces["html"], "h6"), + (namespaces["html"], "head"), + (namespaces["html"], "header"), + (namespaces["html"], "hr"), + (namespaces["html"], "html"), + (namespaces["html"], "iframe"), + # Note that image is commented out in the spec as "this isn't an + # element that can end up on the stack, so it doesn't matter," + (namespaces["html"], "image"), + (namespaces["html"], "img"), + (namespaces["html"], "input"), + (namespaces["html"], "isindex"), + (namespaces["html"], "li"), + (namespaces["html"], "link"), + (namespaces["html"], "listing"), + (namespaces["html"], "marquee"), + (namespaces["html"], "menu"), + (namespaces["html"], "meta"), + (namespaces["html"], "nav"), + (namespaces["html"], "noembed"), + (namespaces["html"], "noframes"), + (namespaces["html"], "noscript"), + (namespaces["html"], "object"), + (namespaces["html"], "ol"), + (namespaces["html"], "p"), + (namespaces["html"], "param"), + (namespaces["html"], "plaintext"), + (namespaces["html"], "pre"), + (namespaces["html"], "script"), + (namespaces["html"], "section"), + (namespaces["html"], "select"), + (namespaces["html"], "style"), + (namespaces["html"], "table"), + (namespaces["html"], "tbody"), + (namespaces["html"], "td"), + (namespaces["html"], "textarea"), + (namespaces["html"], "tfoot"), + (namespaces["html"], "th"), + (namespaces["html"], "thead"), + (namespaces["html"], "title"), + (namespaces["html"], "tr"), + (namespaces["html"], "ul"), + (namespaces["html"], "wbr"), + (namespaces["html"], "xmp"), + (namespaces["svg"], "foreignObject") +]) + +htmlIntegrationPointElements = frozenset([ + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title") +]) + +mathmlTextIntegrationPointElements = frozenset([ + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext") +]) + +adjustSVGAttributes = { + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "contentscripttype": "contentScriptType", + "contentstyletype": "contentStyleType", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "externalresourcesrequired": "externalResourcesRequired", + "filterres": "filterRes", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan" +} + +adjustMathMLAttributes = {"definitionurl": "definitionURL"} + +adjustForeignAttributes = { + "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), + "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), + "xlink:href": ("xlink", "href", namespaces["xlink"]), + "xlink:role": ("xlink", "role", namespaces["xlink"]), + "xlink:show": ("xlink", "show", namespaces["xlink"]), + "xlink:title": ("xlink", "title", namespaces["xlink"]), + "xlink:type": ("xlink", "type", namespaces["xlink"]), + "xml:base": ("xml", "base", namespaces["xml"]), + "xml:lang": ("xml", "lang", namespaces["xml"]), + "xml:space": ("xml", "space", namespaces["xml"]), + "xmlns": (None, "xmlns", namespaces["xmlns"]), + "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) +} + +unadjustForeignAttributes = dict([((ns, local), qname) for qname, (prefix, local, ns) in + adjustForeignAttributes.items()]) + +spaceCharacters = frozenset([ + "\t", + "\n", + "\u000C", + " ", + "\r" +]) + +tableInsertModeElements = frozenset([ + "table", + "tbody", + "tfoot", + "thead", + "tr" +]) + +asciiLowercase = frozenset(string.ascii_lowercase) +asciiUppercase = frozenset(string.ascii_uppercase) +asciiLetters = frozenset(string.ascii_letters) +digits = frozenset(string.digits) +hexDigits = frozenset(string.hexdigits) + +asciiUpper2Lower = dict([(ord(c), ord(c.lower())) + for c in string.ascii_uppercase]) + +# Heading elements need to be ordered +headingElements = ( + "h1", + "h2", + "h3", + "h4", + "h5", + "h6" +) + +voidElements = frozenset([ + "base", + "command", + "event-source", + "link", + "meta", + "hr", + "br", + "img", + "embed", + "param", + "area", + "col", + "input", + "source", + "track" +]) + +cdataElements = frozenset(['title', 'textarea']) + +rcdataElements = frozenset([ + 'style', + 'script', + 'xmp', + 'iframe', + 'noembed', + 'noframes', + 'noscript' +]) + +booleanAttributes = { + "": frozenset(["irrelevant", "itemscope"]), + "style": frozenset(["scoped"]), + "img": frozenset(["ismap"]), + "audio": frozenset(["autoplay", "controls"]), + "video": frozenset(["autoplay", "controls"]), + "script": frozenset(["defer", "async"]), + "details": frozenset(["open"]), + "datagrid": frozenset(["multiple", "disabled"]), + "command": frozenset(["hidden", "disabled", "checked", "default"]), + "hr": frozenset(["noshade"]), + "menu": frozenset(["autosubmit"]), + "fieldset": frozenset(["disabled", "readonly"]), + "option": frozenset(["disabled", "readonly", "selected"]), + "optgroup": frozenset(["disabled", "readonly"]), + "button": frozenset(["disabled", "autofocus"]), + "input": frozenset(["disabled", "readonly", "required", "autofocus", "checked", "ismap"]), + "select": frozenset(["disabled", "readonly", "autofocus", "multiple"]), + "output": frozenset(["disabled", "readonly"]), + "iframe": frozenset(["seamless"]), +} + +# entitiesWindows1252 has to be _ordered_ and needs to have an index. It +# therefore can't be a frozenset. +entitiesWindows1252 = ( + 8364, # 0x80 0x20AC EURO SIGN + 65533, # 0x81 UNDEFINED + 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK + 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK + 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK + 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS + 8224, # 0x86 0x2020 DAGGER + 8225, # 0x87 0x2021 DOUBLE DAGGER + 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT + 8240, # 0x89 0x2030 PER MILLE SIGN + 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON + 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE + 65533, # 0x8D UNDEFINED + 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON + 65533, # 0x8F UNDEFINED + 65533, # 0x90 UNDEFINED + 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK + 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK + 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK + 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK + 8226, # 0x95 0x2022 BULLET + 8211, # 0x96 0x2013 EN DASH + 8212, # 0x97 0x2014 EM DASH + 732, # 0x98 0x02DC SMALL TILDE + 8482, # 0x99 0x2122 TRADE MARK SIGN + 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON + 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE + 65533, # 0x9D UNDEFINED + 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON + 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS +) + +xmlEntities = frozenset(['lt;', 'gt;', 'amp;', 'apos;', 'quot;']) + +entities = { + "AElig": "\xc6", + "AElig;": "\xc6", + "AMP": "&", + "AMP;": "&", + "Aacute": "\xc1", + "Aacute;": "\xc1", + "Abreve;": "\u0102", + "Acirc": "\xc2", + "Acirc;": "\xc2", + "Acy;": "\u0410", + "Afr;": "\U0001d504", + "Agrave": "\xc0", + "Agrave;": "\xc0", + "Alpha;": "\u0391", + "Amacr;": "\u0100", + "And;": "\u2a53", + "Aogon;": "\u0104", + "Aopf;": "\U0001d538", + "ApplyFunction;": "\u2061", + "Aring": "\xc5", + "Aring;": "\xc5", + "Ascr;": "\U0001d49c", + "Assign;": "\u2254", + "Atilde": "\xc3", + "Atilde;": "\xc3", + "Auml": "\xc4", + "Auml;": "\xc4", + "Backslash;": "\u2216", + "Barv;": "\u2ae7", + "Barwed;": "\u2306", + "Bcy;": "\u0411", + "Because;": "\u2235", + "Bernoullis;": "\u212c", + "Beta;": "\u0392", + "Bfr;": "\U0001d505", + "Bopf;": "\U0001d539", + "Breve;": "\u02d8", + "Bscr;": "\u212c", + "Bumpeq;": "\u224e", + "CHcy;": "\u0427", + "COPY": "\xa9", + "COPY;": "\xa9", + "Cacute;": "\u0106", + "Cap;": "\u22d2", + "CapitalDifferentialD;": "\u2145", + "Cayleys;": "\u212d", + "Ccaron;": "\u010c", + "Ccedil": "\xc7", + "Ccedil;": "\xc7", + "Ccirc;": "\u0108", + "Cconint;": "\u2230", + "Cdot;": "\u010a", + "Cedilla;": "\xb8", + "CenterDot;": "\xb7", + "Cfr;": "\u212d", + "Chi;": "\u03a7", + "CircleDot;": "\u2299", + "CircleMinus;": "\u2296", + "CirclePlus;": "\u2295", + "CircleTimes;": "\u2297", + "ClockwiseContourIntegral;": "\u2232", + "CloseCurlyDoubleQuote;": "\u201d", + "CloseCurlyQuote;": "\u2019", + "Colon;": "\u2237", + "Colone;": "\u2a74", + "Congruent;": "\u2261", + "Conint;": "\u222f", + "ContourIntegral;": "\u222e", + "Copf;": "\u2102", + "Coproduct;": "\u2210", + "CounterClockwiseContourIntegral;": "\u2233", + "Cross;": "\u2a2f", + "Cscr;": "\U0001d49e", + "Cup;": "\u22d3", + "CupCap;": "\u224d", + "DD;": "\u2145", + "DDotrahd;": "\u2911", + "DJcy;": "\u0402", + "DScy;": "\u0405", + "DZcy;": "\u040f", + "Dagger;": "\u2021", + "Darr;": "\u21a1", + "Dashv;": "\u2ae4", + "Dcaron;": "\u010e", + "Dcy;": "\u0414", + "Del;": "\u2207", + "Delta;": "\u0394", + "Dfr;": "\U0001d507", + "DiacriticalAcute;": "\xb4", + "DiacriticalDot;": "\u02d9", + "DiacriticalDoubleAcute;": "\u02dd", + "DiacriticalGrave;": "`", + "DiacriticalTilde;": "\u02dc", + "Diamond;": "\u22c4", + "DifferentialD;": "\u2146", + "Dopf;": "\U0001d53b", + "Dot;": "\xa8", + "DotDot;": "\u20dc", + "DotEqual;": "\u2250", + "DoubleContourIntegral;": "\u222f", + "DoubleDot;": "\xa8", + "DoubleDownArrow;": "\u21d3", + "DoubleLeftArrow;": "\u21d0", + "DoubleLeftRightArrow;": "\u21d4", + "DoubleLeftTee;": "\u2ae4", + "DoubleLongLeftArrow;": "\u27f8", + "DoubleLongLeftRightArrow;": "\u27fa", + "DoubleLongRightArrow;": "\u27f9", + "DoubleRightArrow;": "\u21d2", + "DoubleRightTee;": "\u22a8", + "DoubleUpArrow;": "\u21d1", + "DoubleUpDownArrow;": "\u21d5", + "DoubleVerticalBar;": "\u2225", + "DownArrow;": "\u2193", + "DownArrowBar;": "\u2913", + "DownArrowUpArrow;": "\u21f5", + "DownBreve;": "\u0311", + "DownLeftRightVector;": "\u2950", + "DownLeftTeeVector;": "\u295e", + "DownLeftVector;": "\u21bd", + "DownLeftVectorBar;": "\u2956", + "DownRightTeeVector;": "\u295f", + "DownRightVector;": "\u21c1", + "DownRightVectorBar;": "\u2957", + "DownTee;": "\u22a4", + "DownTeeArrow;": "\u21a7", + "Downarrow;": "\u21d3", + "Dscr;": "\U0001d49f", + "Dstrok;": "\u0110", + "ENG;": "\u014a", + "ETH": "\xd0", + "ETH;": "\xd0", + "Eacute": "\xc9", + "Eacute;": "\xc9", + "Ecaron;": "\u011a", + "Ecirc": "\xca", + "Ecirc;": "\xca", + "Ecy;": "\u042d", + "Edot;": "\u0116", + "Efr;": "\U0001d508", + "Egrave": "\xc8", + "Egrave;": "\xc8", + "Element;": "\u2208", + "Emacr;": "\u0112", + "EmptySmallSquare;": "\u25fb", + "EmptyVerySmallSquare;": "\u25ab", + "Eogon;": "\u0118", + "Eopf;": "\U0001d53c", + "Epsilon;": "\u0395", + "Equal;": "\u2a75", + "EqualTilde;": "\u2242", + "Equilibrium;": "\u21cc", + "Escr;": "\u2130", + "Esim;": "\u2a73", + "Eta;": "\u0397", + "Euml": "\xcb", + "Euml;": "\xcb", + "Exists;": "\u2203", + "ExponentialE;": "\u2147", + "Fcy;": "\u0424", + "Ffr;": "\U0001d509", + "FilledSmallSquare;": "\u25fc", + "FilledVerySmallSquare;": "\u25aa", + "Fopf;": "\U0001d53d", + "ForAll;": "\u2200", + "Fouriertrf;": "\u2131", + "Fscr;": "\u2131", + "GJcy;": "\u0403", + "GT": ">", + "GT;": ">", + "Gamma;": "\u0393", + "Gammad;": "\u03dc", + "Gbreve;": "\u011e", + "Gcedil;": "\u0122", + "Gcirc;": "\u011c", + "Gcy;": "\u0413", + "Gdot;": "\u0120", + "Gfr;": "\U0001d50a", + "Gg;": "\u22d9", + "Gopf;": "\U0001d53e", + "GreaterEqual;": "\u2265", + "GreaterEqualLess;": "\u22db", + "GreaterFullEqual;": "\u2267", + "GreaterGreater;": "\u2aa2", + "GreaterLess;": "\u2277", + "GreaterSlantEqual;": "\u2a7e", + "GreaterTilde;": "\u2273", + "Gscr;": "\U0001d4a2", + "Gt;": "\u226b", + "HARDcy;": "\u042a", + "Hacek;": "\u02c7", + "Hat;": "^", + "Hcirc;": "\u0124", + "Hfr;": "\u210c", + "HilbertSpace;": "\u210b", + "Hopf;": "\u210d", + "HorizontalLine;": "\u2500", + "Hscr;": "\u210b", + "Hstrok;": "\u0126", + "HumpDownHump;": "\u224e", + "HumpEqual;": "\u224f", + "IEcy;": "\u0415", + "IJlig;": "\u0132", + "IOcy;": "\u0401", + "Iacute": "\xcd", + "Iacute;": "\xcd", + "Icirc": "\xce", + "Icirc;": "\xce", + "Icy;": "\u0418", + "Idot;": "\u0130", + "Ifr;": "\u2111", + "Igrave": "\xcc", + "Igrave;": "\xcc", + "Im;": "\u2111", + "Imacr;": "\u012a", + "ImaginaryI;": "\u2148", + "Implies;": "\u21d2", + "Int;": "\u222c", + "Integral;": "\u222b", + "Intersection;": "\u22c2", + "InvisibleComma;": "\u2063", + "InvisibleTimes;": "\u2062", + "Iogon;": "\u012e", + "Iopf;": "\U0001d540", + "Iota;": "\u0399", + "Iscr;": "\u2110", + "Itilde;": "\u0128", + "Iukcy;": "\u0406", + "Iuml": "\xcf", + "Iuml;": "\xcf", + "Jcirc;": "\u0134", + "Jcy;": "\u0419", + "Jfr;": "\U0001d50d", + "Jopf;": "\U0001d541", + "Jscr;": "\U0001d4a5", + "Jsercy;": "\u0408", + "Jukcy;": "\u0404", + "KHcy;": "\u0425", + "KJcy;": "\u040c", + "Kappa;": "\u039a", + "Kcedil;": "\u0136", + "Kcy;": "\u041a", + "Kfr;": "\U0001d50e", + "Kopf;": "\U0001d542", + "Kscr;": "\U0001d4a6", + "LJcy;": "\u0409", + "LT": "<", + "LT;": "<", + "Lacute;": "\u0139", + "Lambda;": "\u039b", + "Lang;": "\u27ea", + "Laplacetrf;": "\u2112", + "Larr;": "\u219e", + "Lcaron;": "\u013d", + "Lcedil;": "\u013b", + "Lcy;": "\u041b", + "LeftAngleBracket;": "\u27e8", + "LeftArrow;": "\u2190", + "LeftArrowBar;": "\u21e4", + "LeftArrowRightArrow;": "\u21c6", + "LeftCeiling;": "\u2308", + "LeftDoubleBracket;": "\u27e6", + "LeftDownTeeVector;": "\u2961", + "LeftDownVector;": "\u21c3", + "LeftDownVectorBar;": "\u2959", + "LeftFloor;": "\u230a", + "LeftRightArrow;": "\u2194", + "LeftRightVector;": "\u294e", + "LeftTee;": "\u22a3", + "LeftTeeArrow;": "\u21a4", + "LeftTeeVector;": "\u295a", + "LeftTriangle;": "\u22b2", + "LeftTriangleBar;": "\u29cf", + "LeftTriangleEqual;": "\u22b4", + "LeftUpDownVector;": "\u2951", + "LeftUpTeeVector;": "\u2960", + "LeftUpVector;": "\u21bf", + "LeftUpVectorBar;": "\u2958", + "LeftVector;": "\u21bc", + "LeftVectorBar;": "\u2952", + "Leftarrow;": "\u21d0", + "Leftrightarrow;": "\u21d4", + "LessEqualGreater;": "\u22da", + "LessFullEqual;": "\u2266", + "LessGreater;": "\u2276", + "LessLess;": "\u2aa1", + "LessSlantEqual;": "\u2a7d", + "LessTilde;": "\u2272", + "Lfr;": "\U0001d50f", + "Ll;": "\u22d8", + "Lleftarrow;": "\u21da", + "Lmidot;": "\u013f", + "LongLeftArrow;": "\u27f5", + "LongLeftRightArrow;": "\u27f7", + "LongRightArrow;": "\u27f6", + "Longleftarrow;": "\u27f8", + "Longleftrightarrow;": "\u27fa", + "Longrightarrow;": "\u27f9", + "Lopf;": "\U0001d543", + "LowerLeftArrow;": "\u2199", + "LowerRightArrow;": "\u2198", + "Lscr;": "\u2112", + "Lsh;": "\u21b0", + "Lstrok;": "\u0141", + "Lt;": "\u226a", + "Map;": "\u2905", + "Mcy;": "\u041c", + "MediumSpace;": "\u205f", + "Mellintrf;": "\u2133", + "Mfr;": "\U0001d510", + "MinusPlus;": "\u2213", + "Mopf;": "\U0001d544", + "Mscr;": "\u2133", + "Mu;": "\u039c", + "NJcy;": "\u040a", + "Nacute;": "\u0143", + "Ncaron;": "\u0147", + "Ncedil;": "\u0145", + "Ncy;": "\u041d", + "NegativeMediumSpace;": "\u200b", + "NegativeThickSpace;": "\u200b", + "NegativeThinSpace;": "\u200b", + "NegativeVeryThinSpace;": "\u200b", + "NestedGreaterGreater;": "\u226b", + "NestedLessLess;": "\u226a", + "NewLine;": "\n", + "Nfr;": "\U0001d511", + "NoBreak;": "\u2060", + "NonBreakingSpace;": "\xa0", + "Nopf;": "\u2115", + "Not;": "\u2aec", + "NotCongruent;": "\u2262", + "NotCupCap;": "\u226d", + "NotDoubleVerticalBar;": "\u2226", + "NotElement;": "\u2209", + "NotEqual;": "\u2260", + "NotEqualTilde;": "\u2242\u0338", + "NotExists;": "\u2204", + "NotGreater;": "\u226f", + "NotGreaterEqual;": "\u2271", + "NotGreaterFullEqual;": "\u2267\u0338", + "NotGreaterGreater;": "\u226b\u0338", + "NotGreaterLess;": "\u2279", + "NotGreaterSlantEqual;": "\u2a7e\u0338", + "NotGreaterTilde;": "\u2275", + "NotHumpDownHump;": "\u224e\u0338", + "NotHumpEqual;": "\u224f\u0338", + "NotLeftTriangle;": "\u22ea", + "NotLeftTriangleBar;": "\u29cf\u0338", + "NotLeftTriangleEqual;": "\u22ec", + "NotLess;": "\u226e", + "NotLessEqual;": "\u2270", + "NotLessGreater;": "\u2278", + "NotLessLess;": "\u226a\u0338", + "NotLessSlantEqual;": "\u2a7d\u0338", + "NotLessTilde;": "\u2274", + "NotNestedGreaterGreater;": "\u2aa2\u0338", + "NotNestedLessLess;": "\u2aa1\u0338", + "NotPrecedes;": "\u2280", + "NotPrecedesEqual;": "\u2aaf\u0338", + "NotPrecedesSlantEqual;": "\u22e0", + "NotReverseElement;": "\u220c", + "NotRightTriangle;": "\u22eb", + "NotRightTriangleBar;": "\u29d0\u0338", + "NotRightTriangleEqual;": "\u22ed", + "NotSquareSubset;": "\u228f\u0338", + "NotSquareSubsetEqual;": "\u22e2", + "NotSquareSuperset;": "\u2290\u0338", + "NotSquareSupersetEqual;": "\u22e3", + "NotSubset;": "\u2282\u20d2", + "NotSubsetEqual;": "\u2288", + "NotSucceeds;": "\u2281", + "NotSucceedsEqual;": "\u2ab0\u0338", + "NotSucceedsSlantEqual;": "\u22e1", + "NotSucceedsTilde;": "\u227f\u0338", + "NotSuperset;": "\u2283\u20d2", + "NotSupersetEqual;": "\u2289", + "NotTilde;": "\u2241", + "NotTildeEqual;": "\u2244", + "NotTildeFullEqual;": "\u2247", + "NotTildeTilde;": "\u2249", + "NotVerticalBar;": "\u2224", + "Nscr;": "\U0001d4a9", + "Ntilde": "\xd1", + "Ntilde;": "\xd1", + "Nu;": "\u039d", + "OElig;": "\u0152", + "Oacute": "\xd3", + "Oacute;": "\xd3", + "Ocirc": "\xd4", + "Ocirc;": "\xd4", + "Ocy;": "\u041e", + "Odblac;": "\u0150", + "Ofr;": "\U0001d512", + "Ograve": "\xd2", + "Ograve;": "\xd2", + "Omacr;": "\u014c", + "Omega;": "\u03a9", + "Omicron;": "\u039f", + "Oopf;": "\U0001d546", + "OpenCurlyDoubleQuote;": "\u201c", + "OpenCurlyQuote;": "\u2018", + "Or;": "\u2a54", + "Oscr;": "\U0001d4aa", + "Oslash": "\xd8", + "Oslash;": "\xd8", + "Otilde": "\xd5", + "Otilde;": "\xd5", + "Otimes;": "\u2a37", + "Ouml": "\xd6", + "Ouml;": "\xd6", + "OverBar;": "\u203e", + "OverBrace;": "\u23de", + "OverBracket;": "\u23b4", + "OverParenthesis;": "\u23dc", + "PartialD;": "\u2202", + "Pcy;": "\u041f", + "Pfr;": "\U0001d513", + "Phi;": "\u03a6", + "Pi;": "\u03a0", + "PlusMinus;": "\xb1", + "Poincareplane;": "\u210c", + "Popf;": "\u2119", + "Pr;": "\u2abb", + "Precedes;": "\u227a", + "PrecedesEqual;": "\u2aaf", + "PrecedesSlantEqual;": "\u227c", + "PrecedesTilde;": "\u227e", + "Prime;": "\u2033", + "Product;": "\u220f", + "Proportion;": "\u2237", + "Proportional;": "\u221d", + "Pscr;": "\U0001d4ab", + "Psi;": "\u03a8", + "QUOT": "\"", + "QUOT;": "\"", + "Qfr;": "\U0001d514", + "Qopf;": "\u211a", + "Qscr;": "\U0001d4ac", + "RBarr;": "\u2910", + "REG": "\xae", + "REG;": "\xae", + "Racute;": "\u0154", + "Rang;": "\u27eb", + "Rarr;": "\u21a0", + "Rarrtl;": "\u2916", + "Rcaron;": "\u0158", + "Rcedil;": "\u0156", + "Rcy;": "\u0420", + "Re;": "\u211c", + "ReverseElement;": "\u220b", + "ReverseEquilibrium;": "\u21cb", + "ReverseUpEquilibrium;": "\u296f", + "Rfr;": "\u211c", + "Rho;": "\u03a1", + "RightAngleBracket;": "\u27e9", + "RightArrow;": "\u2192", + "RightArrowBar;": "\u21e5", + "RightArrowLeftArrow;": "\u21c4", + "RightCeiling;": "\u2309", + "RightDoubleBracket;": "\u27e7", + "RightDownTeeVector;": "\u295d", + "RightDownVector;": "\u21c2", + "RightDownVectorBar;": "\u2955", + "RightFloor;": "\u230b", + "RightTee;": "\u22a2", + "RightTeeArrow;": "\u21a6", + "RightTeeVector;": "\u295b", + "RightTriangle;": "\u22b3", + "RightTriangleBar;": "\u29d0", + "RightTriangleEqual;": "\u22b5", + "RightUpDownVector;": "\u294f", + "RightUpTeeVector;": "\u295c", + "RightUpVector;": "\u21be", + "RightUpVectorBar;": "\u2954", + "RightVector;": "\u21c0", + "RightVectorBar;": "\u2953", + "Rightarrow;": "\u21d2", + "Ropf;": "\u211d", + "RoundImplies;": "\u2970", + "Rrightarrow;": "\u21db", + "Rscr;": "\u211b", + "Rsh;": "\u21b1", + "RuleDelayed;": "\u29f4", + "SHCHcy;": "\u0429", + "SHcy;": "\u0428", + "SOFTcy;": "\u042c", + "Sacute;": "\u015a", + "Sc;": "\u2abc", + "Scaron;": "\u0160", + "Scedil;": "\u015e", + "Scirc;": "\u015c", + "Scy;": "\u0421", + "Sfr;": "\U0001d516", + "ShortDownArrow;": "\u2193", + "ShortLeftArrow;": "\u2190", + "ShortRightArrow;": "\u2192", + "ShortUpArrow;": "\u2191", + "Sigma;": "\u03a3", + "SmallCircle;": "\u2218", + "Sopf;": "\U0001d54a", + "Sqrt;": "\u221a", + "Square;": "\u25a1", + "SquareIntersection;": "\u2293", + "SquareSubset;": "\u228f", + "SquareSubsetEqual;": "\u2291", + "SquareSuperset;": "\u2290", + "SquareSupersetEqual;": "\u2292", + "SquareUnion;": "\u2294", + "Sscr;": "\U0001d4ae", + "Star;": "\u22c6", + "Sub;": "\u22d0", + "Subset;": "\u22d0", + "SubsetEqual;": "\u2286", + "Succeeds;": "\u227b", + "SucceedsEqual;": "\u2ab0", + "SucceedsSlantEqual;": "\u227d", + "SucceedsTilde;": "\u227f", + "SuchThat;": "\u220b", + "Sum;": "\u2211", + "Sup;": "\u22d1", + "Superset;": "\u2283", + "SupersetEqual;": "\u2287", + "Supset;": "\u22d1", + "THORN": "\xde", + "THORN;": "\xde", + "TRADE;": "\u2122", + "TSHcy;": "\u040b", + "TScy;": "\u0426", + "Tab;": "\t", + "Tau;": "\u03a4", + "Tcaron;": "\u0164", + "Tcedil;": "\u0162", + "Tcy;": "\u0422", + "Tfr;": "\U0001d517", + "Therefore;": "\u2234", + "Theta;": "\u0398", + "ThickSpace;": "\u205f\u200a", + "ThinSpace;": "\u2009", + "Tilde;": "\u223c", + "TildeEqual;": "\u2243", + "TildeFullEqual;": "\u2245", + "TildeTilde;": "\u2248", + "Topf;": "\U0001d54b", + "TripleDot;": "\u20db", + "Tscr;": "\U0001d4af", + "Tstrok;": "\u0166", + "Uacute": "\xda", + "Uacute;": "\xda", + "Uarr;": "\u219f", + "Uarrocir;": "\u2949", + "Ubrcy;": "\u040e", + "Ubreve;": "\u016c", + "Ucirc": "\xdb", + "Ucirc;": "\xdb", + "Ucy;": "\u0423", + "Udblac;": "\u0170", + "Ufr;": "\U0001d518", + "Ugrave": "\xd9", + "Ugrave;": "\xd9", + "Umacr;": "\u016a", + "UnderBar;": "_", + "UnderBrace;": "\u23df", + "UnderBracket;": "\u23b5", + "UnderParenthesis;": "\u23dd", + "Union;": "\u22c3", + "UnionPlus;": "\u228e", + "Uogon;": "\u0172", + "Uopf;": "\U0001d54c", + "UpArrow;": "\u2191", + "UpArrowBar;": "\u2912", + "UpArrowDownArrow;": "\u21c5", + "UpDownArrow;": "\u2195", + "UpEquilibrium;": "\u296e", + "UpTee;": "\u22a5", + "UpTeeArrow;": "\u21a5", + "Uparrow;": "\u21d1", + "Updownarrow;": "\u21d5", + "UpperLeftArrow;": "\u2196", + "UpperRightArrow;": "\u2197", + "Upsi;": "\u03d2", + "Upsilon;": "\u03a5", + "Uring;": "\u016e", + "Uscr;": "\U0001d4b0", + "Utilde;": "\u0168", + "Uuml": "\xdc", + "Uuml;": "\xdc", + "VDash;": "\u22ab", + "Vbar;": "\u2aeb", + "Vcy;": "\u0412", + "Vdash;": "\u22a9", + "Vdashl;": "\u2ae6", + "Vee;": "\u22c1", + "Verbar;": "\u2016", + "Vert;": "\u2016", + "VerticalBar;": "\u2223", + "VerticalLine;": "|", + "VerticalSeparator;": "\u2758", + "VerticalTilde;": "\u2240", + "VeryThinSpace;": "\u200a", + "Vfr;": "\U0001d519", + "Vopf;": "\U0001d54d", + "Vscr;": "\U0001d4b1", + "Vvdash;": "\u22aa", + "Wcirc;": "\u0174", + "Wedge;": "\u22c0", + "Wfr;": "\U0001d51a", + "Wopf;": "\U0001d54e", + "Wscr;": "\U0001d4b2", + "Xfr;": "\U0001d51b", + "Xi;": "\u039e", + "Xopf;": "\U0001d54f", + "Xscr;": "\U0001d4b3", + "YAcy;": "\u042f", + "YIcy;": "\u0407", + "YUcy;": "\u042e", + "Yacute": "\xdd", + "Yacute;": "\xdd", + "Ycirc;": "\u0176", + "Ycy;": "\u042b", + "Yfr;": "\U0001d51c", + "Yopf;": "\U0001d550", + "Yscr;": "\U0001d4b4", + "Yuml;": "\u0178", + "ZHcy;": "\u0416", + "Zacute;": "\u0179", + "Zcaron;": "\u017d", + "Zcy;": "\u0417", + "Zdot;": "\u017b", + "ZeroWidthSpace;": "\u200b", + "Zeta;": "\u0396", + "Zfr;": "\u2128", + "Zopf;": "\u2124", + "Zscr;": "\U0001d4b5", + "aacute": "\xe1", + "aacute;": "\xe1", + "abreve;": "\u0103", + "ac;": "\u223e", + "acE;": "\u223e\u0333", + "acd;": "\u223f", + "acirc": "\xe2", + "acirc;": "\xe2", + "acute": "\xb4", + "acute;": "\xb4", + "acy;": "\u0430", + "aelig": "\xe6", + "aelig;": "\xe6", + "af;": "\u2061", + "afr;": "\U0001d51e", + "agrave": "\xe0", + "agrave;": "\xe0", + "alefsym;": "\u2135", + "aleph;": "\u2135", + "alpha;": "\u03b1", + "amacr;": "\u0101", + "amalg;": "\u2a3f", + "amp": "&", + "amp;": "&", + "and;": "\u2227", + "andand;": "\u2a55", + "andd;": "\u2a5c", + "andslope;": "\u2a58", + "andv;": "\u2a5a", + "ang;": "\u2220", + "ange;": "\u29a4", + "angle;": "\u2220", + "angmsd;": "\u2221", + "angmsdaa;": "\u29a8", + "angmsdab;": "\u29a9", + "angmsdac;": "\u29aa", + "angmsdad;": "\u29ab", + "angmsdae;": "\u29ac", + "angmsdaf;": "\u29ad", + "angmsdag;": "\u29ae", + "angmsdah;": "\u29af", + "angrt;": "\u221f", + "angrtvb;": "\u22be", + "angrtvbd;": "\u299d", + "angsph;": "\u2222", + "angst;": "\xc5", + "angzarr;": "\u237c", + "aogon;": "\u0105", + "aopf;": "\U0001d552", + "ap;": "\u2248", + "apE;": "\u2a70", + "apacir;": "\u2a6f", + "ape;": "\u224a", + "apid;": "\u224b", + "apos;": "'", + "approx;": "\u2248", + "approxeq;": "\u224a", + "aring": "\xe5", + "aring;": "\xe5", + "ascr;": "\U0001d4b6", + "ast;": "*", + "asymp;": "\u2248", + "asympeq;": "\u224d", + "atilde": "\xe3", + "atilde;": "\xe3", + "auml": "\xe4", + "auml;": "\xe4", + "awconint;": "\u2233", + "awint;": "\u2a11", + "bNot;": "\u2aed", + "backcong;": "\u224c", + "backepsilon;": "\u03f6", + "backprime;": "\u2035", + "backsim;": "\u223d", + "backsimeq;": "\u22cd", + "barvee;": "\u22bd", + "barwed;": "\u2305", + "barwedge;": "\u2305", + "bbrk;": "\u23b5", + "bbrktbrk;": "\u23b6", + "bcong;": "\u224c", + "bcy;": "\u0431", + "bdquo;": "\u201e", + "becaus;": "\u2235", + "because;": "\u2235", + "bemptyv;": "\u29b0", + "bepsi;": "\u03f6", + "bernou;": "\u212c", + "beta;": "\u03b2", + "beth;": "\u2136", + "between;": "\u226c", + "bfr;": "\U0001d51f", + "bigcap;": "\u22c2", + "bigcirc;": "\u25ef", + "bigcup;": "\u22c3", + "bigodot;": "\u2a00", + "bigoplus;": "\u2a01", + "bigotimes;": "\u2a02", + "bigsqcup;": "\u2a06", + "bigstar;": "\u2605", + "bigtriangledown;": "\u25bd", + "bigtriangleup;": "\u25b3", + "biguplus;": "\u2a04", + "bigvee;": "\u22c1", + "bigwedge;": "\u22c0", + "bkarow;": "\u290d", + "blacklozenge;": "\u29eb", + "blacksquare;": "\u25aa", + "blacktriangle;": "\u25b4", + "blacktriangledown;": "\u25be", + "blacktriangleleft;": "\u25c2", + "blacktriangleright;": "\u25b8", + "blank;": "\u2423", + "blk12;": "\u2592", + "blk14;": "\u2591", + "blk34;": "\u2593", + "block;": "\u2588", + "bne;": "=\u20e5", + "bnequiv;": "\u2261\u20e5", + "bnot;": "\u2310", + "bopf;": "\U0001d553", + "bot;": "\u22a5", + "bottom;": "\u22a5", + "bowtie;": "\u22c8", + "boxDL;": "\u2557", + "boxDR;": "\u2554", + "boxDl;": "\u2556", + "boxDr;": "\u2553", + "boxH;": "\u2550", + "boxHD;": "\u2566", + "boxHU;": "\u2569", + "boxHd;": "\u2564", + "boxHu;": "\u2567", + "boxUL;": "\u255d", + "boxUR;": "\u255a", + "boxUl;": "\u255c", + "boxUr;": "\u2559", + "boxV;": "\u2551", + "boxVH;": "\u256c", + "boxVL;": "\u2563", + "boxVR;": "\u2560", + "boxVh;": "\u256b", + "boxVl;": "\u2562", + "boxVr;": "\u255f", + "boxbox;": "\u29c9", + "boxdL;": "\u2555", + "boxdR;": "\u2552", + "boxdl;": "\u2510", + "boxdr;": "\u250c", + "boxh;": "\u2500", + "boxhD;": "\u2565", + "boxhU;": "\u2568", + "boxhd;": "\u252c", + "boxhu;": "\u2534", + "boxminus;": "\u229f", + "boxplus;": "\u229e", + "boxtimes;": "\u22a0", + "boxuL;": "\u255b", + "boxuR;": "\u2558", + "boxul;": "\u2518", + "boxur;": "\u2514", + "boxv;": "\u2502", + "boxvH;": "\u256a", + "boxvL;": "\u2561", + "boxvR;": "\u255e", + "boxvh;": "\u253c", + "boxvl;": "\u2524", + "boxvr;": "\u251c", + "bprime;": "\u2035", + "breve;": "\u02d8", + "brvbar": "\xa6", + "brvbar;": "\xa6", + "bscr;": "\U0001d4b7", + "bsemi;": "\u204f", + "bsim;": "\u223d", + "bsime;": "\u22cd", + "bsol;": "\\", + "bsolb;": "\u29c5", + "bsolhsub;": "\u27c8", + "bull;": "\u2022", + "bullet;": "\u2022", + "bump;": "\u224e", + "bumpE;": "\u2aae", + "bumpe;": "\u224f", + "bumpeq;": "\u224f", + "cacute;": "\u0107", + "cap;": "\u2229", + "capand;": "\u2a44", + "capbrcup;": "\u2a49", + "capcap;": "\u2a4b", + "capcup;": "\u2a47", + "capdot;": "\u2a40", + "caps;": "\u2229\ufe00", + "caret;": "\u2041", + "caron;": "\u02c7", + "ccaps;": "\u2a4d", + "ccaron;": "\u010d", + "ccedil": "\xe7", + "ccedil;": "\xe7", + "ccirc;": "\u0109", + "ccups;": "\u2a4c", + "ccupssm;": "\u2a50", + "cdot;": "\u010b", + "cedil": "\xb8", + "cedil;": "\xb8", + "cemptyv;": "\u29b2", + "cent": "\xa2", + "cent;": "\xa2", + "centerdot;": "\xb7", + "cfr;": "\U0001d520", + "chcy;": "\u0447", + "check;": "\u2713", + "checkmark;": "\u2713", + "chi;": "\u03c7", + "cir;": "\u25cb", + "cirE;": "\u29c3", + "circ;": "\u02c6", + "circeq;": "\u2257", + "circlearrowleft;": "\u21ba", + "circlearrowright;": "\u21bb", + "circledR;": "\xae", + "circledS;": "\u24c8", + "circledast;": "\u229b", + "circledcirc;": "\u229a", + "circleddash;": "\u229d", + "cire;": "\u2257", + "cirfnint;": "\u2a10", + "cirmid;": "\u2aef", + "cirscir;": "\u29c2", + "clubs;": "\u2663", + "clubsuit;": "\u2663", + "colon;": ":", + "colone;": "\u2254", + "coloneq;": "\u2254", + "comma;": ",", + "commat;": "@", + "comp;": "\u2201", + "compfn;": "\u2218", + "complement;": "\u2201", + "complexes;": "\u2102", + "cong;": "\u2245", + "congdot;": "\u2a6d", + "conint;": "\u222e", + "copf;": "\U0001d554", + "coprod;": "\u2210", + "copy": "\xa9", + "copy;": "\xa9", + "copysr;": "\u2117", + "crarr;": "\u21b5", + "cross;": "\u2717", + "cscr;": "\U0001d4b8", + "csub;": "\u2acf", + "csube;": "\u2ad1", + "csup;": "\u2ad0", + "csupe;": "\u2ad2", + "ctdot;": "\u22ef", + "cudarrl;": "\u2938", + "cudarrr;": "\u2935", + "cuepr;": "\u22de", + "cuesc;": "\u22df", + "cularr;": "\u21b6", + "cularrp;": "\u293d", + "cup;": "\u222a", + "cupbrcap;": "\u2a48", + "cupcap;": "\u2a46", + "cupcup;": "\u2a4a", + "cupdot;": "\u228d", + "cupor;": "\u2a45", + "cups;": "\u222a\ufe00", + "curarr;": "\u21b7", + "curarrm;": "\u293c", + "curlyeqprec;": "\u22de", + "curlyeqsucc;": "\u22df", + "curlyvee;": "\u22ce", + "curlywedge;": "\u22cf", + "curren": "\xa4", + "curren;": "\xa4", + "curvearrowleft;": "\u21b6", + "curvearrowright;": "\u21b7", + "cuvee;": "\u22ce", + "cuwed;": "\u22cf", + "cwconint;": "\u2232", + "cwint;": "\u2231", + "cylcty;": "\u232d", + "dArr;": "\u21d3", + "dHar;": "\u2965", + "dagger;": "\u2020", + "daleth;": "\u2138", + "darr;": "\u2193", + "dash;": "\u2010", + "dashv;": "\u22a3", + "dbkarow;": "\u290f", + "dblac;": "\u02dd", + "dcaron;": "\u010f", + "dcy;": "\u0434", + "dd;": "\u2146", + "ddagger;": "\u2021", + "ddarr;": "\u21ca", + "ddotseq;": "\u2a77", + "deg": "\xb0", + "deg;": "\xb0", + "delta;": "\u03b4", + "demptyv;": "\u29b1", + "dfisht;": "\u297f", + "dfr;": "\U0001d521", + "dharl;": "\u21c3", + "dharr;": "\u21c2", + "diam;": "\u22c4", + "diamond;": "\u22c4", + "diamondsuit;": "\u2666", + "diams;": "\u2666", + "die;": "\xa8", + "digamma;": "\u03dd", + "disin;": "\u22f2", + "div;": "\xf7", + "divide": "\xf7", + "divide;": "\xf7", + "divideontimes;": "\u22c7", + "divonx;": "\u22c7", + "djcy;": "\u0452", + "dlcorn;": "\u231e", + "dlcrop;": "\u230d", + "dollar;": "$", + "dopf;": "\U0001d555", + "dot;": "\u02d9", + "doteq;": "\u2250", + "doteqdot;": "\u2251", + "dotminus;": "\u2238", + "dotplus;": "\u2214", + "dotsquare;": "\u22a1", + "doublebarwedge;": "\u2306", + "downarrow;": "\u2193", + "downdownarrows;": "\u21ca", + "downharpoonleft;": "\u21c3", + "downharpoonright;": "\u21c2", + "drbkarow;": "\u2910", + "drcorn;": "\u231f", + "drcrop;": "\u230c", + "dscr;": "\U0001d4b9", + "dscy;": "\u0455", + "dsol;": "\u29f6", + "dstrok;": "\u0111", + "dtdot;": "\u22f1", + "dtri;": "\u25bf", + "dtrif;": "\u25be", + "duarr;": "\u21f5", + "duhar;": "\u296f", + "dwangle;": "\u29a6", + "dzcy;": "\u045f", + "dzigrarr;": "\u27ff", + "eDDot;": "\u2a77", + "eDot;": "\u2251", + "eacute": "\xe9", + "eacute;": "\xe9", + "easter;": "\u2a6e", + "ecaron;": "\u011b", + "ecir;": "\u2256", + "ecirc": "\xea", + "ecirc;": "\xea", + "ecolon;": "\u2255", + "ecy;": "\u044d", + "edot;": "\u0117", + "ee;": "\u2147", + "efDot;": "\u2252", + "efr;": "\U0001d522", + "eg;": "\u2a9a", + "egrave": "\xe8", + "egrave;": "\xe8", + "egs;": "\u2a96", + "egsdot;": "\u2a98", + "el;": "\u2a99", + "elinters;": "\u23e7", + "ell;": "\u2113", + "els;": "\u2a95", + "elsdot;": "\u2a97", + "emacr;": "\u0113", + "empty;": "\u2205", + "emptyset;": "\u2205", + "emptyv;": "\u2205", + "emsp13;": "\u2004", + "emsp14;": "\u2005", + "emsp;": "\u2003", + "eng;": "\u014b", + "ensp;": "\u2002", + "eogon;": "\u0119", + "eopf;": "\U0001d556", + "epar;": "\u22d5", + "eparsl;": "\u29e3", + "eplus;": "\u2a71", + "epsi;": "\u03b5", + "epsilon;": "\u03b5", + "epsiv;": "\u03f5", + "eqcirc;": "\u2256", + "eqcolon;": "\u2255", + "eqsim;": "\u2242", + "eqslantgtr;": "\u2a96", + "eqslantless;": "\u2a95", + "equals;": "=", + "equest;": "\u225f", + "equiv;": "\u2261", + "equivDD;": "\u2a78", + "eqvparsl;": "\u29e5", + "erDot;": "\u2253", + "erarr;": "\u2971", + "escr;": "\u212f", + "esdot;": "\u2250", + "esim;": "\u2242", + "eta;": "\u03b7", + "eth": "\xf0", + "eth;": "\xf0", + "euml": "\xeb", + "euml;": "\xeb", + "euro;": "\u20ac", + "excl;": "!", + "exist;": "\u2203", + "expectation;": "\u2130", + "exponentiale;": "\u2147", + "fallingdotseq;": "\u2252", + "fcy;": "\u0444", + "female;": "\u2640", + "ffilig;": "\ufb03", + "fflig;": "\ufb00", + "ffllig;": "\ufb04", + "ffr;": "\U0001d523", + "filig;": "\ufb01", + "fjlig;": "fj", + "flat;": "\u266d", + "fllig;": "\ufb02", + "fltns;": "\u25b1", + "fnof;": "\u0192", + "fopf;": "\U0001d557", + "forall;": "\u2200", + "fork;": "\u22d4", + "forkv;": "\u2ad9", + "fpartint;": "\u2a0d", + "frac12": "\xbd", + "frac12;": "\xbd", + "frac13;": "\u2153", + "frac14": "\xbc", + "frac14;": "\xbc", + "frac15;": "\u2155", + "frac16;": "\u2159", + "frac18;": "\u215b", + "frac23;": "\u2154", + "frac25;": "\u2156", + "frac34": "\xbe", + "frac34;": "\xbe", + "frac35;": "\u2157", + "frac38;": "\u215c", + "frac45;": "\u2158", + "frac56;": "\u215a", + "frac58;": "\u215d", + "frac78;": "\u215e", + "frasl;": "\u2044", + "frown;": "\u2322", + "fscr;": "\U0001d4bb", + "gE;": "\u2267", + "gEl;": "\u2a8c", + "gacute;": "\u01f5", + "gamma;": "\u03b3", + "gammad;": "\u03dd", + "gap;": "\u2a86", + "gbreve;": "\u011f", + "gcirc;": "\u011d", + "gcy;": "\u0433", + "gdot;": "\u0121", + "ge;": "\u2265", + "gel;": "\u22db", + "geq;": "\u2265", + "geqq;": "\u2267", + "geqslant;": "\u2a7e", + "ges;": "\u2a7e", + "gescc;": "\u2aa9", + "gesdot;": "\u2a80", + "gesdoto;": "\u2a82", + "gesdotol;": "\u2a84", + "gesl;": "\u22db\ufe00", + "gesles;": "\u2a94", + "gfr;": "\U0001d524", + "gg;": "\u226b", + "ggg;": "\u22d9", + "gimel;": "\u2137", + "gjcy;": "\u0453", + "gl;": "\u2277", + "glE;": "\u2a92", + "gla;": "\u2aa5", + "glj;": "\u2aa4", + "gnE;": "\u2269", + "gnap;": "\u2a8a", + "gnapprox;": "\u2a8a", + "gne;": "\u2a88", + "gneq;": "\u2a88", + "gneqq;": "\u2269", + "gnsim;": "\u22e7", + "gopf;": "\U0001d558", + "grave;": "`", + "gscr;": "\u210a", + "gsim;": "\u2273", + "gsime;": "\u2a8e", + "gsiml;": "\u2a90", + "gt": ">", + "gt;": ">", + "gtcc;": "\u2aa7", + "gtcir;": "\u2a7a", + "gtdot;": "\u22d7", + "gtlPar;": "\u2995", + "gtquest;": "\u2a7c", + "gtrapprox;": "\u2a86", + "gtrarr;": "\u2978", + "gtrdot;": "\u22d7", + "gtreqless;": "\u22db", + "gtreqqless;": "\u2a8c", + "gtrless;": "\u2277", + "gtrsim;": "\u2273", + "gvertneqq;": "\u2269\ufe00", + "gvnE;": "\u2269\ufe00", + "hArr;": "\u21d4", + "hairsp;": "\u200a", + "half;": "\xbd", + "hamilt;": "\u210b", + "hardcy;": "\u044a", + "harr;": "\u2194", + "harrcir;": "\u2948", + "harrw;": "\u21ad", + "hbar;": "\u210f", + "hcirc;": "\u0125", + "hearts;": "\u2665", + "heartsuit;": "\u2665", + "hellip;": "\u2026", + "hercon;": "\u22b9", + "hfr;": "\U0001d525", + "hksearow;": "\u2925", + "hkswarow;": "\u2926", + "hoarr;": "\u21ff", + "homtht;": "\u223b", + "hookleftarrow;": "\u21a9", + "hookrightarrow;": "\u21aa", + "hopf;": "\U0001d559", + "horbar;": "\u2015", + "hscr;": "\U0001d4bd", + "hslash;": "\u210f", + "hstrok;": "\u0127", + "hybull;": "\u2043", + "hyphen;": "\u2010", + "iacute": "\xed", + "iacute;": "\xed", + "ic;": "\u2063", + "icirc": "\xee", + "icirc;": "\xee", + "icy;": "\u0438", + "iecy;": "\u0435", + "iexcl": "\xa1", + "iexcl;": "\xa1", + "iff;": "\u21d4", + "ifr;": "\U0001d526", + "igrave": "\xec", + "igrave;": "\xec", + "ii;": "\u2148", + "iiiint;": "\u2a0c", + "iiint;": "\u222d", + "iinfin;": "\u29dc", + "iiota;": "\u2129", + "ijlig;": "\u0133", + "imacr;": "\u012b", + "image;": "\u2111", + "imagline;": "\u2110", + "imagpart;": "\u2111", + "imath;": "\u0131", + "imof;": "\u22b7", + "imped;": "\u01b5", + "in;": "\u2208", + "incare;": "\u2105", + "infin;": "\u221e", + "infintie;": "\u29dd", + "inodot;": "\u0131", + "int;": "\u222b", + "intcal;": "\u22ba", + "integers;": "\u2124", + "intercal;": "\u22ba", + "intlarhk;": "\u2a17", + "intprod;": "\u2a3c", + "iocy;": "\u0451", + "iogon;": "\u012f", + "iopf;": "\U0001d55a", + "iota;": "\u03b9", + "iprod;": "\u2a3c", + "iquest": "\xbf", + "iquest;": "\xbf", + "iscr;": "\U0001d4be", + "isin;": "\u2208", + "isinE;": "\u22f9", + "isindot;": "\u22f5", + "isins;": "\u22f4", + "isinsv;": "\u22f3", + "isinv;": "\u2208", + "it;": "\u2062", + "itilde;": "\u0129", + "iukcy;": "\u0456", + "iuml": "\xef", + "iuml;": "\xef", + "jcirc;": "\u0135", + "jcy;": "\u0439", + "jfr;": "\U0001d527", + "jmath;": "\u0237", + "jopf;": "\U0001d55b", + "jscr;": "\U0001d4bf", + "jsercy;": "\u0458", + "jukcy;": "\u0454", + "kappa;": "\u03ba", + "kappav;": "\u03f0", + "kcedil;": "\u0137", + "kcy;": "\u043a", + "kfr;": "\U0001d528", + "kgreen;": "\u0138", + "khcy;": "\u0445", + "kjcy;": "\u045c", + "kopf;": "\U0001d55c", + "kscr;": "\U0001d4c0", + "lAarr;": "\u21da", + "lArr;": "\u21d0", + "lAtail;": "\u291b", + "lBarr;": "\u290e", + "lE;": "\u2266", + "lEg;": "\u2a8b", + "lHar;": "\u2962", + "lacute;": "\u013a", + "laemptyv;": "\u29b4", + "lagran;": "\u2112", + "lambda;": "\u03bb", + "lang;": "\u27e8", + "langd;": "\u2991", + "langle;": "\u27e8", + "lap;": "\u2a85", + "laquo": "\xab", + "laquo;": "\xab", + "larr;": "\u2190", + "larrb;": "\u21e4", + "larrbfs;": "\u291f", + "larrfs;": "\u291d", + "larrhk;": "\u21a9", + "larrlp;": "\u21ab", + "larrpl;": "\u2939", + "larrsim;": "\u2973", + "larrtl;": "\u21a2", + "lat;": "\u2aab", + "latail;": "\u2919", + "late;": "\u2aad", + "lates;": "\u2aad\ufe00", + "lbarr;": "\u290c", + "lbbrk;": "\u2772", + "lbrace;": "{", + "lbrack;": "[", + "lbrke;": "\u298b", + "lbrksld;": "\u298f", + "lbrkslu;": "\u298d", + "lcaron;": "\u013e", + "lcedil;": "\u013c", + "lceil;": "\u2308", + "lcub;": "{", + "lcy;": "\u043b", + "ldca;": "\u2936", + "ldquo;": "\u201c", + "ldquor;": "\u201e", + "ldrdhar;": "\u2967", + "ldrushar;": "\u294b", + "ldsh;": "\u21b2", + "le;": "\u2264", + "leftarrow;": "\u2190", + "leftarrowtail;": "\u21a2", + "leftharpoondown;": "\u21bd", + "leftharpoonup;": "\u21bc", + "leftleftarrows;": "\u21c7", + "leftrightarrow;": "\u2194", + "leftrightarrows;": "\u21c6", + "leftrightharpoons;": "\u21cb", + "leftrightsquigarrow;": "\u21ad", + "leftthreetimes;": "\u22cb", + "leg;": "\u22da", + "leq;": "\u2264", + "leqq;": "\u2266", + "leqslant;": "\u2a7d", + "les;": "\u2a7d", + "lescc;": "\u2aa8", + "lesdot;": "\u2a7f", + "lesdoto;": "\u2a81", + "lesdotor;": "\u2a83", + "lesg;": "\u22da\ufe00", + "lesges;": "\u2a93", + "lessapprox;": "\u2a85", + "lessdot;": "\u22d6", + "lesseqgtr;": "\u22da", + "lesseqqgtr;": "\u2a8b", + "lessgtr;": "\u2276", + "lesssim;": "\u2272", + "lfisht;": "\u297c", + "lfloor;": "\u230a", + "lfr;": "\U0001d529", + "lg;": "\u2276", + "lgE;": "\u2a91", + "lhard;": "\u21bd", + "lharu;": "\u21bc", + "lharul;": "\u296a", + "lhblk;": "\u2584", + "ljcy;": "\u0459", + "ll;": "\u226a", + "llarr;": "\u21c7", + "llcorner;": "\u231e", + "llhard;": "\u296b", + "lltri;": "\u25fa", + "lmidot;": "\u0140", + "lmoust;": "\u23b0", + "lmoustache;": "\u23b0", + "lnE;": "\u2268", + "lnap;": "\u2a89", + "lnapprox;": "\u2a89", + "lne;": "\u2a87", + "lneq;": "\u2a87", + "lneqq;": "\u2268", + "lnsim;": "\u22e6", + "loang;": "\u27ec", + "loarr;": "\u21fd", + "lobrk;": "\u27e6", + "longleftarrow;": "\u27f5", + "longleftrightarrow;": "\u27f7", + "longmapsto;": "\u27fc", + "longrightarrow;": "\u27f6", + "looparrowleft;": "\u21ab", + "looparrowright;": "\u21ac", + "lopar;": "\u2985", + "lopf;": "\U0001d55d", + "loplus;": "\u2a2d", + "lotimes;": "\u2a34", + "lowast;": "\u2217", + "lowbar;": "_", + "loz;": "\u25ca", + "lozenge;": "\u25ca", + "lozf;": "\u29eb", + "lpar;": "(", + "lparlt;": "\u2993", + "lrarr;": "\u21c6", + "lrcorner;": "\u231f", + "lrhar;": "\u21cb", + "lrhard;": "\u296d", + "lrm;": "\u200e", + "lrtri;": "\u22bf", + "lsaquo;": "\u2039", + "lscr;": "\U0001d4c1", + "lsh;": "\u21b0", + "lsim;": "\u2272", + "lsime;": "\u2a8d", + "lsimg;": "\u2a8f", + "lsqb;": "[", + "lsquo;": "\u2018", + "lsquor;": "\u201a", + "lstrok;": "\u0142", + "lt": "<", + "lt;": "<", + "ltcc;": "\u2aa6", + "ltcir;": "\u2a79", + "ltdot;": "\u22d6", + "lthree;": "\u22cb", + "ltimes;": "\u22c9", + "ltlarr;": "\u2976", + "ltquest;": "\u2a7b", + "ltrPar;": "\u2996", + "ltri;": "\u25c3", + "ltrie;": "\u22b4", + "ltrif;": "\u25c2", + "lurdshar;": "\u294a", + "luruhar;": "\u2966", + "lvertneqq;": "\u2268\ufe00", + "lvnE;": "\u2268\ufe00", + "mDDot;": "\u223a", + "macr": "\xaf", + "macr;": "\xaf", + "male;": "\u2642", + "malt;": "\u2720", + "maltese;": "\u2720", + "map;": "\u21a6", + "mapsto;": "\u21a6", + "mapstodown;": "\u21a7", + "mapstoleft;": "\u21a4", + "mapstoup;": "\u21a5", + "marker;": "\u25ae", + "mcomma;": "\u2a29", + "mcy;": "\u043c", + "mdash;": "\u2014", + "measuredangle;": "\u2221", + "mfr;": "\U0001d52a", + "mho;": "\u2127", + "micro": "\xb5", + "micro;": "\xb5", + "mid;": "\u2223", + "midast;": "*", + "midcir;": "\u2af0", + "middot": "\xb7", + "middot;": "\xb7", + "minus;": "\u2212", + "minusb;": "\u229f", + "minusd;": "\u2238", + "minusdu;": "\u2a2a", + "mlcp;": "\u2adb", + "mldr;": "\u2026", + "mnplus;": "\u2213", + "models;": "\u22a7", + "mopf;": "\U0001d55e", + "mp;": "\u2213", + "mscr;": "\U0001d4c2", + "mstpos;": "\u223e", + "mu;": "\u03bc", + "multimap;": "\u22b8", + "mumap;": "\u22b8", + "nGg;": "\u22d9\u0338", + "nGt;": "\u226b\u20d2", + "nGtv;": "\u226b\u0338", + "nLeftarrow;": "\u21cd", + "nLeftrightarrow;": "\u21ce", + "nLl;": "\u22d8\u0338", + "nLt;": "\u226a\u20d2", + "nLtv;": "\u226a\u0338", + "nRightarrow;": "\u21cf", + "nVDash;": "\u22af", + "nVdash;": "\u22ae", + "nabla;": "\u2207", + "nacute;": "\u0144", + "nang;": "\u2220\u20d2", + "nap;": "\u2249", + "napE;": "\u2a70\u0338", + "napid;": "\u224b\u0338", + "napos;": "\u0149", + "napprox;": "\u2249", + "natur;": "\u266e", + "natural;": "\u266e", + "naturals;": "\u2115", + "nbsp": "\xa0", + "nbsp;": "\xa0", + "nbump;": "\u224e\u0338", + "nbumpe;": "\u224f\u0338", + "ncap;": "\u2a43", + "ncaron;": "\u0148", + "ncedil;": "\u0146", + "ncong;": "\u2247", + "ncongdot;": "\u2a6d\u0338", + "ncup;": "\u2a42", + "ncy;": "\u043d", + "ndash;": "\u2013", + "ne;": "\u2260", + "neArr;": "\u21d7", + "nearhk;": "\u2924", + "nearr;": "\u2197", + "nearrow;": "\u2197", + "nedot;": "\u2250\u0338", + "nequiv;": "\u2262", + "nesear;": "\u2928", + "nesim;": "\u2242\u0338", + "nexist;": "\u2204", + "nexists;": "\u2204", + "nfr;": "\U0001d52b", + "ngE;": "\u2267\u0338", + "nge;": "\u2271", + "ngeq;": "\u2271", + "ngeqq;": "\u2267\u0338", + "ngeqslant;": "\u2a7e\u0338", + "nges;": "\u2a7e\u0338", + "ngsim;": "\u2275", + "ngt;": "\u226f", + "ngtr;": "\u226f", + "nhArr;": "\u21ce", + "nharr;": "\u21ae", + "nhpar;": "\u2af2", + "ni;": "\u220b", + "nis;": "\u22fc", + "nisd;": "\u22fa", + "niv;": "\u220b", + "njcy;": "\u045a", + "nlArr;": "\u21cd", + "nlE;": "\u2266\u0338", + "nlarr;": "\u219a", + "nldr;": "\u2025", + "nle;": "\u2270", + "nleftarrow;": "\u219a", + "nleftrightarrow;": "\u21ae", + "nleq;": "\u2270", + "nleqq;": "\u2266\u0338", + "nleqslant;": "\u2a7d\u0338", + "nles;": "\u2a7d\u0338", + "nless;": "\u226e", + "nlsim;": "\u2274", + "nlt;": "\u226e", + "nltri;": "\u22ea", + "nltrie;": "\u22ec", + "nmid;": "\u2224", + "nopf;": "\U0001d55f", + "not": "\xac", + "not;": "\xac", + "notin;": "\u2209", + "notinE;": "\u22f9\u0338", + "notindot;": "\u22f5\u0338", + "notinva;": "\u2209", + "notinvb;": "\u22f7", + "notinvc;": "\u22f6", + "notni;": "\u220c", + "notniva;": "\u220c", + "notnivb;": "\u22fe", + "notnivc;": "\u22fd", + "npar;": "\u2226", + "nparallel;": "\u2226", + "nparsl;": "\u2afd\u20e5", + "npart;": "\u2202\u0338", + "npolint;": "\u2a14", + "npr;": "\u2280", + "nprcue;": "\u22e0", + "npre;": "\u2aaf\u0338", + "nprec;": "\u2280", + "npreceq;": "\u2aaf\u0338", + "nrArr;": "\u21cf", + "nrarr;": "\u219b", + "nrarrc;": "\u2933\u0338", + "nrarrw;": "\u219d\u0338", + "nrightarrow;": "\u219b", + "nrtri;": "\u22eb", + "nrtrie;": "\u22ed", + "nsc;": "\u2281", + "nsccue;": "\u22e1", + "nsce;": "\u2ab0\u0338", + "nscr;": "\U0001d4c3", + "nshortmid;": "\u2224", + "nshortparallel;": "\u2226", + "nsim;": "\u2241", + "nsime;": "\u2244", + "nsimeq;": "\u2244", + "nsmid;": "\u2224", + "nspar;": "\u2226", + "nsqsube;": "\u22e2", + "nsqsupe;": "\u22e3", + "nsub;": "\u2284", + "nsubE;": "\u2ac5\u0338", + "nsube;": "\u2288", + "nsubset;": "\u2282\u20d2", + "nsubseteq;": "\u2288", + "nsubseteqq;": "\u2ac5\u0338", + "nsucc;": "\u2281", + "nsucceq;": "\u2ab0\u0338", + "nsup;": "\u2285", + "nsupE;": "\u2ac6\u0338", + "nsupe;": "\u2289", + "nsupset;": "\u2283\u20d2", + "nsupseteq;": "\u2289", + "nsupseteqq;": "\u2ac6\u0338", + "ntgl;": "\u2279", + "ntilde": "\xf1", + "ntilde;": "\xf1", + "ntlg;": "\u2278", + "ntriangleleft;": "\u22ea", + "ntrianglelefteq;": "\u22ec", + "ntriangleright;": "\u22eb", + "ntrianglerighteq;": "\u22ed", + "nu;": "\u03bd", + "num;": "#", + "numero;": "\u2116", + "numsp;": "\u2007", + "nvDash;": "\u22ad", + "nvHarr;": "\u2904", + "nvap;": "\u224d\u20d2", + "nvdash;": "\u22ac", + "nvge;": "\u2265\u20d2", + "nvgt;": ">\u20d2", + "nvinfin;": "\u29de", + "nvlArr;": "\u2902", + "nvle;": "\u2264\u20d2", + "nvlt;": "<\u20d2", + "nvltrie;": "\u22b4\u20d2", + "nvrArr;": "\u2903", + "nvrtrie;": "\u22b5\u20d2", + "nvsim;": "\u223c\u20d2", + "nwArr;": "\u21d6", + "nwarhk;": "\u2923", + "nwarr;": "\u2196", + "nwarrow;": "\u2196", + "nwnear;": "\u2927", + "oS;": "\u24c8", + "oacute": "\xf3", + "oacute;": "\xf3", + "oast;": "\u229b", + "ocir;": "\u229a", + "ocirc": "\xf4", + "ocirc;": "\xf4", + "ocy;": "\u043e", + "odash;": "\u229d", + "odblac;": "\u0151", + "odiv;": "\u2a38", + "odot;": "\u2299", + "odsold;": "\u29bc", + "oelig;": "\u0153", + "ofcir;": "\u29bf", + "ofr;": "\U0001d52c", + "ogon;": "\u02db", + "ograve": "\xf2", + "ograve;": "\xf2", + "ogt;": "\u29c1", + "ohbar;": "\u29b5", + "ohm;": "\u03a9", + "oint;": "\u222e", + "olarr;": "\u21ba", + "olcir;": "\u29be", + "olcross;": "\u29bb", + "oline;": "\u203e", + "olt;": "\u29c0", + "omacr;": "\u014d", + "omega;": "\u03c9", + "omicron;": "\u03bf", + "omid;": "\u29b6", + "ominus;": "\u2296", + "oopf;": "\U0001d560", + "opar;": "\u29b7", + "operp;": "\u29b9", + "oplus;": "\u2295", + "or;": "\u2228", + "orarr;": "\u21bb", + "ord;": "\u2a5d", + "order;": "\u2134", + "orderof;": "\u2134", + "ordf": "\xaa", + "ordf;": "\xaa", + "ordm": "\xba", + "ordm;": "\xba", + "origof;": "\u22b6", + "oror;": "\u2a56", + "orslope;": "\u2a57", + "orv;": "\u2a5b", + "oscr;": "\u2134", + "oslash": "\xf8", + "oslash;": "\xf8", + "osol;": "\u2298", + "otilde": "\xf5", + "otilde;": "\xf5", + "otimes;": "\u2297", + "otimesas;": "\u2a36", + "ouml": "\xf6", + "ouml;": "\xf6", + "ovbar;": "\u233d", + "par;": "\u2225", + "para": "\xb6", + "para;": "\xb6", + "parallel;": "\u2225", + "parsim;": "\u2af3", + "parsl;": "\u2afd", + "part;": "\u2202", + "pcy;": "\u043f", + "percnt;": "%", + "period;": ".", + "permil;": "\u2030", + "perp;": "\u22a5", + "pertenk;": "\u2031", + "pfr;": "\U0001d52d", + "phi;": "\u03c6", + "phiv;": "\u03d5", + "phmmat;": "\u2133", + "phone;": "\u260e", + "pi;": "\u03c0", + "pitchfork;": "\u22d4", + "piv;": "\u03d6", + "planck;": "\u210f", + "planckh;": "\u210e", + "plankv;": "\u210f", + "plus;": "+", + "plusacir;": "\u2a23", + "plusb;": "\u229e", + "pluscir;": "\u2a22", + "plusdo;": "\u2214", + "plusdu;": "\u2a25", + "pluse;": "\u2a72", + "plusmn": "\xb1", + "plusmn;": "\xb1", + "plussim;": "\u2a26", + "plustwo;": "\u2a27", + "pm;": "\xb1", + "pointint;": "\u2a15", + "popf;": "\U0001d561", + "pound": "\xa3", + "pound;": "\xa3", + "pr;": "\u227a", + "prE;": "\u2ab3", + "prap;": "\u2ab7", + "prcue;": "\u227c", + "pre;": "\u2aaf", + "prec;": "\u227a", + "precapprox;": "\u2ab7", + "preccurlyeq;": "\u227c", + "preceq;": "\u2aaf", + "precnapprox;": "\u2ab9", + "precneqq;": "\u2ab5", + "precnsim;": "\u22e8", + "precsim;": "\u227e", + "prime;": "\u2032", + "primes;": "\u2119", + "prnE;": "\u2ab5", + "prnap;": "\u2ab9", + "prnsim;": "\u22e8", + "prod;": "\u220f", + "profalar;": "\u232e", + "profline;": "\u2312", + "profsurf;": "\u2313", + "prop;": "\u221d", + "propto;": "\u221d", + "prsim;": "\u227e", + "prurel;": "\u22b0", + "pscr;": "\U0001d4c5", + "psi;": "\u03c8", + "puncsp;": "\u2008", + "qfr;": "\U0001d52e", + "qint;": "\u2a0c", + "qopf;": "\U0001d562", + "qprime;": "\u2057", + "qscr;": "\U0001d4c6", + "quaternions;": "\u210d", + "quatint;": "\u2a16", + "quest;": "?", + "questeq;": "\u225f", + "quot": "\"", + "quot;": "\"", + "rAarr;": "\u21db", + "rArr;": "\u21d2", + "rAtail;": "\u291c", + "rBarr;": "\u290f", + "rHar;": "\u2964", + "race;": "\u223d\u0331", + "racute;": "\u0155", + "radic;": "\u221a", + "raemptyv;": "\u29b3", + "rang;": "\u27e9", + "rangd;": "\u2992", + "range;": "\u29a5", + "rangle;": "\u27e9", + "raquo": "\xbb", + "raquo;": "\xbb", + "rarr;": "\u2192", + "rarrap;": "\u2975", + "rarrb;": "\u21e5", + "rarrbfs;": "\u2920", + "rarrc;": "\u2933", + "rarrfs;": "\u291e", + "rarrhk;": "\u21aa", + "rarrlp;": "\u21ac", + "rarrpl;": "\u2945", + "rarrsim;": "\u2974", + "rarrtl;": "\u21a3", + "rarrw;": "\u219d", + "ratail;": "\u291a", + "ratio;": "\u2236", + "rationals;": "\u211a", + "rbarr;": "\u290d", + "rbbrk;": "\u2773", + "rbrace;": "}", + "rbrack;": "]", + "rbrke;": "\u298c", + "rbrksld;": "\u298e", + "rbrkslu;": "\u2990", + "rcaron;": "\u0159", + "rcedil;": "\u0157", + "rceil;": "\u2309", + "rcub;": "}", + "rcy;": "\u0440", + "rdca;": "\u2937", + "rdldhar;": "\u2969", + "rdquo;": "\u201d", + "rdquor;": "\u201d", + "rdsh;": "\u21b3", + "real;": "\u211c", + "realine;": "\u211b", + "realpart;": "\u211c", + "reals;": "\u211d", + "rect;": "\u25ad", + "reg": "\xae", + "reg;": "\xae", + "rfisht;": "\u297d", + "rfloor;": "\u230b", + "rfr;": "\U0001d52f", + "rhard;": "\u21c1", + "rharu;": "\u21c0", + "rharul;": "\u296c", + "rho;": "\u03c1", + "rhov;": "\u03f1", + "rightarrow;": "\u2192", + "rightarrowtail;": "\u21a3", + "rightharpoondown;": "\u21c1", + "rightharpoonup;": "\u21c0", + "rightleftarrows;": "\u21c4", + "rightleftharpoons;": "\u21cc", + "rightrightarrows;": "\u21c9", + "rightsquigarrow;": "\u219d", + "rightthreetimes;": "\u22cc", + "ring;": "\u02da", + "risingdotseq;": "\u2253", + "rlarr;": "\u21c4", + "rlhar;": "\u21cc", + "rlm;": "\u200f", + "rmoust;": "\u23b1", + "rmoustache;": "\u23b1", + "rnmid;": "\u2aee", + "roang;": "\u27ed", + "roarr;": "\u21fe", + "robrk;": "\u27e7", + "ropar;": "\u2986", + "ropf;": "\U0001d563", + "roplus;": "\u2a2e", + "rotimes;": "\u2a35", + "rpar;": ")", + "rpargt;": "\u2994", + "rppolint;": "\u2a12", + "rrarr;": "\u21c9", + "rsaquo;": "\u203a", + "rscr;": "\U0001d4c7", + "rsh;": "\u21b1", + "rsqb;": "]", + "rsquo;": "\u2019", + "rsquor;": "\u2019", + "rthree;": "\u22cc", + "rtimes;": "\u22ca", + "rtri;": "\u25b9", + "rtrie;": "\u22b5", + "rtrif;": "\u25b8", + "rtriltri;": "\u29ce", + "ruluhar;": "\u2968", + "rx;": "\u211e", + "sacute;": "\u015b", + "sbquo;": "\u201a", + "sc;": "\u227b", + "scE;": "\u2ab4", + "scap;": "\u2ab8", + "scaron;": "\u0161", + "sccue;": "\u227d", + "sce;": "\u2ab0", + "scedil;": "\u015f", + "scirc;": "\u015d", + "scnE;": "\u2ab6", + "scnap;": "\u2aba", + "scnsim;": "\u22e9", + "scpolint;": "\u2a13", + "scsim;": "\u227f", + "scy;": "\u0441", + "sdot;": "\u22c5", + "sdotb;": "\u22a1", + "sdote;": "\u2a66", + "seArr;": "\u21d8", + "searhk;": "\u2925", + "searr;": "\u2198", + "searrow;": "\u2198", + "sect": "\xa7", + "sect;": "\xa7", + "semi;": ";", + "seswar;": "\u2929", + "setminus;": "\u2216", + "setmn;": "\u2216", + "sext;": "\u2736", + "sfr;": "\U0001d530", + "sfrown;": "\u2322", + "sharp;": "\u266f", + "shchcy;": "\u0449", + "shcy;": "\u0448", + "shortmid;": "\u2223", + "shortparallel;": "\u2225", + "shy": "\xad", + "shy;": "\xad", + "sigma;": "\u03c3", + "sigmaf;": "\u03c2", + "sigmav;": "\u03c2", + "sim;": "\u223c", + "simdot;": "\u2a6a", + "sime;": "\u2243", + "simeq;": "\u2243", + "simg;": "\u2a9e", + "simgE;": "\u2aa0", + "siml;": "\u2a9d", + "simlE;": "\u2a9f", + "simne;": "\u2246", + "simplus;": "\u2a24", + "simrarr;": "\u2972", + "slarr;": "\u2190", + "smallsetminus;": "\u2216", + "smashp;": "\u2a33", + "smeparsl;": "\u29e4", + "smid;": "\u2223", + "smile;": "\u2323", + "smt;": "\u2aaa", + "smte;": "\u2aac", + "smtes;": "\u2aac\ufe00", + "softcy;": "\u044c", + "sol;": "/", + "solb;": "\u29c4", + "solbar;": "\u233f", + "sopf;": "\U0001d564", + "spades;": "\u2660", + "spadesuit;": "\u2660", + "spar;": "\u2225", + "sqcap;": "\u2293", + "sqcaps;": "\u2293\ufe00", + "sqcup;": "\u2294", + "sqcups;": "\u2294\ufe00", + "sqsub;": "\u228f", + "sqsube;": "\u2291", + "sqsubset;": "\u228f", + "sqsubseteq;": "\u2291", + "sqsup;": "\u2290", + "sqsupe;": "\u2292", + "sqsupset;": "\u2290", + "sqsupseteq;": "\u2292", + "squ;": "\u25a1", + "square;": "\u25a1", + "squarf;": "\u25aa", + "squf;": "\u25aa", + "srarr;": "\u2192", + "sscr;": "\U0001d4c8", + "ssetmn;": "\u2216", + "ssmile;": "\u2323", + "sstarf;": "\u22c6", + "star;": "\u2606", + "starf;": "\u2605", + "straightepsilon;": "\u03f5", + "straightphi;": "\u03d5", + "strns;": "\xaf", + "sub;": "\u2282", + "subE;": "\u2ac5", + "subdot;": "\u2abd", + "sube;": "\u2286", + "subedot;": "\u2ac3", + "submult;": "\u2ac1", + "subnE;": "\u2acb", + "subne;": "\u228a", + "subplus;": "\u2abf", + "subrarr;": "\u2979", + "subset;": "\u2282", + "subseteq;": "\u2286", + "subseteqq;": "\u2ac5", + "subsetneq;": "\u228a", + "subsetneqq;": "\u2acb", + "subsim;": "\u2ac7", + "subsub;": "\u2ad5", + "subsup;": "\u2ad3", + "succ;": "\u227b", + "succapprox;": "\u2ab8", + "succcurlyeq;": "\u227d", + "succeq;": "\u2ab0", + "succnapprox;": "\u2aba", + "succneqq;": "\u2ab6", + "succnsim;": "\u22e9", + "succsim;": "\u227f", + "sum;": "\u2211", + "sung;": "\u266a", + "sup1": "\xb9", + "sup1;": "\xb9", + "sup2": "\xb2", + "sup2;": "\xb2", + "sup3": "\xb3", + "sup3;": "\xb3", + "sup;": "\u2283", + "supE;": "\u2ac6", + "supdot;": "\u2abe", + "supdsub;": "\u2ad8", + "supe;": "\u2287", + "supedot;": "\u2ac4", + "suphsol;": "\u27c9", + "suphsub;": "\u2ad7", + "suplarr;": "\u297b", + "supmult;": "\u2ac2", + "supnE;": "\u2acc", + "supne;": "\u228b", + "supplus;": "\u2ac0", + "supset;": "\u2283", + "supseteq;": "\u2287", + "supseteqq;": "\u2ac6", + "supsetneq;": "\u228b", + "supsetneqq;": "\u2acc", + "supsim;": "\u2ac8", + "supsub;": "\u2ad4", + "supsup;": "\u2ad6", + "swArr;": "\u21d9", + "swarhk;": "\u2926", + "swarr;": "\u2199", + "swarrow;": "\u2199", + "swnwar;": "\u292a", + "szlig": "\xdf", + "szlig;": "\xdf", + "target;": "\u2316", + "tau;": "\u03c4", + "tbrk;": "\u23b4", + "tcaron;": "\u0165", + "tcedil;": "\u0163", + "tcy;": "\u0442", + "tdot;": "\u20db", + "telrec;": "\u2315", + "tfr;": "\U0001d531", + "there4;": "\u2234", + "therefore;": "\u2234", + "theta;": "\u03b8", + "thetasym;": "\u03d1", + "thetav;": "\u03d1", + "thickapprox;": "\u2248", + "thicksim;": "\u223c", + "thinsp;": "\u2009", + "thkap;": "\u2248", + "thksim;": "\u223c", + "thorn": "\xfe", + "thorn;": "\xfe", + "tilde;": "\u02dc", + "times": "\xd7", + "times;": "\xd7", + "timesb;": "\u22a0", + "timesbar;": "\u2a31", + "timesd;": "\u2a30", + "tint;": "\u222d", + "toea;": "\u2928", + "top;": "\u22a4", + "topbot;": "\u2336", + "topcir;": "\u2af1", + "topf;": "\U0001d565", + "topfork;": "\u2ada", + "tosa;": "\u2929", + "tprime;": "\u2034", + "trade;": "\u2122", + "triangle;": "\u25b5", + "triangledown;": "\u25bf", + "triangleleft;": "\u25c3", + "trianglelefteq;": "\u22b4", + "triangleq;": "\u225c", + "triangleright;": "\u25b9", + "trianglerighteq;": "\u22b5", + "tridot;": "\u25ec", + "trie;": "\u225c", + "triminus;": "\u2a3a", + "triplus;": "\u2a39", + "trisb;": "\u29cd", + "tritime;": "\u2a3b", + "trpezium;": "\u23e2", + "tscr;": "\U0001d4c9", + "tscy;": "\u0446", + "tshcy;": "\u045b", + "tstrok;": "\u0167", + "twixt;": "\u226c", + "twoheadleftarrow;": "\u219e", + "twoheadrightarrow;": "\u21a0", + "uArr;": "\u21d1", + "uHar;": "\u2963", + "uacute": "\xfa", + "uacute;": "\xfa", + "uarr;": "\u2191", + "ubrcy;": "\u045e", + "ubreve;": "\u016d", + "ucirc": "\xfb", + "ucirc;": "\xfb", + "ucy;": "\u0443", + "udarr;": "\u21c5", + "udblac;": "\u0171", + "udhar;": "\u296e", + "ufisht;": "\u297e", + "ufr;": "\U0001d532", + "ugrave": "\xf9", + "ugrave;": "\xf9", + "uharl;": "\u21bf", + "uharr;": "\u21be", + "uhblk;": "\u2580", + "ulcorn;": "\u231c", + "ulcorner;": "\u231c", + "ulcrop;": "\u230f", + "ultri;": "\u25f8", + "umacr;": "\u016b", + "uml": "\xa8", + "uml;": "\xa8", + "uogon;": "\u0173", + "uopf;": "\U0001d566", + "uparrow;": "\u2191", + "updownarrow;": "\u2195", + "upharpoonleft;": "\u21bf", + "upharpoonright;": "\u21be", + "uplus;": "\u228e", + "upsi;": "\u03c5", + "upsih;": "\u03d2", + "upsilon;": "\u03c5", + "upuparrows;": "\u21c8", + "urcorn;": "\u231d", + "urcorner;": "\u231d", + "urcrop;": "\u230e", + "uring;": "\u016f", + "urtri;": "\u25f9", + "uscr;": "\U0001d4ca", + "utdot;": "\u22f0", + "utilde;": "\u0169", + "utri;": "\u25b5", + "utrif;": "\u25b4", + "uuarr;": "\u21c8", + "uuml": "\xfc", + "uuml;": "\xfc", + "uwangle;": "\u29a7", + "vArr;": "\u21d5", + "vBar;": "\u2ae8", + "vBarv;": "\u2ae9", + "vDash;": "\u22a8", + "vangrt;": "\u299c", + "varepsilon;": "\u03f5", + "varkappa;": "\u03f0", + "varnothing;": "\u2205", + "varphi;": "\u03d5", + "varpi;": "\u03d6", + "varpropto;": "\u221d", + "varr;": "\u2195", + "varrho;": "\u03f1", + "varsigma;": "\u03c2", + "varsubsetneq;": "\u228a\ufe00", + "varsubsetneqq;": "\u2acb\ufe00", + "varsupsetneq;": "\u228b\ufe00", + "varsupsetneqq;": "\u2acc\ufe00", + "vartheta;": "\u03d1", + "vartriangleleft;": "\u22b2", + "vartriangleright;": "\u22b3", + "vcy;": "\u0432", + "vdash;": "\u22a2", + "vee;": "\u2228", + "veebar;": "\u22bb", + "veeeq;": "\u225a", + "vellip;": "\u22ee", + "verbar;": "|", + "vert;": "|", + "vfr;": "\U0001d533", + "vltri;": "\u22b2", + "vnsub;": "\u2282\u20d2", + "vnsup;": "\u2283\u20d2", + "vopf;": "\U0001d567", + "vprop;": "\u221d", + "vrtri;": "\u22b3", + "vscr;": "\U0001d4cb", + "vsubnE;": "\u2acb\ufe00", + "vsubne;": "\u228a\ufe00", + "vsupnE;": "\u2acc\ufe00", + "vsupne;": "\u228b\ufe00", + "vzigzag;": "\u299a", + "wcirc;": "\u0175", + "wedbar;": "\u2a5f", + "wedge;": "\u2227", + "wedgeq;": "\u2259", + "weierp;": "\u2118", + "wfr;": "\U0001d534", + "wopf;": "\U0001d568", + "wp;": "\u2118", + "wr;": "\u2240", + "wreath;": "\u2240", + "wscr;": "\U0001d4cc", + "xcap;": "\u22c2", + "xcirc;": "\u25ef", + "xcup;": "\u22c3", + "xdtri;": "\u25bd", + "xfr;": "\U0001d535", + "xhArr;": "\u27fa", + "xharr;": "\u27f7", + "xi;": "\u03be", + "xlArr;": "\u27f8", + "xlarr;": "\u27f5", + "xmap;": "\u27fc", + "xnis;": "\u22fb", + "xodot;": "\u2a00", + "xopf;": "\U0001d569", + "xoplus;": "\u2a01", + "xotime;": "\u2a02", + "xrArr;": "\u27f9", + "xrarr;": "\u27f6", + "xscr;": "\U0001d4cd", + "xsqcup;": "\u2a06", + "xuplus;": "\u2a04", + "xutri;": "\u25b3", + "xvee;": "\u22c1", + "xwedge;": "\u22c0", + "yacute": "\xfd", + "yacute;": "\xfd", + "yacy;": "\u044f", + "ycirc;": "\u0177", + "ycy;": "\u044b", + "yen": "\xa5", + "yen;": "\xa5", + "yfr;": "\U0001d536", + "yicy;": "\u0457", + "yopf;": "\U0001d56a", + "yscr;": "\U0001d4ce", + "yucy;": "\u044e", + "yuml": "\xff", + "yuml;": "\xff", + "zacute;": "\u017a", + "zcaron;": "\u017e", + "zcy;": "\u0437", + "zdot;": "\u017c", + "zeetrf;": "\u2128", + "zeta;": "\u03b6", + "zfr;": "\U0001d537", + "zhcy;": "\u0436", + "zigrarr;": "\u21dd", + "zopf;": "\U0001d56b", + "zscr;": "\U0001d4cf", + "zwj;": "\u200d", + "zwnj;": "\u200c", +} + +replacementCharacters = { + 0x0: "\uFFFD", + 0x0d: "\u000D", + 0x80: "\u20AC", + 0x81: "\u0081", + 0x82: "\u201A", + 0x83: "\u0192", + 0x84: "\u201E", + 0x85: "\u2026", + 0x86: "\u2020", + 0x87: "\u2021", + 0x88: "\u02C6", + 0x89: "\u2030", + 0x8A: "\u0160", + 0x8B: "\u2039", + 0x8C: "\u0152", + 0x8D: "\u008D", + 0x8E: "\u017D", + 0x8F: "\u008F", + 0x90: "\u0090", + 0x91: "\u2018", + 0x92: "\u2019", + 0x93: "\u201C", + 0x94: "\u201D", + 0x95: "\u2022", + 0x96: "\u2013", + 0x97: "\u2014", + 0x98: "\u02DC", + 0x99: "\u2122", + 0x9A: "\u0161", + 0x9B: "\u203A", + 0x9C: "\u0153", + 0x9D: "\u009D", + 0x9E: "\u017E", + 0x9F: "\u0178", +} + +tokenTypes = { + "Doctype": 0, + "Characters": 1, + "SpaceCharacters": 2, + "StartTag": 3, + "EndTag": 4, + "EmptyTag": 5, + "Comment": 6, + "ParseError": 7 +} + +tagTokenTypes = frozenset([tokenTypes["StartTag"], tokenTypes["EndTag"], + tokenTypes["EmptyTag"]]) + + +prefixes = dict([(v, k) for k, v in namespaces.items()]) +prefixes["http://www.w3.org/1998/Math/MathML"] = "math" + + +class DataLossWarning(UserWarning): + """Raised when the current tree is unable to represent the input data""" + pass + + +class _ReparseException(Exception): + pass diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py new file mode 100644 index 0000000..5ba926e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py @@ -0,0 +1,29 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + +from collections import OrderedDict + + +def _attr_key(attr): + """Return an appropriate key for an attribute for sorting + + Attributes have a namespace that can be either ``None`` or a string. We + can't compare the two because they're different types, so we convert + ``None`` to an empty string first. + + """ + return (attr[0][0] or ''), attr[0][1] + + +class Filter(base.Filter): + """Alphabetizes attributes for elements""" + def __iter__(self): + for token in base.Filter.__iter__(self): + if token["type"] in ("StartTag", "EmptyTag"): + attrs = OrderedDict() + for name, value in sorted(token["data"].items(), + key=_attr_key): + attrs[name] = value + token["data"] = attrs + yield token diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py new file mode 100644 index 0000000..c7dbaed --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py @@ -0,0 +1,12 @@ +from __future__ import absolute_import, division, unicode_literals + + +class Filter(object): + def __init__(self, source): + self.source = source + + def __iter__(self): + return iter(self.source) + + def __getattr__(self, name): + return getattr(self.source, name) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py new file mode 100644 index 0000000..aefb5c8 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py @@ -0,0 +1,73 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + + +class Filter(base.Filter): + """Injects ``<meta charset=ENCODING>`` tag into head of document""" + def __init__(self, source, encoding): + """Creates a Filter + + :arg source: the source token stream + + :arg encoding: the encoding to set + + """ + base.Filter.__init__(self, source) + self.encoding = encoding + + def __iter__(self): + state = "pre_head" + meta_found = (self.encoding is None) + pending = [] + + for token in base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag": + if token["name"].lower() == "head": + state = "in_head" + + elif type == "EmptyTag": + if token["name"].lower() == "meta": + # replace charset with actual encoding + has_http_equiv_content_type = False + for (namespace, name), value in token["data"].items(): + if namespace is not None: + continue + elif name.lower() == 'charset': + token["data"][(namespace, name)] = self.encoding + meta_found = True + break + elif name == 'http-equiv' and value.lower() == 'content-type': + has_http_equiv_content_type = True + else: + if has_http_equiv_content_type and (None, "content") in token["data"]: + token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding + meta_found = True + + elif token["name"].lower() == "head" and not meta_found: + # insert meta into empty head + yield {"type": "StartTag", "name": "head", + "data": token["data"]} + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + yield {"type": "EndTag", "name": "head"} + meta_found = True + continue + + elif type == "EndTag": + if token["name"].lower() == "head" and pending: + # insert meta into head (if necessary) and flush pending queue + yield pending.pop(0) + if not meta_found: + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + while pending: + yield pending.pop(0) + meta_found = True + state = "post_head" + + if state == "in_head": + pending.append(token) + else: + yield token diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py new file mode 100644 index 0000000..fcc07ee --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py @@ -0,0 +1,93 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import text_type + +from . import base +from ..constants import namespaces, voidElements + +from ..constants import spaceCharacters +spaceCharacters = "".join(spaceCharacters) + + +class Filter(base.Filter): + """Lints the token stream for errors + + If it finds any errors, it'll raise an ``AssertionError``. + + """ + def __init__(self, source, require_matching_tags=True): + """Creates a Filter + + :arg source: the source token stream + + :arg require_matching_tags: whether or not to require matching tags + + """ + super(Filter, self).__init__(source) + self.require_matching_tags = require_matching_tags + + def __iter__(self): + open_elements = [] + for token in base.Filter.__iter__(self): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + namespace = token["namespace"] + name = token["name"] + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + assert isinstance(token["data"], dict) + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + assert type == "EmptyTag" + else: + assert type == "StartTag" + if type == "StartTag" and self.require_matching_tags: + open_elements.append((namespace, name)) + for (namespace, name), value in token["data"].items(): + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + assert isinstance(value, text_type) + + elif type == "EndTag": + namespace = token["namespace"] + name = token["name"] + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + assert False, "Void element reported as EndTag token: %(tag)s" % {"tag": name} + elif self.require_matching_tags: + start = open_elements.pop() + assert start == (namespace, name) + + elif type == "Comment": + data = token["data"] + assert isinstance(data, text_type) + + elif type in ("Characters", "SpaceCharacters"): + data = token["data"] + assert isinstance(data, text_type) + assert data != "" + if type == "SpaceCharacters": + assert data.strip(spaceCharacters) == "" + + elif type == "Doctype": + name = token["name"] + assert name is None or isinstance(name, text_type) + assert token["publicId"] is None or isinstance(name, text_type) + assert token["systemId"] is None or isinstance(name, text_type) + + elif type == "Entity": + assert isinstance(token["name"], text_type) + + elif type == "SerializerError": + assert isinstance(token["data"], text_type) + + else: + assert False, "Unknown token type: %(type)s" % {"type": type} + + yield token diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py new file mode 100644 index 0000000..4a86501 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py @@ -0,0 +1,207 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + + +class Filter(base.Filter): + """Removes optional tags from the token stream""" + def slider(self): + previous1 = previous2 = None + for token in self.source: + if previous1 is not None: + yield previous2, previous1, token + previous2 = previous1 + previous1 = token + if previous1 is not None: + yield previous2, previous1, None + + def __iter__(self): + for previous, token, next in self.slider(): + type = token["type"] + if type == "StartTag": + if (token["data"] or + not self.is_optional_start(token["name"], previous, next)): + yield token + elif type == "EndTag": + if not self.is_optional_end(token["name"], next): + yield token + else: + yield token + + def is_optional_start(self, tagname, previous, next): + type = next and next["type"] or None + if tagname in 'html': + # An html element's start tag may be omitted if the first thing + # inside the html element is not a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname == 'head': + # A head element's start tag may be omitted if the first thing + # inside the head element is an element. + # XXX: we also omit the start tag if the head element is empty + if type in ("StartTag", "EmptyTag"): + return True + elif type == "EndTag": + return next["name"] == "head" + elif tagname == 'body': + # A body element's start tag may be omitted if the first thing + # inside the body element is not a space character or a comment, + # except if the first thing inside the body element is a script + # or style element and the node immediately preceding the body + # element is a head element whose end tag has been omitted. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we do not look at the preceding event, so we never omit + # the body element's start tag if it's followed by a script or + # a style element. + return next["name"] not in ('script', 'style') + else: + return True + elif tagname == 'colgroup': + # A colgroup element's start tag may be omitted if the first thing + # inside the colgroup element is a col element, and if the element + # is not immediately preceded by another colgroup element whose + # end tag has been omitted. + if type in ("StartTag", "EmptyTag"): + # XXX: we do not look at the preceding event, so instead we never + # omit the colgroup element's end tag when it is immediately + # followed by another colgroup element. See is_optional_end. + return next["name"] == "col" + else: + return False + elif tagname == 'tbody': + # A tbody element's start tag may be omitted if the first thing + # inside the tbody element is a tr element, and if the element is + # not immediately preceded by a tbody, thead, or tfoot element + # whose end tag has been omitted. + if type == "StartTag": + # omit the thead and tfoot elements' end tag when they are + # immediately followed by a tbody element. See is_optional_end. + if previous and previous['type'] == 'EndTag' and \ + previous['name'] in ('tbody', 'thead', 'tfoot'): + return False + return next["name"] == 'tr' + else: + return False + return False + + def is_optional_end(self, tagname, next): + type = next and next["type"] or None + if tagname in ('html', 'head', 'body'): + # An html element's end tag may be omitted if the html element + # is not immediately followed by a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname in ('li', 'optgroup', 'tr'): + # A li element's end tag may be omitted if the li element is + # immediately followed by another li element or if there is + # no more content in the parent element. + # An optgroup element's end tag may be omitted if the optgroup + # element is immediately followed by another optgroup element, + # or if there is no more content in the parent element. + # A tr element's end tag may be omitted if the tr element is + # immediately followed by another tr element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] == tagname + else: + return type == "EndTag" or type is None + elif tagname in ('dt', 'dd'): + # A dt element's end tag may be omitted if the dt element is + # immediately followed by another dt element or a dd element. + # A dd element's end tag may be omitted if the dd element is + # immediately followed by another dd element or a dt element, + # or if there is no more content in the parent element. + if type == "StartTag": + return next["name"] in ('dt', 'dd') + elif tagname == 'dd': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'p': + # A p element's end tag may be omitted if the p element is + # immediately followed by an address, article, aside, + # blockquote, datagrid, dialog, dir, div, dl, fieldset, + # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, + # nav, ol, p, pre, section, table, or ul, element, or if + # there is no more content in the parent element. + if type in ("StartTag", "EmptyTag"): + return next["name"] in ('address', 'article', 'aside', + 'blockquote', 'datagrid', 'dialog', + 'dir', 'div', 'dl', 'fieldset', 'footer', + 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'header', 'hr', 'menu', 'nav', 'ol', + 'p', 'pre', 'section', 'table', 'ul') + else: + return type == "EndTag" or type is None + elif tagname == 'option': + # An option element's end tag may be omitted if the option + # element is immediately followed by another option element, + # or if it is immediately followed by an <code>optgroup</code> + # element, or if there is no more content in the parent + # element. + if type == "StartTag": + return next["name"] in ('option', 'optgroup') + else: + return type == "EndTag" or type is None + elif tagname in ('rt', 'rp'): + # An rt element's end tag may be omitted if the rt element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + # An rp element's end tag may be omitted if the rp element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('rt', 'rp') + else: + return type == "EndTag" or type is None + elif tagname == 'colgroup': + # A colgroup element's end tag may be omitted if the colgroup + # element is not immediately followed by a space character or + # a comment. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we also look for an immediately following colgroup + # element. See is_optional_start. + return next["name"] != 'colgroup' + else: + return True + elif tagname in ('thead', 'tbody'): + # A thead element's end tag may be omitted if the thead element + # is immediately followed by a tbody or tfoot element. + # A tbody element's end tag may be omitted if the tbody element + # is immediately followed by a tbody or tfoot element, or if + # there is no more content in the parent element. + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] in ['tbody', 'tfoot'] + elif tagname == 'tbody': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'tfoot': + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] == 'tbody' + else: + return type == "EndTag" or type is None + elif tagname in ('td', 'th'): + # A td element's end tag may be omitted if the td element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + # A th element's end tag may be omitted if the th element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('td', 'th') + else: + return type == "EndTag" or type is None + return False diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py new file mode 100644 index 0000000..af8e77b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py @@ -0,0 +1,896 @@ +from __future__ import absolute_import, division, unicode_literals + +import re +from xml.sax.saxutils import escape, unescape + +from pip._vendor.six.moves import urllib_parse as urlparse + +from . import base +from ..constants import namespaces, prefixes + +__all__ = ["Filter"] + + +allowed_elements = frozenset(( + (namespaces['html'], 'a'), + (namespaces['html'], 'abbr'), + (namespaces['html'], 'acronym'), + (namespaces['html'], 'address'), + (namespaces['html'], 'area'), + (namespaces['html'], 'article'), + (namespaces['html'], 'aside'), + (namespaces['html'], 'audio'), + (namespaces['html'], 'b'), + (namespaces['html'], 'big'), + (namespaces['html'], 'blockquote'), + (namespaces['html'], 'br'), + (namespaces['html'], 'button'), + (namespaces['html'], 'canvas'), + (namespaces['html'], 'caption'), + (namespaces['html'], 'center'), + (namespaces['html'], 'cite'), + (namespaces['html'], 'code'), + (namespaces['html'], 'col'), + (namespaces['html'], 'colgroup'), + (namespaces['html'], 'command'), + (namespaces['html'], 'datagrid'), + (namespaces['html'], 'datalist'), + (namespaces['html'], 'dd'), + (namespaces['html'], 'del'), + (namespaces['html'], 'details'), + (namespaces['html'], 'dfn'), + (namespaces['html'], 'dialog'), + (namespaces['html'], 'dir'), + (namespaces['html'], 'div'), + (namespaces['html'], 'dl'), + (namespaces['html'], 'dt'), + (namespaces['html'], 'em'), + (namespaces['html'], 'event-source'), + (namespaces['html'], 'fieldset'), + (namespaces['html'], 'figcaption'), + (namespaces['html'], 'figure'), + (namespaces['html'], 'footer'), + (namespaces['html'], 'font'), + (namespaces['html'], 'form'), + (namespaces['html'], 'header'), + (namespaces['html'], 'h1'), + (namespaces['html'], 'h2'), + (namespaces['html'], 'h3'), + (namespaces['html'], 'h4'), + (namespaces['html'], 'h5'), + (namespaces['html'], 'h6'), + (namespaces['html'], 'hr'), + (namespaces['html'], 'i'), + (namespaces['html'], 'img'), + (namespaces['html'], 'input'), + (namespaces['html'], 'ins'), + (namespaces['html'], 'keygen'), + (namespaces['html'], 'kbd'), + (namespaces['html'], 'label'), + (namespaces['html'], 'legend'), + (namespaces['html'], 'li'), + (namespaces['html'], 'm'), + (namespaces['html'], 'map'), + (namespaces['html'], 'menu'), + (namespaces['html'], 'meter'), + (namespaces['html'], 'multicol'), + (namespaces['html'], 'nav'), + (namespaces['html'], 'nextid'), + (namespaces['html'], 'ol'), + (namespaces['html'], 'output'), + (namespaces['html'], 'optgroup'), + (namespaces['html'], 'option'), + (namespaces['html'], 'p'), + (namespaces['html'], 'pre'), + (namespaces['html'], 'progress'), + (namespaces['html'], 'q'), + (namespaces['html'], 's'), + (namespaces['html'], 'samp'), + (namespaces['html'], 'section'), + (namespaces['html'], 'select'), + (namespaces['html'], 'small'), + (namespaces['html'], 'sound'), + (namespaces['html'], 'source'), + (namespaces['html'], 'spacer'), + (namespaces['html'], 'span'), + (namespaces['html'], 'strike'), + (namespaces['html'], 'strong'), + (namespaces['html'], 'sub'), + (namespaces['html'], 'sup'), + (namespaces['html'], 'table'), + (namespaces['html'], 'tbody'), + (namespaces['html'], 'td'), + (namespaces['html'], 'textarea'), + (namespaces['html'], 'time'), + (namespaces['html'], 'tfoot'), + (namespaces['html'], 'th'), + (namespaces['html'], 'thead'), + (namespaces['html'], 'tr'), + (namespaces['html'], 'tt'), + (namespaces['html'], 'u'), + (namespaces['html'], 'ul'), + (namespaces['html'], 'var'), + (namespaces['html'], 'video'), + (namespaces['mathml'], 'maction'), + (namespaces['mathml'], 'math'), + (namespaces['mathml'], 'merror'), + (namespaces['mathml'], 'mfrac'), + (namespaces['mathml'], 'mi'), + (namespaces['mathml'], 'mmultiscripts'), + (namespaces['mathml'], 'mn'), + (namespaces['mathml'], 'mo'), + (namespaces['mathml'], 'mover'), + (namespaces['mathml'], 'mpadded'), + (namespaces['mathml'], 'mphantom'), + (namespaces['mathml'], 'mprescripts'), + (namespaces['mathml'], 'mroot'), + (namespaces['mathml'], 'mrow'), + (namespaces['mathml'], 'mspace'), + (namespaces['mathml'], 'msqrt'), + (namespaces['mathml'], 'mstyle'), + (namespaces['mathml'], 'msub'), + (namespaces['mathml'], 'msubsup'), + (namespaces['mathml'], 'msup'), + (namespaces['mathml'], 'mtable'), + (namespaces['mathml'], 'mtd'), + (namespaces['mathml'], 'mtext'), + (namespaces['mathml'], 'mtr'), + (namespaces['mathml'], 'munder'), + (namespaces['mathml'], 'munderover'), + (namespaces['mathml'], 'none'), + (namespaces['svg'], 'a'), + (namespaces['svg'], 'animate'), + (namespaces['svg'], 'animateColor'), + (namespaces['svg'], 'animateMotion'), + (namespaces['svg'], 'animateTransform'), + (namespaces['svg'], 'clipPath'), + (namespaces['svg'], 'circle'), + (namespaces['svg'], 'defs'), + (namespaces['svg'], 'desc'), + (namespaces['svg'], 'ellipse'), + (namespaces['svg'], 'font-face'), + (namespaces['svg'], 'font-face-name'), + (namespaces['svg'], 'font-face-src'), + (namespaces['svg'], 'g'), + (namespaces['svg'], 'glyph'), + (namespaces['svg'], 'hkern'), + (namespaces['svg'], 'linearGradient'), + (namespaces['svg'], 'line'), + (namespaces['svg'], 'marker'), + (namespaces['svg'], 'metadata'), + (namespaces['svg'], 'missing-glyph'), + (namespaces['svg'], 'mpath'), + (namespaces['svg'], 'path'), + (namespaces['svg'], 'polygon'), + (namespaces['svg'], 'polyline'), + (namespaces['svg'], 'radialGradient'), + (namespaces['svg'], 'rect'), + (namespaces['svg'], 'set'), + (namespaces['svg'], 'stop'), + (namespaces['svg'], 'svg'), + (namespaces['svg'], 'switch'), + (namespaces['svg'], 'text'), + (namespaces['svg'], 'title'), + (namespaces['svg'], 'tspan'), + (namespaces['svg'], 'use'), +)) + +allowed_attributes = frozenset(( + # HTML attributes + (None, 'abbr'), + (None, 'accept'), + (None, 'accept-charset'), + (None, 'accesskey'), + (None, 'action'), + (None, 'align'), + (None, 'alt'), + (None, 'autocomplete'), + (None, 'autofocus'), + (None, 'axis'), + (None, 'background'), + (None, 'balance'), + (None, 'bgcolor'), + (None, 'bgproperties'), + (None, 'border'), + (None, 'bordercolor'), + (None, 'bordercolordark'), + (None, 'bordercolorlight'), + (None, 'bottompadding'), + (None, 'cellpadding'), + (None, 'cellspacing'), + (None, 'ch'), + (None, 'challenge'), + (None, 'char'), + (None, 'charoff'), + (None, 'choff'), + (None, 'charset'), + (None, 'checked'), + (None, 'cite'), + (None, 'class'), + (None, 'clear'), + (None, 'color'), + (None, 'cols'), + (None, 'colspan'), + (None, 'compact'), + (None, 'contenteditable'), + (None, 'controls'), + (None, 'coords'), + (None, 'data'), + (None, 'datafld'), + (None, 'datapagesize'), + (None, 'datasrc'), + (None, 'datetime'), + (None, 'default'), + (None, 'delay'), + (None, 'dir'), + (None, 'disabled'), + (None, 'draggable'), + (None, 'dynsrc'), + (None, 'enctype'), + (None, 'end'), + (None, 'face'), + (None, 'for'), + (None, 'form'), + (None, 'frame'), + (None, 'galleryimg'), + (None, 'gutter'), + (None, 'headers'), + (None, 'height'), + (None, 'hidefocus'), + (None, 'hidden'), + (None, 'high'), + (None, 'href'), + (None, 'hreflang'), + (None, 'hspace'), + (None, 'icon'), + (None, 'id'), + (None, 'inputmode'), + (None, 'ismap'), + (None, 'keytype'), + (None, 'label'), + (None, 'leftspacing'), + (None, 'lang'), + (None, 'list'), + (None, 'longdesc'), + (None, 'loop'), + (None, 'loopcount'), + (None, 'loopend'), + (None, 'loopstart'), + (None, 'low'), + (None, 'lowsrc'), + (None, 'max'), + (None, 'maxlength'), + (None, 'media'), + (None, 'method'), + (None, 'min'), + (None, 'multiple'), + (None, 'name'), + (None, 'nohref'), + (None, 'noshade'), + (None, 'nowrap'), + (None, 'open'), + (None, 'optimum'), + (None, 'pattern'), + (None, 'ping'), + (None, 'point-size'), + (None, 'poster'), + (None, 'pqg'), + (None, 'preload'), + (None, 'prompt'), + (None, 'radiogroup'), + (None, 'readonly'), + (None, 'rel'), + (None, 'repeat-max'), + (None, 'repeat-min'), + (None, 'replace'), + (None, 'required'), + (None, 'rev'), + (None, 'rightspacing'), + (None, 'rows'), + (None, 'rowspan'), + (None, 'rules'), + (None, 'scope'), + (None, 'selected'), + (None, 'shape'), + (None, 'size'), + (None, 'span'), + (None, 'src'), + (None, 'start'), + (None, 'step'), + (None, 'style'), + (None, 'summary'), + (None, 'suppress'), + (None, 'tabindex'), + (None, 'target'), + (None, 'template'), + (None, 'title'), + (None, 'toppadding'), + (None, 'type'), + (None, 'unselectable'), + (None, 'usemap'), + (None, 'urn'), + (None, 'valign'), + (None, 'value'), + (None, 'variable'), + (None, 'volume'), + (None, 'vspace'), + (None, 'vrml'), + (None, 'width'), + (None, 'wrap'), + (namespaces['xml'], 'lang'), + # MathML attributes + (None, 'actiontype'), + (None, 'align'), + (None, 'columnalign'), + (None, 'columnalign'), + (None, 'columnalign'), + (None, 'columnlines'), + (None, 'columnspacing'), + (None, 'columnspan'), + (None, 'depth'), + (None, 'display'), + (None, 'displaystyle'), + (None, 'equalcolumns'), + (None, 'equalrows'), + (None, 'fence'), + (None, 'fontstyle'), + (None, 'fontweight'), + (None, 'frame'), + (None, 'height'), + (None, 'linethickness'), + (None, 'lspace'), + (None, 'mathbackground'), + (None, 'mathcolor'), + (None, 'mathvariant'), + (None, 'mathvariant'), + (None, 'maxsize'), + (None, 'minsize'), + (None, 'other'), + (None, 'rowalign'), + (None, 'rowalign'), + (None, 'rowalign'), + (None, 'rowlines'), + (None, 'rowspacing'), + (None, 'rowspan'), + (None, 'rspace'), + (None, 'scriptlevel'), + (None, 'selection'), + (None, 'separator'), + (None, 'stretchy'), + (None, 'width'), + (None, 'width'), + (namespaces['xlink'], 'href'), + (namespaces['xlink'], 'show'), + (namespaces['xlink'], 'type'), + # SVG attributes + (None, 'accent-height'), + (None, 'accumulate'), + (None, 'additive'), + (None, 'alphabetic'), + (None, 'arabic-form'), + (None, 'ascent'), + (None, 'attributeName'), + (None, 'attributeType'), + (None, 'baseProfile'), + (None, 'bbox'), + (None, 'begin'), + (None, 'by'), + (None, 'calcMode'), + (None, 'cap-height'), + (None, 'class'), + (None, 'clip-path'), + (None, 'color'), + (None, 'color-rendering'), + (None, 'content'), + (None, 'cx'), + (None, 'cy'), + (None, 'd'), + (None, 'dx'), + (None, 'dy'), + (None, 'descent'), + (None, 'display'), + (None, 'dur'), + (None, 'end'), + (None, 'fill'), + (None, 'fill-opacity'), + (None, 'fill-rule'), + (None, 'font-family'), + (None, 'font-size'), + (None, 'font-stretch'), + (None, 'font-style'), + (None, 'font-variant'), + (None, 'font-weight'), + (None, 'from'), + (None, 'fx'), + (None, 'fy'), + (None, 'g1'), + (None, 'g2'), + (None, 'glyph-name'), + (None, 'gradientUnits'), + (None, 'hanging'), + (None, 'height'), + (None, 'horiz-adv-x'), + (None, 'horiz-origin-x'), + (None, 'id'), + (None, 'ideographic'), + (None, 'k'), + (None, 'keyPoints'), + (None, 'keySplines'), + (None, 'keyTimes'), + (None, 'lang'), + (None, 'marker-end'), + (None, 'marker-mid'), + (None, 'marker-start'), + (None, 'markerHeight'), + (None, 'markerUnits'), + (None, 'markerWidth'), + (None, 'mathematical'), + (None, 'max'), + (None, 'min'), + (None, 'name'), + (None, 'offset'), + (None, 'opacity'), + (None, 'orient'), + (None, 'origin'), + (None, 'overline-position'), + (None, 'overline-thickness'), + (None, 'panose-1'), + (None, 'path'), + (None, 'pathLength'), + (None, 'points'), + (None, 'preserveAspectRatio'), + (None, 'r'), + (None, 'refX'), + (None, 'refY'), + (None, 'repeatCount'), + (None, 'repeatDur'), + (None, 'requiredExtensions'), + (None, 'requiredFeatures'), + (None, 'restart'), + (None, 'rotate'), + (None, 'rx'), + (None, 'ry'), + (None, 'slope'), + (None, 'stemh'), + (None, 'stemv'), + (None, 'stop-color'), + (None, 'stop-opacity'), + (None, 'strikethrough-position'), + (None, 'strikethrough-thickness'), + (None, 'stroke'), + (None, 'stroke-dasharray'), + (None, 'stroke-dashoffset'), + (None, 'stroke-linecap'), + (None, 'stroke-linejoin'), + (None, 'stroke-miterlimit'), + (None, 'stroke-opacity'), + (None, 'stroke-width'), + (None, 'systemLanguage'), + (None, 'target'), + (None, 'text-anchor'), + (None, 'to'), + (None, 'transform'), + (None, 'type'), + (None, 'u1'), + (None, 'u2'), + (None, 'underline-position'), + (None, 'underline-thickness'), + (None, 'unicode'), + (None, 'unicode-range'), + (None, 'units-per-em'), + (None, 'values'), + (None, 'version'), + (None, 'viewBox'), + (None, 'visibility'), + (None, 'width'), + (None, 'widths'), + (None, 'x'), + (None, 'x-height'), + (None, 'x1'), + (None, 'x2'), + (namespaces['xlink'], 'actuate'), + (namespaces['xlink'], 'arcrole'), + (namespaces['xlink'], 'href'), + (namespaces['xlink'], 'role'), + (namespaces['xlink'], 'show'), + (namespaces['xlink'], 'title'), + (namespaces['xlink'], 'type'), + (namespaces['xml'], 'base'), + (namespaces['xml'], 'lang'), + (namespaces['xml'], 'space'), + (None, 'y'), + (None, 'y1'), + (None, 'y2'), + (None, 'zoomAndPan'), +)) + +attr_val_is_uri = frozenset(( + (None, 'href'), + (None, 'src'), + (None, 'cite'), + (None, 'action'), + (None, 'longdesc'), + (None, 'poster'), + (None, 'background'), + (None, 'datasrc'), + (None, 'dynsrc'), + (None, 'lowsrc'), + (None, 'ping'), + (namespaces['xlink'], 'href'), + (namespaces['xml'], 'base'), +)) + +svg_attr_val_allows_ref = frozenset(( + (None, 'clip-path'), + (None, 'color-profile'), + (None, 'cursor'), + (None, 'fill'), + (None, 'filter'), + (None, 'marker'), + (None, 'marker-start'), + (None, 'marker-mid'), + (None, 'marker-end'), + (None, 'mask'), + (None, 'stroke'), +)) + +svg_allow_local_href = frozenset(( + (None, 'altGlyph'), + (None, 'animate'), + (None, 'animateColor'), + (None, 'animateMotion'), + (None, 'animateTransform'), + (None, 'cursor'), + (None, 'feImage'), + (None, 'filter'), + (None, 'linearGradient'), + (None, 'pattern'), + (None, 'radialGradient'), + (None, 'textpath'), + (None, 'tref'), + (None, 'set'), + (None, 'use') +)) + +allowed_css_properties = frozenset(( + 'azimuth', + 'background-color', + 'border-bottom-color', + 'border-collapse', + 'border-color', + 'border-left-color', + 'border-right-color', + 'border-top-color', + 'clear', + 'color', + 'cursor', + 'direction', + 'display', + 'elevation', + 'float', + 'font', + 'font-family', + 'font-size', + 'font-style', + 'font-variant', + 'font-weight', + 'height', + 'letter-spacing', + 'line-height', + 'overflow', + 'pause', + 'pause-after', + 'pause-before', + 'pitch', + 'pitch-range', + 'richness', + 'speak', + 'speak-header', + 'speak-numeral', + 'speak-punctuation', + 'speech-rate', + 'stress', + 'text-align', + 'text-decoration', + 'text-indent', + 'unicode-bidi', + 'vertical-align', + 'voice-family', + 'volume', + 'white-space', + 'width', +)) + +allowed_css_keywords = frozenset(( + 'auto', + 'aqua', + 'black', + 'block', + 'blue', + 'bold', + 'both', + 'bottom', + 'brown', + 'center', + 'collapse', + 'dashed', + 'dotted', + 'fuchsia', + 'gray', + 'green', + '!important', + 'italic', + 'left', + 'lime', + 'maroon', + 'medium', + 'none', + 'navy', + 'normal', + 'nowrap', + 'olive', + 'pointer', + 'purple', + 'red', + 'right', + 'solid', + 'silver', + 'teal', + 'top', + 'transparent', + 'underline', + 'white', + 'yellow', +)) + +allowed_svg_properties = frozenset(( + 'fill', + 'fill-opacity', + 'fill-rule', + 'stroke', + 'stroke-width', + 'stroke-linecap', + 'stroke-linejoin', + 'stroke-opacity', +)) + +allowed_protocols = frozenset(( + 'ed2k', + 'ftp', + 'http', + 'https', + 'irc', + 'mailto', + 'news', + 'gopher', + 'nntp', + 'telnet', + 'webcal', + 'xmpp', + 'callto', + 'feed', + 'urn', + 'aim', + 'rsync', + 'tag', + 'ssh', + 'sftp', + 'rtsp', + 'afs', + 'data', +)) + +allowed_content_types = frozenset(( + 'image/png', + 'image/jpeg', + 'image/gif', + 'image/webp', + 'image/bmp', + 'text/plain', +)) + + +data_content_type = re.compile(r''' + ^ + # Match a content type <application>/<type> + (?P<content_type>[-a-zA-Z0-9.]+/[-a-zA-Z0-9.]+) + # Match any character set and encoding + (?:(?:;charset=(?:[-a-zA-Z0-9]+)(?:;(?:base64))?) + |(?:;(?:base64))?(?:;charset=(?:[-a-zA-Z0-9]+))?) + # Assume the rest is data + ,.* + $ + ''', + re.VERBOSE) + + +class Filter(base.Filter): + """Sanitizes token stream of XHTML+MathML+SVG and of inline style attributes""" + def __init__(self, + source, + allowed_elements=allowed_elements, + allowed_attributes=allowed_attributes, + allowed_css_properties=allowed_css_properties, + allowed_css_keywords=allowed_css_keywords, + allowed_svg_properties=allowed_svg_properties, + allowed_protocols=allowed_protocols, + allowed_content_types=allowed_content_types, + attr_val_is_uri=attr_val_is_uri, + svg_attr_val_allows_ref=svg_attr_val_allows_ref, + svg_allow_local_href=svg_allow_local_href): + """Creates a Filter + + :arg allowed_elements: set of elements to allow--everything else will + be escaped + + :arg allowed_attributes: set of attributes to allow in + elements--everything else will be stripped + + :arg allowed_css_properties: set of CSS properties to allow--everything + else will be stripped + + :arg allowed_css_keywords: set of CSS keywords to allow--everything + else will be stripped + + :arg allowed_svg_properties: set of SVG properties to allow--everything + else will be removed + + :arg allowed_protocols: set of allowed protocols for URIs + + :arg allowed_content_types: set of allowed content types for ``data`` URIs. + + :arg attr_val_is_uri: set of attributes that have URI values--values + that have a scheme not listed in ``allowed_protocols`` are removed + + :arg svg_attr_val_allows_ref: set of SVG attributes that can have + references + + :arg svg_allow_local_href: set of SVG elements that can have local + hrefs--these are removed + + """ + super(Filter, self).__init__(source) + self.allowed_elements = allowed_elements + self.allowed_attributes = allowed_attributes + self.allowed_css_properties = allowed_css_properties + self.allowed_css_keywords = allowed_css_keywords + self.allowed_svg_properties = allowed_svg_properties + self.allowed_protocols = allowed_protocols + self.allowed_content_types = allowed_content_types + self.attr_val_is_uri = attr_val_is_uri + self.svg_attr_val_allows_ref = svg_attr_val_allows_ref + self.svg_allow_local_href = svg_allow_local_href + + def __iter__(self): + for token in base.Filter.__iter__(self): + token = self.sanitize_token(token) + if token: + yield token + + # Sanitize the +html+, escaping all elements not in ALLOWED_ELEMENTS, and + # stripping out all attributes not in ALLOWED_ATTRIBUTES. Style attributes + # are parsed, and a restricted set, specified by ALLOWED_CSS_PROPERTIES and + # ALLOWED_CSS_KEYWORDS, are allowed through. attributes in ATTR_VAL_IS_URI + # are scanned, and only URI schemes specified in ALLOWED_PROTOCOLS are + # allowed. + # + # sanitize_html('<script> do_nasty_stuff() </script>') + # => <script> do_nasty_stuff() </script> + # sanitize_html('<a href="javascript: sucker();">Click here for $100</a>') + # => <a>Click here for $100</a> + def sanitize_token(self, token): + + # accommodate filters which use token_type differently + token_type = token["type"] + if token_type in ("StartTag", "EndTag", "EmptyTag"): + name = token["name"] + namespace = token["namespace"] + if ((namespace, name) in self.allowed_elements or + (namespace is None and + (namespaces["html"], name) in self.allowed_elements)): + return self.allowed_token(token) + else: + return self.disallowed_token(token) + elif token_type == "Comment": + pass + else: + return token + + def allowed_token(self, token): + if "data" in token: + attrs = token["data"] + attr_names = set(attrs.keys()) + + # Remove forbidden attributes + for to_remove in (attr_names - self.allowed_attributes): + del token["data"][to_remove] + attr_names.remove(to_remove) + + # Remove attributes with disallowed URL values + for attr in (attr_names & self.attr_val_is_uri): + assert attr in attrs + # I don't have a clue where this regexp comes from or why it matches those + # characters, nor why we call unescape. I just know it's always been here. + # Should you be worried by this comment in a sanitizer? Yes. On the other hand, all + # this will do is remove *more* than it otherwise would. + val_unescaped = re.sub("[`\x00-\x20\x7f-\xa0\\s]+", '', + unescape(attrs[attr])).lower() + # remove replacement characters from unescaped characters + val_unescaped = val_unescaped.replace("\ufffd", "") + try: + uri = urlparse.urlparse(val_unescaped) + except ValueError: + uri = None + del attrs[attr] + if uri and uri.scheme: + if uri.scheme not in self.allowed_protocols: + del attrs[attr] + if uri.scheme == 'data': + m = data_content_type.match(uri.path) + if not m: + del attrs[attr] + elif m.group('content_type') not in self.allowed_content_types: + del attrs[attr] + + for attr in self.svg_attr_val_allows_ref: + if attr in attrs: + attrs[attr] = re.sub(r'url\s*\(\s*[^#\s][^)]+?\)', + ' ', + unescape(attrs[attr])) + if (token["name"] in self.svg_allow_local_href and + (namespaces['xlink'], 'href') in attrs and re.search(r'^\s*[^#\s].*', + attrs[(namespaces['xlink'], 'href')])): + del attrs[(namespaces['xlink'], 'href')] + if (None, 'style') in attrs: + attrs[(None, 'style')] = self.sanitize_css(attrs[(None, 'style')]) + token["data"] = attrs + return token + + def disallowed_token(self, token): + token_type = token["type"] + if token_type == "EndTag": + token["data"] = "</%s>" % token["name"] + elif token["data"]: + assert token_type in ("StartTag", "EmptyTag") + attrs = [] + for (ns, name), v in token["data"].items(): + attrs.append(' %s="%s"' % (name if ns is None else "%s:%s" % (prefixes[ns], name), escape(v))) + token["data"] = "<%s%s>" % (token["name"], ''.join(attrs)) + else: + token["data"] = "<%s>" % token["name"] + if token.get("selfClosing"): + token["data"] = token["data"][:-1] + "/>" + + token["type"] = "Characters" + + del token["name"] + return token + + def sanitize_css(self, style): + # disallow urls + style = re.compile(r'url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) + + # gauntlet + if not re.match(r"""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): + return '' + if not re.match(r"^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): + return '' + + clean = [] + for prop, value in re.findall(r"([-\w]+)\s*:\s*([^:;]*)", style): + if not value: + continue + if prop.lower() in self.allowed_css_properties: + clean.append(prop + ': ' + value + ';') + elif prop.split('-')[0].lower() in ['background', 'border', 'margin', + 'padding']: + for keyword in value.split(): + if keyword not in self.allowed_css_keywords and \ + not re.match(r"^(#[0-9a-fA-F]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): # noqa + break + else: + clean.append(prop + ': ' + value + ';') + elif prop.lower() in self.allowed_svg_properties: + clean.append(prop + ': ' + value + ';') + + return ' '.join(clean) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py new file mode 100644 index 0000000..0d12584 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py @@ -0,0 +1,38 @@ +from __future__ import absolute_import, division, unicode_literals + +import re + +from . import base +from ..constants import rcdataElements, spaceCharacters +spaceCharacters = "".join(spaceCharacters) + +SPACES_REGEX = re.compile("[%s]+" % spaceCharacters) + + +class Filter(base.Filter): + """Collapses whitespace except in pre, textarea, and script elements""" + spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements)) + + def __iter__(self): + preserve = 0 + for token in base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag" \ + and (preserve or token["name"] in self.spacePreserveElements): + preserve += 1 + + elif type == "EndTag" and preserve: + preserve -= 1 + + elif not preserve and type == "SpaceCharacters" and token["data"]: + # Test on token["data"] above to not introduce spaces where there were not + token["data"] = " " + + elif not preserve and type == "Characters": + token["data"] = collapse_spaces(token["data"]) + + yield token + + +def collapse_spaces(text): + return SPACES_REGEX.sub(' ', text) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py new file mode 100644 index 0000000..ae41a13 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py @@ -0,0 +1,2791 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import with_metaclass, viewkeys + +import types +from collections import OrderedDict + +from . import _inputstream +from . import _tokenizer + +from . import treebuilders +from .treebuilders.base import Marker + +from . import _utils +from .constants import ( + spaceCharacters, asciiUpper2Lower, + specialElements, headingElements, cdataElements, rcdataElements, + tokenTypes, tagTokenTypes, + namespaces, + htmlIntegrationPointElements, mathmlTextIntegrationPointElements, + adjustForeignAttributes as adjustForeignAttributesMap, + adjustMathMLAttributes, adjustSVGAttributes, + E, + _ReparseException +) + + +def parse(doc, treebuilder="etree", namespaceHTMLElements=True, **kwargs): + """Parse an HTML document as a string or file-like object into a tree + + :arg doc: the document to parse as a string or file-like object + + :arg treebuilder: the treebuilder to use when parsing + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + :returns: parsed tree + + Example: + + >>> from html5lib.html5parser import parse + >>> parse('<html><body><p>This is a doc</p></body></html>') + <Element u'{http://www.w3.org/1999/xhtml}html' at 0x7feac4909db0> + + """ + tb = treebuilders.getTreeBuilder(treebuilder) + p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) + return p.parse(doc, **kwargs) + + +def parseFragment(doc, container="div", treebuilder="etree", namespaceHTMLElements=True, **kwargs): + """Parse an HTML fragment as a string or file-like object into a tree + + :arg doc: the fragment to parse as a string or file-like object + + :arg container: the container context to parse the fragment in + + :arg treebuilder: the treebuilder to use when parsing + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + :returns: parsed tree + + Example: + + >>> from html5lib.html5libparser import parseFragment + >>> parseFragment('<b>this is a fragment</b>') + <Element u'DOCUMENT_FRAGMENT' at 0x7feac484b090> + + """ + tb = treebuilders.getTreeBuilder(treebuilder) + p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements) + return p.parseFragment(doc, container=container, **kwargs) + + +def method_decorator_metaclass(function): + class Decorated(type): + def __new__(meta, classname, bases, classDict): + for attributeName, attribute in classDict.items(): + if isinstance(attribute, types.FunctionType): + attribute = function(attribute) + + classDict[attributeName] = attribute + return type.__new__(meta, classname, bases, classDict) + return Decorated + + +class HTMLParser(object): + """HTML parser + + Generates a tree structure from a stream of (possibly malformed) HTML. + + """ + + def __init__(self, tree=None, strict=False, namespaceHTMLElements=True, debug=False): + """ + :arg tree: a treebuilder class controlling the type of tree that will be + returned. Built in treebuilders can be accessed through + html5lib.treebuilders.getTreeBuilder(treeType) + + :arg strict: raise an exception when a parse error is encountered + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + :arg debug: whether or not to enable debug mode which logs things + + Example: + + >>> from html5lib.html5parser import HTMLParser + >>> parser = HTMLParser() # generates parser with etree builder + >>> parser = HTMLParser('lxml', strict=True) # generates parser with lxml builder which is strict + + """ + + # Raise an exception on the first error encountered + self.strict = strict + + if tree is None: + tree = treebuilders.getTreeBuilder("etree") + self.tree = tree(namespaceHTMLElements) + self.errors = [] + + self.phases = dict([(name, cls(self, self.tree)) for name, cls in + getPhases(debug).items()]) + + def _parse(self, stream, innerHTML=False, container="div", scripting=False, **kwargs): + + self.innerHTMLMode = innerHTML + self.container = container + self.scripting = scripting + self.tokenizer = _tokenizer.HTMLTokenizer(stream, parser=self, **kwargs) + self.reset() + + try: + self.mainLoop() + except _ReparseException: + self.reset() + self.mainLoop() + + def reset(self): + self.tree.reset() + self.firstStartTag = False + self.errors = [] + self.log = [] # only used with debug mode + # "quirks" / "limited quirks" / "no quirks" + self.compatMode = "no quirks" + + if self.innerHTMLMode: + self.innerHTML = self.container.lower() + + if self.innerHTML in cdataElements: + self.tokenizer.state = self.tokenizer.rcdataState + elif self.innerHTML in rcdataElements: + self.tokenizer.state = self.tokenizer.rawtextState + elif self.innerHTML == 'plaintext': + self.tokenizer.state = self.tokenizer.plaintextState + else: + # state already is data state + # self.tokenizer.state = self.tokenizer.dataState + pass + self.phase = self.phases["beforeHtml"] + self.phase.insertHtmlElement() + self.resetInsertionMode() + else: + self.innerHTML = False # pylint:disable=redefined-variable-type + self.phase = self.phases["initial"] + + self.lastPhase = None + + self.beforeRCDataPhase = None + + self.framesetOK = True + + @property + def documentEncoding(self): + """Name of the character encoding that was used to decode the input stream, or + :obj:`None` if that is not determined yet + + """ + if not hasattr(self, 'tokenizer'): + return None + return self.tokenizer.stream.charEncoding[0].name + + def isHTMLIntegrationPoint(self, element): + if (element.name == "annotation-xml" and + element.namespace == namespaces["mathml"]): + return ("encoding" in element.attributes and + element.attributes["encoding"].translate( + asciiUpper2Lower) in + ("text/html", "application/xhtml+xml")) + else: + return (element.namespace, element.name) in htmlIntegrationPointElements + + def isMathMLTextIntegrationPoint(self, element): + return (element.namespace, element.name) in mathmlTextIntegrationPointElements + + def mainLoop(self): + CharactersToken = tokenTypes["Characters"] + SpaceCharactersToken = tokenTypes["SpaceCharacters"] + StartTagToken = tokenTypes["StartTag"] + EndTagToken = tokenTypes["EndTag"] + CommentToken = tokenTypes["Comment"] + DoctypeToken = tokenTypes["Doctype"] + ParseErrorToken = tokenTypes["ParseError"] + + for token in self.normalizedTokens(): + prev_token = None + new_token = token + while new_token is not None: + prev_token = new_token + currentNode = self.tree.openElements[-1] if self.tree.openElements else None + currentNodeNamespace = currentNode.namespace if currentNode else None + currentNodeName = currentNode.name if currentNode else None + + type = new_token["type"] + + if type == ParseErrorToken: + self.parseError(new_token["data"], new_token.get("datavars", {})) + new_token = None + else: + if (len(self.tree.openElements) == 0 or + currentNodeNamespace == self.tree.defaultNamespace or + (self.isMathMLTextIntegrationPoint(currentNode) and + ((type == StartTagToken and + token["name"] not in frozenset(["mglyph", "malignmark"])) or + type in (CharactersToken, SpaceCharactersToken))) or + (currentNodeNamespace == namespaces["mathml"] and + currentNodeName == "annotation-xml" and + type == StartTagToken and + token["name"] == "svg") or + (self.isHTMLIntegrationPoint(currentNode) and + type in (StartTagToken, CharactersToken, SpaceCharactersToken))): + phase = self.phase + else: + phase = self.phases["inForeignContent"] + + if type == CharactersToken: + new_token = phase.processCharacters(new_token) + elif type == SpaceCharactersToken: + new_token = phase.processSpaceCharacters(new_token) + elif type == StartTagToken: + new_token = phase.processStartTag(new_token) + elif type == EndTagToken: + new_token = phase.processEndTag(new_token) + elif type == CommentToken: + new_token = phase.processComment(new_token) + elif type == DoctypeToken: + new_token = phase.processDoctype(new_token) + + if (type == StartTagToken and prev_token["selfClosing"] and + not prev_token["selfClosingAcknowledged"]): + self.parseError("non-void-element-with-trailing-solidus", + {"name": prev_token["name"]}) + + # When the loop finishes it's EOF + reprocess = True + phases = [] + while reprocess: + phases.append(self.phase) + reprocess = self.phase.processEOF() + if reprocess: + assert self.phase not in phases + + def normalizedTokens(self): + for token in self.tokenizer: + yield self.normalizeToken(token) + + def parse(self, stream, *args, **kwargs): + """Parse a HTML document into a well-formed tree + + :arg stream: a file-like object or string containing the HTML to be parsed + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element). + + :arg scripting: treat noscript elements as if JavaScript was turned on + + :returns: parsed tree + + Example: + + >>> from html5lib.html5parser import HTMLParser + >>> parser = HTMLParser() + >>> parser.parse('<html><body><p>This is a doc</p></body></html>') + <Element u'{http://www.w3.org/1999/xhtml}html' at 0x7feac4909db0> + + """ + self._parse(stream, False, None, *args, **kwargs) + return self.tree.getDocument() + + def parseFragment(self, stream, *args, **kwargs): + """Parse a HTML fragment into a well-formed tree fragment + + :arg container: name of the element we're setting the innerHTML + property if set to None, default to 'div' + + :arg stream: a file-like object or string containing the HTML to be parsed + + The optional encoding parameter must be a string that indicates + the encoding. If specified, that encoding will be used, + regardless of any BOM or later declaration (such as in a meta + element) + + :arg scripting: treat noscript elements as if JavaScript was turned on + + :returns: parsed tree + + Example: + + >>> from html5lib.html5libparser import HTMLParser + >>> parser = HTMLParser() + >>> parser.parseFragment('<b>this is a fragment</b>') + <Element u'DOCUMENT_FRAGMENT' at 0x7feac484b090> + + """ + self._parse(stream, True, *args, **kwargs) + return self.tree.getFragment() + + def parseError(self, errorcode="XXX-undefined-error", datavars=None): + # XXX The idea is to make errorcode mandatory. + if datavars is None: + datavars = {} + self.errors.append((self.tokenizer.stream.position(), errorcode, datavars)) + if self.strict: + raise ParseError(E[errorcode] % datavars) + + def normalizeToken(self, token): + # HTML5 specific normalizations to the token stream + if token["type"] == tokenTypes["StartTag"]: + raw = token["data"] + token["data"] = OrderedDict(raw) + if len(raw) > len(token["data"]): + # we had some duplicated attribute, fix so first wins + token["data"].update(raw[::-1]) + + return token + + def adjustMathMLAttributes(self, token): + adjust_attributes(token, adjustMathMLAttributes) + + def adjustSVGAttributes(self, token): + adjust_attributes(token, adjustSVGAttributes) + + def adjustForeignAttributes(self, token): + adjust_attributes(token, adjustForeignAttributesMap) + + def reparseTokenNormal(self, token): + # pylint:disable=unused-argument + self.parser.phase() + + def resetInsertionMode(self): + # The name of this method is mostly historical. (It's also used in the + # specification.) + last = False + newModes = { + "select": "inSelect", + "td": "inCell", + "th": "inCell", + "tr": "inRow", + "tbody": "inTableBody", + "thead": "inTableBody", + "tfoot": "inTableBody", + "caption": "inCaption", + "colgroup": "inColumnGroup", + "table": "inTable", + "head": "inBody", + "body": "inBody", + "frameset": "inFrameset", + "html": "beforeHead" + } + for node in self.tree.openElements[::-1]: + nodeName = node.name + new_phase = None + if node == self.tree.openElements[0]: + assert self.innerHTML + last = True + nodeName = self.innerHTML + # Check for conditions that should only happen in the innerHTML + # case + if nodeName in ("select", "colgroup", "head", "html"): + assert self.innerHTML + + if not last and node.namespace != self.tree.defaultNamespace: + continue + + if nodeName in newModes: + new_phase = self.phases[newModes[nodeName]] + break + elif last: + new_phase = self.phases["inBody"] + break + + self.phase = new_phase + + def parseRCDataRawtext(self, token, contentType): + # Generic RCDATA/RAWTEXT Parsing algorithm + assert contentType in ("RAWTEXT", "RCDATA") + + self.tree.insertElement(token) + + if contentType == "RAWTEXT": + self.tokenizer.state = self.tokenizer.rawtextState + else: + self.tokenizer.state = self.tokenizer.rcdataState + + self.originalPhase = self.phase + + self.phase = self.phases["text"] + + +@_utils.memoize +def getPhases(debug): + def log(function): + """Logger that records which phase processes each token""" + type_names = dict((value, key) for key, value in + tokenTypes.items()) + + def wrapped(self, *args, **kwargs): + if function.__name__.startswith("process") and len(args) > 0: + token = args[0] + try: + info = {"type": type_names[token['type']]} + except: + raise + if token['type'] in tagTokenTypes: + info["name"] = token['name'] + + self.parser.log.append((self.parser.tokenizer.state.__name__, + self.parser.phase.__class__.__name__, + self.__class__.__name__, + function.__name__, + info)) + return function(self, *args, **kwargs) + else: + return function(self, *args, **kwargs) + return wrapped + + def getMetaclass(use_metaclass, metaclass_func): + if use_metaclass: + return method_decorator_metaclass(metaclass_func) + else: + return type + + # pylint:disable=unused-argument + class Phase(with_metaclass(getMetaclass(debug, log))): + """Base class for helper object that implements each phase of processing + """ + + def __init__(self, parser, tree): + self.parser = parser + self.tree = tree + + def processEOF(self): + raise NotImplementedError + + def processComment(self, token): + # For most phases the following is correct. Where it's not it will be + # overridden. + self.tree.insertComment(token, self.tree.openElements[-1]) + + def processDoctype(self, token): + self.parser.parseError("unexpected-doctype") + + def processCharacters(self, token): + self.tree.insertText(token["data"]) + + def processSpaceCharacters(self, token): + self.tree.insertText(token["data"]) + + def processStartTag(self, token): + return self.startTagHandler[token["name"]](token) + + def startTagHtml(self, token): + if not self.parser.firstStartTag and token["name"] == "html": + self.parser.parseError("non-html-root") + # XXX Need a check here to see if the first start tag token emitted is + # this token... If it's not, invoke self.parser.parseError(). + for attr, value in token["data"].items(): + if attr not in self.tree.openElements[0].attributes: + self.tree.openElements[0].attributes[attr] = value + self.parser.firstStartTag = False + + def processEndTag(self, token): + return self.endTagHandler[token["name"]](token) + + class InitialPhase(Phase): + def processSpaceCharacters(self, token): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + correct = token["correct"] + + if (name != "html" or publicId is not None or + systemId is not None and systemId != "about:legacy-compat"): + self.parser.parseError("unknown-doctype") + + if publicId is None: + publicId = "" + + self.tree.insertDoctype(token) + + if publicId != "": + publicId = publicId.translate(asciiUpper2Lower) + + if (not correct or token["name"] != "html" or + publicId.startswith( + ("+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//")) or + publicId in ("-//w3o//dtd w3 html strict 3.0//en//", + "-/w3c/dtd html 4.0 transitional/en", + "html") or + publicId.startswith( + ("-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//")) and + systemId is None or + systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"): + self.parser.compatMode = "quirks" + elif (publicId.startswith( + ("-//w3c//dtd xhtml 1.0 frameset//", + "-//w3c//dtd xhtml 1.0 transitional//")) or + publicId.startswith( + ("-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//")) and + systemId is not None): + self.parser.compatMode = "limited quirks" + + self.parser.phase = self.parser.phases["beforeHtml"] + + def anythingElse(self): + self.parser.compatMode = "quirks" + self.parser.phase = self.parser.phases["beforeHtml"] + + def processCharacters(self, token): + self.parser.parseError("expected-doctype-but-got-chars") + self.anythingElse() + return token + + def processStartTag(self, token): + self.parser.parseError("expected-doctype-but-got-start-tag", + {"name": token["name"]}) + self.anythingElse() + return token + + def processEndTag(self, token): + self.parser.parseError("expected-doctype-but-got-end-tag", + {"name": token["name"]}) + self.anythingElse() + return token + + def processEOF(self): + self.parser.parseError("expected-doctype-but-got-eof") + self.anythingElse() + return True + + class BeforeHtmlPhase(Phase): + # helper methods + def insertHtmlElement(self): + self.tree.insertRoot(impliedTagToken("html", "StartTag")) + self.parser.phase = self.parser.phases["beforeHead"] + + # other + def processEOF(self): + self.insertHtmlElement() + return True + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + pass + + def processCharacters(self, token): + self.insertHtmlElement() + return token + + def processStartTag(self, token): + if token["name"] == "html": + self.parser.firstStartTag = True + self.insertHtmlElement() + return token + + def processEndTag(self, token): + if token["name"] not in ("head", "body", "html", "br"): + self.parser.parseError("unexpected-end-tag-before-html", + {"name": token["name"]}) + else: + self.insertHtmlElement() + return token + + class BeforeHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("head", "body", "html", "br"), self.endTagImplyHead) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.startTagHead(impliedTagToken("head", "StartTag")) + return True + + def processSpaceCharacters(self, token): + pass + + def processCharacters(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagHead(self, token): + self.tree.insertElement(token) + self.tree.headPointer = self.tree.openElements[-1] + self.parser.phase = self.parser.phases["inHead"] + + def startTagOther(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def endTagImplyHead(self, token): + self.startTagHead(impliedTagToken("head", "StartTag")) + return token + + def endTagOther(self, token): + self.parser.parseError("end-tag-after-implied-root", + {"name": token["name"]}) + + class InHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("title", self.startTagTitle), + (("noframes", "style"), self.startTagNoFramesStyle), + ("noscript", self.startTagNoscript), + ("script", self.startTagScript), + (("base", "basefont", "bgsound", "command", "link"), + self.startTagBaseLinkCommand), + ("meta", self.startTagMeta), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("head", self.endTagHead), + (("br", "html", "body"), self.endTagHtmlBodyBr) + ]) + self.endTagHandler.default = self.endTagOther + + # the real thing + def processEOF(self): + self.anythingElse() + return True + + def processCharacters(self, token): + self.anythingElse() + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagHead(self, token): + self.parser.parseError("two-heads-are-not-better-than-one") + + def startTagBaseLinkCommand(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagMeta(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + attributes = token["data"] + if self.parser.tokenizer.stream.charEncoding[1] == "tentative": + if "charset" in attributes: + self.parser.tokenizer.stream.changeEncoding(attributes["charset"]) + elif ("content" in attributes and + "http-equiv" in attributes and + attributes["http-equiv"].lower() == "content-type"): + # Encoding it as UTF-8 here is a hack, as really we should pass + # the abstract Unicode string, and just use the + # ContentAttrParser on that, but using UTF-8 allows all chars + # to be encoded and as a ASCII-superset works. + data = _inputstream.EncodingBytes(attributes["content"].encode("utf-8")) + parser = _inputstream.ContentAttrParser(data) + codec = parser.parse() + self.parser.tokenizer.stream.changeEncoding(codec) + + def startTagTitle(self, token): + self.parser.parseRCDataRawtext(token, "RCDATA") + + def startTagNoFramesStyle(self, token): + # Need to decide whether to implement the scripting-disabled case + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagNoscript(self, token): + if self.parser.scripting: + self.parser.parseRCDataRawtext(token, "RAWTEXT") + else: + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inHeadNoscript"] + + def startTagScript(self, token): + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState + self.parser.originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["text"] + + def startTagOther(self, token): + self.anythingElse() + return token + + def endTagHead(self, token): + node = self.parser.tree.openElements.pop() + assert node.name == "head", "Expected head got %s" % node.name + self.parser.phase = self.parser.phases["afterHead"] + + def endTagHtmlBodyBr(self, token): + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + self.endTagHead(impliedTagToken("head")) + + class InHeadNoscriptPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("basefont", "bgsound", "link", "meta", "noframes", "style"), self.startTagBaseLinkCommand), + (("head", "noscript"), self.startTagHeadNoscript), + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("noscript", self.endTagNoscript), + ("br", self.endTagBr), + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.parser.parseError("eof-in-head-noscript") + self.anythingElse() + return True + + def processComment(self, token): + return self.parser.phases["inHead"].processComment(token) + + def processCharacters(self, token): + self.parser.parseError("char-in-head-noscript") + self.anythingElse() + return token + + def processSpaceCharacters(self, token): + return self.parser.phases["inHead"].processSpaceCharacters(token) + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagBaseLinkCommand(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagHeadNoscript(self, token): + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + + def startTagOther(self, token): + self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) + self.anythingElse() + return token + + def endTagNoscript(self, token): + node = self.parser.tree.openElements.pop() + assert node.name == "noscript", "Expected noscript got %s" % node.name + self.parser.phase = self.parser.phases["inHead"] + + def endTagBr(self, token): + self.parser.parseError("unexpected-inhead-noscript-tag", {"name": token["name"]}) + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + # Caller must raise parse error first! + self.endTagNoscript(impliedTagToken("noscript")) + + class AfterHeadPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("body", self.startTagBody), + ("frameset", self.startTagFrameset), + (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", + "style", "title"), + self.startTagFromHead), + ("head", self.startTagHead) + ]) + self.startTagHandler.default = self.startTagOther + self.endTagHandler = _utils.MethodDispatcher([(("body", "html", "br"), + self.endTagHtmlBodyBr)]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.anythingElse() + return True + + def processCharacters(self, token): + self.anythingElse() + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagBody(self, token): + self.parser.framesetOK = False + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inBody"] + + def startTagFrameset(self, token): + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inFrameset"] + + def startTagFromHead(self, token): + self.parser.parseError("unexpected-start-tag-out-of-my-head", + {"name": token["name"]}) + self.tree.openElements.append(self.tree.headPointer) + self.parser.phases["inHead"].processStartTag(token) + for node in self.tree.openElements[::-1]: + if node.name == "head": + self.tree.openElements.remove(node) + break + + def startTagHead(self, token): + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + + def startTagOther(self, token): + self.anythingElse() + return token + + def endTagHtmlBodyBr(self, token): + self.anythingElse() + return token + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def anythingElse(self): + self.tree.insertElement(impliedTagToken("body", "StartTag")) + self.parser.phase = self.parser.phases["inBody"] + self.parser.framesetOK = True + + class InBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody + # the really-really-really-very crazy mode + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + # Set this to the default handler + self.processSpaceCharacters = self.processSpaceCharactersNonPre + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("base", "basefont", "bgsound", "command", "link", "meta", + "script", "style", "title"), + self.startTagProcessInHead), + ("body", self.startTagBody), + ("frameset", self.startTagFrameset), + (("address", "article", "aside", "blockquote", "center", "details", + "dir", "div", "dl", "fieldset", "figcaption", "figure", + "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", + "section", "summary", "ul"), + self.startTagCloseP), + (headingElements, self.startTagHeading), + (("pre", "listing"), self.startTagPreListing), + ("form", self.startTagForm), + (("li", "dd", "dt"), self.startTagListItem), + ("plaintext", self.startTagPlaintext), + ("a", self.startTagA), + (("b", "big", "code", "em", "font", "i", "s", "small", "strike", + "strong", "tt", "u"), self.startTagFormatting), + ("nobr", self.startTagNobr), + ("button", self.startTagButton), + (("applet", "marquee", "object"), self.startTagAppletMarqueeObject), + ("xmp", self.startTagXmp), + ("table", self.startTagTable), + (("area", "br", "embed", "img", "keygen", "wbr"), + self.startTagVoidFormatting), + (("param", "source", "track"), self.startTagParamSource), + ("input", self.startTagInput), + ("hr", self.startTagHr), + ("image", self.startTagImage), + ("isindex", self.startTagIsIndex), + ("textarea", self.startTagTextarea), + ("iframe", self.startTagIFrame), + ("noscript", self.startTagNoscript), + (("noembed", "noframes"), self.startTagRawtext), + ("select", self.startTagSelect), + (("rp", "rt"), self.startTagRpRt), + (("option", "optgroup"), self.startTagOpt), + (("math"), self.startTagMath), + (("svg"), self.startTagSvg), + (("caption", "col", "colgroup", "frame", "head", + "tbody", "td", "tfoot", "th", "thead", + "tr"), self.startTagMisplaced) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("body", self.endTagBody), + ("html", self.endTagHtml), + (("address", "article", "aside", "blockquote", "button", "center", + "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", + "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", + "section", "summary", "ul"), self.endTagBlock), + ("form", self.endTagForm), + ("p", self.endTagP), + (("dd", "dt", "li"), self.endTagListItem), + (headingElements, self.endTagHeading), + (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", + "strike", "strong", "tt", "u"), self.endTagFormatting), + (("applet", "marquee", "object"), self.endTagAppletMarqueeObject), + ("br", self.endTagBr), + ]) + self.endTagHandler.default = self.endTagOther + + def isMatchingFormattingElement(self, node1, node2): + return (node1.name == node2.name and + node1.namespace == node2.namespace and + node1.attributes == node2.attributes) + + # helper + def addFormattingElement(self, token): + self.tree.insertElement(token) + element = self.tree.openElements[-1] + + matchingElements = [] + for node in self.tree.activeFormattingElements[::-1]: + if node is Marker: + break + elif self.isMatchingFormattingElement(node, element): + matchingElements.append(node) + + assert len(matchingElements) <= 3 + if len(matchingElements) == 3: + self.tree.activeFormattingElements.remove(matchingElements[-1]) + self.tree.activeFormattingElements.append(element) + + # the real deal + def processEOF(self): + allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td", + "tfoot", "th", "thead", "tr", "body", + "html")) + for node in self.tree.openElements[::-1]: + if node.name not in allowed_elements: + self.parser.parseError("expected-closing-tag-but-got-eof") + break + # Stop parsing + + def processSpaceCharactersDropNewline(self, token): + # Sometimes (start of <pre>, <listing>, and <textarea> blocks) we + # want to drop leading newlines + data = token["data"] + self.processSpaceCharacters = self.processSpaceCharactersNonPre + if (data.startswith("\n") and + self.tree.openElements[-1].name in ("pre", "listing", "textarea") and + not self.tree.openElements[-1].hasContent()): + data = data[1:] + if data: + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(data) + + def processCharacters(self, token): + if token["data"] == "\u0000": + # The tokenizer should always emit null on its own + return + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(token["data"]) + # This must be bad for performance + if (self.parser.framesetOK and + any([char not in spaceCharacters + for char in token["data"]])): + self.parser.framesetOK = False + + def processSpaceCharactersNonPre(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertText(token["data"]) + + def startTagProcessInHead(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagBody(self, token): + self.parser.parseError("unexpected-start-tag", {"name": "body"}) + if (len(self.tree.openElements) == 1 or + self.tree.openElements[1].name != "body"): + assert self.parser.innerHTML + else: + self.parser.framesetOK = False + for attr, value in token["data"].items(): + if attr not in self.tree.openElements[1].attributes: + self.tree.openElements[1].attributes[attr] = value + + def startTagFrameset(self, token): + self.parser.parseError("unexpected-start-tag", {"name": "frameset"}) + if (len(self.tree.openElements) == 1 or self.tree.openElements[1].name != "body"): + assert self.parser.innerHTML + elif not self.parser.framesetOK: + pass + else: + if self.tree.openElements[1].parent: + self.tree.openElements[1].parent.removeChild(self.tree.openElements[1]) + while self.tree.openElements[-1].name != "html": + self.tree.openElements.pop() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inFrameset"] + + def startTagCloseP(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + + def startTagPreListing(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.framesetOK = False + self.processSpaceCharacters = self.processSpaceCharactersDropNewline + + def startTagForm(self, token): + if self.tree.formPointer: + self.parser.parseError("unexpected-start-tag", {"name": "form"}) + else: + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.tree.formPointer = self.tree.openElements[-1] + + def startTagListItem(self, token): + self.parser.framesetOK = False + + stopNamesMap = {"li": ["li"], + "dt": ["dt", "dd"], + "dd": ["dt", "dd"]} + stopNames = stopNamesMap[token["name"]] + for node in reversed(self.tree.openElements): + if node.name in stopNames: + self.parser.phase.processEndTag( + impliedTagToken(node.name, "EndTag")) + break + if (node.nameTuple in specialElements and + node.name not in ("address", "div", "p")): + break + + if self.tree.elementInScope("p", variant="button"): + self.parser.phase.processEndTag( + impliedTagToken("p", "EndTag")) + + self.tree.insertElement(token) + + def startTagPlaintext(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.plaintextState + + def startTagHeading(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + if self.tree.openElements[-1].name in headingElements: + self.parser.parseError("unexpected-start-tag", {"name": token["name"]}) + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagA(self, token): + afeAElement = self.tree.elementInActiveFormattingElements("a") + if afeAElement: + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "a", "endName": "a"}) + self.endTagFormatting(impliedTagToken("a")) + if afeAElement in self.tree.openElements: + self.tree.openElements.remove(afeAElement) + if afeAElement in self.tree.activeFormattingElements: + self.tree.activeFormattingElements.remove(afeAElement) + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagFormatting(self, token): + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagNobr(self, token): + self.tree.reconstructActiveFormattingElements() + if self.tree.elementInScope("nobr"): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "nobr", "endName": "nobr"}) + self.processEndTag(impliedTagToken("nobr")) + # XXX Need tests that trigger the following + self.tree.reconstructActiveFormattingElements() + self.addFormattingElement(token) + + def startTagButton(self, token): + if self.tree.elementInScope("button"): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "button", "endName": "button"}) + self.processEndTag(impliedTagToken("button")) + return token + else: + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.parser.framesetOK = False + + def startTagAppletMarqueeObject(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.tree.activeFormattingElements.append(Marker) + self.parser.framesetOK = False + + def startTagXmp(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.reconstructActiveFormattingElements() + self.parser.framesetOK = False + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagTable(self, token): + if self.parser.compatMode != "quirks": + if self.tree.elementInScope("p", variant="button"): + self.processEndTag(impliedTagToken("p")) + self.tree.insertElement(token) + self.parser.framesetOK = False + self.parser.phase = self.parser.phases["inTable"] + + def startTagVoidFormatting(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + self.parser.framesetOK = False + + def startTagInput(self, token): + framesetOK = self.parser.framesetOK + self.startTagVoidFormatting(token) + if ("type" in token["data"] and + token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): + # input type=hidden doesn't change framesetOK + self.parser.framesetOK = framesetOK + + def startTagParamSource(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagHr(self, token): + if self.tree.elementInScope("p", variant="button"): + self.endTagP(impliedTagToken("p")) + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + self.parser.framesetOK = False + + def startTagImage(self, token): + # No really... + self.parser.parseError("unexpected-start-tag-treated-as", + {"originalName": "image", "newName": "img"}) + self.processStartTag(impliedTagToken("img", "StartTag", + attributes=token["data"], + selfClosing=token["selfClosing"])) + + def startTagIsIndex(self, token): + self.parser.parseError("deprecated-tag", {"name": "isindex"}) + if self.tree.formPointer: + return + form_attrs = {} + if "action" in token["data"]: + form_attrs["action"] = token["data"]["action"] + self.processStartTag(impliedTagToken("form", "StartTag", + attributes=form_attrs)) + self.processStartTag(impliedTagToken("hr", "StartTag")) + self.processStartTag(impliedTagToken("label", "StartTag")) + # XXX Localization ... + if "prompt" in token["data"]: + prompt = token["data"]["prompt"] + else: + prompt = "This is a searchable index. Enter search keywords: " + self.processCharacters( + {"type": tokenTypes["Characters"], "data": prompt}) + attributes = token["data"].copy() + if "action" in attributes: + del attributes["action"] + if "prompt" in attributes: + del attributes["prompt"] + attributes["name"] = "isindex" + self.processStartTag(impliedTagToken("input", "StartTag", + attributes=attributes, + selfClosing=token["selfClosing"])) + self.processEndTag(impliedTagToken("label")) + self.processStartTag(impliedTagToken("hr", "StartTag")) + self.processEndTag(impliedTagToken("form")) + + def startTagTextarea(self, token): + self.tree.insertElement(token) + self.parser.tokenizer.state = self.parser.tokenizer.rcdataState + self.processSpaceCharacters = self.processSpaceCharactersDropNewline + self.parser.framesetOK = False + + def startTagIFrame(self, token): + self.parser.framesetOK = False + self.startTagRawtext(token) + + def startTagNoscript(self, token): + if self.parser.scripting: + self.startTagRawtext(token) + else: + self.startTagOther(token) + + def startTagRawtext(self, token): + """iframe, noembed noframes, noscript(if scripting enabled)""" + self.parser.parseRCDataRawtext(token, "RAWTEXT") + + def startTagOpt(self, token): + if self.tree.openElements[-1].name == "option": + self.parser.phase.processEndTag(impliedTagToken("option")) + self.tree.reconstructActiveFormattingElements() + self.parser.tree.insertElement(token) + + def startTagSelect(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + self.parser.framesetOK = False + if self.parser.phase in (self.parser.phases["inTable"], + self.parser.phases["inCaption"], + self.parser.phases["inColumnGroup"], + self.parser.phases["inTableBody"], + self.parser.phases["inRow"], + self.parser.phases["inCell"]): + self.parser.phase = self.parser.phases["inSelectInTable"] + else: + self.parser.phase = self.parser.phases["inSelect"] + + def startTagRpRt(self, token): + if self.tree.elementInScope("ruby"): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "ruby": + self.parser.parseError() + self.tree.insertElement(token) + + def startTagMath(self, token): + self.tree.reconstructActiveFormattingElements() + self.parser.adjustMathMLAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = namespaces["mathml"] + self.tree.insertElement(token) + # Need to get the parse error right for the case where the token + # has a namespace not equal to the xmlns attribute + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagSvg(self, token): + self.tree.reconstructActiveFormattingElements() + self.parser.adjustSVGAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = namespaces["svg"] + self.tree.insertElement(token) + # Need to get the parse error right for the case where the token + # has a namespace not equal to the xmlns attribute + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagMisplaced(self, token): + """ Elements that should be children of other elements that have a + different insertion mode; here they are ignored + "caption", "col", "colgroup", "frame", "frameset", "head", + "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", + "tr", "noscript" + """ + self.parser.parseError("unexpected-start-tag-ignored", {"name": token["name"]}) + + def startTagOther(self, token): + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(token) + + def endTagP(self, token): + if not self.tree.elementInScope("p", variant="button"): + self.startTagCloseP(impliedTagToken("p", "StartTag")) + self.parser.parseError("unexpected-end-tag", {"name": "p"}) + self.endTagP(impliedTagToken("p", "EndTag")) + else: + self.tree.generateImpliedEndTags("p") + if self.tree.openElements[-1].name != "p": + self.parser.parseError("unexpected-end-tag", {"name": "p"}) + node = self.tree.openElements.pop() + while node.name != "p": + node = self.tree.openElements.pop() + + def endTagBody(self, token): + if not self.tree.elementInScope("body"): + self.parser.parseError() + return + elif self.tree.openElements[-1].name != "body": + for node in self.tree.openElements[2:]: + if node.name not in frozenset(("dd", "dt", "li", "optgroup", + "option", "p", "rp", "rt", + "tbody", "td", "tfoot", + "th", "thead", "tr", "body", + "html")): + # Not sure this is the correct name for the parse error + self.parser.parseError( + "expected-one-end-tag-but-got-another", + {"gotName": "body", "expectedName": node.name}) + break + self.parser.phase = self.parser.phases["afterBody"] + + def endTagHtml(self, token): + # We repeat the test for the body end tag token being ignored here + if self.tree.elementInScope("body"): + self.endTagBody(impliedTagToken("body")) + return token + + def endTagBlock(self, token): + # Put us back in the right whitespace handling mode + if token["name"] == "pre": + self.processSpaceCharacters = self.processSpaceCharactersNonPre + inScope = self.tree.elementInScope(token["name"]) + if inScope: + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + if inScope: + node = self.tree.openElements.pop() + while node.name != token["name"]: + node = self.tree.openElements.pop() + + def endTagForm(self, token): + node = self.tree.formPointer + self.tree.formPointer = None + if node is None or not self.tree.elementInScope(node): + self.parser.parseError("unexpected-end-tag", + {"name": "form"}) + else: + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1] != node: + self.parser.parseError("end-tag-too-early-ignored", + {"name": "form"}) + self.tree.openElements.remove(node) + + def endTagListItem(self, token): + if token["name"] == "li": + variant = "list" + else: + variant = None + if not self.tree.elementInScope(token["name"], variant=variant): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + else: + self.tree.generateImpliedEndTags(exclude=token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError( + "end-tag-too-early", + {"name": token["name"]}) + node = self.tree.openElements.pop() + while node.name != token["name"]: + node = self.tree.openElements.pop() + + def endTagHeading(self, token): + for item in headingElements: + if self.tree.elementInScope(item): + self.tree.generateImpliedEndTags() + break + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + + for item in headingElements: + if self.tree.elementInScope(item): + item = self.tree.openElements.pop() + while item.name not in headingElements: + item = self.tree.openElements.pop() + break + + def endTagFormatting(self, token): + """The much-feared adoption agency algorithm""" + # http://svn.whatwg.org/webapps/complete.html#adoptionAgency revision 7867 + # XXX Better parseError messages appreciated. + + # Step 1 + outerLoopCounter = 0 + + # Step 2 + while outerLoopCounter < 8: + + # Step 3 + outerLoopCounter += 1 + + # Step 4: + + # Let the formatting element be the last element in + # the list of active formatting elements that: + # - is between the end of the list and the last scope + # marker in the list, if any, or the start of the list + # otherwise, and + # - has the same tag name as the token. + formattingElement = self.tree.elementInActiveFormattingElements( + token["name"]) + if (not formattingElement or + (formattingElement in self.tree.openElements and + not self.tree.elementInScope(formattingElement.name))): + # If there is no such node, then abort these steps + # and instead act as described in the "any other + # end tag" entry below. + self.endTagOther(token) + return + + # Otherwise, if there is such a node, but that node is + # not in the stack of open elements, then this is a + # parse error; remove the element from the list, and + # abort these steps. + elif formattingElement not in self.tree.openElements: + self.parser.parseError("adoption-agency-1.2", {"name": token["name"]}) + self.tree.activeFormattingElements.remove(formattingElement) + return + + # Otherwise, if there is such a node, and that node is + # also in the stack of open elements, but the element + # is not in scope, then this is a parse error; ignore + # the token, and abort these steps. + elif not self.tree.elementInScope(formattingElement.name): + self.parser.parseError("adoption-agency-4.4", {"name": token["name"]}) + return + + # Otherwise, there is a formatting element and that + # element is in the stack and is in scope. If the + # element is not the current node, this is a parse + # error. In any case, proceed with the algorithm as + # written in the following steps. + else: + if formattingElement != self.tree.openElements[-1]: + self.parser.parseError("adoption-agency-1.3", {"name": token["name"]}) + + # Step 5: + + # Let the furthest block be the topmost node in the + # stack of open elements that is lower in the stack + # than the formatting element, and is an element in + # the special category. There might not be one. + afeIndex = self.tree.openElements.index(formattingElement) + furthestBlock = None + for element in self.tree.openElements[afeIndex:]: + if element.nameTuple in specialElements: + furthestBlock = element + break + + # Step 6: + + # If there is no furthest block, then the UA must + # first pop all the nodes from the bottom of the stack + # of open elements, from the current node up to and + # including the formatting element, then remove the + # formatting element from the list of active + # formatting elements, and finally abort these steps. + if furthestBlock is None: + element = self.tree.openElements.pop() + while element != formattingElement: + element = self.tree.openElements.pop() + self.tree.activeFormattingElements.remove(element) + return + + # Step 7 + commonAncestor = self.tree.openElements[afeIndex - 1] + + # Step 8: + # The bookmark is supposed to help us identify where to reinsert + # nodes in step 15. We have to ensure that we reinsert nodes after + # the node before the active formatting element. Note the bookmark + # can move in step 9.7 + bookmark = self.tree.activeFormattingElements.index(formattingElement) + + # Step 9 + lastNode = node = furthestBlock + innerLoopCounter = 0 + + index = self.tree.openElements.index(node) + while innerLoopCounter < 3: + innerLoopCounter += 1 + # Node is element before node in open elements + index -= 1 + node = self.tree.openElements[index] + if node not in self.tree.activeFormattingElements: + self.tree.openElements.remove(node) + continue + # Step 9.6 + if node == formattingElement: + break + # Step 9.7 + if lastNode == furthestBlock: + bookmark = self.tree.activeFormattingElements.index(node) + 1 + # Step 9.8 + clone = node.cloneNode() + # Replace node with clone + self.tree.activeFormattingElements[ + self.tree.activeFormattingElements.index(node)] = clone + self.tree.openElements[ + self.tree.openElements.index(node)] = clone + node = clone + # Step 9.9 + # Remove lastNode from its parents, if any + if lastNode.parent: + lastNode.parent.removeChild(lastNode) + node.appendChild(lastNode) + # Step 9.10 + lastNode = node + + # Step 10 + # Foster parent lastNode if commonAncestor is a + # table, tbody, tfoot, thead, or tr we need to foster + # parent the lastNode + if lastNode.parent: + lastNode.parent.removeChild(lastNode) + + if commonAncestor.name in frozenset(("table", "tbody", "tfoot", "thead", "tr")): + parent, insertBefore = self.tree.getTableMisnestedNodePosition() + parent.insertBefore(lastNode, insertBefore) + else: + commonAncestor.appendChild(lastNode) + + # Step 11 + clone = formattingElement.cloneNode() + + # Step 12 + furthestBlock.reparentChildren(clone) + + # Step 13 + furthestBlock.appendChild(clone) + + # Step 14 + self.tree.activeFormattingElements.remove(formattingElement) + self.tree.activeFormattingElements.insert(bookmark, clone) + + # Step 15 + self.tree.openElements.remove(formattingElement) + self.tree.openElements.insert( + self.tree.openElements.index(furthestBlock) + 1, clone) + + def endTagAppletMarqueeObject(self, token): + if self.tree.elementInScope(token["name"]): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("end-tag-too-early", {"name": token["name"]}) + + if self.tree.elementInScope(token["name"]): + element = self.tree.openElements.pop() + while element.name != token["name"]: + element = self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + + def endTagBr(self, token): + self.parser.parseError("unexpected-end-tag-treated-as", + {"originalName": "br", "newName": "br element"}) + self.tree.reconstructActiveFormattingElements() + self.tree.insertElement(impliedTagToken("br", "StartTag")) + self.tree.openElements.pop() + + def endTagOther(self, token): + for node in self.tree.openElements[::-1]: + if node.name == token["name"]: + self.tree.generateImpliedEndTags(exclude=token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + while self.tree.openElements.pop() != node: + pass + break + else: + if node.nameTuple in specialElements: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + break + + class TextPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([]) + self.startTagHandler.default = self.startTagOther + self.endTagHandler = _utils.MethodDispatcher([ + ("script", self.endTagScript)]) + self.endTagHandler.default = self.endTagOther + + def processCharacters(self, token): + self.tree.insertText(token["data"]) + + def processEOF(self): + self.parser.parseError("expected-named-closing-tag-but-got-eof", + {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + self.parser.phase = self.parser.originalPhase + return True + + def startTagOther(self, token): + assert False, "Tried to process start tag %s in RCDATA/RAWTEXT mode" % token['name'] + + def endTagScript(self, token): + node = self.tree.openElements.pop() + assert node.name == "script" + self.parser.phase = self.parser.originalPhase + # The rest of this method is all stuff that only happens if + # document.write works + + def endTagOther(self, token): + self.tree.openElements.pop() + self.parser.phase = self.parser.originalPhase + + class InTablePhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-table + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("caption", self.startTagCaption), + ("colgroup", self.startTagColgroup), + ("col", self.startTagCol), + (("tbody", "tfoot", "thead"), self.startTagRowGroup), + (("td", "th", "tr"), self.startTagImplyTbody), + ("table", self.startTagTable), + (("style", "script"), self.startTagStyleScript), + ("input", self.startTagInput), + ("form", self.startTagForm) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("table", self.endTagTable), + (("body", "caption", "col", "colgroup", "html", "tbody", "td", + "tfoot", "th", "thead", "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods + def clearStackToTableContext(self): + # "clear the stack back to a table context" + while self.tree.openElements[-1].name not in ("table", "html"): + # self.parser.parseError("unexpected-implied-end-tag-in-table", + # {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + # When the current node is <html> it's an innerHTML case + + # processing methods + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-table") + else: + assert self.parser.innerHTML + # Stop parsing + + def processSpaceCharacters(self, token): + originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["inTableText"] + self.parser.phase.originalPhase = originalPhase + self.parser.phase.processSpaceCharacters(token) + + def processCharacters(self, token): + originalPhase = self.parser.phase + self.parser.phase = self.parser.phases["inTableText"] + self.parser.phase.originalPhase = originalPhase + self.parser.phase.processCharacters(token) + + def insertText(self, token): + # If we get here there must be at least one non-whitespace character + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processCharacters(token) + self.tree.insertFromTable = False + + def startTagCaption(self, token): + self.clearStackToTableContext() + self.tree.activeFormattingElements.append(Marker) + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inCaption"] + + def startTagColgroup(self, token): + self.clearStackToTableContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inColumnGroup"] + + def startTagCol(self, token): + self.startTagColgroup(impliedTagToken("colgroup", "StartTag")) + return token + + def startTagRowGroup(self, token): + self.clearStackToTableContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inTableBody"] + + def startTagImplyTbody(self, token): + self.startTagRowGroup(impliedTagToken("tbody", "StartTag")) + return token + + def startTagTable(self, token): + self.parser.parseError("unexpected-start-tag-implies-end-tag", + {"startName": "table", "endName": "table"}) + self.parser.phase.processEndTag(impliedTagToken("table")) + if not self.parser.innerHTML: + return token + + def startTagStyleScript(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagInput(self, token): + if ("type" in token["data"] and + token["data"]["type"].translate(asciiUpper2Lower) == "hidden"): + self.parser.parseError("unexpected-hidden-input-in-table") + self.tree.insertElement(token) + # XXX associate with form + self.tree.openElements.pop() + else: + self.startTagOther(token) + + def startTagForm(self, token): + self.parser.parseError("unexpected-form-in-table") + if self.tree.formPointer is None: + self.tree.insertElement(token) + self.tree.formPointer = self.tree.openElements[-1] + self.tree.openElements.pop() + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-implies-table-voodoo", {"name": token["name"]}) + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processStartTag(token) + self.tree.insertFromTable = False + + def endTagTable(self, token): + if self.tree.elementInScope("table", variant="table"): + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "table": + self.parser.parseError("end-tag-too-early-named", + {"gotName": "table", + "expectedName": self.tree.openElements[-1].name}) + while self.tree.openElements[-1].name != "table": + self.tree.openElements.pop() + self.tree.openElements.pop() + self.parser.resetInsertionMode() + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-implies-table-voodoo", {"name": token["name"]}) + # Do the table magic! + self.tree.insertFromTable = True + self.parser.phases["inBody"].processEndTag(token) + self.tree.insertFromTable = False + + class InTableTextPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.originalPhase = None + self.characterTokens = [] + + def flushCharacters(self): + data = "".join([item["data"] for item in self.characterTokens]) + if any([item not in spaceCharacters for item in data]): + token = {"type": tokenTypes["Characters"], "data": data} + self.parser.phases["inTable"].insertText(token) + elif data: + self.tree.insertText(data) + self.characterTokens = [] + + def processComment(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + def processEOF(self): + self.flushCharacters() + self.parser.phase = self.originalPhase + return True + + def processCharacters(self, token): + if token["data"] == "\u0000": + return + self.characterTokens.append(token) + + def processSpaceCharacters(self, token): + # pretty sure we should never reach here + self.characterTokens.append(token) + # assert False + + def processStartTag(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + def processEndTag(self, token): + self.flushCharacters() + self.parser.phase = self.originalPhase + return token + + class InCaptionPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-caption + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.startTagTableElement) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("caption", self.endTagCaption), + ("table", self.endTagTable), + (("body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + def ignoreEndTagCaption(self): + return not self.tree.elementInScope("caption", variant="table") + + def processEOF(self): + self.parser.phases["inBody"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inBody"].processCharacters(token) + + def startTagTableElement(self, token): + self.parser.parseError() + # XXX Have to duplicate logic here to find out if the tag is ignored + ignoreEndTag = self.ignoreEndTagCaption() + self.parser.phase.processEndTag(impliedTagToken("caption")) + if not ignoreEndTag: + return token + + def startTagOther(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def endTagCaption(self, token): + if not self.ignoreEndTagCaption(): + # AT this code is quite similar to endTagTable in "InTable" + self.tree.generateImpliedEndTags() + if self.tree.openElements[-1].name != "caption": + self.parser.parseError("expected-one-end-tag-but-got-another", + {"gotName": "caption", + "expectedName": self.tree.openElements[-1].name}) + while self.tree.openElements[-1].name != "caption": + self.tree.openElements.pop() + self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + self.parser.phase = self.parser.phases["inTable"] + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagTable(self, token): + self.parser.parseError() + ignoreEndTag = self.ignoreEndTagCaption() + self.parser.phase.processEndTag(impliedTagToken("caption")) + if not ignoreEndTag: + return token + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inBody"].processEndTag(token) + + class InColumnGroupPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-column + + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("col", self.startTagCol) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("colgroup", self.endTagColgroup), + ("col", self.endTagCol) + ]) + self.endTagHandler.default = self.endTagOther + + def ignoreEndTagColgroup(self): + return self.tree.openElements[-1].name == "html" + + def processEOF(self): + if self.tree.openElements[-1].name == "html": + assert self.parser.innerHTML + return + else: + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return True + + def processCharacters(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + def startTagCol(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def startTagOther(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + def endTagColgroup(self, token): + if self.ignoreEndTagColgroup(): + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + else: + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTable"] + + def endTagCol(self, token): + self.parser.parseError("no-end-tag", {"name": "col"}) + + def endTagOther(self, token): + ignoreEndTag = self.ignoreEndTagColgroup() + self.endTagColgroup(impliedTagToken("colgroup")) + if not ignoreEndTag: + return token + + class InTableBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-table0 + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("tr", self.startTagTr), + (("td", "th"), self.startTagTableCell), + (("caption", "col", "colgroup", "tbody", "tfoot", "thead"), + self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), + ("table", self.endTagTable), + (("body", "caption", "col", "colgroup", "html", "td", "th", + "tr"), self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods + def clearStackToTableBodyContext(self): + while self.tree.openElements[-1].name not in ("tbody", "tfoot", + "thead", "html"): + # self.parser.parseError("unexpected-implied-end-tag-in-table", + # {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + if self.tree.openElements[-1].name == "html": + assert self.parser.innerHTML + + # the rest + def processEOF(self): + self.parser.phases["inTable"].processEOF() + + def processSpaceCharacters(self, token): + return self.parser.phases["inTable"].processSpaceCharacters(token) + + def processCharacters(self, token): + return self.parser.phases["inTable"].processCharacters(token) + + def startTagTr(self, token): + self.clearStackToTableBodyContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inRow"] + + def startTagTableCell(self, token): + self.parser.parseError("unexpected-cell-in-table-body", + {"name": token["name"]}) + self.startTagTr(impliedTagToken("tr", "StartTag")) + return token + + def startTagTableOther(self, token): + # XXX AT Any ideas on how to share this with endTagTable? + if (self.tree.elementInScope("tbody", variant="table") or + self.tree.elementInScope("thead", variant="table") or + self.tree.elementInScope("tfoot", variant="table")): + self.clearStackToTableBodyContext() + self.endTagTableRowGroup( + impliedTagToken(self.tree.openElements[-1].name)) + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def startTagOther(self, token): + return self.parser.phases["inTable"].processStartTag(token) + + def endTagTableRowGroup(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.clearStackToTableBodyContext() + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTable"] + else: + self.parser.parseError("unexpected-end-tag-in-table-body", + {"name": token["name"]}) + + def endTagTable(self, token): + if (self.tree.elementInScope("tbody", variant="table") or + self.tree.elementInScope("thead", variant="table") or + self.tree.elementInScope("tfoot", variant="table")): + self.clearStackToTableBodyContext() + self.endTagTableRowGroup( + impliedTagToken(self.tree.openElements[-1].name)) + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag-in-table-body", + {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inTable"].processEndTag(token) + + class InRowPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-row + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("td", "th"), self.startTagTableCell), + (("caption", "col", "colgroup", "tbody", "tfoot", "thead", + "tr"), self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("tr", self.endTagTr), + ("table", self.endTagTable), + (("tbody", "tfoot", "thead"), self.endTagTableRowGroup), + (("body", "caption", "col", "colgroup", "html", "td", "th"), + self.endTagIgnore) + ]) + self.endTagHandler.default = self.endTagOther + + # helper methods (XXX unify this with other table helper methods) + def clearStackToTableRowContext(self): + while self.tree.openElements[-1].name not in ("tr", "html"): + self.parser.parseError("unexpected-implied-end-tag-in-table-row", + {"name": self.tree.openElements[-1].name}) + self.tree.openElements.pop() + + def ignoreEndTagTr(self): + return not self.tree.elementInScope("tr", variant="table") + + # the rest + def processEOF(self): + self.parser.phases["inTable"].processEOF() + + def processSpaceCharacters(self, token): + return self.parser.phases["inTable"].processSpaceCharacters(token) + + def processCharacters(self, token): + return self.parser.phases["inTable"].processCharacters(token) + + def startTagTableCell(self, token): + self.clearStackToTableRowContext() + self.tree.insertElement(token) + self.parser.phase = self.parser.phases["inCell"] + self.tree.activeFormattingElements.append(Marker) + + def startTagTableOther(self, token): + ignoreEndTag = self.ignoreEndTagTr() + self.endTagTr(impliedTagToken("tr")) + # XXX how are we sure it's always ignored in the innerHTML case? + if not ignoreEndTag: + return token + + def startTagOther(self, token): + return self.parser.phases["inTable"].processStartTag(token) + + def endTagTr(self, token): + if not self.ignoreEndTagTr(): + self.clearStackToTableRowContext() + self.tree.openElements.pop() + self.parser.phase = self.parser.phases["inTableBody"] + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagTable(self, token): + ignoreEndTag = self.ignoreEndTagTr() + self.endTagTr(impliedTagToken("tr")) + # Reprocess the current tag if the tr end tag was not ignored + # XXX how are we sure it's always ignored in the innerHTML case? + if not ignoreEndTag: + return token + + def endTagTableRowGroup(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.endTagTr(impliedTagToken("tr")) + return token + else: + self.parser.parseError() + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag-in-table-row", + {"name": token["name"]}) + + def endTagOther(self, token): + return self.parser.phases["inTable"].processEndTag(token) + + class InCellPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-cell + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th", + "thead", "tr"), self.startTagTableOther) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("td", "th"), self.endTagTableCell), + (("body", "caption", "col", "colgroup", "html"), self.endTagIgnore), + (("table", "tbody", "tfoot", "thead", "tr"), self.endTagImply) + ]) + self.endTagHandler.default = self.endTagOther + + # helper + def closeCell(self): + if self.tree.elementInScope("td", variant="table"): + self.endTagTableCell(impliedTagToken("td")) + elif self.tree.elementInScope("th", variant="table"): + self.endTagTableCell(impliedTagToken("th")) + + # the rest + def processEOF(self): + self.parser.phases["inBody"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inBody"].processCharacters(token) + + def startTagTableOther(self, token): + if (self.tree.elementInScope("td", variant="table") or + self.tree.elementInScope("th", variant="table")): + self.closeCell() + return token + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def startTagOther(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def endTagTableCell(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.tree.generateImpliedEndTags(token["name"]) + if self.tree.openElements[-1].name != token["name"]: + self.parser.parseError("unexpected-cell-end-tag", + {"name": token["name"]}) + while True: + node = self.tree.openElements.pop() + if node.name == token["name"]: + break + else: + self.tree.openElements.pop() + self.tree.clearActiveFormattingElements() + self.parser.phase = self.parser.phases["inRow"] + else: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagIgnore(self, token): + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + def endTagImply(self, token): + if self.tree.elementInScope(token["name"], variant="table"): + self.closeCell() + return token + else: + # sometimes innerHTML case + self.parser.parseError() + + def endTagOther(self, token): + return self.parser.phases["inBody"].processEndTag(token) + + class InSelectPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("option", self.startTagOption), + ("optgroup", self.startTagOptgroup), + ("select", self.startTagSelect), + (("input", "keygen", "textarea"), self.startTagInput), + ("script", self.startTagScript) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("option", self.endTagOption), + ("optgroup", self.endTagOptgroup), + ("select", self.endTagSelect) + ]) + self.endTagHandler.default = self.endTagOther + + # http://www.whatwg.org/specs/web-apps/current-work/#in-select + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-select") + else: + assert self.parser.innerHTML + + def processCharacters(self, token): + if token["data"] == "\u0000": + return + self.tree.insertText(token["data"]) + + def startTagOption(self, token): + # We need to imply </option> if <option> is the current node. + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagOptgroup(self, token): + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + if self.tree.openElements[-1].name == "optgroup": + self.tree.openElements.pop() + self.tree.insertElement(token) + + def startTagSelect(self, token): + self.parser.parseError("unexpected-select-in-select") + self.endTagSelect(impliedTagToken("select")) + + def startTagInput(self, token): + self.parser.parseError("unexpected-input-in-select") + if self.tree.elementInScope("select", variant="select"): + self.endTagSelect(impliedTagToken("select")) + return token + else: + assert self.parser.innerHTML + + def startTagScript(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-in-select", + {"name": token["name"]}) + + def endTagOption(self, token): + if self.tree.openElements[-1].name == "option": + self.tree.openElements.pop() + else: + self.parser.parseError("unexpected-end-tag-in-select", + {"name": "option"}) + + def endTagOptgroup(self, token): + # </optgroup> implicitly closes <option> + if (self.tree.openElements[-1].name == "option" and + self.tree.openElements[-2].name == "optgroup"): + self.tree.openElements.pop() + # It also closes </optgroup> + if self.tree.openElements[-1].name == "optgroup": + self.tree.openElements.pop() + # But nothing else + else: + self.parser.parseError("unexpected-end-tag-in-select", + {"name": "optgroup"}) + + def endTagSelect(self, token): + if self.tree.elementInScope("select", variant="select"): + node = self.tree.openElements.pop() + while node.name != "select": + node = self.tree.openElements.pop() + self.parser.resetInsertionMode() + else: + # innerHTML case + assert self.parser.innerHTML + self.parser.parseError() + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-in-select", + {"name": token["name"]}) + + class InSelectInTablePhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), + self.startTagTable) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"), + self.endTagTable) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + self.parser.phases["inSelect"].processEOF() + + def processCharacters(self, token): + return self.parser.phases["inSelect"].processCharacters(token) + + def startTagTable(self, token): + self.parser.parseError("unexpected-table-element-start-tag-in-select-in-table", {"name": token["name"]}) + self.endTagOther(impliedTagToken("select")) + return token + + def startTagOther(self, token): + return self.parser.phases["inSelect"].processStartTag(token) + + def endTagTable(self, token): + self.parser.parseError("unexpected-table-element-end-tag-in-select-in-table", {"name": token["name"]}) + if self.tree.elementInScope(token["name"], variant="table"): + self.endTagOther(impliedTagToken("select")) + return token + + def endTagOther(self, token): + return self.parser.phases["inSelect"].processEndTag(token) + + class InForeignContentPhase(Phase): + breakoutElements = frozenset(["b", "big", "blockquote", "body", "br", + "center", "code", "dd", "div", "dl", "dt", + "em", "embed", "h1", "h2", "h3", + "h4", "h5", "h6", "head", "hr", "i", "img", + "li", "listing", "menu", "meta", "nobr", + "ol", "p", "pre", "ruby", "s", "small", + "span", "strong", "strike", "sub", "sup", + "table", "tt", "u", "ul", "var"]) + + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + def adjustSVGTagNames(self, token): + replacements = {"altglyph": "altGlyph", + "altglyphdef": "altGlyphDef", + "altglyphitem": "altGlyphItem", + "animatecolor": "animateColor", + "animatemotion": "animateMotion", + "animatetransform": "animateTransform", + "clippath": "clipPath", + "feblend": "feBlend", + "fecolormatrix": "feColorMatrix", + "fecomponenttransfer": "feComponentTransfer", + "fecomposite": "feComposite", + "feconvolvematrix": "feConvolveMatrix", + "fediffuselighting": "feDiffuseLighting", + "fedisplacementmap": "feDisplacementMap", + "fedistantlight": "feDistantLight", + "feflood": "feFlood", + "fefunca": "feFuncA", + "fefuncb": "feFuncB", + "fefuncg": "feFuncG", + "fefuncr": "feFuncR", + "fegaussianblur": "feGaussianBlur", + "feimage": "feImage", + "femerge": "feMerge", + "femergenode": "feMergeNode", + "femorphology": "feMorphology", + "feoffset": "feOffset", + "fepointlight": "fePointLight", + "fespecularlighting": "feSpecularLighting", + "fespotlight": "feSpotLight", + "fetile": "feTile", + "feturbulence": "feTurbulence", + "foreignobject": "foreignObject", + "glyphref": "glyphRef", + "lineargradient": "linearGradient", + "radialgradient": "radialGradient", + "textpath": "textPath"} + + if token["name"] in replacements: + token["name"] = replacements[token["name"]] + + def processCharacters(self, token): + if token["data"] == "\u0000": + token["data"] = "\uFFFD" + elif (self.parser.framesetOK and + any(char not in spaceCharacters for char in token["data"])): + self.parser.framesetOK = False + Phase.processCharacters(self, token) + + def processStartTag(self, token): + currentNode = self.tree.openElements[-1] + if (token["name"] in self.breakoutElements or + (token["name"] == "font" and + set(token["data"].keys()) & set(["color", "face", "size"]))): + self.parser.parseError("unexpected-html-element-in-foreign-content", + {"name": token["name"]}) + while (self.tree.openElements[-1].namespace != + self.tree.defaultNamespace and + not self.parser.isHTMLIntegrationPoint(self.tree.openElements[-1]) and + not self.parser.isMathMLTextIntegrationPoint(self.tree.openElements[-1])): + self.tree.openElements.pop() + return token + + else: + if currentNode.namespace == namespaces["mathml"]: + self.parser.adjustMathMLAttributes(token) + elif currentNode.namespace == namespaces["svg"]: + self.adjustSVGTagNames(token) + self.parser.adjustSVGAttributes(token) + self.parser.adjustForeignAttributes(token) + token["namespace"] = currentNode.namespace + self.tree.insertElement(token) + if token["selfClosing"]: + self.tree.openElements.pop() + token["selfClosingAcknowledged"] = True + + def processEndTag(self, token): + nodeIndex = len(self.tree.openElements) - 1 + node = self.tree.openElements[-1] + if node.name.translate(asciiUpper2Lower) != token["name"]: + self.parser.parseError("unexpected-end-tag", {"name": token["name"]}) + + while True: + if node.name.translate(asciiUpper2Lower) == token["name"]: + # XXX this isn't in the spec but it seems necessary + if self.parser.phase == self.parser.phases["inTableText"]: + self.parser.phase.flushCharacters() + self.parser.phase = self.parser.phase.originalPhase + while self.tree.openElements.pop() != node: + assert self.tree.openElements + new_token = None + break + nodeIndex -= 1 + + node = self.tree.openElements[nodeIndex] + if node.namespace != self.tree.defaultNamespace: + continue + else: + new_token = self.parser.phase.processEndTag(token) + break + return new_token + + class AfterBodyPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([("html", self.endTagHtml)]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + # Stop parsing + pass + + def processComment(self, token): + # This is needed because data is to be appended to the <html> element + # here and not to whatever is currently open. + self.tree.insertComment(token, self.tree.openElements[0]) + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-after-body") + self.parser.phase = self.parser.phases["inBody"] + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-after-body", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + def endTagHtml(self, name): + if self.parser.innerHTML: + self.parser.parseError("unexpected-end-tag-after-body-innerhtml") + else: + self.parser.phase = self.parser.phases["afterAfterBody"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-after-body", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + class InFramesetPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#in-frameset + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("frameset", self.startTagFrameset), + ("frame", self.startTagFrame), + ("noframes", self.startTagNoframes) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("frameset", self.endTagFrameset) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + if self.tree.openElements[-1].name != "html": + self.parser.parseError("eof-in-frameset") + else: + assert self.parser.innerHTML + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-in-frameset") + + def startTagFrameset(self, token): + self.tree.insertElement(token) + + def startTagFrame(self, token): + self.tree.insertElement(token) + self.tree.openElements.pop() + + def startTagNoframes(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-in-frameset", + {"name": token["name"]}) + + def endTagFrameset(self, token): + if self.tree.openElements[-1].name == "html": + # innerHTML case + self.parser.parseError("unexpected-frameset-in-frameset-innerhtml") + else: + self.tree.openElements.pop() + if (not self.parser.innerHTML and + self.tree.openElements[-1].name != "frameset"): + # If we're not in innerHTML mode and the current node is not a + # "frameset" element (anymore) then switch. + self.parser.phase = self.parser.phases["afterFrameset"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-in-frameset", + {"name": token["name"]}) + + class AfterFramesetPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#after3 + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("noframes", self.startTagNoframes) + ]) + self.startTagHandler.default = self.startTagOther + + self.endTagHandler = _utils.MethodDispatcher([ + ("html", self.endTagHtml) + ]) + self.endTagHandler.default = self.endTagOther + + def processEOF(self): + # Stop parsing + pass + + def processCharacters(self, token): + self.parser.parseError("unexpected-char-after-frameset") + + def startTagNoframes(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("unexpected-start-tag-after-frameset", + {"name": token["name"]}) + + def endTagHtml(self, token): + self.parser.phase = self.parser.phases["afterAfterFrameset"] + + def endTagOther(self, token): + self.parser.parseError("unexpected-end-tag-after-frameset", + {"name": token["name"]}) + + class AfterAfterBodyPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml) + ]) + self.startTagHandler.default = self.startTagOther + + def processEOF(self): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + return self.parser.phases["inBody"].processSpaceCharacters(token) + + def processCharacters(self, token): + self.parser.parseError("expected-eof-but-got-char") + self.parser.phase = self.parser.phases["inBody"] + return token + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("expected-eof-but-got-start-tag", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + def processEndTag(self, token): + self.parser.parseError("expected-eof-but-got-end-tag", + {"name": token["name"]}) + self.parser.phase = self.parser.phases["inBody"] + return token + + class AfterAfterFramesetPhase(Phase): + def __init__(self, parser, tree): + Phase.__init__(self, parser, tree) + + self.startTagHandler = _utils.MethodDispatcher([ + ("html", self.startTagHtml), + ("noframes", self.startTagNoFrames) + ]) + self.startTagHandler.default = self.startTagOther + + def processEOF(self): + pass + + def processComment(self, token): + self.tree.insertComment(token, self.tree.document) + + def processSpaceCharacters(self, token): + return self.parser.phases["inBody"].processSpaceCharacters(token) + + def processCharacters(self, token): + self.parser.parseError("expected-eof-but-got-char") + + def startTagHtml(self, token): + return self.parser.phases["inBody"].processStartTag(token) + + def startTagNoFrames(self, token): + return self.parser.phases["inHead"].processStartTag(token) + + def startTagOther(self, token): + self.parser.parseError("expected-eof-but-got-start-tag", + {"name": token["name"]}) + + def processEndTag(self, token): + self.parser.parseError("expected-eof-but-got-end-tag", + {"name": token["name"]}) + # pylint:enable=unused-argument + + return { + "initial": InitialPhase, + "beforeHtml": BeforeHtmlPhase, + "beforeHead": BeforeHeadPhase, + "inHead": InHeadPhase, + "inHeadNoscript": InHeadNoscriptPhase, + "afterHead": AfterHeadPhase, + "inBody": InBodyPhase, + "text": TextPhase, + "inTable": InTablePhase, + "inTableText": InTableTextPhase, + "inCaption": InCaptionPhase, + "inColumnGroup": InColumnGroupPhase, + "inTableBody": InTableBodyPhase, + "inRow": InRowPhase, + "inCell": InCellPhase, + "inSelect": InSelectPhase, + "inSelectInTable": InSelectInTablePhase, + "inForeignContent": InForeignContentPhase, + "afterBody": AfterBodyPhase, + "inFrameset": InFramesetPhase, + "afterFrameset": AfterFramesetPhase, + "afterAfterBody": AfterAfterBodyPhase, + "afterAfterFrameset": AfterAfterFramesetPhase, + # XXX after after frameset + } + + +def adjust_attributes(token, replacements): + needs_adjustment = viewkeys(token['data']) & viewkeys(replacements) + if needs_adjustment: + token['data'] = OrderedDict((replacements.get(k, k), v) + for k, v in token['data'].items()) + + +def impliedTagToken(name, type="EndTag", attributes=None, + selfClosing=False): + if attributes is None: + attributes = {} + return {"type": tokenTypes[type], "name": name, "data": attributes, + "selfClosing": selfClosing} + + +class ParseError(Exception): + """Error in parsed document""" + pass diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/serializer.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/serializer.py new file mode 100644 index 0000000..53f4d44 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/serializer.py @@ -0,0 +1,409 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +import re + +from codecs import register_error, xmlcharrefreplace_errors + +from .constants import voidElements, booleanAttributes, spaceCharacters +from .constants import rcdataElements, entities, xmlEntities +from . import treewalkers, _utils +from xml.sax.saxutils import escape + +_quoteAttributeSpecChars = "".join(spaceCharacters) + "\"'=<>`" +_quoteAttributeSpec = re.compile("[" + _quoteAttributeSpecChars + "]") +_quoteAttributeLegacy = re.compile("[" + _quoteAttributeSpecChars + + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n" + "\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15" + "\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + "\x20\x2f\x60\xa0\u1680\u180e\u180f\u2000" + "\u2001\u2002\u2003\u2004\u2005\u2006\u2007" + "\u2008\u2009\u200a\u2028\u2029\u202f\u205f" + "\u3000]") + + +_encode_entity_map = {} +_is_ucs4 = len("\U0010FFFF") == 1 +for k, v in list(entities.items()): + # skip multi-character entities + if ((_is_ucs4 and len(v) > 1) or + (not _is_ucs4 and len(v) > 2)): + continue + if v != "&": + if len(v) == 2: + v = _utils.surrogatePairToCodepoint(v) + else: + v = ord(v) + if v not in _encode_entity_map or k.islower(): + # prefer < over < and similarly for &, >, etc. + _encode_entity_map[v] = k + + +def htmlentityreplace_errors(exc): + if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)): + res = [] + codepoints = [] + skip = False + for i, c in enumerate(exc.object[exc.start:exc.end]): + if skip: + skip = False + continue + index = i + exc.start + if _utils.isSurrogatePair(exc.object[index:min([exc.end, index + 2])]): + codepoint = _utils.surrogatePairToCodepoint(exc.object[index:index + 2]) + skip = True + else: + codepoint = ord(c) + codepoints.append(codepoint) + for cp in codepoints: + e = _encode_entity_map.get(cp) + if e: + res.append("&") + res.append(e) + if not e.endswith(";"): + res.append(";") + else: + res.append("&#x%s;" % (hex(cp)[2:])) + return ("".join(res), exc.end) + else: + return xmlcharrefreplace_errors(exc) + + +register_error("htmlentityreplace", htmlentityreplace_errors) + + +def serialize(input, tree="etree", encoding=None, **serializer_opts): + """Serializes the input token stream using the specified treewalker + + :arg input: the token stream to serialize + + :arg tree: the treewalker to use + + :arg encoding: the encoding to use + + :arg serializer_opts: any options to pass to the + :py:class:`html5lib.serializer.HTMLSerializer` that gets created + + :returns: the tree serialized as a string + + Example: + + >>> from html5lib.html5parser import parse + >>> from html5lib.serializer import serialize + >>> token_stream = parse('<html><body><p>Hi!</p></body></html>') + >>> serialize(token_stream, omit_optional_tags=False) + '<html><head></head><body><p>Hi!</p></body></html>' + + """ + # XXX: Should we cache this? + walker = treewalkers.getTreeWalker(tree) + s = HTMLSerializer(**serializer_opts) + return s.render(walker(input), encoding) + + +class HTMLSerializer(object): + + # attribute quoting options + quote_attr_values = "legacy" # be secure by default + quote_char = '"' + use_best_quote_char = True + + # tag syntax options + omit_optional_tags = True + minimize_boolean_attributes = True + use_trailing_solidus = False + space_before_trailing_solidus = True + + # escaping options + escape_lt_in_attrs = False + escape_rcdata = False + resolve_entities = True + + # miscellaneous options + alphabetical_attributes = False + inject_meta_charset = True + strip_whitespace = False + sanitize = False + + options = ("quote_attr_values", "quote_char", "use_best_quote_char", + "omit_optional_tags", "minimize_boolean_attributes", + "use_trailing_solidus", "space_before_trailing_solidus", + "escape_lt_in_attrs", "escape_rcdata", "resolve_entities", + "alphabetical_attributes", "inject_meta_charset", + "strip_whitespace", "sanitize") + + def __init__(self, **kwargs): + """Initialize HTMLSerializer + + :arg inject_meta_charset: Whether or not to inject the meta charset. + + Defaults to ``True``. + + :arg quote_attr_values: Whether to quote attribute values that don't + require quoting per legacy browser behavior (``"legacy"``), when + required by the standard (``"spec"``), or always (``"always"``). + + Defaults to ``"legacy"``. + + :arg quote_char: Use given quote character for attribute quoting. + + Defaults to ``"`` which will use double quotes unless attribute + value contains a double quote, in which case single quotes are + used. + + :arg escape_lt_in_attrs: Whether or not to escape ``<`` in attribute + values. + + Defaults to ``False``. + + :arg escape_rcdata: Whether to escape characters that need to be + escaped within normal elements within rcdata elements such as + style. + + Defaults to ``False``. + + :arg resolve_entities: Whether to resolve named character entities that + appear in the source tree. The XML predefined entities < > + & " ' are unaffected by this setting. + + Defaults to ``True``. + + :arg strip_whitespace: Whether to remove semantically meaningless + whitespace. (This compresses all whitespace to a single space + except within ``pre``.) + + Defaults to ``False``. + + :arg minimize_boolean_attributes: Shortens boolean attributes to give + just the attribute value, for example:: + + <input disabled="disabled"> + + becomes:: + + <input disabled> + + Defaults to ``True``. + + :arg use_trailing_solidus: Includes a close-tag slash at the end of the + start tag of void elements (empty elements whose end tag is + forbidden). E.g. ``<hr/>``. + + Defaults to ``False``. + + :arg space_before_trailing_solidus: Places a space immediately before + the closing slash in a tag using a trailing solidus. E.g. + ``<hr />``. Requires ``use_trailing_solidus=True``. + + Defaults to ``True``. + + :arg sanitize: Strip all unsafe or unknown constructs from output. + See :py:class:`html5lib.filters.sanitizer.Filter`. + + Defaults to ``False``. + + :arg omit_optional_tags: Omit start/end tags that are optional. + + Defaults to ``True``. + + :arg alphabetical_attributes: Reorder attributes to be in alphabetical order. + + Defaults to ``False``. + + """ + unexpected_args = frozenset(kwargs) - frozenset(self.options) + if len(unexpected_args) > 0: + raise TypeError("__init__() got an unexpected keyword argument '%s'" % next(iter(unexpected_args))) + if 'quote_char' in kwargs: + self.use_best_quote_char = False + for attr in self.options: + setattr(self, attr, kwargs.get(attr, getattr(self, attr))) + self.errors = [] + self.strict = False + + def encode(self, string): + assert(isinstance(string, text_type)) + if self.encoding: + return string.encode(self.encoding, "htmlentityreplace") + else: + return string + + def encodeStrict(self, string): + assert(isinstance(string, text_type)) + if self.encoding: + return string.encode(self.encoding, "strict") + else: + return string + + def serialize(self, treewalker, encoding=None): + # pylint:disable=too-many-nested-blocks + self.encoding = encoding + in_cdata = False + self.errors = [] + + if encoding and self.inject_meta_charset: + from .filters.inject_meta_charset import Filter + treewalker = Filter(treewalker, encoding) + # Alphabetical attributes is here under the assumption that none of + # the later filters add or change order of attributes; it needs to be + # before the sanitizer so escaped elements come out correctly + if self.alphabetical_attributes: + from .filters.alphabeticalattributes import Filter + treewalker = Filter(treewalker) + # WhitespaceFilter should be used before OptionalTagFilter + # for maximum efficiently of this latter filter + if self.strip_whitespace: + from .filters.whitespace import Filter + treewalker = Filter(treewalker) + if self.sanitize: + from .filters.sanitizer import Filter + treewalker = Filter(treewalker) + if self.omit_optional_tags: + from .filters.optionaltags import Filter + treewalker = Filter(treewalker) + + for token in treewalker: + type = token["type"] + if type == "Doctype": + doctype = "<!DOCTYPE %s" % token["name"] + + if token["publicId"]: + doctype += ' PUBLIC "%s"' % token["publicId"] + elif token["systemId"]: + doctype += " SYSTEM" + if token["systemId"]: + if token["systemId"].find('"') >= 0: + if token["systemId"].find("'") >= 0: + self.serializeError("System identifer contains both single and double quote characters") + quote_char = "'" + else: + quote_char = '"' + doctype += " %s%s%s" % (quote_char, token["systemId"], quote_char) + + doctype += ">" + yield self.encodeStrict(doctype) + + elif type in ("Characters", "SpaceCharacters"): + if type == "SpaceCharacters" or in_cdata: + if in_cdata and token["data"].find("</") >= 0: + self.serializeError("Unexpected </ in CDATA") + yield self.encode(token["data"]) + else: + yield self.encode(escape(token["data"])) + + elif type in ("StartTag", "EmptyTag"): + name = token["name"] + yield self.encodeStrict("<%s" % name) + if name in rcdataElements and not self.escape_rcdata: + in_cdata = True + elif in_cdata: + self.serializeError("Unexpected child element of a CDATA element") + for (_, attr_name), attr_value in token["data"].items(): + # TODO: Add namespace support here + k = attr_name + v = attr_value + yield self.encodeStrict(' ') + + yield self.encodeStrict(k) + if not self.minimize_boolean_attributes or \ + (k not in booleanAttributes.get(name, tuple()) and + k not in booleanAttributes.get("", tuple())): + yield self.encodeStrict("=") + if self.quote_attr_values == "always" or len(v) == 0: + quote_attr = True + elif self.quote_attr_values == "spec": + quote_attr = _quoteAttributeSpec.search(v) is not None + elif self.quote_attr_values == "legacy": + quote_attr = _quoteAttributeLegacy.search(v) is not None + else: + raise ValueError("quote_attr_values must be one of: " + "'always', 'spec', or 'legacy'") + v = v.replace("&", "&") + if self.escape_lt_in_attrs: + v = v.replace("<", "<") + if quote_attr: + quote_char = self.quote_char + if self.use_best_quote_char: + if "'" in v and '"' not in v: + quote_char = '"' + elif '"' in v and "'" not in v: + quote_char = "'" + if quote_char == "'": + v = v.replace("'", "'") + else: + v = v.replace('"', """) + yield self.encodeStrict(quote_char) + yield self.encode(v) + yield self.encodeStrict(quote_char) + else: + yield self.encode(v) + if name in voidElements and self.use_trailing_solidus: + if self.space_before_trailing_solidus: + yield self.encodeStrict(" /") + else: + yield self.encodeStrict("/") + yield self.encode(">") + + elif type == "EndTag": + name = token["name"] + if name in rcdataElements: + in_cdata = False + elif in_cdata: + self.serializeError("Unexpected child element of a CDATA element") + yield self.encodeStrict("</%s>" % name) + + elif type == "Comment": + data = token["data"] + if data.find("--") >= 0: + self.serializeError("Comment contains --") + yield self.encodeStrict("<!--%s-->" % token["data"]) + + elif type == "Entity": + name = token["name"] + key = name + ";" + if key not in entities: + self.serializeError("Entity %s not recognized" % name) + if self.resolve_entities and key not in xmlEntities: + data = entities[key] + else: + data = "&%s;" % name + yield self.encodeStrict(data) + + else: + self.serializeError(token["data"]) + + def render(self, treewalker, encoding=None): + """Serializes the stream from the treewalker into a string + + :arg treewalker: the treewalker to serialize + + :arg encoding: the string encoding to use + + :returns: the serialized tree + + Example: + + >>> from html5lib import parse, getTreeWalker + >>> from html5lib.serializer import HTMLSerializer + >>> token_stream = parse('<html><body>Hi!</body></html>') + >>> walker = getTreeWalker('etree') + >>> serializer = HTMLSerializer(omit_optional_tags=False) + >>> serializer.render(walker(token_stream)) + '<html><head></head><body>Hi!</body></html>' + + """ + if encoding: + return b"".join(list(self.serialize(treewalker, encoding))) + else: + return "".join(list(self.serialize(treewalker))) + + def serializeError(self, data="XXX ERROR MESSAGE NEEDED"): + # XXX The idea is to make data mandatory. + self.errors.append(data) + if self.strict: + raise SerializeError + + +class SerializeError(Exception): + """Error in serialized tree""" + pass diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py new file mode 100644 index 0000000..7ef5959 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py @@ -0,0 +1,30 @@ +"""Tree adapters let you convert from one tree structure to another + +Example: + +.. code-block:: python + + from pip._vendor import html5lib + from pip._vendor.html5lib.treeadapters import genshi + + doc = '<html><body>Hi!</body></html>' + treebuilder = html5lib.getTreeBuilder('etree') + parser = html5lib.HTMLParser(tree=treebuilder) + tree = parser.parse(doc) + TreeWalker = html5lib.getTreeWalker('etree') + + genshi_tree = genshi.to_genshi(TreeWalker(tree)) + +""" +from __future__ import absolute_import, division, unicode_literals + +from . import sax + +__all__ = ["sax"] + +try: + from . import genshi # noqa +except ImportError: + pass +else: + __all__.append("genshi") diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py new file mode 100644 index 0000000..61d5fb6 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py @@ -0,0 +1,54 @@ +from __future__ import absolute_import, division, unicode_literals + +from genshi.core import QName, Attrs +from genshi.core import START, END, TEXT, COMMENT, DOCTYPE + + +def to_genshi(walker): + """Convert a tree to a genshi tree + + :arg walker: the treewalker to use to walk the tree to convert it + + :returns: generator of genshi nodes + + """ + text = [] + for token in walker: + type = token["type"] + if type in ("Characters", "SpaceCharacters"): + text.append(token["data"]) + elif text: + yield TEXT, "".join(text), (None, -1, -1) + text = [] + + if type in ("StartTag", "EmptyTag"): + if token["namespace"]: + name = "{%s}%s" % (token["namespace"], token["name"]) + else: + name = token["name"] + attrs = Attrs([(QName("{%s}%s" % attr if attr[0] is not None else attr[1]), value) + for attr, value in token["data"].items()]) + yield (START, (QName(name), attrs), (None, -1, -1)) + if type == "EmptyTag": + type = "EndTag" + + if type == "EndTag": + if token["namespace"]: + name = "{%s}%s" % (token["namespace"], token["name"]) + else: + name = token["name"] + + yield END, QName(name), (None, -1, -1) + + elif type == "Comment": + yield COMMENT, token["data"], (None, -1, -1) + + elif type == "Doctype": + yield DOCTYPE, (token["name"], token["publicId"], + token["systemId"]), (None, -1, -1) + + else: + pass # FIXME: What to do? + + if text: + yield TEXT, "".join(text), (None, -1, -1) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py new file mode 100644 index 0000000..f4ccea5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py @@ -0,0 +1,50 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.sax.xmlreader import AttributesNSImpl + +from ..constants import adjustForeignAttributes, unadjustForeignAttributes + +prefix_mapping = {} +for prefix, localName, namespace in adjustForeignAttributes.values(): + if prefix is not None: + prefix_mapping[prefix] = namespace + + +def to_sax(walker, handler): + """Call SAX-like content handler based on treewalker walker + + :arg walker: the treewalker to use to walk the tree to convert it + + :arg handler: SAX handler to use + + """ + handler.startDocument() + for prefix, namespace in prefix_mapping.items(): + handler.startPrefixMapping(prefix, namespace) + + for token in walker: + type = token["type"] + if type == "Doctype": + continue + elif type in ("StartTag", "EmptyTag"): + attrs = AttributesNSImpl(token["data"], + unadjustForeignAttributes) + handler.startElementNS((token["namespace"], token["name"]), + token["name"], + attrs) + if type == "EmptyTag": + handler.endElementNS((token["namespace"], token["name"]), + token["name"]) + elif type == "EndTag": + handler.endElementNS((token["namespace"], token["name"]), + token["name"]) + elif type in ("Characters", "SpaceCharacters"): + handler.characters(token["data"]) + elif type == "Comment": + pass + else: + assert False, "Unknown token type" + + for prefix, namespace in prefix_mapping.items(): + handler.endPrefixMapping(prefix) + handler.endDocument() diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py new file mode 100644 index 0000000..d44447e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py @@ -0,0 +1,88 @@ +"""A collection of modules for building different kinds of trees from HTML +documents. + +To create a treebuilder for a new type of tree, you need to do +implement several things: + +1. A set of classes for various types of elements: Document, Doctype, Comment, + Element. These must implement the interface of ``base.treebuilders.Node`` + (although comment nodes have a different signature for their constructor, + see ``treebuilders.etree.Comment``) Textual content may also be implemented + as another node type, or not, as your tree implementation requires. + +2. A treebuilder object (called ``TreeBuilder`` by convention) that inherits + from ``treebuilders.base.TreeBuilder``. This has 4 required attributes: + + * ``documentClass`` - the class to use for the bottommost node of a document + * ``elementClass`` - the class to use for HTML Elements + * ``commentClass`` - the class to use for comments + * ``doctypeClass`` - the class to use for doctypes + + It also has one required method: + + * ``getDocument`` - Returns the root node of the complete document tree + +3. If you wish to run the unit tests, you must also create a ``testSerializer`` + method on your treebuilder which accepts a node and returns a string + containing Node and its children serialized according to the format used in + the unittests + +""" + +from __future__ import absolute_import, division, unicode_literals + +from .._utils import default_etree + +treeBuilderCache = {} + + +def getTreeBuilder(treeType, implementation=None, **kwargs): + """Get a TreeBuilder class for various types of trees with built-in support + + :arg treeType: the name of the tree type required (case-insensitive). Supported + values are: + + * "dom" - A generic builder for DOM implementations, defaulting to a + xml.dom.minidom based implementation. + * "etree" - A generic builder for tree implementations exposing an + ElementTree-like interface, defaulting to xml.etree.cElementTree if + available and xml.etree.ElementTree if not. + * "lxml" - A etree-based builder for lxml.etree, handling limitations + of lxml's implementation. + + :arg implementation: (Currently applies to the "etree" and "dom" tree + types). A module implementing the tree type e.g. xml.etree.ElementTree + or xml.etree.cElementTree. + + :arg kwargs: Any additional options to pass to the TreeBuilder when + creating it. + + Example: + + >>> from html5lib.treebuilders import getTreeBuilder + >>> builder = getTreeBuilder('etree') + + """ + + treeType = treeType.lower() + if treeType not in treeBuilderCache: + if treeType == "dom": + from . import dom + # Come up with a sane default (pref. from the stdlib) + if implementation is None: + from xml.dom import minidom + implementation = minidom + # NEVER cache here, caching is done in the dom submodule + return dom.getDomModule(implementation, **kwargs).TreeBuilder + elif treeType == "lxml": + from . import etree_lxml + treeBuilderCache[treeType] = etree_lxml.TreeBuilder + elif treeType == "etree": + from . import etree + if implementation is None: + implementation = default_etree + # NEVER cache here, caching is done in the etree submodule + return etree.getETreeModule(implementation, **kwargs).TreeBuilder + else: + raise ValueError("""Unrecognised treebuilder "%s" """ % treeType) + return treeBuilderCache.get(treeType) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/base.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/base.py new file mode 100644 index 0000000..73973db --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/base.py @@ -0,0 +1,417 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from ..constants import scopingElements, tableInsertModeElements, namespaces + +# The scope markers are inserted when entering object elements, +# marquees, table cells, and table captions, and are used to prevent formatting +# from "leaking" into tables, object elements, and marquees. +Marker = None + +listElementsMap = { + None: (frozenset(scopingElements), False), + "button": (frozenset(scopingElements | set([(namespaces["html"], "button")])), False), + "list": (frozenset(scopingElements | set([(namespaces["html"], "ol"), + (namespaces["html"], "ul")])), False), + "table": (frozenset([(namespaces["html"], "html"), + (namespaces["html"], "table")]), False), + "select": (frozenset([(namespaces["html"], "optgroup"), + (namespaces["html"], "option")]), True) +} + + +class Node(object): + """Represents an item in the tree""" + def __init__(self, name): + """Creates a Node + + :arg name: The tag name associated with the node + + """ + # The tag name assocaited with the node + self.name = name + # The parent of the current node (or None for the document node) + self.parent = None + # The value of the current node (applies to text nodes and comments) + self.value = None + # A dict holding name -> value pairs for attributes of the node + self.attributes = {} + # A list of child nodes of the current node. This must include all + # elements but not necessarily other node types. + self.childNodes = [] + # A list of miscellaneous flags that can be set on the node. + self._flags = [] + + def __str__(self): + attributesStr = " ".join(["%s=\"%s\"" % (name, value) + for name, value in + self.attributes.items()]) + if attributesStr: + return "<%s %s>" % (self.name, attributesStr) + else: + return "<%s>" % (self.name) + + def __repr__(self): + return "<%s>" % (self.name) + + def appendChild(self, node): + """Insert node as a child of the current node + + :arg node: the node to insert + + """ + raise NotImplementedError + + def insertText(self, data, insertBefore=None): + """Insert data as text in the current node, positioned before the + start of node insertBefore or to the end of the node's text. + + :arg data: the data to insert + + :arg insertBefore: True if you want to insert the text before the node + and False if you want to insert it after the node + + """ + raise NotImplementedError + + def insertBefore(self, node, refNode): + """Insert node as a child of the current node, before refNode in the + list of child nodes. Raises ValueError if refNode is not a child of + the current node + + :arg node: the node to insert + + :arg refNode: the child node to insert the node before + + """ + raise NotImplementedError + + def removeChild(self, node): + """Remove node from the children of the current node + + :arg node: the child node to remove + + """ + raise NotImplementedError + + def reparentChildren(self, newParent): + """Move all the children of the current node to newParent. + This is needed so that trees that don't store text as nodes move the + text in the correct way + + :arg newParent: the node to move all this node's children to + + """ + # XXX - should this method be made more general? + for child in self.childNodes: + newParent.appendChild(child) + self.childNodes = [] + + def cloneNode(self): + """Return a shallow copy of the current node i.e. a node with the same + name and attributes but with no parent or child nodes + """ + raise NotImplementedError + + def hasContent(self): + """Return true if the node has children or text, false otherwise + """ + raise NotImplementedError + + +class ActiveFormattingElements(list): + def append(self, node): + equalCount = 0 + if node != Marker: + for element in self[::-1]: + if element == Marker: + break + if self.nodesEqual(element, node): + equalCount += 1 + if equalCount == 3: + self.remove(element) + break + list.append(self, node) + + def nodesEqual(self, node1, node2): + if not node1.nameTuple == node2.nameTuple: + return False + + if not node1.attributes == node2.attributes: + return False + + return True + + +class TreeBuilder(object): + """Base treebuilder implementation + + * documentClass - the class to use for the bottommost node of a document + * elementClass - the class to use for HTML Elements + * commentClass - the class to use for comments + * doctypeClass - the class to use for doctypes + + """ + # pylint:disable=not-callable + + # Document class + documentClass = None + + # The class to use for creating a node + elementClass = None + + # The class to use for creating comments + commentClass = None + + # The class to use for creating doctypes + doctypeClass = None + + # Fragment class + fragmentClass = None + + def __init__(self, namespaceHTMLElements): + """Create a TreeBuilder + + :arg namespaceHTMLElements: whether or not to namespace HTML elements + + """ + if namespaceHTMLElements: + self.defaultNamespace = "http://www.w3.org/1999/xhtml" + else: + self.defaultNamespace = None + self.reset() + + def reset(self): + self.openElements = [] + self.activeFormattingElements = ActiveFormattingElements() + + # XXX - rename these to headElement, formElement + self.headPointer = None + self.formPointer = None + + self.insertFromTable = False + + self.document = self.documentClass() + + def elementInScope(self, target, variant=None): + + # If we pass a node in we match that. if we pass a string + # match any node with that name + exactNode = hasattr(target, "nameTuple") + if not exactNode: + if isinstance(target, text_type): + target = (namespaces["html"], target) + assert isinstance(target, tuple) + + listElements, invert = listElementsMap[variant] + + for node in reversed(self.openElements): + if exactNode and node == target: + return True + elif not exactNode and node.nameTuple == target: + return True + elif (invert ^ (node.nameTuple in listElements)): + return False + + assert False # We should never reach this point + + def reconstructActiveFormattingElements(self): + # Within this algorithm the order of steps described in the + # specification is not quite the same as the order of steps in the + # code. It should still do the same though. + + # Step 1: stop the algorithm when there's nothing to do. + if not self.activeFormattingElements: + return + + # Step 2 and step 3: we start with the last element. So i is -1. + i = len(self.activeFormattingElements) - 1 + entry = self.activeFormattingElements[i] + if entry == Marker or entry in self.openElements: + return + + # Step 6 + while entry != Marker and entry not in self.openElements: + if i == 0: + # This will be reset to 0 below + i = -1 + break + i -= 1 + # Step 5: let entry be one earlier in the list. + entry = self.activeFormattingElements[i] + + while True: + # Step 7 + i += 1 + + # Step 8 + entry = self.activeFormattingElements[i] + clone = entry.cloneNode() # Mainly to get a new copy of the attributes + + # Step 9 + element = self.insertElement({"type": "StartTag", + "name": clone.name, + "namespace": clone.namespace, + "data": clone.attributes}) + + # Step 10 + self.activeFormattingElements[i] = element + + # Step 11 + if element == self.activeFormattingElements[-1]: + break + + def clearActiveFormattingElements(self): + entry = self.activeFormattingElements.pop() + while self.activeFormattingElements and entry != Marker: + entry = self.activeFormattingElements.pop() + + def elementInActiveFormattingElements(self, name): + """Check if an element exists between the end of the active + formatting elements and the last marker. If it does, return it, else + return false""" + + for item in self.activeFormattingElements[::-1]: + # Check for Marker first because if it's a Marker it doesn't have a + # name attribute. + if item == Marker: + break + elif item.name == name: + return item + return False + + def insertRoot(self, token): + element = self.createElement(token) + self.openElements.append(element) + self.document.appendChild(element) + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + doctype = self.doctypeClass(name, publicId, systemId) + self.document.appendChild(doctype) + + def insertComment(self, token, parent=None): + if parent is None: + parent = self.openElements[-1] + parent.appendChild(self.commentClass(token["data"])) + + def createElement(self, token): + """Create an element but don't insert it anywhere""" + name = token["name"] + namespace = token.get("namespace", self.defaultNamespace) + element = self.elementClass(name, namespace) + element.attributes = token["data"] + return element + + def _getInsertFromTable(self): + return self._insertFromTable + + def _setInsertFromTable(self, value): + """Switch the function used to insert an element from the + normal one to the misnested table one and back again""" + self._insertFromTable = value + if value: + self.insertElement = self.insertElementTable + else: + self.insertElement = self.insertElementNormal + + insertFromTable = property(_getInsertFromTable, _setInsertFromTable) + + def insertElementNormal(self, token): + name = token["name"] + assert isinstance(name, text_type), "Element %s not unicode" % name + namespace = token.get("namespace", self.defaultNamespace) + element = self.elementClass(name, namespace) + element.attributes = token["data"] + self.openElements[-1].appendChild(element) + self.openElements.append(element) + return element + + def insertElementTable(self, token): + """Create an element and insert it into the tree""" + element = self.createElement(token) + if self.openElements[-1].name not in tableInsertModeElements: + return self.insertElementNormal(token) + else: + # We should be in the InTable mode. This means we want to do + # special magic element rearranging + parent, insertBefore = self.getTableMisnestedNodePosition() + if insertBefore is None: + parent.appendChild(element) + else: + parent.insertBefore(element, insertBefore) + self.openElements.append(element) + return element + + def insertText(self, data, parent=None): + """Insert text data.""" + if parent is None: + parent = self.openElements[-1] + + if (not self.insertFromTable or (self.insertFromTable and + self.openElements[-1].name + not in tableInsertModeElements)): + parent.insertText(data) + else: + # We should be in the InTable mode. This means we want to do + # special magic element rearranging + parent, insertBefore = self.getTableMisnestedNodePosition() + parent.insertText(data, insertBefore) + + def getTableMisnestedNodePosition(self): + """Get the foster parent element, and sibling to insert before + (or None) when inserting a misnested table node""" + # The foster parent element is the one which comes before the most + # recently opened table element + # XXX - this is really inelegant + lastTable = None + fosterParent = None + insertBefore = None + for elm in self.openElements[::-1]: + if elm.name == "table": + lastTable = elm + break + if lastTable: + # XXX - we should really check that this parent is actually a + # node here + if lastTable.parent: + fosterParent = lastTable.parent + insertBefore = lastTable + else: + fosterParent = self.openElements[ + self.openElements.index(lastTable) - 1] + else: + fosterParent = self.openElements[0] + return fosterParent, insertBefore + + def generateImpliedEndTags(self, exclude=None): + name = self.openElements[-1].name + # XXX td, th and tr are not actually needed + if (name in frozenset(("dd", "dt", "li", "option", "optgroup", "p", "rp", "rt")) and + name != exclude): + self.openElements.pop() + # XXX This is not entirely what the specification says. We should + # investigate it more closely. + self.generateImpliedEndTags(exclude) + + def getDocument(self): + """Return the final tree""" + return self.document + + def getFragment(self): + """Return the final fragment""" + # assert self.innerHTML + fragment = self.fragmentClass() + self.openElements[0].reparentChildren(fragment) + return fragment + + def testSerializer(self, node): + """Serialize the subtree of node in the format required by unit tests + + :arg node: the node from which to start serializing + + """ + raise NotImplementedError diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py new file mode 100644 index 0000000..dcfac22 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py @@ -0,0 +1,236 @@ +from __future__ import absolute_import, division, unicode_literals + + +from collections import MutableMapping +from xml.dom import minidom, Node +import weakref + +from . import base +from .. import constants +from ..constants import namespaces +from .._utils import moduleFactoryFactory + + +def getDomBuilder(DomImplementation): + Dom = DomImplementation + + class AttrList(MutableMapping): + def __init__(self, element): + self.element = element + + def __iter__(self): + return iter(self.element.attributes.keys()) + + def __setitem__(self, name, value): + if isinstance(name, tuple): + raise NotImplementedError + else: + attr = self.element.ownerDocument.createAttribute(name) + attr.value = value + self.element.attributes[name] = attr + + def __len__(self): + return len(self.element.attributes) + + def items(self): + return list(self.element.attributes.items()) + + def values(self): + return list(self.element.attributes.values()) + + def __getitem__(self, name): + if isinstance(name, tuple): + raise NotImplementedError + else: + return self.element.attributes[name].value + + def __delitem__(self, name): + if isinstance(name, tuple): + raise NotImplementedError + else: + del self.element.attributes[name] + + class NodeBuilder(base.Node): + def __init__(self, element): + base.Node.__init__(self, element.nodeName) + self.element = element + + namespace = property(lambda self: hasattr(self.element, "namespaceURI") and + self.element.namespaceURI or None) + + def appendChild(self, node): + node.parent = self + self.element.appendChild(node.element) + + def insertText(self, data, insertBefore=None): + text = self.element.ownerDocument.createTextNode(data) + if insertBefore: + self.element.insertBefore(text, insertBefore.element) + else: + self.element.appendChild(text) + + def insertBefore(self, node, refNode): + self.element.insertBefore(node.element, refNode.element) + node.parent = self + + def removeChild(self, node): + if node.element.parentNode == self.element: + self.element.removeChild(node.element) + node.parent = None + + def reparentChildren(self, newParent): + while self.element.hasChildNodes(): + child = self.element.firstChild + self.element.removeChild(child) + newParent.element.appendChild(child) + self.childNodes = [] + + def getAttributes(self): + return AttrList(self.element) + + def setAttributes(self, attributes): + if attributes: + for name, value in list(attributes.items()): + if isinstance(name, tuple): + if name[0] is not None: + qualifiedName = (name[0] + ":" + name[1]) + else: + qualifiedName = name[1] + self.element.setAttributeNS(name[2], qualifiedName, + value) + else: + self.element.setAttribute( + name, value) + attributes = property(getAttributes, setAttributes) + + def cloneNode(self): + return NodeBuilder(self.element.cloneNode(False)) + + def hasContent(self): + return self.element.hasChildNodes() + + def getNameTuple(self): + if self.namespace is None: + return namespaces["html"], self.name + else: + return self.namespace, self.name + + nameTuple = property(getNameTuple) + + class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable + def documentClass(self): + self.dom = Dom.getDOMImplementation().createDocument(None, None, None) + return weakref.proxy(self) + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + domimpl = Dom.getDOMImplementation() + doctype = domimpl.createDocumentType(name, publicId, systemId) + self.document.appendChild(NodeBuilder(doctype)) + if Dom == minidom: + doctype.ownerDocument = self.dom + + def elementClass(self, name, namespace=None): + if namespace is None and self.defaultNamespace is None: + node = self.dom.createElement(name) + else: + node = self.dom.createElementNS(namespace, name) + + return NodeBuilder(node) + + def commentClass(self, data): + return NodeBuilder(self.dom.createComment(data)) + + def fragmentClass(self): + return NodeBuilder(self.dom.createDocumentFragment()) + + def appendChild(self, node): + self.dom.appendChild(node.element) + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + return self.dom + + def getFragment(self): + return base.TreeBuilder.getFragment(self).element + + def insertText(self, data, parent=None): + data = data + if parent != self: + base.TreeBuilder.insertText(self, data, parent) + else: + # HACK: allow text nodes as children of the document node + if hasattr(self.dom, '_child_node_types'): + # pylint:disable=protected-access + if Node.TEXT_NODE not in self.dom._child_node_types: + self.dom._child_node_types = list(self.dom._child_node_types) + self.dom._child_node_types.append(Node.TEXT_NODE) + self.dom.appendChild(self.dom.createTextNode(data)) + + implementation = DomImplementation + name = None + + def testSerializer(element): + element.normalize() + rv = [] + + def serializeElement(element, indent=0): + if element.nodeType == Node.DOCUMENT_TYPE_NODE: + if element.name: + if element.publicId or element.systemId: + publicId = element.publicId or "" + systemId = element.systemId or "" + rv.append("""|%s<!DOCTYPE %s "%s" "%s">""" % + (' ' * indent, element.name, publicId, systemId)) + else: + rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name)) + else: + rv.append("|%s<!DOCTYPE >" % (' ' * indent,)) + elif element.nodeType == Node.DOCUMENT_NODE: + rv.append("#document") + elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE: + rv.append("#document-fragment") + elif element.nodeType == Node.COMMENT_NODE: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.nodeValue)) + elif element.nodeType == Node.TEXT_NODE: + rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue)) + else: + if (hasattr(element, "namespaceURI") and + element.namespaceURI is not None): + name = "%s %s" % (constants.prefixes[element.namespaceURI], + element.nodeName) + else: + name = element.nodeName + rv.append("|%s<%s>" % (' ' * indent, name)) + if element.hasAttributes(): + attributes = [] + for i in range(len(element.attributes)): + attr = element.attributes.item(i) + name = attr.nodeName + value = attr.value + ns = attr.namespaceURI + if ns: + name = "%s %s" % (constants.prefixes[ns], attr.localName) + else: + name = attr.nodeName + attributes.append((name, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + indent += 2 + for child in element.childNodes: + serializeElement(child, indent) + serializeElement(element, 0) + + return "\n".join(rv) + + return locals() + + +# The actual means to get a module! +getDomModule = moduleFactoryFactory(getDomBuilder) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py new file mode 100644 index 0000000..0dedf44 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py @@ -0,0 +1,340 @@ +from __future__ import absolute_import, division, unicode_literals +# pylint:disable=protected-access + +from pip._vendor.six import text_type + +import re + +from . import base +from .. import _ihatexml +from .. import constants +from ..constants import namespaces +from .._utils import moduleFactoryFactory + +tag_regexp = re.compile("{([^}]*)}(.*)") + + +def getETreeBuilder(ElementTreeImplementation, fullTree=False): + ElementTree = ElementTreeImplementation + ElementTreeCommentType = ElementTree.Comment("asd").tag + + class Element(base.Node): + def __init__(self, name, namespace=None): + self._name = name + self._namespace = namespace + self._element = ElementTree.Element(self._getETreeTag(name, + namespace)) + if namespace is None: + self.nameTuple = namespaces["html"], self._name + else: + self.nameTuple = self._namespace, self._name + self.parent = None + self._childNodes = [] + self._flags = [] + + def _getETreeTag(self, name, namespace): + if namespace is None: + etree_tag = name + else: + etree_tag = "{%s}%s" % (namespace, name) + return etree_tag + + def _setName(self, name): + self._name = name + self._element.tag = self._getETreeTag(self._name, self._namespace) + + def _getName(self): + return self._name + + name = property(_getName, _setName) + + def _setNamespace(self, namespace): + self._namespace = namespace + self._element.tag = self._getETreeTag(self._name, self._namespace) + + def _getNamespace(self): + return self._namespace + + namespace = property(_getNamespace, _setNamespace) + + def _getAttributes(self): + return self._element.attrib + + def _setAttributes(self, attributes): + # Delete existing attributes first + # XXX - there may be a better way to do this... + for key in list(self._element.attrib.keys()): + del self._element.attrib[key] + for key, value in attributes.items(): + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], key[1]) + else: + name = key + self._element.set(name, value) + + attributes = property(_getAttributes, _setAttributes) + + def _getChildNodes(self): + return self._childNodes + + def _setChildNodes(self, value): + del self._element[:] + self._childNodes = [] + for element in value: + self.insertChild(element) + + childNodes = property(_getChildNodes, _setChildNodes) + + def hasContent(self): + """Return true if the node has children or text""" + return bool(self._element.text or len(self._element)) + + def appendChild(self, node): + self._childNodes.append(node) + self._element.append(node._element) + node.parent = self + + def insertBefore(self, node, refNode): + index = list(self._element).index(refNode._element) + self._element.insert(index, node._element) + node.parent = self + + def removeChild(self, node): + self._childNodes.remove(node) + self._element.remove(node._element) + node.parent = None + + def insertText(self, data, insertBefore=None): + if not(len(self._element)): + if not self._element.text: + self._element.text = "" + self._element.text += data + elif insertBefore is None: + # Insert the text as the tail of the last child element + if not self._element[-1].tail: + self._element[-1].tail = "" + self._element[-1].tail += data + else: + # Insert the text before the specified node + children = list(self._element) + index = children.index(insertBefore._element) + if index > 0: + if not self._element[index - 1].tail: + self._element[index - 1].tail = "" + self._element[index - 1].tail += data + else: + if not self._element.text: + self._element.text = "" + self._element.text += data + + def cloneNode(self): + element = type(self)(self.name, self.namespace) + for name, value in self.attributes.items(): + element.attributes[name] = value + return element + + def reparentChildren(self, newParent): + if newParent.childNodes: + newParent.childNodes[-1]._element.tail += self._element.text + else: + if not newParent._element.text: + newParent._element.text = "" + if self._element.text is not None: + newParent._element.text += self._element.text + self._element.text = "" + base.Node.reparentChildren(self, newParent) + + class Comment(Element): + def __init__(self, data): + # Use the superclass constructor to set all properties on the + # wrapper element + self._element = ElementTree.Comment(data) + self.parent = None + self._childNodes = [] + self._flags = [] + + def _getData(self): + return self._element.text + + def _setData(self, value): + self._element.text = value + + data = property(_getData, _setData) + + class DocumentType(Element): + def __init__(self, name, publicId, systemId): + Element.__init__(self, "<!DOCTYPE>") + self._element.text = name + self.publicId = publicId + self.systemId = systemId + + def _getPublicId(self): + return self._element.get("publicId", "") + + def _setPublicId(self, value): + if value is not None: + self._element.set("publicId", value) + + publicId = property(_getPublicId, _setPublicId) + + def _getSystemId(self): + return self._element.get("systemId", "") + + def _setSystemId(self, value): + if value is not None: + self._element.set("systemId", value) + + systemId = property(_getSystemId, _setSystemId) + + class Document(Element): + def __init__(self): + Element.__init__(self, "DOCUMENT_ROOT") + + class DocumentFragment(Element): + def __init__(self): + Element.__init__(self, "DOCUMENT_FRAGMENT") + + def testSerializer(element): + rv = [] + + def serializeElement(element, indent=0): + if not(hasattr(element, "tag")): + element = element.getroot() + if element.tag == "<!DOCTYPE>": + if element.get("publicId") or element.get("systemId"): + publicId = element.get("publicId") or "" + systemId = element.get("systemId") or "" + rv.append("""<!DOCTYPE %s "%s" "%s">""" % + (element.text, publicId, systemId)) + else: + rv.append("<!DOCTYPE %s>" % (element.text,)) + elif element.tag == "DOCUMENT_ROOT": + rv.append("#document") + if element.text is not None: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + if element.tail is not None: + raise TypeError("Document node cannot have tail") + if hasattr(element, "attrib") and len(element.attrib): + raise TypeError("Document node cannot have attributes") + elif element.tag == ElementTreeCommentType: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) + else: + assert isinstance(element.tag, text_type), \ + "Expected unicode, got %s, %s" % (type(element.tag), element.tag) + nsmatch = tag_regexp.match(element.tag) + + if nsmatch is None: + name = element.tag + else: + ns, name = nsmatch.groups() + prefix = constants.prefixes[ns] + name = "%s %s" % (prefix, name) + rv.append("|%s<%s>" % (' ' * indent, name)) + + if hasattr(element, "attrib"): + attributes = [] + for name, value in element.attrib.items(): + nsmatch = tag_regexp.match(name) + if nsmatch is not None: + ns, name = nsmatch.groups() + prefix = constants.prefixes[ns] + attr_string = "%s %s" % (prefix, name) + else: + attr_string = name + attributes.append((attr_string, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + if element.text: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + indent += 2 + for child in element: + serializeElement(child, indent) + if element.tail: + rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) + serializeElement(element, 0) + + return "\n".join(rv) + + def tostring(element): # pylint:disable=unused-variable + """Serialize an element and its child nodes to a string""" + rv = [] + filter = _ihatexml.InfosetFilter() + + def serializeElement(element): + if isinstance(element, ElementTree.ElementTree): + element = element.getroot() + + if element.tag == "<!DOCTYPE>": + if element.get("publicId") or element.get("systemId"): + publicId = element.get("publicId") or "" + systemId = element.get("systemId") or "" + rv.append("""<!DOCTYPE %s PUBLIC "%s" "%s">""" % + (element.text, publicId, systemId)) + else: + rv.append("<!DOCTYPE %s>" % (element.text,)) + elif element.tag == "DOCUMENT_ROOT": + if element.text is not None: + rv.append(element.text) + if element.tail is not None: + raise TypeError("Document node cannot have tail") + if hasattr(element, "attrib") and len(element.attrib): + raise TypeError("Document node cannot have attributes") + + for child in element: + serializeElement(child) + + elif element.tag == ElementTreeCommentType: + rv.append("<!--%s-->" % (element.text,)) + else: + # This is assumed to be an ordinary element + if not element.attrib: + rv.append("<%s>" % (filter.fromXmlName(element.tag),)) + else: + attr = " ".join(["%s=\"%s\"" % ( + filter.fromXmlName(name), value) + for name, value in element.attrib.items()]) + rv.append("<%s %s>" % (element.tag, attr)) + if element.text: + rv.append(element.text) + + for child in element: + serializeElement(child) + + rv.append("</%s>" % (element.tag,)) + + if element.tail: + rv.append(element.tail) + + serializeElement(element) + + return "".join(rv) + + class TreeBuilder(base.TreeBuilder): # pylint:disable=unused-variable + documentClass = Document + doctypeClass = DocumentType + elementClass = Element + commentClass = Comment + fragmentClass = DocumentFragment + implementation = ElementTreeImplementation + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + if fullTree: + return self.document._element + else: + if self.defaultNamespace is not None: + return self.document._element.find( + "{%s}html" % self.defaultNamespace) + else: + return self.document._element.find("html") + + def getFragment(self): + return base.TreeBuilder.getFragment(self)._element + + return locals() + + +getETreeModule = moduleFactoryFactory(getETreeBuilder) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py new file mode 100644 index 0000000..ca12a99 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py @@ -0,0 +1,366 @@ +"""Module for supporting the lxml.etree library. The idea here is to use as much +of the native library as possible, without using fragile hacks like custom element +names that break between releases. The downside of this is that we cannot represent +all possible trees; specifically the following are known to cause problems: + +Text or comments as siblings of the root element +Docypes with no name + +When any of these things occur, we emit a DataLossWarning +""" + +from __future__ import absolute_import, division, unicode_literals +# pylint:disable=protected-access + +import warnings +import re +import sys + +from . import base +from ..constants import DataLossWarning +from .. import constants +from . import etree as etree_builders +from .. import _ihatexml + +import lxml.etree as etree + + +fullTree = True +tag_regexp = re.compile("{([^}]*)}(.*)") + +comment_type = etree.Comment("asd").tag + + +class DocumentType(object): + def __init__(self, name, publicId, systemId): + self.name = name + self.publicId = publicId + self.systemId = systemId + + +class Document(object): + def __init__(self): + self._elementTree = None + self._childNodes = [] + + def appendChild(self, element): + self._elementTree.getroot().addnext(element._element) + + def _getChildNodes(self): + return self._childNodes + + childNodes = property(_getChildNodes) + + +def testSerializer(element): + rv = [] + infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) + + def serializeElement(element, indent=0): + if not hasattr(element, "tag"): + if hasattr(element, "getroot"): + # Full tree case + rv.append("#document") + if element.docinfo.internalDTD: + if not (element.docinfo.public_id or + element.docinfo.system_url): + dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name + else: + dtd_str = """<!DOCTYPE %s "%s" "%s">""" % ( + element.docinfo.root_name, + element.docinfo.public_id, + element.docinfo.system_url) + rv.append("|%s%s" % (' ' * (indent + 2), dtd_str)) + next_element = element.getroot() + while next_element.getprevious() is not None: + next_element = next_element.getprevious() + while next_element is not None: + serializeElement(next_element, indent + 2) + next_element = next_element.getnext() + elif isinstance(element, str) or isinstance(element, bytes): + # Text in a fragment + assert isinstance(element, str) or sys.version_info[0] == 2 + rv.append("|%s\"%s\"" % (' ' * indent, element)) + else: + # Fragment case + rv.append("#document-fragment") + for next_element in element: + serializeElement(next_element, indent + 2) + elif element.tag == comment_type: + rv.append("|%s<!-- %s -->" % (' ' * indent, element.text)) + if hasattr(element, "tail") and element.tail: + rv.append("|%s\"%s\"" % (' ' * indent, element.tail)) + else: + assert isinstance(element, etree._Element) + nsmatch = etree_builders.tag_regexp.match(element.tag) + if nsmatch is not None: + ns = nsmatch.group(1) + tag = nsmatch.group(2) + prefix = constants.prefixes[ns] + rv.append("|%s<%s %s>" % (' ' * indent, prefix, + infosetFilter.fromXmlName(tag))) + else: + rv.append("|%s<%s>" % (' ' * indent, + infosetFilter.fromXmlName(element.tag))) + + if hasattr(element, "attrib"): + attributes = [] + for name, value in element.attrib.items(): + nsmatch = tag_regexp.match(name) + if nsmatch is not None: + ns, name = nsmatch.groups() + name = infosetFilter.fromXmlName(name) + prefix = constants.prefixes[ns] + attr_string = "%s %s" % (prefix, name) + else: + attr_string = infosetFilter.fromXmlName(name) + attributes.append((attr_string, value)) + + for name, value in sorted(attributes): + rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value)) + + if element.text: + rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text)) + indent += 2 + for child in element: + serializeElement(child, indent) + if hasattr(element, "tail") and element.tail: + rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail)) + serializeElement(element, 0) + + return "\n".join(rv) + + +def tostring(element): + """Serialize an element and its child nodes to a string""" + rv = [] + + def serializeElement(element): + if not hasattr(element, "tag"): + if element.docinfo.internalDTD: + if element.docinfo.doctype: + dtd_str = element.docinfo.doctype + else: + dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name + rv.append(dtd_str) + serializeElement(element.getroot()) + + elif element.tag == comment_type: + rv.append("<!--%s-->" % (element.text,)) + + else: + # This is assumed to be an ordinary element + if not element.attrib: + rv.append("<%s>" % (element.tag,)) + else: + attr = " ".join(["%s=\"%s\"" % (name, value) + for name, value in element.attrib.items()]) + rv.append("<%s %s>" % (element.tag, attr)) + if element.text: + rv.append(element.text) + + for child in element: + serializeElement(child) + + rv.append("</%s>" % (element.tag,)) + + if hasattr(element, "tail") and element.tail: + rv.append(element.tail) + + serializeElement(element) + + return "".join(rv) + + +class TreeBuilder(base.TreeBuilder): + documentClass = Document + doctypeClass = DocumentType + elementClass = None + commentClass = None + fragmentClass = Document + implementation = etree + + def __init__(self, namespaceHTMLElements, fullTree=False): + builder = etree_builders.getETreeModule(etree, fullTree=fullTree) + infosetFilter = self.infosetFilter = _ihatexml.InfosetFilter(preventDoubleDashComments=True) + self.namespaceHTMLElements = namespaceHTMLElements + + class Attributes(dict): + def __init__(self, element, value=None): + if value is None: + value = {} + self._element = element + dict.__init__(self, value) # pylint:disable=non-parent-init-called + for key, value in self.items(): + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) + else: + name = infosetFilter.coerceAttribute(key) + self._element._element.attrib[name] = value + + def __setitem__(self, key, value): + dict.__setitem__(self, key, value) + if isinstance(key, tuple): + name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1])) + else: + name = infosetFilter.coerceAttribute(key) + self._element._element.attrib[name] = value + + class Element(builder.Element): + def __init__(self, name, namespace): + name = infosetFilter.coerceElement(name) + builder.Element.__init__(self, name, namespace=namespace) + self._attributes = Attributes(self) + + def _setName(self, name): + self._name = infosetFilter.coerceElement(name) + self._element.tag = self._getETreeTag( + self._name, self._namespace) + + def _getName(self): + return infosetFilter.fromXmlName(self._name) + + name = property(_getName, _setName) + + def _getAttributes(self): + return self._attributes + + def _setAttributes(self, attributes): + self._attributes = Attributes(self, attributes) + + attributes = property(_getAttributes, _setAttributes) + + def insertText(self, data, insertBefore=None): + data = infosetFilter.coerceCharacters(data) + builder.Element.insertText(self, data, insertBefore) + + def appendChild(self, child): + builder.Element.appendChild(self, child) + + class Comment(builder.Comment): + def __init__(self, data): + data = infosetFilter.coerceComment(data) + builder.Comment.__init__(self, data) + + def _setData(self, data): + data = infosetFilter.coerceComment(data) + self._element.text = data + + def _getData(self): + return self._element.text + + data = property(_getData, _setData) + + self.elementClass = Element + self.commentClass = Comment + # self.fragmentClass = builder.DocumentFragment + base.TreeBuilder.__init__(self, namespaceHTMLElements) + + def reset(self): + base.TreeBuilder.reset(self) + self.insertComment = self.insertCommentInitial + self.initial_comments = [] + self.doctype = None + + def testSerializer(self, element): + return testSerializer(element) + + def getDocument(self): + if fullTree: + return self.document._elementTree + else: + return self.document._elementTree.getroot() + + def getFragment(self): + fragment = [] + element = self.openElements[0]._element + if element.text: + fragment.append(element.text) + fragment.extend(list(element)) + if element.tail: + fragment.append(element.tail) + return fragment + + def insertDoctype(self, token): + name = token["name"] + publicId = token["publicId"] + systemId = token["systemId"] + + if not name: + warnings.warn("lxml cannot represent empty doctype", DataLossWarning) + self.doctype = None + else: + coercedName = self.infosetFilter.coerceElement(name) + if coercedName != name: + warnings.warn("lxml cannot represent non-xml doctype", DataLossWarning) + + doctype = self.doctypeClass(coercedName, publicId, systemId) + self.doctype = doctype + + def insertCommentInitial(self, data, parent=None): + assert parent is None or parent is self.document + assert self.document._elementTree is None + self.initial_comments.append(data) + + def insertCommentMain(self, data, parent=None): + if (parent == self.document and + self.document._elementTree.getroot()[-1].tag == comment_type): + warnings.warn("lxml cannot represent adjacent comments beyond the root elements", DataLossWarning) + super(TreeBuilder, self).insertComment(data, parent) + + def insertRoot(self, token): + # Because of the way libxml2 works, it doesn't seem to be possible to + # alter information like the doctype after the tree has been parsed. + # Therefore we need to use the built-in parser to create our initial + # tree, after which we can add elements like normal + docStr = "" + if self.doctype: + assert self.doctype.name + docStr += "<!DOCTYPE %s" % self.doctype.name + if (self.doctype.publicId is not None or + self.doctype.systemId is not None): + docStr += (' PUBLIC "%s" ' % + (self.infosetFilter.coercePubid(self.doctype.publicId or ""))) + if self.doctype.systemId: + sysid = self.doctype.systemId + if sysid.find("'") >= 0 and sysid.find('"') >= 0: + warnings.warn("DOCTYPE system cannot contain single and double quotes", DataLossWarning) + sysid = sysid.replace("'", 'U00027') + if sysid.find("'") >= 0: + docStr += '"%s"' % sysid + else: + docStr += "'%s'" % sysid + else: + docStr += "''" + docStr += ">" + if self.doctype.name != token["name"]: + warnings.warn("lxml cannot represent doctype with a different name to the root element", DataLossWarning) + docStr += "<THIS_SHOULD_NEVER_APPEAR_PUBLICLY/>" + root = etree.fromstring(docStr) + + # Append the initial comments: + for comment_token in self.initial_comments: + comment = self.commentClass(comment_token["data"]) + root.addprevious(comment._element) + + # Create the root document and add the ElementTree to it + self.document = self.documentClass() + self.document._elementTree = root.getroottree() + + # Give the root element the right name + name = token["name"] + namespace = token.get("namespace", self.defaultNamespace) + if namespace is None: + etree_tag = name + else: + etree_tag = "{%s}%s" % (namespace, name) + root.tag = etree_tag + + # Add the root element to the internal child/open data structures + root_element = self.elementClass(name, namespace) + root_element._element = root + self.document._childNodes.append(root_element) + self.openElements.append(root_element) + + # Reset to the default insert comment function + self.insertComment = self.insertCommentMain diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py new file mode 100644 index 0000000..9bec207 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py @@ -0,0 +1,154 @@ +"""A collection of modules for iterating through different kinds of +tree, generating tokens identical to those produced by the tokenizer +module. + +To create a tree walker for a new type of tree, you need to do +implement a tree walker object (called TreeWalker by convention) that +implements a 'serialize' method taking a tree as sole argument and +returning an iterator generating tokens. +""" + +from __future__ import absolute_import, division, unicode_literals + +from .. import constants +from .._utils import default_etree + +__all__ = ["getTreeWalker", "pprint"] + +treeWalkerCache = {} + + +def getTreeWalker(treeType, implementation=None, **kwargs): + """Get a TreeWalker class for various types of tree with built-in support + + :arg str treeType: the name of the tree type required (case-insensitive). + Supported values are: + + * "dom": The xml.dom.minidom DOM implementation + * "etree": A generic walker for tree implementations exposing an + elementtree-like interface (known to work with ElementTree, + cElementTree and lxml.etree). + * "lxml": Optimized walker for lxml.etree + * "genshi": a Genshi stream + + :arg implementation: A module implementing the tree type e.g. + xml.etree.ElementTree or cElementTree (Currently applies to the "etree" + tree type only). + + :arg kwargs: keyword arguments passed to the etree walker--for other + walkers, this has no effect + + :returns: a TreeWalker class + + """ + + treeType = treeType.lower() + if treeType not in treeWalkerCache: + if treeType == "dom": + from . import dom + treeWalkerCache[treeType] = dom.TreeWalker + elif treeType == "genshi": + from . import genshi + treeWalkerCache[treeType] = genshi.TreeWalker + elif treeType == "lxml": + from . import etree_lxml + treeWalkerCache[treeType] = etree_lxml.TreeWalker + elif treeType == "etree": + from . import etree + if implementation is None: + implementation = default_etree + # XXX: NEVER cache here, caching is done in the etree submodule + return etree.getETreeModule(implementation, **kwargs).TreeWalker + return treeWalkerCache.get(treeType) + + +def concatenateCharacterTokens(tokens): + pendingCharacters = [] + for token in tokens: + type = token["type"] + if type in ("Characters", "SpaceCharacters"): + pendingCharacters.append(token["data"]) + else: + if pendingCharacters: + yield {"type": "Characters", "data": "".join(pendingCharacters)} + pendingCharacters = [] + yield token + if pendingCharacters: + yield {"type": "Characters", "data": "".join(pendingCharacters)} + + +def pprint(walker): + """Pretty printer for tree walkers + + Takes a TreeWalker instance and pretty prints the output of walking the tree. + + :arg walker: a TreeWalker instance + + """ + output = [] + indent = 0 + for token in concatenateCharacterTokens(walker): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + # tag name + if token["namespace"] and token["namespace"] != constants.namespaces["html"]: + if token["namespace"] in constants.prefixes: + ns = constants.prefixes[token["namespace"]] + else: + ns = token["namespace"] + name = "%s %s" % (ns, token["name"]) + else: + name = token["name"] + output.append("%s<%s>" % (" " * indent, name)) + indent += 2 + # attributes (sorted for consistent ordering) + attrs = token["data"] + for (namespace, localname), value in sorted(attrs.items()): + if namespace: + if namespace in constants.prefixes: + ns = constants.prefixes[namespace] + else: + ns = namespace + name = "%s %s" % (ns, localname) + else: + name = localname + output.append("%s%s=\"%s\"" % (" " * indent, name, value)) + # self-closing + if type == "EmptyTag": + indent -= 2 + + elif type == "EndTag": + indent -= 2 + + elif type == "Comment": + output.append("%s<!-- %s -->" % (" " * indent, token["data"])) + + elif type == "Doctype": + if token["name"]: + if token["publicId"]: + output.append("""%s<!DOCTYPE %s "%s" "%s">""" % + (" " * indent, + token["name"], + token["publicId"], + token["systemId"] if token["systemId"] else "")) + elif token["systemId"]: + output.append("""%s<!DOCTYPE %s "" "%s">""" % + (" " * indent, + token["name"], + token["systemId"])) + else: + output.append("%s<!DOCTYPE %s>" % (" " * indent, + token["name"])) + else: + output.append("%s<!DOCTYPE >" % (" " * indent,)) + + elif type == "Characters": + output.append("%s\"%s\"" % (" " * indent, token["data"])) + + elif type == "SpaceCharacters": + assert False, "concatenateCharacterTokens should have got rid of all Space tokens" + + else: + raise ValueError("Unknown token type, %s" % type) + + return "\n".join(output) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/base.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/base.py new file mode 100644 index 0000000..80c474c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/base.py @@ -0,0 +1,252 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.dom import Node +from ..constants import namespaces, voidElements, spaceCharacters + +__all__ = ["DOCUMENT", "DOCTYPE", "TEXT", "ELEMENT", "COMMENT", "ENTITY", "UNKNOWN", + "TreeWalker", "NonRecursiveTreeWalker"] + +DOCUMENT = Node.DOCUMENT_NODE +DOCTYPE = Node.DOCUMENT_TYPE_NODE +TEXT = Node.TEXT_NODE +ELEMENT = Node.ELEMENT_NODE +COMMENT = Node.COMMENT_NODE +ENTITY = Node.ENTITY_NODE +UNKNOWN = "<#UNKNOWN#>" + +spaceCharacters = "".join(spaceCharacters) + + +class TreeWalker(object): + """Walks a tree yielding tokens + + Tokens are dicts that all have a ``type`` field specifying the type of the + token. + + """ + def __init__(self, tree): + """Creates a TreeWalker + + :arg tree: the tree to walk + + """ + self.tree = tree + + def __iter__(self): + raise NotImplementedError + + def error(self, msg): + """Generates an error token with the given message + + :arg msg: the error message + + :returns: SerializeError token + + """ + return {"type": "SerializeError", "data": msg} + + def emptyTag(self, namespace, name, attrs, hasChildren=False): + """Generates an EmptyTag token + + :arg namespace: the namespace of the token--can be ``None`` + + :arg name: the name of the element + + :arg attrs: the attributes of the element as a dict + + :arg hasChildren: whether or not to yield a SerializationError because + this tag shouldn't have children + + :returns: EmptyTag token + + """ + yield {"type": "EmptyTag", "name": name, + "namespace": namespace, + "data": attrs} + if hasChildren: + yield self.error("Void element has children") + + def startTag(self, namespace, name, attrs): + """Generates a StartTag token + + :arg namespace: the namespace of the token--can be ``None`` + + :arg name: the name of the element + + :arg attrs: the attributes of the element as a dict + + :returns: StartTag token + + """ + return {"type": "StartTag", + "name": name, + "namespace": namespace, + "data": attrs} + + def endTag(self, namespace, name): + """Generates an EndTag token + + :arg namespace: the namespace of the token--can be ``None`` + + :arg name: the name of the element + + :returns: EndTag token + + """ + return {"type": "EndTag", + "name": name, + "namespace": namespace} + + def text(self, data): + """Generates SpaceCharacters and Characters tokens + + Depending on what's in the data, this generates one or more + ``SpaceCharacters`` and ``Characters`` tokens. + + For example: + + >>> from html5lib.treewalkers.base import TreeWalker + >>> # Give it an empty tree just so it instantiates + >>> walker = TreeWalker([]) + >>> list(walker.text('')) + [] + >>> list(walker.text(' ')) + [{u'data': ' ', u'type': u'SpaceCharacters'}] + >>> list(walker.text(' abc ')) # doctest: +NORMALIZE_WHITESPACE + [{u'data': ' ', u'type': u'SpaceCharacters'}, + {u'data': u'abc', u'type': u'Characters'}, + {u'data': u' ', u'type': u'SpaceCharacters'}] + + :arg data: the text data + + :returns: one or more ``SpaceCharacters`` and ``Characters`` tokens + + """ + data = data + middle = data.lstrip(spaceCharacters) + left = data[:len(data) - len(middle)] + if left: + yield {"type": "SpaceCharacters", "data": left} + data = middle + middle = data.rstrip(spaceCharacters) + right = data[len(middle):] + if middle: + yield {"type": "Characters", "data": middle} + if right: + yield {"type": "SpaceCharacters", "data": right} + + def comment(self, data): + """Generates a Comment token + + :arg data: the comment + + :returns: Comment token + + """ + return {"type": "Comment", "data": data} + + def doctype(self, name, publicId=None, systemId=None): + """Generates a Doctype token + + :arg name: + + :arg publicId: + + :arg systemId: + + :returns: the Doctype token + + """ + return {"type": "Doctype", + "name": name, + "publicId": publicId, + "systemId": systemId} + + def entity(self, name): + """Generates an Entity token + + :arg name: the entity name + + :returns: an Entity token + + """ + return {"type": "Entity", "name": name} + + def unknown(self, nodeType): + """Handles unknown node types""" + return self.error("Unknown node type: " + nodeType) + + +class NonRecursiveTreeWalker(TreeWalker): + def getNodeDetails(self, node): + raise NotImplementedError + + def getFirstChild(self, node): + raise NotImplementedError + + def getNextSibling(self, node): + raise NotImplementedError + + def getParentNode(self, node): + raise NotImplementedError + + def __iter__(self): + currentNode = self.tree + while currentNode is not None: + details = self.getNodeDetails(currentNode) + type, details = details[0], details[1:] + hasChildren = False + + if type == DOCTYPE: + yield self.doctype(*details) + + elif type == TEXT: + for token in self.text(*details): + yield token + + elif type == ELEMENT: + namespace, name, attributes, hasChildren = details + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + for token in self.emptyTag(namespace, name, attributes, + hasChildren): + yield token + hasChildren = False + else: + yield self.startTag(namespace, name, attributes) + + elif type == COMMENT: + yield self.comment(details[0]) + + elif type == ENTITY: + yield self.entity(details[0]) + + elif type == DOCUMENT: + hasChildren = True + + else: + yield self.unknown(details[0]) + + if hasChildren: + firstChild = self.getFirstChild(currentNode) + else: + firstChild = None + + if firstChild is not None: + currentNode = firstChild + else: + while currentNode is not None: + details = self.getNodeDetails(currentNode) + type, details = details[0], details[1:] + if type == ELEMENT: + namespace, name, attributes, hasChildren = details + if (namespace and namespace != namespaces["html"]) or name not in voidElements: + yield self.endTag(namespace, name) + if self.tree is currentNode: + currentNode = None + break + nextSibling = self.getNextSibling(currentNode) + if nextSibling is not None: + currentNode = nextSibling + break + else: + currentNode = self.getParentNode(currentNode) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py new file mode 100644 index 0000000..b0c89b0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py @@ -0,0 +1,43 @@ +from __future__ import absolute_import, division, unicode_literals + +from xml.dom import Node + +from . import base + + +class TreeWalker(base.NonRecursiveTreeWalker): + def getNodeDetails(self, node): + if node.nodeType == Node.DOCUMENT_TYPE_NODE: + return base.DOCTYPE, node.name, node.publicId, node.systemId + + elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE): + return base.TEXT, node.nodeValue + + elif node.nodeType == Node.ELEMENT_NODE: + attrs = {} + for attr in list(node.attributes.keys()): + attr = node.getAttributeNode(attr) + if attr.namespaceURI: + attrs[(attr.namespaceURI, attr.localName)] = attr.value + else: + attrs[(None, attr.name)] = attr.value + return (base.ELEMENT, node.namespaceURI, node.nodeName, + attrs, node.hasChildNodes()) + + elif node.nodeType == Node.COMMENT_NODE: + return base.COMMENT, node.nodeValue + + elif node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE): + return (base.DOCUMENT,) + + else: + return base.UNKNOWN, node.nodeType + + def getFirstChild(self, node): + return node.firstChild + + def getNextSibling(self, node): + return node.nextSibling + + def getParentNode(self, node): + return node.parentNode diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py new file mode 100644 index 0000000..95fc0c1 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py @@ -0,0 +1,130 @@ +from __future__ import absolute_import, division, unicode_literals + +from collections import OrderedDict +import re + +from pip._vendor.six import string_types + +from . import base +from .._utils import moduleFactoryFactory + +tag_regexp = re.compile("{([^}]*)}(.*)") + + +def getETreeBuilder(ElementTreeImplementation): + ElementTree = ElementTreeImplementation + ElementTreeCommentType = ElementTree.Comment("asd").tag + + class TreeWalker(base.NonRecursiveTreeWalker): # pylint:disable=unused-variable + """Given the particular ElementTree representation, this implementation, + to avoid using recursion, returns "nodes" as tuples with the following + content: + + 1. The current element + + 2. The index of the element relative to its parent + + 3. A stack of ancestor elements + + 4. A flag "text", "tail" or None to indicate if the current node is a + text node; either the text or tail of the current element (1) + """ + def getNodeDetails(self, node): + if isinstance(node, tuple): # It might be the root Element + elt, _, _, flag = node + if flag in ("text", "tail"): + return base.TEXT, getattr(elt, flag) + else: + node = elt + + if not(hasattr(node, "tag")): + node = node.getroot() + + if node.tag in ("DOCUMENT_ROOT", "DOCUMENT_FRAGMENT"): + return (base.DOCUMENT,) + + elif node.tag == "<!DOCTYPE>": + return (base.DOCTYPE, node.text, + node.get("publicId"), node.get("systemId")) + + elif node.tag == ElementTreeCommentType: + return base.COMMENT, node.text + + else: + assert isinstance(node.tag, string_types), type(node.tag) + # This is assumed to be an ordinary element + match = tag_regexp.match(node.tag) + if match: + namespace, tag = match.groups() + else: + namespace = None + tag = node.tag + attrs = OrderedDict() + for name, value in list(node.attrib.items()): + match = tag_regexp.match(name) + if match: + attrs[(match.group(1), match.group(2))] = value + else: + attrs[(None, name)] = value + return (base.ELEMENT, namespace, tag, + attrs, len(node) or node.text) + + def getFirstChild(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + element, key, parents, flag = node, None, [], None + + if flag in ("text", "tail"): + return None + else: + if element.text: + return element, key, parents, "text" + elif len(element): + parents.append(element) + return element[0], 0, parents, None + else: + return None + + def getNextSibling(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + return None + + if flag == "text": + if len(element): + parents.append(element) + return element[0], 0, parents, None + else: + return None + else: + if element.tail and flag != "tail": + return element, key, parents, "tail" + elif key < len(parents[-1]) - 1: + return parents[-1][key + 1], key + 1, parents, None + else: + return None + + def getParentNode(self, node): + if isinstance(node, tuple): + element, key, parents, flag = node + else: + return None + + if flag == "text": + if not parents: + return element + else: + return element, key, parents, None + else: + parent = parents.pop() + if not parents: + return parent + else: + assert list(parents[-1]).count(parent) == 1 + return parent, list(parents[-1]).index(parent), parents, None + + return locals() + +getETreeModule = moduleFactoryFactory(getETreeBuilder) diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py new file mode 100644 index 0000000..e81ddf3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py @@ -0,0 +1,213 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from lxml import etree +from ..treebuilders.etree import tag_regexp + +from . import base + +from .. import _ihatexml + + +def ensure_str(s): + if s is None: + return None + elif isinstance(s, text_type): + return s + else: + return s.decode("ascii", "strict") + + +class Root(object): + def __init__(self, et): + self.elementtree = et + self.children = [] + + try: + if et.docinfo.internalDTD: + self.children.append(Doctype(self, + ensure_str(et.docinfo.root_name), + ensure_str(et.docinfo.public_id), + ensure_str(et.docinfo.system_url))) + except AttributeError: + pass + + try: + node = et.getroot() + except AttributeError: + node = et + + while node.getprevious() is not None: + node = node.getprevious() + while node is not None: + self.children.append(node) + node = node.getnext() + + self.text = None + self.tail = None + + def __getitem__(self, key): + return self.children[key] + + def getnext(self): + return None + + def __len__(self): + return 1 + + +class Doctype(object): + def __init__(self, root_node, name, public_id, system_id): + self.root_node = root_node + self.name = name + self.public_id = public_id + self.system_id = system_id + + self.text = None + self.tail = None + + def getnext(self): + return self.root_node.children[1] + + +class FragmentRoot(Root): + def __init__(self, children): + self.children = [FragmentWrapper(self, child) for child in children] + self.text = self.tail = None + + def getnext(self): + return None + + +class FragmentWrapper(object): + def __init__(self, fragment_root, obj): + self.root_node = fragment_root + self.obj = obj + if hasattr(self.obj, 'text'): + self.text = ensure_str(self.obj.text) + else: + self.text = None + if hasattr(self.obj, 'tail'): + self.tail = ensure_str(self.obj.tail) + else: + self.tail = None + + def __getattr__(self, name): + return getattr(self.obj, name) + + def getnext(self): + siblings = self.root_node.children + idx = siblings.index(self) + if idx < len(siblings) - 1: + return siblings[idx + 1] + else: + return None + + def __getitem__(self, key): + return self.obj[key] + + def __bool__(self): + return bool(self.obj) + + def getparent(self): + return None + + def __str__(self): + return str(self.obj) + + def __unicode__(self): + return str(self.obj) + + def __len__(self): + return len(self.obj) + + +class TreeWalker(base.NonRecursiveTreeWalker): + def __init__(self, tree): + # pylint:disable=redefined-variable-type + if isinstance(tree, list): + self.fragmentChildren = set(tree) + tree = FragmentRoot(tree) + else: + self.fragmentChildren = set() + tree = Root(tree) + base.NonRecursiveTreeWalker.__init__(self, tree) + self.filter = _ihatexml.InfosetFilter() + + def getNodeDetails(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + return base.TEXT, ensure_str(getattr(node, key)) + + elif isinstance(node, Root): + return (base.DOCUMENT,) + + elif isinstance(node, Doctype): + return base.DOCTYPE, node.name, node.public_id, node.system_id + + elif isinstance(node, FragmentWrapper) and not hasattr(node, "tag"): + return base.TEXT, ensure_str(node.obj) + + elif node.tag == etree.Comment: + return base.COMMENT, ensure_str(node.text) + + elif node.tag == etree.Entity: + return base.ENTITY, ensure_str(node.text)[1:-1] # strip &; + + else: + # This is assumed to be an ordinary element + match = tag_regexp.match(ensure_str(node.tag)) + if match: + namespace, tag = match.groups() + else: + namespace = None + tag = ensure_str(node.tag) + attrs = {} + for name, value in list(node.attrib.items()): + name = ensure_str(name) + value = ensure_str(value) + match = tag_regexp.match(name) + if match: + attrs[(match.group(1), match.group(2))] = value + else: + attrs[(None, name)] = value + return (base.ELEMENT, namespace, self.filter.fromXmlName(tag), + attrs, len(node) > 0 or node.text) + + def getFirstChild(self, node): + assert not isinstance(node, tuple), "Text nodes have no children" + + assert len(node) or node.text, "Node has no children" + if node.text: + return (node, "text") + else: + return node[0] + + def getNextSibling(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + if key == "text": + # XXX: we cannot use a "bool(node) and node[0] or None" construct here + # because node[0] might evaluate to False if it has no child element + if len(node): + return node[0] + else: + return None + else: # tail + return node.getnext() + + return (node, "tail") if node.tail else node.getnext() + + def getParentNode(self, node): + if isinstance(node, tuple): # Text node + node, key = node + assert key in ("text", "tail"), "Text nodes are text or tail, found %s" % key + if key == "text": + return node + # else: fallback to "normal" processing + elif node in self.fragmentChildren: + return None + + return node.getparent() diff --git a/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py new file mode 100644 index 0000000..7483be2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py @@ -0,0 +1,69 @@ +from __future__ import absolute_import, division, unicode_literals + +from genshi.core import QName +from genshi.core import START, END, XML_NAMESPACE, DOCTYPE, TEXT +from genshi.core import START_NS, END_NS, START_CDATA, END_CDATA, PI, COMMENT + +from . import base + +from ..constants import voidElements, namespaces + + +class TreeWalker(base.TreeWalker): + def __iter__(self): + # Buffer the events so we can pass in the following one + previous = None + for event in self.tree: + if previous is not None: + for token in self.tokens(previous, event): + yield token + previous = event + + # Don't forget the final event! + if previous is not None: + for token in self.tokens(previous, None): + yield token + + def tokens(self, event, next): + kind, data, _ = event + if kind == START: + tag, attribs = data + name = tag.localname + namespace = tag.namespace + converted_attribs = {} + for k, v in attribs: + if isinstance(k, QName): + converted_attribs[(k.namespace, k.localname)] = v + else: + converted_attribs[(None, k)] = v + + if namespace == namespaces["html"] and name in voidElements: + for token in self.emptyTag(namespace, name, converted_attribs, + not next or next[0] != END or + next[1] != tag): + yield token + else: + yield self.startTag(namespace, name, converted_attribs) + + elif kind == END: + name = data.localname + namespace = data.namespace + if namespace != namespaces["html"] or name not in voidElements: + yield self.endTag(namespace, name) + + elif kind == COMMENT: + yield self.comment(data) + + elif kind == TEXT: + for token in self.text(data): + yield token + + elif kind == DOCTYPE: + yield self.doctype(*data) + + elif kind in (XML_NAMESPACE, DOCTYPE, START_NS, END_NS, + START_CDATA, END_CDATA, PI): + pass + + else: + yield self.unknown(kind) diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/idna/__init__.py new file mode 100644 index 0000000..847bf93 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/__init__.py @@ -0,0 +1,2 @@ +from .package_data import __version__ +from .core import * diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/codec.py b/winvenv/Lib/site-packages/pip/_vendor/idna/codec.py new file mode 100644 index 0000000..98c65ea --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/codec.py @@ -0,0 +1,118 @@ +from .core import encode, decode, alabel, ulabel, IDNAError +import codecs +import re + +_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') + +class Codec(codecs.Codec): + + def encode(self, data, errors='strict'): + + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return "", 0 + + return encode(data), len(data) + + def decode(self, data, errors='strict'): + + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return u"", 0 + + return decode(data), len(data) + +class IncrementalEncoder(codecs.BufferedIncrementalEncoder): + def _buffer_encode(self, data, errors, final): + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return ("", 0) + + labels = _unicode_dots_re.split(data) + trailing_dot = u'' + if labels: + if not labels[-1]: + trailing_dot = '.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = '.' + + result = [] + size = 0 + for label in labels: + result.append(alabel(label)) + if size: + size += 1 + size += len(label) + + # Join with U+002E + result = ".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + +class IncrementalDecoder(codecs.BufferedIncrementalDecoder): + def _buffer_decode(self, data, errors, final): + if errors != 'strict': + raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + + if not data: + return (u"", 0) + + # IDNA allows decoding to operate on Unicode strings, too. + if isinstance(data, unicode): + labels = _unicode_dots_re.split(data) + else: + # Must be ASCII string + data = str(data) + unicode(data, "ascii") + labels = data.split(".") + + trailing_dot = u'' + if labels: + if not labels[-1]: + trailing_dot = u'.' + del labels[-1] + elif not final: + # Keep potentially unfinished label until the next call + del labels[-1] + if labels: + trailing_dot = u'.' + + result = [] + size = 0 + for label in labels: + result.append(ulabel(label)) + if size: + size += 1 + size += len(label) + + result = u".".join(result) + trailing_dot + size += len(trailing_dot) + return (result, size) + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + +class StreamReader(Codec, codecs.StreamReader): + pass + +def getregentry(): + return codecs.CodecInfo( + name='idna', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamwriter=StreamWriter, + streamreader=StreamReader, + ) diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/compat.py b/winvenv/Lib/site-packages/pip/_vendor/idna/compat.py new file mode 100644 index 0000000..4d47f33 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/compat.py @@ -0,0 +1,12 @@ +from .core import * +from .codec import * + +def ToASCII(label): + return encode(label) + +def ToUnicode(label): + return decode(label) + +def nameprep(s): + raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") + diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/core.py b/winvenv/Lib/site-packages/pip/_vendor/idna/core.py new file mode 100644 index 0000000..090c2c1 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/core.py @@ -0,0 +1,399 @@ +from . import idnadata +import bisect +import unicodedata +import re +import sys +from .intranges import intranges_contain + +_virama_combining_class = 9 +_alabel_prefix = b'xn--' +_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') + +if sys.version_info[0] == 3: + unicode = str + unichr = chr + +class IDNAError(UnicodeError): + """ Base exception for all IDNA-encoding related problems """ + pass + + +class IDNABidiError(IDNAError): + """ Exception when bidirectional requirements are not satisfied """ + pass + + +class InvalidCodepoint(IDNAError): + """ Exception when a disallowed or unallocated codepoint is used """ + pass + + +class InvalidCodepointContext(IDNAError): + """ Exception when the codepoint is not valid in the context it is used """ + pass + + +def _combining_class(cp): + v = unicodedata.combining(unichr(cp)) + if v == 0: + if not unicodedata.name(unichr(cp)): + raise ValueError("Unknown character in unicodedata") + return v + +def _is_script(cp, script): + return intranges_contain(ord(cp), idnadata.scripts[script]) + +def _punycode(s): + return s.encode('punycode') + +def _unot(s): + return 'U+{0:04X}'.format(s) + + +def valid_label_length(label): + + if len(label) > 63: + return False + return True + + +def valid_string_length(label, trailing_dot): + + if len(label) > (254 if trailing_dot else 253): + return False + return True + + +def check_bidi(label, check_ltr=False): + + # Bidi rules should only be applied if string contains RTL characters + bidi_label = False + for (idx, cp) in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + if direction == '': + # String likely comes from a newer version of Unicode + raise IDNABidiError('Unknown directionality in label {0} at position {1}'.format(repr(label), idx)) + if direction in ['R', 'AL', 'AN']: + bidi_label = True + if not bidi_label and not check_ltr: + return True + + # Bidi rule 1 + direction = unicodedata.bidirectional(label[0]) + if direction in ['R', 'AL']: + rtl = True + elif direction == 'L': + rtl = False + else: + raise IDNABidiError('First codepoint in label {0} must be directionality L, R or AL'.format(repr(label))) + + valid_ending = False + number_type = False + for (idx, cp) in enumerate(label, 1): + direction = unicodedata.bidirectional(cp) + + if rtl: + # Bidi rule 2 + if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: + raise IDNABidiError('Invalid direction for codepoint at position {0} in a right-to-left label'.format(idx)) + # Bidi rule 3 + if direction in ['R', 'AL', 'EN', 'AN']: + valid_ending = True + elif direction != 'NSM': + valid_ending = False + # Bidi rule 4 + if direction in ['AN', 'EN']: + if not number_type: + number_type = direction + else: + if number_type != direction: + raise IDNABidiError('Can not mix numeral types in a right-to-left label') + else: + # Bidi rule 5 + if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: + raise IDNABidiError('Invalid direction for codepoint at position {0} in a left-to-right label'.format(idx)) + # Bidi rule 6 + if direction in ['L', 'EN']: + valid_ending = True + elif direction != 'NSM': + valid_ending = False + + if not valid_ending: + raise IDNABidiError('Label ends with illegal codepoint directionality') + + return True + + +def check_initial_combiner(label): + + if unicodedata.category(label[0])[0] == 'M': + raise IDNAError('Label begins with an illegal combining character') + return True + + +def check_hyphen_ok(label): + + if label[2:4] == '--': + raise IDNAError('Label has disallowed hyphens in 3rd and 4th position') + if label[0] == '-' or label[-1] == '-': + raise IDNAError('Label must not start or end with a hyphen') + return True + + +def check_nfc(label): + + if unicodedata.normalize('NFC', label) != label: + raise IDNAError('Label must be in Normalization Form C') + + +def valid_contextj(label, pos): + + cp_value = ord(label[pos]) + + if cp_value == 0x200c: + + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + + ok = False + for i in range(pos-1, -1, -1): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord('T'): + continue + if joining_type in [ord('L'), ord('D')]: + ok = True + break + + if not ok: + return False + + ok = False + for i in range(pos+1, len(label)): + joining_type = idnadata.joining_types.get(ord(label[i])) + if joining_type == ord('T'): + continue + if joining_type in [ord('R'), ord('D')]: + ok = True + break + return ok + + if cp_value == 0x200d: + + if pos > 0: + if _combining_class(ord(label[pos - 1])) == _virama_combining_class: + return True + return False + + else: + + return False + + +def valid_contexto(label, pos, exception=False): + + cp_value = ord(label[pos]) + + if cp_value == 0x00b7: + if 0 < pos < len(label)-1: + if ord(label[pos - 1]) == 0x006c and ord(label[pos + 1]) == 0x006c: + return True + return False + + elif cp_value == 0x0375: + if pos < len(label)-1 and len(label) > 1: + return _is_script(label[pos + 1], 'Greek') + return False + + elif cp_value == 0x05f3 or cp_value == 0x05f4: + if pos > 0: + return _is_script(label[pos - 1], 'Hebrew') + return False + + elif cp_value == 0x30fb: + for cp in label: + if cp == u'\u30fb': + continue + if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'): + return True + return False + + elif 0x660 <= cp_value <= 0x669: + for cp in label: + if 0x6f0 <= ord(cp) <= 0x06f9: + return False + return True + + elif 0x6f0 <= cp_value <= 0x6f9: + for cp in label: + if 0x660 <= ord(cp) <= 0x0669: + return False + return True + + +def check_label(label): + + if isinstance(label, (bytes, bytearray)): + label = label.decode('utf-8') + if len(label) == 0: + raise IDNAError('Empty Label') + + check_nfc(label) + check_hyphen_ok(label) + check_initial_combiner(label) + + for (pos, cp) in enumerate(label): + cp_value = ord(cp) + if intranges_contain(cp_value, idnadata.codepoint_classes['PVALID']): + continue + elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']): + try: + if not valid_contextj(label, pos): + raise InvalidCodepointContext('Joiner {0} not allowed at position {1} in {2}'.format( + _unot(cp_value), pos+1, repr(label))) + except ValueError: + raise IDNAError('Unknown codepoint adjacent to joiner {0} at position {1} in {2}'.format( + _unot(cp_value), pos+1, repr(label))) + elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']): + if not valid_contexto(label, pos): + raise InvalidCodepointContext('Codepoint {0} not allowed at position {1} in {2}'.format(_unot(cp_value), pos+1, repr(label))) + else: + raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label))) + + check_bidi(label) + + +def alabel(label): + + try: + label = label.encode('ascii') + try: + ulabel(label) + except IDNAError: + raise IDNAError('The label {0} is not a valid A-label'.format(label)) + if not valid_label_length(label): + raise IDNAError('Label too long') + return label + except UnicodeEncodeError: + pass + + if not label: + raise IDNAError('No Input') + + label = unicode(label) + check_label(label) + label = _punycode(label) + label = _alabel_prefix + label + + if not valid_label_length(label): + raise IDNAError('Label too long') + + return label + + +def ulabel(label): + + if not isinstance(label, (bytes, bytearray)): + try: + label = label.encode('ascii') + except UnicodeEncodeError: + check_label(label) + return label + + label = label.lower() + if label.startswith(_alabel_prefix): + label = label[len(_alabel_prefix):] + else: + check_label(label) + return label.decode('ascii') + + label = label.decode('punycode') + check_label(label) + return label + + +def uts46_remap(domain, std3_rules=True, transitional=False): + """Re-map the characters in the string according to UTS46 processing.""" + from .uts46data import uts46data + output = u"" + try: + for pos, char in enumerate(domain): + code_point = ord(char) + uts46row = uts46data[code_point if code_point < 256 else + bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + status = uts46row[1] + replacement = uts46row[2] if len(uts46row) == 3 else None + if (status == "V" or + (status == "D" and not transitional) or + (status == "3" and not std3_rules and replacement is None)): + output += char + elif replacement is not None and (status == "M" or + (status == "3" and not std3_rules) or + (status == "D" and transitional)): + output += replacement + elif status != "I": + raise IndexError() + return unicodedata.normalize("NFC", output) + except IndexError: + raise InvalidCodepoint( + "Codepoint {0} not allowed at position {1} in {2}".format( + _unot(code_point), pos + 1, repr(domain))) + + +def encode(s, strict=False, uts46=False, std3_rules=False, transitional=False): + + if isinstance(s, (bytes, bytearray)): + s = s.decode("ascii") + if uts46: + s = uts46_remap(s, std3_rules, transitional) + trailing_dot = False + result = [] + if strict: + labels = s.split('.') + else: + labels = _unicode_dots_re.split(s) + if not labels or labels == ['']: + raise IDNAError('Empty domain') + if labels[-1] == '': + del labels[-1] + trailing_dot = True + for label in labels: + s = alabel(label) + if s: + result.append(s) + else: + raise IDNAError('Empty label') + if trailing_dot: + result.append(b'') + s = b'.'.join(result) + if not valid_string_length(s, trailing_dot): + raise IDNAError('Domain too long') + return s + + +def decode(s, strict=False, uts46=False, std3_rules=False): + + if isinstance(s, (bytes, bytearray)): + s = s.decode("ascii") + if uts46: + s = uts46_remap(s, std3_rules, False) + trailing_dot = False + result = [] + if not strict: + labels = _unicode_dots_re.split(s) + else: + labels = s.split(u'.') + if not labels or labels == ['']: + raise IDNAError('Empty domain') + if not labels[-1]: + del labels[-1] + trailing_dot = True + for label in labels: + s = ulabel(label) + if s: + result.append(s) + else: + raise IDNAError('Empty label') + if trailing_dot: + result.append(u'') + return u'.'.join(result) diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/idnadata.py b/winvenv/Lib/site-packages/pip/_vendor/idna/idnadata.py new file mode 100644 index 0000000..17974e2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/idnadata.py @@ -0,0 +1,1893 @@ +# This file is automatically generated by tools/idna-data + +__version__ = "10.0.0" +scripts = { + 'Greek': ( + 0x37000000374, + 0x37500000378, + 0x37a0000037e, + 0x37f00000380, + 0x38400000385, + 0x38600000387, + 0x3880000038b, + 0x38c0000038d, + 0x38e000003a2, + 0x3a3000003e2, + 0x3f000000400, + 0x1d2600001d2b, + 0x1d5d00001d62, + 0x1d6600001d6b, + 0x1dbf00001dc0, + 0x1f0000001f16, + 0x1f1800001f1e, + 0x1f2000001f46, + 0x1f4800001f4e, + 0x1f5000001f58, + 0x1f5900001f5a, + 0x1f5b00001f5c, + 0x1f5d00001f5e, + 0x1f5f00001f7e, + 0x1f8000001fb5, + 0x1fb600001fc5, + 0x1fc600001fd4, + 0x1fd600001fdc, + 0x1fdd00001ff0, + 0x1ff200001ff5, + 0x1ff600001fff, + 0x212600002127, + 0xab650000ab66, + 0x101400001018f, + 0x101a0000101a1, + 0x1d2000001d246, + ), + 'Han': ( + 0x2e8000002e9a, + 0x2e9b00002ef4, + 0x2f0000002fd6, + 0x300500003006, + 0x300700003008, + 0x30210000302a, + 0x30380000303c, + 0x340000004db6, + 0x4e0000009feb, + 0xf9000000fa6e, + 0xfa700000fada, + 0x200000002a6d7, + 0x2a7000002b735, + 0x2b7400002b81e, + 0x2b8200002cea2, + 0x2ceb00002ebe1, + 0x2f8000002fa1e, + ), + 'Hebrew': ( + 0x591000005c8, + 0x5d0000005eb, + 0x5f0000005f5, + 0xfb1d0000fb37, + 0xfb380000fb3d, + 0xfb3e0000fb3f, + 0xfb400000fb42, + 0xfb430000fb45, + 0xfb460000fb50, + ), + 'Hiragana': ( + 0x304100003097, + 0x309d000030a0, + 0x1b0010001b11f, + 0x1f2000001f201, + ), + 'Katakana': ( + 0x30a1000030fb, + 0x30fd00003100, + 0x31f000003200, + 0x32d0000032ff, + 0x330000003358, + 0xff660000ff70, + 0xff710000ff9e, + 0x1b0000001b001, + ), +} +joining_types = { + 0x600: 85, + 0x601: 85, + 0x602: 85, + 0x603: 85, + 0x604: 85, + 0x605: 85, + 0x608: 85, + 0x60b: 85, + 0x620: 68, + 0x621: 85, + 0x622: 82, + 0x623: 82, + 0x624: 82, + 0x625: 82, + 0x626: 68, + 0x627: 82, + 0x628: 68, + 0x629: 82, + 0x62a: 68, + 0x62b: 68, + 0x62c: 68, + 0x62d: 68, + 0x62e: 68, + 0x62f: 82, + 0x630: 82, + 0x631: 82, + 0x632: 82, + 0x633: 68, + 0x634: 68, + 0x635: 68, + 0x636: 68, + 0x637: 68, + 0x638: 68, + 0x639: 68, + 0x63a: 68, + 0x63b: 68, + 0x63c: 68, + 0x63d: 68, + 0x63e: 68, + 0x63f: 68, + 0x640: 67, + 0x641: 68, + 0x642: 68, + 0x643: 68, + 0x644: 68, + 0x645: 68, + 0x646: 68, + 0x647: 68, + 0x648: 82, + 0x649: 68, + 0x64a: 68, + 0x66e: 68, + 0x66f: 68, + 0x671: 82, + 0x672: 82, + 0x673: 82, + 0x674: 85, + 0x675: 82, + 0x676: 82, + 0x677: 82, + 0x678: 68, + 0x679: 68, + 0x67a: 68, + 0x67b: 68, + 0x67c: 68, + 0x67d: 68, + 0x67e: 68, + 0x67f: 68, + 0x680: 68, + 0x681: 68, + 0x682: 68, + 0x683: 68, + 0x684: 68, + 0x685: 68, + 0x686: 68, + 0x687: 68, + 0x688: 82, + 0x689: 82, + 0x68a: 82, + 0x68b: 82, + 0x68c: 82, + 0x68d: 82, + 0x68e: 82, + 0x68f: 82, + 0x690: 82, + 0x691: 82, + 0x692: 82, + 0x693: 82, + 0x694: 82, + 0x695: 82, + 0x696: 82, + 0x697: 82, + 0x698: 82, + 0x699: 82, + 0x69a: 68, + 0x69b: 68, + 0x69c: 68, + 0x69d: 68, + 0x69e: 68, + 0x69f: 68, + 0x6a0: 68, + 0x6a1: 68, + 0x6a2: 68, + 0x6a3: 68, + 0x6a4: 68, + 0x6a5: 68, + 0x6a6: 68, + 0x6a7: 68, + 0x6a8: 68, + 0x6a9: 68, + 0x6aa: 68, + 0x6ab: 68, + 0x6ac: 68, + 0x6ad: 68, + 0x6ae: 68, + 0x6af: 68, + 0x6b0: 68, + 0x6b1: 68, + 0x6b2: 68, + 0x6b3: 68, + 0x6b4: 68, + 0x6b5: 68, + 0x6b6: 68, + 0x6b7: 68, + 0x6b8: 68, + 0x6b9: 68, + 0x6ba: 68, + 0x6bb: 68, + 0x6bc: 68, + 0x6bd: 68, + 0x6be: 68, + 0x6bf: 68, + 0x6c0: 82, + 0x6c1: 68, + 0x6c2: 68, + 0x6c3: 82, + 0x6c4: 82, + 0x6c5: 82, + 0x6c6: 82, + 0x6c7: 82, + 0x6c8: 82, + 0x6c9: 82, + 0x6ca: 82, + 0x6cb: 82, + 0x6cc: 68, + 0x6cd: 82, + 0x6ce: 68, + 0x6cf: 82, + 0x6d0: 68, + 0x6d1: 68, + 0x6d2: 82, + 0x6d3: 82, + 0x6d5: 82, + 0x6dd: 85, + 0x6ee: 82, + 0x6ef: 82, + 0x6fa: 68, + 0x6fb: 68, + 0x6fc: 68, + 0x6ff: 68, + 0x710: 82, + 0x712: 68, + 0x713: 68, + 0x714: 68, + 0x715: 82, + 0x716: 82, + 0x717: 82, + 0x718: 82, + 0x719: 82, + 0x71a: 68, + 0x71b: 68, + 0x71c: 68, + 0x71d: 68, + 0x71e: 82, + 0x71f: 68, + 0x720: 68, + 0x721: 68, + 0x722: 68, + 0x723: 68, + 0x724: 68, + 0x725: 68, + 0x726: 68, + 0x727: 68, + 0x728: 82, + 0x729: 68, + 0x72a: 82, + 0x72b: 68, + 0x72c: 82, + 0x72d: 68, + 0x72e: 68, + 0x72f: 82, + 0x74d: 82, + 0x74e: 68, + 0x74f: 68, + 0x750: 68, + 0x751: 68, + 0x752: 68, + 0x753: 68, + 0x754: 68, + 0x755: 68, + 0x756: 68, + 0x757: 68, + 0x758: 68, + 0x759: 82, + 0x75a: 82, + 0x75b: 82, + 0x75c: 68, + 0x75d: 68, + 0x75e: 68, + 0x75f: 68, + 0x760: 68, + 0x761: 68, + 0x762: 68, + 0x763: 68, + 0x764: 68, + 0x765: 68, + 0x766: 68, + 0x767: 68, + 0x768: 68, + 0x769: 68, + 0x76a: 68, + 0x76b: 82, + 0x76c: 82, + 0x76d: 68, + 0x76e: 68, + 0x76f: 68, + 0x770: 68, + 0x771: 82, + 0x772: 68, + 0x773: 82, + 0x774: 82, + 0x775: 68, + 0x776: 68, + 0x777: 68, + 0x778: 82, + 0x779: 82, + 0x77a: 68, + 0x77b: 68, + 0x77c: 68, + 0x77d: 68, + 0x77e: 68, + 0x77f: 68, + 0x7ca: 68, + 0x7cb: 68, + 0x7cc: 68, + 0x7cd: 68, + 0x7ce: 68, + 0x7cf: 68, + 0x7d0: 68, + 0x7d1: 68, + 0x7d2: 68, + 0x7d3: 68, + 0x7d4: 68, + 0x7d5: 68, + 0x7d6: 68, + 0x7d7: 68, + 0x7d8: 68, + 0x7d9: 68, + 0x7da: 68, + 0x7db: 68, + 0x7dc: 68, + 0x7dd: 68, + 0x7de: 68, + 0x7df: 68, + 0x7e0: 68, + 0x7e1: 68, + 0x7e2: 68, + 0x7e3: 68, + 0x7e4: 68, + 0x7e5: 68, + 0x7e6: 68, + 0x7e7: 68, + 0x7e8: 68, + 0x7e9: 68, + 0x7ea: 68, + 0x7fa: 67, + 0x840: 82, + 0x841: 68, + 0x842: 68, + 0x843: 68, + 0x844: 68, + 0x845: 68, + 0x846: 82, + 0x847: 82, + 0x848: 68, + 0x849: 82, + 0x84a: 68, + 0x84b: 68, + 0x84c: 68, + 0x84d: 68, + 0x84e: 68, + 0x84f: 68, + 0x850: 68, + 0x851: 68, + 0x852: 68, + 0x853: 68, + 0x854: 82, + 0x855: 68, + 0x856: 85, + 0x857: 85, + 0x858: 85, + 0x860: 68, + 0x861: 85, + 0x862: 68, + 0x863: 68, + 0x864: 68, + 0x865: 68, + 0x866: 85, + 0x867: 82, + 0x868: 68, + 0x869: 82, + 0x86a: 82, + 0x8a0: 68, + 0x8a1: 68, + 0x8a2: 68, + 0x8a3: 68, + 0x8a4: 68, + 0x8a5: 68, + 0x8a6: 68, + 0x8a7: 68, + 0x8a8: 68, + 0x8a9: 68, + 0x8aa: 82, + 0x8ab: 82, + 0x8ac: 82, + 0x8ad: 85, + 0x8ae: 82, + 0x8af: 68, + 0x8b0: 68, + 0x8b1: 82, + 0x8b2: 82, + 0x8b3: 68, + 0x8b4: 68, + 0x8b6: 68, + 0x8b7: 68, + 0x8b8: 68, + 0x8b9: 82, + 0x8ba: 68, + 0x8bb: 68, + 0x8bc: 68, + 0x8bd: 68, + 0x8e2: 85, + 0x1806: 85, + 0x1807: 68, + 0x180a: 67, + 0x180e: 85, + 0x1820: 68, + 0x1821: 68, + 0x1822: 68, + 0x1823: 68, + 0x1824: 68, + 0x1825: 68, + 0x1826: 68, + 0x1827: 68, + 0x1828: 68, + 0x1829: 68, + 0x182a: 68, + 0x182b: 68, + 0x182c: 68, + 0x182d: 68, + 0x182e: 68, + 0x182f: 68, + 0x1830: 68, + 0x1831: 68, + 0x1832: 68, + 0x1833: 68, + 0x1834: 68, + 0x1835: 68, + 0x1836: 68, + 0x1837: 68, + 0x1838: 68, + 0x1839: 68, + 0x183a: 68, + 0x183b: 68, + 0x183c: 68, + 0x183d: 68, + 0x183e: 68, + 0x183f: 68, + 0x1840: 68, + 0x1841: 68, + 0x1842: 68, + 0x1843: 68, + 0x1844: 68, + 0x1845: 68, + 0x1846: 68, + 0x1847: 68, + 0x1848: 68, + 0x1849: 68, + 0x184a: 68, + 0x184b: 68, + 0x184c: 68, + 0x184d: 68, + 0x184e: 68, + 0x184f: 68, + 0x1850: 68, + 0x1851: 68, + 0x1852: 68, + 0x1853: 68, + 0x1854: 68, + 0x1855: 68, + 0x1856: 68, + 0x1857: 68, + 0x1858: 68, + 0x1859: 68, + 0x185a: 68, + 0x185b: 68, + 0x185c: 68, + 0x185d: 68, + 0x185e: 68, + 0x185f: 68, + 0x1860: 68, + 0x1861: 68, + 0x1862: 68, + 0x1863: 68, + 0x1864: 68, + 0x1865: 68, + 0x1866: 68, + 0x1867: 68, + 0x1868: 68, + 0x1869: 68, + 0x186a: 68, + 0x186b: 68, + 0x186c: 68, + 0x186d: 68, + 0x186e: 68, + 0x186f: 68, + 0x1870: 68, + 0x1871: 68, + 0x1872: 68, + 0x1873: 68, + 0x1874: 68, + 0x1875: 68, + 0x1876: 68, + 0x1877: 68, + 0x1880: 85, + 0x1881: 85, + 0x1882: 85, + 0x1883: 85, + 0x1884: 85, + 0x1885: 84, + 0x1886: 84, + 0x1887: 68, + 0x1888: 68, + 0x1889: 68, + 0x188a: 68, + 0x188b: 68, + 0x188c: 68, + 0x188d: 68, + 0x188e: 68, + 0x188f: 68, + 0x1890: 68, + 0x1891: 68, + 0x1892: 68, + 0x1893: 68, + 0x1894: 68, + 0x1895: 68, + 0x1896: 68, + 0x1897: 68, + 0x1898: 68, + 0x1899: 68, + 0x189a: 68, + 0x189b: 68, + 0x189c: 68, + 0x189d: 68, + 0x189e: 68, + 0x189f: 68, + 0x18a0: 68, + 0x18a1: 68, + 0x18a2: 68, + 0x18a3: 68, + 0x18a4: 68, + 0x18a5: 68, + 0x18a6: 68, + 0x18a7: 68, + 0x18a8: 68, + 0x18aa: 68, + 0x200c: 85, + 0x200d: 67, + 0x202f: 85, + 0x2066: 85, + 0x2067: 85, + 0x2068: 85, + 0x2069: 85, + 0xa840: 68, + 0xa841: 68, + 0xa842: 68, + 0xa843: 68, + 0xa844: 68, + 0xa845: 68, + 0xa846: 68, + 0xa847: 68, + 0xa848: 68, + 0xa849: 68, + 0xa84a: 68, + 0xa84b: 68, + 0xa84c: 68, + 0xa84d: 68, + 0xa84e: 68, + 0xa84f: 68, + 0xa850: 68, + 0xa851: 68, + 0xa852: 68, + 0xa853: 68, + 0xa854: 68, + 0xa855: 68, + 0xa856: 68, + 0xa857: 68, + 0xa858: 68, + 0xa859: 68, + 0xa85a: 68, + 0xa85b: 68, + 0xa85c: 68, + 0xa85d: 68, + 0xa85e: 68, + 0xa85f: 68, + 0xa860: 68, + 0xa861: 68, + 0xa862: 68, + 0xa863: 68, + 0xa864: 68, + 0xa865: 68, + 0xa866: 68, + 0xa867: 68, + 0xa868: 68, + 0xa869: 68, + 0xa86a: 68, + 0xa86b: 68, + 0xa86c: 68, + 0xa86d: 68, + 0xa86e: 68, + 0xa86f: 68, + 0xa870: 68, + 0xa871: 68, + 0xa872: 76, + 0xa873: 85, + 0x10ac0: 68, + 0x10ac1: 68, + 0x10ac2: 68, + 0x10ac3: 68, + 0x10ac4: 68, + 0x10ac5: 82, + 0x10ac6: 85, + 0x10ac7: 82, + 0x10ac8: 85, + 0x10ac9: 82, + 0x10aca: 82, + 0x10acb: 85, + 0x10acc: 85, + 0x10acd: 76, + 0x10ace: 82, + 0x10acf: 82, + 0x10ad0: 82, + 0x10ad1: 82, + 0x10ad2: 82, + 0x10ad3: 68, + 0x10ad4: 68, + 0x10ad5: 68, + 0x10ad6: 68, + 0x10ad7: 76, + 0x10ad8: 68, + 0x10ad9: 68, + 0x10ada: 68, + 0x10adb: 68, + 0x10adc: 68, + 0x10add: 82, + 0x10ade: 68, + 0x10adf: 68, + 0x10ae0: 68, + 0x10ae1: 82, + 0x10ae2: 85, + 0x10ae3: 85, + 0x10ae4: 82, + 0x10aeb: 68, + 0x10aec: 68, + 0x10aed: 68, + 0x10aee: 68, + 0x10aef: 82, + 0x10b80: 68, + 0x10b81: 82, + 0x10b82: 68, + 0x10b83: 82, + 0x10b84: 82, + 0x10b85: 82, + 0x10b86: 68, + 0x10b87: 68, + 0x10b88: 68, + 0x10b89: 82, + 0x10b8a: 68, + 0x10b8b: 68, + 0x10b8c: 82, + 0x10b8d: 68, + 0x10b8e: 82, + 0x10b8f: 82, + 0x10b90: 68, + 0x10b91: 82, + 0x10ba9: 82, + 0x10baa: 82, + 0x10bab: 82, + 0x10bac: 82, + 0x10bad: 68, + 0x10bae: 68, + 0x10baf: 85, + 0x1e900: 68, + 0x1e901: 68, + 0x1e902: 68, + 0x1e903: 68, + 0x1e904: 68, + 0x1e905: 68, + 0x1e906: 68, + 0x1e907: 68, + 0x1e908: 68, + 0x1e909: 68, + 0x1e90a: 68, + 0x1e90b: 68, + 0x1e90c: 68, + 0x1e90d: 68, + 0x1e90e: 68, + 0x1e90f: 68, + 0x1e910: 68, + 0x1e911: 68, + 0x1e912: 68, + 0x1e913: 68, + 0x1e914: 68, + 0x1e915: 68, + 0x1e916: 68, + 0x1e917: 68, + 0x1e918: 68, + 0x1e919: 68, + 0x1e91a: 68, + 0x1e91b: 68, + 0x1e91c: 68, + 0x1e91d: 68, + 0x1e91e: 68, + 0x1e91f: 68, + 0x1e920: 68, + 0x1e921: 68, + 0x1e922: 68, + 0x1e923: 68, + 0x1e924: 68, + 0x1e925: 68, + 0x1e926: 68, + 0x1e927: 68, + 0x1e928: 68, + 0x1e929: 68, + 0x1e92a: 68, + 0x1e92b: 68, + 0x1e92c: 68, + 0x1e92d: 68, + 0x1e92e: 68, + 0x1e92f: 68, + 0x1e930: 68, + 0x1e931: 68, + 0x1e932: 68, + 0x1e933: 68, + 0x1e934: 68, + 0x1e935: 68, + 0x1e936: 68, + 0x1e937: 68, + 0x1e938: 68, + 0x1e939: 68, + 0x1e93a: 68, + 0x1e93b: 68, + 0x1e93c: 68, + 0x1e93d: 68, + 0x1e93e: 68, + 0x1e93f: 68, + 0x1e940: 68, + 0x1e941: 68, + 0x1e942: 68, + 0x1e943: 68, +} +codepoint_classes = { + 'PVALID': ( + 0x2d0000002e, + 0x300000003a, + 0x610000007b, + 0xdf000000f7, + 0xf800000100, + 0x10100000102, + 0x10300000104, + 0x10500000106, + 0x10700000108, + 0x1090000010a, + 0x10b0000010c, + 0x10d0000010e, + 0x10f00000110, + 0x11100000112, + 0x11300000114, + 0x11500000116, + 0x11700000118, + 0x1190000011a, + 0x11b0000011c, + 0x11d0000011e, + 0x11f00000120, + 0x12100000122, + 0x12300000124, + 0x12500000126, + 0x12700000128, + 0x1290000012a, + 0x12b0000012c, + 0x12d0000012e, + 0x12f00000130, + 0x13100000132, + 0x13500000136, + 0x13700000139, + 0x13a0000013b, + 0x13c0000013d, + 0x13e0000013f, + 0x14200000143, + 0x14400000145, + 0x14600000147, + 0x14800000149, + 0x14b0000014c, + 0x14d0000014e, + 0x14f00000150, + 0x15100000152, + 0x15300000154, + 0x15500000156, + 0x15700000158, + 0x1590000015a, + 0x15b0000015c, + 0x15d0000015e, + 0x15f00000160, + 0x16100000162, + 0x16300000164, + 0x16500000166, + 0x16700000168, + 0x1690000016a, + 0x16b0000016c, + 0x16d0000016e, + 0x16f00000170, + 0x17100000172, + 0x17300000174, + 0x17500000176, + 0x17700000178, + 0x17a0000017b, + 0x17c0000017d, + 0x17e0000017f, + 0x18000000181, + 0x18300000184, + 0x18500000186, + 0x18800000189, + 0x18c0000018e, + 0x19200000193, + 0x19500000196, + 0x1990000019c, + 0x19e0000019f, + 0x1a1000001a2, + 0x1a3000001a4, + 0x1a5000001a6, + 0x1a8000001a9, + 0x1aa000001ac, + 0x1ad000001ae, + 0x1b0000001b1, + 0x1b4000001b5, + 0x1b6000001b7, + 0x1b9000001bc, + 0x1bd000001c4, + 0x1ce000001cf, + 0x1d0000001d1, + 0x1d2000001d3, + 0x1d4000001d5, + 0x1d6000001d7, + 0x1d8000001d9, + 0x1da000001db, + 0x1dc000001de, + 0x1df000001e0, + 0x1e1000001e2, + 0x1e3000001e4, + 0x1e5000001e6, + 0x1e7000001e8, + 0x1e9000001ea, + 0x1eb000001ec, + 0x1ed000001ee, + 0x1ef000001f1, + 0x1f5000001f6, + 0x1f9000001fa, + 0x1fb000001fc, + 0x1fd000001fe, + 0x1ff00000200, + 0x20100000202, + 0x20300000204, + 0x20500000206, + 0x20700000208, + 0x2090000020a, + 0x20b0000020c, + 0x20d0000020e, + 0x20f00000210, + 0x21100000212, + 0x21300000214, + 0x21500000216, + 0x21700000218, + 0x2190000021a, + 0x21b0000021c, + 0x21d0000021e, + 0x21f00000220, + 0x22100000222, + 0x22300000224, + 0x22500000226, + 0x22700000228, + 0x2290000022a, + 0x22b0000022c, + 0x22d0000022e, + 0x22f00000230, + 0x23100000232, + 0x2330000023a, + 0x23c0000023d, + 0x23f00000241, + 0x24200000243, + 0x24700000248, + 0x2490000024a, + 0x24b0000024c, + 0x24d0000024e, + 0x24f000002b0, + 0x2b9000002c2, + 0x2c6000002d2, + 0x2ec000002ed, + 0x2ee000002ef, + 0x30000000340, + 0x34200000343, + 0x3460000034f, + 0x35000000370, + 0x37100000372, + 0x37300000374, + 0x37700000378, + 0x37b0000037e, + 0x39000000391, + 0x3ac000003cf, + 0x3d7000003d8, + 0x3d9000003da, + 0x3db000003dc, + 0x3dd000003de, + 0x3df000003e0, + 0x3e1000003e2, + 0x3e3000003e4, + 0x3e5000003e6, + 0x3e7000003e8, + 0x3e9000003ea, + 0x3eb000003ec, + 0x3ed000003ee, + 0x3ef000003f0, + 0x3f3000003f4, + 0x3f8000003f9, + 0x3fb000003fd, + 0x43000000460, + 0x46100000462, + 0x46300000464, + 0x46500000466, + 0x46700000468, + 0x4690000046a, + 0x46b0000046c, + 0x46d0000046e, + 0x46f00000470, + 0x47100000472, + 0x47300000474, + 0x47500000476, + 0x47700000478, + 0x4790000047a, + 0x47b0000047c, + 0x47d0000047e, + 0x47f00000480, + 0x48100000482, + 0x48300000488, + 0x48b0000048c, + 0x48d0000048e, + 0x48f00000490, + 0x49100000492, + 0x49300000494, + 0x49500000496, + 0x49700000498, + 0x4990000049a, + 0x49b0000049c, + 0x49d0000049e, + 0x49f000004a0, + 0x4a1000004a2, + 0x4a3000004a4, + 0x4a5000004a6, + 0x4a7000004a8, + 0x4a9000004aa, + 0x4ab000004ac, + 0x4ad000004ae, + 0x4af000004b0, + 0x4b1000004b2, + 0x4b3000004b4, + 0x4b5000004b6, + 0x4b7000004b8, + 0x4b9000004ba, + 0x4bb000004bc, + 0x4bd000004be, + 0x4bf000004c0, + 0x4c2000004c3, + 0x4c4000004c5, + 0x4c6000004c7, + 0x4c8000004c9, + 0x4ca000004cb, + 0x4cc000004cd, + 0x4ce000004d0, + 0x4d1000004d2, + 0x4d3000004d4, + 0x4d5000004d6, + 0x4d7000004d8, + 0x4d9000004da, + 0x4db000004dc, + 0x4dd000004de, + 0x4df000004e0, + 0x4e1000004e2, + 0x4e3000004e4, + 0x4e5000004e6, + 0x4e7000004e8, + 0x4e9000004ea, + 0x4eb000004ec, + 0x4ed000004ee, + 0x4ef000004f0, + 0x4f1000004f2, + 0x4f3000004f4, + 0x4f5000004f6, + 0x4f7000004f8, + 0x4f9000004fa, + 0x4fb000004fc, + 0x4fd000004fe, + 0x4ff00000500, + 0x50100000502, + 0x50300000504, + 0x50500000506, + 0x50700000508, + 0x5090000050a, + 0x50b0000050c, + 0x50d0000050e, + 0x50f00000510, + 0x51100000512, + 0x51300000514, + 0x51500000516, + 0x51700000518, + 0x5190000051a, + 0x51b0000051c, + 0x51d0000051e, + 0x51f00000520, + 0x52100000522, + 0x52300000524, + 0x52500000526, + 0x52700000528, + 0x5290000052a, + 0x52b0000052c, + 0x52d0000052e, + 0x52f00000530, + 0x5590000055a, + 0x56100000587, + 0x591000005be, + 0x5bf000005c0, + 0x5c1000005c3, + 0x5c4000005c6, + 0x5c7000005c8, + 0x5d0000005eb, + 0x5f0000005f3, + 0x6100000061b, + 0x62000000640, + 0x64100000660, + 0x66e00000675, + 0x679000006d4, + 0x6d5000006dd, + 0x6df000006e9, + 0x6ea000006f0, + 0x6fa00000700, + 0x7100000074b, + 0x74d000007b2, + 0x7c0000007f6, + 0x8000000082e, + 0x8400000085c, + 0x8600000086b, + 0x8a0000008b5, + 0x8b6000008be, + 0x8d4000008e2, + 0x8e300000958, + 0x96000000964, + 0x96600000970, + 0x97100000984, + 0x9850000098d, + 0x98f00000991, + 0x993000009a9, + 0x9aa000009b1, + 0x9b2000009b3, + 0x9b6000009ba, + 0x9bc000009c5, + 0x9c7000009c9, + 0x9cb000009cf, + 0x9d7000009d8, + 0x9e0000009e4, + 0x9e6000009f2, + 0x9fc000009fd, + 0xa0100000a04, + 0xa0500000a0b, + 0xa0f00000a11, + 0xa1300000a29, + 0xa2a00000a31, + 0xa3200000a33, + 0xa3500000a36, + 0xa3800000a3a, + 0xa3c00000a3d, + 0xa3e00000a43, + 0xa4700000a49, + 0xa4b00000a4e, + 0xa5100000a52, + 0xa5c00000a5d, + 0xa6600000a76, + 0xa8100000a84, + 0xa8500000a8e, + 0xa8f00000a92, + 0xa9300000aa9, + 0xaaa00000ab1, + 0xab200000ab4, + 0xab500000aba, + 0xabc00000ac6, + 0xac700000aca, + 0xacb00000ace, + 0xad000000ad1, + 0xae000000ae4, + 0xae600000af0, + 0xaf900000b00, + 0xb0100000b04, + 0xb0500000b0d, + 0xb0f00000b11, + 0xb1300000b29, + 0xb2a00000b31, + 0xb3200000b34, + 0xb3500000b3a, + 0xb3c00000b45, + 0xb4700000b49, + 0xb4b00000b4e, + 0xb5600000b58, + 0xb5f00000b64, + 0xb6600000b70, + 0xb7100000b72, + 0xb8200000b84, + 0xb8500000b8b, + 0xb8e00000b91, + 0xb9200000b96, + 0xb9900000b9b, + 0xb9c00000b9d, + 0xb9e00000ba0, + 0xba300000ba5, + 0xba800000bab, + 0xbae00000bba, + 0xbbe00000bc3, + 0xbc600000bc9, + 0xbca00000bce, + 0xbd000000bd1, + 0xbd700000bd8, + 0xbe600000bf0, + 0xc0000000c04, + 0xc0500000c0d, + 0xc0e00000c11, + 0xc1200000c29, + 0xc2a00000c3a, + 0xc3d00000c45, + 0xc4600000c49, + 0xc4a00000c4e, + 0xc5500000c57, + 0xc5800000c5b, + 0xc6000000c64, + 0xc6600000c70, + 0xc8000000c84, + 0xc8500000c8d, + 0xc8e00000c91, + 0xc9200000ca9, + 0xcaa00000cb4, + 0xcb500000cba, + 0xcbc00000cc5, + 0xcc600000cc9, + 0xcca00000cce, + 0xcd500000cd7, + 0xcde00000cdf, + 0xce000000ce4, + 0xce600000cf0, + 0xcf100000cf3, + 0xd0000000d04, + 0xd0500000d0d, + 0xd0e00000d11, + 0xd1200000d45, + 0xd4600000d49, + 0xd4a00000d4f, + 0xd5400000d58, + 0xd5f00000d64, + 0xd6600000d70, + 0xd7a00000d80, + 0xd8200000d84, + 0xd8500000d97, + 0xd9a00000db2, + 0xdb300000dbc, + 0xdbd00000dbe, + 0xdc000000dc7, + 0xdca00000dcb, + 0xdcf00000dd5, + 0xdd600000dd7, + 0xdd800000de0, + 0xde600000df0, + 0xdf200000df4, + 0xe0100000e33, + 0xe3400000e3b, + 0xe4000000e4f, + 0xe5000000e5a, + 0xe8100000e83, + 0xe8400000e85, + 0xe8700000e89, + 0xe8a00000e8b, + 0xe8d00000e8e, + 0xe9400000e98, + 0xe9900000ea0, + 0xea100000ea4, + 0xea500000ea6, + 0xea700000ea8, + 0xeaa00000eac, + 0xead00000eb3, + 0xeb400000eba, + 0xebb00000ebe, + 0xec000000ec5, + 0xec600000ec7, + 0xec800000ece, + 0xed000000eda, + 0xede00000ee0, + 0xf0000000f01, + 0xf0b00000f0c, + 0xf1800000f1a, + 0xf2000000f2a, + 0xf3500000f36, + 0xf3700000f38, + 0xf3900000f3a, + 0xf3e00000f43, + 0xf4400000f48, + 0xf4900000f4d, + 0xf4e00000f52, + 0xf5300000f57, + 0xf5800000f5c, + 0xf5d00000f69, + 0xf6a00000f6d, + 0xf7100000f73, + 0xf7400000f75, + 0xf7a00000f81, + 0xf8200000f85, + 0xf8600000f93, + 0xf9400000f98, + 0xf9900000f9d, + 0xf9e00000fa2, + 0xfa300000fa7, + 0xfa800000fac, + 0xfad00000fb9, + 0xfba00000fbd, + 0xfc600000fc7, + 0x10000000104a, + 0x10500000109e, + 0x10d0000010fb, + 0x10fd00001100, + 0x120000001249, + 0x124a0000124e, + 0x125000001257, + 0x125800001259, + 0x125a0000125e, + 0x126000001289, + 0x128a0000128e, + 0x1290000012b1, + 0x12b2000012b6, + 0x12b8000012bf, + 0x12c0000012c1, + 0x12c2000012c6, + 0x12c8000012d7, + 0x12d800001311, + 0x131200001316, + 0x13180000135b, + 0x135d00001360, + 0x138000001390, + 0x13a0000013f6, + 0x14010000166d, + 0x166f00001680, + 0x16810000169b, + 0x16a0000016eb, + 0x16f1000016f9, + 0x17000000170d, + 0x170e00001715, + 0x172000001735, + 0x174000001754, + 0x17600000176d, + 0x176e00001771, + 0x177200001774, + 0x1780000017b4, + 0x17b6000017d4, + 0x17d7000017d8, + 0x17dc000017de, + 0x17e0000017ea, + 0x18100000181a, + 0x182000001878, + 0x1880000018ab, + 0x18b0000018f6, + 0x19000000191f, + 0x19200000192c, + 0x19300000193c, + 0x19460000196e, + 0x197000001975, + 0x1980000019ac, + 0x19b0000019ca, + 0x19d0000019da, + 0x1a0000001a1c, + 0x1a2000001a5f, + 0x1a6000001a7d, + 0x1a7f00001a8a, + 0x1a9000001a9a, + 0x1aa700001aa8, + 0x1ab000001abe, + 0x1b0000001b4c, + 0x1b5000001b5a, + 0x1b6b00001b74, + 0x1b8000001bf4, + 0x1c0000001c38, + 0x1c4000001c4a, + 0x1c4d00001c7e, + 0x1cd000001cd3, + 0x1cd400001cfa, + 0x1d0000001d2c, + 0x1d2f00001d30, + 0x1d3b00001d3c, + 0x1d4e00001d4f, + 0x1d6b00001d78, + 0x1d7900001d9b, + 0x1dc000001dfa, + 0x1dfb00001e00, + 0x1e0100001e02, + 0x1e0300001e04, + 0x1e0500001e06, + 0x1e0700001e08, + 0x1e0900001e0a, + 0x1e0b00001e0c, + 0x1e0d00001e0e, + 0x1e0f00001e10, + 0x1e1100001e12, + 0x1e1300001e14, + 0x1e1500001e16, + 0x1e1700001e18, + 0x1e1900001e1a, + 0x1e1b00001e1c, + 0x1e1d00001e1e, + 0x1e1f00001e20, + 0x1e2100001e22, + 0x1e2300001e24, + 0x1e2500001e26, + 0x1e2700001e28, + 0x1e2900001e2a, + 0x1e2b00001e2c, + 0x1e2d00001e2e, + 0x1e2f00001e30, + 0x1e3100001e32, + 0x1e3300001e34, + 0x1e3500001e36, + 0x1e3700001e38, + 0x1e3900001e3a, + 0x1e3b00001e3c, + 0x1e3d00001e3e, + 0x1e3f00001e40, + 0x1e4100001e42, + 0x1e4300001e44, + 0x1e4500001e46, + 0x1e4700001e48, + 0x1e4900001e4a, + 0x1e4b00001e4c, + 0x1e4d00001e4e, + 0x1e4f00001e50, + 0x1e5100001e52, + 0x1e5300001e54, + 0x1e5500001e56, + 0x1e5700001e58, + 0x1e5900001e5a, + 0x1e5b00001e5c, + 0x1e5d00001e5e, + 0x1e5f00001e60, + 0x1e6100001e62, + 0x1e6300001e64, + 0x1e6500001e66, + 0x1e6700001e68, + 0x1e6900001e6a, + 0x1e6b00001e6c, + 0x1e6d00001e6e, + 0x1e6f00001e70, + 0x1e7100001e72, + 0x1e7300001e74, + 0x1e7500001e76, + 0x1e7700001e78, + 0x1e7900001e7a, + 0x1e7b00001e7c, + 0x1e7d00001e7e, + 0x1e7f00001e80, + 0x1e8100001e82, + 0x1e8300001e84, + 0x1e8500001e86, + 0x1e8700001e88, + 0x1e8900001e8a, + 0x1e8b00001e8c, + 0x1e8d00001e8e, + 0x1e8f00001e90, + 0x1e9100001e92, + 0x1e9300001e94, + 0x1e9500001e9a, + 0x1e9c00001e9e, + 0x1e9f00001ea0, + 0x1ea100001ea2, + 0x1ea300001ea4, + 0x1ea500001ea6, + 0x1ea700001ea8, + 0x1ea900001eaa, + 0x1eab00001eac, + 0x1ead00001eae, + 0x1eaf00001eb0, + 0x1eb100001eb2, + 0x1eb300001eb4, + 0x1eb500001eb6, + 0x1eb700001eb8, + 0x1eb900001eba, + 0x1ebb00001ebc, + 0x1ebd00001ebe, + 0x1ebf00001ec0, + 0x1ec100001ec2, + 0x1ec300001ec4, + 0x1ec500001ec6, + 0x1ec700001ec8, + 0x1ec900001eca, + 0x1ecb00001ecc, + 0x1ecd00001ece, + 0x1ecf00001ed0, + 0x1ed100001ed2, + 0x1ed300001ed4, + 0x1ed500001ed6, + 0x1ed700001ed8, + 0x1ed900001eda, + 0x1edb00001edc, + 0x1edd00001ede, + 0x1edf00001ee0, + 0x1ee100001ee2, + 0x1ee300001ee4, + 0x1ee500001ee6, + 0x1ee700001ee8, + 0x1ee900001eea, + 0x1eeb00001eec, + 0x1eed00001eee, + 0x1eef00001ef0, + 0x1ef100001ef2, + 0x1ef300001ef4, + 0x1ef500001ef6, + 0x1ef700001ef8, + 0x1ef900001efa, + 0x1efb00001efc, + 0x1efd00001efe, + 0x1eff00001f08, + 0x1f1000001f16, + 0x1f2000001f28, + 0x1f3000001f38, + 0x1f4000001f46, + 0x1f5000001f58, + 0x1f6000001f68, + 0x1f7000001f71, + 0x1f7200001f73, + 0x1f7400001f75, + 0x1f7600001f77, + 0x1f7800001f79, + 0x1f7a00001f7b, + 0x1f7c00001f7d, + 0x1fb000001fb2, + 0x1fb600001fb7, + 0x1fc600001fc7, + 0x1fd000001fd3, + 0x1fd600001fd8, + 0x1fe000001fe3, + 0x1fe400001fe8, + 0x1ff600001ff7, + 0x214e0000214f, + 0x218400002185, + 0x2c3000002c5f, + 0x2c6100002c62, + 0x2c6500002c67, + 0x2c6800002c69, + 0x2c6a00002c6b, + 0x2c6c00002c6d, + 0x2c7100002c72, + 0x2c7300002c75, + 0x2c7600002c7c, + 0x2c8100002c82, + 0x2c8300002c84, + 0x2c8500002c86, + 0x2c8700002c88, + 0x2c8900002c8a, + 0x2c8b00002c8c, + 0x2c8d00002c8e, + 0x2c8f00002c90, + 0x2c9100002c92, + 0x2c9300002c94, + 0x2c9500002c96, + 0x2c9700002c98, + 0x2c9900002c9a, + 0x2c9b00002c9c, + 0x2c9d00002c9e, + 0x2c9f00002ca0, + 0x2ca100002ca2, + 0x2ca300002ca4, + 0x2ca500002ca6, + 0x2ca700002ca8, + 0x2ca900002caa, + 0x2cab00002cac, + 0x2cad00002cae, + 0x2caf00002cb0, + 0x2cb100002cb2, + 0x2cb300002cb4, + 0x2cb500002cb6, + 0x2cb700002cb8, + 0x2cb900002cba, + 0x2cbb00002cbc, + 0x2cbd00002cbe, + 0x2cbf00002cc0, + 0x2cc100002cc2, + 0x2cc300002cc4, + 0x2cc500002cc6, + 0x2cc700002cc8, + 0x2cc900002cca, + 0x2ccb00002ccc, + 0x2ccd00002cce, + 0x2ccf00002cd0, + 0x2cd100002cd2, + 0x2cd300002cd4, + 0x2cd500002cd6, + 0x2cd700002cd8, + 0x2cd900002cda, + 0x2cdb00002cdc, + 0x2cdd00002cde, + 0x2cdf00002ce0, + 0x2ce100002ce2, + 0x2ce300002ce5, + 0x2cec00002ced, + 0x2cee00002cf2, + 0x2cf300002cf4, + 0x2d0000002d26, + 0x2d2700002d28, + 0x2d2d00002d2e, + 0x2d3000002d68, + 0x2d7f00002d97, + 0x2da000002da7, + 0x2da800002daf, + 0x2db000002db7, + 0x2db800002dbf, + 0x2dc000002dc7, + 0x2dc800002dcf, + 0x2dd000002dd7, + 0x2dd800002ddf, + 0x2de000002e00, + 0x2e2f00002e30, + 0x300500003008, + 0x302a0000302e, + 0x303c0000303d, + 0x304100003097, + 0x30990000309b, + 0x309d0000309f, + 0x30a1000030fb, + 0x30fc000030ff, + 0x31050000312f, + 0x31a0000031bb, + 0x31f000003200, + 0x340000004db6, + 0x4e0000009feb, + 0xa0000000a48d, + 0xa4d00000a4fe, + 0xa5000000a60d, + 0xa6100000a62c, + 0xa6410000a642, + 0xa6430000a644, + 0xa6450000a646, + 0xa6470000a648, + 0xa6490000a64a, + 0xa64b0000a64c, + 0xa64d0000a64e, + 0xa64f0000a650, + 0xa6510000a652, + 0xa6530000a654, + 0xa6550000a656, + 0xa6570000a658, + 0xa6590000a65a, + 0xa65b0000a65c, + 0xa65d0000a65e, + 0xa65f0000a660, + 0xa6610000a662, + 0xa6630000a664, + 0xa6650000a666, + 0xa6670000a668, + 0xa6690000a66a, + 0xa66b0000a66c, + 0xa66d0000a670, + 0xa6740000a67e, + 0xa67f0000a680, + 0xa6810000a682, + 0xa6830000a684, + 0xa6850000a686, + 0xa6870000a688, + 0xa6890000a68a, + 0xa68b0000a68c, + 0xa68d0000a68e, + 0xa68f0000a690, + 0xa6910000a692, + 0xa6930000a694, + 0xa6950000a696, + 0xa6970000a698, + 0xa6990000a69a, + 0xa69b0000a69c, + 0xa69e0000a6e6, + 0xa6f00000a6f2, + 0xa7170000a720, + 0xa7230000a724, + 0xa7250000a726, + 0xa7270000a728, + 0xa7290000a72a, + 0xa72b0000a72c, + 0xa72d0000a72e, + 0xa72f0000a732, + 0xa7330000a734, + 0xa7350000a736, + 0xa7370000a738, + 0xa7390000a73a, + 0xa73b0000a73c, + 0xa73d0000a73e, + 0xa73f0000a740, + 0xa7410000a742, + 0xa7430000a744, + 0xa7450000a746, + 0xa7470000a748, + 0xa7490000a74a, + 0xa74b0000a74c, + 0xa74d0000a74e, + 0xa74f0000a750, + 0xa7510000a752, + 0xa7530000a754, + 0xa7550000a756, + 0xa7570000a758, + 0xa7590000a75a, + 0xa75b0000a75c, + 0xa75d0000a75e, + 0xa75f0000a760, + 0xa7610000a762, + 0xa7630000a764, + 0xa7650000a766, + 0xa7670000a768, + 0xa7690000a76a, + 0xa76b0000a76c, + 0xa76d0000a76e, + 0xa76f0000a770, + 0xa7710000a779, + 0xa77a0000a77b, + 0xa77c0000a77d, + 0xa77f0000a780, + 0xa7810000a782, + 0xa7830000a784, + 0xa7850000a786, + 0xa7870000a789, + 0xa78c0000a78d, + 0xa78e0000a790, + 0xa7910000a792, + 0xa7930000a796, + 0xa7970000a798, + 0xa7990000a79a, + 0xa79b0000a79c, + 0xa79d0000a79e, + 0xa79f0000a7a0, + 0xa7a10000a7a2, + 0xa7a30000a7a4, + 0xa7a50000a7a6, + 0xa7a70000a7a8, + 0xa7a90000a7aa, + 0xa7b50000a7b6, + 0xa7b70000a7b8, + 0xa7f70000a7f8, + 0xa7fa0000a828, + 0xa8400000a874, + 0xa8800000a8c6, + 0xa8d00000a8da, + 0xa8e00000a8f8, + 0xa8fb0000a8fc, + 0xa8fd0000a8fe, + 0xa9000000a92e, + 0xa9300000a954, + 0xa9800000a9c1, + 0xa9cf0000a9da, + 0xa9e00000a9ff, + 0xaa000000aa37, + 0xaa400000aa4e, + 0xaa500000aa5a, + 0xaa600000aa77, + 0xaa7a0000aac3, + 0xaadb0000aade, + 0xaae00000aaf0, + 0xaaf20000aaf7, + 0xab010000ab07, + 0xab090000ab0f, + 0xab110000ab17, + 0xab200000ab27, + 0xab280000ab2f, + 0xab300000ab5b, + 0xab600000ab66, + 0xabc00000abeb, + 0xabec0000abee, + 0xabf00000abfa, + 0xac000000d7a4, + 0xfa0e0000fa10, + 0xfa110000fa12, + 0xfa130000fa15, + 0xfa1f0000fa20, + 0xfa210000fa22, + 0xfa230000fa25, + 0xfa270000fa2a, + 0xfb1e0000fb1f, + 0xfe200000fe30, + 0xfe730000fe74, + 0x100000001000c, + 0x1000d00010027, + 0x100280001003b, + 0x1003c0001003e, + 0x1003f0001004e, + 0x100500001005e, + 0x10080000100fb, + 0x101fd000101fe, + 0x102800001029d, + 0x102a0000102d1, + 0x102e0000102e1, + 0x1030000010320, + 0x1032d00010341, + 0x103420001034a, + 0x103500001037b, + 0x103800001039e, + 0x103a0000103c4, + 0x103c8000103d0, + 0x104280001049e, + 0x104a0000104aa, + 0x104d8000104fc, + 0x1050000010528, + 0x1053000010564, + 0x1060000010737, + 0x1074000010756, + 0x1076000010768, + 0x1080000010806, + 0x1080800010809, + 0x1080a00010836, + 0x1083700010839, + 0x1083c0001083d, + 0x1083f00010856, + 0x1086000010877, + 0x108800001089f, + 0x108e0000108f3, + 0x108f4000108f6, + 0x1090000010916, + 0x109200001093a, + 0x10980000109b8, + 0x109be000109c0, + 0x10a0000010a04, + 0x10a0500010a07, + 0x10a0c00010a14, + 0x10a1500010a18, + 0x10a1900010a34, + 0x10a3800010a3b, + 0x10a3f00010a40, + 0x10a6000010a7d, + 0x10a8000010a9d, + 0x10ac000010ac8, + 0x10ac900010ae7, + 0x10b0000010b36, + 0x10b4000010b56, + 0x10b6000010b73, + 0x10b8000010b92, + 0x10c0000010c49, + 0x10cc000010cf3, + 0x1100000011047, + 0x1106600011070, + 0x1107f000110bb, + 0x110d0000110e9, + 0x110f0000110fa, + 0x1110000011135, + 0x1113600011140, + 0x1115000011174, + 0x1117600011177, + 0x11180000111c5, + 0x111ca000111cd, + 0x111d0000111db, + 0x111dc000111dd, + 0x1120000011212, + 0x1121300011238, + 0x1123e0001123f, + 0x1128000011287, + 0x1128800011289, + 0x1128a0001128e, + 0x1128f0001129e, + 0x1129f000112a9, + 0x112b0000112eb, + 0x112f0000112fa, + 0x1130000011304, + 0x113050001130d, + 0x1130f00011311, + 0x1131300011329, + 0x1132a00011331, + 0x1133200011334, + 0x113350001133a, + 0x1133c00011345, + 0x1134700011349, + 0x1134b0001134e, + 0x1135000011351, + 0x1135700011358, + 0x1135d00011364, + 0x113660001136d, + 0x1137000011375, + 0x114000001144b, + 0x114500001145a, + 0x11480000114c6, + 0x114c7000114c8, + 0x114d0000114da, + 0x11580000115b6, + 0x115b8000115c1, + 0x115d8000115de, + 0x1160000011641, + 0x1164400011645, + 0x116500001165a, + 0x11680000116b8, + 0x116c0000116ca, + 0x117000001171a, + 0x1171d0001172c, + 0x117300001173a, + 0x118c0000118ea, + 0x118ff00011900, + 0x11a0000011a3f, + 0x11a4700011a48, + 0x11a5000011a84, + 0x11a8600011a9a, + 0x11ac000011af9, + 0x11c0000011c09, + 0x11c0a00011c37, + 0x11c3800011c41, + 0x11c5000011c5a, + 0x11c7200011c90, + 0x11c9200011ca8, + 0x11ca900011cb7, + 0x11d0000011d07, + 0x11d0800011d0a, + 0x11d0b00011d37, + 0x11d3a00011d3b, + 0x11d3c00011d3e, + 0x11d3f00011d48, + 0x11d5000011d5a, + 0x120000001239a, + 0x1248000012544, + 0x130000001342f, + 0x1440000014647, + 0x1680000016a39, + 0x16a4000016a5f, + 0x16a6000016a6a, + 0x16ad000016aee, + 0x16af000016af5, + 0x16b0000016b37, + 0x16b4000016b44, + 0x16b5000016b5a, + 0x16b6300016b78, + 0x16b7d00016b90, + 0x16f0000016f45, + 0x16f5000016f7f, + 0x16f8f00016fa0, + 0x16fe000016fe2, + 0x17000000187ed, + 0x1880000018af3, + 0x1b0000001b11f, + 0x1b1700001b2fc, + 0x1bc000001bc6b, + 0x1bc700001bc7d, + 0x1bc800001bc89, + 0x1bc900001bc9a, + 0x1bc9d0001bc9f, + 0x1da000001da37, + 0x1da3b0001da6d, + 0x1da750001da76, + 0x1da840001da85, + 0x1da9b0001daa0, + 0x1daa10001dab0, + 0x1e0000001e007, + 0x1e0080001e019, + 0x1e01b0001e022, + 0x1e0230001e025, + 0x1e0260001e02b, + 0x1e8000001e8c5, + 0x1e8d00001e8d7, + 0x1e9220001e94b, + 0x1e9500001e95a, + 0x200000002a6d7, + 0x2a7000002b735, + 0x2b7400002b81e, + 0x2b8200002cea2, + 0x2ceb00002ebe1, + ), + 'CONTEXTJ': ( + 0x200c0000200e, + ), + 'CONTEXTO': ( + 0xb7000000b8, + 0x37500000376, + 0x5f3000005f5, + 0x6600000066a, + 0x6f0000006fa, + 0x30fb000030fc, + ), +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/intranges.py b/winvenv/Lib/site-packages/pip/_vendor/idna/intranges.py new file mode 100644 index 0000000..fa8a735 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/intranges.py @@ -0,0 +1,53 @@ +""" +Given a list of integers, made up of (hopefully) a small number of long runs +of consecutive integers, compute a representation of the form +((start1, end1), (start2, end2) ...). Then answer the question "was x present +in the original list?" in time O(log(# runs)). +""" + +import bisect + +def intranges_from_list(list_): + """Represent a list of integers as a sequence of ranges: + ((start_0, end_0), (start_1, end_1), ...), such that the original + integers are exactly those x such that start_i <= x < end_i for some i. + + Ranges are encoded as single integers (start << 32 | end), not as tuples. + """ + + sorted_list = sorted(list_) + ranges = [] + last_write = -1 + for i in range(len(sorted_list)): + if i+1 < len(sorted_list): + if sorted_list[i] == sorted_list[i+1]-1: + continue + current_range = sorted_list[last_write+1:i+1] + ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) + last_write = i + + return tuple(ranges) + +def _encode_range(start, end): + return (start << 32) | end + +def _decode_range(r): + return (r >> 32), (r & ((1 << 32) - 1)) + + +def intranges_contain(int_, ranges): + """Determine if `int_` falls into one of the ranges in `ranges`.""" + tuple_ = _encode_range(int_, 0) + pos = bisect.bisect_left(ranges, tuple_) + # we could be immediately ahead of a tuple (start, end) + # with start < int_ <= end + if pos > 0: + left, right = _decode_range(ranges[pos-1]) + if left <= int_ < right: + return True + # or we could be immediately behind a tuple (int_, end) + if pos < len(ranges): + left, _ = _decode_range(ranges[pos]) + if left == int_: + return True + return False diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/package_data.py b/winvenv/Lib/site-packages/pip/_vendor/idna/package_data.py new file mode 100644 index 0000000..39c192b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/package_data.py @@ -0,0 +1,2 @@ +__version__ = '2.7' + diff --git a/winvenv/Lib/site-packages/pip/_vendor/idna/uts46data.py b/winvenv/Lib/site-packages/pip/_vendor/idna/uts46data.py new file mode 100644 index 0000000..79731cb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/idna/uts46data.py @@ -0,0 +1,8179 @@ +# This file is automatically generated by tools/idna-data +# vim: set fileencoding=utf-8 : + +"""IDNA Mapping Table from UTS46.""" + + +__version__ = "10.0.0" +def _seg_0(): + return [ + (0x0, '3'), + (0x1, '3'), + (0x2, '3'), + (0x3, '3'), + (0x4, '3'), + (0x5, '3'), + (0x6, '3'), + (0x7, '3'), + (0x8, '3'), + (0x9, '3'), + (0xA, '3'), + (0xB, '3'), + (0xC, '3'), + (0xD, '3'), + (0xE, '3'), + (0xF, '3'), + (0x10, '3'), + (0x11, '3'), + (0x12, '3'), + (0x13, '3'), + (0x14, '3'), + (0x15, '3'), + (0x16, '3'), + (0x17, '3'), + (0x18, '3'), + (0x19, '3'), + (0x1A, '3'), + (0x1B, '3'), + (0x1C, '3'), + (0x1D, '3'), + (0x1E, '3'), + (0x1F, '3'), + (0x20, '3'), + (0x21, '3'), + (0x22, '3'), + (0x23, '3'), + (0x24, '3'), + (0x25, '3'), + (0x26, '3'), + (0x27, '3'), + (0x28, '3'), + (0x29, '3'), + (0x2A, '3'), + (0x2B, '3'), + (0x2C, '3'), + (0x2D, 'V'), + (0x2E, 'V'), + (0x2F, '3'), + (0x30, 'V'), + (0x31, 'V'), + (0x32, 'V'), + (0x33, 'V'), + (0x34, 'V'), + (0x35, 'V'), + (0x36, 'V'), + (0x37, 'V'), + (0x38, 'V'), + (0x39, 'V'), + (0x3A, '3'), + (0x3B, '3'), + (0x3C, '3'), + (0x3D, '3'), + (0x3E, '3'), + (0x3F, '3'), + (0x40, '3'), + (0x41, 'M', u'a'), + (0x42, 'M', u'b'), + (0x43, 'M', u'c'), + (0x44, 'M', u'd'), + (0x45, 'M', u'e'), + (0x46, 'M', u'f'), + (0x47, 'M', u'g'), + (0x48, 'M', u'h'), + (0x49, 'M', u'i'), + (0x4A, 'M', u'j'), + (0x4B, 'M', u'k'), + (0x4C, 'M', u'l'), + (0x4D, 'M', u'm'), + (0x4E, 'M', u'n'), + (0x4F, 'M', u'o'), + (0x50, 'M', u'p'), + (0x51, 'M', u'q'), + (0x52, 'M', u'r'), + (0x53, 'M', u's'), + (0x54, 'M', u't'), + (0x55, 'M', u'u'), + (0x56, 'M', u'v'), + (0x57, 'M', u'w'), + (0x58, 'M', u'x'), + (0x59, 'M', u'y'), + (0x5A, 'M', u'z'), + (0x5B, '3'), + (0x5C, '3'), + (0x5D, '3'), + (0x5E, '3'), + (0x5F, '3'), + (0x60, '3'), + (0x61, 'V'), + (0x62, 'V'), + (0x63, 'V'), + ] + +def _seg_1(): + return [ + (0x64, 'V'), + (0x65, 'V'), + (0x66, 'V'), + (0x67, 'V'), + (0x68, 'V'), + (0x69, 'V'), + (0x6A, 'V'), + (0x6B, 'V'), + (0x6C, 'V'), + (0x6D, 'V'), + (0x6E, 'V'), + (0x6F, 'V'), + (0x70, 'V'), + (0x71, 'V'), + (0x72, 'V'), + (0x73, 'V'), + (0x74, 'V'), + (0x75, 'V'), + (0x76, 'V'), + (0x77, 'V'), + (0x78, 'V'), + (0x79, 'V'), + (0x7A, 'V'), + (0x7B, '3'), + (0x7C, '3'), + (0x7D, '3'), + (0x7E, '3'), + (0x7F, '3'), + (0x80, 'X'), + (0x81, 'X'), + (0x82, 'X'), + (0x83, 'X'), + (0x84, 'X'), + (0x85, 'X'), + (0x86, 'X'), + (0x87, 'X'), + (0x88, 'X'), + (0x89, 'X'), + (0x8A, 'X'), + (0x8B, 'X'), + (0x8C, 'X'), + (0x8D, 'X'), + (0x8E, 'X'), + (0x8F, 'X'), + (0x90, 'X'), + (0x91, 'X'), + (0x92, 'X'), + (0x93, 'X'), + (0x94, 'X'), + (0x95, 'X'), + (0x96, 'X'), + (0x97, 'X'), + (0x98, 'X'), + (0x99, 'X'), + (0x9A, 'X'), + (0x9B, 'X'), + (0x9C, 'X'), + (0x9D, 'X'), + (0x9E, 'X'), + (0x9F, 'X'), + (0xA0, '3', u' '), + (0xA1, 'V'), + (0xA2, 'V'), + (0xA3, 'V'), + (0xA4, 'V'), + (0xA5, 'V'), + (0xA6, 'V'), + (0xA7, 'V'), + (0xA8, '3', u' ̈'), + (0xA9, 'V'), + (0xAA, 'M', u'a'), + (0xAB, 'V'), + (0xAC, 'V'), + (0xAD, 'I'), + (0xAE, 'V'), + (0xAF, '3', u' ̄'), + (0xB0, 'V'), + (0xB1, 'V'), + (0xB2, 'M', u'2'), + (0xB3, 'M', u'3'), + (0xB4, '3', u' ́'), + (0xB5, 'M', u'μ'), + (0xB6, 'V'), + (0xB7, 'V'), + (0xB8, '3', u' ̧'), + (0xB9, 'M', u'1'), + (0xBA, 'M', u'o'), + (0xBB, 'V'), + (0xBC, 'M', u'1⁄4'), + (0xBD, 'M', u'1⁄2'), + (0xBE, 'M', u'3⁄4'), + (0xBF, 'V'), + (0xC0, 'M', u'à'), + (0xC1, 'M', u'á'), + (0xC2, 'M', u'â'), + (0xC3, 'M', u'ã'), + (0xC4, 'M', u'ä'), + (0xC5, 'M', u'å'), + (0xC6, 'M', u'æ'), + (0xC7, 'M', u'ç'), + ] + +def _seg_2(): + return [ + (0xC8, 'M', u'è'), + (0xC9, 'M', u'é'), + (0xCA, 'M', u'ê'), + (0xCB, 'M', u'ë'), + (0xCC, 'M', u'ì'), + (0xCD, 'M', u'í'), + (0xCE, 'M', u'î'), + (0xCF, 'M', u'ï'), + (0xD0, 'M', u'ð'), + (0xD1, 'M', u'ñ'), + (0xD2, 'M', u'ò'), + (0xD3, 'M', u'ó'), + (0xD4, 'M', u'ô'), + (0xD5, 'M', u'õ'), + (0xD6, 'M', u'ö'), + (0xD7, 'V'), + (0xD8, 'M', u'ø'), + (0xD9, 'M', u'ù'), + (0xDA, 'M', u'ú'), + (0xDB, 'M', u'û'), + (0xDC, 'M', u'ü'), + (0xDD, 'M', u'ý'), + (0xDE, 'M', u'þ'), + (0xDF, 'D', u'ss'), + (0xE0, 'V'), + (0xE1, 'V'), + (0xE2, 'V'), + (0xE3, 'V'), + (0xE4, 'V'), + (0xE5, 'V'), + (0xE6, 'V'), + (0xE7, 'V'), + (0xE8, 'V'), + (0xE9, 'V'), + (0xEA, 'V'), + (0xEB, 'V'), + (0xEC, 'V'), + (0xED, 'V'), + (0xEE, 'V'), + (0xEF, 'V'), + (0xF0, 'V'), + (0xF1, 'V'), + (0xF2, 'V'), + (0xF3, 'V'), + (0xF4, 'V'), + (0xF5, 'V'), + (0xF6, 'V'), + (0xF7, 'V'), + (0xF8, 'V'), + (0xF9, 'V'), + (0xFA, 'V'), + (0xFB, 'V'), + (0xFC, 'V'), + (0xFD, 'V'), + (0xFE, 'V'), + (0xFF, 'V'), + (0x100, 'M', u'ā'), + (0x101, 'V'), + (0x102, 'M', u'ă'), + (0x103, 'V'), + (0x104, 'M', u'ą'), + (0x105, 'V'), + (0x106, 'M', u'ć'), + (0x107, 'V'), + (0x108, 'M', u'ĉ'), + (0x109, 'V'), + (0x10A, 'M', u'ċ'), + (0x10B, 'V'), + (0x10C, 'M', u'č'), + (0x10D, 'V'), + (0x10E, 'M', u'ď'), + (0x10F, 'V'), + (0x110, 'M', u'đ'), + (0x111, 'V'), + (0x112, 'M', u'ē'), + (0x113, 'V'), + (0x114, 'M', u'ĕ'), + (0x115, 'V'), + (0x116, 'M', u'ė'), + (0x117, 'V'), + (0x118, 'M', u'ę'), + (0x119, 'V'), + (0x11A, 'M', u'ě'), + (0x11B, 'V'), + (0x11C, 'M', u'ĝ'), + (0x11D, 'V'), + (0x11E, 'M', u'ğ'), + (0x11F, 'V'), + (0x120, 'M', u'ġ'), + (0x121, 'V'), + (0x122, 'M', u'ģ'), + (0x123, 'V'), + (0x124, 'M', u'ĥ'), + (0x125, 'V'), + (0x126, 'M', u'ħ'), + (0x127, 'V'), + (0x128, 'M', u'ĩ'), + (0x129, 'V'), + (0x12A, 'M', u'ī'), + (0x12B, 'V'), + ] + +def _seg_3(): + return [ + (0x12C, 'M', u'ĭ'), + (0x12D, 'V'), + (0x12E, 'M', u'į'), + (0x12F, 'V'), + (0x130, 'M', u'i̇'), + (0x131, 'V'), + (0x132, 'M', u'ij'), + (0x134, 'M', u'ĵ'), + (0x135, 'V'), + (0x136, 'M', u'ķ'), + (0x137, 'V'), + (0x139, 'M', u'ĺ'), + (0x13A, 'V'), + (0x13B, 'M', u'ļ'), + (0x13C, 'V'), + (0x13D, 'M', u'ľ'), + (0x13E, 'V'), + (0x13F, 'M', u'l·'), + (0x141, 'M', u'ł'), + (0x142, 'V'), + (0x143, 'M', u'ń'), + (0x144, 'V'), + (0x145, 'M', u'ņ'), + (0x146, 'V'), + (0x147, 'M', u'ň'), + (0x148, 'V'), + (0x149, 'M', u'ʼn'), + (0x14A, 'M', u'ŋ'), + (0x14B, 'V'), + (0x14C, 'M', u'ō'), + (0x14D, 'V'), + (0x14E, 'M', u'ŏ'), + (0x14F, 'V'), + (0x150, 'M', u'ő'), + (0x151, 'V'), + (0x152, 'M', u'œ'), + (0x153, 'V'), + (0x154, 'M', u'ŕ'), + (0x155, 'V'), + (0x156, 'M', u'ŗ'), + (0x157, 'V'), + (0x158, 'M', u'ř'), + (0x159, 'V'), + (0x15A, 'M', u'ś'), + (0x15B, 'V'), + (0x15C, 'M', u'ŝ'), + (0x15D, 'V'), + (0x15E, 'M', u'ş'), + (0x15F, 'V'), + (0x160, 'M', u'š'), + (0x161, 'V'), + (0x162, 'M', u'ţ'), + (0x163, 'V'), + (0x164, 'M', u'ť'), + (0x165, 'V'), + (0x166, 'M', u'ŧ'), + (0x167, 'V'), + (0x168, 'M', u'ũ'), + (0x169, 'V'), + (0x16A, 'M', u'ū'), + (0x16B, 'V'), + (0x16C, 'M', u'ŭ'), + (0x16D, 'V'), + (0x16E, 'M', u'ů'), + (0x16F, 'V'), + (0x170, 'M', u'ű'), + (0x171, 'V'), + (0x172, 'M', u'ų'), + (0x173, 'V'), + (0x174, 'M', u'ŵ'), + (0x175, 'V'), + (0x176, 'M', u'ŷ'), + (0x177, 'V'), + (0x178, 'M', u'ÿ'), + (0x179, 'M', u'ź'), + (0x17A, 'V'), + (0x17B, 'M', u'ż'), + (0x17C, 'V'), + (0x17D, 'M', u'ž'), + (0x17E, 'V'), + (0x17F, 'M', u's'), + (0x180, 'V'), + (0x181, 'M', u'ɓ'), + (0x182, 'M', u'ƃ'), + (0x183, 'V'), + (0x184, 'M', u'ƅ'), + (0x185, 'V'), + (0x186, 'M', u'ɔ'), + (0x187, 'M', u'ƈ'), + (0x188, 'V'), + (0x189, 'M', u'ɖ'), + (0x18A, 'M', u'ɗ'), + (0x18B, 'M', u'ƌ'), + (0x18C, 'V'), + (0x18E, 'M', u'ǝ'), + (0x18F, 'M', u'ə'), + (0x190, 'M', u'ɛ'), + (0x191, 'M', u'ƒ'), + (0x192, 'V'), + (0x193, 'M', u'ɠ'), + ] + +def _seg_4(): + return [ + (0x194, 'M', u'ɣ'), + (0x195, 'V'), + (0x196, 'M', u'ɩ'), + (0x197, 'M', u'ɨ'), + (0x198, 'M', u'ƙ'), + (0x199, 'V'), + (0x19C, 'M', u'ɯ'), + (0x19D, 'M', u'ɲ'), + (0x19E, 'V'), + (0x19F, 'M', u'ɵ'), + (0x1A0, 'M', u'ơ'), + (0x1A1, 'V'), + (0x1A2, 'M', u'ƣ'), + (0x1A3, 'V'), + (0x1A4, 'M', u'ƥ'), + (0x1A5, 'V'), + (0x1A6, 'M', u'ʀ'), + (0x1A7, 'M', u'ƨ'), + (0x1A8, 'V'), + (0x1A9, 'M', u'ʃ'), + (0x1AA, 'V'), + (0x1AC, 'M', u'ƭ'), + (0x1AD, 'V'), + (0x1AE, 'M', u'ʈ'), + (0x1AF, 'M', u'ư'), + (0x1B0, 'V'), + (0x1B1, 'M', u'ʊ'), + (0x1B2, 'M', u'ʋ'), + (0x1B3, 'M', u'ƴ'), + (0x1B4, 'V'), + (0x1B5, 'M', u'ƶ'), + (0x1B6, 'V'), + (0x1B7, 'M', u'ʒ'), + (0x1B8, 'M', u'ƹ'), + (0x1B9, 'V'), + (0x1BC, 'M', u'ƽ'), + (0x1BD, 'V'), + (0x1C4, 'M', u'dž'), + (0x1C7, 'M', u'lj'), + (0x1CA, 'M', u'nj'), + (0x1CD, 'M', u'ǎ'), + (0x1CE, 'V'), + (0x1CF, 'M', u'ǐ'), + (0x1D0, 'V'), + (0x1D1, 'M', u'ǒ'), + (0x1D2, 'V'), + (0x1D3, 'M', u'ǔ'), + (0x1D4, 'V'), + (0x1D5, 'M', u'ǖ'), + (0x1D6, 'V'), + (0x1D7, 'M', u'ǘ'), + (0x1D8, 'V'), + (0x1D9, 'M', u'ǚ'), + (0x1DA, 'V'), + (0x1DB, 'M', u'ǜ'), + (0x1DC, 'V'), + (0x1DE, 'M', u'ǟ'), + (0x1DF, 'V'), + (0x1E0, 'M', u'ǡ'), + (0x1E1, 'V'), + (0x1E2, 'M', u'ǣ'), + (0x1E3, 'V'), + (0x1E4, 'M', u'ǥ'), + (0x1E5, 'V'), + (0x1E6, 'M', u'ǧ'), + (0x1E7, 'V'), + (0x1E8, 'M', u'ǩ'), + (0x1E9, 'V'), + (0x1EA, 'M', u'ǫ'), + (0x1EB, 'V'), + (0x1EC, 'M', u'ǭ'), + (0x1ED, 'V'), + (0x1EE, 'M', u'ǯ'), + (0x1EF, 'V'), + (0x1F1, 'M', u'dz'), + (0x1F4, 'M', u'ǵ'), + (0x1F5, 'V'), + (0x1F6, 'M', u'ƕ'), + (0x1F7, 'M', u'ƿ'), + (0x1F8, 'M', u'ǹ'), + (0x1F9, 'V'), + (0x1FA, 'M', u'ǻ'), + (0x1FB, 'V'), + (0x1FC, 'M', u'ǽ'), + (0x1FD, 'V'), + (0x1FE, 'M', u'ǿ'), + (0x1FF, 'V'), + (0x200, 'M', u'ȁ'), + (0x201, 'V'), + (0x202, 'M', u'ȃ'), + (0x203, 'V'), + (0x204, 'M', u'ȅ'), + (0x205, 'V'), + (0x206, 'M', u'ȇ'), + (0x207, 'V'), + (0x208, 'M', u'ȉ'), + (0x209, 'V'), + (0x20A, 'M', u'ȋ'), + (0x20B, 'V'), + (0x20C, 'M', u'ȍ'), + ] + +def _seg_5(): + return [ + (0x20D, 'V'), + (0x20E, 'M', u'ȏ'), + (0x20F, 'V'), + (0x210, 'M', u'ȑ'), + (0x211, 'V'), + (0x212, 'M', u'ȓ'), + (0x213, 'V'), + (0x214, 'M', u'ȕ'), + (0x215, 'V'), + (0x216, 'M', u'ȗ'), + (0x217, 'V'), + (0x218, 'M', u'ș'), + (0x219, 'V'), + (0x21A, 'M', u'ț'), + (0x21B, 'V'), + (0x21C, 'M', u'ȝ'), + (0x21D, 'V'), + (0x21E, 'M', u'ȟ'), + (0x21F, 'V'), + (0x220, 'M', u'ƞ'), + (0x221, 'V'), + (0x222, 'M', u'ȣ'), + (0x223, 'V'), + (0x224, 'M', u'ȥ'), + (0x225, 'V'), + (0x226, 'M', u'ȧ'), + (0x227, 'V'), + (0x228, 'M', u'ȩ'), + (0x229, 'V'), + (0x22A, 'M', u'ȫ'), + (0x22B, 'V'), + (0x22C, 'M', u'ȭ'), + (0x22D, 'V'), + (0x22E, 'M', u'ȯ'), + (0x22F, 'V'), + (0x230, 'M', u'ȱ'), + (0x231, 'V'), + (0x232, 'M', u'ȳ'), + (0x233, 'V'), + (0x23A, 'M', u'ⱥ'), + (0x23B, 'M', u'ȼ'), + (0x23C, 'V'), + (0x23D, 'M', u'ƚ'), + (0x23E, 'M', u'ⱦ'), + (0x23F, 'V'), + (0x241, 'M', u'ɂ'), + (0x242, 'V'), + (0x243, 'M', u'ƀ'), + (0x244, 'M', u'ʉ'), + (0x245, 'M', u'ʌ'), + (0x246, 'M', u'ɇ'), + (0x247, 'V'), + (0x248, 'M', u'ɉ'), + (0x249, 'V'), + (0x24A, 'M', u'ɋ'), + (0x24B, 'V'), + (0x24C, 'M', u'ɍ'), + (0x24D, 'V'), + (0x24E, 'M', u'ɏ'), + (0x24F, 'V'), + (0x2B0, 'M', u'h'), + (0x2B1, 'M', u'ɦ'), + (0x2B2, 'M', u'j'), + (0x2B3, 'M', u'r'), + (0x2B4, 'M', u'ɹ'), + (0x2B5, 'M', u'ɻ'), + (0x2B6, 'M', u'ʁ'), + (0x2B7, 'M', u'w'), + (0x2B8, 'M', u'y'), + (0x2B9, 'V'), + (0x2D8, '3', u' ̆'), + (0x2D9, '3', u' ̇'), + (0x2DA, '3', u' ̊'), + (0x2DB, '3', u' ̨'), + (0x2DC, '3', u' ̃'), + (0x2DD, '3', u' ̋'), + (0x2DE, 'V'), + (0x2E0, 'M', u'ɣ'), + (0x2E1, 'M', u'l'), + (0x2E2, 'M', u's'), + (0x2E3, 'M', u'x'), + (0x2E4, 'M', u'ʕ'), + (0x2E5, 'V'), + (0x340, 'M', u'̀'), + (0x341, 'M', u'́'), + (0x342, 'V'), + (0x343, 'M', u'̓'), + (0x344, 'M', u'̈́'), + (0x345, 'M', u'ι'), + (0x346, 'V'), + (0x34F, 'I'), + (0x350, 'V'), + (0x370, 'M', u'ͱ'), + (0x371, 'V'), + (0x372, 'M', u'ͳ'), + (0x373, 'V'), + (0x374, 'M', u'ʹ'), + (0x375, 'V'), + (0x376, 'M', u'ͷ'), + (0x377, 'V'), + ] + +def _seg_6(): + return [ + (0x378, 'X'), + (0x37A, '3', u' ι'), + (0x37B, 'V'), + (0x37E, '3', u';'), + (0x37F, 'M', u'ϳ'), + (0x380, 'X'), + (0x384, '3', u' ́'), + (0x385, '3', u' ̈́'), + (0x386, 'M', u'ά'), + (0x387, 'M', u'·'), + (0x388, 'M', u'έ'), + (0x389, 'M', u'ή'), + (0x38A, 'M', u'ί'), + (0x38B, 'X'), + (0x38C, 'M', u'ό'), + (0x38D, 'X'), + (0x38E, 'M', u'ύ'), + (0x38F, 'M', u'ώ'), + (0x390, 'V'), + (0x391, 'M', u'α'), + (0x392, 'M', u'β'), + (0x393, 'M', u'γ'), + (0x394, 'M', u'δ'), + (0x395, 'M', u'ε'), + (0x396, 'M', u'ζ'), + (0x397, 'M', u'η'), + (0x398, 'M', u'θ'), + (0x399, 'M', u'ι'), + (0x39A, 'M', u'κ'), + (0x39B, 'M', u'λ'), + (0x39C, 'M', u'μ'), + (0x39D, 'M', u'ν'), + (0x39E, 'M', u'ξ'), + (0x39F, 'M', u'ο'), + (0x3A0, 'M', u'π'), + (0x3A1, 'M', u'ρ'), + (0x3A2, 'X'), + (0x3A3, 'M', u'σ'), + (0x3A4, 'M', u'τ'), + (0x3A5, 'M', u'υ'), + (0x3A6, 'M', u'φ'), + (0x3A7, 'M', u'χ'), + (0x3A8, 'M', u'ψ'), + (0x3A9, 'M', u'ω'), + (0x3AA, 'M', u'ϊ'), + (0x3AB, 'M', u'ϋ'), + (0x3AC, 'V'), + (0x3C2, 'D', u'σ'), + (0x3C3, 'V'), + (0x3CF, 'M', u'ϗ'), + (0x3D0, 'M', u'β'), + (0x3D1, 'M', u'θ'), + (0x3D2, 'M', u'υ'), + (0x3D3, 'M', u'ύ'), + (0x3D4, 'M', u'ϋ'), + (0x3D5, 'M', u'φ'), + (0x3D6, 'M', u'π'), + (0x3D7, 'V'), + (0x3D8, 'M', u'ϙ'), + (0x3D9, 'V'), + (0x3DA, 'M', u'ϛ'), + (0x3DB, 'V'), + (0x3DC, 'M', u'ϝ'), + (0x3DD, 'V'), + (0x3DE, 'M', u'ϟ'), + (0x3DF, 'V'), + (0x3E0, 'M', u'ϡ'), + (0x3E1, 'V'), + (0x3E2, 'M', u'ϣ'), + (0x3E3, 'V'), + (0x3E4, 'M', u'ϥ'), + (0x3E5, 'V'), + (0x3E6, 'M', u'ϧ'), + (0x3E7, 'V'), + (0x3E8, 'M', u'ϩ'), + (0x3E9, 'V'), + (0x3EA, 'M', u'ϫ'), + (0x3EB, 'V'), + (0x3EC, 'M', u'ϭ'), + (0x3ED, 'V'), + (0x3EE, 'M', u'ϯ'), + (0x3EF, 'V'), + (0x3F0, 'M', u'κ'), + (0x3F1, 'M', u'ρ'), + (0x3F2, 'M', u'σ'), + (0x3F3, 'V'), + (0x3F4, 'M', u'θ'), + (0x3F5, 'M', u'ε'), + (0x3F6, 'V'), + (0x3F7, 'M', u'ϸ'), + (0x3F8, 'V'), + (0x3F9, 'M', u'σ'), + (0x3FA, 'M', u'ϻ'), + (0x3FB, 'V'), + (0x3FD, 'M', u'ͻ'), + (0x3FE, 'M', u'ͼ'), + (0x3FF, 'M', u'ͽ'), + (0x400, 'M', u'ѐ'), + (0x401, 'M', u'ё'), + (0x402, 'M', u'ђ'), + ] + +def _seg_7(): + return [ + (0x403, 'M', u'ѓ'), + (0x404, 'M', u'є'), + (0x405, 'M', u'ѕ'), + (0x406, 'M', u'і'), + (0x407, 'M', u'ї'), + (0x408, 'M', u'ј'), + (0x409, 'M', u'љ'), + (0x40A, 'M', u'њ'), + (0x40B, 'M', u'ћ'), + (0x40C, 'M', u'ќ'), + (0x40D, 'M', u'ѝ'), + (0x40E, 'M', u'ў'), + (0x40F, 'M', u'џ'), + (0x410, 'M', u'а'), + (0x411, 'M', u'б'), + (0x412, 'M', u'в'), + (0x413, 'M', u'г'), + (0x414, 'M', u'д'), + (0x415, 'M', u'е'), + (0x416, 'M', u'ж'), + (0x417, 'M', u'з'), + (0x418, 'M', u'и'), + (0x419, 'M', u'й'), + (0x41A, 'M', u'к'), + (0x41B, 'M', u'л'), + (0x41C, 'M', u'м'), + (0x41D, 'M', u'н'), + (0x41E, 'M', u'о'), + (0x41F, 'M', u'п'), + (0x420, 'M', u'р'), + (0x421, 'M', u'с'), + (0x422, 'M', u'т'), + (0x423, 'M', u'у'), + (0x424, 'M', u'ф'), + (0x425, 'M', u'х'), + (0x426, 'M', u'ц'), + (0x427, 'M', u'ч'), + (0x428, 'M', u'ш'), + (0x429, 'M', u'щ'), + (0x42A, 'M', u'ъ'), + (0x42B, 'M', u'ы'), + (0x42C, 'M', u'ь'), + (0x42D, 'M', u'э'), + (0x42E, 'M', u'ю'), + (0x42F, 'M', u'я'), + (0x430, 'V'), + (0x460, 'M', u'ѡ'), + (0x461, 'V'), + (0x462, 'M', u'ѣ'), + (0x463, 'V'), + (0x464, 'M', u'ѥ'), + (0x465, 'V'), + (0x466, 'M', u'ѧ'), + (0x467, 'V'), + (0x468, 'M', u'ѩ'), + (0x469, 'V'), + (0x46A, 'M', u'ѫ'), + (0x46B, 'V'), + (0x46C, 'M', u'ѭ'), + (0x46D, 'V'), + (0x46E, 'M', u'ѯ'), + (0x46F, 'V'), + (0x470, 'M', u'ѱ'), + (0x471, 'V'), + (0x472, 'M', u'ѳ'), + (0x473, 'V'), + (0x474, 'M', u'ѵ'), + (0x475, 'V'), + (0x476, 'M', u'ѷ'), + (0x477, 'V'), + (0x478, 'M', u'ѹ'), + (0x479, 'V'), + (0x47A, 'M', u'ѻ'), + (0x47B, 'V'), + (0x47C, 'M', u'ѽ'), + (0x47D, 'V'), + (0x47E, 'M', u'ѿ'), + (0x47F, 'V'), + (0x480, 'M', u'ҁ'), + (0x481, 'V'), + (0x48A, 'M', u'ҋ'), + (0x48B, 'V'), + (0x48C, 'M', u'ҍ'), + (0x48D, 'V'), + (0x48E, 'M', u'ҏ'), + (0x48F, 'V'), + (0x490, 'M', u'ґ'), + (0x491, 'V'), + (0x492, 'M', u'ғ'), + (0x493, 'V'), + (0x494, 'M', u'ҕ'), + (0x495, 'V'), + (0x496, 'M', u'җ'), + (0x497, 'V'), + (0x498, 'M', u'ҙ'), + (0x499, 'V'), + (0x49A, 'M', u'қ'), + (0x49B, 'V'), + (0x49C, 'M', u'ҝ'), + (0x49D, 'V'), + ] + +def _seg_8(): + return [ + (0x49E, 'M', u'ҟ'), + (0x49F, 'V'), + (0x4A0, 'M', u'ҡ'), + (0x4A1, 'V'), + (0x4A2, 'M', u'ң'), + (0x4A3, 'V'), + (0x4A4, 'M', u'ҥ'), + (0x4A5, 'V'), + (0x4A6, 'M', u'ҧ'), + (0x4A7, 'V'), + (0x4A8, 'M', u'ҩ'), + (0x4A9, 'V'), + (0x4AA, 'M', u'ҫ'), + (0x4AB, 'V'), + (0x4AC, 'M', u'ҭ'), + (0x4AD, 'V'), + (0x4AE, 'M', u'ү'), + (0x4AF, 'V'), + (0x4B0, 'M', u'ұ'), + (0x4B1, 'V'), + (0x4B2, 'M', u'ҳ'), + (0x4B3, 'V'), + (0x4B4, 'M', u'ҵ'), + (0x4B5, 'V'), + (0x4B6, 'M', u'ҷ'), + (0x4B7, 'V'), + (0x4B8, 'M', u'ҹ'), + (0x4B9, 'V'), + (0x4BA, 'M', u'һ'), + (0x4BB, 'V'), + (0x4BC, 'M', u'ҽ'), + (0x4BD, 'V'), + (0x4BE, 'M', u'ҿ'), + (0x4BF, 'V'), + (0x4C0, 'X'), + (0x4C1, 'M', u'ӂ'), + (0x4C2, 'V'), + (0x4C3, 'M', u'ӄ'), + (0x4C4, 'V'), + (0x4C5, 'M', u'ӆ'), + (0x4C6, 'V'), + (0x4C7, 'M', u'ӈ'), + (0x4C8, 'V'), + (0x4C9, 'M', u'ӊ'), + (0x4CA, 'V'), + (0x4CB, 'M', u'ӌ'), + (0x4CC, 'V'), + (0x4CD, 'M', u'ӎ'), + (0x4CE, 'V'), + (0x4D0, 'M', u'ӑ'), + (0x4D1, 'V'), + (0x4D2, 'M', u'ӓ'), + (0x4D3, 'V'), + (0x4D4, 'M', u'ӕ'), + (0x4D5, 'V'), + (0x4D6, 'M', u'ӗ'), + (0x4D7, 'V'), + (0x4D8, 'M', u'ә'), + (0x4D9, 'V'), + (0x4DA, 'M', u'ӛ'), + (0x4DB, 'V'), + (0x4DC, 'M', u'ӝ'), + (0x4DD, 'V'), + (0x4DE, 'M', u'ӟ'), + (0x4DF, 'V'), + (0x4E0, 'M', u'ӡ'), + (0x4E1, 'V'), + (0x4E2, 'M', u'ӣ'), + (0x4E3, 'V'), + (0x4E4, 'M', u'ӥ'), + (0x4E5, 'V'), + (0x4E6, 'M', u'ӧ'), + (0x4E7, 'V'), + (0x4E8, 'M', u'ө'), + (0x4E9, 'V'), + (0x4EA, 'M', u'ӫ'), + (0x4EB, 'V'), + (0x4EC, 'M', u'ӭ'), + (0x4ED, 'V'), + (0x4EE, 'M', u'ӯ'), + (0x4EF, 'V'), + (0x4F0, 'M', u'ӱ'), + (0x4F1, 'V'), + (0x4F2, 'M', u'ӳ'), + (0x4F3, 'V'), + (0x4F4, 'M', u'ӵ'), + (0x4F5, 'V'), + (0x4F6, 'M', u'ӷ'), + (0x4F7, 'V'), + (0x4F8, 'M', u'ӹ'), + (0x4F9, 'V'), + (0x4FA, 'M', u'ӻ'), + (0x4FB, 'V'), + (0x4FC, 'M', u'ӽ'), + (0x4FD, 'V'), + (0x4FE, 'M', u'ӿ'), + (0x4FF, 'V'), + (0x500, 'M', u'ԁ'), + (0x501, 'V'), + (0x502, 'M', u'ԃ'), + ] + +def _seg_9(): + return [ + (0x503, 'V'), + (0x504, 'M', u'ԅ'), + (0x505, 'V'), + (0x506, 'M', u'ԇ'), + (0x507, 'V'), + (0x508, 'M', u'ԉ'), + (0x509, 'V'), + (0x50A, 'M', u'ԋ'), + (0x50B, 'V'), + (0x50C, 'M', u'ԍ'), + (0x50D, 'V'), + (0x50E, 'M', u'ԏ'), + (0x50F, 'V'), + (0x510, 'M', u'ԑ'), + (0x511, 'V'), + (0x512, 'M', u'ԓ'), + (0x513, 'V'), + (0x514, 'M', u'ԕ'), + (0x515, 'V'), + (0x516, 'M', u'ԗ'), + (0x517, 'V'), + (0x518, 'M', u'ԙ'), + (0x519, 'V'), + (0x51A, 'M', u'ԛ'), + (0x51B, 'V'), + (0x51C, 'M', u'ԝ'), + (0x51D, 'V'), + (0x51E, 'M', u'ԟ'), + (0x51F, 'V'), + (0x520, 'M', u'ԡ'), + (0x521, 'V'), + (0x522, 'M', u'ԣ'), + (0x523, 'V'), + (0x524, 'M', u'ԥ'), + (0x525, 'V'), + (0x526, 'M', u'ԧ'), + (0x527, 'V'), + (0x528, 'M', u'ԩ'), + (0x529, 'V'), + (0x52A, 'M', u'ԫ'), + (0x52B, 'V'), + (0x52C, 'M', u'ԭ'), + (0x52D, 'V'), + (0x52E, 'M', u'ԯ'), + (0x52F, 'V'), + (0x530, 'X'), + (0x531, 'M', u'ա'), + (0x532, 'M', u'բ'), + (0x533, 'M', u'գ'), + (0x534, 'M', u'դ'), + (0x535, 'M', u'ե'), + (0x536, 'M', u'զ'), + (0x537, 'M', u'է'), + (0x538, 'M', u'ը'), + (0x539, 'M', u'թ'), + (0x53A, 'M', u'ժ'), + (0x53B, 'M', u'ի'), + (0x53C, 'M', u'լ'), + (0x53D, 'M', u'խ'), + (0x53E, 'M', u'ծ'), + (0x53F, 'M', u'կ'), + (0x540, 'M', u'հ'), + (0x541, 'M', u'ձ'), + (0x542, 'M', u'ղ'), + (0x543, 'M', u'ճ'), + (0x544, 'M', u'մ'), + (0x545, 'M', u'յ'), + (0x546, 'M', u'ն'), + (0x547, 'M', u'շ'), + (0x548, 'M', u'ո'), + (0x549, 'M', u'չ'), + (0x54A, 'M', u'պ'), + (0x54B, 'M', u'ջ'), + (0x54C, 'M', u'ռ'), + (0x54D, 'M', u'ս'), + (0x54E, 'M', u'վ'), + (0x54F, 'M', u'տ'), + (0x550, 'M', u'ր'), + (0x551, 'M', u'ց'), + (0x552, 'M', u'ւ'), + (0x553, 'M', u'փ'), + (0x554, 'M', u'ք'), + (0x555, 'M', u'օ'), + (0x556, 'M', u'ֆ'), + (0x557, 'X'), + (0x559, 'V'), + (0x560, 'X'), + (0x561, 'V'), + (0x587, 'M', u'եւ'), + (0x588, 'X'), + (0x589, 'V'), + (0x58B, 'X'), + (0x58D, 'V'), + (0x590, 'X'), + (0x591, 'V'), + (0x5C8, 'X'), + (0x5D0, 'V'), + (0x5EB, 'X'), + (0x5F0, 'V'), + (0x5F5, 'X'), + ] + +def _seg_10(): + return [ + (0x606, 'V'), + (0x61C, 'X'), + (0x61E, 'V'), + (0x675, 'M', u'اٴ'), + (0x676, 'M', u'وٴ'), + (0x677, 'M', u'ۇٴ'), + (0x678, 'M', u'يٴ'), + (0x679, 'V'), + (0x6DD, 'X'), + (0x6DE, 'V'), + (0x70E, 'X'), + (0x710, 'V'), + (0x74B, 'X'), + (0x74D, 'V'), + (0x7B2, 'X'), + (0x7C0, 'V'), + (0x7FB, 'X'), + (0x800, 'V'), + (0x82E, 'X'), + (0x830, 'V'), + (0x83F, 'X'), + (0x840, 'V'), + (0x85C, 'X'), + (0x85E, 'V'), + (0x85F, 'X'), + (0x860, 'V'), + (0x86B, 'X'), + (0x8A0, 'V'), + (0x8B5, 'X'), + (0x8B6, 'V'), + (0x8BE, 'X'), + (0x8D4, 'V'), + (0x8E2, 'X'), + (0x8E3, 'V'), + (0x958, 'M', u'क़'), + (0x959, 'M', u'ख़'), + (0x95A, 'M', u'ग़'), + (0x95B, 'M', u'ज़'), + (0x95C, 'M', u'ड़'), + (0x95D, 'M', u'ढ़'), + (0x95E, 'M', u'फ़'), + (0x95F, 'M', u'य़'), + (0x960, 'V'), + (0x984, 'X'), + (0x985, 'V'), + (0x98D, 'X'), + (0x98F, 'V'), + (0x991, 'X'), + (0x993, 'V'), + (0x9A9, 'X'), + (0x9AA, 'V'), + (0x9B1, 'X'), + (0x9B2, 'V'), + (0x9B3, 'X'), + (0x9B6, 'V'), + (0x9BA, 'X'), + (0x9BC, 'V'), + (0x9C5, 'X'), + (0x9C7, 'V'), + (0x9C9, 'X'), + (0x9CB, 'V'), + (0x9CF, 'X'), + (0x9D7, 'V'), + (0x9D8, 'X'), + (0x9DC, 'M', u'ড়'), + (0x9DD, 'M', u'ঢ়'), + (0x9DE, 'X'), + (0x9DF, 'M', u'য়'), + (0x9E0, 'V'), + (0x9E4, 'X'), + (0x9E6, 'V'), + (0x9FE, 'X'), + (0xA01, 'V'), + (0xA04, 'X'), + (0xA05, 'V'), + (0xA0B, 'X'), + (0xA0F, 'V'), + (0xA11, 'X'), + (0xA13, 'V'), + (0xA29, 'X'), + (0xA2A, 'V'), + (0xA31, 'X'), + (0xA32, 'V'), + (0xA33, 'M', u'ਲ਼'), + (0xA34, 'X'), + (0xA35, 'V'), + (0xA36, 'M', u'ਸ਼'), + (0xA37, 'X'), + (0xA38, 'V'), + (0xA3A, 'X'), + (0xA3C, 'V'), + (0xA3D, 'X'), + (0xA3E, 'V'), + (0xA43, 'X'), + (0xA47, 'V'), + (0xA49, 'X'), + (0xA4B, 'V'), + (0xA4E, 'X'), + (0xA51, 'V'), + (0xA52, 'X'), + ] + +def _seg_11(): + return [ + (0xA59, 'M', u'ਖ਼'), + (0xA5A, 'M', u'ਗ਼'), + (0xA5B, 'M', u'ਜ਼'), + (0xA5C, 'V'), + (0xA5D, 'X'), + (0xA5E, 'M', u'ਫ਼'), + (0xA5F, 'X'), + (0xA66, 'V'), + (0xA76, 'X'), + (0xA81, 'V'), + (0xA84, 'X'), + (0xA85, 'V'), + (0xA8E, 'X'), + (0xA8F, 'V'), + (0xA92, 'X'), + (0xA93, 'V'), + (0xAA9, 'X'), + (0xAAA, 'V'), + (0xAB1, 'X'), + (0xAB2, 'V'), + (0xAB4, 'X'), + (0xAB5, 'V'), + (0xABA, 'X'), + (0xABC, 'V'), + (0xAC6, 'X'), + (0xAC7, 'V'), + (0xACA, 'X'), + (0xACB, 'V'), + (0xACE, 'X'), + (0xAD0, 'V'), + (0xAD1, 'X'), + (0xAE0, 'V'), + (0xAE4, 'X'), + (0xAE6, 'V'), + (0xAF2, 'X'), + (0xAF9, 'V'), + (0xB00, 'X'), + (0xB01, 'V'), + (0xB04, 'X'), + (0xB05, 'V'), + (0xB0D, 'X'), + (0xB0F, 'V'), + (0xB11, 'X'), + (0xB13, 'V'), + (0xB29, 'X'), + (0xB2A, 'V'), + (0xB31, 'X'), + (0xB32, 'V'), + (0xB34, 'X'), + (0xB35, 'V'), + (0xB3A, 'X'), + (0xB3C, 'V'), + (0xB45, 'X'), + (0xB47, 'V'), + (0xB49, 'X'), + (0xB4B, 'V'), + (0xB4E, 'X'), + (0xB56, 'V'), + (0xB58, 'X'), + (0xB5C, 'M', u'ଡ଼'), + (0xB5D, 'M', u'ଢ଼'), + (0xB5E, 'X'), + (0xB5F, 'V'), + (0xB64, 'X'), + (0xB66, 'V'), + (0xB78, 'X'), + (0xB82, 'V'), + (0xB84, 'X'), + (0xB85, 'V'), + (0xB8B, 'X'), + (0xB8E, 'V'), + (0xB91, 'X'), + (0xB92, 'V'), + (0xB96, 'X'), + (0xB99, 'V'), + (0xB9B, 'X'), + (0xB9C, 'V'), + (0xB9D, 'X'), + (0xB9E, 'V'), + (0xBA0, 'X'), + (0xBA3, 'V'), + (0xBA5, 'X'), + (0xBA8, 'V'), + (0xBAB, 'X'), + (0xBAE, 'V'), + (0xBBA, 'X'), + (0xBBE, 'V'), + (0xBC3, 'X'), + (0xBC6, 'V'), + (0xBC9, 'X'), + (0xBCA, 'V'), + (0xBCE, 'X'), + (0xBD0, 'V'), + (0xBD1, 'X'), + (0xBD7, 'V'), + (0xBD8, 'X'), + (0xBE6, 'V'), + (0xBFB, 'X'), + (0xC00, 'V'), + (0xC04, 'X'), + ] + +def _seg_12(): + return [ + (0xC05, 'V'), + (0xC0D, 'X'), + (0xC0E, 'V'), + (0xC11, 'X'), + (0xC12, 'V'), + (0xC29, 'X'), + (0xC2A, 'V'), + (0xC3A, 'X'), + (0xC3D, 'V'), + (0xC45, 'X'), + (0xC46, 'V'), + (0xC49, 'X'), + (0xC4A, 'V'), + (0xC4E, 'X'), + (0xC55, 'V'), + (0xC57, 'X'), + (0xC58, 'V'), + (0xC5B, 'X'), + (0xC60, 'V'), + (0xC64, 'X'), + (0xC66, 'V'), + (0xC70, 'X'), + (0xC78, 'V'), + (0xC84, 'X'), + (0xC85, 'V'), + (0xC8D, 'X'), + (0xC8E, 'V'), + (0xC91, 'X'), + (0xC92, 'V'), + (0xCA9, 'X'), + (0xCAA, 'V'), + (0xCB4, 'X'), + (0xCB5, 'V'), + (0xCBA, 'X'), + (0xCBC, 'V'), + (0xCC5, 'X'), + (0xCC6, 'V'), + (0xCC9, 'X'), + (0xCCA, 'V'), + (0xCCE, 'X'), + (0xCD5, 'V'), + (0xCD7, 'X'), + (0xCDE, 'V'), + (0xCDF, 'X'), + (0xCE0, 'V'), + (0xCE4, 'X'), + (0xCE6, 'V'), + (0xCF0, 'X'), + (0xCF1, 'V'), + (0xCF3, 'X'), + (0xD00, 'V'), + (0xD04, 'X'), + (0xD05, 'V'), + (0xD0D, 'X'), + (0xD0E, 'V'), + (0xD11, 'X'), + (0xD12, 'V'), + (0xD45, 'X'), + (0xD46, 'V'), + (0xD49, 'X'), + (0xD4A, 'V'), + (0xD50, 'X'), + (0xD54, 'V'), + (0xD64, 'X'), + (0xD66, 'V'), + (0xD80, 'X'), + (0xD82, 'V'), + (0xD84, 'X'), + (0xD85, 'V'), + (0xD97, 'X'), + (0xD9A, 'V'), + (0xDB2, 'X'), + (0xDB3, 'V'), + (0xDBC, 'X'), + (0xDBD, 'V'), + (0xDBE, 'X'), + (0xDC0, 'V'), + (0xDC7, 'X'), + (0xDCA, 'V'), + (0xDCB, 'X'), + (0xDCF, 'V'), + (0xDD5, 'X'), + (0xDD6, 'V'), + (0xDD7, 'X'), + (0xDD8, 'V'), + (0xDE0, 'X'), + (0xDE6, 'V'), + (0xDF0, 'X'), + (0xDF2, 'V'), + (0xDF5, 'X'), + (0xE01, 'V'), + (0xE33, 'M', u'ํา'), + (0xE34, 'V'), + (0xE3B, 'X'), + (0xE3F, 'V'), + (0xE5C, 'X'), + (0xE81, 'V'), + (0xE83, 'X'), + (0xE84, 'V'), + (0xE85, 'X'), + ] + +def _seg_13(): + return [ + (0xE87, 'V'), + (0xE89, 'X'), + (0xE8A, 'V'), + (0xE8B, 'X'), + (0xE8D, 'V'), + (0xE8E, 'X'), + (0xE94, 'V'), + (0xE98, 'X'), + (0xE99, 'V'), + (0xEA0, 'X'), + (0xEA1, 'V'), + (0xEA4, 'X'), + (0xEA5, 'V'), + (0xEA6, 'X'), + (0xEA7, 'V'), + (0xEA8, 'X'), + (0xEAA, 'V'), + (0xEAC, 'X'), + (0xEAD, 'V'), + (0xEB3, 'M', u'ໍາ'), + (0xEB4, 'V'), + (0xEBA, 'X'), + (0xEBB, 'V'), + (0xEBE, 'X'), + (0xEC0, 'V'), + (0xEC5, 'X'), + (0xEC6, 'V'), + (0xEC7, 'X'), + (0xEC8, 'V'), + (0xECE, 'X'), + (0xED0, 'V'), + (0xEDA, 'X'), + (0xEDC, 'M', u'ຫນ'), + (0xEDD, 'M', u'ຫມ'), + (0xEDE, 'V'), + (0xEE0, 'X'), + (0xF00, 'V'), + (0xF0C, 'M', u'་'), + (0xF0D, 'V'), + (0xF43, 'M', u'གྷ'), + (0xF44, 'V'), + (0xF48, 'X'), + (0xF49, 'V'), + (0xF4D, 'M', u'ཌྷ'), + (0xF4E, 'V'), + (0xF52, 'M', u'དྷ'), + (0xF53, 'V'), + (0xF57, 'M', u'བྷ'), + (0xF58, 'V'), + (0xF5C, 'M', u'ཛྷ'), + (0xF5D, 'V'), + (0xF69, 'M', u'ཀྵ'), + (0xF6A, 'V'), + (0xF6D, 'X'), + (0xF71, 'V'), + (0xF73, 'M', u'ཱི'), + (0xF74, 'V'), + (0xF75, 'M', u'ཱུ'), + (0xF76, 'M', u'ྲྀ'), + (0xF77, 'M', u'ྲཱྀ'), + (0xF78, 'M', u'ླྀ'), + (0xF79, 'M', u'ླཱྀ'), + (0xF7A, 'V'), + (0xF81, 'M', u'ཱྀ'), + (0xF82, 'V'), + (0xF93, 'M', u'ྒྷ'), + (0xF94, 'V'), + (0xF98, 'X'), + (0xF99, 'V'), + (0xF9D, 'M', u'ྜྷ'), + (0xF9E, 'V'), + (0xFA2, 'M', u'ྡྷ'), + (0xFA3, 'V'), + (0xFA7, 'M', u'ྦྷ'), + (0xFA8, 'V'), + (0xFAC, 'M', u'ྫྷ'), + (0xFAD, 'V'), + (0xFB9, 'M', u'ྐྵ'), + (0xFBA, 'V'), + (0xFBD, 'X'), + (0xFBE, 'V'), + (0xFCD, 'X'), + (0xFCE, 'V'), + (0xFDB, 'X'), + (0x1000, 'V'), + (0x10A0, 'X'), + (0x10C7, 'M', u'ⴧ'), + (0x10C8, 'X'), + (0x10CD, 'M', u'ⴭ'), + (0x10CE, 'X'), + (0x10D0, 'V'), + (0x10FC, 'M', u'ნ'), + (0x10FD, 'V'), + (0x115F, 'X'), + (0x1161, 'V'), + (0x1249, 'X'), + (0x124A, 'V'), + (0x124E, 'X'), + (0x1250, 'V'), + (0x1257, 'X'), + ] + +def _seg_14(): + return [ + (0x1258, 'V'), + (0x1259, 'X'), + (0x125A, 'V'), + (0x125E, 'X'), + (0x1260, 'V'), + (0x1289, 'X'), + (0x128A, 'V'), + (0x128E, 'X'), + (0x1290, 'V'), + (0x12B1, 'X'), + (0x12B2, 'V'), + (0x12B6, 'X'), + (0x12B8, 'V'), + (0x12BF, 'X'), + (0x12C0, 'V'), + (0x12C1, 'X'), + (0x12C2, 'V'), + (0x12C6, 'X'), + (0x12C8, 'V'), + (0x12D7, 'X'), + (0x12D8, 'V'), + (0x1311, 'X'), + (0x1312, 'V'), + (0x1316, 'X'), + (0x1318, 'V'), + (0x135B, 'X'), + (0x135D, 'V'), + (0x137D, 'X'), + (0x1380, 'V'), + (0x139A, 'X'), + (0x13A0, 'V'), + (0x13F6, 'X'), + (0x13F8, 'M', u'Ᏸ'), + (0x13F9, 'M', u'Ᏹ'), + (0x13FA, 'M', u'Ᏺ'), + (0x13FB, 'M', u'Ᏻ'), + (0x13FC, 'M', u'Ᏼ'), + (0x13FD, 'M', u'Ᏽ'), + (0x13FE, 'X'), + (0x1400, 'V'), + (0x1680, 'X'), + (0x1681, 'V'), + (0x169D, 'X'), + (0x16A0, 'V'), + (0x16F9, 'X'), + (0x1700, 'V'), + (0x170D, 'X'), + (0x170E, 'V'), + (0x1715, 'X'), + (0x1720, 'V'), + (0x1737, 'X'), + (0x1740, 'V'), + (0x1754, 'X'), + (0x1760, 'V'), + (0x176D, 'X'), + (0x176E, 'V'), + (0x1771, 'X'), + (0x1772, 'V'), + (0x1774, 'X'), + (0x1780, 'V'), + (0x17B4, 'X'), + (0x17B6, 'V'), + (0x17DE, 'X'), + (0x17E0, 'V'), + (0x17EA, 'X'), + (0x17F0, 'V'), + (0x17FA, 'X'), + (0x1800, 'V'), + (0x1806, 'X'), + (0x1807, 'V'), + (0x180B, 'I'), + (0x180E, 'X'), + (0x1810, 'V'), + (0x181A, 'X'), + (0x1820, 'V'), + (0x1878, 'X'), + (0x1880, 'V'), + (0x18AB, 'X'), + (0x18B0, 'V'), + (0x18F6, 'X'), + (0x1900, 'V'), + (0x191F, 'X'), + (0x1920, 'V'), + (0x192C, 'X'), + (0x1930, 'V'), + (0x193C, 'X'), + (0x1940, 'V'), + (0x1941, 'X'), + (0x1944, 'V'), + (0x196E, 'X'), + (0x1970, 'V'), + (0x1975, 'X'), + (0x1980, 'V'), + (0x19AC, 'X'), + (0x19B0, 'V'), + (0x19CA, 'X'), + (0x19D0, 'V'), + (0x19DB, 'X'), + (0x19DE, 'V'), + (0x1A1C, 'X'), + ] + +def _seg_15(): + return [ + (0x1A1E, 'V'), + (0x1A5F, 'X'), + (0x1A60, 'V'), + (0x1A7D, 'X'), + (0x1A7F, 'V'), + (0x1A8A, 'X'), + (0x1A90, 'V'), + (0x1A9A, 'X'), + (0x1AA0, 'V'), + (0x1AAE, 'X'), + (0x1AB0, 'V'), + (0x1ABF, 'X'), + (0x1B00, 'V'), + (0x1B4C, 'X'), + (0x1B50, 'V'), + (0x1B7D, 'X'), + (0x1B80, 'V'), + (0x1BF4, 'X'), + (0x1BFC, 'V'), + (0x1C38, 'X'), + (0x1C3B, 'V'), + (0x1C4A, 'X'), + (0x1C4D, 'V'), + (0x1C80, 'M', u'в'), + (0x1C81, 'M', u'д'), + (0x1C82, 'M', u'о'), + (0x1C83, 'M', u'с'), + (0x1C84, 'M', u'т'), + (0x1C86, 'M', u'ъ'), + (0x1C87, 'M', u'ѣ'), + (0x1C88, 'M', u'ꙋ'), + (0x1C89, 'X'), + (0x1CC0, 'V'), + (0x1CC8, 'X'), + (0x1CD0, 'V'), + (0x1CFA, 'X'), + (0x1D00, 'V'), + (0x1D2C, 'M', u'a'), + (0x1D2D, 'M', u'æ'), + (0x1D2E, 'M', u'b'), + (0x1D2F, 'V'), + (0x1D30, 'M', u'd'), + (0x1D31, 'M', u'e'), + (0x1D32, 'M', u'ǝ'), + (0x1D33, 'M', u'g'), + (0x1D34, 'M', u'h'), + (0x1D35, 'M', u'i'), + (0x1D36, 'M', u'j'), + (0x1D37, 'M', u'k'), + (0x1D38, 'M', u'l'), + (0x1D39, 'M', u'm'), + (0x1D3A, 'M', u'n'), + (0x1D3B, 'V'), + (0x1D3C, 'M', u'o'), + (0x1D3D, 'M', u'ȣ'), + (0x1D3E, 'M', u'p'), + (0x1D3F, 'M', u'r'), + (0x1D40, 'M', u't'), + (0x1D41, 'M', u'u'), + (0x1D42, 'M', u'w'), + (0x1D43, 'M', u'a'), + (0x1D44, 'M', u'ɐ'), + (0x1D45, 'M', u'ɑ'), + (0x1D46, 'M', u'ᴂ'), + (0x1D47, 'M', u'b'), + (0x1D48, 'M', u'd'), + (0x1D49, 'M', u'e'), + (0x1D4A, 'M', u'ə'), + (0x1D4B, 'M', u'ɛ'), + (0x1D4C, 'M', u'ɜ'), + (0x1D4D, 'M', u'g'), + (0x1D4E, 'V'), + (0x1D4F, 'M', u'k'), + (0x1D50, 'M', u'm'), + (0x1D51, 'M', u'ŋ'), + (0x1D52, 'M', u'o'), + (0x1D53, 'M', u'ɔ'), + (0x1D54, 'M', u'ᴖ'), + (0x1D55, 'M', u'ᴗ'), + (0x1D56, 'M', u'p'), + (0x1D57, 'M', u't'), + (0x1D58, 'M', u'u'), + (0x1D59, 'M', u'ᴝ'), + (0x1D5A, 'M', u'ɯ'), + (0x1D5B, 'M', u'v'), + (0x1D5C, 'M', u'ᴥ'), + (0x1D5D, 'M', u'β'), + (0x1D5E, 'M', u'γ'), + (0x1D5F, 'M', u'δ'), + (0x1D60, 'M', u'φ'), + (0x1D61, 'M', u'χ'), + (0x1D62, 'M', u'i'), + (0x1D63, 'M', u'r'), + (0x1D64, 'M', u'u'), + (0x1D65, 'M', u'v'), + (0x1D66, 'M', u'β'), + (0x1D67, 'M', u'γ'), + (0x1D68, 'M', u'ρ'), + (0x1D69, 'M', u'φ'), + (0x1D6A, 'M', u'χ'), + ] + +def _seg_16(): + return [ + (0x1D6B, 'V'), + (0x1D78, 'M', u'н'), + (0x1D79, 'V'), + (0x1D9B, 'M', u'ɒ'), + (0x1D9C, 'M', u'c'), + (0x1D9D, 'M', u'ɕ'), + (0x1D9E, 'M', u'ð'), + (0x1D9F, 'M', u'ɜ'), + (0x1DA0, 'M', u'f'), + (0x1DA1, 'M', u'ɟ'), + (0x1DA2, 'M', u'ɡ'), + (0x1DA3, 'M', u'ɥ'), + (0x1DA4, 'M', u'ɨ'), + (0x1DA5, 'M', u'ɩ'), + (0x1DA6, 'M', u'ɪ'), + (0x1DA7, 'M', u'ᵻ'), + (0x1DA8, 'M', u'ʝ'), + (0x1DA9, 'M', u'ɭ'), + (0x1DAA, 'M', u'ᶅ'), + (0x1DAB, 'M', u'ʟ'), + (0x1DAC, 'M', u'ɱ'), + (0x1DAD, 'M', u'ɰ'), + (0x1DAE, 'M', u'ɲ'), + (0x1DAF, 'M', u'ɳ'), + (0x1DB0, 'M', u'ɴ'), + (0x1DB1, 'M', u'ɵ'), + (0x1DB2, 'M', u'ɸ'), + (0x1DB3, 'M', u'ʂ'), + (0x1DB4, 'M', u'ʃ'), + (0x1DB5, 'M', u'ƫ'), + (0x1DB6, 'M', u'ʉ'), + (0x1DB7, 'M', u'ʊ'), + (0x1DB8, 'M', u'ᴜ'), + (0x1DB9, 'M', u'ʋ'), + (0x1DBA, 'M', u'ʌ'), + (0x1DBB, 'M', u'z'), + (0x1DBC, 'M', u'ʐ'), + (0x1DBD, 'M', u'ʑ'), + (0x1DBE, 'M', u'ʒ'), + (0x1DBF, 'M', u'θ'), + (0x1DC0, 'V'), + (0x1DFA, 'X'), + (0x1DFB, 'V'), + (0x1E00, 'M', u'ḁ'), + (0x1E01, 'V'), + (0x1E02, 'M', u'ḃ'), + (0x1E03, 'V'), + (0x1E04, 'M', u'ḅ'), + (0x1E05, 'V'), + (0x1E06, 'M', u'ḇ'), + (0x1E07, 'V'), + (0x1E08, 'M', u'ḉ'), + (0x1E09, 'V'), + (0x1E0A, 'M', u'ḋ'), + (0x1E0B, 'V'), + (0x1E0C, 'M', u'ḍ'), + (0x1E0D, 'V'), + (0x1E0E, 'M', u'ḏ'), + (0x1E0F, 'V'), + (0x1E10, 'M', u'ḑ'), + (0x1E11, 'V'), + (0x1E12, 'M', u'ḓ'), + (0x1E13, 'V'), + (0x1E14, 'M', u'ḕ'), + (0x1E15, 'V'), + (0x1E16, 'M', u'ḗ'), + (0x1E17, 'V'), + (0x1E18, 'M', u'ḙ'), + (0x1E19, 'V'), + (0x1E1A, 'M', u'ḛ'), + (0x1E1B, 'V'), + (0x1E1C, 'M', u'ḝ'), + (0x1E1D, 'V'), + (0x1E1E, 'M', u'ḟ'), + (0x1E1F, 'V'), + (0x1E20, 'M', u'ḡ'), + (0x1E21, 'V'), + (0x1E22, 'M', u'ḣ'), + (0x1E23, 'V'), + (0x1E24, 'M', u'ḥ'), + (0x1E25, 'V'), + (0x1E26, 'M', u'ḧ'), + (0x1E27, 'V'), + (0x1E28, 'M', u'ḩ'), + (0x1E29, 'V'), + (0x1E2A, 'M', u'ḫ'), + (0x1E2B, 'V'), + (0x1E2C, 'M', u'ḭ'), + (0x1E2D, 'V'), + (0x1E2E, 'M', u'ḯ'), + (0x1E2F, 'V'), + (0x1E30, 'M', u'ḱ'), + (0x1E31, 'V'), + (0x1E32, 'M', u'ḳ'), + (0x1E33, 'V'), + (0x1E34, 'M', u'ḵ'), + (0x1E35, 'V'), + (0x1E36, 'M', u'ḷ'), + (0x1E37, 'V'), + (0x1E38, 'M', u'ḹ'), + ] + +def _seg_17(): + return [ + (0x1E39, 'V'), + (0x1E3A, 'M', u'ḻ'), + (0x1E3B, 'V'), + (0x1E3C, 'M', u'ḽ'), + (0x1E3D, 'V'), + (0x1E3E, 'M', u'ḿ'), + (0x1E3F, 'V'), + (0x1E40, 'M', u'ṁ'), + (0x1E41, 'V'), + (0x1E42, 'M', u'ṃ'), + (0x1E43, 'V'), + (0x1E44, 'M', u'ṅ'), + (0x1E45, 'V'), + (0x1E46, 'M', u'ṇ'), + (0x1E47, 'V'), + (0x1E48, 'M', u'ṉ'), + (0x1E49, 'V'), + (0x1E4A, 'M', u'ṋ'), + (0x1E4B, 'V'), + (0x1E4C, 'M', u'ṍ'), + (0x1E4D, 'V'), + (0x1E4E, 'M', u'ṏ'), + (0x1E4F, 'V'), + (0x1E50, 'M', u'ṑ'), + (0x1E51, 'V'), + (0x1E52, 'M', u'ṓ'), + (0x1E53, 'V'), + (0x1E54, 'M', u'ṕ'), + (0x1E55, 'V'), + (0x1E56, 'M', u'ṗ'), + (0x1E57, 'V'), + (0x1E58, 'M', u'ṙ'), + (0x1E59, 'V'), + (0x1E5A, 'M', u'ṛ'), + (0x1E5B, 'V'), + (0x1E5C, 'M', u'ṝ'), + (0x1E5D, 'V'), + (0x1E5E, 'M', u'ṟ'), + (0x1E5F, 'V'), + (0x1E60, 'M', u'ṡ'), + (0x1E61, 'V'), + (0x1E62, 'M', u'ṣ'), + (0x1E63, 'V'), + (0x1E64, 'M', u'ṥ'), + (0x1E65, 'V'), + (0x1E66, 'M', u'ṧ'), + (0x1E67, 'V'), + (0x1E68, 'M', u'ṩ'), + (0x1E69, 'V'), + (0x1E6A, 'M', u'ṫ'), + (0x1E6B, 'V'), + (0x1E6C, 'M', u'ṭ'), + (0x1E6D, 'V'), + (0x1E6E, 'M', u'ṯ'), + (0x1E6F, 'V'), + (0x1E70, 'M', u'ṱ'), + (0x1E71, 'V'), + (0x1E72, 'M', u'ṳ'), + (0x1E73, 'V'), + (0x1E74, 'M', u'ṵ'), + (0x1E75, 'V'), + (0x1E76, 'M', u'ṷ'), + (0x1E77, 'V'), + (0x1E78, 'M', u'ṹ'), + (0x1E79, 'V'), + (0x1E7A, 'M', u'ṻ'), + (0x1E7B, 'V'), + (0x1E7C, 'M', u'ṽ'), + (0x1E7D, 'V'), + (0x1E7E, 'M', u'ṿ'), + (0x1E7F, 'V'), + (0x1E80, 'M', u'ẁ'), + (0x1E81, 'V'), + (0x1E82, 'M', u'ẃ'), + (0x1E83, 'V'), + (0x1E84, 'M', u'ẅ'), + (0x1E85, 'V'), + (0x1E86, 'M', u'ẇ'), + (0x1E87, 'V'), + (0x1E88, 'M', u'ẉ'), + (0x1E89, 'V'), + (0x1E8A, 'M', u'ẋ'), + (0x1E8B, 'V'), + (0x1E8C, 'M', u'ẍ'), + (0x1E8D, 'V'), + (0x1E8E, 'M', u'ẏ'), + (0x1E8F, 'V'), + (0x1E90, 'M', u'ẑ'), + (0x1E91, 'V'), + (0x1E92, 'M', u'ẓ'), + (0x1E93, 'V'), + (0x1E94, 'M', u'ẕ'), + (0x1E95, 'V'), + (0x1E9A, 'M', u'aʾ'), + (0x1E9B, 'M', u'ṡ'), + (0x1E9C, 'V'), + (0x1E9E, 'M', u'ss'), + (0x1E9F, 'V'), + (0x1EA0, 'M', u'ạ'), + (0x1EA1, 'V'), + ] + +def _seg_18(): + return [ + (0x1EA2, 'M', u'ả'), + (0x1EA3, 'V'), + (0x1EA4, 'M', u'ấ'), + (0x1EA5, 'V'), + (0x1EA6, 'M', u'ầ'), + (0x1EA7, 'V'), + (0x1EA8, 'M', u'ẩ'), + (0x1EA9, 'V'), + (0x1EAA, 'M', u'ẫ'), + (0x1EAB, 'V'), + (0x1EAC, 'M', u'ậ'), + (0x1EAD, 'V'), + (0x1EAE, 'M', u'ắ'), + (0x1EAF, 'V'), + (0x1EB0, 'M', u'ằ'), + (0x1EB1, 'V'), + (0x1EB2, 'M', u'ẳ'), + (0x1EB3, 'V'), + (0x1EB4, 'M', u'ẵ'), + (0x1EB5, 'V'), + (0x1EB6, 'M', u'ặ'), + (0x1EB7, 'V'), + (0x1EB8, 'M', u'ẹ'), + (0x1EB9, 'V'), + (0x1EBA, 'M', u'ẻ'), + (0x1EBB, 'V'), + (0x1EBC, 'M', u'ẽ'), + (0x1EBD, 'V'), + (0x1EBE, 'M', u'ế'), + (0x1EBF, 'V'), + (0x1EC0, 'M', u'ề'), + (0x1EC1, 'V'), + (0x1EC2, 'M', u'ể'), + (0x1EC3, 'V'), + (0x1EC4, 'M', u'ễ'), + (0x1EC5, 'V'), + (0x1EC6, 'M', u'ệ'), + (0x1EC7, 'V'), + (0x1EC8, 'M', u'ỉ'), + (0x1EC9, 'V'), + (0x1ECA, 'M', u'ị'), + (0x1ECB, 'V'), + (0x1ECC, 'M', u'ọ'), + (0x1ECD, 'V'), + (0x1ECE, 'M', u'ỏ'), + (0x1ECF, 'V'), + (0x1ED0, 'M', u'ố'), + (0x1ED1, 'V'), + (0x1ED2, 'M', u'ồ'), + (0x1ED3, 'V'), + (0x1ED4, 'M', u'ổ'), + (0x1ED5, 'V'), + (0x1ED6, 'M', u'ỗ'), + (0x1ED7, 'V'), + (0x1ED8, 'M', u'ộ'), + (0x1ED9, 'V'), + (0x1EDA, 'M', u'ớ'), + (0x1EDB, 'V'), + (0x1EDC, 'M', u'ờ'), + (0x1EDD, 'V'), + (0x1EDE, 'M', u'ở'), + (0x1EDF, 'V'), + (0x1EE0, 'M', u'ỡ'), + (0x1EE1, 'V'), + (0x1EE2, 'M', u'ợ'), + (0x1EE3, 'V'), + (0x1EE4, 'M', u'ụ'), + (0x1EE5, 'V'), + (0x1EE6, 'M', u'ủ'), + (0x1EE7, 'V'), + (0x1EE8, 'M', u'ứ'), + (0x1EE9, 'V'), + (0x1EEA, 'M', u'ừ'), + (0x1EEB, 'V'), + (0x1EEC, 'M', u'ử'), + (0x1EED, 'V'), + (0x1EEE, 'M', u'ữ'), + (0x1EEF, 'V'), + (0x1EF0, 'M', u'ự'), + (0x1EF1, 'V'), + (0x1EF2, 'M', u'ỳ'), + (0x1EF3, 'V'), + (0x1EF4, 'M', u'ỵ'), + (0x1EF5, 'V'), + (0x1EF6, 'M', u'ỷ'), + (0x1EF7, 'V'), + (0x1EF8, 'M', u'ỹ'), + (0x1EF9, 'V'), + (0x1EFA, 'M', u'ỻ'), + (0x1EFB, 'V'), + (0x1EFC, 'M', u'ỽ'), + (0x1EFD, 'V'), + (0x1EFE, 'M', u'ỿ'), + (0x1EFF, 'V'), + (0x1F08, 'M', u'ἀ'), + (0x1F09, 'M', u'ἁ'), + (0x1F0A, 'M', u'ἂ'), + (0x1F0B, 'M', u'ἃ'), + (0x1F0C, 'M', u'ἄ'), + (0x1F0D, 'M', u'ἅ'), + ] + +def _seg_19(): + return [ + (0x1F0E, 'M', u'ἆ'), + (0x1F0F, 'M', u'ἇ'), + (0x1F10, 'V'), + (0x1F16, 'X'), + (0x1F18, 'M', u'ἐ'), + (0x1F19, 'M', u'ἑ'), + (0x1F1A, 'M', u'ἒ'), + (0x1F1B, 'M', u'ἓ'), + (0x1F1C, 'M', u'ἔ'), + (0x1F1D, 'M', u'ἕ'), + (0x1F1E, 'X'), + (0x1F20, 'V'), + (0x1F28, 'M', u'ἠ'), + (0x1F29, 'M', u'ἡ'), + (0x1F2A, 'M', u'ἢ'), + (0x1F2B, 'M', u'ἣ'), + (0x1F2C, 'M', u'ἤ'), + (0x1F2D, 'M', u'ἥ'), + (0x1F2E, 'M', u'ἦ'), + (0x1F2F, 'M', u'ἧ'), + (0x1F30, 'V'), + (0x1F38, 'M', u'ἰ'), + (0x1F39, 'M', u'ἱ'), + (0x1F3A, 'M', u'ἲ'), + (0x1F3B, 'M', u'ἳ'), + (0x1F3C, 'M', u'ἴ'), + (0x1F3D, 'M', u'ἵ'), + (0x1F3E, 'M', u'ἶ'), + (0x1F3F, 'M', u'ἷ'), + (0x1F40, 'V'), + (0x1F46, 'X'), + (0x1F48, 'M', u'ὀ'), + (0x1F49, 'M', u'ὁ'), + (0x1F4A, 'M', u'ὂ'), + (0x1F4B, 'M', u'ὃ'), + (0x1F4C, 'M', u'ὄ'), + (0x1F4D, 'M', u'ὅ'), + (0x1F4E, 'X'), + (0x1F50, 'V'), + (0x1F58, 'X'), + (0x1F59, 'M', u'ὑ'), + (0x1F5A, 'X'), + (0x1F5B, 'M', u'ὓ'), + (0x1F5C, 'X'), + (0x1F5D, 'M', u'ὕ'), + (0x1F5E, 'X'), + (0x1F5F, 'M', u'ὗ'), + (0x1F60, 'V'), + (0x1F68, 'M', u'ὠ'), + (0x1F69, 'M', u'ὡ'), + (0x1F6A, 'M', u'ὢ'), + (0x1F6B, 'M', u'ὣ'), + (0x1F6C, 'M', u'ὤ'), + (0x1F6D, 'M', u'ὥ'), + (0x1F6E, 'M', u'ὦ'), + (0x1F6F, 'M', u'ὧ'), + (0x1F70, 'V'), + (0x1F71, 'M', u'ά'), + (0x1F72, 'V'), + (0x1F73, 'M', u'έ'), + (0x1F74, 'V'), + (0x1F75, 'M', u'ή'), + (0x1F76, 'V'), + (0x1F77, 'M', u'ί'), + (0x1F78, 'V'), + (0x1F79, 'M', u'ό'), + (0x1F7A, 'V'), + (0x1F7B, 'M', u'ύ'), + (0x1F7C, 'V'), + (0x1F7D, 'M', u'ώ'), + (0x1F7E, 'X'), + (0x1F80, 'M', u'ἀι'), + (0x1F81, 'M', u'ἁι'), + (0x1F82, 'M', u'ἂι'), + (0x1F83, 'M', u'ἃι'), + (0x1F84, 'M', u'ἄι'), + (0x1F85, 'M', u'ἅι'), + (0x1F86, 'M', u'ἆι'), + (0x1F87, 'M', u'ἇι'), + (0x1F88, 'M', u'ἀι'), + (0x1F89, 'M', u'ἁι'), + (0x1F8A, 'M', u'ἂι'), + (0x1F8B, 'M', u'ἃι'), + (0x1F8C, 'M', u'ἄι'), + (0x1F8D, 'M', u'ἅι'), + (0x1F8E, 'M', u'ἆι'), + (0x1F8F, 'M', u'ἇι'), + (0x1F90, 'M', u'ἠι'), + (0x1F91, 'M', u'ἡι'), + (0x1F92, 'M', u'ἢι'), + (0x1F93, 'M', u'ἣι'), + (0x1F94, 'M', u'ἤι'), + (0x1F95, 'M', u'ἥι'), + (0x1F96, 'M', u'ἦι'), + (0x1F97, 'M', u'ἧι'), + (0x1F98, 'M', u'ἠι'), + (0x1F99, 'M', u'ἡι'), + (0x1F9A, 'M', u'ἢι'), + (0x1F9B, 'M', u'ἣι'), + (0x1F9C, 'M', u'ἤι'), + ] + +def _seg_20(): + return [ + (0x1F9D, 'M', u'ἥι'), + (0x1F9E, 'M', u'ἦι'), + (0x1F9F, 'M', u'ἧι'), + (0x1FA0, 'M', u'ὠι'), + (0x1FA1, 'M', u'ὡι'), + (0x1FA2, 'M', u'ὢι'), + (0x1FA3, 'M', u'ὣι'), + (0x1FA4, 'M', u'ὤι'), + (0x1FA5, 'M', u'ὥι'), + (0x1FA6, 'M', u'ὦι'), + (0x1FA7, 'M', u'ὧι'), + (0x1FA8, 'M', u'ὠι'), + (0x1FA9, 'M', u'ὡι'), + (0x1FAA, 'M', u'ὢι'), + (0x1FAB, 'M', u'ὣι'), + (0x1FAC, 'M', u'ὤι'), + (0x1FAD, 'M', u'ὥι'), + (0x1FAE, 'M', u'ὦι'), + (0x1FAF, 'M', u'ὧι'), + (0x1FB0, 'V'), + (0x1FB2, 'M', u'ὰι'), + (0x1FB3, 'M', u'αι'), + (0x1FB4, 'M', u'άι'), + (0x1FB5, 'X'), + (0x1FB6, 'V'), + (0x1FB7, 'M', u'ᾶι'), + (0x1FB8, 'M', u'ᾰ'), + (0x1FB9, 'M', u'ᾱ'), + (0x1FBA, 'M', u'ὰ'), + (0x1FBB, 'M', u'ά'), + (0x1FBC, 'M', u'αι'), + (0x1FBD, '3', u' ̓'), + (0x1FBE, 'M', u'ι'), + (0x1FBF, '3', u' ̓'), + (0x1FC0, '3', u' ͂'), + (0x1FC1, '3', u' ̈͂'), + (0x1FC2, 'M', u'ὴι'), + (0x1FC3, 'M', u'ηι'), + (0x1FC4, 'M', u'ήι'), + (0x1FC5, 'X'), + (0x1FC6, 'V'), + (0x1FC7, 'M', u'ῆι'), + (0x1FC8, 'M', u'ὲ'), + (0x1FC9, 'M', u'έ'), + (0x1FCA, 'M', u'ὴ'), + (0x1FCB, 'M', u'ή'), + (0x1FCC, 'M', u'ηι'), + (0x1FCD, '3', u' ̓̀'), + (0x1FCE, '3', u' ̓́'), + (0x1FCF, '3', u' ̓͂'), + (0x1FD0, 'V'), + (0x1FD3, 'M', u'ΐ'), + (0x1FD4, 'X'), + (0x1FD6, 'V'), + (0x1FD8, 'M', u'ῐ'), + (0x1FD9, 'M', u'ῑ'), + (0x1FDA, 'M', u'ὶ'), + (0x1FDB, 'M', u'ί'), + (0x1FDC, 'X'), + (0x1FDD, '3', u' ̔̀'), + (0x1FDE, '3', u' ̔́'), + (0x1FDF, '3', u' ̔͂'), + (0x1FE0, 'V'), + (0x1FE3, 'M', u'ΰ'), + (0x1FE4, 'V'), + (0x1FE8, 'M', u'ῠ'), + (0x1FE9, 'M', u'ῡ'), + (0x1FEA, 'M', u'ὺ'), + (0x1FEB, 'M', u'ύ'), + (0x1FEC, 'M', u'ῥ'), + (0x1FED, '3', u' ̈̀'), + (0x1FEE, '3', u' ̈́'), + (0x1FEF, '3', u'`'), + (0x1FF0, 'X'), + (0x1FF2, 'M', u'ὼι'), + (0x1FF3, 'M', u'ωι'), + (0x1FF4, 'M', u'ώι'), + (0x1FF5, 'X'), + (0x1FF6, 'V'), + (0x1FF7, 'M', u'ῶι'), + (0x1FF8, 'M', u'ὸ'), + (0x1FF9, 'M', u'ό'), + (0x1FFA, 'M', u'ὼ'), + (0x1FFB, 'M', u'ώ'), + (0x1FFC, 'M', u'ωι'), + (0x1FFD, '3', u' ́'), + (0x1FFE, '3', u' ̔'), + (0x1FFF, 'X'), + (0x2000, '3', u' '), + (0x200B, 'I'), + (0x200C, 'D', u''), + (0x200E, 'X'), + (0x2010, 'V'), + (0x2011, 'M', u'‐'), + (0x2012, 'V'), + (0x2017, '3', u' ̳'), + (0x2018, 'V'), + (0x2024, 'X'), + (0x2027, 'V'), + (0x2028, 'X'), + ] + +def _seg_21(): + return [ + (0x202F, '3', u' '), + (0x2030, 'V'), + (0x2033, 'M', u'′′'), + (0x2034, 'M', u'′′′'), + (0x2035, 'V'), + (0x2036, 'M', u'‵‵'), + (0x2037, 'M', u'‵‵‵'), + (0x2038, 'V'), + (0x203C, '3', u'!!'), + (0x203D, 'V'), + (0x203E, '3', u' ̅'), + (0x203F, 'V'), + (0x2047, '3', u'??'), + (0x2048, '3', u'?!'), + (0x2049, '3', u'!?'), + (0x204A, 'V'), + (0x2057, 'M', u'′′′′'), + (0x2058, 'V'), + (0x205F, '3', u' '), + (0x2060, 'I'), + (0x2061, 'X'), + (0x2064, 'I'), + (0x2065, 'X'), + (0x2070, 'M', u'0'), + (0x2071, 'M', u'i'), + (0x2072, 'X'), + (0x2074, 'M', u'4'), + (0x2075, 'M', u'5'), + (0x2076, 'M', u'6'), + (0x2077, 'M', u'7'), + (0x2078, 'M', u'8'), + (0x2079, 'M', u'9'), + (0x207A, '3', u'+'), + (0x207B, 'M', u'−'), + (0x207C, '3', u'='), + (0x207D, '3', u'('), + (0x207E, '3', u')'), + (0x207F, 'M', u'n'), + (0x2080, 'M', u'0'), + (0x2081, 'M', u'1'), + (0x2082, 'M', u'2'), + (0x2083, 'M', u'3'), + (0x2084, 'M', u'4'), + (0x2085, 'M', u'5'), + (0x2086, 'M', u'6'), + (0x2087, 'M', u'7'), + (0x2088, 'M', u'8'), + (0x2089, 'M', u'9'), + (0x208A, '3', u'+'), + (0x208B, 'M', u'−'), + (0x208C, '3', u'='), + (0x208D, '3', u'('), + (0x208E, '3', u')'), + (0x208F, 'X'), + (0x2090, 'M', u'a'), + (0x2091, 'M', u'e'), + (0x2092, 'M', u'o'), + (0x2093, 'M', u'x'), + (0x2094, 'M', u'ə'), + (0x2095, 'M', u'h'), + (0x2096, 'M', u'k'), + (0x2097, 'M', u'l'), + (0x2098, 'M', u'm'), + (0x2099, 'M', u'n'), + (0x209A, 'M', u'p'), + (0x209B, 'M', u's'), + (0x209C, 'M', u't'), + (0x209D, 'X'), + (0x20A0, 'V'), + (0x20A8, 'M', u'rs'), + (0x20A9, 'V'), + (0x20C0, 'X'), + (0x20D0, 'V'), + (0x20F1, 'X'), + (0x2100, '3', u'a/c'), + (0x2101, '3', u'a/s'), + (0x2102, 'M', u'c'), + (0x2103, 'M', u'°c'), + (0x2104, 'V'), + (0x2105, '3', u'c/o'), + (0x2106, '3', u'c/u'), + (0x2107, 'M', u'ɛ'), + (0x2108, 'V'), + (0x2109, 'M', u'°f'), + (0x210A, 'M', u'g'), + (0x210B, 'M', u'h'), + (0x210F, 'M', u'ħ'), + (0x2110, 'M', u'i'), + (0x2112, 'M', u'l'), + (0x2114, 'V'), + (0x2115, 'M', u'n'), + (0x2116, 'M', u'no'), + (0x2117, 'V'), + (0x2119, 'M', u'p'), + (0x211A, 'M', u'q'), + (0x211B, 'M', u'r'), + (0x211E, 'V'), + (0x2120, 'M', u'sm'), + (0x2121, 'M', u'tel'), + (0x2122, 'M', u'tm'), + ] + +def _seg_22(): + return [ + (0x2123, 'V'), + (0x2124, 'M', u'z'), + (0x2125, 'V'), + (0x2126, 'M', u'ω'), + (0x2127, 'V'), + (0x2128, 'M', u'z'), + (0x2129, 'V'), + (0x212A, 'M', u'k'), + (0x212B, 'M', u'å'), + (0x212C, 'M', u'b'), + (0x212D, 'M', u'c'), + (0x212E, 'V'), + (0x212F, 'M', u'e'), + (0x2131, 'M', u'f'), + (0x2132, 'X'), + (0x2133, 'M', u'm'), + (0x2134, 'M', u'o'), + (0x2135, 'M', u'א'), + (0x2136, 'M', u'ב'), + (0x2137, 'M', u'ג'), + (0x2138, 'M', u'ד'), + (0x2139, 'M', u'i'), + (0x213A, 'V'), + (0x213B, 'M', u'fax'), + (0x213C, 'M', u'π'), + (0x213D, 'M', u'γ'), + (0x213F, 'M', u'π'), + (0x2140, 'M', u'∑'), + (0x2141, 'V'), + (0x2145, 'M', u'd'), + (0x2147, 'M', u'e'), + (0x2148, 'M', u'i'), + (0x2149, 'M', u'j'), + (0x214A, 'V'), + (0x2150, 'M', u'1⁄7'), + (0x2151, 'M', u'1⁄9'), + (0x2152, 'M', u'1⁄10'), + (0x2153, 'M', u'1⁄3'), + (0x2154, 'M', u'2⁄3'), + (0x2155, 'M', u'1⁄5'), + (0x2156, 'M', u'2⁄5'), + (0x2157, 'M', u'3⁄5'), + (0x2158, 'M', u'4⁄5'), + (0x2159, 'M', u'1⁄6'), + (0x215A, 'M', u'5⁄6'), + (0x215B, 'M', u'1⁄8'), + (0x215C, 'M', u'3⁄8'), + (0x215D, 'M', u'5⁄8'), + (0x215E, 'M', u'7⁄8'), + (0x215F, 'M', u'1⁄'), + (0x2160, 'M', u'i'), + (0x2161, 'M', u'ii'), + (0x2162, 'M', u'iii'), + (0x2163, 'M', u'iv'), + (0x2164, 'M', u'v'), + (0x2165, 'M', u'vi'), + (0x2166, 'M', u'vii'), + (0x2167, 'M', u'viii'), + (0x2168, 'M', u'ix'), + (0x2169, 'M', u'x'), + (0x216A, 'M', u'xi'), + (0x216B, 'M', u'xii'), + (0x216C, 'M', u'l'), + (0x216D, 'M', u'c'), + (0x216E, 'M', u'd'), + (0x216F, 'M', u'm'), + (0x2170, 'M', u'i'), + (0x2171, 'M', u'ii'), + (0x2172, 'M', u'iii'), + (0x2173, 'M', u'iv'), + (0x2174, 'M', u'v'), + (0x2175, 'M', u'vi'), + (0x2176, 'M', u'vii'), + (0x2177, 'M', u'viii'), + (0x2178, 'M', u'ix'), + (0x2179, 'M', u'x'), + (0x217A, 'M', u'xi'), + (0x217B, 'M', u'xii'), + (0x217C, 'M', u'l'), + (0x217D, 'M', u'c'), + (0x217E, 'M', u'd'), + (0x217F, 'M', u'm'), + (0x2180, 'V'), + (0x2183, 'X'), + (0x2184, 'V'), + (0x2189, 'M', u'0⁄3'), + (0x218A, 'V'), + (0x218C, 'X'), + (0x2190, 'V'), + (0x222C, 'M', u'∫∫'), + (0x222D, 'M', u'∫∫∫'), + (0x222E, 'V'), + (0x222F, 'M', u'∮∮'), + (0x2230, 'M', u'∮∮∮'), + (0x2231, 'V'), + (0x2260, '3'), + (0x2261, 'V'), + (0x226E, '3'), + (0x2270, 'V'), + (0x2329, 'M', u'〈'), + ] + +def _seg_23(): + return [ + (0x232A, 'M', u'〉'), + (0x232B, 'V'), + (0x2427, 'X'), + (0x2440, 'V'), + (0x244B, 'X'), + (0x2460, 'M', u'1'), + (0x2461, 'M', u'2'), + (0x2462, 'M', u'3'), + (0x2463, 'M', u'4'), + (0x2464, 'M', u'5'), + (0x2465, 'M', u'6'), + (0x2466, 'M', u'7'), + (0x2467, 'M', u'8'), + (0x2468, 'M', u'9'), + (0x2469, 'M', u'10'), + (0x246A, 'M', u'11'), + (0x246B, 'M', u'12'), + (0x246C, 'M', u'13'), + (0x246D, 'M', u'14'), + (0x246E, 'M', u'15'), + (0x246F, 'M', u'16'), + (0x2470, 'M', u'17'), + (0x2471, 'M', u'18'), + (0x2472, 'M', u'19'), + (0x2473, 'M', u'20'), + (0x2474, '3', u'(1)'), + (0x2475, '3', u'(2)'), + (0x2476, '3', u'(3)'), + (0x2477, '3', u'(4)'), + (0x2478, '3', u'(5)'), + (0x2479, '3', u'(6)'), + (0x247A, '3', u'(7)'), + (0x247B, '3', u'(8)'), + (0x247C, '3', u'(9)'), + (0x247D, '3', u'(10)'), + (0x247E, '3', u'(11)'), + (0x247F, '3', u'(12)'), + (0x2480, '3', u'(13)'), + (0x2481, '3', u'(14)'), + (0x2482, '3', u'(15)'), + (0x2483, '3', u'(16)'), + (0x2484, '3', u'(17)'), + (0x2485, '3', u'(18)'), + (0x2486, '3', u'(19)'), + (0x2487, '3', u'(20)'), + (0x2488, 'X'), + (0x249C, '3', u'(a)'), + (0x249D, '3', u'(b)'), + (0x249E, '3', u'(c)'), + (0x249F, '3', u'(d)'), + (0x24A0, '3', u'(e)'), + (0x24A1, '3', u'(f)'), + (0x24A2, '3', u'(g)'), + (0x24A3, '3', u'(h)'), + (0x24A4, '3', u'(i)'), + (0x24A5, '3', u'(j)'), + (0x24A6, '3', u'(k)'), + (0x24A7, '3', u'(l)'), + (0x24A8, '3', u'(m)'), + (0x24A9, '3', u'(n)'), + (0x24AA, '3', u'(o)'), + (0x24AB, '3', u'(p)'), + (0x24AC, '3', u'(q)'), + (0x24AD, '3', u'(r)'), + (0x24AE, '3', u'(s)'), + (0x24AF, '3', u'(t)'), + (0x24B0, '3', u'(u)'), + (0x24B1, '3', u'(v)'), + (0x24B2, '3', u'(w)'), + (0x24B3, '3', u'(x)'), + (0x24B4, '3', u'(y)'), + (0x24B5, '3', u'(z)'), + (0x24B6, 'M', u'a'), + (0x24B7, 'M', u'b'), + (0x24B8, 'M', u'c'), + (0x24B9, 'M', u'd'), + (0x24BA, 'M', u'e'), + (0x24BB, 'M', u'f'), + (0x24BC, 'M', u'g'), + (0x24BD, 'M', u'h'), + (0x24BE, 'M', u'i'), + (0x24BF, 'M', u'j'), + (0x24C0, 'M', u'k'), + (0x24C1, 'M', u'l'), + (0x24C2, 'M', u'm'), + (0x24C3, 'M', u'n'), + (0x24C4, 'M', u'o'), + (0x24C5, 'M', u'p'), + (0x24C6, 'M', u'q'), + (0x24C7, 'M', u'r'), + (0x24C8, 'M', u's'), + (0x24C9, 'M', u't'), + (0x24CA, 'M', u'u'), + (0x24CB, 'M', u'v'), + (0x24CC, 'M', u'w'), + (0x24CD, 'M', u'x'), + (0x24CE, 'M', u'y'), + (0x24CF, 'M', u'z'), + (0x24D0, 'M', u'a'), + (0x24D1, 'M', u'b'), + ] + +def _seg_24(): + return [ + (0x24D2, 'M', u'c'), + (0x24D3, 'M', u'd'), + (0x24D4, 'M', u'e'), + (0x24D5, 'M', u'f'), + (0x24D6, 'M', u'g'), + (0x24D7, 'M', u'h'), + (0x24D8, 'M', u'i'), + (0x24D9, 'M', u'j'), + (0x24DA, 'M', u'k'), + (0x24DB, 'M', u'l'), + (0x24DC, 'M', u'm'), + (0x24DD, 'M', u'n'), + (0x24DE, 'M', u'o'), + (0x24DF, 'M', u'p'), + (0x24E0, 'M', u'q'), + (0x24E1, 'M', u'r'), + (0x24E2, 'M', u's'), + (0x24E3, 'M', u't'), + (0x24E4, 'M', u'u'), + (0x24E5, 'M', u'v'), + (0x24E6, 'M', u'w'), + (0x24E7, 'M', u'x'), + (0x24E8, 'M', u'y'), + (0x24E9, 'M', u'z'), + (0x24EA, 'M', u'0'), + (0x24EB, 'V'), + (0x2A0C, 'M', u'∫∫∫∫'), + (0x2A0D, 'V'), + (0x2A74, '3', u'::='), + (0x2A75, '3', u'=='), + (0x2A76, '3', u'==='), + (0x2A77, 'V'), + (0x2ADC, 'M', u'⫝̸'), + (0x2ADD, 'V'), + (0x2B74, 'X'), + (0x2B76, 'V'), + (0x2B96, 'X'), + (0x2B98, 'V'), + (0x2BBA, 'X'), + (0x2BBD, 'V'), + (0x2BC9, 'X'), + (0x2BCA, 'V'), + (0x2BD3, 'X'), + (0x2BEC, 'V'), + (0x2BF0, 'X'), + (0x2C00, 'M', u'ⰰ'), + (0x2C01, 'M', u'ⰱ'), + (0x2C02, 'M', u'ⰲ'), + (0x2C03, 'M', u'ⰳ'), + (0x2C04, 'M', u'ⰴ'), + (0x2C05, 'M', u'ⰵ'), + (0x2C06, 'M', u'ⰶ'), + (0x2C07, 'M', u'ⰷ'), + (0x2C08, 'M', u'ⰸ'), + (0x2C09, 'M', u'ⰹ'), + (0x2C0A, 'M', u'ⰺ'), + (0x2C0B, 'M', u'ⰻ'), + (0x2C0C, 'M', u'ⰼ'), + (0x2C0D, 'M', u'ⰽ'), + (0x2C0E, 'M', u'ⰾ'), + (0x2C0F, 'M', u'ⰿ'), + (0x2C10, 'M', u'ⱀ'), + (0x2C11, 'M', u'ⱁ'), + (0x2C12, 'M', u'ⱂ'), + (0x2C13, 'M', u'ⱃ'), + (0x2C14, 'M', u'ⱄ'), + (0x2C15, 'M', u'ⱅ'), + (0x2C16, 'M', u'ⱆ'), + (0x2C17, 'M', u'ⱇ'), + (0x2C18, 'M', u'ⱈ'), + (0x2C19, 'M', u'ⱉ'), + (0x2C1A, 'M', u'ⱊ'), + (0x2C1B, 'M', u'ⱋ'), + (0x2C1C, 'M', u'ⱌ'), + (0x2C1D, 'M', u'ⱍ'), + (0x2C1E, 'M', u'ⱎ'), + (0x2C1F, 'M', u'ⱏ'), + (0x2C20, 'M', u'ⱐ'), + (0x2C21, 'M', u'ⱑ'), + (0x2C22, 'M', u'ⱒ'), + (0x2C23, 'M', u'ⱓ'), + (0x2C24, 'M', u'ⱔ'), + (0x2C25, 'M', u'ⱕ'), + (0x2C26, 'M', u'ⱖ'), + (0x2C27, 'M', u'ⱗ'), + (0x2C28, 'M', u'ⱘ'), + (0x2C29, 'M', u'ⱙ'), + (0x2C2A, 'M', u'ⱚ'), + (0x2C2B, 'M', u'ⱛ'), + (0x2C2C, 'M', u'ⱜ'), + (0x2C2D, 'M', u'ⱝ'), + (0x2C2E, 'M', u'ⱞ'), + (0x2C2F, 'X'), + (0x2C30, 'V'), + (0x2C5F, 'X'), + (0x2C60, 'M', u'ⱡ'), + (0x2C61, 'V'), + (0x2C62, 'M', u'ɫ'), + (0x2C63, 'M', u'ᵽ'), + (0x2C64, 'M', u'ɽ'), + ] + +def _seg_25(): + return [ + (0x2C65, 'V'), + (0x2C67, 'M', u'ⱨ'), + (0x2C68, 'V'), + (0x2C69, 'M', u'ⱪ'), + (0x2C6A, 'V'), + (0x2C6B, 'M', u'ⱬ'), + (0x2C6C, 'V'), + (0x2C6D, 'M', u'ɑ'), + (0x2C6E, 'M', u'ɱ'), + (0x2C6F, 'M', u'ɐ'), + (0x2C70, 'M', u'ɒ'), + (0x2C71, 'V'), + (0x2C72, 'M', u'ⱳ'), + (0x2C73, 'V'), + (0x2C75, 'M', u'ⱶ'), + (0x2C76, 'V'), + (0x2C7C, 'M', u'j'), + (0x2C7D, 'M', u'v'), + (0x2C7E, 'M', u'ȿ'), + (0x2C7F, 'M', u'ɀ'), + (0x2C80, 'M', u'ⲁ'), + (0x2C81, 'V'), + (0x2C82, 'M', u'ⲃ'), + (0x2C83, 'V'), + (0x2C84, 'M', u'ⲅ'), + (0x2C85, 'V'), + (0x2C86, 'M', u'ⲇ'), + (0x2C87, 'V'), + (0x2C88, 'M', u'ⲉ'), + (0x2C89, 'V'), + (0x2C8A, 'M', u'ⲋ'), + (0x2C8B, 'V'), + (0x2C8C, 'M', u'ⲍ'), + (0x2C8D, 'V'), + (0x2C8E, 'M', u'ⲏ'), + (0x2C8F, 'V'), + (0x2C90, 'M', u'ⲑ'), + (0x2C91, 'V'), + (0x2C92, 'M', u'ⲓ'), + (0x2C93, 'V'), + (0x2C94, 'M', u'ⲕ'), + (0x2C95, 'V'), + (0x2C96, 'M', u'ⲗ'), + (0x2C97, 'V'), + (0x2C98, 'M', u'ⲙ'), + (0x2C99, 'V'), + (0x2C9A, 'M', u'ⲛ'), + (0x2C9B, 'V'), + (0x2C9C, 'M', u'ⲝ'), + (0x2C9D, 'V'), + (0x2C9E, 'M', u'ⲟ'), + (0x2C9F, 'V'), + (0x2CA0, 'M', u'ⲡ'), + (0x2CA1, 'V'), + (0x2CA2, 'M', u'ⲣ'), + (0x2CA3, 'V'), + (0x2CA4, 'M', u'ⲥ'), + (0x2CA5, 'V'), + (0x2CA6, 'M', u'ⲧ'), + (0x2CA7, 'V'), + (0x2CA8, 'M', u'ⲩ'), + (0x2CA9, 'V'), + (0x2CAA, 'M', u'ⲫ'), + (0x2CAB, 'V'), + (0x2CAC, 'M', u'ⲭ'), + (0x2CAD, 'V'), + (0x2CAE, 'M', u'ⲯ'), + (0x2CAF, 'V'), + (0x2CB0, 'M', u'ⲱ'), + (0x2CB1, 'V'), + (0x2CB2, 'M', u'ⲳ'), + (0x2CB3, 'V'), + (0x2CB4, 'M', u'ⲵ'), + (0x2CB5, 'V'), + (0x2CB6, 'M', u'ⲷ'), + (0x2CB7, 'V'), + (0x2CB8, 'M', u'ⲹ'), + (0x2CB9, 'V'), + (0x2CBA, 'M', u'ⲻ'), + (0x2CBB, 'V'), + (0x2CBC, 'M', u'ⲽ'), + (0x2CBD, 'V'), + (0x2CBE, 'M', u'ⲿ'), + (0x2CBF, 'V'), + (0x2CC0, 'M', u'ⳁ'), + (0x2CC1, 'V'), + (0x2CC2, 'M', u'ⳃ'), + (0x2CC3, 'V'), + (0x2CC4, 'M', u'ⳅ'), + (0x2CC5, 'V'), + (0x2CC6, 'M', u'ⳇ'), + (0x2CC7, 'V'), + (0x2CC8, 'M', u'ⳉ'), + (0x2CC9, 'V'), + (0x2CCA, 'M', u'ⳋ'), + (0x2CCB, 'V'), + (0x2CCC, 'M', u'ⳍ'), + (0x2CCD, 'V'), + (0x2CCE, 'M', u'ⳏ'), + (0x2CCF, 'V'), + ] + +def _seg_26(): + return [ + (0x2CD0, 'M', u'ⳑ'), + (0x2CD1, 'V'), + (0x2CD2, 'M', u'ⳓ'), + (0x2CD3, 'V'), + (0x2CD4, 'M', u'ⳕ'), + (0x2CD5, 'V'), + (0x2CD6, 'M', u'ⳗ'), + (0x2CD7, 'V'), + (0x2CD8, 'M', u'ⳙ'), + (0x2CD9, 'V'), + (0x2CDA, 'M', u'ⳛ'), + (0x2CDB, 'V'), + (0x2CDC, 'M', u'ⳝ'), + (0x2CDD, 'V'), + (0x2CDE, 'M', u'ⳟ'), + (0x2CDF, 'V'), + (0x2CE0, 'M', u'ⳡ'), + (0x2CE1, 'V'), + (0x2CE2, 'M', u'ⳣ'), + (0x2CE3, 'V'), + (0x2CEB, 'M', u'ⳬ'), + (0x2CEC, 'V'), + (0x2CED, 'M', u'ⳮ'), + (0x2CEE, 'V'), + (0x2CF2, 'M', u'ⳳ'), + (0x2CF3, 'V'), + (0x2CF4, 'X'), + (0x2CF9, 'V'), + (0x2D26, 'X'), + (0x2D27, 'V'), + (0x2D28, 'X'), + (0x2D2D, 'V'), + (0x2D2E, 'X'), + (0x2D30, 'V'), + (0x2D68, 'X'), + (0x2D6F, 'M', u'ⵡ'), + (0x2D70, 'V'), + (0x2D71, 'X'), + (0x2D7F, 'V'), + (0x2D97, 'X'), + (0x2DA0, 'V'), + (0x2DA7, 'X'), + (0x2DA8, 'V'), + (0x2DAF, 'X'), + (0x2DB0, 'V'), + (0x2DB7, 'X'), + (0x2DB8, 'V'), + (0x2DBF, 'X'), + (0x2DC0, 'V'), + (0x2DC7, 'X'), + (0x2DC8, 'V'), + (0x2DCF, 'X'), + (0x2DD0, 'V'), + (0x2DD7, 'X'), + (0x2DD8, 'V'), + (0x2DDF, 'X'), + (0x2DE0, 'V'), + (0x2E4A, 'X'), + (0x2E80, 'V'), + (0x2E9A, 'X'), + (0x2E9B, 'V'), + (0x2E9F, 'M', u'母'), + (0x2EA0, 'V'), + (0x2EF3, 'M', u'龟'), + (0x2EF4, 'X'), + (0x2F00, 'M', u'一'), + (0x2F01, 'M', u'丨'), + (0x2F02, 'M', u'丶'), + (0x2F03, 'M', u'丿'), + (0x2F04, 'M', u'乙'), + (0x2F05, 'M', u'亅'), + (0x2F06, 'M', u'二'), + (0x2F07, 'M', u'亠'), + (0x2F08, 'M', u'人'), + (0x2F09, 'M', u'儿'), + (0x2F0A, 'M', u'入'), + (0x2F0B, 'M', u'八'), + (0x2F0C, 'M', u'冂'), + (0x2F0D, 'M', u'冖'), + (0x2F0E, 'M', u'冫'), + (0x2F0F, 'M', u'几'), + (0x2F10, 'M', u'凵'), + (0x2F11, 'M', u'刀'), + (0x2F12, 'M', u'力'), + (0x2F13, 'M', u'勹'), + (0x2F14, 'M', u'匕'), + (0x2F15, 'M', u'匚'), + (0x2F16, 'M', u'匸'), + (0x2F17, 'M', u'十'), + (0x2F18, 'M', u'卜'), + (0x2F19, 'M', u'卩'), + (0x2F1A, 'M', u'厂'), + (0x2F1B, 'M', u'厶'), + (0x2F1C, 'M', u'又'), + (0x2F1D, 'M', u'口'), + (0x2F1E, 'M', u'囗'), + (0x2F1F, 'M', u'土'), + (0x2F20, 'M', u'士'), + (0x2F21, 'M', u'夂'), + (0x2F22, 'M', u'夊'), + ] + +def _seg_27(): + return [ + (0x2F23, 'M', u'夕'), + (0x2F24, 'M', u'大'), + (0x2F25, 'M', u'女'), + (0x2F26, 'M', u'子'), + (0x2F27, 'M', u'宀'), + (0x2F28, 'M', u'寸'), + (0x2F29, 'M', u'小'), + (0x2F2A, 'M', u'尢'), + (0x2F2B, 'M', u'尸'), + (0x2F2C, 'M', u'屮'), + (0x2F2D, 'M', u'山'), + (0x2F2E, 'M', u'巛'), + (0x2F2F, 'M', u'工'), + (0x2F30, 'M', u'己'), + (0x2F31, 'M', u'巾'), + (0x2F32, 'M', u'干'), + (0x2F33, 'M', u'幺'), + (0x2F34, 'M', u'广'), + (0x2F35, 'M', u'廴'), + (0x2F36, 'M', u'廾'), + (0x2F37, 'M', u'弋'), + (0x2F38, 'M', u'弓'), + (0x2F39, 'M', u'彐'), + (0x2F3A, 'M', u'彡'), + (0x2F3B, 'M', u'彳'), + (0x2F3C, 'M', u'心'), + (0x2F3D, 'M', u'戈'), + (0x2F3E, 'M', u'戶'), + (0x2F3F, 'M', u'手'), + (0x2F40, 'M', u'支'), + (0x2F41, 'M', u'攴'), + (0x2F42, 'M', u'文'), + (0x2F43, 'M', u'斗'), + (0x2F44, 'M', u'斤'), + (0x2F45, 'M', u'方'), + (0x2F46, 'M', u'无'), + (0x2F47, 'M', u'日'), + (0x2F48, 'M', u'曰'), + (0x2F49, 'M', u'月'), + (0x2F4A, 'M', u'木'), + (0x2F4B, 'M', u'欠'), + (0x2F4C, 'M', u'止'), + (0x2F4D, 'M', u'歹'), + (0x2F4E, 'M', u'殳'), + (0x2F4F, 'M', u'毋'), + (0x2F50, 'M', u'比'), + (0x2F51, 'M', u'毛'), + (0x2F52, 'M', u'氏'), + (0x2F53, 'M', u'气'), + (0x2F54, 'M', u'水'), + (0x2F55, 'M', u'火'), + (0x2F56, 'M', u'爪'), + (0x2F57, 'M', u'父'), + (0x2F58, 'M', u'爻'), + (0x2F59, 'M', u'爿'), + (0x2F5A, 'M', u'片'), + (0x2F5B, 'M', u'牙'), + (0x2F5C, 'M', u'牛'), + (0x2F5D, 'M', u'犬'), + (0x2F5E, 'M', u'玄'), + (0x2F5F, 'M', u'玉'), + (0x2F60, 'M', u'瓜'), + (0x2F61, 'M', u'瓦'), + (0x2F62, 'M', u'甘'), + (0x2F63, 'M', u'生'), + (0x2F64, 'M', u'用'), + (0x2F65, 'M', u'田'), + (0x2F66, 'M', u'疋'), + (0x2F67, 'M', u'疒'), + (0x2F68, 'M', u'癶'), + (0x2F69, 'M', u'白'), + (0x2F6A, 'M', u'皮'), + (0x2F6B, 'M', u'皿'), + (0x2F6C, 'M', u'目'), + (0x2F6D, 'M', u'矛'), + (0x2F6E, 'M', u'矢'), + (0x2F6F, 'M', u'石'), + (0x2F70, 'M', u'示'), + (0x2F71, 'M', u'禸'), + (0x2F72, 'M', u'禾'), + (0x2F73, 'M', u'穴'), + (0x2F74, 'M', u'立'), + (0x2F75, 'M', u'竹'), + (0x2F76, 'M', u'米'), + (0x2F77, 'M', u'糸'), + (0x2F78, 'M', u'缶'), + (0x2F79, 'M', u'网'), + (0x2F7A, 'M', u'羊'), + (0x2F7B, 'M', u'羽'), + (0x2F7C, 'M', u'老'), + (0x2F7D, 'M', u'而'), + (0x2F7E, 'M', u'耒'), + (0x2F7F, 'M', u'耳'), + (0x2F80, 'M', u'聿'), + (0x2F81, 'M', u'肉'), + (0x2F82, 'M', u'臣'), + (0x2F83, 'M', u'自'), + (0x2F84, 'M', u'至'), + (0x2F85, 'M', u'臼'), + (0x2F86, 'M', u'舌'), + ] + +def _seg_28(): + return [ + (0x2F87, 'M', u'舛'), + (0x2F88, 'M', u'舟'), + (0x2F89, 'M', u'艮'), + (0x2F8A, 'M', u'色'), + (0x2F8B, 'M', u'艸'), + (0x2F8C, 'M', u'虍'), + (0x2F8D, 'M', u'虫'), + (0x2F8E, 'M', u'血'), + (0x2F8F, 'M', u'行'), + (0x2F90, 'M', u'衣'), + (0x2F91, 'M', u'襾'), + (0x2F92, 'M', u'見'), + (0x2F93, 'M', u'角'), + (0x2F94, 'M', u'言'), + (0x2F95, 'M', u'谷'), + (0x2F96, 'M', u'豆'), + (0x2F97, 'M', u'豕'), + (0x2F98, 'M', u'豸'), + (0x2F99, 'M', u'貝'), + (0x2F9A, 'M', u'赤'), + (0x2F9B, 'M', u'走'), + (0x2F9C, 'M', u'足'), + (0x2F9D, 'M', u'身'), + (0x2F9E, 'M', u'車'), + (0x2F9F, 'M', u'辛'), + (0x2FA0, 'M', u'辰'), + (0x2FA1, 'M', u'辵'), + (0x2FA2, 'M', u'邑'), + (0x2FA3, 'M', u'酉'), + (0x2FA4, 'M', u'釆'), + (0x2FA5, 'M', u'里'), + (0x2FA6, 'M', u'金'), + (0x2FA7, 'M', u'長'), + (0x2FA8, 'M', u'門'), + (0x2FA9, 'M', u'阜'), + (0x2FAA, 'M', u'隶'), + (0x2FAB, 'M', u'隹'), + (0x2FAC, 'M', u'雨'), + (0x2FAD, 'M', u'靑'), + (0x2FAE, 'M', u'非'), + (0x2FAF, 'M', u'面'), + (0x2FB0, 'M', u'革'), + (0x2FB1, 'M', u'韋'), + (0x2FB2, 'M', u'韭'), + (0x2FB3, 'M', u'音'), + (0x2FB4, 'M', u'頁'), + (0x2FB5, 'M', u'風'), + (0x2FB6, 'M', u'飛'), + (0x2FB7, 'M', u'食'), + (0x2FB8, 'M', u'首'), + (0x2FB9, 'M', u'香'), + (0x2FBA, 'M', u'馬'), + (0x2FBB, 'M', u'骨'), + (0x2FBC, 'M', u'高'), + (0x2FBD, 'M', u'髟'), + (0x2FBE, 'M', u'鬥'), + (0x2FBF, 'M', u'鬯'), + (0x2FC0, 'M', u'鬲'), + (0x2FC1, 'M', u'鬼'), + (0x2FC2, 'M', u'魚'), + (0x2FC3, 'M', u'鳥'), + (0x2FC4, 'M', u'鹵'), + (0x2FC5, 'M', u'鹿'), + (0x2FC6, 'M', u'麥'), + (0x2FC7, 'M', u'麻'), + (0x2FC8, 'M', u'黃'), + (0x2FC9, 'M', u'黍'), + (0x2FCA, 'M', u'黑'), + (0x2FCB, 'M', u'黹'), + (0x2FCC, 'M', u'黽'), + (0x2FCD, 'M', u'鼎'), + (0x2FCE, 'M', u'鼓'), + (0x2FCF, 'M', u'鼠'), + (0x2FD0, 'M', u'鼻'), + (0x2FD1, 'M', u'齊'), + (0x2FD2, 'M', u'齒'), + (0x2FD3, 'M', u'龍'), + (0x2FD4, 'M', u'龜'), + (0x2FD5, 'M', u'龠'), + (0x2FD6, 'X'), + (0x3000, '3', u' '), + (0x3001, 'V'), + (0x3002, 'M', u'.'), + (0x3003, 'V'), + (0x3036, 'M', u'〒'), + (0x3037, 'V'), + (0x3038, 'M', u'十'), + (0x3039, 'M', u'卄'), + (0x303A, 'M', u'卅'), + (0x303B, 'V'), + (0x3040, 'X'), + (0x3041, 'V'), + (0x3097, 'X'), + (0x3099, 'V'), + (0x309B, '3', u' ゙'), + (0x309C, '3', u' ゚'), + (0x309D, 'V'), + (0x309F, 'M', u'より'), + (0x30A0, 'V'), + (0x30FF, 'M', u'コト'), + ] + +def _seg_29(): + return [ + (0x3100, 'X'), + (0x3105, 'V'), + (0x312F, 'X'), + (0x3131, 'M', u'ᄀ'), + (0x3132, 'M', u'ᄁ'), + (0x3133, 'M', u'ᆪ'), + (0x3134, 'M', u'ᄂ'), + (0x3135, 'M', u'ᆬ'), + (0x3136, 'M', u'ᆭ'), + (0x3137, 'M', u'ᄃ'), + (0x3138, 'M', u'ᄄ'), + (0x3139, 'M', u'ᄅ'), + (0x313A, 'M', u'ᆰ'), + (0x313B, 'M', u'ᆱ'), + (0x313C, 'M', u'ᆲ'), + (0x313D, 'M', u'ᆳ'), + (0x313E, 'M', u'ᆴ'), + (0x313F, 'M', u'ᆵ'), + (0x3140, 'M', u'ᄚ'), + (0x3141, 'M', u'ᄆ'), + (0x3142, 'M', u'ᄇ'), + (0x3143, 'M', u'ᄈ'), + (0x3144, 'M', u'ᄡ'), + (0x3145, 'M', u'ᄉ'), + (0x3146, 'M', u'ᄊ'), + (0x3147, 'M', u'ᄋ'), + (0x3148, 'M', u'ᄌ'), + (0x3149, 'M', u'ᄍ'), + (0x314A, 'M', u'ᄎ'), + (0x314B, 'M', u'ᄏ'), + (0x314C, 'M', u'ᄐ'), + (0x314D, 'M', u'ᄑ'), + (0x314E, 'M', u'ᄒ'), + (0x314F, 'M', u'ᅡ'), + (0x3150, 'M', u'ᅢ'), + (0x3151, 'M', u'ᅣ'), + (0x3152, 'M', u'ᅤ'), + (0x3153, 'M', u'ᅥ'), + (0x3154, 'M', u'ᅦ'), + (0x3155, 'M', u'ᅧ'), + (0x3156, 'M', u'ᅨ'), + (0x3157, 'M', u'ᅩ'), + (0x3158, 'M', u'ᅪ'), + (0x3159, 'M', u'ᅫ'), + (0x315A, 'M', u'ᅬ'), + (0x315B, 'M', u'ᅭ'), + (0x315C, 'M', u'ᅮ'), + (0x315D, 'M', u'ᅯ'), + (0x315E, 'M', u'ᅰ'), + (0x315F, 'M', u'ᅱ'), + (0x3160, 'M', u'ᅲ'), + (0x3161, 'M', u'ᅳ'), + (0x3162, 'M', u'ᅴ'), + (0x3163, 'M', u'ᅵ'), + (0x3164, 'X'), + (0x3165, 'M', u'ᄔ'), + (0x3166, 'M', u'ᄕ'), + (0x3167, 'M', u'ᇇ'), + (0x3168, 'M', u'ᇈ'), + (0x3169, 'M', u'ᇌ'), + (0x316A, 'M', u'ᇎ'), + (0x316B, 'M', u'ᇓ'), + (0x316C, 'M', u'ᇗ'), + (0x316D, 'M', u'ᇙ'), + (0x316E, 'M', u'ᄜ'), + (0x316F, 'M', u'ᇝ'), + (0x3170, 'M', u'ᇟ'), + (0x3171, 'M', u'ᄝ'), + (0x3172, 'M', u'ᄞ'), + (0x3173, 'M', u'ᄠ'), + (0x3174, 'M', u'ᄢ'), + (0x3175, 'M', u'ᄣ'), + (0x3176, 'M', u'ᄧ'), + (0x3177, 'M', u'ᄩ'), + (0x3178, 'M', u'ᄫ'), + (0x3179, 'M', u'ᄬ'), + (0x317A, 'M', u'ᄭ'), + (0x317B, 'M', u'ᄮ'), + (0x317C, 'M', u'ᄯ'), + (0x317D, 'M', u'ᄲ'), + (0x317E, 'M', u'ᄶ'), + (0x317F, 'M', u'ᅀ'), + (0x3180, 'M', u'ᅇ'), + (0x3181, 'M', u'ᅌ'), + (0x3182, 'M', u'ᇱ'), + (0x3183, 'M', u'ᇲ'), + (0x3184, 'M', u'ᅗ'), + (0x3185, 'M', u'ᅘ'), + (0x3186, 'M', u'ᅙ'), + (0x3187, 'M', u'ᆄ'), + (0x3188, 'M', u'ᆅ'), + (0x3189, 'M', u'ᆈ'), + (0x318A, 'M', u'ᆑ'), + (0x318B, 'M', u'ᆒ'), + (0x318C, 'M', u'ᆔ'), + (0x318D, 'M', u'ᆞ'), + (0x318E, 'M', u'ᆡ'), + (0x318F, 'X'), + (0x3190, 'V'), + (0x3192, 'M', u'一'), + ] + +def _seg_30(): + return [ + (0x3193, 'M', u'二'), + (0x3194, 'M', u'三'), + (0x3195, 'M', u'四'), + (0x3196, 'M', u'上'), + (0x3197, 'M', u'中'), + (0x3198, 'M', u'下'), + (0x3199, 'M', u'甲'), + (0x319A, 'M', u'乙'), + (0x319B, 'M', u'丙'), + (0x319C, 'M', u'丁'), + (0x319D, 'M', u'天'), + (0x319E, 'M', u'地'), + (0x319F, 'M', u'人'), + (0x31A0, 'V'), + (0x31BB, 'X'), + (0x31C0, 'V'), + (0x31E4, 'X'), + (0x31F0, 'V'), + (0x3200, '3', u'(ᄀ)'), + (0x3201, '3', u'(ᄂ)'), + (0x3202, '3', u'(ᄃ)'), + (0x3203, '3', u'(ᄅ)'), + (0x3204, '3', u'(ᄆ)'), + (0x3205, '3', u'(ᄇ)'), + (0x3206, '3', u'(ᄉ)'), + (0x3207, '3', u'(ᄋ)'), + (0x3208, '3', u'(ᄌ)'), + (0x3209, '3', u'(ᄎ)'), + (0x320A, '3', u'(ᄏ)'), + (0x320B, '3', u'(ᄐ)'), + (0x320C, '3', u'(ᄑ)'), + (0x320D, '3', u'(ᄒ)'), + (0x320E, '3', u'(가)'), + (0x320F, '3', u'(나)'), + (0x3210, '3', u'(다)'), + (0x3211, '3', u'(라)'), + (0x3212, '3', u'(마)'), + (0x3213, '3', u'(바)'), + (0x3214, '3', u'(사)'), + (0x3215, '3', u'(아)'), + (0x3216, '3', u'(자)'), + (0x3217, '3', u'(차)'), + (0x3218, '3', u'(카)'), + (0x3219, '3', u'(타)'), + (0x321A, '3', u'(파)'), + (0x321B, '3', u'(하)'), + (0x321C, '3', u'(주)'), + (0x321D, '3', u'(오전)'), + (0x321E, '3', u'(오후)'), + (0x321F, 'X'), + (0x3220, '3', u'(一)'), + (0x3221, '3', u'(二)'), + (0x3222, '3', u'(三)'), + (0x3223, '3', u'(四)'), + (0x3224, '3', u'(五)'), + (0x3225, '3', u'(六)'), + (0x3226, '3', u'(七)'), + (0x3227, '3', u'(八)'), + (0x3228, '3', u'(九)'), + (0x3229, '3', u'(十)'), + (0x322A, '3', u'(月)'), + (0x322B, '3', u'(火)'), + (0x322C, '3', u'(水)'), + (0x322D, '3', u'(木)'), + (0x322E, '3', u'(金)'), + (0x322F, '3', u'(土)'), + (0x3230, '3', u'(日)'), + (0x3231, '3', u'(株)'), + (0x3232, '3', u'(有)'), + (0x3233, '3', u'(社)'), + (0x3234, '3', u'(名)'), + (0x3235, '3', u'(特)'), + (0x3236, '3', u'(財)'), + (0x3237, '3', u'(祝)'), + (0x3238, '3', u'(労)'), + (0x3239, '3', u'(代)'), + (0x323A, '3', u'(呼)'), + (0x323B, '3', u'(学)'), + (0x323C, '3', u'(監)'), + (0x323D, '3', u'(企)'), + (0x323E, '3', u'(資)'), + (0x323F, '3', u'(協)'), + (0x3240, '3', u'(祭)'), + (0x3241, '3', u'(休)'), + (0x3242, '3', u'(自)'), + (0x3243, '3', u'(至)'), + (0x3244, 'M', u'問'), + (0x3245, 'M', u'幼'), + (0x3246, 'M', u'文'), + (0x3247, 'M', u'箏'), + (0x3248, 'V'), + (0x3250, 'M', u'pte'), + (0x3251, 'M', u'21'), + (0x3252, 'M', u'22'), + (0x3253, 'M', u'23'), + (0x3254, 'M', u'24'), + (0x3255, 'M', u'25'), + (0x3256, 'M', u'26'), + (0x3257, 'M', u'27'), + (0x3258, 'M', u'28'), + ] + +def _seg_31(): + return [ + (0x3259, 'M', u'29'), + (0x325A, 'M', u'30'), + (0x325B, 'M', u'31'), + (0x325C, 'M', u'32'), + (0x325D, 'M', u'33'), + (0x325E, 'M', u'34'), + (0x325F, 'M', u'35'), + (0x3260, 'M', u'ᄀ'), + (0x3261, 'M', u'ᄂ'), + (0x3262, 'M', u'ᄃ'), + (0x3263, 'M', u'ᄅ'), + (0x3264, 'M', u'ᄆ'), + (0x3265, 'M', u'ᄇ'), + (0x3266, 'M', u'ᄉ'), + (0x3267, 'M', u'ᄋ'), + (0x3268, 'M', u'ᄌ'), + (0x3269, 'M', u'ᄎ'), + (0x326A, 'M', u'ᄏ'), + (0x326B, 'M', u'ᄐ'), + (0x326C, 'M', u'ᄑ'), + (0x326D, 'M', u'ᄒ'), + (0x326E, 'M', u'가'), + (0x326F, 'M', u'나'), + (0x3270, 'M', u'다'), + (0x3271, 'M', u'라'), + (0x3272, 'M', u'마'), + (0x3273, 'M', u'바'), + (0x3274, 'M', u'사'), + (0x3275, 'M', u'아'), + (0x3276, 'M', u'자'), + (0x3277, 'M', u'차'), + (0x3278, 'M', u'카'), + (0x3279, 'M', u'타'), + (0x327A, 'M', u'파'), + (0x327B, 'M', u'하'), + (0x327C, 'M', u'참고'), + (0x327D, 'M', u'주의'), + (0x327E, 'M', u'우'), + (0x327F, 'V'), + (0x3280, 'M', u'一'), + (0x3281, 'M', u'二'), + (0x3282, 'M', u'三'), + (0x3283, 'M', u'四'), + (0x3284, 'M', u'五'), + (0x3285, 'M', u'六'), + (0x3286, 'M', u'七'), + (0x3287, 'M', u'八'), + (0x3288, 'M', u'九'), + (0x3289, 'M', u'十'), + (0x328A, 'M', u'月'), + (0x328B, 'M', u'火'), + (0x328C, 'M', u'水'), + (0x328D, 'M', u'木'), + (0x328E, 'M', u'金'), + (0x328F, 'M', u'土'), + (0x3290, 'M', u'日'), + (0x3291, 'M', u'株'), + (0x3292, 'M', u'有'), + (0x3293, 'M', u'社'), + (0x3294, 'M', u'名'), + (0x3295, 'M', u'特'), + (0x3296, 'M', u'財'), + (0x3297, 'M', u'祝'), + (0x3298, 'M', u'労'), + (0x3299, 'M', u'秘'), + (0x329A, 'M', u'男'), + (0x329B, 'M', u'女'), + (0x329C, 'M', u'適'), + (0x329D, 'M', u'優'), + (0x329E, 'M', u'印'), + (0x329F, 'M', u'注'), + (0x32A0, 'M', u'項'), + (0x32A1, 'M', u'休'), + (0x32A2, 'M', u'写'), + (0x32A3, 'M', u'正'), + (0x32A4, 'M', u'上'), + (0x32A5, 'M', u'中'), + (0x32A6, 'M', u'下'), + (0x32A7, 'M', u'左'), + (0x32A8, 'M', u'右'), + (0x32A9, 'M', u'医'), + (0x32AA, 'M', u'宗'), + (0x32AB, 'M', u'学'), + (0x32AC, 'M', u'監'), + (0x32AD, 'M', u'企'), + (0x32AE, 'M', u'資'), + (0x32AF, 'M', u'協'), + (0x32B0, 'M', u'夜'), + (0x32B1, 'M', u'36'), + (0x32B2, 'M', u'37'), + (0x32B3, 'M', u'38'), + (0x32B4, 'M', u'39'), + (0x32B5, 'M', u'40'), + (0x32B6, 'M', u'41'), + (0x32B7, 'M', u'42'), + (0x32B8, 'M', u'43'), + (0x32B9, 'M', u'44'), + (0x32BA, 'M', u'45'), + (0x32BB, 'M', u'46'), + (0x32BC, 'M', u'47'), + ] + +def _seg_32(): + return [ + (0x32BD, 'M', u'48'), + (0x32BE, 'M', u'49'), + (0x32BF, 'M', u'50'), + (0x32C0, 'M', u'1月'), + (0x32C1, 'M', u'2月'), + (0x32C2, 'M', u'3月'), + (0x32C3, 'M', u'4月'), + (0x32C4, 'M', u'5月'), + (0x32C5, 'M', u'6月'), + (0x32C6, 'M', u'7月'), + (0x32C7, 'M', u'8月'), + (0x32C8, 'M', u'9月'), + (0x32C9, 'M', u'10月'), + (0x32CA, 'M', u'11月'), + (0x32CB, 'M', u'12月'), + (0x32CC, 'M', u'hg'), + (0x32CD, 'M', u'erg'), + (0x32CE, 'M', u'ev'), + (0x32CF, 'M', u'ltd'), + (0x32D0, 'M', u'ア'), + (0x32D1, 'M', u'イ'), + (0x32D2, 'M', u'ウ'), + (0x32D3, 'M', u'エ'), + (0x32D4, 'M', u'オ'), + (0x32D5, 'M', u'カ'), + (0x32D6, 'M', u'キ'), + (0x32D7, 'M', u'ク'), + (0x32D8, 'M', u'ケ'), + (0x32D9, 'M', u'コ'), + (0x32DA, 'M', u'サ'), + (0x32DB, 'M', u'シ'), + (0x32DC, 'M', u'ス'), + (0x32DD, 'M', u'セ'), + (0x32DE, 'M', u'ソ'), + (0x32DF, 'M', u'タ'), + (0x32E0, 'M', u'チ'), + (0x32E1, 'M', u'ツ'), + (0x32E2, 'M', u'テ'), + (0x32E3, 'M', u'ト'), + (0x32E4, 'M', u'ナ'), + (0x32E5, 'M', u'ニ'), + (0x32E6, 'M', u'ヌ'), + (0x32E7, 'M', u'ネ'), + (0x32E8, 'M', u'ノ'), + (0x32E9, 'M', u'ハ'), + (0x32EA, 'M', u'ヒ'), + (0x32EB, 'M', u'フ'), + (0x32EC, 'M', u'ヘ'), + (0x32ED, 'M', u'ホ'), + (0x32EE, 'M', u'マ'), + (0x32EF, 'M', u'ミ'), + (0x32F0, 'M', u'ム'), + (0x32F1, 'M', u'メ'), + (0x32F2, 'M', u'モ'), + (0x32F3, 'M', u'ヤ'), + (0x32F4, 'M', u'ユ'), + (0x32F5, 'M', u'ヨ'), + (0x32F6, 'M', u'ラ'), + (0x32F7, 'M', u'リ'), + (0x32F8, 'M', u'ル'), + (0x32F9, 'M', u'レ'), + (0x32FA, 'M', u'ロ'), + (0x32FB, 'M', u'ワ'), + (0x32FC, 'M', u'ヰ'), + (0x32FD, 'M', u'ヱ'), + (0x32FE, 'M', u'ヲ'), + (0x32FF, 'X'), + (0x3300, 'M', u'アパート'), + (0x3301, 'M', u'アルファ'), + (0x3302, 'M', u'アンペア'), + (0x3303, 'M', u'アール'), + (0x3304, 'M', u'イニング'), + (0x3305, 'M', u'インチ'), + (0x3306, 'M', u'ウォン'), + (0x3307, 'M', u'エスクード'), + (0x3308, 'M', u'エーカー'), + (0x3309, 'M', u'オンス'), + (0x330A, 'M', u'オーム'), + (0x330B, 'M', u'カイリ'), + (0x330C, 'M', u'カラット'), + (0x330D, 'M', u'カロリー'), + (0x330E, 'M', u'ガロン'), + (0x330F, 'M', u'ガンマ'), + (0x3310, 'M', u'ギガ'), + (0x3311, 'M', u'ギニー'), + (0x3312, 'M', u'キュリー'), + (0x3313, 'M', u'ギルダー'), + (0x3314, 'M', u'キロ'), + (0x3315, 'M', u'キログラム'), + (0x3316, 'M', u'キロメートル'), + (0x3317, 'M', u'キロワット'), + (0x3318, 'M', u'グラム'), + (0x3319, 'M', u'グラムトン'), + (0x331A, 'M', u'クルゼイロ'), + (0x331B, 'M', u'クローネ'), + (0x331C, 'M', u'ケース'), + (0x331D, 'M', u'コルナ'), + (0x331E, 'M', u'コーポ'), + (0x331F, 'M', u'サイクル'), + (0x3320, 'M', u'サンチーム'), + ] + +def _seg_33(): + return [ + (0x3321, 'M', u'シリング'), + (0x3322, 'M', u'センチ'), + (0x3323, 'M', u'セント'), + (0x3324, 'M', u'ダース'), + (0x3325, 'M', u'デシ'), + (0x3326, 'M', u'ドル'), + (0x3327, 'M', u'トン'), + (0x3328, 'M', u'ナノ'), + (0x3329, 'M', u'ノット'), + (0x332A, 'M', u'ハイツ'), + (0x332B, 'M', u'パーセント'), + (0x332C, 'M', u'パーツ'), + (0x332D, 'M', u'バーレル'), + (0x332E, 'M', u'ピアストル'), + (0x332F, 'M', u'ピクル'), + (0x3330, 'M', u'ピコ'), + (0x3331, 'M', u'ビル'), + (0x3332, 'M', u'ファラッド'), + (0x3333, 'M', u'フィート'), + (0x3334, 'M', u'ブッシェル'), + (0x3335, 'M', u'フラン'), + (0x3336, 'M', u'ヘクタール'), + (0x3337, 'M', u'ペソ'), + (0x3338, 'M', u'ペニヒ'), + (0x3339, 'M', u'ヘルツ'), + (0x333A, 'M', u'ペンス'), + (0x333B, 'M', u'ページ'), + (0x333C, 'M', u'ベータ'), + (0x333D, 'M', u'ポイント'), + (0x333E, 'M', u'ボルト'), + (0x333F, 'M', u'ホン'), + (0x3340, 'M', u'ポンド'), + (0x3341, 'M', u'ホール'), + (0x3342, 'M', u'ホーン'), + (0x3343, 'M', u'マイクロ'), + (0x3344, 'M', u'マイル'), + (0x3345, 'M', u'マッハ'), + (0x3346, 'M', u'マルク'), + (0x3347, 'M', u'マンション'), + (0x3348, 'M', u'ミクロン'), + (0x3349, 'M', u'ミリ'), + (0x334A, 'M', u'ミリバール'), + (0x334B, 'M', u'メガ'), + (0x334C, 'M', u'メガトン'), + (0x334D, 'M', u'メートル'), + (0x334E, 'M', u'ヤード'), + (0x334F, 'M', u'ヤール'), + (0x3350, 'M', u'ユアン'), + (0x3351, 'M', u'リットル'), + (0x3352, 'M', u'リラ'), + (0x3353, 'M', u'ルピー'), + (0x3354, 'M', u'ルーブル'), + (0x3355, 'M', u'レム'), + (0x3356, 'M', u'レントゲン'), + (0x3357, 'M', u'ワット'), + (0x3358, 'M', u'0点'), + (0x3359, 'M', u'1点'), + (0x335A, 'M', u'2点'), + (0x335B, 'M', u'3点'), + (0x335C, 'M', u'4点'), + (0x335D, 'M', u'5点'), + (0x335E, 'M', u'6点'), + (0x335F, 'M', u'7点'), + (0x3360, 'M', u'8点'), + (0x3361, 'M', u'9点'), + (0x3362, 'M', u'10点'), + (0x3363, 'M', u'11点'), + (0x3364, 'M', u'12点'), + (0x3365, 'M', u'13点'), + (0x3366, 'M', u'14点'), + (0x3367, 'M', u'15点'), + (0x3368, 'M', u'16点'), + (0x3369, 'M', u'17点'), + (0x336A, 'M', u'18点'), + (0x336B, 'M', u'19点'), + (0x336C, 'M', u'20点'), + (0x336D, 'M', u'21点'), + (0x336E, 'M', u'22点'), + (0x336F, 'M', u'23点'), + (0x3370, 'M', u'24点'), + (0x3371, 'M', u'hpa'), + (0x3372, 'M', u'da'), + (0x3373, 'M', u'au'), + (0x3374, 'M', u'bar'), + (0x3375, 'M', u'ov'), + (0x3376, 'M', u'pc'), + (0x3377, 'M', u'dm'), + (0x3378, 'M', u'dm2'), + (0x3379, 'M', u'dm3'), + (0x337A, 'M', u'iu'), + (0x337B, 'M', u'平成'), + (0x337C, 'M', u'昭和'), + (0x337D, 'M', u'大正'), + (0x337E, 'M', u'明治'), + (0x337F, 'M', u'株式会社'), + (0x3380, 'M', u'pa'), + (0x3381, 'M', u'na'), + (0x3382, 'M', u'μa'), + (0x3383, 'M', u'ma'), + (0x3384, 'M', u'ka'), + ] + +def _seg_34(): + return [ + (0x3385, 'M', u'kb'), + (0x3386, 'M', u'mb'), + (0x3387, 'M', u'gb'), + (0x3388, 'M', u'cal'), + (0x3389, 'M', u'kcal'), + (0x338A, 'M', u'pf'), + (0x338B, 'M', u'nf'), + (0x338C, 'M', u'μf'), + (0x338D, 'M', u'μg'), + (0x338E, 'M', u'mg'), + (0x338F, 'M', u'kg'), + (0x3390, 'M', u'hz'), + (0x3391, 'M', u'khz'), + (0x3392, 'M', u'mhz'), + (0x3393, 'M', u'ghz'), + (0x3394, 'M', u'thz'), + (0x3395, 'M', u'μl'), + (0x3396, 'M', u'ml'), + (0x3397, 'M', u'dl'), + (0x3398, 'M', u'kl'), + (0x3399, 'M', u'fm'), + (0x339A, 'M', u'nm'), + (0x339B, 'M', u'μm'), + (0x339C, 'M', u'mm'), + (0x339D, 'M', u'cm'), + (0x339E, 'M', u'km'), + (0x339F, 'M', u'mm2'), + (0x33A0, 'M', u'cm2'), + (0x33A1, 'M', u'm2'), + (0x33A2, 'M', u'km2'), + (0x33A3, 'M', u'mm3'), + (0x33A4, 'M', u'cm3'), + (0x33A5, 'M', u'm3'), + (0x33A6, 'M', u'km3'), + (0x33A7, 'M', u'm∕s'), + (0x33A8, 'M', u'm∕s2'), + (0x33A9, 'M', u'pa'), + (0x33AA, 'M', u'kpa'), + (0x33AB, 'M', u'mpa'), + (0x33AC, 'M', u'gpa'), + (0x33AD, 'M', u'rad'), + (0x33AE, 'M', u'rad∕s'), + (0x33AF, 'M', u'rad∕s2'), + (0x33B0, 'M', u'ps'), + (0x33B1, 'M', u'ns'), + (0x33B2, 'M', u'μs'), + (0x33B3, 'M', u'ms'), + (0x33B4, 'M', u'pv'), + (0x33B5, 'M', u'nv'), + (0x33B6, 'M', u'μv'), + (0x33B7, 'M', u'mv'), + (0x33B8, 'M', u'kv'), + (0x33B9, 'M', u'mv'), + (0x33BA, 'M', u'pw'), + (0x33BB, 'M', u'nw'), + (0x33BC, 'M', u'μw'), + (0x33BD, 'M', u'mw'), + (0x33BE, 'M', u'kw'), + (0x33BF, 'M', u'mw'), + (0x33C0, 'M', u'kω'), + (0x33C1, 'M', u'mω'), + (0x33C2, 'X'), + (0x33C3, 'M', u'bq'), + (0x33C4, 'M', u'cc'), + (0x33C5, 'M', u'cd'), + (0x33C6, 'M', u'c∕kg'), + (0x33C7, 'X'), + (0x33C8, 'M', u'db'), + (0x33C9, 'M', u'gy'), + (0x33CA, 'M', u'ha'), + (0x33CB, 'M', u'hp'), + (0x33CC, 'M', u'in'), + (0x33CD, 'M', u'kk'), + (0x33CE, 'M', u'km'), + (0x33CF, 'M', u'kt'), + (0x33D0, 'M', u'lm'), + (0x33D1, 'M', u'ln'), + (0x33D2, 'M', u'log'), + (0x33D3, 'M', u'lx'), + (0x33D4, 'M', u'mb'), + (0x33D5, 'M', u'mil'), + (0x33D6, 'M', u'mol'), + (0x33D7, 'M', u'ph'), + (0x33D8, 'X'), + (0x33D9, 'M', u'ppm'), + (0x33DA, 'M', u'pr'), + (0x33DB, 'M', u'sr'), + (0x33DC, 'M', u'sv'), + (0x33DD, 'M', u'wb'), + (0x33DE, 'M', u'v∕m'), + (0x33DF, 'M', u'a∕m'), + (0x33E0, 'M', u'1日'), + (0x33E1, 'M', u'2日'), + (0x33E2, 'M', u'3日'), + (0x33E3, 'M', u'4日'), + (0x33E4, 'M', u'5日'), + (0x33E5, 'M', u'6日'), + (0x33E6, 'M', u'7日'), + (0x33E7, 'M', u'8日'), + (0x33E8, 'M', u'9日'), + ] + +def _seg_35(): + return [ + (0x33E9, 'M', u'10日'), + (0x33EA, 'M', u'11日'), + (0x33EB, 'M', u'12日'), + (0x33EC, 'M', u'13日'), + (0x33ED, 'M', u'14日'), + (0x33EE, 'M', u'15日'), + (0x33EF, 'M', u'16日'), + (0x33F0, 'M', u'17日'), + (0x33F1, 'M', u'18日'), + (0x33F2, 'M', u'19日'), + (0x33F3, 'M', u'20日'), + (0x33F4, 'M', u'21日'), + (0x33F5, 'M', u'22日'), + (0x33F6, 'M', u'23日'), + (0x33F7, 'M', u'24日'), + (0x33F8, 'M', u'25日'), + (0x33F9, 'M', u'26日'), + (0x33FA, 'M', u'27日'), + (0x33FB, 'M', u'28日'), + (0x33FC, 'M', u'29日'), + (0x33FD, 'M', u'30日'), + (0x33FE, 'M', u'31日'), + (0x33FF, 'M', u'gal'), + (0x3400, 'V'), + (0x4DB6, 'X'), + (0x4DC0, 'V'), + (0x9FEB, 'X'), + (0xA000, 'V'), + (0xA48D, 'X'), + (0xA490, 'V'), + (0xA4C7, 'X'), + (0xA4D0, 'V'), + (0xA62C, 'X'), + (0xA640, 'M', u'ꙁ'), + (0xA641, 'V'), + (0xA642, 'M', u'ꙃ'), + (0xA643, 'V'), + (0xA644, 'M', u'ꙅ'), + (0xA645, 'V'), + (0xA646, 'M', u'ꙇ'), + (0xA647, 'V'), + (0xA648, 'M', u'ꙉ'), + (0xA649, 'V'), + (0xA64A, 'M', u'ꙋ'), + (0xA64B, 'V'), + (0xA64C, 'M', u'ꙍ'), + (0xA64D, 'V'), + (0xA64E, 'M', u'ꙏ'), + (0xA64F, 'V'), + (0xA650, 'M', u'ꙑ'), + (0xA651, 'V'), + (0xA652, 'M', u'ꙓ'), + (0xA653, 'V'), + (0xA654, 'M', u'ꙕ'), + (0xA655, 'V'), + (0xA656, 'M', u'ꙗ'), + (0xA657, 'V'), + (0xA658, 'M', u'ꙙ'), + (0xA659, 'V'), + (0xA65A, 'M', u'ꙛ'), + (0xA65B, 'V'), + (0xA65C, 'M', u'ꙝ'), + (0xA65D, 'V'), + (0xA65E, 'M', u'ꙟ'), + (0xA65F, 'V'), + (0xA660, 'M', u'ꙡ'), + (0xA661, 'V'), + (0xA662, 'M', u'ꙣ'), + (0xA663, 'V'), + (0xA664, 'M', u'ꙥ'), + (0xA665, 'V'), + (0xA666, 'M', u'ꙧ'), + (0xA667, 'V'), + (0xA668, 'M', u'ꙩ'), + (0xA669, 'V'), + (0xA66A, 'M', u'ꙫ'), + (0xA66B, 'V'), + (0xA66C, 'M', u'ꙭ'), + (0xA66D, 'V'), + (0xA680, 'M', u'ꚁ'), + (0xA681, 'V'), + (0xA682, 'M', u'ꚃ'), + (0xA683, 'V'), + (0xA684, 'M', u'ꚅ'), + (0xA685, 'V'), + (0xA686, 'M', u'ꚇ'), + (0xA687, 'V'), + (0xA688, 'M', u'ꚉ'), + (0xA689, 'V'), + (0xA68A, 'M', u'ꚋ'), + (0xA68B, 'V'), + (0xA68C, 'M', u'ꚍ'), + (0xA68D, 'V'), + (0xA68E, 'M', u'ꚏ'), + (0xA68F, 'V'), + (0xA690, 'M', u'ꚑ'), + (0xA691, 'V'), + (0xA692, 'M', u'ꚓ'), + (0xA693, 'V'), + (0xA694, 'M', u'ꚕ'), + ] + +def _seg_36(): + return [ + (0xA695, 'V'), + (0xA696, 'M', u'ꚗ'), + (0xA697, 'V'), + (0xA698, 'M', u'ꚙ'), + (0xA699, 'V'), + (0xA69A, 'M', u'ꚛ'), + (0xA69B, 'V'), + (0xA69C, 'M', u'ъ'), + (0xA69D, 'M', u'ь'), + (0xA69E, 'V'), + (0xA6F8, 'X'), + (0xA700, 'V'), + (0xA722, 'M', u'ꜣ'), + (0xA723, 'V'), + (0xA724, 'M', u'ꜥ'), + (0xA725, 'V'), + (0xA726, 'M', u'ꜧ'), + (0xA727, 'V'), + (0xA728, 'M', u'ꜩ'), + (0xA729, 'V'), + (0xA72A, 'M', u'ꜫ'), + (0xA72B, 'V'), + (0xA72C, 'M', u'ꜭ'), + (0xA72D, 'V'), + (0xA72E, 'M', u'ꜯ'), + (0xA72F, 'V'), + (0xA732, 'M', u'ꜳ'), + (0xA733, 'V'), + (0xA734, 'M', u'ꜵ'), + (0xA735, 'V'), + (0xA736, 'M', u'ꜷ'), + (0xA737, 'V'), + (0xA738, 'M', u'ꜹ'), + (0xA739, 'V'), + (0xA73A, 'M', u'ꜻ'), + (0xA73B, 'V'), + (0xA73C, 'M', u'ꜽ'), + (0xA73D, 'V'), + (0xA73E, 'M', u'ꜿ'), + (0xA73F, 'V'), + (0xA740, 'M', u'ꝁ'), + (0xA741, 'V'), + (0xA742, 'M', u'ꝃ'), + (0xA743, 'V'), + (0xA744, 'M', u'ꝅ'), + (0xA745, 'V'), + (0xA746, 'M', u'ꝇ'), + (0xA747, 'V'), + (0xA748, 'M', u'ꝉ'), + (0xA749, 'V'), + (0xA74A, 'M', u'ꝋ'), + (0xA74B, 'V'), + (0xA74C, 'M', u'ꝍ'), + (0xA74D, 'V'), + (0xA74E, 'M', u'ꝏ'), + (0xA74F, 'V'), + (0xA750, 'M', u'ꝑ'), + (0xA751, 'V'), + (0xA752, 'M', u'ꝓ'), + (0xA753, 'V'), + (0xA754, 'M', u'ꝕ'), + (0xA755, 'V'), + (0xA756, 'M', u'ꝗ'), + (0xA757, 'V'), + (0xA758, 'M', u'ꝙ'), + (0xA759, 'V'), + (0xA75A, 'M', u'ꝛ'), + (0xA75B, 'V'), + (0xA75C, 'M', u'ꝝ'), + (0xA75D, 'V'), + (0xA75E, 'M', u'ꝟ'), + (0xA75F, 'V'), + (0xA760, 'M', u'ꝡ'), + (0xA761, 'V'), + (0xA762, 'M', u'ꝣ'), + (0xA763, 'V'), + (0xA764, 'M', u'ꝥ'), + (0xA765, 'V'), + (0xA766, 'M', u'ꝧ'), + (0xA767, 'V'), + (0xA768, 'M', u'ꝩ'), + (0xA769, 'V'), + (0xA76A, 'M', u'ꝫ'), + (0xA76B, 'V'), + (0xA76C, 'M', u'ꝭ'), + (0xA76D, 'V'), + (0xA76E, 'M', u'ꝯ'), + (0xA76F, 'V'), + (0xA770, 'M', u'ꝯ'), + (0xA771, 'V'), + (0xA779, 'M', u'ꝺ'), + (0xA77A, 'V'), + (0xA77B, 'M', u'ꝼ'), + (0xA77C, 'V'), + (0xA77D, 'M', u'ᵹ'), + (0xA77E, 'M', u'ꝿ'), + (0xA77F, 'V'), + (0xA780, 'M', u'ꞁ'), + (0xA781, 'V'), + (0xA782, 'M', u'ꞃ'), + ] + +def _seg_37(): + return [ + (0xA783, 'V'), + (0xA784, 'M', u'ꞅ'), + (0xA785, 'V'), + (0xA786, 'M', u'ꞇ'), + (0xA787, 'V'), + (0xA78B, 'M', u'ꞌ'), + (0xA78C, 'V'), + (0xA78D, 'M', u'ɥ'), + (0xA78E, 'V'), + (0xA790, 'M', u'ꞑ'), + (0xA791, 'V'), + (0xA792, 'M', u'ꞓ'), + (0xA793, 'V'), + (0xA796, 'M', u'ꞗ'), + (0xA797, 'V'), + (0xA798, 'M', u'ꞙ'), + (0xA799, 'V'), + (0xA79A, 'M', u'ꞛ'), + (0xA79B, 'V'), + (0xA79C, 'M', u'ꞝ'), + (0xA79D, 'V'), + (0xA79E, 'M', u'ꞟ'), + (0xA79F, 'V'), + (0xA7A0, 'M', u'ꞡ'), + (0xA7A1, 'V'), + (0xA7A2, 'M', u'ꞣ'), + (0xA7A3, 'V'), + (0xA7A4, 'M', u'ꞥ'), + (0xA7A5, 'V'), + (0xA7A6, 'M', u'ꞧ'), + (0xA7A7, 'V'), + (0xA7A8, 'M', u'ꞩ'), + (0xA7A9, 'V'), + (0xA7AA, 'M', u'ɦ'), + (0xA7AB, 'M', u'ɜ'), + (0xA7AC, 'M', u'ɡ'), + (0xA7AD, 'M', u'ɬ'), + (0xA7AE, 'M', u'ɪ'), + (0xA7AF, 'X'), + (0xA7B0, 'M', u'ʞ'), + (0xA7B1, 'M', u'ʇ'), + (0xA7B2, 'M', u'ʝ'), + (0xA7B3, 'M', u'ꭓ'), + (0xA7B4, 'M', u'ꞵ'), + (0xA7B5, 'V'), + (0xA7B6, 'M', u'ꞷ'), + (0xA7B7, 'V'), + (0xA7B8, 'X'), + (0xA7F7, 'V'), + (0xA7F8, 'M', u'ħ'), + (0xA7F9, 'M', u'œ'), + (0xA7FA, 'V'), + (0xA82C, 'X'), + (0xA830, 'V'), + (0xA83A, 'X'), + (0xA840, 'V'), + (0xA878, 'X'), + (0xA880, 'V'), + (0xA8C6, 'X'), + (0xA8CE, 'V'), + (0xA8DA, 'X'), + (0xA8E0, 'V'), + (0xA8FE, 'X'), + (0xA900, 'V'), + (0xA954, 'X'), + (0xA95F, 'V'), + (0xA97D, 'X'), + (0xA980, 'V'), + (0xA9CE, 'X'), + (0xA9CF, 'V'), + (0xA9DA, 'X'), + (0xA9DE, 'V'), + (0xA9FF, 'X'), + (0xAA00, 'V'), + (0xAA37, 'X'), + (0xAA40, 'V'), + (0xAA4E, 'X'), + (0xAA50, 'V'), + (0xAA5A, 'X'), + (0xAA5C, 'V'), + (0xAAC3, 'X'), + (0xAADB, 'V'), + (0xAAF7, 'X'), + (0xAB01, 'V'), + (0xAB07, 'X'), + (0xAB09, 'V'), + (0xAB0F, 'X'), + (0xAB11, 'V'), + (0xAB17, 'X'), + (0xAB20, 'V'), + (0xAB27, 'X'), + (0xAB28, 'V'), + (0xAB2F, 'X'), + (0xAB30, 'V'), + (0xAB5C, 'M', u'ꜧ'), + (0xAB5D, 'M', u'ꬷ'), + (0xAB5E, 'M', u'ɫ'), + (0xAB5F, 'M', u'ꭒ'), + (0xAB60, 'V'), + (0xAB66, 'X'), + ] + +def _seg_38(): + return [ + (0xAB70, 'M', u'Ꭰ'), + (0xAB71, 'M', u'Ꭱ'), + (0xAB72, 'M', u'Ꭲ'), + (0xAB73, 'M', u'Ꭳ'), + (0xAB74, 'M', u'Ꭴ'), + (0xAB75, 'M', u'Ꭵ'), + (0xAB76, 'M', u'Ꭶ'), + (0xAB77, 'M', u'Ꭷ'), + (0xAB78, 'M', u'Ꭸ'), + (0xAB79, 'M', u'Ꭹ'), + (0xAB7A, 'M', u'Ꭺ'), + (0xAB7B, 'M', u'Ꭻ'), + (0xAB7C, 'M', u'Ꭼ'), + (0xAB7D, 'M', u'Ꭽ'), + (0xAB7E, 'M', u'Ꭾ'), + (0xAB7F, 'M', u'Ꭿ'), + (0xAB80, 'M', u'Ꮀ'), + (0xAB81, 'M', u'Ꮁ'), + (0xAB82, 'M', u'Ꮂ'), + (0xAB83, 'M', u'Ꮃ'), + (0xAB84, 'M', u'Ꮄ'), + (0xAB85, 'M', u'Ꮅ'), + (0xAB86, 'M', u'Ꮆ'), + (0xAB87, 'M', u'Ꮇ'), + (0xAB88, 'M', u'Ꮈ'), + (0xAB89, 'M', u'Ꮉ'), + (0xAB8A, 'M', u'Ꮊ'), + (0xAB8B, 'M', u'Ꮋ'), + (0xAB8C, 'M', u'Ꮌ'), + (0xAB8D, 'M', u'Ꮍ'), + (0xAB8E, 'M', u'Ꮎ'), + (0xAB8F, 'M', u'Ꮏ'), + (0xAB90, 'M', u'Ꮐ'), + (0xAB91, 'M', u'Ꮑ'), + (0xAB92, 'M', u'Ꮒ'), + (0xAB93, 'M', u'Ꮓ'), + (0xAB94, 'M', u'Ꮔ'), + (0xAB95, 'M', u'Ꮕ'), + (0xAB96, 'M', u'Ꮖ'), + (0xAB97, 'M', u'Ꮗ'), + (0xAB98, 'M', u'Ꮘ'), + (0xAB99, 'M', u'Ꮙ'), + (0xAB9A, 'M', u'Ꮚ'), + (0xAB9B, 'M', u'Ꮛ'), + (0xAB9C, 'M', u'Ꮜ'), + (0xAB9D, 'M', u'Ꮝ'), + (0xAB9E, 'M', u'Ꮞ'), + (0xAB9F, 'M', u'Ꮟ'), + (0xABA0, 'M', u'Ꮠ'), + (0xABA1, 'M', u'Ꮡ'), + (0xABA2, 'M', u'Ꮢ'), + (0xABA3, 'M', u'Ꮣ'), + (0xABA4, 'M', u'Ꮤ'), + (0xABA5, 'M', u'Ꮥ'), + (0xABA6, 'M', u'Ꮦ'), + (0xABA7, 'M', u'Ꮧ'), + (0xABA8, 'M', u'Ꮨ'), + (0xABA9, 'M', u'Ꮩ'), + (0xABAA, 'M', u'Ꮪ'), + (0xABAB, 'M', u'Ꮫ'), + (0xABAC, 'M', u'Ꮬ'), + (0xABAD, 'M', u'Ꮭ'), + (0xABAE, 'M', u'Ꮮ'), + (0xABAF, 'M', u'Ꮯ'), + (0xABB0, 'M', u'Ꮰ'), + (0xABB1, 'M', u'Ꮱ'), + (0xABB2, 'M', u'Ꮲ'), + (0xABB3, 'M', u'Ꮳ'), + (0xABB4, 'M', u'Ꮴ'), + (0xABB5, 'M', u'Ꮵ'), + (0xABB6, 'M', u'Ꮶ'), + (0xABB7, 'M', u'Ꮷ'), + (0xABB8, 'M', u'Ꮸ'), + (0xABB9, 'M', u'Ꮹ'), + (0xABBA, 'M', u'Ꮺ'), + (0xABBB, 'M', u'Ꮻ'), + (0xABBC, 'M', u'Ꮼ'), + (0xABBD, 'M', u'Ꮽ'), + (0xABBE, 'M', u'Ꮾ'), + (0xABBF, 'M', u'Ꮿ'), + (0xABC0, 'V'), + (0xABEE, 'X'), + (0xABF0, 'V'), + (0xABFA, 'X'), + (0xAC00, 'V'), + (0xD7A4, 'X'), + (0xD7B0, 'V'), + (0xD7C7, 'X'), + (0xD7CB, 'V'), + (0xD7FC, 'X'), + (0xF900, 'M', u'豈'), + (0xF901, 'M', u'更'), + (0xF902, 'M', u'車'), + (0xF903, 'M', u'賈'), + (0xF904, 'M', u'滑'), + (0xF905, 'M', u'串'), + (0xF906, 'M', u'句'), + (0xF907, 'M', u'龜'), + (0xF909, 'M', u'契'), + (0xF90A, 'M', u'金'), + ] + +def _seg_39(): + return [ + (0xF90B, 'M', u'喇'), + (0xF90C, 'M', u'奈'), + (0xF90D, 'M', u'懶'), + (0xF90E, 'M', u'癩'), + (0xF90F, 'M', u'羅'), + (0xF910, 'M', u'蘿'), + (0xF911, 'M', u'螺'), + (0xF912, 'M', u'裸'), + (0xF913, 'M', u'邏'), + (0xF914, 'M', u'樂'), + (0xF915, 'M', u'洛'), + (0xF916, 'M', u'烙'), + (0xF917, 'M', u'珞'), + (0xF918, 'M', u'落'), + (0xF919, 'M', u'酪'), + (0xF91A, 'M', u'駱'), + (0xF91B, 'M', u'亂'), + (0xF91C, 'M', u'卵'), + (0xF91D, 'M', u'欄'), + (0xF91E, 'M', u'爛'), + (0xF91F, 'M', u'蘭'), + (0xF920, 'M', u'鸞'), + (0xF921, 'M', u'嵐'), + (0xF922, 'M', u'濫'), + (0xF923, 'M', u'藍'), + (0xF924, 'M', u'襤'), + (0xF925, 'M', u'拉'), + (0xF926, 'M', u'臘'), + (0xF927, 'M', u'蠟'), + (0xF928, 'M', u'廊'), + (0xF929, 'M', u'朗'), + (0xF92A, 'M', u'浪'), + (0xF92B, 'M', u'狼'), + (0xF92C, 'M', u'郎'), + (0xF92D, 'M', u'來'), + (0xF92E, 'M', u'冷'), + (0xF92F, 'M', u'勞'), + (0xF930, 'M', u'擄'), + (0xF931, 'M', u'櫓'), + (0xF932, 'M', u'爐'), + (0xF933, 'M', u'盧'), + (0xF934, 'M', u'老'), + (0xF935, 'M', u'蘆'), + (0xF936, 'M', u'虜'), + (0xF937, 'M', u'路'), + (0xF938, 'M', u'露'), + (0xF939, 'M', u'魯'), + (0xF93A, 'M', u'鷺'), + (0xF93B, 'M', u'碌'), + (0xF93C, 'M', u'祿'), + (0xF93D, 'M', u'綠'), + (0xF93E, 'M', u'菉'), + (0xF93F, 'M', u'錄'), + (0xF940, 'M', u'鹿'), + (0xF941, 'M', u'論'), + (0xF942, 'M', u'壟'), + (0xF943, 'M', u'弄'), + (0xF944, 'M', u'籠'), + (0xF945, 'M', u'聾'), + (0xF946, 'M', u'牢'), + (0xF947, 'M', u'磊'), + (0xF948, 'M', u'賂'), + (0xF949, 'M', u'雷'), + (0xF94A, 'M', u'壘'), + (0xF94B, 'M', u'屢'), + (0xF94C, 'M', u'樓'), + (0xF94D, 'M', u'淚'), + (0xF94E, 'M', u'漏'), + (0xF94F, 'M', u'累'), + (0xF950, 'M', u'縷'), + (0xF951, 'M', u'陋'), + (0xF952, 'M', u'勒'), + (0xF953, 'M', u'肋'), + (0xF954, 'M', u'凜'), + (0xF955, 'M', u'凌'), + (0xF956, 'M', u'稜'), + (0xF957, 'M', u'綾'), + (0xF958, 'M', u'菱'), + (0xF959, 'M', u'陵'), + (0xF95A, 'M', u'讀'), + (0xF95B, 'M', u'拏'), + (0xF95C, 'M', u'樂'), + (0xF95D, 'M', u'諾'), + (0xF95E, 'M', u'丹'), + (0xF95F, 'M', u'寧'), + (0xF960, 'M', u'怒'), + (0xF961, 'M', u'率'), + (0xF962, 'M', u'異'), + (0xF963, 'M', u'北'), + (0xF964, 'M', u'磻'), + (0xF965, 'M', u'便'), + (0xF966, 'M', u'復'), + (0xF967, 'M', u'不'), + (0xF968, 'M', u'泌'), + (0xF969, 'M', u'數'), + (0xF96A, 'M', u'索'), + (0xF96B, 'M', u'參'), + (0xF96C, 'M', u'塞'), + (0xF96D, 'M', u'省'), + (0xF96E, 'M', u'葉'), + ] + +def _seg_40(): + return [ + (0xF96F, 'M', u'說'), + (0xF970, 'M', u'殺'), + (0xF971, 'M', u'辰'), + (0xF972, 'M', u'沈'), + (0xF973, 'M', u'拾'), + (0xF974, 'M', u'若'), + (0xF975, 'M', u'掠'), + (0xF976, 'M', u'略'), + (0xF977, 'M', u'亮'), + (0xF978, 'M', u'兩'), + (0xF979, 'M', u'凉'), + (0xF97A, 'M', u'梁'), + (0xF97B, 'M', u'糧'), + (0xF97C, 'M', u'良'), + (0xF97D, 'M', u'諒'), + (0xF97E, 'M', u'量'), + (0xF97F, 'M', u'勵'), + (0xF980, 'M', u'呂'), + (0xF981, 'M', u'女'), + (0xF982, 'M', u'廬'), + (0xF983, 'M', u'旅'), + (0xF984, 'M', u'濾'), + (0xF985, 'M', u'礪'), + (0xF986, 'M', u'閭'), + (0xF987, 'M', u'驪'), + (0xF988, 'M', u'麗'), + (0xF989, 'M', u'黎'), + (0xF98A, 'M', u'力'), + (0xF98B, 'M', u'曆'), + (0xF98C, 'M', u'歷'), + (0xF98D, 'M', u'轢'), + (0xF98E, 'M', u'年'), + (0xF98F, 'M', u'憐'), + (0xF990, 'M', u'戀'), + (0xF991, 'M', u'撚'), + (0xF992, 'M', u'漣'), + (0xF993, 'M', u'煉'), + (0xF994, 'M', u'璉'), + (0xF995, 'M', u'秊'), + (0xF996, 'M', u'練'), + (0xF997, 'M', u'聯'), + (0xF998, 'M', u'輦'), + (0xF999, 'M', u'蓮'), + (0xF99A, 'M', u'連'), + (0xF99B, 'M', u'鍊'), + (0xF99C, 'M', u'列'), + (0xF99D, 'M', u'劣'), + (0xF99E, 'M', u'咽'), + (0xF99F, 'M', u'烈'), + (0xF9A0, 'M', u'裂'), + (0xF9A1, 'M', u'說'), + (0xF9A2, 'M', u'廉'), + (0xF9A3, 'M', u'念'), + (0xF9A4, 'M', u'捻'), + (0xF9A5, 'M', u'殮'), + (0xF9A6, 'M', u'簾'), + (0xF9A7, 'M', u'獵'), + (0xF9A8, 'M', u'令'), + (0xF9A9, 'M', u'囹'), + (0xF9AA, 'M', u'寧'), + (0xF9AB, 'M', u'嶺'), + (0xF9AC, 'M', u'怜'), + (0xF9AD, 'M', u'玲'), + (0xF9AE, 'M', u'瑩'), + (0xF9AF, 'M', u'羚'), + (0xF9B0, 'M', u'聆'), + (0xF9B1, 'M', u'鈴'), + (0xF9B2, 'M', u'零'), + (0xF9B3, 'M', u'靈'), + (0xF9B4, 'M', u'領'), + (0xF9B5, 'M', u'例'), + (0xF9B6, 'M', u'禮'), + (0xF9B7, 'M', u'醴'), + (0xF9B8, 'M', u'隸'), + (0xF9B9, 'M', u'惡'), + (0xF9BA, 'M', u'了'), + (0xF9BB, 'M', u'僚'), + (0xF9BC, 'M', u'寮'), + (0xF9BD, 'M', u'尿'), + (0xF9BE, 'M', u'料'), + (0xF9BF, 'M', u'樂'), + (0xF9C0, 'M', u'燎'), + (0xF9C1, 'M', u'療'), + (0xF9C2, 'M', u'蓼'), + (0xF9C3, 'M', u'遼'), + (0xF9C4, 'M', u'龍'), + (0xF9C5, 'M', u'暈'), + (0xF9C6, 'M', u'阮'), + (0xF9C7, 'M', u'劉'), + (0xF9C8, 'M', u'杻'), + (0xF9C9, 'M', u'柳'), + (0xF9CA, 'M', u'流'), + (0xF9CB, 'M', u'溜'), + (0xF9CC, 'M', u'琉'), + (0xF9CD, 'M', u'留'), + (0xF9CE, 'M', u'硫'), + (0xF9CF, 'M', u'紐'), + (0xF9D0, 'M', u'類'), + (0xF9D1, 'M', u'六'), + (0xF9D2, 'M', u'戮'), + ] + +def _seg_41(): + return [ + (0xF9D3, 'M', u'陸'), + (0xF9D4, 'M', u'倫'), + (0xF9D5, 'M', u'崙'), + (0xF9D6, 'M', u'淪'), + (0xF9D7, 'M', u'輪'), + (0xF9D8, 'M', u'律'), + (0xF9D9, 'M', u'慄'), + (0xF9DA, 'M', u'栗'), + (0xF9DB, 'M', u'率'), + (0xF9DC, 'M', u'隆'), + (0xF9DD, 'M', u'利'), + (0xF9DE, 'M', u'吏'), + (0xF9DF, 'M', u'履'), + (0xF9E0, 'M', u'易'), + (0xF9E1, 'M', u'李'), + (0xF9E2, 'M', u'梨'), + (0xF9E3, 'M', u'泥'), + (0xF9E4, 'M', u'理'), + (0xF9E5, 'M', u'痢'), + (0xF9E6, 'M', u'罹'), + (0xF9E7, 'M', u'裏'), + (0xF9E8, 'M', u'裡'), + (0xF9E9, 'M', u'里'), + (0xF9EA, 'M', u'離'), + (0xF9EB, 'M', u'匿'), + (0xF9EC, 'M', u'溺'), + (0xF9ED, 'M', u'吝'), + (0xF9EE, 'M', u'燐'), + (0xF9EF, 'M', u'璘'), + (0xF9F0, 'M', u'藺'), + (0xF9F1, 'M', u'隣'), + (0xF9F2, 'M', u'鱗'), + (0xF9F3, 'M', u'麟'), + (0xF9F4, 'M', u'林'), + (0xF9F5, 'M', u'淋'), + (0xF9F6, 'M', u'臨'), + (0xF9F7, 'M', u'立'), + (0xF9F8, 'M', u'笠'), + (0xF9F9, 'M', u'粒'), + (0xF9FA, 'M', u'狀'), + (0xF9FB, 'M', u'炙'), + (0xF9FC, 'M', u'識'), + (0xF9FD, 'M', u'什'), + (0xF9FE, 'M', u'茶'), + (0xF9FF, 'M', u'刺'), + (0xFA00, 'M', u'切'), + (0xFA01, 'M', u'度'), + (0xFA02, 'M', u'拓'), + (0xFA03, 'M', u'糖'), + (0xFA04, 'M', u'宅'), + (0xFA05, 'M', u'洞'), + (0xFA06, 'M', u'暴'), + (0xFA07, 'M', u'輻'), + (0xFA08, 'M', u'行'), + (0xFA09, 'M', u'降'), + (0xFA0A, 'M', u'見'), + (0xFA0B, 'M', u'廓'), + (0xFA0C, 'M', u'兀'), + (0xFA0D, 'M', u'嗀'), + (0xFA0E, 'V'), + (0xFA10, 'M', u'塚'), + (0xFA11, 'V'), + (0xFA12, 'M', u'晴'), + (0xFA13, 'V'), + (0xFA15, 'M', u'凞'), + (0xFA16, 'M', u'猪'), + (0xFA17, 'M', u'益'), + (0xFA18, 'M', u'礼'), + (0xFA19, 'M', u'神'), + (0xFA1A, 'M', u'祥'), + (0xFA1B, 'M', u'福'), + (0xFA1C, 'M', u'靖'), + (0xFA1D, 'M', u'精'), + (0xFA1E, 'M', u'羽'), + (0xFA1F, 'V'), + (0xFA20, 'M', u'蘒'), + (0xFA21, 'V'), + (0xFA22, 'M', u'諸'), + (0xFA23, 'V'), + (0xFA25, 'M', u'逸'), + (0xFA26, 'M', u'都'), + (0xFA27, 'V'), + (0xFA2A, 'M', u'飯'), + (0xFA2B, 'M', u'飼'), + (0xFA2C, 'M', u'館'), + (0xFA2D, 'M', u'鶴'), + (0xFA2E, 'M', u'郞'), + (0xFA2F, 'M', u'隷'), + (0xFA30, 'M', u'侮'), + (0xFA31, 'M', u'僧'), + (0xFA32, 'M', u'免'), + (0xFA33, 'M', u'勉'), + (0xFA34, 'M', u'勤'), + (0xFA35, 'M', u'卑'), + (0xFA36, 'M', u'喝'), + (0xFA37, 'M', u'嘆'), + (0xFA38, 'M', u'器'), + (0xFA39, 'M', u'塀'), + (0xFA3A, 'M', u'墨'), + (0xFA3B, 'M', u'層'), + ] + +def _seg_42(): + return [ + (0xFA3C, 'M', u'屮'), + (0xFA3D, 'M', u'悔'), + (0xFA3E, 'M', u'慨'), + (0xFA3F, 'M', u'憎'), + (0xFA40, 'M', u'懲'), + (0xFA41, 'M', u'敏'), + (0xFA42, 'M', u'既'), + (0xFA43, 'M', u'暑'), + (0xFA44, 'M', u'梅'), + (0xFA45, 'M', u'海'), + (0xFA46, 'M', u'渚'), + (0xFA47, 'M', u'漢'), + (0xFA48, 'M', u'煮'), + (0xFA49, 'M', u'爫'), + (0xFA4A, 'M', u'琢'), + (0xFA4B, 'M', u'碑'), + (0xFA4C, 'M', u'社'), + (0xFA4D, 'M', u'祉'), + (0xFA4E, 'M', u'祈'), + (0xFA4F, 'M', u'祐'), + (0xFA50, 'M', u'祖'), + (0xFA51, 'M', u'祝'), + (0xFA52, 'M', u'禍'), + (0xFA53, 'M', u'禎'), + (0xFA54, 'M', u'穀'), + (0xFA55, 'M', u'突'), + (0xFA56, 'M', u'節'), + (0xFA57, 'M', u'練'), + (0xFA58, 'M', u'縉'), + (0xFA59, 'M', u'繁'), + (0xFA5A, 'M', u'署'), + (0xFA5B, 'M', u'者'), + (0xFA5C, 'M', u'臭'), + (0xFA5D, 'M', u'艹'), + (0xFA5F, 'M', u'著'), + (0xFA60, 'M', u'褐'), + (0xFA61, 'M', u'視'), + (0xFA62, 'M', u'謁'), + (0xFA63, 'M', u'謹'), + (0xFA64, 'M', u'賓'), + (0xFA65, 'M', u'贈'), + (0xFA66, 'M', u'辶'), + (0xFA67, 'M', u'逸'), + (0xFA68, 'M', u'難'), + (0xFA69, 'M', u'響'), + (0xFA6A, 'M', u'頻'), + (0xFA6B, 'M', u'恵'), + (0xFA6C, 'M', u'𤋮'), + (0xFA6D, 'M', u'舘'), + (0xFA6E, 'X'), + (0xFA70, 'M', u'並'), + (0xFA71, 'M', u'况'), + (0xFA72, 'M', u'全'), + (0xFA73, 'M', u'侀'), + (0xFA74, 'M', u'充'), + (0xFA75, 'M', u'冀'), + (0xFA76, 'M', u'勇'), + (0xFA77, 'M', u'勺'), + (0xFA78, 'M', u'喝'), + (0xFA79, 'M', u'啕'), + (0xFA7A, 'M', u'喙'), + (0xFA7B, 'M', u'嗢'), + (0xFA7C, 'M', u'塚'), + (0xFA7D, 'M', u'墳'), + (0xFA7E, 'M', u'奄'), + (0xFA7F, 'M', u'奔'), + (0xFA80, 'M', u'婢'), + (0xFA81, 'M', u'嬨'), + (0xFA82, 'M', u'廒'), + (0xFA83, 'M', u'廙'), + (0xFA84, 'M', u'彩'), + (0xFA85, 'M', u'徭'), + (0xFA86, 'M', u'惘'), + (0xFA87, 'M', u'慎'), + (0xFA88, 'M', u'愈'), + (0xFA89, 'M', u'憎'), + (0xFA8A, 'M', u'慠'), + (0xFA8B, 'M', u'懲'), + (0xFA8C, 'M', u'戴'), + (0xFA8D, 'M', u'揄'), + (0xFA8E, 'M', u'搜'), + (0xFA8F, 'M', u'摒'), + (0xFA90, 'M', u'敖'), + (0xFA91, 'M', u'晴'), + (0xFA92, 'M', u'朗'), + (0xFA93, 'M', u'望'), + (0xFA94, 'M', u'杖'), + (0xFA95, 'M', u'歹'), + (0xFA96, 'M', u'殺'), + (0xFA97, 'M', u'流'), + (0xFA98, 'M', u'滛'), + (0xFA99, 'M', u'滋'), + (0xFA9A, 'M', u'漢'), + (0xFA9B, 'M', u'瀞'), + (0xFA9C, 'M', u'煮'), + (0xFA9D, 'M', u'瞧'), + (0xFA9E, 'M', u'爵'), + (0xFA9F, 'M', u'犯'), + (0xFAA0, 'M', u'猪'), + (0xFAA1, 'M', u'瑱'), + ] + +def _seg_43(): + return [ + (0xFAA2, 'M', u'甆'), + (0xFAA3, 'M', u'画'), + (0xFAA4, 'M', u'瘝'), + (0xFAA5, 'M', u'瘟'), + (0xFAA6, 'M', u'益'), + (0xFAA7, 'M', u'盛'), + (0xFAA8, 'M', u'直'), + (0xFAA9, 'M', u'睊'), + (0xFAAA, 'M', u'着'), + (0xFAAB, 'M', u'磌'), + (0xFAAC, 'M', u'窱'), + (0xFAAD, 'M', u'節'), + (0xFAAE, 'M', u'类'), + (0xFAAF, 'M', u'絛'), + (0xFAB0, 'M', u'練'), + (0xFAB1, 'M', u'缾'), + (0xFAB2, 'M', u'者'), + (0xFAB3, 'M', u'荒'), + (0xFAB4, 'M', u'華'), + (0xFAB5, 'M', u'蝹'), + (0xFAB6, 'M', u'襁'), + (0xFAB7, 'M', u'覆'), + (0xFAB8, 'M', u'視'), + (0xFAB9, 'M', u'調'), + (0xFABA, 'M', u'諸'), + (0xFABB, 'M', u'請'), + (0xFABC, 'M', u'謁'), + (0xFABD, 'M', u'諾'), + (0xFABE, 'M', u'諭'), + (0xFABF, 'M', u'謹'), + (0xFAC0, 'M', u'變'), + (0xFAC1, 'M', u'贈'), + (0xFAC2, 'M', u'輸'), + (0xFAC3, 'M', u'遲'), + (0xFAC4, 'M', u'醙'), + (0xFAC5, 'M', u'鉶'), + (0xFAC6, 'M', u'陼'), + (0xFAC7, 'M', u'難'), + (0xFAC8, 'M', u'靖'), + (0xFAC9, 'M', u'韛'), + (0xFACA, 'M', u'響'), + (0xFACB, 'M', u'頋'), + (0xFACC, 'M', u'頻'), + (0xFACD, 'M', u'鬒'), + (0xFACE, 'M', u'龜'), + (0xFACF, 'M', u'𢡊'), + (0xFAD0, 'M', u'𢡄'), + (0xFAD1, 'M', u'𣏕'), + (0xFAD2, 'M', u'㮝'), + (0xFAD3, 'M', u'䀘'), + (0xFAD4, 'M', u'䀹'), + (0xFAD5, 'M', u'𥉉'), + (0xFAD6, 'M', u'𥳐'), + (0xFAD7, 'M', u'𧻓'), + (0xFAD8, 'M', u'齃'), + (0xFAD9, 'M', u'龎'), + (0xFADA, 'X'), + (0xFB00, 'M', u'ff'), + (0xFB01, 'M', u'fi'), + (0xFB02, 'M', u'fl'), + (0xFB03, 'M', u'ffi'), + (0xFB04, 'M', u'ffl'), + (0xFB05, 'M', u'st'), + (0xFB07, 'X'), + (0xFB13, 'M', u'մն'), + (0xFB14, 'M', u'մե'), + (0xFB15, 'M', u'մի'), + (0xFB16, 'M', u'վն'), + (0xFB17, 'M', u'մխ'), + (0xFB18, 'X'), + (0xFB1D, 'M', u'יִ'), + (0xFB1E, 'V'), + (0xFB1F, 'M', u'ײַ'), + (0xFB20, 'M', u'ע'), + (0xFB21, 'M', u'א'), + (0xFB22, 'M', u'ד'), + (0xFB23, 'M', u'ה'), + (0xFB24, 'M', u'כ'), + (0xFB25, 'M', u'ל'), + (0xFB26, 'M', u'ם'), + (0xFB27, 'M', u'ר'), + (0xFB28, 'M', u'ת'), + (0xFB29, '3', u'+'), + (0xFB2A, 'M', u'שׁ'), + (0xFB2B, 'M', u'שׂ'), + (0xFB2C, 'M', u'שּׁ'), + (0xFB2D, 'M', u'שּׂ'), + (0xFB2E, 'M', u'אַ'), + (0xFB2F, 'M', u'אָ'), + (0xFB30, 'M', u'אּ'), + (0xFB31, 'M', u'בּ'), + (0xFB32, 'M', u'גּ'), + (0xFB33, 'M', u'דּ'), + (0xFB34, 'M', u'הּ'), + (0xFB35, 'M', u'וּ'), + (0xFB36, 'M', u'זּ'), + (0xFB37, 'X'), + (0xFB38, 'M', u'טּ'), + (0xFB39, 'M', u'יּ'), + (0xFB3A, 'M', u'ךּ'), + ] + +def _seg_44(): + return [ + (0xFB3B, 'M', u'כּ'), + (0xFB3C, 'M', u'לּ'), + (0xFB3D, 'X'), + (0xFB3E, 'M', u'מּ'), + (0xFB3F, 'X'), + (0xFB40, 'M', u'נּ'), + (0xFB41, 'M', u'סּ'), + (0xFB42, 'X'), + (0xFB43, 'M', u'ףּ'), + (0xFB44, 'M', u'פּ'), + (0xFB45, 'X'), + (0xFB46, 'M', u'צּ'), + (0xFB47, 'M', u'קּ'), + (0xFB48, 'M', u'רּ'), + (0xFB49, 'M', u'שּ'), + (0xFB4A, 'M', u'תּ'), + (0xFB4B, 'M', u'וֹ'), + (0xFB4C, 'M', u'בֿ'), + (0xFB4D, 'M', u'כֿ'), + (0xFB4E, 'M', u'פֿ'), + (0xFB4F, 'M', u'אל'), + (0xFB50, 'M', u'ٱ'), + (0xFB52, 'M', u'ٻ'), + (0xFB56, 'M', u'پ'), + (0xFB5A, 'M', u'ڀ'), + (0xFB5E, 'M', u'ٺ'), + (0xFB62, 'M', u'ٿ'), + (0xFB66, 'M', u'ٹ'), + (0xFB6A, 'M', u'ڤ'), + (0xFB6E, 'M', u'ڦ'), + (0xFB72, 'M', u'ڄ'), + (0xFB76, 'M', u'ڃ'), + (0xFB7A, 'M', u'چ'), + (0xFB7E, 'M', u'ڇ'), + (0xFB82, 'M', u'ڍ'), + (0xFB84, 'M', u'ڌ'), + (0xFB86, 'M', u'ڎ'), + (0xFB88, 'M', u'ڈ'), + (0xFB8A, 'M', u'ژ'), + (0xFB8C, 'M', u'ڑ'), + (0xFB8E, 'M', u'ک'), + (0xFB92, 'M', u'گ'), + (0xFB96, 'M', u'ڳ'), + (0xFB9A, 'M', u'ڱ'), + (0xFB9E, 'M', u'ں'), + (0xFBA0, 'M', u'ڻ'), + (0xFBA4, 'M', u'ۀ'), + (0xFBA6, 'M', u'ہ'), + (0xFBAA, 'M', u'ھ'), + (0xFBAE, 'M', u'ے'), + (0xFBB0, 'M', u'ۓ'), + (0xFBB2, 'V'), + (0xFBC2, 'X'), + (0xFBD3, 'M', u'ڭ'), + (0xFBD7, 'M', u'ۇ'), + (0xFBD9, 'M', u'ۆ'), + (0xFBDB, 'M', u'ۈ'), + (0xFBDD, 'M', u'ۇٴ'), + (0xFBDE, 'M', u'ۋ'), + (0xFBE0, 'M', u'ۅ'), + (0xFBE2, 'M', u'ۉ'), + (0xFBE4, 'M', u'ې'), + (0xFBE8, 'M', u'ى'), + (0xFBEA, 'M', u'ئا'), + (0xFBEC, 'M', u'ئە'), + (0xFBEE, 'M', u'ئو'), + (0xFBF0, 'M', u'ئۇ'), + (0xFBF2, 'M', u'ئۆ'), + (0xFBF4, 'M', u'ئۈ'), + (0xFBF6, 'M', u'ئې'), + (0xFBF9, 'M', u'ئى'), + (0xFBFC, 'M', u'ی'), + (0xFC00, 'M', u'ئج'), + (0xFC01, 'M', u'ئح'), + (0xFC02, 'M', u'ئم'), + (0xFC03, 'M', u'ئى'), + (0xFC04, 'M', u'ئي'), + (0xFC05, 'M', u'بج'), + (0xFC06, 'M', u'بح'), + (0xFC07, 'M', u'بخ'), + (0xFC08, 'M', u'بم'), + (0xFC09, 'M', u'بى'), + (0xFC0A, 'M', u'بي'), + (0xFC0B, 'M', u'تج'), + (0xFC0C, 'M', u'تح'), + (0xFC0D, 'M', u'تخ'), + (0xFC0E, 'M', u'تم'), + (0xFC0F, 'M', u'تى'), + (0xFC10, 'M', u'تي'), + (0xFC11, 'M', u'ثج'), + (0xFC12, 'M', u'ثم'), + (0xFC13, 'M', u'ثى'), + (0xFC14, 'M', u'ثي'), + (0xFC15, 'M', u'جح'), + (0xFC16, 'M', u'جم'), + (0xFC17, 'M', u'حج'), + (0xFC18, 'M', u'حم'), + (0xFC19, 'M', u'خج'), + (0xFC1A, 'M', u'خح'), + (0xFC1B, 'M', u'خم'), + ] + +def _seg_45(): + return [ + (0xFC1C, 'M', u'سج'), + (0xFC1D, 'M', u'سح'), + (0xFC1E, 'M', u'سخ'), + (0xFC1F, 'M', u'سم'), + (0xFC20, 'M', u'صح'), + (0xFC21, 'M', u'صم'), + (0xFC22, 'M', u'ضج'), + (0xFC23, 'M', u'ضح'), + (0xFC24, 'M', u'ضخ'), + (0xFC25, 'M', u'ضم'), + (0xFC26, 'M', u'طح'), + (0xFC27, 'M', u'طم'), + (0xFC28, 'M', u'ظم'), + (0xFC29, 'M', u'عج'), + (0xFC2A, 'M', u'عم'), + (0xFC2B, 'M', u'غج'), + (0xFC2C, 'M', u'غم'), + (0xFC2D, 'M', u'فج'), + (0xFC2E, 'M', u'فح'), + (0xFC2F, 'M', u'فخ'), + (0xFC30, 'M', u'فم'), + (0xFC31, 'M', u'فى'), + (0xFC32, 'M', u'في'), + (0xFC33, 'M', u'قح'), + (0xFC34, 'M', u'قم'), + (0xFC35, 'M', u'قى'), + (0xFC36, 'M', u'قي'), + (0xFC37, 'M', u'كا'), + (0xFC38, 'M', u'كج'), + (0xFC39, 'M', u'كح'), + (0xFC3A, 'M', u'كخ'), + (0xFC3B, 'M', u'كل'), + (0xFC3C, 'M', u'كم'), + (0xFC3D, 'M', u'كى'), + (0xFC3E, 'M', u'كي'), + (0xFC3F, 'M', u'لج'), + (0xFC40, 'M', u'لح'), + (0xFC41, 'M', u'لخ'), + (0xFC42, 'M', u'لم'), + (0xFC43, 'M', u'لى'), + (0xFC44, 'M', u'لي'), + (0xFC45, 'M', u'مج'), + (0xFC46, 'M', u'مح'), + (0xFC47, 'M', u'مخ'), + (0xFC48, 'M', u'مم'), + (0xFC49, 'M', u'مى'), + (0xFC4A, 'M', u'مي'), + (0xFC4B, 'M', u'نج'), + (0xFC4C, 'M', u'نح'), + (0xFC4D, 'M', u'نخ'), + (0xFC4E, 'M', u'نم'), + (0xFC4F, 'M', u'نى'), + (0xFC50, 'M', u'ني'), + (0xFC51, 'M', u'هج'), + (0xFC52, 'M', u'هم'), + (0xFC53, 'M', u'هى'), + (0xFC54, 'M', u'هي'), + (0xFC55, 'M', u'يج'), + (0xFC56, 'M', u'يح'), + (0xFC57, 'M', u'يخ'), + (0xFC58, 'M', u'يم'), + (0xFC59, 'M', u'يى'), + (0xFC5A, 'M', u'يي'), + (0xFC5B, 'M', u'ذٰ'), + (0xFC5C, 'M', u'رٰ'), + (0xFC5D, 'M', u'ىٰ'), + (0xFC5E, '3', u' ٌّ'), + (0xFC5F, '3', u' ٍّ'), + (0xFC60, '3', u' َّ'), + (0xFC61, '3', u' ُّ'), + (0xFC62, '3', u' ِّ'), + (0xFC63, '3', u' ّٰ'), + (0xFC64, 'M', u'ئر'), + (0xFC65, 'M', u'ئز'), + (0xFC66, 'M', u'ئم'), + (0xFC67, 'M', u'ئن'), + (0xFC68, 'M', u'ئى'), + (0xFC69, 'M', u'ئي'), + (0xFC6A, 'M', u'بر'), + (0xFC6B, 'M', u'بز'), + (0xFC6C, 'M', u'بم'), + (0xFC6D, 'M', u'بن'), + (0xFC6E, 'M', u'بى'), + (0xFC6F, 'M', u'بي'), + (0xFC70, 'M', u'تر'), + (0xFC71, 'M', u'تز'), + (0xFC72, 'M', u'تم'), + (0xFC73, 'M', u'تن'), + (0xFC74, 'M', u'تى'), + (0xFC75, 'M', u'تي'), + (0xFC76, 'M', u'ثر'), + (0xFC77, 'M', u'ثز'), + (0xFC78, 'M', u'ثم'), + (0xFC79, 'M', u'ثن'), + (0xFC7A, 'M', u'ثى'), + (0xFC7B, 'M', u'ثي'), + (0xFC7C, 'M', u'فى'), + (0xFC7D, 'M', u'في'), + (0xFC7E, 'M', u'قى'), + (0xFC7F, 'M', u'قي'), + ] + +def _seg_46(): + return [ + (0xFC80, 'M', u'كا'), + (0xFC81, 'M', u'كل'), + (0xFC82, 'M', u'كم'), + (0xFC83, 'M', u'كى'), + (0xFC84, 'M', u'كي'), + (0xFC85, 'M', u'لم'), + (0xFC86, 'M', u'لى'), + (0xFC87, 'M', u'لي'), + (0xFC88, 'M', u'ما'), + (0xFC89, 'M', u'مم'), + (0xFC8A, 'M', u'نر'), + (0xFC8B, 'M', u'نز'), + (0xFC8C, 'M', u'نم'), + (0xFC8D, 'M', u'نن'), + (0xFC8E, 'M', u'نى'), + (0xFC8F, 'M', u'ني'), + (0xFC90, 'M', u'ىٰ'), + (0xFC91, 'M', u'ير'), + (0xFC92, 'M', u'يز'), + (0xFC93, 'M', u'يم'), + (0xFC94, 'M', u'ين'), + (0xFC95, 'M', u'يى'), + (0xFC96, 'M', u'يي'), + (0xFC97, 'M', u'ئج'), + (0xFC98, 'M', u'ئح'), + (0xFC99, 'M', u'ئخ'), + (0xFC9A, 'M', u'ئم'), + (0xFC9B, 'M', u'ئه'), + (0xFC9C, 'M', u'بج'), + (0xFC9D, 'M', u'بح'), + (0xFC9E, 'M', u'بخ'), + (0xFC9F, 'M', u'بم'), + (0xFCA0, 'M', u'به'), + (0xFCA1, 'M', u'تج'), + (0xFCA2, 'M', u'تح'), + (0xFCA3, 'M', u'تخ'), + (0xFCA4, 'M', u'تم'), + (0xFCA5, 'M', u'ته'), + (0xFCA6, 'M', u'ثم'), + (0xFCA7, 'M', u'جح'), + (0xFCA8, 'M', u'جم'), + (0xFCA9, 'M', u'حج'), + (0xFCAA, 'M', u'حم'), + (0xFCAB, 'M', u'خج'), + (0xFCAC, 'M', u'خم'), + (0xFCAD, 'M', u'سج'), + (0xFCAE, 'M', u'سح'), + (0xFCAF, 'M', u'سخ'), + (0xFCB0, 'M', u'سم'), + (0xFCB1, 'M', u'صح'), + (0xFCB2, 'M', u'صخ'), + (0xFCB3, 'M', u'صم'), + (0xFCB4, 'M', u'ضج'), + (0xFCB5, 'M', u'ضح'), + (0xFCB6, 'M', u'ضخ'), + (0xFCB7, 'M', u'ضم'), + (0xFCB8, 'M', u'طح'), + (0xFCB9, 'M', u'ظم'), + (0xFCBA, 'M', u'عج'), + (0xFCBB, 'M', u'عم'), + (0xFCBC, 'M', u'غج'), + (0xFCBD, 'M', u'غم'), + (0xFCBE, 'M', u'فج'), + (0xFCBF, 'M', u'فح'), + (0xFCC0, 'M', u'فخ'), + (0xFCC1, 'M', u'فم'), + (0xFCC2, 'M', u'قح'), + (0xFCC3, 'M', u'قم'), + (0xFCC4, 'M', u'كج'), + (0xFCC5, 'M', u'كح'), + (0xFCC6, 'M', u'كخ'), + (0xFCC7, 'M', u'كل'), + (0xFCC8, 'M', u'كم'), + (0xFCC9, 'M', u'لج'), + (0xFCCA, 'M', u'لح'), + (0xFCCB, 'M', u'لخ'), + (0xFCCC, 'M', u'لم'), + (0xFCCD, 'M', u'له'), + (0xFCCE, 'M', u'مج'), + (0xFCCF, 'M', u'مح'), + (0xFCD0, 'M', u'مخ'), + (0xFCD1, 'M', u'مم'), + (0xFCD2, 'M', u'نج'), + (0xFCD3, 'M', u'نح'), + (0xFCD4, 'M', u'نخ'), + (0xFCD5, 'M', u'نم'), + (0xFCD6, 'M', u'نه'), + (0xFCD7, 'M', u'هج'), + (0xFCD8, 'M', u'هم'), + (0xFCD9, 'M', u'هٰ'), + (0xFCDA, 'M', u'يج'), + (0xFCDB, 'M', u'يح'), + (0xFCDC, 'M', u'يخ'), + (0xFCDD, 'M', u'يم'), + (0xFCDE, 'M', u'يه'), + (0xFCDF, 'M', u'ئم'), + (0xFCE0, 'M', u'ئه'), + (0xFCE1, 'M', u'بم'), + (0xFCE2, 'M', u'به'), + (0xFCE3, 'M', u'تم'), + ] + +def _seg_47(): + return [ + (0xFCE4, 'M', u'ته'), + (0xFCE5, 'M', u'ثم'), + (0xFCE6, 'M', u'ثه'), + (0xFCE7, 'M', u'سم'), + (0xFCE8, 'M', u'سه'), + (0xFCE9, 'M', u'شم'), + (0xFCEA, 'M', u'شه'), + (0xFCEB, 'M', u'كل'), + (0xFCEC, 'M', u'كم'), + (0xFCED, 'M', u'لم'), + (0xFCEE, 'M', u'نم'), + (0xFCEF, 'M', u'نه'), + (0xFCF0, 'M', u'يم'), + (0xFCF1, 'M', u'يه'), + (0xFCF2, 'M', u'ـَّ'), + (0xFCF3, 'M', u'ـُّ'), + (0xFCF4, 'M', u'ـِّ'), + (0xFCF5, 'M', u'طى'), + (0xFCF6, 'M', u'طي'), + (0xFCF7, 'M', u'عى'), + (0xFCF8, 'M', u'عي'), + (0xFCF9, 'M', u'غى'), + (0xFCFA, 'M', u'غي'), + (0xFCFB, 'M', u'سى'), + (0xFCFC, 'M', u'سي'), + (0xFCFD, 'M', u'شى'), + (0xFCFE, 'M', u'شي'), + (0xFCFF, 'M', u'حى'), + (0xFD00, 'M', u'حي'), + (0xFD01, 'M', u'جى'), + (0xFD02, 'M', u'جي'), + (0xFD03, 'M', u'خى'), + (0xFD04, 'M', u'خي'), + (0xFD05, 'M', u'صى'), + (0xFD06, 'M', u'صي'), + (0xFD07, 'M', u'ضى'), + (0xFD08, 'M', u'ضي'), + (0xFD09, 'M', u'شج'), + (0xFD0A, 'M', u'شح'), + (0xFD0B, 'M', u'شخ'), + (0xFD0C, 'M', u'شم'), + (0xFD0D, 'M', u'شر'), + (0xFD0E, 'M', u'سر'), + (0xFD0F, 'M', u'صر'), + (0xFD10, 'M', u'ضر'), + (0xFD11, 'M', u'طى'), + (0xFD12, 'M', u'طي'), + (0xFD13, 'M', u'عى'), + (0xFD14, 'M', u'عي'), + (0xFD15, 'M', u'غى'), + (0xFD16, 'M', u'غي'), + (0xFD17, 'M', u'سى'), + (0xFD18, 'M', u'سي'), + (0xFD19, 'M', u'شى'), + (0xFD1A, 'M', u'شي'), + (0xFD1B, 'M', u'حى'), + (0xFD1C, 'M', u'حي'), + (0xFD1D, 'M', u'جى'), + (0xFD1E, 'M', u'جي'), + (0xFD1F, 'M', u'خى'), + (0xFD20, 'M', u'خي'), + (0xFD21, 'M', u'صى'), + (0xFD22, 'M', u'صي'), + (0xFD23, 'M', u'ضى'), + (0xFD24, 'M', u'ضي'), + (0xFD25, 'M', u'شج'), + (0xFD26, 'M', u'شح'), + (0xFD27, 'M', u'شخ'), + (0xFD28, 'M', u'شم'), + (0xFD29, 'M', u'شر'), + (0xFD2A, 'M', u'سر'), + (0xFD2B, 'M', u'صر'), + (0xFD2C, 'M', u'ضر'), + (0xFD2D, 'M', u'شج'), + (0xFD2E, 'M', u'شح'), + (0xFD2F, 'M', u'شخ'), + (0xFD30, 'M', u'شم'), + (0xFD31, 'M', u'سه'), + (0xFD32, 'M', u'شه'), + (0xFD33, 'M', u'طم'), + (0xFD34, 'M', u'سج'), + (0xFD35, 'M', u'سح'), + (0xFD36, 'M', u'سخ'), + (0xFD37, 'M', u'شج'), + (0xFD38, 'M', u'شح'), + (0xFD39, 'M', u'شخ'), + (0xFD3A, 'M', u'طم'), + (0xFD3B, 'M', u'ظم'), + (0xFD3C, 'M', u'اً'), + (0xFD3E, 'V'), + (0xFD40, 'X'), + (0xFD50, 'M', u'تجم'), + (0xFD51, 'M', u'تحج'), + (0xFD53, 'M', u'تحم'), + (0xFD54, 'M', u'تخم'), + (0xFD55, 'M', u'تمج'), + (0xFD56, 'M', u'تمح'), + (0xFD57, 'M', u'تمخ'), + (0xFD58, 'M', u'جمح'), + (0xFD5A, 'M', u'حمي'), + ] + +def _seg_48(): + return [ + (0xFD5B, 'M', u'حمى'), + (0xFD5C, 'M', u'سحج'), + (0xFD5D, 'M', u'سجح'), + (0xFD5E, 'M', u'سجى'), + (0xFD5F, 'M', u'سمح'), + (0xFD61, 'M', u'سمج'), + (0xFD62, 'M', u'سمم'), + (0xFD64, 'M', u'صحح'), + (0xFD66, 'M', u'صمم'), + (0xFD67, 'M', u'شحم'), + (0xFD69, 'M', u'شجي'), + (0xFD6A, 'M', u'شمخ'), + (0xFD6C, 'M', u'شمم'), + (0xFD6E, 'M', u'ضحى'), + (0xFD6F, 'M', u'ضخم'), + (0xFD71, 'M', u'طمح'), + (0xFD73, 'M', u'طمم'), + (0xFD74, 'M', u'طمي'), + (0xFD75, 'M', u'عجم'), + (0xFD76, 'M', u'عمم'), + (0xFD78, 'M', u'عمى'), + (0xFD79, 'M', u'غمم'), + (0xFD7A, 'M', u'غمي'), + (0xFD7B, 'M', u'غمى'), + (0xFD7C, 'M', u'فخم'), + (0xFD7E, 'M', u'قمح'), + (0xFD7F, 'M', u'قمم'), + (0xFD80, 'M', u'لحم'), + (0xFD81, 'M', u'لحي'), + (0xFD82, 'M', u'لحى'), + (0xFD83, 'M', u'لجج'), + (0xFD85, 'M', u'لخم'), + (0xFD87, 'M', u'لمح'), + (0xFD89, 'M', u'محج'), + (0xFD8A, 'M', u'محم'), + (0xFD8B, 'M', u'محي'), + (0xFD8C, 'M', u'مجح'), + (0xFD8D, 'M', u'مجم'), + (0xFD8E, 'M', u'مخج'), + (0xFD8F, 'M', u'مخم'), + (0xFD90, 'X'), + (0xFD92, 'M', u'مجخ'), + (0xFD93, 'M', u'همج'), + (0xFD94, 'M', u'همم'), + (0xFD95, 'M', u'نحم'), + (0xFD96, 'M', u'نحى'), + (0xFD97, 'M', u'نجم'), + (0xFD99, 'M', u'نجى'), + (0xFD9A, 'M', u'نمي'), + (0xFD9B, 'M', u'نمى'), + (0xFD9C, 'M', u'يمم'), + (0xFD9E, 'M', u'بخي'), + (0xFD9F, 'M', u'تجي'), + (0xFDA0, 'M', u'تجى'), + (0xFDA1, 'M', u'تخي'), + (0xFDA2, 'M', u'تخى'), + (0xFDA3, 'M', u'تمي'), + (0xFDA4, 'M', u'تمى'), + (0xFDA5, 'M', u'جمي'), + (0xFDA6, 'M', u'جحى'), + (0xFDA7, 'M', u'جمى'), + (0xFDA8, 'M', u'سخى'), + (0xFDA9, 'M', u'صحي'), + (0xFDAA, 'M', u'شحي'), + (0xFDAB, 'M', u'ضحي'), + (0xFDAC, 'M', u'لجي'), + (0xFDAD, 'M', u'لمي'), + (0xFDAE, 'M', u'يحي'), + (0xFDAF, 'M', u'يجي'), + (0xFDB0, 'M', u'يمي'), + (0xFDB1, 'M', u'ممي'), + (0xFDB2, 'M', u'قمي'), + (0xFDB3, 'M', u'نحي'), + (0xFDB4, 'M', u'قمح'), + (0xFDB5, 'M', u'لحم'), + (0xFDB6, 'M', u'عمي'), + (0xFDB7, 'M', u'كمي'), + (0xFDB8, 'M', u'نجح'), + (0xFDB9, 'M', u'مخي'), + (0xFDBA, 'M', u'لجم'), + (0xFDBB, 'M', u'كمم'), + (0xFDBC, 'M', u'لجم'), + (0xFDBD, 'M', u'نجح'), + (0xFDBE, 'M', u'جحي'), + (0xFDBF, 'M', u'حجي'), + (0xFDC0, 'M', u'مجي'), + (0xFDC1, 'M', u'فمي'), + (0xFDC2, 'M', u'بحي'), + (0xFDC3, 'M', u'كمم'), + (0xFDC4, 'M', u'عجم'), + (0xFDC5, 'M', u'صمم'), + (0xFDC6, 'M', u'سخي'), + (0xFDC7, 'M', u'نجي'), + (0xFDC8, 'X'), + (0xFDF0, 'M', u'صلے'), + (0xFDF1, 'M', u'قلے'), + (0xFDF2, 'M', u'الله'), + (0xFDF3, 'M', u'اكبر'), + (0xFDF4, 'M', u'محمد'), + (0xFDF5, 'M', u'صلعم'), + ] + +def _seg_49(): + return [ + (0xFDF6, 'M', u'رسول'), + (0xFDF7, 'M', u'عليه'), + (0xFDF8, 'M', u'وسلم'), + (0xFDF9, 'M', u'صلى'), + (0xFDFA, '3', u'صلى الله عليه وسلم'), + (0xFDFB, '3', u'جل جلاله'), + (0xFDFC, 'M', u'ریال'), + (0xFDFD, 'V'), + (0xFDFE, 'X'), + (0xFE00, 'I'), + (0xFE10, '3', u','), + (0xFE11, 'M', u'、'), + (0xFE12, 'X'), + (0xFE13, '3', u':'), + (0xFE14, '3', u';'), + (0xFE15, '3', u'!'), + (0xFE16, '3', u'?'), + (0xFE17, 'M', u'〖'), + (0xFE18, 'M', u'〗'), + (0xFE19, 'X'), + (0xFE20, 'V'), + (0xFE30, 'X'), + (0xFE31, 'M', u'—'), + (0xFE32, 'M', u'–'), + (0xFE33, '3', u'_'), + (0xFE35, '3', u'('), + (0xFE36, '3', u')'), + (0xFE37, '3', u'{'), + (0xFE38, '3', u'}'), + (0xFE39, 'M', u'〔'), + (0xFE3A, 'M', u'〕'), + (0xFE3B, 'M', u'【'), + (0xFE3C, 'M', u'】'), + (0xFE3D, 'M', u'《'), + (0xFE3E, 'M', u'》'), + (0xFE3F, 'M', u'〈'), + (0xFE40, 'M', u'〉'), + (0xFE41, 'M', u'「'), + (0xFE42, 'M', u'」'), + (0xFE43, 'M', u'『'), + (0xFE44, 'M', u'』'), + (0xFE45, 'V'), + (0xFE47, '3', u'['), + (0xFE48, '3', u']'), + (0xFE49, '3', u' ̅'), + (0xFE4D, '3', u'_'), + (0xFE50, '3', u','), + (0xFE51, 'M', u'、'), + (0xFE52, 'X'), + (0xFE54, '3', u';'), + (0xFE55, '3', u':'), + (0xFE56, '3', u'?'), + (0xFE57, '3', u'!'), + (0xFE58, 'M', u'—'), + (0xFE59, '3', u'('), + (0xFE5A, '3', u')'), + (0xFE5B, '3', u'{'), + (0xFE5C, '3', u'}'), + (0xFE5D, 'M', u'〔'), + (0xFE5E, 'M', u'〕'), + (0xFE5F, '3', u'#'), + (0xFE60, '3', u'&'), + (0xFE61, '3', u'*'), + (0xFE62, '3', u'+'), + (0xFE63, 'M', u'-'), + (0xFE64, '3', u'<'), + (0xFE65, '3', u'>'), + (0xFE66, '3', u'='), + (0xFE67, 'X'), + (0xFE68, '3', u'\\'), + (0xFE69, '3', u'$'), + (0xFE6A, '3', u'%'), + (0xFE6B, '3', u'@'), + (0xFE6C, 'X'), + (0xFE70, '3', u' ً'), + (0xFE71, 'M', u'ـً'), + (0xFE72, '3', u' ٌ'), + (0xFE73, 'V'), + (0xFE74, '3', u' ٍ'), + (0xFE75, 'X'), + (0xFE76, '3', u' َ'), + (0xFE77, 'M', u'ـَ'), + (0xFE78, '3', u' ُ'), + (0xFE79, 'M', u'ـُ'), + (0xFE7A, '3', u' ِ'), + (0xFE7B, 'M', u'ـِ'), + (0xFE7C, '3', u' ّ'), + (0xFE7D, 'M', u'ـّ'), + (0xFE7E, '3', u' ْ'), + (0xFE7F, 'M', u'ـْ'), + (0xFE80, 'M', u'ء'), + (0xFE81, 'M', u'آ'), + (0xFE83, 'M', u'أ'), + (0xFE85, 'M', u'ؤ'), + (0xFE87, 'M', u'إ'), + (0xFE89, 'M', u'ئ'), + (0xFE8D, 'M', u'ا'), + (0xFE8F, 'M', u'ب'), + (0xFE93, 'M', u'ة'), + (0xFE95, 'M', u'ت'), + ] + +def _seg_50(): + return [ + (0xFE99, 'M', u'ث'), + (0xFE9D, 'M', u'ج'), + (0xFEA1, 'M', u'ح'), + (0xFEA5, 'M', u'خ'), + (0xFEA9, 'M', u'د'), + (0xFEAB, 'M', u'ذ'), + (0xFEAD, 'M', u'ر'), + (0xFEAF, 'M', u'ز'), + (0xFEB1, 'M', u'س'), + (0xFEB5, 'M', u'ش'), + (0xFEB9, 'M', u'ص'), + (0xFEBD, 'M', u'ض'), + (0xFEC1, 'M', u'ط'), + (0xFEC5, 'M', u'ظ'), + (0xFEC9, 'M', u'ع'), + (0xFECD, 'M', u'غ'), + (0xFED1, 'M', u'ف'), + (0xFED5, 'M', u'ق'), + (0xFED9, 'M', u'ك'), + (0xFEDD, 'M', u'ل'), + (0xFEE1, 'M', u'م'), + (0xFEE5, 'M', u'ن'), + (0xFEE9, 'M', u'ه'), + (0xFEED, 'M', u'و'), + (0xFEEF, 'M', u'ى'), + (0xFEF1, 'M', u'ي'), + (0xFEF5, 'M', u'لآ'), + (0xFEF7, 'M', u'لأ'), + (0xFEF9, 'M', u'لإ'), + (0xFEFB, 'M', u'لا'), + (0xFEFD, 'X'), + (0xFEFF, 'I'), + (0xFF00, 'X'), + (0xFF01, '3', u'!'), + (0xFF02, '3', u'"'), + (0xFF03, '3', u'#'), + (0xFF04, '3', u'$'), + (0xFF05, '3', u'%'), + (0xFF06, '3', u'&'), + (0xFF07, '3', u'\''), + (0xFF08, '3', u'('), + (0xFF09, '3', u')'), + (0xFF0A, '3', u'*'), + (0xFF0B, '3', u'+'), + (0xFF0C, '3', u','), + (0xFF0D, 'M', u'-'), + (0xFF0E, 'M', u'.'), + (0xFF0F, '3', u'/'), + (0xFF10, 'M', u'0'), + (0xFF11, 'M', u'1'), + (0xFF12, 'M', u'2'), + (0xFF13, 'M', u'3'), + (0xFF14, 'M', u'4'), + (0xFF15, 'M', u'5'), + (0xFF16, 'M', u'6'), + (0xFF17, 'M', u'7'), + (0xFF18, 'M', u'8'), + (0xFF19, 'M', u'9'), + (0xFF1A, '3', u':'), + (0xFF1B, '3', u';'), + (0xFF1C, '3', u'<'), + (0xFF1D, '3', u'='), + (0xFF1E, '3', u'>'), + (0xFF1F, '3', u'?'), + (0xFF20, '3', u'@'), + (0xFF21, 'M', u'a'), + (0xFF22, 'M', u'b'), + (0xFF23, 'M', u'c'), + (0xFF24, 'M', u'd'), + (0xFF25, 'M', u'e'), + (0xFF26, 'M', u'f'), + (0xFF27, 'M', u'g'), + (0xFF28, 'M', u'h'), + (0xFF29, 'M', u'i'), + (0xFF2A, 'M', u'j'), + (0xFF2B, 'M', u'k'), + (0xFF2C, 'M', u'l'), + (0xFF2D, 'M', u'm'), + (0xFF2E, 'M', u'n'), + (0xFF2F, 'M', u'o'), + (0xFF30, 'M', u'p'), + (0xFF31, 'M', u'q'), + (0xFF32, 'M', u'r'), + (0xFF33, 'M', u's'), + (0xFF34, 'M', u't'), + (0xFF35, 'M', u'u'), + (0xFF36, 'M', u'v'), + (0xFF37, 'M', u'w'), + (0xFF38, 'M', u'x'), + (0xFF39, 'M', u'y'), + (0xFF3A, 'M', u'z'), + (0xFF3B, '3', u'['), + (0xFF3C, '3', u'\\'), + (0xFF3D, '3', u']'), + (0xFF3E, '3', u'^'), + (0xFF3F, '3', u'_'), + (0xFF40, '3', u'`'), + (0xFF41, 'M', u'a'), + (0xFF42, 'M', u'b'), + (0xFF43, 'M', u'c'), + ] + +def _seg_51(): + return [ + (0xFF44, 'M', u'd'), + (0xFF45, 'M', u'e'), + (0xFF46, 'M', u'f'), + (0xFF47, 'M', u'g'), + (0xFF48, 'M', u'h'), + (0xFF49, 'M', u'i'), + (0xFF4A, 'M', u'j'), + (0xFF4B, 'M', u'k'), + (0xFF4C, 'M', u'l'), + (0xFF4D, 'M', u'm'), + (0xFF4E, 'M', u'n'), + (0xFF4F, 'M', u'o'), + (0xFF50, 'M', u'p'), + (0xFF51, 'M', u'q'), + (0xFF52, 'M', u'r'), + (0xFF53, 'M', u's'), + (0xFF54, 'M', u't'), + (0xFF55, 'M', u'u'), + (0xFF56, 'M', u'v'), + (0xFF57, 'M', u'w'), + (0xFF58, 'M', u'x'), + (0xFF59, 'M', u'y'), + (0xFF5A, 'M', u'z'), + (0xFF5B, '3', u'{'), + (0xFF5C, '3', u'|'), + (0xFF5D, '3', u'}'), + (0xFF5E, '3', u'~'), + (0xFF5F, 'M', u'⦅'), + (0xFF60, 'M', u'⦆'), + (0xFF61, 'M', u'.'), + (0xFF62, 'M', u'「'), + (0xFF63, 'M', u'」'), + (0xFF64, 'M', u'、'), + (0xFF65, 'M', u'・'), + (0xFF66, 'M', u'ヲ'), + (0xFF67, 'M', u'ァ'), + (0xFF68, 'M', u'ィ'), + (0xFF69, 'M', u'ゥ'), + (0xFF6A, 'M', u'ェ'), + (0xFF6B, 'M', u'ォ'), + (0xFF6C, 'M', u'ャ'), + (0xFF6D, 'M', u'ュ'), + (0xFF6E, 'M', u'ョ'), + (0xFF6F, 'M', u'ッ'), + (0xFF70, 'M', u'ー'), + (0xFF71, 'M', u'ア'), + (0xFF72, 'M', u'イ'), + (0xFF73, 'M', u'ウ'), + (0xFF74, 'M', u'エ'), + (0xFF75, 'M', u'オ'), + (0xFF76, 'M', u'カ'), + (0xFF77, 'M', u'キ'), + (0xFF78, 'M', u'ク'), + (0xFF79, 'M', u'ケ'), + (0xFF7A, 'M', u'コ'), + (0xFF7B, 'M', u'サ'), + (0xFF7C, 'M', u'シ'), + (0xFF7D, 'M', u'ス'), + (0xFF7E, 'M', u'セ'), + (0xFF7F, 'M', u'ソ'), + (0xFF80, 'M', u'タ'), + (0xFF81, 'M', u'チ'), + (0xFF82, 'M', u'ツ'), + (0xFF83, 'M', u'テ'), + (0xFF84, 'M', u'ト'), + (0xFF85, 'M', u'ナ'), + (0xFF86, 'M', u'ニ'), + (0xFF87, 'M', u'ヌ'), + (0xFF88, 'M', u'ネ'), + (0xFF89, 'M', u'ノ'), + (0xFF8A, 'M', u'ハ'), + (0xFF8B, 'M', u'ヒ'), + (0xFF8C, 'M', u'フ'), + (0xFF8D, 'M', u'ヘ'), + (0xFF8E, 'M', u'ホ'), + (0xFF8F, 'M', u'マ'), + (0xFF90, 'M', u'ミ'), + (0xFF91, 'M', u'ム'), + (0xFF92, 'M', u'メ'), + (0xFF93, 'M', u'モ'), + (0xFF94, 'M', u'ヤ'), + (0xFF95, 'M', u'ユ'), + (0xFF96, 'M', u'ヨ'), + (0xFF97, 'M', u'ラ'), + (0xFF98, 'M', u'リ'), + (0xFF99, 'M', u'ル'), + (0xFF9A, 'M', u'レ'), + (0xFF9B, 'M', u'ロ'), + (0xFF9C, 'M', u'ワ'), + (0xFF9D, 'M', u'ン'), + (0xFF9E, 'M', u'゙'), + (0xFF9F, 'M', u'゚'), + (0xFFA0, 'X'), + (0xFFA1, 'M', u'ᄀ'), + (0xFFA2, 'M', u'ᄁ'), + (0xFFA3, 'M', u'ᆪ'), + (0xFFA4, 'M', u'ᄂ'), + (0xFFA5, 'M', u'ᆬ'), + (0xFFA6, 'M', u'ᆭ'), + (0xFFA7, 'M', u'ᄃ'), + ] + +def _seg_52(): + return [ + (0xFFA8, 'M', u'ᄄ'), + (0xFFA9, 'M', u'ᄅ'), + (0xFFAA, 'M', u'ᆰ'), + (0xFFAB, 'M', u'ᆱ'), + (0xFFAC, 'M', u'ᆲ'), + (0xFFAD, 'M', u'ᆳ'), + (0xFFAE, 'M', u'ᆴ'), + (0xFFAF, 'M', u'ᆵ'), + (0xFFB0, 'M', u'ᄚ'), + (0xFFB1, 'M', u'ᄆ'), + (0xFFB2, 'M', u'ᄇ'), + (0xFFB3, 'M', u'ᄈ'), + (0xFFB4, 'M', u'ᄡ'), + (0xFFB5, 'M', u'ᄉ'), + (0xFFB6, 'M', u'ᄊ'), + (0xFFB7, 'M', u'ᄋ'), + (0xFFB8, 'M', u'ᄌ'), + (0xFFB9, 'M', u'ᄍ'), + (0xFFBA, 'M', u'ᄎ'), + (0xFFBB, 'M', u'ᄏ'), + (0xFFBC, 'M', u'ᄐ'), + (0xFFBD, 'M', u'ᄑ'), + (0xFFBE, 'M', u'ᄒ'), + (0xFFBF, 'X'), + (0xFFC2, 'M', u'ᅡ'), + (0xFFC3, 'M', u'ᅢ'), + (0xFFC4, 'M', u'ᅣ'), + (0xFFC5, 'M', u'ᅤ'), + (0xFFC6, 'M', u'ᅥ'), + (0xFFC7, 'M', u'ᅦ'), + (0xFFC8, 'X'), + (0xFFCA, 'M', u'ᅧ'), + (0xFFCB, 'M', u'ᅨ'), + (0xFFCC, 'M', u'ᅩ'), + (0xFFCD, 'M', u'ᅪ'), + (0xFFCE, 'M', u'ᅫ'), + (0xFFCF, 'M', u'ᅬ'), + (0xFFD0, 'X'), + (0xFFD2, 'M', u'ᅭ'), + (0xFFD3, 'M', u'ᅮ'), + (0xFFD4, 'M', u'ᅯ'), + (0xFFD5, 'M', u'ᅰ'), + (0xFFD6, 'M', u'ᅱ'), + (0xFFD7, 'M', u'ᅲ'), + (0xFFD8, 'X'), + (0xFFDA, 'M', u'ᅳ'), + (0xFFDB, 'M', u'ᅴ'), + (0xFFDC, 'M', u'ᅵ'), + (0xFFDD, 'X'), + (0xFFE0, 'M', u'¢'), + (0xFFE1, 'M', u'£'), + (0xFFE2, 'M', u'¬'), + (0xFFE3, '3', u' ̄'), + (0xFFE4, 'M', u'¦'), + (0xFFE5, 'M', u'¥'), + (0xFFE6, 'M', u'₩'), + (0xFFE7, 'X'), + (0xFFE8, 'M', u'│'), + (0xFFE9, 'M', u'←'), + (0xFFEA, 'M', u'↑'), + (0xFFEB, 'M', u'→'), + (0xFFEC, 'M', u'↓'), + (0xFFED, 'M', u'■'), + (0xFFEE, 'M', u'○'), + (0xFFEF, 'X'), + (0x10000, 'V'), + (0x1000C, 'X'), + (0x1000D, 'V'), + (0x10027, 'X'), + (0x10028, 'V'), + (0x1003B, 'X'), + (0x1003C, 'V'), + (0x1003E, 'X'), + (0x1003F, 'V'), + (0x1004E, 'X'), + (0x10050, 'V'), + (0x1005E, 'X'), + (0x10080, 'V'), + (0x100FB, 'X'), + (0x10100, 'V'), + (0x10103, 'X'), + (0x10107, 'V'), + (0x10134, 'X'), + (0x10137, 'V'), + (0x1018F, 'X'), + (0x10190, 'V'), + (0x1019C, 'X'), + (0x101A0, 'V'), + (0x101A1, 'X'), + (0x101D0, 'V'), + (0x101FE, 'X'), + (0x10280, 'V'), + (0x1029D, 'X'), + (0x102A0, 'V'), + (0x102D1, 'X'), + (0x102E0, 'V'), + (0x102FC, 'X'), + (0x10300, 'V'), + (0x10324, 'X'), + (0x1032D, 'V'), + ] + +def _seg_53(): + return [ + (0x1034B, 'X'), + (0x10350, 'V'), + (0x1037B, 'X'), + (0x10380, 'V'), + (0x1039E, 'X'), + (0x1039F, 'V'), + (0x103C4, 'X'), + (0x103C8, 'V'), + (0x103D6, 'X'), + (0x10400, 'M', u'𐐨'), + (0x10401, 'M', u'𐐩'), + (0x10402, 'M', u'𐐪'), + (0x10403, 'M', u'𐐫'), + (0x10404, 'M', u'𐐬'), + (0x10405, 'M', u'𐐭'), + (0x10406, 'M', u'𐐮'), + (0x10407, 'M', u'𐐯'), + (0x10408, 'M', u'𐐰'), + (0x10409, 'M', u'𐐱'), + (0x1040A, 'M', u'𐐲'), + (0x1040B, 'M', u'𐐳'), + (0x1040C, 'M', u'𐐴'), + (0x1040D, 'M', u'𐐵'), + (0x1040E, 'M', u'𐐶'), + (0x1040F, 'M', u'𐐷'), + (0x10410, 'M', u'𐐸'), + (0x10411, 'M', u'𐐹'), + (0x10412, 'M', u'𐐺'), + (0x10413, 'M', u'𐐻'), + (0x10414, 'M', u'𐐼'), + (0x10415, 'M', u'𐐽'), + (0x10416, 'M', u'𐐾'), + (0x10417, 'M', u'𐐿'), + (0x10418, 'M', u'𐑀'), + (0x10419, 'M', u'𐑁'), + (0x1041A, 'M', u'𐑂'), + (0x1041B, 'M', u'𐑃'), + (0x1041C, 'M', u'𐑄'), + (0x1041D, 'M', u'𐑅'), + (0x1041E, 'M', u'𐑆'), + (0x1041F, 'M', u'𐑇'), + (0x10420, 'M', u'𐑈'), + (0x10421, 'M', u'𐑉'), + (0x10422, 'M', u'𐑊'), + (0x10423, 'M', u'𐑋'), + (0x10424, 'M', u'𐑌'), + (0x10425, 'M', u'𐑍'), + (0x10426, 'M', u'𐑎'), + (0x10427, 'M', u'𐑏'), + (0x10428, 'V'), + (0x1049E, 'X'), + (0x104A0, 'V'), + (0x104AA, 'X'), + (0x104B0, 'M', u'𐓘'), + (0x104B1, 'M', u'𐓙'), + (0x104B2, 'M', u'𐓚'), + (0x104B3, 'M', u'𐓛'), + (0x104B4, 'M', u'𐓜'), + (0x104B5, 'M', u'𐓝'), + (0x104B6, 'M', u'𐓞'), + (0x104B7, 'M', u'𐓟'), + (0x104B8, 'M', u'𐓠'), + (0x104B9, 'M', u'𐓡'), + (0x104BA, 'M', u'𐓢'), + (0x104BB, 'M', u'𐓣'), + (0x104BC, 'M', u'𐓤'), + (0x104BD, 'M', u'𐓥'), + (0x104BE, 'M', u'𐓦'), + (0x104BF, 'M', u'𐓧'), + (0x104C0, 'M', u'𐓨'), + (0x104C1, 'M', u'𐓩'), + (0x104C2, 'M', u'𐓪'), + (0x104C3, 'M', u'𐓫'), + (0x104C4, 'M', u'𐓬'), + (0x104C5, 'M', u'𐓭'), + (0x104C6, 'M', u'𐓮'), + (0x104C7, 'M', u'𐓯'), + (0x104C8, 'M', u'𐓰'), + (0x104C9, 'M', u'𐓱'), + (0x104CA, 'M', u'𐓲'), + (0x104CB, 'M', u'𐓳'), + (0x104CC, 'M', u'𐓴'), + (0x104CD, 'M', u'𐓵'), + (0x104CE, 'M', u'𐓶'), + (0x104CF, 'M', u'𐓷'), + (0x104D0, 'M', u'𐓸'), + (0x104D1, 'M', u'𐓹'), + (0x104D2, 'M', u'𐓺'), + (0x104D3, 'M', u'𐓻'), + (0x104D4, 'X'), + (0x104D8, 'V'), + (0x104FC, 'X'), + (0x10500, 'V'), + (0x10528, 'X'), + (0x10530, 'V'), + (0x10564, 'X'), + (0x1056F, 'V'), + (0x10570, 'X'), + (0x10600, 'V'), + (0x10737, 'X'), + ] + +def _seg_54(): + return [ + (0x10740, 'V'), + (0x10756, 'X'), + (0x10760, 'V'), + (0x10768, 'X'), + (0x10800, 'V'), + (0x10806, 'X'), + (0x10808, 'V'), + (0x10809, 'X'), + (0x1080A, 'V'), + (0x10836, 'X'), + (0x10837, 'V'), + (0x10839, 'X'), + (0x1083C, 'V'), + (0x1083D, 'X'), + (0x1083F, 'V'), + (0x10856, 'X'), + (0x10857, 'V'), + (0x1089F, 'X'), + (0x108A7, 'V'), + (0x108B0, 'X'), + (0x108E0, 'V'), + (0x108F3, 'X'), + (0x108F4, 'V'), + (0x108F6, 'X'), + (0x108FB, 'V'), + (0x1091C, 'X'), + (0x1091F, 'V'), + (0x1093A, 'X'), + (0x1093F, 'V'), + (0x10940, 'X'), + (0x10980, 'V'), + (0x109B8, 'X'), + (0x109BC, 'V'), + (0x109D0, 'X'), + (0x109D2, 'V'), + (0x10A04, 'X'), + (0x10A05, 'V'), + (0x10A07, 'X'), + (0x10A0C, 'V'), + (0x10A14, 'X'), + (0x10A15, 'V'), + (0x10A18, 'X'), + (0x10A19, 'V'), + (0x10A34, 'X'), + (0x10A38, 'V'), + (0x10A3B, 'X'), + (0x10A3F, 'V'), + (0x10A48, 'X'), + (0x10A50, 'V'), + (0x10A59, 'X'), + (0x10A60, 'V'), + (0x10AA0, 'X'), + (0x10AC0, 'V'), + (0x10AE7, 'X'), + (0x10AEB, 'V'), + (0x10AF7, 'X'), + (0x10B00, 'V'), + (0x10B36, 'X'), + (0x10B39, 'V'), + (0x10B56, 'X'), + (0x10B58, 'V'), + (0x10B73, 'X'), + (0x10B78, 'V'), + (0x10B92, 'X'), + (0x10B99, 'V'), + (0x10B9D, 'X'), + (0x10BA9, 'V'), + (0x10BB0, 'X'), + (0x10C00, 'V'), + (0x10C49, 'X'), + (0x10C80, 'M', u'𐳀'), + (0x10C81, 'M', u'𐳁'), + (0x10C82, 'M', u'𐳂'), + (0x10C83, 'M', u'𐳃'), + (0x10C84, 'M', u'𐳄'), + (0x10C85, 'M', u'𐳅'), + (0x10C86, 'M', u'𐳆'), + (0x10C87, 'M', u'𐳇'), + (0x10C88, 'M', u'𐳈'), + (0x10C89, 'M', u'𐳉'), + (0x10C8A, 'M', u'𐳊'), + (0x10C8B, 'M', u'𐳋'), + (0x10C8C, 'M', u'𐳌'), + (0x10C8D, 'M', u'𐳍'), + (0x10C8E, 'M', u'𐳎'), + (0x10C8F, 'M', u'𐳏'), + (0x10C90, 'M', u'𐳐'), + (0x10C91, 'M', u'𐳑'), + (0x10C92, 'M', u'𐳒'), + (0x10C93, 'M', u'𐳓'), + (0x10C94, 'M', u'𐳔'), + (0x10C95, 'M', u'𐳕'), + (0x10C96, 'M', u'𐳖'), + (0x10C97, 'M', u'𐳗'), + (0x10C98, 'M', u'𐳘'), + (0x10C99, 'M', u'𐳙'), + (0x10C9A, 'M', u'𐳚'), + (0x10C9B, 'M', u'𐳛'), + (0x10C9C, 'M', u'𐳜'), + (0x10C9D, 'M', u'𐳝'), + ] + +def _seg_55(): + return [ + (0x10C9E, 'M', u'𐳞'), + (0x10C9F, 'M', u'𐳟'), + (0x10CA0, 'M', u'𐳠'), + (0x10CA1, 'M', u'𐳡'), + (0x10CA2, 'M', u'𐳢'), + (0x10CA3, 'M', u'𐳣'), + (0x10CA4, 'M', u'𐳤'), + (0x10CA5, 'M', u'𐳥'), + (0x10CA6, 'M', u'𐳦'), + (0x10CA7, 'M', u'𐳧'), + (0x10CA8, 'M', u'𐳨'), + (0x10CA9, 'M', u'𐳩'), + (0x10CAA, 'M', u'𐳪'), + (0x10CAB, 'M', u'𐳫'), + (0x10CAC, 'M', u'𐳬'), + (0x10CAD, 'M', u'𐳭'), + (0x10CAE, 'M', u'𐳮'), + (0x10CAF, 'M', u'𐳯'), + (0x10CB0, 'M', u'𐳰'), + (0x10CB1, 'M', u'𐳱'), + (0x10CB2, 'M', u'𐳲'), + (0x10CB3, 'X'), + (0x10CC0, 'V'), + (0x10CF3, 'X'), + (0x10CFA, 'V'), + (0x10D00, 'X'), + (0x10E60, 'V'), + (0x10E7F, 'X'), + (0x11000, 'V'), + (0x1104E, 'X'), + (0x11052, 'V'), + (0x11070, 'X'), + (0x1107F, 'V'), + (0x110BD, 'X'), + (0x110BE, 'V'), + (0x110C2, 'X'), + (0x110D0, 'V'), + (0x110E9, 'X'), + (0x110F0, 'V'), + (0x110FA, 'X'), + (0x11100, 'V'), + (0x11135, 'X'), + (0x11136, 'V'), + (0x11144, 'X'), + (0x11150, 'V'), + (0x11177, 'X'), + (0x11180, 'V'), + (0x111CE, 'X'), + (0x111D0, 'V'), + (0x111E0, 'X'), + (0x111E1, 'V'), + (0x111F5, 'X'), + (0x11200, 'V'), + (0x11212, 'X'), + (0x11213, 'V'), + (0x1123F, 'X'), + (0x11280, 'V'), + (0x11287, 'X'), + (0x11288, 'V'), + (0x11289, 'X'), + (0x1128A, 'V'), + (0x1128E, 'X'), + (0x1128F, 'V'), + (0x1129E, 'X'), + (0x1129F, 'V'), + (0x112AA, 'X'), + (0x112B0, 'V'), + (0x112EB, 'X'), + (0x112F0, 'V'), + (0x112FA, 'X'), + (0x11300, 'V'), + (0x11304, 'X'), + (0x11305, 'V'), + (0x1130D, 'X'), + (0x1130F, 'V'), + (0x11311, 'X'), + (0x11313, 'V'), + (0x11329, 'X'), + (0x1132A, 'V'), + (0x11331, 'X'), + (0x11332, 'V'), + (0x11334, 'X'), + (0x11335, 'V'), + (0x1133A, 'X'), + (0x1133C, 'V'), + (0x11345, 'X'), + (0x11347, 'V'), + (0x11349, 'X'), + (0x1134B, 'V'), + (0x1134E, 'X'), + (0x11350, 'V'), + (0x11351, 'X'), + (0x11357, 'V'), + (0x11358, 'X'), + (0x1135D, 'V'), + (0x11364, 'X'), + (0x11366, 'V'), + (0x1136D, 'X'), + (0x11370, 'V'), + (0x11375, 'X'), + ] + +def _seg_56(): + return [ + (0x11400, 'V'), + (0x1145A, 'X'), + (0x1145B, 'V'), + (0x1145C, 'X'), + (0x1145D, 'V'), + (0x1145E, 'X'), + (0x11480, 'V'), + (0x114C8, 'X'), + (0x114D0, 'V'), + (0x114DA, 'X'), + (0x11580, 'V'), + (0x115B6, 'X'), + (0x115B8, 'V'), + (0x115DE, 'X'), + (0x11600, 'V'), + (0x11645, 'X'), + (0x11650, 'V'), + (0x1165A, 'X'), + (0x11660, 'V'), + (0x1166D, 'X'), + (0x11680, 'V'), + (0x116B8, 'X'), + (0x116C0, 'V'), + (0x116CA, 'X'), + (0x11700, 'V'), + (0x1171A, 'X'), + (0x1171D, 'V'), + (0x1172C, 'X'), + (0x11730, 'V'), + (0x11740, 'X'), + (0x118A0, 'M', u'𑣀'), + (0x118A1, 'M', u'𑣁'), + (0x118A2, 'M', u'𑣂'), + (0x118A3, 'M', u'𑣃'), + (0x118A4, 'M', u'𑣄'), + (0x118A5, 'M', u'𑣅'), + (0x118A6, 'M', u'𑣆'), + (0x118A7, 'M', u'𑣇'), + (0x118A8, 'M', u'𑣈'), + (0x118A9, 'M', u'𑣉'), + (0x118AA, 'M', u'𑣊'), + (0x118AB, 'M', u'𑣋'), + (0x118AC, 'M', u'𑣌'), + (0x118AD, 'M', u'𑣍'), + (0x118AE, 'M', u'𑣎'), + (0x118AF, 'M', u'𑣏'), + (0x118B0, 'M', u'𑣐'), + (0x118B1, 'M', u'𑣑'), + (0x118B2, 'M', u'𑣒'), + (0x118B3, 'M', u'𑣓'), + (0x118B4, 'M', u'𑣔'), + (0x118B5, 'M', u'𑣕'), + (0x118B6, 'M', u'𑣖'), + (0x118B7, 'M', u'𑣗'), + (0x118B8, 'M', u'𑣘'), + (0x118B9, 'M', u'𑣙'), + (0x118BA, 'M', u'𑣚'), + (0x118BB, 'M', u'𑣛'), + (0x118BC, 'M', u'𑣜'), + (0x118BD, 'M', u'𑣝'), + (0x118BE, 'M', u'𑣞'), + (0x118BF, 'M', u'𑣟'), + (0x118C0, 'V'), + (0x118F3, 'X'), + (0x118FF, 'V'), + (0x11900, 'X'), + (0x11A00, 'V'), + (0x11A48, 'X'), + (0x11A50, 'V'), + (0x11A84, 'X'), + (0x11A86, 'V'), + (0x11A9D, 'X'), + (0x11A9E, 'V'), + (0x11AA3, 'X'), + (0x11AC0, 'V'), + (0x11AF9, 'X'), + (0x11C00, 'V'), + (0x11C09, 'X'), + (0x11C0A, 'V'), + (0x11C37, 'X'), + (0x11C38, 'V'), + (0x11C46, 'X'), + (0x11C50, 'V'), + (0x11C6D, 'X'), + (0x11C70, 'V'), + (0x11C90, 'X'), + (0x11C92, 'V'), + (0x11CA8, 'X'), + (0x11CA9, 'V'), + (0x11CB7, 'X'), + (0x11D00, 'V'), + (0x11D07, 'X'), + (0x11D08, 'V'), + (0x11D0A, 'X'), + (0x11D0B, 'V'), + (0x11D37, 'X'), + (0x11D3A, 'V'), + (0x11D3B, 'X'), + (0x11D3C, 'V'), + (0x11D3E, 'X'), + ] + +def _seg_57(): + return [ + (0x11D3F, 'V'), + (0x11D48, 'X'), + (0x11D50, 'V'), + (0x11D5A, 'X'), + (0x12000, 'V'), + (0x1239A, 'X'), + (0x12400, 'V'), + (0x1246F, 'X'), + (0x12470, 'V'), + (0x12475, 'X'), + (0x12480, 'V'), + (0x12544, 'X'), + (0x13000, 'V'), + (0x1342F, 'X'), + (0x14400, 'V'), + (0x14647, 'X'), + (0x16800, 'V'), + (0x16A39, 'X'), + (0x16A40, 'V'), + (0x16A5F, 'X'), + (0x16A60, 'V'), + (0x16A6A, 'X'), + (0x16A6E, 'V'), + (0x16A70, 'X'), + (0x16AD0, 'V'), + (0x16AEE, 'X'), + (0x16AF0, 'V'), + (0x16AF6, 'X'), + (0x16B00, 'V'), + (0x16B46, 'X'), + (0x16B50, 'V'), + (0x16B5A, 'X'), + (0x16B5B, 'V'), + (0x16B62, 'X'), + (0x16B63, 'V'), + (0x16B78, 'X'), + (0x16B7D, 'V'), + (0x16B90, 'X'), + (0x16F00, 'V'), + (0x16F45, 'X'), + (0x16F50, 'V'), + (0x16F7F, 'X'), + (0x16F8F, 'V'), + (0x16FA0, 'X'), + (0x16FE0, 'V'), + (0x16FE2, 'X'), + (0x17000, 'V'), + (0x187ED, 'X'), + (0x18800, 'V'), + (0x18AF3, 'X'), + (0x1B000, 'V'), + (0x1B11F, 'X'), + (0x1B170, 'V'), + (0x1B2FC, 'X'), + (0x1BC00, 'V'), + (0x1BC6B, 'X'), + (0x1BC70, 'V'), + (0x1BC7D, 'X'), + (0x1BC80, 'V'), + (0x1BC89, 'X'), + (0x1BC90, 'V'), + (0x1BC9A, 'X'), + (0x1BC9C, 'V'), + (0x1BCA0, 'I'), + (0x1BCA4, 'X'), + (0x1D000, 'V'), + (0x1D0F6, 'X'), + (0x1D100, 'V'), + (0x1D127, 'X'), + (0x1D129, 'V'), + (0x1D15E, 'M', u'𝅗𝅥'), + (0x1D15F, 'M', u'𝅘𝅥'), + (0x1D160, 'M', u'𝅘𝅥𝅮'), + (0x1D161, 'M', u'𝅘𝅥𝅯'), + (0x1D162, 'M', u'𝅘𝅥𝅰'), + (0x1D163, 'M', u'𝅘𝅥𝅱'), + (0x1D164, 'M', u'𝅘𝅥𝅲'), + (0x1D165, 'V'), + (0x1D173, 'X'), + (0x1D17B, 'V'), + (0x1D1BB, 'M', u'𝆹𝅥'), + (0x1D1BC, 'M', u'𝆺𝅥'), + (0x1D1BD, 'M', u'𝆹𝅥𝅮'), + (0x1D1BE, 'M', u'𝆺𝅥𝅮'), + (0x1D1BF, 'M', u'𝆹𝅥𝅯'), + (0x1D1C0, 'M', u'𝆺𝅥𝅯'), + (0x1D1C1, 'V'), + (0x1D1E9, 'X'), + (0x1D200, 'V'), + (0x1D246, 'X'), + (0x1D300, 'V'), + (0x1D357, 'X'), + (0x1D360, 'V'), + (0x1D372, 'X'), + (0x1D400, 'M', u'a'), + (0x1D401, 'M', u'b'), + (0x1D402, 'M', u'c'), + (0x1D403, 'M', u'd'), + (0x1D404, 'M', u'e'), + (0x1D405, 'M', u'f'), + ] + +def _seg_58(): + return [ + (0x1D406, 'M', u'g'), + (0x1D407, 'M', u'h'), + (0x1D408, 'M', u'i'), + (0x1D409, 'M', u'j'), + (0x1D40A, 'M', u'k'), + (0x1D40B, 'M', u'l'), + (0x1D40C, 'M', u'm'), + (0x1D40D, 'M', u'n'), + (0x1D40E, 'M', u'o'), + (0x1D40F, 'M', u'p'), + (0x1D410, 'M', u'q'), + (0x1D411, 'M', u'r'), + (0x1D412, 'M', u's'), + (0x1D413, 'M', u't'), + (0x1D414, 'M', u'u'), + (0x1D415, 'M', u'v'), + (0x1D416, 'M', u'w'), + (0x1D417, 'M', u'x'), + (0x1D418, 'M', u'y'), + (0x1D419, 'M', u'z'), + (0x1D41A, 'M', u'a'), + (0x1D41B, 'M', u'b'), + (0x1D41C, 'M', u'c'), + (0x1D41D, 'M', u'd'), + (0x1D41E, 'M', u'e'), + (0x1D41F, 'M', u'f'), + (0x1D420, 'M', u'g'), + (0x1D421, 'M', u'h'), + (0x1D422, 'M', u'i'), + (0x1D423, 'M', u'j'), + (0x1D424, 'M', u'k'), + (0x1D425, 'M', u'l'), + (0x1D426, 'M', u'm'), + (0x1D427, 'M', u'n'), + (0x1D428, 'M', u'o'), + (0x1D429, 'M', u'p'), + (0x1D42A, 'M', u'q'), + (0x1D42B, 'M', u'r'), + (0x1D42C, 'M', u's'), + (0x1D42D, 'M', u't'), + (0x1D42E, 'M', u'u'), + (0x1D42F, 'M', u'v'), + (0x1D430, 'M', u'w'), + (0x1D431, 'M', u'x'), + (0x1D432, 'M', u'y'), + (0x1D433, 'M', u'z'), + (0x1D434, 'M', u'a'), + (0x1D435, 'M', u'b'), + (0x1D436, 'M', u'c'), + (0x1D437, 'M', u'd'), + (0x1D438, 'M', u'e'), + (0x1D439, 'M', u'f'), + (0x1D43A, 'M', u'g'), + (0x1D43B, 'M', u'h'), + (0x1D43C, 'M', u'i'), + (0x1D43D, 'M', u'j'), + (0x1D43E, 'M', u'k'), + (0x1D43F, 'M', u'l'), + (0x1D440, 'M', u'm'), + (0x1D441, 'M', u'n'), + (0x1D442, 'M', u'o'), + (0x1D443, 'M', u'p'), + (0x1D444, 'M', u'q'), + (0x1D445, 'M', u'r'), + (0x1D446, 'M', u's'), + (0x1D447, 'M', u't'), + (0x1D448, 'M', u'u'), + (0x1D449, 'M', u'v'), + (0x1D44A, 'M', u'w'), + (0x1D44B, 'M', u'x'), + (0x1D44C, 'M', u'y'), + (0x1D44D, 'M', u'z'), + (0x1D44E, 'M', u'a'), + (0x1D44F, 'M', u'b'), + (0x1D450, 'M', u'c'), + (0x1D451, 'M', u'd'), + (0x1D452, 'M', u'e'), + (0x1D453, 'M', u'f'), + (0x1D454, 'M', u'g'), + (0x1D455, 'X'), + (0x1D456, 'M', u'i'), + (0x1D457, 'M', u'j'), + (0x1D458, 'M', u'k'), + (0x1D459, 'M', u'l'), + (0x1D45A, 'M', u'm'), + (0x1D45B, 'M', u'n'), + (0x1D45C, 'M', u'o'), + (0x1D45D, 'M', u'p'), + (0x1D45E, 'M', u'q'), + (0x1D45F, 'M', u'r'), + (0x1D460, 'M', u's'), + (0x1D461, 'M', u't'), + (0x1D462, 'M', u'u'), + (0x1D463, 'M', u'v'), + (0x1D464, 'M', u'w'), + (0x1D465, 'M', u'x'), + (0x1D466, 'M', u'y'), + (0x1D467, 'M', u'z'), + (0x1D468, 'M', u'a'), + (0x1D469, 'M', u'b'), + ] + +def _seg_59(): + return [ + (0x1D46A, 'M', u'c'), + (0x1D46B, 'M', u'd'), + (0x1D46C, 'M', u'e'), + (0x1D46D, 'M', u'f'), + (0x1D46E, 'M', u'g'), + (0x1D46F, 'M', u'h'), + (0x1D470, 'M', u'i'), + (0x1D471, 'M', u'j'), + (0x1D472, 'M', u'k'), + (0x1D473, 'M', u'l'), + (0x1D474, 'M', u'm'), + (0x1D475, 'M', u'n'), + (0x1D476, 'M', u'o'), + (0x1D477, 'M', u'p'), + (0x1D478, 'M', u'q'), + (0x1D479, 'M', u'r'), + (0x1D47A, 'M', u's'), + (0x1D47B, 'M', u't'), + (0x1D47C, 'M', u'u'), + (0x1D47D, 'M', u'v'), + (0x1D47E, 'M', u'w'), + (0x1D47F, 'M', u'x'), + (0x1D480, 'M', u'y'), + (0x1D481, 'M', u'z'), + (0x1D482, 'M', u'a'), + (0x1D483, 'M', u'b'), + (0x1D484, 'M', u'c'), + (0x1D485, 'M', u'd'), + (0x1D486, 'M', u'e'), + (0x1D487, 'M', u'f'), + (0x1D488, 'M', u'g'), + (0x1D489, 'M', u'h'), + (0x1D48A, 'M', u'i'), + (0x1D48B, 'M', u'j'), + (0x1D48C, 'M', u'k'), + (0x1D48D, 'M', u'l'), + (0x1D48E, 'M', u'm'), + (0x1D48F, 'M', u'n'), + (0x1D490, 'M', u'o'), + (0x1D491, 'M', u'p'), + (0x1D492, 'M', u'q'), + (0x1D493, 'M', u'r'), + (0x1D494, 'M', u's'), + (0x1D495, 'M', u't'), + (0x1D496, 'M', u'u'), + (0x1D497, 'M', u'v'), + (0x1D498, 'M', u'w'), + (0x1D499, 'M', u'x'), + (0x1D49A, 'M', u'y'), + (0x1D49B, 'M', u'z'), + (0x1D49C, 'M', u'a'), + (0x1D49D, 'X'), + (0x1D49E, 'M', u'c'), + (0x1D49F, 'M', u'd'), + (0x1D4A0, 'X'), + (0x1D4A2, 'M', u'g'), + (0x1D4A3, 'X'), + (0x1D4A5, 'M', u'j'), + (0x1D4A6, 'M', u'k'), + (0x1D4A7, 'X'), + (0x1D4A9, 'M', u'n'), + (0x1D4AA, 'M', u'o'), + (0x1D4AB, 'M', u'p'), + (0x1D4AC, 'M', u'q'), + (0x1D4AD, 'X'), + (0x1D4AE, 'M', u's'), + (0x1D4AF, 'M', u't'), + (0x1D4B0, 'M', u'u'), + (0x1D4B1, 'M', u'v'), + (0x1D4B2, 'M', u'w'), + (0x1D4B3, 'M', u'x'), + (0x1D4B4, 'M', u'y'), + (0x1D4B5, 'M', u'z'), + (0x1D4B6, 'M', u'a'), + (0x1D4B7, 'M', u'b'), + (0x1D4B8, 'M', u'c'), + (0x1D4B9, 'M', u'd'), + (0x1D4BA, 'X'), + (0x1D4BB, 'M', u'f'), + (0x1D4BC, 'X'), + (0x1D4BD, 'M', u'h'), + (0x1D4BE, 'M', u'i'), + (0x1D4BF, 'M', u'j'), + (0x1D4C0, 'M', u'k'), + (0x1D4C1, 'M', u'l'), + (0x1D4C2, 'M', u'm'), + (0x1D4C3, 'M', u'n'), + (0x1D4C4, 'X'), + (0x1D4C5, 'M', u'p'), + (0x1D4C6, 'M', u'q'), + (0x1D4C7, 'M', u'r'), + (0x1D4C8, 'M', u's'), + (0x1D4C9, 'M', u't'), + (0x1D4CA, 'M', u'u'), + (0x1D4CB, 'M', u'v'), + (0x1D4CC, 'M', u'w'), + (0x1D4CD, 'M', u'x'), + (0x1D4CE, 'M', u'y'), + (0x1D4CF, 'M', u'z'), + (0x1D4D0, 'M', u'a'), + ] + +def _seg_60(): + return [ + (0x1D4D1, 'M', u'b'), + (0x1D4D2, 'M', u'c'), + (0x1D4D3, 'M', u'd'), + (0x1D4D4, 'M', u'e'), + (0x1D4D5, 'M', u'f'), + (0x1D4D6, 'M', u'g'), + (0x1D4D7, 'M', u'h'), + (0x1D4D8, 'M', u'i'), + (0x1D4D9, 'M', u'j'), + (0x1D4DA, 'M', u'k'), + (0x1D4DB, 'M', u'l'), + (0x1D4DC, 'M', u'm'), + (0x1D4DD, 'M', u'n'), + (0x1D4DE, 'M', u'o'), + (0x1D4DF, 'M', u'p'), + (0x1D4E0, 'M', u'q'), + (0x1D4E1, 'M', u'r'), + (0x1D4E2, 'M', u's'), + (0x1D4E3, 'M', u't'), + (0x1D4E4, 'M', u'u'), + (0x1D4E5, 'M', u'v'), + (0x1D4E6, 'M', u'w'), + (0x1D4E7, 'M', u'x'), + (0x1D4E8, 'M', u'y'), + (0x1D4E9, 'M', u'z'), + (0x1D4EA, 'M', u'a'), + (0x1D4EB, 'M', u'b'), + (0x1D4EC, 'M', u'c'), + (0x1D4ED, 'M', u'd'), + (0x1D4EE, 'M', u'e'), + (0x1D4EF, 'M', u'f'), + (0x1D4F0, 'M', u'g'), + (0x1D4F1, 'M', u'h'), + (0x1D4F2, 'M', u'i'), + (0x1D4F3, 'M', u'j'), + (0x1D4F4, 'M', u'k'), + (0x1D4F5, 'M', u'l'), + (0x1D4F6, 'M', u'm'), + (0x1D4F7, 'M', u'n'), + (0x1D4F8, 'M', u'o'), + (0x1D4F9, 'M', u'p'), + (0x1D4FA, 'M', u'q'), + (0x1D4FB, 'M', u'r'), + (0x1D4FC, 'M', u's'), + (0x1D4FD, 'M', u't'), + (0x1D4FE, 'M', u'u'), + (0x1D4FF, 'M', u'v'), + (0x1D500, 'M', u'w'), + (0x1D501, 'M', u'x'), + (0x1D502, 'M', u'y'), + (0x1D503, 'M', u'z'), + (0x1D504, 'M', u'a'), + (0x1D505, 'M', u'b'), + (0x1D506, 'X'), + (0x1D507, 'M', u'd'), + (0x1D508, 'M', u'e'), + (0x1D509, 'M', u'f'), + (0x1D50A, 'M', u'g'), + (0x1D50B, 'X'), + (0x1D50D, 'M', u'j'), + (0x1D50E, 'M', u'k'), + (0x1D50F, 'M', u'l'), + (0x1D510, 'M', u'm'), + (0x1D511, 'M', u'n'), + (0x1D512, 'M', u'o'), + (0x1D513, 'M', u'p'), + (0x1D514, 'M', u'q'), + (0x1D515, 'X'), + (0x1D516, 'M', u's'), + (0x1D517, 'M', u't'), + (0x1D518, 'M', u'u'), + (0x1D519, 'M', u'v'), + (0x1D51A, 'M', u'w'), + (0x1D51B, 'M', u'x'), + (0x1D51C, 'M', u'y'), + (0x1D51D, 'X'), + (0x1D51E, 'M', u'a'), + (0x1D51F, 'M', u'b'), + (0x1D520, 'M', u'c'), + (0x1D521, 'M', u'd'), + (0x1D522, 'M', u'e'), + (0x1D523, 'M', u'f'), + (0x1D524, 'M', u'g'), + (0x1D525, 'M', u'h'), + (0x1D526, 'M', u'i'), + (0x1D527, 'M', u'j'), + (0x1D528, 'M', u'k'), + (0x1D529, 'M', u'l'), + (0x1D52A, 'M', u'm'), + (0x1D52B, 'M', u'n'), + (0x1D52C, 'M', u'o'), + (0x1D52D, 'M', u'p'), + (0x1D52E, 'M', u'q'), + (0x1D52F, 'M', u'r'), + (0x1D530, 'M', u's'), + (0x1D531, 'M', u't'), + (0x1D532, 'M', u'u'), + (0x1D533, 'M', u'v'), + (0x1D534, 'M', u'w'), + (0x1D535, 'M', u'x'), + ] + +def _seg_61(): + return [ + (0x1D536, 'M', u'y'), + (0x1D537, 'M', u'z'), + (0x1D538, 'M', u'a'), + (0x1D539, 'M', u'b'), + (0x1D53A, 'X'), + (0x1D53B, 'M', u'd'), + (0x1D53C, 'M', u'e'), + (0x1D53D, 'M', u'f'), + (0x1D53E, 'M', u'g'), + (0x1D53F, 'X'), + (0x1D540, 'M', u'i'), + (0x1D541, 'M', u'j'), + (0x1D542, 'M', u'k'), + (0x1D543, 'M', u'l'), + (0x1D544, 'M', u'm'), + (0x1D545, 'X'), + (0x1D546, 'M', u'o'), + (0x1D547, 'X'), + (0x1D54A, 'M', u's'), + (0x1D54B, 'M', u't'), + (0x1D54C, 'M', u'u'), + (0x1D54D, 'M', u'v'), + (0x1D54E, 'M', u'w'), + (0x1D54F, 'M', u'x'), + (0x1D550, 'M', u'y'), + (0x1D551, 'X'), + (0x1D552, 'M', u'a'), + (0x1D553, 'M', u'b'), + (0x1D554, 'M', u'c'), + (0x1D555, 'M', u'd'), + (0x1D556, 'M', u'e'), + (0x1D557, 'M', u'f'), + (0x1D558, 'M', u'g'), + (0x1D559, 'M', u'h'), + (0x1D55A, 'M', u'i'), + (0x1D55B, 'M', u'j'), + (0x1D55C, 'M', u'k'), + (0x1D55D, 'M', u'l'), + (0x1D55E, 'M', u'm'), + (0x1D55F, 'M', u'n'), + (0x1D560, 'M', u'o'), + (0x1D561, 'M', u'p'), + (0x1D562, 'M', u'q'), + (0x1D563, 'M', u'r'), + (0x1D564, 'M', u's'), + (0x1D565, 'M', u't'), + (0x1D566, 'M', u'u'), + (0x1D567, 'M', u'v'), + (0x1D568, 'M', u'w'), + (0x1D569, 'M', u'x'), + (0x1D56A, 'M', u'y'), + (0x1D56B, 'M', u'z'), + (0x1D56C, 'M', u'a'), + (0x1D56D, 'M', u'b'), + (0x1D56E, 'M', u'c'), + (0x1D56F, 'M', u'd'), + (0x1D570, 'M', u'e'), + (0x1D571, 'M', u'f'), + (0x1D572, 'M', u'g'), + (0x1D573, 'M', u'h'), + (0x1D574, 'M', u'i'), + (0x1D575, 'M', u'j'), + (0x1D576, 'M', u'k'), + (0x1D577, 'M', u'l'), + (0x1D578, 'M', u'm'), + (0x1D579, 'M', u'n'), + (0x1D57A, 'M', u'o'), + (0x1D57B, 'M', u'p'), + (0x1D57C, 'M', u'q'), + (0x1D57D, 'M', u'r'), + (0x1D57E, 'M', u's'), + (0x1D57F, 'M', u't'), + (0x1D580, 'M', u'u'), + (0x1D581, 'M', u'v'), + (0x1D582, 'M', u'w'), + (0x1D583, 'M', u'x'), + (0x1D584, 'M', u'y'), + (0x1D585, 'M', u'z'), + (0x1D586, 'M', u'a'), + (0x1D587, 'M', u'b'), + (0x1D588, 'M', u'c'), + (0x1D589, 'M', u'd'), + (0x1D58A, 'M', u'e'), + (0x1D58B, 'M', u'f'), + (0x1D58C, 'M', u'g'), + (0x1D58D, 'M', u'h'), + (0x1D58E, 'M', u'i'), + (0x1D58F, 'M', u'j'), + (0x1D590, 'M', u'k'), + (0x1D591, 'M', u'l'), + (0x1D592, 'M', u'm'), + (0x1D593, 'M', u'n'), + (0x1D594, 'M', u'o'), + (0x1D595, 'M', u'p'), + (0x1D596, 'M', u'q'), + (0x1D597, 'M', u'r'), + (0x1D598, 'M', u's'), + (0x1D599, 'M', u't'), + (0x1D59A, 'M', u'u'), + (0x1D59B, 'M', u'v'), + ] + +def _seg_62(): + return [ + (0x1D59C, 'M', u'w'), + (0x1D59D, 'M', u'x'), + (0x1D59E, 'M', u'y'), + (0x1D59F, 'M', u'z'), + (0x1D5A0, 'M', u'a'), + (0x1D5A1, 'M', u'b'), + (0x1D5A2, 'M', u'c'), + (0x1D5A3, 'M', u'd'), + (0x1D5A4, 'M', u'e'), + (0x1D5A5, 'M', u'f'), + (0x1D5A6, 'M', u'g'), + (0x1D5A7, 'M', u'h'), + (0x1D5A8, 'M', u'i'), + (0x1D5A9, 'M', u'j'), + (0x1D5AA, 'M', u'k'), + (0x1D5AB, 'M', u'l'), + (0x1D5AC, 'M', u'm'), + (0x1D5AD, 'M', u'n'), + (0x1D5AE, 'M', u'o'), + (0x1D5AF, 'M', u'p'), + (0x1D5B0, 'M', u'q'), + (0x1D5B1, 'M', u'r'), + (0x1D5B2, 'M', u's'), + (0x1D5B3, 'M', u't'), + (0x1D5B4, 'M', u'u'), + (0x1D5B5, 'M', u'v'), + (0x1D5B6, 'M', u'w'), + (0x1D5B7, 'M', u'x'), + (0x1D5B8, 'M', u'y'), + (0x1D5B9, 'M', u'z'), + (0x1D5BA, 'M', u'a'), + (0x1D5BB, 'M', u'b'), + (0x1D5BC, 'M', u'c'), + (0x1D5BD, 'M', u'd'), + (0x1D5BE, 'M', u'e'), + (0x1D5BF, 'M', u'f'), + (0x1D5C0, 'M', u'g'), + (0x1D5C1, 'M', u'h'), + (0x1D5C2, 'M', u'i'), + (0x1D5C3, 'M', u'j'), + (0x1D5C4, 'M', u'k'), + (0x1D5C5, 'M', u'l'), + (0x1D5C6, 'M', u'm'), + (0x1D5C7, 'M', u'n'), + (0x1D5C8, 'M', u'o'), + (0x1D5C9, 'M', u'p'), + (0x1D5CA, 'M', u'q'), + (0x1D5CB, 'M', u'r'), + (0x1D5CC, 'M', u's'), + (0x1D5CD, 'M', u't'), + (0x1D5CE, 'M', u'u'), + (0x1D5CF, 'M', u'v'), + (0x1D5D0, 'M', u'w'), + (0x1D5D1, 'M', u'x'), + (0x1D5D2, 'M', u'y'), + (0x1D5D3, 'M', u'z'), + (0x1D5D4, 'M', u'a'), + (0x1D5D5, 'M', u'b'), + (0x1D5D6, 'M', u'c'), + (0x1D5D7, 'M', u'd'), + (0x1D5D8, 'M', u'e'), + (0x1D5D9, 'M', u'f'), + (0x1D5DA, 'M', u'g'), + (0x1D5DB, 'M', u'h'), + (0x1D5DC, 'M', u'i'), + (0x1D5DD, 'M', u'j'), + (0x1D5DE, 'M', u'k'), + (0x1D5DF, 'M', u'l'), + (0x1D5E0, 'M', u'm'), + (0x1D5E1, 'M', u'n'), + (0x1D5E2, 'M', u'o'), + (0x1D5E3, 'M', u'p'), + (0x1D5E4, 'M', u'q'), + (0x1D5E5, 'M', u'r'), + (0x1D5E6, 'M', u's'), + (0x1D5E7, 'M', u't'), + (0x1D5E8, 'M', u'u'), + (0x1D5E9, 'M', u'v'), + (0x1D5EA, 'M', u'w'), + (0x1D5EB, 'M', u'x'), + (0x1D5EC, 'M', u'y'), + (0x1D5ED, 'M', u'z'), + (0x1D5EE, 'M', u'a'), + (0x1D5EF, 'M', u'b'), + (0x1D5F0, 'M', u'c'), + (0x1D5F1, 'M', u'd'), + (0x1D5F2, 'M', u'e'), + (0x1D5F3, 'M', u'f'), + (0x1D5F4, 'M', u'g'), + (0x1D5F5, 'M', u'h'), + (0x1D5F6, 'M', u'i'), + (0x1D5F7, 'M', u'j'), + (0x1D5F8, 'M', u'k'), + (0x1D5F9, 'M', u'l'), + (0x1D5FA, 'M', u'm'), + (0x1D5FB, 'M', u'n'), + (0x1D5FC, 'M', u'o'), + (0x1D5FD, 'M', u'p'), + (0x1D5FE, 'M', u'q'), + (0x1D5FF, 'M', u'r'), + ] + +def _seg_63(): + return [ + (0x1D600, 'M', u's'), + (0x1D601, 'M', u't'), + (0x1D602, 'M', u'u'), + (0x1D603, 'M', u'v'), + (0x1D604, 'M', u'w'), + (0x1D605, 'M', u'x'), + (0x1D606, 'M', u'y'), + (0x1D607, 'M', u'z'), + (0x1D608, 'M', u'a'), + (0x1D609, 'M', u'b'), + (0x1D60A, 'M', u'c'), + (0x1D60B, 'M', u'd'), + (0x1D60C, 'M', u'e'), + (0x1D60D, 'M', u'f'), + (0x1D60E, 'M', u'g'), + (0x1D60F, 'M', u'h'), + (0x1D610, 'M', u'i'), + (0x1D611, 'M', u'j'), + (0x1D612, 'M', u'k'), + (0x1D613, 'M', u'l'), + (0x1D614, 'M', u'm'), + (0x1D615, 'M', u'n'), + (0x1D616, 'M', u'o'), + (0x1D617, 'M', u'p'), + (0x1D618, 'M', u'q'), + (0x1D619, 'M', u'r'), + (0x1D61A, 'M', u's'), + (0x1D61B, 'M', u't'), + (0x1D61C, 'M', u'u'), + (0x1D61D, 'M', u'v'), + (0x1D61E, 'M', u'w'), + (0x1D61F, 'M', u'x'), + (0x1D620, 'M', u'y'), + (0x1D621, 'M', u'z'), + (0x1D622, 'M', u'a'), + (0x1D623, 'M', u'b'), + (0x1D624, 'M', u'c'), + (0x1D625, 'M', u'd'), + (0x1D626, 'M', u'e'), + (0x1D627, 'M', u'f'), + (0x1D628, 'M', u'g'), + (0x1D629, 'M', u'h'), + (0x1D62A, 'M', u'i'), + (0x1D62B, 'M', u'j'), + (0x1D62C, 'M', u'k'), + (0x1D62D, 'M', u'l'), + (0x1D62E, 'M', u'm'), + (0x1D62F, 'M', u'n'), + (0x1D630, 'M', u'o'), + (0x1D631, 'M', u'p'), + (0x1D632, 'M', u'q'), + (0x1D633, 'M', u'r'), + (0x1D634, 'M', u's'), + (0x1D635, 'M', u't'), + (0x1D636, 'M', u'u'), + (0x1D637, 'M', u'v'), + (0x1D638, 'M', u'w'), + (0x1D639, 'M', u'x'), + (0x1D63A, 'M', u'y'), + (0x1D63B, 'M', u'z'), + (0x1D63C, 'M', u'a'), + (0x1D63D, 'M', u'b'), + (0x1D63E, 'M', u'c'), + (0x1D63F, 'M', u'd'), + (0x1D640, 'M', u'e'), + (0x1D641, 'M', u'f'), + (0x1D642, 'M', u'g'), + (0x1D643, 'M', u'h'), + (0x1D644, 'M', u'i'), + (0x1D645, 'M', u'j'), + (0x1D646, 'M', u'k'), + (0x1D647, 'M', u'l'), + (0x1D648, 'M', u'm'), + (0x1D649, 'M', u'n'), + (0x1D64A, 'M', u'o'), + (0x1D64B, 'M', u'p'), + (0x1D64C, 'M', u'q'), + (0x1D64D, 'M', u'r'), + (0x1D64E, 'M', u's'), + (0x1D64F, 'M', u't'), + (0x1D650, 'M', u'u'), + (0x1D651, 'M', u'v'), + (0x1D652, 'M', u'w'), + (0x1D653, 'M', u'x'), + (0x1D654, 'M', u'y'), + (0x1D655, 'M', u'z'), + (0x1D656, 'M', u'a'), + (0x1D657, 'M', u'b'), + (0x1D658, 'M', u'c'), + (0x1D659, 'M', u'd'), + (0x1D65A, 'M', u'e'), + (0x1D65B, 'M', u'f'), + (0x1D65C, 'M', u'g'), + (0x1D65D, 'M', u'h'), + (0x1D65E, 'M', u'i'), + (0x1D65F, 'M', u'j'), + (0x1D660, 'M', u'k'), + (0x1D661, 'M', u'l'), + (0x1D662, 'M', u'm'), + (0x1D663, 'M', u'n'), + ] + +def _seg_64(): + return [ + (0x1D664, 'M', u'o'), + (0x1D665, 'M', u'p'), + (0x1D666, 'M', u'q'), + (0x1D667, 'M', u'r'), + (0x1D668, 'M', u's'), + (0x1D669, 'M', u't'), + (0x1D66A, 'M', u'u'), + (0x1D66B, 'M', u'v'), + (0x1D66C, 'M', u'w'), + (0x1D66D, 'M', u'x'), + (0x1D66E, 'M', u'y'), + (0x1D66F, 'M', u'z'), + (0x1D670, 'M', u'a'), + (0x1D671, 'M', u'b'), + (0x1D672, 'M', u'c'), + (0x1D673, 'M', u'd'), + (0x1D674, 'M', u'e'), + (0x1D675, 'M', u'f'), + (0x1D676, 'M', u'g'), + (0x1D677, 'M', u'h'), + (0x1D678, 'M', u'i'), + (0x1D679, 'M', u'j'), + (0x1D67A, 'M', u'k'), + (0x1D67B, 'M', u'l'), + (0x1D67C, 'M', u'm'), + (0x1D67D, 'M', u'n'), + (0x1D67E, 'M', u'o'), + (0x1D67F, 'M', u'p'), + (0x1D680, 'M', u'q'), + (0x1D681, 'M', u'r'), + (0x1D682, 'M', u's'), + (0x1D683, 'M', u't'), + (0x1D684, 'M', u'u'), + (0x1D685, 'M', u'v'), + (0x1D686, 'M', u'w'), + (0x1D687, 'M', u'x'), + (0x1D688, 'M', u'y'), + (0x1D689, 'M', u'z'), + (0x1D68A, 'M', u'a'), + (0x1D68B, 'M', u'b'), + (0x1D68C, 'M', u'c'), + (0x1D68D, 'M', u'd'), + (0x1D68E, 'M', u'e'), + (0x1D68F, 'M', u'f'), + (0x1D690, 'M', u'g'), + (0x1D691, 'M', u'h'), + (0x1D692, 'M', u'i'), + (0x1D693, 'M', u'j'), + (0x1D694, 'M', u'k'), + (0x1D695, 'M', u'l'), + (0x1D696, 'M', u'm'), + (0x1D697, 'M', u'n'), + (0x1D698, 'M', u'o'), + (0x1D699, 'M', u'p'), + (0x1D69A, 'M', u'q'), + (0x1D69B, 'M', u'r'), + (0x1D69C, 'M', u's'), + (0x1D69D, 'M', u't'), + (0x1D69E, 'M', u'u'), + (0x1D69F, 'M', u'v'), + (0x1D6A0, 'M', u'w'), + (0x1D6A1, 'M', u'x'), + (0x1D6A2, 'M', u'y'), + (0x1D6A3, 'M', u'z'), + (0x1D6A4, 'M', u'ı'), + (0x1D6A5, 'M', u'ȷ'), + (0x1D6A6, 'X'), + (0x1D6A8, 'M', u'α'), + (0x1D6A9, 'M', u'β'), + (0x1D6AA, 'M', u'γ'), + (0x1D6AB, 'M', u'δ'), + (0x1D6AC, 'M', u'ε'), + (0x1D6AD, 'M', u'ζ'), + (0x1D6AE, 'M', u'η'), + (0x1D6AF, 'M', u'θ'), + (0x1D6B0, 'M', u'ι'), + (0x1D6B1, 'M', u'κ'), + (0x1D6B2, 'M', u'λ'), + (0x1D6B3, 'M', u'μ'), + (0x1D6B4, 'M', u'ν'), + (0x1D6B5, 'M', u'ξ'), + (0x1D6B6, 'M', u'ο'), + (0x1D6B7, 'M', u'π'), + (0x1D6B8, 'M', u'ρ'), + (0x1D6B9, 'M', u'θ'), + (0x1D6BA, 'M', u'σ'), + (0x1D6BB, 'M', u'τ'), + (0x1D6BC, 'M', u'υ'), + (0x1D6BD, 'M', u'φ'), + (0x1D6BE, 'M', u'χ'), + (0x1D6BF, 'M', u'ψ'), + (0x1D6C0, 'M', u'ω'), + (0x1D6C1, 'M', u'∇'), + (0x1D6C2, 'M', u'α'), + (0x1D6C3, 'M', u'β'), + (0x1D6C4, 'M', u'γ'), + (0x1D6C5, 'M', u'δ'), + (0x1D6C6, 'M', u'ε'), + (0x1D6C7, 'M', u'ζ'), + (0x1D6C8, 'M', u'η'), + ] + +def _seg_65(): + return [ + (0x1D6C9, 'M', u'θ'), + (0x1D6CA, 'M', u'ι'), + (0x1D6CB, 'M', u'κ'), + (0x1D6CC, 'M', u'λ'), + (0x1D6CD, 'M', u'μ'), + (0x1D6CE, 'M', u'ν'), + (0x1D6CF, 'M', u'ξ'), + (0x1D6D0, 'M', u'ο'), + (0x1D6D1, 'M', u'π'), + (0x1D6D2, 'M', u'ρ'), + (0x1D6D3, 'M', u'σ'), + (0x1D6D5, 'M', u'τ'), + (0x1D6D6, 'M', u'υ'), + (0x1D6D7, 'M', u'φ'), + (0x1D6D8, 'M', u'χ'), + (0x1D6D9, 'M', u'ψ'), + (0x1D6DA, 'M', u'ω'), + (0x1D6DB, 'M', u'∂'), + (0x1D6DC, 'M', u'ε'), + (0x1D6DD, 'M', u'θ'), + (0x1D6DE, 'M', u'κ'), + (0x1D6DF, 'M', u'φ'), + (0x1D6E0, 'M', u'ρ'), + (0x1D6E1, 'M', u'π'), + (0x1D6E2, 'M', u'α'), + (0x1D6E3, 'M', u'β'), + (0x1D6E4, 'M', u'γ'), + (0x1D6E5, 'M', u'δ'), + (0x1D6E6, 'M', u'ε'), + (0x1D6E7, 'M', u'ζ'), + (0x1D6E8, 'M', u'η'), + (0x1D6E9, 'M', u'θ'), + (0x1D6EA, 'M', u'ι'), + (0x1D6EB, 'M', u'κ'), + (0x1D6EC, 'M', u'λ'), + (0x1D6ED, 'M', u'μ'), + (0x1D6EE, 'M', u'ν'), + (0x1D6EF, 'M', u'ξ'), + (0x1D6F0, 'M', u'ο'), + (0x1D6F1, 'M', u'π'), + (0x1D6F2, 'M', u'ρ'), + (0x1D6F3, 'M', u'θ'), + (0x1D6F4, 'M', u'σ'), + (0x1D6F5, 'M', u'τ'), + (0x1D6F6, 'M', u'υ'), + (0x1D6F7, 'M', u'φ'), + (0x1D6F8, 'M', u'χ'), + (0x1D6F9, 'M', u'ψ'), + (0x1D6FA, 'M', u'ω'), + (0x1D6FB, 'M', u'∇'), + (0x1D6FC, 'M', u'α'), + (0x1D6FD, 'M', u'β'), + (0x1D6FE, 'M', u'γ'), + (0x1D6FF, 'M', u'δ'), + (0x1D700, 'M', u'ε'), + (0x1D701, 'M', u'ζ'), + (0x1D702, 'M', u'η'), + (0x1D703, 'M', u'θ'), + (0x1D704, 'M', u'ι'), + (0x1D705, 'M', u'κ'), + (0x1D706, 'M', u'λ'), + (0x1D707, 'M', u'μ'), + (0x1D708, 'M', u'ν'), + (0x1D709, 'M', u'ξ'), + (0x1D70A, 'M', u'ο'), + (0x1D70B, 'M', u'π'), + (0x1D70C, 'M', u'ρ'), + (0x1D70D, 'M', u'σ'), + (0x1D70F, 'M', u'τ'), + (0x1D710, 'M', u'υ'), + (0x1D711, 'M', u'φ'), + (0x1D712, 'M', u'χ'), + (0x1D713, 'M', u'ψ'), + (0x1D714, 'M', u'ω'), + (0x1D715, 'M', u'∂'), + (0x1D716, 'M', u'ε'), + (0x1D717, 'M', u'θ'), + (0x1D718, 'M', u'κ'), + (0x1D719, 'M', u'φ'), + (0x1D71A, 'M', u'ρ'), + (0x1D71B, 'M', u'π'), + (0x1D71C, 'M', u'α'), + (0x1D71D, 'M', u'β'), + (0x1D71E, 'M', u'γ'), + (0x1D71F, 'M', u'δ'), + (0x1D720, 'M', u'ε'), + (0x1D721, 'M', u'ζ'), + (0x1D722, 'M', u'η'), + (0x1D723, 'M', u'θ'), + (0x1D724, 'M', u'ι'), + (0x1D725, 'M', u'κ'), + (0x1D726, 'M', u'λ'), + (0x1D727, 'M', u'μ'), + (0x1D728, 'M', u'ν'), + (0x1D729, 'M', u'ξ'), + (0x1D72A, 'M', u'ο'), + (0x1D72B, 'M', u'π'), + (0x1D72C, 'M', u'ρ'), + (0x1D72D, 'M', u'θ'), + (0x1D72E, 'M', u'σ'), + ] + +def _seg_66(): + return [ + (0x1D72F, 'M', u'τ'), + (0x1D730, 'M', u'υ'), + (0x1D731, 'M', u'φ'), + (0x1D732, 'M', u'χ'), + (0x1D733, 'M', u'ψ'), + (0x1D734, 'M', u'ω'), + (0x1D735, 'M', u'∇'), + (0x1D736, 'M', u'α'), + (0x1D737, 'M', u'β'), + (0x1D738, 'M', u'γ'), + (0x1D739, 'M', u'δ'), + (0x1D73A, 'M', u'ε'), + (0x1D73B, 'M', u'ζ'), + (0x1D73C, 'M', u'η'), + (0x1D73D, 'M', u'θ'), + (0x1D73E, 'M', u'ι'), + (0x1D73F, 'M', u'κ'), + (0x1D740, 'M', u'λ'), + (0x1D741, 'M', u'μ'), + (0x1D742, 'M', u'ν'), + (0x1D743, 'M', u'ξ'), + (0x1D744, 'M', u'ο'), + (0x1D745, 'M', u'π'), + (0x1D746, 'M', u'ρ'), + (0x1D747, 'M', u'σ'), + (0x1D749, 'M', u'τ'), + (0x1D74A, 'M', u'υ'), + (0x1D74B, 'M', u'φ'), + (0x1D74C, 'M', u'χ'), + (0x1D74D, 'M', u'ψ'), + (0x1D74E, 'M', u'ω'), + (0x1D74F, 'M', u'∂'), + (0x1D750, 'M', u'ε'), + (0x1D751, 'M', u'θ'), + (0x1D752, 'M', u'κ'), + (0x1D753, 'M', u'φ'), + (0x1D754, 'M', u'ρ'), + (0x1D755, 'M', u'π'), + (0x1D756, 'M', u'α'), + (0x1D757, 'M', u'β'), + (0x1D758, 'M', u'γ'), + (0x1D759, 'M', u'δ'), + (0x1D75A, 'M', u'ε'), + (0x1D75B, 'M', u'ζ'), + (0x1D75C, 'M', u'η'), + (0x1D75D, 'M', u'θ'), + (0x1D75E, 'M', u'ι'), + (0x1D75F, 'M', u'κ'), + (0x1D760, 'M', u'λ'), + (0x1D761, 'M', u'μ'), + (0x1D762, 'M', u'ν'), + (0x1D763, 'M', u'ξ'), + (0x1D764, 'M', u'ο'), + (0x1D765, 'M', u'π'), + (0x1D766, 'M', u'ρ'), + (0x1D767, 'M', u'θ'), + (0x1D768, 'M', u'σ'), + (0x1D769, 'M', u'τ'), + (0x1D76A, 'M', u'υ'), + (0x1D76B, 'M', u'φ'), + (0x1D76C, 'M', u'χ'), + (0x1D76D, 'M', u'ψ'), + (0x1D76E, 'M', u'ω'), + (0x1D76F, 'M', u'∇'), + (0x1D770, 'M', u'α'), + (0x1D771, 'M', u'β'), + (0x1D772, 'M', u'γ'), + (0x1D773, 'M', u'δ'), + (0x1D774, 'M', u'ε'), + (0x1D775, 'M', u'ζ'), + (0x1D776, 'M', u'η'), + (0x1D777, 'M', u'θ'), + (0x1D778, 'M', u'ι'), + (0x1D779, 'M', u'κ'), + (0x1D77A, 'M', u'λ'), + (0x1D77B, 'M', u'μ'), + (0x1D77C, 'M', u'ν'), + (0x1D77D, 'M', u'ξ'), + (0x1D77E, 'M', u'ο'), + (0x1D77F, 'M', u'π'), + (0x1D780, 'M', u'ρ'), + (0x1D781, 'M', u'σ'), + (0x1D783, 'M', u'τ'), + (0x1D784, 'M', u'υ'), + (0x1D785, 'M', u'φ'), + (0x1D786, 'M', u'χ'), + (0x1D787, 'M', u'ψ'), + (0x1D788, 'M', u'ω'), + (0x1D789, 'M', u'∂'), + (0x1D78A, 'M', u'ε'), + (0x1D78B, 'M', u'θ'), + (0x1D78C, 'M', u'κ'), + (0x1D78D, 'M', u'φ'), + (0x1D78E, 'M', u'ρ'), + (0x1D78F, 'M', u'π'), + (0x1D790, 'M', u'α'), + (0x1D791, 'M', u'β'), + (0x1D792, 'M', u'γ'), + (0x1D793, 'M', u'δ'), + (0x1D794, 'M', u'ε'), + ] + +def _seg_67(): + return [ + (0x1D795, 'M', u'ζ'), + (0x1D796, 'M', u'η'), + (0x1D797, 'M', u'θ'), + (0x1D798, 'M', u'ι'), + (0x1D799, 'M', u'κ'), + (0x1D79A, 'M', u'λ'), + (0x1D79B, 'M', u'μ'), + (0x1D79C, 'M', u'ν'), + (0x1D79D, 'M', u'ξ'), + (0x1D79E, 'M', u'ο'), + (0x1D79F, 'M', u'π'), + (0x1D7A0, 'M', u'ρ'), + (0x1D7A1, 'M', u'θ'), + (0x1D7A2, 'M', u'σ'), + (0x1D7A3, 'M', u'τ'), + (0x1D7A4, 'M', u'υ'), + (0x1D7A5, 'M', u'φ'), + (0x1D7A6, 'M', u'χ'), + (0x1D7A7, 'M', u'ψ'), + (0x1D7A8, 'M', u'ω'), + (0x1D7A9, 'M', u'∇'), + (0x1D7AA, 'M', u'α'), + (0x1D7AB, 'M', u'β'), + (0x1D7AC, 'M', u'γ'), + (0x1D7AD, 'M', u'δ'), + (0x1D7AE, 'M', u'ε'), + (0x1D7AF, 'M', u'ζ'), + (0x1D7B0, 'M', u'η'), + (0x1D7B1, 'M', u'θ'), + (0x1D7B2, 'M', u'ι'), + (0x1D7B3, 'M', u'κ'), + (0x1D7B4, 'M', u'λ'), + (0x1D7B5, 'M', u'μ'), + (0x1D7B6, 'M', u'ν'), + (0x1D7B7, 'M', u'ξ'), + (0x1D7B8, 'M', u'ο'), + (0x1D7B9, 'M', u'π'), + (0x1D7BA, 'M', u'ρ'), + (0x1D7BB, 'M', u'σ'), + (0x1D7BD, 'M', u'τ'), + (0x1D7BE, 'M', u'υ'), + (0x1D7BF, 'M', u'φ'), + (0x1D7C0, 'M', u'χ'), + (0x1D7C1, 'M', u'ψ'), + (0x1D7C2, 'M', u'ω'), + (0x1D7C3, 'M', u'∂'), + (0x1D7C4, 'M', u'ε'), + (0x1D7C5, 'M', u'θ'), + (0x1D7C6, 'M', u'κ'), + (0x1D7C7, 'M', u'φ'), + (0x1D7C8, 'M', u'ρ'), + (0x1D7C9, 'M', u'π'), + (0x1D7CA, 'M', u'ϝ'), + (0x1D7CC, 'X'), + (0x1D7CE, 'M', u'0'), + (0x1D7CF, 'M', u'1'), + (0x1D7D0, 'M', u'2'), + (0x1D7D1, 'M', u'3'), + (0x1D7D2, 'M', u'4'), + (0x1D7D3, 'M', u'5'), + (0x1D7D4, 'M', u'6'), + (0x1D7D5, 'M', u'7'), + (0x1D7D6, 'M', u'8'), + (0x1D7D7, 'M', u'9'), + (0x1D7D8, 'M', u'0'), + (0x1D7D9, 'M', u'1'), + (0x1D7DA, 'M', u'2'), + (0x1D7DB, 'M', u'3'), + (0x1D7DC, 'M', u'4'), + (0x1D7DD, 'M', u'5'), + (0x1D7DE, 'M', u'6'), + (0x1D7DF, 'M', u'7'), + (0x1D7E0, 'M', u'8'), + (0x1D7E1, 'M', u'9'), + (0x1D7E2, 'M', u'0'), + (0x1D7E3, 'M', u'1'), + (0x1D7E4, 'M', u'2'), + (0x1D7E5, 'M', u'3'), + (0x1D7E6, 'M', u'4'), + (0x1D7E7, 'M', u'5'), + (0x1D7E8, 'M', u'6'), + (0x1D7E9, 'M', u'7'), + (0x1D7EA, 'M', u'8'), + (0x1D7EB, 'M', u'9'), + (0x1D7EC, 'M', u'0'), + (0x1D7ED, 'M', u'1'), + (0x1D7EE, 'M', u'2'), + (0x1D7EF, 'M', u'3'), + (0x1D7F0, 'M', u'4'), + (0x1D7F1, 'M', u'5'), + (0x1D7F2, 'M', u'6'), + (0x1D7F3, 'M', u'7'), + (0x1D7F4, 'M', u'8'), + (0x1D7F5, 'M', u'9'), + (0x1D7F6, 'M', u'0'), + (0x1D7F7, 'M', u'1'), + (0x1D7F8, 'M', u'2'), + (0x1D7F9, 'M', u'3'), + (0x1D7FA, 'M', u'4'), + (0x1D7FB, 'M', u'5'), + ] + +def _seg_68(): + return [ + (0x1D7FC, 'M', u'6'), + (0x1D7FD, 'M', u'7'), + (0x1D7FE, 'M', u'8'), + (0x1D7FF, 'M', u'9'), + (0x1D800, 'V'), + (0x1DA8C, 'X'), + (0x1DA9B, 'V'), + (0x1DAA0, 'X'), + (0x1DAA1, 'V'), + (0x1DAB0, 'X'), + (0x1E000, 'V'), + (0x1E007, 'X'), + (0x1E008, 'V'), + (0x1E019, 'X'), + (0x1E01B, 'V'), + (0x1E022, 'X'), + (0x1E023, 'V'), + (0x1E025, 'X'), + (0x1E026, 'V'), + (0x1E02B, 'X'), + (0x1E800, 'V'), + (0x1E8C5, 'X'), + (0x1E8C7, 'V'), + (0x1E8D7, 'X'), + (0x1E900, 'M', u'𞤢'), + (0x1E901, 'M', u'𞤣'), + (0x1E902, 'M', u'𞤤'), + (0x1E903, 'M', u'𞤥'), + (0x1E904, 'M', u'𞤦'), + (0x1E905, 'M', u'𞤧'), + (0x1E906, 'M', u'𞤨'), + (0x1E907, 'M', u'𞤩'), + (0x1E908, 'M', u'𞤪'), + (0x1E909, 'M', u'𞤫'), + (0x1E90A, 'M', u'𞤬'), + (0x1E90B, 'M', u'𞤭'), + (0x1E90C, 'M', u'𞤮'), + (0x1E90D, 'M', u'𞤯'), + (0x1E90E, 'M', u'𞤰'), + (0x1E90F, 'M', u'𞤱'), + (0x1E910, 'M', u'𞤲'), + (0x1E911, 'M', u'𞤳'), + (0x1E912, 'M', u'𞤴'), + (0x1E913, 'M', u'𞤵'), + (0x1E914, 'M', u'𞤶'), + (0x1E915, 'M', u'𞤷'), + (0x1E916, 'M', u'𞤸'), + (0x1E917, 'M', u'𞤹'), + (0x1E918, 'M', u'𞤺'), + (0x1E919, 'M', u'𞤻'), + (0x1E91A, 'M', u'𞤼'), + (0x1E91B, 'M', u'𞤽'), + (0x1E91C, 'M', u'𞤾'), + (0x1E91D, 'M', u'𞤿'), + (0x1E91E, 'M', u'𞥀'), + (0x1E91F, 'M', u'𞥁'), + (0x1E920, 'M', u'𞥂'), + (0x1E921, 'M', u'𞥃'), + (0x1E922, 'V'), + (0x1E94B, 'X'), + (0x1E950, 'V'), + (0x1E95A, 'X'), + (0x1E95E, 'V'), + (0x1E960, 'X'), + (0x1EE00, 'M', u'ا'), + (0x1EE01, 'M', u'ب'), + (0x1EE02, 'M', u'ج'), + (0x1EE03, 'M', u'د'), + (0x1EE04, 'X'), + (0x1EE05, 'M', u'و'), + (0x1EE06, 'M', u'ز'), + (0x1EE07, 'M', u'ح'), + (0x1EE08, 'M', u'ط'), + (0x1EE09, 'M', u'ي'), + (0x1EE0A, 'M', u'ك'), + (0x1EE0B, 'M', u'ل'), + (0x1EE0C, 'M', u'م'), + (0x1EE0D, 'M', u'ن'), + (0x1EE0E, 'M', u'س'), + (0x1EE0F, 'M', u'ع'), + (0x1EE10, 'M', u'ف'), + (0x1EE11, 'M', u'ص'), + (0x1EE12, 'M', u'ق'), + (0x1EE13, 'M', u'ر'), + (0x1EE14, 'M', u'ش'), + (0x1EE15, 'M', u'ت'), + (0x1EE16, 'M', u'ث'), + (0x1EE17, 'M', u'خ'), + (0x1EE18, 'M', u'ذ'), + (0x1EE19, 'M', u'ض'), + (0x1EE1A, 'M', u'ظ'), + (0x1EE1B, 'M', u'غ'), + (0x1EE1C, 'M', u'ٮ'), + (0x1EE1D, 'M', u'ں'), + (0x1EE1E, 'M', u'ڡ'), + (0x1EE1F, 'M', u'ٯ'), + (0x1EE20, 'X'), + (0x1EE21, 'M', u'ب'), + (0x1EE22, 'M', u'ج'), + (0x1EE23, 'X'), + ] + +def _seg_69(): + return [ + (0x1EE24, 'M', u'ه'), + (0x1EE25, 'X'), + (0x1EE27, 'M', u'ح'), + (0x1EE28, 'X'), + (0x1EE29, 'M', u'ي'), + (0x1EE2A, 'M', u'ك'), + (0x1EE2B, 'M', u'ل'), + (0x1EE2C, 'M', u'م'), + (0x1EE2D, 'M', u'ن'), + (0x1EE2E, 'M', u'س'), + (0x1EE2F, 'M', u'ع'), + (0x1EE30, 'M', u'ف'), + (0x1EE31, 'M', u'ص'), + (0x1EE32, 'M', u'ق'), + (0x1EE33, 'X'), + (0x1EE34, 'M', u'ش'), + (0x1EE35, 'M', u'ت'), + (0x1EE36, 'M', u'ث'), + (0x1EE37, 'M', u'خ'), + (0x1EE38, 'X'), + (0x1EE39, 'M', u'ض'), + (0x1EE3A, 'X'), + (0x1EE3B, 'M', u'غ'), + (0x1EE3C, 'X'), + (0x1EE42, 'M', u'ج'), + (0x1EE43, 'X'), + (0x1EE47, 'M', u'ح'), + (0x1EE48, 'X'), + (0x1EE49, 'M', u'ي'), + (0x1EE4A, 'X'), + (0x1EE4B, 'M', u'ل'), + (0x1EE4C, 'X'), + (0x1EE4D, 'M', u'ن'), + (0x1EE4E, 'M', u'س'), + (0x1EE4F, 'M', u'ع'), + (0x1EE50, 'X'), + (0x1EE51, 'M', u'ص'), + (0x1EE52, 'M', u'ق'), + (0x1EE53, 'X'), + (0x1EE54, 'M', u'ش'), + (0x1EE55, 'X'), + (0x1EE57, 'M', u'خ'), + (0x1EE58, 'X'), + (0x1EE59, 'M', u'ض'), + (0x1EE5A, 'X'), + (0x1EE5B, 'M', u'غ'), + (0x1EE5C, 'X'), + (0x1EE5D, 'M', u'ں'), + (0x1EE5E, 'X'), + (0x1EE5F, 'M', u'ٯ'), + (0x1EE60, 'X'), + (0x1EE61, 'M', u'ب'), + (0x1EE62, 'M', u'ج'), + (0x1EE63, 'X'), + (0x1EE64, 'M', u'ه'), + (0x1EE65, 'X'), + (0x1EE67, 'M', u'ح'), + (0x1EE68, 'M', u'ط'), + (0x1EE69, 'M', u'ي'), + (0x1EE6A, 'M', u'ك'), + (0x1EE6B, 'X'), + (0x1EE6C, 'M', u'م'), + (0x1EE6D, 'M', u'ن'), + (0x1EE6E, 'M', u'س'), + (0x1EE6F, 'M', u'ع'), + (0x1EE70, 'M', u'ف'), + (0x1EE71, 'M', u'ص'), + (0x1EE72, 'M', u'ق'), + (0x1EE73, 'X'), + (0x1EE74, 'M', u'ش'), + (0x1EE75, 'M', u'ت'), + (0x1EE76, 'M', u'ث'), + (0x1EE77, 'M', u'خ'), + (0x1EE78, 'X'), + (0x1EE79, 'M', u'ض'), + (0x1EE7A, 'M', u'ظ'), + (0x1EE7B, 'M', u'غ'), + (0x1EE7C, 'M', u'ٮ'), + (0x1EE7D, 'X'), + (0x1EE7E, 'M', u'ڡ'), + (0x1EE7F, 'X'), + (0x1EE80, 'M', u'ا'), + (0x1EE81, 'M', u'ب'), + (0x1EE82, 'M', u'ج'), + (0x1EE83, 'M', u'د'), + (0x1EE84, 'M', u'ه'), + (0x1EE85, 'M', u'و'), + (0x1EE86, 'M', u'ز'), + (0x1EE87, 'M', u'ح'), + (0x1EE88, 'M', u'ط'), + (0x1EE89, 'M', u'ي'), + (0x1EE8A, 'X'), + (0x1EE8B, 'M', u'ل'), + (0x1EE8C, 'M', u'م'), + (0x1EE8D, 'M', u'ن'), + (0x1EE8E, 'M', u'س'), + (0x1EE8F, 'M', u'ع'), + (0x1EE90, 'M', u'ف'), + (0x1EE91, 'M', u'ص'), + (0x1EE92, 'M', u'ق'), + ] + +def _seg_70(): + return [ + (0x1EE93, 'M', u'ر'), + (0x1EE94, 'M', u'ش'), + (0x1EE95, 'M', u'ت'), + (0x1EE96, 'M', u'ث'), + (0x1EE97, 'M', u'خ'), + (0x1EE98, 'M', u'ذ'), + (0x1EE99, 'M', u'ض'), + (0x1EE9A, 'M', u'ظ'), + (0x1EE9B, 'M', u'غ'), + (0x1EE9C, 'X'), + (0x1EEA1, 'M', u'ب'), + (0x1EEA2, 'M', u'ج'), + (0x1EEA3, 'M', u'د'), + (0x1EEA4, 'X'), + (0x1EEA5, 'M', u'و'), + (0x1EEA6, 'M', u'ز'), + (0x1EEA7, 'M', u'ح'), + (0x1EEA8, 'M', u'ط'), + (0x1EEA9, 'M', u'ي'), + (0x1EEAA, 'X'), + (0x1EEAB, 'M', u'ل'), + (0x1EEAC, 'M', u'م'), + (0x1EEAD, 'M', u'ن'), + (0x1EEAE, 'M', u'س'), + (0x1EEAF, 'M', u'ع'), + (0x1EEB0, 'M', u'ف'), + (0x1EEB1, 'M', u'ص'), + (0x1EEB2, 'M', u'ق'), + (0x1EEB3, 'M', u'ر'), + (0x1EEB4, 'M', u'ش'), + (0x1EEB5, 'M', u'ت'), + (0x1EEB6, 'M', u'ث'), + (0x1EEB7, 'M', u'خ'), + (0x1EEB8, 'M', u'ذ'), + (0x1EEB9, 'M', u'ض'), + (0x1EEBA, 'M', u'ظ'), + (0x1EEBB, 'M', u'غ'), + (0x1EEBC, 'X'), + (0x1EEF0, 'V'), + (0x1EEF2, 'X'), + (0x1F000, 'V'), + (0x1F02C, 'X'), + (0x1F030, 'V'), + (0x1F094, 'X'), + (0x1F0A0, 'V'), + (0x1F0AF, 'X'), + (0x1F0B1, 'V'), + (0x1F0C0, 'X'), + (0x1F0C1, 'V'), + (0x1F0D0, 'X'), + (0x1F0D1, 'V'), + (0x1F0F6, 'X'), + (0x1F101, '3', u'0,'), + (0x1F102, '3', u'1,'), + (0x1F103, '3', u'2,'), + (0x1F104, '3', u'3,'), + (0x1F105, '3', u'4,'), + (0x1F106, '3', u'5,'), + (0x1F107, '3', u'6,'), + (0x1F108, '3', u'7,'), + (0x1F109, '3', u'8,'), + (0x1F10A, '3', u'9,'), + (0x1F10B, 'V'), + (0x1F10D, 'X'), + (0x1F110, '3', u'(a)'), + (0x1F111, '3', u'(b)'), + (0x1F112, '3', u'(c)'), + (0x1F113, '3', u'(d)'), + (0x1F114, '3', u'(e)'), + (0x1F115, '3', u'(f)'), + (0x1F116, '3', u'(g)'), + (0x1F117, '3', u'(h)'), + (0x1F118, '3', u'(i)'), + (0x1F119, '3', u'(j)'), + (0x1F11A, '3', u'(k)'), + (0x1F11B, '3', u'(l)'), + (0x1F11C, '3', u'(m)'), + (0x1F11D, '3', u'(n)'), + (0x1F11E, '3', u'(o)'), + (0x1F11F, '3', u'(p)'), + (0x1F120, '3', u'(q)'), + (0x1F121, '3', u'(r)'), + (0x1F122, '3', u'(s)'), + (0x1F123, '3', u'(t)'), + (0x1F124, '3', u'(u)'), + (0x1F125, '3', u'(v)'), + (0x1F126, '3', u'(w)'), + (0x1F127, '3', u'(x)'), + (0x1F128, '3', u'(y)'), + (0x1F129, '3', u'(z)'), + (0x1F12A, 'M', u'〔s〕'), + (0x1F12B, 'M', u'c'), + (0x1F12C, 'M', u'r'), + (0x1F12D, 'M', u'cd'), + (0x1F12E, 'M', u'wz'), + (0x1F12F, 'X'), + (0x1F130, 'M', u'a'), + (0x1F131, 'M', u'b'), + (0x1F132, 'M', u'c'), + (0x1F133, 'M', u'd'), + ] + +def _seg_71(): + return [ + (0x1F134, 'M', u'e'), + (0x1F135, 'M', u'f'), + (0x1F136, 'M', u'g'), + (0x1F137, 'M', u'h'), + (0x1F138, 'M', u'i'), + (0x1F139, 'M', u'j'), + (0x1F13A, 'M', u'k'), + (0x1F13B, 'M', u'l'), + (0x1F13C, 'M', u'm'), + (0x1F13D, 'M', u'n'), + (0x1F13E, 'M', u'o'), + (0x1F13F, 'M', u'p'), + (0x1F140, 'M', u'q'), + (0x1F141, 'M', u'r'), + (0x1F142, 'M', u's'), + (0x1F143, 'M', u't'), + (0x1F144, 'M', u'u'), + (0x1F145, 'M', u'v'), + (0x1F146, 'M', u'w'), + (0x1F147, 'M', u'x'), + (0x1F148, 'M', u'y'), + (0x1F149, 'M', u'z'), + (0x1F14A, 'M', u'hv'), + (0x1F14B, 'M', u'mv'), + (0x1F14C, 'M', u'sd'), + (0x1F14D, 'M', u'ss'), + (0x1F14E, 'M', u'ppv'), + (0x1F14F, 'M', u'wc'), + (0x1F150, 'V'), + (0x1F16A, 'M', u'mc'), + (0x1F16B, 'M', u'md'), + (0x1F16C, 'X'), + (0x1F170, 'V'), + (0x1F190, 'M', u'dj'), + (0x1F191, 'V'), + (0x1F1AD, 'X'), + (0x1F1E6, 'V'), + (0x1F200, 'M', u'ほか'), + (0x1F201, 'M', u'ココ'), + (0x1F202, 'M', u'サ'), + (0x1F203, 'X'), + (0x1F210, 'M', u'手'), + (0x1F211, 'M', u'字'), + (0x1F212, 'M', u'双'), + (0x1F213, 'M', u'デ'), + (0x1F214, 'M', u'二'), + (0x1F215, 'M', u'多'), + (0x1F216, 'M', u'解'), + (0x1F217, 'M', u'天'), + (0x1F218, 'M', u'交'), + (0x1F219, 'M', u'映'), + (0x1F21A, 'M', u'無'), + (0x1F21B, 'M', u'料'), + (0x1F21C, 'M', u'前'), + (0x1F21D, 'M', u'後'), + (0x1F21E, 'M', u'再'), + (0x1F21F, 'M', u'新'), + (0x1F220, 'M', u'初'), + (0x1F221, 'M', u'終'), + (0x1F222, 'M', u'生'), + (0x1F223, 'M', u'販'), + (0x1F224, 'M', u'声'), + (0x1F225, 'M', u'吹'), + (0x1F226, 'M', u'演'), + (0x1F227, 'M', u'投'), + (0x1F228, 'M', u'捕'), + (0x1F229, 'M', u'一'), + (0x1F22A, 'M', u'三'), + (0x1F22B, 'M', u'遊'), + (0x1F22C, 'M', u'左'), + (0x1F22D, 'M', u'中'), + (0x1F22E, 'M', u'右'), + (0x1F22F, 'M', u'指'), + (0x1F230, 'M', u'走'), + (0x1F231, 'M', u'打'), + (0x1F232, 'M', u'禁'), + (0x1F233, 'M', u'空'), + (0x1F234, 'M', u'合'), + (0x1F235, 'M', u'満'), + (0x1F236, 'M', u'有'), + (0x1F237, 'M', u'月'), + (0x1F238, 'M', u'申'), + (0x1F239, 'M', u'割'), + (0x1F23A, 'M', u'営'), + (0x1F23B, 'M', u'配'), + (0x1F23C, 'X'), + (0x1F240, 'M', u'〔本〕'), + (0x1F241, 'M', u'〔三〕'), + (0x1F242, 'M', u'〔二〕'), + (0x1F243, 'M', u'〔安〕'), + (0x1F244, 'M', u'〔点〕'), + (0x1F245, 'M', u'〔打〕'), + (0x1F246, 'M', u'〔盗〕'), + (0x1F247, 'M', u'〔勝〕'), + (0x1F248, 'M', u'〔敗〕'), + (0x1F249, 'X'), + (0x1F250, 'M', u'得'), + (0x1F251, 'M', u'可'), + (0x1F252, 'X'), + (0x1F260, 'V'), + ] + +def _seg_72(): + return [ + (0x1F266, 'X'), + (0x1F300, 'V'), + (0x1F6D5, 'X'), + (0x1F6E0, 'V'), + (0x1F6ED, 'X'), + (0x1F6F0, 'V'), + (0x1F6F9, 'X'), + (0x1F700, 'V'), + (0x1F774, 'X'), + (0x1F780, 'V'), + (0x1F7D5, 'X'), + (0x1F800, 'V'), + (0x1F80C, 'X'), + (0x1F810, 'V'), + (0x1F848, 'X'), + (0x1F850, 'V'), + (0x1F85A, 'X'), + (0x1F860, 'V'), + (0x1F888, 'X'), + (0x1F890, 'V'), + (0x1F8AE, 'X'), + (0x1F900, 'V'), + (0x1F90C, 'X'), + (0x1F910, 'V'), + (0x1F93F, 'X'), + (0x1F940, 'V'), + (0x1F94D, 'X'), + (0x1F950, 'V'), + (0x1F96C, 'X'), + (0x1F980, 'V'), + (0x1F998, 'X'), + (0x1F9C0, 'V'), + (0x1F9C1, 'X'), + (0x1F9D0, 'V'), + (0x1F9E7, 'X'), + (0x20000, 'V'), + (0x2A6D7, 'X'), + (0x2A700, 'V'), + (0x2B735, 'X'), + (0x2B740, 'V'), + (0x2B81E, 'X'), + (0x2B820, 'V'), + (0x2CEA2, 'X'), + (0x2CEB0, 'V'), + (0x2EBE1, 'X'), + (0x2F800, 'M', u'丽'), + (0x2F801, 'M', u'丸'), + (0x2F802, 'M', u'乁'), + (0x2F803, 'M', u'𠄢'), + (0x2F804, 'M', u'你'), + (0x2F805, 'M', u'侮'), + (0x2F806, 'M', u'侻'), + (0x2F807, 'M', u'倂'), + (0x2F808, 'M', u'偺'), + (0x2F809, 'M', u'備'), + (0x2F80A, 'M', u'僧'), + (0x2F80B, 'M', u'像'), + (0x2F80C, 'M', u'㒞'), + (0x2F80D, 'M', u'𠘺'), + (0x2F80E, 'M', u'免'), + (0x2F80F, 'M', u'兔'), + (0x2F810, 'M', u'兤'), + (0x2F811, 'M', u'具'), + (0x2F812, 'M', u'𠔜'), + (0x2F813, 'M', u'㒹'), + (0x2F814, 'M', u'內'), + (0x2F815, 'M', u'再'), + (0x2F816, 'M', u'𠕋'), + (0x2F817, 'M', u'冗'), + (0x2F818, 'M', u'冤'), + (0x2F819, 'M', u'仌'), + (0x2F81A, 'M', u'冬'), + (0x2F81B, 'M', u'况'), + (0x2F81C, 'M', u'𩇟'), + (0x2F81D, 'M', u'凵'), + (0x2F81E, 'M', u'刃'), + (0x2F81F, 'M', u'㓟'), + (0x2F820, 'M', u'刻'), + (0x2F821, 'M', u'剆'), + (0x2F822, 'M', u'割'), + (0x2F823, 'M', u'剷'), + (0x2F824, 'M', u'㔕'), + (0x2F825, 'M', u'勇'), + (0x2F826, 'M', u'勉'), + (0x2F827, 'M', u'勤'), + (0x2F828, 'M', u'勺'), + (0x2F829, 'M', u'包'), + (0x2F82A, 'M', u'匆'), + (0x2F82B, 'M', u'北'), + (0x2F82C, 'M', u'卉'), + (0x2F82D, 'M', u'卑'), + (0x2F82E, 'M', u'博'), + (0x2F82F, 'M', u'即'), + (0x2F830, 'M', u'卽'), + (0x2F831, 'M', u'卿'), + (0x2F834, 'M', u'𠨬'), + (0x2F835, 'M', u'灰'), + (0x2F836, 'M', u'及'), + (0x2F837, 'M', u'叟'), + (0x2F838, 'M', u'𠭣'), + ] + +def _seg_73(): + return [ + (0x2F839, 'M', u'叫'), + (0x2F83A, 'M', u'叱'), + (0x2F83B, 'M', u'吆'), + (0x2F83C, 'M', u'咞'), + (0x2F83D, 'M', u'吸'), + (0x2F83E, 'M', u'呈'), + (0x2F83F, 'M', u'周'), + (0x2F840, 'M', u'咢'), + (0x2F841, 'M', u'哶'), + (0x2F842, 'M', u'唐'), + (0x2F843, 'M', u'啓'), + (0x2F844, 'M', u'啣'), + (0x2F845, 'M', u'善'), + (0x2F847, 'M', u'喙'), + (0x2F848, 'M', u'喫'), + (0x2F849, 'M', u'喳'), + (0x2F84A, 'M', u'嗂'), + (0x2F84B, 'M', u'圖'), + (0x2F84C, 'M', u'嘆'), + (0x2F84D, 'M', u'圗'), + (0x2F84E, 'M', u'噑'), + (0x2F84F, 'M', u'噴'), + (0x2F850, 'M', u'切'), + (0x2F851, 'M', u'壮'), + (0x2F852, 'M', u'城'), + (0x2F853, 'M', u'埴'), + (0x2F854, 'M', u'堍'), + (0x2F855, 'M', u'型'), + (0x2F856, 'M', u'堲'), + (0x2F857, 'M', u'報'), + (0x2F858, 'M', u'墬'), + (0x2F859, 'M', u'𡓤'), + (0x2F85A, 'M', u'売'), + (0x2F85B, 'M', u'壷'), + (0x2F85C, 'M', u'夆'), + (0x2F85D, 'M', u'多'), + (0x2F85E, 'M', u'夢'), + (0x2F85F, 'M', u'奢'), + (0x2F860, 'M', u'𡚨'), + (0x2F861, 'M', u'𡛪'), + (0x2F862, 'M', u'姬'), + (0x2F863, 'M', u'娛'), + (0x2F864, 'M', u'娧'), + (0x2F865, 'M', u'姘'), + (0x2F866, 'M', u'婦'), + (0x2F867, 'M', u'㛮'), + (0x2F868, 'X'), + (0x2F869, 'M', u'嬈'), + (0x2F86A, 'M', u'嬾'), + (0x2F86C, 'M', u'𡧈'), + (0x2F86D, 'M', u'寃'), + (0x2F86E, 'M', u'寘'), + (0x2F86F, 'M', u'寧'), + (0x2F870, 'M', u'寳'), + (0x2F871, 'M', u'𡬘'), + (0x2F872, 'M', u'寿'), + (0x2F873, 'M', u'将'), + (0x2F874, 'X'), + (0x2F875, 'M', u'尢'), + (0x2F876, 'M', u'㞁'), + (0x2F877, 'M', u'屠'), + (0x2F878, 'M', u'屮'), + (0x2F879, 'M', u'峀'), + (0x2F87A, 'M', u'岍'), + (0x2F87B, 'M', u'𡷤'), + (0x2F87C, 'M', u'嵃'), + (0x2F87D, 'M', u'𡷦'), + (0x2F87E, 'M', u'嵮'), + (0x2F87F, 'M', u'嵫'), + (0x2F880, 'M', u'嵼'), + (0x2F881, 'M', u'巡'), + (0x2F882, 'M', u'巢'), + (0x2F883, 'M', u'㠯'), + (0x2F884, 'M', u'巽'), + (0x2F885, 'M', u'帨'), + (0x2F886, 'M', u'帽'), + (0x2F887, 'M', u'幩'), + (0x2F888, 'M', u'㡢'), + (0x2F889, 'M', u'𢆃'), + (0x2F88A, 'M', u'㡼'), + (0x2F88B, 'M', u'庰'), + (0x2F88C, 'M', u'庳'), + (0x2F88D, 'M', u'庶'), + (0x2F88E, 'M', u'廊'), + (0x2F88F, 'M', u'𪎒'), + (0x2F890, 'M', u'廾'), + (0x2F891, 'M', u'𢌱'), + (0x2F893, 'M', u'舁'), + (0x2F894, 'M', u'弢'), + (0x2F896, 'M', u'㣇'), + (0x2F897, 'M', u'𣊸'), + (0x2F898, 'M', u'𦇚'), + (0x2F899, 'M', u'形'), + (0x2F89A, 'M', u'彫'), + (0x2F89B, 'M', u'㣣'), + (0x2F89C, 'M', u'徚'), + (0x2F89D, 'M', u'忍'), + (0x2F89E, 'M', u'志'), + (0x2F89F, 'M', u'忹'), + (0x2F8A0, 'M', u'悁'), + ] + +def _seg_74(): + return [ + (0x2F8A1, 'M', u'㤺'), + (0x2F8A2, 'M', u'㤜'), + (0x2F8A3, 'M', u'悔'), + (0x2F8A4, 'M', u'𢛔'), + (0x2F8A5, 'M', u'惇'), + (0x2F8A6, 'M', u'慈'), + (0x2F8A7, 'M', u'慌'), + (0x2F8A8, 'M', u'慎'), + (0x2F8A9, 'M', u'慌'), + (0x2F8AA, 'M', u'慺'), + (0x2F8AB, 'M', u'憎'), + (0x2F8AC, 'M', u'憲'), + (0x2F8AD, 'M', u'憤'), + (0x2F8AE, 'M', u'憯'), + (0x2F8AF, 'M', u'懞'), + (0x2F8B0, 'M', u'懲'), + (0x2F8B1, 'M', u'懶'), + (0x2F8B2, 'M', u'成'), + (0x2F8B3, 'M', u'戛'), + (0x2F8B4, 'M', u'扝'), + (0x2F8B5, 'M', u'抱'), + (0x2F8B6, 'M', u'拔'), + (0x2F8B7, 'M', u'捐'), + (0x2F8B8, 'M', u'𢬌'), + (0x2F8B9, 'M', u'挽'), + (0x2F8BA, 'M', u'拼'), + (0x2F8BB, 'M', u'捨'), + (0x2F8BC, 'M', u'掃'), + (0x2F8BD, 'M', u'揤'), + (0x2F8BE, 'M', u'𢯱'), + (0x2F8BF, 'M', u'搢'), + (0x2F8C0, 'M', u'揅'), + (0x2F8C1, 'M', u'掩'), + (0x2F8C2, 'M', u'㨮'), + (0x2F8C3, 'M', u'摩'), + (0x2F8C4, 'M', u'摾'), + (0x2F8C5, 'M', u'撝'), + (0x2F8C6, 'M', u'摷'), + (0x2F8C7, 'M', u'㩬'), + (0x2F8C8, 'M', u'敏'), + (0x2F8C9, 'M', u'敬'), + (0x2F8CA, 'M', u'𣀊'), + (0x2F8CB, 'M', u'旣'), + (0x2F8CC, 'M', u'書'), + (0x2F8CD, 'M', u'晉'), + (0x2F8CE, 'M', u'㬙'), + (0x2F8CF, 'M', u'暑'), + (0x2F8D0, 'M', u'㬈'), + (0x2F8D1, 'M', u'㫤'), + (0x2F8D2, 'M', u'冒'), + (0x2F8D3, 'M', u'冕'), + (0x2F8D4, 'M', u'最'), + (0x2F8D5, 'M', u'暜'), + (0x2F8D6, 'M', u'肭'), + (0x2F8D7, 'M', u'䏙'), + (0x2F8D8, 'M', u'朗'), + (0x2F8D9, 'M', u'望'), + (0x2F8DA, 'M', u'朡'), + (0x2F8DB, 'M', u'杞'), + (0x2F8DC, 'M', u'杓'), + (0x2F8DD, 'M', u'𣏃'), + (0x2F8DE, 'M', u'㭉'), + (0x2F8DF, 'M', u'柺'), + (0x2F8E0, 'M', u'枅'), + (0x2F8E1, 'M', u'桒'), + (0x2F8E2, 'M', u'梅'), + (0x2F8E3, 'M', u'𣑭'), + (0x2F8E4, 'M', u'梎'), + (0x2F8E5, 'M', u'栟'), + (0x2F8E6, 'M', u'椔'), + (0x2F8E7, 'M', u'㮝'), + (0x2F8E8, 'M', u'楂'), + (0x2F8E9, 'M', u'榣'), + (0x2F8EA, 'M', u'槪'), + (0x2F8EB, 'M', u'檨'), + (0x2F8EC, 'M', u'𣚣'), + (0x2F8ED, 'M', u'櫛'), + (0x2F8EE, 'M', u'㰘'), + (0x2F8EF, 'M', u'次'), + (0x2F8F0, 'M', u'𣢧'), + (0x2F8F1, 'M', u'歔'), + (0x2F8F2, 'M', u'㱎'), + (0x2F8F3, 'M', u'歲'), + (0x2F8F4, 'M', u'殟'), + (0x2F8F5, 'M', u'殺'), + (0x2F8F6, 'M', u'殻'), + (0x2F8F7, 'M', u'𣪍'), + (0x2F8F8, 'M', u'𡴋'), + (0x2F8F9, 'M', u'𣫺'), + (0x2F8FA, 'M', u'汎'), + (0x2F8FB, 'M', u'𣲼'), + (0x2F8FC, 'M', u'沿'), + (0x2F8FD, 'M', u'泍'), + (0x2F8FE, 'M', u'汧'), + (0x2F8FF, 'M', u'洖'), + (0x2F900, 'M', u'派'), + (0x2F901, 'M', u'海'), + (0x2F902, 'M', u'流'), + (0x2F903, 'M', u'浩'), + (0x2F904, 'M', u'浸'), + ] + +def _seg_75(): + return [ + (0x2F905, 'M', u'涅'), + (0x2F906, 'M', u'𣴞'), + (0x2F907, 'M', u'洴'), + (0x2F908, 'M', u'港'), + (0x2F909, 'M', u'湮'), + (0x2F90A, 'M', u'㴳'), + (0x2F90B, 'M', u'滋'), + (0x2F90C, 'M', u'滇'), + (0x2F90D, 'M', u'𣻑'), + (0x2F90E, 'M', u'淹'), + (0x2F90F, 'M', u'潮'), + (0x2F910, 'M', u'𣽞'), + (0x2F911, 'M', u'𣾎'), + (0x2F912, 'M', u'濆'), + (0x2F913, 'M', u'瀹'), + (0x2F914, 'M', u'瀞'), + (0x2F915, 'M', u'瀛'), + (0x2F916, 'M', u'㶖'), + (0x2F917, 'M', u'灊'), + (0x2F918, 'M', u'災'), + (0x2F919, 'M', u'灷'), + (0x2F91A, 'M', u'炭'), + (0x2F91B, 'M', u'𠔥'), + (0x2F91C, 'M', u'煅'), + (0x2F91D, 'M', u'𤉣'), + (0x2F91E, 'M', u'熜'), + (0x2F91F, 'X'), + (0x2F920, 'M', u'爨'), + (0x2F921, 'M', u'爵'), + (0x2F922, 'M', u'牐'), + (0x2F923, 'M', u'𤘈'), + (0x2F924, 'M', u'犀'), + (0x2F925, 'M', u'犕'), + (0x2F926, 'M', u'𤜵'), + (0x2F927, 'M', u'𤠔'), + (0x2F928, 'M', u'獺'), + (0x2F929, 'M', u'王'), + (0x2F92A, 'M', u'㺬'), + (0x2F92B, 'M', u'玥'), + (0x2F92C, 'M', u'㺸'), + (0x2F92E, 'M', u'瑇'), + (0x2F92F, 'M', u'瑜'), + (0x2F930, 'M', u'瑱'), + (0x2F931, 'M', u'璅'), + (0x2F932, 'M', u'瓊'), + (0x2F933, 'M', u'㼛'), + (0x2F934, 'M', u'甤'), + (0x2F935, 'M', u'𤰶'), + (0x2F936, 'M', u'甾'), + (0x2F937, 'M', u'𤲒'), + (0x2F938, 'M', u'異'), + (0x2F939, 'M', u'𢆟'), + (0x2F93A, 'M', u'瘐'), + (0x2F93B, 'M', u'𤾡'), + (0x2F93C, 'M', u'𤾸'), + (0x2F93D, 'M', u'𥁄'), + (0x2F93E, 'M', u'㿼'), + (0x2F93F, 'M', u'䀈'), + (0x2F940, 'M', u'直'), + (0x2F941, 'M', u'𥃳'), + (0x2F942, 'M', u'𥃲'), + (0x2F943, 'M', u'𥄙'), + (0x2F944, 'M', u'𥄳'), + (0x2F945, 'M', u'眞'), + (0x2F946, 'M', u'真'), + (0x2F948, 'M', u'睊'), + (0x2F949, 'M', u'䀹'), + (0x2F94A, 'M', u'瞋'), + (0x2F94B, 'M', u'䁆'), + (0x2F94C, 'M', u'䂖'), + (0x2F94D, 'M', u'𥐝'), + (0x2F94E, 'M', u'硎'), + (0x2F94F, 'M', u'碌'), + (0x2F950, 'M', u'磌'), + (0x2F951, 'M', u'䃣'), + (0x2F952, 'M', u'𥘦'), + (0x2F953, 'M', u'祖'), + (0x2F954, 'M', u'𥚚'), + (0x2F955, 'M', u'𥛅'), + (0x2F956, 'M', u'福'), + (0x2F957, 'M', u'秫'), + (0x2F958, 'M', u'䄯'), + (0x2F959, 'M', u'穀'), + (0x2F95A, 'M', u'穊'), + (0x2F95B, 'M', u'穏'), + (0x2F95C, 'M', u'𥥼'), + (0x2F95D, 'M', u'𥪧'), + (0x2F95F, 'X'), + (0x2F960, 'M', u'䈂'), + (0x2F961, 'M', u'𥮫'), + (0x2F962, 'M', u'篆'), + (0x2F963, 'M', u'築'), + (0x2F964, 'M', u'䈧'), + (0x2F965, 'M', u'𥲀'), + (0x2F966, 'M', u'糒'), + (0x2F967, 'M', u'䊠'), + (0x2F968, 'M', u'糨'), + (0x2F969, 'M', u'糣'), + (0x2F96A, 'M', u'紀'), + (0x2F96B, 'M', u'𥾆'), + ] + +def _seg_76(): + return [ + (0x2F96C, 'M', u'絣'), + (0x2F96D, 'M', u'䌁'), + (0x2F96E, 'M', u'緇'), + (0x2F96F, 'M', u'縂'), + (0x2F970, 'M', u'繅'), + (0x2F971, 'M', u'䌴'), + (0x2F972, 'M', u'𦈨'), + (0x2F973, 'M', u'𦉇'), + (0x2F974, 'M', u'䍙'), + (0x2F975, 'M', u'𦋙'), + (0x2F976, 'M', u'罺'), + (0x2F977, 'M', u'𦌾'), + (0x2F978, 'M', u'羕'), + (0x2F979, 'M', u'翺'), + (0x2F97A, 'M', u'者'), + (0x2F97B, 'M', u'𦓚'), + (0x2F97C, 'M', u'𦔣'), + (0x2F97D, 'M', u'聠'), + (0x2F97E, 'M', u'𦖨'), + (0x2F97F, 'M', u'聰'), + (0x2F980, 'M', u'𣍟'), + (0x2F981, 'M', u'䏕'), + (0x2F982, 'M', u'育'), + (0x2F983, 'M', u'脃'), + (0x2F984, 'M', u'䐋'), + (0x2F985, 'M', u'脾'), + (0x2F986, 'M', u'媵'), + (0x2F987, 'M', u'𦞧'), + (0x2F988, 'M', u'𦞵'), + (0x2F989, 'M', u'𣎓'), + (0x2F98A, 'M', u'𣎜'), + (0x2F98B, 'M', u'舁'), + (0x2F98C, 'M', u'舄'), + (0x2F98D, 'M', u'辞'), + (0x2F98E, 'M', u'䑫'), + (0x2F98F, 'M', u'芑'), + (0x2F990, 'M', u'芋'), + (0x2F991, 'M', u'芝'), + (0x2F992, 'M', u'劳'), + (0x2F993, 'M', u'花'), + (0x2F994, 'M', u'芳'), + (0x2F995, 'M', u'芽'), + (0x2F996, 'M', u'苦'), + (0x2F997, 'M', u'𦬼'), + (0x2F998, 'M', u'若'), + (0x2F999, 'M', u'茝'), + (0x2F99A, 'M', u'荣'), + (0x2F99B, 'M', u'莭'), + (0x2F99C, 'M', u'茣'), + (0x2F99D, 'M', u'莽'), + (0x2F99E, 'M', u'菧'), + (0x2F99F, 'M', u'著'), + (0x2F9A0, 'M', u'荓'), + (0x2F9A1, 'M', u'菊'), + (0x2F9A2, 'M', u'菌'), + (0x2F9A3, 'M', u'菜'), + (0x2F9A4, 'M', u'𦰶'), + (0x2F9A5, 'M', u'𦵫'), + (0x2F9A6, 'M', u'𦳕'), + (0x2F9A7, 'M', u'䔫'), + (0x2F9A8, 'M', u'蓱'), + (0x2F9A9, 'M', u'蓳'), + (0x2F9AA, 'M', u'蔖'), + (0x2F9AB, 'M', u'𧏊'), + (0x2F9AC, 'M', u'蕤'), + (0x2F9AD, 'M', u'𦼬'), + (0x2F9AE, 'M', u'䕝'), + (0x2F9AF, 'M', u'䕡'), + (0x2F9B0, 'M', u'𦾱'), + (0x2F9B1, 'M', u'𧃒'), + (0x2F9B2, 'M', u'䕫'), + (0x2F9B3, 'M', u'虐'), + (0x2F9B4, 'M', u'虜'), + (0x2F9B5, 'M', u'虧'), + (0x2F9B6, 'M', u'虩'), + (0x2F9B7, 'M', u'蚩'), + (0x2F9B8, 'M', u'蚈'), + (0x2F9B9, 'M', u'蜎'), + (0x2F9BA, 'M', u'蛢'), + (0x2F9BB, 'M', u'蝹'), + (0x2F9BC, 'M', u'蜨'), + (0x2F9BD, 'M', u'蝫'), + (0x2F9BE, 'M', u'螆'), + (0x2F9BF, 'X'), + (0x2F9C0, 'M', u'蟡'), + (0x2F9C1, 'M', u'蠁'), + (0x2F9C2, 'M', u'䗹'), + (0x2F9C3, 'M', u'衠'), + (0x2F9C4, 'M', u'衣'), + (0x2F9C5, 'M', u'𧙧'), + (0x2F9C6, 'M', u'裗'), + (0x2F9C7, 'M', u'裞'), + (0x2F9C8, 'M', u'䘵'), + (0x2F9C9, 'M', u'裺'), + (0x2F9CA, 'M', u'㒻'), + (0x2F9CB, 'M', u'𧢮'), + (0x2F9CC, 'M', u'𧥦'), + (0x2F9CD, 'M', u'䚾'), + (0x2F9CE, 'M', u'䛇'), + (0x2F9CF, 'M', u'誠'), + ] + +def _seg_77(): + return [ + (0x2F9D0, 'M', u'諭'), + (0x2F9D1, 'M', u'變'), + (0x2F9D2, 'M', u'豕'), + (0x2F9D3, 'M', u'𧲨'), + (0x2F9D4, 'M', u'貫'), + (0x2F9D5, 'M', u'賁'), + (0x2F9D6, 'M', u'贛'), + (0x2F9D7, 'M', u'起'), + (0x2F9D8, 'M', u'𧼯'), + (0x2F9D9, 'M', u'𠠄'), + (0x2F9DA, 'M', u'跋'), + (0x2F9DB, 'M', u'趼'), + (0x2F9DC, 'M', u'跰'), + (0x2F9DD, 'M', u'𠣞'), + (0x2F9DE, 'M', u'軔'), + (0x2F9DF, 'M', u'輸'), + (0x2F9E0, 'M', u'𨗒'), + (0x2F9E1, 'M', u'𨗭'), + (0x2F9E2, 'M', u'邔'), + (0x2F9E3, 'M', u'郱'), + (0x2F9E4, 'M', u'鄑'), + (0x2F9E5, 'M', u'𨜮'), + (0x2F9E6, 'M', u'鄛'), + (0x2F9E7, 'M', u'鈸'), + (0x2F9E8, 'M', u'鋗'), + (0x2F9E9, 'M', u'鋘'), + (0x2F9EA, 'M', u'鉼'), + (0x2F9EB, 'M', u'鏹'), + (0x2F9EC, 'M', u'鐕'), + (0x2F9ED, 'M', u'𨯺'), + (0x2F9EE, 'M', u'開'), + (0x2F9EF, 'M', u'䦕'), + (0x2F9F0, 'M', u'閷'), + (0x2F9F1, 'M', u'𨵷'), + (0x2F9F2, 'M', u'䧦'), + (0x2F9F3, 'M', u'雃'), + (0x2F9F4, 'M', u'嶲'), + (0x2F9F5, 'M', u'霣'), + (0x2F9F6, 'M', u'𩅅'), + (0x2F9F7, 'M', u'𩈚'), + (0x2F9F8, 'M', u'䩮'), + (0x2F9F9, 'M', u'䩶'), + (0x2F9FA, 'M', u'韠'), + (0x2F9FB, 'M', u'𩐊'), + (0x2F9FC, 'M', u'䪲'), + (0x2F9FD, 'M', u'𩒖'), + (0x2F9FE, 'M', u'頋'), + (0x2FA00, 'M', u'頩'), + (0x2FA01, 'M', u'𩖶'), + (0x2FA02, 'M', u'飢'), + (0x2FA03, 'M', u'䬳'), + (0x2FA04, 'M', u'餩'), + (0x2FA05, 'M', u'馧'), + (0x2FA06, 'M', u'駂'), + (0x2FA07, 'M', u'駾'), + (0x2FA08, 'M', u'䯎'), + (0x2FA09, 'M', u'𩬰'), + (0x2FA0A, 'M', u'鬒'), + (0x2FA0B, 'M', u'鱀'), + (0x2FA0C, 'M', u'鳽'), + (0x2FA0D, 'M', u'䳎'), + (0x2FA0E, 'M', u'䳭'), + (0x2FA0F, 'M', u'鵧'), + (0x2FA10, 'M', u'𪃎'), + (0x2FA11, 'M', u'䳸'), + (0x2FA12, 'M', u'𪄅'), + (0x2FA13, 'M', u'𪈎'), + (0x2FA14, 'M', u'𪊑'), + (0x2FA15, 'M', u'麻'), + (0x2FA16, 'M', u'䵖'), + (0x2FA17, 'M', u'黹'), + (0x2FA18, 'M', u'黾'), + (0x2FA19, 'M', u'鼅'), + (0x2FA1A, 'M', u'鼏'), + (0x2FA1B, 'M', u'鼖'), + (0x2FA1C, 'M', u'鼻'), + (0x2FA1D, 'M', u'𪘀'), + (0x2FA1E, 'X'), + (0xE0100, 'I'), + (0xE01F0, 'X'), + ] + +uts46data = tuple( + _seg_0() + + _seg_1() + + _seg_2() + + _seg_3() + + _seg_4() + + _seg_5() + + _seg_6() + + _seg_7() + + _seg_8() + + _seg_9() + + _seg_10() + + _seg_11() + + _seg_12() + + _seg_13() + + _seg_14() + + _seg_15() + + _seg_16() + + _seg_17() + + _seg_18() + + _seg_19() + + _seg_20() + + _seg_21() + + _seg_22() + + _seg_23() + + _seg_24() + + _seg_25() + + _seg_26() + + _seg_27() + + _seg_28() + + _seg_29() + + _seg_30() + + _seg_31() + + _seg_32() + + _seg_33() + + _seg_34() + + _seg_35() + + _seg_36() + + _seg_37() + + _seg_38() + + _seg_39() + + _seg_40() + + _seg_41() + + _seg_42() + + _seg_43() + + _seg_44() + + _seg_45() + + _seg_46() + + _seg_47() + + _seg_48() + + _seg_49() + + _seg_50() + + _seg_51() + + _seg_52() + + _seg_53() + + _seg_54() + + _seg_55() + + _seg_56() + + _seg_57() + + _seg_58() + + _seg_59() + + _seg_60() + + _seg_61() + + _seg_62() + + _seg_63() + + _seg_64() + + _seg_65() + + _seg_66() + + _seg_67() + + _seg_68() + + _seg_69() + + _seg_70() + + _seg_71() + + _seg_72() + + _seg_73() + + _seg_74() + + _seg_75() + + _seg_76() + + _seg_77() +) diff --git a/winvenv/Lib/site-packages/pip/_vendor/ipaddress.py b/winvenv/Lib/site-packages/pip/_vendor/ipaddress.py new file mode 100644 index 0000000..f2d0766 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/ipaddress.py @@ -0,0 +1,2419 @@ +# Copyright 2007 Google Inc. +# Licensed to PSF under a Contributor Agreement. + +"""A fast, lightweight IPv4/IPv6 manipulation library in Python. + +This library is used to create/poke/manipulate IPv4 and IPv6 addresses +and networks. + +""" + +from __future__ import unicode_literals + + +import itertools +import struct + +__version__ = '1.0.22' + +# Compatibility functions +_compat_int_types = (int,) +try: + _compat_int_types = (int, long) +except NameError: + pass +try: + _compat_str = unicode +except NameError: + _compat_str = str + assert bytes != str +if b'\0'[0] == 0: # Python 3 semantics + def _compat_bytes_to_byte_vals(byt): + return byt +else: + def _compat_bytes_to_byte_vals(byt): + return [struct.unpack(b'!B', b)[0] for b in byt] +try: + _compat_int_from_byte_vals = int.from_bytes +except AttributeError: + def _compat_int_from_byte_vals(bytvals, endianess): + assert endianess == 'big' + res = 0 + for bv in bytvals: + assert isinstance(bv, _compat_int_types) + res = (res << 8) + bv + return res + + +def _compat_to_bytes(intval, length, endianess): + assert isinstance(intval, _compat_int_types) + assert endianess == 'big' + if length == 4: + if intval < 0 or intval >= 2 ** 32: + raise struct.error("integer out of range for 'I' format code") + return struct.pack(b'!I', intval) + elif length == 16: + if intval < 0 or intval >= 2 ** 128: + raise struct.error("integer out of range for 'QQ' format code") + return struct.pack(b'!QQ', intval >> 64, intval & 0xffffffffffffffff) + else: + raise NotImplementedError() + + +if hasattr(int, 'bit_length'): + # Not int.bit_length , since that won't work in 2.7 where long exists + def _compat_bit_length(i): + return i.bit_length() +else: + def _compat_bit_length(i): + for res in itertools.count(): + if i >> res == 0: + return res + + +def _compat_range(start, end, step=1): + assert step > 0 + i = start + while i < end: + yield i + i += step + + +class _TotalOrderingMixin(object): + __slots__ = () + + # Helper that derives the other comparison operations from + # __lt__ and __eq__ + # We avoid functools.total_ordering because it doesn't handle + # NotImplemented correctly yet (http://bugs.python.org/issue10042) + def __eq__(self, other): + raise NotImplementedError + + def __ne__(self, other): + equal = self.__eq__(other) + if equal is NotImplemented: + return NotImplemented + return not equal + + def __lt__(self, other): + raise NotImplementedError + + def __le__(self, other): + less = self.__lt__(other) + if less is NotImplemented or not less: + return self.__eq__(other) + return less + + def __gt__(self, other): + less = self.__lt__(other) + if less is NotImplemented: + return NotImplemented + equal = self.__eq__(other) + if equal is NotImplemented: + return NotImplemented + return not (less or equal) + + def __ge__(self, other): + less = self.__lt__(other) + if less is NotImplemented: + return NotImplemented + return not less + + +IPV4LENGTH = 32 +IPV6LENGTH = 128 + + +class AddressValueError(ValueError): + """A Value Error related to the address.""" + + +class NetmaskValueError(ValueError): + """A Value Error related to the netmask.""" + + +def ip_address(address): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP address. Either IPv4 or + IPv6 addresses may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + + Returns: + An IPv4Address or IPv6Address object. + + Raises: + ValueError: if the *address* passed isn't either a v4 or a v6 + address + + """ + try: + return IPv4Address(address) + except (AddressValueError, NetmaskValueError): + pass + + try: + return IPv6Address(address) + except (AddressValueError, NetmaskValueError): + pass + + if isinstance(address, bytes): + raise AddressValueError( + '%r does not appear to be an IPv4 or IPv6 address. ' + 'Did you pass in a bytes (str in Python 2) instead of' + ' a unicode object?' % address) + + raise ValueError('%r does not appear to be an IPv4 or IPv6 address' % + address) + + +def ip_network(address, strict=True): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP network. Either IPv4 or + IPv6 networks may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + + Returns: + An IPv4Network or IPv6Network object. + + Raises: + ValueError: if the string passed isn't either a v4 or a v6 + address. Or if the network has host bits set. + + """ + try: + return IPv4Network(address, strict) + except (AddressValueError, NetmaskValueError): + pass + + try: + return IPv6Network(address, strict) + except (AddressValueError, NetmaskValueError): + pass + + if isinstance(address, bytes): + raise AddressValueError( + '%r does not appear to be an IPv4 or IPv6 network. ' + 'Did you pass in a bytes (str in Python 2) instead of' + ' a unicode object?' % address) + + raise ValueError('%r does not appear to be an IPv4 or IPv6 network' % + address) + + +def ip_interface(address): + """Take an IP string/int and return an object of the correct type. + + Args: + address: A string or integer, the IP address. Either IPv4 or + IPv6 addresses may be supplied; integers less than 2**32 will + be considered to be IPv4 by default. + + Returns: + An IPv4Interface or IPv6Interface object. + + Raises: + ValueError: if the string passed isn't either a v4 or a v6 + address. + + Notes: + The IPv?Interface classes describe an Address on a particular + Network, so they're basically a combination of both the Address + and Network classes. + + """ + try: + return IPv4Interface(address) + except (AddressValueError, NetmaskValueError): + pass + + try: + return IPv6Interface(address) + except (AddressValueError, NetmaskValueError): + pass + + raise ValueError('%r does not appear to be an IPv4 or IPv6 interface' % + address) + + +def v4_int_to_packed(address): + """Represent an address as 4 packed bytes in network (big-endian) order. + + Args: + address: An integer representation of an IPv4 IP address. + + Returns: + The integer address packed as 4 bytes in network (big-endian) order. + + Raises: + ValueError: If the integer is negative or too large to be an + IPv4 IP address. + + """ + try: + return _compat_to_bytes(address, 4, 'big') + except (struct.error, OverflowError): + raise ValueError("Address negative or too large for IPv4") + + +def v6_int_to_packed(address): + """Represent an address as 16 packed bytes in network (big-endian) order. + + Args: + address: An integer representation of an IPv6 IP address. + + Returns: + The integer address packed as 16 bytes in network (big-endian) order. + + """ + try: + return _compat_to_bytes(address, 16, 'big') + except (struct.error, OverflowError): + raise ValueError("Address negative or too large for IPv6") + + +def _split_optional_netmask(address): + """Helper to split the netmask and raise AddressValueError if needed""" + addr = _compat_str(address).split('/') + if len(addr) > 2: + raise AddressValueError("Only one '/' permitted in %r" % address) + return addr + + +def _find_address_range(addresses): + """Find a sequence of sorted deduplicated IPv#Address. + + Args: + addresses: a list of IPv#Address objects. + + Yields: + A tuple containing the first and last IP addresses in the sequence. + + """ + it = iter(addresses) + first = last = next(it) + for ip in it: + if ip._ip != last._ip + 1: + yield first, last + first = ip + last = ip + yield first, last + + +def _count_righthand_zero_bits(number, bits): + """Count the number of zero bits on the right hand side. + + Args: + number: an integer. + bits: maximum number of bits to count. + + Returns: + The number of zero bits on the right hand side of the number. + + """ + if number == 0: + return bits + return min(bits, _compat_bit_length(~number & (number - 1))) + + +def summarize_address_range(first, last): + """Summarize a network range given the first and last IP addresses. + + Example: + >>> list(summarize_address_range(IPv4Address('192.0.2.0'), + ... IPv4Address('192.0.2.130'))) + ... #doctest: +NORMALIZE_WHITESPACE + [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'), + IPv4Network('192.0.2.130/32')] + + Args: + first: the first IPv4Address or IPv6Address in the range. + last: the last IPv4Address or IPv6Address in the range. + + Returns: + An iterator of the summarized IPv(4|6) network objects. + + Raise: + TypeError: + If the first and last objects are not IP addresses. + If the first and last objects are not the same version. + ValueError: + If the last object is not greater than the first. + If the version of the first address is not 4 or 6. + + """ + if (not (isinstance(first, _BaseAddress) and + isinstance(last, _BaseAddress))): + raise TypeError('first and last must be IP addresses, not networks') + if first.version != last.version: + raise TypeError("%s and %s are not of the same version" % ( + first, last)) + if first > last: + raise ValueError('last IP address must be greater than first') + + if first.version == 4: + ip = IPv4Network + elif first.version == 6: + ip = IPv6Network + else: + raise ValueError('unknown IP version') + + ip_bits = first._max_prefixlen + first_int = first._ip + last_int = last._ip + while first_int <= last_int: + nbits = min(_count_righthand_zero_bits(first_int, ip_bits), + _compat_bit_length(last_int - first_int + 1) - 1) + net = ip((first_int, ip_bits - nbits)) + yield net + first_int += 1 << nbits + if first_int - 1 == ip._ALL_ONES: + break + + +def _collapse_addresses_internal(addresses): + """Loops through the addresses, collapsing concurrent netblocks. + + Example: + + ip1 = IPv4Network('192.0.2.0/26') + ip2 = IPv4Network('192.0.2.64/26') + ip3 = IPv4Network('192.0.2.128/26') + ip4 = IPv4Network('192.0.2.192/26') + + _collapse_addresses_internal([ip1, ip2, ip3, ip4]) -> + [IPv4Network('192.0.2.0/24')] + + This shouldn't be called directly; it is called via + collapse_addresses([]). + + Args: + addresses: A list of IPv4Network's or IPv6Network's + + Returns: + A list of IPv4Network's or IPv6Network's depending on what we were + passed. + + """ + # First merge + to_merge = list(addresses) + subnets = {} + while to_merge: + net = to_merge.pop() + supernet = net.supernet() + existing = subnets.get(supernet) + if existing is None: + subnets[supernet] = net + elif existing != net: + # Merge consecutive subnets + del subnets[supernet] + to_merge.append(supernet) + # Then iterate over resulting networks, skipping subsumed subnets + last = None + for net in sorted(subnets.values()): + if last is not None: + # Since they are sorted, + # last.network_address <= net.network_address is a given. + if last.broadcast_address >= net.broadcast_address: + continue + yield net + last = net + + +def collapse_addresses(addresses): + """Collapse a list of IP objects. + + Example: + collapse_addresses([IPv4Network('192.0.2.0/25'), + IPv4Network('192.0.2.128/25')]) -> + [IPv4Network('192.0.2.0/24')] + + Args: + addresses: An iterator of IPv4Network or IPv6Network objects. + + Returns: + An iterator of the collapsed IPv(4|6)Network objects. + + Raises: + TypeError: If passed a list of mixed version objects. + + """ + addrs = [] + ips = [] + nets = [] + + # split IP addresses and networks + for ip in addresses: + if isinstance(ip, _BaseAddress): + if ips and ips[-1]._version != ip._version: + raise TypeError("%s and %s are not of the same version" % ( + ip, ips[-1])) + ips.append(ip) + elif ip._prefixlen == ip._max_prefixlen: + if ips and ips[-1]._version != ip._version: + raise TypeError("%s and %s are not of the same version" % ( + ip, ips[-1])) + try: + ips.append(ip.ip) + except AttributeError: + ips.append(ip.network_address) + else: + if nets and nets[-1]._version != ip._version: + raise TypeError("%s and %s are not of the same version" % ( + ip, nets[-1])) + nets.append(ip) + + # sort and dedup + ips = sorted(set(ips)) + + # find consecutive address ranges in the sorted sequence and summarize them + if ips: + for first, last in _find_address_range(ips): + addrs.extend(summarize_address_range(first, last)) + + return _collapse_addresses_internal(addrs + nets) + + +def get_mixed_type_key(obj): + """Return a key suitable for sorting between networks and addresses. + + Address and Network objects are not sortable by default; they're + fundamentally different so the expression + + IPv4Address('192.0.2.0') <= IPv4Network('192.0.2.0/24') + + doesn't make any sense. There are some times however, where you may wish + to have ipaddress sort these for you anyway. If you need to do this, you + can use this function as the key= argument to sorted(). + + Args: + obj: either a Network or Address object. + Returns: + appropriate key. + + """ + if isinstance(obj, _BaseNetwork): + return obj._get_networks_key() + elif isinstance(obj, _BaseAddress): + return obj._get_address_key() + return NotImplemented + + +class _IPAddressBase(_TotalOrderingMixin): + + """The mother class.""" + + __slots__ = () + + @property + def exploded(self): + """Return the longhand version of the IP address as a string.""" + return self._explode_shorthand_ip_string() + + @property + def compressed(self): + """Return the shorthand version of the IP address as a string.""" + return _compat_str(self) + + @property + def reverse_pointer(self): + """The name of the reverse DNS pointer for the IP address, e.g.: + >>> ipaddress.ip_address("127.0.0.1").reverse_pointer + '1.0.0.127.in-addr.arpa' + >>> ipaddress.ip_address("2001:db8::1").reverse_pointer + '1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa' + + """ + return self._reverse_pointer() + + @property + def version(self): + msg = '%200s has no version specified' % (type(self),) + raise NotImplementedError(msg) + + def _check_int_address(self, address): + if address < 0: + msg = "%d (< 0) is not permitted as an IPv%d address" + raise AddressValueError(msg % (address, self._version)) + if address > self._ALL_ONES: + msg = "%d (>= 2**%d) is not permitted as an IPv%d address" + raise AddressValueError(msg % (address, self._max_prefixlen, + self._version)) + + def _check_packed_address(self, address, expected_len): + address_len = len(address) + if address_len != expected_len: + msg = ( + '%r (len %d != %d) is not permitted as an IPv%d address. ' + 'Did you pass in a bytes (str in Python 2) instead of' + ' a unicode object?') + raise AddressValueError(msg % (address, address_len, + expected_len, self._version)) + + @classmethod + def _ip_int_from_prefix(cls, prefixlen): + """Turn the prefix length into a bitwise netmask + + Args: + prefixlen: An integer, the prefix length. + + Returns: + An integer. + + """ + return cls._ALL_ONES ^ (cls._ALL_ONES >> prefixlen) + + @classmethod + def _prefix_from_ip_int(cls, ip_int): + """Return prefix length from the bitwise netmask. + + Args: + ip_int: An integer, the netmask in expanded bitwise format + + Returns: + An integer, the prefix length. + + Raises: + ValueError: If the input intermingles zeroes & ones + """ + trailing_zeroes = _count_righthand_zero_bits(ip_int, + cls._max_prefixlen) + prefixlen = cls._max_prefixlen - trailing_zeroes + leading_ones = ip_int >> trailing_zeroes + all_ones = (1 << prefixlen) - 1 + if leading_ones != all_ones: + byteslen = cls._max_prefixlen // 8 + details = _compat_to_bytes(ip_int, byteslen, 'big') + msg = 'Netmask pattern %r mixes zeroes & ones' + raise ValueError(msg % details) + return prefixlen + + @classmethod + def _report_invalid_netmask(cls, netmask_str): + msg = '%r is not a valid netmask' % netmask_str + raise NetmaskValueError(msg) + + @classmethod + def _prefix_from_prefix_string(cls, prefixlen_str): + """Return prefix length from a numeric string + + Args: + prefixlen_str: The string to be converted + + Returns: + An integer, the prefix length. + + Raises: + NetmaskValueError: If the input is not a valid netmask + """ + # int allows a leading +/- as well as surrounding whitespace, + # so we ensure that isn't the case + if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): + cls._report_invalid_netmask(prefixlen_str) + try: + prefixlen = int(prefixlen_str) + except ValueError: + cls._report_invalid_netmask(prefixlen_str) + if not (0 <= prefixlen <= cls._max_prefixlen): + cls._report_invalid_netmask(prefixlen_str) + return prefixlen + + @classmethod + def _prefix_from_ip_string(cls, ip_str): + """Turn a netmask/hostmask string into a prefix length + + Args: + ip_str: The netmask/hostmask to be converted + + Returns: + An integer, the prefix length. + + Raises: + NetmaskValueError: If the input is not a valid netmask/hostmask + """ + # Parse the netmask/hostmask like an IP address. + try: + ip_int = cls._ip_int_from_string(ip_str) + except AddressValueError: + cls._report_invalid_netmask(ip_str) + + # Try matching a netmask (this would be /1*0*/ as a bitwise regexp). + # Note that the two ambiguous cases (all-ones and all-zeroes) are + # treated as netmasks. + try: + return cls._prefix_from_ip_int(ip_int) + except ValueError: + pass + + # Invert the bits, and try matching a /0+1+/ hostmask instead. + ip_int ^= cls._ALL_ONES + try: + return cls._prefix_from_ip_int(ip_int) + except ValueError: + cls._report_invalid_netmask(ip_str) + + def __reduce__(self): + return self.__class__, (_compat_str(self),) + + +class _BaseAddress(_IPAddressBase): + + """A generic IP object. + + This IP class contains the version independent methods which are + used by single IP addresses. + """ + + __slots__ = () + + def __int__(self): + return self._ip + + def __eq__(self, other): + try: + return (self._ip == other._ip and + self._version == other._version) + except AttributeError: + return NotImplemented + + def __lt__(self, other): + if not isinstance(other, _IPAddressBase): + return NotImplemented + if not isinstance(other, _BaseAddress): + raise TypeError('%s and %s are not of the same type' % ( + self, other)) + if self._version != other._version: + raise TypeError('%s and %s are not of the same version' % ( + self, other)) + if self._ip != other._ip: + return self._ip < other._ip + return False + + # Shorthand for Integer addition and subtraction. This is not + # meant to ever support addition/subtraction of addresses. + def __add__(self, other): + if not isinstance(other, _compat_int_types): + return NotImplemented + return self.__class__(int(self) + other) + + def __sub__(self, other): + if not isinstance(other, _compat_int_types): + return NotImplemented + return self.__class__(int(self) - other) + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, _compat_str(self)) + + def __str__(self): + return _compat_str(self._string_from_ip_int(self._ip)) + + def __hash__(self): + return hash(hex(int(self._ip))) + + def _get_address_key(self): + return (self._version, self) + + def __reduce__(self): + return self.__class__, (self._ip,) + + +class _BaseNetwork(_IPAddressBase): + + """A generic IP network object. + + This IP class contains the version independent methods which are + used by networks. + + """ + def __init__(self, address): + self._cache = {} + + def __repr__(self): + return '%s(%r)' % (self.__class__.__name__, _compat_str(self)) + + def __str__(self): + return '%s/%d' % (self.network_address, self.prefixlen) + + def hosts(self): + """Generate Iterator over usable hosts in a network. + + This is like __iter__ except it doesn't return the network + or broadcast addresses. + + """ + network = int(self.network_address) + broadcast = int(self.broadcast_address) + for x in _compat_range(network + 1, broadcast): + yield self._address_class(x) + + def __iter__(self): + network = int(self.network_address) + broadcast = int(self.broadcast_address) + for x in _compat_range(network, broadcast + 1): + yield self._address_class(x) + + def __getitem__(self, n): + network = int(self.network_address) + broadcast = int(self.broadcast_address) + if n >= 0: + if network + n > broadcast: + raise IndexError('address out of range') + return self._address_class(network + n) + else: + n += 1 + if broadcast + n < network: + raise IndexError('address out of range') + return self._address_class(broadcast + n) + + def __lt__(self, other): + if not isinstance(other, _IPAddressBase): + return NotImplemented + if not isinstance(other, _BaseNetwork): + raise TypeError('%s and %s are not of the same type' % ( + self, other)) + if self._version != other._version: + raise TypeError('%s and %s are not of the same version' % ( + self, other)) + if self.network_address != other.network_address: + return self.network_address < other.network_address + if self.netmask != other.netmask: + return self.netmask < other.netmask + return False + + def __eq__(self, other): + try: + return (self._version == other._version and + self.network_address == other.network_address and + int(self.netmask) == int(other.netmask)) + except AttributeError: + return NotImplemented + + def __hash__(self): + return hash(int(self.network_address) ^ int(self.netmask)) + + def __contains__(self, other): + # always false if one is v4 and the other is v6. + if self._version != other._version: + return False + # dealing with another network. + if isinstance(other, _BaseNetwork): + return False + # dealing with another address + else: + # address + return (int(self.network_address) <= int(other._ip) <= + int(self.broadcast_address)) + + def overlaps(self, other): + """Tell if self is partly contained in other.""" + return self.network_address in other or ( + self.broadcast_address in other or ( + other.network_address in self or ( + other.broadcast_address in self))) + + @property + def broadcast_address(self): + x = self._cache.get('broadcast_address') + if x is None: + x = self._address_class(int(self.network_address) | + int(self.hostmask)) + self._cache['broadcast_address'] = x + return x + + @property + def hostmask(self): + x = self._cache.get('hostmask') + if x is None: + x = self._address_class(int(self.netmask) ^ self._ALL_ONES) + self._cache['hostmask'] = x + return x + + @property + def with_prefixlen(self): + return '%s/%d' % (self.network_address, self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (self.network_address, self.netmask) + + @property + def with_hostmask(self): + return '%s/%s' % (self.network_address, self.hostmask) + + @property + def num_addresses(self): + """Number of hosts in the current subnet.""" + return int(self.broadcast_address) - int(self.network_address) + 1 + + @property + def _address_class(self): + # Returning bare address objects (rather than interfaces) allows for + # more consistent behaviour across the network address, broadcast + # address and individual host addresses. + msg = '%200s has no associated address class' % (type(self),) + raise NotImplementedError(msg) + + @property + def prefixlen(self): + return self._prefixlen + + def address_exclude(self, other): + """Remove an address from a larger block. + + For example: + + addr1 = ip_network('192.0.2.0/28') + addr2 = ip_network('192.0.2.1/32') + list(addr1.address_exclude(addr2)) = + [IPv4Network('192.0.2.0/32'), IPv4Network('192.0.2.2/31'), + IPv4Network('192.0.2.4/30'), IPv4Network('192.0.2.8/29')] + + or IPv6: + + addr1 = ip_network('2001:db8::1/32') + addr2 = ip_network('2001:db8::1/128') + list(addr1.address_exclude(addr2)) = + [ip_network('2001:db8::1/128'), + ip_network('2001:db8::2/127'), + ip_network('2001:db8::4/126'), + ip_network('2001:db8::8/125'), + ... + ip_network('2001:db8:8000::/33')] + + Args: + other: An IPv4Network or IPv6Network object of the same type. + + Returns: + An iterator of the IPv(4|6)Network objects which is self + minus other. + + Raises: + TypeError: If self and other are of differing address + versions, or if other is not a network object. + ValueError: If other is not completely contained by self. + + """ + if not self._version == other._version: + raise TypeError("%s and %s are not of the same version" % ( + self, other)) + + if not isinstance(other, _BaseNetwork): + raise TypeError("%s is not a network object" % other) + + if not other.subnet_of(self): + raise ValueError('%s not contained in %s' % (other, self)) + if other == self: + return + + # Make sure we're comparing the network of other. + other = other.__class__('%s/%s' % (other.network_address, + other.prefixlen)) + + s1, s2 = self.subnets() + while s1 != other and s2 != other: + if other.subnet_of(s1): + yield s2 + s1, s2 = s1.subnets() + elif other.subnet_of(s2): + yield s1 + s1, s2 = s2.subnets() + else: + # If we got here, there's a bug somewhere. + raise AssertionError('Error performing exclusion: ' + 's1: %s s2: %s other: %s' % + (s1, s2, other)) + if s1 == other: + yield s2 + elif s2 == other: + yield s1 + else: + # If we got here, there's a bug somewhere. + raise AssertionError('Error performing exclusion: ' + 's1: %s s2: %s other: %s' % + (s1, s2, other)) + + def compare_networks(self, other): + """Compare two IP objects. + + This is only concerned about the comparison of the integer + representation of the network addresses. This means that the + host bits aren't considered at all in this method. If you want + to compare host bits, you can easily enough do a + 'HostA._ip < HostB._ip' + + Args: + other: An IP object. + + Returns: + If the IP versions of self and other are the same, returns: + + -1 if self < other: + eg: IPv4Network('192.0.2.0/25') < IPv4Network('192.0.2.128/25') + IPv6Network('2001:db8::1000/124') < + IPv6Network('2001:db8::2000/124') + 0 if self == other + eg: IPv4Network('192.0.2.0/24') == IPv4Network('192.0.2.0/24') + IPv6Network('2001:db8::1000/124') == + IPv6Network('2001:db8::1000/124') + 1 if self > other + eg: IPv4Network('192.0.2.128/25') > IPv4Network('192.0.2.0/25') + IPv6Network('2001:db8::2000/124') > + IPv6Network('2001:db8::1000/124') + + Raises: + TypeError if the IP versions are different. + + """ + # does this need to raise a ValueError? + if self._version != other._version: + raise TypeError('%s and %s are not of the same type' % ( + self, other)) + # self._version == other._version below here: + if self.network_address < other.network_address: + return -1 + if self.network_address > other.network_address: + return 1 + # self.network_address == other.network_address below here: + if self.netmask < other.netmask: + return -1 + if self.netmask > other.netmask: + return 1 + return 0 + + def _get_networks_key(self): + """Network-only key function. + + Returns an object that identifies this address' network and + netmask. This function is a suitable "key" argument for sorted() + and list.sort(). + + """ + return (self._version, self.network_address, self.netmask) + + def subnets(self, prefixlen_diff=1, new_prefix=None): + """The subnets which join to make the current subnet. + + In the case that self contains only one IP + (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 + for IPv6), yield an iterator with just ourself. + + Args: + prefixlen_diff: An integer, the amount the prefix length + should be increased by. This should not be set if + new_prefix is also set. + new_prefix: The desired new prefix length. This must be a + larger number (smaller prefix) than the existing prefix. + This should not be set if prefixlen_diff is also set. + + Returns: + An iterator of IPv(4|6) objects. + + Raises: + ValueError: The prefixlen_diff is too small or too large. + OR + prefixlen_diff and new_prefix are both set or new_prefix + is a smaller number than the current prefix (smaller + number means a larger network) + + """ + if self._prefixlen == self._max_prefixlen: + yield self + return + + if new_prefix is not None: + if new_prefix < self._prefixlen: + raise ValueError('new prefix must be longer') + if prefixlen_diff != 1: + raise ValueError('cannot set prefixlen_diff and new_prefix') + prefixlen_diff = new_prefix - self._prefixlen + + if prefixlen_diff < 0: + raise ValueError('prefix length diff must be > 0') + new_prefixlen = self._prefixlen + prefixlen_diff + + if new_prefixlen > self._max_prefixlen: + raise ValueError( + 'prefix length diff %d is invalid for netblock %s' % ( + new_prefixlen, self)) + + start = int(self.network_address) + end = int(self.broadcast_address) + 1 + step = (int(self.hostmask) + 1) >> prefixlen_diff + for new_addr in _compat_range(start, end, step): + current = self.__class__((new_addr, new_prefixlen)) + yield current + + def supernet(self, prefixlen_diff=1, new_prefix=None): + """The supernet containing the current network. + + Args: + prefixlen_diff: An integer, the amount the prefix length of + the network should be decreased by. For example, given a + /24 network and a prefixlen_diff of 3, a supernet with a + /21 netmask is returned. + + Returns: + An IPv4 network object. + + Raises: + ValueError: If self.prefixlen - prefixlen_diff < 0. I.e., you have + a negative prefix length. + OR + If prefixlen_diff and new_prefix are both set or new_prefix is a + larger number than the current prefix (larger number means a + smaller network) + + """ + if self._prefixlen == 0: + return self + + if new_prefix is not None: + if new_prefix > self._prefixlen: + raise ValueError('new prefix must be shorter') + if prefixlen_diff != 1: + raise ValueError('cannot set prefixlen_diff and new_prefix') + prefixlen_diff = self._prefixlen - new_prefix + + new_prefixlen = self.prefixlen - prefixlen_diff + if new_prefixlen < 0: + raise ValueError( + 'current prefixlen is %d, cannot have a prefixlen_diff of %d' % + (self.prefixlen, prefixlen_diff)) + return self.__class__(( + int(self.network_address) & (int(self.netmask) << prefixlen_diff), + new_prefixlen)) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is a multicast address. + See RFC 2373 2.7 for details. + + """ + return (self.network_address.is_multicast and + self.broadcast_address.is_multicast) + + @staticmethod + def _is_subnet_of(a, b): + try: + # Always false if one is v4 and the other is v6. + if a._version != b._version: + raise TypeError("%s and %s are not of the same version" (a, b)) + return (b.network_address <= a.network_address and + b.broadcast_address >= a.broadcast_address) + except AttributeError: + raise TypeError("Unable to test subnet containment " + "between %s and %s" % (a, b)) + + def subnet_of(self, other): + """Return True if this network is a subnet of other.""" + return self._is_subnet_of(self, other) + + def supernet_of(self, other): + """Return True if this network is a supernet of other.""" + return self._is_subnet_of(other, self) + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within one of the + reserved IPv6 Network ranges. + + """ + return (self.network_address.is_reserved and + self.broadcast_address.is_reserved) + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is reserved per RFC 4291. + + """ + return (self.network_address.is_link_local and + self.broadcast_address.is_link_local) + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per + iana-ipv4-special-registry or iana-ipv6-special-registry. + + """ + return (self.network_address.is_private and + self.broadcast_address.is_private) + + @property + def is_global(self): + """Test if this address is allocated for public networks. + + Returns: + A boolean, True if the address is not reserved per + iana-ipv4-special-registry or iana-ipv6-special-registry. + + """ + return not self.is_private + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 2373 2.5.2. + + """ + return (self.network_address.is_unspecified and + self.broadcast_address.is_unspecified) + + @property + def is_loopback(self): + """Test if the address is a loopback address. + + Returns: + A boolean, True if the address is a loopback address as defined in + RFC 2373 2.5.3. + + """ + return (self.network_address.is_loopback and + self.broadcast_address.is_loopback) + + +class _BaseV4(object): + + """Base IPv4 object. + + The following methods are used by IPv4 objects in both single IP + addresses and networks. + + """ + + __slots__ = () + _version = 4 + # Equivalent to 255.255.255.255 or 32 bits of 1's. + _ALL_ONES = (2 ** IPV4LENGTH) - 1 + _DECIMAL_DIGITS = frozenset('0123456789') + + # the valid octets for host and netmasks. only useful for IPv4. + _valid_mask_octets = frozenset([255, 254, 252, 248, 240, 224, 192, 128, 0]) + + _max_prefixlen = IPV4LENGTH + # There are only a handful of valid v4 netmasks, so we cache them all + # when constructed (see _make_netmask()). + _netmask_cache = {} + + def _explode_shorthand_ip_string(self): + return _compat_str(self) + + @classmethod + def _make_netmask(cls, arg): + """Make a (netmask, prefix_len) tuple from the given argument. + + Argument can be: + - an integer (the prefix length) + - a string representing the prefix length (e.g. "24") + - a string representing the prefix netmask (e.g. "255.255.255.0") + """ + if arg not in cls._netmask_cache: + if isinstance(arg, _compat_int_types): + prefixlen = arg + else: + try: + # Check for a netmask in prefix length form + prefixlen = cls._prefix_from_prefix_string(arg) + except NetmaskValueError: + # Check for a netmask or hostmask in dotted-quad form. + # This may raise NetmaskValueError. + prefixlen = cls._prefix_from_ip_string(arg) + netmask = IPv4Address(cls._ip_int_from_prefix(prefixlen)) + cls._netmask_cache[arg] = netmask, prefixlen + return cls._netmask_cache[arg] + + @classmethod + def _ip_int_from_string(cls, ip_str): + """Turn the given IP string into an integer for comparison. + + Args: + ip_str: A string, the IP ip_str. + + Returns: + The IP ip_str as an integer. + + Raises: + AddressValueError: if ip_str isn't a valid IPv4 Address. + + """ + if not ip_str: + raise AddressValueError('Address cannot be empty') + + octets = ip_str.split('.') + if len(octets) != 4: + raise AddressValueError("Expected 4 octets in %r" % ip_str) + + try: + return _compat_int_from_byte_vals( + map(cls._parse_octet, octets), 'big') + except ValueError as exc: + raise AddressValueError("%s in %r" % (exc, ip_str)) + + @classmethod + def _parse_octet(cls, octet_str): + """Convert a decimal octet into an integer. + + Args: + octet_str: A string, the number to parse. + + Returns: + The octet as an integer. + + Raises: + ValueError: if the octet isn't strictly a decimal from [0..255]. + + """ + if not octet_str: + raise ValueError("Empty octet not permitted") + # Whitelist the characters, since int() allows a lot of bizarre stuff. + if not cls._DECIMAL_DIGITS.issuperset(octet_str): + msg = "Only decimal digits permitted in %r" + raise ValueError(msg % octet_str) + # We do the length check second, since the invalid character error + # is likely to be more informative for the user + if len(octet_str) > 3: + msg = "At most 3 characters permitted in %r" + raise ValueError(msg % octet_str) + # Convert to integer (we know digits are legal) + octet_int = int(octet_str, 10) + # Any octets that look like they *might* be written in octal, + # and which don't look exactly the same in both octal and + # decimal are rejected as ambiguous + if octet_int > 7 and octet_str[0] == '0': + msg = "Ambiguous (octal/decimal) value in %r not permitted" + raise ValueError(msg % octet_str) + if octet_int > 255: + raise ValueError("Octet %d (> 255) not permitted" % octet_int) + return octet_int + + @classmethod + def _string_from_ip_int(cls, ip_int): + """Turns a 32-bit integer into dotted decimal notation. + + Args: + ip_int: An integer, the IP address. + + Returns: + The IP address as a string in dotted decimal notation. + + """ + return '.'.join(_compat_str(struct.unpack(b'!B', b)[0] + if isinstance(b, bytes) + else b) + for b in _compat_to_bytes(ip_int, 4, 'big')) + + def _is_hostmask(self, ip_str): + """Test if the IP string is a hostmask (rather than a netmask). + + Args: + ip_str: A string, the potential hostmask. + + Returns: + A boolean, True if the IP string is a hostmask. + + """ + bits = ip_str.split('.') + try: + parts = [x for x in map(int, bits) if x in self._valid_mask_octets] + except ValueError: + return False + if len(parts) != len(bits): + return False + if parts[0] < parts[-1]: + return True + return False + + def _reverse_pointer(self): + """Return the reverse DNS pointer name for the IPv4 address. + + This implements the method described in RFC1035 3.5. + + """ + reverse_octets = _compat_str(self).split('.')[::-1] + return '.'.join(reverse_octets) + '.in-addr.arpa' + + @property + def max_prefixlen(self): + return self._max_prefixlen + + @property + def version(self): + return self._version + + +class IPv4Address(_BaseV4, _BaseAddress): + + """Represent and manipulate single IPv4 Addresses.""" + + __slots__ = ('_ip', '__weakref__') + + def __init__(self, address): + + """ + Args: + address: A string or integer representing the IP + + Additionally, an integer can be passed, so + IPv4Address('192.0.2.1') == IPv4Address(3221225985). + or, more generally + IPv4Address(int(IPv4Address('192.0.2.1'))) == + IPv4Address('192.0.2.1') + + Raises: + AddressValueError: If ipaddress isn't a valid IPv4 address. + + """ + # Efficient constructor from integer. + if isinstance(address, _compat_int_types): + self._check_int_address(address) + self._ip = address + return + + # Constructing from a packed address + if isinstance(address, bytes): + self._check_packed_address(address, 4) + bvs = _compat_bytes_to_byte_vals(address) + self._ip = _compat_int_from_byte_vals(bvs, 'big') + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP string. + addr_str = _compat_str(address) + if '/' in addr_str: + raise AddressValueError("Unexpected '/' in %r" % address) + self._ip = self._ip_int_from_string(addr_str) + + @property + def packed(self): + """The binary representation of this address.""" + return v4_int_to_packed(self._ip) + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within the + reserved IPv4 Network range. + + """ + return self in self._constants._reserved_network + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per + iana-ipv4-special-registry. + + """ + return any(self in net for net in self._constants._private_networks) + + @property + def is_global(self): + return ( + self not in self._constants._public_network and + not self.is_private) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is multicast. + See RFC 3171 for details. + + """ + return self in self._constants._multicast_network + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 5735 3. + + """ + return self == self._constants._unspecified_address + + @property + def is_loopback(self): + """Test if the address is a loopback address. + + Returns: + A boolean, True if the address is a loopback per RFC 3330. + + """ + return self in self._constants._loopback_network + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is link-local per RFC 3927. + + """ + return self in self._constants._linklocal_network + + +class IPv4Interface(IPv4Address): + + def __init__(self, address): + if isinstance(address, (bytes, _compat_int_types)): + IPv4Address.__init__(self, address) + self.network = IPv4Network(self._ip) + self._prefixlen = self._max_prefixlen + return + + if isinstance(address, tuple): + IPv4Address.__init__(self, address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + + self.network = IPv4Network(address, strict=False) + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + return + + addr = _split_optional_netmask(address) + IPv4Address.__init__(self, addr[0]) + + self.network = IPv4Network(address, strict=False) + self._prefixlen = self.network._prefixlen + + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + + def __str__(self): + return '%s/%d' % (self._string_from_ip_int(self._ip), + self.network.prefixlen) + + def __eq__(self, other): + address_equal = IPv4Address.__eq__(self, other) + if not address_equal or address_equal is NotImplemented: + return address_equal + try: + return self.network == other.network + except AttributeError: + # An interface with an associated network is NOT the + # same as an unassociated address. That's why the hash + # takes the extra info into account. + return False + + def __lt__(self, other): + address_less = IPv4Address.__lt__(self, other) + if address_less is NotImplemented: + return NotImplemented + try: + return (self.network < other.network or + self.network == other.network and address_less) + except AttributeError: + # We *do* allow addresses and interfaces to be sorted. The + # unassociated address is considered less than all interfaces. + return False + + def __hash__(self): + return self._ip ^ self._prefixlen ^ int(self.network.network_address) + + __reduce__ = _IPAddressBase.__reduce__ + + @property + def ip(self): + return IPv4Address(self._ip) + + @property + def with_prefixlen(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.netmask) + + @property + def with_hostmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.hostmask) + + +class IPv4Network(_BaseV4, _BaseNetwork): + + """This class represents and manipulates 32-bit IPv4 network + addresses.. + + Attributes: [examples for IPv4Network('192.0.2.0/27')] + .network_address: IPv4Address('192.0.2.0') + .hostmask: IPv4Address('0.0.0.31') + .broadcast_address: IPv4Address('192.0.2.32') + .netmask: IPv4Address('255.255.255.224') + .prefixlen: 27 + + """ + # Class to use when creating address objects + _address_class = IPv4Address + + def __init__(self, address, strict=True): + + """Instantiate a new IPv4 network object. + + Args: + address: A string or integer representing the IP [& network]. + '192.0.2.0/24' + '192.0.2.0/255.255.255.0' + '192.0.0.2/0.0.0.255' + are all functionally the same in IPv4. Similarly, + '192.0.2.1' + '192.0.2.1/255.255.255.255' + '192.0.2.1/32' + are also functionally equivalent. That is to say, failing to + provide a subnetmask will create an object with a mask of /32. + + If the mask (portion after the / in the argument) is given in + dotted quad form, it is treated as a netmask if it starts with a + non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it + starts with a zero field (e.g. 0.255.255.255 == /8), with the + single exception of an all-zero mask which is treated as a + netmask == /0. If no mask is given, a default of /32 is used. + + Additionally, an integer can be passed, so + IPv4Network('192.0.2.1') == IPv4Network(3221225985) + or, more generally + IPv4Interface(int(IPv4Interface('192.0.2.1'))) == + IPv4Interface('192.0.2.1') + + Raises: + AddressValueError: If ipaddress isn't a valid IPv4 address. + NetmaskValueError: If the netmask isn't valid for + an IPv4 address. + ValueError: If strict is True and a network address is not + supplied. + + """ + _BaseNetwork.__init__(self, address) + + # Constructing from a packed address or integer + if isinstance(address, (_compat_int_types, bytes)): + self.network_address = IPv4Address(address) + self.netmask, self._prefixlen = self._make_netmask( + self._max_prefixlen) + # fixme: address/network test here. + return + + if isinstance(address, tuple): + if len(address) > 1: + arg = address[1] + else: + # We weren't given an address[1] + arg = self._max_prefixlen + self.network_address = IPv4Address(address[0]) + self.netmask, self._prefixlen = self._make_netmask(arg) + packed = int(self.network_address) + if packed & int(self.netmask) != packed: + if strict: + raise ValueError('%s has host bits set' % self) + else: + self.network_address = IPv4Address(packed & + int(self.netmask)) + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + addr = _split_optional_netmask(address) + self.network_address = IPv4Address(self._ip_int_from_string(addr[0])) + + if len(addr) == 2: + arg = addr[1] + else: + arg = self._max_prefixlen + self.netmask, self._prefixlen = self._make_netmask(arg) + + if strict: + if (IPv4Address(int(self.network_address) & int(self.netmask)) != + self.network_address): + raise ValueError('%s has host bits set' % self) + self.network_address = IPv4Address(int(self.network_address) & + int(self.netmask)) + + if self._prefixlen == (self._max_prefixlen - 1): + self.hosts = self.__iter__ + + @property + def is_global(self): + """Test if this address is allocated for public networks. + + Returns: + A boolean, True if the address is not reserved per + iana-ipv4-special-registry. + + """ + return (not (self.network_address in IPv4Network('100.64.0.0/10') and + self.broadcast_address in IPv4Network('100.64.0.0/10')) and + not self.is_private) + + +class _IPv4Constants(object): + + _linklocal_network = IPv4Network('169.254.0.0/16') + + _loopback_network = IPv4Network('127.0.0.0/8') + + _multicast_network = IPv4Network('224.0.0.0/4') + + _public_network = IPv4Network('100.64.0.0/10') + + _private_networks = [ + IPv4Network('0.0.0.0/8'), + IPv4Network('10.0.0.0/8'), + IPv4Network('127.0.0.0/8'), + IPv4Network('169.254.0.0/16'), + IPv4Network('172.16.0.0/12'), + IPv4Network('192.0.0.0/29'), + IPv4Network('192.0.0.170/31'), + IPv4Network('192.0.2.0/24'), + IPv4Network('192.168.0.0/16'), + IPv4Network('198.18.0.0/15'), + IPv4Network('198.51.100.0/24'), + IPv4Network('203.0.113.0/24'), + IPv4Network('240.0.0.0/4'), + IPv4Network('255.255.255.255/32'), + ] + + _reserved_network = IPv4Network('240.0.0.0/4') + + _unspecified_address = IPv4Address('0.0.0.0') + + +IPv4Address._constants = _IPv4Constants + + +class _BaseV6(object): + + """Base IPv6 object. + + The following methods are used by IPv6 objects in both single IP + addresses and networks. + + """ + + __slots__ = () + _version = 6 + _ALL_ONES = (2 ** IPV6LENGTH) - 1 + _HEXTET_COUNT = 8 + _HEX_DIGITS = frozenset('0123456789ABCDEFabcdef') + _max_prefixlen = IPV6LENGTH + + # There are only a bunch of valid v6 netmasks, so we cache them all + # when constructed (see _make_netmask()). + _netmask_cache = {} + + @classmethod + def _make_netmask(cls, arg): + """Make a (netmask, prefix_len) tuple from the given argument. + + Argument can be: + - an integer (the prefix length) + - a string representing the prefix length (e.g. "24") + - a string representing the prefix netmask (e.g. "255.255.255.0") + """ + if arg not in cls._netmask_cache: + if isinstance(arg, _compat_int_types): + prefixlen = arg + else: + prefixlen = cls._prefix_from_prefix_string(arg) + netmask = IPv6Address(cls._ip_int_from_prefix(prefixlen)) + cls._netmask_cache[arg] = netmask, prefixlen + return cls._netmask_cache[arg] + + @classmethod + def _ip_int_from_string(cls, ip_str): + """Turn an IPv6 ip_str into an integer. + + Args: + ip_str: A string, the IPv6 ip_str. + + Returns: + An int, the IPv6 address + + Raises: + AddressValueError: if ip_str isn't a valid IPv6 Address. + + """ + if not ip_str: + raise AddressValueError('Address cannot be empty') + + parts = ip_str.split(':') + + # An IPv6 address needs at least 2 colons (3 parts). + _min_parts = 3 + if len(parts) < _min_parts: + msg = "At least %d parts expected in %r" % (_min_parts, ip_str) + raise AddressValueError(msg) + + # If the address has an IPv4-style suffix, convert it to hexadecimal. + if '.' in parts[-1]: + try: + ipv4_int = IPv4Address(parts.pop())._ip + except AddressValueError as exc: + raise AddressValueError("%s in %r" % (exc, ip_str)) + parts.append('%x' % ((ipv4_int >> 16) & 0xFFFF)) + parts.append('%x' % (ipv4_int & 0xFFFF)) + + # An IPv6 address can't have more than 8 colons (9 parts). + # The extra colon comes from using the "::" notation for a single + # leading or trailing zero part. + _max_parts = cls._HEXTET_COUNT + 1 + if len(parts) > _max_parts: + msg = "At most %d colons permitted in %r" % ( + _max_parts - 1, ip_str) + raise AddressValueError(msg) + + # Disregarding the endpoints, find '::' with nothing in between. + # This indicates that a run of zeroes has been skipped. + skip_index = None + for i in _compat_range(1, len(parts) - 1): + if not parts[i]: + if skip_index is not None: + # Can't have more than one '::' + msg = "At most one '::' permitted in %r" % ip_str + raise AddressValueError(msg) + skip_index = i + + # parts_hi is the number of parts to copy from above/before the '::' + # parts_lo is the number of parts to copy from below/after the '::' + if skip_index is not None: + # If we found a '::', then check if it also covers the endpoints. + parts_hi = skip_index + parts_lo = len(parts) - skip_index - 1 + if not parts[0]: + parts_hi -= 1 + if parts_hi: + msg = "Leading ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # ^: requires ^:: + if not parts[-1]: + parts_lo -= 1 + if parts_lo: + msg = "Trailing ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # :$ requires ::$ + parts_skipped = cls._HEXTET_COUNT - (parts_hi + parts_lo) + if parts_skipped < 1: + msg = "Expected at most %d other parts with '::' in %r" + raise AddressValueError(msg % (cls._HEXTET_COUNT - 1, ip_str)) + else: + # Otherwise, allocate the entire address to parts_hi. The + # endpoints could still be empty, but _parse_hextet() will check + # for that. + if len(parts) != cls._HEXTET_COUNT: + msg = "Exactly %d parts expected without '::' in %r" + raise AddressValueError(msg % (cls._HEXTET_COUNT, ip_str)) + if not parts[0]: + msg = "Leading ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # ^: requires ^:: + if not parts[-1]: + msg = "Trailing ':' only permitted as part of '::' in %r" + raise AddressValueError(msg % ip_str) # :$ requires ::$ + parts_hi = len(parts) + parts_lo = 0 + parts_skipped = 0 + + try: + # Now, parse the hextets into a 128-bit integer. + ip_int = 0 + for i in range(parts_hi): + ip_int <<= 16 + ip_int |= cls._parse_hextet(parts[i]) + ip_int <<= 16 * parts_skipped + for i in range(-parts_lo, 0): + ip_int <<= 16 + ip_int |= cls._parse_hextet(parts[i]) + return ip_int + except ValueError as exc: + raise AddressValueError("%s in %r" % (exc, ip_str)) + + @classmethod + def _parse_hextet(cls, hextet_str): + """Convert an IPv6 hextet string into an integer. + + Args: + hextet_str: A string, the number to parse. + + Returns: + The hextet as an integer. + + Raises: + ValueError: if the input isn't strictly a hex number from + [0..FFFF]. + + """ + # Whitelist the characters, since int() allows a lot of bizarre stuff. + if not cls._HEX_DIGITS.issuperset(hextet_str): + raise ValueError("Only hex digits permitted in %r" % hextet_str) + # We do the length check second, since the invalid character error + # is likely to be more informative for the user + if len(hextet_str) > 4: + msg = "At most 4 characters permitted in %r" + raise ValueError(msg % hextet_str) + # Length check means we can skip checking the integer value + return int(hextet_str, 16) + + @classmethod + def _compress_hextets(cls, hextets): + """Compresses a list of hextets. + + Compresses a list of strings, replacing the longest continuous + sequence of "0" in the list with "" and adding empty strings at + the beginning or at the end of the string such that subsequently + calling ":".join(hextets) will produce the compressed version of + the IPv6 address. + + Args: + hextets: A list of strings, the hextets to compress. + + Returns: + A list of strings. + + """ + best_doublecolon_start = -1 + best_doublecolon_len = 0 + doublecolon_start = -1 + doublecolon_len = 0 + for index, hextet in enumerate(hextets): + if hextet == '0': + doublecolon_len += 1 + if doublecolon_start == -1: + # Start of a sequence of zeros. + doublecolon_start = index + if doublecolon_len > best_doublecolon_len: + # This is the longest sequence of zeros so far. + best_doublecolon_len = doublecolon_len + best_doublecolon_start = doublecolon_start + else: + doublecolon_len = 0 + doublecolon_start = -1 + + if best_doublecolon_len > 1: + best_doublecolon_end = (best_doublecolon_start + + best_doublecolon_len) + # For zeros at the end of the address. + if best_doublecolon_end == len(hextets): + hextets += [''] + hextets[best_doublecolon_start:best_doublecolon_end] = [''] + # For zeros at the beginning of the address. + if best_doublecolon_start == 0: + hextets = [''] + hextets + + return hextets + + @classmethod + def _string_from_ip_int(cls, ip_int=None): + """Turns a 128-bit integer into hexadecimal notation. + + Args: + ip_int: An integer, the IP address. + + Returns: + A string, the hexadecimal representation of the address. + + Raises: + ValueError: The address is bigger than 128 bits of all ones. + + """ + if ip_int is None: + ip_int = int(cls._ip) + + if ip_int > cls._ALL_ONES: + raise ValueError('IPv6 address is too large') + + hex_str = '%032x' % ip_int + hextets = ['%x' % int(hex_str[x:x + 4], 16) for x in range(0, 32, 4)] + + hextets = cls._compress_hextets(hextets) + return ':'.join(hextets) + + def _explode_shorthand_ip_string(self): + """Expand a shortened IPv6 address. + + Args: + ip_str: A string, the IPv6 address. + + Returns: + A string, the expanded IPv6 address. + + """ + if isinstance(self, IPv6Network): + ip_str = _compat_str(self.network_address) + elif isinstance(self, IPv6Interface): + ip_str = _compat_str(self.ip) + else: + ip_str = _compat_str(self) + + ip_int = self._ip_int_from_string(ip_str) + hex_str = '%032x' % ip_int + parts = [hex_str[x:x + 4] for x in range(0, 32, 4)] + if isinstance(self, (_BaseNetwork, IPv6Interface)): + return '%s/%d' % (':'.join(parts), self._prefixlen) + return ':'.join(parts) + + def _reverse_pointer(self): + """Return the reverse DNS pointer name for the IPv6 address. + + This implements the method described in RFC3596 2.5. + + """ + reverse_chars = self.exploded[::-1].replace(':', '') + return '.'.join(reverse_chars) + '.ip6.arpa' + + @property + def max_prefixlen(self): + return self._max_prefixlen + + @property + def version(self): + return self._version + + +class IPv6Address(_BaseV6, _BaseAddress): + + """Represent and manipulate single IPv6 Addresses.""" + + __slots__ = ('_ip', '__weakref__') + + def __init__(self, address): + """Instantiate a new IPv6 address object. + + Args: + address: A string or integer representing the IP + + Additionally, an integer can be passed, so + IPv6Address('2001:db8::') == + IPv6Address(42540766411282592856903984951653826560) + or, more generally + IPv6Address(int(IPv6Address('2001:db8::'))) == + IPv6Address('2001:db8::') + + Raises: + AddressValueError: If address isn't a valid IPv6 address. + + """ + # Efficient constructor from integer. + if isinstance(address, _compat_int_types): + self._check_int_address(address) + self._ip = address + return + + # Constructing from a packed address + if isinstance(address, bytes): + self._check_packed_address(address, 16) + bvs = _compat_bytes_to_byte_vals(address) + self._ip = _compat_int_from_byte_vals(bvs, 'big') + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP string. + addr_str = _compat_str(address) + if '/' in addr_str: + raise AddressValueError("Unexpected '/' in %r" % address) + self._ip = self._ip_int_from_string(addr_str) + + @property + def packed(self): + """The binary representation of this address.""" + return v6_int_to_packed(self._ip) + + @property + def is_multicast(self): + """Test if the address is reserved for multicast use. + + Returns: + A boolean, True if the address is a multicast address. + See RFC 2373 2.7 for details. + + """ + return self in self._constants._multicast_network + + @property + def is_reserved(self): + """Test if the address is otherwise IETF reserved. + + Returns: + A boolean, True if the address is within one of the + reserved IPv6 Network ranges. + + """ + return any(self in x for x in self._constants._reserved_networks) + + @property + def is_link_local(self): + """Test if the address is reserved for link-local. + + Returns: + A boolean, True if the address is reserved per RFC 4291. + + """ + return self in self._constants._linklocal_network + + @property + def is_site_local(self): + """Test if the address is reserved for site-local. + + Note that the site-local address space has been deprecated by RFC 3879. + Use is_private to test if this address is in the space of unique local + addresses as defined by RFC 4193. + + Returns: + A boolean, True if the address is reserved per RFC 3513 2.5.6. + + """ + return self in self._constants._sitelocal_network + + @property + def is_private(self): + """Test if this address is allocated for private networks. + + Returns: + A boolean, True if the address is reserved per + iana-ipv6-special-registry. + + """ + return any(self in net for net in self._constants._private_networks) + + @property + def is_global(self): + """Test if this address is allocated for public networks. + + Returns: + A boolean, true if the address is not reserved per + iana-ipv6-special-registry. + + """ + return not self.is_private + + @property + def is_unspecified(self): + """Test if the address is unspecified. + + Returns: + A boolean, True if this is the unspecified address as defined in + RFC 2373 2.5.2. + + """ + return self._ip == 0 + + @property + def is_loopback(self): + """Test if the address is a loopback address. + + Returns: + A boolean, True if the address is a loopback address as defined in + RFC 2373 2.5.3. + + """ + return self._ip == 1 + + @property + def ipv4_mapped(self): + """Return the IPv4 mapped address. + + Returns: + If the IPv6 address is a v4 mapped address, return the + IPv4 mapped address. Return None otherwise. + + """ + if (self._ip >> 32) != 0xFFFF: + return None + return IPv4Address(self._ip & 0xFFFFFFFF) + + @property + def teredo(self): + """Tuple of embedded teredo IPs. + + Returns: + Tuple of the (server, client) IPs or None if the address + doesn't appear to be a teredo address (doesn't start with + 2001::/32) + + """ + if (self._ip >> 96) != 0x20010000: + return None + return (IPv4Address((self._ip >> 64) & 0xFFFFFFFF), + IPv4Address(~self._ip & 0xFFFFFFFF)) + + @property + def sixtofour(self): + """Return the IPv4 6to4 embedded address. + + Returns: + The IPv4 6to4-embedded address if present or None if the + address doesn't appear to contain a 6to4 embedded address. + + """ + if (self._ip >> 112) != 0x2002: + return None + return IPv4Address((self._ip >> 80) & 0xFFFFFFFF) + + +class IPv6Interface(IPv6Address): + + def __init__(self, address): + if isinstance(address, (bytes, _compat_int_types)): + IPv6Address.__init__(self, address) + self.network = IPv6Network(self._ip) + self._prefixlen = self._max_prefixlen + return + if isinstance(address, tuple): + IPv6Address.__init__(self, address[0]) + if len(address) > 1: + self._prefixlen = int(address[1]) + else: + self._prefixlen = self._max_prefixlen + self.network = IPv6Network(address, strict=False) + self.netmask = self.network.netmask + self.hostmask = self.network.hostmask + return + + addr = _split_optional_netmask(address) + IPv6Address.__init__(self, addr[0]) + self.network = IPv6Network(address, strict=False) + self.netmask = self.network.netmask + self._prefixlen = self.network._prefixlen + self.hostmask = self.network.hostmask + + def __str__(self): + return '%s/%d' % (self._string_from_ip_int(self._ip), + self.network.prefixlen) + + def __eq__(self, other): + address_equal = IPv6Address.__eq__(self, other) + if not address_equal or address_equal is NotImplemented: + return address_equal + try: + return self.network == other.network + except AttributeError: + # An interface with an associated network is NOT the + # same as an unassociated address. That's why the hash + # takes the extra info into account. + return False + + def __lt__(self, other): + address_less = IPv6Address.__lt__(self, other) + if address_less is NotImplemented: + return NotImplemented + try: + return (self.network < other.network or + self.network == other.network and address_less) + except AttributeError: + # We *do* allow addresses and interfaces to be sorted. The + # unassociated address is considered less than all interfaces. + return False + + def __hash__(self): + return self._ip ^ self._prefixlen ^ int(self.network.network_address) + + __reduce__ = _IPAddressBase.__reduce__ + + @property + def ip(self): + return IPv6Address(self._ip) + + @property + def with_prefixlen(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self._prefixlen) + + @property + def with_netmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.netmask) + + @property + def with_hostmask(self): + return '%s/%s' % (self._string_from_ip_int(self._ip), + self.hostmask) + + @property + def is_unspecified(self): + return self._ip == 0 and self.network.is_unspecified + + @property + def is_loopback(self): + return self._ip == 1 and self.network.is_loopback + + +class IPv6Network(_BaseV6, _BaseNetwork): + + """This class represents and manipulates 128-bit IPv6 networks. + + Attributes: [examples for IPv6('2001:db8::1000/124')] + .network_address: IPv6Address('2001:db8::1000') + .hostmask: IPv6Address('::f') + .broadcast_address: IPv6Address('2001:db8::100f') + .netmask: IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0') + .prefixlen: 124 + + """ + + # Class to use when creating address objects + _address_class = IPv6Address + + def __init__(self, address, strict=True): + """Instantiate a new IPv6 Network object. + + Args: + address: A string or integer representing the IPv6 network or the + IP and prefix/netmask. + '2001:db8::/128' + '2001:db8:0000:0000:0000:0000:0000:0000/128' + '2001:db8::' + are all functionally the same in IPv6. That is to say, + failing to provide a subnetmask will create an object with + a mask of /128. + + Additionally, an integer can be passed, so + IPv6Network('2001:db8::') == + IPv6Network(42540766411282592856903984951653826560) + or, more generally + IPv6Network(int(IPv6Network('2001:db8::'))) == + IPv6Network('2001:db8::') + + strict: A boolean. If true, ensure that we have been passed + A true network address, eg, 2001:db8::1000/124 and not an + IP address on a network, eg, 2001:db8::1/124. + + Raises: + AddressValueError: If address isn't a valid IPv6 address. + NetmaskValueError: If the netmask isn't valid for + an IPv6 address. + ValueError: If strict was True and a network address was not + supplied. + + """ + _BaseNetwork.__init__(self, address) + + # Efficient constructor from integer or packed address + if isinstance(address, (bytes, _compat_int_types)): + self.network_address = IPv6Address(address) + self.netmask, self._prefixlen = self._make_netmask( + self._max_prefixlen) + return + + if isinstance(address, tuple): + if len(address) > 1: + arg = address[1] + else: + arg = self._max_prefixlen + self.netmask, self._prefixlen = self._make_netmask(arg) + self.network_address = IPv6Address(address[0]) + packed = int(self.network_address) + if packed & int(self.netmask) != packed: + if strict: + raise ValueError('%s has host bits set' % self) + else: + self.network_address = IPv6Address(packed & + int(self.netmask)) + return + + # Assume input argument to be string or any object representation + # which converts into a formatted IP prefix string. + addr = _split_optional_netmask(address) + + self.network_address = IPv6Address(self._ip_int_from_string(addr[0])) + + if len(addr) == 2: + arg = addr[1] + else: + arg = self._max_prefixlen + self.netmask, self._prefixlen = self._make_netmask(arg) + + if strict: + if (IPv6Address(int(self.network_address) & int(self.netmask)) != + self.network_address): + raise ValueError('%s has host bits set' % self) + self.network_address = IPv6Address(int(self.network_address) & + int(self.netmask)) + + if self._prefixlen == (self._max_prefixlen - 1): + self.hosts = self.__iter__ + + def hosts(self): + """Generate Iterator over usable hosts in a network. + + This is like __iter__ except it doesn't return the + Subnet-Router anycast address. + + """ + network = int(self.network_address) + broadcast = int(self.broadcast_address) + for x in _compat_range(network + 1, broadcast + 1): + yield self._address_class(x) + + @property + def is_site_local(self): + """Test if the address is reserved for site-local. + + Note that the site-local address space has been deprecated by RFC 3879. + Use is_private to test if this address is in the space of unique local + addresses as defined by RFC 4193. + + Returns: + A boolean, True if the address is reserved per RFC 3513 2.5.6. + + """ + return (self.network_address.is_site_local and + self.broadcast_address.is_site_local) + + +class _IPv6Constants(object): + + _linklocal_network = IPv6Network('fe80::/10') + + _multicast_network = IPv6Network('ff00::/8') + + _private_networks = [ + IPv6Network('::1/128'), + IPv6Network('::/128'), + IPv6Network('::ffff:0:0/96'), + IPv6Network('100::/64'), + IPv6Network('2001::/23'), + IPv6Network('2001:2::/48'), + IPv6Network('2001:db8::/32'), + IPv6Network('2001:10::/28'), + IPv6Network('fc00::/7'), + IPv6Network('fe80::/10'), + ] + + _reserved_networks = [ + IPv6Network('::/8'), IPv6Network('100::/8'), + IPv6Network('200::/7'), IPv6Network('400::/6'), + IPv6Network('800::/5'), IPv6Network('1000::/4'), + IPv6Network('4000::/3'), IPv6Network('6000::/3'), + IPv6Network('8000::/3'), IPv6Network('A000::/3'), + IPv6Network('C000::/3'), IPv6Network('E000::/4'), + IPv6Network('F000::/5'), IPv6Network('F800::/6'), + IPv6Network('FE00::/9'), + ] + + _sitelocal_network = IPv6Network('fec0::/10') + + +IPv6Address._constants = _IPv6Constants diff --git a/winvenv/Lib/site-packages/pip/_vendor/lockfile/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/lockfile/__init__.py new file mode 100644 index 0000000..a6f44a5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/lockfile/__init__.py @@ -0,0 +1,347 @@ +# -*- coding: utf-8 -*- + +""" +lockfile.py - Platform-independent advisory file locks. + +Requires Python 2.5 unless you apply 2.4.diff +Locking is done on a per-thread basis instead of a per-process basis. + +Usage: + +>>> lock = LockFile('somefile') +>>> try: +... lock.acquire() +... except AlreadyLocked: +... print 'somefile', 'is locked already.' +... except LockFailed: +... print 'somefile', 'can\\'t be locked.' +... else: +... print 'got lock' +got lock +>>> print lock.is_locked() +True +>>> lock.release() + +>>> lock = LockFile('somefile') +>>> print lock.is_locked() +False +>>> with lock: +... print lock.is_locked() +True +>>> print lock.is_locked() +False + +>>> lock = LockFile('somefile') +>>> # It is okay to lock twice from the same thread... +>>> with lock: +... lock.acquire() +... +>>> # Though no counter is kept, so you can't unlock multiple times... +>>> print lock.is_locked() +False + +Exceptions: + + Error - base class for other exceptions + LockError - base class for all locking exceptions + AlreadyLocked - Another thread or process already holds the lock + LockFailed - Lock failed for some other reason + UnlockError - base class for all unlocking exceptions + AlreadyUnlocked - File was not locked. + NotMyLock - File was locked but not by the current thread/process +""" + +from __future__ import absolute_import + +import functools +import os +import socket +import threading +import warnings + +# Work with PEP8 and non-PEP8 versions of threading module. +if not hasattr(threading, "current_thread"): + threading.current_thread = threading.currentThread +if not hasattr(threading.Thread, "get_name"): + threading.Thread.get_name = threading.Thread.getName + +__all__ = ['Error', 'LockError', 'LockTimeout', 'AlreadyLocked', + 'LockFailed', 'UnlockError', 'NotLocked', 'NotMyLock', + 'LinkFileLock', 'MkdirFileLock', 'SQLiteFileLock', + 'LockBase', 'locked'] + + +class Error(Exception): + """ + Base class for other exceptions. + + >>> try: + ... raise Error + ... except Exception: + ... pass + """ + pass + + +class LockError(Error): + """ + Base class for error arising from attempts to acquire the lock. + + >>> try: + ... raise LockError + ... except Error: + ... pass + """ + pass + + +class LockTimeout(LockError): + """Raised when lock creation fails within a user-defined period of time. + + >>> try: + ... raise LockTimeout + ... except LockError: + ... pass + """ + pass + + +class AlreadyLocked(LockError): + """Some other thread/process is locking the file. + + >>> try: + ... raise AlreadyLocked + ... except LockError: + ... pass + """ + pass + + +class LockFailed(LockError): + """Lock file creation failed for some other reason. + + >>> try: + ... raise LockFailed + ... except LockError: + ... pass + """ + pass + + +class UnlockError(Error): + """ + Base class for errors arising from attempts to release the lock. + + >>> try: + ... raise UnlockError + ... except Error: + ... pass + """ + pass + + +class NotLocked(UnlockError): + """Raised when an attempt is made to unlock an unlocked file. + + >>> try: + ... raise NotLocked + ... except UnlockError: + ... pass + """ + pass + + +class NotMyLock(UnlockError): + """Raised when an attempt is made to unlock a file someone else locked. + + >>> try: + ... raise NotMyLock + ... except UnlockError: + ... pass + """ + pass + + +class _SharedBase(object): + def __init__(self, path): + self.path = path + + def acquire(self, timeout=None): + """ + Acquire the lock. + + * If timeout is omitted (or None), wait forever trying to lock the + file. + + * If timeout > 0, try to acquire the lock for that many seconds. If + the lock period expires and the file is still locked, raise + LockTimeout. + + * If timeout <= 0, raise AlreadyLocked immediately if the file is + already locked. + """ + raise NotImplemented("implement in subclass") + + def release(self): + """ + Release the lock. + + If the file is not locked, raise NotLocked. + """ + raise NotImplemented("implement in subclass") + + def __enter__(self): + """ + Context manager support. + """ + self.acquire() + return self + + def __exit__(self, *_exc): + """ + Context manager support. + """ + self.release() + + def __repr__(self): + return "<%s: %r>" % (self.__class__.__name__, self.path) + + +class LockBase(_SharedBase): + """Base class for platform-specific lock classes.""" + def __init__(self, path, threaded=True, timeout=None): + """ + >>> lock = LockBase('somefile') + >>> lock = LockBase('somefile', threaded=False) + """ + super(LockBase, self).__init__(path) + self.lock_file = os.path.abspath(path) + ".lock" + self.hostname = socket.gethostname() + self.pid = os.getpid() + if threaded: + t = threading.current_thread() + # Thread objects in Python 2.4 and earlier do not have ident + # attrs. Worm around that. + ident = getattr(t, "ident", hash(t)) + self.tname = "-%x" % (ident & 0xffffffff) + else: + self.tname = "" + dirname = os.path.dirname(self.lock_file) + + # unique name is mostly about the current process, but must + # also contain the path -- otherwise, two adjacent locked + # files conflict (one file gets locked, creating lock-file and + # unique file, the other one gets locked, creating lock-file + # and overwriting the already existing lock-file, then one + # gets unlocked, deleting both lock-file and unique file, + # finally the last lock errors out upon releasing. + self.unique_name = os.path.join(dirname, + "%s%s.%s%s" % (self.hostname, + self.tname, + self.pid, + hash(self.path))) + self.timeout = timeout + + def is_locked(self): + """ + Tell whether or not the file is locked. + """ + raise NotImplemented("implement in subclass") + + def i_am_locking(self): + """ + Return True if this object is locking the file. + """ + raise NotImplemented("implement in subclass") + + def break_lock(self): + """ + Remove a lock. Useful if a locking thread failed to unlock. + """ + raise NotImplemented("implement in subclass") + + def __repr__(self): + return "<%s: %r -- %r>" % (self.__class__.__name__, self.unique_name, + self.path) + + +def _fl_helper(cls, mod, *args, **kwds): + warnings.warn("Import from %s module instead of lockfile package" % mod, + DeprecationWarning, stacklevel=2) + # This is a bit funky, but it's only for awhile. The way the unit tests + # are constructed this function winds up as an unbound method, so it + # actually takes three args, not two. We want to toss out self. + if not isinstance(args[0], str): + # We are testing, avoid the first arg + args = args[1:] + if len(args) == 1 and not kwds: + kwds["threaded"] = True + return cls(*args, **kwds) + + +def LinkFileLock(*args, **kwds): + """Factory function provided for backwards compatibility. + + Do not use in new code. Instead, import LinkLockFile from the + lockfile.linklockfile module. + """ + from . import linklockfile + return _fl_helper(linklockfile.LinkLockFile, "lockfile.linklockfile", + *args, **kwds) + + +def MkdirFileLock(*args, **kwds): + """Factory function provided for backwards compatibility. + + Do not use in new code. Instead, import MkdirLockFile from the + lockfile.mkdirlockfile module. + """ + from . import mkdirlockfile + return _fl_helper(mkdirlockfile.MkdirLockFile, "lockfile.mkdirlockfile", + *args, **kwds) + + +def SQLiteFileLock(*args, **kwds): + """Factory function provided for backwards compatibility. + + Do not use in new code. Instead, import SQLiteLockFile from the + lockfile.mkdirlockfile module. + """ + from . import sqlitelockfile + return _fl_helper(sqlitelockfile.SQLiteLockFile, "lockfile.sqlitelockfile", + *args, **kwds) + + +def locked(path, timeout=None): + """Decorator which enables locks for decorated function. + + Arguments: + - path: path for lockfile. + - timeout (optional): Timeout for acquiring lock. + + Usage: + @locked('/var/run/myname', timeout=0) + def myname(...): + ... + """ + def decor(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + lock = FileLock(path, timeout=timeout) + lock.acquire() + try: + return func(*args, **kwargs) + finally: + lock.release() + return wrapper + return decor + + +if hasattr(os, "link"): + from . import linklockfile as _llf + LockFile = _llf.LinkLockFile +else: + from . import mkdirlockfile as _mlf + LockFile = _mlf.MkdirLockFile + +FileLock = LockFile diff --git a/winvenv/Lib/site-packages/pip/_vendor/lockfile/linklockfile.py b/winvenv/Lib/site-packages/pip/_vendor/lockfile/linklockfile.py new file mode 100644 index 0000000..2ca9be0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/lockfile/linklockfile.py @@ -0,0 +1,73 @@ +from __future__ import absolute_import + +import time +import os + +from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, + AlreadyLocked) + + +class LinkLockFile(LockBase): + """Lock access to a file using atomic property of link(2). + + >>> lock = LinkLockFile('somefile') + >>> lock = LinkLockFile('somefile', threaded=False) + """ + + def acquire(self, timeout=None): + try: + open(self.unique_name, "wb").close() + except IOError: + raise LockFailed("failed to create %s" % self.unique_name) + + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + while True: + # Try and create a hard link to it. + try: + os.link(self.unique_name, self.lock_file) + except OSError: + # Link creation failed. Maybe we've double-locked? + nlinks = os.stat(self.unique_name).st_nlink + if nlinks == 2: + # The original link plus the one I created == 2. We're + # good to go. + return + else: + # Otherwise the lock creation failed. + if timeout is not None and time.time() > end_time: + os.unlink(self.unique_name) + if timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(timeout is not None and timeout / 10 or 0.1) + else: + # Link creation succeeded. We're good to go. + return + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + elif not os.path.exists(self.unique_name): + raise NotMyLock("%s is locked, but not by me" % self.path) + os.unlink(self.unique_name) + os.unlink(self.lock_file) + + def is_locked(self): + return os.path.exists(self.lock_file) + + def i_am_locking(self): + return (self.is_locked() and + os.path.exists(self.unique_name) and + os.stat(self.unique_name).st_nlink == 2) + + def break_lock(self): + if os.path.exists(self.lock_file): + os.unlink(self.lock_file) diff --git a/winvenv/Lib/site-packages/pip/_vendor/lockfile/mkdirlockfile.py b/winvenv/Lib/site-packages/pip/_vendor/lockfile/mkdirlockfile.py new file mode 100644 index 0000000..05a8c96 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/lockfile/mkdirlockfile.py @@ -0,0 +1,84 @@ +from __future__ import absolute_import, division + +import time +import os +import sys +import errno + +from . import (LockBase, LockFailed, NotLocked, NotMyLock, LockTimeout, + AlreadyLocked) + + +class MkdirLockFile(LockBase): + """Lock file by creating a directory.""" + def __init__(self, path, threaded=True, timeout=None): + """ + >>> lock = MkdirLockFile('somefile') + >>> lock = MkdirLockFile('somefile', threaded=False) + """ + LockBase.__init__(self, path, threaded, timeout) + # Lock file itself is a directory. Place the unique file name into + # it. + self.unique_name = os.path.join(self.lock_file, + "%s.%s%s" % (self.hostname, + self.tname, + self.pid)) + + def acquire(self, timeout=None): + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + if timeout is None: + wait = 0.1 + else: + wait = max(0, timeout / 10) + + while True: + try: + os.mkdir(self.lock_file) + except OSError: + err = sys.exc_info()[1] + if err.errno == errno.EEXIST: + # Already locked. + if os.path.exists(self.unique_name): + # Already locked by me. + return + if timeout is not None and time.time() > end_time: + if timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + # Someone else has the lock. + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(wait) + else: + # Couldn't create the lock for some other reason + raise LockFailed("failed to create %s" % self.lock_file) + else: + open(self.unique_name, "wb").close() + return + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + elif not os.path.exists(self.unique_name): + raise NotMyLock("%s is locked, but not by me" % self.path) + os.unlink(self.unique_name) + os.rmdir(self.lock_file) + + def is_locked(self): + return os.path.exists(self.lock_file) + + def i_am_locking(self): + return (self.is_locked() and + os.path.exists(self.unique_name)) + + def break_lock(self): + if os.path.exists(self.lock_file): + for name in os.listdir(self.lock_file): + os.unlink(os.path.join(self.lock_file, name)) + os.rmdir(self.lock_file) diff --git a/winvenv/Lib/site-packages/pip/_vendor/lockfile/pidlockfile.py b/winvenv/Lib/site-packages/pip/_vendor/lockfile/pidlockfile.py new file mode 100644 index 0000000..069e85b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/lockfile/pidlockfile.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- + +# pidlockfile.py +# +# Copyright © 2008–2009 Ben Finney <ben+python@benfinney.id.au> +# +# This is free software: you may copy, modify, and/or distribute this work +# under the terms of the Python Software Foundation License, version 2 or +# later as published by the Python Software Foundation. +# No warranty expressed or implied. See the file LICENSE.PSF-2 for details. + +""" Lockfile behaviour implemented via Unix PID files. + """ + +from __future__ import absolute_import + +import errno +import os +import time + +from . import (LockBase, AlreadyLocked, LockFailed, NotLocked, NotMyLock, + LockTimeout) + + +class PIDLockFile(LockBase): + """ Lockfile implemented as a Unix PID file. + + The lock file is a normal file named by the attribute `path`. + A lock's PID file contains a single line of text, containing + the process ID (PID) of the process that acquired the lock. + + >>> lock = PIDLockFile('somefile') + >>> lock = PIDLockFile('somefile') + """ + + def __init__(self, path, threaded=False, timeout=None): + # pid lockfiles don't support threaded operation, so always force + # False as the threaded arg. + LockBase.__init__(self, path, False, timeout) + self.unique_name = self.path + + def read_pid(self): + """ Get the PID from the lock file. + """ + return read_pid_from_pidfile(self.path) + + def is_locked(self): + """ Test if the lock is currently held. + + The lock is held if the PID file for this lock exists. + + """ + return os.path.exists(self.path) + + def i_am_locking(self): + """ Test if the lock is held by the current process. + + Returns ``True`` if the current process ID matches the + number stored in the PID file. + """ + return self.is_locked() and os.getpid() == self.read_pid() + + def acquire(self, timeout=None): + """ Acquire the lock. + + Creates the PID file for this lock, or raises an error if + the lock could not be acquired. + """ + + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + while True: + try: + write_pid_to_pidfile(self.path) + except OSError as exc: + if exc.errno == errno.EEXIST: + # The lock creation failed. Maybe sleep a bit. + if time.time() > end_time: + if timeout is not None and timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(timeout is not None and timeout / 10 or 0.1) + else: + raise LockFailed("failed to create %s" % self.path) + else: + return + + def release(self): + """ Release the lock. + + Removes the PID file to release the lock, or raises an + error if the current process does not hold the lock. + + """ + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + if not self.i_am_locking(): + raise NotMyLock("%s is locked, but not by me" % self.path) + remove_existing_pidfile(self.path) + + def break_lock(self): + """ Break an existing lock. + + Removes the PID file if it already exists, otherwise does + nothing. + + """ + remove_existing_pidfile(self.path) + + +def read_pid_from_pidfile(pidfile_path): + """ Read the PID recorded in the named PID file. + + Read and return the numeric PID recorded as text in the named + PID file. If the PID file cannot be read, or if the content is + not a valid PID, return ``None``. + + """ + pid = None + try: + pidfile = open(pidfile_path, 'r') + except IOError: + pass + else: + # According to the FHS 2.3 section on PID files in /var/run: + # + # The file must consist of the process identifier in + # ASCII-encoded decimal, followed by a newline character. + # + # Programs that read PID files should be somewhat flexible + # in what they accept; i.e., they should ignore extra + # whitespace, leading zeroes, absence of the trailing + # newline, or additional lines in the PID file. + + line = pidfile.readline().strip() + try: + pid = int(line) + except ValueError: + pass + pidfile.close() + + return pid + + +def write_pid_to_pidfile(pidfile_path): + """ Write the PID in the named PID file. + + Get the numeric process ID (“PID”) of the current process + and write it to the named file as a line of text. + + """ + open_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY) + open_mode = 0o644 + pidfile_fd = os.open(pidfile_path, open_flags, open_mode) + pidfile = os.fdopen(pidfile_fd, 'w') + + # According to the FHS 2.3 section on PID files in /var/run: + # + # The file must consist of the process identifier in + # ASCII-encoded decimal, followed by a newline character. For + # example, if crond was process number 25, /var/run/crond.pid + # would contain three characters: two, five, and newline. + + pid = os.getpid() + pidfile.write("%s\n" % pid) + pidfile.close() + + +def remove_existing_pidfile(pidfile_path): + """ Remove the named PID file if it exists. + + Removing a PID file that doesn't already exist puts us in the + desired state, so we ignore the condition if the file does not + exist. + + """ + try: + os.remove(pidfile_path) + except OSError as exc: + if exc.errno == errno.ENOENT: + pass + else: + raise diff --git a/winvenv/Lib/site-packages/pip/_vendor/lockfile/sqlitelockfile.py b/winvenv/Lib/site-packages/pip/_vendor/lockfile/sqlitelockfile.py new file mode 100644 index 0000000..f997e24 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/lockfile/sqlitelockfile.py @@ -0,0 +1,156 @@ +from __future__ import absolute_import, division + +import time +import os + +try: + unicode +except NameError: + unicode = str + +from . import LockBase, NotLocked, NotMyLock, LockTimeout, AlreadyLocked + + +class SQLiteLockFile(LockBase): + "Demonstrate SQL-based locking." + + testdb = None + + def __init__(self, path, threaded=True, timeout=None): + """ + >>> lock = SQLiteLockFile('somefile') + >>> lock = SQLiteLockFile('somefile', threaded=False) + """ + LockBase.__init__(self, path, threaded, timeout) + self.lock_file = unicode(self.lock_file) + self.unique_name = unicode(self.unique_name) + + if SQLiteLockFile.testdb is None: + import tempfile + _fd, testdb = tempfile.mkstemp() + os.close(_fd) + os.unlink(testdb) + del _fd, tempfile + SQLiteLockFile.testdb = testdb + + import sqlite3 + self.connection = sqlite3.connect(SQLiteLockFile.testdb) + + c = self.connection.cursor() + try: + c.execute("create table locks" + "(" + " lock_file varchar(32)," + " unique_name varchar(32)" + ")") + except sqlite3.OperationalError: + pass + else: + self.connection.commit() + import atexit + atexit.register(os.unlink, SQLiteLockFile.testdb) + + def acquire(self, timeout=None): + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + if timeout is None: + wait = 0.1 + elif timeout <= 0: + wait = 0 + else: + wait = timeout / 10 + + cursor = self.connection.cursor() + + while True: + if not self.is_locked(): + # Not locked. Try to lock it. + cursor.execute("insert into locks" + " (lock_file, unique_name)" + " values" + " (?, ?)", + (self.lock_file, self.unique_name)) + self.connection.commit() + + # Check to see if we are the only lock holder. + cursor.execute("select * from locks" + " where unique_name = ?", + (self.unique_name,)) + rows = cursor.fetchall() + if len(rows) > 1: + # Nope. Someone else got there. Remove our lock. + cursor.execute("delete from locks" + " where unique_name = ?", + (self.unique_name,)) + self.connection.commit() + else: + # Yup. We're done, so go home. + return + else: + # Check to see if we are the only lock holder. + cursor.execute("select * from locks" + " where unique_name = ?", + (self.unique_name,)) + rows = cursor.fetchall() + if len(rows) == 1: + # We're the locker, so go home. + return + + # Maybe we should wait a bit longer. + if timeout is not None and time.time() > end_time: + if timeout > 0: + # No more waiting. + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + # Someone else has the lock and we are impatient.. + raise AlreadyLocked("%s is already locked" % self.path) + + # Well, okay. We'll give it a bit longer. + time.sleep(wait) + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + if not self.i_am_locking(): + raise NotMyLock("%s is locked, but not by me (by %s)" % + (self.unique_name, self._who_is_locking())) + cursor = self.connection.cursor() + cursor.execute("delete from locks" + " where unique_name = ?", + (self.unique_name,)) + self.connection.commit() + + def _who_is_locking(self): + cursor = self.connection.cursor() + cursor.execute("select unique_name from locks" + " where lock_file = ?", + (self.lock_file,)) + return cursor.fetchone()[0] + + def is_locked(self): + cursor = self.connection.cursor() + cursor.execute("select * from locks" + " where lock_file = ?", + (self.lock_file,)) + rows = cursor.fetchall() + return not not rows + + def i_am_locking(self): + cursor = self.connection.cursor() + cursor.execute("select * from locks" + " where lock_file = ?" + " and unique_name = ?", + (self.lock_file, self.unique_name)) + return not not cursor.fetchall() + + def break_lock(self): + cursor = self.connection.cursor() + cursor.execute("delete from locks" + " where lock_file = ?", + (self.lock_file,)) + self.connection.commit() diff --git a/winvenv/Lib/site-packages/pip/_vendor/lockfile/symlinklockfile.py b/winvenv/Lib/site-packages/pip/_vendor/lockfile/symlinklockfile.py new file mode 100644 index 0000000..23b41f5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/lockfile/symlinklockfile.py @@ -0,0 +1,70 @@ +from __future__ import absolute_import + +import os +import time + +from . import (LockBase, NotLocked, NotMyLock, LockTimeout, + AlreadyLocked) + + +class SymlinkLockFile(LockBase): + """Lock access to a file using symlink(2).""" + + def __init__(self, path, threaded=True, timeout=None): + # super(SymlinkLockFile).__init(...) + LockBase.__init__(self, path, threaded, timeout) + # split it back! + self.unique_name = os.path.split(self.unique_name)[1] + + def acquire(self, timeout=None): + # Hopefully unnecessary for symlink. + # try: + # open(self.unique_name, "wb").close() + # except IOError: + # raise LockFailed("failed to create %s" % self.unique_name) + timeout = timeout if timeout is not None else self.timeout + end_time = time.time() + if timeout is not None and timeout > 0: + end_time += timeout + + while True: + # Try and create a symbolic link to it. + try: + os.symlink(self.unique_name, self.lock_file) + except OSError: + # Link creation failed. Maybe we've double-locked? + if self.i_am_locking(): + # Linked to out unique name. Proceed. + return + else: + # Otherwise the lock creation failed. + if timeout is not None and time.time() > end_time: + if timeout > 0: + raise LockTimeout("Timeout waiting to acquire" + " lock for %s" % + self.path) + else: + raise AlreadyLocked("%s is already locked" % + self.path) + time.sleep(timeout / 10 if timeout is not None else 0.1) + else: + # Link creation succeeded. We're good to go. + return + + def release(self): + if not self.is_locked(): + raise NotLocked("%s is not locked" % self.path) + elif not self.i_am_locking(): + raise NotMyLock("%s is locked, but not by me" % self.path) + os.unlink(self.lock_file) + + def is_locked(self): + return os.path.islink(self.lock_file) + + def i_am_locking(self): + return (os.path.islink(self.lock_file) + and os.readlink(self.lock_file) == self.unique_name) + + def break_lock(self): + if os.path.islink(self.lock_file): # exists && link + os.unlink(self.lock_file) diff --git a/winvenv/Lib/site-packages/pip/_vendor/msgpack/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/msgpack/__init__.py new file mode 100644 index 0000000..2afca5a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/msgpack/__init__.py @@ -0,0 +1,66 @@ +# coding: utf-8 +from pip._vendor.msgpack._version import version +from pip._vendor.msgpack.exceptions import * + +from collections import namedtuple + + +class ExtType(namedtuple('ExtType', 'code data')): + """ExtType represents ext type in msgpack.""" + def __new__(cls, code, data): + if not isinstance(code, int): + raise TypeError("code must be int") + if not isinstance(data, bytes): + raise TypeError("data must be bytes") + if not 0 <= code <= 127: + raise ValueError("code must be 0~127") + return super(ExtType, cls).__new__(cls, code, data) + + +import os +if os.environ.get('MSGPACK_PUREPYTHON'): + from pip._vendor.msgpack.fallback import Packer, unpackb, Unpacker +else: + try: + from pip._vendor.msgpack._packer import Packer + from pip._vendor.msgpack._unpacker import unpackb, Unpacker + except ImportError: + from pip._vendor.msgpack.fallback import Packer, unpackb, Unpacker + + +def pack(o, stream, **kwargs): + """ + Pack object `o` and write it to `stream` + + See :class:`Packer` for options. + """ + packer = Packer(**kwargs) + stream.write(packer.pack(o)) + + +def packb(o, **kwargs): + """ + Pack object `o` and return packed bytes + + See :class:`Packer` for options. + """ + return Packer(**kwargs).pack(o) + + +def unpack(stream, **kwargs): + """ + Unpack an object from `stream`. + + Raises `ExtraData` when `stream` contains extra bytes. + See :class:`Unpacker` for options. + """ + data = stream.read() + return unpackb(data, **kwargs) + + +# alias for compatibility to simplejson/marshal/pickle. +load = unpack +loads = unpackb + +dump = pack +dumps = packb diff --git a/winvenv/Lib/site-packages/pip/_vendor/msgpack/_version.py b/winvenv/Lib/site-packages/pip/_vendor/msgpack/_version.py new file mode 100644 index 0000000..d28f0de --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/msgpack/_version.py @@ -0,0 +1 @@ +version = (0, 5, 6) diff --git a/winvenv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py b/winvenv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py new file mode 100644 index 0000000..9766881 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py @@ -0,0 +1,41 @@ +class UnpackException(Exception): + """Deprecated. Use Exception instead to catch all exception during unpacking.""" + + +class BufferFull(UnpackException): + pass + + +class OutOfData(UnpackException): + pass + + +class UnpackValueError(UnpackException, ValueError): + """Deprecated. Use ValueError instead.""" + + +class ExtraData(UnpackValueError): + def __init__(self, unpacked, extra): + self.unpacked = unpacked + self.extra = extra + + def __str__(self): + return "unpack(b) received extra data." + + +class PackException(Exception): + """Deprecated. Use Exception instead to catch all exception during packing.""" + + +class PackValueError(PackException, ValueError): + """PackValueError is raised when type of input data is supported but it's value is unsupported. + + Deprecated. Use ValueError instead. + """ + + +class PackOverflowError(PackValueError, OverflowError): + """PackOverflowError is raised when integer value is out of range of msgpack support [-2**31, 2**32). + + Deprecated. Use ValueError instead. + """ diff --git a/winvenv/Lib/site-packages/pip/_vendor/msgpack/fallback.py b/winvenv/Lib/site-packages/pip/_vendor/msgpack/fallback.py new file mode 100644 index 0000000..9418421 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/msgpack/fallback.py @@ -0,0 +1,977 @@ +"""Fallback pure Python implementation of msgpack""" + +import sys +import struct +import warnings + +if sys.version_info[0] == 3: + PY3 = True + int_types = int + Unicode = str + xrange = range + def dict_iteritems(d): + return d.items() +else: + PY3 = False + int_types = (int, long) + Unicode = unicode + def dict_iteritems(d): + return d.iteritems() + + +if hasattr(sys, 'pypy_version_info'): + # cStringIO is slow on PyPy, StringIO is faster. However: PyPy's own + # StringBuilder is fastest. + from __pypy__ import newlist_hint + try: + from __pypy__.builders import BytesBuilder as StringBuilder + except ImportError: + from __pypy__.builders import StringBuilder + USING_STRINGBUILDER = True + class StringIO(object): + def __init__(self, s=b''): + if s: + self.builder = StringBuilder(len(s)) + self.builder.append(s) + else: + self.builder = StringBuilder() + def write(self, s): + if isinstance(s, memoryview): + s = s.tobytes() + elif isinstance(s, bytearray): + s = bytes(s) + self.builder.append(s) + def getvalue(self): + return self.builder.build() +else: + USING_STRINGBUILDER = False + from io import BytesIO as StringIO + newlist_hint = lambda size: [] + + +from pip._vendor.msgpack.exceptions import ( + BufferFull, + OutOfData, + UnpackValueError, + PackValueError, + PackOverflowError, + ExtraData) + +from pip._vendor.msgpack import ExtType + + +EX_SKIP = 0 +EX_CONSTRUCT = 1 +EX_READ_ARRAY_HEADER = 2 +EX_READ_MAP_HEADER = 3 + +TYPE_IMMEDIATE = 0 +TYPE_ARRAY = 1 +TYPE_MAP = 2 +TYPE_RAW = 3 +TYPE_BIN = 4 +TYPE_EXT = 5 + +DEFAULT_RECURSE_LIMIT = 511 + + +def _check_type_strict(obj, t, type=type, tuple=tuple): + if type(t) is tuple: + return type(obj) in t + else: + return type(obj) is t + + +def _get_data_from_buffer(obj): + try: + view = memoryview(obj) + except TypeError: + # try to use legacy buffer protocol if 2.7, otherwise re-raise + if not PY3: + view = memoryview(buffer(obj)) + warnings.warn("using old buffer interface to unpack %s; " + "this leads to unpacking errors if slicing is used and " + "will be removed in a future version" % type(obj), + RuntimeWarning) + else: + raise + if view.itemsize != 1: + raise ValueError("cannot unpack from multi-byte object") + return view + + +def unpack(stream, **kwargs): + warnings.warn( + "Direct calling implementation's unpack() is deprecated, Use msgpack.unpack() or unpackb() instead.", + PendingDeprecationWarning) + data = stream.read() + return unpackb(data, **kwargs) + + +def unpackb(packed, **kwargs): + """ + Unpack an object from `packed`. + + Raises `ExtraData` when `packed` contains extra bytes. + See :class:`Unpacker` for options. + """ + unpacker = Unpacker(None, **kwargs) + unpacker.feed(packed) + try: + ret = unpacker._unpack() + except OutOfData: + raise UnpackValueError("Data is not enough.") + if unpacker._got_extradata(): + raise ExtraData(ret, unpacker._get_extradata()) + return ret + + +class Unpacker(object): + """Streaming unpacker. + + arguments: + + :param file_like: + File-like object having `.read(n)` method. + If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable. + + :param int read_size: + Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`) + + :param bool use_list: + If true, unpack msgpack array to Python list. + Otherwise, unpack to Python tuple. (default: True) + + :param bool raw: + If true, unpack msgpack raw to Python bytes (default). + Otherwise, unpack to Python str (or unicode on Python 2) by decoding + with UTF-8 encoding (recommended). + Currently, the default is true, but it will be changed to false in + near future. So you must specify it explicitly for keeping backward + compatibility. + + *encoding* option which is deprecated overrides this option. + + :param callable object_hook: + When specified, it should be callable. + Unpacker calls it with a dict argument after unpacking msgpack map. + (See also simplejson) + + :param callable object_pairs_hook: + When specified, it should be callable. + Unpacker calls it with a list of key-value pairs after unpacking msgpack map. + (See also simplejson) + + :param str encoding: + Encoding used for decoding msgpack raw. + If it is None (default), msgpack raw is deserialized to Python bytes. + + :param str unicode_errors: + (deprecated) Used for decoding msgpack raw with *encoding*. + (default: `'strict'`) + + :param int max_buffer_size: + Limits size of data waiting unpacked. 0 means system's INT_MAX (default). + Raises `BufferFull` exception when it is insufficient. + You should set this parameter when unpacking data from untrusted source. + + :param int max_str_len: + Limits max length of str. (default: 2**31-1) + + :param int max_bin_len: + Limits max length of bin. (default: 2**31-1) + + :param int max_array_len: + Limits max length of array. (default: 2**31-1) + + :param int max_map_len: + Limits max length of map. (default: 2**31-1) + + + example of streaming deserialize from file-like object:: + + unpacker = Unpacker(file_like, raw=False) + for o in unpacker: + process(o) + + example of streaming deserialize from socket:: + + unpacker = Unpacker(raw=False) + while True: + buf = sock.recv(1024**2) + if not buf: + break + unpacker.feed(buf) + for o in unpacker: + process(o) + """ + + def __init__(self, file_like=None, read_size=0, use_list=True, raw=True, + object_hook=None, object_pairs_hook=None, list_hook=None, + encoding=None, unicode_errors=None, max_buffer_size=0, + ext_hook=ExtType, + max_str_len=2147483647, # 2**32-1 + max_bin_len=2147483647, + max_array_len=2147483647, + max_map_len=2147483647, + max_ext_len=2147483647): + + if encoding is not None: + warnings.warn( + "encoding is deprecated, Use raw=False instead.", + PendingDeprecationWarning) + + if unicode_errors is None: + unicode_errors = 'strict' + + if file_like is None: + self._feeding = True + else: + if not callable(file_like.read): + raise TypeError("`file_like.read` must be callable") + self.file_like = file_like + self._feeding = False + + #: array of bytes fed. + self._buffer = bytearray() + # Some very old pythons don't support `struct.unpack_from()` with a + # `bytearray`. So we wrap it in a `buffer()` there. + if sys.version_info < (2, 7, 6): + self._buffer_view = buffer(self._buffer) + else: + self._buffer_view = self._buffer + #: Which position we currently reads + self._buff_i = 0 + + # When Unpacker is used as an iterable, between the calls to next(), + # the buffer is not "consumed" completely, for efficiency sake. + # Instead, it is done sloppily. To make sure we raise BufferFull at + # the correct moments, we have to keep track of how sloppy we were. + # Furthermore, when the buffer is incomplete (that is: in the case + # we raise an OutOfData) we need to rollback the buffer to the correct + # state, which _buf_checkpoint records. + self._buf_checkpoint = 0 + + self._max_buffer_size = max_buffer_size or 2**31-1 + if read_size > self._max_buffer_size: + raise ValueError("read_size must be smaller than max_buffer_size") + self._read_size = read_size or min(self._max_buffer_size, 16*1024) + self._raw = bool(raw) + self._encoding = encoding + self._unicode_errors = unicode_errors + self._use_list = use_list + self._list_hook = list_hook + self._object_hook = object_hook + self._object_pairs_hook = object_pairs_hook + self._ext_hook = ext_hook + self._max_str_len = max_str_len + self._max_bin_len = max_bin_len + self._max_array_len = max_array_len + self._max_map_len = max_map_len + self._max_ext_len = max_ext_len + self._stream_offset = 0 + + if list_hook is not None and not callable(list_hook): + raise TypeError('`list_hook` is not callable') + if object_hook is not None and not callable(object_hook): + raise TypeError('`object_hook` is not callable') + if object_pairs_hook is not None and not callable(object_pairs_hook): + raise TypeError('`object_pairs_hook` is not callable') + if object_hook is not None and object_pairs_hook is not None: + raise TypeError("object_pairs_hook and object_hook are mutually " + "exclusive") + if not callable(ext_hook): + raise TypeError("`ext_hook` is not callable") + + def feed(self, next_bytes): + assert self._feeding + view = _get_data_from_buffer(next_bytes) + if (len(self._buffer) - self._buff_i + len(view) > self._max_buffer_size): + raise BufferFull + + # Strip buffer before checkpoint before reading file. + if self._buf_checkpoint > 0: + del self._buffer[:self._buf_checkpoint] + self._buff_i -= self._buf_checkpoint + self._buf_checkpoint = 0 + + self._buffer += view + + def _consume(self): + """ Gets rid of the used parts of the buffer. """ + self._stream_offset += self._buff_i - self._buf_checkpoint + self._buf_checkpoint = self._buff_i + + def _got_extradata(self): + return self._buff_i < len(self._buffer) + + def _get_extradata(self): + return self._buffer[self._buff_i:] + + def read_bytes(self, n): + return self._read(n) + + def _read(self, n): + # (int) -> bytearray + self._reserve(n) + i = self._buff_i + self._buff_i = i+n + return self._buffer[i:i+n] + + def _reserve(self, n): + remain_bytes = len(self._buffer) - self._buff_i - n + + # Fast path: buffer has n bytes already + if remain_bytes >= 0: + return + + if self._feeding: + self._buff_i = self._buf_checkpoint + raise OutOfData + + # Strip buffer before checkpoint before reading file. + if self._buf_checkpoint > 0: + del self._buffer[:self._buf_checkpoint] + self._buff_i -= self._buf_checkpoint + self._buf_checkpoint = 0 + + # Read from file + remain_bytes = -remain_bytes + while remain_bytes > 0: + to_read_bytes = max(self._read_size, remain_bytes) + read_data = self.file_like.read(to_read_bytes) + if not read_data: + break + assert isinstance(read_data, bytes) + self._buffer += read_data + remain_bytes -= len(read_data) + + if len(self._buffer) < n + self._buff_i: + self._buff_i = 0 # rollback + raise OutOfData + + def _read_header(self, execute=EX_CONSTRUCT): + typ = TYPE_IMMEDIATE + n = 0 + obj = None + self._reserve(1) + b = self._buffer[self._buff_i] + self._buff_i += 1 + if b & 0b10000000 == 0: + obj = b + elif b & 0b11100000 == 0b11100000: + obj = -1 - (b ^ 0xff) + elif b & 0b11100000 == 0b10100000: + n = b & 0b00011111 + typ = TYPE_RAW + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b & 0b11110000 == 0b10010000: + n = b & 0b00001111 + typ = TYPE_ARRAY + if n > self._max_array_len: + raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) + elif b & 0b11110000 == 0b10000000: + n = b & 0b00001111 + typ = TYPE_MAP + if n > self._max_map_len: + raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) + elif b == 0xc0: + obj = None + elif b == 0xc2: + obj = False + elif b == 0xc3: + obj = True + elif b == 0xc4: + typ = TYPE_BIN + self._reserve(1) + n = self._buffer[self._buff_i] + self._buff_i += 1 + if n > self._max_bin_len: + raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) + obj = self._read(n) + elif b == 0xc5: + typ = TYPE_BIN + self._reserve(2) + n = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0] + self._buff_i += 2 + if n > self._max_bin_len: + raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) + obj = self._read(n) + elif b == 0xc6: + typ = TYPE_BIN + self._reserve(4) + n = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + if n > self._max_bin_len: + raise UnpackValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) + obj = self._read(n) + elif b == 0xc7: # ext 8 + typ = TYPE_EXT + self._reserve(2) + L, n = struct.unpack_from('Bb', self._buffer_view, self._buff_i) + self._buff_i += 2 + if L > self._max_ext_len: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) + obj = self._read(L) + elif b == 0xc8: # ext 16 + typ = TYPE_EXT + self._reserve(3) + L, n = struct.unpack_from('>Hb', self._buffer_view, self._buff_i) + self._buff_i += 3 + if L > self._max_ext_len: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) + obj = self._read(L) + elif b == 0xc9: # ext 32 + typ = TYPE_EXT + self._reserve(5) + L, n = struct.unpack_from('>Ib', self._buffer_view, self._buff_i) + self._buff_i += 5 + if L > self._max_ext_len: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) + obj = self._read(L) + elif b == 0xca: + self._reserve(4) + obj = struct.unpack_from(">f", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + elif b == 0xcb: + self._reserve(8) + obj = struct.unpack_from(">d", self._buffer_view, self._buff_i)[0] + self._buff_i += 8 + elif b == 0xcc: + self._reserve(1) + obj = self._buffer[self._buff_i] + self._buff_i += 1 + elif b == 0xcd: + self._reserve(2) + obj = struct.unpack_from(">H", self._buffer_view, self._buff_i)[0] + self._buff_i += 2 + elif b == 0xce: + self._reserve(4) + obj = struct.unpack_from(">I", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + elif b == 0xcf: + self._reserve(8) + obj = struct.unpack_from(">Q", self._buffer_view, self._buff_i)[0] + self._buff_i += 8 + elif b == 0xd0: + self._reserve(1) + obj = struct.unpack_from("b", self._buffer_view, self._buff_i)[0] + self._buff_i += 1 + elif b == 0xd1: + self._reserve(2) + obj = struct.unpack_from(">h", self._buffer_view, self._buff_i)[0] + self._buff_i += 2 + elif b == 0xd2: + self._reserve(4) + obj = struct.unpack_from(">i", self._buffer_view, self._buff_i)[0] + self._buff_i += 4 + elif b == 0xd3: + self._reserve(8) + obj = struct.unpack_from(">q", self._buffer_view, self._buff_i)[0] + self._buff_i += 8 + elif b == 0xd4: # fixext 1 + typ = TYPE_EXT + if self._max_ext_len < 1: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (1, self._max_ext_len)) + self._reserve(2) + n, obj = struct.unpack_from("b1s", self._buffer_view, self._buff_i) + self._buff_i += 2 + elif b == 0xd5: # fixext 2 + typ = TYPE_EXT + if self._max_ext_len < 2: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (2, self._max_ext_len)) + self._reserve(3) + n, obj = struct.unpack_from("b2s", self._buffer_view, self._buff_i) + self._buff_i += 3 + elif b == 0xd6: # fixext 4 + typ = TYPE_EXT + if self._max_ext_len < 4: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (4, self._max_ext_len)) + self._reserve(5) + n, obj = struct.unpack_from("b4s", self._buffer_view, self._buff_i) + self._buff_i += 5 + elif b == 0xd7: # fixext 8 + typ = TYPE_EXT + if self._max_ext_len < 8: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (8, self._max_ext_len)) + self._reserve(9) + n, obj = struct.unpack_from("b8s", self._buffer_view, self._buff_i) + self._buff_i += 9 + elif b == 0xd8: # fixext 16 + typ = TYPE_EXT + if self._max_ext_len < 16: + raise UnpackValueError("%s exceeds max_ext_len(%s)" % (16, self._max_ext_len)) + self._reserve(17) + n, obj = struct.unpack_from("b16s", self._buffer_view, self._buff_i) + self._buff_i += 17 + elif b == 0xd9: + typ = TYPE_RAW + self._reserve(1) + n = self._buffer[self._buff_i] + self._buff_i += 1 + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b == 0xda: + typ = TYPE_RAW + self._reserve(2) + n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) + self._buff_i += 2 + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b == 0xdb: + typ = TYPE_RAW + self._reserve(4) + n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) + self._buff_i += 4 + if n > self._max_str_len: + raise UnpackValueError("%s exceeds max_str_len(%s)", n, self._max_str_len) + obj = self._read(n) + elif b == 0xdc: + typ = TYPE_ARRAY + self._reserve(2) + n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) + self._buff_i += 2 + if n > self._max_array_len: + raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) + elif b == 0xdd: + typ = TYPE_ARRAY + self._reserve(4) + n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) + self._buff_i += 4 + if n > self._max_array_len: + raise UnpackValueError("%s exceeds max_array_len(%s)", n, self._max_array_len) + elif b == 0xde: + self._reserve(2) + n, = struct.unpack_from(">H", self._buffer_view, self._buff_i) + self._buff_i += 2 + if n > self._max_map_len: + raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) + typ = TYPE_MAP + elif b == 0xdf: + self._reserve(4) + n, = struct.unpack_from(">I", self._buffer_view, self._buff_i) + self._buff_i += 4 + if n > self._max_map_len: + raise UnpackValueError("%s exceeds max_map_len(%s)", n, self._max_map_len) + typ = TYPE_MAP + else: + raise UnpackValueError("Unknown header: 0x%x" % b) + return typ, n, obj + + def _unpack(self, execute=EX_CONSTRUCT): + typ, n, obj = self._read_header(execute) + + if execute == EX_READ_ARRAY_HEADER: + if typ != TYPE_ARRAY: + raise UnpackValueError("Expected array") + return n + if execute == EX_READ_MAP_HEADER: + if typ != TYPE_MAP: + raise UnpackValueError("Expected map") + return n + # TODO should we eliminate the recursion? + if typ == TYPE_ARRAY: + if execute == EX_SKIP: + for i in xrange(n): + # TODO check whether we need to call `list_hook` + self._unpack(EX_SKIP) + return + ret = newlist_hint(n) + for i in xrange(n): + ret.append(self._unpack(EX_CONSTRUCT)) + if self._list_hook is not None: + ret = self._list_hook(ret) + # TODO is the interaction between `list_hook` and `use_list` ok? + return ret if self._use_list else tuple(ret) + if typ == TYPE_MAP: + if execute == EX_SKIP: + for i in xrange(n): + # TODO check whether we need to call hooks + self._unpack(EX_SKIP) + self._unpack(EX_SKIP) + return + if self._object_pairs_hook is not None: + ret = self._object_pairs_hook( + (self._unpack(EX_CONSTRUCT), + self._unpack(EX_CONSTRUCT)) + for _ in xrange(n)) + else: + ret = {} + for _ in xrange(n): + key = self._unpack(EX_CONSTRUCT) + ret[key] = self._unpack(EX_CONSTRUCT) + if self._object_hook is not None: + ret = self._object_hook(ret) + return ret + if execute == EX_SKIP: + return + if typ == TYPE_RAW: + if self._encoding is not None: + obj = obj.decode(self._encoding, self._unicode_errors) + elif self._raw: + obj = bytes(obj) + else: + obj = obj.decode('utf_8') + return obj + if typ == TYPE_EXT: + return self._ext_hook(n, bytes(obj)) + if typ == TYPE_BIN: + return bytes(obj) + assert typ == TYPE_IMMEDIATE + return obj + + def __iter__(self): + return self + + def __next__(self): + try: + ret = self._unpack(EX_CONSTRUCT) + self._consume() + return ret + except OutOfData: + self._consume() + raise StopIteration + + next = __next__ + + def skip(self, write_bytes=None): + self._unpack(EX_SKIP) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + + def unpack(self, write_bytes=None): + ret = self._unpack(EX_CONSTRUCT) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + return ret + + def read_array_header(self, write_bytes=None): + ret = self._unpack(EX_READ_ARRAY_HEADER) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + return ret + + def read_map_header(self, write_bytes=None): + ret = self._unpack(EX_READ_MAP_HEADER) + if write_bytes is not None: + warnings.warn("`write_bytes` option is deprecated. Use `.tell()` instead.", DeprecationWarning) + write_bytes(self._buffer[self._buf_checkpoint:self._buff_i]) + self._consume() + return ret + + def tell(self): + return self._stream_offset + + +class Packer(object): + """ + MessagePack Packer + + usage: + + packer = Packer() + astream.write(packer.pack(a)) + astream.write(packer.pack(b)) + + Packer's constructor has some keyword arguments: + + :param callable default: + Convert user type to builtin type that Packer supports. + See also simplejson's document. + + :param bool use_single_float: + Use single precision float type for float. (default: False) + + :param bool autoreset: + Reset buffer after each pack and return its content as `bytes`. (default: True). + If set this to false, use `bytes()` to get content and `.reset()` to clear buffer. + + :param bool use_bin_type: + Use bin type introduced in msgpack spec 2.0 for bytes. + It also enables str8 type for unicode. + + :param bool strict_types: + If set to true, types will be checked to be exact. Derived classes + from serializeable types will not be serialized and will be + treated as unsupported type and forwarded to default. + Additionally tuples will not be serialized as lists. + This is useful when trying to implement accurate serialization + for python types. + + :param str encoding: + (deprecated) Convert unicode to bytes with this encoding. (default: 'utf-8') + + :param str unicode_errors: + Error handler for encoding unicode. (default: 'strict') + """ + def __init__(self, default=None, encoding=None, unicode_errors=None, + use_single_float=False, autoreset=True, use_bin_type=False, + strict_types=False): + if encoding is None: + encoding = 'utf_8' + else: + warnings.warn( + "encoding is deprecated, Use raw=False instead.", + PendingDeprecationWarning) + + if unicode_errors is None: + unicode_errors = 'strict' + + self._strict_types = strict_types + self._use_float = use_single_float + self._autoreset = autoreset + self._use_bin_type = use_bin_type + self._encoding = encoding + self._unicode_errors = unicode_errors + self._buffer = StringIO() + if default is not None: + if not callable(default): + raise TypeError("default must be callable") + self._default = default + + def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, + check=isinstance, check_type_strict=_check_type_strict): + default_used = False + if self._strict_types: + check = check_type_strict + list_types = list + else: + list_types = (list, tuple) + while True: + if nest_limit < 0: + raise PackValueError("recursion limit exceeded") + if obj is None: + return self._buffer.write(b"\xc0") + if check(obj, bool): + if obj: + return self._buffer.write(b"\xc3") + return self._buffer.write(b"\xc2") + if check(obj, int_types): + if 0 <= obj < 0x80: + return self._buffer.write(struct.pack("B", obj)) + if -0x20 <= obj < 0: + return self._buffer.write(struct.pack("b", obj)) + if 0x80 <= obj <= 0xff: + return self._buffer.write(struct.pack("BB", 0xcc, obj)) + if -0x80 <= obj < 0: + return self._buffer.write(struct.pack(">Bb", 0xd0, obj)) + if 0xff < obj <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xcd, obj)) + if -0x8000 <= obj < -0x80: + return self._buffer.write(struct.pack(">Bh", 0xd1, obj)) + if 0xffff < obj <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xce, obj)) + if -0x80000000 <= obj < -0x8000: + return self._buffer.write(struct.pack(">Bi", 0xd2, obj)) + if 0xffffffff < obj <= 0xffffffffffffffff: + return self._buffer.write(struct.pack(">BQ", 0xcf, obj)) + if -0x8000000000000000 <= obj < -0x80000000: + return self._buffer.write(struct.pack(">Bq", 0xd3, obj)) + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = True + continue + raise PackOverflowError("Integer value out of range") + if check(obj, (bytes, bytearray)): + n = len(obj) + if n >= 2**32: + raise PackValueError("%s is too large" % type(obj).__name__) + self._pack_bin_header(n) + return self._buffer.write(obj) + if check(obj, Unicode): + if self._encoding is None: + raise TypeError( + "Can't encode unicode string: " + "no encoding is specified") + obj = obj.encode(self._encoding, self._unicode_errors) + n = len(obj) + if n >= 2**32: + raise PackValueError("String is too large") + self._pack_raw_header(n) + return self._buffer.write(obj) + if check(obj, memoryview): + n = len(obj) * obj.itemsize + if n >= 2**32: + raise PackValueError("Memoryview is too large") + self._pack_bin_header(n) + return self._buffer.write(obj) + if check(obj, float): + if self._use_float: + return self._buffer.write(struct.pack(">Bf", 0xca, obj)) + return self._buffer.write(struct.pack(">Bd", 0xcb, obj)) + if check(obj, ExtType): + code = obj.code + data = obj.data + assert isinstance(code, int) + assert isinstance(data, bytes) + L = len(data) + if L == 1: + self._buffer.write(b'\xd4') + elif L == 2: + self._buffer.write(b'\xd5') + elif L == 4: + self._buffer.write(b'\xd6') + elif L == 8: + self._buffer.write(b'\xd7') + elif L == 16: + self._buffer.write(b'\xd8') + elif L <= 0xff: + self._buffer.write(struct.pack(">BB", 0xc7, L)) + elif L <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xc8, L)) + else: + self._buffer.write(struct.pack(">BI", 0xc9, L)) + self._buffer.write(struct.pack("b", code)) + self._buffer.write(data) + return + if check(obj, list_types): + n = len(obj) + self._pack_array_header(n) + for i in xrange(n): + self._pack(obj[i], nest_limit - 1) + return + if check(obj, dict): + return self._pack_map_pairs(len(obj), dict_iteritems(obj), + nest_limit - 1) + if not default_used and self._default is not None: + obj = self._default(obj) + default_used = 1 + continue + raise TypeError("Cannot serialize %r" % (obj, )) + + def pack(self, obj): + try: + self._pack(obj) + except: + self._buffer = StringIO() # force reset + raise + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_map_pairs(self, pairs): + self._pack_map_pairs(len(pairs), pairs) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_array_header(self, n): + if n >= 2**32: + raise PackValueError + self._pack_array_header(n) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_map_header(self, n): + if n >= 2**32: + raise PackValueError + self._pack_map_header(n) + ret = self._buffer.getvalue() + if self._autoreset: + self._buffer = StringIO() + elif USING_STRINGBUILDER: + self._buffer = StringIO(ret) + return ret + + def pack_ext_type(self, typecode, data): + if not isinstance(typecode, int): + raise TypeError("typecode must have int type.") + if not 0 <= typecode <= 127: + raise ValueError("typecode should be 0-127") + if not isinstance(data, bytes): + raise TypeError("data must have bytes type") + L = len(data) + if L > 0xffffffff: + raise PackValueError("Too large data") + if L == 1: + self._buffer.write(b'\xd4') + elif L == 2: + self._buffer.write(b'\xd5') + elif L == 4: + self._buffer.write(b'\xd6') + elif L == 8: + self._buffer.write(b'\xd7') + elif L == 16: + self._buffer.write(b'\xd8') + elif L <= 0xff: + self._buffer.write(b'\xc7' + struct.pack('B', L)) + elif L <= 0xffff: + self._buffer.write(b'\xc8' + struct.pack('>H', L)) + else: + self._buffer.write(b'\xc9' + struct.pack('>I', L)) + self._buffer.write(struct.pack('B', typecode)) + self._buffer.write(data) + + def _pack_array_header(self, n): + if n <= 0x0f: + return self._buffer.write(struct.pack('B', 0x90 + n)) + if n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xdc, n)) + if n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xdd, n)) + raise PackValueError("Array is too large") + + def _pack_map_header(self, n): + if n <= 0x0f: + return self._buffer.write(struct.pack('B', 0x80 + n)) + if n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xde, n)) + if n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xdf, n)) + raise PackValueError("Dict is too large") + + def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT): + self._pack_map_header(n) + for (k, v) in pairs: + self._pack(k, nest_limit - 1) + self._pack(v, nest_limit - 1) + + def _pack_raw_header(self, n): + if n <= 0x1f: + self._buffer.write(struct.pack('B', 0xa0 + n)) + elif self._use_bin_type and n <= 0xff: + self._buffer.write(struct.pack('>BB', 0xd9, n)) + elif n <= 0xffff: + self._buffer.write(struct.pack(">BH", 0xda, n)) + elif n <= 0xffffffff: + self._buffer.write(struct.pack(">BI", 0xdb, n)) + else: + raise PackValueError('Raw is too large') + + def _pack_bin_header(self, n): + if not self._use_bin_type: + return self._pack_raw_header(n) + elif n <= 0xff: + return self._buffer.write(struct.pack('>BB', 0xc4, n)) + elif n <= 0xffff: + return self._buffer.write(struct.pack(">BH", 0xc5, n)) + elif n <= 0xffffffff: + return self._buffer.write(struct.pack(">BI", 0xc6, n)) + else: + raise PackValueError('Bin is too large') + + def bytes(self): + return self._buffer.getvalue() + + def reset(self): + self._buffer = StringIO() diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/__about__.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/__about__.py new file mode 100644 index 0000000..21fc6ce --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "18.0" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2018 %s" % __author__ diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/_compat.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/_structures.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/_structures.py new file mode 100644 index 0000000..e9fc4a0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/_structures.py @@ -0,0 +1,70 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + + +NegativeInfinity = NegativeInfinity() diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/markers.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/markers.py new file mode 100644 index 0000000..e5834ce --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from pip._vendor.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from pip._vendor.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from pip._vendor.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "<Marker({0!r})>".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/requirements.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/requirements.py new file mode 100644 index 0000000..d40bd8c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/requirements.py @@ -0,0 +1,130 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from pip._vendor.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from pip._vendor.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from pip._vendor.pyparsing import Literal as L # noqa +from pip._vendor.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPARATOR = SEMICOLON +MARKER = MARKER_SEPARATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd +# pyparsing isn't thread safe during initialization, so we do it eagerly, see +# issue #104 +REQUIREMENT.parseString("x[]") + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement("Parse error at \"{0!r}\": {1}".format( + requirement_string[e.loc:e.loc + 8], e.msg + )) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL: {0}".format(req.url)) + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "<Requirement({0!r})>".format(str(self)) diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/specifiers.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..4c79899 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(==|!=|<=|>=|<|>)) + \s* + (?P<version> + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(~=|==|!=|<=|>=|<|>|===)) + (?P<version> + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?<!==|!=|~=) # We have special cases for these + # operators so we want to make sure they + # don't match here. + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<SpecifierSet({0!r}{1})>".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/utils.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/utils.py new file mode 100644 index 0000000..4b94a82 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/utils.py @@ -0,0 +1,63 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + +from .version import InvalidVersion, Version + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() + + +def canonicalize_version(version): + """ + This is very similar to Version.__str__, but has one subtle differences + with the way it handles the release segment. + """ + + try: + version = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + + parts = [] + + # Epoch + if version.epoch != 0: + parts.append("{0}!".format(version.epoch)) + + # Release segment + # NB: This strips trailing '.0's to normalize + parts.append( + re.sub( + r'(\.0)+$', + '', + ".".join(str(x) for x in version.release) + ) + ) + + # Pre-release + if version.pre is not None: + parts.append("".join(str(x) for x in version.pre)) + + # Post-release + if version.post is not None: + parts.append(".post{0}".format(version.post)) + + # Development release + if version.dev is not None: + parts.append(".dev{0}".format(version.dev)) + + # Local version segment + if version.local is not None: + parts.append("+{0}".format(version.local)) + + return "".join(parts) diff --git a/winvenv/Lib/site-packages/pip/_vendor/packaging/version.py b/winvenv/Lib/site-packages/pip/_vendor/packaging/version.py new file mode 100644 index 0000000..6ed5cbb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/packaging/version.py @@ -0,0 +1,441 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "<LegacyVersion({0})>".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def epoch(self): + return -1 + + @property + def release(self): + return None + + @property + def pre(self): + return None + + @property + def post(self): + return None + + @property + def dev(self): + return None + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + @property + def is_devrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P<epoch>[0-9]+)!)? # epoch + (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment + (?P<pre> # pre-release + [-_\.]? + (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) + [-_\.]? + (?P<pre_n>[0-9]+)? + )? + (?P<post> # post release + (?:-(?P<post_n1>[0-9]+)) + | + (?: + [-_\.]? + (?P<post_l>post|rev|r) + [-_\.]? + (?P<post_n2>[0-9]+)? + ) + )? + (?P<dev> # dev release + [-_\.]? + (?P<dev_l>dev) + [-_\.]? + (?P<dev_n>[0-9]+)? + )? + ) + (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version +""" + + +class Version(_BaseVersion): + + _regex = re.compile( + r"^\s*" + VERSION_PATTERN + r"\s*$", + re.VERBOSE | re.IGNORECASE, + ) + + def __init__(self, version): + # Validate the version and parse it into pieces + match = self._regex.search(version) + if not match: + raise InvalidVersion("Invalid version: '{0}'".format(version)) + + # Store the parsed out pieces of the version + self._version = _Version( + epoch=int(match.group("epoch")) if match.group("epoch") else 0, + release=tuple(int(i) for i in match.group("release").split(".")), + pre=_parse_letter_version( + match.group("pre_l"), + match.group("pre_n"), + ), + post=_parse_letter_version( + match.group("post_l"), + match.group("post_n1") or match.group("post_n2"), + ), + dev=_parse_letter_version( + match.group("dev_l"), + match.group("dev_n"), + ), + local=_parse_local_version(match.group("local")), + ) + + # Generate a key which will be used for sorting + self._key = _cmpkey( + self._version.epoch, + self._version.release, + self._version.pre, + self._version.post, + self._version.dev, + self._version.local, + ) + + def __repr__(self): + return "<Version({0})>".format(repr(str(self))) + + def __str__(self): + parts = [] + + # Epoch + if self.epoch != 0: + parts.append("{0}!".format(self.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self.release)) + + # Pre-release + if self.pre is not None: + parts.append("".join(str(x) for x in self.pre)) + + # Post-release + if self.post is not None: + parts.append(".post{0}".format(self.post)) + + # Development release + if self.dev is not None: + parts.append(".dev{0}".format(self.dev)) + + # Local version segment + if self.local is not None: + parts.append("+{0}".format(self.local)) + + return "".join(parts) + + @property + def epoch(self): + return self._version.epoch + + @property + def release(self): + return self._version.release + + @property + def pre(self): + return self._version.pre + + @property + def post(self): + return self._version.post[1] if self._version.post else None + + @property + def dev(self): + return self._version.dev[1] if self._version.dev else None + + @property + def local(self): + if self._version.local: + return ".".join(str(x) for x in self._version.local) + else: + return None + + @property + def public(self): + return str(self).split("+", 1)[0] + + @property + def base_version(self): + parts = [] + + # Epoch + if self.epoch != 0: + parts.append("{0}!".format(self.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self.release)) + + return "".join(parts) + + @property + def is_prerelease(self): + return self.dev is not None or self.pre is not None + + @property + def is_postrelease(self): + return self.post is not None + + @property + def is_devrelease(self): + return self.dev is not None + + +def _parse_letter_version(letter, number): + if letter: + # We consider there to be an implicit 0 in a pre-release if there is + # not a numeral associated with it. + if number is None: + number = 0 + + # We normalize any letters to their lower case form + letter = letter.lower() + + # We consider some words to be alternate spellings of other words and + # in those cases we want to normalize the spellings to our preferred + # spelling. + if letter == "alpha": + letter = "a" + elif letter == "beta": + letter = "b" + elif letter in ["c", "pre", "preview"]: + letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" + + return letter, int(number) + if not letter and number: + # We assume if we are given a number, but we are not given a letter + # then this is using the implicit post release syntax (e.g. 1.0-1) + letter = "post" + + return letter, int(number) + + +_local_version_separators = re.compile(r"[\._-]") + + +def _parse_local_version(local): + """ + Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). + """ + if local is not None: + return tuple( + part.lower() if not part.isdigit() else int(part) + for part in _local_version_separators.split(local) + ) + + +def _cmpkey(epoch, release, pre, post, dev, local): + # When we compare a release version, we want to compare it with all of the + # trailing zeros removed. So we'll use a reverse the list, drop all the now + # leading zeros until we come to something non zero, then take the rest + # re-reverse it back into the correct order and make it a tuple and use + # that for our sorting key. + release = tuple( + reversed(list( + itertools.dropwhile( + lambda x: x == 0, + reversed(release), + ) + )) + ) + + # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. + # We'll do this by abusing the pre segment, but we _only_ want to do this + # if there is not a pre or a post segment. If we have one of those then + # the normal sorting rules will handle this case correctly. + if pre is None and post is None and dev is not None: + pre = -Infinity + # Versions without a pre-release (except as noted above) should sort after + # those with one. + elif pre is None: + pre = Infinity + + # Versions without a post segment should sort before those with one. + if post is None: + post = -Infinity + + # Versions without a development segment should sort after those with one. + if dev is None: + dev = Infinity + + if local is None: + # Versions without a local segment should sort before those with one. + local = -Infinity + else: + # Versions with a local segment need that segment parsed to implement + # the sorting rules in PEP440. + # - Alpha numeric segments sort before numeric segments + # - Alpha numeric segments sort lexicographically + # - Numeric segments sort numerically + # - Shorter versions sort before longer versions when the prefixes + # match exactly + local = tuple( + (i, "") if isinstance(i, int) else (-Infinity, i) + for i in local + ) + + return epoch, release, pre, post, dev, local diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/__init__.py new file mode 100644 index 0000000..8beedea --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/__init__.py @@ -0,0 +1,4 @@ +"""Wrappers to build Python packages using PEP 517 hooks +""" + +__version__ = '0.2' diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/_in_process.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/_in_process.py new file mode 100644 index 0000000..baa14d3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/_in_process.py @@ -0,0 +1,182 @@ +"""This is invoked in a subprocess to call the build backend hooks. + +It expects: +- Command line args: hook_name, control_dir +- Environment variable: PEP517_BUILD_BACKEND=entry.point:spec +- control_dir/input.json: + - {"kwargs": {...}} + +Results: +- control_dir/output.json + - {"return_val": ...} +""" +from glob import glob +from importlib import import_module +import os +from os.path import join as pjoin +import re +import shutil +import sys + +# This is run as a script, not a module, so it can't do a relative import +import compat + +def _build_backend(): + """Find and load the build backend""" + ep = os.environ['PEP517_BUILD_BACKEND'] + mod_path, _, obj_path = ep.partition(':') + obj = import_module(mod_path) + if obj_path: + for path_part in obj_path.split('.'): + obj = getattr(obj, path_part) + return obj + +def get_requires_for_build_wheel(config_settings): + """Invoke the optional get_requires_for_build_wheel hook + + Returns [] if the hook is not defined. + """ + backend = _build_backend() + try: + hook = backend.get_requires_for_build_wheel + except AttributeError: + return [] + else: + return hook(config_settings) + +def prepare_metadata_for_build_wheel(metadata_directory, config_settings): + """Invoke optional prepare_metadata_for_build_wheel + + Implements a fallback by building a wheel if the hook isn't defined. + """ + backend = _build_backend() + try: + hook = backend.prepare_metadata_for_build_wheel + except AttributeError: + return _get_wheel_metadata_from_wheel(backend, metadata_directory, + config_settings) + else: + return hook(metadata_directory, config_settings) + +WHEEL_BUILT_MARKER = 'PEP517_ALREADY_BUILT_WHEEL' + +def _dist_info_files(whl_zip): + """Identify the .dist-info folder inside a wheel ZipFile.""" + res = [] + for path in whl_zip.namelist(): + m = re.match(r'[^/\\]+-[^/\\]+\.dist-info/', path) + if m: + res.append(path) + if res: + return res + raise Exception("No .dist-info folder found in wheel") + +def _get_wheel_metadata_from_wheel(backend, metadata_directory, config_settings): + """Build a wheel and extract the metadata from it. + + Fallback for when the build backend does not define the 'get_wheel_metadata' + hook. + """ + from zipfile import ZipFile + whl_basename = backend.build_wheel(metadata_directory, config_settings) + with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), 'wb'): + pass # Touch marker file + + whl_file = os.path.join(metadata_directory, whl_basename) + with ZipFile(whl_file) as zipf: + dist_info = _dist_info_files(zipf) + zipf.extractall(path=metadata_directory, members=dist_info) + return dist_info[0].split('/')[0] + +def _find_already_built_wheel(metadata_directory): + """Check for a wheel already built during the get_wheel_metadata hook. + """ + if not metadata_directory: + return None + metadata_parent = os.path.dirname(metadata_directory) + if not os.path.isfile(pjoin(metadata_parent, WHEEL_BUILT_MARKER)): + return None + + whl_files = glob(os.path.join(metadata_parent, '*.whl')) + if not whl_files: + print('Found wheel built marker, but no .whl files') + return None + if len(whl_files) > 1: + print('Found multiple .whl files; unspecified behaviour. ' + 'Will call build_wheel.') + return None + + # Exactly one .whl file + return whl_files[0] + +def build_wheel(wheel_directory, config_settings, metadata_directory=None): + """Invoke the mandatory build_wheel hook. + + If a wheel was already built in the prepare_metadata_for_build_wheel fallback, this + will copy it rather than rebuilding the wheel. + """ + prebuilt_whl = _find_already_built_wheel(metadata_directory) + if prebuilt_whl: + shutil.copy2(prebuilt_whl, wheel_directory) + return os.path.basename(prebuilt_whl) + + return _build_backend().build_wheel(wheel_directory, config_settings, + metadata_directory) + + +def get_requires_for_build_sdist(config_settings): + """Invoke the optional get_requires_for_build_wheel hook + + Returns [] if the hook is not defined. + """ + backend = _build_backend() + try: + hook = backend.get_requires_for_build_sdist + except AttributeError: + return [] + else: + return hook(config_settings) + +class _DummyException(Exception): + """Nothing should ever raise this exception""" + +class GotUnsupportedOperation(Exception): + """For internal use when backend raises UnsupportedOperation""" + +def build_sdist(sdist_directory, config_settings): + """Invoke the mandatory build_sdist hook.""" + backend = _build_backend() + try: + return backend.build_sdist(sdist_directory, config_settings) + except getattr(backend, 'UnsupportedOperation', _DummyException): + raise GotUnsupportedOperation + +HOOK_NAMES = { + 'get_requires_for_build_wheel', + 'prepare_metadata_for_build_wheel', + 'build_wheel', + 'get_requires_for_build_sdist', + 'build_sdist', +} + +def main(): + if len(sys.argv) < 3: + sys.exit("Needs args: hook_name, control_dir") + hook_name = sys.argv[1] + control_dir = sys.argv[2] + if hook_name not in HOOK_NAMES: + sys.exit("Unknown hook: %s" % hook_name) + hook = globals()[hook_name] + + hook_input = compat.read_json(pjoin(control_dir, 'input.json')) + + json_out = {'unsupported': False, 'return_val': None} + try: + json_out['return_val'] = hook(**hook_input['kwargs']) + except GotUnsupportedOperation: + json_out['unsupported'] = True + + compat.write_json(json_out, pjoin(control_dir, 'output.json'), indent=2) + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/check.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/check.py new file mode 100644 index 0000000..c65d51c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/check.py @@ -0,0 +1,194 @@ +"""Check a project and backend by attempting to build using PEP 517 hooks. +""" +import argparse +import logging +import os +from os.path import isfile, join as pjoin +from pip._vendor.pytoml import TomlError, load as toml_load +import shutil +from subprocess import CalledProcessError +import sys +import tarfile +from tempfile import mkdtemp +import zipfile + +from .colorlog import enable_colourful_output +from .envbuild import BuildEnvironment +from .wrappers import Pep517HookCaller + +log = logging.getLogger(__name__) + +def check_build_sdist(hooks): + with BuildEnvironment() as env: + try: + env.pip_install(hooks.build_sys_requires) + log.info('Installed static build dependencies') + except CalledProcessError: + log.error('Failed to install static build dependencies') + return False + + try: + reqs = hooks.get_requires_for_build_sdist({}) + log.info('Got build requires: %s', reqs) + except: + log.error('Failure in get_requires_for_build_sdist', exc_info=True) + return False + + try: + env.pip_install(reqs) + log.info('Installed dynamic build dependencies') + except CalledProcessError: + log.error('Failed to install dynamic build dependencies') + return False + + td = mkdtemp() + log.info('Trying to build sdist in %s', td) + try: + try: + filename = hooks.build_sdist(td, {}) + log.info('build_sdist returned %r', filename) + except: + log.info('Failure in build_sdist', exc_info=True) + return False + + if not filename.endswith('.tar.gz'): + log.error("Filename %s doesn't have .tar.gz extension", filename) + return False + + path = pjoin(td, filename) + if isfile(path): + log.info("Output file %s exists", path) + else: + log.error("Output file %s does not exist", path) + return False + + if tarfile.is_tarfile(path): + log.info("Output file is a tar file") + else: + log.error("Output file is not a tar file") + return False + + finally: + shutil.rmtree(td) + + return True + +def check_build_wheel(hooks): + with BuildEnvironment() as env: + try: + env.pip_install(hooks.build_sys_requires) + log.info('Installed static build dependencies') + except CalledProcessError: + log.error('Failed to install static build dependencies') + return False + + try: + reqs = hooks.get_requires_for_build_wheel({}) + log.info('Got build requires: %s', reqs) + except: + log.error('Failure in get_requires_for_build_sdist', exc_info=True) + return False + + try: + env.pip_install(reqs) + log.info('Installed dynamic build dependencies') + except CalledProcessError: + log.error('Failed to install dynamic build dependencies') + return False + + td = mkdtemp() + log.info('Trying to build wheel in %s', td) + try: + try: + filename = hooks.build_wheel(td, {}) + log.info('build_wheel returned %r', filename) + except: + log.info('Failure in build_wheel', exc_info=True) + return False + + if not filename.endswith('.whl'): + log.error("Filename %s doesn't have .whl extension", filename) + return False + + path = pjoin(td, filename) + if isfile(path): + log.info("Output file %s exists", path) + else: + log.error("Output file %s does not exist", path) + return False + + if zipfile.is_zipfile(path): + log.info("Output file is a zip file") + else: + log.error("Output file is not a zip file") + return False + + finally: + shutil.rmtree(td) + + return True + + +def check(source_dir): + pyproject = pjoin(source_dir, 'pyproject.toml') + if isfile(pyproject): + log.info('Found pyproject.toml') + else: + log.error('Missing pyproject.toml') + return False + + try: + with open(pyproject) as f: + pyproject_data = toml_load(f) + # Ensure the mandatory data can be loaded + buildsys = pyproject_data['build-system'] + requires = buildsys['requires'] + backend = buildsys['build-backend'] + log.info('Loaded pyproject.toml') + except (TomlError, KeyError): + log.error("Invalid pyproject.toml", exc_info=True) + return False + + hooks = Pep517HookCaller(source_dir, backend) + + sdist_ok = check_build_sdist(hooks) + wheel_ok = check_build_wheel(hooks) + + if not sdist_ok: + log.warning('Sdist checks failed; scroll up to see') + if not wheel_ok: + log.warning('Wheel checks failed') + + return sdist_ok + + +def main(argv=None): + ap = argparse.ArgumentParser() + ap.add_argument('source_dir', + help="A directory containing pyproject.toml") + args = ap.parse_args(argv) + + enable_colourful_output() + + ok = check(args.source_dir) + + if ok: + print(ansi('Checks passed', 'green')) + else: + print(ansi('Checks failed', 'red')) + sys.exit(1) + +ansi_codes = { + 'reset': '\x1b[0m', + 'bold': '\x1b[1m', + 'red': '\x1b[31m', + 'green': '\x1b[32m', +} +def ansi(s, attr): + if os.name != 'nt' and sys.stdout.isatty(): + return ansi_codes[attr] + str(s) + ansi_codes['reset'] + else: + return str(s) + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/colorlog.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/colorlog.py new file mode 100644 index 0000000..26cf748 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/colorlog.py @@ -0,0 +1,110 @@ +"""Nicer log formatting with colours. + +Code copied from Tornado, Apache licensed. +""" +# Copyright 2012 Facebook +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import logging +import sys + +try: + import curses +except ImportError: + curses = None + +def _stderr_supports_color(): + color = False + if curses and hasattr(sys.stderr, 'isatty') and sys.stderr.isatty(): + try: + curses.setupterm() + if curses.tigetnum("colors") > 0: + color = True + except Exception: + pass + return color + +class LogFormatter(logging.Formatter): + """Log formatter with colour support + """ + DEFAULT_COLORS = { + logging.INFO: 2, # Green + logging.WARNING: 3, # Yellow + logging.ERROR: 1, # Red + logging.CRITICAL: 1, + } + + def __init__(self, color=True, datefmt=None): + r""" + :arg bool color: Enables color support. + :arg string fmt: Log message format. + It will be applied to the attributes dict of log records. The + text between ``%(color)s`` and ``%(end_color)s`` will be colored + depending on the level if color support is on. + :arg dict colors: color mappings from logging level to terminal color + code + :arg string datefmt: Datetime format. + Used for formatting ``(asctime)`` placeholder in ``prefix_fmt``. + .. versionchanged:: 3.2 + Added ``fmt`` and ``datefmt`` arguments. + """ + logging.Formatter.__init__(self, datefmt=datefmt) + self._colors = {} + if color and _stderr_supports_color(): + # The curses module has some str/bytes confusion in + # python3. Until version 3.2.3, most methods return + # bytes, but only accept strings. In addition, we want to + # output these strings with the logging module, which + # works with unicode strings. The explicit calls to + # unicode() below are harmless in python2 but will do the + # right conversion in python 3. + fg_color = (curses.tigetstr("setaf") or + curses.tigetstr("setf") or "") + if (3, 0) < sys.version_info < (3, 2, 3): + fg_color = str(fg_color, "ascii") + + for levelno, code in self.DEFAULT_COLORS.items(): + self._colors[levelno] = str(curses.tparm(fg_color, code), "ascii") + self._normal = str(curses.tigetstr("sgr0"), "ascii") + + scr = curses.initscr() + self.termwidth = scr.getmaxyx()[1] + curses.endwin() + else: + self._normal = '' + # Default width is usually 80, but too wide is worse than too narrow + self.termwidth = 70 + + def formatMessage(self, record): + l = len(record.message) + right_text = '{initial}-{name}'.format(initial=record.levelname[0], + name=record.name) + if l + len(right_text) < self.termwidth: + space = ' ' * (self.termwidth - (l + len(right_text))) + else: + space = ' ' + + if record.levelno in self._colors: + start_color = self._colors[record.levelno] + end_color = self._normal + else: + start_color = end_color = '' + + return record.message + space + start_color + right_text + end_color + +def enable_colourful_output(level=logging.INFO): + handler = logging.StreamHandler() + handler.setFormatter(LogFormatter()) + logging.root.addHandler(handler) + logging.root.setLevel(level) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/compat.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/compat.py new file mode 100644 index 0000000..01c66fc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/compat.py @@ -0,0 +1,23 @@ +"""Handle reading and writing JSON in UTF-8, on Python 3 and 2.""" +import json +import sys + +if sys.version_info[0] >= 3: + # Python 3 + def write_json(obj, path, **kwargs): + with open(path, 'w', encoding='utf-8') as f: + json.dump(obj, f, **kwargs) + + def read_json(path): + with open(path, 'r', encoding='utf-8') as f: + return json.load(f) + +else: + # Python 2 + def write_json(obj, path, **kwargs): + with open(path, 'wb') as f: + json.dump(obj, f, encoding='utf-8', **kwargs) + + def read_json(path): + with open(path, 'rb') as f: + return json.load(f) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/envbuild.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/envbuild.py new file mode 100644 index 0000000..c264f46 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/envbuild.py @@ -0,0 +1,150 @@ +"""Build wheels/sdists by installing build deps to a temporary environment. +""" + +import os +import logging +from pip._vendor import pytoml +import shutil +from subprocess import check_call +import sys +from sysconfig import get_paths +from tempfile import mkdtemp + +from .wrappers import Pep517HookCaller + +log = logging.getLogger(__name__) + +def _load_pyproject(source_dir): + with open(os.path.join(source_dir, 'pyproject.toml')) as f: + pyproject_data = pytoml.load(f) + buildsys = pyproject_data['build-system'] + return buildsys['requires'], buildsys['build-backend'] + + +class BuildEnvironment(object): + """Context manager to install build deps in a simple temporary environment + + Based on code I wrote for pip, which is MIT licensed. + """ + # Copyright (c) 2008-2016 The pip developers (see AUTHORS.txt file) + # + # 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. + + path = None + + def __init__(self, cleanup=True): + self._cleanup = cleanup + + def __enter__(self): + self.path = mkdtemp(prefix='pep517-build-env-') + log.info('Temporary build environment: %s', self.path) + + self.save_path = os.environ.get('PATH', None) + self.save_pythonpath = os.environ.get('PYTHONPATH', None) + + install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix' + install_dirs = get_paths(install_scheme, vars={ + 'base': self.path, + 'platbase': self.path, + }) + + scripts = install_dirs['scripts'] + if self.save_path: + os.environ['PATH'] = scripts + os.pathsep + self.save_path + else: + os.environ['PATH'] = scripts + os.pathsep + os.defpath + + if install_dirs['purelib'] == install_dirs['platlib']: + lib_dirs = install_dirs['purelib'] + else: + lib_dirs = install_dirs['purelib'] + os.pathsep + \ + install_dirs['platlib'] + if self.save_pythonpath: + os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ + self.save_pythonpath + else: + os.environ['PYTHONPATH'] = lib_dirs + + return self + + def pip_install(self, reqs): + """Install dependencies into this env by calling pip in a subprocess""" + if not reqs: + return + log.info('Calling pip to install %s', reqs) + check_call([sys.executable, '-m', 'pip', 'install', '--ignore-installed', + '--prefix', self.path] + list(reqs)) + + def __exit__(self, exc_type, exc_val, exc_tb): + if self._cleanup and (self.path is not None) and os.path.isdir(self.path): + shutil.rmtree(self.path) + + if self.save_path is None: + os.environ.pop('PATH', None) + else: + os.environ['PATH'] = self.save_path + + if self.save_pythonpath is None: + os.environ.pop('PYTHONPATH', None) + else: + os.environ['PYTHONPATH'] = self.save_pythonpath + +def build_wheel(source_dir, wheel_dir, config_settings=None): + """Build a wheel from a source directory using PEP 517 hooks. + + :param str source_dir: Source directory containing pyproject.toml + :param str wheel_dir: Target directory to create wheel in + :param dict config_settings: Options to pass to build backend + + This is a blocking function which will run pip in a subprocess to install + build requirements. + """ + if config_settings is None: + config_settings = {} + requires, backend = _load_pyproject(source_dir) + hooks = Pep517HookCaller(source_dir, backend) + + with BuildEnvironment() as env: + env.pip_install(requires) + reqs = hooks.get_requires_for_build_wheel(config_settings) + env.pip_install(reqs) + return hooks.build_wheel(wheel_dir, config_settings) + + +def build_sdist(source_dir, sdist_dir, config_settings=None): + """Build an sdist from a source directory using PEP 517 hooks. + + :param str source_dir: Source directory containing pyproject.toml + :param str sdist_dir: Target directory to place sdist in + :param dict config_settings: Options to pass to build backend + + This is a blocking function which will run pip in a subprocess to install + build requirements. + """ + if config_settings is None: + config_settings = {} + requires, backend = _load_pyproject(source_dir) + hooks = Pep517HookCaller(source_dir, backend) + + with BuildEnvironment() as env: + env.pip_install(requires) + reqs = hooks.get_requires_for_build_sdist(config_settings) + env.pip_install(reqs) + return hooks.build_sdist(sdist_dir, config_settings) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pep517/wrappers.py b/winvenv/Lib/site-packages/pip/_vendor/pep517/wrappers.py new file mode 100644 index 0000000..28260f3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pep517/wrappers.py @@ -0,0 +1,134 @@ +from contextlib import contextmanager +import os +from os.path import dirname, abspath, join as pjoin +import shutil +from subprocess import check_call +import sys +from tempfile import mkdtemp + +from . import compat + +_in_proc_script = pjoin(dirname(abspath(__file__)), '_in_process.py') + +@contextmanager +def tempdir(): + td = mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + +class UnsupportedOperation(Exception): + """May be raised by build_sdist if the backend indicates that it can't.""" + +class Pep517HookCaller(object): + """A wrapper around a source directory to be built with a PEP 517 backend. + + source_dir : The path to the source directory, containing pyproject.toml. + backend : The build backend spec, as per PEP 517, from pyproject.toml. + """ + def __init__(self, source_dir, build_backend): + self.source_dir = abspath(source_dir) + self.build_backend = build_backend + + def get_requires_for_build_wheel(self, config_settings=None): + """Identify packages required for building a wheel + + Returns a list of dependency specifications, e.g.: + ["wheel >= 0.25", "setuptools"] + + This does not include requirements specified in pyproject.toml. + It returns the result of calling the equivalently named hook in a + subprocess. + """ + return self._call_hook('get_requires_for_build_wheel', { + 'config_settings': config_settings + }) + + def prepare_metadata_for_build_wheel(self, metadata_directory, config_settings=None): + """Prepare a *.dist-info folder with metadata for this project. + + Returns the name of the newly created folder. + + If the build backend defines a hook with this name, it will be called + in a subprocess. If not, the backend will be asked to build a wheel, + and the dist-info extracted from that. + """ + return self._call_hook('prepare_metadata_for_build_wheel', { + 'metadata_directory': abspath(metadata_directory), + 'config_settings': config_settings, + }) + + def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None): + """Build a wheel from this project. + + Returns the name of the newly created file. + + In general, this will call the 'build_wheel' hook in the backend. + However, if that was previously called by + 'prepare_metadata_for_build_wheel', and the same metadata_directory is + used, the previously built wheel will be copied to wheel_directory. + """ + if metadata_directory is not None: + metadata_directory = abspath(metadata_directory) + return self._call_hook('build_wheel', { + 'wheel_directory': abspath(wheel_directory), + 'config_settings': config_settings, + 'metadata_directory': metadata_directory, + }) + + def get_requires_for_build_sdist(self, config_settings=None): + """Identify packages required for building a wheel + + Returns a list of dependency specifications, e.g.: + ["setuptools >= 26"] + + This does not include requirements specified in pyproject.toml. + It returns the result of calling the equivalently named hook in a + subprocess. + """ + return self._call_hook('get_requires_for_build_sdist', { + 'config_settings': config_settings + }) + + def build_sdist(self, sdist_directory, config_settings=None): + """Build an sdist from this project. + + Returns the name of the newly created file. + + This calls the 'build_sdist' backend hook in a subprocess. + """ + return self._call_hook('build_sdist', { + 'sdist_directory': abspath(sdist_directory), + 'config_settings': config_settings, + }) + + + def _call_hook(self, hook_name, kwargs): + env = os.environ.copy() + + # On Python 2, pytoml returns Unicode values (which is correct) but the + # environment passed to check_call needs to contain string values. We + # convert here by encoding using ASCII (the backend can only contain + # letters, digits and _, . and : characters, and will be used as a + # Python identifier, so non-ASCII content is wrong on Python 2 in + # any case). + if sys.version_info[0] == 2: + build_backend = self.build_backend.encode('ASCII') + else: + build_backend = self.build_backend + + env['PEP517_BUILD_BACKEND'] = build_backend + with tempdir() as td: + compat.write_json({'kwargs': kwargs}, pjoin(td, 'input.json'), + indent=2) + + # Run the hook in a subprocess + check_call([sys.executable, _in_proc_script, hook_name, td], + cwd=self.source_dir, env=env) + + data = compat.read_json(pjoin(td, 'output.json')) + if data.get('unsupported'): + raise UnsupportedOperation + return data['return_val'] + diff --git a/winvenv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py new file mode 100644 index 0000000..0b432f6 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py @@ -0,0 +1,3149 @@ +# coding: utf-8 +""" +Package resource API +-------------------- + +A resource is a logical file contained within a package, or a logical +subdirectory thereof. The package resource API expects resource names +to have their path parts separated with ``/``, *not* whatever the local +path separator is. Do not use os.path operations to manipulate resource +names being passed into the API. + +The package resource API is designed to work with normal filesystem packages, +.egg files, and unpacked .egg files. It can also work in a limited way with +.zip files and with custom PEP 302 loaders that support the ``get_data()`` +method. +""" + +from __future__ import absolute_import + +import sys +import os +import io +import time +import re +import types +import zipfile +import zipimport +import warnings +import stat +import functools +import pkgutil +import operator +import platform +import collections +import plistlib +import email.parser +import errno +import tempfile +import textwrap +import itertools +import inspect +from pkgutil import get_importer + +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + +try: + FileExistsError +except NameError: + FileExistsError = OSError + +from pip._vendor import six +from pip._vendor.six.moves import urllib, map, filter + +# capture these to bypass sandboxing +from os import utime +try: + from os import mkdir, rename, unlink + WRITE_SUPPORT = True +except ImportError: + # no write support, probably under GAE + WRITE_SUPPORT = False + +from os import open as os_open +from os.path import isdir, split + +try: + import importlib.machinery as importlib_machinery + # access attribute to force import under delayed import mechanisms. + importlib_machinery.__name__ +except ImportError: + importlib_machinery = None + +from . import py31compat +from pip._vendor import appdirs +from pip._vendor import packaging +__import__('pip._vendor.packaging.version') +__import__('pip._vendor.packaging.specifiers') +__import__('pip._vendor.packaging.requirements') +__import__('pip._vendor.packaging.markers') + + +__metaclass__ = type + + +if (3, 0) < sys.version_info < (3, 4): + raise RuntimeError("Python 3.4 or later is required") + +if six.PY2: + # Those builtin exceptions are only defined in Python 3 + PermissionError = None + NotADirectoryError = None + +# declare some globals that will be defined later to +# satisfy the linters. +require = None +working_set = None +add_activation_listener = None +resources_stream = None +cleanup_resources = None +resource_dir = None +resource_stream = None +set_extraction_path = None +resource_isdir = None +resource_string = None +iter_entry_points = None +resource_listdir = None +resource_filename = None +resource_exists = None +_distribution_finders = None +_namespace_handlers = None +_namespace_packages = None + + +class PEP440Warning(RuntimeWarning): + """ + Used when there is an issue with a version or specifier not complying with + PEP 440. + """ + + +def parse_version(v): + try: + return packaging.version.Version(v) + except packaging.version.InvalidVersion: + return packaging.version.LegacyVersion(v) + + +_state_vars = {} + + +def _declare_state(vartype, **kw): + globals().update(kw) + _state_vars.update(dict.fromkeys(kw, vartype)) + + +def __getstate__(): + state = {} + g = globals() + for k, v in _state_vars.items(): + state[k] = g['_sget_' + v](g[k]) + return state + + +def __setstate__(state): + g = globals() + for k, v in state.items(): + g['_sset_' + _state_vars[k]](k, g[k], v) + return state + + +def _sget_dict(val): + return val.copy() + + +def _sset_dict(key, ob, state): + ob.clear() + ob.update(state) + + +def _sget_object(val): + return val.__getstate__() + + +def _sset_object(key, ob, state): + ob.__setstate__(state) + + +_sget_none = _sset_none = lambda *args: None + + +def get_supported_platform(): + """Return this platform's maximum compatible version. + + distutils.util.get_platform() normally reports the minimum version + of Mac OS X that would be required to *use* extensions produced by + distutils. But what we want when checking compatibility is to know the + version of Mac OS X that we are *running*. To allow usage of packages that + explicitly require a newer version of Mac OS X, we must also know the + current version of the OS. + + If this condition occurs for any other platform with a version in its + platform strings, this function should be extended accordingly. + """ + plat = get_build_platform() + m = macosVersionString.match(plat) + if m is not None and sys.platform == "darwin": + try: + plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + except ValueError: + # not Mac OS X + pass + return plat + + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'iter_entry_points', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'Environment', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError', 'VersionConflict', 'DistributionNotFound', + 'UnknownExtra', 'ExtractionError', + + # Warnings + 'PEP440Warning', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Deprecated/backward compatibility only + 'run_main', 'AvailableDistributions', +] + + +class ResolutionError(Exception): + """Abstract base for dependency resolution errors""" + + def __repr__(self): + return self.__class__.__name__ + repr(self.args) + + +class VersionConflict(ResolutionError): + """ + An already-installed version conflicts with the requested version. + + Should be initialized with the installed Distribution and the requested + Requirement. + """ + + _template = "{self.dist} is installed but {self.req} is required" + + @property + def dist(self): + return self.args[0] + + @property + def req(self): + return self.args[1] + + def report(self): + return self._template.format(**locals()) + + def with_context(self, required_by): + """ + If required_by is non-empty, return a version of self that is a + ContextualVersionConflict. + """ + if not required_by: + return self + args = self.args + (required_by,) + return ContextualVersionConflict(*args) + + +class ContextualVersionConflict(VersionConflict): + """ + A VersionConflict that accepts a third parameter, the set of the + requirements that required the installed Distribution. + """ + + _template = VersionConflict._template + ' by {self.required_by}' + + @property + def required_by(self): + return self.args[2] + + +class DistributionNotFound(ResolutionError): + """A requested distribution was not found""" + + _template = ("The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}") + + @property + def req(self): + return self.args[0] + + @property + def requirers(self): + return self.args[1] + + @property + def requirers_str(self): + if not self.requirers: + return 'the application' + return ', '.join(self.requirers) + + def report(self): + return self._template.format(**locals()) + + def __str__(self): + return self.report() + + +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" + + +_provider_factories = {} + +PY_MAJOR = sys.version[:3] +EGG_DIST = 3 +BINARY_DIST = 2 +SOURCE_DIST = 1 +CHECKOUT_DIST = 0 +DEVELOP_DIST = -1 + + +def register_loader_type(loader_type, provider_factory): + """Register `provider_factory` to make providers for `loader_type` + + `loader_type` is the type or class of a PEP 302 ``module.__loader__``, + and `provider_factory` is a function that, passed a *module* object, + returns an ``IResourceProvider`` for that module. + """ + _provider_factories[loader_type] = provider_factory + + +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq, Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] + try: + module = sys.modules[moduleOrReq] + except KeyError: + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] + loader = getattr(module, '__loader__', None) + return _find_adapter(_provider_factories, loader)(module) + + +def _macosx_vers(_cache=[]): + if not _cache: + version = platform.mac_ver()[0] + # fallback for MacPorts + if version == '': + plist = '/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists(plist): + if hasattr(plistlib, 'readPlist'): + plist_content = plistlib.readPlist(plist) + if 'ProductVersion' in plist_content: + version = plist_content['ProductVersion'] + + _cache.append(version.split('.')) + return _cache[0] + + +def _macosx_arch(machine): + return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) + + +def get_build_platform(): + """Return this platform's string for platform-specific distributions + + XXX Currently this is the same as ``distutils.util.get_platform()``, but it + needs some hacks for Linux and Mac OS X. + """ + from sysconfig import get_platform + + plat = get_platform() + if sys.platform == "darwin" and not plat.startswith('macosx-'): + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d-%s" % ( + int(version[0]), int(version[1]), + _macosx_arch(machine), + ) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + return plat + + +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +# XXX backward compat +get_platform = get_build_platform + + +def compatible_platforms(provided, required): + """Can code for the `provided` platform run on the `required` platform? + + Returns true if either platform is ``None``, or the platforms are equal. + + XXX Needs compatibility checks for Linux and other unixy OSes. + """ + if provided is None or required is None or provided == required: + # easy case + return True + + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + return True + # egg isn't macosx or legacy darwin + return False + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(3) != reqMac.group(3): + return False + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here + return False + + +def run_script(dist_spec, script_name): + """Locate distribution `dist_spec` and run its `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].run_script(script_name, ns) + + +# backward compatibility +run_main = run_script + + +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist, six.string_types): + dist = Requirement.parse(dist) + if isinstance(dist, Requirement): + dist = get_provider(dist) + if not isinstance(dist, Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist + + +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) + + +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) + + +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) + + +class IMetadataProvider: + def has_metadata(name): + """Does the package's distribution contain the named metadata?""" + + def get_metadata(name): + """The named metadata resource as a string""" + + def get_metadata_lines(name): + """Yield named metadata resource as list of non-blank non-comment lines + + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" + + def metadata_isdir(name): + """Is the named metadata a directory? (like ``os.path.isdir()``)""" + + def metadata_listdir(name): + """List of metadata names in the directory (like ``os.listdir()``)""" + + def run_script(script_name, namespace): + """Execute the named script in the supplied namespace dictionary""" + + +class IResourceProvider(IMetadataProvider): + """An object that provides access to package resources""" + + def get_resource_filename(manager, resource_name): + """Return a true filesystem path for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_stream(manager, resource_name): + """Return a readable file-like object for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_string(manager, resource_name): + """Return a string containing the contents of `resource_name` + + `manager` must be an ``IResourceManager``""" + + def has_resource(resource_name): + """Does the package contain the named resource?""" + + def resource_isdir(resource_name): + """Is the named resource a directory? (like ``os.path.isdir()``)""" + + def resource_listdir(resource_name): + """List of resource names in the directory (like ``os.listdir()``)""" + + +class WorkingSet: + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + @classmethod + def _build_master(cls): + """ + Prepare the master working set. + """ + ws = cls() + try: + from __main__ import __requires__ + except ImportError: + # The main program does not list any requirements + return ws + + # ensure the requirements are met + try: + ws.require(__requires__) + except VersionConflict: + return cls._build_from_requirements(__requires__) + + return ws + + @classmethod + def _build_from_requirements(cls, req_spec): + """ + Build a working set from a requirement spec. Rewrites sys.path. + """ + # try it without defaults already on sys.path + # by starting with an empty path + ws = cls([]) + reqs = parse_requirements(req_spec) + dists = ws.resolve(reqs, Environment()) + for dist in dists: + ws.add(dist) + + # add any missing entries from sys.path + for entry in sys.path: + if entry not in ws.entries: + ws.add_entry(entry) + + # then copy back to sys.path + sys.path[:] = ws.entries + return ws + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry, True)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, True): + self.add(dist, entry, False) + + def __contains__(self, dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + # XXX add more info + raise VersionConflict(dist, req) + return dist + + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` + + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + return ( + entry + for dist in self + for entry in dist.get_entry_map(group).values() + if name is None or name == entry.name + ) + + def run_script(self, requires, script_name): + """Locate distribution for `requires` and run `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + self.require(requires)[0].run_script(script_name, ns) + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + seen = {} + for item in self.entries: + if item not in self.entry_keys: + # workaround a cache issue + continue + + for key in self.entry_keys[item]: + if key not in seen: + seen[key] = 1 + yield self.by_key[key] + + def add(self, dist, entry=None, insert=True, replace=False): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set, unless `replace=True`. + If it's added, any callbacks registered with the ``subscribe()`` method + will be called. + """ + if insert: + dist.insert_on(self.entries, entry, replace=replace) + + if entry is None: + entry = dist.location + keys = self.entry_keys.setdefault(entry, []) + keys2 = self.entry_keys.setdefault(dist.location, []) + if not replace and dist.key in self.by_key: + # ignore hidden distros + return + + self.by_key[dist.key] = dist + if dist.key not in keys: + keys.append(dist.key) + if dist.key not in keys2: + keys2.append(dist.key) + self._added_new(dist) + + def resolve(self, requirements, env=None, installer=None, + replace_conflicting=False, extras=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``Environment`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + + Unless `replace_conflicting=True`, raises a VersionConflict exception + if + any requirements are found on the path that have the correct name but + the wrong version. Otherwise, if an `installer` is supplied it will be + invoked to obtain the correct version of the requirement and activate + it. + + `extras` is a list of the extras to be used with these requirements. + This is important because extra requirements may look like `my_req; + extra = "my_extra"`, which would otherwise be interpreted as a purely + optional requirement. Instead, we want to be able to assert that these + requirements are truly required. + """ + + # set up the stack + requirements = list(requirements)[::-1] + # set of processed requirements + processed = {} + # key -> dist + best = {} + to_activate = [] + + req_extras = _ReqExtras() + + # Mapping of requirement to set of distributions that required it; + # useful for reporting info about conflicts. + required_by = collections.defaultdict(set) + + while requirements: + # process dependencies breadth-first + req = requirements.pop(0) + if req in processed: + # Ignore cyclic or redundant dependencies + continue + + if not req_extras.markers_pass(req, extras): + continue + + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None or (dist not in req and replace_conflicting): + ws = self + if env is None: + if dist is None: + env = Environment(self.entries) + else: + # Use an empty environment and workingset to avoid + # any further conflicts with the conflicting + # distribution + env = Environment([]) + ws = WorkingSet([]) + dist = best[req.key] = env.best_match( + req, ws, installer, + replace_conflicting=replace_conflicting + ) + if dist is None: + requirers = required_by.get(req, None) + raise DistributionNotFound(req, requirers) + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + dependent_req = required_by[req] + raise VersionConflict(dist, req).with_context(dependent_req) + + # push the new requirements onto the stack + new_requirements = dist.requires(req.extras)[::-1] + requirements.extend(new_requirements) + + # Register the new requirements needed by req + for new_requirement in new_requirements: + required_by[new_requirement].add(req.project_name) + req_extras[new_requirement] = req.extras + + processed[req] = True + + # return list of distros to activate + return to_activate + + def find_plugins( + self, plugin_env, full_env=None, installer=None, fallback=True): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + # add plugins+libs to sys.path + map(working_set.add, distributions) + # display errors + print('Could not load', errors) + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + # scan project names in alphabetic order + plugin_projects.sort() + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + # put all our entries in shadow_set + list(map(shadow_set.add, self)) + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError as v: + # save error info + error_info[dist] = v + if fallback: + # try the next older version of project + continue + else: + # give up on this project, keep going + break + + else: + list(map(shadow_set.add, resolvees)) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + def subscribe(self, callback, existing=True): + """Invoke `callback` for all distributions + + If `existing=True` (default), + call on all existing ones, as well. + """ + if callback in self.callbacks: + return + self.callbacks.append(callback) + if not existing: + return + for dist in self: + callback(dist) + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + def __getstate__(self): + return ( + self.entries[:], self.entry_keys.copy(), self.by_key.copy(), + self.callbacks[:] + ) + + def __setstate__(self, e_k_b_c): + entries, keys, by_key, callbacks = e_k_b_c + self.entries = entries[:] + self.entry_keys = keys.copy() + self.by_key = by_key.copy() + self.callbacks = callbacks[:] + + +class _ReqExtras(dict): + """ + Map each requirement to the extras that demanded it. + """ + + def markers_pass(self, req, extras=None): + """ + Evaluate markers for req against each extra that + demanded it. + + Return False if the req has a marker and fails + evaluation. Otherwise, return True. + """ + extra_evals = ( + req.marker.evaluate({'extra': extra}) + for extra in self.get(req, ()) + (extras or (None,)) + ) + return not req.marker or any(extra_evals) + + +class Environment: + """Searchable snapshot of distributions on a search path""" + + def __init__( + self, search_path=None, platform=get_supported_platform(), + python=PY_MAJOR): + """Snapshot distributions available on a search path + + Any distributions found on `search_path` are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. + + `platform` is an optional string specifying the name of the platform + that platform-specific distributions must be compatible with. If + unspecified, it defaults to the current platform. `python` is an + optional string naming the desired version of Python (e.g. ``'3.6'``); + it defaults to the current version. + + You may explicitly set `platform` (and/or `python`) to ``None`` if you + wish to map *all* distributions, not just those compatible with the + running platform or Python version. + """ + self._distmap = {} + self.platform = platform + self.python = python + self.scan(search_path) + + def can_add(self, dist): + """Is distribution `dist` acceptable for this environment? + + The distribution must match the platform and python version + requirements specified when this environment was created, or False + is returned. + """ + py_compat = ( + self.python is None + or dist.py_version is None + or dist.py_version == self.python + ) + return py_compat and compatible_platforms(dist.platform, self.platform) + + def remove(self, dist): + """Remove `dist` from the environment""" + self._distmap[dist.key].remove(dist) + + def scan(self, search_path=None): + """Scan `search_path` for distributions usable in this environment + + Any distributions found are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. Only distributions conforming to + the platform/python version defined at initialization are added. + """ + if search_path is None: + search_path = sys.path + + for item in search_path: + for dist in find_distributions(item): + self.add(dist) + + def __getitem__(self, project_name): + """Return a newest-to-oldest list of distributions for `project_name` + + Uses case-insensitive `project_name` comparison, assuming all the + project's distributions use their project's name converted to all + lowercase as their key. + + """ + distribution_key = project_name.lower() + return self._distmap.get(distribution_key, []) + + def add(self, dist): + """Add `dist` if we ``can_add()`` it and it has not already been added + """ + if self.can_add(dist) and dist.has_version(): + dists = self._distmap.setdefault(dist.key, []) + if dist not in dists: + dists.append(dist) + dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) + + def best_match( + self, req, working_set, installer=None, replace_conflicting=False): + """Find distribution best matching `req` and usable on `working_set` + + This calls the ``find(req)`` method of the `working_set` to see if a + suitable distribution is already active. (This may raise + ``VersionConflict`` if an unsuitable version of the project is already + active in the specified `working_set`.) If a suitable distribution + isn't active, this method returns the newest distribution in the + environment that meets the ``Requirement`` in `req`. If no suitable + distribution is found, and `installer` is supplied, then the result of + calling the environment's ``obtain(req, installer)`` method will be + returned. + """ + try: + dist = working_set.find(req) + except VersionConflict: + if not replace_conflicting: + raise + dist = None + if dist is not None: + return dist + for dist in self[req.key]: + if dist in req: + return dist + # try to download/install + return self.obtain(req, installer) + + def obtain(self, requirement, installer=None): + """Obtain a distribution matching `requirement` (e.g. via download) + + Obtain a distro that matches requirement (e.g. via download). In the + base ``Environment`` class, this routine just returns + ``installer(requirement)``, unless `installer` is None, in which case + None is returned instead. This method is a hook that allows subclasses + to attempt other ways of obtaining a distribution before falling back + to the `installer` argument.""" + if installer is not None: + return installer(requirement) + + def __iter__(self): + """Yield the unique project names of the available distributions""" + for key in self._distmap.keys(): + if self[key]: + yield key + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other, Distribution): + self.add(other) + elif isinstance(other, Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + +# XXX backward compatibility +AvailableDistributions = Environment + + +class ExtractionError(RuntimeError): + """An error occurred extracting a resource + + The following attributes are available from instances of this exception: + + manager + The resource manager that raised this exception + + cache_path + The base directory for resource extraction + + original_error + The exception instance that caused extraction to fail + """ + + +class ResourceManager: + """Manage resource extraction and packages""" + extraction_path = None + + def __init__(self): + self.cached_files = {} + + def resource_exists(self, package_or_requirement, resource_name): + """Does the named resource exist?""" + return get_provider(package_or_requirement).has_resource(resource_name) + + def resource_isdir(self, package_or_requirement, resource_name): + """Is the named resource an existing directory?""" + return get_provider(package_or_requirement).resource_isdir( + resource_name + ) + + def resource_filename(self, package_or_requirement, resource_name): + """Return a true filesystem path for specified resource""" + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name + ) + + def resource_stream(self, package_or_requirement, resource_name): + """Return a readable file-like object for specified resource""" + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name + ) + + def resource_string(self, package_or_requirement, resource_name): + """Return specified resource as a string""" + return get_provider(package_or_requirement).get_resource_string( + self, resource_name + ) + + def resource_listdir(self, package_or_requirement, resource_name): + """List the contents of the named resource directory""" + return get_provider(package_or_requirement).resource_listdir( + resource_name + ) + + def extraction_error(self): + """Give an error message for problems extracting file(s)""" + + old_exc = sys.exc_info()[1] + cache_path = self.extraction_path or get_default_cache() + + tmpl = textwrap.dedent(""" + Can't extract file(s) to egg cache + + The following error occurred while trying to extract file(s) + to the Python egg cache: + + {old_exc} + + The Python egg cache directory is currently set to: + + {cache_path} + + Perhaps your account does not have write access to this directory? + You can change the cache directory by setting the PYTHON_EGG_CACHE + environment variable to point to an accessible directory. + """).lstrip() + err = ExtractionError(tmpl.format(**locals())) + err.manager = self + err.cache_path = cache_path + err.original_error = old_exc + raise err + + def get_cache_path(self, archive_name, names=()): + """Return absolute location in cache for `archive_name` and `names` + + The parent directory of the resulting path will be created if it does + not already exist. `archive_name` should be the base filename of the + enclosing egg (which may not be the name of the enclosing zipfile!), + including its ".egg" extension. `names`, if provided, should be a + sequence of path name parts "under" the egg's extraction location. + + This method should only be called by resource providers that need to + obtain an extraction location, and only for names they intend to + extract, as it tracks the generated names for possible cleanup later. + """ + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name + '-tmp', *names) + try: + _bypass_ensure_directory(target_path) + except Exception: + self.extraction_error() + + self._warn_unsafe_extraction_path(extract_path) + + self.cached_files[target_path] = 1 + return target_path + + @staticmethod + def _warn_unsafe_extraction_path(path): + """ + If the default extraction path is overridden and set to an insecure + location, such as /tmp, it opens up an opportunity for an attacker to + replace an extracted file with an unauthorized payload. Warn the user + if a known insecure location is used. + + See Distribute #375 for more details. + """ + if os.name == 'nt' and not path.startswith(os.environ['windir']): + # On Windows, permissions are generally restrictive by default + # and temp directories are not writable by other users, so + # bypass the warning. + return + mode = os.stat(path).st_mode + if mode & stat.S_IWOTH or mode & stat.S_IWGRP: + msg = ( + "%s is writable by group/others and vulnerable to attack " + "when " + "used with get_resource_filename. Consider a more secure " + "location (set with .set_extraction_path or the " + "PYTHON_EGG_CACHE environment variable)." % path + ) + warnings.warn(msg, UserWarning) + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` + + This is where Mac header rewrites should be done; other platforms don't + have anything special they should do. + + Resource providers should call this method ONLY after successfully + extracting a compressed resource. They must NOT call it on resources + that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. + """ + + if os.name == 'posix': + # Make the resource executable + mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 + os.chmod(tempname, mode) + + def set_extraction_path(self, path): + """Set the base path where resources will be extracted to, if needed. + + If you do not call this routine before any extractions take place, the + path defaults to the return value of ``get_default_cache()``. (Which + is based on the ``PYTHON_EGG_CACHE`` environment variable, with various + platform-specific fallbacks. See that routine's documentation for more + details.) + + Resources are extracted to subdirectories of this path based upon + information given by the ``IResourceProvider``. You may set this to a + temporary directory, but then you must call ``cleanup_resources()`` to + delete the extracted files when done. There is no guarantee that + ``cleanup_resources()`` will be able to remove all extracted files. + + (Note: you may not change the extraction path for a given resource + manager once resources have been extracted, unless you first call + ``cleanup_resources()``.) + """ + if self.cached_files: + raise ValueError( + "Can't change extraction path, files already extracted" + ) + + self.extraction_path = path + + def cleanup_resources(self, force=False): + """ + Delete all extracted resource files and directories, returning a list + of the file and directory names that could not be successfully removed. + This function does not have any concurrency protection, so it should + generally only be called when the extraction path is a temporary + directory exclusive to a single process. This method is not + automatically called; you must call it explicitly or register it as an + ``atexit`` function if you wish to ensure cleanup of a temporary + directory used for extractions. + """ + # XXX + + +def get_default_cache(): + """ + Return the ``PYTHON_EGG_CACHE`` environment variable + or a platform-relevant user cache dir for an app + named "Python-Eggs". + """ + return ( + os.environ.get('PYTHON_EGG_CACHE') + or appdirs.user_cache_dir(appname='Python-Eggs') + ) + + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """ + Convert an arbitrary string to a standard version string + """ + try: + # normalize the version + return str(packaging.version.Version(version)) + except packaging.version.InvalidVersion: + version = version.replace(' ', '.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-', '_') + + +def invalid_marker(text): + """ + Validate text as a PEP 508 environment marker; return an exception + if invalid or False otherwise. + """ + try: + evaluate_marker(text) + except SyntaxError as e: + e.filename = None + e.lineno = None + return e + return False + + +def evaluate_marker(text, extra=None): + """ + Evaluate a PEP 508 environment marker. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. + + This implementation uses the 'pyparsing' module. + """ + try: + marker = packaging.markers.Marker(text) + return marker.evaluate() + except packaging.markers.InvalidMarker as e: + raise SyntaxError(e) + + +class NullProvider: + """Try to implement resources and metadata for arbitrary PEP 302 loaders""" + + egg_name = None + egg_info = None + loader = None + + def __init__(self, module): + self.loader = getattr(module, '__loader__', None) + self.module_path = os.path.dirname(getattr(module, '__file__', '')) + + def get_resource_filename(self, manager, resource_name): + return self._fn(self.module_path, resource_name) + + def get_resource_stream(self, manager, resource_name): + return io.BytesIO(self.get_resource_string(manager, resource_name)) + + def get_resource_string(self, manager, resource_name): + return self._get(self._fn(self.module_path, resource_name)) + + def has_resource(self, resource_name): + return self._has(self._fn(self.module_path, resource_name)) + + def has_metadata(self, name): + return self.egg_info and self._has(self._fn(self.egg_info, name)) + + def get_metadata(self, name): + if not self.egg_info: + return "" + value = self._get(self._fn(self.egg_info, name)) + return value.decode('utf-8') if six.PY3 else value + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + def resource_isdir(self, resource_name): + return self._isdir(self._fn(self.module_path, resource_name)) + + def metadata_isdir(self, name): + return self.egg_info and self._isdir(self._fn(self.egg_info, name)) + + def resource_listdir(self, resource_name): + return self._listdir(self._fn(self.module_path, resource_name)) + + def metadata_listdir(self, name): + if self.egg_info: + return self._listdir(self._fn(self.egg_info, name)) + return [] + + def run_script(self, script_name, namespace): + script = 'scripts/' + script_name + if not self.has_metadata(script): + raise ResolutionError( + "Script {script!r} not found in metadata at {self.egg_info!r}" + .format(**locals()), + ) + script_text = self.get_metadata(script).replace('\r\n', '\n') + script_text = script_text.replace('\r', '\n') + script_filename = self._fn(self.egg_info, script) + namespace['__file__'] = script_filename + if os.path.exists(script_filename): + source = open(script_filename).read() + code = compile(source, script_filename, 'exec') + exec(code, namespace, namespace) + else: + from linecache import cache + cache[script_filename] = ( + len(script_text), 0, script_text.split('\n'), script_filename + ) + script_code = compile(script_text, script_filename, 'exec') + exec(script_code, namespace, namespace) + + def _has(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _isdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _listdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _fn(self, base, resource_name): + if resource_name: + return os.path.join(base, *resource_name.split('/')) + return base + + def _get(self, path): + if hasattr(self.loader, 'get_data'): + return self.loader.get_data(path) + raise NotImplementedError( + "Can't perform this operation for loaders without 'get_data()'" + ) + + +register_loader_type(object, NullProvider) + + +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" + + def __init__(self, module): + NullProvider.__init__(self, module) + self._setup_prefix() + + def _setup_prefix(self): + # we assume here that our metadata may be nested inside a "basket" + # of multiple eggs; that's why we use module_path instead of .archive + path = self.module_path + old = None + while path != old: + if _is_egg_path(path): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path + break + old = path + path, base = os.path.split(path) + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + + def _isdir(self, path): + return os.path.isdir(path) + + def _listdir(self, path): + return os.listdir(path) + + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + + def _get(self, path): + with open(path, 'rb') as stream: + return stream.read() + + @classmethod + def _register(cls): + loader_names = 'SourceFileLoader', 'SourcelessFileLoader', + for name in loader_names: + loader_cls = getattr(importlib_machinery, name, type(None)) + register_loader_type(loader_cls, cls) + + +DefaultProvider._register() + + +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + + module_path = None + + _isdir = _has = lambda self, path: False + + def _get(self, path): + return '' + + def _listdir(self, path): + return [] + + def __init__(self): + pass + + +empty_provider = EmptyProvider() + + +class ZipManifests(dict): + """ + zip manifest builder + """ + + @classmethod + def build(cls, path): + """ + Build a dictionary similar to the zipimport directory + caches, except instead of tuples, store ZipInfo objects. + + Use a platform-specific path separator (os.sep) for the path keys + for compatibility with pypy on Windows. + """ + with zipfile.ZipFile(path) as zfile: + items = ( + ( + name.replace('/', os.sep), + zfile.getinfo(name), + ) + for name in zfile.namelist() + ) + return dict(items) + + load = build + + +class MemoizedZipManifests(ZipManifests): + """ + Memoized zipfile manifests. + """ + manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') + + def load(self, path): + """ + Load a manifest at path or return a suitable manifest already loaded. + """ + path = os.path.normpath(path) + mtime = os.stat(path).st_mtime + + if path not in self or self[path].mtime != mtime: + manifest = self.build(path) + self[path] = self.manifest_mod(manifest, mtime) + + return self[path].manifest + + +class ZipProvider(EggProvider): + """Resource support for zips and eggs""" + + eagers = None + _zip_manifests = MemoizedZipManifests() + + def __init__(self, module): + EggProvider.__init__(self, module) + self.zip_pre = self.loader.archive + os.sep + + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + fspath = fspath.rstrip(os.sep) + if fspath == self.loader.archive: + return '' + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.zip_pre) + ) + + def _parts(self, zip_path): + # Convert a zipfile subpath into an egg-relative path part list. + # pseudo-fs path + fspath = self.zip_pre + zip_path + if fspath.startswith(self.egg_root + os.sep): + return fspath[len(self.egg_root) + 1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.egg_root) + ) + + @property + def zipinfo(self): + return self._zip_manifests.load(self.loader.archive) + + def get_resource_filename(self, manager, resource_name): + if not self.egg_name: + raise NotImplementedError( + "resource_filename() only supported for .egg, not .zip" + ) + # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) + eagers = self._get_eager_resources() + if '/'.join(self._parts(zip_path)) in eagers: + for name in eagers: + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) + + @staticmethod + def _get_date_and_size(zip_stat): + size = zip_stat.file_size + # ymdhms+wday, yday, dst + date_time = zip_stat.date_time + (0, 0, -1) + # 1980 offset already done + timestamp = time.mktime(date_time) + return timestamp, size + + def _extract_resource(self, manager, zip_path): + + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + # return the extracted directory name + return os.path.dirname(last) + + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + + if not WRITE_SUPPORT: + raise IOError('"os.rename" and "os.unlink" are not supported ' + 'on this platform') + try: + + real_path = manager.get_cache_path( + self.egg_name, self._parts(zip_path) + ) + + if self._is_current(real_path, zip_path): + return real_path + + outf, tmpnam = _mkstemp( + ".$extract", + dir=os.path.dirname(real_path), + ) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + utime(tmpnam, (timestamp, timestamp)) + manager.postprocess(tmpnam, real_path) + + try: + rename(tmpnam, real_path) + + except os.error: + if os.path.isfile(real_path): + if self._is_current(real_path, zip_path): + # the file became current since it was checked above, + # so proceed. + return real_path + # Windows, del old file and retry + elif os.name == 'nt': + unlink(real_path) + rename(tmpnam, real_path) + return real_path + raise + + except os.error: + # report a user-friendly error + manager.extraction_error() + + return real_path + + def _is_current(self, file_path, zip_path): + """ + Return True if the file_path is current for this zip_path + """ + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + if not os.path.isfile(file_path): + return False + stat = os.stat(file_path) + if stat.st_size != size or stat.st_mtime != timestamp: + return False + # check that the contents match + zip_contents = self.loader.get_data(zip_path) + with open(file_path, 'rb') as f: + file_contents = f.read() + return zip_contents == file_contents + + def _get_eager_resources(self): + if self.eagers is None: + eagers = [] + for name in ('native_libs.txt', 'eager_resources.txt'): + if self.has_metadata(name): + eagers.extend(self.get_metadata_lines(name)) + self.eagers = eagers + return self.eagers + + def _index(self): + try: + return self._dirindex + except AttributeError: + ind = {} + for path in self.zipinfo: + parts = path.split(os.sep) + while parts: + parent = os.sep.join(parts[:-1]) + if parent in ind: + ind[parent].append(parts[-1]) + break + else: + ind[parent] = [parts.pop()] + self._dirindex = ind + return ind + + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() + + def _isdir(self, fspath): + return self._zipinfo_name(fspath) in self._index() + + def _listdir(self, fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) + + def _eager_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.egg_root, resource_name)) + + def _resource_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.module_path, resource_name)) + + +register_loader_type(zipimport.zipimporter, ZipProvider) + + +class FileMetadata(EmptyProvider): + """Metadata handler for standalone PKG-INFO files + + Usage:: + + metadata = FileMetadata("/path/to/PKG-INFO") + + This provider rejects all data and metadata requests except for PKG-INFO, + which is treated as existing, and will be the contents of the file at + the provided location. + """ + + def __init__(self, path): + self.path = path + + def has_metadata(self, name): + return name == 'PKG-INFO' and os.path.isfile(self.path) + + def get_metadata(self, name): + if name != 'PKG-INFO': + raise KeyError("No metadata except PKG-INFO is available") + + with io.open(self.path, encoding='utf-8', errors="replace") as f: + metadata = f.read() + self._warn_on_replacement(metadata) + return metadata + + def _warn_on_replacement(self, metadata): + # Python 2.7 compat for: replacement_char = '�' + replacement_char = b'\xef\xbf\xbd'.decode('utf-8') + if replacement_char in metadata: + tmpl = "{self.path} could not be properly decoded in UTF-8" + msg = tmpl.format(**locals()) + warnings.warn(msg) + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + +class PathMetadata(DefaultProvider): + """Metadata provider for egg directories + + Usage:: + + # Development eggs: + + egg_info = "/path/to/PackageName.egg-info" + base_dir = os.path.dirname(egg_info) + metadata = PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + dist = Distribution(basedir, project_name=dist_name, metadata=metadata) + + # Unpacked egg directories: + + egg_path = "/path/to/PackageName-ver-pyver-etc.egg" + metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) + dist = Distribution.from_filename(egg_path, metadata=metadata) + """ + + def __init__(self, path, egg_info): + self.module_path = path + self.egg_info = egg_info + + +class EggMetadata(ZipProvider): + """Metadata provider for .egg files""" + + def __init__(self, importer): + """Create a metadata provider from a zipimporter""" + + self.zip_pre = importer.archive + os.sep + self.loader = importer + if importer.prefix: + self.module_path = os.path.join(importer.archive, importer.prefix) + else: + self.module_path = importer.archive + self._setup_prefix() + + +_declare_state('dict', _distribution_finders={}) + + +def register_finder(importer_type, distribution_finder): + """Register `distribution_finder` to find distributions in sys.path items + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `distribution_finder` is a callable that, passed a path + item and the importer instance, yields ``Distribution`` instances found on + that path item. See ``pkg_resources.find_on_path`` for an example.""" + _distribution_finders[importer_type] = distribution_finder + + +def find_distributions(path_item, only=False): + """Yield distributions accessible via `path_item`""" + importer = get_importer(path_item) + finder = _find_adapter(_distribution_finders, importer) + return finder(importer, path_item, only) + + +def find_eggs_in_zip(importer, path_item, only=False): + """ + Find eggs in zip files; possibly multiple nested eggs. + """ + if importer.archive.endswith('.whl'): + # wheels are not supported with this finder + # they don't have PKG-INFO metadata, and won't ever contain eggs + return + metadata = EggMetadata(importer) + if metadata.has_metadata('PKG-INFO'): + yield Distribution.from_filename(path_item, metadata=metadata) + if only: + # don't yield nested distros + return + for subitem in metadata.resource_listdir('/'): + if _is_egg_path(subitem): + subpath = os.path.join(path_item, subitem) + dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) + for dist in dists: + yield dist + elif subitem.lower().endswith('.dist-info'): + subpath = os.path.join(path_item, subitem) + submeta = EggMetadata(zipimport.zipimporter(subpath)) + submeta.egg_info = subpath + yield Distribution.from_location(path_item, subitem, submeta) + + +register_finder(zipimport.zipimporter, find_eggs_in_zip) + + +def find_nothing(importer, path_item, only=False): + return () + + +register_finder(object, find_nothing) + + +def _by_version_descending(names): + """ + Given a list of filenames, return them in descending order + by version number. + + >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' + >>> _by_version_descending(names) + ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] + """ + def _by_version(name): + """ + Parse each component of the filename + """ + name, ext = os.path.splitext(name) + parts = itertools.chain(name.split('-'), [ext]) + return [packaging.version.parse(part) for part in parts] + + return sorted(names, key=_by_version, reverse=True) + + +def find_on_path(importer, path_item, only=False): + """Yield distributions accessible on a sys.path directory""" + path_item = _normalize_cached(path_item) + + if _is_unpacked_egg(path_item): + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item, 'EGG-INFO') + ) + ) + return + + entries = safe_listdir(path_item) + + # for performance, before sorting by version, + # screen entries for only those that will yield + # distributions + filtered = ( + entry + for entry in entries + if dist_factory(path_item, entry, only) + ) + + # scan for .egg and .egg-info in directory + path_item_entries = _by_version_descending(filtered) + for entry in path_item_entries: + fullpath = os.path.join(path_item, entry) + factory = dist_factory(path_item, entry, only) + for dist in factory(fullpath): + yield dist + + +def dist_factory(path_item, entry, only): + """ + Return a dist_factory for a path_item and entry + """ + lower = entry.lower() + is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) + return ( + distributions_from_metadata + if is_meta else + find_distributions + if not only and _is_egg_path(entry) else + resolve_egg_link + if not only and lower.endswith('.egg-link') else + NoDists() + ) + + +class NoDists: + """ + >>> bool(NoDists()) + False + + >>> list(NoDists()('anything')) + [] + """ + def __bool__(self): + return False + if six.PY2: + __nonzero__ = __bool__ + + def __call__(self, fullpath): + return iter(()) + + +def safe_listdir(path): + """ + Attempt to list contents of path, but suppress some exceptions. + """ + try: + return os.listdir(path) + except (PermissionError, NotADirectoryError): + pass + except OSError as e: + # Ignore the directory if does not exist, not a directory or + # permission denied + ignorable = ( + e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) + # Python 2 on Windows needs to be handled this way :( + or getattr(e, "winerror", None) == 267 + ) + if not ignorable: + raise + return () + + +def distributions_from_metadata(path): + root = os.path.dirname(path) + if os.path.isdir(path): + if len(os.listdir(path)) == 0: + # empty metadata dir; skip + return + metadata = PathMetadata(root, path) + else: + metadata = FileMetadata(path) + entry = os.path.basename(path) + yield Distribution.from_location( + root, entry, metadata, precedence=DEVELOP_DIST, + ) + + +def non_empty_lines(path): + """ + Yield non-empty lines from file at path + """ + with open(path) as f: + for line in f: + line = line.strip() + if line: + yield line + + +def resolve_egg_link(path): + """ + Given a path to an .egg-link, resolve distributions + present in the referenced path. + """ + referenced_paths = non_empty_lines(path) + resolved_paths = ( + os.path.join(os.path.dirname(path), ref) + for ref in referenced_paths + ) + dist_groups = map(find_distributions, resolved_paths) + return next(dist_groups, ()) + + +register_finder(pkgutil.ImpImporter, find_on_path) + +if hasattr(importlib_machinery, 'FileFinder'): + register_finder(importlib_machinery.FileFinder, find_on_path) + +_declare_state('dict', _namespace_handlers={}) +_declare_state('dict', _namespace_packages={}) + + +def register_namespace_handler(importer_type, namespace_handler): + """Register `namespace_handler` to declare namespace packages + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `namespace_handler` is a callable like this:: + + def namespace_handler(importer, path_entry, moduleName, module): + # return a path_entry to use for child packages + + Namespace handlers are only called if the importer object has already + agreed that it can handle the relevant path item, and they should only + return a subpath if the module __path__ does not already contain an + equivalent subpath. For an example namespace handler, see + ``pkg_resources.file_ns_handler``. + """ + _namespace_handlers[importer_type] = namespace_handler + + +def _handle_ns(packageName, path_item): + """Ensure that named package includes a subpath of path_item (if needed)""" + + importer = get_importer(path_item) + if importer is None: + return None + + # capture warnings due to #1111 + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + loader = importer.find_module(packageName) + + if loader is None: + return None + module = sys.modules.get(packageName) + if module is None: + module = sys.modules[packageName] = types.ModuleType(packageName) + module.__path__ = [] + _set_parent_ns(packageName) + elif not hasattr(module, '__path__'): + raise TypeError("Not a package:", packageName) + handler = _find_adapter(_namespace_handlers, importer) + subpath = handler(importer, path_item, packageName, module) + if subpath is not None: + path = module.__path__ + path.append(subpath) + loader.load_module(packageName) + _rebuild_mod_path(path, packageName, module) + return subpath + + +def _rebuild_mod_path(orig_path, package_name, module): + """ + Rebuild module.__path__ ensuring that all entries are ordered + corresponding to their sys.path order + """ + sys_path = [_normalize_cached(p) for p in sys.path] + + def safe_sys_path_index(entry): + """ + Workaround for #520 and #513. + """ + try: + return sys_path.index(entry) + except ValueError: + return float('inf') + + def position_in_sys_path(path): + """ + Return the ordinal of the path based on its position in sys.path + """ + path_parts = path.split(os.sep) + module_parts = package_name.count('.') + 1 + parts = path_parts[:-module_parts] + return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) + + new_path = sorted(orig_path, key=position_in_sys_path) + new_path = [_normalize_cached(p) for p in new_path] + + if isinstance(module.__path__, list): + module.__path__[:] = new_path + else: + module.__path__ = new_path + + +def declare_namespace(packageName): + """Declare that package 'packageName' is a namespace package""" + + _imp.acquire_lock() + try: + if packageName in _namespace_packages: + return + + path = sys.path + parent, _, _ = packageName.rpartition('.') + + if parent: + declare_namespace(parent) + if parent not in _namespace_packages: + __import__(parent) + try: + path = sys.modules[parent].__path__ + except AttributeError: + raise TypeError("Not a package:", parent) + + # Track what packages are namespaces, so when new path items are added, + # they can be updated + _namespace_packages.setdefault(parent or None, []).append(packageName) + _namespace_packages.setdefault(packageName, []) + + for path_item in path: + # Ensure all the parent's path items are reflected in the child, + # if they apply + _handle_ns(packageName, path_item) + + finally: + _imp.release_lock() + + +def fixup_namespace_packages(path_item, parent=None): + """Ensure that previously-declared namespace packages include path_item""" + _imp.acquire_lock() + try: + for package in _namespace_packages.get(parent, ()): + subpath = _handle_ns(package, path_item) + if subpath: + fixup_namespace_packages(subpath, package) + finally: + _imp.release_lock() + + +def file_ns_handler(importer, path_item, packageName, module): + """Compute an ns-package subpath for a filesystem or zipfile importer""" + + subpath = os.path.join(path_item, packageName.split('.')[-1]) + normalized = _normalize_cached(subpath) + for item in module.__path__: + if _normalize_cached(item) == normalized: + break + else: + # Only return the path if it's not already there + return subpath + + +register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) +register_namespace_handler(zipimport.zipimporter, file_ns_handler) + +if hasattr(importlib_machinery, 'FileFinder'): + register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) + + +def null_ns_handler(importer, path_item, packageName, module): + return None + + +register_namespace_handler(object, null_ns_handler) + + +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(filename)) + + +def _normalize_cached(filename, _cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result + + +def _is_egg_path(path): + """ + Determine if given path appears to be an egg. + """ + return path.lower().endswith('.egg') + + +def _is_unpacked_egg(path): + """ + Determine if given path appears to be an unpacked egg. + """ + return ( + _is_egg_path(path) and + os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) + ) + + +def _set_parent_ns(packageName): + parts = packageName.split('.') + name = parts.pop() + if parts: + parent = '.'.join(parts) + setattr(sys.modules[parent], name, sys.modules[packageName]) + + +def yield_lines(strs): + """Yield non-empty/non-comment lines of a string or sequence""" + if isinstance(strs, six.string_types): + for s in strs.splitlines(): + s = s.strip() + # skip blank lines/comments + if s and not s.startswith('#'): + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + + +MODULE = re.compile(r"\w+(\.\w+)*$").match +EGG_NAME = re.compile( + r""" + (?P<name>[^-]+) ( + -(?P<ver>[^-]+) ( + -py(?P<pyver>[^-]+) ( + -(?P<plat>.+) + )? + )? + )? + """, + re.VERBOSE | re.IGNORECASE, +).match + + +class EntryPoint: + """Object representing an advertised importable object""" + + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = tuple(extras) + self.dist = dist + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self, require=True, *args, **kwargs): + """ + Require packages for this EntryPoint, then resolve it. + """ + if not require or args or kwargs: + warnings.warn( + "Parameters to load are deprecated. Call .resolve and " + ".require separately.", + DeprecationWarning, + stacklevel=2, + ) + if require: + self.require(*args, **kwargs) + return self.resolve() + + def resolve(self): + """ + Resolve the entry point from its module and attrs. + """ + module = __import__(self.module_name, fromlist=['__name__'], level=0) + try: + return functools.reduce(getattr, self.attrs, module) + except AttributeError as exc: + raise ImportError(str(exc)) + + def require(self, env=None, installer=None): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + + # Get the requirements for this entry point with all its extras and + # then resolve them. We have to pass `extras` along when resolving so + # that the working set knows what extras we want. Otherwise, for + # dist-info distributions, the working set will assume that the + # requirements for that extra are purely optional and skip over them. + reqs = self.dist.requires(self.extras) + items = working_set.resolve(reqs, env, installer, extras=self.extras) + list(map(working_set.add, items)) + + pattern = re.compile( + r'\s*' + r'(?P<name>.+?)\s*' + r'=\s*' + r'(?P<module>[\w.]+)\s*' + r'(:\s*(?P<attr>[\w.]+))?\s*' + r'(?P<extras>\[.*\])?\s*$' + ) + + @classmethod + def parse(cls, src, dist=None): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1, extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + m = cls.pattern.match(src) + if not m: + msg = "EntryPoint must be in 'name=module:attrs [extras]' format" + raise ValueError(msg, src) + res = m.groupdict() + extras = cls._parse_extras(res['extras']) + attrs = res['attr'].split('.') if res['attr'] else () + return cls(res['name'], res['module'], attrs, extras, dist) + + @classmethod + def _parse_extras(cls, extras_spec): + if not extras_spec: + return () + req = Requirement.parse('x' + extras_spec) + if req.specs: + raise ValueError() + return req.extras + + @classmethod + def parse_group(cls, group, lines, dist=None): + """Parse an entry point group""" + if not MODULE(group): + raise ValueError("Invalid group name", group) + this = {} + for line in yield_lines(lines): + ep = cls.parse(line, dist) + if ep.name in this: + raise ValueError("Duplicate entry point", group, ep.name) + this[ep.name] = ep + return this + + @classmethod + def parse_map(cls, data, dist=None): + """Parse a map of entry point groups""" + if isinstance(data, dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for group, lines in data: + if group is None: + if not lines: + continue + raise ValueError("Entry points must be listed in groups") + group = group.strip() + if group in maps: + raise ValueError("Duplicate group name", group) + maps[group] = cls.parse_group(group, lines, dist) + return maps + + +def _remove_md5_fragment(location): + if not location: + return '' + parsed = urllib.parse.urlparse(location) + if parsed[-1].startswith('md5='): + return urllib.parse.urlunparse(parsed[:-1] + ('',)) + return location + + +def _version_from_file(lines): + """ + Given an iterable of lines from a Metadata file, return + the value of the Version field, if present, or None otherwise. + """ + def is_version_line(line): + return line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) + line = next(iter(version_lines), '') + _, _, value = line.partition(':') + return safe_version(value.strip()) or None + + +class Distribution: + """Wrap an actual or potential sys.path entry w/metadata""" + PKG_INFO = 'PKG-INFO' + + def __init__( + self, location=None, metadata=None, project_name=None, + version=None, py_version=PY_MAJOR, platform=None, + precedence=EGG_DIST): + self.project_name = safe_name(project_name or 'Unknown') + if version is not None: + self._version = safe_version(version) + self.py_version = py_version + self.platform = platform + self.location = location + self.precedence = precedence + self._provider = metadata or empty_provider + + @classmethod + def from_location(cls, location, basename, metadata=None, **kw): + project_name, version, py_version, platform = [None] * 4 + basename, ext = os.path.splitext(basename) + if ext.lower() in _distributionImpl: + cls = _distributionImpl[ext.lower()] + + match = EGG_NAME(basename) + if match: + project_name, version, py_version, platform = match.group( + 'name', 'ver', 'pyver', 'plat' + ) + return cls( + location, metadata, project_name=project_name, version=version, + py_version=py_version, platform=platform, **kw + )._reload_version() + + def _reload_version(self): + return self + + @property + def hashcmp(self): + return ( + self.parsed_version, + self.precedence, + self.key, + _remove_md5_fragment(self.location), + self.py_version or '', + self.platform or '', + ) + + def __hash__(self): + return hash(self.hashcmp) + + def __lt__(self, other): + return self.hashcmp < other.hashcmp + + def __le__(self, other): + return self.hashcmp <= other.hashcmp + + def __gt__(self, other): + return self.hashcmp > other.hashcmp + + def __ge__(self, other): + return self.hashcmp >= other.hashcmp + + def __eq__(self, other): + if not isinstance(other, self.__class__): + # It's not a Distribution, so they are not equal + return False + return self.hashcmp == other.hashcmp + + def __ne__(self, other): + return not self == other + + # These properties have to be lazy so that we don't have to load any + # metadata until/unless it's actually needed. (i.e., some distributions + # may not know their name or version without loading PKG-INFO) + + @property + def key(self): + try: + return self._key + except AttributeError: + self._key = key = self.project_name.lower() + return key + + @property + def parsed_version(self): + if not hasattr(self, "_parsed_version"): + self._parsed_version = parse_version(self.version) + + return self._parsed_version + + def _warn_legacy_version(self): + LV = packaging.version.LegacyVersion + is_legacy = isinstance(self._parsed_version, LV) + if not is_legacy: + return + + # While an empty version is technically a legacy version and + # is not a valid PEP 440 version, it's also unlikely to + # actually come from someone and instead it is more likely that + # it comes from setuptools attempting to parse a filename and + # including it in the list. So for that we'll gate this warning + # on if the version is anything at all or not. + if not self.version: + return + + tmpl = textwrap.dedent(""" + '{project_name} ({version})' is being parsed as a legacy, + non PEP 440, + version. You may find odd behavior and sort order. + In particular it will be sorted as less than 0.0. It + is recommended to migrate to PEP 440 compatible + versions. + """).strip().replace('\n', ' ') + + warnings.warn(tmpl.format(**vars(self)), PEP440Warning) + + @property + def version(self): + try: + return self._version + except AttributeError: + version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if version is None: + tmpl = "Missing 'Version:' header and/or %s file" + raise ValueError(tmpl % self.PKG_INFO, self) + return version + + @property + def _dep_map(self): + """ + A map of extra to its list of (direct) requirements + for this distribution, including the null extra. + """ + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._filter_extras(self._build_dep_map()) + return self.__dep_map + + @staticmethod + def _filter_extras(dm): + """ + Given a mapping of extras to dependencies, strip off + environment markers and filter out any dependencies + not matching the markers. + """ + for extra in list(filter(None, dm)): + new_extra = extra + reqs = dm.pop(extra) + new_extra, _, marker = extra.partition(':') + fails_marker = marker and ( + invalid_marker(marker) + or not evaluate_marker(marker) + ) + if fails_marker: + reqs = [] + new_extra = safe_extra(new_extra) or None + + dm.setdefault(new_extra, []).extend(reqs) + return dm + + def _build_dep_map(self): + dm = {} + for name in 'requires.txt', 'depends.txt': + for extra, reqs in split_sections(self._get_metadata(name)): + dm.setdefault(extra, []).extend(parse_requirements(reqs)) + return dm + + def requires(self, extras=()): + """List of Requirements needed for this distro if `extras` are used""" + dm = self._dep_map + deps = [] + deps.extend(dm.get(None, ())) + for ext in extras: + try: + deps.extend(dm[safe_extra(ext)]) + except KeyError: + raise UnknownExtra( + "%s has no such extra feature %r" % (self, ext) + ) + return deps + + def _get_metadata(self, name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + def activate(self, path=None, replace=False): + """Ensure distribution is importable on `path` (default=sys.path)""" + if path is None: + path = sys.path + self.insert_on(path, replace=replace) + if path is sys.path: + fixup_namespace_packages(self.location) + for pkg in self._get_metadata('namespace_packages.txt'): + if pkg in sys.modules: + declare_namespace(pkg) + + def egg_name(self): + """Return what this distribution's standard .egg filename should be""" + filename = "%s-%s-py%s" % ( + to_filename(self.project_name), to_filename(self.version), + self.py_version or PY_MAJOR + ) + + if self.platform: + filename += '-' + self.platform + return filename + + def __repr__(self): + if self.location: + return "%s (%s)" % (self, self.location) + else: + return str(self) + + def __str__(self): + try: + version = getattr(self, 'version', None) + except ValueError: + version = None + version = version or "[unknown version]" + return "%s %s" % (self.project_name, version) + + def __getattr__(self, attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError(attr) + return getattr(self._provider, attr) + + def __dir__(self): + return list( + set(super(Distribution, self).__dir__()) + | set( + attr for attr in self._provider.__dir__() + if not attr.startswith('_') + ) + ) + + if not hasattr(object, '__dir__'): + # python 2.7 not supported + del __dir__ + + @classmethod + def from_filename(cls, filename, metadata=None, **kw): + return cls.from_location( + _normalize_cached(filename), os.path.basename(filename), metadata, + **kw + ) + + def as_requirement(self): + """Return a ``Requirement`` that matches this distribution exactly""" + if isinstance(self.parsed_version, packaging.version.Version): + spec = "%s==%s" % (self.project_name, self.parsed_version) + else: + spec = "%s===%s" % (self.project_name, self.parsed_version) + + return Requirement.parse(spec) + + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group, name) + if ep is None: + raise ImportError("Entry point %r not found" % ((group, name),)) + return ep.load() + + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt'), self + ) + if group is not None: + return ep_map.get(group, {}) + return ep_map + + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + def insert_on(self, path, loc=None, replace=False): + """Ensure self.location is on path + + If replace=False (default): + - If location is already in path anywhere, do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent. + - Else: add to the end of path. + If replace=True: + - If location is already on path anywhere (not eggs) + or higher priority than its parent (eggs) + do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent, + removing any lower-priority entries. + - Else: add it to the front of path. + """ + + loc = loc or self.location + if not loc: + return + + nloc = _normalize_cached(loc) + bdir = os.path.dirname(nloc) + npath = [(p and _normalize_cached(p) or p) for p in path] + + for p, item in enumerate(npath): + if item == nloc: + if replace: + break + else: + # don't modify path (even removing duplicates) if + # found and not replace + return + elif item == bdir and self.precedence == EGG_DIST: + # if it's an .egg, give it precedence over its directory + # UNLESS it's already been added to sys.path and replace=False + if (not replace) and nloc in npath[p:]: + return + if path is sys.path: + self.check_version_conflict() + path.insert(p, loc) + npath.insert(p, nloc) + break + else: + if path is sys.path: + self.check_version_conflict() + if replace: + path.insert(0, loc) + else: + path.append(loc) + return + + # p is the spot where we found or inserted loc; now remove duplicates + while True: + try: + np = npath.index(nloc, p + 1) + except ValueError: + break + else: + del npath[np], path[np] + # ha! + p = np + + return + + def check_version_conflict(self): + if self.key == 'setuptools': + # ignore the inevitable setuptools self-conflicts :( + return + + nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) + loc = normalize_path(self.location) + for modname in self._get_metadata('top_level.txt'): + if (modname not in sys.modules or modname in nsp + or modname in _namespace_packages): + continue + if modname in ('pkg_resources', 'setuptools', 'site'): + continue + fn = getattr(sys.modules[modname], '__file__', None) + if fn and (normalize_path(fn).startswith(loc) or + fn.startswith(self.location)): + continue + issue_warning( + "Module %s was already imported from %s, but %s is being added" + " to sys.path" % (modname, fn, self.location), + ) + + def has_version(self): + try: + self.version + except ValueError: + issue_warning("Unbuilt egg for " + repr(self)) + return False + return True + + def clone(self, **kw): + """Copy this distribution, substituting in any changed keyword args""" + names = 'project_name version py_version platform location precedence' + for attr in names.split(): + kw.setdefault(attr, getattr(self, attr, None)) + kw.setdefault('metadata', self._provider) + return self.__class__(**kw) + + @property + def extras(self): + return [dep for dep in self._dep_map if dep] + + +class EggInfoDistribution(Distribution): + def _reload_version(self): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + take an extra step and try to get the version number from + the metadata file itself instead of the filename. + """ + md_version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if md_version: + self._version = md_version + return self + + +class DistInfoDistribution(Distribution): + """ + Wrap an actual or potential sys.path entry + w/metadata, .dist-info style. + """ + PKG_INFO = 'METADATA' + EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") + + @property + def _parsed_pkg_info(self): + """Parse and cache metadata""" + try: + return self._pkg_info + except AttributeError: + metadata = self.get_metadata(self.PKG_INFO) + self._pkg_info = email.parser.Parser().parsestr(metadata) + return self._pkg_info + + @property + def _dep_map(self): + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._compute_dependencies() + return self.__dep_map + + def _compute_dependencies(self): + """Recompute this distribution's dependencies.""" + dm = self.__dep_map = {None: []} + + reqs = [] + # Including any condition expressions + for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: + reqs.extend(parse_requirements(req)) + + def reqs_for_extra(extra): + for req in reqs: + if not req.marker or req.marker.evaluate({'extra': extra}): + yield req + + common = frozenset(reqs_for_extra(None)) + dm[None].extend(common) + + for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: + s_extra = safe_extra(extra.strip()) + dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) + + return dm + + +_distributionImpl = { + '.egg': Distribution, + '.egg-info': EggInfoDistribution, + '.dist-info': DistInfoDistribution, +} + + +def issue_warning(*args, **kw): + level = 1 + g = globals() + try: + # find the first stack frame that is *not* code in + # the pkg_resources module, to use for the warning + while sys._getframe(level).f_globals is g: + level += 1 + except ValueError: + pass + warnings.warn(stacklevel=level + 1, *args, **kw) + + +class RequirementParseError(ValueError): + def __str__(self): + return ' '.join(self.args) + + +def parse_requirements(strs): + """Yield ``Requirement`` objects for each specification in `strs` + + `strs` must be a string, or a (possibly-nested) iterable thereof. + """ + # create a steppable iterator, so we can handle \-continuations + lines = iter(yield_lines(strs)) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if ' #' in line: + line = line[:line.find(' #')] + # If there is a line continuation, drop it, and append the next line. + if line.endswith('\\'): + line = line[:-2].strip() + try: + line += next(lines) + except StopIteration: + return + yield Requirement(line) + + +class Requirement(packaging.requirements.Requirement): + def __init__(self, requirement_string): + """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" + try: + super(Requirement, self).__init__(requirement_string) + except packaging.requirements.InvalidRequirement as e: + raise RequirementParseError(str(e)) + self.unsafe_name = self.name + project_name = safe_name(self.name) + self.project_name, self.key = project_name, project_name.lower() + self.specs = [ + (spec.operator, spec.version) for spec in self.specifier] + self.extras = tuple(map(safe_extra, self.extras)) + self.hashCmp = ( + self.key, + self.specifier, + frozenset(self.extras), + str(self.marker) if self.marker else None, + ) + self.__hash = hash(self.hashCmp) + + def __eq__(self, other): + return ( + isinstance(other, Requirement) and + self.hashCmp == other.hashCmp + ) + + def __ne__(self, other): + return not self == other + + def __contains__(self, item): + if isinstance(item, Distribution): + if item.key != self.key: + return False + + item = item.version + + # Allow prereleases always in order to match the previous behavior of + # this method. In the future this should be smarter and follow PEP 440 + # more accurately. + return self.specifier.contains(item, prereleases=True) + + def __hash__(self): + return self.__hash + + def __repr__(self): + return "Requirement.parse(%r)" % str(self) + + @staticmethod + def parse(s): + req, = parse_requirements(s) + return req + + +def _always_object(classes): + """ + Ensure object appears in the mro even + for old-style classes. + """ + if object not in classes: + return classes + (object,) + return classes + + +def _find_adapter(registry, ob): + """Return an adapter factory for `ob` from `registry`""" + types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) + for t in types: + if t in registry: + return registry[t] + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + py31compat.makedirs(dirname, exist_ok=True) + + +def _bypass_ensure_directory(path): + """Sandbox-bypassing version of ensure_directory()""" + if not WRITE_SUPPORT: + raise IOError('"os.mkdir" not supported on this platform.') + dirname, filename = split(path) + if dirname and filename and not isdir(dirname): + _bypass_ensure_directory(dirname) + try: + mkdir(dirname, 0o755) + except FileExistsError: + pass + + +def split_sections(s): + """Split a string or iterable thereof into (section, content) pairs + + Each ``section`` is a stripped version of the section header ("[section]") + and each ``content`` is a list of stripped lines excluding blank lines and + comment-only lines. If there are any such lines before the first section + header, they're returned in a first ``section`` of ``None``. + """ + section = None + content = [] + for line in yield_lines(s): + if line.startswith("["): + if line.endswith("]"): + if section or content: + yield section, content + section = line[1:-1].strip() + content = [] + else: + raise ValueError("Invalid section heading", line) + else: + content.append(line) + + # wrap up last segment + yield section, content + + +def _mkstemp(*args, **kw): + old_open = os.open + try: + # temporarily bypass sandboxing + os.open = os_open + return tempfile.mkstemp(*args, **kw) + finally: + # and then put it back + os.open = old_open + + +# Silence the PEP440Warning by default, so that end users don't get hit by it +# randomly just because they use pkg_resources. We want to append the rule +# because we want earlier uses of filterwarnings to take precedence over this +# one. +warnings.filterwarnings("ignore", category=PEP440Warning, append=True) + + +# from jaraco.functools 1.3 +def _call_aside(f, *args, **kwargs): + f(*args, **kwargs) + return f + + +@_call_aside +def _initialize(g=globals()): + "Set up global resource manager (deliberately not state-saved)" + manager = ResourceManager() + g['_manager'] = manager + g.update( + (name, getattr(manager, name)) + for name in dir(manager) + if not name.startswith('_') + ) + + +@_call_aside +def _initialize_master_working_set(): + """ + Prepare the master working set and make the ``require()`` + API available. + + This function has explicit effects on the global state + of pkg_resources. It is intended to be invoked once at + the initialization of this module. + + Invocation by other packages is unsupported and done + at their own risk. + """ + working_set = WorkingSet._build_master() + _declare_state('object', working_set=working_set) + + require = working_set.require + iter_entry_points = working_set.iter_entry_points + add_activation_listener = working_set.subscribe + run_script = working_set.run_script + # backward compatibility + run_main = run_script + # Activate all distributions already on sys.path with replace=False and + # ensure that all distributions added to the working set in the future + # (e.g. by calling ``require()``) will get activated as well, + # with higher priority (replace=True). + tuple( + dist.activate(replace=False) + for dist in working_set + ) + add_activation_listener( + lambda dist: dist.activate(replace=True), + existing=False, + ) + working_set.entries = [] + # match order + list(map(working_set.add_entry, sys.path)) + globals().update(locals()) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py b/winvenv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py new file mode 100644 index 0000000..a2d3007 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py @@ -0,0 +1,23 @@ +import os +import errno +import sys + +from pip._vendor import six + + +def _makedirs_31(path, exist_ok=False): + try: + os.makedirs(path) + except OSError as exc: + if not exist_ok or exc.errno != errno.EEXIST: + raise + + +# rely on compatibility behavior until mode considerations +# and exists_ok considerations are disentangled. +# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 +needs_makedirs = ( + six.PY2 or + (3, 4) <= sys.version_info < (3, 4, 1) +) +makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/winvenv/Lib/site-packages/pip/_vendor/progress/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/progress/__init__.py new file mode 100644 index 0000000..a41f65d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/progress/__init__.py @@ -0,0 +1,127 @@ +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import division + +from collections import deque +from datetime import timedelta +from math import ceil +from sys import stderr +from time import time + + +__version__ = '1.4' + + +class Infinite(object): + file = stderr + sma_window = 10 # Simple Moving Average window + + def __init__(self, *args, **kwargs): + self.index = 0 + self.start_ts = time() + self.avg = 0 + self._ts = self.start_ts + self._xput = deque(maxlen=self.sma_window) + for key, val in kwargs.items(): + setattr(self, key, val) + + def __getitem__(self, key): + if key.startswith('_'): + return None + return getattr(self, key, None) + + @property + def elapsed(self): + return int(time() - self.start_ts) + + @property + def elapsed_td(self): + return timedelta(seconds=self.elapsed) + + def update_avg(self, n, dt): + if n > 0: + self._xput.append(dt / n) + self.avg = sum(self._xput) / len(self._xput) + + def update(self): + pass + + def start(self): + pass + + def finish(self): + pass + + def next(self, n=1): + now = time() + dt = now - self._ts + self.update_avg(n, dt) + self._ts = now + self.index = self.index + n + self.update() + + def iter(self, it): + try: + for x in it: + yield x + self.next() + finally: + self.finish() + + +class Progress(Infinite): + def __init__(self, *args, **kwargs): + super(Progress, self).__init__(*args, **kwargs) + self.max = kwargs.get('max', 100) + + @property + def eta(self): + return int(ceil(self.avg * self.remaining)) + + @property + def eta_td(self): + return timedelta(seconds=self.eta) + + @property + def percent(self): + return self.progress * 100 + + @property + def progress(self): + return min(1, self.index / self.max) + + @property + def remaining(self): + return max(self.max - self.index, 0) + + def start(self): + self.update() + + def goto(self, index): + incr = index - self.index + self.next(incr) + + def iter(self, it): + try: + self.max = len(it) + except TypeError: + pass + + try: + for x in it: + yield x + self.next() + finally: + self.finish() diff --git a/winvenv/Lib/site-packages/pip/_vendor/progress/bar.py b/winvenv/Lib/site-packages/pip/_vendor/progress/bar.py new file mode 100644 index 0000000..025e61c --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/progress/bar.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import unicode_literals + +import sys + +from . import Progress +from .helpers import WritelnMixin + + +class Bar(WritelnMixin, Progress): + width = 32 + message = '' + suffix = '%(index)d/%(max)d' + bar_prefix = ' |' + bar_suffix = '| ' + empty_fill = ' ' + fill = '#' + hide_cursor = True + + def update(self): + filled_length = int(self.width * self.progress) + empty_length = self.width - filled_length + + message = self.message % self + bar = self.fill * filled_length + empty = self.empty_fill * empty_length + suffix = self.suffix % self + line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix, + suffix]) + self.writeln(line) + + +class ChargingBar(Bar): + suffix = '%(percent)d%%' + bar_prefix = ' ' + bar_suffix = ' ' + empty_fill = '∙' + fill = '█' + + +class FillingSquaresBar(ChargingBar): + empty_fill = '▢' + fill = '▣' + + +class FillingCirclesBar(ChargingBar): + empty_fill = '◯' + fill = '◉' + + +class IncrementalBar(Bar): + if sys.platform.startswith('win'): + phases = (u' ', u'▌', u'█') + else: + phases = (' ', '▏', '▎', '▍', '▌', '▋', '▊', '▉', '█') + + def update(self): + nphases = len(self.phases) + filled_len = self.width * self.progress + nfull = int(filled_len) # Number of full chars + phase = int((filled_len - nfull) * nphases) # Phase of last char + nempty = self.width - nfull # Number of empty chars + + message = self.message % self + bar = self.phases[-1] * nfull + current = self.phases[phase] if phase > 0 else '' + empty = self.empty_fill * max(0, nempty - len(current)) + suffix = self.suffix % self + line = ''.join([message, self.bar_prefix, bar, current, empty, + self.bar_suffix, suffix]) + self.writeln(line) + + +class PixelBar(IncrementalBar): + phases = ('⡀', '⡄', '⡆', '⡇', '⣇', '⣧', '⣷', '⣿') + + +class ShadyBar(IncrementalBar): + phases = (' ', '░', '▒', '▓', '█') diff --git a/winvenv/Lib/site-packages/pip/_vendor/progress/counter.py b/winvenv/Lib/site-packages/pip/_vendor/progress/counter.py new file mode 100644 index 0000000..6b45a1e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/progress/counter.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import unicode_literals +from . import Infinite, Progress +from .helpers import WriteMixin + + +class Counter(WriteMixin, Infinite): + message = '' + hide_cursor = True + + def update(self): + self.write(str(self.index)) + + +class Countdown(WriteMixin, Progress): + hide_cursor = True + + def update(self): + self.write(str(self.remaining)) + + +class Stack(WriteMixin, Progress): + phases = (' ', '▁', '▂', '▃', '▄', '▅', '▆', '▇', '█') + hide_cursor = True + + def update(self): + nphases = len(self.phases) + i = min(nphases - 1, int(self.progress * nphases)) + self.write(self.phases[i]) + + +class Pie(Stack): + phases = ('○', '◔', '◑', '◕', '●') diff --git a/winvenv/Lib/site-packages/pip/_vendor/progress/helpers.py b/winvenv/Lib/site-packages/pip/_vendor/progress/helpers.py new file mode 100644 index 0000000..0cde44e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/progress/helpers.py @@ -0,0 +1,91 @@ +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import print_function + + +HIDE_CURSOR = '\x1b[?25l' +SHOW_CURSOR = '\x1b[?25h' + + +class WriteMixin(object): + hide_cursor = False + + def __init__(self, message=None, **kwargs): + super(WriteMixin, self).__init__(**kwargs) + self._width = 0 + if message: + self.message = message + + if self.file and self.file.isatty(): + if self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + print(self.message, end='', file=self.file) + self.file.flush() + + def write(self, s): + if self.file and self.file.isatty(): + b = '\b' * self._width + c = s.ljust(self._width) + print(b + c, end='', file=self.file) + self._width = max(self._width, len(s)) + self.file.flush() + + def finish(self): + if self.file and self.file.isatty() and self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + +class WritelnMixin(object): + hide_cursor = False + + def __init__(self, message=None, **kwargs): + super(WritelnMixin, self).__init__(**kwargs) + if message: + self.message = message + + if self.file and self.file.isatty() and self.hide_cursor: + print(HIDE_CURSOR, end='', file=self.file) + + def clearln(self): + if self.file and self.file.isatty(): + print('\r\x1b[K', end='', file=self.file) + + def writeln(self, line): + if self.file and self.file.isatty(): + self.clearln() + print(line, end='', file=self.file) + self.file.flush() + + def finish(self): + if self.file and self.file.isatty(): + print(file=self.file) + if self.hide_cursor: + print(SHOW_CURSOR, end='', file=self.file) + + +from signal import signal, SIGINT +from sys import exit + + +class SigIntMixin(object): + """Registers a signal handler that calls finish on SIGINT""" + + def __init__(self, *args, **kwargs): + super(SigIntMixin, self).__init__(*args, **kwargs) + signal(SIGINT, self._sigint_handler) + + def _sigint_handler(self, signum, frame): + self.finish() + exit(0) diff --git a/winvenv/Lib/site-packages/pip/_vendor/progress/spinner.py b/winvenv/Lib/site-packages/pip/_vendor/progress/spinner.py new file mode 100644 index 0000000..464c7b2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/progress/spinner.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Giorgos Verigakis <verigak@gmail.com> +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +from __future__ import unicode_literals +from . import Infinite +from .helpers import WriteMixin + + +class Spinner(WriteMixin, Infinite): + message = '' + phases = ('-', '\\', '|', '/') + hide_cursor = True + + def update(self): + i = self.index % len(self.phases) + self.write(self.phases[i]) + + +class PieSpinner(Spinner): + phases = ['◷', '◶', '◵', '◴'] + + +class MoonSpinner(Spinner): + phases = ['◑', '◒', '◐', '◓'] + + +class LineSpinner(Spinner): + phases = ['⎺', '⎻', '⎼', '⎽', '⎼', '⎻'] + +class PixelSpinner(Spinner): + phases = ['⣾','⣷', '⣯', '⣟', '⡿', '⢿', '⣻', '⣽'] diff --git a/winvenv/Lib/site-packages/pip/_vendor/pyparsing.py b/winvenv/Lib/site-packages/pip/_vendor/pyparsing.py new file mode 100644 index 0000000..865152d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pyparsing.py @@ -0,0 +1,5742 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2018 Paul T. McGuire +# +# 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. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pip._vendor.pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes + - construct character word-group expressions using the L{Word} class + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes + - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones + - associate names with your parsed results using L{ParserElement.setResultsName} + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} + - find more useful common expressions in the L{pyparsing_common} namespace class +""" + +__version__ = "2.2.1" +__versionTime__ = "18 Sep 2018 00:49 UTC" +__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + # Python 3 + from collections.abc import Iterable + from collections.abc import MutableMapping +except ImportError: + # Python 2.7 + from collections import Iterable + from collections import MutableMapping + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "</", resTag, ">" ] + + out += [ nl, indent, "</", selfTag, ">" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) + +def lineno(loc,strg): + """Returns current line number within a string, counting newlines as line separators. + The first line is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [frame_summary[:2]] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [frame_summary[:2]] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "<parse action>" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, <TAB> and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}<parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. + + See examples in L{I{copy}<copy>}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or preloc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + from pip._vendor import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}<parseWithTabs>}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}<parseString>} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of <TAB>s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{<TAB>} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): + throwException = True + + if throwException: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except Exception: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "<SPC>", + "\t": "<TAB>", + "\n": "<LF>", + "\r": "<CR>", + "\f": "<FF>", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc<len(instring): + if instring[loc] == "\n": + return loc+1, "\n" + else: + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class StringStart(_PositionToken): + """ + Matches if current position is at the beginning of the parse string + """ + def __init__( self ): + super(StringStart,self).__init__() + self.errmsg = "Expected start of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc != 0: + # see if entire string up to here is just whitespace and ignoreables + if loc != self.preParse( instring, 0 ): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class StringEnd(_PositionToken): + """ + Matches if current position is at the end of the parse string + """ + def __init__( self ): + super(StringEnd,self).__init__() + self.errmsg = "Expected end of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc < len(instring): + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + elif loc > len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + +class ParseExpression(ParserElement): + """ + Abstract subclass of ParserElement, for combining and post-processing parsed tokens. + """ + def __init__( self, exprs, savelist = False ): + super(ParseExpression,self).__init__(savelist) + if isinstance( exprs, _generatorType ): + exprs = list(exprs) + + if isinstance( exprs, basestring ): + self.exprs = [ ParserElement._literalStringClass( exprs ) ] + elif isinstance( exprs, Iterable ): + exprs = list(exprs) + # if sequence of strings provided, wrap with Literal + if all(isinstance(expr, basestring) for expr in exprs): + exprs = map(ParserElement._literalStringClass, exprs) + self.exprs = list(exprs) + else: + try: + self.exprs = list( exprs ) + except TypeError: + self.exprs = [ exprs ] + self.callPreparse = False + + def __getitem__( self, i ): + return self.exprs[i] + + def append( self, other ): + self.exprs.append( other ) + self.strRepr = None + return self + + def leaveWhitespace( self ): + """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on + all contained expressions.""" + self.skipWhitespace = False + self.exprs = [ e.copy() for e in self.exprs ] + for e in self.exprs: + e.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + else: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + return self + + def __str__( self ): + try: + return super(ParseExpression,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) + return self.strRepr + + def streamline( self ): + super(ParseExpression,self).streamline() + + for e in self.exprs: + e.streamline() + + # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) + # but only if there are no parse actions or resultsNames on the nested And's + # (likewise for Or's and MatchFirst's) + if ( len(self.exprs) == 2 ): + other = self.exprs[0] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = other.exprs[:] + [ self.exprs[1] ] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + other = self.exprs[-1] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = self.exprs[:-1] + other.exprs[:] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + self.errmsg = "Expected " + _ustr(self) + + return self + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ParseExpression,self).setResultsName(name,listAllMatches) + return ret + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + for e in self.exprs: + e.validate(tmp) + self.checkRecursion( [] ) + + def copy(self): + ret = super(ParseExpression,self).copy() + ret.exprs = [e.copy() for e in self.exprs] + return ret + +class And(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found in the given order. + Expressions may be separated by whitespace. + May be constructed using the C{'+'} operator. + May also be constructed using the C{'-'} operator, which will suppress backtracking. + + Example:: + integer = Word(nums) + name_expr = OneOrMore(Word(alphas)) + + expr = And([integer("id"),name_expr("name"),integer("age")]) + # more easily written as: + expr = integer("id") + name_expr("name") + integer("age") + """ + + class _ErrorStop(Empty): + def __init__(self, *args, **kwargs): + super(And._ErrorStop,self).__init__(*args, **kwargs) + self.name = '-' + self.leaveWhitespace() + + def __init__( self, exprs, savelist = True ): + super(And,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.setWhitespaceChars( self.exprs[0].whiteChars ) + self.skipWhitespace = self.exprs[0].skipWhitespace + self.callPreparse = True + + def parseImpl( self, instring, loc, doActions=True ): + # pass False as last arg to _parse for first element, since we already + # pre-parsed the string as part of our And pre-parsing + loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False + for e in self.exprs[1:]: + if isinstance(e, And._ErrorStop): + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseSyntaxException: + raise + except ParseBaseException as pe: + pe.__traceback__ = None + raise ParseSyntaxException._from_exception(pe) + except IndexError: + raise ParseSyntaxException(instring, len(instring), self.errmsg, self) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) + if exprtokens or exprtokens.haskeys(): + resultlist += exprtokens + return loc, resultlist + + def __iadd__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #And( [ self, other ] ) + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + if not e.mayReturnEmpty: + break + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + +class Or(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the expression that matches the longest string will be used. + May be constructed using the C{'^'} operator. + + Example:: + # construct Or using '^' operator + + number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) + prints:: + [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(Or,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + matches = [] + for e in self.exprs: + try: + loc2 = e.tryParse( instring, loc ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens)))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <<leaving remove_duplicate_chars (ret: 'dfjkls') + ['dfjkls'] + """ + f = _trim_arity(f) + def z(*paArgs): + thisFunc = f.__name__ + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) + raise + sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) + return ret + try: + z.__name__ = f.__name__ + except AttributeError: + pass + return z + +# +# global helpers +# +def delimitedList( expr, delim=",", combine=False ): + """ + Helper to define a delimited list of expressions - the delimiter defaults to ','. + By default, the list elements and delimiters can have intervening whitespace, and + comments, but this can be overridden by passing C{combine=True} in the constructor. + If C{combine} is set to C{True}, the matching tokens are returned as a single token + string, with the delimiters included; otherwise, the matching tokens are returned + as a list of tokens, with the delimiters suppressed. + + Example:: + delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test <b> bold <i>text</i> </b> normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + ['<b> bold <i>text</i> </b>'] + ['<i>text</i>'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{<TAB>} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString<ParserElement.transformString>}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("</") + tagStr + ">") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the <A> tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{<TD>} or C{<DIV>}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' + <div> + Some text + <div type="grid">1 4 0 1 0</div> + <div type="graph">1,3 2,3 1,1</div> + <div>this has no type</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' + <div> + Some text + <div class="grid">1 4 0 1 0</div> + <div class="graph">1,3 2,3 1,1</div> + <div>this <div> has no class</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") +"Comment of the form C{<!-- ... -->}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) + - common L{programming identifiers<identifier>} + - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) + - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} + - L{UUID<uuid>} + - L{comma-separated list<comma_separated_list>} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pytoml/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/pytoml/__init__.py new file mode 100644 index 0000000..8dc7315 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pytoml/__init__.py @@ -0,0 +1,3 @@ +from .core import TomlError +from .parser import load, loads +from .writer import dump, dumps diff --git a/winvenv/Lib/site-packages/pip/_vendor/pytoml/core.py b/winvenv/Lib/site-packages/pip/_vendor/pytoml/core.py new file mode 100644 index 0000000..c182734 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pytoml/core.py @@ -0,0 +1,13 @@ +class TomlError(RuntimeError): + def __init__(self, message, line, col, filename): + RuntimeError.__init__(self, message, line, col, filename) + self.message = message + self.line = line + self.col = col + self.filename = filename + + def __str__(self): + return '{}({}, {}): {}'.format(self.filename, self.line, self.col, self.message) + + def __repr__(self): + return 'TomlError({!r}, {!r}, {!r}, {!r})'.format(self.message, self.line, self.col, self.filename) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pytoml/parser.py b/winvenv/Lib/site-packages/pip/_vendor/pytoml/parser.py new file mode 100644 index 0000000..9f94e92 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pytoml/parser.py @@ -0,0 +1,374 @@ +import string, re, sys, datetime +from .core import TomlError + +if sys.version_info[0] == 2: + _chr = unichr +else: + _chr = chr + +def load(fin, translate=lambda t, x, v: v, object_pairs_hook=dict): + return loads(fin.read(), translate=translate, object_pairs_hook=object_pairs_hook, filename=getattr(fin, 'name', repr(fin))) + +def loads(s, filename='<string>', translate=lambda t, x, v: v, object_pairs_hook=dict): + if isinstance(s, bytes): + s = s.decode('utf-8') + + s = s.replace('\r\n', '\n') + + root = object_pairs_hook() + tables = object_pairs_hook() + scope = root + + src = _Source(s, filename=filename) + ast = _p_toml(src, object_pairs_hook=object_pairs_hook) + + def error(msg): + raise TomlError(msg, pos[0], pos[1], filename) + + def process_value(v, object_pairs_hook): + kind, text, value, pos = v + if kind == 'str' and value.startswith('\n'): + value = value[1:] + if kind == 'array': + if value and any(k != value[0][0] for k, t, v, p in value[1:]): + error('array-type-mismatch') + value = [process_value(item, object_pairs_hook=object_pairs_hook) for item in value] + elif kind == 'table': + value = object_pairs_hook([(k, process_value(value[k], object_pairs_hook=object_pairs_hook)) for k in value]) + return translate(kind, text, value) + + for kind, value, pos in ast: + if kind == 'kv': + k, v = value + if k in scope: + error('duplicate_keys. Key "{0}" was used more than once.'.format(k)) + scope[k] = process_value(v, object_pairs_hook=object_pairs_hook) + else: + is_table_array = (kind == 'table_array') + cur = tables + for name in value[:-1]: + if isinstance(cur.get(name), list): + d, cur = cur[name][-1] + else: + d, cur = cur.setdefault(name, (None, object_pairs_hook())) + + scope = object_pairs_hook() + name = value[-1] + if name not in cur: + if is_table_array: + cur[name] = [(scope, object_pairs_hook())] + else: + cur[name] = (scope, object_pairs_hook()) + elif isinstance(cur[name], list): + if not is_table_array: + error('table_type_mismatch') + cur[name].append((scope, object_pairs_hook())) + else: + if is_table_array: + error('table_type_mismatch') + old_scope, next_table = cur[name] + if old_scope is not None: + error('duplicate_tables') + cur[name] = (scope, next_table) + + def merge_tables(scope, tables): + if scope is None: + scope = object_pairs_hook() + for k in tables: + if k in scope: + error('key_table_conflict') + v = tables[k] + if isinstance(v, list): + scope[k] = [merge_tables(sc, tbl) for sc, tbl in v] + else: + scope[k] = merge_tables(v[0], v[1]) + return scope + + return merge_tables(root, tables) + +class _Source: + def __init__(self, s, filename=None): + self.s = s + self._pos = (1, 1) + self._last = None + self._filename = filename + self.backtrack_stack = [] + + def last(self): + return self._last + + def pos(self): + return self._pos + + def fail(self): + return self._expect(None) + + def consume_dot(self): + if self.s: + self._last = self.s[0] + self.s = self[1:] + self._advance(self._last) + return self._last + return None + + def expect_dot(self): + return self._expect(self.consume_dot()) + + def consume_eof(self): + if not self.s: + self._last = '' + return True + return False + + def expect_eof(self): + return self._expect(self.consume_eof()) + + def consume(self, s): + if self.s.startswith(s): + self.s = self.s[len(s):] + self._last = s + self._advance(s) + return True + return False + + def expect(self, s): + return self._expect(self.consume(s)) + + def consume_re(self, re): + m = re.match(self.s) + if m: + self.s = self.s[len(m.group(0)):] + self._last = m + self._advance(m.group(0)) + return m + return None + + def expect_re(self, re): + return self._expect(self.consume_re(re)) + + def __enter__(self): + self.backtrack_stack.append((self.s, self._pos)) + + def __exit__(self, type, value, traceback): + if type is None: + self.backtrack_stack.pop() + else: + self.s, self._pos = self.backtrack_stack.pop() + return type == TomlError + + def commit(self): + self.backtrack_stack[-1] = (self.s, self._pos) + + def _expect(self, r): + if not r: + raise TomlError('msg', self._pos[0], self._pos[1], self._filename) + return r + + def _advance(self, s): + suffix_pos = s.rfind('\n') + if suffix_pos == -1: + self._pos = (self._pos[0], self._pos[1] + len(s)) + else: + self._pos = (self._pos[0] + s.count('\n'), len(s) - suffix_pos) + +_ews_re = re.compile(r'(?:[ \t]|#[^\n]*\n|#[^\n]*\Z|\n)*') +def _p_ews(s): + s.expect_re(_ews_re) + +_ws_re = re.compile(r'[ \t]*') +def _p_ws(s): + s.expect_re(_ws_re) + +_escapes = { 'b': '\b', 'n': '\n', 'r': '\r', 't': '\t', '"': '"', '\'': '\'', + '\\': '\\', '/': '/', 'f': '\f' } + +_basicstr_re = re.compile(r'[^"\\\000-\037]*') +_short_uni_re = re.compile(r'u([0-9a-fA-F]{4})') +_long_uni_re = re.compile(r'U([0-9a-fA-F]{8})') +_escapes_re = re.compile('[bnrt"\'\\\\/f]') +_newline_esc_re = re.compile('\n[ \t\n]*') +def _p_basicstr_content(s, content=_basicstr_re): + res = [] + while True: + res.append(s.expect_re(content).group(0)) + if not s.consume('\\'): + break + if s.consume_re(_newline_esc_re): + pass + elif s.consume_re(_short_uni_re) or s.consume_re(_long_uni_re): + res.append(_chr(int(s.last().group(1), 16))) + else: + s.expect_re(_escapes_re) + res.append(_escapes[s.last().group(0)]) + return ''.join(res) + +_key_re = re.compile(r'[0-9a-zA-Z-_]+') +def _p_key(s): + with s: + s.expect('"') + r = _p_basicstr_content(s, _basicstr_re) + s.expect('"') + return r + if s.consume('\''): + if s.consume('\'\''): + r = s.expect_re(_litstr_ml_re).group(0) + s.expect('\'\'\'') + else: + r = s.expect_re(_litstr_re).group(0) + s.expect('\'') + return r + return s.expect_re(_key_re).group(0) + +_float_re = re.compile(r'[+-]?(?:0|[1-9](?:_?\d)*)(?:\.\d(?:_?\d)*)?(?:[eE][+-]?(?:\d(?:_?\d)*))?') +_datetime_re = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(?:Z|([+-]\d{2}):(\d{2}))') + +_basicstr_ml_re = re.compile(r'(?:(?:|"|"")[^"\\\000-\011\013-\037])*') +_litstr_re = re.compile(r"[^'\000\010\012-\037]*") +_litstr_ml_re = re.compile(r"(?:(?:|'|'')(?:[^'\000-\010\013-\037]))*") +def _p_value(s, object_pairs_hook): + pos = s.pos() + + if s.consume('true'): + return 'bool', s.last(), True, pos + if s.consume('false'): + return 'bool', s.last(), False, pos + + if s.consume('"'): + if s.consume('""'): + r = _p_basicstr_content(s, _basicstr_ml_re) + s.expect('"""') + else: + r = _p_basicstr_content(s, _basicstr_re) + s.expect('"') + return 'str', r, r, pos + + if s.consume('\''): + if s.consume('\'\''): + r = s.expect_re(_litstr_ml_re).group(0) + s.expect('\'\'\'') + else: + r = s.expect_re(_litstr_re).group(0) + s.expect('\'') + return 'str', r, r, pos + + if s.consume_re(_datetime_re): + m = s.last() + s0 = m.group(0) + r = map(int, m.groups()[:6]) + if m.group(7): + micro = float(m.group(7)) + else: + micro = 0 + + if m.group(8): + g = int(m.group(8), 10) * 60 + int(m.group(9), 10) + tz = _TimeZone(datetime.timedelta(0, g * 60)) + else: + tz = _TimeZone(datetime.timedelta(0, 0)) + + y, m, d, H, M, S = r + dt = datetime.datetime(y, m, d, H, M, S, int(micro * 1000000), tz) + return 'datetime', s0, dt, pos + + if s.consume_re(_float_re): + m = s.last().group(0) + r = m.replace('_','') + if '.' in m or 'e' in m or 'E' in m: + return 'float', m, float(r), pos + else: + return 'int', m, int(r, 10), pos + + if s.consume('['): + items = [] + with s: + while True: + _p_ews(s) + items.append(_p_value(s, object_pairs_hook=object_pairs_hook)) + s.commit() + _p_ews(s) + s.expect(',') + s.commit() + _p_ews(s) + s.expect(']') + return 'array', None, items, pos + + if s.consume('{'): + _p_ws(s) + items = object_pairs_hook() + if not s.consume('}'): + k = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + items[k] = _p_value(s, object_pairs_hook=object_pairs_hook) + _p_ws(s) + while s.consume(','): + _p_ws(s) + k = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + items[k] = _p_value(s, object_pairs_hook=object_pairs_hook) + _p_ws(s) + s.expect('}') + return 'table', None, items, pos + + s.fail() + +def _p_stmt(s, object_pairs_hook): + pos = s.pos() + if s.consume( '['): + is_array = s.consume('[') + _p_ws(s) + keys = [_p_key(s)] + _p_ws(s) + while s.consume('.'): + _p_ws(s) + keys.append(_p_key(s)) + _p_ws(s) + s.expect(']') + if is_array: + s.expect(']') + return 'table_array' if is_array else 'table', keys, pos + + key = _p_key(s) + _p_ws(s) + s.expect('=') + _p_ws(s) + value = _p_value(s, object_pairs_hook=object_pairs_hook) + return 'kv', (key, value), pos + +_stmtsep_re = re.compile(r'(?:[ \t]*(?:#[^\n]*)?\n)+[ \t]*') +def _p_toml(s, object_pairs_hook): + stmts = [] + _p_ews(s) + with s: + stmts.append(_p_stmt(s, object_pairs_hook=object_pairs_hook)) + while True: + s.commit() + s.expect_re(_stmtsep_re) + stmts.append(_p_stmt(s, object_pairs_hook=object_pairs_hook)) + _p_ews(s) + s.expect_eof() + return stmts + +class _TimeZone(datetime.tzinfo): + def __init__(self, offset): + self._offset = offset + + def utcoffset(self, dt): + return self._offset + + def dst(self, dt): + return None + + def tzname(self, dt): + m = self._offset.total_seconds() // 60 + if m < 0: + res = '-' + m = -m + else: + res = '+' + h = m // 60 + m = m - h * 60 + return '{}{:.02}{:.02}'.format(res, h, m) diff --git a/winvenv/Lib/site-packages/pip/_vendor/pytoml/writer.py b/winvenv/Lib/site-packages/pip/_vendor/pytoml/writer.py new file mode 100644 index 0000000..6eaf5d7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/pytoml/writer.py @@ -0,0 +1,127 @@ +from __future__ import unicode_literals +import io, datetime, math, sys + +if sys.version_info[0] == 3: + long = int + unicode = str + + +def dumps(obj, sort_keys=False): + fout = io.StringIO() + dump(obj, fout, sort_keys=sort_keys) + return fout.getvalue() + + +_escapes = {'\n': 'n', '\r': 'r', '\\': '\\', '\t': 't', '\b': 'b', '\f': 'f', '"': '"'} + + +def _escape_string(s): + res = [] + start = 0 + + def flush(): + if start != i: + res.append(s[start:i]) + return i + 1 + + i = 0 + while i < len(s): + c = s[i] + if c in '"\\\n\r\t\b\f': + start = flush() + res.append('\\' + _escapes[c]) + elif ord(c) < 0x20: + start = flush() + res.append('\\u%04x' % ord(c)) + i += 1 + + flush() + return '"' + ''.join(res) + '"' + + +def _escape_id(s): + if any(not c.isalnum() and c not in '-_' for c in s): + return _escape_string(s) + return s + + +def _format_list(v): + return '[{0}]'.format(', '.join(_format_value(obj) for obj in v)) + +# Formula from: +# https://docs.python.org/2/library/datetime.html#datetime.timedelta.total_seconds +# Once support for py26 is dropped, this can be replaced by td.total_seconds() +def _total_seconds(td): + return ((td.microseconds + + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.0**6) + +def _format_value(v): + if isinstance(v, bool): + return 'true' if v else 'false' + if isinstance(v, int) or isinstance(v, long): + return unicode(v) + if isinstance(v, float): + if math.isnan(v) or math.isinf(v): + raise ValueError("{0} is not a valid TOML value".format(v)) + else: + return repr(v) + elif isinstance(v, unicode) or isinstance(v, bytes): + return _escape_string(v) + elif isinstance(v, datetime.datetime): + offs = v.utcoffset() + offs = _total_seconds(offs) // 60 if offs is not None else 0 + + if offs == 0: + suffix = 'Z' + else: + if offs > 0: + suffix = '+' + else: + suffix = '-' + offs = -offs + suffix = '{0}{1:.02}{2:.02}'.format(suffix, offs // 60, offs % 60) + + if v.microsecond: + return v.strftime('%Y-%m-%dT%H:%M:%S.%f') + suffix + else: + return v.strftime('%Y-%m-%dT%H:%M:%S') + suffix + elif isinstance(v, list): + return _format_list(v) + else: + raise RuntimeError(v) + + +def dump(obj, fout, sort_keys=False): + tables = [((), obj, False)] + + while tables: + name, table, is_array = tables.pop() + if name: + section_name = '.'.join(_escape_id(c) for c in name) + if is_array: + fout.write('[[{0}]]\n'.format(section_name)) + else: + fout.write('[{0}]\n'.format(section_name)) + + table_keys = sorted(table.keys()) if sort_keys else table.keys() + new_tables = [] + has_kv = False + for k in table_keys: + v = table[k] + if isinstance(v, dict): + new_tables.append((name + (k,), v, False)) + elif isinstance(v, list) and v and all(isinstance(o, dict) for o in v): + new_tables.extend((name + (k,), d, True) for d in v) + elif v is None: + # based on mojombo's comment: https://github.com/toml-lang/toml/issues/146#issuecomment-25019344 + fout.write( + '#{} = null # To use: uncomment and replace null with value\n'.format(_escape_id(k))) + has_kv = True + else: + fout.write('{0} = {1}\n'.format(_escape_id(k), _format_value(v))) + has_kv = True + + tables.extend(reversed(new_tables)) + + if (name or has_kv) and tables: + fout.write('\n') diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/requests/__init__.py new file mode 100644 index 0000000..3f3f4f2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/__init__.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- + +# __ +# /__) _ _ _ _ _/ _ +# / ( (- (/ (/ (- _) / _) +# / + +""" +Requests HTTP Library +~~~~~~~~~~~~~~~~~~~~~ + +Requests is an HTTP library, written in Python, for human beings. Basic GET +usage: + + >>> import requests + >>> r = requests.get('https://www.python.org') + >>> r.status_code + 200 + >>> 'Python is a programming language' in r.content + True + +... or POST: + + >>> payload = dict(key1='value1', key2='value2') + >>> r = requests.post('http://httpbin.org/post', data=payload) + >>> print(r.text) + { + ... + "form": { + "key2": "value2", + "key1": "value1" + }, + ... + } + +The other HTTP methods are supported - see `requests.api`. Full documentation +is at <http://python-requests.org>. + +:copyright: (c) 2017 by Kenneth Reitz. +:license: Apache 2.0, see LICENSE for more details. +""" + +from pip._vendor import urllib3 +from pip._vendor import chardet +import warnings +from .exceptions import RequestsDependencyWarning + + +def check_compatibility(urllib3_version, chardet_version): + urllib3_version = urllib3_version.split('.') + assert urllib3_version != ['dev'] # Verify urllib3 isn't installed from git. + + # Sometimes, urllib3 only reports its version as 16.1. + if len(urllib3_version) == 2: + urllib3_version.append('0') + + # Check urllib3 for compatibility. + major, minor, patch = urllib3_version # noqa: F811 + major, minor, patch = int(major), int(minor), int(patch) + # urllib3 >= 1.21.1, <= 1.23 + assert major == 1 + assert minor >= 21 + assert minor <= 23 + + # Check chardet for compatibility. + major, minor, patch = chardet_version.split('.')[:3] + major, minor, patch = int(major), int(minor), int(patch) + # chardet >= 3.0.2, < 3.1.0 + assert major == 3 + assert minor < 1 + assert patch >= 2 + + +def _check_cryptography(cryptography_version): + # cryptography < 1.3.4 + try: + cryptography_version = list(map(int, cryptography_version.split('.'))) + except ValueError: + return + + if cryptography_version < [1, 3, 4]: + warning = 'Old version of cryptography ({0}) may cause slowdown.'.format(cryptography_version) + warnings.warn(warning, RequestsDependencyWarning) + +# Check imported dependencies for compatibility. +try: + check_compatibility(urllib3.__version__, chardet.__version__) +except (AssertionError, ValueError): + warnings.warn("urllib3 ({0}) or chardet ({1}) doesn't match a supported " + "version!".format(urllib3.__version__, chardet.__version__), + RequestsDependencyWarning) + +# Attempt to enable urllib3's SNI support, if possible +from pip._internal.utils.compat import WINDOWS +if not WINDOWS: + try: + from pip._vendor.urllib3.contrib import pyopenssl + pyopenssl.inject_into_urllib3() + + # Check cryptography version + from cryptography import __version__ as cryptography_version + _check_cryptography(cryptography_version) + except ImportError: + pass + +# urllib3's DependencyWarnings should be silenced. +from pip._vendor.urllib3.exceptions import DependencyWarning +warnings.simplefilter('ignore', DependencyWarning) + +from .__version__ import __title__, __description__, __url__, __version__ +from .__version__ import __build__, __author__, __author_email__, __license__ +from .__version__ import __copyright__, __cake__ + +from . import utils +from . import packages +from .models import Request, Response, PreparedRequest +from .api import request, get, head, post, patch, put, delete, options +from .sessions import session, Session +from .status_codes import codes +from .exceptions import ( + RequestException, Timeout, URLRequired, + TooManyRedirects, HTTPError, ConnectionError, + FileModeWarning, ConnectTimeout, ReadTimeout +) + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +logging.getLogger(__name__).addHandler(NullHandler()) + +# FileModeWarnings go off per the default. +warnings.simplefilter('default', FileModeWarning, append=True) diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/__version__.py b/winvenv/Lib/site-packages/pip/_vendor/requests/__version__.py new file mode 100644 index 0000000..ef61ec0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/__version__.py @@ -0,0 +1,14 @@ +# .-. .-. .-. . . .-. .-. .-. .-. +# |( |- |.| | | |- `-. | `-. +# ' ' `-' `-`.`-' `-' `-' ' `-' + +__title__ = 'requests' +__description__ = 'Python HTTP for Humans.' +__url__ = 'http://python-requests.org' +__version__ = '2.19.1' +__build__ = 0x021901 +__author__ = 'Kenneth Reitz' +__author_email__ = 'me@kennethreitz.org' +__license__ = 'Apache 2.0' +__copyright__ = 'Copyright 2018 Kenneth Reitz' +__cake__ = u'\u2728 \U0001f370 \u2728' diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py b/winvenv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py new file mode 100644 index 0000000..759d9a5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +""" +requests._internal_utils +~~~~~~~~~~~~~~ + +Provides utility functions that are consumed internally by Requests +which depend on extremely few external helpers (such as compat) +""" + +from .compat import is_py2, builtin_str, str + + +def to_native_string(string, encoding='ascii'): + """Given a string object, regardless of type, returns a representation of + that string in the native string type, encoding and decoding where + necessary. This assumes ASCII unless told otherwise. + """ + if isinstance(string, builtin_str): + out = string + else: + if is_py2: + out = string.encode(encoding) + else: + out = string.decode(encoding) + + return out + + +def unicode_is_ascii(u_string): + """Determine if unicode string only contains ASCII characters. + + :param str u_string: unicode string to check. Must be unicode + and not Python 2 `str`. + :rtype: bool + """ + assert isinstance(u_string, str) + try: + u_string.encode('ascii') + return True + except UnicodeEncodeError: + return False diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/adapters.py b/winvenv/Lib/site-packages/pip/_vendor/requests/adapters.py new file mode 100644 index 0000000..f6f3f99 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/adapters.py @@ -0,0 +1,530 @@ +# -*- coding: utf-8 -*- + +""" +requests.adapters +~~~~~~~~~~~~~~~~~ + +This module contains the transport adapters that Requests uses to define +and maintain connections. +""" + +import os.path +import socket + +from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url +from pip._vendor.urllib3.response import HTTPResponse +from pip._vendor.urllib3.util import parse_url +from pip._vendor.urllib3.util import Timeout as TimeoutSauce +from pip._vendor.urllib3.util.retry import Retry +from pip._vendor.urllib3.exceptions import ClosedPoolError +from pip._vendor.urllib3.exceptions import ConnectTimeoutError +from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError +from pip._vendor.urllib3.exceptions import MaxRetryError +from pip._vendor.urllib3.exceptions import NewConnectionError +from pip._vendor.urllib3.exceptions import ProxyError as _ProxyError +from pip._vendor.urllib3.exceptions import ProtocolError +from pip._vendor.urllib3.exceptions import ReadTimeoutError +from pip._vendor.urllib3.exceptions import SSLError as _SSLError +from pip._vendor.urllib3.exceptions import ResponseError + +from .models import Response +from .compat import urlparse, basestring +from .utils import (DEFAULT_CA_BUNDLE_PATH, extract_zipped_paths, + get_encoding_from_headers, prepend_scheme_if_needed, + get_auth_from_url, urldefragauth, select_proxy) +from .structures import CaseInsensitiveDict +from .cookies import extract_cookies_to_jar +from .exceptions import (ConnectionError, ConnectTimeout, ReadTimeout, SSLError, + ProxyError, RetryError, InvalidSchema, InvalidProxyURL) +from .auth import _basic_auth_str + +try: + from pip._vendor.urllib3.contrib.socks import SOCKSProxyManager +except ImportError: + def SOCKSProxyManager(*args, **kwargs): + raise InvalidSchema("Missing dependencies for SOCKS support.") + +DEFAULT_POOLBLOCK = False +DEFAULT_POOLSIZE = 10 +DEFAULT_RETRIES = 0 +DEFAULT_POOL_TIMEOUT = None + + +class BaseAdapter(object): + """The Base Transport Adapter""" + + def __init__(self): + super(BaseAdapter, self).__init__() + + def send(self, request, stream=False, timeout=None, verify=True, + cert=None, proxies=None): + """Sends PreparedRequest object. Returns Response object. + + :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. + :param stream: (optional) Whether to stream the request content. + :param timeout: (optional) How long to wait for the server to send + data before giving up, as a float, or a :ref:`(connect timeout, + read timeout) <timeouts>` tuple. + :type timeout: float or tuple + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use + :param cert: (optional) Any user-provided SSL certificate to be trusted. + :param proxies: (optional) The proxies dictionary to apply to the request. + """ + raise NotImplementedError + + def close(self): + """Cleans up adapter specific items.""" + raise NotImplementedError + + +class HTTPAdapter(BaseAdapter): + """The built-in HTTP Adapter for urllib3. + + Provides a general-case interface for Requests sessions to contact HTTP and + HTTPS urls by implementing the Transport Adapter interface. This class will + usually be created by the :class:`Session <Session>` class under the + covers. + + :param pool_connections: The number of urllib3 connection pools to cache. + :param pool_maxsize: The maximum number of connections to save in the pool. + :param max_retries: The maximum number of retries each connection + should attempt. Note, this applies only to failed DNS lookups, socket + connections and connection timeouts, never to requests where data has + made it to the server. By default, Requests does not retry failed + connections. If you need granular control over the conditions under + which we retry a request, import urllib3's ``Retry`` class and pass + that instead. + :param pool_block: Whether the connection pool should block for connections. + + Usage:: + + >>> import requests + >>> s = requests.Session() + >>> a = requests.adapters.HTTPAdapter(max_retries=3) + >>> s.mount('http://', a) + """ + __attrs__ = ['max_retries', 'config', '_pool_connections', '_pool_maxsize', + '_pool_block'] + + def __init__(self, pool_connections=DEFAULT_POOLSIZE, + pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_RETRIES, + pool_block=DEFAULT_POOLBLOCK): + if max_retries == DEFAULT_RETRIES: + self.max_retries = Retry(0, read=False) + else: + self.max_retries = Retry.from_int(max_retries) + self.config = {} + self.proxy_manager = {} + + super(HTTPAdapter, self).__init__() + + self._pool_connections = pool_connections + self._pool_maxsize = pool_maxsize + self._pool_block = pool_block + + self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) + + def __getstate__(self): + return dict((attr, getattr(self, attr, None)) for attr in + self.__attrs__) + + def __setstate__(self, state): + # Can't handle by adding 'proxy_manager' to self.__attrs__ because + # self.poolmanager uses a lambda function, which isn't pickleable. + self.proxy_manager = {} + self.config = {} + + for attr, value in state.items(): + setattr(self, attr, value) + + self.init_poolmanager(self._pool_connections, self._pool_maxsize, + block=self._pool_block) + + def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs): + """Initializes a urllib3 PoolManager. + + This method should not be called from user code, and is only + exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param connections: The number of urllib3 connection pools to cache. + :param maxsize: The maximum number of connections to save in the pool. + :param block: Block when no free connections are available. + :param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager. + """ + # save these values for pickling + self._pool_connections = connections + self._pool_maxsize = maxsize + self._pool_block = block + + self.poolmanager = PoolManager(num_pools=connections, maxsize=maxsize, + block=block, strict=True, **pool_kwargs) + + def proxy_manager_for(self, proxy, **proxy_kwargs): + """Return urllib3 ProxyManager for the given proxy. + + This method should not be called from user code, and is only + exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param proxy: The proxy to return a urllib3 ProxyManager for. + :param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager. + :returns: ProxyManager + :rtype: urllib3.ProxyManager + """ + if proxy in self.proxy_manager: + manager = self.proxy_manager[proxy] + elif proxy.lower().startswith('socks'): + username, password = get_auth_from_url(proxy) + manager = self.proxy_manager[proxy] = SOCKSProxyManager( + proxy, + username=username, + password=password, + num_pools=self._pool_connections, + maxsize=self._pool_maxsize, + block=self._pool_block, + **proxy_kwargs + ) + else: + proxy_headers = self.proxy_headers(proxy) + manager = self.proxy_manager[proxy] = proxy_from_url( + proxy, + proxy_headers=proxy_headers, + num_pools=self._pool_connections, + maxsize=self._pool_maxsize, + block=self._pool_block, + **proxy_kwargs) + + return manager + + def cert_verify(self, conn, url, verify, cert): + """Verify a SSL certificate. This method should not be called from user + code, and is only exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param conn: The urllib3 connection object associated with the cert. + :param url: The requested URL. + :param verify: Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use + :param cert: The SSL certificate to verify. + """ + if url.lower().startswith('https') and verify: + + cert_loc = None + + # Allow self-specified cert location. + if verify is not True: + cert_loc = verify + + if not cert_loc: + cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH) + + if not cert_loc or not os.path.exists(cert_loc): + raise IOError("Could not find a suitable TLS CA certificate bundle, " + "invalid path: {0}".format(cert_loc)) + + conn.cert_reqs = 'CERT_REQUIRED' + + if not os.path.isdir(cert_loc): + conn.ca_certs = cert_loc + else: + conn.ca_cert_dir = cert_loc + else: + conn.cert_reqs = 'CERT_NONE' + conn.ca_certs = None + conn.ca_cert_dir = None + + if cert: + if not isinstance(cert, basestring): + conn.cert_file = cert[0] + conn.key_file = cert[1] + else: + conn.cert_file = cert + conn.key_file = None + if conn.cert_file and not os.path.exists(conn.cert_file): + raise IOError("Could not find the TLS certificate file, " + "invalid path: {0}".format(conn.cert_file)) + if conn.key_file and not os.path.exists(conn.key_file): + raise IOError("Could not find the TLS key file, " + "invalid path: {0}".format(conn.key_file)) + + def build_response(self, req, resp): + """Builds a :class:`Response <requests.Response>` object from a urllib3 + response. This should not be called from user code, and is only exposed + for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>` + + :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response. + :param resp: The urllib3 response object. + :rtype: requests.Response + """ + response = Response() + + # Fallback to None if there's no status_code, for whatever reason. + response.status_code = getattr(resp, 'status', None) + + # Make headers case-insensitive. + response.headers = CaseInsensitiveDict(getattr(resp, 'headers', {})) + + # Set encoding. + response.encoding = get_encoding_from_headers(response.headers) + response.raw = resp + response.reason = response.raw.reason + + if isinstance(req.url, bytes): + response.url = req.url.decode('utf-8') + else: + response.url = req.url + + # Add new cookies from the server. + extract_cookies_to_jar(response.cookies, req, resp) + + # Give the Response some context. + response.request = req + response.connection = self + + return response + + def get_connection(self, url, proxies=None): + """Returns a urllib3 connection for the given URL. This should not be + called from user code, and is only exposed for use when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param url: The URL to connect to. + :param proxies: (optional) A Requests-style dictionary of proxies used on this request. + :rtype: urllib3.ConnectionPool + """ + proxy = select_proxy(url, proxies) + + if proxy: + proxy = prepend_scheme_if_needed(proxy, 'http') + proxy_url = parse_url(proxy) + if not proxy_url.host: + raise InvalidProxyURL("Please check proxy URL. It is malformed" + " and could be missing the host.") + proxy_manager = self.proxy_manager_for(proxy) + conn = proxy_manager.connection_from_url(url) + else: + # Only scheme should be lower case + parsed = urlparse(url) + url = parsed.geturl() + conn = self.poolmanager.connection_from_url(url) + + return conn + + def close(self): + """Disposes of any internal state. + + Currently, this closes the PoolManager and any active ProxyManager, + which closes any pooled connections. + """ + self.poolmanager.clear() + for proxy in self.proxy_manager.values(): + proxy.clear() + + def request_url(self, request, proxies): + """Obtain the url to use when making the final request. + + If the message is being sent through a HTTP proxy, the full URL has to + be used. Otherwise, we should only use the path portion of the URL. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. + :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs. + :rtype: str + """ + proxy = select_proxy(request.url, proxies) + scheme = urlparse(request.url).scheme + + is_proxied_http_request = (proxy and scheme != 'https') + using_socks_proxy = False + if proxy: + proxy_scheme = urlparse(proxy).scheme.lower() + using_socks_proxy = proxy_scheme.startswith('socks') + + url = request.path_url + if is_proxied_http_request and not using_socks_proxy: + url = urldefragauth(request.url) + + return url + + def add_headers(self, request, **kwargs): + """Add any headers needed by the connection. As of v2.0 this does + nothing by default, but is left for overriding by users that subclass + the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to. + :param kwargs: The keyword arguments from the call to send(). + """ + pass + + def proxy_headers(self, proxy): + """Returns a dictionary of the headers to add to any request sent + through a proxy. This works with urllib3 magic to ensure that they are + correctly sent to the proxy, rather than in a tunnelled request if + CONNECT is being used. + + This should not be called from user code, and is only exposed for use + when subclassing the + :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`. + + :param proxies: The url of the proxy being used for this request. + :rtype: dict + """ + headers = {} + username, password = get_auth_from_url(proxy) + + if username: + headers['Proxy-Authorization'] = _basic_auth_str(username, + password) + + return headers + + def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): + """Sends PreparedRequest object. Returns Response object. + + :param request: The :class:`PreparedRequest <PreparedRequest>` being sent. + :param stream: (optional) Whether to stream the request content. + :param timeout: (optional) How long to wait for the server to send + data before giving up, as a float, or a :ref:`(connect timeout, + read timeout) <timeouts>` tuple. + :type timeout: float or tuple or urllib3 Timeout object + :param verify: (optional) Either a boolean, in which case it controls whether + we verify the server's TLS certificate, or a string, in which case it + must be a path to a CA bundle to use + :param cert: (optional) Any user-provided SSL certificate to be trusted. + :param proxies: (optional) The proxies dictionary to apply to the request. + :rtype: requests.Response + """ + + conn = self.get_connection(request.url, proxies) + + self.cert_verify(conn, request.url, verify, cert) + url = self.request_url(request, proxies) + self.add_headers(request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies) + + chunked = not (request.body is None or 'Content-Length' in request.headers) + + if isinstance(timeout, tuple): + try: + connect, read = timeout + timeout = TimeoutSauce(connect=connect, read=read) + except ValueError as e: + # this may raise a string formatting error. + err = ("Invalid timeout {0}. Pass a (connect, read) " + "timeout tuple, or a single float to set " + "both timeouts to the same value".format(timeout)) + raise ValueError(err) + elif isinstance(timeout, TimeoutSauce): + pass + else: + timeout = TimeoutSauce(connect=timeout, read=timeout) + + try: + if not chunked: + resp = conn.urlopen( + method=request.method, + url=url, + body=request.body, + headers=request.headers, + redirect=False, + assert_same_host=False, + preload_content=False, + decode_content=False, + retries=self.max_retries, + timeout=timeout + ) + + # Send the request. + else: + if hasattr(conn, 'proxy_pool'): + conn = conn.proxy_pool + + low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT) + + try: + low_conn.putrequest(request.method, + url, + skip_accept_encoding=True) + + for header, value in request.headers.items(): + low_conn.putheader(header, value) + + low_conn.endheaders() + + for i in request.body: + low_conn.send(hex(len(i))[2:].encode('utf-8')) + low_conn.send(b'\r\n') + low_conn.send(i) + low_conn.send(b'\r\n') + low_conn.send(b'0\r\n\r\n') + + # Receive the response from the server + try: + # For Python 2.7+ versions, use buffering of HTTP + # responses + r = low_conn.getresponse(buffering=True) + except TypeError: + # For compatibility with Python 2.6 versions and back + r = low_conn.getresponse() + + resp = HTTPResponse.from_httplib( + r, + pool=conn, + connection=low_conn, + preload_content=False, + decode_content=False + ) + except: + # If we hit any problems here, clean up the connection. + # Then, reraise so that we can handle the actual exception. + low_conn.close() + raise + + except (ProtocolError, socket.error) as err: + raise ConnectionError(err, request=request) + + except MaxRetryError as e: + if isinstance(e.reason, ConnectTimeoutError): + # TODO: Remove this in 3.0.0: see #2811 + if not isinstance(e.reason, NewConnectionError): + raise ConnectTimeout(e, request=request) + + if isinstance(e.reason, ResponseError): + raise RetryError(e, request=request) + + if isinstance(e.reason, _ProxyError): + raise ProxyError(e, request=request) + + if isinstance(e.reason, _SSLError): + # This branch is for urllib3 v1.22 and later. + raise SSLError(e, request=request) + + raise ConnectionError(e, request=request) + + except ClosedPoolError as e: + raise ConnectionError(e, request=request) + + except _ProxyError as e: + raise ProxyError(e) + + except (_SSLError, _HTTPError) as e: + if isinstance(e, _SSLError): + # This branch is for urllib3 versions earlier than v1.22 + raise SSLError(e, request=request) + elif isinstance(e, ReadTimeoutError): + raise ReadTimeout(e, request=request) + else: + raise + + return self.build_response(request, resp) diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/api.py b/winvenv/Lib/site-packages/pip/_vendor/requests/api.py new file mode 100644 index 0000000..a2cc84d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/api.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- + +""" +requests.api +~~~~~~~~~~~~ + +This module implements the Requests API. + +:copyright: (c) 2012 by Kenneth Reitz. +:license: Apache2, see LICENSE for more details. +""" + +from . import sessions + + +def request(method, url, **kwargs): + """Constructs and sends a :class:`Request <Request>`. + + :param method: method for the new :class:`Request` object. + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. + :param data: (optional) Dictionary or list of tuples ``[(key, value)]`` (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. + :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. + :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. + ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` + or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string + defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers + to add for the file. + :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. + :param timeout: (optional) How many seconds to wait for the server to send data + before giving up, as a float, or a :ref:`(connect timeout, read + timeout) <timeouts>` tuple. + :type timeout: float or tuple + :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``. + :type allow_redirects: bool + :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use. Defaults to ``True``. + :param stream: (optional) if ``False``, the response content will be immediately downloaded. + :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. + :return: :class:`Response <Response>` object + :rtype: requests.Response + + Usage:: + + >>> import requests + >>> req = requests.request('GET', 'http://httpbin.org/get') + <Response [200]> + """ + + # By using the 'with' statement we are sure the session is closed, thus we + # avoid leaving sockets open which can trigger a ResourceWarning in some + # cases, and look like a memory leak in others. + with sessions.Session() as session: + return session.request(method=method, url=url, **kwargs) + + +def get(url, params=None, **kwargs): + r"""Sends a GET request. + + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return request('get', url, params=params, **kwargs) + + +def options(url, **kwargs): + r"""Sends an OPTIONS request. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return request('options', url, **kwargs) + + +def head(url, **kwargs): + r"""Sends a HEAD request. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', False) + return request('head', url, **kwargs) + + +def post(url, data=None, json=None, **kwargs): + r"""Sends a POST request. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('post', url, data=data, json=json, **kwargs) + + +def put(url, data=None, **kwargs): + r"""Sends a PUT request. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('put', url, data=data, **kwargs) + + +def patch(url, data=None, **kwargs): + r"""Sends a PATCH request. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('patch', url, data=data, **kwargs) + + +def delete(url, **kwargs): + r"""Sends a DELETE request. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :return: :class:`Response <Response>` object + :rtype: requests.Response + """ + + return request('delete', url, **kwargs) diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/auth.py b/winvenv/Lib/site-packages/pip/_vendor/requests/auth.py new file mode 100644 index 0000000..4ae4594 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/auth.py @@ -0,0 +1,305 @@ +# -*- coding: utf-8 -*- + +""" +requests.auth +~~~~~~~~~~~~~ + +This module contains the authentication handlers for Requests. +""" + +import os +import re +import time +import hashlib +import threading +import warnings + +from base64 import b64encode + +from .compat import urlparse, str, basestring +from .cookies import extract_cookies_to_jar +from ._internal_utils import to_native_string +from .utils import parse_dict_header + +CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded' +CONTENT_TYPE_MULTI_PART = 'multipart/form-data' + + +def _basic_auth_str(username, password): + """Returns a Basic Auth string.""" + + # "I want us to put a big-ol' comment on top of it that + # says that this behaviour is dumb but we need to preserve + # it because people are relying on it." + # - Lukasa + # + # These are here solely to maintain backwards compatibility + # for things like ints. This will be removed in 3.0.0. + if not isinstance(username, basestring): + warnings.warn( + "Non-string usernames will no longer be supported in Requests " + "3.0.0. Please convert the object you've passed in ({0!r}) to " + "a string or bytes object in the near future to avoid " + "problems.".format(username), + category=DeprecationWarning, + ) + username = str(username) + + if not isinstance(password, basestring): + warnings.warn( + "Non-string passwords will no longer be supported in Requests " + "3.0.0. Please convert the object you've passed in ({0!r}) to " + "a string or bytes object in the near future to avoid " + "problems.".format(password), + category=DeprecationWarning, + ) + password = str(password) + # -- End Removal -- + + if isinstance(username, str): + username = username.encode('latin1') + + if isinstance(password, str): + password = password.encode('latin1') + + authstr = 'Basic ' + to_native_string( + b64encode(b':'.join((username, password))).strip() + ) + + return authstr + + +class AuthBase(object): + """Base class that all auth implementations derive from""" + + def __call__(self, r): + raise NotImplementedError('Auth hooks must be callable.') + + +class HTTPBasicAuth(AuthBase): + """Attaches HTTP Basic Authentication to the given Request object.""" + + def __init__(self, username, password): + self.username = username + self.password = password + + def __eq__(self, other): + return all([ + self.username == getattr(other, 'username', None), + self.password == getattr(other, 'password', None) + ]) + + def __ne__(self, other): + return not self == other + + def __call__(self, r): + r.headers['Authorization'] = _basic_auth_str(self.username, self.password) + return r + + +class HTTPProxyAuth(HTTPBasicAuth): + """Attaches HTTP Proxy Authentication to a given Request object.""" + + def __call__(self, r): + r.headers['Proxy-Authorization'] = _basic_auth_str(self.username, self.password) + return r + + +class HTTPDigestAuth(AuthBase): + """Attaches HTTP Digest Authentication to the given Request object.""" + + def __init__(self, username, password): + self.username = username + self.password = password + # Keep state in per-thread local storage + self._thread_local = threading.local() + + def init_per_thread_state(self): + # Ensure state is initialized just once per-thread + if not hasattr(self._thread_local, 'init'): + self._thread_local.init = True + self._thread_local.last_nonce = '' + self._thread_local.nonce_count = 0 + self._thread_local.chal = {} + self._thread_local.pos = None + self._thread_local.num_401_calls = None + + def build_digest_header(self, method, url): + """ + :rtype: str + """ + + realm = self._thread_local.chal['realm'] + nonce = self._thread_local.chal['nonce'] + qop = self._thread_local.chal.get('qop') + algorithm = self._thread_local.chal.get('algorithm') + opaque = self._thread_local.chal.get('opaque') + hash_utf8 = None + + if algorithm is None: + _algorithm = 'MD5' + else: + _algorithm = algorithm.upper() + # lambdas assume digest modules are imported at the top level + if _algorithm == 'MD5' or _algorithm == 'MD5-SESS': + def md5_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.md5(x).hexdigest() + hash_utf8 = md5_utf8 + elif _algorithm == 'SHA': + def sha_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha1(x).hexdigest() + hash_utf8 = sha_utf8 + elif _algorithm == 'SHA-256': + def sha256_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha256(x).hexdigest() + hash_utf8 = sha256_utf8 + elif _algorithm == 'SHA-512': + def sha512_utf8(x): + if isinstance(x, str): + x = x.encode('utf-8') + return hashlib.sha512(x).hexdigest() + hash_utf8 = sha512_utf8 + + KD = lambda s, d: hash_utf8("%s:%s" % (s, d)) + + if hash_utf8 is None: + return None + + # XXX not implemented yet + entdig = None + p_parsed = urlparse(url) + #: path is request-uri defined in RFC 2616 which should not be empty + path = p_parsed.path or "/" + if p_parsed.query: + path += '?' + p_parsed.query + + A1 = '%s:%s:%s' % (self.username, realm, self.password) + A2 = '%s:%s' % (method, path) + + HA1 = hash_utf8(A1) + HA2 = hash_utf8(A2) + + if nonce == self._thread_local.last_nonce: + self._thread_local.nonce_count += 1 + else: + self._thread_local.nonce_count = 1 + ncvalue = '%08x' % self._thread_local.nonce_count + s = str(self._thread_local.nonce_count).encode('utf-8') + s += nonce.encode('utf-8') + s += time.ctime().encode('utf-8') + s += os.urandom(8) + + cnonce = (hashlib.sha1(s).hexdigest()[:16]) + if _algorithm == 'MD5-SESS': + HA1 = hash_utf8('%s:%s:%s' % (HA1, nonce, cnonce)) + + if not qop: + respdig = KD(HA1, "%s:%s" % (nonce, HA2)) + elif qop == 'auth' or 'auth' in qop.split(','): + noncebit = "%s:%s:%s:%s:%s" % ( + nonce, ncvalue, cnonce, 'auth', HA2 + ) + respdig = KD(HA1, noncebit) + else: + # XXX handle auth-int. + return None + + self._thread_local.last_nonce = nonce + + # XXX should the partial digests be encoded too? + base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \ + 'response="%s"' % (self.username, realm, nonce, path, respdig) + if opaque: + base += ', opaque="%s"' % opaque + if algorithm: + base += ', algorithm="%s"' % algorithm + if entdig: + base += ', digest="%s"' % entdig + if qop: + base += ', qop="auth", nc=%s, cnonce="%s"' % (ncvalue, cnonce) + + return 'Digest %s' % (base) + + def handle_redirect(self, r, **kwargs): + """Reset num_401_calls counter on redirects.""" + if r.is_redirect: + self._thread_local.num_401_calls = 1 + + def handle_401(self, r, **kwargs): + """ + Takes the given response and tries digest-auth, if needed. + + :rtype: requests.Response + """ + + # If response is not 4xx, do not auth + # See https://github.com/requests/requests/issues/3772 + if not 400 <= r.status_code < 500: + self._thread_local.num_401_calls = 1 + return r + + if self._thread_local.pos is not None: + # Rewind the file position indicator of the body to where + # it was to resend the request. + r.request.body.seek(self._thread_local.pos) + s_auth = r.headers.get('www-authenticate', '') + + if 'digest' in s_auth.lower() and self._thread_local.num_401_calls < 2: + + self._thread_local.num_401_calls += 1 + pat = re.compile(r'digest ', flags=re.IGNORECASE) + self._thread_local.chal = parse_dict_header(pat.sub('', s_auth, count=1)) + + # Consume content and release the original connection + # to allow our new request to reuse the same one. + r.content + r.close() + prep = r.request.copy() + extract_cookies_to_jar(prep._cookies, r.request, r.raw) + prep.prepare_cookies(prep._cookies) + + prep.headers['Authorization'] = self.build_digest_header( + prep.method, prep.url) + _r = r.connection.send(prep, **kwargs) + _r.history.append(r) + _r.request = prep + + return _r + + self._thread_local.num_401_calls = 1 + return r + + def __call__(self, r): + # Initialize per-thread state, if needed + self.init_per_thread_state() + # If we have a saved nonce, skip the 401 + if self._thread_local.last_nonce: + r.headers['Authorization'] = self.build_digest_header(r.method, r.url) + try: + self._thread_local.pos = r.body.tell() + except AttributeError: + # In the case of HTTPDigestAuth being reused and the body of + # the previous request was a file-like object, pos has the + # file position of the previous body. Ensure it's set to + # None. + self._thread_local.pos = None + r.register_hook('response', self.handle_401) + r.register_hook('response', self.handle_redirect) + self._thread_local.num_401_calls = 1 + + return r + + def __eq__(self, other): + return all([ + self.username == getattr(other, 'username', None), + self.password == getattr(other, 'password', None) + ]) + + def __ne__(self, other): + return not self == other diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/certs.py b/winvenv/Lib/site-packages/pip/_vendor/requests/certs.py new file mode 100644 index 0000000..06a594e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/certs.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +requests.certs +~~~~~~~~~~~~~~ + +This module returns the preferred default CA certificate bundle. There is +only one — the one from the certifi package. + +If you are packaging Requests, e.g., for a Linux distribution or a managed +environment, you can change the definition of where() to return a separately +packaged CA bundle. +""" +from pip._vendor.certifi import where + +if __name__ == '__main__': + print(where()) diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/compat.py b/winvenv/Lib/site-packages/pip/_vendor/requests/compat.py new file mode 100644 index 0000000..ec5d305 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/compat.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- + +""" +requests.compat +~~~~~~~~~~~~~~~ + +This module handles import compatibility issues between Python 2 and +Python 3. +""" + +from pip._vendor import chardet + +import sys + +# ------- +# Pythons +# ------- + +# Syntax sugar. +_ver = sys.version_info + +#: Python 2.x? +is_py2 = (_ver[0] == 2) + +#: Python 3.x? +is_py3 = (_ver[0] == 3) + +# Note: We've patched out simplejson support in pip because it prevents +# upgrading simplejson on Windows. +# try: +# import simplejson as json +# except (ImportError, SyntaxError): +# # simplejson does not support Python 3.2, it throws a SyntaxError +# # because of u'...' Unicode literals. +import json + +# --------- +# Specifics +# --------- + +if is_py2: + from urllib import ( + quote, unquote, quote_plus, unquote_plus, urlencode, getproxies, + proxy_bypass, proxy_bypass_environment, getproxies_environment) + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urldefrag + from urllib2 import parse_http_list + import cookielib + from Cookie import Morsel + from StringIO import StringIO + from collections import Callable, Mapping, MutableMapping + + from pip._vendor.urllib3.packages.ordered_dict import OrderedDict + + builtin_str = str + bytes = str + str = unicode + basestring = basestring + numeric_types = (int, long, float) + integer_types = (int, long) + +elif is_py3: + from urllib.parse import urlparse, urlunparse, urljoin, urlsplit, urlencode, quote, unquote, quote_plus, unquote_plus, urldefrag + from urllib.request import parse_http_list, getproxies, proxy_bypass, proxy_bypass_environment, getproxies_environment + from http import cookiejar as cookielib + from http.cookies import Morsel + from io import StringIO + from collections import OrderedDict + from collections.abc import Callable, Mapping, MutableMapping + + builtin_str = str + str = str + bytes = bytes + basestring = (str, bytes) + numeric_types = (int, float) + integer_types = (int,) diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/cookies.py b/winvenv/Lib/site-packages/pip/_vendor/requests/cookies.py new file mode 100644 index 0000000..50883a8 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/cookies.py @@ -0,0 +1,546 @@ +# -*- coding: utf-8 -*- + +""" +requests.cookies +~~~~~~~~~~~~~~~~ + +Compatibility code to be able to use `cookielib.CookieJar` with requests. + +requests.utils imports from here, so be careful with imports. +""" + +import copy +import time +import calendar + +from ._internal_utils import to_native_string +from .compat import cookielib, urlparse, urlunparse, Morsel, MutableMapping + +try: + import threading +except ImportError: + import dummy_threading as threading + + +class MockRequest(object): + """Wraps a `requests.Request` to mimic a `urllib2.Request`. + + The code in `cookielib.CookieJar` expects this interface in order to correctly + manage cookie policies, i.e., determine whether a cookie can be set, given the + domains of the request and the cookie. + + The original request object is read-only. The client is responsible for collecting + the new headers via `get_new_headers()` and interpreting them appropriately. You + probably want `get_cookie_header`, defined below. + """ + + def __init__(self, request): + self._r = request + self._new_headers = {} + self.type = urlparse(self._r.url).scheme + + def get_type(self): + return self.type + + def get_host(self): + return urlparse(self._r.url).netloc + + def get_origin_req_host(self): + return self.get_host() + + def get_full_url(self): + # Only return the response's URL if the user hadn't set the Host + # header + if not self._r.headers.get('Host'): + return self._r.url + # If they did set it, retrieve it and reconstruct the expected domain + host = to_native_string(self._r.headers['Host'], encoding='utf-8') + parsed = urlparse(self._r.url) + # Reconstruct the URL as we expect it + return urlunparse([ + parsed.scheme, host, parsed.path, parsed.params, parsed.query, + parsed.fragment + ]) + + def is_unverifiable(self): + return True + + def has_header(self, name): + return name in self._r.headers or name in self._new_headers + + def get_header(self, name, default=None): + return self._r.headers.get(name, self._new_headers.get(name, default)) + + def add_header(self, key, val): + """cookielib has no legitimate use for this method; add it back if you find one.""" + raise NotImplementedError("Cookie headers should be added with add_unredirected_header()") + + def add_unredirected_header(self, name, value): + self._new_headers[name] = value + + def get_new_headers(self): + return self._new_headers + + @property + def unverifiable(self): + return self.is_unverifiable() + + @property + def origin_req_host(self): + return self.get_origin_req_host() + + @property + def host(self): + return self.get_host() + + +class MockResponse(object): + """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. + + ...what? Basically, expose the parsed HTTP headers from the server response + the way `cookielib` expects to see them. + """ + + def __init__(self, headers): + """Make a MockResponse for `cookielib` to read. + + :param headers: a httplib.HTTPMessage or analogous carrying the headers + """ + self._headers = headers + + def info(self): + return self._headers + + def getheaders(self, name): + self._headers.getheaders(name) + + +def extract_cookies_to_jar(jar, request, response): + """Extract the cookies from the response into a CookieJar. + + :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) + :param request: our own requests.Request object + :param response: urllib3.HTTPResponse object + """ + if not (hasattr(response, '_original_response') and + response._original_response): + return + # the _original_response field is the wrapped httplib.HTTPResponse object, + req = MockRequest(request) + # pull out the HTTPMessage with the headers and put it in the mock: + res = MockResponse(response._original_response.msg) + jar.extract_cookies(res, req) + + +def get_cookie_header(jar, request): + """ + Produce an appropriate Cookie header string to be sent with `request`, or None. + + :rtype: str + """ + r = MockRequest(request) + jar.add_cookie_header(r) + return r.get_new_headers().get('Cookie') + + +def remove_cookie_by_name(cookiejar, name, domain=None, path=None): + """Unsets a cookie by name, by default over all domains and paths. + + Wraps CookieJar.clear(), is O(n). + """ + clearables = [] + for cookie in cookiejar: + if cookie.name != name: + continue + if domain is not None and domain != cookie.domain: + continue + if path is not None and path != cookie.path: + continue + clearables.append((cookie.domain, cookie.path, cookie.name)) + + for domain, path, name in clearables: + cookiejar.clear(domain, path, name) + + +class CookieConflictError(RuntimeError): + """There are two cookies that meet the criteria specified in the cookie jar. + Use .get and .set and include domain and path args in order to be more specific. + """ + + +class RequestsCookieJar(cookielib.CookieJar, MutableMapping): + """Compatibility class; is a cookielib.CookieJar, but exposes a dict + interface. + + This is the CookieJar we create by default for requests and sessions that + don't specify one, since some clients may expect response.cookies and + session.cookies to support dict operations. + + Requests does not use the dict interface internally; it's just for + compatibility with external client code. All requests code should work + out of the box with externally provided instances of ``CookieJar``, e.g. + ``LWPCookieJar`` and ``FileCookieJar``. + + Unlike a regular CookieJar, this class is pickleable. + + .. warning:: dictionary operations that are normally O(1) may be O(n). + """ + + def get(self, name, default=None, domain=None, path=None): + """Dict-like get() that also supports optional domain and path args in + order to resolve naming collisions from using one cookie jar over + multiple domains. + + .. warning:: operation is O(n), not O(1). + """ + try: + return self._find_no_duplicates(name, domain, path) + except KeyError: + return default + + def set(self, name, value, **kwargs): + """Dict-like set() that also supports optional domain and path args in + order to resolve naming collisions from using one cookie jar over + multiple domains. + """ + # support client code that unsets cookies by assignment of a None value: + if value is None: + remove_cookie_by_name(self, name, domain=kwargs.get('domain'), path=kwargs.get('path')) + return + + if isinstance(value, Morsel): + c = morsel_to_cookie(value) + else: + c = create_cookie(name, value, **kwargs) + self.set_cookie(c) + return c + + def iterkeys(self): + """Dict-like iterkeys() that returns an iterator of names of cookies + from the jar. + + .. seealso:: itervalues() and iteritems(). + """ + for cookie in iter(self): + yield cookie.name + + def keys(self): + """Dict-like keys() that returns a list of names of cookies from the + jar. + + .. seealso:: values() and items(). + """ + return list(self.iterkeys()) + + def itervalues(self): + """Dict-like itervalues() that returns an iterator of values of cookies + from the jar. + + .. seealso:: iterkeys() and iteritems(). + """ + for cookie in iter(self): + yield cookie.value + + def values(self): + """Dict-like values() that returns a list of values of cookies from the + jar. + + .. seealso:: keys() and items(). + """ + return list(self.itervalues()) + + def iteritems(self): + """Dict-like iteritems() that returns an iterator of name-value tuples + from the jar. + + .. seealso:: iterkeys() and itervalues(). + """ + for cookie in iter(self): + yield cookie.name, cookie.value + + def items(self): + """Dict-like items() that returns a list of name-value tuples from the + jar. Allows client-code to call ``dict(RequestsCookieJar)`` and get a + vanilla python dict of key value pairs. + + .. seealso:: keys() and values(). + """ + return list(self.iteritems()) + + def list_domains(self): + """Utility method to list all the domains in the jar.""" + domains = [] + for cookie in iter(self): + if cookie.domain not in domains: + domains.append(cookie.domain) + return domains + + def list_paths(self): + """Utility method to list all the paths in the jar.""" + paths = [] + for cookie in iter(self): + if cookie.path not in paths: + paths.append(cookie.path) + return paths + + def multiple_domains(self): + """Returns True if there are multiple domains in the jar. + Returns False otherwise. + + :rtype: bool + """ + domains = [] + for cookie in iter(self): + if cookie.domain is not None and cookie.domain in domains: + return True + domains.append(cookie.domain) + return False # there is only one domain in jar + + def get_dict(self, domain=None, path=None): + """Takes as an argument an optional domain and path and returns a plain + old Python dict of name-value pairs of cookies that meet the + requirements. + + :rtype: dict + """ + dictionary = {} + for cookie in iter(self): + if ( + (domain is None or cookie.domain == domain) and + (path is None or cookie.path == path) + ): + dictionary[cookie.name] = cookie.value + return dictionary + + def __contains__(self, name): + try: + return super(RequestsCookieJar, self).__contains__(name) + except CookieConflictError: + return True + + def __getitem__(self, name): + """Dict-like __getitem__() for compatibility with client code. Throws + exception if there are more than one cookie with name. In that case, + use the more explicit get() method instead. + + .. warning:: operation is O(n), not O(1). + """ + return self._find_no_duplicates(name) + + def __setitem__(self, name, value): + """Dict-like __setitem__ for compatibility with client code. Throws + exception if there is already a cookie of that name in the jar. In that + case, use the more explicit set() method instead. + """ + self.set(name, value) + + def __delitem__(self, name): + """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s + ``remove_cookie_by_name()``. + """ + remove_cookie_by_name(self, name) + + def set_cookie(self, cookie, *args, **kwargs): + if hasattr(cookie.value, 'startswith') and cookie.value.startswith('"') and cookie.value.endswith('"'): + cookie.value = cookie.value.replace('\\"', '') + return super(RequestsCookieJar, self).set_cookie(cookie, *args, **kwargs) + + def update(self, other): + """Updates this jar with cookies from another CookieJar or dict-like""" + if isinstance(other, cookielib.CookieJar): + for cookie in other: + self.set_cookie(copy.copy(cookie)) + else: + super(RequestsCookieJar, self).update(other) + + def _find(self, name, domain=None, path=None): + """Requests uses this method internally to get cookie values. + + If there are conflicting cookies, _find arbitrarily chooses one. + See _find_no_duplicates if you want an exception thrown if there are + conflicting cookies. + + :param name: a string containing name of cookie + :param domain: (optional) string containing domain of cookie + :param path: (optional) string containing path of cookie + :return: cookie.value + """ + for cookie in iter(self): + if cookie.name == name: + if domain is None or cookie.domain == domain: + if path is None or cookie.path == path: + return cookie.value + + raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) + + def _find_no_duplicates(self, name, domain=None, path=None): + """Both ``__get_item__`` and ``get`` call this function: it's never + used elsewhere in Requests. + + :param name: a string containing name of cookie + :param domain: (optional) string containing domain of cookie + :param path: (optional) string containing path of cookie + :raises KeyError: if cookie is not found + :raises CookieConflictError: if there are multiple cookies + that match name and optionally domain and path + :return: cookie.value + """ + toReturn = None + for cookie in iter(self): + if cookie.name == name: + if domain is None or cookie.domain == domain: + if path is None or cookie.path == path: + if toReturn is not None: # if there are multiple cookies that meet passed in criteria + raise CookieConflictError('There are multiple cookies with name, %r' % (name)) + toReturn = cookie.value # we will eventually return this as long as no cookie conflict + + if toReturn: + return toReturn + raise KeyError('name=%r, domain=%r, path=%r' % (name, domain, path)) + + def __getstate__(self): + """Unlike a normal CookieJar, this class is pickleable.""" + state = self.__dict__.copy() + # remove the unpickleable RLock object + state.pop('_cookies_lock') + return state + + def __setstate__(self, state): + """Unlike a normal CookieJar, this class is pickleable.""" + self.__dict__.update(state) + if '_cookies_lock' not in self.__dict__: + self._cookies_lock = threading.RLock() + + def copy(self): + """Return a copy of this RequestsCookieJar.""" + new_cj = RequestsCookieJar() + new_cj.set_policy(self.get_policy()) + new_cj.update(self) + return new_cj + + def get_policy(self): + """Return the CookiePolicy instance used.""" + return self._policy + + +def _copy_cookie_jar(jar): + if jar is None: + return None + + if hasattr(jar, 'copy'): + # We're dealing with an instance of RequestsCookieJar + return jar.copy() + # We're dealing with a generic CookieJar instance + new_jar = copy.copy(jar) + new_jar.clear() + for cookie in jar: + new_jar.set_cookie(copy.copy(cookie)) + return new_jar + + +def create_cookie(name, value, **kwargs): + """Make a cookie from underspecified parameters. + + By default, the pair of `name` and `value` will be set for the domain '' + and sent on every request (this is sometimes called a "supercookie"). + """ + result = dict( + version=0, + name=name, + value=value, + port=None, + domain='', + path='/', + secure=False, + expires=None, + discard=True, + comment=None, + comment_url=None, + rest={'HttpOnly': None}, + rfc2109=False,) + + badargs = set(kwargs) - set(result) + if badargs: + err = 'create_cookie() got unexpected keyword arguments: %s' + raise TypeError(err % list(badargs)) + + result.update(kwargs) + result['port_specified'] = bool(result['port']) + result['domain_specified'] = bool(result['domain']) + result['domain_initial_dot'] = result['domain'].startswith('.') + result['path_specified'] = bool(result['path']) + + return cookielib.Cookie(**result) + + +def morsel_to_cookie(morsel): + """Convert a Morsel object into a Cookie containing the one k/v pair.""" + + expires = None + if morsel['max-age']: + try: + expires = int(time.time() + int(morsel['max-age'])) + except ValueError: + raise TypeError('max-age: %s must be integer' % morsel['max-age']) + elif morsel['expires']: + time_template = '%a, %d-%b-%Y %H:%M:%S GMT' + expires = calendar.timegm( + time.strptime(morsel['expires'], time_template) + ) + return create_cookie( + comment=morsel['comment'], + comment_url=bool(morsel['comment']), + discard=False, + domain=morsel['domain'], + expires=expires, + name=morsel.key, + path=morsel['path'], + port=None, + rest={'HttpOnly': morsel['httponly']}, + rfc2109=False, + secure=bool(morsel['secure']), + value=morsel.value, + version=morsel['version'] or 0, + ) + + +def cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True): + """Returns a CookieJar from a key/value dictionary. + + :param cookie_dict: Dict of key/values to insert into CookieJar. + :param cookiejar: (optional) A cookiejar to add the cookies to. + :param overwrite: (optional) If False, will not replace cookies + already in the jar with new ones. + """ + if cookiejar is None: + cookiejar = RequestsCookieJar() + + if cookie_dict is not None: + names_from_jar = [cookie.name for cookie in cookiejar] + for name in cookie_dict: + if overwrite or (name not in names_from_jar): + cookiejar.set_cookie(create_cookie(name, cookie_dict[name])) + + return cookiejar + + +def merge_cookies(cookiejar, cookies): + """Add cookies to cookiejar and returns a merged CookieJar. + + :param cookiejar: CookieJar object to add the cookies to. + :param cookies: Dictionary or CookieJar object to be added. + """ + if not isinstance(cookiejar, cookielib.CookieJar): + raise ValueError('You can only merge into CookieJar') + + if isinstance(cookies, dict): + cookiejar = cookiejar_from_dict( + cookies, cookiejar=cookiejar, overwrite=False) + elif isinstance(cookies, cookielib.CookieJar): + try: + cookiejar.update(cookies) + except AttributeError: + for cookie_in_jar in cookies: + cookiejar.set_cookie(cookie_in_jar) + + return cookiejar diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/exceptions.py b/winvenv/Lib/site-packages/pip/_vendor/requests/exceptions.py new file mode 100644 index 0000000..a91e1fd --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/exceptions.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- + +""" +requests.exceptions +~~~~~~~~~~~~~~~~~~~ + +This module contains the set of Requests' exceptions. +""" +from pip._vendor.urllib3.exceptions import HTTPError as BaseHTTPError + + +class RequestException(IOError): + """There was an ambiguous exception that occurred while handling your + request. + """ + + def __init__(self, *args, **kwargs): + """Initialize RequestException with `request` and `response` objects.""" + response = kwargs.pop('response', None) + self.response = response + self.request = kwargs.pop('request', None) + if (response is not None and not self.request and + hasattr(response, 'request')): + self.request = self.response.request + super(RequestException, self).__init__(*args, **kwargs) + + +class HTTPError(RequestException): + """An HTTP error occurred.""" + + +class ConnectionError(RequestException): + """A Connection error occurred.""" + + +class ProxyError(ConnectionError): + """A proxy error occurred.""" + + +class SSLError(ConnectionError): + """An SSL error occurred.""" + + +class Timeout(RequestException): + """The request timed out. + + Catching this error will catch both + :exc:`~requests.exceptions.ConnectTimeout` and + :exc:`~requests.exceptions.ReadTimeout` errors. + """ + + +class ConnectTimeout(ConnectionError, Timeout): + """The request timed out while trying to connect to the remote server. + + Requests that produced this error are safe to retry. + """ + + +class ReadTimeout(Timeout): + """The server did not send any data in the allotted amount of time.""" + + +class URLRequired(RequestException): + """A valid URL is required to make a request.""" + + +class TooManyRedirects(RequestException): + """Too many redirects.""" + + +class MissingSchema(RequestException, ValueError): + """The URL schema (e.g. http or https) is missing.""" + + +class InvalidSchema(RequestException, ValueError): + """See defaults.py for valid schemas.""" + + +class InvalidURL(RequestException, ValueError): + """The URL provided was somehow invalid.""" + + +class InvalidHeader(RequestException, ValueError): + """The header value provided was somehow invalid.""" + + +class InvalidProxyURL(InvalidURL): + """The proxy URL provided is invalid.""" + + +class ChunkedEncodingError(RequestException): + """The server declared chunked encoding but sent an invalid chunk.""" + + +class ContentDecodingError(RequestException, BaseHTTPError): + """Failed to decode response content""" + + +class StreamConsumedError(RequestException, TypeError): + """The content for this response was already consumed""" + + +class RetryError(RequestException): + """Custom retries logic failed""" + + +class UnrewindableBodyError(RequestException): + """Requests encountered an error when trying to rewind a body""" + +# Warnings + + +class RequestsWarning(Warning): + """Base warning for Requests.""" + pass + + +class FileModeWarning(RequestsWarning, DeprecationWarning): + """A file was opened in text mode, but Requests determined its binary length.""" + pass + + +class RequestsDependencyWarning(RequestsWarning): + """An imported dependency doesn't match the expected version range.""" + pass diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/help.py b/winvenv/Lib/site-packages/pip/_vendor/requests/help.py new file mode 100644 index 0000000..df1b4eb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/help.py @@ -0,0 +1,120 @@ +"""Module containing bug report helper(s).""" +from __future__ import print_function + +import json +import platform +import sys +import ssl + +from pip._vendor import idna +from pip._vendor import urllib3 +from pip._vendor import chardet + +from . import __version__ as requests_version + +try: + from pip._vendor.urllib3.contrib import pyopenssl +except ImportError: + pyopenssl = None + OpenSSL = None + cryptography = None +else: + import OpenSSL + import cryptography + + +def _implementation(): + """Return a dict with the Python implementation and version. + + Provide both the name and the version of the Python implementation + currently running. For example, on CPython 2.7.5 it will return + {'name': 'CPython', 'version': '2.7.5'}. + + This function works best on CPython and PyPy: in particular, it probably + doesn't work for Jython or IronPython. Future investigation should be done + to work out the correct shape of the code for those platforms. + """ + implementation = platform.python_implementation() + + if implementation == 'CPython': + implementation_version = platform.python_version() + elif implementation == 'PyPy': + implementation_version = '%s.%s.%s' % (sys.pypy_version_info.major, + sys.pypy_version_info.minor, + sys.pypy_version_info.micro) + if sys.pypy_version_info.releaselevel != 'final': + implementation_version = ''.join([ + implementation_version, sys.pypy_version_info.releaselevel + ]) + elif implementation == 'Jython': + implementation_version = platform.python_version() # Complete Guess + elif implementation == 'IronPython': + implementation_version = platform.python_version() # Complete Guess + else: + implementation_version = 'Unknown' + + return {'name': implementation, 'version': implementation_version} + + +def info(): + """Generate information for a bug report.""" + try: + platform_info = { + 'system': platform.system(), + 'release': platform.release(), + } + except IOError: + platform_info = { + 'system': 'Unknown', + 'release': 'Unknown', + } + + implementation_info = _implementation() + urllib3_info = {'version': urllib3.__version__} + chardet_info = {'version': chardet.__version__} + + pyopenssl_info = { + 'version': None, + 'openssl_version': '', + } + if OpenSSL: + pyopenssl_info = { + 'version': OpenSSL.__version__, + 'openssl_version': '%x' % OpenSSL.SSL.OPENSSL_VERSION_NUMBER, + } + cryptography_info = { + 'version': getattr(cryptography, '__version__', ''), + } + idna_info = { + 'version': getattr(idna, '__version__', ''), + } + + # OPENSSL_VERSION_NUMBER doesn't exist in the Python 2.6 ssl module. + system_ssl = getattr(ssl, 'OPENSSL_VERSION_NUMBER', None) + system_ssl_info = { + 'version': '%x' % system_ssl if system_ssl is not None else '' + } + + return { + 'platform': platform_info, + 'implementation': implementation_info, + 'system_ssl': system_ssl_info, + 'using_pyopenssl': pyopenssl is not None, + 'pyOpenSSL': pyopenssl_info, + 'urllib3': urllib3_info, + 'chardet': chardet_info, + 'cryptography': cryptography_info, + 'idna': idna_info, + 'requests': { + 'version': requests_version, + }, + } + + +def main(): + """Pretty-print the bug information as JSON.""" + print(json.dumps(info(), sort_keys=True, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/hooks.py b/winvenv/Lib/site-packages/pip/_vendor/requests/hooks.py new file mode 100644 index 0000000..32b32de --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/hooks.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +""" +requests.hooks +~~~~~~~~~~~~~~ + +This module provides the capabilities for the Requests hooks system. + +Available hooks: + +``response``: + The response generated from a Request. +""" +HOOKS = ['response'] + + +def default_hooks(): + return dict((event, []) for event in HOOKS) + +# TODO: response is the only one + + +def dispatch_hook(key, hooks, hook_data, **kwargs): + """Dispatches a hook dictionary on a given piece of data.""" + hooks = hooks or dict() + hooks = hooks.get(key) + if hooks: + if hasattr(hooks, '__call__'): + hooks = [hooks] + for hook in hooks: + _hook_data = hook(hook_data, **kwargs) + if _hook_data is not None: + hook_data = _hook_data + return hook_data diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/models.py b/winvenv/Lib/site-packages/pip/_vendor/requests/models.py new file mode 100644 index 0000000..4230535 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/models.py @@ -0,0 +1,952 @@ +# -*- coding: utf-8 -*- + +""" +requests.models +~~~~~~~~~~~~~~~ + +This module contains the primary objects that power Requests. +""" + +import datetime +import sys + +# Import encoding now, to avoid implicit import later. +# Implicit import within threads may cause LookupError when standard library is in a ZIP, +# such as in Embedded Python. See https://github.com/requests/requests/issues/3578. +import encodings.idna + +from pip._vendor.urllib3.fields import RequestField +from pip._vendor.urllib3.filepost import encode_multipart_formdata +from pip._vendor.urllib3.util import parse_url +from pip._vendor.urllib3.exceptions import ( + DecodeError, ReadTimeoutError, ProtocolError, LocationParseError) + +from io import UnsupportedOperation +from .hooks import default_hooks +from .structures import CaseInsensitiveDict + +from .auth import HTTPBasicAuth +from .cookies import cookiejar_from_dict, get_cookie_header, _copy_cookie_jar +from .exceptions import ( + HTTPError, MissingSchema, InvalidURL, ChunkedEncodingError, + ContentDecodingError, ConnectionError, StreamConsumedError) +from ._internal_utils import to_native_string, unicode_is_ascii +from .utils import ( + guess_filename, get_auth_from_url, requote_uri, + stream_decode_response_unicode, to_key_val_list, parse_header_links, + iter_slices, guess_json_utf, super_len, check_header_validity) +from .compat import ( + Callable, Mapping, + cookielib, urlunparse, urlsplit, urlencode, str, bytes, + is_py2, chardet, builtin_str, basestring) +from .compat import json as complexjson +from .status_codes import codes + +#: The set of HTTP status codes that indicate an automatically +#: processable redirect. +REDIRECT_STATI = ( + codes.moved, # 301 + codes.found, # 302 + codes.other, # 303 + codes.temporary_redirect, # 307 + codes.permanent_redirect, # 308 +) + +DEFAULT_REDIRECT_LIMIT = 30 +CONTENT_CHUNK_SIZE = 10 * 1024 +ITER_CHUNK_SIZE = 512 + + +class RequestEncodingMixin(object): + @property + def path_url(self): + """Build the path URL to use.""" + + url = [] + + p = urlsplit(self.url) + + path = p.path + if not path: + path = '/' + + url.append(path) + + query = p.query + if query: + url.append('?') + url.append(query) + + return ''.join(url) + + @staticmethod + def _encode_params(data): + """Encode parameters in a piece of data. + + Will successfully encode parameters when passed as a dict or a list of + 2-tuples. Order is retained if data is a list of 2-tuples but arbitrary + if parameters are supplied as a dict. + """ + + if isinstance(data, (str, bytes)): + return data + elif hasattr(data, 'read'): + return data + elif hasattr(data, '__iter__'): + result = [] + for k, vs in to_key_val_list(data): + if isinstance(vs, basestring) or not hasattr(vs, '__iter__'): + vs = [vs] + for v in vs: + if v is not None: + result.append( + (k.encode('utf-8') if isinstance(k, str) else k, + v.encode('utf-8') if isinstance(v, str) else v)) + return urlencode(result, doseq=True) + else: + return data + + @staticmethod + def _encode_files(files, data): + """Build the body for a multipart/form-data request. + + Will successfully encode files when passed as a dict or a list of + tuples. Order is retained if data is a list of tuples but arbitrary + if parameters are supplied as a dict. + The tuples may be 2-tuples (filename, fileobj), 3-tuples (filename, fileobj, contentype) + or 4-tuples (filename, fileobj, contentype, custom_headers). + """ + if (not files): + raise ValueError("Files must be provided.") + elif isinstance(data, basestring): + raise ValueError("Data must not be a string.") + + new_fields = [] + fields = to_key_val_list(data or {}) + files = to_key_val_list(files or {}) + + for field, val in fields: + if isinstance(val, basestring) or not hasattr(val, '__iter__'): + val = [val] + for v in val: + if v is not None: + # Don't call str() on bytestrings: in Py3 it all goes wrong. + if not isinstance(v, bytes): + v = str(v) + + new_fields.append( + (field.decode('utf-8') if isinstance(field, bytes) else field, + v.encode('utf-8') if isinstance(v, str) else v)) + + for (k, v) in files: + # support for explicit filename + ft = None + fh = None + if isinstance(v, (tuple, list)): + if len(v) == 2: + fn, fp = v + elif len(v) == 3: + fn, fp, ft = v + else: + fn, fp, ft, fh = v + else: + fn = guess_filename(v) or k + fp = v + + if isinstance(fp, (str, bytes, bytearray)): + fdata = fp + elif hasattr(fp, 'read'): + fdata = fp.read() + elif fp is None: + continue + else: + fdata = fp + + rf = RequestField(name=k, data=fdata, filename=fn, headers=fh) + rf.make_multipart(content_type=ft) + new_fields.append(rf) + + body, content_type = encode_multipart_formdata(new_fields) + + return body, content_type + + +class RequestHooksMixin(object): + def register_hook(self, event, hook): + """Properly register a hook.""" + + if event not in self.hooks: + raise ValueError('Unsupported event specified, with event name "%s"' % (event)) + + if isinstance(hook, Callable): + self.hooks[event].append(hook) + elif hasattr(hook, '__iter__'): + self.hooks[event].extend(h for h in hook if isinstance(h, Callable)) + + def deregister_hook(self, event, hook): + """Deregister a previously registered hook. + Returns True if the hook existed, False if not. + """ + + try: + self.hooks[event].remove(hook) + return True + except ValueError: + return False + + +class Request(RequestHooksMixin): + """A user-created :class:`Request <Request>` object. + + Used to prepare a :class:`PreparedRequest <PreparedRequest>`, which is sent to the server. + + :param method: HTTP method to use. + :param url: URL to send. + :param headers: dictionary of headers to send. + :param files: dictionary of {filename: fileobject} files to multipart upload. + :param data: the body to attach to the request. If a dictionary is provided, form-encoding will take place. + :param json: json for the body to attach to the request (if files or data is not specified). + :param params: dictionary of URL parameters to append to the URL. + :param auth: Auth handler or (user, pass) tuple. + :param cookies: dictionary or CookieJar of cookies to attach to this request. + :param hooks: dictionary of callback hooks, for internal usage. + + Usage:: + + >>> import requests + >>> req = requests.Request('GET', 'http://httpbin.org/get') + >>> req.prepare() + <PreparedRequest [GET]> + """ + + def __init__(self, + method=None, url=None, headers=None, files=None, data=None, + params=None, auth=None, cookies=None, hooks=None, json=None): + + # Default empty dicts for dict params. + data = [] if data is None else data + files = [] if files is None else files + headers = {} if headers is None else headers + params = {} if params is None else params + hooks = {} if hooks is None else hooks + + self.hooks = default_hooks() + for (k, v) in list(hooks.items()): + self.register_hook(event=k, hook=v) + + self.method = method + self.url = url + self.headers = headers + self.files = files + self.data = data + self.json = json + self.params = params + self.auth = auth + self.cookies = cookies + + def __repr__(self): + return '<Request [%s]>' % (self.method) + + def prepare(self): + """Constructs a :class:`PreparedRequest <PreparedRequest>` for transmission and returns it.""" + p = PreparedRequest() + p.prepare( + method=self.method, + url=self.url, + headers=self.headers, + files=self.files, + data=self.data, + json=self.json, + params=self.params, + auth=self.auth, + cookies=self.cookies, + hooks=self.hooks, + ) + return p + + +class PreparedRequest(RequestEncodingMixin, RequestHooksMixin): + """The fully mutable :class:`PreparedRequest <PreparedRequest>` object, + containing the exact bytes that will be sent to the server. + + Generated from either a :class:`Request <Request>` object or manually. + + Usage:: + + >>> import requests + >>> req = requests.Request('GET', 'http://httpbin.org/get') + >>> r = req.prepare() + <PreparedRequest [GET]> + + >>> s = requests.Session() + >>> s.send(r) + <Response [200]> + """ + + def __init__(self): + #: HTTP verb to send to the server. + self.method = None + #: HTTP URL to send the request to. + self.url = None + #: dictionary of HTTP headers. + self.headers = None + # The `CookieJar` used to create the Cookie header will be stored here + # after prepare_cookies is called + self._cookies = None + #: request body to send to the server. + self.body = None + #: dictionary of callback hooks, for internal usage. + self.hooks = default_hooks() + #: integer denoting starting position of a readable file-like body. + self._body_position = None + + def prepare(self, + method=None, url=None, headers=None, files=None, data=None, + params=None, auth=None, cookies=None, hooks=None, json=None): + """Prepares the entire request with the given parameters.""" + + self.prepare_method(method) + self.prepare_url(url, params) + self.prepare_headers(headers) + self.prepare_cookies(cookies) + self.prepare_body(data, files, json) + self.prepare_auth(auth, url) + + # Note that prepare_auth must be last to enable authentication schemes + # such as OAuth to work on a fully prepared request. + + # This MUST go after prepare_auth. Authenticators could add a hook + self.prepare_hooks(hooks) + + def __repr__(self): + return '<PreparedRequest [%s]>' % (self.method) + + def copy(self): + p = PreparedRequest() + p.method = self.method + p.url = self.url + p.headers = self.headers.copy() if self.headers is not None else None + p._cookies = _copy_cookie_jar(self._cookies) + p.body = self.body + p.hooks = self.hooks + p._body_position = self._body_position + return p + + def prepare_method(self, method): + """Prepares the given HTTP method.""" + self.method = method + if self.method is not None: + self.method = to_native_string(self.method.upper()) + + @staticmethod + def _get_idna_encoded_host(host): + from pip._vendor import idna + + try: + host = idna.encode(host, uts46=True).decode('utf-8') + except idna.IDNAError: + raise UnicodeError + return host + + def prepare_url(self, url, params): + """Prepares the given HTTP URL.""" + #: Accept objects that have string representations. + #: We're unable to blindly call unicode/str functions + #: as this will include the bytestring indicator (b'') + #: on python 3.x. + #: https://github.com/requests/requests/pull/2238 + if isinstance(url, bytes): + url = url.decode('utf8') + else: + url = unicode(url) if is_py2 else str(url) + + # Remove leading whitespaces from url + url = url.lstrip() + + # Don't do any URL preparation for non-HTTP schemes like `mailto`, + # `data` etc to work around exceptions from `url_parse`, which + # handles RFC 3986 only. + if ':' in url and not url.lower().startswith('http'): + self.url = url + return + + # Support for unicode domain names and paths. + try: + scheme, auth, host, port, path, query, fragment = parse_url(url) + except LocationParseError as e: + raise InvalidURL(*e.args) + + if not scheme: + error = ("Invalid URL {0!r}: No schema supplied. Perhaps you meant http://{0}?") + error = error.format(to_native_string(url, 'utf8')) + + raise MissingSchema(error) + + if not host: + raise InvalidURL("Invalid URL %r: No host supplied" % url) + + # In general, we want to try IDNA encoding the hostname if the string contains + # non-ASCII characters. This allows users to automatically get the correct IDNA + # behaviour. For strings containing only ASCII characters, we need to also verify + # it doesn't start with a wildcard (*), before allowing the unencoded hostname. + if not unicode_is_ascii(host): + try: + host = self._get_idna_encoded_host(host) + except UnicodeError: + raise InvalidURL('URL has an invalid label.') + elif host.startswith(u'*'): + raise InvalidURL('URL has an invalid label.') + + # Carefully reconstruct the network location + netloc = auth or '' + if netloc: + netloc += '@' + netloc += host + if port: + netloc += ':' + str(port) + + # Bare domains aren't valid URLs. + if not path: + path = '/' + + if is_py2: + if isinstance(scheme, str): + scheme = scheme.encode('utf-8') + if isinstance(netloc, str): + netloc = netloc.encode('utf-8') + if isinstance(path, str): + path = path.encode('utf-8') + if isinstance(query, str): + query = query.encode('utf-8') + if isinstance(fragment, str): + fragment = fragment.encode('utf-8') + + if isinstance(params, (str, bytes)): + params = to_native_string(params) + + enc_params = self._encode_params(params) + if enc_params: + if query: + query = '%s&%s' % (query, enc_params) + else: + query = enc_params + + url = requote_uri(urlunparse([scheme, netloc, path, None, query, fragment])) + self.url = url + + def prepare_headers(self, headers): + """Prepares the given HTTP headers.""" + + self.headers = CaseInsensitiveDict() + if headers: + for header in headers.items(): + # Raise exception on invalid header value. + check_header_validity(header) + name, value = header + self.headers[to_native_string(name)] = value + + def prepare_body(self, data, files, json=None): + """Prepares the given HTTP body data.""" + + # Check if file, fo, generator, iterator. + # If not, run through normal process. + + # Nottin' on you. + body = None + content_type = None + + if not data and json is not None: + # urllib3 requires a bytes-like body. Python 2's json.dumps + # provides this natively, but Python 3 gives a Unicode string. + content_type = 'application/json' + body = complexjson.dumps(json) + if not isinstance(body, bytes): + body = body.encode('utf-8') + + is_stream = all([ + hasattr(data, '__iter__'), + not isinstance(data, (basestring, list, tuple, Mapping)) + ]) + + try: + length = super_len(data) + except (TypeError, AttributeError, UnsupportedOperation): + length = None + + if is_stream: + body = data + + if getattr(body, 'tell', None) is not None: + # Record the current file position before reading. + # This will allow us to rewind a file in the event + # of a redirect. + try: + self._body_position = body.tell() + except (IOError, OSError): + # This differentiates from None, allowing us to catch + # a failed `tell()` later when trying to rewind the body + self._body_position = object() + + if files: + raise NotImplementedError('Streamed bodies and files are mutually exclusive.') + + if length: + self.headers['Content-Length'] = builtin_str(length) + else: + self.headers['Transfer-Encoding'] = 'chunked' + else: + # Multi-part file uploads. + if files: + (body, content_type) = self._encode_files(files, data) + else: + if data: + body = self._encode_params(data) + if isinstance(data, basestring) or hasattr(data, 'read'): + content_type = None + else: + content_type = 'application/x-www-form-urlencoded' + + self.prepare_content_length(body) + + # Add content-type if it wasn't explicitly provided. + if content_type and ('content-type' not in self.headers): + self.headers['Content-Type'] = content_type + + self.body = body + + def prepare_content_length(self, body): + """Prepare Content-Length header based on request method and body""" + if body is not None: + length = super_len(body) + if length: + # If length exists, set it. Otherwise, we fallback + # to Transfer-Encoding: chunked. + self.headers['Content-Length'] = builtin_str(length) + elif self.method not in ('GET', 'HEAD') and self.headers.get('Content-Length') is None: + # Set Content-Length to 0 for methods that can have a body + # but don't provide one. (i.e. not GET or HEAD) + self.headers['Content-Length'] = '0' + + def prepare_auth(self, auth, url=''): + """Prepares the given HTTP auth data.""" + + # If no Auth is explicitly provided, extract it from the URL first. + if auth is None: + url_auth = get_auth_from_url(self.url) + auth = url_auth if any(url_auth) else None + + if auth: + if isinstance(auth, tuple) and len(auth) == 2: + # special-case basic HTTP auth + auth = HTTPBasicAuth(*auth) + + # Allow auth to make its changes. + r = auth(self) + + # Update self to reflect the auth changes. + self.__dict__.update(r.__dict__) + + # Recompute Content-Length + self.prepare_content_length(self.body) + + def prepare_cookies(self, cookies): + """Prepares the given HTTP cookie data. + + This function eventually generates a ``Cookie`` header from the + given cookies using cookielib. Due to cookielib's design, the header + will not be regenerated if it already exists, meaning this function + can only be called once for the life of the + :class:`PreparedRequest <PreparedRequest>` object. Any subsequent calls + to ``prepare_cookies`` will have no actual effect, unless the "Cookie" + header is removed beforehand. + """ + if isinstance(cookies, cookielib.CookieJar): + self._cookies = cookies + else: + self._cookies = cookiejar_from_dict(cookies) + + cookie_header = get_cookie_header(self._cookies, self) + if cookie_header is not None: + self.headers['Cookie'] = cookie_header + + def prepare_hooks(self, hooks): + """Prepares the given hooks.""" + # hooks can be passed as None to the prepare method and to this + # method. To prevent iterating over None, simply use an empty list + # if hooks is False-y + hooks = hooks or [] + for event in hooks: + self.register_hook(event, hooks[event]) + + +class Response(object): + """The :class:`Response <Response>` object, which contains a + server's response to an HTTP request. + """ + + __attrs__ = [ + '_content', 'status_code', 'headers', 'url', 'history', + 'encoding', 'reason', 'cookies', 'elapsed', 'request' + ] + + def __init__(self): + self._content = False + self._content_consumed = False + self._next = None + + #: Integer Code of responded HTTP Status, e.g. 404 or 200. + self.status_code = None + + #: Case-insensitive Dictionary of Response Headers. + #: For example, ``headers['content-encoding']`` will return the + #: value of a ``'Content-Encoding'`` response header. + self.headers = CaseInsensitiveDict() + + #: File-like object representation of response (for advanced usage). + #: Use of ``raw`` requires that ``stream=True`` be set on the request. + # This requirement does not apply for use internally to Requests. + self.raw = None + + #: Final URL location of Response. + self.url = None + + #: Encoding to decode with when accessing r.text. + self.encoding = None + + #: A list of :class:`Response <Response>` objects from + #: the history of the Request. Any redirect responses will end + #: up here. The list is sorted from the oldest to the most recent request. + self.history = [] + + #: Textual reason of responded HTTP Status, e.g. "Not Found" or "OK". + self.reason = None + + #: A CookieJar of Cookies the server sent back. + self.cookies = cookiejar_from_dict({}) + + #: The amount of time elapsed between sending the request + #: and the arrival of the response (as a timedelta). + #: This property specifically measures the time taken between sending + #: the first byte of the request and finishing parsing the headers. It + #: is therefore unaffected by consuming the response content or the + #: value of the ``stream`` keyword argument. + self.elapsed = datetime.timedelta(0) + + #: The :class:`PreparedRequest <PreparedRequest>` object to which this + #: is a response. + self.request = None + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def __getstate__(self): + # Consume everything; accessing the content attribute makes + # sure the content has been fully read. + if not self._content_consumed: + self.content + + return dict( + (attr, getattr(self, attr, None)) + for attr in self.__attrs__ + ) + + def __setstate__(self, state): + for name, value in state.items(): + setattr(self, name, value) + + # pickled objects do not have .raw + setattr(self, '_content_consumed', True) + setattr(self, 'raw', None) + + def __repr__(self): + return '<Response [%s]>' % (self.status_code) + + def __bool__(self): + """Returns True if :attr:`status_code` is less than 400. + + This attribute checks if the status code of the response is between + 400 and 600 to see if there was a client error or a server error. If + the status code, is between 200 and 400, this will return True. This + is **not** a check to see if the response code is ``200 OK``. + """ + return self.ok + + def __nonzero__(self): + """Returns True if :attr:`status_code` is less than 400. + + This attribute checks if the status code of the response is between + 400 and 600 to see if there was a client error or a server error. If + the status code, is between 200 and 400, this will return True. This + is **not** a check to see if the response code is ``200 OK``. + """ + return self.ok + + def __iter__(self): + """Allows you to use a response as an iterator.""" + return self.iter_content(128) + + @property + def ok(self): + """Returns True if :attr:`status_code` is less than 400, False if not. + + This attribute checks if the status code of the response is between + 400 and 600 to see if there was a client error or a server error. If + the status code is between 200 and 400, this will return True. This + is **not** a check to see if the response code is ``200 OK``. + """ + try: + self.raise_for_status() + except HTTPError: + return False + return True + + @property + def is_redirect(self): + """True if this Response is a well-formed HTTP redirect that could have + been processed automatically (by :meth:`Session.resolve_redirects`). + """ + return ('location' in self.headers and self.status_code in REDIRECT_STATI) + + @property + def is_permanent_redirect(self): + """True if this Response one of the permanent versions of redirect.""" + return ('location' in self.headers and self.status_code in (codes.moved_permanently, codes.permanent_redirect)) + + @property + def next(self): + """Returns a PreparedRequest for the next request in a redirect chain, if there is one.""" + return self._next + + @property + def apparent_encoding(self): + """The apparent encoding, provided by the chardet library.""" + return chardet.detect(self.content)['encoding'] + + def iter_content(self, chunk_size=1, decode_unicode=False): + """Iterates over the response data. When stream=True is set on the + request, this avoids reading the content at once into memory for + large responses. The chunk size is the number of bytes it should + read into memory. This is not necessarily the length of each item + returned as decoding can take place. + + chunk_size must be of type int or None. A value of None will + function differently depending on the value of `stream`. + stream=True will read data as it arrives in whatever size the + chunks are received. If stream=False, data is returned as + a single chunk. + + If decode_unicode is True, content will be decoded using the best + available encoding based on the response. + """ + + def generate(): + # Special case for urllib3. + if hasattr(self.raw, 'stream'): + try: + for chunk in self.raw.stream(chunk_size, decode_content=True): + yield chunk + except ProtocolError as e: + raise ChunkedEncodingError(e) + except DecodeError as e: + raise ContentDecodingError(e) + except ReadTimeoutError as e: + raise ConnectionError(e) + else: + # Standard file-like object. + while True: + chunk = self.raw.read(chunk_size) + if not chunk: + break + yield chunk + + self._content_consumed = True + + if self._content_consumed and isinstance(self._content, bool): + raise StreamConsumedError() + elif chunk_size is not None and not isinstance(chunk_size, int): + raise TypeError("chunk_size must be an int, it is instead a %s." % type(chunk_size)) + # simulate reading small chunks of the content + reused_chunks = iter_slices(self._content, chunk_size) + + stream_chunks = generate() + + chunks = reused_chunks if self._content_consumed else stream_chunks + + if decode_unicode: + chunks = stream_decode_response_unicode(chunks, self) + + return chunks + + def iter_lines(self, chunk_size=ITER_CHUNK_SIZE, decode_unicode=None, delimiter=None): + """Iterates over the response data, one line at a time. When + stream=True is set on the request, this avoids reading the + content at once into memory for large responses. + + .. note:: This method is not reentrant safe. + """ + + pending = None + + for chunk in self.iter_content(chunk_size=chunk_size, decode_unicode=decode_unicode): + + if pending is not None: + chunk = pending + chunk + + if delimiter: + lines = chunk.split(delimiter) + else: + lines = chunk.splitlines() + + if lines and lines[-1] and chunk and lines[-1][-1] == chunk[-1]: + pending = lines.pop() + else: + pending = None + + for line in lines: + yield line + + if pending is not None: + yield pending + + @property + def content(self): + """Content of the response, in bytes.""" + + if self._content is False: + # Read the contents. + if self._content_consumed: + raise RuntimeError( + 'The content for this response was already consumed') + + if self.status_code == 0 or self.raw is None: + self._content = None + else: + self._content = b''.join(self.iter_content(CONTENT_CHUNK_SIZE)) or b'' + + self._content_consumed = True + # don't need to release the connection; that's been handled by urllib3 + # since we exhausted the data. + return self._content + + @property + def text(self): + """Content of the response, in unicode. + + If Response.encoding is None, encoding will be guessed using + ``chardet``. + + The encoding of the response content is determined based solely on HTTP + headers, following RFC 2616 to the letter. If you can take advantage of + non-HTTP knowledge to make a better guess at the encoding, you should + set ``r.encoding`` appropriately before accessing this property. + """ + + # Try charset from content-type + content = None + encoding = self.encoding + + if not self.content: + return str('') + + # Fallback to auto-detected encoding. + if self.encoding is None: + encoding = self.apparent_encoding + + # Decode unicode from given encoding. + try: + content = str(self.content, encoding, errors='replace') + except (LookupError, TypeError): + # A LookupError is raised if the encoding was not found which could + # indicate a misspelling or similar mistake. + # + # A TypeError can be raised if encoding is None + # + # So we try blindly encoding. + content = str(self.content, errors='replace') + + return content + + def json(self, **kwargs): + r"""Returns the json-encoded content of a response, if any. + + :param \*\*kwargs: Optional arguments that ``json.loads`` takes. + :raises ValueError: If the response body does not contain valid json. + """ + + if not self.encoding and self.content and len(self.content) > 3: + # No encoding set. JSON RFC 4627 section 3 states we should expect + # UTF-8, -16 or -32. Detect which one to use; If the detection or + # decoding fails, fall back to `self.text` (using chardet to make + # a best guess). + encoding = guess_json_utf(self.content) + if encoding is not None: + try: + return complexjson.loads( + self.content.decode(encoding), **kwargs + ) + except UnicodeDecodeError: + # Wrong UTF codec detected; usually because it's not UTF-8 + # but some other 8-bit codec. This is an RFC violation, + # and the server didn't bother to tell us what codec *was* + # used. + pass + return complexjson.loads(self.text, **kwargs) + + @property + def links(self): + """Returns the parsed header links of the response, if any.""" + + header = self.headers.get('link') + + # l = MultiDict() + l = {} + + if header: + links = parse_header_links(header) + + for link in links: + key = link.get('rel') or link.get('url') + l[key] = link + + return l + + def raise_for_status(self): + """Raises stored :class:`HTTPError`, if one occurred.""" + + http_error_msg = '' + if isinstance(self.reason, bytes): + # We attempt to decode utf-8 first because some servers + # choose to localize their reason strings. If the string + # isn't utf-8, we fall back to iso-8859-1 for all other + # encodings. (See PR #3538) + try: + reason = self.reason.decode('utf-8') + except UnicodeDecodeError: + reason = self.reason.decode('iso-8859-1') + else: + reason = self.reason + + if 400 <= self.status_code < 500: + http_error_msg = u'%s Client Error: %s for url: %s' % (self.status_code, reason, self.url) + + elif 500 <= self.status_code < 600: + http_error_msg = u'%s Server Error: %s for url: %s' % (self.status_code, reason, self.url) + + if http_error_msg: + raise HTTPError(http_error_msg, response=self) + + def close(self): + """Releases the connection back to the pool. Once this method has been + called the underlying ``raw`` object must not be accessed again. + + *Note: Should not normally need to be called explicitly.* + """ + if not self._content_consumed: + self.raw.close() + + release_conn = getattr(self.raw, 'release_conn', None) + if release_conn is not None: + release_conn() diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/packages.py b/winvenv/Lib/site-packages/pip/_vendor/requests/packages.py new file mode 100644 index 0000000..9582fa7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/packages.py @@ -0,0 +1,16 @@ +import sys + +# This code exists for backwards compatibility reasons. +# I don't like it either. Just look the other way. :) + +for package in ('urllib3', 'idna', 'chardet'): + vendored_package = "pip._vendor." + package + locals()[package] = __import__(vendored_package) + # This traversal is apparently necessary such that the identities are + # preserved (requests.packages.urllib3.* is urllib3.*) + for mod in list(sys.modules): + if mod == vendored_package or mod.startswith(vendored_package + '.'): + unprefixed_mod = mod[len("pip._vendor."):] + sys.modules['pip._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] + +# Kinda cool, though, right? diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/sessions.py b/winvenv/Lib/site-packages/pip/_vendor/requests/sessions.py new file mode 100644 index 0000000..ba13526 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/sessions.py @@ -0,0 +1,741 @@ +# -*- coding: utf-8 -*- + +""" +requests.session +~~~~~~~~~~~~~~~~ + +This module provides a Session object to manage and persist settings across +requests (cookies, auth, proxies). +""" +import os +import sys +import time +from datetime import timedelta + +from .auth import _basic_auth_str +from .compat import cookielib, is_py3, OrderedDict, urljoin, urlparse, Mapping +from .cookies import ( + cookiejar_from_dict, extract_cookies_to_jar, RequestsCookieJar, merge_cookies) +from .models import Request, PreparedRequest, DEFAULT_REDIRECT_LIMIT +from .hooks import default_hooks, dispatch_hook +from ._internal_utils import to_native_string +from .utils import to_key_val_list, default_headers +from .exceptions import ( + TooManyRedirects, InvalidSchema, ChunkedEncodingError, ContentDecodingError) + +from .structures import CaseInsensitiveDict +from .adapters import HTTPAdapter + +from .utils import ( + requote_uri, get_environ_proxies, get_netrc_auth, should_bypass_proxies, + get_auth_from_url, rewind_body +) + +from .status_codes import codes + +# formerly defined here, reexposed here for backward compatibility +from .models import REDIRECT_STATI + +# Preferred clock, based on which one is more accurate on a given system. +if sys.platform == 'win32': + try: # Python 3.4+ + preferred_clock = time.perf_counter + except AttributeError: # Earlier than Python 3. + preferred_clock = time.clock +else: + preferred_clock = time.time + + +def merge_setting(request_setting, session_setting, dict_class=OrderedDict): + """Determines appropriate setting for a given request, taking into account + the explicit setting on that request, and the setting in the session. If a + setting is a dictionary, they will be merged together using `dict_class` + """ + + if session_setting is None: + return request_setting + + if request_setting is None: + return session_setting + + # Bypass if not a dictionary (e.g. verify) + if not ( + isinstance(session_setting, Mapping) and + isinstance(request_setting, Mapping) + ): + return request_setting + + merged_setting = dict_class(to_key_val_list(session_setting)) + merged_setting.update(to_key_val_list(request_setting)) + + # Remove keys that are set to None. Extract keys first to avoid altering + # the dictionary during iteration. + none_keys = [k for (k, v) in merged_setting.items() if v is None] + for key in none_keys: + del merged_setting[key] + + return merged_setting + + +def merge_hooks(request_hooks, session_hooks, dict_class=OrderedDict): + """Properly merges both requests and session hooks. + + This is necessary because when request_hooks == {'response': []}, the + merge breaks Session hooks entirely. + """ + if session_hooks is None or session_hooks.get('response') == []: + return request_hooks + + if request_hooks is None or request_hooks.get('response') == []: + return session_hooks + + return merge_setting(request_hooks, session_hooks, dict_class) + + +class SessionRedirectMixin(object): + + def get_redirect_target(self, resp): + """Receives a Response. Returns a redirect URI or ``None``""" + # Due to the nature of how requests processes redirects this method will + # be called at least once upon the original response and at least twice + # on each subsequent redirect response (if any). + # If a custom mixin is used to handle this logic, it may be advantageous + # to cache the redirect location onto the response object as a private + # attribute. + if resp.is_redirect: + location = resp.headers['location'] + # Currently the underlying http module on py3 decode headers + # in latin1, but empirical evidence suggests that latin1 is very + # rarely used with non-ASCII characters in HTTP headers. + # It is more likely to get UTF8 header rather than latin1. + # This causes incorrect handling of UTF8 encoded location headers. + # To solve this, we re-encode the location in latin1. + if is_py3: + location = location.encode('latin1') + return to_native_string(location, 'utf8') + return None + + def resolve_redirects(self, resp, req, stream=False, timeout=None, + verify=True, cert=None, proxies=None, yield_requests=False, **adapter_kwargs): + """Receives a Response. Returns a generator of Responses or Requests.""" + + hist = [] # keep track of history + + url = self.get_redirect_target(resp) + previous_fragment = urlparse(req.url).fragment + while url: + prepared_request = req.copy() + + # Update history and keep track of redirects. + # resp.history must ignore the original request in this loop + hist.append(resp) + resp.history = hist[1:] + + try: + resp.content # Consume socket so it can be released + except (ChunkedEncodingError, ContentDecodingError, RuntimeError): + resp.raw.read(decode_content=False) + + if len(resp.history) >= self.max_redirects: + raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp) + + # Release the connection back into the pool. + resp.close() + + # Handle redirection without scheme (see: RFC 1808 Section 4) + if url.startswith('//'): + parsed_rurl = urlparse(resp.url) + url = '%s:%s' % (to_native_string(parsed_rurl.scheme), url) + + # Normalize url case and attach previous fragment if needed (RFC 7231 7.1.2) + parsed = urlparse(url) + if parsed.fragment == '' and previous_fragment: + parsed = parsed._replace(fragment=previous_fragment) + elif parsed.fragment: + previous_fragment = parsed.fragment + url = parsed.geturl() + + # Facilitate relative 'location' headers, as allowed by RFC 7231. + # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource') + # Compliant with RFC3986, we percent encode the url. + if not parsed.netloc: + url = urljoin(resp.url, requote_uri(url)) + else: + url = requote_uri(url) + + prepared_request.url = to_native_string(url) + + self.rebuild_method(prepared_request, resp) + + # https://github.com/requests/requests/issues/1084 + if resp.status_code not in (codes.temporary_redirect, codes.permanent_redirect): + # https://github.com/requests/requests/issues/3490 + purged_headers = ('Content-Length', 'Content-Type', 'Transfer-Encoding') + for header in purged_headers: + prepared_request.headers.pop(header, None) + prepared_request.body = None + + headers = prepared_request.headers + try: + del headers['Cookie'] + except KeyError: + pass + + # Extract any cookies sent on the response to the cookiejar + # in the new request. Because we've mutated our copied prepared + # request, use the old one that we haven't yet touched. + extract_cookies_to_jar(prepared_request._cookies, req, resp.raw) + merge_cookies(prepared_request._cookies, self.cookies) + prepared_request.prepare_cookies(prepared_request._cookies) + + # Rebuild auth and proxy information. + proxies = self.rebuild_proxies(prepared_request, proxies) + self.rebuild_auth(prepared_request, resp) + + # A failed tell() sets `_body_position` to `object()`. This non-None + # value ensures `rewindable` will be True, allowing us to raise an + # UnrewindableBodyError, instead of hanging the connection. + rewindable = ( + prepared_request._body_position is not None and + ('Content-Length' in headers or 'Transfer-Encoding' in headers) + ) + + # Attempt to rewind consumed file-like object. + if rewindable: + rewind_body(prepared_request) + + # Override the original request. + req = prepared_request + + if yield_requests: + yield req + else: + + resp = self.send( + req, + stream=stream, + timeout=timeout, + verify=verify, + cert=cert, + proxies=proxies, + allow_redirects=False, + **adapter_kwargs + ) + + extract_cookies_to_jar(self.cookies, prepared_request, resp.raw) + + # extract redirect url, if any, for the next loop + url = self.get_redirect_target(resp) + yield resp + + def rebuild_auth(self, prepared_request, response): + """When being redirected we may want to strip authentication from the + request to avoid leaking credentials. This method intelligently removes + and reapplies authentication where possible to avoid credential loss. + """ + headers = prepared_request.headers + url = prepared_request.url + + if 'Authorization' in headers: + # If we get redirected to a new host, we should strip out any + # authentication headers. + original_parsed = urlparse(response.request.url) + redirect_parsed = urlparse(url) + + if (original_parsed.hostname != redirect_parsed.hostname): + del headers['Authorization'] + + # .netrc might have more auth for us on our new host. + new_auth = get_netrc_auth(url) if self.trust_env else None + if new_auth is not None: + prepared_request.prepare_auth(new_auth) + + return + + def rebuild_proxies(self, prepared_request, proxies): + """This method re-evaluates the proxy configuration by considering the + environment variables. If we are redirected to a URL covered by + NO_PROXY, we strip the proxy configuration. Otherwise, we set missing + proxy keys for this URL (in case they were stripped by a previous + redirect). + + This method also replaces the Proxy-Authorization header where + necessary. + + :rtype: dict + """ + proxies = proxies if proxies is not None else {} + headers = prepared_request.headers + url = prepared_request.url + scheme = urlparse(url).scheme + new_proxies = proxies.copy() + no_proxy = proxies.get('no_proxy') + + bypass_proxy = should_bypass_proxies(url, no_proxy=no_proxy) + if self.trust_env and not bypass_proxy: + environ_proxies = get_environ_proxies(url, no_proxy=no_proxy) + + proxy = environ_proxies.get(scheme, environ_proxies.get('all')) + + if proxy: + new_proxies.setdefault(scheme, proxy) + + if 'Proxy-Authorization' in headers: + del headers['Proxy-Authorization'] + + try: + username, password = get_auth_from_url(new_proxies[scheme]) + except KeyError: + username, password = None, None + + if username and password: + headers['Proxy-Authorization'] = _basic_auth_str(username, password) + + return new_proxies + + def rebuild_method(self, prepared_request, response): + """When being redirected we may want to change the method of the request + based on certain specs or browser behavior. + """ + method = prepared_request.method + + # http://tools.ietf.org/html/rfc7231#section-6.4.4 + if response.status_code == codes.see_other and method != 'HEAD': + method = 'GET' + + # Do what the browsers do, despite standards... + # First, turn 302s into GETs. + if response.status_code == codes.found and method != 'HEAD': + method = 'GET' + + # Second, if a POST is responded to with a 301, turn it into a GET. + # This bizarre behaviour is explained in Issue 1704. + if response.status_code == codes.moved and method == 'POST': + method = 'GET' + + prepared_request.method = method + + +class Session(SessionRedirectMixin): + """A Requests session. + + Provides cookie persistence, connection-pooling, and configuration. + + Basic Usage:: + + >>> import requests + >>> s = requests.Session() + >>> s.get('http://httpbin.org/get') + <Response [200]> + + Or as a context manager:: + + >>> with requests.Session() as s: + >>> s.get('http://httpbin.org/get') + <Response [200]> + """ + + __attrs__ = [ + 'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify', + 'cert', 'prefetch', 'adapters', 'stream', 'trust_env', + 'max_redirects', + ] + + def __init__(self): + + #: A case-insensitive dictionary of headers to be sent on each + #: :class:`Request <Request>` sent from this + #: :class:`Session <Session>`. + self.headers = default_headers() + + #: Default Authentication tuple or object to attach to + #: :class:`Request <Request>`. + self.auth = None + + #: Dictionary mapping protocol or protocol and host to the URL of the proxy + #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to + #: be used on each :class:`Request <Request>`. + self.proxies = {} + + #: Event-handling hooks. + self.hooks = default_hooks() + + #: Dictionary of querystring data to attach to each + #: :class:`Request <Request>`. The dictionary values may be lists for + #: representing multivalued query parameters. + self.params = {} + + #: Stream response content default. + self.stream = False + + #: SSL Verification default. + self.verify = True + + #: SSL client certificate default, if String, path to ssl client + #: cert file (.pem). If Tuple, ('cert', 'key') pair. + self.cert = None + + #: Maximum number of redirects allowed. If the request exceeds this + #: limit, a :class:`TooManyRedirects` exception is raised. + #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is + #: 30. + self.max_redirects = DEFAULT_REDIRECT_LIMIT + + #: Trust environment settings for proxy configuration, default + #: authentication and similar. + self.trust_env = True + + #: A CookieJar containing all currently outstanding cookies set on this + #: session. By default it is a + #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but + #: may be any other ``cookielib.CookieJar`` compatible object. + self.cookies = cookiejar_from_dict({}) + + # Default connection adapters. + self.adapters = OrderedDict() + self.mount('https://', HTTPAdapter()) + self.mount('http://', HTTPAdapter()) + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def prepare_request(self, request): + """Constructs a :class:`PreparedRequest <PreparedRequest>` for + transmission and returns it. The :class:`PreparedRequest` has settings + merged from the :class:`Request <Request>` instance and those of the + :class:`Session`. + + :param request: :class:`Request` instance to prepare with this + session's settings. + :rtype: requests.PreparedRequest + """ + cookies = request.cookies or {} + + # Bootstrap CookieJar. + if not isinstance(cookies, cookielib.CookieJar): + cookies = cookiejar_from_dict(cookies) + + # Merge with session cookies + merged_cookies = merge_cookies( + merge_cookies(RequestsCookieJar(), self.cookies), cookies) + + # Set environment's basic authentication if not explicitly set. + auth = request.auth + if self.trust_env and not auth and not self.auth: + auth = get_netrc_auth(request.url) + + p = PreparedRequest() + p.prepare( + method=request.method.upper(), + url=request.url, + files=request.files, + data=request.data, + json=request.json, + headers=merge_setting(request.headers, self.headers, dict_class=CaseInsensitiveDict), + params=merge_setting(request.params, self.params), + auth=merge_setting(auth, self.auth), + cookies=merged_cookies, + hooks=merge_hooks(request.hooks, self.hooks), + ) + return p + + def request(self, method, url, + params=None, data=None, headers=None, cookies=None, files=None, + auth=None, timeout=None, allow_redirects=True, proxies=None, + hooks=None, stream=None, verify=None, cert=None, json=None): + """Constructs a :class:`Request <Request>`, prepares it and sends it. + Returns :class:`Response <Response>` object. + + :param method: method for the new :class:`Request` object. + :param url: URL for the new :class:`Request` object. + :param params: (optional) Dictionary or bytes to be sent in the query + string for the :class:`Request`. + :param data: (optional) Dictionary, bytes, or file-like object to send + in the body of the :class:`Request`. + :param json: (optional) json to send in the body of the + :class:`Request`. + :param headers: (optional) Dictionary of HTTP Headers to send with the + :class:`Request`. + :param cookies: (optional) Dict or CookieJar object to send with the + :class:`Request`. + :param files: (optional) Dictionary of ``'filename': file-like-objects`` + for multipart encoding upload. + :param auth: (optional) Auth tuple or callable to enable + Basic/Digest/Custom HTTP Auth. + :param timeout: (optional) How long to wait for the server to send + data before giving up, as a float, or a :ref:`(connect timeout, + read timeout) <timeouts>` tuple. + :type timeout: float or tuple + :param allow_redirects: (optional) Set to True by default. + :type allow_redirects: bool + :param proxies: (optional) Dictionary mapping protocol or protocol and + hostname to the URL of the proxy. + :param stream: (optional) whether to immediately download the response + content. Defaults to ``False``. + :param verify: (optional) Either a boolean, in which case it controls whether we verify + the server's TLS certificate, or a string, in which case it must be a path + to a CA bundle to use. Defaults to ``True``. + :param cert: (optional) if String, path to ssl client cert file (.pem). + If Tuple, ('cert', 'key') pair. + :rtype: requests.Response + """ + # Create the Request. + req = Request( + method=method.upper(), + url=url, + headers=headers, + files=files, + data=data or {}, + json=json, + params=params or {}, + auth=auth, + cookies=cookies, + hooks=hooks, + ) + prep = self.prepare_request(req) + + proxies = proxies or {} + + settings = self.merge_environment_settings( + prep.url, proxies, stream, verify, cert + ) + + # Send the request. + send_kwargs = { + 'timeout': timeout, + 'allow_redirects': allow_redirects, + } + send_kwargs.update(settings) + resp = self.send(prep, **send_kwargs) + + return resp + + def get(self, url, **kwargs): + r"""Sends a GET request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return self.request('GET', url, **kwargs) + + def options(self, url, **kwargs): + r"""Sends a OPTIONS request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', True) + return self.request('OPTIONS', url, **kwargs) + + def head(self, url, **kwargs): + r"""Sends a HEAD request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + kwargs.setdefault('allow_redirects', False) + return self.request('HEAD', url, **kwargs) + + def post(self, url, data=None, json=None, **kwargs): + r"""Sends a POST request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param json: (optional) json to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('POST', url, data=data, json=json, **kwargs) + + def put(self, url, data=None, **kwargs): + r"""Sends a PUT request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('PUT', url, data=data, **kwargs) + + def patch(self, url, data=None, **kwargs): + r"""Sends a PATCH request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('PATCH', url, data=data, **kwargs) + + def delete(self, url, **kwargs): + r"""Sends a DELETE request. Returns :class:`Response` object. + + :param url: URL for the new :class:`Request` object. + :param \*\*kwargs: Optional arguments that ``request`` takes. + :rtype: requests.Response + """ + + return self.request('DELETE', url, **kwargs) + + def send(self, request, **kwargs): + """Send a given PreparedRequest. + + :rtype: requests.Response + """ + # Set defaults that the hooks can utilize to ensure they always have + # the correct parameters to reproduce the previous request. + kwargs.setdefault('stream', self.stream) + kwargs.setdefault('verify', self.verify) + kwargs.setdefault('cert', self.cert) + kwargs.setdefault('proxies', self.proxies) + + # It's possible that users might accidentally send a Request object. + # Guard against that specific failure case. + if isinstance(request, Request): + raise ValueError('You can only send PreparedRequests.') + + # Set up variables needed for resolve_redirects and dispatching of hooks + allow_redirects = kwargs.pop('allow_redirects', True) + stream = kwargs.get('stream') + hooks = request.hooks + + # Get the appropriate adapter to use + adapter = self.get_adapter(url=request.url) + + # Start time (approximately) of the request + start = preferred_clock() + + # Send the request + r = adapter.send(request, **kwargs) + + # Total elapsed time of the request (approximately) + elapsed = preferred_clock() - start + r.elapsed = timedelta(seconds=elapsed) + + # Response manipulation hooks + r = dispatch_hook('response', hooks, r, **kwargs) + + # Persist cookies + if r.history: + + # If the hooks create history then we want those cookies too + for resp in r.history: + extract_cookies_to_jar(self.cookies, resp.request, resp.raw) + + extract_cookies_to_jar(self.cookies, request, r.raw) + + # Redirect resolving generator. + gen = self.resolve_redirects(r, request, **kwargs) + + # Resolve redirects if allowed. + history = [resp for resp in gen] if allow_redirects else [] + + # Shuffle things around if there's history. + if history: + # Insert the first (original) request at the start + history.insert(0, r) + # Get the last request made + r = history.pop() + r.history = history + + # If redirects aren't being followed, store the response on the Request for Response.next(). + if not allow_redirects: + try: + r._next = next(self.resolve_redirects(r, request, yield_requests=True, **kwargs)) + except StopIteration: + pass + + if not stream: + r.content + + return r + + def merge_environment_settings(self, url, proxies, stream, verify, cert): + """ + Check the environment and merge it with some settings. + + :rtype: dict + """ + # Gather clues from the surrounding environment. + if self.trust_env: + # Set environment's proxies. + no_proxy = proxies.get('no_proxy') if proxies is not None else None + env_proxies = get_environ_proxies(url, no_proxy=no_proxy) + for (k, v) in env_proxies.items(): + proxies.setdefault(k, v) + + # Look for requests environment configuration and be compatible + # with cURL. + if verify is True or verify is None: + verify = (os.environ.get('REQUESTS_CA_BUNDLE') or + os.environ.get('CURL_CA_BUNDLE')) + + # Merge all the kwargs. + proxies = merge_setting(proxies, self.proxies) + stream = merge_setting(stream, self.stream) + verify = merge_setting(verify, self.verify) + cert = merge_setting(cert, self.cert) + + return {'verify': verify, 'proxies': proxies, 'stream': stream, + 'cert': cert} + + def get_adapter(self, url): + """ + Returns the appropriate connection adapter for the given URL. + + :rtype: requests.adapters.BaseAdapter + """ + for (prefix, adapter) in self.adapters.items(): + + if url.lower().startswith(prefix.lower()): + return adapter + + # Nothing matches :-/ + raise InvalidSchema("No connection adapters were found for '%s'" % url) + + def close(self): + """Closes all adapters and as such the session""" + for v in self.adapters.values(): + v.close() + + def mount(self, prefix, adapter): + """Registers a connection adapter to a prefix. + + Adapters are sorted in descending order by prefix length. + """ + self.adapters[prefix] = adapter + keys_to_move = [k for k in self.adapters if len(k) < len(prefix)] + + for key in keys_to_move: + self.adapters[key] = self.adapters.pop(key) + + def __getstate__(self): + state = dict((attr, getattr(self, attr, None)) for attr in self.__attrs__) + return state + + def __setstate__(self, state): + for attr, value in state.items(): + setattr(self, attr, value) + + +def session(): + """ + Returns a :class:`Session` for context-management. + + :rtype: Session + """ + + return Session() diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/status_codes.py b/winvenv/Lib/site-packages/pip/_vendor/requests/status_codes.py new file mode 100644 index 0000000..ff462c6 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/status_codes.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- + +""" +The ``codes`` object defines a mapping from common names for HTTP statuses +to their numerical codes, accessible either as attributes or as dictionary +items. + +>>> requests.codes['temporary_redirect'] +307 +>>> requests.codes.teapot +418 +>>> requests.codes['\o/'] +200 + +Some codes have multiple names, and both upper- and lower-case versions of +the names are allowed. For example, ``codes.ok``, ``codes.OK``, and +``codes.okay`` all correspond to the HTTP status code 200. +""" + +from .structures import LookupDict + +_codes = { + + # Informational. + 100: ('continue',), + 101: ('switching_protocols',), + 102: ('processing',), + 103: ('checkpoint',), + 122: ('uri_too_long', 'request_uri_too_long'), + 200: ('ok', 'okay', 'all_ok', 'all_okay', 'all_good', '\\o/', '✓'), + 201: ('created',), + 202: ('accepted',), + 203: ('non_authoritative_info', 'non_authoritative_information'), + 204: ('no_content',), + 205: ('reset_content', 'reset'), + 206: ('partial_content', 'partial'), + 207: ('multi_status', 'multiple_status', 'multi_stati', 'multiple_stati'), + 208: ('already_reported',), + 226: ('im_used',), + + # Redirection. + 300: ('multiple_choices',), + 301: ('moved_permanently', 'moved', '\\o-'), + 302: ('found',), + 303: ('see_other', 'other'), + 304: ('not_modified',), + 305: ('use_proxy',), + 306: ('switch_proxy',), + 307: ('temporary_redirect', 'temporary_moved', 'temporary'), + 308: ('permanent_redirect', + 'resume_incomplete', 'resume',), # These 2 to be removed in 3.0 + + # Client Error. + 400: ('bad_request', 'bad'), + 401: ('unauthorized',), + 402: ('payment_required', 'payment'), + 403: ('forbidden',), + 404: ('not_found', '-o-'), + 405: ('method_not_allowed', 'not_allowed'), + 406: ('not_acceptable',), + 407: ('proxy_authentication_required', 'proxy_auth', 'proxy_authentication'), + 408: ('request_timeout', 'timeout'), + 409: ('conflict',), + 410: ('gone',), + 411: ('length_required',), + 412: ('precondition_failed', 'precondition'), + 413: ('request_entity_too_large',), + 414: ('request_uri_too_large',), + 415: ('unsupported_media_type', 'unsupported_media', 'media_type'), + 416: ('requested_range_not_satisfiable', 'requested_range', 'range_not_satisfiable'), + 417: ('expectation_failed',), + 418: ('im_a_teapot', 'teapot', 'i_am_a_teapot'), + 421: ('misdirected_request',), + 422: ('unprocessable_entity', 'unprocessable'), + 423: ('locked',), + 424: ('failed_dependency', 'dependency'), + 425: ('unordered_collection', 'unordered'), + 426: ('upgrade_required', 'upgrade'), + 428: ('precondition_required', 'precondition'), + 429: ('too_many_requests', 'too_many'), + 431: ('header_fields_too_large', 'fields_too_large'), + 444: ('no_response', 'none'), + 449: ('retry_with', 'retry'), + 450: ('blocked_by_windows_parental_controls', 'parental_controls'), + 451: ('unavailable_for_legal_reasons', 'legal_reasons'), + 499: ('client_closed_request',), + + # Server Error. + 500: ('internal_server_error', 'server_error', '/o\\', '✗'), + 501: ('not_implemented',), + 502: ('bad_gateway',), + 503: ('service_unavailable', 'unavailable'), + 504: ('gateway_timeout',), + 505: ('http_version_not_supported', 'http_version'), + 506: ('variant_also_negotiates',), + 507: ('insufficient_storage',), + 509: ('bandwidth_limit_exceeded', 'bandwidth'), + 510: ('not_extended',), + 511: ('network_authentication_required', 'network_auth', 'network_authentication'), +} + +codes = LookupDict(name='status_codes') + +def _init(): + for code, titles in _codes.items(): + for title in titles: + setattr(codes, title, code) + if not title.startswith(('\\', '/')): + setattr(codes, title.upper(), code) + + def doc(code): + names = ', '.join('``%s``' % n for n in _codes[code]) + return '* %d: %s' % (code, names) + + global __doc__ + __doc__ = (__doc__ + '\n' + + '\n'.join(doc(code) for code in sorted(_codes)) + if __doc__ is not None else None) + +_init() diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/structures.py b/winvenv/Lib/site-packages/pip/_vendor/requests/structures.py new file mode 100644 index 0000000..da930e2 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/structures.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- + +""" +requests.structures +~~~~~~~~~~~~~~~~~~~ + +Data structures that power Requests. +""" + +from .compat import OrderedDict, Mapping, MutableMapping + + +class CaseInsensitiveDict(MutableMapping): + """A case-insensitive ``dict``-like object. + + Implements all methods and operations of + ``MutableMapping`` as well as dict's ``copy``. Also + provides ``lower_items``. + + All keys are expected to be strings. The structure remembers the + case of the last key to be set, and ``iter(instance)``, + ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` + will contain case-sensitive keys. However, querying and contains + testing is case insensitive:: + + cid = CaseInsensitiveDict() + cid['Accept'] = 'application/json' + cid['aCCEPT'] == 'application/json' # True + list(cid) == ['Accept'] # True + + For example, ``headers['content-encoding']`` will return the + value of a ``'Content-Encoding'`` response header, regardless + of how the header name was originally stored. + + If the constructor, ``.update``, or equality comparison + operations are given keys that have equal ``.lower()``s, the + behavior is undefined. + """ + + def __init__(self, data=None, **kwargs): + self._store = OrderedDict() + if data is None: + data = {} + self.update(data, **kwargs) + + def __setitem__(self, key, value): + # Use the lowercased key for lookups, but store the actual + # key alongside the value. + self._store[key.lower()] = (key, value) + + def __getitem__(self, key): + return self._store[key.lower()][1] + + def __delitem__(self, key): + del self._store[key.lower()] + + def __iter__(self): + return (casedkey for casedkey, mappedvalue in self._store.values()) + + def __len__(self): + return len(self._store) + + def lower_items(self): + """Like iteritems(), but with all lowercase keys.""" + return ( + (lowerkey, keyval[1]) + for (lowerkey, keyval) + in self._store.items() + ) + + def __eq__(self, other): + if isinstance(other, Mapping): + other = CaseInsensitiveDict(other) + else: + return NotImplemented + # Compare insensitively + return dict(self.lower_items()) == dict(other.lower_items()) + + # Copy is required + def copy(self): + return CaseInsensitiveDict(self._store.values()) + + def __repr__(self): + return str(dict(self.items())) + + +class LookupDict(dict): + """Dictionary lookup object.""" + + def __init__(self, name=None): + self.name = name + super(LookupDict, self).__init__() + + def __repr__(self): + return '<lookup \'%s\'>' % (self.name) + + def __getitem__(self, key): + # We allow fall-through here, so values default to None + + return self.__dict__.get(key, None) + + def get(self, key, default=None): + return self.__dict__.get(key, default) diff --git a/winvenv/Lib/site-packages/pip/_vendor/requests/utils.py b/winvenv/Lib/site-packages/pip/_vendor/requests/utils.py new file mode 100644 index 0000000..431f6be --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/requests/utils.py @@ -0,0 +1,976 @@ +# -*- coding: utf-8 -*- + +""" +requests.utils +~~~~~~~~~~~~~~ + +This module provides utility functions that are used within Requests +that are also useful for external consumption. +""" + +import codecs +import contextlib +import io +import os +import re +import socket +import struct +import sys +import tempfile +import warnings +import zipfile + +from .__version__ import __version__ +from . import certs +# to_native_string is unused here, but imported here for backwards compatibility +from ._internal_utils import to_native_string +from .compat import parse_http_list as _parse_list_header +from .compat import ( + quote, urlparse, bytes, str, OrderedDict, unquote, getproxies, + proxy_bypass, urlunparse, basestring, integer_types, is_py3, + proxy_bypass_environment, getproxies_environment, Mapping) +from .cookies import cookiejar_from_dict +from .structures import CaseInsensitiveDict +from .exceptions import ( + InvalidURL, InvalidHeader, FileModeWarning, UnrewindableBodyError) + +NETRC_FILES = ('.netrc', '_netrc') + +DEFAULT_CA_BUNDLE_PATH = certs.where() + + +if sys.platform == 'win32': + # provide a proxy_bypass version on Windows without DNS lookups + + def proxy_bypass_registry(host): + try: + if is_py3: + import winreg + else: + import _winreg as winreg + except ImportError: + return False + + try: + internetSettings = winreg.OpenKey(winreg.HKEY_CURRENT_USER, + r'Software\Microsoft\Windows\CurrentVersion\Internet Settings') + # ProxyEnable could be REG_SZ or REG_DWORD, normalizing it + proxyEnable = int(winreg.QueryValueEx(internetSettings, + 'ProxyEnable')[0]) + # ProxyOverride is almost always a string + proxyOverride = winreg.QueryValueEx(internetSettings, + 'ProxyOverride')[0] + except OSError: + return False + if not proxyEnable or not proxyOverride: + return False + + # make a check value list from the registry entry: replace the + # '<local>' string by the localhost entry and the corresponding + # canonical entry. + proxyOverride = proxyOverride.split(';') + # now check if we match one of the registry values. + for test in proxyOverride: + if test == '<local>': + if '.' not in host: + return True + test = test.replace(".", r"\.") # mask dots + test = test.replace("*", r".*") # change glob sequence + test = test.replace("?", r".") # change glob char + if re.match(test, host, re.I): + return True + return False + + def proxy_bypass(host): # noqa + """Return True, if the host should be bypassed. + + Checks proxy settings gathered from the environment, if specified, + or the registry. + """ + if getproxies_environment(): + return proxy_bypass_environment(host) + else: + return proxy_bypass_registry(host) + + +def dict_to_sequence(d): + """Returns an internal sequence dictionary update.""" + + if hasattr(d, 'items'): + d = d.items() + + return d + + +def super_len(o): + total_length = None + current_position = 0 + + if hasattr(o, '__len__'): + total_length = len(o) + + elif hasattr(o, 'len'): + total_length = o.len + + elif hasattr(o, 'fileno'): + try: + fileno = o.fileno() + except io.UnsupportedOperation: + pass + else: + total_length = os.fstat(fileno).st_size + + # Having used fstat to determine the file length, we need to + # confirm that this file was opened up in binary mode. + if 'b' not in o.mode: + warnings.warn(( + "Requests has determined the content-length for this " + "request using the binary size of the file: however, the " + "file has been opened in text mode (i.e. without the 'b' " + "flag in the mode). This may lead to an incorrect " + "content-length. In Requests 3.0, support will be removed " + "for files in text mode."), + FileModeWarning + ) + + if hasattr(o, 'tell'): + try: + current_position = o.tell() + except (OSError, IOError): + # This can happen in some weird situations, such as when the file + # is actually a special file descriptor like stdin. In this + # instance, we don't know what the length is, so set it to zero and + # let requests chunk it instead. + if total_length is not None: + current_position = total_length + else: + if hasattr(o, 'seek') and total_length is None: + # StringIO and BytesIO have seek but no useable fileno + try: + # seek to end of file + o.seek(0, 2) + total_length = o.tell() + + # seek back to current position to support + # partially read file-like objects + o.seek(current_position or 0) + except (OSError, IOError): + total_length = 0 + + if total_length is None: + total_length = 0 + + return max(0, total_length - current_position) + + +def get_netrc_auth(url, raise_errors=False): + """Returns the Requests tuple auth for a given url from netrc.""" + + try: + from netrc import netrc, NetrcParseError + + netrc_path = None + + for f in NETRC_FILES: + try: + loc = os.path.expanduser('~/{0}'.format(f)) + except KeyError: + # os.path.expanduser can fail when $HOME is undefined and + # getpwuid fails. See http://bugs.python.org/issue20164 & + # https://github.com/requests/requests/issues/1846 + return + + if os.path.exists(loc): + netrc_path = loc + break + + # Abort early if there isn't one. + if netrc_path is None: + return + + ri = urlparse(url) + + # Strip port numbers from netloc. This weird `if...encode`` dance is + # used for Python 3.2, which doesn't support unicode literals. + splitstr = b':' + if isinstance(url, str): + splitstr = splitstr.decode('ascii') + host = ri.netloc.split(splitstr)[0] + + try: + _netrc = netrc(netrc_path).authenticators(host) + if _netrc: + # Return with login / password + login_i = (0 if _netrc[0] else 1) + return (_netrc[login_i], _netrc[2]) + except (NetrcParseError, IOError): + # If there was a parsing error or a permissions issue reading the file, + # we'll just skip netrc auth unless explicitly asked to raise errors. + if raise_errors: + raise + + # AppEngine hackiness. + except (ImportError, AttributeError): + pass + + +def guess_filename(obj): + """Tries to guess the filename of the given object.""" + name = getattr(obj, 'name', None) + if (name and isinstance(name, basestring) and name[0] != '<' and + name[-1] != '>'): + return os.path.basename(name) + + +def extract_zipped_paths(path): + """Replace nonexistent paths that look like they refer to a member of a zip + archive with the location of an extracted copy of the target, or else + just return the provided path unchanged. + """ + if os.path.exists(path): + # this is already a valid path, no need to do anything further + return path + + # find the first valid part of the provided path and treat that as a zip archive + # assume the rest of the path is the name of a member in the archive + archive, member = os.path.split(path) + while archive and not os.path.exists(archive): + archive, prefix = os.path.split(archive) + member = '/'.join([prefix, member]) + + if not zipfile.is_zipfile(archive): + return path + + zip_file = zipfile.ZipFile(archive) + if member not in zip_file.namelist(): + return path + + # we have a valid zip archive and a valid member of that archive + tmp = tempfile.gettempdir() + extracted_path = os.path.join(tmp, *member.split('/')) + if not os.path.exists(extracted_path): + extracted_path = zip_file.extract(member, path=tmp) + + return extracted_path + + +def from_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. Unless it can not be represented as such, return an + OrderedDict, e.g., + + :: + + >>> from_key_val_list([('key', 'val')]) + OrderedDict([('key', 'val')]) + >>> from_key_val_list('string') + ValueError: need more than 1 value to unpack + >>> from_key_val_list({'key': 'val'}) + OrderedDict([('key', 'val')]) + + :rtype: OrderedDict + """ + if value is None: + return None + + if isinstance(value, (str, bytes, bool, int)): + raise ValueError('cannot encode objects that are not 2-tuples') + + return OrderedDict(value) + + +def to_key_val_list(value): + """Take an object and test to see if it can be represented as a + dictionary. If it can be, return a list of tuples, e.g., + + :: + + >>> to_key_val_list([('key', 'val')]) + [('key', 'val')] + >>> to_key_val_list({'key': 'val'}) + [('key', 'val')] + >>> to_key_val_list('string') + ValueError: cannot encode objects that are not 2-tuples. + + :rtype: list + """ + if value is None: + return None + + if isinstance(value, (str, bytes, bool, int)): + raise ValueError('cannot encode objects that are not 2-tuples') + + if isinstance(value, Mapping): + value = value.items() + + return list(value) + + +# From mitsuhiko/werkzeug (used with permission). +def parse_list_header(value): + """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` + :rtype: 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 + + +# From mitsuhiko/werkzeug (used with permission). +def parse_dict_header(value): + """Parse lists of key, value pairs as described by RFC 2068 Section 2 and + convert them into a python dict: + + >>> 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. + + :param value: a string with a dict header. + :return: :class:`dict` + :rtype: dict + """ + result = {} + 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 + + +# From mitsuhiko/werkzeug (used with permission). +def unquote_header_value(value, is_filename=False): + 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. + + :param value: the header value to unquote. + :rtype: str + """ + 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 dict_from_cookiejar(cj): + """Returns a key/value dictionary from a CookieJar. + + :param cj: CookieJar object to extract cookies from. + :rtype: dict + """ + + cookie_dict = {} + + for cookie in cj: + cookie_dict[cookie.name] = cookie.value + + return cookie_dict + + +def add_dict_to_cookiejar(cj, cookie_dict): + """Returns a CookieJar from a key/value dictionary. + + :param cj: CookieJar to insert cookies into. + :param cookie_dict: Dict of key/values to insert into CookieJar. + :rtype: CookieJar + """ + + return cookiejar_from_dict(cookie_dict, cj) + + +def get_encodings_from_content(content): + """Returns encodings from given content string. + + :param content: bytestring to extract encodings from. + """ + warnings.warn(( + 'In requests 3.0, get_encodings_from_content will be removed. For ' + 'more information, please see the discussion on issue #2266. (This' + ' warning should only appear once.)'), + DeprecationWarning) + + charset_re = re.compile(r'<meta.*?charset=["\']*(.+?)["\'>]', flags=re.I) + pragma_re = re.compile(r'<meta.*?content=["\']*;?charset=(.+?)["\'>]', flags=re.I) + xml_re = re.compile(r'^<\?xml.*?encoding=["\']*(.+?)["\'>]') + + return (charset_re.findall(content) + + pragma_re.findall(content) + + xml_re.findall(content)) + + +def _parse_content_type_header(header): + """Returns content type and parameters from given header + + :param header: string + :return: tuple containing content type and dictionary of + parameters + """ + + tokens = header.split(';') + content_type, params = tokens[0].strip(), tokens[1:] + params_dict = {} + items_to_strip = "\"' " + + for param in params: + param = param.strip() + if param: + key, value = param, True + index_of_equals = param.find("=") + if index_of_equals != -1: + key = param[:index_of_equals].strip(items_to_strip) + value = param[index_of_equals + 1:].strip(items_to_strip) + params_dict[key] = value + return content_type, params_dict + + +def get_encoding_from_headers(headers): + """Returns encodings from given HTTP Header Dict. + + :param headers: dictionary to extract encoding from. + :rtype: str + """ + + content_type = headers.get('content-type') + + if not content_type: + return None + + content_type, params = _parse_content_type_header(content_type) + + if 'charset' in params: + return params['charset'].strip("'\"") + + if 'text' in content_type: + return 'ISO-8859-1' + + +def stream_decode_response_unicode(iterator, r): + """Stream decodes a iterator.""" + + if r.encoding is None: + for item in iterator: + yield item + return + + decoder = codecs.getincrementaldecoder(r.encoding)(errors='replace') + for chunk in iterator: + rv = decoder.decode(chunk) + if rv: + yield rv + rv = decoder.decode(b'', final=True) + if rv: + yield rv + + +def iter_slices(string, slice_length): + """Iterate over slices of a string.""" + pos = 0 + if slice_length is None or slice_length <= 0: + slice_length = len(string) + while pos < len(string): + yield string[pos:pos + slice_length] + pos += slice_length + + +def get_unicode_from_response(r): + """Returns the requested content back in unicode. + + :param r: Response object to get unicode content from. + + Tried: + + 1. charset from content-type + 2. fall back and replace all unicode characters + + :rtype: str + """ + warnings.warn(( + 'In requests 3.0, get_unicode_from_response will be removed. For ' + 'more information, please see the discussion on issue #2266. (This' + ' warning should only appear once.)'), + DeprecationWarning) + + tried_encodings = [] + + # Try charset from content-type + encoding = get_encoding_from_headers(r.headers) + + if encoding: + try: + return str(r.content, encoding) + except UnicodeError: + tried_encodings.append(encoding) + + # Fall back: + try: + return str(r.content, encoding, errors='replace') + except TypeError: + return r.content + + +# The unreserved URI characters (RFC 3986) +UNRESERVED_SET = frozenset( + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789-._~") + + +def unquote_unreserved(uri): + """Un-escape any percent-escape sequences in a URI that are unreserved + characters. This leaves all reserved, illegal and non-ASCII bytes encoded. + + :rtype: str + """ + parts = uri.split('%') + for i in range(1, len(parts)): + h = parts[i][0:2] + if len(h) == 2 and h.isalnum(): + try: + c = chr(int(h, 16)) + except ValueError: + raise InvalidURL("Invalid percent-escape sequence: '%s'" % h) + + if c in UNRESERVED_SET: + parts[i] = c + parts[i][2:] + else: + parts[i] = '%' + parts[i] + else: + parts[i] = '%' + parts[i] + return ''.join(parts) + + +def requote_uri(uri): + """Re-quote the given URI. + + This function passes the given URI through an unquote/quote cycle to + ensure that it is fully and consistently quoted. + + :rtype: str + """ + safe_with_percent = "!#$%&'()*+,/:;=?@[]~" + safe_without_percent = "!#$&'()*+,/:;=?@[]~" + try: + # Unquote only the unreserved characters + # Then quote only illegal characters (do not quote reserved, + # unreserved, or '%') + return quote(unquote_unreserved(uri), safe=safe_with_percent) + except InvalidURL: + # We couldn't unquote the given URI, so let's try quoting it, but + # there may be unquoted '%'s in the URI. We need to make sure they're + # properly quoted so they do not cause issues elsewhere. + return quote(uri, safe=safe_without_percent) + + +def address_in_network(ip, net): + """This function allows you to check if an IP belongs to a network subnet + + Example: returns True if ip = 192.168.1.1 and net = 192.168.1.0/24 + returns False if ip = 192.168.1.1 and net = 192.168.100.0/24 + + :rtype: bool + """ + ipaddr = struct.unpack('=L', socket.inet_aton(ip))[0] + netaddr, bits = net.split('/') + netmask = struct.unpack('=L', socket.inet_aton(dotted_netmask(int(bits))))[0] + network = struct.unpack('=L', socket.inet_aton(netaddr))[0] & netmask + return (ipaddr & netmask) == (network & netmask) + + +def dotted_netmask(mask): + """Converts mask from /xx format to xxx.xxx.xxx.xxx + + Example: if mask is 24 function returns 255.255.255.0 + + :rtype: str + """ + bits = 0xffffffff ^ (1 << 32 - mask) - 1 + return socket.inet_ntoa(struct.pack('>I', bits)) + + +def is_ipv4_address(string_ip): + """ + :rtype: bool + """ + try: + socket.inet_aton(string_ip) + except socket.error: + return False + return True + + +def is_valid_cidr(string_network): + """ + Very simple check of the cidr format in no_proxy variable. + + :rtype: bool + """ + if string_network.count('/') == 1: + try: + mask = int(string_network.split('/')[1]) + except ValueError: + return False + + if mask < 1 or mask > 32: + return False + + try: + socket.inet_aton(string_network.split('/')[0]) + except socket.error: + return False + else: + return False + return True + + +@contextlib.contextmanager +def set_environ(env_name, value): + """Set the environment variable 'env_name' to 'value' + + Save previous value, yield, and then restore the previous value stored in + the environment variable 'env_name'. + + If 'value' is None, do nothing""" + value_changed = value is not None + if value_changed: + old_value = os.environ.get(env_name) + os.environ[env_name] = value + try: + yield + finally: + if value_changed: + if old_value is None: + del os.environ[env_name] + else: + os.environ[env_name] = old_value + + +def should_bypass_proxies(url, no_proxy): + """ + Returns whether we should bypass proxies or not. + + :rtype: bool + """ + # Prioritize lowercase environment variables over uppercase + # to keep a consistent behaviour with other http projects (curl, wget). + get_proxy = lambda k: os.environ.get(k) or os.environ.get(k.upper()) + + # First check whether no_proxy is defined. If it is, check that the URL + # we're getting isn't in the no_proxy list. + no_proxy_arg = no_proxy + if no_proxy is None: + no_proxy = get_proxy('no_proxy') + parsed = urlparse(url) + + if no_proxy: + # We need to check whether we match here. We need to see if we match + # the end of the hostname, both with and without the port. + no_proxy = ( + host for host in no_proxy.replace(' ', '').split(',') if host + ) + + if is_ipv4_address(parsed.hostname): + for proxy_ip in no_proxy: + if is_valid_cidr(proxy_ip): + if address_in_network(parsed.hostname, proxy_ip): + return True + elif parsed.hostname == proxy_ip: + # If no_proxy ip was defined in plain IP notation instead of cidr notation & + # matches the IP of the index + return True + else: + host_with_port = parsed.hostname + if parsed.port: + host_with_port += ':{0}'.format(parsed.port) + + for host in no_proxy: + if parsed.hostname.endswith(host) or host_with_port.endswith(host): + # The URL does match something in no_proxy, so we don't want + # to apply the proxies on this URL. + return True + + # If the system proxy settings indicate that this URL should be bypassed, + # don't proxy. + # The proxy_bypass function is incredibly buggy on OS X in early versions + # of Python 2.6, so allow this call to fail. Only catch the specific + # exceptions we've seen, though: this call failing in other ways can reveal + # legitimate problems. + with set_environ('no_proxy', no_proxy_arg): + try: + bypass = proxy_bypass(parsed.hostname) + except (TypeError, socket.gaierror): + bypass = False + + if bypass: + return True + + return False + + +def get_environ_proxies(url, no_proxy=None): + """ + Return a dict of environment proxies. + + :rtype: dict + """ + if should_bypass_proxies(url, no_proxy=no_proxy): + return {} + else: + return getproxies() + + +def select_proxy(url, proxies): + """Select a proxy for the url, if applicable. + + :param url: The url being for the request + :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs + """ + proxies = proxies or {} + urlparts = urlparse(url) + if urlparts.hostname is None: + return proxies.get(urlparts.scheme, proxies.get('all')) + + proxy_keys = [ + urlparts.scheme + '://' + urlparts.hostname, + urlparts.scheme, + 'all://' + urlparts.hostname, + 'all', + ] + proxy = None + for proxy_key in proxy_keys: + if proxy_key in proxies: + proxy = proxies[proxy_key] + break + + return proxy + + +def default_user_agent(name="python-requests"): + """ + Return a string representing the default user agent. + + :rtype: str + """ + return '%s/%s' % (name, __version__) + + +def default_headers(): + """ + :rtype: requests.structures.CaseInsensitiveDict + """ + return CaseInsensitiveDict({ + 'User-Agent': default_user_agent(), + 'Accept-Encoding': ', '.join(('gzip', 'deflate')), + 'Accept': '*/*', + 'Connection': 'keep-alive', + }) + + +def parse_header_links(value): + """Return a list of parsed link headers proxies. + + i.e. Link: <http:/.../front.jpeg>; rel=front; type="image/jpeg",<http://.../back.jpeg>; rel=back;type="image/jpeg" + + :rtype: list + """ + + links = [] + + replace_chars = ' \'"' + + value = value.strip(replace_chars) + if not value: + return links + + for val in re.split(', *<', value): + try: + url, params = val.split(';', 1) + except ValueError: + url, params = val, '' + + link = {'url': url.strip('<> \'"')} + + for param in params.split(';'): + try: + key, value = param.split('=') + except ValueError: + break + + link[key.strip(replace_chars)] = value.strip(replace_chars) + + links.append(link) + + return links + + +# Null bytes; no need to recreate these on each call to guess_json_utf +_null = '\x00'.encode('ascii') # encoding to ASCII for Python 3 +_null2 = _null * 2 +_null3 = _null * 3 + + +def guess_json_utf(data): + """ + :rtype: str + """ + # JSON always starts with two ASCII characters, so detection is as + # easy as counting the nulls and from their location and count + # determine the encoding. Also detect a BOM, if present. + sample = data[:4] + if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE): + return 'utf-32' # BOM included + if sample[:3] == codecs.BOM_UTF8: + return 'utf-8-sig' # BOM included, MS style (discouraged) + if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE): + return 'utf-16' # BOM included + nullcount = sample.count(_null) + if nullcount == 0: + return 'utf-8' + if nullcount == 2: + if sample[::2] == _null2: # 1st and 3rd are null + return 'utf-16-be' + if sample[1::2] == _null2: # 2nd and 4th are null + return 'utf-16-le' + # Did not detect 2 valid UTF-16 ascii-range characters + if nullcount == 3: + if sample[:3] == _null3: + return 'utf-32-be' + if sample[1:] == _null3: + return 'utf-32-le' + # Did not detect a valid UTF-32 ascii-range character + return None + + +def prepend_scheme_if_needed(url, new_scheme): + """Given a URL that may or may not have a scheme, prepend the given scheme. + Does not replace a present scheme with the one provided as an argument. + + :rtype: str + """ + scheme, netloc, path, params, query, fragment = urlparse(url, new_scheme) + + # urlparse is a finicky beast, and sometimes decides that there isn't a + # netloc present. Assume that it's being over-cautious, and switch netloc + # and path if urlparse decided there was no netloc. + if not netloc: + netloc, path = path, netloc + + return urlunparse((scheme, netloc, path, params, query, fragment)) + + +def get_auth_from_url(url): + """Given a url with authentication components, extract them into a tuple of + username,password. + + :rtype: (str,str) + """ + parsed = urlparse(url) + + try: + auth = (unquote(parsed.username), unquote(parsed.password)) + except (AttributeError, TypeError): + auth = ('', '') + + return auth + + +# Moved outside of function to avoid recompile every call +_CLEAN_HEADER_REGEX_BYTE = re.compile(b'^\\S[^\\r\\n]*$|^$') +_CLEAN_HEADER_REGEX_STR = re.compile(r'^\S[^\r\n]*$|^$') + + +def check_header_validity(header): + """Verifies that header value is a string which doesn't contain + leading whitespace or return characters. This prevents unintended + header injection. + + :param header: tuple, in the format (name, value). + """ + name, value = header + + if isinstance(value, bytes): + pat = _CLEAN_HEADER_REGEX_BYTE + else: + pat = _CLEAN_HEADER_REGEX_STR + try: + if not pat.match(value): + raise InvalidHeader("Invalid return character or leading space in header: %s" % name) + except TypeError: + raise InvalidHeader("Value for header {%s: %s} must be of type str or " + "bytes, not %s" % (name, value, type(value))) + + +def urldefragauth(url): + """ + Given a url remove the fragment and the authentication part. + + :rtype: str + """ + scheme, netloc, path, params, query, fragment = urlparse(url) + + # see func:`prepend_scheme_if_needed` + if not netloc: + netloc, path = path, netloc + + netloc = netloc.rsplit('@', 1)[-1] + + return urlunparse((scheme, netloc, path, params, query, '')) + + +def rewind_body(prepared_request): + """Move file pointer back to its recorded starting position + so it can be read again on redirect. + """ + body_seek = getattr(prepared_request.body, 'seek', None) + if body_seek is not None and isinstance(prepared_request._body_position, integer_types): + try: + body_seek(prepared_request._body_position) + except (IOError, OSError): + raise UnrewindableBodyError("An error occurred when rewinding request " + "body for redirect.") + else: + raise UnrewindableBodyError("Unable to rewind request body for redirect.") diff --git a/winvenv/Lib/site-packages/pip/_vendor/retrying.py b/winvenv/Lib/site-packages/pip/_vendor/retrying.py new file mode 100644 index 0000000..6d1e627 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/retrying.py @@ -0,0 +1,267 @@ +## Copyright 2013-2014 Ray Holder +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. + +import random +from pip._vendor import six +import sys +import time +import traceback + + +# sys.maxint / 2, since Python 3.2 doesn't have a sys.maxint... +MAX_WAIT = 1073741823 + + +def retry(*dargs, **dkw): + """ + Decorator function that instantiates the Retrying object + @param *dargs: positional arguments passed to Retrying object + @param **dkw: keyword arguments passed to the Retrying object + """ + # support both @retry and @retry() as valid syntax + if len(dargs) == 1 and callable(dargs[0]): + def wrap_simple(f): + + @six.wraps(f) + def wrapped_f(*args, **kw): + return Retrying().call(f, *args, **kw) + + return wrapped_f + + return wrap_simple(dargs[0]) + + else: + def wrap(f): + + @six.wraps(f) + def wrapped_f(*args, **kw): + return Retrying(*dargs, **dkw).call(f, *args, **kw) + + return wrapped_f + + return wrap + + +class Retrying(object): + + def __init__(self, + stop=None, wait=None, + stop_max_attempt_number=None, + stop_max_delay=None, + wait_fixed=None, + wait_random_min=None, wait_random_max=None, + wait_incrementing_start=None, wait_incrementing_increment=None, + wait_exponential_multiplier=None, wait_exponential_max=None, + retry_on_exception=None, + retry_on_result=None, + wrap_exception=False, + stop_func=None, + wait_func=None, + wait_jitter_max=None): + + self._stop_max_attempt_number = 5 if stop_max_attempt_number is None else stop_max_attempt_number + self._stop_max_delay = 100 if stop_max_delay is None else stop_max_delay + self._wait_fixed = 1000 if wait_fixed is None else wait_fixed + self._wait_random_min = 0 if wait_random_min is None else wait_random_min + self._wait_random_max = 1000 if wait_random_max is None else wait_random_max + self._wait_incrementing_start = 0 if wait_incrementing_start is None else wait_incrementing_start + self._wait_incrementing_increment = 100 if wait_incrementing_increment is None else wait_incrementing_increment + self._wait_exponential_multiplier = 1 if wait_exponential_multiplier is None else wait_exponential_multiplier + self._wait_exponential_max = MAX_WAIT if wait_exponential_max is None else wait_exponential_max + self._wait_jitter_max = 0 if wait_jitter_max is None else wait_jitter_max + + # TODO add chaining of stop behaviors + # stop behavior + stop_funcs = [] + if stop_max_attempt_number is not None: + stop_funcs.append(self.stop_after_attempt) + + if stop_max_delay is not None: + stop_funcs.append(self.stop_after_delay) + + if stop_func is not None: + self.stop = stop_func + + elif stop is None: + self.stop = lambda attempts, delay: any(f(attempts, delay) for f in stop_funcs) + + else: + self.stop = getattr(self, stop) + + # TODO add chaining of wait behaviors + # wait behavior + wait_funcs = [lambda *args, **kwargs: 0] + if wait_fixed is not None: + wait_funcs.append(self.fixed_sleep) + + if wait_random_min is not None or wait_random_max is not None: + wait_funcs.append(self.random_sleep) + + if wait_incrementing_start is not None or wait_incrementing_increment is not None: + wait_funcs.append(self.incrementing_sleep) + + if wait_exponential_multiplier is not None or wait_exponential_max is not None: + wait_funcs.append(self.exponential_sleep) + + if wait_func is not None: + self.wait = wait_func + + elif wait is None: + self.wait = lambda attempts, delay: max(f(attempts, delay) for f in wait_funcs) + + else: + self.wait = getattr(self, wait) + + # retry on exception filter + if retry_on_exception is None: + self._retry_on_exception = self.always_reject + else: + self._retry_on_exception = retry_on_exception + + # TODO simplify retrying by Exception types + # retry on result filter + if retry_on_result is None: + self._retry_on_result = self.never_reject + else: + self._retry_on_result = retry_on_result + + self._wrap_exception = wrap_exception + + def stop_after_attempt(self, previous_attempt_number, delay_since_first_attempt_ms): + """Stop after the previous attempt >= stop_max_attempt_number.""" + return previous_attempt_number >= self._stop_max_attempt_number + + def stop_after_delay(self, previous_attempt_number, delay_since_first_attempt_ms): + """Stop after the time from the first attempt >= stop_max_delay.""" + return delay_since_first_attempt_ms >= self._stop_max_delay + + def no_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """Don't sleep at all before retrying.""" + return 0 + + def fixed_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """Sleep a fixed amount of time between each retry.""" + return self._wait_fixed + + def random_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """Sleep a random amount of time between wait_random_min and wait_random_max""" + return random.randint(self._wait_random_min, self._wait_random_max) + + def incrementing_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + """ + Sleep an incremental amount of time after each attempt, starting at + wait_incrementing_start and incrementing by wait_incrementing_increment + """ + result = self._wait_incrementing_start + (self._wait_incrementing_increment * (previous_attempt_number - 1)) + if result < 0: + result = 0 + return result + + def exponential_sleep(self, previous_attempt_number, delay_since_first_attempt_ms): + exp = 2 ** previous_attempt_number + result = self._wait_exponential_multiplier * exp + if result > self._wait_exponential_max: + result = self._wait_exponential_max + if result < 0: + result = 0 + return result + + def never_reject(self, result): + return False + + def always_reject(self, result): + return True + + def should_reject(self, attempt): + reject = False + if attempt.has_exception: + reject |= self._retry_on_exception(attempt.value[1]) + else: + reject |= self._retry_on_result(attempt.value) + + return reject + + def call(self, fn, *args, **kwargs): + start_time = int(round(time.time() * 1000)) + attempt_number = 1 + while True: + try: + attempt = Attempt(fn(*args, **kwargs), attempt_number, False) + except: + tb = sys.exc_info() + attempt = Attempt(tb, attempt_number, True) + + if not self.should_reject(attempt): + return attempt.get(self._wrap_exception) + + delay_since_first_attempt_ms = int(round(time.time() * 1000)) - start_time + if self.stop(attempt_number, delay_since_first_attempt_ms): + if not self._wrap_exception and attempt.has_exception: + # get() on an attempt with an exception should cause it to be raised, but raise just in case + raise attempt.get() + else: + raise RetryError(attempt) + else: + sleep = self.wait(attempt_number, delay_since_first_attempt_ms) + if self._wait_jitter_max: + jitter = random.random() * self._wait_jitter_max + sleep = sleep + max(0, jitter) + time.sleep(sleep / 1000.0) + + attempt_number += 1 + + +class Attempt(object): + """ + An Attempt encapsulates a call to a target function that may end as a + normal return value from the function or an Exception depending on what + occurred during the execution. + """ + + def __init__(self, value, attempt_number, has_exception): + self.value = value + self.attempt_number = attempt_number + self.has_exception = has_exception + + def get(self, wrap_exception=False): + """ + Return the return value of this Attempt instance or raise an Exception. + If wrap_exception is true, this Attempt is wrapped inside of a + RetryError before being raised. + """ + if self.has_exception: + if wrap_exception: + raise RetryError(self) + else: + six.reraise(self.value[0], self.value[1], self.value[2]) + else: + return self.value + + def __repr__(self): + if self.has_exception: + return "Attempts: {0}, Error:\n{1}".format(self.attempt_number, "".join(traceback.format_tb(self.value[2]))) + else: + return "Attempts: {0}, Value: {1}".format(self.attempt_number, self.value) + + +class RetryError(Exception): + """ + A RetryError encapsulates the last Attempt instance right before giving up. + """ + + def __init__(self, last_attempt): + self.last_attempt = last_attempt + + def __str__(self): + return "RetryError[{0}]".format(self.last_attempt) diff --git a/winvenv/Lib/site-packages/pip/_vendor/six.py b/winvenv/Lib/site-packages/pip/_vendor/six.py new file mode 100644 index 0000000..6bf4fd3 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/six.py @@ -0,0 +1,891 @@ +# Copyright (c) 2010-2017 Benjamin Peterson +# +# 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. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.11.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + try: + if from_value is None: + raise value + raise value from from_value + finally: + value = None +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/__init__.py new file mode 100644 index 0000000..4bd533b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/__init__.py @@ -0,0 +1,97 @@ +""" +urllib3 - Thread-safe connection pooling and re-using. +""" + +from __future__ import absolute_import +import warnings + +from .connectionpool import ( + HTTPConnectionPool, + HTTPSConnectionPool, + connection_from_url +) + +from . import exceptions +from .filepost import encode_multipart_formdata +from .poolmanager import PoolManager, ProxyManager, proxy_from_url +from .response import HTTPResponse +from .util.request import make_headers +from .util.url import get_host +from .util.timeout import Timeout +from .util.retry import Retry + + +# Set default logging handler to avoid "No handler found" warnings. +import logging +try: # Python 2.7+ + from logging import NullHandler +except ImportError: + class NullHandler(logging.Handler): + def emit(self, record): + pass + +__author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' +__license__ = 'MIT' +__version__ = '1.23' + +__all__ = ( + 'HTTPConnectionPool', + 'HTTPSConnectionPool', + 'PoolManager', + 'ProxyManager', + 'HTTPResponse', + 'Retry', + 'Timeout', + 'add_stderr_logger', + 'connection_from_url', + 'disable_warnings', + 'encode_multipart_formdata', + 'get_host', + 'make_headers', + 'proxy_from_url', +) + +logging.getLogger(__name__).addHandler(NullHandler()) + + +def add_stderr_logger(level=logging.DEBUG): + """ + Helper for quickly adding a StreamHandler to the logger. Useful for + debugging. + + Returns the handler after adding it. + """ + # This method needs to be in this __init__.py to get the __name__ correct + # even if urllib3 is vendored within another package. + logger = logging.getLogger(__name__) + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) + logger.addHandler(handler) + logger.setLevel(level) + logger.debug('Added a stderr logging handler to logger: %s', __name__) + return handler + + +# ... Clean up. +del NullHandler + + +# All warning filters *must* be appended unless you're really certain that they +# shouldn't be: otherwise, it's very hard for users to use most Python +# mechanisms to silence them. +# SecurityWarning's always go off by default. +warnings.simplefilter('always', exceptions.SecurityWarning, append=True) +# SubjectAltNameWarning's should go off once per host +warnings.simplefilter('default', exceptions.SubjectAltNameWarning, append=True) +# InsecurePlatformWarning's don't vary between requests, so we keep it default. +warnings.simplefilter('default', exceptions.InsecurePlatformWarning, + append=True) +# SNIMissingWarnings should go off only once. +warnings.simplefilter('default', exceptions.SNIMissingWarning, append=True) + + +def disable_warnings(category=exceptions.HTTPWarning): + """ + Helper for quickly disabling all urllib3 warnings. + """ + warnings.simplefilter('ignore', category) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/_collections.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/_collections.py new file mode 100644 index 0000000..6e36b84 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/_collections.py @@ -0,0 +1,332 @@ +from __future__ import absolute_import +try: + from collections.abc import Mapping, MutableMapping +except ImportError: + from collections import Mapping, MutableMapping +try: + from threading import RLock +except ImportError: # Platform-specific: No threads available + class RLock: + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, traceback): + pass + + +try: # Python 2.7+ + from collections import OrderedDict +except ImportError: + from .packages.ordered_dict import OrderedDict +from .exceptions import InvalidHeader +from .packages.six import iterkeys, itervalues, PY3 + + +__all__ = ['RecentlyUsedContainer', 'HTTPHeaderDict'] + + +_Null = object() + + +class RecentlyUsedContainer(MutableMapping): + """ + Provides a thread-safe dict-like container which maintains up to + ``maxsize`` keys while throwing away the least-recently-used keys beyond + ``maxsize``. + + :param maxsize: + Maximum number of recent elements to retain. + + :param dispose_func: + Every time an item is evicted from the container, + ``dispose_func(value)`` is called. Callback which will get called + """ + + ContainerCls = OrderedDict + + def __init__(self, maxsize=10, dispose_func=None): + self._maxsize = maxsize + self.dispose_func = dispose_func + + self._container = self.ContainerCls() + self.lock = RLock() + + def __getitem__(self, key): + # Re-insert the item, moving it to the end of the eviction line. + with self.lock: + item = self._container.pop(key) + self._container[key] = item + return item + + def __setitem__(self, key, value): + evicted_value = _Null + with self.lock: + # Possibly evict the existing value of 'key' + evicted_value = self._container.get(key, _Null) + self._container[key] = value + + # If we didn't evict an existing value, we might have to evict the + # least recently used item from the beginning of the container. + if len(self._container) > self._maxsize: + _key, evicted_value = self._container.popitem(last=False) + + if self.dispose_func and evicted_value is not _Null: + self.dispose_func(evicted_value) + + def __delitem__(self, key): + with self.lock: + value = self._container.pop(key) + + if self.dispose_func: + self.dispose_func(value) + + def __len__(self): + with self.lock: + return len(self._container) + + def __iter__(self): + raise NotImplementedError('Iteration over this class is unlikely to be threadsafe.') + + def clear(self): + with self.lock: + # Copy pointers to all values, then wipe the mapping + values = list(itervalues(self._container)) + self._container.clear() + + if self.dispose_func: + for value in values: + self.dispose_func(value) + + def keys(self): + with self.lock: + return list(iterkeys(self._container)) + + +class HTTPHeaderDict(MutableMapping): + """ + :param headers: + An iterable of field-value pairs. Must not contain multiple field names + when compared case-insensitively. + + :param kwargs: + Additional field-value pairs to pass in to ``dict.update``. + + A ``dict`` like container for storing HTTP Headers. + + Field names are stored and compared case-insensitively in compliance with + RFC 7230. Iteration provides the first case-sensitive key seen for each + case-insensitive pair. + + Using ``__setitem__`` syntax overwrites fields that compare equal + case-insensitively in order to maintain ``dict``'s api. For fields that + compare equal, instead create a new ``HTTPHeaderDict`` and use ``.add`` + in a loop. + + If multiple fields that are equal case-insensitively are passed to the + constructor or ``.update``, the behavior is undefined and some will be + lost. + + >>> headers = HTTPHeaderDict() + >>> headers.add('Set-Cookie', 'foo=bar') + >>> headers.add('set-cookie', 'baz=quxx') + >>> headers['content-length'] = '7' + >>> headers['SET-cookie'] + 'foo=bar, baz=quxx' + >>> headers['Content-Length'] + '7' + """ + + def __init__(self, headers=None, **kwargs): + super(HTTPHeaderDict, self).__init__() + self._container = OrderedDict() + if headers is not None: + if isinstance(headers, HTTPHeaderDict): + self._copy_from(headers) + else: + self.extend(headers) + if kwargs: + self.extend(kwargs) + + def __setitem__(self, key, val): + self._container[key.lower()] = [key, val] + return self._container[key.lower()] + + def __getitem__(self, key): + val = self._container[key.lower()] + return ', '.join(val[1:]) + + def __delitem__(self, key): + del self._container[key.lower()] + + def __contains__(self, key): + return key.lower() in self._container + + def __eq__(self, other): + if not isinstance(other, Mapping) and not hasattr(other, 'keys'): + return False + if not isinstance(other, type(self)): + other = type(self)(other) + return (dict((k.lower(), v) for k, v in self.itermerged()) == + dict((k.lower(), v) for k, v in other.itermerged())) + + def __ne__(self, other): + return not self.__eq__(other) + + if not PY3: # Python 2 + iterkeys = MutableMapping.iterkeys + itervalues = MutableMapping.itervalues + + __marker = object() + + def __len__(self): + return len(self._container) + + def __iter__(self): + # Only provide the originally cased names + for vals in self._container.values(): + yield vals[0] + + def pop(self, key, default=__marker): + '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + ''' + # Using the MutableMapping function directly fails due to the private marker. + # Using ordinary dict.pop would expose the internal structures. + # So let's reinvent the wheel. + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def discard(self, key): + try: + del self[key] + except KeyError: + pass + + def add(self, key, val): + """Adds a (name, value) pair, doesn't overwrite the value if it already + exists. + + >>> headers = HTTPHeaderDict(foo='bar') + >>> headers.add('Foo', 'baz') + >>> headers['foo'] + 'bar, baz' + """ + key_lower = key.lower() + new_vals = [key, val] + # Keep the common case aka no item present as fast as possible + vals = self._container.setdefault(key_lower, new_vals) + if new_vals is not vals: + vals.append(val) + + def extend(self, *args, **kwargs): + """Generic import function for any type of header-like object. + Adapted version of MutableMapping.update in order to insert items + with self.add instead of self.__setitem__ + """ + if len(args) > 1: + raise TypeError("extend() takes at most 1 positional " + "arguments ({0} given)".format(len(args))) + other = args[0] if len(args) >= 1 else () + + if isinstance(other, HTTPHeaderDict): + for key, val in other.iteritems(): + self.add(key, val) + elif isinstance(other, Mapping): + for key in other: + self.add(key, other[key]) + elif hasattr(other, "keys"): + for key in other.keys(): + self.add(key, other[key]) + else: + for key, value in other: + self.add(key, value) + + for key, value in kwargs.items(): + self.add(key, value) + + def getlist(self, key, default=__marker): + """Returns a list of all the values for the named field. Returns an + empty list if the key doesn't exist.""" + try: + vals = self._container[key.lower()] + except KeyError: + if default is self.__marker: + return [] + return default + else: + return vals[1:] + + # Backwards compatibility for httplib + getheaders = getlist + getallmatchingheaders = getlist + iget = getlist + + # Backwards compatibility for http.cookiejar + get_all = getlist + + def __repr__(self): + return "%s(%s)" % (type(self).__name__, dict(self.itermerged())) + + def _copy_from(self, other): + for key in other: + val = other.getlist(key) + if isinstance(val, list): + # Don't need to convert tuples + val = list(val) + self._container[key.lower()] = [key] + val + + def copy(self): + clone = type(self)() + clone._copy_from(self) + return clone + + def iteritems(self): + """Iterate over all header lines, including duplicate ones.""" + for key in self: + vals = self._container[key.lower()] + for val in vals[1:]: + yield vals[0], val + + def itermerged(self): + """Iterate over all headers, merging duplicate ones together.""" + for key in self: + val = self._container[key.lower()] + yield val[0], ', '.join(val[1:]) + + def items(self): + return list(self.iteritems()) + + @classmethod + def from_httplib(cls, message): # Python 2 + """Read headers from a Python 2 httplib message object.""" + # python2.7 does not expose a proper API for exporting multiheaders + # efficiently. This function re-reads raw lines from the message + # object and extracts the multiheaders properly. + obs_fold_continued_leaders = (' ', '\t') + headers = [] + + for line in message.headers: + if line.startswith(obs_fold_continued_leaders): + if not headers: + # We received a header line that starts with OWS as described + # in RFC-7230 S3.2.4. This indicates a multiline header, but + # there exists no previous header to which we can attach it. + raise InvalidHeader( + 'Header continuation with no previous header: %s' % line + ) + else: + key, value = headers[-1] + headers[-1] = (key, value + ' ' + line.strip()) + continue + + key, value = line.split(':', 1) + headers.append((key, value.strip())) + + return cls(headers) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/connection.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/connection.py new file mode 100644 index 0000000..a03b573 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/connection.py @@ -0,0 +1,403 @@ +from __future__ import absolute_import +import datetime +import logging +import os +import sys +import socket +from socket import error as SocketError, timeout as SocketTimeout +import warnings +from .packages import six +from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection +from .packages.six.moves.http_client import HTTPException # noqa: F401 + +try: # Compiled with SSL? + import ssl + BaseSSLError = ssl.SSLError +except (ImportError, AttributeError): # Platform-specific: No SSL. + ssl = None + + class BaseSSLError(BaseException): + pass + + +try: # Python 3: + # Not a no-op, we're adding this to the namespace so it can be imported. + ConnectionError = ConnectionError +except NameError: # Python 2: + class ConnectionError(Exception): + pass + + +from .exceptions import ( + NewConnectionError, + ConnectTimeoutError, + SubjectAltNameWarning, + SystemTimeWarning, +) +from .packages.ssl_match_hostname import match_hostname, CertificateError + +from .util.ssl_ import ( + resolve_cert_reqs, + resolve_ssl_version, + assert_fingerprint, + create_urllib3_context, + ssl_wrap_socket +) + + +from .util import connection + +from ._collections import HTTPHeaderDict + +log = logging.getLogger(__name__) + +port_by_scheme = { + 'http': 80, + 'https': 443, +} + +# When updating RECENT_DATE, move it to within two years of the current date, +# and not less than 6 months ago. +# Example: if Today is 2018-01-01, then RECENT_DATE should be any date on or +# after 2016-01-01 (today - 2 years) AND before 2017-07-01 (today - 6 months) +RECENT_DATE = datetime.date(2017, 6, 30) + + +class DummyConnection(object): + """Used to detect a failed ConnectionCls import.""" + pass + + +class HTTPConnection(_HTTPConnection, object): + """ + Based on httplib.HTTPConnection but provides an extra constructor + backwards-compatibility layer between older and newer Pythons. + + Additional keyword parameters are used to configure attributes of the connection. + Accepted parameters include: + + - ``strict``: See the documentation on :class:`urllib3.connectionpool.HTTPConnectionPool` + - ``source_address``: Set the source address for the current connection. + + .. note:: This is ignored for Python 2.6. It is only applied for 2.7 and 3.x + + - ``socket_options``: Set specific options on the underlying socket. If not specified, then + defaults are loaded from ``HTTPConnection.default_socket_options`` which includes disabling + Nagle's algorithm (sets TCP_NODELAY to 1) unless the connection is behind a proxy. + + For example, if you wish to enable TCP Keep Alive in addition to the defaults, + you might pass:: + + HTTPConnection.default_socket_options + [ + (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1), + ] + + Or you may want to disable the defaults by passing an empty list (e.g., ``[]``). + """ + + default_port = port_by_scheme['http'] + + #: Disable Nagle's algorithm by default. + #: ``[(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]`` + default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)] + + #: Whether this connection verifies the host's certificate. + is_verified = False + + def __init__(self, *args, **kw): + if six.PY3: # Python 3 + kw.pop('strict', None) + + # Pre-set source_address in case we have an older Python like 2.6. + self.source_address = kw.get('source_address') + + if sys.version_info < (2, 7): # Python 2.6 + # _HTTPConnection on Python 2.6 will balk at this keyword arg, but + # not newer versions. We can still use it when creating a + # connection though, so we pop it *after* we have saved it as + # self.source_address. + kw.pop('source_address', None) + + #: The socket options provided by the user. If no options are + #: provided, we use the default options. + self.socket_options = kw.pop('socket_options', self.default_socket_options) + + # Superclass also sets self.source_address in Python 2.7+. + _HTTPConnection.__init__(self, *args, **kw) + + @property + def host(self): + """ + Getter method to remove any trailing dots that indicate the hostname is an FQDN. + + In general, SSL certificates don't include the trailing dot indicating a + fully-qualified domain name, and thus, they don't validate properly when + checked against a domain name that includes the dot. In addition, some + servers may not expect to receive the trailing dot when provided. + + However, the hostname with trailing dot is critical to DNS resolution; doing a + lookup with the trailing dot will properly only resolve the appropriate FQDN, + whereas a lookup without a trailing dot will search the system's search domain + list. Thus, it's important to keep the original host around for use only in + those cases where it's appropriate (i.e., when doing DNS lookup to establish the + actual TCP connection across which we're going to send HTTP requests). + """ + return self._dns_host.rstrip('.') + + @host.setter + def host(self, value): + """ + Setter for the `host` property. + + We assume that only urllib3 uses the _dns_host attribute; httplib itself + only uses `host`, and it seems reasonable that other libraries follow suit. + """ + self._dns_host = value + + def _new_conn(self): + """ Establish a socket connection and set nodelay settings on it. + + :return: New socket connection. + """ + extra_kw = {} + if self.source_address: + extra_kw['source_address'] = self.source_address + + if self.socket_options: + extra_kw['socket_options'] = self.socket_options + + try: + conn = connection.create_connection( + (self._dns_host, self.port), self.timeout, **extra_kw) + + except SocketTimeout as e: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout)) + + except SocketError as e: + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e) + + return conn + + def _prepare_conn(self, conn): + self.sock = conn + # the _tunnel_host attribute was added in python 2.6.3 (via + # http://hg.python.org/cpython/rev/0f57b30a152f) so pythons 2.6(0-2) do + # not have them. + if getattr(self, '_tunnel_host', None): + # TODO: Fix tunnel so it doesn't depend on self.sock state. + self._tunnel() + # Mark this connection as not reusable + self.auto_open = 0 + + def connect(self): + conn = self._new_conn() + self._prepare_conn(conn) + + def request_chunked(self, method, url, body=None, headers=None): + """ + Alternative to the common request method, which sends the + body with chunked encoding and not as one block + """ + headers = HTTPHeaderDict(headers if headers is not None else {}) + skip_accept_encoding = 'accept-encoding' in headers + skip_host = 'host' in headers + self.putrequest( + method, + url, + skip_accept_encoding=skip_accept_encoding, + skip_host=skip_host + ) + for header, value in headers.items(): + self.putheader(header, value) + if 'transfer-encoding' not in headers: + self.putheader('Transfer-Encoding', 'chunked') + self.endheaders() + + if body is not None: + stringish_types = six.string_types + (six.binary_type,) + if isinstance(body, stringish_types): + body = (body,) + for chunk in body: + if not chunk: + continue + if not isinstance(chunk, six.binary_type): + chunk = chunk.encode('utf8') + len_str = hex(len(chunk))[2:] + self.send(len_str.encode('utf-8')) + self.send(b'\r\n') + self.send(chunk) + self.send(b'\r\n') + + # After the if clause, to always have a closed body + self.send(b'0\r\n\r\n') + + +class HTTPSConnection(HTTPConnection): + default_port = port_by_scheme['https'] + + ssl_version = None + + def __init__(self, host, port=None, key_file=None, cert_file=None, + strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, + ssl_context=None, **kw): + + HTTPConnection.__init__(self, host, port, strict=strict, + timeout=timeout, **kw) + + self.key_file = key_file + self.cert_file = cert_file + self.ssl_context = ssl_context + + # Required property for Google AppEngine 1.9.0 which otherwise causes + # HTTPS requests to go out as HTTP. (See Issue #356) + self._protocol = 'https' + + def connect(self): + conn = self._new_conn() + self._prepare_conn(conn) + + if self.ssl_context is None: + self.ssl_context = create_urllib3_context( + ssl_version=resolve_ssl_version(None), + cert_reqs=resolve_cert_reqs(None), + ) + + self.sock = ssl_wrap_socket( + sock=conn, + keyfile=self.key_file, + certfile=self.cert_file, + ssl_context=self.ssl_context, + ) + + +class VerifiedHTTPSConnection(HTTPSConnection): + """ + Based on httplib.HTTPSConnection but wraps the socket with + SSL certification. + """ + cert_reqs = None + ca_certs = None + ca_cert_dir = None + ssl_version = None + assert_fingerprint = None + + def set_cert(self, key_file=None, cert_file=None, + cert_reqs=None, ca_certs=None, + assert_hostname=None, assert_fingerprint=None, + ca_cert_dir=None): + """ + This method should only be called once, before the connection is used. + """ + # If cert_reqs is not provided, we can try to guess. If the user gave + # us a cert database, we assume they want to use it: otherwise, if + # they gave us an SSL Context object we should use whatever is set for + # it. + if cert_reqs is None: + if ca_certs or ca_cert_dir: + cert_reqs = 'CERT_REQUIRED' + elif self.ssl_context is not None: + cert_reqs = self.ssl_context.verify_mode + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + self.ca_certs = ca_certs and os.path.expanduser(ca_certs) + self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir) + + def connect(self): + # Add certificate verification + conn = self._new_conn() + + hostname = self.host + if getattr(self, '_tunnel_host', None): + # _tunnel_host was added in Python 2.6.3 + # (See: http://hg.python.org/cpython/rev/0f57b30a152f) + + self.sock = conn + # Calls self._set_hostport(), so self.host is + # self._tunnel_host below. + self._tunnel() + # Mark this connection as not reusable + self.auto_open = 0 + + # Override the host with the one we're requesting data from. + hostname = self._tunnel_host + + is_time_off = datetime.date.today() < RECENT_DATE + if is_time_off: + warnings.warn(( + 'System time is way off (before {0}). This will probably ' + 'lead to SSL verification errors').format(RECENT_DATE), + SystemTimeWarning + ) + + # Wrap socket using verification with the root certs in + # trusted_root_certs + if self.ssl_context is None: + self.ssl_context = create_urllib3_context( + ssl_version=resolve_ssl_version(self.ssl_version), + cert_reqs=resolve_cert_reqs(self.cert_reqs), + ) + + context = self.ssl_context + context.verify_mode = resolve_cert_reqs(self.cert_reqs) + self.sock = ssl_wrap_socket( + sock=conn, + keyfile=self.key_file, + certfile=self.cert_file, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + server_hostname=hostname, + ssl_context=context) + + if self.assert_fingerprint: + assert_fingerprint(self.sock.getpeercert(binary_form=True), + self.assert_fingerprint) + elif context.verify_mode != ssl.CERT_NONE \ + and not getattr(context, 'check_hostname', False) \ + and self.assert_hostname is not False: + # While urllib3 attempts to always turn off hostname matching from + # the TLS library, this cannot always be done. So we check whether + # the TLS Library still thinks it's matching hostnames. + cert = self.sock.getpeercert() + if not cert.get('subjectAltName', ()): + warnings.warn(( + 'Certificate for {0} has no `subjectAltName`, falling back to check for a ' + '`commonName` for now. This feature is being removed by major browsers and ' + 'deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 ' + 'for details.)'.format(hostname)), + SubjectAltNameWarning + ) + _match_hostname(cert, self.assert_hostname or hostname) + + self.is_verified = ( + context.verify_mode == ssl.CERT_REQUIRED or + self.assert_fingerprint is not None + ) + + +def _match_hostname(cert, asserted_hostname): + try: + match_hostname(cert, asserted_hostname) + except CertificateError as e: + log.error( + 'Certificate did not match expected hostname: %s. ' + 'Certificate: %s', asserted_hostname, cert + ) + # Add cert to exception and reraise so client code can inspect + # the cert when catching the exception, if they want to + e._peer_cert = cert + raise + + +if ssl: + # Make a copy for testing. + UnverifiedHTTPSConnection = HTTPSConnection + HTTPSConnection = VerifiedHTTPSConnection +else: + HTTPSConnection = DummyConnection diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py new file mode 100644 index 0000000..8fcb0bc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py @@ -0,0 +1,906 @@ +from __future__ import absolute_import +import errno +import logging +import sys +import warnings + +from socket import error as SocketError, timeout as SocketTimeout +import socket + + +from .exceptions import ( + ClosedPoolError, + ProtocolError, + EmptyPoolError, + HeaderParsingError, + HostChangedError, + LocationValueError, + MaxRetryError, + ProxyError, + ReadTimeoutError, + SSLError, + TimeoutError, + InsecureRequestWarning, + NewConnectionError, +) +from .packages.ssl_match_hostname import CertificateError +from .packages import six +from .packages.six.moves import queue +from .connection import ( + port_by_scheme, + DummyConnection, + HTTPConnection, HTTPSConnection, VerifiedHTTPSConnection, + HTTPException, BaseSSLError, +) +from .request import RequestMethods +from .response import HTTPResponse + +from .util.connection import is_connection_dropped +from .util.request import set_file_position +from .util.response import assert_header_parsing +from .util.retry import Retry +from .util.timeout import Timeout +from .util.url import get_host, Url, NORMALIZABLE_SCHEMES +from .util.queue import LifoQueue + + +xrange = six.moves.xrange + +log = logging.getLogger(__name__) + +_Default = object() + + +# Pool objects +class ConnectionPool(object): + """ + Base class for all connection pools, such as + :class:`.HTTPConnectionPool` and :class:`.HTTPSConnectionPool`. + """ + + scheme = None + QueueCls = LifoQueue + + def __init__(self, host, port=None): + if not host: + raise LocationValueError("No host specified.") + + self.host = _ipv6_host(host, self.scheme) + self._proxy_host = host.lower() + self.port = port + + def __str__(self): + return '%s(host=%r, port=%r)' % (type(self).__name__, + self.host, self.port) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + # Return False to re-raise any potential exceptions + return False + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + pass + + +# This is taken from http://hg.python.org/cpython/file/7aaba721ebc0/Lib/socket.py#l252 +_blocking_errnos = set([errno.EAGAIN, errno.EWOULDBLOCK]) + + +class HTTPConnectionPool(ConnectionPool, RequestMethods): + """ + Thread-safe connection pool for one host. + + :param host: + Host used for this HTTP Connection (e.g. "localhost"), passed into + :class:`httplib.HTTPConnection`. + + :param port: + Port used for this HTTP Connection (None is equivalent to 80), passed + into :class:`httplib.HTTPConnection`. + + :param strict: + Causes BadStatusLine to be raised if the status line can't be parsed + as a valid HTTP/1.0 or 1.1 status line, passed into + :class:`httplib.HTTPConnection`. + + .. note:: + Only works in Python 2. This parameter is ignored in Python 3. + + :param timeout: + Socket timeout in seconds for each individual connection. This can + be a float or integer, which sets the timeout for the HTTP request, + or an instance of :class:`urllib3.util.Timeout` which gives you more + fine-grained control over request timeouts. After the constructor has + been parsed, this is always a `urllib3.util.Timeout` object. + + :param maxsize: + Number of connections to save that can be reused. More than 1 is useful + in multithreaded situations. If ``block`` is set to False, more + connections will be created but they will not be saved once they've + been used. + + :param block: + If set to True, no more than ``maxsize`` connections will be used at + a time. When no free connections are available, the call will block + until a connection has been released. This is a useful side effect for + particular multithreaded situations where one does not want to use more + than maxsize connections per host to prevent flooding. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param retries: + Retry configuration to use by default with requests in this pool. + + :param _proxy: + Parsed proxy URL, should not be used directly, instead, see + :class:`urllib3.connectionpool.ProxyManager`" + + :param _proxy_headers: + A dictionary with proxy headers, should not be used directly, + instead, see :class:`urllib3.connectionpool.ProxyManager`" + + :param \\**conn_kw: + Additional parameters are used to create fresh :class:`urllib3.connection.HTTPConnection`, + :class:`urllib3.connection.HTTPSConnection` instances. + """ + + scheme = 'http' + ConnectionCls = HTTPConnection + ResponseCls = HTTPResponse + + def __init__(self, host, port=None, strict=False, + timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, block=False, + headers=None, retries=None, + _proxy=None, _proxy_headers=None, + **conn_kw): + ConnectionPool.__init__(self, host, port) + RequestMethods.__init__(self, headers) + + self.strict = strict + + if not isinstance(timeout, Timeout): + timeout = Timeout.from_float(timeout) + + if retries is None: + retries = Retry.DEFAULT + + self.timeout = timeout + self.retries = retries + + self.pool = self.QueueCls(maxsize) + self.block = block + + self.proxy = _proxy + self.proxy_headers = _proxy_headers or {} + + # Fill the queue up so that doing get() on it will block properly + for _ in xrange(maxsize): + self.pool.put(None) + + # These are mostly for testing and debugging purposes. + self.num_connections = 0 + self.num_requests = 0 + self.conn_kw = conn_kw + + if self.proxy: + # Enable Nagle's algorithm for proxies, to avoid packet fragmentation. + # We cannot know if the user has added default socket options, so we cannot replace the + # list. + self.conn_kw.setdefault('socket_options', []) + + def _new_conn(self): + """ + Return a fresh :class:`HTTPConnection`. + """ + self.num_connections += 1 + log.debug("Starting new HTTP connection (%d): %s:%s", + self.num_connections, self.host, self.port or "80") + + conn = self.ConnectionCls(host=self.host, port=self.port, + timeout=self.timeout.connect_timeout, + strict=self.strict, **self.conn_kw) + return conn + + def _get_conn(self, timeout=None): + """ + Get a connection. Will return a pooled connection if one is available. + + If no connections are available and :prop:`.block` is ``False``, then a + fresh connection is returned. + + :param timeout: + Seconds to wait before giving up and raising + :class:`urllib3.exceptions.EmptyPoolError` if the pool is empty and + :prop:`.block` is ``True``. + """ + conn = None + try: + conn = self.pool.get(block=self.block, timeout=timeout) + + except AttributeError: # self.pool is None + raise ClosedPoolError(self, "Pool is closed.") + + except queue.Empty: + if self.block: + raise EmptyPoolError(self, + "Pool reached maximum size and no more " + "connections are allowed.") + pass # Oh well, we'll create a new connection then + + # If this is a persistent connection, check if it got disconnected + if conn and is_connection_dropped(conn): + log.debug("Resetting dropped connection: %s", self.host) + conn.close() + if getattr(conn, 'auto_open', 1) == 0: + # This is a proxied connection that has been mutated by + # httplib._tunnel() and cannot be reused (since it would + # attempt to bypass the proxy) + conn = None + + return conn or self._new_conn() + + def _put_conn(self, conn): + """ + Put a connection back into the pool. + + :param conn: + Connection object for the current host and port as returned by + :meth:`._new_conn` or :meth:`._get_conn`. + + If the pool is already full, the connection is closed and discarded + because we exceeded maxsize. If connections are discarded frequently, + then maxsize should be increased. + + If the pool is closed, then the connection will be closed and discarded. + """ + try: + self.pool.put(conn, block=False) + return # Everything is dandy, done. + except AttributeError: + # self.pool is None. + pass + except queue.Full: + # This should never happen if self.block == True + log.warning( + "Connection pool is full, discarding connection: %s", + self.host) + + # Connection never got put back into the pool, close it. + if conn: + conn.close() + + def _validate_conn(self, conn): + """ + Called right before a request is made, after the socket is created. + """ + pass + + def _prepare_proxy(self, conn): + # Nothing to do for HTTP connections. + pass + + def _get_timeout(self, timeout): + """ Helper that always returns a :class:`urllib3.util.Timeout` """ + if timeout is _Default: + return self.timeout.clone() + + if isinstance(timeout, Timeout): + return timeout.clone() + else: + # User passed us an int/float. This is for backwards compatibility, + # can be removed later + return Timeout.from_float(timeout) + + def _raise_timeout(self, err, url, timeout_value): + """Is the error actually a timeout? Will raise a ReadTimeout or pass""" + + if isinstance(err, SocketTimeout): + raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) + + # See the above comment about EAGAIN in Python 3. In Python 2 we have + # to specifically catch it and throw the timeout error + if hasattr(err, 'errno') and err.errno in _blocking_errnos: + raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) + + # Catch possible read timeouts thrown as SSL errors. If not the + # case, rethrow the original. We need to do this because of: + # http://bugs.python.org/issue10272 + if 'timed out' in str(err) or 'did not complete (read)' in str(err): # Python 2.6 + raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value) + + def _make_request(self, conn, method, url, timeout=_Default, chunked=False, + **httplib_request_kw): + """ + Perform a request on a given urllib connection object taken from our + pool. + + :param conn: + a connection from one of our connection pools + + :param timeout: + Socket timeout in seconds for the request. This can be a + float or integer, which will set the same timeout value for + the socket connect and the socket read, or an instance of + :class:`urllib3.util.Timeout`, which gives you more fine-grained + control over your timeouts. + """ + self.num_requests += 1 + + timeout_obj = self._get_timeout(timeout) + timeout_obj.start_connect() + conn.timeout = timeout_obj.connect_timeout + + # Trigger any extra validation we need to do. + try: + self._validate_conn(conn) + except (SocketTimeout, BaseSSLError) as e: + # Py2 raises this as a BaseSSLError, Py3 raises it as socket timeout. + self._raise_timeout(err=e, url=url, timeout_value=conn.timeout) + raise + + # conn.request() calls httplib.*.request, not the method in + # urllib3.request. It also calls makefile (recv) on the socket. + if chunked: + conn.request_chunked(method, url, **httplib_request_kw) + else: + conn.request(method, url, **httplib_request_kw) + + # Reset the timeout for the recv() on the socket + read_timeout = timeout_obj.read_timeout + + # App Engine doesn't have a sock attr + if getattr(conn, 'sock', None): + # In Python 3 socket.py will catch EAGAIN and return None when you + # try and read into the file pointer created by http.client, which + # instead raises a BadStatusLine exception. Instead of catching + # the exception and assuming all BadStatusLine exceptions are read + # timeouts, check for a zero timeout before making the request. + if read_timeout == 0: + raise ReadTimeoutError( + self, url, "Read timed out. (read timeout=%s)" % read_timeout) + if read_timeout is Timeout.DEFAULT_TIMEOUT: + conn.sock.settimeout(socket.getdefaulttimeout()) + else: # None or a value + conn.sock.settimeout(read_timeout) + + # Receive the response from the server + try: + try: # Python 2.7, use buffering of HTTP responses + httplib_response = conn.getresponse(buffering=True) + except TypeError: # Python 2.6 and older, Python 3 + try: + httplib_response = conn.getresponse() + except Exception as e: + # Remove the TypeError from the exception chain in Python 3; + # otherwise it looks like a programming error was the cause. + six.raise_from(e, None) + except (SocketTimeout, BaseSSLError, SocketError) as e: + self._raise_timeout(err=e, url=url, timeout_value=read_timeout) + raise + + # AppEngine doesn't have a version attr. + http_version = getattr(conn, '_http_vsn_str', 'HTTP/?') + log.debug("%s://%s:%s \"%s %s %s\" %s %s", self.scheme, self.host, self.port, + method, url, http_version, httplib_response.status, + httplib_response.length) + + try: + assert_header_parsing(httplib_response.msg) + except (HeaderParsingError, TypeError) as hpe: # Platform-specific: Python 3 + log.warning( + 'Failed to parse headers (url=%s): %s', + self._absolute_url(url), hpe, exc_info=True) + + return httplib_response + + def _absolute_url(self, path): + return Url(scheme=self.scheme, host=self.host, port=self.port, path=path).url + + def close(self): + """ + Close all pooled connections and disable the pool. + """ + if self.pool is None: + return + # Disable access to the pool + old_pool, self.pool = self.pool, None + + try: + while True: + conn = old_pool.get(block=False) + if conn: + conn.close() + + except queue.Empty: + pass # Done. + + def is_same_host(self, url): + """ + Check if the given ``url`` is a member of the same host as this + connection pool. + """ + if url.startswith('/'): + return True + + # TODO: Add optional support for socket.gethostbyname checking. + scheme, host, port = get_host(url) + + host = _ipv6_host(host, self.scheme) + + # Use explicit default port for comparison when none is given + if self.port and not port: + port = port_by_scheme.get(scheme) + elif not self.port and port == port_by_scheme.get(scheme): + port = None + + return (scheme, host, port) == (self.scheme, self.host, self.port) + + def urlopen(self, method, url, body=None, headers=None, retries=None, + redirect=True, assert_same_host=True, timeout=_Default, + pool_timeout=None, release_conn=None, chunked=False, + body_pos=None, **response_kw): + """ + Get a connection from the pool and perform an HTTP request. This is the + lowest level call for making a request, so you'll need to specify all + the raw details. + + .. note:: + + More commonly, it's appropriate to use a convenience method provided + by :class:`.RequestMethods`, such as :meth:`request`. + + .. note:: + + `release_conn` will only behave as expected if + `preload_content=False` because we want to make + `preload_content=False` the default behaviour someday soon without + breaking backwards compatibility. + + :param method: + HTTP request method (such as GET, POST, PUT, etc.) + + :param body: + Data to send in the request body (useful for creating + POST requests, see HTTPConnectionPool.post_url for + more convenience). + + :param headers: + Dictionary of custom headers to send, such as User-Agent, + If-None-Match, etc. If None, pool headers are used. If provided, + these headers completely replace any pool-specific headers. + + :param retries: + Configure the number of retries to allow before raising a + :class:`~urllib3.exceptions.MaxRetryError` exception. + + Pass ``None`` to retry until you receive a response. Pass a + :class:`~urllib3.util.retry.Retry` object for fine-grained control + over different types of retries. + Pass an integer number to retry connection errors that many times, + but no other types of errors. Pass zero to never retry. + + If ``False``, then retries are disabled and any exception is raised + immediately. Also, instead of raising a MaxRetryError on redirects, + the redirect response will be returned. + + :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. + + :param redirect: + If True, automatically handle redirects (status codes 301, 302, + 303, 307, 308). Each redirect counts as a retry. Disabling retries + will disable redirect, too. + + :param assert_same_host: + If ``True``, will make sure that the host of the pool requests is + consistent else will raise HostChangedError. When False, you can + use the pool on an HTTP proxy and request foreign hosts. + + :param timeout: + If specified, overrides the default timeout for this one + request. It may be a float (in seconds) or an instance of + :class:`urllib3.util.Timeout`. + + :param pool_timeout: + If set and the pool is set to block=True, then this method will + block for ``pool_timeout`` seconds and raise EmptyPoolError if no + connection is available within the time period. + + :param release_conn: + If False, then the urlopen call will not release the connection + back into the pool once a response is received (but will release if + you read the entire contents of the response such as when + `preload_content=True`). This is useful if you're not preloading + the response's content immediately. You will need to call + ``r.release_conn()`` on the response ``r`` to return the connection + back into the pool. If None, it takes the value of + ``response_kw.get('preload_content', True)``. + + :param chunked: + If True, urllib3 will send the body using chunked transfer + encoding. Otherwise, urllib3 will send the body using the standard + content-length form. Defaults to False. + + :param int body_pos: + Position to seek to in file-like body in the event of a retry or + redirect. Typically this won't need to be set because urllib3 will + auto-populate the value when needed. + + :param \\**response_kw: + Additional parameters are passed to + :meth:`urllib3.response.HTTPResponse.from_httplib` + """ + if headers is None: + headers = self.headers + + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect, default=self.retries) + + if release_conn is None: + release_conn = response_kw.get('preload_content', True) + + # Check host + if assert_same_host and not self.is_same_host(url): + raise HostChangedError(self, url, retries) + + conn = None + + # Track whether `conn` needs to be released before + # returning/raising/recursing. Update this variable if necessary, and + # leave `release_conn` constant throughout the function. That way, if + # the function recurses, the original value of `release_conn` will be + # passed down into the recursive call, and its value will be respected. + # + # See issue #651 [1] for details. + # + # [1] <https://github.com/shazow/urllib3/issues/651> + release_this_conn = release_conn + + # Merge the proxy headers. Only do this in HTTP. We have to copy the + # headers dict so we can safely change it without those changes being + # reflected in anyone else's copy. + if self.scheme == 'http': + headers = headers.copy() + headers.update(self.proxy_headers) + + # Must keep the exception bound to a separate variable or else Python 3 + # complains about UnboundLocalError. + err = None + + # Keep track of whether we cleanly exited the except block. This + # ensures we do proper cleanup in finally. + clean_exit = False + + # Rewind body position, if needed. Record current position + # for future rewinds in the event of a redirect/retry. + body_pos = set_file_position(body, body_pos) + + try: + # Request a connection from the queue. + timeout_obj = self._get_timeout(timeout) + conn = self._get_conn(timeout=pool_timeout) + + conn.timeout = timeout_obj.connect_timeout + + is_new_proxy_conn = self.proxy is not None and not getattr(conn, 'sock', None) + if is_new_proxy_conn: + self._prepare_proxy(conn) + + # Make the request on the httplib connection object. + httplib_response = self._make_request(conn, method, url, + timeout=timeout_obj, + body=body, headers=headers, + chunked=chunked) + + # If we're going to release the connection in ``finally:``, then + # the response doesn't need to know about the connection. Otherwise + # it will also try to release it and we'll have a double-release + # mess. + response_conn = conn if not release_conn else None + + # Pass method to Response for length checking + response_kw['request_method'] = method + + # Import httplib's response into our own wrapper object + response = self.ResponseCls.from_httplib(httplib_response, + pool=self, + connection=response_conn, + retries=retries, + **response_kw) + + # Everything went great! + clean_exit = True + + except queue.Empty: + # Timed out by queue. + raise EmptyPoolError(self, "No pool connections are available.") + + except (TimeoutError, HTTPException, SocketError, ProtocolError, + BaseSSLError, SSLError, CertificateError) as e: + # Discard the connection for these exceptions. It will be + # replaced during the next _get_conn() call. + clean_exit = False + if isinstance(e, (BaseSSLError, CertificateError)): + e = SSLError(e) + elif isinstance(e, (SocketError, NewConnectionError)) and self.proxy: + e = ProxyError('Cannot connect to proxy.', e) + elif isinstance(e, (SocketError, HTTPException)): + e = ProtocolError('Connection aborted.', e) + + retries = retries.increment(method, url, error=e, _pool=self, + _stacktrace=sys.exc_info()[2]) + retries.sleep() + + # Keep track of the error for the retry warning. + err = e + + finally: + if not clean_exit: + # We hit some kind of exception, handled or otherwise. We need + # to throw the connection away unless explicitly told not to. + # Close the connection, set the variable to None, and make sure + # we put the None back in the pool to avoid leaking it. + conn = conn and conn.close() + release_this_conn = True + + if release_this_conn: + # Put the connection back to be reused. If the connection is + # expired then it will be None, which will get replaced with a + # fresh connection during _get_conn. + self._put_conn(conn) + + if not conn: + # Try again + log.warning("Retrying (%r) after connection " + "broken by '%r': %s", retries, err, url) + return self.urlopen(method, url, body, headers, retries, + redirect, assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, body_pos=body_pos, + **response_kw) + + def drain_and_release_conn(response): + try: + # discard any remaining response body, the connection will be + # released back to the pool once the entire response is read + response.read() + except (TimeoutError, HTTPException, SocketError, ProtocolError, + BaseSSLError, SSLError) as e: + pass + + # Handle redirect? + redirect_location = redirect and response.get_redirect_location() + if redirect_location: + if response.status == 303: + method = 'GET' + + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_redirect: + # Drain and release the connection for this response, since + # we're not returning it to be released manually. + drain_and_release_conn(response) + raise + return response + + # drain and return the connection to the pool before recursing + drain_and_release_conn(response) + + retries.sleep_for_retry(response) + log.debug("Redirecting %s -> %s", url, redirect_location) + return self.urlopen( + method, redirect_location, body, headers, + retries=retries, redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, body_pos=body_pos, + **response_kw) + + # Check if we should retry the HTTP response. + has_retry_after = bool(response.getheader('Retry-After')) + if retries.is_retry(method, response.status, has_retry_after): + try: + retries = retries.increment(method, url, response=response, _pool=self) + except MaxRetryError: + if retries.raise_on_status: + # Drain and release the connection for this response, since + # we're not returning it to be released manually. + drain_and_release_conn(response) + raise + return response + + # drain and return the connection to the pool before recursing + drain_and_release_conn(response) + + retries.sleep(response) + log.debug("Retry: %s", url) + return self.urlopen( + method, url, body, headers, + retries=retries, redirect=redirect, + assert_same_host=assert_same_host, + timeout=timeout, pool_timeout=pool_timeout, + release_conn=release_conn, + body_pos=body_pos, **response_kw) + + return response + + +class HTTPSConnectionPool(HTTPConnectionPool): + """ + Same as :class:`.HTTPConnectionPool`, but HTTPS. + + When Python is compiled with the :mod:`ssl` module, then + :class:`.VerifiedHTTPSConnection` is used, which *can* verify certificates, + instead of :class:`.HTTPSConnection`. + + :class:`.VerifiedHTTPSConnection` uses one of ``assert_fingerprint``, + ``assert_hostname`` and ``host`` in this order to verify connections. + If ``assert_hostname`` is False, no verification is done. + + The ``key_file``, ``cert_file``, ``cert_reqs``, ``ca_certs``, + ``ca_cert_dir``, and ``ssl_version`` are only used if :mod:`ssl` is + available and are fed into :meth:`urllib3.util.ssl_wrap_socket` to upgrade + the connection socket into an SSL socket. + """ + + scheme = 'https' + ConnectionCls = HTTPSConnection + + def __init__(self, host, port=None, + strict=False, timeout=Timeout.DEFAULT_TIMEOUT, maxsize=1, + block=False, headers=None, retries=None, + _proxy=None, _proxy_headers=None, + key_file=None, cert_file=None, cert_reqs=None, + ca_certs=None, ssl_version=None, + assert_hostname=None, assert_fingerprint=None, + ca_cert_dir=None, **conn_kw): + + HTTPConnectionPool.__init__(self, host, port, strict, timeout, maxsize, + block, headers, retries, _proxy, _proxy_headers, + **conn_kw) + + if ca_certs and cert_reqs is None: + cert_reqs = 'CERT_REQUIRED' + + self.key_file = key_file + self.cert_file = cert_file + self.cert_reqs = cert_reqs + self.ca_certs = ca_certs + self.ca_cert_dir = ca_cert_dir + self.ssl_version = ssl_version + self.assert_hostname = assert_hostname + self.assert_fingerprint = assert_fingerprint + + def _prepare_conn(self, conn): + """ + Prepare the ``connection`` for :meth:`urllib3.util.ssl_wrap_socket` + and establish the tunnel if proxy is used. + """ + + if isinstance(conn, VerifiedHTTPSConnection): + conn.set_cert(key_file=self.key_file, + cert_file=self.cert_file, + cert_reqs=self.cert_reqs, + ca_certs=self.ca_certs, + ca_cert_dir=self.ca_cert_dir, + assert_hostname=self.assert_hostname, + assert_fingerprint=self.assert_fingerprint) + conn.ssl_version = self.ssl_version + return conn + + def _prepare_proxy(self, conn): + """ + Establish tunnel connection early, because otherwise httplib + would improperly set Host: header to proxy's IP:port. + """ + # Python 2.7+ + try: + set_tunnel = conn.set_tunnel + except AttributeError: # Platform-specific: Python 2.6 + set_tunnel = conn._set_tunnel + + if sys.version_info <= (2, 6, 4) and not self.proxy_headers: # Python 2.6.4 and older + set_tunnel(self._proxy_host, self.port) + else: + set_tunnel(self._proxy_host, self.port, self.proxy_headers) + + conn.connect() + + def _new_conn(self): + """ + Return a fresh :class:`httplib.HTTPSConnection`. + """ + self.num_connections += 1 + log.debug("Starting new HTTPS connection (%d): %s:%s", + self.num_connections, self.host, self.port or "443") + + if not self.ConnectionCls or self.ConnectionCls is DummyConnection: + raise SSLError("Can't connect to HTTPS URL because the SSL " + "module is not available.") + + actual_host = self.host + actual_port = self.port + if self.proxy is not None: + actual_host = self.proxy.host + actual_port = self.proxy.port + + conn = self.ConnectionCls(host=actual_host, port=actual_port, + timeout=self.timeout.connect_timeout, + strict=self.strict, **self.conn_kw) + + return self._prepare_conn(conn) + + def _validate_conn(self, conn): + """ + Called right before a request is made, after the socket is created. + """ + super(HTTPSConnectionPool, self)._validate_conn(conn) + + # Force connect early to allow us to validate the connection. + if not getattr(conn, 'sock', None): # AppEngine might not have `.sock` + conn.connect() + + if not conn.is_verified: + warnings.warn(( + 'Unverified HTTPS request is being made. ' + 'Adding certificate verification is strongly advised. See: ' + 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' + '#ssl-warnings'), + InsecureRequestWarning) + + +def connection_from_url(url, **kw): + """ + Given a url, return an :class:`.ConnectionPool` instance of its host. + + This is a shortcut for not having to parse out the scheme, host, and port + of the url before creating an :class:`.ConnectionPool` instance. + + :param url: + Absolute URL string that must include the scheme. Port is optional. + + :param \\**kw: + Passes additional parameters to the constructor of the appropriate + :class:`.ConnectionPool`. Useful for specifying things like + timeout, maxsize, headers, etc. + + Example:: + + >>> conn = connection_from_url('http://google.com/') + >>> r = conn.request('GET', '/') + """ + scheme, host, port = get_host(url) + port = port or port_by_scheme.get(scheme, 80) + if scheme == 'https': + return HTTPSConnectionPool(host, port=port, **kw) + else: + return HTTPConnectionPool(host, port=port, **kw) + + +def _ipv6_host(host, scheme): + """ + Process IPv6 address literals + """ + + # httplib doesn't like it when we include brackets in IPv6 addresses + # Specifically, if we include brackets but also pass the port then + # httplib crazily doubles up the square brackets on the Host header. + # Instead, we need to make sure we never pass ``None`` as the port. + # However, for backward compatibility reasons we can't actually + # *assert* that. See http://bugs.python.org/issue28539 + # + # Also if an IPv6 address literal has a zone identifier, the + # percent sign might be URIencoded, convert it back into ASCII + if host.startswith('[') and host.endswith(']'): + host = host.replace('%25', '%').strip('[]') + if scheme in NORMALIZABLE_SCHEMES: + host = host.lower() + return host diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py new file mode 100644 index 0000000..bcf41c0 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py @@ -0,0 +1,593 @@ +""" +This module uses ctypes to bind a whole bunch of functions and constants from +SecureTransport. The goal here is to provide the low-level API to +SecureTransport. These are essentially the C-level functions and constants, and +they're pretty gross to work with. + +This code is a bastardised version of the code found in Will Bond's oscrypto +library. An enormous debt is owed to him for blazing this trail for us. For +that reason, this code should be considered to be covered both by urllib3's +license and by oscrypto's: + + Copyright (c) 2015-2016 Will Bond <will@wbond.net> + + 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. +""" +from __future__ import absolute_import + +import platform +from ctypes.util import find_library +from ctypes import ( + c_void_p, c_int32, c_char_p, c_size_t, c_byte, c_uint32, c_ulong, c_long, + c_bool +) +from ctypes import CDLL, POINTER, CFUNCTYPE + + +security_path = find_library('Security') +if not security_path: + raise ImportError('The library Security could not be found') + + +core_foundation_path = find_library('CoreFoundation') +if not core_foundation_path: + raise ImportError('The library CoreFoundation could not be found') + + +version = platform.mac_ver()[0] +version_info = tuple(map(int, version.split('.'))) +if version_info < (10, 8): + raise OSError( + 'Only OS X 10.8 and newer are supported, not %s.%s' % ( + version_info[0], version_info[1] + ) + ) + +Security = CDLL(security_path, use_errno=True) +CoreFoundation = CDLL(core_foundation_path, use_errno=True) + +Boolean = c_bool +CFIndex = c_long +CFStringEncoding = c_uint32 +CFData = c_void_p +CFString = c_void_p +CFArray = c_void_p +CFMutableArray = c_void_p +CFDictionary = c_void_p +CFError = c_void_p +CFType = c_void_p +CFTypeID = c_ulong + +CFTypeRef = POINTER(CFType) +CFAllocatorRef = c_void_p + +OSStatus = c_int32 + +CFDataRef = POINTER(CFData) +CFStringRef = POINTER(CFString) +CFArrayRef = POINTER(CFArray) +CFMutableArrayRef = POINTER(CFMutableArray) +CFDictionaryRef = POINTER(CFDictionary) +CFArrayCallBacks = c_void_p +CFDictionaryKeyCallBacks = c_void_p +CFDictionaryValueCallBacks = c_void_p + +SecCertificateRef = POINTER(c_void_p) +SecExternalFormat = c_uint32 +SecExternalItemType = c_uint32 +SecIdentityRef = POINTER(c_void_p) +SecItemImportExportFlags = c_uint32 +SecItemImportExportKeyParameters = c_void_p +SecKeychainRef = POINTER(c_void_p) +SSLProtocol = c_uint32 +SSLCipherSuite = c_uint32 +SSLContextRef = POINTER(c_void_p) +SecTrustRef = POINTER(c_void_p) +SSLConnectionRef = c_uint32 +SecTrustResultType = c_uint32 +SecTrustOptionFlags = c_uint32 +SSLProtocolSide = c_uint32 +SSLConnectionType = c_uint32 +SSLSessionOption = c_uint32 + + +try: + Security.SecItemImport.argtypes = [ + CFDataRef, + CFStringRef, + POINTER(SecExternalFormat), + POINTER(SecExternalItemType), + SecItemImportExportFlags, + POINTER(SecItemImportExportKeyParameters), + SecKeychainRef, + POINTER(CFArrayRef), + ] + Security.SecItemImport.restype = OSStatus + + Security.SecCertificateGetTypeID.argtypes = [] + Security.SecCertificateGetTypeID.restype = CFTypeID + + Security.SecIdentityGetTypeID.argtypes = [] + Security.SecIdentityGetTypeID.restype = CFTypeID + + Security.SecKeyGetTypeID.argtypes = [] + Security.SecKeyGetTypeID.restype = CFTypeID + + Security.SecCertificateCreateWithData.argtypes = [ + CFAllocatorRef, + CFDataRef + ] + Security.SecCertificateCreateWithData.restype = SecCertificateRef + + Security.SecCertificateCopyData.argtypes = [ + SecCertificateRef + ] + Security.SecCertificateCopyData.restype = CFDataRef + + Security.SecCopyErrorMessageString.argtypes = [ + OSStatus, + c_void_p + ] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SecIdentityCreateWithCertificate.argtypes = [ + CFTypeRef, + SecCertificateRef, + POINTER(SecIdentityRef) + ] + Security.SecIdentityCreateWithCertificate.restype = OSStatus + + Security.SecKeychainCreate.argtypes = [ + c_char_p, + c_uint32, + c_void_p, + Boolean, + c_void_p, + POINTER(SecKeychainRef) + ] + Security.SecKeychainCreate.restype = OSStatus + + Security.SecKeychainDelete.argtypes = [ + SecKeychainRef + ] + Security.SecKeychainDelete.restype = OSStatus + + Security.SecPKCS12Import.argtypes = [ + CFDataRef, + CFDictionaryRef, + POINTER(CFArrayRef) + ] + Security.SecPKCS12Import.restype = OSStatus + + SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, c_void_p, POINTER(c_size_t)) + SSLWriteFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t)) + + Security.SSLSetIOFuncs.argtypes = [ + SSLContextRef, + SSLReadFunc, + SSLWriteFunc + ] + Security.SSLSetIOFuncs.restype = OSStatus + + Security.SSLSetPeerID.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t + ] + Security.SSLSetPeerID.restype = OSStatus + + Security.SSLSetCertificate.argtypes = [ + SSLContextRef, + CFArrayRef + ] + Security.SSLSetCertificate.restype = OSStatus + + Security.SSLSetCertificateAuthorities.argtypes = [ + SSLContextRef, + CFTypeRef, + Boolean + ] + Security.SSLSetCertificateAuthorities.restype = OSStatus + + Security.SSLSetConnection.argtypes = [ + SSLContextRef, + SSLConnectionRef + ] + Security.SSLSetConnection.restype = OSStatus + + Security.SSLSetPeerDomainName.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t + ] + Security.SSLSetPeerDomainName.restype = OSStatus + + Security.SSLHandshake.argtypes = [ + SSLContextRef + ] + Security.SSLHandshake.restype = OSStatus + + Security.SSLRead.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t, + POINTER(c_size_t) + ] + Security.SSLRead.restype = OSStatus + + Security.SSLWrite.argtypes = [ + SSLContextRef, + c_char_p, + c_size_t, + POINTER(c_size_t) + ] + Security.SSLWrite.restype = OSStatus + + Security.SSLClose.argtypes = [ + SSLContextRef + ] + Security.SSLClose.restype = OSStatus + + Security.SSLGetNumberSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetNumberSupportedCiphers.restype = OSStatus + + Security.SSLGetSupportedCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t) + ] + Security.SSLGetSupportedCiphers.restype = OSStatus + + Security.SSLSetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + c_size_t + ] + Security.SSLSetEnabledCiphers.restype = OSStatus + + Security.SSLGetNumberEnabledCiphers.argtype = [ + SSLContextRef, + POINTER(c_size_t) + ] + Security.SSLGetNumberEnabledCiphers.restype = OSStatus + + Security.SSLGetEnabledCiphers.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite), + POINTER(c_size_t) + ] + Security.SSLGetEnabledCiphers.restype = OSStatus + + Security.SSLGetNegotiatedCipher.argtypes = [ + SSLContextRef, + POINTER(SSLCipherSuite) + ] + Security.SSLGetNegotiatedCipher.restype = OSStatus + + Security.SSLGetNegotiatedProtocolVersion.argtypes = [ + SSLContextRef, + POINTER(SSLProtocol) + ] + Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus + + Security.SSLCopyPeerTrust.argtypes = [ + SSLContextRef, + POINTER(SecTrustRef) + ] + Security.SSLCopyPeerTrust.restype = OSStatus + + Security.SecTrustSetAnchorCertificates.argtypes = [ + SecTrustRef, + CFArrayRef + ] + Security.SecTrustSetAnchorCertificates.restype = OSStatus + + Security.SecTrustSetAnchorCertificatesOnly.argstypes = [ + SecTrustRef, + Boolean + ] + Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus + + Security.SecTrustEvaluate.argtypes = [ + SecTrustRef, + POINTER(SecTrustResultType) + ] + Security.SecTrustEvaluate.restype = OSStatus + + Security.SecTrustGetCertificateCount.argtypes = [ + SecTrustRef + ] + Security.SecTrustGetCertificateCount.restype = CFIndex + + Security.SecTrustGetCertificateAtIndex.argtypes = [ + SecTrustRef, + CFIndex + ] + Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef + + Security.SSLCreateContext.argtypes = [ + CFAllocatorRef, + SSLProtocolSide, + SSLConnectionType + ] + Security.SSLCreateContext.restype = SSLContextRef + + Security.SSLSetSessionOption.argtypes = [ + SSLContextRef, + SSLSessionOption, + Boolean + ] + Security.SSLSetSessionOption.restype = OSStatus + + Security.SSLSetProtocolVersionMin.argtypes = [ + SSLContextRef, + SSLProtocol + ] + Security.SSLSetProtocolVersionMin.restype = OSStatus + + Security.SSLSetProtocolVersionMax.argtypes = [ + SSLContextRef, + SSLProtocol + ] + Security.SSLSetProtocolVersionMax.restype = OSStatus + + Security.SecCopyErrorMessageString.argtypes = [ + OSStatus, + c_void_p + ] + Security.SecCopyErrorMessageString.restype = CFStringRef + + Security.SSLReadFunc = SSLReadFunc + Security.SSLWriteFunc = SSLWriteFunc + Security.SSLContextRef = SSLContextRef + Security.SSLProtocol = SSLProtocol + Security.SSLCipherSuite = SSLCipherSuite + Security.SecIdentityRef = SecIdentityRef + Security.SecKeychainRef = SecKeychainRef + Security.SecTrustRef = SecTrustRef + Security.SecTrustResultType = SecTrustResultType + Security.SecExternalFormat = SecExternalFormat + Security.OSStatus = OSStatus + + Security.kSecImportExportPassphrase = CFStringRef.in_dll( + Security, 'kSecImportExportPassphrase' + ) + Security.kSecImportItemIdentity = CFStringRef.in_dll( + Security, 'kSecImportItemIdentity' + ) + + # CoreFoundation time! + CoreFoundation.CFRetain.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFRetain.restype = CFTypeRef + + CoreFoundation.CFRelease.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFRelease.restype = None + + CoreFoundation.CFGetTypeID.argtypes = [ + CFTypeRef + ] + CoreFoundation.CFGetTypeID.restype = CFTypeID + + CoreFoundation.CFStringCreateWithCString.argtypes = [ + CFAllocatorRef, + c_char_p, + CFStringEncoding + ] + CoreFoundation.CFStringCreateWithCString.restype = CFStringRef + + CoreFoundation.CFStringGetCStringPtr.argtypes = [ + CFStringRef, + CFStringEncoding + ] + CoreFoundation.CFStringGetCStringPtr.restype = c_char_p + + CoreFoundation.CFStringGetCString.argtypes = [ + CFStringRef, + c_char_p, + CFIndex, + CFStringEncoding + ] + CoreFoundation.CFStringGetCString.restype = c_bool + + CoreFoundation.CFDataCreate.argtypes = [ + CFAllocatorRef, + c_char_p, + CFIndex + ] + CoreFoundation.CFDataCreate.restype = CFDataRef + + CoreFoundation.CFDataGetLength.argtypes = [ + CFDataRef + ] + CoreFoundation.CFDataGetLength.restype = CFIndex + + CoreFoundation.CFDataGetBytePtr.argtypes = [ + CFDataRef + ] + CoreFoundation.CFDataGetBytePtr.restype = c_void_p + + CoreFoundation.CFDictionaryCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + POINTER(CFTypeRef), + CFIndex, + CFDictionaryKeyCallBacks, + CFDictionaryValueCallBacks + ] + CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef + + CoreFoundation.CFDictionaryGetValue.argtypes = [ + CFDictionaryRef, + CFTypeRef + ] + CoreFoundation.CFDictionaryGetValue.restype = CFTypeRef + + CoreFoundation.CFArrayCreate.argtypes = [ + CFAllocatorRef, + POINTER(CFTypeRef), + CFIndex, + CFArrayCallBacks, + ] + CoreFoundation.CFArrayCreate.restype = CFArrayRef + + CoreFoundation.CFArrayCreateMutable.argtypes = [ + CFAllocatorRef, + CFIndex, + CFArrayCallBacks + ] + CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef + + CoreFoundation.CFArrayAppendValue.argtypes = [ + CFMutableArrayRef, + c_void_p + ] + CoreFoundation.CFArrayAppendValue.restype = None + + CoreFoundation.CFArrayGetCount.argtypes = [ + CFArrayRef + ] + CoreFoundation.CFArrayGetCount.restype = CFIndex + + CoreFoundation.CFArrayGetValueAtIndex.argtypes = [ + CFArrayRef, + CFIndex + ] + CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p + + CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( + CoreFoundation, 'kCFAllocatorDefault' + ) + CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll(CoreFoundation, 'kCFTypeArrayCallBacks') + CoreFoundation.kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll( + CoreFoundation, 'kCFTypeDictionaryKeyCallBacks' + ) + CoreFoundation.kCFTypeDictionaryValueCallBacks = c_void_p.in_dll( + CoreFoundation, 'kCFTypeDictionaryValueCallBacks' + ) + + CoreFoundation.CFTypeRef = CFTypeRef + CoreFoundation.CFArrayRef = CFArrayRef + CoreFoundation.CFStringRef = CFStringRef + CoreFoundation.CFDictionaryRef = CFDictionaryRef + +except (AttributeError): + raise ImportError('Error initializing ctypes') + + +class CFConst(object): + """ + A class object that acts as essentially a namespace for CoreFoundation + constants. + """ + kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) + + +class SecurityConst(object): + """ + A class object that acts as essentially a namespace for Security constants. + """ + kSSLSessionOptionBreakOnServerAuth = 0 + + kSSLProtocol2 = 1 + kSSLProtocol3 = 2 + kTLSProtocol1 = 4 + kTLSProtocol11 = 7 + kTLSProtocol12 = 8 + + kSSLClientSide = 1 + kSSLStreamType = 0 + + kSecFormatPEMSequence = 10 + + kSecTrustResultInvalid = 0 + kSecTrustResultProceed = 1 + # This gap is present on purpose: this was kSecTrustResultConfirm, which + # is deprecated. + kSecTrustResultDeny = 3 + kSecTrustResultUnspecified = 4 + kSecTrustResultRecoverableTrustFailure = 5 + kSecTrustResultFatalTrustFailure = 6 + kSecTrustResultOtherError = 7 + + errSSLProtocol = -9800 + errSSLWouldBlock = -9803 + errSSLClosedGraceful = -9805 + errSSLClosedNoNotify = -9816 + errSSLClosedAbort = -9806 + + errSSLXCertChainInvalid = -9807 + errSSLCrypto = -9809 + errSSLInternal = -9810 + errSSLCertExpired = -9814 + errSSLCertNotYetValid = -9815 + errSSLUnknownRootCert = -9812 + errSSLNoRootCert = -9813 + errSSLHostNameMismatch = -9843 + errSSLPeerHandshakeFail = -9824 + errSSLPeerUserCancelled = -9839 + errSSLWeakPeerEphemeralDHKey = -9850 + errSSLServerAuthCompleted = -9841 + errSSLRecordOverflow = -9847 + + errSecVerifyFailed = -67808 + errSecNoTrustSettings = -25263 + errSecItemNotFound = -25300 + errSecInvalidTrustSettings = -25262 + + # Cipher suites. We only pick the ones our default cipher string allows. + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030 + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F + TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3 + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F + TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2 + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024 + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014 + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B + TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A + TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 + TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027 + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009 + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 + TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040 + TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 + TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032 + TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C + TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D + TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C + TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 + TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F + TLS_AES_128_GCM_SHA256 = 0x1301 + TLS_AES_256_GCM_SHA384 = 0x1302 + TLS_CHACHA20_POLY1305_SHA256 = 0x1303 diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py new file mode 100644 index 0000000..b13cd9e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py @@ -0,0 +1,346 @@ +""" +Low-level helpers for the SecureTransport bindings. + +These are Python functions that are not directly related to the high-level APIs +but are necessary to get them to work. They include a whole bunch of low-level +CoreFoundation messing about and memory management. The concerns in this module +are almost entirely about trying to avoid memory leaks and providing +appropriate and useful assistance to the higher-level code. +""" +import base64 +import ctypes +import itertools +import re +import os +import ssl +import tempfile + +from .bindings import Security, CoreFoundation, CFConst + + +# This regular expression is used to grab PEM data out of a PEM bundle. +_PEM_CERTS_RE = re.compile( + b"-----BEGIN CERTIFICATE-----\n(.*?)\n-----END CERTIFICATE-----", re.DOTALL +) + + +def _cf_data_from_bytes(bytestring): + """ + Given a bytestring, create a CFData object from it. This CFData object must + be CFReleased by the caller. + """ + return CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, bytestring, len(bytestring) + ) + + +def _cf_dictionary_from_tuples(tuples): + """ + Given a list of Python tuples, create an associated CFDictionary. + """ + dictionary_size = len(tuples) + + # We need to get the dictionary keys and values out in the same order. + keys = (t[0] for t in tuples) + values = (t[1] for t in tuples) + cf_keys = (CoreFoundation.CFTypeRef * dictionary_size)(*keys) + cf_values = (CoreFoundation.CFTypeRef * dictionary_size)(*values) + + return CoreFoundation.CFDictionaryCreate( + CoreFoundation.kCFAllocatorDefault, + cf_keys, + cf_values, + dictionary_size, + CoreFoundation.kCFTypeDictionaryKeyCallBacks, + CoreFoundation.kCFTypeDictionaryValueCallBacks, + ) + + +def _cf_string_to_unicode(value): + """ + Creates a Unicode string from a CFString object. Used entirely for error + reporting. + + Yes, it annoys me quite a lot that this function is this complex. + """ + value_as_void_p = ctypes.cast(value, ctypes.POINTER(ctypes.c_void_p)) + + string = CoreFoundation.CFStringGetCStringPtr( + value_as_void_p, + CFConst.kCFStringEncodingUTF8 + ) + if string is None: + buffer = ctypes.create_string_buffer(1024) + result = CoreFoundation.CFStringGetCString( + value_as_void_p, + buffer, + 1024, + CFConst.kCFStringEncodingUTF8 + ) + if not result: + raise OSError('Error copying C string from CFStringRef') + string = buffer.value + if string is not None: + string = string.decode('utf-8') + return string + + +def _assert_no_error(error, exception_class=None): + """ + Checks the return code and throws an exception if there is an error to + report + """ + if error == 0: + return + + cf_error_string = Security.SecCopyErrorMessageString(error, None) + output = _cf_string_to_unicode(cf_error_string) + CoreFoundation.CFRelease(cf_error_string) + + if output is None or output == u'': + output = u'OSStatus %s' % error + + if exception_class is None: + exception_class = ssl.SSLError + + raise exception_class(output) + + +def _cert_array_from_pem(pem_bundle): + """ + Given a bundle of certs in PEM format, turns them into a CFArray of certs + that can be used to validate a cert chain. + """ + # Normalize the PEM bundle's line endings. + pem_bundle = pem_bundle.replace(b"\r\n", b"\n") + + der_certs = [ + base64.b64decode(match.group(1)) + for match in _PEM_CERTS_RE.finditer(pem_bundle) + ] + if not der_certs: + raise ssl.SSLError("No root certificates specified") + + cert_array = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks) + ) + if not cert_array: + raise ssl.SSLError("Unable to allocate memory!") + + try: + for der_bytes in der_certs: + certdata = _cf_data_from_bytes(der_bytes) + if not certdata: + raise ssl.SSLError("Unable to allocate memory!") + cert = Security.SecCertificateCreateWithData( + CoreFoundation.kCFAllocatorDefault, certdata + ) + CoreFoundation.CFRelease(certdata) + if not cert: + raise ssl.SSLError("Unable to build cert object!") + + CoreFoundation.CFArrayAppendValue(cert_array, cert) + CoreFoundation.CFRelease(cert) + except Exception: + # We need to free the array before the exception bubbles further. + # We only want to do that if an error occurs: otherwise, the caller + # should free. + CoreFoundation.CFRelease(cert_array) + + return cert_array + + +def _is_cert(item): + """ + Returns True if a given CFTypeRef is a certificate. + """ + expected = Security.SecCertificateGetTypeID() + return CoreFoundation.CFGetTypeID(item) == expected + + +def _is_identity(item): + """ + Returns True if a given CFTypeRef is an identity. + """ + expected = Security.SecIdentityGetTypeID() + return CoreFoundation.CFGetTypeID(item) == expected + + +def _temporary_keychain(): + """ + This function creates a temporary Mac keychain that we can use to work with + credentials. This keychain uses a one-time password and a temporary file to + store the data. We expect to have one keychain per socket. The returned + SecKeychainRef must be freed by the caller, including calling + SecKeychainDelete. + + Returns a tuple of the SecKeychainRef and the path to the temporary + directory that contains it. + """ + # Unfortunately, SecKeychainCreate requires a path to a keychain. This + # means we cannot use mkstemp to use a generic temporary file. Instead, + # we're going to create a temporary directory and a filename to use there. + # This filename will be 8 random bytes expanded into base64. We also need + # some random bytes to password-protect the keychain we're creating, so we + # ask for 40 random bytes. + random_bytes = os.urandom(40) + filename = base64.b16encode(random_bytes[:8]).decode('utf-8') + password = base64.b16encode(random_bytes[8:]) # Must be valid UTF-8 + tempdirectory = tempfile.mkdtemp() + + keychain_path = os.path.join(tempdirectory, filename).encode('utf-8') + + # We now want to create the keychain itself. + keychain = Security.SecKeychainRef() + status = Security.SecKeychainCreate( + keychain_path, + len(password), + password, + False, + None, + ctypes.byref(keychain) + ) + _assert_no_error(status) + + # Having created the keychain, we want to pass it off to the caller. + return keychain, tempdirectory + + +def _load_items_from_file(keychain, path): + """ + Given a single file, loads all the trust objects from it into arrays and + the keychain. + Returns a tuple of lists: the first list is a list of identities, the + second a list of certs. + """ + certificates = [] + identities = [] + result_array = None + + with open(path, 'rb') as f: + raw_filedata = f.read() + + try: + filedata = CoreFoundation.CFDataCreate( + CoreFoundation.kCFAllocatorDefault, + raw_filedata, + len(raw_filedata) + ) + result_array = CoreFoundation.CFArrayRef() + result = Security.SecItemImport( + filedata, # cert data + None, # Filename, leaving it out for now + None, # What the type of the file is, we don't care + None, # what's in the file, we don't care + 0, # import flags + None, # key params, can include passphrase in the future + keychain, # The keychain to insert into + ctypes.byref(result_array) # Results + ) + _assert_no_error(result) + + # A CFArray is not very useful to us as an intermediary + # representation, so we are going to extract the objects we want + # and then free the array. We don't need to keep hold of keys: the + # keychain already has them! + result_count = CoreFoundation.CFArrayGetCount(result_array) + for index in range(result_count): + item = CoreFoundation.CFArrayGetValueAtIndex( + result_array, index + ) + item = ctypes.cast(item, CoreFoundation.CFTypeRef) + + if _is_cert(item): + CoreFoundation.CFRetain(item) + certificates.append(item) + elif _is_identity(item): + CoreFoundation.CFRetain(item) + identities.append(item) + finally: + if result_array: + CoreFoundation.CFRelease(result_array) + + CoreFoundation.CFRelease(filedata) + + return (identities, certificates) + + +def _load_client_cert_chain(keychain, *paths): + """ + Load certificates and maybe keys from a number of files. Has the end goal + of returning a CFArray containing one SecIdentityRef, and then zero or more + SecCertificateRef objects, suitable for use as a client certificate trust + chain. + """ + # Ok, the strategy. + # + # This relies on knowing that macOS will not give you a SecIdentityRef + # unless you have imported a key into a keychain. This is a somewhat + # artificial limitation of macOS (for example, it doesn't necessarily + # affect iOS), but there is nothing inside Security.framework that lets you + # get a SecIdentityRef without having a key in a keychain. + # + # So the policy here is we take all the files and iterate them in order. + # Each one will use SecItemImport to have one or more objects loaded from + # it. We will also point at a keychain that macOS can use to work with the + # private key. + # + # Once we have all the objects, we'll check what we actually have. If we + # already have a SecIdentityRef in hand, fab: we'll use that. Otherwise, + # we'll take the first certificate (which we assume to be our leaf) and + # ask the keychain to give us a SecIdentityRef with that cert's associated + # key. + # + # We'll then return a CFArray containing the trust chain: one + # SecIdentityRef and then zero-or-more SecCertificateRef objects. The + # responsibility for freeing this CFArray will be with the caller. This + # CFArray must remain alive for the entire connection, so in practice it + # will be stored with a single SSLSocket, along with the reference to the + # keychain. + certificates = [] + identities = [] + + # Filter out bad paths. + paths = (path for path in paths if path) + + try: + for file_path in paths: + new_identities, new_certs = _load_items_from_file( + keychain, file_path + ) + identities.extend(new_identities) + certificates.extend(new_certs) + + # Ok, we have everything. The question is: do we have an identity? If + # not, we want to grab one from the first cert we have. + if not identities: + new_identity = Security.SecIdentityRef() + status = Security.SecIdentityCreateWithCertificate( + keychain, + certificates[0], + ctypes.byref(new_identity) + ) + _assert_no_error(status) + identities.append(new_identity) + + # We now want to release the original certificate, as we no longer + # need it. + CoreFoundation.CFRelease(certificates.pop(0)) + + # We now need to build a new CFArray that holds the trust chain. + trust_chain = CoreFoundation.CFArrayCreateMutable( + CoreFoundation.kCFAllocatorDefault, + 0, + ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), + ) + for item in itertools.chain(identities, certificates): + # ArrayAppendValue does a CFRetain on the item. That's fine, + # because the finally block will release our other refs to them. + CoreFoundation.CFArrayAppendValue(trust_chain, item) + + return trust_chain + finally: + for obj in itertools.chain(identities, certificates): + CoreFoundation.CFRelease(obj) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py new file mode 100644 index 0000000..59f2a61 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py @@ -0,0 +1,305 @@ +""" +This module provides a pool manager that uses Google App Engine's +`URLFetch Service <https://cloud.google.com/appengine/docs/python/urlfetch>`_. + +Example usage:: + + from pip._vendor.urllib3 import PoolManager + from pip._vendor.urllib3.contrib.appengine import AppEngineManager, is_appengine_sandbox + + if is_appengine_sandbox(): + # AppEngineManager uses AppEngine's URLFetch API behind the scenes + http = AppEngineManager() + else: + # PoolManager uses a socket-level API behind the scenes + http = PoolManager() + + r = http.request('GET', 'https://google.com/') + +There are `limitations <https://cloud.google.com/appengine/docs/python/\ +urlfetch/#Python_Quotas_and_limits>`_ to the URLFetch service and it may not be +the best choice for your application. There are three options for using +urllib3 on Google App Engine: + +1. You can use :class:`AppEngineManager` with URLFetch. URLFetch is + cost-effective in many circumstances as long as your usage is within the + limitations. +2. You can use a normal :class:`~urllib3.PoolManager` by enabling sockets. + Sockets also have `limitations and restrictions + <https://cloud.google.com/appengine/docs/python/sockets/\ + #limitations-and-restrictions>`_ and have a lower free quota than URLFetch. + To use sockets, be sure to specify the following in your ``app.yaml``:: + + env_variables: + GAE_USE_SOCKETS_HTTPLIB : 'true' + +3. If you are using `App Engine Flexible +<https://cloud.google.com/appengine/docs/flexible/>`_, you can use the standard +:class:`PoolManager` without any configuration or special environment variables. +""" + +from __future__ import absolute_import +import logging +import os +import warnings +from ..packages.six.moves.urllib.parse import urljoin + +from ..exceptions import ( + HTTPError, + HTTPWarning, + MaxRetryError, + ProtocolError, + TimeoutError, + SSLError +) + +from ..packages.six import BytesIO +from ..request import RequestMethods +from ..response import HTTPResponse +from ..util.timeout import Timeout +from ..util.retry import Retry + +try: + from google.appengine.api import urlfetch +except ImportError: + urlfetch = None + + +log = logging.getLogger(__name__) + + +class AppEnginePlatformWarning(HTTPWarning): + pass + + +class AppEnginePlatformError(HTTPError): + pass + + +class AppEngineManager(RequestMethods): + """ + Connection manager for Google App Engine sandbox applications. + + This manager uses the URLFetch service directly instead of using the + emulated httplib, and is subject to URLFetch limitations as described in + the App Engine documentation `here + <https://cloud.google.com/appengine/docs/python/urlfetch>`_. + + Notably it will raise an :class:`AppEnginePlatformError` if: + * URLFetch is not available. + * If you attempt to use this on App Engine Flexible, as full socket + support is available. + * If a request size is more than 10 megabytes. + * If a response size is more than 32 megabtyes. + * If you use an unsupported request method such as OPTIONS. + + Beyond those cases, it will raise normal urllib3 errors. + """ + + def __init__(self, headers=None, retries=None, validate_certificate=True, + urlfetch_retries=True): + if not urlfetch: + raise AppEnginePlatformError( + "URLFetch is not available in this environment.") + + if is_prod_appengine_mvms(): + raise AppEnginePlatformError( + "Use normal urllib3.PoolManager instead of AppEngineManager" + "on Managed VMs, as using URLFetch is not necessary in " + "this environment.") + + warnings.warn( + "urllib3 is using URLFetch on Google App Engine sandbox instead " + "of sockets. To use sockets directly instead of URLFetch see " + "https://urllib3.readthedocs.io/en/latest/reference/urllib3.contrib.html.", + AppEnginePlatformWarning) + + RequestMethods.__init__(self, headers) + self.validate_certificate = validate_certificate + self.urlfetch_retries = urlfetch_retries + + self.retries = retries or Retry.DEFAULT + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + # Return False to re-raise any potential exceptions + return False + + def urlopen(self, method, url, body=None, headers=None, + retries=None, redirect=True, timeout=Timeout.DEFAULT_TIMEOUT, + **response_kw): + + retries = self._get_retries(retries, redirect) + + try: + follow_redirects = ( + redirect and + retries.redirect != 0 and + retries.total) + response = urlfetch.fetch( + url, + payload=body, + method=method, + headers=headers or {}, + allow_truncated=False, + follow_redirects=self.urlfetch_retries and follow_redirects, + deadline=self._get_absolute_timeout(timeout), + validate_certificate=self.validate_certificate, + ) + except urlfetch.DeadlineExceededError as e: + raise TimeoutError(self, e) + + except urlfetch.InvalidURLError as e: + if 'too large' in str(e): + raise AppEnginePlatformError( + "URLFetch request too large, URLFetch only " + "supports requests up to 10mb in size.", e) + raise ProtocolError(e) + + except urlfetch.DownloadError as e: + if 'Too many redirects' in str(e): + raise MaxRetryError(self, url, reason=e) + raise ProtocolError(e) + + except urlfetch.ResponseTooLargeError as e: + raise AppEnginePlatformError( + "URLFetch response too large, URLFetch only supports" + "responses up to 32mb in size.", e) + + except urlfetch.SSLCertificateError as e: + raise SSLError(e) + + except urlfetch.InvalidMethodError as e: + raise AppEnginePlatformError( + "URLFetch does not support method: %s" % method, e) + + http_response = self._urlfetch_response_to_http_response( + response, retries=retries, **response_kw) + + # Handle redirect? + redirect_location = redirect and http_response.get_redirect_location() + if redirect_location: + # Check for redirect response + if (self.urlfetch_retries and retries.raise_on_redirect): + raise MaxRetryError(self, url, "too many redirects") + else: + if http_response.status == 303: + method = 'GET' + + try: + retries = retries.increment(method, url, response=http_response, _pool=self) + except MaxRetryError: + if retries.raise_on_redirect: + raise MaxRetryError(self, url, "too many redirects") + return http_response + + retries.sleep_for_retry(http_response) + log.debug("Redirecting %s -> %s", url, redirect_location) + redirect_url = urljoin(url, redirect_location) + return self.urlopen( + method, redirect_url, body, headers, + retries=retries, redirect=redirect, + timeout=timeout, **response_kw) + + # Check if we should retry the HTTP response. + has_retry_after = bool(http_response.getheader('Retry-After')) + if retries.is_retry(method, http_response.status, has_retry_after): + retries = retries.increment( + method, url, response=http_response, _pool=self) + log.debug("Retry: %s", url) + retries.sleep(http_response) + return self.urlopen( + method, url, + body=body, headers=headers, + retries=retries, redirect=redirect, + timeout=timeout, **response_kw) + + return http_response + + def _urlfetch_response_to_http_response(self, urlfetch_resp, **response_kw): + + if is_prod_appengine(): + # Production GAE handles deflate encoding automatically, but does + # not remove the encoding header. + content_encoding = urlfetch_resp.headers.get('content-encoding') + + if content_encoding == 'deflate': + del urlfetch_resp.headers['content-encoding'] + + transfer_encoding = urlfetch_resp.headers.get('transfer-encoding') + # We have a full response's content, + # so let's make sure we don't report ourselves as chunked data. + if transfer_encoding == 'chunked': + encodings = transfer_encoding.split(",") + encodings.remove('chunked') + urlfetch_resp.headers['transfer-encoding'] = ','.join(encodings) + + original_response = HTTPResponse( + # In order for decoding to work, we must present the content as + # a file-like object. + body=BytesIO(urlfetch_resp.content), + msg=urlfetch_resp.header_msg, + headers=urlfetch_resp.headers, + status=urlfetch_resp.status_code, + **response_kw + ) + + return HTTPResponse( + body=BytesIO(urlfetch_resp.content), + headers=urlfetch_resp.headers, + status=urlfetch_resp.status_code, + original_response=original_response, + **response_kw + ) + + def _get_absolute_timeout(self, timeout): + if timeout is Timeout.DEFAULT_TIMEOUT: + return None # Defer to URLFetch's default. + if isinstance(timeout, Timeout): + if timeout._read is not None or timeout._connect is not None: + warnings.warn( + "URLFetch does not support granular timeout settings, " + "reverting to total or default URLFetch timeout.", + AppEnginePlatformWarning) + return timeout.total + return timeout + + def _get_retries(self, retries, redirect): + if not isinstance(retries, Retry): + retries = Retry.from_int( + retries, redirect=redirect, default=self.retries) + + if retries.connect or retries.read or retries.redirect: + warnings.warn( + "URLFetch only supports total retries and does not " + "recognize connect, read, or redirect retry parameters.", + AppEnginePlatformWarning) + + return retries + + +def is_appengine(): + return (is_local_appengine() or + is_prod_appengine() or + is_prod_appengine_mvms()) + + +def is_appengine_sandbox(): + return is_appengine() and not is_prod_appengine_mvms() + + +def is_local_appengine(): + return ('APPENGINE_RUNTIME' in os.environ and + 'Development/' in os.environ['SERVER_SOFTWARE']) + + +def is_prod_appengine(): + return ('APPENGINE_RUNTIME' in os.environ and + 'Google App Engine/' in os.environ['SERVER_SOFTWARE'] and + not is_prod_appengine_mvms()) + + +def is_prod_appengine_mvms(): + return os.environ.get('GAE_VM', False) == 'true' diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py new file mode 100644 index 0000000..642e99e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py @@ -0,0 +1,112 @@ +""" +NTLM authenticating pool, contributed by erikcederstran + +Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10 +""" +from __future__ import absolute_import + +from logging import getLogger +from ntlm import ntlm + +from .. import HTTPSConnectionPool +from ..packages.six.moves.http_client import HTTPSConnection + + +log = getLogger(__name__) + + +class NTLMConnectionPool(HTTPSConnectionPool): + """ + Implements an NTLM authentication version of an urllib3 connection pool + """ + + scheme = 'https' + + def __init__(self, user, pw, authurl, *args, **kwargs): + """ + authurl is a random URL on the server that is protected by NTLM. + user is the Windows user, probably in the DOMAIN\\username format. + pw is the password for the user. + """ + super(NTLMConnectionPool, self).__init__(*args, **kwargs) + self.authurl = authurl + self.rawuser = user + user_parts = user.split('\\', 1) + self.domain = user_parts[0].upper() + self.user = user_parts[1] + self.pw = pw + + def _new_conn(self): + # Performs the NTLM handshake that secures the connection. The socket + # must be kept open while requests are performed. + self.num_connections += 1 + log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s', + self.num_connections, self.host, self.authurl) + + headers = {} + headers['Connection'] = 'Keep-Alive' + req_header = 'Authorization' + resp_header = 'www-authenticate' + + conn = HTTPSConnection(host=self.host, port=self.port) + + # Send negotiation message + headers[req_header] = ( + 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)) + log.debug('Request headers: %s', headers) + conn.request('GET', self.authurl, None, headers) + res = conn.getresponse() + reshdr = dict(res.getheaders()) + log.debug('Response status: %s %s', res.status, res.reason) + log.debug('Response headers: %s', reshdr) + log.debug('Response data: %s [...]', res.read(100)) + + # Remove the reference to the socket, so that it can not be closed by + # the response object (we want to keep the socket open) + res.fp = None + + # Server should respond with a challenge message + auth_header_values = reshdr[resp_header].split(', ') + auth_header_value = None + for s in auth_header_values: + if s[:5] == 'NTLM ': + auth_header_value = s[5:] + if auth_header_value is None: + raise Exception('Unexpected %s response header: %s' % + (resp_header, reshdr[resp_header])) + + # Send authentication message + ServerChallenge, NegotiateFlags = \ + ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value) + auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, + self.user, + self.domain, + self.pw, + NegotiateFlags) + headers[req_header] = 'NTLM %s' % auth_msg + log.debug('Request headers: %s', headers) + conn.request('GET', self.authurl, None, headers) + res = conn.getresponse() + log.debug('Response status: %s %s', res.status, res.reason) + log.debug('Response headers: %s', dict(res.getheaders())) + log.debug('Response data: %s [...]', res.read()[:100]) + if res.status != 200: + if res.status == 401: + raise Exception('Server rejected request: wrong ' + 'username or password') + raise Exception('Wrong server response: %s %s' % + (res.status, res.reason)) + + res.fp = None + log.debug('Connection established') + return conn + + def urlopen(self, method, url, body=None, headers=None, retries=3, + redirect=True, assert_same_host=True): + if headers is None: + headers = {} + headers['Connection'] = 'Keep-Alive' + return super(NTLMConnectionPool, self).urlopen(method, url, body, + headers, retries, + redirect, + assert_same_host) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py new file mode 100644 index 0000000..6dd3a01 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py @@ -0,0 +1,457 @@ +""" +SSL with SNI_-support for Python 2. Follow these instructions if you would +like to verify SSL certificates in Python 2. Note, the default libraries do +*not* do certificate checking; you need to do additional work to validate +certificates yourself. + +This needs the following packages installed: + +* pyOpenSSL (tested with 16.0.0) +* cryptography (minimum 1.3.4, from pyopenssl) +* idna (minimum 2.0, from cryptography) + +However, pyopenssl depends on cryptography, which depends on idna, so while we +use all three directly here we end up having relatively few packages required. + +You can install them with the following command: + + pip install pyopenssl cryptography idna + +To activate certificate checking, call +:func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code +before you begin making HTTP requests. This can be done in a ``sitecustomize`` +module, or at any other time before your application begins using ``urllib3``, +like this:: + + try: + import urllib3.contrib.pyopenssl + urllib3.contrib.pyopenssl.inject_into_urllib3() + except ImportError: + pass + +Now you can use :mod:`urllib3` as you normally would, and it will support SNI +when the required modules are installed. + +Activating this module also has the positive side effect of disabling SSL/TLS +compression in Python 2 (see `CRIME attack`_). + +If you want to configure the default list of supported cipher suites, you can +set the ``urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST`` variable. + +.. _sni: https://en.wikipedia.org/wiki/Server_Name_Indication +.. _crime attack: https://en.wikipedia.org/wiki/CRIME_(security_exploit) +""" +from __future__ import absolute_import + +import OpenSSL.SSL +from cryptography import x509 +from cryptography.hazmat.backends.openssl import backend as openssl_backend +from cryptography.hazmat.backends.openssl.x509 import _Certificate +try: + from cryptography.x509 import UnsupportedExtension +except ImportError: + # UnsupportedExtension is gone in cryptography >= 2.1.0 + class UnsupportedExtension(Exception): + pass + +from socket import timeout, error as SocketError +from io import BytesIO + +try: # Platform-specific: Python 2 + from socket import _fileobject +except ImportError: # Platform-specific: Python 3 + _fileobject = None + from ..packages.backports.makefile import backport_makefile + +import logging +import ssl +from ..packages import six +import sys + +from .. import util + +__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] + +# SNI always works. +HAS_SNI = True + +# Map from urllib3 to PyOpenSSL compatible parameter-values. +_openssl_versions = { + ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, + ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD, +} + +if hasattr(ssl, 'PROTOCOL_TLSv1_1') and hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'): + _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD + +if hasattr(ssl, 'PROTOCOL_TLSv1_2') and hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'): + _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD + +try: + _openssl_versions.update({ssl.PROTOCOL_SSLv3: OpenSSL.SSL.SSLv3_METHOD}) +except AttributeError: + pass + +_stdlib_to_openssl_verify = { + ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE, + ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER, + ssl.CERT_REQUIRED: + OpenSSL.SSL.VERIFY_PEER + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT, +} +_openssl_to_stdlib_verify = dict( + (v, k) for k, v in _stdlib_to_openssl_verify.items() +) + +# OpenSSL will only write 16K at a time +SSL_WRITE_BLOCKSIZE = 16384 + +orig_util_HAS_SNI = util.HAS_SNI +orig_util_SSLContext = util.ssl_.SSLContext + + +log = logging.getLogger(__name__) + + +def inject_into_urllib3(): + 'Monkey-patch urllib3 with PyOpenSSL-backed SSL-support.' + + _validate_dependencies_met() + + util.ssl_.SSLContext = PyOpenSSLContext + util.HAS_SNI = HAS_SNI + util.ssl_.HAS_SNI = HAS_SNI + util.IS_PYOPENSSL = True + util.ssl_.IS_PYOPENSSL = True + + +def extract_from_urllib3(): + 'Undo monkey-patching by :func:`inject_into_urllib3`.' + + util.ssl_.SSLContext = orig_util_SSLContext + util.HAS_SNI = orig_util_HAS_SNI + util.ssl_.HAS_SNI = orig_util_HAS_SNI + util.IS_PYOPENSSL = False + util.ssl_.IS_PYOPENSSL = False + + +def _validate_dependencies_met(): + """ + Verifies that PyOpenSSL's package-level dependencies have been met. + Throws `ImportError` if they are not met. + """ + # Method added in `cryptography==1.1`; not available in older versions + from cryptography.x509.extensions import Extensions + if getattr(Extensions, "get_extension_for_class", None) is None: + raise ImportError("'cryptography' module missing required functionality. " + "Try upgrading to v1.3.4 or newer.") + + # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509 + # attribute is only present on those versions. + from OpenSSL.crypto import X509 + x509 = X509() + if getattr(x509, "_x509", None) is None: + raise ImportError("'pyOpenSSL' module missing required functionality. " + "Try upgrading to v0.14 or newer.") + + +def _dnsname_to_stdlib(name): + """ + Converts a dNSName SubjectAlternativeName field to the form used by the + standard library on the given Python version. + + Cryptography produces a dNSName as a unicode string that was idna-decoded + from ASCII bytes. We need to idna-encode that string to get it back, and + then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib + uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8). + """ + def idna_encode(name): + """ + Borrowed wholesale from the Python Cryptography Project. It turns out + that we can't just safely call `idna.encode`: it can explode for + wildcard names. This avoids that problem. + """ + from pip._vendor import idna + + for prefix in [u'*.', u'.']: + if name.startswith(prefix): + name = name[len(prefix):] + return prefix.encode('ascii') + idna.encode(name) + return idna.encode(name) + + name = idna_encode(name) + if sys.version_info >= (3, 0): + name = name.decode('utf-8') + return name + + +def get_subj_alt_name(peer_cert): + """ + Given an PyOpenSSL certificate, provides all the subject alternative names. + """ + # Pass the cert to cryptography, which has much better APIs for this. + if hasattr(peer_cert, "to_cryptography"): + cert = peer_cert.to_cryptography() + else: + # This is technically using private APIs, but should work across all + # relevant versions before PyOpenSSL got a proper API for this. + cert = _Certificate(openssl_backend, peer_cert._x509) + + # We want to find the SAN extension. Ask Cryptography to locate it (it's + # faster than looping in Python) + try: + ext = cert.extensions.get_extension_for_class( + x509.SubjectAlternativeName + ).value + except x509.ExtensionNotFound: + # No such extension, return the empty list. + return [] + except (x509.DuplicateExtension, UnsupportedExtension, + x509.UnsupportedGeneralNameType, UnicodeError) as e: + # A problem has been found with the quality of the certificate. Assume + # no SAN field is present. + log.warning( + "A problem was encountered with the certificate that prevented " + "urllib3 from finding the SubjectAlternativeName field. This can " + "affect certificate validation. The error was %s", + e, + ) + return [] + + # We want to return dNSName and iPAddress fields. We need to cast the IPs + # back to strings because the match_hostname function wants them as + # strings. + # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8 + # decoded. This is pretty frustrating, but that's what the standard library + # does with certificates, and so we need to attempt to do the same. + names = [ + ('DNS', _dnsname_to_stdlib(name)) + for name in ext.get_values_for_type(x509.DNSName) + ] + names.extend( + ('IP Address', str(name)) + for name in ext.get_values_for_type(x509.IPAddress) + ) + + return names + + +class WrappedSocket(object): + '''API-compatibility wrapper for Python OpenSSL's Connection-class. + + Note: _makefile_refs, _drop() and _reuse() are needed for the garbage + collector of pypy. + ''' + + def __init__(self, connection, socket, suppress_ragged_eofs=True): + self.connection = connection + self.socket = socket + self.suppress_ragged_eofs = suppress_ragged_eofs + self._makefile_refs = 0 + self._closed = False + + def fileno(self): + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self): + if self._makefile_refs > 0: + self._makefile_refs -= 1 + if self._closed: + self.close() + + def recv(self, *args, **kwargs): + try: + data = self.connection.recv(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'): + return b'' + else: + raise SocketError(str(e)) + except OpenSSL.SSL.ZeroReturnError as e: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return b'' + else: + raise + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout('The read operation timed out') + else: + return self.recv(*args, **kwargs) + else: + return data + + def recv_into(self, *args, **kwargs): + try: + return self.connection.recv_into(*args, **kwargs) + except OpenSSL.SSL.SysCallError as e: + if self.suppress_ragged_eofs and e.args == (-1, 'Unexpected EOF'): + return 0 + else: + raise SocketError(str(e)) + except OpenSSL.SSL.ZeroReturnError as e: + if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN: + return 0 + else: + raise + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(self.socket, self.socket.gettimeout()): + raise timeout('The read operation timed out') + else: + return self.recv_into(*args, **kwargs) + + def settimeout(self, timeout): + return self.socket.settimeout(timeout) + + def _send_until_done(self, data): + while True: + try: + return self.connection.send(data) + except OpenSSL.SSL.WantWriteError: + if not util.wait_for_write(self.socket, self.socket.gettimeout()): + raise timeout() + continue + except OpenSSL.SSL.SysCallError as e: + raise SocketError(str(e)) + + def sendall(self, data): + total_sent = 0 + while total_sent < len(data): + sent = self._send_until_done(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE]) + total_sent += sent + + def shutdown(self): + # FIXME rethrow compatible exceptions should we ever use this + self.connection.shutdown() + + def close(self): + if self._makefile_refs < 1: + try: + self._closed = True + return self.connection.close() + except OpenSSL.SSL.Error: + return + else: + self._makefile_refs -= 1 + + def getpeercert(self, binary_form=False): + x509 = self.connection.get_peer_certificate() + + if not x509: + return x509 + + if binary_form: + return OpenSSL.crypto.dump_certificate( + OpenSSL.crypto.FILETYPE_ASN1, + x509) + + return { + 'subject': ( + (('commonName', x509.get_subject().CN),), + ), + 'subjectAltName': get_subj_alt_name(x509) + } + + def _reuse(self): + self._makefile_refs += 1 + + def _drop(self): + if self._makefile_refs < 1: + self.close() + else: + self._makefile_refs -= 1 + + +if _fileobject: # Platform-specific: Python 2 + def makefile(self, mode, bufsize=-1): + self._makefile_refs += 1 + return _fileobject(self, mode, bufsize, close=True) +else: # Platform-specific: Python 3 + makefile = backport_makefile + +WrappedSocket.makefile = makefile + + +class PyOpenSSLContext(object): + """ + I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible + for translating the interface of the standard library ``SSLContext`` object + to calls into PyOpenSSL. + """ + def __init__(self, protocol): + self.protocol = _openssl_versions[protocol] + self._ctx = OpenSSL.SSL.Context(self.protocol) + self._options = 0 + self.check_hostname = False + + @property + def options(self): + return self._options + + @options.setter + def options(self, value): + self._options = value + self._ctx.set_options(value) + + @property + def verify_mode(self): + return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()] + + @verify_mode.setter + def verify_mode(self, value): + self._ctx.set_verify( + _stdlib_to_openssl_verify[value], + _verify_callback + ) + + def set_default_verify_paths(self): + self._ctx.set_default_verify_paths() + + def set_ciphers(self, ciphers): + if isinstance(ciphers, six.text_type): + ciphers = ciphers.encode('utf-8') + self._ctx.set_cipher_list(ciphers) + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + if cafile is not None: + cafile = cafile.encode('utf-8') + if capath is not None: + capath = capath.encode('utf-8') + self._ctx.load_verify_locations(cafile, capath) + if cadata is not None: + self._ctx.load_verify_locations(BytesIO(cadata)) + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._ctx.use_certificate_chain_file(certfile) + if password is not None: + self._ctx.set_passwd_cb(lambda max_length, prompt_twice, userdata: password) + self._ctx.use_privatekey_file(keyfile or certfile) + + def wrap_socket(self, sock, server_side=False, + do_handshake_on_connect=True, suppress_ragged_eofs=True, + server_hostname=None): + cnx = OpenSSL.SSL.Connection(self._ctx, sock) + + if isinstance(server_hostname, six.text_type): # Platform-specific: Python 3 + server_hostname = server_hostname.encode('utf-8') + + if server_hostname is not None: + cnx.set_tlsext_host_name(server_hostname) + + cnx.set_connect_state() + + while True: + try: + cnx.do_handshake() + except OpenSSL.SSL.WantReadError: + if not util.wait_for_read(sock, sock.gettimeout()): + raise timeout('select timed out') + continue + except OpenSSL.SSL.Error as e: + raise ssl.SSLError('bad handshake: %r' % e) + break + + return WrappedSocket(cnx, sock) + + +def _verify_callback(cnx, x509, err_no, err_depth, return_code): + return err_no == 0 diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py new file mode 100644 index 0000000..77cb59e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py @@ -0,0 +1,804 @@ +""" +SecureTranport support for urllib3 via ctypes. + +This makes platform-native TLS available to urllib3 users on macOS without the +use of a compiler. This is an important feature because the Python Package +Index is moving to become a TLSv1.2-or-higher server, and the default OpenSSL +that ships with macOS is not capable of doing TLSv1.2. The only way to resolve +this is to give macOS users an alternative solution to the problem, and that +solution is to use SecureTransport. + +We use ctypes here because this solution must not require a compiler. That's +because pip is not allowed to require a compiler either. + +This is not intended to be a seriously long-term solution to this problem. +The hope is that PEP 543 will eventually solve this issue for us, at which +point we can retire this contrib module. But in the short term, we need to +solve the impending tire fire that is Python on Mac without this kind of +contrib module. So...here we are. + +To use this module, simply import and inject it:: + + import urllib3.contrib.securetransport + urllib3.contrib.securetransport.inject_into_urllib3() + +Happy TLSing! +""" +from __future__ import absolute_import + +import contextlib +import ctypes +import errno +import os.path +import shutil +import socket +import ssl +import threading +import weakref + +from .. import util +from ._securetransport.bindings import ( + Security, SecurityConst, CoreFoundation +) +from ._securetransport.low_level import ( + _assert_no_error, _cert_array_from_pem, _temporary_keychain, + _load_client_cert_chain +) + +try: # Platform-specific: Python 2 + from socket import _fileobject +except ImportError: # Platform-specific: Python 3 + _fileobject = None + from ..packages.backports.makefile import backport_makefile + +__all__ = ['inject_into_urllib3', 'extract_from_urllib3'] + +# SNI always works +HAS_SNI = True + +orig_util_HAS_SNI = util.HAS_SNI +orig_util_SSLContext = util.ssl_.SSLContext + +# This dictionary is used by the read callback to obtain a handle to the +# calling wrapped socket. This is a pretty silly approach, but for now it'll +# do. I feel like I should be able to smuggle a handle to the wrapped socket +# directly in the SSLConnectionRef, but for now this approach will work I +# guess. +# +# We need to lock around this structure for inserts, but we don't do it for +# reads/writes in the callbacks. The reasoning here goes as follows: +# +# 1. It is not possible to call into the callbacks before the dictionary is +# populated, so once in the callback the id must be in the dictionary. +# 2. The callbacks don't mutate the dictionary, they only read from it, and +# so cannot conflict with any of the insertions. +# +# This is good: if we had to lock in the callbacks we'd drastically slow down +# the performance of this code. +_connection_refs = weakref.WeakValueDictionary() +_connection_ref_lock = threading.Lock() + +# Limit writes to 16kB. This is OpenSSL's limit, but we'll cargo-cult it over +# for no better reason than we need *a* limit, and this one is right there. +SSL_WRITE_BLOCKSIZE = 16384 + +# This is our equivalent of util.ssl_.DEFAULT_CIPHERS, but expanded out to +# individual cipher suites. We need to do this because this is how +# SecureTransport wants them. +CIPHER_SUITES = [ + SecurityConst.TLS_AES_256_GCM_SHA384, + SecurityConst.TLS_CHACHA20_POLY1305_SHA256, + SecurityConst.TLS_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, + SecurityConst.TLS_RSA_WITH_AES_256_GCM_SHA384, + SecurityConst.TLS_RSA_WITH_AES_128_GCM_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA256, + SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA256, + SecurityConst.TLS_RSA_WITH_AES_256_CBC_SHA, + SecurityConst.TLS_RSA_WITH_AES_128_CBC_SHA, +] + +# Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of +# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version. +_protocol_to_min_max = { + ssl.PROTOCOL_SSLv23: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12), +} + +if hasattr(ssl, "PROTOCOL_SSLv2"): + _protocol_to_min_max[ssl.PROTOCOL_SSLv2] = ( + SecurityConst.kSSLProtocol2, SecurityConst.kSSLProtocol2 + ) +if hasattr(ssl, "PROTOCOL_SSLv3"): + _protocol_to_min_max[ssl.PROTOCOL_SSLv3] = ( + SecurityConst.kSSLProtocol3, SecurityConst.kSSLProtocol3 + ) +if hasattr(ssl, "PROTOCOL_TLSv1"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1] = ( + SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol1 + ) +if hasattr(ssl, "PROTOCOL_TLSv1_1"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1_1] = ( + SecurityConst.kTLSProtocol11, SecurityConst.kTLSProtocol11 + ) +if hasattr(ssl, "PROTOCOL_TLSv1_2"): + _protocol_to_min_max[ssl.PROTOCOL_TLSv1_2] = ( + SecurityConst.kTLSProtocol12, SecurityConst.kTLSProtocol12 + ) +if hasattr(ssl, "PROTOCOL_TLS"): + _protocol_to_min_max[ssl.PROTOCOL_TLS] = _protocol_to_min_max[ssl.PROTOCOL_SSLv23] + + +def inject_into_urllib3(): + """ + Monkey-patch urllib3 with SecureTransport-backed SSL-support. + """ + util.ssl_.SSLContext = SecureTransportContext + util.HAS_SNI = HAS_SNI + util.ssl_.HAS_SNI = HAS_SNI + util.IS_SECURETRANSPORT = True + util.ssl_.IS_SECURETRANSPORT = True + + +def extract_from_urllib3(): + """ + Undo monkey-patching by :func:`inject_into_urllib3`. + """ + util.ssl_.SSLContext = orig_util_SSLContext + util.HAS_SNI = orig_util_HAS_SNI + util.ssl_.HAS_SNI = orig_util_HAS_SNI + util.IS_SECURETRANSPORT = False + util.ssl_.IS_SECURETRANSPORT = False + + +def _read_callback(connection_id, data_buffer, data_length_pointer): + """ + SecureTransport read callback. This is called by ST to request that data + be returned from the socket. + """ + wrapped_socket = None + try: + wrapped_socket = _connection_refs.get(connection_id) + if wrapped_socket is None: + return SecurityConst.errSSLInternal + base_socket = wrapped_socket.socket + + requested_length = data_length_pointer[0] + + timeout = wrapped_socket.gettimeout() + error = None + read_count = 0 + + try: + while read_count < requested_length: + if timeout is None or timeout >= 0: + if not util.wait_for_read(base_socket, timeout): + raise socket.error(errno.EAGAIN, 'timed out') + + remaining = requested_length - read_count + buffer = (ctypes.c_char * remaining).from_address( + data_buffer + read_count + ) + chunk_size = base_socket.recv_into(buffer, remaining) + read_count += chunk_size + if not chunk_size: + if not read_count: + return SecurityConst.errSSLClosedGraceful + break + except (socket.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + data_length_pointer[0] = read_count + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedAbort + raise + + data_length_pointer[0] = read_count + + if read_count != requested_length: + return SecurityConst.errSSLWouldBlock + + return 0 + except Exception as e: + if wrapped_socket is not None: + wrapped_socket._exception = e + return SecurityConst.errSSLInternal + + +def _write_callback(connection_id, data_buffer, data_length_pointer): + """ + SecureTransport write callback. This is called by ST to request that data + actually be sent on the network. + """ + wrapped_socket = None + try: + wrapped_socket = _connection_refs.get(connection_id) + if wrapped_socket is None: + return SecurityConst.errSSLInternal + base_socket = wrapped_socket.socket + + bytes_to_write = data_length_pointer[0] + data = ctypes.string_at(data_buffer, bytes_to_write) + + timeout = wrapped_socket.gettimeout() + error = None + sent = 0 + + try: + while sent < bytes_to_write: + if timeout is None or timeout >= 0: + if not util.wait_for_write(base_socket, timeout): + raise socket.error(errno.EAGAIN, 'timed out') + chunk_sent = base_socket.send(data) + sent += chunk_sent + + # This has some needless copying here, but I'm not sure there's + # much value in optimising this data path. + data = data[chunk_sent:] + except (socket.error) as e: + error = e.errno + + if error is not None and error != errno.EAGAIN: + data_length_pointer[0] = sent + if error == errno.ECONNRESET or error == errno.EPIPE: + return SecurityConst.errSSLClosedAbort + raise + + data_length_pointer[0] = sent + + if sent != bytes_to_write: + return SecurityConst.errSSLWouldBlock + + return 0 + except Exception as e: + if wrapped_socket is not None: + wrapped_socket._exception = e + return SecurityConst.errSSLInternal + + +# We need to keep these two objects references alive: if they get GC'd while +# in use then SecureTransport could attempt to call a function that is in freed +# memory. That would be...uh...bad. Yeah, that's the word. Bad. +_read_callback_pointer = Security.SSLReadFunc(_read_callback) +_write_callback_pointer = Security.SSLWriteFunc(_write_callback) + + +class WrappedSocket(object): + """ + API-compatibility wrapper for Python's OpenSSL wrapped socket object. + + Note: _makefile_refs, _drop(), and _reuse() are needed for the garbage + collector of PyPy. + """ + def __init__(self, socket): + self.socket = socket + self.context = None + self._makefile_refs = 0 + self._closed = False + self._exception = None + self._keychain = None + self._keychain_dir = None + self._client_cert_chain = None + + # We save off the previously-configured timeout and then set it to + # zero. This is done because we use select and friends to handle the + # timeouts, but if we leave the timeout set on the lower socket then + # Python will "kindly" call select on that socket again for us. Avoid + # that by forcing the timeout to zero. + self._timeout = self.socket.gettimeout() + self.socket.settimeout(0) + + @contextlib.contextmanager + def _raise_on_error(self): + """ + A context manager that can be used to wrap calls that do I/O from + SecureTransport. If any of the I/O callbacks hit an exception, this + context manager will correctly propagate the exception after the fact. + This avoids silently swallowing those exceptions. + + It also correctly forces the socket closed. + """ + self._exception = None + + # We explicitly don't catch around this yield because in the unlikely + # event that an exception was hit in the block we don't want to swallow + # it. + yield + if self._exception is not None: + exception, self._exception = self._exception, None + self.close() + raise exception + + def _set_ciphers(self): + """ + Sets up the allowed ciphers. By default this matches the set in + util.ssl_.DEFAULT_CIPHERS, at least as supported by macOS. This is done + custom and doesn't allow changing at this time, mostly because parsing + OpenSSL cipher strings is going to be a freaking nightmare. + """ + ciphers = (Security.SSLCipherSuite * len(CIPHER_SUITES))(*CIPHER_SUITES) + result = Security.SSLSetEnabledCiphers( + self.context, ciphers, len(CIPHER_SUITES) + ) + _assert_no_error(result) + + def _custom_validate(self, verify, trust_bundle): + """ + Called when we have set custom validation. We do this in two cases: + first, when cert validation is entirely disabled; and second, when + using a custom trust DB. + """ + # If we disabled cert validation, just say: cool. + if not verify: + return + + # We want data in memory, so load it up. + if os.path.isfile(trust_bundle): + with open(trust_bundle, 'rb') as f: + trust_bundle = f.read() + + cert_array = None + trust = Security.SecTrustRef() + + try: + # Get a CFArray that contains the certs we want. + cert_array = _cert_array_from_pem(trust_bundle) + + # Ok, now the hard part. We want to get the SecTrustRef that ST has + # created for this connection, shove our CAs into it, tell ST to + # ignore everything else it knows, and then ask if it can build a + # chain. This is a buuuunch of code. + result = Security.SSLCopyPeerTrust( + self.context, ctypes.byref(trust) + ) + _assert_no_error(result) + if not trust: + raise ssl.SSLError("Failed to copy trust reference") + + result = Security.SecTrustSetAnchorCertificates(trust, cert_array) + _assert_no_error(result) + + result = Security.SecTrustSetAnchorCertificatesOnly(trust, True) + _assert_no_error(result) + + trust_result = Security.SecTrustResultType() + result = Security.SecTrustEvaluate( + trust, ctypes.byref(trust_result) + ) + _assert_no_error(result) + finally: + if trust: + CoreFoundation.CFRelease(trust) + + if cert_array is not None: + CoreFoundation.CFRelease(cert_array) + + # Ok, now we can look at what the result was. + successes = ( + SecurityConst.kSecTrustResultUnspecified, + SecurityConst.kSecTrustResultProceed + ) + if trust_result.value not in successes: + raise ssl.SSLError( + "certificate verify failed, error code: %d" % + trust_result.value + ) + + def handshake(self, + server_hostname, + verify, + trust_bundle, + min_version, + max_version, + client_cert, + client_key, + client_key_passphrase): + """ + Actually performs the TLS handshake. This is run automatically by + wrapped socket, and shouldn't be needed in user code. + """ + # First, we do the initial bits of connection setup. We need to create + # a context, set its I/O funcs, and set the connection reference. + self.context = Security.SSLCreateContext( + None, SecurityConst.kSSLClientSide, SecurityConst.kSSLStreamType + ) + result = Security.SSLSetIOFuncs( + self.context, _read_callback_pointer, _write_callback_pointer + ) + _assert_no_error(result) + + # Here we need to compute the handle to use. We do this by taking the + # id of self modulo 2**31 - 1. If this is already in the dictionary, we + # just keep incrementing by one until we find a free space. + with _connection_ref_lock: + handle = id(self) % 2147483647 + while handle in _connection_refs: + handle = (handle + 1) % 2147483647 + _connection_refs[handle] = self + + result = Security.SSLSetConnection(self.context, handle) + _assert_no_error(result) + + # If we have a server hostname, we should set that too. + if server_hostname: + if not isinstance(server_hostname, bytes): + server_hostname = server_hostname.encode('utf-8') + + result = Security.SSLSetPeerDomainName( + self.context, server_hostname, len(server_hostname) + ) + _assert_no_error(result) + + # Setup the ciphers. + self._set_ciphers() + + # Set the minimum and maximum TLS versions. + result = Security.SSLSetProtocolVersionMin(self.context, min_version) + _assert_no_error(result) + result = Security.SSLSetProtocolVersionMax(self.context, max_version) + _assert_no_error(result) + + # If there's a trust DB, we need to use it. We do that by telling + # SecureTransport to break on server auth. We also do that if we don't + # want to validate the certs at all: we just won't actually do any + # authing in that case. + if not verify or trust_bundle is not None: + result = Security.SSLSetSessionOption( + self.context, + SecurityConst.kSSLSessionOptionBreakOnServerAuth, + True + ) + _assert_no_error(result) + + # If there's a client cert, we need to use it. + if client_cert: + self._keychain, self._keychain_dir = _temporary_keychain() + self._client_cert_chain = _load_client_cert_chain( + self._keychain, client_cert, client_key + ) + result = Security.SSLSetCertificate( + self.context, self._client_cert_chain + ) + _assert_no_error(result) + + while True: + with self._raise_on_error(): + result = Security.SSLHandshake(self.context) + + if result == SecurityConst.errSSLWouldBlock: + raise socket.timeout("handshake timed out") + elif result == SecurityConst.errSSLServerAuthCompleted: + self._custom_validate(verify, trust_bundle) + continue + else: + _assert_no_error(result) + break + + def fileno(self): + return self.socket.fileno() + + # Copy-pasted from Python 3.5 source code + def _decref_socketios(self): + if self._makefile_refs > 0: + self._makefile_refs -= 1 + if self._closed: + self.close() + + def recv(self, bufsiz): + buffer = ctypes.create_string_buffer(bufsiz) + bytes_read = self.recv_into(buffer, bufsiz) + data = buffer[:bytes_read] + return data + + def recv_into(self, buffer, nbytes=None): + # Read short on EOF. + if self._closed: + return 0 + + if nbytes is None: + nbytes = len(buffer) + + buffer = (ctypes.c_char * nbytes).from_buffer(buffer) + processed_bytes = ctypes.c_size_t(0) + + with self._raise_on_error(): + result = Security.SSLRead( + self.context, buffer, nbytes, ctypes.byref(processed_bytes) + ) + + # There are some result codes that we want to treat as "not always + # errors". Specifically, those are errSSLWouldBlock, + # errSSLClosedGraceful, and errSSLClosedNoNotify. + if (result == SecurityConst.errSSLWouldBlock): + # If we didn't process any bytes, then this was just a time out. + # However, we can get errSSLWouldBlock in situations when we *did* + # read some data, and in those cases we should just read "short" + # and return. + if processed_bytes.value == 0: + # Timed out, no data read. + raise socket.timeout("recv timed out") + elif result in (SecurityConst.errSSLClosedGraceful, SecurityConst.errSSLClosedNoNotify): + # The remote peer has closed this connection. We should do so as + # well. Note that we don't actually return here because in + # principle this could actually be fired along with return data. + # It's unlikely though. + self.close() + else: + _assert_no_error(result) + + # Ok, we read and probably succeeded. We should return whatever data + # was actually read. + return processed_bytes.value + + def settimeout(self, timeout): + self._timeout = timeout + + def gettimeout(self): + return self._timeout + + def send(self, data): + processed_bytes = ctypes.c_size_t(0) + + with self._raise_on_error(): + result = Security.SSLWrite( + self.context, data, len(data), ctypes.byref(processed_bytes) + ) + + if result == SecurityConst.errSSLWouldBlock and processed_bytes.value == 0: + # Timed out + raise socket.timeout("send timed out") + else: + _assert_no_error(result) + + # We sent, and probably succeeded. Tell them how much we sent. + return processed_bytes.value + + def sendall(self, data): + total_sent = 0 + while total_sent < len(data): + sent = self.send(data[total_sent:total_sent + SSL_WRITE_BLOCKSIZE]) + total_sent += sent + + def shutdown(self): + with self._raise_on_error(): + Security.SSLClose(self.context) + + def close(self): + # TODO: should I do clean shutdown here? Do I have to? + if self._makefile_refs < 1: + self._closed = True + if self.context: + CoreFoundation.CFRelease(self.context) + self.context = None + if self._client_cert_chain: + CoreFoundation.CFRelease(self._client_cert_chain) + self._client_cert_chain = None + if self._keychain: + Security.SecKeychainDelete(self._keychain) + CoreFoundation.CFRelease(self._keychain) + shutil.rmtree(self._keychain_dir) + self._keychain = self._keychain_dir = None + return self.socket.close() + else: + self._makefile_refs -= 1 + + def getpeercert(self, binary_form=False): + # Urgh, annoying. + # + # Here's how we do this: + # + # 1. Call SSLCopyPeerTrust to get hold of the trust object for this + # connection. + # 2. Call SecTrustGetCertificateAtIndex for index 0 to get the leaf. + # 3. To get the CN, call SecCertificateCopyCommonName and process that + # string so that it's of the appropriate type. + # 4. To get the SAN, we need to do something a bit more complex: + # a. Call SecCertificateCopyValues to get the data, requesting + # kSecOIDSubjectAltName. + # b. Mess about with this dictionary to try to get the SANs out. + # + # This is gross. Really gross. It's going to be a few hundred LoC extra + # just to repeat something that SecureTransport can *already do*. So my + # operating assumption at this time is that what we want to do is + # instead to just flag to urllib3 that it shouldn't do its own hostname + # validation when using SecureTransport. + if not binary_form: + raise ValueError( + "SecureTransport only supports dumping binary certs" + ) + trust = Security.SecTrustRef() + certdata = None + der_bytes = None + + try: + # Grab the trust store. + result = Security.SSLCopyPeerTrust( + self.context, ctypes.byref(trust) + ) + _assert_no_error(result) + if not trust: + # Probably we haven't done the handshake yet. No biggie. + return None + + cert_count = Security.SecTrustGetCertificateCount(trust) + if not cert_count: + # Also a case that might happen if we haven't handshaked. + # Handshook? Handshaken? + return None + + leaf = Security.SecTrustGetCertificateAtIndex(trust, 0) + assert leaf + + # Ok, now we want the DER bytes. + certdata = Security.SecCertificateCopyData(leaf) + assert certdata + + data_length = CoreFoundation.CFDataGetLength(certdata) + data_buffer = CoreFoundation.CFDataGetBytePtr(certdata) + der_bytes = ctypes.string_at(data_buffer, data_length) + finally: + if certdata: + CoreFoundation.CFRelease(certdata) + if trust: + CoreFoundation.CFRelease(trust) + + return der_bytes + + def _reuse(self): + self._makefile_refs += 1 + + def _drop(self): + if self._makefile_refs < 1: + self.close() + else: + self._makefile_refs -= 1 + + +if _fileobject: # Platform-specific: Python 2 + def makefile(self, mode, bufsize=-1): + self._makefile_refs += 1 + return _fileobject(self, mode, bufsize, close=True) +else: # Platform-specific: Python 3 + def makefile(self, mode="r", buffering=None, *args, **kwargs): + # We disable buffering with SecureTransport because it conflicts with + # the buffering that ST does internally (see issue #1153 for more). + buffering = 0 + return backport_makefile(self, mode, buffering, *args, **kwargs) + +WrappedSocket.makefile = makefile + + +class SecureTransportContext(object): + """ + I am a wrapper class for the SecureTransport library, to translate the + interface of the standard library ``SSLContext`` object to calls into + SecureTransport. + """ + def __init__(self, protocol): + self._min_version, self._max_version = _protocol_to_min_max[protocol] + self._options = 0 + self._verify = False + self._trust_bundle = None + self._client_cert = None + self._client_key = None + self._client_key_passphrase = None + + @property + def check_hostname(self): + """ + SecureTransport cannot have its hostname checking disabled. For more, + see the comment on getpeercert() in this file. + """ + return True + + @check_hostname.setter + def check_hostname(self, value): + """ + SecureTransport cannot have its hostname checking disabled. For more, + see the comment on getpeercert() in this file. + """ + pass + + @property + def options(self): + # TODO: Well, crap. + # + # So this is the bit of the code that is the most likely to cause us + # trouble. Essentially we need to enumerate all of the SSL options that + # users might want to use and try to see if we can sensibly translate + # them, or whether we should just ignore them. + return self._options + + @options.setter + def options(self, value): + # TODO: Update in line with above. + self._options = value + + @property + def verify_mode(self): + return ssl.CERT_REQUIRED if self._verify else ssl.CERT_NONE + + @verify_mode.setter + def verify_mode(self, value): + self._verify = True if value == ssl.CERT_REQUIRED else False + + def set_default_verify_paths(self): + # So, this has to do something a bit weird. Specifically, what it does + # is nothing. + # + # This means that, if we had previously had load_verify_locations + # called, this does not undo that. We need to do that because it turns + # out that the rest of the urllib3 code will attempt to load the + # default verify paths if it hasn't been told about any paths, even if + # the context itself was sometime earlier. We resolve that by just + # ignoring it. + pass + + def load_default_certs(self): + return self.set_default_verify_paths() + + def set_ciphers(self, ciphers): + # For now, we just require the default cipher string. + if ciphers != util.ssl_.DEFAULT_CIPHERS: + raise ValueError( + "SecureTransport doesn't support custom cipher strings" + ) + + def load_verify_locations(self, cafile=None, capath=None, cadata=None): + # OK, we only really support cadata and cafile. + if capath is not None: + raise ValueError( + "SecureTransport does not support cert directories" + ) + + self._trust_bundle = cafile or cadata + + def load_cert_chain(self, certfile, keyfile=None, password=None): + self._client_cert = certfile + self._client_key = keyfile + self._client_cert_passphrase = password + + def wrap_socket(self, sock, server_side=False, + do_handshake_on_connect=True, suppress_ragged_eofs=True, + server_hostname=None): + # So, what do we do here? Firstly, we assert some properties. This is a + # stripped down shim, so there is some functionality we don't support. + # See PEP 543 for the real deal. + assert not server_side + assert do_handshake_on_connect + assert suppress_ragged_eofs + + # Ok, we're good to go. Now we want to create the wrapped socket object + # and store it in the appropriate place. + wrapped_socket = WrappedSocket(sock) + + # Now we can handshake + wrapped_socket.handshake( + server_hostname, self._verify, self._trust_bundle, + self._min_version, self._max_version, self._client_cert, + self._client_key, self._client_key_passphrase + ) + return wrapped_socket diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py new file mode 100644 index 0000000..811e312 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +""" +This module contains provisional support for SOCKS proxies from within +urllib3. This module supports SOCKS4 (specifically the SOCKS4A variant) and +SOCKS5. To enable its functionality, either install PySocks or install this +module with the ``socks`` extra. + +The SOCKS implementation supports the full range of urllib3 features. It also +supports the following SOCKS features: + +- SOCKS4 +- SOCKS4a +- SOCKS5 +- Usernames and passwords for the SOCKS proxy + +Known Limitations: + +- Currently PySocks does not support contacting remote websites via literal + IPv6 addresses. Any such connection attempt will fail. You must use a domain + name. +- Currently PySocks does not support IPv6 connections to the SOCKS proxy. Any + such connection attempt will fail. +""" +from __future__ import absolute_import + +try: + import socks +except ImportError: + import warnings + from ..exceptions import DependencyWarning + + warnings.warn(( + 'SOCKS support in urllib3 requires the installation of optional ' + 'dependencies: specifically, PySocks. For more information, see ' + 'https://urllib3.readthedocs.io/en/latest/contrib.html#socks-proxies' + ), + DependencyWarning + ) + raise + +from socket import error as SocketError, timeout as SocketTimeout + +from ..connection import ( + HTTPConnection, HTTPSConnection +) +from ..connectionpool import ( + HTTPConnectionPool, HTTPSConnectionPool +) +from ..exceptions import ConnectTimeoutError, NewConnectionError +from ..poolmanager import PoolManager +from ..util.url import parse_url + +try: + import ssl +except ImportError: + ssl = None + + +class SOCKSConnection(HTTPConnection): + """ + A plain-text HTTP connection that connects via a SOCKS proxy. + """ + def __init__(self, *args, **kwargs): + self._socks_options = kwargs.pop('_socks_options') + super(SOCKSConnection, self).__init__(*args, **kwargs) + + def _new_conn(self): + """ + Establish a new connection via the SOCKS proxy. + """ + extra_kw = {} + if self.source_address: + extra_kw['source_address'] = self.source_address + + if self.socket_options: + extra_kw['socket_options'] = self.socket_options + + try: + conn = socks.create_connection( + (self.host, self.port), + proxy_type=self._socks_options['socks_version'], + proxy_addr=self._socks_options['proxy_host'], + proxy_port=self._socks_options['proxy_port'], + proxy_username=self._socks_options['username'], + proxy_password=self._socks_options['password'], + proxy_rdns=self._socks_options['rdns'], + timeout=self.timeout, + **extra_kw + ) + + except SocketTimeout as e: + raise ConnectTimeoutError( + self, "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout)) + + except socks.ProxyError as e: + # This is fragile as hell, but it seems to be the only way to raise + # useful errors here. + if e.socket_err: + error = e.socket_err + if isinstance(error, SocketTimeout): + raise ConnectTimeoutError( + self, + "Connection to %s timed out. (connect timeout=%s)" % + (self.host, self.timeout) + ) + else: + raise NewConnectionError( + self, + "Failed to establish a new connection: %s" % error + ) + else: + raise NewConnectionError( + self, + "Failed to establish a new connection: %s" % e + ) + + except SocketError as e: # Defensive: PySocks should catch all these. + raise NewConnectionError( + self, "Failed to establish a new connection: %s" % e) + + return conn + + +# We don't need to duplicate the Verified/Unverified distinction from +# urllib3/connection.py here because the HTTPSConnection will already have been +# correctly set to either the Verified or Unverified form by that module. This +# means the SOCKSHTTPSConnection will automatically be the correct type. +class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection): + pass + + +class SOCKSHTTPConnectionPool(HTTPConnectionPool): + ConnectionCls = SOCKSConnection + + +class SOCKSHTTPSConnectionPool(HTTPSConnectionPool): + ConnectionCls = SOCKSHTTPSConnection + + +class SOCKSProxyManager(PoolManager): + """ + A version of the urllib3 ProxyManager that routes connections via the + defined SOCKS proxy. + """ + pool_classes_by_scheme = { + 'http': SOCKSHTTPConnectionPool, + 'https': SOCKSHTTPSConnectionPool, + } + + def __init__(self, proxy_url, username=None, password=None, + num_pools=10, headers=None, **connection_pool_kw): + parsed = parse_url(proxy_url) + + if username is None and password is None and parsed.auth is not None: + split = parsed.auth.split(':') + if len(split) == 2: + username, password = split + if parsed.scheme == 'socks5': + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = False + elif parsed.scheme == 'socks5h': + socks_version = socks.PROXY_TYPE_SOCKS5 + rdns = True + elif parsed.scheme == 'socks4': + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = False + elif parsed.scheme == 'socks4a': + socks_version = socks.PROXY_TYPE_SOCKS4 + rdns = True + else: + raise ValueError( + "Unable to determine SOCKS version from %s" % proxy_url + ) + + self.proxy_url = proxy_url + + socks_options = { + 'socks_version': socks_version, + 'proxy_host': parsed.host, + 'proxy_port': parsed.port, + 'username': username, + 'password': password, + 'rdns': rdns + } + connection_pool_kw['_socks_options'] = socks_options + + super(SOCKSProxyManager, self).__init__( + num_pools, headers, **connection_pool_kw + ) + + self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py new file mode 100644 index 0000000..7bbaa98 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py @@ -0,0 +1,246 @@ +from __future__ import absolute_import +from .packages.six.moves.http_client import ( + IncompleteRead as httplib_IncompleteRead +) +# Base Exceptions + + +class HTTPError(Exception): + "Base exception used by this module." + pass + + +class HTTPWarning(Warning): + "Base warning used by this module." + pass + + +class PoolError(HTTPError): + "Base exception for errors caused within a pool." + def __init__(self, pool, message): + self.pool = pool + HTTPError.__init__(self, "%s: %s" % (pool, message)) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, None) + + +class RequestError(PoolError): + "Base exception for PoolErrors that have associated URLs." + def __init__(self, pool, url, message): + self.url = url + PoolError.__init__(self, pool, message) + + def __reduce__(self): + # For pickling purposes. + return self.__class__, (None, self.url, None) + + +class SSLError(HTTPError): + "Raised when SSL certificate fails in an HTTPS connection." + pass + + +class ProxyError(HTTPError): + "Raised when the connection to a proxy fails." + pass + + +class DecodeError(HTTPError): + "Raised when automatic decoding based on Content-Type fails." + pass + + +class ProtocolError(HTTPError): + "Raised when something unexpected happens mid-request/response." + pass + + +#: Renamed to ProtocolError but aliased for backwards compatibility. +ConnectionError = ProtocolError + + +# Leaf Exceptions + +class MaxRetryError(RequestError): + """Raised when the maximum number of retries is exceeded. + + :param pool: The connection pool + :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool` + :param string url: The requested Url + :param exceptions.Exception reason: The underlying error + + """ + + def __init__(self, pool, url, reason=None): + self.reason = reason + + message = "Max retries exceeded with url: %s (Caused by %r)" % ( + url, reason) + + RequestError.__init__(self, pool, url, message) + + +class HostChangedError(RequestError): + "Raised when an existing pool gets a request for a foreign host." + + def __init__(self, pool, url, retries=3): + message = "Tried to open a foreign host with url: %s" % url + RequestError.__init__(self, pool, url, message) + self.retries = retries + + +class TimeoutStateError(HTTPError): + """ Raised when passing an invalid state to a timeout """ + pass + + +class TimeoutError(HTTPError): + """ Raised when a socket timeout error occurs. + + Catching this error will catch both :exc:`ReadTimeoutErrors + <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`. + """ + pass + + +class ReadTimeoutError(TimeoutError, RequestError): + "Raised when a socket timeout occurs while receiving data from a server" + pass + + +# This timeout error does not have a URL attached and needs to inherit from the +# base HTTPError +class ConnectTimeoutError(TimeoutError): + "Raised when a socket timeout occurs while connecting to a server" + pass + + +class NewConnectionError(ConnectTimeoutError, PoolError): + "Raised when we fail to establish a new connection. Usually ECONNREFUSED." + pass + + +class EmptyPoolError(PoolError): + "Raised when a pool runs out of connections and no more are allowed." + pass + + +class ClosedPoolError(PoolError): + "Raised when a request enters a pool after the pool has been closed." + pass + + +class LocationValueError(ValueError, HTTPError): + "Raised when there is something wrong with a given URL input." + pass + + +class LocationParseError(LocationValueError): + "Raised when get_host or similar fails to parse the URL input." + + def __init__(self, location): + message = "Failed to parse: %s" % location + HTTPError.__init__(self, message) + + self.location = location + + +class ResponseError(HTTPError): + "Used as a container for an error reason supplied in a MaxRetryError." + GENERIC_ERROR = 'too many error responses' + SPECIFIC_ERROR = 'too many {status_code} error responses' + + +class SecurityWarning(HTTPWarning): + "Warned when performing security reducing actions" + pass + + +class SubjectAltNameWarning(SecurityWarning): + "Warned when connecting to a host with a certificate missing a SAN." + pass + + +class InsecureRequestWarning(SecurityWarning): + "Warned when making an unverified HTTPS request." + pass + + +class SystemTimeWarning(SecurityWarning): + "Warned when system time is suspected to be wrong" + pass + + +class InsecurePlatformWarning(SecurityWarning): + "Warned when certain SSL configuration is not available on a platform." + pass + + +class SNIMissingWarning(HTTPWarning): + "Warned when making a HTTPS request without SNI available." + pass + + +class DependencyWarning(HTTPWarning): + """ + Warned when an attempt is made to import a module with missing optional + dependencies. + """ + pass + + +class ResponseNotChunked(ProtocolError, ValueError): + "Response needs to be chunked in order to read it as chunks." + pass + + +class BodyNotHttplibCompatible(HTTPError): + """ + Body should be httplib.HTTPResponse like (have an fp attribute which + returns raw chunks) for read_chunked(). + """ + pass + + +class IncompleteRead(HTTPError, httplib_IncompleteRead): + """ + Response length doesn't match expected Content-Length + + Subclass of http_client.IncompleteRead to allow int value + for `partial` to avoid creating large objects on streamed + reads. + """ + def __init__(self, partial, expected): + super(IncompleteRead, self).__init__(partial, expected) + + def __repr__(self): + return ('IncompleteRead(%i bytes read, ' + '%i more expected)' % (self.partial, self.expected)) + + +class InvalidHeader(HTTPError): + "The header provided was somehow invalid." + pass + + +class ProxySchemeUnknown(AssertionError, ValueError): + "ProxyManager does not support the supplied scheme" + # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. + + def __init__(self, scheme): + message = "Not supported proxy scheme %s" % scheme + super(ProxySchemeUnknown, self).__init__(message) + + +class HeaderParsingError(HTTPError): + "Raised by assert_header_parsing, but we convert it to a log.warning statement." + def __init__(self, defects, unparsed_data): + message = '%s, unparsed data: %r' % (defects or 'Unknown', unparsed_data) + super(HeaderParsingError, self).__init__(message) + + +class UnrewindableBodyError(HTTPError): + "urllib3 encountered an error when trying to rewind a body" + pass diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/fields.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/fields.py new file mode 100644 index 0000000..37fe64a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/fields.py @@ -0,0 +1,178 @@ +from __future__ import absolute_import +import email.utils +import mimetypes + +from .packages import six + + +def guess_content_type(filename, default='application/octet-stream'): + """ + Guess the "Content-Type" of a file. + + :param filename: + The filename to guess the "Content-Type" of using :mod:`mimetypes`. + :param default: + If no "Content-Type" can be guessed, default to `default`. + """ + if filename: + return mimetypes.guess_type(filename)[0] or default + return default + + +def format_header_param(name, value): + """ + Helper function to format and quote a single header parameter. + + Particularly useful for header parameters which might contain + non-ASCII values, like file names. This follows RFC 2231, as + suggested by RFC 2388 Section 4.4. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + if not any(ch in value for ch in '"\\\r\n'): + result = '%s="%s"' % (name, value) + try: + result.encode('ascii') + except (UnicodeEncodeError, UnicodeDecodeError): + pass + else: + return result + if not six.PY3 and isinstance(value, six.text_type): # Python 2: + value = value.encode('utf-8') + value = email.utils.encode_rfc2231(value, 'utf-8') + value = '%s*=%s' % (name, value) + return value + + +class RequestField(object): + """ + A data container for request body parameters. + + :param name: + The name of this request field. + :param data: + The data/value body. + :param filename: + An optional filename of the request field. + :param headers: + An optional dict-like object of headers to initially use for the field. + """ + def __init__(self, name, data, filename=None, headers=None): + self._name = name + self._filename = filename + self.data = data + self.headers = {} + if headers: + self.headers = dict(headers) + + @classmethod + def from_tuples(cls, fieldname, value): + """ + A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters. + + Supports constructing :class:`~urllib3.fields.RequestField` from + parameter of key/value strings AND key/filetuple. A filetuple is a + (filename, data, MIME type) tuple where the MIME type is optional. + For example:: + + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + + Field names and filenames must be unicode. + """ + if isinstance(value, tuple): + if len(value) == 3: + filename, data, content_type = value + else: + filename, data = value + content_type = guess_content_type(filename) + else: + filename = None + content_type = None + data = value + + request_param = cls(fieldname, data, filename=filename) + request_param.make_multipart(content_type=content_type) + + return request_param + + def _render_part(self, name, value): + """ + Overridable helper function to format a single header parameter. + + :param name: + The name of the parameter, a string expected to be ASCII only. + :param value: + The value of the parameter, provided as a unicode string. + """ + return format_header_param(name, value) + + def _render_parts(self, header_parts): + """ + Helper function to format and quote a single header. + + Useful for single headers that are composed of multiple items. E.g., + 'Content-Disposition' fields. + + :param header_parts: + A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format + as `k1="v1"; k2="v2"; ...`. + """ + parts = [] + iterable = header_parts + if isinstance(header_parts, dict): + iterable = header_parts.items() + + for name, value in iterable: + if value is not None: + parts.append(self._render_part(name, value)) + + return '; '.join(parts) + + def render_headers(self): + """ + Renders the headers for this request field. + """ + lines = [] + + sort_keys = ['Content-Disposition', 'Content-Type', 'Content-Location'] + for sort_key in sort_keys: + if self.headers.get(sort_key, False): + lines.append('%s: %s' % (sort_key, self.headers[sort_key])) + + for header_name, header_value in self.headers.items(): + if header_name not in sort_keys: + if header_value: + lines.append('%s: %s' % (header_name, header_value)) + + lines.append('\r\n') + return '\r\n'.join(lines) + + def make_multipart(self, content_disposition=None, content_type=None, + content_location=None): + """ + Makes this request field into a multipart request field. + + This method overrides "Content-Disposition", "Content-Type" and + "Content-Location" headers to the request parameter. + + :param content_type: + The 'Content-Type' of the request body. + :param content_location: + The 'Content-Location' of the request body. + + """ + self.headers['Content-Disposition'] = content_disposition or 'form-data' + self.headers['Content-Disposition'] += '; '.join([ + '', self._render_parts( + (('name', self._name), ('filename', self._filename)) + ) + ]) + self.headers['Content-Type'] = content_type + self.headers['Content-Location'] = content_location diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/filepost.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/filepost.py new file mode 100644 index 0000000..78f1e19 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/filepost.py @@ -0,0 +1,98 @@ +from __future__ import absolute_import +import binascii +import codecs +import os + +from io import BytesIO + +from .packages import six +from .packages.six import b +from .fields import RequestField + +writer = codecs.lookup('utf-8')[3] + + +def choose_boundary(): + """ + Our embarrassingly-simple replacement for mimetools.choose_boundary. + """ + boundary = binascii.hexlify(os.urandom(16)) + if six.PY3: + boundary = boundary.decode('ascii') + return boundary + + +def iter_field_objects(fields): + """ + Iterate over fields. + + Supports list of (k, v) tuples and dicts, and lists of + :class:`~urllib3.fields.RequestField`. + + """ + if isinstance(fields, dict): + i = six.iteritems(fields) + else: + i = iter(fields) + + for field in i: + if isinstance(field, RequestField): + yield field + else: + yield RequestField.from_tuples(*field) + + +def iter_fields(fields): + """ + .. deprecated:: 1.6 + + Iterate over fields. + + The addition of :class:`~urllib3.fields.RequestField` makes this function + obsolete. Instead, use :func:`iter_field_objects`, which returns + :class:`~urllib3.fields.RequestField` objects. + + Supports list of (k, v) tuples and dicts. + """ + if isinstance(fields, dict): + return ((k, v) for k, v in six.iteritems(fields)) + + return ((k, v) for k, v in fields) + + +def encode_multipart_formdata(fields, boundary=None): + """ + Encode a dictionary of ``fields`` using the multipart/form-data MIME format. + + :param fields: + Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`). + + :param boundary: + If not specified, then a random boundary will be generated using + :func:`urllib3.filepost.choose_boundary`. + """ + body = BytesIO() + if boundary is None: + boundary = choose_boundary() + + for field in iter_field_objects(fields): + body.write(b('--%s\r\n' % (boundary))) + + writer(body).write(field.render_headers()) + data = field.data + + if isinstance(data, int): + data = str(data) # Backwards compatibility + + if isinstance(data, six.text_type): + writer(body).write(data) + else: + body.write(data) + + body.write(b'\r\n') + + body.write(b('--%s--\r\n' % (boundary))) + + content_type = str('multipart/form-data; boundary=%s' % boundary) + + return body.getvalue(), content_type diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py new file mode 100644 index 0000000..170e974 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py @@ -0,0 +1,5 @@ +from __future__ import absolute_import + +from . import ssl_match_hostname + +__all__ = ('ssl_match_hostname', ) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py new file mode 100644 index 0000000..75b80dc --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +""" +backports.makefile +~~~~~~~~~~~~~~~~~~ + +Backports the Python 3 ``socket.makefile`` method for use with anything that +wants to create a "fake" socket object. +""" +import io + +from socket import SocketIO + + +def backport_makefile(self, mode="r", buffering=None, encoding=None, + errors=None, newline=None): + """ + Backport of ``socket.makefile`` from Python 3.5. + """ + if not set(mode) <= set(["r", "w", "b"]): + raise ValueError( + "invalid mode %r (only r, w, b allowed)" % (mode,) + ) + writing = "w" in mode + reading = "r" in mode or not writing + assert reading or writing + binary = "b" in mode + rawmode = "" + if reading: + rawmode += "r" + if writing: + rawmode += "w" + raw = SocketIO(self, rawmode) + self._makefile_refs += 1 + if buffering is None: + buffering = -1 + if buffering < 0: + buffering = io.DEFAULT_BUFFER_SIZE + if buffering == 0: + if not binary: + raise ValueError("unbuffered streams must be binary") + return raw + if reading and writing: + buffer = io.BufferedRWPair(raw, raw, buffering) + elif reading: + buffer = io.BufferedReader(raw, buffering) + else: + assert writing + buffer = io.BufferedWriter(raw, buffering) + if binary: + return buffer + text = io.TextIOWrapper(buffer, encoding, errors, newline) + text.mode = mode + return text diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py new file mode 100644 index 0000000..4479363 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ordered_dict.py @@ -0,0 +1,259 @@ +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. +# Copyright 2009 Raymond Hettinger, released under the MIT License. +# http://code.activestate.com/recipes/576693/ +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + +try: + from _abcoll import KeysView, ValuesView, ItemsView +except ImportError: + pass + + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# 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. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py new file mode 100644 index 0000000..d6594eb --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py @@ -0,0 +1,19 @@ +import sys + +try: + # Our match_hostname function is the same as 3.5's, so we only want to + # import the match_hostname function if it's at least that good. + if sys.version_info < (3, 5): + raise ImportError("Fallback to vendored code") + + from ssl import CertificateError, match_hostname +except ImportError: + try: + # Backport of the function from a pypi module + from backports.ssl_match_hostname import CertificateError, match_hostname + except ImportError: + # Our vendored copy + from ._implementation import CertificateError, match_hostname + +# Not needed, but documenting what we provide. +__all__ = ('CertificateError', 'match_hostname') diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py new file mode 100644 index 0000000..92c9bc7 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py @@ -0,0 +1,157 @@ +"""The match_hostname() function from Python 3.3.3, essential when using SSL.""" + +# Note: This file is under the PSF license as the code comes from the python +# stdlib. http://docs.python.org/3/license.html + +import re +import sys + +# ipaddress has been backported to 2.6+ in pypi. If it is installed on the +# system, use it to handle IPAddress ServerAltnames (this was added in +# python-3.5) otherwise only do DNS matching. This allows +# backports.ssl_match_hostname to continue to be used all the way back to +# python-2.4. +try: + from pip._vendor import ipaddress +except ImportError: + ipaddress = None + +__version__ = '3.5.0.1' + + +class CertificateError(ValueError): + pass + + +def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r'.') + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + +def _to_unicode(obj): + if isinstance(obj, str) and sys.version_info < (3,): + obj = unicode(obj, encoding='ascii', errors='strict') + return obj + +def _ipaddress_match(ipname, host_ip): + """Exact matching of IP addresses. + + RFC 6125 explicitly doesn't define an algorithm for this + (section 1.7.2 - "Out of Scope"). + """ + # OpenSSL may add a trailing newline to a subjectAltName's IP address + # Divergence from upstream: ipaddress can't handle byte str + ip = ipaddress.ip_address(_to_unicode(ipname).rstrip()) + return ip == host_ip + + +def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + try: + # Divergence from upstream: ipaddress can't handle byte str + host_ip = ipaddress.ip_address(_to_unicode(hostname)) + except ValueError: + # Not an IP address (common case) + host_ip = None + except UnicodeError: + # Divergence from upstream: Have to deal with ipaddress not taking + # byte strings. addresses should be all ascii, so we consider it not + # an ipaddress in this case + host_ip = None + except AttributeError: + # Divergence from upstream: Make ipaddress library optional + if ipaddress is None: + host_ip = None + else: + raise + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if host_ip is None and _dnsname_match(value, hostname): + return + dnsnames.append(value) + elif key == 'IP Address': + if host_ip is not None and _ipaddress_match(value, host_ip): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py new file mode 100644 index 0000000..506a3c9 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py @@ -0,0 +1,449 @@ +from __future__ import absolute_import +import collections +import functools +import logging + +from ._collections import RecentlyUsedContainer +from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool +from .connectionpool import port_by_scheme +from .exceptions import LocationValueError, MaxRetryError, ProxySchemeUnknown +from .packages.six.moves.urllib.parse import urljoin +from .request import RequestMethods +from .util.url import parse_url +from .util.retry import Retry + + +__all__ = ['PoolManager', 'ProxyManager', 'proxy_from_url'] + + +log = logging.getLogger(__name__) + +SSL_KEYWORDS = ('key_file', 'cert_file', 'cert_reqs', 'ca_certs', + 'ssl_version', 'ca_cert_dir', 'ssl_context') + +# All known keyword arguments that could be provided to the pool manager, its +# pools, or the underlying connections. This is used to construct a pool key. +_key_fields = ( + 'key_scheme', # str + 'key_host', # str + 'key_port', # int + 'key_timeout', # int or float or Timeout + 'key_retries', # int or Retry + 'key_strict', # bool + 'key_block', # bool + 'key_source_address', # str + 'key_key_file', # str + 'key_cert_file', # str + 'key_cert_reqs', # str + 'key_ca_certs', # str + 'key_ssl_version', # str + 'key_ca_cert_dir', # str + 'key_ssl_context', # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext + 'key_maxsize', # int + 'key_headers', # dict + 'key__proxy', # parsed proxy url + 'key__proxy_headers', # dict + 'key_socket_options', # list of (level (int), optname (int), value (int or str)) tuples + 'key__socks_options', # dict + 'key_assert_hostname', # bool or string + 'key_assert_fingerprint', # str +) + +#: The namedtuple class used to construct keys for the connection pool. +#: All custom key schemes should include the fields in this key at a minimum. +PoolKey = collections.namedtuple('PoolKey', _key_fields) + + +def _default_key_normalizer(key_class, request_context): + """ + Create a pool key out of a request context dictionary. + + According to RFC 3986, both the scheme and host are case-insensitive. + Therefore, this function normalizes both before constructing the pool + key for an HTTPS request. If you wish to change this behaviour, provide + alternate callables to ``key_fn_by_scheme``. + + :param key_class: + The class to use when constructing the key. This should be a namedtuple + with the ``scheme`` and ``host`` keys at a minimum. + :type key_class: namedtuple + :param request_context: + A dictionary-like object that contain the context for a request. + :type request_context: dict + + :return: A namedtuple that can be used as a connection pool key. + :rtype: PoolKey + """ + # Since we mutate the dictionary, make a copy first + context = request_context.copy() + context['scheme'] = context['scheme'].lower() + context['host'] = context['host'].lower() + + # These are both dictionaries and need to be transformed into frozensets + for key in ('headers', '_proxy_headers', '_socks_options'): + if key in context and context[key] is not None: + context[key] = frozenset(context[key].items()) + + # The socket_options key may be a list and needs to be transformed into a + # tuple. + socket_opts = context.get('socket_options') + if socket_opts is not None: + context['socket_options'] = tuple(socket_opts) + + # Map the kwargs to the names in the namedtuple - this is necessary since + # namedtuples can't have fields starting with '_'. + for key in list(context.keys()): + context['key_' + key] = context.pop(key) + + # Default to ``None`` for keys missing from the context + for field in key_class._fields: + if field not in context: + context[field] = None + + return key_class(**context) + + +#: A dictionary that maps a scheme to a callable that creates a pool key. +#: This can be used to alter the way pool keys are constructed, if desired. +#: Each PoolManager makes a copy of this dictionary so they can be configured +#: globally here, or individually on the instance. +key_fn_by_scheme = { + 'http': functools.partial(_default_key_normalizer, PoolKey), + 'https': functools.partial(_default_key_normalizer, PoolKey), +} + +pool_classes_by_scheme = { + 'http': HTTPConnectionPool, + 'https': HTTPSConnectionPool, +} + + +class PoolManager(RequestMethods): + """ + Allows for arbitrary requests while transparently keeping track of + necessary connection pools for you. + + :param num_pools: + Number of connection pools to cache before discarding the least + recently used pool. + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + + :param \\**connection_pool_kw: + Additional parameters are used to create fresh + :class:`urllib3.connectionpool.ConnectionPool` instances. + + Example:: + + >>> manager = PoolManager(num_pools=2) + >>> r = manager.request('GET', 'http://google.com/') + >>> r = manager.request('GET', 'http://google.com/mail') + >>> r = manager.request('GET', 'http://yahoo.com/') + >>> len(manager.pools) + 2 + + """ + + proxy = None + + def __init__(self, num_pools=10, headers=None, **connection_pool_kw): + RequestMethods.__init__(self, headers) + self.connection_pool_kw = connection_pool_kw + self.pools = RecentlyUsedContainer(num_pools, + dispose_func=lambda p: p.close()) + + # Locally set the pool classes and keys so other PoolManagers can + # override them. + self.pool_classes_by_scheme = pool_classes_by_scheme + self.key_fn_by_scheme = key_fn_by_scheme.copy() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.clear() + # Return False to re-raise any potential exceptions + return False + + def _new_pool(self, scheme, host, port, request_context=None): + """ + Create a new :class:`ConnectionPool` based on host, port, scheme, and + any additional pool keyword arguments. + + If ``request_context`` is provided, it is provided as keyword arguments + to the pool class used. This method is used to actually create the + connection pools handed out by :meth:`connection_from_url` and + companion methods. It is intended to be overridden for customization. + """ + pool_cls = self.pool_classes_by_scheme[scheme] + if request_context is None: + request_context = self.connection_pool_kw.copy() + + # Although the context has everything necessary to create the pool, + # this function has historically only used the scheme, host, and port + # in the positional args. When an API change is acceptable these can + # be removed. + for key in ('scheme', 'host', 'port'): + request_context.pop(key, None) + + if scheme == 'http': + for kw in SSL_KEYWORDS: + request_context.pop(kw, None) + + return pool_cls(host, port, **request_context) + + def clear(self): + """ + Empty our store of pools and direct them all to close. + + This will not affect in-flight connections, but they will not be + re-used after completion. + """ + self.pools.clear() + + def connection_from_host(self, host, port=None, scheme='http', pool_kwargs=None): + """ + Get a :class:`ConnectionPool` based on the host, port, and scheme. + + If ``port`` isn't given, it will be derived from the ``scheme`` using + ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is + provided, it is merged with the instance's ``connection_pool_kw`` + variable and used to create the new connection pool, if one is + needed. + """ + + if not host: + raise LocationValueError("No host specified.") + + request_context = self._merge_pool_kwargs(pool_kwargs) + request_context['scheme'] = scheme or 'http' + if not port: + port = port_by_scheme.get(request_context['scheme'].lower(), 80) + request_context['port'] = port + request_context['host'] = host + + return self.connection_from_context(request_context) + + def connection_from_context(self, request_context): + """ + Get a :class:`ConnectionPool` based on the request context. + + ``request_context`` must at least contain the ``scheme`` key and its + value must be a key in ``key_fn_by_scheme`` instance variable. + """ + scheme = request_context['scheme'].lower() + pool_key_constructor = self.key_fn_by_scheme[scheme] + pool_key = pool_key_constructor(request_context) + + return self.connection_from_pool_key(pool_key, request_context=request_context) + + def connection_from_pool_key(self, pool_key, request_context=None): + """ + Get a :class:`ConnectionPool` based on the provided pool key. + + ``pool_key`` should be a namedtuple that only contains immutable + objects. At a minimum it must have the ``scheme``, ``host``, and + ``port`` fields. + """ + with self.pools.lock: + # If the scheme, host, or port doesn't match existing open + # connections, open a new ConnectionPool. + pool = self.pools.get(pool_key) + if pool: + return pool + + # Make a fresh ConnectionPool of the desired type + scheme = request_context['scheme'] + host = request_context['host'] + port = request_context['port'] + pool = self._new_pool(scheme, host, port, request_context=request_context) + self.pools[pool_key] = pool + + return pool + + def connection_from_url(self, url, pool_kwargs=None): + """ + Similar to :func:`urllib3.connectionpool.connection_from_url`. + + If ``pool_kwargs`` is not provided and a new pool needs to be + constructed, ``self.connection_pool_kw`` is used to initialize + the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs`` + is provided, it is used instead. Note that if a new pool does not + need to be created for the request, the provided ``pool_kwargs`` are + not used. + """ + u = parse_url(url) + return self.connection_from_host(u.host, port=u.port, scheme=u.scheme, + pool_kwargs=pool_kwargs) + + def _merge_pool_kwargs(self, override): + """ + Merge a dictionary of override values for self.connection_pool_kw. + + This does not modify self.connection_pool_kw and returns a new dict. + Any keys in the override dictionary with a value of ``None`` are + removed from the merged dictionary. + """ + base_pool_kwargs = self.connection_pool_kw.copy() + if override: + for key, value in override.items(): + if value is None: + try: + del base_pool_kwargs[key] + except KeyError: + pass + else: + base_pool_kwargs[key] = value + return base_pool_kwargs + + def urlopen(self, method, url, redirect=True, **kw): + """ + Same as :meth:`urllib3.connectionpool.HTTPConnectionPool.urlopen` + with custom cross-host redirect logic and only sends the request-uri + portion of the ``url``. + + The given ``url`` parameter must be absolute, such that an appropriate + :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it. + """ + u = parse_url(url) + conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme) + + kw['assert_same_host'] = False + kw['redirect'] = False + + if 'headers' not in kw: + kw['headers'] = self.headers.copy() + + if self.proxy is not None and u.scheme == "http": + response = conn.urlopen(method, url, **kw) + else: + response = conn.urlopen(method, u.request_uri, **kw) + + redirect_location = redirect and response.get_redirect_location() + if not redirect_location: + return response + + # Support relative URLs for redirecting. + redirect_location = urljoin(url, redirect_location) + + # RFC 7231, Section 6.4.4 + if response.status == 303: + method = 'GET' + + retries = kw.get('retries') + if not isinstance(retries, Retry): + retries = Retry.from_int(retries, redirect=redirect) + + # Strip headers marked as unsafe to forward to the redirected location. + # Check remove_headers_on_redirect to avoid a potential network call within + # conn.is_same_host() which may use socket.gethostbyname() in the future. + if (retries.remove_headers_on_redirect + and not conn.is_same_host(redirect_location)): + for header in retries.remove_headers_on_redirect: + kw['headers'].pop(header, None) + + try: + retries = retries.increment(method, url, response=response, _pool=conn) + except MaxRetryError: + if retries.raise_on_redirect: + raise + return response + + kw['retries'] = retries + kw['redirect'] = redirect + + log.info("Redirecting %s -> %s", url, redirect_location) + return self.urlopen(method, redirect_location, **kw) + + +class ProxyManager(PoolManager): + """ + Behaves just like :class:`PoolManager`, but sends all requests through + the defined proxy, using the CONNECT method for HTTPS URLs. + + :param proxy_url: + The URL of the proxy to be used. + + :param proxy_headers: + A dictionary containing headers that will be sent to the proxy. In case + of HTTP they are being sent with each request, while in the + HTTPS/CONNECT case they are sent only once. Could be used for proxy + authentication. + + Example: + >>> proxy = urllib3.ProxyManager('http://localhost:3128/') + >>> r1 = proxy.request('GET', 'http://google.com/') + >>> r2 = proxy.request('GET', 'http://httpbin.org/') + >>> len(proxy.pools) + 1 + >>> r3 = proxy.request('GET', 'https://httpbin.org/') + >>> r4 = proxy.request('GET', 'https://twitter.com/') + >>> len(proxy.pools) + 3 + + """ + + def __init__(self, proxy_url, num_pools=10, headers=None, + proxy_headers=None, **connection_pool_kw): + + if isinstance(proxy_url, HTTPConnectionPool): + proxy_url = '%s://%s:%i' % (proxy_url.scheme, proxy_url.host, + proxy_url.port) + proxy = parse_url(proxy_url) + if not proxy.port: + port = port_by_scheme.get(proxy.scheme, 80) + proxy = proxy._replace(port=port) + + if proxy.scheme not in ("http", "https"): + raise ProxySchemeUnknown(proxy.scheme) + + self.proxy = proxy + self.proxy_headers = proxy_headers or {} + + connection_pool_kw['_proxy'] = self.proxy + connection_pool_kw['_proxy_headers'] = self.proxy_headers + + super(ProxyManager, self).__init__( + num_pools, headers, **connection_pool_kw) + + def connection_from_host(self, host, port=None, scheme='http', pool_kwargs=None): + if scheme == "https": + return super(ProxyManager, self).connection_from_host( + host, port, scheme, pool_kwargs=pool_kwargs) + + return super(ProxyManager, self).connection_from_host( + self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs) + + def _set_proxy_headers(self, url, headers=None): + """ + Sets headers needed by proxies: specifically, the Accept and Host + headers. Only sets headers not provided by the user. + """ + headers_ = {'Accept': '*/*'} + + netloc = parse_url(url).netloc + if netloc: + headers_['Host'] = netloc + + if headers: + headers_.update(headers) + return headers_ + + def urlopen(self, method, url, redirect=True, **kw): + "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute." + u = parse_url(url) + + if u.scheme == "http": + # For proxied HTTPS requests, httplib sets the necessary headers + # on the CONNECT to the proxy. For HTTP, we'll definitely + # need to set 'Host' at the very least. + headers = kw.get('headers', self.headers) + kw['headers'] = self._set_proxy_headers(url, headers) + + return super(ProxyManager, self).urlopen(method, url, redirect=redirect, **kw) + + +def proxy_from_url(url, **kw): + return ProxyManager(proxy_url=url, **kw) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/request.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/request.py new file mode 100644 index 0000000..1be3334 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/request.py @@ -0,0 +1,150 @@ +from __future__ import absolute_import + +from .filepost import encode_multipart_formdata +from .packages.six.moves.urllib.parse import urlencode + + +__all__ = ['RequestMethods'] + + +class RequestMethods(object): + """ + Convenience mixin for classes who implement a :meth:`urlopen` method, such + as :class:`~urllib3.connectionpool.HTTPConnectionPool` and + :class:`~urllib3.poolmanager.PoolManager`. + + Provides behavior for making common types of HTTP request methods and + decides which type of request field encoding to use. + + Specifically, + + :meth:`.request_encode_url` is for sending requests whose fields are + encoded in the URL (such as GET, HEAD, DELETE). + + :meth:`.request_encode_body` is for sending requests whose fields are + encoded in the *body* of the request using multipart or www-form-urlencoded + (such as for POST, PUT, PATCH). + + :meth:`.request` is for making any kind of request, it will look up the + appropriate encoding format and use one of the above two methods to make + the request. + + Initializer parameters: + + :param headers: + Headers to include with all requests, unless other headers are given + explicitly. + """ + + _encode_url_methods = set(['DELETE', 'GET', 'HEAD', 'OPTIONS']) + + def __init__(self, headers=None): + self.headers = headers or {} + + def urlopen(self, method, url, body=None, headers=None, + encode_multipart=True, multipart_boundary=None, + **kw): # Abstract + raise NotImplementedError("Classes extending RequestMethods must implement " + "their own ``urlopen`` method.") + + def request(self, method, url, fields=None, headers=None, **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the appropriate encoding of + ``fields`` based on the ``method`` used. + + This is a convenience method that requires the least amount of manual + effort. It can be used in most situations, while still having the + option to drop down to more specific methods when necessary, such as + :meth:`request_encode_url`, :meth:`request_encode_body`, + or even the lowest level :meth:`urlopen`. + """ + method = method.upper() + + urlopen_kw['request_url'] = url + + if method in self._encode_url_methods: + return self.request_encode_url(method, url, fields=fields, + headers=headers, + **urlopen_kw) + else: + return self.request_encode_body(method, url, fields=fields, + headers=headers, + **urlopen_kw) + + def request_encode_url(self, method, url, fields=None, headers=None, + **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the url. This is useful for request methods like GET, HEAD, DELETE, etc. + """ + if headers is None: + headers = self.headers + + extra_kw = {'headers': headers} + extra_kw.update(urlopen_kw) + + if fields: + url += '?' + urlencode(fields) + + return self.urlopen(method, url, **extra_kw) + + def request_encode_body(self, method, url, fields=None, headers=None, + encode_multipart=True, multipart_boundary=None, + **urlopen_kw): + """ + Make a request using :meth:`urlopen` with the ``fields`` encoded in + the body. This is useful for request methods like POST, PUT, PATCH, etc. + + When ``encode_multipart=True`` (default), then + :meth:`urllib3.filepost.encode_multipart_formdata` is used to encode + the payload with the appropriate content type. Otherwise + :meth:`urllib.urlencode` is used with the + 'application/x-www-form-urlencoded' content type. + + Multipart encoding must be used when posting files, and it's reasonably + safe to use it in other times too. However, it may break request + signing, such as with OAuth. + + Supports an optional ``fields`` parameter of key/value strings AND + key/filetuple. A filetuple is a (filename, data, MIME type) tuple where + the MIME type is optional. For example:: + + fields = { + 'foo': 'bar', + 'fakefile': ('foofile.txt', 'contents of foofile'), + 'realfile': ('barfile.txt', open('realfile').read()), + 'typedfile': ('bazfile.bin', open('bazfile').read(), + 'image/jpeg'), + 'nonamefile': 'contents of nonamefile field', + } + + When uploading a file, providing a filename (the first parameter of the + tuple) is optional but recommended to best mimic behavior of browsers. + + Note that if ``headers`` are supplied, the 'Content-Type' header will + be overwritten because it depends on the dynamic random boundary string + which is used to compose the body of the request. The random boundary + string can be explicitly set with the ``multipart_boundary`` parameter. + """ + if headers is None: + headers = self.headers + + extra_kw = {'headers': {}} + + if fields: + if 'body' in urlopen_kw: + raise TypeError( + "request got values for both 'fields' and 'body', can only specify one.") + + if encode_multipart: + body, content_type = encode_multipart_formdata(fields, boundary=multipart_boundary) + else: + body, content_type = urlencode(fields), 'application/x-www-form-urlencoded' + + extra_kw['body'] = body + extra_kw['headers'] = {'Content-Type': content_type} + + extra_kw['headers'].update(headers) + extra_kw.update(urlopen_kw) + + return self.urlopen(method, url, **extra_kw) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/response.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/response.py new file mode 100644 index 0000000..9873cb9 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/response.py @@ -0,0 +1,676 @@ +from __future__ import absolute_import +from contextlib import contextmanager +import zlib +import io +import logging +from socket import timeout as SocketTimeout +from socket import error as SocketError + +from ._collections import HTTPHeaderDict +from .exceptions import ( + BodyNotHttplibCompatible, ProtocolError, DecodeError, ReadTimeoutError, + ResponseNotChunked, IncompleteRead, InvalidHeader +) +from .packages.six import string_types as basestring, binary_type, PY3 +from .packages.six.moves import http_client as httplib +from .connection import HTTPException, BaseSSLError +from .util.response import is_fp_closed, is_response_to_head + +log = logging.getLogger(__name__) + + +class DeflateDecoder(object): + + def __init__(self): + self._first_try = True + self._data = binary_type() + self._obj = zlib.decompressobj() + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + if not data: + return data + + if not self._first_try: + return self._obj.decompress(data) + + self._data += data + try: + decompressed = self._obj.decompress(data) + if decompressed: + self._first_try = False + self._data = None + return decompressed + except zlib.error: + self._first_try = False + self._obj = zlib.decompressobj(-zlib.MAX_WBITS) + try: + return self.decompress(self._data) + finally: + self._data = None + + +class GzipDecoderState(object): + + FIRST_MEMBER = 0 + OTHER_MEMBERS = 1 + SWALLOW_DATA = 2 + + +class GzipDecoder(object): + + def __init__(self): + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + self._state = GzipDecoderState.FIRST_MEMBER + + def __getattr__(self, name): + return getattr(self._obj, name) + + def decompress(self, data): + ret = binary_type() + if self._state == GzipDecoderState.SWALLOW_DATA or not data: + return ret + while True: + try: + ret += self._obj.decompress(data) + except zlib.error: + previous_state = self._state + # Ignore data after the first error + self._state = GzipDecoderState.SWALLOW_DATA + if previous_state == GzipDecoderState.OTHER_MEMBERS: + # Allow trailing garbage acceptable in other gzip clients + return ret + raise + data = self._obj.unused_data + if not data: + return ret + self._state = GzipDecoderState.OTHER_MEMBERS + self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + + +def _get_decoder(mode): + if mode == 'gzip': + return GzipDecoder() + + return DeflateDecoder() + + +class HTTPResponse(io.IOBase): + """ + HTTP Response container. + + Backwards-compatible to httplib's HTTPResponse but the response ``body`` is + loaded and decoded on-demand when the ``data`` property is accessed. This + class is also compatible with the Python standard library's :mod:`io` + module, and can hence be treated as a readable object in the context of that + framework. + + Extra parameters for behaviour not present in httplib.HTTPResponse: + + :param preload_content: + If True, the response's body will be preloaded during construction. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param original_response: + When this HTTPResponse wrapper is generated from an httplib.HTTPResponse + object, it's convenient to include the original for debug purposes. It's + otherwise unused. + + :param retries: + The retries contains the last :class:`~urllib3.util.retry.Retry` that + was used during the request. + + :param enforce_content_length: + Enforce content length checking. Body returned by server must match + value of Content-Length header, if present. Otherwise, raise error. + """ + + CONTENT_DECODERS = ['gzip', 'deflate'] + REDIRECT_STATUSES = [301, 302, 303, 307, 308] + + def __init__(self, body='', headers=None, status=0, version=0, reason=None, + strict=0, preload_content=True, decode_content=True, + original_response=None, pool=None, connection=None, msg=None, + retries=None, enforce_content_length=False, + request_method=None, request_url=None): + + if isinstance(headers, HTTPHeaderDict): + self.headers = headers + else: + self.headers = HTTPHeaderDict(headers) + self.status = status + self.version = version + self.reason = reason + self.strict = strict + self.decode_content = decode_content + self.retries = retries + self.enforce_content_length = enforce_content_length + + self._decoder = None + self._body = None + self._fp = None + self._original_response = original_response + self._fp_bytes_read = 0 + self.msg = msg + self._request_url = request_url + + if body and isinstance(body, (basestring, binary_type)): + self._body = body + + self._pool = pool + self._connection = connection + + if hasattr(body, 'read'): + self._fp = body + + # Are we using the chunked-style of transfer encoding? + self.chunked = False + self.chunk_left = None + tr_enc = self.headers.get('transfer-encoding', '').lower() + # Don't incur the penalty of creating a list and then discarding it + encodings = (enc.strip() for enc in tr_enc.split(",")) + if "chunked" in encodings: + self.chunked = True + + # Determine length of response + self.length_remaining = self._init_length(request_method) + + # If requested, preload the body. + if preload_content and not self._body: + self._body = self.read(decode_content=decode_content) + + def get_redirect_location(self): + """ + Should we redirect and where to? + + :returns: Truthy redirect location string if we got a redirect status + code and valid location. ``None`` if redirect status and no + location. ``False`` if not a redirect status code. + """ + if self.status in self.REDIRECT_STATUSES: + return self.headers.get('location') + + return False + + def release_conn(self): + if not self._pool or not self._connection: + return + + self._pool._put_conn(self._connection) + self._connection = None + + @property + def data(self): + # For backwords-compat with earlier urllib3 0.4 and earlier. + if self._body: + return self._body + + if self._fp: + return self.read(cache_content=True) + + @property + def connection(self): + return self._connection + + def isclosed(self): + return is_fp_closed(self._fp) + + def tell(self): + """ + Obtain the number of bytes pulled over the wire so far. May differ from + the amount of content returned by :meth:``HTTPResponse.read`` if bytes + are encoded on the wire (e.g, compressed). + """ + return self._fp_bytes_read + + def _init_length(self, request_method): + """ + Set initial length value for Response content if available. + """ + length = self.headers.get('content-length') + + if length is not None: + if self.chunked: + # This Response will fail with an IncompleteRead if it can't be + # received as chunked. This method falls back to attempt reading + # the response before raising an exception. + log.warning("Received response with both Content-Length and " + "Transfer-Encoding set. This is expressly forbidden " + "by RFC 7230 sec 3.3.2. Ignoring Content-Length and " + "attempting to process response as Transfer-Encoding: " + "chunked.") + return None + + try: + # RFC 7230 section 3.3.2 specifies multiple content lengths can + # be sent in a single Content-Length header + # (e.g. Content-Length: 42, 42). This line ensures the values + # are all valid ints and that as long as the `set` length is 1, + # all values are the same. Otherwise, the header is invalid. + lengths = set([int(val) for val in length.split(',')]) + if len(lengths) > 1: + raise InvalidHeader("Content-Length contained multiple " + "unmatching values (%s)" % length) + length = lengths.pop() + except ValueError: + length = None + else: + if length < 0: + length = None + + # Convert status to int for comparison + # In some cases, httplib returns a status of "_UNKNOWN" + try: + status = int(self.status) + except ValueError: + status = 0 + + # Check for responses that shouldn't include a body + if status in (204, 304) or 100 <= status < 200 or request_method == 'HEAD': + length = 0 + + return length + + def _init_decoder(self): + """ + Set-up the _decoder attribute if necessary. + """ + # Note: content-encoding value should be case-insensitive, per RFC 7230 + # Section 3.2 + content_encoding = self.headers.get('content-encoding', '').lower() + if self._decoder is None and content_encoding in self.CONTENT_DECODERS: + self._decoder = _get_decoder(content_encoding) + + def _decode(self, data, decode_content, flush_decoder): + """ + Decode the data passed in and potentially flush the decoder. + """ + try: + if decode_content and self._decoder: + data = self._decoder.decompress(data) + except (IOError, zlib.error) as e: + content_encoding = self.headers.get('content-encoding', '').lower() + raise DecodeError( + "Received response with content-encoding: %s, but " + "failed to decode it." % content_encoding, e) + + if flush_decoder and decode_content: + data += self._flush_decoder() + + return data + + def _flush_decoder(self): + """ + Flushes the decoder. Should only be called if the decoder is actually + being used. + """ + if self._decoder: + buf = self._decoder.decompress(b'') + return buf + self._decoder.flush() + + return b'' + + @contextmanager + def _error_catcher(self): + """ + Catch low-level python exceptions, instead re-raising urllib3 + variants, so that low-level exceptions are not leaked in the + high-level api. + + On exit, release the connection back to the pool. + """ + clean_exit = False + + try: + try: + yield + + except SocketTimeout: + # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but + # there is yet no clean way to get at it from this context. + raise ReadTimeoutError(self._pool, None, 'Read timed out.') + + except BaseSSLError as e: + # FIXME: Is there a better way to differentiate between SSLErrors? + if 'read operation timed out' not in str(e): # Defensive: + # This shouldn't happen but just in case we're missing an edge + # case, let's avoid swallowing SSL errors. + raise + + raise ReadTimeoutError(self._pool, None, 'Read timed out.') + + except (HTTPException, SocketError) as e: + # This includes IncompleteRead. + raise ProtocolError('Connection broken: %r' % e, e) + + # If no exception is thrown, we should avoid cleaning up + # unnecessarily. + clean_exit = True + finally: + # If we didn't terminate cleanly, we need to throw away our + # connection. + if not clean_exit: + # The response may not be closed but we're not going to use it + # anymore so close it now to ensure that the connection is + # released back to the pool. + if self._original_response: + self._original_response.close() + + # Closing the response may not actually be sufficient to close + # everything, so if we have a hold of the connection close that + # too. + if self._connection: + self._connection.close() + + # If we hold the original response but it's closed now, we should + # return the connection back to the pool. + if self._original_response and self._original_response.isclosed(): + self.release_conn() + + def read(self, amt=None, decode_content=None, cache_content=False): + """ + Similar to :meth:`httplib.HTTPResponse.read`, but with two additional + parameters: ``decode_content`` and ``cache_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + + :param cache_content: + If True, will save the returned data such that the same result is + returned despite of the state of the underlying file object. This + is useful if you want the ``.data`` property to continue working + after having ``.read()`` the file object. (Overridden if ``amt`` is + set.) + """ + self._init_decoder() + if decode_content is None: + decode_content = self.decode_content + + if self._fp is None: + return + + flush_decoder = False + data = None + + with self._error_catcher(): + if amt is None: + # cStringIO doesn't like amt=None + data = self._fp.read() + flush_decoder = True + else: + cache_content = False + data = self._fp.read(amt) + if amt != 0 and not data: # Platform-specific: Buggy versions of Python. + # Close the connection when no data is returned + # + # This is redundant to what httplib/http.client _should_ + # already do. However, versions of python released before + # December 15, 2012 (http://bugs.python.org/issue16298) do + # not properly close the connection in all cases. There is + # no harm in redundantly calling close. + self._fp.close() + flush_decoder = True + if self.enforce_content_length and self.length_remaining not in (0, None): + # This is an edge case that httplib failed to cover due + # to concerns of backward compatibility. We're + # addressing it here to make sure IncompleteRead is + # raised during streaming, so all calls with incorrect + # Content-Length are caught. + raise IncompleteRead(self._fp_bytes_read, self.length_remaining) + + if data: + self._fp_bytes_read += len(data) + if self.length_remaining is not None: + self.length_remaining -= len(data) + + data = self._decode(data, decode_content, flush_decoder) + + if cache_content: + self._body = data + + return data + + def stream(self, amt=2**16, decode_content=None): + """ + A generator wrapper for the read() method. A call will block until + ``amt`` bytes have been read from the connection or until the + connection is closed. + + :param amt: + How much of the content to read. The generator will return up to + much data per iteration, but may return less. This is particularly + likely when using compressed data. However, the empty string will + never be returned. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + if self.chunked and self.supports_chunked_reads(): + for line in self.read_chunked(amt, decode_content=decode_content): + yield line + else: + while not is_fp_closed(self._fp): + data = self.read(amt=amt, decode_content=decode_content) + + if data: + yield data + + @classmethod + def from_httplib(ResponseCls, r, **response_kw): + """ + Given an :class:`httplib.HTTPResponse` instance ``r``, return a + corresponding :class:`urllib3.response.HTTPResponse` object. + + Remaining parameters are passed to the HTTPResponse constructor, along + with ``original_response=r``. + """ + headers = r.msg + + if not isinstance(headers, HTTPHeaderDict): + if PY3: # Python 3 + headers = HTTPHeaderDict(headers.items()) + else: # Python 2 + headers = HTTPHeaderDict.from_httplib(headers) + + # HTTPResponse objects in Python 3 don't have a .strict attribute + strict = getattr(r, 'strict', 0) + resp = ResponseCls(body=r, + headers=headers, + status=r.status, + version=r.version, + reason=r.reason, + strict=strict, + original_response=r, + **response_kw) + return resp + + # Backwards-compatibility methods for httplib.HTTPResponse + def getheaders(self): + return self.headers + + def getheader(self, name, default=None): + return self.headers.get(name, default) + + # Backwards compatibility for http.cookiejar + def info(self): + return self.headers + + # Overrides from io.IOBase + def close(self): + if not self.closed: + self._fp.close() + + if self._connection: + self._connection.close() + + @property + def closed(self): + if self._fp is None: + return True + elif hasattr(self._fp, 'isclosed'): + return self._fp.isclosed() + elif hasattr(self._fp, 'closed'): + return self._fp.closed + else: + return True + + def fileno(self): + if self._fp is None: + raise IOError("HTTPResponse has no file to get a fileno from") + elif hasattr(self._fp, "fileno"): + return self._fp.fileno() + else: + raise IOError("The file-like object this HTTPResponse is wrapped " + "around has no file descriptor") + + def flush(self): + if self._fp is not None and hasattr(self._fp, 'flush'): + return self._fp.flush() + + def readable(self): + # This method is required for `io` module compatibility. + return True + + def readinto(self, b): + # This method is required for `io` module compatibility. + temp = self.read(len(b)) + if len(temp) == 0: + return 0 + else: + b[:len(temp)] = temp + return len(temp) + + def supports_chunked_reads(self): + """ + Checks if the underlying file-like object looks like a + httplib.HTTPResponse object. We do this by testing for the fp + attribute. If it is present we assume it returns raw chunks as + processed by read_chunked(). + """ + return hasattr(self._fp, 'fp') + + def _update_chunk_length(self): + # First, we'll figure out length of a chunk and then + # we'll try to read it from socket. + if self.chunk_left is not None: + return + line = self._fp.fp.readline() + line = line.split(b';', 1)[0] + try: + self.chunk_left = int(line, 16) + except ValueError: + # Invalid chunked protocol response, abort. + self.close() + raise httplib.IncompleteRead(line) + + def _handle_chunk(self, amt): + returned_chunk = None + if amt is None: + chunk = self._fp._safe_read(self.chunk_left) + returned_chunk = chunk + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + elif amt < self.chunk_left: + value = self._fp._safe_read(amt) + self.chunk_left = self.chunk_left - amt + returned_chunk = value + elif amt == self.chunk_left: + value = self._fp._safe_read(amt) + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + returned_chunk = value + else: # amt > self.chunk_left + returned_chunk = self._fp._safe_read(self.chunk_left) + self._fp._safe_read(2) # Toss the CRLF at the end of the chunk. + self.chunk_left = None + return returned_chunk + + def read_chunked(self, amt=None, decode_content=None): + """ + Similar to :meth:`HTTPResponse.read`, but with an additional + parameter: ``decode_content``. + + :param amt: + How much of the content to read. If specified, caching is skipped + because it doesn't make sense to cache partial content as the full + response. + + :param decode_content: + If True, will attempt to decode the body based on the + 'content-encoding' header. + """ + self._init_decoder() + # FIXME: Rewrite this method and make it a class with a better structured logic. + if not self.chunked: + raise ResponseNotChunked( + "Response is not chunked. " + "Header 'transfer-encoding: chunked' is missing.") + if not self.supports_chunked_reads(): + raise BodyNotHttplibCompatible( + "Body should be httplib.HTTPResponse like. " + "It should have have an fp attribute which returns raw chunks.") + + with self._error_catcher(): + # Don't bother reading the body of a HEAD request. + if self._original_response and is_response_to_head(self._original_response): + self._original_response.close() + return + + # If a response is already read and closed + # then return immediately. + if self._fp.fp is None: + return + + while True: + self._update_chunk_length() + if self.chunk_left == 0: + break + chunk = self._handle_chunk(amt) + decoded = self._decode(chunk, decode_content=decode_content, + flush_decoder=False) + if decoded: + yield decoded + + if decode_content: + # On CPython and PyPy, we should never need to flush the + # decoder. However, on Jython we *might* need to, so + # lets defensively do it anyway. + decoded = self._flush_decoder() + if decoded: # Platform-specific: Jython. + yield decoded + + # Chunk content ends with \r\n: discard it. + while True: + line = self._fp.fp.readline() + if not line: + # Some sites may not end with '\r\n'. + break + if line == b'\r\n': + break + + # We read everything; close the "file". + if self._original_response: + self._original_response.close() + + def geturl(self): + """ + Returns the URL that was the source of this response. + If the request that generated this response redirected, this method + will return the final redirect location. + """ + if self.retries is not None and len(self.retries.history): + return self.retries.history[-1].redirect_location + else: + return self._request_url diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py new file mode 100644 index 0000000..2f2770b --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py @@ -0,0 +1,54 @@ +from __future__ import absolute_import +# For backwards compatibility, provide imports that used to be here. +from .connection import is_connection_dropped +from .request import make_headers +from .response import is_fp_closed +from .ssl_ import ( + SSLContext, + HAS_SNI, + IS_PYOPENSSL, + IS_SECURETRANSPORT, + assert_fingerprint, + resolve_cert_reqs, + resolve_ssl_version, + ssl_wrap_socket, +) +from .timeout import ( + current_time, + Timeout, +) + +from .retry import Retry +from .url import ( + get_host, + parse_url, + split_first, + Url, +) +from .wait import ( + wait_for_read, + wait_for_write +) + +__all__ = ( + 'HAS_SNI', + 'IS_PYOPENSSL', + 'IS_SECURETRANSPORT', + 'SSLContext', + 'Retry', + 'Timeout', + 'Url', + 'assert_fingerprint', + 'current_time', + 'is_connection_dropped', + 'is_fp_closed', + 'get_host', + 'parse_url', + 'make_headers', + 'resolve_cert_reqs', + 'resolve_ssl_version', + 'split_first', + 'ssl_wrap_socket', + 'wait_for_read', + 'wait_for_write' +) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py new file mode 100644 index 0000000..5cf488f --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py @@ -0,0 +1,126 @@ +from __future__ import absolute_import +import socket +from .wait import NoWayToWaitForSocketError, wait_for_read + + +def is_connection_dropped(conn): # Platform-specific + """ + Returns True if the connection is dropped and should be closed. + + :param conn: + :class:`httplib.HTTPConnection` object. + + Note: For platforms like AppEngine, this will always return ``False`` to + let the platform handle connection recycling transparently for us. + """ + sock = getattr(conn, 'sock', False) + if sock is False: # Platform-specific: AppEngine + return False + if sock is None: # Connection already closed (such as by httplib). + return True + try: + # Returns True if readable, which here means it's been dropped + return wait_for_read(sock, timeout=0.0) + except NoWayToWaitForSocketError: # Platform-specific: AppEngine + return False + + +# This function is copied from socket.py in the Python 2.7 standard +# library test suite. Added to its signature is only `socket_options`. +# One additional modification is that we avoid binding to IPv6 servers +# discovered in DNS if the system doesn't have IPv6 functionality. +def create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, + source_address=None, socket_options=None): + """Connect to *address* and return the socket object. + + Convenience function. Connect to *address* (a 2-tuple ``(host, + port)``) and return the socket object. Passing the optional + *timeout* parameter will set the timeout on the socket instance + before attempting to connect. If no *timeout* is supplied, the + global default timeout setting returned by :func:`getdefaulttimeout` + is used. If *source_address* is set it must be a tuple of (host, port) + for the socket to bind as a source address before making the connection. + An host of '' or port 0 tells the OS to use the default. + """ + + host, port = address + if host.startswith('['): + host = host.strip('[]') + err = None + + # Using the value from allowed_gai_family() in the context of getaddrinfo lets + # us select whether to work with IPv4 DNS records, IPv6 records, or both. + # The original create_connection function always returns all records. + family = allowed_gai_family() + + for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): + af, socktype, proto, canonname, sa = res + sock = None + try: + sock = socket.socket(af, socktype, proto) + + # If provided, set socket level options before connecting. + _set_socket_options(sock, socket_options) + + if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT: + sock.settimeout(timeout) + if source_address: + sock.bind(source_address) + sock.connect(sa) + return sock + + except socket.error as e: + err = e + if sock is not None: + sock.close() + sock = None + + if err is not None: + raise err + + raise socket.error("getaddrinfo returns an empty list") + + +def _set_socket_options(sock, options): + if options is None: + return + + for opt in options: + sock.setsockopt(*opt) + + +def allowed_gai_family(): + """This function is designed to work in the context of + getaddrinfo, where family=socket.AF_UNSPEC is the default and + will perform a DNS search for both IPv6 and IPv4 records.""" + + family = socket.AF_INET + if HAS_IPV6: + family = socket.AF_UNSPEC + return family + + +def _has_ipv6(host): + """ Returns True if the system can bind an IPv6 address. """ + sock = None + has_ipv6 = False + + if socket.has_ipv6: + # has_ipv6 returns true if cPython was compiled with IPv6 support. + # It does not tell us if the system has IPv6 support enabled. To + # determine that we must bind to an IPv6 address. + # https://github.com/shazow/urllib3/pull/611 + # https://bugs.python.org/issue658327 + try: + sock = socket.socket(socket.AF_INET6) + sock.bind((host, 0)) + has_ipv6 = True + except Exception: + pass + + if sock: + sock.close() + return has_ipv6 + + +HAS_IPV6 = _has_ipv6('::1') diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py new file mode 100644 index 0000000..d3d379a --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py @@ -0,0 +1,21 @@ +import collections +from ..packages import six +from ..packages.six.moves import queue + +if six.PY2: + # Queue is imported for side effects on MS Windows. See issue #229. + import Queue as _unused_module_Queue # noqa: F401 + + +class LifoQueue(queue.Queue): + def _init(self, _): + self.queue = collections.deque() + + def _qsize(self, len=len): + return len(self.queue) + + def _put(self, item): + self.queue.append(item) + + def _get(self): + return self.queue.pop() diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/request.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/request.py new file mode 100644 index 0000000..3ddfcd5 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/request.py @@ -0,0 +1,118 @@ +from __future__ import absolute_import +from base64 import b64encode + +from ..packages.six import b, integer_types +from ..exceptions import UnrewindableBodyError + +ACCEPT_ENCODING = 'gzip,deflate' +_FAILEDTELL = object() + + +def make_headers(keep_alive=None, accept_encoding=None, user_agent=None, + basic_auth=None, proxy_basic_auth=None, disable_cache=None): + """ + Shortcuts for generating request headers. + + :param keep_alive: + If ``True``, adds 'connection: keep-alive' header. + + :param accept_encoding: + Can be a boolean, list, or string. + ``True`` translates to 'gzip,deflate'. + List will get joined by comma. + String will be used as provided. + + :param user_agent: + String representing the user-agent you want, such as + "python-urllib3/0.6" + + :param basic_auth: + Colon-separated username:password string for 'authorization: basic ...' + auth header. + + :param proxy_basic_auth: + Colon-separated username:password string for 'proxy-authorization: basic ...' + auth header. + + :param disable_cache: + If ``True``, adds 'cache-control: no-cache' header. + + Example:: + + >>> make_headers(keep_alive=True, user_agent="Batman/1.0") + {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} + >>> make_headers(accept_encoding=True) + {'accept-encoding': 'gzip,deflate'} + """ + headers = {} + if accept_encoding: + if isinstance(accept_encoding, str): + pass + elif isinstance(accept_encoding, list): + accept_encoding = ','.join(accept_encoding) + else: + accept_encoding = ACCEPT_ENCODING + headers['accept-encoding'] = accept_encoding + + if user_agent: + headers['user-agent'] = user_agent + + if keep_alive: + headers['connection'] = 'keep-alive' + + if basic_auth: + headers['authorization'] = 'Basic ' + \ + b64encode(b(basic_auth)).decode('utf-8') + + if proxy_basic_auth: + headers['proxy-authorization'] = 'Basic ' + \ + b64encode(b(proxy_basic_auth)).decode('utf-8') + + if disable_cache: + headers['cache-control'] = 'no-cache' + + return headers + + +def set_file_position(body, pos): + """ + If a position is provided, move file to that point. + Otherwise, we'll attempt to record a position for future use. + """ + if pos is not None: + rewind_body(body, pos) + elif getattr(body, 'tell', None) is not None: + try: + pos = body.tell() + except (IOError, OSError): + # This differentiates from None, allowing us to catch + # a failed `tell()` later when trying to rewind the body. + pos = _FAILEDTELL + + return pos + + +def rewind_body(body, body_pos): + """ + Attempt to rewind body to a certain position. + Primarily used for request redirects and retries. + + :param body: + File-like object that supports seek. + + :param int pos: + Position to seek to in file. + """ + body_seek = getattr(body, 'seek', None) + if body_seek is not None and isinstance(body_pos, integer_types): + try: + body_seek(body_pos) + except (IOError, OSError): + raise UnrewindableBodyError("An error occurred when rewinding request " + "body for redirect/retry.") + elif body_pos is _FAILEDTELL: + raise UnrewindableBodyError("Unable to record file position for rewinding " + "request body during a redirect/retry.") + else: + raise ValueError("body_pos must be of type integer, " + "instead it was %s." % type(body_pos)) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/response.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/response.py new file mode 100644 index 0000000..67cf730 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/response.py @@ -0,0 +1,81 @@ +from __future__ import absolute_import +from ..packages.six.moves import http_client as httplib + +from ..exceptions import HeaderParsingError + + +def is_fp_closed(obj): + """ + Checks whether a given file-like object is closed. + + :param obj: + The file-like object to check. + """ + + try: + # Check `isclosed()` first, in case Python3 doesn't set `closed`. + # GH Issue #928 + return obj.isclosed() + except AttributeError: + pass + + try: + # Check via the official file-like-object way. + return obj.closed + except AttributeError: + pass + + try: + # Check if the object is a container for another file-like object that + # gets released on exhaustion (e.g. HTTPResponse). + return obj.fp is None + except AttributeError: + pass + + raise ValueError("Unable to determine whether fp is closed.") + + +def assert_header_parsing(headers): + """ + Asserts whether all headers have been successfully parsed. + Extracts encountered errors from the result of parsing headers. + + Only works on Python 3. + + :param headers: Headers to verify. + :type headers: `httplib.HTTPMessage`. + + :raises urllib3.exceptions.HeaderParsingError: + If parsing errors are found. + """ + + # This will fail silently if we pass in the wrong kind of parameter. + # To make debugging easier add an explicit check. + if not isinstance(headers, httplib.HTTPMessage): + raise TypeError('expected httplib.Message, got {0}.'.format( + type(headers))) + + defects = getattr(headers, 'defects', None) + get_payload = getattr(headers, 'get_payload', None) + + unparsed_data = None + if get_payload: # Platform-specific: Python 3. + unparsed_data = get_payload() + + if defects or unparsed_data: + raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) + + +def is_response_to_head(response): + """ + Checks whether the request of a response has been a HEAD-request. + Handles the quirks of AppEngine. + + :param conn: + :type conn: :class:`httplib.HTTPResponse` + """ + # FIXME: Can we do this somehow without accessing private httplib _method? + method = response._method + if isinstance(method, int): # Platform-specific: Appengine + return method == 3 + return method.upper() == 'HEAD' diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py new file mode 100644 index 0000000..7ad3dc6 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py @@ -0,0 +1,411 @@ +from __future__ import absolute_import +import time +import logging +from collections import namedtuple +from itertools import takewhile +import email +import re + +from ..exceptions import ( + ConnectTimeoutError, + MaxRetryError, + ProtocolError, + ReadTimeoutError, + ResponseError, + InvalidHeader, +) +from ..packages import six + + +log = logging.getLogger(__name__) + + +# Data structure for representing the metadata of requests that result in a retry. +RequestHistory = namedtuple('RequestHistory', ["method", "url", "error", + "status", "redirect_location"]) + + +class Retry(object): + """ Retry configuration. + + Each retry attempt will create a new Retry object with updated values, so + they can be safely reused. + + Retries can be defined as a default for a pool:: + + retries = Retry(connect=5, read=2, redirect=5) + http = PoolManager(retries=retries) + response = http.request('GET', 'http://example.com/') + + Or per-request (which overrides the default for the pool):: + + response = http.request('GET', 'http://example.com/', retries=Retry(10)) + + Retries can be disabled by passing ``False``:: + + response = http.request('GET', 'http://example.com/', retries=False) + + Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless + retries are disabled, in which case the causing exception will be raised. + + :param int total: + Total number of retries to allow. Takes precedence over other counts. + + Set to ``None`` to remove this constraint and fall back on other + counts. It's a good idea to set this to some sensibly-high value to + account for unexpected edge cases and avoid infinite retry loops. + + Set to ``0`` to fail on the first retry. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int connect: + How many connection-related errors to retry on. + + These are errors raised before the request is sent to the remote server, + which we assume has not triggered the server to process the request. + + Set to ``0`` to fail on the first retry of this type. + + :param int read: + How many times to retry on read errors. + + These errors are raised after the request was sent to the server, so the + request may have side-effects. + + Set to ``0`` to fail on the first retry of this type. + + :param int redirect: + How many redirects to perform. Limit this to avoid infinite redirect + loops. + + A redirect is a HTTP response with a status code 301, 302, 303, 307 or + 308. + + Set to ``0`` to fail on the first retry of this type. + + Set to ``False`` to disable and imply ``raise_on_redirect=False``. + + :param int status: + How many times to retry on bad status codes. + + These are retries made on responses, where status code matches + ``status_forcelist``. + + Set to ``0`` to fail on the first retry of this type. + + :param iterable method_whitelist: + Set of uppercased HTTP method verbs that we should retry on. + + By default, we only retry on methods which are considered to be + idempotent (multiple requests with the same parameters end with the + same state). See :attr:`Retry.DEFAULT_METHOD_WHITELIST`. + + Set to a ``False`` value to retry on any verb. + + :param iterable status_forcelist: + A set of integer HTTP status codes that we should force a retry on. + A retry is initiated if the request method is in ``method_whitelist`` + and the response status code is in ``status_forcelist``. + + By default, this is disabled with ``None``. + + :param float backoff_factor: + A backoff factor to apply between attempts after the second try + (most errors are resolved immediately by a second try without a + delay). urllib3 will sleep for:: + + {backoff factor} * (2 ^ ({number of total retries} - 1)) + + seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep + for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer + than :attr:`Retry.BACKOFF_MAX`. + + By default, backoff is disabled (set to 0). + + :param bool raise_on_redirect: Whether, if the number of redirects is + exhausted, to raise a MaxRetryError, or to return a response with a + response code in the 3xx range. + + :param bool raise_on_status: Similar meaning to ``raise_on_redirect``: + whether we should raise an exception, or return a response, + if status falls in ``status_forcelist`` range and retries have + been exhausted. + + :param tuple history: The history of the request encountered during + each call to :meth:`~Retry.increment`. The list is in the order + the requests occurred. Each list item is of class :class:`RequestHistory`. + + :param bool respect_retry_after_header: + Whether to respect Retry-After header on status codes defined as + :attr:`Retry.RETRY_AFTER_STATUS_CODES` or not. + + :param iterable remove_headers_on_redirect: + Sequence of headers to remove from the request when a response + indicating a redirect is returned before firing off the redirected + request. + """ + + DEFAULT_METHOD_WHITELIST = frozenset([ + 'HEAD', 'GET', 'PUT', 'DELETE', 'OPTIONS', 'TRACE']) + + RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503]) + + DEFAULT_REDIRECT_HEADERS_BLACKLIST = frozenset(['Authorization']) + + #: Maximum backoff time. + BACKOFF_MAX = 120 + + def __init__(self, total=10, connect=None, read=None, redirect=None, status=None, + method_whitelist=DEFAULT_METHOD_WHITELIST, status_forcelist=None, + backoff_factor=0, raise_on_redirect=True, raise_on_status=True, + history=None, respect_retry_after_header=True, + remove_headers_on_redirect=DEFAULT_REDIRECT_HEADERS_BLACKLIST): + + self.total = total + self.connect = connect + self.read = read + self.status = status + + if redirect is False or total is False: + redirect = 0 + raise_on_redirect = False + + self.redirect = redirect + self.status_forcelist = status_forcelist or set() + self.method_whitelist = method_whitelist + self.backoff_factor = backoff_factor + self.raise_on_redirect = raise_on_redirect + self.raise_on_status = raise_on_status + self.history = history or tuple() + self.respect_retry_after_header = respect_retry_after_header + self.remove_headers_on_redirect = remove_headers_on_redirect + + def new(self, **kw): + params = dict( + total=self.total, + connect=self.connect, read=self.read, redirect=self.redirect, status=self.status, + method_whitelist=self.method_whitelist, + status_forcelist=self.status_forcelist, + backoff_factor=self.backoff_factor, + raise_on_redirect=self.raise_on_redirect, + raise_on_status=self.raise_on_status, + history=self.history, + remove_headers_on_redirect=self.remove_headers_on_redirect + ) + params.update(kw) + return type(self)(**params) + + @classmethod + def from_int(cls, retries, redirect=True, default=None): + """ Backwards-compatibility for the old retries format.""" + if retries is None: + retries = default if default is not None else cls.DEFAULT + + if isinstance(retries, Retry): + return retries + + redirect = bool(redirect) and None + new_retries = cls(retries, redirect=redirect) + log.debug("Converted retries value: %r -> %r", retries, new_retries) + return new_retries + + def get_backoff_time(self): + """ Formula for computing the current backoff + + :rtype: float + """ + # We want to consider only the last consecutive errors sequence (Ignore redirects). + consecutive_errors_len = len(list(takewhile(lambda x: x.redirect_location is None, + reversed(self.history)))) + if consecutive_errors_len <= 1: + return 0 + + backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1)) + return min(self.BACKOFF_MAX, backoff_value) + + def parse_retry_after(self, retry_after): + # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = int(retry_after) + else: + retry_date_tuple = email.utils.parsedate(retry_after) + if retry_date_tuple is None: + raise InvalidHeader("Invalid Retry-After header: %s" % retry_after) + retry_date = time.mktime(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: + seconds = 0 + + return seconds + + def get_retry_after(self, response): + """ Get the value of Retry-After in seconds. """ + + retry_after = response.getheader("Retry-After") + + if retry_after is None: + return None + + return self.parse_retry_after(retry_after) + + def sleep_for_retry(self, response=None): + retry_after = self.get_retry_after(response) + if retry_after: + time.sleep(retry_after) + return True + + return False + + def _sleep_backoff(self): + backoff = self.get_backoff_time() + if backoff <= 0: + return + time.sleep(backoff) + + def sleep(self, response=None): + """ Sleep between retry attempts. + + This method will respect a server's ``Retry-After`` response header + and sleep the duration of the time requested. If that is not present, it + will use an exponential backoff. By default, the backoff factor is 0 and + this method will return immediately. + """ + + if response: + slept = self.sleep_for_retry(response) + if slept: + return + + self._sleep_backoff() + + def _is_connection_error(self, err): + """ Errors when we're fairly sure that the server did not receive the + request, so it should be safe to retry. + """ + return isinstance(err, ConnectTimeoutError) + + def _is_read_error(self, err): + """ Errors that occur after the request has been started, so we should + assume that the server began processing it. + """ + return isinstance(err, (ReadTimeoutError, ProtocolError)) + + def _is_method_retryable(self, method): + """ Checks if a given HTTP method should be retried upon, depending if + it is included on the method whitelist. + """ + if self.method_whitelist and method.upper() not in self.method_whitelist: + return False + + return True + + def is_retry(self, method, status_code, has_retry_after=False): + """ Is this method/status code retryable? (Based on whitelists and control + variables such as the number of total retries to allow, whether to + respect the Retry-After header, whether this header is present, and + whether the returned status code is on the list of status codes to + be retried upon on the presence of the aforementioned header) + """ + if not self._is_method_retryable(method): + return False + + if self.status_forcelist and status_code in self.status_forcelist: + return True + + return (self.total and self.respect_retry_after_header and + has_retry_after and (status_code in self.RETRY_AFTER_STATUS_CODES)) + + def is_exhausted(self): + """ Are we out of retries? """ + retry_counts = (self.total, self.connect, self.read, self.redirect, self.status) + retry_counts = list(filter(None, retry_counts)) + if not retry_counts: + return False + + return min(retry_counts) < 0 + + def increment(self, method=None, url=None, response=None, error=None, + _pool=None, _stacktrace=None): + """ Return a new Retry object with incremented retry counters. + + :param response: A response object, or None, if the server did not + return a response. + :type response: :class:`~urllib3.response.HTTPResponse` + :param Exception error: An error encountered during the request, or + None if the response was received successfully. + + :return: A new ``Retry`` object. + """ + if self.total is False and error: + # Disabled, indicate to re-raise the error. + raise six.reraise(type(error), error, _stacktrace) + + total = self.total + if total is not None: + total -= 1 + + connect = self.connect + read = self.read + redirect = self.redirect + status_count = self.status + cause = 'unknown' + status = None + redirect_location = None + + if error and self._is_connection_error(error): + # Connect retry? + if connect is False: + raise six.reraise(type(error), error, _stacktrace) + elif connect is not None: + connect -= 1 + + elif error and self._is_read_error(error): + # Read retry? + if read is False or not self._is_method_retryable(method): + raise six.reraise(type(error), error, _stacktrace) + elif read is not None: + read -= 1 + + elif response and response.get_redirect_location(): + # Redirect retry? + if redirect is not None: + redirect -= 1 + cause = 'too many redirects' + redirect_location = response.get_redirect_location() + status = response.status + + else: + # Incrementing because of a server error like a 500 in + # status_forcelist and a the given method is in the whitelist + cause = ResponseError.GENERIC_ERROR + if response and response.status: + if status_count is not None: + status_count -= 1 + cause = ResponseError.SPECIFIC_ERROR.format( + status_code=response.status) + status = response.status + + history = self.history + (RequestHistory(method, url, error, status, redirect_location),) + + new_retry = self.new( + total=total, + connect=connect, read=read, redirect=redirect, status=status_count, + history=history) + + if new_retry.is_exhausted(): + raise MaxRetryError(_pool, url, error or ResponseError(cause)) + + log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) + + return new_retry + + def __repr__(self): + return ('{cls.__name__}(total={self.total}, connect={self.connect}, ' + 'read={self.read}, redirect={self.redirect}, status={self.status})').format( + cls=type(self), self=self) + + +# For backwards compatibility (equivalent to pre-v1.9): +Retry.DEFAULT = Retry(3) diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py new file mode 100644 index 0000000..3254280 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py @@ -0,0 +1,396 @@ +from __future__ import absolute_import +import errno +import warnings +import hmac +import socket + +from binascii import hexlify, unhexlify +from hashlib import md5, sha1, sha256 + +from ..exceptions import SSLError, InsecurePlatformWarning, SNIMissingWarning +from ..packages import six + + +SSLContext = None +HAS_SNI = False +IS_PYOPENSSL = False +IS_SECURETRANSPORT = False + +# Maps the length of a digest to a possible hash function producing this digest +HASHFUNC_MAP = { + 32: md5, + 40: sha1, + 64: sha256, +} + + +def _const_compare_digest_backport(a, b): + """ + Compare two digests of equal length in constant time. + + The digests must be of type str/bytes. + Returns True if the digests match, and False otherwise. + """ + result = abs(len(a) - len(b)) + for l, r in zip(bytearray(a), bytearray(b)): + result |= l ^ r + return result == 0 + + +_const_compare_digest = getattr(hmac, 'compare_digest', + _const_compare_digest_backport) + + +try: # Test for SSL features + import ssl + from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23 + from ssl import HAS_SNI # Has SNI? +except ImportError: + pass + + +try: + from ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_COMPRESSION +except ImportError: + OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000 + OP_NO_COMPRESSION = 0x20000 + + +# Python 2.7 and earlier didn't have inet_pton on non-Linux +# so we fallback on inet_aton in those cases. This means that +# we can only detect IPv4 addresses in this case. +if hasattr(socket, 'inet_pton'): + inet_pton = socket.inet_pton +else: + # Maybe we can use ipaddress if the user has urllib3[secure]? + try: + from pip._vendor import ipaddress + + def inet_pton(_, host): + if isinstance(host, six.binary_type): + host = host.decode('ascii') + return ipaddress.ip_address(host) + + except ImportError: # Platform-specific: Non-Linux + def inet_pton(_, host): + return socket.inet_aton(host) + + +# A secure default. +# Sources for more information on TLS ciphers: +# +# - https://wiki.mozilla.org/Security/Server_Side_TLS +# - https://www.ssllabs.com/projects/best-practices/index.html +# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ +# +# The general intent is: +# - Prefer TLS 1.3 cipher suites +# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE), +# - prefer ECDHE over DHE for better performance, +# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and +# security, +# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common, +# - disable NULL authentication, MD5 MACs and DSS for security reasons. +DEFAULT_CIPHERS = ':'.join([ + 'TLS13-AES-256-GCM-SHA384', + 'TLS13-CHACHA20-POLY1305-SHA256', + 'TLS13-AES-128-GCM-SHA256', + 'ECDH+AESGCM', + 'ECDH+CHACHA20', + 'DH+AESGCM', + 'DH+CHACHA20', + 'ECDH+AES256', + 'DH+AES256', + 'ECDH+AES128', + 'DH+AES', + 'RSA+AESGCM', + 'RSA+AES', + '!aNULL', + '!eNULL', + '!MD5', +]) + +try: + from ssl import SSLContext # Modern SSL? +except ImportError: + import sys + + class SSLContext(object): # Platform-specific: Python 2 & 3.1 + supports_set_ciphers = ((2, 7) <= sys.version_info < (3,) or + (3, 2) <= sys.version_info) + + def __init__(self, protocol_version): + self.protocol = protocol_version + # Use default values from a real SSLContext + self.check_hostname = False + self.verify_mode = ssl.CERT_NONE + self.ca_certs = None + self.options = 0 + self.certfile = None + self.keyfile = None + self.ciphers = None + + def load_cert_chain(self, certfile, keyfile): + self.certfile = certfile + self.keyfile = keyfile + + def load_verify_locations(self, cafile=None, capath=None): + self.ca_certs = cafile + + if capath is not None: + raise SSLError("CA directories not supported in older Pythons") + + def set_ciphers(self, cipher_suite): + if not self.supports_set_ciphers: + raise TypeError( + 'Your version of Python does not support setting ' + 'a custom cipher suite. Please upgrade to Python ' + '2.7, 3.2, or later if you need this functionality.' + ) + self.ciphers = cipher_suite + + def wrap_socket(self, socket, server_hostname=None, server_side=False): + warnings.warn( + 'A true SSLContext object is not available. This prevents ' + 'urllib3 from configuring SSL appropriately and may cause ' + 'certain SSL connections to fail. You can upgrade to a newer ' + 'version of Python to solve this. For more information, see ' + 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' + '#ssl-warnings', + InsecurePlatformWarning + ) + kwargs = { + 'keyfile': self.keyfile, + 'certfile': self.certfile, + 'ca_certs': self.ca_certs, + 'cert_reqs': self.verify_mode, + 'ssl_version': self.protocol, + 'server_side': server_side, + } + if self.supports_set_ciphers: # Platform-specific: Python 2.7+ + return wrap_socket(socket, ciphers=self.ciphers, **kwargs) + else: # Platform-specific: Python 2.6 + return wrap_socket(socket, **kwargs) + + +def assert_fingerprint(cert, fingerprint): + """ + Checks if given fingerprint matches the supplied certificate. + + :param cert: + Certificate as bytes object. + :param fingerprint: + Fingerprint as string of hexdigits, can be interspersed by colons. + """ + + fingerprint = fingerprint.replace(':', '').lower() + digest_length = len(fingerprint) + hashfunc = HASHFUNC_MAP.get(digest_length) + if not hashfunc: + raise SSLError( + 'Fingerprint of invalid length: {0}'.format(fingerprint)) + + # We need encode() here for py32; works on py2 and p33. + fingerprint_bytes = unhexlify(fingerprint.encode()) + + cert_digest = hashfunc(cert).digest() + + if not _const_compare_digest(cert_digest, fingerprint_bytes): + raise SSLError('Fingerprints did not match. Expected "{0}", got "{1}".' + .format(fingerprint, hexlify(cert_digest))) + + +def resolve_cert_reqs(candidate): + """ + Resolves the argument to a numeric constant, which can be passed to + the wrap_socket function/method from the ssl module. + Defaults to :data:`ssl.CERT_NONE`. + If given a string it is assumed to be the name of the constant in the + :mod:`ssl` module or its abbreviation. + (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. + If it's neither `None` nor a string we assume it is already the numeric + constant which can directly be passed to wrap_socket. + """ + if candidate is None: + return CERT_NONE + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, 'CERT_' + candidate) + return res + + return candidate + + +def resolve_ssl_version(candidate): + """ + like resolve_cert_reqs + """ + if candidate is None: + return PROTOCOL_SSLv23 + + if isinstance(candidate, str): + res = getattr(ssl, candidate, None) + if res is None: + res = getattr(ssl, 'PROTOCOL_' + candidate) + return res + + return candidate + + +def create_urllib3_context(ssl_version=None, cert_reqs=None, + options=None, ciphers=None): + """All arguments have the same meaning as ``ssl_wrap_socket``. + + By default, this function does a lot of the same work that + ``ssl.create_default_context`` does on Python 3.4+. It: + + - Disables SSLv2, SSLv3, and compression + - Sets a restricted set of server ciphers + + If you wish to enable SSLv3, you can do:: + + from pip._vendor.urllib3.util import ssl_ + context = ssl_.create_urllib3_context() + context.options &= ~ssl_.OP_NO_SSLv3 + + You can do the same to enable compression (substituting ``COMPRESSION`` + for ``SSLv3`` in the last line above). + + :param ssl_version: + The desired protocol version to use. This will default to + PROTOCOL_SSLv23 which will negotiate the highest protocol that both + the server and your installation of OpenSSL support. + :param cert_reqs: + Whether to require the certificate verification. This defaults to + ``ssl.CERT_REQUIRED``. + :param options: + Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, + ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``. + :param ciphers: + Which cipher suites to allow the server to select. + :returns: + Constructed SSLContext object with specified options + :rtype: SSLContext + """ + context = SSLContext(ssl_version or ssl.PROTOCOL_SSLv23) + + # Setting the default here, as we may have no ssl module on import + cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs + + if options is None: + options = 0 + # SSLv2 is easily broken and is considered harmful and dangerous + options |= OP_NO_SSLv2 + # SSLv3 has several problems and is now dangerous + options |= OP_NO_SSLv3 + # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ + # (issue #309) + options |= OP_NO_COMPRESSION + + context.options |= options + + if getattr(context, 'supports_set_ciphers', True): # Platform-specific: Python 2.6 + context.set_ciphers(ciphers or DEFAULT_CIPHERS) + + context.verify_mode = cert_reqs + if getattr(context, 'check_hostname', None) is not None: # Platform-specific: Python 3.2 + # We do our own verification, including fingerprints and alternative + # hostnames. So disable it here + context.check_hostname = False + return context + + +def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None, + ca_certs=None, server_hostname=None, + ssl_version=None, ciphers=None, ssl_context=None, + ca_cert_dir=None): + """ + All arguments except for server_hostname, ssl_context, and ca_cert_dir have + the same meaning as they do when using :func:`ssl.wrap_socket`. + + :param server_hostname: + When SNI is supported, the expected hostname of the certificate + :param ssl_context: + A pre-made :class:`SSLContext` object. If none is provided, one will + be created using :func:`create_urllib3_context`. + :param ciphers: + A string of ciphers we wish the client to support. This is not + supported on Python 2.6 as the ssl module does not support it. + :param ca_cert_dir: + A directory containing CA certificates in multiple separate files, as + supported by OpenSSL's -CApath flag or the capath argument to + SSLContext.load_verify_locations(). + """ + context = ssl_context + if context is None: + # Note: This branch of code and all the variables in it are no longer + # used by urllib3 itself. We should consider deprecating and removing + # this code. + context = create_urllib3_context(ssl_version, cert_reqs, + ciphers=ciphers) + + if ca_certs or ca_cert_dir: + try: + context.load_verify_locations(ca_certs, ca_cert_dir) + except IOError as e: # Platform-specific: Python 2.6, 2.7, 3.2 + raise SSLError(e) + # Py33 raises FileNotFoundError which subclasses OSError + # These are not equivalent unless we check the errno attribute + except OSError as e: # Platform-specific: Python 3.3 and beyond + if e.errno == errno.ENOENT: + raise SSLError(e) + raise + elif getattr(context, 'load_default_certs', None) is not None: + # try to load OS default certs; works well on Windows (require Python3.4+) + context.load_default_certs() + + if certfile: + context.load_cert_chain(certfile, keyfile) + + # If we detect server_hostname is an IP address then the SNI + # extension should not be used according to RFC3546 Section 3.1 + # We shouldn't warn the user if SNI isn't available but we would + # not be using SNI anyways due to IP address for server_hostname. + if ((server_hostname is not None and not is_ipaddress(server_hostname)) + or IS_SECURETRANSPORT): + if HAS_SNI and server_hostname is not None: + return context.wrap_socket(sock, server_hostname=server_hostname) + + warnings.warn( + 'An HTTPS request has been made, but the SNI (Server Name ' + 'Indication) extension to TLS is not available on this platform. ' + 'This may cause the server to present an incorrect TLS ' + 'certificate, which can cause validation failures. You can upgrade to ' + 'a newer version of Python to solve this. For more information, see ' + 'https://urllib3.readthedocs.io/en/latest/advanced-usage.html' + '#ssl-warnings', + SNIMissingWarning + ) + + return context.wrap_socket(sock) + + +def is_ipaddress(hostname): + """Detects whether the hostname given is an IP address. + + :param str hostname: Hostname to examine. + :return: True if the hostname is an IP address, False otherwise. + """ + if six.PY3 and isinstance(hostname, six.binary_type): + # IDN A-label bytes are ASCII compatible. + hostname = hostname.decode('ascii') + + families = [socket.AF_INET] + if hasattr(socket, 'AF_INET6'): + families.append(socket.AF_INET6) + + for af in families: + try: + inet_pton(af, hostname) + except (socket.error, ValueError, OSError): + pass + else: + return True + return False diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py new file mode 100644 index 0000000..cec817e --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py @@ -0,0 +1,242 @@ +from __future__ import absolute_import +# The default socket timeout, used by httplib to indicate that no timeout was +# specified by the user +from socket import _GLOBAL_DEFAULT_TIMEOUT +import time + +from ..exceptions import TimeoutStateError + +# A sentinel value to indicate that no timeout was specified by the user in +# urllib3 +_Default = object() + + +# Use time.monotonic if available. +current_time = getattr(time, "monotonic", time.time) + + +class Timeout(object): + """ Timeout configuration. + + Timeouts can be defined as a default for a pool:: + + timeout = Timeout(connect=2.0, read=7.0) + http = PoolManager(timeout=timeout) + response = http.request('GET', 'http://example.com/') + + Or per-request (which overrides the default for the pool):: + + response = http.request('GET', 'http://example.com/', timeout=Timeout(10)) + + Timeouts can be disabled by setting all the parameters to ``None``:: + + no_timeout = Timeout(connect=None, read=None) + response = http.request('GET', 'http://example.com/, timeout=no_timeout) + + + :param total: + This combines the connect and read timeouts into one; the read timeout + will be set to the time leftover from the connect attempt. In the + event that both a connect timeout and a total are specified, or a read + timeout and a total are specified, the shorter timeout will be applied. + + Defaults to None. + + :type total: integer, float, or None + + :param connect: + The maximum amount of time to wait for a connection attempt to a server + to succeed. Omitting the parameter will default the connect timeout to + the system default, probably `the global default timeout in socket.py + <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. + None will set an infinite timeout for connection attempts. + + :type connect: integer, float, or None + + :param read: + The maximum amount of time to wait between consecutive + read operations for a response from the server. Omitting + the parameter will default the read timeout to the system + default, probably `the global default timeout in socket.py + <http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_. + None will set an infinite timeout. + + :type read: integer, float, or None + + .. note:: + + Many factors can affect the total amount of time for urllib3 to return + an HTTP response. + + For example, Python's DNS resolver does not obey the timeout specified + on the socket. Other factors that can affect total request time include + high CPU load, high swap, the program running at a low priority level, + or other behaviors. + + In addition, the read and total timeouts only measure the time between + read operations on the socket connecting the client and the server, + not the total amount of time for the request to return a complete + response. For most requests, the timeout is raised because the server + has not sent the first byte in the specified time. This is not always + the case; if a server streams one byte every fifteen seconds, a timeout + of 20 seconds will not trigger, even though the request will take + several minutes to complete. + + If your goal is to cut off any request after a set amount of wall clock + time, consider having a second "watcher" thread to cut off a slow + request. + """ + + #: A sentinel object representing the default timeout value + DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT + + def __init__(self, total=None, connect=_Default, read=_Default): + self._connect = self._validate_timeout(connect, 'connect') + self._read = self._validate_timeout(read, 'read') + self.total = self._validate_timeout(total, 'total') + self._start_connect = None + + def __str__(self): + return '%s(connect=%r, read=%r, total=%r)' % ( + type(self).__name__, self._connect, self._read, self.total) + + @classmethod + def _validate_timeout(cls, value, name): + """ Check that a timeout attribute is valid. + + :param value: The timeout value to validate + :param name: The name of the timeout attribute to validate. This is + used to specify in error messages. + :return: The validated and casted version of the given value. + :raises ValueError: If it is a numeric value less than or equal to + zero, or the type is not an integer, float, or None. + """ + if value is _Default: + return cls.DEFAULT_TIMEOUT + + if value is None or value is cls.DEFAULT_TIMEOUT: + return value + + if isinstance(value, bool): + raise ValueError("Timeout cannot be a boolean value. It must " + "be an int, float or None.") + try: + float(value) + except (TypeError, ValueError): + raise ValueError("Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value)) + + try: + if value <= 0: + raise ValueError("Attempted to set %s timeout to %s, but the " + "timeout cannot be set to a value less " + "than or equal to 0." % (name, value)) + except TypeError: # Python 3 + raise ValueError("Timeout value %s was %s, but it must be an " + "int, float or None." % (name, value)) + + return value + + @classmethod + def from_float(cls, timeout): + """ Create a new Timeout from a legacy timeout value. + + The timeout value used by httplib.py sets the same timeout on the + connect(), and recv() socket requests. This creates a :class:`Timeout` + object that sets the individual timeouts to the ``timeout`` value + passed to this function. + + :param timeout: The legacy timeout value. + :type timeout: integer, float, sentinel default object, or None + :return: Timeout object + :rtype: :class:`Timeout` + """ + return Timeout(read=timeout, connect=timeout) + + def clone(self): + """ Create a copy of the timeout object + + Timeout properties are stored per-pool but each request needs a fresh + Timeout object to ensure each one has its own start/stop configured. + + :return: a copy of the timeout object + :rtype: :class:`Timeout` + """ + # We can't use copy.deepcopy because that will also create a new object + # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to + # detect the user default. + return Timeout(connect=self._connect, read=self._read, + total=self.total) + + def start_connect(self): + """ Start the timeout clock, used during a connect() attempt + + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to start a timer that has been started already. + """ + if self._start_connect is not None: + raise TimeoutStateError("Timeout timer has already been started.") + self._start_connect = current_time() + return self._start_connect + + def get_connect_duration(self): + """ Gets the time elapsed since the call to :meth:`start_connect`. + + :return: Elapsed time. + :rtype: float + :raises urllib3.exceptions.TimeoutStateError: if you attempt + to get duration for a timer that hasn't been started. + """ + if self._start_connect is None: + raise TimeoutStateError("Can't get connect duration for timer " + "that has not started.") + return current_time() - self._start_connect + + @property + def connect_timeout(self): + """ Get the value to use when setting a connection timeout. + + This will be a positive float or integer, the value None + (never timeout), or the default system timeout. + + :return: Connect timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + """ + if self.total is None: + return self._connect + + if self._connect is None or self._connect is self.DEFAULT_TIMEOUT: + return self.total + + return min(self._connect, self.total) + + @property + def read_timeout(self): + """ Get the value for the read timeout. + + This assumes some time has elapsed in the connection timeout and + computes the read timeout appropriately. + + If self.total is set, the read timeout is dependent on the amount of + time taken by the connect timeout. If the connection time has not been + established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be + raised. + + :return: Value to use for the read timeout. + :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None + :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` + has not yet been called on this object. + """ + if (self.total is not None and + self.total is not self.DEFAULT_TIMEOUT and + self._read is not None and + self._read is not self.DEFAULT_TIMEOUT): + # In case the connect timeout has not yet been established. + if self._start_connect is None: + return self._read + return max(0, min(self.total - self.get_connect_duration(), + self._read)) + elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT: + return max(0, self.total - self.get_connect_duration()) + else: + return self._read diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/url.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/url.py new file mode 100644 index 0000000..6b6f996 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/url.py @@ -0,0 +1,230 @@ +from __future__ import absolute_import +from collections import namedtuple + +from ..exceptions import LocationParseError + + +url_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment'] + +# We only want to normalize urls with an HTTP(S) scheme. +# urllib3 infers URLs without a scheme (None) to be http. +NORMALIZABLE_SCHEMES = ('http', 'https', None) + + +class Url(namedtuple('Url', url_attrs)): + """ + Datastructure for representing an HTTP URL. Used as a return value for + :func:`parse_url`. Both the scheme and host are normalized as they are + both case-insensitive according to RFC 3986. + """ + __slots__ = () + + def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None, + query=None, fragment=None): + if path and not path.startswith('/'): + path = '/' + path + if scheme: + scheme = scheme.lower() + if host and scheme in NORMALIZABLE_SCHEMES: + host = host.lower() + return super(Url, cls).__new__(cls, scheme, auth, host, port, path, + query, fragment) + + @property + def hostname(self): + """For backwards-compatibility with urlparse. We're nice like that.""" + return self.host + + @property + def request_uri(self): + """Absolute path including the query string.""" + uri = self.path or '/' + + if self.query is not None: + uri += '?' + self.query + + return uri + + @property + def netloc(self): + """Network location including host and port""" + if self.port: + return '%s:%d' % (self.host, self.port) + return self.host + + @property + def url(self): + """ + Convert self into a url + + This function should more or less round-trip with :func:`.parse_url`. The + returned url may not be exactly the same as the url inputted to + :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls + with a blank port will have : removed). + + Example: :: + + >>> U = parse_url('http://google.com/mail/') + >>> U.url + 'http://google.com/mail/' + >>> Url('http', 'username:password', 'host.com', 80, + ... '/path', 'query', 'fragment').url + 'http://username:password@host.com:80/path?query#fragment' + """ + scheme, auth, host, port, path, query, fragment = self + url = '' + + # We use "is not None" we want things to happen with empty strings (or 0 port) + if scheme is not None: + url += scheme + '://' + if auth is not None: + url += auth + '@' + if host is not None: + url += host + if port is not None: + url += ':' + str(port) + if path is not None: + url += path + if query is not None: + url += '?' + query + if fragment is not None: + url += '#' + fragment + + return url + + def __str__(self): + return self.url + + +def split_first(s, delims): + """ + Given a string and an iterable of delimiters, split on the first found + delimiter. Return two split parts and the matched delimiter. + + If not found, then the first part is the full input string. + + Example:: + + >>> split_first('foo/bar?baz', '?/=') + ('foo', 'bar?baz', '/') + >>> split_first('foo/bar?baz', '123') + ('foo/bar?baz', '', None) + + Scales linearly with number of delims. Not ideal for large number of delims. + """ + min_idx = None + min_delim = None + for d in delims: + idx = s.find(d) + if idx < 0: + continue + + if min_idx is None or idx < min_idx: + min_idx = idx + min_delim = d + + if min_idx is None or min_idx < 0: + return s, '', None + + return s[:min_idx], s[min_idx + 1:], min_delim + + +def parse_url(url): + """ + Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is + performed to parse incomplete urls. Fields not provided will be None. + + Partly backwards-compatible with :mod:`urlparse`. + + Example:: + + >>> parse_url('http://google.com/mail/') + Url(scheme='http', host='google.com', port=None, path='/mail/', ...) + >>> parse_url('google.com:80') + Url(scheme=None, host='google.com', port=80, path=None, ...) + >>> parse_url('/foo?bar') + Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) + """ + + # While this code has overlap with stdlib's urlparse, it is much + # simplified for our needs and less annoying. + # Additionally, this implementations does silly things to be optimal + # on CPython. + + if not url: + # Empty + return Url() + + scheme = None + auth = None + host = None + port = None + path = None + fragment = None + query = None + + # Scheme + if '://' in url: + scheme, url = url.split('://', 1) + + # Find the earliest Authority Terminator + # (http://tools.ietf.org/html/rfc3986#section-3.2) + url, path_, delim = split_first(url, ['/', '?', '#']) + + if delim: + # Reassemble the path + path = delim + path_ + + # Auth + if '@' in url: + # Last '@' denotes end of auth part + auth, url = url.rsplit('@', 1) + + # IPv6 + if url and url[0] == '[': + host, url = url.split(']', 1) + host += ']' + + # Port + if ':' in url: + _host, port = url.split(':', 1) + + if not host: + host = _host + + if port: + # If given, ports must be integers. No whitespace, no plus or + # minus prefixes, no non-integer digits such as ^2 (superscript). + if not port.isdigit(): + raise LocationParseError(url) + try: + port = int(port) + except ValueError: + raise LocationParseError(url) + else: + # Blank ports are cool, too. (rfc3986#section-3.2.3) + port = None + + elif not host and url: + host = url + + if not path: + return Url(scheme, auth, host, port, path, query, fragment) + + # Fragment + if '#' in path: + path, fragment = path.split('#', 1) + + # Query + if '?' in path: + path, query = path.split('?', 1) + + return Url(scheme, auth, host, port, path, query, fragment) + + +def get_host(url): + """ + Deprecated. Use :func:`parse_url` instead. + """ + p = parse_url(url) + return p.scheme or 'http', p.hostname, p.port diff --git a/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py new file mode 100644 index 0000000..fa686ef --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py @@ -0,0 +1,153 @@ +import errno +from functools import partial +import select +import sys +try: + from time import monotonic +except ImportError: + from time import time as monotonic + +__all__ = ["NoWayToWaitForSocketError", "wait_for_read", "wait_for_write"] + + +class NoWayToWaitForSocketError(Exception): + pass + + +# How should we wait on sockets? +# +# There are two types of APIs you can use for waiting on sockets: the fancy +# modern stateful APIs like epoll/kqueue, and the older stateless APIs like +# select/poll. The stateful APIs are more efficient when you have a lots of +# sockets to keep track of, because you can set them up once and then use them +# lots of times. But we only ever want to wait on a single socket at a time +# and don't want to keep track of state, so the stateless APIs are actually +# more efficient. So we want to use select() or poll(). +# +# Now, how do we choose between select() and poll()? On traditional Unixes, +# select() has a strange calling convention that makes it slow, or fail +# altogether, for high-numbered file descriptors. The point of poll() is to fix +# that, so on Unixes, we prefer poll(). +# +# On Windows, there is no poll() (or at least Python doesn't provide a wrapper +# for it), but that's OK, because on Windows, select() doesn't have this +# strange calling convention; plain select() works fine. +# +# So: on Windows we use select(), and everywhere else we use poll(). We also +# fall back to select() in case poll() is somehow broken or missing. + +if sys.version_info >= (3, 5): + # Modern Python, that retries syscalls by default + def _retry_on_intr(fn, timeout): + return fn(timeout) +else: + # Old and broken Pythons. + def _retry_on_intr(fn, timeout): + if timeout is not None and timeout <= 0: + return fn(timeout) + + if timeout is None: + deadline = float("inf") + else: + deadline = monotonic() + timeout + + while True: + try: + return fn(timeout) + # OSError for 3 <= pyver < 3.5, select.error for pyver <= 2.7 + except (OSError, select.error) as e: + # 'e.args[0]' incantation works for both OSError and select.error + if e.args[0] != errno.EINTR: + raise + else: + timeout = deadline - monotonic() + if timeout < 0: + timeout = 0 + if timeout == float("inf"): + timeout = None + continue + + +def select_wait_for_socket(sock, read=False, write=False, timeout=None): + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + rcheck = [] + wcheck = [] + if read: + rcheck.append(sock) + if write: + wcheck.append(sock) + # When doing a non-blocking connect, most systems signal success by + # marking the socket writable. Windows, though, signals success by marked + # it as "exceptional". We paper over the difference by checking the write + # sockets for both conditions. (The stdlib selectors module does the same + # thing.) + fn = partial(select.select, rcheck, wcheck, wcheck) + rready, wready, xready = _retry_on_intr(fn, timeout) + return bool(rready or wready or xready) + + +def poll_wait_for_socket(sock, read=False, write=False, timeout=None): + if not read and not write: + raise RuntimeError("must specify at least one of read=True, write=True") + mask = 0 + if read: + mask |= select.POLLIN + if write: + mask |= select.POLLOUT + poll_obj = select.poll() + poll_obj.register(sock, mask) + + # For some reason, poll() takes timeout in milliseconds + def do_poll(t): + if t is not None: + t *= 1000 + return poll_obj.poll(t) + + return bool(_retry_on_intr(do_poll, timeout)) + + +def null_wait_for_socket(*args, **kwargs): + raise NoWayToWaitForSocketError("no select-equivalent available") + + +def _have_working_poll(): + # Apparently some systems have a select.poll that fails as soon as you try + # to use it, either due to strange configuration or broken monkeypatching + # from libraries like eventlet/greenlet. + try: + poll_obj = select.poll() + poll_obj.poll(0) + except (AttributeError, OSError): + return False + else: + return True + + +def wait_for_socket(*args, **kwargs): + # We delay choosing which implementation to use until the first time we're + # called. We could do it at import time, but then we might make the wrong + # decision if someone goes wild with monkeypatching select.poll after + # we're imported. + global wait_for_socket + if _have_working_poll(): + wait_for_socket = poll_wait_for_socket + elif hasattr(select, "select"): + wait_for_socket = select_wait_for_socket + else: # Platform-specific: Appengine. + wait_for_socket = null_wait_for_socket + return wait_for_socket(*args, **kwargs) + + +def wait_for_read(sock, timeout=None): + """ Waits for reading to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, read=True, timeout=timeout) + + +def wait_for_write(sock, timeout=None): + """ Waits for writing to be available on a given socket. + Returns True if the socket is readable, or False if the timeout expired. + """ + return wait_for_socket(sock, write=True, timeout=timeout) diff --git a/winvenv/Lib/site-packages/pip/_vendor/webencodings/__init__.py b/winvenv/Lib/site-packages/pip/_vendor/webencodings/__init__.py new file mode 100644 index 0000000..d21d697 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/webencodings/__init__.py @@ -0,0 +1,342 @@ +# coding: utf-8 +""" + + webencodings + ~~~~~~~~~~~~ + + This is a Python implementation of the `WHATWG Encoding standard + <http://encoding.spec.whatwg.org/>`. See README for details. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +from __future__ import unicode_literals + +import codecs + +from .labels import LABELS + + +VERSION = '0.5.1' + + +# Some names in Encoding are not valid Python aliases. Remap these. +PYTHON_NAMES = { + 'iso-8859-8-i': 'iso-8859-8', + 'x-mac-cyrillic': 'mac-cyrillic', + 'macintosh': 'mac-roman', + 'windows-874': 'cp874'} + +CACHE = {} + + +def ascii_lower(string): + r"""Transform (only) ASCII letters to lower case: A-Z is mapped to a-z. + + :param string: An Unicode string. + :returns: A new Unicode string. + + This is used for `ASCII case-insensitive + <http://encoding.spec.whatwg.org/#ascii-case-insensitive>`_ + matching of encoding labels. + The same matching is also used, among other things, + for `CSS keywords <http://dev.w3.org/csswg/css-values/#keywords>`_. + + This is different from the :meth:`~py:str.lower` method of Unicode strings + which also affect non-ASCII characters, + sometimes mapping them into the ASCII range: + + >>> keyword = u'Bac\N{KELVIN SIGN}ground' + >>> assert keyword.lower() == u'background' + >>> assert ascii_lower(keyword) != keyword.lower() + >>> assert ascii_lower(keyword) == u'bac\N{KELVIN SIGN}ground' + + """ + # This turns out to be faster than unicode.translate() + return string.encode('utf8').lower().decode('utf8') + + +def lookup(label): + """ + Look for an encoding by its label. + This is the spec’s `get an encoding + <http://encoding.spec.whatwg.org/#concept-encoding-get>`_ algorithm. + Supported labels are listed there. + + :param label: A string. + :returns: + An :class:`Encoding` object, or :obj:`None` for an unknown label. + + """ + # Only strip ASCII whitespace: U+0009, U+000A, U+000C, U+000D, and U+0020. + label = ascii_lower(label.strip('\t\n\f\r ')) + name = LABELS.get(label) + if name is None: + return None + encoding = CACHE.get(name) + if encoding is None: + if name == 'x-user-defined': + from .x_user_defined import codec_info + else: + python_name = PYTHON_NAMES.get(name, name) + # Any python_name value that gets to here should be valid. + codec_info = codecs.lookup(python_name) + encoding = Encoding(name, codec_info) + CACHE[name] = encoding + return encoding + + +def _get_encoding(encoding_or_label): + """ + Accept either an encoding object or label. + + :param encoding: An :class:`Encoding` object or a label string. + :returns: An :class:`Encoding` object. + :raises: :exc:`~exceptions.LookupError` for an unknown label. + + """ + if hasattr(encoding_or_label, 'codec_info'): + return encoding_or_label + + encoding = lookup(encoding_or_label) + if encoding is None: + raise LookupError('Unknown encoding label: %r' % encoding_or_label) + return encoding + + +class Encoding(object): + """Reresents a character encoding such as UTF-8, + that can be used for decoding or encoding. + + .. attribute:: name + + Canonical name of the encoding + + .. attribute:: codec_info + + The actual implementation of the encoding, + a stdlib :class:`~codecs.CodecInfo` object. + See :func:`codecs.register`. + + """ + def __init__(self, name, codec_info): + self.name = name + self.codec_info = codec_info + + def __repr__(self): + return '<Encoding %s>' % self.name + + +#: The UTF-8 encoding. Should be used for new content and formats. +UTF8 = lookup('utf-8') + +_UTF16LE = lookup('utf-16le') +_UTF16BE = lookup('utf-16be') + + +def decode(input, fallback_encoding, errors='replace'): + """ + Decode a single string. + + :param input: A byte string + :param fallback_encoding: + An :class:`Encoding` object or a label string. + The encoding to use if :obj:`input` does note have a BOM. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :return: + A ``(output, encoding)`` tuple of an Unicode string + and an :obj:`Encoding`. + + """ + # Fail early if `encoding` is an invalid label. + fallback_encoding = _get_encoding(fallback_encoding) + bom_encoding, input = _detect_bom(input) + encoding = bom_encoding or fallback_encoding + return encoding.codec_info.decode(input, errors)[0], encoding + + +def _detect_bom(input): + """Return (bom_encoding, input), with any BOM removed from the input.""" + if input.startswith(b'\xFF\xFE'): + return _UTF16LE, input[2:] + if input.startswith(b'\xFE\xFF'): + return _UTF16BE, input[2:] + if input.startswith(b'\xEF\xBB\xBF'): + return UTF8, input[3:] + return None, input + + +def encode(input, encoding=UTF8, errors='strict'): + """ + Encode a single string. + + :param input: An Unicode string. + :param encoding: An :class:`Encoding` object or a label string. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :return: A byte string. + + """ + return _get_encoding(encoding).codec_info.encode(input, errors)[0] + + +def iter_decode(input, fallback_encoding, errors='replace'): + """ + "Pull"-based decoder. + + :param input: + An iterable of byte strings. + + The input is first consumed just enough to determine the encoding + based on the precense of a BOM, + then consumed on demand when the return value is. + :param fallback_encoding: + An :class:`Encoding` object or a label string. + The encoding to use if :obj:`input` does note have a BOM. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :returns: + An ``(output, encoding)`` tuple. + :obj:`output` is an iterable of Unicode strings, + :obj:`encoding` is the :obj:`Encoding` that is being used. + + """ + + decoder = IncrementalDecoder(fallback_encoding, errors) + generator = _iter_decode_generator(input, decoder) + encoding = next(generator) + return generator, encoding + + +def _iter_decode_generator(input, decoder): + """Return a generator that first yields the :obj:`Encoding`, + then yields output chukns as Unicode strings. + + """ + decode = decoder.decode + input = iter(input) + for chunck in input: + output = decode(chunck) + if output: + assert decoder.encoding is not None + yield decoder.encoding + yield output + break + else: + # Input exhausted without determining the encoding + output = decode(b'', final=True) + assert decoder.encoding is not None + yield decoder.encoding + if output: + yield output + return + + for chunck in input: + output = decode(chunck) + if output: + yield output + output = decode(b'', final=True) + if output: + yield output + + +def iter_encode(input, encoding=UTF8, errors='strict'): + """ + “Pull”-based encoder. + + :param input: An iterable of Unicode strings. + :param encoding: An :class:`Encoding` object or a label string. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + :returns: An iterable of byte strings. + + """ + # Fail early if `encoding` is an invalid label. + encode = IncrementalEncoder(encoding, errors).encode + return _iter_encode_generator(input, encode) + + +def _iter_encode_generator(input, encode): + for chunck in input: + output = encode(chunck) + if output: + yield output + output = encode('', final=True) + if output: + yield output + + +class IncrementalDecoder(object): + """ + “Push”-based decoder. + + :param fallback_encoding: + An :class:`Encoding` object or a label string. + The encoding to use if :obj:`input` does note have a BOM. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + + """ + def __init__(self, fallback_encoding, errors='replace'): + # Fail early if `encoding` is an invalid label. + self._fallback_encoding = _get_encoding(fallback_encoding) + self._errors = errors + self._buffer = b'' + self._decoder = None + #: The actual :class:`Encoding` that is being used, + #: or :obj:`None` if that is not determined yet. + #: (Ie. if there is not enough input yet to determine + #: if there is a BOM.) + self.encoding = None # Not known yet. + + def decode(self, input, final=False): + """Decode one chunk of the input. + + :param input: A byte string. + :param final: + Indicate that no more input is available. + Must be :obj:`True` if this is the last call. + :returns: An Unicode string. + + """ + decoder = self._decoder + if decoder is not None: + return decoder(input, final) + + input = self._buffer + input + encoding, input = _detect_bom(input) + if encoding is None: + if len(input) < 3 and not final: # Not enough data yet. + self._buffer = input + return '' + else: # No BOM + encoding = self._fallback_encoding + decoder = encoding.codec_info.incrementaldecoder(self._errors).decode + self._decoder = decoder + self.encoding = encoding + return decoder(input, final) + + +class IncrementalEncoder(object): + """ + “Push”-based encoder. + + :param encoding: An :class:`Encoding` object or a label string. + :param errors: Type of error handling. See :func:`codecs.register`. + :raises: :exc:`~exceptions.LookupError` for an unknown encoding label. + + .. method:: encode(input, final=False) + + :param input: An Unicode string. + :param final: + Indicate that no more input is available. + Must be :obj:`True` if this is the last call. + :returns: A byte string. + + """ + def __init__(self, encoding=UTF8, errors='strict'): + encoding = _get_encoding(encoding) + self.encode = encoding.codec_info.incrementalencoder(errors).encode diff --git a/winvenv/Lib/site-packages/pip/_vendor/webencodings/labels.py b/winvenv/Lib/site-packages/pip/_vendor/webencodings/labels.py new file mode 100644 index 0000000..29cbf91 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/webencodings/labels.py @@ -0,0 +1,231 @@ +""" + + webencodings.labels + ~~~~~~~~~~~~~~~~~~~ + + Map encoding labels to their name. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +# XXX Do not edit! +# This file is automatically generated by mklabels.py + +LABELS = { + 'unicode-1-1-utf-8': 'utf-8', + 'utf-8': 'utf-8', + 'utf8': 'utf-8', + '866': 'ibm866', + 'cp866': 'ibm866', + 'csibm866': 'ibm866', + 'ibm866': 'ibm866', + 'csisolatin2': 'iso-8859-2', + 'iso-8859-2': 'iso-8859-2', + 'iso-ir-101': 'iso-8859-2', + 'iso8859-2': 'iso-8859-2', + 'iso88592': 'iso-8859-2', + 'iso_8859-2': 'iso-8859-2', + 'iso_8859-2:1987': 'iso-8859-2', + 'l2': 'iso-8859-2', + 'latin2': 'iso-8859-2', + 'csisolatin3': 'iso-8859-3', + 'iso-8859-3': 'iso-8859-3', + 'iso-ir-109': 'iso-8859-3', + 'iso8859-3': 'iso-8859-3', + 'iso88593': 'iso-8859-3', + 'iso_8859-3': 'iso-8859-3', + 'iso_8859-3:1988': 'iso-8859-3', + 'l3': 'iso-8859-3', + 'latin3': 'iso-8859-3', + 'csisolatin4': 'iso-8859-4', + 'iso-8859-4': 'iso-8859-4', + 'iso-ir-110': 'iso-8859-4', + 'iso8859-4': 'iso-8859-4', + 'iso88594': 'iso-8859-4', + 'iso_8859-4': 'iso-8859-4', + 'iso_8859-4:1988': 'iso-8859-4', + 'l4': 'iso-8859-4', + 'latin4': 'iso-8859-4', + 'csisolatincyrillic': 'iso-8859-5', + 'cyrillic': 'iso-8859-5', + 'iso-8859-5': 'iso-8859-5', + 'iso-ir-144': 'iso-8859-5', + 'iso8859-5': 'iso-8859-5', + 'iso88595': 'iso-8859-5', + 'iso_8859-5': 'iso-8859-5', + 'iso_8859-5:1988': 'iso-8859-5', + 'arabic': 'iso-8859-6', + 'asmo-708': 'iso-8859-6', + 'csiso88596e': 'iso-8859-6', + 'csiso88596i': 'iso-8859-6', + 'csisolatinarabic': 'iso-8859-6', + 'ecma-114': 'iso-8859-6', + 'iso-8859-6': 'iso-8859-6', + 'iso-8859-6-e': 'iso-8859-6', + 'iso-8859-6-i': 'iso-8859-6', + 'iso-ir-127': 'iso-8859-6', + 'iso8859-6': 'iso-8859-6', + 'iso88596': 'iso-8859-6', + 'iso_8859-6': 'iso-8859-6', + 'iso_8859-6:1987': 'iso-8859-6', + 'csisolatingreek': 'iso-8859-7', + 'ecma-118': 'iso-8859-7', + 'elot_928': 'iso-8859-7', + 'greek': 'iso-8859-7', + 'greek8': 'iso-8859-7', + 'iso-8859-7': 'iso-8859-7', + 'iso-ir-126': 'iso-8859-7', + 'iso8859-7': 'iso-8859-7', + 'iso88597': 'iso-8859-7', + 'iso_8859-7': 'iso-8859-7', + 'iso_8859-7:1987': 'iso-8859-7', + 'sun_eu_greek': 'iso-8859-7', + 'csiso88598e': 'iso-8859-8', + 'csisolatinhebrew': 'iso-8859-8', + 'hebrew': 'iso-8859-8', + 'iso-8859-8': 'iso-8859-8', + 'iso-8859-8-e': 'iso-8859-8', + 'iso-ir-138': 'iso-8859-8', + 'iso8859-8': 'iso-8859-8', + 'iso88598': 'iso-8859-8', + 'iso_8859-8': 'iso-8859-8', + 'iso_8859-8:1988': 'iso-8859-8', + 'visual': 'iso-8859-8', + 'csiso88598i': 'iso-8859-8-i', + 'iso-8859-8-i': 'iso-8859-8-i', + 'logical': 'iso-8859-8-i', + 'csisolatin6': 'iso-8859-10', + 'iso-8859-10': 'iso-8859-10', + 'iso-ir-157': 'iso-8859-10', + 'iso8859-10': 'iso-8859-10', + 'iso885910': 'iso-8859-10', + 'l6': 'iso-8859-10', + 'latin6': 'iso-8859-10', + 'iso-8859-13': 'iso-8859-13', + 'iso8859-13': 'iso-8859-13', + 'iso885913': 'iso-8859-13', + 'iso-8859-14': 'iso-8859-14', + 'iso8859-14': 'iso-8859-14', + 'iso885914': 'iso-8859-14', + 'csisolatin9': 'iso-8859-15', + 'iso-8859-15': 'iso-8859-15', + 'iso8859-15': 'iso-8859-15', + 'iso885915': 'iso-8859-15', + 'iso_8859-15': 'iso-8859-15', + 'l9': 'iso-8859-15', + 'iso-8859-16': 'iso-8859-16', + 'cskoi8r': 'koi8-r', + 'koi': 'koi8-r', + 'koi8': 'koi8-r', + 'koi8-r': 'koi8-r', + 'koi8_r': 'koi8-r', + 'koi8-u': 'koi8-u', + 'csmacintosh': 'macintosh', + 'mac': 'macintosh', + 'macintosh': 'macintosh', + 'x-mac-roman': 'macintosh', + 'dos-874': 'windows-874', + 'iso-8859-11': 'windows-874', + 'iso8859-11': 'windows-874', + 'iso885911': 'windows-874', + 'tis-620': 'windows-874', + 'windows-874': 'windows-874', + 'cp1250': 'windows-1250', + 'windows-1250': 'windows-1250', + 'x-cp1250': 'windows-1250', + 'cp1251': 'windows-1251', + 'windows-1251': 'windows-1251', + 'x-cp1251': 'windows-1251', + 'ansi_x3.4-1968': 'windows-1252', + 'ascii': 'windows-1252', + 'cp1252': 'windows-1252', + 'cp819': 'windows-1252', + 'csisolatin1': 'windows-1252', + 'ibm819': 'windows-1252', + 'iso-8859-1': 'windows-1252', + 'iso-ir-100': 'windows-1252', + 'iso8859-1': 'windows-1252', + 'iso88591': 'windows-1252', + 'iso_8859-1': 'windows-1252', + 'iso_8859-1:1987': 'windows-1252', + 'l1': 'windows-1252', + 'latin1': 'windows-1252', + 'us-ascii': 'windows-1252', + 'windows-1252': 'windows-1252', + 'x-cp1252': 'windows-1252', + 'cp1253': 'windows-1253', + 'windows-1253': 'windows-1253', + 'x-cp1253': 'windows-1253', + 'cp1254': 'windows-1254', + 'csisolatin5': 'windows-1254', + 'iso-8859-9': 'windows-1254', + 'iso-ir-148': 'windows-1254', + 'iso8859-9': 'windows-1254', + 'iso88599': 'windows-1254', + 'iso_8859-9': 'windows-1254', + 'iso_8859-9:1989': 'windows-1254', + 'l5': 'windows-1254', + 'latin5': 'windows-1254', + 'windows-1254': 'windows-1254', + 'x-cp1254': 'windows-1254', + 'cp1255': 'windows-1255', + 'windows-1255': 'windows-1255', + 'x-cp1255': 'windows-1255', + 'cp1256': 'windows-1256', + 'windows-1256': 'windows-1256', + 'x-cp1256': 'windows-1256', + 'cp1257': 'windows-1257', + 'windows-1257': 'windows-1257', + 'x-cp1257': 'windows-1257', + 'cp1258': 'windows-1258', + 'windows-1258': 'windows-1258', + 'x-cp1258': 'windows-1258', + 'x-mac-cyrillic': 'x-mac-cyrillic', + 'x-mac-ukrainian': 'x-mac-cyrillic', + 'chinese': 'gbk', + 'csgb2312': 'gbk', + 'csiso58gb231280': 'gbk', + 'gb2312': 'gbk', + 'gb_2312': 'gbk', + 'gb_2312-80': 'gbk', + 'gbk': 'gbk', + 'iso-ir-58': 'gbk', + 'x-gbk': 'gbk', + 'gb18030': 'gb18030', + 'hz-gb-2312': 'hz-gb-2312', + 'big5': 'big5', + 'big5-hkscs': 'big5', + 'cn-big5': 'big5', + 'csbig5': 'big5', + 'x-x-big5': 'big5', + 'cseucpkdfmtjapanese': 'euc-jp', + 'euc-jp': 'euc-jp', + 'x-euc-jp': 'euc-jp', + 'csiso2022jp': 'iso-2022-jp', + 'iso-2022-jp': 'iso-2022-jp', + 'csshiftjis': 'shift_jis', + 'ms_kanji': 'shift_jis', + 'shift-jis': 'shift_jis', + 'shift_jis': 'shift_jis', + 'sjis': 'shift_jis', + 'windows-31j': 'shift_jis', + 'x-sjis': 'shift_jis', + 'cseuckr': 'euc-kr', + 'csksc56011987': 'euc-kr', + 'euc-kr': 'euc-kr', + 'iso-ir-149': 'euc-kr', + 'korean': 'euc-kr', + 'ks_c_5601-1987': 'euc-kr', + 'ks_c_5601-1989': 'euc-kr', + 'ksc5601': 'euc-kr', + 'ksc_5601': 'euc-kr', + 'windows-949': 'euc-kr', + 'csiso2022kr': 'iso-2022-kr', + 'iso-2022-kr': 'iso-2022-kr', + 'utf-16be': 'utf-16be', + 'utf-16': 'utf-16le', + 'utf-16le': 'utf-16le', + 'x-user-defined': 'x-user-defined', +} diff --git a/winvenv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py b/winvenv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py new file mode 100644 index 0000000..295dc92 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py @@ -0,0 +1,59 @@ +""" + + webencodings.mklabels + ~~~~~~~~~~~~~~~~~~~~~ + + Regenarate the webencodings.labels module. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +import json +try: + from urllib import urlopen +except ImportError: + from urllib.request import urlopen + + +def assert_lower(string): + assert string == string.lower() + return string + + +def generate(url): + parts = ['''\ +""" + + webencodings.labels + ~~~~~~~~~~~~~~~~~~~ + + Map encoding labels to their name. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +# XXX Do not edit! +# This file is automatically generated by mklabels.py + +LABELS = { +'''] + labels = [ + (repr(assert_lower(label)).lstrip('u'), + repr(encoding['name']).lstrip('u')) + for category in json.loads(urlopen(url).read().decode('ascii')) + for encoding in category['encodings'] + for label in encoding['labels']] + max_len = max(len(label) for label, name in labels) + parts.extend( + ' %s:%s %s,\n' % (label, ' ' * (max_len - len(label)), name) + for label, name in labels) + parts.append('}') + return ''.join(parts) + + +if __name__ == '__main__': + print(generate('http://encoding.spec.whatwg.org/encodings.json')) diff --git a/winvenv/Lib/site-packages/pip/_vendor/webencodings/tests.py b/winvenv/Lib/site-packages/pip/_vendor/webencodings/tests.py new file mode 100644 index 0000000..e12c10d --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/webencodings/tests.py @@ -0,0 +1,153 @@ +# coding: utf-8 +""" + + webencodings.tests + ~~~~~~~~~~~~~~~~~~ + + A basic test suite for Encoding. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +from __future__ import unicode_literals + +from . import (lookup, LABELS, decode, encode, iter_decode, iter_encode, + IncrementalDecoder, IncrementalEncoder, UTF8) + + +def assert_raises(exception, function, *args, **kwargs): + try: + function(*args, **kwargs) + except exception: + return + else: # pragma: no cover + raise AssertionError('Did not raise %s.' % exception) + + +def test_labels(): + assert lookup('utf-8').name == 'utf-8' + assert lookup('Utf-8').name == 'utf-8' + assert lookup('UTF-8').name == 'utf-8' + assert lookup('utf8').name == 'utf-8' + assert lookup('utf8').name == 'utf-8' + assert lookup('utf8 ').name == 'utf-8' + assert lookup(' \r\nutf8\t').name == 'utf-8' + assert lookup('u8') is None # Python label. + assert lookup('utf-8 ') is None # Non-ASCII white space. + + assert lookup('US-ASCII').name == 'windows-1252' + assert lookup('iso-8859-1').name == 'windows-1252' + assert lookup('latin1').name == 'windows-1252' + assert lookup('LATIN1').name == 'windows-1252' + assert lookup('latin-1') is None + assert lookup('LATİN1') is None # ASCII-only case insensitivity. + + +def test_all_labels(): + for label in LABELS: + assert decode(b'', label) == ('', lookup(label)) + assert encode('', label) == b'' + for repeat in [0, 1, 12]: + output, _ = iter_decode([b''] * repeat, label) + assert list(output) == [] + assert list(iter_encode([''] * repeat, label)) == [] + decoder = IncrementalDecoder(label) + assert decoder.decode(b'') == '' + assert decoder.decode(b'', final=True) == '' + encoder = IncrementalEncoder(label) + assert encoder.encode('') == b'' + assert encoder.encode('', final=True) == b'' + # All encoding names are valid labels too: + for name in set(LABELS.values()): + assert lookup(name).name == name + + +def test_invalid_label(): + assert_raises(LookupError, decode, b'\xEF\xBB\xBF\xc3\xa9', 'invalid') + assert_raises(LookupError, encode, 'é', 'invalid') + assert_raises(LookupError, iter_decode, [], 'invalid') + assert_raises(LookupError, iter_encode, [], 'invalid') + assert_raises(LookupError, IncrementalDecoder, 'invalid') + assert_raises(LookupError, IncrementalEncoder, 'invalid') + + +def test_decode(): + assert decode(b'\x80', 'latin1') == ('€', lookup('latin1')) + assert decode(b'\x80', lookup('latin1')) == ('€', lookup('latin1')) + assert decode(b'\xc3\xa9', 'utf8') == ('é', lookup('utf8')) + assert decode(b'\xc3\xa9', UTF8) == ('é', lookup('utf8')) + assert decode(b'\xc3\xa9', 'ascii') == ('é', lookup('ascii')) + assert decode(b'\xEF\xBB\xBF\xc3\xa9', 'ascii') == ('é', lookup('utf8')) # UTF-8 with BOM + + assert decode(b'\xFE\xFF\x00\xe9', 'ascii') == ('é', lookup('utf-16be')) # UTF-16-BE with BOM + assert decode(b'\xFF\xFE\xe9\x00', 'ascii') == ('é', lookup('utf-16le')) # UTF-16-LE with BOM + assert decode(b'\xFE\xFF\xe9\x00', 'ascii') == ('\ue900', lookup('utf-16be')) + assert decode(b'\xFF\xFE\x00\xe9', 'ascii') == ('\ue900', lookup('utf-16le')) + + assert decode(b'\x00\xe9', 'UTF-16BE') == ('é', lookup('utf-16be')) + assert decode(b'\xe9\x00', 'UTF-16LE') == ('é', lookup('utf-16le')) + assert decode(b'\xe9\x00', 'UTF-16') == ('é', lookup('utf-16le')) + + assert decode(b'\xe9\x00', 'UTF-16BE') == ('\ue900', lookup('utf-16be')) + assert decode(b'\x00\xe9', 'UTF-16LE') == ('\ue900', lookup('utf-16le')) + assert decode(b'\x00\xe9', 'UTF-16') == ('\ue900', lookup('utf-16le')) + + +def test_encode(): + assert encode('é', 'latin1') == b'\xe9' + assert encode('é', 'utf8') == b'\xc3\xa9' + assert encode('é', 'utf8') == b'\xc3\xa9' + assert encode('é', 'utf-16') == b'\xe9\x00' + assert encode('é', 'utf-16le') == b'\xe9\x00' + assert encode('é', 'utf-16be') == b'\x00\xe9' + + +def test_iter_decode(): + def iter_decode_to_string(input, fallback_encoding): + output, _encoding = iter_decode(input, fallback_encoding) + return ''.join(output) + assert iter_decode_to_string([], 'latin1') == '' + assert iter_decode_to_string([b''], 'latin1') == '' + assert iter_decode_to_string([b'\xe9'], 'latin1') == 'é' + assert iter_decode_to_string([b'hello'], 'latin1') == 'hello' + assert iter_decode_to_string([b'he', b'llo'], 'latin1') == 'hello' + assert iter_decode_to_string([b'hell', b'o'], 'latin1') == 'hello' + assert iter_decode_to_string([b'\xc3\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([b'\xEF\xBB\xBF\xc3\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'\xEF\xBB\xBF', b'\xc3', b'\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'\xEF\xBB\xBF', b'a', b'\xc3'], 'latin1') == 'a\uFFFD' + assert iter_decode_to_string([ + b'', b'\xEF', b'', b'', b'\xBB\xBF\xc3', b'\xa9'], 'latin1') == 'é' + assert iter_decode_to_string([b'\xEF\xBB\xBF'], 'latin1') == '' + assert iter_decode_to_string([b'\xEF\xBB'], 'latin1') == 'ï»' + assert iter_decode_to_string([b'\xFE\xFF\x00\xe9'], 'latin1') == 'é' + assert iter_decode_to_string([b'\xFF\xFE\xe9\x00'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'', b'\xFF', b'', b'', b'\xFE\xe9', b'\x00'], 'latin1') == 'é' + assert iter_decode_to_string([ + b'', b'h\xe9', b'llo'], 'x-user-defined') == 'h\uF7E9llo' + + +def test_iter_encode(): + assert b''.join(iter_encode([], 'latin1')) == b'' + assert b''.join(iter_encode([''], 'latin1')) == b'' + assert b''.join(iter_encode(['é'], 'latin1')) == b'\xe9' + assert b''.join(iter_encode(['', 'é', '', ''], 'latin1')) == b'\xe9' + assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16')) == b'\xe9\x00' + assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16le')) == b'\xe9\x00' + assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16be')) == b'\x00\xe9' + assert b''.join(iter_encode([ + '', 'h\uF7E9', '', 'llo'], 'x-user-defined')) == b'h\xe9llo' + + +def test_x_user_defined(): + encoded = b'2,\x0c\x0b\x1aO\xd9#\xcb\x0f\xc9\xbbt\xcf\xa8\xca' + decoded = '2,\x0c\x0b\x1aO\uf7d9#\uf7cb\x0f\uf7c9\uf7bbt\uf7cf\uf7a8\uf7ca' + encoded = b'aa' + decoded = 'aa' + assert decode(encoded, 'x-user-defined') == (decoded, lookup('x-user-defined')) + assert encode(decoded, 'x-user-defined') == encoded diff --git a/winvenv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py b/winvenv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py new file mode 100644 index 0000000..d16e326 --- /dev/null +++ b/winvenv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py @@ -0,0 +1,325 @@ +# coding: utf-8 +""" + + webencodings.x_user_defined + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + An implementation of the x-user-defined encoding. + + :copyright: Copyright 2012 by Simon Sapin + :license: BSD, see LICENSE for details. + +""" + +from __future__ import unicode_literals + +import codecs + + +### Codec APIs + +class Codec(codecs.Codec): + + def encode(self, input, errors='strict'): + return codecs.charmap_encode(input, errors, encoding_table) + + def decode(self, input, errors='strict'): + return codecs.charmap_decode(input, errors, decoding_table) + + +class IncrementalEncoder(codecs.IncrementalEncoder): + def encode(self, input, final=False): + return codecs.charmap_encode(input, self.errors, encoding_table)[0] + + +class IncrementalDecoder(codecs.IncrementalDecoder): + def decode(self, input, final=False): + return codecs.charmap_decode(input, self.errors, decoding_table)[0] + + +class StreamWriter(Codec, codecs.StreamWriter): + pass + + +class StreamReader(Codec, codecs.StreamReader): + pass + + +### encodings module API + +codec_info = codecs.CodecInfo( + name='x-user-defined', + encode=Codec().encode, + decode=Codec().decode, + incrementalencoder=IncrementalEncoder, + incrementaldecoder=IncrementalDecoder, + streamreader=StreamReader, + streamwriter=StreamWriter, +) + + +### Decoding Table + +# Python 3: +# for c in range(256): print(' %r' % chr(c if c < 128 else c + 0xF700)) +decoding_table = ( + '\x00' + '\x01' + '\x02' + '\x03' + '\x04' + '\x05' + '\x06' + '\x07' + '\x08' + '\t' + '\n' + '\x0b' + '\x0c' + '\r' + '\x0e' + '\x0f' + '\x10' + '\x11' + '\x12' + '\x13' + '\x14' + '\x15' + '\x16' + '\x17' + '\x18' + '\x19' + '\x1a' + '\x1b' + '\x1c' + '\x1d' + '\x1e' + '\x1f' + ' ' + '!' + '"' + '#' + '$' + '%' + '&' + "'" + '(' + ')' + '*' + '+' + ',' + '-' + '.' + '/' + '0' + '1' + '2' + '3' + '4' + '5' + '6' + '7' + '8' + '9' + ':' + ';' + '<' + '=' + '>' + '?' + '@' + 'A' + 'B' + 'C' + 'D' + 'E' + 'F' + 'G' + 'H' + 'I' + 'J' + 'K' + 'L' + 'M' + 'N' + 'O' + 'P' + 'Q' + 'R' + 'S' + 'T' + 'U' + 'V' + 'W' + 'X' + 'Y' + 'Z' + '[' + '\\' + ']' + '^' + '_' + '`' + 'a' + 'b' + 'c' + 'd' + 'e' + 'f' + 'g' + 'h' + 'i' + 'j' + 'k' + 'l' + 'm' + 'n' + 'o' + 'p' + 'q' + 'r' + 's' + 't' + 'u' + 'v' + 'w' + 'x' + 'y' + 'z' + '{' + '|' + '}' + '~' + '\x7f' + '\uf780' + '\uf781' + '\uf782' + '\uf783' + '\uf784' + '\uf785' + '\uf786' + '\uf787' + '\uf788' + '\uf789' + '\uf78a' + '\uf78b' + '\uf78c' + '\uf78d' + '\uf78e' + '\uf78f' + '\uf790' + '\uf791' + '\uf792' + '\uf793' + '\uf794' + '\uf795' + '\uf796' + '\uf797' + '\uf798' + '\uf799' + '\uf79a' + '\uf79b' + '\uf79c' + '\uf79d' + '\uf79e' + '\uf79f' + '\uf7a0' + '\uf7a1' + '\uf7a2' + '\uf7a3' + '\uf7a4' + '\uf7a5' + '\uf7a6' + '\uf7a7' + '\uf7a8' + '\uf7a9' + '\uf7aa' + '\uf7ab' + '\uf7ac' + '\uf7ad' + '\uf7ae' + '\uf7af' + '\uf7b0' + '\uf7b1' + '\uf7b2' + '\uf7b3' + '\uf7b4' + '\uf7b5' + '\uf7b6' + '\uf7b7' + '\uf7b8' + '\uf7b9' + '\uf7ba' + '\uf7bb' + '\uf7bc' + '\uf7bd' + '\uf7be' + '\uf7bf' + '\uf7c0' + '\uf7c1' + '\uf7c2' + '\uf7c3' + '\uf7c4' + '\uf7c5' + '\uf7c6' + '\uf7c7' + '\uf7c8' + '\uf7c9' + '\uf7ca' + '\uf7cb' + '\uf7cc' + '\uf7cd' + '\uf7ce' + '\uf7cf' + '\uf7d0' + '\uf7d1' + '\uf7d2' + '\uf7d3' + '\uf7d4' + '\uf7d5' + '\uf7d6' + '\uf7d7' + '\uf7d8' + '\uf7d9' + '\uf7da' + '\uf7db' + '\uf7dc' + '\uf7dd' + '\uf7de' + '\uf7df' + '\uf7e0' + '\uf7e1' + '\uf7e2' + '\uf7e3' + '\uf7e4' + '\uf7e5' + '\uf7e6' + '\uf7e7' + '\uf7e8' + '\uf7e9' + '\uf7ea' + '\uf7eb' + '\uf7ec' + '\uf7ed' + '\uf7ee' + '\uf7ef' + '\uf7f0' + '\uf7f1' + '\uf7f2' + '\uf7f3' + '\uf7f4' + '\uf7f5' + '\uf7f6' + '\uf7f7' + '\uf7f8' + '\uf7f9' + '\uf7fa' + '\uf7fb' + '\uf7fc' + '\uf7fd' + '\uf7fe' + '\uf7ff' +) + +### Encoding table +encoding_table = codecs.charmap_build(decoding_table) diff --git a/winvenv/Lib/site-packages/pkg_resources/__init__.py b/winvenv/Lib/site-packages/pkg_resources/__init__.py new file mode 100644 index 0000000..6ca68da --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/__init__.py @@ -0,0 +1,3171 @@ +# coding: utf-8 +""" +Package resource API +-------------------- + +A resource is a logical file contained within a package, or a logical +subdirectory thereof. The package resource API expects resource names +to have their path parts separated with ``/``, *not* whatever the local +path separator is. Do not use os.path operations to manipulate resource +names being passed into the API. + +The package resource API is designed to work with normal filesystem packages, +.egg files, and unpacked .egg files. It can also work in a limited way with +.zip files and with custom PEP 302 loaders that support the ``get_data()`` +method. +""" + +from __future__ import absolute_import + +import sys +import os +import io +import time +import re +import types +import zipfile +import zipimport +import warnings +import stat +import functools +import pkgutil +import operator +import platform +import collections +import plistlib +import email.parser +import errno +import tempfile +import textwrap +import itertools +import inspect +from pkgutil import get_importer + +try: + import _imp +except ImportError: + # Python 3.2 compatibility + import imp as _imp + +try: + FileExistsError +except NameError: + FileExistsError = OSError + +from pkg_resources.extern import six +from pkg_resources.extern.six.moves import urllib, map, filter + +# capture these to bypass sandboxing +from os import utime +try: + from os import mkdir, rename, unlink + WRITE_SUPPORT = True +except ImportError: + # no write support, probably under GAE + WRITE_SUPPORT = False + +from os import open as os_open +from os.path import isdir, split + +try: + import importlib.machinery as importlib_machinery + # access attribute to force import under delayed import mechanisms. + importlib_machinery.__name__ +except ImportError: + importlib_machinery = None + +from . import py31compat +from pkg_resources.extern import appdirs +from pkg_resources.extern import packaging +__import__('pkg_resources.extern.packaging.version') +__import__('pkg_resources.extern.packaging.specifiers') +__import__('pkg_resources.extern.packaging.requirements') +__import__('pkg_resources.extern.packaging.markers') + + +__metaclass__ = type + + +if (3, 0) < sys.version_info < (3, 4): + raise RuntimeError("Python 3.4 or later is required") + +if six.PY2: + # Those builtin exceptions are only defined in Python 3 + PermissionError = None + NotADirectoryError = None + +# declare some globals that will be defined later to +# satisfy the linters. +require = None +working_set = None +add_activation_listener = None +resources_stream = None +cleanup_resources = None +resource_dir = None +resource_stream = None +set_extraction_path = None +resource_isdir = None +resource_string = None +iter_entry_points = None +resource_listdir = None +resource_filename = None +resource_exists = None +_distribution_finders = None +_namespace_handlers = None +_namespace_packages = None + + +class PEP440Warning(RuntimeWarning): + """ + Used when there is an issue with a version or specifier not complying with + PEP 440. + """ + + +def parse_version(v): + try: + return packaging.version.Version(v) + except packaging.version.InvalidVersion: + return packaging.version.LegacyVersion(v) + + +_state_vars = {} + + +def _declare_state(vartype, **kw): + globals().update(kw) + _state_vars.update(dict.fromkeys(kw, vartype)) + + +def __getstate__(): + state = {} + g = globals() + for k, v in _state_vars.items(): + state[k] = g['_sget_' + v](g[k]) + return state + + +def __setstate__(state): + g = globals() + for k, v in state.items(): + g['_sset_' + _state_vars[k]](k, g[k], v) + return state + + +def _sget_dict(val): + return val.copy() + + +def _sset_dict(key, ob, state): + ob.clear() + ob.update(state) + + +def _sget_object(val): + return val.__getstate__() + + +def _sset_object(key, ob, state): + ob.__setstate__(state) + + +_sget_none = _sset_none = lambda *args: None + + +def get_supported_platform(): + """Return this platform's maximum compatible version. + + distutils.util.get_platform() normally reports the minimum version + of Mac OS X that would be required to *use* extensions produced by + distutils. But what we want when checking compatibility is to know the + version of Mac OS X that we are *running*. To allow usage of packages that + explicitly require a newer version of Mac OS X, we must also know the + current version of the OS. + + If this condition occurs for any other platform with a version in its + platform strings, this function should be extended accordingly. + """ + plat = get_build_platform() + m = macosVersionString.match(plat) + if m is not None and sys.platform == "darwin": + try: + plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + except ValueError: + # not Mac OS X + pass + return plat + + +__all__ = [ + # Basic resource access and distribution/entry point discovery + 'require', 'run_script', 'get_provider', 'get_distribution', + 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'iter_entry_points', + 'resource_string', 'resource_stream', 'resource_filename', + 'resource_listdir', 'resource_exists', 'resource_isdir', + + # Environmental control + 'declare_namespace', 'working_set', 'add_activation_listener', + 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'get_default_cache', + + # Primary implementation classes + 'Environment', 'WorkingSet', 'ResourceManager', + 'Distribution', 'Requirement', 'EntryPoint', + + # Exceptions + 'ResolutionError', 'VersionConflict', 'DistributionNotFound', + 'UnknownExtra', 'ExtractionError', + + # Warnings + 'PEP440Warning', + + # Parsing functions and string utilities + 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', + 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', + + # filesystem utilities + 'ensure_directory', 'normalize_path', + + # Distribution "precedence" constants + 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', + + # "Provider" interfaces, implementations, and registration/lookup APIs + 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', + 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', + 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', + 'register_finder', 'register_namespace_handler', 'register_loader_type', + 'fixup_namespace_packages', 'get_importer', + + # Warnings + 'PkgResourcesDeprecationWarning', + + # Deprecated/backward compatibility only + 'run_main', 'AvailableDistributions', +] + + +class ResolutionError(Exception): + """Abstract base for dependency resolution errors""" + + def __repr__(self): + return self.__class__.__name__ + repr(self.args) + + +class VersionConflict(ResolutionError): + """ + An already-installed version conflicts with the requested version. + + Should be initialized with the installed Distribution and the requested + Requirement. + """ + + _template = "{self.dist} is installed but {self.req} is required" + + @property + def dist(self): + return self.args[0] + + @property + def req(self): + return self.args[1] + + def report(self): + return self._template.format(**locals()) + + def with_context(self, required_by): + """ + If required_by is non-empty, return a version of self that is a + ContextualVersionConflict. + """ + if not required_by: + return self + args = self.args + (required_by,) + return ContextualVersionConflict(*args) + + +class ContextualVersionConflict(VersionConflict): + """ + A VersionConflict that accepts a third parameter, the set of the + requirements that required the installed Distribution. + """ + + _template = VersionConflict._template + ' by {self.required_by}' + + @property + def required_by(self): + return self.args[2] + + +class DistributionNotFound(ResolutionError): + """A requested distribution was not found""" + + _template = ("The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}") + + @property + def req(self): + return self.args[0] + + @property + def requirers(self): + return self.args[1] + + @property + def requirers_str(self): + if not self.requirers: + return 'the application' + return ', '.join(self.requirers) + + def report(self): + return self._template.format(**locals()) + + def __str__(self): + return self.report() + + +class UnknownExtra(ResolutionError): + """Distribution doesn't have an "extra feature" of the given name""" + + +_provider_factories = {} + +PY_MAJOR = sys.version[:3] +EGG_DIST = 3 +BINARY_DIST = 2 +SOURCE_DIST = 1 +CHECKOUT_DIST = 0 +DEVELOP_DIST = -1 + + +def register_loader_type(loader_type, provider_factory): + """Register `provider_factory` to make providers for `loader_type` + + `loader_type` is the type or class of a PEP 302 ``module.__loader__``, + and `provider_factory` is a function that, passed a *module* object, + returns an ``IResourceProvider`` for that module. + """ + _provider_factories[loader_type] = provider_factory + + +def get_provider(moduleOrReq): + """Return an IResourceProvider for the named module or requirement""" + if isinstance(moduleOrReq, Requirement): + return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0] + try: + module = sys.modules[moduleOrReq] + except KeyError: + __import__(moduleOrReq) + module = sys.modules[moduleOrReq] + loader = getattr(module, '__loader__', None) + return _find_adapter(_provider_factories, loader)(module) + + +def _macosx_vers(_cache=[]): + if not _cache: + version = platform.mac_ver()[0] + # fallback for MacPorts + if version == '': + plist = '/System/Library/CoreServices/SystemVersion.plist' + if os.path.exists(plist): + if hasattr(plistlib, 'readPlist'): + plist_content = plistlib.readPlist(plist) + if 'ProductVersion' in plist_content: + version = plist_content['ProductVersion'] + + _cache.append(version.split('.')) + return _cache[0] + + +def _macosx_arch(machine): + return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) + + +def get_build_platform(): + """Return this platform's string for platform-specific distributions + + XXX Currently this is the same as ``distutils.util.get_platform()``, but it + needs some hacks for Linux and Mac OS X. + """ + from sysconfig import get_platform + + plat = get_platform() + if sys.platform == "darwin" and not plat.startswith('macosx-'): + try: + version = _macosx_vers() + machine = os.uname()[4].replace(" ", "_") + return "macosx-%d.%d-%s" % ( + int(version[0]), int(version[1]), + _macosx_arch(machine), + ) + except ValueError: + # if someone is running a non-Mac darwin system, this will fall + # through to the default implementation + pass + return plat + + +macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") +darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") +# XXX backward compat +get_platform = get_build_platform + + +def compatible_platforms(provided, required): + """Can code for the `provided` platform run on the `required` platform? + + Returns true if either platform is ``None``, or the platforms are equal. + + XXX Needs compatibility checks for Linux and other unixy OSes. + """ + if provided is None or required is None or provided == required: + # easy case + return True + + # Mac OS X special cases + reqMac = macosVersionString.match(required) + if reqMac: + provMac = macosVersionString.match(provided) + + # is this a Mac package? + if not provMac: + # this is backwards compatibility for packages built before + # setuptools 0.6. All packages built after this point will + # use the new macosx designation. + provDarwin = darwinVersionString.match(provided) + if provDarwin: + dversion = int(provDarwin.group(1)) + macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) + if dversion == 7 and macosversion >= "10.3" or \ + dversion == 8 and macosversion >= "10.4": + return True + # egg isn't macosx or legacy darwin + return False + + # are they the same major version and machine type? + if provMac.group(1) != reqMac.group(1) or \ + provMac.group(3) != reqMac.group(3): + return False + + # is the required OS major update >= the provided one? + if int(provMac.group(2)) > int(reqMac.group(2)): + return False + + return True + + # XXX Linux and other platforms' special cases should go here + return False + + +def run_script(dist_spec, script_name): + """Locate distribution `dist_spec` and run its `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + require(dist_spec)[0].run_script(script_name, ns) + + +# backward compatibility +run_main = run_script + + +def get_distribution(dist): + """Return a current distribution object for a Requirement or string""" + if isinstance(dist, six.string_types): + dist = Requirement.parse(dist) + if isinstance(dist, Requirement): + dist = get_provider(dist) + if not isinstance(dist, Distribution): + raise TypeError("Expected string, Requirement, or Distribution", dist) + return dist + + +def load_entry_point(dist, group, name): + """Return `name` entry point of `group` for `dist` or raise ImportError""" + return get_distribution(dist).load_entry_point(group, name) + + +def get_entry_map(dist, group=None): + """Return the entry point map for `group`, or the full entry map""" + return get_distribution(dist).get_entry_map(group) + + +def get_entry_info(dist, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return get_distribution(dist).get_entry_info(group, name) + + +class IMetadataProvider: + def has_metadata(name): + """Does the package's distribution contain the named metadata?""" + + def get_metadata(name): + """The named metadata resource as a string""" + + def get_metadata_lines(name): + """Yield named metadata resource as list of non-blank non-comment lines + + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" + + def metadata_isdir(name): + """Is the named metadata a directory? (like ``os.path.isdir()``)""" + + def metadata_listdir(name): + """List of metadata names in the directory (like ``os.listdir()``)""" + + def run_script(script_name, namespace): + """Execute the named script in the supplied namespace dictionary""" + + +class IResourceProvider(IMetadataProvider): + """An object that provides access to package resources""" + + def get_resource_filename(manager, resource_name): + """Return a true filesystem path for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_stream(manager, resource_name): + """Return a readable file-like object for `resource_name` + + `manager` must be an ``IResourceManager``""" + + def get_resource_string(manager, resource_name): + """Return a string containing the contents of `resource_name` + + `manager` must be an ``IResourceManager``""" + + def has_resource(resource_name): + """Does the package contain the named resource?""" + + def resource_isdir(resource_name): + """Is the named resource a directory? (like ``os.path.isdir()``)""" + + def resource_listdir(resource_name): + """List of resource names in the directory (like ``os.listdir()``)""" + + +class WorkingSet: + """A collection of active distributions on sys.path (or a similar list)""" + + def __init__(self, entries=None): + """Create working set from list of path entries (default=sys.path)""" + self.entries = [] + self.entry_keys = {} + self.by_key = {} + self.callbacks = [] + + if entries is None: + entries = sys.path + + for entry in entries: + self.add_entry(entry) + + @classmethod + def _build_master(cls): + """ + Prepare the master working set. + """ + ws = cls() + try: + from __main__ import __requires__ + except ImportError: + # The main program does not list any requirements + return ws + + # ensure the requirements are met + try: + ws.require(__requires__) + except VersionConflict: + return cls._build_from_requirements(__requires__) + + return ws + + @classmethod + def _build_from_requirements(cls, req_spec): + """ + Build a working set from a requirement spec. Rewrites sys.path. + """ + # try it without defaults already on sys.path + # by starting with an empty path + ws = cls([]) + reqs = parse_requirements(req_spec) + dists = ws.resolve(reqs, Environment()) + for dist in dists: + ws.add(dist) + + # add any missing entries from sys.path + for entry in sys.path: + if entry not in ws.entries: + ws.add_entry(entry) + + # then copy back to sys.path + sys.path[:] = ws.entries + return ws + + def add_entry(self, entry): + """Add a path item to ``.entries``, finding any distributions on it + + ``find_distributions(entry, True)`` is used to find distributions + corresponding to the path entry, and they are added. `entry` is + always appended to ``.entries``, even if it is already present. + (This is because ``sys.path`` can contain the same value more than + once, and the ``.entries`` of the ``sys.path`` WorkingSet should always + equal ``sys.path``.) + """ + self.entry_keys.setdefault(entry, []) + self.entries.append(entry) + for dist in find_distributions(entry, True): + self.add(dist, entry, False) + + def __contains__(self, dist): + """True if `dist` is the active distribution for its project""" + return self.by_key.get(dist.key) == dist + + def find(self, req): + """Find a distribution matching requirement `req` + + If there is an active distribution for the requested project, this + returns it as long as it meets the version requirement specified by + `req`. But, if there is an active distribution for the project and it + does *not* meet the `req` requirement, ``VersionConflict`` is raised. + If there is no active distribution for the requested project, ``None`` + is returned. + """ + dist = self.by_key.get(req.key) + if dist is not None and dist not in req: + # XXX add more info + raise VersionConflict(dist, req) + return dist + + def iter_entry_points(self, group, name=None): + """Yield entry point objects from `group` matching `name` + + If `name` is None, yields all entry points in `group` from all + distributions in the working set, otherwise only ones matching + both `group` and `name` are yielded (in distribution order). + """ + return ( + entry + for dist in self + for entry in dist.get_entry_map(group).values() + if name is None or name == entry.name + ) + + def run_script(self, requires, script_name): + """Locate distribution for `requires` and run `script_name` script""" + ns = sys._getframe(1).f_globals + name = ns['__name__'] + ns.clear() + ns['__name__'] = name + self.require(requires)[0].run_script(script_name, ns) + + def __iter__(self): + """Yield distributions for non-duplicate projects in the working set + + The yield order is the order in which the items' path entries were + added to the working set. + """ + seen = {} + for item in self.entries: + if item not in self.entry_keys: + # workaround a cache issue + continue + + for key in self.entry_keys[item]: + if key not in seen: + seen[key] = 1 + yield self.by_key[key] + + def add(self, dist, entry=None, insert=True, replace=False): + """Add `dist` to working set, associated with `entry` + + If `entry` is unspecified, it defaults to the ``.location`` of `dist`. + On exit from this routine, `entry` is added to the end of the working + set's ``.entries`` (if it wasn't already present). + + `dist` is only added to the working set if it's for a project that + doesn't already have a distribution in the set, unless `replace=True`. + If it's added, any callbacks registered with the ``subscribe()`` method + will be called. + """ + if insert: + dist.insert_on(self.entries, entry, replace=replace) + + if entry is None: + entry = dist.location + keys = self.entry_keys.setdefault(entry, []) + keys2 = self.entry_keys.setdefault(dist.location, []) + if not replace and dist.key in self.by_key: + # ignore hidden distros + return + + self.by_key[dist.key] = dist + if dist.key not in keys: + keys.append(dist.key) + if dist.key not in keys2: + keys2.append(dist.key) + self._added_new(dist) + + def resolve(self, requirements, env=None, installer=None, + replace_conflicting=False, extras=None): + """List all distributions needed to (recursively) meet `requirements` + + `requirements` must be a sequence of ``Requirement`` objects. `env`, + if supplied, should be an ``Environment`` instance. If + not supplied, it defaults to all distributions available within any + entry or distribution in the working set. `installer`, if supplied, + will be invoked with each requirement that cannot be met by an + already-installed distribution; it should return a ``Distribution`` or + ``None``. + + Unless `replace_conflicting=True`, raises a VersionConflict exception + if + any requirements are found on the path that have the correct name but + the wrong version. Otherwise, if an `installer` is supplied it will be + invoked to obtain the correct version of the requirement and activate + it. + + `extras` is a list of the extras to be used with these requirements. + This is important because extra requirements may look like `my_req; + extra = "my_extra"`, which would otherwise be interpreted as a purely + optional requirement. Instead, we want to be able to assert that these + requirements are truly required. + """ + + # set up the stack + requirements = list(requirements)[::-1] + # set of processed requirements + processed = {} + # key -> dist + best = {} + to_activate = [] + + req_extras = _ReqExtras() + + # Mapping of requirement to set of distributions that required it; + # useful for reporting info about conflicts. + required_by = collections.defaultdict(set) + + while requirements: + # process dependencies breadth-first + req = requirements.pop(0) + if req in processed: + # Ignore cyclic or redundant dependencies + continue + + if not req_extras.markers_pass(req, extras): + continue + + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None or (dist not in req and replace_conflicting): + ws = self + if env is None: + if dist is None: + env = Environment(self.entries) + else: + # Use an empty environment and workingset to avoid + # any further conflicts with the conflicting + # distribution + env = Environment([]) + ws = WorkingSet([]) + dist = best[req.key] = env.best_match( + req, ws, installer, + replace_conflicting=replace_conflicting + ) + if dist is None: + requirers = required_by.get(req, None) + raise DistributionNotFound(req, requirers) + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + dependent_req = required_by[req] + raise VersionConflict(dist, req).with_context(dependent_req) + + # push the new requirements onto the stack + new_requirements = dist.requires(req.extras)[::-1] + requirements.extend(new_requirements) + + # Register the new requirements needed by req + for new_requirement in new_requirements: + required_by[new_requirement].add(req.project_name) + req_extras[new_requirement] = req.extras + + processed[req] = True + + # return list of distros to activate + return to_activate + + def find_plugins( + self, plugin_env, full_env=None, installer=None, fallback=True): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + # add plugins+libs to sys.path + map(working_set.add, distributions) + # display errors + print('Could not load', errors) + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + # scan project names in alphabetic order + plugin_projects.sort() + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + # put all our entries in shadow_set + list(map(shadow_set.add, self)) + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError as v: + # save error info + error_info[dist] = v + if fallback: + # try the next older version of project + continue + else: + # give up on this project, keep going + break + + else: + list(map(shadow_set.add, resolvees)) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + def require(self, *requirements): + """Ensure that distributions matching `requirements` are activated + + `requirements` must be a string or a (possibly-nested) sequence + thereof, specifying the distributions and versions required. The + return value is a sequence of the distributions that needed to be + activated to fulfill the requirements; all relevant distributions are + included, even if they were already activated in this working set. + """ + needed = self.resolve(parse_requirements(requirements)) + + for dist in needed: + self.add(dist) + + return needed + + def subscribe(self, callback, existing=True): + """Invoke `callback` for all distributions + + If `existing=True` (default), + call on all existing ones, as well. + """ + if callback in self.callbacks: + return + self.callbacks.append(callback) + if not existing: + return + for dist in self: + callback(dist) + + def _added_new(self, dist): + for callback in self.callbacks: + callback(dist) + + def __getstate__(self): + return ( + self.entries[:], self.entry_keys.copy(), self.by_key.copy(), + self.callbacks[:] + ) + + def __setstate__(self, e_k_b_c): + entries, keys, by_key, callbacks = e_k_b_c + self.entries = entries[:] + self.entry_keys = keys.copy() + self.by_key = by_key.copy() + self.callbacks = callbacks[:] + + +class _ReqExtras(dict): + """ + Map each requirement to the extras that demanded it. + """ + + def markers_pass(self, req, extras=None): + """ + Evaluate markers for req against each extra that + demanded it. + + Return False if the req has a marker and fails + evaluation. Otherwise, return True. + """ + extra_evals = ( + req.marker.evaluate({'extra': extra}) + for extra in self.get(req, ()) + (extras or (None,)) + ) + return not req.marker or any(extra_evals) + + +class Environment: + """Searchable snapshot of distributions on a search path""" + + def __init__( + self, search_path=None, platform=get_supported_platform(), + python=PY_MAJOR): + """Snapshot distributions available on a search path + + Any distributions found on `search_path` are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. + + `platform` is an optional string specifying the name of the platform + that platform-specific distributions must be compatible with. If + unspecified, it defaults to the current platform. `python` is an + optional string naming the desired version of Python (e.g. ``'3.6'``); + it defaults to the current version. + + You may explicitly set `platform` (and/or `python`) to ``None`` if you + wish to map *all* distributions, not just those compatible with the + running platform or Python version. + """ + self._distmap = {} + self.platform = platform + self.python = python + self.scan(search_path) + + def can_add(self, dist): + """Is distribution `dist` acceptable for this environment? + + The distribution must match the platform and python version + requirements specified when this environment was created, or False + is returned. + """ + py_compat = ( + self.python is None + or dist.py_version is None + or dist.py_version == self.python + ) + return py_compat and compatible_platforms(dist.platform, self.platform) + + def remove(self, dist): + """Remove `dist` from the environment""" + self._distmap[dist.key].remove(dist) + + def scan(self, search_path=None): + """Scan `search_path` for distributions usable in this environment + + Any distributions found are added to the environment. + `search_path` should be a sequence of ``sys.path`` items. If not + supplied, ``sys.path`` is used. Only distributions conforming to + the platform/python version defined at initialization are added. + """ + if search_path is None: + search_path = sys.path + + for item in search_path: + for dist in find_distributions(item): + self.add(dist) + + def __getitem__(self, project_name): + """Return a newest-to-oldest list of distributions for `project_name` + + Uses case-insensitive `project_name` comparison, assuming all the + project's distributions use their project's name converted to all + lowercase as their key. + + """ + distribution_key = project_name.lower() + return self._distmap.get(distribution_key, []) + + def add(self, dist): + """Add `dist` if we ``can_add()`` it and it has not already been added + """ + if self.can_add(dist) and dist.has_version(): + dists = self._distmap.setdefault(dist.key, []) + if dist not in dists: + dists.append(dist) + dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) + + def best_match( + self, req, working_set, installer=None, replace_conflicting=False): + """Find distribution best matching `req` and usable on `working_set` + + This calls the ``find(req)`` method of the `working_set` to see if a + suitable distribution is already active. (This may raise + ``VersionConflict`` if an unsuitable version of the project is already + active in the specified `working_set`.) If a suitable distribution + isn't active, this method returns the newest distribution in the + environment that meets the ``Requirement`` in `req`. If no suitable + distribution is found, and `installer` is supplied, then the result of + calling the environment's ``obtain(req, installer)`` method will be + returned. + """ + try: + dist = working_set.find(req) + except VersionConflict: + if not replace_conflicting: + raise + dist = None + if dist is not None: + return dist + for dist in self[req.key]: + if dist in req: + return dist + # try to download/install + return self.obtain(req, installer) + + def obtain(self, requirement, installer=None): + """Obtain a distribution matching `requirement` (e.g. via download) + + Obtain a distro that matches requirement (e.g. via download). In the + base ``Environment`` class, this routine just returns + ``installer(requirement)``, unless `installer` is None, in which case + None is returned instead. This method is a hook that allows subclasses + to attempt other ways of obtaining a distribution before falling back + to the `installer` argument.""" + if installer is not None: + return installer(requirement) + + def __iter__(self): + """Yield the unique project names of the available distributions""" + for key in self._distmap.keys(): + if self[key]: + yield key + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other, Distribution): + self.add(other) + elif isinstance(other, Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + +# XXX backward compatibility +AvailableDistributions = Environment + + +class ExtractionError(RuntimeError): + """An error occurred extracting a resource + + The following attributes are available from instances of this exception: + + manager + The resource manager that raised this exception + + cache_path + The base directory for resource extraction + + original_error + The exception instance that caused extraction to fail + """ + + +class ResourceManager: + """Manage resource extraction and packages""" + extraction_path = None + + def __init__(self): + self.cached_files = {} + + def resource_exists(self, package_or_requirement, resource_name): + """Does the named resource exist?""" + return get_provider(package_or_requirement).has_resource(resource_name) + + def resource_isdir(self, package_or_requirement, resource_name): + """Is the named resource an existing directory?""" + return get_provider(package_or_requirement).resource_isdir( + resource_name + ) + + def resource_filename(self, package_or_requirement, resource_name): + """Return a true filesystem path for specified resource""" + return get_provider(package_or_requirement).get_resource_filename( + self, resource_name + ) + + def resource_stream(self, package_or_requirement, resource_name): + """Return a readable file-like object for specified resource""" + return get_provider(package_or_requirement).get_resource_stream( + self, resource_name + ) + + def resource_string(self, package_or_requirement, resource_name): + """Return specified resource as a string""" + return get_provider(package_or_requirement).get_resource_string( + self, resource_name + ) + + def resource_listdir(self, package_or_requirement, resource_name): + """List the contents of the named resource directory""" + return get_provider(package_or_requirement).resource_listdir( + resource_name + ) + + def extraction_error(self): + """Give an error message for problems extracting file(s)""" + + old_exc = sys.exc_info()[1] + cache_path = self.extraction_path or get_default_cache() + + tmpl = textwrap.dedent(""" + Can't extract file(s) to egg cache + + The following error occurred while trying to extract file(s) + to the Python egg cache: + + {old_exc} + + The Python egg cache directory is currently set to: + + {cache_path} + + Perhaps your account does not have write access to this directory? + You can change the cache directory by setting the PYTHON_EGG_CACHE + environment variable to point to an accessible directory. + """).lstrip() + err = ExtractionError(tmpl.format(**locals())) + err.manager = self + err.cache_path = cache_path + err.original_error = old_exc + raise err + + def get_cache_path(self, archive_name, names=()): + """Return absolute location in cache for `archive_name` and `names` + + The parent directory of the resulting path will be created if it does + not already exist. `archive_name` should be the base filename of the + enclosing egg (which may not be the name of the enclosing zipfile!), + including its ".egg" extension. `names`, if provided, should be a + sequence of path name parts "under" the egg's extraction location. + + This method should only be called by resource providers that need to + obtain an extraction location, and only for names they intend to + extract, as it tracks the generated names for possible cleanup later. + """ + extract_path = self.extraction_path or get_default_cache() + target_path = os.path.join(extract_path, archive_name + '-tmp', *names) + try: + _bypass_ensure_directory(target_path) + except Exception: + self.extraction_error() + + self._warn_unsafe_extraction_path(extract_path) + + self.cached_files[target_path] = 1 + return target_path + + @staticmethod + def _warn_unsafe_extraction_path(path): + """ + If the default extraction path is overridden and set to an insecure + location, such as /tmp, it opens up an opportunity for an attacker to + replace an extracted file with an unauthorized payload. Warn the user + if a known insecure location is used. + + See Distribute #375 for more details. + """ + if os.name == 'nt' and not path.startswith(os.environ['windir']): + # On Windows, permissions are generally restrictive by default + # and temp directories are not writable by other users, so + # bypass the warning. + return + mode = os.stat(path).st_mode + if mode & stat.S_IWOTH or mode & stat.S_IWGRP: + msg = ( + "%s is writable by group/others and vulnerable to attack " + "when " + "used with get_resource_filename. Consider a more secure " + "location (set with .set_extraction_path or the " + "PYTHON_EGG_CACHE environment variable)." % path + ) + warnings.warn(msg, UserWarning) + + def postprocess(self, tempname, filename): + """Perform any platform-specific postprocessing of `tempname` + + This is where Mac header rewrites should be done; other platforms don't + have anything special they should do. + + Resource providers should call this method ONLY after successfully + extracting a compressed resource. They must NOT call it on resources + that are already in the filesystem. + + `tempname` is the current (temporary) name of the file, and `filename` + is the name it will be renamed to by the caller after this routine + returns. + """ + + if os.name == 'posix': + # Make the resource executable + mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 + os.chmod(tempname, mode) + + def set_extraction_path(self, path): + """Set the base path where resources will be extracted to, if needed. + + If you do not call this routine before any extractions take place, the + path defaults to the return value of ``get_default_cache()``. (Which + is based on the ``PYTHON_EGG_CACHE`` environment variable, with various + platform-specific fallbacks. See that routine's documentation for more + details.) + + Resources are extracted to subdirectories of this path based upon + information given by the ``IResourceProvider``. You may set this to a + temporary directory, but then you must call ``cleanup_resources()`` to + delete the extracted files when done. There is no guarantee that + ``cleanup_resources()`` will be able to remove all extracted files. + + (Note: you may not change the extraction path for a given resource + manager once resources have been extracted, unless you first call + ``cleanup_resources()``.) + """ + if self.cached_files: + raise ValueError( + "Can't change extraction path, files already extracted" + ) + + self.extraction_path = path + + def cleanup_resources(self, force=False): + """ + Delete all extracted resource files and directories, returning a list + of the file and directory names that could not be successfully removed. + This function does not have any concurrency protection, so it should + generally only be called when the extraction path is a temporary + directory exclusive to a single process. This method is not + automatically called; you must call it explicitly or register it as an + ``atexit`` function if you wish to ensure cleanup of a temporary + directory used for extractions. + """ + # XXX + + +def get_default_cache(): + """ + Return the ``PYTHON_EGG_CACHE`` environment variable + or a platform-relevant user cache dir for an app + named "Python-Eggs". + """ + return ( + os.environ.get('PYTHON_EGG_CACHE') + or appdirs.user_cache_dir(appname='Python-Eggs') + ) + + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """ + Convert an arbitrary string to a standard version string + """ + try: + # normalize the version + return str(packaging.version.Version(version)) + except packaging.version.InvalidVersion: + version = version.replace(' ', '.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-', '_') + + +def invalid_marker(text): + """ + Validate text as a PEP 508 environment marker; return an exception + if invalid or False otherwise. + """ + try: + evaluate_marker(text) + except SyntaxError as e: + e.filename = None + e.lineno = None + return e + return False + + +def evaluate_marker(text, extra=None): + """ + Evaluate a PEP 508 environment marker. + Return a boolean indicating the marker result in this environment. + Raise SyntaxError if marker is invalid. + + This implementation uses the 'pyparsing' module. + """ + try: + marker = packaging.markers.Marker(text) + return marker.evaluate() + except packaging.markers.InvalidMarker as e: + raise SyntaxError(e) + + +class NullProvider: + """Try to implement resources and metadata for arbitrary PEP 302 loaders""" + + egg_name = None + egg_info = None + loader = None + + def __init__(self, module): + self.loader = getattr(module, '__loader__', None) + self.module_path = os.path.dirname(getattr(module, '__file__', '')) + + def get_resource_filename(self, manager, resource_name): + return self._fn(self.module_path, resource_name) + + def get_resource_stream(self, manager, resource_name): + return io.BytesIO(self.get_resource_string(manager, resource_name)) + + def get_resource_string(self, manager, resource_name): + return self._get(self._fn(self.module_path, resource_name)) + + def has_resource(self, resource_name): + return self._has(self._fn(self.module_path, resource_name)) + + def has_metadata(self, name): + return self.egg_info and self._has(self._fn(self.egg_info, name)) + + def get_metadata(self, name): + if not self.egg_info: + return "" + value = self._get(self._fn(self.egg_info, name)) + return value.decode('utf-8') if six.PY3 else value + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + def resource_isdir(self, resource_name): + return self._isdir(self._fn(self.module_path, resource_name)) + + def metadata_isdir(self, name): + return self.egg_info and self._isdir(self._fn(self.egg_info, name)) + + def resource_listdir(self, resource_name): + return self._listdir(self._fn(self.module_path, resource_name)) + + def metadata_listdir(self, name): + if self.egg_info: + return self._listdir(self._fn(self.egg_info, name)) + return [] + + def run_script(self, script_name, namespace): + script = 'scripts/' + script_name + if not self.has_metadata(script): + raise ResolutionError( + "Script {script!r} not found in metadata at {self.egg_info!r}" + .format(**locals()), + ) + script_text = self.get_metadata(script).replace('\r\n', '\n') + script_text = script_text.replace('\r', '\n') + script_filename = self._fn(self.egg_info, script) + namespace['__file__'] = script_filename + if os.path.exists(script_filename): + source = open(script_filename).read() + code = compile(source, script_filename, 'exec') + exec(code, namespace, namespace) + else: + from linecache import cache + cache[script_filename] = ( + len(script_text), 0, script_text.split('\n'), script_filename + ) + script_code = compile(script_text, script_filename, 'exec') + exec(script_code, namespace, namespace) + + def _has(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _isdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _listdir(self, path): + raise NotImplementedError( + "Can't perform this operation for unregistered loader type" + ) + + def _fn(self, base, resource_name): + if resource_name: + return os.path.join(base, *resource_name.split('/')) + return base + + def _get(self, path): + if hasattr(self.loader, 'get_data'): + return self.loader.get_data(path) + raise NotImplementedError( + "Can't perform this operation for loaders without 'get_data()'" + ) + + +register_loader_type(object, NullProvider) + + +class EggProvider(NullProvider): + """Provider based on a virtual filesystem""" + + def __init__(self, module): + NullProvider.__init__(self, module) + self._setup_prefix() + + def _setup_prefix(self): + # we assume here that our metadata may be nested inside a "basket" + # of multiple eggs; that's why we use module_path instead of .archive + path = self.module_path + old = None + while path != old: + if _is_egg_path(path): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path + break + old = path + path, base = os.path.split(path) + + +class DefaultProvider(EggProvider): + """Provides access to package resources in the filesystem""" + + def _has(self, path): + return os.path.exists(path) + + def _isdir(self, path): + return os.path.isdir(path) + + def _listdir(self, path): + return os.listdir(path) + + def get_resource_stream(self, manager, resource_name): + return open(self._fn(self.module_path, resource_name), 'rb') + + def _get(self, path): + with open(path, 'rb') as stream: + return stream.read() + + @classmethod + def _register(cls): + loader_names = 'SourceFileLoader', 'SourcelessFileLoader', + for name in loader_names: + loader_cls = getattr(importlib_machinery, name, type(None)) + register_loader_type(loader_cls, cls) + + +DefaultProvider._register() + + +class EmptyProvider(NullProvider): + """Provider that returns nothing for all requests""" + + module_path = None + + _isdir = _has = lambda self, path: False + + def _get(self, path): + return '' + + def _listdir(self, path): + return [] + + def __init__(self): + pass + + +empty_provider = EmptyProvider() + + +class ZipManifests(dict): + """ + zip manifest builder + """ + + @classmethod + def build(cls, path): + """ + Build a dictionary similar to the zipimport directory + caches, except instead of tuples, store ZipInfo objects. + + Use a platform-specific path separator (os.sep) for the path keys + for compatibility with pypy on Windows. + """ + with zipfile.ZipFile(path) as zfile: + items = ( + ( + name.replace('/', os.sep), + zfile.getinfo(name), + ) + for name in zfile.namelist() + ) + return dict(items) + + load = build + + +class MemoizedZipManifests(ZipManifests): + """ + Memoized zipfile manifests. + """ + manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') + + def load(self, path): + """ + Load a manifest at path or return a suitable manifest already loaded. + """ + path = os.path.normpath(path) + mtime = os.stat(path).st_mtime + + if path not in self or self[path].mtime != mtime: + manifest = self.build(path) + self[path] = self.manifest_mod(manifest, mtime) + + return self[path].manifest + + +class ZipProvider(EggProvider): + """Resource support for zips and eggs""" + + eagers = None + _zip_manifests = MemoizedZipManifests() + + def __init__(self, module): + EggProvider.__init__(self, module) + self.zip_pre = self.loader.archive + os.sep + + def _zipinfo_name(self, fspath): + # Convert a virtual filename (full path to file) into a zipfile subpath + # usable with the zipimport directory cache for our target archive + fspath = fspath.rstrip(os.sep) + if fspath == self.loader.archive: + return '' + if fspath.startswith(self.zip_pre): + return fspath[len(self.zip_pre):] + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.zip_pre) + ) + + def _parts(self, zip_path): + # Convert a zipfile subpath into an egg-relative path part list. + # pseudo-fs path + fspath = self.zip_pre + zip_path + if fspath.startswith(self.egg_root + os.sep): + return fspath[len(self.egg_root) + 1:].split(os.sep) + raise AssertionError( + "%s is not a subpath of %s" % (fspath, self.egg_root) + ) + + @property + def zipinfo(self): + return self._zip_manifests.load(self.loader.archive) + + def get_resource_filename(self, manager, resource_name): + if not self.egg_name: + raise NotImplementedError( + "resource_filename() only supported for .egg, not .zip" + ) + # no need to lock for extraction, since we use temp names + zip_path = self._resource_to_zip(resource_name) + eagers = self._get_eager_resources() + if '/'.join(self._parts(zip_path)) in eagers: + for name in eagers: + self._extract_resource(manager, self._eager_to_zip(name)) + return self._extract_resource(manager, zip_path) + + @staticmethod + def _get_date_and_size(zip_stat): + size = zip_stat.file_size + # ymdhms+wday, yday, dst + date_time = zip_stat.date_time + (0, 0, -1) + # 1980 offset already done + timestamp = time.mktime(date_time) + return timestamp, size + + def _extract_resource(self, manager, zip_path): + + if zip_path in self._index(): + for name in self._index()[zip_path]: + last = self._extract_resource( + manager, os.path.join(zip_path, name) + ) + # return the extracted directory name + return os.path.dirname(last) + + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + + if not WRITE_SUPPORT: + raise IOError('"os.rename" and "os.unlink" are not supported ' + 'on this platform') + try: + + real_path = manager.get_cache_path( + self.egg_name, self._parts(zip_path) + ) + + if self._is_current(real_path, zip_path): + return real_path + + outf, tmpnam = _mkstemp( + ".$extract", + dir=os.path.dirname(real_path), + ) + os.write(outf, self.loader.get_data(zip_path)) + os.close(outf) + utime(tmpnam, (timestamp, timestamp)) + manager.postprocess(tmpnam, real_path) + + try: + rename(tmpnam, real_path) + + except os.error: + if os.path.isfile(real_path): + if self._is_current(real_path, zip_path): + # the file became current since it was checked above, + # so proceed. + return real_path + # Windows, del old file and retry + elif os.name == 'nt': + unlink(real_path) + rename(tmpnam, real_path) + return real_path + raise + + except os.error: + # report a user-friendly error + manager.extraction_error() + + return real_path + + def _is_current(self, file_path, zip_path): + """ + Return True if the file_path is current for this zip_path + """ + timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) + if not os.path.isfile(file_path): + return False + stat = os.stat(file_path) + if stat.st_size != size or stat.st_mtime != timestamp: + return False + # check that the contents match + zip_contents = self.loader.get_data(zip_path) + with open(file_path, 'rb') as f: + file_contents = f.read() + return zip_contents == file_contents + + def _get_eager_resources(self): + if self.eagers is None: + eagers = [] + for name in ('native_libs.txt', 'eager_resources.txt'): + if self.has_metadata(name): + eagers.extend(self.get_metadata_lines(name)) + self.eagers = eagers + return self.eagers + + def _index(self): + try: + return self._dirindex + except AttributeError: + ind = {} + for path in self.zipinfo: + parts = path.split(os.sep) + while parts: + parent = os.sep.join(parts[:-1]) + if parent in ind: + ind[parent].append(parts[-1]) + break + else: + ind[parent] = [parts.pop()] + self._dirindex = ind + return ind + + def _has(self, fspath): + zip_path = self._zipinfo_name(fspath) + return zip_path in self.zipinfo or zip_path in self._index() + + def _isdir(self, fspath): + return self._zipinfo_name(fspath) in self._index() + + def _listdir(self, fspath): + return list(self._index().get(self._zipinfo_name(fspath), ())) + + def _eager_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.egg_root, resource_name)) + + def _resource_to_zip(self, resource_name): + return self._zipinfo_name(self._fn(self.module_path, resource_name)) + + +register_loader_type(zipimport.zipimporter, ZipProvider) + + +class FileMetadata(EmptyProvider): + """Metadata handler for standalone PKG-INFO files + + Usage:: + + metadata = FileMetadata("/path/to/PKG-INFO") + + This provider rejects all data and metadata requests except for PKG-INFO, + which is treated as existing, and will be the contents of the file at + the provided location. + """ + + def __init__(self, path): + self.path = path + + def has_metadata(self, name): + return name == 'PKG-INFO' and os.path.isfile(self.path) + + def get_metadata(self, name): + if name != 'PKG-INFO': + raise KeyError("No metadata except PKG-INFO is available") + + with io.open(self.path, encoding='utf-8', errors="replace") as f: + metadata = f.read() + self._warn_on_replacement(metadata) + return metadata + + def _warn_on_replacement(self, metadata): + # Python 2.7 compat for: replacement_char = '�' + replacement_char = b'\xef\xbf\xbd'.decode('utf-8') + if replacement_char in metadata: + tmpl = "{self.path} could not be properly decoded in UTF-8" + msg = tmpl.format(**locals()) + warnings.warn(msg) + + def get_metadata_lines(self, name): + return yield_lines(self.get_metadata(name)) + + +class PathMetadata(DefaultProvider): + """Metadata provider for egg directories + + Usage:: + + # Development eggs: + + egg_info = "/path/to/PackageName.egg-info" + base_dir = os.path.dirname(egg_info) + metadata = PathMetadata(base_dir, egg_info) + dist_name = os.path.splitext(os.path.basename(egg_info))[0] + dist = Distribution(basedir, project_name=dist_name, metadata=metadata) + + # Unpacked egg directories: + + egg_path = "/path/to/PackageName-ver-pyver-etc.egg" + metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) + dist = Distribution.from_filename(egg_path, metadata=metadata) + """ + + def __init__(self, path, egg_info): + self.module_path = path + self.egg_info = egg_info + + +class EggMetadata(ZipProvider): + """Metadata provider for .egg files""" + + def __init__(self, importer): + """Create a metadata provider from a zipimporter""" + + self.zip_pre = importer.archive + os.sep + self.loader = importer + if importer.prefix: + self.module_path = os.path.join(importer.archive, importer.prefix) + else: + self.module_path = importer.archive + self._setup_prefix() + + +_declare_state('dict', _distribution_finders={}) + + +def register_finder(importer_type, distribution_finder): + """Register `distribution_finder` to find distributions in sys.path items + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `distribution_finder` is a callable that, passed a path + item and the importer instance, yields ``Distribution`` instances found on + that path item. See ``pkg_resources.find_on_path`` for an example.""" + _distribution_finders[importer_type] = distribution_finder + + +def find_distributions(path_item, only=False): + """Yield distributions accessible via `path_item`""" + importer = get_importer(path_item) + finder = _find_adapter(_distribution_finders, importer) + return finder(importer, path_item, only) + + +def find_eggs_in_zip(importer, path_item, only=False): + """ + Find eggs in zip files; possibly multiple nested eggs. + """ + if importer.archive.endswith('.whl'): + # wheels are not supported with this finder + # they don't have PKG-INFO metadata, and won't ever contain eggs + return + metadata = EggMetadata(importer) + if metadata.has_metadata('PKG-INFO'): + yield Distribution.from_filename(path_item, metadata=metadata) + if only: + # don't yield nested distros + return + for subitem in metadata.resource_listdir('/'): + if _is_egg_path(subitem): + subpath = os.path.join(path_item, subitem) + dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) + for dist in dists: + yield dist + elif subitem.lower().endswith('.dist-info'): + subpath = os.path.join(path_item, subitem) + submeta = EggMetadata(zipimport.zipimporter(subpath)) + submeta.egg_info = subpath + yield Distribution.from_location(path_item, subitem, submeta) + + +register_finder(zipimport.zipimporter, find_eggs_in_zip) + + +def find_nothing(importer, path_item, only=False): + return () + + +register_finder(object, find_nothing) + + +def _by_version_descending(names): + """ + Given a list of filenames, return them in descending order + by version number. + + >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' + >>> _by_version_descending(names) + ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] + >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' + >>> _by_version_descending(names) + ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] + """ + def _by_version(name): + """ + Parse each component of the filename + """ + name, ext = os.path.splitext(name) + parts = itertools.chain(name.split('-'), [ext]) + return [packaging.version.parse(part) for part in parts] + + return sorted(names, key=_by_version, reverse=True) + + +def find_on_path(importer, path_item, only=False): + """Yield distributions accessible on a sys.path directory""" + path_item = _normalize_cached(path_item) + + if _is_unpacked_egg(path_item): + yield Distribution.from_filename( + path_item, metadata=PathMetadata( + path_item, os.path.join(path_item, 'EGG-INFO') + ) + ) + return + + entries = safe_listdir(path_item) + + # for performance, before sorting by version, + # screen entries for only those that will yield + # distributions + filtered = ( + entry + for entry in entries + if dist_factory(path_item, entry, only) + ) + + # scan for .egg and .egg-info in directory + path_item_entries = _by_version_descending(filtered) + for entry in path_item_entries: + fullpath = os.path.join(path_item, entry) + factory = dist_factory(path_item, entry, only) + for dist in factory(fullpath): + yield dist + + +def dist_factory(path_item, entry, only): + """ + Return a dist_factory for a path_item and entry + """ + lower = entry.lower() + is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) + return ( + distributions_from_metadata + if is_meta else + find_distributions + if not only and _is_egg_path(entry) else + resolve_egg_link + if not only and lower.endswith('.egg-link') else + NoDists() + ) + + +class NoDists: + """ + >>> bool(NoDists()) + False + + >>> list(NoDists()('anything')) + [] + """ + def __bool__(self): + return False + if six.PY2: + __nonzero__ = __bool__ + + def __call__(self, fullpath): + return iter(()) + + +def safe_listdir(path): + """ + Attempt to list contents of path, but suppress some exceptions. + """ + try: + return os.listdir(path) + except (PermissionError, NotADirectoryError): + pass + except OSError as e: + # Ignore the directory if does not exist, not a directory or + # permission denied + ignorable = ( + e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) + # Python 2 on Windows needs to be handled this way :( + or getattr(e, "winerror", None) == 267 + ) + if not ignorable: + raise + return () + + +def distributions_from_metadata(path): + root = os.path.dirname(path) + if os.path.isdir(path): + if len(os.listdir(path)) == 0: + # empty metadata dir; skip + return + metadata = PathMetadata(root, path) + else: + metadata = FileMetadata(path) + entry = os.path.basename(path) + yield Distribution.from_location( + root, entry, metadata, precedence=DEVELOP_DIST, + ) + + +def non_empty_lines(path): + """ + Yield non-empty lines from file at path + """ + with open(path) as f: + for line in f: + line = line.strip() + if line: + yield line + + +def resolve_egg_link(path): + """ + Given a path to an .egg-link, resolve distributions + present in the referenced path. + """ + referenced_paths = non_empty_lines(path) + resolved_paths = ( + os.path.join(os.path.dirname(path), ref) + for ref in referenced_paths + ) + dist_groups = map(find_distributions, resolved_paths) + return next(dist_groups, ()) + + +register_finder(pkgutil.ImpImporter, find_on_path) + +if hasattr(importlib_machinery, 'FileFinder'): + register_finder(importlib_machinery.FileFinder, find_on_path) + +_declare_state('dict', _namespace_handlers={}) +_declare_state('dict', _namespace_packages={}) + + +def register_namespace_handler(importer_type, namespace_handler): + """Register `namespace_handler` to declare namespace packages + + `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item + handler), and `namespace_handler` is a callable like this:: + + def namespace_handler(importer, path_entry, moduleName, module): + # return a path_entry to use for child packages + + Namespace handlers are only called if the importer object has already + agreed that it can handle the relevant path item, and they should only + return a subpath if the module __path__ does not already contain an + equivalent subpath. For an example namespace handler, see + ``pkg_resources.file_ns_handler``. + """ + _namespace_handlers[importer_type] = namespace_handler + + +def _handle_ns(packageName, path_item): + """Ensure that named package includes a subpath of path_item (if needed)""" + + importer = get_importer(path_item) + if importer is None: + return None + + # capture warnings due to #1111 + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + loader = importer.find_module(packageName) + + if loader is None: + return None + module = sys.modules.get(packageName) + if module is None: + module = sys.modules[packageName] = types.ModuleType(packageName) + module.__path__ = [] + _set_parent_ns(packageName) + elif not hasattr(module, '__path__'): + raise TypeError("Not a package:", packageName) + handler = _find_adapter(_namespace_handlers, importer) + subpath = handler(importer, path_item, packageName, module) + if subpath is not None: + path = module.__path__ + path.append(subpath) + loader.load_module(packageName) + _rebuild_mod_path(path, packageName, module) + return subpath + + +def _rebuild_mod_path(orig_path, package_name, module): + """ + Rebuild module.__path__ ensuring that all entries are ordered + corresponding to their sys.path order + """ + sys_path = [_normalize_cached(p) for p in sys.path] + + def safe_sys_path_index(entry): + """ + Workaround for #520 and #513. + """ + try: + return sys_path.index(entry) + except ValueError: + return float('inf') + + def position_in_sys_path(path): + """ + Return the ordinal of the path based on its position in sys.path + """ + path_parts = path.split(os.sep) + module_parts = package_name.count('.') + 1 + parts = path_parts[:-module_parts] + return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) + + new_path = sorted(orig_path, key=position_in_sys_path) + new_path = [_normalize_cached(p) for p in new_path] + + if isinstance(module.__path__, list): + module.__path__[:] = new_path + else: + module.__path__ = new_path + + +def declare_namespace(packageName): + """Declare that package 'packageName' is a namespace package""" + + _imp.acquire_lock() + try: + if packageName in _namespace_packages: + return + + path = sys.path + parent, _, _ = packageName.rpartition('.') + + if parent: + declare_namespace(parent) + if parent not in _namespace_packages: + __import__(parent) + try: + path = sys.modules[parent].__path__ + except AttributeError: + raise TypeError("Not a package:", parent) + + # Track what packages are namespaces, so when new path items are added, + # they can be updated + _namespace_packages.setdefault(parent or None, []).append(packageName) + _namespace_packages.setdefault(packageName, []) + + for path_item in path: + # Ensure all the parent's path items are reflected in the child, + # if they apply + _handle_ns(packageName, path_item) + + finally: + _imp.release_lock() + + +def fixup_namespace_packages(path_item, parent=None): + """Ensure that previously-declared namespace packages include path_item""" + _imp.acquire_lock() + try: + for package in _namespace_packages.get(parent, ()): + subpath = _handle_ns(package, path_item) + if subpath: + fixup_namespace_packages(subpath, package) + finally: + _imp.release_lock() + + +def file_ns_handler(importer, path_item, packageName, module): + """Compute an ns-package subpath for a filesystem or zipfile importer""" + + subpath = os.path.join(path_item, packageName.split('.')[-1]) + normalized = _normalize_cached(subpath) + for item in module.__path__: + if _normalize_cached(item) == normalized: + break + else: + # Only return the path if it's not already there + return subpath + + +register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) +register_namespace_handler(zipimport.zipimporter, file_ns_handler) + +if hasattr(importlib_machinery, 'FileFinder'): + register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) + + +def null_ns_handler(importer, path_item, packageName, module): + return None + + +register_namespace_handler(object, null_ns_handler) + + +def normalize_path(filename): + """Normalize a file/dir name for comparison purposes""" + return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename)))) + + +def _cygwin_patch(filename): # pragma: nocover + """ + Contrary to POSIX 2008, on Cygwin, getcwd (3) contains + symlink components. Using + os.path.abspath() works around this limitation. A fix in os.getcwd() + would probably better, in Cygwin even more so, except + that this seems to be by design... + """ + return os.path.abspath(filename) if sys.platform == 'cygwin' else filename + + +def _normalize_cached(filename, _cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result + + +def _is_egg_path(path): + """ + Determine if given path appears to be an egg. + """ + return path.lower().endswith('.egg') + + +def _is_unpacked_egg(path): + """ + Determine if given path appears to be an unpacked egg. + """ + return ( + _is_egg_path(path) and + os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) + ) + + +def _set_parent_ns(packageName): + parts = packageName.split('.') + name = parts.pop() + if parts: + parent = '.'.join(parts) + setattr(sys.modules[parent], name, sys.modules[packageName]) + + +def yield_lines(strs): + """Yield non-empty/non-comment lines of a string or sequence""" + if isinstance(strs, six.string_types): + for s in strs.splitlines(): + s = s.strip() + # skip blank lines/comments + if s and not s.startswith('#'): + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + + +MODULE = re.compile(r"\w+(\.\w+)*$").match +EGG_NAME = re.compile( + r""" + (?P<name>[^-]+) ( + -(?P<ver>[^-]+) ( + -py(?P<pyver>[^-]+) ( + -(?P<plat>.+) + )? + )? + )? + """, + re.VERBOSE | re.IGNORECASE, +).match + + +class EntryPoint: + """Object representing an advertised importable object""" + + def __init__(self, name, module_name, attrs=(), extras=(), dist=None): + if not MODULE(module_name): + raise ValueError("Invalid module name", module_name) + self.name = name + self.module_name = module_name + self.attrs = tuple(attrs) + self.extras = tuple(extras) + self.dist = dist + + def __str__(self): + s = "%s = %s" % (self.name, self.module_name) + if self.attrs: + s += ':' + '.'.join(self.attrs) + if self.extras: + s += ' [%s]' % ','.join(self.extras) + return s + + def __repr__(self): + return "EntryPoint.parse(%r)" % str(self) + + def load(self, require=True, *args, **kwargs): + """ + Require packages for this EntryPoint, then resolve it. + """ + if not require or args or kwargs: + warnings.warn( + "Parameters to load are deprecated. Call .resolve and " + ".require separately.", + PkgResourcesDeprecationWarning, + stacklevel=2, + ) + if require: + self.require(*args, **kwargs) + return self.resolve() + + def resolve(self): + """ + Resolve the entry point from its module and attrs. + """ + module = __import__(self.module_name, fromlist=['__name__'], level=0) + try: + return functools.reduce(getattr, self.attrs, module) + except AttributeError as exc: + raise ImportError(str(exc)) + + def require(self, env=None, installer=None): + if self.extras and not self.dist: + raise UnknownExtra("Can't require() without a distribution", self) + + # Get the requirements for this entry point with all its extras and + # then resolve them. We have to pass `extras` along when resolving so + # that the working set knows what extras we want. Otherwise, for + # dist-info distributions, the working set will assume that the + # requirements for that extra are purely optional and skip over them. + reqs = self.dist.requires(self.extras) + items = working_set.resolve(reqs, env, installer, extras=self.extras) + list(map(working_set.add, items)) + + pattern = re.compile( + r'\s*' + r'(?P<name>.+?)\s*' + r'=\s*' + r'(?P<module>[\w.]+)\s*' + r'(:\s*(?P<attr>[\w.]+))?\s*' + r'(?P<extras>\[.*\])?\s*$' + ) + + @classmethod + def parse(cls, src, dist=None): + """Parse a single entry point from string `src` + + Entry point syntax follows the form:: + + name = some.module:some.attr [extra1, extra2] + + The entry name and module name are required, but the ``:attrs`` and + ``[extras]`` parts are optional + """ + m = cls.pattern.match(src) + if not m: + msg = "EntryPoint must be in 'name=module:attrs [extras]' format" + raise ValueError(msg, src) + res = m.groupdict() + extras = cls._parse_extras(res['extras']) + attrs = res['attr'].split('.') if res['attr'] else () + return cls(res['name'], res['module'], attrs, extras, dist) + + @classmethod + def _parse_extras(cls, extras_spec): + if not extras_spec: + return () + req = Requirement.parse('x' + extras_spec) + if req.specs: + raise ValueError() + return req.extras + + @classmethod + def parse_group(cls, group, lines, dist=None): + """Parse an entry point group""" + if not MODULE(group): + raise ValueError("Invalid group name", group) + this = {} + for line in yield_lines(lines): + ep = cls.parse(line, dist) + if ep.name in this: + raise ValueError("Duplicate entry point", group, ep.name) + this[ep.name] = ep + return this + + @classmethod + def parse_map(cls, data, dist=None): + """Parse a map of entry point groups""" + if isinstance(data, dict): + data = data.items() + else: + data = split_sections(data) + maps = {} + for group, lines in data: + if group is None: + if not lines: + continue + raise ValueError("Entry points must be listed in groups") + group = group.strip() + if group in maps: + raise ValueError("Duplicate group name", group) + maps[group] = cls.parse_group(group, lines, dist) + return maps + + +def _remove_md5_fragment(location): + if not location: + return '' + parsed = urllib.parse.urlparse(location) + if parsed[-1].startswith('md5='): + return urllib.parse.urlunparse(parsed[:-1] + ('',)) + return location + + +def _version_from_file(lines): + """ + Given an iterable of lines from a Metadata file, return + the value of the Version field, if present, or None otherwise. + """ + def is_version_line(line): + return line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) + line = next(iter(version_lines), '') + _, _, value = line.partition(':') + return safe_version(value.strip()) or None + + +class Distribution: + """Wrap an actual or potential sys.path entry w/metadata""" + PKG_INFO = 'PKG-INFO' + + def __init__( + self, location=None, metadata=None, project_name=None, + version=None, py_version=PY_MAJOR, platform=None, + precedence=EGG_DIST): + self.project_name = safe_name(project_name or 'Unknown') + if version is not None: + self._version = safe_version(version) + self.py_version = py_version + self.platform = platform + self.location = location + self.precedence = precedence + self._provider = metadata or empty_provider + + @classmethod + def from_location(cls, location, basename, metadata=None, **kw): + project_name, version, py_version, platform = [None] * 4 + basename, ext = os.path.splitext(basename) + if ext.lower() in _distributionImpl: + cls = _distributionImpl[ext.lower()] + + match = EGG_NAME(basename) + if match: + project_name, version, py_version, platform = match.group( + 'name', 'ver', 'pyver', 'plat' + ) + return cls( + location, metadata, project_name=project_name, version=version, + py_version=py_version, platform=platform, **kw + )._reload_version() + + def _reload_version(self): + return self + + @property + def hashcmp(self): + return ( + self.parsed_version, + self.precedence, + self.key, + _remove_md5_fragment(self.location), + self.py_version or '', + self.platform or '', + ) + + def __hash__(self): + return hash(self.hashcmp) + + def __lt__(self, other): + return self.hashcmp < other.hashcmp + + def __le__(self, other): + return self.hashcmp <= other.hashcmp + + def __gt__(self, other): + return self.hashcmp > other.hashcmp + + def __ge__(self, other): + return self.hashcmp >= other.hashcmp + + def __eq__(self, other): + if not isinstance(other, self.__class__): + # It's not a Distribution, so they are not equal + return False + return self.hashcmp == other.hashcmp + + def __ne__(self, other): + return not self == other + + # These properties have to be lazy so that we don't have to load any + # metadata until/unless it's actually needed. (i.e., some distributions + # may not know their name or version without loading PKG-INFO) + + @property + def key(self): + try: + return self._key + except AttributeError: + self._key = key = self.project_name.lower() + return key + + @property + def parsed_version(self): + if not hasattr(self, "_parsed_version"): + self._parsed_version = parse_version(self.version) + + return self._parsed_version + + def _warn_legacy_version(self): + LV = packaging.version.LegacyVersion + is_legacy = isinstance(self._parsed_version, LV) + if not is_legacy: + return + + # While an empty version is technically a legacy version and + # is not a valid PEP 440 version, it's also unlikely to + # actually come from someone and instead it is more likely that + # it comes from setuptools attempting to parse a filename and + # including it in the list. So for that we'll gate this warning + # on if the version is anything at all or not. + if not self.version: + return + + tmpl = textwrap.dedent(""" + '{project_name} ({version})' is being parsed as a legacy, + non PEP 440, + version. You may find odd behavior and sort order. + In particular it will be sorted as less than 0.0. It + is recommended to migrate to PEP 440 compatible + versions. + """).strip().replace('\n', ' ') + + warnings.warn(tmpl.format(**vars(self)), PEP440Warning) + + @property + def version(self): + try: + return self._version + except AttributeError: + version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if version is None: + tmpl = "Missing 'Version:' header and/or %s file" + raise ValueError(tmpl % self.PKG_INFO, self) + return version + + @property + def _dep_map(self): + """ + A map of extra to its list of (direct) requirements + for this distribution, including the null extra. + """ + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._filter_extras(self._build_dep_map()) + return self.__dep_map + + @staticmethod + def _filter_extras(dm): + """ + Given a mapping of extras to dependencies, strip off + environment markers and filter out any dependencies + not matching the markers. + """ + for extra in list(filter(None, dm)): + new_extra = extra + reqs = dm.pop(extra) + new_extra, _, marker = extra.partition(':') + fails_marker = marker and ( + invalid_marker(marker) + or not evaluate_marker(marker) + ) + if fails_marker: + reqs = [] + new_extra = safe_extra(new_extra) or None + + dm.setdefault(new_extra, []).extend(reqs) + return dm + + def _build_dep_map(self): + dm = {} + for name in 'requires.txt', 'depends.txt': + for extra, reqs in split_sections(self._get_metadata(name)): + dm.setdefault(extra, []).extend(parse_requirements(reqs)) + return dm + + def requires(self, extras=()): + """List of Requirements needed for this distro if `extras` are used""" + dm = self._dep_map + deps = [] + deps.extend(dm.get(None, ())) + for ext in extras: + try: + deps.extend(dm[safe_extra(ext)]) + except KeyError: + raise UnknownExtra( + "%s has no such extra feature %r" % (self, ext) + ) + return deps + + def _get_metadata(self, name): + if self.has_metadata(name): + for line in self.get_metadata_lines(name): + yield line + + def activate(self, path=None, replace=False): + """Ensure distribution is importable on `path` (default=sys.path)""" + if path is None: + path = sys.path + self.insert_on(path, replace=replace) + if path is sys.path: + fixup_namespace_packages(self.location) + for pkg in self._get_metadata('namespace_packages.txt'): + if pkg in sys.modules: + declare_namespace(pkg) + + def egg_name(self): + """Return what this distribution's standard .egg filename should be""" + filename = "%s-%s-py%s" % ( + to_filename(self.project_name), to_filename(self.version), + self.py_version or PY_MAJOR + ) + + if self.platform: + filename += '-' + self.platform + return filename + + def __repr__(self): + if self.location: + return "%s (%s)" % (self, self.location) + else: + return str(self) + + def __str__(self): + try: + version = getattr(self, 'version', None) + except ValueError: + version = None + version = version or "[unknown version]" + return "%s %s" % (self.project_name, version) + + def __getattr__(self, attr): + """Delegate all unrecognized public attributes to .metadata provider""" + if attr.startswith('_'): + raise AttributeError(attr) + return getattr(self._provider, attr) + + def __dir__(self): + return list( + set(super(Distribution, self).__dir__()) + | set( + attr for attr in self._provider.__dir__() + if not attr.startswith('_') + ) + ) + + if not hasattr(object, '__dir__'): + # python 2.7 not supported + del __dir__ + + @classmethod + def from_filename(cls, filename, metadata=None, **kw): + return cls.from_location( + _normalize_cached(filename), os.path.basename(filename), metadata, + **kw + ) + + def as_requirement(self): + """Return a ``Requirement`` that matches this distribution exactly""" + if isinstance(self.parsed_version, packaging.version.Version): + spec = "%s==%s" % (self.project_name, self.parsed_version) + else: + spec = "%s===%s" % (self.project_name, self.parsed_version) + + return Requirement.parse(spec) + + def load_entry_point(self, group, name): + """Return the `name` entry point of `group` or raise ImportError""" + ep = self.get_entry_info(group, name) + if ep is None: + raise ImportError("Entry point %r not found" % ((group, name),)) + return ep.load() + + def get_entry_map(self, group=None): + """Return the entry point map for `group`, or the full entry map""" + try: + ep_map = self._ep_map + except AttributeError: + ep_map = self._ep_map = EntryPoint.parse_map( + self._get_metadata('entry_points.txt'), self + ) + if group is not None: + return ep_map.get(group, {}) + return ep_map + + def get_entry_info(self, group, name): + """Return the EntryPoint object for `group`+`name`, or ``None``""" + return self.get_entry_map(group).get(name) + + def insert_on(self, path, loc=None, replace=False): + """Ensure self.location is on path + + If replace=False (default): + - If location is already in path anywhere, do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent. + - Else: add to the end of path. + If replace=True: + - If location is already on path anywhere (not eggs) + or higher priority than its parent (eggs) + do nothing. + - Else: + - If it's an egg and its parent directory is on path, + insert just ahead of the parent, + removing any lower-priority entries. + - Else: add it to the front of path. + """ + + loc = loc or self.location + if not loc: + return + + nloc = _normalize_cached(loc) + bdir = os.path.dirname(nloc) + npath = [(p and _normalize_cached(p) or p) for p in path] + + for p, item in enumerate(npath): + if item == nloc: + if replace: + break + else: + # don't modify path (even removing duplicates) if + # found and not replace + return + elif item == bdir and self.precedence == EGG_DIST: + # if it's an .egg, give it precedence over its directory + # UNLESS it's already been added to sys.path and replace=False + if (not replace) and nloc in npath[p:]: + return + if path is sys.path: + self.check_version_conflict() + path.insert(p, loc) + npath.insert(p, nloc) + break + else: + if path is sys.path: + self.check_version_conflict() + if replace: + path.insert(0, loc) + else: + path.append(loc) + return + + # p is the spot where we found or inserted loc; now remove duplicates + while True: + try: + np = npath.index(nloc, p + 1) + except ValueError: + break + else: + del npath[np], path[np] + # ha! + p = np + + return + + def check_version_conflict(self): + if self.key == 'setuptools': + # ignore the inevitable setuptools self-conflicts :( + return + + nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) + loc = normalize_path(self.location) + for modname in self._get_metadata('top_level.txt'): + if (modname not in sys.modules or modname in nsp + or modname in _namespace_packages): + continue + if modname in ('pkg_resources', 'setuptools', 'site'): + continue + fn = getattr(sys.modules[modname], '__file__', None) + if fn and (normalize_path(fn).startswith(loc) or + fn.startswith(self.location)): + continue + issue_warning( + "Module %s was already imported from %s, but %s is being added" + " to sys.path" % (modname, fn, self.location), + ) + + def has_version(self): + try: + self.version + except ValueError: + issue_warning("Unbuilt egg for " + repr(self)) + return False + return True + + def clone(self, **kw): + """Copy this distribution, substituting in any changed keyword args""" + names = 'project_name version py_version platform location precedence' + for attr in names.split(): + kw.setdefault(attr, getattr(self, attr, None)) + kw.setdefault('metadata', self._provider) + return self.__class__(**kw) + + @property + def extras(self): + return [dep for dep in self._dep_map if dep] + + +class EggInfoDistribution(Distribution): + def _reload_version(self): + """ + Packages installed by distutils (e.g. numpy or scipy), + which uses an old safe_version, and so + their version numbers can get mangled when + converted to filenames (e.g., 1.11.0.dev0+2329eae to + 1.11.0.dev0_2329eae). These distributions will not be + parsed properly + downstream by Distribution and safe_version, so + take an extra step and try to get the version number from + the metadata file itself instead of the filename. + """ + md_version = _version_from_file(self._get_metadata(self.PKG_INFO)) + if md_version: + self._version = md_version + return self + + +class DistInfoDistribution(Distribution): + """ + Wrap an actual or potential sys.path entry + w/metadata, .dist-info style. + """ + PKG_INFO = 'METADATA' + EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") + + @property + def _parsed_pkg_info(self): + """Parse and cache metadata""" + try: + return self._pkg_info + except AttributeError: + metadata = self.get_metadata(self.PKG_INFO) + self._pkg_info = email.parser.Parser().parsestr(metadata) + return self._pkg_info + + @property + def _dep_map(self): + try: + return self.__dep_map + except AttributeError: + self.__dep_map = self._compute_dependencies() + return self.__dep_map + + def _compute_dependencies(self): + """Recompute this distribution's dependencies.""" + dm = self.__dep_map = {None: []} + + reqs = [] + # Including any condition expressions + for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: + reqs.extend(parse_requirements(req)) + + def reqs_for_extra(extra): + for req in reqs: + if not req.marker or req.marker.evaluate({'extra': extra}): + yield req + + common = frozenset(reqs_for_extra(None)) + dm[None].extend(common) + + for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: + s_extra = safe_extra(extra.strip()) + dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) + + return dm + + +_distributionImpl = { + '.egg': Distribution, + '.egg-info': EggInfoDistribution, + '.dist-info': DistInfoDistribution, +} + + +def issue_warning(*args, **kw): + level = 1 + g = globals() + try: + # find the first stack frame that is *not* code in + # the pkg_resources module, to use for the warning + while sys._getframe(level).f_globals is g: + level += 1 + except ValueError: + pass + warnings.warn(stacklevel=level + 1, *args, **kw) + + +class RequirementParseError(ValueError): + def __str__(self): + return ' '.join(self.args) + + +def parse_requirements(strs): + """Yield ``Requirement`` objects for each specification in `strs` + + `strs` must be a string, or a (possibly-nested) iterable thereof. + """ + # create a steppable iterator, so we can handle \-continuations + lines = iter(yield_lines(strs)) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if ' #' in line: + line = line[:line.find(' #')] + # If there is a line continuation, drop it, and append the next line. + if line.endswith('\\'): + line = line[:-2].strip() + try: + line += next(lines) + except StopIteration: + return + yield Requirement(line) + + +class Requirement(packaging.requirements.Requirement): + def __init__(self, requirement_string): + """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" + try: + super(Requirement, self).__init__(requirement_string) + except packaging.requirements.InvalidRequirement as e: + raise RequirementParseError(str(e)) + self.unsafe_name = self.name + project_name = safe_name(self.name) + self.project_name, self.key = project_name, project_name.lower() + self.specs = [ + (spec.operator, spec.version) for spec in self.specifier] + self.extras = tuple(map(safe_extra, self.extras)) + self.hashCmp = ( + self.key, + self.specifier, + frozenset(self.extras), + str(self.marker) if self.marker else None, + ) + self.__hash = hash(self.hashCmp) + + def __eq__(self, other): + return ( + isinstance(other, Requirement) and + self.hashCmp == other.hashCmp + ) + + def __ne__(self, other): + return not self == other + + def __contains__(self, item): + if isinstance(item, Distribution): + if item.key != self.key: + return False + + item = item.version + + # Allow prereleases always in order to match the previous behavior of + # this method. In the future this should be smarter and follow PEP 440 + # more accurately. + return self.specifier.contains(item, prereleases=True) + + def __hash__(self): + return self.__hash + + def __repr__(self): + return "Requirement.parse(%r)" % str(self) + + @staticmethod + def parse(s): + req, = parse_requirements(s) + return req + + +def _always_object(classes): + """ + Ensure object appears in the mro even + for old-style classes. + """ + if object not in classes: + return classes + (object,) + return classes + + +def _find_adapter(registry, ob): + """Return an adapter factory for `ob` from `registry`""" + types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob)))) + for t in types: + if t in registry: + return registry[t] + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + py31compat.makedirs(dirname, exist_ok=True) + + +def _bypass_ensure_directory(path): + """Sandbox-bypassing version of ensure_directory()""" + if not WRITE_SUPPORT: + raise IOError('"os.mkdir" not supported on this platform.') + dirname, filename = split(path) + if dirname and filename and not isdir(dirname): + _bypass_ensure_directory(dirname) + try: + mkdir(dirname, 0o755) + except FileExistsError: + pass + + +def split_sections(s): + """Split a string or iterable thereof into (section, content) pairs + + Each ``section`` is a stripped version of the section header ("[section]") + and each ``content`` is a list of stripped lines excluding blank lines and + comment-only lines. If there are any such lines before the first section + header, they're returned in a first ``section`` of ``None``. + """ + section = None + content = [] + for line in yield_lines(s): + if line.startswith("["): + if line.endswith("]"): + if section or content: + yield section, content + section = line[1:-1].strip() + content = [] + else: + raise ValueError("Invalid section heading", line) + else: + content.append(line) + + # wrap up last segment + yield section, content + + +def _mkstemp(*args, **kw): + old_open = os.open + try: + # temporarily bypass sandboxing + os.open = os_open + return tempfile.mkstemp(*args, **kw) + finally: + # and then put it back + os.open = old_open + + +# Silence the PEP440Warning by default, so that end users don't get hit by it +# randomly just because they use pkg_resources. We want to append the rule +# because we want earlier uses of filterwarnings to take precedence over this +# one. +warnings.filterwarnings("ignore", category=PEP440Warning, append=True) + + +# from jaraco.functools 1.3 +def _call_aside(f, *args, **kwargs): + f(*args, **kwargs) + return f + + +@_call_aside +def _initialize(g=globals()): + "Set up global resource manager (deliberately not state-saved)" + manager = ResourceManager() + g['_manager'] = manager + g.update( + (name, getattr(manager, name)) + for name in dir(manager) + if not name.startswith('_') + ) + + +@_call_aside +def _initialize_master_working_set(): + """ + Prepare the master working set and make the ``require()`` + API available. + + This function has explicit effects on the global state + of pkg_resources. It is intended to be invoked once at + the initialization of this module. + + Invocation by other packages is unsupported and done + at their own risk. + """ + working_set = WorkingSet._build_master() + _declare_state('object', working_set=working_set) + + require = working_set.require + iter_entry_points = working_set.iter_entry_points + add_activation_listener = working_set.subscribe + run_script = working_set.run_script + # backward compatibility + run_main = run_script + # Activate all distributions already on sys.path with replace=False and + # ensure that all distributions added to the working set in the future + # (e.g. by calling ``require()``) will get activated as well, + # with higher priority (replace=True). + tuple( + dist.activate(replace=False) + for dist in working_set + ) + add_activation_listener( + lambda dist: dist.activate(replace=True), + existing=False, + ) + working_set.entries = [] + # match order + list(map(working_set.add_entry, sys.path)) + globals().update(locals()) + +class PkgResourcesDeprecationWarning(Warning): + """ + Base class for warning about deprecations in ``pkg_resources`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/__init__.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/appdirs.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/appdirs.py new file mode 100644 index 0000000..ae67001 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/appdirs.py @@ -0,0 +1,608 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2005-2010 ActiveState Software Inc. +# Copyright (c) 2013 Eddy Petrișor + +"""Utilities for determining application-specific dirs. + +See <http://github.com/ActiveState/appdirs> for details and usage. +""" +# Dev Notes: +# - MSDN on where to store app data files: +# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 +# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +__version_info__ = (1, 4, 3) +__version__ = '.'.join(map(str, __version_info__)) + + +import sys +import os + +PY3 = sys.version_info[0] == 3 + +if PY3: + unicode = str + +if sys.platform.startswith('java'): + import platform + os_name = platform.java_ver()[3][0] + if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. + system = 'win32' + elif os_name.startswith('Mac'): # "Mac OS X", etc. + system = 'darwin' + else: # "Linux", "SunOS", "FreeBSD", etc. + # Setting this to "linux2" is not ideal, but only Windows or Mac + # are actually checked for and the rest of the module expects + # *sys.platform* style strings. + system = 'linux2' +else: + system = sys.platform + + + +def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user data directories are: + Mac OS X: ~/Library/Application Support/<AppName> + Unix: ~/.local/share/<AppName> # or in $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\<username>\Application Data\<AppAuthor>\<AppName> + Win XP (roaming): C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName> + Win 7 (not roaming): C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName> + Win 7 (roaming): C:\Users\<username>\AppData\Roaming\<AppAuthor>\<AppName> + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/<AppName>". + """ + if system == "win32": + if appauthor is None: + appauthor = appname + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.normpath(_get_win_folder(const)) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('~/Library/Application Support/') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of data dirs should be + returned. By default, the first item from XDG_DATA_DIRS is + returned, or '/usr/local/share/<AppName>', + if XDG_DATA_DIRS is not set + + Typical site data directories are: + Mac OS X: /Library/Application Support/<AppName> + Unix: /usr/local/share/<AppName> or /usr/share/<AppName> + Win XP: C:\Documents and Settings\All Users\Application Data\<AppAuthor>\<AppName> + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + Win 7: C:\ProgramData\<AppAuthor>\<AppName> # Hidden, but writeable on Win 7. + + For Unix, this is using the $XDG_DATA_DIRS[0] default. + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('/Library/Application Support') + if appname: + path = os.path.join(path, appname) + else: + # XDG default for $XDG_DATA_DIRS + # only first, if multipath is False + path = os.getenv('XDG_DATA_DIRS', + os.pathsep.join(['/usr/local/share', '/usr/share'])) + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + if appname and version: + path = os.path.join(path, version) + return path + + +def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user config directories are: + Mac OS X: same as user_data_dir + Unix: ~/.config/<AppName> # or in $XDG_CONFIG_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of config dirs should be + returned. By default, the first item from XDG_CONFIG_DIRS is + returned, or '/etc/xdg/<AppName>', if XDG_CONFIG_DIRS is not set + + Typical site config directories are: + Mac OS X: same as site_data_dir + Unix: /etc/xdg/<AppName> or $XDG_CONFIG_DIRS[i]/<AppName> for each value in + $XDG_CONFIG_DIRS + Win *: same as site_data_dir + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + + For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system in ["win32", "darwin"]: + path = site_data_dir(appname, appauthor) + if appname and version: + path = os.path.join(path, version) + else: + # XDG default for $XDG_CONFIG_DIRS + # only first, if multipath is False + path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + +def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Cache" to the base app data dir for Windows. See + discussion below. + + Typical user cache directories are: + Mac OS X: ~/Library/Caches/<AppName> + Unix: ~/.cache/<AppName> (XDG default) + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Cache + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go in + the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming + app data dir (the default returned by `user_data_dir` above). Apps typically + put cache data somewhere *under* the given dir here. Some examples: + ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache + ...\Acme\SuperApp\Cache\1.0 + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + This can be disabled with the `opinion=False` option. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + if opinion: + path = os.path.join(path, "Cache") + elif system == 'darwin': + path = os.path.expanduser('~/Library/Caches') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific state dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx> + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/<AppName> # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal <https://wiki.debian.org/XDGBaseDirectorySpecification#state> + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/<AppName>". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific log dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be "<major>.<minor>". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Logs" to the base app data dir for Windows, and "log" to the + base cache dir for Unix. See discussion below. + + Typical user log directories are: + Mac OS X: ~/Library/Logs/<AppName> + Unix: ~/.cache/<AppName>/log # or under $XDG_CACHE_HOME if defined + Win XP: C:\Documents and Settings\<username>\Local Settings\Application Data\<AppAuthor>\<AppName>\Logs + Vista: C:\Users\<username>\AppData\Local\<AppAuthor>\<AppName>\Logs + + On Windows the only suggestion in the MSDN docs is that local settings + go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in + examples of what some windows apps use for a logs dir.) + + OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` + value for Windows and appends "log" to the user cache dir for Unix. + This can be disabled with the `opinion=False` option. + """ + if system == "darwin": + path = os.path.join( + os.path.expanduser('~/Library/Logs'), + appname) + elif system == "win32": + path = user_data_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "Logs") + else: + path = user_cache_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "log") + if appname and version: + path = os.path.join(path, version) + return path + + +class AppDirs(object): + """Convenience wrapper for getting application dirs.""" + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): + self.appname = appname + self.appauthor = appauthor + self.version = version + self.roaming = roaming + self.multipath = multipath + + @property + def user_data_dir(self): + return user_data_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_data_dir(self): + return site_data_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_config_dir(self): + return user_config_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_config_dir(self): + return site_config_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_cache_dir(self): + return user_cache_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_state_dir(self): + return user_state_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_log_dir(self): + return user_log_dir(self.appname, self.appauthor, + version=self.version) + + +#---- internal support stuff + +def _get_win_folder_from_registry(csidl_name): + """This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + if PY3: + import winreg as _winreg + else: + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + dir, type = _winreg.QueryValueEx(key, shell_folder_name) + return dir + + +def _get_win_folder_with_pywin32(csidl_name): + from win32com.shell import shellcon, shell + dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) + # Try to make this a unicode path because SHGetFolderPath does + # not return unicode strings when there is unicode data in the + # path. + try: + dir = unicode(dir) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + try: + import win32api + dir = win32api.GetShortPathName(dir) + except ImportError: + pass + except UnicodeError: + pass + return dir + + +def _get_win_folder_with_ctypes(csidl_name): + import ctypes + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + +def _get_win_folder_with_jna(csidl_name): + import array + from com.sun import jna + from com.sun.jna.platform import win32 + + buf_size = win32.WinDef.MAX_PATH * 2 + buf = array.zeros('c', buf_size) + shell = win32.Shell32.INSTANCE + shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + # Downgrade to short path name if have highbit chars. See + # <http://bugs.activestate.com/show_bug.cgi?id=85099>. + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf = array.zeros('c', buf_size) + kernel = win32.Kernel32.INSTANCE + if kernel.GetShortPathName(dir, buf, buf_size): + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + return dir + +if system == "win32": + try: + import win32com.shell + _get_win_folder = _get_win_folder_with_pywin32 + except ImportError: + try: + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + try: + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +#---- self test code + +if __name__ == "__main__": + appname = "MyApp" + appauthor = "MyCompany" + + props = ("user_data_dir", + "user_config_dir", + "user_cache_dir", + "user_state_dir", + "user_log_dir", + "site_data_dir", + "site_config_dir") + + print("-- app dirs %s --" % __version__) + + print("-- app dirs (with optional 'version')") + dirs = AppDirs(appname, appauthor, version="1.0") + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'version')") + dirs = AppDirs(appname, appauthor) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'appauthor')") + dirs = AppDirs(appname) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (with disabled 'appauthor')") + dirs = AppDirs(appname, appauthor=False) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py new file mode 100644 index 0000000..95d330e --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "16.8" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_compat.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py new file mode 100644 index 0000000..ccc2786 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + +NegativeInfinity = NegativeInfinity() diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py new file mode 100644 index 0000000..892e578 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from pkg_resources.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from pkg_resources.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from pkg_resources.extern.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "<Marker({0!r})>".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py new file mode 100644 index 0000000..0c8c4a3 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py @@ -0,0 +1,127 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from pkg_resources.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from pkg_resources.extern.pyparsing import Literal as L # noqa +from pkg_resources.extern.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPERATOR = SEMICOLON +MARKER = MARKER_SEPERATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + "Invalid requirement, parse error at \"{0!r}\"".format( + requirement_string[e.loc:e.loc + 8])) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL given") + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "<Requirement({0!r})>".format(str(self)) diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..7f5a76c --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the begining. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(==|!=|<=|>=|<|>)) + \s* + (?P<version> + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(~=|==|!=|<=|>=|<|>|===)) + (?P<version> + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?<!==|!=|~=) # We have special cases for these + # operators so we want to make sure they + # don't match here. + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is techincally greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<SpecifierSet({0!r}{1})>".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py new file mode 100644 index 0000000..942387c --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py new file mode 100644 index 0000000..83b5ee8 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py @@ -0,0 +1,393 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "<LegacyVersion({0})>".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P<epoch>[0-9]+)!)? # epoch + (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment + (?P<pre> # pre-release + [-_\.]? + (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) + [-_\.]? + (?P<pre_n>[0-9]+)? + )? + (?P<post> # post release + (?:-(?P<post_n1>[0-9]+)) + | + (?: + [-_\.]? + (?P<post_l>post|rev|r) + [-_\.]? + (?P<post_n2>[0-9]+)? + ) + )? + (?P<dev> # dev release + [-_\.]? + (?P<dev_l>dev) + [-_\.]? + (?P<dev_n>[0-9]+)? + )? + ) + (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version +""" + + +class Version(_BaseVersion): + + _regex = re.compile( + r"^\s*" + VERSION_PATTERN + r"\s*$", + re.VERBOSE | re.IGNORECASE, + ) + + def __init__(self, version): + # Validate the version and parse it into pieces + match = self._regex.search(version) + if not match: + raise InvalidVersion("Invalid version: '{0}'".format(version)) + + # Store the parsed out pieces of the version + self._version = _Version( + epoch=int(match.group("epoch")) if match.group("epoch") else 0, + release=tuple(int(i) for i in match.group("release").split(".")), + pre=_parse_letter_version( + match.group("pre_l"), + match.group("pre_n"), + ), + post=_parse_letter_version( + match.group("post_l"), + match.group("post_n1") or match.group("post_n2"), + ), + dev=_parse_letter_version( + match.group("dev_l"), + match.group("dev_n"), + ), + local=_parse_local_version(match.group("local")), + ) + + # Generate a key which will be used for sorting + self._key = _cmpkey( + self._version.epoch, + self._version.release, + self._version.pre, + self._version.post, + self._version.dev, + self._version.local, + ) + + def __repr__(self): + return "<Version({0})>".format(repr(str(self))) + + def __str__(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + # Pre-release + if self._version.pre is not None: + parts.append("".join(str(x) for x in self._version.pre)) + + # Post-release + if self._version.post is not None: + parts.append(".post{0}".format(self._version.post[1])) + + # Development release + if self._version.dev is not None: + parts.append(".dev{0}".format(self._version.dev[1])) + + # Local version segment + if self._version.local is not None: + parts.append( + "+{0}".format(".".join(str(x) for x in self._version.local)) + ) + + return "".join(parts) + + @property + def public(self): + return str(self).split("+", 1)[0] + + @property + def base_version(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + return "".join(parts) + + @property + def local(self): + version_string = str(self) + if "+" in version_string: + return version_string.split("+", 1)[1] + + @property + def is_prerelease(self): + return bool(self._version.dev or self._version.pre) + + @property + def is_postrelease(self): + return bool(self._version.post) + + +def _parse_letter_version(letter, number): + if letter: + # We consider there to be an implicit 0 in a pre-release if there is + # not a numeral associated with it. + if number is None: + number = 0 + + # We normalize any letters to their lower case form + letter = letter.lower() + + # We consider some words to be alternate spellings of other words and + # in those cases we want to normalize the spellings to our preferred + # spelling. + if letter == "alpha": + letter = "a" + elif letter == "beta": + letter = "b" + elif letter in ["c", "pre", "preview"]: + letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" + + return letter, int(number) + if not letter and number: + # We assume if we are given a number, but we are not given a letter + # then this is using the implicit post release syntax (e.g. 1.0-1) + letter = "post" + + return letter, int(number) + + +_local_version_seperators = re.compile(r"[\._-]") + + +def _parse_local_version(local): + """ + Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). + """ + if local is not None: + return tuple( + part.lower() if not part.isdigit() else int(part) + for part in _local_version_seperators.split(local) + ) + + +def _cmpkey(epoch, release, pre, post, dev, local): + # When we compare a release version, we want to compare it with all of the + # trailing zeros removed. So we'll use a reverse the list, drop all the now + # leading zeros until we come to something non zero, then take the rest + # re-reverse it back into the correct order and make it a tuple and use + # that for our sorting key. + release = tuple( + reversed(list( + itertools.dropwhile( + lambda x: x == 0, + reversed(release), + ) + )) + ) + + # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. + # We'll do this by abusing the pre segment, but we _only_ want to do this + # if there is not a pre or a post segment. If we have one of those then + # the normal sorting rules will handle this case correctly. + if pre is None and post is None and dev is not None: + pre = -Infinity + # Versions without a pre-release (except as noted above) should sort after + # those with one. + elif pre is None: + pre = Infinity + + # Versions without a post segment should sort before those with one. + if post is None: + post = -Infinity + + # Versions without a development segment should sort after those with one. + if dev is None: + dev = Infinity + + if local is None: + # Versions without a local segment should sort before those with one. + local = -Infinity + else: + # Versions with a local segment need that segment parsed to implement + # the sorting rules in PEP440. + # - Alpha numeric segments sort before numeric segments + # - Alpha numeric segments sort lexicographically + # - Numeric segments sort numerically + # - Shorter versions sort before longer versions when the prefixes + # match exactly + local = tuple( + (i, "") if isinstance(i, int) else (-Infinity, i) + for i in local + ) + + return epoch, release, pre, post, dev, local diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/pyparsing.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/pyparsing.py new file mode 100644 index 0000000..4aa30ee --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/pyparsing.py @@ -0,0 +1,5742 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2018 Paul T. McGuire +# +# 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. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes + - construct character word-group expressions using the L{Word} class + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes + - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones + - associate names with your parsed results using L{ParserElement.setResultsName} + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} + - find more useful common expressions in the L{pyparsing_common} namespace class +""" + +__version__ = "2.2.1" +__versionTime__ = "18 Sep 2018 00:49 UTC" +__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + # Python 3 + from collections.abc import Iterable + from collections.abc import MutableMapping +except ImportError: + # Python 2.7 + from collections import Iterable + from collections import MutableMapping + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "</", resTag, ">" ] + + out += [ nl, indent, "</", selfTag, ">" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) + +def lineno(loc,strg): + """Returns current line number within a string, counting newlines as line separators. + The first line is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [frame_summary[:2]] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [frame_summary[:2]] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "<parse action>" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, <TAB> and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}<parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. + + See examples in L{I{copy}<copy>}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or preloc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}<parseWithTabs>}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}<parseString>} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of <TAB>s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{<TAB>} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): + throwException = True + + if throwException: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except Exception: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "<SPC>", + "\t": "<TAB>", + "\n": "<LF>", + "\r": "<CR>", + "\f": "<FF>", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc<len(instring): + if instring[loc] == "\n": + return loc+1, "\n" + else: + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class StringStart(_PositionToken): + """ + Matches if current position is at the beginning of the parse string + """ + def __init__( self ): + super(StringStart,self).__init__() + self.errmsg = "Expected start of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc != 0: + # see if entire string up to here is just whitespace and ignoreables + if loc != self.preParse( instring, 0 ): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class StringEnd(_PositionToken): + """ + Matches if current position is at the end of the parse string + """ + def __init__( self ): + super(StringEnd,self).__init__() + self.errmsg = "Expected end of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc < len(instring): + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + elif loc > len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + +class ParseExpression(ParserElement): + """ + Abstract subclass of ParserElement, for combining and post-processing parsed tokens. + """ + def __init__( self, exprs, savelist = False ): + super(ParseExpression,self).__init__(savelist) + if isinstance( exprs, _generatorType ): + exprs = list(exprs) + + if isinstance( exprs, basestring ): + self.exprs = [ ParserElement._literalStringClass( exprs ) ] + elif isinstance( exprs, Iterable ): + exprs = list(exprs) + # if sequence of strings provided, wrap with Literal + if all(isinstance(expr, basestring) for expr in exprs): + exprs = map(ParserElement._literalStringClass, exprs) + self.exprs = list(exprs) + else: + try: + self.exprs = list( exprs ) + except TypeError: + self.exprs = [ exprs ] + self.callPreparse = False + + def __getitem__( self, i ): + return self.exprs[i] + + def append( self, other ): + self.exprs.append( other ) + self.strRepr = None + return self + + def leaveWhitespace( self ): + """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on + all contained expressions.""" + self.skipWhitespace = False + self.exprs = [ e.copy() for e in self.exprs ] + for e in self.exprs: + e.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + else: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + return self + + def __str__( self ): + try: + return super(ParseExpression,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) + return self.strRepr + + def streamline( self ): + super(ParseExpression,self).streamline() + + for e in self.exprs: + e.streamline() + + # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) + # but only if there are no parse actions or resultsNames on the nested And's + # (likewise for Or's and MatchFirst's) + if ( len(self.exprs) == 2 ): + other = self.exprs[0] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = other.exprs[:] + [ self.exprs[1] ] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + other = self.exprs[-1] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = self.exprs[:-1] + other.exprs[:] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + self.errmsg = "Expected " + _ustr(self) + + return self + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ParseExpression,self).setResultsName(name,listAllMatches) + return ret + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + for e in self.exprs: + e.validate(tmp) + self.checkRecursion( [] ) + + def copy(self): + ret = super(ParseExpression,self).copy() + ret.exprs = [e.copy() for e in self.exprs] + return ret + +class And(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found in the given order. + Expressions may be separated by whitespace. + May be constructed using the C{'+'} operator. + May also be constructed using the C{'-'} operator, which will suppress backtracking. + + Example:: + integer = Word(nums) + name_expr = OneOrMore(Word(alphas)) + + expr = And([integer("id"),name_expr("name"),integer("age")]) + # more easily written as: + expr = integer("id") + name_expr("name") + integer("age") + """ + + class _ErrorStop(Empty): + def __init__(self, *args, **kwargs): + super(And._ErrorStop,self).__init__(*args, **kwargs) + self.name = '-' + self.leaveWhitespace() + + def __init__( self, exprs, savelist = True ): + super(And,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.setWhitespaceChars( self.exprs[0].whiteChars ) + self.skipWhitespace = self.exprs[0].skipWhitespace + self.callPreparse = True + + def parseImpl( self, instring, loc, doActions=True ): + # pass False as last arg to _parse for first element, since we already + # pre-parsed the string as part of our And pre-parsing + loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False + for e in self.exprs[1:]: + if isinstance(e, And._ErrorStop): + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseSyntaxException: + raise + except ParseBaseException as pe: + pe.__traceback__ = None + raise ParseSyntaxException._from_exception(pe) + except IndexError: + raise ParseSyntaxException(instring, len(instring), self.errmsg, self) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) + if exprtokens or exprtokens.haskeys(): + resultlist += exprtokens + return loc, resultlist + + def __iadd__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #And( [ self, other ] ) + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + if not e.mayReturnEmpty: + break + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + +class Or(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the expression that matches the longest string will be used. + May be constructed using the C{'^'} operator. + + Example:: + # construct Or using '^' operator + + number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) + prints:: + [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(Or,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + matches = [] + for e in self.exprs: + try: + loc2 = e.tryParse( instring, loc ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens)))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <<leaving remove_duplicate_chars (ret: 'dfjkls') + ['dfjkls'] + """ + f = _trim_arity(f) + def z(*paArgs): + thisFunc = f.__name__ + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) + raise + sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) + return ret + try: + z.__name__ = f.__name__ + except AttributeError: + pass + return z + +# +# global helpers +# +def delimitedList( expr, delim=",", combine=False ): + """ + Helper to define a delimited list of expressions - the delimiter defaults to ','. + By default, the list elements and delimiters can have intervening whitespace, and + comments, but this can be overridden by passing C{combine=True} in the constructor. + If C{combine} is set to C{True}, the matching tokens are returned as a single token + string, with the delimiters included; otherwise, the matching tokens are returned + as a list of tokens, with the delimiters suppressed. + + Example:: + delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test <b> bold <i>text</i> </b> normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + ['<b> bold <i>text</i> </b>'] + ['<i>text</i>'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{<TAB>} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString<ParserElement.transformString>}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("</") + tagStr + ">") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the <A> tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{<TD>} or C{<DIV>}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' + <div> + Some text + <div type="grid">1 4 0 1 0</div> + <div type="graph">1,3 2,3 1,1</div> + <div>this has no type</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' + <div> + Some text + <div class="grid">1 4 0 1 0</div> + <div class="graph">1,3 2,3 1,1</div> + <div>this <div> has no class</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") +"Comment of the form C{<!-- ... -->}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) + - common L{programming identifiers<identifier>} + - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) + - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} + - L{UUID<uuid>} + - L{comma-separated list<comma_separated_list>} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/winvenv/Lib/site-packages/pkg_resources/_vendor/six.py b/winvenv/Lib/site-packages/pkg_resources/_vendor/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/_vendor/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# 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. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/winvenv/Lib/site-packages/pkg_resources/extern/__init__.py b/winvenv/Lib/site-packages/pkg_resources/extern/__init__.py new file mode 100644 index 0000000..c1eb9e9 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/extern/__init__.py @@ -0,0 +1,73 @@ +import sys + + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from root_name. + """ + + def __init__(self, root_name, vendored_names=(), vendor_pkg=None): + self.root_name = root_name + self.vendored_names = set(vendored_names) + self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') + + @property + def search_path(self): + """ + Search first the vendor package then as a natural package. + """ + yield self.vendor_pkg + '.' + yield '' + + def find_module(self, fullname, path=None): + """ + Return self when fullname starts with root_name and the + target module is one vendored through this importer. + """ + root, base, target = fullname.partition(self.root_name + '.') + if root: + return + if not any(map(target.startswith, self.vendored_names)): + return + return self + + def load_module(self, fullname): + """ + Iterate over the search path to locate and load fullname. + """ + root, base, target = fullname.partition(self.root_name + '.') + for prefix in self.search_path: + try: + extant = prefix + target + __import__(extant) + mod = sys.modules[extant] + sys.modules[fullname] = mod + # mysterious hack: + # Remove the reference to the extant package/module + # on later Python versions to cause relative imports + # in the vendor package to resolve the same modules + # as those going through this importer. + if prefix and sys.version_info > (3, 3): + del sys.modules[extant] + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + def install(self): + """ + Install this importer into sys.meta_path if not already present. + """ + if self not in sys.meta_path: + sys.meta_path.append(self) + + +names = 'packaging', 'pyparsing', 'six', 'appdirs' +VendorImporter(__name__, names).install() diff --git a/winvenv/Lib/site-packages/pkg_resources/py31compat.py b/winvenv/Lib/site-packages/pkg_resources/py31compat.py new file mode 100644 index 0000000..a381c42 --- /dev/null +++ b/winvenv/Lib/site-packages/pkg_resources/py31compat.py @@ -0,0 +1,23 @@ +import os +import errno +import sys + +from .extern import six + + +def _makedirs_31(path, exist_ok=False): + try: + os.makedirs(path) + except OSError as exc: + if not exist_ok or exc.errno != errno.EEXIST: + raise + + +# rely on compatibility behavior until mode considerations +# and exists_ok considerations are disentangled. +# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 +needs_makedirs = ( + six.PY2 or + (3, 4) <= sys.version_info < (3, 4, 1) +) +makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1-nspkg.pth b/winvenv/Lib/site-packages/protobuf-3.6.1-nspkg.pth new file mode 100644 index 0000000..baef7a0 --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1-nspkg.pth @@ -0,0 +1 @@ +import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('google', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('google', [os.path.dirname(p)])));m = m or sys.modules.setdefault('google', types.ModuleType('google'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p) diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/DESCRIPTION.rst b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..fbb6514 --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/DESCRIPTION.rst @@ -0,0 +1,3 @@ +Protocol Buffers are Google's data interchange format + + diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/INSTALLER b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/METADATA b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/METADATA new file mode 100644 index 0000000..4fd7d4a --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/METADATA @@ -0,0 +1,22 @@ +Metadata-Version: 2.0 +Name: protobuf +Version: 3.6.1 +Summary: Protocol Buffers +Home-page: https://developers.google.com/protocol-buffers/ +Author: protobuf@googlegroups.com +Author-email: protobuf@googlegroups.com +License: 3-Clause BSD License +Download-URL: https://github.com/google/protobuf/releases +Platform: UNKNOWN +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Requires-Dist: setuptools +Requires-Dist: six (>=1.9) + +Protocol Buffers are Google's data interchange format + + diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/RECORD b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/RECORD new file mode 100644 index 0000000..89e4dcd --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/RECORD @@ -0,0 +1,199 @@ +google/protobuf/__init__.py,sha256=IXZY1uQZo6uUYULttDPrk1xt42Nn7TeEThamsEf7drA,1890 +google/protobuf/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/__pycache__/any_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/any_test_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/api_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor_database.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/descriptor_pool.cpython-37.pyc,, +google/protobuf/__pycache__/duration_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/empty_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/field_mask_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/json_format.cpython-37.pyc,, +google/protobuf/__pycache__/map_proto2_unittest_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/map_unittest_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/message.cpython-37.pyc,, +google/protobuf/__pycache__/message_factory.cpython-37.pyc,, +google/protobuf/__pycache__/proto_builder.cpython-37.pyc,, +google/protobuf/__pycache__/reflection.cpython-37.pyc,, +google/protobuf/__pycache__/service.cpython-37.pyc,, +google/protobuf/__pycache__/service_reflection.cpython-37.pyc,, +google/protobuf/__pycache__/source_context_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/struct_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/symbol_database.cpython-37.pyc,, +google/protobuf/__pycache__/test_messages_proto2_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/test_messages_proto3_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/text_encoding.cpython-37.pyc,, +google/protobuf/__pycache__/text_format.cpython-37.pyc,, +google/protobuf/__pycache__/timestamp_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/type_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_arena_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_custom_options_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_import_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_import_public_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_mset_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_mset_wire_format_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_no_arena_import_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_no_arena_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_no_generic_services_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/unittest_proto3_arena_pb2.cpython-37.pyc,, +google/protobuf/__pycache__/wrappers_pb2.cpython-37.pyc,, +google/protobuf/any_pb2.py,sha256=jX1N3BZPQ1ljpWBj-_H8pu1U3ED8XsGSj5uWWfR4uAM,2616 +google/protobuf/any_test_pb2.py,sha256=Je2Pnm0M7pBWkvbh_s5j3MdfZ4a55-pru2O5U5fxmWo,3233 +google/protobuf/api_pb2.py,sha256=7mhGaMy5mJ6PsTmBj51s4-K4dZ9xk4SJo5nbmcOClIw,11001 +google/protobuf/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +google/protobuf/compiler/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/compiler/__pycache__/plugin_pb2.cpython-37.pyc,, +google/protobuf/compiler/plugin_pb2.py,sha256=dRdhy2Y_SOYQG4PIQMt0rfEooBFAk8HF-phU6_-QwB8,10823 +google/protobuf/descriptor.py,sha256=AZCOUjTKshZaUUOfrgx-w-9okNe2fnHgJH8DKe-0SAI,41646 +google/protobuf/descriptor_database.py,sha256=70o7KvrTdzAQyVWmRTGXFHuXNvKFhp4zAKfNLDhwgb4,6295 +google/protobuf/descriptor_pb2.py,sha256=khZQjsmMwCYXKI2RARk5P15dbiDKkP1HZ8isUMD1tJU,92218 +google/protobuf/descriptor_pool.py,sha256=jRpu1Ul-poVr5LpcwsspkzwaPQDRZAe5Kw99Lk569Xs,37891 +google/protobuf/duration_pb2.py,sha256=rAlKCSzzY0wBt6WMxu8Z2LQqBfzqIpjfWtJwTEr_U2c,2710 +google/protobuf/empty_pb2.py,sha256=dKScylLS-ViOg3Dt-rRzLFaVsJKEePOZBZ04m18J54o,1859 +google/protobuf/field_mask_pb2.py,sha256=e2VW6az0kh9mfjG-vkrj48ecr2r-q3jV_EJy5cDkIW8,2341 +google/protobuf/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +google/protobuf/internal/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/internal/__pycache__/_parameterized.cpython-37.pyc,, +google/protobuf/internal/__pycache__/any_test_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/api_implementation.cpython-37.pyc,, +google/protobuf/internal/__pycache__/containers.cpython-37.pyc,, +google/protobuf/internal/__pycache__/decoder.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_database_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_pool_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_pool_test1_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_pool_test2_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/descriptor_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/encoder.cpython-37.pyc,, +google/protobuf/internal/__pycache__/enum_type_wrapper.cpython-37.pyc,, +google/protobuf/internal/__pycache__/factory_test1_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/factory_test2_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/file_options_test_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/generator_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/json_format_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_factory_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_listener.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_set_extensions_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/message_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/missing_enum_values_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/more_extensions_dynamic_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/more_extensions_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/more_messages_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/no_package_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/packed_field_test_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/proto_builder_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/python_message.cpython-37.pyc,, +google/protobuf/internal/__pycache__/reflection_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/service_reflection_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/symbol_database_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/test_bad_identifiers_pb2.cpython-37.pyc,, +google/protobuf/internal/__pycache__/test_util.cpython-37.pyc,, +google/protobuf/internal/__pycache__/testing_refleaks.cpython-37.pyc,, +google/protobuf/internal/__pycache__/text_encoding_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/text_format_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/type_checkers.cpython-37.pyc,, +google/protobuf/internal/__pycache__/unknown_fields_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/well_known_types.cpython-37.pyc,, +google/protobuf/internal/__pycache__/well_known_types_test.cpython-37.pyc,, +google/protobuf/internal/__pycache__/wire_format.cpython-37.pyc,, +google/protobuf/internal/__pycache__/wire_format_test.cpython-37.pyc,, +google/protobuf/internal/_parameterized.py,sha256=FWoyU_OUH3qtMf6VI1qRd2D37ypsrNk_LlwivqQQIk0,15343 +google/protobuf/internal/any_test_pb2.py,sha256=zlLAkahTnDZ1EMzfLojTHvO6IvpbrfWHGIG-1YzCdE8,7055 +google/protobuf/internal/api_implementation.py,sha256=LnP9LiGKTRAVkB7_3qS7Xlqp-nOp4LJROwIdurajGv0,7237 +google/protobuf/internal/containers.py,sha256=b3e9OfWc9T2ZK2iTnj_TqzFTVSFf8_DgU7xWD2mFaGI,20976 +google/protobuf/internal/decoder.py,sha256=Pzv4Sl_ZaDjB96E-g1vITvnVKSJYJovLq_DpLdV4i7c,31291 +google/protobuf/internal/descriptor_database_test.py,sha256=DTo554U0s1pIyfAmEUQmMgPBZUPGkYjkuIzfo9cuoPY,5511 +google/protobuf/internal/descriptor_pool_test.py,sha256=GbLBaLzse6Zf2-n9FK2zODLmb754XvcLSizEAOlSmIk,46056 +google/protobuf/internal/descriptor_pool_test1_pb2.py,sha256=IKpOjuT-PfIjs-R5y_SGX3nFKUtFIyBXNq4cNPWLp7Y,21326 +google/protobuf/internal/descriptor_pool_test2_pb2.py,sha256=mLSGMQ7LHgfISFnNFrDC9W2E_8N18E81q7B2v03u-Y8,12614 +google/protobuf/internal/descriptor_test.py,sha256=JYsb45SC5gb0hPthWa5yd3ECZhNSotVhzF5nM6JI_LE,43029 +google/protobuf/internal/encoder.py,sha256=e4NkXj540EEdk0fUsTcYKiPB2aofGnW_eYiHJnEmWC0,28587 +google/protobuf/internal/enum_type_wrapper.py,sha256=S7yGMF9PamOpMkiur5edHi25zjuIsRluavCvNVlh4hQ,3554 +google/protobuf/internal/factory_test1_pb2.py,sha256=sf_5gHL-n3KG3h1qLpxEBMXkWA2jOIXKax3YnvndV7c,7954 +google/protobuf/internal/factory_test2_pb2.py,sha256=e5HNqsI7t2AjM3kzvqZlUFw4IReskb1qULVBWfdzMGI,25201 +google/protobuf/internal/file_options_test_pb2.py,sha256=nNLdJKh-r-JiNSunNuIdzz7bn1G5nRBJtkt0aNf0np8,3072 +google/protobuf/internal/generator_test.py,sha256=eOz2eYK7ez-nEZasd_t_tIufokRJoXcVJWrKvzhpg64,14773 +google/protobuf/internal/import_test_package/__init__.py,sha256=Dct4MqAtKH6cguzoEmmhey5QUBZcpwBP8o1KwS0Z8H4,1768 +google/protobuf/internal/import_test_package/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/internal/import_test_package/__pycache__/inner_pb2.cpython-37.pyc,, +google/protobuf/internal/import_test_package/__pycache__/outer_pb2.cpython-37.pyc,, +google/protobuf/internal/import_test_package/inner_pb2.py,sha256=TB9Cv_qsg_4T9jSsouaUGJietNC9SflWwt_XBRdsQys,2204 +google/protobuf/internal/import_test_package/outer_pb2.py,sha256=Q1c7YtNWYDSgVI9YhDbsMFRooJaeuJUm8SyIc3D7ek8,2694 +google/protobuf/internal/json_format_test.py,sha256=SrmNwb_KDE1Iw-UVOaY0M1X5BSjlBIQZWmJXAMQTwME,42051 +google/protobuf/internal/message_factory_test.py,sha256=ez7JkALMs5opsNu4cu8avu5XldM-sipYHw988EfRPKY,9678 +google/protobuf/internal/message_listener.py,sha256=Qwc5gkifAvWzhm3b0v-nXJkozNTgL-L92XAslngFaow,3367 +google/protobuf/internal/message_set_extensions_pb2.py,sha256=arQVEw130wj6ZHdkhnCoQ9O1I_8Ptnt5N36gNaSLbbk,8404 +google/protobuf/internal/message_test.py,sha256=9BNes4_wxX9cf_J4MkVnVxCNddvzX4s88XTNPD_5Kks,88370 +google/protobuf/internal/missing_enum_values_pb2.py,sha256=zzBQK26qmctAqXlQykunC_QZoBd2Q_KDnUrk0eM9A6o,9356 +google/protobuf/internal/more_extensions_dynamic_pb2.py,sha256=cGONkEkOTkuj1ise6S1tvBke3UQd_Z56n06rXAP94kk,5005 +google/protobuf/internal/more_extensions_pb2.py,sha256=3TWgANFY_blVY6bXAbzdl52tkUaVMxqCOYy_lk4kpxw,7386 +google/protobuf/internal/more_messages_pb2.py,sha256=44oWSpPB2X-cEA4TbGSKfTLZ8YbzVOa5KSln2mEfVGs,4312 +google/protobuf/internal/no_package_pb2.py,sha256=lbExkdz53McjKrJsjX_b61Djy2TZkyA3dQL9NfeDbng,3026 +google/protobuf/internal/packed_field_test_pb2.py,sha256=uyVVoIBsycPeqr9N8yb7UMEoYUmGRYDy4M6hDwuvoS4,17924 +google/protobuf/internal/proto_builder_test.py,sha256=P7Q0_UHmkqSXi2QP-6zC_gMN88mF6efI2UYnM2iylCo,3770 +google/protobuf/internal/python_message.py,sha256=E3yP2v2iSZgT4nD2aS7Z2fGKlcuVPUybrF4t9aYo2DM,57846 +google/protobuf/internal/reflection_test.py,sha256=7SlWF2mA_Az2DeJBHHkZdkTJJMKmP4nkUBtlIkOg43U,128260 +google/protobuf/internal/service_reflection_test.py,sha256=jYtRs4vKa2FzQzgwj8azRDHExaYK6DlPO780d0ov858,5412 +google/protobuf/internal/symbol_database_test.py,sha256=fyzmO4nMO-ovNUn0IHewDc_2TSTpE1gBDENWF727wkM,5650 +google/protobuf/internal/test_bad_identifiers_pb2.py,sha256=O02edr6ZvCnDWr5YsfFQOPOks3B4W0MxYcIc9XhklcI,5917 +google/protobuf/internal/test_util.py,sha256=59gOA94XkeW2RncpRKOhV8qeqpHssw1z-CdCPMD4Ajo,33949 +google/protobuf/internal/testing_refleaks.py,sha256=bdx5k6rzfcKpP677p7zu3S29-HhefjM-OxB6Ml1WX8Y,4507 +google/protobuf/internal/text_encoding_test.py,sha256=56hukUTsINXsld66zDjHqxg9-P2cZb3_sOdSAli1SSI,2903 +google/protobuf/internal/text_format_test.py,sha256=reZRN1___aOAwK3Djb4vaM_8_mWeN5G5n-SG8_5AnU4,68058 +google/protobuf/internal/type_checkers.py,sha256=8dkYGv6bpPbrvsZ6avSPAx2Xv_mbGOxbBeXRrBf413I,14229 +google/protobuf/internal/unknown_fields_test.py,sha256=t9x7Mjz2eU8Qg0zqrbnySnNMCyIoqmOQK8AIYxsbQJc,13868 +google/protobuf/internal/well_known_types.py,sha256=w3GYttPYtq-_gYkWwpcYDqqNjAQoKdzYoA6tVqvBnXI,28448 +google/protobuf/internal/well_known_types_test.py,sha256=F-zNHh8tXGl-3ZINPnzsVcFyVh_u5hvD0m2pKNZs8wk,35994 +google/protobuf/internal/wire_format.py,sha256=7Wz8gV7QOvoTzLMWrwlWSg7hIJ_T8Pm1w8_WLhpieVw,8444 +google/protobuf/internal/wire_format_test.py,sha256=UNUam8dc8Ex9V2EELOCd0tKIY2yLGBTDtV8y75LGyz0,10930 +google/protobuf/json_format.py,sha256=MkKzgAuF-ilClod4RVX9mxDe0A3hfOHJuH3J4H7I5XA,29835 +google/protobuf/map_proto2_unittest_pb2.py,sha256=as6RUX1ziZpHDvOhXxSo_bYfdIuBh-nm8cJgmpt7wq8,53646 +google/protobuf/map_unittest_pb2.py,sha256=UENFUlJb0miJAjhunttGDS7_C8ozEmMb8Bb7opiFZSQ,121531 +google/protobuf/message.py,sha256=chs-OnslNPDyHnhPinhOMHnYj6N1170o28n8A2yfDfE,11454 +google/protobuf/message_factory.py,sha256=ntyh1gqWh6gsOJ2VULFI42J6stVMtHmFKLcm7j8AmH0,6279 +google/protobuf/proto_builder.py,sha256=JBGzUkVd7eDz8cdzUbpIvy2-JbFPfsGcaIAJJII3gfI,5202 +google/protobuf/pyext/__init__.py,sha256=8SXBh8YGxPXGDmFtR_n90wt5xWvc5CEp_L5Pn687VaU,150 +google/protobuf/pyext/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/pyext/__pycache__/cpp_message.cpython-37.pyc,, +google/protobuf/pyext/__pycache__/python_pb2.cpython-37.pyc,, +google/protobuf/pyext/cpp_message.py,sha256=D0-bxtjf1Ri8b0GubL5xgkkEB_z_mIf847yrRvVqDBU,2851 +google/protobuf/pyext/python_pb2.py,sha256=10npuLYyZfV_XDXPPU9-IRN8_yzVgG-VMzEfKCgdVKw,9753 +google/protobuf/reflection.py,sha256=COX524Q39vboPZI8LVAuomnPxBKUBw3pcMS14IG721I,4562 +google/protobuf/service.py,sha256=wRQxBH9JJRY3h8WPR5V3OTW-BWuX0YZlBLmwnjCL41w,9144 +google/protobuf/service_reflection.py,sha256=9EgQ3T-Haae0i8RQkVqqfpchNT9VxdDnBL46DGyKW-Y,11023 +google/protobuf/source_context_pb2.py,sha256=bJkN-fRy8fqWPQCYdx8DNumkjBLFxgBWbT1YT-oJCsY,2456 +google/protobuf/struct_pb2.py,sha256=TAOOgrEz8gl30SXdYNbpHNrkJd7EAHWys09wG321WGk,10807 +google/protobuf/symbol_database.py,sha256=AC51asImDuv2rH1lOHJMXiG9TVRwjNQXW8IRGLzCWmM,6423 +google/protobuf/test_messages_proto2_pb2.py,sha256=hM2VaXwQi3I3VXGYuYMi_77DVnoHeTbEsWsARiG00Q4,104956 +google/protobuf/test_messages_proto3_pb2.py,sha256=Vxdjj7Gym9Vc9eJU6XUNSDpwlp0cyWB9qwDNEqmPn0s,115424 +google/protobuf/text_encoding.py,sha256=jmPTJzMNTwNC2p97swdNfH3qGnSIop-zxWREO9cR6X0,4617 +google/protobuf/text_format.py,sha256=vM0ksbtb3bXav8F04hqbPu_wSUy23pgKWopxREkeF5I,51635 +google/protobuf/timestamp_pb2.py,sha256=iO97wijlMxP2AYj-HxwjL8ugVlgkbO7wHX6SDqt50ek,2730 +google/protobuf/type_pb2.py,sha256=al7co5w3ENZ8snO8PUjqio9fgpEpn7eJ8-v-GGW4qCs,22405 +google/protobuf/unittest_arena_pb2.py,sha256=ZPZzTa1KEqNiLXMU6XYOHTnvjvW6SEc0vr-Zo1KDoBs,4459 +google/protobuf/unittest_custom_options_pb2.py,sha256=aUHqihyca3aPZa9XitRjVNCG6Ku7CE99peGU1nP2Z-s,84726 +google/protobuf/unittest_import_pb2.py,sha256=KqQmCPgRjQFsgkkFLXTWXFJwwr3GT6TDmx-xa4AFENQ,4608 +google/protobuf/unittest_import_public_pb2.py,sha256=cJH7slGJMMoF114TBT_Xhc0I91gK3zjmvSsL74RtJVk,2261 +google/protobuf/unittest_mset_pb2.py,sha256=JpWHQ_jK4PFckn2NCp7iGBZMFxzYU29sVtWqy3nMF2s,9999 +google/protobuf/unittest_mset_wire_format_pb2.py,sha256=TR6QhsVlUPxEVVTf3dwzgPCgzWYj6NL9kKMN2fKMwCw,3619 +google/protobuf/unittest_no_arena_import_pb2.py,sha256=dMklN5NC1XjhKC2BeXPJqpbl_au_gRpy87kDYsX_JAw,2239 +google/protobuf/unittest_no_arena_pb2.py,sha256=mxWKvqnFqkAyEd5ZvWAoGeJq19BJtr3WQLEv1Q2fDXw,51593 +google/protobuf/unittest_no_generic_services_pb2.py,sha256=2OROGsxYLF2LARGgAkplHZ0iDUZsrdFwoxqVZTJptBE,4306 +google/protobuf/unittest_pb2.py,sha256=M2M32bPdb1iupAX3iI6IJLYWJRNmaHlqB3Cpqkx6CCU,352539 +google/protobuf/unittest_proto3_arena_pb2.py,sha256=Ncnw8Fo9W41xdiixLjri0ILhCacH4ghe90Z-58T_ALQ,54739 +google/protobuf/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +google/protobuf/util/__pycache__/__init__.cpython-37.pyc,, +google/protobuf/util/__pycache__/json_format_proto3_pb2.cpython-37.pyc,, +google/protobuf/util/json_format_proto3_pb2.py,sha256=3JpbT2bhs4H0Ytkw9iryFYH1N0VOhllvhwYkxz7PbbM,81998 +google/protobuf/wrappers_pb2.py,sha256=ydUcYPdruald1EgKMqa5A6mF-4s9XS-mDl-DQGkMngs,11626 +protobuf-3.6.1-nspkg.pth,sha256=xH5gTxc4UipYP3qrbP-4CCHNGBV97eBR4QqhheCvBl4,539 +protobuf-3.6.1.dist-info/DESCRIPTION.rst,sha256=utqsVRNbVQSVt3QnFDS0kBvLICkz66brPchJfhbEx1I,56 +protobuf-3.6.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +protobuf-3.6.1.dist-info/METADATA,sha256=I9Ci2WfM-TAoCwbUs1F9Avzh-3cWGqpRXXBW2RttgSk,716 +protobuf-3.6.1.dist-info/RECORD,, +protobuf-3.6.1.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +protobuf-3.6.1.dist-info/metadata.json,sha256=rDvuAuP0g4zC6PT2jhoXU2qLQdnqJt9YLJtI9P5ITEU,838 +protobuf-3.6.1.dist-info/namespace_packages.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7 +protobuf-3.6.1.dist-info/top_level.txt,sha256=_1QvSJIhFAGfxb79D6DhB7SUw2X6T4rwnz_LLrbcD3c,7 diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/WHEEL b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/WHEEL new file mode 100644 index 0000000..8b6dd1b --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/metadata.json b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/metadata.json new file mode 100644 index 0000000..cb4d625 --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4"], "download_url": "https://github.com/google/protobuf/releases", "extensions": {"python.details": {"contacts": [{"email": "protobuf@googlegroups.com", "name": "protobuf@googlegroups.com", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://developers.google.com/protocol-buffers/"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "license": "3-Clause BSD License", "metadata_version": "2.0", "name": "protobuf", "run_requires": [{"requires": ["setuptools", "six (>=1.9)"]}], "summary": "Protocol Buffers", "version": "3.6.1"} \ No newline at end of file diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt new file mode 100644 index 0000000..cb42911 --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/namespace_packages.txt @@ -0,0 +1 @@ +google diff --git a/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/top_level.txt b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/top_level.txt new file mode 100644 index 0000000..cb42911 --- /dev/null +++ b/winvenv/Lib/site-packages/protobuf-3.6.1.dist-info/top_level.txt @@ -0,0 +1 @@ +google diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/INSTALLER b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/LICENSE b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/LICENSE new file mode 100644 index 0000000..6e0693b --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2016 Jason R Coombs <jaraco@jaraco.com> + +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/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/METADATA b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/METADATA new file mode 100644 index 0000000..5a5fde1 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/METADATA @@ -0,0 +1,73 @@ +Metadata-Version: 2.1 +Name: setuptools +Version: 40.6.2 +Summary: Easily download, build, install, upgrade, and uninstall Python packages +Home-page: https://github.com/pypa/setuptools +Author: Python Packaging Authority +Author-email: distutils-sig@python.org +License: UNKNOWN +Project-URL: Documentation, https://setuptools.readthedocs.io/ +Keywords: CPAN PyPI distutils eggs package management +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +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 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Archiving :: Packaging +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* +Description-Content-Type: text/x-rst; charset=UTF-8 +Provides-Extra: certs +Requires-Dist: certifi (==2016.9.26); extra == 'certs' +Provides-Extra: ssl +Requires-Dist: wincertstore (==0.2); (sys_platform=='win32') and extra == 'ssl' + +.. image:: https://img.shields.io/pypi/v/setuptools.svg + :target: https://pypi.org/project/setuptools + +.. image:: https://readthedocs.org/projects/setuptools/badge/?version=latest + :target: https://setuptools.readthedocs.io + +.. image:: https://img.shields.io/travis/pypa/setuptools/master.svg?label=Linux%20build%20%40%20Travis%20CI + :target: https://travis-ci.org/pypa/setuptools + +.. image:: https://img.shields.io/appveyor/ci/pypa/setuptools/master.svg?label=Windows%20build%20%40%20Appveyor + :target: https://ci.appveyor.com/project/pypa/setuptools/branch/master + +.. image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg + :target: https://codecov.io/gh/pypa/setuptools + +.. image:: https://img.shields.io/pypi/pyversions/setuptools.svg + +.. image:: https://tidelift.com/badges/github/pypa/setuptools + :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme + +See the `Installation Instructions +<https://packaging.python.org/installing/>`_ in the Python Packaging +User's Guide for instructions on installing, upgrading, and uninstalling +Setuptools. + +Questions and comments should be directed to the `distutils-sig +mailing list <http://mail.python.org/pipermail/distutils-sig/>`_. +Bug reports and especially tested patches may be +submitted directly to the `bug tracker +<https://github.com/pypa/setuptools/issues>`_. + + +Code of Conduct +--------------- + +Everyone interacting in the setuptools project's codebases, issue trackers, +chat rooms, and mailing lists is expected to follow the +`PyPA Code of Conduct <https://www.pypa.io/en/latest/code-of-conduct/>`_. + + diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/RECORD b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/RECORD new file mode 100644 index 0000000..13922d3 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/RECORD @@ -0,0 +1,188 @@ +../../Scripts/easy_install-3.7.exe,sha256=mwN0h1VG3i0CY-Or6SXEqcb2x7pUT7-pgLR30NPuxho,102809 +../../Scripts/easy_install.exe,sha256=mwN0h1VG3i0CY-Or6SXEqcb2x7pUT7-pgLR30NPuxho,102809 +__pycache__/easy_install.cpython-37.pyc,, +easy_install.py,sha256=MDC9vt5AxDsXX5qcKlBz2TnW6Tpuv_AobnfhCJ9X3PM,126 +pkg_resources/__init__.py,sha256=d7w_yqCD39lZE0-qxhWXPYoc-pZc3G2mD7EU2xhRLpM,104720 +pkg_resources/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/__pycache__/py31compat.cpython-37.pyc,, +pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources/_vendor/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/appdirs.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/pyparsing.cpython-37.pyc,, +pkg_resources/_vendor/__pycache__/six.cpython-37.pyc,, +pkg_resources/_vendor/appdirs.py,sha256=MievUEuv3l_mQISH5SF0shDk_BNhHHzYiAPrT3ITN4I,24701 +pkg_resources/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 +pkg_resources/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_compat.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/markers.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/utils.cpython-37.pyc,, +pkg_resources/_vendor/packaging/__pycache__/version.cpython-37.pyc,, +pkg_resources/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pkg_resources/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +pkg_resources/_vendor/packaging/markers.py,sha256=uEcBBtGvzqltgnArqb9c4RrcInXezDLos14zbBHhWJo,8248 +pkg_resources/_vendor/packaging/requirements.py,sha256=SikL2UynbsT0qtY9ltqngndha_sfo0w6XGFhAhoSoaQ,4355 +pkg_resources/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +pkg_resources/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +pkg_resources/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +pkg_resources/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +pkg_resources/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pkg_resources/extern/__init__.py,sha256=cHiEfHuLmm6rs5Ve_ztBfMI7Lr31vss-D4wkqF5xzlI,2498 +pkg_resources/extern/__pycache__/__init__.cpython-37.pyc,, +pkg_resources/py31compat.py,sha256=-WQ0e4c3RG_acdhwC3gLiXhP_lg4G5q7XYkZkQg0gxU,558 +setuptools-40.6.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +setuptools-40.6.2.dist-info/LICENSE,sha256=wyo6w5WvYyHv0ovnPQagDw22q4h9HCHU_sRhKNIFbVo,1078 +setuptools-40.6.2.dist-info/METADATA,sha256=xD5qjTNmFccxhrkNSRwX2ksMINOFNLCysl5ESfOrYRE,3092 +setuptools-40.6.2.dist-info/RECORD,, +setuptools-40.6.2.dist-info/WHEEL,sha256=CihQvCnsGZQBGAHLEUMf0IdA4fRduS_NBUTMgCTtvPM,110 +setuptools-40.6.2.dist-info/dependency_links.txt,sha256=HlkCFkoK5TbZ5EMLbLKYhLcY_E31kBWD8TqW2EgmatQ,239 +setuptools-40.6.2.dist-info/entry_points.txt,sha256=jBqCYDlVjl__sjYFGXo1JQGIMAYFJE-prYWUtnMZEew,2990 +setuptools-40.6.2.dist-info/top_level.txt,sha256=2HUXVVwA4Pff1xgTFr3GsTXXKaPaO6vlG6oNJ_4u4Tg,38 +setuptools-40.6.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +setuptools/__init__.py,sha256=ipsF2yFkfHmryPP8ASJEtOj9N9OuYkk8HxxIJyOHtj0,6001 +setuptools/__pycache__/__init__.cpython-37.pyc,, +setuptools/__pycache__/_deprecation_warning.cpython-37.pyc,, +setuptools/__pycache__/archive_util.cpython-37.pyc,, +setuptools/__pycache__/build_meta.cpython-37.pyc,, +setuptools/__pycache__/config.cpython-37.pyc,, +setuptools/__pycache__/dep_util.cpython-37.pyc,, +setuptools/__pycache__/depends.cpython-37.pyc,, +setuptools/__pycache__/dist.cpython-37.pyc,, +setuptools/__pycache__/extension.cpython-37.pyc,, +setuptools/__pycache__/glibc.cpython-37.pyc,, +setuptools/__pycache__/glob.cpython-37.pyc,, +setuptools/__pycache__/launch.cpython-37.pyc,, +setuptools/__pycache__/lib2to3_ex.cpython-37.pyc,, +setuptools/__pycache__/monkey.cpython-37.pyc,, +setuptools/__pycache__/msvc.cpython-37.pyc,, +setuptools/__pycache__/namespaces.cpython-37.pyc,, +setuptools/__pycache__/package_index.cpython-37.pyc,, +setuptools/__pycache__/pep425tags.cpython-37.pyc,, +setuptools/__pycache__/py27compat.cpython-37.pyc,, +setuptools/__pycache__/py31compat.cpython-37.pyc,, +setuptools/__pycache__/py33compat.cpython-37.pyc,, +setuptools/__pycache__/py36compat.cpython-37.pyc,, +setuptools/__pycache__/sandbox.cpython-37.pyc,, +setuptools/__pycache__/site-patch.cpython-37.pyc,, +setuptools/__pycache__/ssl_support.cpython-37.pyc,, +setuptools/__pycache__/unicode_utils.cpython-37.pyc,, +setuptools/__pycache__/version.cpython-37.pyc,, +setuptools/__pycache__/wheel.cpython-37.pyc,, +setuptools/__pycache__/windows_support.cpython-37.pyc,, +setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 +setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools/_vendor/__pycache__/__init__.cpython-37.pyc,, +setuptools/_vendor/__pycache__/pyparsing.cpython-37.pyc,, +setuptools/_vendor/__pycache__/six.cpython-37.pyc,, +setuptools/_vendor/packaging/__about__.py,sha256=zkcCPTN_6TcLW0Nrlg0176-R1QQ_WVPTm8sz1R4-HjM,720 +setuptools/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +setuptools/_vendor/packaging/__pycache__/__about__.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/__init__.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/_compat.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/_structures.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/markers.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/requirements.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/utils.cpython-37.pyc,, +setuptools/_vendor/packaging/__pycache__/version.cpython-37.pyc,, +setuptools/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +setuptools/_vendor/packaging/_structures.py,sha256=RImECJ4c_wTlaTYYwZYLHEiebDMaAJmK1oPARhw1T5o,1416 +setuptools/_vendor/packaging/markers.py,sha256=Gvpk9EY20yKaMTiKgQZ8yFEEpodqVgVYtfekoic1Yts,8239 +setuptools/_vendor/packaging/requirements.py,sha256=t44M2HVWtr8phIz2OhnILzuGT3rTATaovctV1dpnVIg,4343 +setuptools/_vendor/packaging/specifiers.py,sha256=SAMRerzO3fK2IkFZCaZkuwZaL_EGqHNOz4pni4vhnN0,28025 +setuptools/_vendor/packaging/utils.py,sha256=3m6WvPm6NNxE8rkTGmn0r75B_GZSGg7ikafxHsBN1WA,421 +setuptools/_vendor/packaging/version.py,sha256=OwGnxYfr2ghNzYx59qWIBkrK3SnB6n-Zfd1XaLpnnM0,11556 +setuptools/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +setuptools/_vendor/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +setuptools/archive_util.py,sha256=kw8Ib_lKjCcnPKNbS7h8HztRVK0d5RacU3r_KRdVnmM,6592 +setuptools/build_meta.py,sha256=qg4RfvgZF1uZPuO1VMioG8JRhNMp5fHrwgpgkYpnzc8,6021 +setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 +setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/command/__init__.py,sha256=NWzJ0A1BEengZpVeqUyWLNm2bk4P3F4iL5QUErHy7kA,594 +setuptools/command/__pycache__/__init__.cpython-37.pyc,, +setuptools/command/__pycache__/alias.cpython-37.pyc,, +setuptools/command/__pycache__/bdist_egg.cpython-37.pyc,, +setuptools/command/__pycache__/bdist_rpm.cpython-37.pyc,, +setuptools/command/__pycache__/bdist_wininst.cpython-37.pyc,, +setuptools/command/__pycache__/build_clib.cpython-37.pyc,, +setuptools/command/__pycache__/build_ext.cpython-37.pyc,, +setuptools/command/__pycache__/build_py.cpython-37.pyc,, +setuptools/command/__pycache__/develop.cpython-37.pyc,, +setuptools/command/__pycache__/dist_info.cpython-37.pyc,, +setuptools/command/__pycache__/easy_install.cpython-37.pyc,, +setuptools/command/__pycache__/egg_info.cpython-37.pyc,, +setuptools/command/__pycache__/install.cpython-37.pyc,, +setuptools/command/__pycache__/install_egg_info.cpython-37.pyc,, +setuptools/command/__pycache__/install_lib.cpython-37.pyc,, +setuptools/command/__pycache__/install_scripts.cpython-37.pyc,, +setuptools/command/__pycache__/py36compat.cpython-37.pyc,, +setuptools/command/__pycache__/register.cpython-37.pyc,, +setuptools/command/__pycache__/rotate.cpython-37.pyc,, +setuptools/command/__pycache__/saveopts.cpython-37.pyc,, +setuptools/command/__pycache__/sdist.cpython-37.pyc,, +setuptools/command/__pycache__/setopt.cpython-37.pyc,, +setuptools/command/__pycache__/test.cpython-37.pyc,, +setuptools/command/__pycache__/upload.cpython-37.pyc,, +setuptools/command/__pycache__/upload_docs.cpython-37.pyc,, +setuptools/command/alias.py,sha256=KjpE0sz_SDIHv3fpZcIQK-sCkJz-SrC6Gmug6b9Nkc8,2426 +setuptools/command/bdist_egg.py,sha256=be-IBpr1zhS9i6GjKANJgzkbH3ChImdWY7S-j0r2BK8,18167 +setuptools/command/bdist_rpm.py,sha256=B7l0TnzCGb-0nLlm6rS00jWLkojASwVmdhW2w5Qz_Ak,1508 +setuptools/command/bdist_wininst.py,sha256=_6dz3lpB1tY200LxKPLM7qgwTCceOMgaWFF-jW2-pm0,637 +setuptools/command/build_clib.py,sha256=bQ9aBr-5ZSO-9fGsGsDLz0mnnFteHUZnftVLkhvHDq0,4484 +setuptools/command/build_ext.py,sha256=81CTgsqjBjNl_HOgCJ1lQ5vv1NIM3RBpcoVGpqT4N1M,12897 +setuptools/command/build_py.py,sha256=yWyYaaS9F3o9JbIczn064A5g1C5_UiKRDxGaTqYbtLE,9596 +setuptools/command/develop.py,sha256=Sl1iMOORbAnp5BqiXmyMBD0uuvEnhSfOCqbxIPRiJPc,8060 +setuptools/command/dist_info.py,sha256=5t6kOfrdgALT-P3ogss6PF9k-Leyesueycuk3dUyZnI,960 +setuptools/command/easy_install.py,sha256=telww7CuPsoTtvlpY-ktnZGT85cZ6xGCGZa0vHvFJ-Q,87273 +setuptools/command/egg_info.py,sha256=3lsuTHQFjmAw6slzRrB3HjLiF2TaImpWHREllAPhyv8,25541 +setuptools/command/install.py,sha256=a0EZpL_A866KEdhicTGbuyD_TYl1sykfzdrri-zazT4,4683 +setuptools/command/install_egg_info.py,sha256=bMgeIeRiXzQ4DAGPV1328kcjwQjHjOWU4FngAWLV78Q,2203 +setuptools/command/install_lib.py,sha256=11mxf0Ch12NsuYwS8PHwXBRvyh671QAM4cTRh7epzG0,3840 +setuptools/command/install_scripts.py,sha256=UD0rEZ6861mTYhIdzcsqKnUl8PozocXWl9VBQ1VTWnc,2439 +setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 +setuptools/command/py36compat.py,sha256=SzjZcOxF7zdFUT47Zv2n7AM3H8koDys_0OpS-n9gIfc,4986 +setuptools/command/register.py,sha256=LO3MvYKPE8dN1m-KkrBRHC68ZFoPvA_vI8Xgp7vv6zI,534 +setuptools/command/rotate.py,sha256=co5C1EkI7P0GGT6Tqz-T2SIj2LBJTZXYELpmao6d4KQ,2164 +setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 +setuptools/command/sdist.py,sha256=obDTe2BmWt2PlnFPZZh7e0LWvemEsbCCO9MzhrTZjm8,6711 +setuptools/command/setopt.py,sha256=NTWDyx-gjDF-txf4dO577s7LOzHVoKR0Mq33rFxaRr8,5085 +setuptools/command/test.py,sha256=fSl5OsZWSmFR3QJRvyy2OxbcYkuIkPvykWNOhFvAcUA,9228 +setuptools/command/upload.py,sha256=BpQCjKtJZ4kEb0qIOiTjlJtbpapmNacC27nG2ZlSxTY,6825 +setuptools/command/upload_docs.py,sha256=oXiGplM_cUKLwE4CWWw98RzCufAu8tBhMC97GegFcms,7311 +setuptools/config.py,sha256=nCkzIQRWTpVwvtSlFm1kOeSLMMHXmB7hENxwZUT6X9Q,19751 +setuptools/dep_util.py,sha256=fgixvC1R7sH3r13ktyf7N0FALoqEXL1cBarmNpSEoWg,935 +setuptools/depends.py,sha256=hC8QIDcM3VDpRXvRVA6OfL9AaQfxvhxHcN_w6sAyNq8,5837 +setuptools/dist.py,sha256=HyRYLlPp_gkcnvQf8o1RsGq99LtghAeAfxWxbf40KxA,44675 +setuptools/extension.py,sha256=uc6nHI-MxwmNCNPbUiBnybSyqhpJqjbhvOQ-emdvt_E,1729 +setuptools/extern/__init__.py,sha256=TxeNKFMSfBMzBpBDiHx8Dh3RzsdVmvWaXhtZ03DZMs0,2499 +setuptools/extern/__pycache__/__init__.cpython-37.pyc,, +setuptools/glibc.py,sha256=X64VvGPL2AbURKwYRsWJOXXGAYOiF_v2qixeTkAULuU,3146 +setuptools/glob.py,sha256=o75cHrOxYsvn854thSxE0x9k8JrKDuhP_rRXlVB00Q4,5084 +setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 +setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/launch.py,sha256=sd7ejwhBocCDx_wG9rIs0OaZ8HtmmFU8ZC6IR_S0Lvg,787 +setuptools/lib2to3_ex.py,sha256=t5e12hbR2pi9V4ezWDTB4JM-AISUnGOkmcnYHek3xjg,2013 +setuptools/monkey.py,sha256=FGc9fffh7gAxMLFmJs2DW_OYWpBjkdbNS2n14UAK4NA,5264 +setuptools/msvc.py,sha256=uuRFaZzjJt5Fv3ZmyKUUuLtjx12_8G9RILigGec4irI,40838 +setuptools/namespaces.py,sha256=F0Nrbv8KCT2OrO7rwa03om4N4GZKAlnce-rr-cgDQa8,3199 +setuptools/package_index.py,sha256=yeifZQhJVRwPSaQmRrVPxbXRy-1lF5KdTFV8NAb3YcE,40342 +setuptools/pep425tags.py,sha256=bSGwlybcIpssx9kAv_hqAUJzfEpXSzYRp2u-nDYPdbk,10862 +setuptools/py27compat.py,sha256=3mwxRMDk5Q5O1rSXOERbQDXhFqwDJhhUitfMW_qpUCo,536 +setuptools/py31compat.py,sha256=REvrUBibUHgqI9S-ww0C9bhU-n8PyaQ8Slr1_NRxaaE,820 +setuptools/py33compat.py,sha256=OubjldHJH1KGE1CKt1kRU-Q55keftHT3ea1YoL0ZSco,1195 +setuptools/py36compat.py,sha256=VUDWxmu5rt4QHlGTRtAFu6W5jvfL6WBjeDAzeoBy0OM,2891 +setuptools/sandbox.py,sha256=9UbwfEL5QY436oMI1LtFWohhoZ-UzwHvGyZjUH_qhkw,14276 +setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 +setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 +setuptools/site-patch.py,sha256=OumkIHMuoSenRSW1382kKWI1VAwxNE86E5W8iDd34FY,2302 +setuptools/ssl_support.py,sha256=YBDJsCZjSp62CWjxmSkke9kn9rhHHj25Cus6zhJRW3c,8492 +setuptools/unicode_utils.py,sha256=NOiZ_5hD72A6w-4wVj8awHFM3n51Kmw1Ic_vx15XFqw,996 +setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 +setuptools/wheel.py,sha256=A8hKSqHWZ5KM0-VP_DtptxpMxVF9pQwjWZcHGklxq2o,8102 +setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/WHEEL b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/WHEEL new file mode 100644 index 0000000..dea0e20 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt new file mode 100644 index 0000000..e87d021 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/dependency_links.txt @@ -0,0 +1,2 @@ +https://files.pythonhosted.org/packages/source/c/certifi/certifi-2016.9.26.tar.gz#md5=baa81e951a29958563689d868ef1064d +https://files.pythonhosted.org/packages/source/w/wincertstore/wincertstore-0.2.zip#md5=ae728f2f007185648d0c7a8679b361e2 diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/entry_points.txt b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/entry_points.txt new file mode 100644 index 0000000..4159fd0 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/entry_points.txt @@ -0,0 +1,65 @@ +[console_scripts] +easy_install = setuptools.command.easy_install:main +easy_install-3.6 = setuptools.command.easy_install:main + +[distutils.commands] +alias = setuptools.command.alias:alias +bdist_egg = setuptools.command.bdist_egg:bdist_egg +bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm +bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst +build_clib = setuptools.command.build_clib:build_clib +build_ext = setuptools.command.build_ext:build_ext +build_py = setuptools.command.build_py:build_py +develop = setuptools.command.develop:develop +dist_info = setuptools.command.dist_info:dist_info +easy_install = setuptools.command.easy_install:easy_install +egg_info = setuptools.command.egg_info:egg_info +install = setuptools.command.install:install +install_egg_info = setuptools.command.install_egg_info:install_egg_info +install_lib = setuptools.command.install_lib:install_lib +install_scripts = setuptools.command.install_scripts:install_scripts +register = setuptools.command.register:register +rotate = setuptools.command.rotate:rotate +saveopts = setuptools.command.saveopts:saveopts +sdist = setuptools.command.sdist:sdist +setopt = setuptools.command.setopt:setopt +test = setuptools.command.test:test +upload = setuptools.command.upload:upload +upload_docs = setuptools.command.upload_docs:upload_docs + +[distutils.setup_keywords] +convert_2to3_doctests = setuptools.dist:assert_string_list +dependency_links = setuptools.dist:assert_string_list +eager_resources = setuptools.dist:assert_string_list +entry_points = setuptools.dist:check_entry_points +exclude_package_data = setuptools.dist:check_package_data +extras_require = setuptools.dist:check_extras +include_package_data = setuptools.dist:assert_bool +install_requires = setuptools.dist:check_requirements +namespace_packages = setuptools.dist:check_nsp +package_data = setuptools.dist:check_package_data +packages = setuptools.dist:check_packages +python_requires = setuptools.dist:check_specifier +setup_requires = setuptools.dist:check_requirements +test_loader = setuptools.dist:check_importable +test_runner = setuptools.dist:check_importable +test_suite = setuptools.dist:check_test_suite +tests_require = setuptools.dist:check_requirements +use_2to3 = setuptools.dist:assert_bool +use_2to3_exclude_fixers = setuptools.dist:assert_string_list +use_2to3_fixers = setuptools.dist:assert_string_list +zip_safe = setuptools.dist:assert_bool + +[egg_info.writers] +PKG-INFO = setuptools.command.egg_info:write_pkg_info +dependency_links.txt = setuptools.command.egg_info:overwrite_arg +depends.txt = setuptools.command.egg_info:warn_depends_obsolete +eager_resources.txt = setuptools.command.egg_info:overwrite_arg +entry_points.txt = setuptools.command.egg_info:write_entries +namespace_packages.txt = setuptools.command.egg_info:overwrite_arg +requires.txt = setuptools.command.egg_info:write_requirements +top_level.txt = setuptools.command.egg_info:write_toplevel_names + +[setuptools.installation] +eggsecutable = setuptools.command.easy_install:bootstrap + diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/top_level.txt b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/top_level.txt new file mode 100644 index 0000000..4577c6a --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/top_level.txt @@ -0,0 +1,3 @@ +easy_install +pkg_resources +setuptools diff --git a/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/zip-safe b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools-40.6.2.dist-info/zip-safe @@ -0,0 +1 @@ + diff --git a/winvenv/Lib/site-packages/setuptools/__init__.py b/winvenv/Lib/site-packages/setuptools/__init__.py new file mode 100644 index 0000000..e438036 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/__init__.py @@ -0,0 +1,195 @@ +"""Extensions to the 'distutils' for large or complex distributions""" + +import os +import sys +import functools +import distutils.core +import distutils.filelist +from distutils.util import convert_path +from fnmatch import fnmatchcase + +from ._deprecation_warning import SetuptoolsDeprecationWarning + +from setuptools.extern.six import PY3 +from setuptools.extern.six.moves import filter, map + +import setuptools.version +from setuptools.extension import Extension +from setuptools.dist import Distribution, Feature +from setuptools.depends import Require +from . import monkey + +__metaclass__ = type + + +__all__ = [ + 'setup', 'Distribution', 'Feature', 'Command', 'Extension', 'Require', + 'SetuptoolsDeprecationWarning', + 'find_packages' +] + +if PY3: + __all__.append('find_namespace_packages') + +__version__ = setuptools.version.__version__ + +bootstrap_install_from = None + +# If we run 2to3 on .py files, should we also convert docstrings? +# Default: yes; assume that we can detect doctests reliably +run_2to3_on_doctests = True +# Standard package names for fixer packages +lib2to3_fixer_packages = ['lib2to3.fixes'] + + +class PackageFinder: + """ + Generate a list of all Python packages found within a directory + """ + + @classmethod + def find(cls, where='.', exclude=(), include=('*',)): + """Return a list all Python packages found within directory 'where' + + 'where' is the root directory which will be searched for packages. It + should be supplied as a "cross-platform" (i.e. URL-style) path; it will + be converted to the appropriate local path syntax. + + 'exclude' is a sequence of package names to exclude; '*' can be used + as a wildcard in the names, such that 'foo.*' will exclude all + subpackages of 'foo' (but not 'foo' itself). + + 'include' is a sequence of package names to include. If it's + specified, only the named packages will be included. If it's not + specified, all found packages will be included. 'include' can contain + shell style wildcard patterns just like 'exclude'. + """ + + return list(cls._find_packages_iter( + convert_path(where), + cls._build_filter('ez_setup', '*__pycache__', *exclude), + cls._build_filter(*include))) + + @classmethod + def _find_packages_iter(cls, where, exclude, include): + """ + All the packages found in 'where' that pass the 'include' filter, but + not the 'exclude' filter. + """ + for root, dirs, files in os.walk(where, followlinks=True): + # Copy dirs to iterate over it, then empty dirs. + all_dirs = dirs[:] + dirs[:] = [] + + for dir in all_dirs: + full_path = os.path.join(root, dir) + rel_path = os.path.relpath(full_path, where) + package = rel_path.replace(os.path.sep, '.') + + # Skip directory trees that are not valid packages + if ('.' in dir or not cls._looks_like_package(full_path)): + continue + + # Should this package be included? + if include(package) and not exclude(package): + yield package + + # Keep searching subdirectories, as there may be more packages + # down there, even if the parent was excluded. + dirs.append(dir) + + @staticmethod + def _looks_like_package(path): + """Does a directory look like a package?""" + return os.path.isfile(os.path.join(path, '__init__.py')) + + @staticmethod + def _build_filter(*patterns): + """ + Given a list of patterns, return a callable that will be true only if + the input matches at least one of the patterns. + """ + return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) + + +class PEP420PackageFinder(PackageFinder): + @staticmethod + def _looks_like_package(path): + return True + + +find_packages = PackageFinder.find + +if PY3: + find_namespace_packages = PEP420PackageFinder.find + + +def _install_setup_requires(attrs): + # Note: do not use `setuptools.Distribution` directly, as + # our PEP 517 backend patch `distutils.core.Distribution`. + dist = distutils.core.Distribution(dict( + (k, v) for k, v in attrs.items() + if k in ('dependency_links', 'setup_requires') + )) + # Honor setup.cfg's options. + dist.parse_config_files(ignore_option_errors=True) + if dist.setup_requires: + dist.fetch_build_eggs(dist.setup_requires) + + +def setup(**attrs): + # Make sure we have any requirements needed to interpret 'attrs'. + _install_setup_requires(attrs) + return distutils.core.setup(**attrs) + +setup.__doc__ = distutils.core.setup.__doc__ + + +_Command = monkey.get_unpatched(distutils.core.Command) + + +class Command(_Command): + __doc__ = _Command.__doc__ + + command_consumes_arguments = False + + def __init__(self, dist, **kw): + """ + Construct the command for dist, updating + vars(self) with any keyword parameters. + """ + _Command.__init__(self, dist) + vars(self).update(kw) + + def reinitialize_command(self, command, reinit_subcommands=0, **kw): + cmd = _Command.reinitialize_command(self, command, reinit_subcommands) + vars(cmd).update(kw) + return cmd + + +def _find_all_simple(path): + """ + Find all files under 'path' + """ + results = ( + os.path.join(base, file) + for base, dirs, files in os.walk(path, followlinks=True) + for file in files + ) + return filter(os.path.isfile, results) + + +def findall(dir=os.curdir): + """ + Find all files under 'dir' and return the list of full filenames. + Unless dir is '.', return full filenames with dir prepended. + """ + files = _find_all_simple(dir) + if dir == os.curdir: + make_rel = functools.partial(os.path.relpath, start=dir) + files = map(make_rel, files) + return list(files) + + +# Apply monkey patches +monkey.patch_all() diff --git a/winvenv/Lib/site-packages/setuptools/_deprecation_warning.py b/winvenv/Lib/site-packages/setuptools/_deprecation_warning.py new file mode 100644 index 0000000..086b64d --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_deprecation_warning.py @@ -0,0 +1,7 @@ +class SetuptoolsDeprecationWarning(Warning): + """ + Base class for warning deprecations in ``setuptools`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/__init__.py b/winvenv/Lib/site-packages/setuptools/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py new file mode 100644 index 0000000..95d330e --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py @@ -0,0 +1,21 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "16.8" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD or Apache License, Version 2.0" +__copyright__ = "Copyright 2014-2016 %s" % __author__ diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py new file mode 100644 index 0000000..5ee6220 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +from .__about__ import ( + __author__, __copyright__, __email__, __license__, __summary__, __title__, + __uri__, __version__ +) + +__all__ = [ + "__title__", "__summary__", "__uri__", "__version__", "__author__", + "__email__", "__license__", "__copyright__", +] diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/_compat.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/_compat.py new file mode 100644 index 0000000..210bb80 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/_compat.py @@ -0,0 +1,30 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import sys + + +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 + +# flake8: noqa + +if PY3: + string_types = str, +else: + string_types = basestring, + + +def with_metaclass(meta, *bases): + """ + Create a base class with a metaclass. + """ + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py new file mode 100644 index 0000000..ccc2786 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py @@ -0,0 +1,68 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + + +class Infinity(object): + + def __repr__(self): + return "Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return False + + def __le__(self, other): + return False + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return True + + def __ge__(self, other): + return True + + def __neg__(self): + return NegativeInfinity + +Infinity = Infinity() + + +class NegativeInfinity(object): + + def __repr__(self): + return "-Infinity" + + def __hash__(self): + return hash(repr(self)) + + def __lt__(self, other): + return True + + def __le__(self, other): + return True + + def __eq__(self, other): + return isinstance(other, self.__class__) + + def __ne__(self, other): + return not isinstance(other, self.__class__) + + def __gt__(self, other): + return False + + def __ge__(self, other): + return False + + def __neg__(self): + return Infinity + +NegativeInfinity = NegativeInfinity() diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/markers.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/markers.py new file mode 100644 index 0000000..031332a --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/markers.py @@ -0,0 +1,301 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import operator +import os +import platform +import sys + +from setuptools.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd +from setuptools.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString +from setuptools.extern.pyparsing import Literal as L # noqa + +from ._compat import string_types +from .specifiers import Specifier, InvalidSpecifier + + +__all__ = [ + "InvalidMarker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", +] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node(object): + + def __init__(self, value): + self.value = value + + def __str__(self): + return str(self.value) + + def __repr__(self): + return "<{0}({1!r})>".format(self.__class__.__name__, str(self)) + + def serialize(self): + raise NotImplementedError + + +class Variable(Node): + + def serialize(self): + return str(self) + + +class Value(Node): + + def serialize(self): + return '"{0}"'.format(self) + + +class Op(Node): + + def serialize(self): + return str(self) + + +VARIABLE = ( + L("implementation_version") | + L("platform_python_implementation") | + L("implementation_name") | + L("python_full_version") | + L("platform_release") | + L("platform_version") | + L("platform_machine") | + L("platform_system") | + L("python_version") | + L("sys_platform") | + L("os_name") | + L("os.name") | # PEP-345 + L("sys.platform") | # PEP-345 + L("platform.version") | # PEP-345 + L("platform.machine") | # PEP-345 + L("platform.python_implementation") | # PEP-345 + L("python_implementation") | # undocumented setuptools legacy + L("extra") +) +ALIASES = { + 'os.name': 'os_name', + 'sys.platform': 'sys_platform', + 'platform.version': 'platform_version', + 'platform.machine': 'platform_machine', + 'platform.python_implementation': 'platform_python_implementation', + 'python_implementation': 'platform_python_implementation' +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | + L("==") | + L(">=") | + L("<=") | + L("!=") | + L("~=") | + L(">") | + L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results): + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker(marker, first=True): + assert isinstance(marker, (list, tuple, string_types)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if (isinstance(marker, list) and len(marker) == 1 and + isinstance(marker[0], (list, tuple))): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs, op, rhs): + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison( + "Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs) + ) + + return oper(lhs, rhs) + + +_undefined = object() + + +def _get_env(environment, name): + value = environment.get(name, _undefined) + + if value is _undefined: + raise UndefinedEnvironmentName( + "{0!r} does not exist in evaluation environment.".format(name) + ) + + return value + + +def _evaluate_markers(markers, environment): + groups = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, string_types)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info): + version = '{0.major}.{0.minor}.{0.micro}'.format(info) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + +def default_environment(): + if hasattr(sys, 'implementation'): + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + iver = '0' + implementation_name = '' + + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": platform.python_version()[:3], + "sys_platform": sys.platform, + } + + +class Marker(object): + + def __init__(self, marker): + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + err_str = "Invalid marker: {0!r}, parse error at {1!r}".format( + marker, marker[e.loc:e.loc + 8]) + raise InvalidMarker(err_str) + + def __str__(self): + return _format_marker(self._markers) + + def __repr__(self): + return "<Marker({0!r})>".format(str(self)) + + def evaluate(self, environment=None): + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py new file mode 100644 index 0000000..5b49341 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py @@ -0,0 +1,127 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import string +import re + +from setuptools.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException +from setuptools.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine +from setuptools.extern.pyparsing import Literal as L # noqa +from setuptools.extern.six.moves.urllib import parse as urlparse + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r'[^ ]+')("url") +URL = (AT + URI) + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine(VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), + joinString=",", adjacent=False)("_raw_spec") +_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '') + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start:t._original_end]) +) +MARKER_SEPERATOR = SEMICOLON +MARKER = MARKER_SEPERATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = \ + NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd + + +class Requirement(object): + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string): + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + "Invalid requirement, parse error at \"{0!r}\"".format( + requirement_string[e.loc:e.loc + 8])) + + self.name = req.name + if req.url: + parsed_url = urlparse.urlparse(req.url) + if not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc): + raise InvalidRequirement("Invalid URL given") + self.url = req.url + else: + self.url = None + self.extras = set(req.extras.asList() if req.extras else []) + self.specifier = SpecifierSet(req.specifier) + self.marker = req.marker if req.marker else None + + def __str__(self): + parts = [self.name] + + if self.extras: + parts.append("[{0}]".format(",".join(sorted(self.extras)))) + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append("@ {0}".format(self.url)) + + if self.marker: + parts.append("; {0}".format(self.marker)) + + return "".join(parts) + + def __repr__(self): + return "<Requirement({0!r})>".format(str(self)) diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..7f5a76c --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py @@ -0,0 +1,774 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import abc +import functools +import itertools +import re + +from ._compat import string_types, with_metaclass +from .version import Version, LegacyVersion, parse + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): + + @abc.abstractmethod + def __str__(self): + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self): + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractmethod + def __ne__(self, other): + """ + Returns a boolean representing whether or not the two Specifier like + objects are not equal. + """ + + @abc.abstractproperty + def prereleases(self): + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value): + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item, prereleases=None): + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter(self, iterable, prereleases=None): + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators = {} + + def __init__(self, spec="", prereleases=None): + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) + + self._spec = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<{0}({1!r}{2})>".format( + self.__class__.__name__, + str(self), + pre, + ) + + def __str__(self): + return "{0}{1}".format(*self._spec) + + def __hash__(self): + return hash(self._spec) + + def __eq__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec == other._spec + + def __ne__(self, other): + if isinstance(other, string_types): + try: + other = self.__class__(other) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._spec != other._spec + + def _get_operator(self, op): + return getattr(self, "_compare_{0}".format(self._operators[op])) + + def _coerce_version(self, version): + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self): + return self._spec[0] + + @property + def version(self): + return self._spec[1] + + @property + def prereleases(self): + return self._prereleases + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + return self._get_operator(self.operator)(item, self.version) + + def filter(self, iterable, prereleases=None): + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later incase nothing + # else matches this specifier. + if (parsed_version.is_prerelease and not + (prereleases or self.prereleases)): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the begining. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(==|!=|<=|>=|<|>)) + \s* + (?P<version> + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def _coerce_version(self, version): + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective, spec): + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective, spec): + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective, spec): + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective, spec): + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective, spec): + return prospective > self._coerce_version(spec) + + +def _require_version_compare(fn): + @functools.wraps(fn) + def wrapped(self, prospective, spec): + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = ( + r""" + (?P<operator>(~=|==|!=|<=|>=|<|>|===)) + (?P<version> + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?<!==|!=|~=) # We have special cases for these + # operators so we want to make sure they + # don't match here. + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + ) + """ + ) + + _regex = re.compile( + r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "~=": "compatible", + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective, spec): + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore post and dev releases and we want to treat the pre-release as + # it's own separate segment. + prefix = ".".join( + list( + itertools.takewhile( + lambda x: (not x.startswith("post") and not + x.startswith("dev")), + _version_split(spec), + ) + )[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return (self._get_operator(">=")(prospective, spec) and + self._get_operator("==")(prospective, prefix)) + + @_require_version_compare + def _compare_equal(self, prospective, spec): + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + prospective = prospective[:len(spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + spec, prospective = _pad_version(spec, prospective) + else: + # Convert our spec string into a Version + spec = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec.local: + prospective = Version(prospective.public) + + return prospective == spec + + @_require_version_compare + def _compare_not_equal(self, prospective, spec): + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective, spec): + return prospective <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal(self, prospective, spec): + return prospective >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective, spec): + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is techincally greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective, spec): + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self): + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version): + result = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _pad_version(left, right): + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]):]) + right_split.append(right[len(right_split[0]):]) + + # Insert our padding + left_split.insert( + 1, + ["0"] * max(0, len(right_split[0]) - len(left_split[0])), + ) + right_split.insert( + 1, + ["0"] * max(0, len(left_split[0]) - len(right_split[0])), + ) + + return ( + list(itertools.chain(*left_split)), + list(itertools.chain(*right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + + def __init__(self, specifiers="", prereleases=None): + # Split on , to break each indidivual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed = set() + for specifier in specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self): + pre = ( + ", prereleases={0!r}".format(self.prereleases) + if self._prereleases is not None + else "" + ) + + return "<SpecifierSet({0!r}{1})>".format(str(self), pre) + + def __str__(self): + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self): + return hash(self._specs) + + def __and__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __ne__(self, other): + if isinstance(other, string_types): + other = SpecifierSet(other) + elif isinstance(other, _IndividualSpecifier): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs != other._specs + + def __len__(self): + return len(self._specs) + + def __iter__(self): + return iter(self._specs) + + @property + def prereleases(self): + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value): + self._prereleases = value + + def __contains__(self, item): + return self.contains(item) + + def contains(self, item, prereleases=None): + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all( + s.contains(item, prereleases=prereleases) + for s in self._specs + ) + + def filter(self, iterable, prereleases=None): + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered = [] + found_prereleases = [] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/utils.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/utils.py new file mode 100644 index 0000000..942387c --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/utils.py @@ -0,0 +1,14 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import re + + +_canonicalize_regex = re.compile(r"[-_.]+") + + +def canonicalize_name(name): + # This is taken from PEP 503. + return _canonicalize_regex.sub("-", name).lower() diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/packaging/version.py b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/version.py new file mode 100644 index 0000000..83b5ee8 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/packaging/version.py @@ -0,0 +1,393 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import absolute_import, division, print_function + +import collections +import itertools +import re + +from ._structures import Infinity + + +__all__ = [ + "parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN" +] + + +_Version = collections.namedtuple( + "_Version", + ["epoch", "release", "dev", "pre", "post", "local"], +) + + +def parse(version): + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion(object): + + def __hash__(self): + return hash(self._key) + + def __lt__(self, other): + return self._compare(other, lambda s, o: s < o) + + def __le__(self, other): + return self._compare(other, lambda s, o: s <= o) + + def __eq__(self, other): + return self._compare(other, lambda s, o: s == o) + + def __ge__(self, other): + return self._compare(other, lambda s, o: s >= o) + + def __gt__(self, other): + return self._compare(other, lambda s, o: s > o) + + def __ne__(self, other): + return self._compare(other, lambda s, o: s != o) + + def _compare(self, other, method): + if not isinstance(other, _BaseVersion): + return NotImplemented + + return method(self._key, other._key) + + +class LegacyVersion(_BaseVersion): + + def __init__(self, version): + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + def __str__(self): + return self._version + + def __repr__(self): + return "<LegacyVersion({0})>".format(repr(str(self))) + + @property + def public(self): + return self._version + + @property + def base_version(self): + return self._version + + @property + def local(self): + return None + + @property + def is_prerelease(self): + return False + + @property + def is_postrelease(self): + return False + + +_legacy_version_component_re = re.compile( + r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE, +) + +_legacy_version_replacement_map = { + "pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@", +} + + +def _parse_version_parts(s): + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version): + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + parts = tuple(parts) + + return epoch, parts + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P<epoch>[0-9]+)!)? # epoch + (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment + (?P<pre> # pre-release + [-_\.]? + (?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview)) + [-_\.]? + (?P<pre_n>[0-9]+)? + )? + (?P<post> # post release + (?:-(?P<post_n1>[0-9]+)) + | + (?: + [-_\.]? + (?P<post_l>post|rev|r) + [-_\.]? + (?P<post_n2>[0-9]+)? + ) + )? + (?P<dev> # dev release + [-_\.]? + (?P<dev_l>dev) + [-_\.]? + (?P<dev_n>[0-9]+)? + )? + ) + (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version +""" + + +class Version(_BaseVersion): + + _regex = re.compile( + r"^\s*" + VERSION_PATTERN + r"\s*$", + re.VERBOSE | re.IGNORECASE, + ) + + def __init__(self, version): + # Validate the version and parse it into pieces + match = self._regex.search(version) + if not match: + raise InvalidVersion("Invalid version: '{0}'".format(version)) + + # Store the parsed out pieces of the version + self._version = _Version( + epoch=int(match.group("epoch")) if match.group("epoch") else 0, + release=tuple(int(i) for i in match.group("release").split(".")), + pre=_parse_letter_version( + match.group("pre_l"), + match.group("pre_n"), + ), + post=_parse_letter_version( + match.group("post_l"), + match.group("post_n1") or match.group("post_n2"), + ), + dev=_parse_letter_version( + match.group("dev_l"), + match.group("dev_n"), + ), + local=_parse_local_version(match.group("local")), + ) + + # Generate a key which will be used for sorting + self._key = _cmpkey( + self._version.epoch, + self._version.release, + self._version.pre, + self._version.post, + self._version.dev, + self._version.local, + ) + + def __repr__(self): + return "<Version({0})>".format(repr(str(self))) + + def __str__(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + # Pre-release + if self._version.pre is not None: + parts.append("".join(str(x) for x in self._version.pre)) + + # Post-release + if self._version.post is not None: + parts.append(".post{0}".format(self._version.post[1])) + + # Development release + if self._version.dev is not None: + parts.append(".dev{0}".format(self._version.dev[1])) + + # Local version segment + if self._version.local is not None: + parts.append( + "+{0}".format(".".join(str(x) for x in self._version.local)) + ) + + return "".join(parts) + + @property + def public(self): + return str(self).split("+", 1)[0] + + @property + def base_version(self): + parts = [] + + # Epoch + if self._version.epoch != 0: + parts.append("{0}!".format(self._version.epoch)) + + # Release segment + parts.append(".".join(str(x) for x in self._version.release)) + + return "".join(parts) + + @property + def local(self): + version_string = str(self) + if "+" in version_string: + return version_string.split("+", 1)[1] + + @property + def is_prerelease(self): + return bool(self._version.dev or self._version.pre) + + @property + def is_postrelease(self): + return bool(self._version.post) + + +def _parse_letter_version(letter, number): + if letter: + # We consider there to be an implicit 0 in a pre-release if there is + # not a numeral associated with it. + if number is None: + number = 0 + + # We normalize any letters to their lower case form + letter = letter.lower() + + # We consider some words to be alternate spellings of other words and + # in those cases we want to normalize the spellings to our preferred + # spelling. + if letter == "alpha": + letter = "a" + elif letter == "beta": + letter = "b" + elif letter in ["c", "pre", "preview"]: + letter = "rc" + elif letter in ["rev", "r"]: + letter = "post" + + return letter, int(number) + if not letter and number: + # We assume if we are given a number, but we are not given a letter + # then this is using the implicit post release syntax (e.g. 1.0-1) + letter = "post" + + return letter, int(number) + + +_local_version_seperators = re.compile(r"[\._-]") + + +def _parse_local_version(local): + """ + Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve"). + """ + if local is not None: + return tuple( + part.lower() if not part.isdigit() else int(part) + for part in _local_version_seperators.split(local) + ) + + +def _cmpkey(epoch, release, pre, post, dev, local): + # When we compare a release version, we want to compare it with all of the + # trailing zeros removed. So we'll use a reverse the list, drop all the now + # leading zeros until we come to something non zero, then take the rest + # re-reverse it back into the correct order and make it a tuple and use + # that for our sorting key. + release = tuple( + reversed(list( + itertools.dropwhile( + lambda x: x == 0, + reversed(release), + ) + )) + ) + + # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0. + # We'll do this by abusing the pre segment, but we _only_ want to do this + # if there is not a pre or a post segment. If we have one of those then + # the normal sorting rules will handle this case correctly. + if pre is None and post is None and dev is not None: + pre = -Infinity + # Versions without a pre-release (except as noted above) should sort after + # those with one. + elif pre is None: + pre = Infinity + + # Versions without a post segment should sort before those with one. + if post is None: + post = -Infinity + + # Versions without a development segment should sort after those with one. + if dev is None: + dev = Infinity + + if local is None: + # Versions without a local segment should sort before those with one. + local = -Infinity + else: + # Versions with a local segment need that segment parsed to implement + # the sorting rules in PEP440. + # - Alpha numeric segments sort before numeric segments + # - Alpha numeric segments sort lexicographically + # - Numeric segments sort numerically + # - Shorter versions sort before longer versions when the prefixes + # match exactly + local = tuple( + (i, "") if isinstance(i, int) else (-Infinity, i) + for i in local + ) + + return epoch, release, pre, post, dev, local diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/pyparsing.py b/winvenv/Lib/site-packages/setuptools/_vendor/pyparsing.py new file mode 100644 index 0000000..4aa30ee --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/pyparsing.py @@ -0,0 +1,5742 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2018 Paul T. McGuire +# +# 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. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{"<salutation>, <addressee>!"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'<ParserElement.__add__>} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString<ParserElement.parseString>} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes + - construct character word-group expressions using the L{Word} class + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes + - use L{'+'<And>}, L{'|'<MatchFirst>}, L{'^'<Or>}, and L{'&'<Each>} operators to combine simple expressions into more complex ones + - associate names with your parsed results using L{ParserElement.setResultsName} + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf} + - find more useful common expressions in the L{pyparsing_common} namespace class +""" + +__version__ = "2.2.1" +__versionTime__ = "18 Sep 2018 00:49 UTC" +__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + # Python 3 + from collections.abc import Iterable + from collections.abc import MutableMapping +except ImportError: + # Python 2.7 + from collections import Iterable + from collections import MutableMapping + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop<And._ErrorStop>} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.<resultsName>} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "</", resTag, ">" ] + + out += [ nl, indent, "</", selfTag, ">" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0<loc<len(s) and s[loc-1] == '\n' else loc - s.rfind("\n", 0, loc) + +def lineno(loc,strg): + """Returns current line number within a string, counting newlines as line separators. + The first line is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}<ParserElement.parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [frame_summary[:2]] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [frame_summary[:2]] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "<parse action>" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, <TAB> and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}<parseString>} for more information + on parsing strings containing C{<TAB>}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}<setParseAction>}. + + See examples in L{I{copy}<copy>}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}<setParseAction>} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or preloc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}<parseWithTabs>}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}<parseString>} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of <TAB>s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{<TAB>}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{<TAB>} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match <exprname> at loc <n>(<line>,<col>)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc<instrlen and instring[loc] in bodychars): + throwException = True + + if throwException: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except Exception: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P<name>...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "<SPC>", + "\t": "<TAB>", + "\n": "<LF>", + "\r": "<CR>", + "\f": "<FF>", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc<len(instring): + if instring[loc] == "\n": + return loc+1, "\n" + else: + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class StringStart(_PositionToken): + """ + Matches if current position is at the beginning of the parse string + """ + def __init__( self ): + super(StringStart,self).__init__() + self.errmsg = "Expected start of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc != 0: + # see if entire string up to here is just whitespace and ignoreables + if loc != self.preParse( instring, 0 ): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class StringEnd(_PositionToken): + """ + Matches if current position is at the end of the parse string + """ + def __init__( self ): + super(StringEnd,self).__init__() + self.errmsg = "Expected end of text" + + def parseImpl( self, instring, loc, doActions=True ): + if loc < len(instring): + raise ParseException(instring, loc, self.errmsg, self) + elif loc == len(instring): + return loc+1, [] + elif loc > len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc<instrlen: + if (instring[loc] in self.wordChars or + instring[loc-1] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + +class ParseExpression(ParserElement): + """ + Abstract subclass of ParserElement, for combining and post-processing parsed tokens. + """ + def __init__( self, exprs, savelist = False ): + super(ParseExpression,self).__init__(savelist) + if isinstance( exprs, _generatorType ): + exprs = list(exprs) + + if isinstance( exprs, basestring ): + self.exprs = [ ParserElement._literalStringClass( exprs ) ] + elif isinstance( exprs, Iterable ): + exprs = list(exprs) + # if sequence of strings provided, wrap with Literal + if all(isinstance(expr, basestring) for expr in exprs): + exprs = map(ParserElement._literalStringClass, exprs) + self.exprs = list(exprs) + else: + try: + self.exprs = list( exprs ) + except TypeError: + self.exprs = [ exprs ] + self.callPreparse = False + + def __getitem__( self, i ): + return self.exprs[i] + + def append( self, other ): + self.exprs.append( other ) + self.strRepr = None + return self + + def leaveWhitespace( self ): + """Extends C{leaveWhitespace} defined in base class, and also invokes C{leaveWhitespace} on + all contained expressions.""" + self.skipWhitespace = False + self.exprs = [ e.copy() for e in self.exprs ] + for e in self.exprs: + e.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + else: + super( ParseExpression, self).ignore( other ) + for e in self.exprs: + e.ignore( self.ignoreExprs[-1] ) + return self + + def __str__( self ): + try: + return super(ParseExpression,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) ) + return self.strRepr + + def streamline( self ): + super(ParseExpression,self).streamline() + + for e in self.exprs: + e.streamline() + + # collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d ) + # but only if there are no parse actions or resultsNames on the nested And's + # (likewise for Or's and MatchFirst's) + if ( len(self.exprs) == 2 ): + other = self.exprs[0] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = other.exprs[:] + [ self.exprs[1] ] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + other = self.exprs[-1] + if ( isinstance( other, self.__class__ ) and + not(other.parseAction) and + other.resultsName is None and + not other.debug ): + self.exprs = self.exprs[:-1] + other.exprs[:] + self.strRepr = None + self.mayReturnEmpty |= other.mayReturnEmpty + self.mayIndexError |= other.mayIndexError + + self.errmsg = "Expected " + _ustr(self) + + return self + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ParseExpression,self).setResultsName(name,listAllMatches) + return ret + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + for e in self.exprs: + e.validate(tmp) + self.checkRecursion( [] ) + + def copy(self): + ret = super(ParseExpression,self).copy() + ret.exprs = [e.copy() for e in self.exprs] + return ret + +class And(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found in the given order. + Expressions may be separated by whitespace. + May be constructed using the C{'+'} operator. + May also be constructed using the C{'-'} operator, which will suppress backtracking. + + Example:: + integer = Word(nums) + name_expr = OneOrMore(Word(alphas)) + + expr = And([integer("id"),name_expr("name"),integer("age")]) + # more easily written as: + expr = integer("id") + name_expr("name") + integer("age") + """ + + class _ErrorStop(Empty): + def __init__(self, *args, **kwargs): + super(And._ErrorStop,self).__init__(*args, **kwargs) + self.name = '-' + self.leaveWhitespace() + + def __init__( self, exprs, savelist = True ): + super(And,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.setWhitespaceChars( self.exprs[0].whiteChars ) + self.skipWhitespace = self.exprs[0].skipWhitespace + self.callPreparse = True + + def parseImpl( self, instring, loc, doActions=True ): + # pass False as last arg to _parse for first element, since we already + # pre-parsed the string as part of our And pre-parsing + loc, resultlist = self.exprs[0]._parse( instring, loc, doActions, callPreParse=False ) + errorStop = False + for e in self.exprs[1:]: + if isinstance(e, And._ErrorStop): + errorStop = True + continue + if errorStop: + try: + loc, exprtokens = e._parse( instring, loc, doActions ) + except ParseSyntaxException: + raise + except ParseBaseException as pe: + pe.__traceback__ = None + raise ParseSyntaxException._from_exception(pe) + except IndexError: + raise ParseSyntaxException(instring, len(instring), self.errmsg, self) + else: + loc, exprtokens = e._parse( instring, loc, doActions ) + if exprtokens or exprtokens.haskeys(): + resultlist += exprtokens + return loc, resultlist + + def __iadd__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #And( [ self, other ] ) + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + if not e.mayReturnEmpty: + break + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + +class Or(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the expression that matches the longest string will be used. + May be constructed using the C{'^'} operator. + + Example:: + # construct Or using '^' operator + + number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) + prints:: + [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(Or,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + matches = [] + for e in self.exprs: + try: + loc2 = e.tryParse( instring, loc ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens)))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <<leaving remove_duplicate_chars (ret: 'dfjkls') + ['dfjkls'] + """ + f = _trim_arity(f) + def z(*paArgs): + thisFunc = f.__name__ + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) ) + raise + sys.stderr.write( "<<leaving %s (ret: %r)\n" % (thisFunc,ret) ) + return ret + try: + z.__name__ = f.__name__ + except AttributeError: + pass + return z + +# +# global helpers +# +def delimitedList( expr, delim=",", combine=False ): + """ + Helper to define a delimited list of expressions - the delimiter defaults to ','. + By default, the list elements and delimiters can have intervening whitespace, and + comments, but this can be overridden by passing C{combine=True} in the constructor. + If C{combine} is set to C{True}, the matching tokens are returned as a single token + string, with the delimiters included; otherwise, the matching tokens are returned + as a list of tokens, with the delimiters suppressed. + + Example:: + delimitedList(Word(alphas)).parseString("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test <b> bold <i>text</i> </b> normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + ['<b> bold <i>text</i> </b>'] + ['<i>text</i>'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{<TAB>} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString<ParserElement.transformString>}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("</") + tagStr + ">") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("</%s>" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the <A> tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{<TD>} or C{<DIV>}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' + <div> + Some text + <div type="grid">1 4 0 1 0</div> + <div type="graph">1,3 2,3 1,1</div> + <div>this has no type</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' + <div> + Some text + <div class="grid">1 4 0 1 0</div> + <div class="graph">1,3 2,3 1,1</div> + <div>this <div> has no class</div> + </div> + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P<entity>' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"<!--[\s\S]*?-->").setName("HTML comment") +"Comment of the form C{<!-- ... -->}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers<integer>}, L{reals<real>}, L{scientific notation<sci_real>}) + - common L{programming identifiers<identifier>} + - network addresses (L{MAC<mac_address>}, L{IPv4<ipv4_address>}, L{IPv6<ipv6_address>}) + - ISO8601 L{dates<iso8601_date>} and L{datetime<iso8601_datetime>} + - L{UUID<uuid>} + - L{comma-separated list<comma_separated_list>} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P<year>\d{4})(?:-(?P<month>\d\d)(?:-(?P<day>\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P<year>\d{4})-(?P<month>\d\d)-(?P<day>\d\d)[T ](?P<hour>\d\d):(?P<minute>\d\d)(:(?P<second>\d\d(\.\d*)?)?)?(?P<tz>Z|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = '<td>More info at the <a href="http://pyparsing.wikispaces.com">pyparsing</a> wiki page</td>' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/winvenv/Lib/site-packages/setuptools/_vendor/six.py b/winvenv/Lib/site-packages/setuptools/_vendor/six.py new file mode 100644 index 0000000..190c023 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/_vendor/six.py @@ -0,0 +1,868 @@ +"""Utilities for writing code that runs on Python 2 and 3""" + +# Copyright (c) 2010-2015 Benjamin Peterson +# +# 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. + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson <benjamin@python.org>" +__version__ = "1.10.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + raise tp, value, tb +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + if from_value is None: + raise value + raise value from from_value +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + raise value from from_value +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/winvenv/Lib/site-packages/setuptools/archive_util.py b/winvenv/Lib/site-packages/setuptools/archive_util.py new file mode 100644 index 0000000..8143604 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/archive_util.py @@ -0,0 +1,173 @@ +"""Utilities for extracting common archive formats""" + +import zipfile +import tarfile +import os +import shutil +import posixpath +import contextlib +from distutils.errors import DistutilsError + +from pkg_resources import ensure_directory + +__all__ = [ + "unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter", + "UnrecognizedFormat", "extraction_drivers", "unpack_directory", +] + + +class UnrecognizedFormat(DistutilsError): + """Couldn't recognize the archive type""" + + +def default_filter(src, dst): + """The default progress/filter callback; returns True for all files""" + return dst + + +def unpack_archive(filename, extract_dir, progress_filter=default_filter, + drivers=None): + """Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat`` + + `progress_filter` is a function taking two arguments: a source path + internal to the archive ('/'-separated), and a filesystem path where it + will be extracted. The callback must return the desired extract path + (which may be the same as the one passed in), or else ``None`` to skip + that file or directory. The callback can thus be used to report on the + progress of the extraction, as well as to filter the items extracted or + alter their extraction paths. + + `drivers`, if supplied, must be a non-empty sequence of functions with the + same signature as this function (minus the `drivers` argument), that raise + ``UnrecognizedFormat`` if they do not support extracting the designated + archive type. The `drivers` are tried in sequence until one is found that + does not raise an error, or until all are exhausted (in which case + ``UnrecognizedFormat`` is raised). If you do not supply a sequence of + drivers, the module's ``extraction_drivers`` constant will be used, which + means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that + order. + """ + for driver in drivers or extraction_drivers: + try: + driver(filename, extract_dir, progress_filter) + except UnrecognizedFormat: + continue + else: + return + else: + raise UnrecognizedFormat( + "Not a recognized archive type: %s" % filename + ) + + +def unpack_directory(filename, extract_dir, progress_filter=default_filter): + """"Unpack" a directory, using the same interface as for archives + + Raises ``UnrecognizedFormat`` if `filename` is not a directory + """ + if not os.path.isdir(filename): + raise UnrecognizedFormat("%s is not a directory" % filename) + + paths = { + filename: ('', extract_dir), + } + for base, dirs, files in os.walk(filename): + src, dst = paths[base] + for d in dirs: + paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d) + for f in files: + target = os.path.join(dst, f) + target = progress_filter(src + f, target) + if not target: + # skip non-files + continue + ensure_directory(target) + f = os.path.join(base, f) + shutil.copyfile(f, target) + shutil.copystat(f, target) + + +def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): + """Unpack zip `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined + by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + + if not zipfile.is_zipfile(filename): + raise UnrecognizedFormat("%s is not a zip file" % (filename,)) + + with zipfile.ZipFile(filename) as z: + for info in z.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name.split('/'): + continue + + target = os.path.join(extract_dir, *name.split('/')) + target = progress_filter(name, target) + if not target: + continue + if name.endswith('/'): + # directory + ensure_directory(target) + else: + # file + ensure_directory(target) + data = z.read(info.filename) + with open(target, 'wb') as f: + f.write(data) + unix_attributes = info.external_attr >> 16 + if unix_attributes: + os.chmod(target, unix_attributes) + + +def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined + by ``tarfile.open()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise UnrecognizedFormat( + "%s is not a compressed or uncompressed tar file" % (filename,) + ) + with contextlib.closing(tarobj): + # don't do any chowning! + tarobj.chown = lambda *args: None + for member in tarobj: + name = member.name + # don't extract absolute paths or ones with .. in them + if not name.startswith('/') and '..' not in name.split('/'): + prelim_dst = os.path.join(extract_dir, *name.split('/')) + + # resolve any links and to extract the link targets as normal + # files + while member is not None and (member.islnk() or member.issym()): + linkpath = member.linkname + if member.issym(): + base = posixpath.dirname(member.name) + linkpath = posixpath.join(base, linkpath) + linkpath = posixpath.normpath(linkpath) + member = tarobj._getmember(linkpath) + + if member is not None and (member.isfile() or member.isdir()): + final_dst = progress_filter(name, prelim_dst) + if final_dst: + if final_dst.endswith(os.sep): + final_dst = final_dst[:-1] + try: + # XXX Ugh + tarobj._extract_member(member, final_dst) + except tarfile.ExtractError: + # chown/chmod/mkfifo/mknode/makedev failed + pass + return True + + +extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile diff --git a/winvenv/Lib/site-packages/setuptools/build_meta.py b/winvenv/Lib/site-packages/setuptools/build_meta.py new file mode 100644 index 0000000..0067a7a --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/build_meta.py @@ -0,0 +1,182 @@ +"""A PEP 517 interface to setuptools + +Previously, when a user or a command line tool (let's call it a "frontend") +needed to make a request of setuptools to take a certain action, for +example, generating a list of installation requirements, the frontend would +would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line. + +PEP 517 defines a different method of interfacing with setuptools. Rather +than calling "setup.py" directly, the frontend should: + + 1. Set the current directory to the directory with a setup.py file + 2. Import this module into a safe python interpreter (one in which + setuptools can potentially set global variables or crash hard). + 3. Call one of the functions defined in PEP 517. + +What each function does is defined in PEP 517. However, here is a "casual" +definition of the functions (this definition should not be relied on for +bug reports or API stability): + + - `build_wheel`: build a wheel in the folder and return the basename + - `get_requires_for_build_wheel`: get the `setup_requires` to build + - `prepare_metadata_for_build_wheel`: get the `install_requires` + - `build_sdist`: build an sdist in the folder and return the basename + - `get_requires_for_build_sdist`: get the `setup_requires` to build + +Again, this is not a formal definition! Just a "taste" of the module. +""" + +import os +import sys +import tokenize +import shutil +import contextlib + +import setuptools +import distutils + + +class SetupRequirementsError(BaseException): + def __init__(self, specifiers): + self.specifiers = specifiers + + +class Distribution(setuptools.dist.Distribution): + def fetch_build_eggs(self, specifiers): + raise SetupRequirementsError(specifiers) + + @classmethod + @contextlib.contextmanager + def patch(cls): + """ + Replace + distutils.dist.Distribution with this class + for the duration of this context. + """ + orig = distutils.core.Distribution + distutils.core.Distribution = cls + try: + yield + finally: + distutils.core.Distribution = orig + + +def _to_str(s): + """ + Convert a filename to a string (on Python 2, explicitly + a byte string, not Unicode) as distutils checks for the + exact type str. + """ + if sys.version_info[0] == 2 and not isinstance(s, str): + # Assume it's Unicode, as that's what the PEP says + # should be provided. + return s.encode(sys.getfilesystemencoding()) + return s + + +def _run_setup(setup_script='setup.py'): + # Note that we can reuse our build directory between calls + # Correctness comes first, then optimization later + __file__ = setup_script + __name__ = '__main__' + f = getattr(tokenize, 'open', open)(__file__) + code = f.read().replace('\\r\\n', '\\n') + f.close() + exec(compile(code, __file__, 'exec'), locals()) + + +def _fix_config(config_settings): + config_settings = config_settings or {} + config_settings.setdefault('--global-option', []) + return config_settings + + +def _get_build_requires(config_settings, requirements): + config_settings = _fix_config(config_settings) + + sys.argv = sys.argv[:1] + ['egg_info'] + \ + config_settings["--global-option"] + try: + with Distribution.patch(): + _run_setup() + except SetupRequirementsError as e: + requirements += e.specifiers + + return requirements + + +def _get_immediate_subdirectories(a_dir): + return [name for name in os.listdir(a_dir) + if os.path.isdir(os.path.join(a_dir, name))] + + +def get_requires_for_build_wheel(config_settings=None): + config_settings = _fix_config(config_settings) + return _get_build_requires(config_settings, requirements=['setuptools', 'wheel']) + + +def get_requires_for_build_sdist(config_settings=None): + config_settings = _fix_config(config_settings) + return _get_build_requires(config_settings, requirements=['setuptools']) + + +def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None): + sys.argv = sys.argv[:1] + ['dist_info', '--egg-base', _to_str(metadata_directory)] + _run_setup() + + dist_info_directory = metadata_directory + while True: + dist_infos = [f for f in os.listdir(dist_info_directory) + if f.endswith('.dist-info')] + + if len(dist_infos) == 0 and \ + len(_get_immediate_subdirectories(dist_info_directory)) == 1: + dist_info_directory = os.path.join( + dist_info_directory, os.listdir(dist_info_directory)[0]) + continue + + assert len(dist_infos) == 1 + break + + # PEP 517 requires that the .dist-info directory be placed in the + # metadata_directory. To comply, we MUST copy the directory to the root + if dist_info_directory != metadata_directory: + shutil.move( + os.path.join(dist_info_directory, dist_infos[0]), + metadata_directory) + shutil.rmtree(dist_info_directory, ignore_errors=True) + + return dist_infos[0] + + +def build_wheel(wheel_directory, config_settings=None, + metadata_directory=None): + config_settings = _fix_config(config_settings) + wheel_directory = os.path.abspath(wheel_directory) + sys.argv = sys.argv[:1] + ['bdist_wheel'] + \ + config_settings["--global-option"] + _run_setup() + if wheel_directory != 'dist': + shutil.rmtree(wheel_directory) + shutil.copytree('dist', wheel_directory) + + wheels = [f for f in os.listdir(wheel_directory) + if f.endswith('.whl')] + + assert len(wheels) == 1 + return wheels[0] + + +def build_sdist(sdist_directory, config_settings=None): + config_settings = _fix_config(config_settings) + sdist_directory = os.path.abspath(sdist_directory) + sys.argv = sys.argv[:1] + ['sdist'] + \ + config_settings["--global-option"] + \ + ["--dist-dir", sdist_directory] + _run_setup() + + sdists = [f for f in os.listdir(sdist_directory) + if f.endswith('.tar.gz')] + + assert len(sdists) == 1 + return sdists[0] diff --git a/winvenv/Lib/site-packages/setuptools/cli-32.exe b/winvenv/Lib/site-packages/setuptools/cli-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/setuptools/cli-64.exe b/winvenv/Lib/site-packages/setuptools/cli-64.exe new file mode 100644 index 0000000000000000000000000000000000000000..675e6bf3743f3d3011c238657e7128ee9960ef7f GIT binary patch literal 74752 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 &sjKl@1{;unAiW2w^OujNoW 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/setuptools/cli.exe b/winvenv/Lib/site-packages/setuptools/cli.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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[c}i<OXTz6k>I#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*G<xQC7$Bg`f~d>lC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)F<LB!IdzF`7%cck^aLb_J<@DD#CfB0B$E^bzV@-Vr`q!&`=<s^68_Wa_GZ_v^?aY zU=VZGXAzm5x{LcyVkUd8JxnNsqtS!3fw-nje@5tui@0AmI$b-*P5O7)s<z9AVj!{a zusK!aLirXkGmKBs9|=}}+<^)RB1ao<^{^>kX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~<iO|JiNP|OD zR=9Lm@@Ua+Eq87EAwAZBPGrH*)zP)xEF>B0I<PUu3WRluor4HwG59U@*GT3C4#)*> z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU<Qo&ds@10tJ4pnneT?LI)M|HS1v7YY$x9Bv-SsJ$Cl+xPAV;6Eqk-srxG9 z{LT5_#k!V#{GO}ibh%Xvw5jxHs@yzGY~@?`(yJD$GqsX;X$pypI5DT^o5eVu9#Z@z zw!tumU}_j8#vZXTB&Vb!;K(WYBw))aIfHo=I@urFFfxYS9PyXWVFQN5U;5Dw%tIz$ zw`nTQR_c;mZr;Y5QwPf3_^KR#GvcZKkFXD~jQGWdi~_bGh!>?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDU<yTk`c&RTk8mVQAOK~qMQ#2raos*zaqlvJZo>L()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#<Dz&@nl0LRIeY=p^I1%{g=J)$y zJ4tny{}tcKG0i7qLLJtU;jl;LnJu8bQak(kB&;UDjom{#=dp=&3s}YXYz3C()*?Ie zpOr>*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM<W!B9QJEa7>_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|<P zZAhQVQAqt{KX8b!o72`jV*h~V{I<6~6`|CSYi!tcFRq-OP_ri!l#8;keBk$FyRh37 zh-vx<nho1V<uSlQEH;(ry7_afSZop_PK$8boQKoq+i)shoyMOs4}aFK<j<xGJnq14 zb2)CC*WtE#b4An68qy4#ciQ16Pbjcq3r`~(syir#2qbbvYtKWddcXwdfk_9bi9C9n ze)1pT^3siP-~5MsCpR}_o2eh^LneJBm*p>KZqkLal4YCRR9VNhIM|rBqmzzcImvcx z66fD`zj4}M-A;gyA17cSC-oI$`q?*q&8~)Qv|C#(aSFd|hYbf}FFVB?n3Q?Svt+Td z#AW4x=9X}?aizE|`r{}3l-H&b6-{_j#STR!lD001vu;K>KT;*^ChCevBwCMFpg{JI zv``4YsjK1&142Pl%%A#u3rbGso1<_fngd1`+}!pMu@z5Me_5UFxiPYKqFL4_`WXmY zeWJrZUKzrrMuBcHupOq4Wr12sE*T-*CXh;FA=)Q+BMN(?DJ!kq?%Ww`xlG3e;lz2t zY?tl;i?gHO_79VwJ_cThq^>FqRUPlqS?IuI+CfSbNkv_1l~7eGaCwRmuOF|ic1ac2 z9ldo$TN~LhX~J01P75nyi&d8=Y@QNZ5e<=6v_R3rM}nN}5ae`^LV&sAD<=;*z=!~` zvJ0@i!orMuT*5kyXNzJnxfU!+#FTW(syy@yj7XX8#zD_9TWBSg(;KZ25VO;is;-&R zf(29n3U}agkC`j4sjX{=`D1EkCC@enOA~v{GOLYQKAdPN6+?W+QE4fLMhrW4RG<SI z@?qI-KY>bH5^K(rm4T}`=ra<6GP2}cRBE9K8^r(O+ZvKpJDL~qNguPmwQZp-8m7V@ zN^KFU8@Q*E7UJswZD=OYtct4KqA&NDKSOfc-#M>@o#)4;YLqtENdFS^3K9&dFBr|M z*loqE3X2sMmi8hv#7H5<kgna*Z>rqGc_y=ShEbHT^m7S`?4d%B+(-6dYGI-*t5E+< z^P3gqvBIHjFQNKiDKj-p;Y*MmMAXOK^8{gVhrBn?Un}%9(JqaGPiann?Ll$aX-{n1 z!AnT<v!xN*zo+dH+)yR$d)}fNUUOcJ)Xz$%vH5mur0%L;@p((;IW$raH52Q@7``Z{ z?rO>WyjwZ7y=hrziEYVZVX)-}D^!8a+Bc<5#*3h1xvWqS7I$WL>iwNNvp;P<;TX`| zOF6ZibFB4T(YJC~mj~?Ev*ln|9sgYVFTcLiEi{YE;!ZWj>X*aK9|va;HulW-D`RH9 zw=O#R&of(j+rwMS%oCi;+oFskQ}@q2q4x)O3<fKs&%WtzzFD};-G{Hxx)V?F$WHWF z7(*i07&g=2&}`P4G>k5e6yDx`kLvQs@M`+D)vGA+`X6%Dl9YOA?Qrurfg>XqT9E@^ zgWxOT&hX+yo>7=HCb!3BO$p54I3{j@qbN!+nu>Ti*O~vw`5RU!f_JXS+*x#-zFp@m zr}GGVhgT1=p-TFp#dtAVjM3QdpDoi{l*z?1s=d~(E;Fkn=*i8+oB<M)E&5W?I^M)M zknOw+hdKDcP%Q}tuai)WoEa!7&-Iumsf3KA>cJ3Ib?Vh+rZWNZ$pO`dl8LcBv_cAA zc18lYB|rc<0u%wEdTGEup|%_S`L>@ui4LTkvnNApm<q=y*er!iCv8V>#>+b4WIF<} z^J}=w7L&$J%unXCb|Wy{z3WVlMDNhz3o7S-3)6oqjx)7WX0HTEH<C-Do)>{-=9>q+ zXXtoVPHKfVJMk8bt&h;MII}u~0l79^#`5CdW6Ef!eb|E&Q{UJ$n$yP;^Jd)qhw~ej zB?c~nN*%0zm%$}MD%|<q*x?^2$-sGY)_qDIsjoQeKH{k^*%_~Mm`JG>VZuS8W+Qtf zS+Uu?;oSPL<h#s;p3UgxZ3c;@9(LZhh9?&RH`z;Ufi?^GL|RbrQ|i$u#k>L}G`jMH zn3`(J{6K%B(Gykos(!d}z)Wr!%sjC6=V@s)qG1MJN~uoVlq{jeI#XKPMI;@L^`RBZ z<X%K$e<C_&9&p~HQ%fuI$-p5?U{jDsR}QoVqzzw}E77mP5v&U`27f1F&0F8zlxE2) ze=M@fh-;2;q_!ewec2frY%fKQkh6Y#Ck=~JBu;z6vOFXzd7O1mkt`yaC)8Gn>0Fhm zEI{|uQr0z1gk4W{mj*%4Z*00DBL5ko{4X}2{Dl0wAi#aSmq_r~FBHL|;}P&0k>OU! zhx64h5vSKwffV0W4JQs2dFBrfQx(B{AK=BGc`U!}S&BFnE6QSvw?`~m^}8j(4$IzQ z_WzjR?fD!VI8Aa=N;O96$f<JeDN}@@k24)dnpa7nV{o~|y480HWd%qi09M-w5HA7H z5t)dJA9OeU2(Ddz+nofIxgaM#sfN{v)}n+p872aEFyGb(<(TUTpJ(1Bv9RRP<lWbe zn*X9W;yA^EqlAv1#u2Gg|1wrNw~{@z1W#o_GFNuVYLs|BsZ*hkg_h`Il0YDiCHm+W zmS~Y0wwCC%sMd>IWzW@IV2KtfOm4MwFVU~FM5pwL+-yY-+$4mvEEjvjP+5JUm8n(w zTE>U0(q9W!VAi2soP~_07HUw%Pt_tTYxD^79a6Fw-(PjP4xwLxv3Ycv!%RV}m`xvC zX`nx*(H@IF+EJ)392Ul)-t@Oj>L>VGb7%C~V}eWde6yYkCcYR2>L5_BFiz*D#3I_* zY)|v0XvW#xv=Y0=d;t!!=&NUW2H8t2>2H>>rUwQga=@Hd8s$Z+x+rNk0%K7J*cGvn za#2GFTwHgcx}(hY&AoeJJ>OtvvdouZfGLkWz?5@JX6KrhfDJ0`xz(qU+f2hY)2ykx zl5dMrs#`m^OO;aljpVNpXHI7j?NBazjFr-P<5NZ{lysyym6ILI!i}auR#r=s8-sHH zo|F}x&aDr!mLdRfA3dBON<#lrL!uSm7=o9syd*hDuX`F0HkX``(5Ixonj|KOyUg3^ zQc-Q1zi|oXoEJ7t`z@l)r8HbVnV=3@R147(4T%Z?MF>|u+vhb+dmd}f?PMV8SW8Om zNGeF;<~ukE61hiT7Fejt`7XmU^|R{ev+p#`i$*Qly)%e2TjDu=LV)p<*h6u5gyTBv zF2X}pxW+%<Fj!P}AZas9RZ`k$Jvv1owwn8%W?{}x!+bkqQCghlz9l!;d?w_cXMXg@ z&=}JPT7tF@L2ahnMB72@q!wG|Y3@>;eRIVAvq#45Tg=WlQSFR|)0f>5G`p(9xM7}| zFKtPEbWZkN=1qLjD*3c&W=C5QZ78nOyIt7^bEIKqkTQs5B8y0Tx?-c7F3RU`pPOs` z_?hl<U&@p~CMd0Mfz5AN1#S&Vwsi0NvWloHbK|_KEOMjJm}q8E=E&9JuvOv6IZ8ov zcoQ8$o#cQM?=kPAi}LePW480inT%^k+4bRRjjowT_3NF_?RV~cwfUrD02;pIjR9GK zQO@U%q%4cq2SOIu>A-(AYe*|k@#n%-mt4P66m+?M)nmWXqWP-^>As_PEzQPQQFQR8 z8-h3Q39C3Q91oVz2*#A-KL%2bY;8!cmJ9uHA`|<v{z~0`eQ`+GHZb5=o_|mCd#>C8 z$NX`>3!Xc-34zzMQ(s0p^HbkPL0@}t>MK)QkhQHnsYONA8Y3sjLq95yD8o_vXX;;L z>_rtUVz~Yrx{&>y!BX_$%=h%m(WLsmNbc^@hvIY`rx=`G3p{Y^ZC06YKwy@l-|)Hh zU=6u>PjJFvP!kJ(Tc+sbM_EIjrY|G=W}4NvvWB>k^nM4`K&TNt=8t0byviN1Lph6= zm_yLKL?eam;`vUGWXllNQpvgH+$3sPb_yL=Bg|EjmK*vv&mK-$JqW8%=|ASK>2#&P z_Hr|Y5Dkgu7#^X*C_?v-?p6bh!n7?WmSW!JeSwnSm}M7T5((zV1Sgd@d05#6N@`iq zIof-m%Wyrh&Os_zmvwFpf)UBIy{<8BeDtovo%NaL&_|tBV$bJ-C;E$apFPY)zG1$1 z&owMVml>CDJKAdL5zE6EYkt$pYmLfF?wDG0`I8N*#DQu4-A7E6KcN`U27=18Fz;s6 zgRIKZJ=&bE;>8osoUL9Ryh=TbC>SSDx$a_ae4Sb3Y{(ciQKVJ&x*C=an(TMl4xLH2 zXX$$5{C?<{&`X7#bw|C!?@WU>(wf=M60Egk4C)t`yyBd`(C=(qFld4VoFf6R4+pHN zK8Ll6cJ>?zJRuIOK|)?8A%{uGgm6egv3W?S%i_2=V{%GzdHk`#X)(c}lhxAXtow#+ zFHp)}cHUdTEBD@=-@HTIVx!PQ#~t7^T8*<#^hS~|xc9~6%di^At;m{`IHO;U1JyJ& z?$6LV#Y%45gWjnIu3a5-`VNydN5;meS;L)mKjUK-hMMbbbJA&Cbq9~|S=gw!q$wS} z<Z(t^y7;u%;xGk;LG3lcOw_zt$NHvB?!ZTuJIo+vtIY)W*7UDg7nZYhgoJ`|`U@?# zf&SRW>>!$M`UNJWuIMmgl*gmkLk_ZS(?`c%lMZ(&XFK8NP#)0^vSl6vFEG>}Yt=qY z>WCarV-#iQR(@uObO3d9Zj~Ae<}6f(n;Hky?Oz`=r|lj-I0#^gmZN5;ee)19uN-uf zbLW7xnioz$Qqpv@afoy00q1WU<dahvrqv*^Tb#kb-RY_O47=@EAgz1AjGqJEU%$BD z#{P{%{LcENgC^i$Gs0h&&6#v8aM9Ug50ykMQMk~#qpD^cswS=IIHD-)jLMD@Eu?Zl zXzx^j#tYp#^O##HK)x^gH2Y8oBzw6P^DLtqvNE>|&pEgH8343To6masFPXZZ+i2fw zw(TOJh6NWV1zH#tgBTU7eP2E-U^0`E%lVvRweM3##v6R|Hc)r2ZWu6UP8uu_SKF^7 z5Ei+b&tX|(bW>KeN_C)b7q?VhC2@*pFT<#gaK20zQb%f_ppm8Xf&=AdHBgp?2g=0N zzUt06{THYVS>0fh!O|&%MP5GTWr9DpB_rmtxWJV%cw()<Th-`+9pNw^epR)x<&H5y zNn}p<5E>yvDADh1(g)ek#K;gD6diD^_G>B>y~3*2ri=>?y@k#|fr6r^y=jEkKl3E7 z4M}aqf+KgXac<4$1&vT`xA250AV##H0=5ek@I!)vK3Iwme$0oDmHS)WNy*wIdYTYj zZRu7LFxIS58JMfP!&x-K4>+HK()5vW=nSz9Me#w3T`4{giqU44ixK<NS-`KgQcF~+ z$)Xx~#$%3oPu5N7C1^%ShRb#_>rd!tunBaOeaO;`@Gg0VSi}FyYeUlc*jfuoTFFEd zOR8Z4RTBHrnM_v=qLS_KTIyGvYt1|?i!+C4y??`sV=b9MS0Ju6Q)C6T`W3;Z%o85d ziENh~l0#_RtCgzGELP8JHB9M!#^AHfT3W1T^h?P+q1$V+gEe9y%{FPzuSsRs@Ay-r z&&$%MWa*cg*GZ8R;SHL@d5gHczoSYe+a|;+l&uAZooROH4pP=g`GeNXPLfFzb`#S1 z2_-JE19Kg4B`^wb`OGw9drEbu!t~n%qeIJiU}$Ld55)5#)skz}?aZlPlQ8z#UJ#-| zYO^vmzd2P;V*j5ETWQQ}A;NIjCB|%xCEmF;jXrG6JdLv!xSAK@X@Sdl!B-26nk^;Q zowGGGn&>N2cRRN_tq77S`L(hZ^0u`V19Af$;OpSM*@-NJvG_<B4C7r?o87^iy*8Wb zMrpq6c67@_sMBrzt2>@@hy5J^v<IIiJ1y|!Q!YK$isdqQoTPDML_TG>d5CVZ8v5tF zwQ7lkRx1I6-#=R@`m)Md`q#Na+?08k)vz7fn~b?P7;2Kt8t}>IiMVUrKGxYujGZWb zLanz`MzcgG7IDuLahiX|7e$b)I}hh9p%{<(HOiH54&kp~Ytv~>ArTCn#S8~^$oQ)X zh^?`%yGTMs6NUtL_ntBL;MAmDP#8v#36b}%i_U$y`ln#i)B;*>S*Pvjco$ClL? z%=q~elnuXpj0WVh4c6?B5^b?x@W;C;BYJ#|yQV(-^BV8xS@qdyP_7}XGtF%KKWAjn zLectNCDB|O$s?N`pgU^fn(!runKLO{ZL*IDdN#goZ=z)9FDy|a4b+7tIf&rq{hz40 z&UP~#62@?Yv#|LPJJk&HQ3e)?F*x^tH_b5TT8Z=h%QKll3XntrekU{W1ucz%R_!vl zu6JTwtI@B2wku%k4*@aLHLf+aS<jd)!%M#cTQ)o{<ty6y;vrvlB!}@s{CO0_`ltZs z3fJ>dHs*_rgZ{Wh2W%`KXEPa`u}qU^8Nd`Gtzm`f-1-zBi0iySJ$H?3COIw5Sts}8 z<+Vm%m)h*yTBpLCW?Q^x1F!Vd+Cd-yYm=~2?%cW>C+BZ7&rJ<xIqNRtBg?sU36IuH zGk8uOY8JK)$4P80(iq7HrP*8qcI&NRs5o4XL)iMFv+i5c$~Hy3oMB$wp_-Th?yNKL zAangr28eU(Pbpw+wfW(1ey17vQuDUsxUj8DIfV^QQ0G0jGyEy5^P3)CLis=cawvai z-5gx4GVHJ%DF#_>{WkI2`jH<!Izhz8W}oAaF^s~#^M*_X2XtOm#D*kvo)l8G*-}>+ z<t5PsS#I^dD)cT0YpM^@RaIwOUV(>b9w~ZgNut<T7H`U!4Nfz|w82YY^r-kX#J6>( zRG;4bHiKMr_Jpiv$aIiF9yPwvac%awnv<K8gmQS^5Q443>2~cp8C&!2=C}j(2#tMi zjAaHm5bPpSUwa%RYp-#*{ngfz;(tXArj2S*S=&8{L(57D#>Sy>ye}&aBu|6{WXYoR zJy=+9jhe&f&&Pd^I=}K3&D!?hXM~&KKNL|-rI@I}J}9IBm%CT4Pr(h2lA`RU!W}#z zTt1O71J@X3uEEEm16dpYC#BMwiUd{3p3PQWl4fnzvSl_Q9@M}hNeE;-!hE}nWGGc1 zPd%s4GDneKLvjGcS1HB`9XaviNE~IJ5)rQKQ@w;(FbQa{p*Dyv{NvkHXAi;5a-v(C z`r^gH3Wfzd%G^(xROzgOnu~kNc%v|Y{{$u`D4$wu6mDT|WDAsPz{x$PmVRmi?cZF+ z-U3yHJ4XL3ya%Jx{3B1Os@RU`W_KkhwTO`EP<`_mS~KR8U+7dTIE{Ja&Tt#Gon$nl zE(dWJp-%nLFGR6dIAy<_TXIXDnE(n>ay2-K8OIy5nAx_qmLyOgtQ6Fj%*-=qe@HKi z0nCq$syuW4!}7)5RiQ;?m+>J6id0FQbux>KbU4=#b?)3Fg%G{}A@pSk=NYO@J@Gx( z+{gD5$inzGt&2vIBM=9%&Ys$We)D#=;$X>?T(d~*H3&8|nSsg$L4-o()4BCDnT9d8 zE_0<UD}u4Lw;fd;UFHK1Sw-$AMSfUDn)r(v5hd^Sk`)Y2*Ymsk6l$eaD9LZJB+_ZC z?#wseq9VdWMx##Wq_ehmu!z%RL@#$oFo~*F_DyBDl?uh~G*>`&P_=OS)^ylwt2<5* zvwCk}v{^^0RD(Mo4Ce-R%T811{Z?J%>mVhkZSqsZUab`AH#ms$5NI#mLjx`}s<cDr zd(bT?x#j~c4Ean`t;tA{$e7DliznxUyYchy8+U-d7c;x*N+iTJseQy>ob@d<%w|L( zocFxQ+iwIN$`Lbg(^wA>sk1CDaCHq1dn;88aoAtv)vqavty0V_rw}n1A$&%RTW^fp zY)}2T(vF=bG5SC~B*4=@Q8ksK&3H(1Umvsi=+-mqUO_!8b(bJ>RT_kck`^w4=oz2- zwmQq2dD6<s{fq(TOjQ^`MAUW8j=)Q)pKZQtBiUBnNhi3h<-*+j`^bGNgVvX9{sEGR zNO&hvNz2S>)<X=Yal0`ZAdBD?=G#SKJjZ;G*RVweNW@0_IHN=HbIvdd$%?KtCDDXl zS-puTv{HE}Vwupja?ML6W68l~ZcsT0fl8=k*}`^H<U@)jw_TZWQdA3@6ACGl0(xdK zv6O82hzlWrpNr9j5G_^2VwJ3Rizru3uw+-GLsw+ulN!^ZTID%+Zm>hOs(rtPvK;BG z{Y=ms-NO?H{RW<b%v>f<@R!l@1ap~PGv8k0k3-q__{PCC@7C5Fh^ikPxV*RPmYM_6 z0kfvSzBw?k$ERj&%~qlI8?ow$vto~Q!31rW=wT=8P}xDGS$oy?u<(xFOYiHeWgsP# zT)aFG=O0)ID^^KfcN36{h|5_lk9ol<i^Xs#!VJ1=)5TyRo4{4=Mm$HcD9|-JJ&<fh zkv<f^_enN#g)O(Tku&Sh7?;YX7>2Erhw1%VG`GJQ^J0PAl8jr?Yx*E!U4=K2it(Ud zQ6rhrtZtLI1dW*3;fTHQ-7(GY#w6b|7=sK8vsi6UF!k;QP1I`7T{{)D%r}j9f6JY_ z`axh=-H>^}`P?qy;<rl2GrJD5de^xKlln23Oy<F+EPK<&BrJD#Zc35s&LNx|Ji}&J zXm_K>er7j3=la1cXR(2P^}~G5U@)^Y9R^W~(Yf&ei6pNG>XS)n>Z@{y@SU?&+x_PP zwi4TIm{g4?h9h`GI^_u<CDQ?3teJ-(%{L@AWgch0dr;Ksu;h1GD-v@Vd?KD%8=f^m z;~-ZoK9U+x<NkT(4r1pAmLrJ72_nawwuDKdgr0<*Fp4!2$;P1$QjoiH>ccL{tvDS( zC7i=<#ERSNqK5joFl%3Dof%|KBvEU5qQ@ea%d`kN0xVuIHgfZRyPgfKsk;4%Cssd! zRZy@kcG~O{Xfb=dB)TDUpTCpV$~J|+y5e-hioLf6Tpsh<?=bFK?P5~WABz$q<20L1 zgK^Njk^zL6F8vdO>o_n_hSP(E;qsV|s#j?^8BAB(5Hf@{N#z(eFM>tMXu;~1uk&K# zE;Rzpm%)M=;(^<h1j!5clYZyCd5BydPFZnUI5nru$8oe_LALrZ21JRzsDzD_MOjK( zk00E|rj4;t{uou#?P7|O!p$-N?LHWDp|9zbIyggai<?WN4itPete-Y-G=orT;ji9@ zLZ=ymGJHhw=e8|l=poY$b}_LL$-0_PXX|5f%|!A;LiZHb1)@|=P1CS_a;kCA%$JSh zxHn`U3rtF09;IJZvp#yJae2*p+iYVjBMKEb-&RqNfxq_i50rAjaJMzrB+u3l!Dye9 ziMZoyHmr2-3XD;W@iY-=yLLglF9DNcS7U9=rn>O${@GT2SY*Q<WH6{6fu7s|*TK2< zT3P#Nn0GR%^BYE+f1!axn_2WK8jB`q6;Wudt(Y3NX71&$7WkD1)-24lgPvS-^RHD$ z_24>}7pOi8US|%YNHQuI9Dx}gPKACg9BY2xSRbtn$9iuY9oSBsmKgV3c(wEn=%-nK zD|%o2NhvE{vveJc2sn-K3I^M)_Ob0-oNJyT-AUD_7&*4H{_58PGyIvmsB7>#GLE9O zM_%Yt+6~?L-bud7E~=~mV~m!R6?=_4{MCo0O}Rex{k}23X2mR8`5ssCbIoY$sMFI9 zV=R9en4=k(1bGJ`JxbOSr0X_SY1>&{IxnuM;$(R1rZhlZsNjrRzXB)?&li~var z?B}%klDLWDf^4)nO#Q>nX4L#{frSueKHj{6e&Bw?L>`d{`ZHFsWS3ZmQoc`R>p!Zt z)MWNo*@Q0+(@KUAHQ#)n2!1ZmKjktmg>5tXOlEwvo@l;@bE{CFH1qfBRZ%~VD0^FK zYxkW_5R7B$+uR~XI@m1DA|0`t2h;L9#E9HeM)1wN?ybHta2K0&yD%+>v34#tOPGE6 z`4T2CtnhJRUgKcr&fU(Poo6zxgN->hy>T#X%%RSme-YWd)|AY6<Q>vM0lNYNQ&yn% zUR-P#5K5nU)Yx-dWQHOQ5Jo1y$g%9Mk}!8IeeMr47nESfX>;2=StXRpPm!JqVOg!O zss1JtXWbeChf1w%MT>HGxYweE6iHzp10k|K23P|lvUm(HB!wrCOfHOAC+sN2t35LB zOh)u5<f*#!IgOW4DXvp=1(w6XCDf~{2e47@U+w>B9syRTR=6tT`Fqj2nANt5guo2m zFRo1DZ{oTuaTy*M?|e>p@X=?|N4fNYq|h*m3`rtjb3S)K(tr~W*Ak!p*pjtM&|QE` z1g;w|3YQ_Trwmq5RfH^6ge+BrELDUoRfH^6gsiVr1gXj)W9({XO@BJWxitVf8QE40 zLOB<V*u~}OEb%~M+|m&GzUoKm-f$<4BQ9%Yue(_y!71{a^buyY_Xq#|XDDPs%>2Ws z#?1K7`D%?yj@5<1AMJ1LLKc%*@PGU7yMNKNXMh&qIPd`w1JXJYm<B8WRsu!9-9SC? zFz__+B5(jW4s-yHF5&^nKrT=M+zs3V+z<Q!*a;j0jsd5DGl2bbjG6(Xfr&seun_n< zPy*Z!JPqsx{seRYgCIwZ1g-=!fTchQPzP)SegOOo_$_c4I0bY7age!&1CxR40S|CH zPzG!S?gbtLegW(T4g>E39l%IX`-wm@a3j$7_kLoU_KWm1ZQ4y~+M(s#*}g5UJIHUI zPSYM7*7F_qSY1$D>MeBZ<?cJYy4$<HSa+`~FZ8-sSC+4FS5%g-@>W$%;b7krZdIkX zK=(%axhGU<{MY7`8>NNrvT{ksyGmSfD<~6()x~9nZqEk2sJu*h8hXL)rCx%Nv^H*R zh4Ps~G%44(vEA{?E4*bY)KyihDvK-hDHR(epUO-M>aj|vX=}79ZIxE8Rcc=TP0<Rq zQvT7GTA603_bVh>ZDN^GT57!tV<JYH(52a8w3uj@Ju@@2pZumLX&x2Wo$Og2>(H)C zO3L#<8gjb@-_RT@i&pZ}wDlG1`8fyy(bwVN;ozTqYEO+#*R)Fkeo@gjd%u`iNB_71 z@dF1rU4t(gk}&k*OA?0-A2D*&=rQiGmyR1h;j+soUUB85$yZIeI_a8gr%szb<GSRO znW?j8U;nkV^c&`6WX_$JHUGw&7Gy76<XOBVXDJptm*;=|=37?WdfUo^+gBBOSKm=o zTykgWnzHhWyDF=6W9_>28}9zb#_CO*6`47+OuE!lUR<VoD=E`WTBf!{Tgcx9+EndY zS}cRN1**Im-riy7mR8NJ^m;X(IbJ=tpwv+B^CI5UOH0dFN#shSOfO#Jb$cr-%PZZQ zHjvI;x?oXGj^!esTF(51^CCXAj78b$^B4BGESZrsb=ttV^fGrrMMY`xssg>3AyZUP z<z7?3uq?n`*S%{hbQ!Xx<pm7gBCmUnJDhiE@$Hobl^fi})VZ?KyGk$JFeT1Y>Mf}9 zGO)|^f>p#MMnvkDSGlW<ii+||e7pr~+^Z@4n(|67Y4Ey6m0*f0Jmr`2O&u6_l{>ws z7zSx)=geOaF>~~y;wpDRRh4(m?WG&sg+^s@*&XgOl3FXppd!U(#d>i;Y4P1E`M9ML zo;e~F_7c;5yKx8K?hWNeWn@{WxaaF`g03mA(%q%ScX~-(s#EE$GD>xK`D*v7g3?mS zjFyrzUA3xwO@*4`6R%!XT6u+gwNbW8wW*rn1wDl-tI{itRXUaDzw*o|EzK?{E>m@v zdS5H`R@1wz+_<C2T~$%Aij{)k41fZrb3}thw%0X%+N-<nUaRw#EVbHOFQU-pWvjeX zzIuB|K2o+M$zu*FN%?v*C=B^un=JlDnOb!iIXxlVMc#r6tF)wZ?R8&L$92UK5mmqS z#G7%!cvX7gm&BVc@hS{P+uGtv-6$yS=^*Jzm4TFtIdOruzpcDXmhGz<II?=Hg|)j} z*Q7|io_eeGlzC89PInc0*A}nx_Jj?!k#~Is^M*}9TBc`as&>9cwU0rLp)hM0cEx%T zdqSa%f;;<$zi_*RA{7?s1r%YR)#VY>Qce0w?_GwsN(v*Rd`W15p#xdT))X_L7<AI# zGTe<aqe>cZUBTaR%G35qstwOO?!9I7T6x(TZ<$UVB&=$~^M);`yu*-yRjR=yteQ`& zS;TaiuobdCcdtZ}ge-4fHG(xQyLeS)c~$vp-JM&kYB^`pr0(`uU@dwqPg)%FVak*# z+AQ|&J1SYt$_iMKjj}t-%GZ@$PalSwFjLm(v2k&1q7rPTTO#x0<g^R2zWR;gT^RfF zdm!SyiFdUb;*JiC?svpDyWh7(yu<A4cIU1@_xpDu-eYQN?y0G*VMDgvQ*+OjnuLD+ z*patx-AaLyl4?9P^_oMQczLoXuZI1WP1)nACwuqAn)(`IX>7|yMMVxr?D~p|brlu8 z_G7&NzyG<lzW*kIA6ftU`ke1O3ry+D{?%z;{MS2tt=97|O8aX6B2(C+_56#5xcycB zh2y*bzwdwT3;pj#!{h(q5fD||{SSfXuk;J|pggxk_56#D`fC5e@y|D=|6^`{Z3akA z3H%G^C|^DAE)ntm5B&Ou|7x}E3FXpy-mSN&D47H`wOf33TkrX1eM6)F-llKex9!{a zf9Jd3d*J&IKJ@TEJo1k}_~E15AKUTx6Hor=sUQE3pFI83pZ(J_KmWxqfA#Fn=bnGz z*S~r3rQiN;SM%;Ydw<{3x^Mr1mk<8o&?|?Jyn6JtKfeCPu{Ym(`}jZq>75fN-+k}Y zzx?@qv+Z94r~mDP58FTb_m4Y1Idiu2)4zPy#pTGq`9O5x1J74F5dCM@|35qbzq$SY z+JW@K{^~&bpI!f~teI=p%&Zd9gjUFJvOAlfTV6Ks)3UR#E-bv77k-{>O-lzj6LXGJ zM`vwe`P%OHMVywzImcVUk<<#1Zrov1>6&(<QL56o5nNf)O0TFa7MetMLFK9<o^!po zR~j5t#qY*~GWAM6lD<Z|lBPylk`7QtybY3u#Fw}dN6RVDjmkniB)!UF^|rLgsH_UP z<#`LsyrGY!pwZ%-U0$YqbBxflK$o~0@if9~gp)8D{u+n;5RD~|qiOlN99<oH#C=(n zw{p?#C7cuH_Z*Ui;(_0Sf+{_oGv-=I4i!d)a<jgzWVCE(N(Fa#Zzx}%t}V;STr&0A zDH#hOKaeL`QvwP?c_<b&wAzO%Q*#=CcAz<E6&i;&qN!*xX*hm!7A;(~Z0UGy3TIyV z4%3sS+^&+reNCZqzlFRuaH?3dq`X`*;Fo1R{+IsNT$HXIhC^v1_TlT;X^TN)A3A?h zkaeNtX&N+m^$dT%0qstH;qQHY{9hc`+y7vM|Bol6X)git3&+1V!hhEEG%XE?^zWPh zdoz3cAC8DG@qV7#+dndY@lTy?`OAAO@8NRv&1cv3R=5lKfBdxz`;SUb(^3HWT`2xl z^LqRDE$3%9_V({vzB?Cwx&Kc+J#~9A;{8~k_9|b}6Yd)k?|t)|p5Hsa$aLQRdYbkj zAir>ZBmJ+sIZe9;i1gppryTXS_V$nL*F@;USBGfC;q?2K?~0NO$CrF(miG4V8~^$Z zz5OHem-q{7zuf=oExrBw_UHKT_4e<Z{!8Ega{r~<d;9k-|I1JG_U}6{zx^Z2U*q?O zCwuz5Z#fqHtamzn{fl<@_U~KI0SD5wrJs^X=r>3MojVc!>izt0p32|GQ&|!<&s*lL zgt#=vqLj_iD@!xiLc4)ag`Y0mhdDx04|5>O?0E&n`rPu$94I-ZUTbI6zNgJmypm8b zw#R?6K}3&8G^?PjuoMj96G=6@ywE81&V^XJ5Sk64-_kOLVn3%6QZdB99CllX;qZc@ z7kCTSdcWZQm!4Ftg!43Ql0B!?3odbKG&x8?(hCbA7K8uvi;85TR7l)8<!jbZq6Nie zWZy1jwbFsHBXz%C(#X*ZEk}505=Y9rbVG$#n`QYHK*g*Oq##}U9hg(8msadkf$Qu` z!_>R(7W^M7e*=<zSs3Zivh2&sic|{~X0Bfal11&wPBAgY*eTrwy<d->UzOp7hJJ^) z(nEEn>)w|f1UFHnFHL(gIt%)yVs2=UsdtN!af>R6N2;LxK6<|NfDkslh4af`eF+6m z)0!jQ!9K$7ITAO0jz`lHq%{_0X3P5tN(1MlxKNE5FdyxD`_j@X0$BW%S@IR)qI^x> zyE!eh<x3T@LwX~k^goMeuceCoIv?ET`}REAT8$y?O!NZihau7+qv_X_ImC15+au{^ zg*g?)WmY%e6eSsE_E0u+bm3l9rE9w+&o6pt3oZ~NPph-%6&HHv6cto1EzcH8@eLbv zueSUA=`dO!SN&kk8ci#(=UOyz)dKmp#fG<XgU4H`xH7N_RC$>_CDPVQi&xzl8mB*r zXq(Ugqj7T7_*7`$Qn*y<Rchq&raf$1qL(f!TL+S>{aBS?iP!3mTf-#?^-i5iIkYIy zvkydkGkwAIZ-|;(YE%_T+BX=hS9>d&X@8DhFekg9!fHo)VvMc3EtZyt8%Q%FL(vv# z)_jt-m-$7!IlWy7(<b>ZP|O!=%4zS*IFa1D*?m7zHOeWzo6==yb4tsryrBtvuQggi z>ruM)a71ku8G41G%jkWeSExKKMrK~bDzG86%1Nf!ErdI}rlO$I+g;n--Y%5-n3OSM z9OV{N77Jr0UArlB$->M9oCgX^IV_dgmcUk!bT#ddR-D2`tF7<Lq%A_7EAtph04cpH zgwBAy-GGlqoBj9i|LzvpB?|HQ$<v}xh05y+JtH0nS_#&3!JqgG{P*v_Ti~m<z`{SL z{pRPxewXpD<I>dFDt#B-`T)nMV2ubY{4f4woL&rs$D}RvZs(Z@^aBP0$f0Qcfmk3O zaD<-XCf`y7@e`h0*iX`xxbj3Rhsr~yi?|I2E((F<Jr)r6>41EvhrZ{8zFFW^oFyUm zoY0eHTBV=QQ}SjxR_Uza=>}MEkw-%21CX*xJ)}G}fRwp5^xVQz{C$A<*8x%<xd3<t z@Pp9zcAiqc#{tRjM}UNT4v;z>0>u9fK>QPF6ltGuoAKJcHblus#4r3Eeullm-+iBb z{ri6ZweT1652y2A@9DbW&#J5Yg1`S7ZE<0ygjK%_6UF~))L&|G!66XZ$uBqr-2Zjj zfSUY2J`{?Ef`>)h9gnkNt=zI<%h*uoJo%3Gvi%9`S^L8iUGkQ;sYX4YB7F0Xw|2NK z?=SqVMfO#GX`$z{Uom`oDEv;szw+3r$A)YF@|gM9%~oO&f4kG)v|Ysz-BF9*y7eu$ zcH3JeZ(SP^(t52udhAappr>84$%<L}Zx-!tPAFt}4gW&KztLga@bq3O{H@<o&c0<8 zd)47zQ6Nog|1eFf_$W=QADON_Nd6LDp3>KX=g3d?)=o1`;TQ*b%AWlwPua^IJY^Ce ze?Lv_#ZU7T9HXA+5T3X26r5%}&tW{f{+y-_=ed{X2%h)y6kMT@=V+c8Jjd`n@h@qb zo99zJ$MSsURGP91=Hj`YZ;j^$9_{a?X?OEH!BYm?ah^e*2YDWXzWY^x;iK><NmuF= zT9h<tpA!21!H?6l?*iL^dx3hO4yXav0~J6Ka0}o8vVd7YGB6ED0wx0!f$@MF7zrc- z34jZT2kb!Sztbmx2}t-8JdXi~fxW<sz%#((z@xw;z&2nbPyzI}_w>2+=@jadL7(4y z#b1Zbp`VPADB?+6d4_+|PVRo+k#0QiPsT~)ucpF^-~N%s&+_Cfjr9Hxzk4$Nw)lss zmkZ@sGN!|sN4^W6LqL8q7E^(*12QhY4?GLJ27C+*reTtRg@9a?3CEd<Up}x7cmVhn sa1{7=KrVY;4P*nQ!2j#Nzb3L0-REZu{lfJw?Z8eMa0{>$=sSM?C)~1m4*&oF literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/setuptools/command/__init__.py b/winvenv/Lib/site-packages/setuptools/command/__init__.py new file mode 100644 index 0000000..fe619e2 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/__init__.py @@ -0,0 +1,18 @@ +__all__ = [ + 'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop', + 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', + 'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts', + 'register', 'bdist_wininst', 'upload_docs', 'upload', 'build_clib', + 'dist_info', +] + +from distutils.command.bdist import bdist +import sys + +from setuptools.command import install_scripts + +if 'egg' not in bdist.format_commands: + bdist.format_command['egg'] = ('bdist_egg', "Python .egg file") + bdist.format_commands.append('egg') + +del bdist, sys diff --git a/winvenv/Lib/site-packages/setuptools/command/alias.py b/winvenv/Lib/site-packages/setuptools/command/alias.py new file mode 100644 index 0000000..4532b1c --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/alias.py @@ -0,0 +1,80 @@ +from distutils.errors import DistutilsOptionError + +from setuptools.extern.six.moves import map + +from setuptools.command.setopt import edit_config, option_base, config_file + + +def shquote(arg): + """Quote an argument for later parsing by shlex.split()""" + for c in '"', "'", "\\", "#": + if c in arg: + return repr(arg) + if arg.split() != [arg]: + return repr(arg) + return arg + + +class alias(option_base): + """Define a shortcut that invokes one or more commands""" + + description = "define a shortcut to invoke one or more commands" + command_consumes_arguments = True + + user_options = [ + ('remove', 'r', 'remove (unset) the alias'), + ] + option_base.user_options + + boolean_options = option_base.boolean_options + ['remove'] + + def initialize_options(self): + option_base.initialize_options(self) + self.args = None + self.remove = None + + def finalize_options(self): + option_base.finalize_options(self) + if self.remove and len(self.args) != 1: + raise DistutilsOptionError( + "Must specify exactly one argument (the alias name) when " + "using --remove" + ) + + def run(self): + aliases = self.distribution.get_option_dict('aliases') + + if not self.args: + print("Command Aliases") + print("---------------") + for alias in aliases: + print("setup.py alias", format_alias(alias, aliases)) + return + + elif len(self.args) == 1: + alias, = self.args + if self.remove: + command = None + elif alias in aliases: + print("setup.py alias", format_alias(alias, aliases)) + return + else: + print("No alias definition found for %r" % alias) + return + else: + alias = self.args[0] + command = ' '.join(map(shquote, self.args[1:])) + + edit_config(self.filename, {'aliases': {alias: command}}, self.dry_run) + + +def format_alias(name, aliases): + source, command = aliases[name] + if source == config_file('global'): + source = '--global-config ' + elif source == config_file('user'): + source = '--user-config ' + elif source == config_file('local'): + source = '' + else: + source = '--filename=%r' % source + return source + name + ' ' + command diff --git a/winvenv/Lib/site-packages/setuptools/command/bdist_egg.py b/winvenv/Lib/site-packages/setuptools/command/bdist_egg.py new file mode 100644 index 0000000..9f8df91 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/bdist_egg.py @@ -0,0 +1,502 @@ +"""setuptools.command.bdist_egg + +Build .egg distributions""" + +from distutils.errors import DistutilsSetupError +from distutils.dir_util import remove_tree, mkpath +from distutils import log +from types import CodeType +import sys +import os +import re +import textwrap +import marshal + +from setuptools.extern import six + +from pkg_resources import get_build_platform, Distribution, ensure_directory +from pkg_resources import EntryPoint +from setuptools.extension import Library +from setuptools import Command + +try: + # Python 2.7 or >=3.2 + from sysconfig import get_path, get_python_version + + def _get_purelib(): + return get_path("purelib") +except ImportError: + from distutils.sysconfig import get_python_lib, get_python_version + + def _get_purelib(): + return get_python_lib(False) + + +def strip_module(filename): + if '.' in filename: + filename = os.path.splitext(filename)[0] + if filename.endswith('module'): + filename = filename[:-6] + return filename + + +def sorted_walk(dir): + """Do os.walk in a reproducible way, + independent of indeterministic filesystem readdir order + """ + for base, dirs, files in os.walk(dir): + dirs.sort() + files.sort() + yield base, dirs, files + + +def write_stub(resource, pyfile): + _stub_template = textwrap.dedent(""" + def __bootstrap__(): + global __bootstrap__, __loader__, __file__ + import sys, pkg_resources, imp + __file__ = pkg_resources.resource_filename(__name__, %r) + __loader__ = None; del __bootstrap__, __loader__ + imp.load_dynamic(__name__,__file__) + __bootstrap__() + """).lstrip() + with open(pyfile, 'w') as f: + f.write(_stub_template % resource) + + +class bdist_egg(Command): + description = "create an \"egg\" distribution" + + user_options = [ + ('bdist-dir=', 'b', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', "platform name to embed in generated filenames " + "(default: %s)" % get_build_platform()), + ('exclude-source-files', None, + "remove all .py files from the generated egg"), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ] + + boolean_options = [ + 'keep-temp', 'skip-build', 'exclude-source-files' + ] + + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None + self.keep_temp = 0 + self.dist_dir = None + self.skip_build = 0 + self.egg_output = None + self.exclude_source_files = None + + def finalize_options(self): + ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info") + self.egg_info = ei_cmd.egg_info + + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'egg') + + if self.plat_name is None: + self.plat_name = get_build_platform() + + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + + if self.egg_output is None: + + # Compute filename of the output egg + basename = Distribution( + None, None, ei_cmd.egg_name, ei_cmd.egg_version, + get_python_version(), + self.distribution.has_ext_modules() and self.plat_name + ).egg_name() + + self.egg_output = os.path.join(self.dist_dir, basename + '.egg') + + def do_install_data(self): + # Hack for packages that install data to install's --install-lib + self.get_finalized_command('install').install_lib = self.bdist_dir + + site_packages = os.path.normcase(os.path.realpath(_get_purelib())) + old, self.distribution.data_files = self.distribution.data_files, [] + + for item in old: + if isinstance(item, tuple) and len(item) == 2: + if os.path.isabs(item[0]): + realpath = os.path.realpath(item[0]) + normalized = os.path.normcase(realpath) + if normalized == site_packages or normalized.startswith( + site_packages + os.sep + ): + item = realpath[len(site_packages) + 1:], item[1] + # XXX else: raise ??? + self.distribution.data_files.append(item) + + try: + log.info("installing package data to %s", self.bdist_dir) + self.call_command('install_data', force=0, root=None) + finally: + self.distribution.data_files = old + + def get_outputs(self): + return [self.egg_output] + + def call_command(self, cmdname, **kw): + """Invoke reinitialized command `cmdname` with keyword args""" + for dirname in INSTALL_DIRECTORY_ATTRS: + kw.setdefault(dirname, self.bdist_dir) + kw.setdefault('skip_build', self.skip_build) + kw.setdefault('dry_run', self.dry_run) + cmd = self.reinitialize_command(cmdname, **kw) + self.run_command(cmdname) + return cmd + + def run(self): + # Generate metadata first + self.run_command("egg_info") + # We run install_lib before install_data, because some data hacks + # pull their data path from the install_lib command. + log.info("installing library code to %s", self.bdist_dir) + instcmd = self.get_finalized_command('install') + old_root = instcmd.root + instcmd.root = None + if self.distribution.has_c_libraries() and not self.skip_build: + self.run_command('build_clib') + cmd = self.call_command('install_lib', warn_dir=0) + instcmd.root = old_root + + all_outputs, ext_outputs = self.get_ext_outputs() + self.stubs = [] + to_compile = [] + for (p, ext_name) in enumerate(ext_outputs): + filename, ext = os.path.splitext(ext_name) + pyfile = os.path.join(self.bdist_dir, strip_module(filename) + + '.py') + self.stubs.append(pyfile) + log.info("creating stub loader for %s", ext_name) + if not self.dry_run: + write_stub(os.path.basename(ext_name), pyfile) + to_compile.append(pyfile) + ext_outputs[p] = ext_name.replace(os.sep, '/') + + if to_compile: + cmd.byte_compile(to_compile) + if self.distribution.data_files: + self.do_install_data() + + # Make the EGG-INFO directory + archive_root = self.bdist_dir + egg_info = os.path.join(archive_root, 'EGG-INFO') + self.mkpath(egg_info) + if self.distribution.scripts: + script_dir = os.path.join(egg_info, 'scripts') + log.info("installing scripts to %s", script_dir) + self.call_command('install_scripts', install_dir=script_dir, + no_ep=1) + + self.copy_metadata_to(egg_info) + native_libs = os.path.join(egg_info, "native_libs.txt") + if all_outputs: + log.info("writing %s", native_libs) + if not self.dry_run: + ensure_directory(native_libs) + libs_file = open(native_libs, 'wt') + libs_file.write('\n'.join(all_outputs)) + libs_file.write('\n') + libs_file.close() + elif os.path.isfile(native_libs): + log.info("removing %s", native_libs) + if not self.dry_run: + os.unlink(native_libs) + + write_safety_flag( + os.path.join(archive_root, 'EGG-INFO'), self.zip_safe() + ) + + if os.path.exists(os.path.join(self.egg_info, 'depends.txt')): + log.warn( + "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" + "Use the install_requires/extras_require setup() args instead." + ) + + if self.exclude_source_files: + self.zap_pyfiles() + + # Make the archive + make_zipfile(self.egg_output, archive_root, verbose=self.verbose, + dry_run=self.dry_run, mode=self.gen_header()) + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) + + # Add to 'Distribution.dist_files' so that the "upload" command works + getattr(self.distribution, 'dist_files', []).append( + ('bdist_egg', get_python_version(), self.egg_output)) + + def zap_pyfiles(self): + log.info("Removing .py files from temporary directory") + for base, dirs, files in walk_egg(self.bdist_dir): + for name in files: + path = os.path.join(base, name) + + if name.endswith('.py'): + log.debug("Deleting %s", path) + os.unlink(path) + + if base.endswith('__pycache__'): + path_old = path + + pattern = r'(?P<name>.+)\.(?P<magic>[^.]+)\.pyc' + m = re.match(pattern, name) + path_new = os.path.join( + base, os.pardir, m.group('name') + '.pyc') + log.info( + "Renaming file from [%s] to [%s]" + % (path_old, path_new)) + try: + os.remove(path_new) + except OSError: + pass + os.rename(path_old, path_new) + + def zip_safe(self): + safe = getattr(self.distribution, 'zip_safe', None) + if safe is not None: + return safe + log.warn("zip_safe flag not set; analyzing archive contents...") + return analyze_egg(self.bdist_dir, self.stubs) + + def gen_header(self): + epm = EntryPoint.parse_map(self.distribution.entry_points or '') + ep = epm.get('setuptools.installation', {}).get('eggsecutable') + if ep is None: + return 'w' # not an eggsecutable, do it the usual way. + + if not ep.attrs or ep.extras: + raise DistutilsSetupError( + "eggsecutable entry point (%r) cannot have 'extras' " + "or refer to a module" % (ep,) + ) + + pyver = sys.version[:3] + pkg = ep.module_name + full = '.'.join(ep.attrs) + base = ep.attrs[0] + basename = os.path.basename(self.egg_output) + + header = ( + "#!/bin/sh\n" + 'if [ `basename $0` = "%(basename)s" ]\n' + 'then exec python%(pyver)s -c "' + "import sys, os; sys.path.insert(0, os.path.abspath('$0')); " + "from %(pkg)s import %(base)s; sys.exit(%(full)s())" + '" "$@"\n' + 'else\n' + ' echo $0 is not the correct name for this egg file.\n' + ' echo Please rename it back to %(basename)s and try again.\n' + ' exec false\n' + 'fi\n' + ) % locals() + + if not self.dry_run: + mkpath(os.path.dirname(self.egg_output), dry_run=self.dry_run) + f = open(self.egg_output, 'w') + f.write(header) + f.close() + return 'a' + + def copy_metadata_to(self, target_dir): + "Copy metadata (egg info) to the target_dir" + # normalize the path (so that a forward-slash in egg_info will + # match using startswith below) + norm_egg_info = os.path.normpath(self.egg_info) + prefix = os.path.join(norm_egg_info, '') + for path in self.ei_cmd.filelist.files: + if path.startswith(prefix): + target = os.path.join(target_dir, path[len(prefix):]) + ensure_directory(target) + self.copy_file(path, target) + + def get_ext_outputs(self): + """Get a list of relative paths to C extensions in the output distro""" + + all_outputs = [] + ext_outputs = [] + + paths = {self.bdist_dir: ''} + for base, dirs, files in sorted_walk(self.bdist_dir): + for filename in files: + if os.path.splitext(filename)[1].lower() in NATIVE_EXTENSIONS: + all_outputs.append(paths[base] + filename) + for filename in dirs: + paths[os.path.join(base, filename)] = (paths[base] + + filename + '/') + + if self.distribution.has_ext_modules(): + build_cmd = self.get_finalized_command('build_ext') + for ext in build_cmd.extensions: + if isinstance(ext, Library): + continue + fullname = build_cmd.get_ext_fullname(ext.name) + filename = build_cmd.get_ext_filename(fullname) + if not os.path.basename(filename).startswith('dl-'): + if os.path.exists(os.path.join(self.bdist_dir, filename)): + ext_outputs.append(filename) + + return all_outputs, ext_outputs + + +NATIVE_EXTENSIONS = dict.fromkeys('.dll .so .dylib .pyd'.split()) + + +def walk_egg(egg_dir): + """Walk an unpacked egg's contents, skipping the metadata directory""" + walker = sorted_walk(egg_dir) + base, dirs, files = next(walker) + if 'EGG-INFO' in dirs: + dirs.remove('EGG-INFO') + yield base, dirs, files + for bdf in walker: + yield bdf + + +def analyze_egg(egg_dir, stubs): + # check for existing flag in EGG-INFO + for flag, fn in safety_flags.items(): + if os.path.exists(os.path.join(egg_dir, 'EGG-INFO', fn)): + return flag + if not can_scan(): + return False + safe = True + for base, dirs, files in walk_egg(egg_dir): + for name in files: + if name.endswith('.py') or name.endswith('.pyw'): + continue + elif name.endswith('.pyc') or name.endswith('.pyo'): + # always scan, even if we already know we're not safe + safe = scan_module(egg_dir, base, name, stubs) and safe + return safe + + +def write_safety_flag(egg_dir, safe): + # Write or remove zip safety flag file(s) + for flag, fn in safety_flags.items(): + fn = os.path.join(egg_dir, fn) + if os.path.exists(fn): + if safe is None or bool(safe) != flag: + os.unlink(fn) + elif safe is not None and bool(safe) == flag: + f = open(fn, 'wt') + f.write('\n') + f.close() + + +safety_flags = { + True: 'zip-safe', + False: 'not-zip-safe', +} + + +def scan_module(egg_dir, base, name, stubs): + """Check whether module possibly uses unsafe-for-zipfile stuff""" + + filename = os.path.join(base, name) + if filename[:-1] in stubs: + return True # Extension module + pkg = base[len(egg_dir) + 1:].replace(os.sep, '.') + module = pkg + (pkg and '.' or '') + os.path.splitext(name)[0] + if six.PY2: + skip = 8 # skip magic & date + elif sys.version_info < (3, 7): + skip = 12 # skip magic & date & file size + else: + skip = 16 # skip magic & reserved? & date & file size + f = open(filename, 'rb') + f.read(skip) + code = marshal.load(f) + f.close() + safe = True + symbols = dict.fromkeys(iter_symbols(code)) + for bad in ['__file__', '__path__']: + if bad in symbols: + log.warn("%s: module references %s", module, bad) + safe = False + if 'inspect' in symbols: + for bad in [ + 'getsource', 'getabsfile', 'getsourcefile', 'getfile' + 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', + 'getinnerframes', 'getouterframes', 'stack', 'trace' + ]: + if bad in symbols: + log.warn("%s: module MAY be using inspect.%s", module, bad) + safe = False + return safe + + +def iter_symbols(code): + """Yield names and strings used by `code` and its nested code objects""" + for name in code.co_names: + yield name + for const in code.co_consts: + if isinstance(const, six.string_types): + yield const + elif isinstance(const, CodeType): + for name in iter_symbols(const): + yield name + + +def can_scan(): + if not sys.platform.startswith('java') and sys.platform != 'cli': + # CPython, PyPy, etc. + return True + log.warn("Unable to analyze compiled code on this platform.") + log.warn("Please ask the author to include a 'zip_safe'" + " setting (either True or False) in the package's setup.py") + + +# Attribute names of options for commands that might need to be convinced to +# install to the egg build directory + +INSTALL_DIRECTORY_ATTRS = [ + 'install_lib', 'install_dir', 'install_data', 'install_base' +] + + +def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True, + mode='w'): + """Create a zip file from all the files under 'base_dir'. The output + zip file will be named 'base_dir' + ".zip". Uses either the "zipfile" + Python module (if available) or the InfoZIP "zip" utility (if installed + and found on the default search path). If neither tool is available, + raises DistutilsExecError. Returns the name of the output zip file. + """ + import zipfile + + mkpath(os.path.dirname(zip_filename), dry_run=dry_run) + log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir) + + def visit(z, dirname, names): + for name in names: + path = os.path.normpath(os.path.join(dirname, name)) + if os.path.isfile(path): + p = path[len(base_dir) + 1:] + if not dry_run: + z.write(path, p) + log.debug("adding '%s'", p) + + compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED + if not dry_run: + z = zipfile.ZipFile(zip_filename, mode, compression=compression) + for dirname, dirs, files in sorted_walk(base_dir): + visit(z, dirname, files) + z.close() + else: + for dirname, dirs, files in sorted_walk(base_dir): + visit(None, dirname, files) + return zip_filename diff --git a/winvenv/Lib/site-packages/setuptools/command/bdist_rpm.py b/winvenv/Lib/site-packages/setuptools/command/bdist_rpm.py new file mode 100644 index 0000000..7073092 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/bdist_rpm.py @@ -0,0 +1,43 @@ +import distutils.command.bdist_rpm as orig + + +class bdist_rpm(orig.bdist_rpm): + """ + Override the default bdist_rpm behavior to do the following: + + 1. Run egg_info to ensure the name and version are properly calculated. + 2. Always run 'install' using --single-version-externally-managed to + disable eggs in RPM distributions. + 3. Replace dash with underscore in the version numbers for better RPM + compatibility. + """ + + def run(self): + # ensure distro name is up-to-date + self.run_command('egg_info') + + orig.bdist_rpm.run(self) + + def _make_spec_file(self): + version = self.distribution.get_version() + rpmversion = version.replace('-', '_') + spec = orig.bdist_rpm._make_spec_file(self) + line23 = '%define version ' + version + line24 = '%define version ' + rpmversion + spec = [ + line.replace( + "Source0: %{name}-%{version}.tar", + "Source0: %{name}-%{unmangled_version}.tar" + ).replace( + "setup.py install ", + "setup.py install --single-version-externally-managed " + ).replace( + "%setup", + "%setup -n %{name}-%{unmangled_version}" + ).replace(line23, line24) + for line in spec + ] + insert_loc = spec.index(line24) + 1 + unmangled_version = "%define unmangled_version " + version + spec.insert(insert_loc, unmangled_version) + return spec diff --git a/winvenv/Lib/site-packages/setuptools/command/bdist_wininst.py b/winvenv/Lib/site-packages/setuptools/command/bdist_wininst.py new file mode 100644 index 0000000..073de97 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/bdist_wininst.py @@ -0,0 +1,21 @@ +import distutils.command.bdist_wininst as orig + + +class bdist_wininst(orig.bdist_wininst): + def reinitialize_command(self, command, reinit_subcommands=0): + """ + Supplement reinitialize_command to work around + http://bugs.python.org/issue20819 + """ + cmd = self.distribution.reinitialize_command( + command, reinit_subcommands) + if command in ('install', 'install_lib'): + cmd.install_lib = None + return cmd + + def run(self): + self._is_running = True + try: + orig.bdist_wininst.run(self) + finally: + self._is_running = False diff --git a/winvenv/Lib/site-packages/setuptools/command/build_clib.py b/winvenv/Lib/site-packages/setuptools/command/build_clib.py new file mode 100644 index 0000000..09caff6 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/build_clib.py @@ -0,0 +1,98 @@ +import distutils.command.build_clib as orig +from distutils.errors import DistutilsSetupError +from distutils import log +from setuptools.dep_util import newer_pairwise_group + + +class build_clib(orig.build_clib): + """ + Override the default build_clib behaviour to do the following: + + 1. Implement a rudimentary timestamp-based dependency system + so 'compile()' doesn't run every time. + 2. Add more keys to the 'build_info' dictionary: + * obj_deps - specify dependencies for each object compiled. + this should be a dictionary mapping a key + with the source filename to a list of + dependencies. Use an empty string for global + dependencies. + * cflags - specify a list of additional flags to pass to + the compiler. + """ + + def build_libraries(self, libraries): + for (lib_name, build_info) in libraries: + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % lib_name) + sources = list(sources) + + log.info("building '%s' library", lib_name) + + # Make sure everything is the correct type. + # obj_deps should be a dictionary of keys as sources + # and a list/tuple of files that are its dependencies. + obj_deps = build_info.get('obj_deps', dict()) + if not isinstance(obj_deps, dict): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + dependencies = [] + + # Get the global dependencies that are specified by the '' key. + # These will go into every source's dependency list. + global_deps = obj_deps.get('', list()) + if not isinstance(global_deps, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + + # Build the list to be used by newer_pairwise_group + # each source will be auto-added to its dependencies. + for source in sources: + src_deps = [source] + src_deps.extend(global_deps) + extra_deps = obj_deps.get(source, list()) + if not isinstance(extra_deps, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + src_deps.extend(extra_deps) + dependencies.append(src_deps) + + expected_objects = self.compiler.object_filenames( + sources, + output_dir=self.build_temp + ) + + if newer_pairwise_group(dependencies, expected_objects) != ([], []): + # First, compile the source code to object files in the library + # directory. (This should probably change to putting object + # files in a temporary build directory.) + macros = build_info.get('macros') + include_dirs = build_info.get('include_dirs') + cflags = build_info.get('cflags') + objects = self.compiler.compile( + sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=include_dirs, + extra_postargs=cflags, + debug=self.debug + ) + + # Now "link" the object files together into a static library. + # (On Unix at least, this isn't really linking -- it just + # builds an archive. Whatever.) + self.compiler.create_static_lib( + expected_objects, + lib_name, + output_dir=self.build_clib, + debug=self.debug + ) diff --git a/winvenv/Lib/site-packages/setuptools/command/build_ext.py b/winvenv/Lib/site-packages/setuptools/command/build_ext.py new file mode 100644 index 0000000..60a8a32 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/build_ext.py @@ -0,0 +1,321 @@ +import os +import sys +import itertools +import imp +from distutils.command.build_ext import build_ext as _du_build_ext +from distutils.file_util import copy_file +from distutils.ccompiler import new_compiler +from distutils.sysconfig import customize_compiler, get_config_var +from distutils.errors import DistutilsError +from distutils import log + +from setuptools.extension import Library +from setuptools.extern import six + +try: + # Attempt to use Cython for building extensions, if available + from Cython.Distutils.build_ext import build_ext as _build_ext + # Additionally, assert that the compiler module will load + # also. Ref #1229. + __import__('Cython.Compiler.Main') +except ImportError: + _build_ext = _du_build_ext + +# make sure _config_vars is initialized +get_config_var("LDSHARED") +from distutils.sysconfig import _config_vars as _CONFIG_VARS + + +def _customize_compiler_for_shlib(compiler): + if sys.platform == "darwin": + # building .dylib requires additional compiler flags on OSX; here we + # temporarily substitute the pyconfig.h variables so that distutils' + # 'customize_compiler' uses them before we build the shared libraries. + tmp = _CONFIG_VARS.copy() + try: + # XXX Help! I don't have any idea whether these are right... + _CONFIG_VARS['LDSHARED'] = ( + "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup") + _CONFIG_VARS['CCSHARED'] = " -dynamiclib" + _CONFIG_VARS['SO'] = ".dylib" + customize_compiler(compiler) + finally: + _CONFIG_VARS.clear() + _CONFIG_VARS.update(tmp) + else: + customize_compiler(compiler) + + +have_rtld = False +use_stubs = False +libtype = 'shared' + +if sys.platform == "darwin": + use_stubs = True +elif os.name != 'nt': + try: + import dl + use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW') + except ImportError: + pass + +if_dl = lambda s: s if have_rtld else '' + + +def get_abi3_suffix(): + """Return the file extension for an abi3-compliant Extension()""" + for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION): + if '.abi3' in suffix: # Unix + return suffix + elif suffix == '.pyd': # Windows + return suffix + + +class build_ext(_build_ext): + def run(self): + """Build extensions in build directory, then copy if --inplace""" + old_inplace, self.inplace = self.inplace, 0 + _build_ext.run(self) + self.inplace = old_inplace + if old_inplace: + self.copy_extensions_to_source() + + def copy_extensions_to_source(self): + build_py = self.get_finalized_command('build_py') + for ext in self.extensions: + fullname = self.get_ext_fullname(ext.name) + filename = self.get_ext_filename(fullname) + modpath = fullname.split('.') + package = '.'.join(modpath[:-1]) + package_dir = build_py.get_package_dir(package) + dest_filename = os.path.join(package_dir, + os.path.basename(filename)) + src_filename = os.path.join(self.build_lib, filename) + + # Always copy, even if source is older than destination, to ensure + # that the right extensions for the current Python/platform are + # used. + copy_file( + src_filename, dest_filename, verbose=self.verbose, + dry_run=self.dry_run + ) + if ext._needs_stub: + self.write_stub(package_dir or os.curdir, ext, True) + + def get_ext_filename(self, fullname): + filename = _build_ext.get_ext_filename(self, fullname) + if fullname in self.ext_map: + ext = self.ext_map[fullname] + use_abi3 = ( + six.PY3 + and getattr(ext, 'py_limited_api') + and get_abi3_suffix() + ) + if use_abi3: + so_ext = get_config_var('EXT_SUFFIX') + filename = filename[:-len(so_ext)] + filename = filename + get_abi3_suffix() + if isinstance(ext, Library): + fn, ext = os.path.splitext(filename) + return self.shlib_compiler.library_filename(fn, libtype) + elif use_stubs and ext._links_to_dynamic: + d, fn = os.path.split(filename) + return os.path.join(d, 'dl-' + fn) + return filename + + def initialize_options(self): + _build_ext.initialize_options(self) + self.shlib_compiler = None + self.shlibs = [] + self.ext_map = {} + + def finalize_options(self): + _build_ext.finalize_options(self) + self.extensions = self.extensions or [] + self.check_extensions_list(self.extensions) + self.shlibs = [ext for ext in self.extensions + if isinstance(ext, Library)] + if self.shlibs: + self.setup_shlib_compiler() + for ext in self.extensions: + ext._full_name = self.get_ext_fullname(ext.name) + for ext in self.extensions: + fullname = ext._full_name + self.ext_map[fullname] = ext + + # distutils 3.1 will also ask for module names + # XXX what to do with conflicts? + self.ext_map[fullname.split('.')[-1]] = ext + + ltd = self.shlibs and self.links_to_dynamic(ext) or False + ns = ltd and use_stubs and not isinstance(ext, Library) + ext._links_to_dynamic = ltd + ext._needs_stub = ns + filename = ext._file_name = self.get_ext_filename(fullname) + libdir = os.path.dirname(os.path.join(self.build_lib, filename)) + if ltd and libdir not in ext.library_dirs: + ext.library_dirs.append(libdir) + if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs: + ext.runtime_library_dirs.append(os.curdir) + + def setup_shlib_compiler(self): + compiler = self.shlib_compiler = new_compiler( + compiler=self.compiler, dry_run=self.dry_run, force=self.force + ) + _customize_compiler_for_shlib(compiler) + + if self.include_dirs is not None: + compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name, value) in self.define: + compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + compiler.undefine_macro(macro) + if self.libraries is not None: + compiler.set_libraries(self.libraries) + if self.library_dirs is not None: + compiler.set_library_dirs(self.library_dirs) + if self.rpath is not None: + compiler.set_runtime_library_dirs(self.rpath) + if self.link_objects is not None: + compiler.set_link_objects(self.link_objects) + + # hack so distutils' build_extension() builds a library instead + compiler.link_shared_object = link_shared_object.__get__(compiler) + + def get_export_symbols(self, ext): + if isinstance(ext, Library): + return ext.export_symbols + return _build_ext.get_export_symbols(self, ext) + + def build_extension(self, ext): + ext._convert_pyx_sources_to_lang() + _compiler = self.compiler + try: + if isinstance(ext, Library): + self.compiler = self.shlib_compiler + _build_ext.build_extension(self, ext) + if ext._needs_stub: + cmd = self.get_finalized_command('build_py').build_lib + self.write_stub(cmd, ext) + finally: + self.compiler = _compiler + + def links_to_dynamic(self, ext): + """Return true if 'ext' links to a dynamic lib in the same package""" + # XXX this should check to ensure the lib is actually being built + # XXX as dynamic, and not just using a locally-found version or a + # XXX static-compiled version + libnames = dict.fromkeys([lib._full_name for lib in self.shlibs]) + pkg = '.'.join(ext._full_name.split('.')[:-1] + ['']) + return any(pkg + libname in libnames for libname in ext.libraries) + + def get_outputs(self): + return _build_ext.get_outputs(self) + self.__get_stubs_outputs() + + def __get_stubs_outputs(self): + # assemble the base name for each extension that needs a stub + ns_ext_bases = ( + os.path.join(self.build_lib, *ext._full_name.split('.')) + for ext in self.extensions + if ext._needs_stub + ) + # pair each base with the extension + pairs = itertools.product(ns_ext_bases, self.__get_output_extensions()) + return list(base + fnext for base, fnext in pairs) + + def __get_output_extensions(self): + yield '.py' + yield '.pyc' + if self.get_finalized_command('build_py').optimize: + yield '.pyo' + + def write_stub(self, output_dir, ext, compile=False): + log.info("writing stub loader for %s to %s", ext._full_name, + output_dir) + stub_file = (os.path.join(output_dir, *ext._full_name.split('.')) + + '.py') + if compile and os.path.exists(stub_file): + raise DistutilsError(stub_file + " already exists! Please delete.") + if not self.dry_run: + f = open(stub_file, 'w') + f.write( + '\n'.join([ + "def __bootstrap__():", + " global __bootstrap__, __file__, __loader__", + " import sys, os, pkg_resources, imp" + if_dl(", dl"), + " __file__ = pkg_resources.resource_filename" + "(__name__,%r)" + % os.path.basename(ext._file_name), + " del __bootstrap__", + " if '__loader__' in globals():", + " del __loader__", + if_dl(" old_flags = sys.getdlopenflags()"), + " old_dir = os.getcwd()", + " try:", + " os.chdir(os.path.dirname(__file__))", + if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"), + " imp.load_dynamic(__name__,__file__)", + " finally:", + if_dl(" sys.setdlopenflags(old_flags)"), + " os.chdir(old_dir)", + "__bootstrap__()", + "" # terminal \n + ]) + ) + f.close() + if compile: + from distutils.util import byte_compile + + byte_compile([stub_file], optimize=0, + force=True, dry_run=self.dry_run) + optimize = self.get_finalized_command('install_lib').optimize + if optimize > 0: + byte_compile([stub_file], optimize=optimize, + force=True, dry_run=self.dry_run) + if os.path.exists(stub_file) and not self.dry_run: + os.unlink(stub_file) + + +if use_stubs or os.name == 'nt': + # Build shared libraries + # + def link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + self.link( + self.SHARED_LIBRARY, objects, output_libname, + output_dir, libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, extra_preargs, extra_postargs, + build_temp, target_lang + ) +else: + # Build static libraries everywhere else + libtype = 'static' + + def link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + # XXX we need to either disallow these attrs on Library instances, + # or warn/abort here if set, or something... + # libraries=None, library_dirs=None, runtime_library_dirs=None, + # export_symbols=None, extra_preargs=None, extra_postargs=None, + # build_temp=None + + assert output_dir is None # distutils build_ext doesn't pass this + output_dir, filename = os.path.split(output_libname) + basename, ext = os.path.splitext(filename) + if self.library_filename("x").startswith('lib'): + # strip 'lib' prefix; this is kludgy if some platform uses + # a different prefix + basename = basename[3:] + + self.create_static_lib( + objects, basename, output_dir, debug, target_lang + ) diff --git a/winvenv/Lib/site-packages/setuptools/command/build_py.py b/winvenv/Lib/site-packages/setuptools/command/build_py.py new file mode 100644 index 0000000..b0314fd --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/build_py.py @@ -0,0 +1,270 @@ +from glob import glob +from distutils.util import convert_path +import distutils.command.build_py as orig +import os +import fnmatch +import textwrap +import io +import distutils.errors +import itertools + +from setuptools.extern import six +from setuptools.extern.six.moves import map, filter, filterfalse + +try: + from setuptools.lib2to3_ex import Mixin2to3 +except ImportError: + + class Mixin2to3: + def run_2to3(self, files, doctests=True): + "do nothing" + + +class build_py(orig.build_py, Mixin2to3): + """Enhanced 'build_py' command that includes data files with packages + + The data files are specified via a 'package_data' argument to 'setup()'. + See 'setuptools.dist.Distribution' for more details. + + Also, this version of the 'build_py' command allows you to specify both + 'py_modules' and 'packages' in the same setup operation. + """ + + def finalize_options(self): + orig.build_py.finalize_options(self) + self.package_data = self.distribution.package_data + self.exclude_package_data = (self.distribution.exclude_package_data or + {}) + if 'data_files' in self.__dict__: + del self.__dict__['data_files'] + self.__updated_files = [] + self.__doctests_2to3 = [] + + def run(self): + """Build modules, packages, and copy data files to build directory""" + if not self.py_modules and not self.packages: + return + + if self.py_modules: + self.build_modules() + + if self.packages: + self.build_packages() + self.build_package_data() + + self.run_2to3(self.__updated_files, False) + self.run_2to3(self.__updated_files, True) + self.run_2to3(self.__doctests_2to3, True) + + # Only compile actual .py files, using our base class' idea of what our + # output files are. + self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0)) + + def __getattr__(self, attr): + "lazily compute data files" + if attr == 'data_files': + self.data_files = self._get_data_files() + return self.data_files + return orig.build_py.__getattr__(self, attr) + + def build_module(self, module, module_file, package): + if six.PY2 and isinstance(package, six.string_types): + # avoid errors on Python 2 when unicode is passed (#190) + package = package.split('.') + outfile, copied = orig.build_py.build_module(self, module, module_file, + package) + if copied: + self.__updated_files.append(outfile) + return outfile, copied + + def _get_data_files(self): + """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" + self.analyze_manifest() + return list(map(self._get_pkg_data_files, self.packages or ())) + + def _get_pkg_data_files(self, package): + # Locate package source directory + src_dir = self.get_package_dir(package) + + # Compute package build directory + build_dir = os.path.join(*([self.build_lib] + package.split('.'))) + + # Strip directory from globbed filenames + filenames = [ + os.path.relpath(file, src_dir) + for file in self.find_data_files(package, src_dir) + ] + return package, src_dir, build_dir, filenames + + def find_data_files(self, package, src_dir): + """Return filenames for package's data files in 'src_dir'""" + patterns = self._get_platform_patterns( + self.package_data, + package, + src_dir, + ) + globs_expanded = map(glob, patterns) + # flatten the expanded globs into an iterable of matches + globs_matches = itertools.chain.from_iterable(globs_expanded) + glob_files = filter(os.path.isfile, globs_matches) + files = itertools.chain( + self.manifest_files.get(package, []), + glob_files, + ) + return self.exclude_data_files(package, src_dir, files) + + def build_package_data(self): + """Copy data files into build directory""" + for package, src_dir, build_dir, filenames in self.data_files: + for filename in filenames: + target = os.path.join(build_dir, filename) + self.mkpath(os.path.dirname(target)) + srcfile = os.path.join(src_dir, filename) + outf, copied = self.copy_file(srcfile, target) + srcfile = os.path.abspath(srcfile) + if (copied and + srcfile in self.distribution.convert_2to3_doctests): + self.__doctests_2to3.append(outf) + + def analyze_manifest(self): + self.manifest_files = mf = {} + if not self.distribution.include_package_data: + return + src_dirs = {} + for package in self.packages or (): + # Locate package source directory + src_dirs[assert_relative(self.get_package_dir(package))] = package + + self.run_command('egg_info') + ei_cmd = self.get_finalized_command('egg_info') + for path in ei_cmd.filelist.files: + d, f = os.path.split(assert_relative(path)) + prev = None + oldf = f + while d and d != prev and d not in src_dirs: + prev = d + d, df = os.path.split(d) + f = os.path.join(df, f) + if d in src_dirs: + if path.endswith('.py') and f == oldf: + continue # it's a module, not data + mf.setdefault(src_dirs[d], []).append(path) + + def get_data_files(self): + pass # Lazily compute data files in _get_data_files() function. + + def check_package(self, package, package_dir): + """Check namespace packages' __init__ for declare_namespace""" + try: + return self.packages_checked[package] + except KeyError: + pass + + init_py = orig.build_py.check_package(self, package, package_dir) + self.packages_checked[package] = init_py + + if not init_py or not self.distribution.namespace_packages: + return init_py + + for pkg in self.distribution.namespace_packages: + if pkg == package or pkg.startswith(package + '.'): + break + else: + return init_py + + with io.open(init_py, 'rb') as f: + contents = f.read() + if b'declare_namespace' not in contents: + raise distutils.errors.DistutilsError( + "Namespace package problem: %s is a namespace package, but " + "its\n__init__.py does not call declare_namespace()! Please " + 'fix it.\n(See the setuptools manual under ' + '"Namespace Packages" for details.)\n"' % (package,) + ) + return init_py + + def initialize_options(self): + self.packages_checked = {} + orig.build_py.initialize_options(self) + + def get_package_dir(self, package): + res = orig.build_py.get_package_dir(self, package) + if self.distribution.src_root is not None: + return os.path.join(self.distribution.src_root, res) + return res + + def exclude_data_files(self, package, src_dir, files): + """Filter filenames for package's data files in 'src_dir'""" + files = list(files) + patterns = self._get_platform_patterns( + self.exclude_package_data, + package, + src_dir, + ) + match_groups = ( + fnmatch.filter(files, pattern) + for pattern in patterns + ) + # flatten the groups of matches into an iterable of matches + matches = itertools.chain.from_iterable(match_groups) + bad = set(matches) + keepers = ( + fn + for fn in files + if fn not in bad + ) + # ditch dupes + return list(_unique_everseen(keepers)) + + @staticmethod + def _get_platform_patterns(spec, package, src_dir): + """ + yield platform-specific path patterns (suitable for glob + or fn_match) from a glob-based spec (such as + self.package_data or self.exclude_package_data) + matching package in src_dir. + """ + raw_patterns = itertools.chain( + spec.get('', []), + spec.get(package, []), + ) + return ( + # Each pattern has to be converted to a platform-specific path + os.path.join(src_dir, convert_path(pattern)) + for pattern in raw_patterns + ) + + +# from Python docs +def _unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +def assert_relative(path): + if not os.path.isabs(path): + return path + from distutils.errors import DistutilsSetupError + + msg = textwrap.dedent(""" + Error: setup script specifies an absolute path: + + %s + + setup() arguments must *always* be /-separated paths relative to the + setup.py directory, *never* absolute paths. + """).lstrip() % path + raise DistutilsSetupError(msg) diff --git a/winvenv/Lib/site-packages/setuptools/command/develop.py b/winvenv/Lib/site-packages/setuptools/command/develop.py new file mode 100644 index 0000000..fdc9fc4 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/develop.py @@ -0,0 +1,218 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsError, DistutilsOptionError +import os +import glob +import io + +from setuptools.extern import six + +from pkg_resources import Distribution, PathMetadata, normalize_path +from setuptools.command.easy_install import easy_install +from setuptools import namespaces +import setuptools + +__metaclass__ = type + + +class develop(namespaces.DevelopInstaller, easy_install): + """Set up package for development""" + + description = "install package in 'development mode'" + + user_options = easy_install.user_options + [ + ("uninstall", "u", "Uninstall this source package"), + ("egg-path=", None, "Set the path to be used in the .egg-link file"), + ] + + boolean_options = easy_install.boolean_options + ['uninstall'] + + command_consumes_arguments = False # override base + + def run(self): + if self.uninstall: + self.multi_version = True + self.uninstall_link() + self.uninstall_namespaces() + else: + self.install_for_development() + self.warn_deprecated_options() + + def initialize_options(self): + self.uninstall = None + self.egg_path = None + easy_install.initialize_options(self) + self.setup_path = None + self.always_copy_from = '.' # always copy eggs installed in curdir + + def finalize_options(self): + ei = self.get_finalized_command("egg_info") + if ei.broken_egg_info: + template = "Please rename %r to %r before using 'develop'" + args = ei.egg_info, ei.broken_egg_info + raise DistutilsError(template % args) + self.args = [ei.egg_name] + + easy_install.finalize_options(self) + self.expand_basedirs() + self.expand_dirs() + # pick up setup-dir .egg files only: no .egg-info + self.package_index.scan(glob.glob('*.egg')) + + egg_link_fn = ei.egg_name + '.egg-link' + self.egg_link = os.path.join(self.install_dir, egg_link_fn) + self.egg_base = ei.egg_base + if self.egg_path is None: + self.egg_path = os.path.abspath(ei.egg_base) + + target = normalize_path(self.egg_base) + egg_path = normalize_path(os.path.join(self.install_dir, + self.egg_path)) + if egg_path != target: + raise DistutilsOptionError( + "--egg-path must be a relative path from the install" + " directory to " + target + ) + + # Make a distribution for the package's source + self.dist = Distribution( + target, + PathMetadata(target, os.path.abspath(ei.egg_info)), + project_name=ei.egg_name + ) + + self.setup_path = self._resolve_setup_path( + self.egg_base, + self.install_dir, + self.egg_path, + ) + + @staticmethod + def _resolve_setup_path(egg_base, install_dir, egg_path): + """ + Generate a path from egg_base back to '.' where the + setup script resides and ensure that path points to the + setup path from $install_dir/$egg_path. + """ + path_to_setup = egg_base.replace(os.sep, '/').rstrip('/') + if path_to_setup != os.curdir: + path_to_setup = '../' * (path_to_setup.count('/') + 1) + resolved = normalize_path( + os.path.join(install_dir, egg_path, path_to_setup) + ) + if resolved != normalize_path(os.curdir): + raise DistutilsOptionError( + "Can't get a consistent path to setup script from" + " installation directory", resolved, normalize_path(os.curdir)) + return path_to_setup + + def install_for_development(self): + if six.PY3 and getattr(self.distribution, 'use_2to3', False): + # If we run 2to3 we can not do this inplace: + + # Ensure metadata is up-to-date + self.reinitialize_command('build_py', inplace=0) + self.run_command('build_py') + bpy_cmd = self.get_finalized_command("build_py") + build_path = normalize_path(bpy_cmd.build_lib) + + # Build extensions + self.reinitialize_command('egg_info', egg_base=build_path) + self.run_command('egg_info') + + self.reinitialize_command('build_ext', inplace=0) + self.run_command('build_ext') + + # Fixup egg-link and easy-install.pth + ei_cmd = self.get_finalized_command("egg_info") + self.egg_path = build_path + self.dist.location = build_path + # XXX + self.dist._provider = PathMetadata(build_path, ei_cmd.egg_info) + else: + # Without 2to3 inplace works fine: + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + + self.install_site_py() # ensure that target dir is site-safe + if setuptools.bootstrap_install_from: + self.easy_install(setuptools.bootstrap_install_from) + setuptools.bootstrap_install_from = None + + self.install_namespaces() + + # create an .egg-link in the installation dir, pointing to our egg + log.info("Creating %s (link to %s)", self.egg_link, self.egg_base) + if not self.dry_run: + with open(self.egg_link, "w") as f: + f.write(self.egg_path + "\n" + self.setup_path) + # postprocess the installed distro, fixing up .pth, installing scripts, + # and handling requirements + self.process_distribution(None, self.dist, not self.no_deps) + + def uninstall_link(self): + if os.path.exists(self.egg_link): + log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) + egg_link_file = open(self.egg_link) + contents = [line.rstrip() for line in egg_link_file] + egg_link_file.close() + if contents not in ([self.egg_path], + [self.egg_path, self.setup_path]): + log.warn("Link points to %s: uninstall aborted", contents) + return + if not self.dry_run: + os.unlink(self.egg_link) + if not self.dry_run: + self.update_pth(self.dist) # remove any .pth link to us + if self.distribution.scripts: + # XXX should also check for entry point scripts! + log.warn("Note: you must uninstall or replace scripts manually!") + + def install_egg_scripts(self, dist): + if dist is not self.dist: + # Installing a dependency, so fall back to normal behavior + return easy_install.install_egg_scripts(self, dist) + + # create wrapper scripts in the script dir, pointing to dist.scripts + + # new-style... + self.install_wrapper_scripts(dist) + + # ...and old-style + for script_name in self.distribution.scripts or []: + script_path = os.path.abspath(convert_path(script_name)) + script_name = os.path.basename(script_path) + with io.open(script_path) as strm: + script_text = strm.read() + self.install_script(dist, script_name, script_text, script_path) + + def install_wrapper_scripts(self, dist): + dist = VersionlessRequirement(dist) + return easy_install.install_wrapper_scripts(self, dist) + + +class VersionlessRequirement: + """ + Adapt a pkg_resources.Distribution to simply return the project + name as the 'requirement' so that scripts will work across + multiple versions. + + >>> dist = Distribution(project_name='foo', version='1.0') + >>> str(dist.as_requirement()) + 'foo==1.0' + >>> adapted_dist = VersionlessRequirement(dist) + >>> str(adapted_dist.as_requirement()) + 'foo' + """ + + def __init__(self, dist): + self.__dist = dist + + def __getattr__(self, name): + return getattr(self.__dist, name) + + def as_requirement(self): + return self.project_name diff --git a/winvenv/Lib/site-packages/setuptools/command/dist_info.py b/winvenv/Lib/site-packages/setuptools/command/dist_info.py new file mode 100644 index 0000000..c45258f --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/dist_info.py @@ -0,0 +1,36 @@ +""" +Create a dist_info directory +As defined in the wheel specification +""" + +import os + +from distutils.core import Command +from distutils import log + + +class dist_info(Command): + + description = 'create a .dist-info directory' + + user_options = [ + ('egg-base=', 'e', "directory containing .egg-info directories" + " (default: top of the source tree)"), + ] + + def initialize_options(self): + self.egg_base = None + + def finalize_options(self): + pass + + def run(self): + egg_info = self.get_finalized_command('egg_info') + egg_info.egg_base = self.egg_base + egg_info.finalize_options() + egg_info.run() + dist_info_dir = egg_info.egg_info[:-len('.egg-info')] + '.dist-info' + log.info("creating '{}'".format(os.path.abspath(dist_info_dir))) + + bdist_wheel = self.get_finalized_command('bdist_wheel') + bdist_wheel.egg2dist(egg_info.egg_info, dist_info_dir) diff --git a/winvenv/Lib/site-packages/setuptools/command/easy_install.py b/winvenv/Lib/site-packages/setuptools/command/easy_install.py new file mode 100644 index 0000000..06c9827 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/easy_install.py @@ -0,0 +1,2342 @@ +#!/usr/bin/env python +""" +Easy Install +------------ + +A tool for doing automatic download/extract/build of distutils-based Python +packages. For detailed documentation, see the accompanying EasyInstall.txt +file, or visit the `EasyInstall home page`__. + +__ https://setuptools.readthedocs.io/en/latest/easy_install.html + +""" + +from glob import glob +from distutils.util import get_platform +from distutils.util import convert_path, subst_vars +from distutils.errors import ( + DistutilsArgError, DistutilsOptionError, + DistutilsError, DistutilsPlatformError, +) +from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS +from distutils import log, dir_util +from distutils.command.build_scripts import first_line_re +from distutils.spawn import find_executable +import sys +import os +import zipimport +import shutil +import tempfile +import zipfile +import re +import stat +import random +import textwrap +import warnings +import site +import struct +import contextlib +import subprocess +import shlex +import io + + +from sysconfig import get_config_vars, get_path + +from setuptools import SetuptoolsDeprecationWarning + +from setuptools.extern import six +from setuptools.extern.six.moves import configparser, map + +from setuptools import Command +from setuptools.sandbox import run_setup +from setuptools.py27compat import rmtree_safe +from setuptools.command import setopt +from setuptools.archive_util import unpack_archive +from setuptools.package_index import ( + PackageIndex, parse_requirement_arg, URL_SCHEME, +) +from setuptools.command import bdist_egg, egg_info +from setuptools.wheel import Wheel +from pkg_resources import ( + yield_lines, normalize_path, resource_string, ensure_directory, + get_distribution, find_distributions, Environment, Requirement, + Distribution, PathMetadata, EggMetadata, WorkingSet, DistributionNotFound, + VersionConflict, DEVELOP_DIST, +) +import pkg_resources.py31compat + +__metaclass__ = type + +# Turn on PEP440Warnings +warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) + +__all__ = [ + 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', + 'main', 'get_exe_prefixes', +] + + +def is_64bit(): + return struct.calcsize("P") == 8 + + +def samefile(p1, p2): + """ + Determine if two paths reference the same file. + + Augments os.path.samefile to work on Windows and + suppresses errors if the path doesn't exist. + """ + both_exist = os.path.exists(p1) and os.path.exists(p2) + use_samefile = hasattr(os.path, 'samefile') and both_exist + if use_samefile: + return os.path.samefile(p1, p2) + norm_p1 = os.path.normpath(os.path.normcase(p1)) + norm_p2 = os.path.normpath(os.path.normcase(p2)) + return norm_p1 == norm_p2 + + +if six.PY2: + + def _to_bytes(s): + return s + + def isascii(s): + try: + six.text_type(s, 'ascii') + return True + except UnicodeError: + return False +else: + + def _to_bytes(s): + return s.encode('utf8') + + def isascii(s): + try: + s.encode('ascii') + return True + except UnicodeError: + return False + + +_one_liner = lambda text: textwrap.dedent(text).strip().replace('\n', '; ') + + +class easy_install(Command): + """Manage a download/build/install process""" + description = "Find/get/install Python packages" + command_consumes_arguments = True + + user_options = [ + ('prefix=', None, "installation prefix"), + ("zip-ok", "z", "install package as a zipfile"), + ("multi-version", "m", "make apps have to require() a version"), + ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), + ("install-dir=", "d", "install package to DIR"), + ("script-dir=", "s", "install scripts to DIR"), + ("exclude-scripts", "x", "Don't install scripts"), + ("always-copy", "a", "Copy all needed packages to install dir"), + ("index-url=", "i", "base URL of Python Package Index"), + ("find-links=", "f", "additional URL(s) to search for packages"), + ("build-directory=", "b", + "download/extract/build in DIR; keep the results"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('record=', None, + "filename in which to record list of installed files"), + ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), + ('site-dirs=', 'S', "list of directories where .pth files work"), + ('editable', 'e', "Install specified packages in editable form"), + ('no-deps', 'N', "don't install dependencies"), + ('allow-hosts=', 'H', "pattern(s) that hostnames must match"), + ('local-snapshots-ok', 'l', + "allow building eggs from local checkouts"), + ('version', None, "print version information and exit"), + ('no-find-links', None, + "Don't load find-links defined in packages being installed") + ] + boolean_options = [ + 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', + 'editable', + 'no-deps', 'local-snapshots-ok', 'version' + ] + + if site.ENABLE_USER_SITE: + help_msg = "install in user site-package '%s'" % site.USER_SITE + user_options.append(('user', None, help_msg)) + boolean_options.append('user') + + negative_opt = {'always-unzip': 'zip-ok'} + create_index = PackageIndex + + def initialize_options(self): + # the --user option seems to be an opt-in one, + # so the default should be False. + self.user = 0 + self.zip_ok = self.local_snapshots_ok = None + self.install_dir = self.script_dir = self.exclude_scripts = None + self.index_url = None + self.find_links = None + self.build_directory = None + self.args = None + self.optimize = self.record = None + self.upgrade = self.always_copy = self.multi_version = None + self.editable = self.no_deps = self.allow_hosts = None + self.root = self.prefix = self.no_report = None + self.version = None + self.install_purelib = None # for pure module distributions + self.install_platlib = None # non-pure (dists w/ extensions) + self.install_headers = None # for C/C++ headers + self.install_lib = None # set to either purelib or platlib + self.install_scripts = None + self.install_data = None + self.install_base = None + self.install_platbase = None + if site.ENABLE_USER_SITE: + self.install_userbase = site.USER_BASE + self.install_usersite = site.USER_SITE + else: + self.install_userbase = None + self.install_usersite = None + self.no_find_links = None + + # Options not specifiable via command line + self.package_index = None + self.pth_file = self.always_copy_from = None + self.site_dirs = None + self.installed_projects = {} + self.sitepy_installed = False + # Always read easy_install options, even if we are subclassed, or have + # an independent instance created. This ensures that defaults will + # always come from the standard configuration file(s)' "easy_install" + # section, even if this is a "develop" or "install" command, or some + # other embedding. + self._dry_run = None + self.verbose = self.distribution.verbose + self.distribution._set_command_options( + self, self.distribution.get_option_dict('easy_install') + ) + + def delete_blockers(self, blockers): + extant_blockers = ( + filename for filename in blockers + if os.path.exists(filename) or os.path.islink(filename) + ) + list(map(self._delete_path, extant_blockers)) + + def _delete_path(self, path): + log.info("Deleting %s", path) + if self.dry_run: + return + + is_tree = os.path.isdir(path) and not os.path.islink(path) + remover = rmtree if is_tree else os.unlink + remover(path) + + @staticmethod + def _render_version(): + """ + Render the Setuptools version and installation details, then exit. + """ + ver = sys.version[:3] + dist = get_distribution('setuptools') + tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})' + print(tmpl.format(**locals())) + raise SystemExit() + + def finalize_options(self): + self.version and self._render_version() + + py_version = sys.version.split()[0] + prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix') + + self.config_vars = { + 'dist_name': self.distribution.get_name(), + 'dist_version': self.distribution.get_version(), + 'dist_fullname': self.distribution.get_fullname(), + 'py_version': py_version, + 'py_version_short': py_version[0:3], + 'py_version_nodot': py_version[0] + py_version[2], + 'sys_prefix': prefix, + 'prefix': prefix, + 'sys_exec_prefix': exec_prefix, + 'exec_prefix': exec_prefix, + # Only python 3.2+ has abiflags + 'abiflags': getattr(sys, 'abiflags', ''), + } + + if site.ENABLE_USER_SITE: + self.config_vars['userbase'] = self.install_userbase + self.config_vars['usersite'] = self.install_usersite + + self._fix_install_dir_for_user_site() + + self.expand_basedirs() + self.expand_dirs() + + self._expand( + 'install_dir', 'script_dir', 'build_directory', + 'site_dirs', + ) + # If a non-default installation directory was specified, default the + # script directory to match it. + if self.script_dir is None: + self.script_dir = self.install_dir + + if self.no_find_links is None: + self.no_find_links = False + + # Let install_dir get set by install_lib command, which in turn + # gets its info from the install command, and takes into account + # --prefix and --home and all that other crud. + self.set_undefined_options( + 'install_lib', ('install_dir', 'install_dir') + ) + # Likewise, set default script_dir from 'install_scripts.install_dir' + self.set_undefined_options( + 'install_scripts', ('install_dir', 'script_dir') + ) + + if self.user and self.install_purelib: + self.install_dir = self.install_purelib + self.script_dir = self.install_scripts + # default --record from the install command + self.set_undefined_options('install', ('record', 'record')) + # Should this be moved to the if statement below? It's not used + # elsewhere + normpath = map(normalize_path, sys.path) + self.all_site_dirs = get_site_dirs() + if self.site_dirs is not None: + site_dirs = [ + os.path.expanduser(s.strip()) for s in + self.site_dirs.split(',') + ] + for d in site_dirs: + if not os.path.isdir(d): + log.warn("%s (in --site-dirs) does not exist", d) + elif normalize_path(d) not in normpath: + raise DistutilsOptionError( + d + " (in --site-dirs) is not on sys.path" + ) + else: + self.all_site_dirs.append(normalize_path(d)) + if not self.editable: + self.check_site_dir() + self.index_url = self.index_url or "https://pypi.org/simple/" + self.shadow_path = self.all_site_dirs[:] + for path_item in self.install_dir, normalize_path(self.script_dir): + if path_item not in self.shadow_path: + self.shadow_path.insert(0, path_item) + + if self.allow_hosts is not None: + hosts = [s.strip() for s in self.allow_hosts.split(',')] + else: + hosts = ['*'] + if self.package_index is None: + self.package_index = self.create_index( + self.index_url, search_path=self.shadow_path, hosts=hosts, + ) + self.local_index = Environment(self.shadow_path + sys.path) + + if self.find_links is not None: + if isinstance(self.find_links, six.string_types): + self.find_links = self.find_links.split() + else: + self.find_links = [] + if self.local_snapshots_ok: + self.package_index.scan_egg_links(self.shadow_path + sys.path) + if not self.no_find_links: + self.package_index.add_find_links(self.find_links) + self.set_undefined_options('install_lib', ('optimize', 'optimize')) + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + if not (0 <= self.optimize <= 2): + raise ValueError + except ValueError: + raise DistutilsOptionError("--optimize must be 0, 1, or 2") + + if self.editable and not self.build_directory: + raise DistutilsArgError( + "Must specify a build directory (-b) when using --editable" + ) + if not self.args: + raise DistutilsArgError( + "No urls, filenames, or requirements specified (see --help)") + + self.outputs = [] + + def _fix_install_dir_for_user_site(self): + """ + Fix the install_dir if "--user" was used. + """ + if not self.user or not site.ENABLE_USER_SITE: + return + + self.create_home_path() + if self.install_userbase is None: + msg = "User base directory is not specified" + raise DistutilsPlatformError(msg) + self.install_base = self.install_platbase = self.install_userbase + scheme_name = os.name.replace('posix', 'unix') + '_user' + self.select_scheme(scheme_name) + + def _expand_attrs(self, attrs): + for attr in attrs: + val = getattr(self, attr) + if val is not None: + if os.name == 'posix' or os.name == 'nt': + val = os.path.expanduser(val) + val = subst_vars(val, self.config_vars) + setattr(self, attr, val) + + def expand_basedirs(self): + """Calls `os.path.expanduser` on install_base, install_platbase and + root.""" + self._expand_attrs(['install_base', 'install_platbase', 'root']) + + def expand_dirs(self): + """Calls `os.path.expanduser` on install dirs.""" + dirs = [ + 'install_purelib', + 'install_platlib', + 'install_lib', + 'install_headers', + 'install_scripts', + 'install_data', + ] + self._expand_attrs(dirs) + + def run(self): + if self.verbose != self.distribution.verbose: + log.set_verbosity(self.verbose) + try: + for spec in self.args: + self.easy_install(spec, not self.no_deps) + if self.record: + outputs = self.outputs + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in range(len(outputs)): + outputs[counter] = outputs[counter][root_len:] + from distutils import file_util + + self.execute( + file_util.write_file, (self.record, outputs), + "writing list of installed files to '%s'" % + self.record + ) + self.warn_deprecated_options() + finally: + log.set_verbosity(self.distribution.verbose) + + def pseudo_tempname(self): + """Return a pseudo-tempname base in the install directory. + This code is intentionally naive; if a malicious party can write to + the target directory you're already in deep doodoo. + """ + try: + pid = os.getpid() + except Exception: + pid = random.randint(0, sys.maxsize) + return os.path.join(self.install_dir, "test-easy-install-%s" % pid) + + def warn_deprecated_options(self): + pass + + def check_site_dir(self): + """Verify that self.install_dir is .pth-capable dir, if needed""" + + instdir = normalize_path(self.install_dir) + pth_file = os.path.join(instdir, 'easy-install.pth') + + # Is it a configured, PYTHONPATH, implicit, or explicit site dir? + is_site_dir = instdir in self.all_site_dirs + + if not is_site_dir and not self.multi_version: + # No? Then directly test whether it does .pth file processing + is_site_dir = self.check_pth_processing() + else: + # make sure we can write to target dir + testfile = self.pseudo_tempname() + '.write-test' + test_exists = os.path.exists(testfile) + try: + if test_exists: + os.unlink(testfile) + open(testfile, 'w').close() + os.unlink(testfile) + except (OSError, IOError): + self.cant_write_to_target() + + if not is_site_dir and not self.multi_version: + # Can't install non-multi to non-site dir + raise DistutilsError(self.no_default_version_msg()) + + if is_site_dir: + if self.pth_file is None: + self.pth_file = PthDistributions(pth_file, self.all_site_dirs) + else: + self.pth_file = None + + if instdir not in map(normalize_path, _pythonpath()): + # only PYTHONPATH dirs need a site.py, so pretend it's there + self.sitepy_installed = True + elif self.multi_version and not os.path.exists(pth_file): + self.sitepy_installed = True # don't need site.py in this case + self.pth_file = None # and don't create a .pth file + self.install_dir = instdir + + __cant_write_msg = textwrap.dedent(""" + can't create or remove files in install directory + + The following error occurred while trying to add or remove files in the + installation directory: + + %s + + The installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: + + %s + """).lstrip() + + __not_exists_id = textwrap.dedent(""" + This directory does not currently exist. Please create it and try again, or + choose a different installation directory (using the -d or --install-dir + option). + """).lstrip() + + __access_msg = textwrap.dedent(""" + Perhaps your account does not have write access to this directory? If the + installation directory is a system-owned directory, you may need to sign in + as the administrator or "root" account. If you do not have administrative + access to this machine, you may wish to choose a different installation + directory, preferably one that is listed in your PYTHONPATH environment + variable. + + For information on other options, you may wish to consult the + documentation at: + + https://setuptools.readthedocs.io/en/latest/easy_install.html + + Please make the appropriate changes for your system and try again. + """).lstrip() + + def cant_write_to_target(self): + msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,) + + if not os.path.exists(self.install_dir): + msg += '\n' + self.__not_exists_id + else: + msg += '\n' + self.__access_msg + raise DistutilsError(msg) + + def check_pth_processing(self): + """Empirically verify whether .pth files are supported in inst. dir""" + instdir = self.install_dir + log.info("Checking .pth file support in %s", instdir) + pth_file = self.pseudo_tempname() + ".pth" + ok_file = pth_file + '.ok' + ok_exists = os.path.exists(ok_file) + tmpl = _one_liner(""" + import os + f = open({ok_file!r}, 'w') + f.write('OK') + f.close() + """) + '\n' + try: + if ok_exists: + os.unlink(ok_file) + dirname = os.path.dirname(ok_file) + pkg_resources.py31compat.makedirs(dirname, exist_ok=True) + f = open(pth_file, 'w') + except (OSError, IOError): + self.cant_write_to_target() + else: + try: + f.write(tmpl.format(**locals())) + f.close() + f = None + executable = sys.executable + if os.name == 'nt': + dirname, basename = os.path.split(executable) + alt = os.path.join(dirname, 'pythonw.exe') + use_alt = ( + basename.lower() == 'python.exe' and + os.path.exists(alt) + ) + if use_alt: + # use pythonw.exe to avoid opening a console window + executable = alt + + from distutils.spawn import spawn + + spawn([executable, '-E', '-c', 'pass'], 0) + + if os.path.exists(ok_file): + log.info( + "TEST PASSED: %s appears to support .pth files", + instdir + ) + return True + finally: + if f: + f.close() + if os.path.exists(ok_file): + os.unlink(ok_file) + if os.path.exists(pth_file): + os.unlink(pth_file) + if not self.multi_version: + log.warn("TEST FAILED: %s does NOT support .pth files", instdir) + return False + + def install_egg_scripts(self, dist): + """Write all the scripts for `dist`, unless scripts are excluded""" + if not self.exclude_scripts and dist.metadata_isdir('scripts'): + for script_name in dist.metadata_listdir('scripts'): + if dist.metadata_isdir('scripts/' + script_name): + # The "script" is a directory, likely a Python 3 + # __pycache__ directory, so skip it. + continue + self.install_script( + dist, script_name, + dist.get_metadata('scripts/' + script_name) + ) + self.install_wrapper_scripts(dist) + + def add_output(self, path): + if os.path.isdir(path): + for base, dirs, files in os.walk(path): + for filename in files: + self.outputs.append(os.path.join(base, filename)) + else: + self.outputs.append(path) + + def not_editable(self, spec): + if self.editable: + raise DistutilsArgError( + "Invalid argument %r: you can't use filenames or URLs " + "with --editable (except via the --find-links option)." + % (spec,) + ) + + def check_editable(self, spec): + if not self.editable: + return + + if os.path.exists(os.path.join(self.build_directory, spec.key)): + raise DistutilsArgError( + "%r already exists in %s; can't do a checkout there" % + (spec.key, self.build_directory) + ) + + @contextlib.contextmanager + def _tmpdir(self): + tmpdir = tempfile.mkdtemp(prefix=u"easy_install-") + try: + # cast to str as workaround for #709 and #710 and #712 + yield str(tmpdir) + finally: + os.path.exists(tmpdir) and rmtree(rmtree_safe(tmpdir)) + + def easy_install(self, spec, deps=False): + if not self.editable: + self.install_site_py() + + with self._tmpdir() as tmpdir: + if not isinstance(spec, Requirement): + if URL_SCHEME(spec): + # It's a url, download it to tmpdir and process + self.not_editable(spec) + dl = self.package_index.download(spec, tmpdir) + return self.install_item(None, dl, tmpdir, deps, True) + + elif os.path.exists(spec): + # Existing file or directory, just process it directly + self.not_editable(spec) + return self.install_item(None, spec, tmpdir, deps, True) + else: + spec = parse_requirement_arg(spec) + + self.check_editable(spec) + dist = self.package_index.fetch_distribution( + spec, tmpdir, self.upgrade, self.editable, + not self.always_copy, self.local_index + ) + if dist is None: + msg = "Could not find suitable distribution for %r" % spec + if self.always_copy: + msg += " (--always-copy skips system and development eggs)" + raise DistutilsError(msg) + elif dist.precedence == DEVELOP_DIST: + # .egg-info dists don't need installing, just process deps + self.process_distribution(spec, dist, deps, "Using") + return dist + else: + return self.install_item(spec, dist.location, tmpdir, deps) + + def install_item(self, spec, download, tmpdir, deps, install_needed=False): + + # Installation is also needed if file in tmpdir or is not an egg + install_needed = install_needed or self.always_copy + install_needed = install_needed or os.path.dirname(download) == tmpdir + install_needed = install_needed or not download.endswith('.egg') + install_needed = install_needed or ( + self.always_copy_from is not None and + os.path.dirname(normalize_path(download)) == + normalize_path(self.always_copy_from) + ) + + if spec and not install_needed: + # at this point, we know it's a local .egg, we just don't know if + # it's already installed. + for dist in self.local_index[spec.project_name]: + if dist.location == download: + break + else: + install_needed = True # it's not in the local index + + log.info("Processing %s", os.path.basename(download)) + + if install_needed: + dists = self.install_eggs(spec, download, tmpdir) + for dist in dists: + self.process_distribution(spec, dist, deps) + else: + dists = [self.egg_distribution(download)] + self.process_distribution(spec, dists[0], deps, "Using") + + if spec is not None: + for dist in dists: + if dist in spec: + return dist + + def select_scheme(self, name): + """Sets the install directories by applying the install schemes.""" + # it's the caller's problem if they supply a bad name! + scheme = INSTALL_SCHEMES[name] + for key in SCHEME_KEYS: + attrname = 'install_' + key + if getattr(self, attrname) is None: + setattr(self, attrname, scheme[key]) + + def process_distribution(self, requirement, dist, deps=True, *info): + self.update_pth(dist) + self.package_index.add(dist) + if dist in self.local_index[dist.key]: + self.local_index.remove(dist) + self.local_index.add(dist) + self.install_egg_scripts(dist) + self.installed_projects[dist.key] = dist + log.info(self.installation_report(requirement, dist, *info)) + if (dist.has_metadata('dependency_links.txt') and + not self.no_find_links): + self.package_index.add_find_links( + dist.get_metadata_lines('dependency_links.txt') + ) + if not deps and not self.always_copy: + return + elif requirement is not None and dist.key != requirement.key: + log.warn("Skipping dependencies for %s", dist) + return # XXX this is not the distribution we were looking for + elif requirement is None or dist not in requirement: + # if we wound up with a different version, resolve what we've got + distreq = dist.as_requirement() + requirement = Requirement(str(distreq)) + log.info("Processing dependencies for %s", requirement) + try: + distros = WorkingSet([]).resolve( + [requirement], self.local_index, self.easy_install + ) + except DistributionNotFound as e: + raise DistutilsError(str(e)) + except VersionConflict as e: + raise DistutilsError(e.report()) + if self.always_copy or self.always_copy_from: + # Force all the relevant distros to be copied or activated + for dist in distros: + if dist.key not in self.installed_projects: + self.easy_install(dist.as_requirement()) + log.info("Finished processing dependencies for %s", requirement) + + def should_unzip(self, dist): + if self.zip_ok is not None: + return not self.zip_ok + if dist.has_metadata('not-zip-safe'): + return True + if not dist.has_metadata('zip-safe'): + return True + return False + + def maybe_move(self, spec, dist_filename, setup_base): + dst = os.path.join(self.build_directory, spec.key) + if os.path.exists(dst): + msg = ( + "%r already exists in %s; build directory %s will not be kept" + ) + log.warn(msg, spec.key, self.build_directory, setup_base) + return setup_base + if os.path.isdir(dist_filename): + setup_base = dist_filename + else: + if os.path.dirname(dist_filename) == setup_base: + os.unlink(dist_filename) # get it out of the tmp dir + contents = os.listdir(setup_base) + if len(contents) == 1: + dist_filename = os.path.join(setup_base, contents[0]) + if os.path.isdir(dist_filename): + # if the only thing there is a directory, move it instead + setup_base = dist_filename + ensure_directory(dst) + shutil.move(setup_base, dst) + return dst + + def install_wrapper_scripts(self, dist): + if self.exclude_scripts: + return + for args in ScriptWriter.best().get_args(dist): + self.write_script(*args) + + def install_script(self, dist, script_name, script_text, dev_path=None): + """Generate a legacy script wrapper and install it""" + spec = str(dist.as_requirement()) + is_script = is_python_script(script_text, script_name) + + if is_script: + body = self._load_template(dev_path) % locals() + script_text = ScriptWriter.get_header(script_text) + body + self.write_script(script_name, _to_bytes(script_text), 'b') + + @staticmethod + def _load_template(dev_path): + """ + There are a couple of template scripts in the package. This + function loads one of them and prepares it for use. + """ + # See https://github.com/pypa/setuptools/issues/134 for info + # on script file naming and downstream issues with SVR4 + name = 'script.tmpl' + if dev_path: + name = name.replace('.tmpl', ' (dev).tmpl') + + raw_bytes = resource_string('setuptools', name) + return raw_bytes.decode('utf-8') + + def write_script(self, script_name, contents, mode="t", blockers=()): + """Write an executable file to the scripts directory""" + self.delete_blockers( # clean up old .py/.pyw w/o a script + [os.path.join(self.script_dir, x) for x in blockers] + ) + log.info("Installing %s script to %s", script_name, self.script_dir) + target = os.path.join(self.script_dir, script_name) + self.add_output(target) + + if self.dry_run: + return + + mask = current_umask() + ensure_directory(target) + if os.path.exists(target): + os.unlink(target) + with open(target, "w" + mode) as f: + f.write(contents) + chmod(target, 0o777 - mask) + + def install_eggs(self, spec, dist_filename, tmpdir): + # .egg dirs or files are already built, so just return them + if dist_filename.lower().endswith('.egg'): + return [self.install_egg(dist_filename, tmpdir)] + elif dist_filename.lower().endswith('.exe'): + return [self.install_exe(dist_filename, tmpdir)] + elif dist_filename.lower().endswith('.whl'): + return [self.install_wheel(dist_filename, tmpdir)] + + # Anything else, try to extract and build + setup_base = tmpdir + if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'): + unpack_archive(dist_filename, tmpdir, self.unpack_progress) + elif os.path.isdir(dist_filename): + setup_base = os.path.abspath(dist_filename) + + if (setup_base.startswith(tmpdir) # something we downloaded + and self.build_directory and spec is not None): + setup_base = self.maybe_move(spec, dist_filename, setup_base) + + # Find the setup.py file + setup_script = os.path.join(setup_base, 'setup.py') + + if not os.path.exists(setup_script): + setups = glob(os.path.join(setup_base, '*', 'setup.py')) + if not setups: + raise DistutilsError( + "Couldn't find a setup script in %s" % + os.path.abspath(dist_filename) + ) + if len(setups) > 1: + raise DistutilsError( + "Multiple setup scripts in %s" % + os.path.abspath(dist_filename) + ) + setup_script = setups[0] + + # Now run it, and return the result + if self.editable: + log.info(self.report_editable(spec, setup_script)) + return [] + else: + return self.build_and_install(setup_script, setup_base) + + def egg_distribution(self, egg_path): + if os.path.isdir(egg_path): + metadata = PathMetadata(egg_path, os.path.join(egg_path, + 'EGG-INFO')) + else: + metadata = EggMetadata(zipimport.zipimporter(egg_path)) + return Distribution.from_filename(egg_path, metadata=metadata) + + def install_egg(self, egg_path, tmpdir): + destination = os.path.join( + self.install_dir, + os.path.basename(egg_path), + ) + destination = os.path.abspath(destination) + if not self.dry_run: + ensure_directory(destination) + + dist = self.egg_distribution(egg_path) + if not samefile(egg_path, destination): + if os.path.isdir(destination) and not os.path.islink(destination): + dir_util.remove_tree(destination, dry_run=self.dry_run) + elif os.path.exists(destination): + self.execute( + os.unlink, + (destination,), + "Removing " + destination, + ) + try: + new_dist_is_zipped = False + if os.path.isdir(egg_path): + if egg_path.startswith(tmpdir): + f, m = shutil.move, "Moving" + else: + f, m = shutil.copytree, "Copying" + elif self.should_unzip(dist): + self.mkpath(destination) + f, m = self.unpack_and_compile, "Extracting" + else: + new_dist_is_zipped = True + if egg_path.startswith(tmpdir): + f, m = shutil.move, "Moving" + else: + f, m = shutil.copy2, "Copying" + self.execute( + f, + (egg_path, destination), + (m + " %s to %s") % ( + os.path.basename(egg_path), + os.path.dirname(destination) + ), + ) + update_dist_caches( + destination, + fix_zipimporter_caches=new_dist_is_zipped, + ) + except Exception: + update_dist_caches(destination, fix_zipimporter_caches=False) + raise + + self.add_output(destination) + return self.egg_distribution(destination) + + def install_exe(self, dist_filename, tmpdir): + # See if it's valid, get data + cfg = extract_wininst_cfg(dist_filename) + if cfg is None: + raise DistutilsError( + "%s is not a valid distutils Windows .exe" % dist_filename + ) + # Create a dummy distribution object until we build the real distro + dist = Distribution( + None, + project_name=cfg.get('metadata', 'name'), + version=cfg.get('metadata', 'version'), platform=get_platform(), + ) + + # Convert the .exe to an unpacked egg + egg_path = os.path.join(tmpdir, dist.egg_name() + '.egg') + dist.location = egg_path + egg_tmp = egg_path + '.tmp' + _egg_info = os.path.join(egg_tmp, 'EGG-INFO') + pkg_inf = os.path.join(_egg_info, 'PKG-INFO') + ensure_directory(pkg_inf) # make sure EGG-INFO dir exists + dist._provider = PathMetadata(egg_tmp, _egg_info) # XXX + self.exe_to_egg(dist_filename, egg_tmp) + + # Write EGG-INFO/PKG-INFO + if not os.path.exists(pkg_inf): + f = open(pkg_inf, 'w') + f.write('Metadata-Version: 1.0\n') + for k, v in cfg.items('metadata'): + if k != 'target_version': + f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) + f.close() + script_dir = os.path.join(_egg_info, 'scripts') + # delete entry-point scripts to avoid duping + self.delete_blockers([ + os.path.join(script_dir, args[0]) + for args in ScriptWriter.get_args(dist) + ]) + # Build .egg file from tmpdir + bdist_egg.make_zipfile( + egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run, + ) + # install the .egg + return self.install_egg(egg_path, tmpdir) + + def exe_to_egg(self, dist_filename, egg_tmp): + """Extract a bdist_wininst to the directories an egg would use""" + # Check for .pth file and set up prefix translations + prefixes = get_exe_prefixes(dist_filename) + to_compile = [] + native_libs = [] + top_level = {} + + def process(src, dst): + s = src.lower() + for old, new in prefixes: + if s.startswith(old): + src = new + src[len(old):] + parts = src.split('/') + dst = os.path.join(egg_tmp, *parts) + dl = dst.lower() + if dl.endswith('.pyd') or dl.endswith('.dll'): + parts[-1] = bdist_egg.strip_module(parts[-1]) + top_level[os.path.splitext(parts[0])[0]] = 1 + native_libs.append(src) + elif dl.endswith('.py') and old != 'SCRIPTS/': + top_level[os.path.splitext(parts[0])[0]] = 1 + to_compile.append(dst) + return dst + if not src.endswith('.pth'): + log.warn("WARNING: can't process %s", src) + return None + + # extract, tracking .pyd/.dll->native_libs and .py -> to_compile + unpack_archive(dist_filename, egg_tmp, process) + stubs = [] + for res in native_libs: + if res.lower().endswith('.pyd'): # create stubs for .pyd's + parts = res.split('/') + resource = parts[-1] + parts[-1] = bdist_egg.strip_module(parts[-1]) + '.py' + pyfile = os.path.join(egg_tmp, *parts) + to_compile.append(pyfile) + stubs.append(pyfile) + bdist_egg.write_stub(resource, pyfile) + self.byte_compile(to_compile) # compile .py's + bdist_egg.write_safety_flag( + os.path.join(egg_tmp, 'EGG-INFO'), + bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag + + for name in 'top_level', 'native_libs': + if locals()[name]: + txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt') + if not os.path.exists(txt): + f = open(txt, 'w') + f.write('\n'.join(locals()[name]) + '\n') + f.close() + + def install_wheel(self, wheel_path, tmpdir): + wheel = Wheel(wheel_path) + assert wheel.is_compatible() + destination = os.path.join(self.install_dir, wheel.egg_name()) + destination = os.path.abspath(destination) + if not self.dry_run: + ensure_directory(destination) + if os.path.isdir(destination) and not os.path.islink(destination): + dir_util.remove_tree(destination, dry_run=self.dry_run) + elif os.path.exists(destination): + self.execute( + os.unlink, + (destination,), + "Removing " + destination, + ) + try: + self.execute( + wheel.install_as_egg, + (destination,), + ("Installing %s to %s") % ( + os.path.basename(wheel_path), + os.path.dirname(destination) + ), + ) + finally: + update_dist_caches(destination, fix_zipimporter_caches=False) + self.add_output(destination) + return self.egg_distribution(destination) + + __mv_warning = textwrap.dedent(""" + Because this distribution was installed --multi-version, before you can + import modules from this package in an application, you will need to + 'import pkg_resources' and then use a 'require()' call similar to one of + these examples, in order to select the desired version: + + pkg_resources.require("%(name)s") # latest installed version + pkg_resources.require("%(name)s==%(version)s") # this exact version + pkg_resources.require("%(name)s>=%(version)s") # this version or higher + """).lstrip() + + __id_warning = textwrap.dedent(""" + Note also that the installation directory must be on sys.path at runtime for + this to work. (e.g. by being the application's script directory, by being on + PYTHONPATH, or by being added to sys.path by your code.) + """) + + def installation_report(self, req, dist, what="Installed"): + """Helpful installation message for display to package users""" + msg = "\n%(what)s %(eggloc)s%(extras)s" + if self.multi_version and not self.no_report: + msg += '\n' + self.__mv_warning + if self.install_dir not in map(normalize_path, sys.path): + msg += '\n' + self.__id_warning + + eggloc = dist.location + name = dist.project_name + version = dist.version + extras = '' # TODO: self.report_extras(req, dist) + return msg % locals() + + __editable_msg = textwrap.dedent(""" + Extracted editable version of %(spec)s to %(dirname)s + + If it uses setuptools in its setup script, you can activate it in + "development" mode by going to that directory and running:: + + %(python)s setup.py develop + + See the setuptools documentation for the "develop" command for more info. + """).lstrip() + + def report_editable(self, spec, setup_script): + dirname = os.path.dirname(setup_script) + python = sys.executable + return '\n' + self.__editable_msg % locals() + + def run_setup(self, setup_script, setup_base, args): + sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) + sys.modules.setdefault('distutils.command.egg_info', egg_info) + + args = list(args) + if self.verbose > 2: + v = 'v' * (self.verbose - 1) + args.insert(0, '-' + v) + elif self.verbose < 2: + args.insert(0, '-q') + if self.dry_run: + args.insert(0, '-n') + log.info( + "Running %s %s", setup_script[len(setup_base) + 1:], ' '.join(args) + ) + try: + run_setup(setup_script, args) + except SystemExit as v: + raise DistutilsError("Setup script exited with %s" % (v.args[0],)) + + def build_and_install(self, setup_script, setup_base): + args = ['bdist_egg', '--dist-dir'] + + dist_dir = tempfile.mkdtemp( + prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) + ) + try: + self._set_fetcher_options(os.path.dirname(setup_script)) + args.append(dist_dir) + + self.run_setup(setup_script, setup_base, args) + all_eggs = Environment([dist_dir]) + eggs = [] + for key in all_eggs: + for dist in all_eggs[key]: + eggs.append(self.install_egg(dist.location, setup_base)) + if not eggs and not self.dry_run: + log.warn("No eggs found in %s (setup script problem?)", + dist_dir) + return eggs + finally: + rmtree(dist_dir) + log.set_verbosity(self.verbose) # restore our log verbosity + + def _set_fetcher_options(self, base): + """ + When easy_install is about to run bdist_egg on a source dist, that + source dist might have 'setup_requires' directives, requiring + additional fetching. Ensure the fetcher options given to easy_install + are available to that command as well. + """ + # find the fetch options from easy_install and write them out + # to the setup.cfg file. + ei_opts = self.distribution.get_option_dict('easy_install').copy() + fetch_directives = ( + 'find_links', 'site_dirs', 'index_url', 'optimize', + 'site_dirs', 'allow_hosts', + ) + fetch_options = {} + for key, val in ei_opts.items(): + if key not in fetch_directives: + continue + fetch_options[key.replace('_', '-')] = val[1] + # create a settings dictionary suitable for `edit_config` + settings = dict(easy_install=fetch_options) + cfg_filename = os.path.join(base, 'setup.cfg') + setopt.edit_config(cfg_filename, settings) + + def update_pth(self, dist): + if self.pth_file is None: + return + + for d in self.pth_file[dist.key]: # drop old entries + if self.multi_version or d.location != dist.location: + log.info("Removing %s from easy-install.pth file", d) + self.pth_file.remove(d) + if d.location in self.shadow_path: + self.shadow_path.remove(d.location) + + if not self.multi_version: + if dist.location in self.pth_file.paths: + log.info( + "%s is already the active version in easy-install.pth", + dist, + ) + else: + log.info("Adding %s to easy-install.pth file", dist) + self.pth_file.add(dist) # add new entry + if dist.location not in self.shadow_path: + self.shadow_path.append(dist.location) + + if not self.dry_run: + + self.pth_file.save() + + if dist.key == 'setuptools': + # Ensure that setuptools itself never becomes unavailable! + # XXX should this check for latest version? + filename = os.path.join(self.install_dir, 'setuptools.pth') + if os.path.islink(filename): + os.unlink(filename) + f = open(filename, 'wt') + f.write(self.pth_file.make_relative(dist.location) + '\n') + f.close() + + def unpack_progress(self, src, dst): + # Progress filter for unpacking + log.debug("Unpacking %s to %s", src, dst) + return dst # only unpack-and-compile skips files for dry run + + def unpack_and_compile(self, egg_path, destination): + to_compile = [] + to_chmod = [] + + def pf(src, dst): + if dst.endswith('.py') and not src.startswith('EGG-INFO/'): + to_compile.append(dst) + elif dst.endswith('.dll') or dst.endswith('.so'): + to_chmod.append(dst) + self.unpack_progress(src, dst) + return not self.dry_run and dst or None + + unpack_archive(egg_path, destination, pf) + self.byte_compile(to_compile) + if not self.dry_run: + for f in to_chmod: + mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755 + chmod(f, mode) + + def byte_compile(self, to_compile): + if sys.dont_write_bytecode: + return + + from distutils.util import byte_compile + + try: + # try to make the byte compile messages quieter + log.set_verbosity(self.verbose - 1) + + byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) + if self.optimize: + byte_compile( + to_compile, optimize=self.optimize, force=1, + dry_run=self.dry_run, + ) + finally: + log.set_verbosity(self.verbose) # restore original verbosity + + __no_default_msg = textwrap.dedent(""" + bad install directory or PYTHONPATH + + You are attempting to install a package to a directory that is not + on PYTHONPATH and which Python does not read ".pth" files from. The + installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: + + %s + + and your PYTHONPATH environment variable currently contains: + + %r + + Here are some of your options for correcting the problem: + + * You can choose a different installation directory, i.e., one that is + on PYTHONPATH or supports .pth files + + * You can add the installation directory to the PYTHONPATH environment + variable. (It must then also be on PYTHONPATH whenever you run + Python and want to use the package(s) you are installing.) + + * You can set up the installation directory to support ".pth" files by + using one of the approaches described here: + + https://setuptools.readthedocs.io/en/latest/easy_install.html#custom-installation-locations + + + Please make the appropriate changes for your system and try again.""").lstrip() + + def no_default_version_msg(self): + template = self.__no_default_msg + return template % (self.install_dir, os.environ.get('PYTHONPATH', '')) + + def install_site_py(self): + """Make sure there's a site.py in the target dir, if needed""" + + if self.sitepy_installed: + return # already did it, or don't need to + + sitepy = os.path.join(self.install_dir, "site.py") + source = resource_string("setuptools", "site-patch.py") + source = source.decode('utf-8') + current = "" + + if os.path.exists(sitepy): + log.debug("Checking existing site.py in %s", self.install_dir) + with io.open(sitepy) as strm: + current = strm.read() + + if not current.startswith('def __boot():'): + raise DistutilsError( + "%s is not a setuptools-generated site.py; please" + " remove it." % sitepy + ) + + if current != source: + log.info("Creating %s", sitepy) + if not self.dry_run: + ensure_directory(sitepy) + with io.open(sitepy, 'w', encoding='utf-8') as strm: + strm.write(source) + self.byte_compile([sitepy]) + + self.sitepy_installed = True + + def create_home_path(self): + """Create directories under ~.""" + if not self.user: + return + home = convert_path(os.path.expanduser("~")) + for name, path in six.iteritems(self.config_vars): + if path.startswith(home) and not os.path.isdir(path): + self.debug_print("os.makedirs('%s', 0o700)" % path) + os.makedirs(path, 0o700) + + INSTALL_SCHEMES = dict( + posix=dict( + install_dir='$base/lib/python$py_version_short/site-packages', + script_dir='$base/bin', + ), + ) + + DEFAULT_SCHEME = dict( + install_dir='$base/Lib/site-packages', + script_dir='$base/Scripts', + ) + + def _expand(self, *attrs): + config_vars = self.get_finalized_command('install').config_vars + + if self.prefix: + # Set default install_dir/scripts from --prefix + config_vars = config_vars.copy() + config_vars['base'] = self.prefix + scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME) + for attr, val in scheme.items(): + if getattr(self, attr, None) is None: + setattr(self, attr, val) + + from distutils.util import subst_vars + + for attr in attrs: + val = getattr(self, attr) + if val is not None: + val = subst_vars(val, config_vars) + if os.name == 'posix': + val = os.path.expanduser(val) + setattr(self, attr, val) + + +def _pythonpath(): + items = os.environ.get('PYTHONPATH', '').split(os.pathsep) + return filter(None, items) + + +def get_site_dirs(): + """ + Return a list of 'site' dirs + """ + + sitedirs = [] + + # start with PYTHONPATH + sitedirs.extend(_pythonpath()) + + prefixes = [sys.prefix] + if sys.exec_prefix != sys.prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos'): + sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) + elif os.sep == '/': + sitedirs.extend([ + os.path.join( + prefix, + "lib", + "python" + sys.version[:3], + "site-packages", + ), + os.path.join(prefix, "lib", "site-python"), + ]) + else: + sitedirs.extend([ + prefix, + os.path.join(prefix, "lib", "site-packages"), + ]) + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + home_sp = os.path.join( + home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages', + ) + sitedirs.append(home_sp) + lib_paths = get_path('purelib'), get_path('platlib') + for site_lib in lib_paths: + if site_lib not in sitedirs: + sitedirs.append(site_lib) + + if site.ENABLE_USER_SITE: + sitedirs.append(site.USER_SITE) + + try: + sitedirs.extend(site.getsitepackages()) + except AttributeError: + pass + + sitedirs = list(map(normalize_path, sitedirs)) + + return sitedirs + + +def expand_paths(inputs): + """Yield sys.path directories that might contain "old-style" packages""" + + seen = {} + + for dirname in inputs: + dirname = normalize_path(dirname) + if dirname in seen: + continue + + seen[dirname] = 1 + if not os.path.isdir(dirname): + continue + + files = os.listdir(dirname) + yield dirname, files + + for name in files: + if not name.endswith('.pth'): + # We only care about the .pth files + continue + if name in ('easy-install.pth', 'setuptools.pth'): + # Ignore .pth files that we control + continue + + # Read the .pth file + f = open(os.path.join(dirname, name)) + lines = list(yield_lines(f)) + f.close() + + # Yield existing non-dupe, non-import directory lines from it + for line in lines: + if not line.startswith("import"): + line = normalize_path(line.rstrip()) + if line not in seen: + seen[line] = 1 + if not os.path.isdir(line): + continue + yield line, os.listdir(line) + + +def extract_wininst_cfg(dist_filename): + """Extract configuration data from a bdist_wininst .exe + + Returns a configparser.RawConfigParser, or None + """ + f = open(dist_filename, 'rb') + try: + endrec = zipfile._EndRecData(f) + if endrec is None: + return None + + prepended = (endrec[9] - endrec[5]) - endrec[6] + if prepended < 12: # no wininst data here + return None + f.seek(prepended - 12) + + tag, cfglen, bmlen = struct.unpack("<iii", f.read(12)) + if tag not in (0x1234567A, 0x1234567B): + return None # not a valid tag + + f.seek(prepended - (12 + cfglen)) + init = {'version': '', 'target_version': ''} + cfg = configparser.RawConfigParser(init) + try: + part = f.read(cfglen) + # Read up to the first null byte. + config = part.split(b'\0', 1)[0] + # Now the config is in bytes, but for RawConfigParser, it should + # be text, so decode it. + config = config.decode(sys.getfilesystemencoding()) + cfg.readfp(six.StringIO(config)) + except configparser.Error: + return None + if not cfg.has_section('metadata') or not cfg.has_section('Setup'): + return None + return cfg + + finally: + f.close() + + +def get_exe_prefixes(exe_filename): + """Get exe->egg path translations for a given .exe file""" + + prefixes = [ + ('PURELIB/', ''), + ('PLATLIB/pywin32_system32', ''), + ('PLATLIB/', ''), + ('SCRIPTS/', 'EGG-INFO/scripts/'), + ('DATA/lib/site-packages', ''), + ] + z = zipfile.ZipFile(exe_filename) + try: + for info in z.infolist(): + name = info.filename + parts = name.split('/') + if len(parts) == 3 and parts[2] == 'PKG-INFO': + if parts[1].endswith('.egg-info'): + prefixes.insert(0, ('/'.join(parts[:2]), 'EGG-INFO/')) + break + if len(parts) != 2 or not name.endswith('.pth'): + continue + if name.endswith('-nspkg.pth'): + continue + if parts[0].upper() in ('PURELIB', 'PLATLIB'): + contents = z.read(name) + if six.PY3: + contents = contents.decode() + for pth in yield_lines(contents): + pth = pth.strip().replace('\\', '/') + if not pth.startswith('import'): + prefixes.append((('%s/%s/' % (parts[0], pth)), '')) + finally: + z.close() + prefixes = [(x.lower(), y) for x, y in prefixes] + prefixes.sort() + prefixes.reverse() + return prefixes + + +class PthDistributions(Environment): + """A .pth file with Distribution paths in it""" + + dirty = False + + def __init__(self, filename, sitedirs=()): + self.filename = filename + self.sitedirs = list(map(normalize_path, sitedirs)) + self.basedir = normalize_path(os.path.dirname(self.filename)) + self._load() + Environment.__init__(self, [], None, None) + for path in yield_lines(self.paths): + list(map(self.add, find_distributions(path, True))) + + def _load(self): + self.paths = [] + saw_import = False + seen = dict.fromkeys(self.sitedirs) + if os.path.isfile(self.filename): + f = open(self.filename, 'rt') + for line in f: + if line.startswith('import'): + saw_import = True + continue + path = line.rstrip() + self.paths.append(path) + if not path.strip() or path.strip().startswith('#'): + continue + # skip non-existent paths, in case somebody deleted a package + # manually, and duplicate paths as well + path = self.paths[-1] = normalize_path( + os.path.join(self.basedir, path) + ) + if not os.path.exists(path) or path in seen: + self.paths.pop() # skip it + self.dirty = True # we cleaned up, so we're dirty now :) + continue + seen[path] = 1 + f.close() + + if self.paths and not saw_import: + self.dirty = True # ensure anything we touch has import wrappers + while self.paths and not self.paths[-1].strip(): + self.paths.pop() + + def save(self): + """Write changed .pth file back to disk""" + if not self.dirty: + return + + rel_paths = list(map(self.make_relative, self.paths)) + if rel_paths: + log.debug("Saving %s", self.filename) + lines = self._wrap_lines(rel_paths) + data = '\n'.join(lines) + '\n' + + if os.path.islink(self.filename): + os.unlink(self.filename) + with open(self.filename, 'wt') as f: + f.write(data) + + elif os.path.exists(self.filename): + log.debug("Deleting empty %s", self.filename) + os.unlink(self.filename) + + self.dirty = False + + @staticmethod + def _wrap_lines(lines): + return lines + + def add(self, dist): + """Add `dist` to the distribution map""" + new_path = ( + dist.location not in self.paths and ( + dist.location not in self.sitedirs or + # account for '.' being in PYTHONPATH + dist.location == os.getcwd() + ) + ) + if new_path: + self.paths.append(dist.location) + self.dirty = True + Environment.add(self, dist) + + def remove(self, dist): + """Remove `dist` from the distribution map""" + while dist.location in self.paths: + self.paths.remove(dist.location) + self.dirty = True + Environment.remove(self, dist) + + def make_relative(self, path): + npath, last = os.path.split(normalize_path(path)) + baselen = len(self.basedir) + parts = [last] + sep = os.altsep == '/' and '/' or os.sep + while len(npath) >= baselen: + if npath == self.basedir: + parts.append(os.curdir) + parts.reverse() + return sep.join(parts) + npath, last = os.path.split(npath) + parts.append(last) + else: + return path + + +class RewritePthDistributions(PthDistributions): + @classmethod + def _wrap_lines(cls, lines): + yield cls.prelude + for line in lines: + yield line + yield cls.postlude + + prelude = _one_liner(""" + import sys + sys.__plen = len(sys.path) + """) + postlude = _one_liner(""" + import sys + new = sys.path[sys.__plen:] + del sys.path[sys.__plen:] + p = getattr(sys, '__egginsert', 0) + sys.path[p:p] = new + sys.__egginsert = p + len(new) + """) + + +if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite': + PthDistributions = RewritePthDistributions + + +def _first_line_re(): + """ + Return a regular expression based on first_line_re suitable for matching + strings. + """ + if isinstance(first_line_re.pattern, str): + return first_line_re + + # first_line_re in Python >=3.1.4 and >=3.2.1 is a bytes pattern. + return re.compile(first_line_re.pattern.decode()) + + +def auto_chmod(func, arg, exc): + if func in [os.unlink, os.remove] and os.name == 'nt': + chmod(arg, stat.S_IWRITE) + return func(arg) + et, ev, _ = sys.exc_info() + six.reraise(et, (ev[0], ev[1] + (" %s %s" % (func, arg)))) + + +def update_dist_caches(dist_path, fix_zipimporter_caches): + """ + Fix any globally cached `dist_path` related data + + `dist_path` should be a path of a newly installed egg distribution (zipped + or unzipped). + + sys.path_importer_cache contains finder objects that have been cached when + importing data from the original distribution. Any such finders need to be + cleared since the replacement distribution might be packaged differently, + e.g. a zipped egg distribution might get replaced with an unzipped egg + folder or vice versa. Having the old finders cached may then cause Python + to attempt loading modules from the replacement distribution using an + incorrect loader. + + zipimport.zipimporter objects are Python loaders charged with importing + data packaged inside zip archives. If stale loaders referencing the + original distribution, are left behind, they can fail to load modules from + the replacement distribution. E.g. if an old zipimport.zipimporter instance + is used to load data from a new zipped egg archive, it may cause the + operation to attempt to locate the requested data in the wrong location - + one indicated by the original distribution's zip archive directory + information. Such an operation may then fail outright, e.g. report having + read a 'bad local file header', or even worse, it may fail silently & + return invalid data. + + zipimport._zip_directory_cache contains cached zip archive directory + information for all existing zipimport.zipimporter instances and all such + instances connected to the same archive share the same cached directory + information. + + If asked, and the underlying Python implementation allows it, we can fix + all existing zipimport.zipimporter instances instead of having to track + them down and remove them one by one, by updating their shared cached zip + archive directory information. This, of course, assumes that the + replacement distribution is packaged as a zipped egg. + + If not asked to fix existing zipimport.zipimporter instances, we still do + our best to clear any remaining zipimport.zipimporter related cached data + that might somehow later get used when attempting to load data from the new + distribution and thus cause such load operations to fail. Note that when + tracking down such remaining stale data, we can not catch every conceivable + usage from here, and we clear only those that we know of and have found to + cause problems if left alive. Any remaining caches should be updated by + whomever is in charge of maintaining them, i.e. they should be ready to + handle us replacing their zip archives with new distributions at runtime. + + """ + # There are several other known sources of stale zipimport.zipimporter + # instances that we do not clear here, but might if ever given a reason to + # do so: + # * Global setuptools pkg_resources.working_set (a.k.a. 'master working + # set') may contain distributions which may in turn contain their + # zipimport.zipimporter loaders. + # * Several zipimport.zipimporter loaders held by local variables further + # up the function call stack when running the setuptools installation. + # * Already loaded modules may have their __loader__ attribute set to the + # exact loader instance used when importing them. Python 3.4 docs state + # that this information is intended mostly for introspection and so is + # not expected to cause us problems. + normalized_path = normalize_path(dist_path) + _uncache(normalized_path, sys.path_importer_cache) + if fix_zipimporter_caches: + _replace_zip_directory_cache_data(normalized_path) + else: + # Here, even though we do not want to fix existing and now stale + # zipimporter cache information, we still want to remove it. Related to + # Python's zip archive directory information cache, we clear each of + # its stale entries in two phases: + # 1. Clear the entry so attempting to access zip archive information + # via any existing stale zipimport.zipimporter instances fails. + # 2. Remove the entry from the cache so any newly constructed + # zipimport.zipimporter instances do not end up using old stale + # zip archive directory information. + # This whole stale data removal step does not seem strictly necessary, + # but has been left in because it was done before we started replacing + # the zip archive directory information cache content if possible, and + # there are no relevant unit tests that we can depend on to tell us if + # this is really needed. + _remove_and_clear_zip_directory_cache_data(normalized_path) + + +def _collect_zipimporter_cache_entries(normalized_path, cache): + """ + Return zipimporter cache entry keys related to a given normalized path. + + Alternative path spellings (e.g. those using different character case or + those using alternative path separators) related to the same path are + included. Any sub-path entries are included as well, i.e. those + corresponding to zip archives embedded in other zip archives. + + """ + result = [] + prefix_len = len(normalized_path) + for p in cache: + np = normalize_path(p) + if (np.startswith(normalized_path) and + np[prefix_len:prefix_len + 1] in (os.sep, '')): + result.append(p) + return result + + +def _update_zipimporter_cache(normalized_path, cache, updater=None): + """ + Update zipimporter cache data for a given normalized path. + + Any sub-path entries are processed as well, i.e. those corresponding to zip + archives embedded in other zip archives. + + Given updater is a callable taking a cache entry key and the original entry + (after already removing the entry from the cache), and expected to update + the entry and possibly return a new one to be inserted in its place. + Returning None indicates that the entry should not be replaced with a new + one. If no updater is given, the cache entries are simply removed without + any additional processing, the same as if the updater simply returned None. + + """ + for p in _collect_zipimporter_cache_entries(normalized_path, cache): + # N.B. pypy's custom zipimport._zip_directory_cache implementation does + # not support the complete dict interface: + # * Does not support item assignment, thus not allowing this function + # to be used only for removing existing cache entries. + # * Does not support the dict.pop() method, forcing us to use the + # get/del patterns instead. For more detailed information see the + # following links: + # https://github.com/pypa/setuptools/issues/202#issuecomment-202913420 + # http://bit.ly/2h9itJX + old_entry = cache[p] + del cache[p] + new_entry = updater and updater(p, old_entry) + if new_entry is not None: + cache[p] = new_entry + + +def _uncache(normalized_path, cache): + _update_zipimporter_cache(normalized_path, cache) + + +def _remove_and_clear_zip_directory_cache_data(normalized_path): + def clear_and_remove_cached_zip_archive_directory_data(path, old_entry): + old_entry.clear() + + _update_zipimporter_cache( + normalized_path, zipimport._zip_directory_cache, + updater=clear_and_remove_cached_zip_archive_directory_data) + + +# PyPy Python implementation does not allow directly writing to the +# zipimport._zip_directory_cache and so prevents us from attempting to correct +# its content. The best we can do there is clear the problematic cache content +# and have PyPy repopulate it as needed. The downside is that if there are any +# stale zipimport.zipimporter instances laying around, attempting to use them +# will fail due to not having its zip archive directory information available +# instead of being automatically corrected to use the new correct zip archive +# directory information. +if '__pypy__' in sys.builtin_module_names: + _replace_zip_directory_cache_data = \ + _remove_and_clear_zip_directory_cache_data +else: + + def _replace_zip_directory_cache_data(normalized_path): + def replace_cached_zip_archive_directory_data(path, old_entry): + # N.B. In theory, we could load the zip directory information just + # once for all updated path spellings, and then copy it locally and + # update its contained path strings to contain the correct + # spelling, but that seems like a way too invasive move (this cache + # structure is not officially documented anywhere and could in + # theory change with new Python releases) for no significant + # benefit. + old_entry.clear() + zipimport.zipimporter(path) + old_entry.update(zipimport._zip_directory_cache[path]) + return old_entry + + _update_zipimporter_cache( + normalized_path, zipimport._zip_directory_cache, + updater=replace_cached_zip_archive_directory_data) + + +def is_python(text, filename='<string>'): + "Is this string a valid Python script?" + try: + compile(text, filename, 'exec') + except (SyntaxError, TypeError): + return False + else: + return True + + +def is_sh(executable): + """Determine if the specified executable is a .sh (contains a #! line)""" + try: + with io.open(executable, encoding='latin-1') as fp: + magic = fp.read(2) + except (OSError, IOError): + return executable + return magic == '#!' + + +def nt_quote_arg(arg): + """Quote a command line argument according to Windows parsing rules""" + return subprocess.list2cmdline([arg]) + + +def is_python_script(script_text, filename): + """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc. + """ + if filename.endswith('.py') or filename.endswith('.pyw'): + return True # extension says it's Python + if is_python(script_text, filename): + return True # it's syntactically valid Python + if script_text.startswith('#!'): + # It begins with a '#!' line, so check if 'python' is in it somewhere + return 'python' in script_text.splitlines()[0].lower() + + return False # Not any Python I can recognize + + +try: + from os import chmod as _chmod +except ImportError: + # Jython compatibility + def _chmod(*args): + pass + + +def chmod(path, mode): + log.debug("changing mode of %s to %o", path, mode) + try: + _chmod(path, mode) + except os.error as e: + log.debug("chmod failed: %s", e) + + +class CommandSpec(list): + """ + A command spec for a #! header, specified as a list of arguments akin to + those passed to Popen. + """ + + options = [] + split_args = dict() + + @classmethod + def best(cls): + """ + Choose the best CommandSpec class based on environmental conditions. + """ + return cls + + @classmethod + def _sys_executable(cls): + _default = os.path.normpath(sys.executable) + return os.environ.get('__PYVENV_LAUNCHER__', _default) + + @classmethod + def from_param(cls, param): + """ + Construct a CommandSpec from a parameter to build_scripts, which may + be None. + """ + if isinstance(param, cls): + return param + if isinstance(param, list): + return cls(param) + if param is None: + return cls.from_environment() + # otherwise, assume it's a string. + return cls.from_string(param) + + @classmethod + def from_environment(cls): + return cls([cls._sys_executable()]) + + @classmethod + def from_string(cls, string): + """ + Construct a command spec from a simple string representing a command + line parseable by shlex.split. + """ + items = shlex.split(string, **cls.split_args) + return cls(items) + + def install_options(self, script_text): + self.options = shlex.split(self._extract_options(script_text)) + cmdline = subprocess.list2cmdline(self) + if not isascii(cmdline): + self.options[:0] = ['-x'] + + @staticmethod + def _extract_options(orig_script): + """ + Extract any options from the first line of the script. + """ + first = (orig_script + '\n').splitlines()[0] + match = _first_line_re().match(first) + options = match.group(1) or '' if match else '' + return options.strip() + + def as_header(self): + return self._render(self + list(self.options)) + + @staticmethod + def _strip_quotes(item): + _QUOTES = '"\'' + for q in _QUOTES: + if item.startswith(q) and item.endswith(q): + return item[1:-1] + return item + + @staticmethod + def _render(items): + cmdline = subprocess.list2cmdline( + CommandSpec._strip_quotes(item.strip()) for item in items) + return '#!' + cmdline + '\n' + + +# For pbr compat; will be removed in a future version. +sys_executable = CommandSpec._sys_executable() + + +class WindowsCommandSpec(CommandSpec): + split_args = dict(posix=False) + + +class ScriptWriter: + """ + Encapsulates behavior around writing entry point scripts for console and + gui apps. + """ + + template = textwrap.dedent(r""" + # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r + __requires__ = %(spec)r + import re + import sys + from pkg_resources import load_entry_point + + if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit( + load_entry_point(%(spec)r, %(group)r, %(name)r)() + ) + """).lstrip() + + command_spec_class = CommandSpec + + @classmethod + def get_script_args(cls, dist, executable=None, wininst=False): + # for backward compatibility + warnings.warn("Use get_args", EasyInstallDeprecationWarning) + writer = (WindowsScriptWriter if wininst else ScriptWriter).best() + header = cls.get_script_header("", executable, wininst) + return writer.get_args(dist, header) + + @classmethod + def get_script_header(cls, script_text, executable=None, wininst=False): + # for backward compatibility + warnings.warn("Use get_header", EasyInstallDeprecationWarning, stacklevel=2) + if wininst: + executable = "python.exe" + return cls.get_header(script_text, executable) + + @classmethod + def get_args(cls, dist, header=None): + """ + Yield write_script() argument tuples for a distribution's + console_scripts and gui_scripts entry points. + """ + if header is None: + header = cls.get_header() + spec = str(dist.as_requirement()) + for type_ in 'console', 'gui': + group = type_ + '_scripts' + for name, ep in dist.get_entry_map(group).items(): + cls._ensure_safe_name(name) + script_text = cls.template % locals() + args = cls._get_script_args(type_, name, header, script_text) + for res in args: + yield res + + @staticmethod + def _ensure_safe_name(name): + """ + Prevent paths in *_scripts entry point names. + """ + has_path_sep = re.search(r'[\\/]', name) + if has_path_sep: + raise ValueError("Path separators not allowed in script names") + + @classmethod + def get_writer(cls, force_windows): + # for backward compatibility + warnings.warn("Use best", EasyInstallDeprecationWarning) + return WindowsScriptWriter.best() if force_windows else cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter for this environment. + """ + if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'): + return WindowsScriptWriter.best() + else: + return cls + + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + # Simply write the stub with no extension. + yield (name, header + script_text) + + @classmethod + def get_header(cls, script_text="", executable=None): + """Create a #! line, getting options (if any) from script_text""" + cmd = cls.command_spec_class.best().from_param(executable) + cmd.install_options(script_text) + return cmd.as_header() + + +class WindowsScriptWriter(ScriptWriter): + command_spec_class = WindowsCommandSpec + + @classmethod + def get_writer(cls): + # for backward compatibility + warnings.warn("Use best", EasyInstallDeprecationWarning) + return cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter suitable for Windows + """ + writer_lookup = dict( + executable=WindowsExecutableLauncherWriter, + natural=cls, + ) + # for compatibility, use the executable launcher by default + launcher = os.environ.get('SETUPTOOLS_LAUNCHER', 'executable') + return writer_lookup[launcher] + + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + "For Windows, add a .py extension" + ext = dict(console='.pya', gui='.pyw')[type_] + if ext not in os.environ['PATHEXT'].lower().split(';'): + msg = ( + "{ext} not listed in PATHEXT; scripts will not be " + "recognized as executables." + ).format(**locals()) + warnings.warn(msg, UserWarning) + old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe'] + old.remove(ext) + header = cls._adjust_header(type_, header) + blockers = [name + x for x in old] + yield name + ext, header + script_text, 't', blockers + + @classmethod + def _adjust_header(cls, type_, orig_header): + """ + Make sure 'pythonw' is used for gui and and 'python' is used for + console (regardless of what sys.executable is). + """ + pattern = 'pythonw.exe' + repl = 'python.exe' + if type_ == 'gui': + pattern, repl = repl, pattern + pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) + new_header = pattern_ob.sub(string=orig_header, repl=repl) + return new_header if cls._use_header(new_header) else orig_header + + @staticmethod + def _use_header(new_header): + """ + Should _adjust_header use the replaced header? + + On non-windows systems, always use. On + Windows systems, only use the replaced header if it resolves + to an executable on the system. + """ + clean_header = new_header[2:-1].strip('"') + return sys.platform != 'win32' or find_executable(clean_header) + + +class WindowsExecutableLauncherWriter(WindowsScriptWriter): + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + """ + For Windows, add a .py extension and an .exe launcher + """ + if type_ == 'gui': + launcher_type = 'gui' + ext = '-script.pyw' + old = ['.pyw'] + else: + launcher_type = 'cli' + ext = '-script.py' + old = ['.py', '.pyc', '.pyo'] + hdr = cls._adjust_header(type_, header) + blockers = [name + x for x in old] + yield (name + ext, hdr + script_text, 't', blockers) + yield ( + name + '.exe', get_win_launcher(launcher_type), + 'b' # write in binary mode + ) + if not is_64bit(): + # install a manifest for the launcher to prevent Windows + # from detecting it as an installer (which it will for + # launchers like easy_install.exe). Consider only + # adding a manifest for launchers detected as installers. + # See Distribute #143 for details. + m_name = name + '.exe.manifest' + yield (m_name, load_launcher_manifest(name), 't') + + +# for backward-compatibility +get_script_args = ScriptWriter.get_script_args +get_script_header = ScriptWriter.get_script_header + + +def get_win_launcher(type): + """ + Load the Windows launcher (executable) suitable for launching a script. + + `type` should be either 'cli' or 'gui' + + Returns the executable as a byte string. + """ + launcher_fn = '%s.exe' % type + if is_64bit(): + launcher_fn = launcher_fn.replace(".", "-64.") + else: + launcher_fn = launcher_fn.replace(".", "-32.") + return resource_string('setuptools', launcher_fn) + + +def load_launcher_manifest(name): + manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml') + if six.PY2: + return manifest % vars() + else: + return manifest.decode('utf-8') % vars() + + +def rmtree(path, ignore_errors=False, onerror=auto_chmod): + return shutil.rmtree(path, ignore_errors, onerror) + + +def current_umask(): + tmp = os.umask(0o022) + os.umask(tmp) + return tmp + + +def bootstrap(): + # This function is called when setuptools*.egg is run using /bin/sh + import setuptools + + argv0 = os.path.dirname(setuptools.__path__[0]) + sys.argv[0] = argv0 + sys.argv.append(argv0) + main() + + +def main(argv=None, **kw): + from setuptools import setup + from setuptools.dist import Distribution + + class DistributionWithoutHelpCommands(Distribution): + common_usage = "" + + def _show_help(self, *args, **kw): + with _patch_usage(): + Distribution._show_help(self, *args, **kw) + + if argv is None: + argv = sys.argv[1:] + + with _patch_usage(): + setup( + script_args=['-q', 'easy_install', '-v'] + argv, + script_name=sys.argv[0] or 'easy_install', + distclass=DistributionWithoutHelpCommands, + **kw + ) + + +@contextlib.contextmanager +def _patch_usage(): + import distutils.core + USAGE = textwrap.dedent(""" + usage: %(script)s [options] requirement_or_url ... + or: %(script)s --help + """).lstrip() + + def gen_usage(script_name): + return USAGE % dict( + script=os.path.basename(script_name), + ) + + saved = distutils.core.gen_usage + distutils.core.gen_usage = gen_usage + try: + yield + finally: + distutils.core.gen_usage = saved + +class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in EasyInstall in SetupTools. Not ignored by default, unlike DeprecationWarning.""" + diff --git a/winvenv/Lib/site-packages/setuptools/command/egg_info.py b/winvenv/Lib/site-packages/setuptools/command/egg_info.py new file mode 100644 index 0000000..d9fe3da --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/egg_info.py @@ -0,0 +1,716 @@ +"""setuptools.command.egg_info + +Create a distribution's .egg-info directory and contents""" + +from distutils.filelist import FileList as _FileList +from distutils.errors import DistutilsInternalError +from distutils.util import convert_path +from distutils import log +import distutils.errors +import distutils.filelist +import os +import re +import sys +import io +import warnings +import time +import collections + +from setuptools.extern import six +from setuptools.extern.six.moves import map + +from setuptools import Command +from setuptools.command.sdist import sdist +from setuptools.command.sdist import walk_revctrl +from setuptools.command.setopt import edit_config +from setuptools.command import bdist_egg +from pkg_resources import ( + parse_requirements, safe_name, parse_version, + safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename) +import setuptools.unicode_utils as unicode_utils +from setuptools.glob import glob + +from setuptools.extern import packaging +from setuptools import SetuptoolsDeprecationWarning + +def translate_pattern(glob): + """ + Translate a file path glob like '*.txt' in to a regular expression. + This differs from fnmatch.translate which allows wildcards to match + directory separators. It also knows about '**/' which matches any number of + directories. + """ + pat = '' + + # This will split on '/' within [character classes]. This is deliberate. + chunks = glob.split(os.path.sep) + + sep = re.escape(os.sep) + valid_char = '[^%s]' % (sep,) + + for c, chunk in enumerate(chunks): + last_chunk = c == len(chunks) - 1 + + # Chunks that are a literal ** are globstars. They match anything. + if chunk == '**': + if last_chunk: + # Match anything if this is the last component + pat += '.*' + else: + # Match '(name/)*' + pat += '(?:%s+%s)*' % (valid_char, sep) + continue # Break here as the whole path component has been handled + + # Find any special characters in the remainder + i = 0 + chunk_len = len(chunk) + while i < chunk_len: + char = chunk[i] + if char == '*': + # Match any number of name characters + pat += valid_char + '*' + elif char == '?': + # Match a name character + pat += valid_char + elif char == '[': + # Character class + inner_i = i + 1 + # Skip initial !/] chars + if inner_i < chunk_len and chunk[inner_i] == '!': + inner_i = inner_i + 1 + if inner_i < chunk_len and chunk[inner_i] == ']': + inner_i = inner_i + 1 + + # Loop till the closing ] is found + while inner_i < chunk_len and chunk[inner_i] != ']': + inner_i = inner_i + 1 + + if inner_i >= chunk_len: + # Got to the end of the string without finding a closing ] + # Do not treat this as a matching group, but as a literal [ + pat += re.escape(char) + else: + # Grab the insides of the [brackets] + inner = chunk[i + 1:inner_i] + char_class = '' + + # Class negation + if inner[0] == '!': + char_class = '^' + inner = inner[1:] + + char_class += re.escape(inner) + pat += '[%s]' % (char_class,) + + # Skip to the end ] + i = inner_i + else: + pat += re.escape(char) + i += 1 + + # Join each chunk with the dir separator + if not last_chunk: + pat += sep + + pat += r'\Z' + return re.compile(pat, flags=re.MULTILINE|re.DOTALL) + + +class InfoCommon: + tag_build = None + tag_date = None + + @property + def name(self): + return safe_name(self.distribution.get_name()) + + def tagged_version(self): + version = self.distribution.get_version() + # egg_info may be called more than once for a distribution, + # in which case the version string already contains all tags. + if self.vtags and version.endswith(self.vtags): + return safe_version(version) + return safe_version(version + self.vtags) + + def tags(self): + version = '' + if self.tag_build: + version += self.tag_build + if self.tag_date: + version += time.strftime("-%Y%m%d") + return version + vtags = property(tags) + + +class egg_info(InfoCommon, Command): + description = "create a distribution's .egg-info directory" + + user_options = [ + ('egg-base=', 'e', "directory containing .egg-info directories" + " (default: top of the source tree)"), + ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), + ('tag-build=', 'b', "Specify explicit tag to add to version number"), + ('no-date', 'D', "Don't include date stamp [default]"), + ] + + boolean_options = ['tag-date'] + negative_opt = { + 'no-date': 'tag-date', + } + + def initialize_options(self): + self.egg_base = None + self.egg_name = None + self.egg_info = None + self.egg_version = None + self.broken_egg_info = False + + #################################### + # allow the 'tag_svn_revision' to be detected and + # set, supporting sdists built on older Setuptools. + @property + def tag_svn_revision(self): + pass + + @tag_svn_revision.setter + def tag_svn_revision(self, value): + pass + #################################### + + def save_version_info(self, filename): + """ + Materialize the value of date into the + build tag. Install build keys in a deterministic order + to avoid arbitrary reordering on subsequent builds. + """ + egg_info = collections.OrderedDict() + # follow the order these keys would have been added + # when PYTHONHASHSEED=0 + egg_info['tag_build'] = self.tags() + egg_info['tag_date'] = 0 + edit_config(filename, dict(egg_info=egg_info)) + + def finalize_options(self): + # Note: we need to capture the current value returned + # by `self.tagged_version()`, so we can later update + # `self.distribution.metadata.version` without + # repercussions. + self.egg_name = self.name + self.egg_version = self.tagged_version() + parsed_version = parse_version(self.egg_version) + + try: + is_version = isinstance(parsed_version, packaging.version.Version) + spec = ( + "%s==%s" if is_version else "%s===%s" + ) + list( + parse_requirements(spec % (self.egg_name, self.egg_version)) + ) + except ValueError: + raise distutils.errors.DistutilsOptionError( + "Invalid distribution name or version syntax: %s-%s" % + (self.egg_name, self.egg_version) + ) + + if self.egg_base is None: + dirs = self.distribution.package_dir + self.egg_base = (dirs or {}).get('', os.curdir) + + self.ensure_dirname('egg_base') + self.egg_info = to_filename(self.egg_name) + '.egg-info' + if self.egg_base != os.curdir: + self.egg_info = os.path.join(self.egg_base, self.egg_info) + if '-' in self.egg_name: + self.check_broken_egg_info() + + # Set package version for the benefit of dumber commands + # (e.g. sdist, bdist_wininst, etc.) + # + self.distribution.metadata.version = self.egg_version + + # If we bootstrapped around the lack of a PKG-INFO, as might be the + # case in a fresh checkout, make sure that any special tags get added + # to the version info + # + pd = self.distribution._patched_dist + if pd is not None and pd.key == self.egg_name.lower(): + pd._version = self.egg_version + pd._parsed_version = parse_version(self.egg_version) + self.distribution._patched_dist = None + + def write_or_delete_file(self, what, filename, data, force=False): + """Write `data` to `filename` or delete if empty + + If `data` is non-empty, this routine is the same as ``write_file()``. + If `data` is empty but not ``None``, this is the same as calling + ``delete_file(filename)`. If `data` is ``None``, then this is a no-op + unless `filename` exists, in which case a warning is issued about the + orphaned file (if `force` is false), or deleted (if `force` is true). + """ + if data: + self.write_file(what, filename, data) + elif os.path.exists(filename): + if data is None and not force: + log.warn( + "%s not set in setup(), but %s exists", what, filename + ) + return + else: + self.delete_file(filename) + + def write_file(self, what, filename, data): + """Write `data` to `filename` (if not a dry run) after announcing it + + `what` is used in a log message to identify what is being written + to the file. + """ + log.info("writing %s to %s", what, filename) + if six.PY3: + data = data.encode("utf-8") + if not self.dry_run: + f = open(filename, 'wb') + f.write(data) + f.close() + + def delete_file(self, filename): + """Delete `filename` (if not a dry run) after announcing it""" + log.info("deleting %s", filename) + if not self.dry_run: + os.unlink(filename) + + def run(self): + self.mkpath(self.egg_info) + os.utime(self.egg_info, None) + installer = self.distribution.fetch_build_egg + for ep in iter_entry_points('egg_info.writers'): + ep.require(installer=installer) + writer = ep.resolve() + writer(self, ep.name, os.path.join(self.egg_info, ep.name)) + + # Get rid of native_libs.txt if it was put there by older bdist_egg + nl = os.path.join(self.egg_info, "native_libs.txt") + if os.path.exists(nl): + self.delete_file(nl) + + self.find_sources() + + def find_sources(self): + """Generate SOURCES.txt manifest file""" + manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") + mm = manifest_maker(self.distribution) + mm.manifest = manifest_filename + mm.run() + self.filelist = mm.filelist + + def check_broken_egg_info(self): + bei = self.egg_name + '.egg-info' + if self.egg_base != os.curdir: + bei = os.path.join(self.egg_base, bei) + if os.path.exists(bei): + log.warn( + "-" * 78 + '\n' + "Note: Your current .egg-info directory has a '-' in its name;" + '\nthis will not work correctly with "setup.py develop".\n\n' + 'Please rename %s to %s to correct this problem.\n' + '-' * 78, + bei, self.egg_info + ) + self.broken_egg_info = self.egg_info + self.egg_info = bei # make it work for now + + +class FileList(_FileList): + # Implementations of the various MANIFEST.in commands + + def process_template_line(self, line): + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dir_pattern). + (action, patterns, dir, dir_pattern) = self._parse_template_line(line) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + self.debug_print("include " + ' '.join(patterns)) + for pattern in patterns: + if not self.include(pattern): + log.warn("warning: no files found matching '%s'", pattern) + + elif action == 'exclude': + self.debug_print("exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.exclude(pattern): + log.warn(("warning: no previously-included files " + "found matching '%s'"), pattern) + + elif action == 'global-include': + self.debug_print("global-include " + ' '.join(patterns)) + for pattern in patterns: + if not self.global_include(pattern): + log.warn(("warning: no files found matching '%s' " + "anywhere in distribution"), pattern) + + elif action == 'global-exclude': + self.debug_print("global-exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.global_exclude(pattern): + log.warn(("warning: no previously-included files matching " + "'%s' found anywhere in distribution"), + pattern) + + elif action == 'recursive-include': + self.debug_print("recursive-include %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.recursive_include(dir, pattern): + log.warn(("warning: no files found matching '%s' " + "under directory '%s'"), + pattern, dir) + + elif action == 'recursive-exclude': + self.debug_print("recursive-exclude %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.recursive_exclude(dir, pattern): + log.warn(("warning: no previously-included files matching " + "'%s' found under directory '%s'"), + pattern, dir) + + elif action == 'graft': + self.debug_print("graft " + dir_pattern) + if not self.graft(dir_pattern): + log.warn("warning: no directories found matching '%s'", + dir_pattern) + + elif action == 'prune': + self.debug_print("prune " + dir_pattern) + if not self.prune(dir_pattern): + log.warn(("no previously-included directories found " + "matching '%s'"), dir_pattern) + + else: + raise DistutilsInternalError( + "this cannot happen: invalid action '%s'" % action) + + def _remove_files(self, predicate): + """ + Remove all files from the file list that match the predicate. + Return True if any matching files were removed + """ + found = False + for i in range(len(self.files) - 1, -1, -1): + if predicate(self.files[i]): + self.debug_print(" removing " + self.files[i]) + del self.files[i] + found = True + return found + + def include(self, pattern): + """Include files that match 'pattern'.""" + found = [f for f in glob(pattern) if not os.path.isdir(f)] + self.extend(found) + return bool(found) + + def exclude(self, pattern): + """Exclude files that match 'pattern'.""" + match = translate_pattern(pattern) + return self._remove_files(match.match) + + def recursive_include(self, dir, pattern): + """ + Include all files anywhere in 'dir/' that match the pattern. + """ + full_pattern = os.path.join(dir, '**', pattern) + found = [f for f in glob(full_pattern, recursive=True) + if not os.path.isdir(f)] + self.extend(found) + return bool(found) + + def recursive_exclude(self, dir, pattern): + """ + Exclude any file anywhere in 'dir/' that match the pattern. + """ + match = translate_pattern(os.path.join(dir, '**', pattern)) + return self._remove_files(match.match) + + def graft(self, dir): + """Include all files from 'dir/'.""" + found = [ + item + for match_dir in glob(dir) + for item in distutils.filelist.findall(match_dir) + ] + self.extend(found) + return bool(found) + + def prune(self, dir): + """Filter out files from 'dir/'.""" + match = translate_pattern(os.path.join(dir, '**')) + return self._remove_files(match.match) + + def global_include(self, pattern): + """ + Include all files anywhere in the current directory that match the + pattern. This is very inefficient on large file trees. + """ + if self.allfiles is None: + self.findall() + match = translate_pattern(os.path.join('**', pattern)) + found = [f for f in self.allfiles if match.match(f)] + self.extend(found) + return bool(found) + + def global_exclude(self, pattern): + """ + Exclude all files anywhere that match the pattern. + """ + match = translate_pattern(os.path.join('**', pattern)) + return self._remove_files(match.match) + + def append(self, item): + if item.endswith('\r'): # Fix older sdists built on Windows + item = item[:-1] + path = convert_path(item) + + if self._safe_path(path): + self.files.append(path) + + def extend(self, paths): + self.files.extend(filter(self._safe_path, paths)) + + def _repair(self): + """ + Replace self.files with only safe paths + + Because some owners of FileList manipulate the underlying + ``files`` attribute directly, this method must be called to + repair those paths. + """ + self.files = list(filter(self._safe_path, self.files)) + + def _safe_path(self, path): + enc_warn = "'%s' not %s encodable -- skipping" + + # To avoid accidental trans-codings errors, first to unicode + u_path = unicode_utils.filesys_decode(path) + if u_path is None: + log.warn("'%s' in unexpected encoding -- skipping" % path) + return False + + # Must ensure utf-8 encodability + utf8_path = unicode_utils.try_encode(u_path, "utf-8") + if utf8_path is None: + log.warn(enc_warn, path, 'utf-8') + return False + + try: + # accept is either way checks out + if os.path.exists(u_path) or os.path.exists(utf8_path): + return True + # this will catch any encode errors decoding u_path + except UnicodeEncodeError: + log.warn(enc_warn, path, sys.getfilesystemencoding()) + + +class manifest_maker(sdist): + template = "MANIFEST.in" + + def initialize_options(self): + self.use_defaults = 1 + self.prune = 1 + self.manifest_only = 1 + self.force_manifest = 1 + + def finalize_options(self): + pass + + def run(self): + self.filelist = FileList() + if not os.path.exists(self.manifest): + self.write_manifest() # it must exist so it'll get in the list + self.add_defaults() + if os.path.exists(self.template): + self.read_template() + self.prune_file_list() + self.filelist.sort() + self.filelist.remove_duplicates() + self.write_manifest() + + def _manifest_normalize(self, path): + path = unicode_utils.filesys_decode(path) + return path.replace(os.sep, '/') + + def write_manifest(self): + """ + Write the file list in 'self.filelist' to the manifest file + named by 'self.manifest'. + """ + self.filelist._repair() + + # Now _repairs should encodability, but not unicode + files = [self._manifest_normalize(f) for f in self.filelist.files] + msg = "writing manifest file '%s'" % self.manifest + self.execute(write_file, (self.manifest, files), msg) + + def warn(self, msg): + if not self._should_suppress_warning(msg): + sdist.warn(self, msg) + + @staticmethod + def _should_suppress_warning(msg): + """ + suppress missing-file warnings from sdist + """ + return re.match(r"standard file .*not found", msg) + + def add_defaults(self): + sdist.add_defaults(self) + self.filelist.append(self.template) + self.filelist.append(self.manifest) + rcfiles = list(walk_revctrl()) + if rcfiles: + self.filelist.extend(rcfiles) + elif os.path.exists(self.manifest): + self.read_manifest() + + if os.path.exists("setup.py"): + # setup.py should be included by default, even if it's not + # the script called to create the sdist + self.filelist.append("setup.py") + + ei_cmd = self.get_finalized_command('egg_info') + self.filelist.graft(ei_cmd.egg_info) + + def prune_file_list(self): + build = self.get_finalized_command('build') + base_dir = self.distribution.get_fullname() + self.filelist.prune(build.build_base) + self.filelist.prune(base_dir) + sep = re.escape(os.sep) + self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, + is_regex=1) + + +def write_file(filename, contents): + """Create a file with the specified name and write 'contents' (a + sequence of strings without line terminators) to it. + """ + contents = "\n".join(contents) + + # assuming the contents has been vetted for utf-8 encoding + contents = contents.encode("utf-8") + + with open(filename, "wb") as f: # always write POSIX-style manifest + f.write(contents) + + +def write_pkg_info(cmd, basename, filename): + log.info("writing %s", filename) + if not cmd.dry_run: + metadata = cmd.distribution.metadata + metadata.version, oldver = cmd.egg_version, metadata.version + metadata.name, oldname = cmd.egg_name, metadata.name + + try: + # write unescaped data to PKG-INFO, so older pkg_resources + # can still parse it + metadata.write_pkg_info(cmd.egg_info) + finally: + metadata.name, metadata.version = oldname, oldver + + safe = getattr(cmd.distribution, 'zip_safe', None) + + bdist_egg.write_safety_flag(cmd.egg_info, safe) + + +def warn_depends_obsolete(cmd, basename, filename): + if os.path.exists(filename): + log.warn( + "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" + "Use the install_requires/extras_require setup() args instead." + ) + + +def _write_requirements(stream, reqs): + lines = yield_lines(reqs or ()) + append_cr = lambda line: line + '\n' + lines = map(append_cr, lines) + stream.writelines(lines) + + +def write_requirements(cmd, basename, filename): + dist = cmd.distribution + data = six.StringIO() + _write_requirements(data, dist.install_requires) + extras_require = dist.extras_require or {} + for extra in sorted(extras_require): + data.write('\n[{extra}]\n'.format(**vars())) + _write_requirements(data, extras_require[extra]) + cmd.write_or_delete_file("requirements", filename, data.getvalue()) + + +def write_setup_requirements(cmd, basename, filename): + data = io.StringIO() + _write_requirements(data, cmd.distribution.setup_requires) + cmd.write_or_delete_file("setup-requirements", filename, data.getvalue()) + + +def write_toplevel_names(cmd, basename, filename): + pkgs = dict.fromkeys( + [ + k.split('.', 1)[0] + for k in cmd.distribution.iter_distribution_names() + ] + ) + cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') + + +def overwrite_arg(cmd, basename, filename): + write_arg(cmd, basename, filename, True) + + +def write_arg(cmd, basename, filename, force=False): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = '\n'.join(value) + '\n' + cmd.write_or_delete_file(argname, filename, value, force) + + +def write_entries(cmd, basename, filename): + ep = cmd.distribution.entry_points + + if isinstance(ep, six.string_types) or ep is None: + data = ep + elif ep is not None: + data = [] + for section, contents in sorted(ep.items()): + if not isinstance(contents, six.string_types): + contents = EntryPoint.parse_group(section, contents) + contents = '\n'.join(sorted(map(str, contents.values()))) + data.append('[%s]\n%s\n\n' % (section, contents)) + data = ''.join(data) + + cmd.write_or_delete_file('entry points', filename, data, True) + + +def get_pkg_info_revision(): + """ + Get a -r### off of PKG-INFO Version in case this is an sdist of + a subversion revision. + """ + warnings.warn("get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning) + if os.path.exists('PKG-INFO'): + with io.open('PKG-INFO') as f: + for line in f: + match = re.match(r"Version:.*-r(\d+)\s*$", line) + if match: + return int(match.group(1)) + return 0 + + +class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in eggInfo in setupTools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/winvenv/Lib/site-packages/setuptools/command/install.py b/winvenv/Lib/site-packages/setuptools/command/install.py new file mode 100644 index 0000000..31a5ddb --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/install.py @@ -0,0 +1,125 @@ +from distutils.errors import DistutilsArgError +import inspect +import glob +import warnings +import platform +import distutils.command.install as orig + +import setuptools + +# Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for +# now. See https://github.com/pypa/setuptools/issues/199/ +_install = orig.install + + +class install(orig.install): + """Use easy_install to install the package, w/dependencies""" + + user_options = orig.install.user_options + [ + ('old-and-unmanageable', None, "Try not to use this!"), + ('single-version-externally-managed', None, + "used by system package builders to create 'flat' eggs"), + ] + boolean_options = orig.install.boolean_options + [ + 'old-and-unmanageable', 'single-version-externally-managed', + ] + new_commands = [ + ('install_egg_info', lambda self: True), + ('install_scripts', lambda self: True), + ] + _nc = dict(new_commands) + + def initialize_options(self): + orig.install.initialize_options(self) + self.old_and_unmanageable = None + self.single_version_externally_managed = None + + def finalize_options(self): + orig.install.finalize_options(self) + if self.root: + self.single_version_externally_managed = True + elif self.single_version_externally_managed: + if not self.root and not self.record: + raise DistutilsArgError( + "You must specify --record or --root when building system" + " packages" + ) + + def handle_extra_path(self): + if self.root or self.single_version_externally_managed: + # explicit backward-compatibility mode, allow extra_path to work + return orig.install.handle_extra_path(self) + + # Ignore extra_path when installing an egg (or being run by another + # command without --root or --single-version-externally-managed + self.path_file = None + self.extra_dirs = '' + + def run(self): + # Explicit request for old-style install? Just do it + if self.old_and_unmanageable or self.single_version_externally_managed: + return orig.install.run(self) + + if not self._called_from_setup(inspect.currentframe()): + # Run in backward-compatibility mode to support bdist_* commands. + orig.install.run(self) + else: + self.do_egg_install() + + @staticmethod + def _called_from_setup(run_frame): + """ + Attempt to detect whether run() was called from setup() or by another + command. If called by setup(), the parent caller will be the + 'run_command' method in 'distutils.dist', and *its* caller will be + the 'run_commands' method. If called any other way, the + immediate caller *might* be 'run_command', but it won't have been + called by 'run_commands'. Return True in that case or if a call stack + is unavailable. Return False otherwise. + """ + if run_frame is None: + msg = "Call stack not available. bdist_* commands may fail." + warnings.warn(msg) + if platform.python_implementation() == 'IronPython': + msg = "For best results, pass -X:Frames to enable call stack." + warnings.warn(msg) + return True + res = inspect.getouterframes(run_frame)[2] + caller, = res[:1] + info = inspect.getframeinfo(caller) + caller_module = caller.f_globals.get('__name__', '') + return ( + caller_module == 'distutils.dist' + and info.function == 'run_commands' + ) + + def do_egg_install(self): + + easy_install = self.distribution.get_command_class('easy_install') + + cmd = easy_install( + self.distribution, args="x", root=self.root, record=self.record, + ) + cmd.ensure_finalized() # finalize before bdist_egg munges install cmd + cmd.always_copy_from = '.' # make sure local-dir eggs get installed + + # pick up setup-dir .egg files only: no .egg-info + cmd.package_index.scan(glob.glob('*.egg')) + + self.run_command('bdist_egg') + args = [self.distribution.get_command_obj('bdist_egg').egg_output] + + if setuptools.bootstrap_install_from: + # Bootstrap self-installation of setuptools + args.insert(0, setuptools.bootstrap_install_from) + + cmd.args = args + cmd.run() + setuptools.bootstrap_install_from = None + + +# XXX Python 3.1 doesn't see _nc if this is inside the class +install.sub_commands = ( + [cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc] + + install.new_commands +) diff --git a/winvenv/Lib/site-packages/setuptools/command/install_egg_info.py b/winvenv/Lib/site-packages/setuptools/command/install_egg_info.py new file mode 100644 index 0000000..edc4718 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/install_egg_info.py @@ -0,0 +1,62 @@ +from distutils import log, dir_util +import os + +from setuptools import Command +from setuptools import namespaces +from setuptools.archive_util import unpack_archive +import pkg_resources + + +class install_egg_info(namespaces.Installer, Command): + """Install an .egg-info directory for the package""" + + description = "Install an .egg-info directory for the package" + + user_options = [ + ('install-dir=', 'd', "directory to install to"), + ] + + def initialize_options(self): + self.install_dir = None + + def finalize_options(self): + self.set_undefined_options('install_lib', + ('install_dir', 'install_dir')) + ei_cmd = self.get_finalized_command("egg_info") + basename = pkg_resources.Distribution( + None, None, ei_cmd.egg_name, ei_cmd.egg_version + ).egg_name() + '.egg-info' + self.source = ei_cmd.egg_info + self.target = os.path.join(self.install_dir, basename) + self.outputs = [] + + def run(self): + self.run_command('egg_info') + if os.path.isdir(self.target) and not os.path.islink(self.target): + dir_util.remove_tree(self.target, dry_run=self.dry_run) + elif os.path.exists(self.target): + self.execute(os.unlink, (self.target,), "Removing " + self.target) + if not self.dry_run: + pkg_resources.ensure_directory(self.target) + self.execute( + self.copytree, (), "Copying %s to %s" % (self.source, self.target) + ) + self.install_namespaces() + + def get_outputs(self): + return self.outputs + + def copytree(self): + # Copy the .egg-info tree to site-packages + def skimmer(src, dst): + # filter out source-control directories; note that 'src' is always + # a '/'-separated path, regardless of platform. 'dst' is a + # platform-specific path. + for skip in '.svn/', 'CVS/': + if src.startswith(skip) or '/' + skip in src: + return None + self.outputs.append(dst) + log.debug("Copying %s to %s", src, dst) + return dst + + unpack_archive(self.source, self.target, skimmer) diff --git a/winvenv/Lib/site-packages/setuptools/command/install_lib.py b/winvenv/Lib/site-packages/setuptools/command/install_lib.py new file mode 100644 index 0000000..2b31c3e --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/install_lib.py @@ -0,0 +1,121 @@ +import os +import imp +from itertools import product, starmap +import distutils.command.install_lib as orig + + +class install_lib(orig.install_lib): + """Don't add compiled flags to filenames of non-Python files""" + + def run(self): + self.build() + outfiles = self.install() + if outfiles is not None: + # always compile, in case we have any extension stubs to deal with + self.byte_compile(outfiles) + + def get_exclusions(self): + """ + Return a collections.Sized collections.Container of paths to be + excluded for single_version_externally_managed installations. + """ + all_packages = ( + pkg + for ns_pkg in self._get_SVEM_NSPs() + for pkg in self._all_packages(ns_pkg) + ) + + excl_specs = product(all_packages, self._gen_exclusion_paths()) + return set(starmap(self._exclude_pkg_path, excl_specs)) + + def _exclude_pkg_path(self, pkg, exclusion_path): + """ + Given a package name and exclusion path within that package, + compute the full exclusion path. + """ + parts = pkg.split('.') + [exclusion_path] + return os.path.join(self.install_dir, *parts) + + @staticmethod + def _all_packages(pkg_name): + """ + >>> list(install_lib._all_packages('foo.bar.baz')) + ['foo.bar.baz', 'foo.bar', 'foo'] + """ + while pkg_name: + yield pkg_name + pkg_name, sep, child = pkg_name.rpartition('.') + + def _get_SVEM_NSPs(self): + """ + Get namespace packages (list) but only for + single_version_externally_managed installations and empty otherwise. + """ + # TODO: is it necessary to short-circuit here? i.e. what's the cost + # if get_finalized_command is called even when namespace_packages is + # False? + if not self.distribution.namespace_packages: + return [] + + install_cmd = self.get_finalized_command('install') + svem = install_cmd.single_version_externally_managed + + return self.distribution.namespace_packages if svem else [] + + @staticmethod + def _gen_exclusion_paths(): + """ + Generate file paths to be excluded for namespace packages (bytecode + cache files). + """ + # always exclude the package module itself + yield '__init__.py' + + yield '__init__.pyc' + yield '__init__.pyo' + + if not hasattr(imp, 'get_tag'): + return + + base = os.path.join('__pycache__', '__init__.' + imp.get_tag()) + yield base + '.pyc' + yield base + '.pyo' + yield base + '.opt-1.pyc' + yield base + '.opt-2.pyc' + + def copy_tree( + self, infile, outfile, + preserve_mode=1, preserve_times=1, preserve_symlinks=0, level=1 + ): + assert preserve_mode and preserve_times and not preserve_symlinks + exclude = self.get_exclusions() + + if not exclude: + return orig.install_lib.copy_tree(self, infile, outfile) + + # Exclude namespace package __init__.py* files from the output + + from setuptools.archive_util import unpack_directory + from distutils import log + + outfiles = [] + + def pf(src, dst): + if dst in exclude: + log.warn("Skipping installation of %s (namespace package)", + dst) + return False + + log.info("copying %s -> %s", src, os.path.dirname(dst)) + outfiles.append(dst) + return dst + + unpack_directory(infile, outfile, pf) + return outfiles + + def get_outputs(self): + outputs = orig.install_lib.get_outputs(self) + exclude = self.get_exclusions() + if exclude: + return [f for f in outputs if f not in exclude] + return outputs diff --git a/winvenv/Lib/site-packages/setuptools/command/install_scripts.py b/winvenv/Lib/site-packages/setuptools/command/install_scripts.py new file mode 100644 index 0000000..1623427 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/install_scripts.py @@ -0,0 +1,65 @@ +from distutils import log +import distutils.command.install_scripts as orig +import os +import sys + +from pkg_resources import Distribution, PathMetadata, ensure_directory + + +class install_scripts(orig.install_scripts): + """Do normal script install, plus any egg_info wrapper scripts""" + + def initialize_options(self): + orig.install_scripts.initialize_options(self) + self.no_ep = False + + def run(self): + import setuptools.command.easy_install as ei + + self.run_command("egg_info") + if self.distribution.scripts: + orig.install_scripts.run(self) # run first to set up self.outfiles + else: + self.outfiles = [] + if self.no_ep: + # don't install entry point scripts into .egg file! + return + + ei_cmd = self.get_finalized_command("egg_info") + dist = Distribution( + ei_cmd.egg_base, PathMetadata(ei_cmd.egg_base, ei_cmd.egg_info), + ei_cmd.egg_name, ei_cmd.egg_version, + ) + bs_cmd = self.get_finalized_command('build_scripts') + exec_param = getattr(bs_cmd, 'executable', None) + bw_cmd = self.get_finalized_command("bdist_wininst") + is_wininst = getattr(bw_cmd, '_is_running', False) + writer = ei.ScriptWriter + if is_wininst: + exec_param = "python.exe" + writer = ei.WindowsScriptWriter + if exec_param == sys.executable: + # In case the path to the Python executable contains a space, wrap + # it so it's not split up. + exec_param = [exec_param] + # resolve the writer to the environment + writer = writer.best() + cmd = writer.command_spec_class.best().from_param(exec_param) + for args in writer.get_args(dist, cmd.as_header()): + self.write_script(*args) + + def write_script(self, script_name, contents, mode="t", *ignored): + """Write an executable file to the scripts directory""" + from setuptools.command.easy_install import chmod, current_umask + + log.info("Installing %s script to %s", script_name, self.install_dir) + target = os.path.join(self.install_dir, script_name) + self.outfiles.append(target) + + mask = current_umask() + if not self.dry_run: + ensure_directory(target) + f = open(target, "w" + mode) + f.write(contents) + f.close() + chmod(target, 0o777 - mask) diff --git a/winvenv/Lib/site-packages/setuptools/command/launcher manifest.xml b/winvenv/Lib/site-packages/setuptools/command/launcher manifest.xml new file mode 100644 index 0000000..5972a96 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/launcher manifest.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <assemblyIdentity version="1.0.0.0" + processorArchitecture="X86" + name="%(name)s" + type="win32"/> + <!-- Identify the application security requirements. --> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level="asInvoker" uiAccess="false"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly> diff --git a/winvenv/Lib/site-packages/setuptools/command/py36compat.py b/winvenv/Lib/site-packages/setuptools/command/py36compat.py new file mode 100644 index 0000000..61063e7 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/py36compat.py @@ -0,0 +1,136 @@ +import os +from glob import glob +from distutils.util import convert_path +from distutils.command import sdist + +from setuptools.extern.six.moves import filter + + +class sdist_add_defaults: + """ + Mix-in providing forward-compatibility for functionality as found in + distutils on Python 3.7. + + Do not edit the code in this class except to update functionality + as implemented in distutils. Instead, override in the subclass. + """ + + def add_defaults(self): + """Add all the default files to self.filelist: + - README or README.txt + - setup.py + - test/test*.py + - all pure Python modules mentioned in setup script + - all files pointed by package_data (build_py) + - all files defined in data_files. + - all files defined as scripts. + - all C sources listed as part of extensions or C libraries + in the setup script (doesn't catch C headers!) + Warns if (README or README.txt) or setup.py are missing; everything + else is optional. + """ + self._add_defaults_standards() + self._add_defaults_optional() + self._add_defaults_python() + self._add_defaults_data_files() + self._add_defaults_ext() + self._add_defaults_c_libs() + self._add_defaults_scripts() + + @staticmethod + def _cs_path_exists(fspath): + """ + Case-sensitive path existence check + + >>> sdist_add_defaults._cs_path_exists(__file__) + True + >>> sdist_add_defaults._cs_path_exists(__file__.upper()) + False + """ + if not os.path.exists(fspath): + return False + # make absolute so we always have a directory + abspath = os.path.abspath(fspath) + directory, filename = os.path.split(abspath) + return filename in os.listdir(directory) + + def _add_defaults_standards(self): + standards = [self.READMES, self.distribution.script_name] + for fn in standards: + if isinstance(fn, tuple): + alts = fn + got_it = False + for fn in alts: + if self._cs_path_exists(fn): + got_it = True + self.filelist.append(fn) + break + + if not got_it: + self.warn("standard file not found: should have one of " + + ', '.join(alts)) + else: + if self._cs_path_exists(fn): + self.filelist.append(fn) + else: + self.warn("standard file '%s' not found" % fn) + + def _add_defaults_optional(self): + optional = ['test/test*.py', 'setup.cfg'] + for pattern in optional: + files = filter(os.path.isfile, glob(pattern)) + self.filelist.extend(files) + + def _add_defaults_python(self): + # build_py is used to get: + # - python modules + # - files defined in package_data + build_py = self.get_finalized_command('build_py') + + # getting python files + if self.distribution.has_pure_modules(): + self.filelist.extend(build_py.get_source_files()) + + # getting package_data files + # (computed in build_py.data_files by build_py.finalize_options) + for pkg, src_dir, build_dir, filenames in build_py.data_files: + for filename in filenames: + self.filelist.append(os.path.join(src_dir, filename)) + + def _add_defaults_data_files(self): + # getting distribution.data_files + if self.distribution.has_data_files(): + for item in self.distribution.data_files: + if isinstance(item, str): + # plain file + item = convert_path(item) + if os.path.isfile(item): + self.filelist.append(item) + else: + # a (dirname, filenames) tuple + dirname, filenames = item + for f in filenames: + f = convert_path(f) + if os.path.isfile(f): + self.filelist.append(f) + + def _add_defaults_ext(self): + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + self.filelist.extend(build_ext.get_source_files()) + + def _add_defaults_c_libs(self): + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.filelist.extend(build_clib.get_source_files()) + + def _add_defaults_scripts(self): + if self.distribution.has_scripts(): + build_scripts = self.get_finalized_command('build_scripts') + self.filelist.extend(build_scripts.get_source_files()) + + +if hasattr(sdist.sdist, '_add_defaults_standards'): + # disable the functionality already available upstream + class sdist_add_defaults: + pass diff --git a/winvenv/Lib/site-packages/setuptools/command/register.py b/winvenv/Lib/site-packages/setuptools/command/register.py new file mode 100644 index 0000000..98bc015 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/register.py @@ -0,0 +1,18 @@ +from distutils import log +import distutils.command.register as orig + + +class register(orig.register): + __doc__ = orig.register.__doc__ + + def run(self): + try: + # Make sure that we are using valid current name/version info + self.run_command('egg_info') + orig.register.run(self) + finally: + self.announce( + "WARNING: Registering is deprecated, use twine to " + "upload instead (https://pypi.org/p/twine/)", + log.WARN + ) diff --git a/winvenv/Lib/site-packages/setuptools/command/rotate.py b/winvenv/Lib/site-packages/setuptools/command/rotate.py new file mode 100644 index 0000000..b89353f --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/rotate.py @@ -0,0 +1,66 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsOptionError +import os +import shutil + +from setuptools.extern import six + +from setuptools import Command + + +class rotate(Command): + """Delete older distributions""" + + description = "delete older distributions, keeping N newest files" + user_options = [ + ('match=', 'm', "patterns to match (required)"), + ('dist-dir=', 'd', "directory where the distributions are"), + ('keep=', 'k', "number of matching distributions to keep"), + ] + + boolean_options = [] + + def initialize_options(self): + self.match = None + self.dist_dir = None + self.keep = None + + def finalize_options(self): + if self.match is None: + raise DistutilsOptionError( + "Must specify one or more (comma-separated) match patterns " + "(e.g. '.zip' or '.egg')" + ) + if self.keep is None: + raise DistutilsOptionError("Must specify number of files to keep") + try: + self.keep = int(self.keep) + except ValueError: + raise DistutilsOptionError("--keep must be an integer") + if isinstance(self.match, six.string_types): + self.match = [ + convert_path(p.strip()) for p in self.match.split(',') + ] + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + + def run(self): + self.run_command("egg_info") + from glob import glob + + for pattern in self.match: + pattern = self.distribution.get_name() + '*' + pattern + files = glob(os.path.join(self.dist_dir, pattern)) + files = [(os.path.getmtime(f), f) for f in files] + files.sort() + files.reverse() + + log.info("%d file(s) matching %s", len(files), pattern) + files = files[self.keep:] + for (t, f) in files: + log.info("Deleting %s", f) + if not self.dry_run: + if os.path.isdir(f): + shutil.rmtree(f) + else: + os.unlink(f) diff --git a/winvenv/Lib/site-packages/setuptools/command/saveopts.py b/winvenv/Lib/site-packages/setuptools/command/saveopts.py new file mode 100644 index 0000000..611cec5 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/saveopts.py @@ -0,0 +1,22 @@ +from setuptools.command.setopt import edit_config, option_base + + +class saveopts(option_base): + """Save command-line options to a file""" + + description = "save supplied options to setup.cfg or other config file" + + def run(self): + dist = self.distribution + settings = {} + + for cmd in dist.command_options: + + if cmd == 'saveopts': + continue # don't save our own options! + + for opt, (src, val) in dist.get_option_dict(cmd).items(): + if src == "command line": + settings.setdefault(cmd, {})[opt] = val + + edit_config(self.filename, settings, self.dry_run) diff --git a/winvenv/Lib/site-packages/setuptools/command/sdist.py b/winvenv/Lib/site-packages/setuptools/command/sdist.py new file mode 100644 index 0000000..bcfae4d --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/sdist.py @@ -0,0 +1,200 @@ +from distutils import log +import distutils.command.sdist as orig +import os +import sys +import io +import contextlib + +from setuptools.extern import six + +from .py36compat import sdist_add_defaults + +import pkg_resources + +_default_revctrl = list + + +def walk_revctrl(dirname=''): + """Find all files under revision control""" + for ep in pkg_resources.iter_entry_points('setuptools.file_finders'): + for item in ep.load()(dirname): + yield item + + +class sdist(sdist_add_defaults, orig.sdist): + """Smart sdist that finds anything supported by revision control""" + + user_options = [ + ('formats=', None, + "formats for source distribution (comma-separated list)"), + ('keep-temp', 'k', + "keep the distribution tree around after creating " + + "archive file(s)"), + ('dist-dir=', 'd', + "directory to put the source distribution archive(s) in " + "[default: dist]"), + ] + + negative_opt = {} + + README_EXTENSIONS = ['', '.rst', '.txt', '.md'] + READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS) + + def run(self): + self.run_command('egg_info') + ei_cmd = self.get_finalized_command('egg_info') + self.filelist = ei_cmd.filelist + self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt')) + self.check_readme() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + self.make_distribution() + + dist_files = getattr(self.distribution, 'dist_files', []) + for file in self.archive_files: + data = ('sdist', '', file) + if data not in dist_files: + dist_files.append(data) + + def initialize_options(self): + orig.sdist.initialize_options(self) + + self._default_to_gztar() + + def _default_to_gztar(self): + # only needed on Python prior to 3.6. + if sys.version_info >= (3, 6, 0, 'beta', 1): + return + self.formats = ['gztar'] + + def make_distribution(self): + """ + Workaround for #516 + """ + with self._remove_os_link(): + orig.sdist.make_distribution(self) + + @staticmethod + @contextlib.contextmanager + def _remove_os_link(): + """ + In a context, remove and restore os.link if it exists + """ + + class NoValue: + pass + + orig_val = getattr(os, 'link', NoValue) + try: + del os.link + except Exception: + pass + try: + yield + finally: + if orig_val is not NoValue: + setattr(os, 'link', orig_val) + + def __read_template_hack(self): + # This grody hack closes the template file (MANIFEST.in) if an + # exception occurs during read_template. + # Doing so prevents an error when easy_install attempts to delete the + # file. + try: + orig.sdist.read_template(self) + except Exception: + _, _, tb = sys.exc_info() + tb.tb_next.tb_frame.f_locals['template'].close() + raise + + # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle + # has been fixed, so only override the method if we're using an earlier + # Python. + has_leaky_handle = ( + sys.version_info < (2, 7, 2) + or (3, 0) <= sys.version_info < (3, 1, 4) + or (3, 2) <= sys.version_info < (3, 2, 1) + ) + if has_leaky_handle: + read_template = __read_template_hack + + def _add_defaults_python(self): + """getting python files""" + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + self.filelist.extend(build_py.get_source_files()) + # This functionality is incompatible with include_package_data, and + # will in fact create an infinite recursion if include_package_data + # is True. Use of include_package_data will imply that + # distutils-style automatic handling of package_data is disabled + if not self.distribution.include_package_data: + for _, src_dir, _, filenames in build_py.data_files: + self.filelist.extend([os.path.join(src_dir, filename) + for filename in filenames]) + + def _add_defaults_data_files(self): + try: + if six.PY2: + sdist_add_defaults._add_defaults_data_files(self) + else: + super()._add_defaults_data_files() + except TypeError: + log.warn("data_files contains unexpected objects") + + def check_readme(self): + for f in self.READMES: + if os.path.exists(f): + return + else: + self.warn( + "standard file not found: should have one of " + + ', '.join(self.READMES) + ) + + def make_release_tree(self, base_dir, files): + orig.sdist.make_release_tree(self, base_dir, files) + + # Save any egg_info command line options used to create this sdist + dest = os.path.join(base_dir, 'setup.cfg') + if hasattr(os, 'link') and os.path.exists(dest): + # unlink and re-copy, since it might be hard-linked, and + # we don't want to change the source version + os.unlink(dest) + self.copy_file('setup.cfg', dest) + + self.get_finalized_command('egg_info').save_version_info(dest) + + def _manifest_is_not_generated(self): + # check for special comment used in 2.7.1 and higher + if not os.path.isfile(self.manifest): + return False + + with io.open(self.manifest, 'rb') as fp: + first_line = fp.readline() + return (first_line != + '# file GENERATED by distutils, do NOT edit\n'.encode()) + + def read_manifest(self): + """Read the manifest file (named by 'self.manifest') and use it to + fill in 'self.filelist', the list of files to include in the source + distribution. + """ + log.info("reading manifest file '%s'", self.manifest) + manifest = open(self.manifest, 'rb') + for line in manifest: + # The manifest must contain UTF-8. See #303. + if six.PY3: + try: + line = line.decode('UTF-8') + except UnicodeDecodeError: + log.warn("%r not UTF-8 decodable -- skipping" % line) + continue + # ignore comments and blank lines + line = line.strip() + if line.startswith('#') or not line: + continue + self.filelist.append(line) + manifest.close() diff --git a/winvenv/Lib/site-packages/setuptools/command/setopt.py b/winvenv/Lib/site-packages/setuptools/command/setopt.py new file mode 100644 index 0000000..7e57cc0 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/setopt.py @@ -0,0 +1,149 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsOptionError +import distutils +import os + +from setuptools.extern.six.moves import configparser + +from setuptools import Command + +__all__ = ['config_file', 'edit_config', 'option_base', 'setopt'] + + +def config_file(kind="local"): + """Get the filename of the distutils, local, global, or per-user config + + `kind` must be one of "local", "global", or "user" + """ + if kind == 'local': + return 'setup.cfg' + if kind == 'global': + return os.path.join( + os.path.dirname(distutils.__file__), 'distutils.cfg' + ) + if kind == 'user': + dot = os.name == 'posix' and '.' or '' + return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot)) + raise ValueError( + "config_file() type must be 'local', 'global', or 'user'", kind + ) + + +def edit_config(filename, settings, dry_run=False): + """Edit a configuration file to include `settings` + + `settings` is a dictionary of dictionaries or ``None`` values, keyed by + command/section name. A ``None`` value means to delete the entire section, + while a dictionary lists settings to be changed or deleted in that section. + A setting of ``None`` means to delete that setting. + """ + log.debug("Reading configuration from %s", filename) + opts = configparser.RawConfigParser() + opts.read([filename]) + for section, options in settings.items(): + if options is None: + log.info("Deleting section [%s] from %s", section, filename) + opts.remove_section(section) + else: + if not opts.has_section(section): + log.debug("Adding new section [%s] to %s", section, filename) + opts.add_section(section) + for option, value in options.items(): + if value is None: + log.debug( + "Deleting %s.%s from %s", + section, option, filename + ) + opts.remove_option(section, option) + if not opts.options(section): + log.info("Deleting empty [%s] section from %s", + section, filename) + opts.remove_section(section) + else: + log.debug( + "Setting %s.%s to %r in %s", + section, option, value, filename + ) + opts.set(section, option, value) + + log.info("Writing %s", filename) + if not dry_run: + with open(filename, 'w') as f: + opts.write(f) + + +class option_base(Command): + """Abstract base class for commands that mess with config files""" + + user_options = [ + ('global-config', 'g', + "save options to the site-wide distutils.cfg file"), + ('user-config', 'u', + "save options to the current user's pydistutils.cfg file"), + ('filename=', 'f', + "configuration file to use (default=setup.cfg)"), + ] + + boolean_options = [ + 'global-config', 'user-config', + ] + + def initialize_options(self): + self.global_config = None + self.user_config = None + self.filename = None + + def finalize_options(self): + filenames = [] + if self.global_config: + filenames.append(config_file('global')) + if self.user_config: + filenames.append(config_file('user')) + if self.filename is not None: + filenames.append(self.filename) + if not filenames: + filenames.append(config_file('local')) + if len(filenames) > 1: + raise DistutilsOptionError( + "Must specify only one configuration file option", + filenames + ) + self.filename, = filenames + + +class setopt(option_base): + """Save command-line options to a file""" + + description = "set an option in setup.cfg or another config file" + + user_options = [ + ('command=', 'c', 'command to set an option for'), + ('option=', 'o', 'option to set'), + ('set-value=', 's', 'value of the option'), + ('remove', 'r', 'remove (unset) the value'), + ] + option_base.user_options + + boolean_options = option_base.boolean_options + ['remove'] + + def initialize_options(self): + option_base.initialize_options(self) + self.command = None + self.option = None + self.set_value = None + self.remove = None + + def finalize_options(self): + option_base.finalize_options(self) + if self.command is None or self.option is None: + raise DistutilsOptionError("Must specify --command *and* --option") + if self.set_value is None and not self.remove: + raise DistutilsOptionError("Must specify --set-value or --remove") + + def run(self): + edit_config( + self.filename, { + self.command: {self.option.replace('-', '_'): self.set_value} + }, + self.dry_run + ) diff --git a/winvenv/Lib/site-packages/setuptools/command/test.py b/winvenv/Lib/site-packages/setuptools/command/test.py new file mode 100644 index 0000000..dde0118 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/test.py @@ -0,0 +1,270 @@ +import os +import operator +import sys +import contextlib +import itertools +import unittest +from distutils.errors import DistutilsError, DistutilsOptionError +from distutils import log +from unittest import TestLoader + +from setuptools.extern import six +from setuptools.extern.six.moves import map, filter + +from pkg_resources import (resource_listdir, resource_exists, normalize_path, + working_set, _namespace_packages, evaluate_marker, + add_activation_listener, require, EntryPoint) +from setuptools import Command + +__metaclass__ = type + + +class ScanningLoader(TestLoader): + + def __init__(self): + TestLoader.__init__(self) + self._visited = set() + + def loadTestsFromModule(self, module, pattern=None): + """Return a suite of all tests cases contained in the given module + + If the module is a package, load tests from all the modules in it. + If the module has an ``additional_tests`` function, call it and add + the return value to the tests. + """ + if module in self._visited: + return None + self._visited.add(module) + + tests = [] + tests.append(TestLoader.loadTestsFromModule(self, module)) + + if hasattr(module, "additional_tests"): + tests.append(module.additional_tests()) + + if hasattr(module, '__path__'): + for file in resource_listdir(module.__name__, ''): + if file.endswith('.py') and file != '__init__.py': + submodule = module.__name__ + '.' + file[:-3] + else: + if resource_exists(module.__name__, file + '/__init__.py'): + submodule = module.__name__ + '.' + file + else: + continue + tests.append(self.loadTestsFromName(submodule)) + + if len(tests) != 1: + return self.suiteClass(tests) + else: + return tests[0] # don't create a nested suite for only one return + + +# adapted from jaraco.classes.properties:NonDataProperty +class NonDataProperty: + def __init__(self, fget): + self.fget = fget + + def __get__(self, obj, objtype=None): + if obj is None: + return self + return self.fget(obj) + + +class test(Command): + """Command to run unit tests after in-place build""" + + description = "run unit tests after in-place build" + + user_options = [ + ('test-module=', 'm', "Run 'test_suite' in specified module"), + ('test-suite=', 's', + "Run single test, case or suite (e.g. 'module.test_suite')"), + ('test-runner=', 'r', "Test runner to use"), + ] + + def initialize_options(self): + self.test_suite = None + self.test_module = None + self.test_loader = None + self.test_runner = None + + def finalize_options(self): + + if self.test_suite and self.test_module: + msg = "You may specify a module or a suite, but not both" + raise DistutilsOptionError(msg) + + if self.test_suite is None: + if self.test_module is None: + self.test_suite = self.distribution.test_suite + else: + self.test_suite = self.test_module + ".test_suite" + + if self.test_loader is None: + self.test_loader = getattr(self.distribution, 'test_loader', None) + if self.test_loader is None: + self.test_loader = "setuptools.command.test:ScanningLoader" + if self.test_runner is None: + self.test_runner = getattr(self.distribution, 'test_runner', None) + + @NonDataProperty + def test_args(self): + return list(self._test_args()) + + def _test_args(self): + if not self.test_suite and sys.version_info >= (2, 7): + yield 'discover' + if self.verbose: + yield '--verbose' + if self.test_suite: + yield self.test_suite + + def with_project_on_sys_path(self, func): + """ + Backward compatibility for project_on_sys_path context. + """ + with self.project_on_sys_path(): + func() + + @contextlib.contextmanager + def project_on_sys_path(self, include_dists=[]): + with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False) + + if with_2to3: + # If we run 2to3 we can not do this inplace: + + # Ensure metadata is up-to-date + self.reinitialize_command('build_py', inplace=0) + self.run_command('build_py') + bpy_cmd = self.get_finalized_command("build_py") + build_path = normalize_path(bpy_cmd.build_lib) + + # Build extensions + self.reinitialize_command('egg_info', egg_base=build_path) + self.run_command('egg_info') + + self.reinitialize_command('build_ext', inplace=0) + self.run_command('build_ext') + else: + # Without 2to3 inplace works fine: + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + + ei_cmd = self.get_finalized_command("egg_info") + + old_path = sys.path[:] + old_modules = sys.modules.copy() + + try: + project_path = normalize_path(ei_cmd.egg_base) + sys.path.insert(0, project_path) + working_set.__init__() + add_activation_listener(lambda dist: dist.activate()) + require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version)) + with self.paths_on_pythonpath([project_path]): + yield + finally: + sys.path[:] = old_path + sys.modules.clear() + sys.modules.update(old_modules) + working_set.__init__() + + @staticmethod + @contextlib.contextmanager + def paths_on_pythonpath(paths): + """ + Add the indicated paths to the head of the PYTHONPATH environment + variable so that subprocesses will also see the packages at + these paths. + + Do this in a context that restores the value on exit. + """ + nothing = object() + orig_pythonpath = os.environ.get('PYTHONPATH', nothing) + current_pythonpath = os.environ.get('PYTHONPATH', '') + try: + prefix = os.pathsep.join(paths) + to_join = filter(None, [prefix, current_pythonpath]) + new_path = os.pathsep.join(to_join) + if new_path: + os.environ['PYTHONPATH'] = new_path + yield + finally: + if orig_pythonpath is nothing: + os.environ.pop('PYTHONPATH', None) + else: + os.environ['PYTHONPATH'] = orig_pythonpath + + @staticmethod + def install_dists(dist): + """ + Install the requirements indicated by self.distribution and + return an iterable of the dists that were built. + """ + ir_d = dist.fetch_build_eggs(dist.install_requires) + tr_d = dist.fetch_build_eggs(dist.tests_require or []) + er_d = dist.fetch_build_eggs( + v for k, v in dist.extras_require.items() + if k.startswith(':') and evaluate_marker(k[1:]) + ) + return itertools.chain(ir_d, tr_d, er_d) + + def run(self): + installed_dists = self.install_dists(self.distribution) + + cmd = ' '.join(self._argv) + if self.dry_run: + self.announce('skipping "%s" (dry run)' % cmd) + return + + self.announce('running "%s"' % cmd) + + paths = map(operator.attrgetter('location'), installed_dists) + with self.paths_on_pythonpath(paths): + with self.project_on_sys_path(): + self.run_tests() + + def run_tests(self): + # Purge modules under test from sys.modules. The test loader will + # re-import them from the build location. Required when 2to3 is used + # with namespace packages. + if six.PY3 and getattr(self.distribution, 'use_2to3', False): + module = self.test_suite.split('.')[0] + if module in _namespace_packages: + del_modules = [] + if module in sys.modules: + del_modules.append(module) + module += '.' + for name in sys.modules: + if name.startswith(module): + del_modules.append(name) + list(map(sys.modules.__delitem__, del_modules)) + + test = unittest.main( + None, None, self._argv, + testLoader=self._resolve_as_ep(self.test_loader), + testRunner=self._resolve_as_ep(self.test_runner), + exit=False, + ) + if not test.result.wasSuccessful(): + msg = 'Test failed: %s' % test.result + self.announce(msg, log.ERROR) + raise DistutilsError(msg) + + @property + def _argv(self): + return ['unittest'] + self.test_args + + @staticmethod + def _resolve_as_ep(val): + """ + Load the indicated attribute value, called, as a as if it were + specified as an entry point. + """ + if val is None: + return + parsed = EntryPoint.parse("x=" + val) + return parsed.resolve()() diff --git a/winvenv/Lib/site-packages/setuptools/command/upload.py b/winvenv/Lib/site-packages/setuptools/command/upload.py new file mode 100644 index 0000000..dd17f7a --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/upload.py @@ -0,0 +1,196 @@ +import io +import os +import hashlib +import getpass +import platform + +from base64 import standard_b64encode + +from distutils import log +from distutils.command import upload as orig +from distutils.spawn import spawn + +from distutils.errors import DistutilsError + +from setuptools.extern.six.moves.urllib.request import urlopen, Request +from setuptools.extern.six.moves.urllib.error import HTTPError +from setuptools.extern.six.moves.urllib.parse import urlparse + +class upload(orig.upload): + """ + Override default upload behavior to obtain password + in a variety of different ways. + """ + def run(self): + try: + orig.upload.run(self) + finally: + self.announce( + "WARNING: Uploading via this command is deprecated, use twine " + "to upload instead (https://pypi.org/p/twine/)", + log.WARN + ) + + def finalize_options(self): + orig.upload.finalize_options(self) + self.username = ( + self.username or + getpass.getuser() + ) + # Attempt to obtain password. Short circuit evaluation at the first + # sign of success. + self.password = ( + self.password or + self._load_password_from_keyring() or + self._prompt_for_password() + ) + + def upload_file(self, command, pyversion, filename): + # Makes sure the repository URL is compliant + schema, netloc, url, params, query, fragments = \ + urlparse(self.repository) + if params or query or fragments: + raise AssertionError("Incompatible url %s" % self.repository) + + if schema not in ('http', 'https'): + raise AssertionError("unsupported schema " + schema) + + # Sign if requested + if self.sign: + gpg_args = ["gpg", "--detach-sign", "-a", filename] + if self.identity: + gpg_args[2:2] = ["--local-user", self.identity] + spawn(gpg_args, + dry_run=self.dry_run) + + # Fill in the data - send all the meta-data in case we need to + # register a new release + with open(filename, 'rb') as f: + content = f.read() + + meta = self.distribution.metadata + + data = { + # action + ':action': 'file_upload', + 'protocol_version': '1', + + # identify release + 'name': meta.get_name(), + 'version': meta.get_version(), + + # file content + 'content': (os.path.basename(filename),content), + 'filetype': command, + 'pyversion': pyversion, + 'md5_digest': hashlib.md5(content).hexdigest(), + + # additional meta-data + 'metadata_version': str(meta.get_metadata_version()), + 'summary': meta.get_description(), + 'home_page': meta.get_url(), + 'author': meta.get_contact(), + 'author_email': meta.get_contact_email(), + 'license': meta.get_licence(), + 'description': meta.get_long_description(), + 'keywords': meta.get_keywords(), + 'platform': meta.get_platforms(), + 'classifiers': meta.get_classifiers(), + 'download_url': meta.get_download_url(), + # PEP 314 + 'provides': meta.get_provides(), + 'requires': meta.get_requires(), + 'obsoletes': meta.get_obsoletes(), + } + + data['comment'] = '' + + if self.sign: + data['gpg_signature'] = (os.path.basename(filename) + ".asc", + open(filename+".asc", "rb").read()) + + # set up the authentication + user_pass = (self.username + ":" + self.password).encode('ascii') + # The exact encoding of the authentication string is debated. + # Anyway PyPI only accepts ascii for both username or password. + auth = "Basic " + standard_b64encode(user_pass).decode('ascii') + + # Build up the MIME payload for the POST data + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = b'\r\n--' + boundary.encode('ascii') + end_boundary = sep_boundary + b'--\r\n' + body = io.BytesIO() + for key, value in data.items(): + title = '\r\nContent-Disposition: form-data; name="%s"' % key + # handle multiple entries for the same name + if not isinstance(value, list): + value = [value] + for value in value: + if type(value) is tuple: + title += '; filename="%s"' % value[0] + value = value[1] + else: + value = str(value).encode('utf-8') + body.write(sep_boundary) + body.write(title.encode('utf-8')) + body.write(b"\r\n\r\n") + body.write(value) + body.write(end_boundary) + body = body.getvalue() + + msg = "Submitting %s to %s" % (filename, self.repository) + self.announce(msg, log.INFO) + + # build the Request + headers = { + 'Content-type': 'multipart/form-data; boundary=%s' % boundary, + 'Content-length': str(len(body)), + 'Authorization': auth, + } + + request = Request(self.repository, data=body, + headers=headers) + # send the data + try: + result = urlopen(request) + status = result.getcode() + reason = result.msg + except HTTPError as e: + status = e.code + reason = e.msg + except OSError as e: + self.announce(str(e), log.ERROR) + raise + + if status == 200: + self.announce('Server response (%s): %s' % (status, reason), + log.INFO) + if self.show_response: + text = getattr(self, '_read_pypi_response', + lambda x: None)(result) + if text is not None: + msg = '\n'.join(('-' * 75, text, '-' * 75)) + self.announce(msg, log.INFO) + else: + msg = 'Upload failed (%s): %s' % (status, reason) + self.announce(msg, log.ERROR) + raise DistutilsError(msg) + + def _load_password_from_keyring(self): + """ + Attempt to load password from keyring. Suppress Exceptions. + """ + try: + keyring = __import__('keyring') + return keyring.get_password(self.repository, self.username) + except Exception: + pass + + def _prompt_for_password(self): + """ + Prompt for a password on the tty. Suppress Exceptions. + """ + try: + return getpass.getpass() + except (Exception, KeyboardInterrupt): + pass diff --git a/winvenv/Lib/site-packages/setuptools/command/upload_docs.py b/winvenv/Lib/site-packages/setuptools/command/upload_docs.py new file mode 100644 index 0000000..07aa564 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/command/upload_docs.py @@ -0,0 +1,206 @@ +# -*- coding: utf-8 -*- +"""upload_docs + +Implements a Distutils 'upload_docs' subcommand (upload documentation to +PyPI's pythonhosted.org). +""" + +from base64 import standard_b64encode +from distutils import log +from distutils.errors import DistutilsOptionError +import os +import socket +import zipfile +import tempfile +import shutil +import itertools +import functools + +from setuptools.extern import six +from setuptools.extern.six.moves import http_client, urllib + +from pkg_resources import iter_entry_points +from .upload import upload + + +def _encode(s): + errors = 'surrogateescape' if six.PY3 else 'strict' + return s.encode('utf-8', errors) + + +class upload_docs(upload): + # override the default repository as upload_docs isn't + # supported by Warehouse (and won't be). + DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi/' + + description = 'Upload documentation to PyPI' + + user_options = [ + ('repository=', 'r', + "url of repository [default: %s]" % upload.DEFAULT_REPOSITORY), + ('show-response', None, + 'display full response text from server'), + ('upload-dir=', None, 'directory to upload'), + ] + boolean_options = upload.boolean_options + + def has_sphinx(self): + if self.upload_dir is None: + for ep in iter_entry_points('distutils.commands', 'build_sphinx'): + return True + + sub_commands = [('build_sphinx', has_sphinx)] + + def initialize_options(self): + upload.initialize_options(self) + self.upload_dir = None + self.target_dir = None + + def finalize_options(self): + upload.finalize_options(self) + if self.upload_dir is None: + if self.has_sphinx(): + build_sphinx = self.get_finalized_command('build_sphinx') + self.target_dir = build_sphinx.builder_target_dir + else: + build = self.get_finalized_command('build') + self.target_dir = os.path.join(build.build_base, 'docs') + else: + self.ensure_dirname('upload_dir') + self.target_dir = self.upload_dir + if 'pypi.python.org' in self.repository: + log.warn("Upload_docs command is deprecated. Use RTD instead.") + self.announce('Using upload directory %s' % self.target_dir) + + def create_zipfile(self, filename): + zip_file = zipfile.ZipFile(filename, "w") + try: + self.mkpath(self.target_dir) # just in case + for root, dirs, files in os.walk(self.target_dir): + if root == self.target_dir and not files: + tmpl = "no files found in upload directory '%s'" + raise DistutilsOptionError(tmpl % self.target_dir) + for name in files: + full = os.path.join(root, name) + relative = root[len(self.target_dir):].lstrip(os.path.sep) + dest = os.path.join(relative, name) + zip_file.write(full, dest) + finally: + zip_file.close() + + def run(self): + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + tmp_dir = tempfile.mkdtemp() + name = self.distribution.metadata.get_name() + zip_file = os.path.join(tmp_dir, "%s.zip" % name) + try: + self.create_zipfile(zip_file) + self.upload_file(zip_file) + finally: + shutil.rmtree(tmp_dir) + + @staticmethod + def _build_part(item, sep_boundary): + key, values = item + title = '\nContent-Disposition: form-data; name="%s"' % key + # handle multiple entries for the same name + if not isinstance(values, list): + values = [values] + for value in values: + if isinstance(value, tuple): + title += '; filename="%s"' % value[0] + value = value[1] + else: + value = _encode(value) + yield sep_boundary + yield _encode(title) + yield b"\n\n" + yield value + if value and value[-1:] == b'\r': + yield b'\n' # write an extra newline (lurve Macs) + + @classmethod + def _build_multipart(cls, data): + """ + Build up the MIME payload for the POST data + """ + boundary = b'--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = b'\n--' + boundary + end_boundary = sep_boundary + b'--' + end_items = end_boundary, b"\n", + builder = functools.partial( + cls._build_part, + sep_boundary=sep_boundary, + ) + part_groups = map(builder, data.items()) + parts = itertools.chain.from_iterable(part_groups) + body_items = itertools.chain(parts, end_items) + content_type = 'multipart/form-data; boundary=%s' % boundary.decode('ascii') + return b''.join(body_items), content_type + + def upload_file(self, filename): + with open(filename, 'rb') as f: + content = f.read() + meta = self.distribution.metadata + data = { + ':action': 'doc_upload', + 'name': meta.get_name(), + 'content': (os.path.basename(filename), content), + } + # set up the authentication + credentials = _encode(self.username + ':' + self.password) + credentials = standard_b64encode(credentials) + if six.PY3: + credentials = credentials.decode('ascii') + auth = "Basic " + credentials + + body, ct = self._build_multipart(data) + + msg = "Submitting documentation to %s" % (self.repository) + self.announce(msg, log.INFO) + + # build the Request + # We can't use urllib2 since we need to send the Basic + # auth right with the first request + schema, netloc, url, params, query, fragments = \ + urllib.parse.urlparse(self.repository) + assert not params and not query and not fragments + if schema == 'http': + conn = http_client.HTTPConnection(netloc) + elif schema == 'https': + conn = http_client.HTTPSConnection(netloc) + else: + raise AssertionError("unsupported schema " + schema) + + data = '' + try: + conn.connect() + conn.putrequest("POST", url) + content_type = ct + conn.putheader('Content-type', content_type) + conn.putheader('Content-length', str(len(body))) + conn.putheader('Authorization', auth) + conn.endheaders() + conn.send(body) + except socket.error as e: + self.announce(str(e), log.ERROR) + return + + r = conn.getresponse() + if r.status == 200: + msg = 'Server response (%s): %s' % (r.status, r.reason) + self.announce(msg, log.INFO) + elif r.status == 301: + location = r.getheader('Location') + if location is None: + location = 'https://pythonhosted.org/%s/' % meta.get_name() + msg = 'Upload successful. Visit %s' % location + self.announce(msg, log.INFO) + else: + msg = 'Upload failed (%s): %s' % (r.status, r.reason) + self.announce(msg, log.ERROR) + if self.show_response: + print('-' * 75, r.read(), '-' * 75) diff --git a/winvenv/Lib/site-packages/setuptools/config.py b/winvenv/Lib/site-packages/setuptools/config.py new file mode 100644 index 0000000..d1ac673 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/config.py @@ -0,0 +1,635 @@ +from __future__ import absolute_import, unicode_literals +import io +import os +import sys + +import warnings +import functools +from collections import defaultdict +from functools import partial +from functools import wraps +from importlib import import_module + +from distutils.errors import DistutilsOptionError, DistutilsFileError +from setuptools.extern.packaging.version import LegacyVersion, parse +from setuptools.extern.six import string_types, PY3 + + +__metaclass__ = type + + +def read_configuration( + filepath, find_others=False, ignore_option_errors=False): + """Read given configuration file and returns options from it as a dict. + + :param str|unicode filepath: Path to configuration file + to get options from. + + :param bool find_others: Whether to search for other configuration files + which could be on in various places. + + :param bool ignore_option_errors: Whether to silently ignore + options, values of which could not be resolved (e.g. due to exceptions + in directives such as file:, attr:, etc.). + If False exceptions are propagated as expected. + + :rtype: dict + """ + from setuptools.dist import Distribution, _Distribution + + filepath = os.path.abspath(filepath) + + if not os.path.isfile(filepath): + raise DistutilsFileError( + 'Configuration file %s does not exist.' % filepath) + + current_directory = os.getcwd() + os.chdir(os.path.dirname(filepath)) + + try: + dist = Distribution() + + filenames = dist.find_config_files() if find_others else [] + if filepath not in filenames: + filenames.append(filepath) + + _Distribution.parse_config_files(dist, filenames=filenames) + + handlers = parse_configuration( + dist, dist.command_options, + ignore_option_errors=ignore_option_errors) + + finally: + os.chdir(current_directory) + + return configuration_to_dict(handlers) + + +def _get_option(target_obj, key): + """ + Given a target object and option key, get that option from + the target object, either through a get_{key} method or + from an attribute directly. + """ + getter_name = 'get_{key}'.format(**locals()) + by_attribute = functools.partial(getattr, target_obj, key) + getter = getattr(target_obj, getter_name, by_attribute) + return getter() + + +def configuration_to_dict(handlers): + """Returns configuration data gathered by given handlers as a dict. + + :param list[ConfigHandler] handlers: Handlers list, + usually from parse_configuration() + + :rtype: dict + """ + config_dict = defaultdict(dict) + + for handler in handlers: + for option in handler.set_options: + value = _get_option(handler.target_obj, option) + config_dict[handler.section_prefix][option] = value + + return config_dict + + +def parse_configuration( + distribution, command_options, ignore_option_errors=False): + """Performs additional parsing of configuration options + for a distribution. + + Returns a list of used option handlers. + + :param Distribution distribution: + :param dict command_options: + :param bool ignore_option_errors: Whether to silently ignore + options, values of which could not be resolved (e.g. due to exceptions + in directives such as file:, attr:, etc.). + If False exceptions are propagated as expected. + :rtype: list + """ + options = ConfigOptionsHandler( + distribution, command_options, ignore_option_errors) + options.parse() + + meta = ConfigMetadataHandler( + distribution.metadata, command_options, ignore_option_errors, + distribution.package_dir) + meta.parse() + + return meta, options + + +class ConfigHandler: + """Handles metadata supplied in configuration files.""" + + section_prefix = None + """Prefix for config sections handled by this handler. + Must be provided by class heirs. + + """ + + aliases = {} + """Options aliases. + For compatibility with various packages. E.g.: d2to1 and pbr. + Note: `-` in keys is replaced with `_` by config parser. + + """ + + def __init__(self, target_obj, options, ignore_option_errors=False): + sections = {} + + section_prefix = self.section_prefix + for section_name, section_options in options.items(): + if not section_name.startswith(section_prefix): + continue + + section_name = section_name.replace(section_prefix, '').strip('.') + sections[section_name] = section_options + + self.ignore_option_errors = ignore_option_errors + self.target_obj = target_obj + self.sections = sections + self.set_options = [] + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + raise NotImplementedError( + '%s must provide .parsers property' % self.__class__.__name__) + + def __setitem__(self, option_name, value): + unknown = tuple() + target_obj = self.target_obj + + # Translate alias into real name. + option_name = self.aliases.get(option_name, option_name) + + current_value = getattr(target_obj, option_name, unknown) + + if current_value is unknown: + raise KeyError(option_name) + + if current_value: + # Already inhabited. Skipping. + return + + skip_option = False + parser = self.parsers.get(option_name) + if parser: + try: + value = parser(value) + + except Exception: + skip_option = True + if not self.ignore_option_errors: + raise + + if skip_option: + return + + setter = getattr(target_obj, 'set_%s' % option_name, None) + if setter is None: + setattr(target_obj, option_name, value) + else: + setter(value) + + self.set_options.append(option_name) + + @classmethod + def _parse_list(cls, value, separator=','): + """Represents value as a list. + + Value is split either by separator (defaults to comma) or by lines. + + :param value: + :param separator: List items separator character. + :rtype: list + """ + if isinstance(value, list): # _get_parser_compound case + return value + + if '\n' in value: + value = value.splitlines() + else: + value = value.split(separator) + + return [chunk.strip() for chunk in value if chunk.strip()] + + @classmethod + def _parse_dict(cls, value): + """Represents value as a dict. + + :param value: + :rtype: dict + """ + separator = '=' + result = {} + for line in cls._parse_list(value): + key, sep, val = line.partition(separator) + if sep != separator: + raise DistutilsOptionError( + 'Unable to parse option value to dict: %s' % value) + result[key.strip()] = val.strip() + + return result + + @classmethod + def _parse_bool(cls, value): + """Represents value as boolean. + + :param value: + :rtype: bool + """ + value = value.lower() + return value in ('1', 'true', 'yes') + + @classmethod + def _parse_file(cls, value): + """Represents value as a string, allowing including text + from nearest files using `file:` directive. + + Directive is sandboxed and won't reach anything outside + directory with setup.py. + + Examples: + file: LICENSE + file: README.rst, CHANGELOG.md, src/file.txt + + :param str value: + :rtype: str + """ + include_directive = 'file:' + + if not isinstance(value, string_types): + return value + + if not value.startswith(include_directive): + return value + + spec = value[len(include_directive):] + filepaths = (os.path.abspath(path.strip()) for path in spec.split(',')) + return '\n'.join( + cls._read_file(path) + for path in filepaths + if (cls._assert_local(path) or True) + and os.path.isfile(path) + ) + + @staticmethod + def _assert_local(filepath): + if not filepath.startswith(os.getcwd()): + raise DistutilsOptionError( + '`file:` directive can not access %s' % filepath) + + @staticmethod + def _read_file(filepath): + with io.open(filepath, encoding='utf-8') as f: + return f.read() + + @classmethod + def _parse_attr(cls, value, package_dir=None): + """Represents value as a module attribute. + + Examples: + attr: package.attr + attr: package.module.attr + + :param str value: + :rtype: str + """ + attr_directive = 'attr:' + if not value.startswith(attr_directive): + return value + + attrs_path = value.replace(attr_directive, '').strip().split('.') + attr_name = attrs_path.pop() + + module_name = '.'.join(attrs_path) + module_name = module_name or '__init__' + + parent_path = os.getcwd() + if package_dir: + if attrs_path[0] in package_dir: + # A custom path was specified for the module we want to import + custom_path = package_dir[attrs_path[0]] + parts = custom_path.rsplit('/', 1) + if len(parts) > 1: + parent_path = os.path.join(os.getcwd(), parts[0]) + module_name = parts[1] + else: + module_name = custom_path + elif '' in package_dir: + # A custom parent directory was specified for all root modules + parent_path = os.path.join(os.getcwd(), package_dir['']) + sys.path.insert(0, parent_path) + try: + module = import_module(module_name) + value = getattr(module, attr_name) + + finally: + sys.path = sys.path[1:] + + return value + + @classmethod + def _get_parser_compound(cls, *parse_methods): + """Returns parser function to represents value as a list. + + Parses a value applying given methods one after another. + + :param parse_methods: + :rtype: callable + """ + def parse(value): + parsed = value + + for method in parse_methods: + parsed = method(parsed) + + return parsed + + return parse + + @classmethod + def _parse_section_to_dict(cls, section_options, values_parser=None): + """Parses section options into a dictionary. + + Optionally applies a given parser to values. + + :param dict section_options: + :param callable values_parser: + :rtype: dict + """ + value = {} + values_parser = values_parser or (lambda val: val) + for key, (_, val) in section_options.items(): + value[key] = values_parser(val) + return value + + def parse_section(self, section_options): + """Parses configuration file section. + + :param dict section_options: + """ + for (name, (_, value)) in section_options.items(): + try: + self[name] = value + + except KeyError: + pass # Keep silent for a new option may appear anytime. + + def parse(self): + """Parses configuration file items from one + or more related sections. + + """ + for section_name, section_options in self.sections.items(): + + method_postfix = '' + if section_name: # [section.option] variant + method_postfix = '_%s' % section_name + + section_parser_method = getattr( + self, + # Dots in section names are tranlsated into dunderscores. + ('parse_section%s' % method_postfix).replace('.', '__'), + None) + + if section_parser_method is None: + raise DistutilsOptionError( + 'Unsupported distribution option section: [%s.%s]' % ( + self.section_prefix, section_name)) + + section_parser_method(section_options) + + def _deprecated_config_handler(self, func, msg, warning_class): + """ this function will wrap around parameters that are deprecated + + :param msg: deprecation message + :param warning_class: class of warning exception to be raised + :param func: function to be wrapped around + """ + @wraps(func) + def config_handler(*args, **kwargs): + warnings.warn(msg, warning_class) + return func(*args, **kwargs) + + return config_handler + + +class ConfigMetadataHandler(ConfigHandler): + + section_prefix = 'metadata' + + aliases = { + 'home_page': 'url', + 'summary': 'description', + 'classifier': 'classifiers', + 'platform': 'platforms', + } + + strict_mode = False + """We need to keep it loose, to be partially compatible with + `pbr` and `d2to1` packages which also uses `metadata` section. + + """ + + def __init__(self, target_obj, options, ignore_option_errors=False, + package_dir=None): + super(ConfigMetadataHandler, self).__init__(target_obj, options, + ignore_option_errors) + self.package_dir = package_dir + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + parse_list = self._parse_list + parse_file = self._parse_file + parse_dict = self._parse_dict + + return { + 'platforms': parse_list, + 'keywords': parse_list, + 'provides': parse_list, + 'requires': self._deprecated_config_handler(parse_list, + "The requires parameter is deprecated, please use " + + "install_requires for runtime dependencies.", + DeprecationWarning), + 'obsoletes': parse_list, + 'classifiers': self._get_parser_compound(parse_file, parse_list), + 'license': parse_file, + 'description': parse_file, + 'long_description': parse_file, + 'version': self._parse_version, + 'project_urls': parse_dict, + } + + def _parse_version(self, value): + """Parses `version` option value. + + :param value: + :rtype: str + + """ + version = self._parse_file(value) + + if version != value: + version = version.strip() + # Be strict about versions loaded from file because it's easy to + # accidentally include newlines and other unintended content + if isinstance(parse(version), LegacyVersion): + tmpl = ( + 'Version loaded from {value} does not ' + 'comply with PEP 440: {version}' + ) + raise DistutilsOptionError(tmpl.format(**locals())) + + return version + + version = self._parse_attr(value, self.package_dir) + + if callable(version): + version = version() + + if not isinstance(version, string_types): + if hasattr(version, '__iter__'): + version = '.'.join(map(str, version)) + else: + version = '%s' % version + + return version + + +class ConfigOptionsHandler(ConfigHandler): + + section_prefix = 'options' + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + parse_list = self._parse_list + parse_list_semicolon = partial(self._parse_list, separator=';') + parse_bool = self._parse_bool + parse_dict = self._parse_dict + + return { + 'zip_safe': parse_bool, + 'use_2to3': parse_bool, + 'include_package_data': parse_bool, + 'package_dir': parse_dict, + 'use_2to3_fixers': parse_list, + 'use_2to3_exclude_fixers': parse_list, + 'convert_2to3_doctests': parse_list, + 'scripts': parse_list, + 'eager_resources': parse_list, + 'dependency_links': parse_list, + 'namespace_packages': parse_list, + 'install_requires': parse_list_semicolon, + 'setup_requires': parse_list_semicolon, + 'tests_require': parse_list_semicolon, + 'packages': self._parse_packages, + 'entry_points': self._parse_file, + 'py_modules': parse_list, + } + + def _parse_packages(self, value): + """Parses `packages` option value. + + :param value: + :rtype: list + """ + find_directives = ['find:', 'find_namespace:'] + trimmed_value = value.strip() + + if trimmed_value not in find_directives: + return self._parse_list(value) + + findns = trimmed_value == find_directives[1] + if findns and not PY3: + raise DistutilsOptionError( + 'find_namespace: directive is unsupported on Python < 3.3') + + # Read function arguments from a dedicated section. + find_kwargs = self.parse_section_packages__find( + self.sections.get('packages.find', {})) + + if findns: + from setuptools import find_namespace_packages as find_packages + else: + from setuptools import find_packages + + return find_packages(**find_kwargs) + + def parse_section_packages__find(self, section_options): + """Parses `packages.find` configuration file section. + + To be used in conjunction with _parse_packages(). + + :param dict section_options: + """ + section_data = self._parse_section_to_dict( + section_options, self._parse_list) + + valid_keys = ['where', 'include', 'exclude'] + + find_kwargs = dict( + [(k, v) for k, v in section_data.items() if k in valid_keys and v]) + + where = find_kwargs.get('where') + if where is not None: + find_kwargs['where'] = where[0] # cast list to single val + + return find_kwargs + + def parse_section_entry_points(self, section_options): + """Parses `entry_points` configuration file section. + + :param dict section_options: + """ + parsed = self._parse_section_to_dict(section_options, self._parse_list) + self['entry_points'] = parsed + + def _parse_package_data(self, section_options): + parsed = self._parse_section_to_dict(section_options, self._parse_list) + + root = parsed.get('*') + if root: + parsed[''] = root + del parsed['*'] + + return parsed + + def parse_section_package_data(self, section_options): + """Parses `package_data` configuration file section. + + :param dict section_options: + """ + self['package_data'] = self._parse_package_data(section_options) + + def parse_section_exclude_package_data(self, section_options): + """Parses `exclude_package_data` configuration file section. + + :param dict section_options: + """ + self['exclude_package_data'] = self._parse_package_data( + section_options) + + def parse_section_extras_require(self, section_options): + """Parses `extras_require` configuration file section. + + :param dict section_options: + """ + parse_list = partial(self._parse_list, separator=';') + self['extras_require'] = self._parse_section_to_dict( + section_options, parse_list) + + def parse_section_data_files(self, section_options): + """Parses `data_files` configuration file section. + + :param dict section_options: + """ + parsed = self._parse_section_to_dict(section_options, self._parse_list) + self['data_files'] = [(k, v) for k, v in parsed.items()] diff --git a/winvenv/Lib/site-packages/setuptools/dep_util.py b/winvenv/Lib/site-packages/setuptools/dep_util.py new file mode 100644 index 0000000..2931c13 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/dep_util.py @@ -0,0 +1,23 @@ +from distutils.dep_util import newer_group + +# yes, this is was almost entirely copy-pasted from +# 'newer_pairwise()', this is just another convenience +# function. +def newer_pairwise_group(sources_groups, targets): + """Walk both arguments in parallel, testing if each source group is newer + than its corresponding target. Returns a pair of lists (sources_groups, + targets) where sources is newer than target, according to the semantics + of 'newer_group()'. + """ + if len(sources_groups) != len(targets): + raise ValueError("'sources_group' and 'targets' must be the same length") + + # build a pair of lists (sources_groups, targets) where source is newer + n_sources = [] + n_targets = [] + for i in range(len(sources_groups)): + if newer_group(sources_groups[i], targets[i]): + n_sources.append(sources_groups[i]) + n_targets.append(targets[i]) + + return n_sources, n_targets diff --git a/winvenv/Lib/site-packages/setuptools/depends.py b/winvenv/Lib/site-packages/setuptools/depends.py new file mode 100644 index 0000000..45e7052 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/depends.py @@ -0,0 +1,186 @@ +import sys +import imp +import marshal +from distutils.version import StrictVersion +from imp import PKG_DIRECTORY, PY_COMPILED, PY_SOURCE, PY_FROZEN + +from .py33compat import Bytecode + + +__all__ = [ + 'Require', 'find_module', 'get_module_constant', 'extract_constant' +] + + +class Require: + """A prerequisite to building or installing a distribution""" + + def __init__(self, name, requested_version, module, homepage='', + attribute=None, format=None): + + if format is None and requested_version is not None: + format = StrictVersion + + if format is not None: + requested_version = format(requested_version) + if attribute is None: + attribute = '__version__' + + self.__dict__.update(locals()) + del self.self + + def full_name(self): + """Return full package/distribution name, w/version""" + if self.requested_version is not None: + return '%s-%s' % (self.name, self.requested_version) + return self.name + + def version_ok(self, version): + """Is 'version' sufficiently up-to-date?""" + return self.attribute is None or self.format is None or \ + str(version) != "unknown" and version >= self.requested_version + + def get_version(self, paths=None, default="unknown"): + """Get version number of installed module, 'None', or 'default' + + Search 'paths' for module. If not found, return 'None'. If found, + return the extracted version attribute, or 'default' if no version + attribute was specified, or the value cannot be determined without + importing the module. The version is formatted according to the + requirement's version format (if any), unless it is 'None' or the + supplied 'default'. + """ + + if self.attribute is None: + try: + f, p, i = find_module(self.module, paths) + if f: + f.close() + return default + except ImportError: + return None + + v = get_module_constant(self.module, self.attribute, default, paths) + + if v is not None and v is not default and self.format is not None: + return self.format(v) + + return v + + def is_present(self, paths=None): + """Return true if dependency is present on 'paths'""" + return self.get_version(paths) is not None + + def is_current(self, paths=None): + """Return true if dependency is present and up-to-date on 'paths'""" + version = self.get_version(paths) + if version is None: + return False + return self.version_ok(version) + + +def find_module(module, paths=None): + """Just like 'imp.find_module()', but with package support""" + + parts = module.split('.') + + while parts: + part = parts.pop(0) + f, path, (suffix, mode, kind) = info = imp.find_module(part, paths) + + if kind == PKG_DIRECTORY: + parts = parts or ['__init__'] + paths = [path] + + elif parts: + raise ImportError("Can't find %r in %s" % (parts, module)) + + return info + + +def get_module_constant(module, symbol, default=-1, paths=None): + """Find 'module' by searching 'paths', and extract 'symbol' + + Return 'None' if 'module' does not exist on 'paths', or it does not define + 'symbol'. If the module defines 'symbol' as a constant, return the + constant. Otherwise, return 'default'.""" + + try: + f, path, (suffix, mode, kind) = find_module(module, paths) + except ImportError: + # Module doesn't exist + return None + + try: + if kind == PY_COMPILED: + f.read(8) # skip magic & date + code = marshal.load(f) + elif kind == PY_FROZEN: + code = imp.get_frozen_object(module) + elif kind == PY_SOURCE: + code = compile(f.read(), path, 'exec') + else: + # Not something we can parse; we'll have to import it. :( + if module not in sys.modules: + imp.load_module(module, f, path, (suffix, mode, kind)) + return getattr(sys.modules[module], symbol, None) + + finally: + if f: + f.close() + + return extract_constant(code, symbol, default) + + +def extract_constant(code, symbol, default=-1): + """Extract the constant value of 'symbol' from 'code' + + If the name 'symbol' is bound to a constant value by the Python code + object 'code', return that value. If 'symbol' is bound to an expression, + return 'default'. Otherwise, return 'None'. + + Return value is based on the first assignment to 'symbol'. 'symbol' must + be a global, or at least a non-"fast" local in the code block. That is, + only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' + must be present in 'code.co_names'. + """ + if symbol not in code.co_names: + # name's not there, can't possibly be an assignment + return None + + name_idx = list(code.co_names).index(symbol) + + STORE_NAME = 90 + STORE_GLOBAL = 97 + LOAD_CONST = 100 + + const = default + + for byte_code in Bytecode(code): + op = byte_code.opcode + arg = byte_code.arg + + if op == LOAD_CONST: + const = code.co_consts[arg] + elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): + return const + else: + const = default + + +def _update_globals(): + """ + Patch the globals to remove the objects not available on some platforms. + + XXX it'd be better to test assertions about bytecode instead. + """ + + if not sys.platform.startswith('java') and sys.platform != 'cli': + return + incompatible = 'extract_constant', 'get_module_constant' + for name in incompatible: + del globals()[name] + __all__.remove(name) + + +_update_globals() diff --git a/winvenv/Lib/site-packages/setuptools/dist.py b/winvenv/Lib/site-packages/setuptools/dist.py new file mode 100644 index 0000000..7062ae8 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/dist.py @@ -0,0 +1,1147 @@ +# -*- coding: utf-8 -*- +__all__ = ['Distribution'] + +import re +import os +import warnings +import numbers +import distutils.log +import distutils.core +import distutils.cmd +import distutils.dist +import itertools + + +from collections import defaultdict +from email import message_from_file + +from distutils.errors import ( + DistutilsOptionError, DistutilsPlatformError, DistutilsSetupError, +) +from distutils.util import rfc822_escape +from distutils.version import StrictVersion + +from setuptools.extern import six +from setuptools.extern import packaging +from setuptools.extern.six.moves import map, filter, filterfalse + +from . import SetuptoolsDeprecationWarning + +from setuptools.depends import Require +from setuptools import windows_support +from setuptools.monkey import get_unpatched +from setuptools.config import parse_configuration +import pkg_resources +from .py36compat import Distribution_parse_config_files + +__import__('setuptools.extern.packaging.specifiers') +__import__('setuptools.extern.packaging.version') + + +def _get_unpatched(cls): + warnings.warn("Do not call this function", DistDeprecationWarning) + return get_unpatched(cls) + + +def get_metadata_version(self): + mv = getattr(self, 'metadata_version', None) + + if mv is None: + if self.long_description_content_type or self.provides_extras: + mv = StrictVersion('2.1') + elif (self.maintainer is not None or + self.maintainer_email is not None or + getattr(self, 'python_requires', None) is not None): + mv = StrictVersion('1.2') + elif (self.provides or self.requires or self.obsoletes or + self.classifiers or self.download_url): + mv = StrictVersion('1.1') + else: + mv = StrictVersion('1.0') + + self.metadata_version = mv + + return mv + + +def read_pkg_file(self, file): + """Reads the metadata values from a file object.""" + msg = message_from_file(file) + + def _read_field(name): + value = msg[name] + if value == 'UNKNOWN': + return None + return value + + def _read_list(name): + values = msg.get_all(name, None) + if values == []: + return None + return values + + self.metadata_version = StrictVersion(msg['metadata-version']) + self.name = _read_field('name') + self.version = _read_field('version') + self.description = _read_field('summary') + # we are filling author only. + self.author = _read_field('author') + self.maintainer = None + self.author_email = _read_field('author-email') + self.maintainer_email = None + self.url = _read_field('home-page') + self.license = _read_field('license') + + if 'download-url' in msg: + self.download_url = _read_field('download-url') + else: + self.download_url = None + + self.long_description = _read_field('description') + self.description = _read_field('summary') + + if 'keywords' in msg: + self.keywords = _read_field('keywords').split(',') + + self.platforms = _read_list('platform') + self.classifiers = _read_list('classifier') + + # PEP 314 - these fields only exist in 1.1 + if self.metadata_version == StrictVersion('1.1'): + self.requires = _read_list('requires') + self.provides = _read_list('provides') + self.obsoletes = _read_list('obsoletes') + else: + self.requires = None + self.provides = None + self.obsoletes = None + + +# Based on Python 3.5 version +def write_pkg_file(self, file): + """Write the PKG-INFO format data to a file object. + """ + version = self.get_metadata_version() + + if six.PY2: + def write_field(key, value): + file.write("%s: %s\n" % (key, self._encode_field(value))) + else: + def write_field(key, value): + file.write("%s: %s\n" % (key, value)) + + + write_field('Metadata-Version', str(version)) + write_field('Name', self.get_name()) + write_field('Version', self.get_version()) + write_field('Summary', self.get_description()) + write_field('Home-page', self.get_url()) + + if version < StrictVersion('1.2'): + write_field('Author', self.get_contact()) + write_field('Author-email', self.get_contact_email()) + else: + optional_fields = ( + ('Author', 'author'), + ('Author-email', 'author_email'), + ('Maintainer', 'maintainer'), + ('Maintainer-email', 'maintainer_email'), + ) + + for field, attr in optional_fields: + attr_val = getattr(self, attr) + + if attr_val is not None: + write_field(field, attr_val) + + write_field('License', self.get_license()) + if self.download_url: + write_field('Download-URL', self.download_url) + for project_url in self.project_urls.items(): + write_field('Project-URL', '%s, %s' % project_url) + + long_desc = rfc822_escape(self.get_long_description()) + write_field('Description', long_desc) + + keywords = ','.join(self.get_keywords()) + if keywords: + write_field('Keywords', keywords) + + if version >= StrictVersion('1.2'): + for platform in self.get_platforms(): + write_field('Platform', platform) + else: + self._write_list(file, 'Platform', self.get_platforms()) + + self._write_list(file, 'Classifier', self.get_classifiers()) + + # PEP 314 + self._write_list(file, 'Requires', self.get_requires()) + self._write_list(file, 'Provides', self.get_provides()) + self._write_list(file, 'Obsoletes', self.get_obsoletes()) + + # Setuptools specific for PEP 345 + if hasattr(self, 'python_requires'): + write_field('Requires-Python', self.python_requires) + + # PEP 566 + if self.long_description_content_type: + write_field( + 'Description-Content-Type', + self.long_description_content_type + ) + if self.provides_extras: + for extra in self.provides_extras: + write_field('Provides-Extra', extra) + + +sequence = tuple, list + + +def check_importable(dist, attr, value): + try: + ep = pkg_resources.EntryPoint.parse('x=' + value) + assert not ep.extras + except (TypeError, ValueError, AttributeError, AssertionError): + raise DistutilsSetupError( + "%r must be importable 'module:attrs' string (got %r)" + % (attr, value) + ) + + +def assert_string_list(dist, attr, value): + """Verify that value is a string list or None""" + try: + assert ''.join(value) != value + except (TypeError, ValueError, AttributeError, AssertionError): + raise DistutilsSetupError( + "%r must be a list of strings (got %r)" % (attr, value) + ) + + +def check_nsp(dist, attr, value): + """Verify that namespace packages are valid""" + ns_packages = value + assert_string_list(dist, attr, ns_packages) + for nsp in ns_packages: + if not dist.has_contents_for(nsp): + raise DistutilsSetupError( + "Distribution contains no modules or packages for " + + "namespace package %r" % nsp + ) + parent, sep, child = nsp.rpartition('.') + if parent and parent not in ns_packages: + distutils.log.warn( + "WARNING: %r is declared as a package namespace, but %r" + " is not: please correct this in setup.py", nsp, parent + ) + + +def check_extras(dist, attr, value): + """Verify that extras_require mapping is valid""" + try: + list(itertools.starmap(_check_extra, value.items())) + except (TypeError, ValueError, AttributeError): + raise DistutilsSetupError( + "'extras_require' must be a dictionary whose values are " + "strings or lists of strings containing valid project/version " + "requirement specifiers." + ) + + +def _check_extra(extra, reqs): + name, sep, marker = extra.partition(':') + if marker and pkg_resources.invalid_marker(marker): + raise DistutilsSetupError("Invalid environment marker: " + marker) + list(pkg_resources.parse_requirements(reqs)) + + +def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + tmpl = "{attr!r} must be a boolean value (got {value!r})" + raise DistutilsSetupError(tmpl.format(attr=attr, value=value)) + + +def check_requirements(dist, attr, value): + """Verify that install_requires is a valid requirements list""" + try: + list(pkg_resources.parse_requirements(value)) + if isinstance(value, (dict, set)): + raise TypeError("Unordered types are not allowed") + except (TypeError, ValueError) as error: + tmpl = ( + "{attr!r} must be a string or list of strings " + "containing valid project/version requirement specifiers; {error}" + ) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) + + +def check_specifier(dist, attr, value): + """Verify that value is a valid version specifier""" + try: + packaging.specifiers.SpecifierSet(value) + except packaging.specifiers.InvalidSpecifier as error: + tmpl = ( + "{attr!r} must be a string " + "containing valid version specifiers; {error}" + ) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) + + +def check_entry_points(dist, attr, value): + """Verify that entry_points map is parseable""" + try: + pkg_resources.EntryPoint.parse_map(value) + except ValueError as e: + raise DistutilsSetupError(e) + + +def check_test_suite(dist, attr, value): + if not isinstance(value, six.string_types): + raise DistutilsSetupError("test_suite must be a string") + + +def check_package_data(dist, attr, value): + """Verify that value is a dictionary of package names to glob lists""" + if isinstance(value, dict): + for k, v in value.items(): + if not isinstance(k, str): + break + try: + iter(v) + except TypeError: + break + else: + return + raise DistutilsSetupError( + attr + " must be a dictionary mapping package names to lists of " + "wildcard patterns" + ) + + +def check_packages(dist, attr, value): + for pkgname in value: + if not re.match(r'\w+(\.\w+)*', pkgname): + distutils.log.warn( + "WARNING: %r not a valid package name; please use only " + ".-separated package names in setup.py", pkgname + ) + + +_Distribution = get_unpatched(distutils.core.Distribution) + + +class Distribution(Distribution_parse_config_files, _Distribution): + """Distribution with support for features, tests, and package data + + This is an enhanced version of 'distutils.dist.Distribution' that + effectively adds the following new optional keyword arguments to 'setup()': + + 'install_requires' -- a string or sequence of strings specifying project + versions that the distribution requires when installed, in the format + used by 'pkg_resources.require()'. They will be installed + automatically when the package is installed. If you wish to use + packages that are not available in PyPI, or want to give your users an + alternate download location, you can add a 'find_links' option to the + '[easy_install]' section of your project's 'setup.cfg' file, and then + setuptools will scan the listed web pages for links that satisfy the + requirements. + + 'extras_require' -- a dictionary mapping names of optional "extras" to the + additional requirement(s) that using those extras incurs. For example, + this:: + + extras_require = dict(reST = ["docutils>=0.3", "reSTedit"]) + + indicates that the distribution can optionally provide an extra + capability called "reST", but it can only be used if docutils and + reSTedit are installed. If the user installs your package using + EasyInstall and requests one of your extras, the corresponding + additional requirements will be installed if needed. + + 'features' **deprecated** -- a dictionary mapping option names to + 'setuptools.Feature' + objects. Features are a portion of the distribution that can be + included or excluded based on user options, inter-feature dependencies, + and availability on the current system. Excluded features are omitted + from all setup commands, including source and binary distributions, so + you can create multiple distributions from the same source tree. + Feature names should be valid Python identifiers, except that they may + contain the '-' (minus) sign. Features can be included or excluded + via the command line options '--with-X' and '--without-X', where 'X' is + the name of the feature. Whether a feature is included by default, and + whether you are allowed to control this from the command line, is + determined by the Feature object. See the 'Feature' class for more + information. + + 'test_suite' -- the name of a test suite to run for the 'test' command. + If the user runs 'python setup.py test', the package will be installed, + and the named test suite will be run. The format is the same as + would be used on a 'unittest.py' command line. That is, it is the + dotted name of an object to import and call to generate a test suite. + + 'package_data' -- a dictionary mapping package names to lists of filenames + or globs to use to find data files contained in the named packages. + If the dictionary has filenames or globs listed under '""' (the empty + string), those names will be searched for in every package, in addition + to any names for the specific package. Data files found using these + names/globs will be installed along with the package, in the same + location as the package. Note that globs are allowed to reference + the contents of non-package subdirectories, as long as you use '/' as + a path separator. (Globs are automatically converted to + platform-specific paths at runtime.) + + In addition to these new keywords, this class also has several new methods + for manipulating the distribution's contents. For example, the 'include()' + and 'exclude()' methods can be thought of as in-place add and subtract + commands that add or remove packages, modules, extensions, and so on from + the distribution. They are used by the feature subsystem to configure the + distribution for the included and excluded features. + """ + + _DISTUTILS_UNSUPPORTED_METADATA = { + 'long_description_content_type': None, + 'project_urls': dict, + 'provides_extras': set, + } + + _patched_dist = None + + def patch_missing_pkg_info(self, attrs): + # Fake up a replacement for the data that would normally come from + # PKG-INFO, but which might not yet be built if this is a fresh + # checkout. + # + if not attrs or 'name' not in attrs or 'version' not in attrs: + return + key = pkg_resources.safe_name(str(attrs['name'])).lower() + dist = pkg_resources.working_set.by_key.get(key) + if dist is not None and not dist.has_metadata('PKG-INFO'): + dist._version = pkg_resources.safe_version(str(attrs['version'])) + self._patched_dist = dist + + def __init__(self, attrs=None): + have_package_data = hasattr(self, "package_data") + if not have_package_data: + self.package_data = {} + attrs = attrs or {} + if 'features' in attrs or 'require_features' in attrs: + Feature.warn_deprecated() + self.require_features = [] + self.features = {} + self.dist_files = [] + # Filter-out setuptools' specific options. + self.src_root = attrs.pop("src_root", None) + self.patch_missing_pkg_info(attrs) + self.dependency_links = attrs.pop('dependency_links', []) + self.setup_requires = attrs.pop('setup_requires', []) + for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): + vars(self).setdefault(ep.name, None) + _Distribution.__init__(self, { + k: v for k, v in attrs.items() + if k not in self._DISTUTILS_UNSUPPORTED_METADATA + }) + + # Fill-in missing metadata fields not supported by distutils. + # Note some fields may have been set by other tools (e.g. pbr) + # above; they are taken preferrentially to setup() arguments + for option, default in self._DISTUTILS_UNSUPPORTED_METADATA.items(): + for source in self.metadata.__dict__, attrs: + if option in source: + value = source[option] + break + else: + value = default() if default else None + setattr(self.metadata, option, value) + + if isinstance(self.metadata.version, numbers.Number): + # Some people apparently take "version number" too literally :) + self.metadata.version = str(self.metadata.version) + + if self.metadata.version is not None: + try: + ver = packaging.version.Version(self.metadata.version) + normalized_version = str(ver) + if self.metadata.version != normalized_version: + warnings.warn( + "Normalizing '%s' to '%s'" % ( + self.metadata.version, + normalized_version, + ) + ) + self.metadata.version = normalized_version + except (packaging.version.InvalidVersion, TypeError): + warnings.warn( + "The version specified (%r) is an invalid version, this " + "may not work as expected with newer versions of " + "setuptools, pip, and PyPI. Please see PEP 440 for more " + "details." % self.metadata.version + ) + self._finalize_requires() + + def _finalize_requires(self): + """ + Set `metadata.python_requires` and fix environment markers + in `install_requires` and `extras_require`. + """ + if getattr(self, 'python_requires', None): + self.metadata.python_requires = self.python_requires + + if getattr(self, 'extras_require', None): + for extra in self.extras_require.keys(): + # Since this gets called multiple times at points where the + # keys have become 'converted' extras, ensure that we are only + # truly adding extras we haven't seen before here. + extra = extra.split(':')[0] + if extra: + self.metadata.provides_extras.add(extra) + + self._convert_extras_requirements() + self._move_install_requirements_markers() + + def _convert_extras_requirements(self): + """ + Convert requirements in `extras_require` of the form + `"extra": ["barbazquux; {marker}"]` to + `"extra:{marker}": ["barbazquux"]`. + """ + spec_ext_reqs = getattr(self, 'extras_require', None) or {} + self._tmp_extras_require = defaultdict(list) + for section, v in spec_ext_reqs.items(): + # Do not strip empty sections. + self._tmp_extras_require[section] + for r in pkg_resources.parse_requirements(v): + suffix = self._suffix_for(r) + self._tmp_extras_require[section + suffix].append(r) + + @staticmethod + def _suffix_for(req): + """ + For a requirement, return the 'extras_require' suffix for + that requirement. + """ + return ':' + str(req.marker) if req.marker else '' + + def _move_install_requirements_markers(self): + """ + Move requirements in `install_requires` that are using environment + markers `extras_require`. + """ + + # divide the install_requires into two sets, simple ones still + # handled by install_requires and more complex ones handled + # by extras_require. + + def is_simple_req(req): + return not req.marker + + spec_inst_reqs = getattr(self, 'install_requires', None) or () + inst_reqs = list(pkg_resources.parse_requirements(spec_inst_reqs)) + simple_reqs = filter(is_simple_req, inst_reqs) + complex_reqs = filterfalse(is_simple_req, inst_reqs) + self.install_requires = list(map(str, simple_reqs)) + + for r in complex_reqs: + self._tmp_extras_require[':' + str(r.marker)].append(r) + self.extras_require = dict( + (k, [str(r) for r in map(self._clean_req, v)]) + for k, v in self._tmp_extras_require.items() + ) + + def _clean_req(self, req): + """ + Given a Requirement, remove environment markers and return it. + """ + req.marker = None + return req + + def parse_config_files(self, filenames=None, ignore_option_errors=False): + """Parses configuration files from various levels + and loads configuration. + + """ + _Distribution.parse_config_files(self, filenames=filenames) + + parse_configuration(self, self.command_options, + ignore_option_errors=ignore_option_errors) + self._finalize_requires() + + def parse_command_line(self): + """Process features after parsing command line options""" + result = _Distribution.parse_command_line(self) + if self.features: + self._finalize_features() + return result + + def _feature_attrname(self, name): + """Convert feature name to corresponding option attribute name""" + return 'with_' + name.replace('-', '_') + + def fetch_build_eggs(self, requires): + """Resolve pre-setup requirements""" + resolved_dists = pkg_resources.working_set.resolve( + pkg_resources.parse_requirements(requires), + installer=self.fetch_build_egg, + replace_conflicting=True, + ) + for dist in resolved_dists: + pkg_resources.working_set.add(dist, replace=True) + return resolved_dists + + def finalize_options(self): + _Distribution.finalize_options(self) + if self.features: + self._set_global_opts_from_features() + + for ep in pkg_resources.iter_entry_points('distutils.setup_keywords'): + value = getattr(self, ep.name, None) + if value is not None: + ep.require(installer=self.fetch_build_egg) + ep.load()(self, ep.name, value) + if getattr(self, 'convert_2to3_doctests', None): + # XXX may convert to set here when we can rely on set being builtin + self.convert_2to3_doctests = [ + os.path.abspath(p) + for p in self.convert_2to3_doctests + ] + else: + self.convert_2to3_doctests = [] + + def get_egg_cache_dir(self): + egg_cache_dir = os.path.join(os.curdir, '.eggs') + if not os.path.exists(egg_cache_dir): + os.mkdir(egg_cache_dir) + windows_support.hide_file(egg_cache_dir) + readme_txt_filename = os.path.join(egg_cache_dir, 'README.txt') + with open(readme_txt_filename, 'w') as f: + f.write('This directory contains eggs that were downloaded ' + 'by setuptools to build, test, and run plug-ins.\n\n') + f.write('This directory caches those eggs to prevent ' + 'repeated downloads.\n\n') + f.write('However, it is safe to delete this directory.\n\n') + + return egg_cache_dir + + def fetch_build_egg(self, req): + """Fetch an egg needed for building""" + from setuptools.command.easy_install import easy_install + dist = self.__class__({'script_args': ['easy_install']}) + opts = dist.get_option_dict('easy_install') + opts.clear() + opts.update( + (k, v) + for k, v in self.get_option_dict('easy_install').items() + if k in ( + # don't use any other settings + 'find_links', 'site_dirs', 'index_url', + 'optimize', 'site_dirs', 'allow_hosts', + )) + if self.dependency_links: + links = self.dependency_links[:] + if 'find_links' in opts: + links = opts['find_links'][1] + links + opts['find_links'] = ('setup', links) + install_dir = self.get_egg_cache_dir() + cmd = easy_install( + dist, args=["x"], install_dir=install_dir, + exclude_scripts=True, + always_copy=False, build_directory=None, editable=False, + upgrade=False, multi_version=True, no_report=True, user=False + ) + cmd.ensure_finalized() + return cmd.easy_install(req) + + def _set_global_opts_from_features(self): + """Add --with-X/--without-X options based on optional features""" + + go = [] + no = self.negative_opt.copy() + + for name, feature in self.features.items(): + self._set_feature(name, None) + feature.validate(self) + + if feature.optional: + descr = feature.description + incdef = ' (default)' + excdef = '' + if not feature.include_by_default(): + excdef, incdef = incdef, excdef + + new = ( + ('with-' + name, None, 'include ' + descr + incdef), + ('without-' + name, None, 'exclude ' + descr + excdef), + ) + go.extend(new) + no['without-' + name] = 'with-' + name + + self.global_options = self.feature_options = go + self.global_options + self.negative_opt = self.feature_negopt = no + + def _finalize_features(self): + """Add/remove features and resolve dependencies between them""" + + # First, flag all the enabled items (and thus their dependencies) + for name, feature in self.features.items(): + enabled = self.feature_is_included(name) + if enabled or (enabled is None and feature.include_by_default()): + feature.include_in(self) + self._set_feature(name, 1) + + # Then disable the rest, so that off-by-default features don't + # get flagged as errors when they're required by an enabled feature + for name, feature in self.features.items(): + if not self.feature_is_included(name): + feature.exclude_from(self) + self._set_feature(name, 0) + + def get_command_class(self, command): + """Pluggable version of get_command_class()""" + if command in self.cmdclass: + return self.cmdclass[command] + + eps = pkg_resources.iter_entry_points('distutils.commands', command) + for ep in eps: + ep.require(installer=self.fetch_build_egg) + self.cmdclass[command] = cmdclass = ep.load() + return cmdclass + else: + return _Distribution.get_command_class(self, command) + + def print_commands(self): + for ep in pkg_resources.iter_entry_points('distutils.commands'): + if ep.name not in self.cmdclass: + # don't require extras as the commands won't be invoked + cmdclass = ep.resolve() + self.cmdclass[ep.name] = cmdclass + return _Distribution.print_commands(self) + + def get_command_list(self): + for ep in pkg_resources.iter_entry_points('distutils.commands'): + if ep.name not in self.cmdclass: + # don't require extras as the commands won't be invoked + cmdclass = ep.resolve() + self.cmdclass[ep.name] = cmdclass + return _Distribution.get_command_list(self) + + def _set_feature(self, name, status): + """Set feature's inclusion status""" + setattr(self, self._feature_attrname(name), status) + + def feature_is_included(self, name): + """Return 1 if feature is included, 0 if excluded, 'None' if unknown""" + return getattr(self, self._feature_attrname(name)) + + def include_feature(self, name): + """Request inclusion of feature named 'name'""" + + if self.feature_is_included(name) == 0: + descr = self.features[name].description + raise DistutilsOptionError( + descr + " is required, but was excluded or is not available" + ) + self.features[name].include_in(self) + self._set_feature(name, 1) + + def include(self, **attrs): + """Add items to distribution that are named in keyword arguments + + For example, 'dist.exclude(py_modules=["x"])' would add 'x' to + the distribution's 'py_modules' attribute, if it was not already + there. + + Currently, this method only supports inclusion for attributes that are + lists or tuples. If you need to add support for adding to other + attributes in this or a subclass, you can add an '_include_X' method, + where 'X' is the name of the attribute. The method will be called with + the value passed to 'include()'. So, 'dist.include(foo={"bar":"baz"})' + will try to call 'dist._include_foo({"bar":"baz"})', which can then + handle whatever special inclusion logic is needed. + """ + for k, v in attrs.items(): + include = getattr(self, '_include_' + k, None) + if include: + include(v) + else: + self._include_misc(k, v) + + def exclude_package(self, package): + """Remove packages, modules, and extensions in named package""" + + pfx = package + '.' + if self.packages: + self.packages = [ + p for p in self.packages + if p != package and not p.startswith(pfx) + ] + + if self.py_modules: + self.py_modules = [ + p for p in self.py_modules + if p != package and not p.startswith(pfx) + ] + + if self.ext_modules: + self.ext_modules = [ + p for p in self.ext_modules + if p.name != package and not p.name.startswith(pfx) + ] + + def has_contents_for(self, package): + """Return true if 'exclude_package(package)' would do something""" + + pfx = package + '.' + + for p in self.iter_distribution_names(): + if p == package or p.startswith(pfx): + return True + + def _exclude_misc(self, name, value): + """Handle 'exclude()' for list/tuple attrs without a special handler""" + if not isinstance(value, sequence): + raise DistutilsSetupError( + "%s: setting must be a list or tuple (%r)" % (name, value) + ) + try: + old = getattr(self, name) + except AttributeError: + raise DistutilsSetupError( + "%s: No such distribution setting" % name + ) + if old is not None and not isinstance(old, sequence): + raise DistutilsSetupError( + name + ": this setting cannot be changed via include/exclude" + ) + elif old: + setattr(self, name, [item for item in old if item not in value]) + + def _include_misc(self, name, value): + """Handle 'include()' for list/tuple attrs without a special handler""" + + if not isinstance(value, sequence): + raise DistutilsSetupError( + "%s: setting must be a list (%r)" % (name, value) + ) + try: + old = getattr(self, name) + except AttributeError: + raise DistutilsSetupError( + "%s: No such distribution setting" % name + ) + if old is None: + setattr(self, name, value) + elif not isinstance(old, sequence): + raise DistutilsSetupError( + name + ": this setting cannot be changed via include/exclude" + ) + else: + new = [item for item in value if item not in old] + setattr(self, name, old + new) + + def exclude(self, **attrs): + """Remove items from distribution that are named in keyword arguments + + For example, 'dist.exclude(py_modules=["x"])' would remove 'x' from + the distribution's 'py_modules' attribute. Excluding packages uses + the 'exclude_package()' method, so all of the package's contained + packages, modules, and extensions are also excluded. + + Currently, this method only supports exclusion from attributes that are + lists or tuples. If you need to add support for excluding from other + attributes in this or a subclass, you can add an '_exclude_X' method, + where 'X' is the name of the attribute. The method will be called with + the value passed to 'exclude()'. So, 'dist.exclude(foo={"bar":"baz"})' + will try to call 'dist._exclude_foo({"bar":"baz"})', which can then + handle whatever special exclusion logic is needed. + """ + for k, v in attrs.items(): + exclude = getattr(self, '_exclude_' + k, None) + if exclude: + exclude(v) + else: + self._exclude_misc(k, v) + + def _exclude_packages(self, packages): + if not isinstance(packages, sequence): + raise DistutilsSetupError( + "packages: setting must be a list or tuple (%r)" % (packages,) + ) + list(map(self.exclude_package, packages)) + + def _parse_command_opts(self, parser, args): + # Remove --with-X/--without-X options when processing command args + self.global_options = self.__class__.global_options + self.negative_opt = self.__class__.negative_opt + + # First, expand any aliases + command = args[0] + aliases = self.get_option_dict('aliases') + while command in aliases: + src, alias = aliases[command] + del aliases[command] # ensure each alias can expand only once! + import shlex + args[:1] = shlex.split(alias, True) + command = args[0] + + nargs = _Distribution._parse_command_opts(self, parser, args) + + # Handle commands that want to consume all remaining arguments + cmd_class = self.get_command_class(command) + if getattr(cmd_class, 'command_consumes_arguments', None): + self.get_option_dict(command)['args'] = ("command line", nargs) + if nargs is not None: + return [] + + return nargs + + def get_cmdline_options(self): + """Return a '{cmd: {opt:val}}' map of all command-line options + + Option names are all long, but do not include the leading '--', and + contain dashes rather than underscores. If the option doesn't take + an argument (e.g. '--quiet'), the 'val' is 'None'. + + Note that options provided by config files are intentionally excluded. + """ + + d = {} + + for cmd, opts in self.command_options.items(): + + for opt, (src, val) in opts.items(): + + if src != "command line": + continue + + opt = opt.replace('_', '-') + + if val == 0: + cmdobj = self.get_command_obj(cmd) + neg_opt = self.negative_opt.copy() + neg_opt.update(getattr(cmdobj, 'negative_opt', {})) + for neg, pos in neg_opt.items(): + if pos == opt: + opt = neg + val = None + break + else: + raise AssertionError("Shouldn't be able to get here") + + elif val == 1: + val = None + + d.setdefault(cmd, {})[opt] = val + + return d + + def iter_distribution_names(self): + """Yield all packages, modules, and extension names in distribution""" + + for pkg in self.packages or (): + yield pkg + + for module in self.py_modules or (): + yield module + + for ext in self.ext_modules or (): + if isinstance(ext, tuple): + name, buildinfo = ext + else: + name = ext.name + if name.endswith('module'): + name = name[:-6] + yield name + + def handle_display_options(self, option_order): + """If there were any non-global "display-only" options + (--help-commands or the metadata display options) on the command + line, display the requested info and return true; else return + false. + """ + import sys + + if six.PY2 or self.help_commands: + return _Distribution.handle_display_options(self, option_order) + + # Stdout may be StringIO (e.g. in tests) + import io + if not isinstance(sys.stdout, io.TextIOWrapper): + return _Distribution.handle_display_options(self, option_order) + + # Don't wrap stdout if utf-8 is already the encoding. Provides + # workaround for #334. + if sys.stdout.encoding.lower() in ('utf-8', 'utf8'): + return _Distribution.handle_display_options(self, option_order) + + # Print metadata in UTF-8 no matter the platform + encoding = sys.stdout.encoding + errors = sys.stdout.errors + newline = sys.platform != 'win32' and '\n' or None + line_buffering = sys.stdout.line_buffering + + sys.stdout = io.TextIOWrapper( + sys.stdout.detach(), 'utf-8', errors, newline, line_buffering) + try: + return _Distribution.handle_display_options(self, option_order) + finally: + sys.stdout = io.TextIOWrapper( + sys.stdout.detach(), encoding, errors, newline, line_buffering) + + +class Feature: + """ + **deprecated** -- The `Feature` facility was never completely implemented + or supported, `has reported issues + <https://github.com/pypa/setuptools/issues/58>`_ and will be removed in + a future version. + + A subset of the distribution that can be excluded if unneeded/wanted + + Features are created using these keyword arguments: + + 'description' -- a short, human readable description of the feature, to + be used in error messages, and option help messages. + + 'standard' -- if true, the feature is included by default if it is + available on the current system. Otherwise, the feature is only + included if requested via a command line '--with-X' option, or if + another included feature requires it. The default setting is 'False'. + + 'available' -- if true, the feature is available for installation on the + current system. The default setting is 'True'. + + 'optional' -- if true, the feature's inclusion can be controlled from the + command line, using the '--with-X' or '--without-X' options. If + false, the feature's inclusion status is determined automatically, + based on 'availabile', 'standard', and whether any other feature + requires it. The default setting is 'True'. + + 'require_features' -- a string or sequence of strings naming features + that should also be included if this feature is included. Defaults to + empty list. May also contain 'Require' objects that should be + added/removed from the distribution. + + 'remove' -- a string or list of strings naming packages to be removed + from the distribution if this feature is *not* included. If the + feature *is* included, this argument is ignored. This argument exists + to support removing features that "crosscut" a distribution, such as + defining a 'tests' feature that removes all the 'tests' subpackages + provided by other features. The default for this argument is an empty + list. (Note: the named package(s) or modules must exist in the base + distribution when the 'setup()' function is initially called.) + + other keywords -- any other keyword arguments are saved, and passed to + the distribution's 'include()' and 'exclude()' methods when the + feature is included or excluded, respectively. So, for example, you + could pass 'packages=["a","b"]' to cause packages 'a' and 'b' to be + added or removed from the distribution as appropriate. + + A feature must include at least one 'requires', 'remove', or other + keyword argument. Otherwise, it can't affect the distribution in any way. + Note also that you can subclass 'Feature' to create your own specialized + feature types that modify the distribution in other ways when included or + excluded. See the docstrings for the various methods here for more detail. + Aside from the methods, the only feature attributes that distributions look + at are 'description' and 'optional'. + """ + + @staticmethod + def warn_deprecated(): + msg = ( + "Features are deprecated and will be removed in a future " + "version. See https://github.com/pypa/setuptools/issues/65." + ) + warnings.warn(msg, DistDeprecationWarning, stacklevel=3) + + def __init__( + self, description, standard=False, available=True, + optional=True, require_features=(), remove=(), **extras): + self.warn_deprecated() + + self.description = description + self.standard = standard + self.available = available + self.optional = optional + if isinstance(require_features, (str, Require)): + require_features = require_features, + + self.require_features = [ + r for r in require_features if isinstance(r, str) + ] + er = [r for r in require_features if not isinstance(r, str)] + if er: + extras['require_features'] = er + + if isinstance(remove, str): + remove = remove, + self.remove = remove + self.extras = extras + + if not remove and not require_features and not extras: + raise DistutilsSetupError( + "Feature %s: must define 'require_features', 'remove', or " + "at least one of 'packages', 'py_modules', etc." + ) + + def include_by_default(self): + """Should this feature be included by default?""" + return self.available and self.standard + + def include_in(self, dist): + """Ensure feature and its requirements are included in distribution + + You may override this in a subclass to perform additional operations on + the distribution. Note that this method may be called more than once + per feature, and so should be idempotent. + + """ + + if not self.available: + raise DistutilsPlatformError( + self.description + " is required, " + "but is not available on this platform" + ) + + dist.include(**self.extras) + + for f in self.require_features: + dist.include_feature(f) + + def exclude_from(self, dist): + """Ensure feature is excluded from distribution + + You may override this in a subclass to perform additional operations on + the distribution. This method will be called at most once per + feature, and only after all included features have been asked to + include themselves. + """ + + dist.exclude(**self.extras) + + if self.remove: + for item in self.remove: + dist.exclude_package(item) + + def validate(self, dist): + """Verify that feature makes sense in context of distribution + + This method is called by the distribution just before it parses its + command line. It checks to ensure that the 'remove' attribute, if any, + contains only valid package/module names that are present in the base + distribution when 'setup()' is called. You may override it in a + subclass to perform any other required validation of the feature + against a target distribution. + """ + + for item in self.remove: + if not dist.has_contents_for(item): + raise DistutilsSetupError( + "%s wants to be able to remove %s, but the distribution" + " doesn't contain any packages or modules under %s" + % (self.description, item, item) + ) + + +class DistDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in dist in setuptools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/winvenv/Lib/site-packages/setuptools/extension.py b/winvenv/Lib/site-packages/setuptools/extension.py new file mode 100644 index 0000000..2946889 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/extension.py @@ -0,0 +1,57 @@ +import re +import functools +import distutils.core +import distutils.errors +import distutils.extension + +from setuptools.extern.six.moves import map + +from .monkey import get_unpatched + + +def _have_cython(): + """ + Return True if Cython can be imported. + """ + cython_impl = 'Cython.Distutils.build_ext' + try: + # from (cython_impl) import build_ext + __import__(cython_impl, fromlist=['build_ext']).build_ext + return True + except Exception: + pass + return False + + +# for compatibility +have_pyrex = _have_cython + +_Extension = get_unpatched(distutils.core.Extension) + + +class Extension(_Extension): + """Extension that uses '.c' files in place of '.pyx' files""" + + def __init__(self, name, sources, *args, **kw): + # The *args is needed for compatibility as calls may use positional + # arguments. py_limited_api may be set only via keyword. + self.py_limited_api = kw.pop("py_limited_api", False) + _Extension.__init__(self, name, sources, *args, **kw) + + def _convert_pyx_sources_to_lang(self): + """ + Replace sources with .pyx extensions to sources with the target + language extension. This mechanism allows language authors to supply + pre-converted sources but to prefer the .pyx sources. + """ + if _have_cython(): + # the build has Cython, so allow it to compile the .pyx files + return + lang = self.language or '' + target_ext = '.cpp' if lang.lower() == 'c++' else '.c' + sub = functools.partial(re.sub, '.pyx$', target_ext) + self.sources = list(map(sub, self.sources)) + + +class Library(Extension): + """Just like a regular Extension, but built as a library instead""" diff --git a/winvenv/Lib/site-packages/setuptools/extern/__init__.py b/winvenv/Lib/site-packages/setuptools/extern/__init__.py new file mode 100644 index 0000000..cb2fa32 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/extern/__init__.py @@ -0,0 +1,73 @@ +import sys + + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from root_name. + """ + + def __init__(self, root_name, vendored_names=(), vendor_pkg=None): + self.root_name = root_name + self.vendored_names = set(vendored_names) + self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') + + @property + def search_path(self): + """ + Search first the vendor package then as a natural package. + """ + yield self.vendor_pkg + '.' + yield '' + + def find_module(self, fullname, path=None): + """ + Return self when fullname starts with root_name and the + target module is one vendored through this importer. + """ + root, base, target = fullname.partition(self.root_name + '.') + if root: + return + if not any(map(target.startswith, self.vendored_names)): + return + return self + + def load_module(self, fullname): + """ + Iterate over the search path to locate and load fullname. + """ + root, base, target = fullname.partition(self.root_name + '.') + for prefix in self.search_path: + try: + extant = prefix + target + __import__(extant) + mod = sys.modules[extant] + sys.modules[fullname] = mod + # mysterious hack: + # Remove the reference to the extant package/module + # on later Python versions to cause relative imports + # in the vendor package to resolve the same modules + # as those going through this importer. + if sys.version_info >= (3, ): + del sys.modules[extant] + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + def install(self): + """ + Install this importer into sys.meta_path if not already present. + """ + if self not in sys.meta_path: + sys.meta_path.append(self) + + +names = 'six', 'packaging', 'pyparsing', +VendorImporter(__name__, names, 'setuptools._vendor').install() diff --git a/winvenv/Lib/site-packages/setuptools/glibc.py b/winvenv/Lib/site-packages/setuptools/glibc.py new file mode 100644 index 0000000..a134591 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/glibc.py @@ -0,0 +1,86 @@ +# This file originally from pip: +# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/utils/glibc.py +from __future__ import absolute_import + +import ctypes +import re +import warnings + + +def glibc_version_string(): + "Returns glibc version string, or None if not using glibc." + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# Separated out from have_compatible_glibc for easier unit testing +def check_glibc_version(version_str, required_major, minimum_minor): + # Parse string and check against requested version. + # + # We use a regexp instead of str.split because we want to discard any + # random junk that might come after the minor version -- this might happen + # in patched/forked versions of glibc (e.g. Linaro's version of glibc + # uses version strings like "2.20-2014.11"). See gh-3588. + m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str) + if not m: + warnings.warn("Expected glibc version with 2 components major.minor," + " got: %s" % version_str, RuntimeWarning) + return False + return (int(m.group("major")) == required_major and + int(m.group("minor")) >= minimum_minor) + + +def have_compatible_glibc(required_major, minimum_minor): + version_str = glibc_version_string() + if version_str is None: + return False + return check_glibc_version(version_str, required_major, minimum_minor) + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver(): + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/winvenv/Lib/site-packages/setuptools/glob.py b/winvenv/Lib/site-packages/setuptools/glob.py new file mode 100644 index 0000000..9d7cbc5 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/glob.py @@ -0,0 +1,174 @@ +""" +Filename globbing utility. Mostly a copy of `glob` from Python 3.5. + +Changes include: + * `yield from` and PEP3102 `*` removed. + * Hidden files are not ignored. +""" + +import os +import re +import fnmatch + +__all__ = ["glob", "iglob", "escape"] + + +def glob(pathname, recursive=False): + """Return a list of paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + If recursive is true, the pattern '**' will match any files and + zero or more directories and subdirectories. + """ + return list(iglob(pathname, recursive=recursive)) + + +def iglob(pathname, recursive=False): + """Return an iterator which yields the paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + If recursive is true, the pattern '**' will match any files and + zero or more directories and subdirectories. + """ + it = _iglob(pathname, recursive) + if recursive and _isrecursive(pathname): + s = next(it) # skip empty string + assert not s + return it + + +def _iglob(pathname, recursive): + dirname, basename = os.path.split(pathname) + if not has_magic(pathname): + if basename: + if os.path.lexists(pathname): + yield pathname + else: + # Patterns ending with a slash should match only directories + if os.path.isdir(dirname): + yield pathname + return + if not dirname: + if recursive and _isrecursive(basename): + for x in glob2(dirname, basename): + yield x + else: + for x in glob1(dirname, basename): + yield x + return + # `os.path.split()` returns the argument itself as a dirname if it is a + # drive or UNC path. Prevent an infinite recursion if a drive or UNC path + # contains magic characters (i.e. r'\\?\C:'). + if dirname != pathname and has_magic(dirname): + dirs = _iglob(dirname, recursive) + else: + dirs = [dirname] + if has_magic(basename): + if recursive and _isrecursive(basename): + glob_in_dir = glob2 + else: + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) + + +# These 2 helper functions non-recursively glob inside a literal directory. +# They return a list of basenames. `glob1` accepts a pattern while `glob0` +# takes a literal basename (so it only has to check for its existence). + + +def glob1(dirname, pattern): + if not dirname: + if isinstance(pattern, bytes): + dirname = os.curdir.encode('ASCII') + else: + dirname = os.curdir + try: + names = os.listdir(dirname) + except OSError: + return [] + return fnmatch.filter(names, pattern) + + +def glob0(dirname, basename): + if not basename: + # `os.path.split()` returns an empty basename for paths ending with a + # directory separator. 'q*x/' should match only directories. + if os.path.isdir(dirname): + return [basename] + else: + if os.path.lexists(os.path.join(dirname, basename)): + return [basename] + return [] + + +# This helper function recursively yields relative pathnames inside a literal +# directory. + + +def glob2(dirname, pattern): + assert _isrecursive(pattern) + yield pattern[:0] + for x in _rlistdir(dirname): + yield x + + +# Recursively yields relative pathnames inside a literal directory. +def _rlistdir(dirname): + if not dirname: + if isinstance(dirname, bytes): + dirname = os.curdir.encode('ASCII') + else: + dirname = os.curdir + try: + names = os.listdir(dirname) + except os.error: + return + for x in names: + yield x + path = os.path.join(dirname, x) if dirname else x + for y in _rlistdir(path): + yield os.path.join(x, y) + + +magic_check = re.compile('([*?[])') +magic_check_bytes = re.compile(b'([*?[])') + + +def has_magic(s): + if isinstance(s, bytes): + match = magic_check_bytes.search(s) + else: + match = magic_check.search(s) + return match is not None + + +def _isrecursive(pattern): + if isinstance(pattern, bytes): + return pattern == b'**' + else: + return pattern == '**' + + +def escape(pathname): + """Escape all special characters. + """ + # Escaping is done by wrapping any of "*?[" between square brackets. + # Metacharacters do not work in the drive part and shouldn't be escaped. + drive, pathname = os.path.splitdrive(pathname) + if isinstance(pathname, bytes): + pathname = magic_check_bytes.sub(br'[\1]', pathname) + else: + pathname = magic_check.sub(r'[\1]', pathname) + return drive + pathname diff --git a/winvenv/Lib/site-packages/setuptools/gui-32.exe b/winvenv/Lib/site-packages/setuptools/gui-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..f8d3509653ba8f80ca7f3aa7f95616142ba83a94 GIT binary patch literal 65536 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/setuptools/gui-64.exe b/winvenv/Lib/site-packages/setuptools/gui-64.exe new file mode 100644 index 0000000000000000000000000000000000000000..330c51a5dde15a0bb610a48cd0ca11770c914dae GIT binary patch literal 75264 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/setuptools/gui.exe b/winvenv/Lib/site-packages/setuptools/gui.exe new file mode 100644 index 0000000000000000000000000000000000000000..f8d3509653ba8f80ca7f3aa7f95616142ba83a94 GIT binary patch literal 65536 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 literal 0 HcmV?d00001 diff --git a/winvenv/Lib/site-packages/setuptools/launch.py b/winvenv/Lib/site-packages/setuptools/launch.py new file mode 100644 index 0000000..308283e --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/launch.py @@ -0,0 +1,35 @@ +""" +Launch the Python script on the command line after +setuptools is bootstrapped via import. +""" + +# Note that setuptools gets imported implicitly by the +# invocation of this script using python -m setuptools.launch + +import tokenize +import sys + + +def run(): + """ + Run the script in sys.argv[1] as if it had + been invoked naturally. + """ + __builtins__ + script_name = sys.argv[1] + namespace = dict( + __file__=script_name, + __name__='__main__', + __doc__=None, + ) + sys.argv[:] = sys.argv[1:] + + open_ = getattr(tokenize, 'open', open) + script = open_(script_name).read() + norm_script = script.replace('\\r\\n', '\\n') + code = compile(norm_script, script_name, 'exec') + exec(code, namespace) + + +if __name__ == '__main__': + run() diff --git a/winvenv/Lib/site-packages/setuptools/lib2to3_ex.py b/winvenv/Lib/site-packages/setuptools/lib2to3_ex.py new file mode 100644 index 0000000..4b1a73f --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/lib2to3_ex.py @@ -0,0 +1,62 @@ +""" +Customized Mixin2to3 support: + + - adds support for converting doctests + + +This module raises an ImportError on Python 2. +""" + +from distutils.util import Mixin2to3 as _Mixin2to3 +from distutils import log +from lib2to3.refactor import RefactoringTool, get_fixers_from_package + +import setuptools + + +class DistutilsRefactoringTool(RefactoringTool): + def log_error(self, msg, *args, **kw): + log.error(msg, *args) + + def log_message(self, msg, *args): + log.info(msg, *args) + + def log_debug(self, msg, *args): + log.debug(msg, *args) + + +class Mixin2to3(_Mixin2to3): + def run_2to3(self, files, doctests=False): + # See of the distribution option has been set, otherwise check the + # setuptools default. + if self.distribution.use_2to3 is not True: + return + if not files: + return + log.info("Fixing " + " ".join(files)) + self.__build_fixer_names() + self.__exclude_fixers() + if doctests: + if setuptools.run_2to3_on_doctests: + r = DistutilsRefactoringTool(self.fixer_names) + r.refactor(files, write=True, doctests_only=True) + else: + _Mixin2to3.run_2to3(self, files) + + def __build_fixer_names(self): + if self.fixer_names: + return + self.fixer_names = [] + for p in setuptools.lib2to3_fixer_packages: + self.fixer_names.extend(get_fixers_from_package(p)) + if self.distribution.use_2to3_fixers is not None: + for p in self.distribution.use_2to3_fixers: + self.fixer_names.extend(get_fixers_from_package(p)) + + def __exclude_fixers(self): + excluded_fixers = getattr(self, 'exclude_fixers', []) + if self.distribution.use_2to3_exclude_fixers is not None: + excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers) + for fixer_name in excluded_fixers: + if fixer_name in self.fixer_names: + self.fixer_names.remove(fixer_name) diff --git a/winvenv/Lib/site-packages/setuptools/monkey.py b/winvenv/Lib/site-packages/setuptools/monkey.py new file mode 100644 index 0000000..3c77f8c --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/monkey.py @@ -0,0 +1,179 @@ +""" +Monkey patching of distutils. +""" + +import sys +import distutils.filelist +import platform +import types +import functools +from importlib import import_module +import inspect + +from setuptools.extern import six + +import setuptools + +__all__ = [] +""" +Everything is private. Contact the project team +if you think you need this functionality. +""" + + +def _get_mro(cls): + """ + Returns the bases classes for cls sorted by the MRO. + + Works around an issue on Jython where inspect.getmro will not return all + base classes if multiple classes share the same name. Instead, this + function will return a tuple containing the class itself, and the contents + of cls.__bases__. See https://github.com/pypa/setuptools/issues/1024. + """ + if platform.python_implementation() == "Jython": + return (cls,) + cls.__bases__ + return inspect.getmro(cls) + + +def get_unpatched(item): + lookup = ( + get_unpatched_class if isinstance(item, six.class_types) else + get_unpatched_function if isinstance(item, types.FunctionType) else + lambda item: None + ) + return lookup(item) + + +def get_unpatched_class(cls): + """Protect against re-patching the distutils if reloaded + + Also ensures that no other distutils extension monkeypatched the distutils + first. + """ + external_bases = ( + cls + for cls in _get_mro(cls) + if not cls.__module__.startswith('setuptools') + ) + base = next(external_bases) + if not base.__module__.startswith('distutils'): + msg = "distutils has already been patched by %r" % cls + raise AssertionError(msg) + return base + + +def patch_all(): + # we can't patch distutils.cmd, alas + distutils.core.Command = setuptools.Command + + has_issue_12885 = sys.version_info <= (3, 5, 3) + + if has_issue_12885: + # fix findall bug in distutils (http://bugs.python.org/issue12885) + distutils.filelist.findall = setuptools.findall + + needs_warehouse = ( + sys.version_info < (2, 7, 13) + or + (3, 4) < sys.version_info < (3, 4, 6) + or + (3, 5) < sys.version_info <= (3, 5, 3) + ) + + if needs_warehouse: + warehouse = 'https://upload.pypi.org/legacy/' + distutils.config.PyPIRCCommand.DEFAULT_REPOSITORY = warehouse + + _patch_distribution_metadata() + + # Install Distribution throughout the distutils + for module in distutils.dist, distutils.core, distutils.cmd: + module.Distribution = setuptools.dist.Distribution + + # Install the patched Extension + distutils.core.Extension = setuptools.extension.Extension + distutils.extension.Extension = setuptools.extension.Extension + if 'distutils.command.build_ext' in sys.modules: + sys.modules['distutils.command.build_ext'].Extension = ( + setuptools.extension.Extension + ) + + patch_for_msvc_specialized_compiler() + + +def _patch_distribution_metadata(): + """Patch write_pkg_file and read_pkg_file for higher metadata standards""" + for attr in ('write_pkg_file', 'read_pkg_file', 'get_metadata_version'): + new_val = getattr(setuptools.dist, attr) + setattr(distutils.dist.DistributionMetadata, attr, new_val) + + +def patch_func(replacement, target_mod, func_name): + """ + Patch func_name in target_mod with replacement + + Important - original must be resolved by name to avoid + patching an already patched function. + """ + original = getattr(target_mod, func_name) + + # set the 'unpatched' attribute on the replacement to + # point to the original. + vars(replacement).setdefault('unpatched', original) + + # replace the function in the original module + setattr(target_mod, func_name, replacement) + + +def get_unpatched_function(candidate): + return getattr(candidate, 'unpatched') + + +def patch_for_msvc_specialized_compiler(): + """ + Patch functions in distutils to use standalone Microsoft Visual C++ + compilers. + """ + # import late to avoid circular imports on Python < 3.5 + msvc = import_module('setuptools.msvc') + + if platform.system() != 'Windows': + # Compilers only availables on Microsoft Windows + return + + def patch_params(mod_name, func_name): + """ + Prepare the parameters for patch_func to patch indicated function. + """ + repl_prefix = 'msvc9_' if 'msvc9' in mod_name else 'msvc14_' + repl_name = repl_prefix + func_name.lstrip('_') + repl = getattr(msvc, repl_name) + mod = import_module(mod_name) + if not hasattr(mod, func_name): + raise ImportError(func_name) + return repl, mod, func_name + + # Python 2.7 to 3.4 + msvc9 = functools.partial(patch_params, 'distutils.msvc9compiler') + + # Python 3.5+ + msvc14 = functools.partial(patch_params, 'distutils._msvccompiler') + + try: + # Patch distutils.msvc9compiler + patch_func(*msvc9('find_vcvarsall')) + patch_func(*msvc9('query_vcvarsall')) + except ImportError: + pass + + try: + # Patch distutils._msvccompiler._get_vc_env + patch_func(*msvc14('_get_vc_env')) + except ImportError: + pass + + try: + # Patch distutils._msvccompiler.gen_lib_options for Numpy + patch_func(*msvc14('gen_lib_options')) + except ImportError: + pass diff --git a/winvenv/Lib/site-packages/setuptools/msvc.py b/winvenv/Lib/site-packages/setuptools/msvc.py new file mode 100644 index 0000000..b9c472f --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/msvc.py @@ -0,0 +1,1301 @@ +""" +Improved support for Microsoft Visual C++ compilers. + +Known supported compilers: +-------------------------- +Microsoft Visual C++ 9.0: + Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) + Microsoft Windows SDK 6.1 (x86, x64, ia64) + Microsoft Windows SDK 7.0 (x86, x64, ia64) + +Microsoft Visual C++ 10.0: + Microsoft Windows SDK 7.1 (x86, x64, ia64) + +Microsoft Visual C++ 14.0: + Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) + Microsoft Visual Studio 2017 (x86, x64, arm, arm64) + Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) +""" + +import os +import sys +import platform +import itertools +import distutils.errors +from setuptools.extern.packaging.version import LegacyVersion + +from setuptools.extern.six.moves import filterfalse + +from .monkey import get_unpatched + +if platform.system() == 'Windows': + from setuptools.extern.six.moves import winreg + safe_env = os.environ +else: + """ + Mock winreg and environ so the module can be imported + on this platform. + """ + + class winreg: + HKEY_USERS = None + HKEY_CURRENT_USER = None + HKEY_LOCAL_MACHINE = None + HKEY_CLASSES_ROOT = None + + safe_env = dict() + +_msvc9_suppress_errors = ( + # msvc9compiler isn't available on some platforms + ImportError, + + # msvc9compiler raises DistutilsPlatformError in some + # environments. See #1118. + distutils.errors.DistutilsPlatformError, +) + +try: + from distutils.msvc9compiler import Reg +except _msvc9_suppress_errors: + pass + + +def msvc9_find_vcvarsall(version): + """ + Patched "distutils.msvc9compiler.find_vcvarsall" to use the standalone + compiler build for Python (VCForPython). Fall back to original behavior + when the standalone compiler is not available. + + Redirect the path of "vcvarsall.bat". + + Known supported compilers + ------------------------- + Microsoft Visual C++ 9.0: + Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) + + Parameters + ---------- + version: float + Required Microsoft Visual C++ version. + + Return + ------ + vcvarsall.bat path: str + """ + VC_BASE = r'Software\%sMicrosoft\DevDiv\VCForPython\%0.1f' + key = VC_BASE % ('', version) + try: + # Per-user installs register the compiler path here + productdir = Reg.get_value(key, "installdir") + except KeyError: + try: + # All-user installs on a 64-bit system register here + key = VC_BASE % ('Wow6432Node\\', version) + productdir = Reg.get_value(key, "installdir") + except KeyError: + productdir = None + + if productdir: + vcvarsall = os.path.os.path.join(productdir, "vcvarsall.bat") + if os.path.isfile(vcvarsall): + return vcvarsall + + return get_unpatched(msvc9_find_vcvarsall)(version) + + +def msvc9_query_vcvarsall(ver, arch='x86', *args, **kwargs): + """ + Patched "distutils.msvc9compiler.query_vcvarsall" for support extra + compilers. + + Set environment without use of "vcvarsall.bat". + + Known supported compilers + ------------------------- + Microsoft Visual C++ 9.0: + Microsoft Visual C++ Compiler for Python 2.7 (x86, amd64) + Microsoft Windows SDK 6.1 (x86, x64, ia64) + Microsoft Windows SDK 7.0 (x86, x64, ia64) + + Microsoft Visual C++ 10.0: + Microsoft Windows SDK 7.1 (x86, x64, ia64) + + Parameters + ---------- + ver: float + Required Microsoft Visual C++ version. + arch: str + Target architecture. + + Return + ------ + environment: dict + """ + # Try to get environement from vcvarsall.bat (Classical way) + try: + orig = get_unpatched(msvc9_query_vcvarsall) + return orig(ver, arch, *args, **kwargs) + except distutils.errors.DistutilsPlatformError: + # Pass error if Vcvarsall.bat is missing + pass + except ValueError: + # Pass error if environment not set after executing vcvarsall.bat + pass + + # If error, try to set environment directly + try: + return EnvironmentInfo(arch, ver).return_env() + except distutils.errors.DistutilsPlatformError as exc: + _augment_exception(exc, ver, arch) + raise + + +def msvc14_get_vc_env(plat_spec): + """ + Patched "distutils._msvccompiler._get_vc_env" for support extra + compilers. + + Set environment without use of "vcvarsall.bat". + + Known supported compilers + ------------------------- + Microsoft Visual C++ 14.0: + Microsoft Visual C++ Build Tools 2015 (x86, x64, arm) + Microsoft Visual Studio 2017 (x86, x64, arm, arm64) + Microsoft Visual Studio Build Tools 2017 (x86, x64, arm, arm64) + + Parameters + ---------- + plat_spec: str + Target architecture. + + Return + ------ + environment: dict + """ + # Try to get environment from vcvarsall.bat (Classical way) + try: + return get_unpatched(msvc14_get_vc_env)(plat_spec) + except distutils.errors.DistutilsPlatformError: + # Pass error Vcvarsall.bat is missing + pass + + # If error, try to set environment directly + try: + return EnvironmentInfo(plat_spec, vc_min_ver=14.0).return_env() + except distutils.errors.DistutilsPlatformError as exc: + _augment_exception(exc, 14.0) + raise + + +def msvc14_gen_lib_options(*args, **kwargs): + """ + Patched "distutils._msvccompiler.gen_lib_options" for fix + compatibility between "numpy.distutils" and "distutils._msvccompiler" + (for Numpy < 1.11.2) + """ + if "numpy.distutils" in sys.modules: + import numpy as np + if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'): + return np.distutils.ccompiler.gen_lib_options(*args, **kwargs) + return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs) + + +def _augment_exception(exc, version, arch=''): + """ + Add details to the exception message to help guide the user + as to what action will resolve it. + """ + # Error if MSVC++ directory not found or environment not set + message = exc.args[0] + + if "vcvarsall" in message.lower() or "visual c" in message.lower(): + # Special error message if MSVC++ not installed + tmpl = 'Microsoft Visual C++ {version:0.1f} is required.' + message = tmpl.format(**locals()) + msdownload = 'www.microsoft.com/download/details.aspx?id=%d' + if version == 9.0: + if arch.lower().find('ia64') > -1: + # For VC++ 9.0, if IA64 support is needed, redirect user + # to Windows SDK 7.0 + message += ' Get it with "Microsoft Windows SDK 7.0": ' + message += msdownload % 3138 + else: + # For VC++ 9.0 redirect user to Vc++ for Python 2.7 : + # This redirection link is maintained by Microsoft. + # Contact vspython@microsoft.com if it needs updating. + message += ' Get it from http://aka.ms/vcpython27' + elif version == 10.0: + # For VC++ 10.0 Redirect user to Windows SDK 7.1 + message += ' Get it with "Microsoft Windows SDK 7.1": ' + message += msdownload % 8279 + elif version >= 14.0: + # For VC++ 14.0 Redirect user to Visual C++ Build Tools + message += (' Get it with "Microsoft Visual C++ Build Tools": ' + r'https://visualstudio.microsoft.com/downloads/') + + exc.args = (message, ) + + +class PlatformInfo: + """ + Current and Target Architectures informations. + + Parameters + ---------- + arch: str + Target architecture. + """ + current_cpu = safe_env.get('processor_architecture', '').lower() + + def __init__(self, arch): + self.arch = arch.lower().replace('x64', 'amd64') + + @property + def target_cpu(self): + return self.arch[self.arch.find('_') + 1:] + + def target_is_x86(self): + return self.target_cpu == 'x86' + + def current_is_x86(self): + return self.current_cpu == 'x86' + + def current_dir(self, hidex86=False, x64=False): + """ + Current platform specific subfolder. + + Parameters + ---------- + hidex86: bool + return '' and not '\x86' if architecture is x86. + x64: bool + return '\x64' and not '\amd64' if architecture is amd64. + + Return + ------ + subfolder: str + '\target', or '' (see hidex86 parameter) + """ + return ( + '' if (self.current_cpu == 'x86' and hidex86) else + r'\x64' if (self.current_cpu == 'amd64' and x64) else + r'\%s' % self.current_cpu + ) + + def target_dir(self, hidex86=False, x64=False): + r""" + Target platform specific subfolder. + + Parameters + ---------- + hidex86: bool + return '' and not '\x86' if architecture is x86. + x64: bool + return '\x64' and not '\amd64' if architecture is amd64. + + Return + ------ + subfolder: str + '\current', or '' (see hidex86 parameter) + """ + return ( + '' if (self.target_cpu == 'x86' and hidex86) else + r'\x64' if (self.target_cpu == 'amd64' and x64) else + r'\%s' % self.target_cpu + ) + + def cross_dir(self, forcex86=False): + r""" + Cross platform specific subfolder. + + Parameters + ---------- + forcex86: bool + Use 'x86' as current architecture even if current acritecture is + not x86. + + Return + ------ + subfolder: str + '' if target architecture is current architecture, + '\current_target' if not. + """ + current = 'x86' if forcex86 else self.current_cpu + return ( + '' if self.target_cpu == current else + self.target_dir().replace('\\', '\\%s_' % current) + ) + + +class RegistryInfo: + """ + Microsoft Visual Studio related registry informations. + + Parameters + ---------- + platform_info: PlatformInfo + "PlatformInfo" instance. + """ + HKEYS = (winreg.HKEY_USERS, + winreg.HKEY_CURRENT_USER, + winreg.HKEY_LOCAL_MACHINE, + winreg.HKEY_CLASSES_ROOT) + + def __init__(self, platform_info): + self.pi = platform_info + + @property + def visualstudio(self): + """ + Microsoft Visual Studio root registry key. + """ + return 'VisualStudio' + + @property + def sxs(self): + """ + Microsoft Visual Studio SxS registry key. + """ + return os.path.join(self.visualstudio, 'SxS') + + @property + def vc(self): + """ + Microsoft Visual C++ VC7 registry key. + """ + return os.path.join(self.sxs, 'VC7') + + @property + def vs(self): + """ + Microsoft Visual Studio VS7 registry key. + """ + return os.path.join(self.sxs, 'VS7') + + @property + def vc_for_python(self): + """ + Microsoft Visual C++ for Python registry key. + """ + return r'DevDiv\VCForPython' + + @property + def microsoft_sdk(self): + """ + Microsoft SDK registry key. + """ + return 'Microsoft SDKs' + + @property + def windows_sdk(self): + """ + Microsoft Windows/Platform SDK registry key. + """ + return os.path.join(self.microsoft_sdk, 'Windows') + + @property + def netfx_sdk(self): + """ + Microsoft .NET Framework SDK registry key. + """ + return os.path.join(self.microsoft_sdk, 'NETFXSDK') + + @property + def windows_kits_roots(self): + """ + Microsoft Windows Kits Roots registry key. + """ + return r'Windows Kits\Installed Roots' + + def microsoft(self, key, x86=False): + """ + Return key in Microsoft software registry. + + Parameters + ---------- + key: str + Registry key path where look. + x86: str + Force x86 software registry. + + Return + ------ + str: value + """ + node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node' + return os.path.join('Software', node64, 'Microsoft', key) + + def lookup(self, key, name): + """ + Look for values in registry in Microsoft software registry. + + Parameters + ---------- + key: str + Registry key path where look. + name: str + Value name to find. + + Return + ------ + str: value + """ + KEY_READ = winreg.KEY_READ + openkey = winreg.OpenKey + ms = self.microsoft + for hkey in self.HKEYS: + try: + bkey = openkey(hkey, ms(key), 0, KEY_READ) + except (OSError, IOError): + if not self.pi.current_is_x86(): + try: + bkey = openkey(hkey, ms(key, True), 0, KEY_READ) + except (OSError, IOError): + continue + else: + continue + try: + return winreg.QueryValueEx(bkey, name)[0] + except (OSError, IOError): + pass + + +class SystemInfo: + """ + Microsoft Windows and Visual Studio related system inormations. + + Parameters + ---------- + registry_info: RegistryInfo + "RegistryInfo" instance. + vc_ver: float + Required Microsoft Visual C++ version. + """ + + # Variables and properties in this class use originals CamelCase variables + # names from Microsoft source files for more easy comparaison. + WinDir = safe_env.get('WinDir', '') + ProgramFiles = safe_env.get('ProgramFiles', '') + ProgramFilesx86 = safe_env.get('ProgramFiles(x86)', ProgramFiles) + + def __init__(self, registry_info, vc_ver=None): + self.ri = registry_info + self.pi = self.ri.pi + self.vc_ver = vc_ver or self._find_latest_available_vc_ver() + + def _find_latest_available_vc_ver(self): + try: + return self.find_available_vc_vers()[-1] + except IndexError: + err = 'No Microsoft Visual C++ version found' + raise distutils.errors.DistutilsPlatformError(err) + + def find_available_vc_vers(self): + """ + Find all available Microsoft Visual C++ versions. + """ + ms = self.ri.microsoft + vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs) + vc_vers = [] + for hkey in self.ri.HKEYS: + for key in vckeys: + try: + bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ) + except (OSError, IOError): + continue + subkeys, values, _ = winreg.QueryInfoKey(bkey) + for i in range(values): + try: + ver = float(winreg.EnumValue(bkey, i)[0]) + if ver not in vc_vers: + vc_vers.append(ver) + except ValueError: + pass + for i in range(subkeys): + try: + ver = float(winreg.EnumKey(bkey, i)) + if ver not in vc_vers: + vc_vers.append(ver) + except ValueError: + pass + return sorted(vc_vers) + + @property + def VSInstallDir(self): + """ + Microsoft Visual Studio directory. + """ + # Default path + name = 'Microsoft Visual Studio %0.1f' % self.vc_ver + default = os.path.join(self.ProgramFilesx86, name) + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vs, '%0.1f' % self.vc_ver) or default + + @property + def VCInstallDir(self): + """ + Microsoft Visual C++ directory. + """ + self.VSInstallDir + + guess_vc = self._guess_vc() or self._guess_vc_legacy() + + # Try to get "VC++ for Python" path from registry as default path + reg_path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) + python_vc = self.ri.lookup(reg_path, 'installdir') + default_vc = os.path.join(python_vc, 'VC') if python_vc else guess_vc + + # Try to get path from registry, if fail use default path + path = self.ri.lookup(self.ri.vc, '%0.1f' % self.vc_ver) or default_vc + + if not os.path.isdir(path): + msg = 'Microsoft Visual C++ directory not found' + raise distutils.errors.DistutilsPlatformError(msg) + + return path + + def _guess_vc(self): + """ + Locate Visual C for 2017 + """ + if self.vc_ver <= 14.0: + return + + default = r'VC\Tools\MSVC' + guess_vc = os.path.join(self.VSInstallDir, default) + # Subdir with VC exact version as name + try: + vc_exact_ver = os.listdir(guess_vc)[-1] + return os.path.join(guess_vc, vc_exact_ver) + except (OSError, IOError, IndexError): + pass + + def _guess_vc_legacy(self): + """ + Locate Visual C for versions prior to 2017 + """ + default = r'Microsoft Visual Studio %0.1f\VC' % self.vc_ver + return os.path.join(self.ProgramFilesx86, default) + + @property + def WindowsSdkVersion(self): + """ + Microsoft Windows SDK versions for specified MSVC++ version. + """ + if self.vc_ver <= 9.0: + return ('7.0', '6.1', '6.0a') + elif self.vc_ver == 10.0: + return ('7.1', '7.0a') + elif self.vc_ver == 11.0: + return ('8.0', '8.0a') + elif self.vc_ver == 12.0: + return ('8.1', '8.1a') + elif self.vc_ver >= 14.0: + return ('10.0', '8.1') + + @property + def WindowsSdkLastVersion(self): + """ + Microsoft Windows SDK last version + """ + return self._use_last_dir_name(os.path.join( + self.WindowsSdkDir, 'lib')) + + @property + def WindowsSdkDir(self): + """ + Microsoft Windows SDK directory. + """ + sdkdir = '' + for ver in self.WindowsSdkVersion: + # Try to get it from registry + loc = os.path.join(self.ri.windows_sdk, 'v%s' % ver) + sdkdir = self.ri.lookup(loc, 'installationfolder') + if sdkdir: + break + if not sdkdir or not os.path.isdir(sdkdir): + # Try to get "VC++ for Python" version from registry + path = os.path.join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) + install_base = self.ri.lookup(path, 'installdir') + if install_base: + sdkdir = os.path.join(install_base, 'WinSDK') + if not sdkdir or not os.path.isdir(sdkdir): + # If fail, use default new path + for ver in self.WindowsSdkVersion: + intver = ver[:ver.rfind('.')] + path = r'Microsoft SDKs\Windows Kits\%s' % (intver) + d = os.path.join(self.ProgramFiles, path) + if os.path.isdir(d): + sdkdir = d + if not sdkdir or not os.path.isdir(sdkdir): + # If fail, use default old path + for ver in self.WindowsSdkVersion: + path = r'Microsoft SDKs\Windows\v%s' % ver + d = os.path.join(self.ProgramFiles, path) + if os.path.isdir(d): + sdkdir = d + if not sdkdir: + # If fail, use Platform SDK + sdkdir = os.path.join(self.VCInstallDir, 'PlatformSDK') + return sdkdir + + @property + def WindowsSDKExecutablePath(self): + """ + Microsoft Windows SDK executable directory. + """ + # Find WinSDK NetFx Tools registry dir name + if self.vc_ver <= 11.0: + netfxver = 35 + arch = '' + else: + netfxver = 40 + hidex86 = True if self.vc_ver <= 12.0 else False + arch = self.pi.current_dir(x64=True, hidex86=hidex86) + fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-')) + + # liste all possibles registry paths + regpaths = [] + if self.vc_ver >= 14.0: + for ver in self.NetFxSdkVersion: + regpaths += [os.path.join(self.ri.netfx_sdk, ver, fx)] + + for ver in self.WindowsSdkVersion: + regpaths += [os.path.join(self.ri.windows_sdk, 'v%sA' % ver, fx)] + + # Return installation folder from the more recent path + for path in regpaths: + execpath = self.ri.lookup(path, 'installationfolder') + if execpath: + break + return execpath + + @property + def FSharpInstallDir(self): + """ + Microsoft Visual F# directory. + """ + path = r'%0.1f\Setup\F#' % self.vc_ver + path = os.path.join(self.ri.visualstudio, path) + return self.ri.lookup(path, 'productdir') or '' + + @property + def UniversalCRTSdkDir(self): + """ + Microsoft Universal CRT SDK directory. + """ + # Set Kit Roots versions for specified MSVC++ version + if self.vc_ver >= 14.0: + vers = ('10', '81') + else: + vers = () + + # Find path of the more recent Kit + for ver in vers: + sdkdir = self.ri.lookup(self.ri.windows_kits_roots, + 'kitsroot%s' % ver) + if sdkdir: + break + return sdkdir or '' + + @property + def UniversalCRTSdkLastVersion(self): + """ + Microsoft Universal C Runtime SDK last version + """ + return self._use_last_dir_name(os.path.join( + self.UniversalCRTSdkDir, 'lib')) + + @property + def NetFxSdkVersion(self): + """ + Microsoft .NET Framework SDK versions. + """ + # Set FxSdk versions for specified MSVC++ version + if self.vc_ver >= 14.0: + return ('4.6.1', '4.6') + else: + return () + + @property + def NetFxSdkDir(self): + """ + Microsoft .NET Framework SDK directory. + """ + for ver in self.NetFxSdkVersion: + loc = os.path.join(self.ri.netfx_sdk, ver) + sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder') + if sdkdir: + break + return sdkdir or '' + + @property + def FrameworkDir32(self): + """ + Microsoft .NET Framework 32bit directory. + """ + # Default path + guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework') + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw + + @property + def FrameworkDir64(self): + """ + Microsoft .NET Framework 64bit directory. + """ + # Default path + guess_fw = os.path.join(self.WinDir, r'Microsoft.NET\Framework64') + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw + + @property + def FrameworkVersion32(self): + """ + Microsoft .NET Framework 32bit versions. + """ + return self._find_dot_net_versions(32) + + @property + def FrameworkVersion64(self): + """ + Microsoft .NET Framework 64bit versions. + """ + return self._find_dot_net_versions(64) + + def _find_dot_net_versions(self, bits): + """ + Find Microsoft .NET Framework versions. + + Parameters + ---------- + bits: int + Platform number of bits: 32 or 64. + """ + # Find actual .NET version in registry + reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) + dot_net_dir = getattr(self, 'FrameworkDir%d' % bits) + ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or '' + + # Set .NET versions for specified MSVC++ version + if self.vc_ver >= 12.0: + frameworkver = (ver, 'v4.0') + elif self.vc_ver >= 10.0: + frameworkver = ('v4.0.30319' if ver.lower()[:2] != 'v4' else ver, + 'v3.5') + elif self.vc_ver == 9.0: + frameworkver = ('v3.5', 'v2.0.50727') + if self.vc_ver == 8.0: + frameworkver = ('v3.0', 'v2.0.50727') + return frameworkver + + def _use_last_dir_name(self, path, prefix=''): + """ + Return name of the last dir in path or '' if no dir found. + + Parameters + ---------- + path: str + Use dirs in this path + prefix: str + Use only dirs startings by this prefix + """ + matching_dirs = ( + dir_name + for dir_name in reversed(os.listdir(path)) + if os.path.isdir(os.path.join(path, dir_name)) and + dir_name.startswith(prefix) + ) + return next(matching_dirs, None) or '' + + +class EnvironmentInfo: + """ + Return environment variables for specified Microsoft Visual C++ version + and platform : Lib, Include, Path and libpath. + + This function is compatible with Microsoft Visual C++ 9.0 to 14.0. + + Script created by analysing Microsoft environment configuration files like + "vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ... + + Parameters + ---------- + arch: str + Target architecture. + vc_ver: float + Required Microsoft Visual C++ version. If not set, autodetect the last + version. + vc_min_ver: float + Minimum Microsoft Visual C++ version. + """ + + # Variables and properties in this class use originals CamelCase variables + # names from Microsoft source files for more easy comparaison. + + def __init__(self, arch, vc_ver=None, vc_min_ver=0): + self.pi = PlatformInfo(arch) + self.ri = RegistryInfo(self.pi) + self.si = SystemInfo(self.ri, vc_ver) + + if self.vc_ver < vc_min_ver: + err = 'No suitable Microsoft Visual C++ version found' + raise distutils.errors.DistutilsPlatformError(err) + + @property + def vc_ver(self): + """ + Microsoft Visual C++ version. + """ + return self.si.vc_ver + + @property + def VSTools(self): + """ + Microsoft Visual Studio Tools + """ + paths = [r'Common7\IDE', r'Common7\Tools'] + + if self.vc_ver >= 14.0: + arch_subdir = self.pi.current_dir(hidex86=True, x64=True) + paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow'] + paths += [r'Team Tools\Performance Tools'] + paths += [r'Team Tools\Performance Tools%s' % arch_subdir] + + return [os.path.join(self.si.VSInstallDir, path) for path in paths] + + @property + def VCIncludes(self): + """ + Microsoft Visual C++ & Microsoft Foundation Class Includes + """ + return [os.path.join(self.si.VCInstallDir, 'Include'), + os.path.join(self.si.VCInstallDir, r'ATLMFC\Include')] + + @property + def VCLibraries(self): + """ + Microsoft Visual C++ & Microsoft Foundation Class Libraries + """ + if self.vc_ver >= 15.0: + arch_subdir = self.pi.target_dir(x64=True) + else: + arch_subdir = self.pi.target_dir(hidex86=True) + paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir] + + if self.vc_ver >= 14.0: + paths += [r'Lib\store%s' % arch_subdir] + + return [os.path.join(self.si.VCInstallDir, path) for path in paths] + + @property + def VCStoreRefs(self): + """ + Microsoft Visual C++ store references Libraries + """ + if self.vc_ver < 14.0: + return [] + return [os.path.join(self.si.VCInstallDir, r'Lib\store\references')] + + @property + def VCTools(self): + """ + Microsoft Visual C++ Tools + """ + si = self.si + tools = [os.path.join(si.VCInstallDir, 'VCPackages')] + + forcex86 = True if self.vc_ver <= 10.0 else False + arch_subdir = self.pi.cross_dir(forcex86) + if arch_subdir: + tools += [os.path.join(si.VCInstallDir, 'Bin%s' % arch_subdir)] + + if self.vc_ver == 14.0: + path = 'Bin%s' % self.pi.current_dir(hidex86=True) + tools += [os.path.join(si.VCInstallDir, path)] + + elif self.vc_ver >= 15.0: + host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else + r'bin\HostX64%s') + tools += [os.path.join( + si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))] + + if self.pi.current_cpu != self.pi.target_cpu: + tools += [os.path.join( + si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))] + + else: + tools += [os.path.join(si.VCInstallDir, 'Bin')] + + return tools + + @property + def OSLibraries(self): + """ + Microsoft Windows SDK Libraries + """ + if self.vc_ver <= 10.0: + arch_subdir = self.pi.target_dir(hidex86=True, x64=True) + return [os.path.join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)] + + else: + arch_subdir = self.pi.target_dir(x64=True) + lib = os.path.join(self.si.WindowsSdkDir, 'lib') + libver = self._sdk_subdir + return [os.path.join(lib, '%sum%s' % (libver , arch_subdir))] + + @property + def OSIncludes(self): + """ + Microsoft Windows SDK Include + """ + include = os.path.join(self.si.WindowsSdkDir, 'include') + + if self.vc_ver <= 10.0: + return [include, os.path.join(include, 'gl')] + + else: + if self.vc_ver >= 14.0: + sdkver = self._sdk_subdir + else: + sdkver = '' + return [os.path.join(include, '%sshared' % sdkver), + os.path.join(include, '%sum' % sdkver), + os.path.join(include, '%swinrt' % sdkver)] + + @property + def OSLibpath(self): + """ + Microsoft Windows SDK Libraries Paths + """ + ref = os.path.join(self.si.WindowsSdkDir, 'References') + libpath = [] + + if self.vc_ver <= 9.0: + libpath += self.OSLibraries + + if self.vc_ver >= 11.0: + libpath += [os.path.join(ref, r'CommonConfiguration\Neutral')] + + if self.vc_ver >= 14.0: + libpath += [ + ref, + os.path.join(self.si.WindowsSdkDir, 'UnionMetadata'), + os.path.join( + ref, + 'Windows.Foundation.UniversalApiContract', + '1.0.0.0', + ), + os.path.join( + ref, + 'Windows.Foundation.FoundationContract', + '1.0.0.0', + ), + os.path.join( + ref, + 'Windows.Networking.Connectivity.WwanContract', + '1.0.0.0', + ), + os.path.join( + self.si.WindowsSdkDir, + 'ExtensionSDKs', + 'Microsoft.VCLibs', + '%0.1f' % self.vc_ver, + 'References', + 'CommonConfiguration', + 'neutral', + ), + ] + return libpath + + @property + def SdkTools(self): + """ + Microsoft Windows SDK Tools + """ + return list(self._sdk_tools()) + + def _sdk_tools(self): + """ + Microsoft Windows SDK Tools paths generator + """ + if self.vc_ver < 15.0: + bin_dir = 'Bin' if self.vc_ver <= 11.0 else r'Bin\x86' + yield os.path.join(self.si.WindowsSdkDir, bin_dir) + + if not self.pi.current_is_x86(): + arch_subdir = self.pi.current_dir(x64=True) + path = 'Bin%s' % arch_subdir + yield os.path.join(self.si.WindowsSdkDir, path) + + if self.vc_ver == 10.0 or self.vc_ver == 11.0: + if self.pi.target_is_x86(): + arch_subdir = '' + else: + arch_subdir = self.pi.current_dir(hidex86=True, x64=True) + path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir + yield os.path.join(self.si.WindowsSdkDir, path) + + elif self.vc_ver >= 15.0: + path = os.path.join(self.si.WindowsSdkDir, 'Bin') + arch_subdir = self.pi.current_dir(x64=True) + sdkver = self.si.WindowsSdkLastVersion + yield os.path.join(path, '%s%s' % (sdkver, arch_subdir)) + + if self.si.WindowsSDKExecutablePath: + yield self.si.WindowsSDKExecutablePath + + @property + def _sdk_subdir(self): + """ + Microsoft Windows SDK version subdir + """ + ucrtver = self.si.WindowsSdkLastVersion + return ('%s\\' % ucrtver) if ucrtver else '' + + @property + def SdkSetup(self): + """ + Microsoft Windows SDK Setup + """ + if self.vc_ver > 9.0: + return [] + + return [os.path.join(self.si.WindowsSdkDir, 'Setup')] + + @property + def FxTools(self): + """ + Microsoft .NET Framework Tools + """ + pi = self.pi + si = self.si + + if self.vc_ver <= 10.0: + include32 = True + include64 = not pi.target_is_x86() and not pi.current_is_x86() + else: + include32 = pi.target_is_x86() or pi.current_is_x86() + include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64' + + tools = [] + if include32: + tools += [os.path.join(si.FrameworkDir32, ver) + for ver in si.FrameworkVersion32] + if include64: + tools += [os.path.join(si.FrameworkDir64, ver) + for ver in si.FrameworkVersion64] + return tools + + @property + def NetFxSDKLibraries(self): + """ + Microsoft .Net Framework SDK Libraries + """ + if self.vc_ver < 14.0 or not self.si.NetFxSdkDir: + return [] + + arch_subdir = self.pi.target_dir(x64=True) + return [os.path.join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)] + + @property + def NetFxSDKIncludes(self): + """ + Microsoft .Net Framework SDK Includes + """ + if self.vc_ver < 14.0 or not self.si.NetFxSdkDir: + return [] + + return [os.path.join(self.si.NetFxSdkDir, r'include\um')] + + @property + def VsTDb(self): + """ + Microsoft Visual Studio Team System Database + """ + return [os.path.join(self.si.VSInstallDir, r'VSTSDB\Deploy')] + + @property + def MSBuild(self): + """ + Microsoft Build Engine + """ + if self.vc_ver < 12.0: + return [] + elif self.vc_ver < 15.0: + base_path = self.si.ProgramFilesx86 + arch_subdir = self.pi.current_dir(hidex86=True) + else: + base_path = self.si.VSInstallDir + arch_subdir = '' + + path = r'MSBuild\%0.1f\bin%s' % (self.vc_ver, arch_subdir) + build = [os.path.join(base_path, path)] + + if self.vc_ver >= 15.0: + # Add Roslyn C# & Visual Basic Compiler + build += [os.path.join(base_path, path, 'Roslyn')] + + return build + + @property + def HTMLHelpWorkshop(self): + """ + Microsoft HTML Help Workshop + """ + if self.vc_ver < 11.0: + return [] + + return [os.path.join(self.si.ProgramFilesx86, 'HTML Help Workshop')] + + @property + def UCRTLibraries(self): + """ + Microsoft Universal C Runtime SDK Libraries + """ + if self.vc_ver < 14.0: + return [] + + arch_subdir = self.pi.target_dir(x64=True) + lib = os.path.join(self.si.UniversalCRTSdkDir, 'lib') + ucrtver = self._ucrt_subdir + return [os.path.join(lib, '%sucrt%s' % (ucrtver, arch_subdir))] + + @property + def UCRTIncludes(self): + """ + Microsoft Universal C Runtime SDK Include + """ + if self.vc_ver < 14.0: + return [] + + include = os.path.join(self.si.UniversalCRTSdkDir, 'include') + return [os.path.join(include, '%sucrt' % self._ucrt_subdir)] + + @property + def _ucrt_subdir(self): + """ + Microsoft Universal C Runtime SDK version subdir + """ + ucrtver = self.si.UniversalCRTSdkLastVersion + return ('%s\\' % ucrtver) if ucrtver else '' + + @property + def FSharp(self): + """ + Microsoft Visual F# + """ + if self.vc_ver < 11.0 and self.vc_ver > 12.0: + return [] + + return self.si.FSharpInstallDir + + @property + def VCRuntimeRedist(self): + """ + Microsoft Visual C++ runtime redistribuable dll + """ + arch_subdir = self.pi.target_dir(x64=True) + if self.vc_ver < 15: + redist_path = self.si.VCInstallDir + vcruntime = 'redist%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll' + else: + redist_path = self.si.VCInstallDir.replace('\\Tools', '\\Redist') + vcruntime = 'onecore%s\\Microsoft.VC%d0.CRT\\vcruntime%d0.dll' + + # Visual Studio 2017 is still Visual C++ 14.0 + dll_ver = 14.0 if self.vc_ver == 15 else self.vc_ver + + vcruntime = vcruntime % (arch_subdir, self.vc_ver, dll_ver) + return os.path.join(redist_path, vcruntime) + + def return_env(self, exists=True): + """ + Return environment dict. + + Parameters + ---------- + exists: bool + It True, only return existing paths. + """ + env = dict( + include=self._build_paths('include', + [self.VCIncludes, + self.OSIncludes, + self.UCRTIncludes, + self.NetFxSDKIncludes], + exists), + lib=self._build_paths('lib', + [self.VCLibraries, + self.OSLibraries, + self.FxTools, + self.UCRTLibraries, + self.NetFxSDKLibraries], + exists), + libpath=self._build_paths('libpath', + [self.VCLibraries, + self.FxTools, + self.VCStoreRefs, + self.OSLibpath], + exists), + path=self._build_paths('path', + [self.VCTools, + self.VSTools, + self.VsTDb, + self.SdkTools, + self.SdkSetup, + self.FxTools, + self.MSBuild, + self.HTMLHelpWorkshop, + self.FSharp], + exists), + ) + if self.vc_ver >= 14 and os.path.isfile(self.VCRuntimeRedist): + env['py_vcruntime_redist'] = self.VCRuntimeRedist + return env + + def _build_paths(self, name, spec_path_lists, exists): + """ + Given an environment variable name and specified paths, + return a pathsep-separated string of paths containing + unique, extant, directories from those paths and from + the environment variable. Raise an error if no paths + are resolved. + """ + # flatten spec_path_lists + spec_paths = itertools.chain.from_iterable(spec_path_lists) + env_paths = safe_env.get(name, '').split(os.pathsep) + paths = itertools.chain(spec_paths, env_paths) + extant_paths = list(filter(os.path.isdir, paths)) if exists else paths + if not extant_paths: + msg = "%s environment variable is empty" % name.upper() + raise distutils.errors.DistutilsPlatformError(msg) + unique_paths = self._unique_everseen(extant_paths) + return os.pathsep.join(unique_paths) + + # from Python docs + def _unique_everseen(self, iterable, key=None): + """ + List unique elements, preserving order. + Remember all elements ever seen. + + _unique_everseen('AAAABBBCCDAABBB') --> A B C D + + _unique_everseen('ABBCcAD', str.lower) --> A B C D + """ + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element diff --git a/winvenv/Lib/site-packages/setuptools/namespaces.py b/winvenv/Lib/site-packages/setuptools/namespaces.py new file mode 100644 index 0000000..dc16106 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/namespaces.py @@ -0,0 +1,107 @@ +import os +from distutils import log +import itertools + +from setuptools.extern.six.moves import map + + +flatten = itertools.chain.from_iterable + + +class Installer: + + nspkg_ext = '-nspkg.pth' + + def install_namespaces(self): + nsp = self._get_all_ns_packages() + if not nsp: + return + filename, ext = os.path.splitext(self._get_target()) + filename += self.nspkg_ext + self.outputs.append(filename) + log.info("Installing %s", filename) + lines = map(self._gen_nspkg_line, nsp) + + if self.dry_run: + # always generate the lines, even in dry run + list(lines) + return + + with open(filename, 'wt') as f: + f.writelines(lines) + + def uninstall_namespaces(self): + filename, ext = os.path.splitext(self._get_target()) + filename += self.nspkg_ext + if not os.path.exists(filename): + return + log.info("Removing %s", filename) + os.remove(filename) + + def _get_target(self): + return self.target + + _nspkg_tmpl = ( + "import sys, types, os", + "has_mfs = sys.version_info > (3, 5)", + "p = os.path.join(%(root)s, *%(pth)r)", + "importlib = has_mfs and __import__('importlib.util')", + "has_mfs and __import__('importlib.machinery')", + "m = has_mfs and " + "sys.modules.setdefault(%(pkg)r, " + "importlib.util.module_from_spec(" + "importlib.machinery.PathFinder.find_spec(%(pkg)r, " + "[os.path.dirname(p)])))", + "m = m or " + "sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))", + "mp = (m or []) and m.__dict__.setdefault('__path__',[])", + "(p not in mp) and mp.append(p)", + ) + "lines for the namespace installer" + + _nspkg_tmpl_multi = ( + 'm and setattr(sys.modules[%(parent)r], %(child)r, m)', + ) + "additional line(s) when a parent package is indicated" + + def _get_root(self): + return "sys._getframe(1).f_locals['sitedir']" + + def _gen_nspkg_line(self, pkg): + # ensure pkg is not a unicode string under Python 2.7 + pkg = str(pkg) + pth = tuple(pkg.split('.')) + root = self._get_root() + tmpl_lines = self._nspkg_tmpl + parent, sep, child = pkg.rpartition('.') + if parent: + tmpl_lines += self._nspkg_tmpl_multi + return ';'.join(tmpl_lines) % locals() + '\n' + + def _get_all_ns_packages(self): + """Return sorted list of all package namespaces""" + pkgs = self.distribution.namespace_packages or [] + return sorted(flatten(map(self._pkg_names, pkgs))) + + @staticmethod + def _pkg_names(pkg): + """ + Given a namespace package, yield the components of that + package. + + >>> names = Installer._pkg_names('a.b.c') + >>> set(names) == set(['a', 'a.b', 'a.b.c']) + True + """ + parts = pkg.split('.') + while parts: + yield '.'.join(parts) + parts.pop() + + +class DevelopInstaller(Installer): + def _get_root(self): + return repr(str(self.egg_path)) + + def _get_target(self): + return self.egg_link diff --git a/winvenv/Lib/site-packages/setuptools/package_index.py b/winvenv/Lib/site-packages/setuptools/package_index.py new file mode 100644 index 0000000..1608b91 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/package_index.py @@ -0,0 +1,1128 @@ +"""PyPI and direct package downloading""" +import sys +import os +import re +import shutil +import socket +import base64 +import hashlib +import itertools +import warnings +from functools import wraps + +from setuptools.extern import six +from setuptools.extern.six.moves import urllib, http_client, configparser, map + +import setuptools +from pkg_resources import ( + CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST, + Environment, find_distributions, safe_name, safe_version, + to_filename, Requirement, DEVELOP_DIST, EGG_DIST, +) +from setuptools import ssl_support +from distutils import log +from distutils.errors import DistutilsError +from fnmatch import translate +from setuptools.py27compat import get_all_headers +from setuptools.py33compat import unescape +from setuptools.wheel import Wheel + +__metaclass__ = type + +EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$') +HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) +PYPI_MD5 = re.compile( + r'<a href="([^"#]+)">([^<]+)</a>\n\s+\(<a (?:title="MD5 hash"\n\s+)' + r'href="[^?]+\?:action=show_md5&digest=([0-9a-f]{32})">md5</a>\)' +) +URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match +EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() + +__all__ = [ + 'PackageIndex', 'distros_for_url', 'parse_bdist_wininst', + 'interpret_distro_name', +] + +_SOCKET_TIMEOUT = 15 + +_tmpl = "setuptools/{setuptools.__version__} Python-urllib/{py_major}" +user_agent = _tmpl.format(py_major=sys.version[:3], setuptools=setuptools) + + +def parse_requirement_arg(spec): + try: + return Requirement.parse(spec) + except ValueError: + raise DistutilsError( + "Not a URL, existing file, or requirement spec: %r" % (spec,) + ) + + +def parse_bdist_wininst(name): + """Return (base,pyversion) or (None,None) for possible .exe name""" + + lower = name.lower() + base, py_ver, plat = None, None, None + + if lower.endswith('.exe'): + if lower.endswith('.win32.exe'): + base = name[:-10] + plat = 'win32' + elif lower.startswith('.win32-py', -16): + py_ver = name[-7:-4] + base = name[:-16] + plat = 'win32' + elif lower.endswith('.win-amd64.exe'): + base = name[:-14] + plat = 'win-amd64' + elif lower.startswith('.win-amd64-py', -20): + py_ver = name[-7:-4] + base = name[:-20] + plat = 'win-amd64' + return base, py_ver, plat + + +def egg_info_for_url(url): + parts = urllib.parse.urlparse(url) + scheme, server, path, parameters, query, fragment = parts + base = urllib.parse.unquote(path.split('/')[-1]) + if server == 'sourceforge.net' and base == 'download': # XXX Yuck + base = urllib.parse.unquote(path.split('/')[-2]) + if '#' in base: + base, fragment = base.split('#', 1) + return base, fragment + + +def distros_for_url(url, metadata=None): + """Yield egg or source distribution objects that might be found at a URL""" + base, fragment = egg_info_for_url(url) + for dist in distros_for_location(url, base, metadata): + yield dist + if fragment: + match = EGG_FRAGMENT.match(fragment) + if match: + for dist in interpret_distro_name( + url, match.group(1), metadata, precedence=CHECKOUT_DIST + ): + yield dist + + +def distros_for_location(location, basename, metadata=None): + """Yield egg or source distribution objects based on basename""" + if basename.endswith('.egg.zip'): + basename = basename[:-4] # strip the .zip + if basename.endswith('.egg') and '-' in basename: + # only one, unambiguous interpretation + return [Distribution.from_location(location, basename, metadata)] + if basename.endswith('.whl') and '-' in basename: + wheel = Wheel(basename) + if not wheel.is_compatible(): + return [] + return [Distribution( + location=location, + project_name=wheel.project_name, + version=wheel.version, + # Increase priority over eggs. + precedence=EGG_DIST + 1, + )] + if basename.endswith('.exe'): + win_base, py_ver, platform = parse_bdist_wininst(basename) + if win_base is not None: + return interpret_distro_name( + location, win_base, metadata, py_ver, BINARY_DIST, platform + ) + # Try source distro extensions (.zip, .tgz, etc.) + # + for ext in EXTENSIONS: + if basename.endswith(ext): + basename = basename[:-len(ext)] + return interpret_distro_name(location, basename, metadata) + return [] # no extension matched + + +def distros_for_filename(filename, metadata=None): + """Yield possible egg or source distribution objects based on a filename""" + return distros_for_location( + normalize_path(filename), os.path.basename(filename), metadata + ) + + +def interpret_distro_name( + location, basename, metadata, py_version=None, precedence=SOURCE_DIST, + platform=None +): + """Generate alternative interpretations of a source distro name + + Note: if `location` is a filesystem filename, you should call + ``pkg_resources.normalize_path()`` on it before passing it to this + routine! + """ + # Generate alternative interpretations of a source distro name + # Because some packages are ambiguous as to name/versions split + # e.g. "adns-python-1.1.0", "egenix-mx-commercial", etc. + # So, we generate each possible interepretation (e.g. "adns, python-1.1.0" + # "adns-python, 1.1.0", and "adns-python-1.1.0, no version"). In practice, + # the spurious interpretations should be ignored, because in the event + # there's also an "adns" package, the spurious "python-1.1.0" version will + # compare lower than any numeric version number, and is therefore unlikely + # to match a request for it. It's still a potential problem, though, and + # in the long run PyPI and the distutils should go for "safe" names and + # versions in distribution archive names (sdist and bdist). + + parts = basename.split('-') + if not py_version and any(re.match(r'py\d\.\d$', p) for p in parts[2:]): + # it is a bdist_dumb, not an sdist -- bail out + return + + for p in range(1, len(parts) + 1): + yield Distribution( + location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), + py_version=py_version, precedence=precedence, + platform=platform + ) + + +# From Python 2.7 docs +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in six.moves.filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +def unique_values(func): + """ + Wrap a function returning an iterable such that the resulting iterable + only ever yields unique items. + """ + + @wraps(func) + def wrapper(*args, **kwargs): + return unique_everseen(func(*args, **kwargs)) + + return wrapper + + +REL = re.compile(r"""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) +# this line is here to fix emacs' cruddy broken syntax highlighting + + +@unique_values +def find_external_links(url, page): + """Find rel="homepage" and rel="download" links in `page`, yielding URLs""" + + for match in REL.finditer(page): + tag, rel = match.groups() + rels = set(map(str.strip, rel.lower().split(','))) + if 'homepage' in rels or 'download' in rels: + for match in HREF.finditer(tag): + yield urllib.parse.urljoin(url, htmldecode(match.group(1))) + + for tag in ("<th>Home Page", "<th>Download URL"): + pos = page.find(tag) + if pos != -1: + match = HREF.search(page, pos) + if match: + yield urllib.parse.urljoin(url, htmldecode(match.group(1))) + + +class ContentChecker: + """ + A null content checker that defines the interface for checking content + """ + + def feed(self, block): + """ + Feed a block of data to the hash. + """ + return + + def is_valid(self): + """ + Check the hash. Return False if validation fails. + """ + return True + + def report(self, reporter, template): + """ + Call reporter with information about the checker (hash name) + substituted into the template. + """ + return + + +class HashChecker(ContentChecker): + pattern = re.compile( + r'(?P<hash_name>sha1|sha224|sha384|sha256|sha512|md5)=' + r'(?P<expected>[a-f0-9]+)' + ) + + def __init__(self, hash_name, expected): + self.hash_name = hash_name + self.hash = hashlib.new(hash_name) + self.expected = expected + + @classmethod + def from_url(cls, url): + "Construct a (possibly null) ContentChecker from a URL" + fragment = urllib.parse.urlparse(url)[-1] + if not fragment: + return ContentChecker() + match = cls.pattern.search(fragment) + if not match: + return ContentChecker() + return cls(**match.groupdict()) + + def feed(self, block): + self.hash.update(block) + + def is_valid(self): + return self.hash.hexdigest() == self.expected + + def report(self, reporter, template): + msg = template % self.hash_name + return reporter(msg) + + +class PackageIndex(Environment): + """A distribution index that scans web pages for download URLs""" + + def __init__( + self, index_url="https://pypi.org/simple/", hosts=('*',), + ca_bundle=None, verify_ssl=True, *args, **kw + ): + Environment.__init__(self, *args, **kw) + self.index_url = index_url + "/" [:not index_url.endswith('/')] + self.scanned_urls = {} + self.fetched_urls = {} + self.package_pages = {} + self.allows = re.compile('|'.join(map(translate, hosts))).match + self.to_scan = [] + use_ssl = ( + verify_ssl + and ssl_support.is_available + and (ca_bundle or ssl_support.find_ca_bundle()) + ) + if use_ssl: + self.opener = ssl_support.opener_for(ca_bundle) + else: + self.opener = urllib.request.urlopen + + def process_url(self, url, retrieve=False): + """Evaluate a URL as a possible download, and maybe retrieve it""" + if url in self.scanned_urls and not retrieve: + return + self.scanned_urls[url] = True + if not URL_SCHEME(url): + self.process_filename(url) + return + else: + dists = list(distros_for_url(url)) + if dists: + if not self.url_ok(url): + return + self.debug("Found link: %s", url) + + if dists or not retrieve or url in self.fetched_urls: + list(map(self.add, dists)) + return # don't need the actual page + + if not self.url_ok(url): + self.fetched_urls[url] = True + return + + self.info("Reading %s", url) + self.fetched_urls[url] = True # prevent multiple fetch attempts + tmpl = "Download error on %s: %%s -- Some packages may not be found!" + f = self.open_url(url, tmpl % url) + if f is None: + return + self.fetched_urls[f.url] = True + if 'html' not in f.headers.get('content-type', '').lower(): + f.close() # not html, we can't process it + return + + base = f.url # handle redirects + page = f.read() + if not isinstance(page, str): + # In Python 3 and got bytes but want str. + if isinstance(f, urllib.error.HTTPError): + # Errors have no charset, assume latin1: + charset = 'latin-1' + else: + charset = f.headers.get_param('charset') or 'latin-1' + page = page.decode(charset, "ignore") + f.close() + for match in HREF.finditer(page): + link = urllib.parse.urljoin(base, htmldecode(match.group(1))) + self.process_url(link) + if url.startswith(self.index_url) and getattr(f, 'code', None) != 404: + page = self.process_index(url, page) + + def process_filename(self, fn, nested=False): + # process filenames or directories + if not os.path.exists(fn): + self.warn("Not found: %s", fn) + return + + if os.path.isdir(fn) and not nested: + path = os.path.realpath(fn) + for item in os.listdir(path): + self.process_filename(os.path.join(path, item), True) + + dists = distros_for_filename(fn) + if dists: + self.debug("Found: %s", fn) + list(map(self.add, dists)) + + def url_ok(self, url, fatal=False): + s = URL_SCHEME(url) + is_file = s and s.group(1).lower() == 'file' + if is_file or self.allows(urllib.parse.urlparse(url)[1]): + return True + msg = ( + "\nNote: Bypassing %s (disallowed host; see " + "http://bit.ly/2hrImnY for details).\n") + if fatal: + raise DistutilsError(msg % url) + else: + self.warn(msg, url) + + def scan_egg_links(self, search_path): + dirs = filter(os.path.isdir, search_path) + egg_links = ( + (path, entry) + for path in dirs + for entry in os.listdir(path) + if entry.endswith('.egg-link') + ) + list(itertools.starmap(self.scan_egg_link, egg_links)) + + def scan_egg_link(self, path, entry): + with open(os.path.join(path, entry)) as raw_lines: + # filter non-empty lines + lines = list(filter(None, map(str.strip, raw_lines))) + + if len(lines) != 2: + # format is not recognized; punt + return + + egg_path, setup_path = lines + + for dist in find_distributions(os.path.join(path, egg_path)): + dist.location = os.path.join(path, *lines) + dist.precedence = SOURCE_DIST + self.add(dist) + + def process_index(self, url, page): + """Process the contents of a PyPI page""" + + def scan(link): + # Process a URL to see if it's for a package page + if link.startswith(self.index_url): + parts = list(map( + urllib.parse.unquote, link[len(self.index_url):].split('/') + )) + if len(parts) == 2 and '#' not in parts[1]: + # it's a package page, sanitize and index it + pkg = safe_name(parts[0]) + ver = safe_version(parts[1]) + self.package_pages.setdefault(pkg.lower(), {})[link] = True + return to_filename(pkg), to_filename(ver) + return None, None + + # process an index page into the package-page index + for match in HREF.finditer(page): + try: + scan(urllib.parse.urljoin(url, htmldecode(match.group(1)))) + except ValueError: + pass + + pkg, ver = scan(url) # ensure this page is in the page index + if pkg: + # process individual package page + for new_url in find_external_links(url, page): + # Process the found URL + base, frag = egg_info_for_url(new_url) + if base.endswith('.py') and not frag: + if ver: + new_url += '#egg=%s-%s' % (pkg, ver) + else: + self.need_version_info(url) + self.scan_url(new_url) + + return PYPI_MD5.sub( + lambda m: '<a href="%s#md5=%s">%s</a>' % m.group(1, 3, 2), page + ) + else: + return "" # no sense double-scanning non-package pages + + def need_version_info(self, url): + self.scan_all( + "Page at %s links to .py file(s) without version info; an index " + "scan is required.", url + ) + + def scan_all(self, msg=None, *args): + if self.index_url not in self.fetched_urls: + if msg: + self.warn(msg, *args) + self.info( + "Scanning index of all packages (this may take a while)" + ) + self.scan_url(self.index_url) + + def find_packages(self, requirement): + self.scan_url(self.index_url + requirement.unsafe_name + '/') + + if not self.package_pages.get(requirement.key): + # Fall back to safe version of the name + self.scan_url(self.index_url + requirement.project_name + '/') + + if not self.package_pages.get(requirement.key): + # We couldn't find the target package, so search the index page too + self.not_found_in_index(requirement) + + for url in list(self.package_pages.get(requirement.key, ())): + # scan each page that might be related to the desired package + self.scan_url(url) + + def obtain(self, requirement, installer=None): + self.prescan() + self.find_packages(requirement) + for dist in self[requirement.key]: + if dist in requirement: + return dist + self.debug("%s does not match %s", requirement, dist) + return super(PackageIndex, self).obtain(requirement, installer) + + def check_hash(self, checker, filename, tfp): + """ + checker is a ContentChecker + """ + checker.report( + self.debug, + "Validating %%s checksum for %s" % filename) + if not checker.is_valid(): + tfp.close() + os.unlink(filename) + raise DistutilsError( + "%s validation failed for %s; " + "possible download problem?" + % (checker.hash.name, os.path.basename(filename)) + ) + + def add_find_links(self, urls): + """Add `urls` to the list that will be prescanned for searches""" + for url in urls: + if ( + self.to_scan is None # if we have already "gone online" + or not URL_SCHEME(url) # or it's a local file/directory + or url.startswith('file:') + or list(distros_for_url(url)) # or a direct package link + ): + # then go ahead and process it now + self.scan_url(url) + else: + # otherwise, defer retrieval till later + self.to_scan.append(url) + + def prescan(self): + """Scan urls scheduled for prescanning (e.g. --find-links)""" + if self.to_scan: + list(map(self.scan_url, self.to_scan)) + self.to_scan = None # from now on, go ahead and process immediately + + def not_found_in_index(self, requirement): + if self[requirement.key]: # we've seen at least one distro + meth, msg = self.info, "Couldn't retrieve index page for %r" + else: # no distros seen for this name, might be misspelled + meth, msg = ( + self.warn, + "Couldn't find index page for %r (maybe misspelled?)") + meth(msg, requirement.unsafe_name) + self.scan_all() + + def download(self, spec, tmpdir): + """Locate and/or download `spec` to `tmpdir`, returning a local path + + `spec` may be a ``Requirement`` object, or a string containing a URL, + an existing local filename, or a project/version requirement spec + (i.e. the string form of a ``Requirement`` object). If it is the URL + of a .py file with an unambiguous ``#egg=name-version`` tag (i.e., one + that escapes ``-`` as ``_`` throughout), a trivial ``setup.py`` is + automatically created alongside the downloaded file. + + If `spec` is a ``Requirement`` object or a string containing a + project/version requirement spec, this method returns the location of + a matching distribution (possibly after downloading it to `tmpdir`). + If `spec` is a locally existing file or directory name, it is simply + returned unchanged. If `spec` is a URL, it is downloaded to a subpath + of `tmpdir`, and the local filename is returned. Various errors may be + raised if a problem occurs during downloading. + """ + if not isinstance(spec, Requirement): + scheme = URL_SCHEME(spec) + if scheme: + # It's a url, download it to tmpdir + found = self._download_url(scheme.group(1), spec, tmpdir) + base, fragment = egg_info_for_url(spec) + if base.endswith('.py'): + found = self.gen_setup(found, fragment, tmpdir) + return found + elif os.path.exists(spec): + # Existing file or directory, just return it + return spec + else: + spec = parse_requirement_arg(spec) + return getattr(self.fetch_distribution(spec, tmpdir), 'location', None) + + def fetch_distribution( + self, requirement, tmpdir, force_scan=False, source=False, + develop_ok=False, local_index=None): + """Obtain a distribution suitable for fulfilling `requirement` + + `requirement` must be a ``pkg_resources.Requirement`` instance. + If necessary, or if the `force_scan` flag is set, the requirement is + searched for in the (online) package index as well as the locally + installed packages. If a distribution matching `requirement` is found, + the returned distribution's ``location`` is the value you would have + gotten from calling the ``download()`` method with the matching + distribution's URL or filename. If no matching distribution is found, + ``None`` is returned. + + If the `source` flag is set, only source distributions and source + checkout links will be considered. Unless the `develop_ok` flag is + set, development and system eggs (i.e., those using the ``.egg-info`` + format) will be ignored. + """ + # process a Requirement + self.info("Searching for %s", requirement) + skipped = {} + dist = None + + def find(req, env=None): + if env is None: + env = self + # Find a matching distribution; may be called more than once + + for dist in env[req.key]: + + if dist.precedence == DEVELOP_DIST and not develop_ok: + if dist not in skipped: + self.warn( + "Skipping development or system egg: %s", dist, + ) + skipped[dist] = 1 + continue + + test = ( + dist in req + and (dist.precedence <= SOURCE_DIST or not source) + ) + if test: + loc = self.download(dist.location, tmpdir) + dist.download_location = loc + if os.path.exists(dist.download_location): + return dist + + if force_scan: + self.prescan() + self.find_packages(requirement) + dist = find(requirement) + + if not dist and local_index is not None: + dist = find(requirement, local_index) + + if dist is None: + if self.to_scan is not None: + self.prescan() + dist = find(requirement) + + if dist is None and not force_scan: + self.find_packages(requirement) + dist = find(requirement) + + if dist is None: + self.warn( + "No local packages or working download links found for %s%s", + (source and "a source distribution of " or ""), + requirement, + ) + else: + self.info("Best match: %s", dist) + return dist.clone(location=dist.download_location) + + def fetch(self, requirement, tmpdir, force_scan=False, source=False): + """Obtain a file suitable for fulfilling `requirement` + + DEPRECATED; use the ``fetch_distribution()`` method now instead. For + backward compatibility, this routine is identical but returns the + ``location`` of the downloaded distribution instead of a distribution + object. + """ + dist = self.fetch_distribution(requirement, tmpdir, force_scan, source) + if dist is not None: + return dist.location + return None + + def gen_setup(self, filename, fragment, tmpdir): + match = EGG_FRAGMENT.match(fragment) + dists = match and [ + d for d in + interpret_distro_name(filename, match.group(1), None) if d.version + ] or [] + + if len(dists) == 1: # unambiguous ``#egg`` fragment + basename = os.path.basename(filename) + + # Make sure the file has been downloaded to the temp dir. + if os.path.dirname(filename) != tmpdir: + dst = os.path.join(tmpdir, basename) + from setuptools.command.easy_install import samefile + if not samefile(filename, dst): + shutil.copy2(filename, dst) + filename = dst + + with open(os.path.join(tmpdir, 'setup.py'), 'w') as file: + file.write( + "from setuptools import setup\n" + "setup(name=%r, version=%r, py_modules=[%r])\n" + % ( + dists[0].project_name, dists[0].version, + os.path.splitext(basename)[0] + ) + ) + return filename + + elif match: + raise DistutilsError( + "Can't unambiguously interpret project/version identifier %r; " + "any dashes in the name or version should be escaped using " + "underscores. %r" % (fragment, dists) + ) + else: + raise DistutilsError( + "Can't process plain .py files without an '#egg=name-version'" + " suffix to enable automatic setup script generation." + ) + + dl_blocksize = 8192 + + def _download_to(self, url, filename): + self.info("Downloading %s", url) + # Download the file + fp = None + try: + checker = HashChecker.from_url(url) + fp = self.open_url(url) + if isinstance(fp, urllib.error.HTTPError): + raise DistutilsError( + "Can't download %s: %s %s" % (url, fp.code, fp.msg) + ) + headers = fp.info() + blocknum = 0 + bs = self.dl_blocksize + size = -1 + if "content-length" in headers: + # Some servers return multiple Content-Length headers :( + sizes = get_all_headers(headers, 'Content-Length') + size = max(map(int, sizes)) + self.reporthook(url, filename, blocknum, bs, size) + with open(filename, 'wb') as tfp: + while True: + block = fp.read(bs) + if block: + checker.feed(block) + tfp.write(block) + blocknum += 1 + self.reporthook(url, filename, blocknum, bs, size) + else: + break + self.check_hash(checker, filename, tfp) + return headers + finally: + if fp: + fp.close() + + def reporthook(self, url, filename, blocknum, blksize, size): + pass # no-op + + def open_url(self, url, warning=None): + if url.startswith('file:'): + return local_open(url) + try: + return open_with_auth(url, self.opener) + except (ValueError, http_client.InvalidURL) as v: + msg = ' '.join([str(arg) for arg in v.args]) + if warning: + self.warn(warning, msg) + else: + raise DistutilsError('%s %s' % (url, msg)) + except urllib.error.HTTPError as v: + return v + except urllib.error.URLError as v: + if warning: + self.warn(warning, v.reason) + else: + raise DistutilsError("Download error for %s: %s" + % (url, v.reason)) + except http_client.BadStatusLine as v: + if warning: + self.warn(warning, v.line) + else: + raise DistutilsError( + '%s returned a bad status line. The server might be ' + 'down, %s' % + (url, v.line) + ) + except (http_client.HTTPException, socket.error) as v: + if warning: + self.warn(warning, v) + else: + raise DistutilsError("Download error for %s: %s" + % (url, v)) + + def _download_url(self, scheme, url, tmpdir): + # Determine download filename + # + name, fragment = egg_info_for_url(url) + if name: + while '..' in name: + name = name.replace('..', '.').replace('\\', '_') + else: + name = "__downloaded__" # default if URL has no path contents + + if name.endswith('.egg.zip'): + name = name[:-4] # strip the extra .zip before download + + filename = os.path.join(tmpdir, name) + + # Download the file + # + if scheme == 'svn' or scheme.startswith('svn+'): + return self._download_svn(url, filename) + elif scheme == 'git' or scheme.startswith('git+'): + return self._download_git(url, filename) + elif scheme.startswith('hg+'): + return self._download_hg(url, filename) + elif scheme == 'file': + return urllib.request.url2pathname(urllib.parse.urlparse(url)[2]) + else: + self.url_ok(url, True) # raises error if not allowed + return self._attempt_download(url, filename) + + def scan_url(self, url): + self.process_url(url, True) + + def _attempt_download(self, url, filename): + headers = self._download_to(url, filename) + if 'html' in headers.get('content-type', '').lower(): + return self._download_html(url, headers, filename) + else: + return filename + + def _download_html(self, url, headers, filename): + file = open(filename) + for line in file: + if line.strip(): + # Check for a subversion index page + if re.search(r'<title>([^- ]+ - )?Revision \d+:', line): + # it's a subversion index page: + file.close() + os.unlink(filename) + return self._download_svn(url, filename) + break # not an index page + file.close() + os.unlink(filename) + raise DistutilsError("Unexpected HTML page found at " + url) + + def _download_svn(self, url, filename): + warnings.warn("SVN download support is deprecated", UserWarning) + url = url.split('#', 1)[0] # remove any fragment for svn's sake + creds = '' + if url.lower().startswith('svn:') and '@' in url: + scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) + if not netloc and path.startswith('//') and '/' in path[2:]: + netloc, path = path[2:].split('/', 1) + auth, host = urllib.parse.splituser(netloc) + if auth: + if ':' in auth: + user, pw = auth.split(':', 1) + creds = " --username=%s --password=%s" % (user, pw) + else: + creds = " --username=" + auth + netloc = host + parts = scheme, netloc, url, p, q, f + url = urllib.parse.urlunparse(parts) + self.info("Doing subversion checkout from %s to %s", url, filename) + os.system("svn checkout%s -q %s %s" % (creds, url, filename)) + return filename + + @staticmethod + def _vcs_split_rev_from_url(url, pop_prefix=False): + scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) + + scheme = scheme.split('+', 1)[-1] + + # Some fragment identification fails + path = path.split('#', 1)[0] + + rev = None + if '@' in path: + path, rev = path.rsplit('@', 1) + + # Also, discard fragment + url = urllib.parse.urlunsplit((scheme, netloc, path, query, '')) + + return url, rev + + def _download_git(self, url, filename): + filename = filename.split('#', 1)[0] + url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) + + self.info("Doing git clone from %s to %s", url, filename) + os.system("git clone --quiet %s %s" % (url, filename)) + + if rev is not None: + self.info("Checking out %s", rev) + os.system("(cd %s && git checkout --quiet %s)" % ( + filename, + rev, + )) + + return filename + + def _download_hg(self, url, filename): + filename = filename.split('#', 1)[0] + url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) + + self.info("Doing hg clone from %s to %s", url, filename) + os.system("hg clone --quiet %s %s" % (url, filename)) + + if rev is not None: + self.info("Updating to %s", rev) + os.system("(cd %s && hg up -C -r %s -q)" % ( + filename, + rev, + )) + + return filename + + def debug(self, msg, *args): + log.debug(msg, *args) + + def info(self, msg, *args): + log.info(msg, *args) + + def warn(self, msg, *args): + log.warn(msg, *args) + + +# This pattern matches a character entity reference (a decimal numeric +# references, a hexadecimal numeric reference, or a named reference). +entity_sub = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub + + +def decode_entity(match): + what = match.group(0) + return unescape(what) + + +def htmldecode(text): + """ + Decode HTML entities in the given text. + + >>> htmldecode( + ... 'https://../package_name-0.1.2.tar.gz' + ... '?tokena=A&tokenb=B">package_name-0.1.2.tar.gz') + 'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz' + """ + return entity_sub(decode_entity, text) + + +def socket_timeout(timeout=15): + def _socket_timeout(func): + def _socket_timeout(*args, **kwargs): + old_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(timeout) + try: + return func(*args, **kwargs) + finally: + socket.setdefaulttimeout(old_timeout) + + return _socket_timeout + + return _socket_timeout + + +def _encode_auth(auth): + """ + A function compatible with Python 2.3-3.3 that will encode + auth from a URL suitable for an HTTP header. + >>> str(_encode_auth('username%3Apassword')) + 'dXNlcm5hbWU6cGFzc3dvcmQ=' + + Long auth strings should not cause a newline to be inserted. + >>> long_auth = 'username:' + 'password'*10 + >>> chr(10) in str(_encode_auth(long_auth)) + False + """ + auth_s = urllib.parse.unquote(auth) + # convert to bytes + auth_bytes = auth_s.encode() + encoded_bytes = base64.b64encode(auth_bytes) + # convert back to a string + encoded = encoded_bytes.decode() + # strip the trailing carriage return + return encoded.replace('\n', '') + + +class Credential: + """ + A username/password pair. Use like a namedtuple. + """ + + def __init__(self, username, password): + self.username = username + self.password = password + + def __iter__(self): + yield self.username + yield self.password + + def __str__(self): + return '%(username)s:%(password)s' % vars(self) + + +class PyPIConfig(configparser.RawConfigParser): + def __init__(self): + """ + Load from ~/.pypirc + """ + defaults = dict.fromkeys(['username', 'password', 'repository'], '') + configparser.RawConfigParser.__init__(self, defaults) + + rc = os.path.join(os.path.expanduser('~'), '.pypirc') + if os.path.exists(rc): + self.read(rc) + + @property + def creds_by_repository(self): + sections_with_repositories = [ + section for section in self.sections() + if self.get(section, 'repository').strip() + ] + + return dict(map(self._get_repo_cred, sections_with_repositories)) + + def _get_repo_cred(self, section): + repo = self.get(section, 'repository').strip() + return repo, Credential( + self.get(section, 'username').strip(), + self.get(section, 'password').strip(), + ) + + def find_credential(self, url): + """ + If the URL indicated appears to be a repository defined in this + config, return the credential for that repository. + """ + for repository, cred in self.creds_by_repository.items(): + if url.startswith(repository): + return cred + + +def open_with_auth(url, opener=urllib.request.urlopen): + """Open a urllib2 request, handling HTTP authentication""" + + scheme, netloc, path, params, query, frag = urllib.parse.urlparse(url) + + # Double scheme does not raise on Mac OS X as revealed by a + # failing test. We would expect "nonnumeric port". Refs #20. + if netloc.endswith(':'): + raise http_client.InvalidURL("nonnumeric port: ''") + + if scheme in ('http', 'https'): + auth, host = urllib.parse.splituser(netloc) + else: + auth = None + + if not auth: + cred = PyPIConfig().find_credential(url) + if cred: + auth = str(cred) + info = cred.username, url + log.info('Authenticating as %s for %s (from .pypirc)', *info) + + if auth: + auth = "Basic " + _encode_auth(auth) + parts = scheme, host, path, params, query, frag + new_url = urllib.parse.urlunparse(parts) + request = urllib.request.Request(new_url) + request.add_header("Authorization", auth) + else: + request = urllib.request.Request(url) + + request.add_header('User-Agent', user_agent) + fp = opener(request) + + if auth: + # Put authentication info back into request URL if same host, + # so that links found on the page will work + s2, h2, path2, param2, query2, frag2 = urllib.parse.urlparse(fp.url) + if s2 == scheme and h2 == host: + parts = s2, netloc, path2, param2, query2, frag2 + fp.url = urllib.parse.urlunparse(parts) + + return fp + + +# adding a timeout to avoid freezing package_index +open_with_auth = socket_timeout(_SOCKET_TIMEOUT)(open_with_auth) + + +def fix_sf_url(url): + return url # backward compatibility + + +def local_open(url): + """Read a local path, with special support for directories""" + scheme, server, path, param, query, frag = urllib.parse.urlparse(url) + filename = urllib.request.url2pathname(path) + if os.path.isfile(filename): + return urllib.request.urlopen(url) + elif path.endswith('/') and os.path.isdir(filename): + files = [] + for f in os.listdir(filename): + filepath = os.path.join(filename, f) + if f == 'index.html': + with open(filepath, 'r') as fp: + body = fp.read() + break + elif os.path.isdir(filepath): + f += '/' + files.append('<a href="{name}">{name}</a>'.format(name=f)) + else: + tmpl = ( + "<html><head><title>{url}" + "{files}") + body = tmpl.format(url=url, files='\n'.join(files)) + status, message = 200, "OK" + else: + status, message, body = 404, "Path not found", "Not found" + + headers = {'content-type': 'text/html'} + body_stream = six.StringIO(body) + return urllib.error.HTTPError(url, status, message, headers, body_stream) diff --git a/winvenv/Lib/site-packages/setuptools/pep425tags.py b/winvenv/Lib/site-packages/setuptools/pep425tags.py new file mode 100644 index 0000000..8bf4277 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/pep425tags.py @@ -0,0 +1,319 @@ +# This file originally from pip: +# https://github.com/pypa/pip/blob/8f4f15a5a95d7d5b511ceaee9ed261176c181970/src/pip/_internal/pep425tags.py +"""Generate and work with PEP 425 Compatibility Tags.""" +from __future__ import absolute_import + +import distutils.util +from distutils import log +import platform +import re +import sys +import sysconfig +import warnings +from collections import OrderedDict + +from .extern import six + +from . import glibc + +_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)') + + +def get_config_var(var): + try: + return sysconfig.get_config_var(var) + except IOError as e: # Issue #1074 + warnings.warn("{}".format(e), RuntimeWarning) + return None + + +def get_abbr_impl(): + """Return abbreviated implementation name.""" + if hasattr(sys, 'pypy_version_info'): + pyimpl = 'pp' + elif sys.platform.startswith('java'): + pyimpl = 'jy' + elif sys.platform == 'cli': + pyimpl = 'ip' + else: + pyimpl = 'cp' + return pyimpl + + +def get_impl_ver(): + """Return implementation version.""" + impl_ver = get_config_var("py_version_nodot") + if not impl_ver or get_abbr_impl() == 'pp': + impl_ver = ''.join(map(str, get_impl_version_info())) + return impl_ver + + +def get_impl_version_info(): + """Return sys.version_info-like tuple for use in decrementing the minor + version.""" + if get_abbr_impl() == 'pp': + # as per https://github.com/pypa/pip/issues/2882 + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return sys.version_info[0], sys.version_info[1] + + +def get_impl_tag(): + """ + Returns the Tag for this specific implementation. + """ + return "{}{}".format(get_abbr_impl(), get_impl_ver()) + + +def get_flag(var, fallback, expected=True, warn=True): + """Use a fallback method for determining SOABI flags if the needed config + var is unset or unavailable.""" + val = get_config_var(var) + if val is None: + if warn: + log.debug("Config variable '%s' is unset, Python ABI tag may " + "be incorrect", var) + return fallback() + return val == expected + + +def get_abi_tag(): + """Return the ABI tag based on SOABI (if available) or emulate SOABI + (CPython 2, PyPy).""" + soabi = get_config_var('SOABI') + impl = get_abbr_impl() + if not soabi and impl in {'cp', 'pp'} and hasattr(sys, 'maxunicode'): + d = '' + m = '' + u = '' + if get_flag('Py_DEBUG', + lambda: hasattr(sys, 'gettotalrefcount'), + warn=(impl == 'cp')): + d = 'd' + if get_flag('WITH_PYMALLOC', + lambda: impl == 'cp', + warn=(impl == 'cp')): + m = 'm' + if get_flag('Py_UNICODE_SIZE', + lambda: sys.maxunicode == 0x10ffff, + expected=4, + warn=(impl == 'cp' and + six.PY2)) \ + and six.PY2: + u = 'u' + abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) + elif soabi and soabi.startswith('cpython-'): + abi = 'cp' + soabi.split('-')[1] + elif soabi: + abi = soabi.replace('.', '_').replace('-', '_') + else: + abi = None + return abi + + +def _is_running_32bit(): + return sys.maxsize == 2147483647 + + +def get_platform(): + """Return our platform name 'win32', 'linux_x86_64'""" + if sys.platform == 'darwin': + # distutils.util.get_platform() returns the release based on the value + # of MACOSX_DEPLOYMENT_TARGET on which Python was built, which may + # be significantly older than the user's current machine. + release, _, machine = platform.mac_ver() + split_ver = release.split('.') + + if machine == "x86_64" and _is_running_32bit(): + machine = "i386" + elif machine == "ppc64" and _is_running_32bit(): + machine = "ppc" + + return 'macosx_{}_{}_{}'.format(split_ver[0], split_ver[1], machine) + + # XXX remove distutils dependency + result = distutils.util.get_platform().replace('.', '_').replace('-', '_') + if result == "linux_x86_64" and _is_running_32bit(): + # 32 bit Python program (running on a 64 bit Linux): pip should only + # install and run 32 bit compiled extensions in that case. + result = "linux_i686" + + return result + + +def is_manylinux1_compatible(): + # Only Linux, and only x86-64 / i686 + if get_platform() not in {"linux_x86_64", "linux_i686"}: + return False + + # Check for presence of _manylinux module + try: + import _manylinux + return bool(_manylinux.manylinux1_compatible) + except (ImportError, AttributeError): + # Fall through to heuristic check below + pass + + # Check glibc version. CentOS 5 uses glibc 2.5. + return glibc.have_compatible_glibc(2, 5) + + +def get_darwin_arches(major, minor, machine): + """Return a list of supported arches (including group arches) for + the given major, minor and machine architecture of an macOS machine. + """ + arches = [] + + def _supports_arch(major, minor, arch): + # Looking at the application support for macOS versions in the chart + # provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears + # our timeline looks roughly like: + # + # 10.0 - Introduces ppc support. + # 10.4 - Introduces ppc64, i386, and x86_64 support, however the ppc64 + # and x86_64 support is CLI only, and cannot be used for GUI + # applications. + # 10.5 - Extends ppc64 and x86_64 support to cover GUI applications. + # 10.6 - Drops support for ppc64 + # 10.7 - Drops support for ppc + # + # Given that we do not know if we're installing a CLI or a GUI + # application, we must be conservative and assume it might be a GUI + # application and behave as if ppc64 and x86_64 support did not occur + # until 10.5. + # + # Note: The above information is taken from the "Application support" + # column in the chart not the "Processor support" since I believe + # that we care about what instruction sets an application can use + # not which processors the OS supports. + if arch == 'ppc': + return (major, minor) <= (10, 5) + if arch == 'ppc64': + return (major, minor) == (10, 5) + if arch == 'i386': + return (major, minor) >= (10, 4) + if arch == 'x86_64': + return (major, minor) >= (10, 5) + if arch in groups: + for garch in groups[arch]: + if _supports_arch(major, minor, garch): + return True + return False + + groups = OrderedDict([ + ("fat", ("i386", "ppc")), + ("intel", ("x86_64", "i386")), + ("fat64", ("x86_64", "ppc64")), + ("fat32", ("x86_64", "i386", "ppc")), + ]) + + if _supports_arch(major, minor, machine): + arches.append(machine) + + for garch in groups: + if machine in groups[garch] and _supports_arch(major, minor, garch): + arches.append(garch) + + arches.append('universal') + + return arches + + +def get_supported(versions=None, noarch=False, platform=None, + impl=None, abi=None): + """Return a list of supported tags for each version specified in + `versions`. + + :param versions: a list of string versions, of the form ["33", "32"], + or None. The first version will be assumed to support our ABI. + :param platform: specify the exact platform you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abi: specify the exact abi you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported = [] + + # Versions must be given with respect to the preference + if versions is None: + versions = [] + version_info = get_impl_version_info() + major = version_info[:-1] + # Support all previous minor Python versions. + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = impl or get_abbr_impl() + + abis = [] + + abi = abi or get_abi_tag() + if abi: + abis[0:0] = [abi] + + abi3s = set() + import imp + for suffix in imp.get_suffixes(): + if suffix[0].startswith('.abi'): + abi3s.add(suffix[0].split('.', 2)[1]) + + abis.extend(sorted(list(abi3s))) + + abis.append('none') + + if not noarch: + arch = platform or get_platform() + if arch.startswith('macosx'): + # support macosx-10.6-intel on macosx-10.9-x86_64 + match = _osx_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + tpl = '{}_{}_%i_%s'.format(name, major) + arches = [] + for m in reversed(range(int(minor) + 1)): + for a in get_darwin_arches(int(major), m, actual_arch): + arches.append(tpl % (m, a)) + else: + # arch pattern didn't match (?!) + arches = [arch] + elif platform is None and is_manylinux1_compatible(): + arches = [arch.replace('linux', 'manylinux1'), arch] + else: + arches = [arch] + + # Current version, current API (built specifically for our Python): + for abi in abis: + for arch in arches: + supported.append(('%s%s' % (impl, versions[0]), abi, arch)) + + # abi3 modules compatible with older version of Python + for version in versions[1:]: + # abi3 was introduced in Python 3.2 + if version in {'31', '30'}: + break + for abi in abi3s: # empty set if not Python 3 + for arch in arches: + supported.append(("%s%s" % (impl, version), abi, arch)) + + # Has binaries, does not use the Python API: + for arch in arches: + supported.append(('py%s' % (versions[0][0]), 'none', arch)) + + # No abi / arch, but requires our implementation: + supported.append(('%s%s' % (impl, versions[0]), 'none', 'any')) + # Tagged specifically as being cross-version compatible + # (with just the major version specified) + supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + # No abi / arch, generic Python + for i, version in enumerate(versions): + supported.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + supported.append(('py%s' % (version[0]), 'none', 'any')) + + return supported + + +implementation_tag = get_impl_tag() diff --git a/winvenv/Lib/site-packages/setuptools/py27compat.py b/winvenv/Lib/site-packages/setuptools/py27compat.py new file mode 100644 index 0000000..2985011 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/py27compat.py @@ -0,0 +1,28 @@ +""" +Compatibility Support for Python 2.7 and earlier +""" + +import platform + +from setuptools.extern import six + + +def get_all_headers(message, key): + """ + Given an HTTPMessage, return all headers matching a given key. + """ + return message.get_all(key) + + +if six.PY2: + def get_all_headers(message, key): + return message.getheaders(key) + + +linux_py2_ascii = ( + platform.system() == 'Linux' and + six.PY2 +) + +rmtree_safe = str if linux_py2_ascii else lambda x: x +"""Workaround for http://bugs.python.org/issue24672""" diff --git a/winvenv/Lib/site-packages/setuptools/py31compat.py b/winvenv/Lib/site-packages/setuptools/py31compat.py new file mode 100644 index 0000000..1a0705e --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/py31compat.py @@ -0,0 +1,32 @@ +__all__ = [] + +__metaclass__ = type + + +try: + # Python >=3.2 + from tempfile import TemporaryDirectory +except ImportError: + import shutil + import tempfile + + class TemporaryDirectory: + """ + Very simple temporary directory context manager. + Will try to delete afterward, but will also ignore OS and similar + errors on deletion. + """ + + def __init__(self): + self.name = None # Handle mkdtemp raising an exception + self.name = tempfile.mkdtemp() + + def __enter__(self): + return self.name + + def __exit__(self, exctype, excvalue, exctrace): + try: + shutil.rmtree(self.name, True) + except OSError: # removal errors are not the only possible + pass + self.name = None diff --git a/winvenv/Lib/site-packages/setuptools/py33compat.py b/winvenv/Lib/site-packages/setuptools/py33compat.py new file mode 100644 index 0000000..87cf539 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/py33compat.py @@ -0,0 +1,55 @@ +import dis +import array +import collections + +try: + import html +except ImportError: + html = None + +from setuptools.extern import six +from setuptools.extern.six.moves import html_parser + +__metaclass__ = type + +OpArg = collections.namedtuple('OpArg', 'opcode arg') + + +class Bytecode_compat: + def __init__(self, code): + self.code = code + + def __iter__(self): + """Yield '(op,arg)' pair for each operation in code object 'code'""" + + bytes = array.array('b', self.code.co_code) + eof = len(self.code.co_code) + + ptr = 0 + extended_arg = 0 + + while ptr < eof: + + op = bytes[ptr] + + if op >= dis.HAVE_ARGUMENT: + + arg = bytes[ptr + 1] + bytes[ptr + 2] * 256 + extended_arg + ptr += 3 + + if op == dis.EXTENDED_ARG: + long_type = six.integer_types[-1] + extended_arg = arg * long_type(65536) + continue + + else: + arg = None + ptr += 1 + + yield OpArg(op, arg) + + +Bytecode = getattr(dis, 'Bytecode', Bytecode_compat) + + +unescape = getattr(html, 'unescape', html_parser.HTMLParser().unescape) diff --git a/winvenv/Lib/site-packages/setuptools/py36compat.py b/winvenv/Lib/site-packages/setuptools/py36compat.py new file mode 100644 index 0000000..f527969 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/py36compat.py @@ -0,0 +1,82 @@ +import sys +from distutils.errors import DistutilsOptionError +from distutils.util import strtobool +from distutils.debug import DEBUG + + +class Distribution_parse_config_files: + """ + Mix-in providing forward-compatibility for functionality to be + included by default on Python 3.7. + + Do not edit the code in this class except to update functionality + as implemented in distutils. + """ + def parse_config_files(self, filenames=None): + from configparser import ConfigParser + + # Ignore install directory options if we have a venv + if sys.prefix != sys.base_prefix: + ignore_options = [ + 'install-base', 'install-platbase', 'install-lib', + 'install-platlib', 'install-purelib', 'install-headers', + 'install-scripts', 'install-data', 'prefix', 'exec-prefix', + 'home', 'user', 'root'] + else: + ignore_options = [] + + ignore_options = frozenset(ignore_options) + + if filenames is None: + filenames = self.find_config_files() + + if DEBUG: + self.announce("Distribution.parse_config_files():") + + parser = ConfigParser(interpolation=None) + for filename in filenames: + if DEBUG: + self.announce(" reading %s" % filename) + parser.read(filename) + for section in parser.sections(): + options = parser.options(section) + opt_dict = self.get_option_dict(section) + + for opt in options: + if opt != '__name__' and opt not in ignore_options: + val = parser.get(section,opt) + opt = opt.replace('-', '_') + opt_dict[opt] = (filename, val) + + # Make the ConfigParser forget everything (so we retain + # the original filenames that options come from) + parser.__init__() + + # If there was a "global" section in the config file, use it + # to set Distribution options. + + if 'global' in self.command_options: + for (opt, (src, val)) in self.command_options['global'].items(): + alias = self.negative_opt.get(opt) + try: + if alias: + setattr(self, alias, not strtobool(val)) + elif opt in ('verbose', 'dry_run'): # ugh! + setattr(self, opt, strtobool(val)) + else: + setattr(self, opt, val) + except ValueError as msg: + raise DistutilsOptionError(msg) + + +if sys.version_info < (3,): + # Python 2 behavior is sufficient + class Distribution_parse_config_files: + pass + + +if False: + # When updated behavior is available upstream, + # disable override here. + class Distribution_parse_config_files: + pass diff --git a/winvenv/Lib/site-packages/setuptools/sandbox.py b/winvenv/Lib/site-packages/setuptools/sandbox.py new file mode 100644 index 0000000..685f3f7 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/sandbox.py @@ -0,0 +1,491 @@ +import os +import sys +import tempfile +import operator +import functools +import itertools +import re +import contextlib +import pickle +import textwrap + +from setuptools.extern import six +from setuptools.extern.six.moves import builtins, map + +import pkg_resources.py31compat + +if sys.platform.startswith('java'): + import org.python.modules.posix.PosixModule as _os +else: + _os = sys.modules[os.name] +try: + _file = file +except NameError: + _file = None +_open = open +from distutils.errors import DistutilsError +from pkg_resources import working_set + + +__all__ = [ + "AbstractSandbox", "DirectorySandbox", "SandboxViolation", "run_setup", +] + + +def _execfile(filename, globals, locals=None): + """ + Python 3 implementation of execfile. + """ + mode = 'rb' + with open(filename, mode) as stream: + script = stream.read() + if locals is None: + locals = globals + code = compile(script, filename, 'exec') + exec(code, globals, locals) + + +@contextlib.contextmanager +def save_argv(repl=None): + saved = sys.argv[:] + if repl is not None: + sys.argv[:] = repl + try: + yield saved + finally: + sys.argv[:] = saved + + +@contextlib.contextmanager +def save_path(): + saved = sys.path[:] + try: + yield saved + finally: + sys.path[:] = saved + + +@contextlib.contextmanager +def override_temp(replacement): + """ + Monkey-patch tempfile.tempdir with replacement, ensuring it exists + """ + pkg_resources.py31compat.makedirs(replacement, exist_ok=True) + + saved = tempfile.tempdir + + tempfile.tempdir = replacement + + try: + yield + finally: + tempfile.tempdir = saved + + +@contextlib.contextmanager +def pushd(target): + saved = os.getcwd() + os.chdir(target) + try: + yield saved + finally: + os.chdir(saved) + + +class UnpickleableException(Exception): + """ + An exception representing another Exception that could not be pickled. + """ + + @staticmethod + def dump(type, exc): + """ + Always return a dumped (pickled) type and exc. If exc can't be pickled, + wrap it in UnpickleableException first. + """ + try: + return pickle.dumps(type), pickle.dumps(exc) + except Exception: + # get UnpickleableException inside the sandbox + from setuptools.sandbox import UnpickleableException as cls + return cls.dump(cls, cls(repr(exc))) + + +class ExceptionSaver: + """ + A Context Manager that will save an exception, serialized, and restore it + later. + """ + + def __enter__(self): + return self + + def __exit__(self, type, exc, tb): + if not exc: + return + + # dump the exception + self._saved = UnpickleableException.dump(type, exc) + self._tb = tb + + # suppress the exception + return True + + def resume(self): + "restore and re-raise any exception" + + if '_saved' not in vars(self): + return + + type, exc = map(pickle.loads, self._saved) + six.reraise(type, exc, self._tb) + + +@contextlib.contextmanager +def save_modules(): + """ + Context in which imported modules are saved. + + Translates exceptions internal to the context into the equivalent exception + outside the context. + """ + saved = sys.modules.copy() + with ExceptionSaver() as saved_exc: + yield saved + + sys.modules.update(saved) + # remove any modules imported since + del_modules = ( + mod_name for mod_name in sys.modules + if mod_name not in saved + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ) + _clear_modules(del_modules) + + saved_exc.resume() + + +def _clear_modules(module_names): + for mod_name in list(module_names): + del sys.modules[mod_name] + + +@contextlib.contextmanager +def save_pkg_resources_state(): + saved = pkg_resources.__getstate__() + try: + yield saved + finally: + pkg_resources.__setstate__(saved) + + +@contextlib.contextmanager +def setup_context(setup_dir): + temp_dir = os.path.join(setup_dir, 'temp') + with save_pkg_resources_state(): + with save_modules(): + hide_setuptools() + with save_path(): + with save_argv(): + with override_temp(temp_dir): + with pushd(setup_dir): + # ensure setuptools commands are available + __import__('setuptools') + yield + + +def _needs_hiding(mod_name): + """ + >>> _needs_hiding('setuptools') + True + >>> _needs_hiding('pkg_resources') + True + >>> _needs_hiding('setuptools_plugin') + False + >>> _needs_hiding('setuptools.__init__') + True + >>> _needs_hiding('distutils') + True + >>> _needs_hiding('os') + False + >>> _needs_hiding('Cython') + True + """ + pattern = re.compile(r'(setuptools|pkg_resources|distutils|Cython)(\.|$)') + return bool(pattern.match(mod_name)) + + +def hide_setuptools(): + """ + Remove references to setuptools' modules from sys.modules to allow the + invocation to import the most appropriate setuptools. This technique is + necessary to avoid issues such as #315 where setuptools upgrading itself + would fail to find a function declared in the metadata. + """ + modules = filter(_needs_hiding, sys.modules) + _clear_modules(modules) + + +def run_setup(setup_script, args): + """Run a distutils setup script, sandboxed in its directory""" + setup_dir = os.path.abspath(os.path.dirname(setup_script)) + with setup_context(setup_dir): + try: + sys.argv[:] = [setup_script] + list(args) + sys.path.insert(0, setup_dir) + # reset to include setup dir, w/clean callback list + working_set.__init__() + working_set.callbacks.append(lambda dist: dist.activate()) + + # __file__ should be a byte string on Python 2 (#712) + dunder_file = ( + setup_script + if isinstance(setup_script, str) else + setup_script.encode(sys.getfilesystemencoding()) + ) + + with DirectorySandbox(setup_dir): + ns = dict(__file__=dunder_file, __name__='__main__') + _execfile(setup_script, ns) + except SystemExit as v: + if v.args and v.args[0]: + raise + # Normal exit, just return + + +class AbstractSandbox: + """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" + + _active = False + + def __init__(self): + self._attrs = [ + name for name in dir(_os) + if not name.startswith('_') and hasattr(self, name) + ] + + def _copy(self, source): + for name in self._attrs: + setattr(os, name, getattr(source, name)) + + def __enter__(self): + self._copy(self) + if _file: + builtins.file = self._file + builtins.open = self._open + self._active = True + + def __exit__(self, exc_type, exc_value, traceback): + self._active = False + if _file: + builtins.file = _file + builtins.open = _open + self._copy(_os) + + def run(self, func): + """Run 'func' under os sandboxing""" + with self: + return func() + + def _mk_dual_path_wrapper(name): + original = getattr(_os, name) + + def wrap(self, src, dst, *args, **kw): + if self._active: + src, dst = self._remap_pair(name, src, dst, *args, **kw) + return original(src, dst, *args, **kw) + + return wrap + + for name in ["rename", "link", "symlink"]: + if hasattr(_os, name): + locals()[name] = _mk_dual_path_wrapper(name) + + def _mk_single_path_wrapper(name, original=None): + original = original or getattr(_os, name) + + def wrap(self, path, *args, **kw): + if self._active: + path = self._remap_input(name, path, *args, **kw) + return original(path, *args, **kw) + + return wrap + + if _file: + _file = _mk_single_path_wrapper('file', _file) + _open = _mk_single_path_wrapper('open', _open) + for name in [ + "stat", "listdir", "chdir", "open", "chmod", "chown", "mkdir", + "remove", "unlink", "rmdir", "utime", "lchown", "chroot", "lstat", + "startfile", "mkfifo", "mknod", "pathconf", "access" + ]: + if hasattr(_os, name): + locals()[name] = _mk_single_path_wrapper(name) + + def _mk_single_with_return(name): + original = getattr(_os, name) + + def wrap(self, path, *args, **kw): + if self._active: + path = self._remap_input(name, path, *args, **kw) + return self._remap_output(name, original(path, *args, **kw)) + return original(path, *args, **kw) + + return wrap + + for name in ['readlink', 'tempnam']: + if hasattr(_os, name): + locals()[name] = _mk_single_with_return(name) + + def _mk_query(name): + original = getattr(_os, name) + + def wrap(self, *args, **kw): + retval = original(*args, **kw) + if self._active: + return self._remap_output(name, retval) + return retval + + return wrap + + for name in ['getcwd', 'tmpnam']: + if hasattr(_os, name): + locals()[name] = _mk_query(name) + + def _validate_path(self, path): + """Called to remap or validate any path, whether input or output""" + return path + + def _remap_input(self, operation, path, *args, **kw): + """Called for path inputs""" + return self._validate_path(path) + + def _remap_output(self, operation, path): + """Called for path outputs""" + return self._validate_path(path) + + def _remap_pair(self, operation, src, dst, *args, **kw): + """Called for path pairs like rename, link, and symlink operations""" + return ( + self._remap_input(operation + '-from', src, *args, **kw), + self._remap_input(operation + '-to', dst, *args, **kw) + ) + + +if hasattr(os, 'devnull'): + _EXCEPTIONS = [os.devnull,] +else: + _EXCEPTIONS = [] + + +class DirectorySandbox(AbstractSandbox): + """Restrict operations to a single subdirectory - pseudo-chroot""" + + write_ops = dict.fromkeys([ + "open", "chmod", "chown", "mkdir", "remove", "unlink", "rmdir", + "utime", "lchown", "chroot", "mkfifo", "mknod", "tempnam", + ]) + + _exception_patterns = [ + # Allow lib2to3 to attempt to save a pickled grammar object (#121) + r'.*lib2to3.*\.pickle$', + ] + "exempt writing to paths that match the pattern" + + def __init__(self, sandbox, exceptions=_EXCEPTIONS): + self._sandbox = os.path.normcase(os.path.realpath(sandbox)) + self._prefix = os.path.join(self._sandbox, '') + self._exceptions = [ + os.path.normcase(os.path.realpath(path)) + for path in exceptions + ] + AbstractSandbox.__init__(self) + + def _violation(self, operation, *args, **kw): + from setuptools.sandbox import SandboxViolation + raise SandboxViolation(operation, args, kw) + + if _file: + + def _file(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("file", path, mode, *args, **kw) + return _file(path, mode, *args, **kw) + + def _open(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("open", path, mode, *args, **kw) + return _open(path, mode, *args, **kw) + + def tmpnam(self): + self._violation("tmpnam") + + def _ok(self, path): + active = self._active + try: + self._active = False + realpath = os.path.normcase(os.path.realpath(path)) + return ( + self._exempted(realpath) + or realpath == self._sandbox + or realpath.startswith(self._prefix) + ) + finally: + self._active = active + + def _exempted(self, filepath): + start_matches = ( + filepath.startswith(exception) + for exception in self._exceptions + ) + pattern_matches = ( + re.match(pattern, filepath) + for pattern in self._exception_patterns + ) + candidates = itertools.chain(start_matches, pattern_matches) + return any(candidates) + + def _remap_input(self, operation, path, *args, **kw): + """Called for path inputs""" + if operation in self.write_ops and not self._ok(path): + self._violation(operation, os.path.realpath(path), *args, **kw) + return path + + def _remap_pair(self, operation, src, dst, *args, **kw): + """Called for path pairs like rename, link, and symlink operations""" + if not self._ok(src) or not self._ok(dst): + self._violation(operation, src, dst, *args, **kw) + return (src, dst) + + def open(self, file, flags, mode=0o777, *args, **kw): + """Called for low-level os.open()""" + if flags & WRITE_FLAGS and not self._ok(file): + self._violation("os.open", file, flags, mode, *args, **kw) + return _os.open(file, flags, mode, *args, **kw) + + +WRITE_FLAGS = functools.reduce( + operator.or_, [getattr(_os, a, 0) for a in + "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split()] +) + + +class SandboxViolation(DistutilsError): + """A setup script attempted to modify the filesystem outside the sandbox""" + + tmpl = textwrap.dedent(""" + SandboxViolation: {cmd}{args!r} {kwargs} + + The package setup script has attempted to modify files on your system + that are not within the EasyInstall build area, and has been aborted. + + This package cannot be safely installed by EasyInstall, and may not + support alternate installation locations even if you run its setup + script by hand. Please inform the package's author and the EasyInstall + maintainers to find out if a fix or workaround is available. + """).lstrip() + + def __str__(self): + cmd, args, kwargs = self.args + return self.tmpl.format(**locals()) diff --git a/winvenv/Lib/site-packages/setuptools/script (dev).tmpl b/winvenv/Lib/site-packages/setuptools/script (dev).tmpl new file mode 100644 index 0000000..39a24b0 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/script (dev).tmpl @@ -0,0 +1,6 @@ +# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r +__requires__ = %(spec)r +__import__('pkg_resources').require(%(spec)r) +__file__ = %(dev_path)r +with open(__file__) as f: + exec(compile(f.read(), __file__, 'exec')) diff --git a/winvenv/Lib/site-packages/setuptools/script.tmpl b/winvenv/Lib/site-packages/setuptools/script.tmpl new file mode 100644 index 0000000..ff5efbc --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/script.tmpl @@ -0,0 +1,3 @@ +# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r +__requires__ = %(spec)r +__import__('pkg_resources').run_script(%(spec)r, %(script_name)r) diff --git a/winvenv/Lib/site-packages/setuptools/site-patch.py b/winvenv/Lib/site-packages/setuptools/site-patch.py new file mode 100644 index 0000000..40b00de --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/site-patch.py @@ -0,0 +1,74 @@ +def __boot(): + import sys + import os + PYTHONPATH = os.environ.get('PYTHONPATH') + if PYTHONPATH is None or (sys.platform == 'win32' and not PYTHONPATH): + PYTHONPATH = [] + else: + PYTHONPATH = PYTHONPATH.split(os.pathsep) + + pic = getattr(sys, 'path_importer_cache', {}) + stdpath = sys.path[len(PYTHONPATH):] + mydir = os.path.dirname(__file__) + + for item in stdpath: + if item == mydir or not item: + continue # skip if current dir. on Windows, or my own directory + importer = pic.get(item) + if importer is not None: + loader = importer.find_module('site') + if loader is not None: + # This should actually reload the current module + loader.load_module('site') + break + else: + try: + import imp # Avoid import loop in Python 3 + stream, path, descr = imp.find_module('site', [item]) + except ImportError: + continue + if stream is None: + continue + try: + # This should actually reload the current module + imp.load_module('site', stream, path, descr) + finally: + stream.close() + break + else: + raise ImportError("Couldn't find the real 'site' module") + + known_paths = dict([(makepath(item)[1], 1) for item in sys.path]) # 2.2 comp + + oldpos = getattr(sys, '__egginsert', 0) # save old insertion position + sys.__egginsert = 0 # and reset the current one + + for item in PYTHONPATH: + addsitedir(item) + + sys.__egginsert += oldpos # restore effective old position + + d, nd = makepath(stdpath[0]) + insert_at = None + new_path = [] + + for item in sys.path: + p, np = makepath(item) + + if np == nd and insert_at is None: + # We've hit the first 'system' path entry, so added entries go here + insert_at = len(new_path) + + if np in known_paths or insert_at is None: + new_path.append(item) + else: + # new path after the insert point, back-insert it + new_path.insert(insert_at, item) + insert_at += 1 + + sys.path[:] = new_path + + +if __name__ == 'site': + __boot() + del __boot diff --git a/winvenv/Lib/site-packages/setuptools/ssl_support.py b/winvenv/Lib/site-packages/setuptools/ssl_support.py new file mode 100644 index 0000000..6362f1f --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/ssl_support.py @@ -0,0 +1,260 @@ +import os +import socket +import atexit +import re +import functools + +from setuptools.extern.six.moves import urllib, http_client, map, filter + +from pkg_resources import ResolutionError, ExtractionError + +try: + import ssl +except ImportError: + ssl = None + +__all__ = [ + 'VerifyingHTTPSHandler', 'find_ca_bundle', 'is_available', 'cert_paths', + 'opener_for' +] + +cert_paths = """ +/etc/pki/tls/certs/ca-bundle.crt +/etc/ssl/certs/ca-certificates.crt +/usr/share/ssl/certs/ca-bundle.crt +/usr/local/share/certs/ca-root.crt +/etc/ssl/cert.pem +/System/Library/OpenSSL/certs/cert.pem +/usr/local/share/certs/ca-root-nss.crt +/etc/ssl/ca-bundle.pem +""".strip().split() + +try: + HTTPSHandler = urllib.request.HTTPSHandler + HTTPSConnection = http_client.HTTPSConnection +except AttributeError: + HTTPSHandler = HTTPSConnection = object + +is_available = ssl is not None and object not in (HTTPSHandler, HTTPSConnection) + + +try: + from ssl import CertificateError, match_hostname +except ImportError: + try: + from backports.ssl_match_hostname import CertificateError + from backports.ssl_match_hostname import match_hostname + except ImportError: + CertificateError = None + match_hostname = None + +if not CertificateError: + + class CertificateError(ValueError): + pass + + +if not match_hostname: + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + # Ported from python3-syntax: + # leftmost, *remainder = dn.split(r'.') + parts = dn.split(r'.') + leftmost = parts[0] + remainder = parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +class VerifyingHTTPSHandler(HTTPSHandler): + """Simple verifying handler: no auth, subclasses, timeouts, etc.""" + + def __init__(self, ca_bundle): + self.ca_bundle = ca_bundle + HTTPSHandler.__init__(self) + + def https_open(self, req): + return self.do_open( + lambda host, **kw: VerifyingHTTPSConn(host, self.ca_bundle, **kw), req + ) + + +class VerifyingHTTPSConn(HTTPSConnection): + """Simple verifying connection: no auth, subclasses, timeouts, etc.""" + + def __init__(self, host, ca_bundle, **kw): + HTTPSConnection.__init__(self, host, **kw) + self.ca_bundle = ca_bundle + + def connect(self): + sock = socket.create_connection( + (self.host, self.port), getattr(self, 'source_address', None) + ) + + # Handle the socket if a (proxy) tunnel is present + if hasattr(self, '_tunnel') and getattr(self, '_tunnel_host', None): + self.sock = sock + self._tunnel() + # http://bugs.python.org/issue7776: Python>=3.4.1 and >=2.7.7 + # change self.host to mean the proxy server host when tunneling is + # being used. Adapt, since we are interested in the destination + # host for the match_hostname() comparison. + actual_host = self._tunnel_host + else: + actual_host = self.host + + if hasattr(ssl, 'create_default_context'): + ctx = ssl.create_default_context(cafile=self.ca_bundle) + self.sock = ctx.wrap_socket(sock, server_hostname=actual_host) + else: + # This is for python < 2.7.9 and < 3.4? + self.sock = ssl.wrap_socket( + sock, cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.ca_bundle + ) + try: + match_hostname(self.sock.getpeercert(), actual_host) + except CertificateError: + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + +def opener_for(ca_bundle=None): + """Get a urlopen() replacement that uses ca_bundle for verification""" + return urllib.request.build_opener( + VerifyingHTTPSHandler(ca_bundle or find_ca_bundle()) + ).open + + +# from jaraco.functools +def once(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + if not hasattr(func, 'always_returns'): + func.always_returns = func(*args, **kwargs) + return func.always_returns + return wrapper + + +@once +def get_win_certfile(): + try: + import wincertstore + except ImportError: + return None + + class CertFile(wincertstore.CertFile): + def __init__(self): + super(CertFile, self).__init__() + atexit.register(self.close) + + def close(self): + try: + super(CertFile, self).close() + except OSError: + pass + + _wincerts = CertFile() + _wincerts.addstore('CA') + _wincerts.addstore('ROOT') + return _wincerts.name + + +def find_ca_bundle(): + """Return an existing CA bundle path, or None""" + extant_cert_paths = filter(os.path.isfile, cert_paths) + return ( + get_win_certfile() + or next(extant_cert_paths, None) + or _certifi_where() + ) + + +def _certifi_where(): + try: + return __import__('certifi').where() + except (ImportError, ResolutionError, ExtractionError): + pass diff --git a/winvenv/Lib/site-packages/setuptools/unicode_utils.py b/winvenv/Lib/site-packages/setuptools/unicode_utils.py new file mode 100644 index 0000000..7c63efd --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/unicode_utils.py @@ -0,0 +1,44 @@ +import unicodedata +import sys + +from setuptools.extern import six + + +# HFS Plus uses decomposed UTF-8 +def decompose(path): + if isinstance(path, six.text_type): + return unicodedata.normalize('NFD', path) + try: + path = path.decode('utf-8') + path = unicodedata.normalize('NFD', path) + path = path.encode('utf-8') + except UnicodeError: + pass # Not UTF-8 + return path + + +def filesys_decode(path): + """ + Ensure that the given path is decoded, + NONE when no expected encoding works + """ + + if isinstance(path, six.text_type): + return path + + fs_enc = sys.getfilesystemencoding() or 'utf-8' + candidates = fs_enc, 'utf-8' + + for enc in candidates: + try: + return path.decode(enc) + except UnicodeDecodeError: + continue + + +def try_encode(string, enc): + "turn unicode encoding into a functional routine" + try: + return string.encode(enc) + except UnicodeEncodeError: + return None diff --git a/winvenv/Lib/site-packages/setuptools/version.py b/winvenv/Lib/site-packages/setuptools/version.py new file mode 100644 index 0000000..95e1869 --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/version.py @@ -0,0 +1,6 @@ +import pkg_resources + +try: + __version__ = pkg_resources.get_distribution('setuptools').version +except Exception: + __version__ = 'unknown' diff --git a/winvenv/Lib/site-packages/setuptools/wheel.py b/winvenv/Lib/site-packages/setuptools/wheel.py new file mode 100644 index 0000000..95a794a --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/wheel.py @@ -0,0 +1,210 @@ +"""Wheels support.""" + +from distutils.util import get_platform +import email +import itertools +import os +import posixpath +import re +import zipfile + +from pkg_resources import Distribution, PathMetadata, parse_version +from setuptools.extern.packaging.utils import canonicalize_name +from setuptools.extern.six import PY3 +from setuptools import Distribution as SetuptoolsDistribution +from setuptools import pep425tags +from setuptools.command.egg_info import write_requirements + + +__metaclass__ = type + + +WHEEL_NAME = re.compile( + r"""^(?P.+?)-(?P\d.*?) + ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) + )\.whl$""", + re.VERBOSE).match + +NAMESPACE_PACKAGE_INIT = '''\ +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + __path__ = __import__('pkgutil').extend_path(__path__, __name__) +''' + + +def unpack(src_dir, dst_dir): + '''Move everything under `src_dir` to `dst_dir`, and delete the former.''' + for dirpath, dirnames, filenames in os.walk(src_dir): + subdir = os.path.relpath(dirpath, src_dir) + for f in filenames: + src = os.path.join(dirpath, f) + dst = os.path.join(dst_dir, subdir, f) + os.renames(src, dst) + for n, d in reversed(list(enumerate(dirnames))): + src = os.path.join(dirpath, d) + dst = os.path.join(dst_dir, subdir, d) + if not os.path.exists(dst): + # Directory does not exist in destination, + # rename it and prune it from os.walk list. + os.renames(src, dst) + del dirnames[n] + # Cleanup. + for dirpath, dirnames, filenames in os.walk(src_dir, topdown=True): + assert not filenames + os.rmdir(dirpath) + + +class Wheel: + + def __init__(self, filename): + match = WHEEL_NAME(os.path.basename(filename)) + if match is None: + raise ValueError('invalid wheel name: %r' % filename) + self.filename = filename + for k, v in match.groupdict().items(): + setattr(self, k, v) + + def tags(self): + '''List tags (py_version, abi, platform) supported by this wheel.''' + return itertools.product( + self.py_version.split('.'), + self.abi.split('.'), + self.platform.split('.'), + ) + + def is_compatible(self): + '''Is the wheel is compatible with the current platform?''' + supported_tags = pep425tags.get_supported() + return next((True for t in self.tags() if t in supported_tags), False) + + def egg_name(self): + return Distribution( + project_name=self.project_name, version=self.version, + platform=(None if self.platform == 'any' else get_platform()), + ).egg_name() + '.egg' + + def get_dist_info(self, zf): + # find the correct name of the .dist-info dir in the wheel file + for member in zf.namelist(): + dirname = posixpath.dirname(member) + if (dirname.endswith('.dist-info') and + canonicalize_name(dirname).startswith( + canonicalize_name(self.project_name))): + return dirname + raise ValueError("unsupported wheel format. .dist-info not found") + + def install_as_egg(self, destination_eggdir): + '''Install wheel as an egg directory.''' + with zipfile.ZipFile(self.filename) as zf: + self._install_as_egg(destination_eggdir, zf) + + def _install_as_egg(self, destination_eggdir, zf): + dist_basename = '%s-%s' % (self.project_name, self.version) + dist_info = self.get_dist_info(zf) + dist_data = '%s.data' % dist_basename + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + + self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) + self._move_data_entries(destination_eggdir, dist_data) + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): + def get_metadata(name): + with zf.open(posixpath.join(dist_info, name)) as fp: + value = fp.read().decode('utf-8') if PY3 else fp.read() + return email.parser.Parser().parsestr(value) + + wheel_metadata = get_metadata('WHEEL') + # Check wheel format version is supported. + wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) + wheel_v1 = ( + parse_version('1.0') <= wheel_version < parse_version('2.0dev0') + ) + if not wheel_v1: + raise ValueError( + 'unsupported wheel format version: %s' % wheel_version) + # Extract to target directory. + os.mkdir(destination_eggdir) + zf.extractall(destination_eggdir) + # Convert metadata. + dist_info = os.path.join(destination_eggdir, dist_info) + dist = Distribution.from_location( + destination_eggdir, dist_info, + metadata=PathMetadata(destination_eggdir, dist_info), + ) + + # Note: Evaluate and strip markers now, + # as it's difficult to convert back from the syntax: + # foobar; "linux" in sys_platform and extra == 'test' + def raw_req(req): + req.marker = None + return str(req) + install_requires = list(sorted(map(raw_req, dist.requires()))) + extras_require = { + extra: sorted( + req + for req in map(raw_req, dist.requires((extra,))) + if req not in install_requires + ) + for extra in dist.extras + } + os.rename(dist_info, egg_info) + os.rename( + os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO'), + ) + setup_dist = SetuptoolsDistribution( + attrs=dict( + install_requires=install_requires, + extras_require=extras_require, + ), + ) + write_requirements( + setup_dist.get_command_obj('egg_info'), + None, + os.path.join(egg_info, 'requires.txt'), + ) + + @staticmethod + def _move_data_entries(destination_eggdir, dist_data): + """Move data entries to their correct location.""" + dist_data = os.path.join(destination_eggdir, dist_data) + dist_data_scripts = os.path.join(dist_data, 'scripts') + if os.path.exists(dist_data_scripts): + egg_info_scripts = os.path.join( + destination_eggdir, 'EGG-INFO', 'scripts') + os.mkdir(egg_info_scripts) + for entry in os.listdir(dist_data_scripts): + # Remove bytecode, as it's not properly handled + # during easy_install scripts install phase. + if entry.endswith('.pyc'): + os.unlink(os.path.join(dist_data_scripts, entry)) + else: + os.rename( + os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry), + ) + os.rmdir(dist_data_scripts) + for subdir in filter(os.path.exists, ( + os.path.join(dist_data, d) + for d in ('data', 'headers', 'purelib', 'platlib') + )): + unpack(subdir, destination_eggdir) + if os.path.exists(dist_data): + os.rmdir(dist_data) + + @staticmethod + def _fix_namespace_packages(egg_info, destination_eggdir): + namespace_packages = os.path.join( + egg_info, 'namespace_packages.txt') + if os.path.exists(namespace_packages): + with open(namespace_packages) as fp: + namespace_packages = fp.read().split() + for mod in namespace_packages: + mod_dir = os.path.join(destination_eggdir, *mod.split('.')) + mod_init = os.path.join(mod_dir, '__init__.py') + if os.path.exists(mod_dir) and not os.path.exists(mod_init): + with open(mod_init, 'w') as fp: + fp.write(NAMESPACE_PACKAGE_INIT) diff --git a/winvenv/Lib/site-packages/setuptools/windows_support.py b/winvenv/Lib/site-packages/setuptools/windows_support.py new file mode 100644 index 0000000..cb977cf --- /dev/null +++ b/winvenv/Lib/site-packages/setuptools/windows_support.py @@ -0,0 +1,29 @@ +import platform +import ctypes + + +def windows_only(func): + if platform.system() != 'Windows': + return lambda *args, **kwargs: None + return func + + +@windows_only +def hide_file(path): + """ + Set the hidden attribute on a file or directory. + + From http://stackoverflow.com/questions/19622133/ + + `path` must be text. + """ + __import__('ctypes.wintypes') + SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW + SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD + SetFileAttributes.restype = ctypes.wintypes.BOOL + + FILE_ATTRIBUTE_HIDDEN = 0x02 + + ret = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) + if not ret: + raise ctypes.WinError() diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst b/winvenv/Lib/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..09c2c99 --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/DESCRIPTION.rst @@ -0,0 +1,27 @@ +.. image:: http://img.shields.io/pypi/v/six.svg + :target: https://pypi.python.org/pypi/six + +.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master + :target: https://travis-ci.org/benjaminp/six + +.. image:: http://img.shields.io/badge/license-MIT-green.svg + :target: https://github.com/benjaminp/six/blob/master/LICENSE + +Six is a Python 2 and 3 compatibility library. It provides utility functions +for smoothing over the differences between the Python versions with the goal of +writing Python code that is compatible on both Python versions. See the +documentation for more information on what is provided. + +Six supports every Python version since 2.6. It is contained in only one Python +file, so it can be easily copied into your project. (The copyright and license +notice must be retained.) + +Online documentation is at http://six.rtfd.org. + +Bugs can be reported to https://github.com/benjaminp/six. The code can also +be found there. + +For questions about six or porting in general, email the python-porting mailing +list: https://mail.python.org/mailman/listinfo/python-porting + + diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/INSTALLER b/winvenv/Lib/site-packages/six-1.11.0.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/METADATA b/winvenv/Lib/site-packages/six-1.11.0.dist-info/METADATA new file mode 100644 index 0000000..04e93dc --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/METADATA @@ -0,0 +1,43 @@ +Metadata-Version: 2.0 +Name: six +Version: 1.11.0 +Summary: Python 2 and 3 compatibility utilities +Home-page: http://pypi.python.org/pypi/six/ +Author: Benjamin Peterson +Author-email: benjamin@python.org +License: MIT +Platform: UNKNOWN +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: Utilities + +.. image:: http://img.shields.io/pypi/v/six.svg + :target: https://pypi.python.org/pypi/six + +.. image:: https://travis-ci.org/benjaminp/six.svg?branch=master + :target: https://travis-ci.org/benjaminp/six + +.. image:: http://img.shields.io/badge/license-MIT-green.svg + :target: https://github.com/benjaminp/six/blob/master/LICENSE + +Six is a Python 2 and 3 compatibility library. It provides utility functions +for smoothing over the differences between the Python versions with the goal of +writing Python code that is compatible on both Python versions. See the +documentation for more information on what is provided. + +Six supports every Python version since 2.6. It is contained in only one Python +file, so it can be easily copied into your project. (The copyright and license +notice must be retained.) + +Online documentation is at http://six.rtfd.org. + +Bugs can be reported to https://github.com/benjaminp/six. The code can also +be found there. + +For questions about six or porting in general, email the python-porting mailing +list: https://mail.python.org/mailman/listinfo/python-porting + + diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/RECORD b/winvenv/Lib/site-packages/six-1.11.0.dist-info/RECORD new file mode 100644 index 0000000..5ab3c76 --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/RECORD @@ -0,0 +1,9 @@ +__pycache__/six.cpython-37.pyc,, +six-1.11.0.dist-info/DESCRIPTION.rst,sha256=gPBoq1Ruc1QDWyLeXPlieL3F-XZz1_WXB-5gctCfg-A,1098 +six-1.11.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +six-1.11.0.dist-info/METADATA,sha256=06nZXaDYN3vnC-pmUjhkECYFH_a--ywvcPIpUdNeH1o,1607 +six-1.11.0.dist-info/RECORD,, +six-1.11.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 +six-1.11.0.dist-info/metadata.json,sha256=ac3f4f7MpSHSnZ1SqhHCwsL7FGWMG0gBEb0hhS2eSSM,703 +six-1.11.0.dist-info/top_level.txt,sha256=_iVH_iYEtEXnD8nYGQYpYFUvkUW9sEO1GYbkeKSAais,4 +six.py,sha256=A08MPb-Gi9FfInI3IW7HimXFmEH2T2IPzHgDvdhZPRA,30888 diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/WHEEL b/winvenv/Lib/site-packages/six-1.11.0.dist-info/WHEEL new file mode 100644 index 0000000..8b6dd1b --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/metadata.json b/winvenv/Lib/site-packages/six-1.11.0.dist-info/metadata.json new file mode 100644 index 0000000..2c7fcea --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Libraries", "Topic :: Utilities"], "extensions": {"python.details": {"contacts": [{"email": "benjamin@python.org", "name": "Benjamin Peterson", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://pypi.python.org/pypi/six/"}}}, "generator": "bdist_wheel (0.29.0)", "license": "MIT", "metadata_version": "2.0", "name": "six", "summary": "Python 2 and 3 compatibility utilities", "test_requires": [{"requires": ["pytest"]}], "version": "1.11.0"} \ No newline at end of file diff --git a/winvenv/Lib/site-packages/six-1.11.0.dist-info/top_level.txt b/winvenv/Lib/site-packages/six-1.11.0.dist-info/top_level.txt new file mode 100644 index 0000000..ffe2fce --- /dev/null +++ b/winvenv/Lib/site-packages/six-1.11.0.dist-info/top_level.txt @@ -0,0 +1 @@ +six diff --git a/winvenv/Lib/site-packages/six.py b/winvenv/Lib/site-packages/six.py new file mode 100644 index 0000000..6bf4fd3 --- /dev/null +++ b/winvenv/Lib/site-packages/six.py @@ -0,0 +1,891 @@ +# Copyright (c) 2010-2017 Benjamin Peterson +# +# 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. + +"""Utilities for writing code that runs on Python 2 and 3""" + +from __future__ import absolute_import + +import functools +import itertools +import operator +import sys +import types + +__author__ = "Benjamin Peterson " +__version__ = "1.11.0" + + +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 +PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) + +if PY3: + string_types = str, + integer_types = int, + class_types = type, + text_type = str + binary_type = bytes + + MAXSIZE = sys.maxsize +else: + string_types = basestring, + integer_types = (int, long) + class_types = (type, types.ClassType) + text_type = unicode + binary_type = str + + if sys.platform.startswith("java"): + # Jython always uses 32 bits. + MAXSIZE = int((1 << 31) - 1) + else: + # It's possible to have sizeof(long) != sizeof(Py_ssize_t). + class X(object): + + def __len__(self): + return 1 << 31 + try: + len(X()) + except OverflowError: + # 32-bit + MAXSIZE = int((1 << 31) - 1) + else: + # 64-bit + MAXSIZE = int((1 << 63) - 1) + del X + + +def _add_doc(func, doc): + """Add documentation to a function.""" + func.__doc__ = doc + + +def _import_module(name): + """Import module, returning the module after the last dot.""" + __import__(name) + return sys.modules[name] + + +class _LazyDescr(object): + + def __init__(self, name): + self.name = name + + def __get__(self, obj, tp): + result = self._resolve() + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass + return result + + +class MovedModule(_LazyDescr): + + def __init__(self, name, old, new=None): + super(MovedModule, self).__init__(name) + if PY3: + if new is None: + new = name + self.mod = new + else: + self.mod = old + + def _resolve(self): + return _import_module(self.mod) + + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + + +class MovedAttribute(_LazyDescr): + + def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): + super(MovedAttribute, self).__init__(name) + if PY3: + if new_mod is None: + new_mod = name + self.mod = new_mod + if new_attr is None: + if old_attr is None: + new_attr = name + else: + new_attr = old_attr + self.attr = new_attr + else: + self.mod = old_mod + if old_attr is None: + old_attr = name + self.attr = old_attr + + def _resolve(self): + module = _import_module(self.mod) + return getattr(module, self.attr) + + +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): + + """Lazy loading of moved objects""" + __path__ = [] # mark as package + + +_moved_attributes = [ + MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), + MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), + MovedAttribute("map", "itertools", "builtins", "imap", "map"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("getoutput", "commands", "subprocess"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), + MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), + MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), + MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedModule("builtins", "__builtin__"), + MovedModule("configparser", "ConfigParser"), + MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), + MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), + MovedModule("http_cookies", "Cookie", "http.cookies"), + MovedModule("html_entities", "htmlentitydefs", "html.entities"), + MovedModule("html_parser", "HTMLParser", "html.parser"), + MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), + MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), + MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), + MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), + MovedModule("cPickle", "cPickle", "pickle"), + MovedModule("queue", "Queue"), + MovedModule("reprlib", "repr"), + MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), + MovedModule("tkinter", "Tkinter"), + MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), + MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), + MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), + MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), + MovedModule("tkinter_colorchooser", "tkColorChooser", + "tkinter.colorchooser"), + MovedModule("tkinter_commondialog", "tkCommonDialog", + "tkinter.commondialog"), + MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), + MovedModule("tkinter_font", "tkFont", "tkinter.font"), + MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), + MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", + "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), +] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + +for attr in _moved_attributes: + setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), + MovedAttribute("parse_http_list", "urllib2", "urllib.request"), + MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) +del attr + +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") + + +def add_move(move): + """Add an item to six.moves.""" + setattr(_MovedItems, move.name, move) + + +def remove_move(name): + """Remove item from six.moves.""" + try: + delattr(_MovedItems, name) + except AttributeError: + try: + del moves.__dict__[name] + except KeyError: + raise AttributeError("no such move, %r" % (name,)) + + +if PY3: + _meth_func = "__func__" + _meth_self = "__self__" + + _func_closure = "__closure__" + _func_code = "__code__" + _func_defaults = "__defaults__" + _func_globals = "__globals__" +else: + _meth_func = "im_func" + _meth_self = "im_self" + + _func_closure = "func_closure" + _func_code = "func_code" + _func_defaults = "func_defaults" + _func_globals = "func_globals" + + +try: + advance_iterator = next +except NameError: + def advance_iterator(it): + return it.next() +next = advance_iterator + + +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + + +if PY3: + def get_unbound_function(unbound): + return unbound + + create_bound_method = types.MethodType + + def create_unbound_method(func, cls): + return func + + Iterator = object +else: + def get_unbound_function(unbound): + return unbound.im_func + + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + + class Iterator(object): + + def next(self): + return type(self).__next__(self) + + callable = callable +_add_doc(get_unbound_function, + """Get the function out of a possibly unbound function""") + + +get_method_function = operator.attrgetter(_meth_func) +get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) +get_function_code = operator.attrgetter(_func_code) +get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) + + +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") + + +if PY3: + def b(s): + return s.encode("latin-1") + + def u(s): + return s + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter + import io + StringIO = io.StringIO + BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" +else: + def b(s): + return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr + int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) + import StringIO + StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" +_add_doc(b, """Byte literal""") +_add_doc(u, """Text literal""") + + +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) + + +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) + + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None + +else: + def exec_(_code_, _globs_=None, _locs_=None): + """Execute code in a namespace.""" + if _globs_ is None: + frame = sys._getframe(1) + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals + del frame + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") + + exec_("""def reraise(tp, value, tb=None): + try: + raise tp, value, tb + finally: + tb = None +""") + + +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + try: + if from_value is None: + raise value + raise value from from_value + finally: + value = None +""") +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value + + +print_ = getattr(moves.builtins, "print", None) +if print_ is None: + def print_(*args, **kwargs): + """The new-style print function for Python 2.4 and 2.5.""" + fp = kwargs.pop("file", sys.stdout) + if fp is None: + return + + def write(data): + if not isinstance(data, basestring): + data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) + fp.write(data) + want_unicode = False + sep = kwargs.pop("sep", None) + if sep is not None: + if isinstance(sep, unicode): + want_unicode = True + elif not isinstance(sep, str): + raise TypeError("sep must be None or a string") + end = kwargs.pop("end", None) + if end is not None: + if isinstance(end, unicode): + want_unicode = True + elif not isinstance(end, str): + raise TypeError("end must be None or a string") + if kwargs: + raise TypeError("invalid keyword arguments to print()") + if not want_unicode: + for arg in args: + if isinstance(arg, unicode): + want_unicode = True + break + if want_unicode: + newline = unicode("\n") + space = unicode(" ") + else: + newline = "\n" + space = " " + if sep is None: + sep = space + if end is None: + end = newline + for i, arg in enumerate(args): + if i: + write(sep) + write(arg) + write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() + +_add_doc(reraise, """Reraise an exception.""") + +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(type): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff --git a/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/INSTALLER b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/LICENSE.txt b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/LICENSE.txt new file mode 100644 index 0000000..c3441e6 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/LICENSE.txt @@ -0,0 +1,22 @@ +"wheel" copyright (c) 2012-2014 Daniel Holth and +contributors. + +The MIT License + +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/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/METADATA b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/METADATA new file mode 100644 index 0000000..cef8071 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/METADATA @@ -0,0 +1,60 @@ +Metadata-Version: 2.1 +Name: wheel +Version: 0.32.3 +Summary: A built-package format for Python. +Home-page: https://github.com/pypa/wheel +Author: Daniel Holth +Author-email: dholth@fastmail.fm +Maintainer: Alex Grönholm +Maintainer-email: alex.gronholm@nextday.fi +License: MIT +Project-URL: Issue Tracker, https://github.com/pypa/wheel/issues +Project-URL: Documentation, https://wheel.readthedocs.io/ +Project-URL: Changelog, https://wheel.readthedocs.io/en/stable/news.html +Keywords: wheel,packaging +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Topic :: System :: Archiving :: Packaging +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +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 +Classifier: Programming Language :: Python :: 3.7 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Provides-Extra: test +Requires-Dist: pytest (>=3.0.0) ; extra == 'test' +Requires-Dist: pytest-cov ; extra == 'test' + +wheel +===== + +This library is the reference implementation of the Python wheel packaging +standard, as defined in `PEP 427`_. + +It has two different roles: + +#. A setuptools_ extension for building wheels that provides the + ``bdist_wheel`` setuptools command +#. A command line tool for working with wheel files + +It should be noted that wheel is **not** intended to be used as a library, and +as such there is no stable, public API. + +.. _PEP 427: https://www.python.org/dev/peps/pep-0427/ +.. _setuptools: https://pypi.org/project/setuptools/ + + +Code of Conduct +--------------- + +Everyone interacting in the wheel project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_. + +.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ + + diff --git a/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/RECORD b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/RECORD new file mode 100644 index 0000000..28bff1e --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/RECORD @@ -0,0 +1,34 @@ +../../Scripts/wheel.exe,sha256=x_Gzkkdy0ryBJXwrfS_WDyUHHkrQGktnmoDhNfeITR8,102787 +wheel-0.32.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +wheel-0.32.3.dist-info/LICENSE.txt,sha256=zKniDGrx_Pv2lAjzd3aShsvuvN7TNhAMm0o_NfvmNeQ,1125 +wheel-0.32.3.dist-info/METADATA,sha256=1gweIMsoaCjJWccLOuQJCZqj_cWYVM80LkUQosJ4wC8,2082 +wheel-0.32.3.dist-info/RECORD,, +wheel-0.32.3.dist-info/WHEEL,sha256=_wJFdOYk7i3xxT8ElOkUJvOdOvfNGbR9g-bf6UQT6sU,110 +wheel-0.32.3.dist-info/entry_points.txt,sha256=N8HbYFST3yrNQYeB2wXWBEPUhFsEtKNRPaCFGJPyqyc,108 +wheel-0.32.3.dist-info/top_level.txt,sha256=HxSBIbgEstMPe4eFawhA66Mq-QYHMopXVoAncfjb_1c,6 +wheel/__init__.py,sha256=AgAP7YAmbZj84_nCH9za8R0UXHylXdfKNSyg5g1xLZ4,96 +wheel/__main__.py,sha256=lF-YLO4hdQmoWuh4eWZd8YL1U95RSdm76sNLBXa0vjE,417 +wheel/__pycache__/__init__.cpython-37.pyc,, +wheel/__pycache__/__main__.cpython-37.pyc,, +wheel/__pycache__/bdist_wheel.cpython-37.pyc,, +wheel/__pycache__/metadata.cpython-37.pyc,, +wheel/__pycache__/pep425tags.cpython-37.pyc,, +wheel/__pycache__/pkginfo.cpython-37.pyc,, +wheel/__pycache__/util.cpython-37.pyc,, +wheel/__pycache__/wheelfile.cpython-37.pyc,, +wheel/bdist_wheel.py,sha256=0hM63ZD01ATEMRAr6t0mbmhf2y8pbRkMnWGioed9n-o,14627 +wheel/cli/__init__.py,sha256=DsCXkrL_jsTHoR0nhmcwkrlNdkaXw0uV0NL-yYoYQuU,2461 +wheel/cli/__pycache__/__init__.cpython-37.pyc,, +wheel/cli/__pycache__/convert.cpython-37.pyc,, +wheel/cli/__pycache__/install.cpython-37.pyc,, +wheel/cli/__pycache__/pack.cpython-37.pyc,, +wheel/cli/__pycache__/unpack.cpython-37.pyc,, +wheel/cli/convert.py,sha256=me0l6G4gSw-EBVhzjSr7yWYWBp9spMz7mnXlyJTiXso,9497 +wheel/cli/install.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +wheel/cli/pack.py,sha256=RViq4mnUk8s7R5kcrgX0XntX2zalDTeoTSBzLk31SaI,2145 +wheel/cli/unpack.py,sha256=0VWzT7U_xyenTPwEVavxqvdee93GPvAFHnR3Uu91aRc,673 +wheel/metadata.py,sha256=a3QgT8C4QOvrS-8RFdNCn7XWUUqEZpcHelmI8XLTDnY,4691 +wheel/pep425tags.py,sha256=Jdjbnq17kqwPRKJCMb2E1VccNgnC3H6iQL7VGaxkPao,5908 +wheel/pkginfo.py,sha256=GR76kupQzn1x9sKDaXuE6B6FsZ4OkfRtG7pndlXPvQ4,1257 +wheel/util.py,sha256=bYkw5oMccfazVCoYQwKkkemoVyMAFoR34mmKBx8R1NI,859 +wheel/wheelfile.py,sha256=mxv8kcRvXMME4xQstpiiQv59bHc42edS6z8kDAco6iw,6990 diff --git a/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/WHEEL b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/WHEEL new file mode 100644 index 0000000..c4bde30 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.3) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/entry_points.txt b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/entry_points.txt new file mode 100644 index 0000000..b27acad --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/entry_points.txt @@ -0,0 +1,6 @@ +[console_scripts] +wheel = wheel.cli:main + +[distutils.commands] +bdist_wheel = wheel.bdist_wheel:bdist_wheel + diff --git a/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/top_level.txt b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/top_level.txt new file mode 100644 index 0000000..2309722 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel-0.32.3.dist-info/top_level.txt @@ -0,0 +1 @@ +wheel diff --git a/winvenv/Lib/site-packages/wheel/__init__.py b/winvenv/Lib/site-packages/wheel/__init__.py new file mode 100644 index 0000000..6938633 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/__init__.py @@ -0,0 +1,2 @@ +# __variables__ with double-quoted values will be available in setup.py: +__version__ = "0.32.3" diff --git a/winvenv/Lib/site-packages/wheel/__main__.py b/winvenv/Lib/site-packages/wheel/__main__.py new file mode 100644 index 0000000..b3773a2 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/__main__.py @@ -0,0 +1,19 @@ +""" +Wheel command line tool (enable python -m wheel syntax) +""" + +import sys + + +def main(): # needed for console script + if __package__ == '': + # To be able to run 'python wheel-0.9.whl/wheel': + import os.path + path = os.path.dirname(os.path.dirname(__file__)) + sys.path[0:0] = [path] + import wheel.cli + sys.exit(wheel.cli.main()) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/winvenv/Lib/site-packages/wheel/bdist_wheel.py b/winvenv/Lib/site-packages/wheel/bdist_wheel.py new file mode 100644 index 0000000..5796970 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/bdist_wheel.py @@ -0,0 +1,368 @@ +""" +Create a wheel (.whl) distribution. + +A wheel is a built archive format. +""" + +import os +import shutil +import sys +import re +from email.generator import Generator +from distutils.core import Command +from distutils.sysconfig import get_python_version +from distutils import log as logger +from glob import iglob +from shutil import rmtree +from warnings import warn + +import pkg_resources + +from .pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag, get_platform +from .pkginfo import write_pkg_info +from .metadata import pkginfo_to_metadata +from .wheelfile import WheelFile +from . import pep425tags +from . import __version__ as wheel_version + + +safe_name = pkg_resources.safe_name +safe_version = pkg_resources.safe_version + +PY_LIMITED_API_PATTERN = r'cp3\d' + + +def safer_name(name): + return safe_name(name).replace('-', '_') + + +def safer_version(version): + return safe_version(version).replace('-', '_') + + +class bdist_wheel(Command): + + description = 'create a wheel distribution' + + user_options = [('bdist-dir=', 'b', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('relative', None, + "build the archive using relative paths" + "(default: false)"), + ('owner=', 'u', + "Owner name used when creating a tar file" + " [default: current user]"), + ('group=', 'g', + "Group name used when creating a tar file" + " [default: current group]"), + ('universal', None, + "make a universal wheel" + " (default: false)"), + ('python-tag=', None, + "Python implementation compatibility tag" + " (default: py%s)" % get_impl_ver()[0]), + ('build-number=', None, + "Build number for this particular version. " + "As specified in PEP-0427, this must start with a digit. " + "[default: None]"), + ('py-limited-api=', None, + "Python tag (cp32|cp33|cpNN) for abi3 wheel tag" + " (default: false)"), + ] + + boolean_options = ['keep-temp', 'skip-build', 'relative', 'universal'] + + def initialize_options(self): + self.bdist_dir = None + self.data_dir = None + self.plat_name = None + self.plat_tag = None + self.format = 'zip' + self.keep_temp = False + self.dist_dir = None + self.egginfo_dir = None + self.root_is_pure = None + self.skip_build = None + self.relative = False + self.owner = None + self.group = None + self.universal = False + self.python_tag = 'py' + get_impl_ver()[0] + self.build_number = None + self.py_limited_api = False + self.plat_name_supplied = False + + def finalize_options(self): + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'wheel') + + self.data_dir = self.wheel_dist_name + '.data' + self.plat_name_supplied = self.plat_name is not None + + need_options = ('dist_dir', 'plat_name', 'skip_build') + + self.set_undefined_options('bdist', + *zip(need_options, need_options)) + + self.root_is_pure = not (self.distribution.has_ext_modules() + or self.distribution.has_c_libraries()) + + if self.py_limited_api and not re.match(PY_LIMITED_API_PATTERN, self.py_limited_api): + raise ValueError("py-limited-api must match '%s'" % PY_LIMITED_API_PATTERN) + + # Support legacy [wheel] section for setting universal + wheel = self.distribution.get_option_dict('wheel') + if 'universal' in wheel: + # please don't define this in your global configs + logger.warn('The [wheel] section is deprecated. Use [bdist_wheel] instead.') + val = wheel['universal'][1].strip() + if val.lower() in ('1', 'true', 'yes'): + self.universal = True + + if self.build_number is not None and not self.build_number[:1].isdigit(): + raise ValueError("Build tag (build-number) must start with a digit.") + + @property + def wheel_dist_name(self): + """Return distribution full name with - replaced with _""" + components = (safer_name(self.distribution.get_name()), + safer_version(self.distribution.get_version())) + if self.build_number: + components += (self.build_number,) + return '-'.join(components) + + def get_tag(self): + # bdist sets self.plat_name if unset, we should only use it for purepy + # wheels if the user supplied it. + if self.plat_name_supplied: + plat_name = self.plat_name + elif self.root_is_pure: + plat_name = 'any' + else: + plat_name = self.plat_name or get_platform() + if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647: + plat_name = 'linux_i686' + plat_name = plat_name.replace('-', '_').replace('.', '_') + + if self.root_is_pure: + if self.universal: + impl = 'py2.py3' + else: + impl = self.python_tag + tag = (impl, 'none', plat_name) + else: + impl_name = get_abbr_impl() + impl_ver = get_impl_ver() + impl = impl_name + impl_ver + # We don't work on CPython 3.1, 3.0. + if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'): + impl = self.py_limited_api + abi_tag = 'abi3' + else: + abi_tag = str(get_abi_tag()).lower() + tag = (impl, abi_tag, plat_name) + supported_tags = pep425tags.get_supported( + supplied_platform=plat_name if self.plat_name_supplied else None) + # XXX switch to this alternate implementation for non-pure: + if not self.py_limited_api: + assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0]) + assert tag in supported_tags, "would build wheel with unsupported tag {}".format(tag) + return tag + + def run(self): + build_scripts = self.reinitialize_command('build_scripts') + build_scripts.executable = 'python' + + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', + reinit_subcommands=True) + install.root = self.bdist_dir + install.compile = False + install.skip_build = self.skip_build + install.warn_dir = False + + # A wheel without setuptools scripts is more cross-platform. + # Use the (undocumented) `no_ep` option to setuptools' + # install_scripts command to avoid creating entry point scripts. + install_scripts = self.reinitialize_command('install_scripts') + install_scripts.no_ep = True + + # Use a custom scheme for the archive, because we have to decide + # at installation time which scheme to use. + for key in ('headers', 'scripts', 'data', 'purelib', 'platlib'): + setattr(install, + 'install_' + key, + os.path.join(self.data_dir, key)) + + basedir_observed = '' + + if os.name == 'nt': + # win32 barfs if any of these are ''; could be '.'? + # (distutils.command.install:change_roots bug) + basedir_observed = os.path.normpath(os.path.join(self.data_dir, '..')) + self.install_libbase = self.install_lib = basedir_observed + + setattr(install, + 'install_purelib' if self.root_is_pure else 'install_platlib', + basedir_observed) + + logger.info("installing to %s", self.bdist_dir) + + self.run_command('install') + + impl_tag, abi_tag, plat_tag = self.get_tag() + archive_basename = "{}-{}-{}-{}".format(self.wheel_dist_name, impl_tag, abi_tag, plat_tag) + if not self.relative: + archive_root = self.bdist_dir + else: + archive_root = os.path.join( + self.bdist_dir, + self._ensure_relative(install.install_base)) + + self.set_undefined_options('install_egg_info', ('target', 'egginfo_dir')) + distinfo_dirname = '{}-{}.dist-info'.format( + safer_name(self.distribution.get_name()), + safer_version(self.distribution.get_version())) + distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname) + self.egg2dist(self.egginfo_dir, distinfo_dir) + + self.write_wheelfile(distinfo_dir) + + # Make the archive + if not os.path.exists(self.dist_dir): + os.makedirs(self.dist_dir) + + wheel_path = os.path.join(self.dist_dir, archive_basename + '.whl') + with WheelFile(wheel_path, 'w') as wf: + wf.write_files(archive_root) + + # Add to 'Distribution.dist_files' so that the "upload" command works + getattr(self.distribution, 'dist_files', []).append( + ('bdist_wheel', get_python_version(), wheel_path)) + + if not self.keep_temp: + logger.info('removing %s', self.bdist_dir) + if not self.dry_run: + rmtree(self.bdist_dir) + + def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'): + from email.message import Message + msg = Message() + msg['Wheel-Version'] = '1.0' # of the spec + msg['Generator'] = generator + msg['Root-Is-Purelib'] = str(self.root_is_pure).lower() + if self.build_number is not None: + msg['Build'] = self.build_number + + # Doesn't work for bdist_wininst + impl_tag, abi_tag, plat_tag = self.get_tag() + for impl in impl_tag.split('.'): + for abi in abi_tag.split('.'): + for plat in plat_tag.split('.'): + msg['Tag'] = '-'.join((impl, abi, plat)) + + wheelfile_path = os.path.join(wheelfile_base, 'WHEEL') + logger.info('creating %s', wheelfile_path) + with open(wheelfile_path, 'w') as f: + Generator(f, maxheaderlen=0).flatten(msg) + + def _ensure_relative(self, path): + # copied from dir_util, deleted + drive, path = os.path.splitdrive(path) + if path[0:1] == os.sep: + path = drive + path[1:] + return path + + @property + def license_paths(self): + metadata = self.distribution.get_option_dict('metadata') + files = set() + patterns = sorted({ + option for option in metadata.get('license_files', ('', ''))[1].split() + }) + + if 'license_file' in metadata: + warn('The "license_file" option is deprecated. Use "license_files" instead.', + DeprecationWarning) + files.add(metadata['license_file'][1]) + + if 'license_file' not in metadata and 'license_files' not in metadata: + patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') + + for pattern in patterns: + for path in iglob(pattern): + if path not in files and os.path.isfile(path): + logger.info('adding license file "%s" (matched pattern "%s")', path, pattern) + files.add(path) + + return files + + def egg2dist(self, egginfo_path, distinfo_path): + """Convert an .egg-info directory into a .dist-info directory""" + def adios(p): + """Appropriately delete directory, file or link.""" + if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p): + shutil.rmtree(p) + elif os.path.exists(p): + os.unlink(p) + + adios(distinfo_path) + + if not os.path.exists(egginfo_path): + # There is no egg-info. This is probably because the egg-info + # file/directory is not named matching the distribution name used + # to name the archive file. Check for this case and report + # accordingly. + import glob + pat = os.path.join(os.path.dirname(egginfo_path), '*.egg-info') + possible = glob.glob(pat) + err = "Egg metadata expected at %s but not found" % (egginfo_path,) + if possible: + alt = os.path.basename(possible[0]) + err += " (%s found - possible misnamed archive file?)" % (alt,) + + raise ValueError(err) + + if os.path.isfile(egginfo_path): + # .egg-info is a single file + pkginfo_path = egginfo_path + pkg_info = pkginfo_to_metadata(egginfo_path, egginfo_path) + os.mkdir(distinfo_path) + else: + # .egg-info is a directory + pkginfo_path = os.path.join(egginfo_path, 'PKG-INFO') + pkg_info = pkginfo_to_metadata(egginfo_path, pkginfo_path) + + # ignore common egg metadata that is useless to wheel + shutil.copytree(egginfo_path, distinfo_path, + ignore=lambda x, y: {'PKG-INFO', 'requires.txt', 'SOURCES.txt', + 'not-zip-safe'} + ) + + # delete dependency_links if it is only whitespace + dependency_links_path = os.path.join(distinfo_path, 'dependency_links.txt') + with open(dependency_links_path, 'r') as dependency_links_file: + dependency_links = dependency_links_file.read().strip() + if not dependency_links: + adios(dependency_links_path) + + write_pkg_info(os.path.join(distinfo_path, 'METADATA'), pkg_info) + + for license_path in self.license_paths: + filename = os.path.basename(license_path) + shutil.copy(license_path, os.path.join(distinfo_path, filename)) + + adios(egginfo_path) diff --git a/winvenv/Lib/site-packages/wheel/cli/__init__.py b/winvenv/Lib/site-packages/wheel/cli/__init__.py new file mode 100644 index 0000000..635f40f --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/cli/__init__.py @@ -0,0 +1,87 @@ +""" +Wheel command-line utility. +""" + +from __future__ import print_function + +import argparse +import os +import sys + + +def require_pkgresources(name): + try: + import pkg_resources # noqa: F401 + except ImportError: + raise RuntimeError("'{0}' needs pkg_resources (part of setuptools).".format(name)) + + +class WheelError(Exception): + pass + + +def unpack_f(args): + from .unpack import unpack + unpack(args.wheelfile, args.dest) + + +def pack_f(args): + from .pack import pack + pack(args.directory, args.dest_dir) + + +def convert_f(args): + from .convert import convert + convert(args.files, args.dest_dir, args.verbose) + + +def version_f(args): + from .. import __version__ + print("wheel %s" % __version__) + + +def parser(): + p = argparse.ArgumentParser() + s = p.add_subparsers(help="commands") + + unpack_parser = s.add_parser('unpack', help='Unpack wheel') + unpack_parser.add_argument('--dest', '-d', help='Destination directory', + default='.') + unpack_parser.add_argument('wheelfile', help='Wheel file') + unpack_parser.set_defaults(func=unpack_f) + + repack_parser = s.add_parser('pack', help='Repack wheel') + repack_parser.add_argument('directory', help='Root directory of the unpacked wheel') + repack_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, + help="Directory to store the wheel (default %(default)s)") + repack_parser.set_defaults(func=pack_f) + + convert_parser = s.add_parser('convert', help='Convert egg or wininst to wheel') + convert_parser.add_argument('files', nargs='*', help='Files to convert') + convert_parser.add_argument('--dest-dir', '-d', default=os.path.curdir, + help="Directory to store wheels (default %(default)s)") + convert_parser.add_argument('--verbose', '-v', action='store_true') + convert_parser.set_defaults(func=convert_f) + + version_parser = s.add_parser('version', help='Print version and exit') + version_parser.set_defaults(func=version_f) + + help_parser = s.add_parser('help', help='Show this help') + help_parser.set_defaults(func=lambda args: p.print_help()) + + return p + + +def main(): + p = parser() + args = p.parse_args() + if not hasattr(args, 'func'): + p.print_help() + else: + try: + args.func(args) + return 0 + except WheelError as e: + print(e, file=sys.stderr) + + return 1 diff --git a/winvenv/Lib/site-packages/wheel/cli/convert.py b/winvenv/Lib/site-packages/wheel/cli/convert.py new file mode 100644 index 0000000..f1a793a --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/cli/convert.py @@ -0,0 +1,269 @@ +import os.path +import re +import shutil +import sys +import tempfile +import zipfile +from distutils import dist +from glob import iglob + +from ..bdist_wheel import bdist_wheel +from ..wheelfile import WheelFile +from . import WheelError, require_pkgresources + +egg_info_re = re.compile(r''' + (?P.+?)-(?P.+?) + (-(?Ppy\d\.\d) + (-(?P.+?))? + )?.egg$''', re.VERBOSE) + + +class _bdist_wheel_tag(bdist_wheel): + # allow the client to override the default generated wheel tag + # The default bdist_wheel implementation uses python and abi tags + # of the running python process. This is not suitable for + # generating/repackaging prebuild binaries. + + full_tag_supplied = False + full_tag = None # None or a (pytag, soabitag, plattag) triple + + def get_tag(self): + if self.full_tag_supplied and self.full_tag is not None: + return self.full_tag + else: + return bdist_wheel.get_tag(self) + + +def egg2wheel(egg_path, dest_dir): + filename = os.path.basename(egg_path) + match = egg_info_re.match(filename) + if not match: + raise WheelError('Invalid egg file name: {}'.format(filename)) + + egg_info = match.groupdict() + dir = tempfile.mkdtemp(suffix="_e2w") + if os.path.isfile(egg_path): + # assume we have a bdist_egg otherwise + with zipfile.ZipFile(egg_path) as egg: + egg.extractall(dir) + else: + # support buildout-style installed eggs directories + for pth in os.listdir(egg_path): + src = os.path.join(egg_path, pth) + if os.path.isfile(src): + shutil.copy2(src, dir) + else: + shutil.copytree(src, os.path.join(dir, pth)) + + pyver = egg_info['pyver'] + if pyver: + pyver = egg_info['pyver'] = pyver.replace('.', '') + + arch = (egg_info['arch'] or 'any').replace('.', '_').replace('-', '_') + + # assume all binary eggs are for CPython + abi = 'cp' + pyver[2:] if arch != 'any' else 'none' + + root_is_purelib = egg_info['arch'] is None + if root_is_purelib: + bw = bdist_wheel(dist.Distribution()) + else: + bw = _bdist_wheel_tag(dist.Distribution()) + + bw.root_is_pure = root_is_purelib + bw.python_tag = pyver + bw.plat_name_supplied = True + bw.plat_name = egg_info['arch'] or 'any' + if not root_is_purelib: + bw.full_tag_supplied = True + bw.full_tag = (pyver, abi, arch) + + dist_info_dir = os.path.join(dir, '{name}-{ver}.dist-info'.format(**egg_info)) + bw.egg2dist(os.path.join(dir, 'EGG-INFO'), dist_info_dir) + bw.write_wheelfile(dist_info_dir, generator='egg2wheel') + wheel_name = '{name}-{ver}-{pyver}-{}-{}.whl'.format(abi, arch, **egg_info) + with WheelFile(os.path.join(dest_dir, wheel_name), 'w') as wf: + wf.write_files(dir) + + shutil.rmtree(dir) + + +def parse_wininst_info(wininfo_name, egginfo_name): + """Extract metadata from filenames. + + Extracts the 4 metadataitems needed (name, version, pyversion, arch) from + the installer filename and the name of the egg-info directory embedded in + the zipfile (if any). + + The egginfo filename has the format:: + + name-ver(-pyver)(-arch).egg-info + + The installer filename has the format:: + + name-ver.arch(-pyver).exe + + Some things to note: + + 1. The installer filename is not definitive. An installer can be renamed + and work perfectly well as an installer. So more reliable data should + be used whenever possible. + 2. The egg-info data should be preferred for the name and version, because + these come straight from the distutils metadata, and are mandatory. + 3. The pyver from the egg-info data should be ignored, as it is + constructed from the version of Python used to build the installer, + which is irrelevant - the installer filename is correct here (even to + the point that when it's not there, any version is implied). + 4. The architecture must be taken from the installer filename, as it is + not included in the egg-info data. + 5. Architecture-neutral installers still have an architecture because the + installer format itself (being executable) is architecture-specific. We + should therefore ignore the architecture if the content is pure-python. + """ + + egginfo = None + if egginfo_name: + egginfo = egg_info_re.search(egginfo_name) + if not egginfo: + raise ValueError("Egg info filename %s is not valid" % (egginfo_name,)) + + # Parse the wininst filename + # 1. Distribution name (up to the first '-') + w_name, sep, rest = wininfo_name.partition('-') + if not sep: + raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) + + # Strip '.exe' + rest = rest[:-4] + # 2. Python version (from the last '-', must start with 'py') + rest2, sep, w_pyver = rest.rpartition('-') + if sep and w_pyver.startswith('py'): + rest = rest2 + w_pyver = w_pyver.replace('.', '') + else: + # Not version specific - use py2.py3. While it is possible that + # pure-Python code is not compatible with both Python 2 and 3, there + # is no way of knowing from the wininst format, so we assume the best + # here (the user can always manually rename the wheel to be more + # restrictive if needed). + w_pyver = 'py2.py3' + # 3. Version and architecture + w_ver, sep, w_arch = rest.rpartition('.') + if not sep: + raise ValueError("Installer filename %s is not valid" % (wininfo_name,)) + + if egginfo: + w_name = egginfo.group('name') + w_ver = egginfo.group('ver') + + return {'name': w_name, 'ver': w_ver, 'arch': w_arch, 'pyver': w_pyver} + + +def wininst2wheel(path, dest_dir): + with zipfile.ZipFile(path) as bdw: + # Search for egg-info in the archive + egginfo_name = None + for filename in bdw.namelist(): + if '.egg-info' in filename: + egginfo_name = filename + break + + info = parse_wininst_info(os.path.basename(path), egginfo_name) + + root_is_purelib = True + for zipinfo in bdw.infolist(): + if zipinfo.filename.startswith('PLATLIB'): + root_is_purelib = False + break + if root_is_purelib: + paths = {'purelib': ''} + else: + paths = {'platlib': ''} + + dist_info = "%(name)s-%(ver)s" % info + datadir = "%s.data/" % dist_info + + # rewrite paths to trick ZipFile into extracting an egg + # XXX grab wininst .ini - between .exe, padding, and first zip file. + members = [] + egginfo_name = '' + for zipinfo in bdw.infolist(): + key, basename = zipinfo.filename.split('/', 1) + key = key.lower() + basepath = paths.get(key, None) + if basepath is None: + basepath = datadir + key.lower() + '/' + oldname = zipinfo.filename + newname = basepath + basename + zipinfo.filename = newname + del bdw.NameToInfo[oldname] + bdw.NameToInfo[newname] = zipinfo + # Collect member names, but omit '' (from an entry like "PLATLIB/" + if newname: + members.append(newname) + # Remember egg-info name for the egg2dist call below + if not egginfo_name: + if newname.endswith('.egg-info'): + egginfo_name = newname + elif '.egg-info/' in newname: + egginfo_name, sep, _ = newname.rpartition('/') + dir = tempfile.mkdtemp(suffix="_b2w") + bdw.extractall(dir, members) + + # egg2wheel + abi = 'none' + pyver = info['pyver'] + arch = (info['arch'] or 'any').replace('.', '_').replace('-', '_') + # Wininst installers always have arch even if they are not + # architecture-specific (because the format itself is). + # So, assume the content is architecture-neutral if root is purelib. + if root_is_purelib: + arch = 'any' + # If the installer is architecture-specific, it's almost certainly also + # CPython-specific. + if arch != 'any': + pyver = pyver.replace('py', 'cp') + wheel_name = '-'.join((dist_info, pyver, abi, arch)) + if root_is_purelib: + bw = bdist_wheel(dist.Distribution()) + else: + bw = _bdist_wheel_tag(dist.Distribution()) + + bw.root_is_pure = root_is_purelib + bw.python_tag = pyver + bw.plat_name_supplied = True + bw.plat_name = info['arch'] or 'any' + + if not root_is_purelib: + bw.full_tag_supplied = True + bw.full_tag = (pyver, abi, arch) + + dist_info_dir = os.path.join(dir, '%s.dist-info' % dist_info) + bw.egg2dist(os.path.join(dir, egginfo_name), dist_info_dir) + bw.write_wheelfile(dist_info_dir, generator='wininst2wheel') + + wheel_path = os.path.join(dest_dir, wheel_name) + with WheelFile(wheel_path, 'w') as wf: + wf.write_files(dir) + + shutil.rmtree(dir) + + +def convert(files, dest_dir, verbose): + # Only support wheel convert if pkg_resources is present + require_pkgresources('wheel convert') + + for pat in files: + for installer in iglob(pat): + if os.path.splitext(installer)[1] == '.egg': + conv = egg2wheel + else: + conv = wininst2wheel + + if verbose: + print("{}... ".format(installer)) + sys.stdout.flush() + + conv(installer, dest_dir) + if verbose: + print("OK") diff --git a/winvenv/Lib/site-packages/wheel/cli/install.py b/winvenv/Lib/site-packages/wheel/cli/install.py new file mode 100644 index 0000000..e69de29 diff --git a/winvenv/Lib/site-packages/wheel/cli/pack.py b/winvenv/Lib/site-packages/wheel/cli/pack.py new file mode 100644 index 0000000..45c70f2 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/cli/pack.py @@ -0,0 +1,54 @@ +from __future__ import print_function + +import os.path +import re +import sys + +from wheel.cli import WheelError +from wheel.wheelfile import WheelFile + +DIST_INFO_RE = re.compile(r"^(?P(?P.+?)-(?P\d.*?))\.dist-info$") + + +def pack(directory, dest_dir): + """Repack a previously unpacked wheel directory into a new wheel file. + + The .dist-info/WHEEL file must contain one or more tags so that the target + wheel file name can be determined. + + :param directory: The unpacked wheel directory + :param dest_dir: Destination directory (defaults to the current directory) + """ + # Find the .dist-info directory + dist_info_dirs = [fn for fn in os.listdir(directory) + if os.path.isdir(os.path.join(directory, fn)) and DIST_INFO_RE.match(fn)] + if len(dist_info_dirs) > 1: + raise WheelError('Multiple .dist-info directories found in {}'.format(directory)) + elif not dist_info_dirs: + raise WheelError('No .dist-info directories found in {}'.format(directory)) + + # Determine the target wheel filename + dist_info_dir = dist_info_dirs[0] + name_version = DIST_INFO_RE.match(dist_info_dir).group('namever') + + # Read the tags from .dist-info/WHEEL + with open(os.path.join(directory, dist_info_dir, 'WHEEL')) as f: + tags = [line.split(' ')[1].rstrip() for line in f if line.startswith('Tag: ')] + if not tags: + raise WheelError('No tags present in {}/WHEEL; cannot determine target wheel filename' + .format(dist_info_dir)) + + # Reassemble the tags for the wheel file + impls = sorted({tag.split('-')[0] for tag in tags}) + abivers = sorted({tag.split('-')[1] for tag in tags}) + platforms = sorted({tag.split('-')[2] for tag in tags}) + tagline = '-'.join(['.'.join(impls), '.'.join(abivers), '.'.join(platforms)]) + + # Repack the wheel + wheel_path = os.path.join(dest_dir, '{}-{}.whl'.format(name_version, tagline)) + with WheelFile(wheel_path, 'w') as wf: + print("Repacking wheel as {}...".format(wheel_path), end='') + sys.stdout.flush() + wf.write_files(directory) + + print('OK') diff --git a/winvenv/Lib/site-packages/wheel/cli/unpack.py b/winvenv/Lib/site-packages/wheel/cli/unpack.py new file mode 100644 index 0000000..2e9857a --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/cli/unpack.py @@ -0,0 +1,25 @@ +from __future__ import print_function + +import os.path +import sys + +from ..wheelfile import WheelFile + + +def unpack(path, dest='.'): + """Unpack a wheel. + + Wheel content will be unpacked to {dest}/{name}-{ver}, where {name} + is the package name and {ver} its version. + + :param path: The path to the wheel. + :param dest: Destination directory (default to current directory). + """ + with WheelFile(path) as wf: + namever = wf.parsed_filename.group('namever') + destination = os.path.join(dest, namever) + print("Unpacking to: {}...".format(destination), end='') + sys.stdout.flush() + wf.extractall(destination) + + print('OK') diff --git a/winvenv/Lib/site-packages/wheel/metadata.py b/winvenv/Lib/site-packages/wheel/metadata.py new file mode 100644 index 0000000..3edf6ae --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/metadata.py @@ -0,0 +1,141 @@ +""" +Tools for converting old- to new-style metadata. +""" + +import os.path +import re +import textwrap + +import pkg_resources + +from .pkginfo import read_pkg_info + +# Wheel itself is probably the only program that uses non-extras markers +# in METADATA/PKG-INFO. Support its syntax with the extra at the end only. +EXTRA_RE = re.compile( + r"""^(?P.*?)(;\s*(?P.*?)(extra == '(?P.*?)')?)$""") + + +def requires_to_requires_dist(requirement): + """Return the version specifier for a requirement in PEP 345/566 fashion.""" + if getattr(requirement, 'url', None): + return " @ " + requirement.url + + requires_dist = [] + for op, ver in requirement.specs: + requires_dist.append(op + ver) + if not requires_dist: + return '' + return " (%s)" % ','.join(sorted(requires_dist)) + + +def convert_requirements(requirements): + """Yield Requires-Dist: strings for parsed requirements strings.""" + for req in requirements: + parsed_requirement = pkg_resources.Requirement.parse(req) + spec = requires_to_requires_dist(parsed_requirement) + extras = ",".join(parsed_requirement.extras) + if extras: + extras = "[%s]" % extras + yield (parsed_requirement.project_name + extras + spec) + + +def generate_requirements(extras_require): + """ + Convert requirements from a setup()-style dictionary to ('Requires-Dist', 'requirement') + and ('Provides-Extra', 'extra') tuples. + + extras_require is a dictionary of {extra: [requirements]} as passed to setup(), + using the empty extra {'': [requirements]} to hold install_requires. + """ + for extra, depends in extras_require.items(): + condition = '' + extra = extra or '' + if ':' in extra: # setuptools extra:condition syntax + extra, condition = extra.split(':', 1) + + extra = pkg_resources.safe_extra(extra) + if extra: + yield 'Provides-Extra', extra + if condition: + condition = "(" + condition + ") and " + condition += "extra == '%s'" % extra + + if condition: + condition = ' ; ' + condition + + for new_req in convert_requirements(depends): + yield 'Requires-Dist', new_req + condition + + +def pkginfo_to_metadata(egg_info_path, pkginfo_path): + """ + Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format + """ + pkg_info = read_pkg_info(pkginfo_path) + pkg_info.replace_header('Metadata-Version', '2.1') + # Those will be regenerated from `requires.txt`. + del pkg_info['Provides-Extra'] + del pkg_info['Requires-Dist'] + requires_path = os.path.join(egg_info_path, 'requires.txt') + if os.path.exists(requires_path): + with open(requires_path) as requires_file: + requires = requires_file.read() + + parsed_requirements = sorted(pkg_resources.split_sections(requires), + key=lambda x: x[0] or '') + for extra, reqs in parsed_requirements: + for key, value in generate_requirements({extra: reqs}): + if (key, value) not in pkg_info.items(): + pkg_info[key] = value + + description = pkg_info['Description'] + if description: + pkg_info.set_payload(dedent_description(pkg_info)) + del pkg_info['Description'] + + return pkg_info + + +def pkginfo_unicode(pkg_info, field): + """Hack to coax Unicode out of an email Message() - Python 3.3+""" + text = pkg_info[field] + field = field.lower() + if not isinstance(text, str): + if not hasattr(pkg_info, 'raw_items'): # Python 3.2 + return str(text) + for item in pkg_info.raw_items(): + if item[0].lower() == field: + text = item[1].encode('ascii', 'surrogateescape') \ + .decode('utf-8') + break + + return text + + +def dedent_description(pkg_info): + """ + Dedent and convert pkg_info['Description'] to Unicode. + """ + description = pkg_info['Description'] + + # Python 3 Unicode handling, sorta. + surrogates = False + if not isinstance(description, str): + surrogates = True + description = pkginfo_unicode(pkg_info, 'Description') + + description_lines = description.splitlines() + description_dedent = '\n'.join( + # if the first line of long_description is blank, + # the first line here will be indented. + (description_lines[0].lstrip(), + textwrap.dedent('\n'.join(description_lines[1:])), + '\n')) + + if surrogates: + description_dedent = description_dedent \ + .encode("utf8") \ + .decode("ascii", "surrogateescape") + + return description_dedent diff --git a/winvenv/Lib/site-packages/wheel/pep425tags.py b/winvenv/Lib/site-packages/wheel/pep425tags.py new file mode 100644 index 0000000..13b5073 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/pep425tags.py @@ -0,0 +1,185 @@ +"""Generate and work with PEP 425 Compatibility Tags.""" + +import distutils.util +import platform +import sys +import sysconfig +import warnings + +try: + from importlib.machinery import get_all_suffixes +except ImportError: + from imp import get_suffixes as get_all_suffixes + + +def get_config_var(var): + try: + return sysconfig.get_config_var(var) + except IOError as e: # pip Issue #1074 + warnings.warn("{0}".format(e), RuntimeWarning) + return None + + +def get_abbr_impl(): + """Return abbreviated implementation name.""" + impl = platform.python_implementation() + if impl == 'PyPy': + return 'pp' + elif impl == 'Jython': + return 'jy' + elif impl == 'IronPython': + return 'ip' + elif impl == 'CPython': + return 'cp' + + raise LookupError('Unknown Python implementation: ' + impl) + + +def get_impl_ver(): + """Return implementation version.""" + impl_ver = get_config_var("py_version_nodot") + if not impl_ver or get_abbr_impl() == 'pp': + impl_ver = ''.join(map(str, get_impl_version_info())) + return impl_ver + + +def get_impl_version_info(): + """Return sys.version_info-like tuple for use in decrementing the minor + version.""" + if get_abbr_impl() == 'pp': + # as per https://github.com/pypa/pip/issues/2882 + return (sys.version_info[0], sys.pypy_version_info.major, + sys.pypy_version_info.minor) + else: + return sys.version_info[0], sys.version_info[1] + + +def get_flag(var, fallback, expected=True, warn=True): + """Use a fallback method for determining SOABI flags if the needed config + var is unset or unavailable.""" + val = get_config_var(var) + if val is None: + if warn: + warnings.warn("Config variable '{0}' is unset, Python ABI tag may " + "be incorrect".format(var), RuntimeWarning, 2) + return fallback() + return val == expected + + +def get_abi_tag(): + """Return the ABI tag based on SOABI (if available) or emulate SOABI + (CPython 2, PyPy).""" + soabi = get_config_var('SOABI') + impl = get_abbr_impl() + if not soabi and impl in ('cp', 'pp') and hasattr(sys, 'maxunicode'): + d = '' + m = '' + u = '' + if get_flag('Py_DEBUG', + lambda: hasattr(sys, 'gettotalrefcount'), + warn=(impl == 'cp')): + d = 'd' + if get_flag('WITH_PYMALLOC', + lambda: impl == 'cp', + warn=(impl == 'cp')): + m = 'm' + if get_flag('Py_UNICODE_SIZE', + lambda: sys.maxunicode == 0x10ffff, + expected=4, + warn=(impl == 'cp' and + sys.version_info < (3, 3))) \ + and sys.version_info < (3, 3): + u = 'u' + abi = '%s%s%s%s%s' % (impl, get_impl_ver(), d, m, u) + elif soabi and soabi.startswith('cpython-'): + abi = 'cp' + soabi.split('-')[1] + elif soabi: + abi = soabi.replace('.', '_').replace('-', '_') + else: + abi = None + return abi + + +def get_platform(): + """Return our platform name 'win32', 'linux_x86_64'""" + # XXX remove distutils dependency + result = distutils.util.get_platform().replace('.', '_').replace('-', '_') + if result == "linux_x86_64" and sys.maxsize == 2147483647: + # pip pull request #3497 + result = "linux_i686" + return result + + +def get_supported(versions=None, supplied_platform=None): + """Return a list of supported tags for each version specified in + `versions`. + + :param versions: a list of string versions, of the form ["33", "32"], + or None. The first version will be assumed to support our ABI. + """ + supported = [] + + # Versions must be given with respect to the preference + if versions is None: + versions = [] + version_info = get_impl_version_info() + major = version_info[:-1] + # Support all previous minor Python versions. + for minor in range(version_info[-1], -1, -1): + versions.append(''.join(map(str, major + (minor,)))) + + impl = get_abbr_impl() + + abis = [] + + abi = get_abi_tag() + if abi: + abis[0:0] = [abi] + + abi3s = set() + for suffix in get_all_suffixes(): + if suffix[0].startswith('.abi'): + abi3s.add(suffix[0].split('.', 2)[1]) + + abis.extend(sorted(list(abi3s))) + + abis.append('none') + + platforms = [] + if supplied_platform: + platforms.append(supplied_platform) + platforms.append(get_platform()) + + # Current version, current API (built specifically for our Python): + for abi in abis: + for arch in platforms: + supported.append(('%s%s' % (impl, versions[0]), abi, arch)) + + # abi3 modules compatible with older version of Python + for version in versions[1:]: + # abi3 was introduced in Python 3.2 + if version in ('31', '30'): + break + for abi in abi3s: # empty set if not Python 3 + for arch in platforms: + supported.append(("%s%s" % (impl, version), abi, arch)) + + # No abi / arch, but requires our implementation: + for i, version in enumerate(versions): + supported.append(('%s%s' % (impl, version), 'none', 'any')) + if i == 0: + # Tagged specifically as being cross-version compatible + # (with just the major version specified) + supported.append(('%s%s' % (impl, versions[0][0]), 'none', 'any')) + + # Major Python version + platform; e.g. binaries not using the Python API + for arch in platforms: + supported.append(('py%s' % (versions[0][0]), 'none', arch)) + + # No abi / arch, generic Python + for i, version in enumerate(versions): + supported.append(('py%s' % (version,), 'none', 'any')) + if i == 0: + supported.append(('py%s' % (version[0]), 'none', 'any')) + + return supported diff --git a/winvenv/Lib/site-packages/wheel/pkginfo.py b/winvenv/Lib/site-packages/wheel/pkginfo.py new file mode 100644 index 0000000..115be45 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/pkginfo.py @@ -0,0 +1,43 @@ +"""Tools for reading and writing PKG-INFO / METADATA without caring +about the encoding.""" + +from email.parser import Parser + +try: + unicode + _PY3 = False +except NameError: + _PY3 = True + +if not _PY3: + from email.generator import Generator + + def read_pkg_info_bytes(bytestr): + return Parser().parsestr(bytestr) + + def read_pkg_info(path): + with open(path, "r") as headers: + message = Parser().parse(headers) + return message + + def write_pkg_info(path, message): + with open(path, 'w') as metadata: + Generator(metadata, mangle_from_=False, maxheaderlen=0).flatten(message) +else: + from email.generator import BytesGenerator + + def read_pkg_info_bytes(bytestr): + headers = bytestr.decode(encoding="ascii", errors="surrogateescape") + message = Parser().parsestr(headers) + return message + + def read_pkg_info(path): + with open(path, "r", + encoding="ascii", + errors="surrogateescape") as headers: + message = Parser().parse(headers) + return message + + def write_pkg_info(path, message): + with open(path, "wb") as out: + BytesGenerator(out, mangle_from_=False, maxheaderlen=0).flatten(message) diff --git a/winvenv/Lib/site-packages/wheel/util.py b/winvenv/Lib/site-packages/wheel/util.py new file mode 100644 index 0000000..be0aa9b --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/util.py @@ -0,0 +1,41 @@ +import base64 +import sys + + +if sys.version_info[0] < 3: + text_type = unicode # noqa: F821 + + def native(s, encoding='utf-8'): + if isinstance(s, unicode): + return s.encode(encoding) + return s +else: + text_type = str + + def native(s, encoding='utf-8'): + if isinstance(s, bytes): + return s.decode(encoding) + return s + + +def urlsafe_b64encode(data): + """urlsafe_b64encode without padding""" + return base64.urlsafe_b64encode(data).rstrip(b'=') + + +def urlsafe_b64decode(data): + """urlsafe_b64decode without padding""" + pad = b'=' * (4 - (len(data) & 3)) + return base64.urlsafe_b64decode(data + pad) + + +def as_unicode(s): + if isinstance(s, bytes): + return s.decode('utf-8') + return s + + +def as_bytes(s): + if isinstance(s, text_type): + return s.encode('utf-8') + return s diff --git a/winvenv/Lib/site-packages/wheel/wheelfile.py b/winvenv/Lib/site-packages/wheel/wheelfile.py new file mode 100644 index 0000000..635aa77 --- /dev/null +++ b/winvenv/Lib/site-packages/wheel/wheelfile.py @@ -0,0 +1,160 @@ +from __future__ import print_function + +import hashlib +import os.path +import re +import time +from collections import OrderedDict +from distutils import log as logger +from zipfile import ZIP_DEFLATED, ZipInfo, ZipFile + +from wheel.cli import WheelError +from wheel.util import urlsafe_b64decode, as_unicode, native, urlsafe_b64encode, as_bytes + +# Non-greedy matching of an optional build number may be too clever (more +# invalid wheel filenames will match). Separate regex for .dist-info? +WHEEL_INFO_RE = re.compile( + r"""^(?P(?P.+?)-(?P.+?))(-(?P\d[^-]*))? + -(?P.+?)-(?P.+?)-(?P.+?)\.whl$""", + re.VERBOSE) + + +def get_zipinfo_datetime(timestamp=None): + # Some applications need reproducible .whl files, but they can't do this without forcing + # the timestamp of the individual ZipInfo objects. See issue #143. + timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', timestamp or time.time())) + return time.gmtime(timestamp)[0:6] + + +class WheelFile(ZipFile): + """A ZipFile derivative class that also reads SHA-256 hashes from + .dist-info/RECORD and checks any read files against those. + """ + + _default_algorithm = hashlib.sha256 + + def __init__(self, file, mode='r'): + basename = os.path.basename(file) + self.parsed_filename = WHEEL_INFO_RE.match(basename) + if not basename.endswith('.whl') or self.parsed_filename is None: + raise WheelError("Bad wheel filename {!r}".format(basename)) + + ZipFile.__init__(self, file, mode, compression=ZIP_DEFLATED, allowZip64=True) + + self.dist_info_path = '{}.dist-info'.format(self.parsed_filename.group('namever')) + self.record_path = self.dist_info_path + '/RECORD' + self._file_hashes = OrderedDict() + self._file_sizes = {} + if mode == 'r': + # Ignore RECORD and any embedded wheel signatures + self._file_hashes[self.record_path] = None, None + self._file_hashes[self.record_path + '.jws'] = None, None + self._file_hashes[self.record_path + '.p7s'] = None, None + + # Fill in the expected hashes by reading them from RECORD + try: + record = self.open(self.record_path) + except KeyError: + raise WheelError('Missing {} file'.format(self.record_path)) + + with record: + for line in record: + line = line.decode('utf-8') + path, hash_sum, size = line.rsplit(u',', 2) + if hash_sum: + algorithm, hash_sum = hash_sum.split(u'=') + try: + hashlib.new(algorithm) + except ValueError: + raise WheelError('Unsupported hash algorithm: {}'.format(algorithm)) + + if algorithm.lower() in {'md5', 'sha1'}: + raise WheelError( + 'Weak hash algorithm ({}) is not permitted by PEP 427' + .format(algorithm)) + + self._file_hashes[path] = ( + algorithm, urlsafe_b64decode(hash_sum.encode('ascii'))) + + def open(self, name_or_info, mode="r", pwd=None): + def _update_crc(newdata, eof=None): + if eof is None: + eof = ef._eof + update_crc_orig(newdata) + else: # Python 2 + update_crc_orig(newdata, eof) + + running_hash.update(newdata) + if eof and running_hash.digest() != expected_hash: + raise WheelError("Hash mismatch for file '{}'".format(native(ef_name))) + + ef = ZipFile.open(self, name_or_info, mode, pwd) + ef_name = as_unicode(name_or_info.filename if isinstance(name_or_info, ZipInfo) + else name_or_info) + if mode == 'r' and not ef_name.endswith('/'): + if ef_name not in self._file_hashes: + raise WheelError("No hash found for file '{}'".format(native(ef_name))) + + algorithm, expected_hash = self._file_hashes[ef_name] + if expected_hash is not None: + # Monkey patch the _update_crc method to also check for the hash from RECORD + running_hash = hashlib.new(algorithm) + update_crc_orig, ef._update_crc = ef._update_crc, _update_crc + + return ef + + def write_files(self, base_dir): + logger.info("creating '%s' and adding '%s' to it", self.filename, base_dir) + deferred = [] + for root, dirnames, filenames in os.walk(base_dir): + # Sort the directory names so that `os.walk` will walk them in a + # defined order on the next iteration. + dirnames.sort() + for name in sorted(filenames): + path = os.path.normpath(os.path.join(root, name)) + if os.path.isfile(path): + arcname = os.path.relpath(path, base_dir) + if arcname == self.record_path: + pass + elif root.endswith('.dist-info'): + deferred.append((path, arcname)) + else: + self.write(path, arcname) + + deferred.sort() + for path, arcname in deferred: + self.write(path, arcname) + + def write(self, filename, arcname=None, compress_type=None): + with open(filename, 'rb') as f: + st = os.fstat(f.fileno()) + data = f.read() + + zinfo = ZipInfo(arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime)) + zinfo.external_attr = st.st_mode << 16 + zinfo.compress_type = ZIP_DEFLATED + self.writestr(zinfo, data, compress_type) + + def writestr(self, zinfo_or_arcname, bytes, compress_type=None): + ZipFile.writestr(self, zinfo_or_arcname, bytes, compress_type) + fname = (zinfo_or_arcname.filename if isinstance(zinfo_or_arcname, ZipInfo) + else zinfo_or_arcname) + logger.info("adding '%s'", fname) + if fname != self.record_path: + hash_ = self._default_algorithm(bytes) + self._file_hashes[fname] = hash_.name, native(urlsafe_b64encode(hash_.digest())) + self._file_sizes[fname] = len(bytes) + + def close(self): + # Write RECORD + if self.fp is not None and self.mode == 'w' and self._file_hashes: + content = '\n'.join('{},{}={},{}'.format(fname, algorithm, hash_, + self._file_sizes[fname]) + for fname, (algorithm, hash_) in self._file_hashes.items()) + content += '\n{},,\n'.format(self.record_path) + zinfo = ZipInfo(native(self.record_path), date_time=get_zipinfo_datetime()) + zinfo.compress_type = ZIP_DEFLATED + zinfo.external_attr = 0o664 << 16 + self.writestr(zinfo, as_bytes(content)) + + ZipFile.close(self) diff --git a/winvenv/Lib/site.py b/winvenv/Lib/site.py new file mode 100644 index 0000000..dc9887a --- /dev/null +++ b/winvenv/Lib/site.py @@ -0,0 +1,833 @@ +"""Append module search paths for third-party packages to sys.path. + +**************************************************************** +* This module is automatically imported during initialization. * +**************************************************************** + +In earlier versions of Python (up to 1.5a3), scripts or modules that +needed to use site-specific modules would place ``import site'' +somewhere near the top of their code. Because of the automatic +import, this is no longer necessary (but code that does it still +works). + +This will append site-specific paths to the module search path. On +Unix, it starts with sys.prefix and sys.exec_prefix (if different) and +appends lib/python/site-packages as well as lib/site-python. +It also supports the Debian convention of +lib/python/dist-packages. On other platforms (mainly Mac and +Windows), it uses just sys.prefix (and sys.exec_prefix, if different, +but this is unlikely). The resulting directories, if they exist, are +appended to sys.path, and also inspected for path configuration files. + +FOR DEBIAN, this sys.path is augmented with directories in /usr/local. +Local addons go into /usr/local/lib/python/site-packages +(resp. /usr/local/lib/site-python), Debian addons install into +/usr/{lib,share}/python/dist-packages. + +A path configuration file is a file whose name has the form +.pth; its contents are additional directories (one per line) +to be added to sys.path. Non-existing directories (or +non-directories) are never added to sys.path; no directory is added to +sys.path more than once. Blank lines and lines beginning with +'#' are skipped. Lines starting with 'import' are executed. + +For example, suppose sys.prefix and sys.exec_prefix are set to +/usr/local and there is a directory /usr/local/lib/python2.X/site-packages +with three subdirectories, foo, bar and spam, and two path +configuration files, foo.pth and bar.pth. Assume foo.pth contains the +following: + + # foo package configuration + foo + bar + bletch + +and bar.pth contains: + + # bar package configuration + bar + +Then the following directories are added to sys.path, in this order: + + /usr/local/lib/python2.X/site-packages/bar + /usr/local/lib/python2.X/site-packages/foo + +Note that bletch is omitted because it doesn't exist; bar precedes foo +because bar.pth comes alphabetically before foo.pth; and spam is +omitted because it is not mentioned in either path configuration file. + +After these path manipulations, an attempt is made to import a module +named sitecustomize, which can perform arbitrary additional +site-specific customizations. If this import fails with an +ImportError exception, it is silently ignored. + +""" + +import os +import sys + +try: + import __builtin__ as builtins +except ImportError: + import builtins +try: + set +except NameError: + from sets import Set as set + +# Prefixes for site-packages; add additional prefixes like /usr/local here +PREFIXES = [sys.prefix, sys.exec_prefix] +# Enable per user site-packages directory +# set it to False to disable the feature or True to force the feature +ENABLE_USER_SITE = None +# for distutils.commands.install +USER_SITE = None +USER_BASE = None + +_is_64bit = (getattr(sys, "maxsize", None) or getattr(sys, "maxint")) > 2 ** 32 +_is_pypy = hasattr(sys, "pypy_version_info") +_is_jython = sys.platform[:4] == "java" +if _is_jython: + ModuleType = type(os) + + +def makepath(*paths): + dir = os.path.join(*paths) + if _is_jython and (dir == "__classpath__" or dir.startswith("__pyclasspath__")): + return dir, dir + dir = os.path.abspath(dir) + return dir, os.path.normcase(dir) + + +def abs__file__(): + """Set all module' __file__ attribute to an absolute path""" + for m in sys.modules.values(): + if (_is_jython and not isinstance(m, ModuleType)) or hasattr(m, "__loader__"): + # only modules need the abspath in Jython. and don't mess + # with a PEP 302-supplied __file__ + continue + f = getattr(m, "__file__", None) + if f is None: + continue + m.__file__ = os.path.abspath(f) + + +def removeduppaths(): + """ Remove duplicate entries from sys.path along with making them + absolute""" + # This ensures that the initial path provided by the interpreter contains + # only absolute pathnames, even if we're running from the build directory. + L = [] + known_paths = set() + for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in known_paths: + L.append(dir) + known_paths.add(dircase) + sys.path[:] = L + return known_paths + + +# XXX This should not be part of site.py, since it is needed even when +# using the -S option for Python. See http://www.python.org/sf/586680 +def addbuilddir(): + """Append ./build/lib. in case we're running in the build dir + (especially for Guido :-)""" + from distutils.util import get_platform + + s = "build/lib.{}-{:.3}".format(get_platform(), sys.version) + if hasattr(sys, "gettotalrefcount"): + s += "-pydebug" + s = os.path.join(os.path.dirname(sys.path[-1]), s) + sys.path.append(s) + + +def _init_pathinfo(): + """Return a set containing all existing directory entries from sys.path""" + d = set() + for dir in sys.path: + try: + if os.path.isdir(dir): + dir, dircase = makepath(dir) + d.add(dircase) + except TypeError: + continue + return d + + +def addpackage(sitedir, name, known_paths): + """Add a new path to known_paths by combining sitedir and 'name' or execute + sitedir if it starts with 'import'""" + if known_paths is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname, "r") + except IOError: + return + try: + for line in f: + if line.startswith("#"): + continue + if line.startswith("import"): + exec(line) + continue + line = line.rstrip() + dir, dircase = makepath(sitedir, line) + if not dircase in known_paths and os.path.exists(dir): + sys.path.append(dir) + known_paths.add(dircase) + finally: + f.close() + if reset: + known_paths = None + return known_paths + + +def addsitedir(sitedir, known_paths=None): + """Add 'sitedir' argument to sys.path if missing and handle .pth files in + 'sitedir'""" + if known_paths is None: + known_paths = _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in known_paths: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name.endswith(os.extsep + "pth"): + addpackage(sitedir, name, known_paths) + if reset: + known_paths = None + return known_paths + + +def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix): + """Add site-packages (and possibly site-python) to sys.path""" + prefixes = [os.path.join(sys_prefix, "local"), sys_prefix] + if exec_prefix != sys_prefix: + prefixes.append(os.path.join(exec_prefix, "local")) + + for prefix in prefixes: + if prefix: + if sys.platform in ("os2emx", "riscos") or _is_jython: + sitedirs = [os.path.join(prefix, "Lib", "site-packages")] + elif _is_pypy: + sitedirs = [os.path.join(prefix, "site-packages")] + elif sys.platform == "darwin" and prefix == sys_prefix: + + if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python + + sitedirs = [ + os.path.join("/Library/Python", sys.version[:3], "site-packages"), + os.path.join(prefix, "Extras", "lib", "python"), + ] + + else: # any other Python distros on OSX work this way + sitedirs = [os.path.join(prefix, "lib", "python" + sys.version[:3], "site-packages")] + + elif os.sep == "/": + sitedirs = [ + os.path.join(prefix, "lib", "python" + sys.version[:3], "site-packages"), + os.path.join(prefix, "lib", "site-python"), + os.path.join(prefix, "python" + sys.version[:3], "lib-dynload"), + ] + lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages") + if os.path.exists(lib64_dir) and os.path.realpath(lib64_dir) not in [ + os.path.realpath(p) for p in sitedirs + ]: + if _is_64bit: + sitedirs.insert(0, lib64_dir) + else: + sitedirs.append(lib64_dir) + try: + # sys.getobjects only available in --with-pydebug build + sys.getobjects + sitedirs.insert(0, os.path.join(sitedirs[0], "debug")) + except AttributeError: + pass + # Debian-specific dist-packages directories: + sitedirs.append(os.path.join(prefix, "local/lib", "python" + sys.version[:3], "dist-packages")) + if sys.version[0] == "2": + sitedirs.append(os.path.join(prefix, "lib", "python" + sys.version[:3], "dist-packages")) + else: + sitedirs.append(os.path.join(prefix, "lib", "python" + sys.version[0], "dist-packages")) + sitedirs.append(os.path.join(prefix, "lib", "dist-python")) + else: + sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] + if sys.platform == "darwin": + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if "Python.framework" in prefix: + home = os.environ.get("HOME") + if home: + sitedirs.append(os.path.join(home, "Library", "Python", sys.version[:3], "site-packages")) + for sitedir in sitedirs: + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + return None + + +def check_enableusersite(): + """Check if user site directory is safe for inclusion + + The function tests for the command line flag (including environment var), + process uid/gid equal to effective uid/gid. + + None: Disabled for security reasons + False: Disabled by user (command line option) + True: Safe and enabled + """ + if hasattr(sys, "flags") and getattr(sys.flags, "no_user_site", False): + return False + + if hasattr(os, "getuid") and hasattr(os, "geteuid"): + # check process uid == effective uid + if os.geteuid() != os.getuid(): + return None + if hasattr(os, "getgid") and hasattr(os, "getegid"): + # check process gid == effective gid + if os.getegid() != os.getgid(): + return None + + return True + + +def addusersitepackages(known_paths): + """Add a per user site-package to sys.path + + Each user has its own python directory with site-packages in the + home directory. + + USER_BASE is the root directory for all Python versions + + USER_SITE is the user specific site-packages directory + + USER_SITE/.. can be used for data. + """ + global USER_BASE, USER_SITE, ENABLE_USER_SITE + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + # if sys.platform in ('os2emx', 'riscos'): + # # Don't know what to put here + # USER_BASE = '' + # USER_SITE = '' + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser(base, "Python") + USER_SITE = os.path.join(USER_BASE, "Python" + sys.version[0] + sys.version[2], "site-packages") + else: + if env_base: + USER_BASE = env_base + else: + USER_BASE = joinuser("~", ".local") + USER_SITE = os.path.join(USER_BASE, "lib", "python" + sys.version[:3], "site-packages") + + if ENABLE_USER_SITE and os.path.isdir(USER_SITE): + addsitedir(USER_SITE, known_paths) + if ENABLE_USER_SITE: + for dist_libdir in ("lib", "local/lib"): + user_site = os.path.join(USER_BASE, dist_libdir, "python" + sys.version[:3], "dist-packages") + if os.path.isdir(user_site): + addsitedir(user_site, known_paths) + return known_paths + + +def setBEGINLIBPATH(): + """The OS/2 EMX port has optional extension modules that do double duty + as DLLs (and must use the .DLL file extension) for other extensions. + The library search path needs to be amended so these will be found + during module import. Use BEGINLIBPATH so that these are at the start + of the library search path. + + """ + dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") + libpath = os.environ["BEGINLIBPATH"].split(";") + if libpath[-1]: + libpath.append(dllpath) + else: + libpath[-1] = dllpath + os.environ["BEGINLIBPATH"] = ";".join(libpath) + + +def setquit(): + """Define new built-ins 'quit' and 'exit'. + These are simply strings that display a hint on how to exit. + + """ + if os.sep == ":": + eof = "Cmd-Q" + elif os.sep == "\\": + eof = "Ctrl-Z plus Return" + else: + eof = "Ctrl-D (i.e. EOF)" + + class Quitter(object): + def __init__(self, name): + self.name = name + + def __repr__(self): + return "Use {}() or {} to exit".format(self.name, eof) + + def __call__(self, code=None): + # Shells like IDLE catch the SystemExit, but listen when their + # stdin wrapper is closed. + try: + sys.stdin.close() + except: + pass + raise SystemExit(code) + + builtins.quit = Quitter("quit") + builtins.exit = Quitter("exit") + + +class _Printer(object): + """interactive prompt objects for printing the license text, a list of + contributors and the copyright notice.""" + + MAXLINES = 23 + + def __init__(self, name, data, files=(), dirs=()): + self.__name = name + self.__data = data + self.__files = files + self.__dirs = dirs + self.__lines = None + + def __setup(self): + if self.__lines: + return + data = None + for dir in self.__dirs: + for filename in self.__files: + filename = os.path.join(dir, filename) + try: + fp = open(filename, "r") + data = fp.read() + fp.close() + break + except IOError: + pass + if data: + break + if not data: + data = self.__data + self.__lines = data.split("\n") + self.__linecnt = len(self.__lines) + + def __repr__(self): + self.__setup() + if len(self.__lines) <= self.MAXLINES: + return "\n".join(self.__lines) + else: + return "Type %s() to see the full %s text" % ((self.__name,) * 2) + + def __call__(self): + self.__setup() + prompt = "Hit Return for more, or q (and Return) to quit: " + lineno = 0 + while 1: + try: + for i in range(lineno, lineno + self.MAXLINES): + print(self.__lines[i]) + except IndexError: + break + else: + lineno += self.MAXLINES + key = None + while key is None: + try: + key = raw_input(prompt) + except NameError: + key = input(prompt) + if key not in ("", "q"): + key = None + if key == "q": + break + + +def setcopyright(): + """Set 'copyright' and 'credits' in __builtin__""" + builtins.copyright = _Printer("copyright", sys.copyright) + if _is_jython: + builtins.credits = _Printer("credits", "Jython is maintained by the Jython developers (www.jython.org).") + elif _is_pypy: + builtins.credits = _Printer("credits", "PyPy is maintained by the PyPy developers: http://pypy.org/") + else: + builtins.credits = _Printer( + "credits", + """\ + Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands + for supporting Python development. See www.python.org for more information.""", + ) + here = os.path.dirname(os.__file__) + builtins.license = _Printer( + "license", + "See http://www.python.org/%.3s/license.html" % sys.version, + ["LICENSE.txt", "LICENSE"], + [os.path.join(here, os.pardir), here, os.curdir], + ) + + +class _Helper(object): + """Define the built-in 'help'. + This is a wrapper around pydoc.help (with a twist). + + """ + + def __repr__(self): + return "Type help() for interactive help, " "or help(object) for help about object." + + def __call__(self, *args, **kwds): + import pydoc + + return pydoc.help(*args, **kwds) + + +def sethelper(): + builtins.help = _Helper() + + +def aliasmbcs(): + """On Windows, some default encodings are not provided by Python, + while they are always available as "mbcs" in each locale. Make + them usable by aliasing to "mbcs" in such a case.""" + if sys.platform == "win32": + import locale, codecs + + enc = locale.getdefaultlocale()[1] + if enc.startswith("cp"): # "cp***" ? + try: + codecs.lookup(enc) + except LookupError: + import encodings + + encodings._cache[enc] = encodings._unknown + encodings.aliases.aliases[enc] = "mbcs" + + +def setencoding(): + """Set the string encoding used by the Unicode implementation. The + default is 'ascii', but if you're willing to experiment, you can + change this.""" + encoding = "ascii" # Default value set by _PyUnicode_Init() + if 0: + # Enable to support locale aware default string encodings. + import locale + + loc = locale.getdefaultlocale() + if loc[1]: + encoding = loc[1] + if 0: + # Enable to switch off string to Unicode coercion and implicit + # Unicode to string conversion. + encoding = "undefined" + if encoding != "ascii": + # On Non-Unicode builds this will raise an AttributeError... + sys.setdefaultencoding(encoding) # Needs Python Unicode build ! + + +def execsitecustomize(): + """Run custom site specific code, if available.""" + try: + import sitecustomize + except ImportError: + pass + + +def virtual_install_main_packages(): + f = open(os.path.join(os.path.dirname(__file__), "orig-prefix.txt")) + sys.real_prefix = f.read().strip() + f.close() + pos = 2 + hardcoded_relative_dirs = [] + if sys.path[0] == "": + pos += 1 + if _is_jython: + paths = [os.path.join(sys.real_prefix, "Lib")] + elif _is_pypy: + if sys.version_info > (3, 2): + cpyver = "%d" % sys.version_info[0] + elif sys.pypy_version_info >= (1, 5): + cpyver = "%d.%d" % sys.version_info[:2] + else: + cpyver = "%d.%d.%d" % sys.version_info[:3] + paths = [os.path.join(sys.real_prefix, "lib_pypy"), os.path.join(sys.real_prefix, "lib-python", cpyver)] + if sys.pypy_version_info < (1, 9): + paths.insert(1, os.path.join(sys.real_prefix, "lib-python", "modified-%s" % cpyver)) + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + # + # This is hardcoded in the Python executable, but relative to sys.prefix: + for path in paths[:]: + plat_path = os.path.join(path, "plat-%s" % sys.platform) + if os.path.exists(plat_path): + paths.append(plat_path) + elif sys.platform == "win32": + paths = [os.path.join(sys.real_prefix, "Lib"), os.path.join(sys.real_prefix, "DLLs")] + else: + paths = [os.path.join(sys.real_prefix, "lib", "python" + sys.version[:3])] + hardcoded_relative_dirs = paths[:] # for the special 'darwin' case below + lib64_path = os.path.join(sys.real_prefix, "lib64", "python" + sys.version[:3]) + if os.path.exists(lib64_path): + if _is_64bit: + paths.insert(0, lib64_path) + else: + paths.append(lib64_path) + # This is hardcoded in the Python executable, but relative to + # sys.prefix. Debian change: we need to add the multiarch triplet + # here, which is where the real stuff lives. As per PEP 421, in + # Python 3.3+, this lives in sys.implementation, while in Python 2.7 + # it lives in sys. + try: + arch = getattr(sys, "implementation", sys)._multiarch + except AttributeError: + # This is a non-multiarch aware Python. Fallback to the old way. + arch = sys.platform + plat_path = os.path.join(sys.real_prefix, "lib", "python" + sys.version[:3], "plat-%s" % arch) + if os.path.exists(plat_path): + paths.append(plat_path) + # This is hardcoded in the Python executable, but + # relative to sys.prefix, so we have to fix up: + for path in list(paths): + tk_dir = os.path.join(path, "lib-tk") + if os.path.exists(tk_dir): + paths.append(tk_dir) + + # These are hardcoded in the Apple's Python executable, + # but relative to sys.prefix, so we have to fix them up: + if sys.platform == "darwin": + hardcoded_paths = [ + os.path.join(relative_dir, module) + for relative_dir in hardcoded_relative_dirs + for module in ("plat-darwin", "plat-mac", "plat-mac/lib-scriptpackages") + ] + + for path in hardcoded_paths: + if os.path.exists(path): + paths.append(path) + + sys.path.extend(paths) + + +def force_global_eggs_after_local_site_packages(): + """ + Force easy_installed eggs in the global environment to get placed + in sys.path after all packages inside the virtualenv. This + maintains the "least surprise" result that packages in the + virtualenv always mask global packages, never the other way + around. + + """ + egginsert = getattr(sys, "__egginsert", 0) + for i, path in enumerate(sys.path): + if i > egginsert and path.startswith(sys.prefix): + egginsert = i + sys.__egginsert = egginsert + 1 + + +def virtual_addsitepackages(known_paths): + force_global_eggs_after_local_site_packages() + return addsitepackages(known_paths, sys_prefix=sys.real_prefix) + + +def fixclasspath(): + """Adjust the special classpath sys.path entries for Jython. These + entries should follow the base virtualenv lib directories. + """ + paths = [] + classpaths = [] + for path in sys.path: + if path == "__classpath__" or path.startswith("__pyclasspath__"): + classpaths.append(path) + else: + paths.append(path) + sys.path = paths + sys.path.extend(classpaths) + + +def execusercustomize(): + """Run custom user specific code, if available.""" + try: + import usercustomize + except ImportError: + pass + + +def enablerlcompleter(): + """Enable default readline configuration on interactive prompts, by + registering a sys.__interactivehook__. + If the readline module can be imported, the hook will set the Tab key + as completion key and register ~/.python_history as history file. + This can be overridden in the sitecustomize or usercustomize module, + or in a PYTHONSTARTUP file. + """ + + def register_readline(): + import atexit + + try: + import readline + import rlcompleter + except ImportError: + return + + # Reading the initialization (config) file may not be enough to set a + # completion key, so we set one first and then read the file. + readline_doc = getattr(readline, "__doc__", "") + if readline_doc is not None and "libedit" in readline_doc: + readline.parse_and_bind("bind ^I rl_complete") + else: + readline.parse_and_bind("tab: complete") + + try: + readline.read_init_file() + except OSError: + # An OSError here could have many causes, but the most likely one + # is that there's no .inputrc file (or .editrc file in the case of + # Mac OS X + libedit) in the expected location. In that case, we + # want to ignore the exception. + pass + + if readline.get_current_history_length() == 0: + # If no history was loaded, default to .python_history. + # The guard is necessary to avoid doubling history size at + # each interpreter exit when readline was already configured + # through a PYTHONSTARTUP hook, see: + # http://bugs.python.org/issue5845#msg198636 + history = os.path.join(os.path.expanduser("~"), ".python_history") + try: + readline.read_history_file(history) + except OSError: + pass + + def write_history(): + try: + readline.write_history_file(history) + except (FileNotFoundError, PermissionError): + # home directory does not exist or is not writable + # https://bugs.python.org/issue19891 + pass + + atexit.register(write_history) + + sys.__interactivehook__ = register_readline + + +def main(): + global ENABLE_USER_SITE + virtual_install_main_packages() + abs__file__() + paths_in_sys = removeduppaths() + if os.name == "posix" and sys.path and os.path.basename(sys.path[-1]) == "Modules": + addbuilddir() + if _is_jython: + fixclasspath() + GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), "no-global-site-packages.txt")) + if not GLOBAL_SITE_PACKAGES: + ENABLE_USER_SITE = False + if ENABLE_USER_SITE is None: + ENABLE_USER_SITE = check_enableusersite() + paths_in_sys = addsitepackages(paths_in_sys) + paths_in_sys = addusersitepackages(paths_in_sys) + if GLOBAL_SITE_PACKAGES: + paths_in_sys = virtual_addsitepackages(paths_in_sys) + if sys.platform == "os2emx": + setBEGINLIBPATH() + setquit() + setcopyright() + sethelper() + if sys.version_info[0] == 3: + enablerlcompleter() + aliasmbcs() + setencoding() + execsitecustomize() + if ENABLE_USER_SITE: + execusercustomize() + # Remove sys.setdefaultencoding() so that users cannot change the + # encoding after initialization. The test for presence is needed when + # this module is run as a script, because this code is executed twice. + if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding + + +main() + + +def _script(): + help = """\ + %s [--user-base] [--user-site] + + Without arguments print some useful information + With arguments print the value of USER_BASE and/or USER_SITE separated + by '%s'. + + Exit codes with --user-base or --user-site: + 0 - user site directory is enabled + 1 - user site directory is disabled by user + 2 - uses site directory is disabled by super user + or for security reasons + >2 - unknown error + """ + args = sys.argv[1:] + if not args: + print("sys.path = [") + for dir in sys.path: + print(" {!r},".format(dir)) + print("]") + + def exists(path): + if os.path.isdir(path): + return "exists" + else: + return "doesn't exist" + + print("USER_BASE: {!r} ({})".format(USER_BASE, exists(USER_BASE))) + print("USER_SITE: {!r} ({})".format(USER_SITE, exists(USER_BASE))) + print("ENABLE_USER_SITE: %r" % ENABLE_USER_SITE) + sys.exit(0) + + buffer = [] + if "--user-base" in args: + buffer.append(USER_BASE) + if "--user-site" in args: + buffer.append(USER_SITE) + + if buffer: + print(os.pathsep.join(buffer)) + if ENABLE_USER_SITE: + sys.exit(0) + elif ENABLE_USER_SITE is False: + sys.exit(1) + elif ENABLE_USER_SITE is None: + sys.exit(2) + else: + sys.exit(3) + else: + import textwrap + + print(textwrap.dedent(help % (sys.argv[0], os.pathsep))) + sys.exit(10) + + +if __name__ == "__main__": + _script() diff --git a/winvenv/Lib/sre_compile.py b/winvenv/Lib/sre_compile.py new file mode 100644 index 0000000..e5216b7 --- /dev/null +++ b/winvenv/Lib/sre_compile.py @@ -0,0 +1,784 @@ +# +# Secret Labs' Regular Expression Engine +# +# convert template to internal format +# +# Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. +# +# See the sre.py file for information on usage and redistribution. +# + +"""Internal support module for sre""" + +import _sre +import sre_parse +from sre_constants import * + +assert _sre.MAGIC == MAGIC, "SRE module mismatch" + +_LITERAL_CODES = {LITERAL, NOT_LITERAL} +_REPEATING_CODES = {REPEAT, MIN_REPEAT, MAX_REPEAT} +_SUCCESS_CODES = {SUCCESS, FAILURE} +_ASSERT_CODES = {ASSERT, ASSERT_NOT} +_UNIT_CODES = _LITERAL_CODES | {ANY, IN} + +# Sets of lowercase characters which have the same uppercase. +_equivalences = ( + # LATIN SMALL LETTER I, LATIN SMALL LETTER DOTLESS I + (0x69, 0x131), # iı + # LATIN SMALL LETTER S, LATIN SMALL LETTER LONG S + (0x73, 0x17f), # sſ + # MICRO SIGN, GREEK SMALL LETTER MU + (0xb5, 0x3bc), # µμ + # COMBINING GREEK YPOGEGRAMMENI, GREEK SMALL LETTER IOTA, GREEK PROSGEGRAMMENI + (0x345, 0x3b9, 0x1fbe), # \u0345ιι + # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS, GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA + (0x390, 0x1fd3), # ΐΐ + # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS, GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA + (0x3b0, 0x1fe3), # ΰΰ + # GREEK SMALL LETTER BETA, GREEK BETA SYMBOL + (0x3b2, 0x3d0), # βϐ + # GREEK SMALL LETTER EPSILON, GREEK LUNATE EPSILON SYMBOL + (0x3b5, 0x3f5), # εϵ + # GREEK SMALL LETTER THETA, GREEK THETA SYMBOL + (0x3b8, 0x3d1), # θϑ + # GREEK SMALL LETTER KAPPA, GREEK KAPPA SYMBOL + (0x3ba, 0x3f0), # κϰ + # GREEK SMALL LETTER PI, GREEK PI SYMBOL + (0x3c0, 0x3d6), # πϖ + # GREEK SMALL LETTER RHO, GREEK RHO SYMBOL + (0x3c1, 0x3f1), # ρϱ + # GREEK SMALL LETTER FINAL SIGMA, GREEK SMALL LETTER SIGMA + (0x3c2, 0x3c3), # ςσ + # GREEK SMALL LETTER PHI, GREEK PHI SYMBOL + (0x3c6, 0x3d5), # φϕ + # LATIN SMALL LETTER S WITH DOT ABOVE, LATIN SMALL LETTER LONG S WITH DOT ABOVE + (0x1e61, 0x1e9b), # ṡẛ + # LATIN SMALL LIGATURE LONG S T, LATIN SMALL LIGATURE ST + (0xfb05, 0xfb06), # ſtst +) + +# Maps the lowercase code to lowercase codes which have the same uppercase. +_ignorecase_fixes = {i: tuple(j for j in t if i != j) + for t in _equivalences for i in t} + +def _combine_flags(flags, add_flags, del_flags, + TYPE_FLAGS=sre_parse.TYPE_FLAGS): + if add_flags & TYPE_FLAGS: + flags &= ~TYPE_FLAGS + return (flags | add_flags) & ~del_flags + +def _compile(code, pattern, flags): + # internal: compile a (sub)pattern + emit = code.append + _len = len + LITERAL_CODES = _LITERAL_CODES + REPEATING_CODES = _REPEATING_CODES + SUCCESS_CODES = _SUCCESS_CODES + ASSERT_CODES = _ASSERT_CODES + iscased = None + tolower = None + fixes = None + if flags & SRE_FLAG_IGNORECASE and not flags & SRE_FLAG_LOCALE: + if flags & SRE_FLAG_UNICODE and not flags & SRE_FLAG_ASCII: + iscased = _sre.unicode_iscased + tolower = _sre.unicode_tolower + fixes = _ignorecase_fixes + else: + iscased = _sre.ascii_iscased + tolower = _sre.ascii_tolower + for op, av in pattern: + if op in LITERAL_CODES: + if not flags & SRE_FLAG_IGNORECASE: + emit(op) + emit(av) + elif flags & SRE_FLAG_LOCALE: + emit(OP_LOCALE_IGNORE[op]) + emit(av) + elif not iscased(av): + emit(op) + emit(av) + else: + lo = tolower(av) + if not fixes: # ascii + emit(OP_IGNORE[op]) + emit(lo) + elif lo not in fixes: + emit(OP_UNICODE_IGNORE[op]) + emit(lo) + else: + emit(IN_UNI_IGNORE) + skip = _len(code); emit(0) + if op is NOT_LITERAL: + emit(NEGATE) + for k in (lo,) + fixes[lo]: + emit(LITERAL) + emit(k) + emit(FAILURE) + code[skip] = _len(code) - skip + elif op is IN: + charset, hascased = _optimize_charset(av, iscased, tolower, fixes) + if flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE: + emit(IN_LOC_IGNORE) + elif not hascased: + emit(IN) + elif not fixes: # ascii + emit(IN_IGNORE) + else: + emit(IN_UNI_IGNORE) + skip = _len(code); emit(0) + _compile_charset(charset, flags, code) + code[skip] = _len(code) - skip + elif op is ANY: + if flags & SRE_FLAG_DOTALL: + emit(ANY_ALL) + else: + emit(ANY) + elif op in REPEATING_CODES: + if flags & SRE_FLAG_TEMPLATE: + raise error("internal: unsupported template operator %r" % (op,)) + if _simple(av[2]): + if op is MAX_REPEAT: + emit(REPEAT_ONE) + else: + emit(MIN_REPEAT_ONE) + skip = _len(code); emit(0) + emit(av[0]) + emit(av[1]) + _compile(code, av[2], flags) + emit(SUCCESS) + code[skip] = _len(code) - skip + else: + emit(REPEAT) + skip = _len(code); emit(0) + emit(av[0]) + emit(av[1]) + _compile(code, av[2], flags) + code[skip] = _len(code) - skip + if op is MAX_REPEAT: + emit(MAX_UNTIL) + else: + emit(MIN_UNTIL) + elif op is SUBPATTERN: + group, add_flags, del_flags, p = av + if group: + emit(MARK) + emit((group-1)*2) + # _compile_info(code, p, _combine_flags(flags, add_flags, del_flags)) + _compile(code, p, _combine_flags(flags, add_flags, del_flags)) + if group: + emit(MARK) + emit((group-1)*2+1) + elif op in SUCCESS_CODES: + emit(op) + elif op in ASSERT_CODES: + emit(op) + skip = _len(code); emit(0) + if av[0] >= 0: + emit(0) # look ahead + else: + lo, hi = av[1].getwidth() + if lo != hi: + raise error("look-behind requires fixed-width pattern") + emit(lo) # look behind + _compile(code, av[1], flags) + emit(SUCCESS) + code[skip] = _len(code) - skip + elif op is CALL: + emit(op) + skip = _len(code); emit(0) + _compile(code, av, flags) + emit(SUCCESS) + code[skip] = _len(code) - skip + elif op is AT: + emit(op) + if flags & SRE_FLAG_MULTILINE: + av = AT_MULTILINE.get(av, av) + if flags & SRE_FLAG_LOCALE: + av = AT_LOCALE.get(av, av) + elif (flags & SRE_FLAG_UNICODE) and not (flags & SRE_FLAG_ASCII): + av = AT_UNICODE.get(av, av) + emit(av) + elif op is BRANCH: + emit(op) + tail = [] + tailappend = tail.append + for av in av[1]: + skip = _len(code); emit(0) + # _compile_info(code, av, flags) + _compile(code, av, flags) + emit(JUMP) + tailappend(_len(code)); emit(0) + code[skip] = _len(code) - skip + emit(FAILURE) # end of branch + for tail in tail: + code[tail] = _len(code) - tail + elif op is CATEGORY: + emit(op) + if flags & SRE_FLAG_LOCALE: + av = CH_LOCALE[av] + elif (flags & SRE_FLAG_UNICODE) and not (flags & SRE_FLAG_ASCII): + av = CH_UNICODE[av] + emit(av) + elif op is GROUPREF: + if not flags & SRE_FLAG_IGNORECASE: + emit(op) + elif flags & SRE_FLAG_LOCALE: + emit(GROUPREF_LOC_IGNORE) + elif not fixes: # ascii + emit(GROUPREF_IGNORE) + else: + emit(GROUPREF_UNI_IGNORE) + emit(av-1) + elif op is GROUPREF_EXISTS: + emit(op) + emit(av[0]-1) + skipyes = _len(code); emit(0) + _compile(code, av[1], flags) + if av[2]: + emit(JUMP) + skipno = _len(code); emit(0) + code[skipyes] = _len(code) - skipyes + 1 + _compile(code, av[2], flags) + code[skipno] = _len(code) - skipno + else: + code[skipyes] = _len(code) - skipyes + 1 + else: + raise error("internal: unsupported operand type %r" % (op,)) + +def _compile_charset(charset, flags, code): + # compile charset subprogram + emit = code.append + for op, av in charset: + emit(op) + if op is NEGATE: + pass + elif op is LITERAL: + emit(av) + elif op is RANGE or op is RANGE_UNI_IGNORE: + emit(av[0]) + emit(av[1]) + elif op is CHARSET: + code.extend(av) + elif op is BIGCHARSET: + code.extend(av) + elif op is CATEGORY: + if flags & SRE_FLAG_LOCALE: + emit(CH_LOCALE[av]) + elif (flags & SRE_FLAG_UNICODE) and not (flags & SRE_FLAG_ASCII): + emit(CH_UNICODE[av]) + else: + emit(av) + else: + raise error("internal: unsupported set operator %r" % (op,)) + emit(FAILURE) + +def _optimize_charset(charset, iscased=None, fixup=None, fixes=None): + # internal: optimize character set + out = [] + tail = [] + charmap = bytearray(256) + hascased = False + for op, av in charset: + while True: + try: + if op is LITERAL: + if fixup: + lo = fixup(av) + charmap[lo] = 1 + if fixes and lo in fixes: + for k in fixes[lo]: + charmap[k] = 1 + if not hascased and iscased(av): + hascased = True + else: + charmap[av] = 1 + elif op is RANGE: + r = range(av[0], av[1]+1) + if fixup: + if fixes: + for i in map(fixup, r): + charmap[i] = 1 + if i in fixes: + for k in fixes[i]: + charmap[k] = 1 + else: + for i in map(fixup, r): + charmap[i] = 1 + if not hascased: + hascased = any(map(iscased, r)) + else: + for i in r: + charmap[i] = 1 + elif op is NEGATE: + out.append((op, av)) + else: + tail.append((op, av)) + except IndexError: + if len(charmap) == 256: + # character set contains non-UCS1 character codes + charmap += b'\0' * 0xff00 + continue + # Character set contains non-BMP character codes. + if fixup: + hascased = True + # There are only two ranges of cased non-BMP characters: + # 10400-1044F (Deseret) and 118A0-118DF (Warang Citi), + # and for both ranges RANGE_UNI_IGNORE works. + if op is RANGE: + op = RANGE_UNI_IGNORE + tail.append((op, av)) + break + + # compress character map + runs = [] + q = 0 + while True: + p = charmap.find(1, q) + if p < 0: + break + if len(runs) >= 2: + runs = None + break + q = charmap.find(0, p) + if q < 0: + runs.append((p, len(charmap))) + break + runs.append((p, q)) + if runs is not None: + # use literal/range + for p, q in runs: + if q - p == 1: + out.append((LITERAL, p)) + else: + out.append((RANGE, (p, q - 1))) + out += tail + # if the case was changed or new representation is more compact + if hascased or len(out) < len(charset): + return out, hascased + # else original character set is good enough + return charset, hascased + + # use bitmap + if len(charmap) == 256: + data = _mk_bitmap(charmap) + out.append((CHARSET, data)) + out += tail + return out, hascased + + # To represent a big charset, first a bitmap of all characters in the + # set is constructed. Then, this bitmap is sliced into chunks of 256 + # characters, duplicate chunks are eliminated, and each chunk is + # given a number. In the compiled expression, the charset is + # represented by a 32-bit word sequence, consisting of one word for + # the number of different chunks, a sequence of 256 bytes (64 words) + # of chunk numbers indexed by their original chunk position, and a + # sequence of 256-bit chunks (8 words each). + + # Compression is normally good: in a typical charset, large ranges of + # Unicode will be either completely excluded (e.g. if only cyrillic + # letters are to be matched), or completely included (e.g. if large + # subranges of Kanji match). These ranges will be represented by + # chunks of all one-bits or all zero-bits. + + # Matching can be also done efficiently: the more significant byte of + # the Unicode character is an index into the chunk number, and the + # less significant byte is a bit index in the chunk (just like the + # CHARSET matching). + + charmap = bytes(charmap) # should be hashable + comps = {} + mapping = bytearray(256) + block = 0 + data = bytearray() + for i in range(0, 65536, 256): + chunk = charmap[i: i + 256] + if chunk in comps: + mapping[i // 256] = comps[chunk] + else: + mapping[i // 256] = comps[chunk] = block + block += 1 + data += chunk + data = _mk_bitmap(data) + data[0:0] = [block] + _bytes_to_codes(mapping) + out.append((BIGCHARSET, data)) + out += tail + return out, hascased + +_CODEBITS = _sre.CODESIZE * 8 +MAXCODE = (1 << _CODEBITS) - 1 +_BITS_TRANS = b'0' + b'1' * 255 +def _mk_bitmap(bits, _CODEBITS=_CODEBITS, _int=int): + s = bits.translate(_BITS_TRANS)[::-1] + return [_int(s[i - _CODEBITS: i], 2) + for i in range(len(s), 0, -_CODEBITS)] + +def _bytes_to_codes(b): + # Convert block indices to word array + a = memoryview(b).cast('I') + assert a.itemsize == _sre.CODESIZE + assert len(a) * a.itemsize == len(b) + return a.tolist() + +def _simple(p): + # check if this subpattern is a "simple" operator + if len(p) != 1: + return False + op, av = p[0] + if op is SUBPATTERN: + return av[0] is None and _simple(av[-1]) + return op in _UNIT_CODES + +def _generate_overlap_table(prefix): + """ + Generate an overlap table for the following prefix. + An overlap table is a table of the same size as the prefix which + informs about the potential self-overlap for each index in the prefix: + - if overlap[i] == 0, prefix[i:] can't overlap prefix[0:...] + - if overlap[i] == k with 0 < k <= i, prefix[i-k+1:i+1] overlaps with + prefix[0:k] + """ + table = [0] * len(prefix) + for i in range(1, len(prefix)): + idx = table[i - 1] + while prefix[i] != prefix[idx]: + if idx == 0: + table[i] = 0 + break + idx = table[idx - 1] + else: + table[i] = idx + 1 + return table + +def _get_iscased(flags): + if not flags & SRE_FLAG_IGNORECASE: + return None + elif flags & SRE_FLAG_UNICODE and not flags & SRE_FLAG_ASCII: + return _sre.unicode_iscased + else: + return _sre.ascii_iscased + +def _get_literal_prefix(pattern, flags): + # look for literal prefix + prefix = [] + prefixappend = prefix.append + prefix_skip = None + iscased = _get_iscased(flags) + for op, av in pattern.data: + if op is LITERAL: + if iscased and iscased(av): + break + prefixappend(av) + elif op is SUBPATTERN: + group, add_flags, del_flags, p = av + flags1 = _combine_flags(flags, add_flags, del_flags) + if flags1 & SRE_FLAG_IGNORECASE and flags1 & SRE_FLAG_LOCALE: + break + prefix1, prefix_skip1, got_all = _get_literal_prefix(p, flags1) + if prefix_skip is None: + if group is not None: + prefix_skip = len(prefix) + elif prefix_skip1 is not None: + prefix_skip = len(prefix) + prefix_skip1 + prefix.extend(prefix1) + if not got_all: + break + else: + break + else: + return prefix, prefix_skip, True + return prefix, prefix_skip, False + +def _get_charset_prefix(pattern, flags): + while True: + if not pattern.data: + return None + op, av = pattern.data[0] + if op is not SUBPATTERN: + break + group, add_flags, del_flags, pattern = av + flags = _combine_flags(flags, add_flags, del_flags) + if flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE: + return None + + iscased = _get_iscased(flags) + if op is LITERAL: + if iscased and iscased(av): + return None + return [(op, av)] + elif op is BRANCH: + charset = [] + charsetappend = charset.append + for p in av[1]: + if not p: + return None + op, av = p[0] + if op is LITERAL and not (iscased and iscased(av)): + charsetappend((op, av)) + else: + return None + return charset + elif op is IN: + charset = av + if iscased: + for op, av in charset: + if op is LITERAL: + if iscased(av): + return None + elif op is RANGE: + if av[1] > 0xffff: + return None + if any(map(iscased, range(av[0], av[1]+1))): + return None + return charset + return None + +def _compile_info(code, pattern, flags): + # internal: compile an info block. in the current version, + # this contains min/max pattern width, and an optional literal + # prefix or a character map + lo, hi = pattern.getwidth() + if hi > MAXCODE: + hi = MAXCODE + if lo == 0: + code.extend([INFO, 4, 0, lo, hi]) + return + # look for a literal prefix + prefix = [] + prefix_skip = 0 + charset = [] # not used + if not (flags & SRE_FLAG_IGNORECASE and flags & SRE_FLAG_LOCALE): + # look for literal prefix + prefix, prefix_skip, got_all = _get_literal_prefix(pattern, flags) + # if no prefix, look for charset prefix + if not prefix: + charset = _get_charset_prefix(pattern, flags) +## if prefix: +## print("*** PREFIX", prefix, prefix_skip) +## if charset: +## print("*** CHARSET", charset) + # add an info block + emit = code.append + emit(INFO) + skip = len(code); emit(0) + # literal flag + mask = 0 + if prefix: + mask = SRE_INFO_PREFIX + if prefix_skip is None and got_all: + mask = mask | SRE_INFO_LITERAL + elif charset: + mask = mask | SRE_INFO_CHARSET + emit(mask) + # pattern length + if lo < MAXCODE: + emit(lo) + else: + emit(MAXCODE) + prefix = prefix[:MAXCODE] + emit(min(hi, MAXCODE)) + # add literal prefix + if prefix: + emit(len(prefix)) # length + if prefix_skip is None: + prefix_skip = len(prefix) + emit(prefix_skip) # skip + code.extend(prefix) + # generate overlap table + code.extend(_generate_overlap_table(prefix)) + elif charset: + charset, hascased = _optimize_charset(charset) + assert not hascased + _compile_charset(charset, flags, code) + code[skip] = len(code) - skip + +def isstring(obj): + return isinstance(obj, (str, bytes)) + +def _code(p, flags): + + flags = p.pattern.flags | flags + code = [] + + # compile info block + _compile_info(code, p, flags) + + # compile the pattern + _compile(code, p.data, flags) + + code.append(SUCCESS) + + return code + +def _hex_code(code): + return '[%s]' % ', '.join('%#0*x' % (_sre.CODESIZE*2+2, x) for x in code) + +def dis(code): + import sys + + labels = set() + level = 0 + offset_width = len(str(len(code) - 1)) + + def dis_(start, end): + def print_(*args, to=None): + if to is not None: + labels.add(to) + args += ('(to %d)' % (to,),) + print('%*d%s ' % (offset_width, start, ':' if start in labels else '.'), + end=' '*(level-1)) + print(*args) + + def print_2(*args): + print(end=' '*(offset_width + 2*level)) + print(*args) + + nonlocal level + level += 1 + i = start + while i < end: + start = i + op = code[i] + i += 1 + op = OPCODES[op] + if op in (SUCCESS, FAILURE, ANY, ANY_ALL, + MAX_UNTIL, MIN_UNTIL, NEGATE): + print_(op) + elif op in (LITERAL, NOT_LITERAL, + LITERAL_IGNORE, NOT_LITERAL_IGNORE, + LITERAL_UNI_IGNORE, NOT_LITERAL_UNI_IGNORE, + LITERAL_LOC_IGNORE, NOT_LITERAL_LOC_IGNORE): + arg = code[i] + i += 1 + print_(op, '%#02x (%r)' % (arg, chr(arg))) + elif op is AT: + arg = code[i] + i += 1 + arg = str(ATCODES[arg]) + assert arg[:3] == 'AT_' + print_(op, arg[3:]) + elif op is CATEGORY: + arg = code[i] + i += 1 + arg = str(CHCODES[arg]) + assert arg[:9] == 'CATEGORY_' + print_(op, arg[9:]) + elif op in (IN, IN_IGNORE, IN_UNI_IGNORE, IN_LOC_IGNORE): + skip = code[i] + print_(op, skip, to=i+skip) + dis_(i+1, i+skip) + i += skip + elif op in (RANGE, RANGE_UNI_IGNORE): + lo, hi = code[i: i+2] + i += 2 + print_(op, '%#02x %#02x (%r-%r)' % (lo, hi, chr(lo), chr(hi))) + elif op is CHARSET: + print_(op, _hex_code(code[i: i + 256//_CODEBITS])) + i += 256//_CODEBITS + elif op is BIGCHARSET: + arg = code[i] + i += 1 + mapping = list(b''.join(x.to_bytes(_sre.CODESIZE, sys.byteorder) + for x in code[i: i + 256//_sre.CODESIZE])) + print_(op, arg, mapping) + i += 256//_sre.CODESIZE + level += 1 + for j in range(arg): + print_2(_hex_code(code[i: i + 256//_CODEBITS])) + i += 256//_CODEBITS + level -= 1 + elif op in (MARK, GROUPREF, GROUPREF_IGNORE, GROUPREF_UNI_IGNORE, + GROUPREF_LOC_IGNORE): + arg = code[i] + i += 1 + print_(op, arg) + elif op is JUMP: + skip = code[i] + print_(op, skip, to=i+skip) + i += 1 + elif op is BRANCH: + skip = code[i] + print_(op, skip, to=i+skip) + while skip: + dis_(i+1, i+skip) + i += skip + start = i + skip = code[i] + if skip: + print_('branch', skip, to=i+skip) + else: + print_(FAILURE) + i += 1 + elif op in (REPEAT, REPEAT_ONE, MIN_REPEAT_ONE): + skip, min, max = code[i: i+3] + if max == MAXREPEAT: + max = 'MAXREPEAT' + print_(op, skip, min, max, to=i+skip) + dis_(i+3, i+skip) + i += skip + elif op is GROUPREF_EXISTS: + arg, skip = code[i: i+2] + print_(op, arg, skip, to=i+skip) + i += 2 + elif op in (ASSERT, ASSERT_NOT): + skip, arg = code[i: i+2] + print_(op, skip, arg, to=i+skip) + dis_(i+2, i+skip) + i += skip + elif op is INFO: + skip, flags, min, max = code[i: i+4] + if max == MAXREPEAT: + max = 'MAXREPEAT' + print_(op, skip, bin(flags), min, max, to=i+skip) + start = i+4 + if flags & SRE_INFO_PREFIX: + prefix_len, prefix_skip = code[i+4: i+6] + print_2(' prefix_skip', prefix_skip) + start = i + 6 + prefix = code[start: start+prefix_len] + print_2(' prefix', + '[%s]' % ', '.join('%#02x' % x for x in prefix), + '(%r)' % ''.join(map(chr, prefix))) + start += prefix_len + print_2(' overlap', code[start: start+prefix_len]) + start += prefix_len + if flags & SRE_INFO_CHARSET: + level += 1 + print_2('in') + dis_(start, i+skip) + level -= 1 + i += skip + else: + raise ValueError(op) + + level -= 1 + + dis_(0, len(code)) + + +def compile(p, flags=0): + # internal: convert pattern list to internal format + + if isstring(p): + pattern = p + p = sre_parse.parse(p, flags) + else: + pattern = None + + code = _code(p, flags) + + if flags & SRE_FLAG_DEBUG: + print() + dis(code) + + # map in either direction + groupindex = p.pattern.groupdict + indexgroup = [None] * p.pattern.groups + for k, i in groupindex.items(): + indexgroup[i] = k + + return _sre.compile( + pattern, flags | p.pattern.flags, code, + p.pattern.groups-1, + groupindex, tuple(indexgroup) + ) diff --git a/winvenv/Lib/sre_constants.py b/winvenv/Lib/sre_constants.py new file mode 100644 index 0000000..13deb00 --- /dev/null +++ b/winvenv/Lib/sre_constants.py @@ -0,0 +1,261 @@ +# +# Secret Labs' Regular Expression Engine +# +# various symbols used by the regular expression engine. +# run this script to update the _sre include files! +# +# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. +# +# See the sre.py file for information on usage and redistribution. +# + +"""Internal support module for sre""" + +# update when constants are added or removed + +MAGIC = 20171005 + +from _sre import MAXREPEAT, MAXGROUPS + +# SRE standard exception (access as sre.error) +# should this really be here? + +class error(Exception): + """Exception raised for invalid regular expressions. + + Attributes: + + msg: The unformatted error message + pattern: The regular expression pattern + pos: The index in the pattern where compilation failed (may be None) + lineno: The line corresponding to pos (may be None) + colno: The column corresponding to pos (may be None) + """ + + __module__ = 're' + + def __init__(self, msg, pattern=None, pos=None): + self.msg = msg + self.pattern = pattern + self.pos = pos + if pattern is not None and pos is not None: + msg = '%s at position %d' % (msg, pos) + if isinstance(pattern, str): + newline = '\n' + else: + newline = b'\n' + self.lineno = pattern.count(newline, 0, pos) + 1 + self.colno = pos - pattern.rfind(newline, 0, pos) + if newline in pattern: + msg = '%s (line %d, column %d)' % (msg, self.lineno, self.colno) + else: + self.lineno = self.colno = None + super().__init__(msg) + + +class _NamedIntConstant(int): + def __new__(cls, value, name): + self = super(_NamedIntConstant, cls).__new__(cls, value) + self.name = name + return self + + def __str__(self): + return self.name + + __repr__ = __str__ + +MAXREPEAT = _NamedIntConstant(MAXREPEAT, 'MAXREPEAT') + +def _makecodes(names): + names = names.strip().split() + items = [_NamedIntConstant(i, name) for i, name in enumerate(names)] + globals().update({item.name: item for item in items}) + return items + +# operators +# failure=0 success=1 (just because it looks better that way :-) +OPCODES = _makecodes(""" + FAILURE SUCCESS + + ANY ANY_ALL + ASSERT ASSERT_NOT + AT + BRANCH + CALL + CATEGORY + CHARSET BIGCHARSET + GROUPREF GROUPREF_EXISTS + IN + INFO + JUMP + LITERAL + MARK + MAX_UNTIL + MIN_UNTIL + NOT_LITERAL + NEGATE + RANGE + REPEAT + REPEAT_ONE + SUBPATTERN + MIN_REPEAT_ONE + + GROUPREF_IGNORE + IN_IGNORE + LITERAL_IGNORE + NOT_LITERAL_IGNORE + + GROUPREF_LOC_IGNORE + IN_LOC_IGNORE + LITERAL_LOC_IGNORE + NOT_LITERAL_LOC_IGNORE + + GROUPREF_UNI_IGNORE + IN_UNI_IGNORE + LITERAL_UNI_IGNORE + NOT_LITERAL_UNI_IGNORE + RANGE_UNI_IGNORE + + MIN_REPEAT MAX_REPEAT +""") +del OPCODES[-2:] # remove MIN_REPEAT and MAX_REPEAT + +# positions +ATCODES = _makecodes(""" + AT_BEGINNING AT_BEGINNING_LINE AT_BEGINNING_STRING + AT_BOUNDARY AT_NON_BOUNDARY + AT_END AT_END_LINE AT_END_STRING + + AT_LOC_BOUNDARY AT_LOC_NON_BOUNDARY + + AT_UNI_BOUNDARY AT_UNI_NON_BOUNDARY +""") + +# categories +CHCODES = _makecodes(""" + CATEGORY_DIGIT CATEGORY_NOT_DIGIT + CATEGORY_SPACE CATEGORY_NOT_SPACE + CATEGORY_WORD CATEGORY_NOT_WORD + CATEGORY_LINEBREAK CATEGORY_NOT_LINEBREAK + + CATEGORY_LOC_WORD CATEGORY_LOC_NOT_WORD + + CATEGORY_UNI_DIGIT CATEGORY_UNI_NOT_DIGIT + CATEGORY_UNI_SPACE CATEGORY_UNI_NOT_SPACE + CATEGORY_UNI_WORD CATEGORY_UNI_NOT_WORD + CATEGORY_UNI_LINEBREAK CATEGORY_UNI_NOT_LINEBREAK +""") + + +# replacement operations for "ignore case" mode +OP_IGNORE = { + LITERAL: LITERAL_IGNORE, + NOT_LITERAL: NOT_LITERAL_IGNORE, +} + +OP_LOCALE_IGNORE = { + LITERAL: LITERAL_LOC_IGNORE, + NOT_LITERAL: NOT_LITERAL_LOC_IGNORE, +} + +OP_UNICODE_IGNORE = { + LITERAL: LITERAL_UNI_IGNORE, + NOT_LITERAL: NOT_LITERAL_UNI_IGNORE, +} + +AT_MULTILINE = { + AT_BEGINNING: AT_BEGINNING_LINE, + AT_END: AT_END_LINE +} + +AT_LOCALE = { + AT_BOUNDARY: AT_LOC_BOUNDARY, + AT_NON_BOUNDARY: AT_LOC_NON_BOUNDARY +} + +AT_UNICODE = { + AT_BOUNDARY: AT_UNI_BOUNDARY, + AT_NON_BOUNDARY: AT_UNI_NON_BOUNDARY +} + +CH_LOCALE = { + CATEGORY_DIGIT: CATEGORY_DIGIT, + CATEGORY_NOT_DIGIT: CATEGORY_NOT_DIGIT, + CATEGORY_SPACE: CATEGORY_SPACE, + CATEGORY_NOT_SPACE: CATEGORY_NOT_SPACE, + CATEGORY_WORD: CATEGORY_LOC_WORD, + CATEGORY_NOT_WORD: CATEGORY_LOC_NOT_WORD, + CATEGORY_LINEBREAK: CATEGORY_LINEBREAK, + CATEGORY_NOT_LINEBREAK: CATEGORY_NOT_LINEBREAK +} + +CH_UNICODE = { + CATEGORY_DIGIT: CATEGORY_UNI_DIGIT, + CATEGORY_NOT_DIGIT: CATEGORY_UNI_NOT_DIGIT, + CATEGORY_SPACE: CATEGORY_UNI_SPACE, + CATEGORY_NOT_SPACE: CATEGORY_UNI_NOT_SPACE, + CATEGORY_WORD: CATEGORY_UNI_WORD, + CATEGORY_NOT_WORD: CATEGORY_UNI_NOT_WORD, + CATEGORY_LINEBREAK: CATEGORY_UNI_LINEBREAK, + CATEGORY_NOT_LINEBREAK: CATEGORY_UNI_NOT_LINEBREAK +} + +# flags +SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) +SRE_FLAG_IGNORECASE = 2 # case insensitive +SRE_FLAG_LOCALE = 4 # honour system locale +SRE_FLAG_MULTILINE = 8 # treat target as multiline string +SRE_FLAG_DOTALL = 16 # treat target as a single string +SRE_FLAG_UNICODE = 32 # use unicode "locale" +SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments +SRE_FLAG_DEBUG = 128 # debugging +SRE_FLAG_ASCII = 256 # use ascii "locale" + +# flags for INFO primitive +SRE_INFO_PREFIX = 1 # has prefix +SRE_INFO_LITERAL = 2 # entire pattern is literal (given by prefix) +SRE_INFO_CHARSET = 4 # pattern starts with character from given set + +if __name__ == "__main__": + def dump(f, d, prefix): + items = sorted(d) + for item in items: + f.write("#define %s_%s %d\n" % (prefix, item, item)) + with open("sre_constants.h", "w") as f: + f.write("""\ +/* + * Secret Labs' Regular Expression Engine + * + * regular expression matching engine + * + * NOTE: This file is generated by sre_constants.py. If you need + * to change anything in here, edit sre_constants.py and run it. + * + * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. + * + * See the _sre.c file for information on usage and redistribution. + */ + +""") + + f.write("#define SRE_MAGIC %d\n" % MAGIC) + + dump(f, OPCODES, "SRE_OP") + dump(f, ATCODES, "SRE") + dump(f, CHCODES, "SRE") + + f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE) + f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE) + f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE) + f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE) + f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL) + f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE) + f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE) + f.write("#define SRE_FLAG_DEBUG %d\n" % SRE_FLAG_DEBUG) + f.write("#define SRE_FLAG_ASCII %d\n" % SRE_FLAG_ASCII) + + f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX) + f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL) + f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET) + + print("done") diff --git a/winvenv/Lib/sre_parse.py b/winvenv/Lib/sre_parse.py new file mode 100644 index 0000000..a53735b --- /dev/null +++ b/winvenv/Lib/sre_parse.py @@ -0,0 +1,1046 @@ +# +# Secret Labs' Regular Expression Engine +# +# convert re-style regular expression to sre pattern +# +# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. +# +# See the sre.py file for information on usage and redistribution. +# + +"""Internal support module for sre""" + +# XXX: show string offset and offending character for all errors + +from sre_constants import * + +SPECIAL_CHARS = ".\\[{()*+?^$|" +REPEAT_CHARS = "*+?{" + +DIGITS = frozenset("0123456789") + +OCTDIGITS = frozenset("01234567") +HEXDIGITS = frozenset("0123456789abcdefABCDEF") +ASCIILETTERS = frozenset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +WHITESPACE = frozenset(" \t\n\r\v\f") + +_REPEATCODES = frozenset({MIN_REPEAT, MAX_REPEAT}) +_UNITCODES = frozenset({ANY, RANGE, IN, LITERAL, NOT_LITERAL, CATEGORY}) + +ESCAPES = { + r"\a": (LITERAL, ord("\a")), + r"\b": (LITERAL, ord("\b")), + r"\f": (LITERAL, ord("\f")), + r"\n": (LITERAL, ord("\n")), + r"\r": (LITERAL, ord("\r")), + r"\t": (LITERAL, ord("\t")), + r"\v": (LITERAL, ord("\v")), + r"\\": (LITERAL, ord("\\")) +} + +CATEGORIES = { + r"\A": (AT, AT_BEGINNING_STRING), # start of string + r"\b": (AT, AT_BOUNDARY), + r"\B": (AT, AT_NON_BOUNDARY), + r"\d": (IN, [(CATEGORY, CATEGORY_DIGIT)]), + r"\D": (IN, [(CATEGORY, CATEGORY_NOT_DIGIT)]), + r"\s": (IN, [(CATEGORY, CATEGORY_SPACE)]), + r"\S": (IN, [(CATEGORY, CATEGORY_NOT_SPACE)]), + r"\w": (IN, [(CATEGORY, CATEGORY_WORD)]), + r"\W": (IN, [(CATEGORY, CATEGORY_NOT_WORD)]), + r"\Z": (AT, AT_END_STRING), # end of string +} + +FLAGS = { + # standard flags + "i": SRE_FLAG_IGNORECASE, + "L": SRE_FLAG_LOCALE, + "m": SRE_FLAG_MULTILINE, + "s": SRE_FLAG_DOTALL, + "x": SRE_FLAG_VERBOSE, + # extensions + "a": SRE_FLAG_ASCII, + "t": SRE_FLAG_TEMPLATE, + "u": SRE_FLAG_UNICODE, +} + +TYPE_FLAGS = SRE_FLAG_ASCII | SRE_FLAG_LOCALE | SRE_FLAG_UNICODE +GLOBAL_FLAGS = SRE_FLAG_DEBUG | SRE_FLAG_TEMPLATE + +class Verbose(Exception): + pass + +class Pattern: + # master pattern object. keeps track of global attributes + def __init__(self): + self.flags = 0 + self.groupdict = {} + self.groupwidths = [None] # group 0 + self.lookbehindgroups = None + @property + def groups(self): + return len(self.groupwidths) + def opengroup(self, name=None): + gid = self.groups + self.groupwidths.append(None) + if self.groups > MAXGROUPS: + raise error("too many groups") + if name is not None: + ogid = self.groupdict.get(name, None) + if ogid is not None: + raise error("redefinition of group name %r as group %d; " + "was group %d" % (name, gid, ogid)) + self.groupdict[name] = gid + return gid + def closegroup(self, gid, p): + self.groupwidths[gid] = p.getwidth() + def checkgroup(self, gid): + return gid < self.groups and self.groupwidths[gid] is not None + + def checklookbehindgroup(self, gid, source): + if self.lookbehindgroups is not None: + if not self.checkgroup(gid): + raise source.error('cannot refer to an open group') + if gid >= self.lookbehindgroups: + raise source.error('cannot refer to group defined in the same ' + 'lookbehind subpattern') + +class SubPattern: + # a subpattern, in intermediate form + def __init__(self, pattern, data=None): + self.pattern = pattern + if data is None: + data = [] + self.data = data + self.width = None + + def dump(self, level=0): + nl = True + seqtypes = (tuple, list) + for op, av in self.data: + print(level*" " + str(op), end='') + if op is IN: + # member sublanguage + print() + for op, a in av: + print((level+1)*" " + str(op), a) + elif op is BRANCH: + print() + for i, a in enumerate(av[1]): + if i: + print(level*" " + "OR") + a.dump(level+1) + elif op is GROUPREF_EXISTS: + condgroup, item_yes, item_no = av + print('', condgroup) + item_yes.dump(level+1) + if item_no: + print(level*" " + "ELSE") + item_no.dump(level+1) + elif isinstance(av, seqtypes): + nl = False + for a in av: + if isinstance(a, SubPattern): + if not nl: + print() + a.dump(level+1) + nl = True + else: + if not nl: + print(' ', end='') + print(a, end='') + nl = False + if not nl: + print() + else: + print('', av) + def __repr__(self): + return repr(self.data) + def __len__(self): + return len(self.data) + def __delitem__(self, index): + del self.data[index] + def __getitem__(self, index): + if isinstance(index, slice): + return SubPattern(self.pattern, self.data[index]) + return self.data[index] + def __setitem__(self, index, code): + self.data[index] = code + def insert(self, index, code): + self.data.insert(index, code) + def append(self, code): + self.data.append(code) + def getwidth(self): + # determine the width (min, max) for this subpattern + if self.width is not None: + return self.width + lo = hi = 0 + for op, av in self.data: + if op is BRANCH: + i = MAXREPEAT - 1 + j = 0 + for av in av[1]: + l, h = av.getwidth() + i = min(i, l) + j = max(j, h) + lo = lo + i + hi = hi + j + elif op is CALL: + i, j = av.getwidth() + lo = lo + i + hi = hi + j + elif op is SUBPATTERN: + i, j = av[-1].getwidth() + lo = lo + i + hi = hi + j + elif op in _REPEATCODES: + i, j = av[2].getwidth() + lo = lo + i * av[0] + hi = hi + j * av[1] + elif op in _UNITCODES: + lo = lo + 1 + hi = hi + 1 + elif op is GROUPREF: + i, j = self.pattern.groupwidths[av] + lo = lo + i + hi = hi + j + elif op is GROUPREF_EXISTS: + i, j = av[1].getwidth() + if av[2] is not None: + l, h = av[2].getwidth() + i = min(i, l) + j = max(j, h) + else: + i = 0 + lo = lo + i + hi = hi + j + elif op is SUCCESS: + break + self.width = min(lo, MAXREPEAT - 1), min(hi, MAXREPEAT) + return self.width + +class Tokenizer: + def __init__(self, string): + self.istext = isinstance(string, str) + self.string = string + if not self.istext: + string = str(string, 'latin1') + self.decoded_string = string + self.index = 0 + self.next = None + self.__next() + def __next(self): + index = self.index + try: + char = self.decoded_string[index] + except IndexError: + self.next = None + return + if char == "\\": + index += 1 + try: + char += self.decoded_string[index] + except IndexError: + raise error("bad escape (end of pattern)", + self.string, len(self.string) - 1) from None + self.index = index + 1 + self.next = char + def match(self, char): + if char == self.next: + self.__next() + return True + return False + def get(self): + this = self.next + self.__next() + return this + def getwhile(self, n, charset): + result = '' + for _ in range(n): + c = self.next + if c not in charset: + break + result += c + self.__next() + return result + def getuntil(self, terminator): + result = '' + while True: + c = self.next + self.__next() + if c is None: + if not result: + raise self.error("missing group name") + raise self.error("missing %s, unterminated name" % terminator, + len(result)) + if c == terminator: + if not result: + raise self.error("missing group name", 1) + break + result += c + return result + @property + def pos(self): + return self.index - len(self.next or '') + def tell(self): + return self.index - len(self.next or '') + def seek(self, index): + self.index = index + self.__next() + + def error(self, msg, offset=0): + return error(msg, self.string, self.tell() - offset) + +def _class_escape(source, escape): + # handle escape code inside character class + code = ESCAPES.get(escape) + if code: + return code + code = CATEGORIES.get(escape) + if code and code[0] is IN: + return code + try: + c = escape[1:2] + if c == "x": + # hexadecimal escape (exactly two digits) + escape += source.getwhile(2, HEXDIGITS) + if len(escape) != 4: + raise source.error("incomplete escape %s" % escape, len(escape)) + return LITERAL, int(escape[2:], 16) + elif c == "u" and source.istext: + # unicode escape (exactly four digits) + escape += source.getwhile(4, HEXDIGITS) + if len(escape) != 6: + raise source.error("incomplete escape %s" % escape, len(escape)) + return LITERAL, int(escape[2:], 16) + elif c == "U" and source.istext: + # unicode escape (exactly eight digits) + escape += source.getwhile(8, HEXDIGITS) + if len(escape) != 10: + raise source.error("incomplete escape %s" % escape, len(escape)) + c = int(escape[2:], 16) + chr(c) # raise ValueError for invalid code + return LITERAL, c + elif c in OCTDIGITS: + # octal escape (up to three digits) + escape += source.getwhile(2, OCTDIGITS) + c = int(escape[1:], 8) + if c > 0o377: + raise source.error('octal escape value %s outside of ' + 'range 0-0o377' % escape, len(escape)) + return LITERAL, c + elif c in DIGITS: + raise ValueError + if len(escape) == 2: + if c in ASCIILETTERS: + raise source.error('bad escape %s' % escape, len(escape)) + return LITERAL, ord(escape[1]) + except ValueError: + pass + raise source.error("bad escape %s" % escape, len(escape)) + +def _escape(source, escape, state): + # handle escape code in expression + code = CATEGORIES.get(escape) + if code: + return code + code = ESCAPES.get(escape) + if code: + return code + try: + c = escape[1:2] + if c == "x": + # hexadecimal escape + escape += source.getwhile(2, HEXDIGITS) + if len(escape) != 4: + raise source.error("incomplete escape %s" % escape, len(escape)) + return LITERAL, int(escape[2:], 16) + elif c == "u" and source.istext: + # unicode escape (exactly four digits) + escape += source.getwhile(4, HEXDIGITS) + if len(escape) != 6: + raise source.error("incomplete escape %s" % escape, len(escape)) + return LITERAL, int(escape[2:], 16) + elif c == "U" and source.istext: + # unicode escape (exactly eight digits) + escape += source.getwhile(8, HEXDIGITS) + if len(escape) != 10: + raise source.error("incomplete escape %s" % escape, len(escape)) + c = int(escape[2:], 16) + chr(c) # raise ValueError for invalid code + return LITERAL, c + elif c == "0": + # octal escape + escape += source.getwhile(2, OCTDIGITS) + return LITERAL, int(escape[1:], 8) + elif c in DIGITS: + # octal escape *or* decimal group reference (sigh) + if source.next in DIGITS: + escape += source.get() + if (escape[1] in OCTDIGITS and escape[2] in OCTDIGITS and + source.next in OCTDIGITS): + # got three octal digits; this is an octal escape + escape += source.get() + c = int(escape[1:], 8) + if c > 0o377: + raise source.error('octal escape value %s outside of ' + 'range 0-0o377' % escape, + len(escape)) + return LITERAL, c + # not an octal escape, so this is a group reference + group = int(escape[1:]) + if group < state.groups: + if not state.checkgroup(group): + raise source.error("cannot refer to an open group", + len(escape)) + state.checklookbehindgroup(group, source) + return GROUPREF, group + raise source.error("invalid group reference %d" % group, len(escape) - 1) + if len(escape) == 2: + if c in ASCIILETTERS: + raise source.error("bad escape %s" % escape, len(escape)) + return LITERAL, ord(escape[1]) + except ValueError: + pass + raise source.error("bad escape %s" % escape, len(escape)) + +def _uniq(items): + if len(set(items)) == len(items): + return items + newitems = [] + for item in items: + if item not in newitems: + newitems.append(item) + return newitems + +def _parse_sub(source, state, verbose, nested): + # parse an alternation: a|b|c + + items = [] + itemsappend = items.append + sourcematch = source.match + start = source.tell() + while True: + itemsappend(_parse(source, state, verbose, nested + 1, + not nested and not items)) + if not sourcematch("|"): + break + + if len(items) == 1: + return items[0] + + subpattern = SubPattern(state) + + # check if all items share a common prefix + while True: + prefix = None + for item in items: + if not item: + break + if prefix is None: + prefix = item[0] + elif item[0] != prefix: + break + else: + # all subitems start with a common "prefix". + # move it out of the branch + for item in items: + del item[0] + subpattern.append(prefix) + continue # check next one + break + + # check if the branch can be replaced by a character set + set = [] + for item in items: + if len(item) != 1: + break + op, av = item[0] + if op is LITERAL: + set.append((op, av)) + elif op is IN and av[0][0] is not NEGATE: + set.extend(av) + else: + break + else: + # we can store this as a character set instead of a + # branch (the compiler may optimize this even more) + subpattern.append((IN, _uniq(set))) + return subpattern + + subpattern.append((BRANCH, (None, items))) + return subpattern + +def _parse(source, state, verbose, nested, first=False): + # parse a simple pattern + subpattern = SubPattern(state) + + # precompute constants into local variables + subpatternappend = subpattern.append + sourceget = source.get + sourcematch = source.match + _len = len + _ord = ord + + while True: + + this = source.next + if this is None: + break # end of pattern + if this in "|)": + break # end of subpattern + sourceget() + + if verbose: + # skip whitespace and comments + if this in WHITESPACE: + continue + if this == "#": + while True: + this = sourceget() + if this is None or this == "\n": + break + continue + + if this[0] == "\\": + code = _escape(source, this, state) + subpatternappend(code) + + elif this not in SPECIAL_CHARS: + subpatternappend((LITERAL, _ord(this))) + + elif this == "[": + here = source.tell() - 1 + # character set + set = [] + setappend = set.append +## if sourcematch(":"): +## pass # handle character classes + if source.next == '[': + import warnings + warnings.warn( + 'Possible nested set at position %d' % source.tell(), + FutureWarning, stacklevel=nested + 6 + ) + negate = sourcematch("^") + # check remaining characters + while True: + this = sourceget() + if this is None: + raise source.error("unterminated character set", + source.tell() - here) + if this == "]" and set: + break + elif this[0] == "\\": + code1 = _class_escape(source, this) + else: + if set and this in '-&~|' and source.next == this: + import warnings + warnings.warn( + 'Possible set %s at position %d' % ( + 'difference' if this == '-' else + 'intersection' if this == '&' else + 'symmetric difference' if this == '~' else + 'union', + source.tell() - 1), + FutureWarning, stacklevel=nested + 6 + ) + code1 = LITERAL, _ord(this) + if sourcematch("-"): + # potential range + that = sourceget() + if that is None: + raise source.error("unterminated character set", + source.tell() - here) + if that == "]": + if code1[0] is IN: + code1 = code1[1][0] + setappend(code1) + setappend((LITERAL, _ord("-"))) + break + if that[0] == "\\": + code2 = _class_escape(source, that) + else: + if that == '-': + import warnings + warnings.warn( + 'Possible set difference at position %d' % ( + source.tell() - 2), + FutureWarning, stacklevel=nested + 6 + ) + code2 = LITERAL, _ord(that) + if code1[0] != LITERAL or code2[0] != LITERAL: + msg = "bad character range %s-%s" % (this, that) + raise source.error(msg, len(this) + 1 + len(that)) + lo = code1[1] + hi = code2[1] + if hi < lo: + msg = "bad character range %s-%s" % (this, that) + raise source.error(msg, len(this) + 1 + len(that)) + setappend((RANGE, (lo, hi))) + else: + if code1[0] is IN: + code1 = code1[1][0] + setappend(code1) + + set = _uniq(set) + # XXX: should move set optimization to compiler! + if _len(set) == 1 and set[0][0] is LITERAL: + # optimization + if negate: + subpatternappend((NOT_LITERAL, set[0][1])) + else: + subpatternappend(set[0]) + else: + if negate: + set.insert(0, (NEGATE, None)) + # charmap optimization can't be added here because + # global flags still are not known + subpatternappend((IN, set)) + + elif this in REPEAT_CHARS: + # repeat previous item + here = source.tell() + if this == "?": + min, max = 0, 1 + elif this == "*": + min, max = 0, MAXREPEAT + + elif this == "+": + min, max = 1, MAXREPEAT + elif this == "{": + if source.next == "}": + subpatternappend((LITERAL, _ord(this))) + continue + + min, max = 0, MAXREPEAT + lo = hi = "" + while source.next in DIGITS: + lo += sourceget() + if sourcematch(","): + while source.next in DIGITS: + hi += sourceget() + else: + hi = lo + if not sourcematch("}"): + subpatternappend((LITERAL, _ord(this))) + source.seek(here) + continue + + if lo: + min = int(lo) + if min >= MAXREPEAT: + raise OverflowError("the repetition number is too large") + if hi: + max = int(hi) + if max >= MAXREPEAT: + raise OverflowError("the repetition number is too large") + if max < min: + raise source.error("min repeat greater than max repeat", + source.tell() - here) + else: + raise AssertionError("unsupported quantifier %r" % (char,)) + # figure out which item to repeat + if subpattern: + item = subpattern[-1:] + else: + item = None + if not item or item[0][0] is AT: + raise source.error("nothing to repeat", + source.tell() - here + len(this)) + if item[0][0] in _REPEATCODES: + raise source.error("multiple repeat", + source.tell() - here + len(this)) + if item[0][0] is SUBPATTERN: + group, add_flags, del_flags, p = item[0][1] + if group is None and not add_flags and not del_flags: + item = p + if sourcematch("?"): + subpattern[-1] = (MIN_REPEAT, (min, max, item)) + else: + subpattern[-1] = (MAX_REPEAT, (min, max, item)) + + elif this == ".": + subpatternappend((ANY, None)) + + elif this == "(": + start = source.tell() - 1 + group = True + name = None + add_flags = 0 + del_flags = 0 + if sourcematch("?"): + # options + char = sourceget() + if char is None: + raise source.error("unexpected end of pattern") + if char == "P": + # python extensions + if sourcematch("<"): + # named group: skip forward to end of name + name = source.getuntil(">") + if not name.isidentifier(): + msg = "bad character in group name %r" % name + raise source.error(msg, len(name) + 1) + elif sourcematch("="): + # named backreference + name = source.getuntil(")") + if not name.isidentifier(): + msg = "bad character in group name %r" % name + raise source.error(msg, len(name) + 1) + gid = state.groupdict.get(name) + if gid is None: + msg = "unknown group name %r" % name + raise source.error(msg, len(name) + 1) + if not state.checkgroup(gid): + raise source.error("cannot refer to an open group", + len(name) + 1) + state.checklookbehindgroup(gid, source) + subpatternappend((GROUPREF, gid)) + continue + + else: + char = sourceget() + if char is None: + raise source.error("unexpected end of pattern") + raise source.error("unknown extension ?P" + char, + len(char) + 2) + elif char == ":": + # non-capturing group + group = None + elif char == "#": + # comment + while True: + if source.next is None: + raise source.error("missing ), unterminated comment", + source.tell() - start) + if sourceget() == ")": + break + continue + + elif char in "=!<": + # lookahead assertions + dir = 1 + if char == "<": + char = sourceget() + if char is None: + raise source.error("unexpected end of pattern") + if char not in "=!": + raise source.error("unknown extension ?<" + char, + len(char) + 2) + dir = -1 # lookbehind + lookbehindgroups = state.lookbehindgroups + if lookbehindgroups is None: + state.lookbehindgroups = state.groups + p = _parse_sub(source, state, verbose, nested + 1) + if dir < 0: + if lookbehindgroups is None: + state.lookbehindgroups = None + if not sourcematch(")"): + raise source.error("missing ), unterminated subpattern", + source.tell() - start) + if char == "=": + subpatternappend((ASSERT, (dir, p))) + else: + subpatternappend((ASSERT_NOT, (dir, p))) + continue + + elif char == "(": + # conditional backreference group + condname = source.getuntil(")") + if condname.isidentifier(): + condgroup = state.groupdict.get(condname) + if condgroup is None: + msg = "unknown group name %r" % condname + raise source.error(msg, len(condname) + 1) + else: + try: + condgroup = int(condname) + if condgroup < 0: + raise ValueError + except ValueError: + msg = "bad character in group name %r" % condname + raise source.error(msg, len(condname) + 1) from None + if not condgroup: + raise source.error("bad group number", + len(condname) + 1) + if condgroup >= MAXGROUPS: + msg = "invalid group reference %d" % condgroup + raise source.error(msg, len(condname) + 1) + state.checklookbehindgroup(condgroup, source) + item_yes = _parse(source, state, verbose, nested + 1) + if source.match("|"): + item_no = _parse(source, state, verbose, nested + 1) + if source.next == "|": + raise source.error("conditional backref with more than two branches") + else: + item_no = None + if not source.match(")"): + raise source.error("missing ), unterminated subpattern", + source.tell() - start) + subpatternappend((GROUPREF_EXISTS, (condgroup, item_yes, item_no))) + continue + + elif char in FLAGS or char == "-": + # flags + flags = _parse_flags(source, state, char) + if flags is None: # global flags + if not first or subpattern: + import warnings + warnings.warn( + 'Flags not at the start of the expression %r%s' % ( + source.string[:20], # truncate long regexes + ' (truncated)' if len(source.string) > 20 else '', + ), + DeprecationWarning, stacklevel=nested + 6 + ) + if (state.flags & SRE_FLAG_VERBOSE) and not verbose: + raise Verbose + continue + + add_flags, del_flags = flags + group = None + else: + raise source.error("unknown extension ?" + char, + len(char) + 1) + + # parse group contents + if group is not None: + try: + group = state.opengroup(name) + except error as err: + raise source.error(err.msg, len(name) + 1) from None + sub_verbose = ((verbose or (add_flags & SRE_FLAG_VERBOSE)) and + not (del_flags & SRE_FLAG_VERBOSE)) + p = _parse_sub(source, state, sub_verbose, nested + 1) + if not source.match(")"): + raise source.error("missing ), unterminated subpattern", + source.tell() - start) + if group is not None: + state.closegroup(group, p) + subpatternappend((SUBPATTERN, (group, add_flags, del_flags, p))) + + elif this == "^": + subpatternappend((AT, AT_BEGINNING)) + + elif this == "$": + subpatternappend((AT, AT_END)) + + else: + raise AssertionError("unsupported special character %r" % (char,)) + + # unpack non-capturing groups + for i in range(len(subpattern))[::-1]: + op, av = subpattern[i] + if op is SUBPATTERN: + group, add_flags, del_flags, p = av + if group is None and not add_flags and not del_flags: + subpattern[i: i+1] = p + + return subpattern + +def _parse_flags(source, state, char): + sourceget = source.get + add_flags = 0 + del_flags = 0 + if char != "-": + while True: + flag = FLAGS[char] + if source.istext: + if char == 'L': + msg = "bad inline flags: cannot use 'L' flag with a str pattern" + raise source.error(msg) + else: + if char == 'u': + msg = "bad inline flags: cannot use 'u' flag with a bytes pattern" + raise source.error(msg) + add_flags |= flag + if (flag & TYPE_FLAGS) and (add_flags & TYPE_FLAGS) != flag: + msg = "bad inline flags: flags 'a', 'u' and 'L' are incompatible" + raise source.error(msg) + char = sourceget() + if char is None: + raise source.error("missing -, : or )") + if char in ")-:": + break + if char not in FLAGS: + msg = "unknown flag" if char.isalpha() else "missing -, : or )" + raise source.error(msg, len(char)) + if char == ")": + state.flags |= add_flags + return None + if add_flags & GLOBAL_FLAGS: + raise source.error("bad inline flags: cannot turn on global flag", 1) + if char == "-": + char = sourceget() + if char is None: + raise source.error("missing flag") + if char not in FLAGS: + msg = "unknown flag" if char.isalpha() else "missing flag" + raise source.error(msg, len(char)) + while True: + flag = FLAGS[char] + if flag & TYPE_FLAGS: + msg = "bad inline flags: cannot turn off flags 'a', 'u' and 'L'" + raise source.error(msg) + del_flags |= flag + char = sourceget() + if char is None: + raise source.error("missing :") + if char == ":": + break + if char not in FLAGS: + msg = "unknown flag" if char.isalpha() else "missing :" + raise source.error(msg, len(char)) + assert char == ":" + if del_flags & GLOBAL_FLAGS: + raise source.error("bad inline flags: cannot turn off global flag", 1) + if add_flags & del_flags: + raise source.error("bad inline flags: flag turned on and off", 1) + return add_flags, del_flags + +def fix_flags(src, flags): + # Check and fix flags according to the type of pattern (str or bytes) + if isinstance(src, str): + if flags & SRE_FLAG_LOCALE: + raise ValueError("cannot use LOCALE flag with a str pattern") + if not flags & SRE_FLAG_ASCII: + flags |= SRE_FLAG_UNICODE + elif flags & SRE_FLAG_UNICODE: + raise ValueError("ASCII and UNICODE flags are incompatible") + else: + if flags & SRE_FLAG_UNICODE: + raise ValueError("cannot use UNICODE flag with a bytes pattern") + if flags & SRE_FLAG_LOCALE and flags & SRE_FLAG_ASCII: + raise ValueError("ASCII and LOCALE flags are incompatible") + return flags + +def parse(str, flags=0, pattern=None): + # parse 're' pattern into list of (opcode, argument) tuples + + source = Tokenizer(str) + + if pattern is None: + pattern = Pattern() + pattern.flags = flags + pattern.str = str + + try: + p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0) + except Verbose: + # the VERBOSE flag was switched on inside the pattern. to be + # on the safe side, we'll parse the whole thing again... + pattern = Pattern() + pattern.flags = flags | SRE_FLAG_VERBOSE + pattern.str = str + source.seek(0) + p = _parse_sub(source, pattern, True, 0) + + p.pattern.flags = fix_flags(str, p.pattern.flags) + + if source.next is not None: + assert source.next == ")" + raise source.error("unbalanced parenthesis") + + if flags & SRE_FLAG_DEBUG: + p.dump() + + return p + +def parse_template(source, pattern): + # parse 're' replacement string into list of literals and + # group references + s = Tokenizer(source) + sget = s.get + groups = [] + literals = [] + literal = [] + lappend = literal.append + def addgroup(index, pos): + if index > pattern.groups: + raise s.error("invalid group reference %d" % index, pos) + if literal: + literals.append(''.join(literal)) + del literal[:] + groups.append((len(literals), index)) + literals.append(None) + groupindex = pattern.groupindex + while True: + this = sget() + if this is None: + break # end of replacement string + if this[0] == "\\": + # group + c = this[1] + if c == "g": + name = "" + if not s.match("<"): + raise s.error("missing <") + name = s.getuntil(">") + if name.isidentifier(): + try: + index = groupindex[name] + except KeyError: + raise IndexError("unknown group name %r" % name) + else: + try: + index = int(name) + if index < 0: + raise ValueError + except ValueError: + raise s.error("bad character in group name %r" % name, + len(name) + 1) from None + if index >= MAXGROUPS: + raise s.error("invalid group reference %d" % index, + len(name) + 1) + addgroup(index, len(name) + 1) + elif c == "0": + if s.next in OCTDIGITS: + this += sget() + if s.next in OCTDIGITS: + this += sget() + lappend(chr(int(this[1:], 8) & 0xff)) + elif c in DIGITS: + isoctal = False + if s.next in DIGITS: + this += sget() + if (c in OCTDIGITS and this[2] in OCTDIGITS and + s.next in OCTDIGITS): + this += sget() + isoctal = True + c = int(this[1:], 8) + if c > 0o377: + raise s.error('octal escape value %s outside of ' + 'range 0-0o377' % this, len(this)) + lappend(chr(c)) + if not isoctal: + addgroup(int(this[1:]), len(this) - 1) + else: + try: + this = chr(ESCAPES[this][1]) + except KeyError: + if c in ASCIILETTERS: + raise s.error('bad escape %s' % this, len(this)) + lappend(this) + else: + lappend(this) + if literal: + literals.append(''.join(literal)) + if not isinstance(source, str): + # The tokenizer implicitly decodes bytes objects as latin-1, we must + # therefore re-encode the final representation. + literals = [None if s is None else s.encode('latin-1') for s in literals] + return groups, literals + +def expand_template(template, match): + g = match.group + empty = match.string[:0] + groups, literals = template + literals = literals[:] + try: + for index, group in groups: + literals[index] = g(group) or empty + except IndexError: + raise error("invalid group reference %d" % index) + return empty.join(literals) diff --git a/winvenv/Lib/stat.py b/winvenv/Lib/stat.py new file mode 100644 index 0000000..46837c0 --- /dev/null +++ b/winvenv/Lib/stat.py @@ -0,0 +1,178 @@ +"""Constants/functions for interpreting results of os.stat() and os.lstat(). + +Suggested usage: from stat import * +""" + +# Indices for stat struct members in the tuple returned by os.stat() + +ST_MODE = 0 +ST_INO = 1 +ST_DEV = 2 +ST_NLINK = 3 +ST_UID = 4 +ST_GID = 5 +ST_SIZE = 6 +ST_ATIME = 7 +ST_MTIME = 8 +ST_CTIME = 9 + +# Extract bits from the mode + +def S_IMODE(mode): + """Return the portion of the file's mode that can be set by + os.chmod(). + """ + return mode & 0o7777 + +def S_IFMT(mode): + """Return the portion of the file's mode that describes the + file type. + """ + return mode & 0o170000 + +# Constants used as S_IFMT() for various file types +# (not all are implemented on all systems) + +S_IFDIR = 0o040000 # directory +S_IFCHR = 0o020000 # character device +S_IFBLK = 0o060000 # block device +S_IFREG = 0o100000 # regular file +S_IFIFO = 0o010000 # fifo (named pipe) +S_IFLNK = 0o120000 # symbolic link +S_IFSOCK = 0o140000 # socket file + +# Functions to test for each file type + +def S_ISDIR(mode): + """Return True if mode is from a directory.""" + return S_IFMT(mode) == S_IFDIR + +def S_ISCHR(mode): + """Return True if mode is from a character special device file.""" + return S_IFMT(mode) == S_IFCHR + +def S_ISBLK(mode): + """Return True if mode is from a block special device file.""" + return S_IFMT(mode) == S_IFBLK + +def S_ISREG(mode): + """Return True if mode is from a regular file.""" + return S_IFMT(mode) == S_IFREG + +def S_ISFIFO(mode): + """Return True if mode is from a FIFO (named pipe).""" + return S_IFMT(mode) == S_IFIFO + +def S_ISLNK(mode): + """Return True if mode is from a symbolic link.""" + return S_IFMT(mode) == S_IFLNK + +def S_ISSOCK(mode): + """Return True if mode is from a socket.""" + return S_IFMT(mode) == S_IFSOCK + +# Names for permission bits + +S_ISUID = 0o4000 # set UID bit +S_ISGID = 0o2000 # set GID bit +S_ENFMT = S_ISGID # file locking enforcement +S_ISVTX = 0o1000 # sticky bit +S_IREAD = 0o0400 # Unix V7 synonym for S_IRUSR +S_IWRITE = 0o0200 # Unix V7 synonym for S_IWUSR +S_IEXEC = 0o0100 # Unix V7 synonym for S_IXUSR +S_IRWXU = 0o0700 # mask for owner permissions +S_IRUSR = 0o0400 # read by owner +S_IWUSR = 0o0200 # write by owner +S_IXUSR = 0o0100 # execute by owner +S_IRWXG = 0o0070 # mask for group permissions +S_IRGRP = 0o0040 # read by group +S_IWGRP = 0o0020 # write by group +S_IXGRP = 0o0010 # execute by group +S_IRWXO = 0o0007 # mask for others (not in group) permissions +S_IROTH = 0o0004 # read by others +S_IWOTH = 0o0002 # write by others +S_IXOTH = 0o0001 # execute by others + +# Names for file flags + +UF_NODUMP = 0x00000001 # do not dump file +UF_IMMUTABLE = 0x00000002 # file may not be changed +UF_APPEND = 0x00000004 # file may only be appended to +UF_OPAQUE = 0x00000008 # directory is opaque when viewed through a union stack +UF_NOUNLINK = 0x00000010 # file may not be renamed or deleted +UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed +UF_HIDDEN = 0x00008000 # OS X: file should not be displayed +SF_ARCHIVED = 0x00010000 # file may be archived +SF_IMMUTABLE = 0x00020000 # file may not be changed +SF_APPEND = 0x00040000 # file may only be appended to +SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted +SF_SNAPSHOT = 0x00200000 # file is a snapshot file + + +_filemode_table = ( + ((S_IFLNK, "l"), + (S_IFREG, "-"), + (S_IFBLK, "b"), + (S_IFDIR, "d"), + (S_IFCHR, "c"), + (S_IFIFO, "p")), + + ((S_IRUSR, "r"),), + ((S_IWUSR, "w"),), + ((S_IXUSR|S_ISUID, "s"), + (S_ISUID, "S"), + (S_IXUSR, "x")), + + ((S_IRGRP, "r"),), + ((S_IWGRP, "w"),), + ((S_IXGRP|S_ISGID, "s"), + (S_ISGID, "S"), + (S_IXGRP, "x")), + + ((S_IROTH, "r"),), + ((S_IWOTH, "w"),), + ((S_IXOTH|S_ISVTX, "t"), + (S_ISVTX, "T"), + (S_IXOTH, "x")) +) + +def filemode(mode): + """Convert a file's mode to a string of the form '-rwxrwxrwx'.""" + perm = [] + for table in _filemode_table: + for bit, char in table: + if mode & bit == bit: + perm.append(char) + break + else: + perm.append("-") + return "".join(perm) + + +# Windows FILE_ATTRIBUTE constants for interpreting os.stat()'s +# "st_file_attributes" member + +FILE_ATTRIBUTE_ARCHIVE = 32 +FILE_ATTRIBUTE_COMPRESSED = 2048 +FILE_ATTRIBUTE_DEVICE = 64 +FILE_ATTRIBUTE_DIRECTORY = 16 +FILE_ATTRIBUTE_ENCRYPTED = 16384 +FILE_ATTRIBUTE_HIDDEN = 2 +FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 +FILE_ATTRIBUTE_NORMAL = 128 +FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192 +FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072 +FILE_ATTRIBUTE_OFFLINE = 4096 +FILE_ATTRIBUTE_READONLY = 1 +FILE_ATTRIBUTE_REPARSE_POINT = 1024 +FILE_ATTRIBUTE_SPARSE_FILE = 512 +FILE_ATTRIBUTE_SYSTEM = 4 +FILE_ATTRIBUTE_TEMPORARY = 256 +FILE_ATTRIBUTE_VIRTUAL = 65536 + + +# If available, use C implementation +try: + from _stat import * +except ImportError: + pass diff --git a/winvenv/Lib/struct.py b/winvenv/Lib/struct.py new file mode 100644 index 0000000..d6bba58 --- /dev/null +++ b/winvenv/Lib/struct.py @@ -0,0 +1,15 @@ +__all__ = [ + # Functions + 'calcsize', 'pack', 'pack_into', 'unpack', 'unpack_from', + 'iter_unpack', + + # Classes + 'Struct', + + # Exceptions + 'error' + ] + +from _struct import * +from _struct import _clearcache +from _struct import __doc__ diff --git a/winvenv/Lib/tarfile.py b/winvenv/Lib/tarfile.py new file mode 100644 index 0000000..edd31e9 --- /dev/null +++ b/winvenv/Lib/tarfile.py @@ -0,0 +1,2539 @@ +#!/usr/bin/env python3 +#------------------------------------------------------------------- +# tarfile.py +#------------------------------------------------------------------- +# Copyright (C) 2002 Lars Gustaebel +# All rights reserved. +# +# 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. +# +"""Read from and write to tar format archives. +""" + +version = "0.9.0" +__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" +__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." + +#--------- +# Imports +#--------- +from builtins import open as bltn_open +import sys +import os +import io +import shutil +import stat +import time +import struct +import copy +import re + +try: + import pwd +except ImportError: + pwd = None +try: + import grp +except ImportError: + grp = None + +# os.symlink on Windows prior to 6.0 raises NotImplementedError +symlink_exception = (AttributeError, NotImplementedError) +try: + # OSError (winerror=1314) will be raised if the caller does not hold the + # SeCreateSymbolicLinkPrivilege privilege + symlink_exception += (OSError,) +except NameError: + pass + +# from tarfile import * +__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError", + "CompressionError", "StreamError", "ExtractError", "HeaderError", + "ENCODING", "USTAR_FORMAT", "GNU_FORMAT", "PAX_FORMAT", + "DEFAULT_FORMAT", "open"] + +#--------------------------------------------------------- +# tar constants +#--------------------------------------------------------- +NUL = b"\0" # the null character +BLOCKSIZE = 512 # length of processing blocks +RECORDSIZE = BLOCKSIZE * 20 # length of records +GNU_MAGIC = b"ustar \0" # magic gnu tar string +POSIX_MAGIC = b"ustar\x0000" # magic posix tar string + +LENGTH_NAME = 100 # maximum length of a filename +LENGTH_LINK = 100 # maximum length of a linkname +LENGTH_PREFIX = 155 # maximum length of the prefix field + +REGTYPE = b"0" # regular file +AREGTYPE = b"\0" # regular file +LNKTYPE = b"1" # link (inside tarfile) +SYMTYPE = b"2" # symbolic link +CHRTYPE = b"3" # character special device +BLKTYPE = b"4" # block special device +DIRTYPE = b"5" # directory +FIFOTYPE = b"6" # fifo special device +CONTTYPE = b"7" # contiguous file + +GNUTYPE_LONGNAME = b"L" # GNU tar longname +GNUTYPE_LONGLINK = b"K" # GNU tar longlink +GNUTYPE_SPARSE = b"S" # GNU tar sparse file + +XHDTYPE = b"x" # POSIX.1-2001 extended header +XGLTYPE = b"g" # POSIX.1-2001 global header +SOLARIS_XHDTYPE = b"X" # Solaris extended header + +USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format +GNU_FORMAT = 1 # GNU tar format +PAX_FORMAT = 2 # POSIX.1-2001 (pax) format +DEFAULT_FORMAT = GNU_FORMAT + +#--------------------------------------------------------- +# tarfile constants +#--------------------------------------------------------- +# File types that tarfile supports: +SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, + SYMTYPE, DIRTYPE, FIFOTYPE, + CONTTYPE, CHRTYPE, BLKTYPE, + GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# File types that will be treated as a regular file. +REGULAR_TYPES = (REGTYPE, AREGTYPE, + CONTTYPE, GNUTYPE_SPARSE) + +# File types that are part of the GNU tar format. +GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# Fields from a pax header that override a TarInfo attribute. +PAX_FIELDS = ("path", "linkpath", "size", "mtime", + "uid", "gid", "uname", "gname") + +# Fields from a pax header that are affected by hdrcharset. +PAX_NAME_FIELDS = {"path", "linkpath", "uname", "gname"} + +# Fields in a pax header that are numbers, all other fields +# are treated as strings. +PAX_NUMBER_FIELDS = { + "atime": float, + "ctime": float, + "mtime": float, + "uid": int, + "gid": int, + "size": int +} + +#--------------------------------------------------------- +# initialization +#--------------------------------------------------------- +if os.name == "nt": + ENCODING = "utf-8" +else: + ENCODING = sys.getfilesystemencoding() + +#--------------------------------------------------------- +# Some useful functions +#--------------------------------------------------------- + +def stn(s, length, encoding, errors): + """Convert a string to a null-terminated bytes object. + """ + s = s.encode(encoding, errors) + return s[:length] + (length - len(s)) * NUL + +def nts(s, encoding, errors): + """Convert a null-terminated bytes object to a string. + """ + p = s.find(b"\0") + if p != -1: + s = s[:p] + return s.decode(encoding, errors) + +def nti(s): + """Convert a number field to a python number. + """ + # There are two possible encodings for a number field, see + # itn() below. + if s[0] in (0o200, 0o377): + n = 0 + for i in range(len(s) - 1): + n <<= 8 + n += s[i + 1] + if s[0] == 0o377: + n = -(256 ** (len(s) - 1) - n) + else: + try: + s = nts(s, "ascii", "strict") + n = int(s.strip() or "0", 8) + except ValueError: + raise InvalidHeaderError("invalid header") + return n + +def itn(n, digits=8, format=DEFAULT_FORMAT): + """Convert a python number to a number field. + """ + # POSIX 1003.1-1988 requires numbers to be encoded as a string of + # octal digits followed by a null-byte, this allows values up to + # (8**(digits-1))-1. GNU tar allows storing numbers greater than + # that if necessary. A leading 0o200 or 0o377 byte indicate this + # particular encoding, the following digits-1 bytes are a big-endian + # base-256 representation. This allows values up to (256**(digits-1))-1. + # A 0o200 byte indicates a positive number, a 0o377 byte a negative + # number. + n = int(n) + if 0 <= n < 8 ** (digits - 1): + s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL + elif format == GNU_FORMAT and -256 ** (digits - 1) <= n < 256 ** (digits - 1): + if n >= 0: + s = bytearray([0o200]) + else: + s = bytearray([0o377]) + n = 256 ** digits + n + + for i in range(digits - 1): + s.insert(1, n & 0o377) + n >>= 8 + else: + raise ValueError("overflow in number field") + + return s + +def calc_chksums(buf): + """Calculate the checksum for a member's header by summing up all + characters except for the chksum field which is treated as if + it was filled with spaces. According to the GNU tar sources, + some tars (Sun and NeXT) calculate chksum with signed char, + which will be different if there are chars in the buffer with + the high bit set. So we calculate two checksums, unsigned and + signed. + """ + unsigned_chksum = 256 + sum(struct.unpack_from("148B8x356B", buf)) + signed_chksum = 256 + sum(struct.unpack_from("148b8x356b", buf)) + return unsigned_chksum, signed_chksum + +def copyfileobj(src, dst, length=None, exception=OSError, bufsize=None): + """Copy length bytes from fileobj src to fileobj dst. + If length is None, copy the entire content. + """ + bufsize = bufsize or 16 * 1024 + if length == 0: + return + if length is None: + shutil.copyfileobj(src, dst, bufsize) + return + + blocks, remainder = divmod(length, bufsize) + for b in range(blocks): + buf = src.read(bufsize) + if len(buf) < bufsize: + raise exception("unexpected end of data") + dst.write(buf) + + if remainder != 0: + buf = src.read(remainder) + if len(buf) < remainder: + raise exception("unexpected end of data") + dst.write(buf) + return + +def filemode(mode): + """Deprecated in this location; use stat.filemode.""" + import warnings + warnings.warn("deprecated in favor of stat.filemode", + DeprecationWarning, 2) + return stat.filemode(mode) + +def _safe_print(s): + encoding = getattr(sys.stdout, 'encoding', None) + if encoding is not None: + s = s.encode(encoding, 'backslashreplace').decode(encoding) + print(s, end=' ') + + +class TarError(Exception): + """Base exception.""" + pass +class ExtractError(TarError): + """General exception for extract errors.""" + pass +class ReadError(TarError): + """Exception for unreadable tar archives.""" + pass +class CompressionError(TarError): + """Exception for unavailable compression methods.""" + pass +class StreamError(TarError): + """Exception for unsupported operations on stream-like TarFiles.""" + pass +class HeaderError(TarError): + """Base exception for header errors.""" + pass +class EmptyHeaderError(HeaderError): + """Exception for empty headers.""" + pass +class TruncatedHeaderError(HeaderError): + """Exception for truncated headers.""" + pass +class EOFHeaderError(HeaderError): + """Exception for end of file headers.""" + pass +class InvalidHeaderError(HeaderError): + """Exception for invalid headers.""" + pass +class SubsequentHeaderError(HeaderError): + """Exception for missing and invalid extended headers.""" + pass + +#--------------------------- +# internal stream interface +#--------------------------- +class _LowLevelFile: + """Low-level file object. Supports reading and writing. + It is used instead of a regular file object for streaming + access. + """ + + def __init__(self, name, mode): + mode = { + "r": os.O_RDONLY, + "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + }[mode] + if hasattr(os, "O_BINARY"): + mode |= os.O_BINARY + self.fd = os.open(name, mode, 0o666) + + def close(self): + os.close(self.fd) + + def read(self, size): + return os.read(self.fd, size) + + def write(self, s): + os.write(self.fd, s) + +class _Stream: + """Class that serves as an adapter between TarFile and + a stream-like object. The stream-like object only + needs to have a read() or write() method and is accessed + blockwise. Use of gzip or bzip2 compression is possible. + A stream-like object could be for example: sys.stdin, + sys.stdout, a socket, a tape device etc. + + _Stream is intended to be used only internally. + """ + + def __init__(self, name, mode, comptype, fileobj, bufsize): + """Construct a _Stream object. + """ + self._extfileobj = True + if fileobj is None: + fileobj = _LowLevelFile(name, mode) + self._extfileobj = False + + if comptype == '*': + # Enable transparent compression detection for the + # stream interface + fileobj = _StreamProxy(fileobj) + comptype = fileobj.getcomptype() + + self.name = name or "" + self.mode = mode + self.comptype = comptype + self.fileobj = fileobj + self.bufsize = bufsize + self.buf = b"" + self.pos = 0 + self.closed = False + + try: + if comptype == "gz": + try: + import zlib + except ImportError: + raise CompressionError("zlib module is not available") + self.zlib = zlib + self.crc = zlib.crc32(b"") + if mode == "r": + self._init_read_gz() + self.exception = zlib.error + else: + self._init_write_gz() + + elif comptype == "bz2": + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + if mode == "r": + self.dbuf = b"" + self.cmp = bz2.BZ2Decompressor() + self.exception = OSError + else: + self.cmp = bz2.BZ2Compressor() + + elif comptype == "xz": + try: + import lzma + except ImportError: + raise CompressionError("lzma module is not available") + if mode == "r": + self.dbuf = b"" + self.cmp = lzma.LZMADecompressor() + self.exception = lzma.LZMAError + else: + self.cmp = lzma.LZMACompressor() + + elif comptype != "tar": + raise CompressionError("unknown compression type %r" % comptype) + + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + def __del__(self): + if hasattr(self, "closed") and not self.closed: + self.close() + + def _init_write_gz(self): + """Initialize for writing with gzip compression. + """ + self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, + -self.zlib.MAX_WBITS, + self.zlib.DEF_MEM_LEVEL, + 0) + timestamp = struct.pack(" self.bufsize: + self.fileobj.write(self.buf[:self.bufsize]) + self.buf = self.buf[self.bufsize:] + + def close(self): + """Close the _Stream object. No operation should be + done on it afterwards. + """ + if self.closed: + return + + self.closed = True + try: + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() + + if self.mode == "w" and self.buf: + self.fileobj.write(self.buf) + self.buf = b"" + if self.comptype == "gz": + self.fileobj.write(struct.pack("= 0: + blocks, remainder = divmod(pos - self.pos, self.bufsize) + for i in range(blocks): + self.read(self.bufsize) + self.read(remainder) + else: + raise StreamError("seeking backwards is not allowed") + return self.pos + + def read(self, size=None): + """Return the next size number of bytes from the stream. + If size is not defined, return all bytes of the stream + up to EOF. + """ + if size is None: + t = [] + while True: + buf = self._read(self.bufsize) + if not buf: + break + t.append(buf) + buf = b"".join(t) + else: + buf = self._read(size) + self.pos += len(buf) + return buf + + def _read(self, size): + """Return size bytes from the stream. + """ + if self.comptype == "tar": + return self.__read(size) + + c = len(self.dbuf) + t = [self.dbuf] + while c < size: + buf = self.__read(self.bufsize) + if not buf: + break + try: + buf = self.cmp.decompress(buf) + except self.exception: + raise ReadError("invalid compressed data") + t.append(buf) + c += len(buf) + t = b"".join(t) + self.dbuf = t[size:] + return t[:size] + + def __read(self, size): + """Return size bytes from stream. If internal buffer is empty, + read another block from the stream. + """ + c = len(self.buf) + t = [self.buf] + while c < size: + buf = self.fileobj.read(self.bufsize) + if not buf: + break + t.append(buf) + c += len(buf) + t = b"".join(t) + self.buf = t[size:] + return t[:size] +# class _Stream + +class _StreamProxy(object): + """Small proxy class that enables transparent compression + detection for the Stream interface (mode 'r|*'). + """ + + def __init__(self, fileobj): + self.fileobj = fileobj + self.buf = self.fileobj.read(BLOCKSIZE) + + def read(self, size): + self.read = self.fileobj.read + return self.buf + + def getcomptype(self): + if self.buf.startswith(b"\x1f\x8b\x08"): + return "gz" + elif self.buf[0:3] == b"BZh" and self.buf[4:10] == b"1AY&SY": + return "bz2" + elif self.buf.startswith((b"\x5d\x00\x00\x80", b"\xfd7zXZ")): + return "xz" + else: + return "tar" + + def close(self): + self.fileobj.close() +# class StreamProxy + +#------------------------ +# Extraction file object +#------------------------ +class _FileInFile(object): + """A thin wrapper around an existing file object that + provides a part of its data as an individual file + object. + """ + + def __init__(self, fileobj, offset, size, blockinfo=None): + self.fileobj = fileobj + self.offset = offset + self.size = size + self.position = 0 + self.name = getattr(fileobj, "name", None) + self.closed = False + + if blockinfo is None: + blockinfo = [(0, size)] + + # Construct a map with data and zero blocks. + self.map_index = 0 + self.map = [] + lastpos = 0 + realpos = self.offset + for offset, size in blockinfo: + if offset > lastpos: + self.map.append((False, lastpos, offset, None)) + self.map.append((True, offset, offset + size, realpos)) + realpos += size + lastpos = offset + size + if lastpos < self.size: + self.map.append((False, lastpos, self.size, None)) + + def flush(self): + pass + + def readable(self): + return True + + def writable(self): + return False + + def seekable(self): + return self.fileobj.seekable() + + def tell(self): + """Return the current file position. + """ + return self.position + + def seek(self, position, whence=io.SEEK_SET): + """Seek to a position in the file. + """ + if whence == io.SEEK_SET: + self.position = min(max(position, 0), self.size) + elif whence == io.SEEK_CUR: + if position < 0: + self.position = max(self.position + position, 0) + else: + self.position = min(self.position + position, self.size) + elif whence == io.SEEK_END: + self.position = max(min(self.size + position, self.size), 0) + else: + raise ValueError("Invalid argument") + return self.position + + def read(self, size=None): + """Read data from the file. + """ + if size is None: + size = self.size - self.position + else: + size = min(size, self.size - self.position) + + buf = b"" + while size > 0: + while True: + data, start, stop, offset = self.map[self.map_index] + if start <= self.position < stop: + break + else: + self.map_index += 1 + if self.map_index == len(self.map): + self.map_index = 0 + length = min(size, stop - self.position) + if data: + self.fileobj.seek(offset + (self.position - start)) + b = self.fileobj.read(length) + if len(b) != length: + raise ReadError("unexpected end of data") + buf += b + else: + buf += NUL * length + size -= length + self.position += length + return buf + + def readinto(self, b): + buf = self.read(len(b)) + b[:len(buf)] = buf + return len(buf) + + def close(self): + self.closed = True +#class _FileInFile + +class ExFileObject(io.BufferedReader): + + def __init__(self, tarfile, tarinfo): + fileobj = _FileInFile(tarfile.fileobj, tarinfo.offset_data, + tarinfo.size, tarinfo.sparse) + super().__init__(fileobj) +#class ExFileObject + +#------------------ +# Exported Classes +#------------------ +class TarInfo(object): + """Informational class which holds the details about an + archive member given by a tar header block. + TarInfo objects are returned by TarFile.getmember(), + TarFile.getmembers() and TarFile.gettarinfo() and are + usually created internally. + """ + + __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", + "chksum", "type", "linkname", "uname", "gname", + "devmajor", "devminor", + "offset", "offset_data", "pax_headers", "sparse", + "tarfile", "_sparse_structs", "_link_target") + + def __init__(self, name=""): + """Construct a TarInfo object. name is the optional name + of the member. + """ + self.name = name # member name + self.mode = 0o644 # file permissions + self.uid = 0 # user id + self.gid = 0 # group id + self.size = 0 # file size + self.mtime = 0 # modification time + self.chksum = 0 # header checksum + self.type = REGTYPE # member type + self.linkname = "" # link name + self.uname = "" # user name + self.gname = "" # group name + self.devmajor = 0 # device major number + self.devminor = 0 # device minor number + + self.offset = 0 # the tar header starts here + self.offset_data = 0 # the file's data starts here + + self.sparse = None # sparse member information + self.pax_headers = {} # pax header information + + # In pax headers the "name" and "linkname" field are called + # "path" and "linkpath". + @property + def path(self): + return self.name + + @path.setter + def path(self, name): + self.name = name + + @property + def linkpath(self): + return self.linkname + + @linkpath.setter + def linkpath(self, linkname): + self.linkname = linkname + + def __repr__(self): + return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) + + def get_info(self): + """Return the TarInfo's attributes as a dictionary. + """ + info = { + "name": self.name, + "mode": self.mode & 0o7777, + "uid": self.uid, + "gid": self.gid, + "size": self.size, + "mtime": self.mtime, + "chksum": self.chksum, + "type": self.type, + "linkname": self.linkname, + "uname": self.uname, + "gname": self.gname, + "devmajor": self.devmajor, + "devminor": self.devminor + } + + if info["type"] == DIRTYPE and not info["name"].endswith("/"): + info["name"] += "/" + + return info + + def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): + """Return a tar header as a string of 512 byte blocks. + """ + info = self.get_info() + + if format == USTAR_FORMAT: + return self.create_ustar_header(info, encoding, errors) + elif format == GNU_FORMAT: + return self.create_gnu_header(info, encoding, errors) + elif format == PAX_FORMAT: + return self.create_pax_header(info, encoding) + else: + raise ValueError("invalid format") + + def create_ustar_header(self, info, encoding, errors): + """Return the object as a ustar header block. + """ + info["magic"] = POSIX_MAGIC + + if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK: + raise ValueError("linkname is too long") + + if len(info["name"].encode(encoding, errors)) > LENGTH_NAME: + info["prefix"], info["name"] = self._posix_split_name(info["name"], encoding, errors) + + return self._create_header(info, USTAR_FORMAT, encoding, errors) + + def create_gnu_header(self, info, encoding, errors): + """Return the object as a GNU header block sequence. + """ + info["magic"] = GNU_MAGIC + + buf = b"" + if len(info["linkname"].encode(encoding, errors)) > LENGTH_LINK: + buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) + + if len(info["name"].encode(encoding, errors)) > LENGTH_NAME: + buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) + + return buf + self._create_header(info, GNU_FORMAT, encoding, errors) + + def create_pax_header(self, info, encoding): + """Return the object as a ustar header block. If it cannot be + represented this way, prepend a pax extended header sequence + with supplement information. + """ + info["magic"] = POSIX_MAGIC + pax_headers = self.pax_headers.copy() + + # Test string fields for values that exceed the field length or cannot + # be represented in ASCII encoding. + for name, hname, length in ( + ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), + ("uname", "uname", 32), ("gname", "gname", 32)): + + if hname in pax_headers: + # The pax header has priority. + continue + + # Try to encode the string as ASCII. + try: + info[name].encode("ascii", "strict") + except UnicodeEncodeError: + pax_headers[hname] = info[name] + continue + + if len(info[name]) > length: + pax_headers[hname] = info[name] + + # Test number fields for values that exceed the field limit or values + # that like to be stored as float. + for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): + if name in pax_headers: + # The pax header has priority. Avoid overflow. + info[name] = 0 + continue + + val = info[name] + if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): + pax_headers[name] = str(val) + info[name] = 0 + + # Create a pax extended header if necessary. + if pax_headers: + buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) + else: + buf = b"" + + return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") + + @classmethod + def create_pax_global_header(cls, pax_headers): + """Return the object as a pax global header block sequence. + """ + return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf-8") + + def _posix_split_name(self, name, encoding, errors): + """Split a name longer than 100 chars into a prefix + and a name part. + """ + components = name.split("/") + for i in range(1, len(components)): + prefix = "/".join(components[:i]) + name = "/".join(components[i:]) + if len(prefix.encode(encoding, errors)) <= LENGTH_PREFIX and \ + len(name.encode(encoding, errors)) <= LENGTH_NAME: + break + else: + raise ValueError("name is too long") + + return prefix, name + + @staticmethod + def _create_header(info, format, encoding, errors): + """Return a header block. info is a dictionary with file + information, format must be one of the *_FORMAT constants. + """ + parts = [ + stn(info.get("name", ""), 100, encoding, errors), + itn(info.get("mode", 0) & 0o7777, 8, format), + itn(info.get("uid", 0), 8, format), + itn(info.get("gid", 0), 8, format), + itn(info.get("size", 0), 12, format), + itn(info.get("mtime", 0), 12, format), + b" ", # checksum field + info.get("type", REGTYPE), + stn(info.get("linkname", ""), 100, encoding, errors), + info.get("magic", POSIX_MAGIC), + stn(info.get("uname", ""), 32, encoding, errors), + stn(info.get("gname", ""), 32, encoding, errors), + itn(info.get("devmajor", 0), 8, format), + itn(info.get("devminor", 0), 8, format), + stn(info.get("prefix", ""), 155, encoding, errors) + ] + + buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) + chksum = calc_chksums(buf[-BLOCKSIZE:])[0] + buf = buf[:-364] + bytes("%06o\0" % chksum, "ascii") + buf[-357:] + return buf + + @staticmethod + def _create_payload(payload): + """Return the string payload filled with zero bytes + up to the next 512 byte border. + """ + blocks, remainder = divmod(len(payload), BLOCKSIZE) + if remainder > 0: + payload += (BLOCKSIZE - remainder) * NUL + return payload + + @classmethod + def _create_gnu_long_header(cls, name, type, encoding, errors): + """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence + for name. + """ + name = name.encode(encoding, errors) + NUL + + info = {} + info["name"] = "././@LongLink" + info["type"] = type + info["size"] = len(name) + info["magic"] = GNU_MAGIC + + # create extended header + name blocks. + return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ + cls._create_payload(name) + + @classmethod + def _create_pax_generic_header(cls, pax_headers, type, encoding): + """Return a POSIX.1-2008 extended or global header sequence + that contains a list of keyword, value pairs. The values + must be strings. + """ + # Check if one of the fields contains surrogate characters and thereby + # forces hdrcharset=BINARY, see _proc_pax() for more information. + binary = False + for keyword, value in pax_headers.items(): + try: + value.encode("utf-8", "strict") + except UnicodeEncodeError: + binary = True + break + + records = b"" + if binary: + # Put the hdrcharset field at the beginning of the header. + records += b"21 hdrcharset=BINARY\n" + + for keyword, value in pax_headers.items(): + keyword = keyword.encode("utf-8") + if binary: + # Try to restore the original byte representation of `value'. + # Needless to say, that the encoding must match the string. + value = value.encode(encoding, "surrogateescape") + else: + value = value.encode("utf-8") + + l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' + n = p = 0 + while True: + n = l + len(str(p)) + if n == p: + break + p = n + records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" + + # We use a hardcoded "././@PaxHeader" name like star does + # instead of the one that POSIX recommends. + info = {} + info["name"] = "././@PaxHeader" + info["type"] = type + info["size"] = len(records) + info["magic"] = POSIX_MAGIC + + # Create pax header + record blocks. + return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ + cls._create_payload(records) + + @classmethod + def frombuf(cls, buf, encoding, errors): + """Construct a TarInfo object from a 512 byte bytes object. + """ + if len(buf) == 0: + raise EmptyHeaderError("empty header") + if len(buf) != BLOCKSIZE: + raise TruncatedHeaderError("truncated header") + if buf.count(NUL) == BLOCKSIZE: + raise EOFHeaderError("end of file header") + + chksum = nti(buf[148:156]) + if chksum not in calc_chksums(buf): + raise InvalidHeaderError("bad checksum") + + obj = cls() + obj.name = nts(buf[0:100], encoding, errors) + obj.mode = nti(buf[100:108]) + obj.uid = nti(buf[108:116]) + obj.gid = nti(buf[116:124]) + obj.size = nti(buf[124:136]) + obj.mtime = nti(buf[136:148]) + obj.chksum = chksum + obj.type = buf[156:157] + obj.linkname = nts(buf[157:257], encoding, errors) + obj.uname = nts(buf[265:297], encoding, errors) + obj.gname = nts(buf[297:329], encoding, errors) + obj.devmajor = nti(buf[329:337]) + obj.devminor = nti(buf[337:345]) + prefix = nts(buf[345:500], encoding, errors) + + # Old V7 tar format represents a directory as a regular + # file with a trailing slash. + if obj.type == AREGTYPE and obj.name.endswith("/"): + obj.type = DIRTYPE + + # The old GNU sparse format occupies some of the unused + # space in the buffer for up to 4 sparse structures. + # Save them for later processing in _proc_sparse(). + if obj.type == GNUTYPE_SPARSE: + pos = 386 + structs = [] + for i in range(4): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[482]) + origsize = nti(buf[483:495]) + obj._sparse_structs = (structs, isextended, origsize) + + # Remove redundant slashes from directories. + if obj.isdir(): + obj.name = obj.name.rstrip("/") + + # Reconstruct a ustar longname. + if prefix and obj.type not in GNU_TYPES: + obj.name = prefix + "/" + obj.name + return obj + + @classmethod + def fromtarfile(cls, tarfile): + """Return the next TarInfo object from TarFile object + tarfile. + """ + buf = tarfile.fileobj.read(BLOCKSIZE) + obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) + obj.offset = tarfile.fileobj.tell() - BLOCKSIZE + return obj._proc_member(tarfile) + + #-------------------------------------------------------------------------- + # The following are methods that are called depending on the type of a + # member. The entry point is _proc_member() which can be overridden in a + # subclass to add custom _proc_*() methods. A _proc_*() method MUST + # implement the following + # operations: + # 1. Set self.offset_data to the position where the data blocks begin, + # if there is data that follows. + # 2. Set tarfile.offset to the position where the next member's header will + # begin. + # 3. Return self or another valid TarInfo object. + def _proc_member(self, tarfile): + """Choose the right processing method depending on + the type and call it. + """ + if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): + return self._proc_gnulong(tarfile) + elif self.type == GNUTYPE_SPARSE: + return self._proc_sparse(tarfile) + elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): + return self._proc_pax(tarfile) + else: + return self._proc_builtin(tarfile) + + def _proc_builtin(self, tarfile): + """Process a builtin type or an unknown type which + will be treated as a regular file. + """ + self.offset_data = tarfile.fileobj.tell() + offset = self.offset_data + if self.isreg() or self.type not in SUPPORTED_TYPES: + # Skip the following data blocks. + offset += self._block(self.size) + tarfile.offset = offset + + # Patch the TarInfo object with saved global + # header information. + self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) + + return self + + def _proc_gnulong(self, tarfile): + """Process the blocks that hold a GNU longname + or longlink member. + """ + buf = tarfile.fileobj.read(self._block(self.size)) + + # Fetch the next header and process it. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Patch the TarInfo object from the next header with + # the longname information. + next.offset = self.offset + if self.type == GNUTYPE_LONGNAME: + next.name = nts(buf, tarfile.encoding, tarfile.errors) + elif self.type == GNUTYPE_LONGLINK: + next.linkname = nts(buf, tarfile.encoding, tarfile.errors) + + return next + + def _proc_sparse(self, tarfile): + """Process a GNU sparse header plus extra headers. + """ + # We already collected some sparse structures in frombuf(). + structs, isextended, origsize = self._sparse_structs + del self._sparse_structs + + # Collect sparse structures from extended header blocks. + while isextended: + buf = tarfile.fileobj.read(BLOCKSIZE) + pos = 0 + for i in range(21): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + if offset and numbytes: + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[504]) + self.sparse = structs + + self.offset_data = tarfile.fileobj.tell() + tarfile.offset = self.offset_data + self._block(self.size) + self.size = origsize + return self + + def _proc_pax(self, tarfile): + """Process an extended or global header as described in + POSIX.1-2008. + """ + # Read the header information. + buf = tarfile.fileobj.read(self._block(self.size)) + + # A pax header stores supplemental information for either + # the following file (extended) or all following files + # (global). + if self.type == XGLTYPE: + pax_headers = tarfile.pax_headers + else: + pax_headers = tarfile.pax_headers.copy() + + # Check if the pax header contains a hdrcharset field. This tells us + # the encoding of the path, linkpath, uname and gname fields. Normally, + # these fields are UTF-8 encoded but since POSIX.1-2008 tar + # implementations are allowed to store them as raw binary strings if + # the translation to UTF-8 fails. + match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) + if match is not None: + pax_headers["hdrcharset"] = match.group(1).decode("utf-8") + + # For the time being, we don't care about anything other than "BINARY". + # The only other value that is currently allowed by the standard is + # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. + hdrcharset = pax_headers.get("hdrcharset") + if hdrcharset == "BINARY": + encoding = tarfile.encoding + else: + encoding = "utf-8" + + # Parse pax header information. A record looks like that: + # "%d %s=%s\n" % (length, keyword, value). length is the size + # of the complete record including the length field itself and + # the newline. keyword and value are both UTF-8 encoded strings. + regex = re.compile(br"(\d+) ([^=]+)=") + pos = 0 + while True: + match = regex.match(buf, pos) + if not match: + break + + length, keyword = match.groups() + length = int(length) + value = buf[match.end(2) + 1:match.start(1) + length - 1] + + # Normally, we could just use "utf-8" as the encoding and "strict" + # as the error handler, but we better not take the risk. For + # example, GNU tar <= 1.23 is known to store filenames it cannot + # translate to UTF-8 as raw strings (unfortunately without a + # hdrcharset=BINARY header). + # We first try the strict standard encoding, and if that fails we + # fall back on the user's encoding and error handler. + keyword = self._decode_pax_field(keyword, "utf-8", "utf-8", + tarfile.errors) + if keyword in PAX_NAME_FIELDS: + value = self._decode_pax_field(value, encoding, tarfile.encoding, + tarfile.errors) + else: + value = self._decode_pax_field(value, "utf-8", "utf-8", + tarfile.errors) + + pax_headers[keyword] = value + pos += length + + # Fetch the next header. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Process GNU sparse information. + if "GNU.sparse.map" in pax_headers: + # GNU extended sparse format version 0.1. + self._proc_gnusparse_01(next, pax_headers) + + elif "GNU.sparse.size" in pax_headers: + # GNU extended sparse format version 0.0. + self._proc_gnusparse_00(next, pax_headers, buf) + + elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": + # GNU extended sparse format version 1.0. + self._proc_gnusparse_10(next, pax_headers, tarfile) + + if self.type in (XHDTYPE, SOLARIS_XHDTYPE): + # Patch the TarInfo object with the extended header info. + next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) + next.offset = self.offset + + if "size" in pax_headers: + # If the extended header replaces the size field, + # we need to recalculate the offset where the next + # header starts. + offset = next.offset_data + if next.isreg() or next.type not in SUPPORTED_TYPES: + offset += next._block(next.size) + tarfile.offset = offset + + return next + + def _proc_gnusparse_00(self, next, pax_headers, buf): + """Process a GNU tar extended sparse header, version 0.0. + """ + offsets = [] + for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): + offsets.append(int(match.group(1))) + numbytes = [] + for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): + numbytes.append(int(match.group(1))) + next.sparse = list(zip(offsets, numbytes)) + + def _proc_gnusparse_01(self, next, pax_headers): + """Process a GNU tar extended sparse header, version 0.1. + """ + sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _proc_gnusparse_10(self, next, pax_headers, tarfile): + """Process a GNU tar extended sparse header, version 1.0. + """ + fields = None + sparse = [] + buf = tarfile.fileobj.read(BLOCKSIZE) + fields, buf = buf.split(b"\n", 1) + fields = int(fields) + while len(sparse) < fields * 2: + if b"\n" not in buf: + buf += tarfile.fileobj.read(BLOCKSIZE) + number, buf = buf.split(b"\n", 1) + sparse.append(int(number)) + next.offset_data = tarfile.fileobj.tell() + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _apply_pax_info(self, pax_headers, encoding, errors): + """Replace fields with supplemental information from a previous + pax extended or global header. + """ + for keyword, value in pax_headers.items(): + if keyword == "GNU.sparse.name": + setattr(self, "path", value) + elif keyword == "GNU.sparse.size": + setattr(self, "size", int(value)) + elif keyword == "GNU.sparse.realsize": + setattr(self, "size", int(value)) + elif keyword in PAX_FIELDS: + if keyword in PAX_NUMBER_FIELDS: + try: + value = PAX_NUMBER_FIELDS[keyword](value) + except ValueError: + value = 0 + if keyword == "path": + value = value.rstrip("/") + setattr(self, keyword, value) + + self.pax_headers = pax_headers.copy() + + def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): + """Decode a single field from a pax record. + """ + try: + return value.decode(encoding, "strict") + except UnicodeDecodeError: + return value.decode(fallback_encoding, fallback_errors) + + def _block(self, count): + """Round up a byte count by BLOCKSIZE and return it, + e.g. _block(834) => 1024. + """ + blocks, remainder = divmod(count, BLOCKSIZE) + if remainder: + blocks += 1 + return blocks * BLOCKSIZE + + def isreg(self): + return self.type in REGULAR_TYPES + def isfile(self): + return self.isreg() + def isdir(self): + return self.type == DIRTYPE + def issym(self): + return self.type == SYMTYPE + def islnk(self): + return self.type == LNKTYPE + def ischr(self): + return self.type == CHRTYPE + def isblk(self): + return self.type == BLKTYPE + def isfifo(self): + return self.type == FIFOTYPE + def issparse(self): + return self.sparse is not None + def isdev(self): + return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) +# class TarInfo + +class TarFile(object): + """The TarFile Class provides an interface to tar archives. + """ + + debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) + + dereference = False # If true, add content of linked file to the + # tar file, else the link. + + ignore_zeros = False # If true, skips empty or invalid blocks and + # continues processing. + + errorlevel = 1 # If 0, fatal errors only appear in debug + # messages (if debug >= 0). If > 0, errors + # are passed to the caller as exceptions. + + format = DEFAULT_FORMAT # The format to use when creating an archive. + + encoding = ENCODING # Encoding for 8-bit character strings. + + errors = None # Error handler for unicode conversion. + + tarinfo = TarInfo # The default TarInfo class to use. + + fileobject = ExFileObject # The file-object for extractfile(). + + def __init__(self, name=None, mode="r", fileobj=None, format=None, + tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, + errors="surrogateescape", pax_headers=None, debug=None, + errorlevel=None, copybufsize=None): + """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to + read from an existing archive, 'a' to append data to an existing + file or 'w' to create a new file overwriting an existing one. `mode' + defaults to 'r'. + If `fileobj' is given, it is used for reading or writing data. If it + can be determined, `mode' is overridden by `fileobj's mode. + `fileobj' is not closed, when TarFile is closed. + """ + modes = {"r": "rb", "a": "r+b", "w": "wb", "x": "xb"} + if mode not in modes: + raise ValueError("mode must be 'r', 'a', 'w' or 'x'") + self.mode = mode + self._mode = modes[mode] + + if not fileobj: + if self.mode == "a" and not os.path.exists(name): + # Create nonexistent files in append mode. + self.mode = "w" + self._mode = "wb" + fileobj = bltn_open(name, self._mode) + self._extfileobj = False + else: + if (name is None and hasattr(fileobj, "name") and + isinstance(fileobj.name, (str, bytes))): + name = fileobj.name + if hasattr(fileobj, "mode"): + self._mode = fileobj.mode + self._extfileobj = True + self.name = os.path.abspath(name) if name else None + self.fileobj = fileobj + + # Init attributes. + if format is not None: + self.format = format + if tarinfo is not None: + self.tarinfo = tarinfo + if dereference is not None: + self.dereference = dereference + if ignore_zeros is not None: + self.ignore_zeros = ignore_zeros + if encoding is not None: + self.encoding = encoding + self.errors = errors + + if pax_headers is not None and self.format == PAX_FORMAT: + self.pax_headers = pax_headers + else: + self.pax_headers = {} + + if debug is not None: + self.debug = debug + if errorlevel is not None: + self.errorlevel = errorlevel + + # Init datastructures. + self.copybufsize = copybufsize + self.closed = False + self.members = [] # list of members as TarInfo objects + self._loaded = False # flag if all members have been read + self.offset = self.fileobj.tell() + # current position in the archive file + self.inodes = {} # dictionary caching the inodes of + # archive members already added + + try: + if self.mode == "r": + self.firstmember = None + self.firstmember = self.next() + + if self.mode == "a": + # Move to the end of the archive, + # before the first empty block. + while True: + self.fileobj.seek(self.offset) + try: + tarinfo = self.tarinfo.fromtarfile(self) + self.members.append(tarinfo) + except EOFHeaderError: + self.fileobj.seek(self.offset) + break + except HeaderError as e: + raise ReadError(str(e)) + + if self.mode in ("a", "w", "x"): + self._loaded = True + + if self.pax_headers: + buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) + self.fileobj.write(buf) + self.offset += len(buf) + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + #-------------------------------------------------------------------------- + # Below are the classmethods which act as alternate constructors to the + # TarFile class. The open() method is the only one that is needed for + # public use; it is the "super"-constructor and is able to select an + # adequate "sub"-constructor for a particular compression using the mapping + # from OPEN_METH. + # + # This concept allows one to subclass TarFile without losing the comfort of + # the super-constructor. A sub-constructor is registered and made available + # by adding it to the mapping in OPEN_METH. + + @classmethod + def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): + """Open a tar archive for reading, writing or appending. Return + an appropriate TarFile class. + + mode: + 'r' or 'r:*' open for reading with transparent compression + 'r:' open for reading exclusively uncompressed + 'r:gz' open for reading with gzip compression + 'r:bz2' open for reading with bzip2 compression + 'r:xz' open for reading with lzma compression + 'a' or 'a:' open for appending, creating the file if necessary + 'w' or 'w:' open for writing without compression + 'w:gz' open for writing with gzip compression + 'w:bz2' open for writing with bzip2 compression + 'w:xz' open for writing with lzma compression + + 'x' or 'x:' create a tarfile exclusively without compression, raise + an exception if the file is already created + 'x:gz' create a gzip compressed tarfile, raise an exception + if the file is already created + 'x:bz2' create a bzip2 compressed tarfile, raise an exception + if the file is already created + 'x:xz' create an lzma compressed tarfile, raise an exception + if the file is already created + + 'r|*' open a stream of tar blocks with transparent compression + 'r|' open an uncompressed stream of tar blocks for reading + 'r|gz' open a gzip compressed stream of tar blocks + 'r|bz2' open a bzip2 compressed stream of tar blocks + 'r|xz' open an lzma compressed stream of tar blocks + 'w|' open an uncompressed stream for writing + 'w|gz' open a gzip compressed stream for writing + 'w|bz2' open a bzip2 compressed stream for writing + 'w|xz' open an lzma compressed stream for writing + """ + + if not name and not fileobj: + raise ValueError("nothing to open") + + if mode in ("r", "r:*"): + # Find out which *open() is appropriate for opening the file. + def not_compressed(comptype): + return cls.OPEN_METH[comptype] == 'taropen' + for comptype in sorted(cls.OPEN_METH, key=not_compressed): + func = getattr(cls, cls.OPEN_METH[comptype]) + if fileobj is not None: + saved_pos = fileobj.tell() + try: + return func(name, "r", fileobj, **kwargs) + except (ReadError, CompressionError): + if fileobj is not None: + fileobj.seek(saved_pos) + continue + raise ReadError("file could not be opened successfully") + + elif ":" in mode: + filemode, comptype = mode.split(":", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + # Select the *open() function according to + # given compression. + if comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + else: + raise CompressionError("unknown compression type %r" % comptype) + return func(name, filemode, fileobj, **kwargs) + + elif "|" in mode: + filemode, comptype = mode.split("|", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + if filemode not in ("r", "w"): + raise ValueError("mode must be 'r' or 'w'") + + stream = _Stream(name, filemode, comptype, fileobj, bufsize) + try: + t = cls(name, filemode, stream, **kwargs) + except: + stream.close() + raise + t._extfileobj = False + return t + + elif mode in ("a", "w", "x"): + return cls.taropen(name, mode, fileobj, **kwargs) + + raise ValueError("undiscernible mode") + + @classmethod + def taropen(cls, name, mode="r", fileobj=None, **kwargs): + """Open uncompressed tar archive name for reading or writing. + """ + if mode not in ("r", "a", "w", "x"): + raise ValueError("mode must be 'r', 'a', 'w' or 'x'") + return cls(name, mode, fileobj, **kwargs) + + @classmethod + def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open gzip compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if mode not in ("r", "w", "x"): + raise ValueError("mode must be 'r', 'w' or 'x'") + + try: + import gzip + gzip.GzipFile + except (ImportError, AttributeError): + raise CompressionError("gzip module is not available") + + try: + fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + except OSError: + if fileobj is not None and mode == 'r': + raise ReadError("not a gzip file") + raise + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except OSError: + fileobj.close() + if mode == 'r': + raise ReadError("not a gzip file") + raise + except: + fileobj.close() + raise + t._extfileobj = False + return t + + @classmethod + def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open bzip2 compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if mode not in ("r", "w", "x"): + raise ValueError("mode must be 'r', 'w' or 'x'") + + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + + fileobj = bz2.BZ2File(fileobj or name, mode, + compresslevel=compresslevel) + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except (OSError, EOFError): + fileobj.close() + if mode == 'r': + raise ReadError("not a bzip2 file") + raise + except: + fileobj.close() + raise + t._extfileobj = False + return t + + @classmethod + def xzopen(cls, name, mode="r", fileobj=None, preset=None, **kwargs): + """Open lzma compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if mode not in ("r", "w", "x"): + raise ValueError("mode must be 'r', 'w' or 'x'") + + try: + import lzma + except ImportError: + raise CompressionError("lzma module is not available") + + fileobj = lzma.LZMAFile(fileobj or name, mode, preset=preset) + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except (lzma.LZMAError, EOFError): + fileobj.close() + if mode == 'r': + raise ReadError("not an lzma file") + raise + except: + fileobj.close() + raise + t._extfileobj = False + return t + + # All *open() methods are registered here. + OPEN_METH = { + "tar": "taropen", # uncompressed tar + "gz": "gzopen", # gzip compressed tar + "bz2": "bz2open", # bzip2 compressed tar + "xz": "xzopen" # lzma compressed tar + } + + #-------------------------------------------------------------------------- + # The public methods which TarFile provides: + + def close(self): + """Close the TarFile. In write-mode, two finishing zero blocks are + appended to the archive. + """ + if self.closed: + return + + self.closed = True + try: + if self.mode in ("a", "w", "x"): + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + finally: + if not self._extfileobj: + self.fileobj.close() + + def getmember(self, name): + """Return a TarInfo object for member `name'. If `name' can not be + found in the archive, KeyError is raised. If a member occurs more + than once in the archive, its last occurrence is assumed to be the + most up-to-date version. + """ + tarinfo = self._getmember(name) + if tarinfo is None: + raise KeyError("filename %r not found" % name) + return tarinfo + + def getmembers(self): + """Return the members of the archive as a list of TarInfo objects. The + list has the same order as the members in the archive. + """ + self._check() + if not self._loaded: # if we want to obtain a list of + self._load() # all members, we first have to + # scan the whole archive. + return self.members + + def getnames(self): + """Return the members of the archive as a list of their names. It has + the same order as the list returned by getmembers(). + """ + return [tarinfo.name for tarinfo in self.getmembers()] + + def gettarinfo(self, name=None, arcname=None, fileobj=None): + """Create a TarInfo object from the result of os.stat or equivalent + on an existing file. The file is either named by `name', or + specified as a file object `fileobj' with a file descriptor. If + given, `arcname' specifies an alternative name for the file in the + archive, otherwise, the name is taken from the 'name' attribute of + 'fileobj', or the 'name' argument. The name should be a text + string. + """ + self._check("awx") + + # When fileobj is given, replace name by + # fileobj's real name. + if fileobj is not None: + name = fileobj.name + + # Building the name of the member in the archive. + # Backward slashes are converted to forward slashes, + # Absolute paths are turned to relative paths. + if arcname is None: + arcname = name + drv, arcname = os.path.splitdrive(arcname) + arcname = arcname.replace(os.sep, "/") + arcname = arcname.lstrip("/") + + # Now, fill the TarInfo object with + # information specific for the file. + tarinfo = self.tarinfo() + tarinfo.tarfile = self # Not needed + + # Use os.stat or os.lstat, depending on platform + # and if symlinks shall be resolved. + if fileobj is None: + if hasattr(os, "lstat") and not self.dereference: + statres = os.lstat(name) + else: + statres = os.stat(name) + else: + statres = os.fstat(fileobj.fileno()) + linkname = "" + + stmd = statres.st_mode + if stat.S_ISREG(stmd): + inode = (statres.st_ino, statres.st_dev) + if not self.dereference and statres.st_nlink > 1 and \ + inode in self.inodes and arcname != self.inodes[inode]: + # Is it a hardlink to an already + # archived file? + type = LNKTYPE + linkname = self.inodes[inode] + else: + # The inode is added only if its valid. + # For win32 it is always 0. + type = REGTYPE + if inode[0]: + self.inodes[inode] = arcname + elif stat.S_ISDIR(stmd): + type = DIRTYPE + elif stat.S_ISFIFO(stmd): + type = FIFOTYPE + elif stat.S_ISLNK(stmd): + type = SYMTYPE + linkname = os.readlink(name) + elif stat.S_ISCHR(stmd): + type = CHRTYPE + elif stat.S_ISBLK(stmd): + type = BLKTYPE + else: + return None + + # Fill the TarInfo object with all + # information we can get. + tarinfo.name = arcname + tarinfo.mode = stmd + tarinfo.uid = statres.st_uid + tarinfo.gid = statres.st_gid + if type == REGTYPE: + tarinfo.size = statres.st_size + else: + tarinfo.size = 0 + tarinfo.mtime = statres.st_mtime + tarinfo.type = type + tarinfo.linkname = linkname + if pwd: + try: + tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] + except KeyError: + pass + if grp: + try: + tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] + except KeyError: + pass + + if type in (CHRTYPE, BLKTYPE): + if hasattr(os, "major") and hasattr(os, "minor"): + tarinfo.devmajor = os.major(statres.st_rdev) + tarinfo.devminor = os.minor(statres.st_rdev) + return tarinfo + + def list(self, verbose=True, *, members=None): + """Print a table of contents to sys.stdout. If `verbose' is False, only + the names of the members are printed. If it is True, an `ls -l'-like + output is produced. `members' is optional and must be a subset of the + list returned by getmembers(). + """ + self._check() + + if members is None: + members = self + for tarinfo in members: + if verbose: + _safe_print(stat.filemode(tarinfo.mode)) + _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid)) + if tarinfo.ischr() or tarinfo.isblk(): + _safe_print("%10s" % + ("%d,%d" % (tarinfo.devmajor, tarinfo.devminor))) + else: + _safe_print("%10d" % tarinfo.size) + _safe_print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6]) + + _safe_print(tarinfo.name + ("/" if tarinfo.isdir() else "")) + + if verbose: + if tarinfo.issym(): + _safe_print("-> " + tarinfo.linkname) + if tarinfo.islnk(): + _safe_print("link to " + tarinfo.linkname) + print() + + def add(self, name, arcname=None, recursive=True, *, filter=None): + """Add the file `name' to the archive. `name' may be any type of file + (directory, fifo, symbolic link, etc.). If given, `arcname' + specifies an alternative name for the file in the archive. + Directories are added recursively by default. This can be avoided by + setting `recursive' to False. `filter' is a function + that expects a TarInfo object argument and returns the changed + TarInfo object, if it returns None the TarInfo object will be + excluded from the archive. + """ + self._check("awx") + + if arcname is None: + arcname = name + + # Skip if somebody tries to archive the archive... + if self.name is not None and os.path.abspath(name) == self.name: + self._dbg(2, "tarfile: Skipped %r" % name) + return + + self._dbg(1, name) + + # Create a TarInfo object from the file. + tarinfo = self.gettarinfo(name, arcname) + + if tarinfo is None: + self._dbg(1, "tarfile: Unsupported type %r" % name) + return + + # Change or exclude the TarInfo object. + if filter is not None: + tarinfo = filter(tarinfo) + if tarinfo is None: + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Append the tar header and data to the archive. + if tarinfo.isreg(): + with bltn_open(name, "rb") as f: + self.addfile(tarinfo, f) + + elif tarinfo.isdir(): + self.addfile(tarinfo) + if recursive: + for f in sorted(os.listdir(name)): + self.add(os.path.join(name, f), os.path.join(arcname, f), + recursive, filter=filter) + + else: + self.addfile(tarinfo) + + def addfile(self, tarinfo, fileobj=None): + """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is + given, it should be a binary file, and tarinfo.size bytes are read + from it and added to the archive. You can create TarInfo objects + directly, or by using gettarinfo(). + """ + self._check("awx") + + tarinfo = copy.copy(tarinfo) + + buf = tarinfo.tobuf(self.format, self.encoding, self.errors) + self.fileobj.write(buf) + self.offset += len(buf) + bufsize=self.copybufsize + # If there's data to follow, append it. + if fileobj is not None: + copyfileobj(fileobj, self.fileobj, tarinfo.size, bufsize=bufsize) + blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) + if remainder > 0: + self.fileobj.write(NUL * (BLOCKSIZE - remainder)) + blocks += 1 + self.offset += blocks * BLOCKSIZE + + self.members.append(tarinfo) + + def extractall(self, path=".", members=None, *, numeric_owner=False): + """Extract all members from the archive to the current working + directory and set owner, modification time and permissions on + directories afterwards. `path' specifies a different directory + to extract to. `members' is optional and must be a subset of the + list returned by getmembers(). If `numeric_owner` is True, only + the numbers for user/group names are used and not the names. + """ + directories = [] + + if members is None: + members = self + + for tarinfo in members: + if tarinfo.isdir(): + # Extract directories with a safe mode. + directories.append(tarinfo) + tarinfo = copy.copy(tarinfo) + tarinfo.mode = 0o700 + # Do not set_attrs directories, as we will do that further down + self.extract(tarinfo, path, set_attrs=not tarinfo.isdir(), + numeric_owner=numeric_owner) + + # Reverse sort directories. + directories.sort(key=lambda a: a.name) + directories.reverse() + + # Set correct owner, mtime and filemode on directories. + for tarinfo in directories: + dirpath = os.path.join(path, tarinfo.name) + try: + self.chown(tarinfo, dirpath, numeric_owner=numeric_owner) + self.utime(tarinfo, dirpath) + self.chmod(tarinfo, dirpath) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extract(self, member, path="", set_attrs=True, *, numeric_owner=False): + """Extract a member from the archive to the current working directory, + using its full name. Its file information is extracted as accurately + as possible. `member' may be a filename or a TarInfo object. You can + specify a different directory using `path'. File attributes (owner, + mtime, mode) are set unless `set_attrs' is False. If `numeric_owner` + is True, only the numbers for user/group names are used and not + the names. + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + # Prepare the link target for makelink(). + if tarinfo.islnk(): + tarinfo._link_target = os.path.join(path, tarinfo.linkname) + + try: + self._extract_member(tarinfo, os.path.join(path, tarinfo.name), + set_attrs=set_attrs, + numeric_owner=numeric_owner) + except OSError as e: + if self.errorlevel > 0: + raise + else: + if e.filename is None: + self._dbg(1, "tarfile: %s" % e.strerror) + else: + self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extractfile(self, member): + """Extract a member from the archive as a file object. `member' may be + a filename or a TarInfo object. If `member' is a regular file or a + link, an io.BufferedReader object is returned. Otherwise, None is + returned. + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + if tarinfo.isreg() or tarinfo.type not in SUPPORTED_TYPES: + # Members with unknown types are treated as regular files. + return self.fileobject(self, tarinfo) + + elif tarinfo.islnk() or tarinfo.issym(): + if isinstance(self.fileobj, _Stream): + # A small but ugly workaround for the case that someone tries + # to extract a (sym)link as a file-object from a non-seekable + # stream of tar blocks. + raise StreamError("cannot extract (sym)link as file object") + else: + # A (sym)link's file object is its target's file object. + return self.extractfile(self._find_link_target(tarinfo)) + else: + # If there's no data associated with the member (directory, chrdev, + # blkdev, etc.), return None instead of a file object. + return None + + def _extract_member(self, tarinfo, targetpath, set_attrs=True, + numeric_owner=False): + """Extract the TarInfo object tarinfo to a physical + file called targetpath. + """ + # Fetch the TarInfo object for the given name + # and build the destination pathname, replacing + # forward slashes to platform specific separators. + targetpath = targetpath.rstrip("/") + targetpath = targetpath.replace("/", os.sep) + + # Create all upper directories. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + # Create directories that are not part of the archive with + # default permissions. + os.makedirs(upperdirs) + + if tarinfo.islnk() or tarinfo.issym(): + self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) + else: + self._dbg(1, tarinfo.name) + + if tarinfo.isreg(): + self.makefile(tarinfo, targetpath) + elif tarinfo.isdir(): + self.makedir(tarinfo, targetpath) + elif tarinfo.isfifo(): + self.makefifo(tarinfo, targetpath) + elif tarinfo.ischr() or tarinfo.isblk(): + self.makedev(tarinfo, targetpath) + elif tarinfo.islnk() or tarinfo.issym(): + self.makelink(tarinfo, targetpath) + elif tarinfo.type not in SUPPORTED_TYPES: + self.makeunknown(tarinfo, targetpath) + else: + self.makefile(tarinfo, targetpath) + + if set_attrs: + self.chown(tarinfo, targetpath, numeric_owner) + if not tarinfo.issym(): + self.chmod(tarinfo, targetpath) + self.utime(tarinfo, targetpath) + + #-------------------------------------------------------------------------- + # Below are the different file methods. They are called via + # _extract_member() when extract() is called. They can be replaced in a + # subclass to implement other functionality. + + def makedir(self, tarinfo, targetpath): + """Make a directory called targetpath. + """ + try: + # Use a safe mode for the directory, the real mode is set + # later in _extract_member(). + os.mkdir(targetpath, 0o700) + except FileExistsError: + pass + + def makefile(self, tarinfo, targetpath): + """Make a file called targetpath. + """ + source = self.fileobj + source.seek(tarinfo.offset_data) + bufsize = self.copybufsize + with bltn_open(targetpath, "wb") as target: + if tarinfo.sparse is not None: + for offset, size in tarinfo.sparse: + target.seek(offset) + copyfileobj(source, target, size, ReadError, bufsize) + target.seek(tarinfo.size) + target.truncate() + else: + copyfileobj(source, target, tarinfo.size, ReadError, bufsize) + + def makeunknown(self, tarinfo, targetpath): + """Make a file from a TarInfo object with an unknown type + at targetpath. + """ + self.makefile(tarinfo, targetpath) + self._dbg(1, "tarfile: Unknown file type %r, " \ + "extracted as regular file." % tarinfo.type) + + def makefifo(self, tarinfo, targetpath): + """Make a fifo called targetpath. + """ + if hasattr(os, "mkfifo"): + os.mkfifo(targetpath) + else: + raise ExtractError("fifo not supported by system") + + def makedev(self, tarinfo, targetpath): + """Make a character or block device called targetpath. + """ + if not hasattr(os, "mknod") or not hasattr(os, "makedev"): + raise ExtractError("special devices not supported by system") + + mode = tarinfo.mode + if tarinfo.isblk(): + mode |= stat.S_IFBLK + else: + mode |= stat.S_IFCHR + + os.mknod(targetpath, mode, + os.makedev(tarinfo.devmajor, tarinfo.devminor)) + + def makelink(self, tarinfo, targetpath): + """Make a (symbolic) link called targetpath. If it cannot be created + (platform limitation), we try to make a copy of the referenced file + instead of a link. + """ + try: + # For systems that support symbolic and hard links. + if tarinfo.issym(): + os.symlink(tarinfo.linkname, targetpath) + else: + # See extract(). + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except symlink_exception: + try: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") + + def chown(self, tarinfo, targetpath, numeric_owner): + """Set owner of targetpath according to tarinfo. If numeric_owner + is True, use .gid/.uid instead of .gname/.uname. If numeric_owner + is False, fall back to .gid/.uid when the search based on name + fails. + """ + if hasattr(os, "geteuid") and os.geteuid() == 0: + # We have to be root to do so. + g = tarinfo.gid + u = tarinfo.uid + if not numeric_owner: + try: + if grp: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + pass + try: + if pwd: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + pass + try: + if tarinfo.issym() and hasattr(os, "lchown"): + os.lchown(targetpath, u, g) + else: + os.chown(targetpath, u, g) + except OSError: + raise ExtractError("could not change owner") + + def chmod(self, tarinfo, targetpath): + """Set file permissions of targetpath according to tarinfo. + """ + if hasattr(os, 'chmod'): + try: + os.chmod(targetpath, tarinfo.mode) + except OSError: + raise ExtractError("could not change mode") + + def utime(self, tarinfo, targetpath): + """Set modification time of targetpath according to tarinfo. + """ + if not hasattr(os, 'utime'): + return + try: + os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) + except OSError: + raise ExtractError("could not change modification time") + + #-------------------------------------------------------------------------- + def next(self): + """Return the next member of the archive as a TarInfo object, when + TarFile is opened for reading. Return None if there is no more + available. + """ + self._check("ra") + if self.firstmember is not None: + m = self.firstmember + self.firstmember = None + return m + + # Advance the file pointer. + if self.offset != self.fileobj.tell(): + self.fileobj.seek(self.offset - 1) + if not self.fileobj.read(1): + raise ReadError("unexpected end of data") + + # Read the next block. + tarinfo = None + while True: + try: + tarinfo = self.tarinfo.fromtarfile(self) + except EOFHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + except InvalidHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + elif self.offset == 0: + raise ReadError(str(e)) + except EmptyHeaderError: + if self.offset == 0: + raise ReadError("empty file") + except TruncatedHeaderError as e: + if self.offset == 0: + raise ReadError(str(e)) + except SubsequentHeaderError as e: + raise ReadError(str(e)) + break + + if tarinfo is not None: + self.members.append(tarinfo) + else: + self._loaded = True + + return tarinfo + + #-------------------------------------------------------------------------- + # Little helper methods: + + def _getmember(self, name, tarinfo=None, normalize=False): + """Find an archive member by name from bottom to top. + If tarinfo is given, it is used as the starting point. + """ + # Ensure that all members have been loaded. + members = self.getmembers() + + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] + + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member + + def _load(self): + """Read through the entire archive file and look for readable + members. + """ + while True: + tarinfo = self.next() + if tarinfo is None: + break + self._loaded = True + + def _check(self, mode=None): + """Check if TarFile is still open, and if the operation's mode + corresponds to TarFile's mode. + """ + if self.closed: + raise OSError("%s is closed" % self.__class__.__name__) + if mode is not None and self.mode not in mode: + raise OSError("bad operation for mode %r" % self.mode) + + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname))) + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + + def __iter__(self): + """Provide an iterator object. + """ + if self._loaded: + yield from self.members + return + + # Yield items using TarFile's next() method. + # When all members have been read, set TarFile as _loaded. + index = 0 + # Fix for SF #1100429: Under rare circumstances it can + # happen that getmembers() is called during iteration, + # which will have already exhausted the next() method. + if self.firstmember is not None: + tarinfo = self.next() + index += 1 + yield tarinfo + + while True: + if index < len(self.members): + tarinfo = self.members[index] + elif not self._loaded: + tarinfo = self.next() + if not tarinfo: + self._loaded = True + return + else: + return + index += 1 + yield tarinfo + + def _dbg(self, level, msg): + """Write debugging output to sys.stderr. + """ + if level <= self.debug: + print(msg, file=sys.stderr) + + def __enter__(self): + self._check() + return self + + def __exit__(self, type, value, traceback): + if type is None: + self.close() + else: + # An exception occurred. We must not call close() because + # it would try to write end-of-archive blocks and padding. + if not self._extfileobj: + self.fileobj.close() + self.closed = True + +#-------------------- +# exported functions +#-------------------- +def is_tarfile(name): + """Return True if name points to a tar archive that we + are able to handle, else return False. + """ + try: + t = open(name) + t.close() + return True + except TarError: + return False + +open = TarFile.open + + +def main(): + import argparse + + description = 'A simple command-line interface for tarfile module.' + parser = argparse.ArgumentParser(description=description) + parser.add_argument('-v', '--verbose', action='store_true', default=False, + help='Verbose output') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-l', '--list', metavar='', + help='Show listing of a tarfile') + group.add_argument('-e', '--extract', nargs='+', + metavar=('', ''), + help='Extract tarfile into target dir') + group.add_argument('-c', '--create', nargs='+', + metavar=('', ''), + help='Create tarfile from sources') + group.add_argument('-t', '--test', metavar='', + help='Test if a tarfile is valid') + args = parser.parse_args() + + if args.test is not None: + src = args.test + if is_tarfile(src): + with open(src, 'r') as tar: + tar.getmembers() + print(tar.getmembers(), file=sys.stderr) + if args.verbose: + print('{!r} is a tar archive.'.format(src)) + else: + parser.exit(1, '{!r} is not a tar archive.\n'.format(src)) + + elif args.list is not None: + src = args.list + if is_tarfile(src): + with TarFile.open(src, 'r:*') as tf: + tf.list(verbose=args.verbose) + else: + parser.exit(1, '{!r} is not a tar archive.\n'.format(src)) + + elif args.extract is not None: + if len(args.extract) == 1: + src = args.extract[0] + curdir = os.curdir + elif len(args.extract) == 2: + src, curdir = args.extract + else: + parser.exit(1, parser.format_help()) + + if is_tarfile(src): + with TarFile.open(src, 'r:*') as tf: + tf.extractall(path=curdir) + if args.verbose: + if curdir == '.': + msg = '{!r} file is extracted.'.format(src) + else: + msg = ('{!r} file is extracted ' + 'into {!r} directory.').format(src, curdir) + print(msg) + else: + parser.exit(1, '{!r} is not a tar archive.\n'.format(src)) + + elif args.create is not None: + tar_name = args.create.pop(0) + _, ext = os.path.splitext(tar_name) + compressions = { + # gz + '.gz': 'gz', + '.tgz': 'gz', + # xz + '.xz': 'xz', + '.txz': 'xz', + # bz2 + '.bz2': 'bz2', + '.tbz': 'bz2', + '.tbz2': 'bz2', + '.tb2': 'bz2', + } + tar_mode = 'w:' + compressions[ext] if ext in compressions else 'w' + tar_files = args.create + + with TarFile.open(tar_name, tar_mode) as tf: + for file_name in tar_files: + tf.add(file_name) + + if args.verbose: + print('{!r} file created.'.format(tar_name)) + +if __name__ == '__main__': + main() diff --git a/winvenv/Lib/tempfile.py b/winvenv/Lib/tempfile.py new file mode 100644 index 0000000..2143224 --- /dev/null +++ b/winvenv/Lib/tempfile.py @@ -0,0 +1,809 @@ +"""Temporary files. + +This module provides generic, low- and high-level interfaces for +creating temporary files and directories. All of the interfaces +provided by this module can be used without fear of race conditions +except for 'mktemp'. 'mktemp' is subject to race conditions and +should not be used; it is provided for backward compatibility only. + +The default path names are returned as str. If you supply bytes as +input, all return values will be in bytes. Ex: + + >>> tempfile.mkstemp() + (4, '/tmp/tmptpu9nin8') + >>> tempfile.mkdtemp(suffix=b'') + b'/tmp/tmppbi8f0hy' + +This module also provides some data items to the user: + + TMP_MAX - maximum number of names that will be tried before + giving up. + tempdir - If this is set to a string before the first use of + any routine from this module, it will be considered as + another candidate location to store temporary files. +""" + +__all__ = [ + "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces + "SpooledTemporaryFile", "TemporaryDirectory", + "mkstemp", "mkdtemp", # low level safe interfaces + "mktemp", # deprecated unsafe interface + "TMP_MAX", "gettempprefix", # constants + "tempdir", "gettempdir", + "gettempprefixb", "gettempdirb", + ] + + +# Imports. + +import functools as _functools +import warnings as _warnings +import io as _io +import os as _os +import shutil as _shutil +import errno as _errno +from random import Random as _Random +import weakref as _weakref +import _thread +_allocate_lock = _thread.allocate_lock + +_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL +if hasattr(_os, 'O_NOFOLLOW'): + _text_openflags |= _os.O_NOFOLLOW + +_bin_openflags = _text_openflags +if hasattr(_os, 'O_BINARY'): + _bin_openflags |= _os.O_BINARY + +if hasattr(_os, 'TMP_MAX'): + TMP_MAX = _os.TMP_MAX +else: + TMP_MAX = 10000 + +# This variable _was_ unused for legacy reasons, see issue 10354. +# But as of 3.5 we actually use it at runtime so changing it would +# have a possibly desirable side effect... But we do not want to support +# that as an API. It is undocumented on purpose. Do not depend on this. +template = "tmp" + +# Internal routines. + +_once_lock = _allocate_lock() + +if hasattr(_os, "lstat"): + _stat = _os.lstat +elif hasattr(_os, "stat"): + _stat = _os.stat +else: + # Fallback. All we need is something that raises OSError if the + # file doesn't exist. + def _stat(fn): + fd = _os.open(fn, _os.O_RDONLY) + _os.close(fd) + +def _exists(fn): + try: + _stat(fn) + except OSError: + return False + else: + return True + + +def _infer_return_type(*args): + """Look at the type of all args and divine their implied return type.""" + return_type = None + for arg in args: + if arg is None: + continue + if isinstance(arg, bytes): + if return_type is str: + raise TypeError("Can't mix bytes and non-bytes in " + "path components.") + return_type = bytes + else: + if return_type is bytes: + raise TypeError("Can't mix bytes and non-bytes in " + "path components.") + return_type = str + if return_type is None: + return str # tempfile APIs return a str by default. + return return_type + + +def _sanitize_params(prefix, suffix, dir): + """Common parameter processing for most APIs in this module.""" + output_type = _infer_return_type(prefix, suffix, dir) + if suffix is None: + suffix = output_type() + if prefix is None: + if output_type is str: + prefix = template + else: + prefix = _os.fsencode(template) + if dir is None: + if output_type is str: + dir = gettempdir() + else: + dir = gettempdirb() + return prefix, suffix, dir, output_type + + +class _RandomNameSequence: + """An instance of _RandomNameSequence generates an endless + sequence of unpredictable strings which can safely be incorporated + into file names. Each string is eight characters long. Multiple + threads can safely use the same instance at the same time. + + _RandomNameSequence is an iterator.""" + + characters = "abcdefghijklmnopqrstuvwxyz0123456789_" + + @property + def rng(self): + cur_pid = _os.getpid() + if cur_pid != getattr(self, '_rng_pid', None): + self._rng = _Random() + self._rng_pid = cur_pid + return self._rng + + def __iter__(self): + return self + + def __next__(self): + c = self.characters + choose = self.rng.choice + letters = [choose(c) for dummy in range(8)] + return ''.join(letters) + +def _candidate_tempdir_list(): + """Generate a list of candidate temporary directories which + _get_default_tempdir will try.""" + + dirlist = [] + + # First, try the environment. + for envname in 'TMPDIR', 'TEMP', 'TMP': + dirname = _os.getenv(envname) + if dirname: dirlist.append(dirname) + + # Failing that, try OS-specific locations. + if _os.name == 'nt': + dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), + _os.path.expandvars(r'%SYSTEMROOT%\Temp'), + r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) + else: + dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) + + # As a last resort, the current directory. + try: + dirlist.append(_os.getcwd()) + except (AttributeError, OSError): + dirlist.append(_os.curdir) + + return dirlist + +def _get_default_tempdir(): + """Calculate the default directory to use for temporary files. + This routine should be called exactly once. + + We determine whether or not a candidate temp dir is usable by + trying to create and write to a file in that directory. If this + is successful, the test file is deleted. To prevent denial of + service, the name of the test file must be randomized.""" + + namer = _RandomNameSequence() + dirlist = _candidate_tempdir_list() + + for dir in dirlist: + if dir != _os.curdir: + dir = _os.path.abspath(dir) + # Try only a few names per directory. + for seq in range(100): + name = next(namer) + filename = _os.path.join(dir, name) + try: + fd = _os.open(filename, _bin_openflags, 0o600) + try: + try: + with _io.open(fd, 'wb', closefd=False) as fp: + fp.write(b'blat') + finally: + _os.close(fd) + finally: + _os.unlink(filename) + return dir + except FileExistsError: + pass + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + break # no point trying more names in this directory + except OSError: + break # no point trying more names in this directory + raise FileNotFoundError(_errno.ENOENT, + "No usable temporary directory found in %s" % + dirlist) + +_name_sequence = None + +def _get_candidate_names(): + """Common setup sequence for all user-callable interfaces.""" + + global _name_sequence + if _name_sequence is None: + _once_lock.acquire() + try: + if _name_sequence is None: + _name_sequence = _RandomNameSequence() + finally: + _once_lock.release() + return _name_sequence + + +def _mkstemp_inner(dir, pre, suf, flags, output_type): + """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" + + names = _get_candidate_names() + if output_type is bytes: + names = map(_os.fsencode, names) + + for seq in range(TMP_MAX): + name = next(names) + file = _os.path.join(dir, pre + name + suf) + try: + fd = _os.open(file, flags, 0o600) + except FileExistsError: + continue # try again + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + else: + raise + return (fd, _os.path.abspath(file)) + + raise FileExistsError(_errno.EEXIST, + "No usable temporary file name found") + + +# User visible interfaces. + +def gettempprefix(): + """The default prefix for temporary directories.""" + return template + +def gettempprefixb(): + """The default prefix for temporary directories as bytes.""" + return _os.fsencode(gettempprefix()) + +tempdir = None + +def gettempdir(): + """Accessor for tempfile.tempdir.""" + global tempdir + if tempdir is None: + _once_lock.acquire() + try: + if tempdir is None: + tempdir = _get_default_tempdir() + finally: + _once_lock.release() + return tempdir + +def gettempdirb(): + """A bytes version of tempfile.gettempdir().""" + return _os.fsencode(gettempdir()) + +def mkstemp(suffix=None, prefix=None, dir=None, text=False): + """User-callable function to create and return a unique temporary + file. The return value is a pair (fd, name) where fd is the + file descriptor returned by os.open, and name is the filename. + + If 'suffix' is not None, the file name will end with that suffix, + otherwise there will be no suffix. + + If 'prefix' is not None, the file name will begin with that prefix, + otherwise a default prefix is used. + + If 'dir' is not None, the file will be created in that directory, + otherwise a default directory is used. + + If 'text' is specified and true, the file is opened in text + mode. Else (the default) the file is opened in binary mode. On + some operating systems, this makes no difference. + + If any of 'suffix', 'prefix' and 'dir' are not None, they must be the + same type. If they are bytes, the returned name will be bytes; str + otherwise. + + The file is readable and writable only by the creating user ID. + If the operating system uses permission bits to indicate whether a + file is executable, the file is executable by no one. The file + descriptor is not inherited by children of this process. + + Caller is responsible for deleting the file when done with it. + """ + + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) + + if text: + flags = _text_openflags + else: + flags = _bin_openflags + + return _mkstemp_inner(dir, prefix, suffix, flags, output_type) + + +def mkdtemp(suffix=None, prefix=None, dir=None): + """User-callable function to create and return a unique temporary + directory. The return value is the pathname of the directory. + + Arguments are as for mkstemp, except that the 'text' argument is + not accepted. + + The directory is readable, writable, and searchable only by the + creating user. + + Caller is responsible for deleting the directory when done with it. + """ + + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) + + names = _get_candidate_names() + if output_type is bytes: + names = map(_os.fsencode, names) + + for seq in range(TMP_MAX): + name = next(names) + file = _os.path.join(dir, prefix + name + suffix) + try: + _os.mkdir(file, 0o700) + except FileExistsError: + continue # try again + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if (_os.name == 'nt' and _os.path.isdir(dir) and + _os.access(dir, _os.W_OK)): + continue + else: + raise + return file + + raise FileExistsError(_errno.EEXIST, + "No usable temporary directory name found") + +def mktemp(suffix="", prefix=template, dir=None): + """User-callable function to return a unique temporary file name. The + file is not created. + + Arguments are similar to mkstemp, except that the 'text' argument is + not accepted, and suffix=None, prefix=None and bytes file names are not + supported. + + THIS FUNCTION IS UNSAFE AND SHOULD NOT BE USED. The file name may + refer to a file that did not exist at some point, but by the time + you get around to creating it, someone else may have beaten you to + the punch. + """ + +## from warnings import warn as _warn +## _warn("mktemp is a potential security risk to your program", +## RuntimeWarning, stacklevel=2) + + if dir is None: + dir = gettempdir() + + names = _get_candidate_names() + for seq in range(TMP_MAX): + name = next(names) + file = _os.path.join(dir, prefix + name + suffix) + if not _exists(file): + return file + + raise FileExistsError(_errno.EEXIST, + "No usable temporary filename found") + + +class _TemporaryFileCloser: + """A separate object allowing proper closing of a temporary file's + underlying file object, without adding a __del__ method to the + temporary file.""" + + file = None # Set here since __del__ checks it + close_called = False + + def __init__(self, file, name, delete=True): + self.file = file + self.name = name + self.delete = delete + + # NT provides delete-on-close as a primitive, so we don't need + # the wrapper to do anything special. We still use it so that + # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile. + if _os.name != 'nt': + # Cache the unlinker so we don't get spurious errors at + # shutdown when the module-level "os" is None'd out. Note + # that this must be referenced as self.unlink, because the + # name TemporaryFileWrapper may also get None'd out before + # __del__ is called. + + def close(self, unlink=_os.unlink): + if not self.close_called and self.file is not None: + self.close_called = True + try: + self.file.close() + finally: + if self.delete: + unlink(self.name) + + # Need to ensure the file is deleted on __del__ + def __del__(self): + self.close() + + else: + def close(self): + if not self.close_called: + self.close_called = True + self.file.close() + + +class _TemporaryFileWrapper: + """Temporary file wrapper + + This class provides a wrapper around files opened for + temporary use. In particular, it seeks to automatically + remove the file when it is no longer needed. + """ + + def __init__(self, file, name, delete=True): + self.file = file + self.name = name + self.delete = delete + self._closer = _TemporaryFileCloser(file, name, delete) + + def __getattr__(self, name): + # Attribute lookups are delegated to the underlying file + # and cached for non-numeric results + # (i.e. methods are cached, closed and friends are not) + file = self.__dict__['file'] + a = getattr(file, name) + if hasattr(a, '__call__'): + func = a + @_functools.wraps(func) + def func_wrapper(*args, **kwargs): + return func(*args, **kwargs) + # Avoid closing the file as long as the wrapper is alive, + # see issue #18879. + func_wrapper._closer = self._closer + a = func_wrapper + if not isinstance(a, int): + setattr(self, name, a) + return a + + # The underlying __enter__ method returns the wrong object + # (self.file) so override it to return the wrapper + def __enter__(self): + self.file.__enter__() + return self + + # Need to trap __exit__ as well to ensure the file gets + # deleted when used in a with statement + def __exit__(self, exc, value, tb): + result = self.file.__exit__(exc, value, tb) + self.close() + return result + + def close(self): + """ + Close the temporary file, possibly deleting it. + """ + self._closer.close() + + # iter() doesn't use __getattr__ to find the __iter__ method + def __iter__(self): + # Don't return iter(self.file), but yield from it to avoid closing + # file as long as it's being used as iterator (see issue #23700). We + # can't use 'yield from' here because iter(file) returns the file + # object itself, which has a close method, and thus the file would get + # closed when the generator is finalized, due to PEP380 semantics. + for line in self.file: + yield line + + +def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, + newline=None, suffix=None, prefix=None, + dir=None, delete=True): + """Create and return a temporary file. + Arguments: + 'prefix', 'suffix', 'dir' -- as for mkstemp. + 'mode' -- the mode argument to io.open (default "w+b"). + 'buffering' -- the buffer size argument to io.open (default -1). + 'encoding' -- the encoding argument to io.open (default None) + 'newline' -- the newline argument to io.open (default None) + 'delete' -- whether the file is deleted on close (default True). + The file is created as mkstemp() would do it. + + Returns an object with a file-like interface; the name of the file + is accessible as its 'name' attribute. The file will be automatically + deleted when it is closed unless the 'delete' argument is set to False. + """ + + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) + + flags = _bin_openflags + + # Setting O_TEMPORARY in the flags causes the OS to delete + # the file when it is closed. This is only supported by Windows. + if _os.name == 'nt' and delete: + flags |= _os.O_TEMPORARY + + (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) + try: + file = _io.open(fd, mode, buffering=buffering, + newline=newline, encoding=encoding) + + return _TemporaryFileWrapper(file, name, delete) + except BaseException: + _os.unlink(name) + _os.close(fd) + raise + +if _os.name != 'posix' or _os.sys.platform == 'cygwin': + # On non-POSIX and Cygwin systems, assume that we cannot unlink a file + # while it is open. + TemporaryFile = NamedTemporaryFile + +else: + # Is the O_TMPFILE flag available and does it work? + # The flag is set to False if os.open(dir, os.O_TMPFILE) raises an + # IsADirectoryError exception + _O_TMPFILE_WORKS = hasattr(_os, 'O_TMPFILE') + + def TemporaryFile(mode='w+b', buffering=-1, encoding=None, + newline=None, suffix=None, prefix=None, + dir=None): + """Create and return a temporary file. + Arguments: + 'prefix', 'suffix', 'dir' -- as for mkstemp. + 'mode' -- the mode argument to io.open (default "w+b"). + 'buffering' -- the buffer size argument to io.open (default -1). + 'encoding' -- the encoding argument to io.open (default None) + 'newline' -- the newline argument to io.open (default None) + The file is created as mkstemp() would do it. + + Returns an object with a file-like interface. The file has no + name, and will cease to exist when it is closed. + """ + global _O_TMPFILE_WORKS + + prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) + + flags = _bin_openflags + if _O_TMPFILE_WORKS: + try: + flags2 = (flags | _os.O_TMPFILE) & ~_os.O_CREAT + fd = _os.open(dir, flags2, 0o600) + except IsADirectoryError: + # Linux kernel older than 3.11 ignores the O_TMPFILE flag: + # O_TMPFILE is read as O_DIRECTORY. Trying to open a directory + # with O_RDWR|O_DIRECTORY fails with IsADirectoryError, a + # directory cannot be open to write. Set flag to False to not + # try again. + _O_TMPFILE_WORKS = False + except OSError: + # The filesystem of the directory does not support O_TMPFILE. + # For example, OSError(95, 'Operation not supported'). + # + # On Linux kernel older than 3.11, trying to open a regular + # file (or a symbolic link to a regular file) with O_TMPFILE + # fails with NotADirectoryError, because O_TMPFILE is read as + # O_DIRECTORY. + pass + else: + try: + return _io.open(fd, mode, buffering=buffering, + newline=newline, encoding=encoding) + except: + _os.close(fd) + raise + # Fallback to _mkstemp_inner(). + + (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) + try: + _os.unlink(name) + return _io.open(fd, mode, buffering=buffering, + newline=newline, encoding=encoding) + except: + _os.close(fd) + raise + +class SpooledTemporaryFile: + """Temporary file wrapper, specialized to switch from BytesIO + or StringIO to a real file when it exceeds a certain size or + when a fileno is needed. + """ + _rolled = False + + def __init__(self, max_size=0, mode='w+b', buffering=-1, + encoding=None, newline=None, + suffix=None, prefix=None, dir=None): + if 'b' in mode: + self._file = _io.BytesIO() + else: + # Setting newline="\n" avoids newline translation; + # this is important because otherwise on Windows we'd + # get double newline translation upon rollover(). + self._file = _io.StringIO(newline="\n") + self._max_size = max_size + self._rolled = False + self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering, + 'suffix': suffix, 'prefix': prefix, + 'encoding': encoding, 'newline': newline, + 'dir': dir} + + def _check(self, file): + if self._rolled: return + max_size = self._max_size + if max_size and file.tell() > max_size: + self.rollover() + + def rollover(self): + if self._rolled: return + file = self._file + newfile = self._file = TemporaryFile(**self._TemporaryFileArgs) + del self._TemporaryFileArgs + + newfile.write(file.getvalue()) + newfile.seek(file.tell(), 0) + + self._rolled = True + + # The method caching trick from NamedTemporaryFile + # won't work here, because _file may change from a + # BytesIO/StringIO instance to a real file. So we list + # all the methods directly. + + # Context management protocol + def __enter__(self): + if self._file.closed: + raise ValueError("Cannot enter context with closed file") + return self + + def __exit__(self, exc, value, tb): + self._file.close() + + # file protocol + def __iter__(self): + return self._file.__iter__() + + def close(self): + self._file.close() + + @property + def closed(self): + return self._file.closed + + @property + def encoding(self): + try: + return self._file.encoding + except AttributeError: + if 'b' in self._TemporaryFileArgs['mode']: + raise + return self._TemporaryFileArgs['encoding'] + + def fileno(self): + self.rollover() + return self._file.fileno() + + def flush(self): + self._file.flush() + + def isatty(self): + return self._file.isatty() + + @property + def mode(self): + try: + return self._file.mode + except AttributeError: + return self._TemporaryFileArgs['mode'] + + @property + def name(self): + try: + return self._file.name + except AttributeError: + return None + + @property + def newlines(self): + try: + return self._file.newlines + except AttributeError: + if 'b' in self._TemporaryFileArgs['mode']: + raise + return self._TemporaryFileArgs['newline'] + + def read(self, *args): + return self._file.read(*args) + + def readline(self, *args): + return self._file.readline(*args) + + def readlines(self, *args): + return self._file.readlines(*args) + + def seek(self, *args): + self._file.seek(*args) + + @property + def softspace(self): + return self._file.softspace + + def tell(self): + return self._file.tell() + + def truncate(self, size=None): + if size is None: + self._file.truncate() + else: + if size > self._max_size: + self.rollover() + self._file.truncate(size) + + def write(self, s): + file = self._file + rv = file.write(s) + self._check(file) + return rv + + def writelines(self, iterable): + file = self._file + rv = file.writelines(iterable) + self._check(file) + return rv + + +class TemporaryDirectory(object): + """Create and return a temporary directory. This has the same + behavior as mkdtemp but can be used as a context manager. For + example: + + with TemporaryDirectory() as tmpdir: + ... + + Upon exiting the context, the directory and everything contained + in it are removed. + """ + + def __init__(self, suffix=None, prefix=None, dir=None): + self.name = mkdtemp(suffix, prefix, dir) + self._finalizer = _weakref.finalize( + self, self._cleanup, self.name, + warn_message="Implicitly cleaning up {!r}".format(self)) + + @classmethod + def _cleanup(cls, name, warn_message): + _shutil.rmtree(name) + _warnings.warn(warn_message, ResourceWarning) + + def __repr__(self): + return "<{} {!r}>".format(self.__class__.__name__, self.name) + + def __enter__(self): + return self.name + + def __exit__(self, exc, value, tb): + self.cleanup() + + def cleanup(self): + if self._finalizer.detach(): + _shutil.rmtree(self.name) diff --git a/winvenv/Lib/token.py b/winvenv/Lib/token.py new file mode 100644 index 0000000..ba13205 --- /dev/null +++ b/winvenv/Lib/token.py @@ -0,0 +1,160 @@ +"""Token constants (from "token.h").""" + +__all__ = ['tok_name', 'ISTERMINAL', 'ISNONTERMINAL', 'ISEOF'] + +# This file is automatically generated; please don't muck it up! +# +# To update the symbols in this file, 'cd' to the top directory of +# the python source tree after building the interpreter and run: +# +# ./python Lib/token.py + +#--start constants-- +ENDMARKER = 0 +NAME = 1 +NUMBER = 2 +STRING = 3 +NEWLINE = 4 +INDENT = 5 +DEDENT = 6 +LPAR = 7 +RPAR = 8 +LSQB = 9 +RSQB = 10 +COLON = 11 +COMMA = 12 +SEMI = 13 +PLUS = 14 +MINUS = 15 +STAR = 16 +SLASH = 17 +VBAR = 18 +AMPER = 19 +LESS = 20 +GREATER = 21 +EQUAL = 22 +DOT = 23 +PERCENT = 24 +LBRACE = 25 +RBRACE = 26 +EQEQUAL = 27 +NOTEQUAL = 28 +LESSEQUAL = 29 +GREATEREQUAL = 30 +TILDE = 31 +CIRCUMFLEX = 32 +LEFTSHIFT = 33 +RIGHTSHIFT = 34 +DOUBLESTAR = 35 +PLUSEQUAL = 36 +MINEQUAL = 37 +STAREQUAL = 38 +SLASHEQUAL = 39 +PERCENTEQUAL = 40 +AMPEREQUAL = 41 +VBAREQUAL = 42 +CIRCUMFLEXEQUAL = 43 +LEFTSHIFTEQUAL = 44 +RIGHTSHIFTEQUAL = 45 +DOUBLESTAREQUAL = 46 +DOUBLESLASH = 47 +DOUBLESLASHEQUAL = 48 +AT = 49 +ATEQUAL = 50 +RARROW = 51 +ELLIPSIS = 52 +# Don't forget to update the table _PyParser_TokenNames in tokenizer.c! +OP = 53 +ERRORTOKEN = 54 +# These aren't used by the C tokenizer but are needed for tokenize.py +COMMENT = 55 +NL = 56 +ENCODING = 57 +N_TOKENS = 58 +# Special definitions for cooperation with parser +NT_OFFSET = 256 +#--end constants-- + +tok_name = {value: name + for name, value in globals().items() + if isinstance(value, int) and not name.startswith('_')} +__all__.extend(tok_name.values()) + +def ISTERMINAL(x): + return x < NT_OFFSET + +def ISNONTERMINAL(x): + return x >= NT_OFFSET + +def ISEOF(x): + return x == ENDMARKER + + +def _main(): + import re + import sys + args = sys.argv[1:] + inFileName = args and args[0] or "Include/token.h" + outFileName = "Lib/token.py" + if len(args) > 1: + outFileName = args[1] + try: + fp = open(inFileName) + except OSError as err: + sys.stdout.write("I/O error: %s\n" % str(err)) + sys.exit(1) + with fp: + lines = fp.read().split("\n") + prog = re.compile( + r"#define[ \t][ \t]*([A-Z0-9][A-Z0-9_]*)[ \t][ \t]*([0-9][0-9]*)", + re.IGNORECASE) + comment_regex = re.compile( + r"^\s*/\*\s*(.+?)\s*\*/\s*$", + re.IGNORECASE) + + tokens = {} + prev_val = None + for line in lines: + match = prog.match(line) + if match: + name, val = match.group(1, 2) + val = int(val) + tokens[val] = {'token': name} # reverse so we can sort them... + prev_val = val + else: + comment_match = comment_regex.match(line) + if comment_match and prev_val is not None: + comment = comment_match.group(1) + tokens[prev_val]['comment'] = comment + keys = sorted(tokens.keys()) + # load the output skeleton from the target: + try: + fp = open(outFileName) + except OSError as err: + sys.stderr.write("I/O error: %s\n" % str(err)) + sys.exit(2) + with fp: + format = fp.read().split("\n") + try: + start = format.index("#--start constants--") + 1 + end = format.index("#--end constants--") + except ValueError: + sys.stderr.write("target does not contain format markers") + sys.exit(3) + lines = [] + for key in keys: + lines.append("%s = %d" % (tokens[key]["token"], key)) + if "comment" in tokens[key]: + lines.append("# %s" % tokens[key]["comment"]) + format[start:end] = lines + try: + fp = open(outFileName, 'w') + except OSError as err: + sys.stderr.write("I/O error: %s\n" % str(err)) + sys.exit(4) + with fp: + fp.write("\n".join(format)) + + +if __name__ == "__main__": + _main() diff --git a/winvenv/Lib/tokenize.py b/winvenv/Lib/tokenize.py new file mode 100644 index 0000000..0eccc9b --- /dev/null +++ b/winvenv/Lib/tokenize.py @@ -0,0 +1,736 @@ +"""Tokenization help for Python programs. + +tokenize(readline) is a generator that breaks a stream of bytes into +Python tokens. It decodes the bytes according to PEP-0263 for +determining source file encoding. + +It accepts a readline-like method which is called repeatedly to get the +next line of input (or b"" for EOF). It generates 5-tuples with these +members: + + the token type (see token.py) + the token (a string) + the starting (row, column) indices of the token (a 2-tuple of ints) + the ending (row, column) indices of the token (a 2-tuple of ints) + the original line (string) + +It is designed to match the working of the Python tokenizer exactly, except +that it produces COMMENT tokens for comments and gives type OP for all +operators. Additionally, all token lists start with an ENCODING token +which tells you which encoding was used to decode the bytes stream. +""" + +__author__ = 'Ka-Ping Yee ' +__credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, ' + 'Skip Montanaro, Raymond Hettinger, Trent Nelson, ' + 'Michael Foord') +from builtins import open as _builtin_open +from codecs import lookup, BOM_UTF8 +import collections +from io import TextIOWrapper +from itertools import chain +import itertools as _itertools +import re +import sys +from token import * + +cookie_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII) +blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) + +import token +__all__ = token.__all__ + ["tokenize", "detect_encoding", + "untokenize", "TokenInfo"] +del token + +EXACT_TOKEN_TYPES = { + '(': LPAR, + ')': RPAR, + '[': LSQB, + ']': RSQB, + ':': COLON, + ',': COMMA, + ';': SEMI, + '+': PLUS, + '-': MINUS, + '*': STAR, + '/': SLASH, + '|': VBAR, + '&': AMPER, + '<': LESS, + '>': GREATER, + '=': EQUAL, + '.': DOT, + '%': PERCENT, + '{': LBRACE, + '}': RBRACE, + '==': EQEQUAL, + '!=': NOTEQUAL, + '<=': LESSEQUAL, + '>=': GREATEREQUAL, + '~': TILDE, + '^': CIRCUMFLEX, + '<<': LEFTSHIFT, + '>>': RIGHTSHIFT, + '**': DOUBLESTAR, + '+=': PLUSEQUAL, + '-=': MINEQUAL, + '*=': STAREQUAL, + '/=': SLASHEQUAL, + '%=': PERCENTEQUAL, + '&=': AMPEREQUAL, + '|=': VBAREQUAL, + '^=': CIRCUMFLEXEQUAL, + '<<=': LEFTSHIFTEQUAL, + '>>=': RIGHTSHIFTEQUAL, + '**=': DOUBLESTAREQUAL, + '//': DOUBLESLASH, + '//=': DOUBLESLASHEQUAL, + '...': ELLIPSIS, + '->': RARROW, + '@': AT, + '@=': ATEQUAL, +} + +class TokenInfo(collections.namedtuple('TokenInfo', 'type string start end line')): + def __repr__(self): + annotated_type = '%d (%s)' % (self.type, tok_name[self.type]) + return ('TokenInfo(type=%s, string=%r, start=%r, end=%r, line=%r)' % + self._replace(type=annotated_type)) + + @property + def exact_type(self): + if self.type == OP and self.string in EXACT_TOKEN_TYPES: + return EXACT_TOKEN_TYPES[self.string] + else: + return self.type + +def group(*choices): return '(' + '|'.join(choices) + ')' +def any(*choices): return group(*choices) + '*' +def maybe(*choices): return group(*choices) + '?' + +# Note: we use unicode matching for names ("\w") but ascii matching for +# number literals. +Whitespace = r'[ \f\t]*' +Comment = r'#[^\r\n]*' +Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment) +Name = r'\w+' + +Hexnumber = r'0[xX](?:_?[0-9a-fA-F])+' +Binnumber = r'0[bB](?:_?[01])+' +Octnumber = r'0[oO](?:_?[0-7])+' +Decnumber = r'(?:0(?:_?0)*|[1-9](?:_?[0-9])*)' +Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber) +Exponent = r'[eE][-+]?[0-9](?:_?[0-9])*' +Pointfloat = group(r'[0-9](?:_?[0-9])*\.(?:[0-9](?:_?[0-9])*)?', + r'\.[0-9](?:_?[0-9])*') + maybe(Exponent) +Expfloat = r'[0-9](?:_?[0-9])*' + Exponent +Floatnumber = group(Pointfloat, Expfloat) +Imagnumber = group(r'[0-9](?:_?[0-9])*[jJ]', Floatnumber + r'[jJ]') +Number = group(Imagnumber, Floatnumber, Intnumber) + +# Return the empty string, plus all of the valid string prefixes. +def _all_string_prefixes(): + # The valid string prefixes. Only contain the lower case versions, + # and don't contain any permuations (include 'fr', but not + # 'rf'). The various permutations will be generated. + _valid_string_prefixes = ['b', 'r', 'u', 'f', 'br', 'fr'] + # if we add binary f-strings, add: ['fb', 'fbr'] + result = {''} + for prefix in _valid_string_prefixes: + for t in _itertools.permutations(prefix): + # create a list with upper and lower versions of each + # character + for u in _itertools.product(*[(c, c.upper()) for c in t]): + result.add(''.join(u)) + return result + +def _compile(expr): + return re.compile(expr, re.UNICODE) + +# Note that since _all_string_prefixes includes the empty string, +# StringPrefix can be the empty string (making it optional). +StringPrefix = group(*_all_string_prefixes()) + +# Tail end of ' string. +Single = r"[^'\\]*(?:\\.[^'\\]*)*'" +# Tail end of " string. +Double = r'[^"\\]*(?:\\.[^"\\]*)*"' +# Tail end of ''' string. +Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''" +# Tail end of """ string. +Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""' +Triple = group(StringPrefix + "'''", StringPrefix + '"""') +# Single-line ' or " string. +String = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'", + StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"') + +# Because of leftmost-then-longest match semantics, be sure to put the +# longest operators first (e.g., if = came before ==, == would get +# recognized as two instances of =). +Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=", + r"//=?", r"->", + r"[+\-*/%&@|^=<>]=?", + r"~") + +Bracket = '[][(){}]' +Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]') +Funny = group(Operator, Bracket, Special) + +PlainToken = group(Number, Funny, String, Name) +Token = Ignore + PlainToken + +# First (or only) line of ' or " string. +ContStr = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*" + + group("'", r'\\\r?\n'), + StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' + + group('"', r'\\\r?\n')) +PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple) +PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) + +# For a given string prefix plus quotes, endpats maps it to a regex +# to match the remainder of that string. _prefix can be empty, for +# a normal single or triple quoted string (with no prefix). +endpats = {} +for _prefix in _all_string_prefixes(): + endpats[_prefix + "'"] = Single + endpats[_prefix + '"'] = Double + endpats[_prefix + "'''"] = Single3 + endpats[_prefix + '"""'] = Double3 + +# A set of all of the single and triple quoted string prefixes, +# including the opening quotes. +single_quoted = set() +triple_quoted = set() +for t in _all_string_prefixes(): + for u in (t + '"', t + "'"): + single_quoted.add(u) + for u in (t + '"""', t + "'''"): + triple_quoted.add(u) + +tabsize = 8 + +class TokenError(Exception): pass + +class StopTokenizing(Exception): pass + + +class Untokenizer: + + def __init__(self): + self.tokens = [] + self.prev_row = 1 + self.prev_col = 0 + self.encoding = None + + def add_whitespace(self, start): + row, col = start + if row < self.prev_row or row == self.prev_row and col < self.prev_col: + raise ValueError("start ({},{}) precedes previous end ({},{})" + .format(row, col, self.prev_row, self.prev_col)) + row_offset = row - self.prev_row + if row_offset: + self.tokens.append("\\\n" * row_offset) + self.prev_col = 0 + col_offset = col - self.prev_col + if col_offset: + self.tokens.append(" " * col_offset) + + def untokenize(self, iterable): + it = iter(iterable) + indents = [] + startline = False + for t in it: + if len(t) == 2: + self.compat(t, it) + break + tok_type, token, start, end, line = t + if tok_type == ENCODING: + self.encoding = token + continue + if tok_type == ENDMARKER: + break + if tok_type == INDENT: + indents.append(token) + continue + elif tok_type == DEDENT: + indents.pop() + self.prev_row, self.prev_col = end + continue + elif tok_type in (NEWLINE, NL): + startline = True + elif startline and indents: + indent = indents[-1] + if start[1] >= len(indent): + self.tokens.append(indent) + self.prev_col = len(indent) + startline = False + self.add_whitespace(start) + self.tokens.append(token) + self.prev_row, self.prev_col = end + if tok_type in (NEWLINE, NL): + self.prev_row += 1 + self.prev_col = 0 + return "".join(self.tokens) + + def compat(self, token, iterable): + indents = [] + toks_append = self.tokens.append + startline = token[0] in (NEWLINE, NL) + prevstring = False + + for tok in chain([token], iterable): + toknum, tokval = tok[:2] + if toknum == ENCODING: + self.encoding = tokval + continue + + if toknum in (NAME, NUMBER): + tokval += ' ' + + # Insert a space between two consecutive strings + if toknum == STRING: + if prevstring: + tokval = ' ' + tokval + prevstring = True + else: + prevstring = False + + if toknum == INDENT: + indents.append(tokval) + continue + elif toknum == DEDENT: + indents.pop() + continue + elif toknum in (NEWLINE, NL): + startline = True + elif startline and indents: + toks_append(indents[-1]) + startline = False + toks_append(tokval) + + +def untokenize(iterable): + """Transform tokens back into Python source code. + It returns a bytes object, encoded using the ENCODING + token, which is the first token sequence output by tokenize. + + Each element returned by the iterable must be a token sequence + with at least two elements, a token number and token value. If + only two tokens are passed, the resulting output is poor. + + Round-trip invariant for full input: + Untokenized source will match input source exactly + + Round-trip invariant for limited input: + # Output bytes will tokenize back to the input + t1 = [tok[:2] for tok in tokenize(f.readline)] + newcode = untokenize(t1) + readline = BytesIO(newcode).readline + t2 = [tok[:2] for tok in tokenize(readline)] + assert t1 == t2 + """ + ut = Untokenizer() + out = ut.untokenize(iterable) + if ut.encoding is not None: + out = out.encode(ut.encoding) + return out + + +def _get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace("_", "-") + if enc == "utf-8" or enc.startswith("utf-8-"): + return "utf-8" + if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ + enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): + return "iso-8859-1" + return orig_enc + +def detect_encoding(readline): + """ + The detect_encoding() function is used to detect the encoding that should + be used to decode a Python source file. It requires one argument, readline, + in the same way as the tokenize() generator. + + It will call readline a maximum of twice, and return the encoding used + (as a string) and a list of any lines (left as bytes) it has read in. + + It detects the encoding from the presence of a utf-8 bom or an encoding + cookie as specified in pep-0263. If both a bom and a cookie are present, + but disagree, a SyntaxError will be raised. If the encoding cookie is an + invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, + 'utf-8-sig' is returned. + + If no encoding is specified, then the default of 'utf-8' will be returned. + """ + try: + filename = readline.__self__.name + except AttributeError: + filename = None + bom_found = False + encoding = None + default = 'utf-8' + def read_or_stop(): + try: + return readline() + except StopIteration: + return b'' + + def find_cookie(line): + try: + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') + except UnicodeDecodeError: + msg = "invalid or missing encoding declaration" + if filename is not None: + msg = '{} for {!r}'.format(msg, filename) + raise SyntaxError(msg) + + match = cookie_re.match(line_string) + if not match: + return None + encoding = _get_normal_name(match.group(1)) + try: + codec = lookup(encoding) + except LookupError: + # This behaviour mimics the Python interpreter + if filename is None: + msg = "unknown encoding: " + encoding + else: + msg = "unknown encoding for {!r}: {}".format(filename, + encoding) + raise SyntaxError(msg) + + if bom_found: + if encoding != 'utf-8': + # This behaviour mimics the Python interpreter + if filename is None: + msg = 'encoding problem: utf-8' + else: + msg = 'encoding problem for {!r}: utf-8'.format(filename) + raise SyntaxError(msg) + encoding += '-sig' + return encoding + + first = read_or_stop() + if first.startswith(BOM_UTF8): + bom_found = True + first = first[3:] + default = 'utf-8-sig' + if not first: + return default, [] + + encoding = find_cookie(first) + if encoding: + return encoding, [first] + if not blank_re.match(first): + return default, [first] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + + +def open(filename): + """Open a file in read only mode using the encoding detected by + detect_encoding(). + """ + buffer = _builtin_open(filename, 'rb') + try: + encoding, lines = detect_encoding(buffer.readline) + buffer.seek(0) + text = TextIOWrapper(buffer, encoding, line_buffering=True) + text.mode = 'r' + return text + except: + buffer.close() + raise + + +def tokenize(readline): + """ + The tokenize() generator requires one argument, readline, which + must be a callable object which provides the same interface as the + readline() method of built-in file objects. Each call to the function + should return one line of input as bytes. Alternatively, readline + can be a callable function terminating with StopIteration: + readline = open(myfile, 'rb').__next__ # Example of alternate readline + + The generator produces 5-tuples with these members: the token type; the + token string; a 2-tuple (srow, scol) of ints specifying the row and + column where the token begins in the source; a 2-tuple (erow, ecol) of + ints specifying the row and column where the token ends in the source; + and the line on which the token was found. The line passed is the + logical line; continuation lines are included. + + The first token sequence will always be an ENCODING token + which tells you which encoding was used to decode the bytes stream. + """ + # This import is here to avoid problems when the itertools module is not + # built yet and tokenize is imported. + from itertools import chain, repeat + encoding, consumed = detect_encoding(readline) + rl_gen = iter(readline, b"") + empty = repeat(b"") + return _tokenize(chain(consumed, rl_gen, empty).__next__, encoding) + + +def _tokenize(readline, encoding): + lnum = parenlev = continued = 0 + numchars = '0123456789' + contstr, needcont = '', 0 + contline = None + indents = [0] + + if encoding is not None: + if encoding == "utf-8-sig": + # BOM will already have been stripped. + encoding = "utf-8" + yield TokenInfo(ENCODING, encoding, (0, 0), (0, 0), '') + last_line = b'' + line = b'' + while True: # loop over lines in stream + try: + # We capture the value of the line variable here because + # readline uses the empty string '' to signal end of input, + # hence `line` itself will always be overwritten at the end + # of this loop. + last_line = line + line = readline() + except StopIteration: + line = b'' + + if encoding is not None: + line = line.decode(encoding) + lnum += 1 + pos, max = 0, len(line) + + if contstr: # continued string + if not line: + raise TokenError("EOF in multi-line string", strstart) + endmatch = endprog.match(line) + if endmatch: + pos = end = endmatch.end(0) + yield TokenInfo(STRING, contstr + line[:end], + strstart, (lnum, end), contline + line) + contstr, needcont = '', 0 + contline = None + elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': + yield TokenInfo(ERRORTOKEN, contstr + line, + strstart, (lnum, len(line)), contline) + contstr = '' + contline = None + continue + else: + contstr = contstr + line + contline = contline + line + continue + + elif parenlev == 0 and not continued: # new statement + if not line: break + column = 0 + while pos < max: # measure leading whitespace + if line[pos] == ' ': + column += 1 + elif line[pos] == '\t': + column = (column//tabsize + 1)*tabsize + elif line[pos] == '\f': + column = 0 + else: + break + pos += 1 + if pos == max: + break + + if line[pos] in '#\r\n': # skip comments or blank lines + if line[pos] == '#': + comment_token = line[pos:].rstrip('\r\n') + yield TokenInfo(COMMENT, comment_token, + (lnum, pos), (lnum, pos + len(comment_token)), line) + pos += len(comment_token) + + yield TokenInfo(NL, line[pos:], + (lnum, pos), (lnum, len(line)), line) + continue + + if column > indents[-1]: # count indents or dedents + indents.append(column) + yield TokenInfo(INDENT, line[:pos], (lnum, 0), (lnum, pos), line) + while column < indents[-1]: + if column not in indents: + raise IndentationError( + "unindent does not match any outer indentation level", + ("", lnum, pos, line)) + indents = indents[:-1] + + yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line) + + else: # continued statement + if not line: + raise TokenError("EOF in multi-line statement", (lnum, 0)) + continued = 0 + + while pos < max: + pseudomatch = _compile(PseudoToken).match(line, pos) + if pseudomatch: # scan for tokens + start, end = pseudomatch.span(1) + spos, epos, pos = (lnum, start), (lnum, end), end + if start == end: + continue + token, initial = line[start:end], line[start] + + if (initial in numchars or # ordinary number + (initial == '.' and token != '.' and token != '...')): + yield TokenInfo(NUMBER, token, spos, epos, line) + elif initial in '\r\n': + if parenlev > 0: + yield TokenInfo(NL, token, spos, epos, line) + else: + yield TokenInfo(NEWLINE, token, spos, epos, line) + + elif initial == '#': + assert not token.endswith("\n") + yield TokenInfo(COMMENT, token, spos, epos, line) + + elif token in triple_quoted: + endprog = _compile(endpats[token]) + endmatch = endprog.match(line, pos) + if endmatch: # all on one line + pos = endmatch.end(0) + token = line[start:pos] + yield TokenInfo(STRING, token, spos, (lnum, pos), line) + else: + strstart = (lnum, start) # multiple lines + contstr = line[start:] + contline = line + break + + # Check up to the first 3 chars of the token to see if + # they're in the single_quoted set. If so, they start + # a string. + # We're using the first 3, because we're looking for + # "rb'" (for example) at the start of the token. If + # we switch to longer prefixes, this needs to be + # adjusted. + # Note that initial == token[:1]. + # Also note that single quote checking must come after + # triple quote checking (above). + elif (initial in single_quoted or + token[:2] in single_quoted or + token[:3] in single_quoted): + if token[-1] == '\n': # continued string + strstart = (lnum, start) + # Again, using the first 3 chars of the + # token. This is looking for the matching end + # regex for the correct type of quote + # character. So it's really looking for + # endpats["'"] or endpats['"'], by trying to + # skip string prefix characters, if any. + endprog = _compile(endpats.get(initial) or + endpats.get(token[1]) or + endpats.get(token[2])) + contstr, needcont = line[start:], 1 + contline = line + break + else: # ordinary string + yield TokenInfo(STRING, token, spos, epos, line) + + elif initial.isidentifier(): # ordinary name + yield TokenInfo(NAME, token, spos, epos, line) + elif initial == '\\': # continued stmt + continued = 1 + else: + if initial in '([{': + parenlev += 1 + elif initial in ')]}': + parenlev -= 1 + yield TokenInfo(OP, token, spos, epos, line) + else: + yield TokenInfo(ERRORTOKEN, line[pos], + (lnum, pos), (lnum, pos+1), line) + pos += 1 + + # Add an implicit NEWLINE if the input doesn't end in one + if last_line and last_line[-1] not in '\r\n': + yield TokenInfo(NEWLINE, '', (lnum - 1, len(last_line)), (lnum - 1, len(last_line) + 1), '') + for indent in indents[1:]: # pop remaining indent levels + yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '') + yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '') + + +# An undocumented, backwards compatible, API for all the places in the standard +# library that expect to be able to use tokenize with strings +def generate_tokens(readline): + return _tokenize(readline, None) + +def main(): + import argparse + + # Helper error handling routines + def perror(message): + print(message, file=sys.stderr) + + def error(message, filename=None, location=None): + if location: + args = (filename,) + location + (message,) + perror("%s:%d:%d: error: %s" % args) + elif filename: + perror("%s: error: %s" % (filename, message)) + else: + perror("error: %s" % message) + sys.exit(1) + + # Parse the arguments and options + parser = argparse.ArgumentParser(prog='python -m tokenize') + parser.add_argument(dest='filename', nargs='?', + metavar='filename.py', + help='the file to tokenize; defaults to stdin') + parser.add_argument('-e', '--exact', dest='exact', action='store_true', + help='display token names using the exact type') + args = parser.parse_args() + + try: + # Tokenize the input + if args.filename: + filename = args.filename + with _builtin_open(filename, 'rb') as f: + tokens = list(tokenize(f.readline)) + else: + filename = "" + tokens = _tokenize(sys.stdin.readline, None) + + # Output the tokenization + for token in tokens: + token_type = token.type + if args.exact: + token_type = token.exact_type + token_range = "%d,%d-%d,%d:" % (token.start + token.end) + print("%-20s%-15s%-15r" % + (token_range, tok_name[token_type], token.string)) + except IndentationError as err: + line, column = err.args[1][1:3] + error(err.args[0], filename, (line, column)) + except TokenError as err: + line, column = err.args[1] + error(err.args[0], filename, (line, column)) + except SyntaxError as err: + error(err, filename) + except OSError as err: + error(err) + except KeyboardInterrupt: + print("interrupted\n") + except Exception as err: + perror("unexpected error: %s" % err) + raise + +if __name__ == "__main__": + main() diff --git a/winvenv/Lib/types.py b/winvenv/Lib/types.py new file mode 100644 index 0000000..ce4652f --- /dev/null +++ b/winvenv/Lib/types.py @@ -0,0 +1,295 @@ +""" +Define names for built-in types that aren't directly accessible as a builtin. +""" +import sys + +# Iterators in Python aren't a matter of type but of protocol. A large +# and changing number of builtin types implement *some* flavor of +# iterator. Don't check the type! Use hasattr to check for both +# "__iter__" and "__next__" attributes instead. + +def _f(): pass +FunctionType = type(_f) +LambdaType = type(lambda: None) # Same as FunctionType +CodeType = type(_f.__code__) +MappingProxyType = type(type.__dict__) +SimpleNamespace = type(sys.implementation) + +def _g(): + yield 1 +GeneratorType = type(_g()) + +async def _c(): pass +_c = _c() +CoroutineType = type(_c) +_c.close() # Prevent ResourceWarning + +async def _ag(): + yield +_ag = _ag() +AsyncGeneratorType = type(_ag) + +class _C: + def _m(self): pass +MethodType = type(_C()._m) + +BuiltinFunctionType = type(len) +BuiltinMethodType = type([].append) # Same as BuiltinFunctionType + +WrapperDescriptorType = type(object.__init__) +MethodWrapperType = type(object().__str__) +MethodDescriptorType = type(str.join) +ClassMethodDescriptorType = type(dict.__dict__['fromkeys']) + +ModuleType = type(sys) + +try: + raise TypeError +except TypeError: + tb = sys.exc_info()[2] + TracebackType = type(tb) + FrameType = type(tb.tb_frame) + tb = None; del tb + +# For Jython, the following two types are identical +GetSetDescriptorType = type(FunctionType.__code__) +MemberDescriptorType = type(FunctionType.__globals__) + +del sys, _f, _g, _C, _c, # Not for export + + +# Provide a PEP 3115 compliant mechanism for class creation +def new_class(name, bases=(), kwds=None, exec_body=None): + """Create a class object dynamically using the appropriate metaclass.""" + resolved_bases = resolve_bases(bases) + meta, ns, kwds = prepare_class(name, resolved_bases, kwds) + if exec_body is not None: + exec_body(ns) + if resolved_bases is not bases: + ns['__orig_bases__'] = bases + return meta(name, resolved_bases, ns, **kwds) + +def resolve_bases(bases): + """Resolve MRO entries dynamically as specified by PEP 560.""" + new_bases = list(bases) + updated = False + shift = 0 + for i, base in enumerate(bases): + if isinstance(base, type): + continue + if not hasattr(base, "__mro_entries__"): + continue + new_base = base.__mro_entries__(bases) + updated = True + if not isinstance(new_base, tuple): + raise TypeError("__mro_entries__ must return a tuple") + else: + new_bases[i+shift:i+shift+1] = new_base + shift += len(new_base) - 1 + if not updated: + return bases + return tuple(new_bases) + +def prepare_class(name, bases=(), kwds=None): + """Call the __prepare__ method of the appropriate metaclass. + + Returns (metaclass, namespace, kwds) as a 3-tuple + + *metaclass* is the appropriate metaclass + *namespace* is the prepared class namespace + *kwds* is an updated copy of the passed in kwds argument with any + 'metaclass' entry removed. If no kwds argument is passed in, this will + be an empty dict. + """ + if kwds is None: + kwds = {} + else: + kwds = dict(kwds) # Don't alter the provided mapping + if 'metaclass' in kwds: + meta = kwds.pop('metaclass') + else: + if bases: + meta = type(bases[0]) + else: + meta = type + if isinstance(meta, type): + # when meta is a type, we first determine the most-derived metaclass + # instead of invoking the initial candidate directly + meta = _calculate_meta(meta, bases) + if hasattr(meta, '__prepare__'): + ns = meta.__prepare__(name, bases, **kwds) + else: + ns = {} + return meta, ns, kwds + +def _calculate_meta(meta, bases): + """Calculate the most derived metaclass.""" + winner = meta + for base in bases: + base_meta = type(base) + if issubclass(winner, base_meta): + continue + if issubclass(base_meta, winner): + winner = base_meta + continue + # else: + raise TypeError("metaclass conflict: " + "the metaclass of a derived class " + "must be a (non-strict) subclass " + "of the metaclasses of all its bases") + return winner + +class DynamicClassAttribute: + """Route attribute access on a class to __getattr__. + + This is a descriptor, used to define attributes that act differently when + accessed through an instance and through a class. Instance access remains + normal, but access to an attribute through a class will be routed to the + class's __getattr__ method; this is done by raising AttributeError. + + This allows one to have properties active on an instance, and have virtual + attributes on the class with the same name (see Enum for an example). + + """ + def __init__(self, fget=None, fset=None, fdel=None, doc=None): + self.fget = fget + self.fset = fset + self.fdel = fdel + # next two lines make DynamicClassAttribute act the same as property + self.__doc__ = doc or fget.__doc__ + self.overwrite_doc = doc is None + # support for abstract methods + self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False)) + + def __get__(self, instance, ownerclass=None): + if instance is None: + if self.__isabstractmethod__: + return self + raise AttributeError() + elif self.fget is None: + raise AttributeError("unreadable attribute") + return self.fget(instance) + + def __set__(self, instance, value): + if self.fset is None: + raise AttributeError("can't set attribute") + self.fset(instance, value) + + def __delete__(self, instance): + if self.fdel is None: + raise AttributeError("can't delete attribute") + self.fdel(instance) + + def getter(self, fget): + fdoc = fget.__doc__ if self.overwrite_doc else None + result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__) + result.overwrite_doc = self.overwrite_doc + return result + + def setter(self, fset): + result = type(self)(self.fget, fset, self.fdel, self.__doc__) + result.overwrite_doc = self.overwrite_doc + return result + + def deleter(self, fdel): + result = type(self)(self.fget, self.fset, fdel, self.__doc__) + result.overwrite_doc = self.overwrite_doc + return result + + +class _GeneratorWrapper: + # TODO: Implement this in C. + def __init__(self, gen): + self.__wrapped = gen + self.__isgen = gen.__class__ is GeneratorType + self.__name__ = getattr(gen, '__name__', None) + self.__qualname__ = getattr(gen, '__qualname__', None) + def send(self, val): + return self.__wrapped.send(val) + def throw(self, tp, *rest): + return self.__wrapped.throw(tp, *rest) + def close(self): + return self.__wrapped.close() + @property + def gi_code(self): + return self.__wrapped.gi_code + @property + def gi_frame(self): + return self.__wrapped.gi_frame + @property + def gi_running(self): + return self.__wrapped.gi_running + @property + def gi_yieldfrom(self): + return self.__wrapped.gi_yieldfrom + cr_code = gi_code + cr_frame = gi_frame + cr_running = gi_running + cr_await = gi_yieldfrom + def __next__(self): + return next(self.__wrapped) + def __iter__(self): + if self.__isgen: + return self.__wrapped + return self + __await__ = __iter__ + +def coroutine(func): + """Convert regular generator function to a coroutine.""" + + if not callable(func): + raise TypeError('types.coroutine() expects a callable') + + if (func.__class__ is FunctionType and + getattr(func, '__code__', None).__class__ is CodeType): + + co_flags = func.__code__.co_flags + + # Check if 'func' is a coroutine function. + # (0x180 == CO_COROUTINE | CO_ITERABLE_COROUTINE) + if co_flags & 0x180: + return func + + # Check if 'func' is a generator function. + # (0x20 == CO_GENERATOR) + if co_flags & 0x20: + # TODO: Implement this in C. + co = func.__code__ + func.__code__ = CodeType( + co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, + co.co_stacksize, + co.co_flags | 0x100, # 0x100 == CO_ITERABLE_COROUTINE + co.co_code, + co.co_consts, co.co_names, co.co_varnames, co.co_filename, + co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, + co.co_cellvars) + return func + + # The following code is primarily to support functions that + # return generator-like objects (for instance generators + # compiled with Cython). + + # Delay functools and _collections_abc import for speeding up types import. + import functools + import _collections_abc + @functools.wraps(func) + def wrapped(*args, **kwargs): + coro = func(*args, **kwargs) + if (coro.__class__ is CoroutineType or + coro.__class__ is GeneratorType and coro.gi_code.co_flags & 0x100): + # 'coro' is a native coroutine object or an iterable coroutine + return coro + if (isinstance(coro, _collections_abc.Generator) and + not isinstance(coro, _collections_abc.Coroutine)): + # 'coro' is either a pure Python generator iterator, or it + # implements collections.abc.Generator (and does not implement + # collections.abc.Coroutine). + return _GeneratorWrapper(coro) + # 'coro' is either an instance of collections.abc.Coroutine or + # some other object -- pass it through. + return coro + + return wrapped + + +__all__ = [n for n in globals() if n[:1] != '_'] diff --git a/winvenv/Lib/warnings.py b/winvenv/Lib/warnings.py new file mode 100644 index 0000000..81f9864 --- /dev/null +++ b/winvenv/Lib/warnings.py @@ -0,0 +1,554 @@ +"""Python part of the warnings subsystem.""" + +import sys + + +__all__ = ["warn", "warn_explicit", "showwarning", + "formatwarning", "filterwarnings", "simplefilter", + "resetwarnings", "catch_warnings"] + +def showwarning(message, category, filename, lineno, file=None, line=None): + """Hook to write a warning to a file; replace if you like.""" + msg = WarningMessage(message, category, filename, lineno, file, line) + _showwarnmsg_impl(msg) + +def formatwarning(message, category, filename, lineno, line=None): + """Function to format a warning the standard way.""" + msg = WarningMessage(message, category, filename, lineno, None, line) + return _formatwarnmsg_impl(msg) + +def _showwarnmsg_impl(msg): + file = msg.file + if file is None: + file = sys.stderr + if file is None: + # sys.stderr is None when run with pythonw.exe: + # warnings get lost + return + text = _formatwarnmsg(msg) + try: + file.write(text) + except OSError: + # the file (probably stderr) is invalid - this warning gets lost. + pass + +def _formatwarnmsg_impl(msg): + s = ("%s:%s: %s: %s\n" + % (msg.filename, msg.lineno, msg.category.__name__, + msg.message)) + + if msg.line is None: + try: + import linecache + line = linecache.getline(msg.filename, msg.lineno) + except Exception: + # When a warning is logged during Python shutdown, linecache + # and the import machinery don't work anymore + line = None + linecache = None + else: + line = msg.line + if line: + line = line.strip() + s += " %s\n" % line + + if msg.source is not None: + try: + import tracemalloc + tb = tracemalloc.get_object_traceback(msg.source) + except Exception: + # When a warning is logged during Python shutdown, tracemalloc + # and the import machinery don't work anymore + tb = None + + if tb is not None: + s += 'Object allocated at (most recent call last):\n' + for frame in tb: + s += (' File "%s", lineno %s\n' + % (frame.filename, frame.lineno)) + + try: + if linecache is not None: + line = linecache.getline(frame.filename, frame.lineno) + else: + line = None + except Exception: + line = None + if line: + line = line.strip() + s += ' %s\n' % line + return s + +# Keep a reference to check if the function was replaced +_showwarning_orig = showwarning + +def _showwarnmsg(msg): + """Hook to write a warning to a file; replace if you like.""" + try: + sw = showwarning + except NameError: + pass + else: + if sw is not _showwarning_orig: + # warnings.showwarning() was replaced + if not callable(sw): + raise TypeError("warnings.showwarning() must be set to a " + "function or method") + + sw(msg.message, msg.category, msg.filename, msg.lineno, + msg.file, msg.line) + return + _showwarnmsg_impl(msg) + +# Keep a reference to check if the function was replaced +_formatwarning_orig = formatwarning + +def _formatwarnmsg(msg): + """Function to format a warning the standard way.""" + try: + fw = formatwarning + except NameError: + pass + else: + if fw is not _formatwarning_orig: + # warnings.formatwarning() was replaced + return fw(msg.message, msg.category, + msg.filename, msg.lineno, line=msg.line) + return _formatwarnmsg_impl(msg) + +def filterwarnings(action, message="", category=Warning, module="", lineno=0, + append=False): + """Insert an entry into the list of warnings filters (at the front). + + 'action' -- one of "error", "ignore", "always", "default", "module", + or "once" + 'message' -- a regex that the warning message must match + 'category' -- a class that the warning must be a subclass of + 'module' -- a regex that the module name must match + 'lineno' -- an integer line number, 0 matches all warnings + 'append' -- if true, append to the list of filters + """ + assert action in ("error", "ignore", "always", "default", "module", + "once"), "invalid action: %r" % (action,) + assert isinstance(message, str), "message must be a string" + assert isinstance(category, type), "category must be a class" + assert issubclass(category, Warning), "category must be a Warning subclass" + assert isinstance(module, str), "module must be a string" + assert isinstance(lineno, int) and lineno >= 0, \ + "lineno must be an int >= 0" + + if message or module: + import re + + if message: + message = re.compile(message, re.I) + else: + message = None + if module: + module = re.compile(module) + else: + module = None + + _add_filter(action, message, category, module, lineno, append=append) + +def simplefilter(action, category=Warning, lineno=0, append=False): + """Insert a simple entry into the list of warnings filters (at the front). + + A simple filter matches all modules and messages. + 'action' -- one of "error", "ignore", "always", "default", "module", + or "once" + 'category' -- a class that the warning must be a subclass of + 'lineno' -- an integer line number, 0 matches all warnings + 'append' -- if true, append to the list of filters + """ + assert action in ("error", "ignore", "always", "default", "module", + "once"), "invalid action: %r" % (action,) + assert isinstance(lineno, int) and lineno >= 0, \ + "lineno must be an int >= 0" + _add_filter(action, None, category, None, lineno, append=append) + +def _add_filter(*item, append): + # Remove possible duplicate filters, so new one will be placed + # in correct place. If append=True and duplicate exists, do nothing. + if not append: + try: + filters.remove(item) + except ValueError: + pass + filters.insert(0, item) + else: + if item not in filters: + filters.append(item) + _filters_mutated() + +def resetwarnings(): + """Clear the list of warning filters, so that no filters are active.""" + filters[:] = [] + _filters_mutated() + +class _OptionError(Exception): + """Exception used by option processing helpers.""" + pass + +# Helper to process -W options passed via sys.warnoptions +def _processoptions(args): + for arg in args: + try: + _setoption(arg) + except _OptionError as msg: + print("Invalid -W option ignored:", msg, file=sys.stderr) + +# Helper for _processoptions() +def _setoption(arg): + import re + parts = arg.split(':') + if len(parts) > 5: + raise _OptionError("too many fields (max 5): %r" % (arg,)) + while len(parts) < 5: + parts.append('') + action, message, category, module, lineno = [s.strip() + for s in parts] + action = _getaction(action) + message = re.escape(message) + category = _getcategory(category) + module = re.escape(module) + if module: + module = module + '$' + if lineno: + try: + lineno = int(lineno) + if lineno < 0: + raise ValueError + except (ValueError, OverflowError): + raise _OptionError("invalid lineno %r" % (lineno,)) from None + else: + lineno = 0 + filterwarnings(action, message, category, module, lineno) + +# Helper for _setoption() +def _getaction(action): + if not action: + return "default" + if action == "all": return "always" # Alias + for a in ('default', 'always', 'ignore', 'module', 'once', 'error'): + if a.startswith(action): + return a + raise _OptionError("invalid action: %r" % (action,)) + +# Helper for _setoption() +def _getcategory(category): + import re + if not category: + return Warning + if re.match("^[a-zA-Z0-9_]+$", category): + try: + cat = eval(category) + except NameError: + raise _OptionError("unknown warning category: %r" % (category,)) from None + else: + i = category.rfind(".") + module = category[:i] + klass = category[i+1:] + try: + m = __import__(module, None, None, [klass]) + except ImportError: + raise _OptionError("invalid module name: %r" % (module,)) from None + try: + cat = getattr(m, klass) + except AttributeError: + raise _OptionError("unknown warning category: %r" % (category,)) from None + if not issubclass(cat, Warning): + raise _OptionError("invalid warning category: %r" % (category,)) + return cat + + +def _is_internal_frame(frame): + """Signal whether the frame is an internal CPython implementation detail.""" + filename = frame.f_code.co_filename + return 'importlib' in filename and '_bootstrap' in filename + + +def _next_external_frame(frame): + """Find the next frame that doesn't involve CPython internals.""" + frame = frame.f_back + while frame is not None and _is_internal_frame(frame): + frame = frame.f_back + return frame + + +# Code typically replaced by _warnings +def warn(message, category=None, stacklevel=1, source=None): + """Issue a warning, or maybe ignore it or raise an exception.""" + # Check if message is already a Warning object + if isinstance(message, Warning): + category = message.__class__ + # Check category argument + if category is None: + category = UserWarning + if not (isinstance(category, type) and issubclass(category, Warning)): + raise TypeError("category must be a Warning subclass, " + "not '{:s}'".format(type(category).__name__)) + # Get context information + try: + if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)): + # If frame is too small to care or if the warning originated in + # internal code, then do not try to hide any frames. + frame = sys._getframe(stacklevel) + else: + frame = sys._getframe(1) + # Look for one frame less since the above line starts us off. + for x in range(stacklevel-1): + frame = _next_external_frame(frame) + if frame is None: + raise ValueError + except ValueError: + globals = sys.__dict__ + lineno = 1 + else: + globals = frame.f_globals + lineno = frame.f_lineno + if '__name__' in globals: + module = globals['__name__'] + else: + module = "" + filename = globals.get('__file__') + if filename: + fnl = filename.lower() + if fnl.endswith(".pyc"): + filename = filename[:-1] + else: + if module == "__main__": + try: + filename = sys.argv[0] + except AttributeError: + # embedded interpreters don't have sys.argv, see bug #839151 + filename = '__main__' + if not filename: + filename = module + registry = globals.setdefault("__warningregistry__", {}) + warn_explicit(message, category, filename, lineno, module, registry, + globals, source) + +def warn_explicit(message, category, filename, lineno, + module=None, registry=None, module_globals=None, + source=None): + lineno = int(lineno) + if module is None: + module = filename or "" + if module[-3:].lower() == ".py": + module = module[:-3] # XXX What about leading pathname? + if registry is None: + registry = {} + if registry.get('version', 0) != _filters_version: + registry.clear() + registry['version'] = _filters_version + if isinstance(message, Warning): + text = str(message) + category = message.__class__ + else: + text = message + message = category(message) + key = (text, category, lineno) + # Quick test for common case + if registry.get(key): + return + # Search the filters + for item in filters: + action, msg, cat, mod, ln = item + if ((msg is None or msg.match(text)) and + issubclass(category, cat) and + (mod is None or mod.match(module)) and + (ln == 0 or lineno == ln)): + break + else: + action = defaultaction + # Early exit actions + if action == "ignore": + return + + # Prime the linecache for formatting, in case the + # "file" is actually in a zipfile or something. + import linecache + linecache.getlines(filename, module_globals) + + if action == "error": + raise message + # Other actions + if action == "once": + registry[key] = 1 + oncekey = (text, category) + if onceregistry.get(oncekey): + return + onceregistry[oncekey] = 1 + elif action == "always": + pass + elif action == "module": + registry[key] = 1 + altkey = (text, category, 0) + if registry.get(altkey): + return + registry[altkey] = 1 + elif action == "default": + registry[key] = 1 + else: + # Unrecognized actions are errors + raise RuntimeError( + "Unrecognized action (%r) in warnings.filters:\n %s" % + (action, item)) + # Print message and context + msg = WarningMessage(message, category, filename, lineno, source) + _showwarnmsg(msg) + + +class WarningMessage(object): + + _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", + "line", "source") + + def __init__(self, message, category, filename, lineno, file=None, + line=None, source=None): + self.message = message + self.category = category + self.filename = filename + self.lineno = lineno + self.file = file + self.line = line + self.source = source + self._category_name = category.__name__ if category else None + + def __str__(self): + return ("{message : %r, category : %r, filename : %r, lineno : %s, " + "line : %r}" % (self.message, self._category_name, + self.filename, self.lineno, self.line)) + + +class catch_warnings(object): + + """A context manager that copies and restores the warnings filter upon + exiting the context. + + The 'record' argument specifies whether warnings should be captured by a + custom implementation of warnings.showwarning() and be appended to a list + returned by the context manager. Otherwise None is returned by the context + manager. The objects appended to the list are arguments whose attributes + mirror the arguments to showwarning(). + + The 'module' argument is to specify an alternative module to the module + named 'warnings' and imported under that name. This argument is only useful + when testing the warnings module itself. + + """ + + def __init__(self, *, record=False, module=None): + """Specify whether to record warnings and if an alternative module + should be used other than sys.modules['warnings']. + + For compatibility with Python 3.0, please consider all arguments to be + keyword-only. + + """ + self._record = record + self._module = sys.modules['warnings'] if module is None else module + self._entered = False + + def __repr__(self): + args = [] + if self._record: + args.append("record=True") + if self._module is not sys.modules['warnings']: + args.append("module=%r" % self._module) + name = type(self).__name__ + return "%s(%s)" % (name, ", ".join(args)) + + def __enter__(self): + if self._entered: + raise RuntimeError("Cannot enter %r twice" % self) + self._entered = True + self._filters = self._module.filters + self._module.filters = self._filters[:] + self._module._filters_mutated() + self._showwarning = self._module.showwarning + self._showwarnmsg_impl = self._module._showwarnmsg_impl + if self._record: + log = [] + self._module._showwarnmsg_impl = log.append + # Reset showwarning() to the default implementation to make sure + # that _showwarnmsg() calls _showwarnmsg_impl() + self._module.showwarning = self._module._showwarning_orig + return log + else: + return None + + def __exit__(self, *exc_info): + if not self._entered: + raise RuntimeError("Cannot exit %r without entering first" % self) + self._module.filters = self._filters + self._module._filters_mutated() + self._module.showwarning = self._showwarning + self._module._showwarnmsg_impl = self._showwarnmsg_impl + + +# Private utility function called by _PyErr_WarnUnawaitedCoroutine +def _warn_unawaited_coroutine(coro): + msg_lines = [ + f"coroutine '{coro.__qualname__}' was never awaited\n" + ] + if coro.cr_origin is not None: + import linecache, traceback + def extract(): + for filename, lineno, funcname in reversed(coro.cr_origin): + line = linecache.getline(filename, lineno) + yield (filename, lineno, funcname, line) + msg_lines.append("Coroutine created at (most recent call last)\n") + msg_lines += traceback.format_list(list(extract())) + msg = "".join(msg_lines).rstrip("\n") + # Passing source= here means that if the user happens to have tracemalloc + # enabled and tracking where the coroutine was created, the warning will + # contain that traceback. This does mean that if they have *both* + # coroutine origin tracking *and* tracemalloc enabled, they'll get two + # partially-redundant tracebacks. If we wanted to be clever we could + # probably detect this case and avoid it, but for now we don't bother. + warn(msg, category=RuntimeWarning, stacklevel=2, source=coro) + + +# filters contains a sequence of filter 5-tuples +# The components of the 5-tuple are: +# - an action: error, ignore, always, default, module, or once +# - a compiled regex that must match the warning message +# - a class representing the warning category +# - a compiled regex that must match the module that is being warned +# - a line number for the line being warning, or 0 to mean any line +# If either if the compiled regexs are None, match anything. +try: + from _warnings import (filters, _defaultaction, _onceregistry, + warn, warn_explicit, _filters_mutated) + defaultaction = _defaultaction + onceregistry = _onceregistry + _warnings_defaults = True +except ImportError: + filters = [] + defaultaction = "default" + onceregistry = {} + + _filters_version = 1 + + def _filters_mutated(): + global _filters_version + _filters_version += 1 + + _warnings_defaults = False + + +# Module initialization +_processoptions(sys.warnoptions) +if not _warnings_defaults: + # Several warning categories are ignored by default in regular builds + if not hasattr(sys, 'gettotalrefcount'): + filterwarnings("default", category=DeprecationWarning, + module="__main__", append=1) + simplefilter("ignore", category=DeprecationWarning, append=1) + simplefilter("ignore", category=PendingDeprecationWarning, append=1) + simplefilter("ignore", category=ImportWarning, append=1) + simplefilter("ignore", category=ResourceWarning, append=1) + +del _warnings_defaults diff --git a/winvenv/Lib/weakref.py b/winvenv/Lib/weakref.py new file mode 100644 index 0000000..99de2ea --- /dev/null +++ b/winvenv/Lib/weakref.py @@ -0,0 +1,632 @@ +"""Weak reference support for Python. + +This module is an implementation of PEP 205: + +http://www.python.org/dev/peps/pep-0205/ +""" + +# Naming convention: Variables named "wr" are weak reference objects; +# they are called this instead of "ref" to avoid name collisions with +# the module-global ref() function imported from _weakref. + +from _weakref import ( + getweakrefcount, + getweakrefs, + ref, + proxy, + CallableProxyType, + ProxyType, + ReferenceType, + _remove_dead_weakref) + +from _weakrefset import WeakSet, _IterationGuard + +import _collections_abc # Import after _weakref to avoid circular import. +import sys +import itertools + +ProxyTypes = (ProxyType, CallableProxyType) + +__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", + "WeakKeyDictionary", "ReferenceType", "ProxyType", + "CallableProxyType", "ProxyTypes", "WeakValueDictionary", + "WeakSet", "WeakMethod", "finalize"] + + +class WeakMethod(ref): + """ + A custom `weakref.ref` subclass which simulates a weak reference to + a bound method, working around the lifetime problem of bound methods. + """ + + __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__" + + def __new__(cls, meth, callback=None): + try: + obj = meth.__self__ + func = meth.__func__ + except AttributeError: + raise TypeError("argument should be a bound method, not {}" + .format(type(meth))) from None + def _cb(arg): + # The self-weakref trick is needed to avoid creating a reference + # cycle. + self = self_wr() + if self._alive: + self._alive = False + if callback is not None: + callback(self) + self = ref.__new__(cls, obj, _cb) + self._func_ref = ref(func, _cb) + self._meth_type = type(meth) + self._alive = True + self_wr = ref(self) + return self + + def __call__(self): + obj = super().__call__() + func = self._func_ref() + if obj is None or func is None: + return None + return self._meth_type(func, obj) + + def __eq__(self, other): + if isinstance(other, WeakMethod): + if not self._alive or not other._alive: + return self is other + return ref.__eq__(self, other) and self._func_ref == other._func_ref + return False + + def __ne__(self, other): + if isinstance(other, WeakMethod): + if not self._alive or not other._alive: + return self is not other + return ref.__ne__(self, other) or self._func_ref != other._func_ref + return True + + __hash__ = ref.__hash__ + + +class WeakValueDictionary(_collections_abc.MutableMapping): + """Mapping class that references values weakly. + + Entries in the dictionary will be discarded when no strong + reference to the value exists anymore + """ + # We inherit the constructor without worrying about the input + # dictionary; since it uses our .update() method, we get the right + # checks (if the other dictionary is a WeakValueDictionary, + # objects are unwrapped on the way out, and we always wrap on the + # way in). + + def __init__(*args, **kw): + if not args: + raise TypeError("descriptor '__init__' of 'WeakValueDictionary' " + "object needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref): + self = selfref() + if self is not None: + if self._iterating: + self._pending_removals.append(wr.key) + else: + # Atomic removal is necessary since this function + # can be called asynchronously by the GC + _atomic_removal(d, wr.key) + self._remove = remove + # A list of keys to be removed + self._pending_removals = [] + self._iterating = set() + self.data = d = {} + self.update(*args, **kw) + + def _commit_removals(self): + l = self._pending_removals + d = self.data + # We shouldn't encounter any KeyError, because this method should + # always be called *before* mutating the dict. + while l: + key = l.pop() + _remove_dead_weakref(d, key) + + def __getitem__(self, key): + if self._pending_removals: + self._commit_removals() + o = self.data[key]() + if o is None: + raise KeyError(key) + else: + return o + + def __delitem__(self, key): + if self._pending_removals: + self._commit_removals() + del self.data[key] + + def __len__(self): + if self._pending_removals: + self._commit_removals() + return len(self.data) + + def __contains__(self, key): + if self._pending_removals: + self._commit_removals() + try: + o = self.data[key]() + except KeyError: + return False + return o is not None + + def __repr__(self): + return "<%s at %#x>" % (self.__class__.__name__, id(self)) + + def __setitem__(self, key, value): + if self._pending_removals: + self._commit_removals() + self.data[key] = KeyedRef(value, self._remove, key) + + def copy(self): + if self._pending_removals: + self._commit_removals() + new = WeakValueDictionary() + for key, wr in self.data.items(): + o = wr() + if o is not None: + new[key] = o + return new + + __copy__ = copy + + def __deepcopy__(self, memo): + from copy import deepcopy + if self._pending_removals: + self._commit_removals() + new = self.__class__() + for key, wr in self.data.items(): + o = wr() + if o is not None: + new[deepcopy(key, memo)] = o + return new + + def get(self, key, default=None): + if self._pending_removals: + self._commit_removals() + try: + wr = self.data[key] + except KeyError: + return default + else: + o = wr() + if o is None: + # This should only happen + return default + else: + return o + + def items(self): + if self._pending_removals: + self._commit_removals() + with _IterationGuard(self): + for k, wr in self.data.items(): + v = wr() + if v is not None: + yield k, v + + def keys(self): + if self._pending_removals: + self._commit_removals() + with _IterationGuard(self): + for k, wr in self.data.items(): + if wr() is not None: + yield k + + __iter__ = keys + + def itervaluerefs(self): + """Return an iterator that yields the weak references to the values. + + The references are not guaranteed to be 'live' at the time + they are used, so the result of calling the references needs + to be checked before being used. This can be used to avoid + creating references that will cause the garbage collector to + keep the values around longer than needed. + + """ + if self._pending_removals: + self._commit_removals() + with _IterationGuard(self): + yield from self.data.values() + + def values(self): + if self._pending_removals: + self._commit_removals() + with _IterationGuard(self): + for wr in self.data.values(): + obj = wr() + if obj is not None: + yield obj + + def popitem(self): + if self._pending_removals: + self._commit_removals() + while True: + key, wr = self.data.popitem() + o = wr() + if o is not None: + return key, o + + def pop(self, key, *args): + if self._pending_removals: + self._commit_removals() + try: + o = self.data.pop(key)() + except KeyError: + o = None + if o is None: + if args: + return args[0] + else: + raise KeyError(key) + else: + return o + + def setdefault(self, key, default=None): + try: + o = self.data[key]() + except KeyError: + o = None + if o is None: + if self._pending_removals: + self._commit_removals() + self.data[key] = KeyedRef(default, self._remove, key) + return default + else: + return o + + def update(*args, **kwargs): + if not args: + raise TypeError("descriptor 'update' of 'WeakValueDictionary' " + "object needs an argument") + self, *args = args + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + dict = args[0] if args else None + if self._pending_removals: + self._commit_removals() + d = self.data + if dict is not None: + if not hasattr(dict, "items"): + dict = type({})(dict) + for key, o in dict.items(): + d[key] = KeyedRef(o, self._remove, key) + if len(kwargs): + self.update(kwargs) + + def valuerefs(self): + """Return a list of weak references to the values. + + The references are not guaranteed to be 'live' at the time + they are used, so the result of calling the references needs + to be checked before being used. This can be used to avoid + creating references that will cause the garbage collector to + keep the values around longer than needed. + + """ + if self._pending_removals: + self._commit_removals() + return list(self.data.values()) + + +class KeyedRef(ref): + """Specialized reference that includes a key corresponding to the value. + + This is used in the WeakValueDictionary to avoid having to create + a function object for each key stored in the mapping. A shared + callback object can use the 'key' attribute of a KeyedRef instead + of getting a reference to the key from an enclosing scope. + + """ + + __slots__ = "key", + + def __new__(type, ob, callback, key): + self = ref.__new__(type, ob, callback) + self.key = key + return self + + def __init__(self, ob, callback, key): + super().__init__(ob, callback) + + +class WeakKeyDictionary(_collections_abc.MutableMapping): + """ Mapping class that references keys weakly. + + Entries in the dictionary will be discarded when there is no + longer a strong reference to the key. This can be used to + associate additional data with an object owned by other parts of + an application without adding attributes to those objects. This + can be especially useful with objects that override attribute + accesses. + """ + + def __init__(self, dict=None): + self.data = {} + def remove(k, selfref=ref(self)): + self = selfref() + if self is not None: + if self._iterating: + self._pending_removals.append(k) + else: + del self.data[k] + self._remove = remove + # A list of dead weakrefs (keys to be removed) + self._pending_removals = [] + self._iterating = set() + self._dirty_len = False + if dict is not None: + self.update(dict) + + def _commit_removals(self): + # NOTE: We don't need to call this method before mutating the dict, + # because a dead weakref never compares equal to a live weakref, + # even if they happened to refer to equal objects. + # However, it means keys may already have been removed. + l = self._pending_removals + d = self.data + while l: + try: + del d[l.pop()] + except KeyError: + pass + + def _scrub_removals(self): + d = self.data + self._pending_removals = [k for k in self._pending_removals if k in d] + self._dirty_len = False + + def __delitem__(self, key): + self._dirty_len = True + del self.data[ref(key)] + + def __getitem__(self, key): + return self.data[ref(key)] + + def __len__(self): + if self._dirty_len and self._pending_removals: + # self._pending_removals may still contain keys which were + # explicitly removed, we have to scrub them (see issue #21173). + self._scrub_removals() + return len(self.data) - len(self._pending_removals) + + def __repr__(self): + return "<%s at %#x>" % (self.__class__.__name__, id(self)) + + def __setitem__(self, key, value): + self.data[ref(key, self._remove)] = value + + def copy(self): + new = WeakKeyDictionary() + for key, value in self.data.items(): + o = key() + if o is not None: + new[o] = value + return new + + __copy__ = copy + + def __deepcopy__(self, memo): + from copy import deepcopy + new = self.__class__() + for key, value in self.data.items(): + o = key() + if o is not None: + new[o] = deepcopy(value, memo) + return new + + def get(self, key, default=None): + return self.data.get(ref(key),default) + + def __contains__(self, key): + try: + wr = ref(key) + except TypeError: + return False + return wr in self.data + + def items(self): + with _IterationGuard(self): + for wr, value in self.data.items(): + key = wr() + if key is not None: + yield key, value + + def keys(self): + with _IterationGuard(self): + for wr in self.data: + obj = wr() + if obj is not None: + yield obj + + __iter__ = keys + + def values(self): + with _IterationGuard(self): + for wr, value in self.data.items(): + if wr() is not None: + yield value + + def keyrefs(self): + """Return a list of weak references to the keys. + + The references are not guaranteed to be 'live' at the time + they are used, so the result of calling the references needs + to be checked before being used. This can be used to avoid + creating references that will cause the garbage collector to + keep the keys around longer than needed. + + """ + return list(self.data) + + def popitem(self): + self._dirty_len = True + while True: + key, value = self.data.popitem() + o = key() + if o is not None: + return o, value + + def pop(self, key, *args): + self._dirty_len = True + return self.data.pop(ref(key), *args) + + def setdefault(self, key, default=None): + return self.data.setdefault(ref(key, self._remove),default) + + def update(self, dict=None, **kwargs): + d = self.data + if dict is not None: + if not hasattr(dict, "items"): + dict = type({})(dict) + for key, value in dict.items(): + d[ref(key, self._remove)] = value + if len(kwargs): + self.update(kwargs) + + +class finalize: + """Class for finalization of weakrefable objects + + finalize(obj, func, *args, **kwargs) returns a callable finalizer + object which will be called when obj is garbage collected. The + first time the finalizer is called it evaluates func(*arg, **kwargs) + and returns the result. After this the finalizer is dead, and + calling it just returns None. + + When the program exits any remaining finalizers for which the + atexit attribute is true will be run in reverse order of creation. + By default atexit is true. + """ + + # Finalizer objects don't have any state of their own. They are + # just used as keys to lookup _Info objects in the registry. This + # ensures that they cannot be part of a ref-cycle. + + __slots__ = () + _registry = {} + _shutdown = False + _index_iter = itertools.count() + _dirty = False + _registered_with_atexit = False + + class _Info: + __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index") + + def __init__(self, obj, func, *args, **kwargs): + if not self._registered_with_atexit: + # We may register the exit function more than once because + # of a thread race, but that is harmless + import atexit + atexit.register(self._exitfunc) + finalize._registered_with_atexit = True + info = self._Info() + info.weakref = ref(obj, self) + info.func = func + info.args = args + info.kwargs = kwargs or None + info.atexit = True + info.index = next(self._index_iter) + self._registry[self] = info + finalize._dirty = True + + def __call__(self, _=None): + """If alive then mark as dead and return func(*args, **kwargs); + otherwise return None""" + info = self._registry.pop(self, None) + if info and not self._shutdown: + return info.func(*info.args, **(info.kwargs or {})) + + def detach(self): + """If alive then mark as dead and return (obj, func, args, kwargs); + otherwise return None""" + info = self._registry.get(self) + obj = info and info.weakref() + if obj is not None and self._registry.pop(self, None): + return (obj, info.func, info.args, info.kwargs or {}) + + def peek(self): + """If alive then return (obj, func, args, kwargs); + otherwise return None""" + info = self._registry.get(self) + obj = info and info.weakref() + if obj is not None: + return (obj, info.func, info.args, info.kwargs or {}) + + @property + def alive(self): + """Whether finalizer is alive""" + return self in self._registry + + @property + def atexit(self): + """Whether finalizer should be called at exit""" + info = self._registry.get(self) + return bool(info) and info.atexit + + @atexit.setter + def atexit(self, value): + info = self._registry.get(self) + if info: + info.atexit = bool(value) + + def __repr__(self): + info = self._registry.get(self) + obj = info and info.weakref() + if obj is None: + return '<%s object at %#x; dead>' % (type(self).__name__, id(self)) + else: + return '<%s object at %#x; for %r at %#x>' % \ + (type(self).__name__, id(self), type(obj).__name__, id(obj)) + + @classmethod + def _select_for_exit(cls): + # Return live finalizers marked for exit, oldest first + L = [(f,i) for (f,i) in cls._registry.items() if i.atexit] + L.sort(key=lambda item:item[1].index) + return [f for (f,i) in L] + + @classmethod + def _exitfunc(cls): + # At shutdown invoke finalizers for which atexit is true. + # This is called once all other non-daemonic threads have been + # joined. + reenable_gc = False + try: + if cls._registry: + import gc + if gc.isenabled(): + reenable_gc = True + gc.disable() + pending = None + while True: + if pending is None or finalize._dirty: + pending = cls._select_for_exit() + finalize._dirty = False + if not pending: + break + f = pending.pop() + try: + # gc is disabled, so (assuming no daemonic + # threads) the following is the only line in + # this function which might trigger creation + # of a new finalizer + f() + except Exception: + sys.excepthook(*sys.exc_info()) + assert f not in cls._registry + finally: + # prevent any more finalizers from executing during shutdown + finalize._shutdown = True + if reenable_gc: + gc.enable() diff --git a/winvenv/Scripts/activate b/winvenv/Scripts/activate new file mode 100644 index 0000000..053d4e4 --- /dev/null +++ b/winvenv/Scripts/activate @@ -0,0 +1,78 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_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-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u 'C:\Users\lestebanez\Downloads\D3Edit-master\winvenv'; else echo '/C/Users/lestebanez/Downloads/D3Edit-master/winvenv'; fi;)" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/Scripts:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="$PS1" + if [ "x" != x ] ; then + PS1="$PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc + +pydoc () { + python -m pydoc "$@" +} + +# 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-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi diff --git a/winvenv/Scripts/activate.bat b/winvenv/Scripts/activate.bat new file mode 100644 index 0000000..54c23b7 --- /dev/null +++ b/winvenv/Scripts/activate.bat @@ -0,0 +1,30 @@ +@echo off +set "VIRTUAL_ENV=C:\Users\lestebanez\Downloads\D3Edit-master\winvenv" + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) else ( + if not defined PROMPT ( + set "PROMPT=$P$G" + ) + set "_OLD_VIRTUAL_PROMPT=%PROMPT%" +) +set "PROMPT=(winvenv) %PROMPT%" + +REM Don't use () to avoid problems with them in %PATH% +if defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME + set "_OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%" +:ENDIFVHOME + +set PYTHONHOME= + +REM if defined _OLD_VIRTUAL_PATH ( +if not defined _OLD_VIRTUAL_PATH goto ENDIFVPATH1 + set "PATH=%_OLD_VIRTUAL_PATH%" +:ENDIFVPATH1 +REM ) else ( +if defined _OLD_VIRTUAL_PATH goto ENDIFVPATH2 + set "_OLD_VIRTUAL_PATH=%PATH%" +:ENDIFVPATH2 + +set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" diff --git a/winvenv/Scripts/activate.ps1 b/winvenv/Scripts/activate.ps1 new file mode 100644 index 0000000..24730f8 --- /dev/null +++ b/winvenv/Scripts/activate.ps1 @@ -0,0 +1,150 @@ +# This file must be dot sourced from PoSh; you cannot run it +# directly. Do this: . ./activate.ps1 + +# FIXME: clean up unused vars. +$script:THIS_PATH = $myinvocation.mycommand.path +$script:BASE_DIR = split-path (resolve-path "$THIS_PATH/..") -Parent +$script:DIR_NAME = split-path $BASE_DIR -Leaf + +function global:deactivate ( [switch] $NonDestructive ){ + + if ( test-path variable:_OLD_VIRTUAL_PATH ) { + $env:PATH = $variable:_OLD_VIRTUAL_PATH + remove-variable "_OLD_VIRTUAL_PATH" -scope global + } + + if ( test-path function:_old_virtual_prompt ) { + $function:prompt = $function:_old_virtual_prompt + remove-item function:\_old_virtual_prompt + } + + if ($env:VIRTUAL_ENV) { + $old_env = split-path $env:VIRTUAL_ENV -leaf + remove-item env:VIRTUAL_ENV -erroraction silentlycontinue + } + + if ( !$NonDestructive ) { + # Self destruct! + remove-item function:deactivate + } +} + +# unset irrelevant variables +deactivate -nondestructive + +$VIRTUAL_ENV = $BASE_DIR +$env:VIRTUAL_ENV = $VIRTUAL_ENV + +$global:_OLD_VIRTUAL_PATH = $env:PATH +$env:PATH = "$env:VIRTUAL_ENV/Scripts;" + $env:PATH +if (! $env:VIRTUAL_ENV_DISABLE_PROMPT) { + function global:_old_virtual_prompt { "" } + $function:_old_virtual_prompt = $function:prompt + function global:prompt { + # Add a prefix to the current prompt, but don't discard it. + write-host "($(split-path $env:VIRTUAL_ENV -leaf)) " -nonewline + & $function:_old_virtual_prompt + } +} + +# SIG # Begin signature block +# MIISeAYJKoZIhvcNAQcCoIISaTCCEmUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB +# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR +# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUS5reBwSg3zOUwhXf2jPChZzf +# yPmggg6tMIIGcDCCBFigAwIBAgIBJDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQG +# EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp +# Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy +# dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjIwMTQ2WhcNMTcxMDI0MjIw +# MTQ2WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp +# BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV +# BAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUgT2JqZWN0 +# IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyiOLIjUemqAbPJ1J +# 0D8MlzgWKbr4fYlbRVjvhHDtfhFN6RQxq0PjTQxRgWzwFQNKJCdU5ftKoM5N4YSj +# Id6ZNavcSa6/McVnhDAQm+8H3HWoD030NVOxbjgD/Ih3HaV3/z9159nnvyxQEckR +# ZfpJB2Kfk6aHqW3JnSvRe+XVZSufDVCe/vtxGSEwKCaNrsLc9pboUoYIC3oyzWoU +# TZ65+c0H4paR8c8eK/mC914mBo6N0dQ512/bkSdaeY9YaQpGtW/h/W/FkbQRT3sC +# pttLVlIjnkuY4r9+zvqhToPjxcfDYEf+XD8VGkAqle8Aa8hQ+M1qGdQjAye8OzbV +# uUOw7wIDAQABo4IB6TCCAeUwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +# AQYwHQYDVR0OBBYEFNBOD0CZbLhLGW87KLjg44gHNKq3MB8GA1UdIwQYMBaAFE4L +# 7xqkQFulF2mHMMo0aEPQQa7yMD0GCCsGAQUFBwEBBDEwLzAtBggrBgEFBQcwAoYh +# aHR0cDovL3d3dy5zdGFydHNzbC5jb20vc2ZzY2EuY3J0MFsGA1UdHwRUMFIwJ6Al +# oCOGIWh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3Nmc2NhLmNybDAnoCWgI4YhaHR0 +# cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMIGABgNVHSAEeTB3MHUGCysG +# AQQBgbU3AQIBMGYwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +# L3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +# L2ludGVybWVkaWF0ZS5wZGYwEQYJYIZIAYb4QgEBBAQDAgABMFAGCWCGSAGG+EIB +# DQRDFkFTdGFydENvbSBDbGFzcyAyIFByaW1hcnkgSW50ZXJtZWRpYXRlIE9iamVj +# dCBTaWduaW5nIENlcnRpZmljYXRlczANBgkqhkiG9w0BAQUFAAOCAgEAcnMLA3Va +# N4OIE9l4QT5OEtZy5PByBit3oHiqQpgVEQo7DHRsjXD5H/IyTivpMikaaeRxIv95 +# baRd4hoUcMwDj4JIjC3WA9FoNFV31SMljEZa66G8RQECdMSSufgfDYu1XQ+cUKxh +# D3EtLGGcFGjjML7EQv2Iol741rEsycXwIXcryxeiMbU2TPi7X3elbwQMc4JFlJ4B +# y9FhBzuZB1DV2sN2irGVbC3G/1+S2doPDjL1CaElwRa/T0qkq2vvPxUgryAoCppU +# FKViw5yoGYC+z1GaesWWiP1eFKAL0wI7IgSvLzU3y1Vp7vsYaxOVBqZtebFTWRHt +# XjCsFrrQBngt0d33QbQRI5mwgzEp7XJ9xu5d6RVWM4TPRUsd+DDZpBHm9mszvi9g +# VFb2ZG7qRRXCSqys4+u/NLBPbXi/m/lU00cODQTlC/euwjk9HQtRrXQ/zqsBJS6U +# J+eLGw1qOfj+HVBl/ZQpfoLk7IoWlRQvRL1s7oirEaqPZUIWY/grXq9r6jDKAp3L +# ZdKQpPOnnogtqlU4f7/kLjEJhrrc98mrOWmVMK/BuFRAfQ5oDUMnVmCzAzLMjKfG +# cVW/iMew41yfhgKbwpfzm3LBr1Zv+pEBgcgW6onRLSAn3XHM0eNtz+AkxH6rRf6B +# 2mYhLEEGLapH8R1AMAo4BbVFOZR5kXcMCwowggg1MIIHHaADAgECAgIEuDANBgkq +# hkiG9w0BAQUFADCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0 +# ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcx +# ODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUg +# T2JqZWN0IENBMB4XDTExMTIwMzE1MzQxOVoXDTEzMTIwMzE0NTgwN1owgYwxIDAe +# BgNVBA0TFzU4MTc5Ni1HaDd4Zkp4a3hRU0lPNEUwMQswCQYDVQQGEwJERTEPMA0G +# A1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xFjAUBgNVBAMTDUphbm5pcyBM +# ZWlkZWwxITAfBgkqhkiG9w0BCQEWEmphbm5pc0BsZWlkZWwuaW5mbzCCAiIwDQYJ +# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMcPeABYdN7nPq/AkZ/EkyUBGx/l2Yui +# Lfm8ZdLG0ulMb/kQL3fRY7sUjYPyn9S6PhqqlFnNoGHJvbbReCdUC9SIQYmOEjEA +# raHfb7MZU10NjO4U2DdGucj2zuO5tYxKizizOJF0e4yRQZVxpUGdvkW/+GLjCNK5 +# L7mIv3Z1dagxDKHYZT74HXiS4VFUwHF1k36CwfM2vsetdm46bdgSwV+BCMmZICYT +# IJAS9UQHD7kP4rik3bFWjUx08NtYYFAVOd/HwBnemUmJe4j3IhZHr0k1+eDG8hDH +# KVvPgLJIoEjC4iMFk5GWsg5z2ngk0LLu3JZMtckHsnnmBPHQK8a3opUNd8hdMNJx +# gOwKjQt2JZSGUdIEFCKVDqj0FmdnDMPfwy+FNRtpBMl1sz78dUFhSrnM0D8NXrqa +# 4rG+2FoOXlmm1rb6AFtpjAKksHRpYcPk2DPGWp/1sWB+dUQkS3gOmwFzyqeTuXpT +# 0juqd3iAxOGx1VRFQ1VHLLf3AzV4wljBau26I+tu7iXxesVucSdsdQu293jwc2kN +# xK2JyHCoZH+RyytrwS0qw8t7rMOukU9gwP8mn3X6mgWlVUODMcHTULjSiCEtvyZ/ +# aafcwjUbt4ReEcnmuZtWIha86MTCX7U7e+cnpWG4sIHPnvVTaz9rm8RyBkIxtFCB +# nQ3FnoQgyxeJAgMBAAGjggOdMIIDmTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIH +# gDAuBgNVHSUBAf8EJDAiBggrBgEFBQcDAwYKKwYBBAGCNwIBFQYKKwYBBAGCNwoD +# DTAdBgNVHQ4EFgQUWyCgrIWo8Ifvvm1/YTQIeMU9nc8wHwYDVR0jBBgwFoAU0E4P +# QJlsuEsZbzsouODjiAc0qrcwggIhBgNVHSAEggIYMIICFDCCAhAGCysGAQQBgbU3 +# AQICMIIB/zAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9s +# aWN5LnBkZjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50 +# ZXJtZWRpYXRlLnBkZjCB9wYIKwYBBQUHAgIwgeowJxYgU3RhcnRDb20gQ2VydGlm +# aWNhdGlvbiBBdXRob3JpdHkwAwIBARqBvlRoaXMgY2VydGlmaWNhdGUgd2FzIGlz +# c3VlZCBhY2NvcmRpbmcgdG8gdGhlIENsYXNzIDIgVmFsaWRhdGlvbiByZXF1aXJl +# bWVudHMgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeSwgcmVsaWFuY2Ugb25seSBm +# b3IgdGhlIGludGVuZGVkIHB1cnBvc2UgaW4gY29tcGxpYW5jZSBvZiB0aGUgcmVs +# eWluZyBwYXJ0eSBvYmxpZ2F0aW9ucy4wgZwGCCsGAQUFBwICMIGPMCcWIFN0YXJ0 +# Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MAMCAQIaZExpYWJpbGl0eSBhbmQg +# d2FycmFudGllcyBhcmUgbGltaXRlZCEgU2VlIHNlY3Rpb24gIkxlZ2FsIGFuZCBM +# aW1pdGF0aW9ucyIgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeS4wNgYDVR0fBC8w +# LTAroCmgJ4YlaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0YzItY3JsLmNybDCB +# iQYIKwYBBQUHAQEEfTB7MDcGCCsGAQUFBzABhitodHRwOi8vb2NzcC5zdGFydHNz +# bC5jb20vc3ViL2NsYXNzMi9jb2RlL2NhMEAGCCsGAQUFBzAChjRodHRwOi8vYWlh +# LnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3MyLmNvZGUuY2EuY3J0MCMGA1Ud +# EgQcMBqGGGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tLzANBgkqhkiG9w0BAQUFAAOC +# AQEAhrzEV6zwoEtKjnFRhCsjwiPykVpo5Eiye77Ve801rQDiRKgSCCiW6g3HqedL +# OtaSs65Sj2pm3Viea4KR0TECLcbCTgsdaHqw2x1yXwWBQWZEaV6EB05lIwfr94P1 +# SFpV43zkuc+bbmA3+CRK45LOcCNH5Tqq7VGTCAK5iM7tvHwFlbQRl+I6VEL2mjpF +# NsuRjDOVrv/9qw/a22YJ9R7Y1D0vUSs3IqZx2KMUaYDP7H2mSRxJO2nADQZBtriF +# gTyfD3lYV12MlIi5CQwe3QC6DrrfSMP33i5Wa/OFJiQ27WPxmScYVhiqozpImFT4 +# PU9goiBv9RKXdgTmZE1PN0NQ5jGCAzUwggMxAgEBMIGTMIGMMQswCQYDVQQGEwJJ +# TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 +# YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg +# MiBQcmltYXJ5IEludGVybWVkaWF0ZSBPYmplY3QgQ0ECAgS4MAkGBSsOAwIaBQCg +# eDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEE +# AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJ +# BDEWBBRVGw0FDSiaIi38dWteRUAg/9Pr6DANBgkqhkiG9w0BAQEFAASCAgCInvOZ +# FdaNFzbf6trmFDZKMojyx3UjKMCqNjHVBbuKY0qXwFC/ElYDV1ShJ2CBZbdurydO +# OQ6cIQ0KREOCwmX/xB49IlLHHUxNhEkVv7HGU3EKAFf9IBt9Yr7jikiR9cjIsfHK +# 4cjkoKJL7g28yEpLLkHt1eo37f1Ga9lDWEa5Zq3U5yX+IwXhrUBm1h8Xr033FhTR +# VEpuSz6LHtbrL/zgJnCzJ2ahjtJoYevdcWiNXffosJHFaSfYDDbiNsPRDH/1avmb +# 5j/7BhP8BcBaR6Fp8tFbNGIcWHHGcjqLMnTc4w13b7b4pDhypqElBa4+lCmwdvv9 +# GydYtRgPz8GHeoBoKj30YBlMzRIfFYaIFGIC4Ai3UEXkuH9TxYohVbGm/W0Kl4Lb +# RJ1FwiVcLcTOJdgNId2vQvKc+jtNrjcg5SP9h2v/C4aTx8tyc6tE3TOPh2f9b8DL +# S+SbVArJpuJqrPTxDDoO1QNjTgLcdVYeZDE+r/NjaGZ6cMSd8db3EaG3ijD/0bud +# SItbm/OlNVbQOFRR76D+ZNgPcU5iNZ3bmvQQIg6aSB9MHUpIE/SeCkNl9YeVk1/1 +# GFULgNMRmIYP4KLvu9ylh5Gu3hvD5VNhH6+FlXANwFy07uXks5uF8mfZVxVCnodG +# xkNCx+6PsrA5Z7WP4pXcmYnMn97npP/Q9EHJWw== +# SIG # End signature block diff --git a/winvenv/Scripts/activate_this.py b/winvenv/Scripts/activate_this.py new file mode 100644 index 0000000..444d3fd --- /dev/null +++ b/winvenv/Scripts/activate_this.py @@ -0,0 +1,36 @@ +"""By using execfile(this_file, dict(__file__=this_file)) you will +activate this virtualenv environment. + +This can be used when you must use an existing Python interpreter, not +the virtualenv bin/python +""" + +try: + __file__ +except NameError: + raise AssertionError( + "You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))" + ) +import os +import site +import sys + +old_os_path = os.environ.get("PATH", "") +os.environ["PATH"] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path +base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if sys.platform == "win32": + site_packages = os.path.join(base, "Lib", "site-packages") +else: + site_packages = os.path.join(base, "lib", "python%s" % sys.version[:3], "site-packages") +prev_sys_path = list(sys.path) + +site.addsitedir(site_packages) +sys.real_prefix = sys.prefix +sys.prefix = base +# Move the added items to the front of the path: +new_sys_path = [] +for item in list(sys.path): + if item not in prev_sys_path: + new_sys_path.append(item) + sys.path.remove(item) +sys.path[:0] = new_sys_path diff --git a/winvenv/Scripts/deactivate.bat b/winvenv/Scripts/deactivate.bat new file mode 100644 index 0000000..5ad81d4 --- /dev/null +++ b/winvenv/Scripts/deactivate.bat @@ -0,0 +1,20 @@ +@echo off + +set VIRTUAL_ENV= + +REM Don't use () to avoid problems with them in %PATH% +if not defined _OLD_VIRTUAL_PROMPT goto ENDIFVPROMPT + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" + set _OLD_VIRTUAL_PROMPT= +:ENDIFVPROMPT + +if not defined _OLD_VIRTUAL_PYTHONHOME goto ENDIFVHOME + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +:ENDIFVHOME + +if not defined _OLD_VIRTUAL_PATH goto ENDIFVPATH + set "PATH=%_OLD_VIRTUAL_PATH%" + set _OLD_VIRTUAL_PATH= +:ENDIFVPATH + diff --git a/winvenv/Scripts/easy_install-3.7.exe b/winvenv/Scripts/easy_install-3.7.exe new file mode 100644 index 0000000000000000000000000000000000000000..f3c631b86b93fcd806c7a014d3c68e560c59e2f4 GIT binary patch literal 102809 zcmeEvi+>c=+5c`fOO{-i<+2dK$O?<1QH+h3#3i}|yE0og5*0L6Kr|S!pwciSs33`x z)NGF1(!RE}t*y4z)>^H#RSBrDA&?6f33v;j62;3|2Q{E3;X1$Xb7nV*Xy4EK2mJVG zX69U<^PJ~AxAUB{r8lm%IczptI{r6Jo2?N~`WFy?|Mx%L$R0Lf!!X;6LwBClXpihX zYtG_3mV1{~-FLyd@)%HZ5-8PM0*4k}Pmf=}#w{-!O z{(s$e+fo4F{>o-Mqd)Qg@Y0R8El|I=@Kp7-l`3);yoWyo5RILPV9-CW&9-oA)uLO} zTWq#RFGU90v=!n15Apw?e*uuoRI8Y+79X|(06YrMad-~;7qHplQ>+zX>^uXsX3&85)|hA+a$Y9Dcqt&YkdVsiLh-O2*2UjjND*sx~aq>z5*p0 z^m+MHvu!s1k%Tg_Akt#WLM7&jpFm>87@KW9&4=k(d%$Mf(Y#}a5}oIBDN)tuzCqCs zd71N^LiEFqDeQ3J{s?Q2#HOE+Hg<$rJAZ08b=#)Y#nn9KG=D(lUYGs$uoT=IHk-ov zC>$(4VRR@=^%W_sSz+_gzrMwLbF=8jP5tC5(N#Y0TzQT>SH51pL1Bl`Zy>@Fk(kpD zAOY(~)6sOSv>;UYQ6zd>0UwoRv&n2nT^xB{6pGv6pM&zt9*8uy(2fK10P|wlb6RF&}&Ar*C1;S zvv+_szTQLSU#CXzLvI)z#o5r2L`cTc6G?sy0e*sL;SW{zshlUwI$5wA=eyg`?^mcV@UcOoCf3Iqsw9Yvm z*_Cp!L(MGBKY+yLM+`?PJ1B7cCAeQCHqRFbvn^qEQ&E^L$Lsw{m>raFmKVtL<$3c{ zv^Dp7BCLW!VB~P@hN(3B3;C~yVx+MPvSwhSf#nP2^+d~Jln!DCc^j&CuMeK|iM=A1qmK3ONf8l+mcU%OU(8$PS~2>WjH zzZK1E;|hs(eG4%Om!WCCho+}4uC*9W(Wz*M+X!mVbXo5KWqe$jv=y{naPtBh>S^mJ zps;-kJ8F8aLHmk6$<~UMND^Qp4M70X7Gc{J_6}CW6n&A;izQiyvaA!mW}BWn@UHg_ zk%I5jVk)=RQW^RS&|1e7SR# z*iv6L7zuHBFp>omfOKLcp=AKEa8F^o>G=$GBe77IynZb;z&aIRqih4li;wMst(cyd zPzaMXyk?cJjEZR)f|nR+n6a2A<0$ZU`Ek>%Deblu3~nyfjOi&v3n+S`4+CxEIVfDX zhh}gYIM`yo`f6~e9@8{|tYwSQf$6zXRG1rAQ2ckaDr24lR^^Ukrn&wb6gEAVScTfC zkY*LyXBGMf75Z8fa$AMKo7#ApRp>3N&`(iFiRJtai5m!gt)XXac$%Ki_gPe49sw>D z!pO1^5ogdBP%vdhK=dMCfenAASfu+-VLL$gQX{5kHfjUhwdf?mTG8v7=qCv30g=w} zl>@E8XkMmbN6{b^1?4U@J<;TAxxNh}8=v|jS}!v_ldLuuS%B|6YMQ8p^ya-_=KVCd zlqMdG_6Fjy#MBk`86deHwXg>GDkWzl7esrQbS!QqX z+eXlQYhzJ&9Mz4@a+w}ZcocQC9ZKDPH7o3RPhqDLyQr<0$Bu$>Bk2*ubs-x8{81!!$@zY} z?KP4?h3#SXc93l~J@=x^%Hom{$YC8?777i;tD=9FroY0a&u%N@ zZ}+BVq`;byq%8apY(a_XmaINOEXm)wd`xw5jw)3bXR4Ws*`)Z}s=hEBU}-d45Wq1{ zI!zcR^GVbW)}JGITK@3}Yi4h+Pn@*bf@~Lr3?vN}t?7CHZ9%L;%Q)5p3|0tAxE+-- zTZ>keDKRiU5Y-}InM$TjkBy8A0=yi4ZfDD(KReZ8v`|n8-OHsMWTy*0Y2nJ3TN*U)TBRf8udTX z3Q0BM3AHZFPR7d8DvvymRjl;xj>Ke272hZEt(ff*N0XHj z79|F!pg=e_&y|50;S({L=%h6TM4v4EY76@2lhIuSh%SnND-}dyIRqzW0g4R!~k!!bU!a2eHBe1t{}|SeK>Yh6+EI*;b{lUHVlVQ!$2rF#-JFhPpO>KVA#ti5k3% zGJ8ZB^<8{mrq8p!Ugzm&01og&&`=p^3_1K6(MB%n8JkdYsy31TroUMr$YPEWDC%c; zVQQ`|j2jc6R)?^lE!}W8>VgdsPFtMx+DbeC5<`W80*%9B0KiA!I^ynO2EMvYVS6zS z&BOE2*DExFXf9uOCIoFW^qN74_{180K6=|fIy4*0#O&46W?wFBW{s% zQE-p8hR?qMRiZQ83R@eep+-k4tiDma&2lMz&oyV+ZR%)N-G-z(=SUd(nu`bWsU%p2 zGwlp8rQ#Vbb-co6xLLg@mU9TH+E5+_%S77%VTQX$w2-Ea(nXoHmKnKra8Y;KSJE2$ zU>LubKV!NA;ICl@xkVP1%(j%0a=VQH#q5pacjomI;4x5EBXpNFiGPUfJ?aOfD`CEO z^JAF92#CTPDy|r%U8&^vO6$(JqEbIDS7qYwjVsbC^=2<|7`;y<^@*goml%&??ooERE{=ON~y6lnAQN*Z@icvLrA%#X%>c>RdF_E^}8`d|ch0QjCxt(C% zrf!keZI;%x=eL1ysYxhvd@e19l)emUnzDmwIq65cR;;qr|GIWX3LOQxzi=)H1vBO4 zMj;dykf)8;T!c51-dYJ?Eazbqg3d?FVs8hfbQ5Pdzu1`%XN)?G7WPrp#;9|QfAIS- z&Q{@i;dl4HDy+pA!QVhBeq(3z)O0%x-&ytVQ&g z(P#rtHk|%uDblP|v~3`{9(8(9gxf9yU{Pn{N*YgG^Tol8Mb|sOEI^rL$QP&M`7a=GT~yL*(ei=DUL8}i^M#k61xpd zN@?nI>K{x9v-Hi%lJ@cl8)Xmc$4qFD`ms~0vlQ!iNNXDA!wj2oYCUYWYpIxvKU^e3}crk8L%*n%{=l1up zPd_?p^+>(R%{QK2?A7!wHc|Lf%=sb_v6 zH3e>MOUwru)x{sUo$Sl$T}tm^Mej?iDxU=g>Q-uwlDA>SMM@0L5`WW*Or^1#j6|sF zir&@D(`h*QU8L_7K$BF@ZOz!R0}Egze;Xu5q8SL5T5a#aUkirnHbCg7P*8L8=f;W00>E9VG-#&@PYB{62SyUfLFlpL2Th?(=h%{Bb(obc9KX@Vzawzim5Nn z$ydXkAkC>1Q?!#GC$*Si1{r3MVFnpyFm{`pTrluT2;UxgUjopI$s=Kjj}HC{S|NXj z*HXdwr_iygSHYtFK1L4C4Mu~7op=@_f`3x@CG|r^a6L{5M`v`0^$HH&7a(M8DI%T( zd)W)WPrr{3S_(P%*kL6aA^Ue*DLYz9O4t!4I>)z+=yhBv$i-7y*Q1@o7ejqX3W0Cn zh_Tq-N?MF5?-Ds(6!xmG8gorEGz{~sx0&JIuOt4pd(Kt#Q>N;M{Z+V!d|p19Pxd+$ z{L7$%eJg$yhPPFE{y^`{+-#7X!VGmtkj?fPL*Oxjl@kQG3t{C-wdKf8mXbFB4Qtc| zk%|?rP+gB&Ce@S4ANGF{l%{_ZVy{R1?b1V^0kQ~#VhqCyW9BdZ5Y3&t!X>ko2>AD6 zC7&yHWRvp)e-=g@-AaC2;!mO)@xsm8XuW(=#gxO)i zhmJ+q2Sh9jiCAtTVMw#1O;kvZWJcI#ID#*uzRwnYgN$taKO?bnFQmow0nCcEf;J=U z^-}2l3?9)P{Av(?Qr*6RTtTcA9<4Yv9w12zmI$*i!WKcD5z4plzrmJ)Dpm^l#x^VP z)$jn}&?0|p9Ay}T;)+BA7>DA$j#dN7Fmk!|p!t-|k<0G`fJti4z$?f&aR7i*nUu{D zi7kTD^elqEXJ&3ds{1Jl(2QM*38fi3PwzXWPF5=5-hvoA>V%7Q*ClqF{^0~=$)57C zV^kZ&;hm!)p@-vT5ne!;DD(^p^-M2XqfMq(#!)LCC<;*alhT?bb=Z*|?~#kD)sg&l zxP+3h-h@~EbrTErJc48%AYq-Qj2K1I!L^GQf&!uZuy=rcDGXzWN**B=)&g8jfgfW5 zOpYCuz@k+EfjFgg$dJ}GN$a*xB5jXM8=-rK3ip??4j4?JBW(;n34cs-Kn-{Wllujs z7Ru&Fq~=``W-fYOV7vvjyE0TfR?Q8OT@>`kp~ykSgySr&GK97c!PXlG{yAVc?F1T) z{L|~%zptJq>Y;_P+Af29RAZ?ftmJSsGb{zk^qB&>`>#G9;p7trU@kvzU`Xr0!-$@4 z1QL1XRrt8yMRIp_x?bUe*#_$zo>x2Hbsf!9U3}#pc3p1oW*3TUnfc3ItR*o4@5~QU zS%ZBc_GSJOch6>rI*r6Gpy^lX;zTGtL6@r<1Oz+D$gD2P)Y8nY3UoQYqv|l|WIWrN zfI4ie-LvvAuLWop;uAMw>GW*2OSR7yz)F{&UP>jOgqD>Me+%Cn@mI9(x0MS%+xOYab%?oxg14PQ+ zCf~$c*vbS)tbZH)M`+9bz7@lJX5_lmEGi5&f%T~lcE1lg+iL81{Sdv2p3~Jdvo*gr z7Q6&YX~08APCM`mVijI%BP1yg!3{vc?P(nf$r=5PQ@cObyS^;^Jc=@U zpB<*{GvIyfBt#E7nhN73$ZpCF)$YGHQ`Qfj2u5$pHO9$3&31JZ{<_p*vb5n~W>rS( z3?CU5ROzJ|RH;=+m*_PBzRwIuzuFoLfsYDP1#TbWq5(pPuve^o34l9*5Seunz(>D@ zl?ph%l33}^v9NLhtj|pSxLtMX$J4a;xErqhwb)Z5-Dwy9f)Le7Z)=fGO47XV>3fik zr(P$|wEhD254OXeae>MQ`yz#*8AyBeNgckA~`u4ZpGge_)mHM=MOEk&S`1s9&`qUxNYF)-I zg*o7&T$z>7ql( zY8=I1Lvu;v_1}19AQ(v2Fng1##xD|B8ZEktM9;Ax{3YlNPAQL&#IV7!7HJcTS7MhJ z6#w7F?tnh))pvou1iu@_FBc#PS>K8#vRaL+dgNSPy`0ZGk0xR}>*N2VNd&nLk z-*3&M6U`WK6wR7K6P3xmpOXx)m}1i_a&6X16K32Xx*fEJQF#!-j^h7D=ShOS60cAr z&ITL-b%=gTuFdG?w;oQe=u5!wtQGw!k_-?p5$fReA$Cj~OK&9Kx$~1WMnz7^pd?e6> zDVwO5EFEdLrNMqacM|*-@VD6bCU44v;mpJ5Vt5>^qH?n6sfj26j&0+Q^cUTSs{E;& zFlqc|w1jn$xgHg5JP$=okGTmbk2QL-#KBlzJ7_@iE*Orrfp z{yvg~aOd*?49GA8GuDp82y@;CcW)%>ydMvRdFJ84a<0W+zB@rUB}YD1FI8Ab4KK$Z zV+`xlSHaz=xsW^;DLeQQ{9S8JumZ#vV1h|E<1;ZDd{0T-gGE4g45l0VDfIvgNPiFD zo1U9D;e$EbfEjZ7mXp2%1!N)V%;kK2BaM`N!RWKhrpgL-1dC7~4FsV}A`1~2aC6ez z6bO}iG)nIy29c&JwvEY%@%?kGEl^|+~f*J zm*j?{%e@riGT1&0l(KtWrR*Xmr-#|SMWy+@rR;+U_AOcB=}M{Yb2JjJ_=ysZ&T2zw zOb6U!{>vo2hS;|Q_@CFB&1UpP{N2)nPopTCaf06U$MCM-pKgM5EL@dg z_Ey-@YIcz9k0S2@wPv-gV)>n2+7v}E*$k()O+6DMUXM4fVsxOxVPbn&VLMIFpOMUF zrOSl;*cS?N$ASdy2>01IN*97n3ozcvS|o<8e>63G<`L?H{u| z*Z3Hwh$GG-t!`+nL)g;RY{L;`3BsGg-uGX&e6C_*cjREY;yA!&z*6q6Dz>n;{Gw3Z z=c+U4&sQ&^7yptI>J;5?!`?4wab@f(`wMm%!%>33Y^kGFHak+FSG^=~kc!!H=p&xAK%?*!PK0oJ(5?!Z#Yk=ZFZtJ`pG z8j5MtU&pR(bDGRLtSwimwi&4~xoW=#{^8!%k6yRtUiHUv{w}F@H+E6g>bFnw1b(I8578mo|; zrro1|dP@J~guW|H+VDk&u?!7qx1td_%QPzV#2j_Do*1T1Lzm}K-(&QnL!`QKppo8I zTO4ceQuH#+D29hX%MYU#0Za!P*v^lAO0GFEo0$M(gmE=I#y=88up~s0cLs{MQDnH0k0Mu#BBbO{ zD=&&7QeCFi*)SAye+!ggaiLUqh-`bTceqn_KuyI;r2vg;Of$gY-A>L1Y-%hct!yPpjecj;Ao@=39~2bskIl04zfC4( z%p_-@zvPcauwG+_2>yy*u-&`h##Z!c-8QvSfmP8H$knyEy@6a?HRd)Fn|V_2bFXm6 zX1n=Hp8&O%7z4!KB~+1(Is#3%3Suw9@+Kh#e)X@Y4RYaiAnP4u8BXl18LQ0J#Jw2g z`f}9g51mPkv>}WQFno3niGgf5G}~2#iZm5$cmno<>1lxI!5p0l_j)T8VcAD{+DD?V zb@&eJzT-B-hX(#`<@Qls)AJSB7{Gaiim)?|lNv>;ab68xFe)-SpEI>0I5HQ2Sqj2b*0me zEleP`S3hb(&zTHu4;zllAi*L&74~A|BZP=y&<=@hEmLA4Hv;W2%@pPXHiw9sd&Nke zB1@R0J6IYyHuyeF0cpmUB?ExK9Rt+rLQ)kV*r5VYgd{#7+e=}*0wDN_Ak2S&(K@T;)E5b@WFENVG7yZaL_^isKYE!2FzYitt$3pj6w~t}UNJjvc$~BK<0cfO z?K~iiju;JIDcr$7=)z>h9`g})5TOS-v>dGYAUrPQ7ly85vCj=-Ag$$?V&{)x9YLA(bWq zU$57M?Ebd7Eaq9k;sX+~IQaqqB78N_i5L02kPH1L!U|*oEb=iUjNrLGV({><1Y-f0 zKU2*&<6%dK-giOOk(m6s-Zy;3kVaTOw&t3qASyPF#=CwLM(kDbX5~?t1)I{7df)G1 zYmz-P6bjiU#IX@0iMt5_@Vr1Tynj&sUsCy_M1FGLZ7;uJP?OUn6DOkmchr<^Mpc2rib_0|v4GzYMuT6A)NQ%6s9F2$NBMj5tgloWIH4 z7=P<>iC2T>EaMTbzWIvu{86g~1n)?}KIqlD*|j1U{rS-!HYh<;rstvm2s~;R=q3B1 z-`Z5@D7*OIF}aw)?Zj^W-Rgj?V>6zik0I6v5#6_JIVjKH@|!5JA7OPSHbNK1O57f# zy#sDcrg*6RN^G@Tj?Ef^ZRX}+bbfXuIzPSgtA8l5lHc{BbpFYP^a=G2Qm)L`wXc*| z4B-VfvDwp*UR-ad;3RV!G6W0|Aw`2cB9>i`MPGCPu-W&wqo5U~J2P zYuNcLoK7qWOllNR@d|15U7E3imR^)gUY0lO+4 zOPgp=iPbHGVkI{ed7+Vpr!y@>}E{hg}_7J=EP0 z%sgle!)Kc6t{&=@8-lKb^)-YnBcnw;ZL~WIJqH`uTAOht(dN~8z{BHmEa27q#;$Oo znb>r%kqu|r*cHRj3W)c#HlTh3(Qi~?11~1#2fX*T{TA<~2?X!W1@HADIvPCqAa<=V zI4jhi|2-36Lr^87O&)**Q%5R#V;sb5qdoOUA%$(m()Gl|_)Rc|*DCCBN~1;!6o1|< z@Dz1Ak@@&;GfNu{_T?gSfhmdXHpsrxcfm24b0RUH=tH6|bB+>Un9pt#Wzm$?!%Tt(yhWFaK=jQ7dA>W)G!E%Ywpch0o=0ScSl8_l; zwpD(Wz%DM5YR|@t?AQ@@9D)oe(2qK+5;Z1237x*yfvg&nA_t{fEPNOVyG+mDp10QD zCrF@m>19Z~FPXSiBwl?6DILUF_;1ewc|VXIU64(2gkI^V4~r5(-`Pd;d}pf{6qVc6 zDbmYD(#wk7e{_W>e;3-kEDr!xXQqc8Z-(=CXx{*^w4z+?4JCHfnd?uXfohj4?ARjm z*wyJZi6^0~lZle9j@J{2k%S464wu`w#&oa{V`Sq9dSo}IL*F)>jl=O3y(&8xt#lcV z=mHl)bKT%{>tRaSz~;nmRB_&>Ay8lI8o{z@N8zp02Nw4dPUqZ-KY6eAfbg3>On(gx z+h)gt=eZFGA{XVV7Zv@;uAVQwJY0HNw);C)j0H>hL7v>;kR5NzE<2@`I(GOw?g8$b z(u%Md5{8?j)bVaO|B&_y@K*CB4UHg$!S`i4Y@#o7)GTwCHtrQ`Xs=j9d&L^sD>Sr7 z{@Xw|7Pos=Y}I*RZ=hje3rVVsB8H_YEu8p@;hS9YjLk@oIu9b) zmd$WQo$rg6?5J}uy}X01pgFIYCh2neG3RP*7jBc*1!uV{o7thTSGY{%T;I2o=d8xM_{| z+n>4L{wx^$8I#N9Mj}U8x8!wDip#pyEQPsg{}IhWIb7K%Vloh%)t?miQcMpv18d6B zShrcd5D&Qf+ojsype+hF=?>ZY&x1MBEV`A#9aAMtGt4wP1Q78`MdZxZ;IZ_s2Dy!u|BC8zR!B6$$>m>B!L7` zJWgLvXduY<-hd>=r~rSC3dim*-)ND6b2Sw&p4qLAP?#ikC1|uxUPtBhH9$A^D`wN4 zGLuNCBWOOUWu`&|6SI&H1HiIVC(nXa!=2N*9KU)h>UJMvHB{q%QMsFe5d$ zUzZuiUlaL{#(@DNe?6(^ykQh6G%-eL@M@5r%df{;Lo-%^J4PZSrH{11@k9EE)$5KO zP&&=Y2Hb8K8`&@{=N>db27iv}$%j3y=PW`3nTt~rzX6k_a!{L6Td>$MgC67D+k|GL zHBSHr{T8>aRmP?tJcu>KC+V%FM#W=BOHD65P~mAqR3N5nX-&<55_*|VDc}HB;y=-$ zHHargcJ!4vvat`QA^Ov~h1Pmh7fDQvpT7W|f2~!c3U#eX#8?M>r^1#pJ!O9dpU!DO z3*;2|0T2LuVf|=0=V{;2Mj~Z0c)69R7P6e1sWaALdWMOz+p*L}LwD=OOq!k%l&0fc zPt<`xaPJRocLV@JT7vNxahf z;7cV^CDn!CgfEEcx&J9he&-+10fpx%VtOrinT#FAm(Z%{P0iSA#b}c9nJ~HGKqI8_T41rEXyeBmR2%WMM7xVebn6 z?+~0EavLR70;`9ZtMqcZ%Q&CS8U?G-D~oYbxEbum5bWb1Ove3KOwfE#QBB9+?{-R< zrC9SaaVFEkEv@sMTQCmO<9`yU0Di_o;9iLou}^hoG7-mk;hakGmsDN84md=P=jJ~P z9wPo)J1PFkZ^Mj}?+j;9hl!=JonLNH(susS`PAWdeoyjA_AkCg zkBRqS*X~e&qzk^oq_ATJkkbgZW*lWWQ1$s>?l4fCbXURE(8?IBPY4PTfRJYHPSu3F zZjc*fFhA5wHqw3`+Y7E8%lQx9`2$x9T5{3g|4a#&EC9eU&s4%!EXVu{DE0v$2VLEW z?>9>DeT>Ey%X7_*BfvTD^ph2_vqEw9r=PUG#y;3)WArz$-R8 z>fR*cW;riHEx>t|KhZ}wQCa~oF4Y2h%Ke$htrxj{f(|3BhoG23VG_d7)W3vU1C3Vk zpQ>8MZ$X@%Qkkd75Z>s+EIppZGo#-x2>;nls|( z>Z=j<6%8Bv58_$S-zVIyv?h$-VM<;BZ32^z;lbBo(IctRO8Pq`J&B~Xp}LP$$-<5s z@)w`l*{#m`a0S>gPAj7qTtx=oY6gG66Z^rB6Io&kmZf$*0)uuvXtMSsD#5CDkarx@ zW>1vki^4g`p_G^LtRza}9GT;f~%i`X3~Ll2O+KmHI8atqY@0@UYG z{sbtuu*YJdQtcPOLF{S={|qFq_km={K%<1cNC1K7=p|>O31rMeMvZv_5KFbhPH~ET zav!kv>L>@9Va_&qGZeN{W^eK)5Fte)N_C@95Dtf_R8U+vP#L}CT+kr)qfF2Be?%(0 zbDyH0^UwnMLntzJC$B~WSo)p;4>*yXmrvtBA{F@0RCGpI>6>=XOiK7O63|2znvmB6 zAb=MMy$ansoWE7s-KXUDAsCZij8*!5?S6zkH8|FtaUflU@a*I@(3=65j2Ql8%H389 z1fC~?a&n{FOB+Nx`PDaqF+$c1a@bqo#;DoT$FOp6qE+rTN=hErzU2>u#y;YF*q4Iv zo6X?q!{&NJmR#?uEG|@so14Wsk><3TV_yTmRUeaEDiElD(N~Bm=F)Y93b89gn>1_} zow_IVnVxCDxWXP5q(G+ri>;Q!j)=wDELnohlI6J8;9&n*JJK-)MtKVm02)!pSfA@G zeB|jRCk}u@U@)El4){{6IqOi+t+XJ?Tm+5goQ2HfSskGo<+zbxdd{QaVyqB_5JGs# zutYTlB3lwE$@_%Q8i)G(&-$*lCYgq{8jWly$9L?c5EnZ^db&Af=troS)H`zhij_;jBXy{fE6~W$Sd)mKlszIq-I&Ewg3%Mf5c@SYI^* zi%Fvj`sQ*RI_b5VfxcC>mE{DHfn8(OcdJx;F|7^SQ5CF|oNAE@?<+P)PaGvqFLiue zoGV3g{oAG3Lt+Fa=b*BHo@nV-0u*Ri%sgMZ&|9pYpatJ_ycPAlM=AcM<+2hhvjDEX z^}_0J0bP(e2;hwG0^80!zoAz2R+s;cRrSUYmiG|85g<^v|AAFueVWfy7t`aEdW+l> zvf0%e>EY6bg;}=G^khCJR!~T(_)q9t0fBx^Owp4ou*qj;4He18y*08?Cx@(1C}lY5qLBCcZ7N_mQ5*PQ4xC1^`ckR z5AVMcJ>QS>Fj@vR889;SK8NO{cliDyes^*cxDM?Qn43YsX3(E)o)&fZOfIk>wwHxLW1U4z`SDKgpDrswKx%?IhhP$ib9VA`Kkf(Nykchsy1i#2 z2}uvY2*w__0LYs~Or9MF5GQ2+2@RG1S0Mf?4rt{!#=Dza=RCn1o_0(q;A)p!iz$e@%{o{}qa)Z9HgCj2H|}1qJ0mXnaPFO`N_E z+q#H_-@)JbE-+>Nz@&W(n4*4QzLEXkXs-}3m<Pr!vurL16u>mMa-=6q@;9_AC9MSR0M_(pugS2nZR__<|lb%7f(?C|u5rs^VO z(9)ktrX=r9l5=U&_WB&t(zGjkZPnW|6Xj>KX3uB$0nu1u5(ksbQ{0#W`wJ^ zY7(1~TN}Su(z{OL&L<;7pOx#yxeD0HZi<&+Erh5dB?{YWKod^c8ze&z@B>dAoH2=u z!5aAOScX{hP73$-QVe?lKp-Z6J0FVf(eH=ox3_bAe87n_fOBzSjF2q?`-mRHVHGoW zwVl5U93ZY(M%1e{3%fiN&QgsoBNYdM+{c}Wj@PGk+0?~9WTU!zrXv((0eaolBEnvs zYbc*(cZn$~l=YK#Z3Mp*z{>tsb&}ZvH2RG3h(psxqX>5G_*g4bmVy*PGX*{(zi4CB zhiJAB&6>@LW%z4N60Vhi@AITx3ZAm&3Iu_hb0`{rA<#q7I=DEaSrkrWqFO)AWB!uk zCW40x`N@M|K0Sr|!|a5<#%0&eRw`O7p4g(qva4b0SCLaCmffaAq1w;?l@JDJWB(V2 z0rlg)RqaB0TN5T`4?qNHjsSpC(M)=)?%M(mY3v^?*Hbb4n|#13%&0Q}2Scb(K8{&o zC+B{bohA~D@Av4D#N^#^V#5?m)9fby-U zGW7486mk}baS9(B1_#^qi4O=9`@vfdkk9rTNIcS_V#;t{@)bdyePCcg0#|*%{0^?f z9cM|03Y|LYLPR6Ul~`$K5JxBJY~oRzzwO|)PSk~O(8KR~FSS*{kHbwuYxo|7=c`US zTma@A)PWGH- zmUgamDJ;}cpKBo8X>JFCl9oVb5}!;*u==p#`JL12=bddze`t=)I7N|BWtQMx-Y>XQ z_j>&oxe4K(2-A75eK^d4BYILT5eFT#@(`CA3)iz$w--qW%lw#Nr6TR(1!0$Qyo9m$ zSIQS-=n({+LbbYO9+p6^P$VN({4DqYg$m)S3^IRtJthXn*0iPk2ZXSqiBcUYl-!4} zXs+=9ACDI_l#7PYLXdfrjbS$eF$v#pjP#n8-~0oh-?v}1s}=GNyal6P z<6OkLPie^zrSkX&q*~`3jV%70_yD8DU077F4V3cjaHr(ypaNnAI7Dj!AV3k(PW*Ae z09HXUPL`b@9m5@cH_uiWYX?%MKd_BTO5B< zT#93st4DT7YBsi29XQskJQ{JdMGCj!4iHORytV;M5HL(Zurc63#%>-3X<5umSSzYXCsw#w}Br+SsUp>3|3JR@3h006xYH>0V5Ct7y&cIjz~$eo#~w2=Bh8g0>Z_=LGf4m zAp`}E@=;)*s}$EEVtYR~lHXA(O@HII2s>l48?co6-&j7nQm*;X)?FI=J+=T$xy3=L zS~spZ@X;+DE}f(^d-Q%+Pm^1!jiLgPfd0WLCF+RI%7uP`JRJPe z+tQ$6{2j4WHtj;*{2I|&9C0F@>M;J2^|cURS{Bsp=xu_-f?;gu=i(iTgwXP9V`v@% z30e$}0wS8rj!xJNpV@{BQtCc`U@UHZLiImhk5YZc4SKs55G1YyRnd{`N&2Z%2&-qW zBYq$LgY%DLY#$`;rFPg$*_(|Ftko_1F;3a#RmT+WVXwoJl*XGXFePW%=+OJbA;X7o@Qx6z($4eUl{ihoME#qFQD?#Yanf}aid-U z&rbZ`h5C4K{NIiL`?OBukz~A|)I3~~no$FPtSWfvq%TnkPfj1*^ruhj=&sK8*%EUw z8Q;-;{?D?ilh6-YmCH9n$xfbk68bg>6uU`a_epW}{%H~^Typ|FUwO~a))0ac%r!>F zj99u4aw;X(NQ!~4_lvE05L;mqTkvF)*rLC*VxyrB1A7EQg8dzBk_0=8GO29(Ao2Ea zGLyuc1n~xDG_Ug1|3SW4I!}LmVA2-CeWag%N5Wyx=X448K9V5eJ|ns$3HQ2qfrQ(N z7m{#g{HNGbPD;34x2GiB%E1zDS-*t478oaaw2YUbmXL4{qai*WU(wt|HN9U-Thy@} z9c>K=IkYz*f)Bz8#9%v;8uL&Gtvf=#d)4Ehk%;xEU zR7cL~r_-Rwws~=CH9^?c+w6F?*jNUCcp>d*DNKeAk7$ftd=fZjkj+GJ`VDSaJAE10 zLYwJI`SS$}fxT|SIr;~+o2kMP_@s!0rqRd8;^P!H#qrUJ4?LCFB@g!Ct)f$DI_~6~ zks4&3kj4{Am+UW(IL>(A$UxN7uyH$=^ zL&64QR@^Qj1)HJ-r)17{NiT~q(WqpMBHK*waw7nF=*(RGb{8E8wp2}FN?7VTWaS*6 zo8o=vimL?%U#45GR5am8ZEL6tGi^rae?${FmjB=lc)ZPM5g&>dORyxiVvnlO1d-N1 zi8sIVL2Q{z`lDj!3gW9T63e;$H@L>6$#m+U;OOl%kM1^Pf2S->?}Tt_#F@>Ab-~hj zexc|XyBjth6t9>nTcXPevMN;y_t2gMKR}9LENAVnsb1$SRx5@C5nm8Uec-YTxsmLT zo?roZYb_jSwuVT-Q2BCfi2e*8G@PH}Dc286)sb-tgzVTCj$LmL#TNDk>w^VDL$#l) zx26i9fnqeEUV~`O()!F)GU_PiW>o2;D#da&?Bc1ZOw_rY>g1u$*nv7$g`=oSbuLd$ zOC(nMF2ZYJnp`Ayqo4;pL{eO;tp|>kin;GX|E^z!cNFq>NDuu4uWaG(r|Vrb|3{Dn=57;cDa_13CBVR{L0jZ(4CUT z1K8wB`~^iYG652e3=AKvCHo@l-~t*+j`44p2xz03IG0!_-YSb%zpLJYaXt5lX$~Hg zqK>OxU7o2<2-Z(ZwcHRYuMb`{)bNM>?`v6gCi@ey1@K`03r3#8AZ^9{mxhD)do=-B~8*zrUL!OuUq}kXci>N8GhZ z7eHc<;$EHjK^K{XriYH(gGH}@9TEiKZUf=?o7wy>I3f=J(lmdVL?kX0Xbm|&imob9 z5`RURx;-0cajH4Eo_h5EN{|Z$LEbh%km9ydy$>`w6^WIye~XI12M2s3X+(Jm(v3lv z5MS|AM4011m}!;8Zfz*C(-Y63TcXYP@JwMVNt>M(Z35%)b8JmZ5@%+uAjx5-=g|l0 zO{)7f3V=W*p-6*ekOGxZH>k z6}$WEYtG8(NaHe0mD0MIWC0kUgTH?RXp0bt-Wz@aU4VKTZDgm??x8gFOGp7-FO(i6 zMcSB{>WTP6KV4_T$ioG&778uW#sm@>l={C>U18V)+n&Sp9zO*)-n)n#`;qC1)sVo& z^|XA=j+7+gkBC=rYFk3aeuLh3rI0<&y#as!Ld}#LK*l?unnoti2nB~Da4{65(%byme2f?;!|0l( zwMWQ~=ux*S{^QHDxkmLT5=J(Pb6Vd~c#?j|RX(@4N68D%H!lKiK_Bm3FP4^we&vV$ ziFPfsR=_us@3T^bX}d!BHcaQWdxS|VOyLT6eD`#bfb7GL-wB(RFSIkh0NXv`X!;54 zplJw-nc>A9pr9s4Bdzi13?B?$V=T4T0O)_n)Gs$;gUACbNx$NQKptY)M2EVV0YG;v(tUg zsXZSV=STxI0}J7y46;dK#@P`#FV*a@zEX5$A8uR$pz8KKaIxG_iUon)k+;m(`K_1{ zh-UptQyZcC&(nrmIWJrZNe>5V&zjwIs@y@`C)wkUG~P;(KDx`U=2<5YN#8 zv}+T{5YtgFNZ*cG%Hg1dqO zP$%Vw;cKXS3Y0+}lgD9r!oP818_HmJV+s^-byB1vj)J);7{+M`y$gPiqt4PL@$ynf zZ96Gm2HjwWBHu9hka_~RmFrxpeJ0f&EAIB%Oc#2I-DSGe>yaj*u1&|yT<7zP2f%K^ z)(B3meFtnA_pCVpHik?0Of07L*&1p9FFX2zQHduT1^lkwcr%UDL`}j0j5`w}9(C?24!1%CQe51NXOYBRzq(6h^fn>ygYZ zWHlX2M-L0xHacW~4FEA=9Nz~Oot_hu&kvI6JCe_a;5XdkblD@74kg4@*?q@Of64ohkcqk(2P^!v>_DP{NH8QZ0fY zU>xmFb)ZPWyaiTsi4W1?X)O)ZRL{Y+WLNh=Nsdz(j8e*)dC47Ot}%$QXpaJyY`Aj1 z;i^7-DfCqzLgD%GL=j*_+Db~3tFaLEodL?g26CM#Mb89&ksSo)ZHajT*|$j#J5WjQ zyZwPZdfy$Eim&(GC5bcYdf(mFSp>arnOdRuEthIDu>AEt&GLcheJiE9W;E1z4#8Ar zw!s}s*OkH-3ucRp5VtG4j~ZSef)FrwyTGTBX|@G%t7!&&Xef0ge>+yZlDHr3Y$8W2 zAy;Yyx!6FZi)3+K4J@#G=cQkR6Od&Ea_pKT^+De?#%x(cyHQ>slx0BoXIIc9@UO2; zA`GN}6)g8`_2TB>=w(J)^s*EN6Lgh6AxIWGRBVnf(rBv&1=MjZgXklB`Os2}e2l4L zYN-|6pS3lhW|T^suIe+!V5;zNi?ku76?jh%v8&+QN0}U~%6nb7u$6}6qE<6St5uE= zi`SX=W^5Akn1!p*dSySt3}zpPTVN60uN(UV|Kpo933QPu#A}ASw~y6(>QXrfMis)b_yHHLddryoy~s{e7^< zXy{+GzTmp)WW9!qs!};DJ?z+3fpZGvNgGcn6^OPBHJTphN>m4L$F=>$>zShyzl1^`bL+1jrz(ol^!Qwf-c~aet7@C;Bi)gl7%QJ}NE-?+xkuN3=2#FZOk(#E8B3^@ILnsmy*Gr<=Wx@PKXf*#*6v@^`i2DsOMuZc-;N>o>ui`W@ zvC^ll(@5qny7QZ#T9jN3+J$WH({KP_vkZMha^UnWBJFU_S=0j-y!?e;Ax446XN@T` z>kVR{0lK^>39SVvvwlj3>sDz(V_nb6vj|{y{6NdrXh#sp7NXINAQlOMO#Hq-iLOXW zVMIY8%CHOG9HzyiT~0{X7i{gW#96xJf>&r3?lL@SVUmj~UC} zL?Sx2O6d@3cZ&kY2&!P>)>Jd&Ws6OMe#&7PN5hn%@5GL#A%V!s5osY>38EEzCeF1g zdQ}-vOj0kx-+Xl<{$7CH(CQNfQXO5Dh!$LlQ!o~(sl+$di#l3va<|ph$Z(@khiw48%vIf(NX-N4E2S z!qG@uR=9-mH=^=Tup_9B#ahJQGuB9A5rc#AHFIIfvf~ z&@AgCP_)#iNVRhSC&dT^lD0=;1`^<%64|i*Ao&7Gwk9k#+JeE>I3x-1RdzGQ7~p=7 zcEk(>i*v?fyc!*&0zMr5J@K^&1Q7T@mEBGhkO?>-T80b3O zdErjn35CY`9kX$Fqf`Y>`>QLlaU-s*YLch73CO-h@#HI!Gz4A;nMss_$|Y5aA%;v zJ&>tp(>+V5$q)Pvw7%7No5u0qVq`FukD5rbek3#a7WQj-!kh#l0>veCt1M|5dkIak zc{5VK2X!zu(=L9#0ihl|NV|Oq?TI??YbElIs|fMW`x#n=9z99Djv9Cr4bXL5v1N93 zs#5WVz=eXCu?(sl&7fLhgOI&NLe=xWh;O=vBBBxPro_&eL2YR-qTx%>Fg0n%=pxa{ zXX6u>dA2(5fE&~fxGl^C2s1#>pc`;0#$_PxpMI^#%d6K>&kKOz{Q7ZK({NA4F1}+fu*(k6wjFK?s$#_27=u`cXDso9v42Y^iyDRfSN zc$Eb{ts&v^OkO(fMMxW6(2>ihQh9LvA$TU;oHYO)9RD_d9))HtpHCrsIBO)Fo0A)m zq<;#IZfC z^XHI30Mzvt;3Ft0wSf%u)2-n6oeJR?qhL|^cGQV@aglEdO_8|FF<)Pqo32e}0dI*HS0SmMlC$VBtYjiRGD>WL-y%Sg`zPU; z6B@Hzo>m(;g9%QH-|>TwHJSB2GRKR6KAa}HaSQ3Bh@0#LfnvuD%L2bd^aM}~cV2NZ z&UM5djMEqHYNW#whf?3T**qQj_yGxuu99l6Ma>A4T`<|C+7LbvdE(S^BGIr5*V3F2 zAwWp7YvMe|*`l9+JWVY}|3eS`-gK8#*MqkW@IIh-{Rw*Ln-RzqN$XQ;j>Yl4>eHIy zpWz39*(?9TmnOC9^wjZxf?QZN#cPq7O0J<~ltwa~-}rS(t8^_=jQeVe5mnirR!3=- zHN^-L>Q8%+(ypy3hGx;9_ESo`qNezlgVGu(?Yx@em(m8xp&gqsx~BL=q(Np95K?e+ zR6xuAhhP?#Jg%dRijlyB21Mb4B%~-&ftSRapvlzgIBl7K&wLi>CC_!DUCqgRpdEqx zUHB^IAFk^C+IV8rFCueVKbwB$OdvNl&tY$H;KHO&2Q%r%ccqy0)+Q7J--@HP4_?7W zqTi+>RAM_{irUqKSTtr6Gq#g2qN)~)UM^hcf<U!Mju9_)ZRku zM=JW{Rrth|pMx`xEr>~=RxJbs2C-;Mf(ZdSz@qtwpn2lXBLFfVZZ+q`yDec8dI&tO z@P>W&HwP(h8pvG;pDT_F$og$W#UEnj%B^(x62sr4W<;XcWZU8@{Jh#fQ5y~=_w&HZ z6QxJuFsvCjie)o|a=6W|!BL-~n61*wg_QF;zvCtvIF$U;3LrO7+oO(0$oO-C>Qi2I z2>uS${zQ!oZJ7yoIJq_odw?dX_8_3B_QRi3?H{Tk5V6@fEYjgy5+O^tnRc3wz?01( z$@7Yk>SnXqRPCRqqK%2#rM26%JZxFu$FgQ%w|XL)0o%@^Ly+)^J`!i$yA#H61Z$!H zAuSp6Fa`n{+Ll4&q0Yt~_^xSQb>_68>I@*{GHGKQe;7N%1bdws%^b8=-{3fimZIqPM)KP+EzW4B12@!0&<)IXYl4h?|au zivU)RIEgOQEdJU_v|2$zmRz6oZ-U}KynLQg0Y4soZOdGK4gAH2760xk=n>oad)UoN ziu|HTEWLZ6T_MhszJ%M+D*dc#0HDmmo}G*-kK?CR{dhMV{elI;oh%5t>iNIwW&zXl zlS-kQS=~ytf5&(+$xwyh!y~m`C`CQ}Z-+>!DZ++0JqwiG_;E>$IEcGHaRL@e__-q} zJviToW}%s2BCnwZ?hqsECZ-^Z7DRQb2Gc<3rc3*E(=V}>pnqo3A*eNLY4hM~p}%ZG zI{iu*GN8@8fG=y2gR}GpVZlGL7=xx?UK6~IrrC=#0{iPw7w5C_`2O?R-_|9PVXCpb z|5){&{Xf>TevttBlJQsc2VPTPQ#SqJ&j&8}Z9cxSwUMp#f=@f&L^kfEC(Fz9Ot_84 z1zpDUWaAZ)R^h_^re`s{QK|Psc&E}usf0I>K(<;@1WF=VGWds-Nu5e#VY0i3|3E|v zVxICApto@E8+e;XUJCgenIYmI?3DG^CG0NMK_`wYlxc|iER5F_i+k6z zH(2+sUz3Z~kNDw8g*;8zT6-dnCRj~@QSkJZ55Wa{wp?7U3;pk!Y}~j~l?egw*o+%h zsw5eA1L{pvLjLVlA5ssvB`4K8=oGpPeq|9Ztq*@f6W`8%jDdk@CYI(SG`fRQ>XAZp zB(Z?6iBIV5(7WtH9Zcymg}+{4!W~sCK97imvXH*SU?1VDz@WU<3F=X(#_-IT5E+cWwrp`8Kpw z*R8pGTWo<0u#w_Wr|Jl0p2UyDi=(onB**1R?YPhnyjZ;nVO}!+FXE3rOI!MSmdWqJ zTWTBm*gv350wa(4i0i;LSB=MD*IbZw8)E}KEiToCE^X-Ya~X@?7BJu|?`EY7agA?W zeog4<3AcKIjz5#=&sh2+=|=-vZOGq^6BLhZhEJC5#!Y|hEh7Vd3nLA`S<|u}ZQ7!9 zw@hjR$Pi=dRWg3|rMQH4!_@OiZ15PWXO`H~@i@Q4=EP%4iERiT!(j5~C488g5c}8| zDZh$58=S$fq9~YBh<&iW8gJ3k9dcc_I=aExupYr?9TP)~pRSI{HBzt*Sr}PB9W8B0 zjDzFq3%9;49iSkcMkQ_dBzyS~IV)KXq7UW98=0u%Rx|K^1`6_Jv(SfwTuW#1i-AoG z$C-F*wb3kd^BJJnmLOXZF4jPhg>ayxw5(O=3@ij=e3h>Nw1X=+N;&S0CYAA7%FqZ-1D=(mEi zcG3cE8WbZAd!vPXUZ+gYRq&a>rn?_w;Fr=siW0vEeuZ)MB6iUJOEcyI zY6e!?56}ii-(`Bz$s4m@`#V2?9pYA74hCmDCi}N)L*(jR0b?i~mrcj3OJQ@nSQcMA z6Wt1cZ|v_W85)Jn+E8X6K}|o96Rcl_BeoS_+1~?9QMKIA>Qm}N9a0^s;-OmjR-Xc? z$+h388p{gdaPc;iGXoPDYNJ^l%NGE^nj$K#mI9EOhY=}50rD&huHZK<7%HQy-{d=C z^+Sq`snl1$IZksU7_bfH{~vqr0v}~@HU3X-B!q-bfJhLOMM0w6!bOcnBuh59!9>DM zP*D-+wGpMMvgoHO^CGiPpRX3m_+h8GcecM!V_)z(NN7mJ5XP@M&N*Y|O0 z(OXppbor+*-k){gOrC`8@o7tVk5(%EY1ln;yv#JcXS1XNoPjA^H-`+sAWV@;FSjC< z?=<(?tl2Gnw~9`7n`2@*^*OsGQo0+{lG%Wxy}3}H?)EQls9V0|t>`}2Bt}IarBK$Qmo?oSwW9kR zPT{s5JW{Y~`R-5t@|5z$qoMei6kF?3~Q^TwBIddhb$7?zpKJy^oaM@xx;}x3CX|dV91k zl%w`DW2tL>uUHC0UED0%Lm-Ca+Vxi{n!iVO;SR!b!y;;T*03Gc_Q9HGSmesYE21eY z{lk?9ThI%;yus%A!XEB*#T+^k9(PqAT4_!!@Q#>iyJ^+#n4%aSGvQeOaR(awaXbAq z?!>f}+pL6!rsx=VVp>Mp@GEh1}+&*n&%h-7HiB8!m{ zO{^|TjyXm}_Hx5Ol}IIY$)43mHNHd<07o_aaW8o4B4as!F@pW5_Vt!NC1@?YM;2Wo z&zAXFhMp(MTy7aMT=rM=)6~h<^m{`rV!cHO|Mq4P*4H>>b&Kdgym?>a)sdy>h;tp; zwvq~#fmSg$!R0A^P0B6uPPhMA{dV)Kdd6iPJVIm#a2QA6RE9Eq5AqbU*QOtVL;O^` zi*&fBLl5R*-$D1keuvdef#oE0C7eb!ntvcu5vEfj9?j76Z0@(Y{M+>VhP-Q#!}Nl& z1msa$EUfdl^%}fR=K2Qq|3hdadA8rJIuUg z$}M$U15lp4XUZbrYCfNbSql^4sLBnbHCEm-jqzWdKQ_SnG>el!Gs*XgbKL%yvi;j! zfoC()$B$7AN<+(9AY1XF@Wf?{*N;Mr<|gRX@kLe^QSu@yJa}G0HZS4w zxJlQqu`U+P4^nnn;|ah0jF@&s*e|lWZ<6wh*v;EBSpMw^%z$5)HR+;`xe0Bzpx1~T z>4yR@@@G}Z=`X#QU}J`L5~~ndZ%J7+o3_Nu3`mNnivuYGNmmk{t)}`*+h1mVcQqO5 z_*CnQSjbLuZj3zDnzu^w33K{kPCv{k&$P}p`&ps;$01z;6{3D(zqHRhPF%91XvNeJ zTkYU2n(Hklk*h2GFGvgN52A18uUe?`-6oJ;)kr577Q&Vi>eB)*fB=t!> z-VTs@&yaf8Q*)_o#I@2F(QesP)-{|(k4g>Cwre=A!xmwMY;-K8yUmySJ@MCm|CJ}& zc_7=d`c9fRLg$#ug2UUQz30hw(;n+0IrXqxE4M$qE!^uU@ncbAh1*({4{wX~#v7|h zt!Ft>u19Wbj`B@4NCff}+~v}ieMORYgqxzJ`{&g7c6~pRG;{)TWAZbx(dK zj`6KWJ}w7wdDMsql_NPa){*Rv&G4++R*ji#uw-r)A6qgo=lJ7HdO42m-T9`*@Q7Dz zf+UuVF*`x*lEuy`b}3{lL+qQx-V%G0F)qPi+bXtgzTai9vLpp|Um{as zs0*o1V`BC1hJ-*Ccia#IBKi=^B#in@UCIn4Fmk zior7R+v?|Wna0Stc!;T_-oKJ_$^PsZYv(fQ1ujjn{%Vk9>tTa9t=}6Y#k$KNsn#7D z>0#YsEHbRM2Ju)c4U%UqHppyip+WMkB7-cjt};lPHO(LuR<=QwS{WMg3(c%?245?9 ziow?lKEUA8&sYft-za#b!KE9r+HRE6_%{pwp}}QbvYHIuAo$A$-!1rVgEtEPguxF8 zzS-bSg5P6sOYqwb-YWRb25%F*+TbFcu)GG35qyEc(VnQRIR;M_JkQ`x!QBRz*{79e z@KnKv8(fYKTTX+sfK^r>gL?#zF?gQfM{m$&uMoV|;Bs!(I%M!_!4DXGt>AkNzFzPK zgWoRr!vY zf^RW6q5)++U~rG%8x5W(_-zKCE%;i4=L^2f;0pw=FnERFMFw9g_-un$3!Y=}wSs3D ze7)e~41T-dDF)vt_yB`%5lZn(kW^HPoJ7b}}B9 z8IJ`fs1ut?V>89rq+qka*o-$eXnlyk#@GxqHfh+*FgE>+O$IiTjZL(%@nDl-Y`$2c z3%3B9%Z$yt#-;)rx3Sr8Y?fkkp|N>N+vpAm%Mr%%cg9kBA}pQ8@~6g9x+E-n8_R03 zwCQfn2S5?@&$E{%8|Js01iG?D}w*pSou zNIoLCujkrC>z{ZwSCF3JqS>>diBbD}gUJvNhszwO|GKb=>-u!R@M+)WoJJ?AS)L=? z5Ed)n`|GoLl1KkmO|I|Ly=2up0Y}NIui6|-o?|kMf)-fhY2Q=Xj|YzF--?`w7dRyG5z-&{r9N;`?dc2 zmHzvs{@d1RR@x!|!$c8BOywC;1%1eW*oBd?zTrlv26n!W?Wv1zAnf3E7!L)txN#+py7=W{ ztczb^z)AzE0XhwT{6et_3^|6hUHof(zoIg&!vZyxr`1JST>jX@{{1x{aC!Y1@&n?X zCx3F~&+M8HBD~XUK8W;=tofju_msf1-gB)lZV^fUDR{P4gSK#|YseSu{&E)LV?eWr z60!QHv1$RdEW>=zm|qfenKc8Y!sgJKIi4d@==NhkIfYT@&*Sp%6_N7F(>4~_4W4aH zJjVL8oCvaxGgd{3w{XsF))&O&`iBp0agy2`liEx`@G?PuAnD^tvJ$bfMWdb^c|A&2 zb2$?c>#EOe0~1Ywc&66Jh$i z8GIO{^^)H1`{{Ari)u^cKS0_Gxa-t3?LrI#70j1W{cY$QZBldi#*%7`&mDrO>dF?3F$3G+wzbkg3hd8YcuY=29b2Dar}vP z{JX?xIduDGKUSY95j9G1j);0g$4N{-&>~eJI!uln2rzUQy~nm}+sWC3`H1hHiq*yK z5lA}QPE`)t@{Ci9M4u{=YT48D&~`OlOdj&wyKW-Wa_^IyH!eTxIJuT;wf<5U{({r0 z?$cCstl?w|Vv_iDHu3^VZ%P_S>qL(E6KRt5Nxg8;R2U>~;&6jF$hpj)XKEi!*N7Pj zX4L6K8c1prYjIy<+&6{XyJ`0WLHAk4eL=|m<9j9imZ1CjASfOo;`eZndO3p(4Km)5 z8wdS41fhQL)WRA$>Q9371i24{M^^8b(43)|$H@jSr#8vjp^1{m_ZTc8?Gt({@SV2sUCiF1c$j@K=Kz zp!UdpoS|j#4@cL7NByt9%GQ^yudT`{$rE(YrE#Y=cxqsWzkSNbVVy+Y(UZ*s6wiGs z6TNPtc&_F7@1vdW9bz)`!A;Bu|G+qB`U_Fz*eKWEQH7`fyy$b{0gb$Sn3ORW?In)f z8|>F&=~*e5^;3yVh8J$>59*LbL~LC8&F1ivZ$R#_gB%(OFUhQn?48YShuj_*C9<#P zmXw@f`!hL)e=4tRMP$o4B-}&*=Z%tS$sv6kAGiJ_=vcFe9#Kcxqoi)m)MFeR&1+dN zxo`xF)a=8HZm%5ub=G_tz9PQn%Lv~o{-`|8bG8ifM|psC@e{?=+j@0fXml(Bl|xn1 zu=So*NM`LcH!p-Jv2uLtcVwgG2SW5{Yv;A#b38R)H7&`6S*}IAAgfyVNN#u{d*Rd* z(&|9c1uo6I@RzUrf~c?WWTHyDf6m%-mp=G1%v1Aq)8fC1&12YD7we405tBLmlq&sx zn(05RK{)Epe82>Tlik*yI(E(@TK;Cm1RWxb!)EOuhpGNz_Tk#gB$}YPPa?cyo-e(m z$#dkh?DPhnFWpA4(DS9^Q4>dF*yD|{?mbt^Krj1}oY{I+4@vs0*D0dwAkj076LN9U zQsC`Y9Rr^z!_(bfd*03b#u@7VIIUCvz~DwS5^PEB&m3jmp9sdDh(BumDiYH-;hm?- zNghtVpx9y%SFt$sodp?XO7LDcJW&w?tr6sTP@2_EXI)Qse!>YNDzteUescUAV0#z! zE4TihQDNIr&Y%BdpeXH?^J#gxoC0^P^E%RGmXMzjemJA?7$+{n^|?#V!E^pY>udUj z>#*B__P%(u_dTbz_g&kY3V6;Mmt?k`o((5E^-&{8WU@c93GdOOap)net=oRC`*QU8 z&0#j#AUskZ6@kwSuIM8rerWU?i$Dz&YFJsvm#XW}v?qX^wT8mvZ%lhUiuaoCO`{u088C>9! z1;1L0#!**I5l*6LFu#Qx?|ZEKlJ$NsjIlPCzs&|EawDb#yLPaETQ%aKg>+bDn#G0VS$_oE0WM3n74be0eM zCIZHhmnmmEZbsL#Vn;X!uAuVGOga?jb;QZ7*8F(Q9mhp%$`(j^`plw?~pl~6fg%FzY;pAgj z%P{et=D6pGL-XKi5xmVXJ>Jd4$?d6s#7T?eu^aymJ3B*N>mmnd2X+7-h6c-nP z0y|mq@qcYML05elpdD4d;2Fe@l&5};ghy43dsu^95MxI%{`LE%?&G%UtC%vg*EKEm z?(x+BRQv~$CNP_nDj&rNKyBloBk~Mu^%OFz@}%!{+#E;#$=Bm@^2ub*v3e5zn?Hjd z(&Qa$4g?D&k~{73WW^f8phmfBc7#g>`*?Tr6c-gHcZ~JW%g5WZU1RWKU8++aKyIvj&>E*|9*_Mn+LY|N*2^#`^T@Xf zB)$!U*D_vmcvObX;C}mDo^jRk1Jie7%S?SQ43$GU_Pn#>-Crk~in#piKbWzunb{=TrZUz&A9&8%FPFns0Z&$7C_>-X*YhR#_kO!Zy*hQ6e|ev7`LtOD5gW=h3M##5KIQ6vh(tsAkh zB~LNh?L@^rGCg}8p{iduPPuKTq|^Z z&Wf|>SO3POqm$Yo|3JF;jtYo&eX9bZH*0isT`C|7h13d&rf?Fbg94%_Xw_6cW6p63 zh%WhmO##u%v@7WO?^HlEL8{xTLN2BW#z@Z)iCz>gto@f15NY;l87Z;qSlSg3U1Agv z0YVChz)?VS$^U;85Y@2NM-RMN#8}aY2#!}kgiZXXt5^UF@j5CXsvQL%{I?Vk{h4Ta ze@@5Kl>(x5+I>Jr_Y)Klop*={gVBpa&-Op6fM_Li6^}n_qfF{DWLlipK>^Vpkx9U7 zCs9D;mTAtvrhsTUlRVuTzK;T;R8kkuwgRHVZccliTmezI@hxOLxdNhFj)VwJp*6E` zD0;W`(0;`h|Xnl%7EjIWeAE!?HP3Vc7;S|%`y|$ zZ&OG#9)&jxyd(J=R7kX5wA=J(sjI%QjPufgr^Oi8%!aur!bxZrksye(xfo=fQ9y)J zqCV9(h)yC|v`7F)vy71FBocd664~~sBpNC9MJUu0Sn8-fU0}JR_7s7rB&=G6s_?;?=0uO|0rFj*pKm)CkNcW%!rnE{TIsDFJ ze!>Lq=1L5mRT5pJJ=iLVrUs)yC6VqpX;)e$QJOf^oLnVQvI+PtDv1swU?7H==8p^# z*?h<#Va=}#0@0(J_ZzG5=G`DdwJuc>nbH`QM8C$PS~^4_T95B+Auf20we4K1-Y?-jV6QcD79D zwNj#3g0^rUnBxrFnRL$oIdO0wLM{k&R7xakxwPZ9bIhLYcdWT?rX(zVtRkSTq2g9@ z$(n0%`uKO*JE~fAoK7MOtFG2u+={g}B24I@lc<;0s~glwM7Q74*ZPJthW0wPmr2=U zRwQvkE0!b!tgrAQIeM|(>s(Nwn-s6py36bl1fp7Rl<=<^RkFQ*jDOJ{3kl!s~1Htn7*Aki8YD*PW zv*`SFJoc$$&6+StTLZ93SQAZ;z5k3LY2I5@oa< zR=iBoG8zG!L=m{ zJL|GA&soP zYBeGE_U~pN$op5Mx`AiX3B7EWR^XAw_H-RPDiPvIq4Hyo>z z*DaPZGDVlvv2_}a${>9!{8h4N{q-~{Ioo|A64{$4h18EZm+2GWTnyK`wEXeer4#^m z*c0ZtAbtkfM>fu0udVN)BEeI)l*79D&YAXmW{7Kz9%wn?%DS$%oL%YZMk&G&*#wD1 zBsR!w$>htH%mRIzNu;lG@SNA#nMNVX-*1hcCL*S*o3bt_?BhF=6)`tiAEh7>?zG}I zt#r4wX5((C`HkK$YWaiXQ3pdxlhuTsEaT{XC}3`r+g~TQQCu}&hOJ0-rGL6?n5Y4v z0Nfb)X#*mG$GhW`jy-sw|C7NcAYzJMp2AfU*puE`d6qkEewf$k*A|iqN9}oxX(SPR z*uMEJ%+`)_={U|I&J%Jf%k^;lh``Y30MdD2gOy{>yL1-(T%MJC1%6LtAgP#~P!xTT zq2)gI8Mz?VT+Ps;`;rU@EZk;wn=08r-0yZgiYlbF8RU2(qSY&gsA_INqFLHL?4KGu z>|e7ZgWkj5w+zO^CBP>%AN=bvnZB(nz0;>yTfUZe|KNSpo%y1;%iTfI^moZ@9FN&D z8^>cJvte@n{bV+ry9mjE-J5N!gWyxive1m)X4H&8j99mz0_03s-Ql1 zy-{C{%AUb_@Jj_-J2EBFI;>^KNAB~N@wu%}FM}7;7U~HpE1E4vrZf}_duH%(nYf8e zX_IbF8|~&KOge|)l(@{GJf5>GT5I@yl zc7?nCnnBrU+RCZRs+I>u+Gto1@|hCXu5kfM1l8)IZzOC@+m+ra zT3z%8?T)%=*)(&bY{UK32z-hn*fK5|i+Jepjtn+f7#Wz~9g1<(9H!Pwn48WC9^1-k zPQukzGo8aMHBY7n7X)=pr|K9baF41}&^zs}FMs(CxxnWZjnnJ}wA|u$Je7u~N|_G2 zzhUfwb9>M}%@D!_VhY2Y5}pB?$r-o8#^6ZOwO>W6oC+9{6O1Q5rgXup}c-YTHE8_^CbYj&EwDtCHd z*(=Q-$eg%CqOgWmrtSJG2|xwbNxCG#l)dBFT`gjPwcfpU#^B10Y$5I zf!1pMdkN{Yo!%6G$cZKNnlFgF-u0&z4W*dH>9Wsdlq zbi=fej4X|;4hrsK(B@6>ce%*}b%;-8=E66y=xD~5=qVyPTL z$k)d*tV1livm?Hd_H=mV<2u_dBQ)SHxeTK%XNEGWlYdoK&y?J0oh#YkoD81Uyts6( zWY&9y$*i+IvwtB0&6;?1{Y4xk0C5`LnNEiwf~ovTtRdhYe8~XLa4p_UfaY`Yq~kE= z7Ew_2Oif$1H?O8`fj4t&8L^_rBYEp=keaq7jx~vdpe=vcqd6L^#C1W8b_;2${xGij zW7-K_LqhX=AdE20a^Fb8I7(bKY3KQP7`0|;xY2qYsqLE|#fLbKwH=M-YjOPC(R>Gv zTV%*4HHPbTVw4Wq7)8Cu7U_wNQF^B>()-qX-ZeIJv8i`CjbR!FFeVfpFc~OWg-~(k zC=F9hIykMZ-WvRcu7u_n=+4R7H|O}6327DAy1=?ylJ+a3$WhYsA7j+?=*I}PT$>g`pDki~Kmye4Me8;EFkA1)(it1&*TfrCeqAlz zs4y35L@%ysJJUO6tF$R9?98n)`vB>q**krksiav%8q+dWqHdYQ->{Ypp?@@b_Gk+nQ+1NPc8&^N2yETE4biFa3%3^tJg8feX zcEmCqMSt3!ait-nT8_ugHtH8Mr}cj_(?o9oHh zdJde{NA)HdI-J2Zfec5zpWZ8{@W^EUfL0M^)P72HmsCvcje^Hz zRH~o6+uUWPt4x&zQeQVXB1}!)nbAGA zCO?j5(J)&E-_({@w*4bYrbxU=Vk^6`wcK#lrC}#h(=a51S1~bTg63w5`492D6?!Y{ z`4!ABC=fi8FFa!eT(C=qIk#@kMl&%-a>FTJBQ?uMH!AvqjmXSrL}nr_3m=3w)aG@> zE2fB=?g1|ULxh!!ldL&cw;vq0<}ki*Z(*@ClXXpQll9rfMtbI|xv`IOtobuBpj;|# zD`FUt!z`XGNB?_?GMIRz7;+5b1*`8GBnI7x)kv?buZgsJd7JVpkq?BVT+&%r6AeYm z*XN~(37Q9dXIpy+Q9t(#j`7R_LqiiXGTBz@5W0CLW=<`NJa1P749x49Z4Bs1+FMpo zrq>*Wxu!UUA@fqi;91D#WYa)vK+37lN(&x%h3+_^p9XzQy@YGMy=#`IP~x!?ABp^i zbKSq96fiD0_djfmpF*TA%Bu06)9R6y8yL4@|~{DwMO^#9Z^C&J5kx z2yH||QK-LKfK0Rksrgc;evppW>g8oTR^idSB4f_eG!~q|1KkVxbSsg3b-qAN8K@)|-e{sR|lHgSWqD*e5cz zU4wi_R3ft_&%nZ6iw2)H_9IW-D7tE-X6If2Gqu&vczV(Hbf@vOU5x&ZrFGuy@psD|_MyjrEPMYq@0yv zWVy>)C)1z6PVMNk=yZchRz-tvqod|liOV1VVF|OkE!32<{vhS16gRe1l9QKkuyfMP z78JMlioQ^}bt79io6j+}uL;4^R^dn9s=p*WeV5~AFRd+ylUyRHlHb6b^ae+b?AaQ= zp&QFF2{5^rmRYzjr*80W$hSL&XsPM~QgmOyE{E4A#9Q~PK;X%6$z^?9H`b2f?DYxP zk;9qd{sY`|r90=b?>^nE=;gv1zNsQ^uP~OE(3hX%iFkz!XFIa~7D#%kryf3gvR!CB zHY?bjO0#|~%@C89-q>@&K$g(fcGovDuic{+EpoAws&-nHm$O|f-tINtnty?(PIpi; zDhe5;cTc+7BcKn- zlkS5NSSxMw?{{sDgiw;rJly6CR0fBW(yX7U^#*3K+*;-C>=TA>Ce5$x47l#sXTu)zCu4MnQcES$%TaHCa!ab zrEwZ^PFPHMgKO2hPzI6vlZ~$ZU!mzJgWFZJf!KOQ^AV~gyeR_1mDec{ZJnNp)j44? z)yy@YL(`#3TZLJrg|(!1vR|$3!&{Q^6&ACyB_ZfeCa_7XMgg)fTI&er5yB$}`!@_x z4GN{XWI`%5hDkQ#ZHf#_eXWui!7kbQY&w^oPEim$)*tmWQi{4TC@xC}bKmscZ4d$$ zkKHPstV0+NM@^kWA$WC9v;E^t?=xKWo^b0iw$QXHVk@^)+L@hRKkG1w*c&D_prO@? z){_|jL;-s=C~4S{!X*C_`Zv}CdKhjVBhlTZlV z{B#0x7A*C#gLjT`>Y#3VvOhB!x0rIqQqR2LeYjS;ES$iwrvcVIKeVgkjevp!Sg0u_OGMgV7eoyB%vj zTG7w#e}?d-jTEP?Wme6zPO{K^5q%G@iJ`Lj*fH~jQ)5g1$A-ltgm!A`r6seZ%TGWVe5y|S~yohC+=(+@K-8^kzmGPA|+`oS?XCI z?33ivzj3U265j}0^z1%E)Twtkf8M^nlirW@BHQ14yg63N&l#LdydJjrTdm$>B}qNR zjP%rBj%Ih}j=QY~7HcB$bil5bWWx#VgMu}WomqK^#Po0onP3C0vR-%J00l`;SzebnwjV^Q;T0?)60IL|vhFq4468Z#iw3)Q&D&$%V4+z0L#* zIoZ*rS}o^wiq5z|yZ!zc>y}@1;ks3NWow!pWhfsKP+w-Y&hOGmhZ@kqNy^qf9ak`9`w=*~&R|`^lsh+DoX)k~sbBFrlJ%Uwf$le+pw{7$DuX8=tEJyR}SQeHQ zHOt4LvDs6|9bT>fmGyNkn}Hox#zy~ZtkwLnN%6S4ty!M0w6clcGmAeVqt>4ME^Pg| z8P*0nvg2!&9#L5ZUBzT18PI%*Xv06+aJLN) z+VEo=Mh-IJoHo43hSO}gz=pLp{DlqwXu~IM_<{}Jw_%$Nm&rRr{C;4=;j;71FU^K- z8_uzz*M>LQ@OB$MV8h)ueBXv&*|6uCCf*bqUSz|`HmtPaY8&2a!%a4P)P_53*l5Fp zHhkZPZ8q#S*reCThNs(bqz&CR%(LM<8!ootY8&2W!@F$wunqUx@MRkwvSF(Y!-tsk z2iWjD8|K(>o(-4T@Mas{Wy2?I_^b^N+R(CLn+;>_dOO{QBW;*r!z*pL)`q%r`P0X) zm!SD%@FJ%ueV6y74XpURZC+zw=Ww$>F!lomb?x5K|K@97zEaFGwC3`)azV2-!qBZL zGfbyj?KZGb6{;%y%v3YfBsD^=HtJu{JX)Qna#WUWEB-E1*(y^_QEqMPQ66=nTFAc( ziAQ2GzanM+4OdR`VE#F^o!DG&|C9XXs!`g0l(v)5dDzL%WkbQ;s+gP>lg>Q;R*IGW zU8c&_;x6o`;MndH6{NFdP;s#Q>XJOWtV&f^J5@;%TT01=g#EA zn1vc9UGXRBNIV6^=OZUYb_gu_P13n~!3ZH%mT(=_(zvse*3oon+F;o%1;m%xsPC>5chcCkA zjw&h|Wej<+jmxl(au*jCFPv8#VwB6u7awPyQs^xg=jp{2-k^iaH{Vx9W+(f~bmWtL zi*&`iDk@8*zHJg?GMP#LP=$pwqFk#rSlDdLy76>&;@e2WNwy&^7&M@=f8 zrwF5_7kGV@ML6)AR9R|c&}D(IvMOYPUd2U=iaS`$@EKEX`6BIWy3d9MUWrG-OBjVe zg&&2xB%#8>BO;@^MaOiH?GYE>(~*$at9PHIQ~Dn(TX-@8CQ}U)xn?3_^>Fg`6 zylT$X*UZf?m{(X-Trz(_=?|_gTezsa;=0NzuW#{^rPtqZh0rpJ&rU#a~$bvfdd%yWc)a%el#`Pb1; z&{g;;n>KdINnE90nF8;*w6CsWm`4AXs>bq9;v7LdE^=l15$R8yeC7O=9z^n)t5eJY zlTsCFyAqxAh1%}|N>l|_z+VX={h9PP(l<&wETz=*F)h;Vw^a9S9pe)BQqnBNy^Oy% z*#4yT#Ol^%;un8KxEE@7X|a-~lhmYNapJOwzt@vTNmbk`_$M)%5T&>*qCT8ZMoMX7 zU5KspluqsQTJmr5?xj^r>7^E{h_OujDOV-fNqkbL!IDY;)J~@nnobKzTl!S#bDS!L z5up%Mr8*l^3Gpq$EM=BFiH&fA&{IluBBd7TJPHSyF+j>E9M&)037ZZT7#C-npUlD&SGW1B;2Pk~n47Q3lmcY)Qek*-o)w{>O#l`~LZ#OU`Ak zw3Kwcv|*u8&?Fogti|@!g7rOGT@XsItNJddR;9j7PblrXT=y2zYZlW-O0QL{V+it5 z5SsFg?!-@$D~VD12h-oR<;*_!JC1QajY&_m5v@<}$Yr#$44Y?)LgjRqg$K3H4U4X(zpm zjFlCb1(#7kMmHHL4aH>iF{6VCBiwjAjbsfbzYJy8Te8z9zovj$$BE=we$}?w%xaWM zwasku=wIV86>)cEgjo1M0q zldSsJ__c9A-8Qea%>!+716w0u;7;3|XPXDv=KMC}zSK5n*yi8_+G(3_u-%nyma~KM zYdd1X%P|f49k9*0y6ww+K>CCdT}PK=C-r1{y-YQXe@;e7X{pj8&5SY!Ojc^bB_X#yH<0+68@q$}eS+udECdv2r&Rrr7L@=%%`bCq!mtWkt#F+*INckIuBb+0ilT{M6K0 zdB~5QPR(L5`3v&-DYdj>DZdze@G@ge3?PPoV*Jk!3OG;rmqI^i{+;M{qK$`|`L=(x z>coG?`(LHn|AndV_pf6Nt5y5IaAZE;=U*_q^FKUrLjB7K_&>}6VXH#_j2is!{u``8 zfvdyX|AmKrzkk8-Cvx<^YV%z!KvL?%zhH`DYR407#sA-3V&kK;|L<4Yc3%mq9XD7Q zy=(igde!Qh+BG-*aBbZ>|IPJ3`tkZ(ZvDw^KmFOyZ@=RgzufSvJAb|LH+S8A&%O8E zzv;KX`~3rd_~V~8KltZ|9)9G}$F^*J{4Y=Z^~t9iwmrRl$1^*3?cVe3b9=Mq2aWd3m{^ZHI^&MO}m{?<?4!$f(Sz8~Eb*E-4Pm8fTR* zDk@(x-CN)-MIMU%%&OwbDf50%T>bjQnuVDX8+g3caO^i}T7Wd=(*k zV`rjMxkxb!<`+*aUur_mME;k>EO0C3|_T2Zm2 zqT+=4ob1e8#wYtXgYiG9z*|t}EUv69uXL6!a+VeN78NciuDsAWL=OQicS1Z%7Lg{|Yso}A-vV76P;ziz||Mql> zD;Jh7qH4$uRRJ@NxXxD&A*u5Y?DnmhChIdgL}S7)DfKRps;%-CRO;COrD)shOP9x{ z7w3aI(;1TJ{F`>vk*=Dc9sL&->niW)$7Yk6GbW8NJFFf3>y(F{In-HTmqNIuV`x%1 z(f^>Kkglw(e2L~iLU*d}lhpI^HP$JWF48HeobQtgt#YOmFQ#WGEpZkvtnglc_IIZ@ z4_2}}jRG=CyDSbdt1zT6vWWqr>L~bJI8z8 zxRDh_rsFeYI_Y1T947XTQN4@eRPS*;RPSky#`uOF6>p3&`|B?vF!_RS{RbwBufTgE zGzpsfjfg*Y;0}lC@9nAj7R3`soN|nft?bqm*%;0O-kVRqPtdT~NEJH{2|;DIim)DG zst36X>l3T`jB}_yV-i|>HpMl@HpEm!=Xc9X>=�?dYNUd4WaURX_A__M4W}D0!0n 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 literal 0 HcmV?d00001 diff --git a/winvenv/Scripts/easy_install.exe b/winvenv/Scripts/easy_install.exe new file mode 100644 index 0000000000000000000000000000000000000000..f3c631b86b93fcd806c7a014d3c68e560c59e2f4 GIT binary patch literal 102809 zcmeEvi+>c=+5c`fOO{-i<+2dK$O?<1QH+h3#3i}|yE0og5*0L6Kr|S!pwciSs33`x z)NGF1(!RE}t*y4z)>^H#RSBrDA&?6f33v;j62;3|2Q{E3;X1$Xb7nV*Xy4EK2mJVG zX69U<^PJ~AxAUB{r8lm%IczptI{r6Jo2?N~`WFy?|Mx%L$R0Lf!!X;6LwBClXpihX zYtG_3mV1{~-FLyd@)%HZ5-8PM0*4k}Pmf=}#w{-!O z{(s$e+fo4F{>o-Mqd)Qg@Y0R8El|I=@Kp7-l`3);yoWyo5RILPV9-CW&9-oA)uLO} zTWq#RFGU90v=!n15Apw?e*uuoRI8Y+79X|(06YrMad-~;7qHplQ>+zX>^uXsX3&85)|hA+a$Y9Dcqt&YkdVsiLh-O2*2UjjND*sx~aq>z5*p0 z^m+MHvu!s1k%Tg_Akt#WLM7&jpFm>87@KW9&4=k(d%$Mf(Y#}a5}oIBDN)tuzCqCs zd71N^LiEFqDeQ3J{s?Q2#HOE+Hg<$rJAZ08b=#)Y#nn9KG=D(lUYGs$uoT=IHk-ov zC>$(4VRR@=^%W_sSz+_gzrMwLbF=8jP5tC5(N#Y0TzQT>SH51pL1Bl`Zy>@Fk(kpD zAOY(~)6sOSv>;UYQ6zd>0UwoRv&n2nT^xB{6pGv6pM&zt9*8uy(2fK10P|wlb6RF&}&Ar*C1;S zvv+_szTQLSU#CXzLvI)z#o5r2L`cTc6G?sy0e*sL;SW{zshlUwI$5wA=eyg`?^mcV@UcOoCf3Iqsw9Yvm z*_Cp!L(MGBKY+yLM+`?PJ1B7cCAeQCHqRFbvn^qEQ&E^L$Lsw{m>raFmKVtL<$3c{ zv^Dp7BCLW!VB~P@hN(3B3;C~yVx+MPvSwhSf#nP2^+d~Jln!DCc^j&CuMeK|iM=A1qmK3ONf8l+mcU%OU(8$PS~2>WjH zzZK1E;|hs(eG4%Om!WCCho+}4uC*9W(Wz*M+X!mVbXo5KWqe$jv=y{naPtBh>S^mJ zps;-kJ8F8aLHmk6$<~UMND^Qp4M70X7Gc{J_6}CW6n&A;izQiyvaA!mW}BWn@UHg_ zk%I5jVk)=RQW^RS&|1e7SR# z*iv6L7zuHBFp>omfOKLcp=AKEa8F^o>G=$GBe77IynZb;z&aIRqih4li;wMst(cyd zPzaMXyk?cJjEZR)f|nR+n6a2A<0$ZU`Ek>%Deblu3~nyfjOi&v3n+S`4+CxEIVfDX zhh}gYIM`yo`f6~e9@8{|tYwSQf$6zXRG1rAQ2ckaDr24lR^^Ukrn&wb6gEAVScTfC zkY*LyXBGMf75Z8fa$AMKo7#ApRp>3N&`(iFiRJtai5m!gt)XXac$%Ki_gPe49sw>D z!pO1^5ogdBP%vdhK=dMCfenAASfu+-VLL$gQX{5kHfjUhwdf?mTG8v7=qCv30g=w} zl>@E8XkMmbN6{b^1?4U@J<;TAxxNh}8=v|jS}!v_ldLuuS%B|6YMQ8p^ya-_=KVCd zlqMdG_6Fjy#MBk`86deHwXg>GDkWzl7esrQbS!QqX z+eXlQYhzJ&9Mz4@a+w}ZcocQC9ZKDPH7o3RPhqDLyQr<0$Bu$>Bk2*ubs-x8{81!!$@zY} z?KP4?h3#SXc93l~J@=x^%Hom{$YC8?777i;tD=9FroY0a&u%N@ zZ}+BVq`;byq%8apY(a_XmaINOEXm)wd`xw5jw)3bXR4Ws*`)Z}s=hEBU}-d45Wq1{ zI!zcR^GVbW)}JGITK@3}Yi4h+Pn@*bf@~Lr3?vN}t?7CHZ9%L;%Q)5p3|0tAxE+-- zTZ>keDKRiU5Y-}InM$TjkBy8A0=yi4ZfDD(KReZ8v`|n8-OHsMWTy*0Y2nJ3TN*U)TBRf8udTX z3Q0BM3AHZFPR7d8DvvymRjl;xj>Ke272hZEt(ff*N0XHj z79|F!pg=e_&y|50;S({L=%h6TM4v4EY76@2lhIuSh%SnND-}dyIRqzW0g4R!~k!!bU!a2eHBe1t{}|SeK>Yh6+EI*;b{lUHVlVQ!$2rF#-JFhPpO>KVA#ti5k3% zGJ8ZB^<8{mrq8p!Ugzm&01og&&`=p^3_1K6(MB%n8JkdYsy31TroUMr$YPEWDC%c; zVQQ`|j2jc6R)?^lE!}W8>VgdsPFtMx+DbeC5<`W80*%9B0KiA!I^ynO2EMvYVS6zS z&BOE2*DExFXf9uOCIoFW^qN74_{180K6=|fIy4*0#O&46W?wFBW{s% zQE-p8hR?qMRiZQ83R@eep+-k4tiDma&2lMz&oyV+ZR%)N-G-z(=SUd(nu`bWsU%p2 zGwlp8rQ#Vbb-co6xLLg@mU9TH+E5+_%S77%VTQX$w2-Ea(nXoHmKnKra8Y;KSJE2$ zU>LubKV!NA;ICl@xkVP1%(j%0a=VQH#q5pacjomI;4x5EBXpNFiGPUfJ?aOfD`CEO z^JAF92#CTPDy|r%U8&^vO6$(JqEbIDS7qYwjVsbC^=2<|7`;y<^@*goml%&??ooERE{=ON~y6lnAQN*Z@icvLrA%#X%>c>RdF_E^}8`d|ch0QjCxt(C% zrf!keZI;%x=eL1ysYxhvd@e19l)emUnzDmwIq65cR;;qr|GIWX3LOQxzi=)H1vBO4 zMj;dykf)8;T!c51-dYJ?Eazbqg3d?FVs8hfbQ5Pdzu1`%XN)?G7WPrp#;9|QfAIS- z&Q{@i;dl4HDy+pA!QVhBeq(3z)O0%x-&ytVQ&g z(P#rtHk|%uDblP|v~3`{9(8(9gxf9yU{Pn{N*YgG^Tol8Mb|sOEI^rL$QP&M`7a=GT~yL*(ei=DUL8}i^M#k61xpd zN@?nI>K{x9v-Hi%lJ@cl8)Xmc$4qFD`ms~0vlQ!iNNXDA!wj2oYCUYWYpIxvKU^e3}crk8L%*n%{=l1up zPd_?p^+>(R%{QK2?A7!wHc|Lf%=sb_v6 zH3e>MOUwru)x{sUo$Sl$T}tm^Mej?iDxU=g>Q-uwlDA>SMM@0L5`WW*Or^1#j6|sF zir&@D(`h*QU8L_7K$BF@ZOz!R0}Egze;Xu5q8SL5T5a#aUkirnHbCg7P*8L8=f;W00>E9VG-#&@PYB{62SyUfLFlpL2Th?(=h%{Bb(obc9KX@Vzawzim5Nn z$ydXkAkC>1Q?!#GC$*Si1{r3MVFnpyFm{`pTrluT2;UxgUjopI$s=Kjj}HC{S|NXj z*HXdwr_iygSHYtFK1L4C4Mu~7op=@_f`3x@CG|r^a6L{5M`v`0^$HH&7a(M8DI%T( zd)W)WPrr{3S_(P%*kL6aA^Ue*DLYz9O4t!4I>)z+=yhBv$i-7y*Q1@o7ejqX3W0Cn zh_Tq-N?MF5?-Ds(6!xmG8gorEGz{~sx0&JIuOt4pd(Kt#Q>N;M{Z+V!d|p19Pxd+$ z{L7$%eJg$yhPPFE{y^`{+-#7X!VGmtkj?fPL*Oxjl@kQG3t{C-wdKf8mXbFB4Qtc| zk%|?rP+gB&Ce@S4ANGF{l%{_ZVy{R1?b1V^0kQ~#VhqCyW9BdZ5Y3&t!X>ko2>AD6 zC7&yHWRvp)e-=g@-AaC2;!mO)@xsm8XuW(=#gxO)i zhmJ+q2Sh9jiCAtTVMw#1O;kvZWJcI#ID#*uzRwnYgN$taKO?bnFQmow0nCcEf;J=U z^-}2l3?9)P{Av(?Qr*6RTtTcA9<4Yv9w12zmI$*i!WKcD5z4plzrmJ)Dpm^l#x^VP z)$jn}&?0|p9Ay}T;)+BA7>DA$j#dN7Fmk!|p!t-|k<0G`fJti4z$?f&aR7i*nUu{D zi7kTD^elqEXJ&3ds{1Jl(2QM*38fi3PwzXWPF5=5-hvoA>V%7Q*ClqF{^0~=$)57C zV^kZ&;hm!)p@-vT5ne!;DD(^p^-M2XqfMq(#!)LCC<;*alhT?bb=Z*|?~#kD)sg&l zxP+3h-h@~EbrTErJc48%AYq-Qj2K1I!L^GQf&!uZuy=rcDGXzWN**B=)&g8jfgfW5 zOpYCuz@k+EfjFgg$dJ}GN$a*xB5jXM8=-rK3ip??4j4?JBW(;n34cs-Kn-{Wllujs z7Ru&Fq~=``W-fYOV7vvjyE0TfR?Q8OT@>`kp~ykSgySr&GK97c!PXlG{yAVc?F1T) z{L|~%zptJq>Y;_P+Af29RAZ?ftmJSsGb{zk^qB&>`>#G9;p7trU@kvzU`Xr0!-$@4 z1QL1XRrt8yMRIp_x?bUe*#_$zo>x2Hbsf!9U3}#pc3p1oW*3TUnfc3ItR*o4@5~QU zS%ZBc_GSJOch6>rI*r6Gpy^lX;zTGtL6@r<1Oz+D$gD2P)Y8nY3UoQYqv|l|WIWrN zfI4ie-LvvAuLWop;uAMw>GW*2OSR7yz)F{&UP>jOgqD>Me+%Cn@mI9(x0MS%+xOYab%?oxg14PQ+ zCf~$c*vbS)tbZH)M`+9bz7@lJX5_lmEGi5&f%T~lcE1lg+iL81{Sdv2p3~Jdvo*gr z7Q6&YX~08APCM`mVijI%BP1yg!3{vc?P(nf$r=5PQ@cObyS^;^Jc=@U zpB<*{GvIyfBt#E7nhN73$ZpCF)$YGHQ`Qfj2u5$pHO9$3&31JZ{<_p*vb5n~W>rS( z3?CU5ROzJ|RH;=+m*_PBzRwIuzuFoLfsYDP1#TbWq5(pPuve^o34l9*5Seunz(>D@ zl?ph%l33}^v9NLhtj|pSxLtMX$J4a;xErqhwb)Z5-Dwy9f)Le7Z)=fGO47XV>3fik zr(P$|wEhD254OXeae>MQ`yz#*8AyBeNgckA~`u4ZpGge_)mHM=MOEk&S`1s9&`qUxNYF)-I zg*o7&T$z>7ql( zY8=I1Lvu;v_1}19AQ(v2Fng1##xD|B8ZEktM9;Ax{3YlNPAQL&#IV7!7HJcTS7MhJ z6#w7F?tnh))pvou1iu@_FBc#PS>K8#vRaL+dgNSPy`0ZGk0xR}>*N2VNd&nLk z-*3&M6U`WK6wR7K6P3xmpOXx)m}1i_a&6X16K32Xx*fEJQF#!-j^h7D=ShOS60cAr z&ITL-b%=gTuFdG?w;oQe=u5!wtQGw!k_-?p5$fReA$Cj~OK&9Kx$~1WMnz7^pd?e6> zDVwO5EFEdLrNMqacM|*-@VD6bCU44v;mpJ5Vt5>^qH?n6sfj26j&0+Q^cUTSs{E;& zFlqc|w1jn$xgHg5JP$=okGTmbk2QL-#KBlzJ7_@iE*Orrfp z{yvg~aOd*?49GA8GuDp82y@;CcW)%>ydMvRdFJ84a<0W+zB@rUB}YD1FI8Ab4KK$Z zV+`xlSHaz=xsW^;DLeQQ{9S8JumZ#vV1h|E<1;ZDd{0T-gGE4g45l0VDfIvgNPiFD zo1U9D;e$EbfEjZ7mXp2%1!N)V%;kK2BaM`N!RWKhrpgL-1dC7~4FsV}A`1~2aC6ez z6bO}iG)nIy29c&JwvEY%@%?kGEl^|+~f*J zm*j?{%e@riGT1&0l(KtWrR*Xmr-#|SMWy+@rR;+U_AOcB=}M{Yb2JjJ_=ysZ&T2zw zOb6U!{>vo2hS;|Q_@CFB&1UpP{N2)nPopTCaf06U$MCM-pKgM5EL@dg z_Ey-@YIcz9k0S2@wPv-gV)>n2+7v}E*$k()O+6DMUXM4fVsxOxVPbn&VLMIFpOMUF zrOSl;*cS?N$ASdy2>01IN*97n3ozcvS|o<8e>63G<`L?H{u| z*Z3Hwh$GG-t!`+nL)g;RY{L;`3BsGg-uGX&e6C_*cjREY;yA!&z*6q6Dz>n;{Gw3Z z=c+U4&sQ&^7yptI>J;5?!`?4wab@f(`wMm%!%>33Y^kGFHak+FSG^=~kc!!H=p&xAK%?*!PK0oJ(5?!Z#Yk=ZFZtJ`pG z8j5MtU&pR(bDGRLtSwimwi&4~xoW=#{^8!%k6yRtUiHUv{w}F@H+E6g>bFnw1b(I8578mo|; zrro1|dP@J~guW|H+VDk&u?!7qx1td_%QPzV#2j_Do*1T1Lzm}K-(&QnL!`QKppo8I zTO4ceQuH#+D29hX%MYU#0Za!P*v^lAO0GFEo0$M(gmE=I#y=88up~s0cLs{MQDnH0k0Mu#BBbO{ zD=&&7QeCFi*)SAye+!ggaiLUqh-`bTceqn_KuyI;r2vg;Of$gY-A>L1Y-%hct!yPpjecj;Ao@=39~2bskIl04zfC4( z%p_-@zvPcauwG+_2>yy*u-&`h##Z!c-8QvSfmP8H$knyEy@6a?HRd)Fn|V_2bFXm6 zX1n=Hp8&O%7z4!KB~+1(Is#3%3Suw9@+Kh#e)X@Y4RYaiAnP4u8BXl18LQ0J#Jw2g z`f}9g51mPkv>}WQFno3niGgf5G}~2#iZm5$cmno<>1lxI!5p0l_j)T8VcAD{+DD?V zb@&eJzT-B-hX(#`<@Qls)AJSB7{Gaiim)?|lNv>;ab68xFe)-SpEI>0I5HQ2Sqj2b*0me zEleP`S3hb(&zTHu4;zllAi*L&74~A|BZP=y&<=@hEmLA4Hv;W2%@pPXHiw9sd&Nke zB1@R0J6IYyHuyeF0cpmUB?ExK9Rt+rLQ)kV*r5VYgd{#7+e=}*0wDN_Ak2S&(K@T;)E5b@WFENVG7yZaL_^isKYE!2FzYitt$3pj6w~t}UNJjvc$~BK<0cfO z?K~iiju;JIDcr$7=)z>h9`g})5TOS-v>dGYAUrPQ7ly85vCj=-Ag$$?V&{)x9YLA(bWq zU$57M?Ebd7Eaq9k;sX+~IQaqqB78N_i5L02kPH1L!U|*oEb=iUjNrLGV({><1Y-f0 zKU2*&<6%dK-giOOk(m6s-Zy;3kVaTOw&t3qASyPF#=CwLM(kDbX5~?t1)I{7df)G1 zYmz-P6bjiU#IX@0iMt5_@Vr1Tynj&sUsCy_M1FGLZ7;uJP?OUn6DOkmchr<^Mpc2rib_0|v4GzYMuT6A)NQ%6s9F2$NBMj5tgloWIH4 z7=P<>iC2T>EaMTbzWIvu{86g~1n)?}KIqlD*|j1U{rS-!HYh<;rstvm2s~;R=q3B1 z-`Z5@D7*OIF}aw)?Zj^W-Rgj?V>6zik0I6v5#6_JIVjKH@|!5JA7OPSHbNK1O57f# zy#sDcrg*6RN^G@Tj?Ef^ZRX}+bbfXuIzPSgtA8l5lHc{BbpFYP^a=G2Qm)L`wXc*| z4B-VfvDwp*UR-ad;3RV!G6W0|Aw`2cB9>i`MPGCPu-W&wqo5U~J2P zYuNcLoK7qWOllNR@d|15U7E3imR^)gUY0lO+4 zOPgp=iPbHGVkI{ed7+Vpr!y@>}E{hg}_7J=EP0 z%sgle!)Kc6t{&=@8-lKb^)-YnBcnw;ZL~WIJqH`uTAOht(dN~8z{BHmEa27q#;$Oo znb>r%kqu|r*cHRj3W)c#HlTh3(Qi~?11~1#2fX*T{TA<~2?X!W1@HADIvPCqAa<=V zI4jhi|2-36Lr^87O&)**Q%5R#V;sb5qdoOUA%$(m()Gl|_)Rc|*DCCBN~1;!6o1|< z@Dz1Ak@@&;GfNu{_T?gSfhmdXHpsrxcfm24b0RUH=tH6|bB+>Un9pt#Wzm$?!%Tt(yhWFaK=jQ7dA>W)G!E%Ywpch0o=0ScSl8_l; zwpD(Wz%DM5YR|@t?AQ@@9D)oe(2qK+5;Z1237x*yfvg&nA_t{fEPNOVyG+mDp10QD zCrF@m>19Z~FPXSiBwl?6DILUF_;1ewc|VXIU64(2gkI^V4~r5(-`Pd;d}pf{6qVc6 zDbmYD(#wk7e{_W>e;3-kEDr!xXQqc8Z-(=CXx{*^w4z+?4JCHfnd?uXfohj4?ARjm z*wyJZi6^0~lZle9j@J{2k%S464wu`w#&oa{V`Sq9dSo}IL*F)>jl=O3y(&8xt#lcV z=mHl)bKT%{>tRaSz~;nmRB_&>Ay8lI8o{z@N8zp02Nw4dPUqZ-KY6eAfbg3>On(gx z+h)gt=eZFGA{XVV7Zv@;uAVQwJY0HNw);C)j0H>hL7v>;kR5NzE<2@`I(GOw?g8$b z(u%Md5{8?j)bVaO|B&_y@K*CB4UHg$!S`i4Y@#o7)GTwCHtrQ`Xs=j9d&L^sD>Sr7 z{@Xw|7Pos=Y}I*RZ=hje3rVVsB8H_YEu8p@;hS9YjLk@oIu9b) zmd$WQo$rg6?5J}uy}X01pgFIYCh2neG3RP*7jBc*1!uV{o7thTSGY{%T;I2o=d8xM_{| z+n>4L{wx^$8I#N9Mj}U8x8!wDip#pyEQPsg{}IhWIb7K%Vloh%)t?miQcMpv18d6B zShrcd5D&Qf+ojsype+hF=?>ZY&x1MBEV`A#9aAMtGt4wP1Q78`MdZxZ;IZ_s2Dy!u|BC8zR!B6$$>m>B!L7` zJWgLvXduY<-hd>=r~rSC3dim*-)ND6b2Sw&p4qLAP?#ikC1|uxUPtBhH9$A^D`wN4 zGLuNCBWOOUWu`&|6SI&H1HiIVC(nXa!=2N*9KU)h>UJMvHB{q%QMsFe5d$ zUzZuiUlaL{#(@DNe?6(^ykQh6G%-eL@M@5r%df{;Lo-%^J4PZSrH{11@k9EE)$5KO zP&&=Y2Hb8K8`&@{=N>db27iv}$%j3y=PW`3nTt~rzX6k_a!{L6Td>$MgC67D+k|GL zHBSHr{T8>aRmP?tJcu>KC+V%FM#W=BOHD65P~mAqR3N5nX-&<55_*|VDc}HB;y=-$ zHHargcJ!4vvat`QA^Ov~h1Pmh7fDQvpT7W|f2~!c3U#eX#8?M>r^1#pJ!O9dpU!DO z3*;2|0T2LuVf|=0=V{;2Mj~Z0c)69R7P6e1sWaALdWMOz+p*L}LwD=OOq!k%l&0fc zPt<`xaPJRocLV@JT7vNxahf z;7cV^CDn!CgfEEcx&J9he&-+10fpx%VtOrinT#FAm(Z%{P0iSA#b}c9nJ~HGKqI8_T41rEXyeBmR2%WMM7xVebn6 z?+~0EavLR70;`9ZtMqcZ%Q&CS8U?G-D~oYbxEbum5bWb1Ove3KOwfE#QBB9+?{-R< zrC9SaaVFEkEv@sMTQCmO<9`yU0Di_o;9iLou}^hoG7-mk;hakGmsDN84md=P=jJ~P z9wPo)J1PFkZ^Mj}?+j;9hl!=JonLNH(susS`PAWdeoyjA_AkCg zkBRqS*X~e&qzk^oq_ATJkkbgZW*lWWQ1$s>?l4fCbXURE(8?IBPY4PTfRJYHPSu3F zZjc*fFhA5wHqw3`+Y7E8%lQx9`2$x9T5{3g|4a#&EC9eU&s4%!EXVu{DE0v$2VLEW z?>9>DeT>Ey%X7_*BfvTD^ph2_vqEw9r=PUG#y;3)WArz$-R8 z>fR*cW;riHEx>t|KhZ}wQCa~oF4Y2h%Ke$htrxj{f(|3BhoG23VG_d7)W3vU1C3Vk zpQ>8MZ$X@%Qkkd75Z>s+EIppZGo#-x2>;nls|( z>Z=j<6%8Bv58_$S-zVIyv?h$-VM<;BZ32^z;lbBo(IctRO8Pq`J&B~Xp}LP$$-<5s z@)w`l*{#m`a0S>gPAj7qTtx=oY6gG66Z^rB6Io&kmZf$*0)uuvXtMSsD#5CDkarx@ zW>1vki^4g`p_G^LtRza}9GT;f~%i`X3~Ll2O+KmHI8atqY@0@UYG z{sbtuu*YJdQtcPOLF{S={|qFq_km={K%<1cNC1K7=p|>O31rMeMvZv_5KFbhPH~ET zav!kv>L>@9Va_&qGZeN{W^eK)5Fte)N_C@95Dtf_R8U+vP#L}CT+kr)qfF2Be?%(0 zbDyH0^UwnMLntzJC$B~WSo)p;4>*yXmrvtBA{F@0RCGpI>6>=XOiK7O63|2znvmB6 zAb=MMy$ansoWE7s-KXUDAsCZij8*!5?S6zkH8|FtaUflU@a*I@(3=65j2Ql8%H389 z1fC~?a&n{FOB+Nx`PDaqF+$c1a@bqo#;DoT$FOp6qE+rTN=hErzU2>u#y;YF*q4Iv zo6X?q!{&NJmR#?uEG|@so14Wsk><3TV_yTmRUeaEDiElD(N~Bm=F)Y93b89gn>1_} zow_IVnVxCDxWXP5q(G+ri>;Q!j)=wDELnohlI6J8;9&n*JJK-)MtKVm02)!pSfA@G zeB|jRCk}u@U@)El4){{6IqOi+t+XJ?Tm+5goQ2HfSskGo<+zbxdd{QaVyqB_5JGs# zutYTlB3lwE$@_%Q8i)G(&-$*lCYgq{8jWly$9L?c5EnZ^db&Af=troS)H`zhij_;jBXy{fE6~W$Sd)mKlszIq-I&Ewg3%Mf5c@SYI^* zi%Fvj`sQ*RI_b5VfxcC>mE{DHfn8(OcdJx;F|7^SQ5CF|oNAE@?<+P)PaGvqFLiue zoGV3g{oAG3Lt+Fa=b*BHo@nV-0u*Ri%sgMZ&|9pYpatJ_ycPAlM=AcM<+2hhvjDEX z^}_0J0bP(e2;hwG0^80!zoAz2R+s;cRrSUYmiG|85g<^v|AAFueVWfy7t`aEdW+l> zvf0%e>EY6bg;}=G^khCJR!~T(_)q9t0fBx^Owp4ou*qj;4He18y*08?Cx@(1C}lY5qLBCcZ7N_mQ5*PQ4xC1^`ckR z5AVMcJ>QS>Fj@vR889;SK8NO{cliDyes^*cxDM?Qn43YsX3(E)o)&fZOfIk>wwHxLW1U4z`SDKgpDrswKx%?IhhP$ib9VA`Kkf(Nykchsy1i#2 z2}uvY2*w__0LYs~Or9MF5GQ2+2@RG1S0Mf?4rt{!#=Dza=RCn1o_0(q;A)p!iz$e@%{o{}qa)Z9HgCj2H|}1qJ0mXnaPFO`N_E z+q#H_-@)JbE-+>Nz@&W(n4*4QzLEXkXs-}3m<Pr!vurL16u>mMa-=6q@;9_AC9MSR0M_(pugS2nZR__<|lb%7f(?C|u5rs^VO z(9)ktrX=r9l5=U&_WB&t(zGjkZPnW|6Xj>KX3uB$0nu1u5(ksbQ{0#W`wJ^ zY7(1~TN}Su(z{OL&L<;7pOx#yxeD0HZi<&+Erh5dB?{YWKod^c8ze&z@B>dAoH2=u z!5aAOScX{hP73$-QVe?lKp-Z6J0FVf(eH=ox3_bAe87n_fOBzSjF2q?`-mRHVHGoW zwVl5U93ZY(M%1e{3%fiN&QgsoBNYdM+{c}Wj@PGk+0?~9WTU!zrXv((0eaolBEnvs zYbc*(cZn$~l=YK#Z3Mp*z{>tsb&}ZvH2RG3h(psxqX>5G_*g4bmVy*PGX*{(zi4CB zhiJAB&6>@LW%z4N60Vhi@AITx3ZAm&3Iu_hb0`{rA<#q7I=DEaSrkrWqFO)AWB!uk zCW40x`N@M|K0Sr|!|a5<#%0&eRw`O7p4g(qva4b0SCLaCmffaAq1w;?l@JDJWB(V2 z0rlg)RqaB0TN5T`4?qNHjsSpC(M)=)?%M(mY3v^?*Hbb4n|#13%&0Q}2Scb(K8{&o zC+B{bohA~D@Av4D#N^#^V#5?m)9fby-U zGW7486mk}baS9(B1_#^qi4O=9`@vfdkk9rTNIcS_V#;t{@)bdyePCcg0#|*%{0^?f z9cM|03Y|LYLPR6Ul~`$K5JxBJY~oRzzwO|)PSk~O(8KR~FSS*{kHbwuYxo|7=c`US zTma@A)PWGH- zmUgamDJ;}cpKBo8X>JFCl9oVb5}!;*u==p#`JL12=bddze`t=)I7N|BWtQMx-Y>XQ z_j>&oxe4K(2-A75eK^d4BYILT5eFT#@(`CA3)iz$w--qW%lw#Nr6TR(1!0$Qyo9m$ zSIQS-=n({+LbbYO9+p6^P$VN({4DqYg$m)S3^IRtJthXn*0iPk2ZXSqiBcUYl-!4} zXs+=9ACDI_l#7PYLXdfrjbS$eF$v#pjP#n8-~0oh-?v}1s}=GNyal6P z<6OkLPie^zrSkX&q*~`3jV%70_yD8DU077F4V3cjaHr(ypaNnAI7Dj!AV3k(PW*Ae z09HXUPL`b@9m5@cH_uiWYX?%MKd_BTO5B< zT#93st4DT7YBsi29XQskJQ{JdMGCj!4iHORytV;M5HL(Zurc63#%>-3X<5umSSzYXCsw#w}Br+SsUp>3|3JR@3h006xYH>0V5Ct7y&cIjz~$eo#~w2=Bh8g0>Z_=LGf4m zAp`}E@=;)*s}$EEVtYR~lHXA(O@HII2s>l48?co6-&j7nQm*;X)?FI=J+=T$xy3=L zS~spZ@X;+DE}f(^d-Q%+Pm^1!jiLgPfd0WLCF+RI%7uP`JRJPe z+tQ$6{2j4WHtj;*{2I|&9C0F@>M;J2^|cURS{Bsp=xu_-f?;gu=i(iTgwXP9V`v@% z30e$}0wS8rj!xJNpV@{BQtCc`U@UHZLiImhk5YZc4SKs55G1YyRnd{`N&2Z%2&-qW zBYq$LgY%DLY#$`;rFPg$*_(|Ftko_1F;3a#RmT+WVXwoJl*XGXFePW%=+OJbA;X7o@Qx6z($4eUl{ihoME#qFQD?#Yanf}aid-U z&rbZ`h5C4K{NIiL`?OBukz~A|)I3~~no$FPtSWfvq%TnkPfj1*^ruhj=&sK8*%EUw z8Q;-;{?D?ilh6-YmCH9n$xfbk68bg>6uU`a_epW}{%H~^Typ|FUwO~a))0ac%r!>F zj99u4aw;X(NQ!~4_lvE05L;mqTkvF)*rLC*VxyrB1A7EQg8dzBk_0=8GO29(Ao2Ea zGLyuc1n~xDG_Ug1|3SW4I!}LmVA2-CeWag%N5Wyx=X448K9V5eJ|ns$3HQ2qfrQ(N z7m{#g{HNGbPD;34x2GiB%E1zDS-*t478oaaw2YUbmXL4{qai*WU(wt|HN9U-Thy@} z9c>K=IkYz*f)Bz8#9%v;8uL&Gtvf=#d)4Ehk%;xEU zR7cL~r_-Rwws~=CH9^?c+w6F?*jNUCcp>d*DNKeAk7$ftd=fZjkj+GJ`VDSaJAE10 zLYwJI`SS$}fxT|SIr;~+o2kMP_@s!0rqRd8;^P!H#qrUJ4?LCFB@g!Ct)f$DI_~6~ zks4&3kj4{Am+UW(IL>(A$UxN7uyH$=^ zL&64QR@^Qj1)HJ-r)17{NiT~q(WqpMBHK*waw7nF=*(RGb{8E8wp2}FN?7VTWaS*6 zo8o=vimL?%U#45GR5am8ZEL6tGi^rae?${FmjB=lc)ZPM5g&>dORyxiVvnlO1d-N1 zi8sIVL2Q{z`lDj!3gW9T63e;$H@L>6$#m+U;OOl%kM1^Pf2S->?}Tt_#F@>Ab-~hj zexc|XyBjth6t9>nTcXPevMN;y_t2gMKR}9LENAVnsb1$SRx5@C5nm8Uec-YTxsmLT zo?roZYb_jSwuVT-Q2BCfi2e*8G@PH}Dc286)sb-tgzVTCj$LmL#TNDk>w^VDL$#l) zx26i9fnqeEUV~`O()!F)GU_PiW>o2;D#da&?Bc1ZOw_rY>g1u$*nv7$g`=oSbuLd$ zOC(nMF2ZYJnp`Ayqo4;pL{eO;tp|>kin;GX|E^z!cNFq>NDuu4uWaG(r|Vrb|3{Dn=57;cDa_13CBVR{L0jZ(4CUT z1K8wB`~^iYG652e3=AKvCHo@l-~t*+j`44p2xz03IG0!_-YSb%zpLJYaXt5lX$~Hg zqK>OxU7o2<2-Z(ZwcHRYuMb`{)bNM>?`v6gCi@ey1@K`03r3#8AZ^9{mxhD)do=-B~8*zrUL!OuUq}kXci>N8GhZ z7eHc<;$EHjK^K{XriYH(gGH}@9TEiKZUf=?o7wy>I3f=J(lmdVL?kX0Xbm|&imob9 z5`RURx;-0cajH4Eo_h5EN{|Z$LEbh%km9ydy$>`w6^WIye~XI12M2s3X+(Jm(v3lv z5MS|AM4011m}!;8Zfz*C(-Y63TcXYP@JwMVNt>M(Z35%)b8JmZ5@%+uAjx5-=g|l0 zO{)7f3V=W*p-6*ekOGxZH>k z6}$WEYtG8(NaHe0mD0MIWC0kUgTH?RXp0bt-Wz@aU4VKTZDgm??x8gFOGp7-FO(i6 zMcSB{>WTP6KV4_T$ioG&778uW#sm@>l={C>U18V)+n&Sp9zO*)-n)n#`;qC1)sVo& z^|XA=j+7+gkBC=rYFk3aeuLh3rI0<&y#as!Ld}#LK*l?unnoti2nB~Da4{65(%byme2f?;!|0l( zwMWQ~=ux*S{^QHDxkmLT5=J(Pb6Vd~c#?j|RX(@4N68D%H!lKiK_Bm3FP4^we&vV$ ziFPfsR=_us@3T^bX}d!BHcaQWdxS|VOyLT6eD`#bfb7GL-wB(RFSIkh0NXv`X!;54 zplJw-nc>A9pr9s4Bdzi13?B?$V=T4T0O)_n)Gs$;gUACbNx$NQKptY)M2EVV0YG;v(tUg zsXZSV=STxI0}J7y46;dK#@P`#FV*a@zEX5$A8uR$pz8KKaIxG_iUon)k+;m(`K_1{ zh-UptQyZcC&(nrmIWJrZNe>5V&zjwIs@y@`C)wkUG~P;(KDx`U=2<5YN#8 zv}+T{5YtgFNZ*cG%Hg1dqO zP$%Vw;cKXS3Y0+}lgD9r!oP818_HmJV+s^-byB1vj)J);7{+M`y$gPiqt4PL@$ynf zZ96Gm2HjwWBHu9hka_~RmFrxpeJ0f&EAIB%Oc#2I-DSGe>yaj*u1&|yT<7zP2f%K^ z)(B3meFtnA_pCVpHik?0Of07L*&1p9FFX2zQHduT1^lkwcr%UDL`}j0j5`w}9(C?24!1%CQe51NXOYBRzq(6h^fn>ygYZ zWHlX2M-L0xHacW~4FEA=9Nz~Oot_hu&kvI6JCe_a;5XdkblD@74kg4@*?q@Of64ohkcqk(2P^!v>_DP{NH8QZ0fY zU>xmFb)ZPWyaiTsi4W1?X)O)ZRL{Y+WLNh=Nsdz(j8e*)dC47Ot}%$QXpaJyY`Aj1 z;i^7-DfCqzLgD%GL=j*_+Db~3tFaLEodL?g26CM#Mb89&ksSo)ZHajT*|$j#J5WjQ zyZwPZdfy$Eim&(GC5bcYdf(mFSp>arnOdRuEthIDu>AEt&GLcheJiE9W;E1z4#8Ar zw!s}s*OkH-3ucRp5VtG4j~ZSef)FrwyTGTBX|@G%t7!&&Xef0ge>+yZlDHr3Y$8W2 zAy;Yyx!6FZi)3+K4J@#G=cQkR6Od&Ea_pKT^+De?#%x(cyHQ>slx0BoXIIc9@UO2; zA`GN}6)g8`_2TB>=w(J)^s*EN6Lgh6AxIWGRBVnf(rBv&1=MjZgXklB`Os2}e2l4L zYN-|6pS3lhW|T^suIe+!V5;zNi?ku76?jh%v8&+QN0}U~%6nb7u$6}6qE<6St5uE= zi`SX=W^5Akn1!p*dSySt3}zpPTVN60uN(UV|Kpo933QPu#A}ASw~y6(>QXrfMis)b_yHHLddryoy~s{e7^< zXy{+GzTmp)WW9!qs!};DJ?z+3fpZGvNgGcn6^OPBHJTphN>m4L$F=>$>zShyzl1^`bL+1jrz(ol^!Qwf-c~aet7@C;Bi)gl7%QJ}NE-?+xkuN3=2#FZOk(#E8B3^@ILnsmy*Gr<=Wx@PKXf*#*6v@^`i2DsOMuZc-;N>o>ui`W@ zvC^ll(@5qny7QZ#T9jN3+J$WH({KP_vkZMha^UnWBJFU_S=0j-y!?e;Ax446XN@T` z>kVR{0lK^>39SVvvwlj3>sDz(V_nb6vj|{y{6NdrXh#sp7NXINAQlOMO#Hq-iLOXW zVMIY8%CHOG9HzyiT~0{X7i{gW#96xJf>&r3?lL@SVUmj~UC} zL?Sx2O6d@3cZ&kY2&!P>)>Jd&Ws6OMe#&7PN5hn%@5GL#A%V!s5osY>38EEzCeF1g zdQ}-vOj0kx-+Xl<{$7CH(CQNfQXO5Dh!$LlQ!o~(sl+$di#l3va<|ph$Z(@khiw48%vIf(NX-N4E2S z!qG@uR=9-mH=^=Tup_9B#ahJQGuB9A5rc#AHFIIfvf~ z&@AgCP_)#iNVRhSC&dT^lD0=;1`^<%64|i*Ao&7Gwk9k#+JeE>I3x-1RdzGQ7~p=7 zcEk(>i*v?fyc!*&0zMr5J@K^&1Q7T@mEBGhkO?>-T80b3O zdErjn35CY`9kX$Fqf`Y>`>QLlaU-s*YLch73CO-h@#HI!Gz4A;nMss_$|Y5aA%;v zJ&>tp(>+V5$q)Pvw7%7No5u0qVq`FukD5rbek3#a7WQj-!kh#l0>veCt1M|5dkIak zc{5VK2X!zu(=L9#0ihl|NV|Oq?TI??YbElIs|fMW`x#n=9z99Djv9Cr4bXL5v1N93 zs#5WVz=eXCu?(sl&7fLhgOI&NLe=xWh;O=vBBBxPro_&eL2YR-qTx%>Fg0n%=pxa{ zXX6u>dA2(5fE&~fxGl^C2s1#>pc`;0#$_PxpMI^#%d6K>&kKOz{Q7ZK({NA4F1}+fu*(k6wjFK?s$#_27=u`cXDso9v42Y^iyDRfSN zc$Eb{ts&v^OkO(fMMxW6(2>ihQh9LvA$TU;oHYO)9RD_d9))HtpHCrsIBO)Fo0A)m zq<;#IZfC z^XHI30Mzvt;3Ft0wSf%u)2-n6oeJR?qhL|^cGQV@aglEdO_8|FF<)Pqo32e}0dI*HS0SmMlC$VBtYjiRGD>WL-y%Sg`zPU; z6B@Hzo>m(;g9%QH-|>TwHJSB2GRKR6KAa}HaSQ3Bh@0#LfnvuD%L2bd^aM}~cV2NZ z&UM5djMEqHYNW#whf?3T**qQj_yGxuu99l6Ma>A4T`<|C+7LbvdE(S^BGIr5*V3F2 zAwWp7YvMe|*`l9+JWVY}|3eS`-gK8#*MqkW@IIh-{Rw*Ln-RzqN$XQ;j>Yl4>eHIy zpWz39*(?9TmnOC9^wjZxf?QZN#cPq7O0J<~ltwa~-}rS(t8^_=jQeVe5mnirR!3=- zHN^-L>Q8%+(ypy3hGx;9_ESo`qNezlgVGu(?Yx@em(m8xp&gqsx~BL=q(Np95K?e+ zR6xuAhhP?#Jg%dRijlyB21Mb4B%~-&ftSRapvlzgIBl7K&wLi>CC_!DUCqgRpdEqx zUHB^IAFk^C+IV8rFCueVKbwB$OdvNl&tY$H;KHO&2Q%r%ccqy0)+Q7J--@HP4_?7W zqTi+>RAM_{irUqKSTtr6Gq#g2qN)~)UM^hcf<U!Mju9_)ZRku zM=JW{Rrth|pMx`xEr>~=RxJbs2C-;Mf(ZdSz@qtwpn2lXBLFfVZZ+q`yDec8dI&tO z@P>W&HwP(h8pvG;pDT_F$og$W#UEnj%B^(x62sr4W<;XcWZU8@{Jh#fQ5y~=_w&HZ z6QxJuFsvCjie)o|a=6W|!BL-~n61*wg_QF;zvCtvIF$U;3LrO7+oO(0$oO-C>Qi2I z2>uS${zQ!oZJ7yoIJq_odw?dX_8_3B_QRi3?H{Tk5V6@fEYjgy5+O^tnRc3wz?01( z$@7Yk>SnXqRPCRqqK%2#rM26%JZxFu$FgQ%w|XL)0o%@^Ly+)^J`!i$yA#H61Z$!H zAuSp6Fa`n{+Ll4&q0Yt~_^xSQb>_68>I@*{GHGKQe;7N%1bdws%^b8=-{3fimZIqPM)KP+EzW4B12@!0&<)IXYl4h?|au zivU)RIEgOQEdJU_v|2$zmRz6oZ-U}KynLQg0Y4soZOdGK4gAH2760xk=n>oad)UoN ziu|HTEWLZ6T_MhszJ%M+D*dc#0HDmmo}G*-kK?CR{dhMV{elI;oh%5t>iNIwW&zXl zlS-kQS=~ytf5&(+$xwyh!y~m`C`CQ}Z-+>!DZ++0JqwiG_;E>$IEcGHaRL@e__-q} zJviToW}%s2BCnwZ?hqsECZ-^Z7DRQb2Gc<3rc3*E(=V}>pnqo3A*eNLY4hM~p}%ZG zI{iu*GN8@8fG=y2gR}GpVZlGL7=xx?UK6~IrrC=#0{iPw7w5C_`2O?R-_|9PVXCpb z|5){&{Xf>TevttBlJQsc2VPTPQ#SqJ&j&8}Z9cxSwUMp#f=@f&L^kfEC(Fz9Ot_84 z1zpDUWaAZ)R^h_^re`s{QK|Psc&E}usf0I>K(<;@1WF=VGWds-Nu5e#VY0i3|3E|v zVxICApto@E8+e;XUJCgenIYmI?3DG^CG0NMK_`wYlxc|iER5F_i+k6z zH(2+sUz3Z~kNDw8g*;8zT6-dnCRj~@QSkJZ55Wa{wp?7U3;pk!Y}~j~l?egw*o+%h zsw5eA1L{pvLjLVlA5ssvB`4K8=oGpPeq|9Ztq*@f6W`8%jDdk@CYI(SG`fRQ>XAZp zB(Z?6iBIV5(7WtH9Zcymg}+{4!W~sCK97imvXH*SU?1VDz@WU<3F=X(#_-IT5E+cWwrp`8Kpw z*R8pGTWo<0u#w_Wr|Jl0p2UyDi=(onB**1R?YPhnyjZ;nVO}!+FXE3rOI!MSmdWqJ zTWTBm*gv350wa(4i0i;LSB=MD*IbZw8)E}KEiToCE^X-Ya~X@?7BJu|?`EY7agA?W zeog4<3AcKIjz5#=&sh2+=|=-vZOGq^6BLhZhEJC5#!Y|hEh7Vd3nLA`S<|u}ZQ7!9 zw@hjR$Pi=dRWg3|rMQH4!_@OiZ15PWXO`H~@i@Q4=EP%4iERiT!(j5~C488g5c}8| zDZh$58=S$fq9~YBh<&iW8gJ3k9dcc_I=aExupYr?9TP)~pRSI{HBzt*Sr}PB9W8B0 zjDzFq3%9;49iSkcMkQ_dBzyS~IV)KXq7UW98=0u%Rx|K^1`6_Jv(SfwTuW#1i-AoG z$C-F*wb3kd^BJJnmLOXZF4jPhg>ayxw5(O=3@ij=e3h>Nw1X=+N;&S0CYAA7%FqZ-1D=(mEi zcG3cE8WbZAd!vPXUZ+gYRq&a>rn?_w;Fr=siW0vEeuZ)MB6iUJOEcyI zY6e!?56}ii-(`Bz$s4m@`#V2?9pYA74hCmDCi}N)L*(jR0b?i~mrcj3OJQ@nSQcMA z6Wt1cZ|v_W85)Jn+E8X6K}|o96Rcl_BeoS_+1~?9QMKIA>Qm}N9a0^s;-OmjR-Xc? z$+h388p{gdaPc;iGXoPDYNJ^l%NGE^nj$K#mI9EOhY=}50rD&huHZK<7%HQy-{d=C z^+Sq`snl1$IZksU7_bfH{~vqr0v}~@HU3X-B!q-bfJhLOMM0w6!bOcnBuh59!9>DM zP*D-+wGpMMvgoHO^CGiPpRX3m_+h8GcecM!V_)z(NN7mJ5XP@M&N*Y|O0 z(OXppbor+*-k){gOrC`8@o7tVk5(%EY1ln;yv#JcXS1XNoPjA^H-`+sAWV@;FSjC< z?=<(?tl2Gnw~9`7n`2@*^*OsGQo0+{lG%Wxy}3}H?)EQls9V0|t>`}2Bt}IarBK$Qmo?oSwW9kR zPT{s5JW{Y~`R-5t@|5z$qoMei6kF?3~Q^TwBIddhb$7?zpKJy^oaM@xx;}x3CX|dV91k zl%w`DW2tL>uUHC0UED0%Lm-Ca+Vxi{n!iVO;SR!b!y;;T*03Gc_Q9HGSmesYE21eY z{lk?9ThI%;yus%A!XEB*#T+^k9(PqAT4_!!@Q#>iyJ^+#n4%aSGvQeOaR(awaXbAq z?!>f}+pL6!rsx=VVp>Mp@GEh1}+&*n&%h-7HiB8!m{ zO{^|TjyXm}_Hx5Ol}IIY$)43mHNHd<07o_aaW8o4B4as!F@pW5_Vt!NC1@?YM;2Wo z&zAXFhMp(MTy7aMT=rM=)6~h<^m{`rV!cHO|Mq4P*4H>>b&Kdgym?>a)sdy>h;tp; zwvq~#fmSg$!R0A^P0B6uPPhMA{dV)Kdd6iPJVIm#a2QA6RE9Eq5AqbU*QOtVL;O^` zi*&fBLl5R*-$D1keuvdef#oE0C7eb!ntvcu5vEfj9?j76Z0@(Y{M+>VhP-Q#!}Nl& z1msa$EUfdl^%}fR=K2Qq|3hdadA8rJIuUg z$}M$U15lp4XUZbrYCfNbSql^4sLBnbHCEm-jqzWdKQ_SnG>el!Gs*XgbKL%yvi;j! zfoC()$B$7AN<+(9AY1XF@Wf?{*N;Mr<|gRX@kLe^QSu@yJa}G0HZS4w zxJlQqu`U+P4^nnn;|ah0jF@&s*e|lWZ<6wh*v;EBSpMw^%z$5)HR+;`xe0Bzpx1~T z>4yR@@@G}Z=`X#QU}J`L5~~ndZ%J7+o3_Nu3`mNnivuYGNmmk{t)}`*+h1mVcQqO5 z_*CnQSjbLuZj3zDnzu^w33K{kPCv{k&$P}p`&ps;$01z;6{3D(zqHRhPF%91XvNeJ zTkYU2n(Hklk*h2GFGvgN52A18uUe?`-6oJ;)kr577Q&Vi>eB)*fB=t!> z-VTs@&yaf8Q*)_o#I@2F(QesP)-{|(k4g>Cwre=A!xmwMY;-K8yUmySJ@MCm|CJ}& zc_7=d`c9fRLg$#ug2UUQz30hw(;n+0IrXqxE4M$qE!^uU@ncbAh1*({4{wX~#v7|h zt!Ft>u19Wbj`B@4NCff}+~v}ieMORYgqxzJ`{&g7c6~pRG;{)TWAZbx(dK zj`6KWJ}w7wdDMsql_NPa){*Rv&G4++R*ji#uw-r)A6qgo=lJ7HdO42m-T9`*@Q7Dz zf+UuVF*`x*lEuy`b}3{lL+qQx-V%G0F)qPi+bXtgzTai9vLpp|Um{as zs0*o1V`BC1hJ-*Ccia#IBKi=^B#in@UCIn4Fmk zior7R+v?|Wna0Stc!;T_-oKJ_$^PsZYv(fQ1ujjn{%Vk9>tTa9t=}6Y#k$KNsn#7D z>0#YsEHbRM2Ju)c4U%UqHppyip+WMkB7-cjt};lPHO(LuR<=QwS{WMg3(c%?245?9 ziow?lKEUA8&sYft-za#b!KE9r+HRE6_%{pwp}}QbvYHIuAo$A$-!1rVgEtEPguxF8 zzS-bSg5P6sOYqwb-YWRb25%F*+TbFcu)GG35qyEc(VnQRIR;M_JkQ`x!QBRz*{79e z@KnKv8(fYKTTX+sfK^r>gL?#zF?gQfM{m$&uMoV|;Bs!(I%M!_!4DXGt>AkNzFzPK zgWoRr!vY zf^RW6q5)++U~rG%8x5W(_-zKCE%;i4=L^2f;0pw=FnERFMFw9g_-un$3!Y=}wSs3D ze7)e~41T-dDF)vt_yB`%5lZn(kW^HPoJ7b}}B9 z8IJ`fs1ut?V>89rq+qka*o-$eXnlyk#@GxqHfh+*FgE>+O$IiTjZL(%@nDl-Y`$2c z3%3B9%Z$yt#-;)rx3Sr8Y?fkkp|N>N+vpAm%Mr%%cg9kBA}pQ8@~6g9x+E-n8_R03 zwCQfn2S5?@&$E{%8|Js01iG?D}w*pSou zNIoLCujkrC>z{ZwSCF3JqS>>diBbD}gUJvNhszwO|GKb=>-u!R@M+)WoJJ?AS)L=? z5Ed)n`|GoLl1KkmO|I|Ly=2up0Y}NIui6|-o?|kMf)-fhY2Q=Xj|YzF--?`w7dRyG5z-&{r9N;`?dc2 zmHzvs{@d1RR@x!|!$c8BOywC;1%1eW*oBd?zTrlv26n!W?Wv1zAnf3E7!L)txN#+py7=W{ ztczb^z)AzE0XhwT{6et_3^|6hUHof(zoIg&!vZyxr`1JST>jX@{{1x{aC!Y1@&n?X zCx3F~&+M8HBD~XUK8W;=tofju_msf1-gB)lZV^fUDR{P4gSK#|YseSu{&E)LV?eWr z60!QHv1$RdEW>=zm|qfenKc8Y!sgJKIi4d@==NhkIfYT@&*Sp%6_N7F(>4~_4W4aH zJjVL8oCvaxGgd{3w{XsF))&O&`iBp0agy2`liEx`@G?PuAnD^tvJ$bfMWdb^c|A&2 zb2$?c>#EOe0~1Ywc&66Jh$i z8GIO{^^)H1`{{Ari)u^cKS0_Gxa-t3?LrI#70j1W{cY$QZBldi#*%7`&mDrO>dF?3F$3G+wzbkg3hd8YcuY=29b2Dar}vP z{JX?xIduDGKUSY95j9G1j);0g$4N{-&>~eJI!uln2rzUQy~nm}+sWC3`H1hHiq*yK z5lA}QPE`)t@{Ci9M4u{=YT48D&~`OlOdj&wyKW-Wa_^IyH!eTxIJuT;wf<5U{({r0 z?$cCstl?w|Vv_iDHu3^VZ%P_S>qL(E6KRt5Nxg8;R2U>~;&6jF$hpj)XKEi!*N7Pj zX4L6K8c1prYjIy<+&6{XyJ`0WLHAk4eL=|m<9j9imZ1CjASfOo;`eZndO3p(4Km)5 z8wdS41fhQL)WRA$>Q9371i24{M^^8b(43)|$H@jSr#8vjp^1{m_ZTc8?Gt({@SV2sUCiF1c$j@K=Kz zp!UdpoS|j#4@cL7NByt9%GQ^yudT`{$rE(YrE#Y=cxqsWzkSNbVVy+Y(UZ*s6wiGs z6TNPtc&_F7@1vdW9bz)`!A;Bu|G+qB`U_Fz*eKWEQH7`fyy$b{0gb$Sn3ORW?In)f z8|>F&=~*e5^;3yVh8J$>59*LbL~LC8&F1ivZ$R#_gB%(OFUhQn?48YShuj_*C9<#P zmXw@f`!hL)e=4tRMP$o4B-}&*=Z%tS$sv6kAGiJ_=vcFe9#Kcxqoi)m)MFeR&1+dN zxo`xF)a=8HZm%5ub=G_tz9PQn%Lv~o{-`|8bG8ifM|psC@e{?=+j@0fXml(Bl|xn1 zu=So*NM`LcH!p-Jv2uLtcVwgG2SW5{Yv;A#b38R)H7&`6S*}IAAgfyVNN#u{d*Rd* z(&|9c1uo6I@RzUrf~c?WWTHyDf6m%-mp=G1%v1Aq)8fC1&12YD7we405tBLmlq&sx zn(05RK{)Epe82>Tlik*yI(E(@TK;Cm1RWxb!)EOuhpGNz_Tk#gB$}YPPa?cyo-e(m z$#dkh?DPhnFWpA4(DS9^Q4>dF*yD|{?mbt^Krj1}oY{I+4@vs0*D0dwAkj076LN9U zQsC`Y9Rr^z!_(bfd*03b#u@7VIIUCvz~DwS5^PEB&m3jmp9sdDh(BumDiYH-;hm?- zNghtVpx9y%SFt$sodp?XO7LDcJW&w?tr6sTP@2_EXI)Qse!>YNDzteUescUAV0#z! zE4TihQDNIr&Y%BdpeXH?^J#gxoC0^P^E%RGmXMzjemJA?7$+{n^|?#V!E^pY>udUj z>#*B__P%(u_dTbz_g&kY3V6;Mmt?k`o((5E^-&{8WU@c93GdOOap)net=oRC`*QU8 z&0#j#AUskZ6@kwSuIM8rerWU?i$Dz&YFJsvm#XW}v?qX^wT8mvZ%lhUiuaoCO`{u088C>9! z1;1L0#!**I5l*6LFu#Qx?|ZEKlJ$NsjIlPCzs&|EawDb#yLPaETQ%aKg>+bDn#G0VS$_oE0WM3n74be0eM zCIZHhmnmmEZbsL#Vn;X!uAuVGOga?jb;QZ7*8F(Q9mhp%$`(j^`plw?~pl~6fg%FzY;pAgj z%P{et=D6pGL-XKi5xmVXJ>Jd4$?d6s#7T?eu^aymJ3B*N>mmnd2X+7-h6c-nP z0y|mq@qcYML05elpdD4d;2Fe@l&5};ghy43dsu^95MxI%{`LE%?&G%UtC%vg*EKEm z?(x+BRQv~$CNP_nDj&rNKyBloBk~Mu^%OFz@}%!{+#E;#$=Bm@^2ub*v3e5zn?Hjd z(&Qa$4g?D&k~{73WW^f8phmfBc7#g>`*?Tr6c-gHcZ~JW%g5WZU1RWKU8++aKyIvj&>E*|9*_Mn+LY|N*2^#`^T@Xf zB)$!U*D_vmcvObX;C}mDo^jRk1Jie7%S?SQ43$GU_Pn#>-Crk~in#piKbWzunb{=TrZUz&A9&8%FPFns0Z&$7C_>-X*YhR#_kO!Zy*hQ6e|ev7`LtOD5gW=h3M##5KIQ6vh(tsAkh zB~LNh?L@^rGCg}8p{iduPPuKTq|^Z z&Wf|>SO3POqm$Yo|3JF;jtYo&eX9bZH*0isT`C|7h13d&rf?Fbg94%_Xw_6cW6p63 zh%WhmO##u%v@7WO?^HlEL8{xTLN2BW#z@Z)iCz>gto@f15NY;l87Z;qSlSg3U1Agv z0YVChz)?VS$^U;85Y@2NM-RMN#8}aY2#!}kgiZXXt5^UF@j5CXsvQL%{I?Vk{h4Ta ze@@5Kl>(x5+I>Jr_Y)Klop*={gVBpa&-Op6fM_Li6^}n_qfF{DWLlipK>^Vpkx9U7 zCs9D;mTAtvrhsTUlRVuTzK;T;R8kkuwgRHVZccliTmezI@hxOLxdNhFj)VwJp*6E` zD0;W`(0;`h|Xnl%7EjIWeAE!?HP3Vc7;S|%`y|$ zZ&OG#9)&jxyd(J=R7kX5wA=J(sjI%QjPufgr^Oi8%!aur!bxZrksye(xfo=fQ9y)J zqCV9(h)yC|v`7F)vy71FBocd664~~sBpNC9MJUu0Sn8-fU0}JR_7s7rB&=G6s_?;?=0uO|0rFj*pKm)CkNcW%!rnE{TIsDFJ ze!>Lq=1L5mRT5pJJ=iLVrUs)yC6VqpX;)e$QJOf^oLnVQvI+PtDv1swU?7H==8p^# z*?h<#Va=}#0@0(J_ZzG5=G`DdwJuc>nbH`QM8C$PS~^4_T95B+Auf20we4K1-Y?-jV6QcD79D zwNj#3g0^rUnBxrFnRL$oIdO0wLM{k&R7xakxwPZ9bIhLYcdWT?rX(zVtRkSTq2g9@ z$(n0%`uKO*JE~fAoK7MOtFG2u+={g}B24I@lc<;0s~glwM7Q74*ZPJthW0wPmr2=U zRwQvkE0!b!tgrAQIeM|(>s(Nwn-s6py36bl1fp7Rl<=<^RkFQ*jDOJ{3kl!s~1Htn7*Aki8YD*PW zv*`SFJoc$$&6+StTLZ93SQAZ;z5k3LY2I5@oa< zR=iBoG8zG!L=m{ zJL|GA&soP zYBeGE_U~pN$op5Mx`AiX3B7EWR^XAw_H-RPDiPvIq4Hyo>z z*DaPZGDVlvv2_}a${>9!{8h4N{q-~{Ioo|A64{$4h18EZm+2GWTnyK`wEXeer4#^m z*c0ZtAbtkfM>fu0udVN)BEeI)l*79D&YAXmW{7Kz9%wn?%DS$%oL%YZMk&G&*#wD1 zBsR!w$>htH%mRIzNu;lG@SNA#nMNVX-*1hcCL*S*o3bt_?BhF=6)`tiAEh7>?zG}I zt#r4wX5((C`HkK$YWaiXQ3pdxlhuTsEaT{XC}3`r+g~TQQCu}&hOJ0-rGL6?n5Y4v z0Nfb)X#*mG$GhW`jy-sw|C7NcAYzJMp2AfU*puE`d6qkEewf$k*A|iqN9}oxX(SPR z*uMEJ%+`)_={U|I&J%Jf%k^;lh``Y30MdD2gOy{>yL1-(T%MJC1%6LtAgP#~P!xTT zq2)gI8Mz?VT+Ps;`;rU@EZk;wn=08r-0yZgiYlbF8RU2(qSY&gsA_INqFLHL?4KGu z>|e7ZgWkj5w+zO^CBP>%AN=bvnZB(nz0;>yTfUZe|KNSpo%y1;%iTfI^moZ@9FN&D z8^>cJvte@n{bV+ry9mjE-J5N!gWyxive1m)X4H&8j99mz0_03s-Ql1 zy-{C{%AUb_@Jj_-J2EBFI;>^KNAB~N@wu%}FM}7;7U~HpE1E4vrZf}_duH%(nYf8e zX_IbF8|~&KOge|)l(@{GJf5>GT5I@yl zc7?nCnnBrU+RCZRs+I>u+Gto1@|hCXu5kfM1l8)IZzOC@+m+ra zT3z%8?T)%=*)(&bY{UK32z-hn*fK5|i+Jepjtn+f7#Wz~9g1<(9H!Pwn48WC9^1-k zPQukzGo8aMHBY7n7X)=pr|K9baF41}&^zs}FMs(CxxnWZjnnJ}wA|u$Je7u~N|_G2 zzhUfwb9>M}%@D!_VhY2Y5}pB?$r-o8#^6ZOwO>W6oC+9{6O1Q5rgXup}c-YTHE8_^CbYj&EwDtCHd z*(=Q-$eg%CqOgWmrtSJG2|xwbNxCG#l)dBFT`gjPwcfpU#^B10Y$5I zf!1pMdkN{Yo!%6G$cZKNnlFgF-u0&z4W*dH>9Wsdlq zbi=fej4X|;4hrsK(B@6>ce%*}b%;-8=E66y=xD~5=qVyPTL z$k)d*tV1livm?Hd_H=mV<2u_dBQ)SHxeTK%XNEGWlYdoK&y?J0oh#YkoD81Uyts6( zWY&9y$*i+IvwtB0&6;?1{Y4xk0C5`LnNEiwf~ovTtRdhYe8~XLa4p_UfaY`Yq~kE= z7Ew_2Oif$1H?O8`fj4t&8L^_rBYEp=keaq7jx~vdpe=vcqd6L^#C1W8b_;2${xGij zW7-K_LqhX=AdE20a^Fb8I7(bKY3KQP7`0|;xY2qYsqLE|#fLbKwH=M-YjOPC(R>Gv zTV%*4HHPbTVw4Wq7)8Cu7U_wNQF^B>()-qX-ZeIJv8i`CjbR!FFeVfpFc~OWg-~(k zC=F9hIykMZ-WvRcu7u_n=+4R7H|O}6327DAy1=?ylJ+a3$WhYsA7j+?=*I}PT$>g`pDki~Kmye4Me8;EFkA1)(it1&*TfrCeqAlz zs4y35L@%ysJJUO6tF$R9?98n)`vB>q**krksiav%8q+dWqHdYQ->{Ypp?@@b_Gk+nQ+1NPc8&^N2yETE4biFa3%3^tJg8feX zcEmCqMSt3!ait-nT8_ugHtH8Mr}cj_(?o9oHh zdJde{NA)HdI-J2Zfec5zpWZ8{@W^EUfL0M^)P72HmsCvcje^Hz zRH~o6+uUWPt4x&zQeQVXB1}!)nbAGA zCO?j5(J)&E-_({@w*4bYrbxU=Vk^6`wcK#lrC}#h(=a51S1~bTg63w5`492D6?!Y{ z`4!ABC=fi8FFa!eT(C=qIk#@kMl&%-a>FTJBQ?uMH!AvqjmXSrL}nr_3m=3w)aG@> zE2fB=?g1|ULxh!!ldL&cw;vq0<}ki*Z(*@ClXXpQll9rfMtbI|xv`IOtobuBpj;|# zD`FUt!z`XGNB?_?GMIRz7;+5b1*`8GBnI7x)kv?buZgsJd7JVpkq?BVT+&%r6AeYm z*XN~(37Q9dXIpy+Q9t(#j`7R_LqiiXGTBz@5W0CLW=<`NJa1P749x49Z4Bs1+FMpo zrq>*Wxu!UUA@fqi;91D#WYa)vK+37lN(&x%h3+_^p9XzQy@YGMy=#`IP~x!?ABp^i zbKSq96fiD0_djfmpF*TA%Bu06)9R6y8yL4@|~{DwMO^#9Z^C&J5kx z2yH||QK-LKfK0Rksrgc;evppW>g8oTR^idSB4f_eG!~q|1KkVxbSsg3b-qAN8K@)|-e{sR|lHgSWqD*e5cz zU4wi_R3ft_&%nZ6iw2)H_9IW-D7tE-X6If2Gqu&vczV(Hbf@vOU5x&ZrFGuy@psD|_MyjrEPMYq@0yv zWVy>)C)1z6PVMNk=yZchRz-tvqod|liOV1VVF|OkE!32<{vhS16gRe1l9QKkuyfMP z78JMlioQ^}bt79io6j+}uL;4^R^dn9s=p*WeV5~AFRd+ylUyRHlHb6b^ae+b?AaQ= zp&QFF2{5^rmRYzjr*80W$hSL&XsPM~QgmOyE{E4A#9Q~PK;X%6$z^?9H`b2f?DYxP zk;9qd{sY`|r90=b?>^nE=;gv1zNsQ^uP~OE(3hX%iFkz!XFIa~7D#%kryf3gvR!CB zHY?bjO0#|~%@C89-q>@&K$g(fcGovDuic{+EpoAws&-nHm$O|f-tINtnty?(PIpi; zDhe5;cTc+7BcKn- zlkS5NSSxMw?{{sDgiw;rJly6CR0fBW(yX7U^#*3K+*;-C>=TA>Ce5$x47l#sXTu)zCu4MnQcES$%TaHCa!ab zrEwZ^PFPHMgKO2hPzI6vlZ~$ZU!mzJgWFZJf!KOQ^AV~gyeR_1mDec{ZJnNp)j44? z)yy@YL(`#3TZLJrg|(!1vR|$3!&{Q^6&ACyB_ZfeCa_7XMgg)fTI&er5yB$}`!@_x z4GN{XWI`%5hDkQ#ZHf#_eXWui!7kbQY&w^oPEim$)*tmWQi{4TC@xC}bKmscZ4d$$ zkKHPstV0+NM@^kWA$WC9v;E^t?=xKWo^b0iw$QXHVk@^)+L@hRKkG1w*c&D_prO@? z){_|jL;-s=C~4S{!X*C_`Zv}CdKhjVBhlTZlV z{B#0x7A*C#gLjT`>Y#3VvOhB!x0rIqQqR2LeYjS;ES$iwrvcVIKeVgkjevp!Sg0u_OGMgV7eoyB%vj zTG7w#e}?d-jTEP?Wme6zPO{K^5q%G@iJ`Lj*fH~jQ)5g1$A-ltgm!A`r6seZ%TGWVe5y|S~yohC+=(+@K-8^kzmGPA|+`oS?XCI z?33ivzj3U265j}0^z1%E)Twtkf8M^nlirW@BHQ14yg63N&l#LdydJjrTdm$>B}qNR zjP%rBj%Ih}j=QY~7HcB$bil5bWWx#VgMu}WomqK^#Po0onP3C0vR-%J00l`;SzebnwjV^Q;T0?)60IL|vhFq4468Z#iw3)Q&D&$%V4+z0L#* zIoZ*rS}o^wiq5z|yZ!zc>y}@1;ks3NWow!pWhfsKP+w-Y&hOGmhZ@kqNy^qf9ak`9`w=*~&R|`^lsh+DoX)k~sbBFrlJ%Uwf$le+pw{7$DuX8=tEJyR}SQeHQ zHOt4LvDs6|9bT>fmGyNkn}Hox#zy~ZtkwLnN%6S4ty!M0w6clcGmAeVqt>4ME^Pg| z8P*0nvg2!&9#L5ZUBzT18PI%*Xv06+aJLN) z+VEo=Mh-IJoHo43hSO}gz=pLp{DlqwXu~IM_<{}Jw_%$Nm&rRr{C;4=;j;71FU^K- z8_uzz*M>LQ@OB$MV8h)ueBXv&*|6uCCf*bqUSz|`HmtPaY8&2a!%a4P)P_53*l5Fp zHhkZPZ8q#S*reCThNs(bqz&CR%(LM<8!ootY8&2W!@F$wunqUx@MRkwvSF(Y!-tsk z2iWjD8|K(>o(-4T@Mas{Wy2?I_^b^N+R(CLn+;>_dOO{QBW;*r!z*pL)`q%r`P0X) zm!SD%@FJ%ueV6y74XpURZC+zw=Ww$>F!lomb?x5K|K@97zEaFGwC3`)azV2-!qBZL zGfbyj?KZGb6{;%y%v3YfBsD^=HtJu{JX)Qna#WUWEB-E1*(y^_QEqMPQ66=nTFAc( ziAQ2GzanM+4OdR`VE#F^o!DG&|C9XXs!`g0l(v)5dDzL%WkbQ;s+gP>lg>Q;R*IGW zU8c&_;x6o`;MndH6{NFdP;s#Q>XJOWtV&f^J5@;%TT01=g#EA zn1vc9UGXRBNIV6^=OZUYb_gu_P13n~!3ZH%mT(=_(zvse*3oon+F;o%1;m%xsPC>5chcCkA zjw&h|Wej<+jmxl(au*jCFPv8#VwB6u7awPyQs^xg=jp{2-k^iaH{Vx9W+(f~bmWtL zi*&`iDk@8*zHJg?GMP#LP=$pwqFk#rSlDdLy76>&;@e2WNwy&^7&M@=f8 zrwF5_7kGV@ML6)AR9R|c&}D(IvMOYPUd2U=iaS`$@EKEX`6BIWy3d9MUWrG-OBjVe zg&&2xB%#8>BO;@^MaOiH?GYE>(~*$at9PHIQ~Dn(TX-@8CQ}U)xn?3_^>Fg`6 zylT$X*UZf?m{(X-Trz(_=?|_gTezsa;=0NzuW#{^rPtqZh0rpJ&rU#a~$bvfdd%yWc)a%el#`Pb1; z&{g;;n>KdINnE90nF8;*w6CsWm`4AXs>bq9;v7LdE^=l15$R8yeC7O=9z^n)t5eJY zlTsCFyAqxAh1%}|N>l|_z+VX={h9PP(l<&wETz=*F)h;Vw^a9S9pe)BQqnBNy^Oy% z*#4yT#Ol^%;un8KxEE@7X|a-~lhmYNapJOwzt@vTNmbk`_$M)%5T&>*qCT8ZMoMX7 zU5KspluqsQTJmr5?xj^r>7^E{h_OujDOV-fNqkbL!IDY;)J~@nnobKzTl!S#bDS!L z5up%Mr8*l^3Gpq$EM=BFiH&fA&{IluBBd7TJPHSyF+j>E9M&)037ZZT7#C-npUlD&SGW1B;2Pk~n47Q3lmcY)Qek*-o)w{>O#l`~LZ#OU`Ak zw3Kwcv|*u8&?Fogti|@!g7rOGT@XsItNJddR;9j7PblrXT=y2zYZlW-O0QL{V+it5 z5SsFg?!-@$D~VD12h-oR<;*_!JC1QajY&_m5v@<}$Yr#$44Y?)LgjRqg$K3H4U4X(zpm zjFlCb1(#7kMmHHL4aH>iF{6VCBiwjAjbsfbzYJy8Te8z9zovj$$BE=we$}?w%xaWM zwasku=wIV86>)cEgjo1M0q zldSsJ__c9A-8Qea%>!+716w0u;7;3|XPXDv=KMC}zSK5n*yi8_+G(3_u-%nyma~KM zYdd1X%P|f49k9*0y6ww+K>CCdT}PK=C-r1{y-YQXe@;e7X{pj8&5SY!Ojc^bB_X#yH<0+68@q$}eS+udECdv2r&Rrr7L@=%%`bCq!mtWkt#F+*INckIuBb+0ilT{M6K0 zdB~5QPR(L5`3v&-DYdj>DZdze@G@ge3?PPoV*Jk!3OG;rmqI^i{+;M{qK$`|`L=(x z>coG?`(LHn|AndV_pf6Nt5y5IaAZE;=U*_q^FKUrLjB7K_&>}6VXH#_j2is!{u``8 zfvdyX|AmKrzkk8-Cvx<^YV%z!KvL?%zhH`DYR407#sA-3V&kK;|L<4Yc3%mq9XD7Q zy=(igde!Qh+BG-*aBbZ>|IPJ3`tkZ(ZvDw^KmFOyZ@=RgzufSvJAb|LH+S8A&%O8E zzv;KX`~3rd_~V~8KltZ|9)9G}$F^*J{4Y=Z^~t9iwmrRl$1^*3?cVe3b9=Mq2aWd3m{^ZHI^&MO}m{?<?4!$f(Sz8~Eb*E-4Pm8fTR* zDk@(x-CN)-MIMU%%&OwbDf50%T>bjQnuVDX8+g3caO^i}T7Wd=(*k zV`rjMxkxb!<`+*aUur_mME;k>EO0C3|_T2Zm2 zqT+=4ob1e8#wYtXgYiG9z*|t}EUv69uXL6!a+VeN78NciuDsAWL=OQicS1Z%7Lg{|Yso}A-vV76P;ziz||Mql> zD;Jh7qH4$uRRJ@NxXxD&A*u5Y?DnmhChIdgL}S7)DfKRps;%-CRO;COrD)shOP9x{ z7w3aI(;1TJ{F`>vk*=Dc9sL&->niW)$7Yk6GbW8NJFFf3>y(F{In-HTmqNIuV`x%1 z(f^>Kkglw(e2L~iLU*d}lhpI^HP$JWF48HeobQtgt#YOmFQ#WGEpZkvtnglc_IIZ@ z4_2}}jRG=CyDSbdt1zT6vWWqr>L~bJI8z8 zxRDh_rsFeYI_Y1T947XTQN4@eRPS*;RPSky#`uOF6>p3&`|B?vF!_RS{RbwBufTgE zGzpsfjfg*Y;0}lC@9nAj7R3`soN|nft?bqm*%;0O-kVRqPtdT~NEJH{2|;DIim)DG zst36X>l3T`jB}_yV-i|>HpMl@HpEm!=Xc9X>=�?dYNUd4WaURX_A__M4W}D0!0n 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 literal 0 HcmV?d00001 diff --git a/winvenv/Scripts/pip.exe b/winvenv/Scripts/pip.exe new file mode 100644 index 0000000000000000000000000000000000000000..aafd26ab4e780f9fe8c550657c81c0fb198b42a9 GIT binary patch literal 102791 zcmeEvi+>c=+5c`fOO{-i<+2dK$O?<1QH+h3#3i}|yE0og5*0L6Kr|S!pwciSs33`x z)NGF1(!RE}t*y4z)>^H#RSBrDA&?6f33v;j62;3|2Q{E3;X1$Xb7nV*Xy4EK2mJVG zX69U<^PJ~AxAUB{r8lm%IczptI{r6Jo2?N~`WFy?|Mx%L$R0Lf!!X;6LwBClXpihX zYtG_3mV1{~-FLyd@)%HZ5-8PM0*4k}Pmf=}#w{-!O z{(s$e+fo4F{>o-Mqd)Qg@Y0R8El|I=@Kp7-l`3);yoWyo5RILPV9-CW&9-oA)uLO} zTWq#RFGU90v=!n15Apw?e*uuoRI8Y+79X|(06YrMad-~;7qHplQ>+zX>^uXsX3&85)|hA+a$Y9Dcqt&YkdVsiLh-O2*2UjjND*sx~aq>z5*p0 z^m+MHvu!s1k%Tg_Akt#WLM7&jpFm>87@KW9&4=k(d%$Mf(Y#}a5}oIBDN)tuzCqCs zd71N^LiEFqDeQ3J{s?Q2#HOE+Hg<$rJAZ08b=#)Y#nn9KG=D(lUYGs$uoT=IHk-ov zC>$(4VRR@=^%W_sSz+_gzrMwLbF=8jP5tC5(N#Y0TzQT>SH51pL1Bl`Zy>@Fk(kpD zAOY(~)6sOSv>;UYQ6zd>0UwoRv&n2nT^xB{6pGv6pM&zt9*8uy(2fK10P|wlb6RF&}&Ar*C1;S zvv+_szTQLSU#CXzLvI)z#o5r2L`cTc6G?sy0e*sL;SW{zshlUwI$5wA=eyg`?^mcV@UcOoCf3Iqsw9Yvm z*_Cp!L(MGBKY+yLM+`?PJ1B7cCAeQCHqRFbvn^qEQ&E^L$Lsw{m>raFmKVtL<$3c{ zv^Dp7BCLW!VB~P@hN(3B3;C~yVx+MPvSwhSf#nP2^+d~Jln!DCc^j&CuMeK|iM=A1qmK3ONf8l+mcU%OU(8$PS~2>WjH zzZK1E;|hs(eG4%Om!WCCho+}4uC*9W(Wz*M+X!mVbXo5KWqe$jv=y{naPtBh>S^mJ zps;-kJ8F8aLHmk6$<~UMND^Qp4M70X7Gc{J_6}CW6n&A;izQiyvaA!mW}BWn@UHg_ zk%I5jVk)=RQW^RS&|1e7SR# z*iv6L7zuHBFp>omfOKLcp=AKEa8F^o>G=$GBe77IynZb;z&aIRqih4li;wMst(cyd zPzaMXyk?cJjEZR)f|nR+n6a2A<0$ZU`Ek>%Deblu3~nyfjOi&v3n+S`4+CxEIVfDX zhh}gYIM`yo`f6~e9@8{|tYwSQf$6zXRG1rAQ2ckaDr24lR^^Ukrn&wb6gEAVScTfC zkY*LyXBGMf75Z8fa$AMKo7#ApRp>3N&`(iFiRJtai5m!gt)XXac$%Ki_gPe49sw>D z!pO1^5ogdBP%vdhK=dMCfenAASfu+-VLL$gQX{5kHfjUhwdf?mTG8v7=qCv30g=w} zl>@E8XkMmbN6{b^1?4U@J<;TAxxNh}8=v|jS}!v_ldLuuS%B|6YMQ8p^ya-_=KVCd zlqMdG_6Fjy#MBk`86deHwXg>GDkWzl7esrQbS!QqX z+eXlQYhzJ&9Mz4@a+w}ZcocQC9ZKDPH7o3RPhqDLyQr<0$Bu$>Bk2*ubs-x8{81!!$@zY} z?KP4?h3#SXc93l~J@=x^%Hom{$YC8?777i;tD=9FroY0a&u%N@ zZ}+BVq`;byq%8apY(a_XmaINOEXm)wd`xw5jw)3bXR4Ws*`)Z}s=hEBU}-d45Wq1{ zI!zcR^GVbW)}JGITK@3}Yi4h+Pn@*bf@~Lr3?vN}t?7CHZ9%L;%Q)5p3|0tAxE+-- zTZ>keDKRiU5Y-}InM$TjkBy8A0=yi4ZfDD(KReZ8v`|n8-OHsMWTy*0Y2nJ3TN*U)TBRf8udTX z3Q0BM3AHZFPR7d8DvvymRjl;xj>Ke272hZEt(ff*N0XHj z79|F!pg=e_&y|50;S({L=%h6TM4v4EY76@2lhIuSh%SnND-}dyIRqzW0g4R!~k!!bU!a2eHBe1t{}|SeK>Yh6+EI*;b{lUHVlVQ!$2rF#-JFhPpO>KVA#ti5k3% zGJ8ZB^<8{mrq8p!Ugzm&01og&&`=p^3_1K6(MB%n8JkdYsy31TroUMr$YPEWDC%c; zVQQ`|j2jc6R)?^lE!}W8>VgdsPFtMx+DbeC5<`W80*%9B0KiA!I^ynO2EMvYVS6zS z&BOE2*DExFXf9uOCIoFW^qN74_{180K6=|fIy4*0#O&46W?wFBW{s% zQE-p8hR?qMRiZQ83R@eep+-k4tiDma&2lMz&oyV+ZR%)N-G-z(=SUd(nu`bWsU%p2 zGwlp8rQ#Vbb-co6xLLg@mU9TH+E5+_%S77%VTQX$w2-Ea(nXoHmKnKra8Y;KSJE2$ zU>LubKV!NA;ICl@xkVP1%(j%0a=VQH#q5pacjomI;4x5EBXpNFiGPUfJ?aOfD`CEO z^JAF92#CTPDy|r%U8&^vO6$(JqEbIDS7qYwjVsbC^=2<|7`;y<^@*goml%&??ooERE{=ON~y6lnAQN*Z@icvLrA%#X%>c>RdF_E^}8`d|ch0QjCxt(C% zrf!keZI;%x=eL1ysYxhvd@e19l)emUnzDmwIq65cR;;qr|GIWX3LOQxzi=)H1vBO4 zMj;dykf)8;T!c51-dYJ?Eazbqg3d?FVs8hfbQ5Pdzu1`%XN)?G7WPrp#;9|QfAIS- z&Q{@i;dl4HDy+pA!QVhBeq(3z)O0%x-&ytVQ&g z(P#rtHk|%uDblP|v~3`{9(8(9gxf9yU{Pn{N*YgG^Tol8Mb|sOEI^rL$QP&M`7a=GT~yL*(ei=DUL8}i^M#k61xpd zN@?nI>K{x9v-Hi%lJ@cl8)Xmc$4qFD`ms~0vlQ!iNNXDA!wj2oYCUYWYpIxvKU^e3}crk8L%*n%{=l1up zPd_?p^+>(R%{QK2?A7!wHc|Lf%=sb_v6 zH3e>MOUwru)x{sUo$Sl$T}tm^Mej?iDxU=g>Q-uwlDA>SMM@0L5`WW*Or^1#j6|sF zir&@D(`h*QU8L_7K$BF@ZOz!R0}Egze;Xu5q8SL5T5a#aUkirnHbCg7P*8L8=f;W00>E9VG-#&@PYB{62SyUfLFlpL2Th?(=h%{Bb(obc9KX@Vzawzim5Nn z$ydXkAkC>1Q?!#GC$*Si1{r3MVFnpyFm{`pTrluT2;UxgUjopI$s=Kjj}HC{S|NXj z*HXdwr_iygSHYtFK1L4C4Mu~7op=@_f`3x@CG|r^a6L{5M`v`0^$HH&7a(M8DI%T( zd)W)WPrr{3S_(P%*kL6aA^Ue*DLYz9O4t!4I>)z+=yhBv$i-7y*Q1@o7ejqX3W0Cn zh_Tq-N?MF5?-Ds(6!xmG8gorEGz{~sx0&JIuOt4pd(Kt#Q>N;M{Z+V!d|p19Pxd+$ z{L7$%eJg$yhPPFE{y^`{+-#7X!VGmtkj?fPL*Oxjl@kQG3t{C-wdKf8mXbFB4Qtc| zk%|?rP+gB&Ce@S4ANGF{l%{_ZVy{R1?b1V^0kQ~#VhqCyW9BdZ5Y3&t!X>ko2>AD6 zC7&yHWRvp)e-=g@-AaC2;!mO)@xsm8XuW(=#gxO)i zhmJ+q2Sh9jiCAtTVMw#1O;kvZWJcI#ID#*uzRwnYgN$taKO?bnFQmow0nCcEf;J=U z^-}2l3?9)P{Av(?Qr*6RTtTcA9<4Yv9w12zmI$*i!WKcD5z4plzrmJ)Dpm^l#x^VP z)$jn}&?0|p9Ay}T;)+BA7>DA$j#dN7Fmk!|p!t-|k<0G`fJti4z$?f&aR7i*nUu{D zi7kTD^elqEXJ&3ds{1Jl(2QM*38fi3PwzXWPF5=5-hvoA>V%7Q*ClqF{^0~=$)57C zV^kZ&;hm!)p@-vT5ne!;DD(^p^-M2XqfMq(#!)LCC<;*alhT?bb=Z*|?~#kD)sg&l zxP+3h-h@~EbrTErJc48%AYq-Qj2K1I!L^GQf&!uZuy=rcDGXzWN**B=)&g8jfgfW5 zOpYCuz@k+EfjFgg$dJ}GN$a*xB5jXM8=-rK3ip??4j4?JBW(;n34cs-Kn-{Wllujs z7Ru&Fq~=``W-fYOV7vvjyE0TfR?Q8OT@>`kp~ykSgySr&GK97c!PXlG{yAVc?F1T) z{L|~%zptJq>Y;_P+Af29RAZ?ftmJSsGb{zk^qB&>`>#G9;p7trU@kvzU`Xr0!-$@4 z1QL1XRrt8yMRIp_x?bUe*#_$zo>x2Hbsf!9U3}#pc3p1oW*3TUnfc3ItR*o4@5~QU zS%ZBc_GSJOch6>rI*r6Gpy^lX;zTGtL6@r<1Oz+D$gD2P)Y8nY3UoQYqv|l|WIWrN zfI4ie-LvvAuLWop;uAMw>GW*2OSR7yz)F{&UP>jOgqD>Me+%Cn@mI9(x0MS%+xOYab%?oxg14PQ+ zCf~$c*vbS)tbZH)M`+9bz7@lJX5_lmEGi5&f%T~lcE1lg+iL81{Sdv2p3~Jdvo*gr z7Q6&YX~08APCM`mVijI%BP1yg!3{vc?P(nf$r=5PQ@cObyS^;^Jc=@U zpB<*{GvIyfBt#E7nhN73$ZpCF)$YGHQ`Qfj2u5$pHO9$3&31JZ{<_p*vb5n~W>rS( z3?CU5ROzJ|RH;=+m*_PBzRwIuzuFoLfsYDP1#TbWq5(pPuve^o34l9*5Seunz(>D@ zl?ph%l33}^v9NLhtj|pSxLtMX$J4a;xErqhwb)Z5-Dwy9f)Le7Z)=fGO47XV>3fik zr(P$|wEhD254OXeae>MQ`yz#*8AyBeNgckA~`u4ZpGge_)mHM=MOEk&S`1s9&`qUxNYF)-I zg*o7&T$z>7ql( zY8=I1Lvu;v_1}19AQ(v2Fng1##xD|B8ZEktM9;Ax{3YlNPAQL&#IV7!7HJcTS7MhJ z6#w7F?tnh))pvou1iu@_FBc#PS>K8#vRaL+dgNSPy`0ZGk0xR}>*N2VNd&nLk z-*3&M6U`WK6wR7K6P3xmpOXx)m}1i_a&6X16K32Xx*fEJQF#!-j^h7D=ShOS60cAr z&ITL-b%=gTuFdG?w;oQe=u5!wtQGw!k_-?p5$fReA$Cj~OK&9Kx$~1WMnz7^pd?e6> zDVwO5EFEdLrNMqacM|*-@VD6bCU44v;mpJ5Vt5>^qH?n6sfj26j&0+Q^cUTSs{E;& zFlqc|w1jn$xgHg5JP$=okGTmbk2QL-#KBlzJ7_@iE*Orrfp z{yvg~aOd*?49GA8GuDp82y@;CcW)%>ydMvRdFJ84a<0W+zB@rUB}YD1FI8Ab4KK$Z zV+`xlSHaz=xsW^;DLeQQ{9S8JumZ#vV1h|E<1;ZDd{0T-gGE4g45l0VDfIvgNPiFD zo1U9D;e$EbfEjZ7mXp2%1!N)V%;kK2BaM`N!RWKhrpgL-1dC7~4FsV}A`1~2aC6ez z6bO}iG)nIy29c&JwvEY%@%?kGEl^|+~f*J zm*j?{%e@riGT1&0l(KtWrR*Xmr-#|SMWy+@rR;+U_AOcB=}M{Yb2JjJ_=ysZ&T2zw zOb6U!{>vo2hS;|Q_@CFB&1UpP{N2)nPopTCaf06U$MCM-pKgM5EL@dg z_Ey-@YIcz9k0S2@wPv-gV)>n2+7v}E*$k()O+6DMUXM4fVsxOxVPbn&VLMIFpOMUF zrOSl;*cS?N$ASdy2>01IN*97n3ozcvS|o<8e>63G<`L?H{u| z*Z3Hwh$GG-t!`+nL)g;RY{L;`3BsGg-uGX&e6C_*cjREY;yA!&z*6q6Dz>n;{Gw3Z z=c+U4&sQ&^7yptI>J;5?!`?4wab@f(`wMm%!%>33Y^kGFHak+FSG^=~kc!!H=p&xAK%?*!PK0oJ(5?!Z#Yk=ZFZtJ`pG z8j5MtU&pR(bDGRLtSwimwi&4~xoW=#{^8!%k6yRtUiHUv{w}F@H+E6g>bFnw1b(I8578mo|; zrro1|dP@J~guW|H+VDk&u?!7qx1td_%QPzV#2j_Do*1T1Lzm}K-(&QnL!`QKppo8I zTO4ceQuH#+D29hX%MYU#0Za!P*v^lAO0GFEo0$M(gmE=I#y=88up~s0cLs{MQDnH0k0Mu#BBbO{ zD=&&7QeCFi*)SAye+!ggaiLUqh-`bTceqn_KuyI;r2vg;Of$gY-A>L1Y-%hct!yPpjecj;Ao@=39~2bskIl04zfC4( z%p_-@zvPcauwG+_2>yy*u-&`h##Z!c-8QvSfmP8H$knyEy@6a?HRd)Fn|V_2bFXm6 zX1n=Hp8&O%7z4!KB~+1(Is#3%3Suw9@+Kh#e)X@Y4RYaiAnP4u8BXl18LQ0J#Jw2g z`f}9g51mPkv>}WQFno3niGgf5G}~2#iZm5$cmno<>1lxI!5p0l_j)T8VcAD{+DD?V zb@&eJzT-B-hX(#`<@Qls)AJSB7{Gaiim)?|lNv>;ab68xFe)-SpEI>0I5HQ2Sqj2b*0me zEleP`S3hb(&zTHu4;zllAi*L&74~A|BZP=y&<=@hEmLA4Hv;W2%@pPXHiw9sd&Nke zB1@R0J6IYyHuyeF0cpmUB?ExK9Rt+rLQ)kV*r5VYgd{#7+e=}*0wDN_Ak2S&(K@T;)E5b@WFENVG7yZaL_^isKYE!2FzYitt$3pj6w~t}UNJjvc$~BK<0cfO z?K~iiju;JIDcr$7=)z>h9`g})5TOS-v>dGYAUrPQ7ly85vCj=-Ag$$?V&{)x9YLA(bWq zU$57M?Ebd7Eaq9k;sX+~IQaqqB78N_i5L02kPH1L!U|*oEb=iUjNrLGV({><1Y-f0 zKU2*&<6%dK-giOOk(m6s-Zy;3kVaTOw&t3qASyPF#=CwLM(kDbX5~?t1)I{7df)G1 zYmz-P6bjiU#IX@0iMt5_@Vr1Tynj&sUsCy_M1FGLZ7;uJP?OUn6DOkmchr<^Mpc2rib_0|v4GzYMuT6A)NQ%6s9F2$NBMj5tgloWIH4 z7=P<>iC2T>EaMTbzWIvu{86g~1n)?}KIqlD*|j1U{rS-!HYh<;rstvm2s~;R=q3B1 z-`Z5@D7*OIF}aw)?Zj^W-Rgj?V>6zik0I6v5#6_JIVjKH@|!5JA7OPSHbNK1O57f# zy#sDcrg*6RN^G@Tj?Ef^ZRX}+bbfXuIzPSgtA8l5lHc{BbpFYP^a=G2Qm)L`wXc*| z4B-VfvDwp*UR-ad;3RV!G6W0|Aw`2cB9>i`MPGCPu-W&wqo5U~J2P zYuNcLoK7qWOllNR@d|15U7E3imR^)gUY0lO+4 zOPgp=iPbHGVkI{ed7+Vpr!y@>}E{hg}_7J=EP0 z%sgle!)Kc6t{&=@8-lKb^)-YnBcnw;ZL~WIJqH`uTAOht(dN~8z{BHmEa27q#;$Oo znb>r%kqu|r*cHRj3W)c#HlTh3(Qi~?11~1#2fX*T{TA<~2?X!W1@HADIvPCqAa<=V zI4jhi|2-36Lr^87O&)**Q%5R#V;sb5qdoOUA%$(m()Gl|_)Rc|*DCCBN~1;!6o1|< z@Dz1Ak@@&;GfNu{_T?gSfhmdXHpsrxcfm24b0RUH=tH6|bB+>Un9pt#Wzm$?!%Tt(yhWFaK=jQ7dA>W)G!E%Ywpch0o=0ScSl8_l; zwpD(Wz%DM5YR|@t?AQ@@9D)oe(2qK+5;Z1237x*yfvg&nA_t{fEPNOVyG+mDp10QD zCrF@m>19Z~FPXSiBwl?6DILUF_;1ewc|VXIU64(2gkI^V4~r5(-`Pd;d}pf{6qVc6 zDbmYD(#wk7e{_W>e;3-kEDr!xXQqc8Z-(=CXx{*^w4z+?4JCHfnd?uXfohj4?ARjm z*wyJZi6^0~lZle9j@J{2k%S464wu`w#&oa{V`Sq9dSo}IL*F)>jl=O3y(&8xt#lcV z=mHl)bKT%{>tRaSz~;nmRB_&>Ay8lI8o{z@N8zp02Nw4dPUqZ-KY6eAfbg3>On(gx z+h)gt=eZFGA{XVV7Zv@;uAVQwJY0HNw);C)j0H>hL7v>;kR5NzE<2@`I(GOw?g8$b z(u%Md5{8?j)bVaO|B&_y@K*CB4UHg$!S`i4Y@#o7)GTwCHtrQ`Xs=j9d&L^sD>Sr7 z{@Xw|7Pos=Y}I*RZ=hje3rVVsB8H_YEu8p@;hS9YjLk@oIu9b) zmd$WQo$rg6?5J}uy}X01pgFIYCh2neG3RP*7jBc*1!uV{o7thTSGY{%T;I2o=d8xM_{| z+n>4L{wx^$8I#N9Mj}U8x8!wDip#pyEQPsg{}IhWIb7K%Vloh%)t?miQcMpv18d6B zShrcd5D&Qf+ojsype+hF=?>ZY&x1MBEV`A#9aAMtGt4wP1Q78`MdZxZ;IZ_s2Dy!u|BC8zR!B6$$>m>B!L7` zJWgLvXduY<-hd>=r~rSC3dim*-)ND6b2Sw&p4qLAP?#ikC1|uxUPtBhH9$A^D`wN4 zGLuNCBWOOUWu`&|6SI&H1HiIVC(nXa!=2N*9KU)h>UJMvHB{q%QMsFe5d$ zUzZuiUlaL{#(@DNe?6(^ykQh6G%-eL@M@5r%df{;Lo-%^J4PZSrH{11@k9EE)$5KO zP&&=Y2Hb8K8`&@{=N>db27iv}$%j3y=PW`3nTt~rzX6k_a!{L6Td>$MgC67D+k|GL zHBSHr{T8>aRmP?tJcu>KC+V%FM#W=BOHD65P~mAqR3N5nX-&<55_*|VDc}HB;y=-$ zHHargcJ!4vvat`QA^Ov~h1Pmh7fDQvpT7W|f2~!c3U#eX#8?M>r^1#pJ!O9dpU!DO z3*;2|0T2LuVf|=0=V{;2Mj~Z0c)69R7P6e1sWaALdWMOz+p*L}LwD=OOq!k%l&0fc zPt<`xaPJRocLV@JT7vNxahf z;7cV^CDn!CgfEEcx&J9he&-+10fpx%VtOrinT#FAm(Z%{P0iSA#b}c9nJ~HGKqI8_T41rEXyeBmR2%WMM7xVebn6 z?+~0EavLR70;`9ZtMqcZ%Q&CS8U?G-D~oYbxEbum5bWb1Ove3KOwfE#QBB9+?{-R< zrC9SaaVFEkEv@sMTQCmO<9`yU0Di_o;9iLou}^hoG7-mk;hakGmsDN84md=P=jJ~P z9wPo)J1PFkZ^Mj}?+j;9hl!=JonLNH(susS`PAWdeoyjA_AkCg zkBRqS*X~e&qzk^oq_ATJkkbgZW*lWWQ1$s>?l4fCbXURE(8?IBPY4PTfRJYHPSu3F zZjc*fFhA5wHqw3`+Y7E8%lQx9`2$x9T5{3g|4a#&EC9eU&s4%!EXVu{DE0v$2VLEW z?>9>DeT>Ey%X7_*BfvTD^ph2_vqEw9r=PUG#y;3)WArz$-R8 z>fR*cW;riHEx>t|KhZ}wQCa~oF4Y2h%Ke$htrxj{f(|3BhoG23VG_d7)W3vU1C3Vk zpQ>8MZ$X@%Qkkd75Z>s+EIppZGo#-x2>;nls|( z>Z=j<6%8Bv58_$S-zVIyv?h$-VM<;BZ32^z;lbBo(IctRO8Pq`J&B~Xp}LP$$-<5s z@)w`l*{#m`a0S>gPAj7qTtx=oY6gG66Z^rB6Io&kmZf$*0)uuvXtMSsD#5CDkarx@ zW>1vki^4g`p_G^LtRza}9GT;f~%i`X3~Ll2O+KmHI8atqY@0@UYG z{sbtuu*YJdQtcPOLF{S={|qFq_km={K%<1cNC1K7=p|>O31rMeMvZv_5KFbhPH~ET zav!kv>L>@9Va_&qGZeN{W^eK)5Fte)N_C@95Dtf_R8U+vP#L}CT+kr)qfF2Be?%(0 zbDyH0^UwnMLntzJC$B~WSo)p;4>*yXmrvtBA{F@0RCGpI>6>=XOiK7O63|2znvmB6 zAb=MMy$ansoWE7s-KXUDAsCZij8*!5?S6zkH8|FtaUflU@a*I@(3=65j2Ql8%H389 z1fC~?a&n{FOB+Nx`PDaqF+$c1a@bqo#;DoT$FOp6qE+rTN=hErzU2>u#y;YF*q4Iv zo6X?q!{&NJmR#?uEG|@so14Wsk><3TV_yTmRUeaEDiElD(N~Bm=F)Y93b89gn>1_} zow_IVnVxCDxWXP5q(G+ri>;Q!j)=wDELnohlI6J8;9&n*JJK-)MtKVm02)!pSfA@G zeB|jRCk}u@U@)El4){{6IqOi+t+XJ?Tm+5goQ2HfSskGo<+zbxdd{QaVyqB_5JGs# zutYTlB3lwE$@_%Q8i)G(&-$*lCYgq{8jWly$9L?c5EnZ^db&Af=troS)H`zhij_;jBXy{fE6~W$Sd)mKlszIq-I&Ewg3%Mf5c@SYI^* zi%Fvj`sQ*RI_b5VfxcC>mE{DHfn8(OcdJx;F|7^SQ5CF|oNAE@?<+P)PaGvqFLiue zoGV3g{oAG3Lt+Fa=b*BHo@nV-0u*Ri%sgMZ&|9pYpatJ_ycPAlM=AcM<+2hhvjDEX z^}_0J0bP(e2;hwG0^80!zoAz2R+s;cRrSUYmiG|85g<^v|AAFueVWfy7t`aEdW+l> zvf0%e>EY6bg;}=G^khCJR!~T(_)q9t0fBx^Owp4ou*qj;4He18y*08?Cx@(1C}lY5qLBCcZ7N_mQ5*PQ4xC1^`ckR z5AVMcJ>QS>Fj@vR889;SK8NO{cliDyes^*cxDM?Qn43YsX3(E)o)&fZOfIk>wwHxLW1U4z`SDKgpDrswKx%?IhhP$ib9VA`Kkf(Nykchsy1i#2 z2}uvY2*w__0LYs~Or9MF5GQ2+2@RG1S0Mf?4rt{!#=Dza=RCn1o_0(q;A)p!iz$e@%{o{}qa)Z9HgCj2H|}1qJ0mXnaPFO`N_E z+q#H_-@)JbE-+>Nz@&W(n4*4QzLEXkXs-}3m<Pr!vurL16u>mMa-=6q@;9_AC9MSR0M_(pugS2nZR__<|lb%7f(?C|u5rs^VO z(9)ktrX=r9l5=U&_WB&t(zGjkZPnW|6Xj>KX3uB$0nu1u5(ksbQ{0#W`wJ^ zY7(1~TN}Su(z{OL&L<;7pOx#yxeD0HZi<&+Erh5dB?{YWKod^c8ze&z@B>dAoH2=u z!5aAOScX{hP73$-QVe?lKp-Z6J0FVf(eH=ox3_bAe87n_fOBzSjF2q?`-mRHVHGoW zwVl5U93ZY(M%1e{3%fiN&QgsoBNYdM+{c}Wj@PGk+0?~9WTU!zrXv((0eaolBEnvs zYbc*(cZn$~l=YK#Z3Mp*z{>tsb&}ZvH2RG3h(psxqX>5G_*g4bmVy*PGX*{(zi4CB zhiJAB&6>@LW%z4N60Vhi@AITx3ZAm&3Iu_hb0`{rA<#q7I=DEaSrkrWqFO)AWB!uk zCW40x`N@M|K0Sr|!|a5<#%0&eRw`O7p4g(qva4b0SCLaCmffaAq1w;?l@JDJWB(V2 z0rlg)RqaB0TN5T`4?qNHjsSpC(M)=)?%M(mY3v^?*Hbb4n|#13%&0Q}2Scb(K8{&o zC+B{bohA~D@Av4D#N^#^V#5?m)9fby-U zGW7486mk}baS9(B1_#^qi4O=9`@vfdkk9rTNIcS_V#;t{@)bdyePCcg0#|*%{0^?f z9cM|03Y|LYLPR6Ul~`$K5JxBJY~oRzzwO|)PSk~O(8KR~FSS*{kHbwuYxo|7=c`US zTma@A)PWGH- zmUgamDJ;}cpKBo8X>JFCl9oVb5}!;*u==p#`JL12=bddze`t=)I7N|BWtQMx-Y>XQ z_j>&oxe4K(2-A75eK^d4BYILT5eFT#@(`CA3)iz$w--qW%lw#Nr6TR(1!0$Qyo9m$ zSIQS-=n({+LbbYO9+p6^P$VN({4DqYg$m)S3^IRtJthXn*0iPk2ZXSqiBcUYl-!4} zXs+=9ACDI_l#7PYLXdfrjbS$eF$v#pjP#n8-~0oh-?v}1s}=GNyal6P z<6OkLPie^zrSkX&q*~`3jV%70_yD8DU077F4V3cjaHr(ypaNnAI7Dj!AV3k(PW*Ae z09HXUPL`b@9m5@cH_uiWYX?%MKd_BTO5B< zT#93st4DT7YBsi29XQskJQ{JdMGCj!4iHORytV;M5HL(Zurc63#%>-3X<5umSSzYXCsw#w}Br+SsUp>3|3JR@3h006xYH>0V5Ct7y&cIjz~$eo#~w2=Bh8g0>Z_=LGf4m zAp`}E@=;)*s}$EEVtYR~lHXA(O@HII2s>l48?co6-&j7nQm*;X)?FI=J+=T$xy3=L zS~spZ@X;+DE}f(^d-Q%+Pm^1!jiLgPfd0WLCF+RI%7uP`JRJPe z+tQ$6{2j4WHtj;*{2I|&9C0F@>M;J2^|cURS{Bsp=xu_-f?;gu=i(iTgwXP9V`v@% z30e$}0wS8rj!xJNpV@{BQtCc`U@UHZLiImhk5YZc4SKs55G1YyRnd{`N&2Z%2&-qW zBYq$LgY%DLY#$`;rFPg$*_(|Ftko_1F;3a#RmT+WVXwoJl*XGXFePW%=+OJbA;X7o@Qx6z($4eUl{ihoME#qFQD?#Yanf}aid-U z&rbZ`h5C4K{NIiL`?OBukz~A|)I3~~no$FPtSWfvq%TnkPfj1*^ruhj=&sK8*%EUw z8Q;-;{?D?ilh6-YmCH9n$xfbk68bg>6uU`a_epW}{%H~^Typ|FUwO~a))0ac%r!>F zj99u4aw;X(NQ!~4_lvE05L;mqTkvF)*rLC*VxyrB1A7EQg8dzBk_0=8GO29(Ao2Ea zGLyuc1n~xDG_Ug1|3SW4I!}LmVA2-CeWag%N5Wyx=X448K9V5eJ|ns$3HQ2qfrQ(N z7m{#g{HNGbPD;34x2GiB%E1zDS-*t478oaaw2YUbmXL4{qai*WU(wt|HN9U-Thy@} z9c>K=IkYz*f)Bz8#9%v;8uL&Gtvf=#d)4Ehk%;xEU zR7cL~r_-Rwws~=CH9^?c+w6F?*jNUCcp>d*DNKeAk7$ftd=fZjkj+GJ`VDSaJAE10 zLYwJI`SS$}fxT|SIr;~+o2kMP_@s!0rqRd8;^P!H#qrUJ4?LCFB@g!Ct)f$DI_~6~ zks4&3kj4{Am+UW(IL>(A$UxN7uyH$=^ zL&64QR@^Qj1)HJ-r)17{NiT~q(WqpMBHK*waw7nF=*(RGb{8E8wp2}FN?7VTWaS*6 zo8o=vimL?%U#45GR5am8ZEL6tGi^rae?${FmjB=lc)ZPM5g&>dORyxiVvnlO1d-N1 zi8sIVL2Q{z`lDj!3gW9T63e;$H@L>6$#m+U;OOl%kM1^Pf2S->?}Tt_#F@>Ab-~hj zexc|XyBjth6t9>nTcXPevMN;y_t2gMKR}9LENAVnsb1$SRx5@C5nm8Uec-YTxsmLT zo?roZYb_jSwuVT-Q2BCfi2e*8G@PH}Dc286)sb-tgzVTCj$LmL#TNDk>w^VDL$#l) zx26i9fnqeEUV~`O()!F)GU_PiW>o2;D#da&?Bc1ZOw_rY>g1u$*nv7$g`=oSbuLd$ zOC(nMF2ZYJnp`Ayqo4;pL{eO;tp|>kin;GX|E^z!cNFq>NDuu4uWaG(r|Vrb|3{Dn=57;cDa_13CBVR{L0jZ(4CUT z1K8wB`~^iYG652e3=AKvCHo@l-~t*+j`44p2xz03IG0!_-YSb%zpLJYaXt5lX$~Hg zqK>OxU7o2<2-Z(ZwcHRYuMb`{)bNM>?`v6gCi@ey1@K`03r3#8AZ^9{mxhD)do=-B~8*zrUL!OuUq}kXci>N8GhZ z7eHc<;$EHjK^K{XriYH(gGH}@9TEiKZUf=?o7wy>I3f=J(lmdVL?kX0Xbm|&imob9 z5`RURx;-0cajH4Eo_h5EN{|Z$LEbh%km9ydy$>`w6^WIye~XI12M2s3X+(Jm(v3lv z5MS|AM4011m}!;8Zfz*C(-Y63TcXYP@JwMVNt>M(Z35%)b8JmZ5@%+uAjx5-=g|l0 zO{)7f3V=W*p-6*ekOGxZH>k z6}$WEYtG8(NaHe0mD0MIWC0kUgTH?RXp0bt-Wz@aU4VKTZDgm??x8gFOGp7-FO(i6 zMcSB{>WTP6KV4_T$ioG&778uW#sm@>l={C>U18V)+n&Sp9zO*)-n)n#`;qC1)sVo& z^|XA=j+7+gkBC=rYFk3aeuLh3rI0<&y#as!Ld}#LK*l?unnoti2nB~Da4{65(%byme2f?;!|0l( zwMWQ~=ux*S{^QHDxkmLT5=J(Pb6Vd~c#?j|RX(@4N68D%H!lKiK_Bm3FP4^we&vV$ ziFPfsR=_us@3T^bX}d!BHcaQWdxS|VOyLT6eD`#bfb7GL-wB(RFSIkh0NXv`X!;54 zplJw-nc>A9pr9s4Bdzi13?B?$V=T4T0O)_n)Gs$;gUACbNx$NQKptY)M2EVV0YG;v(tUg zsXZSV=STxI0}J7y46;dK#@P`#FV*a@zEX5$A8uR$pz8KKaIxG_iUon)k+;m(`K_1{ zh-UptQyZcC&(nrmIWJrZNe>5V&zjwIs@y@`C)wkUG~P;(KDx`U=2<5YN#8 zv}+T{5YtgFNZ*cG%Hg1dqO zP$%Vw;cKXS3Y0+}lgD9r!oP818_HmJV+s^-byB1vj)J);7{+M`y$gPiqt4PL@$ynf zZ96Gm2HjwWBHu9hka_~RmFrxpeJ0f&EAIB%Oc#2I-DSGe>yaj*u1&|yT<7zP2f%K^ z)(B3meFtnA_pCVpHik?0Of07L*&1p9FFX2zQHduT1^lkwcr%UDL`}j0j5`w}9(C?24!1%CQe51NXOYBRzq(6h^fn>ygYZ zWHlX2M-L0xHacW~4FEA=9Nz~Oot_hu&kvI6JCe_a;5XdkblD@74kg4@*?q@Of64ohkcqk(2P^!v>_DP{NH8QZ0fY zU>xmFb)ZPWyaiTsi4W1?X)O)ZRL{Y+WLNh=Nsdz(j8e*)dC47Ot}%$QXpaJyY`Aj1 z;i^7-DfCqzLgD%GL=j*_+Db~3tFaLEodL?g26CM#Mb89&ksSo)ZHajT*|$j#J5WjQ zyZwPZdfy$Eim&(GC5bcYdf(mFSp>arnOdRuEthIDu>AEt&GLcheJiE9W;E1z4#8Ar zw!s}s*OkH-3ucRp5VtG4j~ZSef)FrwyTGTBX|@G%t7!&&Xef0ge>+yZlDHr3Y$8W2 zAy;Yyx!6FZi)3+K4J@#G=cQkR6Od&Ea_pKT^+De?#%x(cyHQ>slx0BoXIIc9@UO2; zA`GN}6)g8`_2TB>=w(J)^s*EN6Lgh6AxIWGRBVnf(rBv&1=MjZgXklB`Os2}e2l4L zYN-|6pS3lhW|T^suIe+!V5;zNi?ku76?jh%v8&+QN0}U~%6nb7u$6}6qE<6St5uE= zi`SX=W^5Akn1!p*dSySt3}zpPTVN60uN(UV|Kpo933QPu#A}ASw~y6(>QXrfMis)b_yHHLddryoy~s{e7^< zXy{+GzTmp)WW9!qs!};DJ?z+3fpZGvNgGcn6^OPBHJTphN>m4L$F=>$>zShyzl1^`bL+1jrz(ol^!Qwf-c~aet7@C;Bi)gl7%QJ}NE-?+xkuN3=2#FZOk(#E8B3^@ILnsmy*Gr<=Wx@PKXf*#*6v@^`i2DsOMuZc-;N>o>ui`W@ zvC^ll(@5qny7QZ#T9jN3+J$WH({KP_vkZMha^UnWBJFU_S=0j-y!?e;Ax446XN@T` z>kVR{0lK^>39SVvvwlj3>sDz(V_nb6vj|{y{6NdrXh#sp7NXINAQlOMO#Hq-iLOXW zVMIY8%CHOG9HzyiT~0{X7i{gW#96xJf>&r3?lL@SVUmj~UC} zL?Sx2O6d@3cZ&kY2&!P>)>Jd&Ws6OMe#&7PN5hn%@5GL#A%V!s5osY>38EEzCeF1g zdQ}-vOj0kx-+Xl<{$7CH(CQNfQXO5Dh!$LlQ!o~(sl+$di#l3va<|ph$Z(@khiw48%vIf(NX-N4E2S z!qG@uR=9-mH=^=Tup_9B#ahJQGuB9A5rc#AHFIIfvf~ z&@AgCP_)#iNVRhSC&dT^lD0=;1`^<%64|i*Ao&7Gwk9k#+JeE>I3x-1RdzGQ7~p=7 zcEk(>i*v?fyc!*&0zMr5J@K^&1Q7T@mEBGhkO?>-T80b3O zdErjn35CY`9kX$Fqf`Y>`>QLlaU-s*YLch73CO-h@#HI!Gz4A;nMss_$|Y5aA%;v zJ&>tp(>+V5$q)Pvw7%7No5u0qVq`FukD5rbek3#a7WQj-!kh#l0>veCt1M|5dkIak zc{5VK2X!zu(=L9#0ihl|NV|Oq?TI??YbElIs|fMW`x#n=9z99Djv9Cr4bXL5v1N93 zs#5WVz=eXCu?(sl&7fLhgOI&NLe=xWh;O=vBBBxPro_&eL2YR-qTx%>Fg0n%=pxa{ zXX6u>dA2(5fE&~fxGl^C2s1#>pc`;0#$_PxpMI^#%d6K>&kKOz{Q7ZK({NA4F1}+fu*(k6wjFK?s$#_27=u`cXDso9v42Y^iyDRfSN zc$Eb{ts&v^OkO(fMMxW6(2>ihQh9LvA$TU;oHYO)9RD_d9))HtpHCrsIBO)Fo0A)m zq<;#IZfC z^XHI30Mzvt;3Ft0wSf%u)2-n6oeJR?qhL|^cGQV@aglEdO_8|FF<)Pqo32e}0dI*HS0SmMlC$VBtYjiRGD>WL-y%Sg`zPU; z6B@Hzo>m(;g9%QH-|>TwHJSB2GRKR6KAa}HaSQ3Bh@0#LfnvuD%L2bd^aM}~cV2NZ z&UM5djMEqHYNW#whf?3T**qQj_yGxuu99l6Ma>A4T`<|C+7LbvdE(S^BGIr5*V3F2 zAwWp7YvMe|*`l9+JWVY}|3eS`-gK8#*MqkW@IIh-{Rw*Ln-RzqN$XQ;j>Yl4>eHIy zpWz39*(?9TmnOC9^wjZxf?QZN#cPq7O0J<~ltwa~-}rS(t8^_=jQeVe5mnirR!3=- zHN^-L>Q8%+(ypy3hGx;9_ESo`qNezlgVGu(?Yx@em(m8xp&gqsx~BL=q(Np95K?e+ zR6xuAhhP?#Jg%dRijlyB21Mb4B%~-&ftSRapvlzgIBl7K&wLi>CC_!DUCqgRpdEqx zUHB^IAFk^C+IV8rFCueVKbwB$OdvNl&tY$H;KHO&2Q%r%ccqy0)+Q7J--@HP4_?7W zqTi+>RAM_{irUqKSTtr6Gq#g2qN)~)UM^hcf<U!Mju9_)ZRku zM=JW{Rrth|pMx`xEr>~=RxJbs2C-;Mf(ZdSz@qtwpn2lXBLFfVZZ+q`yDec8dI&tO z@P>W&HwP(h8pvG;pDT_F$og$W#UEnj%B^(x62sr4W<;XcWZU8@{Jh#fQ5y~=_w&HZ z6QxJuFsvCjie)o|a=6W|!BL-~n61*wg_QF;zvCtvIF$U;3LrO7+oO(0$oO-C>Qi2I z2>uS${zQ!oZJ7yoIJq_odw?dX_8_3B_QRi3?H{Tk5V6@fEYjgy5+O^tnRc3wz?01( z$@7Yk>SnXqRPCRqqK%2#rM26%JZxFu$FgQ%w|XL)0o%@^Ly+)^J`!i$yA#H61Z$!H zAuSp6Fa`n{+Ll4&q0Yt~_^xSQb>_68>I@*{GHGKQe;7N%1bdws%^b8=-{3fimZIqPM)KP+EzW4B12@!0&<)IXYl4h?|au zivU)RIEgOQEdJU_v|2$zmRz6oZ-U}KynLQg0Y4soZOdGK4gAH2760xk=n>oad)UoN ziu|HTEWLZ6T_MhszJ%M+D*dc#0HDmmo}G*-kK?CR{dhMV{elI;oh%5t>iNIwW&zXl zlS-kQS=~ytf5&(+$xwyh!y~m`C`CQ}Z-+>!DZ++0JqwiG_;E>$IEcGHaRL@e__-q} zJviToW}%s2BCnwZ?hqsECZ-^Z7DRQb2Gc<3rc3*E(=V}>pnqo3A*eNLY4hM~p}%ZG zI{iu*GN8@8fG=y2gR}GpVZlGL7=xx?UK6~IrrC=#0{iPw7w5C_`2O?R-_|9PVXCpb z|5){&{Xf>TevttBlJQsc2VPTPQ#SqJ&j&8}Z9cxSwUMp#f=@f&L^kfEC(Fz9Ot_84 z1zpDUWaAZ)R^h_^re`s{QK|Psc&E}usf0I>K(<;@1WF=VGWds-Nu5e#VY0i3|3E|v zVxICApto@E8+e;XUJCgenIYmI?3DG^CG0NMK_`wYlxc|iER5F_i+k6z zH(2+sUz3Z~kNDw8g*;8zT6-dnCRj~@QSkJZ55Wa{wp?7U3;pk!Y}~j~l?egw*o+%h zsw5eA1L{pvLjLVlA5ssvB`4K8=oGpPeq|9Ztq*@f6W`8%jDdk@CYI(SG`fRQ>XAZp zB(Z?6iBIV5(7WtH9Zcymg}+{4!W~sCK97imvXH*SU?1VDz@WU<3F=X(#_-IT5E+cWwrp`8Kpw z*R8pGTWo<0u#w_Wr|Jl0p2UyDi=(onB**1R?YPhnyjZ;nVO}!+FXE3rOI!MSmdWqJ zTWTBm*gv350wa(4i0i;LSB=MD*IbZw8)E}KEiToCE^X-Ya~X@?7BJu|?`EY7agA?W zeog4<3AcKIjz5#=&sh2+=|=-vZOGq^6BLhZhEJC5#!Y|hEh7Vd3nLA`S<|u}ZQ7!9 zw@hjR$Pi=dRWg3|rMQH4!_@OiZ15PWXO`H~@i@Q4=EP%4iERiT!(j5~C488g5c}8| zDZh$58=S$fq9~YBh<&iW8gJ3k9dcc_I=aExupYr?9TP)~pRSI{HBzt*Sr}PB9W8B0 zjDzFq3%9;49iSkcMkQ_dBzyS~IV)KXq7UW98=0u%Rx|K^1`6_Jv(SfwTuW#1i-AoG z$C-F*wb3kd^BJJnmLOXZF4jPhg>ayxw5(O=3@ij=e3h>Nw1X=+N;&S0CYAA7%FqZ-1D=(mEi zcG3cE8WbZAd!vPXUZ+gYRq&a>rn?_w;Fr=siW0vEeuZ)MB6iUJOEcyI zY6e!?56}ii-(`Bz$s4m@`#V2?9pYA74hCmDCi}N)L*(jR0b?i~mrcj3OJQ@nSQcMA z6Wt1cZ|v_W85)Jn+E8X6K}|o96Rcl_BeoS_+1~?9QMKIA>Qm}N9a0^s;-OmjR-Xc? z$+h388p{gdaPc;iGXoPDYNJ^l%NGE^nj$K#mI9EOhY=}50rD&huHZK<7%HQy-{d=C z^+Sq`snl1$IZksU7_bfH{~vqr0v}~@HU3X-B!q-bfJhLOMM0w6!bOcnBuh59!9>DM zP*D-+wGpMMvgoHO^CGiPpRX3m_+h8GcecM!V_)z(NN7mJ5XP@M&N*Y|O0 z(OXppbor+*-k){gOrC`8@o7tVk5(%EY1ln;yv#JcXS1XNoPjA^H-`+sAWV@;FSjC< z?=<(?tl2Gnw~9`7n`2@*^*OsGQo0+{lG%Wxy}3}H?)EQls9V0|t>`}2Bt}IarBK$Qmo?oSwW9kR zPT{s5JW{Y~`R-5t@|5z$qoMei6kF?3~Q^TwBIddhb$7?zpKJy^oaM@xx;}x3CX|dV91k zl%w`DW2tL>uUHC0UED0%Lm-Ca+Vxi{n!iVO;SR!b!y;;T*03Gc_Q9HGSmesYE21eY z{lk?9ThI%;yus%A!XEB*#T+^k9(PqAT4_!!@Q#>iyJ^+#n4%aSGvQeOaR(awaXbAq z?!>f}+pL6!rsx=VVp>Mp@GEh1}+&*n&%h-7HiB8!m{ zO{^|TjyXm}_Hx5Ol}IIY$)43mHNHd<07o_aaW8o4B4as!F@pW5_Vt!NC1@?YM;2Wo z&zAXFhMp(MTy7aMT=rM=)6~h<^m{`rV!cHO|Mq4P*4H>>b&Kdgym?>a)sdy>h;tp; zwvq~#fmSg$!R0A^P0B6uPPhMA{dV)Kdd6iPJVIm#a2QA6RE9Eq5AqbU*QOtVL;O^` zi*&fBLl5R*-$D1keuvdef#oE0C7eb!ntvcu5vEfj9?j76Z0@(Y{M+>VhP-Q#!}Nl& z1msa$EUfdl^%}fR=K2Qq|3hdadA8rJIuUg z$}M$U15lp4XUZbrYCfNbSql^4sLBnbHCEm-jqzWdKQ_SnG>el!Gs*XgbKL%yvi;j! zfoC()$B$7AN<+(9AY1XF@Wf?{*N;Mr<|gRX@kLe^QSu@yJa}G0HZS4w zxJlQqu`U+P4^nnn;|ah0jF@&s*e|lWZ<6wh*v;EBSpMw^%z$5)HR+;`xe0Bzpx1~T z>4yR@@@G}Z=`X#QU}J`L5~~ndZ%J7+o3_Nu3`mNnivuYGNmmk{t)}`*+h1mVcQqO5 z_*CnQSjbLuZj3zDnzu^w33K{kPCv{k&$P}p`&ps;$01z;6{3D(zqHRhPF%91XvNeJ zTkYU2n(Hklk*h2GFGvgN52A18uUe?`-6oJ;)kr577Q&Vi>eB)*fB=t!> z-VTs@&yaf8Q*)_o#I@2F(QesP)-{|(k4g>Cwre=A!xmwMY;-K8yUmySJ@MCm|CJ}& zc_7=d`c9fRLg$#ug2UUQz30hw(;n+0IrXqxE4M$qE!^uU@ncbAh1*({4{wX~#v7|h zt!Ft>u19Wbj`B@4NCff}+~v}ieMORYgqxzJ`{&g7c6~pRG;{)TWAZbx(dK zj`6KWJ}w7wdDMsql_NPa){*Rv&G4++R*ji#uw-r)A6qgo=lJ7HdO42m-T9`*@Q7Dz zf+UuVF*`x*lEuy`b}3{lL+qQx-V%G0F)qPi+bXtgzTai9vLpp|Um{as zs0*o1V`BC1hJ-*Ccia#IBKi=^B#in@UCIn4Fmk zior7R+v?|Wna0Stc!;T_-oKJ_$^PsZYv(fQ1ujjn{%Vk9>tTa9t=}6Y#k$KNsn#7D z>0#YsEHbRM2Ju)c4U%UqHppyip+WMkB7-cjt};lPHO(LuR<=QwS{WMg3(c%?245?9 ziow?lKEUA8&sYft-za#b!KE9r+HRE6_%{pwp}}QbvYHIuAo$A$-!1rVgEtEPguxF8 zzS-bSg5P6sOYqwb-YWRb25%F*+TbFcu)GG35qyEc(VnQRIR;M_JkQ`x!QBRz*{79e z@KnKv8(fYKTTX+sfK^r>gL?#zF?gQfM{m$&uMoV|;Bs!(I%M!_!4DXGt>AkNzFzPK zgWoRr!vY zf^RW6q5)++U~rG%8x5W(_-zKCE%;i4=L^2f;0pw=FnERFMFw9g_-un$3!Y=}wSs3D ze7)e~41T-dDF)vt_yB`%5lZn(kW^HPoJ7b}}B9 z8IJ`fs1ut?V>89rq+qka*o-$eXnlyk#@GxqHfh+*FgE>+O$IiTjZL(%@nDl-Y`$2c z3%3B9%Z$yt#-;)rx3Sr8Y?fkkp|N>N+vpAm%Mr%%cg9kBA}pQ8@~6g9x+E-n8_R03 zwCQfn2S5?@&$E{%8|Js01iG?D}w*pSou zNIoLCujkrC>z{ZwSCF3JqS>>diBbD}gUJvNhszwO|GKb=>-u!R@M+)WoJJ?AS)L=? z5Ed)n`|GoLl1KkmO|I|Ly=2up0Y}NIui6|-o?|kMf)-fhY2Q=Xj|YzF--?`w7dRyG5z-&{r9N;`?dc2 zmHzvs{@d1RR@x!|!$c8BOywC;1%1eW*oBd?zTrlv26n!W?Wv1zAnf3E7!L)txN#+py7=W{ ztczb^z)AzE0XhwT{6et_3^|6hUHof(zoIg&!vZyxr`1JST>jX@{{1x{aC!Y1@&n?X zCx3F~&+M8HBD~XUK8W;=tofju_msf1-gB)lZV^fUDR{P4gSK#|YseSu{&E)LV?eWr z60!QHv1$RdEW>=zm|qfenKc8Y!sgJKIi4d@==NhkIfYT@&*Sp%6_N7F(>4~_4W4aH zJjVL8oCvaxGgd{3w{XsF))&O&`iBp0agy2`liEx`@G?PuAnD^tvJ$bfMWdb^c|A&2 zb2$?c>#EOe0~1Ywc&66Jh$i z8GIO{^^)H1`{{Ari)u^cKS0_Gxa-t3?LrI#70j1W{cY$QZBldi#*%7`&mDrO>dF?3F$3G+wzbkg3hd8YcuY=29b2Dar}vP z{JX?xIduDGKUSY95j9G1j);0g$4N{-&>~eJI!uln2rzUQy~nm}+sWC3`H1hHiq*yK z5lA}QPE`)t@{Ci9M4u{=YT48D&~`OlOdj&wyKW-Wa_^IyH!eTxIJuT;wf<5U{({r0 z?$cCstl?w|Vv_iDHu3^VZ%P_S>qL(E6KRt5Nxg8;R2U>~;&6jF$hpj)XKEi!*N7Pj zX4L6K8c1prYjIy<+&6{XyJ`0WLHAk4eL=|m<9j9imZ1CjASfOo;`eZndO3p(4Km)5 z8wdS41fhQL)WRA$>Q9371i24{M^^8b(43)|$H@jSr#8vjp^1{m_ZTc8?Gt({@SV2sUCiF1c$j@K=Kz zp!UdpoS|j#4@cL7NByt9%GQ^yudT`{$rE(YrE#Y=cxqsWzkSNbVVy+Y(UZ*s6wiGs z6TNPtc&_F7@1vdW9bz)`!A;Bu|G+qB`U_Fz*eKWEQH7`fyy$b{0gb$Sn3ORW?In)f z8|>F&=~*e5^;3yVh8J$>59*LbL~LC8&F1ivZ$R#_gB%(OFUhQn?48YShuj_*C9<#P zmXw@f`!hL)e=4tRMP$o4B-}&*=Z%tS$sv6kAGiJ_=vcFe9#Kcxqoi)m)MFeR&1+dN zxo`xF)a=8HZm%5ub=G_tz9PQn%Lv~o{-`|8bG8ifM|psC@e{?=+j@0fXml(Bl|xn1 zu=So*NM`LcH!p-Jv2uLtcVwgG2SW5{Yv;A#b38R)H7&`6S*}IAAgfyVNN#u{d*Rd* z(&|9c1uo6I@RzUrf~c?WWTHyDf6m%-mp=G1%v1Aq)8fC1&12YD7we405tBLmlq&sx zn(05RK{)Epe82>Tlik*yI(E(@TK;Cm1RWxb!)EOuhpGNz_Tk#gB$}YPPa?cyo-e(m z$#dkh?DPhnFWpA4(DS9^Q4>dF*yD|{?mbt^Krj1}oY{I+4@vs0*D0dwAkj076LN9U zQsC`Y9Rr^z!_(bfd*03b#u@7VIIUCvz~DwS5^PEB&m3jmp9sdDh(BumDiYH-;hm?- zNghtVpx9y%SFt$sodp?XO7LDcJW&w?tr6sTP@2_EXI)Qse!>YNDzteUescUAV0#z! zE4TihQDNIr&Y%BdpeXH?^J#gxoC0^P^E%RGmXMzjemJA?7$+{n^|?#V!E^pY>udUj z>#*B__P%(u_dTbz_g&kY3V6;Mmt?k`o((5E^-&{8WU@c93GdOOap)net=oRC`*QU8 z&0#j#AUskZ6@kwSuIM8rerWU?i$Dz&YFJsvm#XW}v?qX^wT8mvZ%lhUiuaoCO`{u088C>9! z1;1L0#!**I5l*6LFu#Qx?|ZEKlJ$NsjIlPCzs&|EawDb#yLPaETQ%aKg>+bDn#G0VS$_oE0WM3n74be0eM zCIZHhmnmmEZbsL#Vn;X!uAuVGOga?jb;QZ7*8F(Q9mhp%$`(j^`plw?~pl~6fg%FzY;pAgj z%P{et=D6pGL-XKi5xmVXJ>Jd4$?d6s#7T?eu^aymJ3B*N>mmnd2X+7-h6c-nP z0y|mq@qcYML05elpdD4d;2Fe@l&5};ghy43dsu^95MxI%{`LE%?&G%UtC%vg*EKEm z?(x+BRQv~$CNP_nDj&rNKyBloBk~Mu^%OFz@}%!{+#E;#$=Bm@^2ub*v3e5zn?Hjd z(&Qa$4g?D&k~{73WW^f8phmfBc7#g>`*?Tr6c-gHcZ~JW%g5WZU1RWKU8++aKyIvj&>E*|9*_Mn+LY|N*2^#`^T@Xf zB)$!U*D_vmcvObX;C}mDo^jRk1Jie7%S?SQ43$GU_Pn#>-Crk~in#piKbWzunb{=TrZUz&A9&8%FPFns0Z&$7C_>-X*YhR#_kO!Zy*hQ6e|ev7`LtOD5gW=h3M##5KIQ6vh(tsAkh zB~LNh?L@^rGCg}8p{iduPPuKTq|^Z z&Wf|>SO3POqm$Yo|3JF;jtYo&eX9bZH*0isT`C|7h13d&rf?Fbg94%_Xw_6cW6p63 zh%WhmO##u%v@7WO?^HlEL8{xTLN2BW#z@Z)iCz>gto@f15NY;l87Z;qSlSg3U1Agv z0YVChz)?VS$^U;85Y@2NM-RMN#8}aY2#!}kgiZXXt5^UF@j5CXsvQL%{I?Vk{h4Ta ze@@5Kl>(x5+I>Jr_Y)Klop*={gVBpa&-Op6fM_Li6^}n_qfF{DWLlipK>^Vpkx9U7 zCs9D;mTAtvrhsTUlRVuTzK;T;R8kkuwgRHVZccliTmezI@hxOLxdNhFj)VwJp*6E` zD0;W`(0;`h|Xnl%7EjIWeAE!?HP3Vc7;S|%`y|$ zZ&OG#9)&jxyd(J=R7kX5wA=J(sjI%QjPufgr^Oi8%!aur!bxZrksye(xfo=fQ9y)J zqCV9(h)yC|v`7F)vy71FBocd664~~sBpNC9MJUu0Sn8-fU0}JR_7s7rB&=G6s_?;?=0uO|0rFj*pKm)CkNcW%!rnE{TIsDFJ ze!>Lq=1L5mRT5pJJ=iLVrUs)yC6VqpX;)e$QJOf^oLnVQvI+PtDv1swU?7H==8p^# z*?h<#Va=}#0@0(J_ZzG5=G`DdwJuc>nbH`QM8C$PS~^4_T95B+Auf20we4K1-Y?-jV6QcD79D zwNj#3g0^rUnBxrFnRL$oIdO0wLM{k&R7xakxwPZ9bIhLYcdWT?rX(zVtRkSTq2g9@ z$(n0%`uKO*JE~fAoK7MOtFG2u+={g}B24I@lc<;0s~glwM7Q74*ZPJthW0wPmr2=U zRwQvkE0!b!tgrAQIeM|(>s(Nwn-s6py36bl1fp7Rl<=<^RkFQ*jDOJ{3kl!s~1Htn7*Aki8YD*PW zv*`SFJoc$$&6+StTLZ93SQAZ;z5k3LY2I5@oa< zR=iBoG8zG!L=m{ zJL|GA&soP zYBeGE_U~pN$op5Mx`AiX3B7EWR^XAw_H-RPDiPvIq4Hyo>z z*DaPZGDVlvv2_}a${>9!{8h4N{q-~{Ioo|A64{$4h18EZm+2GWTnyK`wEXeer4#^m z*c0ZtAbtkfM>fu0udVN)BEeI)l*79D&YAXmW{7Kz9%wn?%DS$%oL%YZMk&G&*#wD1 zBsR!w$>htH%mRIzNu;lG@SNA#nMNVX-*1hcCL*S*o3bt_?BhF=6)`tiAEh7>?zG}I zt#r4wX5((C`HkK$YWaiXQ3pdxlhuTsEaT{XC}3`r+g~TQQCu}&hOJ0-rGL6?n5Y4v z0Nfb)X#*mG$GhW`jy-sw|C7NcAYzJMp2AfU*puE`d6qkEewf$k*A|iqN9}oxX(SPR z*uMEJ%+`)_={U|I&J%Jf%k^;lh``Y30MdD2gOy{>yL1-(T%MJC1%6LtAgP#~P!xTT zq2)gI8Mz?VT+Ps;`;rU@EZk;wn=08r-0yZgiYlbF8RU2(qSY&gsA_INqFLHL?4KGu z>|e7ZgWkj5w+zO^CBP>%AN=bvnZB(nz0;>yTfUZe|KNSpo%y1;%iTfI^moZ@9FN&D z8^>cJvte@n{bV+ry9mjE-J5N!gWyxive1m)X4H&8j99mz0_03s-Ql1 zy-{C{%AUb_@Jj_-J2EBFI;>^KNAB~N@wu%}FM}7;7U~HpE1E4vrZf}_duH%(nYf8e zX_IbF8|~&KOge|)l(@{GJf5>GT5I@yl zc7?nCnnBrU+RCZRs+I>u+Gto1@|hCXu5kfM1l8)IZzOC@+m+ra zT3z%8?T)%=*)(&bY{UK32z-hn*fK5|i+Jepjtn+f7#Wz~9g1<(9H!Pwn48WC9^1-k zPQukzGo8aMHBY7n7X)=pr|K9baF41}&^zs}FMs(CxxnWZjnnJ}wA|u$Je7u~N|_G2 zzhUfwb9>M}%@D!_VhY2Y5}pB?$r-o8#^6ZOwO>W6oC+9{6O1Q5rgXup}c-YTHE8_^CbYj&EwDtCHd z*(=Q-$eg%CqOgWmrtSJG2|xwbNxCG#l)dBFT`gjPwcfpU#^B10Y$5I zf!1pMdkN{Yo!%6G$cZKNnlFgF-u0&z4W*dH>9Wsdlq zbi=fej4X|;4hrsK(B@6>ce%*}b%;-8=E66y=xD~5=qVyPTL z$k)d*tV1livm?Hd_H=mV<2u_dBQ)SHxeTK%XNEGWlYdoK&y?J0oh#YkoD81Uyts6( zWY&9y$*i+IvwtB0&6;?1{Y4xk0C5`LnNEiwf~ovTtRdhYe8~XLa4p_UfaY`Yq~kE= z7Ew_2Oif$1H?O8`fj4t&8L^_rBYEp=keaq7jx~vdpe=vcqd6L^#C1W8b_;2${xGij zW7-K_LqhX=AdE20a^Fb8I7(bKY3KQP7`0|;xY2qYsqLE|#fLbKwH=M-YjOPC(R>Gv zTV%*4HHPbTVw4Wq7)8Cu7U_wNQF^B>()-qX-ZeIJv8i`CjbR!FFeVfpFc~OWg-~(k zC=F9hIykMZ-WvRcu7u_n=+4R7H|O}6327DAy1=?ylJ+a3$WhYsA7j+?=*I}PT$>g`pDki~Kmye4Me8;EFkA1)(it1&*TfrCeqAlz zs4y35L@%ysJJUO6tF$R9?98n)`vB>q**krksiav%8q+dWqHdYQ->{Ypp?@@b_Gk+nQ+1NPc8&^N2yETE4biFa3%3^tJg8feX zcEmCqMSt3!ait-nT8_ugHtH8Mr}cj_(?o9oHh zdJde{NA)HdI-J2Zfec5zpWZ8{@W^EUfL0M^)P72HmsCvcje^Hz zRH~o6+uUWPt4x&zQeQVXB1}!)nbAGA zCO?j5(J)&E-_({@w*4bYrbxU=Vk^6`wcK#lrC}#h(=a51S1~bTg63w5`492D6?!Y{ z`4!ABC=fi8FFa!eT(C=qIk#@kMl&%-a>FTJBQ?uMH!AvqjmXSrL}nr_3m=3w)aG@> zE2fB=?g1|ULxh!!ldL&cw;vq0<}ki*Z(*@ClXXpQll9rfMtbI|xv`IOtobuBpj;|# zD`FUt!z`XGNB?_?GMIRz7;+5b1*`8GBnI7x)kv?buZgsJd7JVpkq?BVT+&%r6AeYm z*XN~(37Q9dXIpy+Q9t(#j`7R_LqiiXGTBz@5W0CLW=<`NJa1P749x49Z4Bs1+FMpo zrq>*Wxu!UUA@fqi;91D#WYa)vK+37lN(&x%h3+_^p9XzQy@YGMy=#`IP~x!?ABp^i zbKSq96fiD0_djfmpF*TA%Bu06)9R6y8yL4@|~{DwMO^#9Z^C&J5kx z2yH||QK-LKfK0Rksrgc;evppW>g8oTR^idSB4f_eG!~q|1KkVxbSsg3b-qAN8K@)|-e{sR|lHgSWqD*e5cz zU4wi_R3ft_&%nZ6iw2)H_9IW-D7tE-X6If2Gqu&vczV(Hbf@vOU5x&ZrFGuy@psD|_MyjrEPMYq@0yv zWVy>)C)1z6PVMNk=yZchRz-tvqod|liOV1VVF|OkE!32<{vhS16gRe1l9QKkuyfMP z78JMlioQ^}bt79io6j+}uL;4^R^dn9s=p*WeV5~AFRd+ylUyRHlHb6b^ae+b?AaQ= zp&QFF2{5^rmRYzjr*80W$hSL&XsPM~QgmOyE{E4A#9Q~PK;X%6$z^?9H`b2f?DYxP zk;9qd{sY`|r90=b?>^nE=;gv1zNsQ^uP~OE(3hX%iFkz!XFIa~7D#%kryf3gvR!CB zHY?bjO0#|~%@C89-q>@&K$g(fcGovDuic{+EpoAws&-nHm$O|f-tINtnty?(PIpi; zDhe5;cTc+7BcKn- zlkS5NSSxMw?{{sDgiw;rJly6CR0fBW(yX7U^#*3K+*;-C>=TA>Ce5$x47l#sXTu)zCu4MnQcES$%TaHCa!ab zrEwZ^PFPHMgKO2hPzI6vlZ~$ZU!mzJgWFZJf!KOQ^AV~gyeR_1mDec{ZJnNp)j44? z)yy@YL(`#3TZLJrg|(!1vR|$3!&{Q^6&ACyB_ZfeCa_7XMgg)fTI&er5yB$}`!@_x z4GN{XWI`%5hDkQ#ZHf#_eXWui!7kbQY&w^oPEim$)*tmWQi{4TC@xC}bKmscZ4d$$ zkKHPstV0+NM@^kWA$WC9v;E^t?=xKWo^b0iw$QXHVk@^)+L@hRKkG1w*c&D_prO@? z){_|jL;-s=C~4S{!X*C_`Zv}CdKhjVBhlTZlV z{B#0x7A*C#gLjT`>Y#3VvOhB!x0rIqQqR2LeYjS;ES$iwrvcVIKeVgkjevp!Sg0u_OGMgV7eoyB%vj zTG7w#e}?d-jTEP?Wme6zPO{K^5q%G@iJ`Lj*fH~jQ)5g1$A-ltgm!A`r6seZ%TGWVe5y|S~yohC+=(+@K-8^kzmGPA|+`oS?XCI z?33ivzj3U265j}0^z1%E)Twtkf8M^nlirW@BHQ14yg63N&l#LdydJjrTdm$>B}qNR zjP%rBj%Ih}j=QY~7HcB$bil5bWWx#VgMu}WomqK^#Po0onP3C0vR-%J00l`;SzebnwjV^Q;T0?)60IL|vhFq4468Z#iw3)Q&D&$%V4+z0L#* zIoZ*rS}o^wiq5z|yZ!zc>y}@1;ks3NWow!pWhfsKP+w-Y&hOGmhZ@kqNy^qf9ak`9`w=*~&R|`^lsh+DoX)k~sbBFrlJ%Uwf$le+pw{7$DuX8=tEJyR}SQeHQ zHOt4LvDs6|9bT>fmGyNkn}Hox#zy~ZtkwLnN%6S4ty!M0w6clcGmAeVqt>4ME^Pg| z8P*0nvg2!&9#L5ZUBzT18PI%*Xv06+aJLN) z+VEo=Mh-IJoHo43hSO}gz=pLp{DlqwXu~IM_<{}Jw_%$Nm&rRr{C;4=;j;71FU^K- z8_uzz*M>LQ@OB$MV8h)ueBXv&*|6uCCf*bqUSz|`HmtPaY8&2a!%a4P)P_53*l5Fp zHhkZPZ8q#S*reCThNs(bqz&CR%(LM<8!ootY8&2W!@F$wunqUx@MRkwvSF(Y!-tsk z2iWjD8|K(>o(-4T@Mas{Wy2?I_^b^N+R(CLn+;>_dOO{QBW;*r!z*pL)`q%r`P0X) zm!SD%@FJ%ueV6y74XpURZC+zw=Ww$>F!lomb?x5K|K@97zEaFGwC3`)azV2-!qBZL zGfbyj?KZGb6{;%y%v3YfBsD^=HtJu{JX)Qna#WUWEB-E1*(y^_QEqMPQ66=nTFAc( ziAQ2GzanM+4OdR`VE#F^o!DG&|C9XXs!`g0l(v)5dDzL%WkbQ;s+gP>lg>Q;R*IGW zU8c&_;x6o`;MndH6{NFdP;s#Q>XJOWtV&f^J5@;%TT01=g#EA zn1vc9UGXRBNIV6^=OZUYb_gu_P13n~!3ZH%mT(=_(zvse*3oon+F;o%1;m%xsPC>5chcCkA zjw&h|Wej<+jmxl(au*jCFPv8#VwB6u7awPyQs^xg=jp{2-k^iaH{Vx9W+(f~bmWtL zi*&`iDk@8*zHJg?GMP#LP=$pwqFk#rSlDdLy76>&;@e2WNwy&^7&M@=f8 zrwF5_7kGV@ML6)AR9R|c&}D(IvMOYPUd2U=iaS`$@EKEX`6BIWy3d9MUWrG-OBjVe zg&&2xB%#8>BO;@^MaOiH?GYE>(~*$at9PHIQ~Dn(TX-@8CQ}U)xn?3_^>Fg`6 zylT$X*UZf?m{(X-Trz(_=?|_gTezsa;=0NzuW#{^rPtqZh0rpJ&rU#a~$bvfdd%yWc)a%el#`Pb1; z&{g;;n>KdINnE90nF8;*w6CsWm`4AXs>bq9;v7LdE^=l15$R8yeC7O=9z^n)t5eJY zlTsCFyAqxAh1%}|N>l|_z+VX={h9PP(l<&wETz=*F)h;Vw^a9S9pe)BQqnBNy^Oy% z*#4yT#Ol^%;un8KxEE@7X|a-~lhmYNapJOwzt@vTNmbk`_$M)%5T&>*qCT8ZMoMX7 zU5KspluqsQTJmr5?xj^r>7^E{h_OujDOV-fNqkbL!IDY;)J~@nnobKzTl!S#bDS!L z5up%Mr8*l^3Gpq$EM=BFiH&fA&{IluBBd7TJPHSyF+j>E9M&)037ZZT7#C-npUlD&SGW1B;2Pk~n47Q3lmcY)Qek*-o)w{>O#l`~LZ#OU`Ak zw3Kwcv|*u8&?Fogti|@!g7rOGT@XsItNJddR;9j7PblrXT=y2zYZlW-O0QL{V+it5 z5SsFg?!-@$D~VD12h-oR<;*_!JC1QajY&_m5v@<}$Yr#$44Y?)LgjRqg$K3H4U4X(zpm zjFlCb1(#7kMmHHL4aH>iF{6VCBiwjAjbsfbzYJy8Te8z9zovj$$BE=we$}?w%xaWM zwasku=wIV86>)cEgjo1M0q zldSsJ__c9A-8Qea%>!+716w0u;7;3|XPXDv=KMC}zSK5n*yi8_+G(3_u-%nyma~KM zYdd1X%P|f49k9*0y6ww+K>CCdT}PK=C-r1{y-YQXe@;e7X{pj8&5SY!Ojc^bB_X#yH<0+68@q$}eS+udECdv2r&Rrr7L@=%%`bCq!mtWkt#F+*INckIuBb+0ilT{M6K0 zdB~5QPR(L5`3v&-DYdj>DZdze@G@ge3?PPoV*Jk!3OG;rmqI^i{+;M{qK$`|`L=(x z>coG?`(LHn|AndV_pf6Nt5y5IaAZE;=U*_q^FKUrLjB7K_&>}6VXH#_j2is!{u``8 zfvdyX|AmKrzkk8-Cvx<^YV%z!KvL?%zhH`DYR407#sA-3V&kK;|L<4Yc3%mq9XD7Q zy=(igde!Qh+BG-*aBbZ>|IPJ3`tkZ(ZvDw^KmFOyZ@=RgzufSvJAb|LH+S8A&%O8E zzv;KX`~3rd_~V~8KltZ|9)9G}$F^*J{4Y=Z^~t9iwmrRl$1^*3?cVe3b9=Mq2aWd3m{^ZHI^&MO}m{?<?4!$f(Sz8~Eb*E-4Pm8fTR* zDk@(x-CN)-MIMU%%&OwbDf50%T>bjQnuVDX8+g3caO^i}T7Wd=(*k zV`rjMxkxb!<`+*aUur_mME;k>EO0C3|_T2Zm2 zqT+=4ob1e8#wYtXgYiG9z*|t}EUv69uXL6!a+VeN78NciuDsAWL=OQicS1Z%7Lg{|Yso}A-vV76P;ziz||Mql> zD;Jh7qH4$uRRJ@NxXxD&A*u5Y?DnmhChIdgL}S7)DfKRps;%-CRO;COrD)shOP9x{ z7w3aI(;1TJ{F`>vk*=Dc9sL&->niW)$7Yk6GbW8NJFFf3>y(F{In-HTmqNIuV`x%1 z(f^>Kkglw(e2L~iLU*d}lhpI^HP$JWF48HeobQtgt#YOmFQ#WGEpZkvtnglc_IIZ@ z4_2}}jRG=CyDSbdt1zT6vWWqr>L~bJI8z8 zxRDh_rsFeYI_Y1T947XTQN4@eRPS*;RPSky#`uOF6>p3&`|B?vF!_RS{RbwBufTgE zGzpsfjfg*Y;0}lC@9nAj7R3`soN|nft?bqm*%;0O-kVRqPtdT~NEJH{2|;DIim)DG zst36X>l3T`jB}_yV-i|>HpMl@HpEm!=Xc9X>=�?dYNUd4WaURX_A__M4W}D0!0n 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 Qk2-R&?e!Iznn2*c0V*jytpET3 literal 0 HcmV?d00001 diff --git a/winvenv/Scripts/pip3.7.exe b/winvenv/Scripts/pip3.7.exe new file mode 100644 index 0000000000000000000000000000000000000000..aafd26ab4e780f9fe8c550657c81c0fb198b42a9 GIT binary patch literal 102791 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�?dYNUd4WaURX_A__M4W}D0!0n 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 Qk2-R&?e!Iznn2*c0V*jytpET3 literal 0 HcmV?d00001 diff --git a/winvenv/Scripts/pip3.exe b/winvenv/Scripts/pip3.exe new file mode 100644 index 0000000000000000000000000000000000000000..aafd26ab4e780f9fe8c550657c81c0fb198b42a9 GIT binary patch literal 102791 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�?dYNUd4WaURX_A__M4W}D0!0n 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 Qk2-R&?e!Iznn2*c0V*jytpET3 literal 0 HcmV?d00001 diff --git a/winvenv/Scripts/python.exe b/winvenv/Scripts/python.exe new file mode 100644 index 0000000000000000000000000000000000000000..7013af8388bc0ef07e9f41ccf71d12b772435424 GIT binary patch literal 99992 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܍}bgI;ZmDG-`ZwoED$J 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®)TJsEf-}sEaM=JB(?@Q#n0&1_! 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 z zkX1XoYOM;8TGUKpi@)?mrXV_hYZf78HYbz{me$S68)o^=-fMqqbx>Q-Y`!HFSl>Dinlr9k!ciSH&dhZ?$MG$SUEr`Ul#_n}KWlHf`H|9_D z1kX(i3`Kf$t$d&BEqx-gm{GHZG}dUnon&OT{ci?gqLww!6Ga{dslDJ&9g%ttIu8;g zL#HpL`KopkD~HamRCuloGMf~h;E&0HZZgQFini2DiaH?h!b3Bn7gZF0>?s+SH+xhC zH(sX*mz)^v-!aYK-&?h|iH;=i(^5{H*{l%A)>{0+jk>!c^%IxlaGBKBjEd5UdDSbW z$y(j5_S=(WNPH$Ug<9Y_I%hO@;oE#8n_Wt=r5J4831s@~CHaZP8X`BQU}d!UB&l~5 zb~>=1g9ljYD!^rA?pLk2~VCd`u3EGt~p@@L0px10ly7*K}-|qi$3Vs%Un* zgo8>|Zji@Vc?^+9VwWr52#F-bq}QUjYHyC%+_wlhb;1!9czpaX6I^le5ecSWdBo>H zD%=9v6Gyf#Fd`>uQ*cfm{9a^Zyf)^EWX{$|za%3xM}nAZSYF|cQe5(O$9NYelN{{Z z&8QhK(QNU| z>jPszlWET#nQB#b#0?%#AJ+i;#jvi}TjCB;$JM6K@U>bcHz=!si>XoC^C>POq zv;8&1huaFuKvdBqKzEm02!`~f%BJ0V%3v4efKgKqvfvWsC0Cct9)$+P^j5)2J0WX| zxVX)ZUY0{&xl)LnbuHcy>~uF45;N?z%CLeB1w7a)n(NyD?(plWv3E- zN1W2wPZdgeB31e?74zxHs0^&}Rxoq_iq z0KP2gB*R^r8RPzvk!(FJjAu7Omut8l5KtFnBjr1m{&6=9o2_-u6@1zsh!-nJxFZpb z5)nyX%a5~?NE-E=f=GC6UE=&*zq7*EDFqMmz_#w@T;dX^kRInKn@NOisb?%j&=Qtv z($%7+a9j@Ed^YMkfZ^+=9)@m@-Xv$#`YDuV9)1qrkOUU=&u$m^I-P}rgxZ7tsaO}) z4}A1sm$+)d=qienJ2W4IRvZjCe8jlIMXvl#-Nhm#&v}cW_<^O)_lVLb>-uY{_(LUn zV5!#4-P~$JW(kf!BRJ|24_WQXq|?%)Eif(x27TIVCRhp16|7vQ8Jhu}%Qxe^Ip7Wg z+I|hKI%|wb6usO~ZG-ru`%u2)ZAc&-8n}95PoaVF{5Z#me5Z5kiSpLMy1m0M zzW)U<+Lh&Z}9`7OPqOp*xx=Ym70K3+#^RvBDuqGhRA`Ghnde|u-VSI=BVo* z&?qir0^jop_l2j8caML3!&ejFPc&-EcuvDGHDIf@$4$%B+>=>tN6WP9-6+7Es-%Qz zkF^m3lan;g@|G#zkPiir!mdP9Vc%=;pSkxu^sOeZ0D^lC@gt2Aw|yUK%n)L>DDl3o z-|&`^Fgz3^EKZ$yN(WpL2QqUilrSHG{cAS~h8t85}<*iN|<( zOiHq!StDfIpyc-#GK#`vaCUIUB?z``N*KZo@z8rGcL1SPd_g~r z>xbqg+Y?^RO5!DnS>hLC41@j9Qj$7zC3htK$(Rsp?zDc$WFn&F^U}58LRm)(NJ#y>`4zgre<1OJ}kTtvv&ko{l zs~!jah2=66;tI_!y*rCKUnIs7oPUbP!o)c3mCy8M|L>oiv2jdC_q zT~=tKa>stInTnR@c=5~?SXRtybBJ7(Z6!Y)E*3fvZ)_CzgbgUmFE4yUM9 z5h1hGb(N`Wop->kV5M72taOjJ{UhlgX~Pf6vrj~&y-Ey{qpguMJ&{op1xw#(V*_oS z6_OPB<)h+v1&_#4i~laAL?$9J^(ycNXQ444C@D^$BykB?1gcp%Znb|t%k>o+(9+g} zI&OY@Xi{mPM0p_4Jsrj_e>MN?epWHOv1jK(-AJ;#`^xha?yK8izy#p&}WrA-?3$1qQ#2axF&6Vu= z!DVEHzY^E`s0l~{gp&e{Q5}e=!%NufH%Bg*o#HGAy8WJQB(($t%`uEUGs6**bXBjy|nZ ze$7gRX0J45J(TcCHFq4K>=6F5dX)WqUK~F!P%pP>qQt7Xl4)7yjt4Xt_~q7w0xoyG zuAnT@UZ)Fj;5w4t`6+xnM$&ga$&XQ9>zq%4eBViM;=M}V&k^bUODCWDv-0zIgB5x# zR7G3tU8lOlJCCRqj0HcfJ>7^&k_X1pDW11WbKd*nc`Mu`;;@L(=Vb5+ha5ScS*!9N zP~%-EDX7pH40AC}6&oeuClP;<#LsZ!Ysv|C3V4v4RiY|A#f7kW0;@0-q5R|*Z*VSS zQ->q5I7EpUNZz7)N3+5Gp=lc@dWz~NdO~ZB&=-J-t#&@qqK4-Cs#fD`ZLX+(jpZp5 z@z-wDyiQyqLm)-QY^`Wa@kLhsuJZzs6`*Xb{K}M^N~z9k3a+zR)o7oC0W`Y^&hkXi zX1hRx4mvLil)(Sf0_ts4-yw#gEE{= zxy-pS_$^ASaH-&#VYZfyb3YTJ~| ztnkVd)Y)26sOAX!C?#O)fMVZ?tmKQaw_z8Dc6U##l zMo4BmZjA$UB_2UpFET!M+QZSeSi95#<{}a}{dhpu`Hw08QC{@kqw=mcERPn;@U9{a zbaMgR?54tYM(A0-WuOV`9;%pghrINi1GkRYOJCzbJ#{|JIDsX?fKTxr>Xf z_6^bqfw@kQY#DGW^mj0zH(Z^_@VHKdd$=ow%Z?W;K;Tl?9};=PZeAGc5xWXvkdJSR zOC?_+`C_&1j!aX##f3zo-4(!K|F>M)&Q|;2d~c%ta_`JGy8(ufXjvE1daU*3iMDC8 z%B5XsRs>zSi|66*!5YZLQGM*I9+K-phNHjO>27#b7vv*Fq*+^{DKN{YhDrUD*4%qo z+L}TNH)`*0wf*SzmN=lYqcTUWTO;Gx)eT21iyHj;p{t~#dhial_ydtBP0X0H;HGnX(%#tDNxUQ-rS7`$c{xLripTMOQn@rV0Q)166ZBZCTE9ae?RDC z`-_8zy7}cYrOs|cAAgvJp4d|xx(rZ0s}&l1Drf(MclIUDeF7c|g}rnQ9FK`OZV`|e ziZ{42gXpK;8!ic_kuZ2u9+!>`%QtG~(lVX+XCDvKnpv3XzkxkdZ($%iVL-6OUVsiZ zdS!7f2}(}llEh$bO39$S+2`u_iWxvCkCg4AwY3umm1JfFdT0dr40M9?y!eoE9=qS^ zIZ4hy6mRxj{eZ{)om=b^7 zY4JThw2@0+jFPIGxcOixWttWTqWL&D_lKkNQ__6ca6Fd19nGH06IJ&5g}zsx^&K(}9YRu7Y%?mEL(2E}&Un`>aW0RMYzFRrdA6 z5{$)vx@>+n*aM1mIqlD9aiK~|IwT!n&b_Thl70H% z5y@U6nHg-TKUe$cBH#izzBhSnlEf#x9?4-c@*F2&O^)I?`rg|)T}^z^ z^yH(;O>Cof)xh@fRr_v;l})%~rDPMRM(8K8T?4YK$8f|h)&~`cA;8d1ayE9ccD)$C znvtxYtxr`~2l#!Hi;deS61^}==wp(b$WL7KL&ol){-x_gCQvR=KI%I_0i4d=U>p;>99Tp95gHP-2>t4bu5t081@nn;>Z*(7R$4!I|= z?4?V^}-XCqnt3c=Fmw_Pla6+-UAG9qp>Sn0FUZx|{n?rregzV<~Yi2JS6k}X@x zxmef<+U(GmGYXtkVTw&fFL8dB?~pE*o9crIIk1a(;Ak)M3j^({fMLE5chEQPC z$g0T0o|=2$+kHEwDeMQj(GA<)^d@8@K1z*HUn$MHA*1-q%E;_rXee}B`y?-_I+jr# zb*E*geZP(!qo%9K{9=NW5#4|{!R+EMy^(Q80boSlRCKj#2}CA*A@MgUUF=`hWJIyV z^Jdrs;}I_tK{qg;A%yI-3**6$y1|@Blwil*H6mMfPnj9nYdj*GBeNc0vuzt%koc=K zUbMXSteL{5eHs9S_3;#gk0`-@HXhuoIpg^0lCdKJa!uiHH~W3EilU_j?yiVKd!Obc zn(ZS0w{Um&uYq)r0}&>c07Cz=1!Fe#xgGCme?WTP&+U5B*FFVCW8Y>VE^$TyK#{(Y zPr;5zUH`o+Wx4%}Hhq7C%Zb{ysE$JQ$D!`iJWX9WHXbbcBMQs=Z3Ny=%3l<=AYR!0 zWKOhQ3u_&RTH`|fFWoZq*HF)lLmm1{sQ(8i7sSZC{NE9?Pk8>3o&DYv7cu)Nuw`8# z2&1Ns^p2mInEpxik97OzX#)Q{IV}8jFhhG(epE8;e5$Vhc(}~f^`?RIIK-A%ihb(GB6O81 zDB2T04^dO54QwLV>Ucl))L^aU3tG!;0^sa%E%bE~9lW{^TN9!=uh!IY&H45E!Q2!c zI>~YPu&WltVim#&T(Lr2kbLWVjTsC&VsJR`U=M@igrCa3&ETHN|=Nssb-H&Xzuti)8K(R|)cTOhV z@hlhvnrk90!Slzt1K?j8fdPQUi-7Ln6*EZV+4W}XL8-WT;C-JJDDzpLAqS1YHK^Df z&@R07nAZE=B4TU3k&BbPsc&F5%CUhp-qNAjQ`=Uu`lu{g%egX4q0FMK-c+_|Z$~su z{Z#X!(ng()o$D+USJ~(pHdE*pGZk5~VOkg5-Jr=h12^RYo~$9VYPupe4cK$oX1_O9 zTM&L7nsh$nQHi^1bgo&gE45?G_7#A{&2~~Z(T1&;1frmSm>1d7p(L)OJ_%(ccfqD^ z@s|Fl`fF!Ckz&WSVwBFwp*P_(BA_?Rlt!qIFjWPs9{`$+9gt$7}m(OW-N|Rl)AXrmA(75I(jScA(@Uw%3tCfOXMc|vuSd;LH11oxil$_ zct*~;8yPu$NESUu7|y~|q=2GiakAP?%T9=p>~HIL)(^uqW9C;7`AJu>_G>RD3dvH2 zIMPPLS}*M_IL386tc*ayMRa?XRFF(qxU_S=!b>y);e&5`?0BWu&_6XYYxadY*av!h zFlM`Ra*--`SV)y;b>S)o_74`3j&d9AyPgmsT)gAHKv26{=Vgrvnw&4TUZwgBkkunhP1t0Iu;vl(y~86#YT;Io=_QcxyqR04Bk_;iS5C} z%ljg2NXXX2%hSSWBxJt4lx{LYodM;ure+k!tgmHqp!;OimZ}?IDqf!8Eg9&?WQIwn z(LRG}$&BKMS9wyuP~nncI6d1s@T=TnA!S6Q>G8~o`R*Le{GDcI|LlAUZM1jBCx@;? zBF$$z1ytI!a(C`3c8_78+=yh&nv9lZR1As;r@umsi0M+Fk7daW3A0cxl=}Dot=4pp z*JVk2eJMV(ugbs(|tYkmt7m9f6jvacE;(K!XHwy8_J`!c~h~;8>V))QWMl z)hO(XJr(y3yPjHgS-v#d<9fSNa;_T&yKJ;yW#?U*h_`K;*l6$1W!>H%v}H#*s_i20 zo_L!7=nDGcyl7e?W-c*NmcIz^+a!1Y9ttgV95r_SMRGbno6i5O?%PlPILiJIFJuO} zJgM>Si_^|;WfxW{%o}Ksk5YPtzbAbvOdFU-2yL<0I67EVXH{>rsw@;H=f>HxykYJ|BpOPmHQuU z+e@B!+fI*XpV~4ztLJ0hWHeIS5YEU&zBoo$;$uJPNd4grH?C#?nH(HzH+AhE?1Q9< z1w_cGmu9z-uEI1a<_XW0+c7-B2iNkG4Wl!=jsZpL2NAUCcTu{`hc3=Yl24mm7hhzof-cc+(ztBu8n_H zWXsoB7nIiaqc}d^f*V`dqdndWf6W=9kjmX72c@Fvt1gZgGlpUu^-&ZjyvO5t?;$U9 zXP(q$X*_H`VbK*5a_o0fABS-H+Lx;zb-@Yt%h)v>c;& z*bxVG=0O2_J6~QaDLA7H9h(>rc!D$XL{%NgWZrolqh@ERRv%s6!FXpynP65`5K7y; z8rf)9??0p+xs^CHNPRfE`RKPjlj4RAjcV91p0cE~pOXA08J$m|_;~3U8oF2!yWZ36 zMU(}Xi{ze86;wAjSq!YLMtwhZIZE-rX+Lczp+Kj=vl0c```wy`<^kX7PjQJtmUBW} z&>XZ={|SY~^m6#Kq=;owyqz0wVg`Afe6t|N2Src1irJM!Unum%mTY z$?+En!JRA*uRP9{$1(Egpvb?Ngw%9cJ?csBdl-fVMOl6VN%lZuoeT;=8XZN}R!Z*6%C#<@La3NU| zivc)2QfR-j+`VH`Du}>!9Y3qaOa8Z*)(@JipbYt&W7d6^Zbr@;XqFzn@l+NT{vN5d z=mf)qGwqbg^c)3uG>Z<1l32_aBbj}j`^9SW{@I*9L{_|n4_1a)j6(h@*FxV->Q*&J zNfJtn+q)$sUsbm5iLw$+s9QN^B(xF98o8CVH2cwG@EATk+ZernqH)?5W8rY17@-QD zgs0!cW>qY=rfY7}MC0_m#{Axd`>f4!Br|JVe*j>KDhoMG*Ej2tIQw9wi0z%FE|IL# zN-cx46QD%4+w|Oncei+&->>%L-x}8g`n2^%4s7oFS4Xl67Gw5;mxq#Q~`QhqUv6kE+-n|Ar(G%5nn|i69syXfQMZl^E14B(N(R zM6qB61ra;Kh9ccfgmqbrPkrjMKHK9x3yMA|wuDdugsK$90*cRjSrtU3NZJ4QoO?GL zV*P#od_HWZoH=vm%-oqXXU?2qK&>@vViA+cu7;e_f zl=~*qdwsYh;a(8gXIE+8R9dF&5O{FnqS(UGdUS!-tXq%Ng*Z{59`3|r1^Y1bCJUCp#zUF~+A zuI-9z*BJsD=grJZWbdY1!m@9eZ}>`%VYcmAEa!rH+SiM(uNU7? zFD`Q$63pc_Dy5Wgcf@@asvOhYM|vprd^_DJ{g-@U_PM}kSV2PW?1yEzy;Tois=_fj zt~JkUYm0C<3tW<>C+NIL;=f`B-*_aW(=GCf?ZteAyo1cv*y_VRkfp0Q%(IrdeK4Bp zk?^a^1<_}v31c|Q(Q})_Bx4`nrA0C$FYiuN&!=kkpft|O?Cos2li&?+Ht%uLjtI6` z>h`GU<5EB3k9ABi@gWpJ)$?6AC*$?im4puvhOk8i%(%fOj`Q*V5Od%-SCs*RHg266 zZX*}l?x8|^fVIV0dED#$QBrL^j__+{BQZzi$zV=;n+t>GmMnVF<4%&WV;c=-b7-O6 z2}`skyy~h7)aJyjL(&l7?4%oY&e&=`bgC98J&*WeaTj7fI7$>*ww24c<0v`MP~LA5 zN_;}eqzpk`b}=x{S*G=O9kY;D=WvrM>8`E8LEa>DaX+o?ad{tpn$irh zJh8W&#A~P^yid*lbqcq(0TMi%9OyEwaqw`eG532Z63OU_ahwWao3Wr{1l-w=5%B88 zqFVeX-1*=d*kUc!vPprn@;|{hA4pm`Nd9djxtp@lr60(x!^4{j7B0|ea-5;~s{3PyCT>+I9a zLK}%qkTJJ6Wwd2CldgNn52i`Ep@IRUR+lx1kTQ2AfkZc#TMIRQg`ie7?q$SlM3Kol zb2D8H$F?|h;m)C_D2x5!^Xyo!7f4JCW z#={sJy{cUC2^Z;QqZ|S|>C+Fe2>^I&k1sda8&TH*! zDzzfTZyn+?sh82G=B682IjF2`7BMRd4ophFo=qa2dS#h>#kzzX!D*BYmXIyX=v-7l zoVh49Nvh79*_$ugD7%(K)pW7!tTVgzvGpF$YSE0`-ZI;*GtZDUCe)8x1)@Zgjf?4Z zC@B@!Th^(v5!1&LhFa64tZMd6#p29_vQvT!?v+eU9NK2yB|7@IWLDwae>}7Niqtwf z`bg?2DKcYv(y+KzGYLdI4XYN(1>>rqWf-NR=TIQ=(L^B7RAc>#MLRCS z`wMV~Jkv{z(mVk;bjtK@9EU0FNk(Z$yO2?Oay)QCJkZ1rMA;{28Kp;Pp(6e<9@rfZ z?2HGtN#IZmqjVJktB1~F>OG+zOeqW(o6kc2bz2SmVUsFJ=&HYEAg z(}x5G2CdtT(x8@xZO629a-b_H#GhyLfJ*!)NSj;9^TDM<0kxI`wn+TqRxLvJ%J0eg z+ev>Q{6f;jM(G|#%Oa_QC|

IBn=xZJj$gZvk_mr=hw*s8{snT=fn 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⁣C%uFvuE&x63krx>+_TZBF3RSo0m$Cp0&F1aHeW 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�ANp#}JX_(Hu&%j>9UdS% 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

O!SWK)rs^%`@f2)@DkrFV{B@ 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%0A%0VW#KZOx#HM2H7Ktu2rdq3`(RL$DQ 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 literal 0 HcmV?d00001 diff --git a/venv/lib/python3.7/site-packages/google/protobuf/pyext/cpp_message.py b/venv/lib/python3.7/site-packages/google/protobuf/pyext/cpp_message.py new file mode 100644 index 0000000..fc8eb32 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/pyext/cpp_message.py @@ -0,0 +1,65 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Protocol message implementation hooks for C++ implementation. + +Contains helper functions used to create protocol message classes from +Descriptor objects at runtime backed by the protocol buffer C++ API. +""" + +__author__ = 'tibell@google.com (Johan Tibell)' + +from google.protobuf.pyext import _message + + +class GeneratedProtocolMessageType(_message.MessageMeta): + + """Metaclass for protocol message classes created at runtime from Descriptors. + + The protocol compiler currently uses this metaclass to create protocol + message classes at runtime. Clients can also manually create their own + classes at runtime, as in this example: + + mydescriptor = Descriptor(.....) + factory = symbol_database.Default() + factory.pool.AddDescriptor(mydescriptor) + MyProtoClass = factory.GetPrototype(mydescriptor) + myproto_instance = MyProtoClass() + myproto.foo_field = 23 + ... + + The above example will not work for nested types. If you wish to include them, + use reflection.MakeClass() instead of manually instantiating the class in + order to create the appropriate class structure. + """ + + # Must be consistent with the protocol-compiler code in + # proto2/compiler/internal/generator.*. + _DESCRIPTOR_KEY = 'DESCRIPTOR' diff --git a/venv/lib/python3.7/site-packages/google/protobuf/pyext/python_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/pyext/python_pb2.py new file mode 100644 index 0000000..1e75eee --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/pyext/python_pb2.py @@ -0,0 +1,233 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/pyext/python.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/pyext/python.proto', + package='google.protobuf.python.internal', + syntax='proto2', + serialized_options=_b('H\001'), + serialized_pb=_b('\n\"google/protobuf/pyext/python.proto\x12\x1fgoogle.protobuf.python.internal\"\xbc\x02\n\x0cTestAllTypes\x12\\\n\x17repeated_nested_message\x18\x01 \x03(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessage\x12\\\n\x17optional_nested_message\x18\x02 \x01(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessage\x12\x16\n\x0eoptional_int32\x18\x03 \x01(\x05\x1aX\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\x12;\n\x02\x63\x63\x18\x02 \x01(\x0b\x32/.google.protobuf.python.internal.ForeignMessage\"&\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\x12\t\n\x01\x64\x18\x02 \x03(\x05\"\x1d\n\x11TestAllExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02:\x9a\x01\n!optional_nested_message_extension\x12\x32.google.protobuf.python.internal.TestAllExtensions\x18\x01 \x01(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessage:\x9a\x01\n!repeated_nested_message_extension\x12\x32.google.protobuf.python.internal.TestAllExtensions\x18\x02 \x03(\x0b\x32;.google.protobuf.python.internal.TestAllTypes.NestedMessageB\x02H\x01') +) + + +OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 1 +optional_nested_message_extension = _descriptor.FieldDescriptor( + name='optional_nested_message_extension', full_name='google.protobuf.python.internal.optional_nested_message_extension', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 2 +repeated_nested_message_extension = _descriptor.FieldDescriptor( + name='repeated_nested_message_extension', full_name='google.protobuf.python.internal.repeated_nested_message_extension', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='google.protobuf.python.internal.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='google.protobuf.python.internal.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cc', full_name='google.protobuf.python.internal.TestAllTypes.NestedMessage.cc', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=300, + serialized_end=388, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='google.protobuf.python.internal.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='google.protobuf.python.internal.TestAllTypes.repeated_nested_message', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='google.protobuf.python.internal.TestAllTypes.optional_nested_message', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32', full_name='google.protobuf.python.internal.TestAllTypes.optional_int32', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=72, + serialized_end=388, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='google.protobuf.python.internal.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='google.protobuf.python.internal.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='d', full_name='google.protobuf.python.internal.ForeignMessage.d', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=390, + serialized_end=428, +) + + +_TESTALLEXTENSIONS = _descriptor.Descriptor( + name='TestAllExtensions', + full_name='google.protobuf.python.internal.TestAllExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=430, + serialized_end=459, +) + +_TESTALLTYPES_NESTEDMESSAGE.fields_by_name['cc'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestAllExtensions'] = _TESTALLEXTENSIONS +DESCRIPTOR.extensions_by_name['optional_nested_message_extension'] = optional_nested_message_extension +DESCRIPTOR.extensions_by_name['repeated_nested_message_extension'] = repeated_nested_message_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestAllTypes.NestedMessage) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestAllExtensions = _reflection.GeneratedProtocolMessageType('TestAllExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTALLEXTENSIONS, + __module__ = 'google.protobuf.pyext.python_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.python.internal.TestAllExtensions) + )) +_sym_db.RegisterMessage(TestAllExtensions) + +optional_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(optional_nested_message_extension) +repeated_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(repeated_nested_message_extension) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/reflection.py b/venv/lib/python3.7/site-packages/google/protobuf/reflection.py new file mode 100644 index 0000000..253493a --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/reflection.py @@ -0,0 +1,121 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +# This code is meant to work on Python 2.4 and above only. + +"""Contains a metaclass and helper functions used to create +protocol message classes from Descriptor objects at runtime. + +Recall that a metaclass is the "type" of a class. +(A class is to a metaclass what an instance is to a class.) + +In this case, we use the GeneratedProtocolMessageType metaclass +to inject all the useful functionality into the classes +output by the protocol compiler at compile-time. + +The upshot of all this is that the real implementation +details for ALL pure-Python protocol buffers are *here in +this file*. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + + +from google.protobuf.internal import api_implementation +from google.protobuf import message + + +if api_implementation.Type() == 'cpp': + from google.protobuf.pyext import cpp_message as message_impl +else: + from google.protobuf.internal import python_message as message_impl + +# The type of all Message classes. +# Part of the public interface, but normally only used by message factories. +GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType + +MESSAGE_CLASS_CACHE = {} + + +def ParseMessage(descriptor, byte_str): + """Generate a new Message instance from this Descriptor and a byte string. + + Args: + descriptor: Protobuf Descriptor object + byte_str: Serialized protocol buffer byte string + + Returns: + Newly created protobuf Message object. + """ + result_class = MakeClass(descriptor) + new_msg = result_class() + new_msg.ParseFromString(byte_str) + return new_msg + + +def MakeClass(descriptor): + """Construct a class object for a protobuf described by descriptor. + + Composite descriptors are handled by defining the new class as a member of the + parent class, recursing as deep as necessary. + This is the dynamic equivalent to: + + class Parent(message.Message): + __metaclass__ = GeneratedProtocolMessageType + DESCRIPTOR = descriptor + class Child(message.Message): + __metaclass__ = GeneratedProtocolMessageType + DESCRIPTOR = descriptor.nested_types[0] + + Sample usage: + file_descriptor = descriptor_pb2.FileDescriptorProto() + file_descriptor.ParseFromString(proto2_string) + msg_descriptor = descriptor.MakeDescriptor(file_descriptor.message_type[0]) + msg_class = reflection.MakeClass(msg_descriptor) + msg = msg_class() + + Args: + descriptor: A descriptor.Descriptor object describing the protobuf. + Returns: + The Message class object described by the descriptor. + """ + if descriptor in MESSAGE_CLASS_CACHE: + return MESSAGE_CLASS_CACHE[descriptor] + + attributes = {} + for name, nested_type in list(descriptor.nested_types_by_name.items()): + attributes[name] = MakeClass(nested_type) + + attributes[GeneratedProtocolMessageType._DESCRIPTOR_KEY] = descriptor + + result = GeneratedProtocolMessageType( + str(descriptor.name), (message.Message,), attributes) + MESSAGE_CLASS_CACHE[descriptor] = result + return result diff --git a/venv/lib/python3.7/site-packages/google/protobuf/service.py b/venv/lib/python3.7/site-packages/google/protobuf/service.py new file mode 100644 index 0000000..9e00de7 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/service.py @@ -0,0 +1,226 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""DEPRECATED: Declares the RPC service interfaces. + +This module declares the abstract interfaces underlying proto2 RPC +services. These are intended to be independent of any particular RPC +implementation, so that proto2 services can be used on top of a variety +of implementations. Starting with version 2.3.0, RPC implementations should +not try to build on these, but should instead provide code generator plugins +which generate code specific to the particular RPC implementation. This way +the generated code can be more appropriate for the implementation in use +and can avoid unnecessary layers of indirection. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + + +class RpcException(Exception): + """Exception raised on failed blocking RPC method call.""" + pass + + +class Service(object): + + """Abstract base interface for protocol-buffer-based RPC services. + + Services themselves are abstract classes (implemented either by servers or as + stubs), but they subclass this base interface. The methods of this + interface can be used to call the methods of the service without knowing + its exact type at compile time (analogous to the Message interface). + """ + + def GetDescriptor(): + """Retrieves this service's descriptor.""" + raise NotImplementedError + + def CallMethod(self, method_descriptor, rpc_controller, + request, done): + """Calls a method of the service specified by method_descriptor. + + If "done" is None then the call is blocking and the response + message will be returned directly. Otherwise the call is asynchronous + and "done" will later be called with the response value. + + In the blocking case, RpcException will be raised on error. + + Preconditions: + * method_descriptor.service == GetDescriptor + * request is of the exact same classes as returned by + GetRequestClass(method). + * After the call has started, the request must not be modified. + * "rpc_controller" is of the correct type for the RPC implementation being + used by this Service. For stubs, the "correct type" depends on the + RpcChannel which the stub is using. + + Postconditions: + * "done" will be called when the method is complete. This may be + before CallMethod() returns or it may be at some point in the future. + * If the RPC failed, the response value passed to "done" will be None. + Further details about the failure can be found by querying the + RpcController. + """ + raise NotImplementedError + + def GetRequestClass(self, method_descriptor): + """Returns the class of the request message for the specified method. + + CallMethod() requires that the request is of a particular subclass of + Message. GetRequestClass() gets the default instance of this required + type. + + Example: + method = service.GetDescriptor().FindMethodByName("Foo") + request = stub.GetRequestClass(method)() + request.ParseFromString(input) + service.CallMethod(method, request, callback) + """ + raise NotImplementedError + + def GetResponseClass(self, method_descriptor): + """Returns the class of the response message for the specified method. + + This method isn't really needed, as the RpcChannel's CallMethod constructs + the response protocol message. It's provided anyway in case it is useful + for the caller to know the response type in advance. + """ + raise NotImplementedError + + +class RpcController(object): + + """An RpcController mediates a single method call. + + The primary purpose of the controller is to provide a way to manipulate + settings specific to the RPC implementation and to find out about RPC-level + errors. The methods provided by the RpcController interface are intended + to be a "least common denominator" set of features which we expect all + implementations to support. Specific implementations may provide more + advanced features (e.g. deadline propagation). + """ + + # Client-side methods below + + def Reset(self): + """Resets the RpcController to its initial state. + + After the RpcController has been reset, it may be reused in + a new call. Must not be called while an RPC is in progress. + """ + raise NotImplementedError + + def Failed(self): + """Returns true if the call failed. + + After a call has finished, returns true if the call failed. The possible + reasons for failure depend on the RPC implementation. Failed() must not + be called before a call has finished. If Failed() returns true, the + contents of the response message are undefined. + """ + raise NotImplementedError + + def ErrorText(self): + """If Failed is true, returns a human-readable description of the error.""" + raise NotImplementedError + + def StartCancel(self): + """Initiate cancellation. + + Advises the RPC system that the caller desires that the RPC call be + canceled. The RPC system may cancel it immediately, may wait awhile and + then cancel it, or may not even cancel the call at all. If the call is + canceled, the "done" callback will still be called and the RpcController + will indicate that the call failed at that time. + """ + raise NotImplementedError + + # Server-side methods below + + def SetFailed(self, reason): + """Sets a failure reason. + + Causes Failed() to return true on the client side. "reason" will be + incorporated into the message returned by ErrorText(). If you find + you need to return machine-readable information about failures, you + should incorporate it into your response protocol buffer and should + NOT call SetFailed(). + """ + raise NotImplementedError + + def IsCanceled(self): + """Checks if the client cancelled the RPC. + + If true, indicates that the client canceled the RPC, so the server may + as well give up on replying to it. The server should still call the + final "done" callback. + """ + raise NotImplementedError + + def NotifyOnCancel(self, callback): + """Sets a callback to invoke on cancel. + + Asks that the given callback be called when the RPC is canceled. The + callback will always be called exactly once. If the RPC completes without + being canceled, the callback will be called after completion. If the RPC + has already been canceled when NotifyOnCancel() is called, the callback + will be called immediately. + + NotifyOnCancel() must be called no more than once per request. + """ + raise NotImplementedError + + +class RpcChannel(object): + + """Abstract interface for an RPC channel. + + An RpcChannel represents a communication line to a service which can be used + to call that service's methods. The service may be running on another + machine. Normally, you should not use an RpcChannel directly, but instead + construct a stub {@link Service} wrapping it. Example: + + Example: + RpcChannel channel = rpcImpl.Channel("remotehost.example.com:1234") + RpcController controller = rpcImpl.Controller() + MyService service = MyService_Stub(channel) + service.MyMethod(controller, request, callback) + """ + + def CallMethod(self, method_descriptor, rpc_controller, + request, response_class, done): + """Calls the method identified by the descriptor. + + Call the given method of the remote service. The signature of this + procedure looks the same as Service.CallMethod(), but the requirements + are less strict in one important way: the request object doesn't have to + be of any specific class as long as its descriptor is method.input_type. + """ + raise NotImplementedError diff --git a/venv/lib/python3.7/site-packages/google/protobuf/service_reflection.py b/venv/lib/python3.7/site-packages/google/protobuf/service_reflection.py new file mode 100644 index 0000000..1c3636a --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/service_reflection.py @@ -0,0 +1,284 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains metaclasses used to create protocol service and service stub +classes from ServiceDescriptor objects at runtime. + +The GeneratedServiceType and GeneratedServiceStubType metaclasses are used to +inject all useful functionality into the classes output by the protocol +compiler at compile-time. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + + +class GeneratedServiceType(type): + + """Metaclass for service classes created at runtime from ServiceDescriptors. + + Implementations for all methods described in the Service class are added here + by this class. We also create properties to allow getting/setting all fields + in the protocol message. + + The protocol compiler currently uses this metaclass to create protocol service + classes at runtime. Clients can also manually create their own classes at + runtime, as in this example: + + mydescriptor = ServiceDescriptor(.....) + class MyProtoService(service.Service): + __metaclass__ = GeneratedServiceType + DESCRIPTOR = mydescriptor + myservice_instance = MyProtoService() + ... + """ + + _DESCRIPTOR_KEY = 'DESCRIPTOR' + + def __init__(cls, name, bases, dictionary): + """Creates a message service class. + + Args: + name: Name of the class (ignored, but required by the metaclass + protocol). + bases: Base classes of the class being constructed. + dictionary: The class dictionary of the class being constructed. + dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object + describing this protocol service type. + """ + # Don't do anything if this class doesn't have a descriptor. This happens + # when a service class is subclassed. + if GeneratedServiceType._DESCRIPTOR_KEY not in dictionary: + return + descriptor = dictionary[GeneratedServiceType._DESCRIPTOR_KEY] + service_builder = _ServiceBuilder(descriptor) + service_builder.BuildService(cls) + + +class GeneratedServiceStubType(GeneratedServiceType): + + """Metaclass for service stubs created at runtime from ServiceDescriptors. + + This class has similar responsibilities as GeneratedServiceType, except that + it creates the service stub classes. + """ + + _DESCRIPTOR_KEY = 'DESCRIPTOR' + + def __init__(cls, name, bases, dictionary): + """Creates a message service stub class. + + Args: + name: Name of the class (ignored, here). + bases: Base classes of the class being constructed. + dictionary: The class dictionary of the class being constructed. + dictionary[_DESCRIPTOR_KEY] must contain a ServiceDescriptor object + describing this protocol service type. + """ + super(GeneratedServiceStubType, cls).__init__(name, bases, dictionary) + # Don't do anything if this class doesn't have a descriptor. This happens + # when a service stub is subclassed. + if GeneratedServiceStubType._DESCRIPTOR_KEY not in dictionary: + return + descriptor = dictionary[GeneratedServiceStubType._DESCRIPTOR_KEY] + service_stub_builder = _ServiceStubBuilder(descriptor) + service_stub_builder.BuildServiceStub(cls) + + +class _ServiceBuilder(object): + + """This class constructs a protocol service class using a service descriptor. + + Given a service descriptor, this class constructs a class that represents + the specified service descriptor. One service builder instance constructs + exactly one service class. That means all instances of that class share the + same builder. + """ + + def __init__(self, service_descriptor): + """Initializes an instance of the service class builder. + + Args: + service_descriptor: ServiceDescriptor to use when constructing the + service class. + """ + self.descriptor = service_descriptor + + def BuildService(self, cls): + """Constructs the service class. + + Args: + cls: The class that will be constructed. + """ + + # CallMethod needs to operate with an instance of the Service class. This + # internal wrapper function exists only to be able to pass the service + # instance to the method that does the real CallMethod work. + def _WrapCallMethod(srvc, method_descriptor, + rpc_controller, request, callback): + return self._CallMethod(srvc, method_descriptor, + rpc_controller, request, callback) + self.cls = cls + cls.CallMethod = _WrapCallMethod + cls.GetDescriptor = staticmethod(lambda: self.descriptor) + cls.GetDescriptor.__doc__ = "Returns the service descriptor." + cls.GetRequestClass = self._GetRequestClass + cls.GetResponseClass = self._GetResponseClass + for method in self.descriptor.methods: + setattr(cls, method.name, self._GenerateNonImplementedMethod(method)) + + def _CallMethod(self, srvc, method_descriptor, + rpc_controller, request, callback): + """Calls the method described by a given method descriptor. + + Args: + srvc: Instance of the service for which this method is called. + method_descriptor: Descriptor that represent the method to call. + rpc_controller: RPC controller to use for this method's execution. + request: Request protocol message. + callback: A callback to invoke after the method has completed. + """ + if method_descriptor.containing_service != self.descriptor: + raise RuntimeError( + 'CallMethod() given method descriptor for wrong service type.') + method = getattr(srvc, method_descriptor.name) + return method(rpc_controller, request, callback) + + def _GetRequestClass(self, method_descriptor): + """Returns the class of the request protocol message. + + Args: + method_descriptor: Descriptor of the method for which to return the + request protocol message class. + + Returns: + A class that represents the input protocol message of the specified + method. + """ + if method_descriptor.containing_service != self.descriptor: + raise RuntimeError( + 'GetRequestClass() given method descriptor for wrong service type.') + return method_descriptor.input_type._concrete_class + + def _GetResponseClass(self, method_descriptor): + """Returns the class of the response protocol message. + + Args: + method_descriptor: Descriptor of the method for which to return the + response protocol message class. + + Returns: + A class that represents the output protocol message of the specified + method. + """ + if method_descriptor.containing_service != self.descriptor: + raise RuntimeError( + 'GetResponseClass() given method descriptor for wrong service type.') + return method_descriptor.output_type._concrete_class + + def _GenerateNonImplementedMethod(self, method): + """Generates and returns a method that can be set for a service methods. + + Args: + method: Descriptor of the service method for which a method is to be + generated. + + Returns: + A method that can be added to the service class. + """ + return lambda inst, rpc_controller, request, callback: ( + self._NonImplementedMethod(method.name, rpc_controller, callback)) + + def _NonImplementedMethod(self, method_name, rpc_controller, callback): + """The body of all methods in the generated service class. + + Args: + method_name: Name of the method being executed. + rpc_controller: RPC controller used to execute this method. + callback: A callback which will be invoked when the method finishes. + """ + rpc_controller.SetFailed('Method %s not implemented.' % method_name) + callback(None) + + +class _ServiceStubBuilder(object): + + """Constructs a protocol service stub class using a service descriptor. + + Given a service descriptor, this class constructs a suitable stub class. + A stub is just a type-safe wrapper around an RpcChannel which emulates a + local implementation of the service. + + One service stub builder instance constructs exactly one class. It means all + instances of that class share the same service stub builder. + """ + + def __init__(self, service_descriptor): + """Initializes an instance of the service stub class builder. + + Args: + service_descriptor: ServiceDescriptor to use when constructing the + stub class. + """ + self.descriptor = service_descriptor + + def BuildServiceStub(self, cls): + """Constructs the stub class. + + Args: + cls: The class that will be constructed. + """ + + def _ServiceStubInit(stub, rpc_channel): + stub.rpc_channel = rpc_channel + self.cls = cls + cls.__init__ = _ServiceStubInit + for method in self.descriptor.methods: + setattr(cls, method.name, self._GenerateStubMethod(method)) + + def _GenerateStubMethod(self, method): + return (lambda inst, rpc_controller, request, callback=None: + self._StubMethod(inst, method, rpc_controller, request, callback)) + + def _StubMethod(self, stub, method_descriptor, + rpc_controller, request, callback): + """The body of all service methods in the generated stub class. + + Args: + stub: Stub instance. + method_descriptor: Descriptor of the invoked method. + rpc_controller: Rpc controller to execute the method. + request: Request protocol message. + callback: A callback to execute when the method finishes. + Returns: + Response message (in case of blocking call). + """ + return stub.rpc_channel.CallMethod( + method_descriptor, rpc_controller, request, + method_descriptor.output_type._concrete_class, callback) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/source_context_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/source_context_pb2.py new file mode 100644 index 0000000..6699c81 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/source_context_pb2.py @@ -0,0 +1,70 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/source_context.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/source_context.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\022SourceContextProtoP\001ZAgoogle.golang.org/genproto/protobuf/source_context;source_context\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n$google/protobuf/source_context.proto\x12\x0fgoogle.protobuf\"\"\n\rSourceContext\x12\x11\n\tfile_name\x18\x01 \x01(\tB\x95\x01\n\x13\x63om.google.protobufB\x12SourceContextProtoP\x01ZAgoogle.golang.org/genproto/protobuf/source_context;source_context\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_SOURCECONTEXT = _descriptor.Descriptor( + name='SourceContext', + full_name='google.protobuf.SourceContext', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='file_name', full_name='google.protobuf.SourceContext.file_name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=57, + serialized_end=91, +) + +DESCRIPTOR.message_types_by_name['SourceContext'] = _SOURCECONTEXT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +SourceContext = _reflection.GeneratedProtocolMessageType('SourceContext', (_message.Message,), dict( + DESCRIPTOR = _SOURCECONTEXT, + __module__ = 'google.protobuf.source_context_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceContext) + )) +_sym_db.RegisterMessage(SourceContext) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/struct_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/struct_pb2.py new file mode 100644 index 0000000..6c5c445 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/struct_pb2.py @@ -0,0 +1,279 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/struct.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/struct.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\013StructProtoP\001Z1github.com/golang/protobuf/ptypes/struct;structpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1cgoogle/protobuf/struct.proto\x12\x0fgoogle.protobuf\"\x84\x01\n\x06Struct\x12\x33\n\x06\x66ields\x18\x01 \x03(\x0b\x32#.google.protobuf.Struct.FieldsEntry\x1a\x45\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12%\n\x05value\x18\x02 \x01(\x0b\x32\x16.google.protobuf.Value:\x02\x38\x01\"\xea\x01\n\x05Value\x12\x30\n\nnull_value\x18\x01 \x01(\x0e\x32\x1a.google.protobuf.NullValueH\x00\x12\x16\n\x0cnumber_value\x18\x02 \x01(\x01H\x00\x12\x16\n\x0cstring_value\x18\x03 \x01(\tH\x00\x12\x14\n\nbool_value\x18\x04 \x01(\x08H\x00\x12/\n\x0cstruct_value\x18\x05 \x01(\x0b\x32\x17.google.protobuf.StructH\x00\x12\x30\n\nlist_value\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.ListValueH\x00\x42\x06\n\x04kind\"3\n\tListValue\x12&\n\x06values\x18\x01 \x03(\x0b\x32\x16.google.protobuf.Value*\x1b\n\tNullValue\x12\x0e\n\nNULL_VALUE\x10\x00\x42\x81\x01\n\x13\x63om.google.protobufB\x0bStructProtoP\x01Z1github.com/golang/protobuf/ptypes/struct;structpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + +_NULLVALUE = _descriptor.EnumDescriptor( + name='NullValue', + full_name='google.protobuf.NullValue', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NULL_VALUE', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=474, + serialized_end=501, +) +_sym_db.RegisterEnumDescriptor(_NULLVALUE) + +NullValue = enum_type_wrapper.EnumTypeWrapper(_NULLVALUE) +NULL_VALUE = 0 + + + +_STRUCT_FIELDSENTRY = _descriptor.Descriptor( + name='FieldsEntry', + full_name='google.protobuf.Struct.FieldsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='google.protobuf.Struct.FieldsEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Struct.FieldsEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=182, +) + +_STRUCT = _descriptor.Descriptor( + name='Struct', + full_name='google.protobuf.Struct', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='fields', full_name='google.protobuf.Struct.fields', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_STRUCT_FIELDSENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=50, + serialized_end=182, +) + + +_VALUE = _descriptor.Descriptor( + name='Value', + full_name='google.protobuf.Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='null_value', full_name='google.protobuf.Value.null_value', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number_value', full_name='google.protobuf.Value.number_value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='google.protobuf.Value.string_value', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_value', full_name='google.protobuf.Value.bool_value', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='struct_value', full_name='google.protobuf.Value.struct_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='list_value', full_name='google.protobuf.Value.list_value', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='kind', full_name='google.protobuf.Value.kind', + index=0, containing_type=None, fields=[]), + ], + serialized_start=185, + serialized_end=419, +) + + +_LISTVALUE = _descriptor.Descriptor( + name='ListValue', + full_name='google.protobuf.ListValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='values', full_name='google.protobuf.ListValue.values', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=421, + serialized_end=472, +) + +_STRUCT_FIELDSENTRY.fields_by_name['value'].message_type = _VALUE +_STRUCT_FIELDSENTRY.containing_type = _STRUCT +_STRUCT.fields_by_name['fields'].message_type = _STRUCT_FIELDSENTRY +_VALUE.fields_by_name['null_value'].enum_type = _NULLVALUE +_VALUE.fields_by_name['struct_value'].message_type = _STRUCT +_VALUE.fields_by_name['list_value'].message_type = _LISTVALUE +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['null_value']) +_VALUE.fields_by_name['null_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['number_value']) +_VALUE.fields_by_name['number_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['string_value']) +_VALUE.fields_by_name['string_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['bool_value']) +_VALUE.fields_by_name['bool_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['struct_value']) +_VALUE.fields_by_name['struct_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_VALUE.oneofs_by_name['kind'].fields.append( + _VALUE.fields_by_name['list_value']) +_VALUE.fields_by_name['list_value'].containing_oneof = _VALUE.oneofs_by_name['kind'] +_LISTVALUE.fields_by_name['values'].message_type = _VALUE +DESCRIPTOR.message_types_by_name['Struct'] = _STRUCT +DESCRIPTOR.message_types_by_name['Value'] = _VALUE +DESCRIPTOR.message_types_by_name['ListValue'] = _LISTVALUE +DESCRIPTOR.enum_types_by_name['NullValue'] = _NULLVALUE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Struct = _reflection.GeneratedProtocolMessageType('Struct', (_message.Message,), dict( + + FieldsEntry = _reflection.GeneratedProtocolMessageType('FieldsEntry', (_message.Message,), dict( + DESCRIPTOR = _STRUCT_FIELDSENTRY, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Struct.FieldsEntry) + )) + , + DESCRIPTOR = _STRUCT, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Struct) + )) +_sym_db.RegisterMessage(Struct) +_sym_db.RegisterMessage(Struct.FieldsEntry) + +Value = _reflection.GeneratedProtocolMessageType('Value', (_message.Message,), dict( + DESCRIPTOR = _VALUE, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Value) + )) +_sym_db.RegisterMessage(Value) + +ListValue = _reflection.GeneratedProtocolMessageType('ListValue', (_message.Message,), dict( + DESCRIPTOR = _LISTVALUE, + __module__ = 'google.protobuf.struct_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ListValue) + )) +_sym_db.RegisterMessage(ListValue) + + +DESCRIPTOR._options = None +_STRUCT_FIELDSENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/symbol_database.py b/venv/lib/python3.7/site-packages/google/protobuf/symbol_database.py new file mode 100644 index 0000000..0722e5f --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/symbol_database.py @@ -0,0 +1,189 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""A database of Python protocol buffer generated symbols. + +SymbolDatabase is the MessageFactory for messages generated at compile time, +and makes it easy to create new instances of a registered type, given only the +type's protocol buffer symbol name. + +Example usage: + + db = symbol_database.SymbolDatabase() + + # Register symbols of interest, from one or multiple files. + db.RegisterFileDescriptor(my_proto_pb2.DESCRIPTOR) + db.RegisterMessage(my_proto_pb2.MyMessage) + db.RegisterEnumDescriptor(my_proto_pb2.MyEnum.DESCRIPTOR) + + # The database can be used as a MessageFactory, to generate types based on + # their name: + types = db.GetMessages(['my_proto.proto']) + my_message_instance = types['MyMessage']() + + # The database's underlying descriptor pool can be queried, so it's not + # necessary to know a type's filename to be able to generate it: + filename = db.pool.FindFileContainingSymbol('MyMessage') + my_message_instance = db.GetMessages([filename])['MyMessage']() + + # This functionality is also provided directly via a convenience method: + my_message_instance = db.GetSymbol('MyMessage')() +""" + + +from google.protobuf import descriptor_pool +from google.protobuf import message_factory + + +class SymbolDatabase(message_factory.MessageFactory): + """A database of Python generated symbols.""" + + def RegisterMessage(self, message): + """Registers the given message type in the local database. + + Calls to GetSymbol() and GetMessages() will return messages registered here. + + Args: + message: a message.Message, to be registered. + + Returns: + The provided message. + """ + + desc = message.DESCRIPTOR + self._classes[desc] = message + self.RegisterMessageDescriptor(desc) + return message + + def RegisterMessageDescriptor(self, message_descriptor): + """Registers the given message descriptor in the local database. + + Args: + message_descriptor: a descriptor.MessageDescriptor. + """ + self.pool.AddDescriptor(message_descriptor) + + def RegisterEnumDescriptor(self, enum_descriptor): + """Registers the given enum descriptor in the local database. + + Args: + enum_descriptor: a descriptor.EnumDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddEnumDescriptor(enum_descriptor) + return enum_descriptor + + def RegisterServiceDescriptor(self, service_descriptor): + """Registers the given service descriptor in the local database. + + Args: + service_descriptor: a descriptor.ServiceDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddServiceDescriptor(service_descriptor) + + def RegisterFileDescriptor(self, file_descriptor): + """Registers the given file descriptor in the local database. + + Args: + file_descriptor: a descriptor.FileDescriptor. + + Returns: + The provided descriptor. + """ + self.pool.AddFileDescriptor(file_descriptor) + + def GetSymbol(self, symbol): + """Tries to find a symbol in the local database. + + Currently, this method only returns message.Message instances, however, if + may be extended in future to support other symbol types. + + Args: + symbol: A str, a protocol buffer symbol. + + Returns: + A Python class corresponding to the symbol. + + Raises: + KeyError: if the symbol could not be found. + """ + + return self._classes[self.pool.FindMessageTypeByName(symbol)] + + def GetMessages(self, files): + # TODO(amauryfa): Fix the differences with MessageFactory. + """Gets all registered messages from a specified file. + + Only messages already created and registered will be returned; (this is the + case for imported _pb2 modules) + But unlike MessageFactory, this version also returns already defined nested + messages, but does not register any message extensions. + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. + + Raises: + KeyError: if a file could not be found. + """ + + def _GetAllMessages(desc): + """Walk a message Descriptor and recursively yields all message names.""" + yield desc + for msg_desc in desc.nested_types: + for nested_desc in _GetAllMessages(msg_desc): + yield nested_desc + + result = {} + for file_name in files: + file_desc = self.pool.FindFileByName(file_name) + for msg_desc in list(file_desc.message_types_by_name.values()): + for desc in _GetAllMessages(msg_desc): + try: + result[desc.full_name] = self._classes[desc] + except KeyError: + # This descriptor has no registered class, skip it. + pass + return result + + +_DEFAULT = SymbolDatabase(pool=descriptor_pool.Default()) + + +def Default(): + """Returns the default SymbolDatabase.""" + return _DEFAULT diff --git a/venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto2_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto2_pb2.py new file mode 100644 index 0000000..6b98193 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto2_pb2.py @@ -0,0 +1,1990 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/test_messages_proto2.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/test_messages_proto2.proto', + package='protobuf_test_messages.proto2', + syntax='proto2', + serialized_options=_b('\n(com.google.protobuf_test_messages.proto2H\001\370\001\001'), + serialized_pb=_b('\n*google/protobuf/test_messages_proto2.proto\x12\x1dprotobuf_test_messages.proto2\"\xde\x32\n\x12TestAllTypesProto2\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12`\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage\x12U\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32\x33.protobuf_test_messages.proto2.ForeignMessageProto2\x12Z\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum\x12O\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x30.protobuf_test_messages.proto2.ForeignEnumProto2\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12L\n\x11recursive_message\x18\x1b \x01(\x0b\x32\x31.protobuf_test_messages.proto2.TestAllTypesProto2\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12`\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage\x12U\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32\x33.protobuf_test_messages.proto2.ForeignMessageProto2\x12Z\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum\x12O\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\x30.protobuf_test_messages.proto2.ForeignEnumProto2\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12]\n\x0fmap_int32_int32\x18\x38 \x03(\x0b\x32\x44.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry\x12]\n\x0fmap_int64_int64\x18\x39 \x03(\x0b\x32\x44.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry\x12\x61\n\x11map_uint32_uint32\x18: \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry\x12\x61\n\x11map_uint64_uint64\x18; \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry\x12\x61\n\x11map_sint32_sint32\x18< \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry\x12\x61\n\x11map_sint64_sint64\x18= \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry\x12\x65\n\x13map_fixed32_fixed32\x18> \x03(\x0b\x32H.protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry\x12\x65\n\x13map_fixed64_fixed64\x18? \x03(\x0b\x32H.protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry\x12i\n\x15map_sfixed32_sfixed32\x18@ \x03(\x0b\x32J.protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry\x12i\n\x15map_sfixed64_sfixed64\x18\x41 \x03(\x0b\x32J.protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry\x12]\n\x0fmap_int32_float\x18\x42 \x03(\x0b\x32\x44.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry\x12_\n\x10map_int32_double\x18\x43 \x03(\x0b\x32\x45.protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry\x12Y\n\rmap_bool_bool\x18\x44 \x03(\x0b\x32\x42.protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry\x12\x61\n\x11map_string_string\x18\x45 \x03(\x0b\x32\x46.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry\x12_\n\x10map_string_bytes\x18\x46 \x03(\x0b\x32\x45.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry\x12p\n\x19map_string_nested_message\x18G \x03(\x0b\x32M.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry\x12r\n\x1amap_string_foreign_message\x18H \x03(\x0b\x32N.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry\x12j\n\x16map_string_nested_enum\x18I \x03(\x0b\x32J.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry\x12l\n\x17map_string_foreign_enum\x18J \x03(\x0b\x32K.protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12_\n\x14oneof_nested_message\x18p \x01(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12\x14\n\noneof_bool\x18s \x01(\x08H\x00\x12\x16\n\x0coneof_uint64\x18t \x01(\x04H\x00\x12\x15\n\x0boneof_float\x18u \x01(\x02H\x00\x12\x16\n\x0coneof_double\x18v \x01(\x01H\x00\x12R\n\noneof_enum\x18w \x01(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnumH\x00\x12\x45\n\x04\x64\x61ta\x18\xc9\x01 \x01(\n26.protobuf_test_messages.proto2.TestAllTypesProto2.Data\x12\x13\n\nfieldname1\x18\x91\x03 \x01(\x05\x12\x14\n\x0b\x66ield_name2\x18\x92\x03 \x01(\x05\x12\x15\n\x0c_field_name3\x18\x93\x03 \x01(\x05\x12\x16\n\rfield__name4_\x18\x94\x03 \x01(\x05\x12\x14\n\x0b\x66ield0name5\x18\x95\x03 \x01(\x05\x12\x16\n\rfield_0_name6\x18\x96\x03 \x01(\x05\x12\x13\n\nfieldName7\x18\x97\x03 \x01(\x05\x12\x13\n\nFieldName8\x18\x98\x03 \x01(\x05\x12\x14\n\x0b\x66ield_Name9\x18\x99\x03 \x01(\x05\x12\x15\n\x0c\x46ield_Name10\x18\x9a\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_NAME11\x18\x9b\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_name12\x18\x9c\x03 \x01(\x05\x12\x17\n\x0e__field_name13\x18\x9d\x03 \x01(\x05\x12\x17\n\x0e__Field_name14\x18\x9e\x03 \x01(\x05\x12\x16\n\rfield__name15\x18\x9f\x03 \x01(\x05\x12\x16\n\rfield__Name16\x18\xa0\x03 \x01(\x05\x12\x17\n\x0e\x66ield_name17__\x18\xa1\x03 \x01(\x05\x12\x17\n\x0e\x46ield_name18__\x18\xa2\x03 \x01(\x05\x1a\x62\n\rNestedMessage\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\x46\n\x0b\x63orecursive\x18\x02 \x01(\x0b\x32\x31.protobuf_test_messages.proto2.TestAllTypesProto2\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13MapStringBytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a~\n\x1bMapStringNestedMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12N\n\x05value\x18\x02 \x01(\x0b\x32?.protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage:\x02\x38\x01\x1as\n\x1cMapStringForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x42\n\x05value\x18\x02 \x01(\x0b\x32\x33.protobuf_test_messages.proto2.ForeignMessageProto2:\x02\x38\x01\x1ax\n\x18MapStringNestedEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12K\n\x05value\x18\x02 \x01(\x0e\x32<.protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum:\x02\x38\x01\x1am\n\x19MapStringForeignEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0e\x32\x30.protobuf_test_messages.proto2.ForeignEnumProto2:\x02\x38\x01\x1a\x33\n\x04\x44\x61ta\x12\x14\n\x0bgroup_int32\x18\xca\x01 \x01(\x05\x12\x15\n\x0cgroup_uint32\x18\xcb\x01 \x01(\r\x1a!\n\x11MessageSetCorrect*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\x1a\xe0\x01\n\x1bMessageSetCorrectExtension1\x12\x0b\n\x03str\x18\x19 \x01(\t2\xb3\x01\n\x15message_set_extension\x12\x43.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect\x18\xf9\xbb^ \x01(\x0b\x32M.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1\x1a\xdf\x01\n\x1bMessageSetCorrectExtension2\x12\t\n\x01i\x18\t \x01(\x05\x32\xb4\x01\n\x15message_set_extension\x12\x43.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect\x18\x90\xb3\xfc\x01 \x01(\x0b\x32M.protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x12\x07\n\x03\x42\x41Z\x10\x02\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01*\x05\x08x\x10\xc9\x01\x42\r\n\x0boneof_field\"!\n\x14\x46oreignMessageProto2\x12\t\n\x01\x63\x18\x01 \x01(\x05*F\n\x11\x46oreignEnumProto2\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x00\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x01\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x02:J\n\x0f\x65xtension_int32\x12\x31.protobuf_test_messages.proto2.TestAllTypesProto2\x18x \x01(\x05\x42/\n(com.google.protobuf_test_messages.proto2H\x01\xf8\x01\x01') +) + +_FOREIGNENUMPROTO2 = _descriptor.EnumDescriptor( + name='ForeignEnumProto2', + full_name='protobuf_test_messages.proto2.ForeignEnumProto2', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6609, + serialized_end=6679, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUMPROTO2) + +ForeignEnumProto2 = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUMPROTO2) +FOREIGN_FOO = 0 +FOREIGN_BAR = 1 +FOREIGN_BAZ = 2 + +EXTENSION_INT32_FIELD_NUMBER = 120 +extension_int32 = _descriptor.FieldDescriptor( + name='extension_int32', full_name='protobuf_test_messages.proto2.extension_int32', index=0, + number=120, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_TESTALLTYPESPROTO2_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=6493, + serialized_end=6550, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPESPROTO2_NESTEDENUM) + + +_TESTALLTYPESPROTO2_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='corecursive', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage.corecursive', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4534, + serialized_end=4632, +) + +_TESTALLTYPESPROTO2_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4634, + serialized_end=4686, +) + +_TESTALLTYPESPROTO2_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4688, + serialized_end=4740, +) + +_TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4742, + serialized_end=4796, +) + +_TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4798, + serialized_end=4852, +) + +_TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4854, + serialized_end=4908, +) + +_TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4910, + serialized_end=4964, +) + +_TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4966, + serialized_end=5022, +) + +_TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5024, + serialized_end=5080, +) + +_TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5082, + serialized_end=5140, +) + +_TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5142, + serialized_end=5200, +) + +_TESTALLTYPESPROTO2_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5202, + serialized_end=5254, +) + +_TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5256, + serialized_end=5309, +) + +_TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5311, + serialized_end=5361, +) + +_TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5363, + serialized_end=5417, +) + +_TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY = _descriptor.Descriptor( + name='MapStringBytesEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5419, + serialized_end=5472, +) + +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringNestedMessageEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5474, + serialized_end=5600, +) + +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringForeignMessageEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5602, + serialized_end=5717, +) + +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY = _descriptor.Descriptor( + name='MapStringNestedEnumEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5719, + serialized_end=5839, +) + +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY = _descriptor.Descriptor( + name='MapStringForeignEnumEntry', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5841, + serialized_end=5950, +) + +_TESTALLTYPESPROTO2_DATA = _descriptor.Descriptor( + name='Data', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Data', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='group_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Data.group_int32', index=0, + number=202, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='group_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Data.group_uint32', index=1, + number=203, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5952, + serialized_end=6003, +) + +_TESTALLTYPESPROTO2_MESSAGESETCORRECT = _descriptor.Descriptor( + name='MessageSetCorrect', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=6005, + serialized_end=6038, +) + +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1 = _descriptor.Descriptor( + name='MessageSetCorrectExtension1', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='str', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1.str', index=0, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1.message_set_extension', index=0, + number=1547769, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6041, + serialized_end=6265, +) + +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2 = _descriptor.Descriptor( + name='MessageSetCorrectExtension2', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2.i', index=0, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2.message_set_extension', index=0, + number=4135312, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6268, + serialized_end=6491, +) + +_TESTALLTYPESPROTO2 = _descriptor.Descriptor( + name='TestAllTypesProto2', + full_name='protobuf_test_messages.proto2.TestAllTypesProto2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_nested_message', index=15, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_foreign_message', index=16, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_nested_enum', index=17, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_foreign_enum', index=18, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_string_piece', index=19, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.optional_cord', index=20, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='recursive_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.recursive_message', index=21, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_int32', index=22, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_int64', index=23, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_uint32', index=24, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_uint64', index=25, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sint32', index=26, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sint64', index=27, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_fixed32', index=28, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_fixed64', index=29, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sfixed32', index=30, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_sfixed64', index=31, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_float', index=32, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_double', index=33, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_bool', index=34, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_string', index=35, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_bytes', index=36, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_nested_message', index=37, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_foreign_message', index=38, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_nested_enum', index=39, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_foreign_enum', index=40, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_string_piece', index=41, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.repeated_cord', index=42, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int32_int32', index=43, + number=56, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int64_int64', index=44, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_uint32_uint32', index=45, + number=58, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_uint64_uint64', index=46, + number=59, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sint32_sint32', index=47, + number=60, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sint64_sint64', index=48, + number=61, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_fixed32_fixed32', index=49, + number=62, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_fixed64_fixed64', index=50, + number=63, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sfixed32_sfixed32', index=51, + number=64, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_sfixed64_sfixed64', index=52, + number=65, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int32_float', index=53, + number=66, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_int32_double', index=54, + number=67, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_bool_bool', index=55, + number=68, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_string', index=56, + number=69, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_bytes', index=57, + number=70, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_nested_message', index=58, + number=71, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_foreign_message', index=59, + number=72, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_nested_enum', index=60, + number=73, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.map_string_foreign_enum', index=61, + number=74, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_uint32', index=62, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_nested_message', index=63, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_string', index=64, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_bytes', index=65, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bool', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_bool', index=66, + number=115, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint64', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_uint64', index=67, + number=116, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_float', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_float', index=68, + number=117, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_double', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_double', index=69, + number=118, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_enum', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_enum', index=70, + number=119, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.data', index=71, + number=201, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldname1', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.fieldname1', index=72, + number=401, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name2', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_name2', index=73, + number=402, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='_field_name3', full_name='protobuf_test_messages.proto2.TestAllTypesProto2._field_name3', index=74, + number=403, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name4_', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field__name4_', index=75, + number=404, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field0name5', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field0name5', index=76, + number=405, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_0_name6', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_0_name6', index=77, + number=406, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldName7', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.fieldName7', index=78, + number=407, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FieldName8', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.FieldName8', index=79, + number=408, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_Name9', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_Name9', index=80, + number=409, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_Name10', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Field_Name10', index=81, + number=410, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_NAME11', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.FIELD_NAME11', index=82, + number=411, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_name12', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.FIELD_name12', index=83, + number=412, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__field_name13', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.__field_name13', index=84, + number=413, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__Field_name14', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.__Field_name14', index=85, + number=414, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name15', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field__name15', index=86, + number=415, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__Name16', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field__Name16', index=87, + number=416, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name17__', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.field_name17__', index=88, + number=417, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_name18__', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.Field_name18__', index=89, + number=418, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPESPROTO2_NESTEDMESSAGE, _TESTALLTYPESPROTO2_MAPINT32INT32ENTRY, _TESTALLTYPESPROTO2_MAPINT64INT64ENTRY, _TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY, _TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY, _TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY, _TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY, _TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY, _TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY, _TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY, _TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY, _TESTALLTYPESPROTO2_MAPINT32FLOATENTRY, _TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY, _TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY, _TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY, _TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY, _TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY, _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY, _TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY, _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY, _TESTALLTYPESPROTO2_DATA, _TESTALLTYPESPROTO2_MESSAGESETCORRECT, _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1, _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2, ], + enum_types=[ + _TESTALLTYPESPROTO2_NESTEDENUM, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(120, 201), ], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_test_messages.proto2.TestAllTypesProto2.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=78, + serialized_end=6572, +) + + +_FOREIGNMESSAGEPROTO2 = _descriptor.Descriptor( + name='ForeignMessageProto2', + full_name='protobuf_test_messages.proto2.ForeignMessageProto2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_test_messages.proto2.ForeignMessageProto2.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6574, + serialized_end=6607, +) + +_TESTALLTYPESPROTO2_NESTEDMESSAGE.fields_by_name['corecursive'].message_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_NESTEDMESSAGE.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT32INT32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT64INT64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT32FLOATENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY.fields_by_name['value'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = _FOREIGNMESSAGEPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY.fields_by_name['value'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY.fields_by_name['value'].enum_type = _FOREIGNENUMPROTO2 +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_DATA.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MESSAGESETCORRECT.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGEPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUMPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['recursive_message'].message_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGEPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUMPROTO2 +_TESTALLTYPESPROTO2.fields_by_name['map_int32_int32'].message_type = _TESTALLTYPESPROTO2_MAPINT32INT32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_int64_int64'].message_type = _TESTALLTYPESPROTO2_MAPINT64INT64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_uint32_uint32'].message_type = _TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_uint64_uint64'].message_type = _TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sint32_sint32'].message_type = _TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sint64_sint64'].message_type = _TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_fixed32_fixed32'].message_type = _TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_fixed64_fixed64'].message_type = _TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_int32_float'].message_type = _TESTALLTYPESPROTO2_MAPINT32FLOATENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_int32_double'].message_type = _TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_bool_bool'].message_type = _TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_string'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_bytes'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_nested_message'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_foreign_message'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_nested_enum'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY +_TESTALLTYPESPROTO2.fields_by_name['map_string_foreign_enum'].message_type = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY +_TESTALLTYPESPROTO2.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPESPROTO2_NESTEDMESSAGE +_TESTALLTYPESPROTO2.fields_by_name['oneof_enum'].enum_type = _TESTALLTYPESPROTO2_NESTEDENUM +_TESTALLTYPESPROTO2.fields_by_name['data'].message_type = _TESTALLTYPESPROTO2_DATA +_TESTALLTYPESPROTO2_NESTEDENUM.containing_type = _TESTALLTYPESPROTO2 +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_uint32']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_nested_message']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_string']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_bytes']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_bool']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_bool'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_uint64']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_uint64'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_float']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_float'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_double']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_double'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO2.fields_by_name['oneof_enum']) +_TESTALLTYPESPROTO2.fields_by_name['oneof_enum'].containing_oneof = _TESTALLTYPESPROTO2.oneofs_by_name['oneof_field'] +DESCRIPTOR.message_types_by_name['TestAllTypesProto2'] = _TESTALLTYPESPROTO2 +DESCRIPTOR.message_types_by_name['ForeignMessageProto2'] = _FOREIGNMESSAGEPROTO2 +DESCRIPTOR.enum_types_by_name['ForeignEnumProto2'] = _FOREIGNENUMPROTO2 +DESCRIPTOR.extensions_by_name['extension_int32'] = extension_int32 +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypesProto2 = _reflection.GeneratedProtocolMessageType('TestAllTypesProto2', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_NESTEDMESSAGE, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.NestedMessage) + )) + , + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringStringEntry) + )) + , + + MapStringBytesEntry = _reflection.GeneratedProtocolMessageType('MapStringBytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringBytesEntry) + )) + , + + MapStringNestedMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedMessageEntry) + )) + , + + MapStringForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignMessageEntry) + )) + , + + MapStringNestedEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringNestedEnumEntry) + )) + , + + MapStringForeignEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MapStringForeignEnumEntry) + )) + , + + Data = _reflection.GeneratedProtocolMessageType('Data', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_DATA, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.Data) + )) + , + + MessageSetCorrect = _reflection.GeneratedProtocolMessageType('MessageSetCorrect', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MESSAGESETCORRECT, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrect) + )) + , + + MessageSetCorrectExtension1 = _reflection.GeneratedProtocolMessageType('MessageSetCorrectExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension1) + )) + , + + MessageSetCorrectExtension2 = _reflection.GeneratedProtocolMessageType('MessageSetCorrectExtension2', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2.MessageSetCorrectExtension2) + )) + , + DESCRIPTOR = _TESTALLTYPESPROTO2, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.TestAllTypesProto2) + )) +_sym_db.RegisterMessage(TestAllTypesProto2) +_sym_db.RegisterMessage(TestAllTypesProto2.NestedMessage) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringStringEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringBytesEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringNestedMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringForeignMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringNestedEnumEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.MapStringForeignEnumEntry) +_sym_db.RegisterMessage(TestAllTypesProto2.Data) +_sym_db.RegisterMessage(TestAllTypesProto2.MessageSetCorrect) +_sym_db.RegisterMessage(TestAllTypesProto2.MessageSetCorrectExtension1) +_sym_db.RegisterMessage(TestAllTypesProto2.MessageSetCorrectExtension2) + +ForeignMessageProto2 = _reflection.GeneratedProtocolMessageType('ForeignMessageProto2', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGEPROTO2, + __module__ = 'google.protobuf.test_messages_proto2_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto2.ForeignMessageProto2) + )) +_sym_db.RegisterMessage(ForeignMessageProto2) + +TestAllTypesProto2.RegisterExtension(extension_int32) +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1.extensions_by_name['message_set_extension'].message_type = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1 +TestAllTypesProto2.MessageSetCorrect.RegisterExtension(_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION1.extensions_by_name['message_set_extension']) +_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2.extensions_by_name['message_set_extension'].message_type = _TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2 +TestAllTypesProto2.MessageSetCorrect.RegisterExtension(_TESTALLTYPESPROTO2_MESSAGESETCORRECTEXTENSION2.extensions_by_name['message_set_extension']) + +DESCRIPTOR._options = None +_TESTALLTYPESPROTO2_MAPINT32INT32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPINT64INT64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPUINT32UINT32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPUINT64UINT64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSINT32SINT32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSINT64SINT64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPFIXED32FIXED32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPFIXED64FIXED64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTALLTYPESPROTO2_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTALLTYPESPROTO2_MAPINT32FLOATENTRY._options = None +_TESTALLTYPESPROTO2_MAPINT32DOUBLEENTRY._options = None +_TESTALLTYPESPROTO2_MAPBOOLBOOLENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGSTRINGENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGBYTESENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDMESSAGEENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNMESSAGEENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGNESTEDENUMENTRY._options = None +_TESTALLTYPESPROTO2_MAPSTRINGFOREIGNENUMENTRY._options = None +_TESTALLTYPESPROTO2_MESSAGESETCORRECT._options = None +_TESTALLTYPESPROTO2.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPESPROTO2.fields_by_name['optional_cord']._options = None +_TESTALLTYPESPROTO2.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPESPROTO2.fields_by_name['repeated_cord']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto3_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto3_pb2.py new file mode 100644 index 0000000..81411cd --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/test_messages_proto3_pb2.py @@ -0,0 +1,2044 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/test_messages_proto3.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/test_messages_proto3.proto', + package='protobuf_test_messages.proto3', + syntax='proto3', + serialized_options=_b('\n(com.google.protobuf_test_messages.proto3H\001\370\001\001\242\002\006Proto3'), + serialized_pb=_b('\n*google/protobuf/test_messages_proto3.proto\x12\x1dprotobuf_test_messages.proto3\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\xb4;\n\x12TestAllTypesProto3\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12`\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage\x12O\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32-.protobuf_test_messages.proto3.ForeignMessage\x12Z\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum\x12I\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32*.protobuf_test_messages.proto3.ForeignEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12L\n\x11recursive_message\x18\x1b \x01(\x0b\x32\x31.protobuf_test_messages.proto3.TestAllTypesProto3\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12`\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage\x12O\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32-.protobuf_test_messages.proto3.ForeignMessage\x12Z\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum\x12I\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32*.protobuf_test_messages.proto3.ForeignEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12]\n\x0fmap_int32_int32\x18\x38 \x03(\x0b\x32\x44.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry\x12]\n\x0fmap_int64_int64\x18\x39 \x03(\x0b\x32\x44.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry\x12\x61\n\x11map_uint32_uint32\x18: \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry\x12\x61\n\x11map_uint64_uint64\x18; \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry\x12\x61\n\x11map_sint32_sint32\x18< \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry\x12\x61\n\x11map_sint64_sint64\x18= \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry\x12\x65\n\x13map_fixed32_fixed32\x18> \x03(\x0b\x32H.protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry\x12\x65\n\x13map_fixed64_fixed64\x18? \x03(\x0b\x32H.protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry\x12i\n\x15map_sfixed32_sfixed32\x18@ \x03(\x0b\x32J.protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry\x12i\n\x15map_sfixed64_sfixed64\x18\x41 \x03(\x0b\x32J.protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry\x12]\n\x0fmap_int32_float\x18\x42 \x03(\x0b\x32\x44.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry\x12_\n\x10map_int32_double\x18\x43 \x03(\x0b\x32\x45.protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry\x12Y\n\rmap_bool_bool\x18\x44 \x03(\x0b\x32\x42.protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry\x12\x61\n\x11map_string_string\x18\x45 \x03(\x0b\x32\x46.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry\x12_\n\x10map_string_bytes\x18\x46 \x03(\x0b\x32\x45.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry\x12p\n\x19map_string_nested_message\x18G \x03(\x0b\x32M.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry\x12r\n\x1amap_string_foreign_message\x18H \x03(\x0b\x32N.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry\x12j\n\x16map_string_nested_enum\x18I \x03(\x0b\x32J.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry\x12l\n\x17map_string_foreign_enum\x18J \x03(\x0b\x32K.protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12_\n\x14oneof_nested_message\x18p \x01(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12\x14\n\noneof_bool\x18s \x01(\x08H\x00\x12\x16\n\x0coneof_uint64\x18t \x01(\x04H\x00\x12\x15\n\x0boneof_float\x18u \x01(\x02H\x00\x12\x16\n\x0coneof_double\x18v \x01(\x01H\x00\x12R\n\noneof_enum\x18w \x01(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnumH\x00\x12:\n\x15optional_bool_wrapper\x18\xc9\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\x12<\n\x16optional_int32_wrapper\x18\xca\x01 \x01(\x0b\x32\x1b.google.protobuf.Int32Value\x12<\n\x16optional_int64_wrapper\x18\xcb\x01 \x01(\x0b\x32\x1b.google.protobuf.Int64Value\x12>\n\x17optional_uint32_wrapper\x18\xcc\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12>\n\x17optional_uint64_wrapper\x18\xcd\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12<\n\x16optional_float_wrapper\x18\xce\x01 \x01(\x0b\x32\x1b.google.protobuf.FloatValue\x12>\n\x17optional_double_wrapper\x18\xcf\x01 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue\x12>\n\x17optional_string_wrapper\x18\xd0\x01 \x01(\x0b\x32\x1c.google.protobuf.StringValue\x12<\n\x16optional_bytes_wrapper\x18\xd1\x01 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x12:\n\x15repeated_bool_wrapper\x18\xd3\x01 \x03(\x0b\x32\x1a.google.protobuf.BoolValue\x12<\n\x16repeated_int32_wrapper\x18\xd4\x01 \x03(\x0b\x32\x1b.google.protobuf.Int32Value\x12<\n\x16repeated_int64_wrapper\x18\xd5\x01 \x03(\x0b\x32\x1b.google.protobuf.Int64Value\x12>\n\x17repeated_uint32_wrapper\x18\xd6\x01 \x03(\x0b\x32\x1c.google.protobuf.UInt32Value\x12>\n\x17repeated_uint64_wrapper\x18\xd7\x01 \x03(\x0b\x32\x1c.google.protobuf.UInt64Value\x12<\n\x16repeated_float_wrapper\x18\xd8\x01 \x03(\x0b\x32\x1b.google.protobuf.FloatValue\x12>\n\x17repeated_double_wrapper\x18\xd9\x01 \x03(\x0b\x32\x1c.google.protobuf.DoubleValue\x12>\n\x17repeated_string_wrapper\x18\xda\x01 \x03(\x0b\x32\x1c.google.protobuf.StringValue\x12<\n\x16repeated_bytes_wrapper\x18\xdb\x01 \x03(\x0b\x32\x1b.google.protobuf.BytesValue\x12\x35\n\x11optional_duration\x18\xad\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x12optional_timestamp\x18\xae\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x38\n\x13optional_field_mask\x18\xaf\x02 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x31\n\x0foptional_struct\x18\xb0\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x12+\n\x0coptional_any\x18\xb1\x02 \x01(\x0b\x32\x14.google.protobuf.Any\x12/\n\x0eoptional_value\x18\xb2\x02 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x35\n\x11repeated_duration\x18\xb7\x02 \x03(\x0b\x32\x19.google.protobuf.Duration\x12\x37\n\x12repeated_timestamp\x18\xb8\x02 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x37\n\x12repeated_fieldmask\x18\xb9\x02 \x03(\x0b\x32\x1a.google.protobuf.FieldMask\x12\x31\n\x0frepeated_struct\x18\xc4\x02 \x03(\x0b\x32\x17.google.protobuf.Struct\x12+\n\x0crepeated_any\x18\xbb\x02 \x03(\x0b\x32\x14.google.protobuf.Any\x12/\n\x0erepeated_value\x18\xbc\x02 \x03(\x0b\x32\x16.google.protobuf.Value\x12\x13\n\nfieldname1\x18\x91\x03 \x01(\x05\x12\x14\n\x0b\x66ield_name2\x18\x92\x03 \x01(\x05\x12\x15\n\x0c_field_name3\x18\x93\x03 \x01(\x05\x12\x16\n\rfield__name4_\x18\x94\x03 \x01(\x05\x12\x14\n\x0b\x66ield0name5\x18\x95\x03 \x01(\x05\x12\x16\n\rfield_0_name6\x18\x96\x03 \x01(\x05\x12\x13\n\nfieldName7\x18\x97\x03 \x01(\x05\x12\x13\n\nFieldName8\x18\x98\x03 \x01(\x05\x12\x14\n\x0b\x66ield_Name9\x18\x99\x03 \x01(\x05\x12\x15\n\x0c\x46ield_Name10\x18\x9a\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_NAME11\x18\x9b\x03 \x01(\x05\x12\x15\n\x0c\x46IELD_name12\x18\x9c\x03 \x01(\x05\x12\x17\n\x0e__field_name13\x18\x9d\x03 \x01(\x05\x12\x17\n\x0e__Field_name14\x18\x9e\x03 \x01(\x05\x12\x16\n\rfield__name15\x18\x9f\x03 \x01(\x05\x12\x16\n\rfield__Name16\x18\xa0\x03 \x01(\x05\x12\x17\n\x0e\x66ield_name17__\x18\xa1\x03 \x01(\x05\x12\x17\n\x0e\x46ield_name18__\x18\xa2\x03 \x01(\x05\x1a\x62\n\rNestedMessage\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\x46\n\x0b\x63orecursive\x18\x02 \x01(\x0b\x32\x31.protobuf_test_messages.proto3.TestAllTypesProto3\x1a\x34\n\x12MapInt32Int32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x34\n\x12MapInt64Int64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x03:\x02\x38\x01\x1a\x36\n\x14MapUint32Uint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r:\x02\x38\x01\x1a\x36\n\x14MapUint64Uint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14MapSint32Sint32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x11\x12\r\n\x05value\x18\x02 \x01(\x11:\x02\x38\x01\x1a\x36\n\x14MapSint64Sint64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x12\x12\r\n\x05value\x18\x02 \x01(\x12:\x02\x38\x01\x1a\x38\n\x16MapFixed32Fixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05value\x18\x02 \x01(\x07:\x02\x38\x01\x1a\x38\n\x16MapFixed64Fixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x06\x12\r\n\x05value\x18\x02 \x01(\x06:\x02\x38\x01\x1a:\n\x18MapSfixed32Sfixed32Entry\x12\x0b\n\x03key\x18\x01 \x01(\x0f\x12\r\n\x05value\x18\x02 \x01(\x0f:\x02\x38\x01\x1a:\n\x18MapSfixed64Sfixed64Entry\x12\x0b\n\x03key\x18\x01 \x01(\x10\x12\r\n\x05value\x18\x02 \x01(\x10:\x02\x38\x01\x1a\x34\n\x12MapInt32FloatEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x02:\x02\x38\x01\x1a\x35\n\x13MapInt32DoubleEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\x1a\x32\n\x10MapBoolBoolEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x08:\x02\x38\x01\x1a\x36\n\x14MapStringStringEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x35\n\x13MapStringBytesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\x1a~\n\x1bMapStringNestedMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12N\n\x05value\x18\x02 \x01(\x0b\x32?.protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage:\x02\x38\x01\x1am\n\x1cMapStringForeignMessageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12<\n\x05value\x18\x02 \x01(\x0b\x32-.protobuf_test_messages.proto3.ForeignMessage:\x02\x38\x01\x1ax\n\x18MapStringNestedEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12K\n\x05value\x18\x02 \x01(\x0e\x32<.protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum:\x02\x38\x01\x1ag\n\x19MapStringForeignEnumEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x39\n\x05value\x18\x02 \x01(\x0e\x32*.protobuf_test_messages.proto3.ForeignEnum:\x02\x38\x01\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x12\x07\n\x03\x42\x41Z\x10\x02\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_fieldJ\x06\x08\xf5\x03\x10\xff\x03\"\x1b\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05*@\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x00\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x01\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x02\x42\x38\n(com.google.protobuf_test_messages.proto3H\x01\xf8\x01\x01\xa2\x02\x06Proto3b\x06proto3') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='protobuf_test_messages.proto3.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=7901, + serialized_end=7965, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +FOREIGN_FOO = 0 +FOREIGN_BAR = 1 +FOREIGN_BAZ = 2 + + +_TESTALLTYPESPROTO3_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=7790, + serialized_end=7847, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPESPROTO3_NESTEDENUM) + + +_TESTALLTYPESPROTO3_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='corecursive', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage.corecursive', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6384, + serialized_end=6482, +) + +_TESTALLTYPESPROTO3_MAPINT32INT32ENTRY = _descriptor.Descriptor( + name='MapInt32Int32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6484, + serialized_end=6536, +) + +_TESTALLTYPESPROTO3_MAPINT64INT64ENTRY = _descriptor.Descriptor( + name='MapInt64Int64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry.value', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6538, + serialized_end=6590, +) + +_TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY = _descriptor.Descriptor( + name='MapUint32Uint32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry.value', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6592, + serialized_end=6646, +) + +_TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY = _descriptor.Descriptor( + name='MapUint64Uint64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry.value', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6648, + serialized_end=6702, +) + +_TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY = _descriptor.Descriptor( + name='MapSint32Sint32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry.key', index=0, + number=1, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry.value', index=1, + number=2, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6704, + serialized_end=6758, +) + +_TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY = _descriptor.Descriptor( + name='MapSint64Sint64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry.key', index=0, + number=1, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry.value', index=1, + number=2, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6760, + serialized_end=6814, +) + +_TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY = _descriptor.Descriptor( + name='MapFixed32Fixed32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry.value', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6816, + serialized_end=6872, +) + +_TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY = _descriptor.Descriptor( + name='MapFixed64Fixed64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry.key', index=0, + number=1, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry.value', index=1, + number=2, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6874, + serialized_end=6930, +) + +_TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY = _descriptor.Descriptor( + name='MapSfixed32Sfixed32Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry.key', index=0, + number=1, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry.value', index=1, + number=2, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6932, + serialized_end=6990, +) + +_TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY = _descriptor.Descriptor( + name='MapSfixed64Sfixed64Entry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry.key', index=0, + number=1, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry.value', index=1, + number=2, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6992, + serialized_end=7050, +) + +_TESTALLTYPESPROTO3_MAPINT32FLOATENTRY = _descriptor.Descriptor( + name='MapInt32FloatEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry.value', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7052, + serialized_end=7104, +) + +_TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY = _descriptor.Descriptor( + name='MapInt32DoubleEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry.value', index=1, + number=2, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7106, + serialized_end=7159, +) + +_TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY = _descriptor.Descriptor( + name='MapBoolBoolEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry.value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7161, + serialized_end=7211, +) + +_TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY = _descriptor.Descriptor( + name='MapStringStringEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7213, + serialized_end=7267, +) + +_TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY = _descriptor.Descriptor( + name='MapStringBytesEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7269, + serialized_end=7322, +) + +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringNestedMessageEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7324, + serialized_end=7450, +) + +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY = _descriptor.Descriptor( + name='MapStringForeignMessageEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7452, + serialized_end=7561, +) + +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY = _descriptor.Descriptor( + name='MapStringNestedEnumEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7563, + serialized_end=7683, +) + +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY = _descriptor.Descriptor( + name='MapStringForeignEnumEntry', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry.value', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7685, + serialized_end=7788, +) + +_TESTALLTYPESPROTO3 = _descriptor.Descriptor( + name='TestAllTypesProto3', + full_name='protobuf_test_messages.proto3.TestAllTypesProto3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_nested_message', index=15, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_foreign_message', index=16, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_nested_enum', index=17, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_foreign_enum', index=18, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_string_piece', index=19, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_cord', index=20, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='recursive_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.recursive_message', index=21, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int32', index=22, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int64', index=23, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint32', index=24, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint64', index=25, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sint32', index=26, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sint64', index=27, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_fixed32', index=28, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_fixed64', index=29, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sfixed32', index=30, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_sfixed64', index=31, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_float', index=32, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_double', index=33, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bool', index=34, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_string', index=35, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bytes', index=36, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_nested_message', index=37, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_foreign_message', index=38, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_nested_enum', index=39, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_foreign_enum', index=40, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_string_piece', index=41, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_cord', index=42, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_int32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int32_int32', index=43, + number=56, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int64_int64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int64_int64', index=44, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint32_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_uint32_uint32', index=45, + number=58, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_uint64_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_uint64_uint64', index=46, + number=59, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint32_sint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sint32_sint32', index=47, + number=60, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sint64_sint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sint64_sint64', index=48, + number=61, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed32_fixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_fixed32_fixed32', index=49, + number=62, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_fixed64_fixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_fixed64_fixed64', index=50, + number=63, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed32_sfixed32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sfixed32_sfixed32', index=51, + number=64, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_sfixed64_sfixed64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_sfixed64_sfixed64', index=52, + number=65, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int32_float', index=53, + number=66, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_int32_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_int32_double', index=54, + number=67, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_bool_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_bool_bool', index=55, + number=68, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_string', index=56, + number=69, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_bytes', index=57, + number=70, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_nested_message', index=58, + number=71, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_foreign_message', index=59, + number=72, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_nested_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_nested_enum', index=60, + number=73, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_string_foreign_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.map_string_foreign_enum', index=61, + number=74, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_uint32', index=62, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_nested_message', index=63, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_string', index=64, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_bytes', index=65, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bool', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_bool', index=66, + number=115, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint64', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_uint64', index=67, + number=116, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_float', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_float', index=68, + number=117, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_double', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_double', index=69, + number=118, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_enum', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_enum', index=70, + number=119, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bool_wrapper', index=71, + number=201, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int32_wrapper', index=72, + number=202, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_int64_wrapper', index=73, + number=203, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint32_wrapper', index=74, + number=204, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_uint64_wrapper', index=75, + number=205, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_float_wrapper', index=76, + number=206, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_double_wrapper', index=77, + number=207, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_string_wrapper', index=78, + number=208, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_bytes_wrapper', index=79, + number=209, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bool_wrapper', index=80, + number=211, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int32_wrapper', index=81, + number=212, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_int64_wrapper', index=82, + number=213, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint32_wrapper', index=83, + number=214, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_uint64_wrapper', index=84, + number=215, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_float_wrapper', index=85, + number=216, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_double_wrapper', index=86, + number=217, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_string_wrapper', index=87, + number=218, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes_wrapper', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_bytes_wrapper', index=88, + number=219, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_duration', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_duration', index=89, + number=301, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_timestamp', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_timestamp', index=90, + number=302, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_field_mask', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_field_mask', index=91, + number=303, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_struct', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_struct', index=92, + number=304, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_any', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_any', index=93, + number=305, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.optional_value', index=94, + number=306, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_duration', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_duration', index=95, + number=311, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_timestamp', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_timestamp', index=96, + number=312, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fieldmask', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_fieldmask', index=97, + number=313, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_struct', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_struct', index=98, + number=324, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_any', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_any', index=99, + number=315, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.repeated_value', index=100, + number=316, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldname1', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.fieldname1', index=101, + number=401, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name2', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_name2', index=102, + number=402, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='_field_name3', full_name='protobuf_test_messages.proto3.TestAllTypesProto3._field_name3', index=103, + number=403, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name4_', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field__name4_', index=104, + number=404, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field0name5', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field0name5', index=105, + number=405, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_0_name6', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_0_name6', index=106, + number=406, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldName7', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.fieldName7', index=107, + number=407, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FieldName8', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.FieldName8', index=108, + number=408, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_Name9', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_Name9', index=109, + number=409, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_Name10', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.Field_Name10', index=110, + number=410, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_NAME11', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.FIELD_NAME11', index=111, + number=411, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_name12', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.FIELD_name12', index=112, + number=412, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__field_name13', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.__field_name13', index=113, + number=413, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='__Field_name14', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.__Field_name14', index=114, + number=414, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__name15', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field__name15', index=115, + number=415, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field__Name16', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field__Name16', index=116, + number=416, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name17__', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.field_name17__', index=117, + number=417, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='Field_name18__', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.Field_name18__', index=118, + number=418, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPESPROTO3_NESTEDMESSAGE, _TESTALLTYPESPROTO3_MAPINT32INT32ENTRY, _TESTALLTYPESPROTO3_MAPINT64INT64ENTRY, _TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY, _TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY, _TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY, _TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY, _TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY, _TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY, _TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY, _TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY, _TESTALLTYPESPROTO3_MAPINT32FLOATENTRY, _TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY, _TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY, _TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY, _TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY, _TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY, _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY, _TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY, _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY, ], + enum_types=[ + _TESTALLTYPESPROTO3_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_test_messages.proto3.TestAllTypesProto3.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=266, + serialized_end=7870, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='protobuf_test_messages.proto3.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_test_messages.proto3.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7872, + serialized_end=7899, +) + +_TESTALLTYPESPROTO3_NESTEDMESSAGE.fields_by_name['corecursive'].message_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_NESTEDMESSAGE.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT32INT32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT64INT64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT32FLOATENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY.fields_by_name['value'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY.fields_by_name['value'].message_type = _FOREIGNMESSAGE +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY.fields_by_name['value'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY.fields_by_name['value'].enum_type = _FOREIGNENUM +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPESPROTO3.fields_by_name['recursive_message'].message_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPESPROTO3.fields_by_name['map_int32_int32'].message_type = _TESTALLTYPESPROTO3_MAPINT32INT32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_int64_int64'].message_type = _TESTALLTYPESPROTO3_MAPINT64INT64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_uint32_uint32'].message_type = _TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_uint64_uint64'].message_type = _TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sint32_sint32'].message_type = _TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sint64_sint64'].message_type = _TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_fixed32_fixed32'].message_type = _TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_fixed64_fixed64'].message_type = _TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sfixed32_sfixed32'].message_type = _TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_sfixed64_sfixed64'].message_type = _TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_int32_float'].message_type = _TESTALLTYPESPROTO3_MAPINT32FLOATENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_int32_double'].message_type = _TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_bool_bool'].message_type = _TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_string'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_bytes'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_nested_message'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_foreign_message'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_nested_enum'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY +_TESTALLTYPESPROTO3.fields_by_name['map_string_foreign_enum'].message_type = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY +_TESTALLTYPESPROTO3.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPESPROTO3_NESTEDMESSAGE +_TESTALLTYPESPROTO3.fields_by_name['oneof_enum'].enum_type = _TESTALLTYPESPROTO3_NESTEDENUM +_TESTALLTYPESPROTO3.fields_by_name['optional_bool_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_int32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_int64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_uint32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_uint64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_float_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_double_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_string_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_bytes_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_bool_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_int32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_int64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_uint32_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_uint64_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_float_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_double_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_string_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_bytes_wrapper'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTALLTYPESPROTO3.fields_by_name['optional_duration'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTALLTYPESPROTO3.fields_by_name['optional_timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTALLTYPESPROTO3.fields_by_name['optional_field_mask'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTALLTYPESPROTO3.fields_by_name['optional_struct'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTALLTYPESPROTO3.fields_by_name['optional_any'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTALLTYPESPROTO3.fields_by_name['optional_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTALLTYPESPROTO3.fields_by_name['repeated_duration'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTALLTYPESPROTO3.fields_by_name['repeated_timestamp'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTALLTYPESPROTO3.fields_by_name['repeated_fieldmask'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTALLTYPESPROTO3.fields_by_name['repeated_struct'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTALLTYPESPROTO3.fields_by_name['repeated_any'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTALLTYPESPROTO3.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTALLTYPESPROTO3_NESTEDENUM.containing_type = _TESTALLTYPESPROTO3 +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_uint32']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_nested_message']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_string']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_bytes']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_bool']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_bool'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_uint64']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_uint64'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_float']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_float'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_double']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_double'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +_TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPESPROTO3.fields_by_name['oneof_enum']) +_TESTALLTYPESPROTO3.fields_by_name['oneof_enum'].containing_oneof = _TESTALLTYPESPROTO3.oneofs_by_name['oneof_field'] +DESCRIPTOR.message_types_by_name['TestAllTypesProto3'] = _TESTALLTYPESPROTO3 +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypesProto3 = _reflection.GeneratedProtocolMessageType('TestAllTypesProto3', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_NESTEDMESSAGE, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.NestedMessage) + )) + , + + MapInt32Int32Entry = _reflection.GeneratedProtocolMessageType('MapInt32Int32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT32INT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32Int32Entry) + )) + , + + MapInt64Int64Entry = _reflection.GeneratedProtocolMessageType('MapInt64Int64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT64INT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt64Int64Entry) + )) + , + + MapUint32Uint32Entry = _reflection.GeneratedProtocolMessageType('MapUint32Uint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapUint32Uint32Entry) + )) + , + + MapUint64Uint64Entry = _reflection.GeneratedProtocolMessageType('MapUint64Uint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapUint64Uint64Entry) + )) + , + + MapSint32Sint32Entry = _reflection.GeneratedProtocolMessageType('MapSint32Sint32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSint32Sint32Entry) + )) + , + + MapSint64Sint64Entry = _reflection.GeneratedProtocolMessageType('MapSint64Sint64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSint64Sint64Entry) + )) + , + + MapFixed32Fixed32Entry = _reflection.GeneratedProtocolMessageType('MapFixed32Fixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed32Fixed32Entry) + )) + , + + MapFixed64Fixed64Entry = _reflection.GeneratedProtocolMessageType('MapFixed64Fixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapFixed64Fixed64Entry) + )) + , + + MapSfixed32Sfixed32Entry = _reflection.GeneratedProtocolMessageType('MapSfixed32Sfixed32Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed32Sfixed32Entry) + )) + , + + MapSfixed64Sfixed64Entry = _reflection.GeneratedProtocolMessageType('MapSfixed64Sfixed64Entry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapSfixed64Sfixed64Entry) + )) + , + + MapInt32FloatEntry = _reflection.GeneratedProtocolMessageType('MapInt32FloatEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT32FLOATENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32FloatEntry) + )) + , + + MapInt32DoubleEntry = _reflection.GeneratedProtocolMessageType('MapInt32DoubleEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapInt32DoubleEntry) + )) + , + + MapBoolBoolEntry = _reflection.GeneratedProtocolMessageType('MapBoolBoolEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapBoolBoolEntry) + )) + , + + MapStringStringEntry = _reflection.GeneratedProtocolMessageType('MapStringStringEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringStringEntry) + )) + , + + MapStringBytesEntry = _reflection.GeneratedProtocolMessageType('MapStringBytesEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringBytesEntry) + )) + , + + MapStringNestedMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedMessageEntry) + )) + , + + MapStringForeignMessageEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignMessageEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignMessageEntry) + )) + , + + MapStringNestedEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringNestedEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringNestedEnumEntry) + )) + , + + MapStringForeignEnumEntry = _reflection.GeneratedProtocolMessageType('MapStringForeignEnumEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3.MapStringForeignEnumEntry) + )) + , + DESCRIPTOR = _TESTALLTYPESPROTO3, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.TestAllTypesProto3) + )) +_sym_db.RegisterMessage(TestAllTypesProto3) +_sym_db.RegisterMessage(TestAllTypesProto3.NestedMessage) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt32Int32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt64Int64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapUint32Uint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapUint64Uint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSint32Sint32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSint64Sint64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapFixed32Fixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapFixed64Fixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSfixed32Sfixed32Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapSfixed64Sfixed64Entry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt32FloatEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapInt32DoubleEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapBoolBoolEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringStringEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringBytesEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringNestedMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringForeignMessageEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringNestedEnumEntry) +_sym_db.RegisterMessage(TestAllTypesProto3.MapStringForeignEnumEntry) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.test_messages_proto3_pb2' + # @@protoc_insertion_point(class_scope:protobuf_test_messages.proto3.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + + +DESCRIPTOR._options = None +_TESTALLTYPESPROTO3_MAPINT32INT32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPINT64INT64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPUINT32UINT32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPUINT64UINT64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSINT32SINT32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSINT64SINT64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPFIXED32FIXED32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPFIXED64FIXED64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSFIXED32SFIXED32ENTRY._options = None +_TESTALLTYPESPROTO3_MAPSFIXED64SFIXED64ENTRY._options = None +_TESTALLTYPESPROTO3_MAPINT32FLOATENTRY._options = None +_TESTALLTYPESPROTO3_MAPINT32DOUBLEENTRY._options = None +_TESTALLTYPESPROTO3_MAPBOOLBOOLENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGSTRINGENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGBYTESENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDMESSAGEENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNMESSAGEENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGNESTEDENUMENTRY._options = None +_TESTALLTYPESPROTO3_MAPSTRINGFOREIGNENUMENTRY._options = None +_TESTALLTYPESPROTO3.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPESPROTO3.fields_by_name['optional_cord']._options = None +_TESTALLTYPESPROTO3.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPESPROTO3.fields_by_name['repeated_cord']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/text_encoding.py b/venv/lib/python3.7/site-packages/google/protobuf/text_encoding.py new file mode 100644 index 0000000..9899563 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/text_encoding.py @@ -0,0 +1,107 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Encoding related utilities.""" +import re + +import six + +# Lookup table for utf8 +_cescape_utf8_to_str = [chr(i) for i in range(0, 256)] +_cescape_utf8_to_str[9] = r'\t' # optional escape +_cescape_utf8_to_str[10] = r'\n' # optional escape +_cescape_utf8_to_str[13] = r'\r' # optional escape +_cescape_utf8_to_str[39] = r"\'" # optional escape + +_cescape_utf8_to_str[34] = r'\"' # necessary escape +_cescape_utf8_to_str[92] = r'\\' # necessary escape + +# Lookup table for non-utf8, with necessary escapes at (o >= 127 or o < 32) +_cescape_byte_to_str = ([r'\%03o' % i for i in range(0, 32)] + + [chr(i) for i in range(32, 127)] + + [r'\%03o' % i for i in range(127, 256)]) +_cescape_byte_to_str[9] = r'\t' # optional escape +_cescape_byte_to_str[10] = r'\n' # optional escape +_cescape_byte_to_str[13] = r'\r' # optional escape +_cescape_byte_to_str[39] = r"\'" # optional escape + +_cescape_byte_to_str[34] = r'\"' # necessary escape +_cescape_byte_to_str[92] = r'\\' # necessary escape + + +def CEscape(text, as_utf8): + """Escape a bytes string for use in an ascii protocol buffer. + + text.encode('string_escape') does not seem to satisfy our needs as it + encodes unprintable characters using two-digit hex escapes whereas our + C++ unescaping function allows hex escapes to be any length. So, + "\0011".encode('string_escape') ends up being "\\x011", which will be + decoded in C++ as a single-character string with char code 0x11. + + Args: + text: A byte string to be escaped + as_utf8: Specifies if result should be returned in UTF-8 encoding + Returns: + Escaped string + """ + # PY3 hack: make Ord work for str and bytes: + # //platforms/networking/data uses unicode here, hence basestring. + Ord = ord if isinstance(text, six.string_types) else lambda x: x + if as_utf8: + return ''.join(_cescape_utf8_to_str[Ord(c)] for c in text) + return ''.join(_cescape_byte_to_str[Ord(c)] for c in text) + + +_CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])') +_cescape_highbit_to_str = ([chr(i) for i in range(0, 127)] + + [r'\%03o' % i for i in range(127, 256)]) + + +def CUnescape(text): + """Unescape a text string with C-style escape sequences to UTF-8 bytes.""" + + def ReplaceHex(m): + # Only replace the match if the number of leading back slashes is odd. i.e. + # the slash itself is not escaped. + if len(m.group(1)) & 1: + return m.group(1) + 'x0' + m.group(2) + return m.group(0) + + # This is required because the 'string_escape' encoding doesn't + # allow single-digit hex escapes (like '\xf'). + result = _CUNESCAPE_HEX.sub(ReplaceHex, text) + + if str is bytes: # PY2 + return result.decode('string_escape') + result = ''.join(_cescape_highbit_to_str[ord(c)] for c in result) + return (result.encode('ascii') # Make it bytes to allow decode. + .decode('unicode_escape') + # Make it bytes again to return the proper type. + .encode('raw_unicode_escape')) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/text_format.py b/venv/lib/python3.7/site-packages/google/protobuf/text_format.py new file mode 100644 index 0000000..4a6b062 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/text_format.py @@ -0,0 +1,1593 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 +# OWNER 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. + +"""Contains routines for printing protocol messages in text format. + +Simple usage example: + + # Create a proto object and serialize it to a text proto string. + message = my_proto_pb2.MyMessage(foo='bar') + text_proto = text_format.MessageToString(message) + + # Parse a text proto string. + message = text_format.Parse(text_proto, my_proto_pb2.MyMessage()) +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import io +import re + +import six + +if six.PY3: + long = int # pylint: disable=redefined-builtin,invalid-name + +# pylint: disable=g-import-not-at-top +from google.protobuf.internal import type_checkers +from google.protobuf import descriptor +from google.protobuf import text_encoding + +__all__ = ['MessageToString', 'PrintMessage', 'PrintField', 'PrintFieldValue', + 'Merge'] + +_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(), + type_checkers.Int32ValueChecker(), + type_checkers.Uint64ValueChecker(), + type_checkers.Int64ValueChecker()) +_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE) +_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE) +_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, + descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) +_QUOTES = frozenset(("'", '"')) +_ANY_FULL_TYPE_NAME = 'google.protobuf.Any' + + +class Error(Exception): + """Top-level module error for text_format.""" + + +class ParseError(Error): + """Thrown in case of text parsing or tokenizing error.""" + + def __init__(self, message=None, line=None, column=None): + if message is not None and line is not None: + loc = str(line) + if column is not None: + loc += ':{0}'.format(column) + message = '{0} : {1}'.format(loc, message) + if message is not None: + super(ParseError, self).__init__(message) + else: + super(ParseError, self).__init__() + self._line = line + self._column = column + + def GetLine(self): + return self._line + + def GetColumn(self): + return self._column + + +class TextWriter(object): + + def __init__(self, as_utf8): + if six.PY2: + self._writer = io.BytesIO() + else: + self._writer = io.StringIO() + + def write(self, val): + if six.PY2: + if isinstance(val, six.text_type): + val = val.encode('utf-8') + return self._writer.write(val) + + def close(self): + return self._writer.close() + + def getvalue(self): + return self._writer.getvalue() + + +def MessageToString(message, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + use_field_number=False, + descriptor_pool=None, + indent=0, + message_formatter=None): + """Convert protobuf message to text format. + + Floating point values can be formatted compactly with 15 digits of + precision (which is the most that IEEE 754 "double" can guarantee) + using float_format='.15g'. To ensure that converting to text and back to a + proto will result in an identical value, float_format='.17g' should be used. + + Args: + message: The protocol buffers message. + as_utf8: Produce text output in UTF8 format. + as_one_line: Don't introduce newlines between fields. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, fields of a proto message will be printed using + the order defined in source code instead of the field number, extensions + will be printed at the end of the message and their relative order is + determined by the extension number. By default, use the field number + order. + float_format: If set, use this to specify floating point number formatting + (per the "Format Specification Mini-Language"); otherwise, str() is used. + use_field_number: If True, print field numbers instead of names. + descriptor_pool: A DescriptorPool used to resolve Any types. + indent: The indent level, in terms of spaces, for pretty print. + message_formatter: A function(message, indent, as_one_line): unicode|None + to custom format selected sub-messages (usually based on message type). + Use to pretty print parts of the protobuf for easier diffing. + + Returns: + A string of the text formatted protocol buffer message. + """ + out = TextWriter(as_utf8) + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, use_field_number, + descriptor_pool, message_formatter) + printer.PrintMessage(message) + result = out.getvalue() + out.close() + if as_one_line: + return result.rstrip() + return result + + +def _IsMapEntry(field): + return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) + + +def PrintMessage(message, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None): + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, use_field_number, + descriptor_pool, message_formatter) + printer.PrintMessage(message) + + +def PrintField(field, + value, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + message_formatter=None): + """Print a single field name/value pair.""" + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, message_formatter) + printer.PrintField(field, value) + + +def PrintFieldValue(field, + value, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + message_formatter=None): + """Print a single field value (not including name).""" + printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets, + use_index_order, float_format, message_formatter) + printer.PrintFieldValue(field, value) + + +def _BuildMessageFromTypeName(type_name, descriptor_pool): + """Returns a protobuf message instance. + + Args: + type_name: Fully-qualified protobuf message type name string. + descriptor_pool: DescriptorPool instance. + + Returns: + A Message instance of type matching type_name, or None if the a Descriptor + wasn't found matching type_name. + """ + # pylint: disable=g-import-not-at-top + if descriptor_pool is None: + from google.protobuf import descriptor_pool as pool_mod + descriptor_pool = pool_mod.Default() + from google.protobuf import symbol_database + database = symbol_database.Default() + try: + message_descriptor = descriptor_pool.FindMessageTypeByName(type_name) + except KeyError: + return None + message_type = database.GetPrototype(message_descriptor) + return message_type() + + +class _Printer(object): + """Text format printer for protocol message.""" + + def __init__(self, + out, + indent=0, + as_utf8=False, + as_one_line=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None): + """Initialize the Printer. + + Floating point values can be formatted compactly with 15 digits of + precision (which is the most that IEEE 754 "double" can guarantee) + using float_format='.15g'. To ensure that converting to text and back to a + proto will result in an identical value, float_format='.17g' should be used. + + Args: + out: To record the text format result. + indent: The indent level for pretty print. + as_utf8: Produce text output in UTF8 format. + as_one_line: Don't introduce newlines between fields. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, print fields of a proto message using the order + defined in source code instead of the field number. By default, use the + field number order. + float_format: If set, use this to specify floating point number formatting + (per the "Format Specification Mini-Language"); otherwise, str() is + used. + use_field_number: If True, print field numbers instead of names. + descriptor_pool: A DescriptorPool used to resolve Any types. + message_formatter: A function(message, indent, as_one_line): unicode|None + to custom format selected sub-messages (usually based on message type). + Use to pretty print parts of the protobuf for easier diffing. + """ + self.out = out + self.indent = indent + self.as_utf8 = as_utf8 + self.as_one_line = as_one_line + self.pointy_brackets = pointy_brackets + self.use_index_order = use_index_order + self.float_format = float_format + self.use_field_number = use_field_number + self.descriptor_pool = descriptor_pool + self.message_formatter = message_formatter + + def _TryPrintAsAnyMessage(self, message): + """Serializes if message is a google.protobuf.Any field.""" + packed_message = _BuildMessageFromTypeName(message.TypeName(), + self.descriptor_pool) + if packed_message: + packed_message.MergeFromString(message.value) + self.out.write('%s[%s]' % (self.indent * ' ', message.type_url)) + self._PrintMessageFieldValue(packed_message) + self.out.write(' ' if self.as_one_line else '\n') + return True + else: + return False + + def _TryCustomFormatMessage(self, message): + formatted = self.message_formatter(message, self.indent, self.as_one_line) + if formatted is None: + return False + + out = self.out + out.write(' ' * self.indent) + out.write(formatted) + out.write(' ' if self.as_one_line else '\n') + return True + + def PrintMessage(self, message): + """Convert protobuf message to text format. + + Args: + message: The protocol buffers message. + """ + if self.message_formatter and self._TryCustomFormatMessage(message): + return + if (message.DESCRIPTOR.full_name == _ANY_FULL_TYPE_NAME and + self._TryPrintAsAnyMessage(message)): + return + fields = message.ListFields() + if self.use_index_order: + fields.sort( + key=lambda x: x[0].number if x[0].is_extension else x[0].index) + for field, value in fields: + if _IsMapEntry(field): + for key in sorted(value): + # This is slow for maps with submessage entries because it copies the + # entire tree. Unfortunately this would take significant refactoring + # of this file to work around. + # + # TODO(haberman): refactor and optimize if this becomes an issue. + entry_submsg = value.GetEntryClass()(key=key, value=value[key]) + self.PrintField(field, entry_submsg) + elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + for element in value: + self.PrintField(field, element) + else: + self.PrintField(field, value) + + def PrintField(self, field, value): + """Print a single field name/value pair.""" + out = self.out + out.write(' ' * self.indent) + if self.use_field_number: + out.write(str(field.number)) + else: + if field.is_extension: + out.write('[') + if (field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): + out.write(field.message_type.full_name) + else: + out.write(field.full_name) + out.write(']') + elif field.type == descriptor.FieldDescriptor.TYPE_GROUP: + # For groups, use the capitalized name. + out.write(field.message_type.name) + else: + out.write(field.name) + + if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + # The colon is optional in this case, but our cross-language golden files + # don't include it. + out.write(': ') + + self.PrintFieldValue(field, value) + if self.as_one_line: + out.write(' ') + else: + out.write('\n') + + def _PrintMessageFieldValue(self, value): + if self.pointy_brackets: + openb = '<' + closeb = '>' + else: + openb = '{' + closeb = '}' + + if self.as_one_line: + self.out.write(' %s ' % openb) + self.PrintMessage(value) + self.out.write(closeb) + else: + self.out.write(' %s\n' % openb) + self.indent += 2 + self.PrintMessage(value) + self.indent -= 2 + self.out.write(' ' * self.indent + closeb) + + def PrintFieldValue(self, field, value): + """Print a single field value (not including name). + + For repeated fields, the value should be a single element. + + Args: + field: The descriptor of the field to be printed. + value: The value of the field. + """ + out = self.out + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + self._PrintMessageFieldValue(value) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: + enum_value = field.enum_type.values_by_number.get(value, None) + if enum_value is not None: + out.write(enum_value.name) + else: + out.write(str(value)) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: + out.write('\"') + if isinstance(value, six.text_type): + out_value = value.encode('utf-8') + else: + out_value = value + if field.type == descriptor.FieldDescriptor.TYPE_BYTES: + # We need to escape non-UTF8 chars in TYPE_BYTES field. + out_as_utf8 = False + else: + out_as_utf8 = self.as_utf8 + out.write(text_encoding.CEscape(out_value, out_as_utf8)) + out.write('\"') + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: + if value: + out.write('true') + else: + out.write('false') + elif field.cpp_type in _FLOAT_TYPES and self.float_format is not None: + out.write('{1:{0}}'.format(self.float_format, value)) + else: + out.write(str(value)) + + +def Parse(text, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + NOTE: for historical reasons this function does not clear the input + message. This is different from what the binary msg.ParseFrom(...) does. + + Example + a = MyProto() + a.repeated_field.append('test') + b = MyProto() + + text_format.Parse(repr(a), b) + text_format.Parse(repr(a), b) # repeated_field contains ["test", "test"] + + # Binary version: + b.ParseFromString(a.SerializeToString()) # repeated_field is now "test" + + Caller is responsible for clearing the message as needed. + + Args: + text: Message text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + if not isinstance(text, str): + if six.PY3: + text = text.decode('utf-8') + else: + text = text.encode('utf-8') + return ParseLines(text.split('\n'), + message, + allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + + +def Merge(text, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + Like Parse(), but allows repeated values for a non-repeated field, and uses + the last one. + + Args: + text: Message text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + if not isinstance(text, str): + if six.PY3: + text = text.decode('utf-8') + else: + text = text.encode('utf-8') + return MergeLines( + text.split('\n'), + message, + allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + + +def ParseLines(lines, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + Args: + lines: An iterable of lines of a message's text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + parser = _Parser(allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + return parser.ParseLines(lines, message) + + +def MergeLines(lines, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + """Parses a text representation of a protocol message into a message. + + Args: + lines: An iterable of lines of a message's text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + parser = _Parser(allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool) + return parser.MergeLines(lines, message) + + +class _Parser(object): + """Text format parser for protocol message.""" + + def __init__(self, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None): + self.allow_unknown_extension = allow_unknown_extension + self.allow_field_number = allow_field_number + self.descriptor_pool = descriptor_pool + + def ParseFromString(self, text, message): + """Parses a text representation of a protocol message into a message.""" + if not isinstance(text, str): + text = text.decode('utf-8') + return self.ParseLines(text.split('\n'), message) + + def ParseLines(self, lines, message): + """Parses a text representation of a protocol message into a message.""" + self._allow_multiple_scalars = False + self._ParseOrMerge(lines, message) + return message + + def MergeFromString(self, text, message): + """Merges a text representation of a protocol message into a message.""" + return self._MergeLines(text.split('\n'), message) + + def MergeLines(self, lines, message): + """Merges a text representation of a protocol message into a message.""" + self._allow_multiple_scalars = True + self._ParseOrMerge(lines, message) + return message + + def _ParseOrMerge(self, lines, message): + """Converts a text representation of a protocol message into a message. + + Args: + lines: Lines of a message's text representation. + message: A protocol buffer message to merge into. + + Raises: + ParseError: On text parsing problems. + """ + tokenizer = Tokenizer(lines) + while not tokenizer.AtEnd(): + self._MergeField(tokenizer, message) + + def _MergeField(self, tokenizer, message): + """Merges a single protocol message field into a message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + message: A protocol message to record the data. + + Raises: + ParseError: In case of text parsing problems. + """ + message_descriptor = message.DESCRIPTOR + if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and + tokenizer.TryConsume('[')): + type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer) + tokenizer.Consume(']') + tokenizer.TryConsume(':') + if tokenizer.TryConsume('<'): + expanded_any_end_token = '>' + else: + tokenizer.Consume('{') + expanded_any_end_token = '}' + expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name, + self.descriptor_pool) + if not expanded_any_sub_message: + raise ParseError('Type %s not found in descriptor pool' % + packed_type_name) + while not tokenizer.TryConsume(expanded_any_end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % + (expanded_any_end_token,)) + self._MergeField(tokenizer, expanded_any_sub_message) + message.Pack(expanded_any_sub_message, + type_url_prefix=type_url_prefix) + return + + if tokenizer.TryConsume('['): + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + name = '.'.join(name) + + if not message_descriptor.is_extendable: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" does not have extensions.' % + message_descriptor.full_name) + # pylint: disable=protected-access + field = message.Extensions._FindExtensionByName(name) + # pylint: enable=protected-access + if not field: + if self.allow_unknown_extension: + field = None + else: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" not registered. ' + 'Did you import the _pb2 module which defines it? ' + 'If you are trying to place the extension in the MessageSet ' + 'field of another message that is in an Any or MessageSet field, ' + 'that message\'s _pb2 module must be imported as well' % name) + elif message_descriptor != field.containing_type: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" does not extend message type "%s".' % + (name, message_descriptor.full_name)) + + tokenizer.Consume(']') + + else: + name = tokenizer.ConsumeIdentifierOrNumber() + if self.allow_field_number and name.isdigit(): + number = ParseInteger(name, True, True) + field = message_descriptor.fields_by_number.get(number, None) + if not field and message_descriptor.is_extendable: + field = message.Extensions._FindExtensionByNumber(number) + else: + field = message_descriptor.fields_by_name.get(name, None) + + # Group names are expected to be capitalized as they appear in the + # .proto file, which actually matches their type names, not their field + # names. + if not field: + field = message_descriptor.fields_by_name.get(name.lower(), None) + if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP: + field = None + + if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and + field.message_type.name != name): + field = None + + if not field: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" has no field named "%s".' % + (message_descriptor.full_name, name)) + + if field: + if not self._allow_multiple_scalars and field.containing_oneof: + # Check if there's a different field set in this oneof. + # Note that we ignore the case if the same field was set before, and we + # apply _allow_multiple_scalars to non-scalar fields as well. + which_oneof = message.WhichOneof(field.containing_oneof.name) + if which_oneof is not None and which_oneof != field.name: + raise tokenizer.ParseErrorPreviousToken( + 'Field "%s" is specified along with field "%s", another member ' + 'of oneof "%s" for message type "%s".' % + (field.name, which_oneof, field.containing_oneof.name, + message_descriptor.full_name)) + + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + tokenizer.TryConsume(':') + merger = self._MergeMessageField + else: + tokenizer.Consume(':') + merger = self._MergeScalarField + + if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and + tokenizer.TryConsume('[')): + # Short repeated format, e.g. "foo: [1, 2, 3]" + if not tokenizer.TryConsume(']'): + while True: + merger(tokenizer, message, field) + if tokenizer.TryConsume(']'): + break + tokenizer.Consume(',') + + else: + merger(tokenizer, message, field) + + else: # Proto field is unknown. + assert self.allow_unknown_extension + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + def _ConsumeAnyTypeUrl(self, tokenizer): + """Consumes a google.protobuf.Any type URL and returns the type name.""" + # Consume "type.googleapis.com/". + prefix = [tokenizer.ConsumeIdentifier()] + tokenizer.Consume('.') + prefix.append(tokenizer.ConsumeIdentifier()) + tokenizer.Consume('.') + prefix.append(tokenizer.ConsumeIdentifier()) + tokenizer.Consume('/') + # Consume the fully-qualified type name. + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + return '.'.join(prefix), '.'.join(name) + + def _MergeMessageField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: The message of which field is a member. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + """ + is_map_entry = _IsMapEntry(field) + + if tokenizer.TryConsume('<'): + end_token = '>' + else: + tokenizer.Consume('{') + end_token = '}' + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + sub_message = message.Extensions[field].add() + elif is_map_entry: + sub_message = getattr(message, field.name).GetEntryClass()() + else: + sub_message = getattr(message, field.name).add() + else: + if field.is_extension: + if (not self._allow_multiple_scalars and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + sub_message = message.Extensions[field] + else: + # Also apply _allow_multiple_scalars to message field. + # TODO(jieluo): Change to _allow_singular_overwrites. + if (not self._allow_multiple_scalars and + message.HasField(field.name)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + sub_message = getattr(message, field.name) + sub_message.SetInParent() + + while not tokenizer.TryConsume(end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,)) + self._MergeField(tokenizer, sub_message) + + if is_map_entry: + value_cpptype = field.message_type.fields_by_name['value'].cpp_type + if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + value = getattr(message, field.name)[sub_message.key] + value.MergeFrom(sub_message.value) + else: + getattr(message, field.name)[sub_message.key] = sub_message.value + + @staticmethod + def _IsProto3Syntax(message): + message_descriptor = message.DESCRIPTOR + return (hasattr(message_descriptor, 'syntax') and + message_descriptor.syntax == 'proto3') + + def _MergeScalarField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: A protocol message to record the data. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + RuntimeError: On runtime errors. + """ + _ = self.allow_unknown_extension + value = None + + if field.type in (descriptor.FieldDescriptor.TYPE_INT32, + descriptor.FieldDescriptor.TYPE_SINT32, + descriptor.FieldDescriptor.TYPE_SFIXED32): + value = _ConsumeInt32(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_INT64, + descriptor.FieldDescriptor.TYPE_SINT64, + descriptor.FieldDescriptor.TYPE_SFIXED64): + value = _ConsumeInt64(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32, + descriptor.FieldDescriptor.TYPE_FIXED32): + value = _ConsumeUint32(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64, + descriptor.FieldDescriptor.TYPE_FIXED64): + value = _ConsumeUint64(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT, + descriptor.FieldDescriptor.TYPE_DOUBLE): + value = tokenizer.ConsumeFloat() + elif field.type == descriptor.FieldDescriptor.TYPE_BOOL: + value = tokenizer.ConsumeBool() + elif field.type == descriptor.FieldDescriptor.TYPE_STRING: + value = tokenizer.ConsumeString() + elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: + value = tokenizer.ConsumeByteString() + elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: + value = tokenizer.ConsumeEnum(field) + else: + raise RuntimeError('Unknown field type %d' % field.type) + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + message.Extensions[field].append(value) + else: + getattr(message, field.name).append(value) + else: + # Proto3 doesn't represent presence so we can't test if multiple scalars + # have occurred. We have to allow them. + can_check_presence = not self._IsProto3Syntax(message) + if field.is_extension: + if (not self._allow_multiple_scalars and can_check_presence and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + else: + message.Extensions[field] = value + else: + if (not self._allow_multiple_scalars and can_check_presence and + message.HasField(field.name)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + else: + setattr(message, field.name, value) + + +def _SkipFieldContents(tokenizer): + """Skips over contents (value or message) of a field. + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + # Try to guess the type of this field. + # If this field is not a message, there should be a ":" between the + # field name and the field value and also the field value should not + # start with "{" or "<" which indicates the beginning of a message body. + # If there is no ":" or there is a "{" or "<" after ":", this field has + # to be a message or the input is ill-formed. + if tokenizer.TryConsume(':') and not tokenizer.LookingAt( + '{') and not tokenizer.LookingAt('<'): + _SkipFieldValue(tokenizer) + else: + _SkipFieldMessage(tokenizer) + + +def _SkipField(tokenizer): + """Skips over a complete field (name and value/message). + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + if tokenizer.TryConsume('['): + # Consume extension name. + tokenizer.ConsumeIdentifier() + while tokenizer.TryConsume('.'): + tokenizer.ConsumeIdentifier() + tokenizer.Consume(']') + else: + tokenizer.ConsumeIdentifierOrNumber() + + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + +def _SkipFieldMessage(tokenizer): + """Skips over a field message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + + if tokenizer.TryConsume('<'): + delimiter = '>' + else: + tokenizer.Consume('{') + delimiter = '}' + + while not tokenizer.LookingAt('>') and not tokenizer.LookingAt('}'): + _SkipField(tokenizer) + + tokenizer.Consume(delimiter) + + +def _SkipFieldValue(tokenizer): + """Skips over a field value. + + Args: + tokenizer: A tokenizer to parse the field name and values. + + Raises: + ParseError: In case an invalid field value is found. + """ + # String/bytes tokens can come in multiple adjacent string literals. + # If we can consume one, consume as many as we can. + if tokenizer.TryConsumeByteString(): + while tokenizer.TryConsumeByteString(): + pass + return + + if (not tokenizer.TryConsumeIdentifier() and + not _TryConsumeInt64(tokenizer) and not _TryConsumeUint64(tokenizer) and + not tokenizer.TryConsumeFloat()): + raise ParseError('Invalid field value: ' + tokenizer.token) + + +class Tokenizer(object): + """Protocol buffer text representation tokenizer. + + This class handles the lower level string parsing by splitting it into + meaningful tokens. + + It was directly ported from the Java protocol buffer API. + """ + + _WHITESPACE = re.compile(r'\s+') + _COMMENT = re.compile(r'(\s*#.*$)', re.MULTILINE) + _WHITESPACE_OR_COMMENT = re.compile(r'(\s|(#.*$))+', re.MULTILINE) + _TOKEN = re.compile('|'.join([ + r'[a-zA-Z_][0-9a-zA-Z_+-]*', # an identifier + r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*', # a number + ] + [ # quoted str for each quote mark + r'{qt}([^{qt}\n\\]|\\.)*({qt}|\\?$)'.format(qt=mark) for mark in _QUOTES + ])) + + _IDENTIFIER = re.compile(r'[^\d\W]\w*') + _IDENTIFIER_OR_NUMBER = re.compile(r'\w+') + + def __init__(self, lines, skip_comments=True): + self._position = 0 + self._line = -1 + self._column = 0 + self._token_start = None + self.token = '' + self._lines = iter(lines) + self._current_line = '' + self._previous_line = 0 + self._previous_column = 0 + self._more_lines = True + self._skip_comments = skip_comments + self._whitespace_pattern = (skip_comments and self._WHITESPACE_OR_COMMENT + or self._WHITESPACE) + self._SkipWhitespace() + self.NextToken() + + def LookingAt(self, token): + return self.token == token + + def AtEnd(self): + """Checks the end of the text was reached. + + Returns: + True iff the end was reached. + """ + return not self.token + + def _PopLine(self): + while len(self._current_line) <= self._column: + try: + self._current_line = next(self._lines) + except StopIteration: + self._current_line = '' + self._more_lines = False + return + else: + self._line += 1 + self._column = 0 + + def _SkipWhitespace(self): + while True: + self._PopLine() + match = self._whitespace_pattern.match(self._current_line, self._column) + if not match: + break + length = len(match.group(0)) + self._column += length + + def TryConsume(self, token): + """Tries to consume a given piece of text. + + Args: + token: Text to consume. + + Returns: + True iff the text was consumed. + """ + if self.token == token: + self.NextToken() + return True + return False + + def Consume(self, token): + """Consumes a piece of text. + + Args: + token: Text to consume. + + Raises: + ParseError: If the text couldn't be consumed. + """ + if not self.TryConsume(token): + raise self.ParseError('Expected "%s".' % token) + + def ConsumeComment(self): + result = self.token + if not self._COMMENT.match(result): + raise self.ParseError('Expected comment.') + self.NextToken() + return result + + def ConsumeCommentOrTrailingComment(self): + """Consumes a comment, returns a 2-tuple (trailing bool, comment str).""" + + # Tokenizer initializes _previous_line and _previous_column to 0. As the + # tokenizer starts, it looks like there is a previous token on the line. + just_started = self._line == 0 and self._column == 0 + + before_parsing = self._previous_line + comment = self.ConsumeComment() + + # A trailing comment is a comment on the same line than the previous token. + trailing = (self._previous_line == before_parsing + and not just_started) + + return trailing, comment + + def TryConsumeIdentifier(self): + try: + self.ConsumeIdentifier() + return True + except ParseError: + return False + + def ConsumeIdentifier(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not self._IDENTIFIER.match(result): + raise self.ParseError('Expected identifier.') + self.NextToken() + return result + + def TryConsumeIdentifierOrNumber(self): + try: + self.ConsumeIdentifierOrNumber() + return True + except ParseError: + return False + + def ConsumeIdentifierOrNumber(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not self._IDENTIFIER_OR_NUMBER.match(result): + raise self.ParseError('Expected identifier or number, got %s.' % result) + self.NextToken() + return result + + def TryConsumeInteger(self): + try: + # Note: is_long only affects value type, not whether an error is raised. + self.ConsumeInteger() + return True + except ParseError: + return False + + def ConsumeInteger(self, is_long=False): + """Consumes an integer number. + + Args: + is_long: True if the value should be returned as a long integer. + Returns: + The integer parsed. + + Raises: + ParseError: If an integer couldn't be consumed. + """ + try: + result = _ParseAbstractInteger(self.token, is_long=is_long) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def TryConsumeFloat(self): + try: + self.ConsumeFloat() + return True + except ParseError: + return False + + def ConsumeFloat(self): + """Consumes an floating point number. + + Returns: + The number parsed. + + Raises: + ParseError: If a floating point number couldn't be consumed. + """ + try: + result = ParseFloat(self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ConsumeBool(self): + """Consumes a boolean value. + + Returns: + The bool parsed. + + Raises: + ParseError: If a boolean value couldn't be consumed. + """ + try: + result = ParseBool(self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def TryConsumeByteString(self): + try: + self.ConsumeByteString() + return True + except ParseError: + return False + + def ConsumeString(self): + """Consumes a string value. + + Returns: + The string parsed. + + Raises: + ParseError: If a string value couldn't be consumed. + """ + the_bytes = self.ConsumeByteString() + try: + return six.text_type(the_bytes, 'utf-8') + except UnicodeDecodeError as e: + raise self._StringParseError(e) + + def ConsumeByteString(self): + """Consumes a byte array value. + + Returns: + The array parsed (as a string). + + Raises: + ParseError: If a byte array value couldn't be consumed. + """ + the_list = [self._ConsumeSingleByteString()] + while self.token and self.token[0] in _QUOTES: + the_list.append(self._ConsumeSingleByteString()) + return b''.join(the_list) + + def _ConsumeSingleByteString(self): + """Consume one token of a string literal. + + String literals (whether bytes or text) can come in multiple adjacent + tokens which are automatically concatenated, like in C or Python. This + method only consumes one token. + + Returns: + The token parsed. + Raises: + ParseError: When the wrong format data is found. + """ + text = self.token + if len(text) < 1 or text[0] not in _QUOTES: + raise self.ParseError('Expected string but found: %r' % (text,)) + + if len(text) < 2 or text[-1] != text[0]: + raise self.ParseError('String missing ending quote: %r' % (text,)) + + try: + result = text_encoding.CUnescape(text[1:-1]) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ConsumeEnum(self, field): + try: + result = ParseEnum(field, self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ParseErrorPreviousToken(self, message): + """Creates and *returns* a ParseError for the previously read token. + + Args: + message: A message to set for the exception. + + Returns: + A ParseError instance. + """ + return ParseError(message, self._previous_line + 1, + self._previous_column + 1) + + def ParseError(self, message): + """Creates and *returns* a ParseError for the current token.""" + return ParseError(message, self._line + 1, self._column + 1) + + def _StringParseError(self, e): + return self.ParseError('Couldn\'t parse string: ' + str(e)) + + def NextToken(self): + """Reads the next meaningful token.""" + self._previous_line = self._line + self._previous_column = self._column + + self._column += len(self.token) + self._SkipWhitespace() + + if not self._more_lines: + self.token = '' + return + + match = self._TOKEN.match(self._current_line, self._column) + if not match and not self._skip_comments: + match = self._COMMENT.match(self._current_line, self._column) + if match: + token = match.group(0) + self.token = token + else: + self.token = self._current_line[self._column] + +# Aliased so it can still be accessed by current visibility violators. +# TODO(dbarnett): Migrate violators to textformat_tokenizer. +_Tokenizer = Tokenizer # pylint: disable=invalid-name + + +def _ConsumeInt32(tokenizer): + """Consumes a signed 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=True, is_long=False) + + +def _ConsumeUint32(tokenizer): + """Consumes an unsigned 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=False, is_long=False) + + +def _TryConsumeInt64(tokenizer): + try: + _ConsumeInt64(tokenizer) + return True + except ParseError: + return False + + +def _ConsumeInt64(tokenizer): + """Consumes a signed 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=True, is_long=True) + + +def _TryConsumeUint64(tokenizer): + try: + _ConsumeUint64(tokenizer) + return True + except ParseError: + return False + + +def _ConsumeUint64(tokenizer): + """Consumes an unsigned 64bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 64bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=False, is_long=True) + + +def _TryConsumeInteger(tokenizer, is_signed=False, is_long=False): + try: + _ConsumeInteger(tokenizer, is_signed=is_signed, is_long=is_long) + return True + except ParseError: + return False + + +def _ConsumeInteger(tokenizer, is_signed=False, is_long=False): + """Consumes an integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer parsed. + + Raises: + ParseError: If an integer with given characteristics couldn't be consumed. + """ + try: + result = ParseInteger(tokenizer.token, is_signed=is_signed, is_long=is_long) + except ValueError as e: + raise tokenizer.ParseError(str(e)) + tokenizer.NextToken() + return result + + +def ParseInteger(text, is_signed=False, is_long=False): + """Parses an integer. + + Args: + text: The text to parse. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + result = _ParseAbstractInteger(text, is_long=is_long) + + # Check if the integer is sane. Exceptions handled by callers. + checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] + checker.CheckValue(result) + return result + + +def _ParseAbstractInteger(text, is_long=False): + """Parses an integer without checking size/signedness. + + Args: + text: The text to parse. + is_long: True if the value should be returned as a long integer. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + try: + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + if is_long: + return int(text, 0) + else: + return int(text, 0) + except ValueError: + raise ValueError('Couldn\'t parse integer: %s' % text) + + +def ParseFloat(text): + """Parse a floating point number. + + Args: + text: Text to parse. + + Returns: + The number parsed. + + Raises: + ValueError: If a floating point number couldn't be parsed. + """ + try: + # Assume Python compatible syntax. + return float(text) + except ValueError: + # Check alternative spellings. + if _FLOAT_INFINITY.match(text): + if text[0] == '-': + return float('-inf') + else: + return float('inf') + elif _FLOAT_NAN.match(text): + return float('nan') + else: + # assume '1.0f' format + try: + return float(text.rstrip('f')) + except ValueError: + raise ValueError('Couldn\'t parse float: %s' % text) + + +def ParseBool(text): + """Parse a boolean value. + + Args: + text: Text to parse. + + Returns: + Boolean values parsed + + Raises: + ValueError: If text is not a valid boolean. + """ + if text in ('true', 't', '1', 'True'): + return True + elif text in ('false', 'f', '0', 'False'): + return False + else: + raise ValueError('Expected "true" or "false".') + + +def ParseEnum(field, value): + """Parse an enum value. + + The value can be specified by a number (the enum value), or by + a string literal (the enum name). + + Args: + field: Enum field descriptor. + value: String value. + + Returns: + Enum value number. + + Raises: + ValueError: If the enum value could not be parsed. + """ + enum_descriptor = field.enum_type + try: + number = int(value, 0) + except ValueError: + # Identifier. + enum_value = enum_descriptor.values_by_name.get(value, None) + if enum_value is None: + raise ValueError('Enum type "%s" has no value named %s.' % + (enum_descriptor.full_name, value)) + else: + # Numeric value. + if hasattr(field.file, 'syntax'): + # Attribute is checked for compatibility. + if field.file.syntax == 'proto3': + # Proto3 accept numeric unknown enums. + return number + enum_value = enum_descriptor.values_by_number.get(number, None) + if enum_value is None: + raise ValueError('Enum type "%s" has no value with number %d.' % + (enum_descriptor.full_name, number)) + return enum_value.number diff --git a/venv/lib/python3.7/site-packages/google/protobuf/timestamp_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/timestamp_pb2.py new file mode 100644 index 0000000..eae6c2e --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/timestamp_pb2.py @@ -0,0 +1,77 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/timestamp.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/timestamp.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\016TimestampProtoP\001Z+github.com/golang/protobuf/ptypes/timestamp\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1fgoogle/protobuf/timestamp.proto\x12\x0fgoogle.protobuf\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x42~\n\x13\x63om.google.protobufB\x0eTimestampProtoP\x01Z+github.com/golang/protobuf/ptypes/timestamp\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_TIMESTAMP = _descriptor.Descriptor( + name='Timestamp', + full_name='google.protobuf.Timestamp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='seconds', full_name='google.protobuf.Timestamp.seconds', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nanos', full_name='google.protobuf.Timestamp.nanos', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=52, + serialized_end=95, +) + +DESCRIPTOR.message_types_by_name['Timestamp'] = _TIMESTAMP +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Timestamp = _reflection.GeneratedProtocolMessageType('Timestamp', (_message.Message,), dict( + DESCRIPTOR = _TIMESTAMP, + __module__ = 'google.protobuf.timestamp_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Timestamp) + )) +_sym_db.RegisterMessage(Timestamp) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/type_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/type_pb2.py new file mode 100644 index 0000000..edf78d9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/type_pb2.py @@ -0,0 +1,540 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/type.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import source_context_pb2 as google_dot_protobuf_dot_source__context__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/type.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\tTypeProtoP\001Z/google.golang.org/genproto/protobuf/ptype;ptype\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1agoogle/protobuf/type.proto\x12\x0fgoogle.protobuf\x1a\x19google/protobuf/any.proto\x1a$google/protobuf/source_context.proto\"\xd7\x01\n\x04Type\x12\x0c\n\x04name\x18\x01 \x01(\t\x12&\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x16.google.protobuf.Field\x12\x0e\n\x06oneofs\x18\x03 \x03(\t\x12(\n\x07options\x18\x04 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x36\n\x0esource_context\x18\x05 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12\'\n\x06syntax\x18\x06 \x01(\x0e\x32\x17.google.protobuf.Syntax\"\xd5\x05\n\x05\x46ield\x12)\n\x04kind\x18\x01 \x01(\x0e\x32\x1b.google.protobuf.Field.Kind\x12\x37\n\x0b\x63\x61rdinality\x18\x02 \x01(\x0e\x32\".google.protobuf.Field.Cardinality\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x10\n\x08type_url\x18\x06 \x01(\t\x12\x13\n\x0boneof_index\x18\x07 \x01(\x05\x12\x0e\n\x06packed\x18\x08 \x01(\x08\x12(\n\x07options\x18\t \x03(\x0b\x32\x17.google.protobuf.Option\x12\x11\n\tjson_name\x18\n \x01(\t\x12\x15\n\rdefault_value\x18\x0b \x01(\t\"\xc8\x02\n\x04Kind\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"t\n\x0b\x43\x61rdinality\x12\x17\n\x13\x43\x41RDINALITY_UNKNOWN\x10\x00\x12\x18\n\x14\x43\x41RDINALITY_OPTIONAL\x10\x01\x12\x18\n\x14\x43\x41RDINALITY_REQUIRED\x10\x02\x12\x18\n\x14\x43\x41RDINALITY_REPEATED\x10\x03\"\xce\x01\n\x04\x45num\x12\x0c\n\x04name\x18\x01 \x01(\t\x12-\n\tenumvalue\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.EnumValue\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x36\n\x0esource_context\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12\'\n\x06syntax\x18\x05 \x01(\x0e\x32\x17.google.protobuf.Syntax\"S\n\tEnumValue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\";\n\x06Option\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.google.protobuf.Any*.\n\x06Syntax\x12\x11\n\rSYNTAX_PROTO2\x10\x00\x12\x11\n\rSYNTAX_PROTO3\x10\x01\x42}\n\x13\x63om.google.protobufB\tTypeProtoP\x01Z/google.golang.org/genproto/protobuf/ptype;ptype\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_source__context__pb2.DESCRIPTOR,]) + +_SYNTAX = _descriptor.EnumDescriptor( + name='Syntax', + full_name='google.protobuf.Syntax', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SYNTAX_PROTO2', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SYNTAX_PROTO3', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1413, + serialized_end=1459, +) +_sym_db.RegisterEnumDescriptor(_SYNTAX) + +Syntax = enum_type_wrapper.EnumTypeWrapper(_SYNTAX) +SYNTAX_PROTO2 = 0 +SYNTAX_PROTO3 = 1 + + +_FIELD_KIND = _descriptor.EnumDescriptor( + name='Kind', + full_name='google.protobuf.Field.Kind', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_DOUBLE', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FLOAT', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT64', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT64', index=4, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_INT32', index=5, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED64', index=6, number=6, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED32', index=7, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BOOL', index=8, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_STRING', index=9, number=9, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_GROUP', index=10, number=10, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_MESSAGE', index=11, number=11, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_BYTES', index=12, number=12, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT32', index=13, number=13, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_ENUM', index=14, number=14, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED32', index=15, number=15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED64', index=16, number=16, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT32', index=17, number=17, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT64', index=18, number=18, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=610, + serialized_end=938, +) +_sym_db.RegisterEnumDescriptor(_FIELD_KIND) + +_FIELD_CARDINALITY = _descriptor.EnumDescriptor( + name='Cardinality', + full_name='google.protobuf.Field.Cardinality', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='CARDINALITY_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_OPTIONAL', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_REQUIRED', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_REPEATED', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=940, + serialized_end=1056, +) +_sym_db.RegisterEnumDescriptor(_FIELD_CARDINALITY) + + +_TYPE = _descriptor.Descriptor( + name='Type', + full_name='google.protobuf.Type', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Type.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fields', full_name='google.protobuf.Type.fields', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneofs', full_name='google.protobuf.Type.oneofs', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Type.options', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Type.source_context', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Type.syntax', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=328, +) + + +_FIELD = _descriptor.Descriptor( + name='Field', + full_name='google.protobuf.Field', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='kind', full_name='google.protobuf.Field.kind', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cardinality', full_name='google.protobuf.Field.cardinality', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.Field.number', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Field.name', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type_url', full_name='google.protobuf.Field.type_url', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_index', full_name='google.protobuf.Field.oneof_index', index=5, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed', full_name='google.protobuf.Field.packed', index=6, + number=8, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Field.options', index=7, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='json_name', full_name='google.protobuf.Field.json_name', index=8, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_value', full_name='google.protobuf.Field.default_value', index=9, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELD_KIND, + _FIELD_CARDINALITY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=331, + serialized_end=1056, +) + + +_ENUM = _descriptor.Descriptor( + name='Enum', + full_name='google.protobuf.Enum', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Enum.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enumvalue', full_name='google.protobuf.Enum.enumvalue', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Enum.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Enum.source_context', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Enum.syntax', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1059, + serialized_end=1265, +) + + +_ENUMVALUE = _descriptor.Descriptor( + name='EnumValue', + full_name='google.protobuf.EnumValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumValue.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.EnumValue.number', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumValue.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1267, + serialized_end=1350, +) + + +_OPTION = _descriptor.Descriptor( + name='Option', + full_name='google.protobuf.Option', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Option.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Option.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1352, + serialized_end=1411, +) + +_TYPE.fields_by_name['fields'].message_type = _FIELD +_TYPE.fields_by_name['options'].message_type = _OPTION +_TYPE.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_TYPE.fields_by_name['syntax'].enum_type = _SYNTAX +_FIELD.fields_by_name['kind'].enum_type = _FIELD_KIND +_FIELD.fields_by_name['cardinality'].enum_type = _FIELD_CARDINALITY +_FIELD.fields_by_name['options'].message_type = _OPTION +_FIELD_KIND.containing_type = _FIELD +_FIELD_CARDINALITY.containing_type = _FIELD +_ENUM.fields_by_name['enumvalue'].message_type = _ENUMVALUE +_ENUM.fields_by_name['options'].message_type = _OPTION +_ENUM.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_ENUM.fields_by_name['syntax'].enum_type = _SYNTAX +_ENUMVALUE.fields_by_name['options'].message_type = _OPTION +_OPTION.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +DESCRIPTOR.message_types_by_name['Type'] = _TYPE +DESCRIPTOR.message_types_by_name['Field'] = _FIELD +DESCRIPTOR.message_types_by_name['Enum'] = _ENUM +DESCRIPTOR.message_types_by_name['EnumValue'] = _ENUMVALUE +DESCRIPTOR.message_types_by_name['Option'] = _OPTION +DESCRIPTOR.enum_types_by_name['Syntax'] = _SYNTAX +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Type = _reflection.GeneratedProtocolMessageType('Type', (_message.Message,), dict( + DESCRIPTOR = _TYPE, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Type) + )) +_sym_db.RegisterMessage(Type) + +Field = _reflection.GeneratedProtocolMessageType('Field', (_message.Message,), dict( + DESCRIPTOR = _FIELD, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Field) + )) +_sym_db.RegisterMessage(Field) + +Enum = _reflection.GeneratedProtocolMessageType('Enum', (_message.Message,), dict( + DESCRIPTOR = _ENUM, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Enum) + )) +_sym_db.RegisterMessage(Enum) + +EnumValue = _reflection.GeneratedProtocolMessageType('EnumValue', (_message.Message,), dict( + DESCRIPTOR = _ENUMVALUE, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValue) + )) +_sym_db.RegisterMessage(EnumValue) + +Option = _reflection.GeneratedProtocolMessageType('Option', (_message.Message,), dict( + DESCRIPTOR = _OPTION, + __module__ = 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Option) + )) +_sym_db.RegisterMessage(Option) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_arena_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_arena_pb2.py new file mode 100644 index 0000000..6ed8aec --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_arena_pb2.py @@ -0,0 +1,120 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_arena.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_no_arena_import_pb2 as google_dot_protobuf_dot_unittest__no__arena__import__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_arena.proto', + package='proto2_arena_unittest', + syntax='proto2', + serialized_options=_b('\370\001\001'), + serialized_pb=_b('\n$google/protobuf/unittest_arena.proto\x12\x15proto2_arena_unittest\x1a.google/protobuf/unittest_no_arena_import.proto\"\x1a\n\rNestedMessage\x12\t\n\x01\x64\x18\x01 \x01(\x05\"\xb2\x01\n\x0c\x41renaMessage\x12\x45\n\x17repeated_nested_message\x18\x01 \x03(\x0b\x32$.proto2_arena_unittest.NestedMessage\x12[\n repeated_import_no_arena_message\x18\x02 \x03(\x0b\x32\x31.proto2_arena_unittest.ImportNoArenaNestedMessageB\x03\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__no__arena__import__pb2.DESCRIPTOR,]) + + + + +_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='proto2_arena_unittest.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='proto2_arena_unittest.NestedMessage.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=111, + serialized_end=137, +) + + +_ARENAMESSAGE = _descriptor.Descriptor( + name='ArenaMessage', + full_name='proto2_arena_unittest.ArenaMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='proto2_arena_unittest.ArenaMessage.repeated_nested_message', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_no_arena_message', full_name='proto2_arena_unittest.ArenaMessage.repeated_import_no_arena_message', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=140, + serialized_end=318, +) + +_ARENAMESSAGE.fields_by_name['repeated_nested_message'].message_type = _NESTEDMESSAGE +_ARENAMESSAGE.fields_by_name['repeated_import_no_arena_message'].message_type = google_dot_protobuf_dot_unittest__no__arena__import__pb2._IMPORTNOARENANESTEDMESSAGE +DESCRIPTOR.message_types_by_name['NestedMessage'] = _NESTEDMESSAGE +DESCRIPTOR.message_types_by_name['ArenaMessage'] = _ARENAMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_arena_pb2' + # @@protoc_insertion_point(class_scope:proto2_arena_unittest.NestedMessage) + )) +_sym_db.RegisterMessage(NestedMessage) + +ArenaMessage = _reflection.GeneratedProtocolMessageType('ArenaMessage', (_message.Message,), dict( + DESCRIPTOR = _ARENAMESSAGE, + __module__ = 'google.protobuf.unittest_arena_pb2' + # @@protoc_insertion_point(class_scope:proto2_arena_unittest.ArenaMessage) + )) +_sym_db.RegisterMessage(ArenaMessage) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_custom_options_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_custom_options_pb2.py new file mode 100644 index 0000000..954cb27 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_custom_options_pb2.py @@ -0,0 +1,1845 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_custom_options.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import service as _service +from google.protobuf import service_reflection +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_custom_options.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=_b('\200\001\001\210\001\001\220\001\001\360\350\301\035\352\255\300\345$\372\354\205;p\010d\022\016FileAnnotation\032\026\022\024NestedFileAnnotation\"\036\372\354\205;\031\022\027FileExtensionAnnotation*$\013\020\366\353\256\007\032\033\n\031EmbeddedMessageSetElement\014'), + serialized_pb=_b('\n-google/protobuf/unittest_custom_options.proto\x12\x11protobuf_unittest\x1a google/protobuf/descriptor.proto\"\xbf\x01\n\x1cTestMessageWithCustomOptions\x12\x1e\n\x06\x66ield1\x18\x01 \x01(\tB\x0e\x08\x01\xc1\xe0\xc3\x1d-\xe1u\n\x02\x00\x00\x00\x12\x15\n\x0boneof_field\x18\x02 \x01(\x05H\x00\";\n\x06\x41nEnum\x12\x0f\n\x0b\x41NENUM_VAL1\x10\x01\x12\x16\n\x0b\x41NENUM_VAL2\x10\x02\x1a\x05\xb0\x86\xfa\x05{\x1a\x08\xc5\xf6\xc9\x1d\xeb\xfc\xff\xff:\x10\x08\x00\xe0\xe9\xc2\x1d\xc8\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\x19\n\x07\x41nOneof\x12\x0e\xf8\xac\xc3\x1d\x9d\xff\xff\xff\xff\xff\xff\xff\xff\x01\"\x18\n\x16\x43ustomOptionFooRequest\"\x19\n\x17\x43ustomOptionFooResponse\"\x1e\n\x1c\x43ustomOptionFooClientMessage\"\x1e\n\x1c\x43ustomOptionFooServerMessage\"m\n\x1a\x44ummyMessageContainingEnum\"O\n\x0cTestEnumType\x12\x1a\n\x16TEST_OPTION_ENUM_TYPE1\x10\x16\x12#\n\x16TEST_OPTION_ENUM_TYPE2\x10\xe9\xff\xff\xff\xff\xff\xff\xff\xff\x01\"!\n\x1f\x44ummyMessageInvalidAsOptionType\"\x8a\x01\n\x1c\x43ustomOptionMinIntegerValues:j\xd0\xde\xb2\x1d\x00\xe8\xc6\xb2\x1d\x80\x80\x80\x80\xf8\xff\xff\xff\xff\x01\xb0\xbc\xb2\x1d\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01\x80\x93\xb2\x1d\x00\xf8\xf5\xb0\x1d\x00\x80\xc4\xb0\x1d\xff\xff\xff\xff\x0f\xf8\x97\xb0\x1d\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x9d\xf5\xaf\x1d\x00\x00\x00\x00\x91\xee\xaf\x1d\x00\x00\x00\x00\x00\x00\x00\x00\xad\x8d\xaf\x1d\x00\x00\x00\x80\x99\xd6\xa8\x1d\x00\x00\x00\x00\x00\x00\x00\x80\"\x91\x01\n\x1c\x43ustomOptionMaxIntegerValues:q\xd0\xde\xb2\x1d\x01\xe8\xc6\xb2\x1d\xff\xff\xff\xff\x07\xb0\xbc\xb2\x1d\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x80\x93\xb2\x1d\xff\xff\xff\xff\x0f\xf8\xf5\xb0\x1d\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\xc4\xb0\x1d\xfe\xff\xff\xff\x0f\xf8\x97\xb0\x1d\xfe\xff\xff\xff\xff\xff\xff\xff\xff\x01\x9d\xf5\xaf\x1d\xff\xff\xff\xff\x91\xee\xaf\x1d\xff\xff\xff\xff\xff\xff\xff\xff\xad\x8d\xaf\x1d\xff\xff\xff\x7f\x99\xd6\xa8\x1d\xff\xff\xff\xff\xff\xff\xff\x7f\"n\n\x17\x43ustomOptionOtherValues:S\xe8\xc6\xb2\x1d\x9c\xff\xff\xff\xff\xff\xff\xff\xff\x01\xf5\xdf\xa3\x1d\xe7\x87\x45\x41\xe9\xdc\xa2\x1d\xfbY\x8c\x42\xca\xc0\xf3?\xaa\xdc\xa2\x1d\x0eHello, \"World\"\xb2\xd9\xa2\x1d\x0bHello\x00World\x88\xd9\xa2\x1d\xe9\xff\xff\xff\xff\xff\xff\xff\xff\x01\"4\n\x1cSettingRealsFromPositiveInts:\x14\xf5\xdf\xa3\x1d\x00\x00@A\xe9\xdc\xa2\x1d\x00\x00\x00\x00\x00@c@\"4\n\x1cSettingRealsFromNegativeInts:\x14\xf5\xdf\xa3\x1d\x00\x00@\xc1\xe9\xdc\xa2\x1d\x00\x00\x00\x00\x00@c\xc0\"U\n\x12\x43omplexOptionType1\x12\x0b\n\x03\x66oo\x18\x01 \x01(\x05\x12\x0c\n\x04\x66oo2\x18\x02 \x01(\x05\x12\x0c\n\x04\x66oo3\x18\x03 \x01(\x05\x12\x0c\n\x04\x66oo4\x18\x04 \x03(\x05*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x8b\x03\n\x12\x43omplexOptionType2\x12\x32\n\x03\x62\x61r\x18\x01 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType1\x12\x0b\n\x03\x62\x61z\x18\x02 \x01(\x05\x12\x46\n\x04\x66red\x18\x03 \x01(\x0b\x32\x38.protobuf_unittest.ComplexOptionType2.ComplexOptionType4\x12H\n\x06\x62\x61rney\x18\x04 \x03(\x0b\x32\x38.protobuf_unittest.ComplexOptionType2.ComplexOptionType4\x1a\x97\x01\n\x12\x43omplexOptionType4\x12\r\n\x05waldo\x18\x01 \x01(\x05\x32r\n\x0c\x63omplex_opt4\x12\x1f.google.protobuf.MessageOptions\x18\x8a\xf5\xd1\x03 \x01(\x0b\x32\x38.protobuf_unittest.ComplexOptionType2.ComplexOptionType4*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"\x9c\x01\n\x12\x43omplexOptionType3\x12\x0b\n\x03qux\x18\x01 \x01(\x05\x12T\n\x12\x63omplexoptiontype5\x18\x02 \x01(\n28.protobuf_unittest.ComplexOptionType3.ComplexOptionType5\x1a#\n\x12\x43omplexOptionType5\x12\r\n\x05plugh\x18\x03 \x01(\x05\"\x1f\n\x0b\x43omplexOpt6\x12\x10\n\x05xyzzy\x18\xdf\xbf\xcf\x03 \x01(\x05\"\xf1\x01\n\x15VariousComplexOptions:\xd7\x01\xa2\xe2\x95\x1d\x02\x08*\xa2\xe2\x95\x1d\x06\xd8\x85\x9e\x1d\xc4\x02\xa2\xe2\x95\x1d\x08\x92\xf5\x9d\x1d\x03\x08\xec\x06\xa2\xe2\x95\x1d\x02 c\xa2\xe2\x95\x1d\x02 X\xaa\xfd\x90\x1d\x03\x10\xdb\x07\xaa\xfd\x90\x1d\x06\xf8\xe6\x97\x1d\x8e\x05\xaa\xfd\x90\x1d\x05\n\x03\x08\xe7\x05\xaa\xfd\x90\x1d\x08\n\x06\xd8\x85\x9e\x1d\xcf\x0f\xaa\xfd\x90\x1d\n\n\x08\x92\xf5\x9d\x1d\x03\x08\xd8\x0f\xaa\xfd\x90\x1d\x08\xc2\xac\x97\x1d\x03\x08\xe5\x05\xaa\xfd\x90\x1d\x0b\xc2\xac\x97\x1d\x06\xd8\x85\x9e\x1d\xce\x0f\xaa\xfd\x90\x1d\r\xc2\xac\x97\x1d\x08\x92\xf5\x9d\x1d\x03\x08\xc9\x10\xd2\xa8\x8f\x1d\x03\x08\xb3\x0f\xaa\xfd\x90\x1d\x05\x1a\x03\x08\xc1\x02\xaa\xfd\x90\x1d\x04\"\x02\x08\x65\xaa\xfd\x90\x1d\x05\"\x03\x08\xd4\x01\xfa\xde\x90\x1d\x02\x08\t\xfa\xde\x90\x1d\x04\x13\x18\x16\x14\xe3\xdc\xfc\x1c\xf8\xfd\xfb\x1c\x18\xe4\xdc\xfc\x1c\"#\n\x13\x41ggregateMessageSet*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\"\xa0\x01\n\x1a\x41ggregateMessageSetElement\x12\t\n\x01s\x18\x01 \x01(\t2w\n\x15message_set_extension\x12&.protobuf_unittest.AggregateMessageSet\x18\xf6\xeb\xae\x07 \x01(\x0b\x32-.protobuf_unittest.AggregateMessageSetElement\"\xfd\x01\n\tAggregate\x12\t\n\x01i\x18\x01 \x01(\x05\x12\t\n\x01s\x18\x02 \x01(\t\x12)\n\x03sub\x18\x03 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate\x12*\n\x04\x66ile\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.FileOptions\x12\x34\n\x04mset\x18\x05 \x01(\x0b\x32&.protobuf_unittest.AggregateMessageSet2M\n\x06nested\x12\x1c.google.protobuf.FileOptions\x18\xa7\xd1\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate\"Y\n\x10\x41ggregateMessage\x12)\n\tfieldname\x18\x01 \x01(\x05\x42\x16\xf2\xa1\x87;\x11\x12\x0f\x46ieldAnnotation:\x1a\xc2\xd1\x86;\x15\x08\x65\x12\x11MessageAnnotation\"\xc9\x01\n\x10NestedOptionType\x1a;\n\rNestedMessage\x12\"\n\x0cnested_field\x18\x01 \x01(\x05\x42\x0c\xc1\xe0\xc3\x1d\xea\x03\x00\x00\x00\x00\x00\x00:\x06\xe0\xe9\xc2\x1d\xe9\x07\"5\n\nNestedEnum\x12\x1d\n\x11NESTED_ENUM_VALUE\x10\x01\x1a\x06\xb0\x86\xfa\x05\xec\x07\x1a\x08\xc5\xf6\xc9\x1d\xeb\x03\x00\x00\x32\x41\n\x10nested_extension\x12\x1c.google.protobuf.FileOptions\x18\xfd\xf8\xe2\x03 \x01(\x05\x42\x06\xc8\x8b\xca\x1d\xed\x07\"d\n\rOldOptionType\x12\x38\n\x05value\x18\x01 \x02(\x0e\x32).protobuf_unittest.OldOptionType.TestEnum\"\x19\n\x08TestEnum\x12\r\n\tOLD_VALUE\x10\x00\"s\n\rNewOptionType\x12\x38\n\x05value\x18\x01 \x02(\x0e\x32).protobuf_unittest.NewOptionType.TestEnum\"(\n\x08TestEnum\x12\r\n\tOLD_VALUE\x10\x00\x12\r\n\tNEW_VALUE\x10\x01\"-\n!TestMessageWithRequiredEnumOption:\x08\xfa\xe8\xfc\x94\x03\x02\x08\x00*6\n\nMethodOpt1\x12\x13\n\x0fMETHODOPT1_VAL1\x10\x01\x12\x13\n\x0fMETHODOPT1_VAL2\x10\x02*M\n\rAggregateEnum\x12%\n\x05VALUE\x10\x01\x1a\x1a\xca\xfc\x89;\x15\x12\x13\x45numValueAnnotation\x1a\x15\x92\x95\x88;\x10\x12\x0e\x45numAnnotation2\x8e\x01\n\x1cTestServiceWithCustomOptions\x12\x63\n\x03\x46oo\x12).protobuf_unittest.CustomOptionFooRequest\x1a*.protobuf_unittest.CustomOptionFooResponse\"\x05\xe0\xfa\x8c\x1e\x02\x1a\t\x90\xb2\x8b\x1e\xd3\xdb\x80\xcbI2\x99\x01\n\x10\x41ggregateService\x12k\n\x06Method\x12#.protobuf_unittest.AggregateMessage\x1a#.protobuf_unittest.AggregateMessage\"\x17\xca\xc8\x96;\x12\x12\x10MethodAnnotation\x1a\x18\xca\xfb\x8e;\x13\x12\x11ServiceAnnotation:2\n\tfile_opt1\x12\x1c.google.protobuf.FileOptions\x18\x8e\x9d\xd8\x03 \x01(\x04:8\n\x0cmessage_opt1\x12\x1f.google.protobuf.MessageOptions\x18\x9c\xad\xd8\x03 \x01(\x05:4\n\nfield_opt1\x12\x1d.google.protobuf.FieldOptions\x18\x88\xbc\xd8\x03 \x01(\x06:8\n\nfield_opt2\x12\x1d.google.protobuf.FieldOptions\x18\xb9\xa1\xd9\x03 \x01(\x05:\x02\x34\x32:4\n\noneof_opt1\x12\x1d.google.protobuf.OneofOptions\x18\xcf\xb5\xd8\x03 \x01(\x05:2\n\tenum_opt1\x12\x1c.google.protobuf.EnumOptions\x18\xe8\x9e\xd9\x03 \x01(\x0f:<\n\x0f\x65num_value_opt1\x12!.google.protobuf.EnumValueOptions\x18\xe6\xa0_ \x01(\x05:8\n\x0cservice_opt1\x12\x1f.google.protobuf.ServiceOptions\x18\xa2\xb6\xe1\x03 \x01(\x12:U\n\x0bmethod_opt1\x12\x1e.google.protobuf.MethodOptions\x18\xac\xcf\xe1\x03 \x01(\x0e\x32\x1d.protobuf_unittest.MethodOpt1:4\n\x08\x62ool_opt\x12\x1f.google.protobuf.MessageOptions\x18\xea\xab\xd6\x03 \x01(\x08:5\n\tint32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xed\xa8\xd6\x03 \x01(\x05:5\n\tint64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xc6\xa7\xd6\x03 \x01(\x03:6\n\nuint32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xb0\xa2\xd6\x03 \x01(\r:6\n\nuint64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xdf\x8e\xd6\x03 \x01(\x04:6\n\nsint32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xc0\x88\xd6\x03 \x01(\x11:6\n\nsint64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xff\x82\xd6\x03 \x01(\x12:7\n\x0b\x66ixed32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xd3\xfe\xd5\x03 \x01(\x07:7\n\x0b\x66ixed64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xe2\xfd\xd5\x03 \x01(\x06:8\n\x0csfixed32_opt\x12\x1f.google.protobuf.MessageOptions\x18\xd5\xf1\xd5\x03 \x01(\x0f:8\n\x0csfixed64_opt\x12\x1f.google.protobuf.MessageOptions\x18\xe3\x8a\xd5\x03 \x01(\x10:5\n\tfloat_opt\x12\x1f.google.protobuf.MessageOptions\x18\xfe\xbb\xd4\x03 \x01(\x02:6\n\ndouble_opt\x12\x1f.google.protobuf.MessageOptions\x18\xcd\xab\xd4\x03 \x01(\x01:6\n\nstring_opt\x12\x1f.google.protobuf.MessageOptions\x18\xc5\xab\xd4\x03 \x01(\t:5\n\tbytes_opt\x12\x1f.google.protobuf.MessageOptions\x18\x96\xab\xd4\x03 \x01(\x0c:p\n\x08\x65num_opt\x12\x1f.google.protobuf.MessageOptions\x18\x91\xab\xd4\x03 \x01(\x0e\x32:.protobuf_unittest.DummyMessageContainingEnum.TestEnumType:p\n\x10message_type_opt\x12\x1f.google.protobuf.MessageOptions\x18\xaf\xf2\xd3\x03 \x01(\x0b\x32\x32.protobuf_unittest.DummyMessageInvalidAsOptionType:6\n\x04quux\x12%.protobuf_unittest.ComplexOptionType1\x18\xdb\xe0\xd3\x03 \x01(\x05:^\n\x05\x63orge\x12%.protobuf_unittest.ComplexOptionType1\x18\xd2\xde\xd3\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType3:8\n\x06grault\x12%.protobuf_unittest.ComplexOptionType2\x18\xef\xfc\xd2\x03 \x01(\x05:_\n\x06garply\x12%.protobuf_unittest.ComplexOptionType2\x18\xc8\xf5\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType1:_\n\x0c\x63omplex_opt1\x12\x1f.google.protobuf.MessageOptions\x18\xa4\xdc\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType1:_\n\x0c\x63omplex_opt2\x12\x1f.google.protobuf.MessageOptions\x18\xd5\x8f\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType2:_\n\x0c\x63omplex_opt3\x12\x1f.google.protobuf.MessageOptions\x18\xef\x8b\xd2\x03 \x01(\x0b\x32%.protobuf_unittest.ComplexOptionType3:W\n\x0b\x63omplexopt6\x12\x1f.google.protobuf.MessageOptions\x18\xcc\xcb\xcf\x03 \x01(\n2\x1e.protobuf_unittest.ComplexOpt6:N\n\x07\x66ileopt\x12\x1c.google.protobuf.FileOptions\x18\xcf\xdd\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:P\n\x06msgopt\x12\x1f.google.protobuf.MessageOptions\x18\x98\xea\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:P\n\x08\x66ieldopt\x12\x1d.google.protobuf.FieldOptions\x18\x9e\xf4\xb0\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:N\n\x07\x65numopt\x12\x1c.google.protobuf.EnumOptions\x18\xd2\x82\xb1\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:V\n\nenumvalopt\x12!.google.protobuf.EnumValueOptions\x18\xc9\x9f\xb1\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:T\n\nserviceopt\x12\x1f.google.protobuf.ServiceOptions\x18\xb9\xef\xb1\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:R\n\tmethodopt\x12\x1e.google.protobuf.MethodOptions\x18\x89\xe9\xb2\x07 \x01(\x0b\x32\x1c.protobuf_unittest.Aggregate:_\n\x11required_enum_opt\x12\x1f.google.protobuf.MessageOptions\x18\x8f\xcd\xcf\x32 \x01(\x0b\x32 .protobuf_unittest.OldOptionTypeB\x87\x01\x80\x01\x01\x88\x01\x01\x90\x01\x01\xf0\xe8\xc1\x1d\xea\xad\xc0\xe5$\xfa\xec\x85;p\x08\x64\x12\x0e\x46ileAnnotation\x1a\x16\x12\x14NestedFileAnnotation\"\x1e\xfa\xec\x85;\x19\x12\x17\x46ileExtensionAnnotation*$\x0b\x10\xf6\xeb\xae\x07\x1a\x1b\n\x19\x45mbeddedMessageSetElement\x0c') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + +_METHODOPT1 = _descriptor.EnumDescriptor( + name='MethodOpt1', + full_name='protobuf_unittest.MethodOpt1', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='METHODOPT1_VAL1', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='METHODOPT1_VAL2', index=1, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3006, + serialized_end=3060, +) +_sym_db.RegisterEnumDescriptor(_METHODOPT1) + +MethodOpt1 = enum_type_wrapper.EnumTypeWrapper(_METHODOPT1) +_AGGREGATEENUM = _descriptor.EnumDescriptor( + name='AggregateEnum', + full_name='protobuf_unittest.AggregateEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='VALUE', index=0, number=1, + serialized_options=_b('\312\374\211;\025\022\023EnumValueAnnotation'), + type=None), + ], + containing_type=None, + serialized_options=_b('\222\225\210;\020\022\016EnumAnnotation'), + serialized_start=3062, + serialized_end=3139, +) +_sym_db.RegisterEnumDescriptor(_AGGREGATEENUM) + +AggregateEnum = enum_type_wrapper.EnumTypeWrapper(_AGGREGATEENUM) +METHODOPT1_VAL1 = 1 +METHODOPT1_VAL2 = 2 +VALUE = 1 + +FILE_OPT1_FIELD_NUMBER = 7736974 +file_opt1 = _descriptor.FieldDescriptor( + name='file_opt1', full_name='protobuf_unittest.file_opt1', index=0, + number=7736974, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MESSAGE_OPT1_FIELD_NUMBER = 7739036 +message_opt1 = _descriptor.FieldDescriptor( + name='message_opt1', full_name='protobuf_unittest.message_opt1', index=1, + number=7739036, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIELD_OPT1_FIELD_NUMBER = 7740936 +field_opt1 = _descriptor.FieldDescriptor( + name='field_opt1', full_name='protobuf_unittest.field_opt1', index=2, + number=7740936, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIELD_OPT2_FIELD_NUMBER = 7753913 +field_opt2 = _descriptor.FieldDescriptor( + name='field_opt2', full_name='protobuf_unittest.field_opt2', index=3, + number=7753913, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_OPT1_FIELD_NUMBER = 7740111 +oneof_opt1 = _descriptor.FieldDescriptor( + name='oneof_opt1', full_name='protobuf_unittest.oneof_opt1', index=4, + number=7740111, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUM_OPT1_FIELD_NUMBER = 7753576 +enum_opt1 = _descriptor.FieldDescriptor( + name='enum_opt1', full_name='protobuf_unittest.enum_opt1', index=5, + number=7753576, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUM_VALUE_OPT1_FIELD_NUMBER = 1560678 +enum_value_opt1 = _descriptor.FieldDescriptor( + name='enum_value_opt1', full_name='protobuf_unittest.enum_value_opt1', index=6, + number=1560678, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SERVICE_OPT1_FIELD_NUMBER = 7887650 +service_opt1 = _descriptor.FieldDescriptor( + name='service_opt1', full_name='protobuf_unittest.service_opt1', index=7, + number=7887650, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +METHOD_OPT1_FIELD_NUMBER = 7890860 +method_opt1 = _descriptor.FieldDescriptor( + name='method_opt1', full_name='protobuf_unittest.method_opt1', index=8, + number=7890860, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +BOOL_OPT_FIELD_NUMBER = 7706090 +bool_opt = _descriptor.FieldDescriptor( + name='bool_opt', full_name='protobuf_unittest.bool_opt', index=9, + number=7706090, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +INT32_OPT_FIELD_NUMBER = 7705709 +int32_opt = _descriptor.FieldDescriptor( + name='int32_opt', full_name='protobuf_unittest.int32_opt', index=10, + number=7705709, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +INT64_OPT_FIELD_NUMBER = 7705542 +int64_opt = _descriptor.FieldDescriptor( + name='int64_opt', full_name='protobuf_unittest.int64_opt', index=11, + number=7705542, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +UINT32_OPT_FIELD_NUMBER = 7704880 +uint32_opt = _descriptor.FieldDescriptor( + name='uint32_opt', full_name='protobuf_unittest.uint32_opt', index=12, + number=7704880, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +UINT64_OPT_FIELD_NUMBER = 7702367 +uint64_opt = _descriptor.FieldDescriptor( + name='uint64_opt', full_name='protobuf_unittest.uint64_opt', index=13, + number=7702367, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SINT32_OPT_FIELD_NUMBER = 7701568 +sint32_opt = _descriptor.FieldDescriptor( + name='sint32_opt', full_name='protobuf_unittest.sint32_opt', index=14, + number=7701568, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SINT64_OPT_FIELD_NUMBER = 7700863 +sint64_opt = _descriptor.FieldDescriptor( + name='sint64_opt', full_name='protobuf_unittest.sint64_opt', index=15, + number=7700863, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIXED32_OPT_FIELD_NUMBER = 7700307 +fixed32_opt = _descriptor.FieldDescriptor( + name='fixed32_opt', full_name='protobuf_unittest.fixed32_opt', index=16, + number=7700307, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIXED64_OPT_FIELD_NUMBER = 7700194 +fixed64_opt = _descriptor.FieldDescriptor( + name='fixed64_opt', full_name='protobuf_unittest.fixed64_opt', index=17, + number=7700194, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SFIXED32_OPT_FIELD_NUMBER = 7698645 +sfixed32_opt = _descriptor.FieldDescriptor( + name='sfixed32_opt', full_name='protobuf_unittest.sfixed32_opt', index=18, + number=7698645, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SFIXED64_OPT_FIELD_NUMBER = 7685475 +sfixed64_opt = _descriptor.FieldDescriptor( + name='sfixed64_opt', full_name='protobuf_unittest.sfixed64_opt', index=19, + number=7685475, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FLOAT_OPT_FIELD_NUMBER = 7675390 +float_opt = _descriptor.FieldDescriptor( + name='float_opt', full_name='protobuf_unittest.float_opt', index=20, + number=7675390, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DOUBLE_OPT_FIELD_NUMBER = 7673293 +double_opt = _descriptor.FieldDescriptor( + name='double_opt', full_name='protobuf_unittest.double_opt', index=21, + number=7673293, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +STRING_OPT_FIELD_NUMBER = 7673285 +string_opt = _descriptor.FieldDescriptor( + name='string_opt', full_name='protobuf_unittest.string_opt', index=22, + number=7673285, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +BYTES_OPT_FIELD_NUMBER = 7673238 +bytes_opt = _descriptor.FieldDescriptor( + name='bytes_opt', full_name='protobuf_unittest.bytes_opt', index=23, + number=7673238, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUM_OPT_FIELD_NUMBER = 7673233 +enum_opt = _descriptor.FieldDescriptor( + name='enum_opt', full_name='protobuf_unittest.enum_opt', index=24, + number=7673233, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=22, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MESSAGE_TYPE_OPT_FIELD_NUMBER = 7665967 +message_type_opt = _descriptor.FieldDescriptor( + name='message_type_opt', full_name='protobuf_unittest.message_type_opt', index=25, + number=7665967, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +QUUX_FIELD_NUMBER = 7663707 +quux = _descriptor.FieldDescriptor( + name='quux', full_name='protobuf_unittest.quux', index=26, + number=7663707, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +CORGE_FIELD_NUMBER = 7663442 +corge = _descriptor.FieldDescriptor( + name='corge', full_name='protobuf_unittest.corge', index=27, + number=7663442, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +GRAULT_FIELD_NUMBER = 7650927 +grault = _descriptor.FieldDescriptor( + name='grault', full_name='protobuf_unittest.grault', index=28, + number=7650927, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +GARPLY_FIELD_NUMBER = 7649992 +garply = _descriptor.FieldDescriptor( + name='garply', full_name='protobuf_unittest.garply', index=29, + number=7649992, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEX_OPT1_FIELD_NUMBER = 7646756 +complex_opt1 = _descriptor.FieldDescriptor( + name='complex_opt1', full_name='protobuf_unittest.complex_opt1', index=30, + number=7646756, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEX_OPT2_FIELD_NUMBER = 7636949 +complex_opt2 = _descriptor.FieldDescriptor( + name='complex_opt2', full_name='protobuf_unittest.complex_opt2', index=31, + number=7636949, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEX_OPT3_FIELD_NUMBER = 7636463 +complex_opt3 = _descriptor.FieldDescriptor( + name='complex_opt3', full_name='protobuf_unittest.complex_opt3', index=32, + number=7636463, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +COMPLEXOPT6_FIELD_NUMBER = 7595468 +complexopt6 = _descriptor.FieldDescriptor( + name='complexopt6', full_name='protobuf_unittest.complexopt6', index=33, + number=7595468, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FILEOPT_FIELD_NUMBER = 15478479 +fileopt = _descriptor.FieldDescriptor( + name='fileopt', full_name='protobuf_unittest.fileopt', index=34, + number=15478479, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MSGOPT_FIELD_NUMBER = 15480088 +msgopt = _descriptor.FieldDescriptor( + name='msgopt', full_name='protobuf_unittest.msgopt', index=35, + number=15480088, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +FIELDOPT_FIELD_NUMBER = 15481374 +fieldopt = _descriptor.FieldDescriptor( + name='fieldopt', full_name='protobuf_unittest.fieldopt', index=36, + number=15481374, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUMOPT_FIELD_NUMBER = 15483218 +enumopt = _descriptor.FieldDescriptor( + name='enumopt', full_name='protobuf_unittest.enumopt', index=37, + number=15483218, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ENUMVALOPT_FIELD_NUMBER = 15486921 +enumvalopt = _descriptor.FieldDescriptor( + name='enumvalopt', full_name='protobuf_unittest.enumvalopt', index=38, + number=15486921, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +SERVICEOPT_FIELD_NUMBER = 15497145 +serviceopt = _descriptor.FieldDescriptor( + name='serviceopt', full_name='protobuf_unittest.serviceopt', index=39, + number=15497145, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +METHODOPT_FIELD_NUMBER = 15512713 +methodopt = _descriptor.FieldDescriptor( + name='methodopt', full_name='protobuf_unittest.methodopt', index=40, + number=15512713, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REQUIRED_ENUM_OPT_FIELD_NUMBER = 106161807 +required_enum_opt = _descriptor.FieldDescriptor( + name='required_enum_opt', full_name='protobuf_unittest.required_enum_opt', index=41, + number=106161807, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM = _descriptor.EnumDescriptor( + name='AnEnum', + full_name='protobuf_unittest.TestMessageWithCustomOptions.AnEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ANENUM_VAL1', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ANENUM_VAL2', index=1, number=2, + serialized_options=_b('\260\206\372\005{'), + type=None), + ], + containing_type=None, + serialized_options=_b('\305\366\311\035\353\374\377\377'), + serialized_start=190, + serialized_end=249, +) +_sym_db.RegisterEnumDescriptor(_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM) + +_DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE = _descriptor.EnumDescriptor( + name='TestEnumType', + full_name='protobuf_unittest.DummyMessageContainingEnum.TestEnumType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='TEST_OPTION_ENUM_TYPE1', index=0, number=22, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='TEST_OPTION_ENUM_TYPE2', index=1, number=-23, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=443, + serialized_end=522, +) +_sym_db.RegisterEnumDescriptor(_DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE) + +_NESTEDOPTIONTYPE_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest.NestedOptionType.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NESTED_ENUM_VALUE', index=0, number=1, + serialized_options=_b('\260\206\372\005\354\007'), + type=None), + ], + containing_type=None, + serialized_options=_b('\305\366\311\035\353\003\000\000'), + serialized_start=2618, + serialized_end=2671, +) +_sym_db.RegisterEnumDescriptor(_NESTEDOPTIONTYPE_NESTEDENUM) + +_OLDOPTIONTYPE_TESTENUM = _descriptor.EnumDescriptor( + name='TestEnum', + full_name='protobuf_unittest.OldOptionType.TestEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OLD_VALUE', index=0, number=0, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2815, + serialized_end=2840, +) +_sym_db.RegisterEnumDescriptor(_OLDOPTIONTYPE_TESTENUM) + +_NEWOPTIONTYPE_TESTENUM = _descriptor.EnumDescriptor( + name='TestEnum', + full_name='protobuf_unittest.NewOptionType.TestEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OLD_VALUE', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEW_VALUE', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2917, + serialized_end=2957, +) +_sym_db.RegisterEnumDescriptor(_NEWOPTIONTYPE_TESTENUM) + + +_TESTMESSAGEWITHCUSTOMOPTIONS = _descriptor.Descriptor( + name='TestMessageWithCustomOptions', + full_name='protobuf_unittest.TestMessageWithCustomOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestMessageWithCustomOptions.field1', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001\301\340\303\035-\341u\n\002\000\000\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_field', full_name='protobuf_unittest.TestMessageWithCustomOptions.oneof_field', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM, + ], + serialized_options=_b('\010\000\340\351\302\035\310\377\377\377\377\377\377\377\377\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='AnOneof', full_name='protobuf_unittest.TestMessageWithCustomOptions.AnOneof', + index=0, containing_type=None, fields=[], serialized_options=_b('\370\254\303\035\235\377\377\377\377\377\377\377\377\001')), + ], + serialized_start=103, + serialized_end=294, +) + + +_CUSTOMOPTIONFOOREQUEST = _descriptor.Descriptor( + name='CustomOptionFooRequest', + full_name='protobuf_unittest.CustomOptionFooRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=296, + serialized_end=320, +) + + +_CUSTOMOPTIONFOORESPONSE = _descriptor.Descriptor( + name='CustomOptionFooResponse', + full_name='protobuf_unittest.CustomOptionFooResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=322, + serialized_end=347, +) + + +_CUSTOMOPTIONFOOCLIENTMESSAGE = _descriptor.Descriptor( + name='CustomOptionFooClientMessage', + full_name='protobuf_unittest.CustomOptionFooClientMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=349, + serialized_end=379, +) + + +_CUSTOMOPTIONFOOSERVERMESSAGE = _descriptor.Descriptor( + name='CustomOptionFooServerMessage', + full_name='protobuf_unittest.CustomOptionFooServerMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=381, + serialized_end=411, +) + + +_DUMMYMESSAGECONTAININGENUM = _descriptor.Descriptor( + name='DummyMessageContainingEnum', + full_name='protobuf_unittest.DummyMessageContainingEnum', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=413, + serialized_end=522, +) + + +_DUMMYMESSAGEINVALIDASOPTIONTYPE = _descriptor.Descriptor( + name='DummyMessageInvalidAsOptionType', + full_name='protobuf_unittest.DummyMessageInvalidAsOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=524, + serialized_end=557, +) + + +_CUSTOMOPTIONMININTEGERVALUES = _descriptor.Descriptor( + name='CustomOptionMinIntegerValues', + full_name='protobuf_unittest.CustomOptionMinIntegerValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\320\336\262\035\000\350\306\262\035\200\200\200\200\370\377\377\377\377\001\260\274\262\035\200\200\200\200\200\200\200\200\200\001\200\223\262\035\000\370\365\260\035\000\200\304\260\035\377\377\377\377\017\370\227\260\035\377\377\377\377\377\377\377\377\377\001\235\365\257\035\000\000\000\000\221\356\257\035\000\000\000\000\000\000\000\000\255\215\257\035\000\000\000\200\231\326\250\035\000\000\000\000\000\000\000\200'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=560, + serialized_end=698, +) + + +_CUSTOMOPTIONMAXINTEGERVALUES = _descriptor.Descriptor( + name='CustomOptionMaxIntegerValues', + full_name='protobuf_unittest.CustomOptionMaxIntegerValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\320\336\262\035\001\350\306\262\035\377\377\377\377\007\260\274\262\035\377\377\377\377\377\377\377\377\177\200\223\262\035\377\377\377\377\017\370\365\260\035\377\377\377\377\377\377\377\377\377\001\200\304\260\035\376\377\377\377\017\370\227\260\035\376\377\377\377\377\377\377\377\377\001\235\365\257\035\377\377\377\377\221\356\257\035\377\377\377\377\377\377\377\377\255\215\257\035\377\377\377\177\231\326\250\035\377\377\377\377\377\377\377\177'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=701, + serialized_end=846, +) + + +_CUSTOMOPTIONOTHERVALUES = _descriptor.Descriptor( + name='CustomOptionOtherValues', + full_name='protobuf_unittest.CustomOptionOtherValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\350\306\262\035\234\377\377\377\377\377\377\377\377\001\365\337\243\035\347\207EA\351\334\242\035\373Y\214B\312\300\363?\252\334\242\035\016Hello, \"World\"\262\331\242\035\013Hello\000World\210\331\242\035\351\377\377\377\377\377\377\377\377\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=848, + serialized_end=958, +) + + +_SETTINGREALSFROMPOSITIVEINTS = _descriptor.Descriptor( + name='SettingRealsFromPositiveInts', + full_name='protobuf_unittest.SettingRealsFromPositiveInts', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\365\337\243\035\000\000@A\351\334\242\035\000\000\000\000\000@c@'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=960, + serialized_end=1012, +) + + +_SETTINGREALSFROMNEGATIVEINTS = _descriptor.Descriptor( + name='SettingRealsFromNegativeInts', + full_name='protobuf_unittest.SettingRealsFromNegativeInts', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\365\337\243\035\000\000@\301\351\334\242\035\000\000\000\000\000@c\300'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1014, + serialized_end=1066, +) + + +_COMPLEXOPTIONTYPE1 = _descriptor.Descriptor( + name='ComplexOptionType1', + full_name='protobuf_unittest.ComplexOptionType1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo', full_name='protobuf_unittest.ComplexOptionType1.foo', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo2', full_name='protobuf_unittest.ComplexOptionType1.foo2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo3', full_name='protobuf_unittest.ComplexOptionType1.foo3', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo4', full_name='protobuf_unittest.ComplexOptionType1.foo4', index=3, + number=4, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=1068, + serialized_end=1153, +) + + +_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 = _descriptor.Descriptor( + name='ComplexOptionType4', + full_name='protobuf_unittest.ComplexOptionType2.ComplexOptionType4', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='waldo', full_name='protobuf_unittest.ComplexOptionType2.ComplexOptionType4.waldo', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='complex_opt4', full_name='protobuf_unittest.ComplexOptionType2.ComplexOptionType4.complex_opt4', index=0, + number=7633546, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1390, + serialized_end=1541, +) + +_COMPLEXOPTIONTYPE2 = _descriptor.Descriptor( + name='ComplexOptionType2', + full_name='protobuf_unittest.ComplexOptionType2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bar', full_name='protobuf_unittest.ComplexOptionType2.bar', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='baz', full_name='protobuf_unittest.ComplexOptionType2.baz', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fred', full_name='protobuf_unittest.ComplexOptionType2.fred', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='barney', full_name='protobuf_unittest.ComplexOptionType2.barney', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=1156, + serialized_end=1551, +) + + +_COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5 = _descriptor.Descriptor( + name='ComplexOptionType5', + full_name='protobuf_unittest.ComplexOptionType3.ComplexOptionType5', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='plugh', full_name='protobuf_unittest.ComplexOptionType3.ComplexOptionType5.plugh', index=0, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1675, + serialized_end=1710, +) + +_COMPLEXOPTIONTYPE3 = _descriptor.Descriptor( + name='ComplexOptionType3', + full_name='protobuf_unittest.ComplexOptionType3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='qux', full_name='protobuf_unittest.ComplexOptionType3.qux', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='complexoptiontype5', full_name='protobuf_unittest.ComplexOptionType3.complexoptiontype5', index=1, + number=2, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1554, + serialized_end=1710, +) + + +_COMPLEXOPT6 = _descriptor.Descriptor( + name='ComplexOpt6', + full_name='protobuf_unittest.ComplexOpt6', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='xyzzy', full_name='protobuf_unittest.ComplexOpt6.xyzzy', index=0, + number=7593951, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1712, + serialized_end=1743, +) + + +_VARIOUSCOMPLEXOPTIONS = _descriptor.Descriptor( + name='VariousComplexOptions', + full_name='protobuf_unittest.VariousComplexOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\242\342\225\035\002\010*\242\342\225\035\006\330\205\236\035\304\002\242\342\225\035\010\222\365\235\035\003\010\354\006\242\342\225\035\002 c\242\342\225\035\002 X\252\375\220\035\003\020\333\007\252\375\220\035\006\370\346\227\035\216\005\252\375\220\035\005\n\003\010\347\005\252\375\220\035\010\n\006\330\205\236\035\317\017\252\375\220\035\n\n\010\222\365\235\035\003\010\330\017\252\375\220\035\010\302\254\227\035\003\010\345\005\252\375\220\035\013\302\254\227\035\006\330\205\236\035\316\017\252\375\220\035\r\302\254\227\035\010\222\365\235\035\003\010\311\020\322\250\217\035\003\010\263\017\252\375\220\035\005\032\003\010\301\002\252\375\220\035\004\"\002\010e\252\375\220\035\005\"\003\010\324\001\372\336\220\035\002\010\t\372\336\220\035\004\023\030\026\024\343\334\374\034\370\375\373\034\030\344\334\374\034'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1746, + serialized_end=1987, +) + + +_AGGREGATEMESSAGESET = _descriptor.Descriptor( + name='AggregateMessageSet', + full_name='protobuf_unittest.AggregateMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=1989, + serialized_end=2024, +) + + +_AGGREGATEMESSAGESETELEMENT = _descriptor.Descriptor( + name='AggregateMessageSetElement', + full_name='protobuf_unittest.AggregateMessageSetElement', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='s', full_name='protobuf_unittest.AggregateMessageSetElement.s', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_unittest.AggregateMessageSetElement.message_set_extension', index=0, + number=15447542, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2027, + serialized_end=2187, +) + + +_AGGREGATE = _descriptor.Descriptor( + name='Aggregate', + full_name='protobuf_unittest.Aggregate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.Aggregate.i', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='s', full_name='protobuf_unittest.Aggregate.s', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sub', full_name='protobuf_unittest.Aggregate.sub', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='file', full_name='protobuf_unittest.Aggregate.file', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mset', full_name='protobuf_unittest.Aggregate.mset', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='nested', full_name='protobuf_unittest.Aggregate.nested', index=0, + number=15476903, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2190, + serialized_end=2443, +) + + +_AGGREGATEMESSAGE = _descriptor.Descriptor( + name='AggregateMessage', + full_name='protobuf_unittest.AggregateMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='fieldname', full_name='protobuf_unittest.AggregateMessage.fieldname', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\362\241\207;\021\022\017FieldAnnotation'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\302\321\206;\025\010e\022\021MessageAnnotation'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2445, + serialized_end=2534, +) + + +_NESTEDOPTIONTYPE_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.NestedOptionType.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nested_field', full_name='protobuf_unittest.NestedOptionType.NestedMessage.nested_field', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\301\340\303\035\352\003\000\000\000\000\000\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\340\351\302\035\351\007'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2557, + serialized_end=2616, +) + +_NESTEDOPTIONTYPE = _descriptor.Descriptor( + name='NestedOptionType', + full_name='protobuf_unittest.NestedOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + _descriptor.FieldDescriptor( + name='nested_extension', full_name='protobuf_unittest.NestedOptionType.nested_extension', index=0, + number=7912573, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\310\213\312\035\355\007'), file=DESCRIPTOR), + ], + nested_types=[_NESTEDOPTIONTYPE_NESTEDMESSAGE, ], + enum_types=[ + _NESTEDOPTIONTYPE_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2537, + serialized_end=2738, +) + + +_OLDOPTIONTYPE = _descriptor.Descriptor( + name='OldOptionType', + full_name='protobuf_unittest.OldOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.OldOptionType.value', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _OLDOPTIONTYPE_TESTENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2740, + serialized_end=2840, +) + + +_NEWOPTIONTYPE = _descriptor.Descriptor( + name='NewOptionType', + full_name='protobuf_unittest.NewOptionType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.NewOptionType.value', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _NEWOPTIONTYPE_TESTENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2842, + serialized_end=2957, +) + + +_TESTMESSAGEWITHREQUIREDENUMOPTION = _descriptor.Descriptor( + name='TestMessageWithRequiredEnumOption', + full_name='protobuf_unittest.TestMessageWithRequiredEnumOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\372\350\374\224\003\002\010\000'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2959, + serialized_end=3004, +) + +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM.containing_type = _TESTMESSAGEWITHCUSTOMOPTIONS +_TESTMESSAGEWITHCUSTOMOPTIONS.oneofs_by_name['AnOneof'].fields.append( + _TESTMESSAGEWITHCUSTOMOPTIONS.fields_by_name['oneof_field']) +_TESTMESSAGEWITHCUSTOMOPTIONS.fields_by_name['oneof_field'].containing_oneof = _TESTMESSAGEWITHCUSTOMOPTIONS.oneofs_by_name['AnOneof'] +_DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE.containing_type = _DUMMYMESSAGECONTAININGENUM +_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4.containing_type = _COMPLEXOPTIONTYPE2 +_COMPLEXOPTIONTYPE2.fields_by_name['bar'].message_type = _COMPLEXOPTIONTYPE1 +_COMPLEXOPTIONTYPE2.fields_by_name['fred'].message_type = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 +_COMPLEXOPTIONTYPE2.fields_by_name['barney'].message_type = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 +_COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5.containing_type = _COMPLEXOPTIONTYPE3 +_COMPLEXOPTIONTYPE3.fields_by_name['complexoptiontype5'].message_type = _COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5 +_AGGREGATE.fields_by_name['sub'].message_type = _AGGREGATE +_AGGREGATE.fields_by_name['file'].message_type = google_dot_protobuf_dot_descriptor__pb2._FILEOPTIONS +_AGGREGATE.fields_by_name['mset'].message_type = _AGGREGATEMESSAGESET +_NESTEDOPTIONTYPE_NESTEDMESSAGE.containing_type = _NESTEDOPTIONTYPE +_NESTEDOPTIONTYPE_NESTEDENUM.containing_type = _NESTEDOPTIONTYPE +_OLDOPTIONTYPE.fields_by_name['value'].enum_type = _OLDOPTIONTYPE_TESTENUM +_OLDOPTIONTYPE_TESTENUM.containing_type = _OLDOPTIONTYPE +_NEWOPTIONTYPE.fields_by_name['value'].enum_type = _NEWOPTIONTYPE_TESTENUM +_NEWOPTIONTYPE_TESTENUM.containing_type = _NEWOPTIONTYPE +DESCRIPTOR.message_types_by_name['TestMessageWithCustomOptions'] = _TESTMESSAGEWITHCUSTOMOPTIONS +DESCRIPTOR.message_types_by_name['CustomOptionFooRequest'] = _CUSTOMOPTIONFOOREQUEST +DESCRIPTOR.message_types_by_name['CustomOptionFooResponse'] = _CUSTOMOPTIONFOORESPONSE +DESCRIPTOR.message_types_by_name['CustomOptionFooClientMessage'] = _CUSTOMOPTIONFOOCLIENTMESSAGE +DESCRIPTOR.message_types_by_name['CustomOptionFooServerMessage'] = _CUSTOMOPTIONFOOSERVERMESSAGE +DESCRIPTOR.message_types_by_name['DummyMessageContainingEnum'] = _DUMMYMESSAGECONTAININGENUM +DESCRIPTOR.message_types_by_name['DummyMessageInvalidAsOptionType'] = _DUMMYMESSAGEINVALIDASOPTIONTYPE +DESCRIPTOR.message_types_by_name['CustomOptionMinIntegerValues'] = _CUSTOMOPTIONMININTEGERVALUES +DESCRIPTOR.message_types_by_name['CustomOptionMaxIntegerValues'] = _CUSTOMOPTIONMAXINTEGERVALUES +DESCRIPTOR.message_types_by_name['CustomOptionOtherValues'] = _CUSTOMOPTIONOTHERVALUES +DESCRIPTOR.message_types_by_name['SettingRealsFromPositiveInts'] = _SETTINGREALSFROMPOSITIVEINTS +DESCRIPTOR.message_types_by_name['SettingRealsFromNegativeInts'] = _SETTINGREALSFROMNEGATIVEINTS +DESCRIPTOR.message_types_by_name['ComplexOptionType1'] = _COMPLEXOPTIONTYPE1 +DESCRIPTOR.message_types_by_name['ComplexOptionType2'] = _COMPLEXOPTIONTYPE2 +DESCRIPTOR.message_types_by_name['ComplexOptionType3'] = _COMPLEXOPTIONTYPE3 +DESCRIPTOR.message_types_by_name['ComplexOpt6'] = _COMPLEXOPT6 +DESCRIPTOR.message_types_by_name['VariousComplexOptions'] = _VARIOUSCOMPLEXOPTIONS +DESCRIPTOR.message_types_by_name['AggregateMessageSet'] = _AGGREGATEMESSAGESET +DESCRIPTOR.message_types_by_name['AggregateMessageSetElement'] = _AGGREGATEMESSAGESETELEMENT +DESCRIPTOR.message_types_by_name['Aggregate'] = _AGGREGATE +DESCRIPTOR.message_types_by_name['AggregateMessage'] = _AGGREGATEMESSAGE +DESCRIPTOR.message_types_by_name['NestedOptionType'] = _NESTEDOPTIONTYPE +DESCRIPTOR.message_types_by_name['OldOptionType'] = _OLDOPTIONTYPE +DESCRIPTOR.message_types_by_name['NewOptionType'] = _NEWOPTIONTYPE +DESCRIPTOR.message_types_by_name['TestMessageWithRequiredEnumOption'] = _TESTMESSAGEWITHREQUIREDENUMOPTION +DESCRIPTOR.enum_types_by_name['MethodOpt1'] = _METHODOPT1 +DESCRIPTOR.enum_types_by_name['AggregateEnum'] = _AGGREGATEENUM +DESCRIPTOR.extensions_by_name['file_opt1'] = file_opt1 +DESCRIPTOR.extensions_by_name['message_opt1'] = message_opt1 +DESCRIPTOR.extensions_by_name['field_opt1'] = field_opt1 +DESCRIPTOR.extensions_by_name['field_opt2'] = field_opt2 +DESCRIPTOR.extensions_by_name['oneof_opt1'] = oneof_opt1 +DESCRIPTOR.extensions_by_name['enum_opt1'] = enum_opt1 +DESCRIPTOR.extensions_by_name['enum_value_opt1'] = enum_value_opt1 +DESCRIPTOR.extensions_by_name['service_opt1'] = service_opt1 +DESCRIPTOR.extensions_by_name['method_opt1'] = method_opt1 +DESCRIPTOR.extensions_by_name['bool_opt'] = bool_opt +DESCRIPTOR.extensions_by_name['int32_opt'] = int32_opt +DESCRIPTOR.extensions_by_name['int64_opt'] = int64_opt +DESCRIPTOR.extensions_by_name['uint32_opt'] = uint32_opt +DESCRIPTOR.extensions_by_name['uint64_opt'] = uint64_opt +DESCRIPTOR.extensions_by_name['sint32_opt'] = sint32_opt +DESCRIPTOR.extensions_by_name['sint64_opt'] = sint64_opt +DESCRIPTOR.extensions_by_name['fixed32_opt'] = fixed32_opt +DESCRIPTOR.extensions_by_name['fixed64_opt'] = fixed64_opt +DESCRIPTOR.extensions_by_name['sfixed32_opt'] = sfixed32_opt +DESCRIPTOR.extensions_by_name['sfixed64_opt'] = sfixed64_opt +DESCRIPTOR.extensions_by_name['float_opt'] = float_opt +DESCRIPTOR.extensions_by_name['double_opt'] = double_opt +DESCRIPTOR.extensions_by_name['string_opt'] = string_opt +DESCRIPTOR.extensions_by_name['bytes_opt'] = bytes_opt +DESCRIPTOR.extensions_by_name['enum_opt'] = enum_opt +DESCRIPTOR.extensions_by_name['message_type_opt'] = message_type_opt +DESCRIPTOR.extensions_by_name['quux'] = quux +DESCRIPTOR.extensions_by_name['corge'] = corge +DESCRIPTOR.extensions_by_name['grault'] = grault +DESCRIPTOR.extensions_by_name['garply'] = garply +DESCRIPTOR.extensions_by_name['complex_opt1'] = complex_opt1 +DESCRIPTOR.extensions_by_name['complex_opt2'] = complex_opt2 +DESCRIPTOR.extensions_by_name['complex_opt3'] = complex_opt3 +DESCRIPTOR.extensions_by_name['complexopt6'] = complexopt6 +DESCRIPTOR.extensions_by_name['fileopt'] = fileopt +DESCRIPTOR.extensions_by_name['msgopt'] = msgopt +DESCRIPTOR.extensions_by_name['fieldopt'] = fieldopt +DESCRIPTOR.extensions_by_name['enumopt'] = enumopt +DESCRIPTOR.extensions_by_name['enumvalopt'] = enumvalopt +DESCRIPTOR.extensions_by_name['serviceopt'] = serviceopt +DESCRIPTOR.extensions_by_name['methodopt'] = methodopt +DESCRIPTOR.extensions_by_name['required_enum_opt'] = required_enum_opt +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageWithCustomOptions = _reflection.GeneratedProtocolMessageType('TestMessageWithCustomOptions', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGEWITHCUSTOMOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageWithCustomOptions) + )) +_sym_db.RegisterMessage(TestMessageWithCustomOptions) + +CustomOptionFooRequest = _reflection.GeneratedProtocolMessageType('CustomOptionFooRequest', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOOREQUEST, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooRequest) + )) +_sym_db.RegisterMessage(CustomOptionFooRequest) + +CustomOptionFooResponse = _reflection.GeneratedProtocolMessageType('CustomOptionFooResponse', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOORESPONSE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooResponse) + )) +_sym_db.RegisterMessage(CustomOptionFooResponse) + +CustomOptionFooClientMessage = _reflection.GeneratedProtocolMessageType('CustomOptionFooClientMessage', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOOCLIENTMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooClientMessage) + )) +_sym_db.RegisterMessage(CustomOptionFooClientMessage) + +CustomOptionFooServerMessage = _reflection.GeneratedProtocolMessageType('CustomOptionFooServerMessage', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONFOOSERVERMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionFooServerMessage) + )) +_sym_db.RegisterMessage(CustomOptionFooServerMessage) + +DummyMessageContainingEnum = _reflection.GeneratedProtocolMessageType('DummyMessageContainingEnum', (_message.Message,), dict( + DESCRIPTOR = _DUMMYMESSAGECONTAININGENUM, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.DummyMessageContainingEnum) + )) +_sym_db.RegisterMessage(DummyMessageContainingEnum) + +DummyMessageInvalidAsOptionType = _reflection.GeneratedProtocolMessageType('DummyMessageInvalidAsOptionType', (_message.Message,), dict( + DESCRIPTOR = _DUMMYMESSAGEINVALIDASOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.DummyMessageInvalidAsOptionType) + )) +_sym_db.RegisterMessage(DummyMessageInvalidAsOptionType) + +CustomOptionMinIntegerValues = _reflection.GeneratedProtocolMessageType('CustomOptionMinIntegerValues', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONMININTEGERVALUES, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionMinIntegerValues) + )) +_sym_db.RegisterMessage(CustomOptionMinIntegerValues) + +CustomOptionMaxIntegerValues = _reflection.GeneratedProtocolMessageType('CustomOptionMaxIntegerValues', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONMAXINTEGERVALUES, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionMaxIntegerValues) + )) +_sym_db.RegisterMessage(CustomOptionMaxIntegerValues) + +CustomOptionOtherValues = _reflection.GeneratedProtocolMessageType('CustomOptionOtherValues', (_message.Message,), dict( + DESCRIPTOR = _CUSTOMOPTIONOTHERVALUES, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.CustomOptionOtherValues) + )) +_sym_db.RegisterMessage(CustomOptionOtherValues) + +SettingRealsFromPositiveInts = _reflection.GeneratedProtocolMessageType('SettingRealsFromPositiveInts', (_message.Message,), dict( + DESCRIPTOR = _SETTINGREALSFROMPOSITIVEINTS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.SettingRealsFromPositiveInts) + )) +_sym_db.RegisterMessage(SettingRealsFromPositiveInts) + +SettingRealsFromNegativeInts = _reflection.GeneratedProtocolMessageType('SettingRealsFromNegativeInts', (_message.Message,), dict( + DESCRIPTOR = _SETTINGREALSFROMNEGATIVEINTS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.SettingRealsFromNegativeInts) + )) +_sym_db.RegisterMessage(SettingRealsFromNegativeInts) + +ComplexOptionType1 = _reflection.GeneratedProtocolMessageType('ComplexOptionType1', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPTIONTYPE1, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType1) + )) +_sym_db.RegisterMessage(ComplexOptionType1) + +ComplexOptionType2 = _reflection.GeneratedProtocolMessageType('ComplexOptionType2', (_message.Message,), dict( + + ComplexOptionType4 = _reflection.GeneratedProtocolMessageType('ComplexOptionType4', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType2.ComplexOptionType4) + )) + , + DESCRIPTOR = _COMPLEXOPTIONTYPE2, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType2) + )) +_sym_db.RegisterMessage(ComplexOptionType2) +_sym_db.RegisterMessage(ComplexOptionType2.ComplexOptionType4) + +ComplexOptionType3 = _reflection.GeneratedProtocolMessageType('ComplexOptionType3', (_message.Message,), dict( + + ComplexOptionType5 = _reflection.GeneratedProtocolMessageType('ComplexOptionType5', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPTIONTYPE3_COMPLEXOPTIONTYPE5, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType3.ComplexOptionType5) + )) + , + DESCRIPTOR = _COMPLEXOPTIONTYPE3, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOptionType3) + )) +_sym_db.RegisterMessage(ComplexOptionType3) +_sym_db.RegisterMessage(ComplexOptionType3.ComplexOptionType5) + +ComplexOpt6 = _reflection.GeneratedProtocolMessageType('ComplexOpt6', (_message.Message,), dict( + DESCRIPTOR = _COMPLEXOPT6, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ComplexOpt6) + )) +_sym_db.RegisterMessage(ComplexOpt6) + +VariousComplexOptions = _reflection.GeneratedProtocolMessageType('VariousComplexOptions', (_message.Message,), dict( + DESCRIPTOR = _VARIOUSCOMPLEXOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.VariousComplexOptions) + )) +_sym_db.RegisterMessage(VariousComplexOptions) + +AggregateMessageSet = _reflection.GeneratedProtocolMessageType('AggregateMessageSet', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATEMESSAGESET, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AggregateMessageSet) + )) +_sym_db.RegisterMessage(AggregateMessageSet) + +AggregateMessageSetElement = _reflection.GeneratedProtocolMessageType('AggregateMessageSetElement', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATEMESSAGESETELEMENT, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AggregateMessageSetElement) + )) +_sym_db.RegisterMessage(AggregateMessageSetElement) + +Aggregate = _reflection.GeneratedProtocolMessageType('Aggregate', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Aggregate) + )) +_sym_db.RegisterMessage(Aggregate) + +AggregateMessage = _reflection.GeneratedProtocolMessageType('AggregateMessage', (_message.Message,), dict( + DESCRIPTOR = _AGGREGATEMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.AggregateMessage) + )) +_sym_db.RegisterMessage(AggregateMessage) + +NestedOptionType = _reflection.GeneratedProtocolMessageType('NestedOptionType', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _NESTEDOPTIONTYPE_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NestedOptionType.NestedMessage) + )) + , + DESCRIPTOR = _NESTEDOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NestedOptionType) + )) +_sym_db.RegisterMessage(NestedOptionType) +_sym_db.RegisterMessage(NestedOptionType.NestedMessage) + +OldOptionType = _reflection.GeneratedProtocolMessageType('OldOptionType', (_message.Message,), dict( + DESCRIPTOR = _OLDOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OldOptionType) + )) +_sym_db.RegisterMessage(OldOptionType) + +NewOptionType = _reflection.GeneratedProtocolMessageType('NewOptionType', (_message.Message,), dict( + DESCRIPTOR = _NEWOPTIONTYPE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NewOptionType) + )) +_sym_db.RegisterMessage(NewOptionType) + +TestMessageWithRequiredEnumOption = _reflection.GeneratedProtocolMessageType('TestMessageWithRequiredEnumOption', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGEWITHREQUIREDENUMOPTION, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageWithRequiredEnumOption) + )) +_sym_db.RegisterMessage(TestMessageWithRequiredEnumOption) + +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(file_opt1) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(message_opt1) +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(field_opt1) +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(field_opt2) +google_dot_protobuf_dot_descriptor__pb2.OneofOptions.RegisterExtension(oneof_opt1) +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(enum_opt1) +google_dot_protobuf_dot_descriptor__pb2.EnumValueOptions.RegisterExtension(enum_value_opt1) +google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension(service_opt1) +method_opt1.enum_type = _METHODOPT1 +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(method_opt1) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(bool_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(int32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(int64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(uint32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(uint64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sint32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sint64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(fixed32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(fixed64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sfixed32_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(sfixed64_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(float_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(double_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(string_opt) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(bytes_opt) +enum_opt.enum_type = _DUMMYMESSAGECONTAININGENUM_TESTENUMTYPE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(enum_opt) +message_type_opt.message_type = _DUMMYMESSAGEINVALIDASOPTIONTYPE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(message_type_opt) +ComplexOptionType1.RegisterExtension(quux) +corge.message_type = _COMPLEXOPTIONTYPE3 +ComplexOptionType1.RegisterExtension(corge) +ComplexOptionType2.RegisterExtension(grault) +garply.message_type = _COMPLEXOPTIONTYPE1 +ComplexOptionType2.RegisterExtension(garply) +complex_opt1.message_type = _COMPLEXOPTIONTYPE1 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complex_opt1) +complex_opt2.message_type = _COMPLEXOPTIONTYPE2 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complex_opt2) +complex_opt3.message_type = _COMPLEXOPTIONTYPE3 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complex_opt3) +complexopt6.message_type = _COMPLEXOPT6 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(complexopt6) +fileopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(fileopt) +msgopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(msgopt) +fieldopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(fieldopt) +enumopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(enumopt) +enumvalopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.EnumValueOptions.RegisterExtension(enumvalopt) +serviceopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension(serviceopt) +methodopt.message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(methodopt) +required_enum_opt.message_type = _OLDOPTIONTYPE +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(required_enum_opt) +_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4.extensions_by_name['complex_opt4'].message_type = _COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4 +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(_COMPLEXOPTIONTYPE2_COMPLEXOPTIONTYPE4.extensions_by_name['complex_opt4']) +_AGGREGATEMESSAGESETELEMENT.extensions_by_name['message_set_extension'].message_type = _AGGREGATEMESSAGESETELEMENT +AggregateMessageSet.RegisterExtension(_AGGREGATEMESSAGESETELEMENT.extensions_by_name['message_set_extension']) +_AGGREGATE.extensions_by_name['nested'].message_type = _AGGREGATE +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(_AGGREGATE.extensions_by_name['nested']) +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(_NESTEDOPTIONTYPE.extensions_by_name['nested_extension']) + +DESCRIPTOR._options = None +_AGGREGATEENUM._options = None +_AGGREGATEENUM.values_by_name["VALUE"]._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS.oneofs_by_name['AnOneof']._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS_ANENUM.values_by_name["ANENUM_VAL2"]._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS.fields_by_name['field1']._options = None +_TESTMESSAGEWITHCUSTOMOPTIONS._options = None +_CUSTOMOPTIONMININTEGERVALUES._options = None +_CUSTOMOPTIONMAXINTEGERVALUES._options = None +_CUSTOMOPTIONOTHERVALUES._options = None +_SETTINGREALSFROMPOSITIVEINTS._options = None +_SETTINGREALSFROMNEGATIVEINTS._options = None +_VARIOUSCOMPLEXOPTIONS._options = None +_AGGREGATEMESSAGESET._options = None +_AGGREGATEMESSAGE.fields_by_name['fieldname']._options = None +_AGGREGATEMESSAGE._options = None +_NESTEDOPTIONTYPE_NESTEDMESSAGE.fields_by_name['nested_field']._options = None +_NESTEDOPTIONTYPE_NESTEDMESSAGE._options = None +_NESTEDOPTIONTYPE_NESTEDENUM._options = None +_NESTEDOPTIONTYPE_NESTEDENUM.values_by_name["NESTED_ENUM_VALUE"]._options = None +_NESTEDOPTIONTYPE.extensions_by_name['nested_extension']._options = None +_TESTMESSAGEWITHREQUIREDENUMOPTION._options = None + +_TESTSERVICEWITHCUSTOMOPTIONS = _descriptor.ServiceDescriptor( + name='TestServiceWithCustomOptions', + full_name='protobuf_unittest.TestServiceWithCustomOptions', + file=DESCRIPTOR, + index=0, + serialized_options=_b('\220\262\213\036\323\333\200\313I'), + serialized_start=3142, + serialized_end=3284, + methods=[ + _descriptor.MethodDescriptor( + name='Foo', + full_name='protobuf_unittest.TestServiceWithCustomOptions.Foo', + index=0, + containing_service=None, + input_type=_CUSTOMOPTIONFOOREQUEST, + output_type=_CUSTOMOPTIONFOORESPONSE, + serialized_options=_b('\340\372\214\036\002'), + ), +]) +_sym_db.RegisterServiceDescriptor(_TESTSERVICEWITHCUSTOMOPTIONS) + +DESCRIPTOR.services_by_name['TestServiceWithCustomOptions'] = _TESTSERVICEWITHCUSTOMOPTIONS + + +_AGGREGATESERVICE = _descriptor.ServiceDescriptor( + name='AggregateService', + full_name='protobuf_unittest.AggregateService', + file=DESCRIPTOR, + index=1, + serialized_options=_b('\312\373\216;\023\022\021ServiceAnnotation'), + serialized_start=3287, + serialized_end=3440, + methods=[ + _descriptor.MethodDescriptor( + name='Method', + full_name='protobuf_unittest.AggregateService.Method', + index=0, + containing_service=None, + input_type=_AGGREGATEMESSAGE, + output_type=_AGGREGATEMESSAGE, + serialized_options=_b('\312\310\226;\022\022\020MethodAnnotation'), + ), +]) +_sym_db.RegisterServiceDescriptor(_AGGREGATESERVICE) + +DESCRIPTOR.services_by_name['AggregateService'] = _AGGREGATESERVICE + +TestServiceWithCustomOptions = service_reflection.GeneratedServiceType('TestServiceWithCustomOptions', (_service.Service,), dict( + DESCRIPTOR = _TESTSERVICEWITHCUSTOMOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + +TestServiceWithCustomOptions_Stub = service_reflection.GeneratedServiceStubType('TestServiceWithCustomOptions_Stub', (TestServiceWithCustomOptions,), dict( + DESCRIPTOR = _TESTSERVICEWITHCUSTOMOPTIONS, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + + +AggregateService = service_reflection.GeneratedServiceType('AggregateService', (_service.Service,), dict( + DESCRIPTOR = _AGGREGATESERVICE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + +AggregateService_Stub = service_reflection.GeneratedServiceStubType('AggregateService_Stub', (AggregateService,), dict( + DESCRIPTOR = _AGGREGATESERVICE, + __module__ = 'google.protobuf.unittest_custom_options_pb2' + )) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_import_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_import_pb2.py new file mode 100644 index 0000000..5812759 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_import_pb2.py @@ -0,0 +1,137 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_import.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_public_pb2 as google_dot_protobuf_dot_unittest__import__public__pb2 + +from google.protobuf.unittest_import_public_pb2 import * + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_import.proto', + package='protobuf_unittest_import', + syntax='proto2', + serialized_options=_b('\n\030com.google.protobuf.testH\001\370\001\001'), + serialized_pb=_b('\n%google/protobuf/unittest_import.proto\x12\x18protobuf_unittest_import\x1a,google/protobuf/unittest_import_public.proto\"\x1a\n\rImportMessage\x12\t\n\x01\x64\x18\x01 \x01(\x05*<\n\nImportEnum\x12\x0e\n\nIMPORT_FOO\x10\x07\x12\x0e\n\nIMPORT_BAR\x10\x08\x12\x0e\n\nIMPORT_BAZ\x10\t*1\n\x10ImportEnumForMap\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x42\x1f\n\x18\x63om.google.protobuf.testH\x01\xf8\x01\x01P\x00') + , + dependencies=[google_dot_protobuf_dot_unittest__import__public__pb2.DESCRIPTOR,], + public_dependencies=[google_dot_protobuf_dot_unittest__import__public__pb2.DESCRIPTOR,]) + +_IMPORTENUM = _descriptor.EnumDescriptor( + name='ImportEnum', + full_name='protobuf_unittest_import.ImportEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IMPORT_FOO', index=0, number=7, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IMPORT_BAR', index=1, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IMPORT_BAZ', index=2, number=9, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=141, + serialized_end=201, +) +_sym_db.RegisterEnumDescriptor(_IMPORTENUM) + +ImportEnum = enum_type_wrapper.EnumTypeWrapper(_IMPORTENUM) +_IMPORTENUMFORMAP = _descriptor.EnumDescriptor( + name='ImportEnumForMap', + full_name='protobuf_unittest_import.ImportEnumForMap', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOO', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=203, + serialized_end=252, +) +_sym_db.RegisterEnumDescriptor(_IMPORTENUMFORMAP) + +ImportEnumForMap = enum_type_wrapper.EnumTypeWrapper(_IMPORTENUMFORMAP) +IMPORT_FOO = 7 +IMPORT_BAR = 8 +IMPORT_BAZ = 9 +UNKNOWN = 0 +FOO = 1 +BAR = 2 + + + +_IMPORTMESSAGE = _descriptor.Descriptor( + name='ImportMessage', + full_name='protobuf_unittest_import.ImportMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest_import.ImportMessage.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=139, +) + +DESCRIPTOR.message_types_by_name['ImportMessage'] = _IMPORTMESSAGE +DESCRIPTOR.enum_types_by_name['ImportEnum'] = _IMPORTENUM +DESCRIPTOR.enum_types_by_name['ImportEnumForMap'] = _IMPORTENUMFORMAP +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ImportMessage = _reflection.GeneratedProtocolMessageType('ImportMessage', (_message.Message,), dict( + DESCRIPTOR = _IMPORTMESSAGE, + __module__ = 'google.protobuf.unittest_import_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_import.ImportMessage) + )) +_sym_db.RegisterMessage(ImportMessage) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_import_public_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_import_public_pb2.py new file mode 100644 index 0000000..3a07bef --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_import_public_pb2.py @@ -0,0 +1,70 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_import_public.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_import_public.proto', + package='protobuf_unittest_import', + syntax='proto2', + serialized_options=_b('\n\030com.google.protobuf.test'), + serialized_pb=_b('\n,google/protobuf/unittest_import_public.proto\x12\x18protobuf_unittest_import\" \n\x13PublicImportMessage\x12\t\n\x01\x65\x18\x01 \x01(\x05\x42\x1a\n\x18\x63om.google.protobuf.test') +) + + + + +_PUBLICIMPORTMESSAGE = _descriptor.Descriptor( + name='PublicImportMessage', + full_name='protobuf_unittest_import.PublicImportMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='e', full_name='protobuf_unittest_import.PublicImportMessage.e', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=74, + serialized_end=106, +) + +DESCRIPTOR.message_types_by_name['PublicImportMessage'] = _PUBLICIMPORTMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PublicImportMessage = _reflection.GeneratedProtocolMessageType('PublicImportMessage', (_message.Message,), dict( + DESCRIPTOR = _PUBLICIMPORTMESSAGE, + __module__ = 'google.protobuf.unittest_import_public_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_import.PublicImportMessage) + )) +_sym_db.RegisterMessage(PublicImportMessage) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_pb2.py new file mode 100644 index 0000000..f100110 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_pb2.py @@ -0,0 +1,255 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_mset.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_mset_wire_format_pb2 as google_dot_protobuf_dot_unittest__mset__wire__format__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_mset.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=_b('H\001\370\001\001'), + serialized_pb=_b('\n#google/protobuf/unittest_mset.proto\x12\x11protobuf_unittest\x1a/google/protobuf/unittest_mset_wire_format.proto\"Z\n\x17TestMessageSetContainer\x12?\n\x0bmessage_set\x18\x01 \x01(\x0b\x32*.proto2_wireformat_unittest.TestMessageSet\"\x9f\x01\n\x18TestMessageSetExtension1\x12\t\n\x01i\x18\x0f \x01(\x05\x32x\n\x15message_set_extension\x12*.proto2_wireformat_unittest.TestMessageSet\x18\xb0\xa6^ \x01(\x0b\x32+.protobuf_unittest.TestMessageSetExtension1\"\xa1\x01\n\x18TestMessageSetExtension2\x12\x0b\n\x03str\x18\x19 \x01(\t2x\n\x15message_set_extension\x12*.proto2_wireformat_unittest.TestMessageSet\x18\xf9\xbb^ \x01(\x0b\x32+.protobuf_unittest.TestMessageSetExtension2\"n\n\rRawMessageSet\x12\x33\n\x04item\x18\x01 \x03(\n2%.protobuf_unittest.RawMessageSet.Item\x1a(\n\x04Item\x12\x0f\n\x07type_id\x18\x02 \x02(\x05\x12\x0f\n\x07message\x18\x03 \x02(\x0c\x42\x05H\x01\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__mset__wire__format__pb2.DESCRIPTOR,]) + + + + +_TESTMESSAGESETCONTAINER = _descriptor.Descriptor( + name='TestMessageSetContainer', + full_name='protobuf_unittest.TestMessageSetContainer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_set', full_name='protobuf_unittest.TestMessageSetContainer.message_set', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=107, + serialized_end=197, +) + + +_TESTMESSAGESETEXTENSION1 = _descriptor.Descriptor( + name='TestMessageSetExtension1', + full_name='protobuf_unittest.TestMessageSetExtension1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.TestMessageSetExtension1.i', index=0, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_unittest.TestMessageSetExtension1.message_set_extension', index=0, + number=1545008, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=200, + serialized_end=359, +) + + +_TESTMESSAGESETEXTENSION2 = _descriptor.Descriptor( + name='TestMessageSetExtension2', + full_name='protobuf_unittest.TestMessageSetExtension2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='str', full_name='protobuf_unittest.TestMessageSetExtension2.str', index=0, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='message_set_extension', full_name='protobuf_unittest.TestMessageSetExtension2.message_set_extension', index=0, + number=1547769, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=362, + serialized_end=523, +) + + +_RAWMESSAGESET_ITEM = _descriptor.Descriptor( + name='Item', + full_name='protobuf_unittest.RawMessageSet.Item', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='type_id', full_name='protobuf_unittest.RawMessageSet.Item.type_id', index=0, + number=2, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message', full_name='protobuf_unittest.RawMessageSet.Item.message', index=1, + number=3, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=595, + serialized_end=635, +) + +_RAWMESSAGESET = _descriptor.Descriptor( + name='RawMessageSet', + full_name='protobuf_unittest.RawMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='item', full_name='protobuf_unittest.RawMessageSet.item', index=0, + number=1, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_RAWMESSAGESET_ITEM, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=525, + serialized_end=635, +) + +_TESTMESSAGESETCONTAINER.fields_by_name['message_set'].message_type = google_dot_protobuf_dot_unittest__mset__wire__format__pb2._TESTMESSAGESET +_RAWMESSAGESET_ITEM.containing_type = _RAWMESSAGESET +_RAWMESSAGESET.fields_by_name['item'].message_type = _RAWMESSAGESET_ITEM +DESCRIPTOR.message_types_by_name['TestMessageSetContainer'] = _TESTMESSAGESETCONTAINER +DESCRIPTOR.message_types_by_name['TestMessageSetExtension1'] = _TESTMESSAGESETEXTENSION1 +DESCRIPTOR.message_types_by_name['TestMessageSetExtension2'] = _TESTMESSAGESETEXTENSION2 +DESCRIPTOR.message_types_by_name['RawMessageSet'] = _RAWMESSAGESET +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageSetContainer = _reflection.GeneratedProtocolMessageType('TestMessageSetContainer', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETCONTAINER, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageSetContainer) + )) +_sym_db.RegisterMessage(TestMessageSetContainer) + +TestMessageSetExtension1 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension1', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION1, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageSetExtension1) + )) +_sym_db.RegisterMessage(TestMessageSetExtension1) + +TestMessageSetExtension2 = _reflection.GeneratedProtocolMessageType('TestMessageSetExtension2', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETEXTENSION2, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageSetExtension2) + )) +_sym_db.RegisterMessage(TestMessageSetExtension2) + +RawMessageSet = _reflection.GeneratedProtocolMessageType('RawMessageSet', (_message.Message,), dict( + + Item = _reflection.GeneratedProtocolMessageType('Item', (_message.Message,), dict( + DESCRIPTOR = _RAWMESSAGESET_ITEM, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.RawMessageSet.Item) + )) + , + DESCRIPTOR = _RAWMESSAGESET, + __module__ = 'google.protobuf.unittest_mset_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.RawMessageSet) + )) +_sym_db.RegisterMessage(RawMessageSet) +_sym_db.RegisterMessage(RawMessageSet.Item) + +_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION1 +google_dot_protobuf_dot_unittest__mset__wire__format__pb2.TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION1.extensions_by_name['message_set_extension']) +_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension'].message_type = _TESTMESSAGESETEXTENSION2 +google_dot_protobuf_dot_unittest__mset__wire__format__pb2.TestMessageSet.RegisterExtension(_TESTMESSAGESETEXTENSION2.extensions_by_name['message_set_extension']) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py new file mode 100644 index 0000000..b3eebad --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_mset_wire_format_pb2.py @@ -0,0 +1,104 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_mset_wire_format.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_mset_wire_format.proto', + package='proto2_wireformat_unittest', + syntax='proto2', + serialized_options=_b('H\001\370\001\001\252\002!Google.ProtocolBuffers.TestProtos'), + serialized_pb=_b('\n/google/protobuf/unittest_mset_wire_format.proto\x12\x1aproto2_wireformat_unittest\"\x1e\n\x0eTestMessageSet*\x08\x08\x04\x10\xff\xff\xff\xff\x07:\x02\x08\x01\"d\n!TestMessageSetWireFormatContainer\x12?\n\x0bmessage_set\x18\x01 \x01(\x0b\x32*.proto2_wireformat_unittest.TestMessageSetB)H\x01\xf8\x01\x01\xaa\x02!Google.ProtocolBuffers.TestProtos') +) + + + + +_TESTMESSAGESET = _descriptor.Descriptor( + name='TestMessageSet', + full_name='proto2_wireformat_unittest.TestMessageSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\010\001'), + is_extendable=True, + syntax='proto2', + extension_ranges=[(4, 2147483647), ], + oneofs=[ + ], + serialized_start=79, + serialized_end=109, +) + + +_TESTMESSAGESETWIREFORMATCONTAINER = _descriptor.Descriptor( + name='TestMessageSetWireFormatContainer', + full_name='proto2_wireformat_unittest.TestMessageSetWireFormatContainer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='message_set', full_name='proto2_wireformat_unittest.TestMessageSetWireFormatContainer.message_set', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=111, + serialized_end=211, +) + +_TESTMESSAGESETWIREFORMATCONTAINER.fields_by_name['message_set'].message_type = _TESTMESSAGESET +DESCRIPTOR.message_types_by_name['TestMessageSet'] = _TESTMESSAGESET +DESCRIPTOR.message_types_by_name['TestMessageSetWireFormatContainer'] = _TESTMESSAGESETWIREFORMATCONTAINER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessageSet = _reflection.GeneratedProtocolMessageType('TestMessageSet', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESET, + __module__ = 'google.protobuf.unittest_mset_wire_format_pb2' + # @@protoc_insertion_point(class_scope:proto2_wireformat_unittest.TestMessageSet) + )) +_sym_db.RegisterMessage(TestMessageSet) + +TestMessageSetWireFormatContainer = _reflection.GeneratedProtocolMessageType('TestMessageSetWireFormatContainer', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGESETWIREFORMATCONTAINER, + __module__ = 'google.protobuf.unittest_mset_wire_format_pb2' + # @@protoc_insertion_point(class_scope:proto2_wireformat_unittest.TestMessageSetWireFormatContainer) + )) +_sym_db.RegisterMessage(TestMessageSetWireFormatContainer) + + +DESCRIPTOR._options = None +_TESTMESSAGESET._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_import_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_import_pb2.py new file mode 100644 index 0000000..8bb9c3c --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_import_pb2.py @@ -0,0 +1,69 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_no_arena_import.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_no_arena_import.proto', + package='proto2_arena_unittest', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n.google/protobuf/unittest_no_arena_import.proto\x12\x15proto2_arena_unittest\"\'\n\x1aImportNoArenaNestedMessage\x12\t\n\x01\x64\x18\x01 \x01(\x05') +) + + + + +_IMPORTNOARENANESTEDMESSAGE = _descriptor.Descriptor( + name='ImportNoArenaNestedMessage', + full_name='proto2_arena_unittest.ImportNoArenaNestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='proto2_arena_unittest.ImportNoArenaNestedMessage.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=73, + serialized_end=112, +) + +DESCRIPTOR.message_types_by_name['ImportNoArenaNestedMessage'] = _IMPORTNOARENANESTEDMESSAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ImportNoArenaNestedMessage = _reflection.GeneratedProtocolMessageType('ImportNoArenaNestedMessage', (_message.Message,), dict( + DESCRIPTOR = _IMPORTNOARENANESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_import_pb2' + # @@protoc_insertion_point(class_scope:proto2_arena_unittest.ImportNoArenaNestedMessage) + )) +_sym_db.RegisterMessage(ImportNoArenaNestedMessage) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_pb2.py new file mode 100644 index 0000000..6fe69db --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_arena_pb2.py @@ -0,0 +1,911 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_no_arena.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_pb2 as google_dot_protobuf_dot_unittest__import__pb2 +try: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google_dot_protobuf_dot_unittest__import__public__pb2 +except AttributeError: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google.protobuf.unittest_import_public_pb2 +from google.protobuf import unittest_arena_pb2 as google_dot_protobuf_dot_unittest__arena__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_no_arena.proto', + package='protobuf_unittest_no_arena', + syntax='proto2', + serialized_options=_b('B\rUnittestProtoH\001\200\001\001\210\001\001\220\001\001\370\001\000\242\002\005NOARN'), + serialized_pb=_b('\n\'google/protobuf/unittest_no_arena.proto\x12\x1aprotobuf_unittest_no_arena\x1a%google/protobuf/unittest_import.proto\x1a$google/protobuf/unittest_arena.proto\"\xd0\x1a\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12M\n\roptionalgroup\x18\x10 \x01(\n26.protobuf_unittest_no_arena.TestAllTypes.OptionalGroup\x12W\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessage\x12L\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32*.protobuf_unittest_no_arena.ForeignMessage\x12H\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12Q\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32\x33.protobuf_unittest_no_arena.TestAllTypes.NestedEnum\x12\x46\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\'.protobuf_unittest_no_arena.ForeignEnum\x12\x42\n\x14optional_import_enum\x18\x17 \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12U\n\x1eoptional_public_import_message\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage\x12T\n\x10optional_message\x18\x1b \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12M\n\rrepeatedgroup\x18. \x03(\n26.protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup\x12W\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessage\x12L\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32*.protobuf_unittest_no_arena.ForeignMessage\x12H\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12Q\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32\x33.protobuf_unittest_no_arena.TestAllTypes.NestedEnum\x12\x46\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\'.protobuf_unittest_no_arena.ForeignEnum\x12\x42\n\x14repeated_import_enum\x18\x35 \x03(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12Y\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageB\x02(\x01\x12\x19\n\rdefault_int32\x18= \x01(\x05:\x02\x34\x31\x12\x19\n\rdefault_int64\x18> \x01(\x03:\x02\x34\x32\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint32\x18? \x01(\r:\x02\x34\x33\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint64\x18@ \x01(\x04:\x02\x34\x34\x12\x1b\n\x0e\x64\x65\x66\x61ult_sint32\x18\x41 \x01(\x11:\x03-45\x12\x1a\n\x0e\x64\x65\x66\x61ult_sint64\x18\x42 \x01(\x12:\x02\x34\x36\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed32\x18\x43 \x01(\x07:\x02\x34\x37\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed64\x18\x44 \x01(\x06:\x02\x34\x38\x12\x1c\n\x10\x64\x65\x66\x61ult_sfixed32\x18\x45 \x01(\x0f:\x02\x34\x39\x12\x1d\n\x10\x64\x65\x66\x61ult_sfixed64\x18\x46 \x01(\x10:\x03-50\x12\x1b\n\rdefault_float\x18G \x01(\x02:\x04\x35\x31.5\x12\x1d\n\x0e\x64\x65\x66\x61ult_double\x18H \x01(\x01:\x05\x35\x32\x30\x30\x30\x12\x1a\n\x0c\x64\x65\x66\x61ult_bool\x18I \x01(\x08:\x04true\x12\x1d\n\x0e\x64\x65\x66\x61ult_string\x18J \x01(\t:\x05hello\x12\x1c\n\rdefault_bytes\x18K \x01(\x0c:\x05world\x12U\n\x13\x64\x65\x66\x61ult_nested_enum\x18Q \x01(\x0e\x32\x33.protobuf_unittest_no_arena.TestAllTypes.NestedEnum:\x03\x42\x41R\x12R\n\x14\x64\x65\x66\x61ult_foreign_enum\x18R \x01(\x0e\x32\'.protobuf_unittest_no_arena.ForeignEnum:\x0b\x46OREIGN_BAR\x12M\n\x13\x64\x65\x66\x61ult_import_enum\x18S \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:\nIMPORT_BAR\x12%\n\x14\x64\x65\x66\x61ult_string_piece\x18T \x01(\t:\x03\x61\x62\x63\x42\x02\x08\x02\x12\x1d\n\x0c\x64\x65\x66\x61ult_cord\x18U \x01(\t:\x03\x31\x32\x33\x42\x02\x08\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12V\n\x14oneof_nested_message\x18p \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x12_\n\x19lazy_oneof_nested_message\x18s \x01(\x0b\x32\x36.protobuf_unittest_no_arena.TestAllTypes.NestedMessageB\x02(\x01H\x00\x1a\x1b\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\x1a\x1a\n\rRepeatedGroup\x12\t\n\x01\x61\x18/ \x01(\x05\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_field\"\x1b\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\"P\n\x12TestNoArenaMessage\x12:\n\rarena_message\x18\x01 \x01(\x0b\x32#.proto2_arena_unittest.ArenaMessage*@\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x04\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x05\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x06\x42%B\rUnittestProtoH\x01\x80\x01\x01\x88\x01\x01\x90\x01\x01\xf8\x01\x00\xa2\x02\x05NOARN') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__arena__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='protobuf_unittest_no_arena.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3670, + serialized_end=3734, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +FOREIGN_FOO = 4 +FOREIGN_BAR = 5 +FOREIGN_BAZ = 6 + + +_TESTALLTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest_no_arena.TestAllTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3485, + serialized_end=3542, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPES_NESTEDENUM) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest_no_arena.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest_no_arena.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3400, + serialized_end=3427, +) + +_TESTALLTYPES_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest_no_arena.TestAllTypes.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest_no_arena.TestAllTypes.OptionalGroup.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3429, + serialized_end=3455, +) + +_TESTALLTYPES_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup.a', index=0, + number=47, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3457, + serialized_end=3483, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='protobuf_unittest_no_arena.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest_no_arena.TestAllTypes.optionalgroup', index=15, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_nested_message', index=16, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_foreign_message', index=17, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_import_message', index=18, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_nested_enum', index=19, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_foreign_enum', index=20, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_import_enum', index=21, + number=23, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_string_piece', index=22, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_cord', index=23, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_public_import_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_public_import_message', index=24, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest_no_arena.TestAllTypes.optional_message', index=25, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_int32', index=26, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_int64', index=27, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_uint32', index=28, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_uint64', index=29, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sint32', index=30, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sint64', index=31, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_fixed32', index=32, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_fixed64', index=33, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sfixed32', index=34, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_sfixed64', index=35, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_float', index=36, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_double', index=37, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_bool', index=38, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_string', index=39, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_bytes', index=40, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest_no_arena.TestAllTypes.repeatedgroup', index=41, + number=46, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_nested_message', index=42, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_foreign_message', index=43, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_import_message', index=44, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_nested_enum', index=45, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_foreign_enum', index=46, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_import_enum', index=47, + number=53, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_string_piece', index=48, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_cord', index=49, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_lazy_message', full_name='protobuf_unittest_no_arena.TestAllTypes.repeated_lazy_message', index=50, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_int32', index=51, + number=61, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=41, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_int64', index=52, + number=62, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_uint32', index=53, + number=63, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=43, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_uint64', index=54, + number=64, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=44, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sint32', index=55, + number=65, type=17, cpp_type=1, label=1, + has_default_value=True, default_value=-45, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sint64', index=56, + number=66, type=18, cpp_type=2, label=1, + has_default_value=True, default_value=46, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_fixed32', index=57, + number=67, type=7, cpp_type=3, label=1, + has_default_value=True, default_value=47, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_fixed64', index=58, + number=68, type=6, cpp_type=4, label=1, + has_default_value=True, default_value=48, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed32', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sfixed32', index=59, + number=69, type=15, cpp_type=1, label=1, + has_default_value=True, default_value=49, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed64', full_name='protobuf_unittest_no_arena.TestAllTypes.default_sfixed64', index=60, + number=70, type=16, cpp_type=2, label=1, + has_default_value=True, default_value=-50, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_float', full_name='protobuf_unittest_no_arena.TestAllTypes.default_float', index=61, + number=71, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(51.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_double', full_name='protobuf_unittest_no_arena.TestAllTypes.default_double', index=62, + number=72, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(52000), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bool', full_name='protobuf_unittest_no_arena.TestAllTypes.default_bool', index=63, + number=73, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string', full_name='protobuf_unittest_no_arena.TestAllTypes.default_string', index=64, + number=74, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.default_bytes', index=65, + number=75, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("world"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_nested_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.default_nested_enum', index=66, + number=81, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_foreign_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.default_foreign_enum', index=67, + number=82, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_import_enum', full_name='protobuf_unittest_no_arena.TestAllTypes.default_import_enum', index=68, + number=83, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=8, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string_piece', full_name='protobuf_unittest_no_arena.TestAllTypes.default_string_piece', index=69, + number=84, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("abc").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_cord', full_name='protobuf_unittest_no_arena.TestAllTypes.default_cord', index=70, + number=85, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("123").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_uint32', index=71, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_nested_message', index=72, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_string', index=73, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_bytes', index=74, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lazy_oneof_nested_message', full_name='protobuf_unittest_no_arena.TestAllTypes.lazy_oneof_nested_message', index=75, + number=115, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, _TESTALLTYPES_OPTIONALGROUP, _TESTALLTYPES_REPEATEDGROUP, ], + enum_types=[ + _TESTALLTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_unittest_no_arena.TestAllTypes.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=149, + serialized_end=3557, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='protobuf_unittest_no_arena.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest_no_arena.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3559, + serialized_end=3586, +) + + +_TESTNOARENAMESSAGE = _descriptor.Descriptor( + name='TestNoArenaMessage', + full_name='protobuf_unittest_no_arena.TestNoArenaMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='arena_message', full_name='protobuf_unittest_no_arena.TestNoArenaMessage.arena_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3588, + serialized_end=3668, +) + +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES_OPTIONALGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES_REPEATEDGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['optionalgroup'].message_type = _TESTALLTYPES_OPTIONALGROUP +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['optional_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['optional_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['optional_public_import_message'].message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeatedgroup'].message_type = _TESTALLTYPES_REPEATEDGROUP +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['repeated_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['repeated_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['repeated_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['default_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['default_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['default_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['lazy_oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES_NESTEDENUM.containing_type = _TESTALLTYPES +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_uint32']) +_TESTALLTYPES.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_nested_message']) +_TESTALLTYPES.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_string']) +_TESTALLTYPES.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_bytes']) +_TESTALLTYPES.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['lazy_oneof_nested_message']) +_TESTALLTYPES.fields_by_name['lazy_oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTNOARENAMESSAGE.fields_by_name['arena_message'].message_type = google_dot_protobuf_dot_unittest__arena__pb2._ARENAMESSAGE +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestNoArenaMessage'] = _TESTNOARENAMESSAGE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes.NestedMessage) + )) + , + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes.OptionalGroup) + )) + , + + RepeatedGroup = _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_REPEATEDGROUP, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes.RepeatedGroup) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) +_sym_db.RegisterMessage(TestAllTypes.OptionalGroup) +_sym_db.RegisterMessage(TestAllTypes.RepeatedGroup) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestNoArenaMessage = _reflection.GeneratedProtocolMessageType('TestNoArenaMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTNOARENAMESSAGE, + __module__ = 'google.protobuf.unittest_no_arena_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest_no_arena.TestNoArenaMessage) + )) +_sym_db.RegisterMessage(TestNoArenaMessage) + + +DESCRIPTOR._options = None +_TESTALLTYPES.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPES.fields_by_name['optional_cord']._options = None +_TESTALLTYPES.fields_by_name['optional_message']._options = None +_TESTALLTYPES.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPES.fields_by_name['repeated_cord']._options = None +_TESTALLTYPES.fields_by_name['repeated_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['default_string_piece']._options = None +_TESTALLTYPES.fields_by_name['default_cord']._options = None +_TESTALLTYPES.fields_by_name['lazy_oneof_nested_message']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_generic_services_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_generic_services_pb2.py new file mode 100644 index 0000000..6746a67 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_no_generic_services_pb2.py @@ -0,0 +1,125 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_no_generic_services.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_no_generic_services.proto', + package='google.protobuf.no_generic_services_test', + syntax='proto2', + serialized_options=None, + serialized_pb=_b('\n2google/protobuf/unittest_no_generic_services.proto\x12(google.protobuf.no_generic_services_test\"#\n\x0bTestMessage\x12\t\n\x01\x61\x18\x01 \x01(\x05*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02*\x13\n\x08TestEnum\x12\x07\n\x03\x46OO\x10\x01\x32\x82\x01\n\x0bTestService\x12s\n\x03\x46oo\x12\x35.google.protobuf.no_generic_services_test.TestMessage\x1a\x35.google.protobuf.no_generic_services_test.TestMessage:N\n\x0etest_extension\x12\x35.google.protobuf.no_generic_services_test.TestMessage\x18\xe8\x07 \x01(\x05') +) + +_TESTENUM = _descriptor.EnumDescriptor( + name='TestEnum', + full_name='google.protobuf.no_generic_services_test.TestEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=133, + serialized_end=152, +) +_sym_db.RegisterEnumDescriptor(_TESTENUM) + +TestEnum = enum_type_wrapper.EnumTypeWrapper(_TESTENUM) +FOO = 1 + +TEST_EXTENSION_FIELD_NUMBER = 1000 +test_extension = _descriptor.FieldDescriptor( + name='test_extension', full_name='google.protobuf.no_generic_services_test.test_extension', index=0, + number=1000, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_TESTMESSAGE = _descriptor.Descriptor( + name='TestMessage', + full_name='google.protobuf.no_generic_services_test.TestMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='google.protobuf.no_generic_services_test.TestMessage.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=96, + serialized_end=131, +) + +DESCRIPTOR.message_types_by_name['TestMessage'] = _TESTMESSAGE +DESCRIPTOR.enum_types_by_name['TestEnum'] = _TESTENUM +DESCRIPTOR.extensions_by_name['test_extension'] = test_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestMessage = _reflection.GeneratedProtocolMessageType('TestMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGE, + __module__ = 'google.protobuf.unittest_no_generic_services_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.no_generic_services_test.TestMessage) + )) +_sym_db.RegisterMessage(TestMessage) + +TestMessage.RegisterExtension(test_extension) + + +_TESTSERVICE = _descriptor.ServiceDescriptor( + name='TestService', + full_name='google.protobuf.no_generic_services_test.TestService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=155, + serialized_end=285, + methods=[ + _descriptor.MethodDescriptor( + name='Foo', + full_name='google.protobuf.no_generic_services_test.TestService.Foo', + index=0, + containing_service=None, + input_type=_TESTMESSAGE, + output_type=_TESTMESSAGE, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_TESTSERVICE) + +DESCRIPTOR.services_by_name['TestService'] = _TESTSERVICE + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_pb2.py new file mode 100644 index 0000000..1a4a7db --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_pb2.py @@ -0,0 +1,7082 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import service as _service +from google.protobuf import service_reflection +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_pb2 as google_dot_protobuf_dot_unittest__import__pb2 +try: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google_dot_protobuf_dot_unittest__import__public__pb2 +except AttributeError: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google.protobuf.unittest_import_public_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=_b('B\rUnittestProtoH\001\200\001\001\210\001\001\220\001\001\370\001\001'), + serialized_pb=_b('\n\x1egoogle/protobuf/unittest.proto\x12\x11protobuf_unittest\x1a%google/protobuf/unittest_import.proto\"\xed\x18\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12\x44\n\roptionalgroup\x18\x10 \x01(\n2-.protobuf_unittest.TestAllTypes.OptionalGroup\x12N\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage\x12\x43\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12H\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12H\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum\x12=\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x42\n\x14optional_import_enum\x18\x17 \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12U\n\x1eoptional_public_import_message\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage\x12P\n\x15optional_lazy_message\x18\x1b \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12\x44\n\rrepeatedgroup\x18. \x03(\n2-.protobuf_unittest.TestAllTypes.RepeatedGroup\x12N\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage\x12\x43\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32!.protobuf_unittest.ForeignMessage\x12H\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12H\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum\x12=\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x42\n\x14repeated_import_enum\x18\x35 \x03(\x0e\x32$.protobuf_unittest_import.ImportEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12P\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12\x19\n\rdefault_int32\x18= \x01(\x05:\x02\x34\x31\x12\x19\n\rdefault_int64\x18> \x01(\x03:\x02\x34\x32\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint32\x18? \x01(\r:\x02\x34\x33\x12\x1a\n\x0e\x64\x65\x66\x61ult_uint64\x18@ \x01(\x04:\x02\x34\x34\x12\x1b\n\x0e\x64\x65\x66\x61ult_sint32\x18\x41 \x01(\x11:\x03-45\x12\x1a\n\x0e\x64\x65\x66\x61ult_sint64\x18\x42 \x01(\x12:\x02\x34\x36\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed32\x18\x43 \x01(\x07:\x02\x34\x37\x12\x1b\n\x0f\x64\x65\x66\x61ult_fixed64\x18\x44 \x01(\x06:\x02\x34\x38\x12\x1c\n\x10\x64\x65\x66\x61ult_sfixed32\x18\x45 \x01(\x0f:\x02\x34\x39\x12\x1d\n\x10\x64\x65\x66\x61ult_sfixed64\x18\x46 \x01(\x10:\x03-50\x12\x1b\n\rdefault_float\x18G \x01(\x02:\x04\x35\x31.5\x12\x1d\n\x0e\x64\x65\x66\x61ult_double\x18H \x01(\x01:\x05\x35\x32\x30\x30\x30\x12\x1a\n\x0c\x64\x65\x66\x61ult_bool\x18I \x01(\x08:\x04true\x12\x1d\n\x0e\x64\x65\x66\x61ult_string\x18J \x01(\t:\x05hello\x12\x1c\n\rdefault_bytes\x18K \x01(\x0c:\x05world\x12L\n\x13\x64\x65\x66\x61ult_nested_enum\x18Q \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:\x03\x42\x41R\x12I\n\x14\x64\x65\x66\x61ult_foreign_enum\x18R \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:\x0b\x46OREIGN_BAR\x12M\n\x13\x64\x65\x66\x61ult_import_enum\x18S \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:\nIMPORT_BAR\x12%\n\x14\x64\x65\x66\x61ult_string_piece\x18T \x01(\t:\x03\x61\x62\x63\x42\x02\x08\x02\x12\x1d\n\x0c\x64\x65\x66\x61ult_cord\x18U \x01(\t:\x03\x31\x32\x33\x42\x02\x08\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12M\n\x14oneof_nested_message\x18p \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x1a\x1b\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\x1a\x1a\n\rRepeatedGroup\x12\t\n\x01\x61\x18/ \x01(\x05\"9\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_field\"\xbb\x01\n\x12NestedTestAllTypes\x12\x34\n\x05\x63hild\x18\x01 \x01(\x0b\x32%.protobuf_unittest.NestedTestAllTypes\x12\x30\n\x07payload\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12=\n\x0erepeated_child\x18\x03 \x03(\x0b\x32%.protobuf_unittest.NestedTestAllTypes\"m\n\x14TestDeprecatedFields\x12\x1c\n\x10\x64\x65precated_int32\x18\x01 \x01(\x05\x42\x02\x18\x01\x12\'\n\x19\x64\x65precated_int32_in_oneof\x18\x02 \x01(\x05\x42\x02\x18\x01H\x00\x42\x0e\n\x0coneof_fields\"\x1b\n\x15TestDeprecatedMessage:\x02\x18\x01\"&\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\x12\t\n\x01\x64\x18\x02 \x01(\x05\"0\n\x12TestReservedFieldsJ\x04\x08\x02\x10\x03J\x04\x08\x0f\x10\x10J\x04\x08\t\x10\x0cR\x03\x62\x61rR\x03\x62\x61z\"\x1d\n\x11TestAllExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"$\n\x17OptionalGroup_extension\x12\t\n\x01\x61\x18\x11 \x01(\x05\"$\n\x17RepeatedGroup_extension\x12\t\n\x01\x61\x18/ \x01(\x05\"\xa9\x01\n\tTestGroup\x12\x41\n\roptionalgroup\x18\x10 \x01(\n2*.protobuf_unittest.TestGroup.OptionalGroup\x12=\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x1a\x1a\n\rOptionalGroup\x12\t\n\x01\x61\x18\x11 \x01(\x05\"\x1e\n\x12TestGroupExtension*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"\xb7\x03\n\x13TestNestedExtension\x1a$\n\x17OptionalGroup_extension\x12\t\n\x01\x61\x18\x11 \x01(\x05\x32\x39\n\x04test\x12$.protobuf_unittest.TestAllExtensions\x18\xea\x07 \x01(\t:\x04test2F\n\x17nested_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18\xeb\x07 \x01(\t2\x86\x01\n\x17optionalgroup_extension\x12%.protobuf_unittest.TestGroupExtension\x18\x10 \x01(\n2>.protobuf_unittest.TestNestedExtension.OptionalGroup_extension2n\n\x1foptional_foreign_enum_extension\x12%.protobuf_unittest.TestGroupExtension\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\"\xd5\x05\n\x0cTestRequired\x12\t\n\x01\x61\x18\x01 \x02(\x05\x12\x0e\n\x06\x64ummy2\x18\x02 \x01(\x05\x12\t\n\x01\x62\x18\x03 \x02(\x05\x12\x0e\n\x06\x64ummy4\x18\x04 \x01(\x05\x12\x0e\n\x06\x64ummy5\x18\x05 \x01(\x05\x12\x0e\n\x06\x64ummy6\x18\x06 \x01(\x05\x12\x0e\n\x06\x64ummy7\x18\x07 \x01(\x05\x12\x0e\n\x06\x64ummy8\x18\x08 \x01(\x05\x12\x0e\n\x06\x64ummy9\x18\t \x01(\x05\x12\x0f\n\x07\x64ummy10\x18\n \x01(\x05\x12\x0f\n\x07\x64ummy11\x18\x0b \x01(\x05\x12\x0f\n\x07\x64ummy12\x18\x0c \x01(\x05\x12\x0f\n\x07\x64ummy13\x18\r \x01(\x05\x12\x0f\n\x07\x64ummy14\x18\x0e \x01(\x05\x12\x0f\n\x07\x64ummy15\x18\x0f \x01(\x05\x12\x0f\n\x07\x64ummy16\x18\x10 \x01(\x05\x12\x0f\n\x07\x64ummy17\x18\x11 \x01(\x05\x12\x0f\n\x07\x64ummy18\x18\x12 \x01(\x05\x12\x0f\n\x07\x64ummy19\x18\x13 \x01(\x05\x12\x0f\n\x07\x64ummy20\x18\x14 \x01(\x05\x12\x0f\n\x07\x64ummy21\x18\x15 \x01(\x05\x12\x0f\n\x07\x64ummy22\x18\x16 \x01(\x05\x12\x0f\n\x07\x64ummy23\x18\x17 \x01(\x05\x12\x0f\n\x07\x64ummy24\x18\x18 \x01(\x05\x12\x0f\n\x07\x64ummy25\x18\x19 \x01(\x05\x12\x0f\n\x07\x64ummy26\x18\x1a \x01(\x05\x12\x0f\n\x07\x64ummy27\x18\x1b \x01(\x05\x12\x0f\n\x07\x64ummy28\x18\x1c \x01(\x05\x12\x0f\n\x07\x64ummy29\x18\x1d \x01(\x05\x12\x0f\n\x07\x64ummy30\x18\x1e \x01(\x05\x12\x0f\n\x07\x64ummy31\x18\x1f \x01(\x05\x12\x0f\n\x07\x64ummy32\x18 \x01(\x05\x12\t\n\x01\x63\x18! \x02(\x05\x32V\n\x06single\x12$.protobuf_unittest.TestAllExtensions\x18\xe8\x07 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired2U\n\x05multi\x12$.protobuf_unittest.TestAllExtensions\x18\xe9\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestRequired\"\x9a\x01\n\x13TestRequiredForeign\x12\x39\n\x10optional_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\x39\n\x10repeated_message\x18\x02 \x03(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\r\n\x05\x64ummy\x18\x03 \x01(\x05\"\xc6\x01\n\x13TestRequiredMessage\x12\x39\n\x10optional_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\x39\n\x10repeated_message\x18\x02 \x03(\x0b\x32\x1f.protobuf_unittest.TestRequired\x12\x39\n\x10required_message\x18\x03 \x02(\x0b\x32\x1f.protobuf_unittest.TestRequired\"Z\n\x11TestForeignNested\x12\x45\n\x0e\x66oreign_nested\x18\x01 \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage\"\x12\n\x10TestEmptyMessage\"*\n\x1eTestEmptyMessageWithExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"7\n\x1bTestMultipleExtensionRanges*\x04\x08*\x10+*\x06\x08\xaf \x10\x94!*\n\x08\x80\x80\x04\x10\x80\x80\x80\x80\x02\"4\n\x18TestReallyLargeTagNumber\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\r\n\x02\x62\x62\x18\xff\xff\xff\x7f \x01(\x05\"U\n\x14TestRecursiveMessage\x12\x32\n\x01\x61\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestRecursiveMessage\x12\t\n\x01i\x18\x02 \x01(\x05\"\xe1\x02\n\x14TestMutualRecursionA\x12\x33\n\x02\x62\x62\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestMutualRecursionB\x12\x42\n\x08subgroup\x18\x02 \x01(\n20.protobuf_unittest.TestMutualRecursionA.SubGroup\x1a@\n\nSubMessage\x12\x32\n\x01\x62\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestMutualRecursionB\x1a\x8d\x01\n\x08SubGroup\x12G\n\x0bsub_message\x18\x03 \x01(\x0b\x32\x32.protobuf_unittest.TestMutualRecursionA.SubMessage\x12\x38\n\x0fnot_in_this_scc\x18\x04 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\"b\n\x14TestMutualRecursionB\x12\x32\n\x01\x61\x18\x01 \x01(\x0b\x32\'.protobuf_unittest.TestMutualRecursionA\x12\x16\n\x0eoptional_int32\x18\x02 \x01(\x05\"\xca\x01\n\x11TestIsInitialized\x12\x44\n\x0bsub_message\x18\x01 \x01(\x0b\x32/.protobuf_unittest.TestIsInitialized.SubMessage\x1ao\n\nSubMessage\x12J\n\x08subgroup\x18\x01 \x01(\n28.protobuf_unittest.TestIsInitialized.SubMessage.SubGroup\x1a\x15\n\x08SubGroup\x12\t\n\x01i\x18\x02 \x02(\x05\"\xb3\x01\n\x12TestDupFieldNumber\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\x36\n\x03\x66oo\x18\x02 \x01(\n2).protobuf_unittest.TestDupFieldNumber.Foo\x12\x36\n\x03\x62\x61r\x18\x03 \x01(\n2).protobuf_unittest.TestDupFieldNumber.Bar\x1a\x10\n\x03\x46oo\x12\t\n\x01\x61\x18\x01 \x01(\x05\x1a\x10\n\x03\x42\x61r\x12\t\n\x01\x61\x18\x01 \x01(\x05\"L\n\x10TestEagerMessage\x12\x38\n\x0bsub_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesB\x02(\x00\"K\n\x0fTestLazyMessage\x12\x38\n\x0bsub_message\x18\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesB\x02(\x01\"\x80\x02\n\x18TestNestedMessageHasBits\x12Z\n\x17optional_nested_message\x18\x01 \x01(\x0b\x32\x39.protobuf_unittest.TestNestedMessageHasBits.NestedMessage\x1a\x87\x01\n\rNestedMessage\x12$\n\x1cnestedmessage_repeated_int32\x18\x01 \x03(\x05\x12P\n%nestedmessage_repeated_foreignmessage\x18\x02 \x03(\x0b\x32!.protobuf_unittest.ForeignMessage\"\xe5\x03\n\x17TestCamelCaseFieldNames\x12\x16\n\x0ePrimitiveField\x18\x01 \x01(\x05\x12\x13\n\x0bStringField\x18\x02 \x01(\t\x12\x31\n\tEnumField\x18\x03 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x37\n\x0cMessageField\x18\x04 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12\x1c\n\x10StringPieceField\x18\x05 \x01(\tB\x02\x08\x02\x12\x15\n\tCordField\x18\x06 \x01(\tB\x02\x08\x01\x12\x1e\n\x16RepeatedPrimitiveField\x18\x07 \x03(\x05\x12\x1b\n\x13RepeatedStringField\x18\x08 \x03(\t\x12\x39\n\x11RepeatedEnumField\x18\t \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12?\n\x14RepeatedMessageField\x18\n \x03(\x0b\x32!.protobuf_unittest.ForeignMessage\x12$\n\x18RepeatedStringPieceField\x18\x0b \x03(\tB\x02\x08\x02\x12\x1d\n\x11RepeatedCordField\x18\x0c \x03(\tB\x02\x08\x01\"\xd5\x01\n\x12TestFieldOrderings\x12\x11\n\tmy_string\x18\x0b \x01(\t\x12\x0e\n\x06my_int\x18\x01 \x01(\x03\x12\x10\n\x08my_float\x18\x65 \x01(\x02\x12U\n\x17optional_nested_message\x18\xc8\x01 \x01(\x0b\x32\x33.protobuf_unittest.TestFieldOrderings.NestedMessage\x1a\'\n\rNestedMessage\x12\n\n\x02oo\x18\x02 \x01(\x03\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05*\x04\x08\x02\x10\x0b*\x04\x08\x0c\x10\x65\"\x9c\x01\n\x17TestExtensionOrderings1\x12\x11\n\tmy_string\x18\x01 \x01(\t2n\n\x13test_ext_orderings1\x12%.protobuf_unittest.TestFieldOrderings\x18\r \x01(\x0b\x32*.protobuf_unittest.TestExtensionOrderings1\"\xd4\x02\n\x17TestExtensionOrderings2\x12\x11\n\tmy_string\x18\x01 \x01(\t\x1a\xb5\x01\n\x17TestExtensionOrderings3\x12\x11\n\tmy_string\x18\x01 \x01(\t2\x86\x01\n\x13test_ext_orderings3\x12%.protobuf_unittest.TestFieldOrderings\x18\x0e \x01(\x0b\x32\x42.protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings32n\n\x13test_ext_orderings2\x12%.protobuf_unittest.TestFieldOrderings\x18\x0c \x01(\x0b\x32*.protobuf_unittest.TestExtensionOrderings2\"\xb6\x07\n\x18TestExtremeDefaultValues\x12?\n\rescaped_bytes\x18\x01 \x01(\x0c:(\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\\376\x12 \n\x0clarge_uint32\x18\x02 \x01(\r:\n4294967295\x12*\n\x0clarge_uint64\x18\x03 \x01(\x04:\x14\x31\x38\x34\x34\x36\x37\x34\x34\x30\x37\x33\x37\x30\x39\x35\x35\x31\x36\x31\x35\x12 \n\x0bsmall_int32\x18\x04 \x01(\x05:\x0b-2147483647\x12)\n\x0bsmall_int64\x18\x05 \x01(\x03:\x14-9223372036854775807\x12\'\n\x12really_small_int32\x18\x15 \x01(\x05:\x0b-2147483648\x12\x30\n\x12really_small_int64\x18\x16 \x01(\x03:\x14-9223372036854775808\x12\x18\n\x0butf8_string\x18\x06 \x01(\t:\x03\xe1\x88\xb4\x12\x15\n\nzero_float\x18\x07 \x01(\x02:\x01\x30\x12\x14\n\tone_float\x18\x08 \x01(\x02:\x01\x31\x12\x18\n\x0bsmall_float\x18\t \x01(\x02:\x03\x31.5\x12\x1e\n\x12negative_one_float\x18\n \x01(\x02:\x02-1\x12\x1c\n\x0enegative_float\x18\x0b \x01(\x02:\x04-1.5\x12\x1a\n\x0blarge_float\x18\x0c \x01(\x02:\x05\x32\x65+08\x12$\n\x14small_negative_float\x18\r \x01(\x02:\x06-8e-28\x12\x17\n\ninf_double\x18\x0e \x01(\x01:\x03inf\x12\x1c\n\x0eneg_inf_double\x18\x0f \x01(\x01:\x04-inf\x12\x17\n\nnan_double\x18\x10 \x01(\x01:\x03nan\x12\x16\n\tinf_float\x18\x11 \x01(\x02:\x03inf\x12\x1b\n\rneg_inf_float\x18\x12 \x01(\x02:\x04-inf\x12\x16\n\tnan_float\x18\x13 \x01(\x02:\x03nan\x12+\n\x0c\x63pp_trigraph\x18\x14 \x01(\t:\x15? ? ?? ?? ??? ??/ ??-\x12 \n\x10string_with_zero\x18\x17 \x01(\t:\x06hel\x00lo\x12\"\n\x0f\x62ytes_with_zero\x18\x18 \x01(\x0c:\twor\\000ld\x12(\n\x16string_piece_with_zero\x18\x19 \x01(\t:\x04\x61\x62\x00\x63\x42\x02\x08\x02\x12 \n\x0e\x63ord_with_zero\x18\x1a \x01(\t:\x04\x31\x32\x00\x33\x42\x02\x08\x01\x12&\n\x12replacement_string\x18\x1b \x01(\t:\n${unknown}\"K\n\x11SparseEnumMessage\x12\x36\n\x0bsparse_enum\x18\x01 \x01(\x0e\x32!.protobuf_unittest.TestSparseEnum\"\x19\n\tOneString\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"\x1a\n\nMoreString\x12\x0c\n\x04\x64\x61ta\x18\x01 \x03(\t\"\x18\n\x08OneBytes\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\"\x19\n\tMoreBytes\x12\x0c\n\x04\x64\x61ta\x18\x01 \x03(\x0c\"\x1c\n\x0cInt32Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x05\"\x1d\n\rUint32Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\r\"\x1c\n\x0cInt64Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x03\"\x1d\n\rUint64Message\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x04\"\x1b\n\x0b\x42oolMessage\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x08\"\xd0\x01\n\tTestOneof\x12\x11\n\x07\x66oo_int\x18\x01 \x01(\x05H\x00\x12\x14\n\nfoo_string\x18\x02 \x01(\tH\x00\x12\x36\n\x0b\x66oo_message\x18\x03 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesH\x00\x12\x39\n\x08\x66oogroup\x18\x04 \x01(\n2%.protobuf_unittest.TestOneof.FooGroupH\x00\x1a \n\x08\x46ooGroup\x12\t\n\x01\x61\x18\x05 \x01(\x05\x12\t\n\x01\x62\x18\x06 \x01(\tB\x05\n\x03\x66oo\"\xe7\x01\n\x1cTestOneofBackwardsCompatible\x12\x0f\n\x07\x66oo_int\x18\x01 \x01(\x05\x12\x12\n\nfoo_string\x18\x02 \x01(\t\x12\x34\n\x0b\x66oo_message\x18\x03 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12J\n\x08\x66oogroup\x18\x04 \x01(\n28.protobuf_unittest.TestOneofBackwardsCompatible.FooGroup\x1a \n\x08\x46ooGroup\x12\t\n\x01\x61\x18\x05 \x01(\x05\x12\t\n\x01\x62\x18\x06 \x01(\t\"\x9e\x06\n\nTestOneof2\x12\x11\n\x07\x66oo_int\x18\x01 \x01(\x05H\x00\x12\x14\n\nfoo_string\x18\x02 \x01(\tH\x00\x12\x16\n\x08\x66oo_cord\x18\x03 \x01(\tB\x02\x08\x01H\x00\x12\x1e\n\x10\x66oo_string_piece\x18\x04 \x01(\tB\x02\x08\x02H\x00\x12\x13\n\tfoo_bytes\x18\x05 \x01(\x0cH\x00\x12<\n\x08\x66oo_enum\x18\x06 \x01(\x0e\x32(.protobuf_unittest.TestOneof2.NestedEnumH\x00\x12\x42\n\x0b\x66oo_message\x18\x07 \x01(\x0b\x32+.protobuf_unittest.TestOneof2.NestedMessageH\x00\x12:\n\x08\x66oogroup\x18\x08 \x01(\n2&.protobuf_unittest.TestOneof2.FooGroupH\x00\x12K\n\x10\x66oo_lazy_message\x18\x0b \x01(\x0b\x32+.protobuf_unittest.TestOneof2.NestedMessageB\x02(\x01H\x00\x12\x14\n\x07\x62\x61r_int\x18\x0c \x01(\x05:\x01\x35H\x01\x12\x1c\n\nbar_string\x18\r \x01(\t:\x06STRINGH\x01\x12\x1c\n\x08\x62\x61r_cord\x18\x0e \x01(\t:\x04\x43ORDB\x02\x08\x01H\x01\x12&\n\x10\x62\x61r_string_piece\x18\x0f \x01(\t:\x06SPIECEB\x02\x08\x02H\x01\x12\x1a\n\tbar_bytes\x18\x10 \x01(\x0c:\x05\x42YTESH\x01\x12\x41\n\x08\x62\x61r_enum\x18\x11 \x01(\x0e\x32(.protobuf_unittest.TestOneof2.NestedEnum:\x03\x42\x41RH\x01\x12\x0f\n\x07\x62\x61z_int\x18\x12 \x01(\x05\x12\x17\n\nbaz_string\x18\x13 \x01(\t:\x03\x42\x41Z\x1a \n\x08\x46ooGroup\x12\t\n\x01\x61\x18\t \x01(\x05\x12\t\n\x01\x62\x18\n \x01(\t\x1a\x33\n\rNestedMessage\x12\x0f\n\x07qux_int\x18\x01 \x01(\x03\x12\x11\n\tcorge_int\x18\x02 \x03(\x05\"\'\n\nNestedEnum\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x42\x05\n\x03\x66ooB\x05\n\x03\x62\x61r\"\xb8\x01\n\x11TestRequiredOneof\x12\x11\n\x07\x66oo_int\x18\x01 \x01(\x05H\x00\x12\x14\n\nfoo_string\x18\x02 \x01(\tH\x00\x12I\n\x0b\x66oo_message\x18\x03 \x01(\x0b\x32\x32.protobuf_unittest.TestRequiredOneof.NestedMessageH\x00\x1a(\n\rNestedMessage\x12\x17\n\x0frequired_double\x18\x01 \x02(\x01\x42\x05\n\x03\x66oo\"\xaa\x03\n\x0fTestPackedTypes\x12\x18\n\x0cpacked_int32\x18Z \x03(\x05\x42\x02\x10\x01\x12\x18\n\x0cpacked_int64\x18[ \x03(\x03\x42\x02\x10\x01\x12\x19\n\rpacked_uint32\x18\\ \x03(\rB\x02\x10\x01\x12\x19\n\rpacked_uint64\x18] \x03(\x04\x42\x02\x10\x01\x12\x19\n\rpacked_sint32\x18^ \x03(\x11\x42\x02\x10\x01\x12\x19\n\rpacked_sint64\x18_ \x03(\x12\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed32\x18` \x03(\x07\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed64\x18\x61 \x03(\x06\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed32\x18\x62 \x03(\x0f\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed64\x18\x63 \x03(\x10\x42\x02\x10\x01\x12\x18\n\x0cpacked_float\x18\x64 \x03(\x02\x42\x02\x10\x01\x12\x19\n\rpacked_double\x18\x65 \x03(\x01\x42\x02\x10\x01\x12\x17\n\x0bpacked_bool\x18\x66 \x03(\x08\x42\x02\x10\x01\x12\x37\n\x0bpacked_enum\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x01\"\xc8\x03\n\x11TestUnpackedTypes\x12\x1a\n\x0eunpacked_int32\x18Z \x03(\x05\x42\x02\x10\x00\x12\x1a\n\x0eunpacked_int64\x18[ \x03(\x03\x42\x02\x10\x00\x12\x1b\n\x0funpacked_uint32\x18\\ \x03(\rB\x02\x10\x00\x12\x1b\n\x0funpacked_uint64\x18] \x03(\x04\x42\x02\x10\x00\x12\x1b\n\x0funpacked_sint32\x18^ \x03(\x11\x42\x02\x10\x00\x12\x1b\n\x0funpacked_sint64\x18_ \x03(\x12\x42\x02\x10\x00\x12\x1c\n\x10unpacked_fixed32\x18` \x03(\x07\x42\x02\x10\x00\x12\x1c\n\x10unpacked_fixed64\x18\x61 \x03(\x06\x42\x02\x10\x00\x12\x1d\n\x11unpacked_sfixed32\x18\x62 \x03(\x0f\x42\x02\x10\x00\x12\x1d\n\x11unpacked_sfixed64\x18\x63 \x03(\x10\x42\x02\x10\x00\x12\x1a\n\x0eunpacked_float\x18\x64 \x03(\x02\x42\x02\x10\x00\x12\x1b\n\x0funpacked_double\x18\x65 \x03(\x01\x42\x02\x10\x00\x12\x19\n\runpacked_bool\x18\x66 \x03(\x08\x42\x02\x10\x00\x12\x39\n\runpacked_enum\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x00\" \n\x14TestPackedExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"\"\n\x16TestUnpackedExtensions*\x08\x08\x01\x10\x80\x80\x80\x80\x02\"\x99\x04\n\x15TestDynamicExtensions\x12\x19\n\x10scalar_extension\x18\xd0\x0f \x01(\x07\x12\x37\n\x0e\x65num_extension\x18\xd1\x0f \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12Y\n\x16\x64ynamic_enum_extension\x18\xd2\x0f \x01(\x0e\x32\x38.protobuf_unittest.TestDynamicExtensions.DynamicEnumType\x12=\n\x11message_extension\x18\xd3\x0f \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12_\n\x19\x64ynamic_message_extension\x18\xd4\x0f \x01(\x0b\x32;.protobuf_unittest.TestDynamicExtensions.DynamicMessageType\x12\x1b\n\x12repeated_extension\x18\xd5\x0f \x03(\t\x12\x1d\n\x10packed_extension\x18\xd6\x0f \x03(\x11\x42\x02\x10\x01\x1a,\n\x12\x44ynamicMessageType\x12\x16\n\rdynamic_field\x18\xb4\x10 \x01(\x05\"G\n\x0f\x44ynamicEnumType\x12\x10\n\x0b\x44YNAMIC_FOO\x10\x98\x11\x12\x10\n\x0b\x44YNAMIC_BAR\x10\x99\x11\x12\x10\n\x0b\x44YNAMIC_BAZ\x10\x9a\x11\"\xc0\x01\n#TestRepeatedScalarDifferentTagSizes\x12\x18\n\x10repeated_fixed32\x18\x0c \x03(\x07\x12\x16\n\x0erepeated_int32\x18\r \x03(\x05\x12\x19\n\x10repeated_fixed64\x18\xfe\x0f \x03(\x06\x12\x17\n\x0erepeated_int64\x18\xff\x0f \x03(\x03\x12\x18\n\x0erepeated_float\x18\xfe\xff\x0f \x03(\x02\x12\x19\n\x0frepeated_uint64\x18\xff\xff\x0f \x03(\x04\"\xf7\t\n\x10TestParsingMerge\x12;\n\x12required_all_types\x18\x01 \x02(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12;\n\x12optional_all_types\x18\x02 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12;\n\x12repeated_all_types\x18\x03 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12H\n\roptionalgroup\x18\n \x01(\n21.protobuf_unittest.TestParsingMerge.OptionalGroup\x12H\n\rrepeatedgroup\x18\x14 \x03(\n21.protobuf_unittest.TestParsingMerge.RepeatedGroup\x1a\xaa\x04\n\x17RepeatedFieldsGenerator\x12/\n\x06\x66ield1\x18\x01 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12/\n\x06\x66ield2\x18\x02 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12/\n\x06\x66ield3\x18\x03 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12R\n\x06group1\x18\n \x03(\n2B.protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1\x12R\n\x06group2\x18\x14 \x03(\n2B.protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2\x12.\n\x04\x65xt1\x18\xe8\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x12.\n\x04\x65xt2\x18\xe9\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1a\x39\n\x06Group1\x12/\n\x06\x66ield1\x18\x0b \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1a\x39\n\x06Group2\x12/\n\x06\x66ield1\x18\x15 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1aR\n\rOptionalGroup\x12\x41\n\x18optional_group_all_types\x18\x0b \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\x1aR\n\rRepeatedGroup\x12\x41\n\x18repeated_group_all_types\x18\x15 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\x32[\n\x0coptional_ext\x12#.protobuf_unittest.TestParsingMerge\x18\xe8\x07 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes2[\n\x0crepeated_ext\x12#.protobuf_unittest.TestParsingMerge\x18\xe9\x07 \x03(\x0b\x32\x1f.protobuf_unittest.TestAllTypes\"D\n\x1bTestCommentInjectionMessage\x12%\n\x01\x61\x18\x01 \x01(\t:\x1a*/ <- Neither should this.\"\x0c\n\nFooRequest\"\r\n\x0b\x46ooResponse\"\x12\n\x10\x46ooClientMessage\"\x12\n\x10\x46ooServerMessage\"\x0c\n\nBarRequest\"\r\n\x0b\x42\x61rResponse\"\x92\x01\n\x0cTestJsonName\x12\x13\n\x0b\x66ield_name1\x18\x01 \x01(\x05\x12\x12\n\nfieldName2\x18\x02 \x01(\x05\x12\x12\n\nFieldName3\x18\x03 \x01(\x05\x12\x14\n\x0c_field_name4\x18\x04 \x01(\x05\x12\x13\n\x0b\x46IELD_NAME5\x18\x05 \x01(\x05\x12\x1a\n\x0b\x66ield_name6\x18\x06 \x01(\x05R\x05@type\"\xfd\x05\n\x14TestHugeFieldNumbers\x12\x1a\n\x0eoptional_int32\x18\xf0\xf8\xff\xff\x01 \x01(\x05\x12\x14\n\x08\x66ixed_32\x18\xf1\xf8\xff\xff\x01 \x01(\x05\x12\x1e\n\x0erepeated_int32\x18\xf2\xf8\xff\xff\x01 \x03(\x05\x42\x02\x10\x00\x12\x1c\n\x0cpacked_int32\x18\xf3\xf8\xff\xff\x01 \x03(\x05\x42\x02\x10\x01\x12\x39\n\roptional_enum\x18\xf4\xf8\xff\xff\x01 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum\x12\x1b\n\x0foptional_string\x18\xf5\xf8\xff\xff\x01 \x01(\t\x12\x1a\n\x0eoptional_bytes\x18\xf6\xf8\xff\xff\x01 \x01(\x0c\x12?\n\x10optional_message\x18\xf7\xf8\xff\xff\x01 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage\x12P\n\roptionalgroup\x18\xf8\xf8\xff\xff\x01 \x01(\n25.protobuf_unittest.TestHugeFieldNumbers.OptionalGroup\x12[\n\x11string_string_map\x18\xfa\xf8\xff\xff\x01 \x03(\x0b\x32<.protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry\x12\x1a\n\x0coneof_uint32\x18\xfb\xf8\xff\xff\x01 \x01(\rH\x00\x12\x43\n\x14oneof_test_all_types\x18\xfc\xf8\xff\xff\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypesH\x00\x12\x1a\n\x0coneof_string\x18\xfd\xf8\xff\xff\x01 \x01(\tH\x00\x12\x19\n\x0boneof_bytes\x18\xfe\xf8\xff\xff\x01 \x01(\x0cH\x00\x1a$\n\rOptionalGroup\x12\x13\n\x07group_a\x18\xf9\xf8\xff\xff\x01 \x01(\x05\x1a\x36\n\x14StringStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01*\x0c\x08\xe0\xaa\xff\xff\x01\x10\xf0\xf8\xff\xff\x01\x42\r\n\x0boneof_field\"\xb1\x01\n\x18TestExtensionInsideTable\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\x05\x12\x0e\n\x06\x66ield3\x18\x03 \x01(\x05\x12\x0e\n\x06\x66ield4\x18\x04 \x01(\x05\x12\x0e\n\x06\x66ield6\x18\x06 \x01(\x05\x12\x0e\n\x06\x66ield7\x18\x07 \x01(\x05\x12\x0e\n\x06\x66ield8\x18\x08 \x01(\x05\x12\x0e\n\x06\x66ield9\x18\t \x01(\x05\x12\x0f\n\x07\x66ield10\x18\n \x01(\x05*\x04\x08\x05\x10\x06*@\n\x0b\x46oreignEnum\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x04\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x05\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x06*K\n\x14TestEnumWithDupValue\x12\x08\n\x04\x46OO1\x10\x01\x12\x08\n\x04\x42\x41R1\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x08\n\x04\x46OO2\x10\x01\x12\x08\n\x04\x42\x41R2\x10\x02\x1a\x02\x10\x01*\x89\x01\n\x0eTestSparseEnum\x12\x0c\n\x08SPARSE_A\x10{\x12\x0e\n\x08SPARSE_B\x10\xa6\xe7\x03\x12\x0f\n\x08SPARSE_C\x10\xb2\xb1\x80\x06\x12\x15\n\x08SPARSE_D\x10\xf1\xff\xff\xff\xff\xff\xff\xff\xff\x01\x12\x15\n\x08SPARSE_E\x10\xb4\xde\xfc\xff\xff\xff\xff\xff\xff\x01\x12\x0c\n\x08SPARSE_F\x10\x00\x12\x0c\n\x08SPARSE_G\x10\x02\x32\x99\x01\n\x0bTestService\x12\x44\n\x03\x46oo\x12\x1d.protobuf_unittest.FooRequest\x1a\x1e.protobuf_unittest.FooResponse\x12\x44\n\x03\x42\x61r\x12\x1d.protobuf_unittest.BarRequest\x1a\x1e.protobuf_unittest.BarResponse:F\n\x18optional_int32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x01 \x01(\x05:F\n\x18optional_int64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x02 \x01(\x03:G\n\x19optional_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x03 \x01(\r:G\n\x19optional_uint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x04 \x01(\x04:G\n\x19optional_sint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x05 \x01(\x11:G\n\x19optional_sint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x06 \x01(\x12:H\n\x1aoptional_fixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x07 \x01(\x07:H\n\x1aoptional_fixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x08 \x01(\x06:I\n\x1boptional_sfixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\t \x01(\x0f:I\n\x1boptional_sfixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\n \x01(\x10:F\n\x18optional_float_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0b \x01(\x02:G\n\x19optional_double_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0c \x01(\x01:E\n\x17optional_bool_extension\x12$.protobuf_unittest.TestAllExtensions\x18\r \x01(\x08:G\n\x19optional_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0e \x01(\t:F\n\x18optional_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x0f \x01(\x0c:q\n\x17optionalgroup_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x10 \x01(\n2*.protobuf_unittest.OptionalGroup_extension:~\n!optional_nested_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x12 \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage:s\n\"optional_foreign_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x13 \x01(\x0b\x32!.protobuf_unittest.ForeignMessage:x\n!optional_import_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage:x\n\x1eoptional_nested_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x15 \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:m\n\x1foptional_foreign_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x16 \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:r\n\x1eoptional_import_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x17 \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:Q\n\x1foptional_string_piece_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x18 \x01(\tB\x02\x08\x02:I\n\x17optional_cord_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x19 \x01(\tB\x02\x08\x01:\x85\x01\n(optional_public_import_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage:\x80\x01\n\x1foptional_lazy_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x1b \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01:F\n\x18repeated_int32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x1f \x03(\x05:F\n\x18repeated_int64_extension\x12$.protobuf_unittest.TestAllExtensions\x18 \x03(\x03:G\n\x19repeated_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18! \x03(\r:G\n\x19repeated_uint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\" \x03(\x04:G\n\x19repeated_sint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18# \x03(\x11:G\n\x19repeated_sint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18$ \x03(\x12:H\n\x1arepeated_fixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18% \x03(\x07:H\n\x1arepeated_fixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18& \x03(\x06:I\n\x1brepeated_sfixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\' \x03(\x0f:I\n\x1brepeated_sfixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18( \x03(\x10:F\n\x18repeated_float_extension\x12$.protobuf_unittest.TestAllExtensions\x18) \x03(\x02:G\n\x19repeated_double_extension\x12$.protobuf_unittest.TestAllExtensions\x18* \x03(\x01:E\n\x17repeated_bool_extension\x12$.protobuf_unittest.TestAllExtensions\x18+ \x03(\x08:G\n\x19repeated_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18, \x03(\t:F\n\x18repeated_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18- \x03(\x0c:q\n\x17repeatedgroup_extension\x12$.protobuf_unittest.TestAllExtensions\x18. \x03(\n2*.protobuf_unittest.RepeatedGroup_extension:~\n!repeated_nested_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x30 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage:s\n\"repeated_foreign_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x31 \x03(\x0b\x32!.protobuf_unittest.ForeignMessage:x\n!repeated_import_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage:x\n\x1erepeated_nested_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x33 \x03(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:m\n\x1frepeated_foreign_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x34 \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:r\n\x1erepeated_import_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x35 \x03(\x0e\x32$.protobuf_unittest_import.ImportEnum:Q\n\x1frepeated_string_piece_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x36 \x03(\tB\x02\x08\x02:I\n\x17repeated_cord_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x37 \x03(\tB\x02\x08\x01:\x80\x01\n\x1frepeated_lazy_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x39 \x03(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessageB\x02(\x01:I\n\x17\x64\x65\x66\x61ult_int32_extension\x12$.protobuf_unittest.TestAllExtensions\x18= \x01(\x05:\x02\x34\x31:I\n\x17\x64\x65\x66\x61ult_int64_extension\x12$.protobuf_unittest.TestAllExtensions\x18> \x01(\x03:\x02\x34\x32:J\n\x18\x64\x65\x66\x61ult_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18? \x01(\r:\x02\x34\x33:J\n\x18\x64\x65\x66\x61ult_uint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18@ \x01(\x04:\x02\x34\x34:K\n\x18\x64\x65\x66\x61ult_sint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x41 \x01(\x11:\x03-45:J\n\x18\x64\x65\x66\x61ult_sint64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x42 \x01(\x12:\x02\x34\x36:K\n\x19\x64\x65\x66\x61ult_fixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x43 \x01(\x07:\x02\x34\x37:K\n\x19\x64\x65\x66\x61ult_fixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x44 \x01(\x06:\x02\x34\x38:L\n\x1a\x64\x65\x66\x61ult_sfixed32_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x45 \x01(\x0f:\x02\x34\x39:M\n\x1a\x64\x65\x66\x61ult_sfixed64_extension\x12$.protobuf_unittest.TestAllExtensions\x18\x46 \x01(\x10:\x03-50:K\n\x17\x64\x65\x66\x61ult_float_extension\x12$.protobuf_unittest.TestAllExtensions\x18G \x01(\x02:\x04\x35\x31.5:M\n\x18\x64\x65\x66\x61ult_double_extension\x12$.protobuf_unittest.TestAllExtensions\x18H \x01(\x01:\x05\x35\x32\x30\x30\x30:J\n\x16\x64\x65\x66\x61ult_bool_extension\x12$.protobuf_unittest.TestAllExtensions\x18I \x01(\x08:\x04true:M\n\x18\x64\x65\x66\x61ult_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18J \x01(\t:\x05hello:L\n\x17\x64\x65\x66\x61ult_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18K \x01(\x0c:\x05world:|\n\x1d\x64\x65\x66\x61ult_nested_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18Q \x01(\x0e\x32*.protobuf_unittest.TestAllTypes.NestedEnum:\x03\x42\x41R:y\n\x1e\x64\x65\x66\x61ult_foreign_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18R \x01(\x0e\x32\x1e.protobuf_unittest.ForeignEnum:\x0b\x46OREIGN_BAR:}\n\x1d\x64\x65\x66\x61ult_import_enum_extension\x12$.protobuf_unittest.TestAllExtensions\x18S \x01(\x0e\x32$.protobuf_unittest_import.ImportEnum:\nIMPORT_BAR:U\n\x1e\x64\x65\x66\x61ult_string_piece_extension\x12$.protobuf_unittest.TestAllExtensions\x18T \x01(\t:\x03\x61\x62\x63\x42\x02\x08\x02:M\n\x16\x64\x65\x66\x61ult_cord_extension\x12$.protobuf_unittest.TestAllExtensions\x18U \x01(\t:\x03\x31\x32\x33\x42\x02\x08\x01:D\n\x16oneof_uint32_extension\x12$.protobuf_unittest.TestAllExtensions\x18o \x01(\r:{\n\x1eoneof_nested_message_extension\x12$.protobuf_unittest.TestAllExtensions\x18p \x01(\x0b\x32-.protobuf_unittest.TestAllTypes.NestedMessage:D\n\x16oneof_string_extension\x12$.protobuf_unittest.TestAllExtensions\x18q \x01(\t:C\n\x15oneof_bytes_extension\x12$.protobuf_unittest.TestAllExtensions\x18r \x01(\x0c:B\n\x13my_extension_string\x12%.protobuf_unittest.TestFieldOrderings\x18\x32 \x01(\t:?\n\x10my_extension_int\x12%.protobuf_unittest.TestFieldOrderings\x18\x05 \x01(\x05:K\n\x16packed_int32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18Z \x03(\x05\x42\x02\x10\x01:K\n\x16packed_int64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18[ \x03(\x03\x42\x02\x10\x01:L\n\x17packed_uint32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\\ \x03(\rB\x02\x10\x01:L\n\x17packed_uint64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18] \x03(\x04\x42\x02\x10\x01:L\n\x17packed_sint32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18^ \x03(\x11\x42\x02\x10\x01:L\n\x17packed_sint64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18_ \x03(\x12\x42\x02\x10\x01:M\n\x18packed_fixed32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18` \x03(\x07\x42\x02\x10\x01:M\n\x18packed_fixed64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x61 \x03(\x06\x42\x02\x10\x01:N\n\x19packed_sfixed32_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x62 \x03(\x0f\x42\x02\x10\x01:N\n\x19packed_sfixed64_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x63 \x03(\x10\x42\x02\x10\x01:K\n\x16packed_float_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x64 \x03(\x02\x42\x02\x10\x01:L\n\x17packed_double_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x65 \x03(\x01\x42\x02\x10\x01:J\n\x15packed_bool_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18\x66 \x03(\x08\x42\x02\x10\x01:j\n\x15packed_enum_extension\x12\'.protobuf_unittest.TestPackedExtensions\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x01:O\n\x18unpacked_int32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18Z \x03(\x05\x42\x02\x10\x00:O\n\x18unpacked_int64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18[ \x03(\x03\x42\x02\x10\x00:P\n\x19unpacked_uint32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\\ \x03(\rB\x02\x10\x00:P\n\x19unpacked_uint64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18] \x03(\x04\x42\x02\x10\x00:P\n\x19unpacked_sint32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18^ \x03(\x11\x42\x02\x10\x00:P\n\x19unpacked_sint64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18_ \x03(\x12\x42\x02\x10\x00:Q\n\x1aunpacked_fixed32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18` \x03(\x07\x42\x02\x10\x00:Q\n\x1aunpacked_fixed64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x61 \x03(\x06\x42\x02\x10\x00:R\n\x1bunpacked_sfixed32_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x62 \x03(\x0f\x42\x02\x10\x00:R\n\x1bunpacked_sfixed64_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x63 \x03(\x10\x42\x02\x10\x00:O\n\x18unpacked_float_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x64 \x03(\x02\x42\x02\x10\x00:P\n\x19unpacked_double_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x65 \x03(\x01\x42\x02\x10\x00:N\n\x17unpacked_bool_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18\x66 \x03(\x08\x42\x02\x10\x00:n\n\x17unpacked_enum_extension\x12).protobuf_unittest.TestUnpackedExtensions\x18g \x03(\x0e\x32\x1e.protobuf_unittest.ForeignEnumB\x02\x10\x00:d\n\x0etest_all_types\x12\'.protobuf_unittest.TestHugeFieldNumbers\x18\xe0\xaa\xff\xff\x01 \x01(\x0b\x32\x1f.protobuf_unittest.TestAllTypes:Z\n%test_extension_inside_table_extension\x12+.protobuf_unittest.TestExtensionInsideTable\x18\x05 \x01(\x05\x42\x1d\x42\rUnittestProtoH\x01\x80\x01\x01\x88\x01\x01\x90\x01\x01\xf8\x01\x01') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='protobuf_unittest.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=0, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=1, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=2, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=15306, + serialized_end=15370, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +_TESTENUMWITHDUPVALUE = _descriptor.EnumDescriptor( + name='TestEnumWithDupValue', + full_name='protobuf_unittest.TestEnumWithDupValue', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO1', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR1', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOO2', index=3, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR2', index=4, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=_b('\020\001'), + serialized_start=15372, + serialized_end=15447, +) +_sym_db.RegisterEnumDescriptor(_TESTENUMWITHDUPVALUE) + +TestEnumWithDupValue = enum_type_wrapper.EnumTypeWrapper(_TESTENUMWITHDUPVALUE) +_TESTSPARSEENUM = _descriptor.EnumDescriptor( + name='TestSparseEnum', + full_name='protobuf_unittest.TestSparseEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='SPARSE_A', index=0, number=123, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_B', index=1, number=62374, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_C', index=2, number=12589234, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_D', index=3, number=-15, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_E', index=4, number=-53452, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_F', index=5, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SPARSE_G', index=6, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=15450, + serialized_end=15587, +) +_sym_db.RegisterEnumDescriptor(_TESTSPARSEENUM) + +TestSparseEnum = enum_type_wrapper.EnumTypeWrapper(_TESTSPARSEENUM) +FOREIGN_FOO = 4 +FOREIGN_BAR = 5 +FOREIGN_BAZ = 6 +FOO1 = 1 +BAR1 = 2 +BAZ = 3 +FOO2 = 1 +BAR2 = 2 +SPARSE_A = 123 +SPARSE_B = 62374 +SPARSE_C = 12589234 +SPARSE_D = -15 +SPARSE_E = -53452 +SPARSE_F = 0 +SPARSE_G = 2 + +OPTIONAL_INT32_EXTENSION_FIELD_NUMBER = 1 +optional_int32_extension = _descriptor.FieldDescriptor( + name='optional_int32_extension', full_name='protobuf_unittest.optional_int32_extension', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_INT64_EXTENSION_FIELD_NUMBER = 2 +optional_int64_extension = _descriptor.FieldDescriptor( + name='optional_int64_extension', full_name='protobuf_unittest.optional_int64_extension', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_UINT32_EXTENSION_FIELD_NUMBER = 3 +optional_uint32_extension = _descriptor.FieldDescriptor( + name='optional_uint32_extension', full_name='protobuf_unittest.optional_uint32_extension', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_UINT64_EXTENSION_FIELD_NUMBER = 4 +optional_uint64_extension = _descriptor.FieldDescriptor( + name='optional_uint64_extension', full_name='protobuf_unittest.optional_uint64_extension', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SINT32_EXTENSION_FIELD_NUMBER = 5 +optional_sint32_extension = _descriptor.FieldDescriptor( + name='optional_sint32_extension', full_name='protobuf_unittest.optional_sint32_extension', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SINT64_EXTENSION_FIELD_NUMBER = 6 +optional_sint64_extension = _descriptor.FieldDescriptor( + name='optional_sint64_extension', full_name='protobuf_unittest.optional_sint64_extension', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FIXED32_EXTENSION_FIELD_NUMBER = 7 +optional_fixed32_extension = _descriptor.FieldDescriptor( + name='optional_fixed32_extension', full_name='protobuf_unittest.optional_fixed32_extension', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FIXED64_EXTENSION_FIELD_NUMBER = 8 +optional_fixed64_extension = _descriptor.FieldDescriptor( + name='optional_fixed64_extension', full_name='protobuf_unittest.optional_fixed64_extension', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SFIXED32_EXTENSION_FIELD_NUMBER = 9 +optional_sfixed32_extension = _descriptor.FieldDescriptor( + name='optional_sfixed32_extension', full_name='protobuf_unittest.optional_sfixed32_extension', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_SFIXED64_EXTENSION_FIELD_NUMBER = 10 +optional_sfixed64_extension = _descriptor.FieldDescriptor( + name='optional_sfixed64_extension', full_name='protobuf_unittest.optional_sfixed64_extension', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FLOAT_EXTENSION_FIELD_NUMBER = 11 +optional_float_extension = _descriptor.FieldDescriptor( + name='optional_float_extension', full_name='protobuf_unittest.optional_float_extension', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_DOUBLE_EXTENSION_FIELD_NUMBER = 12 +optional_double_extension = _descriptor.FieldDescriptor( + name='optional_double_extension', full_name='protobuf_unittest.optional_double_extension', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_BOOL_EXTENSION_FIELD_NUMBER = 13 +optional_bool_extension = _descriptor.FieldDescriptor( + name='optional_bool_extension', full_name='protobuf_unittest.optional_bool_extension', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_STRING_EXTENSION_FIELD_NUMBER = 14 +optional_string_extension = _descriptor.FieldDescriptor( + name='optional_string_extension', full_name='protobuf_unittest.optional_string_extension', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_BYTES_EXTENSION_FIELD_NUMBER = 15 +optional_bytes_extension = _descriptor.FieldDescriptor( + name='optional_bytes_extension', full_name='protobuf_unittest.optional_bytes_extension', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONALGROUP_EXTENSION_FIELD_NUMBER = 16 +optionalgroup_extension = _descriptor.FieldDescriptor( + name='optionalgroup_extension', full_name='protobuf_unittest.optionalgroup_extension', index=15, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 18 +optional_nested_message_extension = _descriptor.FieldDescriptor( + name='optional_nested_message_extension', full_name='protobuf_unittest.optional_nested_message_extension', index=16, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FOREIGN_MESSAGE_EXTENSION_FIELD_NUMBER = 19 +optional_foreign_message_extension = _descriptor.FieldDescriptor( + name='optional_foreign_message_extension', full_name='protobuf_unittest.optional_foreign_message_extension', index=17, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_IMPORT_MESSAGE_EXTENSION_FIELD_NUMBER = 20 +optional_import_message_extension = _descriptor.FieldDescriptor( + name='optional_import_message_extension', full_name='protobuf_unittest.optional_import_message_extension', index=18, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER = 21 +optional_nested_enum_extension = _descriptor.FieldDescriptor( + name='optional_nested_enum_extension', full_name='protobuf_unittest.optional_nested_enum_extension', index=19, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_FOREIGN_ENUM_EXTENSION_FIELD_NUMBER = 22 +optional_foreign_enum_extension = _descriptor.FieldDescriptor( + name='optional_foreign_enum_extension', full_name='protobuf_unittest.optional_foreign_enum_extension', index=20, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_IMPORT_ENUM_EXTENSION_FIELD_NUMBER = 23 +optional_import_enum_extension = _descriptor.FieldDescriptor( + name='optional_import_enum_extension', full_name='protobuf_unittest.optional_import_enum_extension', index=21, + number=23, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_STRING_PIECE_EXTENSION_FIELD_NUMBER = 24 +optional_string_piece_extension = _descriptor.FieldDescriptor( + name='optional_string_piece_extension', full_name='protobuf_unittest.optional_string_piece_extension', index=22, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR) +OPTIONAL_CORD_EXTENSION_FIELD_NUMBER = 25 +optional_cord_extension = _descriptor.FieldDescriptor( + name='optional_cord_extension', full_name='protobuf_unittest.optional_cord_extension', index=23, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR) +OPTIONAL_PUBLIC_IMPORT_MESSAGE_EXTENSION_FIELD_NUMBER = 26 +optional_public_import_message_extension = _descriptor.FieldDescriptor( + name='optional_public_import_message_extension', full_name='protobuf_unittest.optional_public_import_message_extension', index=24, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +OPTIONAL_LAZY_MESSAGE_EXTENSION_FIELD_NUMBER = 27 +optional_lazy_message_extension = _descriptor.FieldDescriptor( + name='optional_lazy_message_extension', full_name='protobuf_unittest.optional_lazy_message_extension', index=25, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR) +REPEATED_INT32_EXTENSION_FIELD_NUMBER = 31 +repeated_int32_extension = _descriptor.FieldDescriptor( + name='repeated_int32_extension', full_name='protobuf_unittest.repeated_int32_extension', index=26, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_INT64_EXTENSION_FIELD_NUMBER = 32 +repeated_int64_extension = _descriptor.FieldDescriptor( + name='repeated_int64_extension', full_name='protobuf_unittest.repeated_int64_extension', index=27, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_UINT32_EXTENSION_FIELD_NUMBER = 33 +repeated_uint32_extension = _descriptor.FieldDescriptor( + name='repeated_uint32_extension', full_name='protobuf_unittest.repeated_uint32_extension', index=28, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_UINT64_EXTENSION_FIELD_NUMBER = 34 +repeated_uint64_extension = _descriptor.FieldDescriptor( + name='repeated_uint64_extension', full_name='protobuf_unittest.repeated_uint64_extension', index=29, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SINT32_EXTENSION_FIELD_NUMBER = 35 +repeated_sint32_extension = _descriptor.FieldDescriptor( + name='repeated_sint32_extension', full_name='protobuf_unittest.repeated_sint32_extension', index=30, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SINT64_EXTENSION_FIELD_NUMBER = 36 +repeated_sint64_extension = _descriptor.FieldDescriptor( + name='repeated_sint64_extension', full_name='protobuf_unittest.repeated_sint64_extension', index=31, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FIXED32_EXTENSION_FIELD_NUMBER = 37 +repeated_fixed32_extension = _descriptor.FieldDescriptor( + name='repeated_fixed32_extension', full_name='protobuf_unittest.repeated_fixed32_extension', index=32, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FIXED64_EXTENSION_FIELD_NUMBER = 38 +repeated_fixed64_extension = _descriptor.FieldDescriptor( + name='repeated_fixed64_extension', full_name='protobuf_unittest.repeated_fixed64_extension', index=33, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SFIXED32_EXTENSION_FIELD_NUMBER = 39 +repeated_sfixed32_extension = _descriptor.FieldDescriptor( + name='repeated_sfixed32_extension', full_name='protobuf_unittest.repeated_sfixed32_extension', index=34, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_SFIXED64_EXTENSION_FIELD_NUMBER = 40 +repeated_sfixed64_extension = _descriptor.FieldDescriptor( + name='repeated_sfixed64_extension', full_name='protobuf_unittest.repeated_sfixed64_extension', index=35, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FLOAT_EXTENSION_FIELD_NUMBER = 41 +repeated_float_extension = _descriptor.FieldDescriptor( + name='repeated_float_extension', full_name='protobuf_unittest.repeated_float_extension', index=36, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_DOUBLE_EXTENSION_FIELD_NUMBER = 42 +repeated_double_extension = _descriptor.FieldDescriptor( + name='repeated_double_extension', full_name='protobuf_unittest.repeated_double_extension', index=37, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_BOOL_EXTENSION_FIELD_NUMBER = 43 +repeated_bool_extension = _descriptor.FieldDescriptor( + name='repeated_bool_extension', full_name='protobuf_unittest.repeated_bool_extension', index=38, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_STRING_EXTENSION_FIELD_NUMBER = 44 +repeated_string_extension = _descriptor.FieldDescriptor( + name='repeated_string_extension', full_name='protobuf_unittest.repeated_string_extension', index=39, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_BYTES_EXTENSION_FIELD_NUMBER = 45 +repeated_bytes_extension = _descriptor.FieldDescriptor( + name='repeated_bytes_extension', full_name='protobuf_unittest.repeated_bytes_extension', index=40, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATEDGROUP_EXTENSION_FIELD_NUMBER = 46 +repeatedgroup_extension = _descriptor.FieldDescriptor( + name='repeatedgroup_extension', full_name='protobuf_unittest.repeatedgroup_extension', index=41, + number=46, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 48 +repeated_nested_message_extension = _descriptor.FieldDescriptor( + name='repeated_nested_message_extension', full_name='protobuf_unittest.repeated_nested_message_extension', index=42, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FOREIGN_MESSAGE_EXTENSION_FIELD_NUMBER = 49 +repeated_foreign_message_extension = _descriptor.FieldDescriptor( + name='repeated_foreign_message_extension', full_name='protobuf_unittest.repeated_foreign_message_extension', index=43, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_IMPORT_MESSAGE_EXTENSION_FIELD_NUMBER = 50 +repeated_import_message_extension = _descriptor.FieldDescriptor( + name='repeated_import_message_extension', full_name='protobuf_unittest.repeated_import_message_extension', index=44, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER = 51 +repeated_nested_enum_extension = _descriptor.FieldDescriptor( + name='repeated_nested_enum_extension', full_name='protobuf_unittest.repeated_nested_enum_extension', index=45, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_FOREIGN_ENUM_EXTENSION_FIELD_NUMBER = 52 +repeated_foreign_enum_extension = _descriptor.FieldDescriptor( + name='repeated_foreign_enum_extension', full_name='protobuf_unittest.repeated_foreign_enum_extension', index=46, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_IMPORT_ENUM_EXTENSION_FIELD_NUMBER = 53 +repeated_import_enum_extension = _descriptor.FieldDescriptor( + name='repeated_import_enum_extension', full_name='protobuf_unittest.repeated_import_enum_extension', index=47, + number=53, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +REPEATED_STRING_PIECE_EXTENSION_FIELD_NUMBER = 54 +repeated_string_piece_extension = _descriptor.FieldDescriptor( + name='repeated_string_piece_extension', full_name='protobuf_unittest.repeated_string_piece_extension', index=48, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR) +REPEATED_CORD_EXTENSION_FIELD_NUMBER = 55 +repeated_cord_extension = _descriptor.FieldDescriptor( + name='repeated_cord_extension', full_name='protobuf_unittest.repeated_cord_extension', index=49, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR) +REPEATED_LAZY_MESSAGE_EXTENSION_FIELD_NUMBER = 57 +repeated_lazy_message_extension = _descriptor.FieldDescriptor( + name='repeated_lazy_message_extension', full_name='protobuf_unittest.repeated_lazy_message_extension', index=50, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR) +DEFAULT_INT32_EXTENSION_FIELD_NUMBER = 61 +default_int32_extension = _descriptor.FieldDescriptor( + name='default_int32_extension', full_name='protobuf_unittest.default_int32_extension', index=51, + number=61, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=41, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_INT64_EXTENSION_FIELD_NUMBER = 62 +default_int64_extension = _descriptor.FieldDescriptor( + name='default_int64_extension', full_name='protobuf_unittest.default_int64_extension', index=52, + number=62, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_UINT32_EXTENSION_FIELD_NUMBER = 63 +default_uint32_extension = _descriptor.FieldDescriptor( + name='default_uint32_extension', full_name='protobuf_unittest.default_uint32_extension', index=53, + number=63, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=43, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_UINT64_EXTENSION_FIELD_NUMBER = 64 +default_uint64_extension = _descriptor.FieldDescriptor( + name='default_uint64_extension', full_name='protobuf_unittest.default_uint64_extension', index=54, + number=64, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=44, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SINT32_EXTENSION_FIELD_NUMBER = 65 +default_sint32_extension = _descriptor.FieldDescriptor( + name='default_sint32_extension', full_name='protobuf_unittest.default_sint32_extension', index=55, + number=65, type=17, cpp_type=1, label=1, + has_default_value=True, default_value=-45, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SINT64_EXTENSION_FIELD_NUMBER = 66 +default_sint64_extension = _descriptor.FieldDescriptor( + name='default_sint64_extension', full_name='protobuf_unittest.default_sint64_extension', index=56, + number=66, type=18, cpp_type=2, label=1, + has_default_value=True, default_value=46, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FIXED32_EXTENSION_FIELD_NUMBER = 67 +default_fixed32_extension = _descriptor.FieldDescriptor( + name='default_fixed32_extension', full_name='protobuf_unittest.default_fixed32_extension', index=57, + number=67, type=7, cpp_type=3, label=1, + has_default_value=True, default_value=47, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FIXED64_EXTENSION_FIELD_NUMBER = 68 +default_fixed64_extension = _descriptor.FieldDescriptor( + name='default_fixed64_extension', full_name='protobuf_unittest.default_fixed64_extension', index=58, + number=68, type=6, cpp_type=4, label=1, + has_default_value=True, default_value=48, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SFIXED32_EXTENSION_FIELD_NUMBER = 69 +default_sfixed32_extension = _descriptor.FieldDescriptor( + name='default_sfixed32_extension', full_name='protobuf_unittest.default_sfixed32_extension', index=59, + number=69, type=15, cpp_type=1, label=1, + has_default_value=True, default_value=49, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_SFIXED64_EXTENSION_FIELD_NUMBER = 70 +default_sfixed64_extension = _descriptor.FieldDescriptor( + name='default_sfixed64_extension', full_name='protobuf_unittest.default_sfixed64_extension', index=60, + number=70, type=16, cpp_type=2, label=1, + has_default_value=True, default_value=-50, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FLOAT_EXTENSION_FIELD_NUMBER = 71 +default_float_extension = _descriptor.FieldDescriptor( + name='default_float_extension', full_name='protobuf_unittest.default_float_extension', index=61, + number=71, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(51.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_DOUBLE_EXTENSION_FIELD_NUMBER = 72 +default_double_extension = _descriptor.FieldDescriptor( + name='default_double_extension', full_name='protobuf_unittest.default_double_extension', index=62, + number=72, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(52000), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_BOOL_EXTENSION_FIELD_NUMBER = 73 +default_bool_extension = _descriptor.FieldDescriptor( + name='default_bool_extension', full_name='protobuf_unittest.default_bool_extension', index=63, + number=73, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_STRING_EXTENSION_FIELD_NUMBER = 74 +default_string_extension = _descriptor.FieldDescriptor( + name='default_string_extension', full_name='protobuf_unittest.default_string_extension', index=64, + number=74, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_BYTES_EXTENSION_FIELD_NUMBER = 75 +default_bytes_extension = _descriptor.FieldDescriptor( + name='default_bytes_extension', full_name='protobuf_unittest.default_bytes_extension', index=65, + number=75, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("world"), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_NESTED_ENUM_EXTENSION_FIELD_NUMBER = 81 +default_nested_enum_extension = _descriptor.FieldDescriptor( + name='default_nested_enum_extension', full_name='protobuf_unittest.default_nested_enum_extension', index=66, + number=81, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_FOREIGN_ENUM_EXTENSION_FIELD_NUMBER = 82 +default_foreign_enum_extension = _descriptor.FieldDescriptor( + name='default_foreign_enum_extension', full_name='protobuf_unittest.default_foreign_enum_extension', index=67, + number=82, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_IMPORT_ENUM_EXTENSION_FIELD_NUMBER = 83 +default_import_enum_extension = _descriptor.FieldDescriptor( + name='default_import_enum_extension', full_name='protobuf_unittest.default_import_enum_extension', index=68, + number=83, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=8, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +DEFAULT_STRING_PIECE_EXTENSION_FIELD_NUMBER = 84 +default_string_piece_extension = _descriptor.FieldDescriptor( + name='default_string_piece_extension', full_name='protobuf_unittest.default_string_piece_extension', index=69, + number=84, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("abc").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR) +DEFAULT_CORD_EXTENSION_FIELD_NUMBER = 85 +default_cord_extension = _descriptor.FieldDescriptor( + name='default_cord_extension', full_name='protobuf_unittest.default_cord_extension', index=70, + number=85, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("123").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR) +ONEOF_UINT32_EXTENSION_FIELD_NUMBER = 111 +oneof_uint32_extension = _descriptor.FieldDescriptor( + name='oneof_uint32_extension', full_name='protobuf_unittest.oneof_uint32_extension', index=71, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER = 112 +oneof_nested_message_extension = _descriptor.FieldDescriptor( + name='oneof_nested_message_extension', full_name='protobuf_unittest.oneof_nested_message_extension', index=72, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_STRING_EXTENSION_FIELD_NUMBER = 113 +oneof_string_extension = _descriptor.FieldDescriptor( + name='oneof_string_extension', full_name='protobuf_unittest.oneof_string_extension', index=73, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +ONEOF_BYTES_EXTENSION_FIELD_NUMBER = 114 +oneof_bytes_extension = _descriptor.FieldDescriptor( + name='oneof_bytes_extension', full_name='protobuf_unittest.oneof_bytes_extension', index=74, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MY_EXTENSION_STRING_FIELD_NUMBER = 50 +my_extension_string = _descriptor.FieldDescriptor( + name='my_extension_string', full_name='protobuf_unittest.my_extension_string', index=75, + number=50, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +MY_EXTENSION_INT_FIELD_NUMBER = 5 +my_extension_int = _descriptor.FieldDescriptor( + name='my_extension_int', full_name='protobuf_unittest.my_extension_int', index=76, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +PACKED_INT32_EXTENSION_FIELD_NUMBER = 90 +packed_int32_extension = _descriptor.FieldDescriptor( + name='packed_int32_extension', full_name='protobuf_unittest.packed_int32_extension', index=77, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_INT64_EXTENSION_FIELD_NUMBER = 91 +packed_int64_extension = _descriptor.FieldDescriptor( + name='packed_int64_extension', full_name='protobuf_unittest.packed_int64_extension', index=78, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_UINT32_EXTENSION_FIELD_NUMBER = 92 +packed_uint32_extension = _descriptor.FieldDescriptor( + name='packed_uint32_extension', full_name='protobuf_unittest.packed_uint32_extension', index=79, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_UINT64_EXTENSION_FIELD_NUMBER = 93 +packed_uint64_extension = _descriptor.FieldDescriptor( + name='packed_uint64_extension', full_name='protobuf_unittest.packed_uint64_extension', index=80, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SINT32_EXTENSION_FIELD_NUMBER = 94 +packed_sint32_extension = _descriptor.FieldDescriptor( + name='packed_sint32_extension', full_name='protobuf_unittest.packed_sint32_extension', index=81, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SINT64_EXTENSION_FIELD_NUMBER = 95 +packed_sint64_extension = _descriptor.FieldDescriptor( + name='packed_sint64_extension', full_name='protobuf_unittest.packed_sint64_extension', index=82, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_FIXED32_EXTENSION_FIELD_NUMBER = 96 +packed_fixed32_extension = _descriptor.FieldDescriptor( + name='packed_fixed32_extension', full_name='protobuf_unittest.packed_fixed32_extension', index=83, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_FIXED64_EXTENSION_FIELD_NUMBER = 97 +packed_fixed64_extension = _descriptor.FieldDescriptor( + name='packed_fixed64_extension', full_name='protobuf_unittest.packed_fixed64_extension', index=84, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SFIXED32_EXTENSION_FIELD_NUMBER = 98 +packed_sfixed32_extension = _descriptor.FieldDescriptor( + name='packed_sfixed32_extension', full_name='protobuf_unittest.packed_sfixed32_extension', index=85, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_SFIXED64_EXTENSION_FIELD_NUMBER = 99 +packed_sfixed64_extension = _descriptor.FieldDescriptor( + name='packed_sfixed64_extension', full_name='protobuf_unittest.packed_sfixed64_extension', index=86, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_FLOAT_EXTENSION_FIELD_NUMBER = 100 +packed_float_extension = _descriptor.FieldDescriptor( + name='packed_float_extension', full_name='protobuf_unittest.packed_float_extension', index=87, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_DOUBLE_EXTENSION_FIELD_NUMBER = 101 +packed_double_extension = _descriptor.FieldDescriptor( + name='packed_double_extension', full_name='protobuf_unittest.packed_double_extension', index=88, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_BOOL_EXTENSION_FIELD_NUMBER = 102 +packed_bool_extension = _descriptor.FieldDescriptor( + name='packed_bool_extension', full_name='protobuf_unittest.packed_bool_extension', index=89, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +PACKED_ENUM_EXTENSION_FIELD_NUMBER = 103 +packed_enum_extension = _descriptor.FieldDescriptor( + name='packed_enum_extension', full_name='protobuf_unittest.packed_enum_extension', index=90, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR) +UNPACKED_INT32_EXTENSION_FIELD_NUMBER = 90 +unpacked_int32_extension = _descriptor.FieldDescriptor( + name='unpacked_int32_extension', full_name='protobuf_unittest.unpacked_int32_extension', index=91, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_INT64_EXTENSION_FIELD_NUMBER = 91 +unpacked_int64_extension = _descriptor.FieldDescriptor( + name='unpacked_int64_extension', full_name='protobuf_unittest.unpacked_int64_extension', index=92, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_UINT32_EXTENSION_FIELD_NUMBER = 92 +unpacked_uint32_extension = _descriptor.FieldDescriptor( + name='unpacked_uint32_extension', full_name='protobuf_unittest.unpacked_uint32_extension', index=93, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_UINT64_EXTENSION_FIELD_NUMBER = 93 +unpacked_uint64_extension = _descriptor.FieldDescriptor( + name='unpacked_uint64_extension', full_name='protobuf_unittest.unpacked_uint64_extension', index=94, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SINT32_EXTENSION_FIELD_NUMBER = 94 +unpacked_sint32_extension = _descriptor.FieldDescriptor( + name='unpacked_sint32_extension', full_name='protobuf_unittest.unpacked_sint32_extension', index=95, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SINT64_EXTENSION_FIELD_NUMBER = 95 +unpacked_sint64_extension = _descriptor.FieldDescriptor( + name='unpacked_sint64_extension', full_name='protobuf_unittest.unpacked_sint64_extension', index=96, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_FIXED32_EXTENSION_FIELD_NUMBER = 96 +unpacked_fixed32_extension = _descriptor.FieldDescriptor( + name='unpacked_fixed32_extension', full_name='protobuf_unittest.unpacked_fixed32_extension', index=97, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_FIXED64_EXTENSION_FIELD_NUMBER = 97 +unpacked_fixed64_extension = _descriptor.FieldDescriptor( + name='unpacked_fixed64_extension', full_name='protobuf_unittest.unpacked_fixed64_extension', index=98, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SFIXED32_EXTENSION_FIELD_NUMBER = 98 +unpacked_sfixed32_extension = _descriptor.FieldDescriptor( + name='unpacked_sfixed32_extension', full_name='protobuf_unittest.unpacked_sfixed32_extension', index=99, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_SFIXED64_EXTENSION_FIELD_NUMBER = 99 +unpacked_sfixed64_extension = _descriptor.FieldDescriptor( + name='unpacked_sfixed64_extension', full_name='protobuf_unittest.unpacked_sfixed64_extension', index=100, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_FLOAT_EXTENSION_FIELD_NUMBER = 100 +unpacked_float_extension = _descriptor.FieldDescriptor( + name='unpacked_float_extension', full_name='protobuf_unittest.unpacked_float_extension', index=101, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_DOUBLE_EXTENSION_FIELD_NUMBER = 101 +unpacked_double_extension = _descriptor.FieldDescriptor( + name='unpacked_double_extension', full_name='protobuf_unittest.unpacked_double_extension', index=102, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_BOOL_EXTENSION_FIELD_NUMBER = 102 +unpacked_bool_extension = _descriptor.FieldDescriptor( + name='unpacked_bool_extension', full_name='protobuf_unittest.unpacked_bool_extension', index=103, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +UNPACKED_ENUM_EXTENSION_FIELD_NUMBER = 103 +unpacked_enum_extension = _descriptor.FieldDescriptor( + name='unpacked_enum_extension', full_name='protobuf_unittest.unpacked_enum_extension', index=104, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR) +TEST_ALL_TYPES_FIELD_NUMBER = 536860000 +test_all_types = _descriptor.FieldDescriptor( + name='test_all_types', full_name='protobuf_unittest.test_all_types', index=105, + number=536860000, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +TEST_EXTENSION_INSIDE_TABLE_EXTENSION_FIELD_NUMBER = 5 +test_extension_inside_table_extension = _descriptor.FieldDescriptor( + name='test_extension_inside_table_extension', full_name='protobuf_unittest.test_extension_inside_table_extension', index=106, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + +_TESTALLTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest.TestAllTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=3, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3202, + serialized_end=3259, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPES_NESTEDENUM) + +_TESTONEOF2_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='protobuf_unittest.TestOneof2.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=2, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3202, + serialized_end=3241, +) +_sym_db.RegisterEnumDescriptor(_TESTONEOF2_NESTEDENUM) + +_TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE = _descriptor.EnumDescriptor( + name='DynamicEnumType', + full_name='protobuf_unittest.TestDynamicExtensions.DynamicEnumType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DYNAMIC_FOO', index=0, number=2200, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DYNAMIC_BAR', index=1, number=2201, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DYNAMIC_BAZ', index=2, number=2202, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=12499, + serialized_end=12570, +) +_sym_db.RegisterEnumDescriptor(_TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3117, + serialized_end=3144, +) + +_TESTALLTYPES_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestAllTypes.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestAllTypes.OptionalGroup.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3146, + serialized_end=3172, +) + +_TESTALLTYPES_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest.TestAllTypes.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestAllTypes.RepeatedGroup.a', index=0, + number=47, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3174, + serialized_end=3200, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='protobuf_unittest.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest.TestAllTypes.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='protobuf_unittest.TestAllTypes.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='protobuf_unittest.TestAllTypes.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='protobuf_unittest.TestAllTypes.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='protobuf_unittest.TestAllTypes.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='protobuf_unittest.TestAllTypes.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='protobuf_unittest.TestAllTypes.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='protobuf_unittest.TestAllTypes.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='protobuf_unittest.TestAllTypes.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='protobuf_unittest.TestAllTypes.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='protobuf_unittest.TestAllTypes.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='protobuf_unittest.TestAllTypes.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='protobuf_unittest.TestAllTypes.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_unittest.TestAllTypes.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_unittest.TestAllTypes.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestAllTypes.optionalgroup', index=15, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest.TestAllTypes.optional_nested_message', index=16, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='protobuf_unittest.TestAllTypes.optional_foreign_message', index=17, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_message', full_name='protobuf_unittest.TestAllTypes.optional_import_message', index=18, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='protobuf_unittest.TestAllTypes.optional_nested_enum', index=19, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_unittest.TestAllTypes.optional_foreign_enum', index=20, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_enum', full_name='protobuf_unittest.TestAllTypes.optional_import_enum', index=21, + number=23, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=7, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='protobuf_unittest.TestAllTypes.optional_string_piece', index=22, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='protobuf_unittest.TestAllTypes.optional_cord', index=23, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_public_import_message', full_name='protobuf_unittest.TestAllTypes.optional_public_import_message', index=24, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_lazy_message', full_name='protobuf_unittest.TestAllTypes.optional_lazy_message', index=25, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest.TestAllTypes.repeated_int32', index=26, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_unittest.TestAllTypes.repeated_int64', index=27, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='protobuf_unittest.TestAllTypes.repeated_uint32', index=28, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_unittest.TestAllTypes.repeated_uint64', index=29, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='protobuf_unittest.TestAllTypes.repeated_sint32', index=30, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='protobuf_unittest.TestAllTypes.repeated_sint64', index=31, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_unittest.TestAllTypes.repeated_fixed32', index=32, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_unittest.TestAllTypes.repeated_fixed64', index=33, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='protobuf_unittest.TestAllTypes.repeated_sfixed32', index=34, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='protobuf_unittest.TestAllTypes.repeated_sfixed64', index=35, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_unittest.TestAllTypes.repeated_float', index=36, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='protobuf_unittest.TestAllTypes.repeated_double', index=37, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='protobuf_unittest.TestAllTypes.repeated_bool', index=38, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_unittest.TestAllTypes.repeated_string', index=39, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='protobuf_unittest.TestAllTypes.repeated_bytes', index=40, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest.TestAllTypes.repeatedgroup', index=41, + number=46, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='protobuf_unittest.TestAllTypes.repeated_nested_message', index=42, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='protobuf_unittest.TestAllTypes.repeated_foreign_message', index=43, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_message', full_name='protobuf_unittest.TestAllTypes.repeated_import_message', index=44, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='protobuf_unittest.TestAllTypes.repeated_nested_enum', index=45, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='protobuf_unittest.TestAllTypes.repeated_foreign_enum', index=46, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_enum', full_name='protobuf_unittest.TestAllTypes.repeated_import_enum', index=47, + number=53, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='protobuf_unittest.TestAllTypes.repeated_string_piece', index=48, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='protobuf_unittest.TestAllTypes.repeated_cord', index=49, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_lazy_message', full_name='protobuf_unittest.TestAllTypes.repeated_lazy_message', index=50, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int32', full_name='protobuf_unittest.TestAllTypes.default_int32', index=51, + number=61, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=41, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_int64', full_name='protobuf_unittest.TestAllTypes.default_int64', index=52, + number=62, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=42, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint32', full_name='protobuf_unittest.TestAllTypes.default_uint32', index=53, + number=63, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=43, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_uint64', full_name='protobuf_unittest.TestAllTypes.default_uint64', index=54, + number=64, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=44, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint32', full_name='protobuf_unittest.TestAllTypes.default_sint32', index=55, + number=65, type=17, cpp_type=1, label=1, + has_default_value=True, default_value=-45, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sint64', full_name='protobuf_unittest.TestAllTypes.default_sint64', index=56, + number=66, type=18, cpp_type=2, label=1, + has_default_value=True, default_value=46, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed32', full_name='protobuf_unittest.TestAllTypes.default_fixed32', index=57, + number=67, type=7, cpp_type=3, label=1, + has_default_value=True, default_value=47, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_fixed64', full_name='protobuf_unittest.TestAllTypes.default_fixed64', index=58, + number=68, type=6, cpp_type=4, label=1, + has_default_value=True, default_value=48, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed32', full_name='protobuf_unittest.TestAllTypes.default_sfixed32', index=59, + number=69, type=15, cpp_type=1, label=1, + has_default_value=True, default_value=49, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_sfixed64', full_name='protobuf_unittest.TestAllTypes.default_sfixed64', index=60, + number=70, type=16, cpp_type=2, label=1, + has_default_value=True, default_value=-50, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_float', full_name='protobuf_unittest.TestAllTypes.default_float', index=61, + number=71, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(51.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_double', full_name='protobuf_unittest.TestAllTypes.default_double', index=62, + number=72, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=float(52000), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bool', full_name='protobuf_unittest.TestAllTypes.default_bool', index=63, + number=73, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string', full_name='protobuf_unittest.TestAllTypes.default_string', index=64, + number=74, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hello").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_bytes', full_name='protobuf_unittest.TestAllTypes.default_bytes', index=65, + number=75, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("world"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_nested_enum', full_name='protobuf_unittest.TestAllTypes.default_nested_enum', index=66, + number=81, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_foreign_enum', full_name='protobuf_unittest.TestAllTypes.default_foreign_enum', index=67, + number=82, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_import_enum', full_name='protobuf_unittest.TestAllTypes.default_import_enum', index=68, + number=83, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=8, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_string_piece', full_name='protobuf_unittest.TestAllTypes.default_string_piece', index=69, + number=84, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("abc").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_cord', full_name='protobuf_unittest.TestAllTypes.default_cord', index=70, + number=85, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("123").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_unittest.TestAllTypes.oneof_uint32', index=71, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='protobuf_unittest.TestAllTypes.oneof_nested_message', index=72, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_unittest.TestAllTypes.oneof_string', index=73, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_unittest.TestAllTypes.oneof_bytes', index=74, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, _TESTALLTYPES_OPTIONALGROUP, _TESTALLTYPES_REPEATEDGROUP, ], + enum_types=[ + _TESTALLTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_unittest.TestAllTypes.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=93, + serialized_end=3274, +) + + +_NESTEDTESTALLTYPES = _descriptor.Descriptor( + name='NestedTestAllTypes', + full_name='protobuf_unittest.NestedTestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='child', full_name='protobuf_unittest.NestedTestAllTypes.child', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payload', full_name='protobuf_unittest.NestedTestAllTypes.payload', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_child', full_name='protobuf_unittest.NestedTestAllTypes.repeated_child', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3277, + serialized_end=3464, +) + + +_TESTDEPRECATEDFIELDS = _descriptor.Descriptor( + name='TestDeprecatedFields', + full_name='protobuf_unittest.TestDeprecatedFields', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated_int32', full_name='protobuf_unittest.TestDeprecatedFields.deprecated_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\030\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='deprecated_int32_in_oneof', full_name='protobuf_unittest.TestDeprecatedFields.deprecated_int32_in_oneof', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\030\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_fields', full_name='protobuf_unittest.TestDeprecatedFields.oneof_fields', + index=0, containing_type=None, fields=[]), + ], + serialized_start=3466, + serialized_end=3575, +) + + +_TESTDEPRECATEDMESSAGE = _descriptor.Descriptor( + name='TestDeprecatedMessage', + full_name='protobuf_unittest.TestDeprecatedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('\030\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3577, + serialized_end=3604, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='protobuf_unittest.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest.ForeignMessage.d', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3606, + serialized_end=3644, +) + + +_TESTRESERVEDFIELDS = _descriptor.Descriptor( + name='TestReservedFields', + full_name='protobuf_unittest.TestReservedFields', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3646, + serialized_end=3694, +) + + +_TESTALLEXTENSIONS = _descriptor.Descriptor( + name='TestAllExtensions', + full_name='protobuf_unittest.TestAllExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=3696, + serialized_end=3725, +) + + +_OPTIONALGROUP_EXTENSION = _descriptor.Descriptor( + name='OptionalGroup_extension', + full_name='protobuf_unittest.OptionalGroup_extension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.OptionalGroup_extension.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3727, + serialized_end=3763, +) + + +_REPEATEDGROUP_EXTENSION = _descriptor.Descriptor( + name='RepeatedGroup_extension', + full_name='protobuf_unittest.RepeatedGroup_extension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.RepeatedGroup_extension.a', index=0, + number=47, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3765, + serialized_end=3801, +) + + +_TESTGROUP_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestGroup.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestGroup.OptionalGroup.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3146, + serialized_end=3172, +) + +_TESTGROUP = _descriptor.Descriptor( + name='TestGroup', + full_name='protobuf_unittest.TestGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestGroup.optionalgroup', index=0, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='protobuf_unittest.TestGroup.optional_foreign_enum', index=1, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTGROUP_OPTIONALGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3804, + serialized_end=3973, +) + + +_TESTGROUPEXTENSION = _descriptor.Descriptor( + name='TestGroupExtension', + full_name='protobuf_unittest.TestGroupExtension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=3975, + serialized_end=4005, +) + + +_TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION = _descriptor.Descriptor( + name='OptionalGroup_extension', + full_name='protobuf_unittest.TestNestedExtension.OptionalGroup_extension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestNestedExtension.OptionalGroup_extension.a', index=0, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3727, + serialized_end=3763, +) + +_TESTNESTEDEXTENSION = _descriptor.Descriptor( + name='TestNestedExtension', + full_name='protobuf_unittest.TestNestedExtension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test', full_name='protobuf_unittest.TestNestedExtension.test', index=0, + number=1002, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("test").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nested_string_extension', full_name='protobuf_unittest.TestNestedExtension.nested_string_extension', index=1, + number=1003, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup_extension', full_name='protobuf_unittest.TestNestedExtension.optionalgroup_extension', index=2, + number=16, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum_extension', full_name='protobuf_unittest.TestNestedExtension.optional_foreign_enum_extension', index=3, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4008, + serialized_end=4447, +) + + +_TESTREQUIRED = _descriptor.Descriptor( + name='TestRequired', + full_name='protobuf_unittest.TestRequired', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestRequired.a', index=0, + number=1, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy2', full_name='protobuf_unittest.TestRequired.dummy2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestRequired.b', index=2, + number=3, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy4', full_name='protobuf_unittest.TestRequired.dummy4', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy5', full_name='protobuf_unittest.TestRequired.dummy5', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy6', full_name='protobuf_unittest.TestRequired.dummy6', index=5, + number=6, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy7', full_name='protobuf_unittest.TestRequired.dummy7', index=6, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy8', full_name='protobuf_unittest.TestRequired.dummy8', index=7, + number=8, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy9', full_name='protobuf_unittest.TestRequired.dummy9', index=8, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy10', full_name='protobuf_unittest.TestRequired.dummy10', index=9, + number=10, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy11', full_name='protobuf_unittest.TestRequired.dummy11', index=10, + number=11, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy12', full_name='protobuf_unittest.TestRequired.dummy12', index=11, + number=12, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy13', full_name='protobuf_unittest.TestRequired.dummy13', index=12, + number=13, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy14', full_name='protobuf_unittest.TestRequired.dummy14', index=13, + number=14, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy15', full_name='protobuf_unittest.TestRequired.dummy15', index=14, + number=15, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy16', full_name='protobuf_unittest.TestRequired.dummy16', index=15, + number=16, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy17', full_name='protobuf_unittest.TestRequired.dummy17', index=16, + number=17, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy18', full_name='protobuf_unittest.TestRequired.dummy18', index=17, + number=18, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy19', full_name='protobuf_unittest.TestRequired.dummy19', index=18, + number=19, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy20', full_name='protobuf_unittest.TestRequired.dummy20', index=19, + number=20, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy21', full_name='protobuf_unittest.TestRequired.dummy21', index=20, + number=21, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy22', full_name='protobuf_unittest.TestRequired.dummy22', index=21, + number=22, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy23', full_name='protobuf_unittest.TestRequired.dummy23', index=22, + number=23, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy24', full_name='protobuf_unittest.TestRequired.dummy24', index=23, + number=24, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy25', full_name='protobuf_unittest.TestRequired.dummy25', index=24, + number=25, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy26', full_name='protobuf_unittest.TestRequired.dummy26', index=25, + number=26, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy27', full_name='protobuf_unittest.TestRequired.dummy27', index=26, + number=27, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy28', full_name='protobuf_unittest.TestRequired.dummy28', index=27, + number=28, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy29', full_name='protobuf_unittest.TestRequired.dummy29', index=28, + number=29, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy30', full_name='protobuf_unittest.TestRequired.dummy30', index=29, + number=30, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy31', full_name='protobuf_unittest.TestRequired.dummy31', index=30, + number=31, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy32', full_name='protobuf_unittest.TestRequired.dummy32', index=31, + number=32, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.TestRequired.c', index=32, + number=33, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='single', full_name='protobuf_unittest.TestRequired.single', index=0, + number=1000, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='multi', full_name='protobuf_unittest.TestRequired.multi', index=1, + number=1001, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4450, + serialized_end=5175, +) + + +_TESTREQUIREDFOREIGN = _descriptor.Descriptor( + name='TestRequiredForeign', + full_name='protobuf_unittest.TestRequiredForeign', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest.TestRequiredForeign.optional_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_message', full_name='protobuf_unittest.TestRequiredForeign.repeated_message', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dummy', full_name='protobuf_unittest.TestRequiredForeign.dummy', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5178, + serialized_end=5332, +) + + +_TESTREQUIREDMESSAGE = _descriptor.Descriptor( + name='TestRequiredMessage', + full_name='protobuf_unittest.TestRequiredMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest.TestRequiredMessage.optional_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_message', full_name='protobuf_unittest.TestRequiredMessage.repeated_message', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='required_message', full_name='protobuf_unittest.TestRequiredMessage.required_message', index=2, + number=3, type=11, cpp_type=10, label=2, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5335, + serialized_end=5533, +) + + +_TESTFOREIGNNESTED = _descriptor.Descriptor( + name='TestForeignNested', + full_name='protobuf_unittest.TestForeignNested', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foreign_nested', full_name='protobuf_unittest.TestForeignNested.foreign_nested', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5535, + serialized_end=5625, +) + + +_TESTEMPTYMESSAGE = _descriptor.Descriptor( + name='TestEmptyMessage', + full_name='protobuf_unittest.TestEmptyMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5627, + serialized_end=5645, +) + + +_TESTEMPTYMESSAGEWITHEXTENSIONS = _descriptor.Descriptor( + name='TestEmptyMessageWithExtensions', + full_name='protobuf_unittest.TestEmptyMessageWithExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=5647, + serialized_end=5689, +) + + +_TESTMULTIPLEEXTENSIONRANGES = _descriptor.Descriptor( + name='TestMultipleExtensionRanges', + full_name='protobuf_unittest.TestMultipleExtensionRanges', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(42, 43), (4143, 4244), (65536, 536870912), ], + oneofs=[ + ], + serialized_start=5691, + serialized_end=5746, +) + + +_TESTREALLYLARGETAGNUMBER = _descriptor.Descriptor( + name='TestReallyLargeTagNumber', + full_name='protobuf_unittest.TestReallyLargeTagNumber', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestReallyLargeTagNumber.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestReallyLargeTagNumber.bb', index=1, + number=268435455, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5748, + serialized_end=5800, +) + + +_TESTRECURSIVEMESSAGE = _descriptor.Descriptor( + name='TestRecursiveMessage', + full_name='protobuf_unittest.TestRecursiveMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestRecursiveMessage.a', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.TestRecursiveMessage.i', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5802, + serialized_end=5887, +) + + +_TESTMUTUALRECURSIONA_SUBMESSAGE = _descriptor.Descriptor( + name='SubMessage', + full_name='protobuf_unittest.TestMutualRecursionA.SubMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestMutualRecursionA.SubMessage.b', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6035, + serialized_end=6099, +) + +_TESTMUTUALRECURSIONA_SUBGROUP = _descriptor.Descriptor( + name='SubGroup', + full_name='protobuf_unittest.TestMutualRecursionA.SubGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestMutualRecursionA.SubGroup.sub_message', index=0, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='not_in_this_scc', full_name='protobuf_unittest.TestMutualRecursionA.SubGroup.not_in_this_scc', index=1, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6102, + serialized_end=6243, +) + +_TESTMUTUALRECURSIONA = _descriptor.Descriptor( + name='TestMutualRecursionA', + full_name='protobuf_unittest.TestMutualRecursionA', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestMutualRecursionA.bb', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='subgroup', full_name='protobuf_unittest.TestMutualRecursionA.subgroup', index=1, + number=2, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMUTUALRECURSIONA_SUBMESSAGE, _TESTMUTUALRECURSIONA_SUBGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5890, + serialized_end=6243, +) + + +_TESTMUTUALRECURSIONB = _descriptor.Descriptor( + name='TestMutualRecursionB', + full_name='protobuf_unittest.TestMutualRecursionB', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestMutualRecursionB.a', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest.TestMutualRecursionB.optional_int32', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6245, + serialized_end=6343, +) + + +_TESTISINITIALIZED_SUBMESSAGE_SUBGROUP = _descriptor.Descriptor( + name='SubGroup', + full_name='protobuf_unittest.TestIsInitialized.SubMessage.SubGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='i', full_name='protobuf_unittest.TestIsInitialized.SubMessage.SubGroup.i', index=0, + number=2, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6527, + serialized_end=6548, +) + +_TESTISINITIALIZED_SUBMESSAGE = _descriptor.Descriptor( + name='SubMessage', + full_name='protobuf_unittest.TestIsInitialized.SubMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='subgroup', full_name='protobuf_unittest.TestIsInitialized.SubMessage.subgroup', index=0, + number=1, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTISINITIALIZED_SUBMESSAGE_SUBGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6437, + serialized_end=6548, +) + +_TESTISINITIALIZED = _descriptor.Descriptor( + name='TestIsInitialized', + full_name='protobuf_unittest.TestIsInitialized', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestIsInitialized.sub_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTISINITIALIZED_SUBMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6346, + serialized_end=6548, +) + + +_TESTDUPFIELDNUMBER_FOO = _descriptor.Descriptor( + name='Foo', + full_name='protobuf_unittest.TestDupFieldNumber.Foo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestDupFieldNumber.Foo.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6696, + serialized_end=6712, +) + +_TESTDUPFIELDNUMBER_BAR = _descriptor.Descriptor( + name='Bar', + full_name='protobuf_unittest.TestDupFieldNumber.Bar', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestDupFieldNumber.Bar.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6714, + serialized_end=6730, +) + +_TESTDUPFIELDNUMBER = _descriptor.Descriptor( + name='TestDupFieldNumber', + full_name='protobuf_unittest.TestDupFieldNumber', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestDupFieldNumber.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo', full_name='protobuf_unittest.TestDupFieldNumber.foo', index=1, + number=2, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar', full_name='protobuf_unittest.TestDupFieldNumber.bar', index=2, + number=3, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTDUPFIELDNUMBER_FOO, _TESTDUPFIELDNUMBER_BAR, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6551, + serialized_end=6730, +) + + +_TESTEAGERMESSAGE = _descriptor.Descriptor( + name='TestEagerMessage', + full_name='protobuf_unittest.TestEagerMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestEagerMessage.sub_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6732, + serialized_end=6808, +) + + +_TESTLAZYMESSAGE = _descriptor.Descriptor( + name='TestLazyMessage', + full_name='protobuf_unittest.TestLazyMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sub_message', full_name='protobuf_unittest.TestLazyMessage.sub_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6810, + serialized_end=6885, +) + + +_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestNestedMessageHasBits.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='nestedmessage_repeated_int32', full_name='protobuf_unittest.TestNestedMessageHasBits.NestedMessage.nestedmessage_repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nestedmessage_repeated_foreignmessage', full_name='protobuf_unittest.TestNestedMessageHasBits.NestedMessage.nestedmessage_repeated_foreignmessage', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7009, + serialized_end=7144, +) + +_TESTNESTEDMESSAGEHASBITS = _descriptor.Descriptor( + name='TestNestedMessageHasBits', + full_name='protobuf_unittest.TestNestedMessageHasBits', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest.TestNestedMessageHasBits.optional_nested_message', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=6888, + serialized_end=7144, +) + + +_TESTCAMELCASEFIELDNAMES = _descriptor.Descriptor( + name='TestCamelCaseFieldNames', + full_name='protobuf_unittest.TestCamelCaseFieldNames', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='PrimitiveField', full_name='protobuf_unittest.TestCamelCaseFieldNames.PrimitiveField', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='StringField', full_name='protobuf_unittest.TestCamelCaseFieldNames.StringField', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='EnumField', full_name='protobuf_unittest.TestCamelCaseFieldNames.EnumField', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='MessageField', full_name='protobuf_unittest.TestCamelCaseFieldNames.MessageField', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='StringPieceField', full_name='protobuf_unittest.TestCamelCaseFieldNames.StringPieceField', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='CordField', full_name='protobuf_unittest.TestCamelCaseFieldNames.CordField', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedPrimitiveField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedPrimitiveField', index=6, + number=7, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedStringField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedStringField', index=7, + number=8, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedEnumField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedEnumField', index=8, + number=9, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedMessageField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedMessageField', index=9, + number=10, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedStringPieceField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedStringPieceField', index=10, + number=11, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='RepeatedCordField', full_name='protobuf_unittest.TestCamelCaseFieldNames.RepeatedCordField', index=11, + number=12, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7147, + serialized_end=7632, +) + + +_TESTFIELDORDERINGS_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestFieldOrderings.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='oo', full_name='protobuf_unittest.TestFieldOrderings.NestedMessage.oo', index=0, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bb', full_name='protobuf_unittest.TestFieldOrderings.NestedMessage.bb', index=1, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7797, + serialized_end=7836, +) + +_TESTFIELDORDERINGS = _descriptor.Descriptor( + name='TestFieldOrderings', + full_name='protobuf_unittest.TestFieldOrderings', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestFieldOrderings.my_string', index=0, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='my_int', full_name='protobuf_unittest.TestFieldOrderings.my_int', index=1, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='my_float', full_name='protobuf_unittest.TestFieldOrderings.my_float', index=2, + number=101, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='protobuf_unittest.TestFieldOrderings.optional_nested_message', index=3, + number=200, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTFIELDORDERINGS_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(2, 11), (12, 101), ], + oneofs=[ + ], + serialized_start=7635, + serialized_end=7848, +) + + +_TESTEXTENSIONORDERINGS1 = _descriptor.Descriptor( + name='TestExtensionOrderings1', + full_name='protobuf_unittest.TestExtensionOrderings1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestExtensionOrderings1.my_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test_ext_orderings1', full_name='protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1', index=0, + number=13, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=7851, + serialized_end=8007, +) + + +_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3 = _descriptor.Descriptor( + name='TestExtensionOrderings3', + full_name='protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.my_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test_ext_orderings3', full_name='protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.test_ext_orderings3', index=0, + number=14, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8057, + serialized_end=8238, +) + +_TESTEXTENSIONORDERINGS2 = _descriptor.Descriptor( + name='TestExtensionOrderings2', + full_name='protobuf_unittest.TestExtensionOrderings2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='my_string', full_name='protobuf_unittest.TestExtensionOrderings2.my_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='test_ext_orderings2', full_name='protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2', index=0, + number=12, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8010, + serialized_end=8350, +) + + +_TESTEXTREMEDEFAULTVALUES = _descriptor.Descriptor( + name='TestExtremeDefaultValues', + full_name='protobuf_unittest.TestExtremeDefaultValues', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='escaped_bytes', full_name='protobuf_unittest.TestExtremeDefaultValues.escaped_bytes', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("\000\001\007\010\014\n\r\t\013\\\'\"\376"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='large_uint32', full_name='protobuf_unittest.TestExtremeDefaultValues.large_uint32', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=True, default_value=4294967295, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='large_uint64', full_name='protobuf_unittest.TestExtremeDefaultValues.large_uint64', index=2, + number=3, type=4, cpp_type=4, label=1, + has_default_value=True, default_value=18446744073709551615, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_int32', full_name='protobuf_unittest.TestExtremeDefaultValues.small_int32', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=-2147483647, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_int64', full_name='protobuf_unittest.TestExtremeDefaultValues.small_int64', index=4, + number=5, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=-9223372036854775807, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='really_small_int32', full_name='protobuf_unittest.TestExtremeDefaultValues.really_small_int32', index=5, + number=21, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=-2147483648, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='really_small_int64', full_name='protobuf_unittest.TestExtremeDefaultValues.really_small_int64', index=6, + number=22, type=3, cpp_type=2, label=1, + has_default_value=True, default_value=-9223372036854775808, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='utf8_string', full_name='protobuf_unittest.TestExtremeDefaultValues.utf8_string', index=7, + number=6, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("\341\210\264").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='zero_float', full_name='protobuf_unittest.TestExtremeDefaultValues.zero_float', index=8, + number=7, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='one_float', full_name='protobuf_unittest.TestExtremeDefaultValues.one_float', index=9, + number=8, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(1), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_float', full_name='protobuf_unittest.TestExtremeDefaultValues.small_float', index=10, + number=9, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(1.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='negative_one_float', full_name='protobuf_unittest.TestExtremeDefaultValues.negative_one_float', index=11, + number=10, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(-1), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='negative_float', full_name='protobuf_unittest.TestExtremeDefaultValues.negative_float', index=12, + number=11, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(-1.5), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='large_float', full_name='protobuf_unittest.TestExtremeDefaultValues.large_float', index=13, + number=12, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(2e+08), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='small_negative_float', full_name='protobuf_unittest.TestExtremeDefaultValues.small_negative_float', index=14, + number=13, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=float(-8e-28), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='inf_double', full_name='protobuf_unittest.TestExtremeDefaultValues.inf_double', index=15, + number=14, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='neg_inf_double', full_name='protobuf_unittest.TestExtremeDefaultValues.neg_inf_double', index=16, + number=15, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=-1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nan_double', full_name='protobuf_unittest.TestExtremeDefaultValues.nan_double', index=17, + number=16, type=1, cpp_type=5, label=1, + has_default_value=True, default_value=(1e10000 * 0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='inf_float', full_name='protobuf_unittest.TestExtremeDefaultValues.inf_float', index=18, + number=17, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='neg_inf_float', full_name='protobuf_unittest.TestExtremeDefaultValues.neg_inf_float', index=19, + number=18, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=-1e10000, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='nan_float', full_name='protobuf_unittest.TestExtremeDefaultValues.nan_float', index=20, + number=19, type=2, cpp_type=6, label=1, + has_default_value=True, default_value=(1e10000 * 0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cpp_trigraph', full_name='protobuf_unittest.TestExtremeDefaultValues.cpp_trigraph', index=21, + number=20, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("? ? ?? ?? ??? ??/ ??-").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.string_with_zero', index=22, + number=23, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("hel\000lo").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.bytes_with_zero', index=23, + number=24, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("wor\000ld"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_piece_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.string_piece_with_zero', index=24, + number=25, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("ab\000c").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='cord_with_zero', full_name='protobuf_unittest.TestExtremeDefaultValues.cord_with_zero', index=25, + number=26, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("12\0003").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='replacement_string', full_name='protobuf_unittest.TestExtremeDefaultValues.replacement_string', index=26, + number=27, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("${unknown}").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=8353, + serialized_end=9303, +) + + +_SPARSEENUMMESSAGE = _descriptor.Descriptor( + name='SparseEnumMessage', + full_name='protobuf_unittest.SparseEnumMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='sparse_enum', full_name='protobuf_unittest.SparseEnumMessage.sparse_enum', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=123, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9305, + serialized_end=9380, +) + + +_ONESTRING = _descriptor.Descriptor( + name='OneString', + full_name='protobuf_unittest.OneString', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.OneString.data', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9382, + serialized_end=9407, +) + + +_MORESTRING = _descriptor.Descriptor( + name='MoreString', + full_name='protobuf_unittest.MoreString', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.MoreString.data', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9409, + serialized_end=9435, +) + + +_ONEBYTES = _descriptor.Descriptor( + name='OneBytes', + full_name='protobuf_unittest.OneBytes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.OneBytes.data', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9437, + serialized_end=9461, +) + + +_MOREBYTES = _descriptor.Descriptor( + name='MoreBytes', + full_name='protobuf_unittest.MoreBytes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.MoreBytes.data', index=0, + number=1, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9463, + serialized_end=9488, +) + + +_INT32MESSAGE = _descriptor.Descriptor( + name='Int32Message', + full_name='protobuf_unittest.Int32Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Int32Message.data', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9490, + serialized_end=9518, +) + + +_UINT32MESSAGE = _descriptor.Descriptor( + name='Uint32Message', + full_name='protobuf_unittest.Uint32Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Uint32Message.data', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9520, + serialized_end=9549, +) + + +_INT64MESSAGE = _descriptor.Descriptor( + name='Int64Message', + full_name='protobuf_unittest.Int64Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Int64Message.data', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9551, + serialized_end=9579, +) + + +_UINT64MESSAGE = _descriptor.Descriptor( + name='Uint64Message', + full_name='protobuf_unittest.Uint64Message', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.Uint64Message.data', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9581, + serialized_end=9610, +) + + +_BOOLMESSAGE = _descriptor.Descriptor( + name='BoolMessage', + full_name='protobuf_unittest.BoolMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='protobuf_unittest.BoolMessage.data', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9612, + serialized_end=9639, +) + + +_TESTONEOF_FOOGROUP = _descriptor.Descriptor( + name='FooGroup', + full_name='protobuf_unittest.TestOneof.FooGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestOneof.FooGroup.a', index=0, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestOneof.FooGroup.b', index=1, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9811, + serialized_end=9843, +) + +_TESTONEOF = _descriptor.Descriptor( + name='TestOneof', + full_name='protobuf_unittest.TestOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestOneof.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestOneof.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestOneof.foo_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foogroup', full_name='protobuf_unittest.TestOneof.foogroup', index=3, + number=4, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTONEOF_FOOGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='foo', full_name='protobuf_unittest.TestOneof.foo', + index=0, containing_type=None, fields=[]), + ], + serialized_start=9642, + serialized_end=9850, +) + + +_TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP = _descriptor.Descriptor( + name='FooGroup', + full_name='protobuf_unittest.TestOneofBackwardsCompatible.FooGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestOneofBackwardsCompatible.FooGroup.a', index=0, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestOneofBackwardsCompatible.FooGroup.b', index=1, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9811, + serialized_end=9843, +) + +_TESTONEOFBACKWARDSCOMPATIBLE = _descriptor.Descriptor( + name='TestOneofBackwardsCompatible', + full_name='protobuf_unittest.TestOneofBackwardsCompatible', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foo_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foogroup', full_name='protobuf_unittest.TestOneofBackwardsCompatible.foogroup', index=3, + number=4, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9853, + serialized_end=10084, +) + + +_TESTONEOF2_FOOGROUP = _descriptor.Descriptor( + name='FooGroup', + full_name='protobuf_unittest.TestOneof2.FooGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestOneof2.FooGroup.a', index=0, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestOneof2.FooGroup.b', index=1, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10745, + serialized_end=10777, +) + +_TESTONEOF2_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestOneof2.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='qux_int', full_name='protobuf_unittest.TestOneof2.NestedMessage.qux_int', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='corge_int', full_name='protobuf_unittest.TestOneof2.NestedMessage.corge_int', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=10779, + serialized_end=10830, +) + +_TESTONEOF2 = _descriptor.Descriptor( + name='TestOneof2', + full_name='protobuf_unittest.TestOneof2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestOneof2.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestOneof2.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_cord', full_name='protobuf_unittest.TestOneof2.foo_cord', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string_piece', full_name='protobuf_unittest.TestOneof2.foo_string_piece', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_bytes', full_name='protobuf_unittest.TestOneof2.foo_bytes', index=4, + number=5, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_enum', full_name='protobuf_unittest.TestOneof2.foo_enum', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestOneof2.foo_message', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foogroup', full_name='protobuf_unittest.TestOneof2.foogroup', index=7, + number=8, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_lazy_message', full_name='protobuf_unittest.TestOneof2.foo_lazy_message', index=8, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_int', full_name='protobuf_unittest.TestOneof2.bar_int', index=9, + number=12, type=5, cpp_type=1, label=1, + has_default_value=True, default_value=5, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_string', full_name='protobuf_unittest.TestOneof2.bar_string', index=10, + number=13, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("STRING").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_cord', full_name='protobuf_unittest.TestOneof2.bar_cord', index=11, + number=14, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("CORD").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_string_piece', full_name='protobuf_unittest.TestOneof2.bar_string_piece', index=12, + number=15, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("SPIECE").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_bytes', full_name='protobuf_unittest.TestOneof2.bar_bytes', index=13, + number=16, type=12, cpp_type=9, label=1, + has_default_value=True, default_value=_b("BYTES"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bar_enum', full_name='protobuf_unittest.TestOneof2.bar_enum', index=14, + number=17, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=2, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='baz_int', full_name='protobuf_unittest.TestOneof2.baz_int', index=15, + number=18, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='baz_string', full_name='protobuf_unittest.TestOneof2.baz_string', index=16, + number=19, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("BAZ").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTONEOF2_FOOGROUP, _TESTONEOF2_NESTEDMESSAGE, ], + enum_types=[ + _TESTONEOF2_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='foo', full_name='protobuf_unittest.TestOneof2.foo', + index=0, containing_type=None, fields=[]), + _descriptor.OneofDescriptor( + name='bar', full_name='protobuf_unittest.TestOneof2.bar', + index=1, containing_type=None, fields=[]), + ], + serialized_start=10087, + serialized_end=10885, +) + + +_TESTREQUIREDONEOF_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='protobuf_unittest.TestRequiredOneof.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='required_double', full_name='protobuf_unittest.TestRequiredOneof.NestedMessage.required_double', index=0, + number=1, type=1, cpp_type=5, label=2, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11025, + serialized_end=11065, +) + +_TESTREQUIREDONEOF = _descriptor.Descriptor( + name='TestRequiredOneof', + full_name='protobuf_unittest.TestRequiredOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='foo_int', full_name='protobuf_unittest.TestRequiredOneof.foo_int', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_string', full_name='protobuf_unittest.TestRequiredOneof.foo_string', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='foo_message', full_name='protobuf_unittest.TestRequiredOneof.foo_message', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTREQUIREDONEOF_NESTEDMESSAGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='foo', full_name='protobuf_unittest.TestRequiredOneof.foo', + index=0, containing_type=None, fields=[]), + ], + serialized_start=10888, + serialized_end=11072, +) + + +_TESTPACKEDTYPES = _descriptor.Descriptor( + name='TestPackedTypes', + full_name='protobuf_unittest.TestPackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='packed_int32', full_name='protobuf_unittest.TestPackedTypes.packed_int32', index=0, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_int64', full_name='protobuf_unittest.TestPackedTypes.packed_int64', index=1, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint32', full_name='protobuf_unittest.TestPackedTypes.packed_uint32', index=2, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint64', full_name='protobuf_unittest.TestPackedTypes.packed_uint64', index=3, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint32', full_name='protobuf_unittest.TestPackedTypes.packed_sint32', index=4, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint64', full_name='protobuf_unittest.TestPackedTypes.packed_sint64', index=5, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed32', full_name='protobuf_unittest.TestPackedTypes.packed_fixed32', index=6, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed64', full_name='protobuf_unittest.TestPackedTypes.packed_fixed64', index=7, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed32', full_name='protobuf_unittest.TestPackedTypes.packed_sfixed32', index=8, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed64', full_name='protobuf_unittest.TestPackedTypes.packed_sfixed64', index=9, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_float', full_name='protobuf_unittest.TestPackedTypes.packed_float', index=10, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_double', full_name='protobuf_unittest.TestPackedTypes.packed_double', index=11, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_bool', full_name='protobuf_unittest.TestPackedTypes.packed_bool', index=12, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='protobuf_unittest.TestPackedTypes.packed_enum', index=13, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11075, + serialized_end=11501, +) + + +_TESTUNPACKEDTYPES = _descriptor.Descriptor( + name='TestUnpackedTypes', + full_name='protobuf_unittest.TestUnpackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='unpacked_int32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_int32', index=0, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_int64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_int64', index=1, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_uint32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_uint32', index=2, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_uint64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_uint64', index=3, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sint32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sint32', index=4, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sint64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sint64', index=5, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_fixed32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_fixed32', index=6, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_fixed64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_fixed64', index=7, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sfixed32', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sfixed32', index=8, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_sfixed64', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_sfixed64', index=9, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_float', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_float', index=10, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_double', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_double', index=11, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_bool', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_bool', index=12, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unpacked_enum', full_name='protobuf_unittest.TestUnpackedTypes.unpacked_enum', index=13, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=11504, + serialized_end=11960, +) + + +_TESTPACKEDEXTENSIONS = _descriptor.Descriptor( + name='TestPackedExtensions', + full_name='protobuf_unittest.TestPackedExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=11962, + serialized_end=11994, +) + + +_TESTUNPACKEDEXTENSIONS = _descriptor.Descriptor( + name='TestUnpackedExtensions', + full_name='protobuf_unittest.TestUnpackedExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1, 536870912), ], + oneofs=[ + ], + serialized_start=11996, + serialized_end=12030, +) + + +_TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE = _descriptor.Descriptor( + name='DynamicMessageType', + full_name='protobuf_unittest.TestDynamicExtensions.DynamicMessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='dynamic_field', full_name='protobuf_unittest.TestDynamicExtensions.DynamicMessageType.dynamic_field', index=0, + number=2100, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12453, + serialized_end=12497, +) + +_TESTDYNAMICEXTENSIONS = _descriptor.Descriptor( + name='TestDynamicExtensions', + full_name='protobuf_unittest.TestDynamicExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='scalar_extension', full_name='protobuf_unittest.TestDynamicExtensions.scalar_extension', index=0, + number=2000, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_extension', full_name='protobuf_unittest.TestDynamicExtensions.enum_extension', index=1, + number=2001, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dynamic_enum_extension', full_name='protobuf_unittest.TestDynamicExtensions.dynamic_enum_extension', index=2, + number=2002, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=2200, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_extension', full_name='protobuf_unittest.TestDynamicExtensions.message_extension', index=3, + number=2003, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dynamic_message_extension', full_name='protobuf_unittest.TestDynamicExtensions.dynamic_message_extension', index=4, + number=2004, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_extension', full_name='protobuf_unittest.TestDynamicExtensions.repeated_extension', index=5, + number=2005, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_extension', full_name='protobuf_unittest.TestDynamicExtensions.packed_extension', index=6, + number=2006, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE, ], + enum_types=[ + _TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12033, + serialized_end=12570, +) + + +_TESTREPEATEDSCALARDIFFERENTTAGSIZES = _descriptor.Descriptor( + name='TestRepeatedScalarDifferentTagSizes', + full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_fixed32', index=0, + number=12, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_int32', index=1, + number=13, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_fixed64', index=2, + number=2046, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_int64', index=3, + number=2047, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_float', index=4, + number=262142, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='protobuf_unittest.TestRepeatedScalarDifferentTagSizes.repeated_uint64', index=5, + number=262143, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=12573, + serialized_end=12765, +) + + +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1 = _descriptor.Descriptor( + name='Group1', + full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1.field1', index=0, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13558, + serialized_end=13615, +) + +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2 = _descriptor.Descriptor( + name='Group2', + full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2.field1', index=0, + number=21, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13617, + serialized_end=13674, +) + +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR = _descriptor.Descriptor( + name='RepeatedFieldsGenerator', + full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.field1', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field2', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.field2', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field3', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.field3', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='group1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.group1', index=3, + number=10, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='group2', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.group2', index=4, + number=20, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ext1', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.ext1', index=5, + number=1000, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='ext2', full_name='protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.ext2', index=6, + number=1001, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1, _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13120, + serialized_end=13674, +) + +_TESTPARSINGMERGE_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestParsingMerge.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_group_all_types', full_name='protobuf_unittest.TestParsingMerge.OptionalGroup.optional_group_all_types', index=0, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13676, + serialized_end=13758, +) + +_TESTPARSINGMERGE_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest.TestParsingMerge.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_group_all_types', full_name='protobuf_unittest.TestParsingMerge.RepeatedGroup.repeated_group_all_types', index=0, + number=21, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13760, + serialized_end=13842, +) + +_TESTPARSINGMERGE = _descriptor.Descriptor( + name='TestParsingMerge', + full_name='protobuf_unittest.TestParsingMerge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='required_all_types', full_name='protobuf_unittest.TestParsingMerge.required_all_types', index=0, + number=1, type=11, cpp_type=10, label=2, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_all_types', full_name='protobuf_unittest.TestParsingMerge.optional_all_types', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_all_types', full_name='protobuf_unittest.TestParsingMerge.repeated_all_types', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestParsingMerge.optionalgroup', index=3, + number=10, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest.TestParsingMerge.repeatedgroup', index=4, + number=20, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='optional_ext', full_name='protobuf_unittest.TestParsingMerge.optional_ext', index=0, + number=1000, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_ext', full_name='protobuf_unittest.TestParsingMerge.repeated_ext', index=1, + number=1001, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + nested_types=[_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR, _TESTPARSINGMERGE_OPTIONALGROUP, _TESTPARSINGMERGE_REPEATEDGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=12768, + serialized_end=14039, +) + + +_TESTCOMMENTINJECTIONMESSAGE = _descriptor.Descriptor( + name='TestCommentInjectionMessage', + full_name='protobuf_unittest.TestCommentInjectionMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestCommentInjectionMessage.a', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("*/ <- Neither should this.").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14041, + serialized_end=14109, +) + + +_FOOREQUEST = _descriptor.Descriptor( + name='FooRequest', + full_name='protobuf_unittest.FooRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14111, + serialized_end=14123, +) + + +_FOORESPONSE = _descriptor.Descriptor( + name='FooResponse', + full_name='protobuf_unittest.FooResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14125, + serialized_end=14138, +) + + +_FOOCLIENTMESSAGE = _descriptor.Descriptor( + name='FooClientMessage', + full_name='protobuf_unittest.FooClientMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14140, + serialized_end=14158, +) + + +_FOOSERVERMESSAGE = _descriptor.Descriptor( + name='FooServerMessage', + full_name='protobuf_unittest.FooServerMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14160, + serialized_end=14178, +) + + +_BARREQUEST = _descriptor.Descriptor( + name='BarRequest', + full_name='protobuf_unittest.BarRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14180, + serialized_end=14192, +) + + +_BARRESPONSE = _descriptor.Descriptor( + name='BarResponse', + full_name='protobuf_unittest.BarResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14194, + serialized_end=14207, +) + + +_TESTJSONNAME = _descriptor.Descriptor( + name='TestJsonName', + full_name='protobuf_unittest.TestJsonName', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field_name1', full_name='protobuf_unittest.TestJsonName.field_name1', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fieldName2', full_name='protobuf_unittest.TestJsonName.fieldName2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FieldName3', full_name='protobuf_unittest.TestJsonName.FieldName3', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='_field_name4', full_name='protobuf_unittest.TestJsonName._field_name4', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='FIELD_NAME5', full_name='protobuf_unittest.TestJsonName.FIELD_NAME5', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field_name6', full_name='protobuf_unittest.TestJsonName.field_name6', index=5, + number=6, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='@type', file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=14210, + serialized_end=14356, +) + + +_TESTHUGEFIELDNUMBERS_OPTIONALGROUP = _descriptor.Descriptor( + name='OptionalGroup', + full_name='protobuf_unittest.TestHugeFieldNumbers.OptionalGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='group_a', full_name='protobuf_unittest.TestHugeFieldNumbers.OptionalGroup.group_a', index=0, + number=536870009, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15003, + serialized_end=15039, +) + +_TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY = _descriptor.Descriptor( + name='StringStringMapEntry', + full_name='protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15041, + serialized_end=15095, +) + +_TESTHUGEFIELDNUMBERS = _descriptor.Descriptor( + name='TestHugeFieldNumbers', + full_name='protobuf_unittest.TestHugeFieldNumbers', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_int32', index=0, + number=536870000, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fixed_32', full_name='protobuf_unittest.TestHugeFieldNumbers.fixed_32', index=1, + number=536870001, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='protobuf_unittest.TestHugeFieldNumbers.repeated_int32', index=2, + number=536870002, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_int32', full_name='protobuf_unittest.TestHugeFieldNumbers.packed_int32', index=3, + number=536870003, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_enum', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_enum', index=4, + number=536870004, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=4, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_string', index=5, + number=536870005, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_bytes', index=6, + number=536870006, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_message', full_name='protobuf_unittest.TestHugeFieldNumbers.optional_message', index=7, + number=536870007, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optionalgroup', full_name='protobuf_unittest.TestHugeFieldNumbers.optionalgroup', index=8, + number=536870008, type=10, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_string_map', full_name='protobuf_unittest.TestHugeFieldNumbers.string_string_map', index=9, + number=536870010, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_uint32', index=10, + number=536870011, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_test_all_types', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_test_all_types', index=11, + number=536870012, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_string', index=12, + number=536870013, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_bytes', index=13, + number=536870014, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTHUGEFIELDNUMBERS_OPTIONALGROUP, _TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(536860000, 536870000), ], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='protobuf_unittest.TestHugeFieldNumbers.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=14359, + serialized_end=15124, +) + + +_TESTEXTENSIONINSIDETABLE = _descriptor.Descriptor( + name='TestExtensionInsideTable', + full_name='protobuf_unittest.TestExtensionInsideTable', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='field1', full_name='protobuf_unittest.TestExtensionInsideTable.field1', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field2', full_name='protobuf_unittest.TestExtensionInsideTable.field2', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field3', full_name='protobuf_unittest.TestExtensionInsideTable.field3', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field4', full_name='protobuf_unittest.TestExtensionInsideTable.field4', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field6', full_name='protobuf_unittest.TestExtensionInsideTable.field6', index=4, + number=6, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field7', full_name='protobuf_unittest.TestExtensionInsideTable.field7', index=5, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field8', full_name='protobuf_unittest.TestExtensionInsideTable.field8', index=6, + number=8, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field9', full_name='protobuf_unittest.TestExtensionInsideTable.field9', index=7, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='field10', full_name='protobuf_unittest.TestExtensionInsideTable.field10', index=8, + number=10, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(5, 6), ], + oneofs=[ + ], + serialized_start=15127, + serialized_end=15304, +) + +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES_OPTIONALGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES_REPEATEDGROUP.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['optionalgroup'].message_type = _TESTALLTYPES_OPTIONALGROUP +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['optional_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['optional_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['optional_public_import_message'].message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeatedgroup'].message_type = _TESTALLTYPES_REPEATEDGROUP +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['repeated_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['repeated_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['repeated_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['default_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['default_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['default_import_enum'].enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +_TESTALLTYPES.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES_NESTEDENUM.containing_type = _TESTALLTYPES +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_uint32']) +_TESTALLTYPES.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_nested_message']) +_TESTALLTYPES.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_string']) +_TESTALLTYPES.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_bytes']) +_TESTALLTYPES.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_NESTEDTESTALLTYPES.fields_by_name['child'].message_type = _NESTEDTESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['payload'].message_type = _TESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['repeated_child'].message_type = _NESTEDTESTALLTYPES +_TESTDEPRECATEDFIELDS.oneofs_by_name['oneof_fields'].fields.append( + _TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32_in_oneof']) +_TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32_in_oneof'].containing_oneof = _TESTDEPRECATEDFIELDS.oneofs_by_name['oneof_fields'] +_TESTGROUP_OPTIONALGROUP.containing_type = _TESTGROUP +_TESTGROUP.fields_by_name['optionalgroup'].message_type = _TESTGROUP_OPTIONALGROUP +_TESTGROUP.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION.containing_type = _TESTNESTEDEXTENSION +_TESTREQUIREDFOREIGN.fields_by_name['optional_message'].message_type = _TESTREQUIRED +_TESTREQUIREDFOREIGN.fields_by_name['repeated_message'].message_type = _TESTREQUIRED +_TESTREQUIREDMESSAGE.fields_by_name['optional_message'].message_type = _TESTREQUIRED +_TESTREQUIREDMESSAGE.fields_by_name['repeated_message'].message_type = _TESTREQUIRED +_TESTREQUIREDMESSAGE.fields_by_name['required_message'].message_type = _TESTREQUIRED +_TESTFOREIGNNESTED.fields_by_name['foreign_nested'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTRECURSIVEMESSAGE.fields_by_name['a'].message_type = _TESTRECURSIVEMESSAGE +_TESTMUTUALRECURSIONA_SUBMESSAGE.fields_by_name['b'].message_type = _TESTMUTUALRECURSIONB +_TESTMUTUALRECURSIONA_SUBMESSAGE.containing_type = _TESTMUTUALRECURSIONA +_TESTMUTUALRECURSIONA_SUBGROUP.fields_by_name['sub_message'].message_type = _TESTMUTUALRECURSIONA_SUBMESSAGE +_TESTMUTUALRECURSIONA_SUBGROUP.fields_by_name['not_in_this_scc'].message_type = _TESTALLTYPES +_TESTMUTUALRECURSIONA_SUBGROUP.containing_type = _TESTMUTUALRECURSIONA +_TESTMUTUALRECURSIONA.fields_by_name['bb'].message_type = _TESTMUTUALRECURSIONB +_TESTMUTUALRECURSIONA.fields_by_name['subgroup'].message_type = _TESTMUTUALRECURSIONA_SUBGROUP +_TESTMUTUALRECURSIONB.fields_by_name['a'].message_type = _TESTMUTUALRECURSIONA +_TESTISINITIALIZED_SUBMESSAGE_SUBGROUP.containing_type = _TESTISINITIALIZED_SUBMESSAGE +_TESTISINITIALIZED_SUBMESSAGE.fields_by_name['subgroup'].message_type = _TESTISINITIALIZED_SUBMESSAGE_SUBGROUP +_TESTISINITIALIZED_SUBMESSAGE.containing_type = _TESTISINITIALIZED +_TESTISINITIALIZED.fields_by_name['sub_message'].message_type = _TESTISINITIALIZED_SUBMESSAGE +_TESTDUPFIELDNUMBER_FOO.containing_type = _TESTDUPFIELDNUMBER +_TESTDUPFIELDNUMBER_BAR.containing_type = _TESTDUPFIELDNUMBER +_TESTDUPFIELDNUMBER.fields_by_name['foo'].message_type = _TESTDUPFIELDNUMBER_FOO +_TESTDUPFIELDNUMBER.fields_by_name['bar'].message_type = _TESTDUPFIELDNUMBER_BAR +_TESTEAGERMESSAGE.fields_by_name['sub_message'].message_type = _TESTALLTYPES +_TESTLAZYMESSAGE.fields_by_name['sub_message'].message_type = _TESTALLTYPES +_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE.fields_by_name['nestedmessage_repeated_foreignmessage'].message_type = _FOREIGNMESSAGE +_TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE.containing_type = _TESTNESTEDMESSAGEHASBITS +_TESTNESTEDMESSAGEHASBITS.fields_by_name['optional_nested_message'].message_type = _TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE +_TESTCAMELCASEFIELDNAMES.fields_by_name['EnumField'].enum_type = _FOREIGNENUM +_TESTCAMELCASEFIELDNAMES.fields_by_name['MessageField'].message_type = _FOREIGNMESSAGE +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedEnumField'].enum_type = _FOREIGNENUM +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedMessageField'].message_type = _FOREIGNMESSAGE +_TESTFIELDORDERINGS_NESTEDMESSAGE.containing_type = _TESTFIELDORDERINGS +_TESTFIELDORDERINGS.fields_by_name['optional_nested_message'].message_type = _TESTFIELDORDERINGS_NESTEDMESSAGE +_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3.containing_type = _TESTEXTENSIONORDERINGS2 +_SPARSEENUMMESSAGE.fields_by_name['sparse_enum'].enum_type = _TESTSPARSEENUM +_TESTONEOF_FOOGROUP.containing_type = _TESTONEOF +_TESTONEOF.fields_by_name['foo_message'].message_type = _TESTALLTYPES +_TESTONEOF.fields_by_name['foogroup'].message_type = _TESTONEOF_FOOGROUP +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foo_int']) +_TESTONEOF.fields_by_name['foo_int'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foo_string']) +_TESTONEOF.fields_by_name['foo_string'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foo_message']) +_TESTONEOF.fields_by_name['foo_message'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOF.oneofs_by_name['foo'].fields.append( + _TESTONEOF.fields_by_name['foogroup']) +_TESTONEOF.fields_by_name['foogroup'].containing_oneof = _TESTONEOF.oneofs_by_name['foo'] +_TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP.containing_type = _TESTONEOFBACKWARDSCOMPATIBLE +_TESTONEOFBACKWARDSCOMPATIBLE.fields_by_name['foo_message'].message_type = _TESTALLTYPES +_TESTONEOFBACKWARDSCOMPATIBLE.fields_by_name['foogroup'].message_type = _TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP +_TESTONEOF2_FOOGROUP.containing_type = _TESTONEOF2 +_TESTONEOF2_NESTEDMESSAGE.containing_type = _TESTONEOF2 +_TESTONEOF2.fields_by_name['foo_enum'].enum_type = _TESTONEOF2_NESTEDENUM +_TESTONEOF2.fields_by_name['foo_message'].message_type = _TESTONEOF2_NESTEDMESSAGE +_TESTONEOF2.fields_by_name['foogroup'].message_type = _TESTONEOF2_FOOGROUP +_TESTONEOF2.fields_by_name['foo_lazy_message'].message_type = _TESTONEOF2_NESTEDMESSAGE +_TESTONEOF2.fields_by_name['bar_enum'].enum_type = _TESTONEOF2_NESTEDENUM +_TESTONEOF2_NESTEDENUM.containing_type = _TESTONEOF2 +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_int']) +_TESTONEOF2.fields_by_name['foo_int'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_string']) +_TESTONEOF2.fields_by_name['foo_string'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_cord']) +_TESTONEOF2.fields_by_name['foo_cord'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_string_piece']) +_TESTONEOF2.fields_by_name['foo_string_piece'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_bytes']) +_TESTONEOF2.fields_by_name['foo_bytes'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_enum']) +_TESTONEOF2.fields_by_name['foo_enum'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_message']) +_TESTONEOF2.fields_by_name['foo_message'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foogroup']) +_TESTONEOF2.fields_by_name['foogroup'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['foo'].fields.append( + _TESTONEOF2.fields_by_name['foo_lazy_message']) +_TESTONEOF2.fields_by_name['foo_lazy_message'].containing_oneof = _TESTONEOF2.oneofs_by_name['foo'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_int']) +_TESTONEOF2.fields_by_name['bar_int'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_string']) +_TESTONEOF2.fields_by_name['bar_string'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_cord']) +_TESTONEOF2.fields_by_name['bar_cord'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_string_piece']) +_TESTONEOF2.fields_by_name['bar_string_piece'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_bytes']) +_TESTONEOF2.fields_by_name['bar_bytes'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTONEOF2.oneofs_by_name['bar'].fields.append( + _TESTONEOF2.fields_by_name['bar_enum']) +_TESTONEOF2.fields_by_name['bar_enum'].containing_oneof = _TESTONEOF2.oneofs_by_name['bar'] +_TESTREQUIREDONEOF_NESTEDMESSAGE.containing_type = _TESTREQUIREDONEOF +_TESTREQUIREDONEOF.fields_by_name['foo_message'].message_type = _TESTREQUIREDONEOF_NESTEDMESSAGE +_TESTREQUIREDONEOF.oneofs_by_name['foo'].fields.append( + _TESTREQUIREDONEOF.fields_by_name['foo_int']) +_TESTREQUIREDONEOF.fields_by_name['foo_int'].containing_oneof = _TESTREQUIREDONEOF.oneofs_by_name['foo'] +_TESTREQUIREDONEOF.oneofs_by_name['foo'].fields.append( + _TESTREQUIREDONEOF.fields_by_name['foo_string']) +_TESTREQUIREDONEOF.fields_by_name['foo_string'].containing_oneof = _TESTREQUIREDONEOF.oneofs_by_name['foo'] +_TESTREQUIREDONEOF.oneofs_by_name['foo'].fields.append( + _TESTREQUIREDONEOF.fields_by_name['foo_message']) +_TESTREQUIREDONEOF.fields_by_name['foo_message'].containing_oneof = _TESTREQUIREDONEOF.oneofs_by_name['foo'] +_TESTPACKEDTYPES.fields_by_name['packed_enum'].enum_type = _FOREIGNENUM +_TESTUNPACKEDTYPES.fields_by_name['unpacked_enum'].enum_type = _FOREIGNENUM +_TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE.containing_type = _TESTDYNAMICEXTENSIONS +_TESTDYNAMICEXTENSIONS.fields_by_name['enum_extension'].enum_type = _FOREIGNENUM +_TESTDYNAMICEXTENSIONS.fields_by_name['dynamic_enum_extension'].enum_type = _TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE +_TESTDYNAMICEXTENSIONS.fields_by_name['message_extension'].message_type = _FOREIGNMESSAGE +_TESTDYNAMICEXTENSIONS.fields_by_name['dynamic_message_extension'].message_type = _TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE +_TESTDYNAMICEXTENSIONS_DYNAMICENUMTYPE.containing_type = _TESTDYNAMICEXTENSIONS +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1.fields_by_name['field1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1.containing_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2.fields_by_name['field1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2.containing_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['field1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['field2'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['field3'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['group1'].message_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1 +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['group2'].message_type = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2 +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['ext1'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.fields_by_name['ext2'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR.containing_type = _TESTPARSINGMERGE +_TESTPARSINGMERGE_OPTIONALGROUP.fields_by_name['optional_group_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_OPTIONALGROUP.containing_type = _TESTPARSINGMERGE +_TESTPARSINGMERGE_REPEATEDGROUP.fields_by_name['repeated_group_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE_REPEATEDGROUP.containing_type = _TESTPARSINGMERGE +_TESTPARSINGMERGE.fields_by_name['required_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE.fields_by_name['optional_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE.fields_by_name['repeated_all_types'].message_type = _TESTALLTYPES +_TESTPARSINGMERGE.fields_by_name['optionalgroup'].message_type = _TESTPARSINGMERGE_OPTIONALGROUP +_TESTPARSINGMERGE.fields_by_name['repeatedgroup'].message_type = _TESTPARSINGMERGE_REPEATEDGROUP +_TESTHUGEFIELDNUMBERS_OPTIONALGROUP.containing_type = _TESTHUGEFIELDNUMBERS +_TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY.containing_type = _TESTHUGEFIELDNUMBERS +_TESTHUGEFIELDNUMBERS.fields_by_name['optional_enum'].enum_type = _FOREIGNENUM +_TESTHUGEFIELDNUMBERS.fields_by_name['optional_message'].message_type = _FOREIGNMESSAGE +_TESTHUGEFIELDNUMBERS.fields_by_name['optionalgroup'].message_type = _TESTHUGEFIELDNUMBERS_OPTIONALGROUP +_TESTHUGEFIELDNUMBERS.fields_by_name['string_string_map'].message_type = _TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_test_all_types'].message_type = _TESTALLTYPES +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_uint32']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_uint32'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_test_all_types']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_test_all_types'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_string']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_string'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +_TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'].fields.append( + _TESTHUGEFIELDNUMBERS.fields_by_name['oneof_bytes']) +_TESTHUGEFIELDNUMBERS.fields_by_name['oneof_bytes'].containing_oneof = _TESTHUGEFIELDNUMBERS.oneofs_by_name['oneof_field'] +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['NestedTestAllTypes'] = _NESTEDTESTALLTYPES +DESCRIPTOR.message_types_by_name['TestDeprecatedFields'] = _TESTDEPRECATEDFIELDS +DESCRIPTOR.message_types_by_name['TestDeprecatedMessage'] = _TESTDEPRECATEDMESSAGE +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestReservedFields'] = _TESTRESERVEDFIELDS +DESCRIPTOR.message_types_by_name['TestAllExtensions'] = _TESTALLEXTENSIONS +DESCRIPTOR.message_types_by_name['OptionalGroup_extension'] = _OPTIONALGROUP_EXTENSION +DESCRIPTOR.message_types_by_name['RepeatedGroup_extension'] = _REPEATEDGROUP_EXTENSION +DESCRIPTOR.message_types_by_name['TestGroup'] = _TESTGROUP +DESCRIPTOR.message_types_by_name['TestGroupExtension'] = _TESTGROUPEXTENSION +DESCRIPTOR.message_types_by_name['TestNestedExtension'] = _TESTNESTEDEXTENSION +DESCRIPTOR.message_types_by_name['TestRequired'] = _TESTREQUIRED +DESCRIPTOR.message_types_by_name['TestRequiredForeign'] = _TESTREQUIREDFOREIGN +DESCRIPTOR.message_types_by_name['TestRequiredMessage'] = _TESTREQUIREDMESSAGE +DESCRIPTOR.message_types_by_name['TestForeignNested'] = _TESTFOREIGNNESTED +DESCRIPTOR.message_types_by_name['TestEmptyMessage'] = _TESTEMPTYMESSAGE +DESCRIPTOR.message_types_by_name['TestEmptyMessageWithExtensions'] = _TESTEMPTYMESSAGEWITHEXTENSIONS +DESCRIPTOR.message_types_by_name['TestMultipleExtensionRanges'] = _TESTMULTIPLEEXTENSIONRANGES +DESCRIPTOR.message_types_by_name['TestReallyLargeTagNumber'] = _TESTREALLYLARGETAGNUMBER +DESCRIPTOR.message_types_by_name['TestRecursiveMessage'] = _TESTRECURSIVEMESSAGE +DESCRIPTOR.message_types_by_name['TestMutualRecursionA'] = _TESTMUTUALRECURSIONA +DESCRIPTOR.message_types_by_name['TestMutualRecursionB'] = _TESTMUTUALRECURSIONB +DESCRIPTOR.message_types_by_name['TestIsInitialized'] = _TESTISINITIALIZED +DESCRIPTOR.message_types_by_name['TestDupFieldNumber'] = _TESTDUPFIELDNUMBER +DESCRIPTOR.message_types_by_name['TestEagerMessage'] = _TESTEAGERMESSAGE +DESCRIPTOR.message_types_by_name['TestLazyMessage'] = _TESTLAZYMESSAGE +DESCRIPTOR.message_types_by_name['TestNestedMessageHasBits'] = _TESTNESTEDMESSAGEHASBITS +DESCRIPTOR.message_types_by_name['TestCamelCaseFieldNames'] = _TESTCAMELCASEFIELDNAMES +DESCRIPTOR.message_types_by_name['TestFieldOrderings'] = _TESTFIELDORDERINGS +DESCRIPTOR.message_types_by_name['TestExtensionOrderings1'] = _TESTEXTENSIONORDERINGS1 +DESCRIPTOR.message_types_by_name['TestExtensionOrderings2'] = _TESTEXTENSIONORDERINGS2 +DESCRIPTOR.message_types_by_name['TestExtremeDefaultValues'] = _TESTEXTREMEDEFAULTVALUES +DESCRIPTOR.message_types_by_name['SparseEnumMessage'] = _SPARSEENUMMESSAGE +DESCRIPTOR.message_types_by_name['OneString'] = _ONESTRING +DESCRIPTOR.message_types_by_name['MoreString'] = _MORESTRING +DESCRIPTOR.message_types_by_name['OneBytes'] = _ONEBYTES +DESCRIPTOR.message_types_by_name['MoreBytes'] = _MOREBYTES +DESCRIPTOR.message_types_by_name['Int32Message'] = _INT32MESSAGE +DESCRIPTOR.message_types_by_name['Uint32Message'] = _UINT32MESSAGE +DESCRIPTOR.message_types_by_name['Int64Message'] = _INT64MESSAGE +DESCRIPTOR.message_types_by_name['Uint64Message'] = _UINT64MESSAGE +DESCRIPTOR.message_types_by_name['BoolMessage'] = _BOOLMESSAGE +DESCRIPTOR.message_types_by_name['TestOneof'] = _TESTONEOF +DESCRIPTOR.message_types_by_name['TestOneofBackwardsCompatible'] = _TESTONEOFBACKWARDSCOMPATIBLE +DESCRIPTOR.message_types_by_name['TestOneof2'] = _TESTONEOF2 +DESCRIPTOR.message_types_by_name['TestRequiredOneof'] = _TESTREQUIREDONEOF +DESCRIPTOR.message_types_by_name['TestPackedTypes'] = _TESTPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestUnpackedTypes'] = _TESTUNPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestPackedExtensions'] = _TESTPACKEDEXTENSIONS +DESCRIPTOR.message_types_by_name['TestUnpackedExtensions'] = _TESTUNPACKEDEXTENSIONS +DESCRIPTOR.message_types_by_name['TestDynamicExtensions'] = _TESTDYNAMICEXTENSIONS +DESCRIPTOR.message_types_by_name['TestRepeatedScalarDifferentTagSizes'] = _TESTREPEATEDSCALARDIFFERENTTAGSIZES +DESCRIPTOR.message_types_by_name['TestParsingMerge'] = _TESTPARSINGMERGE +DESCRIPTOR.message_types_by_name['TestCommentInjectionMessage'] = _TESTCOMMENTINJECTIONMESSAGE +DESCRIPTOR.message_types_by_name['FooRequest'] = _FOOREQUEST +DESCRIPTOR.message_types_by_name['FooResponse'] = _FOORESPONSE +DESCRIPTOR.message_types_by_name['FooClientMessage'] = _FOOCLIENTMESSAGE +DESCRIPTOR.message_types_by_name['FooServerMessage'] = _FOOSERVERMESSAGE +DESCRIPTOR.message_types_by_name['BarRequest'] = _BARREQUEST +DESCRIPTOR.message_types_by_name['BarResponse'] = _BARRESPONSE +DESCRIPTOR.message_types_by_name['TestJsonName'] = _TESTJSONNAME +DESCRIPTOR.message_types_by_name['TestHugeFieldNumbers'] = _TESTHUGEFIELDNUMBERS +DESCRIPTOR.message_types_by_name['TestExtensionInsideTable'] = _TESTEXTENSIONINSIDETABLE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +DESCRIPTOR.enum_types_by_name['TestEnumWithDupValue'] = _TESTENUMWITHDUPVALUE +DESCRIPTOR.enum_types_by_name['TestSparseEnum'] = _TESTSPARSEENUM +DESCRIPTOR.extensions_by_name['optional_int32_extension'] = optional_int32_extension +DESCRIPTOR.extensions_by_name['optional_int64_extension'] = optional_int64_extension +DESCRIPTOR.extensions_by_name['optional_uint32_extension'] = optional_uint32_extension +DESCRIPTOR.extensions_by_name['optional_uint64_extension'] = optional_uint64_extension +DESCRIPTOR.extensions_by_name['optional_sint32_extension'] = optional_sint32_extension +DESCRIPTOR.extensions_by_name['optional_sint64_extension'] = optional_sint64_extension +DESCRIPTOR.extensions_by_name['optional_fixed32_extension'] = optional_fixed32_extension +DESCRIPTOR.extensions_by_name['optional_fixed64_extension'] = optional_fixed64_extension +DESCRIPTOR.extensions_by_name['optional_sfixed32_extension'] = optional_sfixed32_extension +DESCRIPTOR.extensions_by_name['optional_sfixed64_extension'] = optional_sfixed64_extension +DESCRIPTOR.extensions_by_name['optional_float_extension'] = optional_float_extension +DESCRIPTOR.extensions_by_name['optional_double_extension'] = optional_double_extension +DESCRIPTOR.extensions_by_name['optional_bool_extension'] = optional_bool_extension +DESCRIPTOR.extensions_by_name['optional_string_extension'] = optional_string_extension +DESCRIPTOR.extensions_by_name['optional_bytes_extension'] = optional_bytes_extension +DESCRIPTOR.extensions_by_name['optionalgroup_extension'] = optionalgroup_extension +DESCRIPTOR.extensions_by_name['optional_nested_message_extension'] = optional_nested_message_extension +DESCRIPTOR.extensions_by_name['optional_foreign_message_extension'] = optional_foreign_message_extension +DESCRIPTOR.extensions_by_name['optional_import_message_extension'] = optional_import_message_extension +DESCRIPTOR.extensions_by_name['optional_nested_enum_extension'] = optional_nested_enum_extension +DESCRIPTOR.extensions_by_name['optional_foreign_enum_extension'] = optional_foreign_enum_extension +DESCRIPTOR.extensions_by_name['optional_import_enum_extension'] = optional_import_enum_extension +DESCRIPTOR.extensions_by_name['optional_string_piece_extension'] = optional_string_piece_extension +DESCRIPTOR.extensions_by_name['optional_cord_extension'] = optional_cord_extension +DESCRIPTOR.extensions_by_name['optional_public_import_message_extension'] = optional_public_import_message_extension +DESCRIPTOR.extensions_by_name['optional_lazy_message_extension'] = optional_lazy_message_extension +DESCRIPTOR.extensions_by_name['repeated_int32_extension'] = repeated_int32_extension +DESCRIPTOR.extensions_by_name['repeated_int64_extension'] = repeated_int64_extension +DESCRIPTOR.extensions_by_name['repeated_uint32_extension'] = repeated_uint32_extension +DESCRIPTOR.extensions_by_name['repeated_uint64_extension'] = repeated_uint64_extension +DESCRIPTOR.extensions_by_name['repeated_sint32_extension'] = repeated_sint32_extension +DESCRIPTOR.extensions_by_name['repeated_sint64_extension'] = repeated_sint64_extension +DESCRIPTOR.extensions_by_name['repeated_fixed32_extension'] = repeated_fixed32_extension +DESCRIPTOR.extensions_by_name['repeated_fixed64_extension'] = repeated_fixed64_extension +DESCRIPTOR.extensions_by_name['repeated_sfixed32_extension'] = repeated_sfixed32_extension +DESCRIPTOR.extensions_by_name['repeated_sfixed64_extension'] = repeated_sfixed64_extension +DESCRIPTOR.extensions_by_name['repeated_float_extension'] = repeated_float_extension +DESCRIPTOR.extensions_by_name['repeated_double_extension'] = repeated_double_extension +DESCRIPTOR.extensions_by_name['repeated_bool_extension'] = repeated_bool_extension +DESCRIPTOR.extensions_by_name['repeated_string_extension'] = repeated_string_extension +DESCRIPTOR.extensions_by_name['repeated_bytes_extension'] = repeated_bytes_extension +DESCRIPTOR.extensions_by_name['repeatedgroup_extension'] = repeatedgroup_extension +DESCRIPTOR.extensions_by_name['repeated_nested_message_extension'] = repeated_nested_message_extension +DESCRIPTOR.extensions_by_name['repeated_foreign_message_extension'] = repeated_foreign_message_extension +DESCRIPTOR.extensions_by_name['repeated_import_message_extension'] = repeated_import_message_extension +DESCRIPTOR.extensions_by_name['repeated_nested_enum_extension'] = repeated_nested_enum_extension +DESCRIPTOR.extensions_by_name['repeated_foreign_enum_extension'] = repeated_foreign_enum_extension +DESCRIPTOR.extensions_by_name['repeated_import_enum_extension'] = repeated_import_enum_extension +DESCRIPTOR.extensions_by_name['repeated_string_piece_extension'] = repeated_string_piece_extension +DESCRIPTOR.extensions_by_name['repeated_cord_extension'] = repeated_cord_extension +DESCRIPTOR.extensions_by_name['repeated_lazy_message_extension'] = repeated_lazy_message_extension +DESCRIPTOR.extensions_by_name['default_int32_extension'] = default_int32_extension +DESCRIPTOR.extensions_by_name['default_int64_extension'] = default_int64_extension +DESCRIPTOR.extensions_by_name['default_uint32_extension'] = default_uint32_extension +DESCRIPTOR.extensions_by_name['default_uint64_extension'] = default_uint64_extension +DESCRIPTOR.extensions_by_name['default_sint32_extension'] = default_sint32_extension +DESCRIPTOR.extensions_by_name['default_sint64_extension'] = default_sint64_extension +DESCRIPTOR.extensions_by_name['default_fixed32_extension'] = default_fixed32_extension +DESCRIPTOR.extensions_by_name['default_fixed64_extension'] = default_fixed64_extension +DESCRIPTOR.extensions_by_name['default_sfixed32_extension'] = default_sfixed32_extension +DESCRIPTOR.extensions_by_name['default_sfixed64_extension'] = default_sfixed64_extension +DESCRIPTOR.extensions_by_name['default_float_extension'] = default_float_extension +DESCRIPTOR.extensions_by_name['default_double_extension'] = default_double_extension +DESCRIPTOR.extensions_by_name['default_bool_extension'] = default_bool_extension +DESCRIPTOR.extensions_by_name['default_string_extension'] = default_string_extension +DESCRIPTOR.extensions_by_name['default_bytes_extension'] = default_bytes_extension +DESCRIPTOR.extensions_by_name['default_nested_enum_extension'] = default_nested_enum_extension +DESCRIPTOR.extensions_by_name['default_foreign_enum_extension'] = default_foreign_enum_extension +DESCRIPTOR.extensions_by_name['default_import_enum_extension'] = default_import_enum_extension +DESCRIPTOR.extensions_by_name['default_string_piece_extension'] = default_string_piece_extension +DESCRIPTOR.extensions_by_name['default_cord_extension'] = default_cord_extension +DESCRIPTOR.extensions_by_name['oneof_uint32_extension'] = oneof_uint32_extension +DESCRIPTOR.extensions_by_name['oneof_nested_message_extension'] = oneof_nested_message_extension +DESCRIPTOR.extensions_by_name['oneof_string_extension'] = oneof_string_extension +DESCRIPTOR.extensions_by_name['oneof_bytes_extension'] = oneof_bytes_extension +DESCRIPTOR.extensions_by_name['my_extension_string'] = my_extension_string +DESCRIPTOR.extensions_by_name['my_extension_int'] = my_extension_int +DESCRIPTOR.extensions_by_name['packed_int32_extension'] = packed_int32_extension +DESCRIPTOR.extensions_by_name['packed_int64_extension'] = packed_int64_extension +DESCRIPTOR.extensions_by_name['packed_uint32_extension'] = packed_uint32_extension +DESCRIPTOR.extensions_by_name['packed_uint64_extension'] = packed_uint64_extension +DESCRIPTOR.extensions_by_name['packed_sint32_extension'] = packed_sint32_extension +DESCRIPTOR.extensions_by_name['packed_sint64_extension'] = packed_sint64_extension +DESCRIPTOR.extensions_by_name['packed_fixed32_extension'] = packed_fixed32_extension +DESCRIPTOR.extensions_by_name['packed_fixed64_extension'] = packed_fixed64_extension +DESCRIPTOR.extensions_by_name['packed_sfixed32_extension'] = packed_sfixed32_extension +DESCRIPTOR.extensions_by_name['packed_sfixed64_extension'] = packed_sfixed64_extension +DESCRIPTOR.extensions_by_name['packed_float_extension'] = packed_float_extension +DESCRIPTOR.extensions_by_name['packed_double_extension'] = packed_double_extension +DESCRIPTOR.extensions_by_name['packed_bool_extension'] = packed_bool_extension +DESCRIPTOR.extensions_by_name['packed_enum_extension'] = packed_enum_extension +DESCRIPTOR.extensions_by_name['unpacked_int32_extension'] = unpacked_int32_extension +DESCRIPTOR.extensions_by_name['unpacked_int64_extension'] = unpacked_int64_extension +DESCRIPTOR.extensions_by_name['unpacked_uint32_extension'] = unpacked_uint32_extension +DESCRIPTOR.extensions_by_name['unpacked_uint64_extension'] = unpacked_uint64_extension +DESCRIPTOR.extensions_by_name['unpacked_sint32_extension'] = unpacked_sint32_extension +DESCRIPTOR.extensions_by_name['unpacked_sint64_extension'] = unpacked_sint64_extension +DESCRIPTOR.extensions_by_name['unpacked_fixed32_extension'] = unpacked_fixed32_extension +DESCRIPTOR.extensions_by_name['unpacked_fixed64_extension'] = unpacked_fixed64_extension +DESCRIPTOR.extensions_by_name['unpacked_sfixed32_extension'] = unpacked_sfixed32_extension +DESCRIPTOR.extensions_by_name['unpacked_sfixed64_extension'] = unpacked_sfixed64_extension +DESCRIPTOR.extensions_by_name['unpacked_float_extension'] = unpacked_float_extension +DESCRIPTOR.extensions_by_name['unpacked_double_extension'] = unpacked_double_extension +DESCRIPTOR.extensions_by_name['unpacked_bool_extension'] = unpacked_bool_extension +DESCRIPTOR.extensions_by_name['unpacked_enum_extension'] = unpacked_enum_extension +DESCRIPTOR.extensions_by_name['test_all_types'] = test_all_types +DESCRIPTOR.extensions_by_name['test_extension_inside_table_extension'] = test_extension_inside_table_extension +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes.NestedMessage) + )) + , + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes.OptionalGroup) + )) + , + + RepeatedGroup = _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_REPEATEDGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes.RepeatedGroup) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) +_sym_db.RegisterMessage(TestAllTypes.OptionalGroup) +_sym_db.RegisterMessage(TestAllTypes.RepeatedGroup) + +NestedTestAllTypes = _reflection.GeneratedProtocolMessageType('NestedTestAllTypes', (_message.Message,), dict( + DESCRIPTOR = _NESTEDTESTALLTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.NestedTestAllTypes) + )) +_sym_db.RegisterMessage(NestedTestAllTypes) + +TestDeprecatedFields = _reflection.GeneratedProtocolMessageType('TestDeprecatedFields', (_message.Message,), dict( + DESCRIPTOR = _TESTDEPRECATEDFIELDS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDeprecatedFields) + )) +_sym_db.RegisterMessage(TestDeprecatedFields) + +TestDeprecatedMessage = _reflection.GeneratedProtocolMessageType('TestDeprecatedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTDEPRECATEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDeprecatedMessage) + )) +_sym_db.RegisterMessage(TestDeprecatedMessage) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestReservedFields = _reflection.GeneratedProtocolMessageType('TestReservedFields', (_message.Message,), dict( + DESCRIPTOR = _TESTRESERVEDFIELDS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestReservedFields) + )) +_sym_db.RegisterMessage(TestReservedFields) + +TestAllExtensions = _reflection.GeneratedProtocolMessageType('TestAllExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTALLEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestAllExtensions) + )) +_sym_db.RegisterMessage(TestAllExtensions) + +OptionalGroup_extension = _reflection.GeneratedProtocolMessageType('OptionalGroup_extension', (_message.Message,), dict( + DESCRIPTOR = _OPTIONALGROUP_EXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OptionalGroup_extension) + )) +_sym_db.RegisterMessage(OptionalGroup_extension) + +RepeatedGroup_extension = _reflection.GeneratedProtocolMessageType('RepeatedGroup_extension', (_message.Message,), dict( + DESCRIPTOR = _REPEATEDGROUP_EXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.RepeatedGroup_extension) + )) +_sym_db.RegisterMessage(RepeatedGroup_extension) + +TestGroup = _reflection.GeneratedProtocolMessageType('TestGroup', (_message.Message,), dict( + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTGROUP_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestGroup.OptionalGroup) + )) + , + DESCRIPTOR = _TESTGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestGroup) + )) +_sym_db.RegisterMessage(TestGroup) +_sym_db.RegisterMessage(TestGroup.OptionalGroup) + +TestGroupExtension = _reflection.GeneratedProtocolMessageType('TestGroupExtension', (_message.Message,), dict( + DESCRIPTOR = _TESTGROUPEXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestGroupExtension) + )) +_sym_db.RegisterMessage(TestGroupExtension) + +TestNestedExtension = _reflection.GeneratedProtocolMessageType('TestNestedExtension', (_message.Message,), dict( + + OptionalGroup_extension = _reflection.GeneratedProtocolMessageType('OptionalGroup_extension', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedExtension.OptionalGroup_extension) + )) + , + DESCRIPTOR = _TESTNESTEDEXTENSION, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedExtension) + )) +_sym_db.RegisterMessage(TestNestedExtension) +_sym_db.RegisterMessage(TestNestedExtension.OptionalGroup_extension) + +TestRequired = _reflection.GeneratedProtocolMessageType('TestRequired', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIRED, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequired) + )) +_sym_db.RegisterMessage(TestRequired) + +TestRequiredForeign = _reflection.GeneratedProtocolMessageType('TestRequiredForeign', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDFOREIGN, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredForeign) + )) +_sym_db.RegisterMessage(TestRequiredForeign) + +TestRequiredMessage = _reflection.GeneratedProtocolMessageType('TestRequiredMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredMessage) + )) +_sym_db.RegisterMessage(TestRequiredMessage) + +TestForeignNested = _reflection.GeneratedProtocolMessageType('TestForeignNested', (_message.Message,), dict( + DESCRIPTOR = _TESTFOREIGNNESTED, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestForeignNested) + )) +_sym_db.RegisterMessage(TestForeignNested) + +TestEmptyMessage = _reflection.GeneratedProtocolMessageType('TestEmptyMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTEMPTYMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEmptyMessage) + )) +_sym_db.RegisterMessage(TestEmptyMessage) + +TestEmptyMessageWithExtensions = _reflection.GeneratedProtocolMessageType('TestEmptyMessageWithExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTEMPTYMESSAGEWITHEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEmptyMessageWithExtensions) + )) +_sym_db.RegisterMessage(TestEmptyMessageWithExtensions) + +TestMultipleExtensionRanges = _reflection.GeneratedProtocolMessageType('TestMultipleExtensionRanges', (_message.Message,), dict( + DESCRIPTOR = _TESTMULTIPLEEXTENSIONRANGES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMultipleExtensionRanges) + )) +_sym_db.RegisterMessage(TestMultipleExtensionRanges) + +TestReallyLargeTagNumber = _reflection.GeneratedProtocolMessageType('TestReallyLargeTagNumber', (_message.Message,), dict( + DESCRIPTOR = _TESTREALLYLARGETAGNUMBER, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestReallyLargeTagNumber) + )) +_sym_db.RegisterMessage(TestReallyLargeTagNumber) + +TestRecursiveMessage = _reflection.GeneratedProtocolMessageType('TestRecursiveMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTRECURSIVEMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursiveMessage) + )) +_sym_db.RegisterMessage(TestRecursiveMessage) + +TestMutualRecursionA = _reflection.GeneratedProtocolMessageType('TestMutualRecursionA', (_message.Message,), dict( + + SubMessage = _reflection.GeneratedProtocolMessageType('SubMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMUTUALRECURSIONA_SUBMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionA.SubMessage) + )) + , + + SubGroup = _reflection.GeneratedProtocolMessageType('SubGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTMUTUALRECURSIONA_SUBGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionA.SubGroup) + )) + , + DESCRIPTOR = _TESTMUTUALRECURSIONA, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionA) + )) +_sym_db.RegisterMessage(TestMutualRecursionA) +_sym_db.RegisterMessage(TestMutualRecursionA.SubMessage) +_sym_db.RegisterMessage(TestMutualRecursionA.SubGroup) + +TestMutualRecursionB = _reflection.GeneratedProtocolMessageType('TestMutualRecursionB', (_message.Message,), dict( + DESCRIPTOR = _TESTMUTUALRECURSIONB, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMutualRecursionB) + )) +_sym_db.RegisterMessage(TestMutualRecursionB) + +TestIsInitialized = _reflection.GeneratedProtocolMessageType('TestIsInitialized', (_message.Message,), dict( + + SubMessage = _reflection.GeneratedProtocolMessageType('SubMessage', (_message.Message,), dict( + + SubGroup = _reflection.GeneratedProtocolMessageType('SubGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTISINITIALIZED_SUBMESSAGE_SUBGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIsInitialized.SubMessage.SubGroup) + )) + , + DESCRIPTOR = _TESTISINITIALIZED_SUBMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIsInitialized.SubMessage) + )) + , + DESCRIPTOR = _TESTISINITIALIZED, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestIsInitialized) + )) +_sym_db.RegisterMessage(TestIsInitialized) +_sym_db.RegisterMessage(TestIsInitialized.SubMessage) +_sym_db.RegisterMessage(TestIsInitialized.SubMessage.SubGroup) + +TestDupFieldNumber = _reflection.GeneratedProtocolMessageType('TestDupFieldNumber', (_message.Message,), dict( + + Foo = _reflection.GeneratedProtocolMessageType('Foo', (_message.Message,), dict( + DESCRIPTOR = _TESTDUPFIELDNUMBER_FOO, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDupFieldNumber.Foo) + )) + , + + Bar = _reflection.GeneratedProtocolMessageType('Bar', (_message.Message,), dict( + DESCRIPTOR = _TESTDUPFIELDNUMBER_BAR, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDupFieldNumber.Bar) + )) + , + DESCRIPTOR = _TESTDUPFIELDNUMBER, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDupFieldNumber) + )) +_sym_db.RegisterMessage(TestDupFieldNumber) +_sym_db.RegisterMessage(TestDupFieldNumber.Foo) +_sym_db.RegisterMessage(TestDupFieldNumber.Bar) + +TestEagerMessage = _reflection.GeneratedProtocolMessageType('TestEagerMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTEAGERMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestEagerMessage) + )) +_sym_db.RegisterMessage(TestEagerMessage) + +TestLazyMessage = _reflection.GeneratedProtocolMessageType('TestLazyMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTLAZYMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestLazyMessage) + )) +_sym_db.RegisterMessage(TestLazyMessage) + +TestNestedMessageHasBits = _reflection.GeneratedProtocolMessageType('TestNestedMessageHasBits', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMESSAGEHASBITS_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedMessageHasBits.NestedMessage) + )) + , + DESCRIPTOR = _TESTNESTEDMESSAGEHASBITS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNestedMessageHasBits) + )) +_sym_db.RegisterMessage(TestNestedMessageHasBits) +_sym_db.RegisterMessage(TestNestedMessageHasBits.NestedMessage) + +TestCamelCaseFieldNames = _reflection.GeneratedProtocolMessageType('TestCamelCaseFieldNames', (_message.Message,), dict( + DESCRIPTOR = _TESTCAMELCASEFIELDNAMES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestCamelCaseFieldNames) + )) +_sym_db.RegisterMessage(TestCamelCaseFieldNames) + +TestFieldOrderings = _reflection.GeneratedProtocolMessageType('TestFieldOrderings', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTFIELDORDERINGS_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestFieldOrderings.NestedMessage) + )) + , + DESCRIPTOR = _TESTFIELDORDERINGS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestFieldOrderings) + )) +_sym_db.RegisterMessage(TestFieldOrderings) +_sym_db.RegisterMessage(TestFieldOrderings.NestedMessage) + +TestExtensionOrderings1 = _reflection.GeneratedProtocolMessageType('TestExtensionOrderings1', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONORDERINGS1, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionOrderings1) + )) +_sym_db.RegisterMessage(TestExtensionOrderings1) + +TestExtensionOrderings2 = _reflection.GeneratedProtocolMessageType('TestExtensionOrderings2', (_message.Message,), dict( + + TestExtensionOrderings3 = _reflection.GeneratedProtocolMessageType('TestExtensionOrderings3', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3) + )) + , + DESCRIPTOR = _TESTEXTENSIONORDERINGS2, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionOrderings2) + )) +_sym_db.RegisterMessage(TestExtensionOrderings2) +_sym_db.RegisterMessage(TestExtensionOrderings2.TestExtensionOrderings3) + +TestExtremeDefaultValues = _reflection.GeneratedProtocolMessageType('TestExtremeDefaultValues', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTREMEDEFAULTVALUES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtremeDefaultValues) + )) +_sym_db.RegisterMessage(TestExtremeDefaultValues) + +SparseEnumMessage = _reflection.GeneratedProtocolMessageType('SparseEnumMessage', (_message.Message,), dict( + DESCRIPTOR = _SPARSEENUMMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.SparseEnumMessage) + )) +_sym_db.RegisterMessage(SparseEnumMessage) + +OneString = _reflection.GeneratedProtocolMessageType('OneString', (_message.Message,), dict( + DESCRIPTOR = _ONESTRING, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OneString) + )) +_sym_db.RegisterMessage(OneString) + +MoreString = _reflection.GeneratedProtocolMessageType('MoreString', (_message.Message,), dict( + DESCRIPTOR = _MORESTRING, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MoreString) + )) +_sym_db.RegisterMessage(MoreString) + +OneBytes = _reflection.GeneratedProtocolMessageType('OneBytes', (_message.Message,), dict( + DESCRIPTOR = _ONEBYTES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.OneBytes) + )) +_sym_db.RegisterMessage(OneBytes) + +MoreBytes = _reflection.GeneratedProtocolMessageType('MoreBytes', (_message.Message,), dict( + DESCRIPTOR = _MOREBYTES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.MoreBytes) + )) +_sym_db.RegisterMessage(MoreBytes) + +Int32Message = _reflection.GeneratedProtocolMessageType('Int32Message', (_message.Message,), dict( + DESCRIPTOR = _INT32MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Int32Message) + )) +_sym_db.RegisterMessage(Int32Message) + +Uint32Message = _reflection.GeneratedProtocolMessageType('Uint32Message', (_message.Message,), dict( + DESCRIPTOR = _UINT32MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Uint32Message) + )) +_sym_db.RegisterMessage(Uint32Message) + +Int64Message = _reflection.GeneratedProtocolMessageType('Int64Message', (_message.Message,), dict( + DESCRIPTOR = _INT64MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Int64Message) + )) +_sym_db.RegisterMessage(Int64Message) + +Uint64Message = _reflection.GeneratedProtocolMessageType('Uint64Message', (_message.Message,), dict( + DESCRIPTOR = _UINT64MESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.Uint64Message) + )) +_sym_db.RegisterMessage(Uint64Message) + +BoolMessage = _reflection.GeneratedProtocolMessageType('BoolMessage', (_message.Message,), dict( + DESCRIPTOR = _BOOLMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.BoolMessage) + )) +_sym_db.RegisterMessage(BoolMessage) + +TestOneof = _reflection.GeneratedProtocolMessageType('TestOneof', (_message.Message,), dict( + + FooGroup = _reflection.GeneratedProtocolMessageType('FooGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF_FOOGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof.FooGroup) + )) + , + DESCRIPTOR = _TESTONEOF, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof) + )) +_sym_db.RegisterMessage(TestOneof) +_sym_db.RegisterMessage(TestOneof.FooGroup) + +TestOneofBackwardsCompatible = _reflection.GeneratedProtocolMessageType('TestOneofBackwardsCompatible', (_message.Message,), dict( + + FooGroup = _reflection.GeneratedProtocolMessageType('FooGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOFBACKWARDSCOMPATIBLE_FOOGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneofBackwardsCompatible.FooGroup) + )) + , + DESCRIPTOR = _TESTONEOFBACKWARDSCOMPATIBLE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneofBackwardsCompatible) + )) +_sym_db.RegisterMessage(TestOneofBackwardsCompatible) +_sym_db.RegisterMessage(TestOneofBackwardsCompatible.FooGroup) + +TestOneof2 = _reflection.GeneratedProtocolMessageType('TestOneof2', (_message.Message,), dict( + + FooGroup = _reflection.GeneratedProtocolMessageType('FooGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF2_FOOGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof2.FooGroup) + )) + , + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF2_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof2.NestedMessage) + )) + , + DESCRIPTOR = _TESTONEOF2, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestOneof2) + )) +_sym_db.RegisterMessage(TestOneof2) +_sym_db.RegisterMessage(TestOneof2.FooGroup) +_sym_db.RegisterMessage(TestOneof2.NestedMessage) + +TestRequiredOneof = _reflection.GeneratedProtocolMessageType('TestRequiredOneof', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTREQUIREDONEOF_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredOneof.NestedMessage) + )) + , + DESCRIPTOR = _TESTREQUIREDONEOF, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRequiredOneof) + )) +_sym_db.RegisterMessage(TestRequiredOneof) +_sym_db.RegisterMessage(TestRequiredOneof.NestedMessage) + +TestPackedTypes = _reflection.GeneratedProtocolMessageType('TestPackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestPackedTypes) + )) +_sym_db.RegisterMessage(TestPackedTypes) + +TestUnpackedTypes = _reflection.GeneratedProtocolMessageType('TestUnpackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDTYPES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestUnpackedTypes) + )) +_sym_db.RegisterMessage(TestUnpackedTypes) + +TestPackedExtensions = _reflection.GeneratedProtocolMessageType('TestPackedExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestPackedExtensions) + )) +_sym_db.RegisterMessage(TestPackedExtensions) + +TestUnpackedExtensions = _reflection.GeneratedProtocolMessageType('TestUnpackedExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestUnpackedExtensions) + )) +_sym_db.RegisterMessage(TestUnpackedExtensions) + +TestDynamicExtensions = _reflection.GeneratedProtocolMessageType('TestDynamicExtensions', (_message.Message,), dict( + + DynamicMessageType = _reflection.GeneratedProtocolMessageType('DynamicMessageType', (_message.Message,), dict( + DESCRIPTOR = _TESTDYNAMICEXTENSIONS_DYNAMICMESSAGETYPE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDynamicExtensions.DynamicMessageType) + )) + , + DESCRIPTOR = _TESTDYNAMICEXTENSIONS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestDynamicExtensions) + )) +_sym_db.RegisterMessage(TestDynamicExtensions) +_sym_db.RegisterMessage(TestDynamicExtensions.DynamicMessageType) + +TestRepeatedScalarDifferentTagSizes = _reflection.GeneratedProtocolMessageType('TestRepeatedScalarDifferentTagSizes', (_message.Message,), dict( + DESCRIPTOR = _TESTREPEATEDSCALARDIFFERENTTAGSIZES, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRepeatedScalarDifferentTagSizes) + )) +_sym_db.RegisterMessage(TestRepeatedScalarDifferentTagSizes) + +TestParsingMerge = _reflection.GeneratedProtocolMessageType('TestParsingMerge', (_message.Message,), dict( + + RepeatedFieldsGenerator = _reflection.GeneratedProtocolMessageType('RepeatedFieldsGenerator', (_message.Message,), dict( + + Group1 = _reflection.GeneratedProtocolMessageType('Group1', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP1, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group1) + )) + , + + Group2 = _reflection.GeneratedProtocolMessageType('Group2', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR_GROUP2, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator.Group2) + )) + , + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDFIELDSGENERATOR, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedFieldsGenerator) + )) + , + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.OptionalGroup) + )) + , + + RepeatedGroup = _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTPARSINGMERGE_REPEATEDGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge.RepeatedGroup) + )) + , + DESCRIPTOR = _TESTPARSINGMERGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestParsingMerge) + )) +_sym_db.RegisterMessage(TestParsingMerge) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedFieldsGenerator) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedFieldsGenerator.Group1) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedFieldsGenerator.Group2) +_sym_db.RegisterMessage(TestParsingMerge.OptionalGroup) +_sym_db.RegisterMessage(TestParsingMerge.RepeatedGroup) + +TestCommentInjectionMessage = _reflection.GeneratedProtocolMessageType('TestCommentInjectionMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTCOMMENTINJECTIONMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestCommentInjectionMessage) + )) +_sym_db.RegisterMessage(TestCommentInjectionMessage) + +FooRequest = _reflection.GeneratedProtocolMessageType('FooRequest', (_message.Message,), dict( + DESCRIPTOR = _FOOREQUEST, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooRequest) + )) +_sym_db.RegisterMessage(FooRequest) + +FooResponse = _reflection.GeneratedProtocolMessageType('FooResponse', (_message.Message,), dict( + DESCRIPTOR = _FOORESPONSE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooResponse) + )) +_sym_db.RegisterMessage(FooResponse) + +FooClientMessage = _reflection.GeneratedProtocolMessageType('FooClientMessage', (_message.Message,), dict( + DESCRIPTOR = _FOOCLIENTMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooClientMessage) + )) +_sym_db.RegisterMessage(FooClientMessage) + +FooServerMessage = _reflection.GeneratedProtocolMessageType('FooServerMessage', (_message.Message,), dict( + DESCRIPTOR = _FOOSERVERMESSAGE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.FooServerMessage) + )) +_sym_db.RegisterMessage(FooServerMessage) + +BarRequest = _reflection.GeneratedProtocolMessageType('BarRequest', (_message.Message,), dict( + DESCRIPTOR = _BARREQUEST, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.BarRequest) + )) +_sym_db.RegisterMessage(BarRequest) + +BarResponse = _reflection.GeneratedProtocolMessageType('BarResponse', (_message.Message,), dict( + DESCRIPTOR = _BARRESPONSE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.BarResponse) + )) +_sym_db.RegisterMessage(BarResponse) + +TestJsonName = _reflection.GeneratedProtocolMessageType('TestJsonName', (_message.Message,), dict( + DESCRIPTOR = _TESTJSONNAME, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestJsonName) + )) +_sym_db.RegisterMessage(TestJsonName) + +TestHugeFieldNumbers = _reflection.GeneratedProtocolMessageType('TestHugeFieldNumbers', (_message.Message,), dict( + + OptionalGroup = _reflection.GeneratedProtocolMessageType('OptionalGroup', (_message.Message,), dict( + DESCRIPTOR = _TESTHUGEFIELDNUMBERS_OPTIONALGROUP, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestHugeFieldNumbers.OptionalGroup) + )) + , + + StringStringMapEntry = _reflection.GeneratedProtocolMessageType('StringStringMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestHugeFieldNumbers.StringStringMapEntry) + )) + , + DESCRIPTOR = _TESTHUGEFIELDNUMBERS, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestHugeFieldNumbers) + )) +_sym_db.RegisterMessage(TestHugeFieldNumbers) +_sym_db.RegisterMessage(TestHugeFieldNumbers.OptionalGroup) +_sym_db.RegisterMessage(TestHugeFieldNumbers.StringStringMapEntry) + +TestExtensionInsideTable = _reflection.GeneratedProtocolMessageType('TestExtensionInsideTable', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONINSIDETABLE, + __module__ = 'google.protobuf.unittest_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtensionInsideTable) + )) +_sym_db.RegisterMessage(TestExtensionInsideTable) + +TestAllExtensions.RegisterExtension(optional_int32_extension) +TestAllExtensions.RegisterExtension(optional_int64_extension) +TestAllExtensions.RegisterExtension(optional_uint32_extension) +TestAllExtensions.RegisterExtension(optional_uint64_extension) +TestAllExtensions.RegisterExtension(optional_sint32_extension) +TestAllExtensions.RegisterExtension(optional_sint64_extension) +TestAllExtensions.RegisterExtension(optional_fixed32_extension) +TestAllExtensions.RegisterExtension(optional_fixed64_extension) +TestAllExtensions.RegisterExtension(optional_sfixed32_extension) +TestAllExtensions.RegisterExtension(optional_sfixed64_extension) +TestAllExtensions.RegisterExtension(optional_float_extension) +TestAllExtensions.RegisterExtension(optional_double_extension) +TestAllExtensions.RegisterExtension(optional_bool_extension) +TestAllExtensions.RegisterExtension(optional_string_extension) +TestAllExtensions.RegisterExtension(optional_bytes_extension) +optionalgroup_extension.message_type = _OPTIONALGROUP_EXTENSION +TestAllExtensions.RegisterExtension(optionalgroup_extension) +optional_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(optional_nested_message_extension) +optional_foreign_message_extension.message_type = _FOREIGNMESSAGE +TestAllExtensions.RegisterExtension(optional_foreign_message_extension) +optional_import_message_extension.message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +TestAllExtensions.RegisterExtension(optional_import_message_extension) +optional_nested_enum_extension.enum_type = _TESTALLTYPES_NESTEDENUM +TestAllExtensions.RegisterExtension(optional_nested_enum_extension) +optional_foreign_enum_extension.enum_type = _FOREIGNENUM +TestAllExtensions.RegisterExtension(optional_foreign_enum_extension) +optional_import_enum_extension.enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +TestAllExtensions.RegisterExtension(optional_import_enum_extension) +TestAllExtensions.RegisterExtension(optional_string_piece_extension) +TestAllExtensions.RegisterExtension(optional_cord_extension) +optional_public_import_message_extension.message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +TestAllExtensions.RegisterExtension(optional_public_import_message_extension) +optional_lazy_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(optional_lazy_message_extension) +TestAllExtensions.RegisterExtension(repeated_int32_extension) +TestAllExtensions.RegisterExtension(repeated_int64_extension) +TestAllExtensions.RegisterExtension(repeated_uint32_extension) +TestAllExtensions.RegisterExtension(repeated_uint64_extension) +TestAllExtensions.RegisterExtension(repeated_sint32_extension) +TestAllExtensions.RegisterExtension(repeated_sint64_extension) +TestAllExtensions.RegisterExtension(repeated_fixed32_extension) +TestAllExtensions.RegisterExtension(repeated_fixed64_extension) +TestAllExtensions.RegisterExtension(repeated_sfixed32_extension) +TestAllExtensions.RegisterExtension(repeated_sfixed64_extension) +TestAllExtensions.RegisterExtension(repeated_float_extension) +TestAllExtensions.RegisterExtension(repeated_double_extension) +TestAllExtensions.RegisterExtension(repeated_bool_extension) +TestAllExtensions.RegisterExtension(repeated_string_extension) +TestAllExtensions.RegisterExtension(repeated_bytes_extension) +repeatedgroup_extension.message_type = _REPEATEDGROUP_EXTENSION +TestAllExtensions.RegisterExtension(repeatedgroup_extension) +repeated_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(repeated_nested_message_extension) +repeated_foreign_message_extension.message_type = _FOREIGNMESSAGE +TestAllExtensions.RegisterExtension(repeated_foreign_message_extension) +repeated_import_message_extension.message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +TestAllExtensions.RegisterExtension(repeated_import_message_extension) +repeated_nested_enum_extension.enum_type = _TESTALLTYPES_NESTEDENUM +TestAllExtensions.RegisterExtension(repeated_nested_enum_extension) +repeated_foreign_enum_extension.enum_type = _FOREIGNENUM +TestAllExtensions.RegisterExtension(repeated_foreign_enum_extension) +repeated_import_enum_extension.enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +TestAllExtensions.RegisterExtension(repeated_import_enum_extension) +TestAllExtensions.RegisterExtension(repeated_string_piece_extension) +TestAllExtensions.RegisterExtension(repeated_cord_extension) +repeated_lazy_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(repeated_lazy_message_extension) +TestAllExtensions.RegisterExtension(default_int32_extension) +TestAllExtensions.RegisterExtension(default_int64_extension) +TestAllExtensions.RegisterExtension(default_uint32_extension) +TestAllExtensions.RegisterExtension(default_uint64_extension) +TestAllExtensions.RegisterExtension(default_sint32_extension) +TestAllExtensions.RegisterExtension(default_sint64_extension) +TestAllExtensions.RegisterExtension(default_fixed32_extension) +TestAllExtensions.RegisterExtension(default_fixed64_extension) +TestAllExtensions.RegisterExtension(default_sfixed32_extension) +TestAllExtensions.RegisterExtension(default_sfixed64_extension) +TestAllExtensions.RegisterExtension(default_float_extension) +TestAllExtensions.RegisterExtension(default_double_extension) +TestAllExtensions.RegisterExtension(default_bool_extension) +TestAllExtensions.RegisterExtension(default_string_extension) +TestAllExtensions.RegisterExtension(default_bytes_extension) +default_nested_enum_extension.enum_type = _TESTALLTYPES_NESTEDENUM +TestAllExtensions.RegisterExtension(default_nested_enum_extension) +default_foreign_enum_extension.enum_type = _FOREIGNENUM +TestAllExtensions.RegisterExtension(default_foreign_enum_extension) +default_import_enum_extension.enum_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTENUM +TestAllExtensions.RegisterExtension(default_import_enum_extension) +TestAllExtensions.RegisterExtension(default_string_piece_extension) +TestAllExtensions.RegisterExtension(default_cord_extension) +TestAllExtensions.RegisterExtension(oneof_uint32_extension) +oneof_nested_message_extension.message_type = _TESTALLTYPES_NESTEDMESSAGE +TestAllExtensions.RegisterExtension(oneof_nested_message_extension) +TestAllExtensions.RegisterExtension(oneof_string_extension) +TestAllExtensions.RegisterExtension(oneof_bytes_extension) +TestFieldOrderings.RegisterExtension(my_extension_string) +TestFieldOrderings.RegisterExtension(my_extension_int) +TestPackedExtensions.RegisterExtension(packed_int32_extension) +TestPackedExtensions.RegisterExtension(packed_int64_extension) +TestPackedExtensions.RegisterExtension(packed_uint32_extension) +TestPackedExtensions.RegisterExtension(packed_uint64_extension) +TestPackedExtensions.RegisterExtension(packed_sint32_extension) +TestPackedExtensions.RegisterExtension(packed_sint64_extension) +TestPackedExtensions.RegisterExtension(packed_fixed32_extension) +TestPackedExtensions.RegisterExtension(packed_fixed64_extension) +TestPackedExtensions.RegisterExtension(packed_sfixed32_extension) +TestPackedExtensions.RegisterExtension(packed_sfixed64_extension) +TestPackedExtensions.RegisterExtension(packed_float_extension) +TestPackedExtensions.RegisterExtension(packed_double_extension) +TestPackedExtensions.RegisterExtension(packed_bool_extension) +packed_enum_extension.enum_type = _FOREIGNENUM +TestPackedExtensions.RegisterExtension(packed_enum_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_int32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_int64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_uint32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_uint64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sint32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sint64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_fixed32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_fixed64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sfixed32_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_sfixed64_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_float_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_double_extension) +TestUnpackedExtensions.RegisterExtension(unpacked_bool_extension) +unpacked_enum_extension.enum_type = _FOREIGNENUM +TestUnpackedExtensions.RegisterExtension(unpacked_enum_extension) +test_all_types.message_type = _TESTALLTYPES +TestHugeFieldNumbers.RegisterExtension(test_all_types) +TestExtensionInsideTable.RegisterExtension(test_extension_inside_table_extension) +TestAllExtensions.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['test']) +TestAllExtensions.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['nested_string_extension']) +_TESTNESTEDEXTENSION.extensions_by_name['optionalgroup_extension'].message_type = _TESTNESTEDEXTENSION_OPTIONALGROUP_EXTENSION +TestGroupExtension.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['optionalgroup_extension']) +_TESTNESTEDEXTENSION.extensions_by_name['optional_foreign_enum_extension'].enum_type = _FOREIGNENUM +TestGroupExtension.RegisterExtension(_TESTNESTEDEXTENSION.extensions_by_name['optional_foreign_enum_extension']) +_TESTREQUIRED.extensions_by_name['single'].message_type = _TESTREQUIRED +TestAllExtensions.RegisterExtension(_TESTREQUIRED.extensions_by_name['single']) +_TESTREQUIRED.extensions_by_name['multi'].message_type = _TESTREQUIRED +TestAllExtensions.RegisterExtension(_TESTREQUIRED.extensions_by_name['multi']) +_TESTEXTENSIONORDERINGS1.extensions_by_name['test_ext_orderings1'].message_type = _TESTEXTENSIONORDERINGS1 +TestFieldOrderings.RegisterExtension(_TESTEXTENSIONORDERINGS1.extensions_by_name['test_ext_orderings1']) +_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3.extensions_by_name['test_ext_orderings3'].message_type = _TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3 +TestFieldOrderings.RegisterExtension(_TESTEXTENSIONORDERINGS2_TESTEXTENSIONORDERINGS3.extensions_by_name['test_ext_orderings3']) +_TESTEXTENSIONORDERINGS2.extensions_by_name['test_ext_orderings2'].message_type = _TESTEXTENSIONORDERINGS2 +TestFieldOrderings.RegisterExtension(_TESTEXTENSIONORDERINGS2.extensions_by_name['test_ext_orderings2']) +_TESTPARSINGMERGE.extensions_by_name['optional_ext'].message_type = _TESTALLTYPES +TestParsingMerge.RegisterExtension(_TESTPARSINGMERGE.extensions_by_name['optional_ext']) +_TESTPARSINGMERGE.extensions_by_name['repeated_ext'].message_type = _TESTALLTYPES +TestParsingMerge.RegisterExtension(_TESTPARSINGMERGE.extensions_by_name['repeated_ext']) + +DESCRIPTOR._options = None +_TESTENUMWITHDUPVALUE._options = None +optional_string_piece_extension._options = None +optional_cord_extension._options = None +optional_lazy_message_extension._options = None +repeated_string_piece_extension._options = None +repeated_cord_extension._options = None +repeated_lazy_message_extension._options = None +default_string_piece_extension._options = None +default_cord_extension._options = None +packed_int32_extension._options = None +packed_int64_extension._options = None +packed_uint32_extension._options = None +packed_uint64_extension._options = None +packed_sint32_extension._options = None +packed_sint64_extension._options = None +packed_fixed32_extension._options = None +packed_fixed64_extension._options = None +packed_sfixed32_extension._options = None +packed_sfixed64_extension._options = None +packed_float_extension._options = None +packed_double_extension._options = None +packed_bool_extension._options = None +packed_enum_extension._options = None +unpacked_int32_extension._options = None +unpacked_int64_extension._options = None +unpacked_uint32_extension._options = None +unpacked_uint64_extension._options = None +unpacked_sint32_extension._options = None +unpacked_sint64_extension._options = None +unpacked_fixed32_extension._options = None +unpacked_fixed64_extension._options = None +unpacked_sfixed32_extension._options = None +unpacked_sfixed64_extension._options = None +unpacked_float_extension._options = None +unpacked_double_extension._options = None +unpacked_bool_extension._options = None +unpacked_enum_extension._options = None +_TESTALLTYPES.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPES.fields_by_name['optional_cord']._options = None +_TESTALLTYPES.fields_by_name['optional_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPES.fields_by_name['repeated_cord']._options = None +_TESTALLTYPES.fields_by_name['repeated_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['default_string_piece']._options = None +_TESTALLTYPES.fields_by_name['default_cord']._options = None +_TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32']._options = None +_TESTDEPRECATEDFIELDS.fields_by_name['deprecated_int32_in_oneof']._options = None +_TESTDEPRECATEDMESSAGE._options = None +_TESTEAGERMESSAGE.fields_by_name['sub_message']._options = None +_TESTLAZYMESSAGE.fields_by_name['sub_message']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['StringPieceField']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['CordField']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedStringPieceField']._options = None +_TESTCAMELCASEFIELDNAMES.fields_by_name['RepeatedCordField']._options = None +_TESTEXTREMEDEFAULTVALUES.fields_by_name['string_piece_with_zero']._options = None +_TESTEXTREMEDEFAULTVALUES.fields_by_name['cord_with_zero']._options = None +_TESTONEOF2.fields_by_name['foo_cord']._options = None +_TESTONEOF2.fields_by_name['foo_string_piece']._options = None +_TESTONEOF2.fields_by_name['foo_lazy_message']._options = None +_TESTONEOF2.fields_by_name['bar_cord']._options = None +_TESTONEOF2.fields_by_name['bar_string_piece']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_float']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_double']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_bool']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_enum']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_int32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_int64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_uint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_uint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_fixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_fixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sfixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_sfixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_float']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_double']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_bool']._options = None +_TESTUNPACKEDTYPES.fields_by_name['unpacked_enum']._options = None +_TESTDYNAMICEXTENSIONS.fields_by_name['packed_extension']._options = None +_TESTHUGEFIELDNUMBERS_STRINGSTRINGMAPENTRY._options = None +_TESTHUGEFIELDNUMBERS.fields_by_name['repeated_int32']._options = None +_TESTHUGEFIELDNUMBERS.fields_by_name['packed_int32']._options = None + +_TESTSERVICE = _descriptor.ServiceDescriptor( + name='TestService', + full_name='protobuf_unittest.TestService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + serialized_start=15590, + serialized_end=15743, + methods=[ + _descriptor.MethodDescriptor( + name='Foo', + full_name='protobuf_unittest.TestService.Foo', + index=0, + containing_service=None, + input_type=_FOOREQUEST, + output_type=_FOORESPONSE, + serialized_options=None, + ), + _descriptor.MethodDescriptor( + name='Bar', + full_name='protobuf_unittest.TestService.Bar', + index=1, + containing_service=None, + input_type=_BARREQUEST, + output_type=_BARRESPONSE, + serialized_options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_TESTSERVICE) + +DESCRIPTOR.services_by_name['TestService'] = _TESTSERVICE + +TestService = service_reflection.GeneratedServiceType('TestService', (_service.Service,), dict( + DESCRIPTOR = _TESTSERVICE, + __module__ = 'google.protobuf.unittest_pb2' + )) + +TestService_Stub = service_reflection.GeneratedServiceStubType('TestService_Stub', (TestService,), dict( + DESCRIPTOR = _TESTSERVICE, + __module__ = 'google.protobuf.unittest_pb2' + )) + + +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/unittest_proto3_arena_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/unittest_proto3_arena_pb2.py new file mode 100644 index 0000000..c68ca38 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/unittest_proto3_arena_pb2.py @@ -0,0 +1,999 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/unittest_proto3_arena.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import unittest_import_pb2 as google_dot_protobuf_dot_unittest__import__pb2 +try: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google_dot_protobuf_dot_unittest__import__public__pb2 +except AttributeError: + google_dot_protobuf_dot_unittest__import__public__pb2 = google_dot_protobuf_dot_unittest__import__pb2.google.protobuf.unittest_import_public_pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/unittest_proto3_arena.proto', + package='proto3_arena_unittest', + syntax='proto3', + serialized_options=_b('\370\001\001'), + serialized_pb=_b('\n+google/protobuf/unittest_proto3_arena.proto\x12\x15proto3_arena_unittest\x1a%google/protobuf/unittest_import.proto\"\xc9\x11\n\x0cTestAllTypes\x12\x16\n\x0eoptional_int32\x18\x01 \x01(\x05\x12\x16\n\x0eoptional_int64\x18\x02 \x01(\x03\x12\x17\n\x0foptional_uint32\x18\x03 \x01(\r\x12\x17\n\x0foptional_uint64\x18\x04 \x01(\x04\x12\x17\n\x0foptional_sint32\x18\x05 \x01(\x11\x12\x17\n\x0foptional_sint64\x18\x06 \x01(\x12\x12\x18\n\x10optional_fixed32\x18\x07 \x01(\x07\x12\x18\n\x10optional_fixed64\x18\x08 \x01(\x06\x12\x19\n\x11optional_sfixed32\x18\t \x01(\x0f\x12\x19\n\x11optional_sfixed64\x18\n \x01(\x10\x12\x16\n\x0eoptional_float\x18\x0b \x01(\x02\x12\x17\n\x0foptional_double\x18\x0c \x01(\x01\x12\x15\n\roptional_bool\x18\r \x01(\x08\x12\x17\n\x0foptional_string\x18\x0e \x01(\t\x12\x16\n\x0eoptional_bytes\x18\x0f \x01(\x0c\x12R\n\x17optional_nested_message\x18\x12 \x01(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessage\x12G\n\x18optional_foreign_message\x18\x13 \x01(\x0b\x32%.proto3_arena_unittest.ForeignMessage\x12H\n\x17optional_import_message\x18\x14 \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12L\n\x14optional_nested_enum\x18\x15 \x01(\x0e\x32..proto3_arena_unittest.TestAllTypes.NestedEnum\x12\x41\n\x15optional_foreign_enum\x18\x16 \x01(\x0e\x32\".proto3_arena_unittest.ForeignEnum\x12!\n\x15optional_string_piece\x18\x18 \x01(\tB\x02\x08\x02\x12\x19\n\roptional_cord\x18\x19 \x01(\tB\x02\x08\x01\x12U\n\x1eoptional_public_import_message\x18\x1a \x01(\x0b\x32-.protobuf_unittest_import.PublicImportMessage\x12T\n\x15optional_lazy_message\x18\x1b \x01(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12Q\n\x1coptional_lazy_import_message\x18s \x01(\x0b\x32\'.protobuf_unittest_import.ImportMessageB\x02(\x01\x12\x16\n\x0erepeated_int32\x18\x1f \x03(\x05\x12\x16\n\x0erepeated_int64\x18 \x03(\x03\x12\x17\n\x0frepeated_uint32\x18! \x03(\r\x12\x17\n\x0frepeated_uint64\x18\" \x03(\x04\x12\x17\n\x0frepeated_sint32\x18# \x03(\x11\x12\x17\n\x0frepeated_sint64\x18$ \x03(\x12\x12\x18\n\x10repeated_fixed32\x18% \x03(\x07\x12\x18\n\x10repeated_fixed64\x18& \x03(\x06\x12\x19\n\x11repeated_sfixed32\x18\' \x03(\x0f\x12\x19\n\x11repeated_sfixed64\x18( \x03(\x10\x12\x16\n\x0erepeated_float\x18) \x03(\x02\x12\x17\n\x0frepeated_double\x18* \x03(\x01\x12\x15\n\rrepeated_bool\x18+ \x03(\x08\x12\x17\n\x0frepeated_string\x18, \x03(\t\x12\x16\n\x0erepeated_bytes\x18- \x03(\x0c\x12R\n\x17repeated_nested_message\x18\x30 \x03(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessage\x12G\n\x18repeated_foreign_message\x18\x31 \x03(\x0b\x32%.proto3_arena_unittest.ForeignMessage\x12H\n\x17repeated_import_message\x18\x32 \x03(\x0b\x32\'.protobuf_unittest_import.ImportMessage\x12L\n\x14repeated_nested_enum\x18\x33 \x03(\x0e\x32..proto3_arena_unittest.TestAllTypes.NestedEnum\x12\x41\n\x15repeated_foreign_enum\x18\x34 \x03(\x0e\x32\".proto3_arena_unittest.ForeignEnum\x12!\n\x15repeated_string_piece\x18\x36 \x03(\tB\x02\x08\x02\x12\x19\n\rrepeated_cord\x18\x37 \x03(\tB\x02\x08\x01\x12T\n\x15repeated_lazy_message\x18\x39 \x03(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessageB\x02(\x01\x12\x16\n\x0coneof_uint32\x18o \x01(\rH\x00\x12Q\n\x14oneof_nested_message\x18p \x01(\x0b\x32\x31.proto3_arena_unittest.TestAllTypes.NestedMessageH\x00\x12\x16\n\x0coneof_string\x18q \x01(\tH\x00\x12\x15\n\x0boneof_bytes\x18r \x01(\x0cH\x00\x1a\x1b\n\rNestedMessage\x12\n\n\x02\x62\x62\x18\x01 \x01(\x05\"C\n\nNestedEnum\x12\x08\n\x04ZERO\x10\x00\x12\x07\n\x03\x46OO\x10\x01\x12\x07\n\x03\x42\x41R\x10\x02\x12\x07\n\x03\x42\x41Z\x10\x03\x12\x10\n\x03NEG\x10\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x42\r\n\x0boneof_field\"\xae\x03\n\x0fTestPackedTypes\x12\x18\n\x0cpacked_int32\x18Z \x03(\x05\x42\x02\x10\x01\x12\x18\n\x0cpacked_int64\x18[ \x03(\x03\x42\x02\x10\x01\x12\x19\n\rpacked_uint32\x18\\ \x03(\rB\x02\x10\x01\x12\x19\n\rpacked_uint64\x18] \x03(\x04\x42\x02\x10\x01\x12\x19\n\rpacked_sint32\x18^ \x03(\x11\x42\x02\x10\x01\x12\x19\n\rpacked_sint64\x18_ \x03(\x12\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed32\x18` \x03(\x07\x42\x02\x10\x01\x12\x1a\n\x0epacked_fixed64\x18\x61 \x03(\x06\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed32\x18\x62 \x03(\x0f\x42\x02\x10\x01\x12\x1b\n\x0fpacked_sfixed64\x18\x63 \x03(\x10\x42\x02\x10\x01\x12\x18\n\x0cpacked_float\x18\x64 \x03(\x02\x42\x02\x10\x01\x12\x19\n\rpacked_double\x18\x65 \x03(\x01\x42\x02\x10\x01\x12\x17\n\x0bpacked_bool\x18\x66 \x03(\x08\x42\x02\x10\x01\x12;\n\x0bpacked_enum\x18g \x03(\x0e\x32\".proto3_arena_unittest.ForeignEnumB\x02\x10\x01\"\xdf\x03\n\x11TestUnpackedTypes\x12\x1a\n\x0erepeated_int32\x18\x01 \x03(\x05\x42\x02\x10\x00\x12\x1a\n\x0erepeated_int64\x18\x02 \x03(\x03\x42\x02\x10\x00\x12\x1b\n\x0frepeated_uint32\x18\x03 \x03(\rB\x02\x10\x00\x12\x1b\n\x0frepeated_uint64\x18\x04 \x03(\x04\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint32\x18\x05 \x03(\x11\x42\x02\x10\x00\x12\x1b\n\x0frepeated_sint64\x18\x06 \x03(\x12\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed32\x18\x07 \x03(\x07\x42\x02\x10\x00\x12\x1c\n\x10repeated_fixed64\x18\x08 \x03(\x06\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed32\x18\t \x03(\x0f\x42\x02\x10\x00\x12\x1d\n\x11repeated_sfixed64\x18\n \x03(\x10\x42\x02\x10\x00\x12\x1a\n\x0erepeated_float\x18\x0b \x03(\x02\x42\x02\x10\x00\x12\x1b\n\x0frepeated_double\x18\x0c \x03(\x01\x42\x02\x10\x00\x12\x19\n\rrepeated_bool\x18\r \x03(\x08\x42\x02\x10\x00\x12P\n\x14repeated_nested_enum\x18\x0e \x03(\x0e\x32..proto3_arena_unittest.TestAllTypes.NestedEnumB\x02\x10\x00\"\xc7\x01\n\x12NestedTestAllTypes\x12\x38\n\x05\x63hild\x18\x01 \x01(\x0b\x32).proto3_arena_unittest.NestedTestAllTypes\x12\x34\n\x07payload\x18\x02 \x01(\x0b\x32#.proto3_arena_unittest.TestAllTypes\x12\x41\n\x0erepeated_child\x18\x03 \x03(\x0b\x32).proto3_arena_unittest.NestedTestAllTypes\"\x1b\n\x0e\x46oreignMessage\x12\t\n\x01\x63\x18\x01 \x01(\x05\"\x12\n\x10TestEmptyMessage*R\n\x0b\x46oreignEnum\x12\x10\n\x0c\x46OREIGN_ZERO\x10\x00\x12\x0f\n\x0b\x46OREIGN_FOO\x10\x04\x12\x0f\n\x0b\x46OREIGN_BAR\x10\x05\x12\x0f\n\x0b\x46OREIGN_BAZ\x10\x06\x42\x03\xf8\x01\x01\x62\x06proto3') + , + dependencies=[google_dot_protobuf_dot_unittest__import__pb2.DESCRIPTOR,]) + +_FOREIGNENUM = _descriptor.EnumDescriptor( + name='ForeignEnum', + full_name='proto3_arena_unittest.ForeignEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOREIGN_ZERO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_FOO', index=1, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAR', index=2, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOREIGN_BAZ', index=3, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3527, + serialized_end=3609, +) +_sym_db.RegisterEnumDescriptor(_FOREIGNENUM) + +ForeignEnum = enum_type_wrapper.EnumTypeWrapper(_FOREIGNENUM) +FOREIGN_ZERO = 0 +FOREIGN_FOO = 4 +FOREIGN_BAR = 5 +FOREIGN_BAZ = 6 + + +_TESTALLTYPES_NESTEDENUM = _descriptor.EnumDescriptor( + name='NestedEnum', + full_name='proto3_arena_unittest.TestAllTypes.NestedEnum', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='ZERO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FOO', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAZ', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='NEG', index=4, number=-1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2277, + serialized_end=2344, +) +_sym_db.RegisterEnumDescriptor(_TESTALLTYPES_NESTEDENUM) + + +_TESTALLTYPES_NESTEDMESSAGE = _descriptor.Descriptor( + name='NestedMessage', + full_name='proto3_arena_unittest.TestAllTypes.NestedMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bb', full_name='proto3_arena_unittest.TestAllTypes.NestedMessage.bb', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2248, + serialized_end=2275, +) + +_TESTALLTYPES = _descriptor.Descriptor( + name='TestAllTypes', + full_name='proto3_arena_unittest.TestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='optional_int32', full_name='proto3_arena_unittest.TestAllTypes.optional_int32', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_int64', full_name='proto3_arena_unittest.TestAllTypes.optional_int64', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint32', full_name='proto3_arena_unittest.TestAllTypes.optional_uint32', index=2, + number=3, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_uint64', full_name='proto3_arena_unittest.TestAllTypes.optional_uint64', index=3, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint32', full_name='proto3_arena_unittest.TestAllTypes.optional_sint32', index=4, + number=5, type=17, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sint64', full_name='proto3_arena_unittest.TestAllTypes.optional_sint64', index=5, + number=6, type=18, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed32', full_name='proto3_arena_unittest.TestAllTypes.optional_fixed32', index=6, + number=7, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_fixed64', full_name='proto3_arena_unittest.TestAllTypes.optional_fixed64', index=7, + number=8, type=6, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed32', full_name='proto3_arena_unittest.TestAllTypes.optional_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_sfixed64', full_name='proto3_arena_unittest.TestAllTypes.optional_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_float', full_name='proto3_arena_unittest.TestAllTypes.optional_float', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_double', full_name='proto3_arena_unittest.TestAllTypes.optional_double', index=11, + number=12, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bool', full_name='proto3_arena_unittest.TestAllTypes.optional_bool', index=12, + number=13, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string', full_name='proto3_arena_unittest.TestAllTypes.optional_string', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_bytes', full_name='proto3_arena_unittest.TestAllTypes.optional_bytes', index=14, + number=15, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_message', full_name='proto3_arena_unittest.TestAllTypes.optional_nested_message', index=15, + number=18, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_message', full_name='proto3_arena_unittest.TestAllTypes.optional_foreign_message', index=16, + number=19, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_import_message', full_name='proto3_arena_unittest.TestAllTypes.optional_import_message', index=17, + number=20, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_nested_enum', full_name='proto3_arena_unittest.TestAllTypes.optional_nested_enum', index=18, + number=21, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_foreign_enum', full_name='proto3_arena_unittest.TestAllTypes.optional_foreign_enum', index=19, + number=22, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_string_piece', full_name='proto3_arena_unittest.TestAllTypes.optional_string_piece', index=20, + number=24, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_cord', full_name='proto3_arena_unittest.TestAllTypes.optional_cord', index=21, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_public_import_message', full_name='proto3_arena_unittest.TestAllTypes.optional_public_import_message', index=22, + number=26, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_lazy_message', full_name='proto3_arena_unittest.TestAllTypes.optional_lazy_message', index=23, + number=27, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optional_lazy_import_message', full_name='proto3_arena_unittest.TestAllTypes.optional_lazy_import_message', index=24, + number=115, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='proto3_arena_unittest.TestAllTypes.repeated_int32', index=25, + number=31, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='proto3_arena_unittest.TestAllTypes.repeated_int64', index=26, + number=32, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='proto3_arena_unittest.TestAllTypes.repeated_uint32', index=27, + number=33, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='proto3_arena_unittest.TestAllTypes.repeated_uint64', index=28, + number=34, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='proto3_arena_unittest.TestAllTypes.repeated_sint32', index=29, + number=35, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='proto3_arena_unittest.TestAllTypes.repeated_sint64', index=30, + number=36, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='proto3_arena_unittest.TestAllTypes.repeated_fixed32', index=31, + number=37, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='proto3_arena_unittest.TestAllTypes.repeated_fixed64', index=32, + number=38, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='proto3_arena_unittest.TestAllTypes.repeated_sfixed32', index=33, + number=39, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='proto3_arena_unittest.TestAllTypes.repeated_sfixed64', index=34, + number=40, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='proto3_arena_unittest.TestAllTypes.repeated_float', index=35, + number=41, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='proto3_arena_unittest.TestAllTypes.repeated_double', index=36, + number=42, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='proto3_arena_unittest.TestAllTypes.repeated_bool', index=37, + number=43, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='proto3_arena_unittest.TestAllTypes.repeated_string', index=38, + number=44, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes', full_name='proto3_arena_unittest.TestAllTypes.repeated_bytes', index=39, + number=45, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_nested_message', index=40, + number=48, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_foreign_message', index=41, + number=49, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_import_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_import_message', index=42, + number=50, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='proto3_arena_unittest.TestAllTypes.repeated_nested_enum', index=43, + number=51, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_foreign_enum', full_name='proto3_arena_unittest.TestAllTypes.repeated_foreign_enum', index=44, + number=52, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_piece', full_name='proto3_arena_unittest.TestAllTypes.repeated_string_piece', index=45, + number=54, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\002'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_cord', full_name='proto3_arena_unittest.TestAllTypes.repeated_cord', index=46, + number=55, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\010\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_lazy_message', full_name='proto3_arena_unittest.TestAllTypes.repeated_lazy_message', index=47, + number=57, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('(\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_uint32', full_name='proto3_arena_unittest.TestAllTypes.oneof_uint32', index=48, + number=111, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_nested_message', full_name='proto3_arena_unittest.TestAllTypes.oneof_nested_message', index=49, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string', full_name='proto3_arena_unittest.TestAllTypes.oneof_string', index=50, + number=113, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes', full_name='proto3_arena_unittest.TestAllTypes.oneof_bytes', index=51, + number=114, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTALLTYPES_NESTEDMESSAGE, ], + enum_types=[ + _TESTALLTYPES_NESTEDENUM, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_field', full_name='proto3_arena_unittest.TestAllTypes.oneof_field', + index=0, containing_type=None, fields=[]), + ], + serialized_start=110, + serialized_end=2359, +) + + +_TESTPACKEDTYPES = _descriptor.Descriptor( + name='TestPackedTypes', + full_name='proto3_arena_unittest.TestPackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='packed_int32', full_name='proto3_arena_unittest.TestPackedTypes.packed_int32', index=0, + number=90, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_int64', full_name='proto3_arena_unittest.TestPackedTypes.packed_int64', index=1, + number=91, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint32', full_name='proto3_arena_unittest.TestPackedTypes.packed_uint32', index=2, + number=92, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_uint64', full_name='proto3_arena_unittest.TestPackedTypes.packed_uint64', index=3, + number=93, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint32', full_name='proto3_arena_unittest.TestPackedTypes.packed_sint32', index=4, + number=94, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sint64', full_name='proto3_arena_unittest.TestPackedTypes.packed_sint64', index=5, + number=95, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed32', full_name='proto3_arena_unittest.TestPackedTypes.packed_fixed32', index=6, + number=96, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_fixed64', full_name='proto3_arena_unittest.TestPackedTypes.packed_fixed64', index=7, + number=97, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed32', full_name='proto3_arena_unittest.TestPackedTypes.packed_sfixed32', index=8, + number=98, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_sfixed64', full_name='proto3_arena_unittest.TestPackedTypes.packed_sfixed64', index=9, + number=99, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_float', full_name='proto3_arena_unittest.TestPackedTypes.packed_float', index=10, + number=100, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_double', full_name='proto3_arena_unittest.TestPackedTypes.packed_double', index=11, + number=101, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_bool', full_name='proto3_arena_unittest.TestPackedTypes.packed_bool', index=12, + number=102, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='proto3_arena_unittest.TestPackedTypes.packed_enum', index=13, + number=103, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\001'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2362, + serialized_end=2792, +) + + +_TESTUNPACKEDTYPES = _descriptor.Descriptor( + name='TestUnpackedTypes', + full_name='proto3_arena_unittest.TestUnpackedTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='repeated_int32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_int32', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_int64', index=1, + number=2, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_uint32', index=2, + number=3, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_uint64', index=3, + number=4, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sint32', index=4, + number=5, type=17, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sint64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sint64', index=5, + number=6, type=18, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_fixed32', index=6, + number=7, type=7, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_fixed64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_fixed64', index=7, + number=8, type=6, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed32', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sfixed32', index=8, + number=9, type=15, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_sfixed64', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_sfixed64', index=9, + number=10, type=16, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_float', index=10, + number=11, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_double', index=11, + number=12, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_bool', index=12, + number=13, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_nested_enum', full_name='proto3_arena_unittest.TestUnpackedTypes.repeated_nested_enum', index=13, + number=14, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=_b('\020\000'), file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2795, + serialized_end=3274, +) + + +_NESTEDTESTALLTYPES = _descriptor.Descriptor( + name='NestedTestAllTypes', + full_name='proto3_arena_unittest.NestedTestAllTypes', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='child', full_name='proto3_arena_unittest.NestedTestAllTypes.child', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payload', full_name='proto3_arena_unittest.NestedTestAllTypes.payload', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_child', full_name='proto3_arena_unittest.NestedTestAllTypes.repeated_child', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3277, + serialized_end=3476, +) + + +_FOREIGNMESSAGE = _descriptor.Descriptor( + name='ForeignMessage', + full_name='proto3_arena_unittest.ForeignMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='c', full_name='proto3_arena_unittest.ForeignMessage.c', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3478, + serialized_end=3505, +) + + +_TESTEMPTYMESSAGE = _descriptor.Descriptor( + name='TestEmptyMessage', + full_name='proto3_arena_unittest.TestEmptyMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3507, + serialized_end=3525, +) + +_TESTALLTYPES_NESTEDMESSAGE.containing_type = _TESTALLTYPES +_TESTALLTYPES.fields_by_name['optional_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['optional_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['optional_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['optional_public_import_message'].message_type = google_dot_protobuf_dot_unittest__import__public__pb2._PUBLICIMPORTMESSAGE +_TESTALLTYPES.fields_by_name['optional_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['optional_lazy_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['repeated_foreign_message'].message_type = _FOREIGNMESSAGE +_TESTALLTYPES.fields_by_name['repeated_import_message'].message_type = google_dot_protobuf_dot_unittest__import__pb2._IMPORTMESSAGE +_TESTALLTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_TESTALLTYPES.fields_by_name['repeated_foreign_enum'].enum_type = _FOREIGNENUM +_TESTALLTYPES.fields_by_name['repeated_lazy_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES.fields_by_name['oneof_nested_message'].message_type = _TESTALLTYPES_NESTEDMESSAGE +_TESTALLTYPES_NESTEDENUM.containing_type = _TESTALLTYPES +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_uint32']) +_TESTALLTYPES.fields_by_name['oneof_uint32'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_nested_message']) +_TESTALLTYPES.fields_by_name['oneof_nested_message'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_string']) +_TESTALLTYPES.fields_by_name['oneof_string'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTALLTYPES.oneofs_by_name['oneof_field'].fields.append( + _TESTALLTYPES.fields_by_name['oneof_bytes']) +_TESTALLTYPES.fields_by_name['oneof_bytes'].containing_oneof = _TESTALLTYPES.oneofs_by_name['oneof_field'] +_TESTPACKEDTYPES.fields_by_name['packed_enum'].enum_type = _FOREIGNENUM +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum'].enum_type = _TESTALLTYPES_NESTEDENUM +_NESTEDTESTALLTYPES.fields_by_name['child'].message_type = _NESTEDTESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['payload'].message_type = _TESTALLTYPES +_NESTEDTESTALLTYPES.fields_by_name['repeated_child'].message_type = _NESTEDTESTALLTYPES +DESCRIPTOR.message_types_by_name['TestAllTypes'] = _TESTALLTYPES +DESCRIPTOR.message_types_by_name['TestPackedTypes'] = _TESTPACKEDTYPES +DESCRIPTOR.message_types_by_name['TestUnpackedTypes'] = _TESTUNPACKEDTYPES +DESCRIPTOR.message_types_by_name['NestedTestAllTypes'] = _NESTEDTESTALLTYPES +DESCRIPTOR.message_types_by_name['ForeignMessage'] = _FOREIGNMESSAGE +DESCRIPTOR.message_types_by_name['TestEmptyMessage'] = _TESTEMPTYMESSAGE +DESCRIPTOR.enum_types_by_name['ForeignEnum'] = _FOREIGNENUM +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestAllTypes = _reflection.GeneratedProtocolMessageType('TestAllTypes', (_message.Message,), dict( + + NestedMessage = _reflection.GeneratedProtocolMessageType('NestedMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTALLTYPES_NESTEDMESSAGE, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestAllTypes.NestedMessage) + )) + , + DESCRIPTOR = _TESTALLTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestAllTypes) + )) +_sym_db.RegisterMessage(TestAllTypes) +_sym_db.RegisterMessage(TestAllTypes.NestedMessage) + +TestPackedTypes = _reflection.GeneratedProtocolMessageType('TestPackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTPACKEDTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestPackedTypes) + )) +_sym_db.RegisterMessage(TestPackedTypes) + +TestUnpackedTypes = _reflection.GeneratedProtocolMessageType('TestUnpackedTypes', (_message.Message,), dict( + DESCRIPTOR = _TESTUNPACKEDTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestUnpackedTypes) + )) +_sym_db.RegisterMessage(TestUnpackedTypes) + +NestedTestAllTypes = _reflection.GeneratedProtocolMessageType('NestedTestAllTypes', (_message.Message,), dict( + DESCRIPTOR = _NESTEDTESTALLTYPES, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.NestedTestAllTypes) + )) +_sym_db.RegisterMessage(NestedTestAllTypes) + +ForeignMessage = _reflection.GeneratedProtocolMessageType('ForeignMessage', (_message.Message,), dict( + DESCRIPTOR = _FOREIGNMESSAGE, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.ForeignMessage) + )) +_sym_db.RegisterMessage(ForeignMessage) + +TestEmptyMessage = _reflection.GeneratedProtocolMessageType('TestEmptyMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTEMPTYMESSAGE, + __module__ = 'google.protobuf.unittest_proto3_arena_pb2' + # @@protoc_insertion_point(class_scope:proto3_arena_unittest.TestEmptyMessage) + )) +_sym_db.RegisterMessage(TestEmptyMessage) + + +DESCRIPTOR._options = None +_TESTALLTYPES.fields_by_name['optional_string_piece']._options = None +_TESTALLTYPES.fields_by_name['optional_cord']._options = None +_TESTALLTYPES.fields_by_name['optional_lazy_message']._options = None +_TESTALLTYPES.fields_by_name['optional_lazy_import_message']._options = None +_TESTALLTYPES.fields_by_name['repeated_string_piece']._options = None +_TESTALLTYPES.fields_by_name['repeated_cord']._options = None +_TESTALLTYPES.fields_by_name['repeated_lazy_message']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_int64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_uint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sint64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_fixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed32']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_sfixed64']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_float']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_double']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_bool']._options = None +_TESTPACKEDTYPES.fields_by_name['packed_enum']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_int32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_int64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_uint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sint64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_fixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed32']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_sfixed64']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_float']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_double']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_bool']._options = None +_TESTUNPACKEDTYPES.fields_by_name['repeated_nested_enum']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/util/__init__.py b/venv/lib/python3.7/site-packages/google/protobuf/util/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/lib/python3.7/site-packages/google/protobuf/util/json_format_proto3_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/util/json_format_proto3_pb2.py new file mode 100644 index 0000000..ff09093 --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/util/json_format_proto3_pb2.py @@ -0,0 +1,1895 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/util/json_format_proto3.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 +from google.protobuf import unittest_pb2 as google_dot_protobuf_dot_unittest__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/util/json_format_proto3.proto', + package='proto3', + syntax='proto3', + serialized_options=_b('\n\030com.google.protobuf.utilB\020JsonFormatProto3'), + serialized_pb=_b('\n-google/protobuf/util/json_format_proto3.proto\x12\x06proto3\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x19google/protobuf/any.proto\x1a google/protobuf/field_mask.proto\x1a\x1egoogle/protobuf/unittest.proto\"\x1c\n\x0bMessageType\x12\r\n\x05value\x18\x01 \x01(\x05\"\x94\x05\n\x0bTestMessage\x12\x12\n\nbool_value\x18\x01 \x01(\x08\x12\x13\n\x0bint32_value\x18\x02 \x01(\x05\x12\x13\n\x0bint64_value\x18\x03 \x01(\x03\x12\x14\n\x0cuint32_value\x18\x04 \x01(\r\x12\x14\n\x0cuint64_value\x18\x05 \x01(\x04\x12\x13\n\x0b\x66loat_value\x18\x06 \x01(\x02\x12\x14\n\x0c\x64ouble_value\x18\x07 \x01(\x01\x12\x14\n\x0cstring_value\x18\x08 \x01(\t\x12\x13\n\x0b\x62ytes_value\x18\t \x01(\x0c\x12$\n\nenum_value\x18\n \x01(\x0e\x32\x10.proto3.EnumType\x12*\n\rmessage_value\x18\x0b \x01(\x0b\x32\x13.proto3.MessageType\x12\x1b\n\x13repeated_bool_value\x18\x15 \x03(\x08\x12\x1c\n\x14repeated_int32_value\x18\x16 \x03(\x05\x12\x1c\n\x14repeated_int64_value\x18\x17 \x03(\x03\x12\x1d\n\x15repeated_uint32_value\x18\x18 \x03(\r\x12\x1d\n\x15repeated_uint64_value\x18\x19 \x03(\x04\x12\x1c\n\x14repeated_float_value\x18\x1a \x03(\x02\x12\x1d\n\x15repeated_double_value\x18\x1b \x03(\x01\x12\x1d\n\x15repeated_string_value\x18\x1c \x03(\t\x12\x1c\n\x14repeated_bytes_value\x18\x1d \x03(\x0c\x12-\n\x13repeated_enum_value\x18\x1e \x03(\x0e\x32\x10.proto3.EnumType\x12\x33\n\x16repeated_message_value\x18\x1f \x03(\x0b\x32\x13.proto3.MessageType\"\xd4\x01\n\tTestOneof\x12\x1b\n\x11oneof_int32_value\x18\x01 \x01(\x05H\x00\x12\x1c\n\x12oneof_string_value\x18\x02 \x01(\tH\x00\x12\x1b\n\x11oneof_bytes_value\x18\x03 \x01(\x0cH\x00\x12,\n\x10oneof_enum_value\x18\x04 \x01(\x0e\x32\x10.proto3.EnumTypeH\x00\x12\x32\n\x13oneof_message_value\x18\x05 \x01(\x0b\x32\x13.proto3.MessageTypeH\x00\x42\r\n\x0boneof_value\"\xe1\x04\n\x07TestMap\x12.\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32\x1c.proto3.TestMap.BoolMapEntry\x12\x30\n\tint32_map\x18\x02 \x03(\x0b\x32\x1d.proto3.TestMap.Int32MapEntry\x12\x30\n\tint64_map\x18\x03 \x03(\x0b\x32\x1d.proto3.TestMap.Int64MapEntry\x12\x32\n\nuint32_map\x18\x04 \x03(\x0b\x32\x1e.proto3.TestMap.Uint32MapEntry\x12\x32\n\nuint64_map\x18\x05 \x03(\x0b\x32\x1e.proto3.TestMap.Uint64MapEntry\x12\x32\n\nstring_map\x18\x06 \x03(\x0b\x32\x1e.proto3.TestMap.StringMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\x85\x06\n\rTestNestedMap\x12\x34\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32\".proto3.TestNestedMap.BoolMapEntry\x12\x36\n\tint32_map\x18\x02 \x03(\x0b\x32#.proto3.TestNestedMap.Int32MapEntry\x12\x36\n\tint64_map\x18\x03 \x03(\x0b\x32#.proto3.TestNestedMap.Int64MapEntry\x12\x38\n\nuint32_map\x18\x04 \x03(\x0b\x32$.proto3.TestNestedMap.Uint32MapEntry\x12\x38\n\nuint64_map\x18\x05 \x03(\x0b\x32$.proto3.TestNestedMap.Uint64MapEntry\x12\x38\n\nstring_map\x18\x06 \x03(\x0b\x32$.proto3.TestNestedMap.StringMapEntry\x12\x32\n\x07map_map\x18\x07 \x03(\x0b\x32!.proto3.TestNestedMap.MapMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x44\n\x0bMapMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.proto3.TestNestedMap:\x02\x38\x01\"\xee\x07\n\x0bTestWrapper\x12.\n\nbool_value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\x12\x30\n\x0bint32_value\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.Int32Value\x12\x30\n\x0bint64_value\x18\x03 \x01(\x0b\x32\x1b.google.protobuf.Int64Value\x12\x32\n\x0cuint32_value\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x32\n\x0cuint64_value\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12\x30\n\x0b\x66loat_value\x18\x06 \x01(\x0b\x32\x1b.google.protobuf.FloatValue\x12\x32\n\x0c\x64ouble_value\x18\x07 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue\x12\x32\n\x0cstring_value\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.StringValue\x12\x30\n\x0b\x62ytes_value\x18\t \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x12\x37\n\x13repeated_bool_value\x18\x0b \x03(\x0b\x32\x1a.google.protobuf.BoolValue\x12\x39\n\x14repeated_int32_value\x18\x0c \x03(\x0b\x32\x1b.google.protobuf.Int32Value\x12\x39\n\x14repeated_int64_value\x18\r \x03(\x0b\x32\x1b.google.protobuf.Int64Value\x12;\n\x15repeated_uint32_value\x18\x0e \x03(\x0b\x32\x1c.google.protobuf.UInt32Value\x12;\n\x15repeated_uint64_value\x18\x0f \x03(\x0b\x32\x1c.google.protobuf.UInt64Value\x12\x39\n\x14repeated_float_value\x18\x10 \x03(\x0b\x32\x1b.google.protobuf.FloatValue\x12;\n\x15repeated_double_value\x18\x11 \x03(\x0b\x32\x1c.google.protobuf.DoubleValue\x12;\n\x15repeated_string_value\x18\x12 \x03(\x0b\x32\x1c.google.protobuf.StringValue\x12\x39\n\x14repeated_bytes_value\x18\x13 \x03(\x0b\x32\x1b.google.protobuf.BytesValue\"n\n\rTestTimestamp\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x0cTestDuration\x12(\n\x05value\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x19.google.protobuf.Duration\":\n\rTestFieldMask\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"e\n\nTestStruct\x12&\n\x05value\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12/\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x17.google.protobuf.Struct\"\\\n\x07TestAny\x12#\n\x05value\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12,\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x14.google.protobuf.Any\"b\n\tTestValue\x12%\n\x05value\x18\x01 \x01(\x0b\x32\x16.google.protobuf.Value\x12.\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x16.google.protobuf.Value\"n\n\rTestListValue\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.ListValue\x12\x32\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.ListValue\"\x89\x01\n\rTestBoolValue\x12\x12\n\nbool_value\x18\x01 \x01(\x08\x12\x34\n\x08\x62ool_map\x18\x02 \x03(\x0b\x32\".proto3.TestBoolValue.BoolMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"+\n\x12TestCustomJsonName\x12\x15\n\x05value\x18\x01 \x01(\x05R\x06@value\"J\n\x0eTestExtensions\x12\x38\n\nextensions\x18\x01 \x01(\x0b\x32$.protobuf_unittest.TestAllExtensions\"\x84\x01\n\rTestEnumValue\x12%\n\x0b\x65num_value1\x18\x01 \x01(\x0e\x32\x10.proto3.EnumType\x12%\n\x0b\x65num_value2\x18\x02 \x01(\x0e\x32\x10.proto3.EnumType\x12%\n\x0b\x65num_value3\x18\x03 \x01(\x0e\x32\x10.proto3.EnumType*\x1c\n\x08\x45numType\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x42,\n\x18\x63om.google.protobuf.utilB\x10JsonFormatProto3b\x06proto3') + , + dependencies=[google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__pb2.DESCRIPTOR,]) + +_ENUMTYPE = _descriptor.EnumDescriptor( + name='EnumType', + full_name='proto3.EnumType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=4668, + serialized_end=4696, +) +_sym_db.RegisterEnumDescriptor(_ENUMTYPE) + +EnumType = enum_type_wrapper.EnumTypeWrapper(_ENUMTYPE) +FOO = 0 +BAR = 1 + + + +_MESSAGETYPE = _descriptor.Descriptor( + name='MessageType', + full_name='proto3.MessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.MessageType.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=277, + serialized_end=305, +) + + +_TESTMESSAGE = _descriptor.Descriptor( + name='TestMessage', + full_name='proto3.TestMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestMessage.bool_value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_value', full_name='proto3.TestMessage.int32_value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_value', full_name='proto3.TestMessage.int64_value', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_value', full_name='proto3.TestMessage.uint32_value', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_value', full_name='proto3.TestMessage.uint64_value', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='float_value', full_name='proto3.TestMessage.float_value', index=5, + number=6, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_value', full_name='proto3.TestMessage.double_value', index=6, + number=7, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='proto3.TestMessage.string_value', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_value', full_name='proto3.TestMessage.bytes_value', index=8, + number=9, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_value', full_name='proto3.TestMessage.enum_value', index=9, + number=10, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message_value', full_name='proto3.TestMessage.message_value', index=10, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool_value', full_name='proto3.TestMessage.repeated_bool_value', index=11, + number=21, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32_value', full_name='proto3.TestMessage.repeated_int32_value', index=12, + number=22, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64_value', full_name='proto3.TestMessage.repeated_int64_value', index=13, + number=23, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32_value', full_name='proto3.TestMessage.repeated_uint32_value', index=14, + number=24, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64_value', full_name='proto3.TestMessage.repeated_uint64_value', index=15, + number=25, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float_value', full_name='proto3.TestMessage.repeated_float_value', index=16, + number=26, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double_value', full_name='proto3.TestMessage.repeated_double_value', index=17, + number=27, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_value', full_name='proto3.TestMessage.repeated_string_value', index=18, + number=28, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes_value', full_name='proto3.TestMessage.repeated_bytes_value', index=19, + number=29, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_enum_value', full_name='proto3.TestMessage.repeated_enum_value', index=20, + number=30, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_message_value', full_name='proto3.TestMessage.repeated_message_value', index=21, + number=31, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=308, + serialized_end=968, +) + + +_TESTONEOF = _descriptor.Descriptor( + name='TestOneof', + full_name='proto3.TestOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='oneof_int32_value', full_name='proto3.TestOneof.oneof_int32_value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_string_value', full_name='proto3.TestOneof.oneof_string_value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_bytes_value', full_name='proto3.TestOneof.oneof_bytes_value', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_enum_value', full_name='proto3.TestOneof.oneof_enum_value', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oneof_message_value', full_name='proto3.TestOneof.oneof_message_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_value', full_name='proto3.TestOneof.oneof_value', + index=0, containing_type=None, fields=[]), + ], + serialized_start=971, + serialized_end=1183, +) + + +_TESTMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1501, + serialized_end=1547, +) + +_TESTMAP_INT32MAPENTRY = _descriptor.Descriptor( + name='Int32MapEntry', + full_name='proto3.TestMap.Int32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Int32MapEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Int32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1549, + serialized_end=1596, +) + +_TESTMAP_INT64MAPENTRY = _descriptor.Descriptor( + name='Int64MapEntry', + full_name='proto3.TestMap.Int64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Int64MapEntry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Int64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1598, + serialized_end=1645, +) + +_TESTMAP_UINT32MAPENTRY = _descriptor.Descriptor( + name='Uint32MapEntry', + full_name='proto3.TestMap.Uint32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Uint32MapEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Uint32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1647, + serialized_end=1695, +) + +_TESTMAP_UINT64MAPENTRY = _descriptor.Descriptor( + name='Uint64MapEntry', + full_name='proto3.TestMap.Uint64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Uint64MapEntry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Uint64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1697, + serialized_end=1745, +) + +_TESTMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.StringMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1747, + serialized_end=1795, +) + +_TESTMAP = _descriptor.Descriptor( + name='TestMap', + full_name='proto3.TestMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_map', full_name='proto3.TestMap.int32_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_map', full_name='proto3.TestMap.int64_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_map', full_name='proto3.TestMap.uint32_map', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_map', full_name='proto3.TestMap.uint64_map', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestMap.string_map', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTMAP_BOOLMAPENTRY, _TESTMAP_INT32MAPENTRY, _TESTMAP_INT64MAPENTRY, _TESTMAP_UINT32MAPENTRY, _TESTMAP_UINT64MAPENTRY, _TESTMAP_STRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1186, + serialized_end=1795, +) + + +_TESTNESTEDMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestNestedMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1501, + serialized_end=1547, +) + +_TESTNESTEDMAP_INT32MAPENTRY = _descriptor.Descriptor( + name='Int32MapEntry', + full_name='proto3.TestNestedMap.Int32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Int32MapEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Int32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1549, + serialized_end=1596, +) + +_TESTNESTEDMAP_INT64MAPENTRY = _descriptor.Descriptor( + name='Int64MapEntry', + full_name='proto3.TestNestedMap.Int64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Int64MapEntry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Int64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1598, + serialized_end=1645, +) + +_TESTNESTEDMAP_UINT32MAPENTRY = _descriptor.Descriptor( + name='Uint32MapEntry', + full_name='proto3.TestNestedMap.Uint32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Uint32MapEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Uint32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1647, + serialized_end=1695, +) + +_TESTNESTEDMAP_UINT64MAPENTRY = _descriptor.Descriptor( + name='Uint64MapEntry', + full_name='proto3.TestNestedMap.Uint64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Uint64MapEntry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Uint64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1697, + serialized_end=1745, +) + +_TESTNESTEDMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestNestedMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.StringMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1747, + serialized_end=1795, +) + +_TESTNESTEDMAP_MAPMAPENTRY = _descriptor.Descriptor( + name='MapMapEntry', + full_name='proto3.TestNestedMap.MapMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.MapMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.MapMapEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2503, + serialized_end=2571, +) + +_TESTNESTEDMAP = _descriptor.Descriptor( + name='TestNestedMap', + full_name='proto3.TestNestedMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestNestedMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_map', full_name='proto3.TestNestedMap.int32_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_map', full_name='proto3.TestNestedMap.int64_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_map', full_name='proto3.TestNestedMap.uint32_map', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_map', full_name='proto3.TestNestedMap.uint64_map', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestNestedMap.string_map', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='map_map', full_name='proto3.TestNestedMap.map_map', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTNESTEDMAP_BOOLMAPENTRY, _TESTNESTEDMAP_INT32MAPENTRY, _TESTNESTEDMAP_INT64MAPENTRY, _TESTNESTEDMAP_UINT32MAPENTRY, _TESTNESTEDMAP_UINT64MAPENTRY, _TESTNESTEDMAP_STRINGMAPENTRY, _TESTNESTEDMAP_MAPMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1798, + serialized_end=2571, +) + + +_TESTWRAPPER = _descriptor.Descriptor( + name='TestWrapper', + full_name='proto3.TestWrapper', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestWrapper.bool_value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int32_value', full_name='proto3.TestWrapper.int32_value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int64_value', full_name='proto3.TestWrapper.int64_value', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint32_value', full_name='proto3.TestWrapper.uint32_value', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='uint64_value', full_name='proto3.TestWrapper.uint64_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='float_value', full_name='proto3.TestWrapper.float_value', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='double_value', full_name='proto3.TestWrapper.double_value', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='proto3.TestWrapper.string_value', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bytes_value', full_name='proto3.TestWrapper.bytes_value', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bool_value', full_name='proto3.TestWrapper.repeated_bool_value', index=9, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int32_value', full_name='proto3.TestWrapper.repeated_int32_value', index=10, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_int64_value', full_name='proto3.TestWrapper.repeated_int64_value', index=11, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint32_value', full_name='proto3.TestWrapper.repeated_uint32_value', index=12, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_uint64_value', full_name='proto3.TestWrapper.repeated_uint64_value', index=13, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_float_value', full_name='proto3.TestWrapper.repeated_float_value', index=14, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_double_value', full_name='proto3.TestWrapper.repeated_double_value', index=15, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_string_value', full_name='proto3.TestWrapper.repeated_string_value', index=16, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_bytes_value', full_name='proto3.TestWrapper.repeated_bytes_value', index=17, + number=19, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2574, + serialized_end=3580, +) + + +_TESTTIMESTAMP = _descriptor.Descriptor( + name='TestTimestamp', + full_name='proto3.TestTimestamp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestTimestamp.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestTimestamp.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3582, + serialized_end=3692, +) + + +_TESTDURATION = _descriptor.Descriptor( + name='TestDuration', + full_name='proto3.TestDuration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestDuration.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestDuration.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3694, + serialized_end=3801, +) + + +_TESTFIELDMASK = _descriptor.Descriptor( + name='TestFieldMask', + full_name='proto3.TestFieldMask', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestFieldMask.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3803, + serialized_end=3861, +) + + +_TESTSTRUCT = _descriptor.Descriptor( + name='TestStruct', + full_name='proto3.TestStruct', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestStruct.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestStruct.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3863, + serialized_end=3964, +) + + +_TESTANY = _descriptor.Descriptor( + name='TestAny', + full_name='proto3.TestAny', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestAny.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestAny.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3966, + serialized_end=4058, +) + + +_TESTVALUE = _descriptor.Descriptor( + name='TestValue', + full_name='proto3.TestValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestValue.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestValue.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4060, + serialized_end=4158, +) + + +_TESTLISTVALUE = _descriptor.Descriptor( + name='TestListValue', + full_name='proto3.TestListValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestListValue.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestListValue.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4160, + serialized_end=4270, +) + + +_TESTBOOLVALUE_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestBoolValue.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestBoolValue.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestBoolValue.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1501, + serialized_end=1547, +) + +_TESTBOOLVALUE = _descriptor.Descriptor( + name='TestBoolValue', + full_name='proto3.TestBoolValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestBoolValue.bool_value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestBoolValue.bool_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_TESTBOOLVALUE_BOOLMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4273, + serialized_end=4410, +) + + +_TESTCUSTOMJSONNAME = _descriptor.Descriptor( + name='TestCustomJsonName', + full_name='proto3.TestCustomJsonName', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestCustomJsonName.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='@value', file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4412, + serialized_end=4455, +) + + +_TESTEXTENSIONS = _descriptor.Descriptor( + name='TestExtensions', + full_name='proto3.TestExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='extensions', full_name='proto3.TestExtensions.extensions', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4457, + serialized_end=4531, +) + + +_TESTENUMVALUE = _descriptor.Descriptor( + name='TestEnumValue', + full_name='proto3.TestEnumValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='enum_value1', full_name='proto3.TestEnumValue.enum_value1', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_value2', full_name='proto3.TestEnumValue.enum_value2', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_value3', full_name='proto3.TestEnumValue.enum_value3', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4534, + serialized_end=4666, +) + +_TESTMESSAGE.fields_by_name['enum_value'].enum_type = _ENUMTYPE +_TESTMESSAGE.fields_by_name['message_value'].message_type = _MESSAGETYPE +_TESTMESSAGE.fields_by_name['repeated_enum_value'].enum_type = _ENUMTYPE +_TESTMESSAGE.fields_by_name['repeated_message_value'].message_type = _MESSAGETYPE +_TESTONEOF.fields_by_name['oneof_enum_value'].enum_type = _ENUMTYPE +_TESTONEOF.fields_by_name['oneof_message_value'].message_type = _MESSAGETYPE +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_int32_value']) +_TESTONEOF.fields_by_name['oneof_int32_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_string_value']) +_TESTONEOF.fields_by_name['oneof_string_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_bytes_value']) +_TESTONEOF.fields_by_name['oneof_bytes_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_enum_value']) +_TESTONEOF.fields_by_name['oneof_enum_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_message_value']) +_TESTONEOF.fields_by_name['oneof_message_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTMAP_BOOLMAPENTRY.containing_type = _TESTMAP +_TESTMAP_INT32MAPENTRY.containing_type = _TESTMAP +_TESTMAP_INT64MAPENTRY.containing_type = _TESTMAP +_TESTMAP_UINT32MAPENTRY.containing_type = _TESTMAP +_TESTMAP_UINT64MAPENTRY.containing_type = _TESTMAP +_TESTMAP_STRINGMAPENTRY.containing_type = _TESTMAP +_TESTMAP.fields_by_name['bool_map'].message_type = _TESTMAP_BOOLMAPENTRY +_TESTMAP.fields_by_name['int32_map'].message_type = _TESTMAP_INT32MAPENTRY +_TESTMAP.fields_by_name['int64_map'].message_type = _TESTMAP_INT64MAPENTRY +_TESTMAP.fields_by_name['uint32_map'].message_type = _TESTMAP_UINT32MAPENTRY +_TESTMAP.fields_by_name['uint64_map'].message_type = _TESTMAP_UINT64MAPENTRY +_TESTMAP.fields_by_name['string_map'].message_type = _TESTMAP_STRINGMAPENTRY +_TESTNESTEDMAP_BOOLMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_INT32MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_INT64MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_UINT32MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_UINT64MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_STRINGMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_MAPMAPENTRY.fields_by_name['value'].message_type = _TESTNESTEDMAP +_TESTNESTEDMAP_MAPMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP.fields_by_name['bool_map'].message_type = _TESTNESTEDMAP_BOOLMAPENTRY +_TESTNESTEDMAP.fields_by_name['int32_map'].message_type = _TESTNESTEDMAP_INT32MAPENTRY +_TESTNESTEDMAP.fields_by_name['int64_map'].message_type = _TESTNESTEDMAP_INT64MAPENTRY +_TESTNESTEDMAP.fields_by_name['uint32_map'].message_type = _TESTNESTEDMAP_UINT32MAPENTRY +_TESTNESTEDMAP.fields_by_name['uint64_map'].message_type = _TESTNESTEDMAP_UINT64MAPENTRY +_TESTNESTEDMAP.fields_by_name['string_map'].message_type = _TESTNESTEDMAP_STRINGMAPENTRY +_TESTNESTEDMAP.fields_by_name['map_map'].message_type = _TESTNESTEDMAP_MAPMAPENTRY +_TESTWRAPPER.fields_by_name['bool_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTWRAPPER.fields_by_name['int32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTWRAPPER.fields_by_name['int64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTWRAPPER.fields_by_name['uint32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTWRAPPER.fields_by_name['uint64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTWRAPPER.fields_by_name['float_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTWRAPPER.fields_by_name['double_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTWRAPPER.fields_by_name['string_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTWRAPPER.fields_by_name['bytes_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTWRAPPER.fields_by_name['repeated_bool_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTWRAPPER.fields_by_name['repeated_int32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTWRAPPER.fields_by_name['repeated_int64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTWRAPPER.fields_by_name['repeated_uint32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTWRAPPER.fields_by_name['repeated_uint64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTWRAPPER.fields_by_name['repeated_float_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTWRAPPER.fields_by_name['repeated_double_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTWRAPPER.fields_by_name['repeated_string_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTWRAPPER.fields_by_name['repeated_bytes_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTTIMESTAMP.fields_by_name['value'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTTIMESTAMP.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTDURATION.fields_by_name['value'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTDURATION.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTFIELDMASK.fields_by_name['value'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTSTRUCT.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTSTRUCT.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTANY.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTANY.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTVALUE.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTVALUE.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTLISTVALUE.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE +_TESTLISTVALUE.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE +_TESTBOOLVALUE_BOOLMAPENTRY.containing_type = _TESTBOOLVALUE +_TESTBOOLVALUE.fields_by_name['bool_map'].message_type = _TESTBOOLVALUE_BOOLMAPENTRY +_TESTEXTENSIONS.fields_by_name['extensions'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLEXTENSIONS +_TESTENUMVALUE.fields_by_name['enum_value1'].enum_type = _ENUMTYPE +_TESTENUMVALUE.fields_by_name['enum_value2'].enum_type = _ENUMTYPE +_TESTENUMVALUE.fields_by_name['enum_value3'].enum_type = _ENUMTYPE +DESCRIPTOR.message_types_by_name['MessageType'] = _MESSAGETYPE +DESCRIPTOR.message_types_by_name['TestMessage'] = _TESTMESSAGE +DESCRIPTOR.message_types_by_name['TestOneof'] = _TESTONEOF +DESCRIPTOR.message_types_by_name['TestMap'] = _TESTMAP +DESCRIPTOR.message_types_by_name['TestNestedMap'] = _TESTNESTEDMAP +DESCRIPTOR.message_types_by_name['TestWrapper'] = _TESTWRAPPER +DESCRIPTOR.message_types_by_name['TestTimestamp'] = _TESTTIMESTAMP +DESCRIPTOR.message_types_by_name['TestDuration'] = _TESTDURATION +DESCRIPTOR.message_types_by_name['TestFieldMask'] = _TESTFIELDMASK +DESCRIPTOR.message_types_by_name['TestStruct'] = _TESTSTRUCT +DESCRIPTOR.message_types_by_name['TestAny'] = _TESTANY +DESCRIPTOR.message_types_by_name['TestValue'] = _TESTVALUE +DESCRIPTOR.message_types_by_name['TestListValue'] = _TESTLISTVALUE +DESCRIPTOR.message_types_by_name['TestBoolValue'] = _TESTBOOLVALUE +DESCRIPTOR.message_types_by_name['TestCustomJsonName'] = _TESTCUSTOMJSONNAME +DESCRIPTOR.message_types_by_name['TestExtensions'] = _TESTEXTENSIONS +DESCRIPTOR.message_types_by_name['TestEnumValue'] = _TESTENUMVALUE +DESCRIPTOR.enum_types_by_name['EnumType'] = _ENUMTYPE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +MessageType = _reflection.GeneratedProtocolMessageType('MessageType', (_message.Message,), dict( + DESCRIPTOR = _MESSAGETYPE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.MessageType) + )) +_sym_db.RegisterMessage(MessageType) + +TestMessage = _reflection.GeneratedProtocolMessageType('TestMessage', (_message.Message,), dict( + DESCRIPTOR = _TESTMESSAGE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMessage) + )) +_sym_db.RegisterMessage(TestMessage) + +TestOneof = _reflection.GeneratedProtocolMessageType('TestOneof', (_message.Message,), dict( + DESCRIPTOR = _TESTONEOF, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestOneof) + )) +_sym_db.RegisterMessage(TestOneof) + +TestMap = _reflection.GeneratedProtocolMessageType('TestMap', (_message.Message,), dict( + + BoolMapEntry = _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_BOOLMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.BoolMapEntry) + )) + , + + Int32MapEntry = _reflection.GeneratedProtocolMessageType('Int32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_INT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Int32MapEntry) + )) + , + + Int64MapEntry = _reflection.GeneratedProtocolMessageType('Int64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_INT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Int64MapEntry) + )) + , + + Uint32MapEntry = _reflection.GeneratedProtocolMessageType('Uint32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_UINT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Uint32MapEntry) + )) + , + + Uint64MapEntry = _reflection.GeneratedProtocolMessageType('Uint64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_UINT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Uint64MapEntry) + )) + , + + StringMapEntry = _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTMAP_STRINGMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.StringMapEntry) + )) + , + DESCRIPTOR = _TESTMAP, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap) + )) +_sym_db.RegisterMessage(TestMap) +_sym_db.RegisterMessage(TestMap.BoolMapEntry) +_sym_db.RegisterMessage(TestMap.Int32MapEntry) +_sym_db.RegisterMessage(TestMap.Int64MapEntry) +_sym_db.RegisterMessage(TestMap.Uint32MapEntry) +_sym_db.RegisterMessage(TestMap.Uint64MapEntry) +_sym_db.RegisterMessage(TestMap.StringMapEntry) + +TestNestedMap = _reflection.GeneratedProtocolMessageType('TestNestedMap', (_message.Message,), dict( + + BoolMapEntry = _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_BOOLMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.BoolMapEntry) + )) + , + + Int32MapEntry = _reflection.GeneratedProtocolMessageType('Int32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_INT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Int32MapEntry) + )) + , + + Int64MapEntry = _reflection.GeneratedProtocolMessageType('Int64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_INT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Int64MapEntry) + )) + , + + Uint32MapEntry = _reflection.GeneratedProtocolMessageType('Uint32MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_UINT32MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Uint32MapEntry) + )) + , + + Uint64MapEntry = _reflection.GeneratedProtocolMessageType('Uint64MapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_UINT64MAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Uint64MapEntry) + )) + , + + StringMapEntry = _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_STRINGMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.StringMapEntry) + )) + , + + MapMapEntry = _reflection.GeneratedProtocolMessageType('MapMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTNESTEDMAP_MAPMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.MapMapEntry) + )) + , + DESCRIPTOR = _TESTNESTEDMAP, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap) + )) +_sym_db.RegisterMessage(TestNestedMap) +_sym_db.RegisterMessage(TestNestedMap.BoolMapEntry) +_sym_db.RegisterMessage(TestNestedMap.Int32MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Int64MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Uint32MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Uint64MapEntry) +_sym_db.RegisterMessage(TestNestedMap.StringMapEntry) +_sym_db.RegisterMessage(TestNestedMap.MapMapEntry) + +TestWrapper = _reflection.GeneratedProtocolMessageType('TestWrapper', (_message.Message,), dict( + DESCRIPTOR = _TESTWRAPPER, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestWrapper) + )) +_sym_db.RegisterMessage(TestWrapper) + +TestTimestamp = _reflection.GeneratedProtocolMessageType('TestTimestamp', (_message.Message,), dict( + DESCRIPTOR = _TESTTIMESTAMP, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestTimestamp) + )) +_sym_db.RegisterMessage(TestTimestamp) + +TestDuration = _reflection.GeneratedProtocolMessageType('TestDuration', (_message.Message,), dict( + DESCRIPTOR = _TESTDURATION, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestDuration) + )) +_sym_db.RegisterMessage(TestDuration) + +TestFieldMask = _reflection.GeneratedProtocolMessageType('TestFieldMask', (_message.Message,), dict( + DESCRIPTOR = _TESTFIELDMASK, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestFieldMask) + )) +_sym_db.RegisterMessage(TestFieldMask) + +TestStruct = _reflection.GeneratedProtocolMessageType('TestStruct', (_message.Message,), dict( + DESCRIPTOR = _TESTSTRUCT, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestStruct) + )) +_sym_db.RegisterMessage(TestStruct) + +TestAny = _reflection.GeneratedProtocolMessageType('TestAny', (_message.Message,), dict( + DESCRIPTOR = _TESTANY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestAny) + )) +_sym_db.RegisterMessage(TestAny) + +TestValue = _reflection.GeneratedProtocolMessageType('TestValue', (_message.Message,), dict( + DESCRIPTOR = _TESTVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestValue) + )) +_sym_db.RegisterMessage(TestValue) + +TestListValue = _reflection.GeneratedProtocolMessageType('TestListValue', (_message.Message,), dict( + DESCRIPTOR = _TESTLISTVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestListValue) + )) +_sym_db.RegisterMessage(TestListValue) + +TestBoolValue = _reflection.GeneratedProtocolMessageType('TestBoolValue', (_message.Message,), dict( + + BoolMapEntry = _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), dict( + DESCRIPTOR = _TESTBOOLVALUE_BOOLMAPENTRY, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestBoolValue.BoolMapEntry) + )) + , + DESCRIPTOR = _TESTBOOLVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestBoolValue) + )) +_sym_db.RegisterMessage(TestBoolValue) +_sym_db.RegisterMessage(TestBoolValue.BoolMapEntry) + +TestCustomJsonName = _reflection.GeneratedProtocolMessageType('TestCustomJsonName', (_message.Message,), dict( + DESCRIPTOR = _TESTCUSTOMJSONNAME, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestCustomJsonName) + )) +_sym_db.RegisterMessage(TestCustomJsonName) + +TestExtensions = _reflection.GeneratedProtocolMessageType('TestExtensions', (_message.Message,), dict( + DESCRIPTOR = _TESTEXTENSIONS, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestExtensions) + )) +_sym_db.RegisterMessage(TestExtensions) + +TestEnumValue = _reflection.GeneratedProtocolMessageType('TestEnumValue', (_message.Message,), dict( + DESCRIPTOR = _TESTENUMVALUE, + __module__ = 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestEnumValue) + )) +_sym_db.RegisterMessage(TestEnumValue) + + +DESCRIPTOR._options = None +_TESTMAP_BOOLMAPENTRY._options = None +_TESTMAP_INT32MAPENTRY._options = None +_TESTMAP_INT64MAPENTRY._options = None +_TESTMAP_UINT32MAPENTRY._options = None +_TESTMAP_UINT64MAPENTRY._options = None +_TESTMAP_STRINGMAPENTRY._options = None +_TESTNESTEDMAP_BOOLMAPENTRY._options = None +_TESTNESTEDMAP_INT32MAPENTRY._options = None +_TESTNESTEDMAP_INT64MAPENTRY._options = None +_TESTNESTEDMAP_UINT32MAPENTRY._options = None +_TESTNESTEDMAP_UINT64MAPENTRY._options = None +_TESTNESTEDMAP_STRINGMAPENTRY._options = None +_TESTNESTEDMAP_MAPMAPENTRY._options = None +_TESTBOOLVALUE_BOOLMAPENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/google/protobuf/wrappers_pb2.py b/venv/lib/python3.7/site-packages/google/protobuf/wrappers_pb2.py new file mode 100644 index 0000000..7b66e8a --- /dev/null +++ b/venv/lib/python3.7/site-packages/google/protobuf/wrappers_pb2.py @@ -0,0 +1,382 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/wrappers.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/wrappers.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=_b('\n\023com.google.protobufB\rWrappersProtoP\001Z*github.com/golang/protobuf/ptypes/wrappers\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes'), + serialized_pb=_b('\n\x1egoogle/protobuf/wrappers.proto\x12\x0fgoogle.protobuf\"\x1c\n\x0b\x44oubleValue\x12\r\n\x05value\x18\x01 \x01(\x01\"\x1b\n\nFloatValue\x12\r\n\x05value\x18\x01 \x01(\x02\"\x1b\n\nInt64Value\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1c\n\x0bUInt64Value\x12\r\n\x05value\x18\x01 \x01(\x04\"\x1b\n\nInt32Value\x12\r\n\x05value\x18\x01 \x01(\x05\"\x1c\n\x0bUInt32Value\x12\r\n\x05value\x18\x01 \x01(\r\"\x1a\n\tBoolValue\x12\r\n\x05value\x18\x01 \x01(\x08\"\x1c\n\x0bStringValue\x12\r\n\x05value\x18\x01 \x01(\t\"\x1b\n\nBytesValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x42|\n\x13\x63om.google.protobufB\rWrappersProtoP\x01Z*github.com/golang/protobuf/ptypes/wrappers\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3') +) + + + + +_DOUBLEVALUE = _descriptor.Descriptor( + name='DoubleValue', + full_name='google.protobuf.DoubleValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.DoubleValue.value', index=0, + number=1, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=79, +) + + +_FLOATVALUE = _descriptor.Descriptor( + name='FloatValue', + full_name='google.protobuf.FloatValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.FloatValue.value', index=0, + number=1, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=81, + serialized_end=108, +) + + +_INT64VALUE = _descriptor.Descriptor( + name='Int64Value', + full_name='google.protobuf.Int64Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Int64Value.value', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=110, + serialized_end=137, +) + + +_UINT64VALUE = _descriptor.Descriptor( + name='UInt64Value', + full_name='google.protobuf.UInt64Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.UInt64Value.value', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=139, + serialized_end=167, +) + + +_INT32VALUE = _descriptor.Descriptor( + name='Int32Value', + full_name='google.protobuf.Int32Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Int32Value.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=169, + serialized_end=196, +) + + +_UINT32VALUE = _descriptor.Descriptor( + name='UInt32Value', + full_name='google.protobuf.UInt32Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.UInt32Value.value', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=198, + serialized_end=226, +) + + +_BOOLVALUE = _descriptor.Descriptor( + name='BoolValue', + full_name='google.protobuf.BoolValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.BoolValue.value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=228, + serialized_end=254, +) + + +_STRINGVALUE = _descriptor.Descriptor( + name='StringValue', + full_name='google.protobuf.StringValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.StringValue.value', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=256, + serialized_end=284, +) + + +_BYTESVALUE = _descriptor.Descriptor( + name='BytesValue', + full_name='google.protobuf.BytesValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.BytesValue.value', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=_b(""), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=286, + serialized_end=313, +) + +DESCRIPTOR.message_types_by_name['DoubleValue'] = _DOUBLEVALUE +DESCRIPTOR.message_types_by_name['FloatValue'] = _FLOATVALUE +DESCRIPTOR.message_types_by_name['Int64Value'] = _INT64VALUE +DESCRIPTOR.message_types_by_name['UInt64Value'] = _UINT64VALUE +DESCRIPTOR.message_types_by_name['Int32Value'] = _INT32VALUE +DESCRIPTOR.message_types_by_name['UInt32Value'] = _UINT32VALUE +DESCRIPTOR.message_types_by_name['BoolValue'] = _BOOLVALUE +DESCRIPTOR.message_types_by_name['StringValue'] = _STRINGVALUE +DESCRIPTOR.message_types_by_name['BytesValue'] = _BYTESVALUE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DoubleValue = _reflection.GeneratedProtocolMessageType('DoubleValue', (_message.Message,), dict( + DESCRIPTOR = _DOUBLEVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DoubleValue) + )) +_sym_db.RegisterMessage(DoubleValue) + +FloatValue = _reflection.GeneratedProtocolMessageType('FloatValue', (_message.Message,), dict( + DESCRIPTOR = _FLOATVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FloatValue) + )) +_sym_db.RegisterMessage(FloatValue) + +Int64Value = _reflection.GeneratedProtocolMessageType('Int64Value', (_message.Message,), dict( + DESCRIPTOR = _INT64VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Int64Value) + )) +_sym_db.RegisterMessage(Int64Value) + +UInt64Value = _reflection.GeneratedProtocolMessageType('UInt64Value', (_message.Message,), dict( + DESCRIPTOR = _UINT64VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value) + )) +_sym_db.RegisterMessage(UInt64Value) + +Int32Value = _reflection.GeneratedProtocolMessageType('Int32Value', (_message.Message,), dict( + DESCRIPTOR = _INT32VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Int32Value) + )) +_sym_db.RegisterMessage(Int32Value) + +UInt32Value = _reflection.GeneratedProtocolMessageType('UInt32Value', (_message.Message,), dict( + DESCRIPTOR = _UINT32VALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value) + )) +_sym_db.RegisterMessage(UInt32Value) + +BoolValue = _reflection.GeneratedProtocolMessageType('BoolValue', (_message.Message,), dict( + DESCRIPTOR = _BOOLVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.BoolValue) + )) +_sym_db.RegisterMessage(BoolValue) + +StringValue = _reflection.GeneratedProtocolMessageType('StringValue', (_message.Message,), dict( + DESCRIPTOR = _STRINGVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.StringValue) + )) +_sym_db.RegisterMessage(StringValue) + +BytesValue = _reflection.GeneratedProtocolMessageType('BytesValue', (_message.Message,), dict( + DESCRIPTOR = _BYTESVALUE, + __module__ = 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.BytesValue) + )) +_sym_db.RegisterMessage(BytesValue) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/venv/lib/python3.7/site-packages/pip-18.1.dist-info/INSTALLER b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.7/site-packages/pip-18.1.dist-info/LICENSE.txt b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/LICENSE.txt new file mode 100644 index 0000000..d3379fa --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2018 The pip developers (see AUTHORS.txt file) + +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/venv/lib/python3.7/site-packages/pip-18.1.dist-info/METADATA b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/METADATA new file mode 100644 index 0000000..2e314aa --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/METADATA @@ -0,0 +1,70 @@ +Metadata-Version: 2.1 +Name: pip +Version: 18.1 +Summary: The PyPA recommended tool for installing Python packages. +Home-page: https://pip.pypa.io/ +Author: The pip developers +Author-email: pypa-dev@groups.google.com +License: MIT +Keywords: distutils easy_install egg setuptools wheel virtualenv +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Build Tools +Classifier: Programming Language :: Python +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 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* + +pip +=== + +The `PyPA recommended`_ tool for installing Python packages. + +.. image:: https://img.shields.io/pypi/v/pip.svg + :target: https://pypi.org/project/pip/ + +.. image:: https://img.shields.io/travis/pypa/pip/master.svg?label=travis-ci + :target: https://travis-ci.org/pypa/pip + +.. image:: https://img.shields.io/appveyor/ci/pypa/pip.svg?label=appveyor-ci + :target: https://ci.appveyor.com/project/pypa/pip/history + +.. image:: https://readthedocs.org/projects/pip/badge/?version=latest + :target: https://pip.pypa.io/en/latest + +* `Installation`_ +* `Documentation`_ +* `Changelog`_ +* `GitHub Page`_ +* `Issue Tracking`_ +* `User mailing list`_ +* `Dev mailing list`_ +* User IRC: #pypa on Freenode. +* Dev IRC: #pypa-dev on Freenode. + +Code of Conduct +--------------- + +Everyone interacting in the pip project's codebases, issue trackers, chat +rooms and mailing lists is expected to follow the `PyPA Code of Conduct`_. + +.. _PyPA recommended: https://packaging.python.org/en/latest/current/ +.. _Installation: https://pip.pypa.io/en/stable/installing.html +.. _Documentation: https://pip.pypa.io/en/stable/ +.. _Changelog: https://pip.pypa.io/en/stable/news.html +.. _GitHub Page: https://github.com/pypa/pip +.. _Issue Tracking: https://github.com/pypa/pip/issues +.. _User mailing list: https://groups.google.com/forum/#!forum/python-virtualenv +.. _Dev mailing list: https://groups.google.com/forum/#!forum/pypa-dev +.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ + + diff --git a/venv/lib/python3.7/site-packages/pip-18.1.dist-info/RECORD b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/RECORD new file mode 100644 index 0000000..590cd02 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/RECORD @@ -0,0 +1,614 @@ +pip/__init__.py,sha256=nO-iphoXiDoci_ZAMl-PG2zdd4Y7m88jBDILTYzwGy4,21 +pip/__main__.py,sha256=L3IHqBeasELUHvwy5CT_izVEMhM12tve289qut49DvU,623 +pip/_internal/__init__.py,sha256=b0jSFCCViGhB1RWni35_NMkH3Y-mbZrV648DGMagDjs,2869 +pip/_internal/build_env.py,sha256=zKhqmDMnrX5OTSNQ4xBw-mN5mTGVu6wjiNFW-ajWYEI,4797 +pip/_internal/cache.py,sha256=96_aKtDbwgLEVNgNabOT8GrFCYZEACedoiucqU5ccg8,6829 +pip/_internal/configuration.py,sha256=KMgG3ufFrUKX_QESi2cMVvFi47tl845Bg1ZkNthlWik,13243 +pip/_internal/download.py,sha256=c5Hkimq39eJdZ6DN0_0etjK43-0a5CK_W_3sVLqH87g,33300 +pip/_internal/exceptions.py,sha256=EIGotnq6qM2nbGtnlgZ8Xp5VfP2W4-9UOCzQGMwy5MY,8899 +pip/_internal/index.py,sha256=6CAtZ8QTLcpw0fJqQ9OPu-Os1ettLZtVY1pPSKia8r8,34789 +pip/_internal/locations.py,sha256=ujNrLnA04Y_EmSriO0nS6qkkw_BkPfobB_hdwIDPvpM,6307 +pip/_internal/pep425tags.py,sha256=TQhxOPss4RjxgyVgxpSRe31HaTcWmn-LVjWBbkvkjzk,10845 +pip/_internal/pyproject.py,sha256=fpO52MCa3w5xSlXIBXw39BDTGzP8G4570EW34hVvIKQ,5481 +pip/_internal/resolve.py,sha256=tdepxCewsXXNFKSIYGSxiLvzi1xCv7UVFT9jRCDO90A,13578 +pip/_internal/wheel.py,sha256=fg9E936DaI1LyrBPHqtzHG_WEVyuUwipHISkD6N3jNw,32007 +pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 +pip/_internal/cli/autocompletion.py,sha256=ptvsMdGjq42pzoY4skABVF43u2xAtLJlXAulPi-A10Y,6083 +pip/_internal/cli/base_command.py,sha256=ke6af4iWzrZoc3HtiPKnCZJvD6GlX8dRwBwpFCg1axc,9963 +pip/_internal/cli/cmdoptions.py,sha256=WoPPY1uHsDjA_NvZek8Mko38rxraD3pX8eZUkNKvk10,19468 +pip/_internal/cli/main_parser.py,sha256=Ga_kT7if-Gg0rmmRqlGEHW6JWVm9zwzO7igJm6RE9EI,2763 +pip/_internal/cli/parser.py,sha256=VZKUKJPbU6I2cHPLDOikin-aCx7OvLcZ3fzYp3xytd8,9378 +pip/_internal/cli/status_codes.py,sha256=F6uDG6Gj7RNKQJUDnd87QKqI16Us-t-B0wPF_4QMpWc,156 +pip/_internal/commands/__init__.py,sha256=CQAzhVx9ViPtqLNUvAeqnKj5iWfFEcqMx5RlZWjJ30c,2251 +pip/_internal/commands/check.py,sha256=CyeYH2kfDKSGSURoBfWtx-sTcZZQP-bK170NmKYlmsg,1398 +pip/_internal/commands/completion.py,sha256=hqvCvoxsIHjysiD7olHKTqK2lzE1_lS6LWn69kN5qyI,2929 +pip/_internal/commands/configuration.py,sha256=265HWuUxPggCNcIeWHA3p-LDDiRVnexwFgwmHGgWOHY,7125 +pip/_internal/commands/download.py,sha256=D_iGMp3xX2iD7KZYZAjXlYT3rf3xjwxyYe05KE-DVzE,6514 +pip/_internal/commands/freeze.py,sha256=VvS3G0wrm_9BH3B7Ex5msLL_1UQTtCq5G8dDI63Iemo,3259 +pip/_internal/commands/hash.py,sha256=K1JycsD-rpjqrRcL_ijacY9UKmI82pQcLYq4kCM4Pv0,1681 +pip/_internal/commands/help.py,sha256=MwBhPJpW1Dt3GfJV3V8V6kgAy_pXT0jGrZJB1wCTW-E,1090 +pip/_internal/commands/install.py,sha256=tKyzfo5bhDGLVTTQCQJ9PFnDjimQvEWnwIAI2XHpaac,21039 +pip/_internal/commands/list.py,sha256=n740MsR0cG34EuvGWMzdVl0uIA3UIYx1_95FUsTktN0,10272 +pip/_internal/commands/search.py,sha256=sLZ9icKMEEGekHvzRRZMiTd1zCFIZeDptyyU1mQCYzk,4728 +pip/_internal/commands/show.py,sha256=9EVh86vY0NZdlhT-wsuV-zq_MAV6qqV4S1Akn3wkUuw,6289 +pip/_internal/commands/uninstall.py,sha256=h0gfPF5jylDESx_IHgF6bZME7QAEOHzQHdn65GP-jrE,2963 +pip/_internal/commands/wheel.py,sha256=ZuVf_DMpKCUzBVstolvQPAeajQRC51Oky5_hDHzhhFs,7020 +pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 +pip/_internal/models/candidate.py,sha256=zq2Vb5l5JflrVX7smHTJHQciZWHyoJZuYTLeQa1G16c,741 +pip/_internal/models/format_control.py,sha256=aDbH4D2XuyaGjtRjTLQhNzClAcLZdJCKSHO8xbZSmFA,2202 +pip/_internal/models/index.py,sha256=YI1WlhWfS9mVPY0bIboA5la2pjJ2J0qgPJIbvdEjZBk,996 +pip/_internal/models/link.py,sha256=E61PvS2Wrmb9-zT-eAc_8_xI3C-89wJlpL8SL-mlQmg,3998 +pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/check.py,sha256=ahcOg5p68nNow6_wy5prYYK0KZq22lm0CsJn8AyDMCI,4937 +pip/_internal/operations/freeze.py,sha256=lskaBcqf3bPZupG032fuLf76QYv5wpAQ6jsiXac56Bg,10450 +pip/_internal/operations/prepare.py,sha256=atoLFj3OD5KfXsa5dYBMC_mI06l068F5yZhF4jle1JA,14280 +pip/_internal/req/__init__.py,sha256=JnNZWvKUQuqAwHh64LCD3zprzWIVQEXChTo2UGHzVqo,2093 +pip/_internal/req/constructors.py,sha256=97WQp9Svh-Jw3oLZL9_57gJ3zihm5LnWlSRjOwOorDU,9573 +pip/_internal/req/req_file.py,sha256=ORA0GKUjGd6vy7pmBwXR55FFj4h_OxYykFQ6gHuWvt0,11940 +pip/_internal/req/req_install.py,sha256=ry1RtNNCefDHAnf3EeGMpea-9pC6Yk1uHzP0Q5p2Un0,34046 +pip/_internal/req/req_set.py,sha256=nE6oagXJSiQREuuebX3oJO5OHSOVUIlvLLilodetBzc,7264 +pip/_internal/req/req_tracker.py,sha256=zH28YHV5TXAVh1ZOEZi6Z1Edkiu26dN2tXfR6VbQ3B4,2370 +pip/_internal/req/req_uninstall.py,sha256=ORSPah64KOVrKo-InMM3zgS5HQqbl5TLHFnE_Lxstq8,16737 +pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/utils/appdirs.py,sha256=SPfibHtvOKzD_sHrpEZ60HfLae3GharU4Tg7SB3c-XM,9120 +pip/_internal/utils/compat.py,sha256=LSAvzXcsGY2O2drKIPszR5Ja2G0kup__51l3bx1jR_Q,8015 +pip/_internal/utils/deprecation.py,sha256=yQTe6dyWlBfxSBrOv_MdRXF1RPLER_EWOp-pa2zLoZc,3021 +pip/_internal/utils/encoding.py,sha256=D8tmfStCah6xh9OLhH9mWLr77q4akhg580YHJMKpq3Y,1025 +pip/_internal/utils/filesystem.py,sha256=ZOIHbacJ-SJtuZru4GoA5DuSIYyeaE4G5kfZPf5cn1A,915 +pip/_internal/utils/glibc.py,sha256=prOrsBjmgkDE-hY4Pl120yF5MIlkkmGrFLs8XfIyT-w,3004 +pip/_internal/utils/hashes.py,sha256=rJk-gj6F-sHggXAG97dhynqUHFFgApyZLWgaG2xCHME,2900 +pip/_internal/utils/logging.py,sha256=BQeUDEER3zlK0O4yv6DBfz6TK3f9XoLXyDlnB0mZVf0,6295 +pip/_internal/utils/misc.py,sha256=YscDfBiFx1spYOtSgdI_5hnc5BZUysWAyz1aVL5y-48,29904 +pip/_internal/utils/models.py,sha256=DQYZSRhjvSdDTAaJLLCpDtxAn1S_-v_8nlNjv4T2jwY,1042 +pip/_internal/utils/outdated.py,sha256=BXtCMKR6gjTrvMfP3MWzZ1Y4ZU4qqoCfbRNqQCusVt8,5642 +pip/_internal/utils/packaging.py,sha256=Ru8ls_S8PPKR8RKEn7jMetENY_A9jPet1HlhTZwpFxU,2443 +pip/_internal/utils/setuptools_build.py,sha256=0blfscmNJW_iZ5DcswJeDB_PbtTEjfK9RL1R1WEDW2E,278 +pip/_internal/utils/temp_dir.py,sha256=n2FkVlwRX_hS61fYt3nSAh2e2V6CcZn_dfbPId1pAQE,2615 +pip/_internal/utils/typing.py,sha256=ztYtZAcqjCYDwP-WlF6EiAAskAsZBMMXtuqvfgZIlgQ,1139 +pip/_internal/utils/ui.py,sha256=FW8wdtc7DvNwJClGr_TvGZlqcoO482GYe0UY9nKmpso,13657 +pip/_internal/vcs/__init__.py,sha256=2Ct9ogOwzS6ZKKaEXKN2XDiBOiFHMcejnN1KM21mLrQ,16319 +pip/_internal/vcs/bazaar.py,sha256=rjskVmSSn68O7lC5JrGmDTWXneXFMMJJvj_bbdSM8QA,3669 +pip/_internal/vcs/git.py,sha256=n1cFBqTnLIcxAOClZMgOBqELjEjygDBPZ9z-Q7g0qVQ,12580 +pip/_internal/vcs/mercurial.py,sha256=jVTa0XQpFR6EiBcaqW4E4JjTce_t1tFnKRaIhaIPlS8,3471 +pip/_internal/vcs/subversion.py,sha256=vDLTfcjj0kgqcEsbPBfveC4CRxyhWiOjke-qN0Zr8CE,7676 +pip/_vendor/__init__.py,sha256=XnhkujjE1qUGRlYGYbIRrEGYYYBcNLBraE27HH48wYw,4756 +pip/_vendor/appdirs.py,sha256=BENKsvcA08IpccD9345-rMrg3aXWFA1q6BFEglnHg6I,24547 +pip/_vendor/distro.py,sha256=dOMrjIXv-3GmEbtP-NJc057Sv19P7ZAdke-v0TBeNio,42455 +pip/_vendor/ipaddress.py,sha256=2OgbkeAD2rLkcXqbcvof3J5R7lRwjNLoBySyTkBtKnc,79852 +pip/_vendor/pyparsing.py,sha256=My2ZwDJCEaZkZgZyG9gL--48RLGmf9vnVCTW93rhdYI,226342 +pip/_vendor/retrying.py,sha256=k3fflf5_Mm0XcIJYhB7Tj34bqCCPhUDkYbx1NvW2FPE,9972 +pip/_vendor/six.py,sha256=A08MPb-Gi9FfInI3IW7HimXFmEH2T2IPzHgDvdhZPRA,30888 +pip/_vendor/cachecontrol/__init__.py,sha256=6cRPchVqkAkeUtYTSW8qCetjSqJo-GxP-n4VMVDbvmc,302 +pip/_vendor/cachecontrol/_cmd.py,sha256=URGE0KrA87QekCG3SGPatlSPT571dZTDjNa-ZXX3pDc,1295 +pip/_vendor/cachecontrol/adapter.py,sha256=eBGAtVNRZgtl_Kj5JV54miqL9YND-D0JZPahwY8kFtY,4863 +pip/_vendor/cachecontrol/cache.py,sha256=1fc4wJP8HYt1ycnJXeEw5pCpeBL2Cqxx6g9Fb0AYDWQ,805 +pip/_vendor/cachecontrol/compat.py,sha256=kHNvMRdt6s_Xwqq_9qJmr9ou3wYMOMUMxPPcwNxT8Mc,695 +pip/_vendor/cachecontrol/controller.py,sha256=U7g-YwizQ2O5NRgK_MZreF1ntM4E49C3PuF3od-Vwz4,13698 +pip/_vendor/cachecontrol/filewrapper.py,sha256=vACKO8Llzu_ZWyjV1Fxn1MA4TGU60N5N3GSrAFdAY2Q,2533 +pip/_vendor/cachecontrol/heuristics.py,sha256=BFGHJ3yQcxvZizfo90LLZ04T_Z5XSCXvFotrp7Us0sc,4070 +pip/_vendor/cachecontrol/serialize.py,sha256=GebE34fgToyWwAsRPguh8hEPN6CqoG-5hRMXRsjVABQ,6954 +pip/_vendor/cachecontrol/wrapper.py,sha256=sfr9YHWx-5TwNz1H5rT6QOo8ggII6v3vbEDjQFwR6wc,671 +pip/_vendor/cachecontrol/caches/__init__.py,sha256=-gHNKYvaeD0kOk5M74eOrsSgIKUtC6i6GfbmugGweEo,86 +pip/_vendor/cachecontrol/caches/file_cache.py,sha256=8vrSzzGcdfEfICago1uSFbkumNJMGLbCdEkXsmUIExw,4177 +pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=HxelMpNCo-dYr2fiJDwM3hhhRmxUYtB5tXm1GpAAT4Y,856 +pip/_vendor/certifi/__init__.py,sha256=5lCYV1iWxoirX1OAaSHkBYUuZGdcwEjEBS6DS_trL0s,63 +pip/_vendor/certifi/__main__.py,sha256=NaCn6WtWME-zzVWQ2j4zFyl8cY4knDa9CwtHNIeFPhM,53 +pip/_vendor/certifi/cacert.pem,sha256=XA-4HVBsOrBD5lfg-b3PiUzAvwUd2qlIzwXypIMIRGM,263074 +pip/_vendor/certifi/core.py,sha256=xPQDdG_siy5A7BfqGWa7RJhcA61xXEqPiSrw9GNyhHE,836 +pip/_vendor/chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 +pip/_vendor/chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 +pip/_vendor/chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 +pip/_vendor/chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 +pip/_vendor/chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 +pip/_vendor/chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 +pip/_vendor/chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 +pip/_vendor/chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 +pip/_vendor/chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 +pip/_vendor/chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 +pip/_vendor/chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 +pip/_vendor/chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 +pip/_vendor/chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 +pip/_vendor/chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 +pip/_vendor/chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 +pip/_vendor/chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 +pip/_vendor/chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 +pip/_vendor/chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 +pip/_vendor/chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 +pip/_vendor/chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 +pip/_vendor/chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 +pip/_vendor/chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 +pip/_vendor/chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 +pip/_vendor/chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 +pip/_vendor/chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 +pip/_vendor/chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 +pip/_vendor/chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 +pip/_vendor/chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 +pip/_vendor/chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 +pip/_vendor/chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 +pip/_vendor/chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 +pip/_vendor/chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 +pip/_vendor/chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 +pip/_vendor/chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 +pip/_vendor/chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 +pip/_vendor/chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 +pip/_vendor/chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 +pip/_vendor/chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 +pip/_vendor/chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 +pip/_vendor/chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +pip/_vendor/chardet/cli/chardetect.py,sha256=DI8dlV3FBD0c0XA_y3sQ78z754DUv1J8n34RtDjOXNw,2774 +pip/_vendor/colorama/__init__.py,sha256=V3-Hv_vOa-2lE5Q_0mGkdhZo-9e4XrGTW_44cU81qQY,240 +pip/_vendor/colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 +pip/_vendor/colorama/ansitowin32.py,sha256=QrieYX2tsaWIO19P6biMa1zUCt-_abudoEp2_IdqZZU,9668 +pip/_vendor/colorama/initialise.py,sha256=cHqVJtb82OG7HUCxvQ2joG7N_CoxbIKbI_fgryZkj20,1917 +pip/_vendor/colorama/win32.py,sha256=5Hc7L1LabubrYDhdWAfRyzlt14ErP3YKDvf_zYaarLk,5426 +pip/_vendor/colorama/winterm.py,sha256=V7U7ojwG1q4n6PKripjEvW_htYQi5ueXSM3LUUoqqDY,6290 +pip/_vendor/distlib/__init__.py,sha256=GxRrh1augb66Eo9NB9jrdwQS02KcBypj9o_-C3oyKZI,581 +pip/_vendor/distlib/compat.py,sha256=xdNZmqFN5HwF30HjRn5M415pcC2kgXRBXn767xS8v-M,41404 +pip/_vendor/distlib/database.py,sha256=LqTcNkDyV4bWcc_qDxiYJHnXaNxFs1O1bFSAg_reaI0,50868 +pip/_vendor/distlib/index.py,sha256=Dd1kIV06XIdynNpKxHMMRRIKsXuoUsG7QIzntfVtZCI,21073 +pip/_vendor/distlib/locators.py,sha256=e4UaQSzNg5iG3PfQRH6lnVMfLOwhm2sVmGGRdjdB3ik,51657 +pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 +pip/_vendor/distlib/markers.py,sha256=6Ac3cCfFBERexiESWIOXmg-apIP8l2esafNSX3KMy-8,4387 +pip/_vendor/distlib/metadata.py,sha256=Ns92dqeMxopDPQsiEWnhMtd4RagJaA58lz8O_vjCxyk,39986 +pip/_vendor/distlib/resources.py,sha256=2FGv0ZHF14KXjLIlL0R991lyQQGcewOS4mJ-5n-JVnc,10766 +pip/_vendor/distlib/scripts.py,sha256=WEqXkpRvqR6oe-QlMRYg8gEJxXRWJeWn1GPc0ihZ4N0,16585 +pip/_vendor/distlib/t32.exe,sha256=ftub1bsSPUCOnBn-eCtcarKTk0N0CBEP53BumkIxWJE,92672 +pip/_vendor/distlib/t64.exe,sha256=iChOG627LWTHY8-jzSwlo9SYU5a-0JHwQu4AqDz8I68,102400 +pip/_vendor/distlib/util.py,sha256=FnzjaibVcIg1xOtET6QPNeqTnn3LcWLCjNOficMyGKA,59494 +pip/_vendor/distlib/version.py,sha256=_n7F6juvQGAcn769E_SHa7fOcf5ERlEVymJ_EjPRwGw,23391 +pip/_vendor/distlib/w32.exe,sha256=NPYPpt7PIjVqABEu1CzabbDyHHkJpuw-_qZq_48H0j0,89088 +pip/_vendor/distlib/w64.exe,sha256=Yb-qr1OQEzL8KRGTk-XHUZDwMSljfQeZnVoTk-K4e7E,99328 +pip/_vendor/distlib/wheel.py,sha256=W9aKwi4CQL_bQFYb8IcwH-c6WK-yku5P8SY3RGPv-Mk,39506 +pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 +pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 +pip/_vendor/distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 +pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 +pip/_vendor/distlib/_backport/sysconfig.py,sha256=JdJ9ztRy4Hc-b5-VS74x3nUtdEIVr_OBvMsIb8O2sjc,26964 +pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 +pip/_vendor/html5lib/__init__.py,sha256=Ztrn7UvF-wIFAgRBBa0ML-Gu5AffH3BPX_INJx4SaBI,1162 +pip/_vendor/html5lib/_ihatexml.py,sha256=3LBtJMlzgwM8vpQiU1TvGmEEmNH72sV0yD8yS53y07A,16705 +pip/_vendor/html5lib/_inputstream.py,sha256=bPUWcAfJScK4xkjQQaG_HsI2BvEVbFvI0AsodDYPQj0,32552 +pip/_vendor/html5lib/_tokenizer.py,sha256=YAaOEBD6qc5ISq9Xt9Nif1OFgcybTTfMdwqBkZhpAq4,76580 +pip/_vendor/html5lib/_utils.py,sha256=ismpASeqa2jqEPQjHUj8vReAf7yIoKnvLN5fuOw6nv0,4015 +pip/_vendor/html5lib/constants.py,sha256=4lmZWLtEPRLnl8NzftOoYTJdo6jpeMtP6dqQC0g_bWQ,83518 +pip/_vendor/html5lib/html5parser.py,sha256=g5g2ezkusHxhi7b23vK_-d6K6BfIJRbqIQmvQ9z4EgI,118963 +pip/_vendor/html5lib/serializer.py,sha256=yfcfBHse2wDs6ojxn-kieJjLT5s1ipilQJ0gL3-rJis,15758 +pip/_vendor/html5lib/_trie/__init__.py,sha256=8VR1bcgD2OpeS2XExpu5yBhP_Q1K-lwKbBKICBPf1kU,289 +pip/_vendor/html5lib/_trie/_base.py,sha256=uJHVhzif9S0MJXgy9F98iEev5evi_rgUk5BmEbUSp8c,930 +pip/_vendor/html5lib/_trie/datrie.py,sha256=EQpqSfkZRuTbE-DuhW7xMdVDxdZNZ0CfmnYfHA_3zxM,1178 +pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 +pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=lViZc2JMCclXi_5gduvmdzrRxtO5Xo9ONnbHBVCsykU,919 +pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 +pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=egDXUEHXmAG9504xz0K6ALDgYkvUrC2q15YUVeNlVQg,2945 +pip/_vendor/html5lib/filters/lint.py,sha256=jk6q56xY0ojiYfvpdP-OZSm9eTqcAdRqhCoPItemPYA,3643 +pip/_vendor/html5lib/filters/optionaltags.py,sha256=8lWT75J0aBOHmPgfmqTHSfPpPMp01T84NKu0CRedxcE,10588 +pip/_vendor/html5lib/filters/sanitizer.py,sha256=4ON02KNjuqda1lCw5_JCUZxb0BzWR5M7ON84dtJ7dm0,26248 +pip/_vendor/html5lib/filters/whitespace.py,sha256=8eWqZxd4UC4zlFGW6iyY6f-2uuT8pOCSALc3IZt7_t4,1214 +pip/_vendor/html5lib/treeadapters/__init__.py,sha256=A0rY5gXIe4bJOiSGRO_j_tFhngRBO8QZPzPtPw5dFzo,679 +pip/_vendor/html5lib/treeadapters/genshi.py,sha256=CH27pAsDKmu4ZGkAUrwty7u0KauGLCZRLPMzaO3M5vo,1715 +pip/_vendor/html5lib/treeadapters/sax.py,sha256=BKS8woQTnKiqeffHsxChUqL4q2ZR_wb5fc9MJ3zQC8s,1776 +pip/_vendor/html5lib/treebuilders/__init__.py,sha256=AysSJyvPfikCMMsTVvaxwkgDieELD5dfR8FJIAuq7hY,3592 +pip/_vendor/html5lib/treebuilders/base.py,sha256=wQGp5yy22TNG8tJ6aREe4UUeTR7A99dEz0BXVaedWb4,14579 +pip/_vendor/html5lib/treebuilders/dom.py,sha256=SY3MsijXyzdNPc8aK5IQsupBoM8J67y56DgNtGvsb9g,8835 +pip/_vendor/html5lib/treebuilders/etree.py,sha256=aqIBOGj_dFYqBURIcTegGNBhAIJOw5iFDHb4jrkYH-8,12764 +pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=9V0dXxbJYYq-Skgb5-_OL2NkVYpjioEb4CHajo0e9yI,14122 +pip/_vendor/html5lib/treewalkers/__init__.py,sha256=yhXxHpjlSqfQyUag3v8-vWjMPriFBU8YRAPNpDgBTn8,5714 +pip/_vendor/html5lib/treewalkers/base.py,sha256=ouiOsuSzvI0KgzdWP8PlxIaSNs9falhbiinAEc_UIJY,7476 +pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 +pip/_vendor/html5lib/treewalkers/etree.py,sha256=sz1o6mmE93NQ53qJFDO7HKyDtuwgK-Ay3qSFZPC6u00,4550 +pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=sY6wfRshWTllu6n48TPWpKsQRPp-0CQrT0hj_AdzHSU,6309 +pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 +pip/_vendor/idna/__init__.py,sha256=9Nt7xpyet3DmOrPUGooDdAwmHZZu1qUAy2EaJ93kGiQ,58 +pip/_vendor/idna/codec.py,sha256=lvYb7yu7PhAqFaAIAdWcwgaWI2UmgseUua-1c0AsG0A,3299 +pip/_vendor/idna/compat.py,sha256=R-h29D-6mrnJzbXxymrWUW7iZUvy-26TQwZ0ij57i4U,232 +pip/_vendor/idna/core.py,sha256=OwI5R_uuXU4PlOSoG8cjaMPA1hhdGGjjZ8I2MZhSPxo,11858 +pip/_vendor/idna/idnadata.py,sha256=zwxvoSsYqPHNa6xzXWHizXpDC28JJMGXRinhJ4Gkcz0,39285 +pip/_vendor/idna/intranges.py,sha256=TY1lpxZIQWEP6tNqjZkFA5hgoMWOj1OBmnUG8ihT87E,1749 +pip/_vendor/idna/package_data.py,sha256=Vt9rtr32BzO7O25rypo8nzAs3syTJhG1ojU3J-s2RFo,21 +pip/_vendor/idna/uts46data.py,sha256=czULzYN5Lr9K5MmOH-1g3CJY7QPjGeHjYmC3saJ_BHk,197803 +pip/_vendor/lockfile/__init__.py,sha256=Tqpz90DwKYfhPsfzVOJl84TL87pdFE5ePNHdXAxs4Tk,9371 +pip/_vendor/lockfile/linklockfile.py,sha256=C7OH3H4GdK68u4FQgp8fkP2kO4fyUTSyj3X6blgfobc,2652 +pip/_vendor/lockfile/mkdirlockfile.py,sha256=e3qgIL-etZMLsS-3ft19iW_8IQ360HNkGOqE3yBKsUw,3096 +pip/_vendor/lockfile/pidlockfile.py,sha256=ukH9uk6NFuxyVmG5QiWw4iKq3fT7MjqUguX95avYPIY,6090 +pip/_vendor/lockfile/sqlitelockfile.py,sha256=o2TMkMRY0iwn-iL1XMRRIFStMUkS4i3ajceeYNntKFg,5506 +pip/_vendor/lockfile/symlinklockfile.py,sha256=ABwXXmvTHvCl5viPblShL3PG-gGsLiT1roAMfDRwhi8,2616 +pip/_vendor/msgpack/__init__.py,sha256=y0bk2YbzK6J2e0J_dyreN6nD7yM2IezT6m_tU2h-Mdg,1677 +pip/_vendor/msgpack/_version.py,sha256=dN7wVIjbyuQIJ35B2o6gymQNDLPlj_7-uTfgCv7KErM,20 +pip/_vendor/msgpack/exceptions.py,sha256=lPkAi_u12NlFajDz4FELSHEdfU8hrR3zeTvKX8aQuz4,1056 +pip/_vendor/msgpack/fallback.py,sha256=h0ll8xnq12mI9PuQ9Qd_Ihtt08Sp8L0JqhG9KY8Vyjk,36411 +pip/_vendor/packaging/__about__.py,sha256=mH-sMIEu48PzdYakZ6Y6OBzL3TlSetzz1fQSkCXiy30,720 +pip/_vendor/packaging/__init__.py,sha256=_vNac5TrzwsrzbOFIbF-5cHqc_Y2aPT2D7zrIR06BOo,513 +pip/_vendor/packaging/_compat.py,sha256=Vi_A0rAQeHbU-a9X0tt1yQm9RqkgQbDSxzRw8WlU9kA,860 +pip/_vendor/packaging/_structures.py,sha256=DCpKtb7u94_oqgVsIJQTrTyZcb3Gz7sSGbk9vYDMME0,1418 +pip/_vendor/packaging/markers.py,sha256=ftZegBU5oEmulEKApDGEPgti2lYIchFQHAfH9tZy3_U,8221 +pip/_vendor/packaging/requirements.py,sha256=xIWdoZXVKhUHxqFP5xmnKylM7NHXQS48hUfIIX1PvY0,4439 +pip/_vendor/packaging/specifiers.py,sha256=pFp716eLYBRt0eLNsy6cnWD9dyMKq-Zag7bsLbLv4Fs,28026 +pip/_vendor/packaging/utils.py,sha256=c9obOpok2CpKDApkc2M5ma0YFnT-jtt4I6XI4F0jYiI,1580 +pip/_vendor/packaging/version.py,sha256=MKL8nbKLPLGPouIwFvwSVnYRzNpkMo5AIcsa6LGqDF8,12219 +pip/_vendor/pep517/__init__.py,sha256=GH4HshnLERtjAjkY0zHoz3f7-35UcIvr27iFWSOUazU,82 +pip/_vendor/pep517/_in_process.py,sha256=iWpagFk2GhNBbvl-Ca2RagfD0ALuits4WWSM6nQMTdg,5831 +pip/_vendor/pep517/check.py,sha256=Yp2NHW71DIOCgkFb7HKJOzKmsum_s_OokRP6HnR3bTg,5761 +pip/_vendor/pep517/colorlog.py,sha256=2AJuPI_DHM5T9IDgcTwf0E8suyHAFnfsesogr0AB7RQ,4048 +pip/_vendor/pep517/compat.py,sha256=4SFG4QN-cNj8ebSa0wV0HUtEEQWwmbok2a0uk1gYEOM,631 +pip/_vendor/pep517/envbuild.py,sha256=osRsJVd7hir1w_uFXiVeeWxfJ3iYhwxsKRgNBWpqtCI,5672 +pip/_vendor/pep517/wrappers.py,sha256=RhgWm-MLxpYPgc9cZ3-A3ToN99ZzgM8-ia4FDB58koM,5018 +pip/_vendor/pkg_resources/__init__.py,sha256=ykZI7-YBIAQ7ztWf0RskP8Oy1VQU88o-16PJbIMCtLg,103915 +pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562 +pip/_vendor/progress/__init__.py,sha256=Hv3Y8Hr6RyM34NdZkrZQWMURjS2h5sONRHJSvZXWZgQ,3188 +pip/_vendor/progress/bar.py,sha256=hlkDAEv9pRRiWqR5XL6vIAgMG4u_dBGEW_8klQhBRq0,2942 +pip/_vendor/progress/counter.py,sha256=XtBuZY4yYmr50E2A_fAzjWhm0IkwaVwxNsNVYDE7nsw,1528 +pip/_vendor/progress/helpers.py,sha256=6FsBLh_xUlKiVua-zZIutCjxth-IO8FtyUj6I2tx9fg,2952 +pip/_vendor/progress/spinner.py,sha256=m7bASI2GUbLFG-PbAefdHtrrWWlJLFhhSBbw70gp2TY,1439 +pip/_vendor/pytoml/__init__.py,sha256=q12Xv23Tta44gtK4HGK68Gr4tKfciILidFPmPuoIqIo,92 +pip/_vendor/pytoml/core.py,sha256=9CrLLTs1PdWjEwRnYzt_i4dhHcZvGxs_GsMlYAX3iY4,509 +pip/_vendor/pytoml/parser.py,sha256=mcTzHB2GQGyK8KVwuQ0EraSz_78O36U60NqHBtgVmV0,11247 +pip/_vendor/pytoml/writer.py,sha256=-mSOVGaiGLrpj5BRR7czmquZXJGflcElHrwAd33J48A,3815 +pip/_vendor/requests/__init__.py,sha256=OrwNk1JwZGqIQ4JVGgMbfpstqey-oHS_Re_Dw6D4ciI,4209 +pip/_vendor/requests/__version__.py,sha256=rJ2xgNOLhjspGkNPfgXTBctqqvsf2uJMFTaE0rlVtbI,436 +pip/_vendor/requests/_internal_utils.py,sha256=Zx3PnEUccyfsB-ie11nZVAW8qClJy0gx1qNME7rgT18,1096 +pip/_vendor/requests/adapters.py,sha256=y5DISepvSsGlu3II_VUsdgKBej1dGY4b5beRrTE2tsI,21428 +pip/_vendor/requests/api.py,sha256=zub9ENcEUT2m9gwgBgqH5RIRDfrx2kwRpZ7L6hX3mcw,6261 +pip/_vendor/requests/auth.py,sha256=oRSQkBYcLkTEssudkzoR1UW1Glb1ts3p1RWusgHf1YU,10208 +pip/_vendor/requests/certs.py,sha256=nXRVq9DtGmv_1AYbwjTu9UrgAcdJv05ZvkNeaoLOZxY,465 +pip/_vendor/requests/compat.py,sha256=7EC6fZY4dJDxuBQnqUGwe13OTZ3VLGO3QfOApE5lE3I,1998 +pip/_vendor/requests/cookies.py,sha256=olUaLeNci_z1K-Bn5PeEKllSspmQqN9-s8Ug7CasaPE,18346 +pip/_vendor/requests/exceptions.py,sha256=-mLam3TAx80V09EaH3H-ZxR61eAVuLRZ8zgBBSLjK44,3197 +pip/_vendor/requests/help.py,sha256=T4K-Oo_FS9fxF8NHVR8hxMwFo71gIkRM7UddCc9vH7Y,3669 +pip/_vendor/requests/hooks.py,sha256=HXAHoC1FNTFRZX6-lNdvPM7Tst4kvGwYTN-AOKRxoRU,767 +pip/_vendor/requests/models.py,sha256=3fmmYdDW7U18SrVeZaseHuk8KPI-7vLp_435DY3ejes,34160 +pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 +pip/_vendor/requests/sessions.py,sha256=71MK2HCadovka1vAx9dyDFWAuw69KgRPRBpd0HWSEAo,27829 +pip/_vendor/requests/status_codes.py,sha256=pgw-xlnxO5zHQWn3fKps2cxwQehKzPxEbdhIrMQe6Ec,4128 +pip/_vendor/requests/structures.py,sha256=zoP8qly2Jak5e89HwpqjN1z2diztI-_gaqts1raJJBc,2981 +pip/_vendor/requests/utils.py,sha256=3OxbbLUQFVdm84fdBD9nduXvhw6hIzj59mhvBomKuJI,30156 +pip/_vendor/urllib3/__init__.py,sha256=DZucS8tlzGYKmK5FIsyUViMghpCq_0_0Ouvm_Jp9GNc,2853 +pip/_vendor/urllib3/_collections.py,sha256=iNeAU_we9L3lMGRUKKdq24Mf7o050TXP5U4Jm9AzAY4,10841 +pip/_vendor/urllib3/connection.py,sha256=My76qeWMDkV-KP1l3iChXHOE7J-ZCaUdP3sPIiLA2uE,14485 +pip/_vendor/urllib3/connectionpool.py,sha256=w20OwKdIqk6f8FIl6QGgn6jf9gZ0-tmgH7VPxnpEgkQ,35464 +pip/_vendor/urllib3/exceptions.py,sha256=rFeIfBNKC8KJ61ux-MtJyJlEC9G9ggkmCeF751JwVR4,6604 +pip/_vendor/urllib3/fields.py,sha256=D_TE_SK15YatdbhWDMN0OE3X6UCJn1RTkANINCYOobE,5943 +pip/_vendor/urllib3/filepost.py,sha256=40CROlpRKVBpFUkD0R6wJf_PpvbcRQRFUu0OOQlFkKM,2436 +pip/_vendor/urllib3/poolmanager.py,sha256=FHBjb7odbP2LyQRzeitgpuh1AQAPyegzmrm2b3gSZlY,16821 +pip/_vendor/urllib3/request.py,sha256=fwjlq5nQfcUa7aoncR25z6-fJAX_oNTcPksKKGjBm38,5996 +pip/_vendor/urllib3/response.py,sha256=uAuOTZSuTodzvQWIDCZghDoKmZ2bKbgIRCfaVIIZfn8,24667 +pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/appengine.py,sha256=Q3BDy5C_TrI-3cSyo0ELNGlNiK2eSVptQAQMdz4PH9Q,11197 +pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=Q9-rO5Rh2-IqyEd4ZicpTDfMnOlf0IPPCkjhChBCjV4,4478 +pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=cM7fVZJRrdLZsprcdWe3meM_hvq8LR73UNDveIMa-20,15480 +pip/_vendor/urllib3/contrib/securetransport.py,sha256=BqXSlChN9_hjCWgyN6JdcgvBUdc37QCCX4u3_8zE_9o,30309 +pip/_vendor/urllib3/contrib/socks.py,sha256=Iom0snbHkCuZbZ7Sle2Kueha1W0jYAJ0SyCOtePLaio,6391 +pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=x2kLSh-ASZKsun0FxtraBuLVe3oHuth4YW6yZ5Vof-w,17560 +pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=Umy5u-3Z957GirdapnicXVOpHaM4xdOZABJuJxfaeJA,12162 +pip/_vendor/urllib3/packages/__init__.py,sha256=nlChrGzkjCkmhCX9HrF_qHPUgosfsPQkVIJxiiLhk9g,109 +pip/_vendor/urllib3/packages/ordered_dict.py,sha256=VQaPONfhVMsb8B63Xg7ZOydJqIE_jzeMhVN3Pec6ogw,8935 +pip/_vendor/urllib3/packages/six.py,sha256=A6hdJZVjI3t_geebZ9BzUvwRrIXo0lfwzQlM2LcKyas,30098 +pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/backports/makefile.py,sha256=r1IADol_pBBq2Y1ub4CPyuS2hXuShK47nfFngZRcRhI,1461 +pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py,sha256=WBVbxQBojNAxfZwNavkox3BgJiMA9BJmm-_fwd0jD_o,688 +pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py,sha256=XCW0ydHg171GfOqNbvUAnRzQ0lc0twp5-dIlolgf4RM,5719 +pip/_vendor/urllib3/util/__init__.py,sha256=6Ran4oAVIy40Cu_oEPWnNV9bwF5rXx6G1DUZ7oehjPY,1044 +pip/_vendor/urllib3/util/connection.py,sha256=8K1VXm8BHsM3QATJJGBNRa_MStkzDy1Da2IaPAaCU8c,4279 +pip/_vendor/urllib3/util/queue.py,sha256=myTX3JDHntglKQNBf3b6dasHH-uF-W59vzGSQiFdAfI,497 +pip/_vendor/urllib3/util/request.py,sha256=H5_lrHvtwl2U2BbT1UYN9HpruNc1gsNFlz2njQmhPrQ,3705 +pip/_vendor/urllib3/util/response.py,sha256=SSNL888W-MQ8t3HAi44kNGgF682p6H__ytEXzBYxV_M,2343 +pip/_vendor/urllib3/util/retry.py,sha256=tlxiEq8OU2BSenPpPjYYO1URne8A-qTEgaykam6rZPg,15104 +pip/_vendor/urllib3/util/ssl_.py,sha256=iHJopgSv8_vXfmGg3lOsTS3ldMD9zhe130huHZxQEGU,14022 +pip/_vendor/urllib3/util/timeout.py,sha256=7lHNrgL5YH2cI1j-yZnzV_J8jBlRVdmFhQaNyM1_2b8,9757 +pip/_vendor/urllib3/util/url.py,sha256=qCY_HHUXvo05wAsEERALgExtlgxLnAHSQ7ce1b-g3SM,6487 +pip/_vendor/urllib3/util/wait.py,sha256=_4vvsT1BTTpqxQYK-2kXVfGsUsVRiuc4R4F-0Bf5BPc,5468 +pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579 +pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 +pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 +pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563 +pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307 +pip-18.1.dist-info/LICENSE.txt,sha256=ORqHhOMZ2uVDFHfUzJvFBPxdcf2eieHIDxzThV9dfPo,1090 +pip-18.1.dist-info/METADATA,sha256=D7pqBJTuqM9w_HTW91a0XGjLT9vynlBAE4pPCt_W_UE,2588 +pip-18.1.dist-info/WHEEL,sha256=8T8fxefr_r-A79qbOJ9d_AaEgkpCGmEPHc-gpCq5BRg,110 +pip-18.1.dist-info/entry_points.txt,sha256=S_zfxY25QtQDVY1BiLAmOKSkkI5llzCKPLiYOSEupsY,98 +pip-18.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip-18.1.dist-info/RECORD,, +../../../bin/pip,sha256=6BNUMhhJuuF3raGNcHxN2aqCeK_lJvP65GFMJRwch3o,258 +../../../bin/pip3,sha256=6BNUMhhJuuF3raGNcHxN2aqCeK_lJvP65GFMJRwch3o,258 +../../../bin/pip3.7,sha256=6BNUMhhJuuF3raGNcHxN2aqCeK_lJvP65GFMJRwch3o,258 +pip-18.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/_internal/utils/__pycache__/appdirs.cpython-37.pyc,, +pip/_internal/utils/__pycache__/logging.cpython-37.pyc,, +pip/_internal/utils/__pycache__/deprecation.cpython-37.pyc,, +pip/_internal/utils/__pycache__/filesystem.cpython-37.pyc,, +pip/_internal/utils/__pycache__/glibc.cpython-37.pyc,, +pip/_internal/utils/__pycache__/outdated.cpython-37.pyc,, +pip/_internal/utils/__pycache__/models.cpython-37.pyc,, +pip/_internal/utils/__pycache__/compat.cpython-37.pyc,, +pip/_internal/utils/__pycache__/hashes.cpython-37.pyc,, +pip/_internal/utils/__pycache__/encoding.cpython-37.pyc,, +pip/_internal/utils/__pycache__/typing.cpython-37.pyc,, +pip/_internal/utils/__pycache__/packaging.cpython-37.pyc,, +pip/_internal/utils/__pycache__/temp_dir.cpython-37.pyc,, +pip/_internal/utils/__pycache__/ui.cpython-37.pyc,, +pip/_internal/utils/__pycache__/setuptools_build.cpython-37.pyc,, +pip/_internal/utils/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/utils/__pycache__/misc.cpython-37.pyc,, +pip/_internal/models/__pycache__/index.cpython-37.pyc,, +pip/_internal/models/__pycache__/candidate.cpython-37.pyc,, +pip/_internal/models/__pycache__/format_control.cpython-37.pyc,, +pip/_internal/models/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/models/__pycache__/link.cpython-37.pyc,, +pip/_internal/__pycache__/build_env.cpython-37.pyc,, +pip/_internal/__pycache__/wheel.cpython-37.pyc,, +pip/_internal/__pycache__/exceptions.cpython-37.pyc,, +pip/_internal/__pycache__/index.cpython-37.pyc,, +pip/_internal/__pycache__/resolve.cpython-37.pyc,, +pip/_internal/__pycache__/download.cpython-37.pyc,, +pip/_internal/__pycache__/locations.cpython-37.pyc,, +pip/_internal/__pycache__/pep425tags.cpython-37.pyc,, +pip/_internal/__pycache__/cache.cpython-37.pyc,, +pip/_internal/__pycache__/configuration.cpython-37.pyc,, +pip/_internal/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/__pycache__/pyproject.cpython-37.pyc,, +pip/_internal/cli/__pycache__/parser.cpython-37.pyc,, +pip/_internal/cli/__pycache__/status_codes.cpython-37.pyc,, +pip/_internal/cli/__pycache__/base_command.cpython-37.pyc,, +pip/_internal/cli/__pycache__/autocompletion.cpython-37.pyc,, +pip/_internal/cli/__pycache__/main_parser.cpython-37.pyc,, +pip/_internal/cli/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/cli/__pycache__/cmdoptions.cpython-37.pyc,, +pip/_internal/operations/__pycache__/prepare.cpython-37.pyc,, +pip/_internal/operations/__pycache__/check.cpython-37.pyc,, +pip/_internal/operations/__pycache__/freeze.cpython-37.pyc,, +pip/_internal/operations/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_tracker.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_set.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_uninstall.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_install.cpython-37.pyc,, +pip/_internal/req/__pycache__/req_file.cpython-37.pyc,, +pip/_internal/req/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/req/__pycache__/constructors.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/subversion.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/git.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/bazaar.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/mercurial.cpython-37.pyc,, +pip/_internal/vcs/__pycache__/__init__.cpython-37.pyc,, +pip/_internal/commands/__pycache__/show.cpython-37.pyc,, +pip/_internal/commands/__pycache__/help.cpython-37.pyc,, +pip/_internal/commands/__pycache__/wheel.cpython-37.pyc,, +pip/_internal/commands/__pycache__/completion.cpython-37.pyc,, +pip/_internal/commands/__pycache__/download.cpython-37.pyc,, +pip/_internal/commands/__pycache__/check.cpython-37.pyc,, +pip/_internal/commands/__pycache__/list.cpython-37.pyc,, +pip/_internal/commands/__pycache__/hash.cpython-37.pyc,, +pip/_internal/commands/__pycache__/search.cpython-37.pyc,, +pip/_internal/commands/__pycache__/install.cpython-37.pyc,, +pip/_internal/commands/__pycache__/configuration.cpython-37.pyc,, +pip/_internal/commands/__pycache__/freeze.cpython-37.pyc,, +pip/_internal/commands/__pycache__/uninstall.cpython-37.pyc,, +pip/_internal/commands/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/_structures.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/version.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/requirements.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/markers.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/_compat.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/specifiers.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/utils.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/__about__.cpython-37.pyc,, +pip/_vendor/packaging/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/parser.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/writer.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/core.cpython-37.pyc,, +pip/_vendor/pytoml/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/_version.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/exceptions.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/fallback.cpython-37.pyc,, +pip/_vendor/msgpack/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/eucjpprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/sjisprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/gb2312prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euctwfreq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/cp949prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/version.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euckrfreq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euckrprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/escsm.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/chardistribution.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/euctwprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/big5freq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/escprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/universaldetector.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/latin1prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/hebrewprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/utf8prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langthaimodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/enums.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/gb2312freq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/big5prober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/mbcssm.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/jpcntx.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langcyrillicmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/jisfreq.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/charsetprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-37.pyc,, +pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-37.pyc,, +pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-37.pyc,, +pip/_vendor/chardet/cli/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/labels.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/tests.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/mklabels.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/bar.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/spinner.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/counter.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/helpers.cpython-37.pyc,, +pip/_vendor/progress/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/_in_process.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/envbuild.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/check.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/wrappers.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pep517/__pycache__/colorlog.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-37.pyc,, +pip/_vendor/distlib/_backport/__pycache__/misc.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/util.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/manifest.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/database.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/version.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/locators.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/wheel.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/scripts.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/index.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/markers.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/resources.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/metadata.cpython-37.pyc,, +pip/_vendor/distlib/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/win32.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/initialise.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/ansi.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/winterm.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/ansitowin32.cpython-37.pyc,, +pip/_vendor/colorama/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/pidlockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/linklockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/symlinklockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/sqlitelockfile.cpython-37.pyc,, +pip/_vendor/lockfile/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/controller.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/serialize.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/cache.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/adapter.cpython-37.pyc,, +pip/_vendor/cachecontrol/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-37.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-37.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/codec.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/idnadata.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/intranges.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/package_data.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/core.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/uts46data.cpython-37.pyc,, +pip/_vendor/idna/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/__pycache__/appdirs.cpython-37.pyc,, +pip/_vendor/__pycache__/ipaddress.cpython-37.pyc,, +pip/_vendor/__pycache__/six.cpython-37.pyc,, +pip/_vendor/__pycache__/retrying.cpython-37.pyc,, +pip/_vendor/__pycache__/distro.cpython-37.pyc,, +pip/_vendor/__pycache__/pyparsing.cpython-37.pyc,, +pip/_vendor/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/_internal_utils.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/help.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/structures.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/certs.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/exceptions.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/__version__.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/status_codes.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/sessions.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/models.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/compat.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/adapters.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/packages.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/auth.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/hooks.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/utils.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/cookies.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/api.cpython-37.pyc,, +pip/_vendor/requests/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/lint.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/base.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-37.pyc,, +pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-37.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/constants.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/serializer.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/html5parser.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_utils.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_inputstream.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-37.pyc,, +pip/_vendor/html5lib/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/py.cpython-37.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-37.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-37.pyc,, +pip/_vendor/certifi/__pycache__/__main__.cpython-37.pyc,, +pip/_vendor/certifi/__pycache__/core.cpython-37.pyc,, +pip/_vendor/certifi/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/response.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/timeout.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/url.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/request.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/connection.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/wait.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/retry.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/util/__pycache__/queue.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/response.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/poolmanager.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/exceptions.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/request.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/filepost.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/connectionpool.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/connection.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/_collections.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/fields.cpython-37.pyc,, +pip/_vendor/urllib3/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-37.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/packages/__pycache__/six.cpython-37.pyc,, +pip/_vendor/urllib3/packages/__pycache__/ordered_dict.cpython-37.pyc,, +pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-37.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/_implementation.cpython-37.pyc,, +pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-37.pyc,, +pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-37.pyc,, +pip/_vendor/pkg_resources/__pycache__/__init__.cpython-37.pyc,, +pip/__pycache__/__main__.cpython-37.pyc,, +pip/__pycache__/__init__.cpython-37.pyc,, diff --git a/venv/lib/python3.7/site-packages/pip-18.1.dist-info/WHEEL b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/WHEEL new file mode 100644 index 0000000..1001235 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.32.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/lib/python3.7/site-packages/pip-18.1.dist-info/entry_points.txt b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/entry_points.txt new file mode 100644 index 0000000..f5809cb --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +pip = pip._internal:main +pip3 = pip._internal:main +pip3.7 = pip._internal:main + diff --git a/venv/lib/python3.7/site-packages/pip-18.1.dist-info/top_level.txt b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip-18.1.dist-info/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/venv/lib/python3.7/site-packages/pip/__init__.py b/venv/lib/python3.7/site-packages/pip/__init__.py new file mode 100644 index 0000000..ae265fa --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/__init__.py @@ -0,0 +1 @@ +__version__ = "18.1" diff --git a/venv/lib/python3.7/site-packages/pip/__main__.py b/venv/lib/python3.7/site-packages/pip/__main__.py new file mode 100644 index 0000000..0c223f8 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/__main__.py @@ -0,0 +1,19 @@ +from __future__ import absolute_import + +import os +import sys + +# If we are running from a wheel, add the wheel to sys.path +# This allows the usage python pip-*.whl/pip install pip-*.whl +if __package__ == '': + # __file__ is pip-*.whl/pip/__main__.py + # first dirname call strips of '/__main__.py', second strips off '/pip' + # Resulting path is the name of the wheel itself + # Add that to sys.path so we can import pip + path = os.path.dirname(os.path.dirname(__file__)) + sys.path.insert(0, path) + +from pip._internal import main as _main # isort:skip # noqa + +if __name__ == '__main__': + sys.exit(_main()) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/__init__.py new file mode 100644 index 0000000..276124d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/__init__.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +from __future__ import absolute_import + +import locale +import logging +import os +import warnings + +import sys + +# 2016-06-17 barry@debian.org: urllib3 1.14 added optional support for socks, +# but if invoked (i.e. imported), it will issue a warning to stderr if socks +# isn't available. requests unconditionally imports urllib3's socks contrib +# module, triggering this warning. The warning breaks DEP-8 tests (because of +# the stderr output) and is just plain annoying in normal usage. I don't want +# to add socks as yet another dependency for pip, nor do I want to allow-stder +# in the DEP-8 tests, so just suppress the warning. pdb tells me this has to +# be done before the import of pip.vcs. +from pip._vendor.urllib3.exceptions import DependencyWarning +warnings.filterwarnings("ignore", category=DependencyWarning) # noqa + +# We want to inject the use of SecureTransport as early as possible so that any +# references or sessions or what have you are ensured to have it, however we +# only want to do this in the case that we're running on macOS and the linked +# OpenSSL is too old to handle TLSv1.2 +try: + import ssl +except ImportError: + pass +else: + # Checks for OpenSSL 1.0.1 on MacOS + if sys.platform == "darwin" and ssl.OPENSSL_VERSION_NUMBER < 0x1000100f: + try: + from pip._vendor.urllib3.contrib import securetransport + except (ImportError, OSError): + pass + else: + securetransport.inject_into_urllib3() + +from pip._internal.cli.autocompletion import autocomplete +from pip._internal.cli.main_parser import parse_command +from pip._internal.commands import commands_dict +from pip._internal.exceptions import PipError +from pip._internal.utils import deprecation +from pip._internal.vcs import git, mercurial, subversion, bazaar # noqa +from pip._vendor.urllib3.exceptions import InsecureRequestWarning + +logger = logging.getLogger(__name__) + +# Hide the InsecureRequestWarning from urllib3 +warnings.filterwarnings("ignore", category=InsecureRequestWarning) + + +def main(args=None): + if args is None: + args = sys.argv[1:] + + # Configure our deprecation warnings to be sent through loggers + deprecation.install_warning_logger() + + autocomplete() + + try: + cmd_name, cmd_args = parse_command(args) + except PipError as exc: + sys.stderr.write("ERROR: %s" % exc) + sys.stderr.write(os.linesep) + sys.exit(1) + + # Needed for locale.getpreferredencoding(False) to work + # in pip._internal.utils.encoding.auto_decode + try: + locale.setlocale(locale.LC_ALL, '') + except locale.Error as e: + # setlocale can apparently crash if locale are uninitialized + logger.debug("Ignoring error %s when setting locale", e) + command = commands_dict[cmd_name](isolated=("--isolated" in cmd_args)) + return command.main(cmd_args) diff --git a/venv/lib/python3.7/site-packages/pip/_internal/build_env.py b/venv/lib/python3.7/site-packages/pip/_internal/build_env.py new file mode 100644 index 0000000..673409d --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/build_env.py @@ -0,0 +1,142 @@ +"""Build Environment used for isolation during sdist building +""" + +import logging +import os +import sys +from distutils.sysconfig import get_python_lib +from sysconfig import get_paths + +from pip._vendor.pkg_resources import Requirement, VersionConflict, WorkingSet + +from pip._internal.utils.misc import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.ui import open_spinner + +logger = logging.getLogger(__name__) + + +class BuildEnvironment(object): + """Creates and manages an isolated environment to install build deps + """ + + def __init__(self): + self._temp_dir = TempDirectory(kind="build-env") + self._temp_dir.create() + + @property + def path(self): + return self._temp_dir.path + + def __enter__(self): + self.save_path = os.environ.get('PATH', None) + self.save_pythonpath = os.environ.get('PYTHONPATH', None) + self.save_nousersite = os.environ.get('PYTHONNOUSERSITE', None) + + install_scheme = 'nt' if (os.name == 'nt') else 'posix_prefix' + install_dirs = get_paths(install_scheme, vars={ + 'base': self.path, + 'platbase': self.path, + }) + + scripts = install_dirs['scripts'] + if self.save_path: + os.environ['PATH'] = scripts + os.pathsep + self.save_path + else: + os.environ['PATH'] = scripts + os.pathsep + os.defpath + + # Note: prefer distutils' sysconfig to get the + # library paths so PyPy is correctly supported. + purelib = get_python_lib(plat_specific=0, prefix=self.path) + platlib = get_python_lib(plat_specific=1, prefix=self.path) + if purelib == platlib: + lib_dirs = purelib + else: + lib_dirs = purelib + os.pathsep + platlib + if self.save_pythonpath: + os.environ['PYTHONPATH'] = lib_dirs + os.pathsep + \ + self.save_pythonpath + else: + os.environ['PYTHONPATH'] = lib_dirs + + os.environ['PYTHONNOUSERSITE'] = '1' + + return self.path + + def __exit__(self, exc_type, exc_val, exc_tb): + def restore_var(varname, old_value): + if old_value is None: + os.environ.pop(varname, None) + else: + os.environ[varname] = old_value + + restore_var('PATH', self.save_path) + restore_var('PYTHONPATH', self.save_pythonpath) + restore_var('PYTHONNOUSERSITE', self.save_nousersite) + + def cleanup(self): + self._temp_dir.cleanup() + + def missing_requirements(self, reqs): + """Return a list of the requirements from reqs that are not present + """ + missing = [] + with self: + ws = WorkingSet(os.environ["PYTHONPATH"].split(os.pathsep)) + for req in reqs: + try: + if ws.find(Requirement.parse(req)) is None: + missing.append(req) + except VersionConflict: + missing.append(req) + return missing + + def install_requirements(self, finder, requirements, message): + args = [ + sys.executable, '-m', 'pip', 'install', '--ignore-installed', + '--no-user', '--prefix', self.path, '--no-warn-script-location', + ] + if logger.getEffectiveLevel() <= logging.DEBUG: + args.append('-v') + for format_control in ('no_binary', 'only_binary'): + formats = getattr(finder.format_control, format_control) + args.extend(('--' + format_control.replace('_', '-'), + ','.join(sorted(formats or {':none:'})))) + if finder.index_urls: + args.extend(['-i', finder.index_urls[0]]) + for extra_index in finder.index_urls[1:]: + args.extend(['--extra-index-url', extra_index]) + else: + args.append('--no-index') + for link in finder.find_links: + args.extend(['--find-links', link]) + for _, host, _ in finder.secure_origins: + args.extend(['--trusted-host', host]) + if finder.allow_all_prereleases: + args.append('--pre') + if finder.process_dependency_links: + args.append('--process-dependency-links') + args.append('--') + args.extend(requirements) + with open_spinner(message) as spinner: + call_subprocess(args, show_stdout=False, spinner=spinner) + + +class NoOpBuildEnvironment(BuildEnvironment): + """A no-op drop-in replacement for BuildEnvironment + """ + + def __init__(self): + pass + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_val, exc_tb): + pass + + def cleanup(self): + pass + + def install_requirements(self, finder, requirements, message): + raise NotImplementedError() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cache.py b/venv/lib/python3.7/site-packages/pip/_internal/cache.py new file mode 100644 index 0000000..33bec97 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cache.py @@ -0,0 +1,202 @@ +"""Cache Management +""" + +import errno +import hashlib +import logging +import os + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.download import path_to_url +from pip._internal.models.link import Link +from pip._internal.utils.compat import expanduser +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel import InvalidWheelFilename, Wheel + +logger = logging.getLogger(__name__) + + +class Cache(object): + """An abstract class - provides cache directories for data from links + + + :param cache_dir: The root of the cache. + :param format_control: An object of FormatControl class to limit + binaries being read from the cache. + :param allowed_formats: which formats of files the cache should store. + ('binary' and 'source' are the only allowed values) + """ + + def __init__(self, cache_dir, format_control, allowed_formats): + super(Cache, self).__init__() + self.cache_dir = expanduser(cache_dir) if cache_dir else None + self.format_control = format_control + self.allowed_formats = allowed_formats + + _valid_formats = {"source", "binary"} + assert self.allowed_formats.union(_valid_formats) == _valid_formats + + def _get_cache_path_parts(self, link): + """Get parts of part that must be os.path.joined with cache_dir + """ + + # We want to generate an url to use as our cache key, we don't want to + # just re-use the URL because it might have other items in the fragment + # and we don't care about those. + key_parts = [link.url_without_fragment] + if link.hash_name is not None and link.hash is not None: + key_parts.append("=".join([link.hash_name, link.hash])) + key_url = "#".join(key_parts) + + # Encode our key url with sha224, we'll use this because it has similar + # security properties to sha256, but with a shorter total output (and + # thus less secure). However the differences don't make a lot of + # difference for our use case here. + hashed = hashlib.sha224(key_url.encode()).hexdigest() + + # We want to nest the directories some to prevent having a ton of top + # level directories where we might run out of sub directories on some + # FS. + parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] + + return parts + + def _get_candidates(self, link, package_name): + can_not_cache = ( + not self.cache_dir or + not package_name or + not link + ) + if can_not_cache: + return [] + + canonical_name = canonicalize_name(package_name) + formats = self.format_control.get_allowed_formats( + canonical_name + ) + if not self.allowed_formats.intersection(formats): + return [] + + root = self.get_path_for_link(link) + try: + return os.listdir(root) + except OSError as err: + if err.errno in {errno.ENOENT, errno.ENOTDIR}: + return [] + raise + + def get_path_for_link(self, link): + """Return a directory to store cached items in for link. + """ + raise NotImplementedError() + + def get(self, link, package_name): + """Returns a link to a cached item if it exists, otherwise returns the + passed link. + """ + raise NotImplementedError() + + def _link_for_candidate(self, link, candidate): + root = self.get_path_for_link(link) + path = os.path.join(root, candidate) + + return Link(path_to_url(path)) + + def cleanup(self): + pass + + +class SimpleWheelCache(Cache): + """A cache of wheels for future installs. + """ + + def __init__(self, cache_dir, format_control): + super(SimpleWheelCache, self).__init__( + cache_dir, format_control, {"binary"} + ) + + def get_path_for_link(self, link): + """Return a directory to store cached wheels for link + + Because there are M wheels for any one sdist, we provide a directory + to cache them in, and then consult that directory when looking up + cache hits. + + We only insert things into the cache if they have plausible version + numbers, so that we don't contaminate the cache with things that were + not unique. E.g. ./package might have dozens of installs done for it + and build a version of 0.0...and if we built and cached a wheel, we'd + end up using the same wheel even if the source has been edited. + + :param link: The link of the sdist for which this will cache wheels. + """ + parts = self._get_cache_path_parts(link) + + # Store wheels within the root cache_dir + return os.path.join(self.cache_dir, "wheels", *parts) + + def get(self, link, package_name): + candidates = [] + + for wheel_name in self._get_candidates(link, package_name): + try: + wheel = Wheel(wheel_name) + except InvalidWheelFilename: + continue + if not wheel.supported(): + # Built for a different python/arch/etc + continue + candidates.append((wheel.support_index_min(), wheel_name)) + + if not candidates: + return link + + return self._link_for_candidate(link, min(candidates)[1]) + + +class EphemWheelCache(SimpleWheelCache): + """A SimpleWheelCache that creates it's own temporary cache directory + """ + + def __init__(self, format_control): + self._temp_dir = TempDirectory(kind="ephem-wheel-cache") + self._temp_dir.create() + + super(EphemWheelCache, self).__init__( + self._temp_dir.path, format_control + ) + + def cleanup(self): + self._temp_dir.cleanup() + + +class WheelCache(Cache): + """Wraps EphemWheelCache and SimpleWheelCache into a single Cache + + This Cache allows for gracefully degradation, using the ephem wheel cache + when a certain link is not found in the simple wheel cache first. + """ + + def __init__(self, cache_dir, format_control): + super(WheelCache, self).__init__( + cache_dir, format_control, {'binary'} + ) + self._wheel_cache = SimpleWheelCache(cache_dir, format_control) + self._ephem_cache = EphemWheelCache(format_control) + + def get_path_for_link(self, link): + return self._wheel_cache.get_path_for_link(link) + + def get_ephem_path_for_link(self, link): + return self._ephem_cache.get_path_for_link(link) + + def get(self, link, package_name): + retval = self._wheel_cache.get(link, package_name) + if retval is link: + retval = self._ephem_cache.get(link, package_name) + return retval + + def cleanup(self): + self._wheel_cache.cleanup() + self._ephem_cache.cleanup() diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/__init__.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/__init__.py new file mode 100644 index 0000000..e589bb9 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/__init__.py @@ -0,0 +1,4 @@ +"""Subpackage containing all of pip's command line interface related code +""" + +# This file intentionally does not import submodules diff --git a/venv/lib/python3.7/site-packages/pip/_internal/cli/autocompletion.py b/venv/lib/python3.7/site-packages/pip/_internal/cli/autocompletion.py new file mode 100644 index 0000000..0a04199 --- /dev/null +++ b/venv/lib/python3.7/site-packages/pip/_internal/cli/autocompletion.py @@ -0,0 +1,152 @@ +"""Logic that powers autocompletion installed by ``pip completion``. +""" + +import optparse +import os +import sys + +from pip._internal.cli.main_parser import create_main_parser +from pip._internal.commands import commands_dict, get_summaries +from pip._internal.utils.misc import get_installed_distributions + + +def autocomplete(): + """Entry Point for completion of main and subcommand options. + """ + # Don't complete if user hasn't sourced bash_completion file. + if 'PIP_AUTO_COMPLETE' not in os.environ: + return + cwords = os.environ['COMP_WORDS'].split()[1:] + cword = int(os.environ['COMP_CWORD']) + try: + current = cwords[cword - 1] + except IndexError: + current = '' + + subcommands = [cmd for cmd, summary in get_summaries()] + options = [] + # subcommand + try: + subcommand_name = [w for w in cwords if w in subcommands][0] + except IndexError: + subcommand_name = None + + parser = create_main_parser() + # subcommand options + if subcommand_name: + # special case: 'help' subcommand has no options + if subcommand_name == 'help': + sys.exit(1) + # special case: list locally installed dists for show and uninstall + should_list_installed = ( + subcommand_name in ['show', 'uninstall'] and + not current.startswith('-') + ) + if should_list_installed: + installed = [] + lc = current.lower() + for dist in get_installed_distributions(local_only=True): + if dist.key.startswith(lc) and dist.key not in cwords[1:]: + installed.append(dist.key) + # if there are no dists installed, fall back to option completion + if installed: + for dist in installed: + print(dist) + sys.exit(1) + + subcommand = commands_dict[subcommand_name]() + + for opt in subcommand.parser.option_list_all: + if opt.help != optparse.SUPPRESS_HELP: + for opt_str in opt._long_opts + opt._short_opts: + options.append((opt_str, opt.nargs)) + + # filter out previously specified options from available options + prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]] + options = [(x, v) for (x, v) in options if x not in prev_opts] + # filter options by current input + options = [(k, v) for k, v in options if k.startswith(current)] + # get completion type given cwords and available subcommand options + completion_type = get_path_completion_type( + cwords, cword, subcommand.parser.option_list_all, + ) + # get completion files and directories if ``completion_type`` is + # ````, ``